⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 devsdp.c

📁 著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是bell实验室开发的Unix后继者。
💻 C
📖 第 1 页 / 共 3 页
字号:
#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "../port/netif.h"#include "../port/error.h"#include	<libsec.h>#include "../port/thwack.h"/* * sdp - secure datagram protocol */typedef struct Sdp Sdp;typedef struct Conv Conv;typedef struct OneWay OneWay;typedef struct Stats Stats;typedef struct AckPkt AckPkt;typedef struct Algorithm Algorithm;typedef struct CipherRc4 CipherRc4;enum{	Qtopdir=	1,		/* top level directory */	Qsdpdir,			/* sdp directory */	Qclone,	Qlog,	Qconvdir,			/* directory per conversation */	Qctl,	Qdata,				/* unreliable packet channel */	Qcontrol,			/* reliable control channel */	Qstatus,	Qstats,	Qrstats,	MaxQ,	Maxconv= 256,		// power of 2	Nfs= 4,				// number of file systems	MaxRetries=	12,	KeepAlive = 120,	// keep alive in seconds	SecretLength= 32,	// a secret per direction	SeqMax = (1<<24),	SeqWindow = 32,	NCompStats = 8,};#define TYPE(x) 	((x).path & 0xff)#define CONV(x) 	(((x).path >> 8)&(Maxconv-1))#define QID(x, y) 	(((x)<<8) | (y))struct Stats{	ulong	outPackets;	ulong	outDataPackets;	ulong	outDataBytes;	ulong	outCompDataBytes;	ulong	outCompBytes;	ulong	outCompStats[NCompStats];	ulong	inPackets;	ulong	inDataPackets;	ulong	inDataBytes;	ulong	inCompDataBytes;	ulong	inMissing;	ulong	inDup;	ulong	inReorder;	ulong	inBadComp;	ulong	inBadAuth;	ulong	inBadSeq;	ulong	inBadOther;};struct OneWay{	Rendez	statsready;	ulong	seqwrap;	// number of wraps of the sequence number	ulong	seq;	ulong	window;	uchar	secret[SecretLength];	QLock	controllk;	Rendez	controlready;	Block	*controlpkt;		// control channel	ulong	controlseq;	void	*cipherstate;	// state cipher	int		cipherivlen;	// initial vector length	int		cipherblklen;	// block length	int		(*cipher)(OneWay*, uchar *buf, int len);	void	*authstate;		// auth state	int		authlen;		// auth data length in bytes	int		(*auth)(OneWay*, uchar *buf, int len);	void	*compstate;	int		(*comp)(Conv*, int subtype, ulong seq, Block **);};// conv statesenum {	CFree,	CInit,	CDial,	CAccept,	COpen,	CLocalClose,	CRemoteClose,	CClosed,};struct Conv {	QLock;	Sdp	*sdp;	int	id;	int ref;	// holds conv up	int state;	int dataopen;	// ref count of opens on Qdata	int controlopen;	// ref count of opens on Qcontrol	int reader;		// reader proc has been started	Stats	lstats;	Stats	rstats;		ulong	lastrecv;	// time last packet was received 	ulong	timeout;	int		retries;	// the following pair uniquely define conversation on this port	ulong dialid;	ulong acceptid;	QLock readlk;		// protects readproc	Proc *readproc;	Chan *chan;		// packet channel	char *channame;	char owner[NAMELEN];		/* protections */	int	perm;	Algorithm *auth;	Algorithm *cipher;	Algorithm *comp;	int drop;	OneWay	in;	OneWay	out;};struct Sdp {	QLock;	Log;	Rendez	vous;			/* used by sdpackproc */	int	nconv;	Conv *conv[Maxconv];	int ackproc;};enum {	TConnect,	TControl,	TData,	TCompData,};enum {	ControlMesg,	ControlAck,};enum {	ThwackU,	ThwackC,};enum {	ConOpenRequest,	ConOpenAck,	ConOpenAckAck,	ConClose,	ConCloseAck,	ConReset,};struct AckPkt{	uchar	cseq[4];	uchar	outPackets[4];	uchar	outDataPackets[4];	uchar	outDataBytes[4];	uchar	outCompDataBytes[4];	uchar	outCompStats[4*NCompStats];	uchar	inPackets[4];	uchar	inDataPackets[4];	uchar	inDataBytes[4];	uchar	inCompDataBytes[4];	uchar	inMissing[4];	uchar	inDup[4];	uchar	inReorder[4];	uchar	inBadComp[4];	uchar	inBadAuth[4];	uchar	inBadSeq[4];	uchar	inBadOther[4];};struct Algorithm{	char 	*name;	int		keylen;		// in bytes	void	(*init)(Conv*);};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;};static Dirtab sdpdirtab[]={	"log",		{Qlog},		0,	0666,	"clone",	{Qclone},		0,	0666,};static Dirtab convdirtab[]={	"ctl",		{Qctl},	0,	0666,	"data",		{Qdata},	0,	0666,	"control",	{Qcontrol},	0,	0666,	"status",	{Qstatus},	0,	0444,	"stats",	{Qstats},	0,	0444,	"rstats",	{Qrstats},	0,	0444,};static int m2p[] = {	[OREAD]		4,	[OWRITE]	2,	[ORDWR]		6};enum {	Logcompress=	(1<<0),	Logauth=	(1<<1),	Loghmac=	(1<<2),};static Logflag logflags[] ={	{ "compress",	Logcompress, },	{ "auth",	Logauth, },	{ "hmac",	Loghmac, },	{ nil,		0, },};static Dirtab	*dirtab[MaxQ];static Sdp sdptab[Nfs];static char *convstatename[] = {	[CFree]		"Free",	[CInit]		"Init",	[CDial]		"Dial",	[CAccept]	"Accept",	[COpen]		"Open",	[CLocalClose] "LocalClose",	[CRemoteClose] "RemoteClose",	[CClosed]	"Closed",};static int sdpgen(Chan *c, Dirtab*, int, int s, Dir *dp);static Conv *sdpclone(Sdp *sdp);static void sdpackproc(void *a);static void onewaycleanup(OneWay *ow);static int readready(void *a);static int controlread();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);static Block *conviput(Conv *c, Block *b, int control);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, ulong, Block *b);static void convoput(Conv *c, int type, int subtype, Block *b);static void convoconnect(Conv *c, int op, ulong dialid, ulong acceptid);static void convopenchan(Conv *c, char *path);static void convstats(Conv *c, int local, char *buf, int n);static void convreader(void *a);static void setalg(Conv *c, char *name, Algorithm *tab, Algorithm **);static void setsecret(OneWay *cc, char *secret);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);static Algorithm cipheralg[] ={	"null",			0,	nullcipherinit,	"des_56_cbc",	7,	descipherinit,	"rc4_128",		16,	rc4cipherinit,	"rc4_256",		32,	rc4cipherinit,	nil,			0,	nil,};static Algorithm authalg[] ={	"null",			0,	nullauthinit,	"hmac_sha1_96",	16,	shaauthinit,	"hmac_md5_96",	16,	md5authinit,	nil,			0,	nil,};static Algorithm compalg[] ={	"null",			0,	nullcompinit,	"thwack",		0,	thwackcompinit,	nil,			0,	nil,};static voidsdpinit(void){	int i;	Dirtab *dt;		// setup dirtab with non directory entries	for(i=0; i<nelem(sdpdirtab); i++) {		dt = sdpdirtab + i;		dirtab[TYPE(dt->qid)] = dt;	}	for(i=0; i<nelem(convdirtab); i++) {		dt = convdirtab + i;		dirtab[TYPE(dt->qid)] = dt;	}}static Chan*sdpattach(char* spec){	Chan *c;	int dev;	char buf[100];	Sdp *sdp;	int start;	dev = atoi(spec);	if(dev<0 || dev >= Nfs)		error("bad specification");	c = devattach('E', spec);	c->qid = (Qid){QID(0, Qtopdir)|CHDIR, 0};	c->dev = dev;	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);	}		return c;}static intsdpwalk(Chan *c, char *name){	return devwalk(c, name, 0, 0, sdpgen);}static voidsdpstat(Chan* c, char* db){	devstat(c, db, nil, 0, sdpgen);}static Chan*sdpopen(Chan* ch, int omode){	int perm;	Sdp *sdp;	Conv *c;	omode &= 3;	perm = m2p[omode];	USED(perm);	sdp = sdptab + ch->dev;	switch(TYPE(ch->qid)) {	default:		break;	case Qtopdir:	case Qsdpdir:	case Qconvdir:		if(omode != OREAD)			error(Eperm);		break;	case Qlog:		logopen(sdp);		break;	case Qclone:		c = sdpclone(sdp);		if(c == nil)			error(Enodev);		ch->qid.path = QID(c->id, Qctl);		break;	case Qdata:	case Qctl:	case Qstatus:	case Qcontrol:	case Qstats:	case Qrstats:		c = sdp->conv[CONV(ch->qid)];		qlock(c);		if(waserror()) {			qunlock(c);			nexterror();		}		if((perm & (c->perm>>6)) != perm)		if(strcmp(up->user, c->owner) != 0 || (perm & c->perm) != perm)				error(Eperm);		c->ref++;		if(TYPE(ch->qid) == Qdata) {			c->dataopen++;			// kill reader if Qdata is opened for the first time			if(c->dataopen == 1)			if(c->readproc != nil)				postnote(c->readproc, 1, "interrupt", 0);		} else if(TYPE(ch->qid) == Qcontrol) {				c->controlopen++;		}		qunlock(c);		poperror();		break;	}	ch->mode = openmode(omode);	ch->flag |= COPEN;	ch->offset = 0;	return ch;}static voidsdpclose(Chan* ch){	Sdp *sdp  = sdptab + ch->dev;	Conv *c;	if(!(ch->flag & COPEN))		return;	switch(TYPE(ch->qid)) {	case Qlog:		logclose(sdp);		break;	case Qctl:	case Qstatus:	case Qstats:	case Qrstats:		c = sdp->conv[CONV(ch->qid)];		qlock(c);		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();		}		qunlock(c);		break;	case Qcontrol:		c = sdp->conv[CONV(ch->qid)];		qlock(c);		c->controlopen--;		convderef(c);		if(c->controlopen == 0 && c->ref != 0) {			switch(c->state) {			default:				convsetstate(c, CClosed);				break;			case CAccept:			case COpen:				convsetstate(c, CLocalClose);				break;			}		}		qunlock(c);		poperror();		break;	}}static longsdpread(Chan *ch, void *a, long n, vlong off){	char buf[256];	char *s;	Sdp *sdp = sdptab + ch->dev;	Conv *c;	Block *b;	int rv;	USED(off);	switch(TYPE(ch->qid)) {	default:		error(Eperm);	case Qtopdir:	case Qsdpdir:	case Qconvdir:		return devdirread(ch, a, n, 0, 0, sdpgen);	case Qlog:		return logread(sdp, a, off, n);	case Qstatus:		c = sdp->conv[CONV(ch->qid)];		qlock(c);		n = readstr(off, a, n, convstatename[c->state]);		qunlock(c);		return n;	case Qctl:		sprint(buf, "%lud", CONV(ch->qid));		return readstr(off, a, n, buf);	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;	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;	}}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);}static longsdpwrite(Chan *ch, void *a, long n, vlong off){	Sdp *sdp = sdptab + ch->dev;	Cmdbuf *cb;	char *arg0;	char *p;	Conv *c;	Block *b;		USED(off);	switch(TYPE(ch->qid)) {	default:		error(Eperm);	case Qctl:		c = sdp->conv[CONV(ch->qid)];		cb = parsecmd(a, n);		qlock(c);		if(waserror()) {			qunlock(c);			free(cb);			nexterror();		}		if(cb->nf == 0)			error("short write");		arg0 = cb->f[0];		if(strcmp(arg0, "accept") == 0) {			if(cb->nf != 2)				error("usage: accect file");			convopenchan(c, cb->f[1]);		} else if(strcmp(arg0, "dial") == 0) {			if(cb->nf != 2)				error("usage: accect file");			convopenchan(c, cb->f[1]);			convsetstate(c, CDial);		} else if(strcmp(arg0, "drop") == 0) {			if(cb->nf != 2)				error("usage: drop permil");			c->drop = atoi(cb->f[1]);		} else if(strcmp(arg0, "cipher") == 0) {			if(cb->nf != 2)				error("usage: cipher alg");			setalg(c, cb->f[1], cipheralg, &c->cipher);		} else if(strcmp(arg0, "auth") == 0) {			if(cb->nf != 2)				error("usage: auth alg");			setalg(c, cb->f[1], authalg, &c->auth);		} else if(strcmp(arg0, "comp") == 0) {			if(cb->nf != 2)				error("usage: comp alg");			setalg(c, cb->f[1], compalg, &c->comp);		} else if(strcmp(arg0, "insecret") == 0) {			if(cb->nf != 2)				error("usage: insecret secret");			setsecret(&c->in, cb->f[1]);			if(c->cipher)				c->cipher->init(c);			if(c->auth)				c->auth->init(c);		} else if(strcmp(arg0, "outsecret") == 0) {			if(cb->nf != 2)				error("usage: outsecret secret");			setsecret(&c->out, cb->f[1]);			if(c->cipher)				c->cipher->init(c);			if(c->auth)				c->auth->init(c);		} else			error("unknown control request");		poperror();		qunlock(c);		free(cb);		return n;	case Qlog:		cb = parsecmd(a, n);		p = logctl(sdp, cb->nf, cb->f, logflags);		free(cb);		if(p != nil)			error(p);		return n;	case Qcontrol:		writecontrol(sdp->conv[CONV(ch->qid)], a, n, 0);		return n;	case Qdata:		b = allocb(n);		memmove(b->wp, a, n);		b->wp += n;		return writedata(sdp->conv[CONV(ch->qid)], b);	}}longsdpbwrite(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);}static intsdpgen(Chan *c, Dirtab*, int, int s, Dir *dp){	Sdp *sdp = sdptab + c->dev;	int type = TYPE(c->qid);	char buf[32];	Dirtab *dt;	Qid qid;	if(s == DEVDOTDOT){		switch(TYPE(c->qid)){		case Qtopdir:		case Qsdpdir:			snprint(buf, sizeof(buf), "#E%ld", c->dev);			devdir(c, (Qid){CHDIR|Qtopdir, 0}, buf, 0, eve, 0555, dp);			break;		case Qconvdir:			snprint(buf, sizeof(buf), "%d", s);			devdir(c, (Qid){CHDIR|Qsdpdir, 0}, buf, 0, eve, 0555, dp);			break;		default:			panic("sdpwalk %lux", c->qid.path);		}		return 1;	}	switch(type) {	default:		// non directory entries end up here		if(c->qid.path & CHDIR)			panic("sdpgen: unexpected directory");			if(s != 0)			return -1;		dt = dirtab[TYPE(c->qid)];		if(dt == nil)			panic("sdpgen: unknown type: %d", TYPE(c->qid));		devdir(c, c->qid, dt->name, dt->length, eve, dt->perm, dp);		return 1;	case Qtopdir:		if(s != 0)			return -1;		devdir(c, (Qid){QID(0,Qsdpdir)|CHDIR,0}, "sdp", 0, eve, 0555, dp);		return 1;	case Qsdpdir:		if(s<nelem(sdpdirtab)) {			dt = sdpdirtab+s;			devdir(c, dt->qid, dt->name, dt->length, eve, dt->perm, dp);			return 1;		}		s -= nelem(sdpdirtab);		if(s >= sdp->nconv)			return -1;		qid = (Qid){QID(s,Qconvdir)|CHDIR, 0};		snprint(buf, sizeof(buf), "%d", s);		devdir(c, qid, buf, 0, eve, 0555, dp);		return 1;	case Qconvdir:		if(s>=nelem(convdirtab))			return -1;		dt = convdirtab+s;		qid = (Qid){QID(CONV(c->qid),TYPE(dt->qid)),0};		devdir(c, qid, dt->name, dt->length, eve, dt->perm, dp);		return 1;	}}static Conv*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -