hostip: Make Curl_ipv6works function independent of getaddrinfo

- Do not assume IPv6 is not working when getaddrinfo is not present.

The check to see if IPv6 actually works is now independent of whether
there is any resolver that can potentially resolve a hostname to IPv6.

Prior to this change if getaddrinfo() was not found at compile time then
Curl_ipv6works() would be defined as a macro that returns FALSE.

When getaddrinfo is not found then libcurl is built with CURLRES_IPV4
defined instead of CURLRES_IPV6, meaning that it cannot do IPv6 lookups
in the traditional way. With this commit if libcurl is built with IPv6
support (ENABLE_IPV6) but without getaddrinfo (CURLRES_IPV6), and the
IPv6 stack is actually working, then it is possible for libcurl to
resolve IPv6 addresses by using DoH.

Ref: https://github.com/curl/curl/issues/7483#issuecomment-890765378

Closes https://github.com/curl/curl/pull/7529
This commit is contained in:
Jay Satiro 2021-08-03 03:03:00 -04:00
parent 26f93cf038
commit 16e9c8e990
3 changed files with 36 additions and 32 deletions

View File

@ -533,6 +533,36 @@ static struct Curl_addrinfo *get_localhost(int port)
return ca;
}
#ifdef ENABLE_IPV6
/*
* Curl_ipv6works() returns TRUE if IPv6 seems to work.
*/
bool Curl_ipv6works(struct Curl_easy *data)
{
if(data) {
/* the nature of most system is that IPv6 status doesn't come and go
during a program's lifetime so we only probe the first time and then we
have the info kept for fast re-use */
DEBUGASSERT(data);
DEBUGASSERT(data->multi);
return data->multi->ipv6_works;
}
else {
int ipv6_works = -1;
/* probe to see if we have a working IPv6 stack */
curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0);
if(s == CURL_SOCKET_BAD)
/* an IPv6 address was requested but we can't get/use one */
ipv6_works = 0;
else {
ipv6_works = 1;
sclose(s);
}
return (ipv6_works>0)?TRUE:FALSE;
}
}
#endif /* ENABLE_IPV6 */
/*
* Curl_host_is_ipnum() returns TRUE if the given string is a numerical IPv4
* (or IPv6 if supported) address.
@ -674,9 +704,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
#endif /* !USE_RESOLVE_ON_IPS */
if(!addr) {
/* Check what IP specifics the app has requested and if we can provide
* it. If not, bail out. */
if(!Curl_ipvalid(data, conn))
if(conn->ip_version == CURL_IPRESOLVE_V6 && !Curl_ipv6works(data))
return CURLRESOLV_ERROR;
if(strcasecompare(hostname, "localhost"))
@ -684,6 +712,10 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
else if(allowDOH && data->set.doh && !ipnum)
addr = Curl_doh(data, hostname, port, &respwait);
else {
/* Check what IP specifics the app has requested and if we can provide
* it. If not, bail out. */
if(!Curl_ipvalid(data, conn))
return CURLRESOLV_ERROR;
/* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a
non-zero value indicating that we need to wait for the response to
the resolve call */

View File

@ -97,7 +97,7 @@ enum resolve_t Curl_resolv_timeout(struct Curl_easy *data,
struct Curl_dns_entry **dnsentry,
timediff_t timeoutms);
#ifdef CURLRES_IPV6
#ifdef ENABLE_IPV6
/*
* Curl_ipv6works() returns TRUE if IPv6 seems to work.
*/

View File

@ -59,34 +59,6 @@
#include "curl_memory.h"
#include "memdebug.h"
/*
* Curl_ipv6works() returns TRUE if IPv6 seems to work.
*/
bool Curl_ipv6works(struct Curl_easy *data)
{
if(data) {
/* the nature of most system is that IPv6 status doesn't come and go
during a program's lifetime so we only probe the first time and then we
have the info kept for fast re-use */
DEBUGASSERT(data);
DEBUGASSERT(data->multi);
return data->multi->ipv6_works;
}
else {
int ipv6_works = -1;
/* probe to see if we have a working IPv6 stack */
curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0);
if(s == CURL_SOCKET_BAD)
/* an IPv6 address was requested but we can't get/use one */
ipv6_works = 0;
else {
ipv6_works = 1;
sclose(s);
}
return (ipv6_works>0)?TRUE:FALSE;
}
}
/*
* Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
* been set and returns TRUE if they are OK.