FBSD: deal with kernel API rename
[openafs.git] / src / rx / FBSD / rx_knet.c
index 30ae839..ded3f7c 100644 (file)
 /*
-****************************************************************************
-*        Copyright IBM Corporation 1988, 1989 - All Rights Reserved        *
-*        Copyright Transarc Corporation 1989 - All Rights Reserved         *
-*                                                                          *
-* Permission to use, copy, modify, and distribute this software and its    *
-* documentation for any purpose and without fee is hereby granted,         *
-* provided that the above copyright notice appear in all copies and        *
-* that both that copyright notice and this permission notice appear in     *
-* supporting documentation, and that the name of IBM not be used in        *
-* advertising or publicity pertaining to distribution of the software      *
-* without specific, written prior permission.                              *
-*                                                                          *
-* IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL *
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL IBM *
-* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY      *
-* DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER  *
-* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING   *
-* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.    *
-****************************************************************************
-*/
-
-#include "../afs/param.h"
-#ifdef AFS_FBSD40_ENV
-#include "../rx/rx_kcommon.h"
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ * 
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+#include <afsconfig.h>
+#include "afs/param.h"
+
+
+#include <sys/malloc.h>
+#include "rx/rx_kcommon.h"
+
+#ifdef RXK_LISTENER_ENV
+int
+osi_NetReceive(osi_socket asocket, struct sockaddr_in *addr,
+              struct iovec *dvec, int nvecs, int *alength)
+{
+    struct uio u;
+    int i;
+    struct iovec iov[RX_MAXIOVECS];
+    struct sockaddr *sa = NULL;
+    int code;
+
+    int haveGlock = ISAFS_GLOCK();
+    /*AFS_STATCNT(osi_NetReceive); */
+
+    if (nvecs > RX_MAXIOVECS)
+       osi_Panic("osi_NetReceive: %d: Too many iovecs.\n", nvecs);
+
+    for (i = 0; i < nvecs; i++)
+       iov[i] = dvec[i];
+
+    u.uio_iov = &iov[0];
+    u.uio_iovcnt = nvecs;
+    u.uio_offset = 0;
+    u.uio_resid = *alength;
+    u.uio_segflg = UIO_SYSSPACE;
+    u.uio_rw = UIO_READ;
+    u.uio_td = NULL;
+
+    if (haveGlock)
+       AFS_GUNLOCK();
+    code = soreceive(asocket, &sa, &u, NULL, NULL, NULL);
+    if (haveGlock)
+       AFS_GLOCK();
+
+    if (code) {
+#if KNET_DEBUG
+       if (code == EINVAL)
+           Debugger("afs NetReceive busted");
+       else
+           printf("y");
+#else
+       return code;
+#endif
+    }
+    *alength -= u.uio_resid;
+    if (sa) {
+       if (sa->sa_family == AF_INET) {
+           if (addr)
+               *addr = *(struct sockaddr_in *)sa;
+       } else
+           printf("Unknown socket family %d in NetReceive\n", sa->sa_family);
+       FREE(sa, M_SONAME);
+    }
+    return code;
+}
+
+extern int rxk_ListenerPid;
+void
+osi_StopListener(void)
+{
+    struct sockaddr_in taddr;
+    struct iovec dvec;
+    struct proc *p;
+    char c;
+    c = '\0';
+
+    /*
+     * Have to drop global lock to safely do this.
+     * soclose() is currently protected by Giant,
+     * but pfind and psignal are MPSAFE.
+     */
+    int haveGlock = ISAFS_GLOCK();
+    if (haveGlock)
+       AFS_GUNLOCK();
+    soshutdown(rx_socket, SHUT_RDWR);
+    p = pfind(rxk_ListenerPid);
+    if (p) {
+       afs_warn("osi_StopListener: rxk_ListenerPid %u\n", rxk_ListenerPid);
+#if (__FreeBSD_version >= 90004)
+       kern_psignal(p, SIGUSR1);
+#else
+       psignal(p, SIGUSR1);
+#endif
+       PROC_UNLOCK(p);
+    } else
+       afs_warn("osi_StopListener: rxk_Listener not found (pid %u)\n",
+           rxk_ListenerPid);
+
+    /* Avoid destroying socket until osi_NetReceive has
+    * had a chance to clean up.  Otherwise we can't restart. */
+    bzero(&taddr, sizeof(taddr));
+    taddr.sin_len = sizeof(struct sockaddr_in);
+    taddr.sin_family = AF_INET;
+    taddr.sin_port = rx_port;
+    taddr.sin_addr.s_addr = htonl(0x7f000001); /* no place like localhost */
+    bzero(&dvec, sizeof(dvec));
+    dvec.iov_base = &c;
+    dvec.iov_len = 1;
+    /* afs_osi_Sleep requires the GLOCK */
+    AFS_GLOCK();
+    while(rxk_ListenerPid) {
+       afs_warn("waiting for rxk_ListenerPid to die\n");
+       osi_NetSend(rx_socket, &taddr, &dvec, 1, 1, 0);
+       afs_osi_Sleep(&rxk_ListenerPid);
+    }
+    AFS_GUNLOCK();
+    /* in theory, we are now the only people doing anything with rx_socket */
+    soclose(rx_socket);
+
+    if (haveGlock)
+       AFS_GLOCK();
+}
+
+int
+osi_NetSend(osi_socket asocket, struct sockaddr_in *addr, struct iovec *dvec,
+           int nvecs, afs_int32 alength, int istack)
+{
+    afs_int32 code;
+    int i;
+    struct iovec iov[RX_MAXIOVECS];
+    struct uio u;
+    int haveGlock = ISAFS_GLOCK();
+
+    AFS_STATCNT(osi_NetSend);
+    if (nvecs > RX_MAXIOVECS)
+       osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
 
+    for (i = 0; i < nvecs; i++)
+       iov[i] = dvec[i];
 
+    u.uio_iov = &iov[0];
+    u.uio_iovcnt = nvecs;
+    u.uio_offset = 0;
+    u.uio_resid = alength;
+    u.uio_segflg = UIO_SYSSPACE;
+    u.uio_rw = UIO_WRITE;
+    u.uio_td = NULL;
+
+    addr->sin_len = sizeof(struct sockaddr_in);
+
+    if (haveGlock)
+       AFS_GUNLOCK();
+#if KNET_DEBUG
+    printf("+");
+#endif
+    code =
+       sosend(asocket, (struct sockaddr *)addr, &u, NULL, NULL, 0,
+              curthread);
+#if KNET_DEBUG
+    if (code) {
+       if (code == EINVAL)
+           Debugger("afs NetSend busted");
+       else
+           printf("z");
+    }
+#endif
+    if (haveGlock)
+       AFS_GLOCK();
+    return code;
+}
+#else
+/* This code *almost* works :( */
 static struct protosw parent_proto;    /* udp proto switch */
