ソースを参照

Merge upstream version 4.4.2

Christoph Biedl 2 年 前
コミット
18bd7d8df9

+ 1 - 1
Makefile.am

@@ -59,6 +59,6 @@ DISTCLEANFILES = .tm_project.cache stamp-h1 *.tar.*
 
 MAINTAINERCLEANFILES = Makefile.in configure *.bak
 
-EXTRA_DIST = doxygen.cfg.in autogen.sh \
+EXTRA_DIST = doxygen.cfg.in \
 	m4/libtool.m4 m4/ltoptions.m4 m4/ltsugar.m4 \
 	m4/ltversion.m4 m4/lt~obsolete.m4 acinclude.m4

+ 1 - 1
Makefile.in

@@ -389,7 +389,7 @@ TEST_DIR = $(top_builddir)/test
 MOSTLYCLEANFILES = tcpreplay.spec *~
 DISTCLEANFILES = .tm_project.cache stamp-h1 *.tar.*
 MAINTAINERCLEANFILES = Makefile.in configure *.bak
-EXTRA_DIST = doxygen.cfg.in autogen.sh \
+EXTRA_DIST = doxygen.cfg.in \
 	m4/libtool.m4 m4/ltoptions.m4 m4/ltsugar.m4 \
 	m4/ltversion.m4 m4/lt~obsolete.m4 acinclude.m4
 

+ 0 - 19
autogen.sh

@@ -1,19 +0,0 @@
-#!/bin/sh
-
-set -e
-
-cd $(dirname $0)
-
-rm -f config/config.guess config/config.sub config/ltmain.sh 2>/dev/null
-rm -f aclocal.m4 2>/dev/null
-aclocal  -I libopts/m4/
-if test -x "$(which glibtoolize)" ; then
-    # Necessary under OS X
-    glibtoolize --copy --automake --force
-else
-    libtoolize --copy --force
-fi
-autoheader
-automake --add-missing --copy
-autoconf
-

+ 12 - 12
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.4.1.
+# Generated by GNU Autoconf 2.69 for tcpreplay 4.4.2.
 #
 # 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.4.1'
-PACKAGE_STRING='tcpreplay 4.4.1'
+PACKAGE_VERSION='4.4.2'
+PACKAGE_STRING='tcpreplay 4.4.2'
 PACKAGE_BUGREPORT='https://github.com/appneta/tcpreplay/issues'
 PACKAGE_URL='http://tcpreplay.sourceforge.net/'
 
