## diffname port/devsdp.c 1999/0824 ## diff -e /dev/null /n/emeliedump/1999/0824/sys/src/brazil/port/devsdp.c 0a #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/netif.h" #include "../port/error.h" #include typedef struct Sdp Sdp; typedef struct Port Port; enum { Qtopdir= 1, /* top level directory */ Qsdpdir, /* sdp directory */ Qclone, Qstats, Qlog, Qportdir, /* directory for a protocol */ Qctl, Qdata, /* reliable control channel */ Qpacket, /* unreliable packet channel */ Qerr, Qlisten, Qlocal, Qremote, Qstatus, MaxQ, Maxport= 256, // power of 2 Nfs= 4, // number of file systems }; #define TYPE(x) ((x).path & 0xff) #define PORT(x) (((x).path >> 8)&(Maxport-1)) #define QID(x, y) (((x)<<8) | (y)) struct Port { int id; Sdp *sdp; int ref; int closed; }; struct Sdp { QLock; Log; int nport; Port *port[Maxport]; }; static Dirtab sdpdirtab[]={ "ctl", {Qctl}, 0, 0666, "stats", {Qstats}, 0, 0444, "log", {Qlog}, 0, 0666, }; static Dirtab portdirtab[]={ "ctl", {Qctl}, 0, 0666, "data", {Qdata}, 0, 0666, "packet", {Qpacket}, 0, 0666, "listen", {Qlisten}, 0, 0666, "local", {Qlocal}, 0, 0444, "remote", {Qlocal}, 0, 0444, "status", {Qstatus}, 0, 0444, }; static int m2p[] = { [OREAD] 4, [OWRITE] 2, [ORDWR] 6 }; enum { Logcompress= (1<<0), Logauth= (1<<1), Loghmac= (1<<2), }; static Logflag logflags[] = { { "compress", Logcompress, }, { "auth", Logauth, }, { "hmac", Loghmac, }, { nil, 0, }, }; static Dirtab *dirtab[MaxQ]; static Sdp sdptab[Nfs]; static int sdpgen(Chan *c, Dirtab*, int, int s, Dir *dp); static void sdpinit(void) { int i; Dirtab *dt; // setup dirtab with non directory entries for(i=0; iqid)] = dt; } for(i=0; iqid)] = dt; } } static Chan* sdpattach(char* spec) { Chan *c; int dev; dev = atoi(spec); if(dev<0 || dev >= Nfs) error("bad specification"); c = devattach('B', spec); c->qid = (Qid){QID(0, Qtopdir)|CHDIR, 0}; c->dev = dev; return c; } static int sdpwalk(Chan *c, char *name) { if(strcmp(name, "..") == 0){ switch(TYPE(c->qid)){ case Qtopdir: case Qsdpdir: c->qid = (Qid){CHDIR|Qtopdir, 0}; break; case Qportdir: c->qid = (Qid){CHDIR|Qsdpdir, 0}; break; default: panic("sdpwalk %lux", c->qid.path); } return 1; } return devwalk(c, name, 0, 0, sdpgen); } static void sdpstat(Chan* c, char* db) { devstat(c, db, nil, 0, sdpgen); } static Chan* sdpopen(Chan* c, int omode) { int perm; Sdp *sdp; omode &= 3; perm = m2p[omode]; USED(perm); sdp = sdptab + c->dev; switch(TYPE(c->qid)) { default: break; case Qtopdir: case Qsdpdir: case Qportdir: case Qstatus: case Qlocal: case Qstats: if(omode != OREAD) error(Eperm); break; case Qlog: logopen(sdp); break; } c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; } static void sdpclose(Chan* c) { Sdp *sdp = sdptab + c->dev; switch(TYPE(c->qid)) { case Qlog: if(c->flag & COPEN) logclose(sdp); break; } } static long sdpread(Chan *c, void *a, long n, vlong off) { char buf[256]; Sdp *sdp = sdptab + c->dev; Port *port; USED(off); switch(TYPE(c->qid)) { default: error(Eperm); case Qtopdir: case Qsdpdir: case Qportdir: return devdirread(c, a, n, 0, 0, sdpgen); case Qlog: return logread(sdp, a, off, n); case Qstatus: qlock(sdp); port = sdp->port[PORT(c->qid)]; if(port == 0) strcpy(buf, "unbound\n"); else { } n = readstr(off, a, n, buf); qunlock(sdp); return n; } } static long sdpwrite(Chan *c, void *a, long n, vlong off) { Sdp *sdp = sdptab + c->dev; Cmdbuf *cb; char *arg0; char *p; USED(off); switch(TYPE(c->qid)) { default: error(Eperm); case Qctl: cb = parsecmd(a, n); qlock(sdp); if(waserror()) { qunlock(sdp); free(cb); nexterror(); } if(cb->nf == 0) error("short write"); arg0 = cb->f[0]; if(strcmp(arg0, "xxx") == 0) { print("xxx\n"); } else error("unknown control request"); poperror(); qunlock(sdp); free(cb); return n; case Qlog: cb = parsecmd(a, n); p = logctl(sdp, cb->nf, cb->f, logflags); free(cb); if(p != nil) error(p); return n; } } static int sdpgen(Chan *c, Dirtab*, int, int s, Dir *dp) { Sdp *sdp = sdptab + c->dev; int type = TYPE(c->qid); char buf[32]; Dirtab *dt; Qid qid; switch(type) { default: // non directory entries end up here if(c->qid.path & CHDIR) panic("sdpgen: unexpected directory"); if(s != 0) return -1; dt = dirtab[TYPE(c->qid)]; if(dt == nil) panic("sdpgen: unknown type: %d", TYPE(c->qid)); devdir(c, c->qid, dt->name, dt->length, eve, dt->perm, dp); return 1; case Qtopdir: if(s != 0) return -1; devdir(c, (Qid){QID(0,Qsdpdir)|CHDIR,0}, "sdp", 0, eve, 0555, dp); return 1; case Qsdpdir: if(sqid, dt->name, dt->length, eve, dt->perm, dp); return 1; } s -= nelem(sdpdirtab); if(s >= sdp->nport) return -1; qid = (Qid){QID(s,Qportdir)|CHDIR, 0}; snprint(buf, sizeof(buf), "%d", s); devdir(c, qid, buf, 0, eve, 0555, dp); return 1; case Qportdir: if(s>=nelem(portdirtab)) return -1; dt = portdirtab+s; qid = (Qid){QID(PORT(c->qid),TYPE(dt->qid)),0}; devdir(c, qid, dt->name, dt->length, eve, dt->perm, dp); return 1; } } Dev sdpdevtab = { 'T', "sdp", devreset, sdpinit, sdpattach, devclone, sdpwalk, sdpstat, sdpopen, devcreate, sdpclose, sdpread, devbread, sdpwrite, devbwrite, devremove, devwstat, }; . ## diffname port/devsdp.c 1999/0901 ## diff -e /n/emeliedump/1999/0824/sys/src/brazil/port/devsdp.c /n/emeliedump/1999/0901/sys/src/brazil/port/devsdp.c 325a } static Conv* sdpclone(Sdp *sdp) { Conv *c, **pp, **ep; c = nil; ep = sdp->conv + nelem(sdp->conv); for(pp = sdp->conv; pp < ep; pp++) { c = *pp; if(c == nil){ c = malloc(sizeof(Conv)); if(c == nil) error(Enomem); qlock(c); c->sdp = sdp; c->id = pp - sdp->conv; *pp = c; sdp->nconv++; break; } if(canqlock(c)){ if(c->inuse == 0) break; qunlock(c); } } if(pp >= ep) { return nil; } c->inuse = 1; strncpy(c->user, up->user, sizeof(c->user)); c->perm = 0660; c->state = 0; qunlock(c); return c; . 321,322c dt = convdirtab+s; qid = (Qid){QID(CONV(c->qid),TYPE(dt->qid)),0}; . 318,319c case Qconvdir: if(s>=nelem(convdirtab)) . 314c qid = (Qid){QID(s,Qconvdir)|CHDIR, 0}; . 312c if(s >= sdp->nconv) . 260a print("cmd = %s\n", arg0); . 247c switch(TYPE(ch->qid)) { . 241c Sdp *sdp = sdptab + ch->dev; . 239c sdpwrite(Chan *ch, void *a, long n, vlong off) . 235d 233a case Qctl: sprint(buf, "%lud", CONV(ch->qid)); return readstr(off, a, n, buf); . 226,227c c = sdp->conv[CONV(ch->qid)]; if(c == 0) . 220,221c case Qconvdir: return devdirread(ch, a, n, 0, 0, sdpgen); . 215c switch(TYPE(ch->qid)) { . 211,212c Sdp *sdp = sdptab + ch->dev; Conv *c; . 208c sdpread(Chan *ch, void *a, long n, vlong off) . 188,191c ch->mode = openmode(omode); ch->flag |= COPEN; ch->offset = 0; return ch; . 186a case Qclone: c = sdpclone(sdp); if(c == nil) error(Enodev); ch->qid.path = QID(c->id, Qctl); break; . 179d 177c case Qconvdir: . 172c switch(TYPE(ch->qid)) { . 170c sdp = sdptab + ch->dev; . 164a Conv *c; . 161c sdpopen(Chan* ch, int omode) . 142c case Qconvdir: . 126c c = devattach('T', spec); . 110,111c for(i=0; i> 8)&(Maxconv-1)) . 35c Maxconv= 256, // power of 2 . 27,30d 23c Qconvdir, /* directory per conversation */ . 12c typedef struct Conv Conv; typedef struct OneWay OneWay; . ## diffname port/devsdp.c 1999/0902 ## diff -e /n/emeliedump/1999/0901/sys/src/brazil/port/devsdp.c /n/emeliedump/1999/0902/sys/src/brazil/port/devsdp.c 400a static void sdpconvfree(Conv *c) { qlock(c); c->ref--; if(c->ref < 0) panic("convfree: bad ref"); if(c->ref > 0) { qunlock(c); return; } memset(&c->in, 0, sizeof(c->in)); memset(&c->out, 0, sizeof(c->out)); if(c->chan) { cclose(c->chan); c->chan = 0; } qunlock(c); } . 397a . 395,396d 392c c->ref++; c->state = COpening; . 390d 388c if(pp >= ep) . 386a poperror(); qunlock(sdp); . 383d 381c if(c->state == CClosed) . 366a qlock(sdp); if(waserror()) { qunlock(sdp); nexterror(); } . 260,261c n = readstr(off, a, n, s); qunlock(c); . 256,258c qlock(c); switch(c->state) { default: panic("unknown state"); case CClosed: s = "closed"; break; case COpening: s = "opening"; break; case COpen: s = "open"; break; case CClosing: s = "closing"; break; . 254d 240a char *s; . 230c if(ch->flag & COPEN) . 228c switch(TYPE(ch->qid)) { . 226c Sdp *sdp = sdptab + ch->dev; . 224c sdpclose(Chan* ch) . 215a case Qdata: case Qctl: case Qstatus: case Qcontrol: c = sdp->conv[CONV(ch->qid)]; qlock(c); if(waserror()) { qunlock(c); nexterror(); } if((perm & (c->perm>>6)) != perm) if(strcmp(up->user, c->user) != 0 || (perm & c->perm) != perm) error(Eperm); c->ref++; qunlock(c); poperror(); break; . 202d 91c "control", {Qcontrol}, 0, 0666, . 79c Conv *conv[Maxconv]; . 71,72c In in; Out out; . 67,69d 64a Chan *chan; // packet channel . 63c int state; ulong session; . 60a int ref; . 59d 56a struct In { ulong seqwrap; // number of wraps of the sequence number ulong seq; ulong window; Block *controlpkt; ulong controlseq; void *cipherstate; // state cipher int ivlen; // in bytes int (*decrypt)(In*, uchar *buf, int len); void *authstate; // auth state int authlen; // auth data length in bytes int (*auth)(In*, uchar *buf, int len); void *uncompstate; int (*uncomp)(In*, uchar *dst, uchar *src, int n); }; enum { CClosed, COpening, COpen, CClosing, }; . 51,54c void *cipherstate; // state cipher int ivlen; // in bytes int (*encrypt)(Out*, uchar *buf, int len); void *authstate; // auth state int authlen; // auth data length in bytes int (*auth)(Out*, uchar *buf, int len); void *compstate; int (*comp)(Out*, uchar *dst, uchar *src, int n); . 46,49c Block *controlpkt; // control channel ulong *controlseq; ulong controltimeout; // timeout when it will be resent int controlretries; . 44d 40c struct Out . 26,27c Qdata, /* unreliable packet channel */ Qcontrol, /* reliable control channel */ . 11,13c typedef struct Sdp Sdp; typedef struct Conv Conv; typedef struct Out Out; typedef struct In In; . ## diffname port/devsdp.c 1999/0906 ## diff -e /n/emeliedump/1999/0902/sys/src/brazil/port/devsdp.c /n/emeliedump/1999/0906/sys/src/brazil/port/devsdp.c 511a // assume hold lock on c static void convsetstate(Conv *c, int state) { switch(state) { default: panic("setstate: bad state: %d", state); case COpening: if(c->state != CInit) error("convsetstate: illegal transition"); c->dialid = (rand()<<16) + rand(); c->timeout = TK2SEC(m->ticks) + 2; c->retries = 0; sendconnect(c, ConOpen, c->dialid, 0); break; case COpen: switch(c->state) { default: error("convsetstate: illegal transition"); case CInit: c->acceptid = (rand()<<16) + rand(); sendconnect(c, ConOpenAck, c->dialid, c->acceptid); break; case COpening: break; } // setup initial key and auth method break; case CClosing: c->timeout = TK2SEC(m->ticks) + 2; c->retries = 0; break; case CClosed: break; } c->state = state; } static void sendconnect(Conv *c, int op, ulong dialid, ulong acceptid) { ConPkt con; if(c->chan == nil) { print("chan = nil\n"); error("no channel attached"); } memset(&con, 0, sizeof(con)); con.type = TConnect; con.op = op; hnputl(con.dialid, dialid); hnputl(con.acceptid, acceptid); // simulated errors if(c->drop && c->drop > nrand(c->drop)) return; devtab[c->chan->type]->write(c->chan, &con, sizeof(con), 0); } . 489d 485,487c static void sdpackproc(void *a) { Sdp *sdp = a; ulong sec; int i; Conv *c; for(;;) { tsleep(&sdp->vous, return0, 0, 1000); sec = TK2SEC(m->ticks); qlock(sdp); for(i=0; inconv; i++) { c = sdp->conv[i]; if(!waserror()) { convtimer(c, sec); poperror(); } } qunlock(sdp); . 482,483d 480a switch(c->state) { case COpening: print("COpening timeout\n"); if(convretry(c)) sendconnect(c, ConOpen, c->dialid, 0); break; case COpen: // check for control packet break; case CClosing: print("CClosing timeout\n"); if(convretry(c)) sendconnect(c, ConClose, c->dialid, c->acceptid); break; } qunlock(c); } . 479c nexterror(); . 474,477c if(waserror()) { . 472a if(c->timeout == 0 || c->timeout > sec) return; . 471c convtimer(Conv *c, ulong sec) . 469a // assume c is locked static int convretry(Conv *c) { c->retries++; if(c->retries > Maxretries) { print("convretry: giving up\n"); convsetstate(c, CClosed); return 0; } c->timeout = TK2SEC(m->ticks) + (1<retries); return 1; } . 461c c->state = CInit; . 361c qunlock(c); . 356,357c if(strcmp(arg0, "chan") == 0) { if(cb->nf != 2) error("usage: chan file"); if(c->chan != nil) error("chan already set"); c->chan = namec(cb->f[1], Aopen, ORDWR, 0); } else if(strcmp(arg0, "accept") == 0) { if(cb->nf != 2) error("usage: accect id"); c->dialid = atoi(cb->f[1]); convsetstate(c, COpen); } else if(strcmp(arg0, "dial") == 0) { if(cb->nf != 1) error("usage: dial"); convsetstate(c, COpening); } else if(strcmp(arg0, "drop") == 0) { if(cb->nf != 2) error("usage: drop permil"); c->drop = atoi(cb->f[1]); . 348c qunlock(c); . 346c qlock(c); . 344a c = sdp->conv[CONV(ch->qid)]; print("Qctl write : conv->id = %d\n", c->id); . 338a Conv *c; . 186a sdp = sdptab + dev; qlock(sdp); start = sdp->ackproc == 0; sdp->ackproc = 1; qunlock(sdp); if(start) { snprint(buf, sizeof(buf), "sdpackproc%d", dev); kproc(buf, sdpackproc, sdp); } . 177a char buf[100]; Sdp *sdp; int start; . 170a . 153a static void convsetstate(Conv *c, int state); static void sendconnect(Conv *c, int op, ulong dialid, ulong acceptid); static void sdpackproc(void *a); . 115a enum { TConnect, TControl, TControlAck, TData, TThwackC, TThwackU, }; enum { ConOpen, ConOpenAck, ConOpenNack, ConClose, ConCloseAck, }; struct ConPkt { uchar type; // always zero = connection packet uchar op; uchar pad[2]; uchar dialid[4]; uchar acceptid[4]; }; . 113a int ackproc; . 111a Rendez vous; /* used by sdpackproc */ . 104a int drop; . 99a Proc *readproc; ulong timeout; int retries; // the following pair uniquely define conversation on this port ulong dialid; ulong acceptid; . 98c int dataopen; . 94c int ref; // number of times the conv is opened . 88a CClosed, . 85c CInit, . 48,49d 34a Maxretries= 4, . 14a typedef struct ConPkt ConPkt; . ## diffname port/devsdp.c 1999/0907 ## diff -e /n/emeliedump/1999/0906/sys/src/brazil/port/devsdp.c /n/emeliedump/1999/0907/sys/src/brazil/port/devsdp.c 691a } static int readready(void *a) { Conv *c = a; return (c->state == CClosed) || c->in.controlpkt != nil || c->dataopen == 0; } static Block * readcontrol(Conv *c, int n) { Block *b; for(;;) { qlock(c); if(c->state == CClosed || c->state == CInit) { qunlock(c); return nil; } if(c->in.controlpkt != nil) { b = c->in.controlpkt; c->in.controlpkt = nil; qunlock(c); return b; } qunlock(c); // hack - this is to avoid gating onto the // read which will in general result in excessive // context switches. // The assumed behavior is that the client will read // from the control channel until the session is authenticated // at which point it will open the data channel and // start reading on that. After the data channel is opened, // read on the channel are required for packets to // be delivered to the control channel if(c->dataopen) { sleep(&c->in.controlready, readready, c); } else { b = convreadblock(c, n); if(b == nil) return nil; qlock(c); if(waserror()) { qunlock(c); return nil; } b = conviput(c, b, 1); poperror(); qunlock(c); if(b != nil) return b; } } } static Block * readdata(Conv *c, int n) { Block *b; for(;;) { b = convreadblock(c, n); if(b == nil) return nil; qlock(c); if(waserror()) { qunlock(c); return nil; } b = conviput(c, b, 0); poperror(); qunlock(c); if(b != nil) return b; } . 677a static Block * convreadblock(Conv *c, int n) { Block *b; qlock(&c->readlk); if(waserror()) { c->readproc = nil; qunlock(&c->readlk); nexterror(); } qlock(c); if(c->state == CClosed) { qunlock(c); poperror(); qunlock(&c->readlk); return 0; } c->readproc = up; qunlock(c); b = devtab[c->chan->type]->bread(c->chan, n, 0); c->readproc = nil; poperror(); qunlock(&c->readlk); return b; } // assume we hold lock for c static Block * conviput(Conv *c, Block *b, int control) { int type; ulong seq, cseq; if(BLEN(b) < 4) { freeb(b); return nil; } type = b->rp[0]; if(type == TConnect) { conviput2(c, b); return nil; } seq = (b->rp[1]<<16) + (b->rp[2]<<8) + b->rp[3]; b->rp += 4; USED(seq); // auth // decrypt // ok the packet is good switch(type) { case TControl: if(BLEN(b) <= 4) break; cseq = nhgetl(b->rp); if(cseq == c->in.controlseq) { // duplicate control packet // send ack b->wp = b->rp + 4; convoput(c, TControlAck, b); return nil; } if(cseq != c->in.controlseq+1) break; c->in.controlseq = cseq; b->rp += 4; if(control) return b; c->in.controlpkt = b; wakeup(&c->in.controlready); return nil; case TControlAck: if(BLEN(b) != 4) break; cseq = nhgetl(b->rp); if(cseq != c->out.controlseq) break; freeb(b); freeb(c->out.controlpkt); c->out.controlpkt = 0; wakeup(&c->out.controlready); return nil; case TData: if(control) break; return b; } print("droping packet %d n=%ld\n", type, BLEN(b)); freeb(b); return nil; } // assume hold conv lock static void conviput2(Conv *c, Block *b) { ConnectPkt *con; ulong dialid; ulong acceptid; if(BLEN(b) != sizeof(ConnectPkt)) { freeb(b); return; } con = (ConnectPkt*)b->rp; dialid = nhgetl(con->dialid); acceptid = nhgetl(con->acceptid); print("conviput2: %d %uld %uld\n", con->op, dialid, acceptid); switch(con->op) { case ConOpen: if(c->state != COpen || dialid != c->dialid || acceptid != c->acceptid) convoput2(c, ConOpenNack, dialid, acceptid); else convoput2(c, ConOpenAck, dialid, acceptid); break; case ConOpenAck: if(c->state != COpening || dialid != c->dialid) break; c->acceptid = acceptid; convsetstate(c, COpen); break; case ConOpenNack: if(c->state != COpening || dialid != c->dialid) break; convsetstate(c, CClosed); break; case ConClose: if(dialid != c->dialid || acceptid != c->acceptid) break; convsetstate(c, CClosed); break; case ConCloseAck: if(c->state != CClosing || dialid != c->dialid || acceptid != c->acceptid) break; convsetstate(c, CClosed); break; } } // assume hold conv lock static void convoput(Conv *c, int type, Block *b) { // try and compress /* Make space to fit sdp header */ b = padblock(b, 4 + c->out.cipherivlen); b->rp[0] = type; c->out.seq++; if(c->out.seq == (1<<24)) { c->out.seq = 0; c->out.seqwrap++; } b->rp[1] = c->out.seq>>16; b->rp[2] = c->out.seq>>8; b->rp[3] = c->out.seq; // encrypt // auth // simulated errors if(c->drop && c->drop > nrand(c->drop)) return; devtab[c->chan->type]->bwrite(c->chan, b, 0); } // assume hold conv lock static void convoput2(Conv *c, int op, ulong dialid, ulong acceptid) { ConnectPkt con; . 676c if(ow->controlpkt) freeb(ow->controlpkt); if(ow->authstate) free(ow->authstate); if(ow->cipherstate) free(ow->cipherstate); if(ow->compstate) free(ow->compstate); memset(ow, 0, sizeof(OneWay)); } . 674c onewaycleanup(OneWay *ow) . 667a if(c->readproc) postnote(c->readproc, 1, "interrupt", 0); if(c->ref) break; if(c->chan) { cclose(c->chan); c->chan = nil; } strcpy(c->owner, "network"); c->perm = 0660; c->dialid = 0; c->acceptid = 0; c->timeout = 0; c->retries = 0; c->drop = 0; memset(c->masterkey, 0, sizeof(c->masterkey)); onewaycleanup(&c->in); onewaycleanup(&c->out); . 663a convoput2(c, ConClose, c->dialid, c->acceptid); . 656c convoput2(c, ConOpenAck, c->dialid, c->acceptid); . 648c convoput2(c, ConOpen, c->dialid, 0); . 638a print("convsetstate %d -> %d\n", c->state, state); . 584c convoput2(c, ConClose, c->dialid, c->acceptid); . 576c convoput2(c, ConOpen, c->dialid, 0); . 541c strncpy(c->owner, up->user, sizeof(c->owner)); . 389a static Block* sdpbread(Chan* ch, long n, ulong offset) { Sdp *sdp = sdptab + ch->dev; if(TYPE(ch->qid) != Qdata) return devbread(ch, n, offset); return readdata(sdp->conv[CONV(ch->qid)], n); } . 386a case Qcontrol: b = readcontrol(sdp->conv[CONV(ch->qid)], n); if(b == nil) return 0; if(BLEN(b) < n) n = BLEN(b); memmove(a, b->rp, n); freeb(b); return n; case Qdata: b = readdata(sdp->conv[CONV(ch->qid)], n); if(b == nil) return 0; if(BLEN(b) < n) n = BLEN(b); memmove(a, b->rp, n); freeb(b); return n; . 350a Block *b; . 340a case Qdata: case Qctl: case Qstatus: case Qcontrol: if(!(ch->flag & COPEN)) break; c = sdp->conv[CONV(ch->qid)]; qlock(c); if(waserror()) { qunlock(c); nexterror(); } c->ref--; if(TYPE(ch->qid) == Qdata) { c->dataopen--; if(c->dataopen == 0) wakeup(&c->in.controlready); } if(c->ref == 0) { switch(c->state) { default: convsetstate(c, CClosed); break; case COpen: convsetstate(c, CClosing); break; case CClosing: break; } } qunlock(c); poperror(); break; . 334a Conv *c; . 320a if(TYPE(ch->qid) == Qdata) c->dataopen++; . 318c if(strcmp(up->user, c->owner) != 0 || (perm & c->perm) != perm) . 197a . 196a static void onewaycleanup(OneWay *ow); static int readready(void *a); static int controlread(); static Block *conviput(Conv *c, Block *b, int control); static void conviput2(Conv *c, Block *b); static Block *readcontrol(Conv *c, int n); static Block *readdata(Conv *c, int n); static void convoput(Conv *c, int type, Block *b); static void convoput2(Conv *c, int op, ulong dialid, ulong acceptid); . 195d 155a . 147c struct ConnectPkt . 117,118c OneWay in; OneWay out; . 114a uchar masterkey[KeyLength]; . 112c char owner[NAMELEN]; /* protections */ . 109a Proc *readproc; QLock readlk; . 101d 63,83c // conv states . 60c int (*comp)(OneWay*, uchar *dst, uchar *src, int n); . 57c int (*auth)(OneWay*, uchar *buf, int len); . 52,53c int cipherivlen; // initial vector length int cipherblklen; // block length int (*cipher)(OneWay*, uchar *buf, int len); . 49c ulong controlseq; . 47a Rendez controlready; . 46a ulong window; . 43c struct OneWay . 36a KeyLength= 32, . 34,35c Maxconv= 256, // power of 2 Nfs= 4, // number of file systems . 13,15c typedef struct OneWay OneWay; typedef struct ConnectPkt ConnectPkt; . 10a /* * sdp - secure datagram protocol */ . ## diffname port/devsdp.c 1999/0908 ## diff -e /n/emeliedump/1999/0907/sys/src/brazil/port/devsdp.c /n/emeliedump/1999/0908/sys/src/brazil/port/devsdp.c 706c print("convsetstate %s -> %s\n", convstatename[c->state], convstatename[state]); . 362c print("close c->ref = %d\n", c->ref); . 320a print(c->ref = %d\n", c->ref); . 181a static char *convstatename[] = { [CInit] "Init", [COpening] "Opening", [COpen] "Open", [CClosing] "Closing", [CClosed] "Closed", }; . ## diffname port/devsdp.c 1999/0909 ## diff -e /n/emeliedump/1999/0908/sys/src/brazil/port/devsdp.c /n/emeliedump/1999/0909/sys/src/brazil/port/devsdp.c 928c } case ConCloseAck: if(c->state == CClosing && dialid == c->dialid && acceptid == c->acceptid) convsetstate(c, CClosed); . 923,926c case CAccept: case COpen: case CClosing: if(dialid == c->dialid && acceptid == c->acceptid) convsetstate(c, CClosed); . 921c convoput2(c, ConCloseAck, dialid, acceptid); // fall though case ConReset: switch(c->state) { case CDial: if(dialid == c->dialid) convsetstate(c, CClosed); . 915,919d 912,913c case CAccept: if(dialid != c->dialid || acceptid != c->acceptid) { convoput2(c, ConReset, dialid, acceptid); break; } convsetstate(c, COpen); } . 910c switch(c->state) { case CDial: if(dialid != c->dialid) { convoput2(c, ConReset, dialid, acceptid); break; } c->acceptid = acceptid; convsetstate(c, COpen); . 903,907c case ConOpenRequest: switch(c->state) { default: convoput2(c, ConReset, dialid, acceptid); break; case CInit: c->dialid = dialid; convsetstate(c, CAccept); break; case CAccept: case COpen: if(dialid != c->dialid || acceptid != c->acceptid) convoput2(c, ConReset, dialid, acceptid); break; } . 742,743d 740a assert(c->state == COpen); convretryinit(c); . 734,736d 728,732c assert(c->state == CDial || c->state == CAccept); if(c->state == CDial) { convretryinit(c); . 726a case CAccept: assert(c->state == CInit); c->acceptid = (rand()<<16) + rand(); convretryinit(c); convoput2(c, ConOpenAck, c->dialid, c->acceptid); break; . 723,725c convretryinit(c); convoput2(c, ConOpenRequest, c->dialid, 0); . 719,721c case CDial: assert(c->state == CInit); . 656d 653c // check for control packet and keepalive . 651a case CAccept: if(convretry(c)) convoput2(c, ConOpenAck, c->dialid, c->acceptid); break; . 650c convoput2(c, ConOpenRequest, c->dialid, 0); . 647,648c case CDial: . 645a print("convtimer: %s\n", convstatename[c->state]); . 632c c->timeout = TK2SEC(m->ticks) + (c->retries+1); . 627c if(c->retries > MaxRetries) { . 622a static void convretryinit(Conv *c) { c->retries = 0; // +2 to avoid rounding effects. c->timeout = TK2SEC(m->ticks) + 2; }; // assume c is locked . 505c convsetstate(c, CDial); . 501c convsetstate(c, CAccept); . 411,427c n = readstr(off, a, n, convstatename[c->state]); . 394d 375a case CAccept: . 328d 184c [CDial] "Dial", [CAccept] "Accept", . 134a ConReset, . 132d 130c ConOpenRequest, . 73c CDial, CAccept, . 39c MaxRetries= 8, KeepAlive = 60, // keep alive in seconds . ## diffname port/devsdp.c 1999/0910 ## diff -e /n/emeliedump/1999/0909/sys/src/brazil/port/devsdp.c /n/emeliedump/1999/0910/sys/src/brazil/port/devsdp.c 1083a } static void convreader(void *a) { Conv *c = a; Block *b; qlock(c); assert(c->reader == 1); while(c->dataopen == 0) { qunlock(c); b = nil; if(!waserror()) { b = convreadblock(c, 2000); poperror(); } qlock(c); if(b == nil) { convsetstate(c, CClosed); break; } if(!waserror()) { conviput(c, b, 1); poperror(); } } c->reader = 0; qunlock(c); pexit("hangup", 1); . 1071,1072d 1061a return 0; . 1034,1060c sleep(&c->in.controlready, readready, c); . 1021c if(c->state == CInit || c->state == CClosed) { . 1018a USED(n); . 1011c return (c->state == CClosed) || c->in.controlpkt != nil; . 1005a static Block * convreadblock(Conv *c, int n) { Block *b; Chan *ch = nil; qlock(&c->readlk); if(waserror()) { c->readproc = nil; if(ch) cclose(ch); qunlock(&c->readlk); nexterror(); } qlock(c); if(c->state == CClosed) { qunlock(c); error("closed"); } c->readproc = up; ch = c->chan; incref(ch); qunlock(c); b = devtab[ch->type]->bread(ch, n, 0); c->readproc = nil; cclose(ch); poperror(); qunlock(&c->readlk); return b; } . 954a Reset: // invalid connection message - reset to sender convoput2(c, ConReset, dialid, acceptid); . 953c return; case CRemoteClose: return; } return; . 950,951c return; case ConReset: switch(c->state) { case CInit: case CDial: case CAccept: case COpen: case CLocalClose: . 945,948c convsetstate(c, CRemoteClose); return; case CRemoteClose: return; . 943a case CLocalClose: convsetstate(c, CClosed); return; . 940,942d 938a case CInit: . 935,937c convoput2(c, ConReset, dialid, acceptid); . 931a return; case COpen: // duplicate that we ignore return; . 927,930d 925c return; case COpen: // duplicate that we have to ack convoput2(c, ConOpenAckAck, acceptid, dialid); return; } break; case ConOpenAckAck: switch(c->state) { . 919,922d 911,913c // duplicate ConOpenRequest that we ignore return; . 908c return; . 902,904d 898c switch(c->state) { default: panic("unknown state: %d", c->state); case CInit: break; case CDial: if(dialid != c->dialid) goto Reset; break; case CAccept: case COpen: case CLocalClose: case CRemoteClose: if(dialid != c->dialid || acceptid != c->acceptid) goto Reset; break; case CClosed: goto Reset; } print("conviput2: %s: %d %uld %uld\n", convstatename[c->state], con->op, dialid, acceptid); . 856,857d 802,810d 786,800d 781,784d 750a if(c->channame) { free(c->channame); c->channame = nil; } . 741a case CRemoteClose: convoput2(c, ConReset, c->dialid, c->acceptid); break; . 737,738c case CLocalClose: assert(c->state == CAccept || c->state == COpen); . 733c convoput2(c, ConOpenAckAck, c->dialid, c->acceptid); . 654c case CLocalClose: . 649a else convoput2(c, ConReset, c->dialid, c->acceptid); . 600c if(!waserror()) { kproc("convreader", convreader, c); c->reader = 1; } . 587c if(c->state == CClosed && c->reader == 0) . 489,490c if(cb->nf != 2) error("usage: accect file"); if(c->chan != nil) error("already connected"); c->chan = namec(cb->f[1], Aopen, ORDWR, 0); c->channame = malloc(strlen(cb->f[1])+1); strcpy(c->channame, cb->f[1]); . 483,487c c->channame = malloc(strlen(cb->f[1])+1); strcpy(c->channame, cb->f[1]); . 481c error("already connected"); . 479c error("usage: accect file"); . 477c if(strcmp(arg0, "accept") == 0) { . 382,383c case CLocalClose: panic("local close already happened"); . 380c convsetstate(c, CLocalClose); . 332a } . 331c if(TYPE(ch->qid) == Qdata) { if(c->dataopen == 0) if(c->readproc != nil) postnote(c->readproc, 1, "interrupt", 0); . 205a static void convreader(void *a); . 189c [CLocalClose] "LocalClose", [CRemoteClose] "RemoteClose", . 135d 133a ConOpenAckAck, . 100a char *channame; . 99c . 97a QLock readlk; // protects readproc . 90d 88a int reader; // reader proc has been started . 77c CLocalClose, CRemoteClose, . ## diffname port/devsdp.c 1999/0914 ## diff -e /n/emeliedump/1999/0910/sys/src/brazil/port/devsdp.c /n/emeliedump/1999/0914/sys/src/brazil/port/devsdp.c 1143a print("convreader exiting\n"); . 1124a print("convreader\n"); . 1098a static int writeready(void *a) { Conv *c = a; return c->out.controlpkt == nil || (c->state == CClosed) || (c->state == CRemoteClose); } static void writecontrol(Conv *c, void *p, int n) { Block *b; qlock(c); for(;;) { if(c->state == CInit || c->state == CClosed || c->state == CRemoteClose) { qunlock(c); print("writecontrol: return error - state = %s\n", convstatename[c->state]); error("conversation closed"); } if(c->state == COpen && c->out.controlpkt == nil) break; qunlock(c); sleep(&c->out.controlready, writeready, c); qlock(c); } b = allocb(4+n); c->out.controlseq++; hnputl(b->wp, c->out.controlseq); memmove(b->wp+4, p, n); b->wp += 4+n; c->out.controlpkt = b; convretryinit(c); print("send %ld size=%ld\n", c->out.controlseq, BLEN(b)); convoput(c, TControl, copyblock(b, blocklen(b))); qunlock(c); } . 1096c // send ack b = allocb(4); hnputl(b->wp, c->in.controlseq); b->wp += 4; convoput(c, TControlAck, b); b = c->in.controlpkt; c->in.controlpkt = nil; qunlock(c); return b; . 1094a qlock(c); . 1093d 1090c print("readcontrol: return nil - state = %s\n", convstatename[c->state]); return nil; . 1086,1088c if(c->in.controlpkt != nil) break; if(c->state == CRemoteClose) { . 1083c print("readcontrol: return error - state = %s\n", convstatename[c->state]); error("conversation closed"); . 1080d 1078a qlock(c); . 1070c return c->in.controlpkt != nil || (c->state == CClosed) || (c->state == CRemoteClose); . 979a print("invalid conviput2 - sending reset\n"); . 912d 890a print("conviput2: %s: %d %uld %uld\n", convstatename[c->state], con->op, dialid, acceptid); . 862c c->out.controlpkt = nil; . 857a print("ControlAck expected %ulx got %ulx\n", c->out.controlseq, cseq); . 851a print("recv %ld size=%ld\n", cseq, BLEN(b)); . 848d 840,842c if(c->in.controlpkt == nil) { // send ack b->wp = b->rp + 4; convoput(c, TControlAck, b); } else freeb(b); . 838a print("duplicate control packet: %ulx\n", cseq); . 827a print("coniput seq=%ulx\n", seq); . 803a // assumes conv is locked static void convopenchan(Conv *c, char *path) { if(c->chan != nil) error("already connected"); c->chan = namec(path, Aopen, ORDWR, 0); c->channame = malloc(strlen(path)+1); strcpy(c->channame, path); if(waserror()) { cclose(c->chan); c->chan = nil; free(c->channame); c->channame = nil; nexterror(); } kproc("convreader", convreader, c); c->reader = 1; poperror(); } . 761a wakeup(&c->in.controlready); . 758a wakeup(&c->in.controlready); . 674a poperror(); . 673a case CRemoteClose: case CClosed: c->timeout = 0; break; . 671c if(convretry(c, 0)) . 668c b = c->out.controlpkt; if(b != nil) { if(convretry(c, 1)) convoput(c, TControl, copyblock(b, blocklen(b))); } else { c->timeout = 0; } // keepalive . 664,665d 662c if(convretry(c, 1)) . 658c if(convretry(c, 1)) . 655d 647a Block *b; . 637a if(reset) convoput2(c, ConReset, c->dialid, c->acceptid); . 635a print("convretry: %s: %d\n", convstatename[c->state], c->retries); . 633c convretry(Conv *c, int reset) . 611,614d 519a case Qcontrol: print("writecontrol %ld\n", n); writecontrol(sdp->conv[CONV(ch->qid)], a, n); return n; . 497,501c convopenchan(c, cb->f[1]); . 489,493c convopenchan(c, cb->f[1]); . 485d 474d 458a . 437a print("readdata\n"); . 431a print("readcontrol asked %ld got %ld\n", n, BLEN(b)); . 381d 210a static void convopenchan(Conv *c, char *path); . 205a static void writecontrol(Conv *c, void *p, int n); . 39c MaxRetries= 4, . ## diffname port/devsdp.c 1999/0915 ## diff -e /n/emeliedump/1999/0914/sys/src/brazil/port/devsdp.c /n/emeliedump/1999/0915/sys/src/brazil/port/devsdp.c 1229,1232c print("up->error = %s\n", up->error); if(strcmp(up->error, Eintr) != 0) { if(!waserror()) { convsetstate(c, CClosed); poperror(); } break; } } else if(!waserror()) { . 1220c while(c->dataopen == 0 && c->state != CClosed) { . 1210a static long writedata(Conv *c, Block *b) { int n; qlock(c); print("writedata %ulx state=%s\n", b, convstatename[c->state]); if(waserror()) { qunlock(c); nexterror(); } if(c->state != COpen) { freeb(b); error("conversation not open"); } n = BLEN(b); convoput(c, TData, b); poperror(); qunlock(c); return n; } . 1188a poperror(); qunlock(&c->out.controllk); . 1164c qlock(&c->out.controllk); if(waserror()) { qunlock(&c->out.controllk); nexterror(); } qlock(c); // this lock is not held in the sleep below . 1146a poperror(); qunlock(&c->in.controllk); . 1130a poperror(); . 1117c qlock(&c->in.controllk); if(waserror()) { qunlock(&c->in.controllk); nexterror(); } qlock(c); // this lock is not held during the sleep below . 1044a print("convoput\n"); . 818c if(c->state != CInit || c->chan != nil) . 779a if(c->ref) break; . 774,775c print("CClosed -> ref = %d\n", c->ref); . 771a wakeup(&c->out.controlready); . 520a long sdpbwrite(Chan *ch, Block *bp, ulong offset) { Sdp *sdp = sdptab + ch->dev; if(TYPE(ch->qid) != Qdata) return devbwrite(ch, bp, offset); return writedata(sdp->conv[CONV(ch->qid)], bp); } . 517a case Qdata: b = allocb(n); memmove(b->wp, a, n); b->wp += n; return writedata(sdp->conv[CONV(ch->qid)], b); . 470a Block *b; . 380,381c if(c->dataopen == 0 && c->reader == 0) { kproc("convreader", convreader, c); c->reader = 1; } . 208a static long writedata(Conv *c, Block *b); . 53a QLock controllk; . ## diffname port/devsdp.c 1999/0929 ## diff -e /n/emeliedump/1999/0915/sys/src/brazil/port/devsdp.c /n/emeliedump/1999/0929/sys/src/brazil/port/devsdp.c 1269a c->outDataPackets++; c->outDataBytes += n; c->outCompDataBytes += n; . 1228a qunlock(c); . 1227c if(wait) writewait(c); . 1217a } static void writecontrol(Conv *c, void *p, int n, int wait) { Block *b; qlock(&c->out.controllk); qlock(c); if(waserror()) { qunlock(c); qunlock(&c->out.controllk); nexterror(); } writewait(c); . 1215a poperror(); . 1214a if(waserror()) { qlock(c); nexterror(); } . 1206d 1195,1203d 1193c writewait(Conv *c) . 1191a // c is locked . 1169,1173c convack(c); . 1076a c->lstats.outPackets++; . 1048c c->lstats.outPackets++; . 923a c->lstats.inDataPackets++; c->lstats.inDataBytes += BLEN(b); c->lstats.inCompDataBytes += BLEN(b); . 917a c->rstat.outPackets = nhgetl(ack->outPackets); c->rstat.outDataPackets = nhgetl(ack->outDataPackets); c->rstat.outDataBytes = nhgetl(ack->outDataBytes); c->rstat.outCompDataBytes = nhgetl(ack->outCompDataBytes); c->rstat.inPackets = nhgetl(ack->inPackets); c->rstat.inDataPackets = nhgetl(ack->inDataPackets); c->rstat.inDataBytes = nhgetl(ack->inDataBytes); c->rstat.inCompDataBytes = nhgetl(ack->inCompDataBytes); c->rstat.inMissing = nhgetl(ack->inMissing); c->rstat.inDup = nhgetl(ack->inDup); c->rstat.inReorder = nhgetl(ack->inReorder); c->rstat.inBadAuth = nhgetl(ack->inBadAuth); c->rstat.inBadSeq = nhgetl(ack->inBadSeq); . 914c ack = (AckPkt*)(b->rp); cseq = nhgetl(ack->cseq); . 912c if(BLEN(b) != sizeof(AckPkt)) . 909c wakeup(&c->in.controlready); } . 907c if(BLEN(b) == 0) { // just a ping freeb(b); convack(c); } else { c->in.controlpkt = b; . 894,899c freeb(b); if(c->in.controlpkt == nil) convack(c); . 888c if(BLEN(b) < 4) . 864a c->lstat.inPackets++; . 863a AckPkt *ack; . 857a qlock(c); if(local) { stats = &c->lstats; } else { if(!waserror()) { writecontrol(c, 0, 0, 1); poperror(); } stats = &c->rstats; } p = buf; ep = buf + n; p += snprint(p, ep-p, "outPackets: %ld\n", stats->outPackets); p += snprint(p, ep-p, "outDataPackets: %ld\n", stats->outDataPackets); p += snprint(p, ep-p, "outDataBytes: %ld\n", stats->outDataBytes); p += snprint(p, ep-p, "outCompDataBytes: %ld\n", stats->outCompDataBytes); p += snprint(p, ep-p, "inPackets: %ld\n", stats->inPackets); p += snprint(p, ep-p, "inDataPackets: %ld\n", stats->inDataPackets); p += snprint(p, ep-p, "inCompDataBytes: %ld\n", stats->inCompDataBytes); p += snprint(p, ep-p, "inMissing: %ld\n", stats->inMissing); p += snprint(p, ep-p, "inDup: %ld\n", stats->inDup); p += snprint(p, ep-p, "inReorder: %ld\n", stats->inReorder); p += snprint(p, ep-p, "inBadAuth: %ld\n", stats->inBadAuth); p += snprint(p, ep-p, "inBadSeq: %ld\n", stats->inBadSeq); USED(p); qunlock(c); } // c is locked static void convack(Conv *c) { Block *b; AckPkt *ack; Stats *s; b = allocb(sizeof(AckPkt)); ack = (Ack)b->wp; b->wp += sizeof(AckPkt); s = &c->lstats; hnputl(ack->cseq, c->in.controlseq); hnputl(ack->outPackets, s->outPackets); hnputl(ack->outDataPackets, s->outDataPackets); hnputl(ack->outDataBytes, s->outDataBytes); hnputl(ack->outCompDataBytes, s->outCompDataBytes); hnputl(ack->inPackets, s->inPackets); hnputl(ack->inDataPackets, s->inDataPackets); hnputl(ack->inDataBytes, s->inDataBytes); hnputl(ack->inCompDataBytes, s->inCompDataBytes); hnputl(ack->inMissing, s->inMissing); hnputl(ack->inDup, s->inDup); hnputl(ack->inReorder, s->inReorder); hnputl(ack->inBadAuth, s->inBadAuth); hnputl(ack->inBadSeq, s->inBadSeq); convoput(c, TControlAck, b); } . 856a static void convstats(Conv *c, int local, char *buf, int n) { Stats *stats; char *p, *ep; . 521c writecontrol(sdp->conv[CONV(ch->qid)], a, n, 0); . 452a case Qstats: case Qrstats: c = sdp->conv[CONV(ch->qid)]; s = smalloc(1000); convstats(c, TYPE(ch->qid) == Qstats, s, 1000); rv = readstr(off, a, n, s); free(s); return rv; . 412a int rv; . 409a char *s; . 329a case Qstats: case Qrstats: . 313d 216d 214a static void convstats(Conv *c, int local, char *buf, int n); . 207c static void writecontrol(Conv *c, void *p, int n, int wait); . 163a "stats", {Qstats}, 0, 0444, "rstats", {Qrstats}, 0, 0444, . 154d 152a . 151a struct AckPkt { uchar cseq[4]; uchar outPackets[4]; uchar outDataPackets[4]; uchar outDataBytes[4]; uchar outCompDataBytes[4]; uchar inPackets[4]; uchar inDataPackets[4]; uchar inDataBytes[4]; uchar inCompDataBytes[4]; uchar inMissing[4]; uchar inDup[4]; uchar inReorder[4]; uchar inBadAuth[4]; uchar inBadSeq[4]; }; . 92a Stats lstats; Stats rstats; . 49a Rendez statsready; . 47a struct Stats { ulong outPackets; ulong outDataPackets; ulong outDataBytes; ulong outCompDataBytes; ulong outCompBytes; ulong inPackets; ulong inDataPackets; ulong inDataBytes; ulong inCompDataBytes; ulong inMissing; ulong inDup; ulong inReorder; ulong inBadAuth; ulong inBadSeq; }; . 33a Qstats, Qrstats, . 26d 18a typedef struct AckPkt AckPkt; . 17a typedef struct Stats Stats; . ## diffname port/devsdp.c 1999/0930 ## diff -e /n/emeliedump/1999/0929/sys/src/brazil/port/devsdp.c /n/emeliedump/1999/0930/sys/src/brazil/port/devsdp.c 1423,1425c c->lstats.outDataPackets++; c->lstats.outDataBytes += n; c->lstats.outCompDataBytes += n; . 1411d 1391a if(b == nil) return nil; . 1379a } . 1378c if(wait) { print("writecontrol wait!\n"); . 1230,1233c convwriteblock(c, b); . 1224,1228c b = allocb(sizeof(ConnectPkt)); con = (ConnectPkt*)b->wp; b->wp += sizeof(ConnectPkt); con->type = TConnect; con->op = op; hnputl(con->dialid, dialid); hnputl(con->acceptid, acceptid); . 1217c Block *b; ConnectPkt *con; . 1205,1210c convwriteblock(c, b); . 1184a // c is locked static void convwriteblock(Conv *c, Block *b) { // simulated errors if(c->drop && c->drop > nrand(c->drop)) return; if(waserror()) { convsetstate(c, CClosed); nexterror(); } devtab[c->chan->type]->bwrite(c->chan, b, 0); poperror(); } . 1044,1056c } c->rstats.outPackets = nhgetl(ack->outPackets); c->rstats.outDataPackets = nhgetl(ack->outDataPackets); c->rstats.outDataBytes = nhgetl(ack->outDataBytes); c->rstats.outCompDataBytes = nhgetl(ack->outCompDataBytes); c->rstats.inPackets = nhgetl(ack->inPackets); c->rstats.inDataPackets = nhgetl(ack->inDataPackets); c->rstats.inDataBytes = nhgetl(ack->inDataBytes); c->rstats.inCompDataBytes = nhgetl(ack->inCompDataBytes); c->rstats.inMissing = nhgetl(ack->inMissing); c->rstats.inDup = nhgetl(ack->inDup); c->rstats.inReorder = nhgetl(ack->inReorder); c->rstats.inBadAuth = nhgetl(ack->inBadAuth); c->rstats.inBadSeq = nhgetl(ack->inBadSeq); . 1042d 1040a if(cseq != c->out.controlseq) { . 1032c if(0) print("recv %ld size=%ld\n", cseq, BLEN(b)); . 1002c if(0) print("coniput seq=%ulx\n", seq); . 985c c->lstats.inPackets++; . 956c ack = (AckPkt*)b->wp; . 936a p += snprint(p, ep-p, "inDataBytes: %ld\n", stats->inDataBytes); . 928a qlock(c); . 919d 492d ## diffname port/devsdp.c 1999/1001 ## diff -e /n/emeliedump/1999/0930/sys/src/brazil/port/devsdp.c /n/emeliedump/1999/1001/sys/src/brazil/port/devsdp.c 1443,1444c if(0) { c->lstats.outCompDataBytes += n; convoput(c, TData, b); poperror(); qunlock(c); return n; } b = padblock(b, 4); b->rp[0] = (c->in.window>>1) & 0xff; b->rp[1] = c->in.seq>>16; b->rp[2] = c->in.seq>>8; b->rp[3] = c->in.seq; // must generate same value as convoput seq = (c->out.seq + 1) & (SeqMax-1); bb = allocb(BLEN(b)); nn = thwack(c->out.compstate, bb->wp, b->rp, BLEN(b), seq); if(nn < 0) { c->lstats.outCompDataBytes += BLEN(b); convoput(c, TThwackU, b); freeb(bb); } else { c->lstats.outCompDataBytes += nn; bb->wp += nn; convoput(c, TThwackC, bb); freeb(b); } . 1427c int n, nn; ulong seq; Block *bb; . 1396d 1393,1394c if(wait) . 1391d 1192c if(c->drop && nrand(c->drop) == 0) . 1115d 1070a case TThwackU: c->lstats.inDataPackets++; c->lstats.inCompDataBytes += BLEN(b); mask = b->rp[0]; mseq = (b->rp[1]<<16) | (b->rp[2]<<8) | b->rp[3]; b->rp += 4; thwackack(c->out.compstate, mseq, mask); c->lstats.inDataBytes += BLEN(b); if(control) break; return b; case TThwackC: c->lstats.inDataPackets++; c->lstats.inCompDataBytes += BLEN(b); bb = b; b = allocb(ThwMaxBlock); n = unthwack(c->in.compstate, b->wp, ThwMaxBlock, bb->rp, BLEN(bb), seq); freeb(bb); if(n < 0) break; b->wp += n; mask = b->rp[0]; mseq = (b->rp[1]<<16) | (b->rp[2]<<8) | b->rp[3]; thwackack(c->out.compstate, mseq, mask); b->rp += 4; c->lstats.inDataBytes += BLEN(b); if(control) break; return b; . 1061a c->timeout = c->lastrecv + KeepAlive; . 1007a if(seqdiff > 0) { while(seqdiff > 0 && c->in.window != 0) { if((c->in.window & (1<<(SeqWindow-1))) == 0) { print("missing packet: %ld\n", seq - seqdiff); c->lstats.inMissing++; } c->in.window <<= 1; seqdiff--; } if(seqdiff > 0) { print("missing packets: %ld-%ld\n", seq - SeqWindow - seqdiff+1, seq-SeqWindow); c->lstats.inMissing += seqdiff; } c->in.seq = seq; c->in.seqwrap = seqwrap; c->in.window |= 1; } c->lastrecv = TK2SEC(m->ticks); . 1002c seqwrap = c->in.seqwrap; seqdiff = seq - c->in.seq; if(seqdiff < -(SeqMax*3/4)) { seqwrap++; seqdiff += SeqMax; } else if(seqdiff > SeqMax*3/4) { seqwrap--; seqdiff -= SeqMax; } if(seqdiff <= 0) { if(seqdiff <= -SeqWindow) { print("old sequence number: %ld (%ld %ld)\n", seq, c->in.seqwrap, seqdiff); c->lstats.inBadSeq++; freeb(b); return nil; } if(c->in.window & (1<<-seqdiff)) { print("dup sequence number: %ld (%ld %ld)\n", seq, c->in.seqwrap, seqdiff); c->lstats.inDup++; freeb(b); return nil; } c->lstats.inReorder++; } // ok the sequence number looks ok . 984a ulong mseq, mask; Block *bb; . 982,983c int type, n; ulong seq, seqwrap, cseq; long seqdiff; . 870a memset(&c->lstats, 0, sizeof(Stats)); memset(&c->rstats, 0, sizeof(Stats)); . 865c c->timeout = ~0; . 861c if(c->ciphername) { free(c->ciphername); c->ciphername = nil; } if(c->authname) { free(c->authname); c->authname = nil; } if(c->compname) { free(c->compname); c->compname = nil; } strcpy(c->owner, "network"); . 754c c->timeout = ~0; . 746c c->timeout = c->lastrecv + KeepAlive; if(c->timeout > sec) break; // keepalive - randomly spaced between KeepAlive and 2*KeepAlive if(c->timeout + KeepAlive > sec && nrand(c->lastrecv + 2*KeepAlive - sec) > 0) break; print("sending keep alive: %ld\n", sec - c->lastrecv); // can not use writecontrol b = allocb(4); c->out.controlseq++; hnputl(b->wp, c->out.controlseq); b->wp += 4; c->out.controlpkt = b; convretryinit(c); if(!waserror()) { convoput(c, TControl, copyblock(b, blocklen(b))); poperror(); } . 743,744c break; . 722c if(c->timeout > sec) . 683a c->in.window = ~0; c->in.compstate = malloc(sizeof(Unthwack)); unthwackinit(c->in.compstate); c->out.compstate = malloc(sizeof(Thwack)); thwackinit(c->out.compstate); . 662a memset(c, 0, sizeof(Conv)); . 575d 210a #ifdef XXX static Algorithm cipheralg[] = { "null", 0, nullcipherinit, "des_56_cbc", 7, descipherinit, "rc4_128", 16, rc4cipherinit, nil, 0, nil, }; static Algorithm authalg[] = { "null", 0, nullauthinit, "hmac_sha_96", 16, shaauthinit, "hmac_md5_96", 16, md5authinit, nil, 0, nil, }; static Algorithm compalg[] = { "null", 0, nullcompinit, "thwack", 0, thwackcompinit, nil, 0, nil, }; #endif . 195a struct Algorithm { char *name; int keylen; // in bytes void (*init)(Conv*, char* name, int keylen); }; . 135a char *authname; char *ciphername; char *compname; . 118c ulong lastrecv; // time last packet was received . 44a SeqMax = (1<<24), SeqWindow = 32, . 42c MaxRetries= 8, . 20a typedef struct Algorithm Algorithm; . 9a #include "../port/thwack.h" . ## diffname port/devsdp.c 1999/1015 ## diff -e /n/emeliedump/1999/1001/sys/src/brazil/port/devsdp.c /n/emeliedump/1999/1015/sys/src/brazil/port/devsdp.c 1665a /* ciphers, authenticators, and compressors */ static void setalg(Conv *c, char *name, Algorithm *alg) { for(; alg->name; alg++) if(strcmp(name, alg->name) == 0) break; if(alg->name == nil) error("unknown algorithm"); alg->init(c, alg->name, alg->keylen); } static void setsecret(OneWay *ow, char *secret) { char *p; int i, c; i = 0; memset(ow->secret, 0, sizeof(ow->secret)); for(p=secret; *p; p++) { if(i >= sizeof(ow->secret)*2) break; c = *p; if(c >= '0' && c <= '9') c -= '0'; else if(c >= 'a' && c <= 'f') c -= 'a'-10; else if(c >= 'A' && c <= 'F') c -= 'A'-10; else error("bad character in secret"); if((i&1) == 0) c <<= 4; ow->secret[i>>1] |= c; i++; } } static void setkey(uchar *key, int n, OneWay *ow, char *prefix) { uchar ibuf[SHAdlen], obuf[MD5dlen], salt[10]; int i, round = 0; while(n > 0){ for(i=0; isecret, sizeof(ow->secret), nil, nil)); i = (n sizeof salt) panic("setkey: you ask too much"); } } static void cipherfree(Conv *c) { if(c->ciphername) { free(c->ciphername); c->ciphername = nil; } if(c->in.cipherstate) { free(c->in.cipherstate); c->in.cipherstate = nil; } if(c->out.cipherstate) { free(c->out.cipherstate); c->out.cipherstate = nil; } c->in.cipher = nil; } static void authfree(Conv *c) { if(c->authname) { free(c->authname); c->authname = nil; } if(c->in.authstate) { free(c->in.authstate); c->in.authstate = nil; } if(c->out.authstate) { free(c->out.authstate); c->out.authstate = nil; } c->in.auth = nil; } static void compfree(Conv *c) { if(c->compname) { free(c->compname); c->compname = nil; } if(c->in.compstate) { free(c->in.compstate); c->in.compstate = nil; } if(c->out.compstate) { free(c->out.compstate); c->out.compstate = nil; } c->in.comp = nil; } static void nullcipherinit(Conv *c, char *, int) { cipherfree(c); } static int desencrypt(OneWay *ow, uchar *p, int n) { uchar *pp, *ip, *eip, *ep; DESstate *ds = ow->cipherstate; ep = p + n; memmove(p, ds->ivec, 8); for(p += 8; p < ep; p += 8){ pp = p; ip = ds->ivec; for(eip = ip+8; ip < eip; ) *pp++ ^= *ip++; block_cipher(ds->expanded, p, 0); memmove(ds->ivec, p, 8); } return 1; } static int desdecrypt(OneWay *ow, uchar *p, int n) { uchar tmp[8]; uchar *tp, *ip, *eip, *ep; DESstate *ds = ow->cipherstate; ep = p + n; memmove(ds->ivec, p, 8); p += 8; while(p < ep){ memmove(tmp, p, 8); block_cipher(ds->expanded, p, 1); tp = tmp; ip = ds->ivec; for(eip = ip+8; ip < eip; ){ *p++ ^= *ip; *ip++ = *tp++; } } return 1; } static void descipherinit(Conv *c, char *name, int n) { uchar key[8]; uchar ivec[8]; int i; cipherfree(c); c->ciphername = malloc(strlen(name)+1); strcpy(c->ciphername, name); if(n > sizeof(key)) n = sizeof(key); /* in */ memset(key, 0, sizeof(key)); setkey(key, n, &c->in, "cipher"); memset(ivec, 0, sizeof(ivec)); c->in.cipherblklen = 8; c->in.cipherivlen = 8; c->in.cipher = desdecrypt; c->in.cipherstate = smalloc(sizeof(DESstate)); setupDESstate(c->in.cipherstate, key, ivec); /* out */ memset(key, 0, sizeof(key)); setkey(key, n, &c->out, "cipher"); for(i=0; i<8; i++) ivec[i] = nrand(256); c->out.cipherblklen = 8; c->out.cipherivlen = 8; c->out.cipher = desencrypt; c->out.cipherstate = smalloc(sizeof(DESstate)); setupDESstate(c->out.cipherstate, key, ivec); } static void rc4cipherinit(Conv *c, char *name, int keylen) { } static void nullauthinit(Conv *c, char *name, int keylen) { authfree(c); } static void shaauthinit(Conv *c, char *name, int keylen) { authfree(c); } static void hmac_md5(uchar hash[MD5dlen], ulong wrap, uchar *t, long tlen, uchar *key, long klen) { uchar ipad[65], opad[65], wbuf[4]; int i; DigestState *digest; uchar innerhash[MD5dlen]; for(i=0; i<64; i++){ ipad[i] = 0x36; opad[i] = 0x5c; } ipad[64] = opad[64] = 0; for(i=0; iauthlen) return 0; tlen -= ow->authlen; memset(hash, 0, MD5dlen); hmac_md5(hash, ow->seqwrap, t, tlen, (uchar*)ow->authstate, 16); r = memcmp(t+tlen, hash, ow->authlen) == 0; memmove(t+tlen, hash, ow->authlen); return r; } static void md5authinit(Conv *c, char *name, int keylen) { authfree(c); c->authname = malloc(strlen(name)+1); strcpy(c->authname, name); if(keylen > 16) keylen = 16; /* in */ c->in.authstate = smalloc(16); memset(c->in.authstate, 0, 16); setkey(c->in.authstate, keylen, &c->in, "auth"); c->in.authlen = 12; c->in.auth = md5auth; /* out */ c->out.authstate = smalloc(16); memset(c->out.authstate, 0, 16); setkey(c->out.authstate, keylen, &c->out, "auth"); c->out.authlen = 12; c->out.auth = md5auth; } static void nullcompinit(Conv *c, char *name, int keylen) { } static void thwackcompinit(Conv *c, char *name, int keylen) { } #ifdef XXX case TThwackU: mask = b->rp[0]; mseq = (b->rp[1]<<16) | (b->rp[2]<<8) | b->rp[3]; b->rp += 4; thwackack(c->out.compstate, mseq, mask); c->lstats.inDataBytes += BLEN(b); if(control) break; return b; case TThwackC: c->lstats.inDataPackets++; c->lstats.inCompDataBytes += BLEN(b); bb = b; b = allocb(ThwMaxBlock); n = unthwack(c->in.compstate, b->wp, ThwMaxBlock, bb->rp, BLEN(bb), seq); freeb(bb); if(n < 0) break; b->wp += n; mask = b->rp[0]; mseq = (b->rp[1]<<16) | (b->rp[2]<<8) | b->rp[3]; thwackack(c->out.compstate, mseq, mask); b->rp += 4; c->lstats.inDataBytes += BLEN(b); if(control) break; return b; } b = padblock(b, 4); b->rp[0] = (c->in.window>>1) & 0xff; b->rp[1] = c->in.seq>>16; b->rp[2] = c->in.seq>>8; b->rp[3] = c->in.seq; // must generate same value as convoput seq = (c->out.seq + 1) & (SeqMax-1); bb = allocb(BLEN(b)); nn = thwack(c->out.compstate, bb->wp, b->rp, BLEN(b), seq); if(nn < 0) { c->lstats.outCompDataBytes += BLEN(b); convoput(c, TThwackU, b); freeb(bb); } else { c->lstats.outCompDataBytes += nn; bb->wp += nn; convoput(c, TThwackC, bb); freeb(b); } #endif . 1616,1623c convoput(c, TCompData, subtype, b); } else convoput(c, TData, 0, b); . 1596,1614c if(c->out.comp != nil) { int subtype = (*c->out.comp)(&c->out, 0, &b); . 1577,1579c int n; . 1544c convoput(c, TControl, ControlMesg, copyblock(b, blocklen(b))); . 1528d 1393,1399c b = allocb(9); b->wp[0] = (TConnect << 4) | op; hnputl(b->wp+1, dialid); hnputl(b->wp+5, acceptid); b->wp += 9; . 1386d 1383c convoconnect(Conv *c, int op, ulong dialid, ulong acceptid) . 1376a if(c->out.auth) { b = padblock(b, -c->out.authlen); b->wp += c->out.authlen; (*c->out.auth)(&c->out, b->rp, BLEN(b)); } . 1365c b->rp[0] = (type << 4) | subtype; . 1359c convoput(Conv *c, int type, int subtype, Block *b) . 1339a static void convicontrol(Conv *c, int subtype, Block *b) { ulong cseq; AckPkt *ack; if(BLEN(b) < 4) return; cseq = nhgetl(b->rp); switch(subtype){ case ControlMesg: if(cseq == c->in.controlseq) { print("duplicate control packet: %ulx\n", cseq); // duplicate control packet freeb(b); if(c->in.controlpkt == nil) convack(c); return; } if(cseq != c->in.controlseq+1) return; c->in.controlseq = cseq; b->rp += 4; if(BLEN(b) == 0) { // just a ping freeb(b); convack(c); } else { c->in.controlpkt = b; if(0) print("recv %ld size=%ld\n", cseq, BLEN(b)); wakeup(&c->in.controlready); } return; case ControlAck: if(cseq != c->out.controlseq) { print("ControlAck expected %ulx got %ulx\n", c->out.controlseq, cseq); return; } if(BLEN(b) < sizeof(AckPkt)) return; ack = (AckPkt*)(b->rp); c->rstats.outPackets = nhgetl(ack->outPackets); c->rstats.outDataPackets = nhgetl(ack->outDataPackets); c->rstats.outDataBytes = nhgetl(ack->outDataBytes); c->rstats.outCompDataBytes = nhgetl(ack->outCompDataBytes); c->rstats.inPackets = nhgetl(ack->inPackets); c->rstats.inDataPackets = nhgetl(ack->inDataPackets); c->rstats.inDataBytes = nhgetl(ack->inDataBytes); c->rstats.inCompDataBytes = nhgetl(ack->inCompDataBytes); c->rstats.inMissing = nhgetl(ack->inMissing); c->rstats.inDup = nhgetl(ack->inDup); c->rstats.inReorder = nhgetl(ack->inReorder); c->rstats.inBadAuth = nhgetl(ack->inBadAuth); c->rstats.inBadSeq = nhgetl(ack->inBadSeq); freeb(b); freeb(c->out.controlpkt); c->out.controlpkt = nil; c->timeout = c->lastrecv + KeepAlive; wakeup(&c->out.controlready); return; } } static Block* convicomp(Conv *c, int subtype, Block *b) { if(c->in.comp == nil) { freeb(b); return nil; } if((*c->in.comp)(&c->in, subtype, &b) < 0) return nil; return b; } . 1336,1337c print("invalid conviconnect - sending reset\n"); convoconnect(c, ConReset, dialid, acceptid); . 1332c break; . 1319c break; . 1305c convoconnect(c, ConReset, dialid, acceptid); . 1290c convoconnect(c, ConOpenAckAck, acceptid, dialid); . 1269c switch(subtype) { . 1262c if(dialid != c->dialid || subtype != ConOpenRequest && acceptid != c->acceptid) . 1247c print("conviconnect: %s: %d %uld %uld\n", convstatename[c->state], subtype, dialid, acceptid); . 1243,1245c dialid = nhgetl(b->rp); acceptid = nhgetl(b->rp + 4); freeb(b); . 1239c if(BLEN(b) != 8) { . 1235d 1233c conviconnect(Conv *c, int subtype, Block *b) . 1207,1224d 1199,1202c b = convicomp(c, subtype, b); if(b == nil); return nil; . 1196c case TCompData: . 1192d 1161,1188d 1135,1159c convicontrol(c, subtype, b); . 1110c if(c->in.auth != 0) { if(!(*c->in.auth)(&c->in, b->rp-4, BLEN(b)+4)) { print("bad auth\n"); c->lstats.inBadAuth++; freeb(b); return nil; } b->wp -= c->in.authlen; } . 1077,1078c seq = (b->rp[0]<<16) + (b->rp[1]<<8) + b->rp[2]; b->rp += 3; . 1073c conviconnect(c, subtype, b); . 1071c type = b->rp[0] >> 4; subtype = type & 0xf; b->rp += 1; . 1060,1062d 1057,1058c int type, subtype; ulong seq, seqwrap; . 1049c convoput(c, TControl, ControlAck, b); . 941d 904c convoconnect(c, ConReset, c->dialid, c->acceptid); . 900c convoconnect(c, ConClose, c->dialid, c->acceptid); . 895c md5authinit(c, "hmac_md5_96", 16); . 893c convoconnect(c, ConOpenAckAck, c->dialid, c->acceptid); hnputl(c->in.secret, c->acceptid); hnputl(c->in.secret+4, c->dialid); hnputl(c->out.secret, c->dialid); hnputl(c->out.secret+4, c->acceptid); } else { hnputl(c->in.secret, c->dialid); hnputl(c->in.secret+4, c->acceptid); hnputl(c->out.secret, c->acceptid); hnputl(c->out.secret+4, c->dialid); . 887c convoconnect(c, ConOpenAck, c->dialid, c->acceptid); . 881c convoconnect(c, ConOpenRequest, c->dialid, 0); . 811c convoconnect(c, ConClose, c->dialid, c->acceptid); . 805c convoput(c, TControl, ControlMesg, copyblock(b, blocklen(b))); . 786c convoput(c, TControl, ControlMesg, copyblock(b, blocklen(b))); . 780c convoconnect(c, ConOpenAck, c->dialid, c->acceptid); . 776c convoconnect(c, ConOpenRequest, c->dialid, 0); . 753c convoconnect(c, ConReset, c->dialid, c->acceptid); . 742c } . 599a } else if(strcmp(arg0, "cipher") == 0) { if(cb->nf != 2) error("usage: cipher alg"); setalg(c, cb->f[1], cipheralg); } else if(strcmp(arg0, "auth") == 0) { if(cb->nf != 2) error("usage: auth alg"); setalg(c, cb->f[1], authalg); } else if(strcmp(arg0, "comp") == 0) { if(cb->nf != 2) error("usage: comp alg"); setalg(c, cb->f[1], compalg); } else if(strcmp(arg0, "insecret") == 0) { if(cb->nf != 2) error("usage: insecret secret"); setsecret(&c->in, cb->f[1]); } else if(strcmp(arg0, "outsecret") == 0) { if(cb->nf != 2) error("usage: outsecret secret"); setsecret(&c->out, cb->f[1]); . 300a static void setalg(Conv *c, char *name, Algorithm *tab); static void setsecret(OneWay *cc, char *secret); static void nullcipherinit(Conv*c, char *name, int keylen); static void descipherinit(Conv*c, char *name, int keylen); static void rc4cipherinit(Conv*c, char *name, int keylen); static void nullauthinit(Conv*c, char *name, int keylen); static void shaauthinit(Conv*c, char *name, int keylen); static void md5authinit(Conv*c, char *name, int keylen); static void nullcompinit(Conv*c, char *name, int keylen); static void thwackcompinit(Conv*c, char *name, int keylen); static Algorithm cipheralg[] = { "null", 0, nullcipherinit, "des_56_cbc", 7, descipherinit, "rc4_128", 16, rc4cipherinit, nil, 0, nil, }; static Algorithm authalg[] = { "null", 0, nullauthinit, "hmac_sha_96", 16, shaauthinit, "hmac_md5_96", 16, md5authinit, nil, 0, nil, }; static Algorithm compalg[] = { "null", 0, nullcompinit, "thwack", 0, thwackcompinit, nil, 0, nil, }; . 295,296c static void convoput(Conv *c, int type, int subtype, Block *b); static void convoconnect(Conv *c, int op, ulong dialid, ulong acceptid); . 290c static void conviconnect(Conv *c, int op, Block *b); static void convicontrol(Conv *c, int op, Block *b); static Block *convicomp(Conv *c, int op, Block *b); . 225,249d 177,185d 169a ControlMesg, ControlAck, }; enum { . 165,166c TCompData, . 163d 140d 96c int (*comp)(OneWay*, int subtype, Block **); . 80a uchar secret[SecretLength]; . 46c SecretLength= 32, // a secret per direction . 20d ## diffname port/devsdp.c 1999/1016 ## diff -e /n/emeliedump/1999/1015/sys/src/brazil/port/devsdp.c /n/emeliedump/1999/1016/sys/src/brazil/port/devsdp.c 2028,2040c c->compname = name; c->in.compstate = malloc(sizeof(Unthwack)); unthwackinit(c->in.compstate); c->out.compstate = malloc(sizeof(Thwack)); thwackinit(c->out.compstate); c->in.comp = thwackuncomp; c->out.comp = thwackcomp; } . 2025,2026c static void thwackcompinit(Conv *c, char *name, int keylen) { compfree(c); . 2019,2023c } . 2014,2017c *bp = b; return 1; . 2007,2008c if(n < 0) { print("unthwack failed: %r!\n"); freeb(b); return 0; } . 1996,2003c return 1; case ThwackC: bb = *bp; . 1990,1991c switch(subtype) { default: return 0; case ThwackU: b = *bp; . 1988a static int thwackuncomp(Conv *c, int subtype, ulong seq, Block **bp) { Block *b, *bb; ulong mask; ulong mseq; int n; . 1986a Block *b, *bb; int nn; // add ack info b = padblock(*bp, 4); b->rp[0] = (c->in.window>>1) & 0xff; b->rp[1] = c->in.seq>>16; b->rp[2] = c->in.seq>>8; b->rp[3] = c->in.seq; bb = allocb(BLEN(b)); nn = thwack(c->out.compstate, bb->wp, b->rp, BLEN(b), seq); if(nn < 0) { freeb(bb); *bp = b; return ThwackU; } else { bb->wp += nn; freeb(b); *bp = bb; return ThwackC; } . 1984,1985c static int thwackcomp(Conv *c, int, ulong seq, Block **bp) . 1981a compfree(c); . 1980c nullcompinit(Conv *c, char*, int) . 1958,1959c c->authname = name; . 1896a cipherfree(c); . 1866,1867c c->ciphername = name; . 1809d 1794,1797c c->compname = nil; . 1776,1779c c->authname = nil; . 1758,1761c c->ciphername = nil; . 1754d 1644c // must generate same value as convoput seq = (c->out.seq + 1) & (SeqMax-1); subtype = (*c->out.comp)(c, 0, seq, &b); . 1626a ulong seq; int subtype; . 1383c if(!(*c->in.comp)(c, subtype, seq, &b)) . 1377c convicomp(Conv *c, int subtype, ulong seq, Block *b) . 1364a c->rstats.inBadComp = nhgetl(ack->inBadComp); . 1191a } . 1189,1190c b = convicomp(c, subtype, seq, b); if(b == nil) { c->lstats.inBadComp++; . 1104c subtype = b->rp[0] & 0xf; . 1081a hnputl(ack->inBadComp, s->inBadComp); . 1051a p += snprint(p, ep-p, "inBadComp: %ld\n", stats->inBadComp); . 958,969c c->ciphername = nil; c->authname = nil; c->compname = nil; . 751,754d 261c static Block *convicomp(Conv *c, int op, ulong, Block *b); . 193a uchar inBadComp[4]; . 172a ThwackU, ThwackC, }; enum { . 97c int (*comp)(Conv*, int subtype, ulong seq, Block **); . 67a ulong inBadComp; . ## diffname port/devsdp.c 1999/1019 ## diff -e /n/emeliedump/1999/1016/sys/src/brazil/port/devsdp.c /n/emeliedump/1999/1019/sys/src/brazil/port/devsdp.c 1991c nn = thwack(c->out.compstate, bb->wp, b->rp, BLEN(b), seq, c->lstats.outCompStats); . 1313a int i; . 1069a for(i=0; ioutCompStats+i*4, s->outCompStats[i]); . 1059a int i; . 1035,1048c p += snprint(p, ep-p, "outPackets: %lud\n", stats->outPackets); p += snprint(p, ep-p, "outDataPackets: %lud\n", stats->outDataPackets); p += snprint(p, ep-p, "outDataBytes: %lud\n", stats->outDataBytes); p += snprint(p, ep-p, "outCompDataBytes: %lud\n", stats->outCompDataBytes); for(i=0; ioutCompStats[i] == 0) continue; p += snprint(p, ep-p, "outCompStats[%d]: %lud\n", i, stats->outCompStats[i]); } p += snprint(p, ep-p, "outCompDataBytes: %lud\n", stats->outCompDataBytes); p += snprint(p, ep-p, "inPackets: %lud\n", stats->inPackets); p += snprint(p, ep-p, "inDataPackets: %lud\n", stats->inDataPackets); p += snprint(p, ep-p, "inDataBytes: %lud\n", stats->inDataBytes); p += snprint(p, ep-p, "inCompDataBytes: %lud\n", stats->inCompDataBytes); p += snprint(p, ep-p, "inMissing: %lud\n", stats->inMissing); p += snprint(p, ep-p, "inDup: %lud\n", stats->inDup); p += snprint(p, ep-p, "inReorder: %lud\n", stats->inReorder); p += snprint(p, ep-p, "inBadComp: %lud\n", stats->inBadComp); p += snprint(p, ep-p, "inBadAuth: %lud\n", stats->inBadAuth); p += snprint(p, ep-p, "inBadSeq: %lud\n", stats->inBadSeq); . 1020a int i; . 192a uchar outCompStats[4*NCompStats]; . 60a ulong outCompStats[NCompStats]; . 47a NCompStats = 8, . ## diffname port/devsdp.c 1999/1021 ## diff -e /n/emeliedump/1999/1019/sys/src/brazil/port/devsdp.c /n/emeliedump/1999/1021/sys/src/brazil/port/devsdp.c 2005c nn = thwack(c->out.compstate, bb->wp, b->rp, BLEN(b), seq); . 1327d 1081c for(i=0; ioutCompStats[i] == 0) . ## diffname port/devsdp.c 1999/1022 ## diff -e /n/emeliedump/1999/1021/sys/src/brazil/port/devsdp.c /n/emeliedump/1999/1022/sys/src/brazil/port/devsdp.c 2060d 2056c thwackcompinit(Conv *c) . 2004c nn = thwack(c->out.compstate, bb->wp, b->rp, BLEN(b), seq, c->lstats.outCompStats); . 1985c nullcompinit(Conv *c) . 1964,1965c keylen = c->auth->keylen; . 1961a int keylen; . 1960c md5authinit(Conv *c) . 1912c shaauthinit(Conv *c) . 1906c nullauthinit(Conv *c) . 1902a n = c->cipher->keylen; if(n > sizeof(key)) n = sizeof(key); /* in */ memset(key, 0, sizeof(key)); setkey(key, n, &c->in, "cipher"); c->in.cipherblklen = 1; c->in.cipherivlen = 4; c->in.cipher = rc4decrypt; cr = smalloc(sizeof(CipherRc4)); memset(cr, 0, sizeof(*cr)); setupRC4state(&cr->current, key, n); c->in.cipherstate = cr; /* out */ memset(key, 0, sizeof(key)); setkey(key, n, &c->out, "cipher"); c->out.cipherblklen = 1; c->out.cipherivlen = 4; c->out.cipher = rc4encrypt; cr = smalloc(sizeof(CipherRc4)); memset(cr, 0, sizeof(*cr)); setupRC4state(&cr->current, key, n); c->out.cipherstate = cr; . 1901a uchar key[32]; CipherRc4 *cr; int n; . 1900c rc4cipherinit(Conv *c) . 1898a static int rc4encrypt(OneWay *ow, uchar *p, int n) { CipherRc4 *cr = ow->cipherstate; if(n < 4) return 0; hnputl(p, cr->cseq); p += 4; n -= 4; rc4(&cr->current, p, n); cr->cseq += n; return 1; } static int rc4decrypt(OneWay *ow, uchar *p, int n) { CipherRc4 *cr = ow->cipherstate; RC4state tmpstate; ulong seq; long d, dd; if(n < 4) return 0; seq = nhgetl(p); p += 4; n -= 4; d = seq-cr->cseq; if(d == 0) { rc4(&cr->current, p, n); cr->cseq += n; if(cr->ovalid) { dd = cr->cseq - cr->lgseq; if(dd > RC4back) cr->ovalid = 0; } } else if(d > 0) { print("missing packet: %uld %ld\n", seq, d); // this link is hosed if(d > RC4forward) return 0; cr->lgseq = seq; if(!cr->ovalid) { cr->ovalid = 1; cr->oseq = cr->cseq; memmove(&cr->old, &cr->current, sizeof(RC4state)); } rc4skip(&cr->current, d); rc4(&cr->current, p, n); cr->cseq = seq+n; } else { print("reordered packet: %uld %ld\n", seq, d); dd = seq - cr->oseq; if(!cr->ovalid || -d > RC4back || dd < 0) return 0; memmove(&tmpstate, &cr->old, sizeof(RC4state)); rc4skip(&tmpstate, dd); rc4(&tmpstate, p, n); return 1; } // move old state up if(cr->ovalid) { dd = cr->cseq - RC4back - cr->oseq; if(dd > 0) { rc4skip(&cr->old, dd); cr->oseq += dd; } } return 1; } . 1872d 1869a int n = c->cipher->keylen; . 1865c descipherinit(Conv *c) . 1847a if(n < 8 || (n & 0x7 != 0)) return 0; . 1827a if(n < 8 || (n & 0x7 != 0)) return 0; . 1817c nullcipherinit(Conv *c) . 1804d 1798a c->in.authlen = 0; c->out.authlen = 0; . 1789d 1783a c->in.cipherblklen = 0; c->out.cipherblklen = 0; c->in.cipherivlen = 0; c->out.cipherivlen = 0; . 1774d 1721c *p = alg; alg->init(c); . 1713c setalg(Conv *c, char *name, Algorithm *alg, Algorithm **p) . 1438d 1435c if(c->out.cipher) (*c->out.cipher)(&c->out, b->rp+4, BLEN(b)-4); . 1422a /* Make room for sdp trailer */ if(c->out.cipherblklen > 1) pad = c->out.cipherblklen - (BLEN(b) + c->out.cipherivlen) % c->out.cipherblklen; else pad = 0; b = padblock(b, -(pad+c->out.authlen)); if(pad) { memset(b->wp, 0, pad-1); b->wp[pad-1] = pad; b->wp += pad; } . 1421c int pad; . 1378a c->rstats.inBadOther = nhgetl(ack->inBadOther); . 1368a for(i=0; irstats.outCompStats[i] = nhgetl(ack->outCompStats + 4*i); . 1326a int i; . 1208a c->lstats.inBadOther++; . 1163c if(c->in.cipher != 0) { if(!(*c->in.cipher)(&c->in, b->rp, BLEN(b))) { print("bad cipher\n"); c->lstats.inBadOther++; freeb(b); return nil; } b->rp += c->in.cipherivlen; if(c->in.cipherblklen > 1) { pad = b->wp[-1]; if(pad > BLEN(b)) { print("pad too big\n"); c->lstats.inBadOther++; freeb(b); return nil; } b->wp -= pad; } } . 1107a c->lstats.inBadOther++; . 1103a int pad; . 1092a hnputl(ack->inBadOther, s->inBadOther); . 1058a p += snprint(p, ep-p, "inBadOther: %lud\n", stats->inBadOther); . 1048d 964,966c c->cipher = nil; c->auth = nil; c->comp = nil; . 937c setalg(c, "hmac_md5_96", authalg, &c->auth); . 636a if(c->cipher) c->cipher->init(c); if(c->auth) c->auth->init(c); . 632a if(c->cipher) c->cipher->init(c); if(c->auth) c->auth->init(c); . 628c setalg(c, cb->f[1], compalg, &c->comp); . 624c setalg(c, cb->f[1], authalg, &c->auth); . 620c setalg(c, cb->f[1], cipheralg, &c->cipher); . 298a "rc4_256", 32, rc4cipherinit, . 285,292c static void nullcipherinit(Conv*c); static void descipherinit(Conv*c); static void rc4cipherinit(Conv*c); static void nullauthinit(Conv*c); static void shaauthinit(Conv*c); static void md5authinit(Conv*c); static void nullcompinit(Conv*c); static void thwackcompinit(Conv*c); . 282c static void setalg(Conv *c, char *name, Algorithm *tab, Algorithm **); . 214a enum { RC4forward = 10*1024*1024, // maximum skip forward RC4back = 100*1024, // maximum look back }; struct CipherRc4 { ulong cseq; // current byte sequence number RC4state current; int ovalid; // old is valid ulong lgseq; // last good sequence ulong oseq; // old byte sequence number RC4state old; }; . 212c void (*init)(Conv*); . 205a uchar inBadOther[4]; . 144,146c Algorithm *auth; Algorithm *cipher; Algorithm *comp; . 72a ulong inBadOther; . 21a typedef struct CipherRc4 CipherRc4; . ## diffname port/devsdp.c 1999/1027 ## diff -e /n/emeliedump/1999/1022/sys/src/brazil/port/devsdp.c /n/emeliedump/1999/1027/sys/src/brazil/port/devsdp.c 974c // convoconnect(c, ConReset, c->dialid, c->acceptid); . 908c 'E', . 558a print("readcontrol asked %ld\n", n); . 370c c = devattach('E', spec); . 342a return; . 333c // "thwack", 0, thwackcompinit, . ## diffname port/devsdp.c 1999/1028 ## diff -e /n/emeliedump/1999/1027/sys/src/brazil/port/devsdp.c /n/emeliedump/1999/1028/sys/src/brazil/port/devsdp.c 561d 333c "thwack", 0, thwackcompinit, . ## diffname port/devsdp.c 1999/1031 ## diff -e /n/emeliedump/1999/1028/sys/src/brazil/port/devsdp.c /n/emeliedump/1999/1031/sys/src/9/port/devsdp.c 1729c if(c->out.comp != nil && 0) { . 1188c print("bad auth %d\n", BLEN(b)+4); . ## diffname port/devsdp.c 1999/1106 ## diff -e /n/emeliedump/1999/1031/sys/src/9/port/devsdp.c /n/emeliedump/1999/1106/sys/src/9/port/devsdp.c 1729c if(0 && c->out.comp != nil) { . 1703a } . 1702c if(b != nil) { if(BLEN(b) > n) b->wp = b->rp + n; . 1691c // some slack for tunneling overhead nn = n + 100; // make sure size is big enough for control messages if(nn < 1000) nn = 1000; b = convreadblock(c, nn); . 1688a int nn; . 1188c print("bad auth %ld\n", BLEN(b)+4); . ## diffname port/devsdp.c 1999/1111 ## diff -e /n/emeliedump/1999/1106/sys/src/9/port/devsdp.c /n/emeliedump/1999/1111/sys/src/9/port/devsdp.c 1740c if(c->out.comp != nil) { . ## diffname port/devsdp.c 1999/1116 ## diff -e /n/emeliedump/1999/1111/sys/src/9/port/devsdp.c /n/emeliedump/1999/1116/sys/src/9/port/devsdp.c 777c if(c->state == CClosed && c->reader == 0 && c->ref == 0) . 344,345d ## diffname port/devsdp.c 1999/1211 ## diff -e /n/emeliedump/1999/1116/sys/src/9/port/devsdp.c /n/emeliedump/1999/1211/sys/src/9/port/devsdp.c 2042c //print("reordered packet: %uld %ld\n", seq, d); . 2028c //print("missing packet: %uld %ld\n", seq, d); . 1785a convderef(c); . 1773,1776c convsetstate(c, CClosed); . 1562d 1557c assert(c->ref > 0); . 1545,1546d 1540c Chan *ch; . 1533c if(!waserror()) { convwriteblock(c, b); poperror(); } . 1523,1526c assert(c->chan != nil); . 1225c //print("missing packets: %ld-%ld\n", seq - SeqWindow - seqdiff+1, seq-SeqWindow); . 1218c //print("missing packet: %ld\n", seq - seqdiff); . 1043a c->ref++; . 1042a assert(c->reader == 0 && c->ref > 0); // after kproc in case it fails . 1011a convderef(Conv *c) { c->ref--; print("convderef: %d: ref == %d\n", c->id, c->ref); if(c->ref > 0) return; assert(c->ref == 0); assert(c->dataopen == 0); assert(c->controlopen == 0); //print("convderef: %d: ref == 0!\n", c->id); c->state = CFree; if(c->chan) { cclose(c->chan); c->chan = nil; } if(c->channame) { free(c->channame); c->channame = nil; } c->cipher = nil; c->auth = nil; c->comp = nil; strcpy(c->owner, "network"); c->perm = 0660; c->dialid = 0; c->acceptid = 0; c->timeout = 0; c->retries = 0; c->drop = 0; onewaycleanup(&c->in); onewaycleanup(&c->out); memset(&c->lstats, 0, sizeof(Stats)); memset(&c->rstats, 0, sizeof(Stats)); } static void . 1010a //assumes c is locked . 981,1005c if(c->state != CClosed) convderef(c); . 974c wakeup(&c->out.controlready); . 951a c->lastrecv = TK2SEC(m->ticks); . 901a qunlock(c); qlock(sdp); . 898c if(c->ref == 0) continue; qunlock(sdp); qlock(c); if(c->ref > 0 && !waserror()) { . 879,880d 876d 834a case CInit: break; . 829,833c . 821a // assumes c is locked . 786c assert(c->state == CFree); // set ref to 2 - 1 ref for open - 1 ref for channel state c->ref = 2; . 774,775c if(c->ref == 0 && canqlock(c)){ print("%d: state=%d reader=%d ref=%d\n", c->id, c->state, c->reader, c->ref); if(c->ref == 0) . 518,519d 501,509c qunlock(c); break; case Qcontrol: c = sdp->conv[CONV(ch->qid)]; qlock(c); c->controlopen--; convderef(c); if(c->controlopen == 0 && c->ref != 0) { . 497,499c convderef(c); qunlock(c); break; case Qdata: c = sdp->conv[CONV(ch->qid)]; qlock(c); c->dataopen--; convderef(c); if(c->dataopen == 0) if(c->reader == 0) if(c->chan != nil) if(!waserror()) { kproc("convreader", convreader, c); c->reader = 1; c->ref++; poperror(); . 492,494c case Qstats: case Qrstats: . 489d 486,487c logclose(sdp); . 483a if(!(ch->flag & COPEN)) return; . 466c } else if(TYPE(ch->qid) == Qcontrol) { c->controlopen++; . 463c c->dataopen++; // kill reader if Qdata is opened for the first time if(c->dataopen == 1) . 460a . 452a print("open %d:%d: ref=%d\n", c->id, TYPE(ch->qid), c->ref); . 414a . 299a static void convreader(void *a); . 297d 291,294d 286a static void convsetstate(Conv *c, int state); static Block *readcontrol(Conv *c, int n); static void writecontrol(Conv *c, void *p, int n, int wait); static Block *readdata(Conv *c, int n); static long writedata(Conv *c, Block *b); static void convderef(Conv *c); . 282d 277c [CClosed] "Closed", . 271,274c [CFree] "Free", [CInit] "Init", [CDial] "Dial", [CAccept] "Accept", [COpen] "Open", . 140c Chan *chan; // packet channel . 123c int dataopen; // ref count of opens on Qdata int controlopen; // ref count of opens on Qcontrol . 121a int ref; // holds conv up . 120a int id; . 118,119d 106a CFree, . 44,45c MaxRetries= 4, KeepAlive = 10, // keep alive in seconds . ## diffname port/devsdp.c 1999/1221 ## diff -e /n/emeliedump/1999/1211/sys/src/9/port/devsdp.c /n/emeliedump/1999/1221/sys/src/9/port/devsdp.c 44,45c MaxRetries= 12, KeepAlive = 120, // keep alive in seconds . ## diffname port/devsdp.c 1999/1230 ## diff -e /n/emeliedump/1999/1221/sys/src/9/port/devsdp.c /n/emeliedump/1999/1230/sys/src/9/port/devsdp.c 729a if(s == DEVDOTDOT){ switch(TYPE(c->qid)){ case Qtopdir: case Qsdpdir: snprint(buf, sizeof(buf), "#E%d", c->dev); devdir(c, (Qid){CHDIR|Qtopdir, 0}, buf, 0, eve, 0555, dp); break; case Qconvdir: snprint(buf, sizeof(buf), "%d", s); devdir(c, (Qid){CHDIR|Qsdpdir, 0}, buf, 0, eve, 0555, dp); break; default: panic("sdpwalk %lux", c->qid.path); } return 1; } . 397,411d ## diffname port/devsdp.c 2000/0112 ## diff -e /n/emeliedump/1999/1230/sys/src/9/port/devsdp.c /n/emeliedump/2000/0112/sys/src/9/port/devsdp.c 2194c seanq_hmac_md5(hash, ow->seqwrap, t, tlen, (uchar*)ow->authstate, 16); . 2159c seanq_hmac_md5(uchar hash[MD5dlen], ulong wrap, uchar *t, long tlen, uchar *key, long klen) . 1888,1889c sha1((uchar*)prefix, strlen(prefix), ibuf, sha1(salt, round+1, nil, nil)); md5(ibuf, SHA1dlen, obuf, md5(ow->secret, sizeof(ow->secret), nil, nil)); . 1882c uchar ibuf[SHA1dlen], obuf[MD5dlen], salt[10]; . 996c setalg(c, "seanq_hmac_md5_96", authalg, &c->auth); . 331,332c "seanq_hmac_sha1_96", 16, shaauthinit, "seanq_hmac_md5_96", 16, md5authinit, . 9c #include . ## diffname port/devsdp.c 2000/0115 ## diff -e /n/emeliedump/2000/0112/sys/src/9/port/devsdp.c /n/emeliedump/2000/0115/sys/src/9/port/devsdp.c 996c setalg(c, "hmac_md5_96", authalg, &c->auth); . 331,332c "hmac_sha1_96", 16, shaauthinit, "hmac_md5_96", 16, md5authinit, . ## diffname port/devsdp.c 2000/0215 ## diff -e /n/emeliedump/2000/0115/sys/src/9/port/devsdp.c /n/emeliedump/2000/0215/sys/src/9/port/devsdp.c 1640c if(c->chan == nil || c->state == CClosed) { . 1420a convsetstate(c, CClosed); . 1412,1413d 1405,1408d 1403c case ConCloseAck: . 1399a // duplicate ConClose convoconnect(c, ConCloseAck, dialid, acceptid); . 1396a convoconnect(c, ConCloseAck, dialid, acceptid); . 1390,1395d 1388d 1382a case CLocalClose: case CRemoteClose: . 1330a if(subtype == ConReset) { convsetstate(c, CClosed); return; } . 1201a switch(c->state) { case CInit: case CDial: c->lstats.inBadOther++; convoconnect(c, ConReset, c->dialid, c->acceptid); convsetstate(c, CClosed); break; case CAccept: case CRemoteClose: case CLocalClose: c->lstats.inBadOther++; freeb(b); return nil; } . 720c snprint(buf, sizeof(buf), "#E%ld", c->dev); . 445c print("open %d:%ld: ref=%d\n", c->id, TYPE(ch->qid), c->ref); . 190a ConCloseAck, . ## diffname port/devsdp.c 2000/0222 ## diff -e /n/emeliedump/2000/0215/sys/src/9/port/devsdp.c /n/emeliedump/2000/0222/sys/src/9/port/devsdp.c 1843d 1833d 1821d 1701d 1698,1699c if(c->state == CInit || c->state == CClosed || c->state == CRemoteClose) . 1665c if(0)print("readcontrol: return nil - state = %s\n", convstatename[c->state]); . 1656c if(0)print("readcontrol: return error - state = %s\n", convstatename[c->state]); . 1477d 1474,1475c if(cseq != c->out.controlseq) . 1432c if(0)print("invalid conviconnect - sending reset\n"); . 1345c if(0)print("conviconnect: %s: %d %uld %uld\n", convstatename[c->state], subtype, dialid, acceptid); . 1026d 964c if(0)print("convsetstate %s -> %s\n", convstatename[c->state], convstatename[state]); . 885d 841d 839d 801d 570d 446d ## diffname port/devsdp.c 2000/0425 ## diff -e /n/emeliedump/2000/0222/sys/src/9/port/devsdp.c /n/emeliedump/2000/0425/sys/src/9/port/devsdp.c 2304a if(c->out.compstate == nil) error(Enomem); . 2302a if(c->in.compstate == nil) error(Enomem); . 1073c c->channame = smalloc(strlen(path)+1); . 1025c if(0)print("convderef: %d: ref == 0!\n", c->id); . 1021a } . 1020c if(c->ref > 0) { . 958c if(1)print("convsetstate %d: %s -> %s\n", c->id, convstatename[c->state], convstatename[state]); . ## diffname port/devsdp.c 2000/0617 ## diff -e /n/emeliedump/2000/0425/sys/src/9/port/devsdp.c /n/emeliedump/2000/0617/sys/src/9/port/devsdp.c 531d ## diffname port/devsdp.c 2001/0213 ## diff -e /n/emeliedump/2000/0617/sys/src/9/port/devsdp.c /n/emeliedump/2001/0213/sys/src/9/port/devsdp.c 2283c print("unthwack failed: %d\n", n); . 2240,2243c b->rp[0] = (c->in.compwindow>>1) & 0xff; b->rp[1] = c->in.compseq>>16; b->rp[2] = c->in.compseq>>8; b->rp[3] = c->in.compseq; . 1689c if(c->state == CFree || c->state == CInit || c->state == CClosed || c->state == CRemoteClose) . 1317c print("dropping packet id=%d: type=%d n=%ld control=%d\n", c->id, type, BLEN(b), control); . 1311a c->in.compseq = c->in.seq; c->in.compwindow = c->in.window; . 1291a c->in.window |= 1<<-seqdiff; . 1290d 1286a seqdiff = 0; . 1285d 1278d 101a ulong compseq; ulong compwindow; . ## diffname port/devsdp.c 2001/0214 ## diff -e /n/emeliedump/2001/0213/sys/src/9/port/devsdp.c /n/emeliedump/2001/0214/sys/src/9/port/devsdp.c 2244,2247c ackseq = unthwackstate(c->in.compstate, &mask); b->rp[0] = mask; b->rp[1] = ackseq>>16; b->rp[2] = ackseq>>8; b->rp[3] = ackseq; . 2240a ulong ackseq; uchar mask; . 1313,1314d 102,103d ## diffname port/devsdp.c 2001/0918 ## diff -e /n/emeliedump/2001/0214/sys/src/9/port/devsdp.c /n/emeliedump/2001/0918/sys/src/9/port/devsdp.c 938d 765c mkqid(&qid, QID(CONV(c->qid),TYPE(dt->qid)), 0, QTFILE); . 757,759c mkqid(&qid, QID(s, Qconvdir), 0, QTDIR); snprint(up->genbuf, sizeof(up->genbuf), "%d", s); devdir(c, qid, up->genbuf, 0, eve, 0555, dp); . 746c mkqid(&qid, QID(0, Qsdpdir), 0, QTDIR); devdir(c, qid, "sdp", 0, eve, 0555, dp); . 734c if(c->qid.type & QTDIR) . 722,723c snprint(up->genbuf, sizeof(up->genbuf), "%d", s); mkqid(&qid, Qsdpdir, 0, QTDIR); devdir(c, qid, up->genbuf, 0, eve, 0555, dp); . 718,719c snprint(up->genbuf, sizeof(up->genbuf), "#E%ld", c->dev); mkqid(&qid, Qtopdir, 0, QTDIR); devdir(c, qid, up->genbuf, 0, eve, 0555, dp); . 710d 706c sdpgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp) . 407d 404c return devstat(c, db, n, nil, 0, sdpgen); . 401,402c static int sdpstat(Chan* c, uchar* db, int n) . 398c return devwalk(c, nc, name, nname, 0, 0, sdpgen); . 395,396c static Walkqid* sdpwalk(Chan *c, Chan *nc, char **name, int nname) . 378c c->qid = (Qid){QID(0, Qtopdir), 0, QTDIR}; . 286c static int sdpgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp); . 147c char owner[KNAMELEN]; /* protections */ . 52,53c #define TYPE(x) (((ulong)(x).path) & 0xff) #define CONV(x) ((((ulong)(x).path) >> 8)&(Maxconv-1)) . ## diffname port/devsdp.c 2001/0926 ## diff -e /n/emeliedump/2001/0918/sys/src/9/port/devsdp.c /n/emeliedump/2001/0926/sys/src/9/port/devsdp.c 1821c if(strcmp(up->errstr, Eintr) != 0) { . ## diffname port/devsdp.c 2002/0109 ## diff -e /n/emeliedump/2001/0926/sys/src/9/port/devsdp.c /n/emeliedump/2002/0109/sys/src/9/port/devsdp.c 937a devshutdown, . ## diffname port/devsdp.c 2002/0125 ## diff -e /n/emeliedump/2002/0109/sys/src/9/port/devsdp.c /n/emeliedump/2002/0125/sys/src/9/port/devsdp.c 740c panic("sdpgen: unknown type: %lud", TYPE(c->qid)); . 726c panic("sdpwalk %llux", c->qid.path); . ## diffname port/devsdp.c 2002/0326 ## diff -e /n/emeliedump/2002/0125/sys/src/9/port/devsdp.c /n/emeliedump/2002/0326/sys/src/9/port/devsdp.c 2288c if(0)print("unthwack failed: %d\n", n); . 1444c if(0)print("duplicate control packet: %ulx\n", cseq); . 1317c if(0)print("dropping packet id=%d: type=%d n=%ld control=%d\n", c->id, type, BLEN(b), control); . 1266c if(0)print("pad too big\n"); . 1257c if(0)print("bad cipher\n"); . 1247c if(0)print("bad auth %ld\n", BLEN(b)+4); . 1234c if(0)print("dup sequence number: %ld (%ld %ld)\n", seq, c->in.seqwrap, seqdiff); . 1227c if(0)print("old sequence number: %ld (%ld %ld)\n", seq, c->in.seqwrap, seqdiff); . 958c if(0)print("convsetstate %d: %s -> %s\n", c->id, convstatename[c->state], convstatename[state]); . ## diffname port/devsdp.c 2002/0612 ## diff -e /n/emeliedump/2002/0326/sys/src/9/port/devsdp.c /n/emeliedump/2002/0612/sys/src/9/port/devsdp.c 1425c if(1)print("invalid conviconnect - sending reset\n"); . 45c KeepAlive = 60, // keep alive in seconds . 43c Nfs= 4, // number of file systems . ## diffname port/devsdp.c 2002/0625 ## diff -e /n/emeliedump/2002/0612/sys/src/9/port/devsdp.c /n/emeliedump/2002/0625/sys/src/9/port/devsdp.c 45c KeepAlive = 300, // keep alive in seconds - should probably be about 60 but is higher to avoid linksys bug . ## diffname port/devsdp.c 2003/0407 ## diff -e /n/emeliedump/2002/0625/sys/src/9/port/devsdp.c /n/emeliedump/2003/0407/sys/src/9/port/devsdp.c 912c tsleep(&up->sleep, return0, 0, 1000); . 163d