net: Don't clobber the TTL for TCPv4 rx
[akaros.git] / kern / src / net / iproute.c
index 61746de..746c826 100644 (file)
@@ -1,4 +1,31 @@
-// INFERNO
+/* Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+ * Portions Copyright © 1997-1999 Vita Nuova Limited
+ * Portions Copyright © 2000-2007 Vita Nuova Holdings Limited
+ *                                (www.vitanuova.com)
+ * Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+ *
+ * Modified for the Akaros operating system:
+ * Copyright (c) 2013-2014 The Regents of the University of California
+ * Copyright (c) 2013-2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE. */
+
 #include <vfs.h>
 #include <kfs.h>
 #include <slab.h>
 #include <smp.h>
 #include <ip.h>
 
-static void    walkadd(struct Fs*, struct route**, struct route*);
-static void    addnode(struct Fs*, struct route**, struct route*);
-static void    calcd(struct route*);
+static void walkadd(struct Fs *, struct route **, struct route *);
+static void addnode(struct Fs *, struct route **, struct route *);
+static void calcd(struct route *);
 
 /* these are used for all instances of IP */
-struct route*  v4freelist;
-struct route*  v6freelist;
-rwlock_t       routelock;
-uint32_t       v4routegeneration, v6routegeneration;
+struct route *v4freelist;
+struct route *v6freelist;
+rwlock_t routelock;
+uint32_t v4routegeneration, v6routegeneration;
+
+/*
+ * TODO: Change this to a proper release.
+ * At the moment this is difficult to do since deleting
+ * a route involves manipulating more data structures than
+ * a kref/struct route.  E.g., unlinking from the route tree
+ * requires access to a parent pointer, which doesn't exist
+ * in the route structure itself.
+ */
+static void route_release(struct kref *kref)
+{
+       (void)kref;
+}
 
-static void
-freeroute(struct route *r)
+static void freeroute(struct route *r)
 {
        struct route **l;
 
        r->rt.left = NULL;
        r->rt.right = NULL;
-       if(r->rt.type & Rv4)
+       if (r->rt.type & Rv4)
                l = &v4freelist;
        else
                l = &v6freelist;
@@ -38,14 +77,13 @@ freeroute(struct route *r)
        *l = r;
 }
 
