raw_usrreq.c revision 25201
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
3425201Swollman *	$Id: raw_usrreq.c,v 1.11 1997/04/14 18:23:25 phk Exp $
351541Srgrimes */
361541Srgrimes
371541Srgrimes#include <sys/param.h>
3814546Sdg#include <sys/queue.h>
392112Swollman#include <sys/systm.h>
401541Srgrimes#include <sys/mbuf.h>
411541Srgrimes#include <sys/domain.h>
4225201Swollman#include <sys/proc.h>
431541Srgrimes#include <sys/protosw.h>
441541Srgrimes#include <sys/socket.h>
451541Srgrimes#include <sys/socketvar.h>
461541Srgrimes#include <sys/errno.h>
471541Srgrimes
481541Srgrimes#include <net/if.h>
491541Srgrimes#include <net/route.h>
501541Srgrimes#include <net/netisr.h>
511541Srgrimes#include <net/raw_cb.h>
521541Srgrimes
531541Srgrimes/*
541541Srgrimes * Initialize raw connection block q.
551541Srgrimes */
561541Srgrimesvoid
571541Srgrimesraw_init()
581541Srgrimes{
5924936Sphk	LIST_INIT(&rawcb_list);
601541Srgrimes}
611541Srgrimes
621541Srgrimes
631541Srgrimes/*
641541Srgrimes * Raw protocol input routine.  Find the socket
651541Srgrimes * associated with the packet(s) and move them over.  If
661541Srgrimes * nothing exists for this packet, drop it.
671541Srgrimes */
681541Srgrimes/*
691541Srgrimes * Raw protocol interface.
701541Srgrimes */
711541Srgrimesvoid
721541Srgrimesraw_input(m0, proto, src, dst)
731541Srgrimes	struct mbuf *m0;
741541Srgrimes	register struct sockproto *proto;
751541Srgrimes	struct sockaddr *src, *dst;
761541Srgrimes{
771541Srgrimes	register struct rawcb *rp;
781541Srgrimes	register struct mbuf *m = m0;
791541Srgrimes	register int sockets = 0;
801541Srgrimes	struct socket *last;
811541Srgrimes
821541Srgrimes	last = 0;
8324936Sphk	LIST_FOREACH(rp, &rawcb_list, list) {
841541Srgrimes		if (rp->rcb_proto.sp_family != proto->sp_family)
851541Srgrimes			continue;
861541Srgrimes		if (rp->rcb_proto.sp_protocol  &&
871541Srgrimes		    rp->rcb_proto.sp_protocol != proto->sp_protocol)
881541Srgrimes			continue;
891541Srgrimes		/*
901541Srgrimes		 * We assume the lower level routines have
911541Srgrimes		 * placed the address in a canonical format
921541Srgrimes		 * suitable for a structure comparison.
931541Srgrimes		 *
941541Srgrimes		 * Note that if the lengths are not the same
951541Srgrimes		 * the comparison will fail at the first byte.
961541Srgrimes		 */
971541Srgrimes#define	equal(a1, a2) \
981541Srgrimes  (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
991541Srgrimes		if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst))
1001541Srgrimes			continue;
1011541Srgrimes		if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
1021541Srgrimes			continue;
1031541Srgrimes		if (last) {
1041541Srgrimes			struct mbuf *n;
1053443Sphk			n = m_copy(m, 0, (int)M_COPYALL);
1063443Sphk			if (n) {
1071541Srgrimes				if (sbappendaddr(&last->so_rcv, src,
1081541Srgrimes				    n, (struct mbuf *)0) == 0)
1091541Srgrimes					/* should notify about lost packet */
1101541Srgrimes					m_freem(n);
1111541Srgrimes				else {
1121541Srgrimes					sorwakeup(last);
1131541Srgrimes					sockets++;
1141541Srgrimes				}
1151541Srgrimes			}
1161541Srgrimes		}
1171541Srgrimes		last = rp->rcb_socket;
1181541Srgrimes	}
1191541Srgrimes	if (last) {
1201541Srgrimes		if (sbappendaddr(&last->so_rcv, src,
1211541Srgrimes		    m, (struct mbuf *)0) == 0)
1221541Srgrimes			m_freem(m);
1231541Srgrimes		else {
1241541Srgrimes			sorwakeup(last);
1251541Srgrimes			sockets++;
1261541Srgrimes		}
1271541Srgrimes	} else
1281541Srgrimes		m_freem(m);
1291541Srgrimes}
1301541Srgrimes
1311541Srgrimes/*ARGSUSED*/
1321541Srgrimesvoid
13312881Sbderaw_ctlinput(cmd, arg, dummy)
1341541Srgrimes	int cmd;
1351541Srgrimes	struct sockaddr *arg;
13612881Sbde	void *dummy;
1371541Srgrimes{
1381541Srgrimes
1391541Srgrimes	if (cmd < 0 || cmd > PRC_NCMDS)
1401541Srgrimes		return;
1411541Srgrimes	/* INCOMPLETE */
1421541Srgrimes}
1431541Srgrimes
14425201Swollmanstatic int
14525201Swollmanraw_uabort(struct socket *so)
1461541Srgrimes{
14725201Swollman	struct rawcb *rp = sotorawcb(so);
1481541Srgrimes
14925201Swollman	if (rp == 0)
15025201Swollman		return EINVAL;
15125201Swollman	raw_disconnect(rp);
15225201Swollman	sofree(so);
15325201Swollman	soisdisconnected(so);
15425201Swollman	return 0;
15525201Swollman}
1561541Srgrimes
15725201Swollman/* pru_accept is EOPNOTSUPP */
1581541Srgrimes
15925201Swollmanstatic int
16025201Swollmanraw_uattach(struct socket *so, int proto, struct proc *p)
16125201Swollman{
16225201Swollman	struct rawcb *rp = sotorawcb(so);
16325201Swollman	int error;
1641541Srgrimes
16525201Swollman	if (rp == 0)
16625201Swollman		return EINVAL;
16725201Swollman	if (p && (error = suser(p->p_ucred, &p->p_acflag)) != 0)
16825201Swollman		return error;
16925201Swollman	return raw_attach(so, proto);
17025201Swollman}
1711541Srgrimes
17225201Swollmanstatic int
17325201Swollmanraw_ubind(struct socket *so, struct mbuf *nam, struct proc *p)
17425201Swollman{
17525201Swollman	return EINVAL;
17625201Swollman}
1771541Srgrimes
17825201Swollmanstatic int
17925201Swollmanraw_uconnect(struct socket *so, struct mbuf *nam, struct proc *p)
18025201Swollman{
18125201Swollman	return EINVAL;
18225201Swollman}
1831541Srgrimes
18425201Swollman/* pru_connect2 is EOPNOTSUPP */
18525201Swollman/* pru_control is EOPNOTSUPP */
1861541Srgrimes
18725201Swollmanstatic int
18825201Swollmanraw_udetach(struct socket *so)
18925201Swollman{
19025201Swollman	struct rawcb *rp = sotorawcb(so);
1911541Srgrimes
19225201Swollman	if (rp == 0)
19325201Swollman		return EINVAL;
1941541Srgrimes
19525201Swollman	raw_detach(rp);
19625201Swollman	return 0;
19725201Swollman}
1981541Srgrimes
19925201Swollmanstatic int
20025201Swollmanraw_udisconnect(struct socket *so)
20125201Swollman{
20225201Swollman	struct rawcb *rp = sotorawcb(so);
2031541Srgrimes
20425201Swollman	if (rp == 0)
20525201Swollman		return EINVAL;
20625201Swollman	if (rp->rcb_faddr == 0) {
20725201Swollman		return ENOTCONN;
20825201Swollman	}
20925201Swollman	raw_disconnect(rp);
21025201Swollman	soisdisconnected(so);
21125201Swollman	return 0;
21225201Swollman}
2131541Srgrimes
21425201Swollman/* pru_listen is EOPNOTSUPP */
2151541Srgrimes
21625201Swollmanstatic int
21725201Swollmanraw_upeeraddr(struct socket *so, struct mbuf *nam)
21825201Swollman{
21925201Swollman	struct rawcb *rp = sotorawcb(so);
22025201Swollman	unsigned len;
2211541Srgrimes
22225201Swollman	if (rp == 0)
22325201Swollman		return EINVAL;
22425201Swollman	if (rp->rcb_faddr == 0) {
22525201Swollman		return ENOTCONN;
22625201Swollman	}
22725201Swollman	len = rp->rcb_faddr->sa_len;
22825201Swollman	bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), len);
22925201Swollman	nam->m_len = len;
23025201Swollman	return 0;
23125201Swollman}
2321541Srgrimes
23325201Swollman/* pru_rcvd is EOPNOTSUPP */
23425201Swollman/* pru_rcvoob is EOPNOTSUPP */
23525201Swollman
23625201Swollmanstatic int
23725201Swollmanraw_usend(struct socket *so, int flags, struct mbuf *m,
23825201Swollman	  struct mbuf *nam, struct mbuf *control, struct proc *p)
23925201Swollman{
24025201Swollman	int error;
24125201Swollman	struct rawcb *rp = sotorawcb(so);
24225201Swollman
24325201Swollman	if (rp == 0) {
24425201Swollman		error = EINVAL;
24525201Swollman		goto release;
2461541Srgrimes	}
24725201Swollman
24825201Swollman	if (flags & PRUS_OOB) {
24925201Swollman		error = EOPNOTSUPP;
25025201Swollman		goto release;
25125201Swollman	}
25225201Swollman
25325201Swollman	if (control && control->m_len) {
25425201Swollman		error = EOPNOTSUPP;
25525201Swollman		goto release;
25625201Swollman	}
25725201Swollman	if (nam) {
25825201Swollman		if (rp->rcb_faddr) {
25925201Swollman			error = EISCONN;
26025201Swollman			goto release;
26125201Swollman		}
26225201Swollman		rp->rcb_faddr = mtod(nam, struct sockaddr *);
26325201Swollman	} else if (rp->rcb_faddr == 0) {
26425201Swollman		error = ENOTCONN;
26525201Swollman		goto release;
26625201Swollman	}
26725201Swollman	error = (*so->so_proto->pr_output)(m, so);
26825201Swollman	m = NULL;
26925201Swollman	if (nam)
27025201Swollman		rp->rcb_faddr = 0;
2711541Srgrimesrelease:
2721541Srgrimes	if (m != NULL)
2731541Srgrimes		m_freem(m);
2741541Srgrimes	return (error);
2751541Srgrimes}
27625201Swollman
27725201Swollman/* pru_sense is null */
27825201Swollman
27925201Swollmanstatic int
28025201Swollmanraw_ushutdown(struct socket *so)
28125201Swollman{
28225201Swollman	struct rawcb *rp = sotorawcb(so);
28325201Swollman
28425201Swollman	if (rp == 0)
28525201Swollman		return EINVAL;
28625201Swollman	socantsendmore(so);
28725201Swollman	return 0;
28825201Swollman}
28925201Swollman
29025201Swollmanstatic int
29125201Swollmanraw_usockaddr(struct socket *so, struct mbuf *nam)
29225201Swollman{
29325201Swollman	struct rawcb *rp = sotorawcb(so);
29425201Swollman	unsigned len;
29525201Swollman
29625201Swollman	if (rp == 0)
29725201Swollman		return EINVAL;
29825201Swollman	if (rp->rcb_laddr == 0)
29925201Swollman		return EINVAL;
30025201Swollman	len = rp->rcb_laddr->sa_len;
30125201Swollman	bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), len);
30225201Swollman	nam->m_len = len;
30325201Swollman	return 0;
30425201Swollman}
30525201Swollman
30625201Swollmanstruct pr_usrreqs raw_usrreqs = {
30725201Swollman	raw_uabort, pru_accept_notsupp, raw_uattach, raw_ubind, raw_uconnect,
30825201Swollman	pru_connect2_notsupp, pru_control_notsupp, raw_udetach,
30925201Swollman	raw_udisconnect, pru_listen_notsupp, raw_upeeraddr, pru_rcvd_notsupp,
31025201Swollman	pru_rcvoob_notsupp, raw_usend, pru_sense_null, raw_ushutdown,
31125201Swollman	raw_usockaddr, sosend, soreceive, soselect
31225201Swollman};
313