Fix 8 space tab formatting for non-C files
[akaros.git] / kern / src / net / udp.c
index f32d83f..c3e901b 100644 (file)
@@ -27,8 +27,6 @@
  * SOFTWARE. */
 
 #define DEBUG
-#include <vfs.h>
-#include <kfs.h>
 #include <slab.h>
 #include <kmalloc.h>
 #include <kref.h>
 #include <cpio.h>
 #include <pmap.h>
 #include <smp.h>
-#include <ip.h>
+#include <net/ip.h>
 
-#include <vfs.h>
-#include <kfs.h>
 #include <slab.h>
 #include <kmalloc.h>
 #include <kref.h>
@@ -53,7 +49,7 @@
 #include <cpio.h>
 #include <pmap.h>
 #include <smp.h>
-#include <ip.h>
+#include <net/ip.h>
 
 #define DPRINT if(0)print
 
@@ -79,21 +75,21 @@ enum {
 typedef struct Udp4hdr Udp4hdr;
 struct Udp4hdr {
        /* ip header */
-       uint8_t vihl;                           /* Version and header length */
-       uint8_t tos;                            /* Type of service */
-       uint8_t length[2];                      /* packet length */
-       uint8_t id[2];                          /* Identification */
-       uint8_t frag[2];                        /* Fragment information */
+       uint8_t vihl;                   /* Version and header length */
+       uint8_t tos;                    /* Type of service */
+       uint8_t length[2];              /* packet length */
+       uint8_t id[2];                  /* Identification */
+       uint8_t frag[2];                /* Fragment information */
        uint8_t Unused;
-       uint8_t udpproto;                       /* Protocol */
-       uint8_t udpplen[2];                     /* Header plus data length */
+       uint8_t udpproto;               /* Protocol */
+       uint8_t udpplen[2];             /* Header plus data length */
        uint8_t udpsrc[IPv4addrlen];    /* Ip source */
        uint8_t udpdst[IPv4addrlen];    /* Ip destination */
 
        /* udp header */
        uint8_t udpsport[2];            /* Source port */
        uint8_t udpdport[2];            /* Destination port */
-       uint8_t udplen[2];                      /* data length */
+       uint8_t udplen[2];              /* data length */
        uint8_t udpcksum[2];            /* Checksum */
 };
 
@@ -109,7 +105,7 @@ struct Udp6hdr {
        /* udp header */
        uint8_t udpsport[2];            /* Source port */
        uint8_t udpdport[2];            /* Destination port */
-       uint8_t udplen[2];                      /* data length */
+       uint8_t udplen[2];              /* data length */
        uint8_t udpcksum[2];            /* Checksum */
 };
 
@@ -130,8 +126,8 @@ struct Udppriv {
        Udpstats ustats;
 
        /* non-MIB stats */
-       uint32_t csumerr;                       /* checksum errors */
-       uint32_t lenerr;                        /* short packet */
+       uint32_t csumerr;               /* checksum errors */
+       uint32_t lenerr;                /* short packet */
 };
 
 void (*etherprofiler) (char *name, int qlen);
@@ -142,45 +138,52 @@ void udpkick(void *x, struct block *bp);
  */
 typedef struct Udpcb Udpcb;
 struct Udpcb {
-       qlock_t qlock;
        uint8_t headers;
 };
 
-static char *udpconnect(struct conv *c, char **argv, int argc)
+static void udpconnect(struct conv *c, char **argv, int argc)
 {
-       char *e;
        Udppriv *upriv;
 
        upriv = c->p->priv;
-       e = Fsstdconnect(c, argv, argc);
-       Fsconnected(c, e);
-       if (e != NULL)
-               return e;
+       Fsstdconnect(c, argv, argc);
+       Fsconnected(c, 0);
 
        iphtadd(&upriv->ht, c);
-       return NULL;
+}
+
+static void udpbind(struct conv *c, char **argv, int argc)
+{
+       Udppriv *upriv;
+
+       upriv = c->p->priv;
+       Fsstdbind(c, argv, argc);
+       iphtadd(&upriv->ht, c);
 }
 
 static int udpstate(struct conv *c, char *state, int n)
 {
        return snprintf(state, n, "%s qin %d qout %d\n",
-                                       c->inuse ? "Open" : "Closed",
-                                       c->rq ? qlen(c->rq) : 0, c->wq ? qlen(c->wq) : 0);
+                       c->inuse ? "Open" : "Closed",
+                       c->rq ? qlen(c->rq) : 0, c->wq ? qlen(c->wq) : 0);
 }
 
