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