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

📄 devip.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
ipbread(Chan* ch, long n, ulong offset){	Conv *c;	Proto *x;	Fs *f;	switch(TYPE(ch->qid)){	case Qdata:		f = ipfs[ch->dev];		x = f->p[PROTO(ch->qid)];		c = x->conv[CONV(ch->qid)];		return qbread(c->rq, n);	default:		return devbread(ch, n, offset);	}}/* *  set local address to be that of the ifc closest to remote address */static voidsetladdr(Conv* c){	findlocalip(c->p->f, c->laddr, c->raddr);}/* *  set a local port making sure the quad of raddr,rport,laddr,lport is unique */char*setluniqueport(Conv* c, int lport){	Proto *p;	Conv *xp;	int x;	p = c->p;	qlock(p);	for(x = 0; x < p->nc; x++){		xp = p->conv[x];		if(xp == nil)			break;		if(xp == c)			continue;		if((xp->state == Connected || xp->state == Announced)		&& xp->lport == lport		&& xp->rport == c->rport		&& ipcmp(xp->raddr, c->raddr) == 0		&& ipcmp(xp->laddr, c->laddr) == 0){			qunlock(p);			return "address in use";		}	}	c->lport = lport;	qunlock(p);	return nil;}/* *  pick a local port and set it */voidsetlport(Conv* c){	Proto *p;	ushort *pp;	int x, found;	p = c->p;	if(c->restricted)		pp = &p->nextrport;	else		pp = &p->nextport;	qlock(p);	for(;;(*pp)++){		/*		 * Fsproto initialises p->nextport to 0 and the restricted		 * ports (p->nextrport) to 600.		 * Restricted ports must lie between 600 and 1024.		 * For the initial condition or if the unrestricted port number		 * has wrapped round, select a random port between 5000 and 1<<15		 * to start at.		 */		if(c->restricted){			if(*pp >= 1024)				*pp = 600;		}		else while(*pp < 5000)			*pp = nrand(1<<15);		found = 0;		for(x = 0; x < p->nc; x++){			if(p->conv[x] == nil)				break;			if(p->conv[x]->lport == *pp){				found = 1;				break;			}		}		if(!found)			break;	}	c->lport = (*pp)++;	qunlock(p);}/* *  set a local address and port from a string of the form *	[address!]port[!r] */char*setladdrport(Conv* c, char* str, int announcing){	char *p;	char *rv;	ushort lport;	uchar addr[IPaddrlen];	rv = nil;	/*	 *  ignore restricted part if it exists.  it's	 *  meaningless on local ports.	 */	p = strchr(str, '!');	if(p != nil){		*p++ = 0;		if(strcmp(p, "r") == 0)			p = nil;	}	c->lport = 0;	if(p == nil){		if(announcing)			ipmove(c->laddr, IPnoaddr);		else			setladdr(c);		p = str;	} else {		if(strcmp(str, "*") == 0)			ipmove(c->laddr, IPnoaddr);		else {			parseip(addr, str);			if(ipforme(c->p->f, addr))				ipmove(c->laddr, addr);			else				return "not a local IP address";		}	}	/* one process can get all connections */	if(announcing && strcmp(p, "*") == 0){		if(!iseve())			error(Eperm);		return setluniqueport(c, 0);	}	lport = atoi(p);	if(lport <= 0)		setlport(c);	else		rv = setluniqueport(c, lport);	return rv;}static char*setraddrport(Conv* c, char* str){	char *p;	p = strchr(str, '!');	if(p == nil)		return "malformed address";	*p++ = 0;	parseip(c->raddr, str);	c->rport = atoi(p);	p = strchr(p, '!');	if(p){		if(strstr(p, "!r") != nil)			c->restricted = 1;	}	return nil;}/* *  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;		p = setladdrport(c, argv[2], 0);		if(p != nil)			return p;	}	if( (memcmp(c->raddr, v4prefix, IPv4off) == 0 &&		memcmp(c->laddr, v4prefix, IPv4off) == 0)		|| ipcmp(c->raddr, IPnoaddr) == 0)		c->ipversion = V4;	else		c->ipversion = V6;	return nil;}/* *  initiate connection and sleep till its set up */static intconnected(void* a){	return ((Conv*)a)->state == Connected;}static voidconnectctlmsg(Proto *x, Conv *c, Cmdbuf *cb){	char *p;	if(c->state != 0)		error(Econinuse);	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);	qunlock(c);	if(waserror()){		qlock(c);		nexterror();	}	sleep(&c->cr, connected, c);	qlock(c);	poperror();	if(c->cerr[0] != '\0')		error(c->cerr);}/* *  called by protocol announce routine to set addresses */char*Fsstdannounce(Conv* c, char* argv[], int argc){	memset(c->raddr, 0, sizeof(c->raddr));	c->rport = 0;	switch(argc){	default:		break;	case 2:		return setladdrport(c, argv[1], 1);	}	return "bad args to announce";}/* *  initiate announcement and sleep till its set up */static intannounced(void* a){	return ((Conv*)a)->state == Announced;}static voidannouncectlmsg(Proto *x, Conv *c, Cmdbuf *cb){	char *p;	if(c->state != 0)		error(Econinuse);	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);	qunlock(c);	if(waserror()){		qlock(c);		nexterror();	}	sleep(&c->cr, announced, c);	qlock(c);	poperror();	if(c->cerr[0] != '\0')		error(c->cerr);}/* *  called by protocol bind routine to set addresses */char*Fsstdbind(Conv* c, char* argv[], int argc){	switch(argc){	default:		break;	case 2:		return setladdrport(c, argv[1], 0);	}	return "bad args to bind";}static voidbindctlmsg(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 voidtosctlmsg(Conv *c, Cmdbuf *cb){	if(cb->nf < 2)		c->tos = 0;	else		c->tos = atoi(cb->f[1]);}static voidttlctlmsg(Conv *c, Cmdbuf *cb){	if(cb->nf < 2)		c->ttl = MAXTTL;	else		c->ttl = atoi(cb->f[1]);}static longipwrite(Chan* ch, void *v, long n, vlong off){	Conv *c;	Proto *x;	char *p;	Cmdbuf *cb;	uchar ia[IPaddrlen], ma[IPaddrlen];	Fs *f;	char *a;	ulong offset = off;	a = v;	f = ipfs[ch->dev];	switch(TYPE(ch->qid)){	default:		error(Eperm);	case Qdata:		x = f->p[PROTO(ch->qid)];		c = x->conv[CONV(ch->qid)];		if(c->wq == nil)			error(Eperm);		qwrite(c->wq, a, n);		break;	case Qarp:		return arpwrite(f, a, n);	case Qiproute:		return routewrite(f, ch, a, n);	case Qlog:		netlogctl(f, a, n);		return n;	case Qndb:		return ndbwrite(f, a, offset, n);		break;	case Qctl:		x = f->p[PROTO(ch->qid)];		c = x->conv[CONV(ch->qid)];		cb = parsecmd(a, n);		qlock(c);		if(waserror()) {			qunlock(c);			free(cb);			nexterror();		}		if(cb->nf < 1)			error("short control request");		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], "tos") == 0)			tosctlmsg(c, cb);		else if(strcmp(cb->f[0], "ignoreadvice") == 0)			c->ignoreadvice = 1;		else if(strcmp(cb->f[0], "addmulti") == 0){			if(cb->nf < 2)				error("addmulti needs interface address");			if(cb->nf == 2){				if(!ipismulticast(c->raddr))					error("addmulti for a non multicast address");				parseip(ia, cb->f[1]);				ipifcaddmulti(c, c->raddr, ia);			} else {				parseip(ma, cb->f[2]);				if(!ipismulticast(ma))					error("addmulti for a non multicast address");				parseip(ia, cb->f[1]);				ipifcaddmulti(c, ma, 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);			if(p != nil)				error(p);		} else			error("unknown control request");		qunlock(c);		free(cb);		poperror();	}	return n;}static longipbwrite(Chan* ch, Block* bp, ulong offset){	Conv *c;	Proto *x;	Fs *f;	int n;	switch(TYPE(ch->qid)){	case Qdata:		f = ipfs[ch->dev];		x = f->p[PROTO(ch->qid)];		c = x->conv[CONV(ch->qid)];		if(c->wq == nil)			error(Eperm);		if(bp->next)			bp = concatblock(bp);		n = BLEN(bp);		qbwrite(c->wq, bp);		return n;	default:		return devbwrite(ch, bp, offset);	}}Dev ipdevtab = {	'I',	"ip",	ipreset,	devinit,	devshutdown,	ipattach,	ipwalk,	ipstat,	ipopen,	ipcreate,	ipclose,	ipread,	ipbread,	ipwrite,	ipbwrite,	ipremove,	ipwstat,};intFsproto(Fs *f, Proto *p){	if(f->np >= Maxproto)		return -1;	p->f = f;	if(p->ipproto > 0){		if(f->t2p[p->ipproto] != nil)			return -1;		f->t2p[p->ipproto] = p;	}	p->qid.type = QTDIR;	p->qid.path = QID(f->np, 0, Qprotodir);	p->conv = malloc(sizeof(Conv*)*(p->nc+1));	if(p->conv == nil)		panic("Fsproto");	p->x = f->np;	p->nextport = 0;	p->nextrport = 600;	f->p[f->np++] = p;	return 0;}/* *  return true if this protocol is *  built in */intFsbuiltinproto(Fs* f, uchar proto){	return f->t2p[proto] != nil;}/* *  called with protocol locked */Conv*Fsprotoclone(Proto *p, char *user){	Conv *c, **pp, **ep;retry:	c = nil;	ep = &p->conv[p->nc];	for(pp = p->conv; pp < ep; pp++) {		c = *pp;		if(c == nil){			c = malloc(sizeof(Conv));			if(c == nil)				error(Enomem);			qlock(c);			c->p = p;			c->x = pp - p->conv;			if(p->ptclsize != 0){				c->ptcl = malloc(p->ptclsize);				if(c->ptcl == nil) {					free(c);					error(Enomem);				}			}			*pp = c;			p->ac++;			c->eq = qopen(1024, Qmsg, 0, 0);			(*p->create)(c);			break;		}		if(canqlock(c)){			/*			 *  make sure both processes and protocol			 *  are done with this Conv			 */			if(c->inuse == 0 && (p->inuse == nil || (*p->inuse)(c) == 0))				break;			qunlock(c);		}	}	if(pp >= ep) {		if(p->gc != nil && (*p->gc)(p))			goto retry;		return nil;	}	c->inuse = 1;	kstrdup(&c->owner, user);	c->perm = 0660;	c->state = Idle;	ipmove(c->laddr, IPnoaddr);	ipmove(c->raddr, IPnoaddr);	c->r = nil;	c->rgen = 0;	c->lport = 0;	c->rport = 0;	c->restricted = 0;	c->ttl = MAXTTL;	qreopen(c->rq);	qreopen(c->wq);	qreopen(c->eq);	qunlock(c);	return c;}intFsconnected(Conv* c, char* msg){	if(msg != nil && *msg != '\0')		strncpy(c->cerr, msg, ERRMAX-1);	switch(c->state){	case Announcing:		c->state = Announced;		break;	case Connecting:		c->state = Connected;		break;	}	wakeup(&c->cr);	return 0;}Proto*Fsrcvpcol(Fs* f, uchar proto){	if(f->ipmux)		return f->ipmux;	else		return f->t2p[proto];}Proto*Fsrcvpcolx(Fs *f, uchar proto){	return f->t2p[proto];}/* *  called with protocol locked */Conv*Fsnewcall(Conv *c, uchar *raddr, ushort rport, uchar *laddr, ushort lport, uchar version){	Conv *nc;	Conv **l;	int i;	qlock(c);	i = 0;	for(l = &c->incall; *l; l = &(*l)->next)		i++;	if(i >= Maxincall) {		qunlock(c);		return nil;	}	/* find a free conversation */	nc = Fsprotoclone(c->p, network);	if(nc == nil) {		qunlock(c);		return nil;	}	ipmove(nc->raddr, raddr);	nc->rport = rport;	ipmove(nc->laddr, laddr);	nc->lport = lport;	nc->next = nil;	*l = nc;	nc->state = Connected;	nc->ipversion = version;	qunlock(c);	wakeup(&c->listenr);	return nc;}longndbwrite(Fs *f, char *a, ulong off, int n){	if(off > strlen(f->ndb))		error(Eio);	if(off+n >= sizeof(f->ndb))		error(Eio);	memmove(f->ndb+off, a, n);	f->ndb[off+n] = 0;	f->ndbvers++;	f->ndbmtime = seconds();	return n;}ulongscalednconv(void){	if(cpuserver && conf.npage*BY2PG >= 128*MB)		return Nchans*4;	return Nchans;}

⌨️ 快捷键说明

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