From: Jay Satiro Date: Tue, 3 Aug 2021 07:03:00 +0000 (-0400) Subject: hostip: Make Curl_ipv6works function independent of getaddrinfo X-Git-Tag: curl-7_79_0~139 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=16e9c8e9909fc12c3f9735f666b5a8c5af669e8b;p=thirdparty%2Fcurl.git 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 --- diff --git a/lib/hostip.c b/lib/hostip.c index 30ce509267..bb110dee5d 100644 --- a/lib/hostip.c +++ b/lib/hostip.c @@ -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 */ diff --git a/lib/hostip.h b/lib/hostip.h index 28f3b84018..67a688aebd 100644 --- a/lib/hostip.h +++ b/lib/hostip.h @@ -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. */ diff --git a/lib/hostip6.c b/lib/hostip6.c index 943cdd261c..e2777c73d4 100644 --- a/lib/hostip6.c +++ b/lib/hostip6.c @@ -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.