New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libcurl can't connect to ipv4 numerical IP address in NAT64 environment #863

Closed
churuxu opened this Issue Jun 6, 2016 · 12 comments

Comments

Projects
None yet
4 participants
@churuxu

churuxu commented Jun 6, 2016

my test environment:
a mac mini share NAT64 wifi,
an iphone connect this wifi,
in this iphone use libcurl to connect ipv4 server url , such like "http://192.168.1.200/"
it can‘t connect to server.

the reason may be:
libcurl try parse ip addr directly. result of resolver only have one sockaddr:
AF_INET: 192.168.1.200

in my test code, the result 'addrinfo' of os 'getaddrino' api have two sockaddr:
AF_INET6: 0064:ff9b:0000:0000:0000:0000:192.168.1.200
AF_INET: 192.168.1.200

connect AF_INET6 addr is ok , and connect AF_INET addr is error in this environment.

curl/libcurl version 7.41

@bagder

This comment has been minimized.

Member

bagder commented Jun 6, 2016

Sorry but I don't understand. You provide a URL using an IPv4 numerical address and it doesn't work? libcurl won't use any resolver for that but will try to connect to that IP address on the default port. If you enable VERBOSE you'll see libcurl saying so.

"connect AF_INET addr is error in this environment"

Then you shouldn't specify the target address using an IPv4 numerical as that will make libcurl try IPv4 on it. How would libcurl know how to trancode that address over to your preferred IPv6 alternative?

@LuoJinghua

This comment has been minimized.

Contributor

LuoJinghua commented Jun 7, 2016

We met the same problem on iOS too since the Apple requires all iOS apps to support IPv6 only networks.

The Apple seggests following solution:

Use System APIs to Synthesize IPv6 Addresses
If your app needs to connect to an IPv4-only server without a DNS hostname, use getaddrinfo to resolve the IPv4 address literal. If the current network interface doesn’t support IPv4, but supports IPv6, NAT64, and DNS64, performing this task will result in a synthesized IPv6 address.

Listing 10-1 shows how to resolve an IPv4 literal using getaddrinfo. Assuming you have an IPv4 address stored in memory as four bytes (such as {192, 0, 2, 1}), this example code converts it to a string (such as "192.0.2.1"), uses getaddrinfo to synthesize an IPv6 address (such as a struct sockaddr_in6 containing the IPv6 address "64:ff9b::192.0.2.1") and tries to connect to that IPv6 address.

https://developer.apple.com/library/ios/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/UnderstandingandPreparingfortheIPv6Transition/UnderstandingandPreparingfortheIPv6Transition.html

Example url:
http://cdn.data.video.iqiyi.com/cdn/transmension/20160518/pvr/17be9445ac588937729a1753d750dfb9.FCP.gz
http://180.153.129.77/cdn/transmension/20160518/pvr/17be9445ac588937729a1753d750dfb9.FCP.gz

@churuxu

This comment has been minimized.

churuxu commented Jun 7, 2016

like thease codes:

getaddrinfo("192.168.1.200", "80", NULL, &ai); sock = socket(ai->ai_family, SOCK_STREAM, 0); connect(sock, ai->ai_addr, ai->ai_addrlen); //connect to server ok, because result of os 'getaddrinfo' api contains AF_INET6 'sockaddr'

`
if(inet_pton(AF_INET, "192.168.1.200", ...)>0){
//use ipv4 'sockaddr'
}else{
if(inet_ntop(AF_INET6, ...)>0){
//use ipv6 'sockaddr'
}
}
...
//can't connect to server, because "192.168.1.200" parsed as AF_INET 'sockaddr'

@churuxu

This comment has been minimized.

churuxu commented Jun 7, 2016

And dns cache feature of libcurl may have a problem:
steps:
1, mobile connect an ipv4 wifi
2, resolv "github.com" result ipv4 'sockaddr'
3, cache this ipv4 'sockaddr'
4, connect to server ok
5, mobile change to an ipv6 wifi
6, resolv "github.com" use cached ipv4 'sockaddr'
7, can't connect to server

@bagder

This comment has been minimized.

Member

bagder commented Jun 7, 2016

And dns cache feature of libcurl may have a problem

That is a totally separate subject. This issue is about IPv4 addresses in a nat64 apple environment.

@bagder

This comment has been minimized.

Member

bagder commented Jun 7, 2016

Apple suggests following solution

Hm ok. That's a bit unfortunate but should be possible quite easily by just removing the shortcuts we have that avoid name resolves for pure numerical addresses (when built for platforms that need this approach). I would prefer someone who can actually try that out to suggest a patch.

@LuoJinghua

This comment has been minimized.

Contributor

LuoJinghua commented Jun 7, 2016

Yes, Apple's suggestion does work for me (but with a minor issue that the sin6_port is always zero). Here is my quick & dirty patch.

http://paste.ubuntu.com/17084154/

@bagder

This comment has been minimized.

Member

bagder commented Jun 7, 2016

Thanks!

  • The conditional shouldn't be for __APPLE__ but a feature-like one USE_RESOLVE_ON_IPS (or something similar) and then you can conditionally define that feature if __APPLE__ is detected , but chances are there are other platforms/environments where this will behavior be interesting.
  • You've added the work-around for the "addr6->sin6_port" problem twice, that seems unnecessary. Can't it be moved to just a single place?
  • Why can't you still have AI_NUMERICHOST set? It is still numerical after all.
  • The ubuntu pastebin site seems stupid enough to now allow a "raw" display without login so it makes it really hard to apply this patch. Maybe do a plain pull-request here?

@bagder bagder changed the title from libcurl can't connect to ipv4 server url in NAT64 environment to libcurl can't connect to ipv4 numerical IP address in NAT64 environment Jun 7, 2016

@LuoJinghua

This comment has been minimized.

Contributor

LuoJinghua commented Jun 7, 2016

The conditional shouldn't be for APPLE but a feature-like one USE_RESOLVE_ON_IPS (or something similar) and then you can conditionally define that feature if APPLE is detected , but chances are there are other platforms/environments where this will behavior be interesting.

Fixed

You've added the work-around for the "addr6->sin6_port" problem twice, that seems unnecessary. Can't it be moved to just a single place?

Fixed

Why can't you still have AI_NUMERICHOST set? It is still numerical after all.

It must be removed to get synthesized IPv6 address.

@bagder bagder closed this in 01a49a7 Jun 7, 2016

jay added a commit that referenced this issue Jun 8, 2016

resolve: enable protocol family logic for synthesized IPv6
- Enable protocol family logic for IPv6 resolves even when support
for synthesized addresses is enabled.

This is a follow up to the parent commit that added support for
synthesized IPv6 addresses from IPv4 on iOS/OS X. The protocol family
logic needed for IPv6 was inadvertently excluded if support for
synthesized addresses was enabled.

Bug: #863
Ref: #866
Ref: #867
@minggo

This comment has been minimized.

minggo commented Jul 11, 2016

@bagder can i know when to release a new CURL version? coocs2d-x uses CURL, the games developed using cocos2d-x were rejected by apple about this issue.

@bagder

This comment has been minimized.

Member

bagder commented Jul 14, 2016

See our release calendar, HTML version. July 21 is the plan.

@minggo

This comment has been minimized.

minggo commented Jul 15, 2016

thanks @bagder

@lock lock bot locked as resolved and limited conversation to collaborators May 7, 2018

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.