raw_usrreq.c revision 95759
11541Srgrimes/*
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 * 3. All advertising materials mentioning features or use of this software
141541Srgrimes *    must display the following acknowledgement:
151541Srgrimes *	This product includes software developed by the University of
161541Srgrimes *	California, Berkeley and its contributors.
171541Srgrimes * 4. Neither the name of the University nor the names of its contributors
181541Srgrimes *    may be used to endorse or promote products derived from this software
191541Srgrimes *    without specific prior written permission.
201541Srgrimes *
211541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311541Srgrimes * SUCH DAMAGE.
321541Srgrimes *
331541Srgrimes *	@(#)raw_usrreq.c	8.1 (Berkeley) 6/10/93
3450477Speter * $FreeBSD: head/sys/net/raw_usrreq.c 95759 2002-04-30 01:54:54Z tanimura $
351541Srgrimes */
361541Srgrimes
371541Srgrimes#include <sys/param.h>
3895759Stanimura#include <sys/lock.h>
391541Srgrimes#include <sys/mbuf.h>
401541Srgrimes#include <sys/protosw.h>
4195759Stanimura#include <sys/signalvar.h>
421541Srgrimes#include <sys/socket.h>
431541Srgrimes#include <sys/socketvar.h>
4495759Stanimura#include <sys/sx.h>
4595759Stanimura#include <sys/systm.h>
461541Srgrimes
471541Srgrimes#include <net/raw_cb.h>
481541Srgrimes
491541Srgrimes/*
501541Srgrimes * Initialize raw connection block q.
511541Srgrimes */
521541Srgrimesvoid
531541Srgrimesraw_init()
541541Srgrimes{
5524936Sphk	LIST_INIT(&rawcb_list);
561541Srgrimes}
571541Srgrimes
581541Srgrimes
591541Srgrimes/*
601541Srgrimes * Raw protocol input routine.  Find the socket
611541Srgrimes * associated with the packet(s) and move them over.  If
621541Srgrimes * nothing exists for this packet, drop it.
631541Srgrimes */
641541Srgrimes/*
651541Srgrimes * Raw protocol interface.
661541Srgrimes */
671541Srgrimesvoid
681541Srgrimesraw_input(m0, proto, src, dst)
691541Srgrimes	struct mbuf *m0;
701541Srgrimes	register struct sockproto *proto;
711541Srgrimes	struct sockaddr *src, *dst;
721541Srgrimes{
731541Srgrimes	register struct rawcb *rp;
741541Srgrimes	register struct mbuf *m = m0;
751541Srgrimes	register int sockets = 0;
761541Srgrimes	struct socket *last;
771541Srgrimes
781541Srgrimes	last = 0;
7924936Sphk	LIST_FOREACH(rp, &rawcb_list, list) {
801541Srgrimes		if (rp->rcb_proto.sp_family != proto->sp_family)
811541Srgrimes			continue;
821541Srgrimes		if (rp->rcb_proto.sp_protocol  &&
831541Srgrimes		    rp->rcb_proto.sp_protocol != proto->sp_protocol)
841541Srgrimes			continue;
851541Srgrimes		/*
861541Srgrimes		 * We assume the lower level routines have
871541Srgrimes		 * placed the address in a canonical format
881541Srgrimes		 * suitable for a structure comparison.
891541Srgrimes		 *
901541Srgrimes		 * Note that if the lengths are not the same
911541Srgrimes		 * the comparison will fail at the first byte.
921541Srgrimes		 */
931541Srgrimes#define	equal(a1, a2) \
941541Srgrimes  (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
951541Srgrimes		if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst))
961541Srgrimes			continue;
971541Srgrimes		if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
981541Srgrimes			continue;
991541Srgrimes		if (last) {
1001541Srgrimes			struct mbuf *n;
1013443Sphk			n = m_copy(m, 0, (int)M_COPYALL);
1023443Sphk			if (n) {
1031541Srgrimes				if (sbappendaddr(&last->so_rcv, src,
1041541Srgrimes				    n, (struct mbuf *)0) == 0)
1051541Srgrimes					/* should notify about lost packet */
1061541Srgrimes					m_freem(n);
1071541Srgrimes				else {
1081541Srgrimes					sorwakeup(last);
1091541Srgrimes					sockets++;
1101541Srgrimes				}
1111541Srgrimes			}
1121541Srgrimes		}
1131541Srgrimes		last = rp->rcb_socket;
1141541Srgrimes	}
1151541Srgrimes	if (last) {
1161541Srgrimes		if (sbappendaddr(&last->so_rcv, src,
1171541Srgrimes		    m, (struct mbuf *)0) == 0)
1181541Srgrimes			m_freem(m);
1191541Srgrimes		else {
1201541Srgrimes			sorwakeup(last);
1211541Srgrimes			sockets++;
1221541Srgrimes		}
1231541Srgrimes	} else
1241541Srgrimes		m_freem(m);
1251541Srgrimes}
1261541Srgrimes
1271541Srgrimes/*ARGSUSED*/
1281541Srgrimesvoid
12912881Sbderaw_ctlinput(cmd, arg, dummy)
1301541Srgrimes	int cmd;
1311541Srgrimes	struct sockaddr *arg;
13212881Sbde	void *dummy;
1331541Srgrimes{
1341541Srgrimes
1351541Srgrimes	if (cmd < 0 || cmd > PRC_NCMDS)
1361541Srgrimes		return;
1371541Srgrimes	/* INCOMPLETE */
1381541Srgrimes}
1391541Srgrimes
14025201Swollmanstatic int
14125201Swollmanraw_uabort(struct socket *so)
1421541Srgrimes{
14325201Swollman	struct rawcb *rp = sotorawcb(so);
1441541Srgrimes
14525201Swollman	if (rp == 0)
14625201Swollman		return EINVAL;
14725201Swollman	raw_disconnect(rp);
14886487Sdillon	sotryfree(so);
14986487Sdillon	soisdisconnected(so);	/* XXX huh? called after the sofree()? */
15025201Swollman	return 0;
15125201Swollman}
1521541Srgrimes
15325201Swollman/* pru_accept is EOPNOTSUPP */
1541541Srgrimes
15525201Swollmanstatic int
15683366Sjulianraw_uattach(struct socket *so, int proto, struct thread *td)
15725201Swollman{
15825201Swollman	struct rawcb *rp = sotorawcb(so);
15925201Swollman	int error;
1601541Srgrimes
16125201Swollman	if (rp == 0)
16225201Swollman		return EINVAL;
16393593Sjhb	if (td && (error = suser(td)) != 0)
16425201Swollman		return error;
16525201Swollman	return raw_attach(so, proto);
16625201Swollman}
1671541Srgrimes
16825201Swollmanstatic int
16983366Sjulianraw_ubind(struct socket *so, struct sockaddr *nam, struct thread *td)
17025201Swollman{
17125201Swollman	return EINVAL;
17225201Swollman}
1731541Srgrimes
17425201Swollmanstatic int
17583366Sjulianraw_uconnect(struct socket *so, struct sockaddr *nam, struct thread *td)
17625201Swollman{
17725201Swollman	return EINVAL;
17825201Swollman}
1791541Srgrimes
18025201Swollman/* pru_connect2 is EOPNOTSUPP */
18125201Swollman/* pru_control is EOPNOTSUPP */
1821541Srgrimes
18325201Swollmanstatic int
18425201Swollmanraw_udetach(struct socket *so)
18525201Swollman{
18625201Swollman	struct rawcb *rp = sotorawcb(so);
1871541Srgrimes
18825201Swollman	if (rp == 0)
18925201Swollman		return EINVAL;
1901541Srgrimes
19125201Swollman	raw_detach(rp);
19225201Swollman	return 0;
19325201Swollman}
1941541Srgrimes
19525201Swollmanstatic int
19625201Swollmanraw_udisconnect(struct socket *so)
19725201Swollman{
19825201Swollman	struct rawcb *rp = sotorawcb(so);
1991541Srgrimes
20025201Swollman	if (rp == 0)
20125201Swollman		return EINVAL;
20225201Swollman	if (rp->rcb_faddr == 0) {
20325201Swollman		return ENOTCONN;
20425201Swollman	}
20525201Swollman	raw_disconnect(rp);
20625201Swollman	soisdisconnected(so);
20725201Swollman	return 0;
20825201Swollman}
2091541Srgrimes
21025201Swollman/* pru_listen is EOPNOTSUPP */
2111541Srgrimes
21225201Swollmanstatic int
21328270Swollmanraw_upeeraddr(struct socket *so, struct sockaddr **nam)
21425201Swollman{
21525201Swollman	struct rawcb *rp = sotorawcb(so);
2161541Srgrimes
21725201Swollman	if (rp == 0)
21825201Swollman		return EINVAL;
21925201Swollman	if (rp->rcb_faddr == 0) {
22025201Swollman		return ENOTCONN;
22125201Swollman	}
22228270Swollman	*nam = dup_sockaddr(rp->rcb_faddr, 1);
22325201Swollman	return 0;
22425201Swollman}
2251541Srgrimes
22625201Swollman/* pru_rcvd is EOPNOTSUPP */
22725201Swollman/* pru_rcvoob is EOPNOTSUPP */
22825201Swollman
22925201Swollmanstatic int
23025201Swollmanraw_usend(struct socket *so, int flags, struct mbuf *m,
23183366Sjulian	  struct sockaddr *nam, struct mbuf *control, struct thread *td)
23225201Swollman{
23325201Swollman	int error;
23425201Swollman	struct rawcb *rp = sotorawcb(so);
23525201Swollman
23625201Swollman	if (rp == 0) {
23725201Swollman		error = EINVAL;
23825201Swollman		goto release;
2391541Srgrimes	}
24025201Swollman
24125201Swollman	if (flags & PRUS_OOB) {
24225201Swollman		error = EOPNOTSUPP;
24325201Swollman		goto release;
24425201Swollman	}
24525201Swollman
24625201Swollman	if (control && control->m_len) {
24725201Swollman		error = EOPNOTSUPP;
24825201Swollman		goto release;
24925201Swollman	}
25025201Swollman	if (nam) {
25125201Swollman		if (rp->rcb_faddr) {
25225201Swollman			error = EISCONN;
25325201Swollman			goto release;
25425201Swollman		}
25528270Swollman		rp->rcb_faddr = nam;
25625201Swollman	} else if (rp->rcb_faddr == 0) {
25725201Swollman		error = ENOTCONN;
25825201Swollman		goto release;
25925201Swollman	}
26025201Swollman	error = (*so->so_proto->pr_output)(m, so);
26125201Swollman	m = NULL;
26225201Swollman	if (nam)
26325201Swollman		rp->rcb_faddr = 0;
2641541Srgrimesrelease:
2651541Srgrimes	if (m != NULL)
2661541Srgrimes		m_freem(m);
2671541Srgrimes	return (error);
2681541Srgrimes}
26925201Swollman
27025201Swollman/* pru_sense is null */
27125201Swollman
27225201Swollmanstatic int
27325201Swollmanraw_ushutdown(struct socket *so)
27425201Swollman{
27525201Swollman	struct rawcb *rp = sotorawcb(so);
27625201Swollman
27725201Swollman	if (rp == 0)
27825201Swollman		return EINVAL;
27925201Swollman	socantsendmore(so);
28025201Swollman	return 0;
28125201Swollman}
28225201Swollman
28325201Swollmanstatic int
28428270Swollmanraw_usockaddr(struct socket *so, struct sockaddr **nam)
28525201Swollman{
28625201Swollman	struct rawcb *rp = sotorawcb(so);
28725201Swollman
28825201Swollman	if (rp == 0)
28925201Swollman		return EINVAL;
29025201Swollman	if (rp->rcb_laddr == 0)
29125201Swollman		return EINVAL;
29228270Swollman	*nam = dup_sockaddr(rp->rcb_laddr, 1);
29325201Swollman	return 0;
29425201Swollman}
29525201Swollman
29625201Swollmanstruct pr_usrreqs raw_usrreqs = {
29725201Swollman	raw_uabort, pru_accept_notsupp, raw_uattach, raw_ubind, raw_uconnect,
29825201Swollman	pru_connect2_notsupp, pru_control_notsupp, raw_udetach,
29925201Swollman	raw_udisconnect, pru_listen_notsupp, raw_upeeraddr, pru_rcvd_notsupp,
30025201Swollman	pru_rcvoob_notsupp, raw_usend, pru_sense_null, raw_ushutdown,
30129366Speter	raw_usockaddr, sosend, soreceive, sopoll
30225201Swollman};
303