kconfig: use pkg-config for ncurses detection
[akaros.git] / kern / src / net / ip.c
index c8f644a..afb47f9 100644 (file)
@@ -1,6 +1,31 @@
-// INFERNO
-#include <vfs.h>
-#include <kfs.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 <slab.h>
 #include <kmalloc.h>
 #include <kref.h>
 #include <cpio.h>
 #include <pmap.h>
 #include <smp.h>
-#include <ip.h>
+#include <net/ip.h>
 
-typedef struct Ip4hdr Ip4hdr;
 typedef struct IP IP;
 typedef struct Fragment4 Fragment4;
 typedef struct Fragment6 Fragment6;
 typedef struct Ipfrag Ipfrag;
 
 enum {
-       IP4HDR = 20,                            /* sizeof(Ip4hdr) */
-       IP6HDR = 40,    /* sizeof(Ip6hdr) */
+       IP4HDR = 20,            /* sizeof(Ip4hdr) */
+       IP6HDR = 40,            /* sizeof(Ip6hdr) */
        IP_HLEN4 = 0x05,        /* Header length in words */
-       IP_DF = 0x4000, /* Don't fragment */
-       IP_MF = 0x2000, /* More fragments */
-       IP6FHDR = 8,    /* sizeof(Fraghdr6) */
+       IP_DF = 0x4000,         /* Don't fragment */
+       IP_MF = 0x2000,         /* More fragments */
+       IP6FHDR = 8,            /* sizeof(Fraghdr6) */
        IP_MAX = 64 * 1024,     /* Maximum Internet packet size */
 };
 
 #define BLKIPVER(xp)   (((struct Ip4hdr*)((xp)->rp))->vihl&0xF0)
 #define NEXT_ID(x) (__sync_add_and_fetch(&(x), 1))
 
