xref: /csrg-svn/sys/net/raw_usrreq.c (revision 40787)
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*40787Ssklower  *	@(#)raw_usrreq.c	7.8 (Berkeley) 04/05/90
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 
3337500Smckusick #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;
5639181Ssklower 	register struct sockproto *proto;
576529Ssam 	struct sockaddr *src, *dst;
585121Swnj {
595612Swnj 	register struct rawcb *rp;
6037472Ssklower 	register struct mbuf *m = m0;
6139181Ssklower 	register int sockets = 0;
625612Swnj 	struct socket *last;
635121Swnj 
645612Swnj 	last = 0;
655612Swnj 	for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
6637472Ssklower 		if (rp->rcb_proto.sp_family != proto->sp_family)
675612Swnj 			continue;
6821769Skarels 		if (rp->rcb_proto.sp_protocol  &&
6937472Ssklower 		    rp->rcb_proto.sp_protocol != proto->sp_protocol)
705612Swnj 			continue;
715612Swnj 		/*
725612Swnj 		 * We assume the lower level routines have
735612Swnj 		 * placed the address in a canonical format
746509Ssam 		 * suitable for a structure comparison.
7537472Ssklower 		 *
7637472Ssklower 		 * Note that if the lengths are not the same
7737472Ssklower 		 * the comparison will fail at the first byte.
785612Swnj 		 */
7937472Ssklower #define	equal(a1, a2) \
8037472Ssklower   (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
8137472Ssklower 		if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst))
825612Swnj 			continue;
8337472Ssklower 		if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
846509Ssam 			continue;
855612Swnj 		if (last) {
865612Swnj 			struct mbuf *n;
8737472Ssklower 			if (n = m_copy(m, 0, (int)M_COPYALL)) {
8837472Ssklower 				if (sbappendaddr(&last->so_rcv, src,
8921531Skarels 				    n, (struct mbuf *)0) == 0)
9021531Skarels 					/* should notify about lost packet */
9121531Skarels 					m_freem(n);
9239181Ssklower 				else {
9321531Skarels 					sorwakeup(last);
9439181Ssklower 					sockets++;
9539181Ssklower 				}
965646Ssam 			}
975612Swnj 		}
986509Ssam 		last = rp->rcb_socket;
995612Swnj 	}
1006584Ssam 	if (last) {
10137472Ssklower 		if (sbappendaddr(&last->so_rcv, src,
10237472Ssklower 		    m, (struct mbuf *)0) == 0)
10337472Ssklower 			m_freem(m);
10439181Ssklower 		else {
10521531Skarels 			sorwakeup(last);
10639181Ssklower 			sockets++;
10739181Ssklower 		}
10821531Skarels 	} else
10921531Skarels 		m_freem(m);
11039181Ssklower 	return (sockets);
1115121Swnj }
1125121Swnj 
1138636Sroot /*ARGSUSED*/
1146584Ssam raw_ctlinput(cmd, arg)
1156584Ssam 	int cmd;
11626379Skarels 	struct sockaddr *arg;
1176584Ssam {
1186591Ssam 
1196591Ssam 	if (cmd < 0 || cmd > PRC_NCMDS)
1206591Ssam 		return;
1218636Sroot 	/* INCOMPLETE */
1226584Ssam }
1236584Ssam 
1245121Swnj /*ARGSUSED*/
125*40787Ssklower raw_usrreq(so, req, m, nam, control)
1265121Swnj 	struct socket *so;
1275121Swnj 	int req;
128*40787Ssklower 	struct mbuf *m, *nam, *control;
1295121Swnj {
1305612Swnj 	register struct rawcb *rp = sotorawcb(so);
13112783Ssam 	register int error = 0;
13237472Ssklower 	int len;
1335121Swnj 
13425501Skarels 	if (req == PRU_CONTROL)
13525501Skarels 		return (EOPNOTSUPP);
136*40787Ssklower 	if (control && control->m_len) {
13712783Ssam 		error = EOPNOTSUPP;
13812783Ssam 		goto release;
13912783Ssam 	}
14037472Ssklower 	if (rp == 0) {
14112783Ssam 		error = EINVAL;
14212783Ssam 		goto release;
14312783Ssam 	}
1445612Swnj 	switch (req) {
1455612Swnj 
1465612Swnj 	/*
1475612Swnj 	 * Allocate a raw control block and fill in the
1485612Swnj 	 * necessary info to allow packets to be routed to
1495612Swnj 	 * the appropriate raw interface routine.
1505612Swnj 	 */
1515612Swnj 	case PRU_ATTACH:
15212783Ssam 		if ((so->so_state & SS_PRIV) == 0) {
15312783Ssam 			error = EACCES;
15413116Ssam 			break;
15512783Ssam 		}
15621769Skarels 		error = raw_attach(so, (int)nam);
1575612Swnj 		break;
1585612Swnj 
1595612Swnj 	/*
1605612Swnj 	 * Destroy state just before socket deallocation.
1615612Swnj 	 * Flush data or not depending on the options.
1625612Swnj 	 */
1635612Swnj 	case PRU_DETACH:
16412783Ssam 		if (rp == 0) {
16512783Ssam 			error = ENOTCONN;
16613116Ssam 			break;
16712783Ssam 		}
1685612Swnj 		raw_detach(rp);
1695612Swnj 		break;
1705612Swnj 
17137472Ssklower #ifdef notdef
1725612Swnj 	/*
1735612Swnj 	 * If a socket isn't bound to a single address,
1745612Swnj 	 * the raw input routine will hand it anything
1755612Swnj 	 * within that protocol family (assuming there's
1765612Swnj 	 * nothing else around it should go to).
1775612Swnj 	 */
1785612Swnj 	case PRU_CONNECT:
17937472Ssklower 		if (rp->rcb_faddr) {
18012783Ssam 			error = EISCONN;
18113116Ssam 			break;
18212783Ssam 		}
18337472Ssklower 		nam = m_copym(nam, 0, M_COPYALL, M_WAIT);
18437472Ssklower 		rp->rcb_faddr = mtod(nam, struct sockaddr *);
1855612Swnj 		soisconnected(so);
1865612Swnj 		break;
1875612Swnj 
18812783Ssam 	case PRU_BIND:
18937472Ssklower 		if (rp->rcb_laddr) {
19012783Ssam 			error = EINVAL;			/* XXX */
19113116Ssam 			break;
19212783Ssam 		}
19312783Ssam 		error = raw_bind(so, nam);
19412783Ssam 		break;
19537472Ssklower #endif
19612783Ssam 
19737472Ssklower 	case PRU_CONNECT2:
19837472Ssklower 		error = EOPNOTSUPP;
19937472Ssklower 		goto release;
20037472Ssklower 
2015612Swnj 	case PRU_DISCONNECT:
20237472Ssklower 		if (rp->rcb_faddr == 0) {
20312783Ssam 			error = ENOTCONN;
20413116Ssam 			break;
20512783Ssam 		}
2065612Swnj 		raw_disconnect(rp);
2075612Swnj 		soisdisconnected(so);
2085612Swnj 		break;
2095612Swnj 
2105612Swnj 	/*
2115612Swnj 	 * Mark the connection as being incapable of further input.
2125612Swnj 	 */
2135612Swnj 	case PRU_SHUTDOWN:
2145612Swnj 		socantsendmore(so);
2155612Swnj 		break;
2165612Swnj 
2175612Swnj 	/*
2185612Swnj 	 * Ship a packet out.  The appropriate raw output
2195612Swnj 	 * routine handles any massaging necessary.
2205612Swnj 	 */
2215612Swnj 	case PRU_SEND:
2228395Swnj 		if (nam) {
22337472Ssklower 			if (rp->rcb_faddr) {
22412783Ssam 				error = EISCONN;
22513116Ssam 				break;
22612783Ssam 			}
22737472Ssklower 			rp->rcb_faddr = mtod(nam, struct sockaddr *);
22837472Ssklower 		} else if (rp->rcb_faddr == 0) {
22912783Ssam 			error = ENOTCONN;
23013116Ssam 			break;
23112783Ssam 		}
2326505Ssam 		error = (*so->so_proto->pr_output)(m, so);
23312783Ssam 		m = NULL;
2348395Swnj 		if (nam)
23537472Ssklower 			rp->rcb_faddr = 0;
2365612Swnj 		break;
2375612Swnj 
2385612Swnj 	case PRU_ABORT:
2395612Swnj 		raw_disconnect(rp);
2405612Swnj 		sofree(so);
2415612Swnj 		soisdisconnected(so);
2425612Swnj 		break;
2435612Swnj 
24416974Skarels 	case PRU_SENSE:
24516974Skarels 		/*
24616974Skarels 		 * stat: don't bother with a blocksize.
24716974Skarels 		 */
24816974Skarels 		return (0);
24916974Skarels 
2505612Swnj 	/*
2515612Swnj 	 * Not supported.
2525612Swnj 	 */
25316773Sbloom 	case PRU_RCVOOB:
2545612Swnj 	case PRU_RCVD:
25516773Sbloom 		return(EOPNOTSUPP);
25616773Sbloom 
25725221Skarels 	case PRU_LISTEN:
25816773Sbloom 	case PRU_ACCEPT:
2595612Swnj 	case PRU_SENDOOB:
2605612Swnj 		error = EOPNOTSUPP;
2615612Swnj 		break;
2625612Swnj 
2636509Ssam 	case PRU_SOCKADDR:
26437472Ssklower 		if (rp->rcb_laddr == 0) {
26537472Ssklower 			error = EINVAL;
26637472Ssklower 			break;
26737472Ssklower 		}
26837472Ssklower 		len = rp->rcb_laddr->sa_len;
26937472Ssklower 		bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len);
27037472Ssklower 		nam->m_len = len;
2716509Ssam 		break;
2726509Ssam 
27314122Ssam 	case PRU_PEERADDR:
27437472Ssklower 		if (rp->rcb_faddr == 0) {
27537472Ssklower 			error = ENOTCONN;
27637472Ssklower 			break;
27737472Ssklower 		}
27837472Ssklower 		len = rp->rcb_faddr->sa_len;
27937472Ssklower 		bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len);
28037472Ssklower 		nam->m_len = len;
28114122Ssam 		break;
28214122Ssam 
2835612Swnj 	default:
2845612Swnj 		panic("raw_usrreq");
2855612Swnj 	}
28612783Ssam release:
28712783Ssam 	if (m != NULL)
28812783Ssam 		m_freem(m);
2895612Swnj 	return (error);
2905121Swnj }
29137472Ssklower 
29237472Ssklower rawintr() {} /* XXX - referenced by locore.  will soon go away */
293