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