xref: /freebsd-13.1/sys/net/raw_usrreq.c (revision f4527134)
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 					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
raw_ctlinput(int cmd,struct sockaddr * arg,void * dummy)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
raw_uabort(struct socket * so)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
raw_uclose(struct socket * so)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
raw_uattach(struct socket * so,int proto,struct thread * td)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
raw_ubind(struct socket * so,struct sockaddr * nam,struct thread * td)174 raw_ubind(struct socket *so, struct sockaddr *nam, struct thread *td)
175 {
176 
177 	return (EINVAL);
178 }
179 
180 static int
raw_uconnect(struct socket * so,struct sockaddr * nam,struct thread * td)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
raw_udetach(struct socket * so)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
raw_udisconnect(struct socket * so)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
raw_upeeraddr(struct socket * so,struct sockaddr ** nam)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
raw_usend(struct socket * so,int flags,struct mbuf * m,struct sockaddr * nam,struct mbuf * control,struct thread * td)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
raw_ushutdown(struct socket * so)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
raw_usockaddr(struct socket * so,struct sockaddr ** nam)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 };
279