raw_usrreq.c revision 1541
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
341541Srgrimes */
351541Srgrimes
361541Srgrimes#include <sys/param.h>
371541Srgrimes#include <sys/mbuf.h>
381541Srgrimes#include <sys/domain.h>
391541Srgrimes#include <sys/protosw.h>
401541Srgrimes#include <sys/socket.h>
411541Srgrimes#include <sys/socketvar.h>
421541Srgrimes#include <sys/errno.h>
431541Srgrimes
441541Srgrimes#include <net/if.h>
451541Srgrimes#include <net/route.h>
461541Srgrimes#include <net/netisr.h>
471541Srgrimes#include <net/raw_cb.h>
481541Srgrimes
491541Srgrimes/*
501541Srgrimes * Initialize raw connection block q.
511541Srgrimes */
521541Srgrimesvoid
531541Srgrimesraw_init()
541541Srgrimes{
551541Srgrimes
561541Srgrimes	rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
571541Srgrimes}
581541Srgrimes
591541Srgrimes
601541Srgrimes/*
611541Srgrimes * Raw protocol input routine.  Find the socket
621541Srgrimes * associated with the packet(s) and move them over.  If
631541Srgrimes * nothing exists for this packet, drop it.
641541Srgrimes */
651541Srgrimes/*
661541Srgrimes * Raw protocol interface.
671541Srgrimes */
681541Srgrimesvoid
691541Srgrimesraw_input(m0, proto, src, dst)
701541Srgrimes	struct mbuf *m0;
711541Srgrimes	register struct sockproto *proto;
721541Srgrimes	struct sockaddr *src, *dst;
731541Srgrimes{
741541Srgrimes	register struct rawcb *rp;
751541Srgrimes	register struct mbuf *m = m0;
761541Srgrimes	register int sockets = 0;
771541Srgrimes	struct socket *last;
781541Srgrimes
791541Srgrimes	last = 0;
801541Srgrimes	for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
811541Srgrimes		if (rp->rcb_proto.sp_family != proto->sp_family)
821541Srgrimes			continue;
831541Srgrimes		if (rp->rcb_proto.sp_protocol  &&
841541Srgrimes		    rp->rcb_proto.sp_protocol != proto->sp_protocol)
851541Srgrimes			continue;
861541Srgrimes		/*
871541Srgrimes		 * We assume the lower level routines have
881541Srgrimes		 * placed the address in a canonical format
891541Srgrimes		 * suitable for a structure comparison.
901541Srgrimes		 *
911541Srgrimes		 * Note that if the lengths are not the same
921541Srgrimes		 * the comparison will fail at the first byte.
931541Srgrimes		 */
941541Srgrimes#define	equal(a1, a2) \
951541Srgrimes  (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
961541Srgrimes		if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst))
971541Srgrimes			continue;
981541Srgrimes		if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
991541Srgrimes			continue;
1001541Srgrimes		if (last) {
1011541Srgrimes			struct mbuf *n;
1021541Srgrimes			if (n = m_copy(m, 0, (int)M_COPYALL)) {
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
1291541Srgrimesraw_ctlinput(cmd, arg)
1301541Srgrimes	int cmd;
1311541Srgrimes	struct sockaddr *arg;
1321541Srgrimes{
1331541Srgrimes
1341541Srgrimes	if (cmd < 0 || cmd > PRC_NCMDS)
1351541Srgrimes		return;
1361541Srgrimes	/* INCOMPLETE */
1371541Srgrimes}
1381541Srgrimes
1391541Srgrimes/*ARGSUSED*/
1401541Srgrimesint
1411541Srgrimesraw_usrreq(so, req, m, nam, control)
1421541Srgrimes	struct socket *so;
1431541Srgrimes	int req;
1441541Srgrimes	struct mbuf *m, *nam, *control;
1451541Srgrimes{
1461541Srgrimes	register struct rawcb *rp = sotorawcb(so);
1471541Srgrimes	register int error = 0;
1481541Srgrimes	int len;
1491541Srgrimes
1501541Srgrimes	if (req == PRU_CONTROL)
1511541Srgrimes		return (EOPNOTSUPP);
1521541Srgrimes	if (control && control->m_len) {
1531541Srgrimes		error = EOPNOTSUPP;
1541541Srgrimes		goto release;
1551541Srgrimes	}
1561541Srgrimes	if (rp == 0) {
1571541Srgrimes		error = EINVAL;
1581541Srgrimes		goto release;
1591541Srgrimes	}
1601541Srgrimes	switch (req) {
1611541Srgrimes
1621541Srgrimes	/*
1631541Srgrimes	 * Allocate a raw control block and fill in the
1641541Srgrimes	 * necessary info to allow packets to be routed to
1651541Srgrimes	 * the appropriate raw interface routine.
1661541Srgrimes	 */
1671541Srgrimes	case PRU_ATTACH:
1681541Srgrimes		if ((so->so_state & SS_PRIV) == 0) {
1691541Srgrimes			error = EACCES;
1701541Srgrimes			break;
1711541Srgrimes		}
1721541Srgrimes		error = raw_attach(so, (int)nam);
1731541Srgrimes		break;
1741541Srgrimes
1751541Srgrimes	/*
1761541Srgrimes	 * Destroy state just before socket deallocation.
1771541Srgrimes	 * Flush data or not depending on the options.
1781541Srgrimes	 */
1791541Srgrimes	case PRU_DETACH:
1801541Srgrimes		if (rp == 0) {
1811541Srgrimes			error = ENOTCONN;
1821541Srgrimes			break;
1831541Srgrimes		}
1841541Srgrimes		raw_detach(rp);
1851541Srgrimes		break;
1861541Srgrimes
1871541Srgrimes#ifdef notdef
1881541Srgrimes	/*
1891541Srgrimes	 * If a socket isn't bound to a single address,
1901541Srgrimes	 * the raw input routine will hand it anything
1911541Srgrimes	 * within that protocol family (assuming there's
1921541Srgrimes	 * nothing else around it should go to).
1931541Srgrimes	 */
1941541Srgrimes	case PRU_CONNECT:
1951541Srgrimes		if (rp->rcb_faddr) {
1961541Srgrimes			error = EISCONN;
1971541Srgrimes			break;
1981541Srgrimes		}
1991541Srgrimes		nam = m_copym(nam, 0, M_COPYALL, M_WAIT);
2001541Srgrimes		rp->rcb_faddr = mtod(nam, struct sockaddr *);
2011541Srgrimes		soisconnected(so);
2021541Srgrimes		break;
2031541Srgrimes
2041541Srgrimes	case PRU_BIND:
2051541Srgrimes		if (rp->rcb_laddr) {
2061541Srgrimes			error = EINVAL;			/* XXX */
2071541Srgrimes			break;
2081541Srgrimes		}
2091541Srgrimes		error = raw_bind(so, nam);
2101541Srgrimes		break;
2111541Srgrimes#endif
2121541Srgrimes
2131541Srgrimes	case PRU_CONNECT2:
2141541Srgrimes		error = EOPNOTSUPP;
2151541Srgrimes		goto release;
2161541Srgrimes
2171541Srgrimes	case PRU_DISCONNECT:
2181541Srgrimes		if (rp->rcb_faddr == 0) {
2191541Srgrimes			error = ENOTCONN;
2201541Srgrimes			break;
2211541Srgrimes		}
2221541Srgrimes		raw_disconnect(rp);
2231541Srgrimes		soisdisconnected(so);
2241541Srgrimes		break;
2251541Srgrimes
2261541Srgrimes	/*
2271541Srgrimes	 * Mark the connection as being incapable of further input.
2281541Srgrimes	 */
2291541Srgrimes	case PRU_SHUTDOWN:
2301541Srgrimes		socantsendmore(so);
2311541Srgrimes		break;
2321541Srgrimes
2331541Srgrimes	/*
2341541Srgrimes	 * Ship a packet out.  The appropriate raw output
2351541Srgrimes	 * routine handles any massaging necessary.
2361541Srgrimes	 */
2371541Srgrimes	case PRU_SEND:
2381541Srgrimes		if (nam) {
2391541Srgrimes			if (rp->rcb_faddr) {
2401541Srgrimes				error = EISCONN;
2411541Srgrimes				break;
2421541Srgrimes			}
2431541Srgrimes			rp->rcb_faddr = mtod(nam, struct sockaddr *);
2441541Srgrimes		} else if (rp->rcb_faddr == 0) {
2451541Srgrimes			error = ENOTCONN;
2461541Srgrimes			break;
2471541Srgrimes		}
2481541Srgrimes		error = (*so->so_proto->pr_output)(m, so);
2491541Srgrimes		m = NULL;
2501541Srgrimes		if (nam)
2511541Srgrimes			rp->rcb_faddr = 0;
2521541Srgrimes		break;
2531541Srgrimes
2541541Srgrimes	case PRU_ABORT:
2551541Srgrimes		raw_disconnect(rp);
2561541Srgrimes		sofree(so);
2571541Srgrimes		soisdisconnected(so);
2581541Srgrimes		break;
2591541Srgrimes
2601541Srgrimes	case PRU_SENSE:
2611541Srgrimes		/*
2621541Srgrimes		 * stat: don't bother with a blocksize.
2631541Srgrimes		 */
2641541Srgrimes		return (0);
2651541Srgrimes
2661541Srgrimes	/*
2671541Srgrimes	 * Not supported.
2681541Srgrimes	 */
2691541Srgrimes	case PRU_RCVOOB:
2701541Srgrimes	case PRU_RCVD:
2711541Srgrimes		return(EOPNOTSUPP);
2721541Srgrimes
2731541Srgrimes	case PRU_LISTEN:
2741541Srgrimes	case PRU_ACCEPT:
2751541Srgrimes	case PRU_SENDOOB:
2761541Srgrimes		error = EOPNOTSUPP;
2771541Srgrimes		break;
2781541Srgrimes
2791541Srgrimes	case PRU_SOCKADDR:
2801541Srgrimes		if (rp->rcb_laddr == 0) {
2811541Srgrimes			error = EINVAL;
2821541Srgrimes			break;
2831541Srgrimes		}
2841541Srgrimes		len = rp->rcb_laddr->sa_len;
2851541Srgrimes		bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len);
2861541Srgrimes		nam->m_len = len;
2871541Srgrimes		break;
2881541Srgrimes
2891541Srgrimes	case PRU_PEERADDR:
2901541Srgrimes		if (rp->rcb_faddr == 0) {
2911541Srgrimes			error = ENOTCONN;
2921541Srgrimes			break;
2931541Srgrimes		}
2941541Srgrimes		len = rp->rcb_faddr->sa_len;
2951541Srgrimes		bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len);
2961541Srgrimes		nam->m_len = len;
2971541Srgrimes		break;
2981541Srgrimes
2991541Srgrimes	default:
3001541Srgrimes		panic("raw_usrreq");
3011541Srgrimes	}
3021541Srgrimesrelease:
3031541Srgrimes	if (m != NULL)
3041541Srgrimes		m_freem(m);
3051541Srgrimes	return (error);
3061541Srgrimes}
307