1139823Simp/*-
21541Srgrimes * Copyright (c) 1980, 1986, 1993
3180305Srwatson *	The Regents of the University of California.
4180305Srwatson * All rights reserved.
51541Srgrimes *
61541Srgrimes * Redistribution and use in source and binary forms, with or without
71541Srgrimes * modification, are permitted provided that the following conditions
81541Srgrimes * are met:
91541Srgrimes * 1. Redistributions of source code must retain the above copyright
101541Srgrimes *    notice, this list of conditions and the following disclaimer.
111541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
121541Srgrimes *    notice, this list of conditions and the following disclaimer in the
131541Srgrimes *    documentation and/or other materials provided with the distribution.
141541Srgrimes * 4. Neither the name of the University nor the names of its contributors
151541Srgrimes *    may be used to endorse or promote products derived from this software
161541Srgrimes *    without specific prior written permission.
171541Srgrimes *
181541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
191541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
201541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
211541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
221541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
231541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
241541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
251541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
261541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
271541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
281541Srgrimes * SUCH DAMAGE.
291541Srgrimes *
301541Srgrimes *	@(#)raw_usrreq.c	8.1 (Berkeley) 6/10/93
3150477Speter * $FreeBSD: releng/11.0/sys/net/raw_usrreq.c 298075 2016-04-15 17:30:33Z pfg $
321541Srgrimes */
331541Srgrimes
341541Srgrimes#include <sys/param.h>
35130514Srwatson#include <sys/kernel.h>
3695759Stanimura#include <sys/lock.h>
37126425Srwatson#include <sys/malloc.h>
381541Srgrimes#include <sys/mbuf.h>
39130387Srwatson#include <sys/mutex.h>
40164033Srwatson#include <sys/priv.h>
411541Srgrimes#include <sys/protosw.h>
4295759Stanimura#include <sys/signalvar.h>
431541Srgrimes#include <sys/socket.h>
441541Srgrimes#include <sys/socketvar.h>
4595759Stanimura#include <sys/sx.h>
4695759Stanimura#include <sys/systm.h>
471541Srgrimes
48183550Szec#include <net/if.h>
49257135Sglebius#include <net/vnet.h>
501541Srgrimes#include <net/raw_cb.h>
511541Srgrimes
52130514SrwatsonMTX_SYSINIT(rawcb_mtx, &rawcb_mtx, "rawcb", MTX_DEF);
53130514Srwatson
541541Srgrimes/*
551541Srgrimes * Initialize raw connection block q.
561541Srgrimes */
571541Srgrimesvoid
58180305Srwatsonraw_init(void)
591541Srgrimes{
60130514Srwatson
61181803Sbz	LIST_INIT(&V_rawcb_list);
621541Srgrimes}
631541Srgrimes
641541Srgrimes/*
65180305Srwatson * Raw protocol input routine.  Find the socket associated with the packet(s)
66180305Srwatson * and move them over.  If nothing exists for this packet, drop it.
671541Srgrimes */
681541Srgrimes/*
691541Srgrimes * Raw protocol interface.
701541Srgrimes */
711541Srgrimesvoid
72180385Srwatsonraw_input(struct mbuf *m0, struct sockproto *proto, struct sockaddr *src)
731541Srgrimes{
74225837Sbz
75225837Sbz	return (raw_input_ext(m0, proto, src, NULL));
76225837Sbz}
77225837Sbz
78225837Sbzvoid
79225837Sbzraw_input_ext(struct mbuf *m0, struct sockproto *proto, struct sockaddr *src,
80225837Sbz    raw_input_cb_fn cb)
81225837Sbz{
82180305Srwatson	struct rawcb *rp;
83180305Srwatson	struct mbuf *m = m0;
841541Srgrimes	struct socket *last;
851541Srgrimes
86298075Spfg	last = NULL;
87130514Srwatson	mtx_lock(&rawcb_mtx);
88181803Sbz	LIST_FOREACH(rp, &V_rawcb_list, list) {
891541Srgrimes		if (rp->rcb_proto.sp_family != proto->sp_family)
901541Srgrimes			continue;
911541Srgrimes		if (rp->rcb_proto.sp_protocol  &&
921541Srgrimes		    rp->rcb_proto.sp_protocol != proto->sp_protocol)
931541Srgrimes			continue;
94225837Sbz		if (cb != NULL && (*cb)(m, proto, src, rp) != 0)
95225837Sbz			continue;
961541Srgrimes		if (last) {
97107113Sluigi			struct mbuf *n;
98107113Sluigi			n = m_copy(m, 0, (int)M_COPYALL);
993443Sphk			if (n) {
1001541Srgrimes				if (sbappendaddr(&last->so_rcv, src,
101107113Sluigi				    n, (struct mbuf *)0) == 0)
1021541Srgrimes					/* should notify about lost packet */
1031541Srgrimes					m_freem(n);
104180305Srwatson				else
1051541Srgrimes					sorwakeup(last);
1061541Srgrimes			}
1071541Srgrimes		}
1081541Srgrimes		last = rp->rcb_socket;
1091541Srgrimes	}
1101541Srgrimes	if (last) {
111107113Sluigi		if (sbappendaddr(&last->so_rcv, src,
112107113Sluigi		    m, (struct mbuf *)0) == 0)
1131541Srgrimes			m_freem(m);
114180305Srwatson		else
1151541Srgrimes			sorwakeup(last);
1161541Srgrimes	} else
1171541Srgrimes		m_freem(m);
118130514Srwatson	mtx_unlock(&rawcb_mtx);
1191541Srgrimes}
1201541Srgrimes
1211541Srgrimes/*ARGSUSED*/
1221541Srgrimesvoid
123180305Srwatsonraw_ctlinput(int cmd, struct sockaddr *arg, void *dummy)
1241541Srgrimes{
1251541Srgrimes
126119995Sru	if (cmd < 0 || cmd >= PRC_NCMDS)
1271541Srgrimes		return;
1281541Srgrimes	/* INCOMPLETE */
1291541Srgrimes}
1301541Srgrimes
131157366Srwatsonstatic void
13225201Swollmanraw_uabort(struct socket *so)
1331541Srgrimes{
1341541Srgrimes
135180385Srwatson	KASSERT(sotorawcb(so) != NULL, ("raw_uabort: rp == NULL"));
136180385Srwatson
137130387Srwatson	soisdisconnected(so);
13825201Swollman}
1391541Srgrimes
140160549Srwatsonstatic void
141160549Srwatsonraw_uclose(struct socket *so)
142160549Srwatson{
143160549Srwatson
144180385Srwatson	KASSERT(sotorawcb(so) != NULL, ("raw_uabort: rp == NULL"));
145180385Srwatson
146160549Srwatson	soisdisconnected(so);
147160549Srwatson}
148160549Srwatson
14925201Swollman/* pru_accept is EOPNOTSUPP */
1501541Srgrimes
15125201Swollmanstatic int
15283366Sjulianraw_uattach(struct socket *so, int proto, struct thread *td)
15325201Swollman{
15425201Swollman	int error;
1551541Srgrimes
156157604Srwatson	/*
157157604Srwatson	 * Implementors of raw sockets will already have allocated the PCB,
158180385Srwatson	 * so it must be non-NULL here.
159157604Srwatson	 */
160157604Srwatson	KASSERT(sotorawcb(so) != NULL, ("raw_uattach: so_pcb == NULL"));
161157604Srwatson
162164033Srwatson	if (td != NULL) {
163164033Srwatson		error = priv_check(td, PRIV_NET_RAW);
164164033Srwatson		if (error)
165180385Srwatson			return (error);
166164033Srwatson	}
167180385Srwatson	return (raw_attach(so, proto));
16825201Swollman}
1691541Srgrimes
17025201Swollmanstatic int
17183366Sjulianraw_ubind(struct socket *so, struct sockaddr *nam, struct thread *td)
17225201Swollman{
173180305Srwatson
174180305Srwatson	return (EINVAL);
17525201Swollman}
1761541Srgrimes
17725201Swollmanstatic int
17883366Sjulianraw_uconnect(struct socket *so, struct sockaddr *nam, struct thread *td)
17925201Swollman{
180180305Srwatson
181180305Srwatson	return (EINVAL);
18225201Swollman}
1831541Srgrimes
18425201Swollman/* pru_connect2 is EOPNOTSUPP */
18525201Swollman/* pru_control is EOPNOTSUPP */
1861541Srgrimes
187157370Srwatsonstatic void
18825201Swollmanraw_udetach(struct socket *so)
18925201Swollman{
19025201Swollman	struct rawcb *rp = sotorawcb(so);
1911541Srgrimes
192157372Srwatson	KASSERT(rp != NULL, ("raw_udetach: rp == NULL"));
193180385Srwatson
19425201Swollman	raw_detach(rp);
19525201Swollman}
1961541Srgrimes
19725201Swollmanstatic int
19825201Swollmanraw_udisconnect(struct socket *so)
19925201Swollman{
2001541Srgrimes
201180385Srwatson	KASSERT(sotorawcb(so) != NULL, ("raw_udisconnect: rp == NULL"));
202180385Srwatson
203180385Srwatson	return (ENOTCONN);
20425201Swollman}
2051541Srgrimes
20625201Swollman/* pru_listen is EOPNOTSUPP */
2071541Srgrimes
20825201Swollmanstatic int
20928270Swollmanraw_upeeraddr(struct socket *so, struct sockaddr **nam)
21025201Swollman{
2111541Srgrimes
212180385Srwatson	KASSERT(sotorawcb(so) != NULL, ("raw_upeeraddr: rp == NULL"));
213180385Srwatson
214180385Srwatson	return (ENOTCONN);
21525201Swollman}
2161541Srgrimes
21725201Swollman/* pru_rcvd is EOPNOTSUPP */
21825201Swollman/* pru_rcvoob is EOPNOTSUPP */
21925201Swollman
22025201Swollmanstatic int
221180305Srwatsonraw_usend(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
222180305Srwatson    struct mbuf *control, struct thread *td)
22325201Swollman{
22425201Swollman
225180385Srwatson	KASSERT(sotorawcb(so) != NULL, ("raw_usend: rp == NULL"));
22625201Swollman
227180385Srwatson	if ((flags & PRUS_OOB) || (control && control->m_len)) {
228180385Srwatson		/* XXXRW: Should control also be freed here? */
229180385Srwatson		if (m != NULL)
230180385Srwatson			m_freem(m);
231180385Srwatson		return (EOPNOTSUPP);
23225201Swollman	}
23325201Swollman
234180385Srwatson	/*
235180385Srwatson	 * For historical (bad?) reasons, we effectively ignore the address
236180385Srwatson	 * argument to sendto(2).  Perhaps we should return an error instead?
237180385Srwatson	 */
238180385Srwatson	return ((*so->so_proto->pr_output)(m, so));
2391541Srgrimes}
24025201Swollman
24125201Swollman/* pru_sense is null */
24225201Swollman
24325201Swollmanstatic int
24425201Swollmanraw_ushutdown(struct socket *so)
24525201Swollman{
24625201Swollman
247157372Srwatson	KASSERT(sotorawcb(so) != NULL, ("raw_ushutdown: rp == NULL"));
248180385Srwatson
24925201Swollman	socantsendmore(so);
250180305Srwatson	return (0);
25125201Swollman}
25225201Swollman
25325201Swollmanstatic int
25428270Swollmanraw_usockaddr(struct socket *so, struct sockaddr **nam)
25525201Swollman{
25625201Swollman
257180385Srwatson	KASSERT(sotorawcb(so) != NULL, ("raw_usockaddr: rp == NULL"));
258180385Srwatson
259180385Srwatson	return (EINVAL);
26025201Swollman}
26125201Swollman
26225201Swollmanstruct pr_usrreqs raw_usrreqs = {
263137386Sphk	.pru_abort =		raw_uabort,
264137386Sphk	.pru_attach =		raw_uattach,
265137386Sphk	.pru_bind =		raw_ubind,
266137386Sphk	.pru_connect =		raw_uconnect,
267137386Sphk	.pru_detach =		raw_udetach,
268137386Sphk	.pru_disconnect =	raw_udisconnect,
269137386Sphk	.pru_peeraddr =		raw_upeeraddr,
270137386Sphk	.pru_send =		raw_usend,
271137386Sphk	.pru_shutdown =		raw_ushutdown,
272137386Sphk	.pru_sockaddr =		raw_usockaddr,
273160549Srwatson	.pru_close =		raw_uclose,
27425201Swollman};
275