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,231999/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    
typedef struct ConnectPkt ConnectPkt; 
1999/0929    
typedef struct AckPkt AckPkt; 
1999/1001    
typedef struct Algorithm Algorithm; 
1999/0824    
 
1999/1001/sys/src/9/port/devsdp.c:43,491999/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    
	KeyLength= 32, 
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,831999/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,991999/1015/sys/src/9/port/devsdp.c:94,100
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/1015    
	int		(*comp)(OneWay*, int subtype, Block **); 
1999/0901    
}; 
 
1999/0907    
// conv states 
1999/1001/sys/src/9/port/devsdp.c:137,1431999/1015/sys/src/9/port/devsdp.c:138,143
1999/0907    
	char owner[NAMELEN];		/* protections */ 
1999/0901    
	int	perm; 
 
1999/0907    
	uchar	masterkey[KeyLength]; 
1999/1001    
	char *authname; 
	char *ciphername; 
	char *compname; 
1999/1001/sys/src/9/port/devsdp.c:160,1721999/1015/sys/src/9/port/devsdp.c:160,175
1999/0906    
enum { 
	TConnect, 
	TControl, 
	TControlAck, 
	TData, 
	TThwackC, 
	TThwackU, 
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,1881999/1015/sys/src/9/port/devsdp.c:177,182
1999/0909    
	ConReset, 
1999/0906    
}; 
 
1999/0907    
struct ConnectPkt 
1999/0906    
{ 
	uchar type;		// always zero = connection packet 
	uchar op; 
	uchar pad[2]; 
	uchar dialid[4]; 
	uchar acceptid[4]; 
}; 
                 
1999/0929    
struct AckPkt 
{ 
	uchar	cseq[4]; 
1999/1001/sys/src/9/port/devsdp.c:222,2521999/1015/sys/src/9/port/devsdp.c:216,221
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/1001/sys/src/9/port/devsdp.c:287,3031999/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); 
static void conviput2(Conv *c, Block *b); 
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    
static void convoput(Conv *c, int type, Block *b); 
static void convoput2(Conv *c, int op, ulong dialid, ulong acceptid); 
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,6021999/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,7451999/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,7561999/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) 
			convoput2(c, ConReset, c->dialid, c->acceptid); 
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,7891999/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    
			convoput2(c, ConOpenRequest, c->dialid, 0); 
1999/1015    
			convoconnect(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/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)) 
				convoput(c, TControl, copyblock(b, blocklen(b))); 
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,8141999/1015/sys/src/9/port/devsdp.c:829,841
1999/1001    
		c->out.controlpkt = b; 
		convretryinit(c); 
		if(!waserror()) { 
			convoput(c, TControl, copyblock(b, blocklen(b))); 
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    
			convoput2(c, ConClose, c->dialid, c->acceptid); 
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,9071999/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); 
		convoput2(c, ConOpenRequest, c->dialid, 0); 
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); 
		convoput2(c, ConOpenAck, c->dialid, c->acceptid); 
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    
			convoput2(c, ConOpenAckAck, c->dialid, c->acceptid); 
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    
		} 
		// setup initial key and auth method 
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    
		convoput2(c, ConClose, c->dialid, c->acceptid); 
1999/1015    
		convoconnect(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); 
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,9441999/1015/sys/src/9/port/devsdp.c:974,979
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)); 
1999/1001/sys/src/9/port/devsdp.c:1046,10521999/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); 
	convoput(c, TControlAck, b); 
1999/1015    
	convoput(c, TControl, ControlAck, b); 
1999/0929    
} 
 
 
1999/1001/sys/src/9/port/devsdp.c:1054,10651999/1015/sys/src/9/port/devsdp.c:1089,1097
1999/0907    
static Block * 
conviput(Conv *c, Block *b, int control) 
{ 
1999/1001    
	int type, n; 
	ulong seq, seqwrap, cseq; 
1999/1015    
	int type, subtype; 
	ulong seq, seqwrap; 
1999/1001    
	long seqdiff; 
1999/0929    
	AckPkt *ack; 
1999/1001    
	ulong mseq, mask; 
	Block *bb; 
1999/0907    
 
1999/0930    
	c->lstats.inPackets++; 
1999/0929    
 
1999/1001/sys/src/9/port/devsdp.c:1068,10811999/1015/sys/src/9/port/devsdp.c:1100,1115
1999/0907    
		return nil; 
	} 
	 
	type = b->rp[0]; 
1999/1015    
	type = b->rp[0] >> 4; 
	subtype = type & 0xf; 
	b->rp += 1; 
1999/0907    
	if(type == TConnect) { 
		conviput2(c, b); 
1999/1015    
		conviconnect(c, subtype, b); 
1999/0907    
		return nil; 
	} 
 
	seq = (b->rp[1]<<16) + (b->rp[2]<<8) + b->rp[3]; 
	b->rp += 4; 
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,11131999/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    
	// auth 
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,12271999/1015/sys/src/9/port/devsdp.c:1175,1198
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/0929    
			freeb(b); 
			if(c->in.controlpkt == nil) 
				convack(c); 
1999/0907    
			return nil; 
		} 
                 
		if(cseq != c->in.controlseq+1) 
			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/0930    
if(0) print("recv %ld size=%ld\n", cseq, BLEN(b)); 
1999/0929    
			wakeup(&c->in.controlready); 
		} 
