fix windows localhost for ares_gethostbyname_file() when /etc/hosts doesn't have an entry

pull/593/head
Brad House 1 year ago
parent 065760bcb9
commit 92caef17b3
  1. 5
      src/lib/ares__hosts_file.c
  2. 6
      src/lib/ares_getaddrinfo.c
  3. 61
      src/lib/ares_gethostbyname.c
  4. 1
      src/lib/ares_private.h

@ -866,6 +866,7 @@ ares_status_t ares__hosts_entry_to_hostent(const ares_hosts_entry_t *entry,
char **temp = NULL;
memset(&addr, 0, sizeof(addr));
addr.family = family;
ptr = ares__parse_ipaddr(ipaddr, &addr, &ptr_len);
if (ptr == NULL)
@ -873,6 +874,10 @@ ares_status_t ares__hosts_entry_to_hostent(const ares_hosts_entry_t *entry,
/* If family == AF_UNSPEC, then we want to inherit this for future
* conversions as we can only support a single address class */
if (family == AF_UNSPEC) {
family = addr.family;
(*hostent)->h_addrtype = addr.family;
}
temp = ares_realloc_zero((*hostent)->h_addr_list,
(idx + 1) * sizeof(*(*hostent)->h_addr_list),

@ -349,7 +349,7 @@ static void end_hquery(struct host_query *hquery, ares_status_t status)
ares_free(hquery);
}
static ares_bool_t is_localhost(const char *name)
ares_bool_t ares__is_localhost(const char *name)
{
/* RFC6761 6.3 says : The domain "localhost." and any names falling within
* ".localhost." */
@ -411,7 +411,7 @@ done:
* We will also ignore ALL errors when trying to resolve localhost, such
* as permissions errors reading /etc/hosts or a malformed /etc/hosts */
if (status != ARES_SUCCESS && status != ARES_ENOMEM &&
is_localhost(hquery->name)) {
ares__is_localhost(hquery->name)) {
return ares__addrinfo_localhost(hquery->name, hquery->port, &hquery->hints,
hquery->ai);
}
@ -427,7 +427,7 @@ static void next_lookup(struct host_query *hquery, ares_status_t status)
* queries for localhost names to their configured caching DNS
* server(s)."
* Otherwise, DNS lookup. */
if (!is_localhost(hquery->name) && next_dns_lookup(hquery)) {
if (!ares__is_localhost(hquery->name) && next_dns_lookup(hquery)) {
break;
}

@ -231,6 +231,37 @@ static size_t get6_address_index(const struct ares_in6_addr *addr,
}
static ares_status_t ares__hostent_localhost(const char *name, int family,
struct hostent **host_out)
{
ares_status_t status;
struct ares_addrinfo *ai = NULL;
struct ares_addrinfo_hints hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = family;
ai = ares_malloc_zero(sizeof(*ai));
if (ai == NULL) {
status = ARES_ENOMEM;
goto done;
}
status = ares__addrinfo_localhost(name, 0, &hints, ai);
if (status != ARES_SUCCESS) {
goto done;
}
status = ares__addrinfo2hostent(ai, family, host_out);
if (status != ARES_SUCCESS) {
goto done;
}
done:
ares_freeaddrinfo(ai);
return status;
}
/* I really have no idea why this is exposed as a public function, but since
* it is, we can't kill this legacy function. */
int ares_gethostbyname_file(ares_channel channel, const char *name, int family,
@ -241,11 +272,12 @@ int ares_gethostbyname_file(ares_channel channel, const char *name, int family,
ares_status_t status;
/* We only take the channel to ensure that ares_init() been called. */
if (channel == NULL) {
if (channel == NULL || name == NULL || host == NULL) {
/* Anything will do, really. This seems fine, and is consistent with
other error cases. */
*host = NULL;
return (int)ARES_ENOTFOUND;
if (host != NULL)
*host = NULL;
return ARES_ENOTFOUND;
}
/* Per RFC 7686, reject queries for ".onion" domain names with NXDOMAIN. */
@ -254,13 +286,26 @@ int ares_gethostbyname_file(ares_channel channel, const char *name, int family,
}
status = ares__hosts_search_host(channel, ARES_FALSE, name, &entry);
if (status != ARES_SUCCESS)
return (int)status;
if (status != ARES_SUCCESS) {
goto done;
}
status = ares__hosts_entry_to_hostent(entry, family, host);
if (status != ARES_SUCCESS)
return (int)status;
if (status != ARES_SUCCESS) {
goto done;
}
done:
/* RFC6761 section 6.3 #3 states that "Name resolution APIs and libraries
* SHOULD recognize localhost names as special and SHOULD always return the
* IP loopback address for address queries".
* We will also ignore ALL errors when trying to resolve localhost, such
* as permissions errors reading /etc/hosts or a malformed /etc/hosts */
if (status != ARES_SUCCESS && status != ARES_ENOMEM &&
ares__is_localhost(name)) {
return (int)ares__hostent_localhost(name, family, host);
}
return (int)ARES_SUCCESS;
return (int)status;
}

@ -413,6 +413,7 @@ ares_status_t ares__sortaddrinfo(ares_channel channel,
struct ares_addrinfo_node *ai_node);
void ares__freeaddrinfo_nodes(struct ares_addrinfo_node *ai_node);
ares_bool_t ares__is_localhost(const char *name);
struct ares_addrinfo_node *
ares__append_addrinfo_node(struct ares_addrinfo_node **ai_node);

Loading…
Cancel
Save