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

📄 ipifc.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
			v6delroute(f, v6allnodesN, v6allnodesNmask, 1);		else if(memcmp(lifc->local, v6linklocal, v6llpreflen) == 0)			/* remove route for all link multicast */			v6delroute(f, v6allnodesL, v6allnodesLmask, 1);	}	free(lifc);	return nil;}/* *  remove an address from an interface. *  called with c->car locked */char*ipifcrem(Ipifc *ifc, char **argv, int argc){	uchar ip[IPaddrlen];	uchar mask[IPaddrlen];	uchar rem[IPaddrlen];	Iplifc *lifc;	char *rv;	if(argc < 3)		return Ebadarg;	parseip(ip, argv[1]);	parseipmask(mask, argv[2]);	if(argc < 4)		maskip(ip, mask, rem);	else		parseip(rem, argv[3]);	wlock(ifc);	/*	 *  find address on this interface and remove from chain.	 *  for pt to pt we actually specify the remote address as the	 *  addresss to remove.	 */	for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next) {		if (memcmp(ip, lifc->local, IPaddrlen) == 0		&& memcmp(mask, lifc->mask, IPaddrlen) == 0		&& memcmp(rem, lifc->remote, IPaddrlen) == 0)			break;	}	rv = ipifcremlifc(ifc, lifc);	wunlock(ifc);	return rv;}/* * distribute routes to active interfaces like the * TRIP linecards */voidipifcaddroute(Fs *f, int vers, uchar *addr, uchar *mask, uchar *gate, int type){	Medium *m;	Conv **cp, **e;	Ipifc *ifc;	e = &f->ipifc->conv[f->ipifc->nc];	for(cp = f->ipifc->conv; cp < e; cp++){		if(*cp != nil) {			ifc = (Ipifc*)(*cp)->ptcl;			m = ifc->m;			if(m == nil)				continue;			if(m->addroute != nil)				m->addroute(ifc, vers, addr, mask, gate, type);		}	}}voidipifcremroute(Fs *f, int vers, uchar *addr, uchar *mask){	Medium *m;	Conv **cp, **e;	Ipifc *ifc;	e = &f->ipifc->conv[f->ipifc->nc];	for(cp = f->ipifc->conv; cp < e; cp++){		if(*cp != nil) {			ifc = (Ipifc*)(*cp)->ptcl;			m = ifc->m;			if(m == nil)				continue;			if(m->remroute != nil)				m->remroute(ifc, vers, addr, mask);		}	}}/* *  associate an address with the interface.  This wipes out any previous *  addresses.  This is a macro that means, remove all the old interfaces *  and add a new one. */static char*ipifcconnect(Conv* c, char **argv, int argc){	char *err;	Ipifc *ifc;	ifc = (Ipifc*)c->ptcl;	if(ifc->m == nil)		 return "ipifc not yet bound to device";	if(waserror()){		wunlock(ifc);		nexterror();	}	wlock(ifc);	while(ifc->lifc){		err = ipifcremlifc(ifc, ifc->lifc);		if(err)			error(err);	}	wunlock(ifc);	poperror();	err = ipifcadd(ifc, argv, argc, 0, nil);	if(err)		return err;	Fsconnected(c, nil);	return nil;}char*ipifcsetpar6(Ipifc *ifc, char **argv, int argc){	int i, argsleft, vmax = ifc->rp.maxraint, vmin = ifc->rp.minraint;	argsleft = argc - 1;	i = 1;	if(argsleft % 2 != 0)		return Ebadarg;	while (argsleft > 1) {		if(strcmp(argv[i],"recvra")==0)			ifc->recvra6 = (atoi(argv[i+1]) != 0);		else if(strcmp(argv[i],"sendra")==0)			ifc->sendra6 = (atoi(argv[i+1]) != 0);		else if(strcmp(argv[i],"mflag")==0)			ifc->rp.mflag = (atoi(argv[i+1]) != 0);		else if(strcmp(argv[i],"oflag")==0)			ifc->rp.oflag = (atoi(argv[i+1]) != 0);		else if(strcmp(argv[i],"maxraint")==0)			ifc->rp.maxraint = atoi(argv[i+1]);		else if(strcmp(argv[i],"minraint")==0)			ifc->rp.minraint = atoi(argv[i+1]);		else if(strcmp(argv[i],"linkmtu")==0)			ifc->rp.linkmtu = atoi(argv[i+1]);		else if(strcmp(argv[i],"reachtime")==0)			ifc->rp.reachtime = atoi(argv[i+1]);		else if(strcmp(argv[i],"rxmitra")==0)			ifc->rp.rxmitra = atoi(argv[i+1]);		else if(strcmp(argv[i],"ttl")==0)			ifc->rp.ttl = atoi(argv[i+1]);		else if(strcmp(argv[i],"routerlt")==0)			ifc->rp.routerlt = atoi(argv[i+1]);		else			return Ebadarg;		argsleft -= 2;		i += 2;	}	// consistency check	if(ifc->rp.maxraint < ifc->rp.minraint) {		ifc->rp.maxraint = vmax;		ifc->rp.minraint = vmin;		return Ebadarg;	}	return nil;}char*ipifcsendra6(Ipifc *ifc, char **argv, int argc){	int i;	i = 0;	if(argc > 1)		i = atoi(argv[1]);	ifc->sendra6 = (i!=0);	return nil;}char*ipifcrecvra6(Ipifc *ifc, char **argv, int argc){	int i;	i = 0;	if(argc > 1)		i = atoi(argv[1]);	ifc->recvra6 = (i!=0);	return nil;}/* *  non-standard control messages. *  called with c->car locked. */static char*ipifcctl(Conv* c, char**argv, int argc){	Ipifc *ifc;	int i;	ifc = (Ipifc*)c->ptcl;	if(strcmp(argv[0], "add") == 0)		return ipifcadd(ifc, argv, argc, 0, nil);	else if(strcmp(argv[0], "try") == 0)		return ipifcadd(ifc, argv, argc, 1, nil);	else if(strcmp(argv[0], "remove") == 0)		return ipifcrem(ifc, argv, argc);	else if(strcmp(argv[0], "unbind") == 0)		return ipifcunbind(ifc);	else if(strcmp(argv[0], "joinmulti") == 0)		return ipifcjoinmulti(ifc, argv, argc);	else if(strcmp(argv[0], "leavemulti") == 0)		return ipifcleavemulti(ifc, argv, argc);	else if(strcmp(argv[0], "mtu") == 0)		return ipifcsetmtu(ifc, argv, argc);	else if(strcmp(argv[0], "reassemble") == 0){		ifc->reassemble = 1;		return nil;	}	else if(strcmp(argv[0], "iprouting") == 0){		i = 1;		if(argc > 1)			i = atoi(argv[1]);		iprouting(c->p->f, i);		return nil;	}	else if(strcmp(argv[0], "addpref6") == 0)		return ipifcaddpref6(ifc, argv, argc);	else if(strcmp(argv[0], "setpar6") == 0)		return ipifcsetpar6(ifc, argv, argc);	else if(strcmp(argv[0], "sendra6") == 0)		return ipifcsendra6(ifc, argv, argc);	else if(strcmp(argv[0], "recvra6") == 0)		return ipifcrecvra6(ifc, argv, argc);	return "unsupported ctl";}intipifcstats(Proto *ipifc, char *buf, int len){	return ipstats(ipifc->f, buf, len);}voidipifcinit(Fs *f){	Proto *ipifc;	ipifc = smalloc(sizeof(Proto));	ipifc->name = "ipifc";	ipifc->connect = ipifcconnect;	ipifc->announce = nil;	ipifc->bind = ipifcbind;	ipifc->state = ipifcstate;	ipifc->create = ipifccreate;	ipifc->close = ipifcclose;	ipifc->rcv = nil;	ipifc->ctl = ipifcctl;	ipifc->advise = nil;	ipifc->stats = ipifcstats;	ipifc->inuse = ipifcinuse;	ipifc->local = ipifclocal;	ipifc->ipproto = -1;	ipifc->nc = Maxmedia;	ipifc->ptclsize = sizeof(Ipifc);	f->ipifc = ipifc;			/* hack for ipifcremroute, findipifc, ... */	f->self = smalloc(sizeof(Ipselftab));	/* hack for ipforme */	Fsproto(f, ipifc);}/* *  add to self routing cache *	called with c->car locked */static voidaddselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a, int type){	Ipself *p;	Iplink *lp;	int h;	qlock(f->self);	/* see if the address already exists */	h = hashipa(a);	for(p = f->self->hash[h]; p; p = p->next)		if(memcmp(a, p->a, IPaddrlen) == 0)			break;	/* allocate a local address and add to hash chain */	if(p == nil){		p = smalloc(sizeof(*p));		ipmove(p->a, a);		p->type = type;		p->next = f->self->hash[h];		f->self->hash[h] = p;		/* if the null address, accept all packets */		if(ipcmp(a, v4prefix) == 0 || ipcmp(a, IPnoaddr) == 0)			f->self->acceptall = 1;	}	/* look for a link for this lifc */	for(lp = p->link; lp; lp = lp->selflink)		if(lp->lifc == lifc)			break;	/* allocate a lifc-to-local link and link to both */	if(lp == nil){		lp = smalloc(sizeof(*lp));		lp->ref = 1;		lp->lifc = lifc;		lp->self = p;		lp->selflink = p->link;		p->link = lp;		lp->lifclink = lifc->link;		lifc->link = lp;		/* add to routing table */		if(isv4(a))			v4addroute(f, tifc, a+IPv4off, IPallbits+IPv4off, a+IPv4off, type);		else			v6addroute(f, tifc, a, IPallbits, a, type);		if((type & Rmulti) && ifc->m->addmulti != nil)			(*ifc->m->addmulti)(ifc, a, lifc->local);	} else {		lp->ref++;	}	qunlock(f->self);}/* *  These structures are unlinked from their chains while *  other threads may be using them.  To avoid excessive locking, *  just put them aside for a while before freeing them. *	called with f->self locked */static Iplink *freeiplink;static Ipself *freeipself;static voidiplinkfree(Iplink *p){	Iplink **l, *np;	ulong now = NOW;	l = &freeiplink;	for(np = *l; np; np = *l){		if(np->expire > now){			*l = np->next;			free(np);			continue;		}		l = &np->next;	}	p->expire = now + 5000;		/* give other threads 5 secs to get out */	p->next = nil;	*l = p;}static voidipselffree(Ipself *p){	Ipself **l, *np;	ulong now = NOW;	l = &freeipself;	for(np = *l; np; np = *l){		if(np->expire > now){			*l = np->next;			free(np);			continue;		}		l = &np->next;	}	p->expire = now + 5000;		/* give other threads 5 secs to get out */	p->next = nil;	*l = p;}/* *  Decrement reference for this address on this link. *  Unlink from selftab if this is the last ref. *	called with c->car locked */static voidremselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a){	Ipself *p, **l;	Iplink *link, **l_self, **l_lifc;	qlock(f->self);	/* find the unique selftab entry */	l = &f->self->hash[hashipa(a)];	for(p = *l; p; p = *l){		if(ipcmp(p->a, a) == 0)			break;		l = &p->next;	}	if(p == nil)		goto out;	/*	 *  walk down links from an ifc looking for one	 *  that matches the selftab entry	 */	l_lifc = &lifc->link;	for(link = *l_lifc; link; link = *l_lifc){		if(link->self == p)			break;		l_lifc = &link->lifclink;	}	if(link == nil)		goto out;	/*	 *  walk down the links from the selftab looking for	 *  the one we just found	 */	l_self = &p->link;	for(link = *l_self; link; link = *l_self){		if(link == *(l_lifc))			break;		l_self = &link->selflink;	}	if(link == nil)		panic("remselfcache");	if(--(link->ref) != 0)		goto out;	if((p->type & Rmulti) && ifc->m->remmulti != nil)		(*ifc->m->remmulti)(ifc, a, lifc->local);	/* ref == 0, remove from both chains and free the link */	*l_lifc = link->lifclink;	*l_self = link->selflink;	iplinkfree(link);	if(p->link != nil)		goto out;	/* remove from routing table */	if(isv4(a))		v4delroute(f, a+IPv4off, IPallbits+IPv4off, 1);	else		v6delroute(f, a, IPallbits, 1);	/* no more links, remove from hash and free */	*l = p->next;	ipselffree(p);	/* if IPnoaddr, forget */	if(ipcmp(a, v4prefix) == 0 || ipcmp(a, IPnoaddr) == 0)		f->self->acceptall = 0;out:	qunlock(f->self);}static char *stformat = "%-44.44I %2.2d %4.4s\n";enum{	Nstformat= 41,};longipselftabread(Fs *f, char *cp, ulong offset, int n){	int i, m, nifc, off;	Ipself *p;	Iplink *link;	char state[8];	m = 0;	off = offset;	qlock(f->self);	for(i = 0; i < NHASH && m < n; i++){		for(p = f->self->hash[i]; p != nil && m < n; p = p->next){			nifc = 0;			for(link = p->link; link; link = link->selflink)				nifc++;			routetype(p->type, state);			m += snprint(cp + m, n - m, stformat, p->a, nifc, state);			if(off > 0){				off -= m;				m = 0;			}		}	}	qunlock(f->self);	return m;}intiptentative(Fs *f, uchar *addr){ 	Ipself *p;	p = f->self->hash[hashipa(addr)];	for(; p; p = p->next){		if(ipcmp(addr, p->a) == 0) {			return p->link->lifc->tentative;		}	}	return 0;}/* *  returns *	0		- no match *	Runi *	Rbcast *	Rmcast */intipforme(Fs *f, uchar *addr){	Ipself *p;	p = f->self->hash[hashipa(addr)];	for(; p; p = p->next){		if(ipcmp(addr, p->a) == 0)			return p->type;	}	/* hack to say accept anything */	if(f->self->acceptall)		return Runi;	return 0;}/* *  find the ifc on same net as the remote system.  If none, *  return nil. */Ipifc*findipifc(Fs *f, uchar *remote, int type){	Ipifc *ifc, *x;	Iplifc *lifc;	Conv **cp, **e;	uchar gnet[IPaddrlen];	uchar xmask[IPaddrlen];

⌨️ 快捷键说明

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