From e2bec5adf828fbd3a4f66d161a42a7a5233347c6 Mon Sep 17 00:00:00 2001
From: Dmitry Karpov <dkarpov@roku.com>
Date: Mon, 23 May 2022 12:30:42 -0700
Subject: [PATCH] Disabled using AAAA DNS queries for IPv4 resolve mode.

---
 lib/asyn-ares.c   |  7 +++++--
 lib/asyn-thread.c |  2 +-
 lib/doh.c         |  2 +-
 lib/hostip.c      | 23 +++++++++++++++++++++++
 lib/hostip6.c     |  2 +-
 5 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c
index c885adef5..eb7ac514d 100644
--- a/lib/asyn-ares.c
+++ b/lib/asyn-ares.c
@@ -775,6 +775,8 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
     /* initial status - failed */
     res->last_status = ARES_ENOTFOUND;
 
+    struct connectdata* conn = data->conn;
+
 #ifdef HAVE_CARES_GETADDRINFO
     {
       struct ares_addrinfo_hints hints;
@@ -784,7 +786,8 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
 #ifdef CURLRES_IPV6
       if(Curl_ipv6works(data))
         /* The stack seems to be IPv6-enabled */
-        pf = PF_UNSPEC;
+        if(conn->ip_version != CURL_IPRESOLVE_V4)
+          pf = PF_UNSPEC;
 #endif /* CURLRES_IPV6 */
       hints.ai_family = pf;
       hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP)?
@@ -797,7 +800,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
 #else
 
 #ifdef HAVE_CARES_IPV6
-    if(Curl_ipv6works(data)) {
+    if(Curl_ipv6works(data) && conn->ip_version != CURL_IPRESOLVE_V4) {
       /* The stack seems to be IPv6-enabled */
       res->num_pending = 2;
 
diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c
index 149172ad3..adc63b3c1 100644
--- a/lib/asyn-thread.c
+++ b/lib/asyn-thread.c
@@ -700,7 +700,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
   *waitp = 0; /* default to synchronous response */
 
 #ifdef CURLRES_IPV6
-  if(Curl_ipv6works(data))
+  if(Curl_ipv6works(data) && data->conn->ip_version != CURL_IPRESOLVE_V4)
     /* The stack seems to be IPv6-enabled */
     pf = PF_UNSPEC;
 #endif /* CURLRES_IPV6 */
diff --git a/lib/doh.c b/lib/doh.c
index 4aef8b266..4e975add6 100644
--- a/lib/doh.c
+++ b/lib/doh.c
@@ -407,7 +407,7 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
     goto error;
   dohp->pending++;
 
-  if(Curl_ipv6works(data)) {
+  if(Curl_ipv6works(data) || conn->ip_version != CURL_IPRESOLVE_V4) {
     /* create IPv6 DoH request */
     result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V6],
                       DNS_TYPE_AAAA, hostname, data->set.str[STRING_DOH],
diff --git a/lib/hostip.c b/lib/hostip.c
index 7000b8550..9e2b618c4 100644
--- a/lib/hostip.c
+++ b/lib/hostip.c
@@ -295,6 +295,29 @@ static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data,
     }
   }
 
+  /* See if the returned entry matches the required resolve mode */
+  if(dns && data->conn->ip_version != CURL_IPRESOLVE_WHATEVER) {
+      int pf = PF_INET;
+      if(data->conn->ip_version == CURL_IPRESOLVE_V6)
+        pf = PF_INET6;
+
+      bool found = false;
+      struct Curl_addrinfo* addr = dns->addr;
+
+      while(addr) {
+        if(addr->ai_family == pf) {
+            found = true;
+            break;
+        }
+        addr = addr->ai_next;
+      }
+
+      if(!found) {
+        infof(data, "Hostname in DNS cache doesn't have needed family, zapped");
+        dns = NULL; /* the memory deallocation is being handled by the hash */
+        Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
+      }
+  }
   return dns;
 }
 
diff --git a/lib/hostip6.c b/lib/hostip6.c
index c2d5f08e3..a00bb9f4f 100644
--- a/lib/hostip6.c
+++ b/lib/hostip6.c
@@ -115,7 +115,7 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
 
   *waitp = 0; /* synchronous response only */
 
-  if(Curl_ipv6works(data))
+  if(Curl_ipv6works(data) && data->conn->ip_version != CURL_IPRESOLVE_V4)
     /* The stack seems to be IPv6-enabled */
     pf = PF_UNSPEC;
 
-- 
2.35.1.windows.2

