tizen 2.3.1 release
[external/curl.git] / lib / hostip6.c
index ca02807..bb72391 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2014, 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
  *
  ***************************************************************************/
 
-#include "setup.h"
+#include "curl_setup.h"
 
-#include <string.h>
-
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
 #ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
 #ifdef HAVE_ARPA_INET_H
 #include <arpa/inet.h>
 #endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>     /* required for free() prototypes */
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>     /* for the close() proto */
-#endif
 #ifdef __VMS
 #include <in.h>
 #include <inet.h>
-#include <stdlib.h>
 #endif
 
 #ifdef HAVE_PROCESS_H
@@ -70,7 +58,7 @@
 #include "memdebug.h"
 
 /***********************************************************************
- * Only for ipv6-enabled builds
+ * Only for IPv6-enabled builds
  **********************************************************************/
 #ifdef CURLRES_IPV6
 
@@ -78,7 +66,7 @@
 #if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO)
 /* These are strictly for memory tracing and are using the same style as the
  * family otherwise present in memdebug.c. I put these ones here since they
- * require a bunch of structs I didn't wanna include in memdebug.c
+ * require a bunch of structs I didn't want to include in memdebug.c
  */
 
 /*
@@ -109,19 +97,36 @@ int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
 #endif /* defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO) */
 
 /*
- * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
- * been set and returns TRUE if they are OK.
+ * Curl_ipv6works() returns TRUE if IPv6 seems to work.
  */
-bool Curl_ipvalid(struct connectdata *conn)
+bool Curl_ipv6works(void)
 {
-  if(conn->ip_version == CURL_IPRESOLVE_V6) {
-    /* see if we have an IPv6 stack */
+  /* 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 */
+  static int ipv6_works = -1;
+  if(-1 == ipv6_works) {
+    /* 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 and we can't get/use one */
-      return FALSE;
-    sclose(s);
+      /* an IPv6 address was requested but we can't get/use one */
+      ipv6_works = 0;
+    else {
+      ipv6_works = 1;
+      Curl_closesocket(NULL, 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.
+ */
+bool Curl_ipvalid(struct connectdata *conn)
+{
+  if(conn->ip_version == CURL_IPRESOLVE_V6)
+    return Curl_ipv6works();
   return TRUE;
 }
 
@@ -131,7 +136,7 @@ bool Curl_ipvalid(struct connectdata *conn)
 static void dump_addrinfo(struct connectdata *conn, const Curl_addrinfo *ai)
 {
   printf("dump_addrinfo:\n");
-  for ( ; ai; ai = ai->ai_next) {
+  for(; ai; ai = ai->ai_next) {
     char  buf[INET6_ADDRSTRLEN];
 
     printf("    fam %2d, CNAME %s, ",
@@ -143,11 +148,11 @@ static void dump_addrinfo(struct connectdata *conn, const Curl_addrinfo *ai)
   }
 }
 #else
-#define dump_addrinfo(x,y)
+#define dump_addrinfo(x,y) Curl_nop_stmt
 #endif
 
 /*
- * Curl_getaddrinfo() when built ipv6-enabled (non-threading and
+ * Curl_getaddrinfo() when built IPv6-enabled (non-threading and
  * non-ares version).
  *
  * Returns name information about the given hostname and port number. If
@@ -163,7 +168,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
   struct addrinfo hints;
   Curl_addrinfo *res;
   int error;
-  char sbuf[NI_MAXSERV];
+  char sbuf[12];
   char *sbufptr = NULL;
   char addrbuf[128];
   int pf;
@@ -186,23 +191,9 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
     break;
   }
 
-  if (pf != PF_INET) {
-    /* see if we have an IPv6 stack */
-    curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0);
-    if(s == CURL_SOCKET_BAD) {
-      /* Some non-IPv6 stacks have been found to make very slow name resolves
-       * when PF_UNSPEC is used, so thus we switch to a mere PF_INET lookup if
-       * the stack seems to be a non-ipv6 one. */
-
-      pf = PF_INET;
-    }
-    else {
-      /* This seems to be an IPv6-capable stack, use PF_UNSPEC for the widest
-       * possible checks. And close the socket again.
-       */
-      sclose(s);
-    }
-  }
+  if((pf != PF_INET) && !Curl_ipv6works())
+    /* The stack seems to be a non-IPv6 one */
+    pf = PF_INET;
 
   memset(&hints, 0, sizeof(hints));
   hints.ai_family = pf;