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