From 0496e1c79e280ce9e43f686323684f1ad8324bdb Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 13 Sep 2000 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2000-09-13 --- ip/ethermedium.c | 16 +++---- ip/ip.c | 2 +- ip/ipifc.c | 2 +- port/devcons.c | 3 +- port/devloopback.c | 2 +- port/devssl.c | 108 +++++++++++++++++++++++++++++++++------------ port/qio.c | 4 +- 7 files changed, 95 insertions(+), 42 deletions(-) diff --git a/ip/ethermedium.c b/ip/ethermedium.c index e4eff7580a09cc17e258edc7b59171b0dff1721a..b15f6f06d2f1b375c24f112c3320e1958a089220 100644 --- a/ip/ethermedium.c +++ b/ip/ethermedium.c @@ -22,7 +22,7 @@ static void etherunbind(Ipifc *ifc); static void etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip); static void etheraddmulti(Ipifc *ifc, uchar *a, uchar *ia); static void etherremmulti(Ipifc *ifc, uchar *a, uchar *ia); -static Block* multicastarp(Fs *f, Arpent *a, uchar *mac); +static Block* multicastarp(Fs *f, Arpent *a, Medium*, uchar *mac); static void sendarp(Ipifc *ifc, Arpent *a); static void sendgarp(Ipifc *ifc, uchar*); static int multicastea(uchar *ea, uchar *ip); @@ -215,10 +215,10 @@ etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip) Etherrock *er = ifc->arg; /* get mac address of destination */ - a = arpget(er->f->arp, bp, version, ðermedium, ip, mac); + a = arpget(er->f->arp, bp, version, ifc->m, ip, mac); if(a){ /* check for broadcast or multicast */ - bp = multicastarp(er->f, a, mac); + bp = multicastarp(er->f, a, ifc->m, mac); if(bp == nil){ sendarp(ifc, a); return; @@ -384,8 +384,8 @@ sendgarp(Ipifc *ifc, uchar *ip) return; n = sizeof(Etherarp); - if(n < ethermedium.minmtu) - n = ethermedium.minmtu; + if(n < ifc->m->minmtu) + n = ifc->m->minmtu; bp = allocb(n); memset(bp->rp, 0, n); e = (Etherarp*)bp->rp; @@ -533,7 +533,7 @@ multicastea(uchar *ea, uchar *ip) * addresses */ static Block* -multicastarp(Fs *f, Arpent *a, uchar *mac) +multicastarp(Fs *f, Arpent *a, Medium *medium, uchar *mac) { /* is it broadcast? */ switch(ipforme(f, a->ip)){ @@ -541,7 +541,7 @@ multicastarp(Fs *f, Arpent *a, uchar *mac) return nil; case Rbcast: memset(mac, 0xff, 6); - return arpresolve(f->arp, a, ðermedium, mac); + return arpresolve(f->arp, a, medium, mac); default: break; } @@ -550,7 +550,7 @@ multicastarp(Fs *f, Arpent *a, uchar *mac) switch(multicastea(mac, a->ip)){ case V4: case V6: - return arpresolve(f->arp, a, ðermedium, mac); + return arpresolve(f->arp, a, medium, mac); } /* let arp take care of it */ diff --git a/ip/ip.c b/ip/ip.c index 2631f752a891e24fd7726a2a8f764ae71a01ff24..07d7c6f6aab3a5df62e9cabbd262a075d22266e9 100644 --- a/ip/ip.c +++ b/ip/ip.c @@ -218,7 +218,7 @@ ipoput(Fs *f, Block *bp, int gating, int ttl, int tos) goto raise; /* If we dont need to fragment just send it */ - medialen = ifc->m->maxmtu - ifc->m->hsize; + medialen = ifc->maxmtu - ifc->m->hsize; if(len <= medialen) { if(!gating) hnputs(eh->id, incref(&ip->id)); diff --git a/ip/ipifc.c b/ip/ipifc.c index 0607e4673c76e6679756fb4343bce9dcf8018419..85464b69eda08bc0b93e8a882720e2bf630364e9 100644 --- a/ip/ipifc.c +++ b/ip/ipifc.c @@ -662,7 +662,7 @@ ipifcinit(Fs *f) { Proto *ipifc; - ipifc = smalloc(sizeof(Ipifc)); + ipifc = smalloc(sizeof(Proto)); ipifc->name = "ipifc"; ipifc->kick = ipifckick; ipifc->connect = ipifcconnect; diff --git a/port/devcons.c b/port/devcons.c index 3bcfc28627106020fc2e6daf74d447cb4960848d..966b198900dde7fb9db53a6c2e09855162cf70e7 100644 --- a/port/devcons.c +++ b/port/devcons.c @@ -1013,8 +1013,7 @@ readtime(ulong off, char *buf, int n) { vlong nsec, ticks; long sec; - char str[7*NUMSIZE+4]; // extra 4 bytes are null plus doprint - // reserving space for a frigging UTF + char str[7*NUMSIZE]; // char nsec = todget(&ticks); diff --git a/port/devloopback.c b/port/devloopback.c index 2d5531f54acb97a92699e139e063ac0910b45c1c..a99f92ab4355389159996d30b44ad84fb4bbc42d 100644 --- a/port/devloopback.c +++ b/port/devloopback.c @@ -181,7 +181,7 @@ loopbackattach(char *spec) c->qid = (Qid){CHDIR|QID(0, Qtopdir), 0}; c->aux = lb; - c->dev = 0; + c->dev = dev; return c; } diff --git a/port/devssl.c b/port/devssl.c index 7db77acfb48fccfa7431c1522cbb58c2ee772f30..b86283c0b4b220ed18d6212977dca83d11b64d18 100644 --- a/port/devssl.c +++ b/port/devssl.c @@ -72,7 +72,7 @@ struct Dstate Lock dslock; int dshiwat; -int maxdstate = 20; +int maxdstate = 128; Dstate** dstate; char *encalgs; char *hashalgs; @@ -430,6 +430,29 @@ consume(Block **l, uchar *p, int n) } } +/* + * give back n bytes + */ +static void +regurgitate(Dstate *s, uchar *p, int n) +{ + Block *b; + + if(n <= 0) + return; + b = s->unprocessed; + if(s->unprocessed == nil || b->rp - b->base < n) { + b = allocb(n); + memmove(p, b->wp, n); + b->wp += n; + b->next = s->unprocessed; + s->unprocessed = b; + } else { + b->rp -= n; + memmove(p, b->rp, n); + } +} + /* * remove at most n bytes from the queue, if discard is set * dump the remainder @@ -478,12 +501,20 @@ qremove(Block **l, int n, int discard) return first; } +/* + * We can't let Eintr's lose data since the program + * doing the read may be able to handle it. The only + * places Eintr is possible is during the read's in consume. + * Therefore, we make sure we can always put back the bytes + * consumed before the last ensure. + */ static Block* sslbread(Chan *c, long n, ulong) { volatile struct { Dstate *s; } s; Block *b; - uchar count[2]; + uchar consumed[3]; + int nconsumed; int len, pad; s.s = dstate[CONV(c->qid)]; @@ -492,9 +523,11 @@ sslbread(Chan *c, long n, ulong) if(s.s->state == Sincomplete) error(Ebadusefd); + nconsumed = 0; if(waserror()){ + if(strcmp(up->error, Eintr) != 0 && nconsumed) + regurgitate(s.s, consumed, nconsumed); qunlock(&s.s->in.q); - sslhangup(s.s); nexterror(); } qlock(&s.s->in.q); @@ -502,58 +535,72 @@ sslbread(Chan *c, long n, ulong) if(s.s->processed == 0){ /* read in the whole message */ ensure(s.s, &s.s->unprocessed, 2); - consume(&s.s->unprocessed, count, 2); - if(count[0] & 0x80){ - len = ((count[0] & 0x7f)<<8) | count[1]; + consume(&s.s->unprocessed, consumed, 2); + nconsumed = 2; + if(consumed[0] & 0x80){ + len = ((consumed[0] & 0x7f)<<8) | consumed[1]; ensure(s.s, &s.s->unprocessed, len); pad = 0; } else { - len = ((count[0] & 0x3f)<<8) | count[1]; + len = ((consumed[0] & 0x3f)<<8) | consumed[1]; ensure(s.s, &s.s->unprocessed, len+1); - consume(&s.s->unprocessed, count, 1); - pad = count[0]; + consume(&s.s->unprocessed, &consumed[2], 1); + pad = consumed[2]; if(pad > len){ print("pad %d buf len %d\n", pad, len); error("bad pad in ssl message"); } } + USED(nconsumed); + nconsumed = 0; + + /* if an Eintr happens after this, we screwed. Make + * sure nothing we call can sleep. Luckily, allocb + * won't sleep, it'll just error out. + */ - /* put extra on unprocessed queue */ - s.s->processed = qremove(&s.s->unprocessed, len, 0); + /* grab the next message and decode/decrypt it */ + b = qremove(&s.s->unprocessed, len, 0); if(waserror()){ qunlock(&s.s->in.ctlq); + if(b != nil) + freeb(b); nexterror(); } qlock(&s.s->in.ctlq); switch(s.s->state){ case Sencrypting: - s.s->processed = decryptb(s.s, s.s->processed); + b = decryptb(s.s, b); break; case Sdigesting: - s.s->processed = pullupblock(s.s->processed, s.s->diglen); - if(s.s->processed == 0) + b = pullupblock(b, s.s->diglen); + if(b == nil) error("ssl message too short"); - checkdigestb(s.s, s.s->processed); - s.s->processed->rp += s.s->diglen; + checkdigestb(s.s, b); + b->rp += s.s->diglen; break; case Sdigenc: - s.s->processed = decryptb(s.s, s.s->processed); - s.s->processed = pullupblock(s.s->processed, s.s->diglen); - if(s.s->processed == 0) + b = decryptb(s.s, b); + b = pullupblock(b, s.s->diglen); + if(b == nil) error("ssl message too short"); - checkdigestb(s.s, s.s->processed); - s.s->processed->rp += s.s->diglen; + checkdigestb(s.s, b); + b->rp += s.s->diglen; len -= s.s->diglen; break; } - s.s->in.mid++; - qunlock(&s.s->in.ctlq); - poperror(); /* remove pad */ if(pad) - s.s->processed = qremove(&s.s->processed, len - pad, 1); + s.s->processed = qremove(&b, len - pad, 1); + else + s.s->processed = b; + b = nil; + s.s->in.mid++; + qunlock(&s.s->in.ctlq); + poperror(); + USED(nconsumed); } /* return at most what was asked for */ @@ -626,7 +673,10 @@ randfill(uchar *buf, int len) } /* - * use SSL record format, add in count and digest or encrypt + * use SSL record format, add in count, digest and/or encrypt. + * the write is interruptable. if it is interrupted, we'll + * get out of sync with the far side. not much we can do about + * it since we don't know if any bytes have been written. */ static long sslbwrite(Chan *c, Block *b, ulong offset) @@ -646,11 +696,13 @@ sslbwrite(Chan *c, Block *b, ulong offset) error(Ebadusefd); } + nb = nil; if(waserror()){ qunlock(&s.s->out.q); - if(bb.b) + if(bb.b != nil) freeb(bb.b); - sslhangup(s.s); + if(nb != nil) + freeb(nb); nexterror(); } qlock(&s.s->out.q); diff --git a/port/qio.c b/port/qio.c index 57ee03317340da94c0f9f599952bd55e4fbda6f5..c2139341eff6c9a0f8ae570221ed444ee4385d96 100644 --- a/port/qio.c +++ b/port/qio.c @@ -896,6 +896,8 @@ qbwrite(Queue *q, Block *b) n = BLEN(b); qlock(&q->wlock); if(waserror()){ + if(b != nil) + freeb(b); qunlock(&q->wlock); nexterror(); } @@ -906,7 +908,6 @@ qbwrite(Queue *q, Block *b) if(q->state & Qclosed){ iunlock(q); - freeb(b); error(q->err); } @@ -935,6 +936,7 @@ qbwrite(Queue *q, Block *b) q->len += BALLOC(b); q->dlen += n; QDEBUG checkb(b, "qbwrite"); + b = nil; if(q->state & Qstarve){ q->state &= ~Qstarve;