Replacing gethostbyname, gethostbyname2 and their _r variants with getaddrinfo to...
authorTobias Brunner <tobias@strongswan.org>
Fri, 14 Aug 2009 13:47:04 +0000 (15:47 +0200)
committerTobias Brunner <tobias@strongswan.org>
Fri, 14 Aug 2009 14:14:32 +0000 (16:14 +0200)
configure.in
src/libfreeswan/atoaddr.3
src/libfreeswan/atoaddr.c
src/libfreeswan/ttoaddr.3
src/libfreeswan/ttoaddr.c
src/libstrongswan/utils/host.c

index 9c811a5..f677cb6 100644 (file)
@@ -882,7 +882,6 @@ AC_TRY_COMPILE(
 )
 
 AC_CHECK_FUNCS(prctl)
-AC_CHECK_FUNCS(gethostbyname_r)
 
 AC_CHECK_HEADERS(sys/sockio.h)
 AC_CHECK_HEADERS(net/pfkeyv2.h netipsec/ipsec.h netinet6/ipsec.h linux/udp.h)
index fce8884..10da269 100644 (file)
@@ -54,7 +54,7 @@ on a big-endian host and
 .B 4.3.2.1
 on a little-endian host),
 a DNS name to be looked up via
-.IR gethostbyname (3),
+.IR getaddrinfo (3),
 or an old-style network name to be looked up via
 .IR getnetbyname (3).
 .PP
@@ -91,10 +91,8 @@ DNS names may be complete (optionally terminated with a ``.'')
 or incomplete, and are looked up as specified by local system configuration
 (see
 .IR resolver (5)).
-The
-.I h_addr
-value returned by
-.IR gethostbyname (3)
+The first value returned by
+.IR getaddrinfo (3)
 is used,
 so with current DNS implementations,
 the result when the name corresponds to more than one address is
@@ -102,7 +100,7 @@ difficult to predict.
 Name lookup resorts to
 .IR getnetbyname (3)
 only if
-.IR gethostbyname (3)
+.IR getaddrinfo (3)
 fails.
 .PP
 A subnet specification is of the form \fInetwork\fB/\fImask\fR.
index dd73be7..c962a16 100644 (file)
@@ -12,6 +12,8 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
  * License for more details.
  */
+#include <sys/socket.h>
+
 #include "internal.h"
 #include "freeswan.h"
 
@@ -41,7 +43,7 @@ const char *src;
 size_t srclen;                 /* 0 means "apply strlen" */
 struct in_addr *addrp;
 {
-       struct hostent *h;
+       struct addrinfo hints, *res;
        struct netent *ne = NULL;
        const char *oops;
 #      define  HEXLEN  10      /* strlen("0x11223344") */
@@ -51,6 +53,7 @@ struct in_addr *addrp;
        char namebuf[ATOADDRBUF];
        char *p = namebuf;
        char *q;
+       int error;
 
        if (srclen == 0)
                srclen = strlen(src);
@@ -87,18 +90,33 @@ struct in_addr *addrp;
                return "illegal (non-DNS-name) character in name";
 
        /* try as host name, failing that as /etc/networks network name */
-       h = gethostbyname(p);
-       if (h == NULL)
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = AF_INET;
+       error = getaddrinfo(p, NULL, &hints, &res);
+       if (error != 0)
+       {
                ne = getnetbyname(p);
+               if (ne == NULL)
+               {
+                       if (p != namebuf)
+                       {
+                               FREE(p);
+                       }
+                       return "name lookup failed";
+               }
+               addrp->s_addr = htonl(ne->n_net);
+       }
+       else
+       {
+               memcpy(&addrp->s_addr, res->ai_addr->sa_data, sizeof(addrp->s_addr));
+               freeaddrinfo(res);
+       }
+
        if (p != namebuf)
+       {
                FREE(p);
-       if (h == NULL && ne == NULL)
-               return "name lookup failed";
+       }
 
-       if (h != NULL)
-               memcpy(&addrp->s_addr, h->h_addr, sizeof(addrp->s_addr));
-       else
-               addrp->s_addr = htonl(ne->n_net);
        return NULL;
 }
 
index 7067114..d43d2b1 100644 (file)
@@ -59,7 +59,7 @@ on a big-endian host and
 .B 4.3.2.1
 on a little-endian host),
 a DNS name to be looked up via
