Fix permission checks for devether
[akaros.git] / kern / src / net / icmp6.c
index e85f6b0..a6b6d72 100644 (file)
@@ -1,16 +1,36 @@
-// INFERNO
-#include <vfs.h>
-#include <kfs.h>
-#include <slab.h>
+/* 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 <kmalloc.h>
-#include <kref.h>
 #include <string.h>
 #include <stdio.h>
-#include <assert.h>
+#include <syscall.h>
 #include <error.h>
-#include <cpio.h>
-#include <pmap.h>
-#include <smp.h>
 #include <ip.h>
 
 struct ICMPpkt {
@@ -25,10 +45,6 @@ struct ICMPpkt {
  * We have been naming the struct
  * members and just using the extra level of deref
  * e.g. i->x becomes i->i6->x.
- * I'm going to use insert the structs into
- * this because it's just a lot easier, and
- * maybe someday gcc will grow up and me more
- * like Plan 9 C.
  */
 struct IPICMP {
 /*
@@ -183,7 +199,6 @@ typedef struct Icmppriv6 {
 } Icmppriv6;
 
 typedef struct Icmpcb6 {
-       qlock_t qlock;
        uint8_t headers;
 } Icmpcb6;
 
@@ -238,7 +253,7 @@ static void set_cksum(struct block *bp)
 static struct block *newIPICMP(int packetlen)
 {
        struct block *nbp;
-       nbp = allocb(packetlen);
+       nbp = block_alloc(packetlen, MEM_WAIT);
        nbp->wp += packetlen;
        memset(nbp->rp, 0, packetlen);
        return nbp;
@@ -316,19 +331,14 @@ static void icmpkick6(void *x, struct block *bp)
        ipoput6(c->p->f, bp, 0, c->ttl, c->tos, NULL);
 }
 
-char *icmpctl6(struct conv *c, char **argv, int argc)
+static void icmpctl6(struct conv *c, char **argv, int argc)
 {
-       Icmpcb6 *icb;
-
-       icb = (Icmpcb6 *) c->ptcl;
+       Icmpcb6 *icb = (Icmpcb6*)c->ptcl;
 
-       if (argc == 1) {
-               if (strcmp(argv[0], "headers") == 0) {
-                       icb->headers = 6;
-                       return NULL;
-               }
-       }
-       return "unknown control request";
+       if ((argc == 1) && strcmp(argv[0], "headers") == 0)
+               icb->headers = 6;
+       else
+               error(EINVAL, "unknown command to icmpctl6");
 }
 
 static void goticmpkt6(struct Proto *icmp, struct block *bp, int muxkey)
@@ -374,14 +384,15 @@ static struct block *mkechoreply6(struct block *bp)
 
 /*
  * sends out an ICMPv6 neighbor solicitation
- *     suni == SRC_UNSPEC or SRC_UNI, 
+ *     suni == SRC_UNSPEC or SRC_UNI,
  *     tuni == TARG_MULTI => multicast for address resolution,
  *     and tuni == TARG_UNI => neighbor reachability.
  */
 
-extern void
-icmpns(struct Fs *f, uint8_t * src, int suni, uint8_t * targ, int tuni,
-          uint8_t * mac)
+void icmpns(struct Fs *f,
+            uint8_t *src, int suni,
+            uint8_t *targ, int tuni,
+            uint8_t *mac)
 {
        struct block *nbp;
        struct Ndpkt *np;
@@ -425,9 +436,8 @@ icmpns(struct Fs *f, uint8_t * src, int suni, uint8_t * targ, int tuni,
 /*
  * sends out an ICMPv6 neighbor advertisement. pktflags == RSO flags.
  */
-extern void
-icmpna(struct Fs *f, uint8_t * src, uint8_t * dst, uint8_t * targ,
-          uint8_t * mac, uint8_t flags)
+void icmpna(struct Fs *f, uint8_t * src, uint8_t * dst, uint8_t * targ,
+            uint8_t * mac, uint8_t flags)
 {
        struct block *nbp;
        struct Ndpkt *np;
@@ -458,9 +468,8 @@ icmpna(struct Fs *f, uint8_t * src, uint8_t * dst, uint8_t * targ,
        ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, NULL);
 }
 
-extern void
-icmphostunr(struct Fs *f, struct Ipifc *ifc,
-                       struct block *bp, int code, int free)
+void icmphostunr(struct Fs *f, struct Ipifc *ifc,
+                 struct block *bp, int code, int free)
 {
        struct block *nbp;
        struct IPICMP *np;
@@ -473,7 +482,7 @@ icmphostunr(struct Fs *f, struct Ipifc *ifc,
        p = (struct ip6hdr *)bp->rp;
 
        if (isv6mcast(p->src))
-               goto clean;
+               goto freebl;
 
        nbp = newIPICMP(sz);
        np = (struct IPICMP *)nbp->rp;
@@ -483,11 +492,9 @@ icmphostunr(struct Fs *f, struct Ipifc *ifc,
                netlog(f, Logicmp, "send icmphostunr -> s%I d%I\n", p->src, p->dst);
        } else {
                netlog(f, Logicmp, "icmphostunr fail -> s%I d%I\n", p->src, p->dst);
+               runlock(&ifc->rwlock);
                freeblist(nbp);
-               if (free)
-                       goto clean;
-               else
-                       return;
+               goto freebl;
        }
 
        memmove(np->dst, p->src, IPaddrlen);
@@ -502,17 +509,15 @@ icmphostunr(struct Fs *f, struct Ipifc *ifc,
 
        if (free)
                ipiput6(f, ifc, nbp);
-       else {
+       else
                ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, NULL);
-               return;
-       }
-
-clean:
        runlock(&ifc->rwlock);
-       freeblist(bp);
+freebl:
+       if (free)
+               freeblist(bp);
 }
 
-extern void icmpttlexceeded6(struct Fs *f, struct Ipifc *ifc, struct block *bp)
+void icmpttlexceeded6(struct Fs *f, struct Ipifc *ifc, struct block *bp)
 {
        struct block *nbp;
        struct IPICMP *np;
@@ -532,10 +537,10 @@ extern void icmpttlexceeded6(struct Fs *f, struct Ipifc *ifc, struct block *bp)
 
        if (ipv6anylocal(ifc, np->src)) {
                netlog(f, Logicmp, "send icmpttlexceeded6 -> s%I d%I\n", p->src,
-                          p->dst);
+                      p->dst);
        } else {
                netlog(f, Logicmp, "icmpttlexceeded6 fail -> s%I d%I\n", p->src,
-                          p->dst);
+                      p->dst);
                return;
        }
 
@@ -543,7 +548,7 @@ extern void icmpttlexceeded6(struct Fs *f, struct Ipifc *ifc, struct block *bp)
        np->type = TimeExceedV6;
        np->code = 0;
        memmove(nbp->rp + sizeof(struct IPICMP), bp->rp,
-                       sz - sizeof(struct IPICMP));
+               sz - sizeof(struct IPICMP));
        set_cksum(nbp);
        np->ttl = HOP_LIMIT;
        np->vcf[0] = 0x06 << 4;
@@ -551,7 +556,7 @@ extern void icmpttlexceeded6(struct Fs *f, struct Ipifc *ifc, struct block *bp)
        ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, NULL);
 }
 
