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