Add getaddrinfo() for those without it, written by Russ Allbery
This commit is contained in:
2
MANIFEST
2
MANIFEST
@@ -26,6 +26,8 @@ compat/dlfcn.h
|
||||
compat/dlopen.c
|
||||
compat/fnmatch.c
|
||||
compat/fnmatch.h
|
||||
compat/getaddrinfo.c
|
||||
compat/getaddrinfo.h
|
||||
compat/getcwd.c
|
||||
compat/getgrouplist.c
|
||||
compat/getline.c
|
||||
|
2
aclocal.m4
vendored
2
aclocal.m4
vendored
@@ -211,7 +211,7 @@ dnl check for sa_len field in struct sockaddr
|
||||
dnl
|
||||
AC_DEFUN([SUDO_SOCK_SA_LEN], [
|
||||
AC_CHECK_MEMBER([struct sockaddr.sa_len],
|
||||
[AC_DEFINE(HAVE_SA_LEN, 1, [Define if your struct sockadr has an sa_len field.])],
|
||||
[AC_DEFINE(HAVE_STRUCT_SOCKADDR_SA_LEN, 1, [Define if your struct sockadr has an sa_len field.])],
|
||||
[],
|
||||
[ #include <sys/types.h>
|
||||
#include <sys/socket.h>]
|
||||
|
436
compat/getaddrinfo.c
Normal file
436
compat/getaddrinfo.c
Normal file
@@ -0,0 +1,436 @@
|
||||
/*
|
||||
* Replacement for a missing getaddrinfo.
|
||||
*
|
||||
* This is an implementation of getaddrinfo for systems that don't have one so
|
||||
* that networking code can use a consistant interface without #ifdef. It is
|
||||
* a fairly minimal implementation, with the following limitations:
|
||||
*
|
||||
* - IPv4 support only. IPv6 is not supported.
|
||||
* - AI_ADDRCONFIG is ignored.
|
||||
* - Not thread-safe due to gethostbyname and getservbyname.
|
||||
* - SOCK_DGRAM and SOCK_STREAM only.
|
||||
* - Multiple possible socket types only generate one addrinfo struct.
|
||||
* - Protocol hints aren't used correctly.
|
||||
*
|
||||
* The last four issues could probably be easily remedied, but haven't been
|
||||
* needed to date. Adding IPv6 support isn't worth it; systems with IPv6
|
||||
* support should already support getaddrinfo natively.
|
||||
*
|
||||
* The canonical version of this file is maintained in the rra-c-util package,
|
||||
* which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
|
||||
*
|
||||
* Written by Russ Allbery <rra@stanford.edu>
|
||||
*
|
||||
* The authors hereby relinquish any claim to any copyright that they may have
|
||||
* in this work, whether granted under contract or by operation of law or
|
||||
* international treaty, and hereby commit to the public, at large, that they
|
||||
* shall not, at any time in the future, seek to enforce any copyright in this
|
||||
* work against any person or entity, or prevent any person or entity from
|
||||
* copying, publishing, distributing or creating derivative works of this
|
||||
* work.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
# include <stddef.h>
|
||||
#else
|
||||
# ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#endif /* STDC_HEADERS */
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif /* HAVE_STRING_H */
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif /* HAVE_STRINGS_H */
|
||||
#include <netdb.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "compat/getaddrinfo.h"
|
||||
|
||||
/* We need access to h_errno to map errors from gethostbyname. */
|
||||
#if !HAVE_DECL_H_ERRNO
|
||||
extern int h_errno;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The netdb constants, which aren't always defined (particularly if h_errno
|
||||
* isn't declared). We also make sure that a few of the less-used ones are
|
||||
* defined so that we can deal with them in case statements.
|
||||
*/
|
||||
#ifndef HOST_NOT_FOUND
|
||||
# define HOST_NOT_FOUND 1
|
||||
# define TRY_AGAIN 2
|
||||
# define NO_RECOVERY 3
|
||||
# define NO_DATA 4
|
||||
#endif
|
||||
#ifndef NETDB_INTERNAL
|
||||
# define NETDB_INTERNAL -1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If we're running the test suite, rename the functions to avoid conflicts
|
||||
* with the system version. Note that we don't rename the structures and
|
||||
* constants, but that should be okay (except possibly for gai_strerror).
|
||||
*/
|
||||
#if TESTING
|
||||
# define gai_strerror test_gai_strerror
|
||||
# define freeaddrinfo test_freeaddrinfo
|
||||
# define getaddrinfo test_getaddrinfo
|
||||
const char *test_gai_strerror(int);
|
||||
void test_freeaddrinfo(struct addrinfo *);
|
||||
int test_getaddrinfo(const char *, const char *, const struct addrinfo *,
|
||||
struct addrinfo **);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If the native platform doesn't support AI_NUMERICSERV or AI_NUMERICHOST,
|
||||
* pick some other values for them.
|
||||
*/
|
||||
#if TESTING
|
||||
# if AI_NUMERICSERV == 0
|
||||
# undef AI_NUMERICSERV
|
||||
# define AI_NUMERICSERV 0x0080
|
||||
# endif
|
||||
# if AI_NUMERICHOST == 0
|
||||
# undef AI_NUMERICHOST
|
||||
# define AI_NUMERICHOST 0x0100
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Value representing all of the hint flags set. Linux uses flags up to
|
||||
* 0x0400, so be sure not to break when testing on that platform.
|
||||
*/
|
||||
#if TESTING
|
||||
# ifdef HAVE_GETADDRINFO
|
||||
# define AI_INTERNAL_ALL 0x04ff
|
||||
# else
|
||||
# define AI_INTERNAL_ALL 0x01ff
|
||||
# endif
|
||||
#else
|
||||
# define AI_INTERNAL_ALL 0x007f
|
||||
#endif
|
||||
|
||||
/* Table of strings corresponding to the EAI_* error codes. */
|
||||
static const char * const gai_errors[] = {
|
||||
"Host name lookup failure", /* 1 EAI_AGAIN */
|
||||
"Invalid flag value", /* 2 EAI_BADFLAGS */
|
||||
"Unknown server error", /* 3 EAI_FAIL */
|
||||
"Unsupported address family", /* 4 EAI_FAMILY */
|
||||
"Memory allocation failure", /* 5 EAI_MEMORY */
|
||||
"Host unknown or not given", /* 6 EAI_NONAME */
|
||||
"Service not supported for socket", /* 7 EAI_SERVICE */
|
||||
"Unsupported socket type", /* 8 EAI_SOCKTYPE */
|
||||
"System error", /* 9 EAI_SYSTEM */
|
||||
"Supplied buffer too small", /* 10 EAI_OVERFLOW */
|
||||
};
|
||||
|
||||
/* Macro to set the len attribute of sockaddr_in. */
|
||||
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
|
||||
# define sin_set_length(s) ((s)->sin_len = sizeof(struct sockaddr_in))
|
||||
#else
|
||||
# define sin_set_length(s) /* empty */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Used for iterating through arrays. ARRAY_SIZE returns the number of
|
||||
* elements in the array (useful for a < upper bound in a for loop).
|
||||
*/
|
||||
#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
|
||||
|
||||
|
||||
/*
|
||||
* Return a constant string for a given EAI_* error code or a string
|
||||
* indicating an unknown error.
|
||||
*/
|
||||
const char *
|
||||
gai_strerror(int ecode)
|
||||
{
|
||||
if (ecode < 1 || (size_t) ecode > ARRAY_SIZE(gai_errors))
|
||||
return "Unknown error";
|
||||
else
|
||||
return gai_errors[ecode - 1];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Free a linked list of addrinfo structs.
|
||||
*/
|
||||
void
|
||||
freeaddrinfo(struct addrinfo *ai)
|
||||
{
|
||||
struct addrinfo *next;
|
||||
|
||||
while (ai != NULL) {
|
||||
next = ai->ai_next;
|
||||
if (ai->ai_addr != NULL)
|
||||
free(ai->ai_addr);
|
||||
if (ai->ai_canonname != NULL)
|
||||
free(ai->ai_canonname);
|
||||
free(ai);
|
||||
ai = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert a numeric service string to a number with error checking, returning
|
||||
* true if the number was parsed correctly and false otherwise. Stores the
|
||||
* converted number in the second argument. Equivalent to calling strtol, but
|
||||
* with the base always fixed at 10, with checking of errno, ensuring that all
|
||||
* of the string is consumed, and checking that the resulting number is
|
||||
* positive.
|
||||
*/
|
||||
static int
|
||||
convert_service(const char *string, long *result)
|
||||
{
|
||||
char *end;
|
||||
|
||||
if (*string == '\0')
|
||||
return 0;
|
||||
errno = 0;
|
||||
*result = strtol(string, &end, 10);
|
||||
if (errno != 0 || *end != '\0' || *result < 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Allocate a new addrinfo struct, setting some defaults given that this
|
||||
* implementation is IPv4 only. Also allocates an attached sockaddr_in and
|
||||
* zeroes it, per the requirement for getaddrinfo. Takes the socktype,
|
||||
* canonical name (which is copied if not NULL), address, and port. Returns
|
||||
* NULL on a memory allocation failure.
|
||||
*/
|
||||
static struct addrinfo *
|
||||
gai_addrinfo_new(int socktype, const char *canonical, struct in_addr addr,
|
||||
unsigned short port)
|
||||
{
|
||||
struct addrinfo *ai;
|
||||
|
||||
ai = malloc(sizeof(*ai));
|
||||
if (ai == NULL)
|
||||
return NULL;
|
||||
ai->ai_addr = malloc(sizeof(struct sockaddr_in));
|
||||
if (ai->ai_addr == NULL) {
|
||||
free(ai);
|
||||
return NULL;
|
||||
}
|
||||
ai->ai_next = NULL;
|
||||
if (canonical == NULL)
|
||||
ai->ai_canonname = NULL;
|
||||
else {
|
||||
ai->ai_canonname = strdup(canonical);
|
||||
if (ai->ai_canonname == NULL) {
|
||||
freeaddrinfo(ai);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
memset(ai->ai_addr, 0, sizeof(struct sockaddr_in));
|
||||
ai->ai_flags = 0;
|
||||
ai->ai_family = AF_INET;
|
||||
ai->ai_socktype = socktype;
|
||||
ai->ai_protocol = (socktype == SOCK_DGRAM) ? IPPROTO_UDP : IPPROTO_TCP;
|
||||
ai->ai_addrlen = sizeof(struct sockaddr_in);
|
||||
((struct sockaddr_in *) ai->ai_addr)->sin_family = AF_INET;
|
||||
((struct sockaddr_in *) ai->ai_addr)->sin_addr = addr;
|
||||
((struct sockaddr_in *) ai->ai_addr)->sin_port = htons(port);
|
||||
sin_set_length((struct sockaddr_in *) ai->ai_addr);
|
||||
return ai;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Look up a service. Takes the service name (which may be numeric), the hint
|
||||
* flags, a pointer to the socket type (used to determine whether TCP or UDP
|
||||
* services are of interest and, if 0, is filled in with the result of
|
||||
* getservbyname if the service was not numeric), and a pointer to the
|
||||
* addrinfo struct to fill in. Returns 0 on success or an EAI_* error on
|
||||
* failure.
|
||||
*/
|
||||
static int
|
||||
gai_service(const char *servname, int flags, int *type, unsigned short *port)
|
||||
{
|
||||
struct servent *servent;
|
||||
const char *protocol;
|
||||
long value;
|
||||
|
||||
if (convert_service(servname, &value)) {
|
||||
if (value > (1L << 16) - 1)
|
||||
return EAI_SERVICE;
|
||||
*port = value;
|
||||
} else {
|
||||
if (flags & AI_NUMERICSERV)
|
||||
return EAI_NONAME;
|
||||
if (*type != 0)
|
||||
protocol = (*type == SOCK_DGRAM) ? "udp" : "tcp";
|
||||
else
|
||||
protocol = NULL;
|
||||
|
||||
/*
|
||||
* We really technically should be generating an addrinfo struct for
|
||||
* each possible protocol unless type is set, but this works well
|
||||
* enough for what I need this for.
|
||||
*/
|
||||
servent = getservbyname(servname, protocol);
|
||||
if (servent == NULL)
|
||||
return EAI_NONAME;
|
||||
if (strcmp(servent->s_proto, "udp") == 0)
|
||||
*type = SOCK_DGRAM;
|
||||
else if (strcmp(servent->s_proto, "tcp") == 0)
|
||||
*type = SOCK_STREAM;
|
||||
else
|
||||
return EAI_SERVICE;
|
||||
*port = htons(servent->s_port);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Look up a host and fill in a linked list of addrinfo structs with the
|
||||
* results, one per IP address of the returned host. Takes the name or IP
|
||||
* address of the host as a string, the lookup flags, the type of socket (to
|
||||
* fill into the addrinfo structs), the port (likewise), and a pointer to
|
||||
* where the head of the linked list should be put. Returns 0 on success or
|
||||
* the appropriate EAI_* error.
|
||||
*/
|
||||
static int
|
||||
gai_lookup(const char *nodename, int flags, int socktype, unsigned short port,
|
||||
struct addrinfo **res)
|
||||
{
|
||||
struct addrinfo *ai, *first, *prev;
|
||||
struct in_addr addr;
|
||||
struct hostent *host;
|
||||
const char *canonical;
|
||||
int i;
|
||||
|
||||
if (inet_aton(nodename, &addr)) {
|
||||
canonical = (flags & AI_CANONNAME) ? nodename : NULL;
|
||||
ai = gai_addrinfo_new(socktype, canonical, addr, port);
|
||||
if (ai == NULL)
|
||||
return EAI_MEMORY;
|
||||
*res = ai;
|
||||
return 0;
|
||||
} else {
|
||||
if (flags & AI_NUMERICHOST)
|
||||
return EAI_NONAME;
|
||||
host = gethostbyname(nodename);
|
||||
if (host == NULL)
|
||||
switch (h_errno) {
|
||||
case HOST_NOT_FOUND:
|
||||
return EAI_NONAME;
|
||||
case TRY_AGAIN:
|
||||
case NO_DATA:
|
||||
return EAI_AGAIN;
|
||||
case NO_RECOVERY:
|
||||
return EAI_FAIL;
|
||||
case NETDB_INTERNAL:
|
||||
default:
|
||||
return EAI_SYSTEM;
|
||||
}
|
||||
if (host->h_addr_list[0] == NULL)
|
||||
return EAI_FAIL;
|
||||
canonical = (flags & AI_CANONNAME)
|
||||
? ((host->h_name != NULL) ? host->h_name : nodename)
|
||||
: NULL;
|
||||
first = NULL;
|
||||
prev = NULL;
|
||||
for (i = 0; host->h_addr_list[i] != NULL; i++) {
|
||||
if (host->h_length != sizeof(addr)) {
|
||||
freeaddrinfo(first);
|
||||
return EAI_FAIL;
|
||||
}
|
||||
memcpy(&addr, host->h_addr_list[i], sizeof(addr));
|
||||
ai = gai_addrinfo_new(socktype, canonical, addr, port);
|
||||
if (ai == NULL) {
|
||||
freeaddrinfo(first);
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
if (first == NULL) {
|
||||
first = ai;
|
||||
prev = ai;
|
||||
} else {
|
||||
prev->ai_next = ai;
|
||||
prev = ai;
|
||||
}
|
||||
}
|
||||
*res = first;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The actual getaddrinfo implementation.
|
||||
*/
|
||||
int
|
||||
getaddrinfo(const char *nodename, const char *servname,
|
||||
const struct addrinfo *hints, struct addrinfo **res)
|
||||
{
|
||||
struct addrinfo *ai;
|
||||
struct in_addr addr;
|
||||
int flags, socktype, status;
|
||||
unsigned short port;
|
||||
|
||||
/* Take the hints into account and check them for validity. */
|
||||
if (hints != NULL) {
|
||||
flags = hints->ai_flags;
|
||||
socktype = hints->ai_socktype;
|
||||
if ((flags & AI_INTERNAL_ALL) != flags)
|
||||
return EAI_BADFLAGS;
|
||||
if (hints->ai_family != AF_UNSPEC && hints->ai_family != AF_INET)
|
||||
return EAI_FAMILY;
|
||||
if (socktype != 0 && socktype != SOCK_STREAM && socktype != SOCK_DGRAM)
|
||||
return EAI_SOCKTYPE;
|
||||
|
||||
/* EAI_SOCKTYPE isn't quite right, but there isn't anything better. */
|
||||
if (hints->ai_protocol != 0) {
|
||||
int protocol = hints->ai_protocol;
|
||||
if (protocol != IPPROTO_TCP && protocol != IPPROTO_UDP)
|
||||
return EAI_SOCKTYPE;
|
||||
}
|
||||
} else {
|
||||
flags = 0;
|
||||
socktype = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* See what we're doing. If nodename is null, either AI_PASSIVE is set or
|
||||
* we're getting information for connecting to a service on the loopback
|
||||
* address. Otherwise, we're getting information for connecting to a
|
||||
* remote system.
|
||||
*/
|
||||
if (servname == NULL)
|
||||
port = 0;
|
||||
else {
|
||||
status = gai_service(servname, flags, &socktype, &port);
|
||||
if (status != 0)
|
||||
return status;
|
||||
}
|
||||
if (nodename != NULL)
|
||||
return gai_lookup(nodename, flags, socktype, port, res);
|
||||
else {
|
||||
if (servname == NULL)
|
||||
return EAI_NONAME;
|
||||
if ((flags & AI_PASSIVE) == AI_PASSIVE)
|
||||
addr.s_addr = INADDR_ANY;
|
||||
else
|
||||
addr.s_addr = htonl(0x7f000001UL);
|
||||
ai = gai_addrinfo_new(socktype, NULL, addr, port);
|
||||
if (ai == NULL)
|
||||
return EAI_MEMORY;
|
||||
*res = ai;
|
||||
return 0;
|
||||
}
|
||||
}
|
75
compat/getaddrinfo.h
Normal file
75
compat/getaddrinfo.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Replacement implementation of getaddrinfo.
|
||||
*
|
||||
* This is an implementation of the getaddrinfo family of functions for
|
||||
* systems that lack it, so that code can use getaddrinfo always. It provides
|
||||
* IPv4 support only; for IPv6 support, a native getaddrinfo implemenation is
|
||||
* required.
|
||||
*
|
||||
* The canonical version of this file is maintained in the rra-c-util package,
|
||||
* which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
|
||||
*
|
||||
* Written by Russ Allbery <rra@stanford.edu>
|
||||
*
|
||||
* The authors hereby relinquish any claim to any copyright that they may have
|
||||
* in this work, whether granted under contract or by operation of law or
|
||||
* international treaty, and hereby commit to the public, at large, that they
|
||||
* shall not, at any time in the future, seek to enforce any copyright in this
|
||||
* work against any person or entity, or prevent any person or entity from
|
||||
* copying, publishing, distributing or creating derivative works of this
|
||||
* work.
|
||||
*/
|
||||
|
||||
#ifndef _COMPAT_GETADDRINFO_H
|
||||
#define _COMPAT_GETADDRINFO_H
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Skip this entire file if a system getaddrinfo was detected. */
|
||||
#ifndef HAVE_GETADDRINFO
|
||||
|
||||
/* OpenBSD likes to have sys/types.h included before sys/socket.h. */
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
/* The struct returned by getaddrinfo, from RFC 3493. */
|
||||
struct addrinfo {
|
||||
int ai_flags; /* AI_PASSIVE, AI_CANONNAME, .. */
|
||||
int ai_family; /* AF_xxx */
|
||||
int ai_socktype; /* SOCK_xxx */
|
||||
int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
|
||||
socklen_t ai_addrlen; /* Length of ai_addr */
|
||||
char *ai_canonname; /* Canonical name for nodename */
|
||||
struct sockaddr *ai_addr; /* Binary address */
|
||||
struct addrinfo *ai_next; /* Next structure in linked list */
|
||||
};
|
||||
|
||||
/* Constants for ai_flags from RFC 3493, combined with binary or. */
|
||||
#define AI_PASSIVE 0x0001
|
||||
#define AI_CANONNAME 0x0002
|
||||
#define AI_NUMERICHOST 0x0004
|
||||
#define AI_NUMERICSERV 0x0008
|
||||
#define AI_V4MAPPED 0x0010
|
||||
#define AI_ALL 0x0020
|
||||
#define AI_ADDRCONFIG 0x0040
|
||||
|
||||
/* Error return codes from RFC 3493. */
|
||||
#define EAI_AGAIN 1 /* Temporary name resolution failure */
|
||||
#define EAI_BADFLAGS 2 /* Invalid value in ai_flags parameter */
|
||||
#define EAI_FAIL 3 /* Permanent name resolution failure */
|
||||
#define EAI_FAMILY 4 /* Address family not recognized */
|
||||
#define EAI_MEMORY 5 /* Memory allocation failure */
|
||||
#define EAI_NONAME 6 /* nodename or servname unknown */
|
||||
#define EAI_SERVICE 7 /* Service not recognized for socket type */
|
||||
#define EAI_SOCKTYPE 8 /* Socket type not recognized */
|
||||
#define EAI_SYSTEM 9 /* System error occurred, see errno */
|
||||
#define EAI_OVERFLOW 10 /* An argument buffer overflowed */
|
||||
|
||||
/* Function prototypes. */
|
||||
int getaddrinfo(const char *nodename, const char *servname,
|
||||
const struct addrinfo *hints, struct addrinfo **res);
|
||||
void freeaddrinfo(struct addrinfo *ai);
|
||||
const char *gai_strerror(int ecode);
|
||||
|
||||
#endif /* !HAVE_GETADDRINFO */
|
||||
#endif /* _COMPAT_GETADDRINFO_H */
|
10
config.h.in
10
config.h.in
@@ -83,6 +83,10 @@
|
||||
*/
|
||||
#undef HAVE_DECL_ERRNO
|
||||
|
||||
/* Define to 1 if you have the declaration of `h_errno', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_H_ERRNO
|
||||
|
||||
/* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_SYS_SIGLIST
|
||||
@@ -411,9 +415,6 @@
|
||||
/* Define to 1 if you have the <sasl/sasl.h> header file. */
|
||||
#undef HAVE_SASL_SASL_H
|
||||
|
||||
/* Define if your struct sockadr has an sa_len field. */
|
||||
#undef HAVE_SA_LEN
|
||||
|
||||
/* Define to 1 if you use SecurID for authentication. */
|
||||
#undef HAVE_SECURID
|
||||
|
||||
@@ -501,6 +502,9 @@
|
||||
/* Define to 1 if the system has the type `struct in6_addr'. */
|
||||
#undef HAVE_STRUCT_IN6_ADDR
|
||||
|
||||
/* Define if your struct sockadr has an sa_len field. */
|
||||
#undef HAVE_STRUCT_SOCKADDR_SA_LEN
|
||||
|
||||
/* Define to 1 if the system has the type `struct timespec'. */
|
||||
#undef HAVE_STRUCT_TIMESPEC
|
||||
|
||||
|
33
configure
vendored
33
configure
vendored
@@ -15847,7 +15847,7 @@ _ACEOF
|
||||
"
|
||||
if test "x$ac_cv_member_struct_sockaddr_sa_len" = xyes; then :
|
||||
|
||||
$as_echo "#define HAVE_SA_LEN 1" >>confdefs.h
|
||||
$as_echo "#define HAVE_STRUCT_SOCKADDR_SA_LEN 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
@@ -16221,7 +16221,7 @@ fi
|
||||
LIBS=$ac_save_LIBS
|
||||
|
||||
for ac_func in strrchr sysconf tzset strftime \
|
||||
regcomp setlocale nl_langinfo getaddrinfo mbr_check_membership \
|
||||
regcomp setlocale nl_langinfo mbr_check_membership \
|
||||
setrlimit64 sysctl
|
||||
do :
|
||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
@@ -16813,6 +16813,19 @@ esac
|
||||
|
||||
fi
|
||||
|
||||
ac_fn_c_check_func "$LINENO" "getaddrinfo" "ac_cv_func_getaddrinfo"
|
||||
if test "x$ac_cv_func_getaddrinfo" = xyes; then :
|
||||
$as_echo "#define HAVE_GETADDRINFO 1" >>confdefs.h
|
||||
|
||||
else
|
||||
case " $LIBOBJS " in
|
||||
*" getaddrinfo.$ac_objext "* ) ;;
|
||||
*) LIBOBJS="$LIBOBJS getaddrinfo.$ac_objext"
|
||||
;;
|
||||
esac
|
||||
|
||||
fi
|
||||
|
||||
ac_fn_c_check_func "$LINENO" "memrchr" "ac_cv_func_memrchr"
|
||||
if test "x$ac_cv_func_memrchr" = xyes; then :
|
||||
$as_echo "#define HAVE_MEMRCHR 1" >>confdefs.h
|
||||
@@ -17795,6 +17808,22 @@ cat >>confdefs.h <<_ACEOF
|
||||
_ACEOF
|
||||
|
||||
|
||||
ac_fn_c_check_decl "$LINENO" "h_errno" "ac_cv_have_decl_h_errno" "
|
||||
$ac_includes_default
|
||||
#include <netdb.h>
|
||||
|
||||
"
|
||||
if test "x$ac_cv_have_decl_h_errno" = xyes; then :
|
||||
ac_have_decl=1
|
||||
else
|
||||
ac_have_decl=0
|
||||
fi
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_DECL_H_ERRNO $ac_have_decl
|
||||
_ACEOF
|
||||
|
||||
|
||||
for ac_func in strsignal
|
||||
do :
|
||||
ac_fn_c_check_func "$LINENO" "strsignal" "ac_cv_func_strsignal"
|
||||
|
12
configure.in
12
configure.in
@@ -2077,7 +2077,7 @@ dnl Function checks
|
||||
dnl
|
||||
AC_FUNC_GETGROUPS
|
||||
AC_CHECK_FUNCS(strrchr sysconf tzset strftime \
|
||||
regcomp setlocale nl_langinfo getaddrinfo mbr_check_membership \
|
||||
regcomp setlocale nl_langinfo mbr_check_membership \
|
||||
setrlimit64 sysctl)
|
||||
AC_REPLACE_FUNCS(getgrouplist)
|
||||
AC_CHECK_FUNCS(getline, [], [
|
||||
@@ -2137,7 +2137,7 @@ AC_CHECK_FUNCS(utimes, [AC_CHECK_FUNCS(futimes futimesat, [break])], [AC_CHECK_F
|
||||
AC_CHECK_FUNCS(killpg, [], [AC_LIBOBJ(killpg)])
|
||||
SUDO_FUNC_FNMATCH([AC_DEFINE(HAVE_FNMATCH)], [AC_LIBOBJ(fnmatch)])
|
||||
SUDO_FUNC_ISBLANK
|
||||
AC_REPLACE_FUNCS(memrchr strlcpy strlcat setenv)
|
||||
AC_REPLACE_FUNCS(getaddrinfo memrchr strlcpy strlcat setenv)
|
||||
AC_CHECK_FUNCS(nanosleep, [], [
|
||||
# On Solaris, nanosleep is in librt
|
||||
AC_CHECK_LIB(rt, nanosleep, [REPLAY_LIBS="${REPLAY_LIBS} -lrt"], [AC_LIBOBJ(nanosleep)])
|
||||
@@ -2316,6 +2316,14 @@ AC_INCLUDES_DEFAULT
|
||||
#include <errno.h>
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl Check for h_errno declaration in netdb.h
|
||||
dnl
|
||||
AC_CHECK_DECLS([h_errno], [], [], [
|
||||
AC_INCLUDES_DEFAULT
|
||||
#include <netdb.h>
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl Check for strsignal() or sys_siglist
|
||||
dnl
|
||||
|
@@ -76,6 +76,9 @@
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#include <setjmp.h>
|
||||
#ifndef HAVE_GETADDRINFO
|
||||
# include "compat/getaddrinfo.h"
|
||||
#endif
|
||||
|
||||
#include "sudoers.h"
|
||||
#include "interfaces.h"
|
||||
@@ -1050,34 +1053,22 @@ set_loginclass(struct passwd *pw)
|
||||
void
|
||||
set_fqdn(void)
|
||||
{
|
||||
#ifdef HAVE_GETADDRINFO
|
||||
struct addrinfo *res0, hint;
|
||||
#else
|
||||
struct hostent *hp;
|
||||
#endif
|
||||
char *p;
|
||||
debug_decl(set_fqdn, SUDO_DEBUG_PLUGIN)
|
||||
|
||||
#ifdef HAVE_GETADDRINFO
|
||||
zero_bytes(&hint, sizeof(hint));
|
||||
hint.ai_family = PF_UNSPEC;
|
||||
hint.ai_flags = AI_CANONNAME;
|
||||
if (getaddrinfo(user_host, NULL, &hint, &res0) != 0) {
|
||||
#else
|
||||
if (!(hp = gethostbyname(user_host))) {
|
||||
#endif
|
||||
log_error(MSG_ONLY|NO_EXIT,
|
||||
_("unable to resolve host %s"), user_host);
|
||||
} else {
|
||||
if (user_shost != user_host)
|
||||
efree(user_shost);
|
||||
efree(user_host);
|
||||
#ifdef HAVE_GETADDRINFO
|
||||
user_host = estrdup(res0->ai_canonname);
|
||||
freeaddrinfo(res0);
|
||||
#else
|
||||
user_host = estrdup(hp->h_name);
|
||||
#endif
|
||||
}
|
||||
if ((p = strchr(user_host, '.')) != NULL)
|
||||
user_shost = estrndup(user_host, (size_t)(p - user_host));
|
||||
|
@@ -264,10 +264,10 @@ get_net_ifs(char **addrinfo)
|
||||
|
||||
/* Set i to the subscript of the next interface. */
|
||||
i += sizeof(struct ifreq);
|
||||
#ifdef HAVE_SA_LEN
|
||||
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
|
||||
if (ifr->ifr_addr.sa_len > sizeof(ifr->ifr_addr))
|
||||
i += ifr->ifr_addr.sa_len - sizeof(struct sockaddr);
|
||||
#endif /* HAVE_SA_LEN */
|
||||
#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
|
||||
|
||||
/* Skip duplicates and interfaces with NULL addresses. */
|
||||
sin = (struct sockaddr_in *) &ifr->ifr_addr;
|
||||
|
Reference in New Issue
Block a user