| plan 9 kernel history: overview | file list | diff list |
1999/1015/port/devsdp.c (diff list | history)
| 1999/1001/sys/src/9/port/devsdp.c:17,23 – 1999/1015/sys/src/9/port/devsdp.c:17,22 (short | long | prev | next) | ||
| 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 | |