-static char *udpannounce(struct conv *c, char **argv, int argc)
+static void udpannounce(struct conv *c, char **argv, int argc)
 {
-       char *e;
        Udppriv *upriv;
 
        upriv = c->p->priv;
-       e = Fsstdannounce(c, argv, argc);
-       if (e != NULL)
-               return e;
+       Fsstdannounce(c, argv, argc);
        Fsconnected(c, NULL);
        iphtadd(&upriv->ht, c);
+}
+
+static void udpbypass(struct conv *cv, char **argv, int argc)
+{
+       Udppriv *upriv = cv->p->priv;
 
-       return NULL;
+       Fsstdbypass(cv, argv, argc);
+       iphtadd(&upriv->ht, cv);
 }
 
 static void udpcreate(struct conv *c)
@@ -236,40 +239,40 @@ void udpkick(void *x, struct block *bp)
 
        ucb = (Udpcb *) c->ptcl;
        switch (ucb->headers) {
-               case 7:
-                       /* get user specified addresses */
-                       bp = pullupblock(bp, UDP_USEAD7);
-                       if (bp == NULL)
-                               return;
-                       ipmove(raddr, bp->rp);
-                       bp->rp += IPaddrlen;
-                       ipmove(laddr, bp->rp);
-                       bp->rp += IPaddrlen;
-                       /* pick interface closest to dest */
-                       if (ipforme(f, laddr) != Runi)
-                               findlocalip(f, laddr, raddr);
-                       bp->rp += IPaddrlen;    /* Ignore ifc address */
-                       rport = nhgets(bp->rp);
-                       bp->rp += 2 + 2;        /* Ignore local port */
-                       break;
-               case 6:
-                       /* get user specified addresses */
-                       bp = pullupblock(bp, UDP_USEAD6);
-                       if (bp == NULL)
-                               return;
-                       ipmove(raddr, bp->rp);
-                       bp->rp += IPaddrlen;
-                       ipmove(laddr, bp->rp);
-                       bp->rp += IPaddrlen;
-                       /* pick interface closest to dest */
-                       if (ipforme(f, laddr) != Runi)
-                               findlocalip(f, laddr, raddr);
-                       rport = nhgets(bp->rp);
-                       bp->rp += 2 + 2;        /* Ignore local port */
-                       break;
-               default:
-                       rport = 0;
-                       break;
+       case 7:
+               /* get user specified addresses */
+               bp = pullupblock(bp, UDP_USEAD7);
+               if (bp == NULL)
+                       return;
+               ipmove(raddr, bp->rp);
+               bp->rp += IPaddrlen;
+               ipmove(laddr, bp->rp);
+               bp->rp += IPaddrlen;
+               /* pick interface closest to dest */
+               if (ipforme(f, laddr) != Runi)
+                       findlocalip(f, laddr, raddr);
+               bp->rp += IPaddrlen;    /* Ignore ifc address */
+               rport = nhgets(bp->rp);
+               bp->rp += 2 + 2;        /* Ignore local port */
+               break;
+       case 6:
+               /* get user specified addresses */
+               bp = pullupblock(bp, UDP_USEAD6);
+               if (bp == NULL)
+                       return;
+               ipmove(raddr, bp->rp);
+               bp->rp += IPaddrlen;
+               ipmove(laddr, bp->rp);
+               bp->rp += IPaddrlen;
+               /* pick interface closest to dest */
+               if (ipforme(f, laddr) != Runi)
+                       findlocalip(f, laddr, raddr);
+               rport = nhgets(bp->rp);
+               bp->rp += 2 + 2;        /* Ignore local port */
+               break;
+       default:
+               rport = 0;
+               break;
        }
 
        if (ucb->headers) {
@@ -291,85 +294,89 @@ void udpkick(void *x, struct block *bp)
 
        /* fill in pseudo header and compute checksum */
        switch (version) {
-               case V4:
-                       bp = padblock(bp, UDP4_IPHDR_SZ + UDP_UDPHDR_SZ);
-                       if (bp == NULL)
-                               return;
-
-                       uh4 = (Udp4hdr *) (bp->rp);
-                       ptcllen = dlen + UDP_UDPHDR_SZ;
-                       uh4->Unused = 0;
-                       uh4->udpproto = IP_UDPPROTO;
-                       uh4->frag[0] = 0;
-                       uh4->frag[1] = 0;
-                       hnputs(uh4->udpplen, ptcllen);
-                       if (ucb->headers) {
-                               v6tov4(uh4->udpdst, raddr);
-                               hnputs(uh4->udpdport, rport);
-                               v6tov4(uh4->udpsrc, laddr);
-                               rc = NULL;
-                       } else {
-                               v6tov4(uh4->udpdst, c->raddr);
-                               hnputs(uh4->udpdport, c->rport);
-                               if (ipcmp(c->laddr, IPnoaddr) == 0)
-                                       findlocalip(f, c->laddr, c->raddr);
-                               v6tov4(uh4->udpsrc, c->laddr);
-                               rc = c;
-                       }
-                       hnputs(uh4->udpsport, c->lport);
-                       hnputs(uh4->udplen, ptcllen);
-                       uh4->udpcksum[0] = 0;
-                       uh4->udpcksum[1] = 0;
-                       hnputs(uh4->udpcksum,
-                                  ~ptclcsum(bp, UDP4_PHDR_OFF, UDP4_PHDR_SZ));
-                       bp->checksum_start = UDP4_IPHDR_SZ;
-                       bp->checksum_offset = uh4->udpcksum - uh4->udpsport;
-                       bp->flag |= Budpck;
-                       uh4->vihl = IP_VER4;
-                       ipoput4(f, bp, 0, c->ttl, c->tos, rc);
-                       break;
-
-               case V6:
-                       bp = padblock(bp, UDP6_IPHDR_SZ + UDP_UDPHDR_SZ);
-                       if (bp == NULL)
-                               return;
-
-                       // using the v6 ip header to create pseudo header 
-                       // first then reset it to the normal ip header
-                       uh6 = (Udp6hdr *) (bp->rp);
-                       memset(uh6, 0, 8);
-                       ptcllen = dlen + UDP_UDPHDR_SZ;
-                       hnputl(uh6->viclfl, ptcllen);
-                       uh6->hoplimit = IP_UDPPROTO;
-                       if (ucb->headers) {
-                               ipmove(uh6->udpdst, raddr);
-                               hnputs(uh6->udpdport, rport);
-                               ipmove(uh6->udpsrc, laddr);
-                               rc = NULL;
-                       } else {
-                               ipmove(uh6->udpdst, c->raddr);
-                               hnputs(uh6->udpdport, c->rport);
-                               if (ipcmp(c->laddr, IPnoaddr) == 0)
-                                       findlocalip(f, c->laddr, c->raddr);
-                               ipmove(uh6->udpsrc, c->laddr);
-                               rc = c;
-                       }
-                       hnputs(uh6->udpsport, c->lport);
-                       hnputs(uh6->udplen, ptcllen);
-                       uh6->udpcksum[0] = 0;
-                       uh6->udpcksum[1] = 0;
-                       hnputs(uh6->udpcksum,
-                                  ptclcsum(bp, UDP6_PHDR_OFF,
-                                                       dlen + UDP_UDPHDR_SZ + UDP6_PHDR_SZ));
-                       memset(uh6, 0, 8);
-                       uh6->viclfl[0] = IP_VER6;
-                       hnputs(uh6->len, ptcllen);
-                       uh6->nextheader = IP_UDPPROTO;
-                       ipoput6(f, bp, 0, c->ttl, c->tos, rc);
-                       break;
-
-               default:
-                       panic("udpkick: version %d", version);
+       case V4:
+               bp = padblock(bp, UDP4_IPHDR_SZ + UDP_UDPHDR_SZ);
+               if (bp == NULL)
+                       return;
+
+               uh4 = (Udp4hdr *) (bp->rp);
+               ptcllen = dlen + UDP_UDPHDR_SZ;
+               uh4->Unused = 0;
+               uh4->udpproto = IP_UDPPROTO;
+               uh4->frag[0] = 0;
+               uh4->frag[1] = 0;
+               hnputs(uh4->udpplen, ptcllen);
+               if (ucb->headers) {
+                       v6tov4(uh4->udpdst, raddr);
+                       hnputs(uh4->udpdport, rport);
+                       v6tov4(uh4->udpsrc, laddr);
+                       rc = NULL;
+               } else {
+                       v6tov4(uh4->udpdst, c->raddr);
+                       hnputs(uh4->udpdport, c->rport);
+                       if (ipcmp(c->laddr, IPnoaddr) == 0)
+                               findlocalip(f, c->laddr, c->raddr);
+                       v6tov4(uh4->udpsrc, c->laddr);
+                       rc = c;
+               }
+               hnputs(uh4->udpsport, c->lport);
+               hnputs(uh4->udplen, ptcllen);
+               uh4->udpcksum[0] = 0;
+               uh4->udpcksum[1] = 0;
+               bp->network_offset = 0;
+               bp->transport_offset = offsetof(Udp4hdr, udpsport);
+               assert(bp->transport_offset == UDP4_IPHDR_SZ);
+               hnputs(uh4->udpcksum,
+                          ~ptclcsum(bp, UDP4_PHDR_OFF, UDP4_PHDR_SZ));
+               bp->tx_csum_offset = uh4->udpcksum - uh4->udpsport;
+               bp->flag |= Budpck;
+               uh4->vihl = IP_VER4;
+               ipoput4(f, bp, 0, c->ttl, c->tos, rc);
+               break;
+
+       case V6:
+               bp = padblock(bp, UDP6_IPHDR_SZ + UDP_UDPHDR_SZ);
+               if (bp == NULL)
+                       return;
+
+               // using the v6 ip header to create pseudo header
+               // first then reset it to the normal ip header
+               uh6 = (Udp6hdr *) (bp->rp);
+               memset(uh6, 0, 8);
+               ptcllen = dlen + UDP_UDPHDR_SZ;
+               hnputl(uh6->viclfl, ptcllen);
+               uh6->hoplimit = IP_UDPPROTO;
+               if (ucb->headers) {
+                       ipmove(uh6->udpdst, raddr);
+                       hnputs(uh6->udpdport, rport);
+                       ipmove(uh6->udpsrc, laddr);
+                       rc = NULL;
+               } else {
+                       ipmove(uh6->udpdst, c->raddr);
+                       hnputs(uh6->udpdport, c->rport);
+                       if (ipcmp(c->laddr, IPnoaddr) == 0)
+                               findlocalip(f, c->laddr, c->raddr);
+                       ipmove(uh6->udpsrc, c->laddr);
+                       rc = c;
+               }
+               hnputs(uh6->udpsport, c->lport);
+               hnputs(uh6->udplen, ptcllen);
+               uh6->udpcksum[0] = 0;
+               uh6->udpcksum[1] = 0;
+               hnputs(uh6->udpcksum,
+                          ptclcsum(bp, UDP6_PHDR_OFF, dlen + UDP_UDPHDR_SZ +
+                                   UDP6_PHDR_SZ));
+               memset(uh6, 0, 8);
+               bp->network_offset = 0;
+               bp->transport_offset = offsetof(Udp6hdr, udpsport);
+               uh6->viclfl[0] = IP_VER6;
+               hnputs(uh6->len, ptcllen);
+               uh6->nextheader = IP_UDPPROTO;
+               ipoput6(f, bp, 0, c->ttl, c->tos, rc);
+               break;
+
+       default:
+               panic("udpkick: version %d", version);
        }
        upriv->ustats.udpOutDatagrams++;
 }
