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