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