@@ -397,89 +404,92 @@ void udpiput(struct Proto *udp, struct Ipifc *ifc, struct block *bp)
        version = ((uh4->vihl & 0xF0) == IP_VER6) ? V6 : V4;
 
        /*
-        * Put back pseudo header for checksum 
+        * Put back pseudo header for checksum
         * (remember old values for icmpnoconv())
         */
        switch (version) {
-               case V4:
-                       ottl = uh4->Unused;
-                       uh4->Unused = 0;
-                       len = nhgets(uh4->udplen);
-                       olen = nhgets(uh4->udpplen);
-                       hnputs(uh4->udpplen, len);
-
-                       v4tov6(raddr, uh4->udpsrc);
-                       v4tov6(laddr, uh4->udpdst);
-                       lport = nhgets(uh4->udpdport);
-                       rport = nhgets(uh4->udpsport);
-
-                       if (!(bp->flag & Budpck) &&
-                           (uh4->udpcksum[0] || uh4->udpcksum[1]) &&
-                           ptclcsum(bp, UDP4_PHDR_OFF, len + UDP4_PHDR_SZ)) {
-                               upriv->ustats.udpInErrors++;
-                               netlog(f, Logudp, "udp: checksum error %I\n",
-                                      raddr);
-                               printd("udp: checksum error %I\n", raddr);
-                               freeblist(bp);
-                               return;
-                       }
-                       uh4->Unused = ottl;
-                       hnputs(uh4->udpplen, olen);
-                       break;
-               case V6:
-                       uh6 = (Udp6hdr *) (bp->rp);
-                       len = nhgets(uh6->udplen);
-                       oviclfl = nhgetl(uh6->viclfl);
-                       olen = nhgets(uh6->len);
-                       ottl = uh6->hoplimit;
-                       ipmove(raddr, uh6->udpsrc);
-                       ipmove(laddr, uh6->udpdst);
-                       lport = nhgets(uh6->udpdport);
-                       rport = nhgets(uh6->udpsport);
-                       memset(uh6, 0, 8);
-                       hnputl(uh6->viclfl, len);
-                       uh6->hoplimit = IP_UDPPROTO;
-                       if (ptclcsum(bp, UDP6_PHDR_OFF, len + UDP6_PHDR_SZ)) {
-                               upriv->ustats.udpInErrors++;
-                               netlog(f, Logudp, "udp: checksum error %I\n", raddr);
-                               printd("udp: checksum error %I\n", raddr);
-                               freeblist(bp);
-                               return;
-                       }
-                       hnputl(uh6->viclfl, oviclfl);
-                       hnputs(uh6->len, olen);
-                       uh6->nextheader = IP_UDPPROTO;
-                       uh6->hoplimit = ottl;
-                       break;
-               default:
-                       panic("udpiput: version %d", version);
-                       return; /* to avoid a warning */
+       case V4:
+               ottl = uh4->Unused;
+               uh4->Unused = 0;
+               len = nhgets(uh4->udplen);
+               olen = nhgets(uh4->udpplen);
+               hnputs(uh4->udpplen, len);
+
+               v4tov6(raddr, uh4->udpsrc);
+               v4tov6(laddr, uh4->udpdst);
+               lport = nhgets(uh4->udpdport);
+               rport = nhgets(uh4->udpsport);
+
+               if (!(bp->flag & Budpck) &&
+                   (uh4->udpcksum[0] || uh4->udpcksum[1]) &&
+                   ptclcsum(bp, UDP4_PHDR_OFF, len + UDP4_PHDR_SZ)) {
+                       upriv->ustats.udpInErrors++;
+                       netlog(f, Logudp, "udp: checksum error %I\n",
+                              raddr);
+                       printd("udp: checksum error %I\n", raddr);
+                       freeblist(bp);
+                       return;
+               }
+               uh4->Unused = ottl;
+               hnputs(uh4->udpplen, olen);
+               break;
+       case V6:
+               uh6 = (Udp6hdr *) (bp->rp);
+               len = nhgets(uh6->udplen);
+               oviclfl = nhgetl(uh6->viclfl);
+               olen = nhgets(uh6->len);
+               ottl = uh6->hoplimit;
+               ipmove(raddr, uh6->udpsrc);
+               ipmove(laddr, uh6->udpdst);
+               lport = nhgets(uh6->udpdport);
+               rport = nhgets(uh6->udpsport);
+               memset(uh6, 0, 8);
+               hnputl(uh6->viclfl, len);
+               uh6->hoplimit = IP_UDPPROTO;
+               if (ptclcsum(bp, UDP6_PHDR_OFF, len + UDP6_PHDR_SZ)) {
+                       upriv->ustats.udpInErrors++;
+                       netlog(f, Logudp, "udp: checksum error %I\n", raddr);
+                       printd("udp: checksum error %I\n", raddr);
+                       freeblist(bp);
+                       return;
+               }
+               hnputl(uh6->viclfl, oviclfl);
+               hnputs(uh6->len, olen);
+               uh6->nextheader = IP_UDPPROTO;
+               uh6->hoplimit = ottl;
+               break;
+       default:
+               panic("udpiput: version %d", version);
+               return; /* to avoid a warning */
        }
 
