diff options
| -rw-r--r-- | libc/inet/resolv.c | 48 | 
1 files changed, 31 insertions, 17 deletions
| diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c index 1f12be9b9..e38c8bd67 100644 --- a/libc/inet/resolv.c +++ b/libc/inet/resolv.c @@ -1551,7 +1551,7 @@ int attribute_hidden __read_etc_hosts_r(FILE * fp, const char * name, int type,  	struct in_addr **addr_list = NULL;  #ifdef __UCLIBC_HAS_IPV6__  	struct in6_addr *in6 = NULL; -	struct in6_addr **addr_list6 =NULL; +	struct in6_addr **addr_list6 = NULL;  #endif /* __UCLIBC_HAS_IPV6__ */  	char *cp, **alias;  	int aliases, i, ret = HOST_NOT_FOUND; @@ -1613,14 +1613,15 @@ int attribute_hidden __read_etc_hosts_r(FILE * fp, const char * name, int type,  		fp = __open_etc_hosts();  		if (fp == NULL) { -			result = NULL; +			*result = NULL;  			return errno;  		}  	}  	*h_errnop = HOST_NOT_FOUND;  	while (fgets(buf, buflen, fp)) { -		if ((cp = strchr(buf, '#'))) +		cp = strchr(buf, '#'); +		if (cp)  			*cp = '\0';  		DPRINTF("Looking at: %s\n", buf);  		aliases = 0; @@ -1630,7 +1631,7 @@ int attribute_hidden __read_etc_hosts_r(FILE * fp, const char * name, int type,  			while (*cp && isspace(*cp))  				*cp++ = '\0';  			if (!*cp) -				continue; +				break;  			if (aliases < (2+MAX_ALIASES))  				alias[aliases++] = cp;  			while (*cp && !isspace(*cp)) @@ -1644,7 +1645,8 @@ int attribute_hidden __read_etc_hosts_r(FILE * fp, const char * name, int type,  		if (action == GETHOSTENT) {  			/* Return whatever the next entry happens to be. */  			break; -		} else if (action == GET_HOSTS_BYADDR) { +		} +		if (action == GET_HOSTS_BYADDR) {  			if (strcmp(name, alias[0]) != 0)  				continue;  		} else { @@ -1688,13 +1690,12 @@ int attribute_hidden __read_etc_hosts_r(FILE * fp, const char * name, int type,  			 * If looking for an IPv6 addr, don't bail when we got the IPv4  			 */  			DPRINTF("Error: Found host but diff network type\n"); +			/* NB: gethostbyname2_r depends on this feature +			 * to avoid looking for IPv6 addr of "localhost" etc */  			ret = TRY_AGAIN;  			continue;  		} - -		if (action != GETHOSTENT) -			fclose(fp); -		return ret; +		break;  	}  	if (action != GETHOSTENT)  		fclose(fp); @@ -2206,6 +2207,7 @@ int gethostbyname2_r(const char *name, int family,  	int nest = 0;  	int __nameserversXX;  	char ** __nameserverXX; +	int wrong_af = 0;  	if (family == AF_INET)  		return gethostbyname_r(name, result_buf, buf, buflen, result, h_errnop); @@ -2223,11 +2225,15 @@ int gethostbyname2_r(const char *name, int family,  		int old_errno = errno;	/* Save the old errno and reset errno */  		__set_errno(0);			/* to check for missing /etc/hosts. */ -		if ((i = __get_hosts_byname_r(name, family, result_buf, -									  buf, buflen, result, h_errnop)) == 0) +		i = __get_hosts_byname_r(name, family, result_buf, +				buf, buflen, result, h_errnop); +		if (i == NETDB_SUCCESS) { +//FIXME: restore errno?  			return i; +		}  		switch (*h_errnop) {  			case HOST_NOT_FOUND: +				wrong_af = (i == TRY_AGAIN);  			case NO_ADDRESS:  				break;  			case NETDB_INTERNAL: @@ -2274,7 +2280,15 @@ int gethostbyname2_r(const char *name, int family,  		return NETDB_SUCCESS;  	} -	memset((char *) &a, '\0', sizeof(a)); +	/* What if /etc/hosts has it but it's not IPv6? +	 * F.e. "127.0.0.1 localhost". We don't do DNS query for such hosts - +	 * "ping localhost" should be fast even if DNS server is down! */ +	if (wrong_af) { +		*h_errnop = HOST_NOT_FOUND; +		return TRY_AGAIN; +	} + +	memset(&a, '\0', sizeof(a));  	for (;;) {  		__UCLIBC_MUTEX_LOCK(__resolv_lock); @@ -2306,7 +2320,8 @@ int gethostbyname2_r(const char *name, int family,  				return -1;  			}  			continue; -		} else if (a.atype == T_AAAA) {	/* ADDRESS */ +		} +		if (a.atype == T_AAAA) {	/* ADDRESS */  			memcpy(in, a.rdata, sizeof(*in));  			result_buf->h_name = buf;  			result_buf->h_addrtype = AF_INET6; @@ -2314,11 +2329,10 @@ int gethostbyname2_r(const char *name, int family,  			result_buf->h_addr_list = (char **) addr_list;  			free(packet);  			break; -		} else { -			free(packet); -			*h_errnop = HOST_NOT_FOUND; -			return TRY_AGAIN;  		} +		free(packet); +		*h_errnop = HOST_NOT_FOUND; +		return TRY_AGAIN;  	}  	*result = result_buf; | 
