aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/c-ares/src/lib/ares_getaddrinfo.c
diff options
context:
space:
mode:
authorrobot-contrib <robot-contrib@yandex-team.com>2024-11-12 04:41:48 +0300
committerrobot-contrib <robot-contrib@yandex-team.com>2024-11-12 04:53:58 +0300
commit18b18c79e00cbe11bf0ec82039f1bddbb2c19681 (patch)
tree1b6cebe27d564b429744a96cb8842e306a5d79d0 /contrib/libs/c-ares/src/lib/ares_getaddrinfo.c
parent9632e4fecfdc42cd6b3cb58f05676e3a5dbcf043 (diff)
downloadydb-18b18c79e00cbe11bf0ec82039f1bddbb2c19681.tar.gz
Update contrib/libs/c-ares to 1.34.3
commit_hash:a4dc6127c1976aed745669af6ede1483b05f9686
Diffstat (limited to 'contrib/libs/c-ares/src/lib/ares_getaddrinfo.c')
-rw-r--r--contrib/libs/c-ares/src/lib/ares_getaddrinfo.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/contrib/libs/c-ares/src/lib/ares_getaddrinfo.c b/contrib/libs/c-ares/src/lib/ares_getaddrinfo.c
index 09d34d3378..32791dc37d 100644
--- a/contrib/libs/c-ares/src/lib/ares_getaddrinfo.c
+++ b/contrib/libs/c-ares/src/lib/ares_getaddrinfo.c
@@ -481,6 +481,18 @@ static void terminate_retries(const struct host_query *hquery,
query->no_retries = ARES_TRUE;
}
+static ares_bool_t ai_has_ipv4(struct ares_addrinfo *ai)
+{
+ struct ares_addrinfo_node *node;
+
+ for (node = ai->nodes; node != NULL; node = node->ai_next) {
+ if (node->ai_family == AF_INET) {
+ return ARES_TRUE;
+ }
+ }
+ return ARES_FALSE;
+}
+
static void host_callback(void *arg, ares_status_t status, size_t timeouts,
const ares_dns_record_t *dnsrec)
{
@@ -496,7 +508,27 @@ static void host_callback(void *arg, ares_status_t status, size_t timeouts,
addinfostatus =
ares_parse_into_addrinfo(dnsrec, ARES_TRUE, hquery->port, hquery->ai);
}
- if (addinfostatus == ARES_SUCCESS) {
+
+ /* We sent out ipv4 and ipv6 requests simultaneously. If we got a
+ * successful ipv4 response, we want to go ahead and tell the ipv6 request
+ * that if it fails or times out to not try again since we have the data
+ * we need.
+ *
+ * Our initial implementation of this would terminate retries if we got any
+ * successful response (ipv4 _or_ ipv6). But we did get some user-reported
+ * issues with this that had bad system configs and odd behavior:
+ * https://github.com/alpinelinux/docker-alpine/issues/366
+ *
+ * Essentially the ipv6 query succeeded but the ipv4 query failed or timed
+ * out, and so we only returned the ipv6 address, but the host couldn't
+ * use ipv6. If we continued to allow ipv4 retries it would have found a
+ * server that worked and returned both address classes (this is clearly
+ * unexpected behavior).
+ *
+ * At some point down the road if ipv6 actually becomes required and
+ * reliable we can drop this ipv4 check.
+ */
+ if (addinfostatus == ARES_SUCCESS && ai_has_ipv4(hquery->ai)) {
terminate_retries(hquery, ares_dns_record_get_id(dnsrec));
}
}