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

1998/0306/ip/devip.c (diff list | history)

1997/1128/sys/src/9/ip/devip.c:14,261998/0306/sys/src/9/ip/devip.c:14,27 (short | long | prev | next)
1997/0327    
	Qtopdir=	1,		/* top level directory */ 
	Qtopbase, 
	Qarp=		Qtopbase, 
	Qipifc, 
	Qiproute, 
1998/0306    
	Qiprouter, 
1997/0327    
	Qlog, 
 
	Qprotodir,			/* directory for a protocol */ 
	Qprotobase, 
	Qclone=		Qprotobase, 
1998/0306    
	Qstats, 
1997/0327    
 
	Qconvdir,			/* directory for a conversation */ 
	Qconvbase, 
1997/1128/sys/src/9/ip/devip.c:79,851998/0306/sys/src/9/ip/devip.c:80,86
1997/0327    
		q = (Qid){QID(PROTO(c->qid), CONV(c->qid), Qstatus), 0}; 
		break; 
	} 
	devdir(c, q, p, 0, cv->owner, 0444, dp); 
1998/0306    
	devdir(c, q, p, 0, cv->owner, 0666, dp); 
1997/0327    
	return 1; 
} 
 
1997/1128/sys/src/9/ip/devip.c:91,981998/0306/sys/src/9/ip/devip.c:92,103
1997/0327    
	switch(i) { 
	case Qclone: 
		q = (Qid){QID(PROTO(c->qid), 0, Qclone), 0}; 
		devdir(c, q, "clone", 0, network, 0444, dp); 
1998/0306    
		devdir(c, q, "clone", 0, network, 0666, dp); 
1997/0327    
		return 1; 
1998/0306    
	case Qstats: 
		q = (Qid){QID(PROTO(c->qid), 0, Qstats), 0}; 
		devdir(c, q, "stats", 0, network, 0444, dp); 
		return 1; 
1997/0327    
	}	 
	return -1; 
} 
1997/1128/sys/src/9/ip/devip.c:110,1291998/0306/sys/src/9/ip/devip.c:115,134
1997/0327    
		p = "arp"; 
		q = (Qid){QID(0, 0, Qarp), 0}; 
		break; 
	case Qipifc: 
		p = "ipifc"; 
		q = (Qid){QID(0, 0, Qipifc), 0}; 
		break; 
	case Qiproute: 
		p = "iproute"; 
		q = (Qid){QID(0, 0, Qiproute), 0}; 
		break; 
1998/0306    
	case Qiprouter: 
		p = "iprouter"; 
		q = (Qid){QID(0, 0, Qiprouter), 0}; 
		break; 
1997/0327    
	case Qlog: 
		p = "log"; 
		q = (Qid){QID(0, 0, Qlog), 0}; 
		break; 
	} 
	devdir(c, q, p, 0, network, 0444, dp); 
1998/0306    
	devdir(c, q, p, 0, network, 0666, dp); 
1997/0327    
	return 1; 
} 
 
1997/1128/sys/src/9/ip/devip.c:146,1541998/0306/sys/src/9/ip/devip.c:151,159
1997/0327    
		s -= fs.np; 
		return ip1gen(c, s+Qtopbase, dp); 
	case Qarp: 
	case Qipifc: 
	case Qlog: 
	case Qiproute: 
1998/0306    
	case Qiprouter: 
1997/0327    
		return ip1gen(c, TYPE(c->qid), dp); 
	case Qprotodir: 
		if(s < fs.p[PROTO(c->qid)]->ac) { 
1997/1128/sys/src/9/ip/devip.c:161,1661998/0306/sys/src/9/ip/devip.c:166,172
1997/0327    
		s -= fs.p[PROTO(c->qid)]->ac; 
		return ip2gen(c, s+Qprotobase, dp); 
	case Qclone: 
1998/0306    
	case Qstats: 
1997/0327    
		return ip2gen(c, TYPE(c->qid), dp); 
	case Qconvdir: 
		return ip3gen(c, s+Qconvbase, dp); 
1997/1128/sys/src/9/ip/devip.c:193,1981998/0306/sys/src/9/ip/devip.c:199,206
1997/0327    
	fmtinstall('i', eipconv); 
	fmtinstall('I', eipconv); 
	fmtinstall('E', eipconv); 
1998/0306    
	fmtinstall('V', eipconv); 
	fmtinstall('M', eipconv); 
1997/0327    
} 
 
