raw_usrreq.c revision 157372
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 157372 2006-04-01 15:55:44Z 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
158157372Srwatson	KASSERT(sotorawcb(so) == NULL, ("raw_uattach: rp != NULL"));
15993593Sjhb	if (td && (error = suser(td)) != 0)
16025201Swollman		return error;
16125201Swollman	return raw_attach(so, proto);
16225201Swollman}
1631541Srgrimes
16425201Swollmanstatic int
16583366Sjulianraw_ubind(struct socket *so, struct sockaddr *nam, struct thread *td)
16625201Swollman{
16725201Swollman	return EINVAL;
16825201Swollman}
1691541Srgrimes
17025201Swollmanstatic int
17183366Sjulianraw_uconnect(struct socket *so, struct sockaddr *nam, struct thread *td)
17225201Swollman{
17325201Swollman	return EINVAL;
17425201Swollman}
1751541Srgrimes
17625201Swollman/* pru_connect2 is EOPNOTSUPP */
17725201Swollman/* pru_control is EOPNOTSUPP */
1781541Srgrimes
179157370Srwatsonstatic void
18025201Swollmanraw_udetach(struct socket *so)
18125201Swollman{
18225201Swollman	struct rawcb *rp = sotorawcb(so);
1831541Srgrimes
184157372Srwatson	KASSERT(rp != NULL, ("raw_udetach: rp == NULL"));
18525201Swollman	raw_detach(rp);
18625201Swollman}
1871541Srgrimes
18825201Swollmanstatic int
18925201Swollmanraw_udisconnect(struct socket *so)
19025201Swollman{
19125201Swollman	struct rawcb *rp = sotorawcb(so);
1921541Srgrimes
193157372Srwatson	KASSERT(rp != NULL, ("raw_udisconnect: rp == NULL"));
194107113Sluigi	if (rp->rcb_faddr == 0) {
19525201Swollman		return ENOTCONN;
196107113Sluigi	}
19725201Swollman	raw_disconnect(rp);
19825201Swollman	soisdisconnected(so);
19925201Swollman	return 0;
20025201Swollman}
2011541Srgrimes
20225201Swollman/* pru_listen is EOPNOTSUPP */
2031541Srgrimes
20425201Swollmanstatic int
20528270Swollmanraw_upeeraddr(struct socket *so, struct sockaddr **nam)
20625201Swollman{
20725201Swollman	struct rawcb *rp = sotorawcb(so);
2081541Srgrimes
209157372Srwatson	KASSERT(rp != NULL, ("raw_upeeraddr: rp == NULL"));
210107113Sluigi	if (rp->rcb_faddr == 0) {
21125201Swollman		return ENOTCONN;
212107113Sluigi	}
213126425Srwatson	*nam = sodupsockaddr(rp->rcb_faddr, M_WAITOK);
21425201Swollman	return 0;
21525201Swollman}
2161541Srgrimes
21725201Swollman/* pru_rcvd is EOPNOTSUPP */
21825201Swollman/* pru_rcvoob is EOPNOTSUPP */
21925201Swollman
22025201Swollmanstatic int
22125201Swollmanraw_usend(struct socket *so, int flags, struct mbuf *m,
22283366Sjulian	  struct sockaddr *nam, struct mbuf *control, struct thread *td)
22325201Swollman{
22425201Swollman	int error;
22525201Swollman	struct rawcb *rp = sotorawcb(so);
22625201Swollman
227157372Srwatson	KASSERT(rp != NULL, ("raw_usend: rp == NULL"));
22825201Swollman
22925201Swollman	if (flags & PRUS_OOB) {
23025201Swollman		error = EOPNOTSUPP;
23125201Swollman		goto release;
23225201Swollman	}
23325201Swollman
23425201Swollman	if (control && control->m_len) {
23525201Swollman		error = EOPNOTSUPP;
23625201Swollman		goto release;
23725201Swollman	}
23825201Swollman	if (nam) {
23925201Swollman		if (rp->rcb_faddr) {
24025201Swollman			error = EISCONN;
24125201Swollman			goto release;
24225201Swollman		}
24328270Swollman		rp->rcb_faddr = nam;
24425201Swollman	} else if (rp->rcb_faddr == 0) {
24525201Swollman		error = ENOTCONN;
24625201Swollman		goto release;
24725201Swollman	}
24825201Swollman	error = (*so->so_proto->pr_output)(m, so);
24925201Swollman	m = NULL;
25025201Swollman	if (nam)
25125201Swollman		rp->rcb_faddr = 0;
2521541Srgrimesrelease:
2531541Srgrimes	if (m != NULL)
2541541Srgrimes		m_freem(m);
2551541Srgrimes	return (error);
2561541Srgrimes}
25725201Swollman
25825201Swollman/* pru_sense is null */
25925201Swollman
26025201Swollmanstatic int
26125201Swollmanraw_ushutdown(struct socket *so)
26225201Swollman{
26325201Swollman
264157372Srwatson	KASSERT(sotorawcb(so) != NULL, ("raw_ushutdown: rp == NULL"));
26525201Swollman	socantsendmore(so);
26625201Swollman	return 0;
26725201Swollman}
26825201Swollman
26925201Swollmanstatic int
27028270Swollmanraw_usockaddr(struct socket *so, struct sockaddr **nam)
27125201Swollman{
27225201Swollman	struct rawcb *rp = sotorawcb(so);
27325201Swollman
274157372Srwatson	KASSERT(rp != NULL, ("raw_usockaddr: rp == NULL"));
27525201Swollman	if (rp->rcb_laddr == 0)
27625201Swollman		return EINVAL;
277126425Srwatson	*nam = sodupsockaddr(rp->rcb_laddr, M_WAITOK);
27825201Swollman	return 0;
27925201Swollman}
28025201Swollman
28125201Swollmanstruct pr_usrreqs raw_usrreqs = {
282137386Sphk	.pru_abort =		raw_uabort,
283137386Sphk	.pru_attach =		raw_uattach,
284137386Sphk	.pru_bind =		raw_ubind,
285137386Sphk	.pru_connect =		raw_uconnect,
286137386Sphk	.pru_detach =		raw_udetach,
287137386Sphk	.pru_disconnect =	raw_udisconnect,
288137386Sphk	.pru_peeraddr =		raw_upeeraddr,
289137386Sphk	.pru_send =		raw_usend,
290137386Sphk	.pru_shutdown =		raw_ushutdown,
291137386Sphk	.pru_sockaddr =		raw_usockaddr,
29225201Swollman};
293