diff options
| author | Luo Jinghua <sunmoon1997@gmail.com> | 2016-06-07 18:11:37 +0800 | 
|---|---|---|
| committer | Daniel Stenberg <daniel@haxx.se> | 2016-06-07 20:39:05 +0200 | 
| commit | 01a49a7626ee4a226cd0b50d70591ab147d60ee0 (patch) | |
| tree | ef54a49ff290e8c432570d6dc081ebb6c56f420d | |
| parent | 9b6d3a662ea81ec3bbb12002ca79fd27d750671e (diff) | |
resolve: add support for IPv6 DNS64/NAT64 Networks on OS X + iOS
Use getaddrinfo() to resolve the IPv4 address literal on iOS/Mac OS X.
If the current network interface doesn’t support IPv4, but supports
IPv6, NAT64, and DNS64.
Closes #866
Fixes #863
| -rw-r--r-- | lib/asyn-thread.c | 11 | ||||
| -rw-r--r-- | lib/curl_addrinfo.c | 29 | ||||
| -rw-r--r-- | lib/curl_addrinfo.h | 10 | ||||
| -rw-r--r-- | lib/curl_setup.h | 9 | ||||
| -rw-r--r-- | lib/hostip6.c | 12 | 
5 files changed, 69 insertions, 2 deletions
| diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c index 81caedb09..0ca260334 100644 --- a/lib/asyn-thread.c +++ b/lib/asyn-thread.c @@ -279,6 +279,9 @@ static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg)      if(tsd->sock_error == 0)        tsd->sock_error = RESOLVER_ENOMEM;    } +  else { +    Curl_addrinfo_set_port(tsd->res, tsd->port); +  }    Curl_mutex_acquire(tsd->mtx);    if(tsd->done) { @@ -602,6 +605,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,    *waitp = 0; /* default to synchronous response */ +#ifndef USE_RESOLVE_ON_IPS    /* First check if this is an IPv4 address string */    if(Curl_inet_pton(AF_INET, hostname, &in) > 0)      /* This is a dotted IP address 123.123.123.123-style */ @@ -609,7 +613,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,  #ifdef CURLRES_IPV6    /* check if this is an IPv6 address string */ -  if(Curl_inet_pton (AF_INET6, hostname, &in6) > 0) +  if(Curl_inet_pton(AF_INET6, hostname, &in6) > 0)      /* This is an IPv6 address literal */      return Curl_ip2addr(AF_INET6, &in6, hostname, port); @@ -633,6 +637,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,      pf = PF_INET;  #endif /* CURLRES_IPV6 */ +#endif /* USE_RESOLVE_ON_IPS */    memset(&hints, 0, sizeof(hints));    hints.ai_family = pf; @@ -656,6 +661,10 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,            hostname, port, Curl_strerror(conn, SOCKERRNO));      return NULL;    } +  else { +    Curl_addrinfo_set_port(res, port); +  } +    return res;  } diff --git a/lib/curl_addrinfo.c b/lib/curl_addrinfo.c index 8fa0c84cc..35eb2ddb9 100644 --- a/lib/curl_addrinfo.c +++ b/lib/curl_addrinfo.c @@ -563,3 +563,32 @@ curl_dogetaddrinfo(const char *hostname,  }  #endif /* defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) */ +#if defined(HAVE_GETADDRINFO) && defined(USE_RESOLVE_ON_IPS) +/* + * Work-arounds the sin6_port is always zero bug on iOS 9.3.2 and Mac OS X + * 10.11.5. + */ +void Curl_addrinfo_set_port(Curl_addrinfo *addrinfo, int port) +{ +  Curl_addrinfo *ca; +  struct sockaddr_in *addr; +#ifdef ENABLE_IPV6 +  struct sockaddr_in6 *addr6; +#endif +  for(ca = addrinfo; ca != NULL; ca = ca->ai_next) { +    switch (ca->ai_family) { +    case AF_INET: +      addr = (void *)ca->ai_addr; /* storage area for this info */ +      addr->sin_port = htons((unsigned short)port); +      break; + +#ifdef ENABLE_IPV6 +    case AF_INET6: +      addr6 = (void *)ca->ai_addr; /* storage area for this info */ +      addr6->sin6_port = htons((unsigned short)port); +      break; +#endif +    } +  } +} +#endif diff --git a/lib/curl_addrinfo.h b/lib/curl_addrinfo.h index 01f286478..1a681e61e 100644 --- a/lib/curl_addrinfo.h +++ b/lib/curl_addrinfo.h @@ -7,7 +7,7 @@   *                            | (__| |_| |  _ <| |___   *                             \___|\___/|_| \_\_____|   * - * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.   *   * This software is licensed as described in the file COPYING, which   * you should have received as part of this distribution. The terms @@ -99,4 +99,12 @@ curl_dogetaddrinfo(const char *hostname,                     int line, const char *source);  #endif +#ifdef HAVE_GETADDRINFO +#ifdef USE_RESOLVE_ON_IPS +void Curl_addrinfo_set_port(Curl_addrinfo *addrinfo, int port); +#else +#define Curl_addrinfo_set_port(x,y) +#endif +#endif +  #endif /* HEADER_CURL_ADDRINFO_H */ diff --git a/lib/curl_setup.h b/lib/curl_setup.h index d78873fe5..7dcc4c4cd 100644 --- a/lib/curl_setup.h +++ b/lib/curl_setup.h @@ -222,6 +222,15 @@  #endif  /* + * 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. + */ +#ifdef  __APPLE__ +#define USE_RESOLVE_ON_IPS 1 +#endif + +/*   * Include header files for windows builds before redefining anything.   * Use this preprocessor block only to include or exclude windows.h,   * winsock2.h, ws2tcpip.h or winsock.h. Any other windows thing belongs diff --git a/lib/hostip6.c b/lib/hostip6.c index 59bc4e4ac..9d401484a 100644 --- a/lib/hostip6.c +++ b/lib/hostip6.c @@ -167,7 +167,9 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,    int error;    char sbuf[12];    char *sbufptr = NULL; +#ifndef USE_RESOLVE_ON_IPS    char addrbuf[128]; +#endif    int pf;  #if !defined(CURL_DISABLE_VERBOSE_STRINGS)    struct SessionHandle *data = conn->data; @@ -196,11 +198,17 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,    hints.ai_family = pf;    hints.ai_socktype = conn->socktype; +#ifndef USE_RESOLVE_ON_IPS +  /* +   * The AI_NUMERICHOST must not be set to get synthesized IPv6 address from +   * an IPv4 address on iOS and Mac OS X. +   */    if((1 == Curl_inet_pton(AF_INET, hostname, addrbuf)) ||       (1 == Curl_inet_pton(AF_INET6, hostname, addrbuf))) {      /* the given address is numerical only, prevent a reverse lookup */      hints.ai_flags = AI_NUMERICHOST;    } +#endif    if(port) {      snprintf(sbuf, sizeof(sbuf), "%d", port); @@ -213,6 +221,10 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,      return NULL;    } +  if(port) { +    Curl_addrinfo_set_port(res, port); +  } +    dump_addrinfo(conn, res);    return res; | 
