Exemplo n.º 1
0
/*
 *  find the local address 'closest' to the remote system, copy it to
 *  local and return the ifc for that address
 */
void
findlocalip(Fs *f, uint8_t *local, uint8_t *remote)
{
	int version, atype = unspecifiedv6, atypel = unknownv6;
	int atyper, deprecated;
	uint8_t gate[IPaddrlen], gnet[IPaddrlen];
	Ipifc *ifc;
	Iplifc *lifc;
	Route *r;

	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);
		}

		switch(version) {
		case V4:
			/* find ifc address closest to the gateway to use */
			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:
			/* find ifc address with scope matching the destination */
			atyper = v6addrtype(remote);
			deprecated = 0;
			for(lifc = ifc->lifc; lifc; lifc = lifc->next){
				atypel = v6addrtype(lifc->local);
				/* prefer appropriate scope */
				if(atypel > atype && atype < atyper ||
				   atypel < atype && atype > atyper){
					ipmove(local, lifc->local);
					deprecated = !v6addrcurr(lifc);
					atype = atypel;
				} else if(atypel == atype){
					/* avoid deprecated addresses */
					if(deprecated && v6addrcurr(lifc)){
						ipmove(local, lifc->local);
						atype = atypel;
						deprecated = 0;
					}
				}
				if(atype == atyper && !deprecated)
					goto out;
			}
			if(atype >= atyper)
				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);
}
Exemplo n.º 2
0
Arquivo: ipifc.c Projeto: 7perl/akaros
/*
 *  find the local address 'closest' to the remote system, copy it to
 *  local and return the ifc for that address
 */
void findlocalip(struct Fs *f, uint8_t * local, uint8_t * remote)
{
	struct Ipifc *ifc;
	struct Iplifc *lifc;
	struct route *r;
	uint8_t gate[IPaddrlen];
	uint8_t gnet[IPaddrlen];
	int version;
	int atype = unspecifiedv6, atypel = unknownv6;

	qlock(&f->ipifc->qlock);
	r = v6lookup(f, remote, NULL);
	version = isv4(remote) ? V4 : V6;

	if (r != NULL) {
		ifc = r->rt.ifc;
		if (r->rt.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->qlock);
}