xref: /csrg-svn/sys/netiso/clnp_raw.c (revision 37469)
1*37469Ssklower /*********************************************************** 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 $ */
2836373Ssklower #ifndef lint
2936373Ssklower static char *rcsid = "$Header: clnp_raw.c,v 4.2 88/06/29 14:58:56 hagens Exp $";
3036373Ssklower #endif lint
3136373Ssklower 
3236373Ssklower #ifdef ISO
3336373Ssklower 
3436373Ssklower #include "../h/types.h"
3536373Ssklower #include "../h/param.h"
3636373Ssklower #include "../h/mbuf.h"
3736373Ssklower #include "../h/domain.h"
3836373Ssklower #include "../h/protosw.h"
3936373Ssklower #include "../h/socket.h"
4036373Ssklower #include "../h/socketvar.h"
4136373Ssklower #include "../h/errno.h"
4236373Ssklower #include "../h/time.h"
4336373Ssklower 
4436373Ssklower #include "../net/if.h"
4536373Ssklower #include "../net/route.h"
4636373Ssklower #include "../net/raw_cb.h"
4736373Ssklower 
48*37469Ssklower #include "iso.h"
49*37469Ssklower #include "iso_pcb.h"
50*37469Ssklower #include "clnp.h"
51*37469Ssklower #include "clnp_stat.h"
52*37469Ssklower #include "argo_debug.h"
5336373Ssklower 
54*37469Ssklower #include "tp_user.h"/* XXX -- defines SOL_NETWORK */
55*37469Ssklower 
56*37469Ssklower struct sockaddr_iso	rclnp_src	= { sizeof(rclnp_src), AF_ISO };
57*37469Ssklower struct sockaddr_iso	rclnp_dst	= { sizeof(rclnp_src), AF_ISO };
5836373Ssklower struct sockproto	rclnp_proto	= { PF_ISO, 0 };
5936373Ssklower /*
6036373Ssklower  * FUNCTION:		rclnp_input
6136373Ssklower  *
6236373Ssklower  * PURPOSE:			Setup generic address an protocol structures for
6336373Ssklower  *					raw input routine, then pass them along with the
6436373Ssklower  *					mbuf chain.
6536373Ssklower  *
6636373Ssklower  * RETURNS:			none
6736373Ssklower  *
6836373Ssklower  * SIDE EFFECTS:
6936373Ssklower  *
7036373Ssklower  * NOTES:			The protocol field of rclnp_proto is set to zero indicating
7136373Ssklower  *					no protocol.
7236373Ssklower  */
7336373Ssklower rclnp_input(m, src, dst, hdrlen)
7436373Ssklower struct mbuf 		*m;		/* ptr to packet */
7536373Ssklower struct iso_addr		*src;	/* ptr to src address */
7636373Ssklower struct iso_addr		*dst;	/* ptr to dest address */
7736373Ssklower int					hdrlen; /* length (in bytes) of clnp header */
7836373Ssklower {
7936373Ssklower #ifdef	TROLL
8036373Ssklower 	if (trollctl.tr_ops & TR_CHUCK) {
8136373Ssklower 		m_freem(m);
8236373Ssklower 		return;
8336373Ssklower 	}
8436373Ssklower #endif	TROLL
8536373Ssklower 
8636373Ssklower 	rclnp_src.siso_addr = *src;
8736373Ssklower 	rclnp_dst.siso_addr = *dst;
8836373Ssklower 	raw_input(m, &rclnp_proto, (struct sockaddr *)&rclnp_src,
8936373Ssklower 		(struct sockaddr *)&rclnp_dst);
9036373Ssklower }
9136373Ssklower 
9236373Ssklower /*
9336373Ssklower  * FUNCTION:		rclnp_output
9436373Ssklower  *
9536373Ssklower  * PURPOSE:			Prepare to send a raw clnp packet. Setup src and dest
9636373Ssklower  *					addresses, count the number of bytes to send, and
9736373Ssklower  *					call clnp_output.
9836373Ssklower  *
9936373Ssklower  * RETURNS:			success - 0
10036373Ssklower  *					failure - an appropriate error code
10136373Ssklower  *
10236373Ssklower  * SIDE EFFECTS:
10336373Ssklower  *
10436373Ssklower  * NOTES:
10536373Ssklower  */
10636373Ssklower rclnp_output(m0, so)
10736373Ssklower struct mbuf		*m0;		/* packet to send */
10836373Ssklower struct socket	*so;	/* socket to send from */
10936373Ssklower {
11036373Ssklower 	register struct mbuf	*m;			/* used to scan a chain */
11136373Ssklower 	int						len = 0;	/* store length of chain here */
112*37469Ssklower 	struct rawisopcb		*rp = sotorawisopcb(so); /* ptr to raw cb */
11336373Ssklower 	int						error;		/* return value of function */
114*37469Ssklower 	int						flags;		/* flags for clnp_output */
11536373Ssklower 
11636373Ssklower 	/*
11736373Ssklower 	 *	Set up src address. If user has bound socket to an address, use it.
11836373Ssklower 	 *	Otherwise, do not specify src (clnp_output will fill it in).
11936373Ssklower 	 */
120*37469Ssklower 	if (rp->risop_rcb.rcb_laddr) {
121*37469Ssklower 		if (rp->risop_isop.isop_sladdr.siso_family != AF_ISO) {
122*37469Ssklower bad:
12336373Ssklower 			m_freem(m0);
12436373Ssklower 			return(EAFNOSUPPORT);
12536373Ssklower 		}
12636373Ssklower 	}
12736373Ssklower 	/* set up dest address */
128*37469Ssklower 	if (rp->risop_rcb.rcb_faddr == 0)
129*37469Ssklower 		goto bad;
130*37469Ssklower 	rp->risop_isop.isop_sfaddr =
131*37469Ssklower 				*(struct sockaddr_iso *)rp->risop_rcb.rcb_faddr;
132*37469Ssklower 	rp->risop_isop.isop_faddr = &rp->risop_isop.isop_sfaddr;
13336373Ssklower 
13436373Ssklower 	/* get flags and ship it off */
135*37469Ssklower 	flags = rp->risop_flags & CLNP_VFLAGS;
13636373Ssklower 
137*37469Ssklower 	error = clnp_output(m0, &rp->risop_isop, flags|CLNP_NOCACHE);
13836373Ssklower 
13936373Ssklower 	return (error);
14036373Ssklower }
14136373Ssklower 
14236373Ssklower /*
14336373Ssklower  * FUNCTION:		rclnp_ctloutput
14436373Ssklower  *
14536373Ssklower  * PURPOSE:			Raw clnp socket option processing
14636373Ssklower  *					All options are stored inside an mbuf.
14736373Ssklower  *
14836373Ssklower  * RETURNS:			success - 0
14936373Ssklower  *					failure - unix error code
15036373Ssklower  *
15136373Ssklower  * SIDE EFFECTS:	If the options mbuf does not exist, it the mbuf passed
15236373Ssklower  *					is used.
15336373Ssklower  *
15436373Ssklower  * NOTES:
15536373Ssklower  */
15636373Ssklower rclnp_ctloutput(op, so, level, optname, m)
15736373Ssklower int				op;				/* type of operation */
15836373Ssklower struct socket	*so;			/* ptr to socket */
15936373Ssklower int 			level;			/* level of option */
16036373Ssklower int				optname;		/* name of option */
16136373Ssklower struct mbuf		**m;			/* ptr to ptr to option data */
16236373Ssklower {
16336373Ssklower 	int						error = 0;
164*37469Ssklower 	register struct rawisopcb	*rp = sotorawisopcb(so);/* raw cb ptr */
16536373Ssklower 
16636373Ssklower 	IFDEBUG(D_CTLOUTPUT)
16736373Ssklower 		printf("rclnp_ctloutput: op = x%x, level = x%x, name = x%x\n",
16836373Ssklower 			op, level, optname);
16936373Ssklower 		if (*m != NULL) {
17036373Ssklower 			printf("rclnp_ctloutput: %d bytes of mbuf data\n", (*m)->m_len);
17136373Ssklower 			dump_buf(mtod((*m), caddr_t), (*m)->m_len);
17236373Ssklower 		}
17336373Ssklower 	ENDDEBUG
17436373Ssklower 
17536373Ssklower #ifdef SOL_NETWORK
17636373Ssklower 	if (level != SOL_NETWORK)
17736373Ssklower 		error = EINVAL;
17836373Ssklower 	else switch (op) {
17936373Ssklower #else
18036373Ssklower 	switch (op) {
18136373Ssklower #endif SOL_NETWORK
18236373Ssklower 		case PRCO_SETOPT:
18336373Ssklower 			switch (optname) {
18436373Ssklower 				case CLNPOPT_FLAGS: {
18536373Ssklower 					u_short	usr_flags;
18636373Ssklower 					/*
18736373Ssklower 					 *	Insure that the data passed has exactly one short in it
18836373Ssklower 					 */
18936373Ssklower 					if ((*m == NULL) || ((*m)->m_len != sizeof(short))) {
19036373Ssklower 						error = EINVAL;
19136373Ssklower 						break;
19236373Ssklower 					}
19336373Ssklower 
19436373Ssklower 					/*
19536373Ssklower 					 *	Don't allow invalid flags to be set
19636373Ssklower 					 */
19736373Ssklower 					usr_flags = (*mtod((*m), short *));
19836373Ssklower 
19936373Ssklower 					if ((usr_flags & (CLNP_VFLAGS)) != usr_flags) {
20036373Ssklower 						error = EINVAL;
20136373Ssklower 					} else
202*37469Ssklower 						rp->risop_flags |= usr_flags;
20336373Ssklower 
20436373Ssklower 					} break;
20536373Ssklower 
20636373Ssklower 				case CLNPOPT_OPTS:
207*37469Ssklower 					if (error = clnp_set_opts(&rp->risop_isop.isop_options, m))
208*37469Ssklower 						break;
209*37469Ssklower 					rp->risop_isop.isop_optindex = m_get(M_WAIT, MT_SOOPTS);
210*37469Ssklower 					(void) clnp_opt_sanity(rp->risop_isop.isop_options,
211*37469Ssklower 						mtod(rp->risop_isop.isop_options, caddr_t),
212*37469Ssklower 						rp->risop_isop.isop_options->m_len,
213*37469Ssklower 						mtod(rp->risop_isop.isop_optindex,
214*37469Ssklower 							struct clnp_optidx *));
21536373Ssklower 					break;
21636373Ssklower 			}
21736373Ssklower 			break;
21836373Ssklower 
21936373Ssklower 		case PRCO_GETOPT:
22036373Ssklower #ifdef notdef
22136373Ssklower 			/* commented out to keep hi C quiet */
22236373Ssklower 			switch (optname) {
22336373Ssklower 				default:
22436373Ssklower 					error = EINVAL;
22536373Ssklower 					break;
22636373Ssklower 			}
22736373Ssklower #endif notdef
22836373Ssklower 			break;
22936373Ssklower 		default:
23036373Ssklower 			error = EINVAL;
23136373Ssklower 			break;
23236373Ssklower 	}
23336373Ssklower 	if (op == PRCO_SETOPT) {
23436373Ssklower 		/* note: m_freem does not barf is *m is NULL */
23536373Ssklower 		m_freem(*m);
23636373Ssklower 		*m = NULL;
23736373Ssklower 	}
23836373Ssklower 
23936373Ssklower 	return error;
24036373Ssklower }
24136373Ssklower 
24236373Ssklower /*ARGSUSED*/
243*37469Ssklower clnp_usrreq(so, req, m, nam, rights, control)
244*37469Ssklower 	register struct socket *so;
24536373Ssklower 	int req;
246*37469Ssklower 	struct mbuf *m, *nam, *rights, *control;
24736373Ssklower {
248*37469Ssklower 	register int error = 0;
249*37469Ssklower 	register struct rawisopcb *rp = sotorawisopcb(so);
250*37469Ssklower 
251*37469Ssklower 	rp = sotorawisopcb(so);
252*37469Ssklower 	switch (req) {
253*37469Ssklower 
254*37469Ssklower 	case PRU_ATTACH:
255*37469Ssklower 		if (rp)
256*37469Ssklower 			panic("rip_attach");
257*37469Ssklower 		MALLOC(rp, struct rawisopcb *, sizeof *rp, M_PCB, M_WAITOK);
258*37469Ssklower 		if (rp == 0)
259*37469Ssklower 			return (ENOBUFS);
260*37469Ssklower 		bzero((caddr_t)rp, sizeof *rp);
261*37469Ssklower 		so->so_pcb = (caddr_t)rp;
262*37469Ssklower 		break;
263*37469Ssklower 
264*37469Ssklower 	case PRU_DETACH:
265*37469Ssklower 		if (rp == 0)
266*37469Ssklower 			panic("rip_detach");
267*37469Ssklower 		if (rp->risop_isop.isop_options)
268*37469Ssklower 			m_freem(rp->risop_isop.isop_options);
269*37469Ssklower 		if (rp->risop_isop.isop_route.ro_rt)
270*37469Ssklower 			RTFREE(rp->risop_isop.isop_route.ro_rt);
271*37469Ssklower 		if (rp->risop_rcb.rcb_laddr)
272*37469Ssklower 			rp->risop_rcb.rcb_laddr = 0;
273*37469Ssklower 		/* free clnp cached hdr if necessary */
274*37469Ssklower 		if (rp->risop_isop.isop_clnpcache != NULL) {
275*37469Ssklower 			struct clnp_cache *clcp =
276*37469Ssklower 				mtod(rp->risop_isop.isop_clnpcache, struct clnp_cache *);
277*37469Ssklower 			if (clcp->clc_hdr != NULL) {
278*37469Ssklower 				m_free(clcp->clc_hdr);
279*37469Ssklower 			}
280*37469Ssklower 			m_free(rp->risop_isop.isop_clnpcache);
281*37469Ssklower 		}
282*37469Ssklower 		if (rp->risop_isop.isop_optindex != NULL)
283*37469Ssklower 			m_free(rp->risop_isop.isop_optindex);
284*37469Ssklower 
285*37469Ssklower 		break;
286*37469Ssklower 
287*37469Ssklower 	case PRU_BIND:
288*37469Ssklower 	    {
289*37469Ssklower 		struct sockaddr_iso *addr = mtod(nam, struct sockaddr_iso *);
290*37469Ssklower 
291*37469Ssklower 		if (nam->m_len != sizeof(*addr))
292*37469Ssklower 			return (EINVAL);
293*37469Ssklower 		if ((ifnet == 0) ||
294*37469Ssklower 		    (addr->siso_family != AF_ISO) ||
295*37469Ssklower 		    (addr->siso_addr.isoa_len  &&
296*37469Ssklower 		     ifa_ifwithaddr((struct sockaddr *)addr) == 0))
297*37469Ssklower 			return (EADDRNOTAVAIL);
298*37469Ssklower 		rp->risop_isop.isop_sladdr = *addr;
299*37469Ssklower 		rp->risop_rcb.rcb_laddr = (struct sockaddr *)
300*37469Ssklower 			(rp->risop_isop.isop_laddr = &rp->risop_isop.isop_sladdr);
301*37469Ssklower 		return (0);
302*37469Ssklower 	    }
303*37469Ssklower 	case PRU_CONNECT:
304*37469Ssklower 	    {
305*37469Ssklower 		struct sockaddr_iso *addr = mtod(nam, struct sockaddr_iso *);
306*37469Ssklower 
307*37469Ssklower 		if ((nam->m_len > sizeof(*addr)) || (addr->siso_len > sizeof(*addr)))
308*37469Ssklower 			return (EINVAL);
309*37469Ssklower 		if (ifnet == 0)
310*37469Ssklower 			return (EADDRNOTAVAIL);
311*37469Ssklower 		if (addr->siso_family != AF_ISO)
312*37469Ssklower 		rp->risop_isop.isop_sfaddr = *addr;
313*37469Ssklower 		rp->risop_rcb.rcb_faddr = (struct sockaddr *)
314*37469Ssklower 			(rp->risop_isop.isop_faddr = &rp->risop_isop.isop_sfaddr);
315*37469Ssklower 		soisconnected(so);
316*37469Ssklower 		return (0);
317*37469Ssklower 	    }
318*37469Ssklower 	}
319*37469Ssklower 	error =  raw_usrreq(so, req, m, nam, rights, control);
320*37469Ssklower 
321*37469Ssklower 	if (error && req == PRU_ATTACH && so->so_pcb)
322*37469Ssklower 		free((caddr_t)rp, M_PCB);
323*37469Ssklower 	return (error);
32436373Ssklower }
32536373Ssklower #endif	ISO
326