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