@@ -1445,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.4.1 to adapt to many kinds of systems.
+\`configure' configures tcpreplay 4.4.2 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1517,7 +1517,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of tcpreplay 4.4.1:";;
+     short | recursive ) echo "Configuration of tcpreplay 4.4.2:";;
    esac
   cat <<\_ACEOF
 
@@ -1689,7 +1689,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-tcpreplay configure 4.4.1
+tcpreplay configure 4.4.2
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2649,7 +2649,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.4.1, which was
+It was created by tcpreplay $as_me 4.4.2, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -3816,7 +3816,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='tcpreplay'
- VERSION='4.4.1'
+ VERSION='4.4.2'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -23277,7 +23277,7 @@ case "$host_os" in
         case "$host_cpu" in
 
         # XXX: should also check that they don't do weird things
-        alpha*|hp*|mips*|sparc*|ia64)
+        alpha*|arm*|hp*|mips*|sparc*|ia64)
                 unaligned_cv_fail=yes
                 ;;
 
@@ -23434,7 +23434,7 @@ fi
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 'make test' profile" >&5
 $as_echo_n "checking for 'make test' profile... " >&6; }
-if test "$host" == "$build" ; then
+if test "$host" = "$build" ; then
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
@@ -25873,7 +25873,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.4.1, which was
+This file was extended by tcpreplay $as_me 4.4.2, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -25940,7 +25940,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.4.1
+tcpreplay config.status 4.4.2
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 

+ 3 - 3
configure.ac

@@ -4,7 +4,7 @@ dnl $Id$
 AC_PREREQ([2.69])
 
 dnl Set version info here!
-AC_INIT([tcpreplay],[4.4.1],[https://github.com/appneta/tcpreplay/issues],[tcpreplay],[http://tcpreplay.sourceforge.net/])
+AC_INIT([tcpreplay],[4.4.2],[https://github.com/appneta/tcpreplay/issues],[tcpreplay],[http://tcpreplay.sourceforge.net/])
 AC_CONFIG_SRCDIR([src/tcpreplay.c])
 AC_CONFIG_HEADERS([src/config.h])
 AC_CONFIG_AUX_DIR(config)
@@ -1717,7 +1717,7 @@ case "$host_os" in
         case "$host_cpu" in
 
         # XXX: should also check that they don't do weird things
-        alpha*|hp*|mips*|sparc*|ia64)
+        alpha*|arm*|hp*|mips*|sparc*|ia64)
                 unaligned_cv_fail=yes
                 ;;
 
@@ -1808,7 +1808,7 @@ fi
 dnl No 'make test' when cross compile
 
 AC_MSG_CHECKING(for 'make test' profile)
-if test "$host" == "$build" ; then
+if test "$host" = "$build" ; then
     AC_MSG_RESULT([yes])
 else    
     AC_MSG_WARN(Unable to do tests when cross-compiling)

+ 13 - 0
docs/CHANGELOG

@@ -1,3 +1,16 @@
+08/28/2022 Version 4.4.2
+    - remove autogen.sh from distribution tarballs (#745)
+    - CVE-2022-37048 heap-overflow in get_l2len_protocol (#735)
+    - replaying on a loopback interface is broken (#732)
+    - replay edit with both --loop and --preload_pcap options (#729)
+    - test suite bus error on armhf (#725)
+    - CVE-2022-28487 format string vulnerability in fix_ipv6_checksums (#723)
+    - CVE-2022-27942 heap-overflow in parse_mpls (#719)
+    - CVE-2022-27940 CVE-2022-37047 CVE-2022-37049 heap-overflow in get_ipv6_next (#718)
+    - CVE-2022-27939 reachable assertion in get_layer4_v6 (#717)
+    - CVE-2022-25484 CVE-2022-27941 heap buffer overflow in get_l2len_protocol (#716)
+    - remove bash-only test in configure script (#714)
+
 02/12/2022 Version 4.4.1
     - fix support for piping PCAP files from STDIN (#708)
     - build failures Debian/kfreebsd (#706)

+ 0 - 2
src/common/flows.c

@@ -201,8 +201,6 @@ flow_entry_type_t flow_decode(flow_hash_table_t *fht, const struct pcap_pkthdr *
         return FLOW_ENTRY_INVALID;
     }
 
-    assert(l2len > 0);
-
     if (ether_type == ETHERTYPE_IP) {
         if (pkt_len < l2len + sizeof(ipv4_hdr_t))
                 return FLOW_ENTRY_INVALID;

+ 50 - 48
src/common/get.c

@@ -42,6 +42,10 @@ extern const char pcap_version[];
 #define JUNIPER_FLAG_NO_L2          0x02     /* L2 header */
 #define JUNIPER_FLAG_EXT            0x80     /* Juniper extensions present */
 #define JUNIPER_PCAP_MAGIC          "MGC"
+
+static void *
+get_ipv6_next(struct tcpr_ipv6_ext_hdr_base *exthdr, const u_char *end_ptr);
+
 /**
  * Depending on what version of libpcap/WinPcap there are different ways to get 
  * the version of the libpcap/WinPcap library.  This presents a unified way to 
@@ -94,7 +98,7 @@ int parse_mpls(const u_char *pktdata,
                uint32_t *l2offset)
 {
     struct tcpr_mpls_label *mpls_label;
-    int len_remaining = (int)datalen;
+    const u_char *end_ptr = pktdata + datalen;
     u_char first_nibble;
     eth_hdr_t *eth_hdr;
     bool bos = false;
@@ -109,12 +113,11 @@ int parse_mpls(const u_char *pktdata,
 
     /* move over MPLS labels until we get to the last one */
     while (!bos) {
-        if (len_remaining < (int)sizeof(*mpls_label))
+        if (pktdata + len + sizeof(*mpls_label) > end_ptr)
             return -1;
 
         mpls_label = (struct tcpr_mpls_label*)(pktdata + len);
         len += sizeof(*mpls_label);
-        len_remaining -= sizeof(*mpls_label);
         bos = (ntohl(mpls_label->entry) & MPLS_LS_S_MASK) != 0;
         label = ntohl(mpls_label->entry) >> MPLS_LS_LABEL_SHIFT;
         if (label == MPLS_LABEL_GACH) {
@@ -124,7 +127,7 @@ int parse_mpls(const u_char *pktdata,
         }
     }
 
-    if (len_remaining < 4)
+    if ((u_char*)mpls_label + 1 > end_ptr)
         return -1;
 
     first_nibble = *((u_char *)(mpls_label + 1)) >> 4;
@@ -139,11 +142,10 @@ int parse_mpls(const u_char *pktdata,
         /* EoMPLS - jump over PW Ethernet Control Word and handle
          * inner Ethernet header
          */
-        len += 4;
-        len_remaining -= 4;
-        if (len_remaining < (int)sizeof(*eth_hdr))
+        if (pktdata + len + 4 + sizeof(*eth_hdr) > end_ptr)
             return -1;
 
+        len += 4;
         *l2offset = len;
         eth_hdr = (eth_hdr_t*)(pktdata + len);
         len += sizeof(*eth_hdr);
@@ -270,6 +272,7 @@ int get_l2len_protocol(const u_char *pktdata,
     *vlan_offset = 0;
 
     switch (datalink) {
+    case DLT_NULL:
     case DLT_RAW:
         if (datalen == 0)
             return -1;
@@ -317,13 +320,15 @@ int get_l2len_protocol(const u_char *pktdata,
         /* fall through */
     case DLT_EN10MB:
     {
-        eth_hdr_t *eth_hdr = (eth_hdr_t*)(pktdata + *l2offset);
+        eth_hdr_t *eth_hdr;
+        uint16_t ether_type;
         uint32_t l2_net_off = sizeof(*eth_hdr) + *l2offset;
-        uint16_t ether_type = ntohs(eth_hdr->ether_type);
 
         if (datalen <= l2_net_off)
             return -1;
 
+        eth_hdr = (eth_hdr_t*)(pktdata + *l2offset);
+        ether_type = ntohs(eth_hdr->ether_type);
         if (parse_metadata(pktdata,
                            datalen,
                            &ether_type,
@@ -332,7 +337,7 @@ int get_l2len_protocol(const u_char *pktdata,
                            vlan_offset))
             return -1;
 
-        if (datalen < l2_net_off)
+        if (datalen <= l2_net_off)
             return -1;
 
         *l2len = l2_net_off;
@@ -568,15 +573,16 @@ 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 l3len)
+get_layer4_v4(const ipv4_hdr_t *ip_hdr, const u_char *end_ptr)
 {
     void *ptr;
 
     assert(ip_hdr);
+    assert(end_ptr);
 
     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 + l3len))
+    if ((u_char *)ptr > end_ptr)
         return NULL;
 
     return ((void *)ptr);
@@ -588,24 +594,21 @@ get_layer4_v4(const ipv4_hdr_t *ip_hdr, const int l3len)
  * v6 Frag or ESP header.  Function is recursive.
  */
 void *
-get_layer4_v6(const ipv6_hdr_t *ip6_hdr, const int l3len)
+get_layer4_v6(const ipv6_hdr_t *ip6_hdr, const u_char *end_ptr)
 {
     struct tcpr_ipv6_ext_hdr_base *next, *exthdr;
     bool done = false;
-    uint32_t maxlen;
     uint8_t proto;
-    int min_len;
 
     assert(ip6_hdr);
-
-    min_len = TCPR_IPV6_H + sizeof(struct tcpr_ipv6_ext_hdr_base);
-    if (l3len < min_len)
-        return NULL;
+    assert(end_ptr);
 
     /* jump to the end of the IPv6 header */
     next = (struct tcpr_ipv6_ext_hdr_base *)((u_char *)ip6_hdr + TCPR_IPV6_H);
-    proto = ip6_hdr->ip_nh;
+    if ((u_char*)next > end_ptr)
+        return NULL;
 
+    proto = ip6_hdr->ip_nh;
     while (!done) {
         dbgx(3, "Processing proto: 0x%hx", (uint16_t)proto);
 
@@ -613,7 +616,7 @@ get_layer4_v6(const ipv6_hdr_t *ip6_hdr, const int l3len)
         /* 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");
-            next = get_layer4_v6((ipv6_hdr_t *)next, l3len - min_len);
+            next = get_layer4_v6((ipv6_hdr_t *)next, end_ptr);
             break;
 
         /* loop again */
@@ -622,9 +625,9 @@ get_layer4_v6(const ipv6_hdr_t *ip6_hdr, const int l3len)
         case TCPR_IPV6_NH_DESTOPTS:
         case TCPR_IPV6_NH_HBH:
             dbgx(3, "Going deeper due to extension header 0x%02X", proto);
-            maxlen = l3len - (int)((u_char *)ip6_hdr - (u_char *)next);
-            exthdr = get_ipv6_next(next, maxlen);
+            exthdr = get_ipv6_next(next, end_ptr);
             if (exthdr == NULL) {
+                next = NULL;
                 done = true;
                 break;
             }
@@ -655,10 +658,10 @@ get_layer4_v6(const ipv6_hdr_t *ip6_hdr, const int l3len)
 
             done = true;
         } /* switch */
-    } /* while */
 
-    if (!next || (u_char*)next > (u_char*)ip6_hdr + l3len)
-        return NULL;
+        if (next == NULL)
+            done = true;
+    } /* while */
 
     return next;
 }
@@ -668,15 +671,15 @@ get_layer4_v6(const ipv6_hdr_t *ip6_hdr, const int l3len)
  * returns the next payload or header of the current extension header
  * returns NULL for none/ESP.
  */
-void *
-get_ipv6_next(struct tcpr_ipv6_ext_hdr_base *exthdr, const int len)
+static void *
+get_ipv6_next(struct tcpr_ipv6_ext_hdr_base *exthdr, const u_char *end_ptr)
 {
-    int extlen = 0;
-    int maxlen;
-    void *ptr;
+    uint8_t extlen = 0;
+    u_char *ptr;
     assert(exthdr);
 
-    maxlen = *((int*)((u_char *)exthdr + len));
+    if ((u_char*)exthdr + sizeof(*exthdr) > end_ptr)
+        return NULL;
 
     dbgx(3, "Jumping to next IPv6 header.  Processing 0x%02x", exthdr->ip_nh);
     switch (exthdr->ip_nh) {
@@ -695,9 +698,9 @@ get_ipv6_next(struct tcpr_ipv6_ext_hdr_base *exthdr, const int len)
     case TCPR_IPV6_NH_FRAGMENT:
         dbg(3, "Looks like were a fragment header. Returning some frag'd data.");
         ptr = (void *)((u_char *)exthdr + sizeof(struct tcpr_ipv6_frag_hdr));
-        if (*(int*)ptr > maxlen)
+        if (ptr > end_ptr)
             return NULL;
-        return ptr;
+        return (void *)ptr;
         break;
 
     /* all the rest require us to go deeper using the ip_len field */
@@ -708,11 +711,11 @@ get_ipv6_next(struct tcpr_ipv6_ext_hdr_base *exthdr, const int len)
     case TCPR_IPV6_NH_AH:
         extlen = IPV6_EXTLEN_TO_BYTES(exthdr->ip_len);
         dbgx(3, "Looks like we're an ext header (0x%hhx).  Jumping %u bytes"
-               " to the next", exthdr->ip_nh, extlen);
-        ptr = (void *)((u_char *)exthdr + extlen);
-        if (*(int*)ptr > maxlen)
+                " to the next", exthdr->ip_nh, extlen);
+        ptr = (u_char *)exthdr + extlen;
+        if (ptr > end_ptr)
             return NULL;
-        return ptr;
+        return (void *)ptr;
         break;
 
     default:
@@ -727,7 +730,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, const int l3len)
+get_ipv6_l4proto(const ipv6_hdr_t *ip6_hdr, const u_char *end_ptr)
 {
     u_char *ptr = (u_char *)ip6_hdr + TCPR_IPV6_H; /* jump to the end of the IPv6 header */
     uint8_t proto;
@@ -735,15 +738,15 @@ get_ipv6_l4proto(const ipv6_hdr_t *ip6_hdr, const int l3len)
 
     assert(ip6_hdr);
 
-    proto = ip6_hdr->ip_nh;
-    int l4len = l3len - TCPR_IPV6_H;
-    if (l4len < 0)
-        return proto;
+    if (ptr > end_ptr)
+        return TCPR_IPV6_NH_NO_NEXT;
 
+    proto = ip6_hdr->ip_nh;
     while (TRUE) {
         dbgx(3, "Processing next proto 0x%02X", proto);
         switch (proto) {
             /* no further processing for IPV6 types with nothing beyond them */
+            case TCPR_IPV6_NH_NO_NEXT:
             case TCPR_IPV6_NH_FRAGMENT:
             case TCPR_IPV6_NH_ESP:
                 dbg(3, "No-Next or ESP... can't go any further...");
@@ -753,7 +756,7 @@ get_ipv6_l4proto(const ipv6_hdr_t *ip6_hdr, const int l3len)
             /* recurse */
             case TCPR_IPV6_NH_IPV6:
                 dbg(3, "Recursing due to v6 in v6");
-                return get_ipv6_l4proto((ipv6_hdr_t *)ptr, l4len);
+                return get_ipv6_l4proto((ipv6_hdr_t *)ptr, end_ptr);
                 break;
 
             /* loop again */
@@ -763,11 +766,10 @@ get_ipv6_l4proto(const ipv6_hdr_t *ip6_hdr, const int l3len)
             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,
-                        l4len);
-                if (exthdr == NULL)
-                    return proto;
+                        end_ptr);
+                if (exthdr == NULL || (u_char*)exthdr + sizeof(*exthdr) > end_ptr)
+                    return TCPR_IPV6_NH_NO_NEXT;
                 proto = exthdr->ip_nh;
-                l4len -= (u_char *)exthdr - ptr;
                 ptr = (u_char *)exthdr;
                 break;
 

+ 3 - 4
src/common/get.h

@@ -47,11 +47,10 @@ int get_l2len_protocol(const u_char *pktdata,
                        uint32_t *l2offset,
                        uint32_t *vlan_offset);
 
-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);
+void *get_layer4_v4(const ipv4_hdr_t *ip_hdr, const u_char *end_ptr);
+void *get_layer4_v6(const ipv6_hdr_t *ip_hdr, const u_char *end_ptr);
 
-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);
+u_int8_t get_ipv6_l4proto(const ipv6_hdr_t *ip6_hdr, const u_char *end_ptr);
 
 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.4.1";
+const char GIT_Version[] = "git:v4.4.2";
 const char *git_version(void) {
     return GIT_Version;
 }

+ 0 - 3
src/send_packets.c

@@ -444,9 +444,6 @@ send_packets(tcpreplay_t *ctx, pcap_t *pcap, int idx)
                     timeradd(&stats->pkt_ts_delta, &delta, &stats->pkt_ts_delta);
                     TIMEVAL_SET(&last_pkt_ts, &pkthdr.ts);
                 }
-
-                if (!timerisset(&stats->time_delta))
-                    TIMEVAL_SET(&stats->pkt_ts_delta, &stats->pkt_ts_delta);
             }
 
             if (!top_speed) {

+ 1 - 1
src/tcpbridge.1

@@ -10,7 +10,7 @@
 .ds B-Font B
 .ds I-Font I
 .ds R-Font R
-.TH tcpbridge 1 "12 Feb 2022" "tcpbridge" "User Commands"
+.TH tcpbridge 1 "26 Aug 2022" "tcpbridge" "User Commands"
 .\"
 .\" DO NOT EDIT THIS FILE (in-mem file)
 .\"

+ 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 Feb 2022" "Tcpreplay Suite" "User Commands"
+.TH tcpcapinfo 1 "26 Aug 2022" "Tcpreplay Suite" "User Commands"
 .\"
 .\" DO NOT EDIT THIS FILE (in-mem file)
 .\"

+ 8 - 3
src/tcpedit/checksum.c

@@ -34,7 +34,12 @@ 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 len,
+            const u_char *end_ptr)
+{
     ipv4_hdr_t *ipv4;
     ipv6_hdr_t *ipv6;
     tcp_hdr_t *tcp;
@@ -60,10 +65,10 @@ do_checksum(tcpedit_t *tcpedit, uint8_t *data, int proto, int len) {
         ipv6 = (ipv6_hdr_t *)data;
         ipv4 = NULL;
 
-        proto = get_ipv6_l4proto(ipv6, len + sizeof(ipv6_hdr_t));
+        proto = get_ipv6_l4proto(ipv6, end_ptr);
         dbgx(3, "layer4 proto is 0x%hx", (uint16_t)proto);
 
-        layer = (u_char*)get_layer4_v6(ipv6, len + sizeof(ipv6_hdr_t));
+        layer = (u_char*)get_layer4_v6(ipv6, end_ptr);
         if (!layer) {
             tcpedit_setwarn(tcpedit, "%s", "Packet to short for checksum");
             return TCPEDIT_WARN;

+ 1 - 1
src/tcpedit/checksum.h

@@ -24,6 +24,6 @@
 #define CHECKSUM_CARRY(x) \
     (x = (x >> 16) + (x & 0xffff), (~(x + (x >> 16)) & 0xffff))
 
-int do_checksum(tcpedit_t *, u_int8_t *, int, int);
+int do_checksum(tcpedit_t *, u_int8_t *, int, int, const u_char*);
 
 #endif

+ 23 - 18
src/tcpedit/edit_packet.c

@@ -87,14 +87,21 @@ fix_ipv4_checksums(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
                            tcpedit->runtime.packetnum);
             return TCPEDIT_ERROR;
         }
-        ret1 = do_checksum(tcpedit, (u_char*)ip_hdr, ip_hdr->ip_p,
-                           ip_len - (ip_hdr->ip_hl << 2));
+        ret1 = do_checksum(tcpedit,
+                           (u_char*)ip_hdr,
+                           ip_hdr->ip_p,
+                           ip_len - (ip_hdr->ip_hl << 2),
+                           (u_char*)ip_hdr + pkthdr->caplen - l2len);
         if (ret1 < 0)
             return TCPEDIT_ERROR;
     }
     
     /* calc IP checksum */
-    ret2 = do_checksum(tcpedit, (u_char *) ip_hdr, IPPROTO_IP, ip_len);
+    ret2 = do_checksum(tcpedit,
+                       (u_char*)ip_hdr,
+                       IPPROTO_IP,
+                       ip_len,
+                       (u_char*)ip_hdr + pkthdr->caplen - l2len);
     if (ret2 < 0)
         return TCPEDIT_ERROR;
 
@@ -161,11 +168,14 @@ fix_ipv6_checksums(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
         int ip6_len = ipv6_header_length(ip6_hdr, pkthdr->len, l2len);
         if (ip6_hdr->ip_len < ip6_len) {
             tcpedit_setwarn(tcpedit, "Unable to checksum IPv6 packet with invalid: pkt=" COUNTER_SPEC " IP length=%u caplen=" COUNTER_SPEC,
-                           tcpedit->runtime.packetnum, ip6_hdr->ip_len);
+                           tcpedit->runtime.packetnum, ip6_hdr->ip_len, pkthdr->caplen);
             return TCPEDIT_WARN;
         }
-        ret = do_checksum(tcpedit, (u_char *)ip6_hdr, ip6_hdr->ip_nh,
-            htons(ip6_hdr->ip_len));
+        ret = do_checksum(tcpedit,
+                          (u_char*)ip6_hdr,
+                          ip6_hdr->ip_nh,
+                          htons(ip6_hdr->ip_len),
+                          (u_char*)ip6_hdr + pkthdr->caplen - l2len);
         if (ret < 0)
             return TCPEDIT_ERROR;
     }
@@ -265,13 +275,13 @@ static void ipv4_addr_csum_replace(ipv4_hdr_t *ip_hdr, uint32_t old_ip,
     protocol = ip_hdr->ip_p;
     switch (protocol) {
     case IPPROTO_UDP:
-        l4 = get_layer4_v4(ip_hdr, len);
+        l4 = get_layer4_v4(ip_hdr, (u_char *)ip_hdr + l3len);
         len -= ip_hdr->ip_hl << 2;
         len -= TCPR_UDP_H;
         break;
 
     case IPPROTO_TCP:
-        l4 = get_layer4_v4(ip_hdr, len);
+        l4 = get_layer4_v4(ip_hdr, (u_char *)ip_hdr + l3len);
         len -= ip_hdr->ip_hl << 2;
         len -= TCPR_TCP_H;
         break;
@@ -293,32 +303,27 @@ static void ipv6_addr_csum_replace(ipv6_hdr_t *ip6_hdr,
         const int l3len)
 {
     uint8_t *l4, protocol;
-    int len = l3len;
 
     assert(ip6_hdr);
 
-    if ((size_t)len < sizeof(*ip6_hdr))
+    if ((size_t)l3len < sizeof(*ip6_hdr))
         return;
 
-    protocol = get_ipv6_l4proto(ip6_hdr, len);
+    protocol = get_ipv6_l4proto(ip6_hdr, (u_char*)ip6_hdr + l3len);
     switch (protocol) {
     case IPPROTO_UDP:
-        l4 = get_layer4_v6(ip6_hdr, len);
-        len -= sizeof(*ip6_hdr);
-        len -= TCPR_UDP_H;
+        l4 = get_layer4_v6(ip6_hdr, (u_char*)ip6_hdr + l3len);
         break;
 
     case IPPROTO_TCP:
-        l4 = get_layer4_v6(ip6_hdr, len);
-        len -= sizeof(*ip6_hdr);
-        len -= TCPR_TCP_H;
+        l4 = get_layer4_v6(ip6_hdr, (u_char*)ip6_hdr + l3len);
         break;
 
     default:
         l4 = NULL;
     }
 
-    if (!l4 || len < 0)
+    if (!l4)
         return;
 
     ipv6_l34_csum_replace(l4, protocol, (uint32_t*)old_ip, (uint32_t*)new_ip);

+ 40 - 37
src/tcpedit/fuzzing.c

@@ -73,11 +73,11 @@ int
 fuzzing(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
         u_char **pktdata)
 {
-    int packet_changed = 0;
+    int chksum_update_required = 0;
     uint32_t r, s;
     uint16_t l2proto;
     uint8_t l4proto;
-    u_char *packet, *l3data, *l4data;
+    u_char *packet, *l3data, *l4data, *end_ptr;
     tcpeditdlt_plugin_t *plugin;
     int l2len, l4len;
     tcpeditdlt_t *ctx;
@@ -102,6 +102,7 @@ fuzzing(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
     /* initializations */
     ctx = tcpedit->dlt_ctx;
     packet = *pktdata;
+    end_ptr = packet + pkthdr->caplen;
     plugin = tcpedit->dlt_ctx->encoder;
     l2len = plugin->plugin_l2len(ctx, packet, pkthdr->caplen);
     l2proto = ntohs(plugin->plugin_proto(ctx, packet, pkthdr->caplen));
@@ -119,29 +120,31 @@ fuzzing(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
     if (!l3data)
         goto done;
 
-    l4len = pkthdr->caplen - l2len;
     switch (l2proto) {
     case (ETHERTYPE_IP):
     {
-        l4data = get_layer4_v4((ipv4_hdr_t*)l3data, pkthdr->caplen - l2len);
+        l4data = get_layer4_v4((ipv4_hdr_t*)(packet + l2len), end_ptr);
         if (!l4data)
             goto done;
 
+        l4len = l4data - packet;
         l4proto = ((ipv4_hdr_t *)l3data)->ip_p;
         break;
     }
     case (ETHERTYPE_IP6): {
-        l4data = get_layer4_v6((ipv6_hdr_t*)l3data, pkthdr->caplen - l2len);
+        l4data = get_layer4_v6((ipv6_hdr_t*)(packet + l2len), end_ptr);
         if (!l4data)
             goto done;
 
+        l4len = l4data - packet;
         l4proto = ((ipv6_hdr_t *)l3data)->ip_nh;
         break;
     }
     default:
         /* apply fuzzing on unknown packet types */
-       l4data = l3data;
-       l4proto = IPPROTO_RAW;
+        l4len = pkthdr->caplen - l2len;
+        l4data = packet + l2len;
+        l4proto = IPPROTO_RAW;
 
     }
 
@@ -149,21 +152,21 @@ fuzzing(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
     switch (l4proto) {
     case IPPROTO_TCP:
         l4len -= sizeof(tcp_hdr_t);
+        l4data += sizeof(tcp_hdr_t);
         break;
     case IPPROTO_UDP:
         l4len -= sizeof(udp_hdr_t);
+        l4data += sizeof(udp_hdr_t);
         break;
     }
 
-    if (l4len <= 1)
+    if (l4len <= 1 || l4data > end_ptr)
         goto done;
 
     /* add some additional randomization */
     r ^= r >> 16;
 
     s = r % FUZZING_TOTAL_ACTION_NUMBER;
-
-    dbgx(3, "packet fuzzed : %d", s);
     switch (s) {
     case FUZZING_DROP_PACKET:
     {
@@ -172,18 +175,17 @@ fuzzing(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
             /* could not change packet size, so packet left unchanged */
             goto done;
 
-        packet_changed = 1;
         break;
     }
     case FUZZING_REDUCE_SIZE:
     {
         /* reduce packet size */
-        uint32_t new_len = (r % ((l4len) - 1)) + 1;
+        uint32_t new_len = (r % (l4len - 1)) + 1;
         if (fuzz_reduce_packet_size(tcpedit, pkthdr, new_len) < 0)
             /* could not change packet size, so packet left unchanged */
             goto done;
 
-        packet_changed = 1;
+        chksum_update_required = 1;
         break;
     }
     case FUZZING_CHANGE_START_ZERO:
@@ -191,7 +193,7 @@ fuzzing(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
         /* fuzz random-size segment at the beginning of the packet with 0x00 */
         uint32_t sgt_size = fuzz_get_sgt_size(r, l4len);
         memset(l4data, 0x00, sgt_size);
-        packet_changed = 1;
+        chksum_update_required = 1;
         break;
     }
     case FUZZING_CHANGE_START_RANDOM:
@@ -208,7 +210,7 @@ fuzzing(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
         for (i = 0; i < sgt_size; i++)
             l4data[i] = l4data[i] ^ (u_char)(r >> 4);
 
-        packet_changed = 1;
+        chksum_update_required = 1;
         break;
     }
     case FUZZING_CHANGE_START_FF:
@@ -222,67 +224,73 @@ fuzzing(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
             goto done;
 
         memset(l4data, 0xff, sgt_size);
-        packet_changed = 1;
+        chksum_update_required = 1;
         break;
     }
     case FUZZING_CHANGE_MID_ZERO:
     {
         /* fuzz random-size segment inside the packet payload with 0x00 */
+        if (l4len <= 2)
+            goto done;
+
         uint32_t offset = ((r >> 16) % (l4len - 1)) + 1;
         uint32_t sgt_size = fuzz_get_sgt_size(r, l4len - offset);
         if (!sgt_size)
             goto done;
 
         memset(l4data + offset, 0x00, sgt_size);
-        packet_changed = 1;
+        chksum_update_required = 1;
         break;
     }
     case FUZZING_CHANGE_MID_FF:
     {
         /* fuzz random-size segment inside the packet payload with 0xff */
+        if (l4len <= 2)
+            goto done;
+
         uint32_t offset = ((r >> 16) % (l4len - 1)) + 1;
         uint32_t sgt_size = fuzz_get_sgt_size(r, l4len - offset);
         if (!sgt_size)
             goto done;
 
         memset(l4data + offset, 0xff, sgt_size);
-        packet_changed = 1;
+        chksum_update_required = 1;
         break;
     }
     case FUZZING_CHANGE_END_ZERO:
     {
         /* fuzz random-sized segment at the end of the packet payload with 0x00 */
-        uint32_t sgt_size = fuzz_get_sgt_size(r, l4len);
-        if (!sgt_size)
+        int sgt_size = fuzz_get_sgt_size(r, l4len);
+        if (!sgt_size || sgt_size > l4len)
             goto done;
 
         memset(l4data + l4len - sgt_size, 0x00, sgt_size);
-        packet_changed = 1;
+        chksum_update_required = 1;
         break;
     }
     case FUZZING_CHANGE_END_RANDOM:
     {
         /* fuzz random-sized segment at the end of the packet with random Bytes */
         int i;
-        uint32_t sgt_size = fuzz_get_sgt_size(r, l4len);
-        if (!sgt_size)
+        int sgt_size = fuzz_get_sgt_size(r, l4len);
+        if (!sgt_size || sgt_size > l4len)
             goto done;
 
         for (i = (l4len - sgt_size); i < l4len; i++)
             l4data[i] = l4data[i] ^ (u_char)(r >> 4);
 
-        packet_changed = 1;
+        chksum_update_required = 1;
         break;
     }
     case FUZZING_CHANGE_END_FF:
     {
         /* fuzz random-sized segment at the end of the packet with 0xff00 */
-        uint32_t sgt_size = fuzz_get_sgt_size(r, l4len);
-        if (!sgt_size)
+        int sgt_size = fuzz_get_sgt_size(r, l4len);
+        if (!sgt_size || sgt_size > l4len)
             goto done;
 
         memset(l4data + l4len - sgt_size, 0xff, sgt_size);
-        packet_changed = 1;
+        chksum_update_required = 1;
         break;
     }
 
@@ -291,27 +299,22 @@ fuzzing(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
         /* fuzz random-size segment inside the packet with random Bytes */
         size_t i;
         uint32_t offset = ((r >> 16) % (l4len - 1)) + 1;
-        uint32_t sgt_size = fuzz_get_sgt_size(r, l4len - offset);
-        if (!sgt_size)
+        int sgt_size = fuzz_get_sgt_size(r, l4len - offset);
+        if (!sgt_size || sgt_size > l4len)
             goto done;
 
         for (i = offset; i < offset + sgt_size; i++)
             l4data[i] = l4data[i] ^ (u_char)(r >> 4);
 
-        packet_changed = 1;
+        chksum_update_required = 1;
         break;
     }
     default:
         assert(false);
     }
 
-    /* in cases where 'l3data' is a working buffer, copy it back to '*pkthdr' */
-    plugin->plugin_merge_layer3(ctx,
-                                packet,
-                                pkthdr->caplen,
-                                (l2proto == ETHERTYPE_IP) ? l4data : NULL,
-                                (l2proto == ETHERTYPE_IP6) ? l4data : NULL);
+    dbgx(3, "packet %llu fuzzed : %d", tcpedit->runtime.packetnum, s);
 
 done:
-    return packet_changed;
+    return chksum_update_required;
 }

+ 2 - 2
src/tcpedit/portmap.c

@@ -370,7 +370,7 @@ rewrite_ipv4_ports(tcpedit_t *tcpedit, ipv4_hdr_t **ip_hdr, const int l3len)
                 l3len);
         return TCPEDIT_ERROR;
     } else if ((*ip_hdr)->ip_p == IPPROTO_TCP || (*ip_hdr)->ip_p == IPPROTO_UDP) {
-        l4 = get_layer4_v4(*ip_hdr, l3len);
+        l4 = get_layer4_v4(*ip_hdr, (u_char *)ip_hdr + l3len);
         if (l4)
             return rewrite_ports(tcpedit, (*ip_hdr)->ip_p, l4,
                     l3len - (l4 - (u_char*)*ip_hdr));
@@ -394,7 +394,7 @@ rewrite_ipv6_ports(tcpedit_t *tcpedit, ipv6_hdr_t **ip6_hdr, const int l3len)
                 l3len);
         return TCPEDIT_ERROR;
     } else if ((*ip6_hdr)->ip_nh == IPPROTO_TCP || (*ip6_hdr)->ip_nh == IPPROTO_UDP) {
-        l4 = get_layer4_v6(*ip6_hdr, l3len);
+        l4 = get_layer4_v6(*ip6_hdr, (u_char*)ip6_hdr + l3len);
         if (l4)
             return rewrite_ports(tcpedit, (*ip6_hdr)->ip_nh, l4,
                     l3len - (l4 - (u_char*)*ip6_hdr));

+ 4 - 2
src/tcpedit/rewrite_sequence.c

@@ -70,7 +70,8 @@ rewrite_ipv4_tcp_sequence(tcpedit_t *tcpedit, ipv4_hdr_t **ip_hdr,
     assert(*ip_hdr && ip_hdr);
 
     if (*ip_hdr && (*ip_hdr)->ip_p == IPPROTO_TCP) {
-        tcp_hdr_t *tcp_hdr = (tcp_hdr_t *)get_layer4_v4(*ip_hdr, l3len);
+        tcp_hdr_t *tcp_hdr = (tcp_hdr_t *)get_layer4_v4(*ip_hdr,
+                                                        (u_char *)ip_hdr + l3len);
         if (!tcp_hdr) {
             tcpedit_setwarn(tcpedit, "caplen to small to set TCP sequence for IP packet: l3 len=%d",
                     l3len);
@@ -91,7 +92,8 @@ rewrite_ipv6_tcp_sequence(tcpedit_t *tcpedit, ipv6_hdr_t **ip6_hdr,
     assert(*ip6_hdr && ip6_hdr);
 
     if (*ip6_hdr && (*ip6_hdr)->ip_nh == IPPROTO_TCP) {
-        tcp_hdr_t *tcp_hdr = (tcp_hdr_t *)get_layer4_v6(*ip6_hdr, l3len);
+        tcp_hdr_t *tcp_hdr = (tcp_hdr_t *)get_layer4_v6(*ip6_hdr,
+                                                        (u_char*)ip6_hdr + l3len);
         if (!tcp_hdr) {
             tcpedit_setwarn(tcpedit, "caplen to small to set TCP sequence for IP packet: l3 len=%d",
                     l3len);

+ 2 - 2
src/tcpedit/tcpedit.c

@@ -174,7 +174,7 @@ again:
         if (ip_hdr == NULL)
             return TCPEDIT_SOFT_ERROR;
 
-        p = get_layer4_v4(ip_hdr, (*pkthdr)->caplen - l2len);
+        p = get_layer4_v4(ip_hdr, (u_char*)ip_hdr + (*pkthdr)->caplen - l2len);
         if (!p) {
             tcpedit_seterr(tcpedit, "Packet length %d is too short to contain a layer %d byte IP header for DLT 0x%04x",
                     pktlen, ip_hdr->ip_hl << 2,  dst_dlt);
@@ -195,7 +195,7 @@ again:
         if (ip6_hdr == NULL)
             return TCPEDIT_SOFT_ERROR;
 
-        p = get_layer4_v6(ip6_hdr, (*pkthdr)->caplen - l2len);
+        p = get_layer4_v6(ip6_hdr, (u_char*)ip6_hdr + (*pkthdr)->caplen - l2len);
         if (!p) {
             tcpedit_seterr(tcpedit, "Packet length %d is too short to contain an IPv6 header for DLT 0x%04x",
                     pktlen, dst_dlt);

+ 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 Feb 2022" "tcpliveplay" "User Commands"
+.TH tcpliveplay 1 "26 Aug 2022" "tcpliveplay" "User Commands"
 .\"
 .\" DO NOT EDIT THIS FILE (in-mem file)
 .\"

+ 1 - 1
src/tcpliveplay.c

@@ -746,7 +746,7 @@ got_packet(_U_ u_char *args, _U_ const struct pcap_pkthdr *header,
     if((flags == (TH_SYN|TH_ACK)) && (sched_index==1) && (tcphdr->th_ack==htonl(sched[sched_index-1].curr_lseq + 1))){
         unsigned int j;
         printf("Received Remote Packet...............	[%u]\n", sched_index + 1);
-        printf("Remote Pakcet Expectation met.\nProceeding in replay....\n");
+        printf("Remote Packet Expectation met.\nProceeding in replay....\n");
         //printf("SYN-ACKed Random SEQ set!\n");
         initial_rseq = ntohl(tcphdr->th_seq); 
         //printf("initial_rseq: %u\n", initial_rseq);

+ 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 Feb 2022" "tcpprep" "User Commands"
+.TH tcpprep 1 "26 Aug 2022" "tcpprep" "User Commands"
 .\"
 .\" DO NOT EDIT THIS FILE (in-mem file)
 .\"

+ 3 - 3
src/tcpprep.c

@@ -215,14 +215,14 @@ check_dst_port(ipv4_hdr_t *ip_hdr, ipv6_hdr_t *ip6_hdr, int len)
             return 0; /* not enough data in the packet to know */
 
         proto = ip_hdr->ip_p;
-        l4 = get_layer4_v4(ip_hdr, len);
+        l4 = get_layer4_v4(ip_hdr, (u_char*)ip_hdr + len);
     } else if (ip6_hdr) {
         if (len < (TCPR_IPV6_H + 4))
             return 0; /* not enough data in the packet to know */
 
-        proto = get_ipv6_l4proto(ip6_hdr, len);
+        proto = get_ipv6_l4proto(ip6_hdr, (u_char*)ip6_hdr + len);
         dbgx(3, "Our layer4 proto is 0x%hhu", proto);
-        if ((l4 = get_layer4_v6(ip6_hdr, len)) == NULL)
+        if ((l4 = get_layer4_v6(ip6_hdr, (u_char*)ip6_hdr + len)) == NULL)
             return 0;
 
         dbgx(3, "Found proto %u at offset %p.  base %p (%p)", proto, (void *)l4, (void *)ip6_hdr, (void*)(l4 - (u_char *)ip6_hdr));

+ 1 - 1
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 Feb 2022" "tcpreplay" "User Commands"
+.TH tcpreplay-edit 1 "26 Aug 2022" "tcpreplay" "User Commands"
 .\"
 .\" DO NOT EDIT THIS FILE (in-mem file)
 .\"

+ 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 Feb 2022" "tcpreplay" "User Commands"
+.TH tcpreplay 1 "26 Aug 2022" "tcpreplay" "User Commands"
 .\"
 .\" DO NOT EDIT THIS FILE (in-mem file)
 .\"

+ 0 - 4
src/tcpreplay.c

@@ -67,11 +67,7 @@ main(int argc, char *argv[])
     fflush(NULL);
 
     ctx = tcpreplay_init();
-#ifdef TCPREPLAY
     optct = optionProcess(&tcpreplayOptions, argc, argv);
-#elif defined TCPREPLAY_EDIT
-    optct = optionProcess(&tcpreplay_editOptions, argc, argv);
-#endif
     argc -= optct;
     argv += optct;
 

+ 10 - 0
src/tcpreplay_api.c

@@ -227,6 +227,16 @@ tcpreplay_post_args(tcpreplay_t *ctx, int argc)
         options->preload_pcap = true;
     }
 
+#ifdef TCPREPLAY_EDIT
+    if (HAVE_OPT(PRELOAD_PCAP) && OPT_VALUE_LOOP > 1) {
+        tcpreplay_seterr(ctx,
+                         "%s",
+                         "tcpreplay_edit --loop (-l) and --preload_pcap (-K) options are mutually exclusive");
+        ret = -1;
+        goto out;
+    }
+#endif
+
     /* Dual file mode */
     if (HAVE_OPT(DUALFILE)) {
         options->dualfile = true;

+ 1 - 1
src/tcprewrite.1

@@ -10,7 +10,7 @@
 .ds B-Font B
 .ds I-Font I
 .ds R-Font R
-.TH tcprewrite 1 "12 Feb 2022" "tcprewrite" "User Commands"
+.TH tcprewrite 1 "26 Aug 2022" "tcprewrite" "User Commands"
 .\"
 .\" DO NOT EDIT THIS FILE (in-mem file)
 .\"

BIN
test/test.rewrite_l7fuzzing


BIN
test/test2.rewrite_l7fuzzing