-static struct route*
-allocroute(int type)
+static struct route *allocroute(int type)
 {
        struct route *r;
        int n;
        struct route **l;
 
-       if(type & Rv4){
+       if (type & Rv4) {
                n = sizeof(struct RouteTree) + sizeof(struct V4route);
                l = &v4freelist;
        } else {
@@ -54,27 +92,26 @@ allocroute(int type)
        }
 
        r = *l;
-       if(r != NULL){
+       if (r != NULL) {
                *l = r->rt.mid;
        } else {
                r = kzmalloc(n, 0);
-               if(r == NULL)
+               if (r == NULL)
                        panic("out of routing nodes");
        }
        memset(r, 0, n);
        r->rt.type = type;
        r->rt.ifc = NULL;
-       kref_init(&r->rt.kref, fake_release, 1);
+       kref_init(&r->rt.kref, route_release, 1);
 
        return r;
 }
 
-static void
-addqueue(struct route **q, struct route *r)
+static void addqueue(struct route **q, struct route *r)
 {
        struct route *l;
 
-       if(r == NULL)
+       if (r == NULL)
                return;
 
        l = allocroute(r->rt.type);
@@ -86,15 +123,14 @@ addqueue(struct route **q, struct route *r)
 /*
  *   compare 2 v6 addresses
  */
-static int
-lcmp(uint32_t *a, uint32_t *b)
+static int lcmp(uint32_t * a, uint32_t * b)
 {
        int i;
 
-       for(i = 0; i < IPllen; i++){
-               if(a[i] > b[i])
+       for (i = 0; i < IPllen; i++) {
+               if (a[i] > b[i])
                        return 1;
-               if(a[i] < b[i])
+               if (a[i] < b[i])
                        return -1;
        }
        return 0;
@@ -103,8 +139,7 @@ lcmp(uint32_t *a, uint32_t *b)
 /*
  *  compare 2 v4 or v6 ranges
  */
-enum
-{
+enum {
        Rpreceeds,
        Rfollows,
        Requals,
@@ -112,47 +147,45 @@ enum
        Rcontained,
 };
 
-static int
-rangecompare(struct route *a, struct route *b)
+static int rangecompare(struct route *a, struct route *b)
 {
-       if(a->rt.type & Rv4){
-               if(a->v4.endaddress < b->v4.address)
+       if (a->rt.type & Rv4) {
+               if (a->v4.endaddress < b->v4.address)
                        return Rpreceeds;
 
-               if(a->v4.address > b->v4.endaddress)
+               if (a->v4.address > b->v4.endaddress)
                        return Rfollows;
 
-               if(a->v4.address <= b->v4.address
-               && a->v4.endaddress >= b->v4.endaddress){
-                       if(a->v4.address == b->v4.address
-                       && a->v4.endaddress == b->v4.endaddress)
+               if (a->v4.address <= b->v4.address
+                       && a->v4.endaddress >= b->v4.endaddress) {
+                       if (a->v4.address == b->v4.address
+                               && a->v4.endaddress == b->v4.endaddress)
                                return Requals;
                        return Rcontains;
                }
                return Rcontained;
        }
 
-       if(lcmp(a->v6.endaddress, b->v6.address) < 0)
+       if (lcmp(a->v6.endaddress, b->v6.address) < 0)
                return Rpreceeds;
 
-       if(lcmp(a->v6.address, b->v6.endaddress) > 0)
+       if (lcmp(a->v6.address, b->v6.endaddress) > 0)
                return Rfollows;
 
-       if(lcmp(a->v6.address, b->v6.address) <= 0
-       && lcmp(a->v6.endaddress, b->v6.endaddress) >= 0){
-               if(lcmp(a->v6.address, b->v6.address) == 0
-               && lcmp(a->v6.endaddress, b->v6.endaddress) == 0)
-                               return Requals;
+       if (lcmp(a->v6.address, b->v6.address) <= 0
+               && lcmp(a->v6.endaddress, b->v6.endaddress) >= 0) {
+               if (lcmp(a->v6.address, b->v6.address) == 0
+                       && lcmp(a->v6.endaddress, b->v6.endaddress) == 0)
+                       return Requals;
                return Rcontains;
        }
 
        return Rcontained;
 }
 
-static void
-copygate(struct route *old, struct route *new)
+static void copygate(struct route *old, struct route *new)
 {
-       if(new->rt.type & Rv4)
+       if (new->rt.type & Rv4)
                memmove(old->v4.gate, new->v4.gate, IPv4addrlen);
        else
                memmove(old->v6.gate, new->v6.gate, IPaddrlen);
@@ -161,8 +194,7 @@ copygate(struct route *old, struct route *new)
 /*
  *  walk down a tree adding nodes back in
  */
-static void
-walkadd(struct Fs *f, struct route **root, struct route *p)
+static void walkadd(struct Fs *f, struct route **root, struct route *p)
 {
        struct route *l, *r;
 
@@ -171,41 +203,39 @@ walkadd(struct Fs *f, struct route **root, struct route *p)
        p->rt.left = 0;
        p->rt.right = 0;
        addnode(f, root, p);
-       if(l)
+       if (l)
                walkadd(f, root, l);
-       if(r)
+       if (r)
                walkadd(f, root, r);
 }
 
 /*
  *  calculate depth
  */
-static void
-calcd(struct route *p)
+static void calcd(struct route *p)
 {
        struct route *q;
        int d;
 
-       if(p) {
+       if (p) {
                d = 0;
                q = p->rt.left;
-               if(q)
+               if (q)
                        d = q->rt.depth;
                q = p->rt.right;
-               if(q && q->rt.depth > d)
+               if (q && q->rt.depth > d)
                        d = q->rt.depth;
                q = p->rt.mid;
-               if(q && q->rt.depth > d)
+               if (q && q->rt.depth > d)
                        d = q->rt.depth;
-               p->rt.depth = d+1;
+               p->rt.depth = d + 1;
        }
 }
 
 /*
  *  balance the tree at the current node
  */
-static void
-balancetree(struct route **cur)
+static void balancetree(struct route **cur)
 {
        struct route *p, *l, *r;
        int dl, dr;
@@ -216,17 +246,20 @@ balancetree(struct route **cur)
         * rotate tree node
         */
        p = *cur;
-       dl = 0; if((l = p->rt.left)) dl = l->rt.depth;
-       dr = 0; if((r = p->rt.right)) dr = r->rt.depth;
-
-       if(dl > dr+1) {
+       dl = 0;
+       if ((l = p->rt.left))
+               dl = l->rt.depth;
+       dr = 0;
+       if ((r = p->rt.right))
+               dr = r->rt.depth;
+
+       if (dl > dr + 1) {
                p->rt.left = l->rt.right;
                l->rt.right = p;
                *cur = l;
                calcd(p);
                calcd(l);
-       } else
-       if(dr > dl+1) {
+       } else if (dr > dl + 1) {
                p->rt.right = r->rt.left;
                r->rt.left = p;
                *cur = r;
@@ -239,63 +272,62 @@ balancetree(struct route **cur)
 /*
  *  add a new node to the tree
  */
-static void
-addnode(struct Fs *f, struct route **cur, struct route *new)
+static void addnode(struct Fs *f, struct route **cur, struct route *new)
 {
        struct route *p;
 
        p = *cur;
-       if(p == 0) {
+       if (p == 0) {
                *cur = new;
                new->rt.depth = 1;
                return;
        }
 
-       switch(rangecompare(new, p)){
-       case Rpreceeds:
-               addnode(f, &p->rt.left, new);
-               break;
-       case Rfollows:
-               addnode(f, &p->rt.right, new);
-               break;
-       case Rcontains:
-               /*
-                *  if new node is superset
-                *  of tree node,
-                *  replace tree node and
-                *  queue tree node to be
-                *  merged into root.
-                */
-               *cur = new;
-               new->rt.depth = 1;
-               addqueue(&f->queue, p);
-               break;
-       case Requals:
-               /*
-                *  supercede the old entry if the old one isn't
-                *  a local interface.
-                */
-               if((p->rt.type & Rifc) == 0){
-                       p->rt.type = new->rt.type;
-                       p->rt.ifcid = -1;
-                       copygate(p, new);
-               } else if(new->rt.type & Rifc)
-                       kref_get(&p->rt.kref, 1);
-               freeroute(new);
-               break;
-       case Rcontained:
-               addnode(f, &p->rt.mid, new);
-               break;
+       switch (rangecompare(new, p)) {
+               case Rpreceeds:
+                       addnode(f, &p->rt.left, new);
+                       break;
+               case Rfollows:
+                       addnode(f, &p->rt.right, new);
+                       break;
+               case Rcontains:
+                       /*
+                        *  if new node is superset
+                        *  of tree node,
+                        *  replace tree node and
+                        *  queue tree node to be
+                        *  merged into root.
+                        */
+                       *cur = new;
+                       new->rt.depth = 1;
+                       addqueue(&f->queue, p);
+                       break;
+               case Requals:
+                       /*
+                        *  supercede the old entry if the old one isn't
+                        *  a local interface.
+                        */
+                       if ((p->rt.type & Rifc) == 0) {
+                               p->rt.type = new->rt.type;
+                               p->rt.ifcid = -1;
+                               copygate(p, new);
+                       } else if (new->rt.type & Rifc)
+                               kref_get(&p->rt.kref, 1);
+                       freeroute(new);
+                       break;
+               case Rcontained:
+                       addnode(f, &p->rt.mid, new);
+                       break;
        }
-       
+
        balancetree(cur);
 }
 
 #define        V4H(a)  ((a&0x07ffffff)>>(32-Lroot-5))
 
 void
-v4addroute(struct Fs *f, char *tag, uint8_t *a, uint8_t *mask,
-          uint8_t *gate, int type)
+v4addroute(struct Fs *f, char *tag, uint8_t * a, uint8_t * mask,
+                  uint8_t * gate, int type)
 {
        struct route *p;
        uint32_t sa;
@@ -308,7 +340,7 @@ v4addroute(struct Fs *f, char *tag, uint8_t *a, uint8_t *mask,
        ea = sa | ~m;
 
        eh = V4H(ea);
-       for(h=V4H(sa); h<=eh; h++) {
+       for (h = V4H(sa); h <= eh; h++) {
                p = allocroute(Rv4 | type);
                p->v4.address = sa;
                p->v4.endaddress = ea;
@@ -317,7 +349,7 @@ v4addroute(struct Fs *f, char *tag, uint8_t *a, uint8_t *mask,
 
                wlock(&routelock);
                addnode(f, &f->v4root[h], p);
-               while((p = f->queue)) {
+               while ((p = f->queue)) {
                        f->queue = p->rt.mid;
                        walkadd(f, &f->v4root[h], p->rt.left);
                        freeroute(p);
@@ -333,8 +365,8 @@ v4addroute(struct Fs *f, char *tag, uint8_t *a, uint8_t *mask,
 #define ISDFLT(a, mask, tag) ((ipcmp((a),v6Unspecified)==0) && (ipcmp((mask),v6Unspecified)==0) && (strcmp((tag), "ra")!=0))
 
 void
-v6addroute(struct Fs *f, char *tag, uint8_t *a, uint8_t *mask,
-          uint8_t *gate, int type)
+v6addroute(struct Fs *f, char *tag, uint8_t * a, uint8_t * mask,
+                  uint8_t * gate, int type)
 {
        struct route *p;
        uint32_t sa[IPllen], ea[IPllen];
@@ -342,20 +374,19 @@ v6addroute(struct Fs *f, char *tag, uint8_t *a, uint8_t *mask,
        int h, eh;
 
        /*
-       if(ISDFLT(a, mask, tag))
-               f->v6p->cdrouter = -1;
-       */
-
+          if(ISDFLT(a, mask, tag))
+          f->v6p->cdrouter = -1;
+        */
 
-       for(h = 0; h < IPllen; h++){
-               x = nhgetl(a+4*h);
-               y = nhgetl(mask+4*h);
+       for (h = 0; h < IPllen; h++) {
+               x = nhgetl(a + 4 * h);
+               y = nhgetl(mask + 4 * h);
                sa[h] = x & y;
                ea[h] = x | ~y;
        }
 
        eh = V6H(ea);
-       for(h = V6H(sa); h <= eh; h++) {
+       for (h = V6H(sa); h <= eh; h++) {
                p = allocroute(type);
                memmove(p->v6.address, sa, IPaddrlen);
                memmove(p->v6.endaddress, ea, IPaddrlen);
@@ -364,7 +395,7 @@ v6addroute(struct Fs *f, char *tag, uint8_t *a, uint8_t *mask,
 
                wlock(&routelock);
                addnode(f, &f->v6root[h], p);
-               while((p = f->queue)) {
+               while ((p = f->queue)) {
                        f->queue = p->rt.mid;
                        walkadd(f, &f->v6root[h], p->rt.left);
                        freeroute(p);
@@ -376,36 +407,34 @@ v6addroute(struct Fs *f, char *tag, uint8_t *a, uint8_t *mask,
        ipifcaddroute(f, 0, a, mask, gate, type);
 }
 
-struct route**
-looknode(struct route **cur, struct route *r)
+struct route **looknode(struct route **cur, struct route *r)
 {
        struct route *p;
 
-       for(;;){
+       for (;;) {
                p = *cur;
-               if(p == 0)
+               if (p == 0)
                        return 0;
-       
-               switch(rangecompare(r, p)){
-               case Rcontains:
-                       return 0;
-               case Rpreceeds:
-                       cur = &p->rt.left;
-                       break;
-               case Rfollows:
-                       cur = &p->rt.right;
-                       break;
-               case Rcontained:
-                       cur = &p->rt.mid;
-                       break;
-               case Requals:
-                       return cur;
+
+               switch (rangecompare(r, p)) {
+                       case Rcontains:
+                               return 0;
+                       case Rpreceeds:
+                               cur = &p->rt.left;
+                               break;
+                       case Rfollows:
+                               cur = &p->rt.right;
+                               break;
+                       case Rcontained:
+                               cur = &p->rt.mid;
+                               break;
+                       case Requals:
+                               return cur;
                }
        }
 }
 
-void
-v4delroute(struct Fs *f, uint8_t *a, uint8_t *mask, int dolock)
+void v4delroute(struct Fs *f, uint8_t * a, uint8_t * mask, int dolock)
 {
        struct route **r, *p;
        struct route rt;
@@ -418,11 +447,11 @@ v4delroute(struct Fs *f, uint8_t *a, uint8_t *mask, int dolock)
        rt.rt.type = Rv4;
 
        eh = V4H(rt.v4.endaddress);
-       for(h=V4H(rt.v4.address); h<=eh; h++) {
-               if(dolock)
+       for (h = V4H(rt.v4.address); h <= eh; h++) {
+               if (dolock)
                        wlock(&routelock);
                r = looknode(&f->v4root[h], &rt);
-               if(r) {
+               if (r) {
                        p = *r;
                        /* TODO: bad usage of kref (maybe use a release).  I didn't change
                         * this one, since it looks like the if code is when we want to
@@ -433,14 +462,14 @@ v4delroute(struct Fs *f, uint8_t *a, uint8_t *mask, int dolock)
                                addqueue(&f->queue, p->rt.mid);
                                addqueue(&f->queue, p->rt.right);
                                freeroute(p);
-                               while((p = f->queue)) {
+                               while ((p = f->queue)) {
                                        f->queue = p->rt.mid;
                                        walkadd(f, &f->v4root[h], p->rt.left);
                                        freeroute(p);
                                }
                        }
                }
-               if(dolock)
+               if (dolock)
                        wunlock(&routelock);
        }
        v4routegeneration++;
@@ -448,28 +477,27 @@ v4delroute(struct Fs *f, uint8_t *a, uint8_t *mask, int dolock)
        ipifcremroute(f, Rv4, a, mask);
 }
 
-void
-v6delroute(struct Fs *f, uint8_t *a, uint8_t *mask, int dolock)
+void v6delroute(struct Fs *f, uint8_t * a, uint8_t * mask, int dolock)
 {
        struct route **r, *p;
        struct route rt;
        int h, eh;
        uint32_t x, y;
 
-       for(h = 0; h < IPllen; h++){
-               x = nhgetl(a+4*h);
-               y = nhgetl(mask+4*h);
+       for (h = 0; h < IPllen; h++) {
+               x = nhgetl(a + 4 * h);
+               y = nhgetl(mask + 4 * h);
                rt.v6.address[h] = x & y;
                rt.v6.endaddress[h] = x | ~y;
        }
        rt.rt.type = 0;
 
        eh = V6H(rt.v6.endaddress);
-       for(h=V6H(rt.v6.address); h<=eh; h++) {
-               if(dolock)
+       for (h = V6H(rt.v6.address); h <= eh; h++) {
+               if (dolock)
                        wlock(&routelock);
                r = looknode(&f->v6root[h], &rt);
-               if(r) {
+               if (r) {
                        p = *r;
                        /* TODO: bad usage of kref (maybe use a release).  I didn't change
                         * this one, since it looks like the if code is when we want to
@@ -480,14 +508,14 @@ v6delroute(struct Fs *f, uint8_t *a, uint8_t *mask, int dolock)
                                addqueue(&f->queue, p->rt.mid);
                                addqueue(&f->queue, p->rt.right);
                                freeroute(p);
-                               while((p = f->queue)) {
+                               while ((p = f->queue)) {
                                        f->queue = p->rt.mid;
                                        walkadd(f, &f->v6root[h], p->rt.left);
                                        freeroute(p);
                                }
                        }
                }
-               if(dolock)
+               if (dolock)
                        wunlock(&routelock);
        }
        v6routegeneration++;
@@ -495,22 +523,22 @@ v6delroute(struct Fs *f, uint8_t *a, uint8_t *mask, int dolock)
        ipifcremroute(f, 0, a, mask);
 }
 
-struct route*
-v4lookup(struct Fs *f, uint8_t *a, struct conv *c)
+struct route *v4lookup(struct Fs *f, uint8_t * a, struct conv *c)
 {
        struct route *p, *q;
        uint32_t la;
        uint8_t gate[IPaddrlen];
        struct Ipifc *ifc;
 
-       if(c != NULL && c->r != NULL && c->r->rt.ifc != NULL && c->rgen == v4routegeneration)
+       if (c != NULL && c->r != NULL && c->r->rt.ifc != NULL
+               && c->rgen == v4routegeneration)
                return c->r;
 
        la = nhgetl(a);
        q = NULL;
-       for(p=f->v4root[V4H(la)]; p;)
-               if(la >= p->v4.address) {
-                       if(la <= p->v4.endaddress) {
+       for (p = f->v4root[V4H(la)]; p;)
+               if (la >= p->v4.address) {
+                       if (la <= p->v4.endaddress) {
                                q = p;
                                p = p->rt.mid;
                        } else
@@ -518,20 +546,20 @@ v4lookup(struct Fs *f, uint8_t *a, struct conv *c)
                } else
                        p = p->rt.left;
 
-       if(q && (q->rt.ifc == NULL || q->rt.ifcid != q->rt.ifc->ifcid)){
-               if(q->rt.type & Rifc) {
-                       hnputl(gate+IPv4off, q->v4.address);
+       if (q && (q->rt.ifc == NULL || q->rt.ifcid != q->rt.ifc->ifcid)) {
+               if (q->rt.type & Rifc) {
+                       hnputl(gate + IPv4off, q->v4.address);
                        memmove(gate, v4prefix, IPv4off);
                } else
                        v4tov6(gate, q->v4.gate);
                ifc = findipifc(f, gate, q->rt.type);
-               if(ifc == NULL)
+               if (ifc == NULL)
                        return NULL;
                q->rt.ifc = ifc;
                q->rt.ifcid = ifc->ifcid;
        }
 
-       if(c != NULL){
+       if (c != NULL) {
                c->r = q;
                c->rgen = v4routegeneration;
        }
@@ -539,8 +567,7 @@ v4lookup(struct Fs *f, uint8_t *a, struct conv *c)
        return q;
 }
 
-struct route*
-v6lookup(struct Fs *f, uint8_t *a, struct conv *c)
+struct route *v6lookup(struct Fs *f, uint8_t * a, struct conv *c)
 {
        struct route *p, *q;
        uint32_t la[IPllen];
@@ -549,37 +576,38 @@ v6lookup(struct Fs *f, uint8_t *a, struct conv *c)
        uint8_t gate[IPaddrlen];
        struct Ipifc *ifc;
 
-       if(memcmp(a, v4prefix, IPv4off) == 0){
-               q = v4lookup(f, a+IPv4off, c);
-               if(q != NULL)
+       if (memcmp(a, v4prefix, IPv4off) == 0) {
+               q = v4lookup(f, a + IPv4off, c);
+               if (q != NULL)
                        return q;
        }
 
-       if(c != NULL && c->r != NULL && c->r->rt.ifc != NULL && c->rgen == v6routegeneration)
+       if (c != NULL && c->r != NULL && c->r->rt.ifc != NULL
+               && c->rgen == v6routegeneration)
                return c->r;
 
-       for(h = 0; h < IPllen; h++)
-               la[h] = nhgetl(a+4*h);
+       for (h = 0; h < IPllen; h++)
+               la[h] = nhgetl(a + 4 * h);
 
        q = 0;
-       for(p=f->v6root[V6H(la)]; p;){
-               for(h = 0; h < IPllen; h++){
+       for (p = f->v6root[V6H(la)]; p;) {
+               for (h = 0; h < IPllen; h++) {
                        x = la[h];
                        y = p->v6.address[h];
-                       if(x == y)
+                       if (x == y)
                                continue;
-                       if(x < y){
+                       if (x < y) {
                                p = p->rt.left;
                                goto next;
                        }
                        break;
                }
-               for(h = 0; h < IPllen; h++){
+               for (h = 0; h < IPllen; h++) {
                        x = la[h];
                        y = p->v6.endaddress[h];
-                       if(x == y)
+                       if (x == y)
                                continue;
-                       if(x > y){
+                       if (x > y) {
                                p = p->rt.right;
                                goto next;
                        }
@@ -587,76 +615,75 @@ v6lookup(struct Fs *f, uint8_t *a, struct conv *c)
                }
                q = p;
                p = p->rt.mid;
-next:          ;
+next:  ;
        }
 
-       if(q && (q->rt.ifc == NULL || q->rt.ifcid != q->rt.ifc->ifcid)){
-               if(q->rt.type & Rifc) {
-                       for(h = 0; h < IPllen; h++)
-                               hnputl(gate+4*h, q->v6.address[h]);
+       if (q && (q->rt.ifc == NULL || q->rt.ifcid != q->rt.ifc->ifcid)) {
+               if (q->rt.type & Rifc) {
+                       for (h = 0; h < IPllen; h++)
+                               hnputl(gate + 4 * h, q->v6.address[h]);
                        ifc = findipifc(f, gate, q->rt.type);
                } else
                        ifc = findipifc(f, q->v6.gate, q->rt.type);
-               if(ifc == NULL)
+               if (ifc == NULL)
                        return NULL;
                q->rt.ifc = ifc;
                q->rt.ifcid = ifc->ifcid;
        }
-       if(c != NULL){
+       if (c != NULL) {
                c->r = q;
                c->rgen = v6routegeneration;
        }
-       
+
        return q;
 }
 
-void
-routetype(int type, char *p)
+void routetype(int type, char *p)
 {
        memset(p, ' ', 4);
        p[4] = 0;
-       if(type & Rv4)
+       if (type & Rv4)
                *p++ = '4';
        else
                *p++ = '6';
-       if(type & Rifc)
+       if (type & Rifc)
                *p++ = 'i';
-       if(type & Runi)
+       if (type & Runi)
                *p++ = 'u';
-       else if(type & Rbcast)
+       else if (type & Rbcast)
                *p++ = 'b';
-       else if(type & Rmulti)
+       else if (type & Rmulti)
                *p++ = 'm';
-       if(type & Rptpt)
+       if (type & Rptpt)
                *p = 'p';
 }
 
 char *rformat = "%-15I %-4M %-15I %4.4s %4.4s %3s\n";
 
 void
-convroute(struct route *r, uint8_t *addr, uint8_t *mask,
-         uint8_t *gate, char *t, int *nifc)
+convroute(struct route *r, uint8_t * addr, uint8_t * mask,
+                 uint8_t * gate, char *t, int *nifc)
 {
        int i;
 
-       if(r->rt.type & Rv4){
+       if (r->rt.type & Rv4) {
                memmove(addr, v4prefix, IPv4off);
-               hnputl(addr+IPv4off, r->v4.address);
+               hnputl(addr + IPv4off, r->v4.address);
                memset(mask, 0xff, IPv4off);
-               hnputl(mask+IPv4off, ~(r->v4.endaddress ^ r->v4.address));
+               hnputl(mask + IPv4off, ~(r->v4.endaddress ^ r->v4.address));
                memmove(gate, v4prefix, IPv4off);
-               memmove(gate+IPv4off, r->v4.gate, IPv4addrlen);
+               memmove(gate + IPv4off, r->v4.gate, IPv4addrlen);
        } else {
-               for(i = 0; i < IPllen; i++){
-                       hnputl(addr + 4*i, r->v6.address[i]);
-                       hnputl(mask + 4*i, ~(r->v6.endaddress[i] ^ r->v6.address[i]));
+               for (i = 0; i < IPllen; i++) {
+                       hnputl(addr + 4 * i, r->v6.address[i]);
+                       hnputl(mask + 4 * i, ~(r->v6.endaddress[i] ^ r->v6.address[i]));
                }
                memmove(gate, r->v6.gate, IPaddrlen);
        }
 
        routetype(r->rt.type, t);
 
-       if(r->rt.ifc)
+       if (r->rt.ifc)
                *nifc = r->rt.ifc->conv->x;
        else
                *nifc = -1;
@@ -665,8 +692,7 @@ convroute(struct route *r, uint8_t *addr, uint8_t *mask,
 /*
  *  this code is not in rr to reduce stack size
  */
-static void
-sprintroute(struct route *r, struct routewalk *rw)
+static void sprintroute(struct route *r, struct routewalk *rw)
 {
        int nifc, n;
        char t[5], *iname, ifbuf[5];
@@ -675,15 +701,15 @@ sprintroute(struct route *r, struct routewalk *rw)
 
        convroute(r, addr, mask, gate, t, &nifc);
        iname = "-";
-       if(nifc != -1) {
+       if (nifc != -1) {
                iname = ifbuf;
                snprintf(ifbuf, sizeof ifbuf, "%d", nifc);
        }
        p = seprintf(rw->p, rw->e, rformat, addr, mask, gate, t, r->rt.tag, iname);
-       if(rw->o < 0){
+       if (rw->o < 0) {
                n = p - rw->p;
-               if(n > -rw->o){
-                       memmove(rw->p, rw->p-rw->o, n+rw->o);
+               if (n > -rw->o) {
+                       memmove(rw->p, rw->p - rw->o, n + rw->o);
                        rw->p = p + rw->o;
                }
                rw->o += n;
@@ -694,57 +720,54 @@ sprintroute(struct route *r, struct routewalk *rw)
 /*
  *  recurse descending tree, applying the function in Routewalk
  */
-static int
-rr(struct route *r, struct routewalk *rw)
+static int rr(struct route *r, struct routewalk *rw)
 {
        int h;
 
-       if(rw->e <= rw->p)
+       if (rw->e <= rw->p)
                return 0;
-       if(r == NULL)
+       if (r == NULL)
                return 1;
 
-       if(rr(r->rt.left, rw) == 0)
+       if (rr(r->rt.left, rw) == 0)
                return 0;
 
-       if(r->rt.type & Rv4)
+       if (r->rt.type & Rv4)
                h = V4H(r->v4.address);
        else
                h = V6H(r->v6.address);
 
-       if(h == rw->h)
+       if (h == rw->h)
                rw->walk(r, rw);
 
-       if(rr(r->rt.mid, rw) == 0)
+       if (rr(r->rt.mid, rw) == 0)
                return 0;
 
        return rr(r->rt.right, rw);
 }
 
-void
-ipwalkroutes(struct Fs *f, struct routewalk *rw)
+void ipwalkroutes(struct Fs *f, struct routewalk *rw)
 {
        rlock(&routelock);
-       if(rw->e > rw->p) {
-               for(rw->h = 0; rw->h < ARRAY_SIZE(f->v4root); rw->h++)
-                       if(rr(f->v4root[rw->h], rw) == 0)
+       if (rw->e > rw->p) {
+               for (rw->h = 0; rw->h < ARRAY_SIZE(f->v4root); rw->h++)
+                       if (rr(f->v4root[rw->h], rw) == 0)
                                break;
        }
-       if(rw->e > rw->p) {
-               for(rw->h = 0; rw->h < ARRAY_SIZE(f->v6root); rw->h++)
-                       if(rr(f->v6root[rw->h], rw) == 0)
+       if (rw->e > rw->p) {
+               for (rw->h = 0; rw->h < ARRAY_SIZE(f->v6root); rw->h++)
+                       if (rr(f->v6root[rw->h], rw) == 0)
                                break;
        }
        runlock(&routelock);
 }
 
-long
-routeread(struct Fs *f, char *p, uint32_t offset, int n)
+long routeread(struct Fs *f, char *p, uint32_t offset, int n)
 {
        struct routewalk rw;
 
        rw.p = p;
-       rw.e = p+n;
+       rw.e = p + n;
        rw.o = -offset;
        rw.walk = sprintroute;
 
@@ -756,8 +779,7 @@ routeread(struct Fs *f, char *p, uint32_t offset, int n)
 /*
  *  this code is not in routeflush to reduce stack size
  */
-void
-delroute(struct Fs *f, struct route *r, int dolock)
+void delroute(struct Fs *f, struct route *r, int dolock)
 {
        uint8_t addr[IPaddrlen];
        uint8_t mask[IPaddrlen];
@@ -766,8 +788,8 @@ delroute(struct Fs *f, struct route *r, int dolock)
        int nifc;
 
        convroute(r, addr, mask, gate, t, &nifc);
-       if(r->rt.type & Rv4)
-               v4delroute(f, addr+IPv4off, mask+IPv4off, dolock);
+       if (r->rt.type & Rv4)
+               v4delroute(f, addr + IPv4off, mask + IPv4off, dolock);
        else
                v6delroute(f, addr, mask, dolock);
 }
@@ -776,19 +798,18 @@ delroute(struct Fs *f, struct route *r, int dolock)
  *  recurse until one route is deleted
  *    returns 0 if nothing is deleted, 1 otherwise
  */
-int
-routeflush(struct Fs *f, struct route *r, char *tag)
+int routeflush(struct Fs *f, struct route *r, char *tag)
 {
-       if(r == NULL)
+       if (r == NULL)
                return 0;
-       if(routeflush(f, r->rt.mid, tag))
+       if (routeflush(f, r->rt.mid, tag))
                return 1;
-       if(routeflush(f, r->rt.left, tag))
+       if (routeflush(f, r->rt.left, tag))
                return 1;
-       if(routeflush(f, r->rt.right, tag))
+       if (routeflush(f, r->rt.right, tag))
                return 1;
-       if((r->rt.type & Rifc) == 0){
-               if(tag == NULL || strncmp(tag, r->rt.tag, sizeof(r->rt.tag)) == 0){
+       if ((r->rt.type & Rifc) == 0) {
+               if (tag == NULL || strncmp(tag, r->rt.tag, sizeof(r->rt.tag)) == 0) {
                        delroute(f, r, 0);
                        return 1;
                }
@@ -796,8 +817,7 @@ routeflush(struct Fs *f, struct route *r, char *tag)
        return 0;
 }
 
-long
-routewrite(struct Fs *f, struct chan *c, char *p, int n)
+long routewrite(struct Fs *f, struct chan *c, char *p, int n)
 {
        ERRSTACK(1);
        int h, changed;
@@ -809,52 +829,55 @@ routewrite(struct Fs *f, struct chan *c, char *p, int n)
        struct IPaux *a, *na;
 
        cb = parsecmd(p, n);
-       if(waserror()){
+       if (waserror()) {
                kfree(cb);
                nexterror();
        }
+       if (cb->nf < 1)
+               error(EINVAL, "short control request");
 
-       if(strcmp(cb->f[0], "flush") == 0){
+       if (strcmp(cb->f[0], "flush") == 0) {
                tag = cb->f[1];
-               for(h = 0; h < ARRAY_SIZE(f->v4root); h++)
-                       for(changed = 1; changed;){
+               for (h = 0; h < ARRAY_SIZE(f->v4root); h++)
+                       for (changed = 1; changed;) {
                                wlock(&routelock);
                                changed = routeflush(f, f->v4root[h], tag);
                                wunlock(&routelock);
                        }
-               for(h = 0; h < ARRAY_SIZE(f->v6root); h++)
-                       for(changed = 1; changed;){
+               for (h = 0; h < ARRAY_SIZE(f->v6root); h++)
+                       for (changed = 1; changed;) {
                                wlock(&routelock);
                                changed = routeflush(f, f->v6root[h], tag);
                                wunlock(&routelock);
                        }
-       } else if(strcmp(cb->f[0], "remove") == 0){
-               if(cb->nf < 3)
-                       error(Ebadarg);
+       } else if (strcmp(cb->f[0], "remove") == 0) {
+               if (cb->nf < 3)
+                       error(EINVAL, ERROR_FIXME);
                parseip(addr, cb->f[1]);
                parseipmask(mask, cb->f[2]);
-               if(memcmp(addr, v4prefix, IPv4off) == 0)
-                       v4delroute(f, addr+IPv4off, mask+IPv4off, 1);
+               if (memcmp(addr, v4prefix, IPv4off) == 0)
+                       v4delroute(f, addr + IPv4off, mask + IPv4off, 1);
                else
                        v6delroute(f, addr, mask, 1);
-       } else if(strcmp(cb->f[0], "add") == 0){
-               if(cb->nf < 4)
-                       error(Ebadarg);
+       } else if (strcmp(cb->f[0], "add") == 0) {
+               if (cb->nf < 4)
+                       error(EINVAL, ERROR_FIXME);
                parseip(addr, cb->f[1]);
                parseipmask(mask, cb->f[2]);
                parseip(gate, cb->f[3]);
                tag = "none";
-               if(c != NULL){
+               if (c != NULL) {
                        a = c->aux;
                        tag = a->tag;
                }
-               if(memcmp(addr, v4prefix, IPv4off) == 0)
-                       v4addroute(f, tag, addr+IPv4off, mask+IPv4off, gate+IPv4off, 0);
+               if (memcmp(addr, v4prefix, IPv4off) == 0)
+                       v4addroute(f, tag, addr + IPv4off, mask + IPv4off, gate + IPv4off,
+                                          0);
                else
                        v6addroute(f, tag, addr, mask, gate, 0);
-       } else if(strcmp(cb->f[0], "tag") == 0) {
-               if(cb->nf < 2)
-                       error(Ebadarg);
+       } else if (strcmp(cb->f[0], "tag") == 0) {
+               if (cb->nf < 2)
+                       error(EINVAL, ERROR_FIXME);
 
                a = c->aux;
                na = newipaux(a->owner, cb->f[1]);