Have #ip protocol's announce()s throw errors
[akaros.git] / kern / src / net / tcp.c
index fedcd60..b4882e2 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>
@@ -436,16 +463,10 @@ void tcpsetstate(struct conv *s, uint8_t newstate)
                Fsconnected(s, NULL);
 }
 
-static char *tcpconnect(struct conv *c, char **argv, int argc)
+static void tcpconnect(struct conv *c, char **argv, int argc)
 {
-       char *e;
-
-       e = Fsstdconnect(c, argv, argc);
-       if (e != NULL)
-               return e;
+       Fsstdconnect(c, argv, argc);
        tcpstart(c, TCP_CONNECT);
-
-       return NULL;
 }
 
 static int tcpstate(struct conv *c, char *state, int n)
@@ -455,7 +476,7 @@ static int tcpstate(struct conv *c, char *state, int n)
        s = (Tcpctl *) (c->ptcl);
 
        return snprintf(state, n,
-                                       "%s qin %d qout %d srtt %d mdev %d cwin %lu swin %lu>>%d rwin %lu>>%d timer.start %llu timer.count %llu rerecv %d katimer.start %d katimer.count %d\n",
+                                       "%s qin %d qout %d srtt %d mdev %d cwin %u swin %u>>%d rwin %u>>%d timer.start %llu timer.count %llu rerecv %d katimer.start %d katimer.count %d\n",
                                        tcpstates[s->state],
                                        c->rq ? qlen(c->rq) : 0,
                                        c->wq ? qlen(c->wq) : 0,
@@ -473,17 +494,11 @@ static int tcpinuse(struct conv *c)
        return s->state != Closed;
 }
 
