xref: /csrg-svn/sys/netiso/clnp_raw.c (revision 63222)
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