]> granicus.if.org Git - sudo/commitdiff
Add getaddrinfo() for those without it, written by Russ Allbery
authorTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 2 Dec 2011 22:28:50 +0000 (17:28 -0500)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 2 Dec 2011 22:28:50 +0000 (17:28 -0500)
MANIFEST
aclocal.m4
compat/getaddrinfo.c [new file with mode: 0644]
compat/getaddrinfo.h [new file with mode: 0644]
config.h.in
configure
configure.in
plugins/sudoers/sudoers.c
src/net_ifs.c

index 632a2b1bd8aec3ca5f0bd56cb2c30d7be477a2e6..e3d6f352a0c01cc8245df6f78fa69b05f05e3a80 100644 (file)
--- a/MANIFEST
+++ b/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
index dcb08e40ce72da48e1d59e2facac3d9a5381b5a8..e446fdb444ca55808146394a031ba51f110262a8 100644 (file)
@@ -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>] 
diff --git a/compat/getaddrinfo.c b/compat/getaddrinfo.c
new file mode 100644 (file)
index 0000000..4698891
--- /dev/null
@@ -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;
+    }
+}
diff --git a/compat/getaddrinfo.h b/compat/getaddrinfo.h
new file mode 100644 (file)
index 0000000..a8a4b69
--- /dev/null
@@ -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 */
index b2163abed12e5e5e5d01f544e3a993ab380caf71..823b6d954945a1819ff1ba0ea2e79b1aa5e92454 100644 (file)
    */
 #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
 /* 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
 
 /* 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
 
index 76a5b4dc663bb8c585aacfafcdfd16a673263463..bae370846de0d4dc6989423d9ac18dd577483517 100755 (executable)
--- a/configure
+++ b/configure
@@ -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"
index d27d355ebb05d937aee7956b53f2f936fbc7ed82..123a2e60713fb556a8255bf631782633277a448b 100644 (file)
@@ -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
index f86a0c673a0c445538ef70f5794e2e5164ae8b6d..3dd6b856b4f039f493a2cc3321ecc575f87487ed 100644 (file)
@@ -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));
index 460d54fff13b3b2c9d1ba69505ad05e0dd46b852..fa8b6760415b327a42018dfb4644e682e8bda9c9 100644 (file)
@@ -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;