inner loop in sosend limited to "space" bytes to fix
[unix-history] / usr / src / sys / net / raw_usrreq.c
index b301fde..0670f0f 100644 (file)
@@ -1,4 +1,4 @@
-/*     raw_usrreq.c    4.25    83/02/10        */
+/*     raw_usrreq.c    6.1     83/07/29        */
 
 #include "../h/param.h"
 #include "../h/mbuf.h"
 
 #include "../h/param.h"
 #include "../h/mbuf.h"
@@ -8,6 +8,7 @@
 #include "../h/errno.h"
 
 #include "../net/if.h"
 #include "../h/errno.h"
 
 #include "../net/if.h"
+#include "../net/route.h"
 #include "../net/netisr.h"
 #include "../net/raw_cb.h"
 
 #include "../net/netisr.h"
 #include "../net/raw_cb.h"
 
@@ -112,7 +113,8 @@ next:
                        struct mbuf *n;
                        if ((n = m_copy(m->m_next, 0, (int)M_COPYALL)) == 0)
                                goto nospace;
                        struct mbuf *n;
                        if ((n = m_copy(m->m_next, 0, (int)M_COPYALL)) == 0)
                                goto nospace;
-                       if (sbappendaddr(&last->so_rcv, &rh->raw_src, n)==0) {
+                       if (sbappendaddr(&last->so_rcv, &rh->raw_src,
+                           n, (struct mbuf *)0) == 0) {
                                /* should notify about lost packet */
                                m_freem(n);
                                goto nospace;
                                /* should notify about lost packet */
                                m_freem(n);
                                goto nospace;
@@ -124,7 +126,8 @@ nospace:
        }
        if (last) {
                m = m_free(m);          /* header */
        }
        if (last) {
                m = m_free(m);          /* header */
-               if (sbappendaddr(&last->so_rcv, &rh->raw_src, m) == 0)
+               if (sbappendaddr(&last->so_rcv, &rh->raw_src,
+                   m, (struct mbuf *)0) == 0)
                        goto drop;
                sorwakeup(last);
                goto next;
                        goto drop;
                sorwakeup(last);
                goto next;
@@ -146,17 +149,22 @@ raw_ctlinput(cmd, arg)
 }
 
 /*ARGSUSED*/
 }
 
 /*ARGSUSED*/
-raw_usrreq(so, req, m, nam)
+raw_usrreq(so, req, m, nam, rights)
        struct socket *so;
        int req;
        struct socket *so;
        int req;
