commit 806985cfde7bc2678f5411db63f7c973442abcb6
parent 9fe5368ffce8e9f27a5534e82f99f5aace22737a
Author: Jordan Ritter <jpr5@darkridge.com>
Date: Thu, 22 May 2014 12:42:06 -0700
Invert BPF lexer restart default - don't unless specified
Addresses Github issue #2.
Diffstat:
M | configure | | | 361 | +++++++++++++++++++++++++++++-------------------------------------------------- |
M | configure.in | | | 142 | +++++++++++++++++++++++++++++++++++++++++++------------------------------------ |
2 files changed, 210 insertions(+), 293 deletions(-)
diff --git a/configure b/configure
@@ -659,10 +659,10 @@ SHELL'
ac_subst_files=''
ac_user_opts='
enable_option_checking
-enable_pcap_restart
with_dropprivs_user
enable_dropprivs
enable_ipv6
+enable_pcap_restart
enable_pcre
enable_tcpkill
with_pcap_includes
@@ -1288,9 +1288,9 @@ Optional Features:
--disable-option-checking ignore unrecognized --enable/--with options
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
- --disable-pcap-restart disable libpcap restart in parser
--disable-dropprivs disable privilege dropping logic
--enable-ipv6 enable IPv6 (and ICMPv6) support
+ --enable-pcap-restart enable BPF lexer restart bugfix for older versions of PCAP
--enable-pcre use PCRE instead of GNU regex
--enable-tcpkill enable connection killing support
@@ -3324,25 +3324,6 @@ EXTRA_LIBS=""
-# Check whether --enable-pcap-restart was given.
-if test "${enable_pcap_restart+set}" = set; then :
- enableval=$enable_pcap_restart;
- use_pcap_restart="$enableval"
-
-else
-
- use_pcap_restart="yes"
-
-fi
-
-
-if test $use_pcap_restart = yes; then
- USE_PCAP_RESTART="1"
-else
- USE_PCAP_RESTART="0"
-fi
-
-
# Check whether --with-dropprivs-user was given.
if test "${with_dropprivs_user+set}" = set; then :
@@ -3395,6 +3376,19 @@ else
fi
+# Check whether --enable-pcap-restart was given.
+if test "${enable_pcap_restart+set}" = set; then :
+ enableval=$enable_pcap_restart;
+ USE_PCAP_RESTART="1"
+
+else
+
+ USE_PCAP_RESTART="0"
+
+fi
+
+
+
REGEX_DIR=''
REGEX_OBJS=''
@@ -3479,22 +3473,6 @@ case "$target_os" in
OS=BSD
- if test "$USE_PCAP_RESTART" = "0"; then
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: !!! warning: Your OS ($target_os) may have an old libpcap installation.
-If the resulting ngrep binary segfaults when a BPF filter is specified
-without an ngrep match string then you should reconfigure ngrep with
-the option \`\`--disable-pcap-restart''.
-" >&5
-$as_echo "$as_me: WARNING: !!! warning: Your OS ($target_os) may have an old libpcap installation.
-If the resulting ngrep binary segfaults when a BPF filter is specified
-without an ngrep match string then you should reconfigure ngrep with
-the option \`\`--disable-pcap-restart''.
-" >&2;}
- sleep 3
-
- fi
-
;;
*solaris*)
@@ -3699,6 +3677,115 @@ fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcap_open_live in -lpcap" >&5
+$as_echo_n "checking for pcap_open_live in -lpcap... " >&6; }
+if ${ac_cv_lib_pcap_pcap_open_live+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpcap $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 pcap_open_live ();
+int
+main ()
+{
+return pcap_open_live ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_pcap_pcap_open_live=yes
+else
+ ac_cv_lib_pcap_pcap_open_live=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_pcap_pcap_open_live" >&5
+$as_echo "$ac_cv_lib_pcap_pcap_open_live" >&6; }
+if test "x$ac_cv_lib_pcap_pcap_open_live" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBPCAP 1
+_ACEOF
+
+ LIBS="-lpcap $LIBS"
+
+else
+ echo !!! error: need a viable pcap lib; exit
+fi
+
+
+
+if test "$USE_PCAP_RESTART" = "1"; then
+ PCAP_RESTART_FUNC="unused"
+
+ for func in pcap_restart pcap_yyrestart yyrestart; do
+ as_ac_Lib=`$as_echo "ac_cv_lib_pcap_$func" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $func in -lpcap" >&5
+$as_echo_n "checking for $func in -lpcap... " >&6; }
+if eval \${$as_ac_Lib+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpcap $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 $func ();
+int
+main ()
+{
+return $func ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$as_ac_Lib=yes"
+else
+ eval "$as_ac_Lib=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+eval ac_res=\$$as_ac_Lib
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then :
+ found="$func"
+fi
+
+ if test -n "$found"; then
+ USE_PCAP_RESTART="1"
+ PCAP_RESTART_FUNC="$found"
+ break
+ fi
+ done
+
+ if test "$PCAP_RESTART_FUNC" = "unused"; then
+ as_fn_error but no restart function found "BPF lexer restart fix requested" "$LINENO" 5
+ fi
+fi
+
+
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BPF include path" >&5
$as_echo_n "checking for BPF include path... " >&6; }
BPF=`/usr/bin/perl -ne '/include\s+<(.*bpf\.h)>/ && print "$1\n"' $pcap_base/pcap.h`
@@ -3842,6 +3929,11 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
+cat >>confdefs.h <<_ACEOF
+#define PCAP_RESTART_FUNC $PCAP_RESTART_FUNC
+_ACEOF
+
+
cat >>confdefs.h <<_ACEOF
#define USE_PCRE $USE_PCRE
@@ -3908,200 +4000,11 @@ _ACEOF
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcap_open_live in -lpcap" >&5
-$as_echo_n "checking for pcap_open_live in -lpcap... " >&6; }
-if ${ac_cv_lib_pcap_pcap_open_live+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lpcap $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 pcap_open_live ();
-int
-main ()
-{
-return pcap_open_live ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_pcap_pcap_open_live=yes
-else
- ac_cv_lib_pcap_pcap_open_live=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_pcap_pcap_open_live" >&5
-$as_echo "$ac_cv_lib_pcap_pcap_open_live" >&6; }
-if test "x$ac_cv_lib_pcap_pcap_open_live" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBPCAP 1
-_ACEOF
-
- LIBS="-lpcap $LIBS"
-
-else
- echo !!! error: need a viable pcap lib; exit
-fi
-
-
-
-pcap_restart_func=""
-if test "$use_pcap_restart" = "yes" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcap_restart in -lpcap" >&5
-$as_echo_n "checking for pcap_restart in -lpcap... " >&6; }
-if ${ac_cv_lib_pcap_pcap_restart+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lpcap $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 pcap_restart ();
-int
-main ()
-{
-return pcap_restart ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_pcap_pcap_restart=yes
-else
- ac_cv_lib_pcap_pcap_restart=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_pcap_pcap_restart" >&5
-$as_echo "$ac_cv_lib_pcap_pcap_restart" >&6; }
-if test "x$ac_cv_lib_pcap_pcap_restart" = xyes; then :
- pcap_restart_func="pcap_restart"
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcap_yyrestart in -lpcap" >&5
-$as_echo_n "checking for pcap_yyrestart in -lpcap... " >&6; }
-if ${ac_cv_lib_pcap_pcap_yyrestart+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lpcap $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 pcap_yyrestart ();
-int
-main ()
-{
-return pcap_yyrestart ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_pcap_pcap_yyrestart=yes
-else
- ac_cv_lib_pcap_pcap_yyrestart=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_pcap_pcap_yyrestart" >&5
-$as_echo "$ac_cv_lib_pcap_pcap_yyrestart" >&6; }
-if test "x$ac_cv_lib_pcap_pcap_yyrestart" = xyes; then :
- pcap_restart_func="pcap_yyrestart"
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for yyrestart in -lpcap" >&5
-$as_echo_n "checking for yyrestart in -lpcap... " >&6; }
-if ${ac_cv_lib_pcap_yyrestart+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lpcap $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 yyrestart ();
-int
-main ()
-{
-return yyrestart ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_pcap_yyrestart=yes
-else
- ac_cv_lib_pcap_yyrestart=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_pcap_yyrestart" >&5
-$as_echo "$ac_cv_lib_pcap_yyrestart" >&6; }
-if test "x$ac_cv_lib_pcap_yyrestart" = xyes; then :
- pcap_restart_func="yyrestart"
-else
- echo no yacc restart func found
- echo perhaps libpcap wasn\'t compiled with bison/flex\?
- exit
-fi
-
-fi
-
-fi
-
-fi
-
-if test -z "$pcap_restart_func"; then
- pcap_restart_func="unused"
-fi
-
-
-cat >>confdefs.h <<_ACEOF
-#define PCAP_RESTART_FUNC $pcap_restart_func
-_ACEOF
-
-
-
echo
-if test "$USE_PCAP_RESTART" = "0"; then
- echo "CONFIG: pcap restart logic disabled"
+if test "$USE_PCAP_RESTART" = "1"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: CONFIG: BPF filter lexer restart enabled (using $PCAP_RESTART_FUNC)" >&5
+$as_echo "CONFIG: BPF filter lexer restart enabled (using $PCAP_RESTART_FUNC)" >&6; }
fi
if test "$USE_IPv6" = "1"; then
diff --git a/configure.in b/configure.in
@@ -31,29 +31,6 @@ dnl Define the arguments that we accept. Parse them first.
dnl
dnl
-dnl For libpcap's that don't need the restart function called for multiple lexer
-dnl passes, allow them to turn it off here. This option exists solely to
-dnl address a very rude email from the pcap maintainer indicating that it
-dnl shouldn't be called directly (and of course he was wrong because this is
-dnl still needed on some older platforms).
-dnl
-
-AC_ARG_ENABLE(pcap-restart,
-[ --disable-pcap-restart disable libpcap restart in parser],
-[
- use_pcap_restart="$enableval"
-],
-[
- use_pcap_restart="yes"
-])
-
-if test $use_pcap_restart = yes; then
- USE_PCAP_RESTART="1"
-else
- USE_PCAP_RESTART="0"
-fi
-
-dnl
dnl Allow user to specify alternate ``nobody'' user.
dnl
@@ -104,6 +81,52 @@ else
USE_IPv6="0"
fi
+dnl
+dnl PCAP BPF filter expression lexer bugfix
+dnl
+dnl Typically ngrep is invoked with a (optional) search string plus a BPF
+dnl filter. However, ngrep doesn't semantically understand BPF filter terms
+dnl itself, so it assumes the first non-option parameter is the search string,
+dnl and attempts to compile the remainder as the BPF filter expression. If the
+dnl compilation fails, it probably means that no search string was specified, so
+dnl it restarts the BPF filter expression lexer and attempts to compile the
+dnl entire non-option parameter string as the expression. If that fails, then
+dnl the specified BPF filter expression is definitely bogus and ngrep errors
+dnl out.
+dnl
+dnl I favored this approach because it made invocation simpler & more fluid. In
+dnl order to make it work however, I had to solve for a bug in older versions of
+dnl libpcap where the library would segfault if the BPF filter compilation
+dnl function was invoked more than once. The workaround turned out to be a
+dnl simple invocation of the lexer's restart function in between compilation
+dnl invocations, however that function wasn't normally exposed in the header
+dnl since it was an internal built-in of whatever grammar lexer libpcap had
+dnl compiled with (bison/yacc/etc).
+dnl
+dnl The default behavior has long been to restart the lexer (keeping invocation
+dnl simpler) and provide a compile-time option to disable the mechanism, if
+dnl anyone cared to. Based on a more recent bug report however[1], it seems
+dnl that the newer libpcap breaks when the lexer restart function is called.
+dnl So, given the choice between old platforms working by default (always call
+dnl restart/allow disablement at compile-time) vs. newer platforms working by
+dnl default (never call restart/allow enablement at compile-time), the default
+dnl behavior now is to do the latter.
+dnl
+dnl For versions of libpcap that require restart function invocation in between
+dnl multiple lexer passes, allow them to enable it here.
+dnl
+dnl [1] https://github.com/jpr5/ngrep/issues/2
+dnl
+
+AC_ARG_ENABLE(pcap-restart,
+[ --enable-pcap-restart enable BPF lexer restart bugfix for older versions of PCAP],
+[
+ USE_PCAP_RESTART="1"
+],
+[
+ USE_PCAP_RESTART="0"
+])
+
dnl
dnl Configure the regular expression library.
@@ -186,18 +209,6 @@ case "$target_os" in
*bsd*)
AC_SUBST(OS, BSD)
- if test "$USE_PCAP_RESTART" = "0"; then
-
- AC_MSG_WARN(
-!!! warning: Your OS ($target_os) may have an old libpcap installation.
-If the resulting ngrep binary segfaults when a BPF filter is specified
-without an ngrep match string then you should reconfigure ngrep with
-the option ``--disable-pcap-restart''.
-)
- sleep 3
-
- fi
-
;;
*solaris*)
@@ -310,6 +321,34 @@ fi
dnl
+dnl Check for a working PCAP library we can link against..
+dnl
+
+AC_CHECK_LIB(pcap, pcap_open_live,,echo !!! error: need a viable pcap lib; exit)
+
+dnl
+dnl And the PCAP restart function.
+dnl
+
+if test "$USE_PCAP_RESTART" = "1"; then
+ PCAP_RESTART_FUNC="unused"
+
+ for func in pcap_restart pcap_yyrestart yyrestart; do
+ AC_CHECK_LIB(pcap, $func, found="$func")
+ if test -n "$found"; then
+ USE_PCAP_RESTART="1"
+ PCAP_RESTART_FUNC="$found"
+ break
+ fi
+ done
+
+ if test "$PCAP_RESTART_FUNC" = "unused"; then
+ AC_MSG_ERROR(BPF lexer restart fix requested, but no restart function found)
+ fi
+fi
+
+
+dnl
dnl Next figure out which bpf header file to look at.
dnl
@@ -397,7 +436,8 @@ dnl Now that we're past the OS-specific stuff, which could have
dnl modified our USE_* and other defines, define them all now.
dnl
-AC_DEFINE_UNQUOTED(USE_PCAP_RESTART, $USE_PCAP_RESTART, [whether to call pcap_restart() before subsequent invocations of pcap_compile() (default yes)])
+AC_DEFINE_UNQUOTED(USE_PCAP_RESTART, $USE_PCAP_RESTART, [whether to call the BPF lexer restart function between multiple BPF filter compilation attempts (default no)])
+AC_DEFINE_UNQUOTED(PCAP_RESTART_FUNC, $PCAP_RESTART_FUNC, [routine used for restarting the BPF lexer])
AC_DEFINE_UNQUOTED(USE_PCRE, $USE_PCRE, [whether to use PCRE (default GNU Regex)])
AC_DEFINE_UNQUOTED(USE_IPv6, $USE_IPv6, [whether to use IPv6 (default off)])
@@ -424,39 +464,13 @@ AC_SUBST(EXTRA_OBJS)
AC_SUBST(EXTRA_LIBS)
dnl
-dnl And the PCAP library..
-dnl
-
-AC_CHECK_LIB(pcap, pcap_open_live,,echo !!! error: need a viable pcap lib; exit)
-
-dnl
-dnl And the PCAP restart function..
-dnl
-
-pcap_restart_func=""
-if test "$use_pcap_restart" = "yes" ; then
- AC_CHECK_LIB(pcap, pcap_restart, pcap_restart_func="pcap_restart",
- AC_CHECK_LIB(pcap, pcap_yyrestart, pcap_restart_func="pcap_yyrestart",
- AC_CHECK_LIB(pcap, yyrestart, pcap_restart_func="yyrestart",
- echo no yacc restart func found
- echo perhaps libpcap wasn\'t compiled with bison/flex\?
- exit)))
-fi
-
-if test -z "$pcap_restart_func"; then
- pcap_restart_func="unused"
-fi
-
-AC_DEFINE_UNQUOTED(PCAP_RESTART_FUNC, $pcap_restart_func, [routine used for restarting the PCAP lexer])
-
-dnl
dnl Emit configuration messages about any flags specified.
dnl
echo
-if test "$USE_PCAP_RESTART" = "0"; then
- echo "CONFIG: pcap restart logic disabled"
+if test "$USE_PCAP_RESTART" = "1"; then
+ AC_MSG_RESULT([CONFIG: BPF filter lexer restart enabled (using $PCAP_RESTART_FUNC)])
fi
if test "$USE_IPv6" = "1"; then