-static char *tcpannounce(struct conv *c, char **argv, int argc)
+static void tcpannounce(struct conv *c, char **argv, int argc)
 {
-       char *e;
-
-       e = Fsstdannounce(c, argv, argc);
-       if (e != NULL)
-               return e;
+       Fsstdannounce(c, argv, argc);
        tcpstart(c, TCP_LISTEN);
        Fsconnected(c, NULL);
-
-       return NULL;
 }
 
 /*
@@ -537,11 +552,11 @@ void tcpkick(void *x)
 
        tcb = (Tcpctl *) s->ptcl;
 
+       qlock(&s->qlock);
        if (waserror()) {
                qunlock(&s->qlock);
                nexterror();
        }
-       qlock(&s->qlock);
 
        switch (tcb->state) {
                case Syn_sent:
@@ -586,11 +601,11 @@ void tcpacktimer(void *v)
        s = v;
        tcb = (Tcpctl *) s->ptcl;
 
+       qlock(&s->qlock);
        if (waserror()) {
                qunlock(&s->qlock);
                nexterror();
        }
-       qlock(&s->qlock);
        if (tcb->state != Closed) {
                tcb->flags |= FORCE;
                tcprcvwin(s);
@@ -649,7 +664,7 @@ void tcpackproc(void *a)
        priv = tcp->priv;
 
        for (;;) {
-               udelay_sched(MSPTICK * 1000);
+               kthread_usleep(MSPTICK * 1000);
 
                qlock(&priv->tl);
                timeo = NULL;
@@ -1208,7 +1223,7 @@ int ntohtcp4(Tcp * tcph, struct block **bpp)
  */
 void tcpsndsyn(struct conv *s, Tcpctl * tcb)
 {
-       tcb->iss = (nrand(1 << 16) << 16) | nrand(1 << 16);
+       urandom_read(&tcb->iss, sizeof(tcb->iss));
        tcb->rttseq = tcb->iss;
        tcb->snd.wl2 = tcb->iss;
        tcb->snd.una = tcb->iss;
@@ -1233,7 +1248,7 @@ sndrst(struct Proto *tcp, uint8_t * source, uint8_t * dest,
        Tcp4hdr ph4;
        Tcp6hdr ph6;
 
-       netlog(tcp->f, Logtcp, "sndrst: %s", reason);
+       netlog(tcp->f, Logtcp, "sndrst: %s\n", reason);
 
        tpriv = tcp->priv;
 
@@ -1310,18 +1325,14 @@ sndrst(struct Proto *tcp, uint8_t * source, uint8_t * dest,
  *  send a reset to the remote side and close the conversation
  *  called with s qlocked
  */
-char *tcphangup(struct conv *s)
+static void tcphangup(struct conv *s)
 {
-       ERRSTACK(2);
+       ERRSTACK(1);
        Tcp seg;
        Tcpctl *tcb;
        struct block *hbp;
 
        tcb = (Tcpctl *) s->ptcl;
-       if (waserror()) {
-               poperror();
-               return commonerror();
-       }
        if (ipcmp(s->raddr, IPnoaddr)) {
                /* discard error style, poperror regardless */
                if (!waserror()) {
@@ -1351,8 +1362,6 @@ char *tcphangup(struct conv *s)
                poperror();
        }
        localclose(s, NULL);
-       poperror();
-       return NULL;
 }
 
 /*
@@ -1481,7 +1490,7 @@ limbo(struct conv *s, uint8_t * source, uint8_t * dest, Tcp * seg, int version)
                lp->mss = seg->mss;
                lp->rcvscale = seg->ws;
                lp->irs = seg->seq;
-               lp->iss = (nrand(1 << 16) << 16) | nrand(1 << 16);
+               urandom_read(&lp->iss, sizeof(lp->iss));
        }
 
        if (sndsynack(s->p, lp) < 0) {
@@ -1604,7 +1613,7 @@ static struct conv *tcpincoming(struct conv *s, Tcp * segp, uint8_t * src,
        h = hashipa(src, segp->source);
        for (l = &tpriv->lht[h]; (lp = *l) != NULL; l = &lp->next) {
                netlog(s->p->f, Logtcp,
-                          "tcpincoming s %I,0x%x/%I,0x%x d %I,0x%x/%I,0x%x v %d/%d", src,
+                          "tcpincoming s %I!%d/%I!%d d %I!%d/%I!%d v %d/%d\n", src,
                           segp->source, lp->raddr, lp->rport, dst, segp->dest, lp->laddr,
                           lp->lport, version, lp->version);
 
@@ -1618,7 +1627,7 @@ static struct conv *tcpincoming(struct conv *s, Tcp * segp, uint8_t * src,
 
                /* we're assuming no data with the initial SYN */
                if (segp->seq != lp->irs + 1 || segp->ack != lp->iss + 1) {
-                       netlog(s->p->f, Logtcp, "tcpincoming s 0x%lx/0x%lx a 0x%lx 0x%lx",
+                       netlog(s->p->f, Logtcp, "tcpincoming s 0x%lx/0x%lx a 0x%lx 0x%lx\n",
                                   segp->seq, lp->irs + 1, segp->ack, lp->iss + 1);
                        lp = NULL;
                } else {
@@ -2014,7 +2023,7 @@ void tcpiput(struct Proto *tcp, struct Ipifc *unused, struct block *bp)
        /* Look for a matching conversation */
        s = iphtlook(&tpriv->ht, source, seg.source, dest, seg.dest);
        if (s == NULL) {
-               netlog(f, Logtcp, "iphtlook failed");
+               netlog(f, Logtcp, "iphtlook failed\n");
 reset:
                qunlock(&tcp->qlock);
                sndrst(tcp, source, dest, length, &seg, version, "no conversation");
@@ -2082,7 +2091,7 @@ reset:
                        }
                        if (seg.flags & RST) {
                                if (seg.flags & ACK)
-                                       localclose(s, Econrefused);
+                                       localclose(s, errno_to_string(ECONNREFUSED));
                                goto raise;
                        }
 
@@ -2187,7 +2196,7 @@ reset:
                                                 s->raddr, s->rport, s->laddr, s->lport, tcb->rcv.nxt,
                                                 seg.seq);
                        }
-                       localclose(s, Econrefused);
+                       localclose(s, errno_to_string(ECONNREFUSED));
                        goto raise;
                }
 
@@ -2653,7 +2662,7 @@ void tcpsendka(struct conv *s)
        seg.mss = 0;
        seg.ws = 0;
        if (tcpporthogdefense)
-               seg.seq = tcb->snd.una - (1 << 30) - nrand(1 << 20);
+               urandom_read(&seg.seq, sizeof(seg.seq));
        else
                seg.seq = tcb->snd.una - 1;
        seg.ack = tcb->rcv.nxt;
@@ -2709,14 +2718,14 @@ void tcpkeepalive(void *v)
 
        s = v;
        tcb = (Tcpctl *) s->ptcl;
+       qlock(&s->qlock);
        if (waserror()) {
                qunlock(&s->qlock);
                nexterror();
        }
-       qlock(&s->qlock);
        if (tcb->state != Closed) {
                if (--(tcb->kacounter) <= 0) {
-                       localclose(s, Etimedout);
+                       localclose(s, errno_to_string(ETIMEDOUT));
                } else {
                        tcpsendka(s);
                        tcpgo(s->p->priv, &tcb->katimer);
@@ -2729,14 +2738,14 @@ void tcpkeepalive(void *v)
 /*
  *  start keepalive timer
  */
-char *tcpstartka(struct conv *s, char **f, int n)
+static void tcpstartka(struct conv *s, char **f, int n)
 {
        Tcpctl *tcb;
        int x;
 
        tcb = (Tcpctl *) s->ptcl;
        if (tcb->state != Established)
-               return "connection must be in Establised state";
+               error(ENOTCONN, "connection must be in Establised state");
        if (n > 1) {
                x = atoi(f[1]);
                if (x >= MSPTICK)
@@ -2744,21 +2753,17 @@ char *tcpstartka(struct conv *s, char **f, int n)
        }
        tcpsetkacounter(tcb);
        tcpgo(s->p->priv, &tcb->katimer);
-
-       return NULL;
 }
 
 /*
  *  turn checksums on/off
  */
-char *tcpsetchecksum(struct conv *s, char **f, int unused)
+static void tcpsetchecksum(struct conv *s, char **f, int unused)
 {
        Tcpctl *tcb;
 
        tcb = (Tcpctl *) s->ptcl;
        tcb->nochecksum = !atoi(f[1]);
-
-       return NULL;
 }
 
 void tcprxmit(struct conv *s)
@@ -2795,11 +2800,11 @@ void tcptimeout(void *arg)
        tpriv = s->p->priv;
        tcb = (Tcpctl *) s->ptcl;
 
+       qlock(&s->qlock);
        if (waserror()) {
                qunlock(&s->qlock);
                nexterror();
        }
-       qlock(&s->qlock);
        switch (tcb->state) {
                default:
                        tcb->backoff++;
@@ -2809,7 +2814,7 @@ void tcptimeout(void *arg)
                                maxback = MAXBACKMS;
                        tcb->backedoff += tcb->timer.start * MSPTICK;
                        if (tcb->backedoff >= maxback) {
-                               localclose(s, Etimedout);
+                               localclose(s, errno_to_string(ETIMEDOUT));
                                break;
                        }
                        netlog(s->p->f, Logtcprxmt, "timeout rexmit 0x%lx %llu/%llu\n",
@@ -3059,29 +3064,29 @@ void tcpadvise(struct Proto *tcp, struct block *bp, char *msg)
        freeblist(bp);
 }
 
-static char *tcpporthogdefensectl(char *val)
+static void tcpporthogdefensectl(char *val)
 {
        if (strcmp(val, "on") == 0)
                tcpporthogdefense = 1;
        else if (strcmp(val, "off") == 0)
                tcpporthogdefense = 0;
        else
-               return "unknown value for tcpporthogdefense";
-       return NULL;
+               error(EINVAL, "unknown value for tcpporthogdefense");
 }
 
 /* called with c qlocked */
-char *tcpctl(struct conv *c, char **f, int n)
+static void tcpctl(struct conv *c, char **f, int n)
 {
        if (n == 1 && strcmp(f[0], "hangup") == 0)
-               return tcphangup(c);
-       if (n >= 1 && strcmp(f[0], "keepalive") == 0)
-               return tcpstartka(c, f, n);
-       if (n >= 1 && strcmp(f[0], "checksum") == 0)
-               return tcpsetchecksum(c, f, n);
-       if (n >= 1 && strcmp(f[0], "tcpporthogdefense") == 0)
-               return tcpporthogdefensectl(f[1]);
-       return "unknown control request";
+               tcphangup(c);
+       else if (n >= 1 && strcmp(f[0], "keepalive") == 0)
+               tcpstartka(c, f, n);
+       else if (n >= 1 && strcmp(f[0], "checksum") == 0)
+               tcpsetchecksum(c, f, n);
+       else if (n >= 1 && strcmp(f[0], "tcpporthogdefense") == 0)
+               tcpporthogdefensectl(f[1]);
+       else
+               error(EINVAL, "unknown command to %s", __func__);
 }
 
 int tcpstats(struct Proto *tcp, char *buf, int len)