qio: Track the amount of bytes read
[akaros.git] / kern / src / net / icmp.c
index 1ec1f28..c4b0d53 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>
@@ -127,16 +154,10 @@ static void icmpcreate(struct conv *c)
        c->wq = qbypass(icmpkick, c);
 }
 
-extern char *icmpconnect(struct conv *c, char **argv, int argc)
+void icmpconnect(struct conv *c, char **argv, int argc)
 {
-       char *e;
-
-       e = Fsstdconnect(c, argv, argc);
-       if (e != NULL)
-               return e;
-       Fsconnected(c, e);
-
-       return NULL;
+       Fsstdconnect(c, argv, argc);
+       Fsconnected(c, 0);
 }
 
 extern int icmpstate(struct conv *c, char *state, int n)
@@ -146,16 +167,10 @@ extern int icmpstate(struct conv *c, char *state, int n)
                                        c->rq ? qlen(c->rq) : 0, c->wq ? qlen(c->wq) : 0);
 }
 
-extern char *icmpannounce(struct conv *c, char **argv, int argc)
+void icmpannounce(struct conv *c, char **argv, int argc)
 {
-       char *e;
-
-       e = Fsstdannounce(c, argv, argc);
-       if (e != NULL)
-               return e;
+       Fsstdannounce(c, argv, argc);
        Fsconnected(c, NULL);
-
-       return NULL;
 }
 
 extern void icmpclose(struct conv *c)
@@ -192,6 +207,10 @@ static void icmpkick(void *x, struct block *bp)
        memset(p->cksum, 0, sizeof(p->cksum));
        hnputs(p->cksum, ptclcsum(bp, ICMP_IPSIZE, blocklen(bp) - ICMP_IPSIZE));
        ipriv->stats[OutMsgs]++;
+       netlog(c->p->f, Logicmp,
+              "icmp output: Type %s (%d,%d), To %V, TTL %d, ID %d, SEQ %d\n",
+              icmpnames[MIN(p->type, Maxtype)],
+              p->type, p->code, p->dst, p->ttl, nhgets(p->icmpid), nhgets(p->seq));
        ipoput4(c->p->f, bp, 0, c->ttl, c->tos, NULL);
 }
 
@@ -203,7 +222,7 @@ extern void icmpttlexceeded(struct Fs *f, uint8_t * ia, struct block *bp)
        p = (Icmp *) bp->rp;
 
        netlog(f, Logicmp, "sending icmpttlexceeded -> %V\n", p->src);
-       nbp = allocb(ICMP_IPSIZE + ICMP_HDRSIZE + ICMP_IPSIZE + 8);
+       nbp = block_alloc(ICMP_IPSIZE + ICMP_HDRSIZE + ICMP_IPSIZE + 8, MEM_WAIT);
        nbp->wp += ICMP_IPSIZE + ICMP_HDRSIZE + ICMP_IPSIZE + 8;
        np = (Icmp *) nbp->rp;
        np->vihl = IP_VER4;
@@ -240,8 +259,11 @@ static void icmpunreachable(struct Fs *f, struct block *bp, int code, int seq)
        if (i != 0 && (i & Runi) == 0)
                return;
 
+       /* TODO: Clean this up or remove it.  This is for things like UDP port
+        * unreachable.  But we might not be UDP, due to how the code is built.
+        * Check the UDP netlog if you see this. */
        netlog(f, Logicmp, "sending icmpnoconv -> %V\n", p->src);
-       nbp = allocb(ICMP_IPSIZE + ICMP_HDRSIZE + ICMP_IPSIZE + 8);
+       nbp = block_alloc(ICMP_IPSIZE + ICMP_HDRSIZE + ICMP_IPSIZE + 8, MEM_WAIT);
        nbp->wp += ICMP_IPSIZE + ICMP_HDRSIZE + ICMP_IPSIZE + 8;
        np = (Icmp *) nbp->rp;
        np->vihl = IP_VER4;
@@ -292,7 +314,7 @@ static void goticmpkt(struct Proto *icmp, struct block *bp)
        freeblist(bp);
 }
 
-static struct block *mkechoreply(struct block *bp)
+static struct block *mkechoreply(struct Proto *icmp, struct block *bp)
 {
        Icmp *q;
        uint8_t ip[4];
@@ -308,7 +330,9 @@ static struct block *mkechoreply(struct block *bp)
        q->type = EchoReply;
        memset(q->cksum, 0, sizeof(q->cksum));
        hnputs(q->cksum, ptclcsum(bp, ICMP_IPSIZE, blocklen(bp) - ICMP_IPSIZE));
-
+       netlog(icmp->f, Logicmp,
+              "icmp echo reply: To %V, TTL %d, ID %d, SEQ %d\n",
+              q->dst, q->ttl, nhgets(q->icmpid), nhgets(q->seq));
        return bp;
 }
 
@@ -340,9 +364,15 @@ static void icmpiput(struct Proto *icmp, struct Ipifc *unused, struct block *bp)
        ipriv->stats[InMsgs]++;
 
        p = (Icmp *) bp->rp;
-       netlog(icmp->f, Logicmp, "icmpiput %d %d\n", p->type, p->code);
+       /* The ID and SEQ are only for Echo Request and Reply, but close enough. */
+       netlog(icmp->f, Logicmp,
+              "icmp input: Type %s (%d,%d), From %V, TTL %d, ID %d, SEQ %d\n",
+              icmpnames[MIN(p->type, Maxtype)],
+              p->type, p->code, p->src, p->ttl, nhgets(p->icmpid), nhgets(p->seq));
        n = blocklen(bp);
        if (n < ICMP_IPSIZE + ICMP_HDRSIZE) {
+               /* pullupblock should fail if dlen < size.  b->len >= b->dlen. */
+               panic("We did a pullupblock and thought we had enough!");
                ipriv->stats[InErrors]++;
                ipriv->stats[HlenErrs]++;
                netlog(icmp->f, Logicmp, "icmp hlen %d\n", n);
@@ -368,7 +398,7 @@ static void icmpiput(struct Proto *icmp, struct Ipifc *unused, struct block *bp)
                case EchoRequest:
                        if (iplen < n)
                                bp = trimblock(bp, 0, iplen);
-                       r = mkechoreply(bp);
+                       r = mkechoreply(icmp, bp);
                        ipriv->out[EchoReply]++;
                        ipoput4(icmp->f, r, 0, MAXTTL, DFLTTOS, NULL);
                        break;