static Chan* 
1997/1128/sys/src/9/ip/devip.c:217,2411998/0306/sys/src/9/ip/devip.c:225,248
1997/0327    
{ 
	Path *op; 
 
	if(strcmp(name, "..") == 0){ 
		switch(TYPE(c->qid)){ 
		case Qtopdir: 
		case Qprotodir: 
			c->qid = (Qid){QID(0, 0, Qtopdir)|CHDIR, 0}; 
			break; 
		case Qconvdir: 
1997/0823    
			c->qid = (Qid){QID(PROTO(c->qid), 0, Qprotodir)|CHDIR, 0}; 
1997/0327    
			break; 
		default: 
			panic("ipwalk %lux", c->qid.path); 
		} 
		op = c->path; 
		c->path = ptenter(&syspt, op, name); 
		decref(op); 
		return 1; 
	} 
1998/0306    
	if(strcmp(name, "..") != 0) 
		return devwalk(c, name, nil, 0, ipgen); 
1997/0327    
 
	return devwalk(c, name, nil, 0, ipgen); 
1998/0306    
	switch(TYPE(c->qid)){ 
	case Qtopdir: 
	case Qprotodir: 
		c->qid = (Qid){QID(0, 0, Qtopdir)|CHDIR, 0}; 
		break; 
	case Qconvdir: 
		c->qid = (Qid){QID(PROTO(c->qid), 0, Qprotodir)|CHDIR, 0}; 
		break; 
	default: 
		panic("ipwalk %lux", c->qid.path); 
	} 
	op = c->path; 
	c->path = ptenter(&syspt, op, name); 
	decref(op); 
	return 1; 
1997/0327    
} 
 
