]> The Tcpdump Group git mirrors - libpcap/commitdiff
Try to make pcap_compile() thread-safer.
authorGuy Harris <[email protected]>
Sun, 28 Jan 2018 07:09:39 +0000 (23:09 -0800)
committerGuy Harris <[email protected]>
Sun, 28 Jan 2018 07:09:39 +0000 (23:09 -0800)
Always use getaddrinfo() for name-to-address lookups; it's the only
portable API that lets you do those lookups in a thread-safe fashion.
This means we require getaddrinfo(); yes, this leaves older OSes out in
the cold - you'd have to provide your own getaddrinfo() on older OSes
that lack it, just as you now will need to provide versions of Flex and
bison/Berkeley YACC that can support reentrant scanners/parsers on older
OSes that lack it, and compilers capable of supporting some C99 features
on older platforms that lack it.

Try to find reentrant versions of getnetbyname() and getprotobyname();
that's a pain, and, if none are found, we'll just have to hope that the
native versions are thread-safe, which they aren't on NetBSD and
OpenBSD.

CMakeLists.txt
aclocal.m4
cmakeconfig.h.in
config.h.in
configure
gencode.c
nametoaddr.c
pcap/namedb.h

index c38af042fbb06e8536b5d295c1d4f49af2cb6847..b47c78ee8f1511501ed6994e90650bb01d4e53c0 100644 (file)
@@ -344,24 +344,188 @@ check_function_exists(vsnprintf HAVE_VSNPRINTF)
 check_function_exists(strtok_r HAVE_STRTOK_R)
 
 #
-# Find library needed for gethostbyname.
+# These tests are for network applications that need socket functions
+# and getaddrinfo()/getnameinfo()-ish functions.  We now require
+# getaddrinfo() and getnameinfo().  We also prefer versions of
+# recvmsg() that conform to the Single UNIX Specification, so that we
+# can check whether a datagram received with recvmsg() was truncated
+# when received due to the buffer being too small.
+#
+# On most operating systems, they're available in the system library.
+#
+# Under Solaris, we need to link with libsocket and libnsl to get
+# getaddrinfo() and getnameinfo() and, if we have libxnet, we need to
+# link with libxnet before libsocket to get a version of recvmsg()
+# that conforms to the Single UNIX Specification.
+#
+# We use getaddrinfo() because we want a portable thread-safe way
+# of getting information for a host name or port; there exist _r
+# versions of gethostbyname() and getservbyname() on some platforms,
+# but not on all platforms.
+#
+# Unfortunately, there's no such portable thread-safe way to translate
+# network names or IP protocol names to values; we look for various
+# getnetbyname_r() and getprotoent_r() APIs.
+#
 # NOTE: if you hand check_library_exists as its last argument a variable
 # that's been set, it skips the test, so we need different variables.
 #
 set(PCAP_LINK_LIBRARIES "")
 include(CheckLibraryExists)
-check_function_exists(gethostbyname STDLIBS_HAVE_GETHOSTBYNAME)
-if(NOT STDLIBS_HAVE_GETHOSTBYNAME)
-    check_library_exists(xnet gethostbyname "" LIBXNET_HAS_GETHOSTBYNAME)
-    if(LIBXNET_HAS_GETHOSTBYNAME)
-        set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} xnet)
-    else()
-        check_library_exists(nsl gethostbyname "" LIBNSL_HAS_GETHOSTBYNAME)
-        if(LIBNSL_HAS_GETHOSTBYNAME)
-            set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} nsl)
-        endif()
-    endif()
-endif()
+check_function_exists(getaddrinfo STDLIBS_HAVE_GETADDRINFO)
+if(NOT STDLIBS_HAVE_GETADDRINFO)
+    #
+    # Not found in the standard system libraries.
+    # Try libsocket, which requires libnsl.
+    #
+    cmake_push_check_state()
+    set(CMAKE_REQUIRED_LIBRARIES nsl)
+    check_library_exists(socket getaddrinfo "" LIBSOCKET_HAS_GETADDRINFO)
+    cmake_pop_check_state()
+    if(LIBSOCKET_HAS_GETADDRINFO)
+        #
+        # OK, we found it in libsocket.
+        #
+        set(PCAP_LINK_LIBRARIES socket nsl ${PCAP_LINK_LIBRARIES})
+    else(LIBSOCKET_HAS_GETADDRINFO)
+        #
+        # We didn't find it.
+        #
+        message(ERROR "getaddrinfo is required, but wasn't found")
+    endif(LIBSOCKET_HAS_GETADDRINFO)
+
+    #
+    # OK, do we have recvmsg() in libxnet?
+    # We also link with libsocket and libnsl.
+    #
+    cmake_push_check_state()
+    set(CMAKE_REQUIRED_LIBRARIES socket nsl)
+    check_library_exists(xnet recvmsg "" LIBXNET_HAS_RECVMSG)
+    cmake_pop_check_state()
+    if(LIBXNET_HAS_RECVMSG)
+        #
+        # Yes - link with it as well.
+        #
+        set(PCAP_LINK_LIBRARIES xnet ${PCAP_LINK_LIBRARIES})
+    endif(LIBXNET_HAS_RECVMSG)
+endif(NOT STDLIBS_HAVE_GETADDRINFO)
+
+# DLPI needs putmsg under HPUX so test for -lstr while we're at it
+check_function_exists(putmsg STDLIBS_HAVE_PUTMSG)
+if(NOT STDLIBS_HAVE_PUTMSG)
+    check_library_exists(str putmsg "" LIBSTR_HAS_PUTMSG)
+    if(LIBSTR_HAS_PUTMSG)
+        set(PCAP_LINK_LIBRARIES str ${PCAP_LINK_LIBRARIES})
+    endif(LIBSTR_HAS_PUTMSG)
+endif(NOT STDLIBS_HAVE_PUTMSG)
+
+
+#
+# Check for reentrant versions of getnetbyname_r(), as provided by
+# Linux (glibc), Solaris/IRIX, and AIX (with three different APIs!).
+# If we don't find one, we just use getnetbyname(), which uses
+# thread-specific data on many platforms, but doesn't use it on
+# NetBSD or OpenBSD, and may not use it on older versions of other
+# platforms.
+#
+check_c_source_compiles(
+"#include <netdb.h>
+
+int
+main(void)
+{
+    struct netent netent_buf;
+    char buf[1024];
+    struct netent *resultp;
+    int h_errnoval;
+
+    return getnetbyname_r(NULL, &netent_buf, buf, sizeof buf, &resultp, &h_errnoval);
+}
+"
+    HAVE_LINUX_GETNETBYNAME_R)
+if(NOT HAVE_LINUX_GETNETBYNAME_R)
+    check_c_source_compiles(
+"#include <netdb.h>
+
+int
+main(void)
+{
+    struct netent netent_buf;
+    char buf[1024];
+
+    return getnetbyname_r(NULL, &netent_buf, buf, (int)sizeof buf) != NULL;
+}
+"
+        HAVE_SOLARIS_IRIX_GETNETBYNAME_R)
+    if(NOT HAVE_SOLARIS_IRIX_GETNETBYNAME_R)
+        check_c_source_compiles(
+"#include <netdb.h>
+
+int
+main(void)
+{
+    struct netent netent_buf;
+    struct netent_data net_data;
+
+    return getnetbyname_r(NULL, &netent_buf, &net_data);
+}
+"
+            HAVE_AIX_GETNETBYNAME_R)
+    endif(NOT HAVE_SOLARIS_IRIX_GETNETBYNAME_R)
+endif(NOT HAVE_LINUX_GETNETBYNAME_R)
+
+#
+# Check for reentrant versions of getprotobyname_r(), as provided by
+# Linux (glibc), Solaris/IRIX, and AIX (with three different APIs!).
+# If we don't find one, we just use getprotobyname(), which uses
+# thread-specific data on many platforms, but doesn't use it on
+# NetBSD or OpenBSD, and may not use it on older versions of other
+# platforms.
+#
+check_c_source_compiles(
+"#include <netdb.h>
+
+int
+main(void)
+{
+    struct protoent protoent_buf;
+    char buf[1024];
+    struct protoent *resultp;
+
+    return getprotobyname_r(NULL, &protoent_buf, buf, sizeof buf, &resultp);
+}
+"
+    HAVE_LINUX_GETPROTOBYNAME_R)
+if(NOT HAVE_LINUX_GETPROTOBYNAME_R)
+    check_c_source_compiles(
+"#include <netdb.h>
+
+int
+main(void)
+{
+    struct protoent protoent_buf;
+    char buf[1024];
+
+    return getprotobyname_r(NULL, &protoent_buf, buf, (int)sizeof buf) != NULL;
+}
+"
+        HAVE_SOLARIS_IRIX_GETPROTOBYNAME_R)
+    if(NOT HAVE_SOLARIS_IRIX_GETPROTOBYNAME_R)
+        check_c_source_compiles(
+"#include <netdb.h>
+
+int
+main(void)
+{
+    struct protoent protoent_buf;
+    struct protoent_data proto_data;
+
+    return getprotobyname_r(NULL, &protoent_buf, &proto_data);
+}
+"
+            HAVE_AIX_GETPROTOBYNAME_R)
+    endif(NOT HAVE_SOLARIS_IRIX_GETPROTOBYNAME_R)
+endif(NOT HAVE_LINUX_GETPROTOBYNAME_R)
 
 #
 # Data types.