-.IR gethostbyname (3),
+.IR getaddrinfo (3),
 or an old-style network name to be looked up via
 .IR getnetbyname (3).
 .PP
@@ -100,7 +100,7 @@ abbreviating at most one subsequence of multiple zeros (e.g.
 which is synonymous with
 .BR 99:ab:0:0:0:0:54:68 ),
 or a DNS name to be looked up via
-.IR gethostbyname (3).
+.IR getaddrinfo (3).
 The result of applying
 .I addrtot
 to an IPv6 address will use
@@ -115,10 +115,8 @@ DNS names may be complete (optionally terminated with a ``.'')
 or incomplete, and are looked up as specified by local system configuration
 (see
 .IR resolver (5)).
-The
-.I h_addr
-value returned by
-.IR gethostbyname2 (3)
+The first value returned by
+.IR getaddrinfo (3)
 is used,
 so with current DNS implementations,
 the result when the name corresponds to more than one address is
@@ -126,7 +124,7 @@ difficult to predict.
 IPv4 name lookup resorts to
 .IR getnetbyname (3)
 only if
-.IR gethostbyname2 (3)
+.IR getaddrinfo (3)
 fails.
 .PP
 A subnet specification is of the form \fInetwork\fB/\fImask\fR.
index e4ceec8..ede0713 100644 (file)
@@ -157,12 +157,15 @@ int nultermd;                     /* is it known to be NUL-terminated? */
 int af;
 ip_address *dst;
 {
-       struct hostent *h;
+       struct addrinfo hints, *res;
        struct netent *ne = NULL;
        char namebuf[100];      /* enough for most DNS names */
        const char *cp;
        char *p = namebuf;
+       unsigned char *addr = NULL;
        size_t n;
+       int error;
+       err_t err = NULL;
 
        for (cp = src, n = srclen; n > 0; cp++, n--)
                if (ISASCII(*cp) && strchr(namechars, *cp) == NULL)
@@ -181,25 +184,40 @@ ip_address *dst;
                cp = (const char *)p;
        }
 
-       h = gethostbyname2(cp, af);
-       if (h == NULL && af == AF_INET)
-               ne = getnetbyname(cp);
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = af;
+       error = getaddrinfo(cp, NULL, &hints, &res);
+       if (error != 0)
+       {       /* getaddrinfo failed, try getnetbyname */
+               if (af == AF_INET)
+               {
+                       ne = getnetbyname(cp);
+                       if (ne != NULL)
+                       {
+                               ne->n_net = htonl(ne->n_net);
+                               addr = (unsigned char*)&ne->n_net;
+                               err = initaddr(addr, sizeof(ne->n_net), af, dst);
+                       }
+               }
+       }
+       else
+       {
+               addr = res->ai_addr->sa_data;
+               err = initaddr(addr, res->ai_addrlen, af, dst);
+               freeaddrinfo(res);
+       }
+
        if (p != namebuf)
+       {
                FREE(p);
-       if (h == NULL && ne == NULL)
-               return "does not look numeric and name lookup failed";
+       }
 
-       if (h != NULL) {
-               if (h->h_addrtype != af)
-                       return "address-type mismatch from gethostbyname2!!!";
-               return initaddr((unsigned char *)h->h_addr, h->h_length, af, dst);
-       } else {
-               if (ne->n_addrtype != af)
-                       return "address-type mismatch from getnetbyname!!!";
-               ne->n_net = htonl(ne->n_net);
-               return initaddr((unsigned char *)&ne->n_net, sizeof(ne->n_net),
-                                                               af, dst);
+       if (addr == NULL)
+       {
+               return "does not look numeric and name lookup failed";
        }
+
+       return err;
 }
 
 /*
index 484de5e..661bec3 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #define _GNU_SOURCE
+#include <sys/socket.h>
 #include <netdb.h>
 #include <string.h>
 
@@ -433,16 +434,40 @@ host_t *host_create_from_string(char *string, u_int16_t port)
 /*
  * Described in header.
  */
