net: Don't clobber the TTL for TCPv4 rx
[akaros.git] / kern / src / net / netif.c
index ac753bd..4f348a4 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>
@@ -26,8 +53,7 @@ static int parseaddr(uint8_t * unused_uint8_p_t, char *unused_char_p_t, int);
 void netifinit(struct ether *nif, char *name, int nfile, uint32_t limit)
 {
        qlock_init(&nif->qlock);
-       strncpy(nif->name, name, KNAMELEN - 1);
-       nif->name[KNAMELEN - 1] = 0;
+       strlcpy(nif->name, name, KNAMELEN);
        nif->nfile = nfile;
        nif->f = kzmalloc(nfile * sizeof(struct netfile *), 0);
        if (nif->f)
@@ -59,13 +85,13 @@ netifgen(struct chan *c, char *unused_char_p_t, struct dirtab *vp,
                        case DEVDOTDOT:
                                q.path = 0;
                                q.type = QTDIR;
-                               devdir(c, q, ".", 0, eve, 0555, dp);
+                               devdir(c, q, ".", 0, eve.name, 0555, dp);
                                break;
                        case 0:
                                q.path = N2ndqid;
                                q.type = QTDIR;
-                               strncpy(get_cur_genbuf(), nif->name, GENBUF_SZ);
-                               devdir(c, q, get_cur_genbuf(), 0, eve, 0555, dp);
+                               strlcpy(get_cur_genbuf(), nif->name, GENBUF_SZ);
+                               devdir(c, q, get_cur_genbuf(), 0, eve.name, 0555, dp);
                                break;
                        default:
                                return -1;
@@ -113,23 +139,23 @@ netifgen(struct chan *c, char *unused_char_p_t, struct dirtab *vp,
                        case DEVDOTDOT:
                                q.type = QTDIR;
                                q.path = 0;
-                               devdir(c, q, ".", 0, eve, DMDIR | 0555, dp);
+                               devdir(c, q, ".", 0, eve.name, DMDIR | 0555, dp);
                                break;
                        case 0:
                                q.path = Ncloneqid;
-                               devdir(c, q, "clone", 0, eve, 0666, dp);
+                               devdir(c, q, "clone", 0, eve.name, 0666, dp);
                                break;
                        case 1:
                                q.path = Naddrqid;
-                               devdir(c, q, "addr", 0, eve, 0666, dp);
+                               devdir(c, q, "addr", 0, eve.name, 0666, dp);
                                break;
                        case 2:
                                q.path = Nstatqid;
-                               devdir(c, q, "stats", 0, eve, 0444, dp);
+                               devdir(c, q, "stats", 0, eve.name, 0444, dp);
                                break;
                        case 3:
                                q.path = Nifstatqid;
-                               devdir(c, q, "ifstats", 0, eve, 0444, dp);
+                               devdir(c, q, "ifstats", 0, eve.name, 0444, dp);
                                break;
                        default:
                                i -= 4;
@@ -140,7 +166,7 @@ netifgen(struct chan *c, char *unused_char_p_t, struct dirtab *vp,
                                q.type = QTDIR;
                                q.path = NETQID(i, N3rdqid);
                                snprintf(get_cur_genbuf(), GENBUF_SZ, "%d", i);
-                               devdir(c, q, get_cur_genbuf(), 0, eve, DMDIR | 0555, dp);
+                               devdir(c, q, get_cur_genbuf(), 0, eve.name, DMDIR | 0555, dp);
                                break;
                }
                return 1;
@@ -154,15 +180,15 @@ netifgen(struct chan *c, char *unused_char_p_t, struct dirtab *vp,
                o = f->owner;
                perm = f->mode;
        } else {
-               o = eve;
+               o = eve.name;
                perm = 0666;
        }
        switch (i) {
                case DEVDOTDOT:
                        q.type = QTDIR;
                        q.path = N2ndqid;
-                       strncpy(get_cur_genbuf(), nif->name, GENBUF_SZ);
-                       devdir(c, q, get_cur_genbuf(), 0, eve, DMDIR | 0555, dp);
+                       strlcpy(get_cur_genbuf(), nif->name, GENBUF_SZ);
+                       devdir(c, q, get_cur_genbuf(), 0, eve.name, DMDIR | 0555, dp);
                        break;
                case 0:
                        q.path = NETQID(NETID(c->qid.path), Ndataqid);
@@ -174,15 +200,15 @@ netifgen(struct chan *c, char *unused_char_p_t, struct dirtab *vp,
                        break;
                case 2:
                        q.path = NETQID(NETID(c->qid.path), Nstatqid);
-                       devdir(c, q, "stats", 0, eve, 0444, dp);
+                       devdir(c, q, "stats", 0, eve.name, 0444, dp);
                        break;
                case 3:
                        q.path = NETQID(NETID(c->qid.path), Ntypeqid);
-                       devdir(c, q, "type", 0, eve, 0444, dp);
+                       devdir(c, q, "type", 0, eve.name, 0444, dp);
                        break;
                case 4:
                        q.path = NETQID(NETID(c->qid.path), Nifstatqid);
-                       devdir(c, q, "ifstats", 0, eve, 0444, dp);
+                       devdir(c, q, "ifstats", 0, eve.name, 0444, dp);
                        break;
                default:
                        return -1;
@@ -203,8 +229,8 @@ struct chan *netifopen(struct ether *nif, struct chan *c, int omode)
 
        id = 0;
        if (c->qid.type & QTDIR) {
-               if (!IS_RDONLY(omode))
-                       error(Eperm);
+               if (omode & O_WRITE)
+                       error(EPERM, ERROR_FIXME);
        } else {
                switch (NETTYPE(c->qid.path)) {
                        case Ndataqid:
@@ -217,15 +243,15 @@ struct chan *netifopen(struct ether *nif, struct chan *c, int omode)
                                c->qid.path = NETQID(id, Nctlqid);
                                break;
                        default:
-                               if (!IS_RDONLY(omode))
-                                       error(Ebadarg);
+                               if (omode & O_WRITE)
+                                       error(EINVAL, ERROR_FIXME);
                }
                switch (NETTYPE(c->qid.path)) {
                        case Ndataqid:
                        case Nctlqid:
                                f = nif->f[id];
-                               if (netown(f, current->user, omode & 7) < 0)
-                                       error(Eperm);
+                               if (netown(f, current->user.name, omode & 7) < 0)
+                                       error(EPERM, ERROR_FIXME);
                                break;
                }
        }
@@ -281,7 +307,7 @@ netifread(struct ether *nif, struct chan *c, void *a, long n,
                        if (nif->feat & NETF_UDPCK)
                                j += snprintf(p + j, READSTR - j, "udpck ");
                        if (nif->feat & NETF_TCPCK)
-                               j += snprintf(p + j, READSTR - j, "tcppck ");
+                               j += snprintf(p + j, READSTR - j, "tcpck ");
                        if (nif->feat & NETF_PADMIN)
                                j += snprintf(p + j, READSTR - j, "padmin ");
                        if (nif->feat & NETF_SG)
@@ -310,7 +336,7 @@ netifread(struct ether *nif, struct chan *c, void *a, long n,
                case Nifstatqid:
                        return 0;
        }
-       error(Ebadarg);
+       error(EINVAL, ERROR_FIXME);
        return -1;      /* not reached */
 }
 
@@ -356,24 +382,24 @@ long netifwrite(struct ether *nif, struct chan *c, void *a, long n)
        uint8_t binaddr[Nmaxaddr];
 
        if (NETTYPE(c->qid.path) != Nctlqid)
-               error(Eperm);
+               error(EPERM, ERROR_FIXME);
 
        if (n >= sizeof(buf))
                n = sizeof(buf) - 1;
        memmove(buf, a, n);
        buf[n] = 0;
 
+       qlock(&nif->qlock);
        if (waserror()) {
                qunlock(&nif->qlock);
                nexterror();
        }
 
-       qlock(&nif->qlock);
        f = nif->f[NETID(c->qid.path)];
        if ((p = matchtoken(buf, "connect")) != 0) {
                type = strtol(p, 0, 0); /* allows any base, though usually hex */
                if (typeinuse(nif, type))
-                       error(Einuse);
+                       error(EBUSY, ERROR_FIXME);
                f->type = type;
                if (f->type < 0)
                        nif->all++;
@@ -401,16 +427,20 @@ long netifwrite(struct ether *nif, struct chan *c, void *a, long n)
                f->headersonly = 1;
        } else if ((p = matchtoken(buf, "addmulti")) != 0) {
                if (parseaddr(binaddr, p, nif->alen) < 0)
-                       error("bad address");
+                       error(EFAIL, "bad address");
                p = netmulti(nif, f, binaddr, 1);
                if (p)
-                       error(p);
+                       error(EFAIL, p);
        } else if ((p = matchtoken(buf, "remmulti")) != 0) {
                if (parseaddr(binaddr, p, nif->alen) < 0)
-                       error("bad address");
+                       error(EFAIL, "bad address");
                p = netmulti(nif, f, binaddr, 0);
                if (p)
-                       error(p);
+                       error(EFAIL, p);
+       } else if (matchtoken(buf, "oneblock")) {
+               /* Qmsg + Qcoal = one block at a time. */
+               q_toggle_qmsg(f->in, TRUE);
+               q_toggle_qcoalesce(f->in, TRUE);
        } else
                n = -1;
        qunlock(&nif->qlock);
@@ -425,22 +455,20 @@ int netifwstat(struct ether *nif, struct chan *c, uint8_t * db, int n)
        int m;
 
        f = nif->f[NETID(c->qid.path)];
-       if (f == 0) {
-               set_errno(ENOENT);
-               error(Enonexist);
-       }
+       if (f == 0)
+               error(ENOENT, ERROR_FIXME);
 
-       if (netown(f, current->user, OWRITE) < 0)
-               error(Eperm);
+       if (netown(f, current->user.name, O_WRITE) < 0)
+               error(EPERM, ERROR_FIXME);
 
        dir = kzmalloc(sizeof(struct dir) + n, 0);
        m = convM2D(db, n, &dir[0], (char *)&dir[1]);
        if (m == 0) {
                kfree(dir);
-               error(Eshortstat);
+               error(ENODATA, ERROR_FIXME);
        }
        if (!emptystr(dir[0].uid))
-               strncpy(f->owner, dir[0].uid, KNAMELEN);
+               strlcpy(f->owner, dir[0].uid, KNAMELEN);
        if (dir[0].mode != ~0UL)
                f->mode = dir[0].mode;
        kfree(dir);
@@ -511,21 +539,20 @@ spinlock_t netlock = SPINLOCK_INITIALIZER;
 
 static int netown(struct netfile *p, char *o, int omode)
 {
-       static int access[] = { 0400, 0200, 0600, 0100 };
        int mode;
-       int t;
+       int rwx;
 
        spin_lock(&netlock);
        if (*p->owner) {
                if (strncmp(o, p->owner, KNAMELEN) == 0)        /* User */
                        mode = p->mode;
-               else if (strncmp(o, eve, KNAMELEN) == 0)        /* Bootes is group */
+               else if (strncmp(o, eve.name, KNAMELEN) == 0)   /* Bootes is group */
                        mode = p->mode << 3;
                else
                        mode = p->mode << 6;    /* Other */
 
-               t = access[omode & 3];
-               if ((t & mode) == t) {
+               rwx = omode_to_rwx(omode);
+               if ((rwx & mode) == rwx) {
                        spin_unlock(&netlock);
                        return 0;
                } else {
@@ -533,7 +560,7 @@ static int netown(struct netfile *p, char *o, int omode)
                        return -1;
                }
        }
-       strncpy(p->owner, o, KNAMELEN);
+       strlcpy(p->owner, o, KNAMELEN);
        p->mode = 0660;
        spin_unlock(&netlock);
        return 0;
@@ -551,7 +578,7 @@ static int openfile(struct ether *nif, int id)
        if (id >= 0) {
                f = nif->f[id];
                if (f == 0)
-                       error(Enodev);
+                       error(ENODEV, ERROR_FIXME);
                qlock(&f->qlock);
                qreopen(f->in);
                f->inuse++;
@@ -589,13 +616,13 @@ static int openfile(struct ether *nif, int id)
                }
                f->inuse = 1;
                qreopen(f->in);
-               netown(f, current->user, 0);
+               netown(f, current->user.name, 0);
                qunlock(&f->qlock);
                qunlock(&nif->qlock);
                poperror();
                return fp - nif->f;
        }
-       error(Enodev);
+       error(ENODEV, ERROR_FIXME);
        return -1;      /* not reached */
 }