@@ -948,7 +1112,7 @@ if(NOT WIN32)
                     set(HAVE_GETIFADDRS TRUE)
                 endif()
             endif()
-       endif()
+        endif()
         if(HAVE_GETIFADDRS)
             #
             # We have "getifaddrs()"; make sure we have <ifaddrs.h>
index 3689f6c8e277a917110d54297ff0a2262b24d421..df6d0dff3f823fc537d708f31f6ed6a3628e4456 100644 (file)
@@ -935,130 +935,194 @@ fi
 dnl
 dnl AC_LBL_LIBRARY_NET
 dnl
-dnl This test is for network applications that need socket() and
-dnl gethostbyname() -ish functions.  Under Solaris, those applications
-dnl need to link with "-lsocket -lnsl".  Under IRIX, they need to link
-dnl with "-lnsl" but should *not* link with "-lsocket" because
-dnl libsocket.a breaks a number of things (for instance:
-dnl gethostbyname() under IRIX 5.2, and snoop sockets under most
-dnl versions of IRIX).
-dnl
-dnl Unfortunately, many application developers are not aware of this,
-dnl and mistakenly write tests that cause -lsocket to be used under
-dnl IRIX.  It is also easy to write tests that cause -lnsl to be used
-dnl under operating systems where neither are necessary (or useful),
-dnl such as SunOS 4.1.4, which uses -lnsl for TLI.
-dnl
-dnl This test exists so that every application developer does not test
-dnl this in a different, and subtly broken fashion.
-
-dnl It has been argued that this test should be broken up into two
-dnl seperate tests, one for the resolver libraries, and one for the
-dnl libraries necessary for using Sockets API. Unfortunately, the two
-dnl are carefully intertwined and allowing the autoconf user to use
-dnl them independantly potentially results in unfortunate ordering
-dnl dependancies -- as such, such component macros would have to
-dnl carefully use indirection and be aware if the other components were
-dnl executed. Since other autoconf macros do not go to this trouble,
-dnl and almost no applications use sockets without the resolver, this
-dnl complexity has not been implemented.
-dnl
-dnl The check for libresolv is in case you are attempting to link
-dnl statically and happen to have a libresolv.a lying around (and no
-dnl libnsl.a).
+dnl This test is for network applications that need socket functions and
+dnl getaddrinfo()/getnameinfo()-ish functions.  We now require
+dnl getaddrinfo() and getnameinfo().  We also prefer versions of
+dnl recvmsg() that conform to the Single UNIX Specification, so that we
+dnl can check whether a datagram received with recvmsg() was truncated
+dnl when received due to the buffer being too small.
+dnl
+dnl On most operating systems, they're available in the system library.
+dnl
+dnl Under Solaris, we need to link with libsocket and libnsl to get
+dnl getaddrinfo() and getnameinfo() and, if we have libxnet, we need to
+dnl link with libxnet before libsocket to get a version of recvmsg()
+dnl that conforms to the Single UNIX Specification.
+dnl
+dnl We use getaddrinfo() because we want a portable thread-safe way
+dnl of getting information for a host name or port; there exist _r
+dnl versions of gethostbyname() and getservbyname() on some platforms,
+dnl but not on all platforms.
+dnl
+dnl Unfortunately, there's no such portable thread-safe way to translate
+dnl network names or IP protocol names to values; we look for various
+dnl getnetbyname_r() and getprotoent_r() APIs.
 dnl
 AC_DEFUN(AC_LBL_LIBRARY_NET, [
     #
-    # Most operating systems have gethostbyname() in the default searched
+    # Most operating systems have getaddrinfo() in the default searched
     # libraries (i.e. libc).  Check there first.
     #
-    AC_CHECK_FUNC(gethostbyname,,
+    AC_CHECK_FUNC(getaddrinfo,,
     [
        #
        # Not found in the standard system libraries.
-       # Some OSes (eg. Solaris) place it in libnsl, but in at least some
-       # versions of Solaris, there are alternate versions of these APIs
-       # in libxnet, and those versions conform to the Single UNIX
-       # Specification, meaning you can actually check for truncation
-       # of incoming datagrams in recvmsg(), so we prefer that.
-       # Some strange OSes (SINIX) have it in libsocket, so try libxneet.
+       # Try libsocket, which requires libnsl.
        #
-       AC_CHECK_LIB(xnet, gethostbyname,
+       AC_CHECK_LIB(socket, getaddrinfo,
        [
            #
-           # OK, we found it in libxnet.
-           # Unfortunately, on some versions of Solaris, getnameinfo()
-           # getaddrinfo(), freeaddrinfo(), and gai_strerror() are *not*
-           # in libxnet, they're only in libsocket.  In that case, we
-           # want to link with libxnet followed by libsocket, so we get
-           # the libxnet versions of everything that's in libxnet, and
-           # the libsocket versions of everything that's not in libxnet
-           # but is in libsocket.
+           # OK, we found it in libsocket.
            #
-           # All we want is something close to a modern SUS UNIX, plus
-           # whatever additional stuff we need.  Is this too much to
-           # ask for?
-           #
-           AC_CHECK_LIB(xnet, getnameinfo,
-           [
-               #
-               # Yay, it looks as if libxnet has it all!  Just add it.
-               #
-               LIBS="-lxnet $LIBS"
-           ],
-           [
-               #
-               # OK, do we find libsocket if we link only with
-               # libsocket?
-               #
-               AC_CHECK_LIB(socket, getnameinfo,
-               [
-                   #
-                   # Yes, so link with -lxnet and -lsocket.
-                   #
-                   LIBS="-lxnet -lsocket $LIBS"
-               ],
-               [
-                   #
-                   # No, so maybe libsocket depends on libnsl, so
-                   # try with both of them.
-                   #
-                   AC_CHECK_LIB(socket, gethostbyname,
-                   [
-                       #
-                       # OK, it works with both libsocket and libnsl.
-                       #
-                       LIBS="-lxnet -lsocket -lnsl $LIBS"
-                   ], , -lnsl)
-               ])
-           ])
+           LIBS="-lsocket -lnsl $LIBS"
        ],
        [
            #
-           # OK, no gethostbyname in the standard system libraries
-           # or libxnet, so try the other libraries.
+           # We didn't find it.
            #
-           AC_SEARCH_LIBS(gethostbyname, nsl socket resolv)
-
-           #
-           # Again, handle the case of libsocket depending on libnsl;
-           # AC_SEARCH_LIBS can't handle that.
-           #
-           if test "$ac_cv_search_gethostbyname" = "no"
-           then
-               AC_CHECK_LIB(socket, gethostbyname,
-                   LIBS="-lsocket -lnsl $LIBS", , -lnsl)
-           fi
-       ])
+           AC_MSG_ERROR([getaddrinfo is required, but wasn't found])
+       ], -lnsl)
 
        #
-       # Make sure we also have socket().
-       # (We don't worry about this if we have libxnet; we assume it
-       # has socket().)
+       # OK, do we have recvmsg() in libxnet?
+       # We also link with libsocket and libnsl.
        #
-       AC_SEARCH_LIBS(socket, socket, ,
-           AC_CHECK_LIB(socket, socket, LIBS="-lsocket -lnsl $LIBS", , -lnsl))
+       AC_CHECK_LIB(xnet, recvmsg,
+       [
+           #
+           # Yes - link with it as well.
+           #
+           LIBS="-lxnet $LIBS"
+       ], , -lsocket -lnsl)
     ])
     # DLPI needs putmsg under HPUX so test for -lstr while we're at it
     AC_SEARCH_LIBS(putmsg, str)
+
+    #
+    # Check for reentrant versions of getnetbyname_r(), as provided by
+    # Linux (glibc), Solaris/IRIX, and AIX (with three different APIs!).
+    # If we don't find one, we just use getnetbyname(), which uses
+    # thread-specific data on many platforms, but doesn't use it on
+    # NetBSD or OpenBSD, and may not use it on older versions of other
+    # platforms.
+    #
+    AC_MSG_CHECKING([for the Linux getnetbyname_r()])
+    AC_TRY_COMPILE(
+       [#include <netdb.h>],
+       [
+           struct netent netent_buf;
+           char buf[1024];
+           struct netent *resultp;
+           int h_errnoval;
+
+           return getnetbyname_r(NULL, &netent_buf, buf, sizeof buf, &resultp, &h_errnoval);
+       ],
+       [
+           AC_MSG_RESULT(yes)
+           AC_DEFINE(HAVE_LINUX_GETNETBYNAME_R, 1,
+                   [define if we have the Linux getnetbyname_r()])
+       ],
+       [
+           AC_MSG_RESULT(no)
+
+           AC_MSG_CHECKING([for Solaris/IRIX getnetbyname_r()])
+           AC_TRY_COMPILE(
+               [#include <netdb.h>],
+               [
+                   struct netent netent_buf;
+                   char buf[1024];
+
+                   return getnetbyname_r(NULL, &netent_buf, buf, (int)sizeof buf) != NULL;
+               ],
+               [
+                   AC_MSG_RESULT(yes)
+                   AC_DEFINE(HAVE_SOLARIS_IRIX_GETNETBYNAME_R, 1,
+                           [define if we have the Solaris/IRIX getnetbyname_r()])
+               ],
+               [
+                   AC_MSG_RESULT(no)
+
+                   AC_MSG_CHECKING([for AIX getnetbyname_r()])
+                   AC_TRY_COMPILE(
+                       [#include <netdb.h>],
+                       [
+                           struct netent netent_buf;
+                           struct netent_data net_data;
+
+                           return getnetbyname_r(NULL, &netent_buf, &net_data);
+                       ],
+                       [
+                           AC_MSG_RESULT(yes)
+                           AC_DEFINE(HAVE_AIX_GETNETBYNAME_R, 1,
+                                   [define if we have the AIX getnetbyname_r()])
+                       ],
+                       [
+                           AC_MSG_RESULT(no)
+                       ])
+               ])
+       ])
+
+    #
+    # Check for reentrant versions of getprotobyname_r(), as provided by
+    # Linux (glibc), Solaris/IRIX, and AIX (with three different APIs!).
+    # If we don't find one, we just use getprotobyname(), which uses
+    # thread-specific data on many platforms, but doesn't use it on
+    # NetBSD or OpenBSD, and may not use it on older versions of other
+    # platforms.
+    #
+    AC_MSG_CHECKING([for the Linux getprotobyname_r()])
+    AC_TRY_COMPILE(
+       [#include <netdb.h>],
+       [
+           struct protoent protoent_buf;
+           char buf[1024];
+           struct protoent *resultp;
+
+           return getprotobyname_r(NULL, &protoent_buf, buf, sizeof buf, &resultp);
+       ],
+       [
+           AC_MSG_RESULT(yes)
+           AC_DEFINE(HAVE_LINUX_GETPROTOBYNAME_R, 1,
+                   [define if we have the Linux getprotobyname_r()])
+       ],
+       [
+           AC_MSG_RESULT(no)
+
+           AC_MSG_CHECKING([for Solaris/IRIX getprotobyname_r()])
+           AC_TRY_COMPILE(
+               [#include <netdb.h>],
+               [
+                   struct protoent protoent_buf;
+                   char buf[1024];
+
+                   return getprotobyname_r(NULL, &protoent_buf, buf, (int)sizeof buf) != NULL;
+               ],
+               [
+                   AC_MSG_RESULT(yes)
+                   AC_DEFINE(HAVE_SOLARIS_IRIX_GETPROTOBYNAME_R, 1,
+                           [define if we have the Solaris/IRIX getprotobyname_r()])
+               ],
+               [
+                   AC_MSG_RESULT(no)
+
+                   AC_MSG_CHECKING([for AIX getprotobyname_r()])
+                   AC_TRY_COMPILE(
+                       [#include <netdb.h>],
+                       [
+                           struct protoent protoent_buf;
+                           struct protoent_data proto_data;
+
+                           return getprotobyname_r(NULL, &protoent_buf, &proto_data);
+                       ],
+                       [
+                           AC_MSG_RESULT(yes)
+                           AC_DEFINE(HAVE_AIX_GETPROTOBYNAME_R, 1,
+                                   [define if we have the AIX getprotobyname_r()])
+                       ],
+                       [
+                           AC_MSG_RESULT(no)
+                       ])
+               ])
+               ])
+       ])
 ])
index d526c61c7623bf6c82d69c589d7b8baffc0ce599..e1630f2a7dc0ae14c5e4fd85ba1a0e84e1a02149 100644 (file)
@@ -9,6 +9,12 @@
 /* Define to 1 if remote packet capture is to be supported */
 #cmakedefine ENABLE_REMOTE 1
 
+/* define if we have the AIX getnetbyname_r() */
+#cmakedefine HAVE_AIX_GETNETBYNAME_R 1
+
+/* define if we have the AIX getprotobyname_r() */
+#cmakedefine HAVE_AIX_GETPROTOBYNAME_R 1
+
 /* define if you have the DAG API */
 #cmakedefine HAVE_DAG_API 1
 
 /* Define to 1 if you have the <linux/ethtool.h> header file. */
 #cmakedefine HAVE_LINUX_ETHTOOL_H 1
 
+/* define if we have the Linux getnetbyname_r() */
+#cmakedefine HAVE_LINUX_GETNETBYNAME_R 1
+
+/* define if we have the Linux getprotobyname_r() */
+#cmakedefine HAVE_LINUX_GETPROTOBYNAME_R 1
+
 /* Define to 1 if you have the <linux/if_bonding.h> header file. */
 #cmakedefine HAVE_LINUX_IF_BONDING_H 1
 
 /* On solaris */
 #cmakedefine HAVE_SOLARIS 1
 
+/* define if we have the Solaris/IRIX getnetbyname_r() */
+#cmakedefine HAVE_SOLARIS_IRIX_GETNETBYNAME_R 1
+
+/* define if we have the Solaris/IRIX getprotobyname_r() */
+#cmakedefine HAVE_SOLARIS_IRIX_GETPROTOBYNAME_R 1
+
 /* Define to 1 if you have the <stdint.h> header file. */
 #cmakedefine HAVE_STDINT_H 1
 
index 042fb756fc821545a0e7e89685cb7f9715eb3936..ce1f02fafaef5926e579343d77089c13d24c46a3 100644 (file)
@@ -9,6 +9,12 @@
 /* Define to 1 if remote packet capture is to be supported */
 #undef ENABLE_REMOTE
 
+/* define if we have the AIX getnetbyname_r() */
+#undef HAVE_AIX_GETNETBYNAME_R
+
+/* define if we have the AIX getprotobyname_r() */
+#undef HAVE_AIX_GETPROTOBYNAME_R
+
 /* define if you have the DAG API */
 #undef HAVE_DAG_API
 
 /* Define to 1 if you have the <linux/ethtool.h> header file. */
 #undef HAVE_LINUX_ETHTOOL_H
 
+/* define if we have the Linux getnetbyname_r() */
+#undef HAVE_LINUX_GETNETBYNAME_R
+
+/* define if we have the Linux getprotobyname_r() */
+#undef HAVE_LINUX_GETPROTOBYNAME_R
+
 /* Define to 1 if you have the <linux/if_bonding.h> header file. */
 #undef HAVE_LINUX_IF_BONDING_H
 
 /* On solaris */
 #undef HAVE_SOLARIS
 
+/* define if we have the Solaris/IRIX getnetbyname_r() */
+#undef HAVE_SOLARIS_IRIX_GETNETBYNAME_R
+
+/* define if we have the Solaris/IRIX getprotobyname_r() */
+#undef HAVE_SOLARIS_IRIX_GETPROTOBYNAME_R
+
 /* Define to 1 if you have the <stdint.h> header file. */
 #undef HAVE_STDINT_H
 
index f4903557fab1d1c25504fec026bad0c786dd1df2..e087536996ce2c9f914d265b2d4c71613165d13a 100755 (executable)
--- a/configure
+++ b/configure
@@ -4983,30 +4983,25 @@ fi
 #
 
     #
-    # Most operating systems have gethostbyname() in the default searched
+    # Most operating systems have getaddrinfo() in the default searched
     # libraries (i.e. libc).  Check there first.
     #
-    ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname"
-if test "x$ac_cv_func_gethostbyname" = xyes; then :
+    ac_fn_c_check_func "$LINENO" "getaddrinfo" "ac_cv_func_getaddrinfo"
+if test "x$ac_cv_func_getaddrinfo" = xyes; then :
 
 else
 
        #
        # Not found in the standard system libraries.
-       # Some OSes (eg. Solaris) place it in libnsl, but in at least some
-       # versions of Solaris, there are alternate versions of these APIs
-       # in libxnet, and those versions conform to the Single UNIX
-       # Specification, meaning you can actually check for truncation
-       # of incoming datagrams in recvmsg(), so we prefer that.
-       # Some strange OSes (SINIX) have it in libsocket, so try libxneet.
+       # Try libsocket, which requires libnsl.
        #
-       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lxnet" >&5
-$as_echo_n "checking for gethostbyname in -lxnet... " >&6; }
-if ${ac_cv_lib_xnet_gethostbyname+:} false; then :
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getaddrinfo in -lsocket" >&5
+$as_echo_n "checking for getaddrinfo in -lsocket... " >&6; }
+if ${ac_cv_lib_socket_getaddrinfo+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lxnet  $LIBS"
+LIBS="-lsocket -lnsl $LIBS"
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -5016,147 +5011,54 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 #ifdef __cplusplus
 extern "C"
 #endif
-char gethostbyname ();
+char getaddrinfo ();
 int
 main ()
 {
-return gethostbyname ();
+return getaddrinfo ();
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_xnet_gethostbyname=yes
+  ac_cv_lib_socket_getaddrinfo=yes
 else
-  ac_cv_lib_xnet_gethostbyname=no
+  ac_cv_lib_socket_getaddrinfo=no
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xnet_gethostbyname" >&5
-$as_echo "$ac_cv_lib_xnet_gethostbyname" >&6; }
-if test "x$ac_cv_lib_xnet_gethostbyname" = xyes; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_getaddrinfo" >&5
+$as_echo "$ac_cv_lib_socket_getaddrinfo" >&6; }
+if test "x$ac_cv_lib_socket_getaddrinfo" = xyes; then :
 
            #
-           # OK, we found it in libxnet.
-           # Unfortunately, on some versions of Solaris, getnameinfo()
-           # getaddrinfo(), freeaddrinfo(), and gai_strerror() are *not*
-           # in libxnet, they're only in libsocket.  In that case, we
-           # want to link with libxnet followed by libsocket, so we get
-           # the libxnet versions of everything that's in libxnet, and
-           # the libsocket versions of everything that's not in libxnet
-           # but is in libsocket.
-           #
-           # All we want is something close to a modern SUS UNIX, plus
-           # whatever additional stuff we need.  Is this too much to
-           # ask for?
+           # OK, we found it in libsocket.
            #
-           { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getnameinfo in -lxnet" >&5
-$as_echo_n "checking for getnameinfo in -lxnet... " >&6; }
-if ${ac_cv_lib_xnet_getnameinfo+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lxnet  $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char getnameinfo ();
-int
-main ()
-{
-return getnameinfo ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_xnet_getnameinfo=yes
-else
-  ac_cv_lib_xnet_getnameinfo=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xnet_getnameinfo" >&5
-$as_echo "$ac_cv_lib_xnet_getnameinfo" >&6; }
-if test "x$ac_cv_lib_xnet_getnameinfo" = xyes; then :
-
-               #
-               # Yay, it looks as if libxnet has it all!  Just add it.
-               #
-               LIBS="-lxnet $LIBS"
+           LIBS="-lsocket -lnsl $LIBS"
 
 else
 
-               #
-               # OK, do we find libsocket if we link only with
-               # libsocket?
-               #
-               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getnameinfo in -lsocket" >&5
-$as_echo_n "checking for getnameinfo in -lsocket... " >&6; }
-if ${ac_cv_lib_socket_getnameinfo+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsocket  $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
+           #
+           # We didn't find it.
+           #
+           as_fn_error $? "getaddrinfo is required, but wasn't found" "$LINENO" 5
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char getnameinfo ();
-int
-main ()
-{
-return getnameinfo ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_socket_getnameinfo=yes
-else
-  ac_cv_lib_socket_getnameinfo=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_getnameinfo" >&5
-$as_echo "$ac_cv_lib_socket_getnameinfo" >&6; }
-if test "x$ac_cv_lib_socket_getnameinfo" = xyes; then :
-
-                   #
-                   # Yes, so link with -lxnet and -lsocket.
-                   #
-                   LIBS="-lxnet -lsocket $LIBS"
 
-else
 
-                   #
-                   # No, so maybe libsocket depends on libnsl, so
-                   # try with both of them.
-                   #
-                   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lsocket" >&5
-$as_echo_n "checking for gethostbyname in -lsocket... " >&6; }
-if ${ac_cv_lib_socket_gethostbyname+:} false; then :
+       #
+       # OK, do we have recvmsg() in libxnet?
+       # We also link with libsocket and libnsl.
+       #
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for recvmsg in -lxnet" >&5
+$as_echo_n "checking for recvmsg in -lxnet... " >&6; }
+if ${ac_cv_lib_xnet_recvmsg+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsocket -lnsl $LIBS"
+LIBS="-lxnet -lsocket -lnsl $LIBS"
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -5166,51 +5068,42 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 #ifdef __cplusplus
 extern "C"
 #endif
-char gethostbyname ();
+char recvmsg ();
 int
 main ()
 {
-return gethostbyname ();
+return recvmsg ();
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_socket_gethostbyname=yes
+  ac_cv_lib_xnet_recvmsg=yes
 else
-  ac_cv_lib_socket_gethostbyname=no
+  ac_cv_lib_xnet_recvmsg=no
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_gethostbyname" >&5
-$as_echo "$ac_cv_lib_socket_gethostbyname" >&6; }
-if test "x$ac_cv_lib_socket_gethostbyname" = xyes; then :
-
-                       #
-                       # OK, it works with both libsocket and libnsl.
-                       #
-                       LIBS="-lxnet -lsocket -lnsl $LIBS"
-
-fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xnet_recvmsg" >&5
+$as_echo "$ac_cv_lib_xnet_recvmsg" >&6; }
+if test "x$ac_cv_lib_xnet_recvmsg" = xyes; then :
 
+           #
+           # Yes - link with it as well.
+           #
+           LIBS="-lxnet $LIBS"
 
 fi
 
 
 fi
 
-
-else
-
-           #
-           # OK, no gethostbyname in the standard system libraries
-           # or libxnet, so try the other libraries.
-           #
-           { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5
-$as_echo_n "checking for library containing gethostbyname... " >&6; }
-if ${ac_cv_search_gethostbyname+:} false; then :
+    # DLPI needs putmsg under HPUX so test for -lstr while we're at it
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing putmsg" >&5
+$as_echo_n "checking for library containing putmsg... " >&6; }
+if ${ac_cv_search_putmsg+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_func_search_save_LIBS=$LIBS
@@ -5223,16 +5116,16 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 #ifdef __cplusplus
 extern "C"
 #endif
-char gethostbyname ();
+char putmsg ();
 int
 main ()
 {
-return gethostbyname ();
+return putmsg ();
   ;
   return 0;
 }
 _ACEOF
-for ac_lib in '' nsl socket resolv; do
+for ac_lib in '' str; do
   if test -z "$ac_lib"; then
     ac_res="none required"
   else
@@ -5240,244 +5133,253 @@ for ac_lib in '' nsl socket resolv; do
     LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
   fi
   if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_gethostbyname=$ac_res
+  ac_cv_search_putmsg=$ac_res
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext
-  if ${ac_cv_search_gethostbyname+:} false; then :
+  if ${ac_cv_search_putmsg+:} false; then :
   break
 fi
 done
-if ${ac_cv_search_gethostbyname+:} false; then :
+if ${ac_cv_search_putmsg+:} false; then :
 
 else
-  ac_cv_search_gethostbyname=no
+  ac_cv_search_putmsg=no
 fi
 rm conftest.$ac_ext
 LIBS=$ac_func_search_save_LIBS
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5
-$as_echo "$ac_cv_search_gethostbyname" >&6; }
-ac_res=$ac_cv_search_gethostbyname
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_putmsg" >&5
+$as_echo "$ac_cv_search_putmsg" >&6; }
+ac_res=$ac_cv_search_putmsg
 if test "$ac_res" != no; then :
   test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
 
 fi
 
 
-           #
-           # Again, handle the case of libsocket depending on libnsl;
-           # AC_SEARCH_LIBS can't handle that.
-           #
-           if test "$ac_cv_search_gethostbyname" = "no"
-           then
-               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lsocket" >&5
-$as_echo_n "checking for gethostbyname in -lsocket... " >&6; }
-if ${ac_cv_lib_socket_gethostbyname+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsocket -lnsl $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+    #
+    # Check for reentrant versions of getnetbyname_r(), as provided by
+    # Linux (glibc), Solaris/IRIX, and AIX (with three different APIs!).
+    # If we don't find one, we just use getnetbyname(), which uses
+    # thread-specific data on many platforms, but doesn't use it on
+    # NetBSD or OpenBSD, and may not use it on older versions of other
+    # platforms.
+    #
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the Linux getnetbyname_r()" >&5
+$as_echo_n "checking for the Linux getnetbyname_r()... " >&6; }
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char gethostbyname ();
+#include <netdb.h>
 int
 main ()
 {
-return gethostbyname ();
+
+           struct netent netent_buf;
+           char buf[1024];
+           struct netent *resultp;
+           int h_errnoval;
+
+           return getnetbyname_r(NULL, &netent_buf, buf, sizeof buf, &resultp, &h_errnoval);
+
   ;
   return 0;
 }
 _ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_socket_gethostbyname=yes
