From 2da1851522d11276da4f811f086c9bc51c3f8112 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 2 Sep 1999 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1999-09-02 --- port/devsdp.c | 174 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 132 insertions(+), 42 deletions(-) diff --git a/port/devsdp.c b/port/devsdp.c index c551b9f19291dcbc4ca3d40abb1ce1fae2c14dad..fa00dbb634a46b3861dbe941310649be73f77d26 100644 --- a/port/devsdp.c +++ b/port/devsdp.c @@ -8,9 +8,10 @@ #include -typedef struct Sdp Sdp; -typedef struct Conv Conv; -typedef struct OneWay OneWay; +typedef struct Sdp Sdp; +typedef struct Conv Conv; +typedef struct Out Out; +typedef struct In In; enum { @@ -23,8 +24,8 @@ enum Qconvdir, /* directory per conversation */ Qctl, - Qdata, /* reliable control channel */ - Qpacket, /* unreliable packet channel */ + Qdata, /* unreliable packet channel */ + Qcontrol, /* reliable control channel */ Qstatus, MaxQ, @@ -37,46 +38,79 @@ enum #define CONV(x) (((x).path >> 8)&(Maxconv-1)) #define QID(x, y) (((x)<<8) | (y)) -struct OneWay +struct Out { 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); + Block *controlpkt; // control channel + ulong *controlseq; + ulong controltimeout; // timeout when it will be resent + int controlretries; - char *aalg; - void *astate; // auth state - int alen; // auth data length in bytes - int (*auth)(OneWay*, uchar *buf, int len, uchar *hash); + 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); +}; + +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, }; struct Conv { QLock; - int id; + int ref; Sdp *sdp; - Chan chan; // packet channel + int state; + ulong session; + + Chan *chan; // packet channel char user[NAMELEN]; /* protections */ int perm; - int inuse; - int length; - int state; - OneWay in; - OneWay out; + In in; + Out out; }; struct Sdp { QLock; Log; int nconv; - Conv *conv[Maxconv]; + Conv *conv[Maxconv]; }; static Dirtab sdpdirtab[]={ @@ -88,7 +122,7 @@ static Dirtab sdpdirtab[]={ static Dirtab convdirtab[]={ "ctl", {Qctl}, 0, 0666, "data", {Qdata}, 0, 0666, - "packet", {Qpacket}, 0, 0666, + "control", {Qcontrol}, 0, 0666, "status", {Qstatus}, 0, 0444, }; @@ -199,7 +233,6 @@ sdpopen(Chan* ch, int omode) case Qtopdir: case Qsdpdir: case Qconvdir: - case Qstatus: case Qstats: if(omode != OREAD) error(Eperm); @@ -213,6 +246,23 @@ sdpopen(Chan* ch, int omode) error(Enodev); ch->qid.path = QID(c->id, Qctl); break; + 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; } ch->mode = openmode(omode); ch->flag |= COPEN; @@ -221,13 +271,13 @@ sdpopen(Chan* ch, int omode) } static void -sdpclose(Chan* c) +sdpclose(Chan* ch) { - Sdp *sdp = sdptab + c->dev; + Sdp *sdp = sdptab + ch->dev; - switch(TYPE(c->qid)) { + switch(TYPE(ch->qid)) { case Qlog: - if(c->flag & COPEN) + if(ch->flag & COPEN) logclose(sdp); break; } @@ -238,6 +288,7 @@ sdpread(Chan *ch, void *a, long n, vlong off) { char buf[256]; Sdp *sdp = sdptab + ch->dev; + char *s; Conv *c; USED(off); @@ -251,14 +302,26 @@ sdpread(Chan *ch, void *a, long n, vlong off) case Qlog: return logread(sdp, a, off, n); case Qstatus: - qlock(sdp); c = sdp->conv[CONV(ch->qid)]; - if(c == 0) - strcpy(buf, "unbound\n"); - else { + 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; } - n = readstr(off, a, n, buf); - qunlock(sdp); + n = readstr(off, a, n, s); + qunlock(c); return n; case Qctl: sprint(buf, "%lud", CONV(ch->qid)); @@ -364,6 +427,11 @@ sdpclone(Sdp *sdp) c = nil; ep = sdp->conv + nelem(sdp->conv); + qlock(sdp); + if(waserror()) { + qunlock(sdp); + nexterror(); + } for(pp = sdp->conv; pp < ep; pp++) { c = *pp; if(c == nil){ @@ -378,26 +446,48 @@ sdpclone(Sdp *sdp) break; } if(canqlock(c)){ - if(c->inuse == 0) + if(c->state == CClosed) break; - qunlock(c); } } + poperror(); + qunlock(sdp); - if(pp >= ep) { + if(pp >= ep) return nil; - } - c->inuse = 1; + c->ref++; + c->state = COpening; + strncpy(c->user, up->user, sizeof(c->user)); c->perm = 0660; - c->state = 0; - qunlock(c); + return c; } +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); +} Dev sdpdevtab = { 'T',