-       struct mbuf *m, *nam;
+       struct mbuf *m, *nam, *rights;
 {
        register struct rawcb *rp = sotorawcb(so);
 {
        register struct rawcb *rp = sotorawcb(so);
-       int error = 0;
-
-       if (rp == 0 && req != PRU_ATTACH)
-               return (EINVAL);
+       register int error = 0;
 
 
+       if (rights && rights->m_len) {
+               error = EOPNOTSUPP;
+               goto release;
+       }
+       if (rp == 0 && req != PRU_ATTACH) {
+               error = EINVAL;
+               goto release;
+       }
        switch (req) {
 
        /*
        switch (req) {
 
        /*
@@ -165,10 +173,14 @@ raw_usrreq(so, req, m, nam)
         * the appropriate raw interface routine.
         */
        case PRU_ATTACH:
         * the appropriate raw interface routine.
         */
        case PRU_ATTACH:
-               if ((so->so_state & SS_PRIV) == 0)
-                       return (EACCES);
-               if (rp)
-                       return (EINVAL);
+               if ((so->so_state & SS_PRIV) == 0) {
+                       error = EACCES;
+                       break;
+               }
+               if (rp) {
+                       error = EINVAL;
+                       break;
+               }
                error = raw_attach(so);
                break;
 
                error = raw_attach(so);
                break;
 
@@ -177,8 +189,10 @@ raw_usrreq(so, req, m, nam)
         * 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;
 
@@ -189,15 +203,33 @@ raw_usrreq(so, req, m, nam)
         * 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_FADDR)
-                       return (EISCONN);
+               if (rp->rcb_flags & RAW_FADDR) {
+                       error = EISCONN;
+                       break;
+               }
                raw_connaddr(rp, nam);
                soisconnected(so);
                break;
 
                raw_connaddr(rp, nam);
                soisconnected(so);
                break;
 
+       case PRU_CONNECT2:
+               error = EOPNOTSUPP;
+               goto release;
+
+       case PRU_BIND:
+               if (rp->rcb_flags & RAW_LADDR) {
+                       error = EINVAL;                 /* XXX */
+                       break;
+               }
+               error = raw_bind(so, nam);
+               break;
+
        case PRU_DISCONNECT:
        case PRU_DISCONNECT:
-               if ((rp->rcb_flags & RAW_FADDR) == 0)
-                       return (ENOTCONN);
+               if ((rp->rcb_flags & RAW_FADDR) == 0) {
+                       error = ENOTCONN;
+                       break;
+               }
+               if (rp->rcb_route.ro_rt)
+                       rtfree(rp->rcb_route.ro_rt);
                raw_disconnect(rp);
                soisdisconnected(so);
                break;
                raw_disconnect(rp);
                soisdisconnected(so);
                break;
@@ -215,12 +247,31 @@ raw_usrreq(so, req, m, nam)
         */
        case PRU_SEND:
                if (nam) {
         */
        case PRU_SEND:
                if (nam) {
-                       if (rp->rcb_flags & RAW_FADDR)
-                               return (EISCONN);
+                       if (rp->rcb_flags & RAW_FADDR) {
+                               error = EISCONN;
+                               break;
+                       }
                        raw_connaddr(rp, nam);
                        raw_connaddr(rp, nam);
-               } else if ((rp->rcb_flags & RAW_FADDR) == 0)
-                       return (ENOTCONN);
+               } else if ((rp->rcb_flags & RAW_FADDR) == 0) {
+                       error = ENOTCONN;
+                       break;
+               }
+               /*
+                * Check for routing.  If new foreign address, or
+                * no route presently in use, try to allocate new
+                * route.  On failure, just hand packet to output
+                * routine anyway in case it can handle it.
+                */
+               if ((rp->rcb_flags & RAW_DONTROUTE) == 0)
+                       if (!equal(rp->rcb_faddr, rp->rcb_route.ro_dst) ||
+                           rp->rcb_route.ro_rt == 0) {
+                               if (rp->rcb_route.ro_rt)
+                                       rtfree(rp->rcb_route.ro_rt);
+                               rp->rcb_route.ro_dst = rp->rcb_faddr;
+                               rtalloc(&rp->rcb_route);
+                       }
                error = (*so->so_proto->pr_output)(m, so);
                error = (*so->so_proto->pr_output)(m, so);
+               m = NULL;
                if (nam)
                        rp->rcb_flags &= ~RAW_FADDR;
                break;
                if (nam)
                        rp->rcb_flags &= ~RAW_FADDR;
                break;
@@ -231,12 +282,16 @@ raw_usrreq(so, req, m, nam)
                soisdisconnected(so);
                break;
 
                soisdisconnected(so);
                break;
 
+       case PRU_CONTROL:
+               m = NULL;
+               error = EOPNOTSUPP;
+               break;
+
        /*
         * Not supported.
         */
        case PRU_ACCEPT:
        case PRU_RCVD:
        /*
         * Not supported.
         */
        case PRU_ACCEPT:
        case PRU_RCVD:
-       case PRU_CONTROL:
        case PRU_SENSE:
        case PRU_RCVOOB:
        case PRU_SENDOOB:
        case PRU_SENSE:
        case PRU_RCVOOB:
        case PRU_SENDOOB:
@@ -249,8 +304,17 @@ raw_usrreq(so, req, m, nam)
                nam->m_len = sizeof (struct sockaddr);
                break;
 
                nam->m_len = sizeof (struct sockaddr);
                break;
 
+       case PRU_PEERADDR:
+               bcopy((caddr_t)&rp->rcb_faddr, mtod(nam, caddr_t),
+                   sizeof (struct sockaddr));
+               nam->m_len = sizeof (struct sockaddr);
+               break;
+
        default:
                panic("raw_usrreq");
        }
        default:
                panic("raw_usrreq");
        }
+release:
+       if (m != NULL)
+               m_freem(m);
        return (error);
 }
        return (error);
 }