xref: /f-stack/freebsd/net/raw_usrreq.c (revision 22ce4aff)
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
raw_init(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
raw_input(struct mbuf * m0,struct sockproto * proto,struct sockaddr * src)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
raw_input_ext(struct mbuf * m0,struct sockproto * proto,struct sockaddr * src,raw_input_cb_fn cb)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 					/* should notify about lost packet */
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 			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
raw_ctlinput(int cmd,struct sockaddr * arg,void * dummy)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
raw_uabort(struct socket * so)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
raw_uclose(struct socket * so)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
raw_uattach(struct socket * so,int proto,struct thread * td)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
raw_ubind(struct socket * so,struct sockaddr * nam,struct thread * td)173 raw_ubind(struct socket *so, struct sockaddr *nam, struct thread *td)
174 {
175 
176 	return (EINVAL);
177 }
178 
179 static int
raw_uconnect(struct socket * so,struct sockaddr * nam,struct thread * td)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
raw_udetach(struct socket * so)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
raw_udisconnect(struct socket * so)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
raw_upeeraddr(struct socket * so,struct sockaddr ** nam)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
raw_usend(struct socket * so,int flags,struct mbuf * m,struct sockaddr * nam,struct mbuf * control,struct thread * td)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
raw_ushutdown(struct socket * so)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
raw_usockaddr(struct socket * so,struct sockaddr ** nam)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 };
278