-else
-  ac_cv_lib_socket_gethostbyname=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_gethostbyname" >&5
-$as_echo "$ac_cv_lib_socket_gethostbyname" >&6; }
-if test "x$ac_cv_lib_socket_gethostbyname" = xyes; then :
-  LIBS="-lsocket -lnsl $LIBS"
-fi
+if ac_fn_c_try_compile "$LINENO"; then :
 
-           fi
+           { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
 
-fi
+$as_echo "#define HAVE_LINUX_GETNETBYNAME_R 1" >>confdefs.h
 
 
-       #
-       # Make sure we also have socket().
-       # (We don't worry about this if we have libxnet; we assume it
-       # has socket().)
-       #
-       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5
-$as_echo_n "checking for library containing socket... " >&6; }
-if ${ac_cv_search_socket+:} false; then :
-  $as_echo_n "(cached) " >&6
 else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char socket ();
+           { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+           { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Solaris/IRIX getnetbyname_r()" >&5
+$as_echo_n "checking for Solaris/IRIX getnetbyname_r()... " >&6; }
+           cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <netdb.h>
 int
 main ()
 {
-return socket ();
+
+                   struct netent netent_buf;
+                   char buf[1024];
+
+                   return getnetbyname_r(NULL, &netent_buf, buf, (int)sizeof buf) != NULL;
+
   ;
   return 0;
 }
 _ACEOF
-for ac_lib in '' socket; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_socket=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_socket+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_socket+:} false; then :
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_SOLARIS_IRIX_GETNETBYNAME_R 1" >>confdefs.h
 
