M ip/ethermedium.c => ip/ethermedium.c +8 -8
@@ 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 */
M ip/ip.c => ip/ip.c +1 -1
@@ 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));
M ip/ipifc.c => ip/ipifc.c +1 -1
@@ 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;
M port/devcons.c => port/devcons.c +1 -2
@@ 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);
M port/devloopback.c => port/devloopback.c +1 -1
@@ 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;
}
M port/devssl.c => port/devssl.c +80 -28
@@ 72,7 72,7 @@ struct Dstate
Lock dslock;
int dshiwat;
-int maxdstate = 20;
+int maxdstate = 128;
Dstate** dstate;
char *encalgs;
char *hashalgs;
@@ 431,6 431,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);
M port/qio.c => port/qio.c +3 -1
@@ 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;