socket-util: Use getaddrinfo() instead of gethostbyname() for thread safety.
authorBen Pfaff <blp@nicira.com>
Thu, 2 May 2013 21:34:45 +0000 (14:34 -0700)
committerBen Pfaff <blp@nicira.com>
Thu, 2 May 2013 21:34:45 +0000 (14:34 -0700)
Signed-off-by: Ben Pfaff <blp@nicira.com>
lib/socket-util.c

index 4f9b5b8..906b970 100644 (file)
@@ -178,30 +178,57 @@ lookup_ipv6(const char *host_name, struct in6_addr *addr)
  * successful, otherwise a positive errno value.
  *
  * Most Open vSwitch code should not use this because it causes deadlocks:
- * gethostbyname() sends out a DNS request but that starts a new flow for which
+ * getaddrinfo() sends out a DNS request but that starts a new flow for which
  * OVS must set up a flow, but it can't because it's waiting for a DNS reply.
  * The synchronous lookup also delays other activity.  (Of course we can solve
  * this but it doesn't seem worthwhile quite yet.)  */
 int
 lookup_hostname(const char *host_name, struct in_addr *addr)
 {
-    struct hostent *h;
+    struct addrinfo *result;
+    struct addrinfo hints;
 
     if (inet_aton(host_name, addr)) {
         return 0;
     }
 
-    h = gethostbyname(host_name);
-    if (h) {
-        *addr = *(struct in_addr *) h->h_addr;
+    memset(&hints, 0, sizeof hints);
+    hints.ai_family = AF_INET;
+
+    switch (getaddrinfo(host_name, NULL, &hints, &result)) {
+    case 0:
+        *addr = ((struct sockaddr_in *) result->ai_addr)->sin_addr;
+        freeaddrinfo(result);
         return 0;
-    }
 
-    return (h_errno == HOST_NOT_FOUND ? ENOENT
-            : h_errno == TRY_AGAIN ? EAGAIN
-            : h_errno == NO_RECOVERY ? EIO
-            : h_errno == NO_ADDRESS ? ENXIO
-            : EINVAL);
+    case EAI_ADDRFAMILY:
+    case EAI_NONAME:
+    case EAI_SERVICE:
+        return ENOENT;
+
+    case EAI_AGAIN:
+        return EAGAIN;
+
+    case EAI_BADFLAGS:
+    case EAI_FAMILY:
+    case EAI_SOCKTYPE:
+        return EINVAL;
+
+    case EAI_FAIL:
+        return EIO;
+
+    case EAI_MEMORY:
+        return ENOMEM;
+
+    case EAI_NODATA:
+        return ENXIO;
+
+    case EAI_SYSTEM:
+        return errno;
+
+    default:
+        return EPROTO;
+    }
 }
 
 int