149267Sbostic /*-
2*63222Sbostic * Copyright (c) 1991, 1993
3*63222Sbostic * The Regents of the University of California. All rights reserved.
449267Sbostic *
549267Sbostic * %sccs.include.redist.c%
649267Sbostic *
7*63222Sbostic * @(#)clnp_raw.c 8.1 (Berkeley) 06/10/93
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
3956533Sbostic #include <sys/param.h>
4056533Sbostic #include <sys/mbuf.h>
4156533Sbostic #include <sys/domain.h>
4256533Sbostic #include <sys/protosw.h>
4356533Sbostic #include <sys/socket.h>
4456533Sbostic #include <sys/socketvar.h>
4556533Sbostic #include <sys/errno.h>
4656533Sbostic #include <sys/time.h>
4736373Ssklower
4856533Sbostic #include <net/if.h>
4956533Sbostic #include <net/route.h>
5056533Sbostic #include <net/raw_cb.h>
5136373Ssklower
5256533Sbostic #include <netiso/iso.h>
5356533Sbostic #include <netiso/iso_pcb.h>
5456533Sbostic #include <netiso/clnp.h>
5556533Sbostic #include <netiso/clnp_stat.h>
5656533Sbostic #include <netiso/argo_debug.h>
5736373Ssklower
5856533Sbostic #include <netiso/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 }
8660359Sbostic #endif /* TROLL */
8736373Ssklower
8861296Ssklower raw_input(m, &rclnp_proto, (struct sockaddr *)src, (struct sockaddr *)dst);
8936373Ssklower }
9036373Ssklower
9136373Ssklower /*
9236373Ssklower * FUNCTION: rclnp_output
9336373Ssklower *
9436373Ssklower * PURPOSE: Prepare to send a raw clnp packet. Setup src and dest
9536373Ssklower * addresses, count the number of bytes to send, and
9636373Ssklower * call clnp_output.
9736373Ssklower *
9836373Ssklower * RETURNS: success - 0
9936373Ssklower * failure - an appropriate error code
10036373Ssklower *
10136373Ssklower * SIDE EFFECTS:
10236373Ssklower *
10336373Ssklower * NOTES:
10436373Ssklower */
10536373Ssklower rclnp_output(m0, so)
10636373Ssklower struct mbuf *m0; /* packet to send */
10736373Ssklower struct socket *so; /* socket to send from */
10836373Ssklower {
10936373Ssklower register struct mbuf *m; /* used to scan a chain */
11036373Ssklower int len = 0; /* store length of chain here */
11137469Ssklower struct rawisopcb *rp = sotorawisopcb(so); /* ptr to raw cb */
11236373Ssklower int error; /* return value of function */
11337469Ssklower int flags; /* flags for clnp_output */
11436373Ssklower
11552434Ssklower if (0 == (m0->m_flags & M_PKTHDR))
11638841Ssklower return (EINVAL);
11736373Ssklower /*
11836373Ssklower * Set up src address. If user has bound socket to an address, use it.
11936373Ssklower * Otherwise, do not specify src (clnp_output will fill it in).
12036373Ssklower */
12137469Ssklower if (rp->risop_rcb.rcb_laddr) {
12237469Ssklower if (rp->risop_isop.isop_sladdr.siso_family != AF_ISO) {
12337469Ssklower bad:
12436373Ssklower m_freem(m0);
12536373Ssklower return(EAFNOSUPPORT);
12636373Ssklower }
12736373Ssklower }
12836373Ssklower /* set up dest address */
12937469Ssklower if (rp->risop_rcb.rcb_faddr == 0)
13037469Ssklower goto bad;
13137469Ssklower rp->risop_isop.isop_sfaddr =
13237469Ssklower *(struct sockaddr_iso *)rp->risop_rcb.rcb_faddr;
13337469Ssklower rp->risop_isop.isop_faddr = &rp->risop_isop.isop_sfaddr;
13436373Ssklower
13536373Ssklower /* get flags and ship it off */
13637469Ssklower flags = rp->risop_flags & CLNP_VFLAGS;
13736373Ssklower
13838841Ssklower error = clnp_output(m0, &rp->risop_isop, m0->m_pkthdr.len,
13938841Ssklower flags|CLNP_NOCACHE);
14036373Ssklower
14136373Ssklower return (error);
14236373Ssklower }
14336373Ssklower
14436373Ssklower /*
14536373Ssklower * FUNCTION: rclnp_ctloutput
14636373Ssklower *
14736373Ssklower * PURPOSE: Raw clnp socket option processing
14836373Ssklower * All options are stored inside an mbuf.
14936373Ssklower *
15036373Ssklower * RETURNS: success - 0
15136373Ssklower * failure - unix error code
15236373Ssklower *
15336373Ssklower * SIDE EFFECTS: If the options mbuf does not exist, it the mbuf passed
15436373Ssklower * is used.
15536373Ssklower *
15636373Ssklower * NOTES:
15736373Ssklower */
rclnp_ctloutput(op,so,level,optname,m)15836373Ssklower rclnp_ctloutput(op, so, level, optname, m)
15936373Ssklower int op; /* type of operation */
16036373Ssklower struct socket *so; /* ptr to socket */
16136373Ssklower int level; /* level of option */
16236373Ssklower int optname; /* name of option */
16336373Ssklower struct mbuf **m; /* ptr to ptr to option data */
16436373Ssklower {
16536373Ssklower int error = 0;
16637469Ssklower register struct rawisopcb *rp = sotorawisopcb(so);/* raw cb ptr */
16736373Ssklower
16836373Ssklower IFDEBUG(D_CTLOUTPUT)
16936373Ssklower printf("rclnp_ctloutput: op = x%x, level = x%x, name = x%x\n",
17036373Ssklower op, level, optname);
17136373Ssklower if (*m != NULL) {
17236373Ssklower printf("rclnp_ctloutput: %d bytes of mbuf data\n", (*m)->m_len);
17336373Ssklower dump_buf(mtod((*m), caddr_t), (*m)->m_len);
17436373Ssklower }
17536373Ssklower ENDDEBUG
17636373Ssklower
17736373Ssklower #ifdef SOL_NETWORK
17836373Ssklower if (level != SOL_NETWORK)
17936373Ssklower error = EINVAL;
18036373Ssklower else switch (op) {
18136373Ssklower #else
18236373Ssklower switch (op) {
18360359Sbostic #endif /* SOL_NETWORK */
18436373Ssklower case PRCO_SETOPT:
18536373Ssklower switch (optname) {
18636373Ssklower case CLNPOPT_FLAGS: {
18736373Ssklower u_short usr_flags;
18836373Ssklower /*
18936373Ssklower * Insure that the data passed has exactly one short in it
19036373Ssklower */
19136373Ssklower if ((*m == NULL) || ((*m)->m_len != sizeof(short))) {
19236373Ssklower error = EINVAL;
19336373Ssklower break;
19436373Ssklower }
19536373Ssklower
19636373Ssklower /*
19736373Ssklower * Don't allow invalid flags to be set
19836373Ssklower */
19936373Ssklower usr_flags = (*mtod((*m), short *));
20036373Ssklower
20136373Ssklower if ((usr_flags & (CLNP_VFLAGS)) != usr_flags) {
20236373Ssklower error = EINVAL;
20336373Ssklower } else
20437469Ssklower rp->risop_flags |= usr_flags;
20536373Ssklower
20636373Ssklower } break;
20736373Ssklower
20836373Ssklower case CLNPOPT_OPTS:
20937469Ssklower if (error = clnp_set_opts(&rp->risop_isop.isop_options, m))
21037469Ssklower break;
21137469Ssklower rp->risop_isop.isop_optindex = m_get(M_WAIT, MT_SOOPTS);
21237469Ssklower (void) clnp_opt_sanity(rp->risop_isop.isop_options,
21337469Ssklower mtod(rp->risop_isop.isop_options, caddr_t),
21437469Ssklower rp->risop_isop.isop_options->m_len,
21537469Ssklower mtod(rp->risop_isop.isop_optindex,
21637469Ssklower struct clnp_optidx *));
21736373Ssklower break;
21836373Ssklower }
21936373Ssklower break;
22036373Ssklower
22136373Ssklower case PRCO_GETOPT:
22236373Ssklower #ifdef notdef
22336373Ssklower /* commented out to keep hi C quiet */
22436373Ssklower switch (optname) {
22536373Ssklower default:
22636373Ssklower error = EINVAL;
22736373Ssklower break;
22836373Ssklower }
22960359Sbostic #endif /* notdef */
23036373Ssklower break;
23136373Ssklower default:
23236373Ssklower error = EINVAL;
23336373Ssklower break;
23436373Ssklower }
23536373Ssklower if (op == PRCO_SETOPT) {
23636373Ssklower /* note: m_freem does not barf is *m is NULL */
23736373Ssklower m_freem(*m);
23836373Ssklower *m = NULL;
23936373Ssklower }
24036373Ssklower
24136373Ssklower return error;
24236373Ssklower }
24336373Ssklower
24436373Ssklower /*ARGSUSED*/
clnp_usrreq(so,req,m,nam,control)24540779Ssklower clnp_usrreq(so, req, m, nam, control)
24637469Ssklower register struct socket *so;
24736373Ssklower int req;
24840779Ssklower struct mbuf *m, *nam, *control;
24936373Ssklower {
25037469Ssklower register int error = 0;
25137469Ssklower register struct rawisopcb *rp = sotorawisopcb(so);
25237469Ssklower
25337469Ssklower rp = sotorawisopcb(so);
25437469Ssklower switch (req) {
25537469Ssklower
25637469Ssklower case PRU_ATTACH:
25737469Ssklower if (rp)
25837469Ssklower panic("rip_attach");
25937469Ssklower MALLOC(rp, struct rawisopcb *, sizeof *rp, M_PCB, M_WAITOK);
26037469Ssklower if (rp == 0)
26137469Ssklower return (ENOBUFS);
26237469Ssklower bzero((caddr_t)rp, sizeof *rp);
26337469Ssklower so->so_pcb = (caddr_t)rp;
26437469Ssklower break;
26537469Ssklower
26637469Ssklower case PRU_DETACH:
26737469Ssklower if (rp == 0)
26837469Ssklower panic("rip_detach");
26937469Ssklower if (rp->risop_isop.isop_options)
27037469Ssklower m_freem(rp->risop_isop.isop_options);
27137469Ssklower if (rp->risop_isop.isop_route.ro_rt)
27237469Ssklower RTFREE(rp->risop_isop.isop_route.ro_rt);
27337469Ssklower if (rp->risop_rcb.rcb_laddr)
27437469Ssklower rp->risop_rcb.rcb_laddr = 0;
27537469Ssklower /* free clnp cached hdr if necessary */
27637469Ssklower if (rp->risop_isop.isop_clnpcache != NULL) {
27737469Ssklower struct clnp_cache *clcp =
27837469Ssklower mtod(rp->risop_isop.isop_clnpcache, struct clnp_cache *);
27937469Ssklower if (clcp->clc_hdr != NULL) {
28037469Ssklower m_free(clcp->clc_hdr);
28137469Ssklower }
28237469Ssklower m_free(rp->risop_isop.isop_clnpcache);
28337469Ssklower }
28437469Ssklower if (rp->risop_isop.isop_optindex != NULL)
28537469Ssklower m_free(rp->risop_isop.isop_optindex);
28637469Ssklower
28737469Ssklower break;
28837469Ssklower
28937469Ssklower case PRU_BIND:
29037469Ssklower {
29137469Ssklower struct sockaddr_iso *addr = mtod(nam, struct sockaddr_iso *);
29237469Ssklower
29337469Ssklower if (nam->m_len != sizeof(*addr))
29437469Ssklower return (EINVAL);
29537469Ssklower if ((ifnet == 0) ||
29637469Ssklower (addr->siso_family != AF_ISO) ||
29737469Ssklower (addr->siso_addr.isoa_len &&
29837469Ssklower ifa_ifwithaddr((struct sockaddr *)addr) == 0))
29937469Ssklower return (EADDRNOTAVAIL);
30037469Ssklower rp->risop_isop.isop_sladdr = *addr;
30137469Ssklower rp->risop_rcb.rcb_laddr = (struct sockaddr *)
30237469Ssklower (rp->risop_isop.isop_laddr = &rp->risop_isop.isop_sladdr);
30337469Ssklower return (0);
30437469Ssklower }
30537469Ssklower case PRU_CONNECT:
30637469Ssklower {
30737469Ssklower struct sockaddr_iso *addr = mtod(nam, struct sockaddr_iso *);
30837469Ssklower
30937469Ssklower if ((nam->m_len > sizeof(*addr)) || (addr->siso_len > sizeof(*addr)))
31037469Ssklower return (EINVAL);
31137469Ssklower if (ifnet == 0)
31237469Ssklower return (EADDRNOTAVAIL);
31337469Ssklower if (addr->siso_family != AF_ISO)
31437469Ssklower rp->risop_isop.isop_sfaddr = *addr;
31537469Ssklower rp->risop_rcb.rcb_faddr = (struct sockaddr *)
31637469Ssklower (rp->risop_isop.isop_faddr = &rp->risop_isop.isop_sfaddr);
31737469Ssklower soisconnected(so);
31837469Ssklower return (0);
31937469Ssklower }
32037469Ssklower }
32140779Ssklower error = raw_usrreq(so, req, m, nam, control);
32237469Ssklower
32337469Ssklower if (error && req == PRU_ATTACH && so->so_pcb)
32437469Ssklower free((caddr_t)rp, M_PCB);
32537469Ssklower return (error);
32636373Ssklower }
327