diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libfreeswan/atoaddr.3 | 10 | ||||
-rw-r--r-- | src/libfreeswan/atoaddr.c | 36 | ||||
-rw-r--r-- | src/libfreeswan/ttoaddr.3 | 12 | ||||
-rw-r--r-- | src/libfreeswan/ttoaddr.c | 50 | ||||
-rw-r--r-- | src/libstrongswan/utils/host.c | 139 |
5 files changed, 123 insertions, 124 deletions
diff --git a/src/libfreeswan/atoaddr.3 b/src/libfreeswan/atoaddr.3 index fce8884e4..10da2691c 100644 --- a/src/libfreeswan/atoaddr.3 +++ b/src/libfreeswan/atoaddr.3 @@ -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. diff --git a/src/libfreeswan/atoaddr.c b/src/libfreeswan/atoaddr.c index dd73be7f3..c962a1627 100644 --- a/src/libfreeswan/atoaddr.c +++ b/src/libfreeswan/atoaddr.c @@ -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; } diff --git a/src/libfreeswan/ttoaddr.3 b/src/libfreeswan/ttoaddr.3 index 70671145e..d43d2b16f 100644 --- a/src/libfreeswan/ttoaddr.3 +++ b/src/libfreeswan/ttoaddr.3 @@ -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. diff --git a/src/libfreeswan/ttoaddr.c b/src/libfreeswan/ttoaddr.c index e4ceec863..ede0713f0 100644 --- a/src/libfreeswan/ttoaddr.c +++ b/src/libfreeswan/ttoaddr.c @@ -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; } /* diff --git a/src/libstrongswan/utils/host.c b/src/libstrongswan/utils/host.c index 484de5e54..661bec315 100644 --- a/src/libstrongswan/utils/host.c +++ b/src/libstrongswan/utils/host.c @@ -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(); |