raw_usrreq.c revision 28270
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
3428270Swollman *	$Id: raw_usrreq.c,v 1.13 1997/08/02 14:32:40 bde Exp $
351541Srgrimes */
361541Srgrimes
371541Srgrimes#include <sys/param.h>
382112Swollman#include <sys/systm.h>
391541Srgrimes#include <sys/mbuf.h>
4025201Swollman#include <sys/proc.h>
411541Srgrimes#include <sys/protosw.h>
421541Srgrimes#include <sys/socket.h>
431541Srgrimes#include <sys/socketvar.h>
441541Srgrimes
451541Srgrimes#include <net/raw_cb.h>
461541Srgrimes
471541Srgrimes/*
481541Srgrimes * Initialize raw connection block q.
491541Srgrimes */
501541Srgrimesvoid
511541Srgrimesraw_init()
521541Srgrimes{
5324936Sphk	LIST_INIT(&rawcb_list);
541541Srgrimes}
551541Srgrimes
561541Srgrimes
571541Srgrimes/*
581541Srgrimes * Raw protocol input routine.  Find the socket
591541Srgrimes * associated with the packet(s) and move them over.  If
601541Srgrimes * nothing exists for this packet, drop it.
611541Srgrimes */
621541Srgrimes/*
631541Srgrimes * Raw protocol interface.
641541Srgrimes */
651541Srgrimesvoid
661541Srgrimesraw_input(m0, proto, src, dst)
671541Srgrimes	struct mbuf *m0;
681541Srgrimes	register struct sockproto *proto;
691541Srgrimes	struct sockaddr *src, *dst;
701541Srgrimes{
711541Srgrimes	register struct rawcb *rp;
721541Srgrimes	register struct mbuf *m = m0;
731541Srgrimes	register int sockets = 0;
741541Srgrimes	struct socket *last;
751541Srgrimes
761541Srgrimes	last = 0;
7724936Sphk	LIST_FOREACH(rp, &rawcb_list, list) {
781541Srgrimes		if (rp->rcb_proto.sp_family != proto->sp_family)
791541Srgrimes			continue;
801541Srgrimes		if (rp->rcb_proto.sp_protocol  &&
811541Srgrimes		    rp->rcb_proto.sp_protocol != proto->sp_protocol)
821541Srgrimes			continue;
831541Srgrimes		/*
841541Srgrimes		 * We assume the lower level routines have
851541Srgrimes		 * placed the address in a canonical format
861541Srgrimes		 * suitable for a structure comparison.
871541Srgrimes		 *
881541Srgrimes		 * Note that if the lengths are not the same
891541Srgrimes		 * the comparison will fail at the first byte.
901541Srgrimes		 */
911541Srgrimes#define	equal(a1, a2) \
921541Srgrimes  (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
931541Srgrimes		if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst))
941541Srgrimes			continue;
951541Srgrimes		if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
961541Srgrimes			continue;
971541Srgrimes		if (last) {
981541Srgrimes			struct mbuf *n;
993443Sphk			n = m_copy(m, 0, (int)M_COPYALL);
1003443Sphk			if (n) {
1011541Srgrimes				if (sbappendaddr(&last->so_rcv, src,
1021541Srgrimes				    n, (struct mbuf *)0) == 0)
1031541Srgrimes					/* should notify about lost packet */
1041541Srgrimes					m_freem(n);
1051541Srgrimes				else {
1061541Srgrimes					sorwakeup(last);
1071541Srgrimes					sockets++;
1081541Srgrimes				}
1091541Srgrimes			}
1101541Srgrimes		}
1111541Srgrimes		last = rp->rcb_socket;
1121541Srgrimes	}
1131541Srgrimes	if (last) {
1141541Srgrimes		if (sbappendaddr(&last->so_rcv, src,
1151541Srgrimes		    m, (struct mbuf *)0) == 0)
1161541Srgrimes			m_freem(m);
1171541Srgrimes		else {
1181541Srgrimes			sorwakeup(last);
1191541Srgrimes			sockets++;
1201541Srgrimes		}
1211541Srgrimes	} else
1221541Srgrimes		m_freem(m);
1231541Srgrimes}
1241541Srgrimes
1251541Srgrimes/*ARGSUSED*/
1261541Srgrimesvoid
12712881Sbderaw_ctlinput(cmd, arg, dummy)
1281541Srgrimes	int cmd;
1291541Srgrimes	struct sockaddr *arg;
13012881Sbde	void *dummy;
1311541Srgrimes{
1321541Srgrimes
1331541Srgrimes	if (cmd < 0 || cmd > PRC_NCMDS)
1341541Srgrimes		return;
1351541Srgrimes	/* INCOMPLETE */
1361541Srgrimes}
1371541Srgrimes
13825201Swollmanstatic int
13925201Swollmanraw_uabort(struct socket *so)
1401541Srgrimes{
14125201Swollman	struct rawcb *rp = sotorawcb(so);
1421541Srgrimes
14325201Swollman	if (rp == 0)
14425201Swollman		return EINVAL;
14525201Swollman	raw_disconnect(rp);
14625201Swollman	sofree(so);
14725201Swollman	soisdisconnected(so);
14825201Swollman	return 0;
14925201Swollman}
1501541Srgrimes
15125201Swollman/* pru_accept is EOPNOTSUPP */
1521541Srgrimes
15325201Swollmanstatic int
15425201Swollmanraw_uattach(struct socket *so, int proto, struct proc *p)
15525201Swollman{
15625201Swollman	struct rawcb *rp = sotorawcb(so);
15725201Swollman	int error;
1581541Srgrimes
15925201Swollman	if (rp == 0)
16025201Swollman		return EINVAL;
16125201Swollman	if (p && (error = suser(p->p_ucred, &p->p_acflag)) != 0)
16225201Swollman		return error;
16325201Swollman	return raw_attach(so, proto);
16425201Swollman}
1651541Srgrimes
16625201Swollmanstatic int
16728270Swollmanraw_ubind(struct socket *so, struct sockaddr *nam, struct proc *p)
16825201Swollman{
16925201Swollman	return EINVAL;
17025201Swollman}
1711541Srgrimes
17225201Swollmanstatic int
17328270Swollmanraw_uconnect(struct socket *so, struct sockaddr *nam, struct proc *p)
17425201Swollman{
17525201Swollman	return EINVAL;
17625201Swollman}
1771541Srgrimes
17825201Swollman/* pru_connect2 is EOPNOTSUPP */
17925201Swollman/* pru_control is EOPNOTSUPP */
1801541Srgrimes
18125201Swollmanstatic int
18225201Swollmanraw_udetach(struct socket *so)
18325201Swollman{
18425201Swollman	struct rawcb *rp = sotorawcb(so);
1851541Srgrimes
18625201Swollman	if (rp == 0)
18725201Swollman		return EINVAL;
1881541Srgrimes
18925201Swollman	raw_detach(rp);
19025201Swollman	return 0;
19125201Swollman}
1921541Srgrimes
19325201Swollmanstatic int
19425201Swollmanraw_udisconnect(struct socket *so)
19525201Swollman{
19625201Swollman	struct rawcb *rp = sotorawcb(so);
1971541Srgrimes
19825201Swollman	if (rp == 0)
19925201Swollman		return EINVAL;
20025201Swollman	if (rp->rcb_faddr == 0) {
20125201Swollman		return ENOTCONN;
20225201Swollman	}
20325201Swollman	raw_disconnect(rp);
20425201Swollman	soisdisconnected(so);
20525201Swollman	return 0;
20625201Swollman}
2071541Srgrimes
20825201Swollman/* pru_listen is EOPNOTSUPP */
2091541Srgrimes
21025201Swollmanstatic int
21128270Swollmanraw_upeeraddr(struct socket *so, struct sockaddr **nam)
21225201Swollman{
21325201Swollman	struct rawcb *rp = sotorawcb(so);
21425201Swollman	unsigned len;
2151541Srgrimes
21625201Swollman	if (rp == 0)
21725201Swollman		return EINVAL;
21825201Swollman	if (rp->rcb_faddr == 0) {
21925201Swollman		return ENOTCONN;
22025201Swollman	}
22128270Swollman	*nam = dup_sockaddr(rp->rcb_faddr, 1);
22225201Swollman	return 0;
22325201Swollman}
2241541Srgrimes
22525201Swollman/* pru_rcvd is EOPNOTSUPP */
22625201Swollman/* pru_rcvoob is EOPNOTSUPP */
22725201Swollman
22825201Swollmanstatic int
22925201Swollmanraw_usend(struct socket *so, int flags, struct mbuf *m,
23028270Swollman	  struct sockaddr *nam, struct mbuf *control, struct proc *p)
23125201Swollman{
23225201Swollman	int error;
23325201Swollman	struct rawcb *rp = sotorawcb(so);
23425201Swollman
23525201Swollman	if (rp == 0) {
23625201Swollman		error = EINVAL;
23725201Swollman		goto release;
2381541Srgrimes	}
23925201Swollman
24025201Swollman	if (flags & PRUS_OOB) {
24125201Swollman		error = EOPNOTSUPP;
24225201Swollman		goto release;
24325201Swollman	}
24425201Swollman
24525201Swollman	if (control && control->m_len) {
24625201Swollman		error = EOPNOTSUPP;
24725201Swollman		goto release;
24825201Swollman	}
24925201Swollman	if (nam) {
25025201Swollman		if (rp->rcb_faddr) {
25125201Swollman			error = EISCONN;
25225201Swollman			goto release;
25325201Swollman		}
25428270Swollman		rp->rcb_faddr = nam;
25525201Swollman	} else if (rp->rcb_faddr == 0) {
25625201Swollman		error = ENOTCONN;
25725201Swollman		goto release;
25825201Swollman	}
25925201Swollman	error = (*so->so_proto->pr_output)(m, so);
26025201Swollman	m = NULL;
26125201Swollman	if (nam)
26225201Swollman		rp->rcb_faddr = 0;
2631541Srgrimesrelease:
2641541Srgrimes	if (m != NULL)
2651541Srgrimes		m_freem(m);
2661541Srgrimes	return (error);
2671541Srgrimes}
26825201Swollman
26925201Swollman/* pru_sense is null */
27025201Swollman
27125201Swollmanstatic int
27225201Swollmanraw_ushutdown(struct socket *so)
27325201Swollman{
27425201Swollman	struct rawcb *rp = sotorawcb(so);
27525201Swollman
27625201Swollman	if (rp == 0)
27725201Swollman		return EINVAL;
27825201Swollman	socantsendmore(so);
27925201Swollman	return 0;
28025201Swollman}
28125201Swollman
28225201Swollmanstatic int
28328270Swollmanraw_usockaddr(struct socket *so, struct sockaddr **nam)
28425201Swollman{
28525201Swollman	struct rawcb *rp = sotorawcb(so);
28625201Swollman	unsigned len;
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,
30125201Swollman	raw_usockaddr, sosend, soreceive, soselect
30225201Swollman};
303