diff --git a/binaries/aarch64/tpws b/binaries/aarch64/tpws index 62bbf87..31f54f1 100755 Binary files a/binaries/aarch64/tpws and b/binaries/aarch64/tpws differ diff --git a/binaries/arm/tpws b/binaries/arm/tpws index c8bb041..846289f 100755 Binary files a/binaries/arm/tpws and b/binaries/arm/tpws differ diff --git a/binaries/freebsd-x64/tpws b/binaries/freebsd-x64/tpws index c7a6b69..e3ce621 100755 Binary files a/binaries/freebsd-x64/tpws and b/binaries/freebsd-x64/tpws differ diff --git a/binaries/mac64/tpws b/binaries/mac64/tpws index 311f62a..a22780c 100755 Binary files a/binaries/mac64/tpws and b/binaries/mac64/tpws differ diff --git a/binaries/mips32r1-lsb/tpws b/binaries/mips32r1-lsb/tpws index e61d2f9..46e59a4 100755 Binary files a/binaries/mips32r1-lsb/tpws and b/binaries/mips32r1-lsb/tpws differ diff --git a/binaries/mips32r1-msb/tpws b/binaries/mips32r1-msb/tpws index 66eb71d..085945e 100755 Binary files a/binaries/mips32r1-msb/tpws and b/binaries/mips32r1-msb/tpws differ diff --git a/binaries/mips64r2-msb/tpws b/binaries/mips64r2-msb/tpws index c753bd9..3b55be1 100755 Binary files a/binaries/mips64r2-msb/tpws and b/binaries/mips64r2-msb/tpws differ diff --git a/binaries/ppc/tpws b/binaries/ppc/tpws index 0e4acab..d2095ce 100755 Binary files a/binaries/ppc/tpws and b/binaries/ppc/tpws differ diff --git a/binaries/x86/tpws b/binaries/x86/tpws index d35d305..4d14b14 100755 Binary files a/binaries/x86/tpws and b/binaries/x86/tpws differ diff --git a/binaries/x86_64/tpws b/binaries/x86_64/tpws index 301b162..de8b872 100755 Binary files a/binaries/x86_64/tpws and b/binaries/x86_64/tpws differ diff --git a/binaries/x86_64/tpws_wsl.tgz b/binaries/x86_64/tpws_wsl.tgz index 0e4f3f8..e6575aa 100644 Binary files a/binaries/x86_64/tpws_wsl.tgz and b/binaries/x86_64/tpws_wsl.tgz differ diff --git a/docs/changes.txt b/docs/changes.txt index 58bb3a3..03418cf 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -262,3 +262,12 @@ tpws: out of band send when splitting (--oob) nfqws: autottl nfqws: datanoack fooling nftables: use POSTNAT path for tcp redirections to allow NAT-breaking strategies. use additional mark bit DESYNC_MARK_POSTNAT. + +v55 + +tpws: incompatible oob parameter change. it doesn't take oob byte anymore. instead it takes optional protocol filter - http or tls. + the same is done with disorder. oob byte can be specified in parameter --oob-data. +blockcheck: quick mode, strategy order optimizations, QUIC protocol support +nfqws: syndata desync mode + + \ No newline at end of file diff --git a/docs/readme.eng.md b/docs/readme.eng.md index f69cf33..5f93d35 100644 --- a/docs/readme.eng.md +++ b/docs/readme.eng.md @@ -576,8 +576,9 @@ tpws is transparent proxy. --split-http-req=method|host ; split http request at specified logical position. --split-pos= ; split at specified pos. split-http-req takes precedence over split-pos for http reqs. --split-any-protocol ; split not only http and https - --disorder ; when splitting simulate sending second fragment first - --oob[=|0xHEX] ; when splitting send out of band byte. default is HEX 0x00. + --disorder[=http|tls] ; when splitting simulate sending second fragment first + --oob[=http|tls] ; when splitting send out of band byte. default is HEX 0x00. + --oob-data=|0xHEX ; override default 0x00 OOB byte. --hostcase ; change Host: => host: --hostspell ; exact spelling of "Host" header. must be 4 chars. default is "host" --hostdot ; add "." after Host: name @@ -796,10 +797,6 @@ may start to break the website. This situation can only be controlled manually. Remove undesired domain from the autohostlist file, restart nfqws/tpws or send them SIGHUP. Use exclude hostlist to prevent further auto additions. -It's possible to use one auto hostlist with multiple processes. All processes check for file modification time. -If a process modified autohostlist, all others will reread it automatically. -All processes must run with the same uid. - If zapret scripts are used then autohostlist is `ipset/zapret-hosts-auto.txt` and exlude list is `ipset/zapret-hosts-user-exclude.txt`. autohostlist mode includes hostlist mode. You can use `ipset/zapret-hosts-user.txt`. diff --git a/docs/readme.txt b/docs/readme.txt index 9585622..55c407e 100644 --- a/docs/readme.txt +++ b/docs/readme.txt @@ -1,4 +1,4 @@ -zapret v.54 +zapret v.55 English ------- @@ -657,6 +657,9 @@ tpws - это transparent proxy. --split-http-req=method|host ; способ разделения http запросов на сегменты : около метода (GET,POST) или около заголовка Host --split-pos= ; делить все посылы на сегменты в указанной позиции. единственная опция, работающая на не-http. при указании split-http-req он имеет преимущество на http. --split-any-protocol ; применять split-pos к любым пакетам. по умолчанию - только к http и TLS ClientHello + --disorder[=http|tls] ; путем манипуляций с сокетом вынуждает отправлять первым второй сегмент разделенного запроса + --oob[=http|tls] ; отправить байт out-of-band data (OOB) в конце первой части сплита + --oob-data=|0xHEX ; переопределить байт OOB. по умолчанию 0x00. --disorder ; путем манипуляций с сокетом вынуждает отправлять первым второй сегмент разделенного запроса --oob[=|0xHEX] ; отправить байт out-of-band data (OOB) в конце первой части сплита --hostcase ; менять регистр заголовка "Host:". по умолчанию на "host:". diff --git a/tpws/params.h b/tpws/params.h index faa6f84..b8a6f31 100644 --- a/tpws/params.h +++ b/tpws/params.h @@ -50,7 +50,8 @@ struct params_s int tlsrec_pos; bool split_any_protocol; int split_pos; - bool disorder, oob; + bool disorder, disorder_http, disorder_tls; + bool oob, oob_http, oob_tls; uint8_t oob_byte; int ttl_default; diff --git a/tpws/tamper.c b/tpws/tamper.c index 982fe67..20e44ec 100644 --- a/tpws/tamper.c +++ b/tpws/tamper.c @@ -25,7 +25,7 @@ bool find_host(uint8_t **pHost,uint8_t *buf,size_t bs) static const char *http_methods[] = { "GET /","POST /","HEAD /","OPTIONS /","PUT /","DELETE /","CONNECT /","TRACE /",NULL }; // segment buffer has at least 5 extra bytes to extend data block -void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,size_t *size, size_t *split_pos) +void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,size_t *size, size_t *split_pos, uint8_t *split_flags) { uint8_t *p, *pp, *pHost = NULL; size_t method_len = 0, pos; @@ -37,6 +37,7 @@ void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,si DBGPRINT("tamper_out") *split_pos=0; + *split_flags=0; for (method = http_methods; *method; method++) { @@ -209,6 +210,8 @@ void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,si default: if (params.split_pos < *size) *split_pos = params.split_pos; } + if (params.disorder_http) *split_flags |= SPLIT_FLAG_DISORDER; + if (params.oob_http) *split_flags |= SPLIT_FLAG_OOB; } else { @@ -269,6 +272,9 @@ void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,si if (params.split_pos < *size) *split_pos = params.split_pos; + + if (params.disorder_tls) *split_flags |= SPLIT_FLAG_DISORDER; + if (params.oob_tls) *split_flags |= SPLIT_FLAG_OOB; } } else if (params.split_any_protocol && params.split_pos < *size) @@ -279,7 +285,8 @@ void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,si DBGPRINT("tamper_out put hostname : %s", Host) ctrack->hostname=strdup(Host); } - + if (params.disorder) *split_flags |= SPLIT_FLAG_DISORDER; + if (params.oob) *split_flags |= SPLIT_FLAG_OOB; } diff --git a/tpws/tamper.h b/tpws/tamper.h index f2b2fde..7f4172e 100644 --- a/tpws/tamper.h +++ b/tpws/tamper.h @@ -4,6 +4,9 @@ #include #include +#define SPLIT_FLAG_DISORDER 0x01 +#define SPLIT_FLAG_OOB 0x02 + typedef enum {UNKNOWN=0, HTTP, TLS} t_l7proto; typedef struct { @@ -14,7 +17,7 @@ typedef struct char *hostname; } t_ctrack; -void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,size_t *size, size_t *split_pos); +void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,size_t *size, size_t *split_pos, uint8_t *split_flags); void tamper_in(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,size_t *size); // connection reset by remote leg void rst_in(t_ctrack *ctrack); diff --git a/tpws/tpws.c b/tpws/tpws.c index 14c1ed0..d831b29 100644 --- a/tpws/tpws.c +++ b/tpws/tpws.c @@ -171,11 +171,12 @@ static void exithelp(void) " --split-pos=\t\t; split at specified pos. split-http-req takes precedence for http.\n" " --split-any-protocol\t\t\t; split not only http and https\n" #if defined(BSD) && !defined(__APPLE__) - " --disorder\t\t\t\t; when splitting simulate sending second fragment first (BSD sends entire message instead of first fragment, this is not good)\n" + " --disorder[=http|tls]\t\t\t; when splitting simulate sending second fragment first (BSD sends entire message instead of first fragment, this is not good)\n" #else - " --disorder\t\t\t\t; when splitting simulate sending second fragment first\n" + " --disorder[=http|tls]\t\t\t; when splitting simulate sending second fragment first\n" #endif - " --oob[=|0xHEX]\t\t\t; when splitting send out of band byte. default is HEX 0x00.\n" + " --oob[=http|tls]\t\t\t; when splitting send out of band byte. default is HEX 0x00.\n" + " --oob-data=|0xHEX\t\t; override default 0x00 OOB byte.\n" " --hostcase\t\t\t\t; change Host: => host:\n" " --hostspell\t\t\t\t; exact spelling of \"Host\" header. must be 4 chars. default is \"host\"\n" " --hostdot\t\t\t\t; add \".\" after Host: name\n" @@ -295,33 +296,34 @@ void parse_params(int argc, char *argv[]) { "split-http-req",required_argument,0,0 },// optidx=23 { "split-pos",required_argument,0,0 },// optidx=24 { "split-any-protocol",optional_argument,0,0},// optidx=25 - { "disorder",no_argument,0,0 },// optidx=26 + { "disorder",optional_argument,0,0 },// optidx=26 { "oob",optional_argument,0,0 },// optidx=27 - { "methodspace",no_argument,0,0 },// optidx=28 - { "methodeol",no_argument,0,0 },// optidx=29 - { "hosttab",no_argument,0,0 },// optidx=30 - { "unixeol",no_argument,0,0 },// optidx=31 - { "tlsrec",required_argument,0,0 },// optidx=32 - { "tlsrec-pos",required_argument,0,0 },// optidx=33 - { "hostlist",required_argument,0,0 },// optidx=34 - { "hostlist-exclude",required_argument,0,0 },// optidx=35 - { "hostlist-auto",required_argument,0,0}, // optidx=36 - { "hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=37 - { "hostlist-auto-fail-time",required_argument,0,0}, // optidx=38 - { "hostlist-auto-debug",required_argument,0,0}, // optidx=39 - { "pidfile",required_argument,0,0 },// optidx=40 - { "debug",optional_argument,0,0 },// optidx=41 - { "local-rcvbuf",required_argument,0,0 },// optidx=42 - { "local-sndbuf",required_argument,0,0 },// optidx=43 - { "remote-rcvbuf",required_argument,0,0 },// optidx=44 - { "remote-sndbuf",required_argument,0,0 },// optidx=45 - { "socks",no_argument,0,0 },// optidx=46 - { "no-resolve",no_argument,0,0 },// optidx=47 - { "skip-nodelay",no_argument,0,0 },// optidx=48 - { "tamper-start",required_argument,0,0 },// optidx=49 - { "tamper-cutoff",required_argument,0,0 },// optidx=50 + { "oob-data",required_argument,0,0 },// optidx=28 + { "methodspace",no_argument,0,0 },// optidx=29 + { "methodeol",no_argument,0,0 },// optidx=30 + { "hosttab",no_argument,0,0 },// optidx=31 + { "unixeol",no_argument,0,0 },// optidx=32 + { "tlsrec",required_argument,0,0 },// optidx=33 + { "tlsrec-pos",required_argument,0,0 },// optidx=34 + { "hostlist",required_argument,0,0 },// optidx=35 + { "hostlist-exclude",required_argument,0,0 },// optidx=36 + { "hostlist-auto",required_argument,0,0}, // optidx=37 + { "hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=38 + { "hostlist-auto-fail-time",required_argument,0,0}, // optidx=39 + { "hostlist-auto-debug",required_argument,0,0}, // optidx=40 + { "pidfile",required_argument,0,0 },// optidx=41 + { "debug",optional_argument,0,0 },// optidx=42 + { "local-rcvbuf",required_argument,0,0 },// optidx=43 + { "local-sndbuf",required_argument,0,0 },// optidx=44 + { "remote-rcvbuf",required_argument,0,0 },// optidx=45 + { "remote-sndbuf",required_argument,0,0 },// optidx=46 + { "socks",no_argument,0,0 },// optidx=47 + { "no-resolve",no_argument,0,0 },// optidx=48 + { "skip-nodelay",no_argument,0,0 },// optidx=49 + { "tamper-start",required_argument,0,0 },// optidx=50 + { "tamper-cutoff",required_argument,0,0 },// optidx=51 #if defined(BSD) && !defined(__OpenBSD__) && !defined(__APPLE__) - { "enable-pf",no_argument,0,0 },// optidx=51 + { "enable-pf",no_argument,0,0 },// optidx=52 #endif { "hostlist-auto-retrans-threshold",optional_argument,0,0}, // ignored. for nfqws command line compatibility { NULL,0,NULL,0 } @@ -507,41 +509,64 @@ void parse_params(int argc, char *argv[]) params.split_any_protocol = true; break; case 26: /* disorder */ - params.disorder = true; + if (optarg) + { + if (!strcmp(optarg,"http")) params.disorder_http=true; + else if (!strcmp(optarg,"tls")) params.disorder_tls=true; + else + { + fprintf(stderr, "Invalid argument for disorder\n"); + exit_clean(1); + } + } + else + params.disorder = true; save_default_ttl(); break; case 27: /* oob */ if (optarg) + { + if (!strcmp(optarg,"http")) params.oob_http=true; + else if (!strcmp(optarg,"tls")) params.oob_tls=true; + else + { + fprintf(stderr, "Invalid argument for oob\n"); + exit_clean(1); + } + } + else + params.oob = true; + break; + case 28: /* oob-data */ { size_t l = strlen(optarg); unsigned int bt; if (l==1) params.oob_byte = (uint8_t)*optarg; else if (l!=4 || sscanf(optarg,"0x%02X",&bt)!=1) { - fprintf(stderr, "Invalid argument for oob\n"); + fprintf(stderr, "Invalid argument for oob-data\n"); exit_clean(1); } else params.oob_byte = (uint8_t)bt; } - params.oob = true; break; - case 28: /* methodspace */ + case 29: /* methodspace */ params.methodspace = true; params.tamper = true; break; - case 29: /* methodeol */ + case 30: /* methodeol */ params.methodeol = true; params.tamper = true; break; - case 30: /* hosttab */ + case 31: /* hosttab */ params.hosttab = true; params.tamper = true; break; - case 31: /* unixeol */ + case 32: /* unixeol */ params.unixeol = true; params.tamper = true; break; - case 32: /* tlsrec */ + case 33: /* tlsrec */ if (!strcmp(optarg, "sni")) params.tlsrec = tlsrec_sni; else @@ -551,7 +576,7 @@ void parse_params(int argc, char *argv[]) } params.tamper = true; break; - case 33: /* tlsrec-pos */ + case 34: /* tlsrec-pos */ if ((params.tlsrec_pos = atoi(optarg))>0) params.tlsrec = tlsrec_pos; else @@ -561,7 +586,7 @@ void parse_params(int argc, char *argv[]) } params.tamper = true; break; - case 34: /* hostlist */ + case 35: /* hostlist */ if (!strlist_add(¶ms.hostlist_files, optarg)) { fprintf(stderr, "strlist_add failed\n"); @@ -569,7 +594,7 @@ void parse_params(int argc, char *argv[]) } params.tamper = true; break; - case 35: /* hostlist-exclude */ + case 36: /* hostlist-exclude */ if (!strlist_add(¶ms.hostlist_exclude_files, optarg)) { fprintf(stderr, "strlist_add failed\n"); @@ -577,7 +602,7 @@ void parse_params(int argc, char *argv[]) } params.tamper = true; break; - case 36: /* hostlist-auto */ + case 37: /* hostlist-auto */ if (*params.hostlist_auto_filename) { fprintf(stderr, "only one auto hostlist is supported\n"); @@ -609,7 +634,7 @@ void parse_params(int argc, char *argv[]) params.hostlist_auto_filename[sizeof(params.hostlist_auto_filename) - 1] = '\0'; params.tamper = true; // need to detect blocks and update autohostlist. cannot just slice. break; - case 37: /* hostlist-auto-fail-threshold */ + case 38: /* hostlist-auto-fail-threshold */ params.hostlist_auto_fail_threshold = (uint8_t)atoi(optarg); if (params.hostlist_auto_fail_threshold<1 || params.hostlist_auto_fail_threshold>20) { @@ -617,7 +642,7 @@ void parse_params(int argc, char *argv[]) exit_clean(1); } break; - case 38: /* hostlist-auto-fail-time */ + case 39: /* hostlist-auto-fail-time */ params.hostlist_auto_fail_time = (uint8_t)atoi(optarg); if (params.hostlist_auto_fail_time<1) { @@ -625,7 +650,7 @@ void parse_params(int argc, char *argv[]) exit_clean(1); } break; - case 39: /* hostlist-auto-debug */ + case 40: /* hostlist-auto-debug */ { FILE *F = fopen(optarg,"a+t"); if (!F) @@ -640,35 +665,35 @@ void parse_params(int argc, char *argv[]) params.hostlist_auto_debuglog[sizeof(params.hostlist_auto_debuglog) - 1] = '\0'; } break; - case 40: /* pidfile */ + case 41: /* pidfile */ strncpy(params.pidfile,optarg,sizeof(params.pidfile)); params.pidfile[sizeof(params.pidfile)-1]='\0'; break; - case 41: + case 42: params.debug = optarg ? atoi(optarg) : 1; break; - case 42: /* local-rcvbuf */ + case 43: /* local-rcvbuf */ params.local_rcvbuf = atoi(optarg)/2; break; - case 43: /* local-sndbuf */ + case 44: /* local-sndbuf */ params.local_sndbuf = atoi(optarg)/2; break; - case 44: /* remote-rcvbuf */ + case 45: /* remote-rcvbuf */ params.remote_rcvbuf = atoi(optarg)/2; break; - case 45: /* remote-sndbuf */ + case 46: /* remote-sndbuf */ params.remote_sndbuf = atoi(optarg)/2; break; - case 46: /* socks */ + case 47: /* socks */ params.proxy_type = CONN_TYPE_SOCKS; break; - case 47: /* no-resolve */ + case 48: /* no-resolve */ params.no_resolve = true; break; - case 48: /* skip-nodelay */ + case 49: /* skip-nodelay */ params.skip_nodelay = true; break; - case 49: /* tamper-start */ + case 50: /* tamper-start */ { const char *p=optarg; if (*p=='n') @@ -681,7 +706,7 @@ void parse_params(int argc, char *argv[]) params.tamper_start = atoi(p); } break; - case 50: /* tamper-cutoff */ + case 51: /* tamper-cutoff */ { const char *p=optarg; if (*p=='n') @@ -695,7 +720,7 @@ void parse_params(int argc, char *argv[]) } break; #if defined(BSD) && !defined(__OpenBSD__) && !defined(__APPLE__) - case 51: /* enable-pf */ + case 52: /* enable-pf */ params.pf_enable = true; break; #endif diff --git a/tpws/tpws_conn.c b/tpws/tpws_conn.c index 0d6f822..3c6fa45 100644 --- a/tpws/tpws_conn.c +++ b/tpws/tpws_conn.c @@ -101,6 +101,7 @@ ssize_t send_with_ttl(int fd, const void *buf, size_t len, int flags, int ttl) { DBGPRINT("send_with_ttl %d fd=%d",ttl,fd); if (!set_ttl_hl(fd, ttl)) + //fprintf(stderr,"could not set ttl %d to fd=%d\n",ttl,fd); fprintf(stderr,"could not set ttl %d to fd=%d\n",ttl,fd); } wr = send(fd, buf, len, flags); @@ -915,7 +916,7 @@ static bool in_tamper_out_range(tproxy_conn_t *conn) (!params.tamper_cutoff || (params.tamper_cutoff_n ? (conn->tnrd+1) : conn->trd) < params.tamper_cutoff); } -static void tamper(tproxy_conn_t *conn, uint8_t *segment, size_t segment_buffer_size, size_t *segment_size, size_t *split_pos) +static void tamper(tproxy_conn_t *conn, uint8_t *segment, size_t segment_buffer_size, size_t *segment_size, size_t *split_pos, uint8_t *split_flags) { *split_pos=0; if (params.tamper) @@ -935,7 +936,7 @@ static void tamper(tproxy_conn_t *conn, uint8_t *segment, size_t segment_buffer_ params.tamper_start_n ? "n" : "" , params.tamper_start, params.tamper_cutoff_n ? "n" : "" , params.tamper_cutoff, in_range ? "IN RANGE" : "OUT OF RANGE") - if (in_range) tamper_out(&conn->track,segment,segment_buffer_size,segment_size,split_pos); + if (in_range) tamper_out(&conn->track,segment,segment_buffer_size,segment_size,split_pos,split_flags); } } } @@ -1029,28 +1030,30 @@ static bool handle_epoll(tproxy_conn_t *conn, struct tailhead *conn_list, uint32 if (rd>0) { size_t split_pos; + uint8_t split_flags; bs = rd; // tamper needs to know stream position of the block start - tamper(conn, buf, sizeof(buf), &bs, &split_pos); + tamper(conn, buf, sizeof(buf), &bs, &split_pos, &split_flags); // increase after tamper conn->tnrd++; conn->trd+=rd; if (split_pos) { - VPRINT("Splitting at pos %zu", split_pos) - if (params.oob) + VPRINT("Splitting at pos %zu%s", split_pos, (split_flags & SPLIT_FLAG_DISORDER) ? " with disorder" : "") + if (split_flags && SPLIT_FLAG_OOB) { + VPRINT("Sending OOB byte %02X", params.oob_byte) uint8_t oob_save; oob_save = buf[split_pos]; buf[split_pos] = params.oob_byte; - wr = send_or_buffer(conn->partner->wr_buf, conn->partner->fd, buf, split_pos+1, MSG_OOB, params.disorder ? 1 : 0); + wr = send_or_buffer(conn->partner->wr_buf, conn->partner->fd, buf, split_pos+1, MSG_OOB, !!(split_flags & SPLIT_FLAG_DISORDER)); buf[split_pos] = oob_save; } else - wr = send_or_buffer(conn->partner->wr_buf, conn->partner->fd, buf, split_pos, 0, params.disorder ? 1 : 0); + wr = send_or_buffer(conn->partner->wr_buf, conn->partner->fd, buf, split_pos, 0, !!(split_flags & SPLIT_FLAG_DISORDER)); DBGPRINT("send_or_buffer(1) fd=%d wr=%zd err=%d",conn->partner->fd,wr,errno) if (wr >= 0) { @@ -1133,8 +1136,9 @@ static bool read_all_and_buffer(tproxy_conn_t *conn, int buffer_number) conn->partner->bFlowOut = true; size_t split_pos; + uint8_t split_flags; - tamper(conn, conn->partner->wr_buf[buffer_number].data, numbytes+5, &conn->partner->wr_buf[buffer_number].len, &split_pos); + tamper(conn, conn->partner->wr_buf[buffer_number].data, numbytes+5, &conn->partner->wr_buf[buffer_number].len, &split_pos, &split_flags); if (epoll_update_flow(conn->partner)) return true;