-else
-  ac_cv_search_socket=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket" >&5
-$as_echo "$ac_cv_search_socket" >&6; }
-ac_res=$ac_cv_search_socket
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
 
 else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5
-$as_echo_n "checking for socket in -lsocket... " >&6; }
-if ${ac_cv_lib_socket_socket+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsocket -lnsl $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char socket ();
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for AIX getnetbyname_r()" >&5
+$as_echo_n "checking for AIX getnetbyname_r()... " >&6; }
+                   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <netdb.h>
 int
 main ()
 {
-return socket ();
+
+                           struct netent netent_buf;
+                           struct netent_data net_data;
+
+                           return getnetbyname_r(NULL, &netent_buf, &net_data);
+
   ;
   return 0;
 }
 _ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_socket_socket=yes
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                           { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_AIX_GETNETBYNAME_R 1" >>confdefs.h
+
+
 else
-  ac_cv_lib_socket_socket=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
+
+                           { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_socket" >&5
-$as_echo "$ac_cv_lib_socket_socket" >&6; }
-if test "x$ac_cv_lib_socket_socket" = xyes; then :
-  LIBS="-lsocket -lnsl $LIBS"
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
 fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
 fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+    #
+    # Check for reentrant versions of getprotobyname_r(), as provided by
+    # Linux (glibc), Solaris/IRIX, and AIX (with three different APIs!).
+    # If we don't find one, we just use getprotobyname(), which uses
+    # thread-specific data on many platforms, but doesn't use it on
+    # NetBSD or OpenBSD, and may not use it on older versions of other
+    # platforms.
+    #
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the Linux getprotobyname_r()" >&5
+$as_echo_n "checking for the Linux getprotobyname_r()... " >&6; }
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <netdb.h>
+int
+main ()
+{
 
+           struct protoent protoent_buf;
+           char buf[1024];
+           struct protoent *resultp;
+
+           return getprotobyname_r(NULL, &protoent_buf, buf, sizeof buf, &resultp);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+           { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_LINUX_GETPROTOBYNAME_R 1" >>confdefs.h
 
-fi
 
-    # DLPI needs putmsg under HPUX so test for -lstr while we're at it
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing putmsg" >&5
-$as_echo_n "checking for library containing putmsg... " >&6; }
-if ${ac_cv_search_putmsg+:} false; then :
-  $as_echo_n "(cached) " >&6
 else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+
+           { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+           { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Solaris/IRIX getprotobyname_r()" >&5
+$as_echo_n "checking for Solaris/IRIX getprotobyname_r()... " >&6; }
+           cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
+#include <netdb.h>
+int
+main ()
+{
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char putmsg ();
+                   struct protoent protoent_buf;
+                   char buf[1024];
+
+                   return getprotobyname_r(NULL, &protoent_buf, buf, (int)sizeof buf) != NULL;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_SOLARIS_IRIX_GETPROTOBYNAME_R 1" >>confdefs.h
+
+
+else
+
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for AIX getprotobyname_r()" >&5
+$as_echo_n "checking for AIX getprotobyname_r()... " >&6; }
+                   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <netdb.h>
 int
 main ()
 {
-return putmsg ();
+
+                           struct protoent protoent_buf;
+                           struct protoent_data proto_data;
+
+                           return getprotobyname_r(NULL, &protoent_buf, &proto_data);
+
   ;
   return 0;
 }
 _ACEOF
-for ac_lib in '' str; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_putmsg=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_putmsg+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_putmsg+:} false; then :
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                           { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_AIX_GETPROTOBYNAME_R 1" >>confdefs.h
+
 
 else
-  ac_cv_search_putmsg=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
+
+                           { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_putmsg" >&5
-$as_echo "$ac_cv_search_putmsg" >&6; }
-ac_res=$ac_cv_search_putmsg
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
 fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
 
 #
index 645d162c22729a46db609ae8d3855eaf7e77e341..e612625b564027ed76f71607dd3c30557ca17610 100644 (file)
--- a/gencode.c
+++ b/gencode.c
@@ -49,6 +49,7 @@
 #endif
 
 #include "pcap-int.h"
+#include <netdb.h>
 
 #include "ethertype.h"
 #include "nlpid.h"
@@ -265,7 +266,6 @@ struct _compiler_state {
        /* XXX */
        u_int pcap_fddipad;
 
-#ifdef INET6
        /*
         * As errors are handled by a longjmp, anything allocated must
         * be freed in the longjmp handler, so it must be reachable
@@ -276,7 +276,6 @@ struct _compiler_state {
         * any addrinfo structure that would need to be freed.
         */
        struct addrinfo *ai;
-#endif
 
        /*
         * Various code constructs need to know the layout of the packet.
@@ -517,7 +516,7 @@ static struct block *gen_host6(compiler_state_t *, struct in6_addr *,
 #endif
 #ifndef INET6
 static struct block *gen_gateway(compiler_state_t *, const u_char *,
-    bpf_u_int32 **, int, int);
+    struct addrinfo *, int, int);
 #endif
 static struct block *gen_ipfrag(compiler_state_t *);
 static struct block *gen_portatom(compiler_state_t *, int, bpf_int32);
@@ -4949,10 +4948,12 @@ gen_host6(compiler_state_t *cstate, struct in6_addr *addr,
 
 #ifndef INET6
 static struct block *
-gen_gateway(compiler_state_t *cstate, const u_char *eaddr, bpf_u_int32 **alist,
-    int proto, int dir)
+gen_gateway(compiler_state_t *cstate, const u_char *eaddr,
+    struct addrinfo *alist, int proto, int dir)
 {
        struct block *b0, *b1, *tmp;
+       struct addrinfo *ai;
+       struct sockaddr_in *sin;
 
        if (dir != 0)
                bpf_error(cstate, "direction applied to 'gateway'");
@@ -5000,12 +5001,48 @@ gen_gateway(compiler_state_t *cstate, const u_char *eaddr, bpf_u_int32 **alist,
                        bpf_error(cstate,
                            "'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
                }
-               b1 = gen_host(cstate, **alist++, 0xffffffff, proto, Q_OR, Q_HOST);
-               while (*alist) {
-                       tmp = gen_host(cstate, **alist++, 0xffffffff, proto, Q_OR,
-                           Q_HOST);
-                       gen_or(b1, tmp);
-                       b1 = tmp;
+               b1 = NULL;
+               for (ai = alist; ai != NULL; ai = ai->ai_next) {
+                       /*
+                        * Does it have an address?
+                        */
+                       if (ai->ai_addr != NULL) {
+                               /*
+                                * Yes.  Is it an IPv4 address?
+                                */
+                               if (ai->ai_addr->sa_family == AF_INET) {
+                                       /*
+                                        * Generate an entry for it.
+                                        */
+                                       sin = (struct sockaddr_in *)ai->ai_addr;
+                                       tmp = gen_host(cstate,
+                                           ntohl(sin->sin_addr.s_addr),
+                                           0xffffffff, proto, Q_OR, Q_HOST);
+                                       /*
+                                        * Is it the *first* IPv4 address?
+                                        */
+                                       if (b1 == NULL) {
+                                               /*
+                                                * Yes, so start with it.
+                                                */
+                                               b1 = tmp;
+                                       } else {
+                                               /*
+                                                * No, so OR it into the
+                                                * existing set of
+                                                * addresses.
+                                                */
+                                               gen_or(b1, tmp);
+                                               b1 = tmp;
+                                       }
+                               }
+                       }
+               }
+               if (b1 == NULL) {
+                       /*
+                        * No IPv4 addresses found.
+                        */
+                       return (NULL);
                }
                gen_not(b1);
                gen_and(b0, b1);
@@ -6243,13 +6280,11 @@ gen_scode(compiler_state_t *cstate, const char *name, struct qual q)
        int tproto;
        u_char *eaddr;
        bpf_u_int32 mask, addr;
-#ifndef INET6
-       bpf_u_int32 **alist;
-#else
-       int tproto6;
+       struct addrinfo *res, *res0;
        struct sockaddr_in *sin4;
+#ifdef INET6
+       int tproto6;
        struct sockaddr_in6 *sin6;
-       struct addrinfo *res, *res0;
        struct in6_addr mask128;
 #endif /*INET6*/
        struct block *b, *tmp;
@@ -6348,46 +6383,39 @@ gen_scode(compiler_state_t *cstate, const char *name, struct qual q)
                         */
                        return (gen_host(cstate, dn_addr, 0, proto, dir, q.addr));
                } else {
-#ifndef INET6
-                       alist = pcap_nametoaddr(name);
-                       if (alist == NULL || *alist == NULL)
-                               bpf_error(cstate, "unknown host '%s'", name);
-                       tproto = proto;
-                       if (cstate->off_linktype.constant_part == OFFSET_NOT_SET &&
-                           tproto == Q_DEFAULT)
-                               tproto = Q_IP;
-                       b = gen_host(cstate, **alist++, 0xffffffff, tproto, dir, q.addr);
-                       while (*alist) {
-                               tmp = gen_host(cstate, **alist++, 0xffffffff,
-                                              tproto, dir, q.addr);
-                               gen_or(b, tmp);
-                               b = tmp;
-                       }
-                       return b;
-#else
+#ifdef INET6
                        memset(&mask128, 0xff, sizeof(mask128));
+#endif
                        res0 = res = pcap_nametoaddrinfo(name);
                        if (res == NULL)
                                bpf_error(cstate, "unknown host '%s'", name);
                        cstate->ai = res;
                        b = tmp = NULL;
-                       tproto = tproto6 = proto;
+                       tproto = proto;
+#ifdef INET6
+                       tproto6 = proto;
+#endif
                        if (cstate->off_linktype.constant_part == OFFSET_NOT_SET &&
                            tproto == Q_DEFAULT) {
                                tproto = Q_IP;
+#ifdef INET6
                                tproto6 = Q_IPV6;
+#endif
                        }
                        for (res = res0; res; res = res->ai_next) {
                                switch (res->ai_family) {
                                case AF_INET:
+#ifdef INET6
                                        if (tproto == Q_IPV6)
                                                continue;
+#endif
 
                                        sin4 = (struct sockaddr_in *)
                                                res->ai_addr;
                                        tmp = gen_host(cstate, ntohl(sin4->sin_addr.s_addr),
                                                0xffffffff, tproto, dir, q.addr);
                                        break;
+#ifdef INET6
                                case AF_INET6:
                                        if (tproto6 == Q_IP)
                                                continue;
@@ -6397,6 +6425,7 @@ gen_scode(compiler_state_t *cstate, const char *name, struct qual q)
                                        tmp = gen_host6(cstate, &sin6->sin6_addr,
                                                &mask128, tproto6, dir, q.addr);
                                        break;
+#endif
                                default:
                                        continue;
                                }
@@ -6413,7 +6442,6 @@ gen_scode(compiler_state_t *cstate, const char *name, struct qual q)
                                        : " for specified address family");
                        }
                        return b;
-#endif /*INET6*/
                }
 
        case Q_PORT:
