xref: /csrg-svn/sys/net/raw_usrreq.c (revision 37500)
123162Smckusick /*
229068Smckusick  * Copyright (c) 1980, 1986 Regents of the University of California.
333183Sbostic  * All rights reserved.
423162Smckusick  *
533183Sbostic  * Redistribution and use in source and binary forms are permitted
634844Sbostic  * provided that the above copyright notice and this paragraph are
734844Sbostic  * duplicated in all such forms and that any documentation,
834844Sbostic  * advertising materials, and other materials related to such
934844Sbostic  * distribution and use acknowledge that the software was developed
1034844Sbostic  * by the University of California, Berkeley.  The name of the
1134844Sbostic  * University may not be used to endorse or promote products derived
1234844Sbostic  * from this software without specific prior written permission.
1334844Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1434844Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1534844Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1633183Sbostic  *
17*37500Smckusick  *	@(#)raw_usrreq.c	7.6 (Berkeley) 04/25/89
1823162Smckusick  */
195121Swnj 
2017037Sbloom #include "param.h"
2117037Sbloom #include "mbuf.h"
2217037Sbloom #include "domain.h"
2317037Sbloom #include "protosw.h"
2417037Sbloom #include "socket.h"
2517037Sbloom #include "socketvar.h"
2617037Sbloom #include "errno.h"
2710890Ssam 
2817037Sbloom #include "if.h"
2917037Sbloom #include "route.h"
3017037Sbloom #include "netisr.h"
3117037Sbloom #include "raw_cb.h"
325121Swnj 
33*37500Smckusick #include "machine/mtpr.h"
3410890Ssam 
355121Swnj /*
365612Swnj  * Initialize raw connection block q.
376211Swnj  */
385612Swnj raw_init()
395612Swnj {
406211Swnj 
415612Swnj 	rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
426211Swnj 	rawintrq.ifq_maxlen = IFQ_MAXLEN;
435612Swnj }
445612Swnj 
4537472Ssklower 
465612Swnj /*
4737472Ssklower  * Raw protocol input routine.  Find the socket
4837472Ssklower  * associated with the packet(s) and move them over.  If
4937472Ssklower  * nothing exists for this packet, drop it.
5037472Ssklower  */
5137472Ssklower /*
525121Swnj  * Raw protocol interface.
535121Swnj  */
546529Ssam raw_input(m0, proto, src, dst)
555612Swnj 	struct mbuf *m0;
566509Ssam 	struct sockproto *proto;
576529Ssam 	struct sockaddr *src, *dst;
585121Swnj {
595612Swnj 	register struct rawcb *rp;
6037472Ssklower 	register struct mbuf *m = m0;
615612Swnj 	struct socket *last;
625121Swnj 
635612Swnj 	last = 0;
645612Swnj 	for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
6537472Ssklower 		if (rp->rcb_proto.sp_family != proto->sp_family)
665612Swnj 			continue;
6721769Skarels 		if (rp->rcb_proto.sp_protocol  &&
6837472Ssklower 		    rp->rcb_proto.sp_protocol != proto->sp_protocol)
695612Swnj 			continue;
705612Swnj 		/*
715612Swnj 		 * We assume the lower level routines have
725612Swnj 		 * placed the address in a canonical format
736509Ssam 		 * suitable for a structure comparison.
7437472Ssklower 		 *
7537472Ssklower 		 * Note that if the lengths are not the same
7637472Ssklower 		 * the comparison will fail at the first byte.
775612Swnj 		 */
7837472Ssklower #define	equal(a1, a2) \
7937472Ssklower   (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
8037472Ssklower 		if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst))
815612Swnj 			continue;
8237472Ssklower 		if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
836509Ssam 			continue;
845612Swnj 		if (last) {
855612Swnj 			struct mbuf *n;
8637472Ssklower 			if (n = m_copy(m, 0, (int)M_COPYALL)) {
8737472Ssklower 				if (sbappendaddr(&last->so_rcv, src,
8821531Skarels 				    n, (struct mbuf *)0) == 0)
8921531Skarels 					/* should notify about lost packet */
9021531Skarels 					m_freem(n);
9121531Skarels 				else
9221531Skarels 					sorwakeup(last);
935646Ssam 			}
945612Swnj 		}
956509Ssam 		last = rp->rcb_socket;
965612Swnj 	}
976584Ssam 	if (last) {
9837472Ssklower 		if (sbappendaddr(&last->so_rcv, src,
9937472Ssklower 		    m, (struct mbuf *)0) == 0)
10037472Ssklower 			m_freem(m);
10121531Skarels 		else
10221531Skarels 			sorwakeup(last);
10321531Skarels 	} else
10421531Skarels 		m_freem(m);
1055121Swnj }
1065121Swnj 
1078636Sroot /*ARGSUSED*/
1086584Ssam raw_ctlinput(cmd, arg)
1096584Ssam 	int cmd;
11026379Skarels 	struct sockaddr *arg;
1116584Ssam {
1126591Ssam 
1136591Ssam 	if (cmd < 0 || cmd > PRC_NCMDS)
1146591Ssam 		return;
1158636Sroot 	/* INCOMPLETE */
1166584Ssam }
1176584Ssam 
1185121Swnj /*ARGSUSED*/
11937472Ssklower raw_usrreq(so, req, m, nam, rights, control)
1205121Swnj 	struct socket *so;
1215121Swnj 	int req;
12237472Ssklower 	struct mbuf *m, *nam, *rights, *control;
1235121Swnj {
1245612Swnj 	register struct rawcb *rp = sotorawcb(so);
12512783Ssam 	register int error = 0;
12637472Ssklower 	int len;
1275121Swnj 
12825501Skarels 	if (req == PRU_CONTROL)
12925501Skarels 		return (EOPNOTSUPP);
13012783Ssam 	if (rights && rights->m_len) {
13112783Ssam 		error = EOPNOTSUPP;
13212783Ssam 		goto release;
13312783Ssam 	}
13437472Ssklower 	if (rp == 0) {
13512783Ssam 		error = EINVAL;
13612783Ssam 		goto release;
13712783Ssam 	}
1385612Swnj 	switch (req) {
1395612Swnj 
1405612Swnj 	/*
1415612Swnj 	 * Allocate a raw control block and fill in the
1425612Swnj 	 * necessary info to allow packets to be routed to
1435612Swnj 	 * the appropriate raw interface routine.
1445612Swnj 	 */
1455612Swnj 	case PRU_ATTACH:
14612783Ssam 		if ((so->so_state & SS_PRIV) == 0) {
14712783Ssam 			error = EACCES;
14813116Ssam 			break;
14912783Ssam 		}
15021769Skarels 		error = raw_attach(so, (int)nam);
1515612Swnj 		break;
1525612Swnj 
1535612Swnj 	/*
1545612Swnj 	 * Destroy state just before socket deallocation.
1555612Swnj 	 * Flush data or not depending on the options.
1565612Swnj 	 */
1575612Swnj 	case PRU_DETACH:
15812783Ssam 		if (rp == 0) {
15912783Ssam 			error = ENOTCONN;
16013116Ssam 			break;
16112783Ssam 		}
1625612Swnj 		raw_detach(rp);
1635612Swnj 		break;
1645612Swnj 
16537472Ssklower #ifdef notdef
1665612Swnj 	/*
1675612Swnj 	 * If a socket isn't bound to a single address,
1685612Swnj 	 * the raw input routine will hand it anything
1695612Swnj 	 * within that protocol family (assuming there's
1705612Swnj 	 * nothing else around it should go to).
1715612Swnj 	 */
1725612Swnj 	case PRU_CONNECT:
17337472Ssklower 		if (rp->rcb_faddr) {
17412783Ssam 			error = EISCONN;
17513116Ssam 			break;
17612783Ssam 		}
17737472Ssklower 		nam = m_copym(nam, 0, M_COPYALL, M_WAIT);
17837472Ssklower 		rp->rcb_faddr = mtod(nam, struct sockaddr *);
1795612Swnj 		soisconnected(so);
1805612Swnj 		break;
1815612Swnj 
18212783Ssam 	case PRU_BIND:
18337472Ssklower 		if (rp->rcb_laddr) {
18412783Ssam 			error = EINVAL;			/* XXX */
18513116Ssam 			break;
18612783Ssam 		}
18712783Ssam 		error = raw_bind(so, nam);
18812783Ssam 		break;
18937472Ssklower #endif
19012783Ssam 
19137472Ssklower 	case PRU_CONNECT2:
19237472Ssklower 		error = EOPNOTSUPP;
19337472Ssklower 		goto release;
19437472Ssklower 
1955612Swnj 	case PRU_DISCONNECT:
19637472Ssklower 		if (rp->rcb_faddr == 0) {
19712783Ssam 			error = ENOTCONN;
19813116Ssam 			break;
19912783Ssam 		}
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) {
21737472Ssklower 			if (rp->rcb_faddr) {
21812783Ssam 				error = EISCONN;
21913116Ssam 				break;
22012783Ssam 			}
22137472Ssklower 			rp->rcb_faddr = mtod(nam, struct sockaddr *);
22237472Ssklower 		} else if (rp->rcb_faddr == 0) {
22312783Ssam 			error = ENOTCONN;
22413116Ssam 			break;
22512783Ssam 		}
2266505Ssam 		error = (*so->so_proto->pr_output)(m, so);
22712783Ssam 		m = NULL;
2288395Swnj 		if (nam)
22937472Ssklower 			rp->rcb_faddr = 0;
2305612Swnj 		break;
2315612Swnj 
2325612Swnj 	case PRU_ABORT:
2335612Swnj 		raw_disconnect(rp);
2345612Swnj 		sofree(so);
2355612Swnj 		soisdisconnected(so);
2365612Swnj 		break;
2375612Swnj 
23816974Skarels 	case PRU_SENSE:
23916974Skarels 		/*
24016974Skarels 		 * stat: don't bother with a blocksize.
24116974Skarels 		 */
24216974Skarels 		return (0);
24316974Skarels 
2445612Swnj 	/*
2455612Swnj 	 * Not supported.
2465612Swnj 	 */
24716773Sbloom 	case PRU_RCVOOB:
2485612Swnj 	case PRU_RCVD:
24916773Sbloom 		return(EOPNOTSUPP);
25016773Sbloom 
25125221Skarels 	case PRU_LISTEN:
25216773Sbloom 	case PRU_ACCEPT:
2535612Swnj 	case PRU_SENDOOB:
2545612Swnj 		error = EOPNOTSUPP;
2555612Swnj 		break;
2565612Swnj 
2576509Ssam 	case PRU_SOCKADDR:
25837472Ssklower 		if (rp->rcb_laddr == 0) {
25937472Ssklower 			error = EINVAL;
26037472Ssklower 			break;
26137472Ssklower 		}
26237472Ssklower 		len = rp->rcb_laddr->sa_len;
26337472Ssklower 		bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len);
26437472Ssklower 		nam->m_len = len;
2656509Ssam 		break;
2666509Ssam 
26714122Ssam 	case PRU_PEERADDR:
26837472Ssklower 		if (rp->rcb_faddr == 0) {
26937472Ssklower 			error = ENOTCONN;
27037472Ssklower 			break;
27137472Ssklower 		}
27237472Ssklower 		len = rp->rcb_faddr->sa_len;
27337472Ssklower 		bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len);
27437472Ssklower 		nam->m_len = len;
27514122Ssam 		break;
27614122Ssam 
2775612Swnj 	default:
2785612Swnj 		panic("raw_usrreq");
2795612Swnj 	}
28012783Ssam release:
28112783Ssam 	if (m != NULL)
28212783Ssam 		m_freem(m);
2835612Swnj 	return (error);
2845121Swnj }
28537472Ssklower 
28637472Ssklower rawintr() {} /* XXX - referenced by locore.  will soon go away */
287