xref: /csrg-svn/sys/netiso/clnp_raw.c (revision 36373)
1*36373Ssklower /***********************************************************
2*36373Ssklower 		Copyright IBM Corporation 1987
3*36373Ssklower 
4*36373Ssklower                       All Rights Reserved
5*36373Ssklower 
6*36373Ssklower Permission to use, copy, modify, and distribute this software and its
7*36373Ssklower documentation for any purpose and without fee is hereby granted,
8*36373Ssklower provided that the above copyright notice appear in all copies and that
9*36373Ssklower both that copyright notice and this permission notice appear in
10*36373Ssklower supporting documentation, and that the name of IBM not be
11*36373Ssklower used in advertising or publicity pertaining to distribution of the
12*36373Ssklower software without specific, written prior permission.
13*36373Ssklower 
14*36373Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15*36373Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16*36373Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17*36373Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18*36373Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19*36373Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20*36373Ssklower SOFTWARE.
21*36373Ssklower 
22*36373Ssklower ******************************************************************/
23*36373Ssklower 
24*36373Ssklower /*
25*36373Ssklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
26*36373Ssklower  */
27*36373Ssklower /* $Header: clnp_raw.c,v 4.2 88/06/29 14:58:56 hagens Exp $ */
28*36373Ssklower /* $Source: /usr/argo/sys/netiso/RCS/clnp_raw.c,v $ */
29*36373Ssklower #ifndef lint
30*36373Ssklower static char *rcsid = "$Header: clnp_raw.c,v 4.2 88/06/29 14:58:56 hagens Exp $";
31*36373Ssklower #endif lint
32*36373Ssklower 
33*36373Ssklower #ifdef ISO
34*36373Ssklower 
35*36373Ssklower #include "../h/types.h"
36*36373Ssklower #include "../h/param.h"
37*36373Ssklower #include "../h/mbuf.h"
38*36373Ssklower #include "../h/domain.h"
39*36373Ssklower #include "../h/protosw.h"
40*36373Ssklower #include "../h/socket.h"
41*36373Ssklower #include "../h/socketvar.h"
42*36373Ssklower #include "../h/errno.h"
43*36373Ssklower #include "../h/time.h"
44*36373Ssklower 
45*36373Ssklower #include "../net/if.h"
46*36373Ssklower #include "../net/route.h"
47*36373Ssklower #include "../net/raw_cb.h"
48*36373Ssklower 
49*36373Ssklower #include "../netiso/iso.h"
50*36373Ssklower #include "../netiso/iso_pcb.h"
51*36373Ssklower #include "../netiso/clnp.h"
52*36373Ssklower #include "../netiso/clnp_stat.h"
53*36373Ssklower #include "../netiso/argo_debug.h"
54*36373Ssklower 
55*36373Ssklower struct sockaddr_iso	rclnp_src	= { AF_ISO };
56*36373Ssklower struct sockaddr_iso	rclnp_dst	= { AF_ISO };
57*36373Ssklower struct sockproto	rclnp_proto	= { PF_ISO, 0 };
58*36373Ssklower /*
59*36373Ssklower  * FUNCTION:		rclnp_input
60*36373Ssklower  *
61*36373Ssklower  * PURPOSE:			Setup generic address an protocol structures for
62*36373Ssklower  *					raw input routine, then pass them along with the
63*36373Ssklower  *					mbuf chain.
64*36373Ssklower  *
65*36373Ssklower  * RETURNS:			none
66*36373Ssklower  *
67*36373Ssklower  * SIDE EFFECTS:
68*36373Ssklower  *
69*36373Ssklower  * NOTES:			The protocol field of rclnp_proto is set to zero indicating
70*36373Ssklower  *					no protocol.
71*36373Ssklower  */
72*36373Ssklower rclnp_input(m, src, dst, hdrlen)
73*36373Ssklower struct mbuf 		*m;		/* ptr to packet */
74*36373Ssklower struct iso_addr		*src;	/* ptr to src address */
75*36373Ssklower struct iso_addr		*dst;	/* ptr to dest address */
76*36373Ssklower int					hdrlen; /* length (in bytes) of clnp header */
77*36373Ssklower {
78*36373Ssklower #ifdef	TROLL
79*36373Ssklower 	if (trollctl.tr_ops & TR_CHUCK) {
80*36373Ssklower 		m_freem(m);
81*36373Ssklower 		return;
82*36373Ssklower 	}
83*36373Ssklower #endif	TROLL
84*36373Ssklower 
85*36373Ssklower 	rclnp_src.siso_addr = *src;
86*36373Ssklower 	rclnp_dst.siso_addr = *dst;
87*36373Ssklower 	raw_input(m, &rclnp_proto, (struct sockaddr *)&rclnp_src,
88*36373Ssklower 		(struct sockaddr *)&rclnp_dst);
89*36373Ssklower }
90*36373Ssklower 
91*36373Ssklower /*
92*36373Ssklower  * FUNCTION:		rclnp_output
93*36373Ssklower  *
94*36373Ssklower  * PURPOSE:			Prepare to send a raw clnp packet. Setup src and dest
95*36373Ssklower  *					addresses, count the number of bytes to send, and
96*36373Ssklower  *					call clnp_output.
97*36373Ssklower  *
98*36373Ssklower  * RETURNS:			success - 0
99*36373Ssklower  *					failure - an appropriate error code
100*36373Ssklower  *
101*36373Ssklower  * SIDE EFFECTS:
102*36373Ssklower  *
103*36373Ssklower  * NOTES:
104*36373Ssklower  */
105*36373Ssklower rclnp_output(m0, so)
106*36373Ssklower struct mbuf		*m0;		/* packet to send */
107*36373Ssklower struct socket	*so;	/* socket to send from */
108*36373Ssklower {
109*36373Ssklower 	register struct mbuf	*m;			/* used to scan a chain */
110*36373Ssklower 	int						len = 0;	/* store length of chain here */
111*36373Ssklower 	struct rawcb			*rp = sotorawcb(so); /* ptr to raw cb */
112*36373Ssklower 	int						error;		/* return value of function */
113*36373Ssklower 	u_int					flags;		/* flags for clnp_output */
114*36373Ssklower 	struct isopcb			isopcb;		/* isopcb used to interface w/clnp */
115*36373Ssklower 
116*36373Ssklower 	/* Calculate length of data */
117*36373Ssklower 	for (m = m0; m; m = m->m_next)
118*36373Ssklower 		len += m->m_len;
119*36373Ssklower 
120*36373Ssklower 	bzero((caddr_t)&isopcb, sizeof(isopcb));
121*36373Ssklower 
122*36373Ssklower 	/*
123*36373Ssklower 	 *	Set up src address. If user has bound socket to an address, use it.
124*36373Ssklower 	 *	Otherwise, do not specify src (clnp_output will fill it in).
125*36373Ssklower 	 */
126*36373Ssklower 	if (rp->rcb_flags & RAW_LADDR) {
127*36373Ssklower 		if (rp->rcb_laddr.sa_family != AF_ISO) {
128*36373Ssklower 			m_freem(m0);
129*36373Ssklower 			return(EAFNOSUPPORT);
130*36373Ssklower 		}
131*36373Ssklower 		bcopy((caddr_t)&rp->rcb_laddr, &isopcb.isop_laddr,
132*36373Ssklower 			sizeof(struct sockaddr_iso));
133*36373Ssklower 	}
134*36373Ssklower 
135*36373Ssklower 	/* set up route structure, if route is present */
136*36373Ssklower 	if (rp->rcb_route.ro_rt != NULL)
137*36373Ssklower 		bcopy((caddr_t)&rp->rcb_route, (caddr_t)&isopcb.isop_route,
138*36373Ssklower 			sizeof(struct route));
139*36373Ssklower 
140*36373Ssklower 	/* set up dest address */
141*36373Ssklower 	bcopy((caddr_t)&rp->rcb_faddr, &isopcb.isop_faddr,
142*36373Ssklower 		sizeof(struct sockaddr_iso));
143*36373Ssklower 
144*36373Ssklower 	/*
145*36373Ssklower 	 *	setup option index - this was done when option was set, but raw
146*36373Ssklower 	 *	cb has no place to put it.
147*36373Ssklower 	 */
148*36373Ssklower 	if (rp->rcb_options != NULL) {
149*36373Ssklower 		isopcb.isop_options = rp->rcb_options;
150*36373Ssklower 		isopcb.isop_optindex = m_get(M_WAIT, MT_SOOPTS);
151*36373Ssklower 		(void) clnp_opt_sanity(isopcb.isop_options,
152*36373Ssklower 			mtod(isopcb.isop_options, caddr_t), isopcb.isop_options->m_len,
153*36373Ssklower 			mtod(isopcb.isop_optindex, struct clnp_optidx *));
154*36373Ssklower 	}
155*36373Ssklower 
156*36373Ssklower 	/* get flags and ship it off */
157*36373Ssklower 	flags = rp->rcb_flags & CLNP_VFLAGS;
158*36373Ssklower 
159*36373Ssklower #ifdef	TROLL
160*36373Ssklower 	if (trollctl.tr_ops & TR_BLAST) {
161*36373Ssklower 		register int i;
162*36373Ssklower 		struct timeval start, stop;
163*36373Ssklower 		extern struct timeval	time;
164*36373Ssklower 		struct mbuf *mbuf_orig;
165*36373Ssklower 
166*36373Ssklower 		mbuf_orig = m0;
167*36373Ssklower 		start = time;
168*36373Ssklower 		for (i=0; i<trollctl.tr_blast_cnt; i++) {
169*36373Ssklower 			m0 = m_copy(mbuf_orig, 0, M_COPYALL);
170*36373Ssklower 			if (m0 == NULL) {
171*36373Ssklower 				error = ENOBUFS;
172*36373Ssklower 			} else {
173*36373Ssklower 				error = clnp_output(m0, &isopcb, len, flags);
174*36373Ssklower 			}
175*36373Ssklower 			if (error)
176*36373Ssklower 				break;
177*36373Ssklower 		}
178*36373Ssklower 		stop = time;
179*36373Ssklower 		printf("rclnp_output: %d pkts in %d sec\n", i,
180*36373Ssklower 			stop.tv_sec - start.tv_sec);
181*36373Ssklower 		m_freem(mbuf_orig);
182*36373Ssklower 	} else {
183*36373Ssklower 		/*
184*36373Ssklower 		 *	Don't bother creating the cache since this is raw; probably
185*36373Ssklower 		 *	a one shot send
186*36373Ssklower 		 */
187*36373Ssklower 		error = clnp_output(m0, &isopcb, len, flags|CLNP_NOCACHE);
188*36373Ssklower 	}
189*36373Ssklower #else
190*36373Ssklower 		error = clnp_output(m0, &isopcb, len, flags|CLNP_NOCACHE);
191*36373Ssklower #endif	TROLL
192*36373Ssklower 
193*36373Ssklower 	if (isopcb.isop_route.ro_rt)
194*36373Ssklower 		RTFREE(isopcb.isop_route.ro_rt);
195*36373Ssklower 
196*36373Ssklower 	/* free clnp cached hdr if necessary */
197*36373Ssklower 	if (isopcb.isop_clnpcache != NULL) {
198*36373Ssklower 		struct clnp_cache *clcp =
199*36373Ssklower 			mtod(isopcb.isop_clnpcache, struct clnp_cache *);
200*36373Ssklower 		if (clcp->clc_hdr != NULL) {
201*36373Ssklower 			m_free(clcp->clc_hdr);
202*36373Ssklower 		}
203*36373Ssklower 		m_free(isopcb.isop_clnpcache);
204*36373Ssklower 	}
205*36373Ssklower 
206*36373Ssklower 	if (isopcb.isop_optindex != NULL)
207*36373Ssklower 		m_free(isopcb.isop_optindex);
208*36373Ssklower 
209*36373Ssklower 	return (error);
210*36373Ssklower }
211*36373Ssklower 
212*36373Ssklower /*
213*36373Ssklower  * FUNCTION:		rclnp_ctloutput
214*36373Ssklower  *
215*36373Ssklower  * PURPOSE:			Raw clnp socket option processing
216*36373Ssklower  *					All options are stored inside an mbuf.
217*36373Ssklower  *
218*36373Ssklower  * RETURNS:			success - 0
219*36373Ssklower  *					failure - unix error code
220*36373Ssklower  *
221*36373Ssklower  * SIDE EFFECTS:	If the options mbuf does not exist, it the mbuf passed
222*36373Ssklower  *					is used.
223*36373Ssklower  *
224*36373Ssklower  * NOTES:
225*36373Ssklower  */
226*36373Ssklower rclnp_ctloutput(op, so, level, optname, m)
227*36373Ssklower int				op;				/* type of operation */
228*36373Ssklower struct socket	*so;			/* ptr to socket */
229*36373Ssklower int 			level;			/* level of option */
230*36373Ssklower int				optname;		/* name of option */
231*36373Ssklower struct mbuf		**m;			/* ptr to ptr to option data */
232*36373Ssklower {
233*36373Ssklower 	int						error = 0;
234*36373Ssklower 	register struct rawcb	*rp = sotorawcb(so);/* raw cb ptr */
235*36373Ssklower 
236*36373Ssklower 	IFDEBUG(D_CTLOUTPUT)
237*36373Ssklower 		printf("rclnp_ctloutput: op = x%x, level = x%x, name = x%x\n",
238*36373Ssklower 			op, level, optname);
239*36373Ssklower 		if (*m != NULL) {
240*36373Ssklower 			printf("rclnp_ctloutput: %d bytes of mbuf data\n", (*m)->m_len);
241*36373Ssklower 			dump_buf(mtod((*m), caddr_t), (*m)->m_len);
242*36373Ssklower 		}
243*36373Ssklower 	ENDDEBUG
244*36373Ssklower 
245*36373Ssklower #ifdef SOL_NETWORK
246*36373Ssklower 	if (level != SOL_NETWORK)
247*36373Ssklower 		error = EINVAL;
248*36373Ssklower 	else switch (op) {
249*36373Ssklower #else
250*36373Ssklower 	switch (op) {
251*36373Ssklower #endif SOL_NETWORK
252*36373Ssklower 		case PRCO_SETOPT:
253*36373Ssklower 			switch (optname) {
254*36373Ssklower 				case CLNPOPT_FLAGS: {
255*36373Ssklower 					u_short	usr_flags;
256*36373Ssklower 					/*
257*36373Ssklower 					 *	Insure that the data passed has exactly one short in it
258*36373Ssklower 					 */
259*36373Ssklower 					if ((*m == NULL) || ((*m)->m_len != sizeof(short))) {
260*36373Ssklower 						error = EINVAL;
261*36373Ssklower 						break;
262*36373Ssklower 					}
263*36373Ssklower 
264*36373Ssklower 					/*
265*36373Ssklower 					 *	Don't allow invalid flags to be set
266*36373Ssklower 					 */
267*36373Ssklower 					usr_flags = (*mtod((*m), short *));
268*36373Ssklower 
269*36373Ssklower 					if ((usr_flags & (CLNP_VFLAGS)) != usr_flags) {
270*36373Ssklower 						error = EINVAL;
271*36373Ssklower 					} else
272*36373Ssklower 						rp->rcb_flags |= usr_flags;
273*36373Ssklower 
274*36373Ssklower 					} break;
275*36373Ssklower 
276*36373Ssklower 				case CLNPOPT_OPTS:
277*36373Ssklower 					error = clnp_set_opts(&rp->rcb_options, m);
278*36373Ssklower 					break;
279*36373Ssklower 			}
280*36373Ssklower 			break;
281*36373Ssklower 
282*36373Ssklower 		case PRCO_GETOPT:
283*36373Ssklower #ifdef notdef
284*36373Ssklower 			/* commented out to keep hi C quiet */
285*36373Ssklower 			switch (optname) {
286*36373Ssklower 				default:
287*36373Ssklower 					error = EINVAL;
288*36373Ssklower 					break;
289*36373Ssklower 			}
290*36373Ssklower #endif notdef
291*36373Ssklower 			break;
292*36373Ssklower 		default:
293*36373Ssklower 			error = EINVAL;
294*36373Ssklower 			break;
295*36373Ssklower 	}
296*36373Ssklower 	if (op == PRCO_SETOPT) {
297*36373Ssklower 		/* note: m_freem does not barf is *m is NULL */
298*36373Ssklower 		m_freem(*m);
299*36373Ssklower 		*m = NULL;
300*36373Ssklower 	}
301*36373Ssklower 
302*36373Ssklower 	return error;
303*36373Ssklower }
304*36373Ssklower 
305*36373Ssklower /*ARGSUSED*/
306*36373Ssklower clnp_usrreq(so, req, m, nam, rights)
307*36373Ssklower 	struct socket *so;
308*36373Ssklower 	int req;
309*36373Ssklower 	struct mbuf *m, *nam, *rights;
310*36373Ssklower {
311*36373Ssklower 	return EPROTOTYPE;
312*36373Ssklower }
313*36373Ssklower #endif	ISO
314