xref: /csrg-svn/sys/net/raw_usrreq.c (revision 8723)
1*8723Sroot /*	raw_usrreq.c	4.22	82/10/20	*/
25121Swnj 
35121Swnj #include "../h/param.h"
45121Swnj #include "../h/mbuf.h"
55612Swnj #include "../h/protosw.h"
65121Swnj #include "../h/socket.h"
75121Swnj #include "../h/socketvar.h"
88636Sroot #include "../vax/mtpr.h"
95121Swnj #include "../net/if.h"
108395Swnj #include "../net/netisr.h"
115612Swnj #include "../net/raw_cb.h"
126509Ssam #include <errno.h>
135121Swnj 
145121Swnj /*
155612Swnj  * Initialize raw connection block q.
166211Swnj  */
175612Swnj raw_init()
185612Swnj {
196211Swnj 
205612Swnj 	rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
216211Swnj 	rawintrq.ifq_maxlen = IFQ_MAXLEN;
225612Swnj }
235612Swnj 
245612Swnj /*
255121Swnj  * Raw protocol interface.
265121Swnj  */
276529Ssam raw_input(m0, proto, src, dst)
285612Swnj 	struct mbuf *m0;
296509Ssam 	struct sockproto *proto;
306529Ssam 	struct sockaddr *src, *dst;
315121Swnj {
325612Swnj 	register struct mbuf *m;
335612Swnj 	struct raw_header *rh;
345121Swnj 	int s;
355121Swnj 
365612Swnj 	/*
375612Swnj 	 * Rip off an mbuf for a generic header.
385612Swnj 	 */
395612Swnj 	m = m_get(M_DONTWAIT);
405612Swnj 	if (m == 0) {
415612Swnj 		m_freem(m0);
425612Swnj 		return;
435612Swnj 	}
445612Swnj 	m->m_next = m0;
455612Swnj 	m->m_len = sizeof(struct raw_header);
465612Swnj 	rh = mtod(m, struct raw_header *);
476509Ssam 	rh->raw_dst = *dst;
486509Ssam 	rh->raw_src = *src;
496509Ssam 	rh->raw_proto = *proto;
505612Swnj 
515612Swnj 	/*
525612Swnj 	 * Header now contains enough info to decide
535612Swnj 	 * which socket to place packet in (if any).
545612Swnj 	 * Queue it up for the raw protocol process
555612Swnj 	 * running at software interrupt level.
565612Swnj 	 */
575121Swnj 	s = splimp();
586211Swnj 	if (IF_QFULL(&rawintrq))
596211Swnj 		m_freem(m);
606211Swnj 	else
616211Swnj 		IF_ENQUEUE(&rawintrq, m);
625121Swnj 	splx(s);
636263Swnj 	schednetisr(NETISR_RAW);
645121Swnj }
655121Swnj 
665612Swnj /*
675612Swnj  * Raw protocol input routine.  Process packets entered
685612Swnj  * into the queue at interrupt time.  Find the socket
695612Swnj  * associated with the packet(s) and move them over.  If
705612Swnj  * nothing exists for this packet, drop it.
715612Swnj  */
725121Swnj rawintr()
735121Swnj {
745121Swnj 	int s;
755121Swnj 	struct mbuf *m;
765612Swnj 	register struct rawcb *rp;
776509Ssam 	register struct protosw *lproto;
786529Ssam 	register struct raw_header *rh;
795612Swnj 	struct socket *last;
805121Swnj 
815121Swnj next:
825121Swnj 	s = splimp();
835121Swnj 	IF_DEQUEUE(&rawintrq, m);
845121Swnj 	splx(s);
855121Swnj 	if (m == 0)
865121Swnj 		return;
876509Ssam 	rh = mtod(m, struct raw_header *);
885612Swnj 	last = 0;
895612Swnj 	for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
906509Ssam 		lproto = rp->rcb_socket->so_proto;
916509Ssam 		if (lproto->pr_family != rh->raw_proto.sp_family)
925612Swnj 			continue;
936509Ssam 		if (lproto->pr_protocol &&
946509Ssam 		    lproto->pr_protocol != rh->raw_proto.sp_protocol)
955612Swnj 			continue;
965612Swnj 		/*
975612Swnj 		 * We assume the lower level routines have
985612Swnj 		 * placed the address in a canonical format
996509Ssam 		 * suitable for a structure comparison.
1005612Swnj 		 */
1016529Ssam #define equal(a1, a2) \
1026529Ssam 	(bcmp((caddr_t)&(a1), (caddr_t)&(a2), sizeof (struct sockaddr)) == 0)
1036509Ssam 		if ((rp->rcb_flags & RAW_LADDR) &&
1046529Ssam 		    !equal(rp->rcb_laddr, rh->raw_dst))
1055612Swnj 			continue;
1066509Ssam 		if ((rp->rcb_flags & RAW_FADDR) &&
1076529Ssam 		    !equal(rp->rcb_faddr, rh->raw_src))
1086509Ssam 			continue;
1095612Swnj 		if (last) {
1105612Swnj 			struct mbuf *n;
1117517Sroot 			if ((n = m_copy(m->m_next, 0, (int)M_COPYALL)) == 0)
1125612Swnj 				goto nospace;
1136509Ssam 			if (sbappendaddr(&last->so_rcv, &rh->raw_src, n)==0) {
1146509Ssam 				/* should notify about lost packet */
1155646Ssam 				m_freem(n);
1165646Ssam 				goto nospace;
1175646Ssam 			}
1185612Swnj 			sorwakeup(last);
1195612Swnj 		}
1205612Swnj nospace:
1216509Ssam 		last = rp->rcb_socket;
1225612Swnj 	}
1236584Ssam 	if (last) {
1246584Ssam 		m = m_free(m);		/* header */
1256584Ssam 		if (sbappendaddr(&last->so_rcv, &rh->raw_src, m) == 0)
1266584Ssam 			goto drop;
1276584Ssam 		sorwakeup(last);
1286584Ssam 		goto next;
1296584Ssam 	}
1305121Swnj drop:
1315121Swnj 	m_freem(m);
1325121Swnj 	goto next;
1335121Swnj }
1345121Swnj 
1358636Sroot /*ARGSUSED*/
1366584Ssam raw_ctlinput(cmd, arg)
1376584Ssam 	int cmd;
1386584Ssam 	caddr_t arg;
1396584Ssam {
1406591Ssam 
1416591Ssam 	if (cmd < 0 || cmd > PRC_NCMDS)
1426591Ssam 		return;
1438636Sroot 	/* INCOMPLETE */
1446584Ssam }
1456584Ssam 
1465121Swnj /*ARGSUSED*/
1478395Swnj raw_usrreq(so, req, m, nam, opt)
1485121Swnj 	struct socket *so;
1495121Swnj 	int req;
1508395Swnj 	struct mbuf *m, *nam;
1518395Swnj 	struct socketopt *opt;
1525121Swnj {
1535612Swnj 	register struct rawcb *rp = sotorawcb(so);
1545612Swnj 	int error = 0;
1555121Swnj 
1565612Swnj 	if (rp == 0 && req != PRU_ATTACH)
1575612Swnj 		return (EINVAL);
1585121Swnj 
1595612Swnj 	switch (req) {
1605612Swnj 
1615612Swnj 	/*
1625612Swnj 	 * Allocate a raw control block and fill in the
1635612Swnj 	 * necessary info to allow packets to be routed to
1645612Swnj 	 * the appropriate raw interface routine.
1655612Swnj 	 */
1665612Swnj 	case PRU_ATTACH:
1676211Swnj 		if ((so->so_state & SS_PRIV) == 0)
1686584Ssam 			return (EACCES);
1695612Swnj 		if (rp)
1706211Swnj 			return (EINVAL);
1718395Swnj 		error = raw_attach(so);
1725612Swnj 		break;
1735612Swnj 
1745612Swnj 	/*
1755612Swnj 	 * Destroy state just before socket deallocation.
1765612Swnj 	 * Flush data or not depending on the options.
1775612Swnj 	 */
1785612Swnj 	case PRU_DETACH:
1795612Swnj 		if (rp == 0)
1805612Swnj 			return (ENOTCONN);
1815612Swnj 		raw_detach(rp);
1825612Swnj 		break;
1835612Swnj 
1845612Swnj 	/*
1855612Swnj 	 * If a socket isn't bound to a single address,
1865612Swnj 	 * the raw input routine will hand it anything
1875612Swnj 	 * within that protocol family (assuming there's
1885612Swnj 	 * nothing else around it should go to).
1895612Swnj 	 */
1905612Swnj 	case PRU_CONNECT:
1916509Ssam 		if (rp->rcb_flags & RAW_FADDR)
1925612Swnj 			return (EISCONN);
1938395Swnj 		raw_connaddr(rp, nam);
1945612Swnj 		soisconnected(so);
1955612Swnj 		break;
1965612Swnj 
1975612Swnj 	case PRU_DISCONNECT:
1986509Ssam 		if ((rp->rcb_flags & RAW_FADDR) == 0)
1995612Swnj 			return (ENOTCONN);
2005612Swnj 		raw_disconnect(rp);
2015612Swnj 		soisdisconnected(so);
2025612Swnj 		break;
2035612Swnj 
2045612Swnj 	/*
2055612Swnj 	 * Mark the connection as being incapable of further input.
2065612Swnj 	 */
2075612Swnj 	case PRU_SHUTDOWN:
2085612Swnj 		socantsendmore(so);
2095612Swnj 		break;
2105612Swnj 
2115612Swnj 	/*
2125612Swnj 	 * Ship a packet out.  The appropriate raw output
2135612Swnj 	 * routine handles any massaging necessary.
2145612Swnj 	 */
2155612Swnj 	case PRU_SEND:
2168395Swnj 		if (nam) {
2176509Ssam 			if (rp->rcb_flags & RAW_FADDR)
2185612Swnj 				return (EISCONN);
2198395Swnj 			raw_connaddr(rp, nam);
2206509Ssam 		} else if ((rp->rcb_flags & RAW_FADDR) == 0)
2215612Swnj 			return (ENOTCONN);
2226505Ssam 		error = (*so->so_proto->pr_output)(m, so);
2238395Swnj 		if (nam)
2246509Ssam 			rp->rcb_flags &= ~RAW_FADDR;
2255612Swnj 		break;
2265612Swnj 
2275612Swnj 	case PRU_ABORT:
2285612Swnj 		raw_disconnect(rp);
2295612Swnj 		sofree(so);
2305612Swnj 		soisdisconnected(so);
2315612Swnj 		break;
2325612Swnj 
2335612Swnj 	/*
2345612Swnj 	 * Not supported.
2355612Swnj 	 */
2365612Swnj 	case PRU_ACCEPT:
2375612Swnj 	case PRU_RCVD:
2385612Swnj 	case PRU_CONTROL:
2395612Swnj 	case PRU_SENSE:
2405612Swnj 	case PRU_RCVOOB:
2415612Swnj 	case PRU_SENDOOB:
2425612Swnj 		error = EOPNOTSUPP;
2435612Swnj 		break;
2445612Swnj 
2456509Ssam 	case PRU_SOCKADDR:
246*8723Sroot 		bcopy((caddr_t)&rp->rcb_laddr, mtod(nam, caddr_t),
2478395Swnj 		    sizeof (struct sockaddr));
2488395Swnj 		nam->m_len = sizeof (struct sockaddr);
2496509Ssam 		break;
2506509Ssam 
2515612Swnj 	default:
2525612Swnj 		panic("raw_usrreq");
2535612Swnj 	}
2545612Swnj 	return (error);
2555121Swnj }
256