]> The Tcpdump Group git mirrors - libpcap/commitdiff
From Scott Barron <[email protected]>: use the
authorguy <guy>
Sun, 29 Jul 2001 18:25:46 +0000 (18:25 +0000)
committerguy <guy>
Sun, 29 Jul 2001 18:25:46 +0000 (18:25 +0000)
SOL_PACKET/PACKET_STATISTICS "getsockopt()" call, on Linux kernels that
support it, to get packet statistics, so that we can report the number
of dropped packets, and always use <linux/if_packet.h> to get
definitions for PF_PACKET sockets, so that we don't depend on glibc's
header files having been updated to support all the latest shiniest
kernel features (many systems with 2.4[.x] kernels don't have a
<netpacket/packet.h> that defines "struct tpacket_stats", for example,
so we wouldn't have been able to support that kernel feature on those
systems).

CREDITS
README.linux
aclocal.m4
config.h.in
configure
configure.in
pcap-linux.c

diff --git a/CREDITS b/CREDITS
index 5537c1c10ce12729cf30317b6bfdd27f4ebfe1a4..3583847f643a6d49f57b753ab89cded2312b9165 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -37,6 +37,7 @@ Additional people who have contributed patches:
        Peter Jeremy                    <[email protected]>
        Rafal Maszkowski                <[email protected]>
        Rick Jones                      <[email protected]>
+       Scott Barron                    <[email protected]>
        Stefan Hudson                   <[email protected]>
        Tony Li                         <[email protected]>
        Uns Lider                       <[email protected]>
index ecd00e8fe89304c42cbd3d7f769267a72c9962cb..dd959139d3f9327746a0165c94813addc2011060 100644 (file)
@@ -68,3 +68,21 @@ file says:
          Filtering works on all socket types except TCP for now. See the text
          file linux/Documentation/networking/filter.txt for more information.
          If unsure, say N.
+
+
+Statistics:
+Statistics reported by pcap are platform specific.  The statistics
+reported by pcap_stats on Linux are as follows:
+
+2.2.x
+=====
+ps_recv   Number of packets that were accepted by the pcap filter
+ps_drops  Always 0, this statistic is not gatherd on this platform
+
+2.4.x
+=====
+ps_rec    Number of packets that were accepted by the pcap filter
+ps_drops  Number of packets that had passed filtering but were not
+          passed on to pcap due to things like buffer shortage, etc.
+                        This is useful because these are packets you are interested in
+                        but won't be reported by, for example, tcpdump output.
index e283bc82ba143c8b4f94fd6e9df5ba96b3f8104c..8f4d9ab5916103e00526f5d5f57496670c8e3968 100644 (file)
@@ -1,4 +1,4 @@
-dnl @(#) $Header: /tcpdump/master/libpcap/aclocal.m4,v 1.71 2000-09-19 03:56:26 guy Exp $ (LBL)
+dnl @(#) $Header: /tcpdump/master/libpcap/aclocal.m4,v 1.72 2001-07-29 18:25:46 guy Exp $ (LBL)
 dnl
 dnl Copyright (c) 1995, 1996, 1997, 1998
 dnl    The Regents of the University of California.  All rights reserved.
@@ -767,3 +767,21 @@ fi
 AC_MSG_RESULT($ac_cv___attribute__)
 ])
 
