Browse Source

Import upstream version 4.3.3

Fred Klassen 4 years ago
parent
commit
e275e34f9b
67 changed files with 675 additions and 476 deletions
  1. 1 0
      Makefile.in
  2. 115 118
      configure
  3. 60 45
      configure.ac
  4. 20 1
      docs/CHANGELOG
  5. 1 0
      docs/Makefile.in
  6. 1 0
      lib/Makefile.in
  7. 1 0
      libopts/Makefile.in
  8. 1 1
      libopts/boolean.c
  9. 1 0
      libopts/configfile.c
  10. 1 0
      scripts/Makefile.in
  11. 1 0
      src/Makefile.in
  12. 2 0
      src/bridge.c
  13. 1 1
      src/common/Makefile.am
  14. 4 4
      src/common/Makefile.in
  15. 29 18
      src/common/flows.c
  16. 49 27
      src/common/get.c
  17. 5 5
      src/common/get.h
  18. 1 1
      src/common/git_version.c
  19. 8 5
      src/common/sendpacket.c
  20. 23 3
      src/common/utils.c
  21. 3 7
      src/config.h.in
  22. 13 5
      src/defines.h
  23. 13 5
      src/defines.h.in
  24. 1 0
      src/fragroute/Makefile.in
  25. 1 0
      src/fragroute/fragroute.c
  26. 1 0
      src/fragroute/mod.c
  27. 1 0
      src/fragroute/mod_ip_frag.c
  28. 1 0
      src/fragroute/mod_tcp_seg.c
  29. 1 1
      src/fragroute/pkt.h
  30. 29 28
      src/send_packets.c
  31. 2 2
      src/sleep.h
  32. 2 2
      src/tcpbridge.1
  33. 1 1
      src/tcpbridge_opts.c
  34. 1 1
      src/tcpcapinfo.1
  35. 1 1
      src/tcpcapinfo.c
  36. 1 4
      src/tcpedit/Makefile.in
  37. 35 15
      src/tcpedit/checksum.c
  38. 63 103
      src/tcpedit/edit_packet.c
  39. 5 5
      src/tcpedit/edit_packet.h
  40. 1 1
      src/tcpedit/fuzzing.c
  41. 16 7
      src/tcpedit/plugins/dlt_en10mb/en10mb.c
  42. 2 1
      src/tcpedit/plugins/dlt_hdlc/hdlc.c
  43. 0 1
      src/tcpedit/plugins/dlt_jnpr_ether/Makefile.am
  44. 0 1
      src/tcpedit/plugins/dlt_pppserial/Makefile.am
  45. 2 1
      src/tcpedit/plugins/dlt_user/user.c
  46. 38 12
      src/tcpedit/portmap.c
  47. 2 2
      src/tcpedit/portmap.h
  48. 20 6
      src/tcpedit/rewrite_sequence.c
  49. 4 5
      src/tcpedit/rewrite_sequence.h
  50. 10 7
      src/tcpedit/tcpedit.c
  51. 1 1
      src/tcpedit/tcpedit_opts.def
  52. 1 1
      src/tcpliveplay.1
  53. 2 0
      src/tcpliveplay.c
  54. 1 1
      src/tcpprep.1
  55. 6 1
      src/tcpprep.c
  56. 11 1
      src/tcpr.h
  57. 2 2
      src/tcpreplay-edit.1
  58. 1 1
      src/tcpreplay.1
  59. 1 1
      src/tcpreplay.c
  60. 8 3
      src/tcpreplay_api.c
  61. 1 1
      src/tcpreplay_edit_opts.c
  62. 2 2
      src/tcprewrite.1
  63. 2 2
      src/tcprewrite.c
  64. 1 1
      src/tcprewrite_opts.c
  65. 1 1
      src/timestamp_trace.h
  66. 38 4
      src/tree.c
  67. 1 0
      test/Makefile.in

+ 1 - 0
Makefile.in

@@ -324,6 +324,7 @@ am__untar = @am__untar@
 bindir = @bindir@
 build = @build@
 build_alias = @build_alias@
+build_asan = @build_asan@
 build_cpu = @build_cpu@
 build_os = @build_os@
 build_vendor = @build_vendor@

+ 115 - 118
configure

@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for tcpreplay 4.3.2.
+# Generated by GNU Autoconf 2.69 for tcpreplay 4.3.3.
 #
 # Report bugs to <https://github.com/appneta/tcpreplay/issues>.
 #
@@ -590,8 +590,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='tcpreplay'
 PACKAGE_TARNAME='tcpreplay'
-PACKAGE_VERSION='4.3.2'
-PACKAGE_STRING='tcpreplay 4.3.2'
+PACKAGE_VERSION='4.3.3'
+PACKAGE_STRING='tcpreplay 4.3.3'
 PACKAGE_BUGREPORT='https://github.com/appneta/tcpreplay/issues'
 PACKAGE_URL='http://tcpreplay.sourceforge.net/'
 
@@ -681,6 +681,7 @@ timestamp_trace_flag
 extra_debug_flag
 debug_run_time_flag
 debug_flag
+build_asan
 WORDS_BIGENDIAN_FALSE
 WORDS_BIGENDIAN_TRUE
 SYSTEM_STRLCPY_FALSE
@@ -845,6 +846,7 @@ with_gnu_ld
 with_sysroot
 enable_libtool_lock
 enable_largefile
+enable_asan
 enable_debug
 enable_extra_debug
 enable_timestamp_trace
