]> The Tcpdump Group git mirrors - libpcap/commitdiff
Don't test for capture devices, test for header files.
authorGuy Harris <[email protected]>
Fri, 15 Sep 2017 12:14:10 +0000 (05:14 -0700)
committerGuy Harris <[email protected]>
Fri, 15 Sep 2017 12:14:10 +0000 (05:14 -0700)
Testing for /dev/bpf or /dev/bpfN in CMake requires that they be
readable.  Test for various header files required by various pcap-XXX.c
files, and use that to determine what the capture mechanism for the
host platform is.

Don't look for headers by absolute path, as that could get in the way of
cross-development (if any cross-development where the build machine and
the host machine are running different OSes works).

This means we have to determine whether we have a cloning BPF device at
run time; do so.

CMakeLists.txt
config.h.in
configure
configure.ac
pcap-bpf.c

index 197874d45d1d181ade7eaa7aa75994d491f8e24b..0763fb40fd01de9e41b3f6e906e006caf84e4774 100644 (file)
@@ -303,39 +303,65 @@ else()
     # what libraries we'd need to link libpcap with, if any.
     #
     set(PCAP_LINK_LIBRARIES "")
-    if(EXISTS /dev/bpf)
+
+    #
+    # Check for a bunch of headers for various packet capture mechanisms.
+    #
+    check_include_file(net/bpf.h HAVE_NET_BPF_H)
+    check_include_file(net/pfilt.h HAVE_NET_PFILT_H)
+    check_include_file(net/enet.h HAVE_NET_ENET_H)
+    check_include_file(net/nit.h HAVE_NET_NIT_H)
+    check_include_file(sys/net/nit.h HAVE_SYS_NET_NIT_H)
+    check_include_file(linux/socket.h HAVE_LINUX_SOCKET_H)
+    check_include_file(net/raw.h HAVE_NET_RAW_H)
+    check_include_file(sys/dlpi.h HAVE_SYS_DLPI_H)
+
+    if(HAVE_NET_BPF_H)
        #
-       # Cloning BPF device.
+       # BPF.
+       # Check this before DLPI, so that we pick BPF on
+       # Solaris 11 and later.
        #
        set(PCAP_TYPE bpf)
-       set(HAVE_CLONING_BPF TRUE)
-    elseif(EXISTS /dev/bpf0)
-       set(PCAP_TYPE bpf)
-    elseif(EXISTS /usr/include/net/pfilt.h)
+    elseif(HAVE_NET_PFILT_H)
         #
         # DEC OSF/1, Digital UNIX, Tru64 UNIX
         #
        set(PCAP_TYPE pf)
-    elseif(EXISTS /dev/enet)
+    elseif(HAVE_NET_ENET_H)
+       #
+       # Stanford Enetfilter.
+       #
         set(PCAP_TYPE enet)
-    elseif(EXISTS /dev/nit)
+    elseif(HAVE_NET_NIT_H)
+       #
+       # SunOS 4.x STREAMS NIT.
+       #
         set(PCAP_TYPE snit)
-    elseif(EXISTS /usr/include/sys/net/nit.h)
+    elseif(HAVE_SYS_NET_NIT_H)
+       #
+       # Pre-SunOS 4.x non-STREAMS NIT.
+       #
         set(PCAP_TYPE nit)
-    elseif(EXISTS /usr/include/linux/socket.h)
+    elseif(HAVE_LINUX_SOCKET_H)
+       #
+       # No prizes for guessing this one.
+       #
         set(PCAP_TYPE linux)
-    elseif(EXISTS /usr/include/net/raw.h)
+    elseif(HAVE_NET_RAW_H)
+       #
+       # IRIX snoop.
+       #
         set(PCAP_TYPE snoop)