+host_t *host_create_from_sockaddr(sockaddr_t *sockaddr)
+{
+       private_host_t *this = host_create_empty();
+       
+       switch (sockaddr->sa_family)
+       {
+               case AF_INET:
+               {
+                       memcpy(&this->address4, sockaddr, sizeof(struct sockaddr_in));
+                       this->socklen = sizeof(struct sockaddr_in);
+                       return &this->public;
+               }
+               case AF_INET6:
+               {
+                       memcpy(&this->address6, sockaddr, sizeof(struct sockaddr_in6));
+                       this->socklen = sizeof(struct sockaddr_in6);
+                       return &this->public;
+               }
+               default:
+                       break;
+       }
+       free(this);
+       return NULL;
+}
+
+/*
+ * Described in header.
+ */
 host_t *host_create_from_dns(char *string, int af, u_int16_t port)
 {
        private_host_t *this;
-       struct hostent *ptr;
-       int ret = 0, err;
-#ifdef HAVE_GETHOSTBYNAME_R
-       struct hostent host;
-       char buf[512];
-#endif
-
+       struct addrinfo hints, *result;
+       int error;
+       
        if (streq(string, "%any"))
        {
                return host_create_any_port(af ? af : AF_INET, port);
@@ -451,62 +476,32 @@ host_t *host_create_from_dns(char *string, int af, u_int16_t port)
        {
                return host_create_any_port(af ? af : AF_INET6, port);
        }
-       else if (strchr(string, ':'))
-       {
-               /* gethostbyname does not like IPv6 addresses - fallback */
-               return host_create_from_string(string, port);
-       }
-
-#ifdef HAVE_GETHOSTBYNAME_R
-       if (af)
-       {
-               ret = gethostbyname2_r(string, af, &host, buf, sizeof(buf), &ptr, &err);
-       }
-       else
-       {
-               ret = gethostbyname_r(string, &host, buf, sizeof(buf), &ptr, &err);
-       }
-#else
-       /* Some systems (e.g. Mac OS X) do not support gethostbyname_r */
-       if (af)
-       {
-               ptr = gethostbyname2(string, af);
-       }
-       else
-       {
-               ptr = gethostbyname(string);
-       }
-       if (ptr == NULL)
-       {
-               err = h_errno;
-       }
-#endif
-       if (ret != 0 || ptr == NULL)
+       
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = af;
+       error = getaddrinfo(string, NULL, &hints, &result);
+       if (error != 0)
        {
-               DBG1("resolving '%s' failed: %s", string, hstrerror(err));
+               DBG1("resolving '%s' failed: %s", string, gai_strerror(error));
                return NULL;
        }
-       this = host_create_empty();
-       this->address.sa_family = ptr->h_addrtype;
-       switch (this->address.sa_family)
+       /* result is a linked list, but we use only the first address */
+       this = (private_host_t*)host_create_from_sockaddr(result->ai_addr);
+       freeaddrinfo(result);
+       if (this)
        {
-               case AF_INET:
-                       memcpy(&this->address4.sin_addr.s_addr,
-                                  ptr->h_addr_list[0], ptr->h_length);
-                       this->address4.sin_port = htons(port);
-                       this->socklen = sizeof(struct sockaddr_in);
-                       break;
-               case AF_INET6:
-                       memcpy(&this->address6.sin6_addr.s6_addr,
-                                  ptr->h_addr_list[0], ptr->h_length);
-                       this->address6.sin6_port = htons(port);
-                       this->socklen = sizeof(struct sockaddr_in6);
-                       break;
-               default:
-                       free(this);
-                       return NULL;
+               switch (this->address.sa_family)
+               {
+                       case AF_INET:
+                               this->address4.sin_port = htons(port);
+                               break;
+                       case AF_INET6:
+                               this->address6.sin6_port = htons(port);
+                               break;
+               }
+               return &this->public;
        }
-       return &this->public;
+       return NULL;
 }
 
 /*
@@ -569,34 +564,6 @@ host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port)
 /*
  * Described in header.
  */
-host_t *host_create_from_sockaddr(sockaddr_t *sockaddr)
-{
-       private_host_t *this = host_create_empty();
-       
-       switch (sockaddr->sa_family)
-       {
-               case AF_INET:
-               {
-                       memcpy(&this->address4, sockaddr, sizeof(struct sockaddr_in));
-                       this->socklen = sizeof(struct sockaddr_in);
-                       return &this->public;
-               }
-               case AF_INET6:
-               {
-                       memcpy(&this->address6, sockaddr, sizeof(struct sockaddr_in6));
-                       this->socklen = sizeof(struct sockaddr_in6);
-                       return &this->public;
-               }
-               default:
-                       break;
-       }
-       free(this);
-       return NULL;
-}
-
-/*
- * Described in header.
- */
 host_t *host_create_any(int family)
 {
        private_host_t *this = host_create_empty();