@@ -1443,7 +1445,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures tcpreplay 4.3.2 to adapt to many kinds of systems.
+\`configure' configures tcpreplay 4.3.3 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1515,7 +1517,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of tcpreplay 4.3.2:";;
+     short | recursive ) echo "Configuration of tcpreplay 4.3.3:";;
    esac
   cat <<\_ACEOF
 
@@ -1538,6 +1540,7 @@ Optional Features:
                           optimize for fast installation [default=yes]
   --disable-libtool-lock  avoid locking (might break parallel builds)
   --disable-largefile     omit support for large files
+  --enable-asan           Enable Address Sanitizer support
   --enable-debug          Enable debugging code and support for the -d option
   --enable-extra-debug    Enable additional debugging code (may affect
                           performance)
@@ -1689,7 +1692,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-tcpreplay configure 4.3.2
+tcpreplay configure 4.3.3
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2649,7 +2652,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by tcpreplay $as_me 4.3.2, which was
+It was created by tcpreplay $as_me 4.3.3, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -3217,9 +3220,6 @@ fi
 
 
 
-MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH) 2> /dev/null || ${host_cpu}-${host_os}
-
-
 
 # Check whether --with-macosx-sdk was given.
 if test "${with_macosx_sdk+set}" = set; then :
@@ -3231,49 +3231,54 @@ fi
 
 case "$host_os" in
     darwin*) # Mac OS X or iOS
-    # If no --with-macosx-sdk option is given, look for one
+        # If no --with-macosx-sdk option is given, look for one
 
-    # The intent is that for "most" Mac-based developers, a suitable
-    # SDK will be found automatically without any configure options.
+        # The intent is that for "most" Mac-based developers, a suitable
+        # SDK will be found automatically without any configure options.
 
-    # For developers with a current Xcode, the lowest-numbered SDK
-    # higher than or equal to the minimum required should be found.
+        # For developers with a current Xcode, the lowest-numbered SDK
+        # higher than or equal to the minimum required should be found.
 
-    # To find a list of available version run `xcodebuild -showsdks`
+        # To find a list of available version run `xcodebuild -showsdks`
 
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking what macOS compiler to use" >&5
+        MULTIARCH=${host_cpu}-${host_os}
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking what macOS compiler to use" >&5
 $as_echo_n "checking what macOS compiler to use... " >&6; }
 
-    for _macosx_sdk in $with_macosx_sdk 10.8 10.9 10.10 10.11 10.12 10.13 10.14 10.15 10.16.10.17 10.18 10.19 10.20 11.0 11.1 11.2 11.3 11.4 11.5; do
-        MACOSX_SDK_PATH=$(xcrun --sdk macosx${_macosx_sdk} --show-sdk-path 2> /dev/null)
-        if test -d "$MACOSX_SDK_PATH"; then
-            with_macosx_sdk="${_macosx_sdk}"
-            break
-        else
-            MACOSX_SDK_PATH="$(xcode-select -print-path)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX${_macosx_sdk}.sdk"
+        for _macosx_sdk in $with_macosx_sdk 10.8 10.9 10.10 10.11 10.12 10.13 10.14 10.15 10.16 10.17 10.18 10.19 10.20 11.0 11.1 11.2 11.3 11.4 11.5; do
+            MACOSX_SDK_PATH=$(xcrun --sdk macosx${_macosx_sdk} --show-sdk-path 2> /dev/null)
             if test -d "$MACOSX_SDK_PATH"; then
                 with_macosx_sdk="${_macosx_sdk}"
                 break
+            else
+                MACOSX_SDK_PATH=$(xcode-select -print-path)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX${_macosx_sdk}.sdk
+                if test -d "$MACOSX_SDK_PATH"; then
+                    with_macosx_sdk="${_macosx_sdk}"
+                    break
+                fi
             fi
-        fi
-    done
-    if test -d "$MACOSX_SDK_PATH"; then
-        CC="$(xcrun -find clang) -m64 -isysroot $MACOSX_SDK_PATH"
-        INSTALL_NAME_TOOL=$(xcrun -find install_name_tool)
-        AR=$(xcrun -find ar)
-        NM=$(xcrun -find nm)
-        STRIP=$(xcrun -find strip)
-        LIBTOOL=$(xcrun -find libtool)
-        RANLIB=$(xcrun -find ranlib)
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+        done
+        if test -d "$MACOSX_SDK_PATH"; then
+            CC="$(xcrun -find clang) -m64 -isysroot $MACOSX_SDK_PATH"
+            INSTALL_NAME_TOOL=$(xcrun -find install_name_tool)
+            AR=$(xcrun -find ar)
+            NM=$(xcrun -find nm)
+            STRIP=$(xcrun -find strip)
+            LIBTOOL=$(xcrun -find libtool)
+            RANLIB=$(xcrun -find ranlib)
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
 $as_echo "$CC" >&6; }
-    else
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: legacy" >&5
+        else
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: legacy" >&5
 $as_echo "legacy" >&6; }
-    fi
-
-    ;;
-
+        fi
+        ;;
+    Linux*)
+                                        MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH) 2> /dev/null || ${host_cpu}-${host_os}
+        ;;
+    *)
+        MULTIARCH=${host_cpu}-${host_os}
+        ;;
 esac
 
 
@@ -3790,7 +3795,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='tcpreplay'
- VERSION='4.3.2'
+ VERSION='4.3.3'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -13874,6 +13879,11 @@ else
 fi
 
 
+
+# for compat with old systems.
+# deprecated in favor of AC_PROG_CC since automake 1.14 and is now no-op
+
+
    case $ac_cv_prog_cc_stdc in #(
   no) :
     ac_cv_prog_cc_c99=no; ac_cv_prog_cc_c89=no ;; #(
@@ -20232,73 +20242,6 @@ esac
 
 fi
 
-for ac_header in stdlib.h
-do :
-  ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default"
-if test "x$ac_cv_header_stdlib_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_STDLIB_H 1
-_ACEOF
-
-fi
-
-done
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5
-$as_echo_n "checking for GNU libc compatible malloc... " >&6; }
-if ${ac_cv_func_malloc_0_nonnull+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$cross_compiling" = yes; then :
-  ac_cv_func_malloc_0_nonnull=no
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#if defined STDC_HEADERS || defined HAVE_STDLIB_H
-# include <stdlib.h>
-#else
-char *malloc ();
-#endif
-
-int
-main ()
-{
-return ! malloc (0);
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-  ac_cv_func_malloc_0_nonnull=yes
-else
-  ac_cv_func_malloc_0_nonnull=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
-  conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5
-$as_echo "$ac_cv_func_malloc_0_nonnull" >&6; }
-if test $ac_cv_func_malloc_0_nonnull = yes; then :
-
-$as_echo "#define HAVE_MALLOC 1" >>confdefs.h
-
-else
-  $as_echo "#define HAVE_MALLOC 0" >>confdefs.h
-
-   case " $LIBOBJS " in
-  *" malloc.$ac_objext "* ) ;;
-  *) LIBOBJS="$LIBOBJS malloc.$ac_objext"
- ;;
-esac
-
-
-$as_echo "#define malloc rpl_malloc" >>confdefs.h
-
-fi
-
-
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working memcmp" >&5
 $as_echo_n "checking for working memcmp... " >&6; }
 if ${ac_cv_func_memcmp_working+:} false; then :
@@ -21262,6 +21205,67 @@ else
 fi
 
 
+# Check whether --enable-asan was given.
+if test "${enable_asan+set}" = set; then :
+  enableval=$enable_asan;
+fi
+
+if test "x$enable_asan" = "xyes"; then
+        build_asan=yes
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __asan_report_error in -lasan" >&5
+$as_echo_n "checking for __asan_report_error in -lasan... " >&6; }
+if ${ac_cv_lib_asan___asan_report_error+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lasan  $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 __asan_report_error ();
+int
+main ()
+{
+return __asan_report_error ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_asan___asan_report_error=yes
+else
+  ac_cv_lib_asan___asan_report_error=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_asan___asan_report_error" >&5
+$as_echo "$ac_cv_lib_asan___asan_report_error" >&6; }
+if test "x$ac_cv_lib_asan___asan_report_error" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBASAN 1
+_ACEOF
+
+  LIBS="-lasan $LIBS"
+
+else
+  as_fn_error $? "libasan.so not found, this is required for --enable-asan" "$LINENO" 5
+fi
+
+        CFLAGS="${CFLAGS} -O1 -g -fsanitize=address -fno-omit-frame-pointer"
+                LDFLAGS="-lasan ${LDFLAGS}"
+else
+        build_asan=no
+fi
+
+
 debug=no
 debug_flag=NDEBUG
 debug_run_time_flag=
@@ -26270,7 +26274,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by tcpreplay $as_me 4.3.2, which was
+This file was extended by tcpreplay $as_me 4.3.3, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -26337,7 +26341,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-tcpreplay config.status 4.3.2
+tcpreplay config.status 4.3.3
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
@@ -28361,13 +28365,6 @@ Tuntap device support:      ${have_tuntap}
 
 
 case $host in
-    *-apple-darwin*)
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Apple OS X versions prior to 10.5 (Leopard) have a serious problem!
-Please see: http://tcpreplay.synfin.net/trac/ticket/142 for more details" >&5
-$as_echo "$as_me: WARNING: Apple OS X versions prior to 10.5 (Leopard) have a serious problem!
-Please see: http://tcpreplay.synfin.net/trac/ticket/142 for more details" >&2;}
-    ;;
-
     *-*-cygwin)
         { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Windows/Cygwin support is still somewhat experimental.
 Please report any bugs! https://github.com/appneta/tcpreplay/issues" >&5

+ 60 - 45
configure.ac

@@ -4,7 +4,7 @@ dnl $Id$
 AC_PREREQ([2.69])
 
 dnl Set version info here!
-AC_INIT([tcpreplay],[4.3.2],
+AC_INIT([tcpreplay],[4.3.3],
     [https://github.com/appneta/tcpreplay/issues],
     [tcpreplay],
     [http://tcpreplay.sourceforge.net/])
@@ -48,13 +48,6 @@ AC_SUBST(CROSS_ARCH)
 AC_SUBST(CROSS_LD)
 
 dnl ============================================
-dnl Some libraries are in /usr/lib/i386-linux-gnu
-dnl but host is i686-linux-gnu
-dnl ============================================
-
-MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH) 2> /dev/null || ${host_cpu}-${host_os}
-
-dnl ============================================
 dnl MacOSX build and runtime environment options
 dnl ============================================
 
@@ -74,46 +67,55 @@ dnl ===========================
 
 case "$host_os" in
     darwin*) # Mac OS X or iOS
-    # If no --with-macosx-sdk option is given, look for one
+        # If no --with-macosx-sdk option is given, look for one
 
-    # The intent is that for "most" Mac-based developers, a suitable
-    # SDK will be found automatically without any configure options.
+        # The intent is that for "most" Mac-based developers, a suitable
+        # SDK will be found automatically without any configure options.
 
-    # For developers with a current Xcode, the lowest-numbered SDK
-    # higher than or equal to the minimum required should be found.
+        # For developers with a current Xcode, the lowest-numbered SDK
+        # higher than or equal to the minimum required should be found.
 
-    # To find a list of available version run `xcodebuild -showsdks`
+        # To find a list of available version run `xcodebuild -showsdks`
 
-    AC_MSG_CHECKING([what macOS compiler to use])
+        MULTIARCH=${host_cpu}-${host_os}
+        AC_MSG_CHECKING([what macOS compiler to use])
 
-    for _macosx_sdk in $with_macosx_sdk 10.8 10.9 10.10 10.11 10.12 10.13 10.14 10.15 10.16.10.17 10.18 10.19 10.20 11.0 11.1 11.2 11.3 11.4 11.5; do
-        MACOSX_SDK_PATH=$(xcrun --sdk macosx${_macosx_sdk} --show-sdk-path 2> /dev/null)
-        if test -d "$MACOSX_SDK_PATH"; then
-            with_macosx_sdk="${_macosx_sdk}"
-            break
-        else
-            MACOSX_SDK_PATH="$(xcode-select -print-path)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX${_macosx_sdk}.sdk"
+        for _macosx_sdk in $with_macosx_sdk 10.8 10.9 10.10 10.11 10.12 10.13 10.14 10.15 10.16 10.17 10.18 10.19 10.20 11.0 11.1 11.2 11.3 11.4 11.5; do
+            MACOSX_SDK_PATH=$(xcrun --sdk macosx${_macosx_sdk} --show-sdk-path 2> /dev/null)
             if test -d "$MACOSX_SDK_PATH"; then
                 with_macosx_sdk="${_macosx_sdk}"
                 break
+            else
+                MACOSX_SDK_PATH=$(xcode-select -print-path)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX${_macosx_sdk}.sdk
+                if test -d "$MACOSX_SDK_PATH"; then
+                    with_macosx_sdk="${_macosx_sdk}"
+                    break
+                fi
             fi
+        done
+        if test -d "$MACOSX_SDK_PATH"; then
+            CC="$(xcrun -find clang) -m64 -isysroot $MACOSX_SDK_PATH"
+            INSTALL_NAME_TOOL=$(xcrun -find install_name_tool)
+            AR=$(xcrun -find ar)
+            NM=$(xcrun -find nm)
+            STRIP=$(xcrun -find strip)
+            LIBTOOL=$(xcrun -find libtool)
+            RANLIB=$(xcrun -find ranlib)
+            AC_MSG_RESULT([$CC])
+        else
+            AC_MSG_RESULT([legacy])
         fi
-    done
-    if test -d "$MACOSX_SDK_PATH"; then
-        CC="$(xcrun -find clang) -m64 -isysroot $MACOSX_SDK_PATH"
-        INSTALL_NAME_TOOL=$(xcrun -find install_name_tool)
-        AR=$(xcrun -find ar)
-        NM=$(xcrun -find nm)
-        STRIP=$(xcrun -find strip)
-        LIBTOOL=$(xcrun -find libtool)
-        RANLIB=$(xcrun -find ranlib)
-        AC_MSG_RESULT([$CC])
-    else
-        AC_MSG_RESULT([legacy])
-    fi
-
-    ;;
-
+        ;;
+    Linux*)
+        dnl ============================================
+        dnl Some libraries are in /usr/lib/i386-linux-gnu
+        dnl but host is i686-linux-gnu
+        dnl ============================================
+        MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH) 2> /dev/null || ${host_cpu}-${host_os}
+        ;;
+    *)
+        MULTIARCH=${host_cpu}-${host_os}
+        ;;
 esac
 
 AC_SUBST(MACOSX_SDK_PATH)
@@ -152,6 +154,11 @@ AM_PROG_AR
 AC_PROG_INSTALL
 AC_PROG_LIBTOOL
 AC_PROG_CC
+
+# for compat with old systems.
+# deprecated in favor of AC_PROG_CC since automake 1.14 and is now no-op
+AM_PROG_CC_C_O
+
 AC_PROG_CC_STDC
 AC_PROG_CXX
 AC_PROG_CPP
@@ -197,7 +204,7 @@ if test -n "${AUTOGEN}" ; then
     if test -z "$AUTOGEN_BUILD"; then
         AUTOGEN_BUILD=0
     fi
-    if (test ${AUTOGEN_MAJOR} -eq 5 && test ${AUTOGEN_MINOR} -eq 18 && test ${AUTOGEN_BUILD} -lt 4) || 
+    if (test ${AUTOGEN_MAJOR} -eq 5 && test ${AUTOGEN_MINOR} -eq 18 && test ${AUTOGEN_BUILD} -lt 4) ||
             (test ${AUTOGEN_MAJOR} -eq 5 && test ${AUTOGEN_MINOR} -lt 18) ||
             test ${AUTOGEN_MAJOR} -lt 5 ; then
         AC_MSG_RESULT(no)
@@ -360,7 +367,6 @@ AC_CHECK_LIB(resolv, resolv)
 dnl Checks for library functions.
 AC_FUNC_FORK
 AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK
-AC_FUNC_MALLOC
 AC_FUNC_MEMCMP
 AC_TYPE_SIGNAL
 AC_FUNC_VPRINTF
@@ -382,6 +388,20 @@ AM_CONDITIONAL(SYSTEM_STRLCPY, [test x$have_strlcpy = xtrue])
 AC_C_BIGENDIAN
 AM_CONDITIONAL([WORDS_BIGENDIAN], [ test x$ac_cv_c_bigendian = xyes ])
 
+AC_ARG_ENABLE([asan],
+    AC_HELP_STRING([--enable-asan], [Enable Address Sanitizer support]))
+if test "x$enable_asan" = "xyes"; then
+        build_asan=yes
+        AC_CHECK_LIB([asan], [__asan_report_error], ,
+                [AC_MSG_ERROR([libasan.so not found, this is required for --enable-asan])])
+        CFLAGS="${CFLAGS} -O1 -g -fsanitize=address -fno-omit-frame-pointer"
+        dnl -lasan always need to be the first library
+        LDFLAGS="-lasan ${LDFLAGS}"
+else
+        build_asan=no
+fi
+AC_SUBST(build_asan)
+
 dnl Enable debugging in code/compiler options
 debug=no
 debug_flag=NDEBUG
@@ -1958,11 +1978,6 @@ Tuntap device support:      ${have_tuntap}
 
 
 case $host in
-    *-apple-darwin*)
-    AC_MSG_WARN([Apple OS X versions prior to 10.5 (Leopard) have a serious problem!
-Please see: http://tcpreplay.synfin.net/trac/ticket/142 for more details])
-    ;;
-
     *-*-cygwin)
         AC_MSG_WARN([Windows/Cygwin support is still somewhat experimental.
 Please report any bugs! https://github.com/appneta/tcpreplay/issues])

+ 20 - 1
docs/CHANGELOG

@@ -1,3 +1,23 @@
+05/20/2020 Version 4.3.3
+    - Increase cache buffers size to accomodate VLAN edits (#594)
+    - Correct L2 header length to correct IP header offset (#583)
+    - Fix warnings from gcc version 10 (#580)
+    - Heap Buffer Overflow in randomize_iparp (#579)
+    - Use after free in get_ipv6_next (#578)
+    - Heap Buffer Overflow in git_ipv6_next (#576)
+    - Call pcap_freecode() on pcap_compile() (#572)
+    - Increase max snaplen to 262144 (#571)
+    - Fix divide by zero in fuzzing (#570)
+    - Unique IP repeats at very high iteration counts (#566)
+    - Fails to compile on FreeBSD amd64 13.0 (#558)
+    - Heap Buffer Overflow in do_checksum (#556) (#577)
+    - Attempt to correct corrupt pcap files, if possible (#557)
+    - Fix GCC v10 warnings (#555)
+    - Remove some duplicated SOURCES entries (#551)
+    - Expand /dev/bpfX hard limit to fix macOS Mojave (#550)
+    - Implement --loopdelay-ms when using --loop=0 (#546)
+    - Heap overflow packet2tree and get_l2len (#530)
+
 03/12/2019 Version 4.3.2
     - CVE-2019-8381 memory access in do_checksum() (#538)
     - CVE-2019-8376 NULL pointer dereference get_layer4_v6() (#537)
@@ -6,7 +26,6 @@
 
 12/27/2018 Version 4.3.1
     - Fix checkspell detected typos (#531)
-    - Heap overflow packet2tree and get_l2len (#530)
 
 11/10/2018 Version 4.3.0
     - Fix maxOS TOS checksum failure (#524)

+ 1 - 0
docs/Makefile.in

@@ -237,6 +237,7 @@ am__untar = @am__untar@
 bindir = @bindir@
 build = @build@
 build_alias = @build_alias@
+build_asan = @build_asan@
 build_cpu = @build_cpu@
 build_os = @build_os@
 build_vendor = @build_vendor@

+ 1 - 0
lib/Makefile.in

@@ -297,6 +297,7 @@ am__untar = @am__untar@
 bindir = @bindir@
 build = @build@
 build_alias = @build_alias@
+build_asan = @build_asan@
 build_cpu = @build_cpu@
 build_os = @build_os@
 build_vendor = @build_vendor@

+ 1 - 0
libopts/Makefile.in

@@ -320,6 +320,7 @@ am__untar = @am__untar@
 bindir = @bindir@
 build = @build@
 build_alias = @build_alias@
+build_asan = @build_asan@
 build_cpu = @build_cpu@
 build_os = @build_os@
 build_vendor = @build_vendor@

+ 1 - 1
libopts/boolean.c

@@ -64,8 +64,8 @@ optionBooleanVal(tOptions * opts, tOptDesc * od)
         long  val = strtol(od->optArg.argString, &pz, 0);
         if ((val != 0) || (*pz != NUL))
             break;
-        /* FALLTHROUGH */
     }
+    /* FALLTHROUGH */
     case 'N':
     case 'n':
     case 'F':

+ 1 - 0
libopts/configfile.c

@@ -466,6 +466,7 @@ file_preset(tOptions * opts, char const * fname, int dir)
                 ftext = strchr(ftext + 2, '>');
                 if (ftext++ != NULL)
                     break;
+                /* fallthrough */
 
             default:
                 ftext = NULL;

+ 1 - 0
scripts/Makefile.in

@@ -237,6 +237,7 @@ am__untar = @am__untar@
 bindir = @bindir@
 build = @build@
 build_alias = @build_alias@
+build_asan = @build_asan@
 build_cpu = @build_cpu@
 build_os = @build_os@
 build_vendor = @build_vendor@

+ 1 - 0
src/Makefile.in

@@ -447,6 +447,7 @@ am__untar = @am__untar@
 bindir = @bindir@
 build = @build@
 build_alias = @build_alias@
+build_asan = @build_asan@
 build_cpu = @build_cpu@
 build_os = @build_os@
 build_vendor = @build_vendor@

+ 2 - 0
src/bridge.c

@@ -212,6 +212,7 @@ do_bridge(tcpbridge_opt_t *options, tcpedit_t *tcpedit)
 
         /* apply filter */
         pcap_setfilter(options->pcap1, &options->bpf.program);
+        pcap_freecode(&options->bpf.program);
 
         /* same for other interface if applicable */
         if (options->unidir == 0) {
@@ -223,6 +224,7 @@ do_bridge(tcpbridge_opt_t *options, tcpedit_t *tcpedit)
 
             /* apply filter */
             pcap_setfilter(options->pcap2, &options->bpf.program);
+            pcap_freecode(&options->bpf.program);
         }
     }
 

+ 1 - 1
src/common/Makefile.am

@@ -14,7 +14,7 @@ git_version.c:
 libcommon_a_SOURCES = cidr.c err.c list.c cache.c services.c get.c \
 		      fakepcap.c fakepcapnav.c fakepoll.c xX.c utils.c \
 		      timer.c git_version.c sendpacket.c \
-		      dlt_names.c mac.c interface.c git_version.c \
+		      dlt_names.c mac.c interface.c \
 		      flows.c txring.c
 
 if ENABLE_TCPDUMP

+ 4 - 4
src/common/Makefile.in

@@ -127,9 +127,8 @@ am_libcommon_a_OBJECTS = cidr.$(OBJEXT) err.$(OBJEXT) list.$(OBJEXT) \
 	fakepcap.$(OBJEXT) fakepcapnav.$(OBJEXT) fakepoll.$(OBJEXT) \
 	xX.$(OBJEXT) utils.$(OBJEXT) timer.$(OBJEXT) \
 	git_version.$(OBJEXT) sendpacket.$(OBJEXT) dlt_names.$(OBJEXT) \
-	mac.$(OBJEXT) interface.$(OBJEXT) git_version.$(OBJEXT) \
-	flows.$(OBJEXT) txring.$(OBJEXT) $(am__objects_1) \
-	$(am__objects_2)
+	mac.$(OBJEXT) interface.$(OBJEXT) flows.$(OBJEXT) \
+	txring.$(OBJEXT) $(am__objects_1) $(am__objects_2)
 libcommon_a_OBJECTS = $(am_libcommon_a_OBJECTS)
 AM_V_P = $(am__v_P_@AM_V@)
 am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
@@ -310,6 +309,7 @@ am__untar = @am__untar@
 bindir = @bindir@
 build = @build@
 build_alias = @build_alias@
+build_asan = @build_asan@
 build_cpu = @build_cpu@
 build_os = @build_os@
 build_vendor = @build_vendor@
@@ -370,7 +370,7 @@ BUILT_SOURCES = git_version.c
 libcommon_a_SOURCES = cidr.c err.c list.c cache.c services.c get.c \
 	fakepcap.c fakepcapnav.c fakepoll.c xX.c utils.c timer.c \
 	git_version.c sendpacket.c dlt_names.c mac.c interface.c \
-	git_version.c flows.c txring.c $(am__append_1) $(am__append_2)
+	flows.c txring.c $(am__append_1) $(am__append_2)
 AM_CFLAGS = -I$(srcdir)/.. -I$(srcdir)/../.. $(LNAV_CFLAGS) @LDNETINC@
 @SYSTEM_STRLCPY_FALSE@libcommon_a_LIBADD = ../../lib/libstrl.a
 noinst_HEADERS = cidr.h err.h list.h cache.h services.h get.h \

+ 29 - 18
src/common/flows.c

@@ -90,7 +90,7 @@ static inline flow_hash_entry_t *hash_add_entry(flow_hash_table_t *fht, const ui
 
     assert(hv < fht->num_buckets);
 
-    he = malloc(sizeof (*he));
+    he = safe_malloc(sizeof (*he));
     if (!he) {
         warn("out of memory");
         return NULL;
@@ -234,25 +234,24 @@ flow_entry_type_t flow_decode(flow_hash_table_t *fht, const struct pcap_pkthdr *
             l2_len = 4; /* no header extensions */
         }
 
-        /* no break */
+        /* fallthrough */
     case DLT_EN10MB:
-        /* set l2_len if we did not fell through */
-        if (l2_len == 0)
-            l2_len = sizeof(eth_hdr_t);
-
-        if (pkthdr->caplen < l2_len)
+        /* l2_len will be zero if we did not fall through */
+        if (pkthdr->caplen < l2_len + sizeof(eth_hdr_t))
             return FLOW_ENTRY_INVALID;
 
         ether_type = ntohs(((eth_hdr_t*)(pktdata + l2_len))->ether_type);
+        l2_len += sizeof(eth_hdr_t);
 
         while (ether_type == ETHERTYPE_VLAN) {
+            if (pkthdr->caplen < l2_len + sizeof(vlan_hdr_t))
+                    return FLOW_ENTRY_INVALID;
+
             vlan_hdr_t *vlan_hdr = (vlan_hdr_t *)(pktdata + l2_len);
-            entry.vlan = vlan_hdr->vlan_priority_c_vid & htons(0xfff);
-            ether_type = ntohs(vlan_hdr->vlan_len);
+            entry.vlan = vlan_hdr->vlan_tci & htons(0xfff);
+            ether_type = ntohs(vlan_hdr->vlan_tpid);
             l2_len += 4;
         }
-
-        l2_len += sizeof(eth_hdr_t);
         break;
 
     default:
@@ -262,6 +261,9 @@ flow_entry_type_t flow_decode(flow_hash_table_t *fht, const struct pcap_pkthdr *
     }
 
     if (ether_type == ETHERTYPE_IP) {
+        if (pkthdr->caplen < l2_len + sizeof(ipv4_hdr_t))
+                return FLOW_ENTRY_INVALID;
+
         ip_hdr = (ipv4_hdr_t *)(pktdata + l2_len);
 
         if (ip_hdr->ip_v != 4)
@@ -272,6 +274,8 @@ flow_entry_type_t flow_decode(flow_hash_table_t *fht, const struct pcap_pkthdr *
         entry.src_ip.in = ip_hdr->ip_src;
         entry.dst_ip.in = ip_hdr->ip_dst;
     } else if (ether_type == ETHERTYPE_IP6) {
+        if (pkthdr->caplen < l2_len + sizeof(ipv6_hdr_t))
+                return FLOW_ENTRY_INVALID;
 
         if ((pktdata[0] >> 4) != 6)
             return FLOW_ENTRY_NON_IP;
@@ -295,12 +299,16 @@ flow_entry_type_t flow_decode(flow_hash_table_t *fht, const struct pcap_pkthdr *
 
     switch (protocol) {
     case IPPROTO_UDP:
+        if (pkthdr->caplen < (l2_len + ip_len + sizeof(udp_hdr_t)))
+            return FLOW_ENTRY_INVALID;
         udp_hdr = (udp_hdr_t*)(pktdata + ip_len + l2_len);
         entry.src_port = udp_hdr->uh_sport;
         entry.dst_port = udp_hdr->uh_dport;
         break;
 
     case IPPROTO_TCP:
+        if (pkthdr->caplen < (l2_len + ip_len + sizeof(tcp_hdr_t)))
+            return FLOW_ENTRY_INVALID;
         tcp_hdr = (tcp_hdr_t*)(pktdata + ip_len + l2_len);
         entry.src_port = tcp_hdr->th_sport;
         entry.dst_port = tcp_hdr->th_dport;
@@ -308,9 +316,12 @@ flow_entry_type_t flow_decode(flow_hash_table_t *fht, const struct pcap_pkthdr *
 
     case IPPROTO_ICMP:
     case IPPROTO_ICMPV6:
+        if (pkthdr->caplen < (l2_len + ip_len + sizeof(icmpv4_hdr_t)))
+            return FLOW_ENTRY_INVALID;
         icmp_hdr = (icmpv4_hdr_t*)(pktdata + ip_len + l2_len);
         entry.src_port = icmp_hdr->icmp_type;
         entry.dst_port = icmp_hdr->icmp_code;
+        break;
     }
 
     /* hash the 5-tuple */
@@ -322,15 +333,15 @@ flow_entry_type_t flow_decode(flow_hash_table_t *fht, const struct pcap_pkthdr *
 static void flow_cache_clear(flow_hash_table_t *fht)
 {
     flow_hash_entry_t *fhe = NULL;
-    flow_hash_entry_t *fhe_tmp = NULL;
+    flow_hash_entry_t *fhe_next = NULL;
     size_t i;
 
     for (i = 0; i < fht->num_buckets; i++) {
-        if ( (fhe = fht->buckets[i]) ) {
+        if ((fhe = fht->buckets[i]) != NULL) {
             while (fhe) {
-                fhe_tmp = fhe;
-                fhe = fhe->next;
-                free(fhe_tmp);
+                fhe_next = fhe->next;
+                safe_free(fhe);
+                fhe = fhe_next;
             }
             fht->buckets[i] = NULL;
         }
@@ -356,6 +367,6 @@ void flow_hash_table_release(flow_hash_table_t *fht)
         return;
 
     flow_cache_clear(fht);
-    free(fht->buckets);
-    free(fht);
+    safe_free(fht->buckets);
+    safe_free(fht);
 }

+ 49 - 27
src/common/get.c

@@ -76,7 +76,7 @@ get_pcap_version(void)
  * or 0 for error
  */
 uint16_t
-get_l2protocol(const u_char *pktdata, const int datalen, const int datalink)
+get_l2protocol(const u_char *pktdata, const uint32_t datalen, const int datalink)
 {
     uint16_t eth_hdr_offset = 0;
 
@@ -95,6 +95,9 @@ get_l2protocol(const u_char *pktdata, const int datalen, const int datalink)
         break;
 
     case DLT_JUNIPER_ETHER:
+        if (datalen < 5)
+            return 0;
+
         if (memcmp(pktdata, "MGC", 3))
             warnx("No Magic Number found: %s (0x%x)",
                  pcap_datalink_val_to_description(datalink), datalink);
@@ -105,19 +108,22 @@ get_l2protocol(const u_char *pktdata, const int datalen, const int datalink)
         } else {
             eth_hdr_offset = 4; /* no header extensions */
         }
-        /* no break */
+        /* fallthrough */
     case DLT_EN10MB:
         if ((size_t)datalen >= (sizeof(eth_hdr_t) + eth_hdr_offset)) {
-            vlan_hdr_t *vlan_hdr;
             eth_hdr_t *eth_hdr = (eth_hdr_t *)(pktdata + eth_hdr_offset);
             uint16_t ether_type = ntohs(eth_hdr->ether_type);
-            switch (ether_type) {
-            case ETHERTYPE_VLAN: /* 802.1q */
-                vlan_hdr = (vlan_hdr_t *)pktdata;
-                return ntohs(vlan_hdr->vlan_len);
-            default:
-                return ether_type; /* yes, return it in host byte order */
+            uint16_t l2_len = sizeof(*eth_hdr) + eth_hdr_offset;
+            while (ether_type == ETHERTYPE_VLAN) {
+                if (datalen < l2_len + sizeof(vlan_hdr_t))
+                     return 0;
+
+                 vlan_hdr_t *vlan_hdr = (vlan_hdr_t*)(pktdata + l2_len);
+                 ether_type = ntohs(vlan_hdr->vlan_tpid);
+                 l2_len += sizeof(vlan_hdr_t);
             }
+
+            return ether_type; /* yes, return it in host byte order */
         }
         break;
 
@@ -172,23 +178,37 @@ get_l2len(const u_char *pktdata, const int datalen, const int datalink)
         break;
 
     case DLT_JUNIPER_ETHER:
-        l2_len = 24;
-        /* no break */
+        if (datalen >= 5) {
+            l2_len = -1;
+            break;
+        }
+
+        if (memcmp(pktdata, "MGC", 3))
+            warnx("No Magic Number found: %s (0x%x)",
+                 pcap_datalink_val_to_description(datalink), datalink);
+
+        if ((pktdata[3] & 0x80) == 0x80) {
+            l2_len = ntohs(*((uint16_t*)&pktdata[4]));
+            l2_len += 6;
+        } else {
+            l2_len = 4; /* no header extensions */
+        }
+
+        /* fallthrough */
     case DLT_EN10MB:
         if ((size_t)datalen >= sizeof(eth_hdr_t) + l2_len) {
             uint16_t ether_type = ntohs(((eth_hdr_t*)(pktdata + l2_len))->ether_type);
 
+            l2_len += sizeof(eth_hdr_t);
             while (ether_type == ETHERTYPE_VLAN) {
-                vlan_hdr_t *vlan_hdr = (vlan_hdr_t *)(pktdata + l2_len);
-                ether_type = ntohs(vlan_hdr->vlan_len);
-                l2_len += 4;
                 if ((size_t)datalen < sizeof(vlan_hdr_t) + l2_len) {
                     l2_len = -1;
                     break;
                 }
+                vlan_hdr_t *vlan_hdr = (vlan_hdr_t *)(pktdata + l2_len);
+                ether_type = ntohs(vlan_hdr->vlan_tpid);
+                l2_len += 4;
             }
-
-            l2_len += sizeof(eth_hdr_t);
         }
 
         if (datalen < l2_len)
@@ -352,7 +372,7 @@ get_ipv6(const u_char *pktdata, int datalen, int datalink, u_char **newbuff)
  * If the packet is to short, returns NULL
  */
 void *
-get_layer4_v4(const ipv4_hdr_t *ip_hdr, const int len)
+get_layer4_v4(const ipv4_hdr_t *ip_hdr, const int l3len)
 {
     void *ptr;
 
@@ -360,7 +380,7 @@ get_layer4_v4(const ipv4_hdr_t *ip_hdr, const int len)
 
     ptr = (u_char *)ip_hdr + (ip_hdr->ip_hl << 2);
     /* make sure we don't jump over the end of the buffer */
-    if ((u_char *)ptr > ((u_char *)ip_hdr + len))
+    if ((u_char *)ptr > ((u_char *)ip_hdr + l3len))
         return NULL;
 
     return ((void *)ptr);
@@ -372,7 +392,7 @@ get_layer4_v4(const ipv4_hdr_t *ip_hdr, const int len)
  * v6 Frag or ESP header.  Function is recursive.
  */
 void *
-get_layer4_v6(const ipv6_hdr_t *ip6_hdr, const int len)
+get_layer4_v6(const ipv6_hdr_t *ip6_hdr, const int l3len)
 {
     struct tcpr_ipv6_ext_hdr_base *next, *exthdr;
     uint8_t proto;
@@ -382,7 +402,7 @@ get_layer4_v6(const ipv6_hdr_t *ip6_hdr, const int len)
     assert(ip6_hdr);
 
     min_len = TCPR_IPV6_H + sizeof(struct tcpr_ipv6_ext_hdr_base);
-    if (len < min_len)
+    if (l3len < min_len)
         return NULL;
 
     /* jump to the end of the IPv6 header */
@@ -396,7 +416,7 @@ get_layer4_v6(const ipv6_hdr_t *ip6_hdr, const int len)
         /* recurse due to v6-in-v6, need to recast next as an IPv6 Header */
         case TCPR_IPV6_NH_IPV6:
             dbg(3, "recursing due to v6-in-v6");
-            return get_layer4_v6((ipv6_hdr_t *)next, len - min_len);
+            return get_layer4_v6((ipv6_hdr_t *)next, l3len - min_len);
             break;
 
         /* loop again */
@@ -405,7 +425,7 @@ get_layer4_v6(const ipv6_hdr_t *ip6_hdr, const int len)
         case TCPR_IPV6_NH_DESTOPTS:
         case TCPR_IPV6_NH_HBH:
             dbgx(3, "Going deeper due to extension header 0x%02X", proto);
-            maxlen = len - (int)((u_char *)ip6_hdr - (u_char *)next);
+            maxlen = l3len - (int)((u_char *)ip6_hdr - (u_char *)next);
             exthdr = get_ipv6_next(next, maxlen);
             if (exthdr == NULL)
                 return next;
@@ -502,7 +522,7 @@ get_ipv6_next(struct tcpr_ipv6_ext_hdr_base *exthdr, const int len)
  * the extension headers
  */
 uint8_t 
-get_ipv6_l4proto(const ipv6_hdr_t *ip6_hdr, int len)
+get_ipv6_l4proto(const ipv6_hdr_t *ip6_hdr, const int l3len)
 {
     u_char *ptr = (u_char *)ip6_hdr + TCPR_IPV6_H; /* jump to the end of the IPv6 header */
     uint8_t proto;
@@ -511,8 +531,8 @@ get_ipv6_l4proto(const ipv6_hdr_t *ip6_hdr, int len)
     assert(ip6_hdr);
 
     proto = ip6_hdr->ip_nh;
-    len -= TCPR_IPV6_H;
-    if (len < 0)
+    int l4len = l3len - TCPR_IPV6_H;
+    if (l4len < 0)
         return proto;
 
     while (TRUE) {
@@ -528,7 +548,7 @@ get_ipv6_l4proto(const ipv6_hdr_t *ip6_hdr, int len)
             /* recurse */
             case TCPR_IPV6_NH_IPV6:
                 dbg(3, "Recursing due to v6 in v6");
-                return get_ipv6_l4proto((ipv6_hdr_t *)ptr, len);
+                return get_ipv6_l4proto((ipv6_hdr_t *)ptr, l4len);
                 break;
 
             /* loop again */
@@ -537,10 +557,12 @@ get_ipv6_l4proto(const ipv6_hdr_t *ip6_hdr, int len)
             case TCPR_IPV6_NH_DESTOPTS:
             case TCPR_IPV6_NH_HBH:
                 dbgx(3, "Jumping to next extension header (0x%hhx)", proto);
-                exthdr = get_ipv6_next((struct tcpr_ipv6_ext_hdr_base *)ptr, len);
+                exthdr = get_ipv6_next((struct tcpr_ipv6_ext_hdr_base *)ptr,
+                        l4len);
                 if (exthdr == NULL)
                     return proto;
                 proto = exthdr->ip_nh;
+                l4len -= (u_char *)exthdr - ptr;
                 ptr = (u_char *)exthdr;
                 break;
 

+ 5 - 5
src/common/get.h

@@ -28,13 +28,13 @@
 
 int get_l2len(const u_char *pktdata, const int datalen, const int datalink);
 
-u_int16_t get_l2protocol(const u_char *pktdata, const int datalen, const int datalink);
+u_int16_t get_l2protocol(const u_char *pktdata, const uint32_t datalen, const int datalink);
 
-void *get_layer4_v4(const ipv4_hdr_t *ip_hdr, const int len);
-void *get_layer4_v6(const ipv6_hdr_t *ip_hdr, const int len);
+void *get_layer4_v4(const ipv4_hdr_t *ip_hdr, const int l3len);
+void *get_layer4_v6(const ipv6_hdr_t *ip_hdr, const int l3len);
 
-u_int8_t get_ipv6_l4proto(const ipv6_hdr_t *ip6_hdr, int len);
-void *get_ipv6_next(struct tcpr_ipv6_ext_hdr_base *exthdr, const int len);
+u_int8_t get_ipv6_l4proto(const ipv6_hdr_t *ip6_hdr, const int l3len);
+void *get_ipv6_next(struct tcpr_ipv6_ext_hdr_base *exthdr, const int l3len);
 
 const u_char *get_ipv4(const u_char *pktdata, int datalen, int datalink, u_char **newbuff);
 const u_char *get_ipv6(const u_char *pktdata, int datalen, int datalink, u_char **newbuff);

+ 1 - 1
src/common/git_version.c

@@ -1,4 +1,4 @@
-const char GIT_Version[] = "git:v4.3.2";
+const char GIT_Version[] = "git:v4.3.3";
 const char *git_version(void) {
     return GIT_Version;
 }

+ 8 - 5
src/common/sendpacket.c

@@ -471,7 +471,7 @@ TRY_SEND_AGAIN:
  */
 sendpacket_t *
 sendpacket_open(const char *device, char *errbuf, tcpr_dir_t direction,
-        sendpacket_type_t sendpacket_type, void *arg)
+        sendpacket_type_t sendpacket_type _U_, void *arg _U_)
 {
     sendpacket_t *sp;
     struct stat sdata;
@@ -1053,7 +1053,7 @@ static sendpacket_t *
 sendpacket_open_bpf(const char *device, char *errbuf)
 {
     sendpacket_t *sp;
-    char bpf_dev[10];
+    char bpf_dev[16];
     int dev, mysocket, link_offset, link_type;
     struct ifreq ifr;
     struct bpf_version bv;
@@ -1066,15 +1066,18 @@ sendpacket_open_bpf(const char *device, char *errbuf)
     assert(errbuf);
     memset(&ifr, '\0', sizeof(struct ifreq));
 
-    dbg(1, "sendpacket: using BPF");
+    dbg(1, "sendpacket_open_bpf: using BPF");
     /* open socket */
     mysocket = -1;
-    for (dev = 0; dev <= 9; dev ++) {
+    for (dev = 0; dev < 512; dev ++) {
         memset(bpf_dev, '\0', sizeof(bpf_dev));
         snprintf(bpf_dev, sizeof(bpf_dev), "/dev/bpf%d", dev);
-        if ((mysocket = open(bpf_dev, O_RDWR, 0)) > 0) {
+        dbgx(3, "sendpacket_open_bpf: attempting to open %s", bpf_dev);
+        if (!access(bpf_dev, F_OK) && (mysocket = open(bpf_dev, O_RDWR, 0)) > 0) {
+            dbg(3, "Success!");
             break;
         }
+        dbgx(4, "failed with error %s", strerror(errno));
     }
 
     /* error?? */

+ 23 - 3
src/common/utils.c

@@ -128,17 +128,27 @@ u_char *_our_safe_pcap_next(pcap_t *pcap,  struct pcap_pkthdr *pkthdr,
     u_char *pktdata = (u_char *)pcap_next(pcap, pkthdr);
 
     if (pktdata) {
-        if (pkthdr->len > MAXPACKET) {
+        if (pkthdr->len > MAX_SNAPLEN) {
             fprintf(stderr, "safe_pcap_next ERROR: Invalid packet length in %s:%s() line %d: %u is greater than maximum %u\n",
-                    file, funcname, line, pkthdr->len, MAXPACKET);
+                    file, funcname, line, pkthdr->len, MAX_SNAPLEN);
             exit(-1);
         }
 
-        if (!pkthdr->len || pkthdr->len < pkthdr->caplen) {
+        if (!pkthdr->len || !pkthdr->caplen) {
             fprintf(stderr, "safe_pcap_next ERROR: Invalid packet length in %s:%s() line %d: packet length=%u capture length=%u\n",
                     file, funcname, line, pkthdr->len, pkthdr->caplen);
             exit(-1);
         }
+
+        /* attempt to correct invalid captures */
+        if (pkthdr->len < pkthdr->caplen) {
+            dbgx(1, "Correcting invalid packet capture length %d: packet length=%u",
+                    pkthdr->caplen, pkthdr->len);
+            pkthdr->caplen = pkthdr->len;
+        }
+    } else {
+        /* this will be reported as a failed packet in final report */
+        dbg(1, "No data found in packet");
     }
 
     return pktdata;
@@ -165,6 +175,16 @@ int _our_safe_pcap_next_ex(pcap_t *pcap, struct pcap_pkthdr **pkthdr,
                     file, funcname, line, (*pkthdr)->len, (*pkthdr)->caplen);
             exit(-1);
         }
+
+        if ((*pkthdr)->len < (*pkthdr)->caplen) {
+            dbgx(1, "Correcting invalid packet capture length %d: packet length=%u",
+                    (*pkthdr)->caplen, (*pkthdr)->len);
+            (*pkthdr)->caplen = (*pkthdr)->len;
+        }
+    } else {
+        /* this will be reported as a failed packet in final report */
+        dbgx(1, "No data found in packet 0x%p and/or header 0x%p",
+                *pktdata, *pkthdr);
     }
 
     return res;

+ 3 - 7
src/config.h.in

@@ -202,6 +202,9 @@
 /* Define to 1 if you have the `ioperm' function. */
 #undef HAVE_IOPERM
 
