From 778d7cd9e7bf6b31ce697f47cbe935e33a63a5b4 Mon Sep 17 00:00:00 2001 From: bradh352 Date: Tue, 19 Oct 2021 13:06:07 -0400 Subject: [PATCH] use helper function for addrinfo to simplify code --- src/lib/ares__addrinfo_localhost.c | 21 ++++---- src/lib/ares__parse_into_addrinfo.c | 56 +++----------------- src/lib/ares__readaddrinfo.c | 68 +++++++++--------------- src/lib/ares_getaddrinfo.c | 81 ++++++++++------------------- src/lib/ares_parse_a_reply.c | 2 +- src/lib/ares_parse_aaaa_reply.c | 2 +- src/lib/ares_private.h | 5 ++ test/ares-test.cc | 7 ++- test/ares-test.h | 1 + 9 files changed, 82 insertions(+), 161 deletions(-) diff --git a/src/lib/ares__addrinfo_localhost.c b/src/lib/ares__addrinfo_localhost.c index df480c2a..057018b9 100644 --- a/src/lib/ares__addrinfo_localhost.c +++ b/src/lib/ares__addrinfo_localhost.c @@ -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); } diff --git a/src/lib/ares__parse_into_addrinfo.c b/src/lib/ares__parse_into_addrinfo.c index 1d577893..e0463933 100644 --- a/src/lib/ares__parse_into_addrinfo.c +++ b/src/lib/ares__parse_into_addrinfo.c @@ -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) diff --git a/src/lib/ares__readaddrinfo.c b/src/lib/ares__readaddrinfo.c index 7d809101..673de877 100644 --- a/src/lib/ares__readaddrinfo.c +++ b/src/lib/ares__readaddrinfo.c @@ -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; } diff --git a/src/lib/ares_getaddrinfo.c b/src/lib/ares_getaddrinfo.c index a7a6c1eb..c9912fab 100644 --- a/src/lib/ares_getaddrinfo.c +++ b/src/lib/ares_getaddrinfo.c @@ -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) diff --git a/src/lib/ares_parse_a_reply.c b/src/lib/ares_parse_a_reply.c index 35219777..ee903c75 100644 --- a/src/lib/ares_parse_a_reply.c +++ b/src/lib/ares_parse_a_reply.c @@ -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; diff --git a/src/lib/ares_parse_aaaa_reply.c b/src/lib/ares_parse_aaaa_reply.c index 43c53c95..091065d3 100644 --- a/src/lib/ares_parse_aaaa_reply.c +++ b/src/lib/ares_parse_aaaa_reply.c @@ -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; diff --git a/src/lib/ares_private.h b/src/lib/ares_private.h index 1a1e26ca..3b358ac6 100644 --- a/src/lib/ares_private.h +++ b/src/lib/ares_private.h @@ -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, diff --git a/test/ares-test.cc b/test/ares-test.cc index 32053175..fe1b461e 100644 --- a/test/ares-test.cc +++ b/test/ares-test.cc @@ -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; diff --git a/test/ares-test.h b/test/ares-test.h index c015d906..9337915e 100644 --- a/test/ares-test.h +++ b/test/ares-test.h @@ -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.