137469Ssklower /*********************************************************** Copyright IBM Corporation 1987 236373Ssklower 336373Ssklower All Rights Reserved 436373Ssklower 536373Ssklower Permission to use, copy, modify, and distribute this software and its 636373Ssklower documentation for any purpose and without fee is hereby granted, 736373Ssklower provided that the above copyright notice appear in all copies and that 836373Ssklower both that copyright notice and this permission notice appear in 936373Ssklower supporting documentation, and that the name of IBM not be 1036373Ssklower used in advertising or publicity pertaining to distribution of the 1136373Ssklower software without specific, written prior permission. 1236373Ssklower 1336373Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 1436373Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 1536373Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 1636373Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 1736373Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 1836373Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 1936373Ssklower SOFTWARE. 2036373Ssklower 2136373Ssklower ******************************************************************/ 2236373Ssklower 2336373Ssklower /* 2436373Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 2536373Ssklower */ 2636373Ssklower /* $Header: clnp_raw.c,v 4.2 88/06/29 14:58:56 hagens Exp $ */ 2736373Ssklower /* $Source: /usr/argo/sys/netiso/RCS/clnp_raw.c,v $ */ 28*38841Ssklower /* @(#)clnp_raw.c 7.4 (Berkeley) 08/29/89 */ 2936373Ssklower #ifndef lint 3036373Ssklower static char *rcsid = "$Header: clnp_raw.c,v 4.2 88/06/29 14:58:56 hagens Exp $"; 3136373Ssklower #endif lint 3236373Ssklower 3336373Ssklower #ifdef ISO 3436373Ssklower 3537536Smckusick #include "types.h" 3637536Smckusick #include "param.h" 3737536Smckusick #include "mbuf.h" 3837536Smckusick #include "domain.h" 3937536Smckusick #include "protosw.h" 4037536Smckusick #include "socket.h" 4137536Smckusick #include "socketvar.h" 4237536Smckusick #include "errno.h" 4337536Smckusick #include "time.h" 4436373Ssklower 4536373Ssklower #include "../net/if.h" 4636373Ssklower #include "../net/route.h" 4736373Ssklower #include "../net/raw_cb.h" 4836373Ssklower 4937469Ssklower #include "iso.h" 5037469Ssklower #include "iso_pcb.h" 5137469Ssklower #include "clnp.h" 5237469Ssklower #include "clnp_stat.h" 5337469Ssklower #include "argo_debug.h" 5436373Ssklower 5537469Ssklower #include "tp_user.h"/* XXX -- defines SOL_NETWORK */ 5637469Ssklower 5737469Ssklower struct sockaddr_iso rclnp_src = { sizeof(rclnp_src), AF_ISO }; 5837469Ssklower struct sockaddr_iso rclnp_dst = { sizeof(rclnp_src), AF_ISO }; 5936373Ssklower struct sockproto rclnp_proto = { PF_ISO, 0 }; 6036373Ssklower /* 6136373Ssklower * FUNCTION: rclnp_input 6236373Ssklower * 6336373Ssklower * PURPOSE: Setup generic address an protocol structures for 6436373Ssklower * raw input routine, then pass them along with the 6536373Ssklower * mbuf chain. 6636373Ssklower * 6736373Ssklower * RETURNS: none 6836373Ssklower * 6936373Ssklower * SIDE EFFECTS: 7036373Ssklower * 7136373Ssklower * NOTES: The protocol field of rclnp_proto is set to zero indicating 7236373Ssklower * no protocol. 7336373Ssklower */ 7436373Ssklower rclnp_input(m, src, dst, hdrlen) 7536373Ssklower struct mbuf *m; /* ptr to packet */ 7636373Ssklower struct iso_addr *src; /* ptr to src address */ 7736373Ssklower struct iso_addr *dst; /* ptr to dest address */ 7836373Ssklower int hdrlen; /* length (in bytes) of clnp header */ 7936373Ssklower { 8036373Ssklower #ifdef TROLL 8136373Ssklower if (trollctl.tr_ops & TR_CHUCK) { 8236373Ssklower m_freem(m); 8336373Ssklower return; 8436373Ssklower } 8536373Ssklower #endif TROLL 8636373Ssklower 8736373Ssklower rclnp_src.siso_addr = *src; 8836373Ssklower rclnp_dst.siso_addr = *dst; 8936373Ssklower raw_input(m, &rclnp_proto, (struct sockaddr *)&rclnp_src, 9036373Ssklower (struct sockaddr *)&rclnp_dst); 9136373Ssklower } 9236373Ssklower 9336373Ssklower /* 9436373Ssklower * FUNCTION: rclnp_output 9536373Ssklower * 9636373Ssklower * PURPOSE: Prepare to send a raw clnp packet. Setup src and dest 9736373Ssklower * addresses, count the number of bytes to send, and 9836373Ssklower * call clnp_output. 9936373Ssklower * 10036373Ssklower * RETURNS: success - 0 10136373Ssklower * failure - an appropriate error code 10236373Ssklower * 10336373Ssklower * SIDE EFFECTS: 10436373Ssklower * 10536373Ssklower * NOTES: 10636373Ssklower */ 10736373Ssklower rclnp_output(m0, so) 10836373Ssklower struct mbuf *m0; /* packet to send */ 10936373Ssklower struct socket *so; /* socket to send from */ 11036373Ssklower { 11136373Ssklower register struct mbuf *m; /* used to scan a chain */ 11236373Ssklower int len = 0; /* store length of chain here */ 11337469Ssklower struct rawisopcb *rp = sotorawisopcb(so); /* ptr to raw cb */ 11436373Ssklower int error; /* return value of function */ 11537469Ssklower int flags; /* flags for clnp_output */ 11636373Ssklower 117*38841Ssklower if (0 == m0->m_flags & M_PKTHDR) 118*38841Ssklower return (EINVAL); 11936373Ssklower /* 12036373Ssklower * Set up src address. If user has bound socket to an address, use it. 12136373Ssklower * Otherwise, do not specify src (clnp_output will fill it in). 12236373Ssklower */ 12337469Ssklower if (rp->risop_rcb.rcb_laddr) { 12437469Ssklower if (rp->risop_isop.isop_sladdr.siso_family != AF_ISO) { 12537469Ssklower bad: 12636373Ssklower m_freem(m0); 12736373Ssklower return(EAFNOSUPPORT); 12836373Ssklower } 12936373Ssklower } 13036373Ssklower /* set up dest address */ 13137469Ssklower if (rp->risop_rcb.rcb_faddr == 0) 13237469Ssklower goto bad; 13337469Ssklower rp->risop_isop.isop_sfaddr = 13437469Ssklower *(struct sockaddr_iso *)rp->risop_rcb.rcb_faddr; 13537469Ssklower rp->risop_isop.isop_faddr = &rp->risop_isop.isop_sfaddr; 13636373Ssklower 13736373Ssklower /* get flags and ship it off */ 13837469Ssklower flags = rp->risop_flags & CLNP_VFLAGS; 13936373Ssklower 140*38841Ssklower error = clnp_output(m0, &rp->risop_isop, m0->m_pkthdr.len, 141*38841Ssklower flags|CLNP_NOCACHE); 14236373Ssklower 14336373Ssklower return (error); 14436373Ssklower } 14536373Ssklower 14636373Ssklower /* 14736373Ssklower * FUNCTION: rclnp_ctloutput 14836373Ssklower * 14936373Ssklower * PURPOSE: Raw clnp socket option processing 15036373Ssklower * All options are stored inside an mbuf. 15136373Ssklower * 15236373Ssklower * RETURNS: success - 0 15336373Ssklower * failure - unix error code 15436373Ssklower * 15536373Ssklower * SIDE EFFECTS: If the options mbuf does not exist, it the mbuf passed 15636373Ssklower * is used. 15736373Ssklower * 15836373Ssklower * NOTES: 15936373Ssklower */ 16036373Ssklower rclnp_ctloutput(op, so, level, optname, m) 16136373Ssklower int op; /* type of operation */ 16236373Ssklower struct socket *so; /* ptr to socket */ 16336373Ssklower int level; /* level of option */ 16436373Ssklower int optname; /* name of option */ 16536373Ssklower struct mbuf **m; /* ptr to ptr to option data */ 16636373Ssklower { 16736373Ssklower int error = 0; 16837469Ssklower register struct rawisopcb *rp = sotorawisopcb(so);/* raw cb ptr */ 16936373Ssklower 17036373Ssklower IFDEBUG(D_CTLOUTPUT) 17136373Ssklower printf("rclnp_ctloutput: op = x%x, level = x%x, name = x%x\n", 17236373Ssklower op, level, optname); 17336373Ssklower if (*m != NULL) { 17436373Ssklower printf("rclnp_ctloutput: %d bytes of mbuf data\n", (*m)->m_len); 17536373Ssklower dump_buf(mtod((*m), caddr_t), (*m)->m_len); 17636373Ssklower } 17736373Ssklower ENDDEBUG 17836373Ssklower 17936373Ssklower #ifdef SOL_NETWORK 18036373Ssklower if (level != SOL_NETWORK) 18136373Ssklower error = EINVAL; 18236373Ssklower else switch (op) { 18336373Ssklower #else 18436373Ssklower switch (op) { 18536373Ssklower #endif SOL_NETWORK 18636373Ssklower case PRCO_SETOPT: 18736373Ssklower switch (optname) { 18836373Ssklower case CLNPOPT_FLAGS: { 18936373Ssklower u_short usr_flags; 19036373Ssklower /* 19136373Ssklower * Insure that the data passed has exactly one short in it 19236373Ssklower */ 19336373Ssklower if ((*m == NULL) || ((*m)->m_len != sizeof(short))) { 19436373Ssklower error = EINVAL; 19536373Ssklower break; 19636373Ssklower } 19736373Ssklower 19836373Ssklower /* 19936373Ssklower * Don't allow invalid flags to be set 20036373Ssklower */ 20136373Ssklower usr_flags = (*mtod((*m), short *)); 20236373Ssklower 20336373Ssklower if ((usr_flags & (CLNP_VFLAGS)) != usr_flags) { 20436373Ssklower error = EINVAL; 20536373Ssklower } else 20637469Ssklower rp->risop_flags |= usr_flags; 20736373Ssklower 20836373Ssklower } break; 20936373Ssklower 21036373Ssklower case CLNPOPT_OPTS: 21137469Ssklower if (error = clnp_set_opts(&rp->risop_isop.isop_options, m)) 21237469Ssklower break; 21337469Ssklower rp->risop_isop.isop_optindex = m_get(M_WAIT, MT_SOOPTS); 21437469Ssklower (void) clnp_opt_sanity(rp->risop_isop.isop_options, 21537469Ssklower mtod(rp->risop_isop.isop_options, caddr_t), 21637469Ssklower rp->risop_isop.isop_options->m_len, 21737469Ssklower mtod(rp->risop_isop.isop_optindex, 21837469Ssklower struct clnp_optidx *)); 21936373Ssklower break; 22036373Ssklower } 22136373Ssklower break; 22236373Ssklower 22336373Ssklower case PRCO_GETOPT: 22436373Ssklower #ifdef notdef 22536373Ssklower /* commented out to keep hi C quiet */ 22636373Ssklower switch (optname) { 22736373Ssklower default: 22836373Ssklower error = EINVAL; 22936373Ssklower break; 23036373Ssklower } 23136373Ssklower #endif notdef 23236373Ssklower break; 23336373Ssklower default: 23436373Ssklower error = EINVAL; 23536373Ssklower break; 23636373Ssklower } 23736373Ssklower if (op == PRCO_SETOPT) { 23836373Ssklower /* note: m_freem does not barf is *m is NULL */ 23936373Ssklower m_freem(*m); 24036373Ssklower *m = NULL; 24136373Ssklower } 24236373Ssklower 24336373Ssklower return error; 24436373Ssklower } 24536373Ssklower 24636373Ssklower /*ARGSUSED*/ 24737469Ssklower clnp_usrreq(so, req, m, nam, rights, control) 24837469Ssklower register struct socket *so; 24936373Ssklower int req; 25037469Ssklower struct mbuf *m, *nam, *rights, *control; 25136373Ssklower { 25237469Ssklower register int error = 0; 25337469Ssklower register struct rawisopcb *rp = sotorawisopcb(so); 25437469Ssklower 25537469Ssklower rp = sotorawisopcb(so); 25637469Ssklower switch (req) { 25737469Ssklower 25837469Ssklower case PRU_ATTACH: 25937469Ssklower if (rp) 26037469Ssklower panic("rip_attach"); 26137469Ssklower MALLOC(rp, struct rawisopcb *, sizeof *rp, M_PCB, M_WAITOK); 26237469Ssklower if (rp == 0) 26337469Ssklower return (ENOBUFS); 26437469Ssklower bzero((caddr_t)rp, sizeof *rp); 26537469Ssklower so->so_pcb = (caddr_t)rp; 26637469Ssklower break; 26737469Ssklower 26837469Ssklower case PRU_DETACH: 26937469Ssklower if (rp == 0) 27037469Ssklower panic("rip_detach"); 27137469Ssklower if (rp->risop_isop.isop_options) 27237469Ssklower m_freem(rp->risop_isop.isop_options); 27337469Ssklower if (rp->risop_isop.isop_route.ro_rt) 27437469Ssklower RTFREE(rp->risop_isop.isop_route.ro_rt); 27537469Ssklower if (rp->risop_rcb.rcb_laddr) 27637469Ssklower rp->risop_rcb.rcb_laddr = 0; 27737469Ssklower /* free clnp cached hdr if necessary */ 27837469Ssklower if (rp->risop_isop.isop_clnpcache != NULL) { 27937469Ssklower struct clnp_cache *clcp = 28037469Ssklower mtod(rp->risop_isop.isop_clnpcache, struct clnp_cache *); 28137469Ssklower if (clcp->clc_hdr != NULL) { 28237469Ssklower m_free(clcp->clc_hdr); 28337469Ssklower } 28437469Ssklower m_free(rp->risop_isop.isop_clnpcache); 28537469Ssklower } 28637469Ssklower if (rp->risop_isop.isop_optindex != NULL) 28737469Ssklower m_free(rp->risop_isop.isop_optindex); 28837469Ssklower 28937469Ssklower break; 29037469Ssklower 29137469Ssklower case PRU_BIND: 29237469Ssklower { 29337469Ssklower struct sockaddr_iso *addr = mtod(nam, struct sockaddr_iso *); 29437469Ssklower 29537469Ssklower if (nam->m_len != sizeof(*addr)) 29637469Ssklower return (EINVAL); 29737469Ssklower if ((ifnet == 0) || 29837469Ssklower (addr->siso_family != AF_ISO) || 29937469Ssklower (addr->siso_addr.isoa_len && 30037469Ssklower ifa_ifwithaddr((struct sockaddr *)addr) == 0)) 30137469Ssklower return (EADDRNOTAVAIL); 30237469Ssklower rp->risop_isop.isop_sladdr = *addr; 30337469Ssklower rp->risop_rcb.rcb_laddr = (struct sockaddr *) 30437469Ssklower (rp->risop_isop.isop_laddr = &rp->risop_isop.isop_sladdr); 30537469Ssklower return (0); 30637469Ssklower } 30737469Ssklower case PRU_CONNECT: 30837469Ssklower { 30937469Ssklower struct sockaddr_iso *addr = mtod(nam, struct sockaddr_iso *); 31037469Ssklower 31137469Ssklower if ((nam->m_len > sizeof(*addr)) || (addr->siso_len > sizeof(*addr))) 31237469Ssklower return (EINVAL); 31337469Ssklower if (ifnet == 0) 31437469Ssklower return (EADDRNOTAVAIL); 31537469Ssklower if (addr->siso_family != AF_ISO) 31637469Ssklower rp->risop_isop.isop_sfaddr = *addr; 31737469Ssklower rp->risop_rcb.rcb_faddr = (struct sockaddr *) 31837469Ssklower (rp->risop_isop.isop_faddr = &rp->risop_isop.isop_sfaddr); 31937469Ssklower soisconnected(so); 32037469Ssklower return (0); 32137469Ssklower } 32237469Ssklower } 32337469Ssklower error = raw_usrreq(so, req, m, nam, rights, control); 32437469Ssklower 32537469Ssklower if (error && req == PRU_ATTACH && so->so_pcb) 32637469Ssklower free((caddr_t)rp, M_PCB); 32737469Ssklower return (error); 32836373Ssklower } 32936373Ssklower #endif ISO 330