1999/1015    
		convicontrol(c, subtype, b); 
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/0930    
		if(cseq != c->out.controlseq) { 
1999/0914    
print("ControlAck expected %ulx got %ulx\n", c->out.controlseq, cseq); 
1999/0907    
			break; 
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/1001    
		c->timeout = c->lastrecv + KeepAlive; 
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/1001    
	case TThwackU: 
1999/1015    
	case TCompData: 
1999/1001    
		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); 
1999/1015    
		b = convicomp(c, subtype, b); 
		if(b == nil); 
			return nil; 
1999/1001    
		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/1001/sys/src/9/port/devsdp.c:1230,12501999/1015/sys/src/9/port/devsdp.c:1201,1220
1999/0907    
 
// assume hold conv lock 
static void 
conviput2(Conv *c, Block *b) 
1999/1015    
conviconnect(Conv *c, int subtype, Block *b) 
1999/0907    
{ 
	ConnectPkt *con; 
	ulong dialid; 
	ulong acceptid; 
 
	if(BLEN(b) != sizeof(ConnectPkt)) { 
1999/1015    
	if(BLEN(b) != 8) { 
1999/0907    
		freeb(b); 
		return; 
	} 
	con = (ConnectPkt*)b->rp; 
	dialid = nhgetl(con->dialid); 
	acceptid = nhgetl(con->acceptid); 
1999/1015    
	dialid = nhgetl(b->rp); 
	acceptid = nhgetl(b->rp + 4); 
	freeb(b); 
1999/0907    
 
1999/0914    
print("conviput2: %s: %d %uld %uld\n", convstatename[c->state], con->op, dialid, acceptid); 
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,12651999/1015/sys/src/9/port/devsdp.c:1229,1236
1999/0910    
	case COpen: 
	case CLocalClose: 
	case CRemoteClose: 
		if(dialid != c->dialid || acceptid != c->acceptid) 
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,12721999/1015/sys/src/9/port/devsdp.c:1237,1243
1999/0910    
		goto Reset; 
	} 
 
1999/0907    
	switch(con->op) { 
1999/1015    
	switch(subtype) { 
1999/0909    
	case ConOpenRequest: 
		switch(c->state) { 
		case CInit: 
1999/1001/sys/src/9/port/devsdp.c:1287,12931999/1015/sys/src/9/port/devsdp.c:1258,1264
1999/0910    
			return; 
		case COpen: 
			// duplicate that we have to ack 
			convoput2(c, ConOpenAckAck, acceptid, dialid); 
1999/1015    
			convoconnect(c, ConOpenAckAck, acceptid, dialid); 
1999/0910    
			return; 
		} 
		break; 
1999/1001/sys/src/9/port/devsdp.c:1302,13081999/1015/sys/src/9/port/devsdp.c:1273,1279
1999/0909    
		} 
1999/0907    
		break; 
	case ConClose: 
1999/0910    
		convoput2(c, ConReset, dialid, acceptid); 
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,13221999/1015/sys/src/9/port/devsdp.c:1287,1293
1999/0910    
		case CRemoteClose: 
			return; 
1999/0909    
		} 
1999/0910    
		return; 
1999/1015    
		break; 
1999/0910    
	case ConReset: 
		switch(c->state) { 
		case CInit: 
1999/1001/sys/src/9/port/devsdp.c:1329,13421999/1015/sys/src/9/port/devsdp.c:1300,1390
1999/0910    
		case CRemoteClose: 
			return; 
		} 
		return; 
1999/1015    
		break; 
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/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,13681999/1015/sys/src/9/port/devsdp.c:1404,1416
1999/0930    
 
1999/0907    
// assume hold conv lock 
static void 
convoput(Conv *c, int type, Block *b) 
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); 
	b->rp[0] = type; 
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,13791999/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,13891999/1015/sys/src/9/port/devsdp.c:1433,1441
1999/0907    
 
// assume hold conv lock 
static void 
convoput2(Conv *c, int op, ulong dialid, ulong acceptid) 
1999/1015    
convoconnect(Conv *c, int op, ulong dialid, ulong acceptid) 
1999/0907    
{ 
1999/0930    
	Block *b; 
	ConnectPkt *con; 
1999/0907    
 
1999/0929    
	c->lstats.outPackets++; 
1999/0906    
	if(c->chan == nil) { 
1999/1001/sys/src/9/port/devsdp.c:1390,14021999/1015/sys/src/9/port/devsdp.c:1442,1452
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/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,15311999/1015/sys/src/9/port/devsdp.c:1575,1580
1999/0929    
{ 
	Block *b; 
 
                 
	qlock(&c->out.controllk); 
	qlock(c); 
	if(waserror()) { 
1999/1001/sys/src/9/port/devsdp.c:1541,15471999/1015/sys/src/9/port/devsdp.c:1590,1596
1999/0914    
	b->wp += 4+n; 
	c->out.controlpkt = b; 
	convretryinit(c); 
	convoput(c, TControl, copyblock(b, blocklen(b))); 
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,15821999/1015/sys/src/9/port/devsdp.c:1623,1629
1999/0915    
static long 
writedata(Conv *c, Block *b) 
{ 
1999/1001    
	int n, nn; 
	ulong seq; 
	Block *bb; 
1999/1015    
	int n; 
1999/0915    
 
	qlock(c); 
	if(waserror()) { 
1999/1001/sys/src/9/port/devsdp.c:1593,16261999/1015/sys/src/9/port/devsdp.c:1640,1651
1999/0930    
	c->lstats.outDataPackets++; 
	c->lstats.outDataBytes += n; 
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) { 
1999/1015    
	if(c->out.comp != nil) { 
		int subtype = (*c->out.comp)(&c->out, 0, &b); 
1999/1001    
		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/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,16651999/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 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)