-       qlock(&udp->qlock);
-
        c = iphtlook(&upriv->ht, raddr, rport, laddr, lport);
        if (c == NULL) {
                /* no converstation found */
                upriv->ustats.udpNoPorts++;
-               qunlock(&udp->qlock);
                netlog(f, Logudp, "udp: no conv %I!%d -> %I!%d\n", raddr, rport,
                           laddr, lport);
 
                switch (version) {
-                       case V4:
-                               icmpnoconv(f, bp);
-                               break;
-                       case V6:
-                               icmphostunr(f, ifc, bp, icmp6_port_unreach, 0);
-                               break;
-                       default:
-                               panic("udpiput2: version %d", version);
+               case V4:
+                       icmpnoconv(f, bp);
+                       break;
+               case V6:
+                       icmphostunr(f, ifc, bp, icmp6_port_unreach, 0);
+                       break;
+               default:
+                       panic("udpiput2: version %d", version);
                }
 
                freeblist(bp);
                return;
        }
+
+       if (c->state == Bypass) {
+               bypass_or_drop(c, bp);
+               return;
+       }
+
        ucb = (Udpcb *) c->ptcl;
 
        if (c->state == Announced) {
@@ -487,19 +497,20 @@ void udpiput(struct Proto *udp, struct Ipifc *ifc, struct block *bp)
                        /* create a new conversation */
                        if (ipforme(f, laddr) != Runi) {
                                switch (version) {
-                                       case V4:
-                                               v4tov6(laddr, ifc->lifc->local);
-                                               break;
-                                       case V6:
-                                               ipmove(laddr, ifc->lifc->local);
-                                               break;
-                                       default:
-                                               panic("udpiput3: version %d", version);
+                               case V4:
+                                       v4tov6(laddr, ifc->lifc->local);
+                                       break;
+                               case V6:
+                                       ipmove(laddr, ifc->lifc->local);
+                                       break;
+                               default:
+                                       panic("udpiput3: version %d", version);
                                }
                        }
+                       qlock(&udp->qlock);
                        c = Fsnewcall(c, raddr, rport, laddr, lport, version);
+                       qunlock(&udp->qlock);
                        if (c == NULL) {
-                               qunlock(&udp->qlock);
                                freeblist(bp);
                                return;
                        }
@@ -509,22 +520,21 @@ void udpiput(struct Proto *udp, struct Ipifc *ifc, struct block *bp)
        }
 
        qlock(&c->qlock);
