resolve: make forced IPv4 resolve only use A queries

This protects IPv4-only transfers from undesired bad IPv6-related side
effects and make IPv4 transfers in dual-stack libcurl behave the same
way as in IPv4 single-stack libcurl.

Closes #9540
This commit is contained in:
Dmitry Karpov 2022-09-19 13:59:35 -07:00 committed by Daniel Stenberg
parent ae9e713c4e
commit 1902e8fc51
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
5 changed files with 29 additions and 5 deletions

View File

@ -781,6 +781,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
#ifdef CURLRES_IPV6 #ifdef CURLRES_IPV6
if(Curl_ipv6works(data)) if(Curl_ipv6works(data))
/* The stack seems to be IPv6-enabled */ /* The stack seems to be IPv6-enabled */
if(data->conn->ip_version != CURL_IPRESOLVE_V4)
pf = PF_UNSPEC; pf = PF_UNSPEC;
#endif /* CURLRES_IPV6 */ #endif /* CURLRES_IPV6 */
hints.ai_family = pf; hints.ai_family = pf;
@ -794,7 +795,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
#else #else
#ifdef HAVE_CARES_IPV6 #ifdef HAVE_CARES_IPV6
if(Curl_ipv6works(data)) { if(Curl_ipv6works(data) && data->conn->ip_version != CURL_IPRESOLVE_V4) {
/* The stack seems to be IPv6-enabled */ /* The stack seems to be IPv6-enabled */
res->num_pending = 2; res->num_pending = 2;

View File

@ -707,7 +707,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
*waitp = 0; /* default to synchronous response */ *waitp = 0; /* default to synchronous response */
#ifdef CURLRES_IPV6 #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 */ /* The stack seems to be IPv6-enabled */
pf = PF_UNSPEC; pf = PF_UNSPEC;
#endif /* CURLRES_IPV6 */ #endif /* CURLRES_IPV6 */

View File

@ -396,7 +396,7 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
goto error; goto error;
dohp->pending++; dohp->pending++;
if(Curl_ipv6works(data)) { if(Curl_ipv6works(data) && conn->ip_version != CURL_IPRESOLVE_V4) {
/* create IPv6 DoH request */ /* create IPv6 DoH request */
result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V6], result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V6],
DNS_TYPE_AAAA, hostname, data->set.str[STRING_DOH], DNS_TYPE_AAAA, hostname, data->set.str[STRING_DOH],

View File

@ -297,6 +297,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;
bool found = false;
struct Curl_addrinfo *addr = dns->addr;
if(data->conn->ip_version == CURL_IPRESOLVE_V6)
pf = PF_INET6;
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; return dns;
} }

View File

@ -117,7 +117,7 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
*waitp = 0; /* synchronous response only */ *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 */ /* The stack seems to be IPv6-enabled */
pf = PF_UNSPEC; pf = PF_UNSPEC;