139195Ssklower /*********************************************************** 239195Ssklower 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*39933Ssklower /* @(#)clnp_raw.c 7.6 (Berkeley) 01/17/90 */ 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 5536373Ssklower struct sockproto rclnp_proto = { PF_ISO, 0 }; 5636373Ssklower /* 5736373Ssklower * FUNCTION: rclnp_input 5836373Ssklower * 5936373Ssklower * PURPOSE: Setup generic address an protocol structures for 6036373Ssklower * raw input routine, then pass them along with the 6136373Ssklower * mbuf chain. 6236373Ssklower * 6336373Ssklower * RETURNS: none 6436373Ssklower * 6536373Ssklower * SIDE EFFECTS: 6636373Ssklower * 6736373Ssklower * NOTES: The protocol field of rclnp_proto is set to zero indicating 6836373Ssklower * no protocol. 6936373Ssklower */ 7036373Ssklower rclnp_input(m, src, dst, hdrlen) 7136373Ssklower struct mbuf *m; /* ptr to packet */ 72*39933Ssklower struct sockaddr_iso *src; /* ptr to src address */ 73*39933Ssklower struct sockaddr_iso *dst; /* ptr to dest address */ 7436373Ssklower int hdrlen; /* length (in bytes) of clnp header */ 7536373Ssklower { 7636373Ssklower #ifdef TROLL 7736373Ssklower if (trollctl.tr_ops & TR_CHUCK) { 7836373Ssklower m_freem(m); 7936373Ssklower return; 8036373Ssklower } 8136373Ssklower #endif TROLL 8236373Ssklower 83*39933Ssklower if (raw_input(m, &rclnp_proto, (struct sockaddr *)src, 84*39933Ssklower (struct sockaddr *)dst) == 0) { 8539195Ssklower clnp_stat.cns_delivered--; 8639195Ssklower clnp_stat.cns_noproto++; 8739195Ssklower } 8836373Ssklower } 8936373Ssklower 9036373Ssklower /* 9136373Ssklower * FUNCTION: rclnp_output 9236373Ssklower * 9336373Ssklower * PURPOSE: Prepare to send a raw clnp packet. Setup src and dest 9436373Ssklower * addresses, count the number of bytes to send, and 9536373Ssklower * call clnp_output. 9636373Ssklower * 9736373Ssklower * RETURNS: success - 0 9836373Ssklower * failure - an appropriate error code 9936373Ssklower * 10036373Ssklower * SIDE EFFECTS: 10136373Ssklower * 10236373Ssklower * NOTES: 10336373Ssklower */ 10436373Ssklower rclnp_output(m0, so) 10536373Ssklower struct mbuf *m0; /* packet to send */ 10636373Ssklower struct socket *so; /* socket to send from */ 10736373Ssklower { 10836373Ssklower register struct mbuf *m; /* used to scan a chain */ 10936373Ssklower int len = 0; /* store length of chain here */ 11037469Ssklower struct rawisopcb *rp = sotorawisopcb(so); /* ptr to raw cb */ 11136373Ssklower int error; /* return value of function */ 11237469Ssklower int flags; /* flags for clnp_output */ 11336373Ssklower 11438841Ssklower if (0 == m0->m_flags & M_PKTHDR) 11538841Ssklower return (EINVAL); 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 13738841Ssklower error = clnp_output(m0, &rp->risop_isop, m0->m_pkthdr.len, 13838841Ssklower flags|CLNP_NOCACHE); 13936373Ssklower 14036373Ssklower return (error); 14136373Ssklower } 14236373Ssklower 14336373Ssklower /* 14436373Ssklower * FUNCTION: rclnp_ctloutput 14536373Ssklower * 14636373Ssklower * PURPOSE: Raw clnp socket option processing 14736373Ssklower * All options are stored inside an mbuf. 14836373Ssklower * 14936373Ssklower * RETURNS: success - 0 15036373Ssklower * failure - unix error code 15136373Ssklower * 15236373Ssklower * SIDE EFFECTS: If the options mbuf does not exist, it the mbuf passed 15336373Ssklower * is used. 15436373Ssklower * 15536373Ssklower * NOTES: 15636373Ssklower */ 15736373Ssklower rclnp_ctloutput(op, so, level, optname, m) 15836373Ssklower int op; /* type of operation */ 15936373Ssklower struct socket *so; /* ptr to socket */ 16036373Ssklower int level; /* level of option */ 16136373Ssklower int optname; /* name of option */ 16236373Ssklower struct mbuf **m; /* ptr to ptr to option data */ 16336373Ssklower { 16436373Ssklower int error = 0; 16537469Ssklower register struct rawisopcb *rp = sotorawisopcb(so);/* raw cb ptr */ 16636373Ssklower 16736373Ssklower IFDEBUG(D_CTLOUTPUT) 16836373Ssklower printf("rclnp_ctloutput: op = x%x, level = x%x, name = x%x\n", 16936373Ssklower op, level, optname); 17036373Ssklower if (*m != NULL) { 17136373Ssklower printf("rclnp_ctloutput: %d bytes of mbuf data\n", (*m)->m_len); 17236373Ssklower dump_buf(mtod((*m), caddr_t), (*m)->m_len); 17336373Ssklower } 17436373Ssklower ENDDEBUG 17536373Ssklower 17636373Ssklower #ifdef SOL_NETWORK 17736373Ssklower if (level != SOL_NETWORK) 17836373Ssklower error = EINVAL; 17936373Ssklower else switch (op) { 18036373Ssklower #else 18136373Ssklower switch (op) { 18236373Ssklower #endif SOL_NETWORK 18336373Ssklower case PRCO_SETOPT: 18436373Ssklower switch (optname) { 18536373Ssklower case CLNPOPT_FLAGS: { 18636373Ssklower u_short usr_flags; 18736373Ssklower /* 18836373Ssklower * Insure that the data passed has exactly one short in it 18936373Ssklower */ 19036373Ssklower if ((*m == NULL) || ((*m)->m_len != sizeof(short))) { 19136373Ssklower error = EINVAL; 19236373Ssklower break; 19336373Ssklower } 19436373Ssklower 19536373Ssklower /* 19636373Ssklower * Don't allow invalid flags to be set 19736373Ssklower */ 19836373Ssklower usr_flags = (*mtod((*m), short *)); 19936373Ssklower 20036373Ssklower if ((usr_flags & (CLNP_VFLAGS)) != usr_flags) { 20136373Ssklower error = EINVAL; 20236373Ssklower } else 20337469Ssklower rp->risop_flags |= usr_flags; 20436373Ssklower 20536373Ssklower } break; 20636373Ssklower 20736373Ssklower case CLNPOPT_OPTS: 20837469Ssklower if (error = clnp_set_opts(&rp->risop_isop.isop_options, m)) 20937469Ssklower break; 21037469Ssklower rp->risop_isop.isop_optindex = m_get(M_WAIT, MT_SOOPTS); 21137469Ssklower (void) clnp_opt_sanity(rp->risop_isop.isop_options, 21237469Ssklower mtod(rp->risop_isop.isop_options, caddr_t), 21337469Ssklower rp->risop_isop.isop_options->m_len, 21437469Ssklower mtod(rp->risop_isop.isop_optindex, 21537469Ssklower struct clnp_optidx *)); 21636373Ssklower break; 21736373Ssklower } 21836373Ssklower break; 21936373Ssklower 22036373Ssklower case PRCO_GETOPT: 22136373Ssklower #ifdef notdef 22236373Ssklower /* commented out to keep hi C quiet */ 22336373Ssklower switch (optname) { 22436373Ssklower default: 22536373Ssklower error = EINVAL; 22636373Ssklower break; 22736373Ssklower } 22836373Ssklower #endif notdef 22936373Ssklower break; 23036373Ssklower default: 23136373Ssklower error = EINVAL; 23236373Ssklower break; 23336373Ssklower } 23436373Ssklower if (op == PRCO_SETOPT) { 23536373Ssklower /* note: m_freem does not barf is *m is NULL */ 23636373Ssklower m_freem(*m); 23736373Ssklower *m = NULL; 23836373Ssklower } 23936373Ssklower 24036373Ssklower return error; 24136373Ssklower } 24236373Ssklower 24336373Ssklower /*ARGSUSED*/ 24437469Ssklower clnp_usrreq(so, req, m, nam, rights, control) 24537469Ssklower register struct socket *so; 24636373Ssklower int req; 24737469Ssklower struct mbuf *m, *nam, *rights, *control; 24836373Ssklower { 24937469Ssklower register int error = 0; 25037469Ssklower register struct rawisopcb *rp = sotorawisopcb(so); 25137469Ssklower 25237469Ssklower rp = sotorawisopcb(so); 25337469Ssklower switch (req) { 25437469Ssklower 25537469Ssklower case PRU_ATTACH: 25637469Ssklower if (rp) 25737469Ssklower panic("rip_attach"); 25837469Ssklower MALLOC(rp, struct rawisopcb *, sizeof *rp, M_PCB, M_WAITOK); 25937469Ssklower if (rp == 0) 26037469Ssklower return (ENOBUFS); 26137469Ssklower bzero((caddr_t)rp, sizeof *rp); 26237469Ssklower so->so_pcb = (caddr_t)rp; 26337469Ssklower break; 26437469Ssklower 26537469Ssklower case PRU_DETACH: 26637469Ssklower if (rp == 0) 26737469Ssklower panic("rip_detach"); 26837469Ssklower if (rp->risop_isop.isop_options) 26937469Ssklower m_freem(rp->risop_isop.isop_options); 27037469Ssklower if (rp->risop_isop.isop_route.ro_rt) 27137469Ssklower RTFREE(rp->risop_isop.isop_route.ro_rt); 27237469Ssklower if (rp->risop_rcb.rcb_laddr) 27337469Ssklower rp->risop_rcb.rcb_laddr = 0; 27437469Ssklower /* free clnp cached hdr if necessary */ 27537469Ssklower if (rp->risop_isop.isop_clnpcache != NULL) { 27637469Ssklower struct clnp_cache *clcp = 27737469Ssklower mtod(rp->risop_isop.isop_clnpcache, struct clnp_cache *); 27837469Ssklower if (clcp->clc_hdr != NULL) { 27937469Ssklower m_free(clcp->clc_hdr); 28037469Ssklower } 28137469Ssklower m_free(rp->risop_isop.isop_clnpcache); 28237469Ssklower } 28337469Ssklower if (rp->risop_isop.isop_optindex != NULL) 28437469Ssklower m_free(rp->risop_isop.isop_optindex); 28537469Ssklower 28637469Ssklower break; 28737469Ssklower 28837469Ssklower case PRU_BIND: 28937469Ssklower { 29037469Ssklower struct sockaddr_iso *addr = mtod(nam, struct sockaddr_iso *); 29137469Ssklower 29237469Ssklower if (nam->m_len != sizeof(*addr)) 29337469Ssklower return (EINVAL); 29437469Ssklower if ((ifnet == 0) || 29537469Ssklower (addr->siso_family != AF_ISO) || 29637469Ssklower (addr->siso_addr.isoa_len && 29737469Ssklower ifa_ifwithaddr((struct sockaddr *)addr) == 0)) 29837469Ssklower return (EADDRNOTAVAIL); 29937469Ssklower rp->risop_isop.isop_sladdr = *addr; 30037469Ssklower rp->risop_rcb.rcb_laddr = (struct sockaddr *) 30137469Ssklower (rp->risop_isop.isop_laddr = &rp->risop_isop.isop_sladdr); 30237469Ssklower return (0); 30337469Ssklower } 30437469Ssklower case PRU_CONNECT: 30537469Ssklower { 30637469Ssklower struct sockaddr_iso *addr = mtod(nam, struct sockaddr_iso *); 30737469Ssklower 30837469Ssklower if ((nam->m_len > sizeof(*addr)) || (addr->siso_len > sizeof(*addr))) 30937469Ssklower return (EINVAL); 31037469Ssklower if (ifnet == 0) 31137469Ssklower return (EADDRNOTAVAIL); 31237469Ssklower if (addr->siso_family != AF_ISO) 31337469Ssklower rp->risop_isop.isop_sfaddr = *addr; 31437469Ssklower rp->risop_rcb.rcb_faddr = (struct sockaddr *) 31537469Ssklower (rp->risop_isop.isop_faddr = &rp->risop_isop.isop_sfaddr); 31637469Ssklower soisconnected(so); 31737469Ssklower return (0); 31837469Ssklower } 31937469Ssklower } 32037469Ssklower error = raw_usrreq(so, req, m, nam, rights, control); 32137469Ssklower 32237469Ssklower if (error && req == PRU_ATTACH && so->so_pcb) 32337469Ssklower free((caddr_t)rp, M_PCB); 32437469Ssklower return (error); 32536373Ssklower } 326