-       qunlock(&udp->qlock);
 
        /*
         * Trim the packet down to data size
         */
        len -= UDP_UDPHDR_SZ;
        switch (version) {
-               case V4:
-                       bp = trimblock(bp, UDP4_IPHDR_SZ + UDP_UDPHDR_SZ, len);
-                       break;
-               case V6:
-                       bp = trimblock(bp, UDP6_IPHDR_SZ + UDP_UDPHDR_SZ, len);
-                       break;
-               default:
-                       bp = NULL;
-                       panic("udpiput4: version %d", version);
+       case V4:
+               bp = trimblock(bp, UDP4_IPHDR_SZ + UDP_UDPHDR_SZ, len);
+               break;
+       case V6:
+               bp = trimblock(bp, UDP6_IPHDR_SZ + UDP_UDPHDR_SZ, len);
+               break;
+       default:
+               bp = NULL;
+               panic("udpiput4: version %d", version);
        }
        if (bp == NULL) {
                qunlock(&c->qlock);
@@ -538,32 +548,32 @@ void udpiput(struct Proto *udp, struct Ipifc *ifc, struct block *bp)
                   laddr, lport, len);
 
        switch (ucb->headers) {
-               case 7:
-                       /* pass the src address */
-                       bp = padblock(bp, UDP_USEAD7);
-                       p = bp->rp;
-                       ipmove(p, raddr);
-                       p += IPaddrlen;
-                       ipmove(p, laddr);
-                       p += IPaddrlen;
-                       ipmove(p, ifc->lifc->local);
-                       p += IPaddrlen;
-                       hnputs(p, rport);
-                       p += 2;
-                       hnputs(p, lport);
-                       break;
-               case 6:
-                       /* pass the src address */
-                       bp = padblock(bp, UDP_USEAD6);
-                       p = bp->rp;
-                       ipmove(p, raddr);
-                       p += IPaddrlen;
-                       ipmove(p, ipforme(f, laddr) == Runi ? laddr : ifc->lifc->local);
-                       p += IPaddrlen;
-                       hnputs(p, rport);
-                       p += 2;
-                       hnputs(p, lport);
-                       break;
+       case 7:
+               /* pass the src address */
+               bp = padblock(bp, UDP_USEAD7);
+               p = bp->rp;
+               ipmove(p, raddr);
+               p += IPaddrlen;
+               ipmove(p, laddr);
+               p += IPaddrlen;
+               ipmove(p, ifc->lifc->local);
+               p += IPaddrlen;
+               hnputs(p, rport);
+               p += 2;
+               hnputs(p, lport);
+               break;
+       case 6:
+               /* pass the src address */
+               bp = padblock(bp, UDP_USEAD6);
+               p = bp->rp;
+               ipmove(p, raddr);
+               p += IPaddrlen;
+               ipmove(p, ipforme(f, laddr) == Runi ? laddr : ifc->lifc->local);
+               p += IPaddrlen;
+               hnputs(p, rport);
+               p += 2;
+               hnputs(p, lport);
+               break;
        }
 
        if (bp->next)
