early versions
authorBill Joy <wnj@ucbvax.Berkeley.EDU>
Mon, 25 Jan 1982 10:36:02 +0000 (02:36 -0800)
committerBill Joy <wnj@ucbvax.Berkeley.EDU>
Mon, 25 Jan 1982 10:36:02 +0000 (02:36 -0800)
SCCS-vsn: sys/net/raw_usrreq.c 4.5
SCCS-vsn: sys/netinet/raw_ip.c 4.2

usr/src/sys/net/raw_usrreq.c
usr/src/sys/netinet/raw_ip.c

index 0448e16..82d5e99 100644 (file)
@@ -1,47 +1,81 @@
-/*     raw_usrreq.c    4.4     82/01/19        */
+/*     raw_usrreq.c    4.5     82/01/24        */
 
 #include "../h/param.h"
 #include "../h/mbuf.h"
 
 #include "../h/param.h"
 #include "../h/mbuf.h"
+#include "../h/protosw.h"
 #include "../h/socket.h"
 #include "../h/socketvar.h"
 #include "../h/mtpr.h"
 #include "../net/in.h"
 #include "../net/in_systm.h"
 #include "../net/if.h"
 #include "../h/socket.h"
 #include "../h/socketvar.h"
 #include "../h/mtpr.h"
 #include "../net/in.h"
 #include "../net/in_systm.h"
 #include "../net/if.h"
+#include "../net/raw_cb.h"
+#include "/usr/include/errno.h"
+
+/*
+ * Initialize raw connection block q.
+*/
+raw_init()
+{
+COUNT(RAW_INIT);
+       rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
+}
 
 /*
  * Raw protocol interface.
  */
 
 /*
  * Raw protocol interface.
  */
-raw_input(m, pf, af)
-       struct mbuf *m;
+raw_input(m0, pf, af)
+       struct mbuf *m0;
        struct sockproto pf;
        struct sockaddr af;
 {
        struct sockproto pf;
        struct sockaddr af;
 {
-       struct mbuf *mh;
+       register struct mbuf *m;
+       struct raw_header *rh;
        int s;
 
        int s;
 
-       mh = m_get(M_DONTWAIT);
-       if (mh == 0)
-               goto drop;
-       mh->m_next = m;
-       mh->m_off = MMINOFF + sizeof (struct sockproto);
-       *mtod(m, struct sockaddr *) = af;
-       mh->m_off = MMINOFF;
-       *mtod(m, struct sockproto *) = pf;
-       mh->m_len = sizeof (struct sockproto) + sizeof (struct sockaddr);
+       /*
+        * Rip off an mbuf for a generic header.
+        */
+       m = m_get(M_DONTWAIT);
+       if (m == 0) {
+               m_freem(m0);
+               return;
+       }
+       m->m_next = m0;
+       m->m_off = MMINOFF;
+       m->m_len = sizeof(struct raw_header);
+       rh = mtod(m, struct raw_header *);
+       rh->raw_address = af;
+       rh->raw_protocol = pf;
+
+       /*
+        * Header now contains enough info to decide
+        * which socket to place packet in (if any).
+        * Queue it up for the raw protocol process
+        * running at software interrupt level.
+        */
        s = splimp();
        s = splimp();
-       IF_ENQUEUE(&rawintrq, mh);
+       IF_ENQUEUE(&rawintrq, m);
        splx(s);
        setrawintr();
        splx(s);
        setrawintr();
-       return;
-drop:
-       m_freem(m);
 }
 
 }
 
