cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: Problem resolving localhost with IPv6 disabled

From: Maxim Prohorov <prohorov.max_at_gmail.com>
Date: Mon, 12 Mar 2012 20:42:24 +0400

On Sun, Mar 11, 2012 at 2:38 AM, Daniel Stenberg <daniel_at_haxx.se> wrote:
> Did you also upgrade c-ares or only libcurl? It so feels like a c-ares
> problem...

No, the c-ares remained the same (1.7.5)

And I think I've failed in naming the problem...
Anything with both IPv4 and IPv6 addresses fails.

As an example (curl from git master):
> $ host download.opensuse.com 8.8.8.8 | tail -n 2
> download.opensuse.org has address 195.135.221.134
> download.opensuse.org has IPv6 address 2001:67c:2178:8::13

> $ curl download.opensuse.com
> curl: (2) Failed initialization

> $ curl -v 195.135.221.134
> ...
> * Connected to 195.135.221.134 (195.135.221.134) port 80 (#0)
> ...

> $ curl -g '[2001:67c:2178:8::13]'
> curl: (2) Failed initialization

> $ curl --version
> curl 7.25.0-DEV (x86_64-unknown-linux-gnu) libcurl/7.25.0-DEV OpenSSL/1.0.0g zlib/1.2.6 c-ares/1.7.5 libidn/1.24 libssh2/1.3.0 librtmp/2.3
> Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp scp sftp smtp smtps telnet tftp
> Features: AsynchDNS IDN IPv6 Largefile NTLM NTLM_WB SSL libz

The root of the problem seems to be this part of asyn-ares.c
Since ipv6 enabled in config, code under the ifdef ENABLE_IPV6 runs:
lib/asyn-ares.c:588-591
> ares_gethostbyname((ares_channel)data->state.resolver, hostname,
> PF_INET, query_completed_cb, conn);
> ares_gethostbyname((ares_channel)data->state.resolver, hostname,
> PF_INET6, query_completed_cb, conn);

Sometime after Curl_resolv loop inside Curl_connecthost
(and 9 in 10 times, first one to check is IPv6):
lib/connect.c:1068 Curl_connecthost
> res = singleipconnect(conn, curr_addr,

lib/connect.c:882-884 singleipconnect
> res = Curl_socket(conn, ai, &addr, &sockfd);
> if(res)
> return res;

Displayed error comes from here:
lib/connect.c:1228-1232 Curl_socket
> *sockfd = socket(addr->family, addr->socktype, addr->protocol);
>
> if (*sockfd == CURLE_SOCKET_BAD)
> /* no socket, no connection */
> return CURLE_FAILED_INIT;

And the reason of CURLE_SOCKET_BAD (strace dump):
> socket(PF_INET6, SOCK_STREAM, IPPROTO_IP) = -1 EAFNOSUPPORT (Address family not supported by protocol)

Suse reporter mentioned that they bisected bug to the commit
9109cdec11ee5a19f132fd7bdf2e9ceefea4de41
Before that commit, when addr->family was PF_INET6 the same statement
returned CURLE_OK.
Because of that, loop inside Curl_connecthost continued to the next
(ipv4) address without any errors.

Again, going back to Suse bug report. Now they are using
--enable-threaded-resolver
Looks like the threaded one works ok because of this check:
lib/asyn-thread.c:643-645 Curl_resolver_getaddrinfo
> if((pf != PF_INET) && !Curl_ipv6works())
> /* the stack seems to be a non-ipv6 one */
> pf = PF_INET;

Not sure this is a good solution, but why not to use Curl_ipv6works in
asyn-ares too? [attachment]

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html

Received on 2012-03-12