@@ -6511,11 +6539,15 @@ gen_scode(compiler_state_t *cstate, const char *name, struct qual q)
                if (eaddr == NULL)
                        bpf_error(cstate, "unknown ether host: %s", name);
 
-               alist = pcap_nametoaddr(name);
-               if (alist == NULL || *alist == NULL)
+               res = pcap_nametoaddrinfo(name);
+               cstate->ai = res;
+               if (res == NULL)
+                       bpf_error(cstate, "unknown host '%s'", name);
+               b = gen_gateway(cstate, eaddr, res, proto, dir);
+               cstate->ai = NULL;
+               freeaddrinfo(res);
+               if (b == NULL)
                        bpf_error(cstate, "unknown host '%s'", name);
-               b = gen_gateway(cstate, eaddr, alist, proto, dir);
-               free(eaddr);
                return b;
 #else
                bpf_error(cstate, "'gateway' not supported in this configuration");
index 17c455678c4cc5d0d826b4d8915af6acd6646a67..45743c71c532a178e9e4adffe54321e446115362 100644 (file)
@@ -61,7 +61,7 @@
   #endif /* INET6 */
 #else /* _WIN32 */
   #include <sys/param.h>
-  #include <sys/types.h>                       /* concession to AIX */
+  #include <sys/types.h>
   #include <sys/socket.h>
   #include <sys/time.h>
 
