diff --git a/lib/hostip.c b/lib/hostip.c index bd00efff61..2ace940670 100644 --- a/lib/hostip.c +++ b/lib/hostip.c @@ -741,36 +741,33 @@ static struct Curl_addrinfo *get_localhost(int port, const char *name) } #ifdef USE_IPV6 +/* the nature of most systems is that IPv6 status does not come and go during a + program's lifetime so we only probe the first time and then we have the + info kept for fast reuse */ +CURLcode Curl_probeipv6(struct Curl_multi *multi) +{ + /* probe to see if we have a working IPv6 stack */ + curl_socket_t s = CURL_SOCKET(PF_INET6, SOCK_DGRAM, 0); + multi->ipv6_works = FALSE; + if(s == CURL_SOCKET_BAD) { + if(SOCKERRNO == SOCKENOMEM) + return CURLE_OUT_OF_MEMORY; + } + else { + multi->ipv6_works = TRUE; + sclose(s); + } + return CURLE_OK; +} + /* * 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 does not come and go - during a program's lifetime so we only probe the first time and then we - have the info kept for fast reuse */ - DEBUGASSERT(data); - DEBUGASSERT(data->multi); - if(data->multi->ipv6_up == IPV6_UNKNOWN) { - bool works = Curl_ipv6works(NULL); - data->multi->ipv6_up = works ? IPV6_WORKS : IPV6_DEAD; - } - return data->multi->ipv6_up == IPV6_WORKS; - } - else { - int ipv6_works = -1; - /* probe to see if we have a working IPv6 stack */ - curl_socket_t s = CURL_SOCKET(PF_INET6, SOCK_DGRAM, 0); - if(s == CURL_SOCKET_BAD) - /* an IPv6 address was requested but we cannot get/use one */ - ipv6_works = 0; - else { - ipv6_works = 1; - sclose(s); - } - return ipv6_works > 0; - } + DEBUGASSERT(data); + DEBUGASSERT(data->multi); + return data ? data->multi->ipv6_works : FALSE; } #endif /* USE_IPV6 */ diff --git a/lib/hostip.h b/lib/hostip.h index 45d63e97f3..0257e43645 100644 --- a/lib/hostip.h +++ b/lib/hostip.h @@ -48,6 +48,7 @@ struct Curl_easy; struct connectdata; struct easy_pollset; struct Curl_https_rrinfo; +struct Curl_multi; enum alpnid { ALPN_none = 0, @@ -104,11 +105,15 @@ CURLcode Curl_resolv_timeout(struct Curl_easy *data, timediff_t timeoutms); #ifdef USE_IPV6 + +/* probe if it seems to work */ +CURLcode Curl_probeipv6(struct Curl_multi *multi); /* * Curl_ipv6works() returns TRUE if IPv6 seems to work. */ bool Curl_ipv6works(struct Curl_easy *data); #else +#define Curl_probeipv6(x) CURLE_OK #define Curl_ipv6works(x) FALSE #endif diff --git a/lib/multi.c b/lib/multi.c index 477b0d2243..a7f0d24ee0 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -300,6 +300,9 @@ struct Curl_multi *Curl_multi_handle(uint32_t xfer_table_size, } #endif + if(Curl_probeipv6(multi)) + goto error; + return multi; error: diff --git a/lib/multihandle.h b/lib/multihandle.h index f66853f5f0..7a561124ae 100644 --- a/lib/multihandle.h +++ b/lib/multihandle.h @@ -174,10 +174,7 @@ struct Curl_multi { #ifdef DEBUGBUILD unsigned int now_access_count; #endif -#define IPV6_UNKNOWN 0 -#define IPV6_DEAD 1 -#define IPV6_WORKS 2 - unsigned char ipv6_up; /* IPV6_* defined */ + BIT(ipv6_works); BIT(multiplexing); /* multiplexing wanted */ BIT(recheckstate); /* see Curl_multi_connchanged */ BIT(in_callback); /* true while executing a callback */