]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/net/raw_usrreq.c
Teach if_smsc to get MAC from bootargs.
[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  */
34
35 #include <sys/param.h>
36 #include <sys/kernel.h>
37 #include <sys/lock.h>
38 #include <sys/malloc.h>
39 #include <sys/mbuf.h>
40 #include <sys/mutex.h>
41 #include <sys/priv.h>
42 #include <sys/protosw.h>
43 #include <sys/signalvar.h>
44 #include <sys/socket.h>
45 #include <sys/socketvar.h>
46 #include <sys/sx.h>
47 #include <sys/systm.h>
48
49 #include <net/if.h>
50 #include <net/vnet.h>
51 #include <net/raw_cb.h>
52
53 MTX_SYSINIT(rawcb_mtx, &rawcb_mtx, "rawcb", MTX_DEF);
54
55 /*
56  * Initialize raw connection block q.
57  */
58 void
59 raw_init(void)
60 {
61
62         LIST_INIT(&V_rawcb_list);
63 }
64
65 /*
66  * Raw protocol input routine.  Find the socket associated with the packet(s)
67  * and move them over.  If nothing exists for this packet, drop it.
68  */
69 /*
70  * Raw protocol interface.
71  */
72 void
73 raw_input(struct mbuf *m0, struct sockproto *proto, struct sockaddr *src)
74 {
75
76         return (raw_input_ext(m0, proto, src, NULL));
77 }
78
79 void
80 raw_input_ext(struct mbuf *m0, struct sockproto *proto, struct sockaddr *src,
81     raw_input_cb_fn cb)
82 {
83         struct rawcb *rp;
84         struct mbuf *m = m0;
85         struct socket *last;
86
87         last = NULL;
88         mtx_lock(&rawcb_mtx);
89         LIST_FOREACH(rp, &V_rawcb_list, list) {
90                 if (rp->rcb_proto.sp_family != proto->sp_family)
91                         continue;
92                 if (rp->rcb_proto.sp_protocol  &&
93                     rp->rcb_proto.sp_protocol != proto->sp_protocol)
94                         continue;
95                 if (cb != NULL && (*cb)(m, proto, src, rp) != 0)
96                         continue;
97                 if (last) {
98                         struct mbuf *n;
99                         n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
100                         if (n) {
101                                 if (sbappendaddr(&last->so_rcv, src,
102                                     n, (struct mbuf *)0) == 0) {
103                                         soroverflow(last);
104                                         m_freem(n);
105                                 } else
106                                         sorwakeup(last);
107                         }
108                 }
109                 last = rp->rcb_socket;
110         }
111         if (last) {
112                 if (sbappendaddr(&last->so_rcv, src,
113                     m, (struct mbuf *)0) == 0) {
114                         soroverflow(last);
115                         m_freem(m);
116                 } else
117                         sorwakeup(last);
118         } else
119                 m_freem(m);
120         mtx_unlock(&rawcb_mtx);
121 }
122
123 /*ARGSUSED*/
124 void
125 raw_ctlinput(int cmd, struct sockaddr *arg, void *dummy)
126 {
127
128         if (cmd < 0 || cmd >= PRC_NCMDS)
129                 return;
130         /* INCOMPLETE */
131 }
132
133 static void
134 raw_uabort(struct socket *so)
135 {
136
137         KASSERT(sotorawcb(so) != NULL, ("raw_uabort: rp == NULL"));
138
139         soisdisconnected(so);
140 }
141
142 static void
143 raw_uclose(struct socket *so)
144 {
145
146         KASSERT(sotorawcb(so) != NULL, ("raw_uabort: rp == NULL"));
147
148         soisdisconnected(so);
149 }
150
151 /* pru_accept is EOPNOTSUPP */
152
153 static int
154 raw_uattach(struct socket *so, int proto, struct thread *td)
155 {
156         int error;
157
158         /*
159          * Implementors of raw sockets will already have allocated the PCB,
160          * so it must be non-NULL here.
161          */
162         KASSERT(sotorawcb(so) != NULL, ("raw_uattach: so_pcb == NULL"));
163
164         if (td != NULL) {
165                 error = priv_check(td, PRIV_NET_RAW);
166                 if (error)
167                         return (error);
168         }
169         return (raw_attach(so, proto));
170 }
171
172 static int
173 raw_ubind(struct socket *so, struct sockaddr *nam, struct thread *td)
174 {
175
176         return (EINVAL);
177 }
178
179 static int
180 raw_uconnect(struct socket *so, struct sockaddr *nam, struct thread *td)
181 {
182
183         return (EINVAL);
184 }
185
186 /* pru_connect2 is EOPNOTSUPP */
187 /* pru_control is EOPNOTSUPP */
188
189 static void
190 raw_udetach(struct socket *so)
191 {
192         struct rawcb *rp = sotorawcb(so);
193
194         KASSERT(rp != NULL, ("raw_udetach: rp == NULL"));
195
196         raw_detach(rp);
197 }
198
199 static int
200 raw_udisconnect(struct socket *so)
201 {
202
203         KASSERT(sotorawcb(so) != NULL, ("raw_udisconnect: rp == NULL"));
204
205         return (ENOTCONN);
206 }
207
208 /* pru_listen is EOPNOTSUPP */
209
210 static int
211 raw_upeeraddr(struct socket *so, struct sockaddr **nam)
212 {
213
214         KASSERT(sotorawcb(so) != NULL, ("raw_upeeraddr: rp == NULL"));
215
216         return (ENOTCONN);
217 }
218
219 /* pru_rcvd is EOPNOTSUPP */
220 /* pru_rcvoob is EOPNOTSUPP */
221
222 static int
223 raw_usend(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
224     struct mbuf *control, struct thread *td)
225 {
226
227         KASSERT(sotorawcb(so) != NULL, ("raw_usend: rp == NULL"));
228
229         if ((flags & PRUS_OOB) || (control && control->m_len)) {
230                 if (m != NULL)
231                         m_freem(m);
232                 if (control != NULL)
233                         m_freem(control);
234                 return (EOPNOTSUPP);
235         }
236
237         /*
238          * For historical (bad?) reasons, we effectively ignore the address
239          * argument to sendto(2).  Perhaps we should return an error instead?
240          */
241         return ((*so->so_proto->pr_output)(m, so));
242 }
243
244 /* pru_sense is null */
245
246 static int
247 raw_ushutdown(struct socket *so)
248 {
249
250         KASSERT(sotorawcb(so) != NULL, ("raw_ushutdown: rp == NULL"));
251
252         socantsendmore(so);
253         return (0);
254 }
255
256 static int
257 raw_usockaddr(struct socket *so, struct sockaddr **nam)
258 {
259
260         KASSERT(sotorawcb(so) != NULL, ("raw_usockaddr: rp == NULL"));
261
262         return (EINVAL);
263 }
264
265 struct pr_usrreqs raw_usrreqs = {
266         .pru_abort =            raw_uabort,
267         .pru_attach =           raw_uattach,
268         .pru_bind =             raw_ubind,
269         .pru_connect =          raw_uconnect,
270         .pru_detach =           raw_udetach, 
271         .pru_disconnect =       raw_udisconnect,
272         .pru_peeraddr =         raw_upeeraddr,
273         .pru_send =             raw_usend,
274         .pru_shutdown =         raw_ushutdown,
275         .pru_sockaddr =         raw_usockaddr,
276         .pru_close =            raw_uclose,
277 };