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