~kris/9p

9hist

2da1851522d11276da4f811f086c9bc51c3f8112 — David du Colombier 27 years ago b8ca678
Plan 9 from Bell Labs 1999-09-02
1 files changed, 132 insertions(+), 42 deletions(-)

M port/devsdp.c
M port/devsdp.c => port/devsdp.c +132 -42
@@ 8,9 8,10 @@

#include	<libcrypt.h>

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',