static void 
1997/1128/sys/src/9/ip/devip.c:272,2831998/0306/sys/src/9/ip/devip.c:279,293
1997/0327    
	switch(TYPE(c->qid)) { 
	default: 
		break; 
1997/0423    
	case Qipifc: 
		c->aux = newifcconv(); 
		break; 
1997/0327    
	case Qlog: 
		netlogopen(); 
		break; 
1998/0306    
	case Qiprouter: 
		iprouteropen(); 
		break; 
	case Qiproute: 
		memmove(c->tag, "none", sizeof(c->tag)); 
		break; 
1997/0327    
	case Qtopdir: 
	case Qprotodir: 
	case Qconvdir: 
1997/1128/sys/src/9/ip/devip.c:284,2891998/0306/sys/src/9/ip/devip.c:294,300
1997/0327    
	case Qstatus: 
	case Qremote: 
	case Qlocal: 
1998/0306    
	case Qstats: 
1997/0327    
		if(omode != OREAD) 
			error(Eperm); 
		break; 
1997/1128/sys/src/9/ip/devip.c:300,3111998/0306/sys/src/9/ip/devip.c:311,322
1997/0327    
	case Qctl: 
	case Qerr: 
		p = fs.p[PROTO(c->qid)]; 
		lock(p); 
1998/0306    
		qlock(p); 
1997/0327    
		cv = p->conv[CONV(c->qid)]; 
		lock(cv); 
		if(waserror()) { 
			unlock(cv); 
			unlock(p); 
1998/0306    
			qunlock(p); 
1997/0327    
			nexterror(); 
		} 
		if((perm & (cv->perm>>6)) != perm) { 
1997/1128/sys/src/9/ip/devip.c:321,3271998/0306/sys/src/9/ip/devip.c:332,338
1997/0327    
			cv->perm = 0660; 
		} 
		unlock(cv); 
		unlock(p); 
1998/0306    
		qunlock(p); 
1997/0327    
		poperror(); 
		break; 
	case Qlisten: 
1997/1128/sys/src/9/ip/devip.c:381,3881998/0306/sys/src/9/ip/devip.c:392,401
1997/0327    
closeconv(Conv *cv) 
{ 
	Conv *nc; 
1998/0306    
	Ipmulti *mp; 
1997/0327    
 
	lock(cv); 
1998/0306    
 
1997/0327    
	if(--cv->inuse > 0) { 
		unlock(cv); 
		return; 
1997/1128/sys/src/9/ip/devip.c:397,4021998/0306/sys/src/9/ip/devip.c:410,418
1997/0327    
	strcpy(cv->owner, network); 
	cv->perm = 0660; 
 
1998/0306    
	while((mp = cv->multi) != nil) 
		ipifcremmulti(cv, mp->ma, mp->ia); 
 
1997/0327    
	/* The close routine will unlock the conv */ 
	cv->p->close(cv); 
} 
1997/1128/sys/src/9/ip/devip.c:407,4191998/0306/sys/src/9/ip/devip.c:423,435
1997/0327    
	switch(TYPE(c->qid)) { 
	default: 
		break; 
1997/0423    
	case Qipifc: 
1998/0306    
	case Qlog: 
1997/0531    
		if(c->flag & COPEN) 
			closeifcconv(c->aux); 
1997/0423    
		c->aux = nil; 
1998/0306    
			netlogclose(); 
1997/0423    
		break; 
1997/0327    
	case Qlog: 
		netlogclose(); 
1998/0306    
	case Qiprouter: 
		if(c->flag & COPEN) 
			iprouterclose(); 
1997/0327    
		break; 
	case Qdata: 
	case Qctl: 
1997/1128/sys/src/9/ip/devip.c:423,4351998/0306/sys/src/9/ip/devip.c:439,456
1997/0327    
	} 
} 
 
1998/0306    
enum 
{ 
	Statelen=	1024, 
}; 
 
1997/0327    
static long 
ipread(Chan *ch, void *a, long n, ulong offset) 
{ 
	Conv *c; 
	Proto *x; 
	byte ip[4]; 
	char buf[256], *p, *statename; 
1998/0306    
	char *buf, *p; 
	long m, rv; 
1997/0327    
 
	p = a; 
	switch(TYPE(ch->qid)) { 
1997/1128/sys/src/9/ip/devip.c:441,4811998/0306/sys/src/9/ip/devip.c:462,522
1997/0327    
		return devdirread(ch, a, n, 0, 0, ipgen); 
	case Qarp: 
		return arpread(a, offset, n); 
	case Qipifc: 
		return Mediaifcread(a, offset, n); 
	case Qiproute: 
		return routeread(a, offset, n); 
1998/0306    
	case Qiprouter: 
		return iprouterread(a, n); 
1997/0327    
	case Qlog: 
		return netlogread(a, offset, n); 
	case Qctl: 
1998/0306    
		buf = smalloc(16); 
1997/0327    
		sprint(buf, "%d", CONV(ch->qid)); 
		return readstr(offset, p, n, buf); 
1998/0306    
		rv = readstr(offset, p, n, buf); 
		free(buf); 
		return rv; 
1997/0327    
	case Qremote: 
1998/0306    
		buf = smalloc(Statelen); 
1997/0327    
		c = fs.p[PROTO(ch->qid)]->conv[CONV(ch->qid)]; 
		hnputl(ip, c->raddr); 
		sprint(buf, "%I!%d\n", ip, c->rport); 
		return readstr(offset, p, n, buf); 
1998/0306    
		sprint(buf, "%I!%d\n", c->raddr, c->rport); 
		rv = readstr(offset, p, n, buf); 
		free(buf); 
		return rv; 
1997/0327    
	case Qlocal: 
		c = fs.p[PROTO(ch->qid)]->conv[CONV(ch->qid)]; 
		if(media != nil && c->laddr == 0) 
			hnputl(ip, Mediagetaddr(media)); 
		else 
			hnputl(ip, c->laddr); 
		sprint(buf, "%I!%d\n", ip, c->lport); 
		return readstr(offset, p, n, buf); 
1998/0306    
		buf = smalloc(Statelen); 
		x = fs.p[PROTO(ch->qid)]; 
		c = x->conv[CONV(ch->qid)]; 
		if(x->local == nil) { 
			sprint(buf, "%I!%d\n", c->laddr, c->lport); 
		} else { 
			(*x->local)(c, buf, Statelen-2); 
		} 
		rv = readstr(offset, p, n, buf); 
		free(buf); 
		return rv; 
1997/0327    
	case Qstatus: 
1998/0306    
		buf = smalloc(Statelen); 
1997/0327    
		x = fs.p[PROTO(ch->qid)]; 
		c = x->conv[CONV(ch->qid)]; 
		x->state(&statename, c); 
		sprint(buf, "%s/%d %d %s \n", c->p->name, c->x, c->inuse, statename); 
		return readstr(offset, p, n, buf); 
1998/0306    
		m = sprint(buf, "%s/%d %d ", c->p->name, c->x, c->inuse); 
		(*x->state)(c, buf, Statelen-m-2); 
		rv = readstr(offset, p, n, buf); 
		free(buf); 
		return rv; 
1997/0327    
	case Qdata: 
		c = fs.p[PROTO(ch->qid)]->conv[CONV(ch->qid)]; 
1997/1105    
		return qread(c->rq, a, n); 
                 
1997/0327    
	case Qerr: 
		c = fs.p[PROTO(ch->qid)]->conv[CONV(ch->qid)]; 
		return qread(c->eq, a, n); 
1998/0306    
	case Qstats: 
		x = fs.p[PROTO(ch->qid)]; 
		if(x->stats == nil) 
			error("stats not implemented"); 
		buf = smalloc(Statelen); 
		(*x->stats)(buf, Statelen); 
		rv = readstr(offset, p, n, buf); 
		free(buf); 
		return rv; 
1997/0327    
	} 
} 
 
1997/1128/sys/src/9/ip/devip.c:485,4991998/0306/sys/src/9/ip/devip.c:526,543
1997/0327    
	return devbread(c, n, offset); 
} 
 
