Skip to content

Commit

Permalink
fix localhost resolution
Browse files Browse the repository at this point in the history
  • Loading branch information
bradh352 committed Dec 27, 2024
1 parent b494025 commit 9b395f1
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 27 deletions.
49 changes: 29 additions & 20 deletions src/lib/ares_addrinfo_localhost.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,19 @@
# endif
#endif

static ares_bool_t ares_ai_has_family(int aftype,
const struct ares_addrinfo_node *nodes)
{
const struct ares_addrinfo_node *node;

for (node = nodes; node != NULL; node = node->ai_next) {
if (node->ai_family == aftype)
return ARES_TRUE;
}

return ARES_FALSE;
}

ares_status_t ares_append_ai_node(int aftype, unsigned short port,
unsigned int ttl, const void *adata,
struct ares_addrinfo_node **nodes)
Expand Down Expand Up @@ -107,7 +120,8 @@ static ares_status_t
{
ares_status_t status = ARES_SUCCESS;

if (aftype == AF_UNSPEC || aftype == AF_INET6) {
if ((aftype == AF_UNSPEC || aftype == AF_INET6) &&
!ares_ai_has_family(AF_INET6, *nodes)) {
struct ares_in6_addr addr6;
ares_inet_pton(AF_INET6, "::1", &addr6);
status = ares_append_ai_node(AF_INET6, port, 0, &addr6, nodes);
Expand All @@ -116,7 +130,8 @@ static ares_status_t
}
}

if (aftype == AF_UNSPEC || aftype == AF_INET) {
if ((aftype == AF_UNSPEC || aftype == AF_INET) &&
!ares_ai_has_family(AF_INET, *nodes)) {
struct in_addr addr4;
ares_inet_pton(AF_INET, "127.0.0.1", &addr4);
status = ares_append_ai_node(AF_INET, port, 0, &addr4, nodes);
Expand Down Expand Up @@ -150,11 +165,13 @@ static ares_status_t
continue;
}

if (table->Table[i].Address.si_family == AF_INET) {
if (table->Table[i].Address.si_family == AF_INET &&
!ares_ai_has_family(AF_INET, *nodes)) {
status =
ares_append_ai_node(table->Table[i].Address.si_family, port, 0,
&table->Table[i].Address.Ipv4.sin_addr, nodes);
} else if (table->Table[i].Address.si_family == AF_INET6) {
} else if (table->Table[i].Address.si_family == AF_INET6 &&
!ares_ai_has_family(AF_INET6, *nodes)) {
status =
ares_append_ai_node(table->Table[i].Address.si_family, port, 0,
&table->Table[i].Address.Ipv6.sin6_addr, nodes);
Expand Down Expand Up @@ -195,8 +212,7 @@ ares_status_t ares_addrinfo_localhost(const char *name, unsigned short port,
const struct ares_addrinfo_hints *hints,
struct ares_addrinfo *ai)
{
struct ares_addrinfo_node *nodes = NULL;
ares_status_t status;
ares_status_t status;

/* Validate family */
switch (hints->ai_family) {
Expand All @@ -210,24 +226,17 @@ ares_status_t ares_addrinfo_localhost(const char *name, unsigned short port,

ai->name = ares_strdup(name);
if (!ai->name) {
goto enomem; /* LCOV_EXCL_LINE: OutOfMemory */
status = ARES_ENOMEM;
goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}

status = ares_system_loopback_addrs(hints->ai_family, port, &nodes);

if (status == ARES_ENOTFOUND) {
status = ares_default_loopback_addrs(hints->ai_family, port, &nodes);
status = ares_system_loopback_addrs(hints->ai_family, port, &ai->nodes);
if (status != ARES_SUCCESS && status != ARES_ENOTFOUND) {
goto done;
}

ares_addrinfo_cat_nodes(&ai->nodes, nodes);
status = ares_default_loopback_addrs(hints->ai_family, port, &ai->nodes);

done:
return status;

/* LCOV_EXCL_START: OutOfMemory */
enomem:
ares_freeaddrinfo_nodes(nodes);
ares_free(ai->name);
ai->name = NULL;
return ARES_ENOMEM;
/* LCOV_EXCL_STOP */
}
10 changes: 7 additions & 3 deletions src/lib/ares_getaddrinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -418,9 +418,13 @@ static ares_status_t file_lookup(struct host_query *hquery)
* 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(hquery->name)) {
* as permissions errors reading /etc/hosts or a malformed /etc/hosts.
*
* Also, just because the query itself returned success from /etc/hosts
* lookup doesn't mean it returned everything it needed to for all requested
* address families. As long as we're not on a critical out of memory
* condition pass it through to fill in any other address classes. */
if (status != ARES_ENOMEM && ares_is_localhost(hquery->name)) {
return ares_addrinfo_localhost(hquery->name, hquery->port, &hquery->hints,
hquery->ai);
}
Expand Down
10 changes: 7 additions & 3 deletions src/lib/ares_gethostbyname.c
Original file line number Diff line number Diff line change
Expand Up @@ -307,9 +307,13 @@ static ares_status_t ares_gethostbyname_file_int(ares_channel_t *channel,
* 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)) {
* as permissions errors reading /etc/hosts or a malformed /etc/hosts.
*
* Also, just because the query itself returned success from /etc/hosts
* lookup doesn't mean it returned everything it needed to for all requested
* address families. As long as we're not on a critical out of memory
* condition pass it through to fill in any other address classes. */
if (status != ARES_ENOMEM && ares_is_localhost(name)) {
return ares_hostent_localhost(name, family, host);
}

Expand Down
7 changes: 6 additions & 1 deletion src/lib/ares_hosts_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -845,7 +845,7 @@ ares_status_t ares_hosts_entry_to_addrinfo(const ares_hosts_entry_t *entry,
ares_bool_t want_cnames,
struct ares_addrinfo *ai)
{
ares_status_t status;
ares_status_t status = ARES_ENOTFOUND;
struct ares_addrinfo_cname *cnames = NULL;
struct ares_addrinfo_node *ainodes = NULL;
ares_llist_node_t *node;
Expand Down Expand Up @@ -888,6 +888,11 @@ ares_status_t ares_hosts_entry_to_addrinfo(const ares_hosts_entry_t *entry,
}
}

/* Might be ARES_ENOTFOUND here if no ips matched requested address family */
if (status != ARES_SUCCESS) {
goto done;
}

if (want_cnames) {
status = ares_hosts_ai_append_cnames(entry, &cnames);
if (status != ARES_SUCCESS) {
Expand Down

0 comments on commit 9b395f1

Please sign in to comment.