| plan 9 kernel history: overview | file list | diff list |
1999/1001/port/devsdp.c (diff list | history)
| 1999/0824/sys/src/9/port/devsdp.c:9,15 – 1999/0901/sys/src/9/port/devsdp.c:9,16 (short | long) | ||
| 1999/0824 | #include <libcrypt.h> typedef struct Sdp Sdp; | |
| 1999/0901 | typedef struct Conv Conv; typedef struct OneWay OneWay; | |
| 1999/0824 | enum { | |
| 1999/0824/sys/src/9/port/devsdp.c:20,72 – 1999/0901/sys/src/9/port/devsdp.c:21,94 | ||
| 1999/0824 | Qstats, Qlog, | |
| 1999/0901 | Qconvdir, /* directory per conversation */ | |
| 1999/0824 | Qctl, Qdata, /* reliable control channel */ Qpacket, /* unreliable packet channel */ | |
| 1999/0901 | Maxconv= 256, // power of 2 | |
| 1999/0824 | Nfs= 4, // number of file systems }; #define TYPE(x) ((x).path & 0xff) | |
| 1999/0901 | #define CONV(x) (((x).path >> 8)&(Maxconv-1)) | |
| 1999/0824 | #define QID(x, y) (((x)<<8) | (y)) | |
| 1999/0901 | struct OneWay { ulong seqwrap; // number of wraps of the sequence number ulong seq; ulong window; // for replay attacks char *calg; void *cstate; // state cipher int civlen; // in bytes int (*cipher)(OneWay*, uchar *buf, int len); char *aalg; void *astate; // auth state int alen; // auth data length in bytes int (*auth)(OneWay*, uchar *buf, int len, uchar *hash); }; struct Conv { QLock; | |
| 1999/0824 | int id; Sdp *sdp; | |
| 1999/0901 | Chan chan; // packet channel char user[NAMELEN]; /* protections */ int perm; int inuse; int length; int state; OneWay in; OneWay out; | |
| 1999/0824 | }; struct Sdp { QLock; Log; | |
| 1999/0901 | int nconv; Conv *conv[Maxconv]; | |
| 1999/0824 | }; static Dirtab sdpdirtab[]={ | |
| 1999/0901 | "clone", {Qclone}, 0, 0666, | |
| 1999/0824 | }; | |
| 1999/0901 | static Dirtab convdirtab[]={ | |
| 1999/0824 | "ctl", {Qctl}, 0, 0666, "data", {Qdata}, 0, 0666, "packet", {Qpacket}, 0, 0666, | |
| 1999/0824/sys/src/9/port/devsdp.c:94,99 – 1999/0901/sys/src/9/port/devsdp.c:116,122 | ||
| 1999/0824 | static Sdp sdptab[Nfs]; static int sdpgen(Chan *c, Dirtab*, int, int s, Dir *dp); | |
| 1999/0901 | static Conv *sdpclone(Sdp *sdp); | |
| 1999/0824 | static void sdpinit(void) | |
| 1999/0824/sys/src/9/port/devsdp.c:107,114 – 1999/0901/sys/src/9/port/devsdp.c:130,137 | ||
| 1999/0824 | dirtab[TYPE(dt->qid)] = dt; } | |
| 1999/0901 | for(i=0; i<nelem(convdirtab); i++) { dt = convdirtab + i; | |
| 1999/0824 | dirtab[TYPE(dt->qid)] = dt; } } | |
| 1999/0824/sys/src/9/port/devsdp.c:123,129 – 1999/0901/sys/src/9/port/devsdp.c:146,152 | ||
| 1999/0824 | if(dev<0 || dev >= Nfs) error("bad specification"); | |
| 1999/0901 | c = devattach('T', spec); | |
| 1999/0824 | c->qid = (Qid){QID(0, Qtopdir)|CHDIR, 0}; c->dev = dev; | |
| 1999/0824/sys/src/9/port/devsdp.c:139,145 – 1999/0901/sys/src/9/port/devsdp.c:162,168 | ||
| 1999/0824 | case Qsdpdir: c->qid = (Qid){CHDIR|Qtopdir, 0}; break; | |
| 1999/0901 | case Qconvdir: | |
| 1999/0824 | c->qid = (Qid){CHDIR|Qsdpdir, 0}; break; default: | |
| 1999/0824/sys/src/9/port/devsdp.c:158,182 – 1999/0901/sys/src/9/port/devsdp.c:181,205 | ||
| 1999/0824 | } static Chan* | |
| 1999/0901 | sdpopen(Chan* ch, int omode) | |
| 1999/0824 | { int perm; Sdp *sdp; | |
| 1999/0901 | Conv *c; | |
| 1999/0824 | omode &= 3; perm = m2p[omode]; USED(perm); | |
| 1999/0901 | sdp = sdptab + ch->dev; | |
| 1999/0824 |
| |
| 1999/0901 | switch(TYPE(ch->qid)) { | |
| 1999/0824 | default: break; case Qtopdir: case Qsdpdir: | |
| 1999/0901 | case Qconvdir: | |
| 1999/0824 | case Qstatus: | |
| 1999/0824/sys/src/9/port/devsdp.c:184,194 – 1999/0901/sys/src/9/port/devsdp.c:207,223 | ||
| 1999/0824 | case Qlog: logopen(sdp); break; | |
| 1999/0901 | case Qclone: c = sdpclone(sdp); if(c == nil) error(Enodev); ch->qid.path = QID(c->id, Qctl); break; | |
| 1999/0824 | } | |
| 1999/0901 | ch->mode = openmode(omode); ch->flag |= COPEN; ch->offset = 0; return ch; | |
| 1999/0824 | } static void | |
| 1999/0824/sys/src/9/port/devsdp.c:205,230 – 1999/0901/sys/src/9/port/devsdp.c:234,259 | ||
| 1999/0824 | } static long | |
| 1999/0901 | sdpread(Chan *ch, void *a, long n, vlong off) | |
| 1999/0824 | { char buf[256]; | |
| 1999/0901 | Sdp *sdp = sdptab + ch->dev; Conv *c; | |
| 1999/0824 | USED(off); | |
| 1999/0901 | switch(TYPE(ch->qid)) { | |
| 1999/0824 | default: error(Eperm); case Qtopdir: case Qsdpdir: | |
| 1999/0901 | case Qconvdir: return devdirread(ch, a, n, 0, 0, sdpgen); | |
| 1999/0824 | case Qlog: return logread(sdp, a, off, n); case Qstatus: qlock(sdp); | |
| 1999/0901 | c = sdp->conv[CONV(ch->qid)]; if(c == 0) | |
| 1999/0824 | strcpy(buf, "unbound\n"); else { } | |
| 1999/0824/sys/src/9/port/devsdp.c:231,250 – 1999/0901/sys/src/9/port/devsdp.c:260,281 | ||
| 1999/0824 | n = readstr(off, a, n, buf); qunlock(sdp); return n; | |
| 1999/0901 | case Qctl: sprint(buf, "%lud", CONV(ch->qid)); return readstr(off, a, n, buf); | |
| 1999/0824 | } | |
| 1999/0901 | sdpwrite(Chan *ch, void *a, long n, vlong off) | |
| 1999/0824 | { | |
| 1999/0901 | Sdp *sdp = sdptab + ch->dev; | |
| 1999/0824 | Cmdbuf *cb; char *arg0; char *p; USED(off); | |
| 1999/0901 | switch(TYPE(ch->qid)) { | |
| 1999/0824 | default: error(Eperm); case Qctl: | |
| 1999/0824/sys/src/9/port/devsdp.c:258,263 – 1999/0901/sys/src/9/port/devsdp.c:289,295 | ||
| 1999/0824 | if(cb->nf == 0) error("short write"); arg0 = cb->f[0]; | |
| 1999/0901 | print("cmd = %s\n", arg0); | |
| 1999/0824 | if(strcmp(arg0, "xxx") == 0) { print("xxx\n"); } else | |
| 1999/0824/sys/src/9/port/devsdp.c:309,328 – 1999/0901/sys/src/9/port/devsdp.c:341,401 | ||
| 1999/0824 | return 1; } s -= nelem(sdpdirtab); | |
| 1999/0901 | if(s >= sdp->nconv) | |
| 1999/0824 | return -1; | |
| 1999/0901 | qid = (Qid){QID(s,Qconvdir)|CHDIR, 0}; | |
| 1999/0824 | snprint(buf, sizeof(buf), "%d", s); devdir(c, qid, buf, 0, eve, 0555, dp); return 1; | |
| 1999/0901 | case Qconvdir: if(s>=nelem(convdirtab)) | |
| 1999/0824 | return -1; | |
| 1999/0901 | dt = convdirtab+s; qid = (Qid){QID(CONV(c->qid),TYPE(dt->qid)),0}; | |
| 1999/0824 | devdir(c, qid, dt->name, dt->length, eve, dt->perm, dp); return 1; } | |
| 1999/0901 | } 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; | |
| 1999/0824 | } | |
| 1999/0901/sys/src/9/port/devsdp.c:8,16 – 1999/0902/sys/src/9/port/devsdp.c:8,17 (short | long) | ||
| 1999/0824 | #include <libcrypt.h> | |
| 1999/0901 |
| |
| 1999/0902 | typedef struct Sdp Sdp; typedef struct Conv Conv; typedef struct Out Out; typedef struct In In; | |
| 1999/0824 | enum { | |
| 1999/0901/sys/src/9/port/devsdp.c:23,30 – 1999/0902/sys/src/9/port/devsdp.c:24,31 | ||
| 1999/0824 | ||
| 1999/0901 | Qconvdir, /* directory per conversation */ | |
| 1999/0824 | Qctl, | |
| 1999/0902 | Qdata, /* unreliable packet channel */ Qcontrol, /* reliable control channel */ | |
| 1999/0824 | Qstatus, MaxQ, | |
| 1999/0901/sys/src/9/port/devsdp.c:37,75 – 1999/0902/sys/src/9/port/devsdp.c:38,109 | ||
| 1999/0901 | #define CONV(x) (((x).path >> 8)&(Maxconv-1)) | |
| 1999/0824 | #define QID(x, y) (((x)<<8) | (y)) | |
| 1999/0901 |
| |
| 1999/0902 | struct Out | |
| 1999/0901 | { ulong seqwrap; // number of wraps of the sequence number ulong seq; | |
| 1999/0902 | Block *controlpkt; // control channel ulong *controlseq; ulong controltimeout; // timeout when it will be resent int controlretries; | |
| 1999/0901 |
| |
| 1999/0902 | 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); | |
| 1999/0901 | }; | |
| 1999/0902 | 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, }; | |
| 1999/0901 | struct Conv { QLock; | |
| 1999/0824 | int id; | |
| 1999/0902 | int ref; | |
| 1999/0824 | Sdp *sdp; | |
| 1999/0901 |
| |
| 1999/0902 | int state; ulong session; | |
| 1999/0901 | ||
| 1999/0902 | Chan *chan; // packet channel | |
| 1999/0901 | char user[NAMELEN]; /* protections */ int perm; | |
| 1999/0902 | In in; Out out; | |
| 1999/0824 | }; struct Sdp { | |
| 1999/0901/sys/src/9/port/devsdp.c:76,82 – 1999/0902/sys/src/9/port/devsdp.c:110,116 | ||
| 1999/0824 | QLock; Log; | |
| 1999/0901 | int nconv; | |
| 1999/0902 | Conv *conv[Maxconv]; | |
| 1999/0824 | }; static Dirtab sdpdirtab[]={ | |
| 1999/0901/sys/src/9/port/devsdp.c:88,94 – 1999/0902/sys/src/9/port/devsdp.c:122,128 | ||
| 1999/0901 | static Dirtab convdirtab[]={ | |
| 1999/0824 | "ctl", {Qctl}, 0, 0666, "data", {Qdata}, 0, 0666, | |
| 1999/0902 | "control", {Qcontrol}, 0, 0666, | |
| 1999/0824 | "status", {Qstatus}, 0, 0444, }; | |
| 1999/0901/sys/src/9/port/devsdp.c:199,205 – 1999/0902/sys/src/9/port/devsdp.c:233,238 | ||
| 1999/0824 | case Qtopdir: case Qsdpdir: | |
| 1999/0901 | case Qconvdir: | |
| 1999/0824 |
| |
| 1999/0901/sys/src/9/port/devsdp.c:213,218 – 1999/0902/sys/src/9/port/devsdp.c:246,268 | ||
| 1999/0901 | error(Enodev); ch->qid.path = QID(c->id, Qctl); break; | |
| 1999/0902 | 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; | |
| 1999/0824 | } | |
| 1999/0901 | ch->mode = openmode(omode); ch->flag |= COPEN; | |
| 1999/0901/sys/src/9/port/devsdp.c:221,233 – 1999/0902/sys/src/9/port/devsdp.c:271,283 | ||
| 1999/0824 | } static void | |
| 1999/0902 | sdpclose(Chan* ch) | |
| 1999/0824 | { | |
| 1999/0902 | Sdp *sdp = sdptab + ch->dev; | |
| 1999/0824 |
| |
| 1999/0902 | switch(TYPE(ch->qid)) { | |
| 1999/0824 | case Qlog: | |
| 1999/0902 | if(ch->flag & COPEN) | |
| 1999/0824 | logclose(sdp); break; } | |
| 1999/0901/sys/src/9/port/devsdp.c:238,243 – 1999/0902/sys/src/9/port/devsdp.c:288,294 | ||
| 1999/0824 | { char buf[256]; | |
| 1999/0901 | Sdp *sdp = sdptab + ch->dev; | |
| 1999/0902 | char *s; | |
| 1999/0901 | Conv *c; | |
| 1999/0824 | USED(off); | |
| 1999/0901/sys/src/9/port/devsdp.c:251,264 – 1999/0902/sys/src/9/port/devsdp.c:302,327 | ||
| 1999/0824 | case Qlog: return logread(sdp, a, off, n); case Qstatus: | |
| 1999/0901 | c = sdp->conv[CONV(ch->qid)]; | |
| 1999/0824 |
| |
| 1999/0902 | 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; | |
| 1999/0824 | } | |
| 1999/0902 | n = readstr(off, a, n, s); qunlock(c); | |
| 1999/0824 | return n; | |
| 1999/0901 | case Qctl: sprint(buf, "%lud", CONV(ch->qid)); | |
| 1999/0901/sys/src/9/port/devsdp.c:364,369 – 1999/0902/sys/src/9/port/devsdp.c:427,437 | ||
| 1999/0901 | c = nil; ep = sdp->conv + nelem(sdp->conv); | |
| 1999/0902 | qlock(sdp); if(waserror()) { qunlock(sdp); nexterror(); } | |
| 1999/0901 | for(pp = sdp->conv; pp < ep; pp++) { c = *pp; if(c == nil){ | |
| 1999/0901/sys/src/9/port/devsdp.c:378,403 – 1999/0902/sys/src/9/port/devsdp.c:446,493 | ||
| 1999/0901 | break; } if(canqlock(c)){ | |
| 1999/0902 | if(c->state == CClosed) | |
| 1999/0901 | break; | |
| 1999/0902 | poperror(); qunlock(sdp); | |
| 1999/0901 |
| |
| 1999/0902 | if(pp >= ep) | |
| 1999/0901 | return nil; | |
| 1999/0902 | c->ref++; c->state = COpening; | |
| 1999/0901 | strncpy(c->user, up->user, sizeof(c->user)); c->perm = 0660; | |
| 1999/0902 | ||
| 1999/0901 | return c; | |
| 1999/0824 | } | |
| 1999/0902 | 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); } | |
| 1999/0824 | Dev sdpdevtab = { 'T', | |
| 1999/0902/sys/src/9/port/devsdp.c:12,17 – 1999/0906/sys/src/9/port/devsdp.c:12,18 (short | long) | ||
| 1999/0902 | typedef struct Conv Conv; typedef struct Out Out; typedef struct In In; | |
| 1999/0906 | typedef struct ConPkt ConPkt; | |
| 1999/0824 | enum { | |
| 1999/0902/sys/src/9/port/devsdp.c:32,37 – 1999/0906/sys/src/9/port/devsdp.c:33,39 | ||
| 1999/0824 | ||
| 1999/0901 | Maxconv= 256, // power of 2 | |
| 1999/0824 | Nfs= 4, // number of file systems | |
| 1999/0906 | Maxretries= 4, | |
| 1999/0824 | }; #define TYPE(x) ((x).path & 0xff) | |
| 1999/0902/sys/src/9/port/devsdp.c:45,52 – 1999/0906/sys/src/9/port/devsdp.c:47,52 | ||
| 1999/0901 | ||
| 1999/0902 | Block *controlpkt; // control channel ulong *controlseq; | |
| 1999/0901 | ||
| 1999/0902 | void *cipherstate; // state cipher int ivlen; // in bytes | |
| 1999/0902/sys/src/9/port/devsdp.c:82,107 – 1999/0906/sys/src/9/port/devsdp.c:82,119 | ||
| 1999/0902 | }; enum { | |
| 1999/0906 | CInit, | |
| 1999/0902 | COpening, COpen, CClosing, | |
| 1999/0906 | CClosed, | |
| 1999/0902 | }; | |
| 1999/0901 | struct Conv { QLock; | |
| 1999/0824 | int id; | |
| 1999/0902 |
| |
| 1999/0906 | int ref; // number of times the conv is opened | |
| 1999/0824 | Sdp *sdp; | |
| 1999/0901 | ||
| 1999/0902 | int state; | |
| 1999/0906 | int dataopen; | |
| 1999/0901 | ||
| 1999/0906 | Proc *readproc; ulong timeout; int retries; // the following pair uniquely define conversation on this port ulong dialid; ulong acceptid; | |
| 1999/0902 | Chan *chan; // packet channel | |
| 1999/0901 | char user[NAMELEN]; /* protections */ int perm; | |
| 1999/0906 | int drop; | |
| 1999/0902 | In in; Out out; | |
| 1999/0824 | }; | |
| 1999/0902/sys/src/9/port/devsdp.c:109,118 – 1999/0906/sys/src/9/port/devsdp.c:121,158 | ||
| 1999/0824 | struct Sdp { QLock; Log; | |
| 1999/0906 | Rendez vous; /* used by sdpackproc */ | |
| 1999/0901 | int nconv; | |
| 1999/0902 | Conv *conv[Maxconv]; | |
| 1999/0906 | int ackproc; | |
| 1999/0824 | }; | |
| 1999/0906 | 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]; }; | |
| 1999/0824 | static Dirtab sdpdirtab[]={ "stats", {Qstats}, 0, 0444, "log", {Qlog}, 0, 0666, | |
| 1999/0902/sys/src/9/port/devsdp.c:151,156 – 1999/0906/sys/src/9/port/devsdp.c:191,199 | ||
| 1999/0824 | static int sdpgen(Chan *c, Dirtab*, int, int s, Dir *dp); | |
| 1999/0901 | static Conv *sdpclone(Sdp *sdp); | |
| 1999/0906 | static void convsetstate(Conv *c, int state); static void sendconnect(Conv *c, int op, ulong dialid, ulong acceptid); static void sdpackproc(void *a); | |
| 1999/0824 | static void sdpinit(void) | |
| 1999/0902/sys/src/9/port/devsdp.c:168,173 – 1999/0906/sys/src/9/port/devsdp.c:211,217 | ||
| 1999/0901 | dt = convdirtab + i; | |
| 1999/0824 | dirtab[TYPE(dt->qid)] = dt; } | |
| 1999/0906 | ||
| 1999/0824 | } static Chan* | |
| 1999/0902/sys/src/9/port/devsdp.c:175,180 – 1999/0906/sys/src/9/port/devsdp.c:219,227 | ||
| 1999/0824 | { Chan *c; int dev; | |
| 1999/0906 | char buf[100]; Sdp *sdp; int start; | |
| 1999/0824 | dev = atoi(spec); if(dev<0 || dev >= Nfs) | |
| 1999/0902/sys/src/9/port/devsdp.c:184,189 – 1999/0906/sys/src/9/port/devsdp.c:231,247 | ||
| 1999/0824 | c->qid = (Qid){QID(0, Qtopdir)|CHDIR, 0}; c->dev = dev; | |
| 1999/0906 | 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); } | |
| 1999/0824 | return c; } | |
| 1999/0902/sys/src/9/port/devsdp.c:336,341 – 1999/0906/sys/src/9/port/devsdp.c:394,400 | ||
| 1999/0824 | Cmdbuf *cb; char *arg0; char *p; | |
| 1999/0906 | Conv *c; | |
| 1999/0824 | USED(off); | |
| 1999/0901 | switch(TYPE(ch->qid)) { | |
| 1999/0902/sys/src/9/port/devsdp.c:342,351 – 1999/0906/sys/src/9/port/devsdp.c:401,412 | ||
| 1999/0824 | default: error(Eperm); case Qctl: | |
| 1999/0906 | c = sdp->conv[CONV(ch->qid)]; print("Qctl write : conv->id = %d\n", c->id); | |
| 1999/0824 | cb = parsecmd(a, n); | |
| 1999/0906 | qlock(c); | |
| 1999/0824 | if(waserror()) { | |
| 1999/0906 | qunlock(c); | |
| 1999/0824 | free(cb); nexterror(); } | |
| 1999/0902/sys/src/9/port/devsdp.c:353,364 – 1999/0906/sys/src/9/port/devsdp.c:414,442 | ||
| 1999/0824 | error("short write"); arg0 = cb->f[0]; | |
| 1999/0901 | print("cmd = %s\n", arg0); | |
| 1999/0824 |
| |
| 1999/0906 | 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]); | |
| 1999/0824 | } else error("unknown control request"); poperror(); | |
| 1999/0906 | qunlock(c); | |
| 1999/0824 | free(cb); return n; case Qlog: | |
| 1999/0902/sys/src/9/port/devsdp.c:458,464 – 1999/0906/sys/src/9/port/devsdp.c:536,542 | ||
| 1999/0901 | return nil; | |
| 1999/0902 | c->ref++; | |
| 1999/0906 | c->state = CInit; | |
| 1999/0902 | ||
| 1999/0901 | strncpy(c->user, up->user, sizeof(c->user)); c->perm = 0660; | |
| 1999/0902/sys/src/9/port/devsdp.c:467,492 – 1999/0906/sys/src/9/port/devsdp.c:545,614 | ||
| 1999/0901 | return c; | |
| 1999/0824 | } | |
| 1999/0906 | // 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<<c->retries); return 1; } | |
| 1999/0902 | static void | |
| 1999/0906 | convtimer(Conv *c, ulong sec) | |
| 1999/0902 | { | |
| 1999/0906 | if(c->timeout == 0 || c->timeout > sec) return; | |
| 1999/0902 | qlock(c); | |
| 1999/0906 | if(waserror()) { | |
| 1999/0902 | qunlock(c); | |
| 1999/0906 | nexterror(); | |
| 1999/0902 | } | |
| 1999/0906 | 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); } | |
| 1999/0902 |
| |
| 1999/0906 | 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; i<sdp->nconv; i++) { c = sdp->conv[i]; if(!waserror()) { convtimer(c, sec); poperror(); } } qunlock(sdp); | |
| 1999/0902 | } | |
| 1999/0824 | Dev sdpdevtab = { | |
| 1999/0902/sys/src/9/port/devsdp.c:509,511 – 1999/0906/sys/src/9/port/devsdp.c:631,692 | ||
| 1999/0824 | devremove, devwstat, }; | |
| 1999/0906 | // 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); } | |
| 1999/0906/sys/src/9/port/devsdp.c:8,18 – 1999/0907/sys/src/9/port/devsdp.c:8,21 (short | long) | ||
| 1999/0824 | #include <libcrypt.h> | |
| 1999/0907 | /* * sdp - secure datagram protocol */ | |
| 1999/0902 | typedef struct Sdp Sdp; typedef struct Conv Conv; | |
| 1999/0906 |
| |
| 1999/0907 | typedef struct OneWay OneWay; typedef struct ConnectPkt ConnectPkt; | |
| 1999/0824 | enum { | |
| 1999/0906/sys/src/9/port/devsdp.c:31,39 – 1999/0907/sys/src/9/port/devsdp.c:34,43 | ||
| 1999/0824 | MaxQ, | |
| 1999/0901 |
| |
| 1999/0824 |
| |
| 1999/0907 | Maxconv= 256, // power of 2 Nfs= 4, // number of file systems | |
| 1999/0906 | Maxretries= 4, | |
| 1999/0907 | KeyLength= 32, | |
| 1999/0824 | }; #define TYPE(x) ((x).path & 0xff) | |
| 1999/0906/sys/src/9/port/devsdp.c:40,86 – 1999/0907/sys/src/9/port/devsdp.c:44,73 | ||
| 1999/0901 | #define CONV(x) (((x).path >> 8)&(Maxconv-1)) | |
| 1999/0824 | #define QID(x, y) (((x)<<8) | (y)) | |
| 1999/0902 |
| |
| 1999/0907 | struct OneWay | |
| 1999/0901 | { ulong seqwrap; // number of wraps of the sequence number ulong seq; | |
| 1999/0907 | ulong window; | |
| 1999/0901 | ||
| 1999/0907 | Rendez controlready; | |
| 1999/0902 | Block *controlpkt; // control channel | |
| 1999/0907 | ulong controlseq; | |
| 1999/0901 | ||
| 1999/0902 | void *cipherstate; // state cipher | |
| 1999/0907 | int cipherivlen; // initial vector length int cipherblklen; // block length int (*cipher)(OneWay*, uchar *buf, int len); | |
| 1999/0902 | void *authstate; // auth state int authlen; // auth data length in bytes | |
| 1999/0907 | int (*auth)(OneWay*, uchar *buf, int len); | |
| 1999/0902 | void *compstate; | |
| 1999/0907 | int (*comp)(OneWay*, uchar *dst, uchar *src, int n); | |
| 1999/0901 | }; | |
| 1999/0902 |
| |
| 1999/0907 | // conv states | |
| 1999/0902 | enum { | |
| 1999/0906 | CInit, | |
| 1999/0902 | COpening, | |
| 1999/0906/sys/src/9/port/devsdp.c:98,104 – 1999/0907/sys/src/9/port/devsdp.c:85,90 | ||
| 1999/0902 | int state; | |
| 1999/0906 | int dataopen; | |
| 1999/0901 | ||
| 1999/0906 |
| |
| 1999/0906/sys/src/9/port/devsdp.c:107,121 – 1999/0907/sys/src/9/port/devsdp.c:93,111 | ||
| 1999/0906 | ulong dialid; ulong acceptid; | |
| 1999/0907 | Proc *readproc; QLock readlk; | |
| 1999/0902 | Chan *chan; // packet channel | |
| 1999/0901 |
| |
| 1999/0907 | char owner[NAMELEN]; /* protections */ | |
| 1999/0901 | int perm; | |
| 1999/0907 | uchar masterkey[KeyLength]; | |
| 1999/0906 | int drop; | |
| 1999/0902 |
| |
| 1999/0907 | OneWay in; OneWay out; | |
| 1999/0824 | }; struct Sdp { | |
| 1999/0906/sys/src/9/port/devsdp.c:144,150 – 1999/0907/sys/src/9/port/devsdp.c:134,140 | ||
| 1999/0906 | ConCloseAck, }; | |
| 1999/0907 | struct ConnectPkt | |
| 1999/0906 | { uchar type; // always zero = connection packet uchar op; | |
| 1999/0906/sys/src/9/port/devsdp.c:153,158 – 1999/0907/sys/src/9/port/devsdp.c:143,149 | ||
| 1999/0906 | uchar acceptid[4]; }; | |
| 1999/0907 | ||
| 1999/0824 | static Dirtab sdpdirtab[]={ "stats", {Qstats}, 0, 0444, "log", {Qlog}, 0, 0666, | |
| 1999/0906/sys/src/9/port/devsdp.c:192,200 – 1999/0907/sys/src/9/port/devsdp.c:183,200 | ||
| 1999/0824 | static int sdpgen(Chan *c, Dirtab*, int, int s, Dir *dp); | |
| 1999/0901 | static Conv *sdpclone(Sdp *sdp); | |
| 1999/0906 | static void convsetstate(Conv *c, int state); | |
| 1999/0907 | 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); | |
| 1999/0824 | ||
| 1999/0907 | ||
| 1999/0824 | static void sdpinit(void) { | |
| 1999/0906/sys/src/9/port/devsdp.c:315,323 – 1999/0907/sys/src/9/port/devsdp.c:315,325 | ||
| 1999/0902 | nexterror(); } if((perm & (c->perm>>6)) != perm) | |
| 1999/0907 | if(strcmp(up->user, c->owner) != 0 || (perm & c->perm) != perm) | |
| 1999/0902 | error(Eperm); c->ref++; | |
| 1999/0907 | if(TYPE(ch->qid) == Qdata) c->dataopen++; | |
| 1999/0902 | qunlock(c); poperror(); break; | |
| 1999/0906/sys/src/9/port/devsdp.c:332,337 – 1999/0907/sys/src/9/port/devsdp.c:334,340 | ||
| 1999/0902 | sdpclose(Chan* ch) | |
| 1999/0824 | { | |
| 1999/0902 | Sdp *sdp = sdptab + ch->dev; | |
| 1999/0907 | Conv *c; | |
| 1999/0824 | ||
| 1999/0902 | switch(TYPE(ch->qid)) { | |
| 1999/0824 | case Qlog: | |
| 1999/0906/sys/src/9/port/devsdp.c:338,343 – 1999/0907/sys/src/9/port/devsdp.c:341,380 | ||
| 1999/0902 | if(ch->flag & COPEN) | |
| 1999/0824 | logclose(sdp); break; | |
| 1999/0907 | 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; | |
| 1999/0824 | } } | |
| 1999/0906/sys/src/9/port/devsdp.c:348,353 – 1999/0907/sys/src/9/port/devsdp.c:385,391 | ||
| 1999/0901 | Sdp *sdp = sdptab + ch->dev; | |
| 1999/0902 | char *s; | |
| 1999/0901 | Conv *c; | |
| 1999/0907 | Block *b; | |
| 1999/0824 | USED(off); | |
| 1999/0901 | switch(TYPE(ch->qid)) { | |
| 1999/0906/sys/src/9/port/devsdp.c:384,392 – 1999/0907/sys/src/9/port/devsdp.c:422,458 | ||
| 1999/0901 | case Qctl: sprint(buf, "%lud", CONV(ch->qid)); return readstr(off, a, n, buf); | |
| 1999/0907 | 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; | |
| 1999/0824 | } } | |
| 1999/0907 | 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); } | |
| 1999/0824 | static long | |
| 1999/0901 | sdpwrite(Chan *ch, void *a, long n, vlong off) | |
| 1999/0824 | { | |
| 1999/0906/sys/src/9/port/devsdp.c:538,544 – 1999/0907/sys/src/9/port/devsdp.c:604,610 | ||
| 1999/0902 | c->ref++; | |
| 1999/0906 | c->state = CInit; | |
| 1999/0902 | ||
| 1999/0901 |
| |
| 1999/0907 | strncpy(c->owner, up->user, sizeof(c->owner)); | |
| 1999/0901 | c->perm = 0660; qunlock(c); | |
| 1999/0902 | ||
| 1999/0906/sys/src/9/port/devsdp.c:573,579 – 1999/0907/sys/src/9/port/devsdp.c:639,645 | ||
| 1999/0906 | case COpening: print("COpening timeout\n"); if(convretry(c)) | |
| 1999/0907 | convoput2(c, ConOpen, c->dialid, 0); | |
| 1999/0906 | break; case COpen: // check for control packet | |
| 1999/0906/sys/src/9/port/devsdp.c:581,587 – 1999/0907/sys/src/9/port/devsdp.c:647,653 | ||
| 1999/0906 | case CClosing: print("CClosing timeout\n"); if(convretry(c)) | |
| 1999/0907 | convoput2(c, ConClose, c->dialid, c->acceptid); | |
| 1999/0906 | break; } qunlock(c); | |
| 1999/0906/sys/src/9/port/devsdp.c:636,641 – 1999/0907/sys/src/9/port/devsdp.c:702,710 | ||
| 1999/0906 | static void convsetstate(Conv *c, int state) { | |
| 1999/0907 | print("convsetstate %d -> %d\n", c->state, state); | |
| 1999/0906 | switch(state) { default: panic("setstate: bad state: %d", state); | |
| 1999/0906/sys/src/9/port/devsdp.c:645,651 – 1999/0907/sys/src/9/port/devsdp.c:714,720 | ||
| 1999/0906 | c->dialid = (rand()<<16) + rand(); c->timeout = TK2SEC(m->ticks) + 2; c->retries = 0; | |
| 1999/0907 | convoput2(c, ConOpen, c->dialid, 0); | |
| 1999/0906 | break; case COpen: switch(c->state) { | |
| 1999/0906/sys/src/9/port/devsdp.c:653,659 – 1999/0907/sys/src/9/port/devsdp.c:722,728 | ||
| 1999/0906 | error("convsetstate: illegal transition"); case CInit: c->acceptid = (rand()<<16) + rand(); | |
| 1999/0907 | convoput2(c, ConOpenAck, c->dialid, c->acceptid); | |
| 1999/0906 | break; case COpening: break; | |
| 1999/0906/sys/src/9/port/devsdp.c:661,670 – 1999/0907/sys/src/9/port/devsdp.c:730,758 | ||
| 1999/0906 | // setup initial key and auth method break; case CClosing: | |
| 1999/0907 | convoput2(c, ConClose, c->dialid, c->acceptid); | |
| 1999/0906 | c->timeout = TK2SEC(m->ticks) + 2; c->retries = 0; break; case CClosed: | |
| 1999/0907 | 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); | |
| 1999/0906 | break; } c->state = state; | |
| 1999/0906/sys/src/9/port/devsdp.c:671,680 – 1999/0907/sys/src/9/port/devsdp.c:759,960 | ||
| 1999/0906 | } static void | |
| 1999/0907 | onewaycleanup(OneWay *ow) | |
| 1999/0906 | { | |
| 1999/0907 | 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)); } | |
| 1999/0906 | ||
| 1999/0907 | 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; | |
| 1999/0906 | if(c->chan == nil) { print("chan = nil\n"); error("no channel attached"); | |
| 1999/0906/sys/src/9/port/devsdp.c:689,692 – 1999/0907/sys/src/9/port/devsdp.c:969,1052 | ||
| 1999/0906 | if(c->drop && c->drop > nrand(c->drop)) return; devtab[c->chan->type]->write(c->chan, &con, sizeof(con), 0); | |
| 1999/0907 | } 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; } | |
| 1999/0906 | } | |
| 1999/0907/sys/src/9/port/devsdp.c:179,184 – 1999/0908/sys/src/9/port/devsdp.c:179,191 (short | long) | ||
| 1999/0824 | static Dirtab *dirtab[MaxQ]; static Sdp sdptab[Nfs]; | |
| 1999/0908 | static char *convstatename[] = { [CInit] "Init", [COpening] "Opening", [COpen] "Open", [CClosing] "Closing", [CClosed] "Closed", }; | |
| 1999/0824 | static int sdpgen(Chan *c, Dirtab*, int, int s, Dir *dp); | |
| 1999/0901 | static Conv *sdpclone(Sdp *sdp); | |
| 1999/0907/sys/src/9/port/devsdp.c:318,323 – 1999/0908/sys/src/9/port/devsdp.c:325,331 | ||
| 1999/0907 | if(strcmp(up->user, c->owner) != 0 || (perm & c->perm) != perm) | |
| 1999/0902 | error(Eperm); c->ref++; | |
| 1999/0908 | print(c->ref = %d\n", c->ref); | |
| 1999/0907 | if(TYPE(ch->qid) == Qdata) c->dataopen++; | |
| 1999/0902 | qunlock(c); | |
| 1999/0907/sys/src/9/port/devsdp.c:359,365 – 1999/0908/sys/src/9/port/devsdp.c:367,373 | ||
| 1999/0907 | if(c->dataopen == 0) wakeup(&c->in.controlready); } | |
| 1999/0908 | print("close c->ref = %d\n", c->ref); | |
| 1999/0907 | if(c->ref == 0) { switch(c->state) { default: | |
| 1999/0907/sys/src/9/port/devsdp.c:703,709 – 1999/0908/sys/src/9/port/devsdp.c:711,717 | ||
| 1999/0906 | convsetstate(Conv *c, int state) { | |
| 1999/0907 |
| |
| 1999/0908 | print("convsetstate %s -> %s\n", convstatename[c->state], convstatename[state]); | |
| 1999/0907 | ||
| 1999/0906 | switch(state) { default: | |
| 1999/0908/sys/src/9/port/devsdp.c:36,42 – 1999/0909/sys/src/9/port/devsdp.c:36,43 (short | long) | ||
| 1999/0824 | ||
| 1999/0907 | Maxconv= 256, // power of 2 Nfs= 4, // number of file systems | |
| 1999/0906 |
| |
| 1999/0909 | MaxRetries= 8, KeepAlive = 60, // keep alive in seconds | |
| 1999/0907 | KeyLength= 32, | |
| 1999/0824 | }; | |
| 1999/0908/sys/src/9/port/devsdp.c:70,76 – 1999/0909/sys/src/9/port/devsdp.c:71,78 | ||
| 1999/0907 | // conv states | |
| 1999/0902 | enum { | |
| 1999/0906 | CInit, | |
| 1999/0902 |
| |
| 1999/0909 | CDial, CAccept, | |
| 1999/0902 | COpen, CClosing, | |
| 1999/0906 | CClosed, | |
| 1999/0908/sys/src/9/port/devsdp.c:127,137 – 1999/0909/sys/src/9/port/devsdp.c:129,139 | ||
| 1999/0906 | }; enum { | |
| 1999/0909 | ConOpenRequest, | |
| 1999/0906 | ConOpenAck, | |
| 1999/0909 | ConReset, | |
| 1999/0906 | }; | |
| 1999/0907 | struct ConnectPkt | |
| 1999/0908/sys/src/9/port/devsdp.c:181,187 – 1999/0909/sys/src/9/port/devsdp.c:183,190 | ||
| 1999/0824 | static Sdp sdptab[Nfs]; | |
| 1999/0908 | static char *convstatename[] = { [CInit] "Init", | |
| 1999/0909 | [CDial] "Dial", [CAccept] "Accept", | |
| 1999/0908 | [COpen] "Open", [CClosing] "Closing", [CClosed] "Closed", | |
| 1999/0908/sys/src/9/port/devsdp.c:325,331 – 1999/0909/sys/src/9/port/devsdp.c:328,333 | ||
| 1999/0907 | if(strcmp(up->user, c->owner) != 0 || (perm & c->perm) != perm) | |
| 1999/0902 | error(Eperm); c->ref++; | |
| 1999/0908 |
| |
| 1999/0907 | if(TYPE(ch->qid) == Qdata) c->dataopen++; | |
| 1999/0902 | qunlock(c); | |
| 1999/0908/sys/src/9/port/devsdp.c:373,378 – 1999/0909/sys/src/9/port/devsdp.c:375,381 | ||
| 1999/0907 | default: convsetstate(c, CClosed); break; | |
| 1999/0909 | case CAccept: | |
| 1999/0907 | case COpen: convsetstate(c, CClosing); break; | |
| 1999/0908/sys/src/9/port/devsdp.c:391,397 – 1999/0909/sys/src/9/port/devsdp.c:394,399 | ||
| 1999/0824 | { char buf[256]; | |
| 1999/0901 | Sdp *sdp = sdptab + ch->dev; | |
| 1999/0902 |
| |
| 1999/0901 | Conv *c; | |
| 1999/0907 | Block *b; | |
| 1999/0824 | ||
| 1999/0908/sys/src/9/port/devsdp.c:408,430 – 1999/0909/sys/src/9/port/devsdp.c:410,416 | ||
| 1999/0824 | case Qstatus: | |
| 1999/0901 | c = sdp->conv[CONV(ch->qid)]; | |
| 1999/0902 | qlock(c); | |
| 1999/0824 |
| |
| 1999/0902 |
| |
| 1999/0909 | n = readstr(off, a, n, convstatename[c->state]); | |
| 1999/0902 | qunlock(c); | |
| 1999/0824 | return n; | |
| 1999/0901 | case Qctl: | |
| 1999/0908/sys/src/9/port/devsdp.c:498,508 – 1999/0909/sys/src/9/port/devsdp.c:484,494 | ||
| 1999/0906 | if(cb->nf != 2) error("usage: accect id"); c->dialid = atoi(cb->f[1]); | |
| 1999/0909 | convsetstate(c, CAccept); | |
| 1999/0906 | } else if(strcmp(arg0, "dial") == 0) { if(cb->nf != 1) error("usage: dial"); | |
| 1999/0909 | convsetstate(c, CDial); | |
| 1999/0906 | } else if(strcmp(arg0, "drop") == 0) { if(cb->nf != 2) error("usage: drop permil"); | |
| 1999/0908/sys/src/9/port/devsdp.c:620,635 – 1999/0909/sys/src/9/port/devsdp.c:606,630 | ||
| 1999/0824 | } | |
| 1999/0906 | // assume c is locked | |
| 1999/0909 | static void convretryinit(Conv *c) { c->retries = 0; // +2 to avoid rounding effects. c->timeout = TK2SEC(m->ticks) + 2; }; // assume c is locked | |
| 1999/0906 | static int convretry(Conv *c) { c->retries++; | |
| 1999/0909 | if(c->retries > MaxRetries) { | |
| 1999/0906 | print("convretry: giving up\n"); convsetstate(c, CClosed); return 0; } | |
| 1999/0909 | c->timeout = TK2SEC(m->ticks) + (c->retries+1); | |
| 1999/0906 | return 1; } | |
| 1999/0908/sys/src/9/port/devsdp.c:643,659 – 1999/0909/sys/src/9/port/devsdp.c:638,657 | ||
| 1999/0902 | qunlock(c); | |
| 1999/0906 | nexterror(); | |
| 1999/0902 | } | |
| 1999/0909 | print("convtimer: %s\n", convstatename[c->state]); | |
| 1999/0906 | switch(c->state) { | |
| 1999/0909 | case CDial: | |
| 1999/0906 | if(convretry(c)) | |
| 1999/0907 |
| |
| 1999/0909 | convoput2(c, ConOpenRequest, c->dialid, 0); | |
| 1999/0906 | break; | |
| 1999/0909 | case CAccept: if(convretry(c)) convoput2(c, ConOpenAck, c->dialid, c->acceptid); break; | |
| 1999/0906 | case COpen: | |
| 1999/0909 | // check for control packet and keepalive | |
| 1999/0906 | break; case CClosing: | |
| 1999/0907 | convoput2(c, ConClose, c->dialid, c->acceptid); | |
| 1999/0906 | break; | |
| 1999/0908/sys/src/9/port/devsdp.c:716,746 – 1999/0909/sys/src/9/port/devsdp.c:714,743 | ||
| 1999/0906 | switch(state) { default: panic("setstate: bad state: %d", state); | |
| 1999/0909 | case CDial: assert(c->state == CInit); | |
| 1999/0906 | c->dialid = (rand()<<16) + rand(); | |
| 1999/0907 |
| |
| 1999/0909 | convretryinit(c); convoput2(c, ConOpenRequest, c->dialid, 0); | |
| 1999/0906 | break; | |
| 1999/0909 | case CAccept: assert(c->state == CInit); c->acceptid = (rand()<<16) + rand(); convretryinit(c); convoput2(c, ConOpenAck, c->dialid, c->acceptid); break; | |
| 1999/0906 | case COpen: | |
| 1999/0909 | assert(c->state == CDial || c->state == CAccept); if(c->state == CDial) { convretryinit(c); | |
| 1999/0907 | convoput2(c, ConOpenAck, c->dialid, c->acceptid); | |
| 1999/0906 |
| |
| 1999/0909 | assert(c->state == COpen); convretryinit(c); | |
| 1999/0907 | convoput2(c, ConClose, c->dialid, c->acceptid); | |
| 1999/0906 |
| |
| 1999/0907 | if(c->readproc) | |
| 1999/0908/sys/src/9/port/devsdp.c:900,931 – 1999/0909/sys/src/9/port/devsdp.c:897,955 | ||
| 1999/0907 | print("conviput2: %d %uld %uld\n", con->op, dialid, acceptid); switch(con->op) { | |
| 1999/0909 | 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; } | |
| 1999/0907 | break; case ConOpenAck: | |
| 1999/0909 | switch(c->state) { case CDial: if(dialid != c->dialid) { convoput2(c, ConReset, dialid, acceptid); break; } c->acceptid = acceptid; convsetstate(c, COpen); | |
| 1999/0907 | break; | |
| 1999/0909 | case CAccept: if(dialid != c->dialid || acceptid != c->acceptid) { convoput2(c, ConReset, dialid, acceptid); break; } convsetstate(c, COpen); } | |
| 1999/0907 | break; | |
| 1999/0909 | convoput2(c, ConCloseAck, dialid, acceptid); // fall though case ConReset: switch(c->state) { case CDial: if(dialid == c->dialid) convsetstate(c, CClosed); | |
| 1999/0907 | break; | |
| 1999/0909 | case CAccept: case COpen: case CClosing: if(dialid == c->dialid && acceptid == c->acceptid) convsetstate(c, CClosed); | |
| 1999/0907 | break; | |
| 1999/0909 | } case ConCloseAck: if(c->state == CClosing && dialid == c->dialid && acceptid == c->acceptid) convsetstate(c, CClosed); | |
| 1999/0907 | break; } } | |
| 1999/0909/sys/src/9/port/devsdp.c:74,80 – 1999/0910/sys/src/9/port/devsdp.c:74,81 (short | long) | ||
| 1999/0909 | CDial, CAccept, | |
| 1999/0902 | COpen, | |
| 1999/0910 | CLocalClose, CRemoteClose, | |
| 1999/0906 | CClosed, | |
| 1999/0902 | }; | |
| 1999/0909/sys/src/9/port/devsdp.c:86,93 – 1999/0910/sys/src/9/port/devsdp.c:87,94 | ||
| 1999/0901 | ||
| 1999/0902 | int state; | |
| 1999/0906 | int dataopen; | |
| 1999/0910 | int reader; // reader proc has been started | |
| 1999/0901 | ||
| 1999/0906 |
| |
| 1999/0909/sys/src/9/port/devsdp.c:95,103 – 1999/0910/sys/src/9/port/devsdp.c:96,106 | ||
| 1999/0906 | ulong dialid; ulong acceptid; | |
| 1999/0910 | QLock readlk; // protects readproc | |
| 1999/0907 | Proc *readproc; | |
| 1999/0910 | ||
| 1999/0902 | Chan *chan; // packet channel | |
| 1999/0910 | char *channame; | |
| 1999/0902 | ||
| 1999/0907 | char owner[NAMELEN]; /* protections */ | |
| 1999/0901 | int perm; | |
| 1999/0909/sys/src/9/port/devsdp.c:131,138 – 1999/0910/sys/src/9/port/devsdp.c:134,141 | ||
| 1999/0906 | enum { | |
| 1999/0909 | ConOpenRequest, | |
| 1999/0906 | ConOpenAck, | |
| 1999/0910 | ConOpenAckAck, | |
| 1999/0906 | ConClose, | |
| 1999/0909 | ConReset, | |
| 1999/0906 | }; | |
| 1999/0909/sys/src/9/port/devsdp.c:186,192 – 1999/0910/sys/src/9/port/devsdp.c:189,196 | ||
| 1999/0909 | [CDial] "Dial", [CAccept] "Accept", | |
| 1999/0908 | [COpen] "Open", | |
| 1999/0910 | [CLocalClose] "LocalClose", [CRemoteClose] "RemoteClose", | |
| 1999/0908 | [CClosed] "Closed", }; | |
| 1999/0824 | ||
| 1999/0909/sys/src/9/port/devsdp.c:203,208 – 1999/0910/sys/src/9/port/devsdp.c:207,213 | ||
| 1999/0907 | 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); | |
| 1999/0910 | static void convreader(void *a); | |
| 1999/0824 | ||
| 1999/0907 | ||
| 1999/0824 | static void | |
| 1999/0909/sys/src/9/port/devsdp.c:328,335 – 1999/0910/sys/src/9/port/devsdp.c:333,344 | ||
| 1999/0907 | if(strcmp(up->user, c->owner) != 0 || (perm & c->perm) != perm) | |
| 1999/0902 | error(Eperm); c->ref++; | |
| 1999/0907 |
| |
| 1999/0910 | if(TYPE(ch->qid) == Qdata) { if(c->dataopen == 0) if(c->readproc != nil) postnote(c->readproc, 1, "interrupt", 0); | |
| 1999/0907 | c->dataopen++; | |
| 1999/0910 | } | |
| 1999/0902 | qunlock(c); poperror(); break; | |
| 1999/0909/sys/src/9/port/devsdp.c:377,386 – 1999/0910/sys/src/9/port/devsdp.c:386,395 | ||
| 1999/0907 | break; | |
| 1999/0909 | case CAccept: | |
| 1999/0907 | case COpen: | |
| 1999/0910 | convsetstate(c, CLocalClose); | |
| 1999/0907 | break; | |
| 1999/0910 | case CLocalClose: panic("local close already happened"); | |
| 1999/0907 | } } qunlock(c); | |
| 1999/0909/sys/src/9/port/devsdp.c:474,493 – 1999/0910/sys/src/9/port/devsdp.c:483,504 | ||
| 1999/0824 | error("short write"); arg0 = cb->f[0]; | |
| 1999/0901 | print("cmd = %s\n", arg0); | |
| 1999/0906 |
| |
| 1999/0910 | if(strcmp(arg0, "accept") == 0) { | |
| 1999/0906 | if(cb->nf != 2) | |
| 1999/0910 | error("usage: accect file"); | |
| 1999/0906 | if(c->chan != nil) | |
| 1999/0910 | error("already connected"); | |
| 1999/0906 | c->chan = namec(cb->f[1], Aopen, ORDWR, 0); | |
| 1999/0909 |
| |
| 1999/0910 | c->channame = malloc(strlen(cb->f[1])+1); strcpy(c->channame, cb->f[1]); | |
| 1999/0906 | } else if(strcmp(arg0, "dial") == 0) { | |
| 1999/0910 | 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]); | |
| 1999/0909 | convsetstate(c, CDial); | |
| 1999/0906 | } else if(strcmp(arg0, "drop") == 0) { if(cb->nf != 2) | |
| 1999/0909/sys/src/9/port/devsdp.c:584,590 – 1999/0910/sys/src/9/port/devsdp.c:595,601 | ||
| 1999/0901 | break; } if(canqlock(c)){ | |
| 1999/0902 |
| |
| 1999/0910 | if(c->state == CClosed && c->reader == 0) | |
| 1999/0901 | break; qunlock(c); } | |
| 1999/0909/sys/src/9/port/devsdp.c:597,603 – 1999/0910/sys/src/9/port/devsdp.c:608,617 | ||
| 1999/0901 | ||
| 1999/0902 | c->ref++; | |
| 1999/0906 | c->state = CInit; | |
| 1999/0902 | ||
| 1999/0910 | if(!waserror()) { kproc("convreader", convreader, c); c->reader = 1; } | |
| 1999/0907 | strncpy(c->owner, up->user, sizeof(c->owner)); | |
| 1999/0901 | c->perm = 0660; qunlock(c); | |
| 1999/0909/sys/src/9/port/devsdp.c:647,657 – 1999/0910/sys/src/9/port/devsdp.c:661,673 | ||
| 1999/0909 | case CAccept: if(convretry(c)) convoput2(c, ConOpenAck, c->dialid, c->acceptid); | |
| 1999/0910 | else convoput2(c, ConReset, c->dialid, c->acceptid); | |
| 1999/0909 | break; | |
| 1999/0906 | case COpen: | |
| 1999/0909 | // check for control packet and keepalive | |
| 1999/0906 | break; | |
| 1999/0910 | case CLocalClose: | |
| 1999/0906 | if(convretry(c)) | |
| 1999/0907 | convoput2(c, ConClose, c->dialid, c->acceptid); | |
| 1999/0906 | break; | |
| 1999/0909/sys/src/9/port/devsdp.c:730,744 – 1999/0910/sys/src/9/port/devsdp.c:746,763 | ||
| 1999/0909 | assert(c->state == CDial || c->state == CAccept); if(c->state == CDial) { convretryinit(c); | |
| 1999/0907 |
| |
| 1999/0910 | convoput2(c, ConOpenAckAck, c->dialid, c->acceptid); | |
| 1999/0906 | } // setup initial key and auth method break; | |
| 1999/0909 |
| |
| 1999/0910 | case CLocalClose: assert(c->state == CAccept || c->state == COpen); | |
| 1999/0909 | convretryinit(c); | |
| 1999/0907 | convoput2(c, ConClose, c->dialid, c->acceptid); | |
| 1999/0906 | break; | |
| 1999/0910 | case CRemoteClose: convoput2(c, ConReset, c->dialid, c->acceptid); break; | |
| 1999/0906 | case CClosed: | |
| 1999/0907 | if(c->readproc) postnote(c->readproc, 1, "interrupt", 0); | |
| 1999/0909/sys/src/9/port/devsdp.c:748,753 – 1999/0910/sys/src/9/port/devsdp.c:767,776 | ||
| 1999/0907 | cclose(c->chan); c->chan = nil; } | |
| 1999/0910 | if(c->channame) { free(c->channame); c->channame = nil; } | |
| 1999/0907 | strcpy(c->owner, "network"); c->perm = 0660; c->dialid = 0; | |
| 1999/0909/sys/src/9/port/devsdp.c:778,813 – 1999/0910/sys/src/9/port/devsdp.c:801,808 | ||
| 1999/0907 | } | |
| 1999/0906 | ||
| 1999/0907 |
| |
| 1999/0909/sys/src/9/port/devsdp.c:853,860 – 1999/0910/sys/src/9/port/devsdp.c:848,853 | ||
| 1999/0907 | c->in.controlseq = cseq; b->rp += 4; | |
| 1999/0909/sys/src/9/port/devsdp.c:895,957 – 1999/0910/sys/src/9/port/devsdp.c:888,983 | ||
| 1999/0907 | dialid = nhgetl(con->dialid); acceptid = nhgetl(con->acceptid); | |
| 1999/0910 | 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); | |
| 1999/0907 | switch(con->op) { | |
| 1999/0909 | case ConOpenRequest: switch(c->state) { | |
| 1999/0910 | return; | |
| 1999/0909 | case CAccept: case COpen: | |
| 1999/0910 | // duplicate ConOpenRequest that we ignore return; | |
| 1999/0909 | } | |
| 1999/0907 | break; case ConOpenAck: | |
| 1999/0909 | switch(c->state) { case CDial: | |
| 1999/0907 |
| |
| 1999/0910 | return; case COpen: // duplicate that we have to ack convoput2(c, ConOpenAckAck, acceptid, dialid); return; } break; case ConOpenAckAck: switch(c->state) { | |
| 1999/0909 | case CAccept: | |
| 1999/0910 | return; case COpen: // duplicate that we ignore return; | |
| 1999/0909 | } | |
| 1999/0907 | break; case ConClose: | |
| 1999/0909 |
| |
| 1999/0910 | convoput2(c, ConReset, dialid, acceptid); | |
| 1999/0909 | switch(c->state) { | |
| 1999/0910 | case CInit: | |
| 1999/0909 | case CDial: | |
| 1999/0907 |
| |
| 1999/0909 | case CAccept: | |
| 1999/0910 | case CLocalClose: convsetstate(c, CClosed); return; | |
| 1999/0909 | case COpen: | |
| 1999/0907 |
| |
| 1999/0910 | convsetstate(c, CRemoteClose); return; case CRemoteClose: return; | |
| 1999/0909 | } | |
| 1999/0910 | return; case ConReset: switch(c->state) { case CInit: case CDial: case CAccept: case COpen: case CLocalClose: | |
| 1999/0909 | convsetstate(c, CClosed); | |
| 1999/0907 |
| |
| 1999/0910 | return; case CRemoteClose: return; } return; | |
| 1999/0907 | } | |
| 1999/0910 | Reset: // invalid connection message - reset to sender convoput2(c, ConReset, dialid, acceptid); | |
| 1999/0907 | } // assume hold conv lock | |
| 1999/0909/sys/src/9/port/devsdp.c:1003,1014 – 1999/0910/sys/src/9/port/devsdp.c:1029,1073 | ||
| 1999/0906 | devtab[c->chan->type]->write(c->chan, &con, sizeof(con), 0); | |
| 1999/0907 | } | |
| 1999/0910 | 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; } | |
| 1999/0907 | static int readready(void *a) { Conv *c = a; | |
| 1999/0910 | return (c->state == CClosed) || c->in.controlpkt != nil; | |
| 1999/0907 | } static Block * | |
| 1999/0909/sys/src/9/port/devsdp.c:1016,1024 – 1999/0910/sys/src/9/port/devsdp.c:1075,1084 | ||
| 1999/0907 | { Block *b; | |
| 1999/0910 | USED(n); | |
| 1999/0907 | for(;;) { qlock(c); | |
| 1999/0910 | if(c->state == CInit || c->state == CClosed) { | |
| 1999/0907 | qunlock(c); return nil; } | |
| 1999/0909/sys/src/9/port/devsdp.c:1031,1064 – 1999/0910/sys/src/9/port/devsdp.c:1091,1099 | ||
| 1999/0907 | } qunlock(c); | |
| 1999/0910 | sleep(&c->in.controlready, readready, c); | |
| 1999/0907 | } | |
| 1999/0910 | return 0; | |
| 1999/0907 | } static Block * | |
| 1999/0909/sys/src/9/port/devsdp.c:1068,1075 – 1999/0910/sys/src/9/port/devsdp.c:1103,1108 | ||
| 1999/0907 | for(;;) { b = convreadblock(c, n); | |
| 1999/0909/sys/src/9/port/devsdp.c:1081,1084 – 1999/0910/sys/src/9/port/devsdp.c:1114,1147 | ||
| 1999/0907 | if(b != nil) return b; } | |
| 1999/0910 | } 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); | |
| 1999/0906 | } | |
| 1999/0910/sys/src/9/port/devsdp.c:36,42 – 1999/0914/sys/src/9/port/devsdp.c:36,42 (short | long) | ||
| 1999/0824 | ||
| 1999/0907 | Maxconv= 256, // power of 2 Nfs= 4, // number of file systems | |
| 1999/0909 |
| |
| 1999/0914 | MaxRetries= 4, | |
| 1999/0909 | KeepAlive = 60, // keep alive in seconds | |
| 1999/0907 | KeyLength= 32, | |
| 1999/0824 | }; | |
| 1999/0910/sys/src/9/port/devsdp.c:203,213 – 1999/0914/sys/src/9/port/devsdp.c:203,215 | ||
| 1999/0907 | static int controlread(); static Block *conviput(Conv *c, Block *b, int control); static void conviput2(Conv *c, Block *b); | |
| 1999/0914 | static void writecontrol(Conv *c, void *p, int n); | |
| 1999/0907 | 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); | |
| 1999/0910 | static void convreader(void *a); | |
| 1999/0914 | static void convopenchan(Conv *c, char *path); | |
| 1999/0824 | ||
| 1999/0907 | ||
| 1999/0824 | static void | |
| 1999/0910/sys/src/9/port/devsdp.c:378,384 – 1999/0914/sys/src/9/port/devsdp.c:380,385 | ||
| 1999/0907 | if(c->dataopen == 0) wakeup(&c->in.controlready); } | |
| 1999/0908 |
| |
| 1999/0907 | if(c->ref == 0) { switch(c->state) { default: | |
| 1999/0910/sys/src/9/port/devsdp.c:429,434 – 1999/0914/sys/src/9/port/devsdp.c:430,436 | ||
| 1999/0907 | b = readcontrol(sdp->conv[CONV(ch->qid)], n); if(b == nil) return 0; | |
| 1999/0914 | print("readcontrol asked %ld got %ld\n", n, BLEN(b)); | |
| 1999/0907 | if(BLEN(b) < n) n = BLEN(b); memmove(a, b->rp, n); | |
| 1999/0910/sys/src/9/port/devsdp.c:435,440 – 1999/0914/sys/src/9/port/devsdp.c:437,443 | ||
| 1999/0907 | freeb(b); return n; case Qdata: | |
| 1999/0914 | print("readdata\n"); | |
| 1999/0907 | b = readdata(sdp->conv[CONV(ch->qid)], n); if(b == nil) return 0; | |
| 1999/0910/sys/src/9/port/devsdp.c:456,461 – 1999/0914/sys/src/9/port/devsdp.c:459,465 | ||
| 1999/0907 | return readdata(sdp->conv[CONV(ch->qid)], n); } | |
| 1999/0914 | ||
| 1999/0824 | static long | |
| 1999/0901 | sdpwrite(Chan *ch, void *a, long n, vlong off) | |
| 1999/0824 | { | |
| 1999/0910/sys/src/9/port/devsdp.c:471,477 – 1999/0914/sys/src/9/port/devsdp.c:475,480 | ||
| 1999/0824 | error(Eperm); case Qctl: | |
| 1999/0906 | c = sdp->conv[CONV(ch->qid)]; | |
| 1999/0824 | cb = parsecmd(a, n); | |
| 1999/0906 | qlock(c); | |
| 1999/0824 | if(waserror()) { | |
| 1999/0910/sys/src/9/port/devsdp.c:482,504 – 1999/0914/sys/src/9/port/devsdp.c:485,498 | ||
| 1999/0824 | if(cb->nf == 0) error("short write"); arg0 = cb->f[0]; | |
| 1999/0901 |
| |
| 1999/0910 | if(strcmp(arg0, "accept") == 0) { | |
| 1999/0906 | if(cb->nf != 2) | |
| 1999/0910 | error("usage: accect file"); | |
| 1999/0906 |
| |
| 1999/0910 |
| |
| 1999/0906 |
| |
| 1999/0910 |
| |
| 1999/0914 | convopenchan(c, cb->f[1]); | |
| 1999/0906 | } else if(strcmp(arg0, "dial") == 0) { | |
| 1999/0910 | if(cb->nf != 2) error("usage: accect file"); | |
| 1999/0914 | convopenchan(c, cb->f[1]); | |
| 1999/0909 | convsetstate(c, CDial); | |
| 1999/0906 | } else if(strcmp(arg0, "drop") == 0) { if(cb->nf != 2) | |
| 1999/0910/sys/src/9/port/devsdp.c:517,522 – 1999/0914/sys/src/9/port/devsdp.c:511,520 | ||
| 1999/0824 | if(p != nil) error(p); return n; | |
| 1999/0914 | case Qcontrol: print("writecontrol %ld\n", n); writecontrol(sdp->conv[CONV(ch->qid)], a, n); return n; | |
| 1999/0824 | } } | |
| 1999/0910/sys/src/9/port/devsdp.c:608,617 – 1999/0914/sys/src/9/port/devsdp.c:606,611 | ||
| 1999/0901 | ||
| 1999/0902 | c->ref++; | |
| 1999/0906 | c->state = CInit; | |
| 1999/0910 |
| |
| 1999/0907 | strncpy(c->owner, up->user, sizeof(c->owner)); | |
| 1999/0901 | c->perm = 0660; qunlock(c); | |
| 1999/0910/sys/src/9/port/devsdp.c:630,640 – 1999/0914/sys/src/9/port/devsdp.c:624,637 | ||
| 1999/0909 | // assume c is locked | |
| 1999/0906 | static int | |
| 1999/0914 | convretry(Conv *c, int reset) | |
| 1999/0906 | { c->retries++; | |
| 1999/0914 | print("convretry: %s: %d\n", convstatename[c->state], c->retries); | |
| 1999/0909 | if(c->retries > MaxRetries) { | |
| 1999/0906 | print("convretry: giving up\n"); | |
| 1999/0914 | if(reset) convoput2(c, ConReset, c->dialid, c->acceptid); | |
| 1999/0906 | convsetstate(c, CClosed); return 0; } | |
| 1999/0910/sys/src/9/port/devsdp.c:645,650 – 1999/0914/sys/src/9/port/devsdp.c:642,649 | ||
| 1999/0902 | static void | |
| 1999/0906 | convtimer(Conv *c, ulong sec) | |
| 1999/0902 | { | |
| 1999/0914 | Block *b; | |
| 1999/0906 | if(c->timeout == 0 || c->timeout > sec) return; | |
| 1999/0902 | qlock(c); | |
| 1999/0910/sys/src/9/port/devsdp.c:652,677 – 1999/0914/sys/src/9/port/devsdp.c:651,685 | ||
| 1999/0902 | qunlock(c); | |
| 1999/0906 | nexterror(); | |
| 1999/0902 | } | |
| 1999/0909 |
| |
| 1999/0906 | switch(c->state) { | |
| 1999/0909 | case CDial: | |
| 1999/0906 |
| |
| 1999/0914 | if(convretry(c, 1)) | |
| 1999/0909 | convoput2(c, ConOpenRequest, c->dialid, 0); | |
| 1999/0906 | break; | |
| 1999/0909 | case CAccept: | |
| 1999/0914 | if(convretry(c, 1)) | |
| 1999/0909 | convoput2(c, ConOpenAck, c->dialid, c->acceptid); | |
| 1999/0910 |
| |
| 1999/0909 | break; | |
| 1999/0906 | case COpen: | |
| 1999/0909 |
| |
| 1999/0914 | b = c->out.controlpkt; if(b != nil) { if(convretry(c, 1)) convoput(c, TControl, copyblock(b, blocklen(b))); } else { c->timeout = 0; } // keepalive | |
| 1999/0906 | break; | |
| 1999/0910 | case CLocalClose: | |
| 1999/0906 |
| |
| 1999/0914 | if(convretry(c, 0)) | |
| 1999/0907 | convoput2(c, ConClose, c->dialid, c->acceptid); | |
| 1999/0906 | break; | |
| 1999/0914 | case CRemoteClose: case CClosed: c->timeout = 0; break; | |
| 1999/0906 | } | |
| 1999/0914 | poperror(); | |
| 1999/0906 | qunlock(c); } | |
| 1999/0902 | ||
| 1999/0910/sys/src/9/port/devsdp.c:756,764 – 1999/0914/sys/src/9/port/devsdp.c:764,774 | ||
| 1999/0907 | convoput2(c, ConClose, c->dialid, c->acceptid); | |
| 1999/0906 | break; | |
| 1999/0910 | case CRemoteClose: | |
| 1999/0914 | wakeup(&c->in.controlready); | |
| 1999/0910 | convoput2(c, ConReset, c->dialid, c->acceptid); break; | |
| 1999/0906 | case CClosed: | |
| 1999/0914 | wakeup(&c->in.controlready); | |
| 1999/0907 | if(c->readproc) postnote(c->readproc, 1, "interrupt", 0); if(c->ref) | |
| 1999/0910/sys/src/9/port/devsdp.c:801,806 – 1999/0914/sys/src/9/port/devsdp.c:811,836 | ||
| 1999/0907 | } | |
| 1999/0906 | ||
| 1999/0907 | ||
| 1999/0914 | // 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(); } | |
| 1999/0907 | // assume we hold lock for c | |
| 1999/0910/sys/src/9/port/devsdp.c:825,830 – 1999/0914/sys/src/9/port/devsdp.c:855,861 | ||
| 1999/0907 | b->rp += 4; USED(seq); | |
| 1999/0914 | print("coniput seq=%ulx\n", seq); | |
| 1999/0907 | // auth // decrypt | |
| 1999/0910/sys/src/9/port/devsdp.c:836,854 – 1999/0914/sys/src/9/port/devsdp.c:867,889 | ||
| 1999/0907 | break; cseq = nhgetl(b->rp); if(cseq == c->in.controlseq) { | |
| 1999/0914 | print("duplicate control packet: %ulx\n", cseq); | |
| 1999/0907 | // duplicate control packet | |
| 1999/0914 | if(c->in.controlpkt == nil) { // send ack b->wp = b->rp + 4; convoput(c, TControlAck, b); } else freeb(b); | |
| 1999/0907 | return nil; } if(cseq != c->in.controlseq+1) break; | |
| 1999/0914 | print("recv %ld size=%ld\n", cseq, BLEN(b)); | |
| 1999/0907 | wakeup(&c->in.controlready); return nil; case TControlAck: | |
| 1999/0910/sys/src/9/port/devsdp.c:855,865 – 1999/0914/sys/src/9/port/devsdp.c:890,901 | ||
| 1999/0907 | if(BLEN(b) != 4) break; cseq = nhgetl(b->rp); | |
| 1999/0914 | print("ControlAck expected %ulx got %ulx\n", c->out.controlseq, cseq); | |
| 1999/0907 | if(cseq != c->out.controlseq) break; freeb(b); freeb(c->out.controlpkt); | |
| 1999/0914 | c->out.controlpkt = nil; | |
| 1999/0907 | wakeup(&c->out.controlready); return nil; case TData: | |
| 1999/0910/sys/src/9/port/devsdp.c:888,893 – 1999/0914/sys/src/9/port/devsdp.c:924,931 | ||
| 1999/0907 | dialid = nhgetl(con->dialid); acceptid = nhgetl(con->acceptid); | |
| 1999/0914 | print("conviput2: %s: %d %uld %uld\n", convstatename[c->state], con->op, dialid, acceptid); | |
| 1999/0910 | switch(c->state) { default: panic("unknown state: %d", c->state); | |
| 1999/0910/sys/src/9/port/devsdp.c:909,915 – 1999/0914/sys/src/9/port/devsdp.c:947,952 | ||
| 1999/0910 | } | |
| 1999/0907 | switch(con->op) { | |
| 1999/0909 | case ConOpenRequest: switch(c->state) { | |
| 1999/0910/sys/src/9/port/devsdp.c:977,982 – 1999/0914/sys/src/9/port/devsdp.c:1014,1020 | ||
| 1999/0907 | } | |
| 1999/0910 | Reset: // invalid connection message - reset to sender | |
| 1999/0914 | print("invalid conviput2 - sending reset\n"); | |
| 1999/0910 | convoput2(c, ConReset, dialid, acceptid); | |
| 1999/0907 | } | |
| 1999/0910/sys/src/9/port/devsdp.c:1067,1073 – 1999/0914/sys/src/9/port/devsdp.c:1105,1111 | ||
| 1999/0907 | { Conv *c = a; | |
| 1999/0910 |
| |
| 1999/0914 | return c->in.controlpkt != nil || (c->state == CClosed) || (c->state == CRemoteClose); | |
| 1999/0907 | } static Block * | |
| 1999/0910/sys/src/9/port/devsdp.c:1076,1101 – 1999/0914/sys/src/9/port/devsdp.c:1114,1193 | ||
| 1999/0907 | Block *b; | |
| 1999/0910 | USED(n); | |
| 1999/0914 | qlock(c); | |
| 1999/0907 | for(;;) { | |
| 1999/0910 | if(c->state == CInit || c->state == CClosed) { | |
| 1999/0907 | qunlock(c); | |
| 1999/0914 | print("readcontrol: return error - state = %s\n", convstatename[c->state]); error("conversation closed"); | |
| 1999/0907 | } | |
| 1999/0914 | if(c->in.controlpkt != nil) break; if(c->state == CRemoteClose) { | |
| 1999/0907 | qunlock(c); | |
| 1999/0914 | print("readcontrol: return nil - state = %s\n", convstatename[c->state]); return nil; | |
| 1999/0907 | } qunlock(c); | |
| 1999/0910 | sleep(&c->in.controlready, readready, c); | |
| 1999/0914 | qlock(c); | |
| 1999/0907 | } | |
| 1999/0910 |
| |
| 1999/0914 | // 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; | |
| 1999/0907 | } | |
| 1999/0914 | 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); } | |
| 1999/0907 | static Block * readdata(Conv *c, int n) { | |
| 1999/0910/sys/src/9/port/devsdp.c:1122,1127 – 1999/0914/sys/src/9/port/devsdp.c:1214,1220 | ||
| 1999/0910 | Conv *c = a; Block *b; | |
| 1999/0914 | print("convreader\n"); | |
| 1999/0910 | qlock(c); assert(c->reader == 1); while(c->dataopen == 0) { | |
| 1999/0910/sys/src/9/port/devsdp.c:1141,1146 – 1999/0914/sys/src/9/port/devsdp.c:1234,1240 | ||
| 1999/0910 | poperror(); } } | |
| 1999/0914 | print("convreader exiting\n"); | |
| 1999/0910 | c->reader = 0; qunlock(c); pexit("hangup", 1); | |
| 1999/0914/sys/src/9/port/devsdp.c:51,56 – 1999/0915/sys/src/9/port/devsdp.c:51,57 (short | long) | ||
| 1999/0901 | ulong seq; | |
| 1999/0907 | ulong window; | |
| 1999/0901 | ||
| 1999/0915 | QLock controllk; | |
| 1999/0907 | Rendez controlready; | |
| 1999/0902 | Block *controlpkt; // control channel | |
| 1999/0907 | ulong controlseq; | |
| 1999/0914/sys/src/9/port/devsdp.c:206,211 – 1999/0915/sys/src/9/port/devsdp.c:207,213 | ||
| 1999/0914 | static void writecontrol(Conv *c, void *p, int n); | |
| 1999/0907 | static Block *readcontrol(Conv *c, int n); static Block *readdata(Conv *c, int n); | |
| 1999/0915 | static long writedata(Conv *c, Block *b); | |
| 1999/0907 | static void convoput(Conv *c, int type, Block *b); static void convoput2(Conv *c, int op, ulong dialid, ulong acceptid); | |
| 1999/0910 | static void convreader(void *a); | |
| 1999/0914/sys/src/9/port/devsdp.c:377,384 – 1999/0915/sys/src/9/port/devsdp.c:379,388 | ||
| 1999/0907 | c->ref--; if(TYPE(ch->qid) == Qdata) { c->dataopen--; | |
| 1999/0915 | if(c->dataopen == 0 && c->reader == 0) { kproc("convreader", convreader, c); c->reader = 1; } | |
| 1999/0907 | } if(c->ref == 0) { switch(c->state) { | |
| 1999/0914/sys/src/9/port/devsdp.c:468,473 – 1999/0915/sys/src/9/port/devsdp.c:472,478 | ||
| 1999/0824 | char *arg0; char *p; | |
| 1999/0906 | Conv *c; | |
| 1999/0915 | Block *b; | |
| 1999/0824 | USED(off); | |
| 1999/0901 | switch(TYPE(ch->qid)) { | |
| 1999/0914/sys/src/9/port/devsdp.c:515,523 – 1999/0915/sys/src/9/port/devsdp.c:520,543 | ||
| 1999/0914 | print("writecontrol %ld\n", n); writecontrol(sdp->conv[CONV(ch->qid)], a, n); return n; | |
| 1999/0915 | case Qdata: b = allocb(n); memmove(b->wp, a, n); b->wp += n; return writedata(sdp->conv[CONV(ch->qid)], b); | |
| 1999/0824 | } } | |
| 1999/0915 | 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); } | |
| 1999/0824 | static int sdpgen(Chan *c, Dirtab*, int, int s, Dir *dp) { | |
| 1999/0914/sys/src/9/port/devsdp.c:769,782 – 1999/0915/sys/src/9/port/devsdp.c:789,804 | ||
| 1999/0910 | break; | |
| 1999/0906 | case CClosed: | |
| 1999/0914 | wakeup(&c->in.controlready); | |
| 1999/0915 | wakeup(&c->out.controlready); | |
| 1999/0907 | if(c->readproc) postnote(c->readproc, 1, "interrupt", 0); | |
| 1999/0915 | print("CClosed -> ref = %d\n", c->ref); | |
| 1999/0907 | if(c->chan) { cclose(c->chan); c->chan = nil; } | |
| 1999/0915 | if(c->ref) break; | |
| 1999/0910 | if(c->channame) { free(c->channame); c->channame = nil; | |
| 1999/0914/sys/src/9/port/devsdp.c:815,821 – 1999/0915/sys/src/9/port/devsdp.c:837,843 | ||
| 1999/0914 | static void convopenchan(Conv *c, char *path) { | |
| 1999/0915 | if(c->state != CInit || c->chan != nil) | |
| 1999/0914 | error("already connected"); c->chan = namec(path, Aopen, ORDWR, 0); c->channame = malloc(strlen(path)+1); | |
| 1999/0914/sys/src/9/port/devsdp.c:1042,1047 – 1999/0915/sys/src/9/port/devsdp.c:1064,1070 | ||
| 1999/0907 | // simulated errors if(c->drop && c->drop > nrand(c->drop)) return; | |
| 1999/0915 | print("convoput\n"); | |
| 1999/0907 | devtab[c->chan->type]->bwrite(c->chan, b, 0); } | |
| 1999/0914/sys/src/9/port/devsdp.c:1114,1120 – 1999/0915/sys/src/9/port/devsdp.c:1137,1150 | ||
| 1999/0907 | Block *b; | |
| 1999/0910 | USED(n); | |
| 1999/0914 |
| |
| 1999/0915 | qlock(&c->in.controllk); if(waserror()) { qunlock(&c->in.controllk); nexterror(); } qlock(c); // this lock is not held during the sleep below | |
| 1999/0907 | for(;;) { | |
| 1999/0910 | if(c->state == CInit || c->state == CClosed) { | |
| 1999/0907 | qunlock(c); | |
| 1999/0914/sys/src/9/port/devsdp.c:1128,1133 – 1999/0915/sys/src/9/port/devsdp.c:1158,1164 | ||
| 1999/0914 | if(c->state == CRemoteClose) { | |
| 1999/0907 | qunlock(c); | |
| 1999/0914 | print("readcontrol: return nil - state = %s\n", convstatename[c->state]); | |
| 1999/0915 | poperror(); | |
| 1999/0914 | return nil; | |
| 1999/0907 | } qunlock(c); | |
| 1999/0914/sys/src/9/port/devsdp.c:1144,1149 – 1999/0915/sys/src/9/port/devsdp.c:1175,1182 | ||
| 1999/0914 | b = c->in.controlpkt; c->in.controlpkt = nil; qunlock(c); | |
| 1999/0915 | poperror(); qunlock(&c->in.controllk); | |
| 1999/0914 | return b; | |
| 1999/0907 | } | |
| 1999/0914/sys/src/9/port/devsdp.c:1161,1167 – 1999/0915/sys/src/9/port/devsdp.c:1194,1206 | ||
| 1999/0914 | { Block *b; | |
| 1999/0915 | qlock(&c->out.controllk); if(waserror()) { qunlock(&c->out.controllk); nexterror(); } qlock(c); // this lock is not held in the sleep below | |
| 1999/0914 | for(;;) { if(c->state == CInit || c->state == CClosed || c->state == CRemoteClose) { qunlock(c); | |
| 1999/0914/sys/src/9/port/devsdp.c:1186,1191 – 1999/0915/sys/src/9/port/devsdp.c:1225,1232 | ||
| 1999/0914 | print("send %ld size=%ld\n", c->out.controlseq, BLEN(b)); convoput(c, TControl, copyblock(b, blocklen(b))); qunlock(c); | |
| 1999/0915 | poperror(); qunlock(&c->out.controllk); | |
| 1999/0914 | } | |
| 1999/0907 | static Block * | |
| 1999/0914/sys/src/9/port/devsdp.c:1208,1213 – 1999/0915/sys/src/9/port/devsdp.c:1249,1278 | ||
| 1999/0907 | } | |
| 1999/0910 | } | |
| 1999/0915 | 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; } | |
| 1999/0910 | static void convreader(void *a) { | |
| 1999/0914/sys/src/9/port/devsdp.c:1217,1223 – 1999/0915/sys/src/9/port/devsdp.c:1282,1288 | ||
| 1999/0914 | print("convreader\n"); | |
| 1999/0910 | qlock(c); assert(c->reader == 1); | |
| 1999/0915 | while(c->dataopen == 0 && c->state != CClosed) { | |
| 1999/0910 | qunlock(c); b = nil; if(!waserror()) { | |
| 1999/0914/sys/src/9/port/devsdp.c:1226,1235 – 1999/0915/sys/src/9/port/devsdp.c:1291,1305 | ||
| 1999/0910 | } qlock(c); if(b == nil) { | |
| 1999/0915 | print("up->error = %s\n", up->error); if(strcmp(up->error, Eintr) != 0) { if(!waserror()) { convsetstate(c, CClosed); poperror(); } break; } } else if(!waserror()) { | |
| 1999/0910 | conviput(c, b, 1); poperror(); } | |
| 1999/0915/sys/src/9/port/devsdp.c:15,21 – 1999/0929/sys/src/9/port/devsdp.c:15,23 (short | long) | ||
| 1999/0902 | typedef struct Sdp Sdp; typedef struct Conv Conv; | |
| 1999/0907 | typedef struct OneWay OneWay; | |
| 1999/0929 | typedef struct Stats Stats; | |
| 1999/0907 | typedef struct ConnectPkt ConnectPkt; | |
| 1999/0929 | typedef struct AckPkt AckPkt; | |
| 1999/0824 | enum { | |
| 1999/0915/sys/src/9/port/devsdp.c:23,29 – 1999/0929/sys/src/9/port/devsdp.c:25,30 | ||
| 1999/0824 | Qsdpdir, /* sdp directory */ Qclone, | |
| 1999/0901 | Qconvdir, /* directory per conversation */ | |
| 1999/0915/sys/src/9/port/devsdp.c:31,36 – 1999/0929/sys/src/9/port/devsdp.c:32,39 | ||
| 1999/0902 | Qdata, /* unreliable packet channel */ Qcontrol, /* reliable control channel */ | |
| 1999/0824 | Qstatus, | |
| 1999/0929 | Qstats, Qrstats, | |
| 1999/0824 | MaxQ, | |
| 1999/0915/sys/src/9/port/devsdp.c:45,52 – 1999/0929/sys/src/9/port/devsdp.c:48,75 | ||
| 1999/0901 | #define CONV(x) (((x).path >> 8)&(Maxconv-1)) | |
| 1999/0824 | #define QID(x, y) (((x)<<8) | (y)) | |
| 1999/0929 | 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; }; | |
| 1999/0907 | struct OneWay | |
| 1999/0901 | { | |
| 1999/0929 | Rendez statsready; | |
| 1999/0901 | ulong seqwrap; // number of wraps of the sequence number ulong seq; | |
| 1999/0907 | ulong window; | |
| 1999/0915/sys/src/9/port/devsdp.c:90,95 – 1999/0929/sys/src/9/port/devsdp.c:113,121 | ||
| 1999/0906 | int dataopen; | |
| 1999/0910 | int reader; // reader proc has been started | |
| 1999/0901 | ||
| 1999/0929 | Stats lstats; Stats rstats; | |
| 1999/0906 | ulong timeout; int retries; | |
| 1999/0915/sys/src/9/port/devsdp.c:149,157 – 1999/0929/sys/src/9/port/devsdp.c:175,200 | ||
| 1999/0906 | uchar acceptid[4]; }; | |
| 1999/0929 | 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]; }; | |
| 1999/0907 | ||
| 1999/0929 | ||
| 1999/0824 | static Dirtab sdpdirtab[]={ | |
| 1999/0901 | "clone", {Qclone}, 0, 0666, | |
| 1999/0824 | }; | |
| 1999/0915/sys/src/9/port/devsdp.c:161,166 – 1999/0929/sys/src/9/port/devsdp.c:204,211 | ||
| 1999/0824 | "data", {Qdata}, 0, 0666, | |
| 1999/0902 | "control", {Qcontrol}, 0, 0666, | |
| 1999/0824 | "status", {Qstatus}, 0, 0444, | |
| 1999/0929 | "stats", {Qstats}, 0, 0444, "rstats", {Qrstats}, 0, 0444, | |
| 1999/0824 | }; static int m2p[] = { | |
| 1999/0915/sys/src/9/port/devsdp.c:204,210 – 1999/0929/sys/src/9/port/devsdp.c:249,255 | ||
| 1999/0907 | static int controlread(); static Block *conviput(Conv *c, Block *b, int control); static void conviput2(Conv *c, Block *b); | |
| 1999/0914 |
| |
| 1999/0929 | static void writecontrol(Conv *c, void *p, int n, int wait); | |
| 1999/0907 | static Block *readcontrol(Conv *c, int n); static Block *readdata(Conv *c, int n); | |
| 1999/0915 | static long writedata(Conv *c, Block *b); | |
| 1999/0915/sys/src/9/port/devsdp.c:212,219 – 1999/0929/sys/src/9/port/devsdp.c:257,264 | ||
| 1999/0907 | static void convoput2(Conv *c, int op, ulong dialid, ulong acceptid); | |
| 1999/0910 | static void convreader(void *a); | |
| 1999/0914 | static void convopenchan(Conv *c, char *path); | |
| 1999/0929 | static void convstats(Conv *c, int local, char *buf, int n); | |
| 1999/0824 | ||
| 1999/0907 | ||
| 1999/0824 | static void sdpinit(void) { | |
| 1999/0915/sys/src/9/port/devsdp.c:310,316 – 1999/0929/sys/src/9/port/devsdp.c:355,360 | ||
| 1999/0824 | case Qtopdir: case Qsdpdir: | |
| 1999/0901 | case Qconvdir: | |
| 1999/0824 |
| |
| 1999/0915/sys/src/9/port/devsdp.c:327,332 – 1999/0929/sys/src/9/port/devsdp.c:371,378 | ||
| 1999/0902 | case Qctl: case Qstatus: case Qcontrol: | |
| 1999/0929 | case Qstats: case Qrstats: | |
| 1999/0902 | c = sdp->conv[CONV(ch->qid)]; qlock(c); if(waserror()) { | |
| 1999/0915/sys/src/9/port/devsdp.c:407,415 – 1999/0929/sys/src/9/port/devsdp.c:453,463 | ||
| 1999/0901 | sdpread(Chan *ch, void *a, long n, vlong off) | |
| 1999/0824 | { char buf[256]; | |
| 1999/0929 | char *s; | |
| 1999/0901 | Sdp *sdp = sdptab + ch->dev; Conv *c; | |
| 1999/0907 | Block *b; | |
| 1999/0929 | int rv; | |
| 1999/0824 | USED(off); | |
| 1999/0901 | switch(TYPE(ch->qid)) { | |
| 1999/0915/sys/src/9/port/devsdp.c:450,455 – 1999/0929/sys/src/9/port/devsdp.c:498,511 | ||
| 1999/0907 | memmove(a, b->rp, n); freeb(b); return n; | |
| 1999/0929 | 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; | |
| 1999/0824 | } } | |
| 1999/0915/sys/src/9/port/devsdp.c:518,524 – 1999/0929/sys/src/9/port/devsdp.c:574,580 | ||
| 1999/0824 | return n; | |
| 1999/0914 | case Qcontrol: print("writecontrol %ld\n", n); | |
| 1999/0929 | writecontrol(sdp->conv[CONV(ch->qid)], a, n, 0); | |
| 1999/0914 | return n; | |
| 1999/0915 | case Qdata: b = allocb(n); | |
| 1999/0915/sys/src/9/port/devsdp.c:854,860 – 1999/0929/sys/src/9/port/devsdp.c:910,979 | ||
| 1999/0914 | poperror(); } | |
| 1999/0907 | ||
| 1999/0929 | static void convstats(Conv *c, int local, char *buf, int n) { Stats *stats; char *p, *ep; | |
| 1999/0907 | ||
| 1999/0929 | 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); } | |
| 1999/0907 | // assume we hold lock for c static Block * conviput(Conv *c, Block *b, int control) | |
| 1999/0915/sys/src/9/port/devsdp.c:861,867 – 1999/0929/sys/src/9/port/devsdp.c:980,989 | ||
| 1999/0907 | { int type; ulong seq, cseq; | |
| 1999/0929 | AckPkt *ack; | |
| 1999/0907 | ||
| 1999/0929 | c->lstat.inPackets++; | |
| 1999/0907 | if(BLEN(b) < 4) { freeb(b); return nil; | |
| 1999/0915/sys/src/9/port/devsdp.c:885,902 – 1999/0929/sys/src/9/port/devsdp.c:1007,1021 | ||
| 1999/0907 | switch(type) { case TControl: | |
| 1999/0929 | if(BLEN(b) < 4) | |
| 1999/0907 | break; cseq = nhgetl(b->rp); if(cseq == c->in.controlseq) { | |
| 1999/0914 | print("duplicate control packet: %ulx\n", cseq); | |
| 1999/0907 | // duplicate control packet | |
| 1999/0914 |
| |
| 1999/0929 | freeb(b); if(c->in.controlpkt == nil) convack(c); | |
| 1999/0907 | return nil; } | |
| 1999/0915/sys/src/9/port/devsdp.c:904,920 – 1999/0929/sys/src/9/port/devsdp.c:1023,1059 | ||
| 1999/0907 | break; c->in.controlseq = cseq; b->rp += 4; | |
| 1999/0929 | if(BLEN(b) == 0) { // just a ping freeb(b); convack(c); } else { c->in.controlpkt = b; | |
| 1999/0914 | print("recv %ld size=%ld\n", cseq, BLEN(b)); | |
| 1999/0907 |
| |
| 1999/0929 | wakeup(&c->in.controlready); } | |
| 1999/0907 | return nil; case TControlAck: | |
| 1999/0929 | if(BLEN(b) != sizeof(AckPkt)) | |
| 1999/0907 | break; | |
| 1999/0929 | ack = (AckPkt*)(b->rp); cseq = nhgetl(ack->cseq); | |
| 1999/0914 | print("ControlAck expected %ulx got %ulx\n", c->out.controlseq, cseq); | |
| 1999/0907 | if(cseq != c->out.controlseq) break; | |
| 1999/0929 | 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); | |
| 1999/0907 | freeb(b); freeb(c->out.controlpkt); | |
| 1999/0914 | c->out.controlpkt = nil; | |
| 1999/0915/sys/src/9/port/devsdp.c:921,926 – 1999/0929/sys/src/9/port/devsdp.c:1060,1068 | ||
| 1999/0907 | wakeup(&c->out.controlready); return nil; case TData: | |
| 1999/0929 | c->lstats.inDataPackets++; c->lstats.inDataBytes += BLEN(b); c->lstats.inCompDataBytes += BLEN(b); | |
| 1999/0907 | if(control) break; return b; | |
| 1999/0915/sys/src/9/port/devsdp.c:1045,1051 – 1999/0929/sys/src/9/port/devsdp.c:1187,1193 | ||
| 1999/0907 | convoput(Conv *c, int type, Block *b) { // try and compress | |
| 1999/0929 | c->lstats.outPackets++; | |
| 1999/0907 | /* Make space to fit sdp header */ b = padblock(b, 4 + c->out.cipherivlen); b->rp[0] = type; | |
| 1999/0915/sys/src/9/port/devsdp.c:1074,1079 – 1999/0929/sys/src/9/port/devsdp.c:1216,1222 | ||
| 1999/0907 | { ConnectPkt con; | |
| 1999/0929 | c->lstats.outPackets++; | |
| 1999/0906 | if(c->chan == nil) { print("chan = nil\n"); error("no channel attached"); | |
| 1999/0915/sys/src/9/port/devsdp.c:1166,1176 – 1999/0929/sys/src/9/port/devsdp.c:1309,1315 | ||
| 1999/0914 | qlock(c); | |
| 1999/0907 | } | |
| 1999/0914 |
| |
| 1999/0929 | convack(c); | |
| 1999/0914 | b = c->in.controlpkt; c->in.controlpkt = nil; | |
| 1999/0915/sys/src/9/port/devsdp.c:1189,1209 – 1999/0929/sys/src/9/port/devsdp.c:1328,1339 | ||
| 1999/0914 | return c->out.controlpkt == nil || (c->state == CClosed) || (c->state == CRemoteClose); } | |
| 1999/0929 | // c is locked | |
| 1999/0914 | static void | |
| 1999/0929 | writewait(Conv *c) | |
| 1999/0914 | { | |
| 1999/0915 |
| |
| 1999/0914 | for(;;) { if(c->state == CInit || c->state == CClosed || c->state == CRemoteClose) { | |
| 1999/0915/sys/src/9/port/devsdp.c:1212,1220 – 1999/0929/sys/src/9/port/devsdp.c:1342,1371 | ||
| 1999/0914 | break; qunlock(c); | |
| 1999/0929 | if(waserror()) { qlock(c); nexterror(); } | |
| 1999/0914 | sleep(&c->out.controlready, writeready, c); | |
| 1999/0929 | poperror(); | |
| 1999/0914 | qlock(c); } | |
| 1999/0929 | } 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); | |
| 1999/0914 | b = allocb(4+n); c->out.controlseq++; hnputl(b->wp, c->out.controlseq); | |
| 1999/0915/sys/src/9/port/devsdp.c:1224,1231 – 1999/0929/sys/src/9/port/devsdp.c:1375,1384 | ||
| 1999/0914 | convretryinit(c); print("send %ld size=%ld\n", c->out.controlseq, BLEN(b)); convoput(c, TControl, copyblock(b, blocklen(b))); | |
| 1999/0929 | if(wait) writewait(c); | |
| 1999/0915 | poperror(); | |
| 1999/0929 | qunlock(c); | |
| 1999/0915 | qunlock(&c->out.controllk); | |
| 1999/0914 | } | |
| 1999/0915/sys/src/9/port/devsdp.c:1267,1272 – 1999/0929/sys/src/9/port/devsdp.c:1420,1428 | ||
| 1999/0915 | } n = BLEN(b); | |
| 1999/0929 | c->outDataPackets++; c->outDataBytes += n; c->outCompDataBytes += n; | |
| 1999/0915 | convoput(c, TData, b); poperror(); qunlock(c); | |
| 1999/0929/sys/src/9/port/devsdp.c:489,495 – 1999/0930/sys/src/9/port/devsdp.c:489,494 (short | long) | ||
| 1999/0907 | freeb(b); return n; case Qdata: | |
| 1999/0914 |
| |
| 1999/0907 | b = readdata(sdp->conv[CONV(ch->qid)], n); if(b == nil) return 0; | |
| 1999/0929/sys/src/9/port/devsdp.c:916,922 – 1999/0930/sys/src/9/port/devsdp.c:915,920 | ||
| 1999/0929 | Stats *stats; char *p, *ep; | |
| 1999/0907 | ||
| 1999/0929 |
| |
| 1999/0929/sys/src/9/port/devsdp.c:926,931 – 1999/0930/sys/src/9/port/devsdp.c:924,931 | ||
| 1999/0929 | } stats = &c->rstats; } | |
| 1999/0930 | qlock(c); | |
| 1999/0929 | p = buf; ep = buf + n; p += snprint(p, ep-p, "outPackets: %ld\n", stats->outPackets); | |
| 1999/0929/sys/src/9/port/devsdp.c:934,939 – 1999/0930/sys/src/9/port/devsdp.c:934,940 | ||
| 1999/0929 | 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); | |
| 1999/0930 | p += snprint(p, ep-p, "inDataBytes: %ld\n", stats->inDataBytes); | |
| 1999/0929 | 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); | |
| 1999/0929/sys/src/9/port/devsdp.c:953,959 – 1999/0930/sys/src/9/port/devsdp.c:954,960 | ||
| 1999/0929 | Stats *s; b = allocb(sizeof(AckPkt)); | |
| 1999/0930 | ack = (AckPkt*)b->wp; | |
| 1999/0929 | b->wp += sizeof(AckPkt); s = &c->lstats; hnputl(ack->cseq, c->in.controlseq); | |
| 1999/0929/sys/src/9/port/devsdp.c:982,988 – 1999/0930/sys/src/9/port/devsdp.c:983,989 | ||
| 1999/0907 | ulong seq, cseq; | |
| 1999/0929 | AckPkt *ack; | |
| 1999/0907 | ||
| 1999/0929 |
| |
| 1999/0930 | c->lstats.inPackets++; | |
| 1999/0929 | ||
| 1999/0907 | if(BLEN(b) < 4) { freeb(b); | |
| 1999/0929/sys/src/9/port/devsdp.c:999,1005 – 1999/0930/sys/src/9/port/devsdp.c:1000,1006 | ||
| 1999/0907 | b->rp += 4; USED(seq); | |
| 1999/0914 |
| |
| 1999/0930 | if(0) print("coniput seq=%ulx\n", seq); | |
| 1999/0907 | // auth // decrypt | |
| 1999/0929/sys/src/9/port/devsdp.c:1029,1035 – 1999/0930/sys/src/9/port/devsdp.c:1030,1036 | ||
| 1999/0929 | convack(c); } else { c->in.controlpkt = b; | |
| 1999/0914 |
| |
| 1999/0930 | if(0) print("recv %ld size=%ld\n", cseq, BLEN(b)); | |
| 1999/0929 | wakeup(&c->in.controlready); } | |
| 1999/0907 | return nil; | |
| 1999/0929/sys/src/9/port/devsdp.c:1038,1059 – 1999/0930/sys/src/9/port/devsdp.c:1039,1061 | ||
| 1999/0907 | break; | |
| 1999/0929 | ack = (AckPkt*)(b->rp); cseq = nhgetl(ack->cseq); | |
| 1999/0930 | if(cseq != c->out.controlseq) { | |
| 1999/0914 | print("ControlAck expected %ulx got %ulx\n", c->out.controlseq, cseq); | |
| 1999/0907 |
| |
| 1999/0929 |
| |
| 1999/0930 | } 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); | |
| 1999/0907 | freeb(b); freeb(c->out.controlpkt); | |
| 1999/0914 | c->out.controlpkt = nil; | |
| 1999/0929/sys/src/9/port/devsdp.c:1182,1187 – 1999/0930/sys/src/9/port/devsdp.c:1184,1206 | ||
| 1999/0910 | convoput2(c, ConReset, dialid, acceptid); | |
| 1999/0907 | } | |
| 1999/0930 | // 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(); } | |
| 1999/0907 | // assume hold conv lock static void convoput(Conv *c, int type, Block *b) | |
| 1999/0929/sys/src/9/port/devsdp.c:1202,1213 – 1999/0930/sys/src/9/port/devsdp.c:1221,1228 | ||
| 1999/0907 | // encrypt // auth | |
| 1999/0915 |
| |
| 1999/0907 |
| |
| 1999/0930 | convwriteblock(c, b); | |
| 1999/0907 | } // assume hold conv lock | |
| 1999/0929/sys/src/9/port/devsdp.c:1214,1220 – 1999/0930/sys/src/9/port/devsdp.c:1229,1236 | ||
| 1999/0907 | static void convoput2(Conv *c, int op, ulong dialid, ulong acceptid) { | |
| 1999/0930 | Block *b; ConnectPkt *con; | |
| 1999/0907 | ||
| 1999/0929 | c->lstats.outPackets++; | |
| 1999/0906 | if(c->chan == nil) { | |
| 1999/0929/sys/src/9/port/devsdp.c:1221,1236 – 1999/0930/sys/src/9/port/devsdp.c:1237,1251 | ||
| 1999/0906 | print("chan = nil\n"); error("no channel attached"); } | |
| 1999/0930 | 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); | |
| 1999/0906 |
| |
| 1999/0930 | convwriteblock(c, b); | |
| 1999/0907 | } | |
| 1999/0910 | static Block * | |
| 1999/0929/sys/src/9/port/devsdp.c:1375,1382 – 1999/0930/sys/src/9/port/devsdp.c:1390,1399 | ||
| 1999/0914 | convretryinit(c); print("send %ld size=%ld\n", c->out.controlseq, BLEN(b)); convoput(c, TControl, copyblock(b, blocklen(b))); | |
| 1999/0929 |
| |
| 1999/0930 | if(wait) { print("writecontrol wait!\n"); | |
| 1999/0929 | writewait(c); | |
| 1999/0930 | } | |
| 1999/0915 | poperror(); | |
| 1999/0929 | qunlock(c); | |
| 1999/0915 | qunlock(&c->out.controllk); | |
| 1999/0929/sys/src/9/port/devsdp.c:1389,1394 – 1999/0930/sys/src/9/port/devsdp.c:1406,1413 | ||
| 1999/0907 | for(;;) { b = convreadblock(c, n); | |
| 1999/0930 | if(b == nil) return nil; | |
| 1999/0907 | qlock(c); if(waserror()) { qunlock(c); | |
| 1999/0929/sys/src/9/port/devsdp.c:1408,1414 – 1999/0930/sys/src/9/port/devsdp.c:1427,1432 | ||
| 1999/0915 | int n; qlock(c); | |
| 1999/0929/sys/src/9/port/devsdp.c:1420,1428 – 1999/0930/sys/src/9/port/devsdp.c:1438,1446 | ||
| 1999/0915 | } n = BLEN(b); | |
| 1999/0929 |
| |
| 1999/0930 | c->lstats.outDataPackets++; c->lstats.outDataBytes += n; c->lstats.outCompDataBytes += n; | |
| 1999/0915 | convoput(c, TData, b); poperror(); qunlock(c); | |
| 1999/0930/sys/src/9/port/devsdp.c:7,12 – 1999/1001/sys/src/9/port/devsdp.c:7,13 (short | long) | ||
| 1999/0824 | #include "../port/error.h" #include <libcrypt.h> | |
| 1999/1001 | #include "../port/thwack.h" | |
| 1999/0824 | ||
| 1999/0907 | /* * sdp - secure datagram protocol | |
| 1999/0930/sys/src/9/port/devsdp.c:18,23 – 1999/1001/sys/src/9/port/devsdp.c:19,25 | ||
| 1999/0929 | typedef struct Stats Stats; | |
| 1999/0907 | typedef struct ConnectPkt ConnectPkt; | |
| 1999/0929 | typedef struct AckPkt AckPkt; | |
| 1999/1001 | typedef struct Algorithm Algorithm; | |
| 1999/0824 | enum { | |
| 1999/0930/sys/src/9/port/devsdp.c:39,47 – 1999/1001/sys/src/9/port/devsdp.c:41,51 | ||
| 1999/0824 | ||
| 1999/0907 | Maxconv= 256, // power of 2 Nfs= 4, // number of file systems | |
| 1999/0914 |
| |
| 1999/1001 | MaxRetries= 8, | |
| 1999/0909 | KeepAlive = 60, // keep alive in seconds | |
| 1999/0907 | KeyLength= 32, | |
| 1999/1001 | SeqMax = (1<<24), SeqWindow = 32, | |
| 1999/0824 | }; #define TYPE(x) ((x).path & 0xff) | |
| 1999/0930/sys/src/9/port/devsdp.c:115,121 – 1999/1001/sys/src/9/port/devsdp.c:119,126 | ||
| 1999/0901 | ||
| 1999/0929 | Stats lstats; Stats rstats; | |
| 1999/1001 | ulong lastrecv; // time last packet was received | |
| 1999/0906 | ulong timeout; int retries; | |
| 1999/0930/sys/src/9/port/devsdp.c:133,138 – 1999/1001/sys/src/9/port/devsdp.c:138,146 | ||
| 1999/0901 | int perm; | |
| 1999/0907 | uchar masterkey[KeyLength]; | |
| 1999/1001 | char *authname; char *ciphername; char *compname; | |
| 1999/0907 | ||
| 1999/0906 | int drop; | |
| 1999/0930/sys/src/9/port/devsdp.c:193,198 – 1999/1001/sys/src/9/port/devsdp.c:201,212 | ||
| 1999/0929 | uchar inBadSeq[4]; }; | |
| 1999/0907 | ||
| 1999/1001 | struct Algorithm { char *name; int keylen; // in bytes void (*init)(Conv*, char* name, int keylen); }; | |
| 1999/0929 | ||
| 1999/0824 | static Dirtab sdpdirtab[]={ "log", {Qlog}, 0, 0666, | |
| 1999/0930/sys/src/9/port/devsdp.c:208,213 – 1999/1001/sys/src/9/port/devsdp.c:222,252 | ||
| 1999/0929 | "rstats", {Qrstats}, 0, 0444, | |
| 1999/0824 | }; | |
| 1999/1001 | #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 | |
| 1999/0824 | static int m2p[] = { [OREAD] 4, [OWRITE] 2, | |
| 1999/0930/sys/src/9/port/devsdp.c:572,578 – 1999/1001/sys/src/9/port/devsdp.c:611,616 | ||
| 1999/0824 | error(p); return n; | |
| 1999/0914 | case Qcontrol: | |
| 1999/0929 | writecontrol(sdp->conv[CONV(ch->qid)], a, n, 0); | |
| 1999/0914 | return n; | |
| 1999/0915 | case Qdata: | |
| 1999/0930/sys/src/9/port/devsdp.c:660,665 – 1999/1001/sys/src/9/port/devsdp.c:698,704 | ||
| 1999/0901 | c = malloc(sizeof(Conv)); if(c == nil) error(Enomem); | |
| 1999/1001 | memset(c, 0, sizeof(Conv)); | |
| 1999/0901 | qlock(c); c->sdp = sdp; c->id = pp - sdp->conv; | |
| 1999/0930/sys/src/9/port/devsdp.c:681,686 – 1999/1001/sys/src/9/port/devsdp.c:720,730 | ||
| 1999/0901 | ||
| 1999/0902 | c->ref++; | |
| 1999/0906 | c->state = CInit; | |
| 1999/1001 | c->in.window = ~0; c->in.compstate = malloc(sizeof(Unthwack)); unthwackinit(c->in.compstate); c->out.compstate = malloc(sizeof(Thwack)); thwackinit(c->out.compstate); | |
| 1999/0907 | strncpy(c->owner, up->user, sizeof(c->owner)); | |
| 1999/0901 | c->perm = 0660; qunlock(c); | |
| 1999/0930/sys/src/9/port/devsdp.c:719,725 – 1999/1001/sys/src/9/port/devsdp.c:763,769 | ||
| 1999/0902 | { | |
| 1999/0914 | Block *b; | |
| 1999/0906 |
| |
| 1999/1001 | if(c->timeout > sec) | |
| 1999/0906 | return; | |
| 1999/0902 | qlock(c); | |
| 1999/0906 | if(waserror()) { | |
| 1999/0930/sys/src/9/port/devsdp.c:740,749 – 1999/1001/sys/src/9/port/devsdp.c:784,810 | ||
| 1999/0914 | if(b != nil) { if(convretry(c, 1)) convoput(c, TControl, copyblock(b, blocklen(b))); | |
| 1999/1001 | break; | |
| 1999/0914 | } | |
| 1999/1001 | 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(); } | |
| 1999/0906 | break; | |
| 1999/0910 | case CLocalClose: | |
| 1999/0914 | if(convretry(c, 0)) | |
| 1999/0930/sys/src/9/port/devsdp.c:751,757 – 1999/1001/sys/src/9/port/devsdp.c:812,818 | ||
| 1999/0906 | break; | |
| 1999/0914 | case CRemoteClose: case CClosed: | |
| 1999/1001 | c->timeout = ~0; | |
| 1999/0914 | break; | |
| 1999/0906 | } | |
| 1999/0914 | poperror(); | |
| 1999/0930/sys/src/9/port/devsdp.c:858,873 – 1999/1001/sys/src/9/port/devsdp.c:919,948 | ||
| 1999/0910 | free(c->channame); c->channame = nil; } | |
| 1999/0907 |
| |
| 1999/1001 | 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"); | |
| 1999/0907 | c->perm = 0660; c->dialid = 0; c->acceptid = 0; | |
| 1999/1001 | c->timeout = ~0; | |
| 1999/0907 | c->retries = 0; c->drop = 0; memset(c->masterkey, 0, sizeof(c->masterkey)); onewaycleanup(&c->in); onewaycleanup(&c->out); | |
| 1999/1001 | memset(&c->lstats, 0, sizeof(Stats)); memset(&c->rstats, 0, sizeof(Stats)); | |
| 1999/0906 | break; } c->state = state; | |
| 1999/0930/sys/src/9/port/devsdp.c:979,987 – 1999/1001/sys/src/9/port/devsdp.c:1054,1065 | ||
| 1999/0907 | static Block * conviput(Conv *c, Block *b, int control) { | |
| 1999/1001 | int type, n; ulong seq, seqwrap, cseq; long seqdiff; | |
| 1999/0929 | AckPkt *ack; | |
| 1999/1001 | ulong mseq, mask; Block *bb; | |
| 1999/0907 | ||
| 1999/0930 | c->lstats.inPackets++; | |
| 1999/0929 | ||
| 1999/0930/sys/src/9/port/devsdp.c:999,1010 – 1999/1001/sys/src/9/port/devsdp.c:1077,1134 | ||
| 1999/0907 | seq = (b->rp[1]<<16) + (b->rp[2]<<8) + b->rp[3]; b->rp += 4; | |
| 1999/1001 | 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 | |
| 1999/0930 | if(0) print("coniput seq=%ulx\n", seq); | |
| 1999/0907 | // auth // decrypt // ok the packet is good | |
| 1999/1001 | 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); | |
| 1999/0907 | switch(type) { case TControl: | |
| 1999/0930/sys/src/9/port/devsdp.c:1059,1064 – 1999/1001/sys/src/9/port/devsdp.c:1183,1189 | ||
| 1999/0907 | freeb(b); freeb(c->out.controlpkt); | |
| 1999/0914 | c->out.controlpkt = nil; | |
| 1999/1001 | c->timeout = c->lastrecv + KeepAlive; | |
| 1999/0907 | wakeup(&c->out.controlready); return nil; case TData: | |
| 1999/0930/sys/src/9/port/devsdp.c:1068,1073 – 1999/1001/sys/src/9/port/devsdp.c:1193,1227 | ||
| 1999/0907 | if(control) break; return b; | |
| 1999/1001 | 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; | |
| 1999/0907 | } print("droping packet %d n=%ld\n", type, BLEN(b)); freeb(b); | |
| 1999/0930/sys/src/9/port/devsdp.c:1112,1118 – 1999/1001/sys/src/9/port/devsdp.c:1266,1271 | ||
| 1999/0910 | goto Reset; } | |
| 1999/0907 | switch(con->op) { | |
| 1999/0909 | case ConOpenRequest: switch(c->state) { | |
| 1999/0930/sys/src/9/port/devsdp.c:1189,1195 – 1999/1001/sys/src/9/port/devsdp.c:1342,1348 | ||
| 1999/0930 | convwriteblock(Conv *c, Block *b) { // simulated errors | |
| 1999/1001 | if(c->drop && nrand(c->drop) == 0) | |
| 1999/0930 | return; if(waserror()) { | |
| 1999/0930/sys/src/9/port/devsdp.c:1388,1399 – 1999/1001/sys/src/9/port/devsdp.c:1541,1549 | ||
| 1999/0914 | b->wp += 4+n; c->out.controlpkt = b; convretryinit(c); | |
| 1999/0930 |
| |
| 1999/1001 | if(wait) | |
| 1999/0929 | writewait(c); | |
| 1999/0930 |
| |
| 1999/0915 | poperror(); | |
| 1999/0929 | qunlock(c); | |
| 1999/0915 | qunlock(&c->out.controllk); | |
| 1999/0930/sys/src/9/port/devsdp.c:1424,1430 – 1999/1001/sys/src/9/port/devsdp.c:1574,1582 | ||
| 1999/0915 | static long writedata(Conv *c, Block *b) { | |
| 1999/1001 | int n, nn; ulong seq; Block *bb; | |
| 1999/0915 | qlock(c); if(waserror()) { | |
| 1999/0930/sys/src/9/port/devsdp.c:1440,1447 – 1999/1001/sys/src/9/port/devsdp.c:1592,1627 | ||
| 1999/0915 | n = BLEN(b); | |
| 1999/0930 | c->lstats.outDataPackets++; c->lstats.outDataBytes += n; | |
| 1999/0915 |
| |
| 1999/1001 | 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); } | |
| 1999/0915 | poperror(); qunlock(c); return n; | |
| 1999/1001/sys/src/9/port/devsdp.c:17,23 – 1999/1015/sys/src/9/port/devsdp.c:17,22 (short | long) | ||
| 1999/0902 | typedef struct Conv Conv; | |
| 1999/0907 | typedef struct OneWay OneWay; | |
| 1999/0929 | typedef struct Stats Stats; | |
| 1999/0907 |
| |
| 1999/0929 | typedef struct AckPkt AckPkt; | |
| 1999/1001 | typedef struct Algorithm Algorithm; | |
| 1999/0824 | ||
| 1999/1001/sys/src/9/port/devsdp.c:43,49 – 1999/1015/sys/src/9/port/devsdp.c:42,48 | ||
| 1999/0907 | Nfs= 4, // number of file systems | |
| 1999/1001 | MaxRetries= 8, | |
| 1999/0909 | KeepAlive = 60, // keep alive in seconds | |
| 1999/0907 |
| |
| 1999/1015 | SecretLength= 32, // a secret per direction | |
| 1999/1001 | SeqMax = (1<<24), SeqWindow = 32, | |
| 1999/0824 | }; | |
| 1999/1001/sys/src/9/port/devsdp.c:78,83 – 1999/1015/sys/src/9/port/devsdp.c:77,84 | ||
| 1999/0901 | ulong seq; | |
| 1999/0907 | ulong window; | |
| 1999/0901 | ||
| 1999/1015 | uchar secret[SecretLength]; | |
| 1999/0915 | QLock controllk; | |
| 1999/0907 | Rendez controlready; | |
| 1999/0902 | Block *controlpkt; // control channel | |
| 1999/1001/sys/src/9/port/devsdp.c:93,99 – 1999/1015/sys/src/9/port/devsdp.c:94,100 | ||
| 1999/0907 | int (*auth)(OneWay*, uchar *buf, int len); | |
| 1999/0902 | void *compstate; | |
| 1999/0907 |
| |
| 1999/1015 | int (*comp)(OneWay*, int subtype, Block **); | |
| 1999/0901 | }; | |
| 1999/0907 | // conv states | |
| 1999/1001/sys/src/9/port/devsdp.c:137,143 – 1999/1015/sys/src/9/port/devsdp.c:138,143 | ||
| 1999/0907 | char owner[NAMELEN]; /* protections */ | |
| 1999/0901 | int perm; | |
| 1999/0907 |
| |
| 1999/1001 | char *authname; char *ciphername; char *compname; | |
| 1999/1001/sys/src/9/port/devsdp.c:160,172 – 1999/1015/sys/src/9/port/devsdp.c:160,175 | ||
| 1999/0906 | enum { TConnect, TControl, | |
| 1999/1015 | TCompData, | |
| 1999/0906 | }; enum { | |
| 1999/1015 | ControlMesg, ControlAck, }; enum { | |
| 1999/0909 | ConOpenRequest, | |
| 1999/0906 | ConOpenAck, | |
| 1999/0910 | ConOpenAckAck, | |
| 1999/1001/sys/src/9/port/devsdp.c:174,188 – 1999/1015/sys/src/9/port/devsdp.c:177,182 | ||
| 1999/0909 | ConReset, | |
| 1999/0906 | }; | |
| 1999/0907 |
| |
| 1999/0906 |
| |
| 1999/0929 | struct AckPkt { uchar cseq[4]; | |
| 1999/1001/sys/src/9/port/devsdp.c:222,252 – 1999/1015/sys/src/9/port/devsdp.c:216,221 | ||
| 1999/0929 | "rstats", {Qrstats}, 0, 0444, | |
| 1999/0824 | }; | |
| 1999/1001 |
| |
| 1999/0824 | static int m2p[] = { [OREAD] 4, [OWRITE] 2, | |
| 1999/1001/sys/src/9/port/devsdp.c:287,303 – 1999/1015/sys/src/9/port/devsdp.c:256,310 | ||
| 1999/0907 | static int readready(void *a); static int controlread(); static Block *conviput(Conv *c, Block *b, int control); | |
| 1999/1015 | 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); | |
| 1999/0929 | static void writecontrol(Conv *c, void *p, int n, int wait); | |
| 1999/0907 | static Block *readcontrol(Conv *c, int n); static Block *readdata(Conv *c, int n); | |
| 1999/0915 | static long writedata(Conv *c, Block *b); | |
| 1999/0907 |
| |
| 1999/1015 | static void convoput(Conv *c, int type, int subtype, Block *b); static void convoconnect(Conv *c, int op, ulong dialid, ulong acceptid); | |
| 1999/0910 | static void convreader(void *a); | |
| 1999/0914 | static void convopenchan(Conv *c, char *path); | |
| 1999/0929 | static void convstats(Conv *c, int local, char *buf, int n); | |
| 1999/0824 | ||
| 1999/1015 | 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, }; | |
| 1999/0824 | static void sdpinit(void) { | |
| 1999/1001/sys/src/9/port/devsdp.c:597,602 – 1999/1015/sys/src/9/port/devsdp.c:604,629 | ||
| 1999/0906 | if(cb->nf != 2) error("usage: drop permil"); c->drop = atoi(cb->f[1]); | |
| 1999/1015 | } 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]); | |
| 1999/0824 | } else error("unknown control request"); poperror(); | |
| 1999/1001/sys/src/9/port/devsdp.c:739,745 – 1999/1015/sys/src/9/port/devsdp.c:766,772 | ||
| 1999/0909 | c->retries = 0; // +2 to avoid rounding effects. c->timeout = TK2SEC(m->ticks) + 2; | |
| 1999/1015 | } | |
| 1999/0909 | // assume c is locked | |
| 1999/0906 | static int | |
| 1999/1001/sys/src/9/port/devsdp.c:750,756 – 1999/1015/sys/src/9/port/devsdp.c:777,783 | ||
| 1999/0909 | if(c->retries > MaxRetries) { | |
| 1999/0906 | print("convretry: giving up\n"); | |
| 1999/0914 | if(reset) | |
| 1999/1015 | convoconnect(c, ConReset, c->dialid, c->acceptid); | |
| 1999/0906 | convsetstate(c, CClosed); return 0; } | |
| 1999/1001/sys/src/9/port/devsdp.c:773,789 – 1999/1015/sys/src/9/port/devsdp.c:800,816 | ||
| 1999/0906 | switch(c->state) { | |
| 1999/0909 | case CDial: | |
| 1999/0914 | if(convretry(c, 1)) | |
| 1999/0909 |
| |
| 1999/1015 | convoconnect(c, ConOpenRequest, c->dialid, 0); | |
| 1999/0906 | break; | |
| 1999/0909 | case CAccept: | |
| 1999/0914 | if(convretry(c, 1)) | |
| 1999/0909 |
| |
| 1999/1015 | convoconnect(c, ConOpenAck, c->dialid, c->acceptid); | |
| 1999/0909 | break; | |
| 1999/0906 | case COpen: | |
| 1999/0914 | b = c->out.controlpkt; if(b != nil) { if(convretry(c, 1)) | |
| 1999/1015 | convoput(c, TControl, ControlMesg, copyblock(b, blocklen(b))); | |
| 1999/1001 | break; | |
| 1999/0914 | } | |
| 1999/1001 | ||
| 1999/1001/sys/src/9/port/devsdp.c:802,814 – 1999/1015/sys/src/9/port/devsdp.c:829,841 | ||
| 1999/1001 | c->out.controlpkt = b; convretryinit(c); if(!waserror()) { | |
| 1999/1015 | convoput(c, TControl, ControlMesg, copyblock(b, blocklen(b))); | |
| 1999/1001 | poperror(); } | |
| 1999/0906 | break; | |
| 1999/0910 | case CLocalClose: | |
| 1999/0914 | if(convretry(c, 0)) | |
| 1999/0907 |
| |
| 1999/1015 | convoconnect(c, ConClose, c->dialid, c->acceptid); | |
| 1999/0906 | break; | |
| 1999/0914 | case CRemoteClose: case CClosed: | |
| 1999/1001/sys/src/9/port/devsdp.c:878,907 – 1999/1015/sys/src/9/port/devsdp.c:905,943 | ||
| 1999/0909 | assert(c->state == CInit); | |
| 1999/0906 | c->dialid = (rand()<<16) + rand(); | |
| 1999/0909 | convretryinit(c); | |
| 1999/1015 | convoconnect(c, ConOpenRequest, c->dialid, 0); | |
| 1999/0906 | break; | |
| 1999/0909 | case CAccept: assert(c->state == CInit); c->acceptid = (rand()<<16) + rand(); convretryinit(c); | |
| 1999/1015 | convoconnect(c, ConOpenAck, c->dialid, c->acceptid); | |
| 1999/0909 | break; | |
| 1999/0906 | case COpen: | |
| 1999/0909 | assert(c->state == CDial || c->state == CAccept); if(c->state == CDial) { convretryinit(c); | |
| 1999/0910 |
| |
| 1999/1015 | 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); | |
| 1999/0906 | } | |
| 1999/1015 | md5authinit(c, "hmac_md5_96", 16); | |
| 1999/0906 | break; | |
| 1999/0910 | case CLocalClose: assert(c->state == CAccept || c->state == COpen); | |
| 1999/0909 | convretryinit(c); | |
| 1999/0907 |
| |
| 1999/1015 | convoconnect(c, ConClose, c->dialid, c->acceptid); | |
| 1999/0906 | break; | |
| 1999/0910 | case CRemoteClose: | |
| 1999/0914 | wakeup(&c->in.controlready); | |
| 1999/0910 |
| |
| 1999/1015 | convoconnect(c, ConReset, c->dialid, c->acceptid); | |
| 1999/0910 | break; | |
| 1999/0906 | case CClosed: | |
| 1999/0914 | wakeup(&c->in.controlready); | |
| 1999/1001/sys/src/9/port/devsdp.c:938,944 – 1999/1015/sys/src/9/port/devsdp.c:974,979 | ||
| 1999/1001 | c->timeout = ~0; | |
| 1999/0907 | c->retries = 0; c->drop = 0; | |
| 1999/1001 | memset(&c->lstats, 0, sizeof(Stats)); | |
| 1999/1001/sys/src/9/port/devsdp.c:1046,1052 – 1999/1015/sys/src/9/port/devsdp.c:1081,1087 | ||
| 1999/0929 | hnputl(ack->inReorder, s->inReorder); hnputl(ack->inBadAuth, s->inBadAuth); hnputl(ack->inBadSeq, s->inBadSeq); | |
| 1999/1015 | convoput(c, TControl, ControlAck, b); | |
| 1999/0929 | } | |
| 1999/1001/sys/src/9/port/devsdp.c:1054,1065 – 1999/1015/sys/src/9/port/devsdp.c:1089,1097 | ||
| 1999/0907 | static Block * conviput(Conv *c, Block *b, int control) { | |
| 1999/1001 |
| |
| 1999/1015 | int type, subtype; ulong seq, seqwrap; | |
| 1999/1001 | long seqdiff; | |
| 1999/0929 |
| |
| 1999/1001 |
| |
| 1999/0907 | ||
| 1999/0930 | c->lstats.inPackets++; | |
| 1999/0929 | ||
| 1999/1001/sys/src/9/port/devsdp.c:1068,1081 – 1999/1015/sys/src/9/port/devsdp.c:1100,1115 | ||
| 1999/0907 | return nil; } | |
| 1999/1015 | type = b->rp[0] >> 4; subtype = type & 0xf; b->rp += 1; | |
| 1999/0907 | if(type == TConnect) { | |
| 1999/1015 | conviconnect(c, subtype, b); | |
| 1999/0907 | return nil; } | |
| 1999/1015 | seq = (b->rp[0]<<16) + (b->rp[1]<<8) + b->rp[2]; b->rp += 3; | |
| 1999/0907 | ||
| 1999/1001 | seqwrap = c->in.seqwrap; seqdiff = seq - c->in.seq; | |
| 1999/1001/sys/src/9/port/devsdp.c:1107,1113 – 1999/1015/sys/src/9/port/devsdp.c:1141,1156 | ||
| 1999/1001 | // ok the sequence number looks ok | |
| 1999/0930 | if(0) print("coniput seq=%ulx\n", seq); | |
| 1999/0907 |
| |
| 1999/1015 | 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; } | |
| 1999/0907 | // decrypt // ok the packet is good | |
| 1999/1001/sys/src/9/port/devsdp.c:1132,1227 – 1999/1015/sys/src/9/port/devsdp.c:1175,1198 | ||
| 1999/0907 | switch(type) { case TControl: | |
| 1999/0929 |
| |
| 1999/0907 |
| |
| 1999/0914 |
| |
| 1999/0907 |
| |
| 1999/0929 |
| |
| 1999/0907 |
| |
| 1999/0929 |
| |
| 1999/0930 |
| |
| 1999/0929 |
| |
| 1999/1015 | convicontrol(c, subtype, b); | |
| 1999/0907 | return nil; | |
| 1999/0929 |
| |
| 1999/0907 |
| |
| 1999/0929 |
| |
| 1999/0930 |
| |
| 1999/0914 |
| |
| 1999/0907 |
| |
| 1999/0930 |
| |
| 1999/0907 |
| |
| 1999/0914 |
| |
| 1999/1001 |
| |
| 1999/0907 |
| |
| 1999/0929 | c->lstats.inDataPackets++; c->lstats.inDataBytes += BLEN(b); | |
| 1999/0907 | if(control) break; return b; | |
| 1999/1001 |
| |
| 1999/1015 | case TCompData: | |
| 1999/1001 | c->lstats.inDataPackets++; c->lstats.inCompDataBytes += BLEN(b); | |
| 1999/1015 | b = convicomp(c, subtype, b); if(b == nil); return nil; | |
| 1999/1001 | c->lstats.inDataBytes += BLEN(b); if(control) break; return b; | |
| 1999/0907 | } print("droping packet %d n=%ld\n", type, BLEN(b)); freeb(b); | |
| 1999/1001/sys/src/9/port/devsdp.c:1230,1250 – 1999/1015/sys/src/9/port/devsdp.c:1201,1220 | ||
| 1999/0907 | // assume hold conv lock static void | |
| 1999/1015 | conviconnect(Conv *c, int subtype, Block *b) | |
| 1999/0907 | { | |
| 1999/1015 | if(BLEN(b) != 8) { | |
| 1999/0907 | freeb(b); return; } | |
| 1999/1015 | dialid = nhgetl(b->rp); acceptid = nhgetl(b->rp + 4); freeb(b); | |
| 1999/0907 | ||
| 1999/0914 |
| |
| 1999/1015 | print("conviconnect: %s: %d %uld %uld\n", convstatename[c->state], subtype, dialid, acceptid); | |
| 1999/0914 | ||
| 1999/0910 | switch(c->state) { default: | |
| 1999/1001/sys/src/9/port/devsdp.c:1259,1265 – 1999/1015/sys/src/9/port/devsdp.c:1229,1236 | ||
| 1999/0910 | case COpen: case CLocalClose: case CRemoteClose: | |
| 1999/1015 | if(dialid != c->dialid || subtype != ConOpenRequest && acceptid != c->acceptid) | |
| 1999/0910 | goto Reset; break; case CClosed: | |
| 1999/1001/sys/src/9/port/devsdp.c:1266,1272 – 1999/1015/sys/src/9/port/devsdp.c:1237,1243 | ||
| 1999/0910 | goto Reset; } | |
| 1999/0907 |
| |
| 1999/1015 | switch(subtype) { | |
| 1999/0909 | case ConOpenRequest: switch(c->state) { case CInit: | |
| 1999/1001/sys/src/9/port/devsdp.c:1287,1293 – 1999/1015/sys/src/9/port/devsdp.c:1258,1264 | ||
| 1999/0910 | return; case COpen: // duplicate that we have to ack | |
| 1999/1015 | convoconnect(c, ConOpenAckAck, acceptid, dialid); | |
| 1999/0910 | return; } break; | |
| 1999/1001/sys/src/9/port/devsdp.c:1302,1308 – 1999/1015/sys/src/9/port/devsdp.c:1273,1279 | ||
| 1999/0909 | } | |
| 1999/0907 | break; case ConClose: | |
| 1999/0910 |
| |
| 1999/1015 | convoconnect(c, ConReset, dialid, acceptid); | |
| 1999/0909 | switch(c->state) { | |
| 1999/0910 | case CInit: | |
| 1999/0909 | case CDial: | |
| 1999/1001/sys/src/9/port/devsdp.c:1316,1322 – 1999/1015/sys/src/9/port/devsdp.c:1287,1293 | ||
| 1999/0910 | case CRemoteClose: return; | |
| 1999/0909 | } | |
| 1999/0910 |
| |
| 1999/1015 | break; | |
| 1999/0910 | case ConReset: switch(c->state) { case CInit: | |
| 1999/1001/sys/src/9/port/devsdp.c:1329,1342 – 1999/1015/sys/src/9/port/devsdp.c:1300,1390 | ||
| 1999/0910 | case CRemoteClose: return; } | |
| 1999/1015 | break; | |
| 1999/0907 | } | |
| 1999/0910 | Reset: // invalid connection message - reset to sender | |
| 1999/0914 |
| |
| 1999/0910 |
| |
| 1999/1015 | print("invalid conviconnect - sending reset\n"); convoconnect(c, ConReset, dialid, acceptid); | |
| 1999/0907 | } | |
| 1999/1015 | 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; } | |
| 1999/0930 | // c is locked static void convwriteblock(Conv *c, Block *b) | |
| 1999/1001/sys/src/9/port/devsdp.c:1356,1368 – 1999/1015/sys/src/9/port/devsdp.c:1404,1416 | ||
| 1999/0930 | ||
| 1999/0907 | // assume hold conv lock static void | |
| 1999/1015 | convoput(Conv *c, int type, int subtype, Block *b) | |
| 1999/0907 | { // try and compress | |
| 1999/0929 | c->lstats.outPackets++; | |
| 1999/0907 | /* Make space to fit sdp header */ b = padblock(b, 4 + c->out.cipherivlen); | |
| 1999/1015 | b->rp[0] = (type << 4) | subtype; | |
| 1999/0907 | c->out.seq++; if(c->out.seq == (1<<24)) { c->out.seq = 0; | |
| 1999/1001/sys/src/9/port/devsdp.c:1374,1379 – 1999/1015/sys/src/9/port/devsdp.c:1422,1432 | ||
| 1999/0907 | // encrypt // auth | |
| 1999/1015 | if(c->out.auth) { b = padblock(b, -c->out.authlen); b->wp += c->out.authlen; (*c->out.auth)(&c->out, b->rp, BLEN(b)); } | |
| 1999/0930 | convwriteblock(c, b); | |
| 1999/0907 | } | |
| 1999/1001/sys/src/9/port/devsdp.c:1380,1389 – 1999/1015/sys/src/9/port/devsdp.c:1433,1441 | ||
| 1999/0907 | // assume hold conv lock static void | |
| 1999/1015 | convoconnect(Conv *c, int op, ulong dialid, ulong acceptid) | |
| 1999/0907 | { | |
| 1999/0930 | Block *b; | |
| 1999/0907 | ||
| 1999/0929 | c->lstats.outPackets++; | |
| 1999/0906 | if(c->chan == nil) { | |
| 1999/1001/sys/src/9/port/devsdp.c:1390,1402 – 1999/1015/sys/src/9/port/devsdp.c:1442,1452 | ||
| 1999/0906 | print("chan = nil\n"); error("no channel attached"); } | |
| 1999/0930 |
| |
| 1999/1015 | b = allocb(9); b->wp[0] = (TConnect << 4) | op; hnputl(b->wp+1, dialid); hnputl(b->wp+5, acceptid); b->wp += 9; | |
| 1999/0906 | ||
| 1999/0930 | convwriteblock(c, b); | |
| 1999/0907 | } | |
| 1999/1001/sys/src/9/port/devsdp.c:1525,1531 – 1999/1015/sys/src/9/port/devsdp.c:1575,1580 | ||
| 1999/0929 | { Block *b; | |
| 1999/1001/sys/src/9/port/devsdp.c:1541,1547 – 1999/1015/sys/src/9/port/devsdp.c:1590,1596 | ||
| 1999/0914 | b->wp += 4+n; c->out.controlpkt = b; convretryinit(c); | |
| 1999/1015 | convoput(c, TControl, ControlMesg, copyblock(b, blocklen(b))); | |
| 1999/1001 | if(wait) | |
| 1999/0929 | writewait(c); | |
| 1999/0915 | poperror(); | |
| 1999/1001/sys/src/9/port/devsdp.c:1574,1582 – 1999/1015/sys/src/9/port/devsdp.c:1623,1629 | ||
| 1999/0915 | static long writedata(Conv *c, Block *b) { | |
| 1999/1001 |
| |
| 1999/1015 | int n; | |
| 1999/0915 | qlock(c); if(waserror()) { | |
| 1999/1001/sys/src/9/port/devsdp.c:1593,1626 – 1999/1015/sys/src/9/port/devsdp.c:1640,1651 | ||
| 1999/0930 | c->lstats.outDataPackets++; c->lstats.outDataBytes += n; | |
| 1999/1001 |
| |
| 1999/1015 | if(c->out.comp != nil) { int subtype = (*c->out.comp)(&c->out, 0, &b); | |
| 1999/1001 | c->lstats.outCompDataBytes += BLEN(b); | |
| 1999/1015 | convoput(c, TCompData, subtype, b); } else convoput(c, TData, 0, b); | |
| 1999/1001 | ||
| 1999/0915 | poperror(); qunlock(c); | |
| 1999/1001/sys/src/9/port/devsdp.c:1663,1665 – 1999/1015/sys/src/9/port/devsdp.c:1688,2040 | ||
| 1999/0910 | qunlock(c); pexit("hangup", 1); | |
| 1999/0906 | } | |
| 1999/1015 | /* 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; i<round+1; i++) salt[i] = 'A'+round; sha((uchar*)prefix, strlen(prefix), ibuf, sha(salt, round+1, nil, nil)); md5(ibuf, SHAdlen, obuf, md5(ow->secret, sizeof(ow->secret), nil, nil)); i = (n<MD5dlen) ? n : MD5dlen; memmove(key, obuf, i); key += i; n -= i; if(++round > 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; i<klen; i++){ ipad[i] ^= key[i]; opad[i] ^= key[i]; } hnputl(wbuf, wrap); digest = md5(ipad, 64, nil, nil); digest = md5(wbuf, sizeof(wbuf), nil, digest); md5(t, tlen, innerhash, digest); digest = md5(opad, 64, nil, nil); md5(innerhash, MD5dlen, hash, digest); } static int md5auth(OneWay *ow, uchar *t, int tlen) { uchar hash[MD5dlen]; int r; if(tlen < ow->authlen) 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 | |
| 1999/1015/sys/src/9/port/devsdp.c:65,70 – 1999/1016/sys/src/9/port/devsdp.c:65,71 (short | long) | ||
| 1999/0929 | ulong inMissing; ulong inDup; ulong inReorder; | |
| 1999/1016 | ulong inBadComp; | |
| 1999/0929 | ulong inBadAuth; ulong inBadSeq; }; | |
| 1999/1015/sys/src/9/port/devsdp.c:94,100 – 1999/1016/sys/src/9/port/devsdp.c:95,101 | ||
| 1999/0907 | int (*auth)(OneWay*, uchar *buf, int len); | |
| 1999/0902 | void *compstate; | |
| 1999/1015 |
| |
| 1999/1016 | int (*comp)(Conv*, int subtype, ulong seq, Block **); | |
| 1999/0901 | }; | |
| 1999/0907 | // conv states | |
| 1999/1015/sys/src/9/port/devsdp.c:170,175 – 1999/1016/sys/src/9/port/devsdp.c:171,181 | ||
| 1999/1015 | }; enum { | |
| 1999/1016 | ThwackU, ThwackC, }; enum { | |
| 1999/0909 | ConOpenRequest, | |
| 1999/0906 | ConOpenAck, | |
| 1999/0910 | ConOpenAckAck, | |
| 1999/1015/sys/src/9/port/devsdp.c:191,196 – 1999/1016/sys/src/9/port/devsdp.c:197,203 | ||
| 1999/0929 | uchar inMissing[4]; uchar inDup[4]; uchar inReorder[4]; | |
| 1999/1016 | uchar inBadComp[4]; | |
| 1999/0929 | uchar inBadAuth[4]; uchar inBadSeq[4]; }; | |
| 1999/1015/sys/src/9/port/devsdp.c:258,264 – 1999/1016/sys/src/9/port/devsdp.c:265,271 | ||
| 1999/0907 | static Block *conviput(Conv *c, Block *b, int control); | |
| 1999/1015 | static void conviconnect(Conv *c, int op, Block *b); static void convicontrol(Conv *c, int op, Block *b); | |
| 1999/1016 | static Block *convicomp(Conv *c, int op, ulong, Block *b); | |
| 1999/0929 | static void writecontrol(Conv *c, void *p, int n, int wait); | |
| 1999/0907 | static Block *readcontrol(Conv *c, int n); static Block *readdata(Conv *c, int n); | |
| 1999/1015/sys/src/9/port/devsdp.c:748,757 – 1999/1016/sys/src/9/port/devsdp.c:755,760 | ||
| 1999/0902 | c->ref++; | |
| 1999/0906 | c->state = CInit; | |
| 1999/1001 | c->in.window = ~0; | |
| 1999/0907 | strncpy(c->owner, up->user, sizeof(c->owner)); | |
| 1999/0901 | c->perm = 0660; qunlock(c); | |
| 1999/1015/sys/src/9/port/devsdp.c:955,972 – 1999/1016/sys/src/9/port/devsdp.c:958,966 | ||
| 1999/0910 | free(c->channame); c->channame = nil; } | |
| 1999/1001 |
| |
| 1999/1016 | c->ciphername = nil; c->authname = nil; c->compname = nil; | |
| 1999/1001 | strcpy(c->owner, "network"); | |
| 1999/0907 | c->perm = 0660; c->dialid = 0; | |
| 1999/1015/sys/src/9/port/devsdp.c:1049,1054 – 1999/1016/sys/src/9/port/devsdp.c:1043,1049 | ||
| 1999/0929 | 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); | |
| 1999/1016 | p += snprint(p, ep-p, "inBadComp: %ld\n", stats->inBadComp); | |
| 1999/0929 | p += snprint(p, ep-p, "inBadAuth: %ld\n", stats->inBadAuth); p += snprint(p, ep-p, "inBadSeq: %ld\n", stats->inBadSeq); USED(p); | |
| 1999/1015/sys/src/9/port/devsdp.c:1079,1084 – 1999/1016/sys/src/9/port/devsdp.c:1074,1080 | ||
| 1999/0929 | hnputl(ack->inMissing, s->inMissing); hnputl(ack->inDup, s->inDup); hnputl(ack->inReorder, s->inReorder); | |
| 1999/1016 | hnputl(ack->inBadComp, s->inBadComp); | |
| 1999/0929 | hnputl(ack->inBadAuth, s->inBadAuth); hnputl(ack->inBadSeq, s->inBadSeq); | |
| 1999/1015 | convoput(c, TControl, ControlAck, b); | |
| 1999/1015/sys/src/9/port/devsdp.c:1101,1107 – 1999/1016/sys/src/9/port/devsdp.c:1097,1103 | ||
| 1999/0907 | } | |
| 1999/1015 | type = b->rp[0] >> 4; | |
| 1999/1016 | subtype = b->rp[0] & 0xf; | |
| 1999/1015 | b->rp += 1; | |
| 1999/0907 | if(type == TConnect) { | |
| 1999/1015 | conviconnect(c, subtype, b); | |
| 1999/1015/sys/src/9/port/devsdp.c:1186,1194 – 1999/1016/sys/src/9/port/devsdp.c:1182,1192 | ||
| 1999/1015 | case TCompData: | |
| 1999/1001 | c->lstats.inDataPackets++; c->lstats.inCompDataBytes += BLEN(b); | |
| 1999/1015 |
| |
| 1999/1016 | b = convicomp(c, subtype, seq, b); if(b == nil) { c->lstats.inBadComp++; | |
| 1999/1015 | return nil; | |
| 1999/1016 | } | |
| 1999/1001 | c->lstats.inDataBytes += BLEN(b); if(control) break; | |
| 1999/1015/sys/src/9/port/devsdp.c:1362,1367 – 1999/1016/sys/src/9/port/devsdp.c:1360,1366 | ||
| 1999/1015 | c->rstats.inMissing = nhgetl(ack->inMissing); c->rstats.inDup = nhgetl(ack->inDup); c->rstats.inReorder = nhgetl(ack->inReorder); | |
| 1999/1016 | c->rstats.inBadComp = nhgetl(ack->inBadComp); | |
| 1999/1015 | c->rstats.inBadAuth = nhgetl(ack->inBadAuth); c->rstats.inBadSeq = nhgetl(ack->inBadSeq); freeb(b); | |
| 1999/1015/sys/src/9/port/devsdp.c:1374,1386 – 1999/1016/sys/src/9/port/devsdp.c:1373,1385 | ||
| 1999/1015 | } static Block* | |
| 1999/1016 | convicomp(Conv *c, int subtype, ulong seq, Block *b) | |
| 1999/1015 | { if(c->in.comp == nil) { freeb(b); return nil; } | |
| 1999/1016 | if(!(*c->in.comp)(c, subtype, seq, &b)) | |
| 1999/1015 | return nil; return b; } | |
| 1999/1015/sys/src/9/port/devsdp.c:1624,1629 – 1999/1016/sys/src/9/port/devsdp.c:1623,1630 | ||
| 1999/0915 | writedata(Conv *c, Block *b) { | |
| 1999/1015 | int n; | |
| 1999/1016 | ulong seq; int subtype; | |
| 1999/0915 | qlock(c); if(waserror()) { | |
| 1999/1015/sys/src/9/port/devsdp.c:1641,1647 – 1999/1016/sys/src/9/port/devsdp.c:1642,1651 | ||
| 1999/0930 | c->lstats.outDataBytes += n; | |
| 1999/1001 | ||
| 1999/1015 | if(c->out.comp != nil) { | |
| 1999/1016 | // must generate same value as convoput seq = (c->out.seq + 1) & (SeqMax-1); subtype = (*c->out.comp)(c, 0, seq, &b); | |
| 1999/1001 | c->lstats.outCompDataBytes += BLEN(b); | |
| 1999/1015 | convoput(c, TCompData, subtype, b); } else | |
| 1999/1015/sys/src/9/port/devsdp.c:1751,1764 – 1999/1016/sys/src/9/port/devsdp.c:1755,1764 | ||
| 1999/1015 | } } | |
| 1999/1016 | c->ciphername = nil; | |
| 1999/1015 | if(c->in.cipherstate) { free(c->in.cipherstate); c->in.cipherstate = nil; | |
| 1999/1015/sys/src/9/port/devsdp.c:1773,1782 – 1999/1016/sys/src/9/port/devsdp.c:1773,1779 | ||
| 1999/1015 | static void authfree(Conv *c) { | |
| 1999/1016 | c->authname = nil; | |
| 1999/1015 | if(c->in.authstate) { free(c->in.authstate); c->in.authstate = nil; | |
| 1999/1015/sys/src/9/port/devsdp.c:1791,1800 – 1999/1016/sys/src/9/port/devsdp.c:1788,1794 | ||
| 1999/1015 | static void compfree(Conv *c) { | |
| 1999/1016 | c->compname = nil; | |
| 1999/1015 | if(c->in.compstate) { free(c->in.compstate); c->in.compstate = nil; | |
| 1999/1015/sys/src/9/port/devsdp.c:1806,1812 – 1999/1016/sys/src/9/port/devsdp.c:1800,1805 | ||
| 1999/1015 | c->in.comp = nil; } | |
| 1999/1015/sys/src/9/port/devsdp.c:1863,1870 – 1999/1016/sys/src/9/port/devsdp.c:1856,1862 | ||
| 1999/1015 | int i; cipherfree(c); | |
| 1999/1016 | c->ciphername = name; | |
| 1999/1015 | if(n > sizeof(key)) n = sizeof(key); | |
| 1999/1015/sys/src/9/port/devsdp.c:1894,1899 – 1999/1016/sys/src/9/port/devsdp.c:1886,1892 | ||
| 1999/1015 | static void rc4cipherinit(Conv *c, char *name, int keylen) { | |
| 1999/1016 | cipherfree(c); | |
| 1999/1015 | } static void | |
| 1999/1015/sys/src/9/port/devsdp.c:1955,1962 – 1999/1016/sys/src/9/port/devsdp.c:1948,1954 | ||
| 1999/1015 | { authfree(c); | |
| 1999/1016 | c->authname = name; | |
| 1999/1015 | if(keylen > 16) keylen = 16; | |
| 1999/1015/sys/src/9/port/devsdp.c:1977,2040 – 1999/1016/sys/src/9/port/devsdp.c:1969,2054 | ||
| 1999/1015 | } static void | |
| 1999/1016 | nullcompinit(Conv *c, char*, int) | |
| 1999/1015 | { | |
| 1999/1016 | compfree(c); | |
| 1999/1015 | } | |
| 1999/1016 | static int thwackcomp(Conv *c, int, ulong seq, Block **bp) | |
| 1999/1015 | { | |
| 1999/1016 | 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; } | |
| 1999/1015 | } | |
| 1999/1016 | static int thwackuncomp(Conv *c, int subtype, ulong seq, Block **bp) { Block *b, *bb; ulong mask; ulong mseq; int n; | |
| 1999/1015 |
| |
| 1999/1016 | switch(subtype) { default: return 0; case ThwackU: b = *bp; | |
| 1999/1015 | 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); | |
| 1999/1016 | return 1; case ThwackC: bb = *bp; | |
| 1999/1015 | b = allocb(ThwMaxBlock); n = unthwack(c->in.compstate, b->wp, ThwMaxBlock, bb->rp, BLEN(bb), seq); freeb(bb); | |
| 1999/1016 | if(n < 0) { print("unthwack failed: %r!\n"); freeb(b); return 0; } | |
| 1999/1015 | 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; | |
| 1999/1016 | *bp = b; return 1; | |
| 1999/1015 | } | |
| 1999/1016 | } | |
| 1999/1015 |
| |
| 1999/1016 | static void thwackcompinit(Conv *c, char *name, int keylen) { compfree(c); | |
| 1999/1015 |
| |
| 1999/1016 | 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; } | |
| 1999/1016/sys/src/9/port/devsdp.c:45,50 – 1999/1019/sys/src/9/port/devsdp.c:45,51 (short | long) | ||
| 1999/1015 | SecretLength= 32, // a secret per direction | |
| 1999/1001 | SeqMax = (1<<24), SeqWindow = 32, | |
| 1999/1019 | NCompStats = 8, | |
| 1999/0824 | }; #define TYPE(x) ((x).path & 0xff) | |
| 1999/1016/sys/src/9/port/devsdp.c:58,63 – 1999/1019/sys/src/9/port/devsdp.c:59,65 | ||
| 1999/0929 | ulong outDataBytes; ulong outCompDataBytes; ulong outCompBytes; | |
| 1999/1019 | ulong outCompStats[NCompStats]; | |
| 1999/0929 | ulong inPackets; ulong inDataPackets; ulong inDataBytes; | |
| 1999/1016/sys/src/9/port/devsdp.c:190,195 – 1999/1019/sys/src/9/port/devsdp.c:192,198 | ||
| 1999/0929 | uchar outDataPackets[4]; uchar outDataBytes[4]; uchar outCompDataBytes[4]; | |
| 1999/1019 | uchar outCompStats[4*NCompStats]; | |
| 1999/0929 | uchar inPackets[4]; uchar inDataPackets[4]; uchar inDataBytes[4]; | |
| 1999/1016/sys/src/9/port/devsdp.c:1018,1023 – 1999/1019/sys/src/9/port/devsdp.c:1021,1027 | ||
| 1999/0929 | { Stats *stats; char *p, *ep; | |
| 1999/1019 | int i; | |
| 1999/0907 | ||
| 1999/0929 | if(local) { stats = &c->lstats; | |
| 1999/1016/sys/src/9/port/devsdp.c:1032,1051 – 1999/1019/sys/src/9/port/devsdp.c:1036,1061 | ||
| 1999/0930 | qlock(c); | |
| 1999/0929 | p = buf; ep = buf + n; | |
| 1999/0930 |
| |
| 1999/0929 |
| |
| 1999/1016 |
| |
| 1999/0929 |
| |
| 1999/1019 | 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; i<NCompStat; i++) { if(stat->outCompStats[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); | |
| 1999/0929 | USED(p); qunlock(c); } | |
| 1999/1016/sys/src/9/port/devsdp.c:1057,1062 – 1999/1019/sys/src/9/port/devsdp.c:1067,1073 | ||
| 1999/0929 | Block *b; AckPkt *ack; Stats *s; | |
| 1999/1019 | int i; | |
| 1999/0929 | b = allocb(sizeof(AckPkt)); | |
| 1999/0930 | ack = (AckPkt*)b->wp; | |
| 1999/1016/sys/src/9/port/devsdp.c:1067,1072 – 1999/1019/sys/src/9/port/devsdp.c:1078,1085 | ||
| 1999/0929 | hnputl(ack->outDataPackets, s->outDataPackets); hnputl(ack->outDataBytes, s->outDataBytes); hnputl(ack->outCompDataBytes, s->outCompDataBytes); | |
| 1999/1019 | for(i=0; i<NCompStat; i++) hnputl(ack->outCompStats+i*4, s->outCompStats[i]); | |
| 1999/0929 | hnputl(ack->inPackets, s->inPackets); hnputl(ack->inDataPackets, s->inDataPackets); hnputl(ack->inDataBytes, s->inDataBytes); | |
| 1999/1016/sys/src/9/port/devsdp.c:1311,1316 – 1999/1019/sys/src/9/port/devsdp.c:1324,1330 | ||
| 1999/1015 | { ulong cseq; AckPkt *ack; | |
| 1999/1019 | int i; | |
| 1999/1015 | if(BLEN(b) < 4) return; | |
| 1999/1016/sys/src/9/port/devsdp.c:1988,1994 – 1999/1019/sys/src/9/port/devsdp.c:2002,2008 | ||
| 1999/1016 | b->rp[3] = c->in.seq; bb = allocb(BLEN(b)); | |
| 1999/1019 | nn = thwack(c->out.compstate, bb->wp, b->rp, BLEN(b), seq, c->lstats.outCompStats); | |
| 1999/1016 | if(nn < 0) { freeb(bb); *bp = b; | |
| 1999/1019/sys/src/9/port/devsdp.c:1040,1047 – 1999/1021/sys/src/9/port/devsdp.c:1040,1047 (short | long) | ||
| 1999/1019 | 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); | |
| 1999/1021 | for(i=0; i<NCompStats; i++) { if(stats->outCompStats[i] == 0) | |
| 1999/1019 | continue; p += snprint(p, ep-p, "outCompStats[%d]: %lud\n", i, stats->outCompStats[i]); } | |
| 1999/1019/sys/src/9/port/devsdp.c:1078,1084 – 1999/1021/sys/src/9/port/devsdp.c:1078,1084 | ||
| 1999/0929 | hnputl(ack->outDataPackets, s->outDataPackets); hnputl(ack->outDataBytes, s->outDataBytes); hnputl(ack->outCompDataBytes, s->outCompDataBytes); | |
| 1999/1019 |
| |
| 1999/1021 | for(i=0; i<NCompStats; i++) | |
| 1999/1019 | hnputl(ack->outCompStats+i*4, s->outCompStats[i]); | |
| 1999/0929 | hnputl(ack->inPackets, s->inPackets); hnputl(ack->inDataPackets, s->inDataPackets); | |
| 1999/1019/sys/src/9/port/devsdp.c:1324,1330 – 1999/1021/sys/src/9/port/devsdp.c:1324,1329 | ||
| 1999/1015 | { ulong cseq; AckPkt *ack; | |
| 1999/1019 |
| |
| 1999/1015 | if(BLEN(b) < 4) return; | |
| 1999/1019/sys/src/9/port/devsdp.c:2002,2008 – 1999/1021/sys/src/9/port/devsdp.c:2001,2007 | ||
| 1999/1016 | b->rp[3] = c->in.seq; bb = allocb(BLEN(b)); | |
| 1999/1019 |
| |
| 1999/1021 | nn = thwack(c->out.compstate, bb->wp, b->rp, BLEN(b), seq); | |
| 1999/1016 | if(nn < 0) { freeb(bb); *bp = b; | |
| 1999/1021/sys/src/9/port/devsdp.c:19,24 – 1999/1022/sys/src/9/port/devsdp.c:19,25 (short | long) | ||
| 1999/0929 | typedef struct Stats Stats; typedef struct AckPkt AckPkt; | |
| 1999/1001 | typedef struct Algorithm Algorithm; | |
| 1999/1022 | typedef struct CipherRc4 CipherRc4; | |
| 1999/0824 | enum { | |
| 1999/1021/sys/src/9/port/devsdp.c:70,75 – 1999/1022/sys/src/9/port/devsdp.c:71,77 | ||
| 1999/1016 | ulong inBadComp; | |
| 1999/0929 | ulong inBadAuth; ulong inBadSeq; | |
| 1999/1022 | ulong inBadOther; | |
| 1999/0929 | }; | |
| 1999/0907 | struct OneWay | |
| 1999/1021/sys/src/9/port/devsdp.c:141,149 – 1999/1022/sys/src/9/port/devsdp.c:143,151 | ||
| 1999/0907 | char owner[NAMELEN]; /* protections */ | |
| 1999/0901 | int perm; | |
| 1999/1001 |
| |
| 1999/1022 | Algorithm *auth; Algorithm *cipher; Algorithm *comp; | |
| 1999/0907 | ||
| 1999/0906 | int drop; | |
| 1999/1021/sys/src/9/port/devsdp.c:203,208 – 1999/1022/sys/src/9/port/devsdp.c:205,211 | ||
| 1999/1016 | uchar inBadComp[4]; | |
| 1999/0929 | uchar inBadAuth[4]; uchar inBadSeq[4]; | |
| 1999/1022 | uchar inBadOther[4]; | |
| 1999/0929 | }; | |
| 1999/0907 | ||
| 1999/1001 | struct Algorithm | |
| 1999/1021/sys/src/9/port/devsdp.c:209,217 – 1999/1022/sys/src/9/port/devsdp.c:212,236 | ||
| 1999/1001 | { char *name; int keylen; // in bytes | |
| 1999/1022 | void (*init)(Conv*); | |
| 1999/1001 | }; | |
| 1999/0929 | ||
| 1999/1022 | 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; }; | |
| 1999/0824 | static Dirtab sdpdirtab[]={ "log", {Qlog}, 0, 0666, | |
| 1999/0901 | "clone", {Qclone}, 0, 0666, | |
| 1999/1021/sys/src/9/port/devsdp.c:279,295 – 1999/1022/sys/src/9/port/devsdp.c:298,314 | ||
| 1999/0914 | static void convopenchan(Conv *c, char *path); | |
| 1999/0929 | static void convstats(Conv *c, int local, char *buf, int n); | |
| 1999/0824 | ||
| 1999/1015 |
| |
| 1999/1022 | static void setalg(Conv *c, char *name, Algorithm *tab, Algorithm **); | |
| 1999/1015 | static void setsecret(OneWay *cc, char *secret); | |
| 1999/1022 | 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); | |
| 1999/1015 | static Algorithm cipheralg[] = { | |
| 1999/1021/sys/src/9/port/devsdp.c:296,301 – 1999/1022/sys/src/9/port/devsdp.c:315,321 | ||
| 1999/1015 | "null", 0, nullcipherinit, "des_56_cbc", 7, descipherinit, "rc4_128", 16, rc4cipherinit, | |
| 1999/1022 | "rc4_256", 32, rc4cipherinit, | |
| 1999/1015 | nil, 0, nil, }; | |
| 1999/1021/sys/src/9/port/devsdp.c:617,639 – 1999/1022/sys/src/9/port/devsdp.c:637,667 | ||
| 1999/1015 | } else if(strcmp(arg0, "cipher") == 0) { if(cb->nf != 2) error("usage: cipher alg"); | |
| 1999/1022 | setalg(c, cb->f[1], cipheralg, &c->cipher); | |
| 1999/1015 | } else if(strcmp(arg0, "auth") == 0) { if(cb->nf != 2) error("usage: auth alg"); | |
| 1999/1022 | setalg(c, cb->f[1], authalg, &c->auth); | |
| 1999/1015 | } else if(strcmp(arg0, "comp") == 0) { if(cb->nf != 2) error("usage: comp alg"); | |
| 1999/1022 | setalg(c, cb->f[1], compalg, &c->comp); | |
| 1999/1015 | } else if(strcmp(arg0, "insecret") == 0) { if(cb->nf != 2) error("usage: insecret secret"); setsecret(&c->in, cb->f[1]); | |
| 1999/1022 | if(c->cipher) c->cipher->init(c); if(c->auth) c->auth->init(c); | |
| 1999/1015 | } else if(strcmp(arg0, "outsecret") == 0) { if(cb->nf != 2) error("usage: outsecret secret"); setsecret(&c->out, cb->f[1]); | |
| 1999/1022 | if(c->cipher) c->cipher->init(c); if(c->auth) c->auth->init(c); | |
| 1999/0824 | } else error("unknown control request"); poperror(); | |
| 1999/1021/sys/src/9/port/devsdp.c:934,940 – 1999/1022/sys/src/9/port/devsdp.c:962,968 | ||
| 1999/1015 | hnputl(c->out.secret, c->acceptid); hnputl(c->out.secret+4, c->dialid); | |
| 1999/0906 | } | |
| 1999/1015 |
| |
| 1999/1022 | setalg(c, "hmac_md5_96", authalg, &c->auth); | |
| 1999/0906 | break; | |
| 1999/0910 | case CLocalClose: assert(c->state == CAccept || c->state == COpen); | |
| 1999/1021/sys/src/9/port/devsdp.c:961,969 – 1999/1022/sys/src/9/port/devsdp.c:989,997 | ||
| 1999/0910 | free(c->channame); c->channame = nil; } | |
| 1999/1016 |
| |
| 1999/1022 | c->cipher = nil; c->auth = nil; c->comp = nil; | |
| 1999/1001 | strcpy(c->owner, "network"); | |
| 1999/0907 | c->perm = 0660; c->dialid = 0; | |
| 1999/1021/sys/src/9/port/devsdp.c:1045,1051 – 1999/1022/sys/src/9/port/devsdp.c:1073,1078 | ||
| 1999/1019 | continue; p += snprint(p, ep-p, "outCompStats[%d]: %lud\n", i, stats->outCompStats[i]); } | |
| 1999/1021/sys/src/9/port/devsdp.c:1056,1061 – 1999/1022/sys/src/9/port/devsdp.c:1083,1089 | ||
| 1999/1019 | 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); | |
| 1999/1022 | p += snprint(p, ep-p, "inBadOther: %lud\n", stats->inBadOther); | |
| 1999/0929 | USED(p); qunlock(c); } | |
| 1999/1021/sys/src/9/port/devsdp.c:1090,1095 – 1999/1022/sys/src/9/port/devsdp.c:1118,1124 | ||
| 1999/1016 | hnputl(ack->inBadComp, s->inBadComp); | |
| 1999/0929 | hnputl(ack->inBadAuth, s->inBadAuth); hnputl(ack->inBadSeq, s->inBadSeq); | |
| 1999/1022 | hnputl(ack->inBadOther, s->inBadOther); | |
| 1999/1015 | convoput(c, TControl, ControlAck, b); | |
| 1999/0929 | } | |
| 1999/1021/sys/src/9/port/devsdp.c:1101,1110 – 1999/1022/sys/src/9/port/devsdp.c:1130,1141 | ||
| 1999/1015 | int type, subtype; ulong seq, seqwrap; | |
| 1999/1001 | long seqdiff; | |
| 1999/1022 | int pad; | |
| 1999/0907 | ||
| 1999/0930 | c->lstats.inPackets++; | |
| 1999/0929 | ||
| 1999/0907 | if(BLEN(b) < 4) { | |
| 1999/1022 | c->lstats.inBadOther++; | |
| 1999/0907 | freeb(b); return nil; } | |
| 1999/1021/sys/src/9/port/devsdp.c:1160,1166 – 1999/1022/sys/src/9/port/devsdp.c:1191,1215 | ||
| 1999/1015 | b->wp -= c->in.authlen; } | |
| 1999/0907 |
| |
| 1999/1022 | 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; } } | |
| 1999/0907 | // ok the packet is good | |
| 1999/1001 | if(seqdiff > 0) { | |
| 1999/1021/sys/src/9/port/devsdp.c:1206,1211 – 1999/1022/sys/src/9/port/devsdp.c:1255,1261 | ||
| 1999/1001 | return b; | |
| 1999/0907 | } print("droping packet %d n=%ld\n", type, BLEN(b)); | |
| 1999/1022 | c->lstats.inBadOther++; | |
| 1999/0907 | freeb(b); return nil; } | |
| 1999/1021/sys/src/9/port/devsdp.c:1324,1329 – 1999/1022/sys/src/9/port/devsdp.c:1374,1380 | ||
| 1999/1015 | { ulong cseq; AckPkt *ack; | |
| 1999/1022 | int i; | |
| 1999/1015 | if(BLEN(b) < 4) return; | |
| 1999/1021/sys/src/9/port/devsdp.c:1366,1371 – 1999/1022/sys/src/9/port/devsdp.c:1417,1424 | ||
| 1999/1015 | c->rstats.outDataPackets = nhgetl(ack->outDataPackets); c->rstats.outDataBytes = nhgetl(ack->outDataBytes); c->rstats.outCompDataBytes = nhgetl(ack->outCompDataBytes); | |
| 1999/1022 | for(i=0; i<NCompStats; i++) c->rstats.outCompStats[i] = nhgetl(ack->outCompStats + 4*i); | |
| 1999/1015 | c->rstats.inPackets = nhgetl(ack->inPackets); c->rstats.inDataPackets = nhgetl(ack->inDataPackets); c->rstats.inDataBytes = nhgetl(ack->inDataBytes); | |
| 1999/1021/sys/src/9/port/devsdp.c:1376,1381 – 1999/1022/sys/src/9/port/devsdp.c:1429,1435 | ||
| 1999/1016 | c->rstats.inBadComp = nhgetl(ack->inBadComp); | |
| 1999/1015 | c->rstats.inBadAuth = nhgetl(ack->inBadAuth); c->rstats.inBadSeq = nhgetl(ack->inBadSeq); | |
| 1999/1022 | c->rstats.inBadOther = nhgetl(ack->inBadOther); | |
| 1999/1015 | freeb(b); freeb(c->out.controlpkt); c->out.controlpkt = nil; | |
| 1999/1021/sys/src/9/port/devsdp.c:1418,1425 – 1999/1022/sys/src/9/port/devsdp.c:1472,1494 | ||
| 1999/0907 | static void | |
| 1999/1015 | convoput(Conv *c, int type, int subtype, Block *b) | |
| 1999/0907 | { | |
| 1999/1022 | int pad; | |
| 1999/0929 | c->lstats.outPackets++; | |
| 1999/1022 | /* 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; } | |
| 1999/0907 | /* Make space to fit sdp header */ b = padblock(b, 4 + c->out.cipherivlen); | |
| 1999/1015 | b->rp[0] = (type << 4) | subtype; | |
| 1999/1021/sys/src/9/port/devsdp.c:1432,1441 – 1999/1022/sys/src/9/port/devsdp.c:1501,1511 | ||
| 1999/0907 | b->rp[2] = c->out.seq>>8; b->rp[3] = c->out.seq; | |
| 1999/1022 | if(c->out.cipher) (*c->out.cipher)(&c->out, b->rp+4, BLEN(b)-4); | |
| 1999/0907 | // auth | |
| 1999/1015 | if(c->out.auth) { | |
| 1999/1021/sys/src/9/port/devsdp.c:1710,1716 – 1999/1022/sys/src/9/port/devsdp.c:1780,1786 | ||
| 1999/1015 | /* ciphers, authenticators, and compressors */ static void | |
| 1999/1022 | setalg(Conv *c, char *name, Algorithm *alg, Algorithm **p) | |
| 1999/1015 | { for(; alg->name; alg++) if(strcmp(name, alg->name) == 0) | |
| 1999/1021/sys/src/9/port/devsdp.c:1718,1724 – 1999/1022/sys/src/9/port/devsdp.c:1788,1795 | ||
| 1999/1015 | if(alg->name == nil) error("unknown algorithm"); | |
| 1999/1022 | *p = alg; alg->init(c); | |
| 1999/1015 | } static void | |
| 1999/1021/sys/src/9/port/devsdp.c:1771,1777 – 1999/1022/sys/src/9/port/devsdp.c:1842,1847 | ||
| 1999/1015 | static void cipherfree(Conv *c) { | |
| 1999/1016 |
| |
| 1999/1015 | if(c->in.cipherstate) { free(c->in.cipherstate); c->in.cipherstate = nil; | |
| 1999/1021/sys/src/9/port/devsdp.c:1781,1792 – 1999/1022/sys/src/9/port/devsdp.c:1851,1865 | ||
| 1999/1015 | c->out.cipherstate = nil; } c->in.cipher = nil; | |
| 1999/1022 | c->in.cipherblklen = 0; c->out.cipherblklen = 0; c->in.cipherivlen = 0; c->out.cipherivlen = 0; | |
| 1999/1015 | } static void authfree(Conv *c) { | |
| 1999/1016 |
| |
| 1999/1015 | if(c->in.authstate) { free(c->in.authstate); c->in.authstate = nil; | |
| 1999/1021/sys/src/9/port/devsdp.c:1796,1807 – 1999/1022/sys/src/9/port/devsdp.c:1869,1881 | ||
| 1999/1015 | c->out.authstate = nil; } c->in.auth = nil; | |
| 1999/1022 | c->in.authlen = 0; c->out.authlen = 0; | |
| 1999/1015 | } static void compfree(Conv *c) { | |
| 1999/1016 |
| |
| 1999/1015 | if(c->in.compstate) { free(c->in.compstate); c->in.compstate = nil; | |
| 1999/1021/sys/src/9/port/devsdp.c:1814,1820 – 1999/1022/sys/src/9/port/devsdp.c:1888,1894 | ||
| 1999/1015 | } static void | |
| 1999/1022 | nullcipherinit(Conv *c) | |
| 1999/1015 | { cipherfree(c); } | |
| 1999/1021/sys/src/9/port/devsdp.c:1825,1830 – 1999/1022/sys/src/9/port/devsdp.c:1899,1906 | ||
| 1999/1015 | uchar *pp, *ip, *eip, *ep; DESstate *ds = ow->cipherstate; | |
| 1999/1022 | if(n < 8 || (n & 0x7 != 0)) return 0; | |
| 1999/1015 | ep = p + n; memmove(p, ds->ivec, 8); for(p += 8; p < ep; p += 8){ | |
| 1999/1021/sys/src/9/port/devsdp.c:1845,1850 – 1999/1022/sys/src/9/port/devsdp.c:1921,1928 | ||
| 1999/1015 | uchar *tp, *ip, *eip, *ep; DESstate *ds = ow->cipherstate; | |
| 1999/1022 | if(n < 8 || (n & 0x7 != 0)) return 0; | |
| 1999/1015 | ep = p + n; memmove(ds->ivec, p, 8); p += 8; | |
| 1999/1021/sys/src/9/port/devsdp.c:1862,1875 – 1999/1022/sys/src/9/port/devsdp.c:1940,1953 | ||
| 1999/1015 | } static void | |
| 1999/1022 | descipherinit(Conv *c) | |
| 1999/1015 | { uchar key[8]; uchar ivec[8]; int i; | |
| 1999/1022 | int n = c->cipher->keylen; | |
| 1999/1015 | cipherfree(c); | |
| 1999/1016 |
| |
| 1999/1015 | if(n > sizeof(key)) n = sizeof(key); | |
| 1999/1021/sys/src/9/port/devsdp.c:1896,1915 – 1999/1022/sys/src/9/port/devsdp.c:1974,2099 | ||
| 1999/1015 | setupDESstate(c->out.cipherstate, key, ivec); } | |
| 1999/1022 | 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; } | |
| 1999/1015 | static void | |
| 1999/1022 | rc4cipherinit(Conv *c) | |
| 1999/1015 | { | |
| 1999/1022 | uchar key[32]; CipherRc4 *cr; int n; | |
| 1999/1016 | cipherfree(c); | |
| 1999/1022 | 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; | |
| 1999/1015 | } static void | |
| 1999/1022 | nullauthinit(Conv *c) | |
| 1999/1015 | { authfree(c); } static void | |
| 1999/1022 | shaauthinit(Conv *c) | |
| 1999/1015 | { authfree(c); } | |
| 1999/1021/sys/src/9/port/devsdp.c:1957,1968 – 1999/1022/sys/src/9/port/devsdp.c:2141,2153 | ||
| 1999/1015 | } static void | |
| 1999/1022 | md5authinit(Conv *c) | |
| 1999/1015 | { | |
| 1999/1022 | int keylen; | |
| 1999/1015 | authfree(c); | |
| 1999/1016 |
| |
| 1999/1015 | ||
| 1999/1022 | keylen = c->auth->keylen; | |
| 1999/1015 | if(keylen > 16) keylen = 16; | |
| 1999/1021/sys/src/9/port/devsdp.c:1982,1988 – 1999/1022/sys/src/9/port/devsdp.c:2167,2173 | ||
| 1999/1015 | } static void | |
| 1999/1016 |
| |
| 1999/1022 | nullcompinit(Conv *c) | |
| 1999/1015 | { | |
| 1999/1016 | compfree(c); | |
| 1999/1015 | } | |
| 1999/1021/sys/src/9/port/devsdp.c:2001,2007 – 1999/1022/sys/src/9/port/devsdp.c:2186,2192 | ||
| 1999/1016 | b->rp[3] = c->in.seq; bb = allocb(BLEN(b)); | |
| 1999/1021 |
| |
| 1999/1022 | nn = thwack(c->out.compstate, bb->wp, b->rp, BLEN(b), seq, c->lstats.outCompStats); | |
| 1999/1016 | if(nn < 0) { freeb(bb); *bp = b; | |
| 1999/1021/sys/src/9/port/devsdp.c:2053,2063 – 1999/1022/sys/src/9/port/devsdp.c:2238,2247 | ||
| 1999/1016 | } | |
| 1999/1015 | ||
| 1999/1016 | static void | |
| 1999/1022 | thwackcompinit(Conv *c) | |
| 1999/1016 | { compfree(c); | |
| 1999/1015 | ||
| 1999/1016 |
| |
| 1999/1022/sys/src/9/port/devsdp.c:330,336 – 1999/1027/sys/src/9/port/devsdp.c:330,336 (short | long) | ||
| 1999/1015 | static Algorithm compalg[] = { "null", 0, nullcompinit, | |
| 1999/1027 | // "thwack", 0, thwackcompinit, | |
| 1999/1015 | nil, 0, nil, }; | |
| 1999/1022/sys/src/9/port/devsdp.c:340,345 – 1999/1027/sys/src/9/port/devsdp.c:340,347 | ||
| 1999/0824 | { int i; Dirtab *dt; | |
| 1999/1027 | return; | |
| 1999/0824 | // setup dirtab with non directory entries for(i=0; i<nelem(sdpdirtab); i++) { | |
| 1999/1022/sys/src/9/port/devsdp.c:367,373 – 1999/1027/sys/src/9/port/devsdp.c:369,375 | ||
| 1999/0824 | if(dev<0 || dev >= Nfs) error("bad specification"); | |
| 1999/0901 |
| |
| 1999/1027 | c = devattach('E', spec); | |
| 1999/0824 | c->qid = (Qid){QID(0, Qtopdir)|CHDIR, 0}; c->dev = dev; | |
| 1999/1022/sys/src/9/port/devsdp.c:556,561 – 1999/1027/sys/src/9/port/devsdp.c:558,564 | ||
| 1999/0901 | return readstr(off, a, n, buf); | |
| 1999/0907 | case Qcontrol: b = readcontrol(sdp->conv[CONV(ch->qid)], n); | |
| 1999/1027 | print("readcontrol asked %ld\n", n); | |
| 1999/0907 | if(b == nil) return 0; | |
| 1999/0914 | print("readcontrol asked %ld got %ld\n", n, BLEN(b)); | |
| 1999/1022/sys/src/9/port/devsdp.c:905,911 – 1999/1027/sys/src/9/port/devsdp.c:908,914 | ||
| 1999/0902 | } | |
| 1999/0824 | Dev sdpdevtab = { | |
| 1999/1027 | 'E', | |
| 1999/0824 | "sdp", devreset, | |
| 1999/1022/sys/src/9/port/devsdp.c:971,977 – 1999/1027/sys/src/9/port/devsdp.c:974,980 | ||
| 1999/0906 | break; | |
| 1999/0910 | case CRemoteClose: | |
| 1999/0914 | wakeup(&c->in.controlready); | |
| 1999/1015 |
| |
| 1999/1027 | // convoconnect(c, ConReset, c->dialid, c->acceptid); | |
| 1999/0910 | break; | |
| 1999/0906 | case CClosed: | |
| 1999/0914 | wakeup(&c->in.controlready); | |
| 1999/1027/sys/src/9/port/devsdp.c:330,336 – 1999/1028/sys/src/9/port/devsdp.c:330,336 (short | long) | ||
| 1999/1015 | static Algorithm compalg[] = { "null", 0, nullcompinit, | |
| 1999/1027 |
| |
| 1999/1028 | "thwack", 0, thwackcompinit, | |
| 1999/1015 | nil, 0, nil, }; | |
| 1999/1027/sys/src/9/port/devsdp.c:558,564 – 1999/1028/sys/src/9/port/devsdp.c:558,563 | ||
| 1999/0901 | return readstr(off, a, n, buf); | |
| 1999/0907 | case Qcontrol: b = readcontrol(sdp->conv[CONV(ch->qid)], n); | |
| 1999/1027 |
| |
| 1999/0907 | if(b == nil) return 0; | |
| 1999/0914 | print("readcontrol asked %ld got %ld\n", n, BLEN(b)); | |
| 1999/1028/sys/src/9/port/devsdp.c:1185,1191 – 1999/1031/sys/src/9/port/devsdp.c:1185,1191 (short | long) | ||
| 1999/0930 | if(0) print("coniput seq=%ulx\n", seq); | |
| 1999/1015 | if(c->in.auth != 0) { if(!(*c->in.auth)(&c->in, b->rp-4, BLEN(b)+4)) { | |
| 1999/1031 | print("bad auth %d\n", BLEN(b)+4); | |
| 1999/1015 | c->lstats.inBadAuth++; freeb(b); return nil; | |
| 1999/1028/sys/src/9/port/devsdp.c:1726,1732 – 1999/1031/sys/src/9/port/devsdp.c:1726,1732 | ||
| 1999/0930 | c->lstats.outDataPackets++; c->lstats.outDataBytes += n; | |
| 1999/1001 | ||
| 1999/1015 |
| |
| 1999/1031 | if(c->out.comp != nil && 0) { | |
| 1999/1016 | // must generate same value as convoput seq = (c->out.seq + 1) & (SeqMax-1); | |
| 1999/1031/sys/src/9/port/devsdp.c:1185,1191 – 1999/1106/sys/src/9/port/devsdp.c:1185,1191 (short | long) | ||
| 1999/0930 | if(0) print("coniput seq=%ulx\n", seq); | |
| 1999/1015 | if(c->in.auth != 0) { if(!(*c->in.auth)(&c->in, b->rp-4, BLEN(b)+4)) { | |
| 1999/1031 |
| |
| 1999/1106 | print("bad auth %ld\n", BLEN(b)+4); | |
| 1999/1015 | c->lstats.inBadAuth++; freeb(b); return nil; | |
| 1999/1031/sys/src/9/port/devsdp.c:1686,1694 – 1999/1106/sys/src/9/port/devsdp.c:1686,1702 | ||
| 1999/0907 | readdata(Conv *c, int n) { Block *b; | |
| 1999/1106 | int nn; | |
| 1999/0907 | for(;;) { | |
| 1999/1106 | // 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); | |
| 1999/0930 | if(b == nil) return nil; | |
| 1999/0907 | qlock(c); | |
| 1999/1031/sys/src/9/port/devsdp.c:1699,1706 – 1999/1106/sys/src/9/port/devsdp.c:1707,1717 | ||
| 1999/0907 | b = conviput(c, b, 0); poperror(); qunlock(c); | |
| 1999/1106 | if(b != nil) { if(BLEN(b) > n) b->wp = b->rp + n; | |
| 1999/0907 | return b; | |
| 1999/1106 | } | |
| 1999/0907 | } | |
| 1999/0910 | } | |
| 1999/1031/sys/src/9/port/devsdp.c:1726,1732 – 1999/1106/sys/src/9/port/devsdp.c:1737,1743 | ||
| 1999/0930 | c->lstats.outDataPackets++; c->lstats.outDataBytes += n; | |
| 1999/1001 | ||
| 1999/1031 |
| |
| 1999/1106 | if(0 && c->out.comp != nil) { | |
| 1999/1016 | // must generate same value as convoput seq = (c->out.seq + 1) & (SeqMax-1); | |
| 1999/1106/sys/src/9/port/devsdp.c:1737,1743 – 1999/1111/sys/src/9/port/devsdp.c:1737,1743 (short | long) | ||
| 1999/0930 | c->lstats.outDataPackets++; c->lstats.outDataBytes += n; | |
| 1999/1001 | ||
| 1999/1106 |
| |
| 1999/1111 | if(c->out.comp != nil) { | |
| 1999/1016 | // must generate same value as convoput seq = (c->out.seq + 1) & (SeqMax-1); | |
| 1999/1111/sys/src/9/port/devsdp.c:341,348 – 1999/1116/sys/src/9/port/devsdp.c:341,346 (short | long) | ||
| 1999/0824 | int i; Dirtab *dt; | |
| 1999/1027 |
| |
| 1999/0824 |
| |
| 1999/1111/sys/src/9/port/devsdp.c:774,780 – 1999/1116/sys/src/9/port/devsdp.c:772,778 | ||
| 1999/0901 | break; } if(canqlock(c)){ | |
| 1999/0910 |
| |
| 1999/1116 | if(c->state == CClosed && c->reader == 0 && c->ref == 0) | |
| 1999/0901 | break; qunlock(c); } | |
| 1999/1116/sys/src/9/port/devsdp.c:41,48 – 1999/1211/sys/src/9/port/devsdp.c:41,48 (short | long) | ||
| 1999/0824 | ||
| 1999/0907 | Maxconv= 256, // power of 2 Nfs= 4, // number of file systems | |
| 1999/1001 |
| |
| 1999/0909 |
| |
| 1999/1211 | MaxRetries= 4, KeepAlive = 10, // keep alive in seconds | |
| 1999/1015 | SecretLength= 32, // a secret per direction | |
| 1999/1001 | SeqMax = (1<<24), SeqWindow = 32, | |
| 1999/1116/sys/src/9/port/devsdp.c:104,109 – 1999/1211/sys/src/9/port/devsdp.c:104,110 | ||
| 1999/0901 | ||
| 1999/0907 | // conv states | |
| 1999/0902 | enum { | |
| 1999/1211 | CFree, | |
| 1999/0906 | CInit, | |
| 1999/0909 | CDial, CAccept, | |
| 1999/1116/sys/src/9/port/devsdp.c:115,126 – 1999/1211/sys/src/9/port/devsdp.c:116,130 | ||
| 1999/0902 | ||
| 1999/0901 | struct Conv { QLock; | |
| 1999/0824 |
| |
| 1999/0906 |
| |
| 1999/0824 | Sdp *sdp; | |
| 1999/1211 | int id; | |
| 1999/0901 | ||
| 1999/1211 | int ref; // holds conv up | |
| 1999/0902 | int state; | |
| 1999/0906 |
| |
| 1999/1211 | int dataopen; // ref count of opens on Qdata int controlopen; // ref count of opens on Qcontrol | |
| 1999/0910 | int reader; // reader proc has been started | |
| 1999/0901 | ||
| 1999/0929 | Stats lstats; | |
| 1999/1116/sys/src/9/port/devsdp.c:137,143 – 1999/1211/sys/src/9/port/devsdp.c:141,147 | ||
| 1999/0910 | QLock readlk; // protects readproc | |
| 1999/0907 | Proc *readproc; | |
| 1999/0910 | ||
| 1999/0902 |
| |
| 1999/1211 | Chan *chan; // packet channel | |
| 1999/0910 | char *channame; | |
| 1999/0902 | ||
| 1999/0907 | char owner[NAMELEN]; /* protections */ | |
| 1999/1116/sys/src/9/port/devsdp.c:268,302 – 1999/1211/sys/src/9/port/devsdp.c:272,308 | ||
| 1999/0824 | static Dirtab *dirtab[MaxQ]; static Sdp sdptab[Nfs]; | |
| 1999/0908 | static char *convstatename[] = { | |
| 1999/0909 |
| |
| 1999/0908 |
| |
| 1999/1211 | [CFree] "Free", [CInit] "Init", [CDial] "Dial", [CAccept] "Accept", [COpen] "Open", | |
| 1999/0910 | [CLocalClose] "LocalClose", [CRemoteClose] "RemoteClose", | |
| 1999/0908 |
| |
| 1999/1211 | [CClosed] "Closed", | |
| 1999/0908 | }; | |
| 1999/0824 | static int sdpgen(Chan *c, Dirtab*, int, int s, Dir *dp); | |
| 1999/0901 | static Conv *sdpclone(Sdp *sdp); | |
| 1999/0906 |
| |
| 1999/0907 | static void onewaycleanup(OneWay *ow); static int readready(void *a); static int controlread(); | |
| 1999/1211 | 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); | |
| 1999/0907 | static Block *conviput(Conv *c, Block *b, int control); | |
| 1999/1015 | static void conviconnect(Conv *c, int op, Block *b); static void convicontrol(Conv *c, int op, Block *b); | |
| 1999/1016 | static Block *convicomp(Conv *c, int op, ulong, Block *b); | |
| 1999/0929 |
| |
| 1999/0907 |
| |
| 1999/0915 |
| |
| 1999/1015 | static void convoput(Conv *c, int type, int subtype, Block *b); static void convoconnect(Conv *c, int op, ulong dialid, ulong acceptid); | |
| 1999/0910 |
| |
| 1999/0914 | static void convopenchan(Conv *c, char *path); | |
| 1999/0929 | static void convstats(Conv *c, int local, char *buf, int n); | |
| 1999/1211 | static void convreader(void *a); | |
| 1999/0824 | ||
| 1999/1022 | static void setalg(Conv *c, char *name, Algorithm *tab, Algorithm **); | |
| 1999/1015 | static void setsecret(OneWay *cc, char *secret); | |
| 1999/1116/sys/src/9/port/devsdp.c:412,417 – 1999/1211/sys/src/9/port/devsdp.c:418,424 | ||
| 1999/0824 | devstat(c, db, nil, 0, sdpgen); } | |
| 1999/1211 | ||
| 1999/0824 | static Chan* | |
| 1999/0901 | sdpopen(Chan* ch, int omode) | |
| 1999/0824 | { | |
| 1999/1116/sys/src/9/port/devsdp.c:450,455 – 1999/1211/sys/src/9/port/devsdp.c:457,463 | ||
| 1999/0929 | case Qstats: case Qrstats: | |
| 1999/0902 | c = sdp->conv[CONV(ch->qid)]; | |
| 1999/1211 | print("open %d:%d: ref=%d\n", c->id, TYPE(ch->qid), c->ref); | |
| 1999/0902 | qlock(c); if(waserror()) { qunlock(c); | |
| 1999/1116/sys/src/9/port/devsdp.c:458,469 – 1999/1211/sys/src/9/port/devsdp.c:466,481 | ||
| 1999/0902 | if((perm & (c->perm>>6)) != perm) | |
| 1999/0907 | if(strcmp(up->user, c->owner) != 0 || (perm & c->perm) != perm) | |
| 1999/0902 | error(Eperm); | |
| 1999/1211 | ||
| 1999/0902 | c->ref++; | |
| 1999/0910 | if(TYPE(ch->qid) == Qdata) { | |
| 1999/1211 | c->dataopen++; // kill reader if Qdata is opened for the first time if(c->dataopen == 1) | |
| 1999/0910 | if(c->readproc != nil) postnote(c->readproc, 1, "interrupt", 0); | |
| 1999/0907 |
| |
| 1999/1211 | } else if(TYPE(ch->qid) == Qcontrol) { c->controlopen++; | |
| 1999/0910 | } | |
| 1999/0902 | qunlock(c); poperror(); | |
| 1999/1116/sys/src/9/port/devsdp.c:481,512 – 1999/1211/sys/src/9/port/devsdp.c:493,537 | ||
| 1999/0902 | Sdp *sdp = sdptab + ch->dev; | |
| 1999/0907 | Conv *c; | |
| 1999/0824 | ||
| 1999/1211 | if(!(ch->flag & COPEN)) return; | |
| 1999/0902 | switch(TYPE(ch->qid)) { | |
| 1999/0824 | case Qlog: | |
| 1999/0902 |
| |
| 1999/0824 |
| |
| 1999/1211 | logclose(sdp); | |
| 1999/0824 | break; | |
| 1999/0907 |
| |
| 1999/1211 | case Qstats: case Qrstats: | |
| 1999/0907 | c = sdp->conv[CONV(ch->qid)]; qlock(c); | |
| 1999/1211 | 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(); | |
| 1999/0907 | } | |
| 1999/0915 |
| |
| 1999/0907 |
| |
| 1999/1211 | qunlock(c); break; case Qcontrol: c = sdp->conv[CONV(ch->qid)]; qlock(c); c->controlopen--; convderef(c); if(c->controlopen == 0 && c->ref != 0) { | |
| 1999/0907 | switch(c->state) { default: convsetstate(c, CClosed); | |
| 1999/1116/sys/src/9/port/devsdp.c:515,522 – 1999/1211/sys/src/9/port/devsdp.c:540,545 | ||
| 1999/0907 | case COpen: | |
| 1999/0910 | convsetstate(c, CLocalClose); | |
| 1999/0907 | break; | |
| 1999/0910 |
| |
| 1999/0907 | } } qunlock(c); | |
| 1999/1116/sys/src/9/port/devsdp.c:771,778 – 1999/1211/sys/src/9/port/devsdp.c:794,802 | ||
| 1999/0901 | sdp->nconv++; break; } | |
| 1999/1116 |
| |
| 1999/1211 | 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) | |
| 1999/0901 | break; qunlock(c); } | |
| 1999/1116/sys/src/9/port/devsdp.c:783,789 – 1999/1211/sys/src/9/port/devsdp.c:807,815 | ||
| 1999/0902 | if(pp >= ep) | |
| 1999/0901 | return nil; | |
| 1999/0902 |
| |
| 1999/1211 | assert(c->state == CFree); // set ref to 2 - 1 ref for open - 1 ref for channel state c->ref = 2; | |
| 1999/0906 | c->state = CInit; | |
| 1999/1001 | c->in.window = ~0; | |
| 1999/0907 | strncpy(c->owner, up->user, sizeof(c->owner)); | |
| 1999/1116/sys/src/9/port/devsdp.c:819,824 – 1999/1211/sys/src/9/port/devsdp.c:845,851 | ||
| 1999/0906 | return 1; } | |
| 1999/1211 | // assumes c is locked | |
| 1999/0902 | static void | |
| 1999/0906 | convtimer(Conv *c, ulong sec) | |
| 1999/0902 | { | |
| 1999/1116/sys/src/9/port/devsdp.c:826,837 – 1999/1211/sys/src/9/port/devsdp.c:853,862 | ||
| 1999/0914 | ||
| 1999/1001 | if(c->timeout > sec) | |
| 1999/0906 | return; | |
| 1999/0902 |
| |
| 1999/0906 |
| |
| 1999/0902 |
| |
| 1999/0906 |
| |
| 1999/0902 |
| |
| 1999/1211 | ||
| 1999/0906 | switch(c->state) { | |
| 1999/1211 | case CInit: break; | |
| 1999/0909 | case CDial: | |
| 1999/0914 | if(convretry(c, 1)) | |
| 1999/1015 | convoconnect(c, ConOpenRequest, c->dialid, 0); | |
| 1999/1116/sys/src/9/port/devsdp.c:873,883 – 1999/1211/sys/src/9/port/devsdp.c:898,905 | ||
| 1999/0906 | break; | |
| 1999/0914 | case CRemoteClose: case CClosed: | |
| 1999/1001 |
| |
| 1999/0914 | break; | |
| 1999/0906 | } | |
| 1999/0914 |
| |
| 1999/0906 |
| |
| 1999/0902 | ||
| 1999/1116/sys/src/9/port/devsdp.c:895,904 – 1999/1211/sys/src/9/port/devsdp.c:917,932 | ||
| 1999/0906 | qlock(sdp); for(i=0; i<sdp->nconv; i++) { c = sdp->conv[i]; | |
| 1999/1211 | if(c->ref == 0) continue; qunlock(sdp); qlock(c); if(c->ref > 0 && !waserror()) { | |
| 1999/0906 | convtimer(c, sec); poperror(); } | |
| 1999/1211 | qunlock(c); qlock(sdp); | |
| 1999/0906 | } qunlock(sdp); | |
| 1999/0902 | } | |
| 1999/1116/sys/src/9/port/devsdp.c:949,954 – 1999/1211/sys/src/9/port/devsdp.c:977,983 | ||
| 1999/0909 | break; | |
| 1999/0906 | case COpen: | |
| 1999/0909 | assert(c->state == CDial || c->state == CAccept); | |
| 1999/1211 | c->lastrecv = TK2SEC(m->ticks); | |
| 1999/0909 | if(c->state == CDial) { convretryinit(c); | |
| 1999/1015 | convoconnect(c, ConOpenAckAck, c->dialid, c->acceptid); | |
| 1999/1116/sys/src/9/port/devsdp.c:971,977 – 1999/1211/sys/src/9/port/devsdp.c:1000,1006 | ||
| 1999/0906 | break; | |
| 1999/0910 | case CRemoteClose: | |
| 1999/0914 | wakeup(&c->in.controlready); | |
| 1999/1027 |
| |
| 1999/1211 | wakeup(&c->out.controlready); | |
| 1999/0910 | break; | |
| 1999/0906 | case CClosed: | |
| 1999/0914 | wakeup(&c->in.controlready); | |
| 1999/1116/sys/src/9/port/devsdp.c:978,1014 – 1999/1211/sys/src/9/port/devsdp.c:1007,1058 | ||
| 1999/0915 | wakeup(&c->out.controlready); | |
| 1999/0907 | if(c->readproc) postnote(c->readproc, 1, "interrupt", 0); | |
| 1999/0915 |
| |
| 1999/0907 |
| |
| 1999/0915 |
| |
| 1999/0910 |
| |
| 1999/1022 |
| |
| 1999/1001 |
| |
| 1999/0907 |
| |
| 1999/1001 |
| |
| 1999/0907 |
| |
| 1999/1001 |
| |
| 1999/1211 | if(c->state != CClosed) convderef(c); | |
| 1999/0906 | break; } c->state = state; } | |
| 1999/1211 | //assumes c is locked | |
| 1999/0906 | static void | |
| 1999/1211 | 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 | |
| 1999/0907 | onewaycleanup(OneWay *ow) | |
| 1999/0906 | { | |
| 1999/0907 | if(ow->controlpkt) | |
| 1999/1116/sys/src/9/port/devsdp.c:1040,1046 – 1999/1211/sys/src/9/port/devsdp.c:1084,1095 | ||
| 1999/0914 | nexterror(); } kproc("convreader", convreader, c); | |
| 1999/1211 | assert(c->reader == 0 && c->ref > 0); // after kproc in case it fails | |
| 1999/0914 | c->reader = 1; | |
| 1999/1211 | c->ref++; | |
| 1999/0914 | poperror(); } | |
| 1999/0907 | ||
| 1999/1116/sys/src/9/port/devsdp.c:1215,1221 – 1999/1211/sys/src/9/port/devsdp.c:1264,1270 | ||
| 1999/1001 | if(seqdiff > 0) { while(seqdiff > 0 && c->in.window != 0) { if((c->in.window & (1<<(SeqWindow-1))) == 0) { | |
| 1999/1211 | //print("missing packet: %ld\n", seq - seqdiff); | |
| 1999/1001 | c->lstats.inMissing++; } c->in.window <<= 1; | |
| 1999/1116/sys/src/9/port/devsdp.c:1222,1228 – 1999/1211/sys/src/9/port/devsdp.c:1271,1277 | ||
| 1999/1001 | seqdiff--; } if(seqdiff > 0) { | |
| 1999/1211 | //print("missing packets: %ld-%ld\n", seq - SeqWindow - seqdiff+1, seq-SeqWindow); | |
| 1999/1001 | c->lstats.inMissing += seqdiff; } c->in.seq = seq; | |
| 1999/1116/sys/src/9/port/devsdp.c:1520,1529 – 1999/1211/sys/src/9/port/devsdp.c:1569,1575 | ||
| 1999/0930 | Block *b; | |
| 1999/0907 | ||
| 1999/0929 | c->lstats.outPackets++; | |
| 1999/0906 |
| |
| 1999/1211 | assert(c->chan != nil); | |
| 1999/1015 | b = allocb(9); b->wp[0] = (TConnect << 4) | op; hnputl(b->wp+1, dialid); | |
| 1999/1116/sys/src/9/port/devsdp.c:1530,1536 – 1999/1211/sys/src/9/port/devsdp.c:1576,1585 | ||
| 1999/1015 | hnputl(b->wp+5, acceptid); b->wp += 9; | |
| 1999/0906 | ||
| 1999/0930 |
| |
| 1999/1211 | if(!waserror()) { convwriteblock(c, b); poperror(); } | |
| 1999/0907 | } | |
| 1999/0910 | static Block * | |
| 1999/1116/sys/src/9/port/devsdp.c:1537,1549 – 1999/1211/sys/src/9/port/devsdp.c:1586,1596 | ||
| 1999/0910 | convreadblock(Conv *c, int n) { Block *b; | |
| 1999/1211 | Chan *ch; | |
| 1999/0910 | qlock(&c->readlk); if(waserror()) { c->readproc = nil; | |
| 1999/1116/sys/src/9/port/devsdp.c:1554,1565 – 1999/1211/sys/src/9/port/devsdp.c:1601,1611 | ||
| 1999/0910 | } c->readproc = up; ch = c->chan; | |
| 1999/1211 | assert(c->ref > 0); | |
| 1999/0910 | qunlock(c); b = devtab[ch->type]->bread(ch, n, 0); c->readproc = nil; | |
| 1999/1116/sys/src/9/port/devsdp.c:1770,1779 – 1999/1211/sys/src/9/port/devsdp.c:1816,1822 | ||
| 1999/0910 | if(b == nil) { | |
| 1999/0915 | print("up->error = %s\n", up->error); if(strcmp(up->error, Eintr) != 0) { | |
| 1999/1211 | convsetstate(c, CClosed); | |
| 1999/0915 | break; } } else if(!waserror()) { | |
| 1999/1116/sys/src/9/port/devsdp.c:1783,1788 – 1999/1211/sys/src/9/port/devsdp.c:1826,1832 | ||
| 1999/0910 | } | |
| 1999/0914 | print("convreader exiting\n"); | |
| 1999/0910 | c->reader = 0; | |
| 1999/1211 | convderef(c); | |
| 1999/0910 | qunlock(c); pexit("hangup", 1); | |
| 1999/0906 | } | |
| 1999/1116/sys/src/9/port/devsdp.c:2025,2031 – 1999/1211/sys/src/9/port/devsdp.c:2069,2075 | ||
| 1999/1022 | cr->ovalid = 0; } } else if(d > 0) { | |
| 1999/1211 | //print("missing packet: %uld %ld\n", seq, d); | |
| 1999/1022 | // this link is hosed if(d > RC4forward) return 0; | |
| 1999/1116/sys/src/9/port/devsdp.c:2039,2045 – 1999/1211/sys/src/9/port/devsdp.c:2083,2089 | ||
| 1999/1022 | rc4(&cr->current, p, n); cr->cseq = seq+n; } else { | |
| 1999/1211 | //print("reordered packet: %uld %ld\n", seq, d); | |
| 1999/1022 | dd = seq - cr->oseq; if(!cr->ovalid || -d > RC4back || dd < 0) return 0; | |
| 1999/1211/sys/src/9/port/devsdp.c:41,48 – 1999/1221/sys/src/9/port/devsdp.c:41,48 (short | long) | ||
| 1999/0824 | ||
| 1999/0907 | Maxconv= 256, // power of 2 Nfs= 4, // number of file systems | |
| 1999/1211 |
| |
| 1999/1221 | MaxRetries= 12, KeepAlive = 120, // keep alive in seconds | |
| 1999/1015 | SecretLength= 32, // a secret per direction | |
| 1999/1001 | SeqMax = (1<<24), SeqWindow = 32, | |
| Too many diffs (26 > 25). Stopping. | ||