xref: /csrg-svn/sys/net/raw_usrreq.c (revision 12783)
1*12783Ssam /*	raw_usrreq.c	4.26	83/05/27	*/
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"
810890Ssam #include "../h/errno.h"
910890Ssam 
105121Swnj #include "../net/if.h"
118395Swnj #include "../net/netisr.h"
125612Swnj #include "../net/raw_cb.h"
135121Swnj 
1410890Ssam #include "../vax/mtpr.h"
1510890Ssam 
165121Swnj /*
175612Swnj  * Initialize raw connection block q.
186211Swnj  */
195612Swnj raw_init()
205612Swnj {
216211Swnj 
225612Swnj 	rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
236211Swnj 	rawintrq.ifq_maxlen = IFQ_MAXLEN;
245612Swnj }
255612Swnj 
265612Swnj /*
275121Swnj  * Raw protocol interface.
285121Swnj  */
296529Ssam raw_input(m0, proto, src, dst)
305612Swnj 	struct mbuf *m0;
316509Ssam 	struct sockproto *proto;
326529Ssam 	struct sockaddr *src, *dst;
335121Swnj {
345612Swnj 	register struct mbuf *m;
355612Swnj 	struct raw_header *rh;
365121Swnj 	int s;
375121Swnj 
385612Swnj 	/*
395612Swnj 	 * Rip off an mbuf for a generic header.
405612Swnj 	 */
419638Ssam 	m = m_get(M_DONTWAIT, MT_HEADER);
425612Swnj 	if (m == 0) {
435612Swnj 		m_freem(m0);
445612Swnj 		return;
455612Swnj 	}
465612Swnj 	m->m_next = m0;
475612Swnj 	m->m_len = sizeof(struct raw_header);
485612Swnj 	rh = mtod(m, struct raw_header *);
496509Ssam 	rh->raw_dst = *dst;
506509Ssam 	rh->raw_src = *src;
516509Ssam 	rh->raw_proto = *proto;
525612Swnj 
535612Swnj 	/*
545612Swnj 	 * Header now contains enough info to decide
555612Swnj 	 * which socket to place packet in (if any).
565612Swnj 	 * Queue it up for the raw protocol process
575612Swnj 	 * running at software interrupt level.
585612Swnj 	 */
595121Swnj 	s = splimp();
606211Swnj 	if (IF_QFULL(&rawintrq))
616211Swnj 		m_freem(m);
626211Swnj 	else
636211Swnj 		IF_ENQUEUE(&rawintrq, m);
645121Swnj 	splx(s);
656263Swnj 	schednetisr(NETISR_RAW);
665121Swnj }
675121Swnj 
685612Swnj /*
695612Swnj  * Raw protocol input routine.  Process packets entered
705612Swnj  * into the queue at interrupt time.  Find the socket
715612Swnj  * associated with the packet(s) and move them over.  If
725612Swnj  * nothing exists for this packet, drop it.
735612Swnj  */
745121Swnj rawintr()
755121Swnj {
765121Swnj 	int s;
775121Swnj 	struct mbuf *m;
785612Swnj 	register struct rawcb *rp;
796509Ssam 	register struct protosw *lproto;
806529Ssam 	register struct raw_header *rh;
815612Swnj 	struct socket *last;
825121Swnj 
835121Swnj next:
845121Swnj 	s = splimp();
855121Swnj 	IF_DEQUEUE(&rawintrq, m);
865121Swnj 	splx(s);
875121Swnj 	if (m == 0)
885121Swnj 		return;
896509Ssam 	rh = mtod(m, struct raw_header *);
905612Swnj 	last = 0;
915612Swnj 	for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
926509Ssam 		lproto = rp->rcb_socket->so_proto;
936509Ssam 		if (lproto->pr_family != rh->raw_proto.sp_family)
945612Swnj 			continue;
956509Ssam 		if (lproto->pr_protocol &&
966509Ssam 		    lproto->pr_protocol != rh->raw_proto.sp_protocol)
975612Swnj 			continue;
985612Swnj 		/*
995612Swnj 		 * We assume the lower level routines have
1005612Swnj 		 * placed the address in a canonical format
1016509Ssam 		 * suitable for a structure comparison.
1025612Swnj 		 */
1036529Ssam #define equal(a1, a2) \
1046529Ssam 	(bcmp((caddr_t)&(a1), (caddr_t)&(a2), sizeof (struct sockaddr)) == 0)
1056509Ssam 		if ((rp->rcb_flags & RAW_LADDR) &&
1066529Ssam 		    !equal(rp->rcb_laddr, rh->raw_dst))
1075612Swnj 			continue;
1086509Ssam 		if ((rp->rcb_flags & RAW_FADDR) &&
1096529Ssam 		    !equal(rp->rcb_faddr, rh->raw_src))
1106509Ssam 			continue;
1115612Swnj 		if (last) {
1125612Swnj 			struct mbuf *n;
1137517Sroot 			if ((n = m_copy(m->m_next, 0, (int)M_COPYALL)) == 0)
1145612Swnj 				goto nospace;
115*12783Ssam 			if (sbappendaddr(&last->so_rcv, &rh->raw_src,
116*12783Ssam 			    n, (struct mbuf *)0) == 0) {
1176509Ssam 				/* should notify about lost packet */
1185646Ssam 				m_freem(n);
1195646Ssam 				goto nospace;
1205646Ssam 			}
1215612Swnj 			sorwakeup(last);
1225612Swnj 		}
1235612Swnj nospace:
1246509Ssam 		last = rp->rcb_socket;
1255612Swnj 	}
1266584Ssam 	if (last) {
1276584Ssam 		m = m_free(m);		/* header */
128*12783Ssam 		if (sbappendaddr(&last->so_rcv, &rh->raw_src,
129*12783Ssam 		    m, (struct mbuf *)0) == 0)
1306584Ssam 			goto drop;
1316584Ssam 		sorwakeup(last);
1326584Ssam 		goto next;
1336584Ssam 	}
1345121Swnj drop:
1355121Swnj 	m_freem(m);
1365121Swnj 	goto next;
1375121Swnj }
1385121Swnj 
1398636Sroot /*ARGSUSED*/
1406584Ssam raw_ctlinput(cmd, arg)
1416584Ssam 	int cmd;
1426584Ssam 	caddr_t arg;
1436584Ssam {
1446591Ssam 
1456591Ssam 	if (cmd < 0 || cmd > PRC_NCMDS)
1466591Ssam 		return;
1478636Sroot 	/* INCOMPLETE */
1486584Ssam }
1496584Ssam 
1505121Swnj /*ARGSUSED*/
151*12783Ssam raw_usrreq(so, req, m, nam, rights)
1525121Swnj 	struct socket *so;
1535121Swnj 	int req;
154*12783Ssam 	struct mbuf *m, *nam, *rights;
1555121Swnj {
1565612Swnj 	register struct rawcb *rp = sotorawcb(so);
157*12783Ssam 	register int error = 0;
1585121Swnj 
159*12783Ssam 	if (rights && rights->m_len) {
160*12783Ssam 		error = EOPNOTSUPP;
161*12783Ssam 		goto release;
162*12783Ssam 	}
163*12783Ssam 	if (rp == 0 && req != PRU_ATTACH) {
164*12783Ssam 		error = EINVAL;
165*12783Ssam 		goto release;
166*12783Ssam 	}
1675612Swnj 	switch (req) {
1685612Swnj 
1695612Swnj 	/*
1705612Swnj 	 * Allocate a raw control block and fill in the
1715612Swnj 	 * necessary info to allow packets to be routed to
1725612Swnj 	 * the appropriate raw interface routine.
1735612Swnj 	 */
1745612Swnj 	case PRU_ATTACH:
175*12783Ssam 		if ((so->so_state & SS_PRIV) == 0) {
176*12783Ssam 			error = EACCES;
177*12783Ssam 			goto release;
178*12783Ssam 		}
179*12783Ssam 		if (rp) {
180*12783Ssam 			error = EINVAL;
181*12783Ssam 			goto release;
182*12783Ssam 		}
1838395Swnj 		error = raw_attach(so);
1845612Swnj 		break;
1855612Swnj 
1865612Swnj 	/*
1875612Swnj 	 * Destroy state just before socket deallocation.
1885612Swnj 	 * Flush data or not depending on the options.
1895612Swnj 	 */
1905612Swnj 	case PRU_DETACH:
191*12783Ssam 		if (rp == 0) {
192*12783Ssam 			error = ENOTCONN;
193*12783Ssam 			goto release;
194*12783Ssam 		}
1955612Swnj 		raw_detach(rp);
1965612Swnj 		break;
1975612Swnj 
1985612Swnj 	/*
1995612Swnj 	 * If a socket isn't bound to a single address,
2005612Swnj 	 * the raw input routine will hand it anything
2015612Swnj 	 * within that protocol family (assuming there's
2025612Swnj 	 * nothing else around it should go to).
2035612Swnj 	 */
2045612Swnj 	case PRU_CONNECT:
205*12783Ssam 		if (rp->rcb_flags & RAW_FADDR) {
206*12783Ssam 			error = EISCONN;
207*12783Ssam 			goto release;
208*12783Ssam 		}
2098395Swnj 		raw_connaddr(rp, nam);
2105612Swnj 		soisconnected(so);
2115612Swnj 		break;
2125612Swnj 
213*12783Ssam 	case PRU_BIND:
214*12783Ssam 		if (rp->rcb_flags & RAW_LADDR) {
215*12783Ssam 			error = EINVAL;			/* XXX */
216*12783Ssam 			goto release;
217*12783Ssam 		}
218*12783Ssam 		error = raw_bind(so, nam);
219*12783Ssam 		break;
220*12783Ssam 
2215612Swnj 	case PRU_DISCONNECT:
222*12783Ssam 		if ((rp->rcb_flags & RAW_FADDR) == 0) {
223*12783Ssam 			error = ENOTCONN;
224*12783Ssam 			goto release;
225*12783Ssam 		}
2265612Swnj 		raw_disconnect(rp);
2275612Swnj 		soisdisconnected(so);
2285612Swnj 		break;
2295612Swnj 
2305612Swnj 	/*
2315612Swnj 	 * Mark the connection as being incapable of further input.
2325612Swnj 	 */
2335612Swnj 	case PRU_SHUTDOWN:
2345612Swnj 		socantsendmore(so);
2355612Swnj 		break;
2365612Swnj 
2375612Swnj 	/*
2385612Swnj 	 * Ship a packet out.  The appropriate raw output
2395612Swnj 	 * routine handles any massaging necessary.
2405612Swnj 	 */
2415612Swnj 	case PRU_SEND:
2428395Swnj 		if (nam) {
243*12783Ssam 			if (rp->rcb_flags & RAW_FADDR) {
244*12783Ssam 				error = EISCONN;
245*12783Ssam 				goto release;
246*12783Ssam 			}
2478395Swnj 			raw_connaddr(rp, nam);
248*12783Ssam 		} else if ((rp->rcb_flags & RAW_FADDR) == 0) {
249*12783Ssam 			error = ENOTCONN;
250*12783Ssam 			goto release;
251*12783Ssam 		}
2526505Ssam 		error = (*so->so_proto->pr_output)(m, so);
253*12783Ssam 		m = NULL;
2548395Swnj 		if (nam)
2556509Ssam 			rp->rcb_flags &= ~RAW_FADDR;
2565612Swnj 		break;
2575612Swnj 
2585612Swnj 	case PRU_ABORT:
2595612Swnj 		raw_disconnect(rp);
2605612Swnj 		sofree(so);
2615612Swnj 		soisdisconnected(so);
2625612Swnj 		break;
2635612Swnj 
2645612Swnj 	/*
2655612Swnj 	 * Not supported.
2665612Swnj 	 */
2675612Swnj 	case PRU_ACCEPT:
2685612Swnj 	case PRU_RCVD:
2695612Swnj 	case PRU_CONTROL:
2705612Swnj 	case PRU_SENSE:
2715612Swnj 	case PRU_RCVOOB:
2725612Swnj 	case PRU_SENDOOB:
2735612Swnj 		error = EOPNOTSUPP;
2745612Swnj 		break;
2755612Swnj 
2766509Ssam 	case PRU_SOCKADDR:
2778723Sroot 		bcopy((caddr_t)&rp->rcb_laddr, mtod(nam, caddr_t),
2788395Swnj 		    sizeof (struct sockaddr));
2798395Swnj 		nam->m_len = sizeof (struct sockaddr);
2806509Ssam 		break;
2816509Ssam 
2825612Swnj 	default:
2835612Swnj 		panic("raw_usrreq");
2845612Swnj 	}
285*12783Ssam release:
286*12783Ssam 	if (m != NULL)
287*12783Ssam 		m_freem(m);
2885612Swnj 	return (error);
2895121Swnj }
290