-    elseif(EXISTS /usr/include/odmi.h)
-        #
-        # On AIX, the BPF devices might not yet be present - they're
-        # created the first time libpcap runs after booting.
-        # We check for odmi.h instead.
-        #
-        set(PCAP_TYPE bpf)
-    elseif(/usr/include/sys/dlpi.h)
+    elseif(HAVE_SYS_DLPI_H)
+       #
+       # DLPI on pre-Solaris 11 SunOS 5, HP-UX, possibly others.
+       #
         set(PCAP_TYPE dlpi)
     else()
+       #
+       # Nothing we support.
+       #
        set(PCAP_TYPE null)
     endif()
 endif(WIN32)
index d4ab2409e6159f123143699bbea156357bb72c1b..9ba62ee9663c34cf9fef85e94f61475b50aec19a 100644 (file)
@@ -3,9 +3,6 @@
 /* Enable optimizer debugging */
 #undef BDEBUG
 
-/* define if you have a cloning BPF device */
-#undef HAVE_CLONING_BPF
-
 /* define if you have the DAG API */
 #undef HAVE_DAG_API
 
@@ -82,6 +79,9 @@
 /* Define to 1 if you have the <linux/net_tstamp.h> header file. */
 #undef HAVE_LINUX_NET_TSTAMP_H
 
+/* Define to 1 if you have the <linux/socket.h> header file. */
+#undef HAVE_LINUX_SOCKET_H
+
 /* Define to 1 if you have the <linux/sockios.h> header file. */
 #undef HAVE_LINUX_SOCKIOS_H
 
 /* Define to 1 if you have the <netpacket/packet.h> header file. */
 #undef HAVE_NETPACKET_PACKET_H
 
+/* Define to 1 if you have the <net/bpf.h> header file. */
+#undef HAVE_NET_BPF_H
+
+/* Define to 1 if you have the <net/enet.h> header file. */
+#undef HAVE_NET_ENET_H
+
 /* Define to 1 if you have the <net/if_media.h> header file. */
 #undef HAVE_NET_IF_MEDIA_H
 
+/* Define to 1 if you have the <net/nit.h> header file. */
+#undef HAVE_NET_NIT_H
+
+/* Define to 1 if you have the <net/pfilt.h> header file. */
+#undef HAVE_NET_PFILT_H
+
 /* Define to 1 if you have the <net/pfvar.h> header file. */
 #undef HAVE_NET_PFVAR_H
 
+/* Define to 1 if you have the <net/raw.h> header file. */
+#undef HAVE_NET_RAW_H
+
 /* if there's an os_proto.h for this platform, to use additional prototypes */
 #undef HAVE_OS_PROTO_H
 
 /* Define to 1 if you have the <sys/dlpi_ext.h> header file. */
 #undef HAVE_SYS_DLPI_EXT_H
 
+/* Define to 1 if you have the <sys/dlpi.h> header file. */
+#undef HAVE_SYS_DLPI_H
+
 /* Define to 1 if you have the <sys/ioccom.h> header file. */
 #undef HAVE_SYS_IOCCOM_H
 
+/* Define to 1 if you have the <sys/net/nit.h> header file. */
+#undef HAVE_SYS_NET_NIT_H
+
 /* Define to 1 if you have the <sys/sockio.h> header file. */
 #undef HAVE_SYS_SOCKIO_H
 
index 08614a2928be0a741e394c46c923be79f3938560..ec86476bcc081882171fe47cf454fb47f12635c6 100755 (executable)
--- a/configure
+++ b/configure
@@ -5285,71 +5285,98 @@ if test "${with_pcap+set}" = set; then :
   withval=$with_pcap;
 fi
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking packet capture type" >&5
-$as_echo_n "checking packet capture type... " >&6; }
 if test ! -z "$with_pcap" ; then
        V_PCAP="$withval"
-elif test -r /dev/bpf -o -h /dev/bpf ; then
+else
        #
-       # Cloning BPF device.
+       # Check for a bunch of headers for various packet
+       # capture mechanisms.
        #
