xref: /csrg-svn/sys/net/raw_usrreq.c (revision 44465)
123162Smckusick /*
229068Smckusick  * Copyright (c) 1980, 1986 Regents of the University of California.
333183Sbostic  * All rights reserved.
423162Smckusick  *
5*44465Sbostic  * %sccs.include.redist.c%
633183Sbostic  *
7*44465Sbostic  *	@(#)raw_usrreq.c	7.9 (Berkeley) 06/28/90
823162Smckusick  */
95121Swnj 
1017037Sbloom #include "param.h"
1117037Sbloom #include "mbuf.h"
1217037Sbloom #include "domain.h"
1317037Sbloom #include "protosw.h"
1417037Sbloom #include "socket.h"
1517037Sbloom #include "socketvar.h"
1617037Sbloom #include "errno.h"
1710890Ssam 
1817037Sbloom #include "if.h"
1917037Sbloom #include "route.h"
2017037Sbloom #include "netisr.h"
2117037Sbloom #include "raw_cb.h"
225121Swnj 
2337500Smckusick #include "machine/mtpr.h"
2410890Ssam 
255121Swnj /*
265612Swnj  * Initialize raw connection block q.
276211Swnj  */
285612Swnj raw_init()
295612Swnj {
306211Swnj 
315612Swnj 	rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
326211Swnj 	rawintrq.ifq_maxlen = IFQ_MAXLEN;
335612Swnj }
345612Swnj 
3537472Ssklower 
365612Swnj /*
3737472Ssklower  * Raw protocol input routine.  Find the socket
3837472Ssklower  * associated with the packet(s) and move them over.  If
3937472Ssklower  * nothing exists for this packet, drop it.
4037472Ssklower  */
4137472Ssklower /*
425121Swnj  * Raw protocol interface.
435121Swnj  */
446529Ssam raw_input(m0, proto, src, dst)
455612Swnj 	struct mbuf *m0;
4639181Ssklower 	register struct sockproto *proto;
476529Ssam 	struct sockaddr *src, *dst;
485121Swnj {
495612Swnj 	register struct rawcb *rp;
5037472Ssklower 	register struct mbuf *m = m0;
5139181Ssklower 	register int sockets = 0;
525612Swnj 	struct socket *last;
535121Swnj 
545612Swnj 	last = 0;
555612Swnj 	for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
5637472Ssklower 		if (rp->rcb_proto.sp_family != proto->sp_family)
575612Swnj 			continue;
5821769Skarels 		if (rp->rcb_proto.sp_protocol  &&
5937472Ssklower 		    rp->rcb_proto.sp_protocol != proto->sp_protocol)
605612Swnj 			continue;
615612Swnj 		/*
625612Swnj 		 * We assume the lower level routines have
635612Swnj 		 * placed the address in a canonical format
646509Ssam 		 * suitable for a structure comparison.
6537472Ssklower 		 *
6637472Ssklower 		 * Note that if the lengths are not the same
6737472Ssklower 		 * the comparison will fail at the first byte.
685612Swnj 		 */
6937472Ssklower #define	equal(a1, a2) \
7037472Ssklower   (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
7137472Ssklower 		if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst))
725612Swnj 			continue;
7337472Ssklower 		if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
746509Ssam 			continue;
755612Swnj 		if (last) {
765612Swnj 			struct mbuf *n;
7737472Ssklower 			if (n = m_copy(m, 0, (int)M_COPYALL)) {
7837472Ssklower 				if (sbappendaddr(&last->so_rcv, src,
7921531Skarels 				    n, (struct mbuf *)0) == 0)
8021531Skarels 					/* should notify about lost packet */
8121531Skarels 					m_freem(n);
8239181Ssklower 				else {
8321531Skarels 					sorwakeup(last);
8439181Ssklower 					sockets++;
8539181Ssklower 				}
865646Ssam 			}
875612Swnj 		}
886509Ssam 		last = rp->rcb_socket;
895612Swnj 	}
906584Ssam 	if (last) {
9137472Ssklower 		if (sbappendaddr(&last->so_rcv, src,
9237472Ssklower 		    m, (struct mbuf *)0) == 0)
9337472Ssklower 			m_freem(m);
9439181Ssklower 		else {
9521531Skarels 			sorwakeup(last);
9639181Ssklower 			sockets++;
9739181Ssklower 		}
9821531Skarels 	} else
9921531Skarels 		m_freem(m);
10039181Ssklower 	return (sockets);
1015121Swnj }
1025121Swnj 
1038636Sroot /*ARGSUSED*/
1046584Ssam raw_ctlinput(cmd, arg)
1056584Ssam 	int cmd;
10626379Skarels 	struct sockaddr *arg;
1076584Ssam {
1086591Ssam 
1096591Ssam 	if (cmd < 0 || cmd > PRC_NCMDS)
1106591Ssam 		return;
1118636Sroot 	/* INCOMPLETE */
1126584Ssam }
1136584Ssam 
1145121Swnj /*ARGSUSED*/
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 }
28137472Ssklower 
28237472Ssklower rawintr() {} /* XXX - referenced by locore.  will soon go away */
283