xref: /csrg-svn/sys/net/raw_usrreq.c (revision 26379)
123162Smckusick /*
223162Smckusick  * Copyright (c) 1980 Regents of the University of California.
323162Smckusick  * All rights reserved.  The Berkeley software License Agreement
423162Smckusick  * specifies the terms and conditions for redistribution.
523162Smckusick  *
6*26379Skarels  *	@(#)raw_usrreq.c	6.13 (Berkeley) 02/23/86
723162Smckusick  */
85121Swnj 
917037Sbloom #include "param.h"
1017037Sbloom #include "mbuf.h"
1117037Sbloom #include "domain.h"
1217037Sbloom #include "protosw.h"
1317037Sbloom #include "socket.h"
1417037Sbloom #include "socketvar.h"
1517037Sbloom #include "errno.h"
1610890Ssam 
1717037Sbloom #include "if.h"
1817037Sbloom #include "route.h"
1917037Sbloom #include "netisr.h"
2017037Sbloom #include "raw_cb.h"
215121Swnj 
2210890Ssam #include "../vax/mtpr.h"
2310890Ssam 
245121Swnj /*
255612Swnj  * Initialize raw connection block q.
266211Swnj  */
275612Swnj raw_init()
285612Swnj {
296211Swnj 
305612Swnj 	rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
316211Swnj 	rawintrq.ifq_maxlen = IFQ_MAXLEN;
325612Swnj }
335612Swnj 
345612Swnj /*
355121Swnj  * Raw protocol interface.
365121Swnj  */
376529Ssam raw_input(m0, proto, src, dst)
385612Swnj 	struct mbuf *m0;
396509Ssam 	struct sockproto *proto;
406529Ssam 	struct sockaddr *src, *dst;
415121Swnj {
425612Swnj 	register struct mbuf *m;
435612Swnj 	struct raw_header *rh;
445121Swnj 	int s;
455121Swnj 
465612Swnj 	/*
475612Swnj 	 * Rip off an mbuf for a generic header.
485612Swnj 	 */
499638Ssam 	m = m_get(M_DONTWAIT, MT_HEADER);
505612Swnj 	if (m == 0) {
515612Swnj 		m_freem(m0);
525612Swnj 		return;
535612Swnj 	}
545612Swnj 	m->m_next = m0;
555612Swnj 	m->m_len = sizeof(struct raw_header);
565612Swnj 	rh = mtod(m, struct raw_header *);
576509Ssam 	rh->raw_dst = *dst;
586509Ssam 	rh->raw_src = *src;
596509Ssam 	rh->raw_proto = *proto;
605612Swnj 
615612Swnj 	/*
625612Swnj 	 * Header now contains enough info to decide
635612Swnj 	 * which socket to place packet in (if any).
645612Swnj 	 * Queue it up for the raw protocol process
655612Swnj 	 * running at software interrupt level.
665612Swnj 	 */
675121Swnj 	s = splimp();
686211Swnj 	if (IF_QFULL(&rawintrq))
696211Swnj 		m_freem(m);
706211Swnj 	else
716211Swnj 		IF_ENQUEUE(&rawintrq, m);
725121Swnj 	splx(s);
736263Swnj 	schednetisr(NETISR_RAW);
745121Swnj }
755121Swnj 
765612Swnj /*
775612Swnj  * Raw protocol input routine.  Process packets entered
785612Swnj  * into the queue at interrupt time.  Find the socket
795612Swnj  * associated with the packet(s) and move them over.  If
805612Swnj  * nothing exists for this packet, drop it.
815612Swnj  */
825121Swnj rawintr()
835121Swnj {
845121Swnj 	int s;
855121Swnj 	struct mbuf *m;
865612Swnj 	register struct rawcb *rp;
876529Ssam 	register struct raw_header *rh;
885612Swnj 	struct socket *last;
895121Swnj 
905121Swnj next:
915121Swnj 	s = splimp();
925121Swnj 	IF_DEQUEUE(&rawintrq, m);
935121Swnj 	splx(s);
945121Swnj 	if (m == 0)
955121Swnj 		return;
966509Ssam 	rh = mtod(m, struct raw_header *);
975612Swnj 	last = 0;
985612Swnj 	for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
9921769Skarels 		if (rp->rcb_proto.sp_family != rh->raw_proto.sp_family)
1005612Swnj 			continue;
10121769Skarels 		if (rp->rcb_proto.sp_protocol  &&
10221769Skarels 		    rp->rcb_proto.sp_protocol != rh->raw_proto.sp_protocol)
1035612Swnj 			continue;
1045612Swnj 		/*
1055612Swnj 		 * We assume the lower level routines have
1065612Swnj 		 * placed the address in a canonical format
1076509Ssam 		 * suitable for a structure comparison.
1085612Swnj 		 */
1096529Ssam #define equal(a1, a2) \
1106529Ssam 	(bcmp((caddr_t)&(a1), (caddr_t)&(a2), sizeof (struct sockaddr)) == 0)
1116509Ssam 		if ((rp->rcb_flags & RAW_LADDR) &&
1126529Ssam 		    !equal(rp->rcb_laddr, rh->raw_dst))
1135612Swnj 			continue;
1146509Ssam 		if ((rp->rcb_flags & RAW_FADDR) &&
1156529Ssam 		    !equal(rp->rcb_faddr, rh->raw_src))
1166509Ssam 			continue;
1175612Swnj 		if (last) {
1185612Swnj 			struct mbuf *n;
11921531Skarels 			if (n = m_copy(m->m_next, 0, (int)M_COPYALL)) {
12021531Skarels 				if (sbappendaddr(&last->so_rcv, &rh->raw_src,
12121531Skarels 				    n, (struct mbuf *)0) == 0)
12221531Skarels 					/* should notify about lost packet */
12321531Skarels 					m_freem(n);
12421531Skarels 				else
12521531Skarels 					sorwakeup(last);
1265646Ssam 			}
1275612Swnj 		}
1286509Ssam 		last = rp->rcb_socket;
1295612Swnj 	}
1306584Ssam 	if (last) {
13112783Ssam 		if (sbappendaddr(&last->so_rcv, &rh->raw_src,
13221531Skarels 		    m->m_next, (struct mbuf *)0) == 0)
13321531Skarels 			m_freem(m->m_next);
13421531Skarels 		else
13521531Skarels 			sorwakeup(last);
13621531Skarels 		(void) m_free(m);		/* header */
13721531Skarels 	} else
13821531Skarels 		m_freem(m);
1395121Swnj 	goto next;
1405121Swnj }
1415121Swnj 
1428636Sroot /*ARGSUSED*/
1436584Ssam raw_ctlinput(cmd, arg)
1446584Ssam 	int cmd;
145*26379Skarels 	struct sockaddr *arg;
1466584Ssam {
1476591Ssam 
1486591Ssam 	if (cmd < 0 || cmd > PRC_NCMDS)
1496591Ssam 		return;
1508636Sroot 	/* INCOMPLETE */
1516584Ssam }
1526584Ssam 
1535121Swnj /*ARGSUSED*/
15412783Ssam raw_usrreq(so, req, m, nam, rights)
1555121Swnj 	struct socket *so;
1565121Swnj 	int req;
15712783Ssam 	struct mbuf *m, *nam, *rights;
1585121Swnj {
1595612Swnj 	register struct rawcb *rp = sotorawcb(so);
16012783Ssam 	register int error = 0;
1615121Swnj 
16225501Skarels 	if (req == PRU_CONTROL)
16325501Skarels 		return (EOPNOTSUPP);
16412783Ssam 	if (rights && rights->m_len) {
16512783Ssam 		error = EOPNOTSUPP;
16612783Ssam 		goto release;
16712783Ssam 	}
16812783Ssam 	if (rp == 0 && req != PRU_ATTACH) {
16912783Ssam 		error = EINVAL;
17012783Ssam 		goto release;
17112783Ssam 	}
1725612Swnj 	switch (req) {
1735612Swnj 
1745612Swnj 	/*
1755612Swnj 	 * Allocate a raw control block and fill in the
1765612Swnj 	 * necessary info to allow packets to be routed to
1775612Swnj 	 * the appropriate raw interface routine.
1785612Swnj 	 */
1795612Swnj 	case PRU_ATTACH:
18012783Ssam 		if ((so->so_state & SS_PRIV) == 0) {
18112783Ssam 			error = EACCES;
18213116Ssam 			break;
18312783Ssam 		}
18412783Ssam 		if (rp) {
18512783Ssam 			error = EINVAL;
18613116Ssam 			break;
18712783Ssam 		}
18821769Skarels 		error = raw_attach(so, (int)nam);
1895612Swnj 		break;
1905612Swnj 
1915612Swnj 	/*
1925612Swnj 	 * Destroy state just before socket deallocation.
1935612Swnj 	 * Flush data or not depending on the options.
1945612Swnj 	 */
1955612Swnj 	case PRU_DETACH:
19612783Ssam 		if (rp == 0) {
19712783Ssam 			error = ENOTCONN;
19813116Ssam 			break;
19912783Ssam 		}
2005612Swnj 		raw_detach(rp);
2015612Swnj 		break;
2025612Swnj 
2035612Swnj 	/*
2045612Swnj 	 * If a socket isn't bound to a single address,
2055612Swnj 	 * the raw input routine will hand it anything
2065612Swnj 	 * within that protocol family (assuming there's
2075612Swnj 	 * nothing else around it should go to).
2085612Swnj 	 */
2095612Swnj 	case PRU_CONNECT:
21012783Ssam 		if (rp->rcb_flags & RAW_FADDR) {
21112783Ssam 			error = EISCONN;
21213116Ssam 			break;
21312783Ssam 		}
2148395Swnj 		raw_connaddr(rp, nam);
2155612Swnj 		soisconnected(so);
2165612Swnj 		break;
2175612Swnj 
21813116Ssam 	case PRU_CONNECT2:
21913116Ssam 		error = EOPNOTSUPP;
22013116Ssam 		goto release;
22113116Ssam 
22212783Ssam 	case PRU_BIND:
22312783Ssam 		if (rp->rcb_flags & RAW_LADDR) {
22412783Ssam 			error = EINVAL;			/* XXX */
22513116Ssam 			break;
22612783Ssam 		}
22712783Ssam 		error = raw_bind(so, nam);
22812783Ssam 		break;
22912783Ssam 
2305612Swnj 	case PRU_DISCONNECT:
23112783Ssam 		if ((rp->rcb_flags & RAW_FADDR) == 0) {
23212783Ssam 			error = ENOTCONN;
23313116Ssam 			break;
23412783Ssam 		}
2355612Swnj 		raw_disconnect(rp);
2365612Swnj 		soisdisconnected(so);
2375612Swnj 		break;
2385612Swnj 
2395612Swnj 	/*
2405612Swnj 	 * Mark the connection as being incapable of further input.
2415612Swnj 	 */
2425612Swnj 	case PRU_SHUTDOWN:
2435612Swnj 		socantsendmore(so);
2445612Swnj 		break;
2455612Swnj 
2465612Swnj 	/*
2475612Swnj 	 * Ship a packet out.  The appropriate raw output
2485612Swnj 	 * routine handles any massaging necessary.
2495612Swnj 	 */
2505612Swnj 	case PRU_SEND:
2518395Swnj 		if (nam) {
25212783Ssam 			if (rp->rcb_flags & RAW_FADDR) {
25312783Ssam 				error = EISCONN;
25413116Ssam 				break;
25512783Ssam 			}
2568395Swnj 			raw_connaddr(rp, nam);
25712783Ssam 		} else if ((rp->rcb_flags & RAW_FADDR) == 0) {
25812783Ssam 			error = ENOTCONN;
25913116Ssam 			break;
26012783Ssam 		}
2616505Ssam 		error = (*so->so_proto->pr_output)(m, so);
26212783Ssam 		m = NULL;
2638395Swnj 		if (nam)
2646509Ssam 			rp->rcb_flags &= ~RAW_FADDR;
2655612Swnj 		break;
2665612Swnj 
2675612Swnj 	case PRU_ABORT:
2685612Swnj 		raw_disconnect(rp);
2695612Swnj 		sofree(so);
2705612Swnj 		soisdisconnected(so);
2715612Swnj 		break;
2725612Swnj 
27316974Skarels 	case PRU_SENSE:
27416974Skarels 		/*
27516974Skarels 		 * stat: don't bother with a blocksize.
27616974Skarels 		 */
27716974Skarels 		return (0);
27816974Skarels 
2795612Swnj 	/*
2805612Swnj 	 * Not supported.
2815612Swnj 	 */
28216773Sbloom 	case PRU_RCVOOB:
2835612Swnj 	case PRU_RCVD:
28416773Sbloom 		return(EOPNOTSUPP);
28516773Sbloom 
28625221Skarels 	case PRU_LISTEN:
28716773Sbloom 	case PRU_ACCEPT:
2885612Swnj 	case PRU_SENDOOB:
2895612Swnj 		error = EOPNOTSUPP;
2905612Swnj 		break;
2915612Swnj 
2926509Ssam 	case PRU_SOCKADDR:
2938723Sroot 		bcopy((caddr_t)&rp->rcb_laddr, mtod(nam, caddr_t),
2948395Swnj 		    sizeof (struct sockaddr));
2958395Swnj 		nam->m_len = sizeof (struct sockaddr);
2966509Ssam 		break;
2976509Ssam 
29814122Ssam 	case PRU_PEERADDR:
29914122Ssam 		bcopy((caddr_t)&rp->rcb_faddr, mtod(nam, caddr_t),
30014122Ssam 		    sizeof (struct sockaddr));
30114122Ssam 		nam->m_len = sizeof (struct sockaddr);
30214122Ssam 		break;
30314122Ssam 
3045612Swnj 	default:
3055612Swnj 		panic("raw_usrreq");
3065612Swnj 	}
30712783Ssam release:
30812783Ssam 	if (m != NULL)
30912783Ssam 		m_freem(m);
3105612Swnj 	return (error);
3115121Swnj }
312