-       V_PCAP=bpf
+       for ac_header in net/bpf.h net/pfilt.h net/enet.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
 
-$as_echo "#define HAVE_CLONING_BPF 1" >>confdefs.h
+fi
 
+done
 
-       #
-       # We have BPF, so build valgrindtest with "make test".
-       #
-       VALGRINDTEST=valgrindtest
-elif test -r /dev/bpf0 ; then
-       V_PCAP=bpf
+       for ac_header in net/nit.h sys/net/nit.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
 
-       #
-       # We have BPF, so build valgrindtest with "make test".
-       #
-       VALGRINDTEST=valgrindtest
-elif test -r /usr/include/net/pfilt.h ; then
-       V_PCAP=pf
-elif test -r /dev/enet ; then
-       V_PCAP=enet
-elif test -r /dev/nit ; then
-       V_PCAP=snit
-elif test -r /usr/include/sys/net/nit.h ; then
-       V_PCAP=nit
-elif test -r /usr/include/linux/socket.h ; then
-       V_PCAP=linux
+fi
 
-       #
-       # XXX - this won't work with older kernels that have SOCK_PACKET
-       # sockets but not PF_PACKET sockets.
-       #
-       VALGRINDTEST=valgrindtest
-elif test -r /usr/include/net/raw.h ; then
-       V_PCAP=snoop
-elif test -r /usr/include/odmi.h ; then
-       #
-       # On AIX, the BPF devices might not yet be present - they're
-       # created the first time libpcap runs after booting.
-       # We check for odmi.h instead.
-       #
-       V_PCAP=bpf
-elif test -c /dev/bpf0 ; then          # check again in case not readable
-       V_PCAP=bpf
+done
 
-       #
-       # We have BPF, so build valgrindtest with "make test".
-       #
-       VALGRINDTEST=valgrindtest
-elif test -r /usr/include/sys/dlpi.h ; then
-       V_PCAP=dlpi
-elif test -c /dev/enet ; then          # check again in case not readable
-       V_PCAP=enet
-elif test -c /dev/nit ; then           # check again in case not readable
-       V_PCAP=snit
-else
-       V_PCAP=null
+       for ac_header in linux/socket.h net/raw.h sys/dlpi.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+       if test "$ac_cv_header_net_bpf_h" = yes; then
+               #
+               # BPF.
+               # Check this before DLPI, so that we pick BPF on
+               # Solaris 11 and later.
+               #
+               V_PCAP=bpf
+
+               #
+               # We have BPF, so build valgrindtest with "make test"
+               # on macOS, FreeBSD, and Linux (add your OS once
+               # there's a valgrind for it).
+               #
+               case "$host_os" in
+
+               freebsd*|darwin*|linux*)
+                       VALGRINDTEST=valgrindtest
+                       ;;
+               esac
+       elif test "$ac_cv_header_net_pfilt_h" = yes; then
+               V_PCAP=pf
+       elif test "$ac_cv_header_net_enet_h" = yes; then
+               V_PCAP=enet
+       elif test "$ac_header_net_nit_h" = yes; then
+               V_PCAP=snit
+       elif test "$ac_header_sys_net_nit_h" = yes; then
+               V_PCAP=nit
+       elif test "$ac_header_linux_socket_h" = yes; then
+               V_PCAP=linux
+
+               #
+               # XXX - this won't work with older kernels that have
+               # SOCK_PACKET sockets but not PF_PACKET sockets.
+               #
+               VALGRINDTEST=valgrindtest
+       elif test "$ac_header_net_raw_h" = yes; then
+               V_PCAP=snoop
+       elif test "$ac_header_sys_dlpi_h" = yes; then
+               V_PCAP=dlpi
+       else
+               V_PCAP=null
+       fi
 fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking packet capture type" >&5
+$as_echo_n "checking packet capture type... " >&6; }
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $V_PCAP" >&5
 $as_echo "$V_PCAP" >&6; }
 
