]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/net/raw_usrreq.c
Add UPDATING entries and bump version.
[FreeBSD/FreeBSD.git] / sys / net / raw_usrreq.c
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1980, 1986, 1993
5  *      The Regents of the University of California.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  *      @(#)raw_usrreq.c        8.1 (Berkeley) 6/10/93
33  * $FreeBSD$
34  */
35
36 #include <sys/param.h>
37 #include <sys/kernel.h>
38 #include <sys/lock.h>
39 #include <sys/malloc.h>
40 #include <sys/mbuf.h>
41 #include <sys/mutex.h>
42 #include <sys/priv.h>
43 #include <sys/protosw.h>
44 #include <sys/signalvar.h>
45 #include <sys/socket.h>
46 #include <sys/socketvar.h>
47 #include <sys/sx.h>
48 #include <sys/systm.h>
49
50 #include <net/if.h>
51 #include <net/vnet.h>
52 #include <net/raw_cb.h>
53
54 MTX_SYSINIT(rawcb_mtx, &rawcb_mtx, "rawcb", MTX_DEF);
55
56 /*
57  * Initialize raw connection block q.
58  */
59 void
60 raw_init(void)
61 {
62
63         LIST_INIT(&V_rawcb_list);
64 }
65
66 /*
67  * Raw protocol input routine.  Find the socket associated with the packet(s)
68  * and move them over.  If nothing exists for this packet, drop it.
69  */
70 /*
71  * Raw protocol interface.
72  */
73 void
74 raw_input(struct mbuf *m0, struct sockproto *proto, struct sockaddr *src)
75 {
76
77         return (raw_input_ext(m0, proto, src, NULL));
78 }
79
80 void
81 raw_input_ext(struct mbuf *m0, struct sockproto *proto, struct sockaddr *src,
82     raw_input_cb_fn cb)
83 {
84         struct rawcb *rp;
85         struct mbuf *m = m0;
86         struct socket *last;
87
88         last = NULL;
89         mtx_lock(&rawcb_mtx);
90         LIST_FOREACH(rp, &V_rawcb_list, list) {
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                 if (cb != NULL && (*cb)(m, proto, src, rp) != 0)
97                         continue;
98                 if (last) {
99                         struct mbuf *n;
100                         n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
101                         if (n) {
102                                 if (sbappendaddr(&last->so_rcv, src,
103                                     n, (struct mbuf *)0) == 0) {
104                                         soroverflow(last);
105                                         m_freem(n);
106                                 } else
107                                         sorwakeup(last);
108                         }
109                 }
110                 last = rp->rcb_socket;
111         }
112         if (last) {
113                 if (sbappendaddr(&last->so_rcv, src,
114                     m, (struct mbuf *)0) == 0) {
115                         soroverflow(last);
116                         m_freem(m);
117                 } else
118                         sorwakeup(last);
119         } else
120                 m_freem(m);
121         mtx_unlock(&rawcb_mtx);
122 }
123
124 /*ARGSUSED*/
125 void
126 raw_ctlinput(int cmd, struct sockaddr *arg, void *dummy)
127 {
128
129         if (cmd < 0 || cmd >= PRC_NCMDS)
130                 return;
131         /* INCOMPLETE */
132 }
133
134 static void
135 raw_uabort(struct socket *so)
136 {
137
138         KASSERT(sotorawcb(so) != NULL, ("raw_uabort: rp == NULL"));
139
140         soisdisconnected(so);
141 }
142
143 static void
144 raw_uclose(struct socket *so)
145 {
146
147         KASSERT(sotorawcb(so) != NULL, ("raw_uabort: rp == NULL"));
148
149         soisdisconnected(so);
150 }
151
152 /* pru_accept is EOPNOTSUPP */
153
154 static int
155 raw_uattach(struct socket *so, int proto, struct thread *td)
156 {
157         int error;
158
159         /*
160          * Implementors of raw sockets will already have allocated the PCB,
161          * so it must be non-NULL here.
162          */
163         KASSERT(sotorawcb(so) != NULL, ("raw_uattach: so_pcb == NULL"));
164
165         if (td != NULL) {
166                 error = priv_check(td, PRIV_NET_RAW);
167                 if (error)
168                         return (error);
169         }
170         return (raw_attach(so, proto));
171 }
172
173 static int
174 raw_ubind(struct socket *so, struct sockaddr *nam, struct thread *td)
175 {
176
177         return (EINVAL);
178 }
179
180 static int
181 raw_uconnect(struct socket *so, struct sockaddr *nam, struct thread *td)
182 {
183
184         return (EINVAL);
185 }
186
187 /* pru_connect2 is EOPNOTSUPP */
188 /* pru_control is EOPNOTSUPP */
189
190 static void
191 raw_udetach(struct socket *so)
192 {
193         struct rawcb *rp = sotorawcb(so);
194
195         KASSERT(rp != NULL, ("raw_udetach: rp == NULL"));
196
197         raw_detach(rp);
198 }
199
200 static int
201 raw_udisconnect(struct socket *so)
202 {
203
204         KASSERT(sotorawcb(so) != NULL, ("raw_udisconnect: rp == NULL"));
205
206         return (ENOTCONN);
207 }
208
209 /* pru_listen is EOPNOTSUPP */
210
211 static int
212 raw_upeeraddr(struct socket *so, struct sockaddr **nam)
213 {
214
215         KASSERT(sotorawcb(so) != NULL, ("raw_upeeraddr: rp == NULL"));
216
217         return (ENOTCONN);
218 }
219
220 /* pru_rcvd is EOPNOTSUPP */
221 /* pru_rcvoob is EOPNOTSUPP */
222
223 static int
224 raw_usend(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
225     struct mbuf *control, struct thread *td)
226 {
227
228         KASSERT(sotorawcb(so) != NULL, ("raw_usend: rp == NULL"));
229
230         if ((flags & PRUS_OOB) || (control && control->m_len)) {
231                 if (m != NULL)
232                         m_freem(m);
233                 if (control != NULL)
234                         m_freem(control);
235                 return (EOPNOTSUPP);
236         }
237
238         /*
239          * For historical (bad?) reasons, we effectively ignore the address
240          * argument to sendto(2).  Perhaps we should return an error instead?
241          */
242         return ((*so->so_proto->pr_output)(m, so));
243 }
244
245 /* pru_sense is null */
246
247 static int
248 raw_ushutdown(struct socket *so)
249 {
250
251         KASSERT(sotorawcb(so) != NULL, ("raw_ushutdown: rp == NULL"));
252
253         socantsendmore(so);
254         return (0);
255 }
256
257 static int
258 raw_usockaddr(struct socket *so, struct sockaddr **nam)
259 {
260
261         KASSERT(sotorawcb(so) != NULL, ("raw_usockaddr: rp == NULL"));
262
263         return (EINVAL);
264 }
265
266 struct pr_usrreqs raw_usrreqs = {
267         .pru_abort =            raw_uabort,
268         .pru_attach =           raw_uattach,
269         .pru_bind =             raw_ubind,
270         .pru_connect =          raw_uconnect,
271         .pru_detach =           raw_udetach, 
272         .pru_disconnect =       raw_udisconnect,
273         .pru_peeraddr =         raw_upeeraddr,
274         .pru_send =             raw_usend,
275         .pru_shutdown =         raw_ushutdown,
276         .pru_sockaddr =         raw_usockaddr,
277         .pru_close =            raw_uclose,
278 };