Replacing gethostbyname, gethostbyname2 and their _r variants with getaddrinfo to increase portability.

This commit is contained in:
Tobias Brunner
2009-08-14 16:14:32 +02:00
parent 26965b4ef3
commit f1777dff59
6 changed files with 128 additions and 130 deletions
+53 -86
View File
@@ -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.
*/