@@ -582,21 +592,16 @@ void udpiput(struct Proto *udp, struct Ipifc *ifc, struct block *bp)
 
 }
 
-char *udpctl(struct conv *c, char **f, int n)
+static void udpctl(struct conv *c, char **f, int n)
 {
-       Udpcb *ucb;
-
-       ucb = (Udpcb *) c->ptcl;
-       if (n == 1) {
-               if (strcmp(f[0], "oldheaders") == 0) {
-                       ucb->headers = 6;
-                       return NULL;
-               } else if (strcmp(f[0], "headers") == 0) {
-                       ucb->headers = 7;
-                       return NULL;
-               }
-       }
-       return "unknown control request";
+       Udpcb *ucb = (Udpcb*)c->ptcl;
+
+       if ((n == 1) && strcmp(f[0], "oldheaders") == 0)
+               ucb->headers = 6;
+       else if ((n == 1) && strcmp(f[0], "headers") == 0)
+               ucb->headers = 7;
+       else
+               error(EINVAL, "unknown command to %s", __func__);
 }
 
 void udpadvise(struct Proto *udp, struct block *bp, char *msg)
@@ -612,26 +617,25 @@ void udpadvise(struct Proto *udp, struct block *bp, char *msg)
        version = ((h4->vihl & 0xF0) == IP_VER6) ? V6 : V4;
 
        switch (version) {
-               case V4:
-                       v4tov6(dest, h4->udpdst);
-                       v4tov6(source, h4->udpsrc);
-                       psource = nhgets(h4->udpsport);
-                       pdest = nhgets(h4->udpdport);
-                       break;
-               case V6:
-                       h6 = (Udp6hdr *) (bp->rp);
-                       ipmove(dest, h6->udpdst);
-                       ipmove(source, h6->udpsrc);
-                       psource = nhgets(h6->udpsport);
-                       pdest = nhgets(h6->udpdport);
-                       break;
-               default:
-                       panic("udpadvise: version %d", version);
-                       return; /* to avoid a warning */
+       case V4:
+               v4tov6(dest, h4->udpdst);
+               v4tov6(source, h4->udpsrc);
+               psource = nhgets(h4->udpsport);
+               pdest = nhgets(h4->udpdport);
+               break;
+       case V6:
+               h6 = (Udp6hdr *) (bp->rp);
+               ipmove(dest, h6->udpdst);
+               ipmove(source, h6->udpsrc);
+               psource = nhgets(h6->udpsport);
+               pdest = nhgets(h6->udpdport);
+               break;
+       default:
+               panic("udpadvise: version %d", version);
+               return; /* to avoid a warning */
        }
 
        /* Look for a connection */