index 5f534f630bf0d193e15b7cec924f411a90295928..77d502f1943a4a993db791331184115583c54098 100644 (file)
@@ -261,68 +261,85 @@ if test -z "$with_pcap" && test "$cross_compiling" = yes; then
 fi
 AC_ARG_WITH(pcap,
 AC_HELP_STRING([--with-pcap=TYPE],[use packet capture TYPE]))
-AC_MSG_CHECKING(packet capture type)
 if test ! -z "$with_pcap" ; then
        V_PCAP="$withval"
-elif test -r /dev/bpf -o -h /dev/bpf ; then
+else
        #
-       # Cloning BPF device.
+       # Check for a bunch of headers for various packet
+       # capture mechanisms.
        #
-       V_PCAP=bpf
-       AC_DEFINE(HAVE_CLONING_BPF,1,[define if you have a cloning BPF device])
+       AC_CHECK_HEADERS(net/bpf.h net/pfilt.h net/enet.h)
+       AC_CHECK_HEADERS(net/nit.h sys/net/nit.h)
+       AC_CHECK_HEADERS(linux/socket.h net/raw.h sys/dlpi.h)
 
-       #
-       # We have BPF, so build valgrindtest with "make test".
-       #
-       VALGRINDTEST=valgrindtest
-elif test -r /dev/bpf0 ; then
-       V_PCAP=bpf
+       if test "$ac_cv_header_net_bpf_h" = yes; then
+               #
+               # BPF.
+               # Check this before DLPI, so that we pick BPF on
+               # Solaris 11 and later.
+               #
+               V_PCAP=bpf
 
-       #
-       # We have BPF, so build valgrindtest with "make test".
-       #
-       VALGRINDTEST=valgrindtest
-elif test -r /usr/include/net/pfilt.h ; then
-       V_PCAP=pf
-elif test -r /dev/enet ; then
-       V_PCAP=enet
-elif test -r /dev/nit ; then
-       V_PCAP=snit
-elif test -r /usr/include/sys/net/nit.h ; then
-       V_PCAP=nit
-elif test -r /usr/include/linux/socket.h ; then
-       V_PCAP=linux
+               #
+               # We have BPF, so build valgrindtest with "make test"
+               # on macOS, FreeBSD, and Linux (add your OS once
+               # there's a valgrind for it).
+               #
+               case "$host_os" in
 
-       #
-       # XXX - this won't work with older kernels that have SOCK_PACKET
-       # sockets but not PF_PACKET sockets.
-       #
-       VALGRINDTEST=valgrindtest
-elif test -r /usr/include/net/raw.h ; then
-       V_PCAP=snoop
-elif test -r /usr/include/odmi.h ; then
-       #
-       # On AIX, the BPF devices might not yet be present - they're
-       # created the first time libpcap runs after booting.
-       # We check for odmi.h instead.
-       #
-       V_PCAP=bpf
-elif test -c /dev/bpf0 ; then          # check again in case not readable
-       V_PCAP=bpf
+               freebsd*|darwin*|linux*)
+                       VALGRINDTEST=valgrindtest
+                       ;;
+               esac
+       elif test "$ac_cv_header_net_pfilt_h" = yes; then
+               #
+               # DEC OSF/1, Digital UNIX, Tru64 UNIX
+               #
+               V_PCAP=pf
+       elif test "$ac_cv_header_net_enet_h" = yes; then
+               #
+               # Stanford Enetfilter.
+               #
+               V_PCAP=enet
+       elif test "$ac_header_net_nit_h" = yes; then
+               #
+               # SunOS 4.x STREAMS NIT.
+               #
+               V_PCAP=snit
+       elif test "$ac_header_sys_net_nit_h" = yes; then
+               #
+               # Pre-SunOS 4.x non-STREAMS NIT.
+               #
+               V_PCAP=nit
+       elif test "$ac_header_linux_socket_h" = yes; then
+               #
+               # No prizes for guessing this one.
+               #
+               V_PCAP=linux
 
