xref: /csrg-svn/sys/net/raw_usrreq.c (revision 56529)
123162Smckusick /*
229068Smckusick  * Copyright (c) 1980, 1986 Regents of the University of California.
333183Sbostic  * All rights reserved.
423162Smckusick  *
544465Sbostic  * %sccs.include.redist.c%
633183Sbostic  *
7*56529Sbostic  *	@(#)raw_usrreq.c	7.12 (Berkeley) 10/11/92
823162Smckusick  */
95121Swnj 
10*56529Sbostic #include <sys/param.h>
11*56529Sbostic #include <sys/mbuf.h>
12*56529Sbostic #include <sys/domain.h>
13*56529Sbostic #include <sys/protosw.h>
14*56529Sbostic #include <sys/socket.h>
15*56529Sbostic #include <sys/socketvar.h>
16*56529Sbostic #include <sys/errno.h>
1710890Ssam 
18*56529Sbostic #include <net/if.h>
19*56529Sbostic #include <net/route.h>
20*56529Sbostic #include <net/netisr.h>
21*56529Sbostic #include <net/raw_cb.h>
225121Swnj 
235121Swnj /*
245612Swnj  * Initialize raw connection block q.
256211Swnj  */
265612Swnj raw_init()
275612Swnj {
286211Swnj 
295612Swnj 	rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
305612Swnj }
315612Swnj 
3237472Ssklower 
335612Swnj /*
3437472Ssklower  * Raw protocol input routine.  Find the socket
3537472Ssklower  * associated with the packet(s) and move them over.  If
3637472Ssklower  * nothing exists for this packet, drop it.
3737472Ssklower  */
3837472Ssklower /*
395121Swnj  * Raw protocol interface.
405121Swnj  */
416529Ssam raw_input(m0, proto, src, dst)
425612Swnj 	struct mbuf *m0;
4339181Ssklower 	register struct sockproto *proto;
446529Ssam 	struct sockaddr *src, *dst;
455121Swnj {
465612Swnj 	register struct rawcb *rp;
4737472Ssklower 	register struct mbuf *m = m0;
4839181Ssklower 	register int sockets = 0;
495612Swnj 	struct socket *last;
505121Swnj 
515612Swnj 	last = 0;
525612Swnj 	for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
5337472Ssklower 		if (rp->rcb_proto.sp_family != proto->sp_family)
545612Swnj 			continue;
5521769Skarels 		if (rp->rcb_proto.sp_protocol  &&
5637472Ssklower 		    rp->rcb_proto.sp_protocol != proto->sp_protocol)
575612Swnj 			continue;
585612Swnj 		/*
595612Swnj 		 * We assume the lower level routines have
605612Swnj 		 * placed the address in a canonical format
616509Ssam 		 * suitable for a structure comparison.
6237472Ssklower 		 *
6337472Ssklower 		 * Note that if the lengths are not the same
6437472Ssklower 		 * the comparison will fail at the first byte.
655612Swnj 		 */
6637472Ssklower #define	equal(a1, a2) \
6737472Ssklower   (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
6837472Ssklower 		if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst))
695612Swnj 			continue;
7037472Ssklower 		if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
716509Ssam 			continue;
725612Swnj 		if (last) {
735612Swnj 			struct mbuf *n;
7437472Ssklower 			if (n = m_copy(m, 0, (int)M_COPYALL)) {
7537472Ssklower 				if (sbappendaddr(&last->so_rcv, src,
7621531Skarels 				    n, (struct mbuf *)0) == 0)
7721531Skarels 					/* should notify about lost packet */
7821531Skarels 					m_freem(n);
7939181Ssklower 				else {
8021531Skarels 					sorwakeup(last);
8139181Ssklower 					sockets++;
8239181Ssklower 				}
835646Ssam 			}
845612Swnj 		}
856509Ssam 		last = rp->rcb_socket;
865612Swnj 	}
876584Ssam 	if (last) {
8837472Ssklower 		if (sbappendaddr(&last->so_rcv, src,
8937472Ssklower 		    m, (struct mbuf *)0) == 0)
9037472Ssklower 			m_freem(m);
9139181Ssklower 		else {
9221531Skarels 			sorwakeup(last);
9339181Ssklower 			sockets++;
9439181Ssklower 		}
9521531Skarels 	} else
9621531Skarels 		m_freem(m);
9739181Ssklower 	return (sockets);
985121Swnj }
995121Swnj 
1008636Sroot /*ARGSUSED*/
1016584Ssam raw_ctlinput(cmd, arg)
1026584Ssam 	int cmd;
10326379Skarels 	struct sockaddr *arg;
1046584Ssam {
1056591Ssam 
1066591Ssam 	if (cmd < 0 || cmd > PRC_NCMDS)
1076591Ssam 		return;
1088636Sroot 	/* INCOMPLETE */
1096584Ssam }
1106584Ssam 
1115121Swnj /*ARGSUSED*/
11240787Ssklower raw_usrreq(so, req, m, nam, control)
1135121Swnj 	struct socket *so;
1145121Swnj 	int req;
11540787Ssklower 	struct mbuf *m, *nam, *control;
1165121Swnj {
1175612Swnj 	register struct rawcb *rp = sotorawcb(so);
11812783Ssam 	register int error = 0;
11937472Ssklower 	int len;
1205121Swnj 
12125501Skarels 	if (req == PRU_CONTROL)
12225501Skarels 		return (EOPNOTSUPP);
12340787Ssklower 	if (control && control->m_len) {
12412783Ssam 		error = EOPNOTSUPP;
12512783Ssam 		goto release;
12612783Ssam 	}
12737472Ssklower 	if (rp == 0) {
12812783Ssam 		error = EINVAL;
12912783Ssam 		goto release;
13012783Ssam 	}
1315612Swnj 	switch (req) {
1325612Swnj 
1335612Swnj 	/*
1345612Swnj 	 * Allocate a raw control block and fill in the
1355612Swnj 	 * necessary info to allow packets to be routed to
1365612Swnj 	 * the appropriate raw interface routine.
1375612Swnj 	 */
1385612Swnj 	case PRU_ATTACH:
13912783Ssam 		if ((so->so_state & SS_PRIV) == 0) {
14012783Ssam 			error = EACCES;
14113116Ssam 			break;
14212783Ssam 		}
14321769Skarels 		error = raw_attach(so, (int)nam);
1445612Swnj 		break;
1455612Swnj 
1465612Swnj 	/*
1475612Swnj 	 * Destroy state just before socket deallocation.
1485612Swnj 	 * Flush data or not depending on the options.
1495612Swnj 	 */
1505612Swnj 	case PRU_DETACH:
15112783Ssam 		if (rp == 0) {
15212783Ssam 			error = ENOTCONN;
15313116Ssam 			break;
15412783Ssam 		}
1555612Swnj 		raw_detach(rp);
1565612Swnj 		break;
1575612Swnj 
15837472Ssklower #ifdef notdef
1595612Swnj 	/*
1605612Swnj 	 * If a socket isn't bound to a single address,
1615612Swnj 	 * the raw input routine will hand it anything
1625612Swnj 	 * within that protocol family (assuming there's
1635612Swnj 	 * nothing else around it should go to).
1645612Swnj 	 */
1655612Swnj 	case PRU_CONNECT:
16637472Ssklower 		if (rp->rcb_faddr) {
16712783Ssam 			error = EISCONN;
16813116Ssam 			break;
16912783Ssam 		}
17037472Ssklower 		nam = m_copym(nam, 0, M_COPYALL, M_WAIT);
17137472Ssklower 		rp->rcb_faddr = mtod(nam, struct sockaddr *);
1725612Swnj 		soisconnected(so);
1735612Swnj 		break;
1745612Swnj 
17512783Ssam 	case PRU_BIND:
17637472Ssklower 		if (rp->rcb_laddr) {
17712783Ssam 			error = EINVAL;			/* XXX */
17813116Ssam 			break;
17912783Ssam 		}
18012783Ssam 		error = raw_bind(so, nam);
18112783Ssam 		break;
18237472Ssklower #endif
18312783Ssam 
18437472Ssklower 	case PRU_CONNECT2:
18537472Ssklower 		error = EOPNOTSUPP;
18637472Ssklower 		goto release;
18737472Ssklower 
1885612Swnj 	case PRU_DISCONNECT:
18937472Ssklower 		if (rp->rcb_faddr == 0) {
19012783Ssam 			error = ENOTCONN;
19113116Ssam 			break;
19212783Ssam 		}
1935612Swnj 		raw_disconnect(rp);
1945612Swnj 		soisdisconnected(so);
1955612Swnj 		break;
1965612Swnj 
1975612Swnj 	/*
1985612Swnj 	 * Mark the connection as being incapable of further input.
1995612Swnj 	 */
2005612Swnj 	case PRU_SHUTDOWN:
2015612Swnj 		socantsendmore(so);
2025612Swnj 		break;
2035612Swnj 
2045612Swnj 	/*
2055612Swnj 	 * Ship a packet out.  The appropriate raw output
2065612Swnj 	 * routine handles any massaging necessary.
2075612Swnj 	 */
2085612Swnj 	case PRU_SEND:
2098395Swnj 		if (nam) {
21037472Ssklower 			if (rp->rcb_faddr) {
21112783Ssam 				error = EISCONN;
21213116Ssam 				break;
21312783Ssam 			}
21437472Ssklower 			rp->rcb_faddr = mtod(nam, struct sockaddr *);
21537472Ssklower 		} else if (rp->rcb_faddr == 0) {
21612783Ssam 			error = ENOTCONN;
21713116Ssam 			break;
21812783Ssam 		}
2196505Ssam 		error = (*so->so_proto->pr_output)(m, so);
22012783Ssam 		m = NULL;
2218395Swnj 		if (nam)
22237472Ssklower 			rp->rcb_faddr = 0;
2235612Swnj 		break;
2245612Swnj 
2255612Swnj 	case PRU_ABORT:
2265612Swnj 		raw_disconnect(rp);
2275612Swnj 		sofree(so);
2285612Swnj 		soisdisconnected(so);
2295612Swnj 		break;
2305612Swnj 
23116974Skarels 	case PRU_SENSE:
23216974Skarels 		/*
23316974Skarels 		 * stat: don't bother with a blocksize.
23416974Skarels 		 */
23516974Skarels 		return (0);
23616974Skarels 
2375612Swnj 	/*
2385612Swnj 	 * Not supported.
2395612Swnj 	 */
24016773Sbloom 	case PRU_RCVOOB:
2415612Swnj 	case PRU_RCVD:
24216773Sbloom 		return(EOPNOTSUPP);
24316773Sbloom 
24425221Skarels 	case PRU_LISTEN:
24516773Sbloom 	case PRU_ACCEPT:
2465612Swnj 	case PRU_SENDOOB:
2475612Swnj 		error = EOPNOTSUPP;
2485612Swnj 		break;
2495612Swnj 
2506509Ssam 	case PRU_SOCKADDR:
25137472Ssklower 		if (rp->rcb_laddr == 0) {
25237472Ssklower 			error = EINVAL;
25337472Ssklower 			break;
25437472Ssklower 		}
25537472Ssklower 		len = rp->rcb_laddr->sa_len;
25637472Ssklower 		bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len);
25737472Ssklower 		nam->m_len = len;
2586509Ssam 		break;
2596509Ssam 
26014122Ssam 	case PRU_PEERADDR:
26137472Ssklower 		if (rp->rcb_faddr == 0) {
26237472Ssklower 			error = ENOTCONN;
26337472Ssklower 			break;
26437472Ssklower 		}
26537472Ssklower 		len = rp->rcb_faddr->sa_len;
26637472Ssklower 		bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len);
26737472Ssklower 		nam->m_len = len;
26814122Ssam 		break;
26914122Ssam 
2705612Swnj 	default:
2715612Swnj 		panic("raw_usrreq");
2725612Swnj 	}
27312783Ssam release:
27412783Ssam 	if (m != NULL)
27512783Ssam 		m_freem(m);
2765612Swnj 	return (error);
2775121Swnj }
278