Replacing gethostbyname, gethostbyname2 and their _r variants with getaddrinfo to increase portability.
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -430,19 +431,43 @@ host_t *host_create_from_string(char *string, u_int16_t port)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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, ':'))
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = af;
|
||||
error = getaddrinfo(string, NULL, &hints, &result);
|
||||
if (error != 0)
|
||||
{
|
||||
/* 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -566,34 +561,6 @@ host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port)
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user