xref: /original-bsd/sys/netiso/clnp_raw.c (revision b4971bb3)
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.12 (Berkeley) 06/04/93
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 	raw_input(m, &rclnp_proto, (struct sockaddr *)src, (struct sockaddr *)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 rawisopcb		*rp = sotorawisopcb(so); /* ptr to raw cb */
112 	int						error;		/* return value of function */
113 	int						flags;		/* flags for clnp_output */
114 
115 	if (0 == (m0->m_flags & M_PKTHDR))
116 		return (EINVAL);
117 	/*
118 	 *	Set up src address. If user has bound socket to an address, use it.
119 	 *	Otherwise, do not specify src (clnp_output will fill it in).
120 	 */
121 	if (rp->risop_rcb.rcb_laddr) {
122 		if (rp->risop_isop.isop_sladdr.siso_family != AF_ISO) {
123 bad:
124 			m_freem(m0);
125 			return(EAFNOSUPPORT);
126 		}
127 	}
128 	/* set up dest address */
129 	if (rp->risop_rcb.rcb_faddr == 0)
130 		goto bad;
131 	rp->risop_isop.isop_sfaddr =
132 				*(struct sockaddr_iso *)rp->risop_rcb.rcb_faddr;
133 	rp->risop_isop.isop_faddr = &rp->risop_isop.isop_sfaddr;
134 
135 	/* get flags and ship it off */
136 	flags = rp->risop_flags & CLNP_VFLAGS;
137 
138 	error = clnp_output(m0, &rp->risop_isop, m0->m_pkthdr.len,
139 												flags|CLNP_NOCACHE);
140 
141 	return (error);
142 }
143 
144 /*
145  * FUNCTION:		rclnp_ctloutput
146  *
147  * PURPOSE:			Raw clnp socket option processing
148  *					All options are stored inside an mbuf.
149  *
150  * RETURNS:			success - 0
151  *					failure - unix error code
152  *
153  * SIDE EFFECTS:	If the options mbuf does not exist, it the mbuf passed
154  *					is used.
155  *
156  * NOTES:
157  */
158 rclnp_ctloutput(op, so, level, optname, m)
159 int				op;				/* type of operation */
160 struct socket	*so;			/* ptr to socket */
161 int 			level;			/* level of option */
162 int				optname;		/* name of option */
163 struct mbuf		**m;			/* ptr to ptr to option data */
164 {
165 	int						error = 0;
166 	register struct rawisopcb	*rp = sotorawisopcb(so);/* raw cb ptr */
167 
168 	IFDEBUG(D_CTLOUTPUT)
169 		printf("rclnp_ctloutput: op = x%x, level = x%x, name = x%x\n",
170 			op, level, optname);
171 		if (*m != NULL) {
172 			printf("rclnp_ctloutput: %d bytes of mbuf data\n", (*m)->m_len);
173 			dump_buf(mtod((*m), caddr_t), (*m)->m_len);
174 		}
175 	ENDDEBUG
176 
177 #ifdef SOL_NETWORK
178 	if (level != SOL_NETWORK)
179 		error = EINVAL;
180 	else switch (op) {
181 #else
182 	switch (op) {
183 #endif /* SOL_NETWORK */
184 		case PRCO_SETOPT:
185 			switch (optname) {
186 				case CLNPOPT_FLAGS: {
187 					u_short	usr_flags;
188 					/*
189 					 *	Insure that the data passed has exactly one short in it
190 					 */
191 					if ((*m == NULL) || ((*m)->m_len != sizeof(short))) {
192 						error = EINVAL;
193 						break;
194 					}
195 
196 					/*
197 					 *	Don't allow invalid flags to be set
198 					 */
199 					usr_flags = (*mtod((*m), short *));
200 
201 					if ((usr_flags & (CLNP_VFLAGS)) != usr_flags) {
202 						error = EINVAL;
203 					} else
204 						rp->risop_flags |= usr_flags;
205 
206 					} break;
207 
208 				case CLNPOPT_OPTS:
209 					if (error = clnp_set_opts(&rp->risop_isop.isop_options, m))
210 						break;
211 					rp->risop_isop.isop_optindex = m_get(M_WAIT, MT_SOOPTS);
212 					(void) clnp_opt_sanity(rp->risop_isop.isop_options,
213 						mtod(rp->risop_isop.isop_options, caddr_t),
214 						rp->risop_isop.isop_options->m_len,
215 						mtod(rp->risop_isop.isop_optindex,
216 							struct clnp_optidx *));
217 					break;
218 			}
219 			break;
220 
221 		case PRCO_GETOPT:
222 #ifdef notdef
223 			/* commented out to keep hi C quiet */
224 			switch (optname) {
225 				default:
226 					error = EINVAL;
227 					break;
228 			}
229 #endif /* notdef */
230 			break;
231 		default:
232 			error = EINVAL;
233 			break;
234 	}
235 	if (op == PRCO_SETOPT) {
236 		/* note: m_freem does not barf is *m is NULL */
237 		m_freem(*m);
238 		*m = NULL;
239 	}
240 
241 	return error;
242 }
243 
244 /*ARGSUSED*/
245 clnp_usrreq(so, req, m, nam, control)
246 	register struct socket *so;
247 	int req;
248 	struct mbuf *m, *nam, *control;
249 {
250 	register int error = 0;
251 	register struct rawisopcb *rp = sotorawisopcb(so);
252 
253 	rp = sotorawisopcb(so);
254 	switch (req) {
255 
256 	case PRU_ATTACH:
257 		if (rp)
258 			panic("rip_attach");
259 		MALLOC(rp, struct rawisopcb *, sizeof *rp, M_PCB, M_WAITOK);
260 		if (rp == 0)
261 			return (ENOBUFS);
262 		bzero((caddr_t)rp, sizeof *rp);
263 		so->so_pcb = (caddr_t)rp;
264 		break;
265 
266 	case PRU_DETACH:
267 		if (rp == 0)
268 			panic("rip_detach");
269 		if (rp->risop_isop.isop_options)
270 			m_freem(rp->risop_isop.isop_options);
271 		if (rp->risop_isop.isop_route.ro_rt)
272 			RTFREE(rp->risop_isop.isop_route.ro_rt);
273 		if (rp->risop_rcb.rcb_laddr)
274 			rp->risop_rcb.rcb_laddr = 0;
275 		/* free clnp cached hdr if necessary */
276 		if (rp->risop_isop.isop_clnpcache != NULL) {
277 			struct clnp_cache *clcp =
278 				mtod(rp->risop_isop.isop_clnpcache, struct clnp_cache *);
279 			if (clcp->clc_hdr != NULL) {
280 				m_free(clcp->clc_hdr);
281 			}
282 			m_free(rp->risop_isop.isop_clnpcache);
283 		}
284 		if (rp->risop_isop.isop_optindex != NULL)
285 			m_free(rp->risop_isop.isop_optindex);
286 
287 		break;
288 
289 	case PRU_BIND:
290 	    {
291 		struct sockaddr_iso *addr = mtod(nam, struct sockaddr_iso *);
292 
293 		if (nam->m_len != sizeof(*addr))
294 			return (EINVAL);
295 		if ((ifnet == 0) ||
296 		    (addr->siso_family != AF_ISO) ||
297 		    (addr->siso_addr.isoa_len  &&
298 		     ifa_ifwithaddr((struct sockaddr *)addr) == 0))
299 			return (EADDRNOTAVAIL);
300 		rp->risop_isop.isop_sladdr = *addr;
301 		rp->risop_rcb.rcb_laddr = (struct sockaddr *)
302 			(rp->risop_isop.isop_laddr = &rp->risop_isop.isop_sladdr);
303 		return (0);
304 	    }
305 	case PRU_CONNECT:
306 	    {
307 		struct sockaddr_iso *addr = mtod(nam, struct sockaddr_iso *);
308 
309 		if ((nam->m_len > sizeof(*addr)) || (addr->siso_len > sizeof(*addr)))
310 			return (EINVAL);
311 		if (ifnet == 0)
312 			return (EADDRNOTAVAIL);
313 		if (addr->siso_family != AF_ISO)
314 		rp->risop_isop.isop_sfaddr = *addr;
315 		rp->risop_rcb.rcb_faddr = (struct sockaddr *)
316 			(rp->risop_isop.isop_faddr = &rp->risop_isop.isop_sfaddr);
317 		soisconnected(so);
318 		return (0);
319 	    }
320 	}
321 	error =  raw_usrreq(so, req, m, nam, control);
322 
323 	if (error && req == PRU_ATTACH && so->so_pcb)
324 		free((caddr_t)rp, M_PCB);
325 	return (error);
326 }
327