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