-       #
-       # We have BPF, so build valgrindtest with "make test".
-       #
-       VALGRINDTEST=valgrindtest
-elif test -r /usr/include/sys/dlpi.h ; then
-       V_PCAP=dlpi
-elif test -c /dev/enet ; then          # check again in case not readable
-       V_PCAP=enet
-elif test -c /dev/nit ; then           # check again in case not readable
-       V_PCAP=snit
-else
-       V_PCAP=null
+               #
+               # XXX - this won't work with older kernels that have
+               # SOCK_PACKET sockets but not PF_PACKET sockets.
+               #
+               VALGRINDTEST=valgrindtest
+       elif test "$ac_header_net_raw_h" = yes; then
+               #
+               # IRIX snoop.
+               #
+               V_PCAP=snoop
+       elif test "$ac_header_sys_dlpi_h" = yes; then
+               #
+               # DLPI on pre-Solaris 11 SunOS 5, HP-UX, possibly others.
+               #
+               V_PCAP=dlpi
+       else
+               #
+               # Nothing we support.
+               #
+               V_PCAP=null
+       fi
 fi
+AC_MSG_CHECKING(packet capture type)
 AC_MSG_RESULT($V_PCAP)
 AC_SUBST(VALGRINDTEST)
 
index a6403780a81817b837e38b96b907f88a4cd22117..e821ff05105c73de22236327d517f41ba9341de7 100644 (file)
@@ -477,12 +477,10 @@ static int
 bpf_open(char *errbuf)
 {
        int fd;
-#ifdef HAVE_CLONING_BPF
-       static const char device[] = "/dev/bpf";
-#else
+       static const char cloning_device[] = "/dev/bpf";
        int n = 0;
        char device[sizeof "/dev/bpf0000000000"];
-#endif
+       static int no_cloning_bpf = 0;
 
 #ifdef _AIX
        /*
@@ -494,19 +492,32 @@ bpf_open(char *errbuf)
                return (PCAP_ERROR);
 #endif
 
-#ifdef HAVE_CLONING_BPF
-       if ((fd = open(device, O_RDWR)) == -1 &&
-           (errno != EACCES || (fd = open(device, O_RDONLY)) == -1)) {
-               if (errno == EACCES)
-                       fd = PCAP_ERROR_PERM_DENIED;
-               else
-                       fd = PCAP_ERROR;
-               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                 "(cannot open device) %s: %s", device, pcap_strerror(errno));
+       /*
+        * First, unless we've already tried opening /dev/bpf and
+        * gotten ENOENT, try opening /dev/bpf.
+        * If it fails with ENOENT, remember that, so we don't try
+        * again, and try /dev/bpfN.
+        */
+       if (!no_cloning_bpf &&
+           (fd = open(cloning_device, O_RDWR)) == -1 &&
+           ((errno != EACCES && errno != ENOENT) ||
+            (fd = open(cloning_device, O_RDONLY)) == -1)) {
+               if (errno != ENOENT) {
+                       if (errno == EACCES)
+                               fd = PCAP_ERROR_PERM_DENIED;
+                       else
+                               fd = PCAP_ERROR;
+                       pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                         "(cannot open device) %s: %s", device,
+                         pcap_strerror(errno));
+                       return (fd);
+               }
+               no_cloning_bpf = 1;
        }
-#else
+
        /*
-        * Go through all the minors and find one that isn't in use.
+        * Go through all the /dev/bpfN minors and find one that isn't
+        * in use.
         */
        do {
                (void)pcap_snprintf(device, sizeof(device), "/dev/bpf%d", n++);
@@ -580,7 +591,6 @@ bpf_open(char *errbuf)
                        break;
                }
        }
-#endif
 
        return (fd);
 }