123162Smckusick /*
2*63211Sbostic * Copyright (c) 1980, 1986, 1993
3*63211Sbostic * The Regents of the University of California. All rights reserved.
423162Smckusick *
544465Sbostic * %sccs.include.redist.c%
633183Sbostic *
7*63211Sbostic * @(#)raw_usrreq.c 8.1 (Berkeley) 06/10/93
823162Smckusick */
95121Swnj
1056529Sbostic #include <sys/param.h>
1156529Sbostic #include <sys/mbuf.h>
1256529Sbostic #include <sys/domain.h>
1356529Sbostic #include <sys/protosw.h>
1456529Sbostic #include <sys/socket.h>
1556529Sbostic #include <sys/socketvar.h>
1656529Sbostic #include <sys/errno.h>
1710890Ssam
1856529Sbostic #include <net/if.h>
1956529Sbostic #include <net/route.h>
2056529Sbostic #include <net/netisr.h>
2156529Sbostic #include <net/raw_cb.h>
225121Swnj
235121Swnj /*
245612Swnj * Initialize raw connection block q.
256211Swnj */
2661357Sbostic void
raw_init()275612Swnj raw_init()
285612Swnj {
296211Swnj
305612Swnj rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
315612Swnj }
325612Swnj
3337472Ssklower
345612Swnj /*
3537472Ssklower * Raw protocol input routine. Find the socket
3637472Ssklower * associated with the packet(s) and move them over. If
3737472Ssklower * nothing exists for this packet, drop it.
3837472Ssklower */
3937472Ssklower /*
405121Swnj * Raw protocol interface.
415121Swnj */
4261357Sbostic void
raw_input(m0,proto,src,dst)436529Ssam raw_input(m0, proto, src, dst)
445612Swnj struct mbuf *m0;
4539181Ssklower register struct sockproto *proto;
466529Ssam struct sockaddr *src, *dst;
475121Swnj {
485612Swnj register struct rawcb *rp;
4937472Ssklower register struct mbuf *m = m0;
5039181Ssklower register int sockets = 0;
515612Swnj struct socket *last;
525121Swnj
535612Swnj last = 0;
545612Swnj for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
5537472Ssklower if (rp->rcb_proto.sp_family != proto->sp_family)
565612Swnj continue;
5721769Skarels if (rp->rcb_proto.sp_protocol &&
5837472Ssklower rp->rcb_proto.sp_protocol != proto->sp_protocol)
595612Swnj continue;
605612Swnj /*
615612Swnj * We assume the lower level routines have
625612Swnj * placed the address in a canonical format
636509Ssam * suitable for a structure comparison.
6437472Ssklower *
6537472Ssklower * Note that if the lengths are not the same
6637472Ssklower * the comparison will fail at the first byte.
675612Swnj */
6837472Ssklower #define equal(a1, a2) \
6937472Ssklower (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
7037472Ssklower if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst))
715612Swnj continue;
7237472Ssklower if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
736509Ssam continue;
745612Swnj if (last) {
755612Swnj struct mbuf *n;
7637472Ssklower if (n = m_copy(m, 0, (int)M_COPYALL)) {
7737472Ssklower if (sbappendaddr(&last->so_rcv, src,
7821531Skarels n, (struct mbuf *)0) == 0)
7921531Skarels /* should notify about lost packet */
8021531Skarels m_freem(n);
8139181Ssklower else {
8221531Skarels sorwakeup(last);
8339181Ssklower sockets++;
8439181Ssklower }
855646Ssam }
865612Swnj }
876509Ssam last = rp->rcb_socket;
885612Swnj }
896584Ssam if (last) {
9037472Ssklower if (sbappendaddr(&last->so_rcv, src,
9137472Ssklower m, (struct mbuf *)0) == 0)
9237472Ssklower m_freem(m);
9339181Ssklower else {
9421531Skarels sorwakeup(last);
9539181Ssklower sockets++;
9639181Ssklower }
9721531Skarels } else
9821531Skarels m_freem(m);
995121Swnj }
1005121Swnj
1018636Sroot /*ARGSUSED*/
10261357Sbostic void
raw_ctlinput(cmd,arg)1036584Ssam raw_ctlinput(cmd, arg)
1046584Ssam int cmd;
10526379Skarels struct sockaddr *arg;
1066584Ssam {
1076591Ssam
1086591Ssam if (cmd < 0 || cmd > PRC_NCMDS)
1096591Ssam return;
1108636Sroot /* INCOMPLETE */
1116584Ssam }
1126584Ssam
1135121Swnj /*ARGSUSED*/
11461357Sbostic int
raw_usrreq(so,req,m,nam,control)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 }
281