plan 9 kernel history: overview | file list | diff list

1999/0824/port/devsdp.c (diff list | history)

port/devsdp.c on 1999/0824
1999/0824    
#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	<libcrypt.h> 
 
typedef struct Sdp		Sdp; 
typedef struct Port 	Port; 
 
enum 
{ 
	Qtopdir=	1,		/* top level directory */ 
 
	Qsdpdir,			/* sdp directory */ 
	Qclone, 
	Qstats, 
	Qlog, 
 
	Qportdir,			/* directory for a protocol */ 
	Qctl, 
	Qdata,				/* reliable control channel */ 
	Qpacket,			/* unreliable packet channel */ 
	Qerr, 
	Qlisten, 
	Qlocal, 
	Qremote, 
	Qstatus, 
 
	MaxQ, 
 
	Maxport=	256,		// power of 2 
	Nfs=		4,			// number of file systems 
}; 
 
#define TYPE(x) 	((x).path & 0xff) 
#define PORT(x) 	(((x).path >> 8)&(Maxport-1)) 
#define QID(x, y) 	(((x)<<8) | (y)) 
 
struct Port { 
	int	id; 
	Sdp	*sdp; 
	int	ref; 
	int	closed; 
}; 
 
struct Sdp { 
	QLock; 
	Log; 
	int	nport; 
	Port	*port[Maxport]; 
}; 
 
static Dirtab sdpdirtab[]={ 
	"ctl",		{Qctl},	0,	0666, 
	"stats",	{Qstats},	0,	0444, 
	"log",		{Qlog},		0,	0666, 
}; 
 
static Dirtab portdirtab[]={ 
	"ctl",		{Qctl},	0,	0666, 
	"data",		{Qdata},	0,	0666, 
	"packet",	{Qpacket},	0,	0666, 
	"listen",	{Qlisten},	0,	0666, 
	"local",	{Qlocal},	0,	0444, 
	"remote",	{Qlocal},	0,	0444, 
	"status",	{Qstatus},	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 int sdpgen(Chan *c, Dirtab*, int, int s, Dir *dp); 
 
static void 
sdpinit(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(portdirtab); i++) { 
		dt = portdirtab + i; 
		dirtab[TYPE(dt->qid)] = dt; 
	} 
} 
 
static Chan* 
sdpattach(char* spec) 
{ 
	Chan *c; 
	int dev; 
 
	dev = atoi(spec); 
	if(dev<0 || dev >= Nfs) 
		error("bad specification"); 
 
	c = devattach('B', spec); 
	c->qid = (Qid){QID(0, Qtopdir)|CHDIR, 0}; 
	c->dev = dev; 
 
	return c; 
} 
 
static int 
sdpwalk(Chan *c, char *name) 
{ 
	if(strcmp(name, "..") == 0){ 
		switch(TYPE(c->qid)){ 
		case Qtopdir: 
		case Qsdpdir: 
			c->qid = (Qid){CHDIR|Qtopdir, 0}; 
			break; 
		case Qportdir: 
			c->qid = (Qid){CHDIR|Qsdpdir, 0}; 
			break; 
		default: 
			panic("sdpwalk %lux", c->qid.path); 
		} 
		return 1; 
	} 
 
	return devwalk(c, name, 0, 0, sdpgen); 
} 
 
static void 
sdpstat(Chan* c, char* db) 
{ 
	devstat(c, db, nil, 0, sdpgen); 
} 
 
static Chan* 
sdpopen(Chan* c, int omode) 
{ 
	int perm; 
	Sdp *sdp; 
 
	omode &= 3; 
	perm = m2p[omode]; 
	USED(perm); 
 
	sdp = sdptab + c->dev; 
 
	switch(TYPE(c->qid)) { 
	default: 
		break; 
	case Qtopdir: 
	case Qsdpdir: 
	case Qportdir: 
	case Qstatus: 
	case Qlocal: 
	case Qstats: 
		if(omode != OREAD) 
			error(Eperm); 
		break; 
	case Qlog: 
		logopen(sdp); 
		break; 
	} 
	c->mode = openmode(omode); 
	c->flag |= COPEN; 
	c->offset = 0; 
	return c; 
} 
 
static void 
sdpclose(Chan* c) 
{ 
	Sdp *sdp  = sdptab + c->dev; 
 
	switch(TYPE(c->qid)) { 
	case Qlog: 
		if(c->flag & COPEN) 
			logclose(sdp); 
		break; 
	} 
} 
 
static long 
sdpread(Chan *c, void *a, long n, vlong off) 
{ 
	char buf[256]; 
	Sdp *sdp = sdptab + c->dev; 
	Port *port; 
 
	USED(off); 
	switch(TYPE(c->qid)) { 
	default: 
		error(Eperm); 
	case Qtopdir: 
	case Qsdpdir: 
	case Qportdir: 
		return devdirread(c, a, n, 0, 0, sdpgen); 
	case Qlog: 
		return logread(sdp, a, off, n); 
	case Qstatus: 
		qlock(sdp); 
		port = sdp->port[PORT(c->qid)]; 
		if(port == 0) 
			strcpy(buf, "unbound\n"); 
		else { 
		} 
		n = readstr(off, a, n, buf); 
		qunlock(sdp); 
		return n; 
	} 
 
} 
 
static long 
sdpwrite(Chan *c, void *a, long n, vlong off) 
{ 
	Sdp *sdp = sdptab + c->dev; 
	Cmdbuf *cb; 
	char *arg0; 
	char *p; 
	 
	USED(off); 
	switch(TYPE(c->qid)) { 
	default: 
		error(Eperm); 
	case Qctl: 
		cb = parsecmd(a, n); 
		qlock(sdp); 
		if(waserror()) { 
			qunlock(sdp); 
			free(cb); 
			nexterror(); 
		} 
		if(cb->nf == 0) 
			error("short write"); 
		arg0 = cb->f[0]; 
		if(strcmp(arg0, "xxx") == 0) { 
			print("xxx\n"); 
		} else 
			error("unknown control request"); 
		poperror(); 
		qunlock(sdp); 
		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; 
	} 
} 
 
static int 
sdpgen(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; 
 
	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->nport) 
			return -1; 
		qid = (Qid){QID(s,Qportdir)|CHDIR, 0}; 
		snprint(buf, sizeof(buf), "%d", s); 
		devdir(c, qid, buf, 0, eve, 0555, dp); 
		return 1; 
	case Qportdir: 
		if(s>=nelem(portdirtab)) 
			return -1; 
		dt = portdirtab+s; 
		qid = (Qid){QID(PORT(c->qid),TYPE(dt->qid)),0}; 
		devdir(c, qid, dt->name, dt->length, eve, dt->perm, dp); 
		return 1; 
	} 
} 
 
 
Dev sdpdevtab = { 
	'T', 
	"sdp", 
 
	devreset, 
	sdpinit, 
	sdpattach, 
	devclone, 
	sdpwalk, 
	sdpstat, 
	sdpopen, 
	devcreate, 
	sdpclose, 
	sdpread, 
	devbread, 
	sdpwrite, 
	devbwrite, 
	devremove, 
	devwstat, 
}; 


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