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; char **temp = NULL;
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
addr.family = family; addr.family = family;
ptr = ares__parse_ipaddr(ipaddr, &addr, &ptr_len); ptr = ares__parse_ipaddr(ipaddr, &addr, &ptr_len);
if (ptr == NULL) 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 /* If family == AF_UNSPEC, then we want to inherit this for future
* conversions as we can only support a single address class */ * 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, temp = ares_realloc_zero((*hostent)->h_addr_list,
(idx + 1) * sizeof(*(*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); 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 /* RFC6761 6.3 says : The domain "localhost." and any names falling within
* ".localhost." */ * ".localhost." */
@ -411,7 +411,7 @@ done:
* We will also ignore ALL errors when trying to resolve localhost, such * We will also ignore ALL errors when trying to resolve localhost, such
* as permissions errors reading /etc/hosts or a malformed /etc/hosts */ * as permissions errors reading /etc/hosts or a malformed /etc/hosts */
if (status != ARES_SUCCESS && status != ARES_ENOMEM && 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, return ares__addrinfo_localhost(hquery->name, hquery->port, &hquery->hints,
hquery->ai); 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 * queries for localhost names to their configured caching DNS
* server(s)." * server(s)."
* Otherwise, DNS lookup. */ * Otherwise, DNS lookup. */
if (!is_localhost(hquery->name) && next_dns_lookup(hquery)) { if (!ares__is_localhost(hquery->name) && next_dns_lookup(hquery)) {
break; 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 /* I really have no idea why this is exposed as a public function, but since
* it is, we can't kill this legacy function. */ * it is, we can't kill this legacy function. */
int ares_gethostbyname_file(ares_channel channel, const char *name, int family, 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; ares_status_t status;
/* We only take the channel to ensure that ares_init() been called. */ /* 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 /* Anything will do, really. This seems fine, and is consistent with
other error cases. */ other error cases. */
*host = NULL; if (host != NULL)
return (int)ARES_ENOTFOUND; *host = NULL;
return ARES_ENOTFOUND;
} }
/* Per RFC 7686, reject queries for ".onion" domain names with NXDOMAIN. */ /* 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); status = ares__hosts_search_host(channel, ARES_FALSE, name, &entry);
if (status != ARES_SUCCESS) if (status != ARES_SUCCESS) {
return (int)status; goto done;
}
status = ares__hosts_entry_to_hostent(entry, family, host); status = ares__hosts_entry_to_hostent(entry, family, host);
if (status != ARES_SUCCESS) if (status != ARES_SUCCESS) {
return (int)status; 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); struct ares_addrinfo_node *ai_node);
void ares__freeaddrinfo_nodes(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 * struct ares_addrinfo_node *
ares__append_addrinfo_node(struct ares_addrinfo_node **ai_node); ares__append_addrinfo_node(struct ares_addrinfo_node **ai_node);

Loading…
Cancel
Save