+/* Define to 1 if you have the `asan' library (-lasan). */
+#undef HAVE_LIBASAN
+
 /* Do we have libdnet? */
 #undef HAVE_LIBDNET
 
@@ -238,10 +241,6 @@
 /* Building Linux */
 #undef HAVE_LINUX
 
-/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
-   to 0 otherwise. */
-#undef HAVE_MALLOC
-
 /* Define to 1 if you have the `memmove' function. */
 #undef HAVE_MEMMOVE
 
@@ -752,9 +751,6 @@
    a type exists and the standard includes do not define it. */
 #undef int8_t
 
-/* Define to rpl_malloc if the replacement function should be used. */
-#undef malloc
-
 /* Define to `long int' if <sys/types.h> does not define. */
 #undef off_t
 

+ 13 - 5
src/defines.h

@@ -100,7 +100,8 @@ typedef struct tcpr_udp_hdr udp_hdr_t;
 typedef struct tcpr_icmpv4_hdr icmpv4_hdr_t;
 typedef struct tcpr_icmpv6_hdr icmpv6_hdr_t;
 typedef struct tcpr_ethernet_hdr eth_hdr_t;
-typedef struct tcpr_802_1q_hdr vlan_hdr_t;
+typedef struct tcpr_802_1q_tag vlan_hdr_t;
+typedef struct tcpr_802_1q_hdr vlan_pkt_hdr_t;
 typedef struct sll_header sll_hdr_t;
 typedef struct tcpr_arp_hdr arp_hdr_t;
 typedef struct tcpr_dnsv4_hdr dnsv4_hdr_t;
