use new form of suser()
[unix-history] / usr / src / sys / net / raw_usrreq.c
index aee828e..5a9656d 100644 (file)
@@ -1,18 +1,36 @@
-/*     raw_usrreq.c    4.11    82/03/19        */
+/*
+ * Copyright (c) 1980, 1986 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *     @(#)raw_usrreq.c        7.6 (Berkeley) %G%
+ */
+
+#include "param.h"
+#include "mbuf.h"
+#include "domain.h"
+#include "protosw.h"
+#include "socket.h"
+#include "socketvar.h"
+#include "errno.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 "../net/raw_cb.h"
-#include "../errno.h"
+#include "if.h"
+#include "route.h"
+#include "netisr.h"
+#include "raw_cb.h"
 
 
-int    rawqmaxlen = IFQ_MAXLEN;
+#include "machine/mtpr.h"
 
 /*
  * Initialize raw connection block q.
 
 /*
  * Initialize raw connection block q.
@@ -20,165 +38,103 @@ int       rawqmaxlen = IFQ_MAXLEN;
 raw_init()
 {
 
 raw_init()
 {
 
-COUNT(RAW_INIT);
        rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
        rawintrq.ifq_maxlen = IFQ_MAXLEN;
 }
 
        rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
        rawintrq.ifq_maxlen = IFQ_MAXLEN;
 }
 
-/*
- * Raw protocol interface.
- */
-raw_input(m0, pf, daf, saf)
-       struct mbuf *m0;
-       struct sockproto *pf;
-       struct sockaddr *daf, *saf;
-{
-       register struct mbuf *m;
-       struct raw_header *rh;
-       int s;
-
-COUNT(RAW_INPUT);
-       /*
-        * 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_dst = *daf;
-       rh->raw_src = *saf;
-       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();
-       if (IF_QFULL(&rawintrq))
-               m_freem(m);
-       else
-               IF_ENQUEUE(&rawintrq, m);
-       splx(s);
-       schednetisr(NETISR_RAW);
-}
 
 /*
 
 /*
- * Raw protocol input routine.  Process packets entered
- * into the queue at interrupt time.  Find the socket
+ * Raw protocol input routine.  Find the socket
  * associated with the packet(s) and move them over.  If
  * nothing exists for this packet, drop it.
  */
  * associated with the packet(s) and move them over.  If
  * nothing exists for this packet, drop it.
  */
-rawintr()
+/*
+ * Raw protocol interface.
+ */
+raw_input(m0, proto, src, dst)
+       struct mbuf *m0;
+       struct sockproto *proto;
+       struct sockaddr *src, *dst;
 {
 {
-       int s;
-       struct mbuf *m;
        register struct rawcb *rp;
        register struct rawcb *rp;
-       register struct socket *so;
-       register struct protosw *pr;
-       register struct sockproto *sp;
-       register struct sockaddr *sa;
-       struct raw_header *rawp;
+       register struct mbuf *m = m0;
        struct socket *last;
 
        struct socket *last;
 
-COUNT(RAWINTR);
-next:
-       s = splimp();
-       IF_DEQUEUE(&rawintrq, m);
-       splx(s);
-       if (m == 0)
-               return;
-       rawp = mtod(m, struct raw_header *);
-       sp = &rawp->raw_protocol;
-       sa = &rawp->raw_dst;
-
-       /*
-        * 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) {
        last = 0;
        for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
-               so = rp->rcb_socket;
-               pr = so->so_proto;
-               if (pr->pr_family != sp->sp_family ||
-                   (pr->pr_protocol && pr->pr_protocol != sp->sp_protocol))
+               if (rp->rcb_proto.sp_family != proto->sp_family)
                        continue;
                        continue;
-               if (so->so_addr.sa_family && 
-                   sa->sa_family != so->so_addr.sa_family)
+               if (rp->rcb_proto.sp_protocol  &&
+                   rp->rcb_proto.sp_protocol != proto->sp_protocol)
                        continue;
                /*
                 * We assume the lower level routines have
                 * placed the address in a canonical format
                        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.
+                * suitable for a structure comparison.
                 *
                 *
-                * SHOULD HAVE A NUMBER OF MECHANISMS FOR
-                * MATCHING BASED ON rcb_flags
+                * Note that if the lengths are not the same
+                * the comparison will fail at the first byte.
                 */
                 */
-               if ((rp->rcb_flags & RAW_ADDR) &&
-                   bcmp(sa->sa_data, so->so_addr.sa_data, 14) != 0)
+#define        equal(a1, a2) \
+  (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
+               if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst))
+                       continue;
+               if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
                        continue;
                        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 (last) {
                        struct mbuf *n;
-
-                       if (n = m_copy(m->m_next, 0, (int)M_COPYALL))
-                               goto nospace;
-                       if (sbappendaddr(&last->so_rcv, &rawp->raw_src, n) == 0) {
-                               /*
-                                * Should drop notification of lost packet
-                                * into this guy's queue, but...
-                                */
-                               m_freem(n);
-                               goto nospace;
+                       if (n = m_copy(m, 0, (int)M_COPYALL)) {
+                               if (sbappendaddr(&last->so_rcv, src,
+                                   n, (struct mbuf *)0) == 0)
+                                       /* should notify about lost packet */
+                                       m_freem(n);
+                               else
+                                       sorwakeup(last);
                        }
                        }
-                       sorwakeup(last);
                }
                }
-nospace:
-               last = so;
+               last = rp->rcb_socket;
        }
        }
