nrelease - fix/improve livecd
[dragonfly.git] / sys / net / raw_usrreq.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 1980, 1986, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * @(#)raw_usrreq.c 8.1 (Berkeley) 6/10/93
30 * $FreeBSD: src/sys/net/raw_usrreq.c,v 1.18 1999/08/28 00:48:28 peter Exp $
31 */
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/malloc.h>
36#include <sys/mbuf.h>
37#include <sys/proc.h>
38#include <sys/caps.h>
39#include <sys/protosw.h>
40#include <sys/socket.h>
41#include <sys/socketvar.h>
42
43#include <sys/socketvar2.h>
44#include <sys/msgport2.h>
45
46#include <net/raw_cb.h>
47#include <net/netisr2.h>
48
49/*
50 * Except from the raw_init(), rest of interfaces must be called
51 * from netisr0.
52 */
53
54/*
55 * Initialize raw connection block q.
56 */
57void
58raw_init(void)
59{
60 LIST_INIT(&rawcb_list);
61}
62
63/************************************************************************
64 * RAW PROTOCOL INTERFACE *
65 ************************************************************************/
66
67/*
68 * Raw protocol input routine. Find the socket associated with the packet(s)
69 * and move them over. If nothing exists for this packet, drop it. This
70 * routine is indirect called via rts_input() and will be serialized on
71 * cpu 0.
72 *
73 * Most other raw protocol interface functions are also serialized XXX.
74 */
75void
76raw_input(struct mbuf *m0, const struct sockproto *proto,
77 const struct sockaddr *src, const struct sockaddr *dst,
78 const struct rawcb *skip)
79{
80 struct rawcb *rp;
81 struct mbuf *m = m0;
82 struct socket *last;
83
84 ASSERT_NETISR0;
85
86 last = NULL;
87
88 LIST_FOREACH(rp, &rawcb_list, list) {
89 if (rp == skip)
90 continue;
91 if (rp->rcb_proto.sp_family != proto->sp_family)
92 continue;
93 if (rp->rcb_proto.sp_protocol &&
94 rp->rcb_proto.sp_protocol != proto->sp_protocol)
95 continue;
96 /*
97 * We assume the lower level routines have
98 * placed the address in a canonical format
99 * suitable for a structure comparison.
100 *
101 * Note that if the lengths are not the same
102 * the comparison will fail at the first byte.
103 */
104 if (rp->rcb_laddr && !sa_equal(rp->rcb_laddr, dst))
105 continue;
106 if (rp->rcb_faddr && !sa_equal(rp->rcb_faddr, src))
107 continue;
108 /* Run any filtering that may have been installed. */
109 if (rp->rcb_filter != NULL && rp->rcb_filter(m, proto, rp) != 0)
110 continue;
111 if (last) {
112 struct mbuf *n;
113
114 n = m_copypacket(m, M_NOWAIT);
115 if (n != NULL) {
116 lwkt_gettoken(&last->so_rcv.ssb_token);
117 if (ssb_appendaddr(&last->so_rcv, src, n,
118 NULL) == 0) {
119 m_freem(n);
120 soroverflow(last);
121 } else {
122 sorwakeup(last);
123 }
124 lwkt_reltoken(&last->so_rcv.ssb_token);
125 }
126 }
127 last = rp->rcb_socket;
128 }
129 if (last) {
130 lwkt_gettoken(&last->so_rcv.ssb_token);
131 if (ssb_appendaddr(&last->so_rcv, src, m, NULL) == 0) {
132 m_freem(m);
133 soroverflow(last);
134 } else
135 sorwakeup(last);
136 lwkt_reltoken(&last->so_rcv.ssb_token);
137 } else {
138 m_freem(m);
139 }
140}
141
142/*
143 * nm_cmd, nm_arg, nm_extra
144 */
145void
146raw_ctlinput(netmsg_t msg)
147{
148 int error = 0;
149
150 ASSERT_NETISR0;
151
152 if (msg->ctlinput.nm_cmd < 0 || msg->ctlinput.nm_cmd > PRC_NCMDS) {
153 ; /* no-op */
154 }
155 lwkt_replymsg(&msg->lmsg, error);
156}
157
158/*
159 * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
160 * will sofree() it when we return.
161 */
162static void
163raw_uabort(netmsg_t msg)
164{
165 struct rawcb *rp = sotorawcb(msg->base.nm_so);
166 int error;
167
168 ASSERT_NETISR0;
169
170 if (rp) {
171 raw_disconnect(rp);
172 soisdisconnected(msg->base.nm_so);
173 error = 0;
174 } else {
175 error = EINVAL;
176 }
177 lwkt_replymsg(&msg->lmsg, error);
178}
179
180/* pru_accept is EOPNOTSUPP */
181
182static void
183raw_uattach(netmsg_t msg)
184{
185 struct socket *so = msg->base.nm_so;
186 int proto = msg->attach.nm_proto;
187 struct pru_attach_info *ai = msg->attach.nm_ai;
188 struct rawcb *rp;
189 int error;
190
191 ASSERT_NETISR0;
192
193 rp = sotorawcb(so);
194 if (rp) {
195 error = caps_priv_check(ai->p_ucred, SYSCAP_RESTRICTEDROOT |
196 __SYSCAP_NULLCRED);
197 if (error == 0)
198 error = raw_attach(so, proto, ai->sb_rlimit);
199 } else {
200 error = EINVAL;
201 }
202 lwkt_replymsg(&msg->lmsg, error);
203}
204
205static void
206raw_ubind(netmsg_t msg)
207{
208 ASSERT_NETISR0;
209 lwkt_replymsg(&msg->lmsg, EINVAL);
210}
211
212static void
213raw_uconnect(netmsg_t msg)
214{
215 ASSERT_NETISR0;
216 lwkt_replymsg(&msg->lmsg, EINVAL);
217}
218
219/* pru_connect2 is EOPNOTSUPP */
220/* pru_control is EOPNOTSUPP */
221
222static void
223raw_udetach(netmsg_t msg)
224{
225 struct rawcb *rp = sotorawcb(msg->base.nm_so);
226 int error;
227
228 ASSERT_NETISR0;
229
230 if (rp) {
231 raw_detach(rp);
232 error = 0;
233 } else {
234 error = EINVAL;
235 }
236 lwkt_replymsg(&msg->lmsg, error);
237}
238
239static void
240raw_udisconnect(netmsg_t msg)
241{
242 struct socket *so = msg->base.nm_so;
243 struct rawcb *rp;
244 int error;
245
246 ASSERT_NETISR0;
247
248 rp = sotorawcb(so);
249 if (rp == NULL) {
250 error = EINVAL;
251 } else if (rp->rcb_faddr == NULL) {
252 error = ENOTCONN;
253 } else {
254 soreference(so);
255 raw_disconnect(rp);
256 soisdisconnected(so);
257 sofree(so);
258 error = 0;
259 }
260 lwkt_replymsg(&msg->lmsg, error);
261}
262
263/* pru_listen is EOPNOTSUPP */
264
265static void
266raw_upeeraddr(netmsg_t msg)
267{
268 struct rawcb *rp = sotorawcb(msg->base.nm_so);
269 int error;
270
271 ASSERT_NETISR0;
272
273 if (rp == NULL) {
274 error = EINVAL;
275 } else if (rp->rcb_faddr == NULL) {
276 error = ENOTCONN;
277 } else {
278 *msg->peeraddr.nm_nam = dup_sockaddr(rp->rcb_faddr);
279 error = 0;
280 }
281 lwkt_replymsg(&msg->lmsg, error);
282}
283
284/* pru_rcvd is EOPNOTSUPP */
285/* pru_rcvoob is EOPNOTSUPP */
286
287static void
288raw_usend(netmsg_t msg)
289{
290 struct socket *so = msg->base.nm_so;
291 struct mbuf *m = msg->send.nm_m;
292 struct mbuf *control = msg->send.nm_control;
293 struct rawcb *rp = sotorawcb(so);
294 struct pr_output_info oi;
295 int flags = msg->send.nm_flags;
296 int error;
297
298 ASSERT_NETISR0;
299
300 if (rp == NULL) {
301 error = EINVAL;
302 goto release;
303 }
304
305 if (flags & PRUS_OOB) {
306 error = EOPNOTSUPP;
307 goto release;
308 }
309
310 if (control && control->m_len) {
311 error = EOPNOTSUPP;
312 goto release;
313 }
314 if (msg->send.nm_addr) {
315 if (rp->rcb_faddr) {
316 error = EISCONN;
317 goto release;
318 }
319 rp->rcb_faddr = msg->send.nm_addr;
320 } else if (rp->rcb_faddr == NULL) {
321 error = ENOTCONN;
322 goto release;
323 }
324 oi.p_pid = msg->send.nm_td->td_proc->p_pid;
325 error = (*so->so_proto->pr_output)(m, so, &oi);
326 m = NULL;
327 if (msg->send.nm_addr)
328 rp->rcb_faddr = NULL;
329release:
330 if (m != NULL)
331 m_freem(m);
332 lwkt_replymsg(&msg->lmsg, error);
333}
334
335/* pru_sense is null */
336
337static void
338raw_ushutdown(netmsg_t msg)
339{
340 struct rawcb *rp = sotorawcb(msg->base.nm_so);
341 int error;
342
343 ASSERT_NETISR0;
344
345 if (rp) {
346 socantsendmore(msg->base.nm_so);
347 error = 0;
348 } else {
349 error = EINVAL;
350 }
351 lwkt_replymsg(&msg->lmsg, error);
352}
353
354static void
355raw_usockaddr(netmsg_t msg)
356{
357 struct rawcb *rp = sotorawcb(msg->base.nm_so);
358 int error;
359
360 ASSERT_NETISR0;
361
362 if (rp == NULL) {
363 error = EINVAL;
364 } else if (rp->rcb_laddr == NULL) {
365 error = EINVAL;
366 } else {
367 *msg->sockaddr.nm_nam = dup_sockaddr(rp->rcb_laddr);
368 error = 0;
369 }
370 lwkt_replymsg(&msg->lmsg, error);
371}
372
373struct pr_usrreqs raw_usrreqs = {
374 .pru_abort = raw_uabort,
375 .pru_accept = pr_generic_notsupp,
376 .pru_attach = raw_uattach,
377 .pru_bind = raw_ubind,
378 .pru_connect = raw_uconnect,
379 .pru_connect2 = pr_generic_notsupp,
380 .pru_control = pr_generic_notsupp,
381 .pru_detach = raw_udetach,
382 .pru_disconnect = raw_udisconnect,
383 .pru_listen = pr_generic_notsupp,
384 .pru_peeraddr = raw_upeeraddr,
385 .pru_rcvd = pr_generic_notsupp,
386 .pru_rcvoob = pr_generic_notsupp,
387 .pru_send = raw_usend,
388 .pru_sense = pru_sense_null,
389 .pru_shutdown = raw_ushutdown,
390 .pru_sockaddr = raw_usockaddr,
391 .pru_sosend = sosend,
392 .pru_soreceive = soreceive
393};