+dnl
+dnl Checks to see if tpacket_stats is defined in linux/if_packet.h
+dnl If so then pcap-linux.c can use this to report proper statistics.
+dnl
+dnl -Scott Barron
+dnl
+AC_DEFUN(AC_LBL_TPACKET_STATS,
+   [AC_MSG_CHECKING(if if_packet.h has tpacket_stats defined)
+   AC_CACHE_VAL(ac_cv_lbl_tpacket_stats,
+   AC_TRY_COMPILE([
+#  include <linux/if_packet.h>],
+   [struct tpacket_stats stats],
+   ac_cv_lbl_tpacket_stats=yes,
+   ac_cv_lbl_tpacket_stats=no))
+   AC_MSG_RESULT($ac_cv_lbl_tpacket_stats)
+   if test $ac_cv_lbl_tpacket_stats = yes; then
+       AC_DEFINE(HAVE_TPACKET_STATS,1,[if if_packet.h has tpacket_stats defined])
+   fi])
index f012a9d500d93a4d67a5da458fc0c8f09d566358..c02efadda33d716fc7f32b2fc66ca8cec2ee67ec 100644 (file)
@@ -24,9 +24,6 @@
 /* Define if you have the <netinet/if_ether.h> header file.  */
 #undef HAVE_NETINET_IF_ETHER_H
 
-/* Define if you have the <netpacket/packet.h> header file.  */
-#undef HAVE_NETPACKET_PACKET_H
-
 /* Define if you have the <sys/bufmod.h> header file.  */
 #undef HAVE_SYS_BUFMOD_H
 
@@ -66,6 +63,9 @@
 /* /dev/dlpi directory */
 #undef PCAP_DEV_PREFIX
 
+/* if if_packet.h has tpacket_stats defined */
+#undef HAVE_TPACKET_STATS
+
 /* define on AIX to get certain functions */
 #undef _SUN
 
index 5245a8a916d5c46ad5b5c72981843a506ae3fb9e..500502fc7014d518d5fd6c8692aaccd2488de34e 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,6 +1,7 @@
 #! /bin/sh
 
-# From configure.in Revision: 1.88 
+# From configure.in Revision: 1.89 
+
 
 
 
@@ -616,7 +617,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
 fi
 
 echo $ac_n "checking host system type""... $ac_c" 1>&6
-echo "configure:620: checking host system type" >&5
+echo "configure:621: checking host system type" >&5
 
 host_alias=$host
 case "$host_alias" in
@@ -637,7 +638,7 @@ host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
 echo "$ac_t""$host" 1>&6
 
 echo $ac_n "checking target system type""... $ac_c" 1>&6
-echo "configure:641: checking target system type" >&5
+echo "configure:642: checking target system type" >&5
 
 target_alias=$target
 case "$target_alias" in
@@ -655,7 +656,7 @@ target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
 echo "$ac_t""$target" 1>&6
 
 echo $ac_n "checking build system type""... $ac_c" 1>&6
-echo "configure:659: checking build system type" >&5
+echo "configure:660: checking build system type" >&5
 
 build_alias=$build
 case "$build_alias" in
@@ -703,7 +704,7 @@ fi
                    # Extract the first word of "shlicc2", so it can be a program name with args.
 set dummy shlicc2; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:707: checking for $ac_word" >&5
+echo "configure:708: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_SHLICC2'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -744,7 +745,7 @@ fi
     # Extract the first word of "gcc", so it can be a program name with args.
 set dummy gcc; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:748: checking for $ac_word" >&5
+echo "configure:749: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -774,7 +775,7 @@ if test -z "$CC"; then
   # Extract the first word of "cc", so it can be a program name with args.
 set dummy cc; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:778: checking for $ac_word" >&5
+echo "configure:779: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -825,7 +826,7 @@ fi
       # Extract the first word of "cl", so it can be a program name with args.
 set dummy cl; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:829: checking for $ac_word" >&5
+echo "configure:830: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -857,7 +858,7 @@ fi
 fi
 
 echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:861: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+echo "configure:862: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
 
 ac_ext=c
 # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
@@ -868,12 +869,12 @@ cross_compiling=$ac_cv_prog_cc_cross
 
 cat > conftest.$ac_ext << EOF
 
-#line 872 "configure"
+#line 873 "configure"
 #include "confdefs.h"
 
 main(){return(0);}
 EOF
-if { (eval echo configure:877: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:878: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   ac_cv_prog_cc_works=yes
   # If we can't run a trivial program, we are probably using a cross compiler.
   if (./conftest; exit) 2>/dev/null; then
@@ -899,12 +900,12 @@ if test $ac_cv_prog_cc_works = no; then
   { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
 fi
 echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:903: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "configure:904: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
 cross_compiling=$ac_cv_prog_cc_cross
 
 echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:908: checking whether we are using GNU C" >&5
+echo "configure:909: checking whether we are using GNU C" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -913,7 +914,7 @@ else
   yes;
 #endif
 EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:917: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:918: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
   ac_cv_prog_gcc=yes
 else
   ac_cv_prog_gcc=no
@@ -932,7 +933,7 @@ ac_test_CFLAGS="${CFLAGS+set}"
 ac_save_CFLAGS="$CFLAGS"
 CFLAGS=
 echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:936: checking whether ${CC-cc} accepts -g" >&5
+echo "configure:937: checking whether ${CC-cc} accepts -g" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -969,7 +970,7 @@ fi
                    V_CCOPT="-O2"
            else
                    echo $ac_n "checking gcc version""... $ac_c" 1>&6
-echo "configure:973: checking gcc version" >&5
+echo "configure:974: checking gcc version" >&5
                    if eval "test \"`echo '$''{'ac_cv_lbl_gcc_vers'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -987,19 +988,19 @@ fi
            fi
     else
            echo $ac_n "checking that $CC handles ansi prototypes""... $ac_c" 1>&6
-echo "configure:991: checking that $CC handles ansi prototypes" >&5
+echo "configure:992: checking that $CC handles ansi prototypes" >&5
            if eval "test \"`echo '$''{'ac_cv_lbl_cc_ansi_prototypes'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 996 "configure"
+#line 997 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 int main() {
 int frob(int, char *)
 ; return 0; }
 EOF
-if { (eval echo configure:1003: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1004: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_lbl_cc_ansi_prototypes=yes
 else
@@ -1017,21 +1018,21 @@ fi
 
                    hpux*)
                            echo $ac_n "checking for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE)""... $ac_c" 1>&6
-echo "configure:1021: checking for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE)" >&5
+echo "configure:1022: checking for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE)" >&5
                            savedcflags="$CFLAGS"
                            CFLAGS="-Aa -D_HPUX_SOURCE $CFLAGS"
                            if eval "test \"`echo '$''{'ac_cv_lbl_cc_hpux_cc_aa'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1028 "configure"
+#line 1029 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 int main() {
 int frob(int, char *)
 ; return 0; }
 EOF
-if { (eval echo configure:1035: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1036: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_lbl_cc_hpux_cc_aa=yes
 else
@@ -1075,12 +1076,12 @@ EOF
 
            ultrix*)
                    echo $ac_n "checking that Ultrix $CC hacks const in prototypes""... $ac_c" 1>&6
-echo "configure:1079: checking that Ultrix $CC hacks const in prototypes" >&5
+echo "configure:1080: checking that Ultrix $CC hacks const in prototypes" >&5
                    if eval "test \"`echo '$''{'ac_cv_lbl_cc_const_proto'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1084 "configure"
+#line 1085 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 int main() {
@@ -1088,7 +1089,7 @@ struct a { int b; };
                            void c(const struct a *)
 ; return 0; }
 EOF
-if { (eval echo configure:1092: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1093: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_lbl_cc_const_proto=yes
 else
@@ -1112,21 +1113,21 @@ EOF
     fi
 
 echo $ac_n "checking for inline""... $ac_c" 1>&6
-echo "configure:1116: checking for inline" >&5
+echo "configure:1117: checking for inline" >&5
 if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   ac_cv_c_inline=no
 for ac_kw in inline __inline__ __inline; do
   cat > conftest.$ac_ext <<EOF
-#line 1123 "configure"
+#line 1124 "configure"
 #include "confdefs.h"
 
 int main() {
 } $ac_kw foo() {
 ; return 0; }
 EOF
-if { (eval echo configure:1130: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1131: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_inline=$ac_kw; break
 else
@@ -1153,13 +1154,13 @@ esac
 
 
 echo $ac_n "checking for __attribute__""... $ac_c" 1>&6
-echo "configure:1157: checking for __attribute__" >&5
+echo "configure:1158: checking for __attribute__" >&5
 if eval "test \"`echo '$''{'ac_cv___attribute__'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 1163 "configure"
+#line 1164 "configure"
 #include "confdefs.h"
 
 #include <stdlib.h>
@@ -1176,7 +1177,7 @@ foo(void)
 
 ; return 0; }
 EOF
-if { (eval echo configure:1180: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1181: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv___attribute__=yes
 else
@@ -1198,12 +1199,12 @@ echo "$ac_t""$ac_cv___attribute__" 1>&6
 
 
 echo $ac_n "checking for u_int8_t using $CC""... $ac_c" 1>&6
-echo "configure:1202: checking for u_int8_t using $CC" >&5
+echo "configure:1203: checking for u_int8_t using $CC" >&5
     if eval "test \"`echo '$''{'ac_cv_lbl_have_u_int8_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1207 "configure"
+#line 1208 "configure"
 #include "confdefs.h"
 
 #      include "confdefs.h"
@@ -1216,7 +1217,7 @@ int main() {
 u_int8_t i
 ; return 0; }
 EOF
-if { (eval echo configure:1220: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1221: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_lbl_have_u_int8_t=yes
 else
@@ -1236,12 +1237,12 @@ EOF
 
     fi
 echo $ac_n "checking for u_int16_t using $CC""... $ac_c" 1>&6
-echo "configure:1240: checking for u_int16_t using $CC" >&5
+echo "configure:1241: checking for u_int16_t using $CC" >&5
     if eval "test \"`echo '$''{'ac_cv_lbl_have_u_int16_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1245 "configure"
+#line 1246 "configure"
 #include "confdefs.h"
 
 #      include "confdefs.h"
@@ -1254,7 +1255,7 @@ int main() {
 u_int16_t i
 ; return 0; }
 EOF
-if { (eval echo configure:1258: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1259: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_lbl_have_u_int16_t=yes
 else
@@ -1274,12 +1275,12 @@ EOF
 
     fi
 echo $ac_n "checking for u_int32_t using $CC""... $ac_c" 1>&6
-echo "configure:1278: checking for u_int32_t using $CC" >&5
+echo "configure:1279: checking for u_int32_t using $CC" >&5
     if eval "test \"`echo '$''{'ac_cv_lbl_have_u_int32_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1283 "configure"
+#line 1284 "configure"
 #include "confdefs.h"
 
 #      include "confdefs.h"
@@ -1292,7 +1293,7 @@ int main() {
 u_int32_t i
 ; return 0; }
 EOF
-if { (eval echo configure:1296: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1297: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_lbl_have_u_int32_t=yes
 else
@@ -1313,7 +1314,7 @@ EOF
     fi
 
 echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:1317: checking how to run the C preprocessor" >&5
+echo "configure:1318: checking how to run the C preprocessor" >&5
 # On Suns, sometimes $CPP names a directory.
 if test -n "$CPP" && test -d "$CPP"; then
   CPP=
@@ -1328,13 +1329,13 @@ else
   # On the NeXT, cc -E runs the code through the compiler's parser,
   # not just through cpp.
   cat > conftest.$ac_ext <<EOF
-#line 1332 "configure"
+#line 1333 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1338: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1339: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   :
@@ -1345,13 +1346,13 @@ else
   rm -rf conftest*
   CPP="${CC-cc} -E -traditional-cpp"
   cat > conftest.$ac_ext <<EOF
-#line 1349 "configure"
+#line 1350 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1355: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1356: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   :
@@ -1362,13 +1363,13 @@ else
   rm -rf conftest*
   CPP="${CC-cc} -nologo -E"
   cat > conftest.$ac_ext <<EOF
-#line 1366 "configure"
+#line 1367 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1372: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1373: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   :
@@ -1396,17 +1397,17 @@ for ac_hdr in sys/ioccom.h sys/sockio.h ifaddrs.h netinet/if_ether.h
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1400: checking for $ac_hdr" >&5
+echo "configure:1401: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1405 "configure"
+#line 1406 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1410: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1411: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -1435,12 +1436,12 @@ done
 
 if test "$GCC" = yes ; then
            echo $ac_n "checking for ANSI ioctl definitions""... $ac_c" 1>&6
-echo "configure:1439: checking for ANSI ioctl definitions" >&5
+echo "configure:1440: checking for ANSI ioctl definitions" >&5
            if eval "test \"`echo '$''{'ac_cv_lbl_gcc_fixincludes'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1444 "configure"
+#line 1445 "configure"
 #include "confdefs.h"
 /*
                     * This generates a "duplicate case value" when fixincludes
@@ -1459,7 +1460,7 @@ switch (0) {
                    }
 ; return 0; }
 EOF
-if { (eval echo configure:1463: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1464: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_lbl_gcc_fixincludes=yes
 else
@@ -1482,12 +1483,12 @@ fi
 for ac_func in ether_hostton strerror freeifaddrs strlcpy
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:1486: checking for $ac_func" >&5
+echo "configure:1487: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1491 "configure"
+#line 1492 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -1510,7 +1511,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:1514: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1515: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -1536,7 +1537,7 @@ done
 
 
 echo $ac_n "checking if --disable-protochain option is specified""... $ac_c" 1>&6
-echo "configure:1540: checking if --disable-protochain option is specified" >&5
+echo "configure:1541: checking if --disable-protochain option is specified" >&5
 # Check whether --enable-protochain or --disable-protochain was given.
 if test "${enable_protochain+set}" = set; then
   enableval="$enable_protochain"
@@ -1567,7 +1568,7 @@ if test "${with_pcap+set}" = set; then
 fi
 
 echo $ac_n "checking packet capture type""... $ac_c" 1>&6
-echo "configure:1571: checking packet capture type" >&5
+echo "configure:1572: checking packet capture type" >&5
 if test ! -z "$with_pcap" ; then
        V_PCAP="$withval"
 elif test -r /dev/bpf0 ; then
@@ -1598,7 +1599,7 @@ fi
 echo "$ac_t""$V_PCAP" 1>&6
 
 echo $ac_n "checking if --enable-ipv6 option is specified""... $ac_c" 1>&6
-echo "configure:1602: checking if --enable-ipv6 option is specified" >&5
+echo "configure:1603: checking if --enable-ipv6 option is specified" >&5
 # Check whether --enable-ipv6 or --disable-ipv6 was given.
 if test "${enable_ipv6+set}" = set; then
   enableval="$enable_ipv6"
@@ -1620,17 +1621,17 @@ dlpi)
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1624: checking for $ac_hdr" >&5
+echo "configure:1625: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1629 "configure"
+#line 1630 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1634: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1635: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -1657,7 +1658,7 @@ fi
 done
 
        echo $ac_n "checking for /dev/dlpi device""... $ac_c" 1>&6
-echo "configure:1661: checking for /dev/dlpi device" >&5
+echo "configure:1662: checking for /dev/dlpi device" >&5
        if test -c /dev/dlpi ; then
                echo "$ac_t""yes" 1>&6
                cat >> confdefs.h <<\EOF
@@ -1668,7 +1669,7 @@ EOF
                echo "$ac_t""no" 1>&6
                dir="/dev/dlpi"
                echo $ac_n "checking for $dir directory""... $ac_c" 1>&6
-echo "configure:1672: checking for $dir directory" >&5
+echo "configure:1673: checking for $dir directory" >&5
                if test -d $dir ; then
                        echo "$ac_t""yes" 1>&6
                        cat >> confdefs.h <<EOF
@@ -1682,48 +1683,8 @@ EOF
        ;;
 
 linux)
-       for ac_hdr in netpacket/packet.h
-do
-ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1690: checking for $ac_hdr" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  cat > conftest.$ac_ext <<EOF
-#line 1695 "configure"
-#include "confdefs.h"
-#include <$ac_hdr>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1700: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
-  rm -rf conftest*
-  eval "ac_cv_header_$ac_safe=yes"
-else
-  echo "$ac_err" >&5
-  echo "configure: failed program was:" >&5
-  cat conftest.$ac_ext >&5
-  rm -rf conftest*
-  eval "ac_cv_header_$ac_safe=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
-  echo "$ac_t""yes" 1>&6
-    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
-  cat >> confdefs.h <<EOF
-#define $ac_tr_hdr 1
-EOF
-else
-  echo "$ac_t""no" 1>&6
-fi
-done
-
        echo $ac_n "checking Linux kernel version""... $ac_c" 1>&6
-echo "configure:1727: checking Linux kernel version" >&5
+echo "configure:1688: checking Linux kernel version" >&5
        if test "$cross_compiling" = yes; then
                if eval "test \"`echo '$''{'ac_cv_linux_vers'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1747,6 +1708,39 @@ fi
        if test $ac_cv_linux_vers -lt 2 ; then
                { echo "configure: error: version 2 or higher required; see the INSTALL doc for more info" 1>&2; exit 1; }
        fi
+       echo $ac_n "checking if if_packet.h has tpacket_stats defined""... $ac_c" 1>&6
+echo "configure:1713: checking if if_packet.h has tpacket_stats defined" >&5
+   if eval "test \"`echo '$''{'ac_cv_lbl_tpacket_stats'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1718 "configure"
+#include "confdefs.h"
+
+#  include <linux/if_packet.h>
+int main() {
+struct tpacket_stats stats
+; return 0; }
+EOF
+if { (eval echo configure:1726: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_lbl_tpacket_stats=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_lbl_tpacket_stats=no
+fi
+rm -f conftest*
+fi
+
+   echo "$ac_t""$ac_cv_lbl_tpacket_stats" 1>&6
+   if test $ac_cv_lbl_tpacket_stats = yes; then
+       cat >> confdefs.h <<\EOF
+#define HAVE_TPACKET_STATS 1
+EOF
+
+   fi
        ;;
 
 null)
@@ -1776,7 +1770,7 @@ do
 # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1780: checking for $ac_word" >&5
+echo "configure:1774: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_V_LEX'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -1810,7 +1804,7 @@ test -n "$V_LEX" || V_LEX="lex"
     if test "$V_LEX" = flex ; then
            # The -V flag was added in 2.4
            echo $ac_n "checking for flex 2.4 or higher""... $ac_c" 1>&6
-echo "configure:1814: checking for flex 2.4 or higher" >&5
+echo "configure:1808: checking for flex 2.4 or higher" >&5
            if eval "test \"`echo '$''{'ac_cv_lbl_flex_v24'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -1836,7 +1830,7 @@ do
 # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1840: checking for $ac_word" >&5
+echo "configure:1834: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_V_YACC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -1883,7 +1877,7 @@ if test "$V_LEX" = lex ; then
 # Some versions of lex can't handle the definitions section of scanner.l .
 # Try lexing it and complain if it can't deal.
        echo $ac_n "checking for capable lex""... $ac_c" 1>&6
-echo "configure:1887: checking for capable lex" >&5
+echo "configure:1881: checking for capable lex" >&5
 if eval "test \"`echo '$''{'tcpdump_cv_capable_lex'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -1934,19 +1928,19 @@ EOF
 
 sinix*)
        echo $ac_n "checking if SINIX compiler defines sinix""... $ac_c" 1>&6
-echo "configure:1938: checking if SINIX compiler defines sinix" >&5
+echo "configure:1932: checking if SINIX compiler defines sinix" >&5
        if eval "test \"`echo '$''{'ac_cv_cc_sinix_defined'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1943 "configure"
+#line 1937 "configure"
 #include "confdefs.h"
 
 int main() {
 int i = sinix;
 ; return 0; }
 EOF
-if { (eval echo configure:1950: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1944: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_cc_sinix_defined=yes
 else
@@ -1978,7 +1972,7 @@ esac
 # Extract the first word of "ranlib", so it can be a program name with args.
 set dummy ranlib; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1982: checking for $ac_word" >&5
+echo "configure:1976: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -2046,12 +2040,12 @@ EOF
     fi
 
 echo $ac_n "checking if sockaddr struct has sa_len member""... $ac_c" 1>&6
-echo "configure:2050: checking if sockaddr struct has sa_len member" >&5
+echo "configure:2044: checking if sockaddr struct has sa_len member" >&5
     if eval "test \"`echo '$''{'ac_cv_lbl_sockaddr_has_sa_len'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2055 "configure"
+#line 2049 "configure"
 #include "confdefs.h"
 
 #      include <sys/types.h>
@@ -2060,7 +2054,7 @@ int main() {
 u_int i = sizeof(((struct sockaddr *)0)->sa_len)
 ; return 0; }
 EOF
-if { (eval echo configure:2064: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2058: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_lbl_sockaddr_has_sa_len=yes
 else
@@ -2081,12 +2075,12 @@ EOF
     fi
 
 echo $ac_n "checking if dl_hp_ppa_info_t struct has dl_module_id_1 member""... $ac_c" 1>&6
-echo "configure:2085: checking if dl_hp_ppa_info_t struct has dl_module_id_1 member" >&5
+echo "configure:2079: checking if dl_hp_ppa_info_t struct has dl_module_id_1 member" >&5
     if eval "test \"`echo '$''{'ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2090 "configure"
+#line 2084 "configure"
 #include "confdefs.h"
 
 #      include <sys/types.h>
@@ -2096,7 +2090,7 @@ int main() {
 u_int i = sizeof(((dl_hp_ppa_info_t *)0)->dl_module_id_1)
 ; return 0; }
 EOF
-if { (eval echo configure:2100: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2094: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1=yes
 else
@@ -2117,7 +2111,7 @@ EOF
     fi
 
 echo $ac_n "checking if unaligned accesses fail""... $ac_c" 1>&6
-echo "configure:2121: checking if unaligned accesses fail" >&5
+echo "configure:2115: checking if unaligned accesses fail" >&5
     if eval "test \"`echo '$''{'ac_cv_lbl_unaligned_fail'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -2202,7 +2196,7 @@ ln -s ${srcdir}/bpf/net net
 # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
 # ./install, which can be erroneously created by make from ./install.sh.
 echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:2206: checking for a BSD compatible install" >&5
+echo "configure:2200: checking for a BSD compatible install" >&5
 if test -z "$INSTALL"; then
 if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
index eefa3c3846020d65df6affed44274375e64ac9d1..6dd0f19382bcffb629ffcc10717cf5a1f7f66077 100644 (file)
@@ -1,4 +1,4 @@
-dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.88 2001-01-17 18:18:48 guy Exp $ (LBL)
+dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.89 2001-07-29 18:25:47 guy Exp $ (LBL)
 dnl
 dnl Copyright (c) 1994, 1995, 1996, 1997
 dnl    The Regents of the University of California.  All rights reserved.
@@ -6,7 +6,7 @@ dnl
 dnl Process this file with autoconf to produce a configure script.
 dnl
 
-AC_REVISION($Revision: 1.88 $)
+AC_REVISION($Revision: 1.89 $)
 AC_INIT(pcap.c)
 
 AC_CANONICAL_SYSTEM
@@ -116,7 +116,6 @@ dlpi)
        ;;
 
 linux)
-       AC_CHECK_HEADERS(netpacket/packet.h)
        AC_MSG_CHECKING(Linux kernel version)
        if test "$cross_compiling" = yes; then
                AC_CACHE_VAL(ac_cv_linux_vers,
@@ -133,6 +132,7 @@ linux)
        if test $ac_cv_linux_vers -lt 2 ; then
                AC_MSG_ERROR(version 2 or higher required; see the INSTALL doc for more info)
        fi
+       AC_LBL_TPACKET_STATS
        ;;
 
 null)
index ea8b30b9327fb296d1d3bc156d9d257ae7d78cb7..2b1604c68de351e3193d7fe2335288348b44f20b 100644 (file)
@@ -26,7 +26,7 @@
  */
 #ifndef lint
 static const char rcsid[] =
-    "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.60 2001-07-29 01:22:41 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.61 2001-07-29 18:25:47 guy Exp $ (LBL)";
 #endif
 
 /*
@@ -74,37 +74,38 @@ static const char rcsid[] =
 #include <linux/if_ether.h>
 #include <net/if_arp.h>
 
-#ifdef HAVE_NETPACKET_PACKET_H
-# include <netpacket/packet.h>
-
- /*
-  * We assume this means we really do have PF_PACKET sockets.
-  */
-# define HAVE_PF_PACKET_SOCKETS
-#else
- /*
-  * Oh, joy.  Some Linux distributions have 2.2 or later kernels and
-  * libc5.  On at least one of those systems (Slackware 4.0), it
-  * appears that "/usr/include/sys/socket.h" includes <linux/socket.h>,
-  * which means it picks up all the AF_, PF_, and SO_ definitions
-  * appropriate for the current kernel; however, it also appears that
-  * they did not see fit to provide a "/usr/include/netpacket/packet.h"
-  * file.
-  *
-  * However, you should be able to get the right definitions by including
-  * <linux/if_packet.h>.
-  *
-  * So if this system has PF_PACKET defined but doesn't have the
-  * <netpacket/packet.h> header file, we include <linux/if_packet.h>
-  * instead.
-  */
-# ifdef PF_PACKET
-#  include <linux/if_packet.h>
+/*
+ * If PF_PACKET is defined, we can use {SOCK_RAW,SOCK_DGRAM}/PF_PACKET
+ * sockets rather than SOCK_PACKET sockets.
+ *
+ * To use them, we include <linux/if_packet.h> rather than
+ * <netpacket/packet.h>; we do so because
+ *
+ *     some Linux distributions (e.g., Slackware 4.0) have 2.2 or
+ *     later kernels and libc5, and don't provide a <netpacket/packet.h>
+ *     file;
+ *
+ *     not all versions of glibc2 have a <netpacket/packet.h> file
+ *     that defines stuff needed for some of the 2.4-or-later-kernel
+ *     features, so if the system has a 2.4 or later kernel, we
+ *     still can't use those features.
+ *
+ * We're already including a number of other <linux/XXX.h> headers, and
+ * this code is Linux-specific (no other OS has PF_PACKET sockets as
+ * a raw packet capture mechanism), so it's not as if you gain any
+ * useful portability by using <netpacket/packet.h>
+ *
+ * XXX - should we just include <linux/if_packet.h> even if PF_PACKET
+ * isn't defined?  It only defines one data structure in 2.0.x, so
+ * it shouldn't cause any problems.
+ */
+#ifdef PF_PACKET  
+# include <linux/if_packet.h>
 
  /*
-  * However, on at least some Linux distributions (for example, Red Hat
-  * 5.2), there's no <netpacket/packet.h> file, but PF_PACKET is defined
-  * if you include <sys/socket.h>, but <linux/if_packet.h> doesn't define
+  * On at least some Linux distributions (for example, Red Hat 5.2),
+  * there's no <netpacket/packet.h> file, but PF_PACKET is defined if
+  * you include <sys/socket.h>, but <linux/if_packet.h> doesn't define
   * any of the PF_PACKET stuff such as "struct sockaddr_ll" or any of
   * the PACKET_xxx stuff.
   *
@@ -114,8 +115,7 @@ static const char rcsid[] =
 # ifdef PACKET_HOST
 #  define HAVE_PF_PACKET_SOCKETS
 # endif /* PACKET_HOST */
-# endif /* PF_PACKET */
-#endif /* HAVE_NETPACKET_PACKET_H */
+#endif /* PF_PACKET */
 
 #ifdef SO_ATTACH_FILTER
 #include <linux/types.h>
@@ -440,8 +440,42 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
        pcap_header.caplen      = caplen;
        pcap_header.len         = packet_len;
 
-       /* Call the user supplied callback function */
+       /*
+        * Count the packet.
+        *
+        * Arguably, we should count them before we check the filter,
+        * as on many other platforms "ps_recv" counts packets
+        * handed to the filter rather than packets that passed
+        * the filter, but if filtering is done in the kernel, we
+        * can't get a count of packets that passed the filter,
+        * and that would mean the meaning of "ps_recv" wouldn't
+        * be the same on all Linux systems.
+        *
+        * XXX - it's not the same on all systems in any case;
+        * ideally, we should have a "get the statistics" call
+        * that supplies more counts and indicates which of them
+        * it supplies, so that we supply a count of packets
+        * handed to the filter only on platforms where that
+        * information is available.
+        *
+        * We count them here even if we can get the packet count
+        * from the kernel, as we can only determine at run time
+        * whether we'll be able to get it from the kernel (if
+        * HAVE_TPACKET_STATS isn't defined, we can't get it from
+        * the kernel, but if it is defined, the library might
+        * have been built with a 2.4 or later kernel, but we
+        * might be running on a 2.2[.x] kernel without Alexey
+        * Kuznetzov's turbopacket patches, and thus the kernel
+        * might not be able to supply those statistics).  We
+        * could, I guess, try, when opening the socket, to get
+        * the statistics, and if we can not increment the count
+        * here, but it's not clear that always incrementing
+        * the count is more expensive than always testing a flag
+        * in memory.
+        */
        handle->md.stat.ps_recv++;
+
+       /* Call the user supplied callback function */
        callback(userdata, &pcap_header, handle->buffer + handle->offset);
 
        return 1;
@@ -449,15 +483,33 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
 
 /*
  *  Get the statistics for the given packet capture handle.
- *  FIXME: Currently does not report the number of dropped packets.
+ *  Reports the number of dropped packets iff the kernel supports
+ *  the PACKET_STATISTICS "getsockopt()" argument (2.4 and later
+ *  kernels, and 2.2[.x] kernels with Alexey Kuznetzov's turbopacket
+ *  patches); otherwise, that information isn't available, and we lie
+ *  and report 0 as the count of dropped packets.
  */
 int
 pcap_stats(pcap_t *handle, struct pcap_stat *stats)
 {
+#ifdef HAVE_TPACKET_STATS
+       struct tpacket_stats kstats;
+       socklen_t len;
+
+       /*
+        * Try to get the packet counts from the kernel.
+        */
+       if (getsockopt(handle->fd, SOL_PACKET, PACKET_STATISTICS,
+                       &kstats, &len) > -1) {
+               handle->md.stat.ps_recv = (kstats.tp_packets - kstats.tp_drops);
+               handle->md.stat.ps_drop = kstats.tp_drops;
+       }
+#endif
        /*
         * "ps_recv" counts only packets that passed the filter.
         *
-        * "ps_drop" isn't maintained.
+        * "ps_drop" is maintained only on systems that support
+        * the PACKET_STATISTICS "getsockopt()" argument.
         */
        *stats = handle->md.stat;
        return 0;