xref: /csrg-svn/sys/netiso/clnp_raw.c (revision 39195)
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 /*	@(#)clnp_raw.c	7.5 (Berkeley) 09/22/89 */
30 #ifndef lint
31 static char *rcsid = "$Header: clnp_raw.c,v 4.2 88/06/29 14:58:56 hagens Exp $";
32 #endif lint
33 
34 #include "param.h"
35 #include "mbuf.h"
36 #include "domain.h"
37 #include "protosw.h"
38 #include "socket.h"
39 #include "socketvar.h"
40 #include "errno.h"
41 #include "time.h"
42 
43 #include "../net/if.h"
44 #include "../net/route.h"
45 #include "../net/raw_cb.h"
46 
47 #include "iso.h"
48 #include "iso_pcb.h"
49 #include "clnp.h"
50 #include "clnp_stat.h"
51 #include "argo_debug.h"
52 
53 #include "tp_user.h"/* XXX -- defines SOL_NETWORK */
54 
55 struct sockaddr_iso	rclnp_src	= { sizeof(rclnp_src), AF_ISO };
56 struct sockaddr_iso	rclnp_dst	= { sizeof(rclnp_src), 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 	if (raw_input(m, &rclnp_proto, (struct sockaddr *)&rclnp_src,
88 		(struct sockaddr *)&rclnp_dst) == 0) {
89 			clnp_stat.cns_delivered--;
90 			clnp_stat.cns_noproto++;
91 	}
92 }
93 
94 /*
95  * FUNCTION:		rclnp_output
96  *
97  * PURPOSE:			Prepare to send a raw clnp packet. Setup src and dest
98  *					addresses, count the number of bytes to send, and
99  *					call clnp_output.
100  *
101  * RETURNS:			success - 0
102  *					failure - an appropriate error code
103  *
104  * SIDE EFFECTS:
105  *
106  * NOTES:
107  */
108 rclnp_output(m0, so)
109 struct mbuf		*m0;		/* packet to send */
110 struct socket	*so;	/* socket to send from */
111 {
112 	register struct mbuf	*m;			/* used to scan a chain */
113 	int						len = 0;	/* store length of chain here */
114 	struct rawisopcb		*rp = sotorawisopcb(so); /* ptr to raw cb */
115 	int						error;		/* return value of function */
116 	int						flags;		/* flags for clnp_output */
117 
118 	if (0 == m0->m_flags & M_PKTHDR)
119 		return (EINVAL);
120 	/*
121 	 *	Set up src address. If user has bound socket to an address, use it.
122 	 *	Otherwise, do not specify src (clnp_output will fill it in).
123 	 */
124 	if (rp->risop_rcb.rcb_laddr) {
125 		if (rp->risop_isop.isop_sladdr.siso_family != AF_ISO) {
126 bad:
127 			m_freem(m0);
128 			return(EAFNOSUPPORT);
129 		}
130 	}
131 	/* set up dest address */
132 	if (rp->risop_rcb.rcb_faddr == 0)
133 		goto bad;
134 	rp->risop_isop.isop_sfaddr =
135 				*(struct sockaddr_iso *)rp->risop_rcb.rcb_faddr;
136 	rp->risop_isop.isop_faddr = &rp->risop_isop.isop_sfaddr;
137 
138 	/* get flags and ship it off */
139 	flags = rp->risop_flags & CLNP_VFLAGS;
140 
141 	error = clnp_output(m0, &rp->risop_isop, m0->m_pkthdr.len,
142 												flags|CLNP_NOCACHE);
143 
144 	return (error);
145 }
146 
147 /*
148  * FUNCTION:		rclnp_ctloutput
149  *
150  * PURPOSE:			Raw clnp socket option processing
151  *					All options are stored inside an mbuf.
152  *
153  * RETURNS:			success - 0
154  *					failure - unix error code
155  *
156  * SIDE EFFECTS:	If the options mbuf does not exist, it the mbuf passed
157  *					is used.
158  *
159  * NOTES:
160  */
161 rclnp_ctloutput(op, so, level, optname, m)
162 int				op;				/* type of operation */
163 struct socket	*so;			/* ptr to socket */
164 int 			level;			/* level of option */
165 int				optname;		/* name of option */
166 struct mbuf		**m;			/* ptr to ptr to option data */
167 {
168 	int						error = 0;
169 	register struct rawisopcb	*rp = sotorawisopcb(so);/* raw cb ptr */
170 
171 	IFDEBUG(D_CTLOUTPUT)
172 		printf("rclnp_ctloutput: op = x%x, level = x%x, name = x%x\n",
173 			op, level, optname);
174 		if (*m != NULL) {
175 			printf("rclnp_ctloutput: %d bytes of mbuf data\n", (*m)->m_len);
176 			dump_buf(mtod((*m), caddr_t), (*m)->m_len);
177 		}
178 	ENDDEBUG
179 
180 #ifdef SOL_NETWORK
181 	if (level != SOL_NETWORK)
182 		error = EINVAL;
183 	else switch (op) {
184 #else
185 	switch (op) {
186 #endif SOL_NETWORK
187 		case PRCO_SETOPT:
188 			switch (optname) {
189 				case CLNPOPT_FLAGS: {
190 					u_short	usr_flags;
191 					/*
192 					 *	Insure that the data passed has exactly one short in it
193 					 */
194 					if ((*m == NULL) || ((*m)->m_len != sizeof(short))) {
195 						error = EINVAL;
196 						break;
197 					}
198 
199 					/*
200 					 *	Don't allow invalid flags to be set
201 					 */
202 					usr_flags = (*mtod((*m), short *));
203 
204 					if ((usr_flags & (CLNP_VFLAGS)) != usr_flags) {
205 						error = EINVAL;
206 					} else
207 						rp->risop_flags |= usr_flags;
208 
209 					} break;
210 
211 				case CLNPOPT_OPTS:
212 					if (error = clnp_set_opts(&rp->risop_isop.isop_options, m))
213 						break;
214 					rp->risop_isop.isop_optindex = m_get(M_WAIT, MT_SOOPTS);
215 					(void) clnp_opt_sanity(rp->risop_isop.isop_options,
216 						mtod(rp->risop_isop.isop_options, caddr_t),
217 						rp->risop_isop.isop_options->m_len,
218 						mtod(rp->risop_isop.isop_optindex,
219 							struct clnp_optidx *));
220 					break;
221 			}
222 			break;
223 
224 		case PRCO_GETOPT:
225 #ifdef notdef
226 			/* commented out to keep hi C quiet */
227 			switch (optname) {
228 				default:
229 					error = EINVAL;
230 					break;
231 			}
232 #endif notdef
233 			break;
234 		default:
235 			error = EINVAL;
236 			break;
237 	}
238 	if (op == PRCO_SETOPT) {
239 		/* note: m_freem does not barf is *m is NULL */
240 		m_freem(*m);
241 		*m = NULL;
242 	}
243 
244 	return error;
245 }
246 
247 /*ARGSUSED*/
248 clnp_usrreq(so, req, m, nam, rights, control)
249 	register struct socket *so;
250 	int req;
251 	struct mbuf *m, *nam, *rights, *control;
252 {
253 	register int error = 0;
254 	register struct rawisopcb *rp = sotorawisopcb(so);
255 
256 	rp = sotorawisopcb(so);
257 	switch (req) {
258 
259 	case PRU_ATTACH:
260 		if (rp)
261 			panic("rip_attach");
262 		MALLOC(rp, struct rawisopcb *, sizeof *rp, M_PCB, M_WAITOK);
263 		if (rp == 0)
264 			return (ENOBUFS);
265 		bzero((caddr_t)rp, sizeof *rp);
266 		so->so_pcb = (caddr_t)rp;
267 		break;
268 
269 	case PRU_DETACH:
270 		if (rp == 0)
271 			panic("rip_detach");
272 		if (rp->risop_isop.isop_options)
273 			m_freem(rp->risop_isop.isop_options);
274 		if (rp->risop_isop.isop_route.ro_rt)
275 			RTFREE(rp->risop_isop.isop_route.ro_rt);
276 		if (rp->risop_rcb.rcb_laddr)
277 			rp->risop_rcb.rcb_laddr = 0;
278 		/* free clnp cached hdr if necessary */
279 		if (rp->risop_isop.isop_clnpcache != NULL) {
280 			struct clnp_cache *clcp =
281 				mtod(rp->risop_isop.isop_clnpcache, struct clnp_cache *);
282 			if (clcp->clc_hdr != NULL) {
283 				m_free(clcp->clc_hdr);
284 			}
285 			m_free(rp->risop_isop.isop_clnpcache);
286 		}
287 		if (rp->risop_isop.isop_optindex != NULL)
288 			m_free(rp->risop_isop.isop_optindex);
289 
290 		break;
291 
292 	case PRU_BIND:
293 	    {
294 		struct sockaddr_iso *addr = mtod(nam, struct sockaddr_iso *);
295 
296 		if (nam->m_len != sizeof(*addr))
297 			return (EINVAL);
298 		if ((ifnet == 0) ||
299 		    (addr->siso_family != AF_ISO) ||
300 		    (addr->siso_addr.isoa_len  &&
301 		     ifa_ifwithaddr((struct sockaddr *)addr) == 0))
302 			return (EADDRNOTAVAIL);
303 		rp->risop_isop.isop_sladdr = *addr;
304 		rp->risop_rcb.rcb_laddr = (struct sockaddr *)
305 			(rp->risop_isop.isop_laddr = &rp->risop_isop.isop_sladdr);
306 		return (0);
307 	    }
308 	case PRU_CONNECT:
309 	    {
310 		struct sockaddr_iso *addr = mtod(nam, struct sockaddr_iso *);
311 
312 		if ((nam->m_len > sizeof(*addr)) || (addr->siso_len > sizeof(*addr)))
313 			return (EINVAL);
314 		if (ifnet == 0)
315 			return (EADDRNOTAVAIL);
316 		if (addr->siso_family != AF_ISO)
317 		rp->risop_isop.isop_sfaddr = *addr;
318 		rp->risop_rcb.rcb_faddr = (struct sockaddr *)
319 			(rp->risop_isop.isop_faddr = &rp->risop_isop.isop_sfaddr);
320 		soisconnected(so);
321 		return (0);
322 	    }
323 	}
324 	error =  raw_usrreq(so, req, m, nam, rights, control);
325 
326 	if (error && req == PRU_ATTACH && so->so_pcb)
327 		free((caddr_t)rp, M_PCB);
328 	return (error);
329 }
330