@@ -148,12 +149,19 @@ typedef struct tcpr_speed_s {
 #define MAX_FILES   1024        /* Max number of files we can pass to tcpreplay */
 
 #define DEFAULT_MTU 1500        /* Max Transmission Unit of standard ethernet
-                                 * don't forget *frames* are MTU + L2 header! */
+                                 * don't forget *frames* are MTU + L2 header!
+                                 */
 
-#define MAXPACKET 65549         /* was 16436 linux loopback, but maybe something is bigger then
-                                   linux loopback */
+#define MAX_SNAPLEN 262144      /* tell libpcap to capture the entire packet
+                                 * this is the maximum size supported by libpcap
+                                 * (https://github.com/the-tcpdump-group/libpcap/blob/master/pcap-int.h#L99-L125)
+                                 */
 
-#define MAX_SNAPLEN 65535       /* tell libpcap to capture the entire packet */
+#define MAXPACKET (MAX_SNAPLEN + 22)    /* snap length plus some room for adding a 
+                                         * couple VLAN headers or a L2 header
+                                         */
+
+#define PACKET_HEADROOM 512     /* additional headroom allocated for packets to accommodate editing */
 
 #define DNS_RESOLVE 1
 #define DNS_DONT_RESOLVE 0

+ 13 - 5
src/defines.h.in

@@ -100,7 +100,8 @@ typedef struct tcpr_udp_hdr udp_hdr_t;
 typedef struct tcpr_icmpv4_hdr icmpv4_hdr_t;
 typedef struct tcpr_icmpv6_hdr icmpv6_hdr_t;
 typedef struct tcpr_ethernet_hdr eth_hdr_t;
-typedef struct tcpr_802_1q_hdr vlan_hdr_t;
+typedef struct tcpr_802_1q_tag vlan_hdr_t;
+typedef struct tcpr_802_1q_hdr vlan_pkt_hdr_t;
 typedef struct sll_header sll_hdr_t;
 typedef struct tcpr_arp_hdr arp_hdr_t;
 typedef struct tcpr_dnsv4_hdr dnsv4_hdr_t;
@@ -148,12 +149,19 @@ typedef struct tcpr_speed_s {
 #define MAX_FILES   1024        /* Max number of files we can pass to tcpreplay */
 
 #define DEFAULT_MTU 1500        /* Max Transmission Unit of standard ethernet
-                                 * don't forget *frames* are MTU + L2 header! */
+                                 * don't forget *frames* are MTU + L2 header!
+                                 */
 
-#define MAXPACKET 65549         /* was 16436 linux loopback, but maybe something is bigger then
-                                   linux loopback */
+#define MAX_SNAPLEN 262144      /* tell libpcap to capture the entire packet
+                                 * this is the maximum size supported by libpcap
+                                 * (https://github.com/the-tcpdump-group/libpcap/blob/master/pcap-int.h#L99-L125)
+                                 */
 
-#define MAX_SNAPLEN 65535       /* tell libpcap to capture the entire packet */
+#define MAXPACKET (MAX_SNAPLEN + 22)    /* snap length plus some room for adding a 
+                                         * couple VLAN headers or a L2 header
+                                         */
+
+#define PACKET_HEADROOM 512     /* additional headroom allocated for packets to accommodate editing */
 
 #define DNS_RESOLVE 1
 #define DNS_DONT_RESOLVE 0

+ 1 - 0
src/fragroute/Makefile.in

@@ -316,6 +316,7 @@ am__untar = @am__untar@
 bindir = @bindir@
 build = @build@
 build_alias = @build_alias@
+build_asan = @build_asan@
 build_cpu = @build_cpu@
 build_os = @build_os@
 build_vendor = @build_vendor@

+ 1 - 0
src/fragroute/fragroute.c

@@ -8,6 +8,7 @@
  */
 
 #include "config.h"
+#include "lib/queue.h"
 #include "defines.h"
 #include "common.h"
 

+ 1 - 0
src/fragroute/mod.c

@@ -8,6 +8,7 @@
  */
 
 #include "config.h"
+#include "lib/queue.h"
 #include "defines.h"
 #include "common.h"
 

+ 1 - 0
src/fragroute/mod_ip_frag.c

@@ -7,6 +7,7 @@
  */
 
 #include "config.h"
+#include "lib/queue.h"
 #include "defines.h"
 #include "common.h"
 

+ 1 - 0
src/fragroute/mod_tcp_seg.c

@@ -7,6 +7,7 @@
  */
 
 #include "config.h"
+#include "lib/queue.h"
 #include "defines.h"
 #include "common.h"
 

+ 1 - 1
src/fragroute/pkt.h

@@ -10,8 +10,8 @@
 #define PKT_H
 
 #include "config.h"
+#include "lib/queue.h"
 #include "defines.h"
-#include "../../lib/queue.h"
 #include <sys/time.h>
 
 #ifdef HAVE_LIBDNET

+ 29 - 28
src/send_packets.c

@@ -89,7 +89,7 @@ static uint32_t get_user_count(tcpreplay_t *ctx, sendpacket_t *sp, COUNTER count
  */
 static void
 fast_edit_packet_dl(struct pcap_pkthdr *pkthdr, u_char **pktdata,
-        uint32_t iteration, bool cached, int datalink)
+        COUNTER iteration, bool cached, int datalink)
 {
     int l2_len = 0;
     ipv4_hdr_t *ip_hdr;
@@ -194,13 +194,13 @@ fast_edit_packet_dl(struct pcap_pkthdr *pkthdr, u_char **pktdata,
 
         /* CRC compensations  for wrap conditions */
         if (src_ip > src_ip_orig && dst_ip > dst_ip_orig) {
-            dbgx(1, "dst_ip > src_ip(%u): before(1) src_ip=0x%08x dst_ip=0x%08x", iteration, src_ip, dst_ip);
+            dbgx(1, "dst_ip > src_ip(" COUNTER_SPEC "): before(1) src_ip=0x%08x dst_ip=0x%08x", iteration, src_ip, dst_ip);
             --src_ip;
-            dbgx(1, "dst_ip > src_ip(%u): after(1)  src_ip=0x%08x dst_ip=0x%08x", iteration, src_ip, dst_ip);
+            dbgx(1, "dst_ip > src_ip(" COUNTER_SPEC "): after(1)  src_ip=0x%08x dst_ip=0x%08x", iteration, src_ip, dst_ip);
         } else if (dst_ip < dst_ip_orig && src_ip < src_ip_orig) {
-            dbgx(1, "dst_ip > src_ip(%u): before(2) src_ip=0x%08x dst_ip=0x%08x", iteration, src_ip, dst_ip);
+            dbgx(1, "dst_ip > src_ip(" COUNTER_SPEC "): before(2) src_ip=0x%08x dst_ip=0x%08x", iteration, src_ip, dst_ip);
             ++dst_ip;
-            dbgx(1, "dst_ip > src_ip(%u): after(2)  src_ip=0x%08x dst_ip=0x%08x", iteration, src_ip, dst_ip);
+            dbgx(1, "dst_ip > src_ip(" COUNTER_SPEC "): after(2)  src_ip=0x%08x dst_ip=0x%08x", iteration, src_ip, dst_ip);
         }
     } else {
         if (cached) {
@@ -213,20 +213,21 @@ fast_edit_packet_dl(struct pcap_pkthdr *pkthdr, u_char **pktdata,
 
         /* CRC compensations  for wrap conditions */
         if (dst_ip > dst_ip_orig && src_ip > src_ip_orig) {
-            dbgx(1, "src_ip > dst_ip(%u): before(1) dst_ip=0x%08x src_ip=0x%08x", iteration, dst_ip, src_ip);
+            dbgx(1, "src_ip > dst_ip(" COUNTER_SPEC "): before(1) dst_ip=0x%08x src_ip=0x%08x", iteration, dst_ip, src_ip);
             --dst_ip;
-            dbgx(1, "src_ip > dst_ip(%u): after(1)  dst_ip=0x%08x src_ip=0x%08x", iteration, dst_ip, src_ip);
+            dbgx(1, "src_ip > dst_ip(" COUNTER_SPEC "): after(1)  dst_ip=0x%08x src_ip=0x%08x", iteration, dst_ip, src_ip);
         } else if (src_ip < src_ip_orig && dst_ip < dst_ip_orig) {
-            dbgx(1, "src_ip > dst_ip(%u): before(2) dst_ip=0x%08x src_ip=0x%08x", iteration, dst_ip, src_ip);
+            dbgx(1, "src_ip > dst_ip(" COUNTER_SPEC "): before(2) dst_ip=0x%08x src_ip=0x%08x", iteration, dst_ip, src_ip);
             ++src_ip;
-            dbgx(1, "src_ip > dst_ip(%u): after(2)  dst_ip=0x%08x src_ip=0x%08x", iteration, dst_ip, src_ip);
+            dbgx(1, "src_ip > dst_ip(" COUNTER_SPEC "): after(2)  dst_ip=0x%08x src_ip=0x%08x", iteration, dst_ip, src_ip);
         }
     }
 
-    dbgx(1, "(%u): final src_ip=0x%08x dst_ip=0x%08x", iteration, src_ip, dst_ip);
+    dbgx(1, "(" COUNTER_SPEC "): final src_ip=0x%08x dst_ip=0x%08x", iteration, src_ip, dst_ip);
 }
 
-static inline void wake_send_queues(sendpacket_t *sp, tcpreplay_opt_t *options)
+static inline void wake_send_queues(sendpacket_t *sp _U_,
+		tcpreplay_opt_t *options _U_)
 {
 #ifdef HAVE_NETMAP
     if (options->netmap)
@@ -236,10 +237,9 @@ static inline void wake_send_queues(sendpacket_t *sp, tcpreplay_opt_t *options)
 
 static inline void
 fast_edit_packet(struct pcap_pkthdr *pkthdr, u_char **pktdata,
-        uint32_t iteration, bool cached, int datalink)
+        COUNTER iteration, bool cached, int datalink)
 {
     uint16_t ether_type;
-    vlan_hdr_t *vlan_hdr;
     ipv4_hdr_t *ip_hdr = NULL;
     ipv6_hdr_t *ip6_hdr = NULL;
     uint32_t src_ip, dst_ip;
@@ -274,12 +274,12 @@ fast_edit_packet(struct pcap_pkthdr *pkthdr, u_char **pktdata,
 
     /* assume Ethernet, IPv4 for now */
     ether_type = ntohs(((eth_hdr_t*)(packet + l2_len))->ether_type);
+    l2_len += sizeof(eth_hdr_t);
     while (ether_type == ETHERTYPE_VLAN) {
-        vlan_hdr = (vlan_hdr_t *)(packet + l2_len);
-        ether_type = ntohs(vlan_hdr->vlan_len);
-        l2_len += 4;
+         vlan_hdr_t *vlan_hdr = (vlan_hdr_t*)(pktdata + l2_len);
+         ether_type = ntohs(vlan_hdr->vlan_tpid);
+         l2_len += 4;
     }
-    l2_len += sizeof(eth_hdr_t);
 
     switch (ether_type) {
     case ETHERTYPE_IP:
@@ -313,13 +313,13 @@ fast_edit_packet(struct pcap_pkthdr *pkthdr, u_char **pktdata,
 
         /* CRC compensations  for wrap conditions */
         if (src_ip > src_ip_orig && dst_ip > dst_ip_orig) {
-            dbgx(1, "dst_ip > src_ip(%u): before(1) src_ip=0x%08x dst_ip=0x%08x", iteration, src_ip, dst_ip);
+            dbgx(1, "dst_ip > src_ip(" COUNTER_SPEC "): before(1) src_ip=0x%08x dst_ip=0x%08x", iteration, src_ip, dst_ip);
             --src_ip;
-            dbgx(1, "dst_ip > src_ip(%u): after(1)  src_ip=0x%08x dst_ip=0x%08x", iteration, src_ip, dst_ip);
+            dbgx(1, "dst_ip > src_ip(" COUNTER_SPEC "): after(1)  src_ip=0x%08x dst_ip=0x%08x", iteration, src_ip, dst_ip);
         } else if (dst_ip < dst_ip_orig && src_ip < src_ip_orig) {
-            dbgx(1, "dst_ip > src_ip(%u): before(2) src_ip=0x%08x dst_ip=0x%08x", iteration, src_ip, dst_ip);
+            dbgx(1, "dst_ip > src_ip(" COUNTER_SPEC "): before(2) src_ip=0x%08x dst_ip=0x%08x", iteration, src_ip, dst_ip);
             ++dst_ip;
-            dbgx(1, "dst_ip > src_ip(%u): after(2)  src_ip=0x%08x dst_ip=0x%08x", iteration, src_ip, dst_ip);
+            dbgx(1, "dst_ip > src_ip(" COUNTER_SPEC "): after(2)  src_ip=0x%08x dst_ip=0x%08x", iteration, src_ip, dst_ip);
         }
     } else {
         if (cached) {
@@ -332,17 +332,17 @@ fast_edit_packet(struct pcap_pkthdr *pkthdr, u_char **pktdata,
 
         /* CRC compensations  for wrap conditions */
         if (dst_ip > dst_ip_orig && src_ip > src_ip_orig) {
-            dbgx(1, "src_ip > dst_ip(%u): before(1) dst_ip=0x%08x src_ip=0x%08x", iteration, dst_ip, src_ip);
+            dbgx(1, "src_ip > dst_ip(" COUNTER_SPEC "): before(1) dst_ip=0x%08x src_ip=0x%08x", iteration, dst_ip, src_ip);
             --dst_ip;
-            dbgx(1, "src_ip > dst_ip(%u): after(1)  dst_ip=0x%08x src_ip=0x%08x", iteration, dst_ip, src_ip);
+            dbgx(1, "src_ip > dst_ip(" COUNTER_SPEC "): after(1)  dst_ip=0x%08x src_ip=0x%08x", iteration, dst_ip, src_ip);
         } else if (src_ip < src_ip_orig && dst_ip < dst_ip_orig) {
-            dbgx(1, "src_ip > dst_ip(%u): before(2) dst_ip=0x%08x src_ip=0x%08x", iteration, dst_ip, src_ip);
+            dbgx(1, "src_ip > dst_ip(" COUNTER_SPEC "): before(2) dst_ip=0x%08x src_ip=0x%08x", iteration, dst_ip, src_ip);
             ++src_ip;
-            dbgx(1, "src_ip > dst_ip(%u): after(2)  dst_ip=0x%08x src_ip=0x%08x", iteration, dst_ip, src_ip);
+            dbgx(1, "src_ip > dst_ip(" COUNTER_SPEC "): after(2)  dst_ip=0x%08x src_ip=0x%08x", iteration, dst_ip, src_ip);
         }
     }
 
-    dbgx(1, "(%u): final src_ip=0x%08x dst_ip=0x%08x", iteration, src_ip, dst_ip);
+    dbgx(1, "(" COUNTER_SPEC "): final src_ip=0x%08x dst_ip=0x%08x", iteration, src_ip, dst_ip);
 
     switch (ether_type) {
     case ETHERTYPE_IP:
@@ -460,7 +460,8 @@ static void increment_iteration(tcpreplay_t *ctx)
     if (options->unique_ip) {
         assert(options->unique_loops > 0.0);
         ctx->unique_iteration =
-                (COUNTER)((float)ctx->iteration / options->unique_loops) + 1;
+                ((ctx->iteration * 1000) / (COUNTER)(options->unique_loops * 1000.0))
+                + 1;
     }
 }
 
@@ -1055,7 +1056,7 @@ get_next_packet(tcpreplay_t *ctx, pcap_t *pcap, struct pcap_pkthdr *pkthdr, int
                     (*prev_packet)->next = NULL;
                     pktlen = pkthdr->len;
 
-                    (*prev_packet)->pktdata = safe_malloc(pktlen);
+                    (*prev_packet)->pktdata = safe_malloc(pktlen + PACKET_HEADROOM);
                     memcpy((*prev_packet)->pktdata, pktdata, pktlen);
                     memcpy(&((*prev_packet)->pkthdr), pkthdr, sizeof(struct pcap_pkthdr));
                 }

+ 2 - 2
src/sleep.h

@@ -74,7 +74,7 @@ nanosleep_sleep(sendpacket_t *sp _U_, const struct timespec *nap,
  */
 static inline void
 gettimeofday_sleep(sendpacket_t *sp _U_, struct timespec *nap,
-        struct timeval *now, bool flush)
+        struct timeval *now, bool flush _U_)
 {
     struct timeval sleep_until, nap_for;
 #ifdef HAVE_NETMAP
@@ -116,7 +116,7 @@ gettimeofday_sleep(sendpacket_t *sp _U_, struct timespec *nap,
  */
 static inline void 
 select_sleep(sendpacket_t *sp _U_, const struct timespec *nap,
-        struct timeval *now,  bool flush)
+        struct timeval *now,  bool flush _U_)
 {
     struct timeval timeout;
 #ifdef HAVE_NETMAP

+ 2 - 2
src/tcpbridge.1

@@ -10,7 +10,7 @@
 .ds B-Font B
 .ds I-Font I
 .ds R-Font R
-.TH tcpbridge 1 "12 Mar 2019" "tcpbridge" "User Commands"
+.TH tcpbridge 1 "14 Jun 2020" "tcpbridge" "User Commands"
 .\"
 .\" DO NOT EDIT THIS FILE (in-mem file)
 .\"
@@ -175,7 +175,7 @@ is constrained to being:
 .in +4
 .nf
 .na
-in the range  1 through MAXPACKET
+in the range  1 through MAX_SNAPLEN
 .fi
 .in -4
 .sp

+ 1 - 1
src/tcpbridge_opts.c

@@ -1794,7 +1794,7 @@ static void
 doOptMtu(tOptions* pOptions, tOptDesc* pOptDesc)
 {
     static struct {long rmin, rmax;} const rng[1] = {
-        { 1, MAXPACKET } };
+        { 1, MAX_SNAPLEN } };
     int  ix;
 
     if (pOptions <= OPTPROC_EMIT_LIMIT)

+ 1 - 1
src/tcpcapinfo.1

@@ -10,7 +10,7 @@
 .ds B-Font B
 .ds I-Font I
 .ds R-Font R
-.TH tcpcapinfo 1 "12 Mar 2019" "Tcpreplay Suite" "User Commands"
+.TH tcpcapinfo 1 "14 Jun 2020" "Tcpreplay Suite" "User Commands"
 .\"
 .\" DO NOT EDIT THIS FILE (in-mem file)
 .\"

+ 1 - 1
src/tcpcapinfo.c

@@ -275,7 +275,7 @@ main(int argc, char *argv[])
                         PRIx32".%"PRIx32,
                         pktcnt, pcap_ph.len, pcap_ph.caplen, 
                         (unsigned int)pcap_ph.ts.tv_sec, (unsigned int)pcap_ph.ts.tv_usec);
-                if (pcap_fh.snaplen < pcap_ph.caplen) {
+                if (pcap_fh.snaplen < pcap_ph.caplen || pcap_ph.caplen > MAX_SNAPLEN) {
                     caplentoobig = 1;
                 }
                 caplen = pcap_ph.caplen;

+ 1 - 4
src/tcpedit/Makefile.in

@@ -227,8 +227,6 @@ am_libtcpedit_a_OBJECTS = tcpedit.$(OBJEXT) parse_args.$(OBJEXT) \
 	plugins/dlt_ieee80211/ieee80211_hdr.$(OBJEXT) \
 	plugins/dlt_radiotap/radiotap.$(OBJEXT) \
 	plugins/dlt_jnpr_ether/jnpr_ether.$(OBJEXT) \
-	plugins/dlt_jnpr_ether/jnpr_ether.$(OBJEXT) \
-	plugins/dlt_pppserial/pppserial.$(OBJEXT) \
 	plugins/dlt_pppserial/pppserial.$(OBJEXT)
 libtcpedit_a_OBJECTS = $(am_libtcpedit_a_OBJECTS)
 AM_V_P = $(am__v_P_@AM_V@)
@@ -422,6 +420,7 @@ am__untar = @am__untar@
 bindir = @bindir@
 build = @build@
 build_alias = @build_alias@
+build_asan = @build_asan@
 build_cpu = @build_cpu@
 build_os = @build_os@
 build_vendor = @build_vendor@
@@ -491,8 +490,6 @@ libtcpedit_a_SOURCES = tcpedit.c parse_args.c edit_packet.c portmap.c \
 	plugins/dlt_ieee80211/ieee80211_hdr.c \
 	plugins/dlt_radiotap/radiotap.c \
 	plugins/dlt_jnpr_ether/jnpr_ether.c \
-	plugins/dlt_jnpr_ether/jnpr_ether.c \
-	plugins/dlt_pppserial/pppserial.c \
 	plugins/dlt_pppserial/pppserial.c
 AM_CFLAGS = -I$(srcdir). -I$(srcdir)/.. -I$(srcdir)/../common \
 	-I$(srcdir)/../.. @LDNETINC@ $(LIBOPTS_CFLAGS) $(LNAV_CFLAGS) \

+ 35 - 15
src/tcpedit/checksum.c

@@ -34,7 +34,7 @@ static int do_checksum_math(uint16_t *, int);
  * Returns -1 on error and 0 on success, 1 on warn
  */
 int
-do_checksum(tcpedit_t *tcpedit, uint8_t *data, int proto, int len) {
+do_checksum(tcpedit_t *tcpedit, uint8_t *data, int proto, int payload_len) {
     ipv4_hdr_t *ipv4;
     ipv6_hdr_t *ipv6;
     tcp_hdr_t *tcp;
@@ -50,20 +50,25 @@ do_checksum(tcpedit_t *tcpedit, uint8_t *data, int proto, int len) {
     ipv6 = NULL;
     assert(data);
 
-    if (!data || len <= 0 || len > 65535) {
-        tcpedit_setwarn(tcpedit, "%s", "Unable to checksum packets with no L3+ data");
+    if (!data || payload_len < (int)sizeof(*ipv4) || payload_len > 0xffff) {
+        tcpedit_setwarn(tcpedit, "%s", "Unable to checksum packet with no L3+ data");
         return TCPEDIT_WARN;
     }
 
     ipv4 = (ipv4_hdr_t *)data;
     if (ipv4->ip_v == 6) {
+        if (payload_len < (int)sizeof(*ipv6)) {
+            tcpedit_setwarn(tcpedit, "%s", "Unable to checksum IPv6 packet with insufficient data");
+            return TCPEDIT_WARN;
+        }
+
         ipv6 = (ipv6_hdr_t *)data;
         ipv4 = NULL;
 
-        proto = get_ipv6_l4proto(ipv6, len);
+        proto = get_ipv6_l4proto(ipv6, payload_len + sizeof(ipv6_hdr_t));
         dbgx(3, "layer4 proto is 0x%hx", (uint16_t)proto);
 
-        layer = (u_char*)get_layer4_v6(ipv6, len);
+        layer = (u_char*)get_layer4_v6(ipv6, payload_len + sizeof(ipv6_hdr_t));
         if (!layer) {
             tcpedit_setwarn(tcpedit, "%s", "Packet to short for checksum");
             return TCPEDIT_WARN;
@@ -72,14 +77,18 @@ do_checksum(tcpedit_t *tcpedit, uint8_t *data, int proto, int len) {
         ip_hl = layer - (u_char*)data;
         dbgx(3, "ip_hl proto is 0x%d", ip_hl);
 
-        len -= (ip_hl - TCPR_IPV6_H);
+        payload_len -= (ip_hl - TCPR_IPV6_H);
     } else {
         ip_hl = ipv4->ip_hl << 2;
     }
 
     switch (proto) {
-
         case IPPROTO_TCP:
+            if (payload_len < (int)sizeof(tcp_hdr_t)) {
+                tcpedit_setwarn(tcpedit, "%s", "Unable to checksum TCP with insufficient L4 data");
+                return TCPEDIT_WARN;
+            }
+
             tcp = (tcp_hdr_t *)(data + ip_hl);
 #ifdef STUPID_SOLARIS_CHECKSUM_BUG
             tcp->th_sum = tcp->th_off << 2;
@@ -95,12 +104,16 @@ do_checksum(tcpedit_t *tcpedit, uint8_t *data, int proto, int len) {
             } else {
                 sum = do_checksum_math((uint16_t *)&ipv4->ip_src, 8);
             }
-            sum += ntohs(IPPROTO_TCP + len);
-            sum += do_checksum_math((uint16_t *)tcp, len);
+            sum += ntohs(IPPROTO_TCP + payload_len);
+            sum += do_checksum_math((uint16_t *)tcp, payload_len);
             tcp->th_sum = CHECKSUM_CARRY(sum);
             break;
 
         case IPPROTO_UDP:
+            if (payload_len < (int)sizeof(udp_hdr_t)) {
+                tcpedit_setwarn(tcpedit, "%s", "Unable to checksum UDP with insufficient L4 data");
+                return TCPEDIT_WARN;
+            }
             udp = (udp_hdr_t *)(data + ip_hl);
             /* No need to recalculate UDP checksums if already 0 */
             if (udp->uh_sum == 0)
@@ -111,34 +124,41 @@ do_checksum(tcpedit_t *tcpedit, uint8_t *data, int proto, int len) {
             } else {
                 sum = do_checksum_math((uint16_t *)&ipv4->ip_src, 8);
             }
-            sum += ntohs(IPPROTO_UDP + len);
-            sum += do_checksum_math((uint16_t *)udp, len);
+            sum += ntohs(IPPROTO_UDP + payload_len);
+            sum += do_checksum_math((uint16_t *)udp, payload_len);
             udp->uh_sum = CHECKSUM_CARRY(sum);
             break;
 
         case IPPROTO_ICMP:
+            if (payload_len < (int)sizeof(icmpv4_hdr_t)) {
+                tcpedit_setwarn(tcpedit, "%s", "Unable to checksum ICMP with insufficient L4 data");
+                return TCPEDIT_WARN;
+            }
             icmp = (icmpv4_hdr_t *)(data + ip_hl);
             icmp->icmp_sum = 0;
             if (ipv6 != NULL) {
                 sum = do_checksum_math((uint16_t *)&ipv6->ip_src, 32);
                 icmp->icmp_sum = CHECKSUM_CARRY(sum);
             }
-            sum += do_checksum_math((uint16_t *)icmp, len);
+            sum += do_checksum_math((uint16_t *)icmp, payload_len);
             icmp->icmp_sum = CHECKSUM_CARRY(sum);
             break;
 
         case IPPROTO_ICMP6:
+            if (payload_len < (int)sizeof(icmpv6_hdr_t)) {
+                tcpedit_setwarn(tcpedit, "%s", "Unable to checksum ICMP6 with insufficient L4 data");
+                return TCPEDIT_WARN;
+            }
             icmp6 = (icmpv6_hdr_t *)(data + ip_hl);
             icmp6->icmp_sum = 0;
             if (ipv6 != NULL) {
                 sum = do_checksum_math((u_int16_t *)&ipv6->ip_src, 32);
             }
-            sum += ntohs(IPPROTO_ICMP6 + len);
-            sum += do_checksum_math((u_int16_t *)icmp6, len);
+            sum += ntohs(IPPROTO_ICMP6 + payload_len);
+            sum += do_checksum_math((u_int16_t *)icmp6, payload_len);
             icmp6->icmp_sum = CHECKSUM_CARRY(sum);
             break;
 
-
         case IPPROTO_IP:
             if (ipv4) {
                 ipv4->ip_sum = 0;

+ 63 - 103
src/tcpedit/edit_packet.c

@@ -62,14 +62,21 @@ fix_ipv4_checksums(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr, ipv4_hdr_t *i
     assert(tcpedit);
     assert(pkthdr);
     assert(ip_hdr);
-    
+
+    if (pkthdr->caplen < sizeof(*ip_hdr)) {
+        tcpedit_setwarn(tcpedit, "caplen too small to read IPv4 header: %u",
+                pkthdr->caplen);
+        return TCPEDIT_WARN;
+    }
+
+    if (ip_hdr->ip_v != 4) {
+        tcpedit_seterr(tcpedit, "Invalid packet: Expected IPv4 packet: got %u", ip_hdr->ip_v);
+        return TCPEDIT_ERROR;
+    }
 
     /* calc the L4 checksum if we have the whole packet && not a frag or first frag */
     if (pkthdr->caplen == pkthdr->len &&
             (htons(ip_hdr->ip_off) & (IP_MF | IP_OFFMASK)) == 0) {
-        if (ntohs(ip_hdr->ip_len) < (ip_hdr->ip_hl << 2))
-            return TCPEDIT_WARN;
-
         ip_len = (int)ntohs(ip_hdr->ip_len);
         ret1 = do_checksum(tcpedit, (u_char *) ip_hdr, ip_hdr->ip_p,
                 ip_len - (ip_hdr->ip_hl << 2));
@@ -128,12 +135,26 @@ fix_ipv6_checksums(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr, ipv6_hdr_t *i
     assert(pkthdr);
     assert(ip6_hdr);
 
+    if (pkthdr->caplen < sizeof(*ip6_hdr)) {
+        tcpedit_setwarn(tcpedit, "caplen too small to read IPv6 header: %u",
+                pkthdr->caplen);
+        return TCPEDIT_WARN;
+    }
+
+    ipv4_hdr_t *ip_hdr = (ipv4_hdr_t*)ip6_hdr;
+    if (ip_hdr->ip_v != 6) {
+        tcpedit_seterr(tcpedit, "Invalid packet: Expected IPv6 packet: got %u", ip_hdr->ip_v);
+        return TCPEDIT_ERROR;
+    }
 
     /* calc the L4 checksum if we have the whole packet && not a frag or first frag */
     if (pkthdr->caplen == pkthdr->len) {
-        if (ip6_hdr->ip_len < ipv6_header_length(ip6_hdr, pkthdr->len))
+        if (ip6_hdr->ip_len < ipv6_header_length(ip6_hdr, pkthdr->len)) {
+            tcpedit_setwarn(tcpedit, "Unable to checksum IPv6 packet with invalid length %u",
+                    ip6_hdr->ip_len);
             return TCPEDIT_WARN;
-        ret = do_checksum(tcpedit, (u_char *) ip6_hdr, ip6_hdr->ip_nh,
+        }
+        ret = do_checksum(tcpedit, (u_char *)ip6_hdr, ip6_hdr->ip_nh,
             htons(ip6_hdr->ip_len));
         if (ret < 0)
             return TCPEDIT_ERROR;
@@ -233,9 +254,10 @@ static void ipv6_l34_csum_replace(uint8_t *data, uint8_t protocol,
 }
 
 static void ipv4_addr_csum_replace(ipv4_hdr_t *ip_hdr, uint32_t old_ip,
-        uint32_t new_ip, int len)
+        uint32_t new_ip, const int l3len)
 {
     uint8_t *l4, protocol;
+    int len = l3len;
 
     assert(ip_hdr);
 
@@ -271,9 +293,11 @@ static void ipv4_addr_csum_replace(ipv4_hdr_t *ip_hdr, uint32_t old_ip,
 }
 
 static void ipv6_addr_csum_replace(ipv6_hdr_t *ip6_hdr,
-        struct tcpr_in6_addr *old_ip, struct tcpr_in6_addr *new_ip, int len)
+        struct tcpr_in6_addr *old_ip, struct tcpr_in6_addr *new_ip,
+        const int l3len)
 {
     uint8_t *l4, protocol;
+    int len = l3len;
 
     assert(ip6_hdr);
 
@@ -353,7 +377,7 @@ randomize_ipv6_addr(tcpedit_t *tcpedit, struct tcpr_in6_addr *addr)
  */
 int
 randomize_ipv4(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr, 
-        u_char *pktdata, ipv4_hdr_t *ip_hdr, int len)
+        u_char *pktdata, ipv4_hdr_t *ip_hdr, const int l3len)
 {
 #ifdef DEBUG
     char srcip[16], dstip[16];
@@ -371,19 +395,25 @@ randomize_ipv4(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
     /* randomize IP addresses based on the value of random */
     dbgx(1, "Old Src IP: %s\tOld Dst IP: %s", srcip, dstip);
 
+    if (l3len < (int)ip_hdr->ip_hl << 2) {
+        tcpedit_seterr(tcpedit, "Unable to randomize IP header due to packet capture snap length %u",
+                pkthdr->caplen);
+        return TCPEDIT_ERROR;
+    }
+
     /* don't rewrite broadcast addresses */
     if ((tcpedit->skip_broadcast && is_unicast_ipv4(tcpedit, (u_int32_t)ip_hdr->ip_dst.s_addr)) 
             || !tcpedit->skip_broadcast) {
         uint32_t old_ip = ip_hdr->ip_dst.s_addr;
         ip_hdr->ip_dst.s_addr = randomize_ipv4_addr(tcpedit, ip_hdr->ip_dst.s_addr);
-        ipv4_addr_csum_replace(ip_hdr, old_ip, ip_hdr->ip_dst.s_addr, len);
+        ipv4_addr_csum_replace(ip_hdr, old_ip, ip_hdr->ip_dst.s_addr, l3len);
     }
     
     if ((tcpedit->skip_broadcast && is_unicast_ipv4(tcpedit, (u_int32_t)ip_hdr->ip_src.s_addr))
             || !tcpedit->skip_broadcast) {
         uint32_t old_ip = ip_hdr->ip_src.s_addr;
         ip_hdr->ip_src.s_addr = randomize_ipv4_addr(tcpedit, ip_hdr->ip_src.s_addr);
-        ipv4_addr_csum_replace(ip_hdr, old_ip, ip_hdr->ip_src.s_addr, len);
+        ipv4_addr_csum_replace(ip_hdr, old_ip, ip_hdr->ip_src.s_addr, l3len);
     }
 
 #ifdef DEBUG    
@@ -398,7 +428,7 @@ randomize_ipv4(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
 
 int
 randomize_ipv6(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
-        u_char *pktdata, ipv6_hdr_t *ip6_hdr, int len)
+        u_char *pktdata, ipv6_hdr_t *ip6_hdr, const int l3len)
 {
 #ifdef DEBUG
     char srcip[INET6_ADDRSTRLEN], dstip[INET6_ADDRSTRLEN];
@@ -415,6 +445,11 @@ randomize_ipv6(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
 
     /* randomize IP addresses based on the value of random */
     dbgx(1, "Old Src IP: %s\tOld Dst IP: %s", srcip, dstip);
+    if (l3len < (int)sizeof(ipv6_hdr_t)) {
+        tcpedit_seterr(tcpedit, "Unable to randomize IPv6 header due to packet capture snap length %u",
+                pkthdr->caplen);
+        return TCPEDIT_ERROR;
+    }
 
     /* don't rewrite broadcast addresses */
     if ((tcpedit->skip_broadcast && !is_multicast_ipv6(tcpedit, &ip6_hdr->ip_dst))
@@ -422,7 +457,7 @@ randomize_ipv6(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
         struct tcpr_in6_addr old_ip6;
         memcpy(&old_ip6, &ip6_hdr->ip_dst, sizeof(old_ip6));
         randomize_ipv6_addr(tcpedit, &ip6_hdr->ip_dst);
-        ipv6_addr_csum_replace(ip6_hdr, &old_ip6, &ip6_hdr->ip_dst, len);
+        ipv6_addr_csum_replace(ip6_hdr, &old_ip6, &ip6_hdr->ip_dst, l3len);
     }
 
     if ((tcpedit->skip_broadcast && !is_multicast_ipv6(tcpedit, &ip6_hdr->ip_src))
@@ -430,7 +465,7 @@ randomize_ipv6(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
         struct tcpr_in6_addr old_ip6;
         memcpy(&old_ip6, &ip6_hdr->ip_src, sizeof(old_ip6));
         randomize_ipv6_addr(tcpedit, &ip6_hdr->ip_src);
-        ipv6_addr_csum_replace(ip6_hdr, &old_ip6, &ip6_hdr->ip_src, len);
+        ipv6_addr_csum_replace(ip6_hdr, &old_ip6, &ip6_hdr->ip_src, l3len);
     }
 
 #ifdef DEBUG
@@ -504,7 +539,7 @@ untrunc_packet(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
            * which seems like a corrupted pcap
            */
         if (pkthdr->len > pkthdr->caplen) {
-            packet = safe_realloc(packet, pkthdr->len);
+            packet = safe_realloc(packet, pkthdr->len + PACKET_HEADROOM);
             memset(packet + pkthdr->caplen, '\0', pkthdr->len - pkthdr->caplen);
             pkthdr->caplen = pkthdr->len;
         } else if (pkthdr->len < pkthdr->caplen) {
@@ -549,88 +584,6 @@ done:
 }
 
 /**
- * Extracts the layer 7 data from the packet for TCP, UDP, ICMP
- * returns the number of bytes and a pointer to the layer 7 data. 
- * Returns 0 for no data
- */
-int
-extract_data(tcpedit_t *tcpedit, const u_char *pktdata, int caplen, 
-        char *l7data[])
-{
-    int datalen = 0; /* amount of data beyond ip header */
-    ipv4_hdr_t *ip_hdr;
-    u_char ipbuff[MAXPACKET];
-    u_char *dataptr;
-    int ip_len;
-    
-    assert(tcpedit);
-    assert(pktdata);
-    assert(l7data);
-
-    /* grab our IPv4 header */
-    dataptr = ipbuff;
-    if ((ip_hdr = (ipv4_hdr_t*)get_ipv4(pktdata, caplen, 
-                    tcpedit->runtime.dlt1, &dataptr)) == NULL)
-        return 0;
-
-    /* 
-     * figure out the actual datalen which might be < the caplen
-     * due to ethernet padding 
-     */
-    ip_len = (int)ntohs(ip_hdr->ip_len);
-    if (caplen > ip_len) {
-        datalen = ip_len;
-    } else {
-        datalen = caplen - tcpedit->dlt_ctx->l2len;
-    }
-
-    /* update the datlen to not include the IP header len */
-    datalen -= ip_hdr->ip_hl << 2;
-    dataptr += ip_hdr->ip_hl << 2;
-    if (datalen <= 0)
-        goto nodata;
-
-    /* TCP ? */
-    if (ip_hdr->ip_p == IPPROTO_TCP) {
-        tcp_hdr_t *tcp_hdr = (tcp_hdr_t *) get_layer4_v4(ip_hdr, datalen);
-        datalen -= tcp_hdr->th_off << 2;
-        if (datalen <= 0)
-            goto nodata;
-
-        dataptr += tcp_hdr->th_off << 2;
-    }
-
-    /* UDP ? */
-    else if (ip_hdr->ip_p == IPPROTO_UDP) {
-        datalen -= TCPR_UDP_H;
-        if (datalen <= 0)
-            goto nodata;
-
-        dataptr += TCPR_UDP_H;
-    }
-
-    /* ICMP ? just ignore it for now */
-    else if (ip_hdr->ip_p == IPPROTO_ICMP) {
-        dbg(2, "Ignoring any possible data in ICMP packet");
-        goto nodata;
-    }
-
-    /* unknown proto, just dump everything past the IP header */
-    else {
-        dbg(2, "Unknown protocol, dumping everything past the IP header");
-        dataptr = (u_char *)ip_hdr;
-    }
-
-    dbgx(2, "packet had %d bytes of layer 7 data", datalen);
-    memcpy(l7data, dataptr, datalen);
-    return datalen;
-
-  nodata:
-    dbg(2, "packet has no data, skipping...");
-    return 0;
-}
-
-/**
  * rewrites an IPv4 packet's TTL based on the rules
  * return 0 if no change, 1 if changed 
  */
@@ -892,7 +845,7 @@ rewrite_ipv4l3(tcpedit_t *tcpedit, ipv4_hdr_t *ip_hdr, tcpr_dir_t direction,
 
 int
 rewrite_ipv6l3(tcpedit_t *tcpedit, ipv6_hdr_t *ip6_hdr, tcpr_dir_t direction,
-        int len)
+        int l3len)
 {
     tcpr_cidrmap_t *cidrmap1 = NULL, *cidrmap2 = NULL;
     int didsrc = 0, diddst = 0, loop = 1;
@@ -908,7 +861,7 @@ rewrite_ipv6l3(tcpedit_t *tcpedit, ipv6_hdr_t *ip6_hdr, tcpr_dir_t direction,
             struct tcpr_in6_addr old_ip6;
             memcpy(&old_ip6, &ip6_hdr->ip_src, sizeof(old_ip6));
             remap_ipv6(tcpedit, ipmap->to, &ip6_hdr->ip_src);
-            ipv6_addr_csum_replace(ip6_hdr, &old_ip6, &ip6_hdr->ip_src, len);
+            ipv6_addr_csum_replace(ip6_hdr, &old_ip6, &ip6_hdr->ip_src, l3len);
             dbgx(2, "Remapped src addr to: %s", get_addr2name6(&ip6_hdr->ip_src, RESOLVE));
             break;
         }
@@ -921,7 +874,7 @@ rewrite_ipv6l3(tcpedit_t *tcpedit, ipv6_hdr_t *ip6_hdr, tcpr_dir_t direction,
             struct tcpr_in6_addr old_ip6;
             memcpy(&old_ip6, &ip6_hdr->ip_dst, sizeof(old_ip6));
             remap_ipv6(tcpedit, ipmap->to, &ip6_hdr->ip_dst);
-            ipv6_addr_csum_replace(ip6_hdr, &old_ip6, &ip6_hdr->ip_dst, len);
+            ipv6_addr_csum_replace(ip6_hdr, &old_ip6, &ip6_hdr->ip_dst, l3len);
             dbgx(2, "Remapped dst addr to: %s", get_addr2name6(&ip6_hdr->ip_dst, RESOLVE));
             break;
         }
@@ -948,7 +901,7 @@ rewrite_ipv6l3(tcpedit_t *tcpedit, ipv6_hdr_t *ip6_hdr, tcpr_dir_t direction,
             struct tcpr_in6_addr old_ip6;
             memcpy(&old_ip6, &ip6_hdr->ip_dst, sizeof(old_ip6));
             remap_ipv6(tcpedit, cidrmap2->to, &ip6_hdr->ip_dst);
-            ipv6_addr_csum_replace(ip6_hdr, &old_ip6, &ip6_hdr->ip_dst, len);
+            ipv6_addr_csum_replace(ip6_hdr, &old_ip6, &ip6_hdr->ip_dst, l3len);
             dbgx(2, "Remapped dst addr to: %s", get_addr2name6(&ip6_hdr->ip_dst, RESOLVE));
             diddst = 1;
         }
@@ -956,7 +909,7 @@ rewrite_ipv6l3(tcpedit_t *tcpedit, ipv6_hdr_t *ip6_hdr, tcpr_dir_t direction,
             struct tcpr_in6_addr old_ip6;
             memcpy(&old_ip6, &ip6_hdr->ip_src, sizeof(old_ip6));
             remap_ipv6(tcpedit, cidrmap1->to, &ip6_hdr->ip_src);
-            ipv6_addr_csum_replace(ip6_hdr, &old_ip6, &ip6_hdr->ip_src, len);
+            ipv6_addr_csum_replace(ip6_hdr, &old_ip6, &ip6_hdr->ip_src, l3len);
             dbgx(2, "Remapped src addr to: %s", get_addr2name6(&ip6_hdr->ip_src, RESOLVE));
             didsrc = 1;
         }
@@ -996,7 +949,7 @@ rewrite_ipv6l3(tcpedit_t *tcpedit, ipv6_hdr_t *ip6_hdr, tcpr_dir_t direction,
  */
 int 
 randomize_iparp(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr, 
-        u_char *pktdata, int datalink)
+        u_char *pktdata, int datalink, const int l3len)
 {
     arp_hdr_t *arp_hdr ;
     int l2len;
@@ -1008,7 +961,14 @@ randomize_iparp(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
     assert(pkthdr);
     assert(pktdata);
 
+    if (l3len < (int)sizeof(arp_hdr_t)) {
+        tcpedit_seterr(tcpedit, "Unable to randomize ARP packet due to packet capture snap length %u",
+                pkthdr->caplen);
+        return TCPEDIT_ERROR;
+    }
+
     l2len = get_l2len(pktdata, pkthdr->caplen, datalink);
+
     arp_hdr = (arp_hdr_t *)(pktdata + l2len);
 
     /*

+ 5 - 5
src/tcpedit/edit_packet.h

@@ -28,13 +28,13 @@ int untrunc_packet(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
         u_char **pktdata, ipv4_hdr_t *ip_hdr, ipv6_hdr_t *ip6_hdr);
 
 int randomize_ipv4(tcpedit_t *tcpedit, struct pcap_pkthdr *pktdhr, 
-        u_char *pktdata, ipv4_hdr_t *ip_hdr, int len);
+        u_char *pktdata, ipv4_hdr_t *ip_hdr, const int l3len);
 
 int randomize_ipv6(tcpedit_t *tcpedit, struct pcap_pkthdr *pktdhr,
-        u_char *pktdata, ipv6_hdr_t *ip_hdr, int len);
+        u_char *pktdata, ipv6_hdr_t *ip_hdr, const int l3len);
 
 int randomize_iparp(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr, 
-        u_char *pktdata, int datalink);
+        u_char *pktdata, int datalink, const int l3len);
 
 int fix_ipv4_checksums(tcpedit_t *tcpedit, struct pcap_pkthdr *pkdhdr,
         ipv4_hdr_t *ip_hdr);
@@ -50,10 +50,10 @@ int extract_data(tcpedit_t *tcpedit, const u_char *pktdata,
         int caplen, char *l7data[]);
 
 int rewrite_ipv4l3(tcpedit_t *tcpedit, ipv4_hdr_t *ip_hdr, tcpr_dir_t direction,
-        int len);
+        int l3len);
 
 int rewrite_ipv6l3(tcpedit_t *tcpedit, ipv6_hdr_t *ip_hdr, tcpr_dir_t direction,
-        int len);
+        int l3len);
 
 int rewrite_iparp(tcpedit_t *tcpedit, arp_hdr_t *arp_hdr, int direction);
 

+ 1 - 1
src/tcpedit/fuzzing.c

@@ -156,7 +156,7 @@ fuzzing(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
         break;
     }
 
-    if (l4len < 1)
+    if (l4len <= 1)
         goto done;
 
     /* add some additional randomization */

+ 16 - 7
src/tcpedit/plugins/dlt_en10mb/en10mb.c

@@ -670,8 +670,11 @@ dlt_en10mb_proto(tcpeditdlt_t *ctx, const u_char *packet, const int pktlen)
     
     assert(ctx);
     assert(packet);
-    if (pktlen < (int) sizeof(*eth))
+    if (pktlen < (int) sizeof(*eth)) {
+        tcpedit_seterr(ctx->tcpedit, "Ethernet packet length too short: %d",
+                pktlen);
         return TCPEDIT_ERROR;
+    }
     
     eth = (struct tcpr_ethernet_hdr *)packet;
     switch (ntohs(eth->ether_type)) {
@@ -684,6 +687,7 @@ dlt_en10mb_proto(tcpeditdlt_t *ctx, const u_char *packet, const int pktlen)
             return eth->ether_type;
             break;
     }
+
     return TCPEDIT_ERROR;
 }
 
@@ -771,24 +775,29 @@ dlt_en10mb_l2len(tcpeditdlt_t *ctx, const u_char *packet, const int pktlen)
     if (pktlen < l2len)
         return -1;
 
-    ether_type = ntohs(((eth_hdr_t*)(packet + l2len))->ether_type);
+    ether_type = ntohs(((eth_hdr_t*)packet)->ether_type);
     while (ether_type == ETHERTYPE_VLAN) {
-        vlan_hdr_t *vlan_hdr = (vlan_hdr_t *)(packet + l2len);
-        ether_type = ntohs(vlan_hdr->vlan_len);
-        l2len += 4;
+        if (pktlen < l2len + (int)sizeof(vlan_hdr_t))
+             return -1;
+
+         vlan_hdr_t *vlan_hdr = (vlan_hdr_t*)(packet + l2len);
+         ether_type = ntohs(vlan_hdr->vlan_tpid);
+         l2len += 4;
     }
 
     if (l2len > 0) {
         if (pktlen < l2len) {
             /* can happen if fuzzing is enabled */
+            tcpedit_seterr(ctx->tcpedit, "dlt_en10mb_l2len: pktlen=%u is less than l2len=%u",
+                    pktlen, l2len);
             return -1;
         }
 
         return l2len;
     }
 
-    tcpedit_seterr(ctx->tcpedit, "%s", "Whoops!  Bug in my code!");
-    return -1;
+    tcpedit_seterr(ctx->tcpedit, "dlt_en10mb_l2len: %s", "Whoops!  Bug in my code!");
+    return TCPEDIT_ERROR;
 }
 
 tcpeditdlt_l2addr_type_t

+ 2 - 1
src/tcpedit/plugins/dlt_hdlc/hdlc.c

@@ -228,7 +228,6 @@ dlt_hdlc_encode(tcpeditdlt_t *ctx, u_char *packet, int pktlen, _U_ tcpr_dir_t di
     hdlc_config_t *config = NULL;
     hdlc_extra_t *extra = NULL;
     tcpeditdlt_plugin_t *plugin = NULL;
-    u_char tmpbuff[MAXPACKET];
     int newpktlen;
 
     assert(ctx);
@@ -244,8 +243,10 @@ dlt_hdlc_encode(tcpeditdlt_t *ctx, u_char *packet, int pktlen, _U_ tcpr_dir_t di
     if (ctx->l2len > 4) {
         memmove(packet + 4, packet + ctx->l2len, pktlen - ctx->l2len);
     } else if (ctx->l2len < 4) {
+        u_char *tmpbuff = safe_malloc(pktlen);
         memcpy(tmpbuff, packet, pktlen);
         memcpy(packet + 4, (tmpbuff + ctx->l2len), pktlen - ctx->l2len);
+        safe_free(tmpbuff);
     }
     
     /* update the total packet length */

+ 0 - 1
src/tcpedit/plugins/dlt_jnpr_ether/Makefile.am

@@ -7,7 +7,6 @@
 # add your dependency information (see comment below)
 
 libtcpedit_a_SOURCES += \
-	%reldir%/jnpr_ether.c \
 	%reldir%/jnpr_ether.c
 
 noinst_HEADERS += \

+ 0 - 1
src/tcpedit/plugins/dlt_pppserial/Makefile.am

@@ -7,7 +7,6 @@
 # add your dependency information (see comment below)
 
 libtcpedit_a_SOURCES += \
-	%reldir%/pppserial.c \
 	%reldir%/pppserial.c
 
 noinst_HEADERS += \

+ 2 - 1
src/tcpedit/plugins/dlt_user/user.c

@@ -227,7 +227,6 @@ dlt_user_encode(tcpeditdlt_t *ctx, u_char *packet, int pktlen, tcpr_dir_t dir)
 {
     user_config_t *config;
     tcpeditdlt_plugin_t *plugin;
-    u_char tmpbuff[MAXPACKET];
 
     assert(ctx);
     assert(packet);
@@ -247,8 +246,10 @@ dlt_user_encode(tcpeditdlt_t *ctx, u_char *packet, int pktlen, tcpr_dir_t dir)
     if (ctx->l2len > config->length) {
         memmove(packet + config->length, packet + ctx->l2len, pktlen - ctx->l2len);
     } else if (ctx->l2len < config->length) {
+        u_char *tmpbuff = safe_malloc(pktlen);
         memcpy(tmpbuff, packet, pktlen);
         memcpy(packet + config->length, (tmpbuff + ctx->l2len), pktlen - ctx->l2len);
+        safe_free(tmpbuff);
     }
 
     /* update the total packet length */

+ 38 - 12
src/tcpedit/portmap.c

@@ -292,7 +292,8 @@ map_port(tcpedit_portmap_t *portmap_data, long port)
  */
 
 static int
-rewrite_ports(tcpedit_t *tcpedit, u_char protocol, u_char *layer4)
+rewrite_ports(tcpedit_t *tcpedit, u_char protocol, u_char *layer4,
+        const int l4len)
 {
     tcp_hdr_t *tcp_hdr = NULL;
     udp_hdr_t *udp_hdr = NULL;
@@ -304,6 +305,12 @@ rewrite_ports(tcpedit_t *tcpedit, u_char protocol, u_char *layer4)
     portmap = tcpedit->portmap;
 
     if (protocol == IPPROTO_TCP) {
+        if (l4len < (int)sizeof(tcp_hdr_t)) {
+            tcpedit_setwarn(tcpedit, "caplen to small to set TCP port: l4 len=%d",
+                    l4len);
+            return TCPEDIT_WARN;
+        }
+
         tcp_hdr = (tcp_hdr_t *)layer4;
 
         /* check if we need to remap the destination port */
@@ -319,8 +326,13 @@ rewrite_ports(tcpedit_t *tcpedit, u_char protocol, u_char *layer4)
             csum_replace2(&tcp_hdr->th_sum, tcp_hdr->th_sport, newport);
             tcp_hdr->th_sport = newport;
         }
-
     } else if (protocol == IPPROTO_UDP) {
+        if (l4len < (int)sizeof(udp_hdr_t)) {
+            tcpedit_setwarn(tcpedit, "caplen to small to set UDP port: l4 len=%d",
+                    l4len);
+            return TCPEDIT_WARN;
+        }
+
         udp_hdr = (udp_hdr_t *)layer4;
 
         /* check if we need to remap the destination port */
@@ -348,34 +360,48 @@ rewrite_ports(tcpedit_t *tcpedit, u_char protocol, u_char *layer4)
 }
 
 int
-rewrite_ipv4_ports(tcpedit_t *tcpedit, ipv4_hdr_t **ip_hdr, const int len)
+rewrite_ipv4_ports(tcpedit_t *tcpedit, ipv4_hdr_t **ip_hdr, const int l3len)
 {
     assert(tcpedit);
     u_char *l4;
 
-    if (*ip_hdr == NULL) {
-        return 0;
+    if (*ip_hdr == NULL || ip_hdr == NULL) {
+        tcpedit_seterr(tcpedit, "rewrite_ipv4_ports: NULL IP header: l3 len=%d",
+                l3len);
+        return TCPEDIT_ERROR;
     } else if ((*ip_hdr)->ip_p == IPPROTO_TCP || (*ip_hdr)->ip_p == IPPROTO_UDP) {
-        l4 = get_layer4_v4(*ip_hdr, len);
+        l4 = get_layer4_v4(*ip_hdr, l3len);
         if (l4)
-            return rewrite_ports(tcpedit, (*ip_hdr)->ip_p, l4);
+            return rewrite_ports(tcpedit, (*ip_hdr)->ip_p, l4,
+                    l3len - (l4 - (u_char*)*ip_hdr));
+
+        tcpedit_setwarn(tcpedit, "Unable to rewrite ports on IP header: l3 len=%d",
+                l3len);
+        return TCPEDIT_WARN;
     }
 
     return 0;
 }
 
 int
-rewrite_ipv6_ports(tcpedit_t *tcpedit, ipv6_hdr_t **ip6_hdr, const int len)
+rewrite_ipv6_ports(tcpedit_t *tcpedit, ipv6_hdr_t **ip6_hdr, const int l3len)
 {
     assert(tcpedit);
     u_char *l4;
 
-    if (*ip6_hdr == NULL) {
-        return 0;
+    if (*ip6_hdr == NULL || ip6_hdr == NULL) {
+        tcpedit_seterr(tcpedit, "rewrite_ipv6_ports: NULL IPv6 header: l3 len=%d",
+                l3len);
+        return TCPEDIT_ERROR;
     } else if ((*ip6_hdr)->ip_nh == IPPROTO_TCP || (*ip6_hdr)->ip_nh == IPPROTO_UDP) {
-        l4 = get_layer4_v6(*ip6_hdr, len);
+        l4 = get_layer4_v6(*ip6_hdr, l3len);
         if (l4)
-            return rewrite_ports(tcpedit, (*ip6_hdr)->ip_nh, l4);
+            return rewrite_ports(tcpedit, (*ip6_hdr)->ip_nh, l4,
+                    l3len - (l4 - (u_char*)*ip6_hdr));
+
+        tcpedit_setwarn(tcpedit, "Unable to rewrite ports on IPv6 header: l3 len=%d",
+                l3len);
+        return TCPEDIT_WARN;
     }
 
     return 0;

+ 2 - 2
src/tcpedit/portmap.h

@@ -28,7 +28,7 @@ int parse_portmap(tcpedit_portmap_t **portmapdata, const char *ourstr);
 void free_portmap(tcpedit_portmap_t *portmap);
 void print_portmap(tcpedit_portmap_t *portmap);
 long map_port(tcpedit_portmap_t *portmap , long port);
-int rewrite_ipv4_ports(tcpedit_t *tcpedit, ipv4_hdr_t **ip_hdr, const int len);
-int rewrite_ipv6_ports(tcpedit_t *tcpedit, ipv6_hdr_t **ip_hdr, const int len);
+int rewrite_ipv4_ports(tcpedit_t *tcpedit, ipv4_hdr_t **ip_hdr, const int l3len);
+int rewrite_ipv6_ports(tcpedit_t *tcpedit, ipv6_hdr_t **ip_hdr, const int l3len);
 
 #endif

+ 20 - 6
src/tcpedit/rewrite_sequence.c

@@ -63,13 +63,20 @@ rewrite_seqs(tcpedit_t *tcpedit, tcp_hdr_t *tcp_hdr)
 
 
 int
-rewrite_ipv4_sequence(tcpedit_t *tcpedit, ipv4_hdr_t **ip_hdr)
+rewrite_ipv4_tcp_sequence(tcpedit_t *tcpedit, ipv4_hdr_t **ip_hdr,
+        const int l3len)
 {
     assert(tcpedit);
-    tcp_hdr_t *tcp_hdr = NULL;
+    assert(*ip_hdr && ip_hdr);
 
     if (*ip_hdr && (*ip_hdr)->ip_p == IPPROTO_TCP) {
-        tcp_hdr = (tcp_hdr_t *)get_layer4_v4(*ip_hdr, 65536);
+        tcp_hdr_t *tcp_hdr = (tcp_hdr_t *)get_layer4_v4(*ip_hdr, l3len);
+        if (!tcp_hdr) {
+            tcpedit_setwarn(tcpedit, "caplen to small to set TCP sequence for IP packet: l3 len=%d",
+                    l3len);
+            return TCPEDIT_WARN;
+        }
+
         return rewrite_seqs(tcpedit, tcp_hdr);
     }
 
@@ -77,13 +84,20 @@ rewrite_ipv4_sequence(tcpedit_t *tcpedit, ipv4_hdr_t **ip_hdr)
 }
 
 int
-rewrite_ipv6_sequence(tcpedit_t *tcpedit, ipv6_hdr_t **ip6_hdr)
+rewrite_ipv6_tcp_sequence(tcpedit_t *tcpedit, ipv6_hdr_t **ip6_hdr,
+        const int l3len)
 {
     assert(tcpedit);
-    tcp_hdr_t *tcp_hdr = NULL;
+    assert(*ip6_hdr && ip6_hdr);
 
     if (*ip6_hdr && (*ip6_hdr)->ip_nh == IPPROTO_TCP) {
-        tcp_hdr = (tcp_hdr_t *)get_layer4_v6(*ip6_hdr, 65535);
+        tcp_hdr_t *tcp_hdr = (tcp_hdr_t *)get_layer4_v6(*ip6_hdr, l3len);
+        if (!tcp_hdr) {
+            tcpedit_setwarn(tcpedit, "caplen to small to set TCP sequence for IP packet: l3 len=%d",
+                    l3len);
+            return TCPEDIT_WARN;
+        }
+
         return rewrite_seqs(tcpedit, tcp_hdr);
     }
 

+ 4 - 5
src/tcpedit/rewrite_sequence.h

@@ -24,10 +24,9 @@
 #ifndef __REWRITE_SEQUENCE_H__
 #define __REWRITE_SEQUENCE_H__
 
-int rewrite_ipv4_sequence(tcpedit_t *tcpedit, ipv4_hdr_t **ip_hdr);
-int rewrite_ipv6_sequence(tcpedit_t *tcpedit, ipv6_hdr_t **ip_hdr);
-
-int rewrite_ipv4_sequence(tcpedit_t *tcpedit, ipv4_hdr_t **ip_hdr);
-int rewrite_ipv6_sequence(tcpedit_t *tcpedit, ipv6_hdr_t **ip6_hdr);
+int rewrite_ipv4_tcp_sequence(tcpedit_t *tcpedit, ipv4_hdr_t **ip_hdr,
+        const int l3len);
+int rewrite_ipv6_tcp_sequence(tcpedit_t *tcpedit, ipv6_hdr_t **ip6_hdr,
+        const int l3len);
 
 #endif

+ 10 - 7
src/tcpedit/tcpedit.c

@@ -42,7 +42,7 @@
 #include "lib/sll.h"
 #include "dlt.h"
 
-tOptDesc *const tcpedit_tcpedit_optDesc_p;
+extern tOptDesc *const tcpedit_tcpedit_optDesc_p;
 
 /**
  * \brief Checks to see if you should make an edit
@@ -220,12 +220,14 @@ tcpedit_packet(tcpedit_t *tcpedit, struct pcap_pkthdr **pkthdr,
 
         /* rewrite TCP/UDP ports */
         if (tcpedit->portmap != NULL) {
-            if ((retval = rewrite_ipv4_ports(tcpedit, &ip_hdr, (*pkthdr)->caplen)) < 0)
+            if ((retval = rewrite_ipv4_ports(tcpedit, &ip_hdr,
+                    (*pkthdr)->caplen - l2len)) < 0)
                 return TCPEDIT_ERROR;
         }
 
         if (tcpedit->tcp_sequence_enable)
-            rewrite_ipv4_sequence(tcpedit, &ip_hdr);
+            rewrite_ipv4_tcp_sequence(tcpedit, &ip_hdr,
+                    (*pkthdr)->caplen - l2len);
     }
 
     /* IPv6 edits */
@@ -261,12 +263,13 @@ tcpedit_packet(tcpedit_t *tcpedit, struct pcap_pkthdr **pkthdr,
 
         /* rewrite TCP/UDP ports */
         if (tcpedit->portmap != NULL) {
-            if ((retval = rewrite_ipv6_ports(tcpedit, &ip6_hdr, (*pkthdr)->caplen)) < 0)
+            if ((retval = rewrite_ipv6_ports(tcpedit, &ip6_hdr,
+                    (*pkthdr)->caplen - l2len)) < 0)
                 return TCPEDIT_ERROR;
         }
 
         if (tcpedit->tcp_sequence_enable)
-            rewrite_ipv6_sequence(tcpedit, &ip6_hdr);
+            rewrite_ipv6_tcp_sequence(tcpedit, &ip6_hdr, (*pkthdr)->caplen - l2len);
     }
 
     if (tcpedit->fuzz_seed != 0) {
@@ -327,11 +330,11 @@ tcpedit_packet(tcpedit_t *tcpedit, struct pcap_pkthdr **pkthdr,
         } else if (l2proto == htons(ETHERTYPE_ARP)) {
             if (direction == TCPR_DIR_C2S) {
                 if (randomize_iparp(tcpedit, *pkthdr, packet, 
-                        tcpedit->runtime.dlt1) < 0)
+                        tcpedit->runtime.dlt1, (*pkthdr)->caplen - l2len) < 0)
                     return TCPEDIT_ERROR;
             } else {
                 if (randomize_iparp(tcpedit, *pkthdr, packet, 
-                        tcpedit->runtime.dlt2) < 0)
+                        tcpedit->runtime.dlt2, (*pkthdr)->caplen - l2len) < 0)
                     return TCPEDIT_ERROR;
             }
         }

+ 1 - 1
src/tcpedit/tcpedit_opts.def

@@ -175,7 +175,7 @@ flag = {
     value       = m;
     arg-type    = number;
     max         = 1;
-    arg-range   = "1->MAXPACKET";
+    arg-range   = "1->MAX_SNAPLEN";
     default     = DEFAULT_MTU;
     descrip     = "Override default MTU length (1500 bytes)";
     doc         = <<- EOText

+ 1 - 1
src/tcpliveplay.1

@@ -10,7 +10,7 @@
 .ds B-Font B
 .ds I-Font I
 .ds R-Font R
-.TH tcpliveplay 1 "12 Mar 2019" "tcpliveplay" "User Commands"
+.TH tcpliveplay 1 "14 Jun 2020" "tcpliveplay" "User Commands"
 .\"
 .\" DO NOT EDIT THIS FILE (in-mem file)
 .\"

+ 2 - 0
src/tcpliveplay.c

@@ -668,6 +668,7 @@ set_live_filter(char *dev, input_addr* hostip, unsigned int port)
         return handle;
     }
 
+    pcap_freecode(&fp);
     return handle;
 }
 
@@ -703,6 +704,7 @@ set_offline_filter(char* file)
         return handle;
     }
 
+    pcap_freecode(&fp);
     return handle;
 }
 

+ 1 - 1
src/tcpprep.1

@@ -10,7 +10,7 @@
 .ds B-Font B
 .ds I-Font I
 .ds R-Font R
-.TH tcpprep 1 "12 Mar 2019" "tcpprep" "User Commands"
+.TH tcpprep 1 "14 Jun 2020" "tcpprep" "User Commands"
 .\"
 .\" DO NOT EDIT THIS FILE (in-mem file)
 .\"

+ 6 - 1
src/tcpprep.c

@@ -141,6 +141,7 @@ main(int argc, char *argv[])
             errx(-1, "Error compiling BPF filter: %s", pcap_geterr(options->pcap));
         }
         pcap_setfilter(options->pcap, &options->bpf.program);
+        pcap_freecode(&options->bpf.program);
     }
 
     if ((totpackets = process_raw_packets(options->pcap)) == 0) {
@@ -325,12 +326,14 @@ process_raw_packets(pcap_t * pcap)
     const u_char *pktdata = NULL;
     COUNTER packetnum = 0;
     int l2len;
-    u_char ipbuff[MAXPACKET], *buffptr;
+    u_char *ipbuff, *buffptr;
     tcpr_dir_t direction = TCPR_DIR_ERROR;
     tcpprep_opt_t *options = tcpprep->options;
 
     assert(pcap);
     
+    ipbuff = safe_malloc(MAXPACKET);
+
     while ((pktdata = safe_pcap_next(pcap, &pkthdr)) != NULL) {
         packetnum++;
 
@@ -566,6 +569,8 @@ process_raw_packets(pcap_t * pcap)
 #endif
     }
 
+    safe_free(ipbuff);
+
     return packetnum;
 }
 

+ 11 - 1
src/tcpr.h

@@ -139,7 +139,17 @@
 #define TCPR_HSRP_H           0x14    /**< HSRP header:          8 bytes */
 
 /**
- * IEEE 802.1Q (Virtual Local Area Network) VLAN header, static header
+ * IEEE 802.1Q (Virtual Local Area Network) VLAN tag
+ * size: 8 bytes
+ */
+struct tcpr_802_1q_tag
+{
+    uint16_t       vlan_tci;               /* VLAN TCI */
+    uint16_t       vlan_tpid;              /* Next ETH_TYPE */
+};
+
+/**
+ * IEEE 802.1Q (Virtual Local Area Network) VLAN packet header
  * size: 8 bytes
  */
 struct tcpr_802_1q_hdr

+ 2 - 2
src/tcpreplay-edit.1

@@ -10,7 +10,7 @@
 .ds B-Font B
 .ds I-Font I
 .ds R-Font R
-.TH tcpreplay-edit 1 "12 Mar 2019" "tcpreplay" "User Commands"
+.TH tcpreplay-edit 1 "14 Jun 2020" "tcpreplay" "User Commands"
 .\"
 .\" DO NOT EDIT THIS FILE (in-mem file)
 .\"
@@ -175,7 +175,7 @@ is constrained to being:
 .in +4
 .nf
 .na
-in the range  1 through MAXPACKET
+in the range  1 through MAX_SNAPLEN
 .fi
 .in -4
 .sp

+ 1 - 1
src/tcpreplay.1

@@ -10,7 +10,7 @@
 .ds B-Font B
 .ds I-Font I
 .ds R-Font R
-.TH tcpreplay 1 "12 Mar 2019" "tcpreplay" "User Commands"
+.TH tcpreplay 1 "14 Jun 2020" "tcpreplay" "User Commands"
 .\"
 .\" DO NOT EDIT THIS FILE (in-mem file)
 .\"

+ 1 - 1
src/tcpreplay.c

@@ -110,7 +110,7 @@ main(int argc, char *argv[])
      * Setup up the file cache, if required
      */
     if (ctx->options->preload_pcap) {
-        /* Initialise each of the file cache structures */
+        /* Initialize each of the file cache structures */
         for (i = 0; i < argc; i++) {
             ctx->options->file_cache[i].index = i;
             ctx->options->file_cache[i].cached = FALSE;

+ 8 - 3
src/tcpreplay_api.c

@@ -769,7 +769,7 @@ tcpreplay_set_tcpprep_cache(tcpreplay_t *ctx, char *file)
  * Enable verbose mode
  */
 int
-tcpreplay_set_verbose(tcpreplay_t *ctx, bool value)
+tcpreplay_set_verbose(tcpreplay_t *ctx, bool value _U_)
 {
     assert(ctx);
 #ifdef ENABLE_VERBOSE
@@ -788,7 +788,7 @@ tcpreplay_set_verbose(tcpreplay_t *ctx, bool value)
  * verbose mode.  See TCPDUMP_ARGS in tcpdump.h for the default options
  */
 int
-tcpreplay_set_tcpdump_args(tcpreplay_t *ctx, char *value)
+tcpreplay_set_tcpdump_args(tcpreplay_t *ctx, char *value _U_)
 {
     assert(ctx);
 #ifdef ENABLE_VERBOSE
@@ -808,7 +808,7 @@ tcpreplay_set_tcpdump_args(tcpreplay_t *ctx, char *value)
  * tcpdump lives
  */
 int
-tcpreplay_set_tcpdump(tcpreplay_t *ctx, tcpdump_t *value)
+tcpreplay_set_tcpdump(tcpreplay_t *ctx, tcpdump_t *value _U_)
 {
     assert(ctx);
 #ifdef ENABLE_VERBOSE
@@ -1158,6 +1158,11 @@ tcpreplay_replay(tcpreplay_t *ctx)
             if ((rcode = tcpr_replay_index(ctx)) < 0)
                 return rcode;
 
+            if (!ctx->abort && ctx->options->loopdelay_ms > 0) {
+                usleep(ctx->options->loopdelay_ms * 1000);
+                gettimeofday(&ctx->stats.end_time, NULL);
+            }
+
             if (ctx->options->stats == 0 && !ctx->abort)
                 packet_stats(&ctx->stats);
         }

+ 1 - 1
src/tcpreplay_edit_opts.c

@@ -2419,7 +2419,7 @@ static void
 doOptMtu(tOptions* pOptions, tOptDesc* pOptDesc)
 {
     static struct {long rmin, rmax;} const rng[1] = {
-        { 1, MAXPACKET } };
+        { 1, MAX_SNAPLEN } };
     int  ix;
 
     if (pOptions <= OPTPROC_EMIT_LIMIT)

+ 2 - 2
src/tcprewrite.1

@@ -10,7 +10,7 @@
 .ds B-Font B
 .ds I-Font I
 .ds R-Font R
-.TH tcprewrite 1 "12 Mar 2019" "tcprewrite" "User Commands"
+.TH tcprewrite 1 "14 Jun 2020" "tcprewrite" "User Commands"
 .\"
 .\" DO NOT EDIT THIS FILE (in-mem file)
 .\"
@@ -200,7 +200,7 @@ is constrained to being:
 .in +4
 .nf
 .na
-in the range  1 through MAXPACKET
+in the range  1 through MAX_SNAPLEN
 .fi
 .in -4
 .sp

+ 2 - 2
src/tcprewrite.c

@@ -261,8 +261,8 @@ rewrite_packets(tcpedit_t *tcpedit, pcap_t *pin, pcap_dumper_t *pout)
         packetnum++;
         dbgx(2, "packet " COUNTER_SPEC " caplen %d", packetnum, pkthdr.caplen);
 
-        if (pkthdr.caplen > MAXPACKET)
-            errx(-1, "Frame too big, caplen %d exceeds %d", pkthdr.caplen, MAXPACKET);
+        if (pkthdr.caplen > MAX_SNAPLEN)
+            errx(-1, "Frame too big, caplen %d exceeds %d", pkthdr.caplen, MAX_SNAPLEN);
         /* 
          * copy over the packet so we can pad it out if necessary and
          * because pcap_next() returns a const ptr

+ 1 - 1
src/tcprewrite_opts.c

@@ -1719,7 +1719,7 @@ static void
 doOptMtu(tOptions* pOptions, tOptDesc* pOptDesc)
 {
     static struct {long rmin, rmax;} const rng[1] = {
-        { 1, MAXPACKET } };
+        { 1, MAX_SNAPLEN } };
     int  ix;
 
     if (pOptions <= OPTPROC_EMIT_LIMIT)

+ 1 - 1
src/timestamp_trace.h

@@ -25,7 +25,6 @@
 
 #define TRACE_MAX_ENTRIES 15000
 
-uint32_t trace_num;
 struct timestamp_trace_entry {
     COUNTER skip_length;
     COUNTER size;
@@ -39,6 +38,7 @@ struct timestamp_trace_entry {
 typedef struct timestamp_trace_entry timestamp_trace_entry_t;
 
 #ifdef TIMESTAMP_TRACE
+uint32_t trace_num;
 timestamp_trace_entry_t timestamp_trace_entry_array[TRACE_MAX_ENTRIES];
 
 static inline void update_current_timestamp_trace_entry(COUNTER bytes_sent,

+ 38 - 4
src/tree.c

@@ -714,9 +714,8 @@ packet2tree(const u_char * data, const int len)
     char srcip[INET6_ADDRSTRLEN];
 #endif
 
-    if ((size_t)len < sizeof(*eth_hdr)) {
-        errx(-1, "packet capture length %d too small to process", len);
-        return NULL;
+    if (len < (int)sizeof(*eth_hdr)) {
+        goto len_error;
     }
 
     node = new_tree();
@@ -730,9 +729,13 @@ packet2tree(const u_char * data, const int len)
     if (ether_type == htons(ETHERTYPE_VLAN)) {
        dbg(4,"Processing as VLAN traffic...");
 
+       hl += 4;
+       if (len < TCPR_ETH_H + hl) {
+           goto len_error;
+       }
+
        /* prevent issues with byte alignment, must memcpy */
        memcpy(&ether_type, (u_char*)eth_hdr + 16, 2);
-       hl += 4;
     }
 
     if (ether_type == htons(ETHERTYPE_IP)) {
@@ -743,6 +746,10 @@ packet2tree(const u_char * data, const int len)
             return NULL;
         }
 
+        if (len < TCPR_ETH_H + TCPR_IPV4_H + hl) {
+            goto len_error;
+        }
+
         memcpy(&ip_hdr, (data + TCPR_ETH_H + hl), TCPR_IPV4_H);
 
         node->family = AF_INET;
@@ -762,6 +769,10 @@ packet2tree(const u_char * data, const int len)
             return NULL;
         }
 
+        if (len < TCPR_ETH_H + TCPR_IPV6_H + hl) {
+            goto len_error;
+        }
+
         memcpy(&ip6_hdr, (data + TCPR_ETH_H + hl), TCPR_IPV6_H);
 
         node->family = AF_INET6;
@@ -789,6 +800,10 @@ packet2tree(const u_char * data, const int len)
 
         dbgx(3, "%s uses TCP...  ", srcip);
 
+        if (len < TCPR_ETH_H + TCPR_TCP_H + hl) {
+            goto len_error;
+        }
+
         /* memcpy it over to prevent alignment issues */
         memcpy(&tcp_hdr, (data + TCPR_ETH_H + hl), TCPR_TCP_H);
 
@@ -814,12 +829,20 @@ packet2tree(const u_char * data, const int len)
      * UDP 
      */
     else if (proto == IPPROTO_UDP) {
+        if (len < TCPR_ETH_H + TCPR_UDP_H + hl) {
+            goto len_error;
+        }
+
         /* memcpy over to prevent alignment issues */
         memcpy(&udp_hdr, (data + TCPR_ETH_H + hl), TCPR_UDP_H);
         dbgx(3, "%s uses UDP...  ", srcip);
 
         switch (ntohs(udp_hdr.uh_dport)) {
         case 0x0035:           /* dns */
+            if (len < TCPR_ETH_H + TCPR_UDP_H + TCPR_DNS_H + hl) {
+                goto len_error;
+            }
+
             /* prevent memory alignment issues */
             memcpy(&dnsv4_hdr,
                    (data + TCPR_ETH_H + hl + TCPR_UDP_H), TCPR_DNS_H);
@@ -845,6 +868,10 @@ packet2tree(const u_char * data, const int len)
 
         switch (ntohs(udp_hdr.uh_sport)) {
         case 0x0035:           /* dns */
+            if (len < TCPR_ETH_H + TCPR_UDP_H + TCPR_DNS_H + hl) {
+                goto len_error;
+            }
+
             /* prevent memory alignment issues */
             memcpy(&dnsv4_hdr,
                    (data + TCPR_ETH_H + hl + TCPR_UDP_H),
@@ -873,6 +900,9 @@ packet2tree(const u_char * data, const int len)
      * ICMP 
      */
     else if (proto == IPPROTO_ICMP) {
+        if (len < TCPR_ETH_H + TCPR_ICMPV4_H + hl) {
+            goto len_error;
+        }
 
         /* prevent alignment issues */
         memcpy(&icmp_hdr, (data + TCPR_ETH_H + hl), TCPR_ICMPV4_H);
@@ -891,6 +921,10 @@ packet2tree(const u_char * data, const int len)
     }
 
     return (node);
+
+len_error:
+    errx(-1, "packet capture length %d too small to process", len);
+    return NULL;
 }
 
 #ifdef DEBUG

+ 1 - 0
test/Makefile.in

@@ -237,6 +237,7 @@ am__untar = @am__untar@
 bindir = @bindir@
 build = @build@
 build_alias = @build_alias@
+build_asan = @build_asan@
 build_cpu = @build_cpu@
 build_os = @build_os@
 build_vendor = @build_vendor@