use helper function for addrinfo to simplify code

pull/431/head
bradh352 3 years ago
parent 43d8946dd1
commit 778d7cd9e7
  1. 21
      src/lib/ares__addrinfo_localhost.c
  2. 56
      src/lib/ares__parse_into_addrinfo.c
  3. 68
      src/lib/ares__readaddrinfo.c
  4. 81
      src/lib/ares_getaddrinfo.c
  5. 2
      src/lib/ares_parse_a_reply.c
  6. 2
      src/lib/ares_parse_aaaa_reply.c
  7. 5
      src/lib/ares_private.h
  8. 7
      test/ares-test.cc
  9. 1
      test/ares-test.h

@ -35,12 +35,11 @@
#include "ares_nowarn.h"
#include "ares_private.h"
static int ares_append_ai_node(int aftype,
unsigned short port,
const void *adata,
struct ares_addrinfo_node **nodes)
int ares_append_ai_node(int aftype,
unsigned short port,
int ttl,
const void *adata,
struct ares_addrinfo_node **nodes)
{
struct ares_addrinfo_node *node;
@ -69,6 +68,7 @@ static int ares_append_ai_node(int aftype,
node->ai_family = AF_INET;
node->ai_addrlen = sizeof(struct sockaddr_in);
node->ai_addr = (struct sockaddr *)sin;
node->ai_ttl = ttl;
}
if (aftype == AF_INET6)
@ -88,6 +88,7 @@ static int ares_append_ai_node(int aftype,
node->ai_family = AF_INET6;
node->ai_addrlen = sizeof(struct ares_in6_addr);
node->ai_addr = (struct sockaddr *)sin6;
node->ai_ttl = ttl;
}
return ARES_SUCCESS;
@ -104,7 +105,7 @@ static int ares__default_loopback_addrs(int aftype,
{
struct ares_in6_addr addr6;
ares_inet_pton(AF_INET6, "::1", &addr6);
status = ares_append_ai_node(AF_INET6, port, &addr6, nodes);
status = ares_append_ai_node(AF_INET6, port, 0, &addr6, nodes);
if (status != ARES_SUCCESS)
{
return status;
@ -115,7 +116,7 @@ static int ares__default_loopback_addrs(int aftype,
{
struct in_addr addr4;
ares_inet_pton(AF_INET, "127.0.0.1", &addr4);
status = ares_append_ai_node(AF_INET, port, &addr4, nodes);
status = ares_append_ai_node(AF_INET, port, 0, &addr4, nodes);
if (status != ARES_SUCCESS)
{
return status;
@ -150,13 +151,13 @@ static int ares__system_loopback_addrs(int aftype,
if (table->Table[i].Address.si_family == AF_INET)
{
status = ares_append_ai_node(table->Table[i].Address.si_family, port,
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)
{
status = ares_append_ai_node(table->Table[i].Address.si_family, port,
status = ares_append_ai_node(table->Table[i].Address.si_family, port, 0,
&table->Table[i].Address.Ipv6.sin6_addr,
nodes);
}

@ -41,6 +41,7 @@
int ares__parse_into_addrinfo(const unsigned char *abuf,
int alen, int cname_only_is_enodata,
unsigned short port,
struct ares_addrinfo *ai)
{
unsigned int qdcount, ancount;
@ -120,30 +121,9 @@ int ares__parse_into_addrinfo(const unsigned char *abuf,
goto failed_stat;
} /* LCOV_EXCL_STOP */
node = ares__append_addrinfo_node(&nodes);
if (!node)
{
status = ARES_ENOMEM;
goto failed_stat;
}
sin = ares_malloc(sizeof(struct sockaddr_in));
if (!sin)
{
status = ARES_ENOMEM;
goto failed_stat;
}
memset(sin, 0, sizeof(struct sockaddr_in));
memcpy(&sin->sin_addr.s_addr, aptr, sizeof(struct in_addr));
sin->sin_family = AF_INET;
node->ai_addr = (struct sockaddr *)sin;
node->ai_family = AF_INET;
node->ai_addrlen = sizeof(struct sockaddr_in);
node->ai_ttl = rr_ttl;
status = ARES_SUCCESS;
status = ares_append_ai_node(AF_INET, port, rr_ttl, aptr, &nodes);
if (status != ARES_SUCCESS)
goto failed_stat;
}
else if (rr_class == C_IN && rr_type == T_AAAA
&& rr_len == sizeof(struct ares_in6_addr)
@ -156,31 +136,9 @@ int ares__parse_into_addrinfo(const unsigned char *abuf,
goto failed_stat;
} /* LCOV_EXCL_STOP */
node = ares__append_addrinfo_node(&nodes);
if (!node)
{
status = ARES_ENOMEM;
goto failed_stat;
}
sin6 = ares_malloc(sizeof(struct sockaddr_in6));
if (!sin6)
{
status = ARES_ENOMEM;
goto failed_stat;
}
memset(sin6, 0, sizeof(struct sockaddr_in6));
memcpy(&sin6->sin6_addr.s6_addr, aptr, sizeof(struct ares_in6_addr));
sin6->sin6_family = AF_INET6;
node->ai_addr = (struct sockaddr *)sin6;
node->ai_family = AF_INET6;
node->ai_addrlen = sizeof(struct sockaddr_in6);
node->ai_ttl = rr_ttl;
status = ARES_SUCCESS;
status = ares_append_ai_node(AF_INET6, port, rr_ttl, aptr, &nodes);
if (status != ARES_SUCCESS)
goto failed_stat;
}
if (rr_class == C_IN && rr_type == T_CNAME)

@ -42,11 +42,10 @@ int ares__readaddrinfo(FILE *fp,
char *txtaddr, *txthost, *txtalias;
char *aliases[MAX_ALIASES];
unsigned int i, alias_count;
int status;
int status = ARES_SUCCESS;
size_t linesize;
ares_sockaddr addr;
struct ares_addrinfo_cname *cname = NULL, *cnames = NULL;
struct ares_addrinfo_node *node = NULL, *nodes = NULL;
struct ares_addrinfo_node *nodes = NULL;
int match_with_alias, match_with_canonical;
int want_cname = hints->ai_flags & ARES_AI_CANONNAME;
@ -63,7 +62,8 @@ int ares__readaddrinfo(FILE *fp,
ai->name = ares_strdup(name);
if(!ai->name)
{
goto enomem;
status = ARES_ENOMEM;
goto fail;
}
while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
@ -168,57 +168,36 @@ int ares__readaddrinfo(FILE *fp,
continue;
}
/* Zero-out 'addr' struct, as there are members that we may not set, especially
* for ipv6. We don't want garbage data */
memset(&addr, 0, sizeof(addr));
/*
* Convert address string to network address for the requested families.
* Actual address family possible values are AF_INET and AF_INET6 only.
*/
if ((hints->ai_family == AF_INET) || (hints->ai_family == AF_UNSPEC))
{
addr.sa4.sin_port = htons(port);
if (ares_inet_pton(AF_INET, txtaddr, &addr.sa4.sin_addr) > 0)
struct in_addr addr4;
if (ares_inet_pton(AF_INET, txtaddr, &addr4) == 1)
{
node = ares__append_addrinfo_node(&nodes);
if(!node)
status = ares_append_ai_node(AF_INET, port, 0, &addr4, &nodes);
if (status != ARES_SUCCESS)
{
goto enomem;
goto fail;
}
node->ai_family = addr.sa.sa_family = AF_INET;
node->ai_addrlen = sizeof(addr.sa4);
node->ai_addr = ares_malloc(sizeof(addr.sa4));
if (!node->ai_addr)
{
goto enomem;
}
memcpy(node->ai_addr, &addr.sa4, sizeof(addr.sa4));
}
}
if ((hints->ai_family == AF_INET6) || (hints->ai_family == AF_UNSPEC))
{
addr.sa6.sin6_port = htons(port);
if (ares_inet_pton(AF_INET6, txtaddr, &addr.sa6.sin6_addr) > 0)
struct ares_in6_addr addr6;
if (ares_inet_pton(AF_INET6, txtaddr, &addr6) == 1)
{
node = ares__append_addrinfo_node(&nodes);
if (!node)
status = ares_append_ai_node(AF_INET6, port, 0, &addr6, &nodes);
if (status != ARES_SUCCESS)
{
goto enomem;
goto fail;
}
node->ai_family = addr.sa.sa_family = AF_INET6;
node->ai_addrlen = sizeof(addr.sa6);
node->ai_addr = ares_malloc(sizeof(addr.sa6));
if (!node->ai_addr)
{
goto enomem;
}
memcpy(node->ai_addr, &addr.sa6, sizeof(addr.sa6));
}
}
if (!node)
if (status != ARES_SUCCESS)
/* Ignore line if invalid address string for the requested family. */
continue;
@ -229,7 +208,8 @@ int ares__readaddrinfo(FILE *fp,
cname = ares__append_addrinfo_cname(&cnames);
if (!cname)
{
goto enomem;
status = ARES_ENOMEM;
goto fail;
}
cname->alias = ares_strdup(aliases[i]);
cname->name = ares_strdup(txthost);
@ -240,7 +220,8 @@ int ares__readaddrinfo(FILE *fp,
cname = ares__append_addrinfo_cname(&cnames);
if (!cname)
{
goto enomem;
status = ARES_ENOMEM;
goto fail;
}
cname->name = ares_strdup(txthost);
}
@ -250,22 +231,21 @@ int ares__readaddrinfo(FILE *fp,
/* Last read failed. */
if (status == ARES_ENOMEM)
{
goto enomem;
goto fail;
}
/* Free line buffer. */
ares_free(line);
ares__addrinfo_cat_cnames(&ai->cnames, cnames);
ares__addrinfo_cat_nodes(&ai->nodes, nodes);
return node ? ARES_SUCCESS : ARES_ENOTFOUND;
return nodes ? ARES_SUCCESS : ARES_ENOTFOUND;
enomem:
fail:
ares_free(line);
ares__freeaddrinfo_cnames(cnames);
ares__freeaddrinfo_nodes(nodes);
ares_free(ai->name);
ai->name = NULL;
return ARES_ENOMEM;
return status;
}

@ -284,9 +284,7 @@ static int fake_addrinfo(const char *name,
void *arg)
{
struct ares_addrinfo_cname *cname;
struct ares_addrinfo_node *node;
ares_sockaddr addr;
size_t addrlen;
int status = ARES_SUCCESS;
int result = 0;
int family = hints->ai_family;
if (family == AF_INET || family == AF_INET6 || family == AF_UNSPEC)
@ -307,62 +305,45 @@ static int fake_addrinfo(const char *name,
}
}
memset(&addr, 0, sizeof(addr));
/* if we don't have 3 dots, it is illegal
* (although inet_pton doesn't think so).
*/
if (numdots != 3 || !valid)
result = 0;
else
result =
(ares_inet_pton(AF_INET, name, &addr.sa4.sin_addr) < 1 ? 0 : 1);
if (result)
{
family = addr.sa.sa_family = AF_INET;
addr.sa4.sin_port = htons(port);
addrlen = sizeof(addr.sa4);
struct in_addr addr4;
result = ares_inet_pton(AF_INET, name, &addr4) < 1 ? 0 : 1;
if (result)
{
status = ares_append_ai_node(AF_INET, port, 0, &addr4, &ai->nodes);
if (status != ARES_SUCCESS)
{
callback(arg, status, 0, NULL);
return 1;
}
}
}
}
if (family == AF_INET6 || family == AF_UNSPEC)
{
result =
(ares_inet_pton(AF_INET6, name, &addr.sa6.sin6_addr) < 1 ? 0 : 1);
addr.sa6.sin6_family = AF_INET6;
addr.sa6.sin6_port = htons(port);
addrlen = sizeof(addr.sa6);
struct ares_in6_addr addr6;
result = ares_inet_pton(AF_INET6, name, &addr6) < 1 ? 0 : 1;
if (result)
{
status = ares_append_ai_node(AF_INET6, port, 0, &addr6, &ai->nodes);
if (status != ARES_SUCCESS)
{
callback(arg, status, 0, NULL);
return 1;
}
}
}
if (!result)
return 0;
node = ares__malloc_addrinfo_node();
if (!node)
{
ares_freeaddrinfo(ai);
callback(arg, ARES_ENOMEM, 0, NULL);
return 1;
}
ai->nodes = node;
node->ai_addr = ares_malloc(addrlen);
if (!node->ai_addr)
{
ares_freeaddrinfo(ai);
callback(arg, ARES_ENOMEM, 0, NULL);
return 1;
}
node->ai_addrlen = (unsigned int)addrlen;
node->ai_family = addr.sa.sa_family;
if (addr.sa.sa_family == AF_INET)
memcpy(node->ai_addr, &addr.sa4, sizeof(addr.sa4));
else
memcpy(node->ai_addr, &addr.sa6, sizeof(addr.sa6));
if (hints->ai_flags & ARES_AI_CANONNAME)
{
cname = ares__append_addrinfo_cname(&ai->cnames);
@ -383,8 +364,8 @@ static int fake_addrinfo(const char *name,
}
}
node->ai_socktype = hints->ai_socktype;
node->ai_protocol = hints->ai_protocol;
ai->nodes->ai_socktype = hints->ai_socktype;
ai->nodes->ai_protocol = hints->ai_protocol;
callback(arg, ARES_SUCCESS, 0, ai);
return 1;
@ -403,19 +384,11 @@ static void end_hquery(struct host_query *hquery, int status)
hquery->ai->nodes = sentinel.ai_next;
}
next = hquery->ai->nodes;
/* Set port into each address (resolved separately). */
while (next)
{
next->ai_socktype = hquery->hints.ai_socktype;
next->ai_protocol = hquery->hints.ai_protocol;
if (next->ai_family == AF_INET)
{
(CARES_INADDR_CAST(struct sockaddr_in *, next->ai_addr))->sin_port = htons(hquery->port);
}
else
{
(CARES_INADDR_CAST(struct sockaddr_in6 *, next->ai_addr))->sin6_port = htons(hquery->port);
}
next = next->ai_next;
}
}
@ -562,7 +535,7 @@ static void host_callback(void *arg, int status, int timeouts,
if (status == ARES_SUCCESS)
{
addinfostatus = ares__parse_into_addrinfo(abuf, alen, 1, hquery->ai);
addinfostatus = ares__parse_into_addrinfo(abuf, alen, 1, hquery->port, hquery->ai);
}
if (!hquery->remaining)

@ -58,7 +58,7 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen,
memset(&ai, 0, sizeof(ai));
status = ares__parse_into_addrinfo(abuf, alen, 0, &ai);
status = ares__parse_into_addrinfo(abuf, alen, 0, 0, &ai);
if (status != ARES_SUCCESS && status != ARES_ENODATA)
{
goto fail;

@ -60,7 +60,7 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen,
memset(&ai, 0, sizeof(ai));
status = ares__parse_into_addrinfo(abuf, alen, 0, &ai);
status = ares__parse_into_addrinfo(abuf, alen, 0, 0, &ai);
if (status != ARES_SUCCESS && status != ARES_ENODATA)
{
goto fail;

@ -387,11 +387,16 @@ void ares__freeaddrinfo_cnames(struct ares_addrinfo_cname *ai_cname);
struct ares_addrinfo_cname *ares__append_addrinfo_cname(struct ares_addrinfo_cname **ai_cname);
int ares_append_ai_node(int aftype, unsigned short port, int ttl,
const void *adata,
struct ares_addrinfo_node **nodes);
void ares__addrinfo_cat_cnames(struct ares_addrinfo_cname **head,
struct ares_addrinfo_cname *tail);
int ares__parse_into_addrinfo(const unsigned char *abuf,
int alen, int cname_only_is_enodata,
unsigned short port,
struct ares_addrinfo *ai);
int ares__addrinfo2hostent(const struct ares_addrinfo *ai, int family,

@ -564,11 +564,13 @@ std::ostream& operator<<(std::ostream& os, const HostResult& result) {
return os;
}
HostEnt::HostEnt(const struct hostent *hostent) : addrtype_(-1), name_("") {
HostEnt::HostEnt(const struct hostent *hostent) : addrtype_(-1) {
if (!hostent)
return;
if (hostent->h_name)
name_ = hostent->h_name;
if (hostent->h_aliases) {
char** palias = hostent->h_aliases;
while (*palias != nullptr) {
@ -576,7 +578,9 @@ HostEnt::HostEnt(const struct hostent *hostent) : addrtype_(-1), name_("") {
palias++;
}
}
addrtype_ = hostent->h_addrtype;
if (hostent->h_addr_list) {
char** paddr = hostent->h_addr_list;
while (*paddr != nullptr) {
@ -616,7 +620,6 @@ void HostCallback(void *data, int status, int timeouts,
result->done_ = true;
result->status_ = status;
result->timeouts_ = timeouts;
result->host_ = nullptr;
if (hostent)
result->host_ = HostEnt(hostent);
if (verbose) std::cerr << "HostCallback(" << *result << ")" << std::endl;

@ -247,6 +247,7 @@ std::ostream& operator<<(std::ostream& os, const HostEnt& result);
// Structure that describes the result of an ares_host_callback invocation.
struct HostResult {
HostResult() : done_(false), status_(0), timeouts_(0) {}
// Whether the callback has been invoked.
bool done_;
// Explicitly provided result information.

Loading…
Cancel
Save