diff options
| -rw-r--r-- | src/network/lookup_name.c | 47 | 
1 files changed, 32 insertions, 15 deletions
diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c index a1851f1f..0e6db9ef 100644 --- a/src/network/lookup_name.c +++ b/src/network/lookup_name.c @@ -355,36 +355,53 @@ int __lookup_name(struct address buf[static MAXADDRS], char canon[static 256], c  	 * excessive runtime and code size cost and dubious benefit.  	 * So far the label/precedence table cannot be customized. */  	for (i=0; i<cnt; i++) { +		int family = buf[i].family;  		int key = 0; -		struct sockaddr_in6 sa, da = { +		struct sockaddr_in6 sa6 = { 0 }, da6 = {  			.sin6_family = AF_INET6,  			.sin6_scope_id = buf[i].scopeid,  			.sin6_port = 65535  		}; -		if (buf[i].family == AF_INET6) { -			memcpy(da.sin6_addr.s6_addr, buf[i].addr, 16); +		struct sockaddr_in sa4 = { 0 }, da4 = { +			.sin_family = AF_INET, +			.sin_port = 65535 +		}; +		void *sa, *da; +		socklen_t salen, dalen; +		if (family == AF_INET6) { +			memcpy(da6.sin6_addr.s6_addr, buf[i].addr, 16); +			da = &da6; dalen = sizeof da6; +			sa = &sa6; salen = sizeof sa6;  		} else { -			memcpy(da.sin6_addr.s6_addr, +			memcpy(sa6.sin6_addr.s6_addr, +				"\0\0\0\0\0\0\0\0\0\0\xff\xff", 12); +			memcpy(da6.sin6_addr.s6_addr+12, buf[i].addr, 4); +			memcpy(da6.sin6_addr.s6_addr,  				"\0\0\0\0\0\0\0\0\0\0\xff\xff", 12); -			memcpy(da.sin6_addr.s6_addr+12, buf[i].addr, 4); +			memcpy(da6.sin6_addr.s6_addr+12, buf[i].addr, 4); +			memcpy(&da4.sin_addr, buf[i].addr, 4); +			da = &da4; dalen = sizeof da4; +			sa = &sa4; salen = sizeof sa4;  		} -		const struct policy *dpolicy = policyof(&da.sin6_addr); -		int dscope = scopeof(&da.sin6_addr); +		const struct policy *dpolicy = policyof(&da6.sin6_addr); +		int dscope = scopeof(&da6.sin6_addr);  		int dlabel = dpolicy->label;  		int dprec = dpolicy->prec;  		int prefixlen = 0; -		int fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_UDP); +		int fd = socket(family, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_UDP);  		if (fd >= 0) { -			if (!connect(fd, (void *)&da, sizeof da)) { +			if (!connect(fd, da, dalen)) {  				key |= DAS_USABLE; -				if (!getsockname(fd, (void *)&sa, -				    &(socklen_t){sizeof sa})) { -					if (dscope == scopeof(&sa.sin6_addr)) +				if (!getsockname(fd, sa, &salen)) { +					if (family == AF_INET) memcpy( +						&sa6.sin6_addr.s6_addr+12, +						&sa4.sin_addr, 4); +					if (dscope == scopeof(&sa6.sin6_addr))  						key |= DAS_MATCHINGSCOPE; -					if (dlabel == labelof(&sa.sin6_addr)) +					if (dlabel == labelof(&sa6.sin6_addr))  						key |= DAS_MATCHINGLABEL; -					prefixlen = prefixmatch(&sa.sin6_addr, -						&da.sin6_addr); +					prefixlen = prefixmatch(&sa6.sin6_addr, +						&da6.sin6_addr);  				}  			}  			close(fd);  | 
