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 $ */ 2836373Ssklower #ifndef lint 2936373Ssklower static char *rcsid = "$Header: clnp_raw.c,v 4.2 88/06/29 14:58:56 hagens Exp $"; 3036373Ssklower #endif lint 3136373Ssklower 3236373Ssklower #ifdef ISO 3336373Ssklower 34*37536Smckusick #include "types.h" 35*37536Smckusick #include "param.h" 36*37536Smckusick #include "mbuf.h" 37*37536Smckusick #include "domain.h" 38*37536Smckusick #include "protosw.h" 39*37536Smckusick #include "socket.h" 40*37536Smckusick #include "socketvar.h" 41*37536Smckusick #include "errno.h" 42*37536Smckusick #include "time.h" 4336373Ssklower 4436373Ssklower #include "../net/if.h" 4536373Ssklower #include "../net/route.h" 4636373Ssklower #include "../net/raw_cb.h" 4736373Ssklower 4837469Ssklower #include "iso.h" 4937469Ssklower #include "iso_pcb.h" 5037469Ssklower #include "clnp.h" 5137469Ssklower #include "clnp_stat.h" 5237469Ssklower #include "argo_debug.h" 5336373Ssklower 5437469Ssklower #include "tp_user.h"/* XXX -- defines SOL_NETWORK */ 5537469Ssklower 5637469Ssklower struct sockaddr_iso rclnp_src = { sizeof(rclnp_src), AF_ISO }; 5737469Ssklower struct sockaddr_iso rclnp_dst = { sizeof(rclnp_src), AF_ISO }; 5836373Ssklower struct sockproto rclnp_proto = { PF_ISO, 0 }; 5936373Ssklower /* 6036373Ssklower * FUNCTION: rclnp_input 6136373Ssklower * 6236373Ssklower * PURPOSE: Setup generic address an protocol structures for 6336373Ssklower * raw input routine, then pass them along with the 6436373Ssklower * mbuf chain. 6536373Ssklower * 6636373Ssklower * RETURNS: none 6736373Ssklower * 6836373Ssklower * SIDE EFFECTS: 6936373Ssklower * 7036373Ssklower * NOTES: The protocol field of rclnp_proto is set to zero indicating 7136373Ssklower * no protocol. 7236373Ssklower */ 7336373Ssklower rclnp_input(m, src, dst, hdrlen) 7436373Ssklower struct mbuf *m; /* ptr to packet */ 7536373Ssklower struct iso_addr *src; /* ptr to src address */ 7636373Ssklower struct iso_addr *dst; /* ptr to dest address */ 7736373Ssklower int hdrlen; /* length (in bytes) of clnp header */ 7836373Ssklower { 7936373Ssklower #ifdef TROLL 8036373Ssklower if (trollctl.tr_ops & TR_CHUCK) { 8136373Ssklower m_freem(m); 8236373Ssklower return; 8336373Ssklower } 8436373Ssklower #endif TROLL 8536373Ssklower 8636373Ssklower rclnp_src.siso_addr = *src; 8736373Ssklower rclnp_dst.siso_addr = *dst; 8836373Ssklower raw_input(m, &rclnp_proto, (struct sockaddr *)&rclnp_src, 8936373Ssklower (struct sockaddr *)&rclnp_dst); 9036373Ssklower } 9136373Ssklower 9236373Ssklower /* 9336373Ssklower * FUNCTION: rclnp_output 9436373Ssklower * 9536373Ssklower * PURPOSE: Prepare to send a raw clnp packet. Setup src and dest 9636373Ssklower * addresses, count the number of bytes to send, and 9736373Ssklower * call clnp_output. 9836373Ssklower * 9936373Ssklower * RETURNS: success - 0 10036373Ssklower * failure - an appropriate error code 10136373Ssklower * 10236373Ssklower * SIDE EFFECTS: 10336373Ssklower * 10436373Ssklower * NOTES: 10536373Ssklower */ 10636373Ssklower rclnp_output(m0, so) 10736373Ssklower struct mbuf *m0; /* packet to send */ 10836373Ssklower struct socket *so; /* socket to send from */ 10936373Ssklower { 11036373Ssklower register struct mbuf *m; /* used to scan a chain */ 11136373Ssklower int len = 0; /* store length of chain here */ 11237469Ssklower struct rawisopcb *rp = sotorawisopcb(so); /* ptr to raw cb */ 11336373Ssklower int error; /* return value of function */ 11437469Ssklower int flags; /* flags for clnp_output */ 11536373Ssklower 11636373Ssklower /* 11736373Ssklower * Set up src address. If user has bound socket to an address, use it. 11836373Ssklower * Otherwise, do not specify src (clnp_output will fill it in). 11936373Ssklower */ 12037469Ssklower if (rp->risop_rcb.rcb_laddr) { 12137469Ssklower if (rp->risop_isop.isop_sladdr.siso_family != AF_ISO) { 12237469Ssklower bad: 12336373Ssklower m_freem(m0); 12436373Ssklower return(EAFNOSUPPORT); 12536373Ssklower } 12636373Ssklower } 12736373Ssklower /* set up dest address */ 12837469Ssklower if (rp->risop_rcb.rcb_faddr == 0) 12937469Ssklower goto bad; 13037469Ssklower rp->risop_isop.isop_sfaddr = 13137469Ssklower *(struct sockaddr_iso *)rp->risop_rcb.rcb_faddr; 13237469Ssklower rp->risop_isop.isop_faddr = &rp->risop_isop.isop_sfaddr; 13336373Ssklower 13436373Ssklower /* get flags and ship it off */ 13537469Ssklower flags = rp->risop_flags & CLNP_VFLAGS; 13636373Ssklower 13737469Ssklower error = clnp_output(m0, &rp->risop_isop, flags|CLNP_NOCACHE); 13836373Ssklower 13936373Ssklower return (error); 14036373Ssklower } 14136373Ssklower 14236373Ssklower /* 14336373Ssklower * FUNCTION: rclnp_ctloutput 14436373Ssklower * 14536373Ssklower * PURPOSE: Raw clnp socket option processing 14636373Ssklower * All options are stored inside an mbuf. 14736373Ssklower * 14836373Ssklower * RETURNS: success - 0 14936373Ssklower * failure - unix error code 15036373Ssklower * 15136373Ssklower * SIDE EFFECTS: If the options mbuf does not exist, it the mbuf passed 15236373Ssklower * is used. 15336373Ssklower * 15436373Ssklower * NOTES: 15536373Ssklower */ 15636373Ssklower rclnp_ctloutput(op, so, level, optname, m) 15736373Ssklower int op; /* type of operation */ 15836373Ssklower struct socket *so; /* ptr to socket */ 15936373Ssklower int level; /* level of option */ 16036373Ssklower int optname; /* name of option */ 16136373Ssklower struct mbuf **m; /* ptr to ptr to option data */ 16236373Ssklower { 16336373Ssklower int error = 0; 16437469Ssklower register struct rawisopcb *rp = sotorawisopcb(so);/* raw cb ptr */ 16536373Ssklower 16636373Ssklower IFDEBUG(D_CTLOUTPUT) 16736373Ssklower printf("rclnp_ctloutput: op = x%x, level = x%x, name = x%x\n", 16836373Ssklower op, level, optname); 16936373Ssklower if (*m != NULL) { 17036373Ssklower printf("rclnp_ctloutput: %d bytes of mbuf data\n", (*m)->m_len); 17136373Ssklower dump_buf(mtod((*m), caddr_t), (*m)->m_len); 17236373Ssklower } 17336373Ssklower ENDDEBUG 17436373Ssklower 17536373Ssklower #ifdef SOL_NETWORK 17636373Ssklower if (level != SOL_NETWORK) 17736373Ssklower error = EINVAL; 17836373Ssklower else switch (op) { 17936373Ssklower #else 18036373Ssklower switch (op) { 18136373Ssklower #endif SOL_NETWORK 18236373Ssklower case PRCO_SETOPT: 18336373Ssklower switch (optname) { 18436373Ssklower case CLNPOPT_FLAGS: { 18536373Ssklower u_short usr_flags; 18636373Ssklower /* 18736373Ssklower * Insure that the data passed has exactly one short in it 18836373Ssklower */ 18936373Ssklower if ((*m == NULL) || ((*m)->m_len != sizeof(short))) { 19036373Ssklower error = EINVAL; 19136373Ssklower break; 19236373Ssklower } 19336373Ssklower 19436373Ssklower /* 19536373Ssklower * Don't allow invalid flags to be set 19636373Ssklower */ 19736373Ssklower usr_flags = (*mtod((*m), short *)); 19836373Ssklower 19936373Ssklower if ((usr_flags & (CLNP_VFLAGS)) != usr_flags) { 20036373Ssklower error = EINVAL; 20136373Ssklower } else 20237469Ssklower rp->risop_flags |= usr_flags; 20336373Ssklower 20436373Ssklower } break; 20536373Ssklower 20636373Ssklower case CLNPOPT_OPTS: 20737469Ssklower if (error = clnp_set_opts(&rp->risop_isop.isop_options, m)) 20837469Ssklower break; 20937469Ssklower rp->risop_isop.isop_optindex = m_get(M_WAIT, MT_SOOPTS); 21037469Ssklower (void) clnp_opt_sanity(rp->risop_isop.isop_options, 21137469Ssklower mtod(rp->risop_isop.isop_options, caddr_t), 21237469Ssklower rp->risop_isop.isop_options->m_len, 21337469Ssklower mtod(rp->risop_isop.isop_optindex, 21437469Ssklower struct clnp_optidx *)); 21536373Ssklower break; 21636373Ssklower } 21736373Ssklower break; 21836373Ssklower 21936373Ssklower case PRCO_GETOPT: 22036373Ssklower #ifdef notdef 22136373Ssklower /* commented out to keep hi C quiet */ 22236373Ssklower switch (optname) { 22336373Ssklower default: 22436373Ssklower error = EINVAL; 22536373Ssklower break; 22636373Ssklower } 22736373Ssklower #endif notdef 22836373Ssklower break; 22936373Ssklower default: 23036373Ssklower error = EINVAL; 23136373Ssklower break; 23236373Ssklower } 23336373Ssklower if (op == PRCO_SETOPT) { 23436373Ssklower /* note: m_freem does not barf is *m is NULL */ 23536373Ssklower m_freem(*m); 23636373Ssklower *m = NULL; 23736373Ssklower } 23836373Ssklower 23936373Ssklower return error; 24036373Ssklower } 24136373Ssklower 24236373Ssklower /*ARGSUSED*/ 24337469Ssklower clnp_usrreq(so, req, m, nam, rights, control) 24437469Ssklower register struct socket *so; 24536373Ssklower int req; 24637469Ssklower struct mbuf *m, *nam, *rights, *control; 24736373Ssklower { 24837469Ssklower register int error = 0; 24937469Ssklower register struct rawisopcb *rp = sotorawisopcb(so); 25037469Ssklower 25137469Ssklower rp = sotorawisopcb(so); 25237469Ssklower switch (req) { 25337469Ssklower 25437469Ssklower case PRU_ATTACH: 25537469Ssklower if (rp) 25637469Ssklower panic("rip_attach"); 25737469Ssklower MALLOC(rp, struct rawisopcb *, sizeof *rp, M_PCB, M_WAITOK); 25837469Ssklower if (rp == 0) 25937469Ssklower return (ENOBUFS); 26037469Ssklower bzero((caddr_t)rp, sizeof *rp); 26137469Ssklower so->so_pcb = (caddr_t)rp; 26237469Ssklower break; 26337469Ssklower 26437469Ssklower case PRU_DETACH: 26537469Ssklower if (rp == 0) 26637469Ssklower panic("rip_detach"); 26737469Ssklower if (rp->risop_isop.isop_options) 26837469Ssklower m_freem(rp->risop_isop.isop_options); 26937469Ssklower if (rp->risop_isop.isop_route.ro_rt) 27037469Ssklower RTFREE(rp->risop_isop.isop_route.ro_rt); 27137469Ssklower if (rp->risop_rcb.rcb_laddr) 27237469Ssklower rp->risop_rcb.rcb_laddr = 0; 27337469Ssklower /* free clnp cached hdr if necessary */ 27437469Ssklower if (rp->risop_isop.isop_clnpcache != NULL) { 27537469Ssklower struct clnp_cache *clcp = 27637469Ssklower mtod(rp->risop_isop.isop_clnpcache, struct clnp_cache *); 27737469Ssklower if (clcp->clc_hdr != NULL) { 27837469Ssklower m_free(clcp->clc_hdr); 27937469Ssklower } 28037469Ssklower m_free(rp->risop_isop.isop_clnpcache); 28137469Ssklower } 28237469Ssklower if (rp->risop_isop.isop_optindex != NULL) 28337469Ssklower m_free(rp->risop_isop.isop_optindex); 28437469Ssklower 28537469Ssklower break; 28637469Ssklower 28737469Ssklower case PRU_BIND: 28837469Ssklower { 28937469Ssklower struct sockaddr_iso *addr = mtod(nam, struct sockaddr_iso *); 29037469Ssklower 29137469Ssklower if (nam->m_len != sizeof(*addr)) 29237469Ssklower return (EINVAL); 29337469Ssklower if ((ifnet == 0) || 29437469Ssklower (addr->siso_family != AF_ISO) || 29537469Ssklower (addr->siso_addr.isoa_len && 29637469Ssklower ifa_ifwithaddr((struct sockaddr *)addr) == 0)) 29737469Ssklower return (EADDRNOTAVAIL); 29837469Ssklower rp->risop_isop.isop_sladdr = *addr; 29937469Ssklower rp->risop_rcb.rcb_laddr = (struct sockaddr *) 30037469Ssklower (rp->risop_isop.isop_laddr = &rp->risop_isop.isop_sladdr); 30137469Ssklower return (0); 30237469Ssklower } 30337469Ssklower case PRU_CONNECT: 30437469Ssklower { 30537469Ssklower struct sockaddr_iso *addr = mtod(nam, struct sockaddr_iso *); 30637469Ssklower 30737469Ssklower if ((nam->m_len > sizeof(*addr)) || (addr->siso_len > sizeof(*addr))) 30837469Ssklower return (EINVAL); 30937469Ssklower if (ifnet == 0) 31037469Ssklower return (EADDRNOTAVAIL); 31137469Ssklower if (addr->siso_family != AF_ISO) 31237469Ssklower rp->risop_isop.isop_sfaddr = *addr; 31337469Ssklower rp->risop_rcb.rcb_faddr = (struct sockaddr *) 31437469Ssklower (rp->risop_isop.isop_faddr = &rp->risop_isop.isop_sfaddr); 31537469Ssklower soisconnected(so); 31637469Ssklower return (0); 31737469Ssklower } 31837469Ssklower } 31937469Ssklower error = raw_usrreq(so, req, m, nam, rights, control); 32037469Ssklower 32137469Ssklower if (error && req == PRU_ATTACH && so->so_pcb) 32237469Ssklower free((caddr_t)rp, M_PCB); 32337469Ssklower return (error); 32436373Ssklower } 32536373Ssklower #endif ISO 326