-extern void icmppkttoobig6(struct Fs *f, struct Ipifc *ifc, struct block *bp)
+void icmppkttoobig6(struct Fs *f, struct Ipifc *ifc, struct block *bp)
 {
        struct block *nbp;
        struct IPICMP *np;
@@ -569,12 +574,11 @@ extern void icmppkttoobig6(struct Fs *f, struct Ipifc *ifc, struct block *bp)
        nbp = newIPICMP(sz);
        np = (struct IPICMP *)nbp->rp;
 
-       if (ipv6anylocal(ifc, np->src)) {
-               netlog(f, Logicmp, "send icmppkttoobig6 -> s%I d%I\n", p->src, p->dst);
-       } else {
+       if (!ipv6anylocal(ifc, np->src)) {
                netlog(f, Logicmp, "icmppkttoobig6 fail -> s%I d%I\n", p->src, p->dst);
                return;
        }
+       netlog(f, Logicmp, "send icmppkttoobig6 -> s%I d%I\n", p->src, p->dst);
 
        memmove(np->dst, p->src, IPaddrlen);
        np->type = PacketTooBigV6;
@@ -592,9 +596,8 @@ extern void icmppkttoobig6(struct Fs *f, struct Ipifc *ifc, struct block *bp)
 /*
  * RFC 2461, pages 39-40, pages 57-58.
  */
-static int
-valid(struct Proto *icmp, struct Ipifc *ifc,
-         struct block *bp, Icmppriv6 * ipriv)
+static int valid(struct Proto *icmp, struct Ipifc *ifc,
+                 struct block *bp, Icmppriv6 * ipriv)
 {
        int sz, osz, unsp, n, ttl, iplen;
        int pktsz = BLEN(bp);
@@ -828,7 +831,7 @@ static void icmpiput6(struct Proto *icmp, struct Ipifc *ipifc, struct block *bp)
 
                case RouterAdvert:
                case RouterSolicit:
-                       /* using lsrc as a temp, munge hdr for goticmp6 
+                       /* using lsrc as a temp, munge hdr for goticmp6
                           memmove(lsrc, p->src, IPaddrlen);
                           memmove(p->src, p->dst, IPaddrlen);
                           memmove(p->dst, lsrc, IPaddrlen); */
@@ -872,10 +875,10 @@ static void icmpiput6(struct Proto *icmp, struct Ipifc *ipifc, struct block *bp)
                case NbrAdvert:
                        np = (struct Ndpkt *)p;
 
-                       /* if the target address matches one of the local interface 
-                        * address and the local interface address has tentative bit set, 
-                        * then insert into ARP table. this is so the duplication address 
-                        * detection part of ipconfig can discover duplication through 
+                       /* if the target address matches one of the local interface
+                        * address and the local interface address has tentative bit set,
+                        * then insert into ARP table. this is so the duplication address
+                        * detection part of ipconfig can discover duplication through
                         * the arp table
                         */
                        lifc = iplocalonifc(ipifc, np->target);
@@ -914,27 +917,18 @@ int icmpstats6(struct Proto *icmp6, char *buf, int len)
                if (icmpnames6[i])
                        p = seprintf(p, e, "%s: %u %u\n", icmpnames6[i], priv->in[i],
                                                 priv->out[i]);
-/*             else
+               else
                        p = seprintf(p, e, "%d: %u %u\n", i, priv->in[i], priv->out[i]);
-*/
        }
        return p - buf;
 }
 
 // need to import from icmp.c
 extern int icmpstate(struct conv *c, char *state, int n);
-extern char *icmpannounce(struct conv *c, char **argv, int argc);
-extern char *icmpconnect(struct conv *c, char **argv, int argc);
+extern void icmpannounce(struct conv *c, char **argv, int argc);
+extern void icmpconnect(struct conv *c, char **argv, int argc);
 extern void icmpclose(struct conv *c);
 
-void icmp6newconv(struct Proto *icmp6, struct conv *conv)
-{
-       /* Fsprotoclone alloc'd our priv struct and attached it to conv already.
-        * Now we need to init it */
-       struct Icmpcb6 *icb = (struct Icmpcb6 *)conv->ptcl;
-       qlock_init(&icb->qlock);
-}
-
 void icmp6init(struct Fs *fs)
 {
        struct Proto *icmp6 = kzmalloc(sizeof(struct Proto), 0);
@@ -950,7 +944,6 @@ void icmp6init(struct Fs *fs)
        icmp6->stats = icmpstats6;
        icmp6->ctl = icmpctl6;
        icmp6->advise = icmpadvise6;
-       icmp6->newconv = icmp6newconv;
        icmp6->gc = NULL;
        icmp6->ipproto = ICMPv6;
        icmp6->nc = 16;