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