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