+/*
+ * Raw protocol input routine.  Process packets entered
+ * into the queue at interrupt time.  Find the socket
+ * associated with the packet(s) and move them over.  If
+ * nothing exists for this packet, drop it.
+ */
 rawintr()
 {
        int s;
        struct mbuf *m;
 rawintr()
 {
        int s;
        struct mbuf *m;
+       register struct rawcb *rp;
+       register struct socket *so;
+       register struct protosw *pr;
+       register struct sockproto *sp;
+       register struct sockaddr *sa;
+       struct socket *last;
 
 COUNT(RAWINTR);
 next:
 
 COUNT(RAWINTR);
 next:
@@ -50,8 +84,65 @@ next:
        splx(s);
        if (m == 0)
                return;
        splx(s);
        if (m == 0)
                return;
-       /* ... */
-       goto drop;
+       sp = &(mtod(m, struct raw_header *)->raw_protocol);
+       sa = &(mtod(m, struct raw_header *)->raw_address);
+
+       /*
+        * Find the appropriate socket(s) in which to place this
+        * packet.  This is done by matching the protocol and
+        * address information prepended by raw_input against
+        * the info stored in the control block structures.
+        */
+       last = 0;
+       for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
+               so = rp->rcb_socket;
+               pr = so->so_proto;
+
+               if (so->so_options & SO_DEBUG) {
+                       printf("rawintr: sp=<%d,%d>, af=<%d,%x>\n",
+                        sp->sp_family, sp->sp_protocol, sa->sa_family,
+                        ((struct sockaddr_in *)sa)->sin_addr);
+                       printf("pr=<%d,%d>\n", pr->pr_family, pr->pr_protocol);
+               }
+               if (pr->pr_family != sp->sp_family ||
+                   pr->pr_protocol != sp->sp_protocol)
+                       continue;
+               printf("rawintr: so=<%d,%x>\n", so->so_addr.sa_family,
+                       ((struct sockaddr_in *)&so->so_addr)->sin_addr);
+               if (sa->sa_family != so->so_addr.sa_family)
+                       continue;
+               /*
+                * We assume the lower level routines have
+                * placed the address in a canonical format
+                * suitable for a structure comparison. Packets
+                * are duplicated for each receiving socket.
+                */
+               if ((rp->rcb_flags & RAW_ADDR) &&
+                   bcmp(sa->sa_data, so->so_addr.sa_data, 14) != 0)
+                       continue;
+               /*
+                * To avoid extraneous packet copies, we keep
+                * track of the last socket the packet should be
+                * placed in, and make copies only after finding a
+                * socket which "collides".
+                */
+               if (last) {
+                       struct mbuf *n;
+
+                       if (n = m_copy(m->m_next, 0, M_COPYALL))
+                               goto nospace;
+                       sbappend(&last->so_rcv, n);
+                       sorwakeup(last);
+               }
+nospace:
+               last = so;
+       }
+       if (last == 0)
+               goto drop;
+       m = m_free(m);          /* drop generic header */
+       sbappend(&last->so_rcv, m->m_next);
+       sorwakeup(last);
+       goto next;
 drop:
        m_freem(m);
        goto next;
 drop:
        m_freem(m);
        goto next;
@@ -64,7 +155,101 @@ raw_usrreq(so, req, m, addr)
        struct mbuf *m;
        caddr_t addr;
 {
        struct mbuf *m;
        caddr_t addr;
 {
+       register struct rawcb *rp = sotorawcb(so);
+       int error = 0;
 
 COUNT(RAW_USRREQ);
 
 COUNT(RAW_USRREQ);
+       if (so->so_options & SO_DEBUG)
+               printf("raw_usrreq: req=%d\n");
+       if (rp == 0 && req != PRU_ATTACH)
+               return (EINVAL);
+
+       switch (req) {
+
+       /*
+        * Allocate a raw control block and fill in the
+        * necessary info to allow packets to be routed to
+        * the appropriate raw interface routine.
+        */
+       case PRU_ATTACH:
+               if (rp)
+                       return (EINVAL);;
+               error = raw_attach(so, (struct sockaddr *)addr);
+               break;
+
+       /*
+        * Destroy state just before socket deallocation.
+        * Flush data or not depending on the options.
+        */
+       case PRU_DETACH:
+               if (rp == 0)
+                       return (ENOTCONN);
+               raw_detach(rp);
+               break;
+
+       /*
+        * If a socket isn't bound to a single address,
+        * the raw input routine will hand it anything
+        * within that protocol family (assuming there's
+        * nothing else around it should go to). 
+        */
+       case PRU_CONNECT:
+               if (rp->rcb_flags & RAW_ADDR)
+                       return (EISCONN);
+               raw_connaddr(rp, (struct sockaddr *)addr);
+               soisconnected(so);
+               break;
+
+       case PRU_DISCONNECT:
+               if ((rp->rcb_flags & RAW_ADDR) == 0)
+                       return (ENOTCONN);
+               raw_disconnect(rp);
+               soisdisconnected(so);
+               break;
+
+       /*
+        * Mark the connection as being incapable of further input.
+        */
+       case PRU_SHUTDOWN:
+               socantsendmore(so);
+               break;
+
+       /*
+        * Ship a packet out.  The appropriate raw output
+        * routine handles any massaging necessary.
+        */
+       case PRU_SEND:
+               if (addr) {
+                       if (rp->rcb_flags & RAW_ADDR)
+                               return (EISCONN);
+                       raw_connaddr(rp, (struct sockaddr *)addr);
+               } else if ((rp->rcb_flags & RAW_ADDR) == 0)
+                       return (ENOTCONN);
+               (void) (*so->so_proto->pr_output)(m, so);
+               if (addr)
+                       rp->rcb_flags &= ~RAW_ADDR;
+               break;
+
+       case PRU_ABORT:
+               raw_disconnect(rp);
+               sofree(so);
+               soisdisconnected(so);
+               break;
+
+       /*
+        * Not supported.
+        */
+       case PRU_ACCEPT:
+       case PRU_RCVD:
+       case PRU_CONTROL:
+       case PRU_SENSE:
+       case PRU_RCVOOB:
+       case PRU_SENDOOB:
+               error = EOPNOTSUPP;
+               break;
 
 
+       default:
+               panic("raw_usrreq");
+       }
+       return (error);
 }
 }
index 8ec42b3..4dc91f8 100644 (file)
-/*     raw_ip.c        4.1     81/11/29        */
+/*     raw_ip.c        4.2     82/01/24        */
 
 #include "../h/param.h"
 #include "../h/mbuf.h"
 #include "../h/socket.h"
 
 #include "../h/param.h"
 #include "../h/mbuf.h"
 #include "../h/socket.h"
+#include "../h/protosw.h"
 #include "../h/socketvar.h"
 #include "../net/in.h"
 #include "../net/in_systm.h"
 #include "../h/socketvar.h"
 #include "../net/in.h"
 #include "../net/in_systm.h"
+#include "../net/ip.h"
+#include "../net/ip_var.h"
+#include "../net/raw_cb.h"
+#include "/usr/include/errno.h"
 
 /*
 
 /*
- * Raw protocol interface.
+ * Raw interface to IP protocol.
+ */
+
+static struct sockaddr_in ripaddr = { PF_INET };
+static struct sockproto ripproto = { AF_INET };
+
+/*
+ * Setup generic address and protocol structures
+ * for raw_input routine, then pass them along with
+ * mbuf chain.
  */
  */
-/*ARGSUSED*/
 rip_input(m)
        struct mbuf *m;
 {
 rip_input(m)
        struct mbuf *m;
 {
+       register struct ip *ip = mtod(m, struct ip *);
+       struct sockaddr_in sin;
+       struct sockproto sp;
 
 COUNT(RIP_INPUT);
 
 COUNT(RIP_INPUT);
-
-       /* call raw_input with prepared parameters */
+       ripproto.sp_protocol = ip->ip_p;
+       ripaddr.sin_addr = ip->ip_dst;
+       raw_input(m, ripproto, ripaddr);
 }
 
 /*ARGSUSED*/
 rip_ctlinput(m)
        struct mbuf *m;
 {
 }
 
 /*ARGSUSED*/
 rip_ctlinput(m)
        struct mbuf *m;
 {
-
 COUNT(RIP_CTLINPUT);
 COUNT(RIP_CTLINPUT);
-
 }
 
 }
 
-/*ARGSUSED*/
-rip_output(m)
-       struct mbuf *m;
+/*
+ * Generate IP header and pass packet to ip_output.
+ * Tack on options user may have setup with control call.
+ */
+rip_output(m0, so)
+       struct mbuf *m0;
+       struct socket *so;
 {
 {
+       register struct mbuf *m;
+       register struct ip *ip;
+       register int len = 0;
+       register struct rawcb *rp = sotorawcb(so);
 
 COUNT(RIP_OUTPUT);
 
 COUNT(RIP_OUTPUT);
-
+       if (so->so_options & SO_DEBUG)
+               printf("rip_output\n");
+       /*
+        * Calculate data length and get an mbuf
+        * for IP header.
+        */
+       for (m = m0; m; m = m->m_next)
+               len += m->m_len;
+       m = m_get(M_DONTWAIT);
+       if (m == 0) {
+               (void) m_freem(m);
+               return;
+       }
+       
+       /*
+        * Fill in IP header as needed.
+        */
+       m->m_off = MMAXOFF - sizeof(struct ip);
+       m->m_len = sizeof(struct ip);
+       m->m_next = m0;
+       ip = mtod(m, struct ip *);
+       ip->ip_p = so->so_proto->pr_protocol;
+       ip->ip_len = sizeof(struct ip) + len;
+       ip->ip_dst =
+               ((struct sockaddr_in *)&rp->rcb_addr)->sin_addr;
+       ip->ip_src =
+               ((struct sockaddr_in *)&so->so_addr)->sin_addr;
+       ip->ip_ttl = MAXTTL;
+printf("ip=<p=%d,len=%d,dst=%x,src=%x>\n",ip->ip_p,ip->ip_len,ip->ip_dst,ip->ip_src);
+       return (ip_output(m, 0));
 }
 
 }
 
-/*ARGSUSED*/
+/*
+ * Intercept control operations related to
+ * handling of IP options.  Otherwise,
+ * just pass things on to the raw_usrreq
+ * routine for setup and tear down of
+ * raw control block data structures.
+ */
 rip_usrreq(so, req, m, addr)
        struct socket *so;
        int req;
        struct mbuf *m;
        caddr_t addr;
 {
 rip_usrreq(so, req, m, addr)
        struct socket *so;
        int req;
        struct mbuf *m;
        caddr_t addr;
 {
+       register struct rawcb *rp = sotorawcb(so);
 
 COUNT(RAW_USRREQ);
 
 COUNT(RAW_USRREQ);
-
-}
-
-rip_slowtimo()
-{
-
-COUNT(RIP_SLOWTIMO);
-
+       if (rp == 0 && req != PRU_ATTACH)
+               return (EINVAL);
+
+       switch (req) {
+       
+       case PRU_CONTROL:
+               return (EOPNOTSUPP);
+       }
+       return (raw_usrreq(so, req, m, addr));
 }
 }