ongrep

A cleaned up fork of ngrep for OpenBSD
git clone git://git.sgregoratto.me/ongrep
Log | Files | Refs | README | LICENSE

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:
Mconfigure | 361+++++++++++++++++++++++++++++--------------------------------------------------
Mconfigure.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