-static void rxk_input (struct mbuf *am, int iphlen);
-static void rxk_fasttimo (void);
+static void rxk_input(struct mbuf *am, int iphlen);
+static void rxk_fasttimo(void);
 
 /* start intercepting basic calls */
-rxk_init() {
-    register struct protosw *tpro, *last;
-    if (rxk_initDone) return 0;
+rxk_init()
+{
+    struct protosw *tpro, *last;
+    if (rxk_initDone)
+       return 0;
 
     last = inetdomain.dom_protoswNPROTOSW;
     for (tpro = inetdomain.dom_protosw; tpro < last; tpro++)
-      if (tpro->pr_protocol == IPPROTO_UDP) {
-       /* force UDP checksumming on for AFS    */
-        extern int udpcksum;
-        udpcksum = 1;  
-          bcopy(tpro, &parent_proto, sizeof(parent_proto));
-          tpro->pr_input = rxk_input;
-          tpro->pr_fasttimo = rxk_fasttimo;
-          /*
-           * don't bother with pr_drain and pr_ctlinput
-           * until we have something to do
-           */
-          rxk_initDone = 1;
-          return 0;
-      }
+       if (tpro->pr_protocol == IPPROTO_UDP) {
+#if 0                          /* not exported */
+           /* force UDP checksumming on for AFS    */
+           extern int udpcksum;
+           udpcksum = 1;
+#endif
+           memcpy(&parent_proto, tpro, sizeof(parent_proto));
+           tpro->pr_input = rxk_input;
+           tpro->pr_fasttimo = rxk_fasttimo;
+           /*
+            * don't bother with pr_drain and pr_ctlinput
+            * until we have something to do
+            */
+           rxk_initDone = 1;
+           return 0;
+       }
     osi_Panic("inet:no udp");
 }
 
 
-static void rxk_input (struct mbuf *am, int iphlen)
+static void
+rxk_input(struct mbuf *am, int iphlen)
 {
-    void (*tproc)();
-    register unsigned short *tsp;
+    void (*tproc) ();
+    unsigned short *tsp;
     int hdr;
     struct udphdr *tu;
-    register struct ip *ti;
+    struct ip *ti;
     struct udpiphdr *tvu;
-    register int i;
+    int i;
     char *phandle;
     afs_int32 code;
     struct sockaddr_in taddr;
@@ -74,28 +230,28 @@ static void rxk_input (struct mbuf *am, int iphlen)
     NETPRI;
 
     /* make sure we have base ip and udp headers in first mbuf */
-    if (iphlen > sizeof (struct ip)) {
-        ip_stripoptions(am, (struct mbuf *)0);
-        iphlen = sizeof (struct ip);
+    if (iphlen > sizeof(struct ip)) {
+       ip_stripoptions(am, NULL);
+       iphlen = sizeof(struct ip);
     }
 
     if (am->m_len < sizeof(struct udpiphdr)) {
-        am = m_pullup(am, sizeof(struct udpiphdr));
-        if (!am) {
+       am = m_pullup(am, sizeof(struct udpiphdr));
+       if (!am) {
            USERPRI;
            return;
-        }
+       }
     }
 
     ti = mtod(am, struct ip *);
     /* skip basic ip hdr */
-    tu = (struct udphdr *)(((char *)ti) + sizeof(struct ip)); 
-    
+    tu = (struct udphdr *)(((char *)ti) + sizeof(struct ip));
+
     /* now read the port out */
     port = tu->uh_dport;
 
     if (port) {
-       for(tsp=rxk_ports, i=0; i<MAXRXPORTS;i++) {
+       for (tsp = rxk_ports, i = 0; i < MAXRXPORTS; i++) {
            if (*tsp++ == port) {
                /* checksum the packet */
                /*
@@ -103,7 +259,7 @@ static void rxk_input (struct mbuf *am, int iphlen)
                 * If not enough data to reflect UDP length, drop.
                 */
                tvu = (struct udpiphdr *)ti;
-               tlen = ntohs((u_short)tvu->ui_ulen);
+               tlen = ntohs((u_short) tvu->ui_ulen);
                if ((int)ti->ip_len != tlen) {
                    if (tlen > (int)ti->ip_len) {
                        m_free(am);
@@ -113,31 +269,31 @@ static void rxk_input (struct mbuf *am, int iphlen)
                    m_adj(am, tlen - (int)ti->ip_len);
                }
                /* deliver packet to rx */
-               taddr.sin_family = AF_INET;         /* compute source address */
+               taddr.sin_family = AF_INET;     /* compute source address */
                taddr.sin_port = tu->uh_sport;
                taddr.sin_addr.s_addr = ti->ip_src.s_addr;
                taddr.sin_len = sizeof(taddr);
-               tvu = (struct udpiphdr *) ti;   /* virtual udp structure, for cksum */
+               tvu = (struct udpiphdr *)ti;    /* virtual udp structure, for cksum */
                /* handle the checksum.  Note that this code damages the actual ip
-                  header (replacing it with the virtual one, which is the same size),
-                  so we must ensure we get everything out we need, first */
-               if ( tu->uh_sum != 0) {
-                       /* if the checksum is there, always check it. It's crazy not
-                        * to, unless you can really be sure that your
-                        * underlying network (and interfaces and drivers and
-                        * DMA hardware, etc!) is error-free. First, fill
-                        * in entire virtual ip header. */
-                       memset(tvu->ui_i.ih_x1, 0, 9);
-                       tvu->ui_len = tvu->ui_ulen;
-                       tlen = ntohs((unsigned short)(tvu->ui_ulen));
-                       if (in_cksum(am, sizeof(struct ip) + tlen)) {
-                           /* checksum, including cksum field, doesn't come out 0, so
-                              this packet is bad */
-                           m_freem(am);
-                           USERPRI;
-                           return;
-                       }
-                     }
+                * header (replacing it with the virtual one, which is the same size),
+                * so we must ensure we get everything out we need, first */
+               if (tu->uh_sum != 0) {
+                   /* if the checksum is there, always check it. It's crazy not
+                    * to, unless you can really be sure that your
+                    * underlying network (and interfaces and drivers and
+                    * DMA hardware, etc!) is error-free. First, fill
+                    * in entire virtual ip header. */
+                   memset(tvu->ui_i.ih_x1, 0, 9);
+                   tvu->ui_len = tvu->ui_ulen;
+                   tlen = ntohs((unsigned short)(tvu->ui_ulen));
+                   if (in_cksum(am, sizeof(struct ip) + tlen)) {
+                       /* checksum, including cksum field, doesn't come out 0, so
+                        * this packet is bad */
+                       m_freem(am);
+                       USERPRI;
+                       return;
+                   }
+               }
 
                /*
                 * 28 is IP (20) + UDP (8) header.  ulen includes
@@ -146,26 +302,25 @@ static void rxk_input (struct mbuf *am, int iphlen)
                 */
                data_len = ntohs(tu->uh_ulen);
                data_len -= 8;
-               AFS_RXGLOCK();
-               if (!(*rxk_GetPacketProc)(&phandle, data_len)) {
-                 if (rx_mb_to_packet(am, m_freem, 28, data_len, phandle)) {
-                   /* XXX should just increment counter here.. */
-                   printf("rx: truncated UDP packet\n");
-                   rxi_FreePacket(phandle);
-                 }
-                 else 
-                   (*rxk_PacketArrivalProc)(phandle, &taddr,
-                                            rxk_portRocks[i], data_len);
-               }else m_freem(am);
-               AFS_RXGUNLOCK();
+               if (!(*rxk_GetPacketProc) (&phandle, data_len)) {
+                   if (rx_mb_to_packet(am, m_freem, 28, data_len, phandle)) {
+                       /* XXX should just increment counter here.. */
+                       printf("rx: truncated UDP packet\n");
+                       rxi_FreePacket(phandle);
+                   } else
+                       (*rxk_PacketArrivalProc) (phandle, &taddr,
+                                                 rxk_portRocks[i], data_len);
+               } else
+                   m_freem(am);
                USERPRI;
                return;
-               }
            }
        }
+    }
 
     /* if we get here, try to deliver packet to udp */
-    if (tproc = parent_proto.pr_input) (*tproc)(am,iphlen);
+    if (tproc = parent_proto.pr_input)
+       (*tproc) (am, iphlen);
     USERPRI;
     return;
 }
@@ -176,17 +331,18 @@ static void rxk_input (struct mbuf *am, int iphlen)
  * Called about 5 times per second (at unknown priority?).  Must go to
  * splnet or obtain global lock before touching anything significant.
  */
-static void rxk_fasttimo (void)
+static void
+rxk_fasttimo(void)
 {
-    void (*tproc)();
+    void (*tproc) ();
     struct clock temp;
 
     /* do rx fasttimo processing here */
     rxevent_RaiseEvents(&temp);
-    if (tproc = parent_proto.pr_fasttimo) (*tproc)();
+    if (tproc = parent_proto.pr_fasttimo)
+       (*tproc) ();
 }
 
-
 /* rx_NetSend - send asize bytes at adata from asocket to host at addr.
  *
  * Now, why do we allocate a new buffer when we could theoretically use the one
@@ -205,65 +361,72 @@ static void rxk_fasttimo (void)
 
 /* set lock on sockbuf sb; can't call sblock since we're at interrupt level
  * sometimes */
-static trysblock(sb)    
-register struct sockbuf *sb; {
+static
+trysblock(sb)
+     struct sockbuf *sb;
+{
     AFS_STATCNT(trysblock);
-    if (sb->sb_flags & SB_LOCK){
-       return -1;  /* can't lock socket */
+    if (sb->sb_flags & SB_LOCK) {
+       return -1;              /* can't lock socket */
     }
     sb->sb_flags |= SB_LOCK;
     return 0;
 }
 
-int 
-osi_NetSend(asocket, addr, dvec, nvec, asize, istack)
-     register struct socket *asocket;
-     struct iovec *dvec;
-     int nvec;
-     register afs_int32 asize;
-     struct sockaddr_in *addr;
-     int istack;
+/* We only have to do all the mbuf management ourselves if we can be called at
+   interrupt time. in RXK_LISTENER_ENV, we can just call sosend() */
+int
+osi_NetSend(osi_socket asocket, struct sockaddr_in *addr, struct iovec *dvec,
+           int nvec, afs_int32 asize, int istack)
 {
-    register struct mbuf *tm, *um;
-    register afs_int32 code;
+    struct mbuf *tm, *um;
+    afs_int32 code;
     int s;
     struct mbuf *top = 0;
-    register struct mbuf *m, **mp;
+    struct mbuf *m, **mp;
     int len;
     char *tdata;
     caddr_t tpa;
-    int i,tl,rlen;
+    int i, tl, rlen;
     int mlen;
     int haveGlock;
+#if KNET_DEBUG
+    static int before = 0;
+#endif
 
     AFS_STATCNT(osi_NetSend);
-
 /* Actually, the Ultrix way is as good as any for us, so we don't bother with
  * special mbufs any more.  Used to think we could get away with not copying
  * the data to the interface, but there's no way to tell the caller not to
  * reuse the buffers after sending, so we lost out on that trick anyway */
-
     s = splnet();
+    if (trysblock(&asocket->so_snd)) {
+       splx(s);
+       return 1;
+    }
     mp = &top;
     i = 0;
     tdata = dvec[i].iov_base;
     tl = dvec[i].iov_len;
     while (1) {
        mlen = MLEN;
-        if (top == 0) {
-            MGETHDR(m, M_DONTWAIT, MT_DATA);
-            if (!m) {
-                splx(s);
-                return 1;
-            }
-            mlen = MHLEN;
-            m->m_pkthdr.len = 0;
-            m->m_pkthdr.rcvif = (struct ifnet *)0;
-        } else
-       MGET(m, M_DONTWAIT, MT_DATA);
+       if (top == 0) {
+           MGETHDR(m, M_DONTWAIT, MT_DATA);
+           if (!m) {
+               sbunlock(&asocket->so_snd);
+               splx(s);
+               return 1;
+           }
+           mlen = MHLEN;
+           m->m_pkthdr.len = 0;
+           m->m_pkthdr.rcvif = NULL;
+       } else
+           MGET(m, M_DONTWAIT, MT_DATA);
        if (!m) {
            /* can't get an mbuf, give up */
-           if (top) m_freem(top);      /* free mbuf list we're building */
+           if (top)
+               m_freem(top);   /* free mbuf list we're building */
+           sbunlock(&asocket->so_snd);
            splx(s);
            return 1;
        }
@@ -278,84 +441,93 @@ osi_NetSend(asocket, addr, dvec, nvec, asize, istack)
         * to ourself).
         */
        if (asize >= 4 * MLEN) {        /* try to get cluster mbuf */
-           register struct mbuf *p;
-
            /* different algorithms for getting cluster mbuf */
-            MCLGET(m, M_DONTWAIT);
-            if ((m->m_flags & M_EXT) == 0)
-                goto nopages;
-            mlen = MCLBYTES;
+           MCLGET(m, M_DONTWAIT);
+           if ((m->m_flags & M_EXT) == 0)
+               goto nopages;
+           mlen = MCLBYTES;
 
            /* now compute usable size */
-            len = MIN(mlen, asize);
+           len = MIN(mlen, asize);
 /* Should I look at MAPPED_MBUFS??? */
        } else {
-nopages:
-            len = MIN(mlen, asize);
+         nopages:
+           len = MIN(mlen, asize);
        }
        m->m_len = 0;
-        *mp = m;       /* XXXX */
-        top->m_pkthdr.len += len;
+       *mp = m;                /* XXXX */
+       top->m_pkthdr.len += len;
        tpa = mtod(m, caddr_t);
        while (len) {
-         rlen = MIN(len, tl);
-         bcopy(tdata, tpa, rlen);
-         asize -= rlen;
-         len -= rlen;
-         tpa += rlen;
-         m->m_len += rlen;
-         tdata += rlen;
-         tl -= rlen;
-         if (tl <= 0) {
-           i++;
-           if (i > nvec) {
-             /* shouldn't come here! */
-             asize = 0;   /* so we make progress toward completion */
-             break;
+           rlen = MIN(len, tl);
+           memcpy(tpa, tdata, rlen);
+           asize -= rlen;
+           len -= rlen;
+           tpa += rlen;
+           m->m_len += rlen;
+           tdata += rlen;
+           tl -= rlen;
+           if (tl <= 0) {
+               i++;
+               if (i > nvec) {
+                   /* shouldn't come here! */
+                   asize = 0;  /* so we make progress toward completion */
+                   break;
+               }
+               tdata = dvec[i].iov_base;
+               tl = dvec[i].iov_len;
            }
-           tdata = dvec[i].iov_base;
-           tl = dvec[i].iov_len;
-         }
        }
        *mp = m;
        mp = &m->m_next;
        if (asize <= 0)
-         break;
+           break;
     }
     tm = top;
 
-    tm->m_act = (struct mbuf *) 0;
+    tm->m_act = NULL;
 
     /* setup mbuf corresponding to destination address */
     um = m_get(M_DONTWAIT, MT_SONAME);
     if (!um) {
-       if (top) m_freem(top);  /* free mbuf chain */
-       /* if this were vfs40, we'd do sbunlock(asocket, &asocket->so_snd), but
-          we don't do the locking at all for vfs40 systems */
+       if (top)
+           m_freem(top);       /* free mbuf chain */
+       sbunlock(&asocket->so_snd);
        splx(s);
        return 1;
     }
-    bcopy(addr, mtod(um, caddr_t), sizeof(*addr));
-    um->m_len = sizeof(*addr);
+    memcpy(mtod(um, caddr_t), addr, sizeof(*addr));
+    addr->sin_len = um->m_len = sizeof(*addr);
     /* note that udp_usrreq frees funny mbuf.  We hold onto data, but mbuf
-     * around it is gone.  we free address ourselves.  */
+     * around it is gone. */
     /*    haveGlock = ISAFS_GLOCK();
-    if (haveGlock) {
-       AFS_GUNLOCK();
-       }  */
+     * if (haveGlock) {
+     * AFS_GUNLOCK();
+     * }  */
     /* SOCKET_LOCK(asocket); */
     /* code = (*asocket->so_proto->pr_usrreq)(asocket, PRU_SEND, tm, um, 0); */
-    code = (*asocket->so_proto->pr_usrreqs->pru_send)(asocket, 0, tm, 
-                                                     (struct sockaddr *) addr,
-                                                     um, curproc);
+#if KNET_DEBUG
+    if (before)
+       Debugger("afs NetSend before");
+#endif
+    code =
+       (*asocket->so_proto->pr_usrreqs->pru_send) (asocket, 0, tm,
+                                                   (struct sockaddr *)
+                                                   addr, um, &proc0);
     /* SOCKET_UNLOCK(asocket); */
     /* if (haveGlock) {
-       AFS_GLOCK();
-       } */
+     * AFS_GLOCK();
+     * } */
+    sbunlock(&asocket->so_snd);
     splx(s);
-    m_free(um);
-
+#if KNET_DEBUG
+    if (code) {
+       if (code == EINVAL)
+           Debugger("afs NetSend busted");
+       else
+           printf("z");
+    }
+#endif
     return code;
 }
-
-#endif /* AFS_FBSD40_ENV */
+#endif