1998/0306    
/* 
 *  set local address to be that of the ifc closest to remote address 
 */ 
1997/0327    
static void 
setladdr(Conv* c) 
{ 
	byte rem[4]; 
                 
	hnputl(rem, c->raddr); 
	c->laddr = Mediagetsrc(rem); 
1998/0306    
	findlocalip(c->laddr, c->raddr); 
1997/0327    
} 
 
1998/0306    
/* 
 *  pick a local port and set it 
 */ 
1997/0327    
static void 
setlport(Conv* c) 
{ 
1997/1128/sys/src/9/ip/devip.c:506,5121998/0306/sys/src/9/ip/devip.c:550,556
1997/0327    
		pp = &p->nextrport; 
	else 
		pp = &p->nextport; 
	lock(p); 
1998/0306    
	qlock(p); 
1997/0327    
	for(;;(*pp)++){ 
1997/0508    
		/* 
		 * Fsproto initialises p->nextport to 0 and the restricted 
1997/1128/sys/src/9/ip/devip.c:536,5491998/0306/sys/src/9/ip/devip.c:580,600
1997/0327    
			break; 
	} 
	c->lport = (*pp)++; 
	unlock(p); 
1998/0306    
	qunlock(p); 
1997/0327    
} 
 
1998/0306    
/* 
 *  set a local address and port from a string of the form 
 *	address!port 
 *  if address is missing and not announcing, pick one 
 *  if address is missing and announcing, leave address as zero (i.e. matches anything) 
 *  if port is 0, pick a free one 
 *  if port is '*', leave port as zero (i.e. matches anything) 
 */ 
1997/0327    
static void 
1997/1030    
setladdrport(Conv* c, char* str, int nodefault) 
1998/0306    
setladdrport(Conv* c, char* str, int announcing) 
1997/0327    
{ 
1997/0423    
	char *p; 
1997/0815    
	uchar addr[IPaddrlen]; 
1997/0327    
 
1997/1128    
	/* 
	 *  ignore restricted part if it exists.  it's 
1997/1128/sys/src/9/ip/devip.c:552,5701998/0306/sys/src/9/ip/devip.c:603,618
1997/0327    
	p = strchr(str, '!'); 
1997/1128    
	if(p == nil || strcmp(p, "!r") == 0) { 
1997/0327    
		p = str; 
1997/1030    
		if(nodefault) 
1998/0306    
		memset(c->laddr, 0, sizeof(c->laddr)); 
		if(!announcing) 
1997/1030    
			setladdr(c); 
		else 
			c->laddr = 0; 
1997/0327    
	} 
	else { 
1998/0306    
	} else { 
1997/0327    
		*p++ = 0; 
		parseip(addr, str); 
1997/0423    
		c->laddr = nhgetl(addr); 
1998/0306    
		parseip(c->laddr, str); 
1997/0327    
	} 
	if(*p == '*') 
		c->lport = 0; 
	else { 
1998/0306    
 
	c->lport = 0; 
	if(*p != '*'){ 
1997/0327    
		c->lport = atoi(p); 
		if(c->lport == 0) 
			setlport(c); 
1997/1128/sys/src/9/ip/devip.c:575,5881998/0306/sys/src/9/ip/devip.c:623,634
1997/0327    
setraddrport(Conv* c, char* str) 
{ 
1997/0423    
	char *p; 
1997/0815    
	uchar addr[IPaddrlen]; 
1997/0327    
 
	p = strchr(str, '!'); 
	if(p == nil) 
		return "malformed address"; 
	*p++ = 0; 
	parseip(addr, str); 
1997/0423    
	c->raddr = nhgetl(addr); 
1998/0306    
	parseip(c->raddr, str); 
1997/0327    
	c->rport = atoi(p); 
	p = strchr(p, '!'); 
	if(p){ 
1997/1128/sys/src/9/ip/devip.c:592,6351998/0306/sys/src/9/ip/devip.c:638,800
1997/0327    
	return nil; 
} 
 
1998/0306    
/* 
 *  called by protocol connect routine to set addresses 
 */ 
char* 
Fsstdconnect(Conv *c, char *argv[], int argc) 
{ 
	char *p; 
 
	switch(argc) { 
	default: 
		return "bad args to connect"; 
	case 2: 
		p = setraddrport(c, argv[1]); 
		if(p != nil) 
			return p; 
		setladdr(c); 
		setlport(c); 
		break; 
	case 3: 
		p = setraddrport(c, argv[1]); 
		if(p != nil) 
			return p; 
		setladdrport(c, argv[2], 0); 
		break; 
	} 
	return nil; 
} 
/* 
 *  initiate connection and sleep till its set up 
 */ 
1997/0327    
static int 
connected(void* a) 
{ 
	return ((Conv*)a)->state == Connected; 
} 
1998/0306    
static void 
connectctlmsg(Proto *x, Conv *c, Cmdbuf *cb) 
{ 
	char *p; 
1997/0327    
 
1998/0306    
	c->state = Connecting; 
	c->cerr[0] = '\0'; 
	if(x->connect == nil) 
		error("connect not supported"); 
	p = x->connect(c, cb->f, cb->nf); 
	if(p != nil) 
		error(p); 
	sleep(&c->cr, connected, c); 
	if(c->cerr[0] != '\0') 
		error(c->cerr); 
} 
 
/* 
 *  called by protocol announce routine to set addresses 
 */ 
char* 
Fsstdannounce(Conv* c, char* argv[], int argc) 
{ 
	switch(argc){ 
	default: 
		return "bad args to announce"; 
	case 2: 
		setladdrport(c, argv[1], 1); 
		break; 
	} 
	return nil; 
} 
 
/* 
 *  initiate announcement and sleep till its set up 
 */ 
1997/0327    
static int 
announced(void* a) 
{ 
	return ((Conv*)a)->state == Announced; 
} 
1998/0306    
static void 
announcectlmsg(Proto *x, Conv *c, Cmdbuf *cb) 
{ 
	char *p; 
1997/0327    
 
1998/0306    
	c->state = Announcing; 
	c->cerr[0] = '\0'; 
	if(x->announce == nil) 
		error("announce not supported"); 
	p = x->announce(c, cb->f, cb->nf); 
	if(p != nil) 
		error(p); 
	sleep(&c->cr, announced, c); 
	if(c->cerr[0] != '\0') 
		error(c->cerr); 
} 
 
/* 
 *  called by protocol bide routine to set addresses 
 */ 
char* 
Fsstdbind(Conv* c, char* argv[], int argc) 
{ 
	switch(argc){ 
	default: 
		return "bad args to bind"; 
	case 2: 
		setladdrport(c, argv[1], 0); 
		break; 
	} 
	return nil; 
} 
 
static void 
bindctlmsg(Proto *x, Conv *c, Cmdbuf *cb) 
{ 
	char *p; 
 
	if(x->bind == nil) 
		p = Fsstdbind(c, cb->f, cb->nf); 
	else 
		p = x->bind(c, cb->f, cb->nf); 
	if(p != nil) 
		error(p); 
} 
 
static void 
ttlctlmsg(Conv *c, Cmdbuf *cb) 
{ 
	if(cb->nf < 2) 
		c->ttl = MAXTTL; 
	else 
		c->ttl = atoi(cb->f[1]); 
} 
 
1997/0327    
static long 
ipwrite(Chan* ch, char* a, long n, ulong) 
{ 
	Conv *c; 
	Proto *x; 
	int nfield; 
	char *p, *fields[10], buf[128]; 
1998/0306    
	char *p; 
	Cmdbuf *cb; 
	uchar ia[IPaddrlen]; 
1997/0327    
 
	switch(TYPE(ch->qid)){ 
	default: 
		error(Eperm); 
1998/0306    
	case Qdata: 
		x = fs.p[PROTO(ch->qid)]; 
		c = x->conv[CONV(ch->qid)]; 
 
		if(c->wq == nil) 
			error(Eperm); 
 
		qwrite(c->wq, a, n); 
		x->kick(c, n); 
		break; 
1997/0327    
	case Qarp: 
		p = arpwrite(a, n); 
		if(p != nil) 
			error(p); 
		return n; 
	case Qipifc: 
1997/0423    
		p = Mediaifcwrite(ch->aux, a, n); 
1997/0327    
		if(p != nil) 
			error(p); 
		return n; 
1998/0306    
		return arpwrite(a, n); 
1997/0327    
	case Qiproute: 
		p = routewrite(a, n); 
		if(p != nil) 
			error(p); 
		return n; 
1998/0306    
		return routewrite(ch, a, n); 
1997/0327    
	case Qlog: 
		p = netlogctl(a, n); 
		if(p != nil) 
1997/1128/sys/src/9/ip/devip.c:638,7271998/0306/sys/src/9/ip/devip.c:803,850
1997/0327    
	case Qctl: 
		x = fs.p[PROTO(ch->qid)]; 
		c = x->conv[CONV(ch->qid)]; 
		if(n > sizeof(buf)-1) 
			n = sizeof(buf)-1; 
		memmove(buf, a, n); 
		buf[n] = '\0'; 
		nfield = parsefields(buf, fields, 10, " "); 
		if(strcmp(fields[0], "connect") == 0){ 
			if(canqlock(&c->car) == 0) 
				error("connect/announce in progress"); 
			if(waserror()) { 
				qunlock(&c->car); 
				nexterror(); 
			} 
			c->state = Connecting; 
			c->cerr[0] = '\0'; 
			p = x->connect(c, fields, nfield); 
			if(p != nil) 
				error(p); 
			sleep(&c->cr, connected, c); 
			if(c->cerr[0] != '\0') 
				error(c->cerr); 
			qunlock(&c->car); 
			poperror(); 
			return n; 
1998/0306    
		cb = parsecmd(a, n); 
 
		if(canqlock(&c->car) == 0){ 
			free(cb); 
			error("connect/announce in progress"); 
1997/0327    
		} 
		if(strcmp(fields[0], "announce") == 0){ 
			if(canqlock(&c->car) == 0) 
				error("connect/announce in progress"); 
			if(waserror()) { 
				qunlock(&c->car); 
				nexterror(); 
			} 
			c->state = Announcing; 
			c->cerr[0] = '\0'; 
1997/0403    
			p = x->announce(c, fields, nfield); 
			if(p != nil) 
				error(p); 
1997/0327    
			sleep(&c->cr, announced, c); 
			if(c->cerr[0] != '\0') 
				error(c->cerr); 
1998/0306    
		if(waserror()) { 
1997/0327    
			qunlock(&c->car); 
			poperror(); 
			return n; 
1998/0306    
			free(cb); 
			nexterror(); 
1997/0327    
		} 
		if(strcmp(fields[0], "bind") == 0){ 
			if(canqlock(&c->car) == 0) 
				error("connect/announce in progress"); 
			if(waserror()) { 
				qunlock(&c->car); 
				nexterror(); 
			} 
			switch(nfield){ 
			default: 
				error("bad args to bind"); 
			case 2: 
				setladdr(c); 
				c->lport = atoi(fields[1]); 
				if(c->lport == 0) 
					setlport(c); 
				break; 
			} 
			qunlock(&c->car); 
			poperror(); 
			return n; 
		} 
		if(strcmp(fields[0], "ttl") == 0){ 
			if(nfield < 2) 
				c->ttl = MAXTTL; 
			else 
				c->ttl = atoi(fields[1]); 
			return n; 
		} 
		if(x->ctl != nil) { 
			p = x->ctl(c, fields, nfield); 
1998/0306    
		if(strcmp(cb->f[0], "connect") == 0) 
			connectctlmsg(x, c, cb); 
		else if(strcmp(cb->f[0], "announce") == 0) 
			announcectlmsg(x, c, cb); 
		else if(strcmp(cb->f[0], "bind") == 0) 
			bindctlmsg(x, c, cb); 
		else if(strcmp(cb->f[0], "ttl") == 0) 
			ttlctlmsg(c, cb); 
		else if(strcmp(cb->f[0], "addmulti") == 0){ 
			if(cb->nf < 2) 
				error("addmulti needs interface address"); 
			if(!ipismulticast(c->raddr)) 
				error("addmulti for a non multicast address"); 
			parseip(ia, cb->f[1]); 
			ipifcaddmulti(c, c->raddr, ia); 
		} else if(strcmp(cb->f[0], "remmulti") == 0){ 
			if(cb->nf < 2) 
				error("remmulti needs interface address"); 
			if(!ipismulticast(c->raddr)) 
				error("remmulti for a non multicast address"); 
			parseip(ia, cb->f[1]); 
			ipifcremmulti(c, c->raddr, ia); 
		} else if(x->ctl != nil) { 
			p = x->ctl(c, cb->f, cb->nf); 
1997/0327    
			if(p != nil) 
				error(p); 
			return n; 
		} 
		error("unknown control request"); 
	case Qdata: 
		x = fs.p[PROTO(ch->qid)]; 
		c = x->conv[CONV(ch->qid)]; 
                 
		qwrite(c->wq, a, n); 
		x->kick(c, n); 
1998/0306    
		} else 
			error("unknown control request"); 
		qunlock(&c->car); 
		free(cb); 
		poperror(); 
1997/0327    
	} 
	return n; 
} 
1997/1128/sys/src/9/ip/devip.c:782,7881998/0306/sys/src/9/ip/devip.c:905,911
1997/0327    
 *  built in 
 */ 
int 
Fsbuiltinproto(Fs* fs, byte proto) 
1998/0306    
Fsbuiltinproto(Fs* fs, uchar proto) 
1997/0327    
{ 
	return fs->t2p[proto] != nil; 
} 
1997/1128/sys/src/9/ip/devip.c:790,8031998/0306/sys/src/9/ip/devip.c:913,924
1997/0327    
Conv* 
Fsprotoclone(Proto *p, char *user) 
{ 
	char *junk; 
	int unused; 
	Conv *c, **pp, **ep; 
 
	c = nil; 
	lock(p); 
1998/0306    
	qlock(p); 
1997/0327    
	if(waserror()) { 
		unlock(p); 
1998/0306    
		qunlock(p); 
1997/0327    
		nexterror(); 
	} 
	ep = &p->conv[p->nc]; 
1997/1128/sys/src/9/ip/devip.c:812,8181998/0306/sys/src/9/ip/devip.c:933,938
1997/0327    
			c->x = pp - p->conv; 
			c->ptcl = malloc(p->ptclsize); 
			if(c->ptcl == nil) { 
1997/1104    
				unlock(c); 
1997/0327    
				free(c); 
				error(Enomem); 
			} 
1997/1128/sys/src/9/ip/devip.c:823,8301998/0306/sys/src/9/ip/devip.c:943,953
1997/0327    
			break; 
		} 
		if(canlock(c)){ 
			unused = p->state(&junk, c); 
			if(c->inuse == 0 && unused) 
1998/0306    
			/* 
			 *  make sure both processes and protocol 
			 *  are done with this Conv 
			 */ 
			if(c->inuse == 0 && (p->inuse == nil || (*p->inuse)(c) == 0)) 
1997/0327    
				break; 
 
			unlock(c); 
1997/1128/sys/src/9/ip/devip.c:831,8371998/0306/sys/src/9/ip/devip.c:954,960
1997/0327    
		} 
	} 
	if(pp >= ep) { 
		unlock(p); 
1998/0306    
		qunlock(p); 
1997/0327    
		poperror(); 
		return nil; 
	} 
1997/1128/sys/src/9/ip/devip.c:840,8471998/0306/sys/src/9/ip/devip.c:963,970
1997/0327    
	strcpy(c->owner, user); 
	c->perm = 0660; 
	c->state = 0; 
	c->laddr = 0; 
	c->raddr = 0; 
1998/0306    
	ipmove(c->laddr, IPnoaddr); 
	ipmove(c->raddr, IPnoaddr); 
1997/0327    
	c->lport = 0; 
	c->rport = 0; 
	c->restricted = 0; 
1997/1128/sys/src/9/ip/devip.c:851,8571998/0306/sys/src/9/ip/devip.c:974,980
1997/0327    
	qreopen(c->eq); 
 
	unlock(c); 
	unlock(p); 
1998/0306    
	qunlock(p); 
1997/0327    
	poperror(); 
	return c; 
} 
1997/1128/sys/src/9/ip/devip.c:878,8901998/0306/sys/src/9/ip/devip.c:1001,1013
1997/0327    
} 
 
Proto* 
Fsrcvpcol(Fs* fs, byte proto) 
1998/0306    
Fsrcvpcol(Fs* fs, uchar proto) 
1997/0327    
{ 
	return fs->t2p[proto]; 
} 
 
Conv* 
Fsnewcall(Fs*, Conv *c, Ipaddr raddr, ushort rport, Ipaddr laddr, ushort lport) 
1998/0306    
Fsnewcall(Fs*, Conv *c, uchar *raddr, ushort rport, uchar *laddr, ushort lport) 
1997/0327    
{ 
	Conv *nc; 
	Conv **l; 
1997/1128/sys/src/9/ip/devip.c:905,9131998/0306/sys/src/9/ip/devip.c:1028,1036
1997/0327    
		unlock(c); 
		return nil; 
	} 
	nc->raddr = raddr; 
1998/0306    
	ipmove(nc->raddr, raddr); 
1997/0327    
	nc->rport = rport; 
	nc->laddr = laddr; 
1998/0306    
	ipmove(nc->laddr, laddr); 
1997/0327    
	nc->lport = lport; 
	nc->next = nil; 
	*l = nc; 
1997/1128/sys/src/9/ip/devip.c:916,9751998/0306/sys/src/9/ip/devip.c:1039,1042
1997/0327    
	wakeup(&c->listenr); 
 
	return nc; 
} 
                 
int 
Fspcolstats(char *buf, int len) 
{ 
	Proto **p; 
	int n; 
                 
	n = 0; 
1997/0916    
	for(p = fs.p; *p; p++){ 
1997/0327    
		n += snprint(buf + n, len - n, 
1997/0916    
			"%s: csum %d hlen %d len %d order %d rexmit %d\n", 
1997/0327    
			(*p)->name, (*p)->csumerr, (*p)->hlenerr, (*p)->lenerr, 
1997/0916    
			(*p)->order, (*p)->rexmit); 
		if((*p)->stats) 
			n += (*(*p)->stats)(buf + n, len - n); 
	} 
1997/0327    
	return n; 
} 
                 
char* 
Fsstdconnect(Conv *c, char *argv[], int argc) 
{ 
	char *p; 
                 
	switch(argc) { 
	default: 
		return "bad args to connect"; 
	case 2: 
		p = setraddrport(c, argv[1]); 
		if(p != nil) 
			return p; 
		setladdr(c); 
		setlport(c); 
		break; 
	case 3: 
		p = setraddrport(c, argv[1]); 
		if(p != nil) 
			return p; 
1997/1030    
		setladdrport(c, argv[2], 1); 
1997/0403    
		break; 
	} 
	return nil; 
} 
                 
char* 
Fsstdannounce(Conv* c, char* argv[], int argc) 
{ 
	switch(argc){ 
	default: 
		return "bad args to announce"; 
	case 2: 
1997/1030    
		setladdrport(c, argv[1], 0); 
1997/0327    
		break; 
	} 
	return nil; 
} 


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