-       if (last == 0)
-               goto drop;
-       if (sbappendaddr(&last->so_rcv, &rawp->raw_src, m->m_next) == 0)
-{
-printf("rawintr: sbappendaddr failed\n");
-               goto drop;
+       if (last) {
+               if (sbappendaddr(&last->so_rcv, src,
+                   m, (struct mbuf *)0) == 0)
+                       m_freem(m);
+               else
+                       sorwakeup(last);
+       } else
+               m_freem(m);
 }
 }
-       (void) m_free(m);       /* generic header */
-       sorwakeup(last);
-       goto next;
-drop:
-       m_freem(m);
-       goto next;
+
+/*ARGSUSED*/
+raw_ctlinput(cmd, arg)
+       int cmd;
+       struct sockaddr *arg;
+{
+
+       if (cmd < 0 || cmd > PRC_NCMDS)
+               return;
+       /* INCOMPLETE */
 }
 
 /*ARGSUSED*/
 }
 
 /*ARGSUSED*/
-raw_usrreq(so, req, m, addr)
+raw_usrreq(so, req, m, nam, rights, control)
        struct socket *so;
        int req;
        struct socket *so;
        int req;
-       struct mbuf *m;
-       caddr_t addr;
+       struct mbuf *m, *nam, *rights, *control;
 {
        register struct rawcb *rp = sotorawcb(so);
 {
        register struct rawcb *rp = sotorawcb(so);
-       int error = 0;
-
-COUNT(RAW_USRREQ);
-       if (rp == 0 && req != PRU_ATTACH)
-               return (EINVAL);
+       register int error = 0;
+       int len;
 
 
+       if (req == PRU_CONTROL)
+               return (EOPNOTSUPP);
+       if (rights && rights->m_len) {
+               error = EOPNOTSUPP;
+               goto release;
+       }
+       if (rp == 0) {
+               error = EINVAL;
+               goto release;
+       }
        switch (req) {
 
        /*
        switch (req) {
 
        /*
@@ -187,11 +143,11 @@ COUNT(RAW_USRREQ);
         * the appropriate raw interface routine.
         */
        case PRU_ATTACH:
         * the appropriate raw interface routine.
         */
        case PRU_ATTACH:
-               if ((so->so_state & SS_PRIV) == 0)
-                       return (EPERM);
-               if (rp)
-                       return (EINVAL);
-               error = raw_attach(so, (struct sockaddr *)addr);
+               if ((so->so_state & SS_PRIV) == 0) {
+                       error = EACCES;
+                       break;
+               }
+               error = raw_attach(so, (int)nam);
                break;
 
        /*
                break;
 
        /*
@@ -199,11 +155,14 @@ COUNT(RAW_USRREQ);
         * Flush data or not depending on the options.
         */
        case PRU_DETACH:
         * Flush data or not depending on the options.
         */
        case PRU_DETACH:
-               if (rp == 0)
-                       return (ENOTCONN);
+               if (rp == 0) {
+                       error = ENOTCONN;
+                       break;
+               }
                raw_detach(rp);
                break;
 
                raw_detach(rp);
                break;
 
+#ifdef notdef
        /*
         * If a socket isn't bound to a single address,
         * the raw input routine will hand it anything
        /*
         * If a socket isn't bound to a single address,
         * the raw input routine will hand it anything
@@ -211,15 +170,33 @@ COUNT(RAW_USRREQ);
         * nothing else around it should go to). 
         */
        case PRU_CONNECT:
         * nothing else around it should go to). 
         */
        case PRU_CONNECT:
-               if (rp->rcb_flags & RAW_ADDR)
-                       return (EISCONN);
-               raw_connaddr(rp, (struct sockaddr *)addr);
+               if (rp->rcb_faddr) {
+                       error = EISCONN;
+                       break;
+               }
+               nam = m_copym(nam, 0, M_COPYALL, M_WAIT);
+               rp->rcb_faddr = mtod(nam, struct sockaddr *);
                soisconnected(so);
                break;
 
                soisconnected(so);
                break;
 
+       case PRU_BIND:
+               if (rp->rcb_laddr) {
+                       error = EINVAL;                 /* XXX */
+                       break;
+               }
+               error = raw_bind(so, nam);
+               break;
+#endif
+
+       case PRU_CONNECT2:
+               error = EOPNOTSUPP;
+               goto release;
+
        case PRU_DISCONNECT:
        case PRU_DISCONNECT:
-               if ((rp->rcb_flags & RAW_ADDR) == 0)
-                       return (ENOTCONN);
+               if (rp->rcb_faddr == 0) {
+                       error = ENOTCONN;
+                       break;
+               }
                raw_disconnect(rp);
                soisdisconnected(so);
                break;
                raw_disconnect(rp);
                soisdisconnected(so);
                break;
@@ -236,15 +213,20 @@ COUNT(RAW_USRREQ);
         * routine handles any massaging necessary.
         */
        case PRU_SEND:
         * 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;
+               if (nam) {
+                       if (rp->rcb_faddr) {
+                               error = EISCONN;
+                               break;
+                       }
+                       rp->rcb_faddr = mtod(nam, struct sockaddr *);
+               } else if (rp->rcb_faddr == 0) {
+                       error = ENOTCONN;
+                       break;
+               }
+               error = (*so->so_proto->pr_output)(m, so);
+               m = NULL;
+               if (nam)
+                       rp->rcb_faddr = 0;
                break;
 
        case PRU_ABORT:
                break;
 
        case PRU_ABORT:
@@ -253,20 +235,52 @@ COUNT(RAW_USRREQ);
                soisdisconnected(so);
                break;
 
                soisdisconnected(so);
                break;
 
+       case PRU_SENSE:
+               /*
+                * stat: don't bother with a blocksize.
+                */
+               return (0);
+
        /*
         * Not supported.
         */
        /*
         * Not supported.
         */
-       case PRU_ACCEPT:
-       case PRU_RCVD:
-       case PRU_CONTROL:
-       case PRU_SENSE:
        case PRU_RCVOOB:
        case PRU_RCVOOB:
+       case PRU_RCVD:
+               return(EOPNOTSUPP);
+
+       case PRU_LISTEN:
+       case PRU_ACCEPT:
        case PRU_SENDOOB:
                error = EOPNOTSUPP;
                break;
 
        case PRU_SENDOOB:
                error = EOPNOTSUPP;
                break;
 
+       case PRU_SOCKADDR:
+               if (rp->rcb_laddr == 0) {
+                       error = EINVAL;
+                       break;
+               }
+               len = rp->rcb_laddr->sa_len;
+               bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len);
+               nam->m_len = len;
+               break;
+
+       case PRU_PEERADDR:
+               if (rp->rcb_faddr == 0) {
+                       error = ENOTCONN;
+                       break;
+               }
+               len = rp->rcb_faddr->sa_len;
+               bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len);
+               nam->m_len = len;
+               break;
+
        default:
                panic("raw_usrreq");
        }
        default:
                panic("raw_usrreq");
        }
+release:
+       if (m != NULL)
+               m_freem(m);
        return (error);
 }
        return (error);
 }
+
+rawintr() {} /* XXX - referenced by locore.  will soon go away */