xref: /csrg-svn/sys/net/raw_usrreq.c (revision 25221)
1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  *
6  *	@(#)raw_usrreq.c	6.9 (Berkeley) 10/17/85
7  */
8 
9 #include "param.h"
10 #include "mbuf.h"
11 #include "domain.h"
12 #include "protosw.h"
13 #include "socket.h"
14 #include "socketvar.h"
15 #include "errno.h"
16 
17 #include "if.h"
18 #include "route.h"
19 #include "netisr.h"
20 #include "raw_cb.h"
21 
22 #include "../vax/mtpr.h"
23 
24 /*
25  * Initialize raw connection block q.
26  */
27 raw_init()
28 {
29 
30 	rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
31 	rawintrq.ifq_maxlen = IFQ_MAXLEN;
32 }
33 
34 /*
35  * Raw protocol interface.
36  */
37 raw_input(m0, proto, src, dst)
38 	struct mbuf *m0;
39 	struct sockproto *proto;
40 	struct sockaddr *src, *dst;
41 {
42 	register struct mbuf *m;
43 	struct raw_header *rh;
44 	int s;
45 
46 	/*
47 	 * Rip off an mbuf for a generic header.
48 	 */
49 	m = m_get(M_DONTWAIT, MT_HEADER);
50 	if (m == 0) {
51 		m_freem(m0);
52 		return;
53 	}
54 	m->m_next = m0;
55 	m->m_len = sizeof(struct raw_header);
56 	rh = mtod(m, struct raw_header *);
57 	rh->raw_dst = *dst;
58 	rh->raw_src = *src;
59 	rh->raw_proto = *proto;
60 
61 	/*
62 	 * Header now contains enough info to decide
63 	 * which socket to place packet in (if any).
64 	 * Queue it up for the raw protocol process
65 	 * running at software interrupt level.
66 	 */
67 	s = splimp();
68 	if (IF_QFULL(&rawintrq))
69 		m_freem(m);
70 	else
71 		IF_ENQUEUE(&rawintrq, m);
72 	splx(s);
73 	schednetisr(NETISR_RAW);
74 }
75 
76 /*
77  * Raw protocol input routine.  Process packets entered
78  * into the queue at interrupt time.  Find the socket
79  * associated with the packet(s) and move them over.  If
80  * nothing exists for this packet, drop it.
81  */
82 rawintr()
83 {
84 	int s;
85 	struct mbuf *m;
86 	register struct rawcb *rp;
87 	register struct raw_header *rh;
88 	struct socket *last;
89 
90 next:
91 	s = splimp();
92 	IF_DEQUEUE(&rawintrq, m);
93 	splx(s);
94 	if (m == 0)
95 		return;
96 	rh = mtod(m, struct raw_header *);
97 	last = 0;
98 	for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
99 		if (rp->rcb_proto.sp_family != rh->raw_proto.sp_family)
100 			continue;
101 		if (rp->rcb_proto.sp_protocol  &&
102 		    rp->rcb_proto.sp_protocol != rh->raw_proto.sp_protocol)
103 			continue;
104 		/*
105 		 * We assume the lower level routines have
106 		 * placed the address in a canonical format
107 		 * suitable for a structure comparison.
108 		 */
109 #define equal(a1, a2) \
110 	(bcmp((caddr_t)&(a1), (caddr_t)&(a2), sizeof (struct sockaddr)) == 0)
111 		if ((rp->rcb_flags & RAW_LADDR) &&
112 		    !equal(rp->rcb_laddr, rh->raw_dst))
113 			continue;
114 		if ((rp->rcb_flags & RAW_FADDR) &&
115 		    !equal(rp->rcb_faddr, rh->raw_src))
116 			continue;
117 		if (last) {
118 			struct mbuf *n;
119 			if (n = m_copy(m->m_next, 0, (int)M_COPYALL)) {
120 				if (sbappendaddr(&last->so_rcv, &rh->raw_src,
121 				    n, (struct mbuf *)0) == 0)
122 					/* should notify about lost packet */
123 					m_freem(n);
124 				else
125 					sorwakeup(last);
126 			}
127 		}
128 		last = rp->rcb_socket;
129 	}
130 	if (last) {
131 		if (sbappendaddr(&last->so_rcv, &rh->raw_src,
132 		    m->m_next, (struct mbuf *)0) == 0)
133 			m_freem(m->m_next);
134 		else
135 			sorwakeup(last);
136 		(void) m_free(m);		/* header */
137 	} else
138 		m_freem(m);
139 	goto next;
140 }
141 
142 /*ARGSUSED*/
143 raw_ctlinput(cmd, arg)
144 	int cmd;
145 	caddr_t arg;
146 {
147 
148 	if (cmd < 0 || cmd > PRC_NCMDS)
149 		return;
150 	/* INCOMPLETE */
151 }
152 
153 /*ARGSUSED*/
154 raw_usrreq(so, req, m, nam, rights)
155 	struct socket *so;
156 	int req;
157 	struct mbuf *m, *nam, *rights;
158 {
159 	register struct rawcb *rp = sotorawcb(so);
160 	register int error = 0;
161 
162 	if (rights && rights->m_len) {
163 		error = EOPNOTSUPP;
164 		goto release;
165 	}
166 	if (rp == 0 && req != PRU_ATTACH) {
167 		error = EINVAL;
168 		goto release;
169 	}
170 	switch (req) {
171 
172 	/*
173 	 * Allocate a raw control block and fill in the
174 	 * necessary info to allow packets to be routed to
175 	 * the appropriate raw interface routine.
176 	 */
177 	case PRU_ATTACH:
178 		if ((so->so_state & SS_PRIV) == 0) {
179 			error = EACCES;
180 			break;
181 		}
182 		if (rp) {
183 			error = EINVAL;
184 			break;
185 		}
186 		error = raw_attach(so, (int)nam);
187 		break;
188 
189 	/*
190 	 * Destroy state just before socket deallocation.
191 	 * Flush data or not depending on the options.
192 	 */
193 	case PRU_DETACH:
194 		if (rp == 0) {
195 			error = ENOTCONN;
196 			break;
197 		}
198 		raw_detach(rp);
199 		break;
200 
201 	/*
202 	 * If a socket isn't bound to a single address,
203 	 * the raw input routine will hand it anything
204 	 * within that protocol family (assuming there's
205 	 * nothing else around it should go to).
206 	 */
207 	case PRU_CONNECT:
208 		if (rp->rcb_flags & RAW_FADDR) {
209 			error = EISCONN;
210 			break;
211 		}
212 		raw_connaddr(rp, nam);
213 		soisconnected(so);
214 		break;
215 
216 	case PRU_CONNECT2:
217 		error = EOPNOTSUPP;
218 		goto release;
219 
220 	case PRU_BIND:
221 		if (rp->rcb_flags & RAW_LADDR) {
222 			error = EINVAL;			/* XXX */
223 			break;
224 		}
225 		error = raw_bind(so, nam);
226 		break;
227 
228 	case PRU_DISCONNECT:
229 		if ((rp->rcb_flags & RAW_FADDR) == 0) {
230 			error = ENOTCONN;
231 			break;
232 		}
233 		if (rp->rcb_route.ro_rt)
234 			rtfree(rp->rcb_route.ro_rt);
235 		raw_disconnect(rp);
236 		soisdisconnected(so);
237 		break;
238 
239 	/*
240 	 * Mark the connection as being incapable of further input.
241 	 */
242 	case PRU_SHUTDOWN:
243 		socantsendmore(so);
244 		break;
245 
246 	/*
247 	 * Ship a packet out.  The appropriate raw output
248 	 * routine handles any massaging necessary.
249 	 */
250 	case PRU_SEND:
251 		if (nam) {
252 			if (rp->rcb_flags & RAW_FADDR) {
253 				error = EISCONN;
254 				break;
255 			}
256 			raw_connaddr(rp, nam);
257 		} else if ((rp->rcb_flags & RAW_FADDR) == 0) {
258 			error = ENOTCONN;
259 			break;
260 		}
261 		/*
262 		 * Check for routing.  If new foreign address, or
263 		 * no route presently in use, try to allocate new
264 		 * route.  On failure, just hand packet to output
265 		 * routine anyway in case it can handle it.
266 		 */
267 		if ((rp->rcb_flags & RAW_DONTROUTE) == 0)
268 			if (!equal(rp->rcb_faddr, rp->rcb_route.ro_dst) ||
269 			    rp->rcb_route.ro_rt == 0) {
270 				if (rp->rcb_route.ro_rt) {
271 					RTFREE(rp->rcb_route.ro_rt);
272 					rp->rcb_route.ro_rt = NULL;
273 				}
274 				rp->rcb_route.ro_dst = rp->rcb_faddr;
275 				rtalloc(&rp->rcb_route);
276 			}
277 		error = (*so->so_proto->pr_output)(m, so);
278 		m = NULL;
279 		if (nam)
280 			rp->rcb_flags &= ~RAW_FADDR;
281 		break;
282 
283 	case PRU_ABORT:
284 		raw_disconnect(rp);
285 		sofree(so);
286 		soisdisconnected(so);
287 		break;
288 
289 	case PRU_SENSE:
290 		/*
291 		 * stat: don't bother with a blocksize.
292 		 */
293 		return (0);
294 
295 	/*
296 	 * Not supported.
297 	 */
298 	case PRU_CONTROL:
299 	case PRU_RCVOOB:
300 	case PRU_RCVD:
301 		return(EOPNOTSUPP);
302 
303 	case PRU_LISTEN:
304 	case PRU_ACCEPT:
305 	case PRU_SENDOOB:
306 		error = EOPNOTSUPP;
307 		break;
308 
309 	case PRU_SOCKADDR:
310 		bcopy((caddr_t)&rp->rcb_laddr, mtod(nam, caddr_t),
311 		    sizeof (struct sockaddr));
312 		nam->m_len = sizeof (struct sockaddr);
313 		break;
314 
315 	case PRU_PEERADDR:
316 		bcopy((caddr_t)&rp->rcb_faddr, mtod(nam, caddr_t),
317 		    sizeof (struct sockaddr));
318 		nam->m_len = sizeof (struct sockaddr);
319 		break;
320 
321 	default:
322 		panic("raw_usrreq");
323 	}
324 release:
325 	if (m != NULL)
326 		m_freem(m);
327 	return (error);
328 }
329