xref: /csrg-svn/sys/net/raw_usrreq.c (revision 63211)
123162Smckusick /*
2*63211Sbostic  * Copyright (c) 1980, 1986, 1993
3*63211Sbostic  *	The Regents of the University of California.  All rights reserved.
423162Smckusick  *
544465Sbostic  * %sccs.include.redist.c%
633183Sbostic  *
7*63211Sbostic  *	@(#)raw_usrreq.c	8.1 (Berkeley) 06/10/93
823162Smckusick  */
95121Swnj 
1056529Sbostic #include <sys/param.h>
1156529Sbostic #include <sys/mbuf.h>
1256529Sbostic #include <sys/domain.h>
1356529Sbostic #include <sys/protosw.h>
1456529Sbostic #include <sys/socket.h>
1556529Sbostic #include <sys/socketvar.h>
1656529Sbostic #include <sys/errno.h>
1710890Ssam 
1856529Sbostic #include <net/if.h>
1956529Sbostic #include <net/route.h>
2056529Sbostic #include <net/netisr.h>
2156529Sbostic #include <net/raw_cb.h>
225121Swnj 
235121Swnj /*
245612Swnj  * Initialize raw connection block q.
256211Swnj  */
2661357Sbostic void
raw_init()275612Swnj raw_init()
285612Swnj {
296211Swnj 
305612Swnj 	rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
315612Swnj }
325612Swnj 
3337472Ssklower 
345612Swnj /*
3537472Ssklower  * Raw protocol input routine.  Find the socket
3637472Ssklower  * associated with the packet(s) and move them over.  If
3737472Ssklower  * nothing exists for this packet, drop it.
3837472Ssklower  */
3937472Ssklower /*
405121Swnj  * Raw protocol interface.
415121Swnj  */
4261357Sbostic void
raw_input(m0,proto,src,dst)436529Ssam raw_input(m0, proto, src, dst)
445612Swnj 	struct mbuf *m0;
4539181Ssklower 	register struct sockproto *proto;
466529Ssam 	struct sockaddr *src, *dst;
475121Swnj {
485612Swnj 	register struct rawcb *rp;
4937472Ssklower 	register struct mbuf *m = m0;
5039181Ssklower 	register int sockets = 0;
515612Swnj 	struct socket *last;
525121Swnj 
535612Swnj 	last = 0;
545612Swnj 	for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
5537472Ssklower 		if (rp->rcb_proto.sp_family != proto->sp_family)
565612Swnj 			continue;
5721769Skarels 		if (rp->rcb_proto.sp_protocol  &&
5837472Ssklower 		    rp->rcb_proto.sp_protocol != proto->sp_protocol)
595612Swnj 			continue;
605612Swnj 		/*
615612Swnj 		 * We assume the lower level routines have
625612Swnj 		 * placed the address in a canonical format
636509Ssam 		 * suitable for a structure comparison.
6437472Ssklower 		 *
6537472Ssklower 		 * Note that if the lengths are not the same
6637472Ssklower 		 * the comparison will fail at the first byte.
675612Swnj 		 */
6837472Ssklower #define	equal(a1, a2) \
6937472Ssklower   (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
7037472Ssklower 		if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst))
715612Swnj 			continue;
7237472Ssklower 		if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
736509Ssam 			continue;
745612Swnj 		if (last) {
755612Swnj 			struct mbuf *n;
7637472Ssklower 			if (n = m_copy(m, 0, (int)M_COPYALL)) {
7737472Ssklower 				if (sbappendaddr(&last->so_rcv, src,
7821531Skarels 				    n, (struct mbuf *)0) == 0)
7921531Skarels 					/* should notify about lost packet */
8021531Skarels 					m_freem(n);
8139181Ssklower 				else {
8221531Skarels 					sorwakeup(last);
8339181Ssklower 					sockets++;
8439181Ssklower 				}
855646Ssam 			}
865612Swnj 		}
876509Ssam 		last = rp->rcb_socket;
885612Swnj 	}
896584Ssam 	if (last) {
9037472Ssklower 		if (sbappendaddr(&last->so_rcv, src,
9137472Ssklower 		    m, (struct mbuf *)0) == 0)
9237472Ssklower 			m_freem(m);
9339181Ssklower 		else {
9421531Skarels 			sorwakeup(last);
9539181Ssklower 			sockets++;
9639181Ssklower 		}
9721531Skarels 	} else
9821531Skarels 		m_freem(m);
995121Swnj }
1005121Swnj 
1018636Sroot /*ARGSUSED*/
10261357Sbostic void
raw_ctlinput(cmd,arg)1036584Ssam raw_ctlinput(cmd, arg)
1046584Ssam 	int cmd;
10526379Skarels 	struct sockaddr *arg;
1066584Ssam {
1076591Ssam 
1086591Ssam 	if (cmd < 0 || cmd > PRC_NCMDS)
1096591Ssam 		return;
1108636Sroot 	/* INCOMPLETE */
1116584Ssam }
1126584Ssam 
1135121Swnj /*ARGSUSED*/
11461357Sbostic int
raw_usrreq(so,req,m,nam,control)11540787Ssklower raw_usrreq(so, req, m, nam, control)
1165121Swnj 	struct socket *so;
1175121Swnj 	int req;
11840787Ssklower 	struct mbuf *m, *nam, *control;
1195121Swnj {
1205612Swnj 	register struct rawcb *rp = sotorawcb(so);
12112783Ssam 	register int error = 0;
12237472Ssklower 	int len;
1235121Swnj 
12425501Skarels 	if (req == PRU_CONTROL)
12525501Skarels 		return (EOPNOTSUPP);
12640787Ssklower 	if (control && control->m_len) {
12712783Ssam 		error = EOPNOTSUPP;
12812783Ssam 		goto release;
12912783Ssam 	}
13037472Ssklower 	if (rp == 0) {
13112783Ssam 		error = EINVAL;
13212783Ssam 		goto release;
13312783Ssam 	}
1345612Swnj 	switch (req) {
1355612Swnj 
1365612Swnj 	/*
1375612Swnj 	 * Allocate a raw control block and fill in the
1385612Swnj 	 * necessary info to allow packets to be routed to
1395612Swnj 	 * the appropriate raw interface routine.
1405612Swnj 	 */
1415612Swnj 	case PRU_ATTACH:
14212783Ssam 		if ((so->so_state & SS_PRIV) == 0) {
14312783Ssam 			error = EACCES;
14413116Ssam 			break;
14512783Ssam 		}
14621769Skarels 		error = raw_attach(so, (int)nam);
1475612Swnj 		break;
1485612Swnj 
1495612Swnj 	/*
1505612Swnj 	 * Destroy state just before socket deallocation.
1515612Swnj 	 * Flush data or not depending on the options.
1525612Swnj 	 */
1535612Swnj 	case PRU_DETACH:
15412783Ssam 		if (rp == 0) {
15512783Ssam 			error = ENOTCONN;
15613116Ssam 			break;
15712783Ssam 		}
1585612Swnj 		raw_detach(rp);
1595612Swnj 		break;
1605612Swnj 
16137472Ssklower #ifdef notdef
1625612Swnj 	/*
1635612Swnj 	 * If a socket isn't bound to a single address,
1645612Swnj 	 * the raw input routine will hand it anything
1655612Swnj 	 * within that protocol family (assuming there's
1665612Swnj 	 * nothing else around it should go to).
1675612Swnj 	 */
1685612Swnj 	case PRU_CONNECT:
16937472Ssklower 		if (rp->rcb_faddr) {
17012783Ssam 			error = EISCONN;
17113116Ssam 			break;
17212783Ssam 		}
17337472Ssklower 		nam = m_copym(nam, 0, M_COPYALL, M_WAIT);
17437472Ssklower 		rp->rcb_faddr = mtod(nam, struct sockaddr *);
1755612Swnj 		soisconnected(so);
1765612Swnj 		break;
1775612Swnj 
17812783Ssam 	case PRU_BIND:
17937472Ssklower 		if (rp->rcb_laddr) {
18012783Ssam 			error = EINVAL;			/* XXX */
18113116Ssam 			break;
18212783Ssam 		}
18312783Ssam 		error = raw_bind(so, nam);
18412783Ssam 		break;
18537472Ssklower #endif
18612783Ssam 
18737472Ssklower 	case PRU_CONNECT2:
18837472Ssklower 		error = EOPNOTSUPP;
18937472Ssklower 		goto release;
19037472Ssklower 
1915612Swnj 	case PRU_DISCONNECT:
19237472Ssklower 		if (rp->rcb_faddr == 0) {
19312783Ssam 			error = ENOTCONN;
19413116Ssam 			break;
19512783Ssam 		}
1965612Swnj 		raw_disconnect(rp);
1975612Swnj 		soisdisconnected(so);
1985612Swnj 		break;
1995612Swnj 
2005612Swnj 	/*
2015612Swnj 	 * Mark the connection as being incapable of further input.
2025612Swnj 	 */
2035612Swnj 	case PRU_SHUTDOWN:
2045612Swnj 		socantsendmore(so);
2055612Swnj 		break;
2065612Swnj 
2075612Swnj 	/*
2085612Swnj 	 * Ship a packet out.  The appropriate raw output
2095612Swnj 	 * routine handles any massaging necessary.
2105612Swnj 	 */
2115612Swnj 	case PRU_SEND:
2128395Swnj 		if (nam) {
21337472Ssklower 			if (rp->rcb_faddr) {
21412783Ssam 				error = EISCONN;
21513116Ssam 				break;
21612783Ssam 			}
21737472Ssklower 			rp->rcb_faddr = mtod(nam, struct sockaddr *);
21837472Ssklower 		} else if (rp->rcb_faddr == 0) {
21912783Ssam 			error = ENOTCONN;
22013116Ssam 			break;
22112783Ssam 		}
2226505Ssam 		error = (*so->so_proto->pr_output)(m, so);
22312783Ssam 		m = NULL;
2248395Swnj 		if (nam)
22537472Ssklower 			rp->rcb_faddr = 0;
2265612Swnj 		break;
2275612Swnj 
2285612Swnj 	case PRU_ABORT:
2295612Swnj 		raw_disconnect(rp);
2305612Swnj 		sofree(so);
2315612Swnj 		soisdisconnected(so);
2325612Swnj 		break;
2335612Swnj 
23416974Skarels 	case PRU_SENSE:
23516974Skarels 		/*
23616974Skarels 		 * stat: don't bother with a blocksize.
23716974Skarels 		 */
23816974Skarels 		return (0);
23916974Skarels 
2405612Swnj 	/*
2415612Swnj 	 * Not supported.
2425612Swnj 	 */
24316773Sbloom 	case PRU_RCVOOB:
2445612Swnj 	case PRU_RCVD:
24516773Sbloom 		return(EOPNOTSUPP);
24616773Sbloom 
24725221Skarels 	case PRU_LISTEN:
24816773Sbloom 	case PRU_ACCEPT:
2495612Swnj 	case PRU_SENDOOB:
2505612Swnj 		error = EOPNOTSUPP;
2515612Swnj 		break;
2525612Swnj 
2536509Ssam 	case PRU_SOCKADDR:
25437472Ssklower 		if (rp->rcb_laddr == 0) {
25537472Ssklower 			error = EINVAL;
25637472Ssklower 			break;
25737472Ssklower 		}
25837472Ssklower 		len = rp->rcb_laddr->sa_len;
25937472Ssklower 		bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len);
26037472Ssklower 		nam->m_len = len;
2616509Ssam 		break;
2626509Ssam 
26314122Ssam 	case PRU_PEERADDR:
26437472Ssklower 		if (rp->rcb_faddr == 0) {
26537472Ssklower 			error = ENOTCONN;
26637472Ssklower 			break;
26737472Ssklower 		}
26837472Ssklower 		len = rp->rcb_faddr->sa_len;
26937472Ssklower 		bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len);
27037472Ssklower 		nam->m_len = len;
27114122Ssam 		break;
27214122Ssam 
2735612Swnj 	default:
2745612Swnj 		panic("raw_usrreq");
2755612Swnj 	}
27612783Ssam release:
27712783Ssam 	if (m != NULL)
27812783Ssam 		m_freem(m);
2795612Swnj 	return (error);
2805121Swnj }
281