-       qlock(&udp->qlock);
        for (p = udp->conv; *p; p++) {
                s = *p;
                if (s->rport == pdest)
@@ -641,7 +645,6 @@ void udpadvise(struct Proto *udp, struct block *bp, char *msg)
                                                if (s->ignoreadvice)
                                                        break;
                                                qlock(&s->qlock);
-                                               qunlock(&udp->qlock);
                                                qhangup(s->rq, msg);
                                                qhangup(s->wq, msg);
                                                qunlock(&s->qlock);
@@ -649,7 +652,6 @@ void udpadvise(struct Proto *udp, struct block *bp, char *msg)
                                                return;
                                        }
        }
-       qunlock(&udp->qlock);
        freeblist(bp);
 }
 
@@ -668,14 +670,6 @@ int udpstats(struct Proto *udp, char *buf, int len)
        return p - buf;
 }
 
-void udpnewconv(struct Proto *udp, struct conv *conv)
-{
-       /* Fsprotoclone alloc'd our priv struct and attached it to conv already.
-        * Now we need to init it */
-       struct Udpcb *ucb = (struct Udpcb *)conv->ptcl;
-       qlock_init(&ucb->qlock);
-}
-
 void udpinit(struct Fs *fs)
 {
        struct Proto *udp;
@@ -684,7 +678,9 @@ void udpinit(struct Fs *fs)
        udp->priv = kzmalloc(sizeof(Udppriv), 0);
        udp->name = "udp";
        udp->connect = udpconnect;
+       udp->bind = udpbind;
        udp->announce = udpannounce;
+       udp->bypass = udpbypass;
        udp->ctl = udpctl;
        udp->state = udpstate;
        udp->create = udpcreate;
@@ -693,8 +689,7 @@ void udpinit(struct Fs *fs)
        udp->advise = udpadvise;
        udp->stats = udpstats;
        udp->ipproto = IP_UDPPROTO;
-       udp->nc = Nchans;
-       udp->newconv = udpnewconv;
+       udp->nc = 4096;
        udp->ptclsize = sizeof(Udpcb);
 
        Fsproto(fs, udp);