@@ -155,6 +155,7 @@ static inline int xdtoi(int);
 /*
  *  Convert host name to internet address.
  *  Return 0 upon failure.
+ *  XXX - not thread-safe; don't use it inside libpcap.
  */
 bpf_u_int32 **
 pcap_nametoaddr(const char *name)
@@ -180,7 +181,6 @@ pcap_nametoaddr(const char *name)
                return 0;
 }
 
-#ifdef INET6
 struct addrinfo *
 pcap_nametoaddrinfo(const char *name)
 {
@@ -197,23 +197,17 @@ pcap_nametoaddrinfo(const char *name)
        else
                return res;
 }
-#endif /*INET6*/
 
 /*
  *  Convert net name to internet address.
  *  Return 0 upon failure.
+ *  XXX - not guaranteed to be thread-safe!  See below for platforms
+ *  on which it is thread-safe and on which it isn't.
  */
 bpf_u_int32
 pcap_nametonetaddr(const char *name)
 {
-#ifndef _WIN32
-       struct netent *np;
-
-       if ((np = getnetbyname(name)) != NULL)
-               return np->n_net;
-       else
-               return 0;
-#else
+#ifdef _WIN32
        /*
         * There's no "getnetbyname()" on Windows.
         *
@@ -227,7 +221,66 @@ pcap_nametonetaddr(const char *name)
         * of *UN*X* machines.)
         */
        return 0;
-#endif
+#else
+       /*
+        * UN*X.
+        */
+       struct netent *np;
+  #if defined(HAVE_LINUX_GETNETBYNAME_R)
+       /*
+        * We have Linux's reentrant getnetbyname_r().
+        */
+       struct netent result_buf;
+       char buf[1024]; /* arbitrary size */
+       int h_errnoval;
+       int err;
+
+       err = getnetbyname_r(name, &result_buf, buf, sizeof buf, &np,
+           &h_errnoval);
+       if (err != 0) {
+               /*
+                * XXX - dynamically allocate the buffer, and make it
+                * bigger if we get ERANGE back?
+                */
+               return 0;
+       }
+  #elif defined(HAVE_SOLARIS_IRIX_GETNETBYNAME_R)
+       /*
+        * We have Solaris's and IRIX's reentrant getnetbyname_r().
+        */
+       struct netent result_buf;
+       char buf[1024]; /* arbitrary size */
+
+       np = getnetbyname_r(name, &result_buf, buf, (int)sizeof buf);
+  #elif defined(HAVE_AIX_GETNETBYNAME_R)
+       /*
+        * We have AIX's reentrant getnetbyname_r().
+        */
+       struct netent result_buf;
+       struct netent_data net_data;
+
+       if (getnetbyname_r(name, &result_buf, &net_data) == -1)
+               np = NULL;
+       else
+               np = &result_buf;
+  #else
+       /*
+        * We don't have any getnetbyname_r(); either we have a
+        * getnetbyname() that uses thread-specific data, in which
+        * case we're thread-safe (sufficiently recent FreeBSD,
+        * sufficiently recent Darwin-based OS, sufficiently recent
+        * HP-UX, sufficiently recent Tru64 UNIX), or we have the
+        * traditional getnetbyname() (everything else, including
+        * current NetBSD and OpenBSD), in which case we're not
+        * thread-safe.
+        */
+       np = getnetbyname(name);
+  #endif
+       if (np != NULL)
+               return np->n_net;
+       else
+               return 0;
+#endif /* _WIN32 */
 }
 
 /*
@@ -238,20 +291,111 @@ pcap_nametonetaddr(const char *name)
 int
 pcap_nametoport(const char *name, int *port, int *proto)
 {
-       struct servent *sp;
+       struct addrinfo hints, *res, *ai;
+       int error;
+       struct sockaddr_in *in4;
+#ifdef INET6
+       struct sockaddr_in6 *in6;
+#endif
        int tcp_port = -1;
        int udp_port = -1;
 
+       /*
+        * We check for both TCP and UDP in case there are
+        * ambiguous entries.
+        */
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = PF_UNSPEC;
+       hints.ai_socktype = SOCK_STREAM;
+       hints.ai_protocol = IPPROTO_TCP;
+       error = getaddrinfo(NULL, name, &hints, &res);
+       if (error != 0) {
+               if (error != EAI_NONAME) {
+                       /*
+                        * This is a real error, not just "there's
+                        * no such service name".
+                        * XXX - this doesn't return an error string.
+                        */
+                       return 0;
+               }
+       } else {
+               /*
+                * OK, we found it.  Did it find anything?
+                */
+               for (ai = res; ai != NULL; ai = ai->ai_next) {
+                       /*
+                        * Does it have an address?
+                        */
+                       if (ai->ai_addr != NULL) {
+                               /*
+                                * Yes.  Get a port number; we're done.
+                                */
+                               if (ai->ai_addr->sa_family == AF_INET) {
+                                       in4 = (struct sockaddr_in *)ai->ai_addr;
+                                       tcp_port = ntohs(in4->sin_port);
+                                       break;
+                               }
+#ifdef INET6
+                               if (ai->ai_addr->sa_family == AF_INET6) {
+                                       in6 = (struct sockaddr_in6 *)ai->ai_addr;
+                                       tcp_port = ntohs(in6->sin6_port);
+                                       break;
+                               }
+#endif
+                       }
+               }
+               freeaddrinfo(res);
+       }
+
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = PF_UNSPEC;
+       hints.ai_socktype = SOCK_DGRAM;
+       hints.ai_protocol = IPPROTO_UDP;
+       error = getaddrinfo(NULL, name, &hints, &res);
+       if (error != 0) {
+               if (error != EAI_NONAME) {
+                       /*
+                        * This is a real error, not just "there's
+                        * no such service name".
+                        * XXX - this doesn't return an error string.
+                        */
+                       return 0;
+               }
+       } else {
+               /*
+                * OK, we found it.  Did it find anything?
+                */
+               for (ai = res; ai != NULL; ai = ai->ai_next) {
+                       /*
+                        * Does it have an address?
+                        */
+                       if (ai->ai_addr != NULL) {
+                               /*
+                                * Yes.  Get a port number; we're done.
+                                */
+                               if (ai->ai_addr->sa_family == AF_INET) {
+                                       in4 = (struct sockaddr_in *)ai->ai_addr;
+                                       udp_port = ntohs(in4->sin_port);
+                                       break;
+                               }
+#ifdef INET6
+                               if (ai->ai_addr->sa_family == AF_INET6) {
+                                       in6 = (struct sockaddr_in6 *)ai->ai_addr;
+                                       udp_port = ntohs(in6->sin6_port);
+                                       break;
+                               }
+#endif
+                       }
+               }
+               freeaddrinfo(res);
+       }
+
        /*
         * We need to check /etc/services for ambiguous entries.
-        * If we find the ambiguous entry, and it has the
+        * If we find an ambiguous entry, and it has the
         * same port number, change the proto to PROTO_UNDEF
         * so both TCP and UDP will be checked.
         */
