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

📄 ipifc.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
	x = nil; memset(xmask, 0, IPaddrlen);	/* find most specific match */	e = &f->ipifc->conv[f->ipifc->nc];	for(cp = f->ipifc->conv; cp < e; cp++){		if(*cp == 0)			continue;		ifc = (Ipifc*)(*cp)->ptcl;		for(lifc = ifc->lifc; lifc; lifc = lifc->next){			maskip(remote, lifc->mask, gnet);			if(ipcmp(gnet, lifc->net) == 0){				if(x == nil || ipcmp(lifc->mask, xmask) > 0){					x = ifc;					ipmove(xmask, lifc->mask);				}			}		}	}	if(x != nil)		return x;	/* for now for broadcast and multicast, just use first interface */	if(type & (Rbcast|Rmulti)){		for(cp = f->ipifc->conv; cp < e; cp++){			if(*cp == 0)				continue;			ifc = (Ipifc*)(*cp)->ptcl;			if(ifc->lifc != nil)				return ifc;		}	}	return nil;}enum {	unknownv6,	multicastv6,	unspecifiedv6,	linklocalv6,	sitelocalv6,	globalv6,};intv6addrtype(uchar *addr){	if(isv6global(addr))		return globalv6;	if(islinklocal(addr))		return linklocalv6;	if(isv6mcast(addr))		return multicastv6;	if(issitelocal(addr))		return sitelocalv6;	return unknownv6;}#define v6addrcurr(lifc) (( (lifc)->origint + (lifc)->preflt >= (NOW/10^3) ) || ( (lifc)->preflt == 0xffffffff ))static voidfindprimaryipv6(Fs *f, uchar *local){	Conv **cp, **e;	Ipifc *ifc;	Iplifc *lifc;	int atype, atypel;	ipmove(local, v6Unspecified);	atype = unspecifiedv6;	/* find "best" (global > sitelocal > link local > unspecified)	 * local address; address must be current */	e = &f->ipifc->conv[f->ipifc->nc];	for(cp = f->ipifc->conv; cp < e; cp++){		if(*cp == 0)			continue;		ifc = (Ipifc*)(*cp)->ptcl;		for(lifc = ifc->lifc; lifc; lifc = lifc->next){			atypel = v6addrtype(lifc->local);			if(atypel > atype)			if(v6addrcurr(lifc)) {				ipmove(local, lifc->local);				atype = atypel;				if(atype == globalv6)					return;			}		}	}}/* *  returns first ip address configured */static voidfindprimaryipv4(Fs *f, uchar *local){	Conv **cp, **e;	Ipifc *ifc;	Iplifc *lifc;	/* find first ifc local address */	e = &f->ipifc->conv[f->ipifc->nc];	for(cp = f->ipifc->conv; cp < e; cp++){		if(*cp == 0)			continue;		ifc = (Ipifc*)(*cp)->ptcl;		if((lifc = ifc->lifc) != nil){			ipmove(local, lifc->local);			return;		}	}}/* *  find the local address 'closest' to the remote system, copy it to *  local and return the ifc for that address */voidfindlocalip(Fs *f, uchar *local, uchar *remote){	Ipifc *ifc;	Iplifc *lifc;	Route *r;	uchar gate[IPaddrlen];	uchar gnet[IPaddrlen];	int version;	int atype = unspecifiedv6, atypel = unknownv6;	USED(atype);	USED(atypel);	qlock(f->ipifc);	r = v6lookup(f, remote, nil); 	version = (memcmp(remote, v4prefix, IPv4off) == 0) ? V4 : V6;	if(r != nil){		ifc = r->ifc;		if(r->type & Rv4)			v4tov6(gate, r->v4.gate);		else {			ipmove(gate, r->v6.gate);			ipmove(local, v6Unspecified);		}		/* find ifc address closest to the gateway to use */		switch(version) {		case V4:			for(lifc = ifc->lifc; lifc; lifc = lifc->next){				maskip(gate, lifc->mask, gnet);				if(ipcmp(gnet, lifc->net) == 0){					ipmove(local, lifc->local);					goto out;				}			}			break;		case V6:			for(lifc = ifc->lifc; lifc; lifc = lifc->next){				atypel = v6addrtype(lifc->local);				maskip(gate, lifc->mask, gnet);				if(ipcmp(gnet, lifc->net) == 0)				if(atypel > atype)				if(v6addrcurr(lifc)) {					ipmove(local, lifc->local);					atype = atypel;					if(atype == globalv6)						break;				}			}			if(atype > unspecifiedv6)				goto out;			break;		default:			panic("findlocalip: version %d", version);		}	}	switch(version){	case V4:		findprimaryipv4(f, local);		break;	case V6:		findprimaryipv6(f, local);		break;	default:		panic("findlocalip2: version %d", version);	}out:	qunlock(f->ipifc);}/* *  return first v4 address associated with an interface */intipv4local(Ipifc *ifc, uchar *addr){	Iplifc *lifc;	for(lifc = ifc->lifc; lifc; lifc = lifc->next){		if(isv4(lifc->local)){			memmove(addr, lifc->local+IPv4off, IPv4addrlen);			return 1;		}	}	return 0;}/* *  return first v6 address associated with an interface */intipv6local(Ipifc *ifc, uchar *addr){	Iplifc *lifc;	for(lifc = ifc->lifc; lifc; lifc = lifc->next){		if(!isv4(lifc->local) && !(lifc->tentative)){			ipmove(addr, lifc->local);			return 1;		}	}	return 0;}intipv6anylocal(Ipifc *ifc, uchar *addr){	Iplifc *lifc;	for(lifc = ifc->lifc; lifc; lifc = lifc->next){		if(!isv4(lifc->local)){			ipmove(addr, lifc->local);			return SRC_UNI;		}	}	return SRC_UNSPEC;}/* *  see if this address is bound to the interface */Iplifc*iplocalonifc(Ipifc *ifc, uchar *ip){	Iplifc *lifc;	for(lifc = ifc->lifc; lifc; lifc = lifc->next)		if(ipcmp(ip, lifc->local) == 0)			return lifc;	return nil;}/* *  See if we're proxying for this address on this interface */intipproxyifc(Fs *f, Ipifc *ifc, uchar *ip){	Route *r;	uchar net[IPaddrlen];	Iplifc *lifc;	/* see if this is a direct connected pt to pt address */	r = v6lookup(f, ip, nil);	if(r == nil)		return 0;	if((r->type & (Rifc|Rproxy)) != (Rifc|Rproxy))		return 0;	/* see if this is on the right interface */	for(lifc = ifc->lifc; lifc; lifc = lifc->next){		maskip(ip, lifc->mask, net);		if(ipcmp(net, lifc->remote) == 0)			return 1;	}	return 0;}/* *  return multicast version if any */intipismulticast(uchar *ip){	if(isv4(ip)){		if(ip[IPv4off] >= 0xe0 && ip[IPv4off] < 0xf0)			return V4;	} else {		if(ip[0] == 0xff)			return V6;	}	return 0;}intipisbm(uchar *ip){	if(isv4(ip)){		if(ip[IPv4off] >= 0xe0 && ip[IPv4off] < 0xf0)			return V4;		if(ipcmp(ip, IPv4bcast) == 0)			return V4;	} else {		if(ip[0] == 0xff)			return V6;	}	return 0;}/* *  add a multicast address to an interface, called with c->car locked */voidipifcaddmulti(Conv *c, uchar *ma, uchar *ia){	Ipifc *ifc;	Iplifc *lifc;	Conv **p;	Ipmulti *multi, **l;	Fs *f;	f = c->p->f;	for(l = &c->multi; *l; l = &(*l)->next)		if(ipcmp(ma, (*l)->ma) == 0)		if(ipcmp(ia, (*l)->ia) == 0)			return;		/* it's already there */	multi = *l = smalloc(sizeof(*multi));	ipmove(multi->ma, ma);	ipmove(multi->ia, ia);	multi->next = nil;	for(p = f->ipifc->conv; *p; p++){		if((*p)->inuse == 0)			continue;		ifc = (Ipifc*)(*p)->ptcl;		if(waserror()){			wunlock(ifc);			nexterror();		}		wlock(ifc);		for(lifc = ifc->lifc; lifc; lifc = lifc->next)			if(ipcmp(ia, lifc->local) == 0)				addselfcache(f, ifc, lifc, ma, Rmulti);		wunlock(ifc);		poperror();	}}/* *  remove a multicast address from an interface, called with c->car locked */voidipifcremmulti(Conv *c, uchar *ma, uchar *ia){	Ipmulti *multi, **l;	Iplifc *lifc;	Conv **p;	Ipifc *ifc;	Fs *f;	f = c->p->f;	for(l = &c->multi; *l; l = &(*l)->next)		if(ipcmp(ma, (*l)->ma) == 0)		if(ipcmp(ia, (*l)->ia) == 0)			break;	multi = *l;	if(multi == nil)		return; 	/* we don't have it open */	*l = multi->next;	for(p = f->ipifc->conv; *p; p++){		if((*p)->inuse == 0)			continue;		ifc = (Ipifc*)(*p)->ptcl;		if(waserror()){			wunlock(ifc);			nexterror();		}		wlock(ifc);		for(lifc = ifc->lifc; lifc; lifc = lifc->next)			if(ipcmp(ia, lifc->local) == 0)				remselfcache(f, ifc, lifc, ma);		wunlock(ifc);		poperror();	}	free(multi);}/* *  make lifc's join and leave multicast groups */static char*ipifcjoinmulti(Ipifc *ifc, char **argv, int argc){	USED(ifc, argv, argc);	return nil;}static char*ipifcleavemulti(Ipifc *ifc, char **argv, int argc){	USED(ifc, argv, argc);	return nil;}static voidipifcregisterproxy(Fs *f, Ipifc *ifc, uchar *ip){	Conv **cp, **e;	Ipifc *nifc;	Iplifc *lifc;	Medium *m;	uchar net[IPaddrlen];	/* register the address on any network that will proxy for us */	e = &f->ipifc->conv[f->ipifc->nc];	if(!isv4(ip)) { // V6		for(cp = f->ipifc->conv; cp < e; cp++){			if(*cp == nil)				continue;			nifc = (Ipifc*)(*cp)->ptcl;			if(nifc == ifc)				continue;			rlock(nifc);			m = nifc->m;			if(m == nil || m->addmulti == nil) {				runlock(nifc);				continue;			}			for(lifc = nifc->lifc; lifc; lifc = lifc->next){				maskip(ip, lifc->mask, net);				if(ipcmp(net, lifc->remote) == 0) { /* add solicited-node multicast address */					ipv62smcast(net, ip);					addselfcache(f, nifc, lifc, net, Rmulti);					arpenter(f, V6, ip, nifc->mac, 6, 0);					//(*m->addmulti)(nifc, net, ip);					break;				}			}			runlock(nifc);		}		return;	}	else { // V4		for(cp = f->ipifc->conv; cp < e; cp++){			if(*cp == nil)				continue;			nifc = (Ipifc*)(*cp)->ptcl;			if(nifc == ifc)				continue;			rlock(nifc);			m = nifc->m;			if(m == nil || m->areg == nil){				runlock(nifc);				continue;			}			for(lifc = nifc->lifc; lifc; lifc = lifc->next){				maskip(ip, lifc->mask, net);				if(ipcmp(net, lifc->remote) == 0){					(*m->areg)(nifc, ip);					break;				}			}			runlock(nifc);		}	}}// added for new v6 mesg typesstatic voidadddefroute6(Fs *f, uchar *gate, int force){	Route *r;	r = v6lookup(f, v6Unspecified, nil);	if(r!=nil)	if(!(force) && (strcmp(r->tag,"ra")!=0))	// route entries generated		return;			// by all other means take					// precedence over router annc	v6delroute(f, v6Unspecified, v6Unspecified, 1);	v6addroute(f, "ra", v6Unspecified, v6Unspecified, gate, 0);}enum{	Ngates = 3,};char*ipifcaddpref6(Ipifc *ifc, char**argv, int argc){	uchar	onlink = 1;	uchar	autoflag = 1;	long 	validlt = 0xffffffff;	long 	preflt = 0xffffffff;	long	origint = NOW / 10^3;	uchar	prefix[IPaddrlen];	int	plen = 64;	Iplifc	*lifc;	char	addr[40], preflen[6];	char	*params[3];	switch(argc) {	case 7:		preflt = atoi(argv[6]);		/* fall through */	case 6:		validlt = atoi(argv[5]);		/* fall through */	case 5:		autoflag = atoi(argv[4]);		/* fall through */	case 4:		onlink = atoi(argv[3]);		/* fall through */	case 3:		plen = atoi(argv[2]);	case 2:		break;	default:		return Ebadarg;	}	if((parseip(prefix, argv[1])!=6) ||	 	(validlt < preflt) ||		(plen < 0) || (plen > 64) ||		(islinklocal(prefix))	)		return Ebadarg;	lifc = smalloc(sizeof(Iplifc));	lifc->onlink = (onlink!=0);	lifc->autoflag = (autoflag!=0);	lifc->validlt = validlt;	lifc->preflt = preflt;	lifc->origint = origint;	if(ifc->m->pref2addr!=nil)		ifc->m->pref2addr(prefix, ifc->mac);	else		return Ebadarg;	sprint(addr, "%I", prefix);	sprint(preflen, "/%d", plen);	params[0] = "add";	params[1] = addr;	params[2] = preflen;	return ipifcadd(ifc, params, 3, 0, lifc);}

⌨️ 快捷键说明

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