diff options
author | Ben Pfaff <blp@nicira.com> | 2013-05-02 14:34:45 -0700 |
---|---|---|
committer | Ben Pfaff <blp@nicira.com> | 2013-05-02 14:34:45 -0700 |
commit | 3cbb5dc7e89df2b40bb6f715873cf2b6b25a7054 (patch) | |
tree | f05efe1a959f0aeb13fcc3a3ce14b392a2b31500 /lib/socket-util.c | |
parent | 92829687b4f303fef7a6ca39d226e63d6be145e3 (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.c | 49 |
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 |