raw_usrreq.c revision 157604
1139823Simp/*-
21541Srgrimes * Copyright (c) 1980, 1986, 1993
31541Srgrimes *	The Regents of the University of California.  All rights reserved.
41541Srgrimes *
51541Srgrimes * Redistribution and use in source and binary forms, with or without
61541Srgrimes * modification, are permitted provided that the following conditions
71541Srgrimes * are met:
81541Srgrimes * 1. Redistributions of source code must retain the above copyright
91541Srgrimes *    notice, this list of conditions and the following disclaimer.
101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111541Srgrimes *    notice, this list of conditions and the following disclaimer in the
121541Srgrimes *    documentation and/or other materials provided with the distribution.
131541Srgrimes * 4. Neither the name of the University nor the names of its contributors
141541Srgrimes *    may be used to endorse or promote products derived from this software
151541Srgrimes *    without specific prior written permission.
161541Srgrimes *
171541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271541Srgrimes * SUCH DAMAGE.
281541Srgrimes *
291541Srgrimes *	@(#)raw_usrreq.c	8.1 (Berkeley) 6/10/93
3050477Speter * $FreeBSD: head/sys/net/raw_usrreq.c 157604 2006-04-09 15:15:28Z rwatson $
311541Srgrimes */
321541Srgrimes
331541Srgrimes#include <sys/param.h>
34130514Srwatson#include <sys/kernel.h>
3595759Stanimura#include <sys/lock.h>
36126425Srwatson#include <sys/malloc.h>
371541Srgrimes#include <sys/mbuf.h>
38130387Srwatson#include <sys/mutex.h>
391541Srgrimes#include <sys/protosw.h>
4095759Stanimura#include <sys/signalvar.h>
411541Srgrimes#include <sys/socket.h>
421541Srgrimes#include <sys/socketvar.h>
4395759Stanimura#include <sys/sx.h>
4495759Stanimura#include <sys/systm.h>
451541Srgrimes
461541Srgrimes#include <net/raw_cb.h>
471541Srgrimes
48130514SrwatsonMTX_SYSINIT(rawcb_mtx, &rawcb_mtx, "rawcb", MTX_DEF);
49130514Srwatson
501541Srgrimes/*
511541Srgrimes * Initialize raw connection block q.
521541Srgrimes */
531541Srgrimesvoid
54107113Sluigiraw_init()
551541Srgrimes{
56130514Srwatson
5724936Sphk	LIST_INIT(&rawcb_list);
581541Srgrimes}
591541Srgrimes
601541Srgrimes
611541Srgrimes/*
621541Srgrimes * Raw protocol input routine.  Find the socket
631541Srgrimes * associated with the packet(s) and move them over.  If
641541Srgrimes * nothing exists for this packet, drop it.
651541Srgrimes */
661541Srgrimes/*
671541Srgrimes * Raw protocol interface.
681541Srgrimes */
691541Srgrimesvoid
70107113Sluigiraw_input(m0, proto, src, dst)
71107113Sluigi	struct mbuf *m0;
72107113Sluigi	register struct sockproto *proto;
73107113Sluigi	struct sockaddr *src, *dst;
741541Srgrimes{
75107113Sluigi	register struct rawcb *rp;
76107113Sluigi	register struct mbuf *m = m0;
771541Srgrimes	struct socket *last;
781541Srgrimes
79107113Sluigi	last = 0;
80130514Srwatson	mtx_lock(&rawcb_mtx);
8124936Sphk	LIST_FOREACH(rp, &rawcb_list, list) {
821541Srgrimes		if (rp->rcb_proto.sp_family != proto->sp_family)
831541Srgrimes			continue;
841541Srgrimes		if (rp->rcb_proto.sp_protocol  &&
851541Srgrimes		    rp->rcb_proto.sp_protocol != proto->sp_protocol)
861541Srgrimes			continue;
871541Srgrimes		/*
881541Srgrimes		 * We assume the lower level routines have
891541Srgrimes		 * placed the address in a canonical format
901541Srgrimes		 * suitable for a structure comparison.
911541Srgrimes		 *
921541Srgrimes		 * Note that if the lengths are not the same
931541Srgrimes		 * the comparison will fail at the first byte.
941541Srgrimes		 */
95107113Sluigi#define	equal(a1, a2) \
96107113Sluigi  (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
971541Srgrimes		if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst))
981541Srgrimes			continue;
991541Srgrimes		if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
1001541Srgrimes			continue;
1011541Srgrimes		if (last) {
102107113Sluigi			struct mbuf *n;
103107113Sluigi			n = m_copy(m, 0, (int)M_COPYALL);
1043443Sphk			if (n) {
1051541Srgrimes				if (sbappendaddr(&last->so_rcv, src,
106107113Sluigi				    n, (struct mbuf *)0) == 0)
1071541Srgrimes					/* should notify about lost packet */
1081541Srgrimes					m_freem(n);
1091541Srgrimes				else {
1101541Srgrimes					sorwakeup(last);
1111541Srgrimes				}
1121541Srgrimes			}
1131541Srgrimes		}
1141541Srgrimes		last = rp->rcb_socket;
1151541Srgrimes	}
1161541Srgrimes	if (last) {
117107113Sluigi		if (sbappendaddr(&last->so_rcv, src,
118107113Sluigi		    m, (struct mbuf *)0) == 0)
1191541Srgrimes			m_freem(m);
1201541Srgrimes		else {
1211541Srgrimes			sorwakeup(last);
1221541Srgrimes		}
1231541Srgrimes	} else
1241541Srgrimes		m_freem(m);
125130514Srwatson	mtx_unlock(&rawcb_mtx);
1261541Srgrimes}
1271541Srgrimes
1281541Srgrimes/*ARGSUSED*/
1291541Srgrimesvoid
130107113Sluigiraw_ctlinput(cmd, arg, dummy)
131107113Sluigi	int cmd;
132107113Sluigi	struct sockaddr *arg;
133107113Sluigi	void *dummy;
1341541Srgrimes{
1351541Srgrimes
136119995Sru	if (cmd < 0 || cmd >= PRC_NCMDS)
1371541Srgrimes		return;
1381541Srgrimes	/* INCOMPLETE */
1391541Srgrimes}
1401541Srgrimes
141157366Srwatsonstatic void
14225201Swollmanraw_uabort(struct socket *so)
1431541Srgrimes{
14425201Swollman	struct rawcb *rp = sotorawcb(so);
1451541Srgrimes
146157366Srwatson	KASSERT(rp != NULL, ("raw_uabort: rp == NULL"));
14725201Swollman	raw_disconnect(rp);
148130387Srwatson	soisdisconnected(so);
14925201Swollman}
1501541Srgrimes
15125201Swollman/* pru_accept is EOPNOTSUPP */
1521541Srgrimes
15325201Swollmanstatic int
15483366Sjulianraw_uattach(struct socket *so, int proto, struct thread *td)
15525201Swollman{
15625201Swollman	int error;
1571541Srgrimes
158157604Srwatson	/*
159157604Srwatson	 * Implementors of raw sockets will already have allocated the PCB,
160157604Srwatson	 * so it must be non-NULL here.
161157604Srwatson	 */
162157604Srwatson	KASSERT(sotorawcb(so) != NULL, ("raw_uattach: so_pcb == NULL"));
163157604Srwatson
16493593Sjhb	if (td && (error = suser(td)) != 0)
16525201Swollman		return error;
16625201Swollman	return raw_attach(so, proto);
16725201Swollman}
1681541Srgrimes
16925201Swollmanstatic int
17083366Sjulianraw_ubind(struct socket *so, struct sockaddr *nam, struct thread *td)
17125201Swollman{
17225201Swollman	return EINVAL;
17325201Swollman}
1741541Srgrimes
17525201Swollmanstatic int
17683366Sjulianraw_uconnect(struct socket *so, struct sockaddr *nam, struct thread *td)
17725201Swollman{
17825201Swollman	return EINVAL;
17925201Swollman}
1801541Srgrimes
18125201Swollman/* pru_connect2 is EOPNOTSUPP */
18225201Swollman/* pru_control is EOPNOTSUPP */
1831541Srgrimes
184157370Srwatsonstatic void
18525201Swollmanraw_udetach(struct socket *so)
18625201Swollman{
18725201Swollman	struct rawcb *rp = sotorawcb(so);
1881541Srgrimes
189157372Srwatson	KASSERT(rp != NULL, ("raw_udetach: rp == NULL"));
19025201Swollman	raw_detach(rp);
19125201Swollman}
1921541Srgrimes
19325201Swollmanstatic int
19425201Swollmanraw_udisconnect(struct socket *so)
19525201Swollman{
19625201Swollman	struct rawcb *rp = sotorawcb(so);
1971541Srgrimes
198157372Srwatson	KASSERT(rp != NULL, ("raw_udisconnect: rp == NULL"));
199107113Sluigi	if (rp->rcb_faddr == 0) {
20025201Swollman		return ENOTCONN;
201107113Sluigi	}
20225201Swollman	raw_disconnect(rp);
20325201Swollman	soisdisconnected(so);
20425201Swollman	return 0;
20525201Swollman}
2061541Srgrimes
20725201Swollman/* pru_listen is EOPNOTSUPP */
2081541Srgrimes
20925201Swollmanstatic int
21028270Swollmanraw_upeeraddr(struct socket *so, struct sockaddr **nam)
21125201Swollman{
21225201Swollman	struct rawcb *rp = sotorawcb(so);
2131541Srgrimes
214157372Srwatson	KASSERT(rp != NULL, ("raw_upeeraddr: rp == NULL"));
215107113Sluigi	if (rp->rcb_faddr == 0) {
21625201Swollman		return ENOTCONN;
217107113Sluigi	}
218126425Srwatson	*nam = sodupsockaddr(rp->rcb_faddr, M_WAITOK);
21925201Swollman	return 0;
22025201Swollman}
2211541Srgrimes
22225201Swollman/* pru_rcvd is EOPNOTSUPP */
22325201Swollman/* pru_rcvoob is EOPNOTSUPP */
22425201Swollman
22525201Swollmanstatic int
22625201Swollmanraw_usend(struct socket *so, int flags, struct mbuf *m,
22783366Sjulian	  struct sockaddr *nam, struct mbuf *control, struct thread *td)
22825201Swollman{
22925201Swollman	int error;
23025201Swollman	struct rawcb *rp = sotorawcb(so);
23125201Swollman
232157372Srwatson	KASSERT(rp != NULL, ("raw_usend: rp == NULL"));
23325201Swollman
23425201Swollman	if (flags & PRUS_OOB) {
23525201Swollman		error = EOPNOTSUPP;
23625201Swollman		goto release;
23725201Swollman	}
23825201Swollman
23925201Swollman	if (control && control->m_len) {
24025201Swollman		error = EOPNOTSUPP;
24125201Swollman		goto release;
24225201Swollman	}
24325201Swollman	if (nam) {
24425201Swollman		if (rp->rcb_faddr) {
24525201Swollman			error = EISCONN;
24625201Swollman			goto release;
24725201Swollman		}
24828270Swollman		rp->rcb_faddr = nam;
24925201Swollman	} else if (rp->rcb_faddr == 0) {
25025201Swollman		error = ENOTCONN;
25125201Swollman		goto release;
25225201Swollman	}
25325201Swollman	error = (*so->so_proto->pr_output)(m, so);
25425201Swollman	m = NULL;
25525201Swollman	if (nam)
25625201Swollman		rp->rcb_faddr = 0;
2571541Srgrimesrelease:
2581541Srgrimes	if (m != NULL)
2591541Srgrimes		m_freem(m);
2601541Srgrimes	return (error);
2611541Srgrimes}
26225201Swollman
26325201Swollman/* pru_sense is null */
26425201Swollman
26525201Swollmanstatic int
26625201Swollmanraw_ushutdown(struct socket *so)
26725201Swollman{
26825201Swollman
269157372Srwatson	KASSERT(sotorawcb(so) != NULL, ("raw_ushutdown: rp == NULL"));
27025201Swollman	socantsendmore(so);
27125201Swollman	return 0;
27225201Swollman}
27325201Swollman
27425201Swollmanstatic int
27528270Swollmanraw_usockaddr(struct socket *so, struct sockaddr **nam)
27625201Swollman{
27725201Swollman	struct rawcb *rp = sotorawcb(so);
27825201Swollman
279157372Srwatson	KASSERT(rp != NULL, ("raw_usockaddr: rp == NULL"));
28025201Swollman	if (rp->rcb_laddr == 0)
28125201Swollman		return EINVAL;
282126425Srwatson	*nam = sodupsockaddr(rp->rcb_laddr, M_WAITOK);
28325201Swollman	return 0;
28425201Swollman}
28525201Swollman
28625201Swollmanstruct pr_usrreqs raw_usrreqs = {
287137386Sphk	.pru_abort =		raw_uabort,
288137386Sphk	.pru_attach =		raw_uattach,
289137386Sphk	.pru_bind =		raw_ubind,
290137386Sphk	.pru_connect =		raw_uconnect,
291137386Sphk	.pru_detach =		raw_udetach,
292137386Sphk	.pru_disconnect =	raw_udisconnect,
293137386Sphk	.pru_peeraddr =		raw_upeeraddr,
294137386Sphk	.pru_send =		raw_usend,
295137386Sphk	.pru_shutdown =		raw_ushutdown,
296137386Sphk	.pru_sockaddr =		raw_usockaddr,
29725201Swollman};
298