xref: /csrg-svn/sys/netiso/clnp_raw.c (revision 38841)
137469Ssklower /*********************************************************** Copyright IBM Corporation 1987
236373Ssklower 
336373Ssklower                       All Rights Reserved
436373Ssklower 
536373Ssklower Permission to use, copy, modify, and distribute this software and its
636373Ssklower documentation for any purpose and without fee is hereby granted,
736373Ssklower provided that the above copyright notice appear in all copies and that
836373Ssklower both that copyright notice and this permission notice appear in
936373Ssklower supporting documentation, and that the name of IBM not be
1036373Ssklower used in advertising or publicity pertaining to distribution of the
1136373Ssklower software without specific, written prior permission.
1236373Ssklower 
1336373Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
1436373Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
1536373Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
1636373Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
1736373Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
1836373Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
1936373Ssklower SOFTWARE.
2036373Ssklower 
2136373Ssklower ******************************************************************/
2236373Ssklower 
2336373Ssklower /*
2436373Ssklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
2536373Ssklower  */
2636373Ssklower /* $Header: clnp_raw.c,v 4.2 88/06/29 14:58:56 hagens Exp $ */
2736373Ssklower /* $Source: /usr/argo/sys/netiso/RCS/clnp_raw.c,v $ */
28*38841Ssklower /*	@(#)clnp_raw.c	7.4 (Berkeley) 08/29/89 */
2936373Ssklower #ifndef lint
3036373Ssklower static char *rcsid = "$Header: clnp_raw.c,v 4.2 88/06/29 14:58:56 hagens Exp $";
3136373Ssklower #endif lint
3236373Ssklower 
3336373Ssklower #ifdef ISO
3436373Ssklower 
3537536Smckusick #include "types.h"
3637536Smckusick #include "param.h"
3737536Smckusick #include "mbuf.h"
3837536Smckusick #include "domain.h"
3937536Smckusick #include "protosw.h"
4037536Smckusick #include "socket.h"
4137536Smckusick #include "socketvar.h"
4237536Smckusick #include "errno.h"
4337536Smckusick #include "time.h"
4436373Ssklower 
4536373Ssklower #include "../net/if.h"
4636373Ssklower #include "../net/route.h"
4736373Ssklower #include "../net/raw_cb.h"
4836373Ssklower 
4937469Ssklower #include "iso.h"
5037469Ssklower #include "iso_pcb.h"
5137469Ssklower #include "clnp.h"
5237469Ssklower #include "clnp_stat.h"
5337469Ssklower #include "argo_debug.h"
5436373Ssklower 
5537469Ssklower #include "tp_user.h"/* XXX -- defines SOL_NETWORK */
5637469Ssklower 
5737469Ssklower struct sockaddr_iso	rclnp_src	= { sizeof(rclnp_src), AF_ISO };
5837469Ssklower struct sockaddr_iso	rclnp_dst	= { sizeof(rclnp_src), AF_ISO };
5936373Ssklower struct sockproto	rclnp_proto	= { PF_ISO, 0 };
6036373Ssklower /*
6136373Ssklower  * FUNCTION:		rclnp_input
6236373Ssklower  *
6336373Ssklower  * PURPOSE:			Setup generic address an protocol structures for
6436373Ssklower  *					raw input routine, then pass them along with the
6536373Ssklower  *					mbuf chain.
6636373Ssklower  *
6736373Ssklower  * RETURNS:			none
6836373Ssklower  *
6936373Ssklower  * SIDE EFFECTS:
7036373Ssklower  *
7136373Ssklower  * NOTES:			The protocol field of rclnp_proto is set to zero indicating
7236373Ssklower  *					no protocol.
7336373Ssklower  */
7436373Ssklower rclnp_input(m, src, dst, hdrlen)
7536373Ssklower struct mbuf 		*m;		/* ptr to packet */
7636373Ssklower struct iso_addr		*src;	/* ptr to src address */
7736373Ssklower struct iso_addr		*dst;	/* ptr to dest address */
7836373Ssklower int					hdrlen; /* length (in bytes) of clnp header */
7936373Ssklower {
8036373Ssklower #ifdef	TROLL
8136373Ssklower 	if (trollctl.tr_ops & TR_CHUCK) {
8236373Ssklower 		m_freem(m);
8336373Ssklower 		return;
8436373Ssklower 	}
8536373Ssklower #endif	TROLL
8636373Ssklower 
8736373Ssklower 	rclnp_src.siso_addr = *src;
8836373Ssklower 	rclnp_dst.siso_addr = *dst;
8936373Ssklower 	raw_input(m, &rclnp_proto, (struct sockaddr *)&rclnp_src,
9036373Ssklower 		(struct sockaddr *)&rclnp_dst);
9136373Ssklower }
9236373Ssklower 
9336373Ssklower /*
9436373Ssklower  * FUNCTION:		rclnp_output
9536373Ssklower  *
9636373Ssklower  * PURPOSE:			Prepare to send a raw clnp packet. Setup src and dest
9736373Ssklower  *					addresses, count the number of bytes to send, and
9836373Ssklower  *					call clnp_output.
9936373Ssklower  *
10036373Ssklower  * RETURNS:			success - 0
10136373Ssklower  *					failure - an appropriate error code
10236373Ssklower  *
10336373Ssklower  * SIDE EFFECTS:
10436373Ssklower  *
10536373Ssklower  * NOTES:
10636373Ssklower  */
10736373Ssklower rclnp_output(m0, so)
10836373Ssklower struct mbuf		*m0;		/* packet to send */
10936373Ssklower struct socket	*so;	/* socket to send from */
11036373Ssklower {
11136373Ssklower 	register struct mbuf	*m;			/* used to scan a chain */
11236373Ssklower 	int						len = 0;	/* store length of chain here */
11337469Ssklower 	struct rawisopcb		*rp = sotorawisopcb(so); /* ptr to raw cb */
11436373Ssklower 	int						error;		/* return value of function */
11537469Ssklower 	int						flags;		/* flags for clnp_output */
11636373Ssklower 
117*38841Ssklower 	if (0 == m0->m_flags & M_PKTHDR)
118*38841Ssklower 		return (EINVAL);
11936373Ssklower 	/*
12036373Ssklower 	 *	Set up src address. If user has bound socket to an address, use it.
12136373Ssklower 	 *	Otherwise, do not specify src (clnp_output will fill it in).
12236373Ssklower 	 */
12337469Ssklower 	if (rp->risop_rcb.rcb_laddr) {
12437469Ssklower 		if (rp->risop_isop.isop_sladdr.siso_family != AF_ISO) {
12537469Ssklower bad:
12636373Ssklower 			m_freem(m0);
12736373Ssklower 			return(EAFNOSUPPORT);
12836373Ssklower 		}
12936373Ssklower 	}
13036373Ssklower 	/* set up dest address */
13137469Ssklower 	if (rp->risop_rcb.rcb_faddr == 0)
13237469Ssklower 		goto bad;
13337469Ssklower 	rp->risop_isop.isop_sfaddr =
13437469Ssklower 				*(struct sockaddr_iso *)rp->risop_rcb.rcb_faddr;
13537469Ssklower 	rp->risop_isop.isop_faddr = &rp->risop_isop.isop_sfaddr;
13636373Ssklower 
13736373Ssklower 	/* get flags and ship it off */
13837469Ssklower 	flags = rp->risop_flags & CLNP_VFLAGS;
13936373Ssklower 
140*38841Ssklower 	error = clnp_output(m0, &rp->risop_isop, m0->m_pkthdr.len,
141*38841Ssklower 												flags|CLNP_NOCACHE);
14236373Ssklower 
14336373Ssklower 	return (error);
14436373Ssklower }
14536373Ssklower 
14636373Ssklower /*
14736373Ssklower  * FUNCTION:		rclnp_ctloutput
14836373Ssklower  *
14936373Ssklower  * PURPOSE:			Raw clnp socket option processing
15036373Ssklower  *					All options are stored inside an mbuf.
15136373Ssklower  *
15236373Ssklower  * RETURNS:			success - 0
15336373Ssklower  *					failure - unix error code
15436373Ssklower  *
15536373Ssklower  * SIDE EFFECTS:	If the options mbuf does not exist, it the mbuf passed
15636373Ssklower  *					is used.
15736373Ssklower  *
15836373Ssklower  * NOTES:
15936373Ssklower  */
16036373Ssklower rclnp_ctloutput(op, so, level, optname, m)
16136373Ssklower int				op;				/* type of operation */
16236373Ssklower struct socket	*so;			/* ptr to socket */
16336373Ssklower int 			level;			/* level of option */
16436373Ssklower int				optname;		/* name of option */
16536373Ssklower struct mbuf		**m;			/* ptr to ptr to option data */
16636373Ssklower {
16736373Ssklower 	int						error = 0;
16837469Ssklower 	register struct rawisopcb	*rp = sotorawisopcb(so);/* raw cb ptr */
16936373Ssklower 
17036373Ssklower 	IFDEBUG(D_CTLOUTPUT)
17136373Ssklower 		printf("rclnp_ctloutput: op = x%x, level = x%x, name = x%x\n",
17236373Ssklower 			op, level, optname);
17336373Ssklower 		if (*m != NULL) {
17436373Ssklower 			printf("rclnp_ctloutput: %d bytes of mbuf data\n", (*m)->m_len);
17536373Ssklower 			dump_buf(mtod((*m), caddr_t), (*m)->m_len);
17636373Ssklower 		}
17736373Ssklower 	ENDDEBUG
17836373Ssklower 
17936373Ssklower #ifdef SOL_NETWORK
18036373Ssklower 	if (level != SOL_NETWORK)
18136373Ssklower 		error = EINVAL;
18236373Ssklower 	else switch (op) {
18336373Ssklower #else
18436373Ssklower 	switch (op) {
18536373Ssklower #endif SOL_NETWORK
18636373Ssklower 		case PRCO_SETOPT:
18736373Ssklower 			switch (optname) {
18836373Ssklower 				case CLNPOPT_FLAGS: {
18936373Ssklower 					u_short	usr_flags;
19036373Ssklower 					/*
19136373Ssklower 					 *	Insure that the data passed has exactly one short in it
19236373Ssklower 					 */
19336373Ssklower 					if ((*m == NULL) || ((*m)->m_len != sizeof(short))) {
19436373Ssklower 						error = EINVAL;
19536373Ssklower 						break;
19636373Ssklower 					}
19736373Ssklower 
19836373Ssklower 					/*
19936373Ssklower 					 *	Don't allow invalid flags to be set
20036373Ssklower 					 */
20136373Ssklower 					usr_flags = (*mtod((*m), short *));
20236373Ssklower 
20336373Ssklower 					if ((usr_flags & (CLNP_VFLAGS)) != usr_flags) {
20436373Ssklower 						error = EINVAL;
20536373Ssklower 					} else
20637469Ssklower 						rp->risop_flags |= usr_flags;
20736373Ssklower 
20836373Ssklower 					} break;
20936373Ssklower 
21036373Ssklower 				case CLNPOPT_OPTS:
21137469Ssklower 					if (error = clnp_set_opts(&rp->risop_isop.isop_options, m))
21237469Ssklower 						break;
21337469Ssklower 					rp->risop_isop.isop_optindex = m_get(M_WAIT, MT_SOOPTS);
21437469Ssklower 					(void) clnp_opt_sanity(rp->risop_isop.isop_options,
21537469Ssklower 						mtod(rp->risop_isop.isop_options, caddr_t),
21637469Ssklower 						rp->risop_isop.isop_options->m_len,
21737469Ssklower 						mtod(rp->risop_isop.isop_optindex,
21837469Ssklower 							struct clnp_optidx *));
21936373Ssklower 					break;
22036373Ssklower 			}
22136373Ssklower 			break;
22236373Ssklower 
22336373Ssklower 		case PRCO_GETOPT:
22436373Ssklower #ifdef notdef
22536373Ssklower 			/* commented out to keep hi C quiet */
22636373Ssklower 			switch (optname) {
22736373Ssklower 				default:
22836373Ssklower 					error = EINVAL;
22936373Ssklower 					break;
23036373Ssklower 			}
23136373Ssklower #endif notdef
23236373Ssklower 			break;
23336373Ssklower 		default:
23436373Ssklower 			error = EINVAL;
23536373Ssklower 			break;
23636373Ssklower 	}
23736373Ssklower 	if (op == PRCO_SETOPT) {
23836373Ssklower 		/* note: m_freem does not barf is *m is NULL */
23936373Ssklower 		m_freem(*m);
24036373Ssklower 		*m = NULL;
24136373Ssklower 	}
24236373Ssklower 
24336373Ssklower 	return error;
24436373Ssklower }
24536373Ssklower 
24636373Ssklower /*ARGSUSED*/
24737469Ssklower clnp_usrreq(so, req, m, nam, rights, control)
24837469Ssklower 	register struct socket *so;
24936373Ssklower 	int req;
25037469Ssklower 	struct mbuf *m, *nam, *rights, *control;
25136373Ssklower {
25237469Ssklower 	register int error = 0;
25337469Ssklower 	register struct rawisopcb *rp = sotorawisopcb(so);
25437469Ssklower 
25537469Ssklower 	rp = sotorawisopcb(so);
25637469Ssklower 	switch (req) {
25737469Ssklower 
25837469Ssklower 	case PRU_ATTACH:
25937469Ssklower 		if (rp)
26037469Ssklower 			panic("rip_attach");
26137469Ssklower 		MALLOC(rp, struct rawisopcb *, sizeof *rp, M_PCB, M_WAITOK);
26237469Ssklower 		if (rp == 0)
26337469Ssklower 			return (ENOBUFS);
26437469Ssklower 		bzero((caddr_t)rp, sizeof *rp);
26537469Ssklower 		so->so_pcb = (caddr_t)rp;
26637469Ssklower 		break;
26737469Ssklower 
26837469Ssklower 	case PRU_DETACH:
26937469Ssklower 		if (rp == 0)
27037469Ssklower 			panic("rip_detach");
27137469Ssklower 		if (rp->risop_isop.isop_options)
27237469Ssklower 			m_freem(rp->risop_isop.isop_options);
27337469Ssklower 		if (rp->risop_isop.isop_route.ro_rt)
27437469Ssklower 			RTFREE(rp->risop_isop.isop_route.ro_rt);
27537469Ssklower 		if (rp->risop_rcb.rcb_laddr)
27637469Ssklower 			rp->risop_rcb.rcb_laddr = 0;
27737469Ssklower 		/* free clnp cached hdr if necessary */
27837469Ssklower 		if (rp->risop_isop.isop_clnpcache != NULL) {
27937469Ssklower 			struct clnp_cache *clcp =
28037469Ssklower 				mtod(rp->risop_isop.isop_clnpcache, struct clnp_cache *);
28137469Ssklower 			if (clcp->clc_hdr != NULL) {
28237469Ssklower 				m_free(clcp->clc_hdr);
28337469Ssklower 			}
28437469Ssklower 			m_free(rp->risop_isop.isop_clnpcache);
28537469Ssklower 		}
28637469Ssklower 		if (rp->risop_isop.isop_optindex != NULL)
28737469Ssklower 			m_free(rp->risop_isop.isop_optindex);
28837469Ssklower 
28937469Ssklower 		break;
29037469Ssklower 
29137469Ssklower 	case PRU_BIND:
29237469Ssklower 	    {
29337469Ssklower 		struct sockaddr_iso *addr = mtod(nam, struct sockaddr_iso *);
29437469Ssklower 
29537469Ssklower 		if (nam->m_len != sizeof(*addr))
29637469Ssklower 			return (EINVAL);
29737469Ssklower 		if ((ifnet == 0) ||
29837469Ssklower 		    (addr->siso_family != AF_ISO) ||
29937469Ssklower 		    (addr->siso_addr.isoa_len  &&
30037469Ssklower 		     ifa_ifwithaddr((struct sockaddr *)addr) == 0))
30137469Ssklower 			return (EADDRNOTAVAIL);
30237469Ssklower 		rp->risop_isop.isop_sladdr = *addr;
30337469Ssklower 		rp->risop_rcb.rcb_laddr = (struct sockaddr *)
30437469Ssklower 			(rp->risop_isop.isop_laddr = &rp->risop_isop.isop_sladdr);
30537469Ssklower 		return (0);
30637469Ssklower 	    }
30737469Ssklower 	case PRU_CONNECT:
30837469Ssklower 	    {
30937469Ssklower 		struct sockaddr_iso *addr = mtod(nam, struct sockaddr_iso *);
31037469Ssklower 
31137469Ssklower 		if ((nam->m_len > sizeof(*addr)) || (addr->siso_len > sizeof(*addr)))
31237469Ssklower 			return (EINVAL);
31337469Ssklower 		if (ifnet == 0)
31437469Ssklower 			return (EADDRNOTAVAIL);
31537469Ssklower 		if (addr->siso_family != AF_ISO)
31637469Ssklower 		rp->risop_isop.isop_sfaddr = *addr;
31737469Ssklower 		rp->risop_rcb.rcb_faddr = (struct sockaddr *)
31837469Ssklower 			(rp->risop_isop.isop_faddr = &rp->risop_isop.isop_sfaddr);
31937469Ssklower 		soisconnected(so);
32037469Ssklower 		return (0);
32137469Ssklower 	    }
32237469Ssklower 	}
32337469Ssklower 	error =  raw_usrreq(so, req, m, nam, rights, control);
32437469Ssklower 
32537469Ssklower 	if (error && req == PRU_ATTACH && so->so_pcb)
32637469Ssklower 		free((caddr_t)rp, M_PCB);
32737469Ssklower 	return (error);
32836373Ssklower }
32936373Ssklower #endif	ISO
330