Correct BSD License clause numbering from 1-2-4 to 1-2-3.
[dragonfly.git] / sys / net / raw_usrreq.c
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  * $DragonFly: src/sys/net/raw_usrreq.c,v 1.14 2007/06/24 20:00:00 dillon Exp $
32  */
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/mbuf.h>
37 #include <sys/proc.h>
38 #include <sys/priv.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
48
49 static struct lwkt_token raw_token = LWKT_TOKEN_INITIALIZER(raw_token);
50
51 /*
52  * Initialize raw connection block q.
53  */
54 void
55 raw_init(void)
56 {
57         LIST_INIT(&rawcb_list);
58 }
59
60 /************************************************************************
61  *                       RAW PROTOCOL INTERFACE                         *
62  ************************************************************************/
63
64 /*
65  * Raw protocol input routine.  Find the socket associated with the packet(s)
66  * and move them over.  If nothing exists for this packet, drop it.  This
67  * routine is indirect called via rts_input() and will be serialized on
68  * cpu 0.
69  *
70  * Most other raw protocol interface functions are also serialized XXX.
71  */
72 void
73 raw_input(struct mbuf *m0, const struct sockproto *proto,
74           const struct sockaddr *src, const struct sockaddr *dst,
75           const struct rawcb *skip)
76 {
77         struct rawcb *rp;
78         struct mbuf *m = m0;
79         struct socket *last;
80
81         lwkt_gettoken(&raw_token);
82
83         last = NULL;
84         LIST_FOREACH(rp, &rawcb_list, list) {
85                 if (rp == skip)
86                         continue;
87                 if (rp->rcb_proto.sp_family != proto->sp_family)
88                         continue;
89                 if (rp->rcb_proto.sp_protocol  &&
90                     rp->rcb_proto.sp_protocol != proto->sp_protocol)
91                         continue;
92                 /*
93                  * We assume the lower level routines have
94                  * placed the address in a canonical format
95                  * suitable for a structure comparison.
96                  *
97                  * Note that if the lengths are not the same
98                  * the comparison will fail at the first byte.
99                  */
100                 if (rp->rcb_laddr && !sa_equal(rp->rcb_laddr, dst))
101                         continue;
102                 if (rp->rcb_faddr && !sa_equal(rp->rcb_faddr, src))
103                         continue;
104                 if (last) {
105                         struct mbuf *n;
106
107                         n = m_copypacket(m, MB_DONTWAIT);
108                         if (n != NULL) {
109                                 lwkt_gettoken(&last->so_rcv.ssb_token);
110                                 if (ssb_appendaddr(&last->so_rcv, src, n,
111                                                  NULL) == 0) {
112                                         /* should notify about lost packet */
113                                         m_freem(n);
114                                 } else {
115                                         sorwakeup(last);
116                                 }
117                                 lwkt_reltoken(&last->so_rcv.ssb_token);
118                         }
119                 }
120                 last = rp->rcb_socket;
121         }
122         if (last) {
123                 lwkt_gettoken(&last->so_rcv.ssb_token);
124                 if (ssb_appendaddr(&last->so_rcv, src, m, NULL) == 0)
125                         m_freem(m);
126                 else
127                         sorwakeup(last);
128                 lwkt_reltoken(&last->so_rcv.ssb_token);
129         } else {
130                 m_freem(m);
131         }
132         lwkt_reltoken(&raw_token);
133 }
134
135 /*
136  * nm_cmd, nm_arg, nm_extra
137  */
138 void
139 raw_ctlinput(netmsg_t msg)
140 {
141         int error = 0;
142
143         if (msg->ctlinput.nm_cmd < 0 || msg->ctlinput.nm_cmd > PRC_NCMDS)
144                 ;
145         lwkt_replymsg(&msg->lmsg, error);
146 }
147
148 /*
149  * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
150  *       will sofree() it when we return.
151  */
152 static void
153 raw_uabort(netmsg_t msg)
154 {
155         struct rawcb *rp = sotorawcb(msg->base.nm_so);
156         int error;
157
158         if (rp) {
159                 raw_disconnect(rp);
160                 soisdisconnected(msg->base.nm_so);
161                 error = 0;
162         } else {
163                 error = EINVAL;
164         }
165         lwkt_replymsg(&msg->lmsg, error);
166 }
167
168 /* pru_accept is EOPNOTSUPP */
169
170 static void
171 raw_uattach(netmsg_t msg)
172 {
173         struct socket *so = msg->base.nm_so;
174         int proto = msg->attach.nm_proto;
175         struct pru_attach_info *ai = msg->attach.nm_ai;
176         struct rawcb *rp;
177         int error;
178
179         rp = sotorawcb(so);
180         if (rp) {
181                 error = priv_check_cred(ai->p_ucred, PRIV_ROOT, NULL_CRED_OKAY);
182                 if (error == 0)
183                         error = raw_attach(so, proto, ai->sb_rlimit);
184         } else {
185                 error = EINVAL;
186         }
187         lwkt_replymsg(&msg->lmsg, error);
188 }
189
190 static void
191 raw_ubind(netmsg_t msg)
192 {
193         lwkt_replymsg(&msg->lmsg, EINVAL);
194 }
195
196 static void
197 raw_uconnect(netmsg_t msg)
198 {
199         lwkt_replymsg(&msg->lmsg, EINVAL);
200 }
201
202 /* pru_connect2 is EOPNOTSUPP */
203 /* pru_control is EOPNOTSUPP */
204
205 static void
206 raw_udetach(netmsg_t msg)
207 {
208         struct rawcb *rp = sotorawcb(msg->base.nm_so);
209         int error;
210
211         if (rp) {
212                 raw_detach(rp);
213                 error = 0;
214         } else {
215                 error = EINVAL;
216         }
217         lwkt_replymsg(&msg->lmsg, error);
218 }
219
220 static void
221 raw_udisconnect(netmsg_t msg)
222 {
223         struct socket *so = msg->base.nm_so;
224         struct rawcb *rp;
225         int error;
226
227         rp = sotorawcb(so);
228         if (rp == NULL) {
229                 error = EINVAL;
230         } else if (rp->rcb_faddr == NULL) {
231                 error = ENOTCONN;
232         } else {
233                 soreference(so);
234                 raw_disconnect(rp);
235                 soisdisconnected(so);
236                 sofree(so);
237                 error = 0;
238         }
239         lwkt_replymsg(&msg->lmsg, error);
240 }
241
242 /* pru_listen is EOPNOTSUPP */
243
244 static void
245 raw_upeeraddr(netmsg_t msg)
246 {
247         struct rawcb *rp = sotorawcb(msg->base.nm_so);
248         int error;
249
250         if (rp == NULL) {
251                 error = EINVAL;
252         } else if (rp->rcb_faddr == NULL) {
253                 error = ENOTCONN;
254         } else {
255                 *msg->peeraddr.nm_nam = dup_sockaddr(rp->rcb_faddr);
256                 error = 0;
257         }
258         lwkt_replymsg(&msg->lmsg, error);
259 }
260
261 /* pru_rcvd is EOPNOTSUPP */
262 /* pru_rcvoob is EOPNOTSUPP */
263
264 static void
265 raw_usend(netmsg_t msg)
266 {
267         struct socket *so = msg->base.nm_so;
268         struct mbuf *m = msg->send.nm_m;
269         struct mbuf *control = msg->send.nm_control;
270         struct rawcb *rp = sotorawcb(so);
271         struct pr_output_info oi;
272         int flags = msg->send.nm_flags;
273         int error;
274
275         if (rp == NULL) {
276                 error = EINVAL;
277                 goto release;
278         }
279
280         if (flags & PRUS_OOB) {
281                 error = EOPNOTSUPP;
282                 goto release;
283         }
284
285         if (control && control->m_len) {
286                 error = EOPNOTSUPP;
287                 goto release;
288         }
289         if (msg->send.nm_addr) {
290                 if (rp->rcb_faddr) {
291                         error = EISCONN;
292                         goto release;
293                 }
294                 rp->rcb_faddr = msg->send.nm_addr;
295         } else if (rp->rcb_faddr == NULL) {
296                 error = ENOTCONN;
297                 goto release;
298         }
299         oi.p_pid = msg->send.nm_td->td_proc->p_pid;
300         error = (*so->so_proto->pr_output)(m, so, &oi);
301         m = NULL;
302         if (msg->send.nm_addr)
303                 rp->rcb_faddr = NULL;
304 release:
305         if (m != NULL)
306                 m_freem(m);
307         lwkt_replymsg(&msg->lmsg, error);
308 }
309
310 /* pru_sense is null */
311
312 static void
313 raw_ushutdown(netmsg_t msg)
314 {
315         struct rawcb *rp = sotorawcb(msg->base.nm_so);
316         int error;
317
318         if (rp) {
319                 socantsendmore(msg->base.nm_so);
320                 error = 0;
321         } else {
322                 error = EINVAL;
323         }
324         lwkt_replymsg(&msg->lmsg, error);
325 }
326
327 static void
328 raw_usockaddr(netmsg_t msg)
329 {
330         struct rawcb *rp = sotorawcb(msg->base.nm_so);
331         int error;
332
333         if (rp == NULL) {
334                 error = EINVAL;
335         } else if (rp->rcb_laddr == NULL) {
336                 error = EINVAL;
337         } else {
338                 *msg->sockaddr.nm_nam = dup_sockaddr(rp->rcb_laddr);
339                 error = 0;
340         }
341         lwkt_replymsg(&msg->lmsg, error);
342 }
343
344 struct pr_usrreqs raw_usrreqs = {
345         .pru_abort = raw_uabort,
346         .pru_accept = pr_generic_notsupp,
347         .pru_attach = raw_uattach,
348         .pru_bind = raw_ubind,
349         .pru_connect = raw_uconnect,
350         .pru_connect2 = pr_generic_notsupp,
351         .pru_control = pr_generic_notsupp,
352         .pru_detach = raw_udetach, 
353         .pru_disconnect = raw_udisconnect,
354         .pru_listen = pr_generic_notsupp,
355         .pru_peeraddr = raw_upeeraddr,
356         .pru_rcvd = pr_generic_notsupp,
357         .pru_rcvoob = pr_generic_notsupp,
358         .pru_send = raw_usend,
359         .pru_sense = pru_sense_null,
360         .pru_shutdown = raw_ushutdown,
361         .pru_sockaddr = raw_usockaddr,
362         .pru_sosend = sosend,
363         .pru_soreceive = soreceive
364 };