-struct Ip4hdr {
-       uint8_t vihl;                           /* Version and header length */
-       uint8_t tos;                            /* Type of service */
-       uint8_t length[2];                      /* packet length */
-       uint8_t id[2];                          /* ip->identification */
-       uint8_t frag[2];                        /* Fragment information */
-       uint8_t ttl;                            /* Time to live */
-       uint8_t proto;                          /* Protocol */
-       uint8_t cksum[2];                       /* Header checksum */
-       uint8_t src[4];                         /* IP source */
-       uint8_t dst[4];                         /* IP destination */
-};
-
 /* MIB II counters */
 enum {
        Forwarding,
@@ -76,7 +87,7 @@ struct fragment4 {
        uint32_t src;
        uint32_t dst;
        uint16_t id;
-       uint32_t age;
+       uint64_t age;
 };
 
 struct fragment6 {
@@ -85,7 +96,7 @@ struct fragment6 {
        uint8_t src[IPaddrlen];
        uint8_t dst[IPaddrlen];
        unsigned int id;
-       uint32_t age;
+       uint64_t age;
 };
 
 struct Ipfrag {
@@ -107,7 +118,7 @@ struct IP {
        struct fragment6 *fragfree6;
        int id6;
 
-       int iprouting;                          /* true if we route like a gateway */
+       int iprouting;          /* true if we route like a gateway */
 };
 
 static char *statnames[] = {
@@ -140,8 +151,8 @@ static char *statnames[] = {
 #define BKFG(xp)       ((struct Ipfrag*)((xp)->base))
 
 uint16_t ipcsum(uint8_t * unused_uint8_p_t);
-struct block *ip4reassemble(struct IP *, int unused_int,
-                                                       struct block *, struct Ip4hdr *);
+struct block *ip4reassemble(struct IP *, int unused_int, struct block *,
+                           struct Ip4hdr *);
 void ipfragfree4(struct IP *, struct fragment4 *);
 struct fragment4 *ipfragallo4(struct IP *);
 
@@ -175,7 +186,7 @@ void initfrag(struct IP *ip, int size)
        struct fragment6 *fq6, *eq6;
 
        ip->fragfree4 =
-               (struct fragment4 *)kzmalloc(sizeof(struct fragment4) * size, 0);
+           (struct fragment4 *)kzmalloc(sizeof(struct fragment4) * size, 0);
        if (ip->fragfree4 == NULL)
                panic("initfrag");
 
@@ -186,7 +197,7 @@ void initfrag(struct IP *ip, int size)
        ip->fragfree4[size - 1].next = NULL;
 
        ip->fragfree6 =
-               (struct fragment6 *)kzmalloc(sizeof(struct fragment6) * size, 0);
+           (struct fragment6 *)kzmalloc(sizeof(struct fragment6) * size, 0);
        if (ip->fragfree6 == NULL)
                panic("initfrag");
 
@@ -219,9 +230,8 @@ void iprouting(struct Fs *f, int on)
                f->ip->stats[Forwarding] = 1;
 }
 
-int
-ipoput4(struct Fs *f,
-               struct block *bp, int gating, int ttl, int tos, struct conv *c)
+int ipoput4(struct Fs *f, struct block *bp, int gating, int ttl, int tos, struct
+           conv *c)
 {
        ERRSTACK(1);
        struct Ipifc *ifc;
@@ -236,6 +246,9 @@ ipoput4(struct Fs *f,
 
        ip = f->ip;
 
+       /* Sanity check for our transport protocols. */
+       if (bp->mss)
+               assert(bp->flag & Btso);
        /* Fill out the ip header */
        eh = (struct Ip4hdr *)(bp->rp);
 
@@ -296,12 +309,12 @@ ipoput4(struct Fs *f,
 
        /* If we dont need to fragment just send it */
        medialen = ifc->maxtu - ifc->m->hsize;
-       if (len <= medialen) {
+       if (bp->flag & Btso || len <= medialen) {
                if (!gating)
                        hnputs(eh->id, NEXT_ID(ip->id4));
                hnputs(eh->length, len);
                if (!gating) {
-                       eh->frag[0] = 0;
+                       eh->frag[0] = 0x40;
                        eh->frag[1] = 0;
                }
                eh->cksum[0] = 0;
@@ -342,6 +355,8 @@ ipoput4(struct Fs *f,
        else
                lid = NEXT_ID(ip->id4);
 
+       /* advance through the blist enough to drop IP4HDR size.  this should
+        * usually just be the first block. */
        offset = IP4HDR;
        while (xp != NULL && offset && offset >= BLEN(xp)) {
                offset -= BLEN(xp);
@@ -355,7 +370,7 @@ ipoput4(struct Fs *f,
                fragoff = 0;
        dlen += fragoff;
        for (; fragoff < dlen; fragoff += seglen) {
-               nb = allocb(IP4HDR + seglen);
+               nb = blist_clone(xp, IP4HDR, seglen, fragoff);
                feh = (struct Ip4hdr *)(nb->rp);
 
                memmove(nb->wp, eh, IP4HDR);
@@ -370,27 +385,6 @@ ipoput4(struct Fs *f,
                hnputs(feh->length, seglen + IP4HDR);
                hnputs(feh->id, lid);
 
-               /* Copy up the data area */
-               chunk = seglen;
-               while (chunk) {
-                       if (!xp) {
-                               ip->stats[OutDiscards]++;
-                               ip->stats[FragFails]++;
-                               freeblist(nb);
-                               netlog(f, Logip, "!xp: chunk %d\n", chunk);
-                               goto raise;
-                       }
-                       blklen = chunk;
-                       if (BLEN(xp) < chunk)
-                               blklen = BLEN(xp);
-                       memmove(nb->wp, xp->rp, blklen);
-                       nb->wp += blklen;
-                       xp->rp += blklen;
-                       chunk -= blklen;
-                       if (xp->rp == xp->wp)
-                               xp = xp->next;
-               }
-
                feh->cksum[0] = 0;
                feh->cksum[1] = 0;
                hnputs(feh->cksum, ipcsum(&feh->vihl));
@@ -418,6 +412,7 @@ void ipiput4(struct Fs *f, struct Ipifc *ifc, struct block *bp)
        struct IP *ip;
        struct route *r;
 
+       bp = pullupblock(bp, 1);
        if (BLKIPVER(bp) != IP_VER4) {
                ipiput6(f, ifc, bp);
                return;
@@ -459,7 +454,8 @@ void ipiput4(struct Fs *f, struct Ipifc *ifc, struct block *bp)
                hl = (h->vihl & 0xF) << 2;
                if (hl < (IP_HLEN4 << 2)) {
                        ip->stats[InHdrErrors]++;
-                       netlog(f, Logip, "ip: %V bad hivl 0x%x\n", h->src, h->vihl);
+                       netlog(f, Logip, "ip: %V bad hivl 0x%x\n", h->src,
+                              h->vihl);
                        freeblist(bp);
                        return;
                }
@@ -596,7 +592,7 @@ struct block *ip4reassemble(struct IP *ip, int offset, struct block *bp,
         *  find a reassembly queue for this fragment
         */
        for (f = ip->flisthead4; f; f = fnext) {
-               fnext = f->next;        /* because ipfragfree4 changes the list */
+               fnext = f->next;/* because ipfragfree4 changes the list */
                if (f->src == src && f->dst == dst && f->id == id)
                        break;
                if (f->age < NOW) {