-       sp = getservbyname(name, "tcp");
-       if (sp != NULL) tcp_port = ntohs(sp->s_port);
-       sp = getservbyname(name, "udp");
-       if (sp != NULL) udp_port = ntohs(sp->s_port);
        if (tcp_port >= 0) {
                *port = tcp_port;
                *proto = IPPROTO_TCP;
@@ -330,12 +474,62 @@ pcap_nametoportrange(const char *name, int *port1, int *port2, int *proto)
        return 1;
 }
 
+/*
+ * XXX - not guaranteed to be thread-safe!  See below for platforms
+ * on which it is thread-safe and on which it isn't.
+ */
 int
 pcap_nametoproto(const char *str)
 {
        struct protoent *p;
+  #if defined(HAVE_LINUX_GETNETBYNAME_R)
+       /*
+        * We have Linux's reentrant getprotobyname_r().
+        */
+       struct protoent result_buf;
+       char buf[1024]; /* arbitrary size */
+       int err;
+
+       err = getprotobyname_r(str, &result_buf, buf, sizeof buf, &p);
+       if (err != 0) {
+               /*
+                * XXX - dynamically allocate the buffer, and make it
+                * bigger if we get ERANGE back?
+                */
+               return 0;
+       }
+  #elif defined(HAVE_SOLARIS_IRIX_GETNETBYNAME_R)
+       /*
+        * We have Solaris's and IRIX's reentrant getprotobyname_r().
+        */
+       struct protoent result_buf;
+       char buf[1024]; /* arbitrary size */
 
+       p = getprotobyname_r(str, &result_buf, buf, (int)sizeof buf);
+  #elif defined(HAVE_AIX_GETNETBYNAME_R)
+       /*
+        * We have AIX's reentrant getprotobyname_r().
+        */
+       struct protoent result_buf;
+       struct protoent_data proto_data;
+
+       if (getprotobyname_r(str, &result_buf, &proto_data) == -1)
+               p = NULL;
+       else
+               p = &result_buf;
+  #else
+       /*
+        * We don't have any getprotobyname_r(); either we have a
+        * getprotobyname() that uses thread-specific data, in which
+        * case we're thread-safe (sufficiently recent FreeBSD,
+        * sufficiently recent Darwin-based OS, sufficiently recent
+        * HP-UX, sufficiently recent Tru64 UNIX, Windows), or we have
+        * the traditional getprotobyname() (everything else, including
+        * current NetBSD and OpenBSD), in which case we're not
+        * thread-safe.
+        */
        p = getprotobyname(str);
+  #endif
        if (p != 0)
                return p->p_proto;
        else
@@ -508,6 +702,9 @@ pcap_ether_aton(const char *s)
        return (e);
 }
 
+/*
+ * XXX - not thread-safe!
+ */
 #ifndef HAVE_ETHER_HOSTTON
 /* Roll our own */
 u_char *
@@ -557,6 +754,9 @@ pcap_ether_hostton(const char *name)
 }
 #endif
 
+/*
+ * XXX - not guaranteed to be thread-safe!
+ */
 int
 __pcap_nametodnaddr(const char *name, u_short *res)
 {
index 73fb40a4cf3ffcb5be96b810257dde17eaed9f69..c66846d3451bd4b5ab0e9c4bfd651ef413dbf4d9 100644 (file)
@@ -60,9 +60,7 @@ PCAP_API u_char *pcap_ether_hostton(const char*);
 PCAP_API u_char *pcap_ether_aton(const char *);
 
 PCAP_API bpf_u_int32 **pcap_nametoaddr(const char *);
-#ifdef INET6
 PCAP_API struct addrinfo *pcap_nametoaddrinfo(const char *);
-#endif
 PCAP_API bpf_u_int32 pcap_nametonetaddr(const char *);
 
 PCAP_API int   pcap_nametoport(const char *, int *, int *);