xref: /csrg-svn/sys/netiso/clnp_raw.c (revision 39195)
1*39195Ssklower /***********************************************************
2*39195Ssklower 				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*39195Ssklower /*	@(#)clnp_raw.c	7.5 (Berkeley) 09/22/89 */
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 
5537469Ssklower struct sockaddr_iso	rclnp_src	= { sizeof(rclnp_src), AF_ISO };
5637469Ssklower struct sockaddr_iso	rclnp_dst	= { sizeof(rclnp_src), AF_ISO };
5736373Ssklower struct sockproto	rclnp_proto	= { PF_ISO, 0 };
5836373Ssklower /*
5936373Ssklower  * FUNCTION:		rclnp_input
6036373Ssklower  *
6136373Ssklower  * PURPOSE:			Setup generic address an protocol structures for
6236373Ssklower  *					raw input routine, then pass them along with the
6336373Ssklower  *					mbuf chain.
6436373Ssklower  *
6536373Ssklower  * RETURNS:			none
6636373Ssklower  *
6736373Ssklower  * SIDE EFFECTS:
6836373Ssklower  *
6936373Ssklower  * NOTES:			The protocol field of rclnp_proto is set to zero indicating
7036373Ssklower  *					no protocol.
7136373Ssklower  */
7236373Ssklower rclnp_input(m, src, dst, hdrlen)
7336373Ssklower struct mbuf 		*m;		/* ptr to packet */
7436373Ssklower struct iso_addr		*src;	/* ptr to src address */
7536373Ssklower struct iso_addr		*dst;	/* ptr to dest address */
7636373Ssklower int					hdrlen; /* length (in bytes) of clnp header */
7736373Ssklower {
7836373Ssklower #ifdef	TROLL
7936373Ssklower 	if (trollctl.tr_ops & TR_CHUCK) {
8036373Ssklower 		m_freem(m);
8136373Ssklower 		return;
8236373Ssklower 	}
8336373Ssklower #endif	TROLL
8436373Ssklower 
8536373Ssklower 	rclnp_src.siso_addr = *src;
8636373Ssklower 	rclnp_dst.siso_addr = *dst;
87*39195Ssklower 	if (raw_input(m, &rclnp_proto, (struct sockaddr *)&rclnp_src,
88*39195Ssklower 		(struct sockaddr *)&rclnp_dst) == 0) {
89*39195Ssklower 			clnp_stat.cns_delivered--;
90*39195Ssklower 			clnp_stat.cns_noproto++;
91*39195Ssklower 	}
9236373Ssklower }
9336373Ssklower 
9436373Ssklower /*
9536373Ssklower  * FUNCTION:		rclnp_output
9636373Ssklower  *
9736373Ssklower  * PURPOSE:			Prepare to send a raw clnp packet. Setup src and dest
9836373Ssklower  *					addresses, count the number of bytes to send, and
9936373Ssklower  *					call clnp_output.
10036373Ssklower  *
10136373Ssklower  * RETURNS:			success - 0
10236373Ssklower  *					failure - an appropriate error code
10336373Ssklower  *
10436373Ssklower  * SIDE EFFECTS:
10536373Ssklower  *
10636373Ssklower  * NOTES:
10736373Ssklower  */
10836373Ssklower rclnp_output(m0, so)
10936373Ssklower struct mbuf		*m0;		/* packet to send */
11036373Ssklower struct socket	*so;	/* socket to send from */
11136373Ssklower {
11236373Ssklower 	register struct mbuf	*m;			/* used to scan a chain */
11336373Ssklower 	int						len = 0;	/* store length of chain here */
11437469Ssklower 	struct rawisopcb		*rp = sotorawisopcb(so); /* ptr to raw cb */
11536373Ssklower 	int						error;		/* return value of function */
11637469Ssklower 	int						flags;		/* flags for clnp_output */
11736373Ssklower 
11838841Ssklower 	if (0 == m0->m_flags & M_PKTHDR)
11938841Ssklower 		return (EINVAL);
12036373Ssklower 	/*
12136373Ssklower 	 *	Set up src address. If user has bound socket to an address, use it.
12236373Ssklower 	 *	Otherwise, do not specify src (clnp_output will fill it in).
12336373Ssklower 	 */
12437469Ssklower 	if (rp->risop_rcb.rcb_laddr) {
12537469Ssklower 		if (rp->risop_isop.isop_sladdr.siso_family != AF_ISO) {
12637469Ssklower bad:
12736373Ssklower 			m_freem(m0);
12836373Ssklower 			return(EAFNOSUPPORT);
12936373Ssklower 		}
13036373Ssklower 	}
13136373Ssklower 	/* set up dest address */
13237469Ssklower 	if (rp->risop_rcb.rcb_faddr == 0)
13337469Ssklower 		goto bad;
13437469Ssklower 	rp->risop_isop.isop_sfaddr =
13537469Ssklower 				*(struct sockaddr_iso *)rp->risop_rcb.rcb_faddr;
13637469Ssklower 	rp->risop_isop.isop_faddr = &rp->risop_isop.isop_sfaddr;
13736373Ssklower 
13836373Ssklower 	/* get flags and ship it off */
13937469Ssklower 	flags = rp->risop_flags & CLNP_VFLAGS;
14036373Ssklower 
14138841Ssklower 	error = clnp_output(m0, &rp->risop_isop, m0->m_pkthdr.len,
14238841Ssklower 												flags|CLNP_NOCACHE);
14336373Ssklower 
14436373Ssklower 	return (error);
14536373Ssklower }
14636373Ssklower 
14736373Ssklower /*
14836373Ssklower  * FUNCTION:		rclnp_ctloutput
14936373Ssklower  *
15036373Ssklower  * PURPOSE:			Raw clnp socket option processing
15136373Ssklower  *					All options are stored inside an mbuf.
15236373Ssklower  *
15336373Ssklower  * RETURNS:			success - 0
15436373Ssklower  *					failure - unix error code
15536373Ssklower  *
15636373Ssklower  * SIDE EFFECTS:	If the options mbuf does not exist, it the mbuf passed
15736373Ssklower  *					is used.
15836373Ssklower  *
15936373Ssklower  * NOTES:
16036373Ssklower  */
16136373Ssklower rclnp_ctloutput(op, so, level, optname, m)
16236373Ssklower int				op;				/* type of operation */
16336373Ssklower struct socket	*so;			/* ptr to socket */
16436373Ssklower int 			level;			/* level of option */
16536373Ssklower int				optname;		/* name of option */
16636373Ssklower struct mbuf		**m;			/* ptr to ptr to option data */
16736373Ssklower {
16836373Ssklower 	int						error = 0;
16937469Ssklower 	register struct rawisopcb	*rp = sotorawisopcb(so);/* raw cb ptr */
17036373Ssklower 
17136373Ssklower 	IFDEBUG(D_CTLOUTPUT)
17236373Ssklower 		printf("rclnp_ctloutput: op = x%x, level = x%x, name = x%x\n",
17336373Ssklower 			op, level, optname);
17436373Ssklower 		if (*m != NULL) {
17536373Ssklower 			printf("rclnp_ctloutput: %d bytes of mbuf data\n", (*m)->m_len);
17636373Ssklower 			dump_buf(mtod((*m), caddr_t), (*m)->m_len);
17736373Ssklower 		}
17836373Ssklower 	ENDDEBUG
17936373Ssklower 
18036373Ssklower #ifdef SOL_NETWORK
18136373Ssklower 	if (level != SOL_NETWORK)
18236373Ssklower 		error = EINVAL;
18336373Ssklower 	else switch (op) {
18436373Ssklower #else
18536373Ssklower 	switch (op) {
18636373Ssklower #endif SOL_NETWORK
18736373Ssklower 		case PRCO_SETOPT:
18836373Ssklower 			switch (optname) {
18936373Ssklower 				case CLNPOPT_FLAGS: {
19036373Ssklower 					u_short	usr_flags;
19136373Ssklower 					/*
19236373Ssklower 					 *	Insure that the data passed has exactly one short in it
19336373Ssklower 					 */
19436373Ssklower 					if ((*m == NULL) || ((*m)->m_len != sizeof(short))) {
19536373Ssklower 						error = EINVAL;
19636373Ssklower 						break;
19736373Ssklower 					}
19836373Ssklower 
19936373Ssklower 					/*
20036373Ssklower 					 *	Don't allow invalid flags to be set
20136373Ssklower 					 */
20236373Ssklower 					usr_flags = (*mtod((*m), short *));
20336373Ssklower 
20436373Ssklower 					if ((usr_flags & (CLNP_VFLAGS)) != usr_flags) {
20536373Ssklower 						error = EINVAL;
20636373Ssklower 					} else
20737469Ssklower 						rp->risop_flags |= usr_flags;
20836373Ssklower 
20936373Ssklower 					} break;
21036373Ssklower 
21136373Ssklower 				case CLNPOPT_OPTS:
21237469Ssklower 					if (error = clnp_set_opts(&rp->risop_isop.isop_options, m))
21337469Ssklower 						break;
21437469Ssklower 					rp->risop_isop.isop_optindex = m_get(M_WAIT, MT_SOOPTS);
21537469Ssklower 					(void) clnp_opt_sanity(rp->risop_isop.isop_options,
21637469Ssklower 						mtod(rp->risop_isop.isop_options, caddr_t),
21737469Ssklower 						rp->risop_isop.isop_options->m_len,
21837469Ssklower 						mtod(rp->risop_isop.isop_optindex,
21937469Ssklower 							struct clnp_optidx *));
22036373Ssklower 					break;
22136373Ssklower 			}
22236373Ssklower 			break;
22336373Ssklower 
22436373Ssklower 		case PRCO_GETOPT:
22536373Ssklower #ifdef notdef
22636373Ssklower 			/* commented out to keep hi C quiet */
22736373Ssklower 			switch (optname) {
22836373Ssklower 				default:
22936373Ssklower 					error = EINVAL;
23036373Ssklower 					break;
23136373Ssklower 			}
23236373Ssklower #endif notdef
23336373Ssklower 			break;
23436373Ssklower 		default:
23536373Ssklower 			error = EINVAL;
23636373Ssklower 			break;
23736373Ssklower 	}
23836373Ssklower 	if (op == PRCO_SETOPT) {
23936373Ssklower 		/* note: m_freem does not barf is *m is NULL */
24036373Ssklower 		m_freem(*m);
24136373Ssklower 		*m = NULL;
24236373Ssklower 	}
24336373Ssklower 
24436373Ssklower 	return error;
24536373Ssklower }
24636373Ssklower 
24736373Ssklower /*ARGSUSED*/
24837469Ssklower clnp_usrreq(so, req, m, nam, rights, control)
24937469Ssklower 	register struct socket *so;
25036373Ssklower 	int req;
25137469Ssklower 	struct mbuf *m, *nam, *rights, *control;
25236373Ssklower {
25337469Ssklower 	register int error = 0;
25437469Ssklower 	register struct rawisopcb *rp = sotorawisopcb(so);
25537469Ssklower 
25637469Ssklower 	rp = sotorawisopcb(so);
25737469Ssklower 	switch (req) {
25837469Ssklower 
25937469Ssklower 	case PRU_ATTACH:
26037469Ssklower 		if (rp)
26137469Ssklower 			panic("rip_attach");
26237469Ssklower 		MALLOC(rp, struct rawisopcb *, sizeof *rp, M_PCB, M_WAITOK);
26337469Ssklower 		if (rp == 0)
26437469Ssklower 			return (ENOBUFS);
26537469Ssklower 		bzero((caddr_t)rp, sizeof *rp);
26637469Ssklower 		so->so_pcb = (caddr_t)rp;
26737469Ssklower 		break;
26837469Ssklower 
26937469Ssklower 	case PRU_DETACH:
27037469Ssklower 		if (rp == 0)
27137469Ssklower 			panic("rip_detach");
27237469Ssklower 		if (rp->risop_isop.isop_options)
27337469Ssklower 			m_freem(rp->risop_isop.isop_options);
27437469Ssklower 		if (rp->risop_isop.isop_route.ro_rt)
27537469Ssklower 			RTFREE(rp->risop_isop.isop_route.ro_rt);
27637469Ssklower 		if (rp->risop_rcb.rcb_laddr)
27737469Ssklower 			rp->risop_rcb.rcb_laddr = 0;
27837469Ssklower 		/* free clnp cached hdr if necessary */
27937469Ssklower 		if (rp->risop_isop.isop_clnpcache != NULL) {
28037469Ssklower 			struct clnp_cache *clcp =
28137469Ssklower 				mtod(rp->risop_isop.isop_clnpcache, struct clnp_cache *);
28237469Ssklower 			if (clcp->clc_hdr != NULL) {
28337469Ssklower 				m_free(clcp->clc_hdr);
28437469Ssklower 			}
28537469Ssklower 			m_free(rp->risop_isop.isop_clnpcache);
28637469Ssklower 		}
28737469Ssklower 		if (rp->risop_isop.isop_optindex != NULL)
28837469Ssklower 			m_free(rp->risop_isop.isop_optindex);
28937469Ssklower 
29037469Ssklower 		break;
29137469Ssklower 
29237469Ssklower 	case PRU_BIND:
29337469Ssklower 	    {
29437469Ssklower 		struct sockaddr_iso *addr = mtod(nam, struct sockaddr_iso *);
29537469Ssklower 
29637469Ssklower 		if (nam->m_len != sizeof(*addr))
29737469Ssklower 			return (EINVAL);
29837469Ssklower 		if ((ifnet == 0) ||
29937469Ssklower 		    (addr->siso_family != AF_ISO) ||
30037469Ssklower 		    (addr->siso_addr.isoa_len  &&
30137469Ssklower 		     ifa_ifwithaddr((struct sockaddr *)addr) == 0))
30237469Ssklower 			return (EADDRNOTAVAIL);
30337469Ssklower 		rp->risop_isop.isop_sladdr = *addr;
30437469Ssklower 		rp->risop_rcb.rcb_laddr = (struct sockaddr *)
30537469Ssklower 			(rp->risop_isop.isop_laddr = &rp->risop_isop.isop_sladdr);
30637469Ssklower 		return (0);
30737469Ssklower 	    }
30837469Ssklower 	case PRU_CONNECT:
30937469Ssklower 	    {
31037469Ssklower 		struct sockaddr_iso *addr = mtod(nam, struct sockaddr_iso *);
31137469Ssklower 
31237469Ssklower 		if ((nam->m_len > sizeof(*addr)) || (addr->siso_len > sizeof(*addr)))
31337469Ssklower 			return (EINVAL);
31437469Ssklower 		if (ifnet == 0)
31537469Ssklower 			return (EADDRNOTAVAIL);
31637469Ssklower 		if (addr->siso_family != AF_ISO)
31737469Ssklower 		rp->risop_isop.isop_sfaddr = *addr;
31837469Ssklower 		rp->risop_rcb.rcb_faddr = (struct sockaddr *)
31937469Ssklower 			(rp->risop_isop.isop_faddr = &rp->risop_isop.isop_sfaddr);
32037469Ssklower 		soisconnected(so);
32137469Ssklower 		return (0);
32237469Ssklower 	    }
32337469Ssklower 	}
32437469Ssklower 	error =  raw_usrreq(so, req, m, nam, rights, control);
32537469Ssklower 
32637469Ssklower 	if (error && req == PRU_ATTACH && so->so_pcb)
32737469Ssklower 		free((caddr_t)rp, M_PCB);
32837469Ssklower 	return (error);
32936373Ssklower }
330