aboutsummaryrefslogtreecommitdiff
path: root/lib/socket-util.c
diff options
context:
space:
mode:
authorBen Pfaff <blp@nicira.com>2013-05-02 14:34:45 -0700
committerBen Pfaff <blp@nicira.com>2013-05-02 14:34:45 -0700
commit3cbb5dc7e89df2b40bb6f715873cf2b6b25a7054 (patch)
treef05efe1a959f0aeb13fcc3a3ce14b392a2b31500 /lib/socket-util.c
parent92829687b4f303fef7a6ca39d226e63d6be145e3 (diff)
socket-util: Use getaddrinfo() instead of gethostbyname() for thread safety.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Diffstat (limited to 'lib/socket-util.c')
-rw-r--r--lib/socket-util.c49
1 files changed, 38 insertions, 11 deletions
diff --git a/lib/socket-util.c b/lib/socket-util.c
index 4f9b5b89..906b970a 100644
--- a/lib/socket-util.c
+++ b/lib/socket-util.c
@@ -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