diff --git a/nfq/conntrack.h b/nfq/conntrack.h index 83a6ca58..f82a3fb5 100644 --- a/nfq/conntrack.h +++ b/nfq/conntrack.h @@ -83,13 +83,15 @@ typedef struct bool b_cutoff; // mark for deletion bool b_wssize_cutoff, b_desync_cutoff, b_dup_cutoff, b_orig_mod_cutoff; + uint16_t ip_id; + t_l7proto l7proto; bool l7proto_discovered; char *hostname; bool hostname_is_ip; bool hostname_discovered; bool hostname_ah_check; // should perform autohostlist checks - + t_reassemble reasm_orig; struct rawpacket_tailhead delayed; } t_ctrack; diff --git a/nfq/darkmagic.c b/nfq/darkmagic.c index 8d71bf20..1e85a7cb 100644 --- a/nfq/darkmagic.c +++ b/nfq/darkmagic.c @@ -420,7 +420,7 @@ bool prepare_udp_segment4( memcpy(payload,data,len); if (padding) - fill_pattern(payload+len,padlen,padding,padding_size); + fill_pattern(payload+len,padlen,padding,padding_size,0); else memset(payload+len,0,padlen); udp4_fix_checksum(udp,ip_payload_len,&ip->ip_src,&ip->ip_dst); @@ -509,7 +509,7 @@ bool prepare_udp_segment6( memcpy(payload,data,len); if (padding) - fill_pattern(payload+len,padlen,padding,padding_size); + fill_pattern(payload+len,padlen,padding,padding_size,0); else memset(payload+len,0,padlen); udp6_fix_checksum(udp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst); diff --git a/nfq/desync.c b/nfq/desync.c index 9be73626..00d6f835 100644 --- a/nfq/desync.c +++ b/nfq/desync.c @@ -12,9 +12,9 @@ #include "conntrack.h" const char *fake_http_request_default = "GET / HTTP/1.1\r\nHost: www.iana.org\r\n" - "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/109.0\r\n" - "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\r\n" - "Accept-Encoding: gzip, deflate, br\r\n\r\n"; +"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/109.0\r\n" +"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\r\n" +"Accept-Encoding: gzip, deflate, br\r\n\r\n"; // SNI - www.microsoft.com const uint8_t fake_tls_clienthello_default[680] = { @@ -83,29 +83,29 @@ const uint8_t fake_tls_clienthello_default[680] = { #define TCP_MAX_REASM 16384 #define UDP_MAX_REASM 16384 -static void TLSDebugHandshake(const uint8_t *tls,size_t sz) +static void TLSDebugHandshake(const uint8_t *tls, size_t sz) { if (!params.debug) return; - if (sz<6) return; + if (sz < 6) return; const uint8_t *ext; - size_t len,len2; + size_t len, len2; - uint16_t v_handshake=pntoh16(tls+4), v, v2; - DLOG("TLS handshake version : %s\n",TLSVersionStr(v_handshake)); + uint16_t v_handshake = pntoh16(tls + 4), v, v2; + DLOG("TLS handshake version : %s\n", TLSVersionStr(v_handshake)); - if (TLSFindExtInHandshake(tls,sz,43,&ext,&len,false)) + if (TLSFindExtInHandshake(tls, sz, 43, &ext, &len, false)) { if (len) { len2 = ext[0]; - if (len2=2) + if (len >= 2) { len2 = pntoh16(ext); - if (len2<=(len-2)) + if (len2 <= (len - 2)) { char s[32]; - for(ext+=2; len2 ;) + for (ext += 2; len2;) { v = *ext; ext++; len2--; - if (v<=len2) + if (v <= len2) { - v2 = vsa_family==AF_INET && !dp->filter_ipv4) || (dest->sa_family==AF_INET6 && !dp->filter_ipv6)) + if ((dest->sa_family == AF_INET && !dp->filter_ipv4) || (dest->sa_family == AF_INET6 && !dp->filter_ipv6)) // L3 filter does not match return false; - if ((l3proto==IPPROTO_TCP && !port_filters_in_range(&dp->pf_tcp,saport(dest))) || (l3proto==IPPROTO_UDP && !port_filters_in_range(&dp->pf_udp,saport(dest)))) + if ((l3proto == IPPROTO_TCP && !port_filters_in_range(&dp->pf_tcp, saport(dest))) || (l3proto == IPPROTO_UDP && !port_filters_in_range(&dp->pf_udp, saport(dest)))) // L4 filter does not match return false; if (dp->filter_l7 && !l7_proto_match(l7proto, dp->filter_l7)) // L7 filter does not match return false; #ifdef HAS_FILTER_SSID - if (!LIST_EMPTY(&dp->filter_ssid) && !strlist_search(&dp->filter_ssid,ssid)) + if (!LIST_EMPTY(&dp->filter_ssid) && !strlist_search(&dp->filter_ssid, ssid)) return false; #endif @@ -254,7 +254,7 @@ static bool dp_match( if (!dp->hostlist_auto && !hostname && !bHostlistsEmpty) // avoid cpu consuming ipset check. profile cannot win if regular hostlists are present without auto hostlist and hostname is unknown. return false; - if (!IpsetCheck(dp, dest->sa_family==AF_INET ? &((struct sockaddr_in*)dest)->sin_addr : NULL, dest->sa_family==AF_INET6 ? &((struct sockaddr_in6*)dest)->sin6_addr : NULL)) + if (!IpsetCheck(dp, dest->sa_family == AF_INET ? &((struct sockaddr_in*)dest)->sin_addr : NULL, dest->sa_family == AF_INET6 ? &((struct sockaddr_in6*)dest)->sin6_addr : NULL)) // target ip does not match return false; @@ -287,15 +287,15 @@ static struct desync_profile *dp_find( if (params.debug) { char ip_port[48]; - ntop46_port(dest, ip_port,sizeof(ip_port)); + ntop46_port(dest, ip_port, sizeof(ip_port)); DLOG("desync profile search for %s target=%s l7proto=%s ssid='%s' hostname='%s'\n", proto_name(l3proto), ip_port, l7proto_str(l7proto), ssid ? ssid : "", hostname ? hostname : ""); } if (bCheckDone) *bCheckDone = false; LIST_FOREACH(dpl, head, next) { - if (dp_match(&dpl->dp,l3proto,dest,hostname,bNoSubdom,l7proto,ssid,bCheckDone,bCheckResult,bExcluded)) + if (dp_match(&dpl->dp, l3proto, dest, hostname, bNoSubdom, l7proto, ssid, bCheckDone, bCheckResult, bExcluded)) { - DLOG("desync profile %d matches\n",dpl->dp.n); + DLOG("desync profile %d matches\n", dpl->dp.n); return &dpl->dp; } } @@ -304,10 +304,10 @@ static struct desync_profile *dp_find( } // auto creates internal socket and uses it for subsequent calls -static bool rawsend_rep(int repeats, const struct sockaddr* dst,uint32_t fwmark,const char *ifout,const void *data,size_t len) +static bool rawsend_rep(int repeats, const struct sockaddr* dst, uint32_t fwmark, const char *ifout, const void *data, size_t len) { - for (int i=0;ipcounter_orig; - case 'd': return ctrack->pdcounter_orig; - case 's': return ctrack->seq_last - ctrack->seq0; - default: return 0; + case 'n': return ctrack->pcounter_orig; + case 'd': return ctrack->pdcounter_orig; + case 's': return ctrack->seq_last - ctrack->seq0; + default: return 0; } } static bool cutoff_test(const t_ctrack *ctrack, uint64_t cutoff, char mode) { - return cutoff && cutoff_get_limit(ctrack, mode)>=cutoff; + return cutoff && cutoff_get_limit(ctrack, mode) >= cutoff; } static void maybe_cutoff(t_ctrack *ctrack, uint8_t proto) { if (ctrack && ctrack->dp) { - if (proto==IPPROTO_TCP) + if (proto == IPPROTO_TCP) ctrack->b_wssize_cutoff |= cutoff_test(ctrack, ctrack->dp->wssize_cutoff, ctrack->dp->wssize_cutoff_mode); ctrack->b_desync_cutoff |= cutoff_test(ctrack, ctrack->dp->desync_cutoff, ctrack->dp->desync_cutoff_mode); ctrack->b_dup_cutoff |= cutoff_test(ctrack, ctrack->dp->dup_cutoff, ctrack->dp->dup_cutoff_mode); @@ -345,10 +345,10 @@ static void maybe_cutoff(t_ctrack *ctrack, uint8_t proto) // do not drop udp entry because it will be recreated when next packet arrives if (proto==IPPROTO_TCP) ctrack->b_cutoff |= \ - (!ctrack->dp->wssize || ctrack->b_wssize_cutoff) && - (!ctrack->dp->desync_cutoff || ctrack->b_desync_cutoff) && - (!ctrack->hostname_ah_check || ctrack->req_retrans_counter==RETRANS_COUNTER_STOP) && - ReasmIsEmpty(&ctrack->reasm_orig); + (!ctrack->dp->wssize || ctrack->b_wssize_cutoff) && + (!ctrack->dp->desync_cutoff || ctrack->b_desync_cutoff) && + (!ctrack->hostname_ah_check || ctrack->req_retrans_counter==RETRANS_COUNTER_STOP) && + ReasmIsEmpty(&ctrack->reasm_orig); */ } } @@ -383,7 +383,7 @@ static void auto_hostlist_reset_fail_counter(struct desync_profile *dp, const ch if (hostname) { hostfail_pool *fail_counter; - + fail_counter = HostFailPoolFind(dp->hostlist_auto_fail_counters, hostname); if (fail_counter) { @@ -397,9 +397,9 @@ static void auto_hostlist_reset_fail_counter(struct desync_profile *dp, const ch // return true if retrans trigger fires static bool auto_hostlist_retrans(t_ctrack *ctrack, uint8_t l4proto, int threshold, const char *client_ip_port, t_l7proto l7proto) { - if (ctrack && ctrack->dp && ctrack->hostname_ah_check && ctrack->req_retrans_counter!=RETRANS_COUNTER_STOP) + if (ctrack && ctrack->dp && ctrack->hostname_ah_check && ctrack->req_retrans_counter != RETRANS_COUNTER_STOP) { - if (l4proto==IPPROTO_TCP) + if (l4proto == IPPROTO_TCP) { if (!ctrack->req_seq_finalized || ctrack->req_seq_abandoned) return false; @@ -414,18 +414,18 @@ static bool auto_hostlist_retrans(t_ctrack *ctrack, uint8_t l4proto, int thresho ctrack->req_retrans_counter++; if (ctrack->req_retrans_counter >= threshold) { - DLOG("req retrans threshold reached : %u/%u\n",ctrack->req_retrans_counter, threshold); + DLOG("req retrans threshold reached : %u/%u\n", ctrack->req_retrans_counter, threshold); ctrack_stop_retrans_counter(ctrack); return true; } - DLOG("req retrans counter : %u/%u\n",ctrack->req_retrans_counter, threshold); + DLOG("req retrans counter : %u/%u\n", ctrack->req_retrans_counter, threshold); } return false; } static void auto_hostlist_failed(struct desync_profile *dp, const char *hostname, bool bNoSubdom, const char *client_ip_port, t_l7proto l7proto) { hostfail_pool *fail_counter; - + fail_counter = HostFailPoolFind(dp->hostlist_auto_fail_counters, hostname); if (!fail_counter) { @@ -443,9 +443,9 @@ static void auto_hostlist_failed(struct desync_profile *dp, const char *hostname { DLOG("auto hostlist (profile %d) : fail threshold reached. about to add %s to auto hostlist\n", dp->n, hostname); HostFailPoolDel(&dp->hostlist_auto_fail_counters, fail_counter); - + DLOG("auto hostlist (profile %d) : rechecking %s to avoid duplicates\n", dp->n, hostname); - bool bExcluded=false; + bool bExcluded = false; if (!HostlistCheck(dp, hostname, bNoSubdom, &bExcluded, false) && !bExcluded) { DLOG("auto hostlist (profile %d) : adding %s to %s\n", dp->n, hostname, dp->hostlist_auto->filename); @@ -475,9 +475,9 @@ static void process_retrans_fail(t_ctrack *ctrack, uint8_t proto, const struct s { char client_ip_port[48]; if (*params.hostlist_auto_debuglog) - ntop46_port((struct sockaddr*)client,client_ip_port,sizeof(client_ip_port)); + ntop46_port((struct sockaddr*)client, client_ip_port, sizeof(client_ip_port)); else - *client_ip_port=0; + *client_ip_port = 0; if (ctrack && ctrack->dp && ctrack->hostname && auto_hostlist_retrans(ctrack, proto, ctrack->dp->hostlist_auto_retrans_threshold, client_ip_port, ctrack->l7proto)) { HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : client %s : proto %s : retrans threshold reached", ctrack->hostname, ctrack->dp->n, client_ip_port, l7proto_str(ctrack->l7proto)); @@ -499,34 +499,34 @@ static bool send_delayed(t_ctrack *ctrack) static bool reasm_start(t_ctrack *ctrack, t_reassemble *reasm, uint8_t proto, size_t sz, size_t szMax, const uint8_t *data_payload, size_t len_payload) { ReasmClear(reasm); - if (sz<=szMax) + if (sz <= szMax) { - uint32_t seq = (proto==IPPROTO_TCP) ? ctrack->seq_last : 0; - if (ReasmInit(reasm,sz,seq)) + uint32_t seq = (proto == IPPROTO_TCP) ? ctrack->seq_last : 0; + if (ReasmInit(reasm, sz, seq)) { - ReasmFeed(reasm,seq,data_payload,len_payload); - DLOG("starting reassemble. now we have %zu/%zu\n",reasm->size_present,reasm->size); + ReasmFeed(reasm, seq, data_payload, len_payload); + DLOG("starting reassemble. now we have %zu/%zu\n", reasm->size_present, reasm->size); return true; } else DLOG("reassemble init failed. out of memory\n"); } else - DLOG("unexpected large payload for reassemble: size=%zu\n",sz); + DLOG("unexpected large payload for reassemble: size=%zu\n", sz); return false; } static bool reasm_orig_start(t_ctrack *ctrack, uint8_t proto, size_t sz, size_t szMax, const uint8_t *data_payload, size_t len_payload) { - return reasm_start(ctrack,&ctrack->reasm_orig,proto,sz,szMax,data_payload,len_payload); + return reasm_start(ctrack, &ctrack->reasm_orig, proto, sz, szMax, data_payload, len_payload); } static bool reasm_feed(t_ctrack *ctrack, t_reassemble *reasm, uint8_t proto, const uint8_t *data_payload, size_t len_payload) { if (ctrack && !ReasmIsEmpty(reasm)) { - uint32_t seq = (proto==IPPROTO_TCP) ? ctrack->seq_last : (uint32_t)reasm->size_present; + uint32_t seq = (proto == IPPROTO_TCP) ? ctrack->seq_last : (uint32_t)reasm->size_present; if (ReasmFeed(reasm, seq, data_payload, len_payload)) { - DLOG("reassemble : feeding data payload size=%zu. now we have %zu/%zu\n", len_payload,reasm->size_present,reasm->size); + DLOG("reassemble : feeding data payload size=%zu. now we have %zu/%zu\n", len_payload, reasm->size_present, reasm->size); return true; } else @@ -548,7 +548,7 @@ static void reasm_orig_stop(t_ctrack *ctrack, const char *dlog_msg) { if (!ReasmIsEmpty(&ctrack->reasm_orig)) { - DLOG("%s",dlog_msg); + DLOG("%s", dlog_msg); ReasmClear(&ctrack->reasm_orig); } send_delayed(ctrack); @@ -570,7 +570,7 @@ static uint8_t ct_new_postnat_fix(const t_ctrack *ctrack, struct ip *ip, struct // if used in postnat chain, dropping initial packet will cause conntrack connection teardown // so we need to workaround this. // SYN and SYN,ACK checks are for conntrack-less mode - if (ctrack && ctrack->pcounter_orig==1 || tcp && (tcp_syn_segment(tcp) || tcp_synack_segment(tcp))) + if (ctrack && ctrack->pcounter_orig == 1 || tcp && (tcp_syn_segment(tcp) || tcp_synack_segment(tcp))) { DLOG("applying linux postnat conntrack workaround\n"); // make ip protocol invalid and low TTL @@ -602,10 +602,10 @@ static bool check_desync_interval(const struct desync_profile *dp, const t_ctrac { if (!cutoff_test(ctrack, dp->desync_start, dp->desync_start_mode)) { - DLOG("desync-start not reached (mode %c): %llu/%u . not desyncing\n", dp->desync_start_mode, (unsigned long long)cutoff_get_limit(ctrack,dp->desync_start_mode), dp->desync_start); + DLOG("desync-start not reached (mode %c): %llu/%u . not desyncing\n", dp->desync_start_mode, (unsigned long long)cutoff_get_limit(ctrack, dp->desync_start_mode), dp->desync_start); return false; } - DLOG("desync-start reached (mode %c): %llu/%u\n", dp->desync_start_mode, (unsigned long long)cutoff_get_limit(ctrack,dp->desync_start_mode), dp->desync_start); + DLOG("desync-start reached (mode %c): %llu/%u\n", dp->desync_start_mode, (unsigned long long)cutoff_get_limit(ctrack, dp->desync_start_mode), dp->desync_start); } else { @@ -619,10 +619,10 @@ static bool check_desync_interval(const struct desync_profile *dp, const t_ctrac { if (ctrack->b_desync_cutoff) { - DLOG("desync-cutoff reached (mode %c): %llu/%u . not desyncing\n", dp->desync_cutoff_mode, (unsigned long long)cutoff_get_limit(ctrack,dp->desync_cutoff_mode), dp->desync_cutoff); + DLOG("desync-cutoff reached (mode %c): %llu/%u . not desyncing\n", dp->desync_cutoff_mode, (unsigned long long)cutoff_get_limit(ctrack, dp->desync_cutoff_mode), dp->desync_cutoff); return false; } - DLOG("desync-cutoff not reached (mode %c): %llu/%u\n", dp->desync_cutoff_mode, (unsigned long long)cutoff_get_limit(ctrack,dp->desync_cutoff_mode), dp->desync_cutoff); + DLOG("desync-cutoff not reached (mode %c): %llu/%u\n", dp->desync_cutoff_mode, (unsigned long long)cutoff_get_limit(ctrack, dp->desync_cutoff_mode), dp->desync_cutoff); } else { @@ -653,10 +653,10 @@ static bool check_dup_interval(const struct desync_profile *dp, const t_ctrack * { if (!cutoff_test(ctrack, dp->dup_start, dp->dup_start_mode)) { - DLOG("dup-start not reached (mode %c): %llu/%u . not duping\n", dp->dup_start_mode, (unsigned long long)cutoff_get_limit(ctrack,dp->dup_start_mode), dp->dup_start); + DLOG("dup-start not reached (mode %c): %llu/%u . not duping\n", dp->dup_start_mode, (unsigned long long)cutoff_get_limit(ctrack, dp->dup_start_mode), dp->dup_start); return false; } - DLOG("dup-start reached (mode %c): %llu/%u\n", dp->dup_start_mode, (unsigned long long)cutoff_get_limit(ctrack,dp->dup_start_mode), dp->dup_start); + DLOG("dup-start reached (mode %c): %llu/%u\n", dp->dup_start_mode, (unsigned long long)cutoff_get_limit(ctrack, dp->dup_start_mode), dp->dup_start); } else { @@ -670,10 +670,10 @@ static bool check_dup_interval(const struct desync_profile *dp, const t_ctrack * { if (ctrack->b_dup_cutoff) { - DLOG("dup-cutoff reached (mode %c): %llu/%u . not duping\n", dp->dup_cutoff_mode, (unsigned long long)cutoff_get_limit(ctrack,dp->dup_cutoff_mode), dp->dup_cutoff); + DLOG("dup-cutoff reached (mode %c): %llu/%u . not duping\n", dp->dup_cutoff_mode, (unsigned long long)cutoff_get_limit(ctrack, dp->dup_cutoff_mode), dp->dup_cutoff); return false; } - DLOG("dup-cutoff not reached (mode %c): %llu/%u\n", dp->dup_cutoff_mode, (unsigned long long)cutoff_get_limit(ctrack,dp->dup_cutoff_mode), dp->dup_cutoff); + DLOG("dup-cutoff not reached (mode %c): %llu/%u\n", dp->dup_cutoff_mode, (unsigned long long)cutoff_get_limit(ctrack, dp->dup_cutoff_mode), dp->dup_cutoff); } else { @@ -694,10 +694,10 @@ static bool check_orig_mod_interval(const struct desync_profile *dp, const t_ctr { if (!cutoff_test(ctrack, dp->orig_mod_start, dp->orig_mod_start_mode)) { - DLOG("orig-mod-start not reached (mode %c): %llu/%u . not modding original\n", dp->orig_mod_start_mode, (unsigned long long)cutoff_get_limit(ctrack,dp->orig_mod_start_mode), dp->orig_mod_start); + DLOG("orig-mod-start not reached (mode %c): %llu/%u . not modding original\n", dp->orig_mod_start_mode, (unsigned long long)cutoff_get_limit(ctrack, dp->orig_mod_start_mode), dp->orig_mod_start); return false; } - DLOG("orig-mod-start reached (mode %c): %llu/%u\n", dp->orig_mod_start_mode, (unsigned long long)cutoff_get_limit(ctrack,dp->orig_mod_start_mode), dp->orig_mod_start); + DLOG("orig-mod-start reached (mode %c): %llu/%u\n", dp->orig_mod_start_mode, (unsigned long long)cutoff_get_limit(ctrack, dp->orig_mod_start_mode), dp->orig_mod_start); } else { @@ -711,10 +711,10 @@ static bool check_orig_mod_interval(const struct desync_profile *dp, const t_ctr { if (ctrack->b_orig_mod_cutoff) { - DLOG("orig-mod-cutoff reached (mode %c): %llu/%u . not modding original\n", dp->orig_mod_cutoff_mode, (unsigned long long)cutoff_get_limit(ctrack,dp->orig_mod_cutoff_mode), dp->orig_mod_cutoff); + DLOG("orig-mod-cutoff reached (mode %c): %llu/%u . not modding original\n", dp->orig_mod_cutoff_mode, (unsigned long long)cutoff_get_limit(ctrack, dp->orig_mod_cutoff_mode), dp->orig_mod_cutoff); return false; } - DLOG("orig-mod-cutoff not reached (mode %c): %llu/%u\n", dp->orig_mod_cutoff_mode, (unsigned long long)cutoff_get_limit(ctrack,dp->orig_mod_cutoff_mode), dp->orig_mod_cutoff); + DLOG("orig-mod-cutoff not reached (mode %c): %llu/%u\n", dp->orig_mod_cutoff_mode, (unsigned long long)cutoff_get_limit(ctrack, dp->orig_mod_cutoff_mode), dp->orig_mod_cutoff); } else { @@ -730,28 +730,28 @@ static bool replay_queue(struct rawpacket_tailhead *q); static size_t pos_normalize(size_t split_pos, size_t reasm_offset, size_t len_payload) { - return (split_pos>reasm_offset && (split_pos-reasm_offset) reasm_offset && (split_pos - reasm_offset) < len_payload) ? split_pos - reasm_offset : 0; } static uint8_t autottl_guess(autottl *attl, uint8_t hop_count, const char *attl_kind) { - if (AUTOTTL_ENABLED(*attl)) - { - uint8_t autottl = autottl_eval(hop_count, attl); - if (autottl) - DLOG("%s autottl: guessed %u\n",attl_kind,autottl); - else - DLOG("%s autottl: could not guess\n",attl_kind); - return autottl; - } + if (AUTOTTL_ENABLED(*attl)) + { + uint8_t autottl = autottl_eval(hop_count, attl); + if (autottl) + DLOG("%s autottl: guessed %u\n", attl_kind, autottl); else - return 0; + DLOG("%s autottl: could not guess\n", attl_kind); + return autottl; + } + else + return 0; } static void autottl_discover(t_ctrack *ctrack, const struct in_addr *a4, const struct in6_addr *a6, const char *iface) { if (ctrack && params.autottl_present && !ctrack->b_autottl_discovered) { - ip_cache_item *ipc = ipcacheTouch(¶ms.ipcache,a4,a6,iface); + ip_cache_item *ipc = ipcacheTouch(¶ms.ipcache, a4, a6, iface); if (!ipc) { DLOG_ERR("ipcache: out of memory\n"); @@ -762,7 +762,7 @@ static void autottl_discover(t_ctrack *ctrack, const struct in_addr *a4, const s uint8_t old_hops = ipc->hops; ipc->hops = hop_count_guess(ctrack->incoming_ttl); DLOG("incoming hops guessed %u\n", ipc->hops); - if (old_hops!=ipc->hops) + if (old_hops != ipc->hops) DLOG("updated autottl cache\n"); } else if (ipc->hops) @@ -783,7 +783,7 @@ static void autottl_rediscover(t_ctrack *ctrack, const struct in_addr *a4, const if (ctrack) { ctrack->b_autottl_discovered = false; - autottl_discover(ctrack,a4,a6,iface); + autottl_discover(ctrack, a4, a6, iface); } } @@ -791,13 +791,13 @@ static bool ipcache_put_hostname(const struct in_addr *a4, const struct in6_addr { if (!params.cache_hostname) return true; - ip_cache_item *ipc = ipcacheTouch(¶ms.ipcache,a4,a6,NULL); + ip_cache_item *ipc = ipcacheTouch(¶ms.ipcache, a4, a6, NULL); if (!ipc) { DLOG_ERR("ipcache_put_hostname: out of memory\n"); return false; } - if (!ipc->hostname || strcmp(ipc->hostname,hostname)) + if (!ipc->hostname || strcmp(ipc->hostname, hostname)) { free(ipc->hostname); if (!(ipc->hostname = strdup(hostname))) @@ -817,7 +817,7 @@ static bool ipcache_get_hostname(const struct in_addr *a4, const struct in6_addr *hostname = 0; return true; } - ip_cache_item *ipc = ipcacheTouch(¶ms.ipcache,a4,a6,NULL); + ip_cache_item *ipc = ipcacheTouch(¶ms.ipcache, a4, a6, NULL); if (!ipc) { DLOG_ERR("ipcache_get_hostname: out of memory\n"); @@ -826,7 +826,7 @@ static bool ipcache_get_hostname(const struct in_addr *a4, const struct in6_addr if (ipc->hostname) { DLOG("got cached hostname (is_ip=%u): %s\n", ipc->hostname_is_ip, ipc->hostname); - snprintf(hostname,hostname_buf_len,"%s",ipc->hostname); + snprintf(hostname, hostname_buf_len, "%s", ipc->hostname); if (hostname_is_ip) *hostname_is_ip = ipc->hostname_is_ip; } else @@ -839,12 +839,12 @@ static uint16_t IP4_IP_ID_FIX(const struct ip *ip) { return ip ? ip->ip_id ? ip->ip_id : (uint16_t)random() : 0; } -static uint16_t IP4_IP_ID_ADD(uint16_t ip_id,uint16_t inc) +static uint16_t IP4_IP_ID_ADD(uint16_t ip_id, uint16_t inc) { if (ip_id) { - ip_id+=net16_add(ip_id,inc); - if (!ip_id) ip_id=net16_add(ip_id,((int16_t)inc)<0 ? -1 : 1); // do not allow zero + ip_id += net16_add(ip_id, inc); + if (!ip_id) ip_id = net16_add(ip_id, ((int16_t)inc) < 0 ? -1 : 1); // do not allow zero } return ip_id; } @@ -859,51 +859,51 @@ static uint16_t IP4_IP_ID_ADD(uint16_t ip_id,uint16_t inc) // fake_mod buffer must at least sizeof(desync_profile->fake_tls) // size does not change // return : true - altered, false - not altered -static bool runtime_tls_mod(int fake_n,const struct fake_tls_mod_cache *modcache, const struct fake_tls_mod *tls_mod, const uint8_t *fake_data, size_t fake_data_size, const uint8_t *payload, size_t payload_len, uint8_t *fake_mod) +static bool runtime_tls_mod(int fake_n, const struct fake_tls_mod_cache *modcache, const struct fake_tls_mod *tls_mod, const uint8_t *fake_data, size_t fake_data_size, const uint8_t *payload, size_t payload_len, uint8_t *fake_mod) { - bool b=false; + bool b = false; if (modcache) // it's filled only if it's TLS { if (tls_mod->mod & FAKE_TLS_MOD_PADENCAP) { - size_t sz_rec = pntoh16(fake_data+3) + payload_len; - size_t sz_handshake = pntoh24(fake_data+6) + payload_len; - size_t sz_ext = pntoh16(fake_data+modcache->extlen_offset) + payload_len; - size_t sz_pad = pntoh16(fake_data+modcache->padlen_offset) + payload_len; + size_t sz_rec = pntoh16(fake_data + 3) + payload_len; + size_t sz_handshake = pntoh24(fake_data + 6) + payload_len; + size_t sz_ext = pntoh16(fake_data + modcache->extlen_offset) + payload_len; + size_t sz_pad = pntoh16(fake_data + modcache->padlen_offset) + payload_len; if ((sz_rec & ~0xFFFF) || (sz_handshake & ~0xFFFFFF) || (sz_ext & ~0xFFFF) || (sz_pad & ~0xFFFF)) DLOG("fake[%d] cannot apply padencap tls mod. length overflow.\n", fake_n); else { - memcpy(fake_mod,fake_data,fake_data_size); - phton16(fake_mod+3,(uint16_t)sz_rec); - phton24(fake_mod+6,(uint32_t)sz_handshake); - phton16(fake_mod+modcache->extlen_offset,(uint16_t)sz_ext); - phton16(fake_mod+modcache->padlen_offset,(uint16_t)sz_pad); - b=true; + memcpy(fake_mod, fake_data, fake_data_size); + phton16(fake_mod + 3, (uint16_t)sz_rec); + phton24(fake_mod + 6, (uint32_t)sz_handshake); + phton16(fake_mod + modcache->extlen_offset, (uint16_t)sz_ext); + phton16(fake_mod + modcache->padlen_offset, (uint16_t)sz_pad); + b = true; DLOG("fake[%d] applied padencap tls mod. sizes increased by %zu bytes.\n", fake_n, payload_len); } } if (tls_mod->mod & FAKE_TLS_MOD_RND) { - if (!b) memcpy(fake_mod,fake_data,fake_data_size); - fill_random_bytes(fake_mod+11,32); // random - fill_random_bytes(fake_mod+44,fake_mod[43]); // session id - b=true; + if (!b) memcpy(fake_mod, fake_data, fake_data_size); + fill_random_bytes(fake_mod + 11, 32); // random + fill_random_bytes(fake_mod + 44, fake_mod[43]); // session id + b = true; DLOG("fake[%d] applied rnd tls mod\n", fake_n); } if (tls_mod->mod & FAKE_TLS_MOD_DUP_SID) { - if (payload_len<44) - DLOG("fake[%d] cannot apply dupsid tls mod. data payload is too short.\n",fake_n); - else if (fake_data[43]!=payload[43]) - DLOG("fake[%d] cannot apply dupsid tls mod. fake and orig session id length mismatch : %u!=%u.\n",fake_n,fake_data[43],payload[43]); - else if (payload_len<(44+payload[43])) - DLOG("fake[%d] cannot apply dupsid tls mod. data payload is not valid.\n",fake_n); + if (payload_len < 44) + DLOG("fake[%d] cannot apply dupsid tls mod. data payload is too short.\n", fake_n); + else if (fake_data[43] != payload[43]) + DLOG("fake[%d] cannot apply dupsid tls mod. fake and orig session id length mismatch : %u!=%u.\n", fake_n, fake_data[43], payload[43]); + else if (payload_len < (44 + payload[43])) + DLOG("fake[%d] cannot apply dupsid tls mod. data payload is not valid.\n", fake_n); else { - if (!b) memcpy(fake_mod,fake_data,fake_data_size); - memcpy(fake_mod+44,payload+44,fake_mod[43]); // session id - b=true; + if (!b) memcpy(fake_mod, fake_data, fake_data_size); + memcpy(fake_mod + 44, payload + 44, fake_mod[43]); // session id + b = true; DLOG("fake[%d] applied dupsid tls mod\n", fake_n); } } @@ -913,16 +913,16 @@ static bool runtime_tls_mod(int fake_n,const struct fake_tls_mod_cache *modcache uint8_t orig_mod(const struct desync_profile *dp, const t_ctrack *ctrack, struct dissect *dis) { - uint8_t ttl,ttl_orig; + uint8_t ttl, ttl_orig; ttl = (ctrack && ctrack->orig_autottl) ? ctrack->orig_autottl : dis->ip6 ? dp->orig_mod_ttl6 : dp->orig_mod_ttl; - if (ttl && check_orig_mod_interval(dp,ctrack)) + if (ttl && check_orig_mod_interval(dp, ctrack)) { ttl_orig = dis->ip ? dis->ip->ip_ttl : dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim; - if (ttl_orig!=ttl) + if (ttl_orig != ttl) { - DLOG("rewrite original packet ttl %u => %u\n",ttl_orig,ttl); - rewrite_ttl(dis->ip,dis->ip6,ttl); + DLOG("rewrite original packet ttl %u => %u\n", ttl_orig, ttl); + rewrite_ttl(dis->ip, dis->ip6, ttl); return true; } } @@ -937,21 +937,21 @@ static bool orig_send_rewrite( // here we avoid heavy ops and preserve exact tcp options structure - if (ttl_fake==ttl_orig) + if (ttl_fake == ttl_orig) DLOG("sending %u dups\n", dp->dup_repeats); else DLOG("sending %u dups with ttl rewrite %u => %u\n", dp->dup_repeats, ttl_orig, ttl_fake); - rewrite_ttl(dis->ip,dis->ip6,ttl_fake); + rewrite_ttl(dis->ip, dis->ip6, ttl_fake); // send dups - for (k=0;kdup_repeats;k++) + for (k = 0; k < dp->dup_repeats; k++) { - if (!rawsend(dst, fwmark, ifout , dis->data_pkt, dis->len_pkt)) + if (!rawsend(dst, fwmark, ifout, dis->data_pkt, dis->len_pkt)) { - rewrite_ttl(dis->ip,dis->ip6,ttl_orig); + rewrite_ttl(dis->ip, dis->ip6, ttl_orig); return false; } } - rewrite_ttl(dis->ip,dis->ip6,ttl_orig); + rewrite_ttl(dis->ip, dis->ip6, ttl_orig); return true; } @@ -961,39 +961,39 @@ static bool tcp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, c if (dp->dup_repeats || bForceSend) { unsigned int k; - uint8_t pkt[DPI_DESYNC_MAX_FAKE_LEN+100]; + uint8_t pkt[DPI_DESYNC_MAX_FAKE_LEN + 100]; size_t len; uint16_t ip_id, nmss; struct sockaddr_storage src, dst; - uint8_t ttl_orig,ttl_fake,flags_orig,scale_factor; + uint8_t ttl_orig, ttl_fake, flags_orig, scale_factor; uint32_t *timestamps; - bool sack,DF; + bool sack, DF; extract_endpoints(dis->ip, dis->ip6, dis->tcp, NULL, &src, &dst); ttl_orig = dis->ip ? dis->ip->ip_ttl : dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim; verdict_tcp_csum_fix(verdict, dis->tcp, dis->transport_len, dis->ip, dis->ip6); - if (dp->dup_repeats && check_dup_interval(dp,ctrack)) + if (dp->dup_repeats && check_dup_interval(dp, ctrack)) { ttl_fake = (ctrack && ctrack->dup_autottl) ? ctrack->dup_autottl : (dis->ip6 ? (dp->dup_ttl6 ? dp->dup_ttl6 : ttl_orig) : (dp->dup_ttl ? dp->dup_ttl : ttl_orig)); if (dp->dup_fooling_mode) { - flags_orig = *((uint8_t*)dis->tcp+13); + flags_orig = *((uint8_t*)dis->tcp + 13); scale_factor = tcp_find_scale_factor(dis->tcp); timestamps = tcp_find_timestamps(dis->tcp); sack = tcp_has_sack(dis->tcp); nmss = tcp_find_mss(dis->tcp); - ip_id = IP4_IP_ID_FIX(dis->ip); + ip_id = IP4_IP_ID_FIX(dis->ip); len = sizeof(pkt); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, - flags_orig, sack, nmss, - dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, - ip_has_df(dis->ip),ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), - dp->dup_fooling_mode,dp->dup_ts_increment,dp->dup_badseq_increment,dp->dup_badseq_ack_increment, - dis->data_payload, dis->len_payload, pkt, &len)) + flags_orig, sack, nmss, + dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, + ip_has_df(dis->ip), ttl_fake, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), + dp->dup_fooling_mode, dp->dup_ts_increment, dp->dup_badseq_increment, dp->dup_badseq_ack_increment, + dis->data_payload, dis->len_payload, pkt, &len)) { DLOG_ERR("dup: packet reconstruct failed\n"); return false; @@ -1001,15 +1001,15 @@ static bool tcp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, c DLOG("sending %u dups with packet reconstruct. ttl %u => %u\n", dp->dup_repeats, ttl_orig, ttl_fake); // send dups - for (k=0;kdup_repeats;k++) + for (k = 0; k < dp->dup_repeats; k++) { - if (!rawsend((struct sockaddr *)&dst, fwmark, ifout , pkt, len)) + if (!rawsend((struct sockaddr *)&dst, fwmark, ifout, pkt, len)) return false; } } else { - if (!orig_send_rewrite(fwmark,ifout,(struct sockaddr *)&dst,ttl_orig,ttl_fake,dp,dis)) + if (!orig_send_rewrite(fwmark, ifout, (struct sockaddr *)&dst, ttl_orig, ttl_fake, dp, dis)) return false; } if (dp->dup_replace) @@ -1017,7 +1017,7 @@ static bool tcp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, c else { DLOG("sending original ttl %u\n", ttl_orig); - if (!rawsend((struct sockaddr *)&dst, fwmark, ifout , dis->data_pkt, dis->len_pkt)) + if (!rawsend((struct sockaddr *)&dst, fwmark, ifout, dis->data_pkt, dis->len_pkt)) return false; } return true; @@ -1025,7 +1025,7 @@ static bool tcp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, c if (bForceSend) { DLOG("sending original ttl %u\n", ttl_orig); - if (!rawsend((struct sockaddr *)&dst, fwmark, ifout , dis->data_pkt, dis->len_pkt)) + if (!rawsend((struct sockaddr *)&dst, fwmark, ifout, dis->data_pkt, dis->len_pkt)) return false; return true; } @@ -1038,28 +1038,28 @@ static bool udp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, c if (dp->dup_repeats || bForceSend) { unsigned int k; - uint8_t pkt[DPI_DESYNC_MAX_FAKE_LEN+100]; + uint8_t pkt[DPI_DESYNC_MAX_FAKE_LEN + 100]; size_t len; uint16_t ip_id; struct sockaddr_storage src, dst; - uint8_t ttl_orig,ttl_fake; + uint8_t ttl_orig, ttl_fake; extract_endpoints(dis->ip, dis->ip6, NULL, dis->udp, &src, &dst); ttl_orig = dis->ip ? dis->ip->ip_ttl : dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim; verdict_udp_csum_fix(verdict, dis->udp, dis->transport_len, dis->ip, dis->ip6); - if (dp->dup_repeats && check_dup_interval(dp,ctrack)) + if (dp->dup_repeats && check_dup_interval(dp, ctrack)) { ttl_fake = (ctrack && ctrack->dup_autottl) ? ctrack->dup_autottl : (dis->ip6 ? (dp->dup_ttl6 ? dp->dup_ttl6 : ttl_orig) : (dp->dup_ttl ? dp->dup_ttl : ttl_orig)); if (dp->dup_fooling_mode) { - ip_id = IP4_IP_ID_FIX(dis->ip); + ip_id = IP4_IP_ID_FIX(dis->ip); len = sizeof(pkt); if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, - ip_has_df(dis->ip),ttl_fake, IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), + ip_has_df(dis->ip), ttl_fake, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), dp->dup_fooling_mode, NULL, 0, 0, dis->data_payload, dis->len_payload, pkt, &len)) { @@ -1070,15 +1070,15 @@ static bool udp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, c DLOG("sending %u dups with packet reconstruct. ttl %u => %u\n", dp->dup_repeats, ttl_orig, ttl_fake); // send dups - for (k=0;kdup_repeats;k++) + for (k = 0; k < dp->dup_repeats; k++) { - if (!rawsend((struct sockaddr *)&dst, fwmark, ifout , pkt, len)) + if (!rawsend((struct sockaddr *)&dst, fwmark, ifout, pkt, len)) return false; } } else { - if (!orig_send_rewrite(fwmark,ifout,(struct sockaddr *)&dst,ttl_orig,ttl_fake,dp,dis)) + if (!orig_send_rewrite(fwmark, ifout, (struct sockaddr *)&dst, ttl_orig, ttl_fake, dp, dis)) return false; } if (dp->dup_replace) @@ -1086,7 +1086,7 @@ static bool udp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, c else { DLOG("sending original ttl %u\n", ttl_orig); - if (!rawsend((struct sockaddr *)&dst, fwmark, ifout , dis->data_pkt, dis->len_pkt)) + if (!rawsend((struct sockaddr *)&dst, fwmark, ifout, dis->data_pkt, dis->len_pkt)) return false; } return true; @@ -1094,7 +1094,7 @@ static bool udp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, c if (bForceSend) { DLOG("sending original ttl %u\n", ttl_orig); - if (!rawsend((struct sockaddr *)&dst, fwmark, ifout , dis->data_pkt, dis->len_pkt)) + if (!rawsend((struct sockaddr *)&dst, fwmark, ifout, dis->data_pkt, dis->len_pkt)) return false; return true; } @@ -1104,23 +1104,23 @@ static bool udp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, c static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint32_t fwmark, const char *ifin, const char *ifout, struct dissect *dis) { - uint8_t verdict=VERDICT_PASS; + uint8_t verdict = VERDICT_PASS; // additional safety check if (!!dis->ip == !!dis->ip6) return verdict; struct desync_profile *dp = NULL; - t_ctrack *ctrack=NULL, *ctrack_replay=NULL; - bool bReverse=false; - bool bFake=false; + t_ctrack *ctrack = NULL, *ctrack_replay = NULL; + bool bReverse = false; + bool bFake = false; struct sockaddr_storage src, dst; - uint8_t pkt1[DPI_DESYNC_MAX_FAKE_LEN+100], pkt2[DPI_DESYNC_MAX_FAKE_LEN+100], pkt3[DPI_DESYNC_MAX_FAKE_LEN+100]; + uint8_t pkt1[DPI_DESYNC_MAX_FAKE_LEN + 100], pkt2[DPI_DESYNC_MAX_FAKE_LEN + 100], pkt3[DPI_DESYNC_MAX_FAKE_LEN + 100]; size_t pkt1_len, pkt2_len, pkt3_len; - uint8_t ttl_orig,ttl_fake,flags_orig,scale_factor; + uint8_t ttl_orig, ttl_fake, flags_orig, scale_factor; uint32_t *timestamps; - bool bSack,DF; + bool bSack, DF; uint16_t nmss; char host[256]; const char *ifname = NULL, *ssid = NULL; @@ -1142,16 +1142,16 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint ifname = bReverse ? ifin : ifout; #ifdef HAS_FILTER_SSID ssid = wlan_ssid_search_ifname(ifname); - if (ssid) DLOG("found ssid for %s : %s\n",ifname,ssid); + if (ssid) DLOG("found ssid for %s : %s\n", ifname, ssid); #endif dp = ctrack_replay->dp; if (dp) - DLOG("using cached desync profile %d\n",dp->n); + DLOG("using cached desync profile %d\n", dp->n); else if (!ctrack_replay->dp_search_complete) { if (!ctrack_replay->hostname && !bReverse) { - if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL,dis->ip6 ? &dis->ip6->ip6_dst : NULL , host, sizeof(host), &ctrack_replay->hostname_is_ip) && *host) + if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL, host, sizeof(host), &ctrack_replay->hostname_is_ip) && *host) if (!(ctrack_replay->hostname = strdup(host))) DLOG_ERR("strdup(host): out of memory\n"); } @@ -1180,10 +1180,10 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint ifname = bReverse ? ifin : ifout; #ifdef HAS_FILTER_SSID ssid = wlan_ssid_search_ifname(ifname); - if (ssid) DLOG("found ssid for %s : %s\n",ifname,ssid); + if (ssid) DLOG("found ssid for %s : %s\n", ifname, ssid); #endif if (dp) - DLOG("using cached desync profile %d\n",dp->n); + DLOG("using cached desync profile %d\n", dp->n); else if (!ctrack || !ctrack->dp_search_complete) { const char *hostname = NULL; @@ -1194,7 +1194,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint hostname_is_ip = ctrack->hostname_is_ip; if (!hostname && !bReverse) { - if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL,dis->ip6 ? &dis->ip6->ip6_dst : NULL , host, sizeof(host), &hostname_is_ip) && *host) + if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL, host, sizeof(host), &hostname_is_ip) && *host) if (!(hostname = ctrack_replay->hostname = strdup(host))) DLOG_ERR("strdup(host): out of memory\n"); } @@ -1222,13 +1222,13 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint if (dp->wsize) { tcp_rewrite_winsize(dis->tcp, dp->wsize, dp->wscale); - verdict=VERDICT_MODIFY; + verdict = VERDICT_MODIFY; } - if (dp->synack_split==SS_SYN) + if (dp->synack_split == SS_SYN) { DLOG("split SYNACK : clearing ACK bit\n"); dis->tcp->th_flags &= ~TH_ACK; - verdict=VERDICT_MODIFY; + verdict = VERDICT_MODIFY; } } @@ -1237,22 +1237,22 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint if (ctrack && !ctrack->incoming_ttl) { ctrack->incoming_ttl = ttl_orig; - DLOG("incoming TTL %u\n",ttl_orig); - autottl_rediscover(ctrack,dis->ip ? &dis->ip->ip_src : NULL,dis->ip6 ? &dis->ip6->ip6_src : NULL , ifin); + DLOG("incoming TTL %u\n", ttl_orig); + autottl_rediscover(ctrack, dis->ip ? &dis->ip->ip_src : NULL, dis->ip6 ? &dis->ip6->ip6_src : NULL, ifin); } // process reply packets for auto hostlist mode // by looking at RSTs or HTTP replies we decide whether original request looks like DPI blocked // we only process first-sequence replies. do not react to subsequent redirects or RSTs - if (ctrack && ctrack->hostname && ctrack->hostname_ah_check && (ctrack->ack_last-ctrack->ack0)==1) + if (ctrack && ctrack->hostname && ctrack->hostname_ah_check && (ctrack->ack_last - ctrack->ack0) == 1) { - bool bFail=false; + bool bFail = false; char client_ip_port[48]; if (*params.hostlist_auto_debuglog) - ntop46_port((struct sockaddr*)&dst,client_ip_port,sizeof(client_ip_port)); + ntop46_port((struct sockaddr*)&dst, client_ip_port, sizeof(client_ip_port)); else - *client_ip_port=0; + *client_ip_port = 0; if (dis->tcp->th_flags & TH_RST) { @@ -1260,9 +1260,9 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : client %s : proto %s : incoming RST", ctrack->hostname, ctrack->dp->n, client_ip_port, l7proto_str(ctrack->l7proto)); bFail = true; } - else if (dis->len_payload && ctrack->l7proto==HTTP) + else if (dis->len_payload && ctrack->l7proto == HTTP) { - if (IsHttpReply(dis->data_payload,dis->len_payload)) + if (IsHttpReply(dis->data_payload, dis->len_payload)) { DLOG("incoming HTTP reply detected for hostname %s\n", ctrack->hostname); bFail = HttpReplyLooksLikeDPIRedirect(dis->data_payload, dis->len_payload, ctrack->hostname); @@ -1288,28 +1288,28 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint if (dis->tcp->th_flags & TH_RST) ConntrackClearHostname(ctrack); // do not react to further dup RSTs } - + return verdict; // nothing to do. do not waste cpu } - autottl_discover(ctrack,dis->ip ? &dis->ip->ip_dst : NULL,dis->ip6 ? &dis->ip6->ip6_dst : NULL , ifout); + autottl_discover(ctrack, dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL, ifout); - if (orig_mod(dp,ctrack,dis)) // ttl can change ! + if (orig_mod(dp, ctrack, dis)) // ttl can change ! verdict = VERDICT_MODIFY; - + if (dp->wssize) { if (ctrack) { if (ctrack->b_wssize_cutoff) { - DLOG("wssize-cutoff reached (mode %c): %llu/%u . not changing wssize.\n", dp->wssize_cutoff_mode, (unsigned long long)cutoff_get_limit(ctrack,dp->wssize_cutoff_mode), dp->wssize_cutoff); + DLOG("wssize-cutoff reached (mode %c): %llu/%u . not changing wssize.\n", dp->wssize_cutoff_mode, (unsigned long long)cutoff_get_limit(ctrack, dp->wssize_cutoff_mode), dp->wssize_cutoff); } else { - if (dp->wssize_cutoff) DLOG("wssize-cutoff not reached (mode %c): %llu/%u\n", dp->wssize_cutoff_mode, (unsigned long long)cutoff_get_limit(ctrack,dp->wssize_cutoff_mode), dp->wssize_cutoff); + if (dp->wssize_cutoff) DLOG("wssize-cutoff not reached (mode %c): %llu/%u\n", dp->wssize_cutoff_mode, (unsigned long long)cutoff_get_limit(ctrack, dp->wssize_cutoff_mode), dp->wssize_cutoff); tcp_rewrite_winsize(dis->tcp, dp->wssize, dp->wsscale); - verdict=VERDICT_MODIFY; + verdict = VERDICT_MODIFY; } } else @@ -1318,15 +1318,15 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint } } - if ((dp->synack_split==SS_SYNACK || dp->synack_split==SS_ACKSYN) && tcp_synack_segment(dis->tcp)) + if ((dp->synack_split == SS_SYNACK || dp->synack_split == SS_ACKSYN) && tcp_synack_segment(dis->tcp)) { // reconstruct required dis->tcp->th_flags &= ~TH_ACK; - tcp_fix_checksum(dis->tcp,dis->transport_len, dis->ip, dis->ip6); + tcp_fix_checksum(dis->tcp, dis->transport_len, dis->ip, dis->ip6); - char ss[2],i; - if (dp->synack_split==SS_SYNACK) + char ss[2], i; + if (dp->synack_split == SS_SYNACK) { ss[0] = 'S'; ss[1] = 'A'; @@ -1338,26 +1338,26 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint } pkt1_len = sizeof(pkt1); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_ACK, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, SCALE_NONE, timestamps, - DF,ttl_orig,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6), - FOOL_NONE,0,0,0,NULL, 0, pkt1, &pkt1_len)) + DF, ttl_orig, IP4_TOS(dis->ip), IP4_IP_ID_FIX(dis->ip), IP6_FLOW(dis->ip6), + FOOL_NONE, 0, 0, 0, NULL, 0, pkt1, &pkt1_len)) { DLOG_ERR("cannot prepare split SYNACK ACK part\n"); goto send_orig; } - for (int i=0;i<2;i++) + for (int i = 0; i < 2; i++) { - switch(ss[i]) + switch (ss[i]) { - case 'S': - DLOG("split SYNACK : SYN\n"); - if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , dis->data_pkt, dis->len_pkt)) - goto send_orig; - break; - case 'A': - DLOG("split SYNACK : ACK\n"); - if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) - goto send_orig; - break; + case 'S': + DLOG("split SYNACK : SYN\n"); + if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, dis->data_pkt, dis->len_pkt)) + goto send_orig; + break; + case 'A': + DLOG("split SYNACK : ACK\n"); + if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) + goto send_orig; + break; } } return VERDICT_DROP; @@ -1369,7 +1369,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint ttl_orig = dis->ip ? dis->ip->ip_ttl : dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim; ttl_fake = (ctrack_replay && ctrack_replay->desync_autottl) ? ctrack_replay->desync_autottl : (dis->ip6 ? (dp->desync_ttl6 ? dp->desync_ttl6 : ttl_orig) : (dp->desync_ttl ? dp->desync_ttl : ttl_orig)); - flags_orig = *((uint8_t*)dis->tcp+13); + flags_orig = *((uint8_t*)dis->tcp + 13); scale_factor = tcp_find_scale_factor(dis->tcp); bSack = tcp_has_sack(dis->tcp); nmss = tcp_find_mss(dis->tcp); @@ -1380,46 +1380,46 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint { switch (dp->desync_mode0) { - case DESYNC_SYNACK: - pkt1_len = sizeof(pkt1); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_SYN|TH_ACK, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, - DF,ttl_fake,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6), - dp->desync_fooling_mode,dp->desync_ts_increment,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, - NULL, 0, pkt1, &pkt1_len)) - { - goto send_orig; - } - DLOG("sending fake SYNACK\n"); - if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) - goto send_orig; + case DESYNC_SYNACK: + pkt1_len = sizeof(pkt1); + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_SYN | TH_ACK, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, + DF, ttl_fake, IP4_TOS(dis->ip), IP4_IP_ID_FIX(dis->ip), IP6_FLOW(dis->ip6), + dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment, + NULL, 0, pkt1, &pkt1_len)) + { + goto send_orig; + } + DLOG("sending fake SYNACK\n"); + if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) + goto send_orig; + break; + case DESYNC_SYNDATA: + // make sure we are not breaking TCP fast open + if (tcp_has_fastopen(dis->tcp)) + { + DLOG("received SYN with TCP fast open option. syndata desync is not applied.\n"); break; - case DESYNC_SYNDATA: - // make sure we are not breaking TCP fast open - if (tcp_has_fastopen(dis->tcp)) - { - DLOG("received SYN with TCP fast open option. syndata desync is not applied.\n"); - break; - } - if (dis->len_payload) - { - DLOG("received SYN with data payload. syndata desync is not applied.\n"); - break; - } - pkt1_len = sizeof(pkt1); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, bSack, nmss, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, - DF,ttl_orig,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6), - 0,0,0,0, dp->fake_syndata,dp->fake_syndata_size, pkt1,&pkt1_len)) - { - goto send_orig; - } - DLOG("sending SYN with fake data : "); - hexdump_limited_dlog(dp->fake_syndata,dp->fake_syndata_size,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) - goto send_orig; - verdict = VERDICT_DROP; - break; - default: + } + if (dis->len_payload) + { + DLOG("received SYN with data payload. syndata desync is not applied.\n"); break; + } + pkt1_len = sizeof(pkt1); + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, bSack, nmss, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, + DF, ttl_orig, IP4_TOS(dis->ip), IP4_IP_ID_FIX(dis->ip), IP6_FLOW(dis->ip6), + 0, 0, 0, 0, dp->fake_syndata, dp->fake_syndata_size, pkt1, &pkt1_len)) + { + goto send_orig; + } + DLOG("sending SYN with fake data : "); + hexdump_limited_dlog(dp->fake_syndata, dp->fake_syndata_size, PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) + goto send_orig; + verdict = VERDICT_DROP; + break; + default: + break; } // can do nothing else with SYN packet goto send_orig; @@ -1431,7 +1431,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint { struct blob_collection_head *fake; - uint8_t *p, *phost=NULL; + uint8_t *p, *phost = NULL; const uint8_t *rdata_payload = dis->data_payload; size_t rlen_payload = dis->len_payload; size_t split_pos, seqovl_pos; @@ -1440,7 +1440,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint int i; uint16_t ip_id = IP4_IP_ID_FIX(dis->ip); - bool bHaveHost=false, bHostIsIp=false; + bool bHaveHost = false, bHostIsIp = false; t_l7proto l7proto = UNKNOWN; if (replay) @@ -1448,7 +1448,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint rdata_payload = ctrack_replay->reasm_orig.packet; rlen_payload = ctrack_replay->reasm_orig.size_present; } - else if (reasm_orig_feed(ctrack,IPPROTO_TCP,dis->data_payload,dis->len_payload)) + else if (reasm_orig_feed(ctrack, IPPROTO_TCP, dis->data_payload, dis->len_payload)) { rdata_payload = ctrack->reasm_orig.packet; rlen_payload = ctrack->reasm_orig.size_present; @@ -1456,17 +1456,17 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint process_retrans_fail(ctrack, IPPROTO_TCP, (struct sockaddr*)&src); - if (IsHttp(rdata_payload,rlen_payload)) + if (IsHttp(rdata_payload, rlen_payload)) { DLOG("packet contains HTTP request\n"); l7proto = HTTP; - if (ctrack && ctrack->l7proto==UNKNOWN) ctrack->l7proto = l7proto; + if (ctrack && ctrack->l7proto == UNKNOWN) ctrack->l7proto = l7proto; // we do not reassemble http reasm_orig_cancel(ctrack); forced_wssize_cutoff(ctrack); - bHaveHost=HttpExtractHost(rdata_payload,rlen_payload,host,sizeof(host)); + bHaveHost = HttpExtractHost(rdata_payload, rlen_payload, host, sizeof(host)); if (!bHaveHost) { DLOG("not applying tampering to HTTP without Host:\n"); @@ -1477,22 +1477,22 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint // we do not reassemble http if (!ctrack->req_seq_present) { - ctrack->req_seq_start=ctrack->seq_last; - ctrack->req_seq_end=ctrack->pos_orig-1; - ctrack->req_seq_present=ctrack->req_seq_finalized=true; - DLOG("req retrans : tcp seq interval %u-%u\n",ctrack->req_seq_start,ctrack->req_seq_end); + ctrack->req_seq_start = ctrack->seq_last; + ctrack->req_seq_end = ctrack->pos_orig - 1; + ctrack->req_seq_present = ctrack->req_seq_finalized = true; + DLOG("req retrans : tcp seq interval %u-%u\n", ctrack->req_seq_start, ctrack->req_seq_end); } } } - else if (IsTLSClientHello(rdata_payload,rlen_payload,TLS_PARTIALS_ENABLE)) + else if (IsTLSClientHello(rdata_payload, rlen_payload, TLS_PARTIALS_ENABLE)) { - bool bReqFull = IsTLSRecordFull(rdata_payload,rlen_payload); + bool bReqFull = IsTLSRecordFull(rdata_payload, rlen_payload); DLOG(bReqFull ? "packet contains full TLS ClientHello\n" : "packet contains partial TLS ClientHello\n"); l7proto = TLS; - if (bReqFull) TLSDebug(rdata_payload,rlen_payload); + if (bReqFull) TLSDebug(rdata_payload, rlen_payload); - bHaveHost=TLSHelloExtractHost(rdata_payload,rlen_payload,host,sizeof(host),TLS_PARTIALS_ENABLE); + bHaveHost = TLSHelloExtractHost(rdata_payload, rlen_payload, host, sizeof(host), TLS_PARTIALS_ENABLE); if (ctrack) { @@ -1502,7 +1502,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint !(ctrack->req_seq_finalized && seq_within(ctrack->seq_last, ctrack->req_seq_start, ctrack->req_seq_end))) { // do not reconstruct unexpected large payload (they are feeding garbage ?) - if (!reasm_orig_start(ctrack,IPPROTO_TCP,TLSRecordLen(dis->data_payload),TCP_MAX_REASM,dis->data_payload,dis->len_payload)) + if (!reasm_orig_start(ctrack, IPPROTO_TCP, TLSRecordLen(dis->data_payload), TCP_MAX_REASM, dis->data_payload, dis->len_payload)) { reasm_orig_cancel(ctrack); goto send_orig; @@ -1513,13 +1513,13 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint if (!ctrack->req_seq_present) { // lower bound of request seq interval - ctrack->req_seq_start=ctrack->seq_last; - ctrack->req_seq_present=true; + ctrack->req_seq_start = ctrack->seq_last; + ctrack->req_seq_present = true; } // upper bound of request seq interval // it can grow on every packet until request is complete. then interval is finalized and never touched again. - ctrack->req_seq_end=ctrack->pos_orig-1; - DLOG("req retrans : seq interval %u-%u\n",ctrack->req_seq_start,ctrack->req_seq_end); + ctrack->req_seq_end = ctrack->pos_orig - 1; + DLOG("req retrans : seq interval %u-%u\n", ctrack->req_seq_start, ctrack->req_seq_end); ctrack->req_seq_finalized |= bReqFull; } if (bReqFull || ReasmIsEmpty(&ctrack->reasm_orig)) forced_wssize_cutoff(ctrack); @@ -1558,23 +1558,23 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint { uint32_t dseq = ctrack->seq_last - ctrack->req_seq_end; // do not react to 32-bit overflowed sequence numbers. allow 16 Mb grace window then cutoff. - if (dseq>=0x1000000 && !(dseq & 0x80000000)) ctrack->req_seq_abandoned=true; + if (dseq >= 0x1000000 && !(dseq & 0x80000000)) ctrack->req_seq_abandoned = true; } if (bHaveHost) { - bHostIsIp=strip_host_to_ip(host); - DLOG("hostname: %s\n",host); + bHostIsIp = strip_host_to_ip(host); + DLOG("hostname: %s\n", host); } bool bDiscoveredL7; if (ctrack_replay) { - bDiscoveredL7 = !ctrack_replay->l7proto_discovered && ctrack_replay->l7proto!=UNKNOWN; - ctrack_replay->l7proto_discovered=true; + bDiscoveredL7 = !ctrack_replay->l7proto_discovered && ctrack_replay->l7proto != UNKNOWN; + ctrack_replay->l7proto_discovered = true; } else - bDiscoveredL7 = !ctrack_replay && l7proto!=UNKNOWN; + bDiscoveredL7 = !ctrack_replay && l7proto != UNKNOWN; if (bDiscoveredL7) DLOG("discovered l7 protocol\n"); bool bDiscoveredHostname = bHaveHost && !(ctrack_replay && ctrack_replay->hostname_discovered); @@ -1584,16 +1584,16 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint if (ctrack_replay) { free(ctrack_replay->hostname); - ctrack_replay->hostname=strdup(host); - ctrack_replay->hostname_is_ip=bHostIsIp; + ctrack_replay->hostname = strdup(host); + ctrack_replay->hostname_is_ip = bHostIsIp; if (!ctrack_replay->hostname) { DLOG_ERR("hostname dup : out of memory"); reasm_orig_cancel(ctrack); goto send_orig; } - ctrack_replay->hostname_discovered=true; - if (!ipcache_put_hostname(dis->ip ? &dis->ip->ip_dst : NULL,dis->ip6 ? &dis->ip6->ip6_dst : NULL , host, bHostIsIp)) + ctrack_replay->hostname_discovered = true; + if (!ipcache_put_hostname(dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL, host, bHostIsIp)) { reasm_orig_cancel(ctrack); goto send_orig; @@ -1602,7 +1602,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint } } - bool bCheckDone=false, bCheckResult=false, bCheckExcluded=false; + bool bCheckDone = false, bCheckResult = false, bCheckExcluded = false; if (bDiscoveredL7 || bDiscoveredHostname) { struct desync_profile *dp_prev = dp; @@ -1625,20 +1625,20 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint reasm_orig_cancel(ctrack); goto send_orig; } - if (dp!=dp_prev) + if (dp != dp_prev) { DLOG("desync profile changed by revealed l7 protocol or hostname !\n"); - autottl_rediscover(ctrack_replay,dis->ip ? &dis->ip->ip_dst : NULL,dis->ip6 ? &dis->ip6->ip6_dst : NULL , ifout); + autottl_rediscover(ctrack_replay, dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL, ifout); // re-evaluate start/cutoff limiters if (replay) { - if (orig_mod(dp,ctrack_replay,dis)) // ttl can change ! + if (orig_mod(dp, ctrack_replay, dis)) // ttl can change ! verdict = VERDICT_MODIFY; } else { maybe_cutoff(ctrack, IPPROTO_TCP); - if (orig_mod(dp,ctrack,dis)) // ttl can change ! + if (orig_mod(dp, ctrack, dis)) // ttl can change ! verdict = VERDICT_MODIFY; if (!process_desync_interval(dp, ctrack)) { @@ -1675,7 +1675,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint } } - if (l7proto==UNKNOWN) + if (l7proto == UNKNOWN) { if (!dp->desync_any_proto) { @@ -1687,20 +1687,20 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint } ttl_fake = (ctrack_replay && ctrack_replay->desync_autottl) ? ctrack_replay->desync_autottl : (dis->ip6 ? (dp->desync_ttl6 ? dp->desync_ttl6 : ttl_orig) : (dp->desync_ttl ? dp->desync_ttl : ttl_orig)); - if ((l7proto == HTTP) && (dp->hostcase || dp->hostnospace || dp->domcase || dp->methodeol) && HttpFindHost(&phost,dis->data_payload,dis->len_payload)) + if ((l7proto == HTTP) && (dp->hostcase || dp->hostnospace || dp->domcase || dp->methodeol) && HttpFindHost(&phost, dis->data_payload, dis->len_payload)) { if (dp->hostcase) { DLOG("modifying Host: => %c%c%c%c:\n", dp->hostspell[0], dp->hostspell[1], dp->hostspell[2], dp->hostspell[3]); memcpy(phost, dp->hostspell, 4); - verdict=VERDICT_MODIFY; + verdict = VERDICT_MODIFY; } if (dp->domcase) { DLOG("mixing domain case\n"); - for (p = phost+5; p < (dis->data_payload + dis->len_payload) && *p != '\r' && *p != '\n'; p++) + for (p = phost + 5; p < (dis->data_payload + dis->len_payload) && *p != '\r' && *p != '\n'; p++) *p = (((size_t)p) & 1) ? tolower(*p) : toupper(*p); - verdict=VERDICT_MODIFY; + verdict = VERDICT_MODIFY; } uint8_t *pua; if (dp->hostnospace) @@ -1712,34 +1712,34 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint if (pua > phost) { memmove(phost + 5, phost + 6, pua - phost - 6); - pua[-1]=' '; + pua[-1] = ' '; } else { memmove(pua + 1, pua, phost - pua + 5); *pua = ' '; } - verdict=VERDICT_MODIFY; + verdict = VERDICT_MODIFY; } else DLOG("cannot do hostnospace because valid User-Agent: not found\n"); } else if (dp->methodeol) { - if (phost[5]==' ' || phost[5]=='\t') + if (phost[5] == ' ' || phost[5] == '\t') { DLOG("removing space after Host: and adding '\\n' before method\n"); - memmove(dis->data_payload+1,dis->data_payload,phost-dis->data_payload+5); - dis->data_payload[0]='\n'; - verdict=VERDICT_MODIFY; + memmove(dis->data_payload + 1, dis->data_payload, phost - dis->data_payload + 5); + dis->data_payload[0] = '\n'; + verdict = VERDICT_MODIFY; } else DLOG("cannot do methodeol because there's no space or tab after Host:\n"); } - + } - if (dp->desync_mode==DESYNC_NONE) + if (dp->desync_mode == DESYNC_NONE) { reasm_orig_cancel(ctrack); goto send_orig; @@ -1747,34 +1747,34 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint if (params.debug) { - char s1[48],s2[48]; + char s1[48], s2[48]; ntop46_port((struct sockaddr *)&src, s1, sizeof(s1)); ntop46_port((struct sockaddr *)&dst, s2, sizeof(s2)); - DLOG("dpi desync src=%s dst=%s\n",s1,s2); + DLOG("dpi desync src=%s dst=%s\n", s1, s2); } - switch(l7proto) + switch (l7proto) { - case HTTP: - fake = &dp->fake_http; - break; - case TLS: - fake = &dp->fake_tls; - break; - default: - fake = &dp->fake_unknown; - break; + case HTTP: + fake = &dp->fake_http; + break; + case TLS: + fake = &dp->fake_tls; + break; + default: + fake = &dp->fake_unknown; + break; } - if (dp->desync_mode==DESYNC_MULTISPLIT || dp->desync_mode==DESYNC_MULTIDISORDER || dp->desync_mode2==DESYNC_MULTISPLIT || dp->desync_mode2==DESYNC_MULTIDISORDER) + if (dp->desync_mode == DESYNC_MULTISPLIT || dp->desync_mode == DESYNC_MULTIDISORDER || dp->desync_mode2 == DESYNC_MULTISPLIT || dp->desync_mode2 == DESYNC_MULTIDISORDER) { - split_pos=0; + split_pos = 0; ResolveMultiPos(rdata_payload, rlen_payload, l7proto, dp->splits, dp->split_count, multisplit_pos, &multisplit_count); if (params.debug) { if (multisplit_count) { DLOG("multisplit pos: "); - for (i=0;ilen_payload); + multisplit_pos[j] = pos_normalize(multisplit_pos[i], reasm_offset, dis->len_payload); if (multisplit_pos[j]) j++; } - multisplit_count=j; + multisplit_count = j; if (params.debug) { if (multisplit_count) { DLOG("normalized multisplit pos: "); - for (i=0;idesync_mode==DESYNC_FAKEDSPLIT || dp->desync_mode==DESYNC_FAKEDDISORDER || dp->desync_mode2==DESYNC_FAKEDSPLIT || dp->desync_mode2==DESYNC_FAKEDDISORDER) + else if (dp->desync_mode == DESYNC_FAKEDSPLIT || dp->desync_mode == DESYNC_FAKEDDISORDER || dp->desync_mode2 == DESYNC_FAKEDSPLIT || dp->desync_mode2 == DESYNC_FAKEDDISORDER) { - multisplit_count=0; + multisplit_count = 0; // first look for non-abs split - for(i=0,split_pos=0;isplit_count && !split_pos;i++) - if (dp->splits[i].marker!=PM_ABS) - split_pos = ResolvePos(rdata_payload, rlen_payload, l7proto, dp->splits+i); + for (i = 0, split_pos = 0; i < dp->split_count && !split_pos; i++) + if (dp->splits[i].marker != PM_ABS) + split_pos = ResolvePos(rdata_payload, rlen_payload, l7proto, dp->splits + i); // second look for abs split if (!split_pos) - for(i=0,split_pos=0;isplit_count && !split_pos;i++) - if (dp->splits[i].marker==PM_ABS) - split_pos = ResolvePos(rdata_payload, rlen_payload, l7proto, dp->splits+i); + for (i = 0, split_pos = 0; i < dp->split_count && !split_pos; i++) + if (dp->splits[i].marker == PM_ABS) + split_pos = ResolvePos(rdata_payload, rlen_payload, l7proto, dp->splits + i); if (!split_pos) split_pos = 1; - DLOG("regular split pos: %zu\n",split_pos); - if (!split_pos || split_pos>rlen_payload) split_pos=1; - split_pos=pos_normalize(split_pos,reasm_offset,dis->len_payload); + DLOG("regular split pos: %zu\n", split_pos); + if (!split_pos || split_pos > rlen_payload) split_pos = 1; + split_pos = pos_normalize(split_pos, reasm_offset, dis->len_payload); if (split_pos) - DLOG("normalized regular split pos : %zu\n",split_pos); + DLOG("normalized regular split pos : %zu\n", split_pos); else DLOG("regular split pos is outside of this packet\n"); } - else if (dp->desync_mode==DESYNC_HOSTFAKESPLIT || dp->desync_mode2==DESYNC_HOSTFAKESPLIT) + else if (dp->desync_mode == DESYNC_HOSTFAKESPLIT || dp->desync_mode2 == DESYNC_HOSTFAKESPLIT) { struct proto_pos splits[2] = { - { .marker = PM_HOST, .pos = 0}, - { .marker = PM_HOST_END, .pos = 0} + {.marker = PM_HOST,.pos = 0}, + {.marker = PM_HOST_END,.pos = 0} }; - split_pos=0; + split_pos = 0; ResolveMultiPos(rdata_payload, rlen_payload, l7proto, splits, 2, multisplit_pos, &multisplit_count); - if (multisplit_count!=2) + if (multisplit_count != 2) { DLOG("hostfakesplit: host and endhost positions not found\n"); - multisplit_count=0; + multisplit_count = 0; } else { int j; - for (i=j=0;ilen_payload); + multisplit_pos[j] = pos_normalize(multisplit_pos[i], reasm_offset, dis->len_payload); if (multisplit_pos[j]) j++; } - multisplit_count=j; - if (multisplit_count!=2) + multisplit_count = j; + if (multisplit_count != 2) { DLOG("hostfakesplit: host or endhost are outside of this packet\n"); - multisplit_count=0; + multisplit_count = 0; } else { DLOG("normalized hostfakesplit pos: "); - for (i=0;ihostfakesplit_midhost); + multisplit_pos[2] = ResolvePos(rdata_payload, rlen_payload, l7proto, &dp->hostfakesplit_midhost); if (multisplit_pos[2]) { - multisplit_pos[2]=pos_normalize(multisplit_pos[2],reasm_offset,dis->len_payload); - if (multisplit_pos[2]>multisplit_pos[0] && multisplit_pos[2]len_payload); + if (multisplit_pos[2] > multisplit_pos[0] && multisplit_pos[2] < multisplit_pos[1]) { - DLOG("normalized hostfakesplit midhost pos: %zu\n",multisplit_pos[2]); + DLOG("normalized hostfakesplit midhost pos: %zu\n", multisplit_pos[2]); multisplit_count++; } } @@ -1870,593 +1870,370 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint } else { - multisplit_count=0; + multisplit_count = 0; split_pos = 0; } - if (dp->desync_mode==DESYNC_FAKEDSPLIT || dp->desync_mode==DESYNC_MULTISPLIT || dp->desync_mode2==DESYNC_FAKEDSPLIT || dp->desync_mode2==DESYNC_MULTISPLIT) + if (dp->desync_mode == DESYNC_FAKEDSPLIT || dp->desync_mode == DESYNC_MULTISPLIT || dp->desync_mode2 == DESYNC_FAKEDSPLIT || dp->desync_mode2 == DESYNC_MULTISPLIT) { // split seqovl only uses absolute positive values - seqovl_pos = (dp->seqovl.marker==PM_ABS && dp->seqovl.pos>0) ? dp->seqovl.pos : 0; - if (seqovl_pos) DLOG("seqovl : %zu\n",seqovl_pos); + seqovl_pos = (dp->seqovl.marker == PM_ABS && dp->seqovl.pos > 0) ? dp->seqovl.pos : 0; + if (seqovl_pos) DLOG("seqovl : %zu\n", seqovl_pos); } - else if (dp->desync_mode==DESYNC_FAKEDDISORDER || dp->desync_mode==DESYNC_MULTIDISORDER || dp->desync_mode2==DESYNC_FAKEDDISORDER || dp->desync_mode2==DESYNC_MULTIDISORDER) + else if (dp->desync_mode == DESYNC_FAKEDDISORDER || dp->desync_mode == DESYNC_MULTIDISORDER || dp->desync_mode2 == DESYNC_FAKEDDISORDER || dp->desync_mode2 == DESYNC_MULTIDISORDER) { seqovl_pos = ResolvePos(rdata_payload, rlen_payload, l7proto, &dp->seqovl); - seqovl_pos = pos_normalize(seqovl_pos,reasm_offset,dis->len_payload); - if (seqovl_pos) DLOG("normalized seqovl : %zu\n",seqovl_pos); + seqovl_pos = pos_normalize(seqovl_pos, reasm_offset, dis->len_payload); + if (seqovl_pos) DLOG("normalized seqovl : %zu\n", seqovl_pos); } else seqovl_pos = 0; uint32_t fooling_orig = FOOL_NONE; - switch(dp->desync_mode) + switch (dp->desync_mode) { - case DESYNC_FAKE_KNOWN: - if (reasm_offset) break; - if (l7proto==UNKNOWN) - { - DLOG("not applying fake because of unknown protocol\n"); - break; - } - case DESYNC_FAKE: - if (reasm_offset) break; + case DESYNC_FAKE_KNOWN: + if (reasm_offset) break; + if (l7proto == UNKNOWN) + { + DLOG("not applying fake because of unknown protocol\n"); + break; + } + case DESYNC_FAKE: + if (reasm_offset) break; - { - struct blob_item *fake_item; - size_t fake_size; - uint8_t *fake_data; - uint8_t fake_data_buf[FAKE_MAX_TCP]; - int n=0; - uint32_t sequence, sequence0; + { + struct blob_item *fake_item; + size_t fake_size; + uint8_t *fake_data; + uint8_t fake_data_buf[FAKE_MAX_TCP]; + int n = 0; + uint32_t sequence, sequence0; - sequence = sequence0 = ntohl(dis->tcp->th_seq); - LIST_FOREACH(fake_item, fake, next) + sequence = sequence0 = ntohl(dis->tcp->th_seq); + LIST_FOREACH(fake_item, fake, next) + { + n++; + switch (l7proto) { - n++; - switch(l7proto) + case TLS: + if ((fake_item->size <= sizeof(fake_data_buf)) && + runtime_tls_mod(n, (struct fake_tls_mod_cache *)fake_item->extra, (struct fake_tls_mod *)fake_item->extra2, fake_item->data, fake_item->size, rdata_payload, rlen_payload, fake_data_buf)) { - case TLS: - if ((fake_item->size <= sizeof(fake_data_buf)) && - runtime_tls_mod(n,(struct fake_tls_mod_cache *)fake_item->extra,(struct fake_tls_mod *)fake_item->extra2, fake_item->data, fake_item->size, rdata_payload, rlen_payload, fake_data_buf)) - { - fake_data = fake_data_buf; - break; - } - default: - fake_data = fake_item->data; + fake_data = fake_data_buf; + break; } - fake_data += fake_item->offset; - fake_size = fake_item->size - fake_item->offset; - - pkt1_len = sizeof(pkt1); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, htonl(sequence), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, - DF,ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), - dp->desync_fooling_mode,dp->desync_ts_increment,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, - fake_data, fake_size, pkt1, &pkt1_len)) - { - reasm_orig_cancel(ctrack); - goto send_orig; - } - DLOG("sending fake[%d] seq=+%u : ", n, sequence-sequence0); - hexdump_limited_dlog(fake_data,fake_size,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) - { - reasm_orig_cancel(ctrack); - goto send_orig; - } - ip_id=IP4_IP_ID_NEXT(ip_id); - if (dp->tcp_mod.seq) sequence += fake_size; + default: + fake_data = fake_item->data; } - } - bFake = true; - break; - case DESYNC_RST: - case DESYNC_RSTACK: - if (reasm_offset) break; - pkt1_len = sizeof(pkt1); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_RST | (dp->desync_mode==DESYNC_RSTACK ? TH_ACK:0), false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, - DF,ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), - dp->desync_fooling_mode,dp->desync_ts_increment,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, - NULL, 0, pkt1, &pkt1_len)) - { - reasm_orig_cancel(ctrack); - goto send_orig; - } - DLOG("sending fake RST/RSTACK\n"); - if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) - { - reasm_orig_cancel(ctrack); - goto send_orig; - } - ip_id=IP4_IP_ID_NEXT(ip_id); - bFake = true; - break; - case DESYNC_HOPBYHOP: - case DESYNC_DESTOPT: - case DESYNC_IPFRAG1: - fooling_orig = (dp->desync_mode==DESYNC_HOPBYHOP) ? FOOL_HOPBYHOP : (dp->desync_mode==DESYNC_DESTOPT) ? FOOL_DESTOPT : FOOL_IPFRAG1; - if (dis->ip6 && (dp->desync_mode2==DESYNC_NONE || !desync_valid_second_stage_tcp(dp->desync_mode2) || - (!split_pos && (dp->desync_mode2==DESYNC_FAKEDSPLIT || dp->desync_mode2==DESYNC_FAKEDDISORDER)) || - (multisplit_count<2 && dp->desync_mode2==DESYNC_HOSTFAKESPLIT) || - (!multisplit_count && (dp->desync_mode2==DESYNC_MULTISPLIT || dp->desync_mode2==DESYNC_MULTIDISORDER)))) - { - reasm_orig_cancel(ctrack); - rdata_payload=NULL; + fake_data += fake_item->offset; + fake_size = fake_item->size - fake_item->offset; pkt1_len = sizeof(pkt1); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, - DF,ttl_orig,0,0,IP6_FLOW(dis->ip6), - fooling_orig,0,0,0, - dis->data_payload, dis->len_payload, pkt1, &pkt1_len)) + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, htonl(sequence), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, + DF, ttl_fake, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), + dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment, + fake_data, fake_size, pkt1, &pkt1_len)) { + reasm_orig_cancel(ctrack); goto send_orig; } - DLOG("resending original packet with extension header\n"); - if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) + DLOG("sending fake[%d] seq=+%u : ", n, sequence - sequence0); + hexdump_limited_dlog(fake_data, fake_size, PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) + { + reasm_orig_cancel(ctrack); goto send_orig; - // this mode is final, no other options available - return VERDICT_DROP; + } + ip_id = IP4_IP_ID_NEXT(ip_id); + if (dp->tcp_mod.seq) sequence += fake_size; } - default: - pkt1_len=0; - break; + } + bFake = true; + break; + case DESYNC_RST: + case DESYNC_RSTACK: + if (reasm_offset) break; + pkt1_len = sizeof(pkt1); + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_RST | (dp->desync_mode == DESYNC_RSTACK ? TH_ACK : 0), false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, + DF, ttl_fake, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), + dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment, + NULL, 0, pkt1, &pkt1_len)) + { + reasm_orig_cancel(ctrack); + goto send_orig; + } + DLOG("sending fake RST/RSTACK\n"); + if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) + { + reasm_orig_cancel(ctrack); + goto send_orig; + } + ip_id = IP4_IP_ID_NEXT(ip_id); + bFake = true; + break; + case DESYNC_HOPBYHOP: + case DESYNC_DESTOPT: + case DESYNC_IPFRAG1: + fooling_orig = (dp->desync_mode == DESYNC_HOPBYHOP) ? FOOL_HOPBYHOP : (dp->desync_mode == DESYNC_DESTOPT) ? FOOL_DESTOPT : FOOL_IPFRAG1; + if (dis->ip6 && (dp->desync_mode2 == DESYNC_NONE || !desync_valid_second_stage_tcp(dp->desync_mode2) || + (!split_pos && (dp->desync_mode2 == DESYNC_FAKEDSPLIT || dp->desync_mode2 == DESYNC_FAKEDDISORDER)) || + (multisplit_count < 2 && dp->desync_mode2 == DESYNC_HOSTFAKESPLIT) || + (!multisplit_count && (dp->desync_mode2 == DESYNC_MULTISPLIT || dp->desync_mode2 == DESYNC_MULTIDISORDER)))) + { + reasm_orig_cancel(ctrack); + rdata_payload = NULL; + + pkt1_len = sizeof(pkt1); + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, + DF, ttl_orig, 0, 0, IP6_FLOW(dis->ip6), + fooling_orig, 0, 0, 0, + dis->data_payload, dis->len_payload, pkt1, &pkt1_len)) + { + goto send_orig; + } + DLOG("resending original packet with extension header\n"); + if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) + goto send_orig; + // this mode is final, no other options available + return VERDICT_DROP; + } + default: + pkt1_len = 0; + break; } // we do not need reasm buffer anymore reasm_orig_cancel(ctrack); - rdata_payload=NULL; + rdata_payload = NULL; - enum dpi_desync_mode desync_mode = dp->desync_mode2==DESYNC_NONE ? dp->desync_mode : dp->desync_mode2; - switch(desync_mode) + enum dpi_desync_mode desync_mode = dp->desync_mode2 == DESYNC_NONE ? dp->desync_mode : dp->desync_mode2; + switch (desync_mode) { - case DESYNC_HOSTFAKESPLIT: - // can be 2 or 3 split pos - // if 2 split pos : host, endhost - // if 3 split pos : host, endhost, midhost - if (multisplit_count>=2) + case DESYNC_HOSTFAKESPLIT: + // can be 2 or 3 split pos + // if 2 split pos : host, endhost + // if 3 split pos : host, endhost, midhost + if (multisplit_count >= 2) + { + uint8_t *seg; + size_t seg_len, host_size, pos_host, pos_endhost, pos_split_host, sz; + uint8_t *fakehost; + uint16_t ip_id_after_host; + + seg = dis->data_payload; + seg_len = dis->len_payload; + pos_host = multisplit_pos[0]; + pos_endhost = multisplit_pos[1]; + pos_split_host = multisplit_count >= 3 ? multisplit_pos[2] : 0; + host_size = pos_endhost - pos_host; + + if (replay && ctrack_replay->ip_id) ip_id = ctrack_replay->ip_id; + + // before_host segment + pkt1_len = sizeof(pkt1); + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, + dis->tcp->th_seq, dis->tcp->th_ack, + dis->tcp->th_win, scale_factor, timestamps, + DF, ttl_orig, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), + fooling_orig, 0, 0, 0, + seg, pos_host, pkt1, &pkt1_len)) + goto send_orig; + ip_id = IP4_IP_ID_NEXT(ip_id); + DLOG("sending hostfakesplit before_host part 0-%zu len=%zu : ", pos_host - 1, pos_host); + hexdump_limited_dlog(seg, pos_host, PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) + goto send_orig; + + if (!(fakehost = malloc(host_size + 1))) { - uint16_t ip_id_fake = (uint16_t)random(); - uint8_t *seg; - size_t seg_len, host_size, pos_host, pos_endhost, pos_split_host, sz; - uint8_t *fakehost; - - seg = dis->data_payload; - seg_len = dis->len_payload; - pos_host = multisplit_pos[0]; - pos_endhost = multisplit_pos[1]; - pos_split_host = multisplit_count>=3 ? multisplit_pos[2] : 0; - host_size = pos_endhost-pos_host; - - // before_host segment - pkt1_len = sizeof(pkt1); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, - dis->tcp->th_seq, dis->tcp->th_ack, - dis->tcp->th_win, scale_factor, timestamps, - DF,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), - fooling_orig,0,0,0, - seg, pos_host, pkt1, &pkt1_len)) - goto send_orig; - ip_id=IP4_IP_ID_NEXT(ip_id); - DLOG("sending hostfakesplit before_host part 0-%zu len=%zu : ",pos_host-1,pos_host); - hexdump_limited_dlog(seg,pos_host,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) - goto send_orig; - - // pkt3: after_host segment - pkt3_len = sizeof(pkt3); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, - net32_add(dis->tcp->th_seq,pos_endhost), dis->tcp->th_ack, - dis->tcp->th_win, scale_factor, timestamps, - DF,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), - fooling_orig,0,0,0, - seg+pos_endhost, seg_len-pos_endhost, pkt3, &pkt3_len)) - goto send_orig; - - if (!(fakehost=malloc(host_size+1))) - { - DLOG("fakehost out of memory\n"); - goto send_orig; - } - if (*dp->hfs_mod.host) - { - if (host_size<=dp->hfs_mod.host_size) - { - // "google.com" => "gle.com" - // "google.com" => "google.com" - memcpy(fakehost,dp->hfs_mod.host+dp->hfs_mod.host_size-host_size,host_size); - } - else - { - // "google.com" => "nb4auv9.google.com" - // "google.com" => ".google.com" - sz = host_size - dp->hfs_mod.host_size; - memcpy(fakehost+sz,dp->hfs_mod.host,dp->hfs_mod.host_size); - fakehost[--sz]='.'; - if (sz) - { - fill_random_az(fakehost,1); - sz--; - } - fill_random_az09(fakehost+1,sz); - } - } - else - { - fill_random_az(fakehost,1); - fill_random_az09(fakehost+1,host_size-1); - if (host_size>=7) fakehost[host_size-4] = '.'; - } - fakehost[host_size]=0; - DLOG("generated fake host: %s\n",fakehost); - - // pkt2: fake_host segment - pkt2_len = sizeof(pkt2); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, - net32_add(dis->tcp->th_seq,pos_host), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, - DF,ttl_fake,IP4_TOS(dis->ip),ip_id_fake,IP6_FLOW(dis->ip6), - dp->desync_fooling_mode,dp->desync_ts_increment,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, - fakehost, host_size, pkt2, &pkt2_len)) - goto send_orig_clean; - DLOG("sending hostfakesplit fake host %zu-%zu len=%zu : ",pos_host,pos_endhost-1,host_size); - hexdump_limited_dlog(fakehost,host_size,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , pkt2, pkt2_len)) - goto send_orig_clean; - - if (dp->hfs_mod.ordering==1) - { - DLOG("sending hostfakesplit after_host part %zu-%zu len=%zu : ",pos_endhost,seg_len-1,seg_len-pos_endhost); - hexdump_limited_dlog(seg+pos_endhost,seg_len-pos_endhost,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt3, pkt3_len)) - goto send_orig_clean; - } - - sz = pos_split_host ? pos_split_host-pos_host : host_size; - pkt1_len = sizeof(pkt1); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, - net32_add(dis->tcp->th_seq,pos_host), dis->tcp->th_ack, - dis->tcp->th_win, scale_factor, timestamps, - DF,ttl_orig,IP4_TOS(dis->ip),ip_id_fake,IP6_FLOW(dis->ip6), - fooling_orig,0,0,0, - seg+pos_host, sz, pkt1, &pkt1_len)) - goto send_orig_clean; - - DLOG("sending hostfakesplit real host %s%zu-%zu len=%zu : ",pos_split_host ? "part 1 " : "",pos_host,pos_host+sz-1,sz); - hexdump_limited_dlog(seg+pos_host,sz,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) - goto send_orig_clean; - - if (pos_split_host) - { - sz = pos_endhost - pos_split_host; - pkt1_len = sizeof(pkt1); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, - net32_add(dis->tcp->th_seq,pos_split_host), dis->tcp->th_ack, - dis->tcp->th_win, scale_factor, timestamps, - DF,ttl_orig,IP4_TOS(dis->ip),net16_add(ip_id_fake,1),IP6_FLOW(dis->ip6), - fooling_orig,0,0,0, - seg+pos_split_host, sz, pkt1, &pkt1_len)) - goto send_orig_clean; - DLOG("sending hostfakesplit real host part 2 %zu-%zu len=%zu : ",pos_split_host,pos_endhost-1,sz); - hexdump_limited_dlog(seg+pos_split_host,sz,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) - goto send_orig_clean; - } - - if (dp->hfs_mod.ordering==0) - { - DLOG("sending hostfakesplit fake(2) host %zu-%zu len=%zu : ",pos_host,pos_endhost-1,host_size); - hexdump_limited_dlog(fakehost,host_size,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , pkt2, pkt2_len)) - goto send_orig_clean; - - DLOG("sending hostfakesplit after_host part %zu-%zu len=%zu : ",pos_endhost,seg_len-1,seg_len-pos_endhost); - hexdump_limited_dlog(seg+pos_endhost,seg_len-pos_endhost,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt3, pkt3_len)) - goto send_orig_clean; - } - - free(fakehost); - return VERDICT_DROP; -send_orig_clean: - free(fakehost); + DLOG("fakehost out of memory\n"); goto send_orig; } - break; - case DESYNC_MULTISPLIT: - if (multisplit_count) + if (*dp->hfs_mod.host) { - uint8_t ovlseg[DPI_DESYNC_MAX_FAKE_LEN+100], *seg; - size_t seg_len,from,to; - unsigned int seqovl; - - for (i=0,from=0 ; i<=multisplit_count ; i++) + if (host_size <= dp->hfs_mod.host_size) { - to = i==multisplit_count ? dis->len_payload : multisplit_pos[i]; - - // do seqovl only to the first packet - // otherwise it's prone to race condition on server side - // what happens first : server pushes socket buffer to process or another packet with seqovl arrives - seqovl = (i==0 && reasm_offset==0) ? seqovl_pos : 0; -#ifdef __linux__ -// only linux return error if MTU is exceeded - for(;;seqovl=0) - { -#endif - if (seqovl) - { - seg_len = to-from+seqovl; - if (seg_len>sizeof(ovlseg)) - { - DLOG("seqovl is too large"); - goto send_orig; - } - fill_pattern(ovlseg,seqovl,dp->seqovl_pattern,sizeof(dp->seqovl_pattern)); - memcpy(ovlseg+seqovl,dis->data_payload+from,to-from); - seg = ovlseg; - } - else - { - seqovl = 0; - seg = dis->data_payload+from; - seg_len = to-from; - } - - pkt1_len = sizeof(pkt1); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, - net32_add(dis->tcp->th_seq,from-seqovl), dis->tcp->th_ack, - dis->tcp->th_win, scale_factor, timestamps, - DF,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), - fooling_orig,0,0,0, - seg, seg_len, pkt1, &pkt1_len)) - goto send_orig; - ip_id=IP4_IP_ID_NEXT(ip_id); - DLOG("sending multisplit part %d %zu-%zu len=%zu seqovl=%u : ",i+1,from,to-1,to-from,seqovl); - hexdump_limited_dlog(seg,seg_len,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) - { -#ifdef __linux__ - if (errno==EMSGSIZE && seqovl) - { - DLOG("MTU exceeded. cancelling seqovl.\n"); - continue; - } -#endif - goto send_orig; - } -#ifdef __linux__ - break; - } -#endif - - from = to; - } - return VERDICT_DROP; - } - break; - case DESYNC_MULTIDISORDER: - if (multisplit_count) - { - uint8_t ovlseg[DPI_DESYNC_MAX_FAKE_LEN+100], *seg; - size_t seg_len,from,to; - unsigned int seqovl; - - ip_id=IP4_IP_ID_ADD(ip_id,(uint16_t)multisplit_count); - for (i=multisplit_count-1,to=dis->len_payload ; i>=-1 ; i--) - { - from = i>=0 ? multisplit_pos[i] : 0; - - seg = dis->data_payload+from; - seg_len = to-from; - seqovl = 0; - // do seqovl only to the second packet - // otherwise sequence overlap becomes problematic. overlap algorithm is not too obvious. - // real observations revealed that server can receive overlap junk instead of real data - if (i==0) - { - if (seqovl_pos>=from) - DLOG("seqovl>=split_pos (%zu>=%zu). cancelling seqovl for part %d.\n",seqovl,from,i+2); - else - { - seqovl = seqovl_pos; - seg_len = to-from+seqovl; - if (seg_len>sizeof(ovlseg)) - { - DLOG("seqovl is too large"); - goto send_orig; - } - fill_pattern(ovlseg,seqovl,dp->seqovl_pattern,sizeof(dp->seqovl_pattern)); - memcpy(ovlseg+seqovl,dis->data_payload+from,to-from); - seg = ovlseg; - } - } - - pkt1_len = sizeof(pkt1); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, - net32_add(dis->tcp->th_seq,from-seqovl), dis->tcp->th_ack, - dis->tcp->th_win, scale_factor, timestamps, - DF,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), - fooling_orig,0,0,0, - seg, seg_len, pkt1, &pkt1_len)) - goto send_orig; - ip_id=IP4_IP_ID_PREV(ip_id); - DLOG("sending multisplit part %d %zu-%zu len=%zu seqovl=%u : ",i+2,from,to-1,to-from,seqovl); - hexdump_limited_dlog(seg,seg_len,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) - goto send_orig; - - to = from; - } - return VERDICT_DROP; - } - break; - case DESYNC_FAKEDDISORDER: - if (split_pos) - { - uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN+100], fakeseg2[DPI_DESYNC_MAX_FAKE_LEN+100], pat[DPI_DESYNC_MAX_FAKE_LEN], *seg; - size_t seg_len,fakeseg2_len; - unsigned int seqovl; - - if (dis->len_payload > sizeof(pat)) - { - DLOG("packet is too large\n"); - goto send_orig; - } - fill_pattern(pat,dis->len_payload,dp->fsplit_pattern,sizeof(dp->fsplit_pattern)); - - ip_id=IP4_IP_ID_NEXT(ip_id); - - if (seqovl_pos>=split_pos) - { - DLOG("seqovl>=split_pos (%zu>=%zu). cancelling seqovl.\n",seqovl_pos,split_pos); - seqovl = 0; - } - else - seqovl = seqovl_pos; - - if (seqovl) - { - seg_len = dis->len_payload-split_pos+seqovl; - if (seg_len>sizeof(fakeseg)) - { - DLOG("seqovl is too large\n"); - goto send_orig; - } - fill_pattern(fakeseg,seqovl,dp->seqovl_pattern,sizeof(dp->seqovl_pattern)); - memcpy(fakeseg+seqovl,dis->data_payload+split_pos,dis->len_payload-split_pos); - seg = fakeseg; + // "google.com" => "gle.com" + // "google.com" => "google.com" + memcpy(fakehost, dp->hfs_mod.host + dp->hfs_mod.host_size - host_size, host_size); } else { - seg = dis->data_payload+split_pos; - seg_len = dis->len_payload-split_pos; + // "google.com" => "nb4auv9.google.com" + // "google.com" => ".google.com" + sz = host_size - dp->hfs_mod.host_size; + memcpy(fakehost + sz, dp->hfs_mod.host, dp->hfs_mod.host_size); + fakehost[--sz] = '.'; + if (sz) + { + fill_random_az(fakehost, 1); + sz--; + } + fill_random_az09(fakehost + 1, sz); } - - fakeseg2_len = sizeof(fakeseg2); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq,split_pos), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, - DF,ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), - dp->desync_fooling_mode,dp->desync_ts_increment,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, - pat+split_pos, dis->len_payload-split_pos, fakeseg2, &fakeseg2_len)) - goto send_orig; - DLOG("sending fake(1) 2nd out-of-order tcp segment %zu-%zu len=%zu : ",split_pos,dis->len_payload-1, dis->len_payload-split_pos); - hexdump_limited_dlog(pat+split_pos,dis->len_payload-split_pos,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg2, fakeseg2_len)) - goto send_orig; - - pkt1_len = sizeof(pkt1); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq , split_pos - seqovl), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, - DF,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), - fooling_orig,dp->desync_ts_increment,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, - seg, seg_len, pkt1, &pkt1_len)) - goto send_orig; - DLOG("sending 2nd out-of-order tcp segment %zu-%zu len=%zu seqovl=%u : ",split_pos,dis->len_payload-1, dis->len_payload-split_pos, seqovl); - hexdump_limited_dlog(seg,seg_len,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) - goto send_orig; - - DLOG("sending fake(2) 2nd out-of-order tcp segment %zu-%zu len=%zu : ",split_pos,dis->len_payload-1, dis->len_payload-split_pos); - hexdump_limited_dlog(pat+split_pos,dis->len_payload-split_pos,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg2, fakeseg2_len)) - goto send_orig; - - ip_id=IP4_IP_ID_PREV(ip_id); - - seg_len = sizeof(fakeseg); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, - DF,ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), - dp->desync_fooling_mode,dp->desync_ts_increment,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, - pat, split_pos, fakeseg, &seg_len)) - goto send_orig; - DLOG("sending fake(1) 1st out-of-order tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos); - hexdump_limited_dlog(pat,split_pos,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, seg_len)) - goto send_orig; - - pkt1_len = sizeof(pkt1); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, - DF,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), - fooling_orig,dp->desync_ts_increment,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, - dis->data_payload, split_pos, pkt1, &pkt1_len)) - goto send_orig; - DLOG("sending 1st out-of-order tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos); - hexdump_limited_dlog(dis->data_payload,split_pos,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) - goto send_orig; - - if (dis->ip) ((struct ip*)fakeseg)->ip_id = ip_id; - DLOG("sending fake(2) 1st out-of-order tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos); - hexdump_limited_dlog(pat,split_pos,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, seg_len)) - goto send_orig; - - return VERDICT_DROP; } - break; - case DESYNC_FAKEDSPLIT: - if (split_pos) + else { - uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN+100],ovlseg[DPI_DESYNC_MAX_FAKE_LEN+100],pat[DPI_DESYNC_MAX_FAKE_LEN], *seg; - size_t fakeseg_len,seg_len; - - if (dis->len_payload > sizeof(pat)) + fill_random_az(fakehost, 1); + fill_random_az09(fakehost + 1, host_size - 1); + if (host_size >= 7) { - DLOG("packet is too large\n"); - goto send_orig; + fakehost[host_size - 4] = '.'; + memcpy(fakehost + host_size - 3, tld[random() % (sizeof(tld) / sizeof(*tld))], 3); } - fill_pattern(pat,dis->len_payload,dp->fsplit_pattern,sizeof(dp->fsplit_pattern)); + } + fakehost[host_size] = 0; + DLOG("generated fake host: %s\n", fakehost); - fakeseg_len = sizeof(fakeseg); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, - DF,ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), - dp->desync_fooling_mode,dp->desync_ts_increment,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, - pat, split_pos, fakeseg, &fakeseg_len)) - goto send_orig; + // pkt2: fake_host segment + pkt2_len = sizeof(pkt2); + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, + net32_add(dis->tcp->th_seq, pos_host), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, + DF, ttl_fake, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), + dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment, + fakehost, host_size, pkt2, &pkt2_len)) + goto send_orig_clean; - if (dp->fs_mod.ordering==0) - { - ip_id=IP4_IP_ID_NEXT(ip_id); - DLOG("sending fake(1) 1st tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos); - hexdump_limited_dlog(pat,split_pos,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, fakeseg_len)) - goto send_orig; - } + DLOG("sending hostfakesplit fake host %zu-%zu len=%zu : ", pos_host, pos_endhost - 1, host_size); + hexdump_limited_dlog(fakehost, host_size, PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, pkt2, pkt2_len)) + goto send_orig_clean; - unsigned int seqovl = reasm_offset ? 0 : seqovl_pos; + ip_id_after_host = IP4_IP_ID_NEXT(ip_id); + if (pos_split_host) ip_id_after_host = IP4_IP_ID_NEXT(ip_id_after_host); + + // pkt3: after_host segment + pkt3_len = sizeof(pkt3); + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, + net32_add(dis->tcp->th_seq, pos_endhost), dis->tcp->th_ack, + dis->tcp->th_win, scale_factor, timestamps, + DF, ttl_orig, IP4_TOS(dis->ip), ip_id_after_host, IP6_FLOW(dis->ip6), + fooling_orig, 0, 0, 0, + seg + pos_endhost, seg_len - pos_endhost, pkt3, &pkt3_len)) + goto send_orig_clean; + + if (dp->hfs_mod.ordering == 1) + { + DLOG("sending hostfakesplit after_host part %zu-%zu len=%zu : ", pos_endhost, seg_len - 1, seg_len - pos_endhost); + hexdump_limited_dlog(seg + pos_endhost, seg_len - pos_endhost, PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt3, pkt3_len)) + goto send_orig_clean; + } + + sz = pos_split_host ? pos_split_host - pos_host : host_size; + pkt1_len = sizeof(pkt1); + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, + net32_add(dis->tcp->th_seq, pos_host), dis->tcp->th_ack, + dis->tcp->th_win, scale_factor, timestamps, + DF, ttl_orig, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), + fooling_orig, 0, 0, 0, + seg + pos_host, sz, pkt1, &pkt1_len)) + goto send_orig_clean; + + DLOG("sending hostfakesplit real host %s%zu-%zu len=%zu : ", pos_split_host ? "part 1 " : "", pos_host, pos_host + sz - 1, sz); + hexdump_limited_dlog(seg + pos_host, sz, PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) + goto send_orig_clean; + + if (pos_split_host) + { + sz = pos_endhost - pos_split_host; + pkt1_len = sizeof(pkt1); + ip_id = IP4_IP_ID_NEXT(ip_id); + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, + net32_add(dis->tcp->th_seq, pos_split_host), dis->tcp->th_ack, + dis->tcp->th_win, scale_factor, timestamps, + DF, ttl_orig, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), + fooling_orig, 0, 0, 0, + seg + pos_split_host, sz, pkt1, &pkt1_len)) + goto send_orig_clean; + DLOG("sending hostfakesplit real host part 2 %zu-%zu len=%zu : ", pos_split_host, pos_endhost - 1, sz); + hexdump_limited_dlog(seg + pos_split_host, sz, PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) + goto send_orig_clean; + } + + if (dp->hfs_mod.ordering == 0) + { + DLOG("sending hostfakesplit fake(2) host %zu-%zu len=%zu : ", pos_host, pos_endhost - 1, host_size); + hexdump_limited_dlog(fakehost, host_size, PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, pkt2, pkt2_len)) + goto send_orig_clean; + + DLOG("sending hostfakesplit after_host part %zu-%zu len=%zu : ", pos_endhost, seg_len - 1, seg_len - pos_endhost); + hexdump_limited_dlog(seg + pos_endhost, seg_len - pos_endhost, PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt3, pkt3_len)) + goto send_orig_clean; + } + + free(fakehost); + + if (replay) ctrack_replay->ip_id = IP4_IP_ID_NEXT(ip_id_after_host); + + return VERDICT_DROP; + send_orig_clean: + free(fakehost); + goto send_orig; + } + else + goto unsplitted_part; + + case DESYNC_MULTISPLIT: + if (multisplit_count) + { + uint8_t ovlseg[DPI_DESYNC_MAX_FAKE_LEN + 100], *seg; + size_t seg_len, from, to; + unsigned int seqovl; + + if (replay && ctrack_replay->ip_id) ip_id = ctrack_replay->ip_id; + + for (i = 0, from = 0; i <= multisplit_count; i++) + { + to = i == multisplit_count ? dis->len_payload : multisplit_pos[i]; + + // do seqovl only to the first packet + // otherwise it's prone to race condition on server side + // what happens first : server pushes socket buffer to process or another packet with seqovl arrives + seqovl = (i == 0 && reasm_offset == 0) ? seqovl_pos : 0; #ifdef __linux__ -// only linux return error if MTU is exceeded - for(;;seqovl=0) + // only linux return error if MTU is exceeded + for (;; seqovl = 0) { #endif if (seqovl) { - seg_len = split_pos+seqovl; - if (seg_len>sizeof(ovlseg)) + seg_len = to - from + seqovl; + if (seg_len > sizeof(ovlseg)) { - DLOG("seqovl is too large\n"); + DLOG("seqovl is too large"); goto send_orig; } - fill_pattern(ovlseg,seqovl,dp->seqovl_pattern,sizeof(dp->seqovl_pattern)); - memcpy(ovlseg+seqovl,dis->data_payload,split_pos); + fill_pattern(ovlseg, seqovl, dp->seqovl_pattern, sizeof(dp->seqovl_pattern), 0); + memcpy(ovlseg + seqovl, dis->data_payload + from, to - from); seg = ovlseg; } else { - seg = dis->data_payload; - seg_len = split_pos; + seqovl = 0; + seg = dis->data_payload + from; + seg_len = to - from; } pkt1_len = sizeof(pkt1); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq,-seqovl), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, - DF,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), - fooling_orig,dp->desync_ts_increment,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, - seg, seg_len, pkt1, &pkt1_len)) + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, + net32_add(dis->tcp->th_seq, from - seqovl), dis->tcp->th_ack, + dis->tcp->th_win, scale_factor, timestamps, + DF, ttl_orig, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), + fooling_orig, 0, 0, 0, + seg, seg_len, pkt1, &pkt1_len)) goto send_orig; - ip_id=IP4_IP_ID_NEXT(ip_id); - DLOG("sending 1st tcp segment 0-%zu len=%zu seqovl=%u : ",split_pos-1, split_pos, seqovl); - hexdump_limited_dlog(seg,seg_len,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) + ip_id = IP4_IP_ID_NEXT(ip_id); + DLOG("sending multisplit part %d %zu-%zu len=%zu seqovl=%u : ", i + 1, from, to - 1, to - from, seqovl); + hexdump_limited_dlog(seg, seg_len, PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) { #ifdef __linux__ - if (errno==EMSGSIZE && seqovl) + if (errno == EMSGSIZE && seqovl) { DLOG("MTU exceeded. cancelling seqovl.\n"); continue; @@ -2468,107 +2245,407 @@ send_orig_clean: break; } #endif - if (dp->fs_mod.ordering<=1) - { - if (dis->ip) ((struct ip*)fakeseg)->ip_id = ip_id; - ip_id=IP4_IP_ID_NEXT(ip_id); - DLOG("sending fake(2) 1st tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos); - hexdump_limited_dlog(pat,split_pos,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, fakeseg_len)) - goto send_orig; - } - fakeseg_len = sizeof(fakeseg); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq,split_pos), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, - DF,ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), - dp->desync_fooling_mode,dp->desync_ts_increment,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, - pat+split_pos, dis->len_payload-split_pos, fakeseg, &fakeseg_len)) - goto send_orig; - ip_id=IP4_IP_ID_NEXT(ip_id); - DLOG("sending fake(1) 2nd tcp segment %zu-%zu len=%zu : ",split_pos,dis->len_payload-1, dis->len_payload-split_pos); - hexdump_limited_dlog(pat+split_pos,dis->len_payload-split_pos,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, fakeseg_len)) - goto send_orig; - - pkt1_len = sizeof(pkt1); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq,split_pos), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, - DF,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), - fooling_orig,dp->desync_ts_increment,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, - dis->data_payload+split_pos, dis->len_payload-split_pos, pkt1, &pkt1_len)) - goto send_orig; - ip_id=IP4_IP_ID_NEXT(ip_id); - DLOG("sending 2nd tcp segment %zu-%zu len=%zu : ",split_pos,dis->len_payload-1, dis->len_payload-split_pos); - hexdump_limited_dlog(dis->data_payload+split_pos,dis->len_payload-split_pos,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) - goto send_orig; - - if (dp->fs_mod.ordering<=2) - { - if (dis->ip) ((struct ip*)fakeseg)->ip_id = ip_id; - DLOG("sending fake(2) 2nd tcp segment %zu-%zu len=%zu : ",split_pos,dis->len_payload-1, dis->len_payload-split_pos); - hexdump_limited_dlog(pat+split_pos,dis->len_payload-split_pos,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, fakeseg_len)) - goto send_orig; - } - - return VERDICT_DROP; + from = to; } - break; - case DESYNC_IPFRAG2: - if (!reasm_offset) + + if (replay) ctrack_replay->ip_id = ip_id; + + return VERDICT_DROP; + } + else + goto unsplitted_part; + + case DESYNC_MULTIDISORDER: + if (multisplit_count) + { + uint8_t ovlseg[DPI_DESYNC_MAX_FAKE_LEN + 100], *seg; + size_t seg_len, from, to; + unsigned int seqovl; + uint16_t ip_id_end; + + if (replay && ctrack_replay->ip_id) ip_id = ctrack_replay->ip_id; + + ip_id_end = ip_id = IP4_IP_ID_ADD(ip_id, (uint16_t)multisplit_count); + + for (i = multisplit_count - 1, to = dis->len_payload; i >= -1; i--) { - verdict_tcp_csum_fix(verdict, dis->tcp, dis->transport_len, dis->ip, dis->ip6); + from = i >= 0 ? multisplit_pos[i] : 0; - uint8_t *pkt_orig; - size_t pkt_orig_len; - - uint32_t ident = dis->ip ? ip_id ? ip_id : htons(1+random()%0xFFFF) : htonl(1+random()%0xFFFFFFFF); - size_t ipfrag_pos = (dp->desync_ipfrag_pos_tcp && dp->desync_ipfrag_pos_tcptransport_len) ? dp->desync_ipfrag_pos_tcp : 24; + seg = dis->data_payload + from; + seg_len = to - from; + seqovl = 0; + // do seqovl only to the second packet + // otherwise sequence overlap becomes problematic. overlap algorithm is not too obvious. + // real observations revealed that server can receive overlap junk instead of real data + if (i == 0) + { + if (seqovl_pos >= from) + DLOG("seqovl>=split_pos (%zu>=%zu). cancelling seqovl for part %d.\n", seqovl, from, i + 2); + else + { + seqovl = seqovl_pos; + seg_len = to - from + seqovl; + if (seg_len > sizeof(ovlseg)) + { + DLOG("seqovl is too large"); + goto send_orig; + } + fill_pattern(ovlseg, seqovl, dp->seqovl_pattern, sizeof(dp->seqovl_pattern), 0); + memcpy(ovlseg + seqovl, dis->data_payload + from, to - from); + seg = ovlseg; + } + } pkt1_len = sizeof(pkt1); - pkt2_len = sizeof(pkt2); - - if (dis->ip6 && (fooling_orig==FOOL_HOPBYHOP || fooling_orig==FOOL_DESTOPT)) - { - pkt_orig_len = sizeof(pkt3); - if (!ip6_insert_simple_hdr(fooling_orig==FOOL_HOPBYHOP ? IPPROTO_HOPOPTS : IPPROTO_DSTOPTS, dis->data_pkt, dis->len_pkt, pkt3, &pkt_orig_len)) - goto send_orig; - pkt_orig = pkt3; - } - else - { - pkt_orig = dis->data_pkt; - pkt_orig_len = dis->len_pkt; - } - - if (!ip_frag(pkt_orig, pkt_orig_len, ipfrag_pos, ident, pkt1, &pkt1_len, pkt2, &pkt2_len)) + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, + net32_add(dis->tcp->th_seq, from - seqovl), dis->tcp->th_ack, + dis->tcp->th_win, scale_factor, timestamps, + DF, ttl_orig, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), + fooling_orig, 0, 0, 0, + seg, seg_len, pkt1, &pkt1_len)) + goto send_orig; + ip_id = IP4_IP_ID_PREV(ip_id); + DLOG("sending multisplit part %d %zu-%zu len=%zu seqovl=%u : ", i + 2, from, to - 1, to - from, seqovl); + hexdump_limited_dlog(seg, seg_len, PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) goto send_orig; - DLOG("sending 1st ip fragment 0-%zu ip_payload_len=%zu : ", ipfrag_pos-1, ipfrag_pos); - hexdump_limited_dlog(pkt1,pkt1_len,IP_MAXDUMP); DLOG("\n"); - if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) - goto send_orig; - - DLOG("sending 2nd ip fragment %zu-%zu ip_payload_len=%zu : ", ipfrag_pos, dis->transport_len-1, dis->transport_len-ipfrag_pos); - hexdump_limited_dlog(pkt2,pkt2_len,IP_MAXDUMP); DLOG("\n"); - if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt2, pkt2_len)) - goto send_orig; - - return VERDICT_DROP; + to = from; } - default: + + if (replay) ctrack_replay->ip_id = IP4_IP_ID_NEXT(ip_id_end); + + return VERDICT_DROP; + } + else + goto unsplitted_part; + + case DESYNC_FAKEDDISORDER: + { + uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN + 100], fakeseg2[DPI_DESYNC_MAX_FAKE_LEN + 100], pat[DPI_DESYNC_MAX_FAKE_LEN], *seg; + size_t seg_len, fakeseg2_len; + unsigned int seqovl; + int order; + + if (dis->len_payload > sizeof(pat)) + { + DLOG("packet is too large\n"); + goto send_orig; + } + + if (replay && ctrack_replay->ip_id) ip_id = ctrack_replay->ip_id; + + seqovl = 0; + if (split_pos) + { + order = dp->fs_mod.ordering & 3; + if (seqovl_pos >= split_pos) + DLOG("seqovl>=split_pos (%zu>=%zu). cancelling seqovl.\n", seqovl_pos, split_pos); + else + seqovl = seqovl_pos; + ip_id = IP4_IP_ID_NEXT(ip_id); + } + else + { + order = (dp->fs_mod.ordering >> 3) & 3; + } + + fill_pattern(pat, dis->len_payload, dp->fsplit_pattern, dp->fsplit_pattern_size, reasm_offset); + + if (seqovl) + { + seg_len = dis->len_payload - split_pos + seqovl; + if (seg_len > sizeof(fakeseg)) + { + DLOG("seqovl is too large\n"); + goto send_orig; + } + fill_pattern(fakeseg, seqovl, dp->seqovl_pattern, sizeof(dp->seqovl_pattern), 0); + memcpy(fakeseg + seqovl, dis->data_payload + split_pos, dis->len_payload - split_pos); + seg = fakeseg; + } + else + { + seg = dis->data_payload + split_pos; + seg_len = dis->len_payload - split_pos; + } + + fakeseg2_len = sizeof(fakeseg2); + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq, split_pos), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, + DF, ttl_fake, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), + dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment, + pat + split_pos, dis->len_payload - split_pos, fakeseg2, &fakeseg2_len)) + goto send_orig; + + if (order == 0) + { + DLOG("sending fake(1) 2nd out-of-order tcp segment %zu-%zu len=%zu : ", split_pos, dis->len_payload - 1, dis->len_payload - split_pos); + hexdump_limited_dlog(pat + split_pos, dis->len_payload - split_pos, PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg2, fakeseg2_len)) + goto send_orig; + } + + pkt1_len = sizeof(pkt1); + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq, split_pos - seqovl), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, + DF, ttl_orig, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), + fooling_orig, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment, + seg, seg_len, pkt1, &pkt1_len)) + goto send_orig; + DLOG("sending 2nd out-of-order tcp segment %zu-%zu len=%zu seqovl=%u : ", split_pos, dis->len_payload - 1, dis->len_payload - split_pos, seqovl); + hexdump_limited_dlog(seg, seg_len, PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) + goto send_orig; + + if (order <= 1) + { + DLOG("sending fake(2) 2nd out-of-order tcp segment %zu-%zu len=%zu : ", split_pos, dis->len_payload - 1, dis->len_payload - split_pos); + hexdump_limited_dlog(pat + split_pos, dis->len_payload - split_pos, PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg2, fakeseg2_len)) + goto send_orig; + } + + if (split_pos) + { + ip_id = IP4_IP_ID_PREV(ip_id); + + seg_len = sizeof(fakeseg); + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, + DF, ttl_fake, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), + dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment, + pat, split_pos, fakeseg, &seg_len)) + goto send_orig; + DLOG("sending fake(1) 1st out-of-order tcp segment 0-%zu len=%zu : ", split_pos - 1, split_pos); + hexdump_limited_dlog(pat, split_pos, PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, seg_len)) + goto send_orig; + + pkt1_len = sizeof(pkt1); + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, + DF, ttl_orig, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), + fooling_orig, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment, + dis->data_payload, split_pos, pkt1, &pkt1_len)) + goto send_orig; + DLOG("sending 1st out-of-order tcp segment 0-%zu len=%zu : ", split_pos - 1, split_pos); + hexdump_limited_dlog(dis->data_payload, split_pos, PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) + goto send_orig; + + if (order <= 2) + { + DLOG("sending fake(2) 1st out-of-order tcp segment 0-%zu len=%zu : ", split_pos - 1, split_pos); + hexdump_limited_dlog(pat, split_pos, PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, seg_len)) + goto send_orig; + } + } + + if (replay) ctrack_replay->ip_id = IP4_IP_ID_NEXT(ip_id); + + return VERDICT_DROP; + } + + case DESYNC_FAKEDSPLIT: + { + uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN + 100], ovlseg[DPI_DESYNC_MAX_FAKE_LEN + 100], pat[DPI_DESYNC_MAX_FAKE_LEN], *seg; + size_t fakeseg_len, seg_len; + int order; + + if (replay && ctrack_replay->ip_id) ip_id = ctrack_replay->ip_id; + + if (dis->len_payload > sizeof(pat)) + { + DLOG("packet is too large\n"); + goto send_orig; + } + + fill_pattern(pat, dis->len_payload, dp->fsplit_pattern, dp->fsplit_pattern_size, reasm_offset); + + if (split_pos) + { + order = dp->fs_mod.ordering & 3; + } + else + { + order = (dp->fs_mod.ordering >> 3) & 3; + split_pos = dis->len_payload; + } + + fakeseg_len = sizeof(fakeseg); + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, + DF, ttl_fake, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), + dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment, + pat, split_pos, fakeseg, &fakeseg_len)) + goto send_orig; + + if (order == 0) + { + DLOG("sending fake(1) 1st tcp segment 0-%zu len=%zu : ", split_pos - 1, split_pos); + hexdump_limited_dlog(pat, split_pos, PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, fakeseg_len)) + goto send_orig; + } + + unsigned int seqovl = (reasm_offset || split_pos>=dis->len_payload) ? 0 : seqovl_pos; +#ifdef __linux__ + // only linux return error if MTU is exceeded + for (;; seqovl = 0) + { +#endif + if (seqovl) + { + seg_len = split_pos + seqovl; + if (seg_len > sizeof(ovlseg)) + { + DLOG("seqovl is too large\n"); + goto send_orig; + } + fill_pattern(ovlseg, seqovl, dp->seqovl_pattern, sizeof(dp->seqovl_pattern), 0); + memcpy(ovlseg + seqovl, dis->data_payload, split_pos); + seg = ovlseg; + } + else + { + seg = dis->data_payload; + seg_len = split_pos; + } + + pkt1_len = sizeof(pkt1); + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq, -seqovl), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, + DF, ttl_orig, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), + fooling_orig, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment, + seg, seg_len, pkt1, &pkt1_len)) + goto send_orig; + ip_id = IP4_IP_ID_NEXT(ip_id); + DLOG("sending 1st tcp segment 0-%zu len=%zu seqovl=%u : ", split_pos - 1, split_pos, seqovl); + hexdump_limited_dlog(seg, seg_len, PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) + { +#ifdef __linux__ + if (errno == EMSGSIZE && seqovl) + { + DLOG("MTU exceeded. cancelling seqovl.\n"); + continue; + } +#endif + goto send_orig; + } +#ifdef __linux__ break; + } +#endif + if (order <= 1) + { + DLOG("sending fake(2) 1st tcp segment 0-%zu len=%zu : ", split_pos - 1, split_pos); + hexdump_limited_dlog(pat, split_pos, PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, fakeseg_len)) + goto send_orig; + } + + if (split_pos < dis->len_payload) + { + fakeseg_len = sizeof(fakeseg); + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq, split_pos), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, + DF, ttl_fake, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), + dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment, + pat + split_pos, dis->len_payload - split_pos, fakeseg, &fakeseg_len)) + goto send_orig; + DLOG("sending fake(1) 2nd tcp segment %zu-%zu len=%zu : ", split_pos, dis->len_payload - 1, dis->len_payload - split_pos); + hexdump_limited_dlog(pat + split_pos, dis->len_payload - split_pos, PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, fakeseg_len)) + goto send_orig; + + pkt1_len = sizeof(pkt1); + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq, split_pos), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, + DF, ttl_orig, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), + fooling_orig, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment, + dis->data_payload + split_pos, dis->len_payload - split_pos, pkt1, &pkt1_len)) + goto send_orig; + ip_id = IP4_IP_ID_NEXT(ip_id); + DLOG("sending 2nd tcp segment %zu-%zu len=%zu : ", split_pos, dis->len_payload - 1, dis->len_payload - split_pos); + hexdump_limited_dlog(dis->data_payload + split_pos, dis->len_payload - split_pos, PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) + goto send_orig; + + if (order <= 2) + { + DLOG("sending fake(2) 2nd tcp segment %zu-%zu len=%zu : ", split_pos, dis->len_payload - 1, dis->len_payload - split_pos); + hexdump_limited_dlog(pat + split_pos, dis->len_payload - split_pos, PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, fakeseg_len)) + goto send_orig; + } + } + + if (replay) ctrack_replay->ip_id = ip_id; + + return VERDICT_DROP; + } + case DESYNC_IPFRAG2: + if (!reasm_offset) + { + verdict_tcp_csum_fix(verdict, dis->tcp, dis->transport_len, dis->ip, dis->ip6); + + uint8_t *pkt_orig; + size_t pkt_orig_len; + + uint32_t ident = dis->ip ? ip_id ? ip_id : htons(1 + random() % 0xFFFF) : htonl(1 + random() % 0xFFFFFFFF); + size_t ipfrag_pos = (dp->desync_ipfrag_pos_tcp && dp->desync_ipfrag_pos_tcp < dis->transport_len) ? dp->desync_ipfrag_pos_tcp : 24; + + pkt1_len = sizeof(pkt1); + pkt2_len = sizeof(pkt2); + + if (dis->ip6 && (fooling_orig == FOOL_HOPBYHOP || fooling_orig == FOOL_DESTOPT)) + { + pkt_orig_len = sizeof(pkt3); + if (!ip6_insert_simple_hdr(fooling_orig == FOOL_HOPBYHOP ? IPPROTO_HOPOPTS : IPPROTO_DSTOPTS, dis->data_pkt, dis->len_pkt, pkt3, &pkt_orig_len)) + goto send_orig; + pkt_orig = pkt3; + } + else + { + pkt_orig = dis->data_pkt; + pkt_orig_len = dis->len_pkt; + } + + if (!ip_frag(pkt_orig, pkt_orig_len, ipfrag_pos, ident, pkt1, &pkt1_len, pkt2, &pkt2_len)) + goto send_orig; + + DLOG("sending 1st ip fragment 0-%zu ip_payload_len=%zu : ", ipfrag_pos - 1, ipfrag_pos); + hexdump_limited_dlog(pkt1, pkt1_len, IP_MAXDUMP); DLOG("\n"); + if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) + goto send_orig; + + DLOG("sending 2nd ip fragment %zu-%zu ip_payload_len=%zu : ", ipfrag_pos, dis->transport_len - 1, dis->transport_len - ipfrag_pos); + hexdump_limited_dlog(pkt2, pkt2_len, IP_MAXDUMP); DLOG("\n"); + if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt2, pkt2_len)) + goto send_orig; + + return VERDICT_DROP; + } + default: + break; } } send_orig: - if ((verdict & VERDICT_MASK)==VERDICT_DROP) + if ((verdict & VERDICT_MASK) == VERDICT_DROP) verdict = ct_new_postnat_fix(ctrack, dis->ip, dis->ip6, dis->tcp); else - if (tcp_orig_send(verdict,desync_fwmark,ifout,dp,ctrack_replay,dis,bFake)) + if (tcp_orig_send(verdict, desync_fwmark, ifout, dp, ctrack_replay, dis, bFake)) verdict = ct_new_postnat_fix(ctrack, dis->ip, dis->ip6, dis->tcp); return verdict; + +unsplitted_part: + if (replay && dis->ip && ctrack_replay->ip_id) + { + DLOG("changing ip_id of unsplitted part\n"); + dis->ip->ip_id = ctrack_replay->ip_id; + ctrack_replay->ip_id = IP4_IP_ID_NEXT(ctrack_replay->ip_id); + return VERDICT_MODIFY; + } + goto send_orig; + } // return : true - should continue, false - should stop with verdict @@ -2577,33 +2654,33 @@ static bool quic_reasm_cancel(t_ctrack *ctrack, const char *reason) reasm_orig_cancel(ctrack); if (ctrack && ctrack->dp && ctrack->dp->desync_any_proto) { - DLOG("%s. applying tampering because desync_any_proto is set\n",reason); + DLOG("%s. applying tampering because desync_any_proto is set\n", reason); return true; } else { - DLOG("%s. not applying tampering because desync_any_proto is not set\n",reason); + DLOG("%s. not applying tampering because desync_any_proto is not set\n", reason); return false; } } static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint32_t fwmark, const char *ifin, const char *ifout, struct dissect *dis) { - uint8_t verdict=VERDICT_PASS; + uint8_t verdict = VERDICT_PASS; // additional safety check if (!!dis->ip == !!dis->ip6) return verdict; struct desync_profile *dp = NULL; - t_ctrack *ctrack=NULL, *ctrack_replay=NULL; - bool bReverse=false; + t_ctrack *ctrack = NULL, *ctrack_replay = NULL; + bool bReverse = false; bool bFake = false; struct sockaddr_storage src, dst; - uint8_t pkt1[DPI_DESYNC_MAX_FAKE_LEN+100], pkt2[DPI_DESYNC_MAX_FAKE_LEN+100], pkt3[DPI_DESYNC_MAX_FAKE_LEN+100]; + uint8_t pkt1[DPI_DESYNC_MAX_FAKE_LEN + 100], pkt2[DPI_DESYNC_MAX_FAKE_LEN + 100], pkt3[DPI_DESYNC_MAX_FAKE_LEN + 100]; size_t pkt1_len, pkt2_len; - uint8_t ttl_orig,ttl_fake; + uint8_t ttl_orig, ttl_fake; bool DF; char host[256]; t_l7proto l7proto = UNKNOWN; @@ -2622,17 +2699,17 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint ifname = bReverse ? ifin : ifout; #ifdef HAS_FILTER_SSID ssid = wlan_ssid_search_ifname(ifname); - if (ssid) DLOG("found ssid for %s : %s\n",ifname,ssid); + if (ssid) DLOG("found ssid for %s : %s\n", ifname, ssid); #endif dp = ctrack_replay->dp; if (dp) - DLOG("using cached desync profile %d\n",dp->n); + DLOG("using cached desync profile %d\n", dp->n); else if (!ctrack_replay->dp_search_complete) { if (!ctrack_replay->hostname && !bReverse) { - if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL,dis->ip6 ? &dis->ip6->ip6_dst : NULL , host, sizeof(host), &ctrack_replay->hostname_is_ip) && *host) + if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL, host, sizeof(host), &ctrack_replay->hostname_is_ip) && *host) if (!(ctrack_replay->hostname = strdup(host))) DLOG_ERR("strdup(host): out of memory\n"); } @@ -2661,10 +2738,10 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint ifname = bReverse ? ifin : ifout; #ifdef HAS_FILTER_SSID ssid = wlan_ssid_search_ifname(ifname); - if (ssid) DLOG("found ssid for %s : %s\n",ifname,ssid); + if (ssid) DLOG("found ssid for %s : %s\n", ifname, ssid); #endif if (dp) - DLOG("using cached desync profile %d\n",dp->n); + DLOG("using cached desync profile %d\n", dp->n); else if (!ctrack || !ctrack->dp_search_complete) { const char *hostname = NULL; @@ -2675,7 +2752,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint hostname_is_ip = ctrack->hostname_is_ip; if (!hostname && !bReverse) { - if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL,dis->ip6 ? &dis->ip6->ip6_dst : NULL , host, sizeof(host), &hostname_is_ip) && *host) + if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL, host, sizeof(host), &hostname_is_ip) && *host) if (!(hostname = ctrack_replay->hostname = strdup(host))) DLOG_ERR("strdup(host): out of memory\n"); } @@ -2696,7 +2773,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint HostFailPoolPurgeRateLimited(&dp->hostlist_auto_fail_counters); //ConntrackPoolDump(¶ms.conntrack); - + if (bReverse) { if (ctrack) @@ -2704,17 +2781,17 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint ttl_orig = dis->ip ? dis->ip->ip_ttl : dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim; if (!ctrack->incoming_ttl) { - DLOG("incoming TTL %u\n",ttl_orig); + DLOG("incoming TTL %u\n", ttl_orig); ctrack->incoming_ttl = ttl_orig; - autottl_rediscover(ctrack,dis->ip ? &dis->ip->ip_src : NULL,dis->ip6 ? &dis->ip6->ip6_src : NULL , ifin); + autottl_rediscover(ctrack, dis->ip ? &dis->ip->ip_src : NULL, dis->ip6 ? &dis->ip6->ip6_src : NULL, ifin); } } return verdict; // nothing to do. do not waste cpu } - autottl_discover(ctrack,dis->ip ? &dis->ip->ip_dst : NULL,dis->ip6 ? &dis->ip6->ip6_dst : NULL , ifout); + autottl_discover(ctrack, dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL, ifout); - if (orig_mod(dp,ctrack,dis)) // ttl can change ! + if (orig_mod(dp, ctrack, dis)) // ttl can change ! verdict = VERDICT_MODIFY; // start and cutoff limiters @@ -2728,14 +2805,14 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint if (dis->len_payload) { struct blob_collection_head *fake; - bool bHaveHost=false, bHostIsIp=false; + bool bHaveHost = false, bHostIsIp = false; uint16_t ip_id = IP4_IP_ID_FIX(dis->ip); - if (IsQUICInitial(dis->data_payload,dis->len_payload)) + if (IsQUICInitial(dis->data_payload, dis->len_payload)) { DLOG("packet contains QUIC initial\n"); l7proto = QUIC; - if (ctrack && ctrack->l7proto==UNKNOWN) ctrack->l7proto = l7proto; + if (ctrack && ctrack->l7proto == UNKNOWN) ctrack->l7proto = l7proto; uint8_t clean[16384], *pclean; size_t clean_len; @@ -2748,7 +2825,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint else { clean_len = sizeof(clean); - pclean = QUICDecryptInitial(dis->data_payload,dis->len_payload,clean,&clean_len) ? clean : NULL; + pclean = QUICDecryptInitial(dis->data_payload, dis->len_payload, clean, &clean_len) ? clean : NULL; } if (pclean) { @@ -2756,7 +2833,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint { if (ReasmHasSpace(&ctrack->reasm_orig, clean_len)) { - reasm_orig_feed(ctrack,IPPROTO_UDP,clean,clean_len); + reasm_orig_feed(ctrack, IPPROTO_UDP, clean, clean_len); pclean = ctrack->reasm_orig.packet; clean_len = ctrack->reasm_orig.size_present; } @@ -2770,25 +2847,25 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint uint8_t defrag[UDP_MAX_REASM]; size_t hello_offset, hello_len, defrag_len = sizeof(defrag); bool bFull; - if (QUICDefragCrypto(pclean,clean_len,defrag,&defrag_len,&bFull)) + if (QUICDefragCrypto(pclean, clean_len, defrag, &defrag_len, &bFull)) { if (bFull) { DLOG("QUIC initial contains CRYPTO with full fragment coverage\n"); bool bIsHello = IsQUICCryptoHello(defrag, defrag_len, &hello_offset, &hello_len); - bool bReqFull = bIsHello ? IsTLSHandshakeFull(defrag+hello_offset,hello_len) : false; + bool bReqFull = bIsHello ? IsTLSHandshakeFull(defrag + hello_offset, hello_len) : false; DLOG(bIsHello ? bReqFull ? "packet contains full TLS ClientHello\n" : "packet contains partial TLS ClientHello\n" : "packet does not contain TLS ClientHello\n"); - if (bReqFull) TLSDebugHandshake(defrag+hello_offset,hello_len); + if (bReqFull) TLSDebugHandshake(defrag + hello_offset, hello_len); if (ctrack) { if (bIsHello && !bReqFull && ReasmIsEmpty(&ctrack->reasm_orig)) { // preallocate max buffer to avoid reallocs that cause memory copy - if (!reasm_orig_start(ctrack,IPPROTO_UDP,UDP_MAX_REASM,UDP_MAX_REASM,clean,clean_len)) + if (!reasm_orig_start(ctrack, IPPROTO_UDP, UDP_MAX_REASM, UDP_MAX_REASM, clean, clean_len)) { reasm_orig_cancel(ctrack); goto send_orig; @@ -2828,7 +2905,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint } else { - if (!quic_reasm_cancel(ctrack,"QUIC initial without ClientHello")) goto send_orig; + if (!quic_reasm_cancel(ctrack, "QUIC initial without ClientHello")) goto send_orig; } } else @@ -2839,7 +2916,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint if (ReasmIsEmpty(&ctrack->reasm_orig)) { // preallocate max buffer to avoid reallocs that cause memory copy - if (!reasm_orig_start(ctrack,IPPROTO_UDP,UDP_MAX_REASM,UDP_MAX_REASM,clean,clean_len)) + if (!reasm_orig_start(ctrack, IPPROTO_UDP, UDP_MAX_REASM, UDP_MAX_REASM, clean, clean_len)) { reasm_orig_cancel(ctrack); goto send_orig; @@ -2858,19 +2935,19 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint } return ct_new_postnat_fix(ctrack, dis->ip, dis->ip6, NULL); } - if (!quic_reasm_cancel(ctrack,"QUIC initial fragmented CRYPTO")) goto send_orig; + if (!quic_reasm_cancel(ctrack, "QUIC initial fragmented CRYPTO")) goto send_orig; } } else { // defrag failed - if (!quic_reasm_cancel(ctrack,"QUIC initial defrag CRYPTO failed")) goto send_orig; + if (!quic_reasm_cancel(ctrack, "QUIC initial defrag CRYPTO failed")) goto send_orig; } } else { // decrypt failed - if (!quic_reasm_cancel(ctrack,"QUIC initial decryption failed")) goto send_orig; + if (!quic_reasm_cancel(ctrack, "QUIC initial decryption failed")) goto send_orig; } } else // not QUIC initial @@ -2880,29 +2957,29 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint reasm_orig_cancel(ctrack); - if (IsWireguardHandshakeInitiation(dis->data_payload,dis->len_payload)) + if (IsWireguardHandshakeInitiation(dis->data_payload, dis->len_payload)) { DLOG("packet contains wireguard handshake initiation\n"); l7proto = WIREGUARD; - if (ctrack && ctrack->l7proto==UNKNOWN) ctrack->l7proto = l7proto; + if (ctrack && ctrack->l7proto == UNKNOWN) ctrack->l7proto = l7proto; } - else if (IsDhtD1(dis->data_payload,dis->len_payload)) + else if (IsDhtD1(dis->data_payload, dis->len_payload)) { DLOG("packet contains DHT d1...e\n"); l7proto = DHT; - if (ctrack && ctrack->l7proto==UNKNOWN) ctrack->l7proto = l7proto; + if (ctrack && ctrack->l7proto == UNKNOWN) ctrack->l7proto = l7proto; } - else if (IsDiscordIpDiscoveryRequest(dis->data_payload,dis->len_payload)) + else if (IsDiscordIpDiscoveryRequest(dis->data_payload, dis->len_payload)) { DLOG("packet contains discord voice IP discovery\n"); l7proto = DISCORD; - if (ctrack && ctrack->l7proto==UNKNOWN) ctrack->l7proto = l7proto; + if (ctrack && ctrack->l7proto == UNKNOWN) ctrack->l7proto = l7proto; } - else if (IsStunMessage(dis->data_payload,dis->len_payload)) + else if (IsStunMessage(dis->data_payload, dis->len_payload)) { DLOG("packet contains STUN message\n"); l7proto = STUN; - if (ctrack && ctrack->l7proto==UNKNOWN) ctrack->l7proto = l7proto; + if (ctrack && ctrack->l7proto == UNKNOWN) ctrack->l7proto = l7proto; } else { @@ -2917,18 +2994,18 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint if (bHaveHost) { - bHostIsIp=strip_host_to_ip(host); - DLOG("hostname: %s\n",host); + bHostIsIp = strip_host_to_ip(host); + DLOG("hostname: %s\n", host); } bool bDiscoveredL7; if (ctrack_replay) { - bDiscoveredL7 = !ctrack_replay->l7proto_discovered && ctrack_replay->l7proto!=UNKNOWN; - ctrack_replay->l7proto_discovered=true; + bDiscoveredL7 = !ctrack_replay->l7proto_discovered && ctrack_replay->l7proto != UNKNOWN; + ctrack_replay->l7proto_discovered = true; } else - bDiscoveredL7 = !ctrack_replay && l7proto!=UNKNOWN; + bDiscoveredL7 = !ctrack_replay && l7proto != UNKNOWN; if (bDiscoveredL7) DLOG("discovered l7 protocol\n"); bool bDiscoveredHostname = bHaveHost && !(ctrack_replay && ctrack_replay->hostname_discovered); @@ -2937,21 +3014,21 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint DLOG("discovered hostname\n"); if (ctrack_replay) { - ctrack_replay->hostname_discovered=true; + ctrack_replay->hostname_discovered = true; free(ctrack_replay->hostname); - ctrack_replay->hostname=strdup(host); + ctrack_replay->hostname = strdup(host); ctrack_replay->hostname_is_ip = bHostIsIp; if (!ctrack_replay->hostname) { DLOG_ERR("hostname dup : out of memory"); goto send_orig; } - if (!ipcache_put_hostname(dis->ip ? &dis->ip->ip_dst : NULL,dis->ip6 ? &dis->ip6->ip6_dst : NULL , host, bHostIsIp)) + if (!ipcache_put_hostname(dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL, host, bHostIsIp)) goto send_orig; } } - bool bCheckDone=false, bCheckResult=false, bCheckExcluded=false; + bool bCheckDone = false, bCheckResult = false, bCheckExcluded = false; if (bDiscoveredL7 || bDiscoveredHostname) { struct desync_profile *dp_prev = dp; @@ -2974,20 +3051,20 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint reasm_orig_cancel(ctrack); goto send_orig; } - if (dp!=dp_prev) + if (dp != dp_prev) { DLOG("desync profile changed by revealed l7 protocol or hostname !\n"); - autottl_rediscover(ctrack_replay,dis->ip ? &dis->ip->ip_dst : NULL,dis->ip6 ? &dis->ip6->ip6_dst : NULL , ifout); + autottl_rediscover(ctrack_replay, dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL, ifout); // re-evaluate start/cutoff limiters if (replay) { - if (orig_mod(dp,ctrack_replay,dis)) // ttl can change ! + if (orig_mod(dp, ctrack_replay, dis)) // ttl can change ! verdict = VERDICT_MODIFY; } else { maybe_cutoff(ctrack, IPPROTO_UDP); - if (orig_mod(dp,ctrack,dis)) // ttl can change ! + if (orig_mod(dp, ctrack, dis)) // ttl can change ! verdict = VERDICT_MODIFY; if (!process_desync_interval(dp, ctrack)) goto send_orig; } @@ -3024,26 +3101,26 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint } // desync profile may have changed after hostname was revealed - switch(l7proto) + switch (l7proto) { - case QUIC: - fake = &dp->fake_quic; - break; - case WIREGUARD: - fake = &dp->fake_wg; - break; - case DHT: - fake = &dp->fake_dht; - break; - case DISCORD: - fake = &dp->fake_discord; - break; - case STUN: - fake = &dp->fake_stun; - break; - default: - fake = &dp->fake_unknown_udp; - break; + case QUIC: + fake = &dp->fake_quic; + break; + case WIREGUARD: + fake = &dp->fake_wg; + break; + case DHT: + fake = &dp->fake_dht; + break; + case DISCORD: + fake = &dp->fake_discord; + break; + case STUN: + fake = &dp->fake_stun; + break; + default: + fake = &dp->fake_unknown_udp; + break; } ttl_fake = (ctrack_replay && ctrack_replay->desync_autottl) ? ctrack_replay->desync_autottl : (dis->ip6 ? (dp->desync_ttl6 ? dp->desync_ttl6 : ttl_orig) : (dp->desync_ttl ? dp->desync_ttl : ttl_orig)); @@ -3052,175 +3129,175 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint if (params.debug) { - char s1[48],s2[48]; + char s1[48], s2[48]; ntop46_port((struct sockaddr *)&src, s1, sizeof(s1)); ntop46_port((struct sockaddr *)&dst, s2, sizeof(s2)); - DLOG("dpi desync src=%s dst=%s\n",s1,s2); + DLOG("dpi desync src=%s dst=%s\n", s1, s2); } - switch(dp->desync_mode) + switch (dp->desync_mode) { - case DESYNC_FAKE_KNOWN: - if (l7proto==UNKNOWN) - { - DLOG("not applying fake because of unknown protocol\n"); - break; - } - case DESYNC_FAKE: - if (!reasm_offset) - { - size_t fake_size; - uint8_t *fake_data; - struct blob_item *fake_item; - int n=0; - - LIST_FOREACH(fake_item, fake, next) - { - n++; - - fake_data=fake_item->data + fake_item->offset; - fake_size=fake_item->size - fake_item->offset; - - pkt1_len = sizeof(pkt1); - if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, - DF,ttl_fake, IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), - dp->desync_fooling_mode, NULL, 0, 0, - fake_data, fake_size, pkt1, &pkt1_len)) - { - goto send_orig; - } - DLOG("sending fake[%d] : ", n); - hexdump_limited_dlog(fake_data,fake_size,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) - goto send_orig; - ip_id=IP4_IP_ID_NEXT(ip_id); - } - bFake = true; - } + case DESYNC_FAKE_KNOWN: + if (l7proto == UNKNOWN) + { + DLOG("not applying fake because of unknown protocol\n"); break; - case DESYNC_HOPBYHOP: - case DESYNC_DESTOPT: - case DESYNC_IPFRAG1: - fooling_orig = (dp->desync_mode==DESYNC_HOPBYHOP) ? FOOL_HOPBYHOP : (dp->desync_mode==DESYNC_DESTOPT) ? FOOL_DESTOPT : FOOL_IPFRAG1; - if (dis->ip6 && (dp->desync_mode2==DESYNC_NONE || !desync_valid_second_stage_udp(dp->desync_mode2))) + } + case DESYNC_FAKE: + if (!reasm_offset) + { + size_t fake_size; + uint8_t *fake_data; + struct blob_item *fake_item; + int n = 0; + + LIST_FOREACH(fake_item, fake, next) { + n++; + + fake_data = fake_item->data + fake_item->offset; + fake_size = fake_item->size - fake_item->offset; + pkt1_len = sizeof(pkt1); if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, - DF,ttl_orig,0,0,IP6_FLOW(dis->ip6),fooling_orig,NULL,0,0, - dis->data_payload, dis->len_payload, pkt1, &pkt1_len)) + DF, ttl_fake, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), + dp->desync_fooling_mode, NULL, 0, 0, + fake_data, fake_size, pkt1, &pkt1_len)) { goto send_orig; } - DLOG("resending original packet with extension header\n"); - if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) + DLOG("sending fake[%d] : ", n); + hexdump_limited_dlog(fake_data, fake_size, PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) goto send_orig; - // this mode is final, no other options available - return ct_new_postnat_fix(ctrack, dis->ip, dis->ip6, NULL); + ip_id = IP4_IP_ID_NEXT(ip_id); } - break; - default: - pkt1_len=0; - break; + bFake = true; + } + break; + case DESYNC_HOPBYHOP: + case DESYNC_DESTOPT: + case DESYNC_IPFRAG1: + fooling_orig = (dp->desync_mode == DESYNC_HOPBYHOP) ? FOOL_HOPBYHOP : (dp->desync_mode == DESYNC_DESTOPT) ? FOOL_DESTOPT : FOOL_IPFRAG1; + if (dis->ip6 && (dp->desync_mode2 == DESYNC_NONE || !desync_valid_second_stage_udp(dp->desync_mode2))) + { + pkt1_len = sizeof(pkt1); + if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, + DF, ttl_orig, 0, 0, IP6_FLOW(dis->ip6), fooling_orig, NULL, 0, 0, + dis->data_payload, dis->len_payload, pkt1, &pkt1_len)) + { + goto send_orig; + } + DLOG("resending original packet with extension header\n"); + if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) + goto send_orig; + // this mode is final, no other options available + return ct_new_postnat_fix(ctrack, dis->ip, dis->ip6, NULL); + } + break; + default: + pkt1_len = 0; + break; } - enum dpi_desync_mode desync_mode = dp->desync_mode2==DESYNC_NONE ? dp->desync_mode : dp->desync_mode2; - switch(desync_mode) + enum dpi_desync_mode desync_mode = dp->desync_mode2 == DESYNC_NONE ? dp->desync_mode : dp->desync_mode2; + switch (desync_mode) { - case DESYNC_UDPLEN: + case DESYNC_UDPLEN: + pkt1_len = sizeof(pkt1); + if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, DF, ttl_orig, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), fooling_orig, dp->udplen_pattern, sizeof(dp->udplen_pattern), dp->udplen_increment, dis->data_payload, dis->len_payload, pkt1, &pkt1_len)) + { + DLOG("could not construct packet with modified length. too large ?\n"); + break; + } + DLOG("resending original packet with increased by %d length\n", dp->udplen_increment); + if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) + goto send_orig; + return ct_new_postnat_fix(ctrack, dis->ip, dis->ip6, NULL); + case DESYNC_TAMPER: + if (IsDhtD1(dis->data_payload, dis->len_payload)) + { + size_t szbuf, szcopy; + memcpy(pkt2, "d2:001:x", 8); + pkt2_len = 8; + szbuf = sizeof(pkt2) - pkt2_len; + szcopy = dis->len_payload - 1; + if (szcopy > szbuf) + { + DLOG("packet is too long to tamper"); + break; + } + memcpy(pkt2 + pkt2_len, dis->data_payload + 1, szcopy); + pkt2_len += szcopy; pkt1_len = sizeof(pkt1); - if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, DF, ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), fooling_orig, dp->udplen_pattern, sizeof(dp->udplen_pattern), dp->udplen_increment, dis->data_payload, dis->len_payload, pkt1, &pkt1_len)) + if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, DF, ttl_orig, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), fooling_orig, NULL, 0, 0, pkt2, pkt2_len, pkt1, &pkt1_len)) { DLOG("could not construct packet with modified length. too large ?\n"); break; } - DLOG("resending original packet with increased by %d length\n", dp->udplen_increment); - if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) + DLOG("resending tampered DHT\n"); + if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) goto send_orig; return ct_new_postnat_fix(ctrack, dis->ip, dis->ip6, NULL); - case DESYNC_TAMPER: - if (IsDhtD1(dis->data_payload,dis->len_payload)) - { - size_t szbuf,szcopy; - memcpy(pkt2,"d2:001:x",8); - pkt2_len=8; - szbuf=sizeof(pkt2)-pkt2_len; - szcopy=dis->len_payload-1; - if (szcopy>szbuf) - { - DLOG("packet is too long to tamper"); - break; - } - memcpy(pkt2+pkt2_len,dis->data_payload+1,szcopy); - pkt2_len+=szcopy; - pkt1_len = sizeof(pkt1); - if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, DF, ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), fooling_orig, NULL, 0 , 0, pkt2, pkt2_len, pkt1, &pkt1_len)) - { - DLOG("could not construct packet with modified length. too large ?\n"); - break; - } - DLOG("resending tampered DHT\n"); - if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) - goto send_orig; - return ct_new_postnat_fix(ctrack, dis->ip, dis->ip6, NULL); - } - else - { - DLOG("payload is not tamperable\n"); - break; - } - case DESYNC_IPFRAG2: - { - verdict_udp_csum_fix(verdict, dis->udp, dis->transport_len, dis->ip, dis->ip6); - - uint8_t *pkt_orig; - size_t pkt_orig_len; - - // freebsd do not set ip.id - ip_id = IP4_IP_ID_FIX(dis->ip); - uint32_t ident = dis->ip ? ip_id ? ip_id : htons(1+random()%0xFFFF) : htonl(1+random()%0xFFFFFFFF); - size_t ipfrag_pos = (dp->desync_ipfrag_pos_udp && dp->desync_ipfrag_pos_udptransport_len) ? dp->desync_ipfrag_pos_udp : sizeof(struct udphdr); - - pkt1_len = sizeof(pkt1); - pkt2_len = sizeof(pkt2); - - if (dis->ip6 && (fooling_orig==FOOL_HOPBYHOP || fooling_orig==FOOL_DESTOPT)) - { - pkt_orig_len = sizeof(pkt3); - if (!ip6_insert_simple_hdr(fooling_orig==FOOL_HOPBYHOP ? IPPROTO_HOPOPTS : IPPROTO_DSTOPTS, dis->data_pkt, dis->len_pkt, pkt3, &pkt_orig_len)) - goto send_orig; - pkt_orig = pkt3; - } - else - { - pkt_orig = dis->data_pkt; - pkt_orig_len = dis->len_pkt; - } - - if (!ip_frag(pkt_orig, pkt_orig_len, ipfrag_pos, ident, pkt1, &pkt1_len, pkt2, &pkt2_len)) - goto send_orig; - - DLOG("sending 1st ip fragment 0-%zu ip_payload_len=%zu : ", ipfrag_pos-1, ipfrag_pos); - hexdump_limited_dlog(pkt1,pkt1_len,IP_MAXDUMP); DLOG("\n"); - if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) - goto send_orig; - - DLOG("sending 2nd ip fragment %zu-%zu ip_payload_len=%zu : ", ipfrag_pos, dis->transport_len-1, dis->transport_len-ipfrag_pos); - hexdump_limited_dlog(pkt2,pkt2_len,IP_MAXDUMP); DLOG("\n"); - if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt2, pkt2_len)) - goto send_orig; - - return ct_new_postnat_fix(ctrack, dis->ip, dis->ip6, NULL); - } - default: + } + else + { + DLOG("payload is not tamperable\n"); break; + } + case DESYNC_IPFRAG2: + { + verdict_udp_csum_fix(verdict, dis->udp, dis->transport_len, dis->ip, dis->ip6); + + uint8_t *pkt_orig; + size_t pkt_orig_len; + + // freebsd do not set ip.id + ip_id = IP4_IP_ID_FIX(dis->ip); + uint32_t ident = dis->ip ? ip_id ? ip_id : htons(1 + random() % 0xFFFF) : htonl(1 + random() % 0xFFFFFFFF); + size_t ipfrag_pos = (dp->desync_ipfrag_pos_udp && dp->desync_ipfrag_pos_udp < dis->transport_len) ? dp->desync_ipfrag_pos_udp : sizeof(struct udphdr); + + pkt1_len = sizeof(pkt1); + pkt2_len = sizeof(pkt2); + + if (dis->ip6 && (fooling_orig == FOOL_HOPBYHOP || fooling_orig == FOOL_DESTOPT)) + { + pkt_orig_len = sizeof(pkt3); + if (!ip6_insert_simple_hdr(fooling_orig == FOOL_HOPBYHOP ? IPPROTO_HOPOPTS : IPPROTO_DSTOPTS, dis->data_pkt, dis->len_pkt, pkt3, &pkt_orig_len)) + goto send_orig; + pkt_orig = pkt3; + } + else + { + pkt_orig = dis->data_pkt; + pkt_orig_len = dis->len_pkt; + } + + if (!ip_frag(pkt_orig, pkt_orig_len, ipfrag_pos, ident, pkt1, &pkt1_len, pkt2, &pkt2_len)) + goto send_orig; + + DLOG("sending 1st ip fragment 0-%zu ip_payload_len=%zu : ", ipfrag_pos - 1, ipfrag_pos); + hexdump_limited_dlog(pkt1, pkt1_len, IP_MAXDUMP); DLOG("\n"); + if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) + goto send_orig; + + DLOG("sending 2nd ip fragment %zu-%zu ip_payload_len=%zu : ", ipfrag_pos, dis->transport_len - 1, dis->transport_len - ipfrag_pos); + hexdump_limited_dlog(pkt2, pkt2_len, IP_MAXDUMP); DLOG("\n"); + if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt2, pkt2_len)) + goto send_orig; + + return ct_new_postnat_fix(ctrack, dis->ip, dis->ip6, NULL); + } + default: + break; } } send_orig: - if ((verdict & VERDICT_MASK)==VERDICT_DROP) + if ((verdict & VERDICT_MASK) == VERDICT_DROP) verdict = ct_new_postnat_fix(ctrack, dis->ip, dis->ip6, NULL); else - if (udp_orig_send(verdict,desync_fwmark,ifout,dp,ctrack_replay,dis,bFake)) + if (udp_orig_send(verdict, desync_fwmark, ifout, dp, ctrack_replay, dis, bFake)) verdict = ct_new_postnat_fix(ctrack, dis->ip, dis->ip6, NULL); return verdict; } @@ -3234,29 +3311,29 @@ static void packet_debug(bool replay, const struct dissect *dis) if (dis->ip) { char s[66]; - str_ip(s,sizeof(s),dis->ip); - DLOG("IP4: %s",s); + str_ip(s, sizeof(s), dis->ip); + DLOG("IP4: %s", s); } else if (dis->ip6) { char s[128]; - str_ip6hdr(s,sizeof(s),dis->ip6, dis->proto); - DLOG("IP6: %s",s); + str_ip6hdr(s, sizeof(s), dis->ip6, dis->proto); + DLOG("IP6: %s", s); } if (dis->tcp) { char s[80]; - str_tcphdr(s,sizeof(s),dis->tcp); - DLOG(" %s\n",s); - if (dis->len_payload) { DLOG("TCP: len=%zu : ",dis->len_payload); hexdump_limited_dlog(dis->data_payload, dis->len_payload, PKTDATA_MAXDUMP); DLOG("\n"); } + str_tcphdr(s, sizeof(s), dis->tcp); + DLOG(" %s\n", s); + if (dis->len_payload) { DLOG("TCP: len=%zu : ", dis->len_payload); hexdump_limited_dlog(dis->data_payload, dis->len_payload, PKTDATA_MAXDUMP); DLOG("\n"); } } else if (dis->udp) { char s[30]; - str_udphdr(s,sizeof(s),dis->udp); - DLOG(" %s\n",s); - if (dis->len_payload) { DLOG("UDP: len=%zu : ",dis->len_payload); hexdump_limited_dlog(dis->data_payload, dis->len_payload, PKTDATA_MAXDUMP); DLOG("\n"); } + str_udphdr(s, sizeof(s), dis->udp); + DLOG(" %s\n", s); + if (dis->len_payload) { DLOG("UDP: len=%zu : ", dis->len_payload); hexdump_limited_dlog(dis->data_payload, dis->len_payload, PKTDATA_MAXDUMP); DLOG("\n"); } } else DLOG("\n"); @@ -3268,27 +3345,27 @@ static uint8_t dpi_desync_packet_play(bool replay, size_t reasm_offset, uint32_t { struct dissect dis; uint8_t verdict = VERDICT_PASS; - - proto_dissect_l3l4(data_pkt,*len_pkt,&dis); + + proto_dissect_l3l4(data_pkt, *len_pkt, &dis); if (!!dis.ip != !!dis.ip6) { packet_debug(replay, &dis); - switch(dis.proto) + switch (dis.proto) { - case IPPROTO_TCP: - if (dis.tcp) - { - verdict = dpi_desync_tcp_packet_play(replay, reasm_offset, fwmark, ifin, ifout, &dis); - verdict_tcp_csum_fix(verdict, dis.tcp, dis.transport_len, dis.ip, dis.ip6); - } - break; - case IPPROTO_UDP: - if (dis.udp) - { - verdict = dpi_desync_udp_packet_play(replay, reasm_offset, fwmark, ifin, ifout, &dis); - verdict_udp_csum_fix(verdict, dis.udp, dis.transport_len, dis.ip, dis.ip6); - } - break; + case IPPROTO_TCP: + if (dis.tcp) + { + verdict = dpi_desync_tcp_packet_play(replay, reasm_offset, fwmark, ifin, ifout, &dis); + verdict_tcp_csum_fix(verdict, dis.tcp, dis.transport_len, dis.ip, dis.ip6); + } + break; + case IPPROTO_UDP: + if (dis.udp) + { + verdict = dpi_desync_udp_packet_play(replay, reasm_offset, fwmark, ifin, ifout, &dis); + verdict_udp_csum_fix(verdict, dis.udp, dis.transport_len, dis.ip, dis.ip6); + } + break; } *len_pkt = dis.len_pkt; } @@ -3308,23 +3385,23 @@ static bool replay_queue(struct rawpacket_tailhead *q) size_t offset; unsigned int i; bool b = true; - for (i=1,offset=0 ; (rp=rawpacket_dequeue(q)) ; offset+=rp->len_payload, rawpacket_free(rp), i++) + for (i = 1, offset = 0; (rp = rawpacket_dequeue(q)); offset += rp->len_payload, rawpacket_free(rp), i++) { - DLOG("REPLAYING delayed packet #%u offset %zu\n",i,offset); + DLOG("REPLAYING delayed packet #%u offset %zu\n", i, offset); uint8_t verdict = dpi_desync_packet_play(true, offset, rp->fwmark, rp->ifin, rp->ifout, rp->packet, &rp->len); - switch(verdict & VERDICT_MASK) + switch (verdict & VERDICT_MASK) { - case VERDICT_MODIFY: - DLOG("SENDING delayed packet #%u modified\n", i); - b &= rawsend_rp(rp); - break; - case VERDICT_PASS: - DLOG("SENDING delayed packet #%u unmodified\n", i); - b &= rawsend_rp(rp); - break; - case VERDICT_DROP: - DLOG("DROPPING delayed packet #%u\n", i); - break; + case VERDICT_MODIFY: + DLOG("SENDING delayed packet #%u modified\n", i); + b &= rawsend_rp(rp); + break; + case VERDICT_PASS: + DLOG("SENDING delayed packet #%u unmodified\n", i); + b &= rawsend_rp(rp); + break; + case VERDICT_DROP: + DLOG("DROPPING delayed packet #%u\n", i); + break; } } return b; diff --git a/nfq/helpers.c b/nfq/helpers.c index 73e498da..bbc74fa2 100644 --- a/nfq/helpers.c +++ b/nfq/helpers.c @@ -338,10 +338,18 @@ bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size) return true; } -void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize) +void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize,size_t offset) { size_t size; + if (offset%=patsize) + { + size = patsize-offset; + size = bufsize>size ? size : bufsize; + memcpy(buf,pattern+offset,size); + buf += size; + bufsize -= size; + } while (bufsize) { size = bufsize>patsize ? patsize : bufsize; diff --git a/nfq/helpers.h b/nfq/helpers.h index d8d662ac..31f24bad 100644 --- a/nfq/helpers.h +++ b/nfq/helpers.h @@ -70,7 +70,7 @@ static inline uint32_t pntoh32(const uint8_t *p) { } bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size); -void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize); +void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize,size_t offset); int fprint_localtime(FILE *F); diff --git a/nfq/nfqws.c b/nfq/nfqws.c index 46fb35f2..2415eaf3 100644 --- a/nfq/nfqws.c +++ b/nfq/nfqws.c @@ -54,15 +54,15 @@ #define MAX_CONFIG_FILE_SIZE 16384 struct params_s params; -static bool bReload=false; +static bool bReload = false; #ifdef __CYGWIN__ -bool bQuit=false; +bool bQuit = false; #endif static void onhup(int sig) { printf("HUP received ! Lists will be reloaded.\n"); - bReload=true; + bReload = true; } static void ReloadCheck() { @@ -80,7 +80,7 @@ static void ReloadCheck() DLOG_ERR("ipset load failed. this is fatal.\n"); exit(1); } - bReload=false; + bReload = false; } } @@ -93,11 +93,11 @@ static void onusr1(int sig) static void onusr2(int sig) { printf("\nHOSTFAIL POOL DUMP\n"); - + struct desync_profile_list *dpl; LIST_FOREACH(dpl, ¶ms.desync_profiles, next) { - printf("\nDESYNC PROFILE %d\n",dpl->dp.n); + printf("\nDESYNC PROFILE %d\n", dpl->dp.n); HostFailPoolDump(dpl->dp.hostlist_auto_fail_counters); } if (params.autottl_present || params.cache_hostname) @@ -138,14 +138,14 @@ static bool test_list_files() if (hfile->filename && !file_open_test(hfile->filename, O_RDONLY)) { DLOG_PERROR("file_open_test"); - DLOG_ERR("cannot access hostlist file '%s'\n",hfile->filename); + DLOG_ERR("cannot access hostlist file '%s'\n", hfile->filename); return false; } LIST_FOREACH(ifile, ¶ms.ipsets, next) if (ifile->filename && !file_open_test(ifile->filename, O_RDONLY)) { DLOG_PERROR("file_open_test"); - DLOG_ERR("cannot access ipset file '%s'\n",ifile->filename); + DLOG_ERR("cannot access ipset file '%s'\n", ifile->filename); return false; } return true; @@ -169,12 +169,12 @@ static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_da ilen = nfq_get_payload(nfa, &data); ifidx_out = nfq_get_outdev(nfa); - *ifout=0; - if (ifidx_out) if_indextoname(ifidx_out,ifout); + *ifout = 0; + if (ifidx_out) if_indextoname(ifidx_out, ifout); ifidx_in = nfq_get_indev(nfa); - *ifin=0; - if (ifidx_in) if_indextoname(ifidx_in,ifin); + *ifin = 0; + if (ifidx_in) if_indextoname(ifidx_in, ifin); DLOG("\npacket: id=%d len=%d mark=%08X ifin=%s(%u) ifout=%s(%u)\n", id, ilen, mark, ifin, ifidx_in, ifout, ifidx_out); @@ -182,7 +182,7 @@ static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_da { len = ilen; uint8_t verdict = processPacketData(&mark, ifin, ifout, data, &len); - switch(verdict & VERDICT_MASK) + switch (verdict & VERDICT_MASK) { case VERDICT_MODIFY: DLOG("packet: id=%d pass modified. len=%zu\n", id, len); @@ -195,7 +195,7 @@ static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_da DLOG("packet: id=%d pass unmodified\n", id); return nfq_set_verdict2(qh, id, NF_ACCEPT, mark, 0, NULL); } -static void nfq_deinit(struct nfq_handle **h,struct nfq_q_handle **qh) +static void nfq_deinit(struct nfq_handle **h, struct nfq_q_handle **qh) { if (*qh) { @@ -210,9 +210,9 @@ static void nfq_deinit(struct nfq_handle **h,struct nfq_q_handle **qh) *h = NULL; } } -static bool nfq_init(struct nfq_handle **h,struct nfq_q_handle **qh) +static bool nfq_init(struct nfq_handle **h, struct nfq_q_handle **qh) { - nfq_deinit(h,qh); + nfq_deinit(h, qh); DLOG_CONDUP("opening library handle\n"); *h = nfq_open(); @@ -250,17 +250,17 @@ static bool nfq_init(struct nfq_handle **h,struct nfq_q_handle **qh) goto exiterr; } // accept packets if they cant be handled - if (nfq_set_queue_flags(*qh, NFQA_CFG_F_FAIL_OPEN , NFQA_CFG_F_FAIL_OPEN)) + if (nfq_set_queue_flags(*qh, NFQA_CFG_F_FAIL_OPEN, NFQA_CFG_F_FAIL_OPEN)) { DLOG_ERR("can't set queue flags. its OK on linux <3.6\n"); // dot not fail. not supported on old linuxes <3.6 } - DLOG_CONDUP("initializing raw sockets bind-fix4=%u bind-fix6=%u\n",params.bind_fix4,params.bind_fix6); - if (!rawsend_preinit(params.bind_fix4,params.bind_fix6)) + DLOG_CONDUP("initializing raw sockets bind-fix4=%u bind-fix6=%u\n", params.bind_fix4, params.bind_fix6); + if (!rawsend_preinit(params.bind_fix4, params.bind_fix6)) goto exiterr; - int yes=1, fd = nfq_fd(*h); + int yes = 1, fd = nfq_fd(*h); #if defined SOL_NETLINK && defined NETLINK_NO_ENOBUFS if (setsockopt(fd, SOL_NETLINK, NETLINK_NO_ENOBUFS, &yes, sizeof(yes)) == -1) @@ -269,7 +269,7 @@ static bool nfq_init(struct nfq_handle **h,struct nfq_q_handle **qh) return true; exiterr: - nfq_deinit(h,qh); + nfq_deinit(h, qh); return false; } @@ -287,11 +287,11 @@ static int nfq_main(void) uint8_t buf[16384] __attribute__((aligned)); struct nfq_handle *h = NULL; struct nfq_q_handle *qh = NULL; - int fd,e; + int fd, e; ssize_t rd; FILE *Fpid = NULL; - if (*params.pidfile && !(Fpid=fopen(params.pidfile,"w"))) + if (*params.pidfile && !(Fpid = fopen(params.pidfile, "w"))) { DLOG_PERROR("create pidfile"); return 1; @@ -303,7 +303,7 @@ static int nfq_main(void) if (params.droproot && !test_list_files()) goto err; - if (!nfq_init(&h,&qh)) + if (!nfq_init(&h, &qh)) goto err; #ifdef HAS_FILTER_SSID @@ -324,13 +324,13 @@ static int nfq_main(void) if (Fpid) { - if (fprintf(Fpid, "%d", getpid())<=0) + if (fprintf(Fpid, "%d", getpid()) <= 0) { DLOG_PERROR("write pidfile"); goto err; } fclose(Fpid); - Fpid=NULL; + Fpid = NULL; } pre_desync(); @@ -355,21 +355,21 @@ static int nfq_main(void) else DLOG("recv from nfq returned 0 !\n"); } - e=errno; - DLOG_ERR("recv: recv=%zd errno %d\n",rd,e); - errno=e; + e = errno; + DLOG_ERR("recv: recv=%zd errno %d\n", rd, e); + errno = e; DLOG_PERROR("recv"); // do not fail on ENOBUFS - } while(e==ENOBUFS); + } while (e == ENOBUFS); - nfq_deinit(&h,&qh); + nfq_deinit(&h, &qh); #ifdef HAS_FILTER_SSID wlan_info_deinit(); #endif return 0; err: if (Fpid) fclose(Fpid); - nfq_deinit(&h,&qh); + nfq_deinit(&h, &qh); #ifdef HAS_FILTER_SSID wlan_info_deinit(); #endif @@ -382,15 +382,15 @@ static int dvt_main(void) { uint8_t buf[16384] __attribute__((aligned)); struct sockaddr_storage sa_from; - int fd[2] = {-1,-1}; // 4,6 - int i,r,res=1,fdct=1,fdmax; - unsigned int id=0; + int fd[2] = { -1,-1 }; // 4,6 + int i, r, res = 1, fdct = 1, fdmax; + unsigned int id = 0; socklen_t socklen; - ssize_t rd,wr; + ssize_t rd, wr; fd_set fdset; FILE *Fpid = NULL; - if (*params.pidfile && !(Fpid=fopen(params.pidfile,"w"))) + if (*params.pidfile && !(Fpid = fopen(params.pidfile, "w"))) { DLOG_PERROR("create pidfile"); return 1; @@ -401,7 +401,7 @@ static int dvt_main(void) bp4.sin_family = AF_INET; bp4.sin_port = htons(params.port); bp4.sin_addr.s_addr = INADDR_ANY; - + DLOG_CONDUP("creating divert4 socket\n"); fd[0] = socket_divert(AF_INET); if (fd[0] == -1) { @@ -421,10 +421,10 @@ static int dvt_main(void) { // in OpenBSD must use separate divert sockets for ipv4 and ipv6 struct sockaddr_in6 bp6; - memset(&bp6,0,sizeof(bp6)); + memset(&bp6, 0, sizeof(bp6)); bp6.sin6_family = AF_INET6; bp6.sin6_port = htons(params.port); - + DLOG_CONDUP("creating divert6 socket\n"); fd[1] = socket_divert(AF_INET6); if (fd[1] == -1) { @@ -440,10 +440,10 @@ static int dvt_main(void) fdct++; } #endif - fdmax = (fd[0]>fd[1] ? fd[0] : fd[1]) + 1; + fdmax = (fd[0] > fd[1] ? fd[0] : fd[1]) + 1; DLOG_CONDUP("initializing raw sockets\n"); - if (!rawsend_preinit(false,false)) + if (!rawsend_preinit(false, false)) goto exiterr; @@ -457,25 +457,25 @@ static int dvt_main(void) if (Fpid) { - if (fprintf(Fpid, "%d", getpid())<=0) + if (fprintf(Fpid, "%d", getpid()) <= 0) { DLOG_PERROR("write pidfile"); goto exiterr; } fclose(Fpid); - Fpid=NULL; + Fpid = NULL; } pre_desync(); - for(;;) + for (;;) { FD_ZERO(&fdset); - for(i=0;i0) + else if (rd > 0) { - uint32_t mark=0; + uint32_t mark = 0; uint8_t verdict; size_t len = rd; @@ -508,14 +508,14 @@ static int dvt_main(void) { case VERDICT_PASS: case VERDICT_MODIFY: - if ((verdict & VERDICT_MASK)==VERDICT_PASS) + if ((verdict & VERDICT_MASK) == VERDICT_PASS) DLOG("packet: id=%u reinject unmodified\n", id); else DLOG("packet: id=%u reinject modified len=%zu\n", id, len); wr = sendto(fd[i], buf, len, 0, (struct sockaddr*)&sa_from, socklen); - if (wr<0) + if (wr < 0) DLOG_PERROR("reinject sendto"); - else if (wr!=len) + else if (wr != len) DLOG_ERR("reinject sendto: not all data was reinjected. received %zu, sent %zd\n", len, wr); break; default: @@ -531,11 +531,11 @@ static int dvt_main(void) } } - res=0; + res = 0; exiterr: if (Fpid) fclose(Fpid); - if (fd[0]!=-1) close(fd[0]); - if (fd[1]!=-1) close(fd[1]); + if (fd[0] != -1) close(fd[0]); + if (fd[1] != -1) close(fd[1]); return res; } @@ -569,7 +569,7 @@ static int win_main(const char *windivert_filter) pre_desync(); - for(;;) + for (;;) { if (!logical_net_filter_match()) { @@ -583,8 +583,7 @@ static int win_main(const char *windivert_filter) return 0; } usleep(500000); - } - while (!logical_net_filter_match()); + } while (!logical_net_filter_match()); DLOG_CONDUP("logical network now present\n"); } @@ -596,23 +595,23 @@ static int win_main(const char *windivert_filter) DLOG_CONDUP("windivert initialized. capture is started.\n"); - for (id=0;;id++) + for (id = 0;; id++) { len = sizeof(packet); if (!windivert_recv(packet, &len, &wa)) { - if (errno==ENOBUFS) + if (errno == ENOBUFS) { DLOG("windivert: ignoring too large packet\n"); continue; // too large packet } - else if (errno==ENODEV) + else if (errno == ENODEV) { DLOG_CONDUP("logical network disappeared. deinitializing windivert.\n"); rawsend_cleanup(); break; } - else if (errno==EINTR) + else if (errno == EINTR) { DLOG("QUIT requested\n"); win_dark_deinit(); @@ -625,8 +624,8 @@ static int win_main(const char *windivert_filter) ReloadCheck(); - *ifname=0; - snprintf(ifname,sizeof(ifname),"%u.%u", wa.Network.IfIdx, wa.Network.SubIfIdx); + *ifname = 0; + snprintf(ifname, sizeof(ifname), "%u.%u", wa.Network.IfIdx, wa.Network.SubIfIdx); DLOG("\npacket: id=%u len=%zu %s IPv6=%u IPChecksum=%u TCPChecksum=%u UDPChecksum=%u IfIdx=%u.%u\n", id, len, wa.Outbound ? "outbound" : "inbound", wa.IPv6, wa.IPChecksum, wa.TCPChecksum, wa.UDPChecksum, wa.Network.IfIdx, wa.Network.SubIfIdx); if (wa.Impostor) { @@ -640,23 +639,23 @@ static int win_main(const char *windivert_filter) } else { - mark=0; + mark = 0; // pseudo interface id IfIdx.SubIfIdx verdict = processPacketData(&mark, ifname, ifname, packet, &len); } switch (verdict & VERDICT_MASK) { - case VERDICT_PASS: - case VERDICT_MODIFY: - if ((verdict & VERDICT_MASK)==VERDICT_PASS) - DLOG("packet: id=%u reinject unmodified\n", id); - else - DLOG("packet: id=%u reinject modified len=%zu\n", id, len); - if (!windivert_send(packet, len, &wa)) - DLOG_ERR("windivert: reinject of packet id=%u failed\n", id); - break; - default: - DLOG("packet: id=%u drop\n", id); + case VERDICT_PASS: + case VERDICT_MODIFY: + if ((verdict & VERDICT_MASK) == VERDICT_PASS) + DLOG("packet: id=%u reinject unmodified\n", id); + else + DLOG("packet: id=%u reinject modified len=%zu\n", id, len); + if (!windivert_send(packet, len, &wa)) + DLOG_ERR("windivert: reinject of packet id=%u failed\n", id); + break; + default: + DLOG("packet: id=%u drop\n", id); } } } @@ -681,24 +680,24 @@ static bool parse_uid(const char *opt, uid_t *uid, gid_t *gid, int *gid_count, i unsigned int u; char c, *p, *e; - *gid_count=0; - if ((e = strchr(optarg,':'))) *e++=0; - if (sscanf(opt,"%u",&u)!=1) return false; + *gid_count = 0; + if ((e = strchr(optarg, ':'))) *e++ = 0; + if (sscanf(opt, "%u", &u) != 1) return false; *uid = (uid_t)u; - for (p=e ; p ; ) + for (p = e; p; ) { - if ((e = strchr(p,','))) + if ((e = strchr(p, ','))) { - c=*e; - *e=0; + c = *e; + *e = 0; } if (p) { - if (sscanf(p,"%u",&u)!=1) return false; - if (*gid_count>=max_gids) return false; + if (sscanf(p, "%u", &u) != 1) return false; + if (*gid_count >= max_gids) return false; gid[(*gid_count)++] = (gid_t)u; } - if (e) *e++=c; + if (e) *e++ = c; p = e; } return true; @@ -709,14 +708,14 @@ static bool parse_ws_scale_factor(char *s, uint16_t *wsize, uint8_t *wscale) int v; char *p; - if ((p = strchr(s,':'))) *p++=0; + if ((p = strchr(s, ':'))) *p++ = 0; v = atoi(s); if (v < 0 || v>65535) { DLOG_ERR("bad wsize\n"); return false; } - *wsize=(uint16_t)v; + *wsize = (uint16_t)v; if (p && *p) { v = atoi(p); @@ -732,19 +731,19 @@ static bool parse_ws_scale_factor(char *s, uint16_t *wsize, uint8_t *wscale) static bool parse_cutoff(const char *opt, unsigned int *value, char *mode) { - *mode = (*opt=='n' || *opt=='d' || *opt=='s') ? *opt++ : 'n'; - return sscanf(opt, "%u", value)>0; + *mode = (*opt == 'n' || *opt == 'd' || *opt == 's') ? *opt++ : 'n'; + return sscanf(opt, "%u", value) > 0; } static bool parse_net32_signed(const char *opt, uint32_t *value) { - if (((opt[0]=='0' && opt[1]=='x') || (opt[0]=='-' && opt[1]=='0' && opt[2]=='x')) && sscanf(opt+2+(opt[0]=='-'), "%X", (int32_t*)value)>0) + if (((opt[0] == '0' && opt[1] == 'x') || (opt[0] == '-' && opt[1] == '0' && opt[2] == 'x')) && sscanf(opt + 2 + (opt[0] == '-'), "%X", (int32_t*)value) > 0) { - if (opt[0]=='-') *value = -*value; + if (opt[0] == '-') *value = -*value; return true; } else { - return sscanf(opt, "%d", (int32_t*)value)>0; + return sscanf(opt, "%d", (int32_t*)value) > 0; } } static void load_file_or_exit(const char *filename, void *buf, size_t *size, size_t *offset) @@ -756,54 +755,54 @@ static void load_file_or_exit(const char *filename, void *buf, size_t *size, siz // @filename // +123@filename - if (offset) *offset=0; - if (filename[0]=='0' && filename[1]=='x') + if (offset) *offset = 0; + if (filename[0] == '0' && filename[1] == 'x') { - if (!parse_hex_str(filename+2,buf,size) || !*size) + if (!parse_hex_str(filename + 2, buf, size) || !*size) { - DLOG_ERR("invalid hex string: %s\n",filename+2); + DLOG_ERR("invalid hex string: %s\n", filename + 2); exit_clean(1); } - DLOG("read %zu bytes from hex string\n",*size); + DLOG("read %zu bytes from hex string\n", *size); } else { - ofs=0; - if (filename[0]=='+') + ofs = 0; + if (filename[0] == '+') { filename++; - if (sscanf(filename,"%zu",&ofs)!=1) + if (sscanf(filename, "%zu", &ofs) != 1) { - DLOG("offset read error: %s\n",filename); + DLOG("offset read error: %s\n", filename); exit_clean(1); } - while(*filename && *filename!='@') filename++; - if (*filename=='@') filename++; + while (*filename && *filename != '@') filename++; + if (*filename == '@') filename++; } - else if (filename[0]=='@') + else if (filename[0] == '@') filename++; - if (!load_file_nonempty(filename,buf,size)) + if (!load_file_nonempty(filename, buf, size)) { - DLOG_ERR("could not read %s\n",filename); + DLOG_ERR("could not read %s\n", filename); exit_clean(1); } - DLOG("read %zu bytes from '%s'. offset=%zu\n",*size,filename,ofs); - if (ofs>=*size) + DLOG("read %zu bytes from '%s'. offset=%zu\n", *size, filename, ofs); + if (ofs >= *size) { - DLOG("'%s' : offset %zu is out of data range %zu\n",filename,ofs,*size); + DLOG("'%s' : offset %zu is out of data range %zu\n", filename, ofs, *size); exit_clean(1); } if (offset) - *offset=ofs; + *offset = ofs; else - memmove(buf,(uint8_t*)buf+ofs,*size-=ofs); + memmove(buf, (uint8_t*)buf + ofs, *size -= ofs); } } static bool parse_autottl(const char *s, autottl *t, int8_t def_delta, uint8_t def_min, uint8_t def_max) { - bool neg=true; - unsigned int delta,min,max; + bool neg = true; + unsigned int delta, min, max; t->delta = def_delta; t->min = def_min; @@ -811,31 +810,32 @@ static bool parse_autottl(const char *s, autottl *t, int8_t def_delta, uint8_t d if (s) { // "-" means disable - if (s[0]=='-' && s[1]==0) - memset(t,0,sizeof(*t)); + if (s[0] == '-' && s[1] == 0) + memset(t, 0, sizeof(*t)); else { max = t->max; - if (*s=='+') + if (*s == '+') { - neg=false; + neg = false; s++; - } else if (*s=='-') + } + else if (*s == '-') s++; - switch (sscanf(s,"%u:%u-%u",&delta,&min,&max)) + switch (sscanf(s, "%u:%u-%u", &delta, &min, &max)) { - case 3: - if ((delta && !max) || max>255) return false; - t->max=(uint8_t)max; - case 2: - if ((delta && !min) || min>255 || min>max) return false; - t->min=(uint8_t)min; - case 1: - if (delta>127) return false; - t->delta=(int8_t)(neg ? -delta : delta); - break; - default: - return false; + case 3: + if ((delta && !max) || max > 255) return false; + t->max = (uint8_t)max; + case 2: + if ((delta && !min) || min > 255 || min > max) return false; + t->min = (uint8_t)min; + case 1: + if (delta > 127) return false; + t->delta = (int8_t)(neg ? -delta : delta); + break; + default: + return false; } } } @@ -844,35 +844,35 @@ static bool parse_autottl(const char *s, autottl *t, int8_t def_delta, uint8_t d static bool parse_l7_list(char *opt, uint32_t *l7) { - char *e,*p,c; + char *e, *p, c; - for (p=opt,*l7=0 ; p ; ) + for (p = opt, *l7 = 0; p; ) { - if ((e = strchr(p,','))) + if ((e = strchr(p, ','))) { - c=*e; - *e=0; + c = *e; + *e = 0; } - if (!strcmp(p,"http")) + if (!strcmp(p, "http")) *l7 |= L7_PROTO_HTTP; - else if (!strcmp(p,"tls")) + else if (!strcmp(p, "tls")) *l7 |= L7_PROTO_TLS; - else if (!strcmp(p,"quic")) + else if (!strcmp(p, "quic")) *l7 |= L7_PROTO_QUIC; - else if (!strcmp(p,"wireguard")) + else if (!strcmp(p, "wireguard")) *l7 |= L7_PROTO_WIREGUARD; - else if (!strcmp(p,"dht")) + else if (!strcmp(p, "dht")) *l7 |= L7_PROTO_DHT; - else if (!strcmp(p,"discord")) + else if (!strcmp(p, "discord")) *l7 |= L7_PROTO_DISCORD; - else if (!strcmp(p,"stun")) + else if (!strcmp(p, "stun")) *l7 |= L7_PROTO_STUN; - else if (!strcmp(p,"unknown")) + else if (!strcmp(p, "unknown")) *l7 |= L7_PROTO_UNKNOWN; else return false; - if (e) *e++=c; + if (e) *e++ = c; p = e; } return true; @@ -880,20 +880,20 @@ static bool parse_l7_list(char *opt, uint32_t *l7) static bool parse_pf_list(char *opt, struct port_filters_head *pfl) { - char *e,*p,c; + char *e, *p, c; port_filter pf; bool b; - for (p=opt ; p ; ) + for (p = opt; p; ) { - if ((e = strchr(p,','))) + if ((e = strchr(p, ','))) { - c=*e; - *e=0; + c = *e; + *e = 0; } - b = pf_parse(p,&pf) && port_filter_add(pfl,&pf); - if (e) *e++=c; + b = pf_parse(p, &pf) && port_filter_add(pfl, &pf); + if (e) *e++ = c; if (!b) return false; p = e; @@ -903,23 +903,23 @@ static bool parse_pf_list(char *opt, struct port_filters_head *pfl) static bool wf_make_l3(char *opt, bool *ipv4, bool *ipv6) { - char *e,*p,c; + char *e, *p, c; - for (p=opt,*ipv4=*ipv6=false ; p ; ) + for (p = opt, *ipv4 = *ipv6 = false; p; ) { - if ((e = strchr(p,','))) + if ((e = strchr(p, ','))) { - c=*e; - *e=0; + c = *e; + *e = 0; } - if (!strcmp(p,"ipv4")) + if (!strcmp(p, "ipv4")) *ipv4 = true; - else if (!strcmp(p,"ipv6")) + else if (!strcmp(p, "ipv6")) *ipv6 = true; else return false; - if (e) *e++=c; + if (e) *e++ = c; p = e; } return true; @@ -930,12 +930,12 @@ static bool parse_httpreqpos(const char *s, struct proto_pos *sp) if (!strcmp(s, "method")) { sp->marker = PM_HTTP_METHOD; - sp->pos=2; + sp->pos = 2; } else if (!strcmp(s, "host")) { sp->marker = PM_HOST; - sp->pos=1; + sp->pos = 1; } else return false; @@ -946,17 +946,17 @@ static bool parse_tlspos(const char *s, struct proto_pos *sp) if (!strcmp(s, "sni")) { sp->marker = PM_HOST; - sp->pos=1; + sp->pos = 1; } else if (!strcmp(s, "sniext")) { sp->marker = PM_SNI_EXT; - sp->pos=1; + sp->pos = 1; } else if (!strcmp(s, "snisld")) { sp->marker = PM_HOST_MIDSLD; - sp->pos=0; + sp->pos = 0; } else return false; @@ -965,29 +965,29 @@ static bool parse_tlspos(const char *s, struct proto_pos *sp) static bool parse_int16(const char *p, int16_t *v) { - if (*p=='+' || *p=='-' || *p>='0' && *p<='9') + if (*p == '+' || *p == '-' || *p >= '0' && *p <= '9') { int i = atoi(p); *v = (int16_t)i; - return *v==i; // check overflow + return *v == i; // check overflow } return false; } static bool parse_posmarker(const char *opt, uint8_t *posmarker) { - if (!strcmp(opt,"host")) + if (!strcmp(opt, "host")) *posmarker = PM_HOST; - else if (!strcmp(opt,"endhost")) + else if (!strcmp(opt, "endhost")) *posmarker = PM_HOST_END; - else if (!strcmp(opt,"sld")) + else if (!strcmp(opt, "sld")) *posmarker = PM_HOST_SLD; - else if (!strcmp(opt,"midsld")) + else if (!strcmp(opt, "midsld")) *posmarker = PM_HOST_MIDSLD; - else if (!strcmp(opt,"endsld")) + else if (!strcmp(opt, "endsld")) *posmarker = PM_HOST_ENDSLD; - else if (!strcmp(opt,"method")) + else if (!strcmp(opt, "method")) *posmarker = PM_HTTP_METHOD; - else if (!strcmp(opt,"sniext")) + else if (!strcmp(opt, "sniext")) *posmarker = PM_SNI_EXT; else return false; @@ -995,23 +995,23 @@ static bool parse_posmarker(const char *opt, uint8_t *posmarker) } static bool parse_split_pos(char *opt, struct proto_pos *split) { - if (parse_int16(opt,&split->pos)) + if (parse_int16(opt, &split->pos)) { split->marker = PM_ABS; return !!split->pos; } else { - char c,*p=opt; + char c, *p = opt; bool b; - for (; *opt && *opt!='+' && *opt!='-'; opt++); - c=*opt; *opt=0; - b=parse_posmarker(p,&split->marker); - *opt=c; + for (; *opt && *opt != '+' && *opt != '-'; opt++); + c = *opt; *opt = 0; + b = parse_posmarker(p, &split->marker); + *opt = c; if (!b) return false; if (*opt) - return parse_int16(opt,&split->pos); + return parse_int16(opt, &split->pos); else split->pos = 0; } @@ -1019,17 +1019,17 @@ static bool parse_split_pos(char *opt, struct proto_pos *split) } static bool parse_split_pos_list(char *opt, struct proto_pos *splits, int splits_size, int *split_count) { - char c,*e,*p; + char c, *e, *p; - for (p=opt, *split_count=0 ; p && *split_countmod &= FAKE_TLS_MOD_SAVE_MASK; tls_mod->mod |= FAKE_TLS_MOD_SET; - for (p=opt ; p ; ) + for (p = opt; p; ) { - for (e2=p ; *e2 && *e2!=',' && *e2!='=' ; e2++); + for (e2 = p; *e2 && *e2 != ',' && *e2 != '='; e2++); - if ((e = strchr(e2,','))) + if ((e = strchr(e2, ','))) { - c=*e; - *e=0; + c = *e; + *e = 0; } - if (*e2=='=') + if (*e2 == '=') { - c2=*e2; - *e2=0; + c2 = *e2; + *e2 = 0; } else - e2=NULL; + e2 = NULL; - if (!strcmp(p,"rnd")) + if (!strcmp(p, "rnd")) tls_mod->mod |= FAKE_TLS_MOD_RND; - else if (!strcmp(p,"rndsni")) + else if (!strcmp(p, "rndsni")) tls_mod->mod |= FAKE_TLS_MOD_RND_SNI; - else if (!strcmp(p,"sni")) + else if (!strcmp(p, "sni")) { tls_mod->mod |= FAKE_TLS_MOD_SNI; - if (!e2 || !e2[1] || e2[1]==',') goto err; - strncpy(tls_mod->sni,e2+1,sizeof(tls_mod->sni)-1); - tls_mod->sni[sizeof(tls_mod->sni)-1-1]=0; + if (!e2 || !e2[1] || e2[1] == ',') goto err; + strncpy(tls_mod->sni, e2 + 1, sizeof(tls_mod->sni) - 1); + tls_mod->sni[sizeof(tls_mod->sni) - 1 - 1] = 0; } - else if (!strcmp(p,"padencap")) + else if (!strcmp(p, "padencap")) tls_mod->mod |= FAKE_TLS_MOD_PADENCAP; - else if (!strcmp(p,"dupsid")) + else if (!strcmp(p, "dupsid")) tls_mod->mod |= FAKE_TLS_MOD_DUP_SID; - else if (strcmp(p,"none")) + else if (strcmp(p, "none")) goto err; - if (e2) *e2=c2; - if (e) *e++=c; + if (e2) *e2 = c2; + if (e) *e++ = c; p = e; } return true; err: - if (e2) *e2=c2; - if (e) *e++=c; + if (e2) *e2 = c2; + if (e) *e++ = c; return false; } static bool parse_hostfakesplit_mod(char *opt, struct hostfakesplit_mod *hfs_mod) { - char *e,*e2,*p,c,c2; + char *e, *e2, *p, c, c2; - for (p=opt ; p ; ) + for (p = opt; p; ) { - for (e2=p ; *e2 && *e2!=',' && *e2!='=' ; e2++); + for (e2 = p; *e2 && *e2 != ',' && *e2 != '='; e2++); - if ((e = strchr(e2,','))) + if ((e = strchr(e2, ','))) { - c=*e; - *e=0; + c = *e; + *e = 0; } - if (*e2=='=') + if (*e2 == '=') { - c2=*e2; - *e2=0; + c2 = *e2; + *e2 = 0; } else - e2=NULL; + e2 = NULL; - if (!strcmp(p,"host")) + if (!strcmp(p, "host")) { - if (!e2 || !e2[1] || e2[1]==',') goto err; - strncpy(hfs_mod->host,e2+1,sizeof(hfs_mod->host)-1); - hfs_mod->host[sizeof(hfs_mod->host)-1-1]=0; + if (!e2 || !e2[1] || e2[1] == ',') goto err; + strncpy(hfs_mod->host, e2 + 1, sizeof(hfs_mod->host) - 1); + hfs_mod->host[sizeof(hfs_mod->host) - 1 - 1] = 0; hfs_mod->host_size = strlen(hfs_mod->host); // cache value } - else if (!strcmp(p,"altorder")) + else if (!strcmp(p, "altorder")) { - if (!e2 || !e2[1] || e2[1]==',') goto err; - hfs_mod->ordering = atoi(e2+1); - if (hfs_mod->ordering<0 || hfs_mod->ordering>1) goto err; + if (!e2 || !e2[1] || e2[1] == ',') goto err; + hfs_mod->ordering = atoi(e2 + 1); + if (hfs_mod->ordering < 0 || hfs_mod->ordering>1) goto err; } - else if (strcmp(p,"none")) + else if (strcmp(p, "none")) goto err; - if (e2) *e2=c2; - if (e) *e++=c; + if (e2) *e2 = c2; + if (e) *e++ = c; p = e; } return true; err: - if (e2) *e2=c2; - if (e) *e++=c; + if (e2) *e2 = c2; + if (e) *e++ = c; return false; } static bool parse_fakedsplit_mod(char *opt, struct fakedsplit_mod *fs_mod) { - char *e,*e2,*p,c,c2; + char *e, *e2, *p, c, c2; - for (p=opt ; p ; ) + for (p = opt; p; ) { - for (e2=p ; *e2 && *e2!=',' && *e2!='=' ; e2++); + for (e2 = p; *e2 && *e2 != ',' && *e2 != '='; e2++); - if ((e = strchr(e2,','))) + if ((e = strchr(e2, ','))) { - c=*e; - *e=0; + c = *e; + *e = 0; } - if (*e2=='=') + if (*e2 == '=') { - c2=*e2; - *e2=0; + c2 = *e2; + *e2 = 0; } else - e2=NULL; + e2 = NULL; - if (!strcmp(p,"altorder")) + if (!strcmp(p, "altorder")) { - if (!e2 || !e2[1] || e2[1]==',') goto err; - fs_mod->ordering = atoi(e2+1); - if (fs_mod->ordering<0 || fs_mod->ordering>3) goto err; + if (!e2 || !e2[1] || e2[1] == ',') goto err; + fs_mod->ordering = atoi(e2 + 1); + // unsplitted altorder in 0x03 mask. 0x04 reserved. splitted altorder in 0x18 mask + if ((fs_mod->ordering & 0xFFFFFFE4) || (((fs_mod->ordering>>3) & 3)>2)) goto err; } - else if (strcmp(p,"none")) + else if (strcmp(p, "none")) goto err; - if (e2) *e2=c2; - if (e) *e++=c; + if (e2) *e2 = c2; + if (e) *e++ = c; p = e; } return true; err: - if (e2) *e2=c2; - if (e) *e++=c; + if (e2) *e2 = c2; + if (e) *e++ = c; return false; } static bool parse_tcpmod(char *opt, struct tcp_mod *tcp_mod) { - char *e,*e2,*p,c,c2; + char *e, *e2, *p, c, c2; - for (p=opt ; p ; ) + for (p = opt; p; ) { - for (e2=p ; *e2 && *e2!=',' && *e2!='=' ; e2++); + for (e2 = p; *e2 && *e2 != ',' && *e2 != '='; e2++); - if ((e = strchr(e2,','))) + if ((e = strchr(e2, ','))) { - c=*e; - *e=0; + c = *e; + *e = 0; } - if (*e2=='=') + if (*e2 == '=') { - c2=*e2; - *e2=0; + c2 = *e2; + *e2 = 0; } else - e2=NULL; + e2 = NULL; - if (!strcmp(p,"seq")) + if (!strcmp(p, "seq")) { tcp_mod->seq = true; } - else if (strcmp(p,"none")) + else if (strcmp(p, "none")) goto err; - if (e2) *e2=c2; - if (e) *e++=c; + if (e2) *e2 = c2; + if (e) *e++ = c; p = e; } return true; err: - if (e2) *e2=c2; - if (e) *e++=c; + if (e2) *e2 = c2; + if (e) *e++ = c; return false; } static bool parse_fooling(char *opt, unsigned int *fooling_mode) { - char *e,*p = opt; + char *e, *p = opt; while (p) { - e = strchr(p,','); - if (e) *e++=0; - if (!strcmp(p,"md5sig")) + e = strchr(p, ','); + if (e) *e++ = 0; + if (!strcmp(p, "md5sig")) *fooling_mode |= FOOL_MD5SIG; - else if (!strcmp(p,"ts")) + else if (!strcmp(p, "ts")) *fooling_mode |= FOOL_TS; - else if (!strcmp(p,"badsum")) + else if (!strcmp(p, "badsum")) *fooling_mode |= FOOL_BADSUM; - else if (!strcmp(p,"badseq")) + else if (!strcmp(p, "badseq")) *fooling_mode |= FOOL_BADSEQ; - else if (!strcmp(p,"datanoack")) + else if (!strcmp(p, "datanoack")) *fooling_mode |= FOOL_DATANOACK; - else if (!strcmp(p,"hopbyhop")) + else if (!strcmp(p, "hopbyhop")) *fooling_mode |= FOOL_HOPBYHOP; - else if (!strcmp(p,"hopbyhop2")) + else if (!strcmp(p, "hopbyhop2")) *fooling_mode |= FOOL_HOPBYHOP2; - else if (strcmp(p,"none")) + else if (strcmp(p, "none")) return false; p = e; } @@ -1290,11 +1291,11 @@ static bool parse_fooling(char *opt, unsigned int *fooling_mode) static bool parse_strlist(char *opt, struct str_list_head *list) { - char *e,*p = optarg; + char *e, *p = optarg; while (p) { - e = strchr(p,','); - if (e) *e++=0; + e = strchr(p, ','); + if (e) *e++ = 0; if (*p && !strlist_add(list, p)) return false; p = e; @@ -1310,7 +1311,7 @@ static void split_compat(struct desync_profile *dp) dp->splits[dp->split_count].pos = 2; dp->split_count++; } - if ((dp->seqovl.marker!=PM_ABS || dp->seqovl.pos<0) && (dp->desync_mode==DESYNC_FAKEDSPLIT || dp->desync_mode==DESYNC_MULTISPLIT || dp->desync_mode2==DESYNC_FAKEDSPLIT || dp->desync_mode2==DESYNC_MULTISPLIT)) + if ((dp->seqovl.marker != PM_ABS || dp->seqovl.pos < 0) && (dp->desync_mode == DESYNC_FAKEDSPLIT || dp->desync_mode == DESYNC_MULTISPLIT || dp->desync_mode2 == DESYNC_FAKEDSPLIT || dp->desync_mode2 == DESYNC_MULTISPLIT)) { DLOG_ERR("split seqovl supports only absolute positive positions\n"); exit_clean(1); @@ -1324,39 +1325,37 @@ static void SplitDebug(void) LIST_FOREACH(dpl, ¶ms.desync_profiles, next) { dp = &dpl->dp; - for(int x=0;xsplit_count;x++) - DLOG("profile %d multisplit %s %d\n",dp->n,posmarker_name(dp->splits[x].marker),dp->splits[x].pos); - if (!PROTO_POS_EMPTY(&dp->seqovl)) DLOG("profile %d seqovl %s %d\n",dp->n,posmarker_name(dp->seqovl.marker),dp->seqovl.pos); - if (!PROTO_POS_EMPTY(&dp->hostfakesplit_midhost)) DLOG("profile %d hostfakesplit midhost %s %d\n",dp->n,posmarker_name(dp->hostfakesplit_midhost.marker),dp->hostfakesplit_midhost.pos); + for (int x = 0; x < dp->split_count; x++) + DLOG("profile %d multisplit %s %d\n", dp->n, posmarker_name(dp->splits[x].marker), dp->splits[x].pos); + if (!PROTO_POS_EMPTY(&dp->seqovl)) DLOG("profile %d seqovl %s %d\n", dp->n, posmarker_name(dp->seqovl.marker), dp->seqovl.pos); + if (!PROTO_POS_EMPTY(&dp->hostfakesplit_midhost)) DLOG("profile %d hostfakesplit midhost %s %d\n", dp->n, posmarker_name(dp->hostfakesplit_midhost.marker), dp->hostfakesplit_midhost.pos); } } -static const char * tld[]={"com","org","net","edu","gov","biz"}; - static bool onetime_tls_mod_blob(int profile_n, int fake_n, const struct fake_tls_mod *tls_mod, uint8_t *fake_tls, size_t *fake_tls_size, size_t fake_tls_buf_size, struct fake_tls_mod_cache *modcache) { const uint8_t *ext; size_t extlen; modcache->extlen_offset = modcache->padlen_offset = 0; - if (tls_mod->mod & (FAKE_TLS_MOD_RND_SNI|FAKE_TLS_MOD_SNI|FAKE_TLS_MOD_PADENCAP)) + if (tls_mod->mod & (FAKE_TLS_MOD_RND_SNI | FAKE_TLS_MOD_SNI | FAKE_TLS_MOD_PADENCAP)) { - if (!TLSFindExtLen(fake_tls,*fake_tls_size,&modcache->extlen_offset)) + if (!TLSFindExtLen(fake_tls, *fake_tls_size, &modcache->extlen_offset)) { DLOG_ERR("profile %d fake[%d] padencap set but tls fake structure invalid\n", profile_n, fake_n); return false; } DLOG("profile %d fake[%d] tls extensions length offset : %zu\n", profile_n, fake_n, modcache->extlen_offset); - if (tls_mod->mod & (FAKE_TLS_MOD_RND_SNI|FAKE_TLS_MOD_SNI)) + if (tls_mod->mod & (FAKE_TLS_MOD_RND_SNI | FAKE_TLS_MOD_SNI)) { size_t slen; - if (!TLSFindExt(fake_tls,*fake_tls_size,0,&ext,&extlen,false)) + if (!TLSFindExt(fake_tls, *fake_tls_size, 0, &ext, &extlen, false)) { DLOG_ERR("profile %d fake[%d] sni mod is set but tls fake does not have SNI\n", profile_n, fake_n); return false; } uint8_t *sniext = fake_tls + (ext - fake_tls); - if (!TLSAdvanceToHostInSNI(&ext,&extlen,&slen)) + if (!TLSAdvanceToHostInSNI(&ext, &extlen, &slen)) { DLOG_ERR("profile %d fake[%d] sni set but tls fake has invalid SNI structure\n", profile_n, fake_n); return false; @@ -1365,37 +1364,37 @@ static bool onetime_tls_mod_blob(int profile_n, int fake_n, const struct fake_tl if (tls_mod->mod & FAKE_TLS_MOD_SNI) { size_t slen_new = strlen(tls_mod->sni); - ssize_t slen_delta = slen_new-slen; - char *s1=NULL; + ssize_t slen_delta = slen_new - slen; + char *s1 = NULL; if (params.debug) { - if ((s1 = malloc(slen+1))) + if ((s1 = malloc(slen + 1))) { - memcpy(s1,sni,slen); s1[slen]=0; + memcpy(s1, sni, slen); s1[slen] = 0; } } if (slen_delta) { - if ((*fake_tls_size+slen_delta)>fake_tls_buf_size) + if ((*fake_tls_size + slen_delta) > fake_tls_buf_size) { DLOG_ERR("profile %d fake[%d] not enough space for new SNI\n", profile_n, fake_n); free(s1); return false; } - memmove(sni+slen_new,sni+slen,fake_tls+*fake_tls_size-(sni+slen)); - phton16(fake_tls+3,(uint16_t)(pntoh16(fake_tls+3)+slen_delta)); - phton24(fake_tls+6,(uint32_t)(pntoh24(fake_tls+6)+slen_delta)); - phton16(fake_tls+modcache->extlen_offset,(uint16_t)(pntoh16(fake_tls+modcache->extlen_offset)+slen_delta)); - phton16(sniext-2,(uint16_t)(pntoh16(sniext-2)+slen_delta)); - phton16(sniext,(uint16_t)(pntoh16(sniext)+slen_delta)); - phton16(sni-2,(uint16_t)(pntoh16(sni-2)+slen_delta)); - *fake_tls_size+=slen_delta; + memmove(sni + slen_new, sni + slen, fake_tls + *fake_tls_size - (sni + slen)); + phton16(fake_tls + 3, (uint16_t)(pntoh16(fake_tls + 3) + slen_delta)); + phton24(fake_tls + 6, (uint32_t)(pntoh24(fake_tls + 6) + slen_delta)); + phton16(fake_tls + modcache->extlen_offset, (uint16_t)(pntoh16(fake_tls + modcache->extlen_offset) + slen_delta)); + phton16(sniext - 2, (uint16_t)(pntoh16(sniext - 2) + slen_delta)); + phton16(sniext, (uint16_t)(pntoh16(sniext) + slen_delta)); + phton16(sni - 2, (uint16_t)(pntoh16(sni - 2) + slen_delta)); + *fake_tls_size += slen_delta; slen = slen_new; } DLOG("profile %d fake[%d] change SNI : %s => %s size_delta=%zd\n", profile_n, fake_n, s1, tls_mod->sni, slen_delta); free(s1); - memcpy(sni,tls_mod->sni,slen_new); + memcpy(sni, tls_mod->sni, slen_new); } if (tls_mod->mod & FAKE_TLS_MOD_RND_SNI) { @@ -1405,31 +1404,31 @@ static bool onetime_tls_mod_blob(int profile_n, int fake_n, const struct fake_tl return false; } - char *s1=NULL, *s2=NULL; + char *s1 = NULL, *s2 = NULL; if (params.debug) { - if ((s1 = malloc(slen+1))) + if ((s1 = malloc(slen + 1))) { - memcpy(s1,sni,slen); s1[slen]=0; + memcpy(s1, sni, slen); s1[slen] = 0; } } - fill_random_az(sni,1); - if (slen>=7) // domain name in SNI must be at least 3 chars long to enable xxx.tls randomization + fill_random_az(sni, 1); + if (slen >= 7) // domain name in SNI must be at least 3 chars long to enable xxx.tls randomization { - fill_random_az09(sni+1,slen-5); - sni[slen-4] = '.'; - memcpy(sni+slen-3,tld[random()%(sizeof(tld)/sizeof(*tld))],3); + fill_random_az09(sni + 1, slen - 5); + sni[slen - 4] = '.'; + memcpy(sni + slen - 3, tld[random() % (sizeof(tld) / sizeof(*tld))], 3); } else - fill_random_az09(sni+1,slen-1); + fill_random_az09(sni + 1, slen - 1); if (params.debug) { - if (s1 && (s2 = malloc(slen+1))) + if (s1 && (s2 = malloc(slen + 1))) { - memcpy(s2,sni,slen); s2[slen]=0; - DLOG("profile %d fake[%d] generated random SNI : %s -> %s\n",profile_n,fake_n,s1,s2); + memcpy(s2, sni, slen); s2[slen] = 0; + DLOG("profile %d fake[%d] generated random SNI : %s -> %s\n", profile_n, fake_n, s1, s2); } free(s1); free(s2); } @@ -1437,31 +1436,31 @@ static bool onetime_tls_mod_blob(int profile_n, int fake_n, const struct fake_tl } if (tls_mod->mod & FAKE_TLS_MOD_PADENCAP) { - if (TLSFindExt(fake_tls,*fake_tls_size,21,&ext,&extlen,false)) + if (TLSFindExt(fake_tls, *fake_tls_size, 21, &ext, &extlen, false)) { - if ((ext-fake_tls+extlen)!=*fake_tls_size) + if ((ext - fake_tls + extlen) != *fake_tls_size) { - DLOG_ERR("profile %d fake[%d] tls padding ext is present but it's not at the end. padding ext offset %zu, padding ext size %zu, fake size %zu\n", profile_n, fake_n, ext-fake_tls, extlen, *fake_tls_size); + DLOG_ERR("profile %d fake[%d] tls padding ext is present but it's not at the end. padding ext offset %zu, padding ext size %zu, fake size %zu\n", profile_n, fake_n, ext - fake_tls, extlen, *fake_tls_size); return false; } - modcache->padlen_offset = ext-fake_tls-2; + modcache->padlen_offset = ext - fake_tls - 2; DLOG("profile %d fake[%d] tls padding ext is present, padding length offset %zu\n", profile_n, fake_n, modcache->padlen_offset); } else { - if ((*fake_tls_size+4)>fake_tls_buf_size) + if ((*fake_tls_size + 4) > fake_tls_buf_size) { DLOG_ERR("profile %d fake[%d] tls padding is absent and there's no space to add it\n", profile_n, fake_n); return false; } - phton16(fake_tls+*fake_tls_size,21); - *fake_tls_size+=2; - modcache->padlen_offset=*fake_tls_size; - phton16(fake_tls+*fake_tls_size,0); - *fake_tls_size+=2; - phton16(fake_tls+modcache->extlen_offset,pntoh16(fake_tls+modcache->extlen_offset)+4); - phton16(fake_tls+3,pntoh16(fake_tls+3)+4); // increase tls record len - phton24(fake_tls+6,pntoh24(fake_tls+6)+4); // increase tls handshake len + phton16(fake_tls + *fake_tls_size, 21); + *fake_tls_size += 2; + modcache->padlen_offset = *fake_tls_size; + phton16(fake_tls + *fake_tls_size, 0); + *fake_tls_size += 2; + phton16(fake_tls + modcache->extlen_offset, pntoh16(fake_tls + modcache->extlen_offset) + 4); + phton16(fake_tls + 3, pntoh16(fake_tls + 3) + 4); // increase tls record len + phton24(fake_tls + 6, pntoh24(fake_tls + 6) + 4); // increase tls handshake len DLOG("profile %d fake[%d] tls padding is absent. added. padding length offset %zu\n", profile_n, fake_n, modcache->padlen_offset); } } @@ -1472,19 +1471,19 @@ static bool onetime_tls_mod(struct desync_profile *dp) { struct blob_item *fake_tls; struct fake_tls_mod *tls_mod; - int n=0; + int n = 0; LIST_FOREACH(fake_tls, &dp->fake_tls, next) { ++n; tls_mod = (struct fake_tls_mod *)fake_tls->extra2; if (!tls_mod) continue; - if (dp->n && !(tls_mod->mod & (FAKE_TLS_MOD_SET|FAKE_TLS_MOD_CUSTOM_FAKE))) - tls_mod->mod |= FAKE_TLS_MOD_RND|FAKE_TLS_MOD_RND_SNI|FAKE_TLS_MOD_DUP_SID; // old behavior compat + dup_sid + if (dp->n && !(tls_mod->mod & (FAKE_TLS_MOD_SET | FAKE_TLS_MOD_CUSTOM_FAKE))) + tls_mod->mod |= FAKE_TLS_MOD_RND | FAKE_TLS_MOD_RND_SNI | FAKE_TLS_MOD_DUP_SID; // old behavior compat + dup_sid if (!(tls_mod->mod & ~FAKE_TLS_MOD_SAVE_MASK)) continue; - if (!IsTLSClientHello(fake_tls->data,fake_tls->size,false) || (fake_tls->size < (44+fake_tls->data[43]))) // has session id ? + if (!IsTLSClientHello(fake_tls->data, fake_tls->size, false) || (fake_tls->size < (44 + fake_tls->data[43]))) // has session id ? { DLOG("profile %d fake[%d] tls mod set but tls fake structure invalid.\n", dp->n, n); return false; @@ -1494,7 +1493,7 @@ static bool onetime_tls_mod(struct desync_profile *dp) fake_tls->extra = malloc(sizeof(struct fake_tls_mod_cache)); if (!fake_tls->extra) return false; } - if (!onetime_tls_mod_blob(dp->n,n,tls_mod,fake_tls->data,&fake_tls->size,fake_tls->size_buf,(struct fake_tls_mod_cache*)fake_tls->extra)) + if (!onetime_tls_mod_blob(dp->n, n, tls_mod, fake_tls->data, &fake_tls->size, fake_tls->size_buf, (struct fake_tls_mod_cache*)fake_tls->extra)) return false; if (fake_tls->offset >= fake_tls->size) { @@ -1510,40 +1509,40 @@ static struct blob_item *load_blob_to_collection(const char *filename, struct bl struct blob_item *blob = blob_collection_add(blobs); uint8_t *p; - if (!blob || (!(blob->data = malloc(max_size+size_reserve)))) + if (!blob || (!(blob->data = malloc(max_size + size_reserve)))) { DLOG_ERR("out of memory\n"); exit_clean(1); } blob->size = max_size; - load_file_or_exit(filename,blob->data,&blob->size,&blob->offset); - p = realloc(blob->data,blob->size+size_reserve); + load_file_or_exit(filename, blob->data, &blob->size, &blob->offset); + p = realloc(blob->data, blob->size + size_reserve); if (!p) { DLOG_ERR("out of memory\n"); exit_clean(1); } blob->data = p; - blob->size_buf = blob->size+size_reserve; + blob->size_buf = blob->size + size_reserve; return blob; } -static struct blob_item *load_const_blob_to_collection(const void *data,size_t sz, struct blob_collection_head *blobs, size_t size_reserve, size_t offset) +static struct blob_item *load_const_blob_to_collection(const void *data, size_t sz, struct blob_collection_head *blobs, size_t size_reserve, size_t offset) { if (offset >= sz) { - DLOG_ERR("offset %zu is out of data range %zu\n",offset,sz); + DLOG_ERR("offset %zu is out of data range %zu\n", offset, sz); exit_clean(1); } struct blob_item *blob = blob_collection_add(blobs); - if (!blob || (!(blob->data = malloc(sz+size_reserve)))) + if (!blob || (!(blob->data = malloc(sz + size_reserve)))) { DLOG_ERR("out of memory\n"); exit_clean(1); } blob->size = sz; - blob->size_buf = sz+size_reserve; + blob->size_buf = sz + size_reserve; blob->offset = offset; - memcpy(blob->data,data,sz); + memcpy(blob->data, data, sz); return blob; } @@ -1551,32 +1550,32 @@ static struct blob_item *load_const_blob_to_collection(const void *data,size_t s #ifdef __CYGWIN__ static bool wf_make_pf(char *opt, const char *l4, const char *portname, char *buf, size_t len) { - char *e,*p,c,s1[64]; + char *e, *p, c, s1[64]; port_filter pf; int n; - if (len<3) return false; + if (len < 3) return false; - for (n=0,p=opt,*buf='(',buf[1]=0 ; p ; n++) + for (n = 0, p = opt, *buf = '(', buf[1] = 0; p; n++) { - if ((e = strchr(p,','))) + if ((e = strchr(p, ','))) { - c=*e; - *e=0; + c = *e; + *e = 0; } - if (!pf_parse(p,&pf)) return false; + if (!pf_parse(p, &pf)) return false; - if (pf.from==pf.to) + if (pf.from == pf.to) snprintf(s1, sizeof(s1), "(%s.%s %s %u)", l4, portname, pf.neg ? "!=" : "==", pf.from); else - snprintf(s1, sizeof(s1), "(%s.%s %s %u %s %s.%s %s %u)", l4, portname, pf.neg ? "<" : ">=", pf.from, pf.neg ? "or" : "and" , l4, portname, pf.neg ? ">" : "<=", pf.to); - if (n) strncat(buf," or ",len-strlen(buf)-1); - strncat(buf, s1, len-strlen(buf)-1); + snprintf(s1, sizeof(s1), "(%s.%s %s %u %s %s.%s %s %u)", l4, portname, pf.neg ? "<" : ">=", pf.from, pf.neg ? "or" : "and", l4, portname, pf.neg ? ">" : "<=", pf.to); + if (n) strncat(buf, " or ", len - strlen(buf) - 1); + strncat(buf, s1, len - strlen(buf) - 1); - if (e) *e++=c; + if (e) *e++ = c; p = e; } - strncat(buf, ")", len-strlen(buf)-1); + strncat(buf, ")", len - strlen(buf) - 1); return true; } @@ -1619,33 +1618,33 @@ static bool wf_make_pf(char *opt, const char *l4, const char *portname, char *bu static bool wf_make_filter( char *wf, size_t len, - unsigned int IfIdx,unsigned int SubIfIdx, + unsigned int IfIdx, unsigned int SubIfIdx, bool ipv4, bool ipv6, const char *pf_tcp_src, const char *pf_tcp_dst, const char *pf_udp_src, const char *pf_udp_dst, const struct str_list_head *wf_raw_part, bool bFilterOutLAN) { - char pf_dst_buf[8192],iface[64]; + char pf_dst_buf[8192], iface[64]; struct str_list *wfpart; int n; const char *pf_dst; const char *f_tcpin = *pf_tcp_src ? dp_list_have_autohostlist(¶ms.desync_profiles) ? "(" DIVERT_TCP_INBOUNDS " or (" DIVERT_HTTP_REDIRECT "))" : DIVERT_TCP_INBOUNDS : ""; const char *f_tcp_not_empty = (*pf_tcp_src && !dp_list_need_all_out(¶ms.desync_profiles)) ? DIVERT_TCP_NOT_EMPTY " and " : ""; - snprintf(iface,sizeof(iface)," ifIdx=%u and subIfIdx=%u and",IfIdx,SubIfIdx); + snprintf(iface, sizeof(iface), " ifIdx=%u and subIfIdx=%u and", IfIdx, SubIfIdx); - snprintf(wf,len,"%s and%s%s\n(", + snprintf(wf, len, "%s and%s%s\n(", DIVERT_PROLOG, IfIdx ? iface : "", ipv4 ? ipv6 ? "" : " ip and" : " ipv6 and" ); - n=0; + n = 0; if (!LIST_EMPTY(wf_raw_part)) { LIST_FOREACH(wfpart, wf_raw_part, next) { - snprintf(wf+strlen(wf),len-strlen(wf),"%s(\n%s\n )", n ? "\n or\n " : "\n " ,wfpart->str); + snprintf(wf + strlen(wf), len - strlen(wf), "%s(\n%s\n )", n ? "\n or\n " : "\n ", wfpart->str); n++; } } @@ -1654,15 +1653,15 @@ static bool wf_make_filter( { if (*pf_tcp_src && *pf_udp_src) { - snprintf(pf_dst_buf,sizeof(pf_dst_buf),"(%s or %s)",pf_tcp_dst,pf_udp_dst); + snprintf(pf_dst_buf, sizeof(pf_dst_buf), "(%s or %s)", pf_tcp_dst, pf_udp_dst); pf_dst = pf_dst_buf; } else pf_dst = *pf_tcp_dst ? pf_tcp_dst : pf_udp_dst; - snprintf(wf+strlen(wf),len-strlen(wf), n++ ? "\n or\n " : "\n "); + snprintf(wf + strlen(wf), len - strlen(wf), n++ ? "\n or\n " : "\n "); - snprintf(wf+strlen(wf),len-strlen(wf), + snprintf(wf + strlen(wf), len - strlen(wf), "(\n (outbound and %s%s)\n or\n (inbound and tcp%s%s%s%s%s)\n )", f_tcp_not_empty, pf_dst, @@ -1673,20 +1672,20 @@ static bool wf_make_filter( *pf_tcp_src ? pf_tcp_src : ""); } - strncat(wf,"\n)",len-strlen(wf)-1); + strncat(wf, "\n)", len - strlen(wf) - 1); if (bFilterOutLAN) - snprintf(wf+strlen(wf),len-strlen(wf),"\nand\n(\n outbound and %s\n or\n inbound and %s\n)\n", + snprintf(wf + strlen(wf), len - strlen(wf), "\nand\n(\n outbound and %s\n or\n inbound and %s\n)\n", ipv4 ? ipv6 ? DIVERT_NO_LOCALNETS_DST : DIVERT_NO_LOCALNETSv4_DST : DIVERT_NO_LOCALNETSv6_DST, ipv4 ? ipv6 ? DIVERT_NO_LOCALNETS_SRC : DIVERT_NO_LOCALNETSv4_SRC : DIVERT_NO_LOCALNETSv6_SRC); return true; } -static unsigned int hash_jen(const void *data,unsigned int len) +static unsigned int hash_jen(const void *data, unsigned int len) { unsigned int hash; - HASH_JEN(data,len,hash); + HASH_JEN(data, len, hash); return hash; } @@ -1843,13 +1842,13 @@ static void exithelp(void) CTRACK_T_SYN, CTRACK_T_EST, CTRACK_T_FIN, CTRACK_T_UDP, IPCACHE_LIFETIME, HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT, HOSTLIST_AUTO_FAIL_TIME_DEFAULT, HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT, - AUTOTTL_DEFAULT_ORIG_DELTA,AUTOTTL_DEFAULT_ORIG_MIN,AUTOTTL_DEFAULT_ORIG_MAX, - AUTOTTL_DEFAULT_DUP_DELTA,AUTOTTL_DEFAULT_DUP_MIN,AUTOTTL_DEFAULT_DUP_MAX, + AUTOTTL_DEFAULT_ORIG_DELTA, AUTOTTL_DEFAULT_ORIG_MIN, AUTOTTL_DEFAULT_ORIG_MAX, + AUTOTTL_DEFAULT_DUP_DELTA, AUTOTTL_DEFAULT_DUP_MIN, AUTOTTL_DEFAULT_DUP_MAX, TS_INCREMENT_DEFAULT, BADSEQ_INCREMENT_DEFAULT, BADSEQ_ACK_INCREMENT_DEFAULT, #if defined(__linux__) || defined(SO_USER_COOKIE) - DPI_DESYNC_FWMARK_DEFAULT,DPI_DESYNC_FWMARK_DEFAULT, + DPI_DESYNC_FWMARK_DEFAULT, DPI_DESYNC_FWMARK_DEFAULT, #endif - AUTOTTL_DEFAULT_DESYNC_DELTA,AUTOTTL_DEFAULT_DESYNC_MIN,AUTOTTL_DEFAULT_DESYNC_MAX, + AUTOTTL_DEFAULT_DESYNC_DELTA, AUTOTTL_DEFAULT_DESYNC_MIN, AUTOTTL_DEFAULT_DESYNC_MAX, DPI_DESYNC_MAX_FAKE_LEN, IPFRAG_UDP_DEFAULT, DPI_DESYNC_MAX_FAKE_LEN, IPFRAG_TCP_DEFAULT, TS_INCREMENT_DEFAULT, BADSEQ_INCREMENT_DEFAULT, BADSEQ_ACK_INCREMENT_DEFAULT, @@ -1869,22 +1868,22 @@ void config_from_file(const char *filename) { // config from a file char buf[MAX_CONFIG_FILE_SIZE]; - buf[0]='x'; // fake argv[0] - buf[1]=' '; - size_t bufsize=sizeof(buf)-3; - if (!load_file(filename,buf+2,&bufsize)) + buf[0] = 'x'; // fake argv[0] + buf[1] = ' '; + size_t bufsize = sizeof(buf) - 3; + if (!load_file(filename, buf + 2, &bufsize)) { - DLOG_ERR("could not load config file '%s'\n",filename); + DLOG_ERR("could not load config file '%s'\n", filename); exit_clean(1); } - buf[bufsize+2]=0; + buf[bufsize + 2] = 0; // wordexp fails if it sees \t \n \r between args - replace_char(buf,'\n',' '); - replace_char(buf,'\r',' '); - replace_char(buf,'\t',' '); + replace_char(buf, '\n', ' '); + replace_char(buf, '\r', ' '); + replace_char(buf, '\t', ' '); if (wordexp(buf, ¶ms.wexp, WRDE_NOCMD)) { - DLOG_ERR("failed to split command line options from file '%s'\n",filename); + DLOG_ERR("failed to split command line options from file '%s'\n", filename); exit_clean(1); } } @@ -1894,9 +1893,9 @@ void check_dp(const struct desync_profile *dp) { // only linux has connbytes limiter if ((dp->desync_any_proto && !dp->desync_cutoff && - (dp->desync_mode==DESYNC_FAKE || dp->desync_mode==DESYNC_RST || dp->desync_mode==DESYNC_RSTACK || - dp->desync_mode==DESYNC_FAKEDSPLIT || dp->desync_mode==DESYNC_FAKEDDISORDER || dp->desync_mode==DESYNC_HOSTFAKESPLIT || - dp->desync_mode2==DESYNC_FAKEDSPLIT || dp->desync_mode2==DESYNC_FAKEDDISORDER || dp->desync_mode2==DESYNC_HOSTFAKESPLIT)) + (dp->desync_mode == DESYNC_FAKE || dp->desync_mode == DESYNC_RST || dp->desync_mode == DESYNC_RSTACK || + dp->desync_mode == DESYNC_FAKEDSPLIT || dp->desync_mode == DESYNC_FAKEDDISORDER || dp->desync_mode == DESYNC_HOSTFAKESPLIT || + dp->desync_mode2 == DESYNC_FAKEDSPLIT || dp->desync_mode2 == DESYNC_FAKEDDISORDER || dp->desync_mode2 == DESYNC_HOSTFAKESPLIT)) || dp->dup_repeats && !dp->dup_cutoff) { @@ -2214,9 +2213,9 @@ int main(int argc, char **argv) struct ipset_file *anon_ips = NULL, *anon_ips_exclude = NULL; #ifdef __CYGWIN__ char windivert_filter[16384], wf_pf_tcp_src[4096], wf_pf_tcp_dst[4096], wf_pf_udp_src[4096], wf_pf_udp_dst[4096], wf_save_file[256]; - bool wf_ipv4=true, wf_ipv6=true, wf_filter_lan=true; - unsigned int IfIdx=0, SubIfIdx=0; - unsigned int hash_wf_tcp=0,hash_wf_udp=0,hash_wf_raw=0,hash_wf_raw_part=0,hash_ssid_filter=0,hash_nlm_filter=0; + bool wf_ipv4 = true, wf_ipv6 = true, wf_filter_lan = true; + unsigned int IfIdx = 0, SubIfIdx = 0; + unsigned int hash_wf_tcp = 0, hash_wf_udp = 0, hash_wf_raw = 0, hash_wf_raw_part = 0, hash_ssid_filter = 0, hash_nlm_filter = 0; *windivert_filter = *wf_pf_tcp_src = *wf_pf_tcp_dst = *wf_pf_udp_src = *wf_pf_udp_dst = *wf_save_file = 0; #endif @@ -2229,7 +2228,7 @@ int main(int argc, char **argv) struct desync_profile_list *dpl; struct desync_profile *dp; - int desync_profile_count=0; + int desync_profile_count = 0; if (!(dpl = dp_list_add(¶ms.desync_profiles))) { @@ -2268,11 +2267,11 @@ int main(int argc, char **argv) #endif #if !defined( __OpenBSD__) && !defined(__ANDROID__) - if (argc>=2 && (argv[1][0]=='@' || argv[1][0]=='$')) + if (argc >= 2 && (argv[1][0] == '@' || argv[1][0] == '$')) { - config_from_file(argv[1]+1); - argv=params.wexp.we_wordv; - argc=params.wexp.we_wordc; + config_from_file(argv[1] + 1); + argv = params.wexp.we_wordv; + argc = params.wexp.we_wordc; } #endif @@ -2291,11 +2290,11 @@ int main(int argc, char **argv) case IDX_DEBUG: if (optarg) { - if (*optarg=='@') + if (*optarg == '@') { - strncpy(params.debug_logfile,optarg+1,sizeof(params.debug_logfile)); - params.debug_logfile[sizeof(params.debug_logfile)-1] = 0; - FILE *F = fopen(params.debug_logfile,"wt"); + strncpy(params.debug_logfile, optarg + 1, sizeof(params.debug_logfile)); + params.debug_logfile[sizeof(params.debug_logfile) - 1] = 0; + FILE *F = fopen(params.debug_logfile, "wt"); if (!F) { fprintf(stderr, "cannot create %s\n", params.debug_logfile); @@ -2304,20 +2303,20 @@ int main(int argc, char **argv) params.debug = true; params.debug_target = LOG_TARGET_FILE; } - else if (!strcmp(optarg,"syslog")) + else if (!strcmp(optarg, "syslog")) { params.debug = true; params.debug_target = LOG_TARGET_SYSLOG; - openlog(progname,LOG_PID,LOG_USER); + openlog(progname, LOG_PID, LOG_USER); } #ifdef __ANDROID__ - else if (!strcmp(optarg,"android")) + else if (!strcmp(optarg, "android")) { if (!params.debug) params.debug = 1; params.debug_target = LOG_TARGET_ANDROID; } #endif - else if (optarg[0]>='0' && optarg[0]<='1') + else if (optarg[0] >= '0' && optarg[0] <= '1') { params.debug = atoi(optarg); params.debug_target = LOG_TARGET_CONSOLE; @@ -2335,7 +2334,7 @@ int main(int argc, char **argv) } break; case IDX_DRY_RUN: - bDry=true; + bDry = true; break; case IDX_VERSION: exit_clean(0); @@ -2353,27 +2352,27 @@ int main(int argc, char **argv) break; #elif defined(BSD) case IDX_PORT: + { + int i = atoi(optarg); + if (i <= 0 || i > 65535) { - int i = atoi(optarg); - if (i <= 0 || i > 65535) - { - DLOG_ERR("bad port number\n"); - exit_clean(1); - } - params.port = (uint16_t)i; + DLOG_ERR("bad port number\n"); + exit_clean(1); } - break; + params.port = (uint16_t)i; + } + break; #endif case IDX_DAEMON: params.daemon = true; break; case IDX_PIDFILE: - snprintf(params.pidfile,sizeof(params.pidfile),"%s",optarg); + snprintf(params.pidfile, sizeof(params.pidfile), "%s", optarg); break; #ifndef __CYGWIN__ case IDX_USER: { - free(params.user); params.user=NULL; + free(params.user); params.user = NULL; struct passwd *pwd = getpwnam(optarg); if (!pwd) { @@ -2381,9 +2380,9 @@ int main(int argc, char **argv) exit_clean(1); } params.uid = pwd->pw_uid; - params.gid[0]=pwd->pw_gid; - params.gid_count=1; - if (!(params.user=strdup(optarg))) + params.gid[0] = pwd->pw_gid; + params.gid_count = 1; + if (!(params.user = strdup(optarg))) { DLOG_ERR("strdup: out of memory\n"); exit_clean(1); @@ -2392,8 +2391,8 @@ int main(int argc, char **argv) break; } case IDX_UID: - free(params.user); params.user=NULL; - if (!parse_uid(optarg,¶ms.uid,params.gid,¶ms.gid_count,MAX_GIDS)) + free(params.user); params.user = NULL; + if (!parse_uid(optarg, ¶ms.uid, params.gid, ¶ms.gid_count, MAX_GIDS)) { DLOG_ERR("--uid should be : uid[:gid,gid,...]\n"); exit_clean(1); @@ -2407,11 +2406,11 @@ int main(int argc, char **argv) break; #endif case IDX_WSIZE: - if (!parse_ws_scale_factor(optarg,&dp->wsize,&dp->wscale)) + if (!parse_ws_scale_factor(optarg, &dp->wsize, &dp->wscale)) exit_clean(1); break; case IDX_WSSIZE: - if (!parse_ws_scale_factor(optarg,&dp->wssize,&dp->wsscale)) + if (!parse_ws_scale_factor(optarg, &dp->wssize, &dp->wsscale)) exit_clean(1); break; case IDX_WSSIZE_CUTOFF: @@ -2425,11 +2424,11 @@ int main(int argc, char **argv) dp->synack_split = SS_SYN; if (optarg) { - if (!strcmp(optarg,"synack")) + if (!strcmp(optarg, "synack")) dp->synack_split = SS_SYNACK; - else if (!strcmp(optarg,"acksyn")) + else if (!strcmp(optarg, "acksyn")) dp->synack_split = SS_ACKSYN; - else if (strcmp(optarg,"syn")) + else if (strcmp(optarg, "syn")) { DLOG_ERR("invalid synack-split value\n"); exit_clean(1); @@ -2437,7 +2436,7 @@ int main(int argc, char **argv) } break; case IDX_CTRACK_TIMEOUTS: - if (sscanf(optarg, "%u:%u:%u:%u", ¶ms.ctrack_t_syn, ¶ms.ctrack_t_est, ¶ms.ctrack_t_fin, ¶ms.ctrack_t_udp)<3) + if (sscanf(optarg, "%u:%u:%u:%u", ¶ms.ctrack_t_syn, ¶ms.ctrack_t_est, ¶ms.ctrack_t_fin, ¶ms.ctrack_t_udp) < 3) { DLOG_ERR("invalid ctrack-timeouts value\n"); exit_clean(1); @@ -2447,7 +2446,7 @@ int main(int argc, char **argv) params.ctrack_disable = !optarg || atoi(optarg); break; case IDX_IPCACHE_LIFETIME: - if (sscanf(optarg, "%u", ¶ms.ipcache_lifetime)!=1) + if (sscanf(optarg, "%u", ¶ms.ipcache_lifetime) != 1) { DLOG_ERR("invalid ipcache-lifetime value\n"); exit_clean(1); @@ -2488,50 +2487,50 @@ int main(int argc, char **argv) dp->methodeol = true; break; case IDX_DPI_DESYNC: - { - char *mode=optarg,*mode2,*mode3; - mode2 = mode ? strchr(mode,',') : NULL; - if (mode2) *mode2++=0; - mode3 = mode2 ? strchr(mode2,',') : NULL; - if (mode3) *mode3++=0; + { + char *mode = optarg, *mode2, *mode3; + mode2 = mode ? strchr(mode, ',') : NULL; + if (mode2) *mode2++ = 0; + mode3 = mode2 ? strchr(mode2, ',') : NULL; + if (mode3) *mode3++ = 0; - dp->desync_mode0 = desync_mode_from_string(mode); - if (desync_valid_zero_stage(dp->desync_mode0)) - { - mode = mode2; - mode2 = mode3; - mode3 = NULL; - } - else - { - dp->desync_mode0 = DESYNC_NONE; - } - dp->desync_mode = desync_mode_from_string(mode); - dp->desync_mode2 = desync_mode_from_string(mode2); - if (dp->desync_mode0==DESYNC_INVALID || dp->desync_mode==DESYNC_INVALID || dp->desync_mode2==DESYNC_INVALID) - { - DLOG_ERR("invalid dpi-desync mode\n"); - exit_clean(1); - } - if (mode3) - { - DLOG_ERR("invalid desync combo : %s+%s+%s\n",mode,mode2,mode3); - exit_clean(1); - } - if (dp->desync_mode2 && (desync_only_first_stage(dp->desync_mode) || !(desync_valid_first_stage(dp->desync_mode) && desync_valid_second_stage(dp->desync_mode2)))) - { - DLOG_ERR("invalid desync combo : %s+%s\n", mode,mode2); - exit_clean(1); - } - #if defined(__OpenBSD__) - if (dp->desync_mode==DESYNC_IPFRAG2 || dp->desync_mode2==DESYNC_IPFRAG2) - { - DLOG_ERR("OpenBSD has checksum issues with fragmented packets. ipfrag disabled.\n"); - exit_clean(1); - } - #endif + dp->desync_mode0 = desync_mode_from_string(mode); + if (desync_valid_zero_stage(dp->desync_mode0)) + { + mode = mode2; + mode2 = mode3; + mode3 = NULL; } - break; + else + { + dp->desync_mode0 = DESYNC_NONE; + } + dp->desync_mode = desync_mode_from_string(mode); + dp->desync_mode2 = desync_mode_from_string(mode2); + if (dp->desync_mode0 == DESYNC_INVALID || dp->desync_mode == DESYNC_INVALID || dp->desync_mode2 == DESYNC_INVALID) + { + DLOG_ERR("invalid dpi-desync mode\n"); + exit_clean(1); + } + if (mode3) + { + DLOG_ERR("invalid desync combo : %s+%s+%s\n", mode, mode2, mode3); + exit_clean(1); + } + if (dp->desync_mode2 && (desync_only_first_stage(dp->desync_mode) || !(desync_valid_first_stage(dp->desync_mode) && desync_valid_second_stage(dp->desync_mode2)))) + { + DLOG_ERR("invalid desync combo : %s+%s\n", mode, mode2); + exit_clean(1); + } +#if defined(__OpenBSD__) + if (dp->desync_mode == DESYNC_IPFRAG2 || dp->desync_mode2 == DESYNC_IPFRAG2) + { + DLOG_ERR("OpenBSD has checksum issues with fragmented packets. ipfrag disabled.\n"); + exit_clean(1); + } +#endif + } + break; #if defined(__linux__) case IDX_DPI_DESYNC_FWMARK: #elif defined(SO_USER_COOKIE) @@ -2539,7 +2538,7 @@ int main(int argc, char **argv) #endif #if defined(__linux__) || defined(SO_USER_COOKIE) params.desync_fwmark = 0; - if (sscanf(optarg, "0x%X", ¶ms.desync_fwmark)<=0) sscanf(optarg, "%u", ¶ms.desync_fwmark); + if (sscanf(optarg, "0x%X", ¶ms.desync_fwmark) <= 0) sscanf(optarg, "%u", ¶ms.desync_fwmark); if (!params.desync_fwmark) { DLOG_ERR("fwmark/sockarg should be decimal or 0xHEX and should not be zero\n"); @@ -2549,7 +2548,7 @@ int main(int argc, char **argv) #endif case IDX_DUP: - if (sscanf(optarg,"%u",&dp->dup_repeats)<1 || dp->dup_repeats>1024) + if (sscanf(optarg, "%u", &dp->dup_repeats) < 1 || dp->dup_repeats > 1024) { DLOG_ERR("dup-repeats must be within 0..1024\n"); exit_clean(1); @@ -2567,7 +2566,7 @@ int main(int argc, char **argv) DLOG_ERR("dup-autottl value error\n"); exit_clean(1); } - params.autottl_present=true; + params.autottl_present = true; break; case IDX_DUP_AUTOTTL6: if (!parse_autottl(optarg, &dp->dup_autottl6, AUTOTTL_DEFAULT_DUP_DELTA, AUTOTTL_DEFAULT_DUP_MIN, AUTOTTL_DEFAULT_DUP_MAX)) @@ -2575,34 +2574,34 @@ int main(int argc, char **argv) DLOG_ERR("dup-autottl6 value error\n"); exit_clean(1); } - params.autottl_present=true; + params.autottl_present = true; break; case IDX_DUP_REPLACE: dp->dup_replace = !optarg || atoi(optarg); break; case IDX_DUP_FOOLING: - if (!parse_fooling(optarg,&dp->dup_fooling_mode)) + if (!parse_fooling(optarg, &dp->dup_fooling_mode)) { DLOG_ERR("fooling allowed values : none,md5sig,ts,badseq,badsum,datanoack,hopbyhop,hopbyhop2\n"); exit_clean(1); } break; case IDX_DUP_TS_INCREMENT: - if (!parse_net32_signed(optarg,&dp->dup_ts_increment)) + if (!parse_net32_signed(optarg, &dp->dup_ts_increment)) { DLOG_ERR("dup-ts-increment should be signed decimal or signed 0xHEX\n"); exit_clean(1); } break; case IDX_DUP_BADSEQ_INCREMENT: - if (!parse_net32_signed(optarg,&dp->dup_badseq_increment)) + if (!parse_net32_signed(optarg, &dp->dup_badseq_increment)) { DLOG_ERR("dup-badseq-increment should be signed decimal or signed 0xHEX\n"); exit_clean(1); } break; case IDX_DUP_BADACK_INCREMENT: - if (!parse_net32_signed(optarg,&dp->dup_badseq_ack_increment)) + if (!parse_net32_signed(optarg, &dp->dup_badseq_ack_increment)) { DLOG_ERR("dup-badack-increment should be signed decimal or signed 0xHEX\n"); exit_clean(1); @@ -2635,7 +2634,7 @@ int main(int argc, char **argv) DLOG_ERR("orig-autottl value error\n"); exit_clean(1); } - params.autottl_present=true; + params.autottl_present = true; break; case IDX_ORIG_AUTOTTL6: if (!parse_autottl(optarg, &dp->orig_autottl6, AUTOTTL_DEFAULT_ORIG_DELTA, AUTOTTL_DEFAULT_ORIG_MIN, AUTOTTL_DEFAULT_ORIG_MAX)) @@ -2643,7 +2642,7 @@ int main(int argc, char **argv) DLOG_ERR("orig-autottl6 value error\n"); exit_clean(1); } - params.autottl_present=true; + params.autottl_present = true; break; case IDX_ORIG_MOD_CUTOFF: if (!parse_cutoff(optarg, &dp->orig_mod_cutoff, &dp->orig_mod_cutoff_mode)) @@ -2672,7 +2671,7 @@ int main(int argc, char **argv) DLOG_ERR("dpi-desync-autottl value error\n"); exit_clean(1); } - params.autottl_present=true; + params.autottl_present = true; break; case IDX_DPI_DESYNC_AUTOTTL6: if (!parse_autottl(optarg, &dp->desync_autottl6, AUTOTTL_DEFAULT_DESYNC_DELTA, AUTOTTL_DEFAULT_DESYNC_MIN, AUTOTTL_DEFAULT_DESYNC_MAX)) @@ -2680,17 +2679,17 @@ int main(int argc, char **argv) DLOG_ERR("dpi-desync-autottl6 value error\n"); exit_clean(1); } - params.autottl_present=true; + params.autottl_present = true; break; case IDX_DPI_DESYNC_FOOLING: - if (!parse_fooling(optarg,&dp->desync_fooling_mode)) + if (!parse_fooling(optarg, &dp->desync_fooling_mode)) { DLOG_ERR("fooling allowed values : none,md5sig,ts,badseq,badsum,datanoack,hopbyhop,hopbyhop2\n"); exit_clean(1); } break; case IDX_DPI_DESYNC_REPEATS: - if (sscanf(optarg,"%u",&dp->desync_repeats)<1 || !dp->desync_repeats || dp->desync_repeats>1024) + if (sscanf(optarg, "%u", &dp->desync_repeats) < 1 || !dp->desync_repeats || dp->desync_repeats > 1024) { DLOG_ERR("dpi-desync-repeats must be within 1..1024\n"); exit_clean(1); @@ -2700,22 +2699,22 @@ int main(int argc, char **argv) dp->desync_skip_nosni = !optarg || atoi(optarg); break; case IDX_DPI_DESYNC_SPLIT_POS: + { + int ct; + if (!parse_split_pos_list(optarg, dp->splits + dp->split_count, MAX_SPLITS - dp->split_count, &ct)) { - int ct; - if (!parse_split_pos_list(optarg,dp->splits+dp->split_count,MAX_SPLITS-dp->split_count,&ct)) - { - DLOG_ERR("could not parse split pos list or too much positions (before parsing - %u, max - %u) : %s\n",dp->split_count,MAX_SPLITS,optarg); - exit_clean(1); - } - dp->split_count += ct; + DLOG_ERR("could not parse split pos list or too much positions (before parsing - %u, max - %u) : %s\n", dp->split_count, MAX_SPLITS, optarg); + exit_clean(1); } - break; + dp->split_count += ct; + } + break; case IDX_DPI_DESYNC_SPLIT_HTTP_REQ: // obsolete arg - DLOG_CONDUP("WARNING ! --dpi-desync-split-http-req is deprecated. use --dpi-desync-split-pos with markers.\n",MAX_SPLITS); - if (dp->split_count>=MAX_SPLITS) + DLOG_CONDUP("WARNING ! --dpi-desync-split-http-req is deprecated. use --dpi-desync-split-pos with markers.\n", MAX_SPLITS); + if (dp->split_count >= MAX_SPLITS) { - DLOG_ERR("Too much splits. max splits: %u\n",MAX_SPLITS); + DLOG_ERR("Too much splits. max splits: %u\n", MAX_SPLITS); exit_clean(1); } if (!parse_httpreqpos(optarg, dp->splits + dp->split_count)) @@ -2727,10 +2726,10 @@ int main(int argc, char **argv) break; case IDX_DPI_DESYNC_SPLIT_TLS: // obsolete arg - DLOG_CONDUP("WARNING ! --dpi-desync-split-tls is deprecated. use --dpi-desync-split-pos with markers.\n",MAX_SPLITS); - if (dp->split_count>=MAX_SPLITS) + DLOG_CONDUP("WARNING ! --dpi-desync-split-tls is deprecated. use --dpi-desync-split-pos with markers.\n", MAX_SPLITS); + if (dp->split_count >= MAX_SPLITS) { - DLOG_ERR("Too much splits. max splits: %u\n",MAX_SPLITS); + DLOG_ERR("Too much splits. max splits: %u\n", MAX_SPLITS); exit_clean(1); } if (!parse_tlspos(optarg, dp->splits + dp->split_count)) @@ -2741,11 +2740,11 @@ int main(int argc, char **argv) dp->split_count++; break; case IDX_DPI_DESYNC_SPLIT_SEQOVL: - if (!strcmp(optarg,"0")) + if (!strcmp(optarg, "0")) { // allow zero = disable seqovl - dp->seqovl.marker=PM_ABS; - dp->seqovl.pos=0; + dp->seqovl.marker = PM_ABS; + dp->seqovl.pos = 0; } else if (!parse_split_pos(optarg, &dp->seqovl)) { @@ -2754,34 +2753,37 @@ int main(int argc, char **argv) } break; case IDX_DPI_DESYNC_SPLIT_SEQOVL_PATTERN: - { - char buf[sizeof(dp->seqovl_pattern)]; - size_t sz=sizeof(buf); - load_file_or_exit(optarg,buf,&sz,NULL); - fill_pattern(dp->seqovl_pattern,sizeof(dp->seqovl_pattern),buf,sz); - } - break; + { + char buf[sizeof(dp->seqovl_pattern)]; + size_t sz = sizeof(buf); + load_file_or_exit(optarg, buf, &sz, NULL); + fill_pattern(dp->seqovl_pattern, sizeof(dp->seqovl_pattern), buf, sz, 0); + } + break; case IDX_DPI_DESYNC_FAKEDSPLIT_PATTERN: + { + if (!(dp->fsplit_pattern = malloc(dp->fsplit_pattern_size=32768))) { - char buf[sizeof(dp->fsplit_pattern)]; - size_t sz=sizeof(buf); - load_file_or_exit(optarg,buf,&sz,NULL); - fill_pattern(dp->fsplit_pattern,sizeof(dp->fsplit_pattern),buf,sz); + DLOG_ERR("out of memory\n"); + exit_clean(1); } - break; + load_file_or_exit(optarg, dp->fsplit_pattern, &dp->fsplit_pattern_size, NULL); + dp->fsplit_pattern = realloc(dp->fsplit_pattern, dp->fsplit_pattern_size); + } + break; case IDX_DPI_DESYNC_FAKEDSPLIT_MOD: - if (!parse_fakedsplit_mod(optarg,&dp->fs_mod)) + if (!parse_fakedsplit_mod(optarg, &dp->fs_mod)) { - DLOG_ERR("Invalid fakedsplit mod : %s\n",optarg); + DLOG_ERR("Invalid fakedsplit mod : %s\n", optarg); exit_clean(1); } break; case IDX_DPI_DESYNC_HOSTFAKESPLIT_MIDHOST: - if (!strcmp(optarg,"0")) + if (!strcmp(optarg, "0")) { // allow zero = disable midhost split - dp->hostfakesplit_midhost.marker=PM_ABS; - dp->hostfakesplit_midhost.pos=0; + dp->hostfakesplit_midhost.marker = PM_ABS; + dp->hostfakesplit_midhost.pos = 0; } else if (!parse_split_pos(optarg, &dp->hostfakesplit_midhost)) { @@ -2790,16 +2792,16 @@ int main(int argc, char **argv) } break; case IDX_DPI_DESYNC_HOSTFAKESPLIT_MOD: - if (!parse_hostfakesplit_mod(optarg,&dp->hfs_mod)) + if (!parse_hostfakesplit_mod(optarg, &dp->hfs_mod)) { - DLOG_ERR("Invalid hostfakesplit mod : %s\n",optarg); + DLOG_ERR("Invalid hostfakesplit mod : %s\n", optarg); exit_clean(1); } break; case IDX_DPI_DESYNC_IPFRAG_POS_TCP: - if (sscanf(optarg,"%u",&dp->desync_ipfrag_pos_tcp)<1 || dp->desync_ipfrag_pos_tcp<1 || dp->desync_ipfrag_pos_tcp>DPI_DESYNC_MAX_FAKE_LEN) + if (sscanf(optarg, "%u", &dp->desync_ipfrag_pos_tcp) < 1 || dp->desync_ipfrag_pos_tcp<1 || dp->desync_ipfrag_pos_tcp>DPI_DESYNC_MAX_FAKE_LEN) { - DLOG_ERR("dpi-desync-ipfrag-pos-tcp must be within 1..%u range\n",DPI_DESYNC_MAX_FAKE_LEN); + DLOG_ERR("dpi-desync-ipfrag-pos-tcp must be within 1..%u range\n", DPI_DESYNC_MAX_FAKE_LEN); exit_clean(1); } if (dp->desync_ipfrag_pos_tcp & 7) @@ -2809,9 +2811,9 @@ int main(int argc, char **argv) } break; case IDX_DPI_DESYNC_IPFRAG_POS_UDP: - if (sscanf(optarg,"%u",&dp->desync_ipfrag_pos_udp)<1 || dp->desync_ipfrag_pos_udp<1 || dp->desync_ipfrag_pos_udp>DPI_DESYNC_MAX_FAKE_LEN) + if (sscanf(optarg, "%u", &dp->desync_ipfrag_pos_udp) < 1 || dp->desync_ipfrag_pos_udp<1 || dp->desync_ipfrag_pos_udp>DPI_DESYNC_MAX_FAKE_LEN) { - DLOG_ERR("dpi-desync-ipfrag-pos-udp must be within 1..%u range\n",DPI_DESYNC_MAX_FAKE_LEN); + DLOG_ERR("dpi-desync-ipfrag-pos-udp must be within 1..%u range\n", DPI_DESYNC_MAX_FAKE_LEN); exit_clean(1); } if (dp->desync_ipfrag_pos_udp & 7) @@ -2821,21 +2823,21 @@ int main(int argc, char **argv) } break; case IDX_DPI_DESYNC_TS_INCREMENT: - if (!parse_net32_signed(optarg,&dp->desync_ts_increment)) + if (!parse_net32_signed(optarg, &dp->desync_ts_increment)) { DLOG_ERR("dpi-desync-ts-increment should be signed decimal or signed 0xHEX\n"); exit_clean(1); } break; case IDX_DPI_DESYNC_BADSEQ_INCREMENT: - if (!parse_net32_signed(optarg,&dp->desync_badseq_increment)) + if (!parse_net32_signed(optarg, &dp->desync_badseq_increment)) { DLOG_ERR("dpi-desync-badseq-increment should be signed decimal or signed 0xHEX\n"); exit_clean(1); } break; case IDX_DPI_DESYNC_BADACK_INCREMENT: - if (!parse_net32_signed(optarg,&dp->desync_badseq_ack_increment)) + if (!parse_net32_signed(optarg, &dp->desync_badseq_ack_increment)) { DLOG_ERR("dpi-desync-badack-increment should be signed decimal or signed 0xHEX\n"); exit_clean(1); @@ -2845,9 +2847,9 @@ int main(int argc, char **argv) dp->desync_any_proto = !optarg || atoi(optarg); break; case IDX_DPI_DESYNC_FAKE_TCP_MOD: - if (!parse_tcpmod(optarg,&dp->tcp_mod)) + if (!parse_tcpmod(optarg, &dp->tcp_mod)) { - DLOG_ERR("Invalid tcp mod : %s\n",optarg); + DLOG_ERR("Invalid tcp mod : %s\n", optarg); exit_clean(1); } break; @@ -2855,25 +2857,25 @@ int main(int argc, char **argv) load_blob_to_collection(optarg, &dp->fake_http, FAKE_MAX_TCP, 0); break; case IDX_DPI_DESYNC_FAKE_TLS: + { + if (optarg[0] == '!' && (optarg[1] == 0 || optarg[1] == '+')) + dp->tls_fake_last = load_const_blob_to_collection(fake_tls_clienthello_default, sizeof(fake_tls_clienthello_default), &dp->fake_tls, 4 + sizeof(dp->tls_mod_last.sni), optarg[1] == '+' ? (size_t)atoi(optarg + 1) : 0); + else + dp->tls_fake_last = load_blob_to_collection(optarg, &dp->fake_tls, FAKE_MAX_TCP, 4 + sizeof(dp->tls_mod_last.sni)); + if (!(dp->tls_fake_last->extra2 = malloc(sizeof(struct fake_tls_mod)))) { - if (optarg[0]=='!' && (optarg[1]==0 || optarg[1]=='+')) - dp->tls_fake_last = load_const_blob_to_collection(fake_tls_clienthello_default,sizeof(fake_tls_clienthello_default),&dp->fake_tls,4+sizeof(dp->tls_mod_last.sni), optarg[1]=='+' ? (size_t)atoi(optarg+1) : 0); - else - dp->tls_fake_last = load_blob_to_collection(optarg, &dp->fake_tls, FAKE_MAX_TCP,4+sizeof(dp->tls_mod_last.sni)); - if (!(dp->tls_fake_last->extra2 = malloc(sizeof(struct fake_tls_mod)))) - { - DLOG_ERR("out of memory\n"); - exit_clean(1); - } - struct fake_tls_mod *tls_mod = (struct fake_tls_mod*)dp->tls_fake_last->extra2; - *tls_mod = dp->tls_mod_last; - tls_mod->mod |= FAKE_TLS_MOD_CUSTOM_FAKE; + DLOG_ERR("out of memory\n"); + exit_clean(1); } - break; + struct fake_tls_mod *tls_mod = (struct fake_tls_mod*)dp->tls_fake_last->extra2; + *tls_mod = dp->tls_mod_last; + tls_mod->mod |= FAKE_TLS_MOD_CUSTOM_FAKE; + } + break; case IDX_DPI_DESYNC_FAKE_TLS_MOD: - if (!parse_tlsmod_list(optarg,&dp->tls_mod_last)) + if (!parse_tlsmod_list(optarg, &dp->tls_mod_last)) { - DLOG_ERR("Invalid tls mod : %s\n",optarg); + DLOG_ERR("Invalid tls mod : %s\n", optarg); exit_clean(1); } if (dp->tls_fake_last) @@ -2884,7 +2886,7 @@ int main(int argc, char **argv) break; case IDX_DPI_DESYNC_FAKE_SYNDATA: dp->fake_syndata_size = sizeof(dp->fake_syndata); - load_file_or_exit(optarg,dp->fake_syndata,&dp->fake_syndata_size,NULL); + load_file_or_exit(optarg, dp->fake_syndata, &dp->fake_syndata_size, NULL); break; case IDX_DPI_DESYNC_FAKE_QUIC: load_blob_to_collection(optarg, &dp->fake_quic, FAKE_MAX_UDP, 0); @@ -2905,20 +2907,20 @@ int main(int argc, char **argv) load_blob_to_collection(optarg, &dp->fake_unknown_udp, FAKE_MAX_UDP, 0); break; case IDX_DPI_DESYNC_UDPLEN_INCREMENT: - if (sscanf(optarg,"%d",&dp->udplen_increment)<1 || dp->udplen_increment>0x7FFF || dp->udplen_increment<-0x8000) + if (sscanf(optarg, "%d", &dp->udplen_increment) < 1 || dp->udplen_increment > 0x7FFF || dp->udplen_increment < -0x8000) { DLOG_ERR("dpi-desync-udplen-increment must be integer within -32768..32767 range\n"); exit_clean(1); } break; case IDX_DPI_DESYNC_UDPLEN_PATTERN: - { - char buf[sizeof(dp->udplen_pattern)]; - size_t sz=sizeof(buf); - load_file_or_exit(optarg,buf,&sz,NULL); - fill_pattern(dp->udplen_pattern,sizeof(dp->udplen_pattern),buf,sz); - } - break; + { + char buf[sizeof(dp->udplen_pattern)]; + size_t sz = sizeof(buf); + load_file_or_exit(optarg, buf, &sz, NULL); + fill_pattern(dp->udplen_pattern, sizeof(dp->udplen_pattern), buf, sz, 0); + } + break; case IDX_DPI_DESYNC_CUTOFF: if (!parse_cutoff(optarg, &dp->desync_cutoff, &dp->desync_cutoff_mode)) { @@ -2943,7 +2945,7 @@ int main(int argc, char **argv) break; case IDX_HOSTLIST_DOMAINS: if (bSkip) break; - if (!anon_hl && !(anon_hl=RegisterHostlist(dp, false, NULL))) + if (!anon_hl && !(anon_hl = RegisterHostlist(dp, false, NULL))) { DLOG_ERR("failed to register anonymous hostlist\n"); exit_clean(1); @@ -2964,7 +2966,7 @@ int main(int argc, char **argv) break; case IDX_HOSTLIST_EXCLUDE_DOMAINS: if (bSkip) break; - if (!anon_hl_exclude && !(anon_hl_exclude=RegisterHostlist(dp, true, NULL))) + if (!anon_hl_exclude && !(anon_hl_exclude = RegisterHostlist(dp, true, NULL))) { DLOG_ERR("failed to register anonymous hostlist\n"); exit_clean(1); @@ -2983,7 +2985,7 @@ int main(int argc, char **argv) exit_clean(1); } { - FILE *F = fopen(optarg,"a+b"); + FILE *F = fopen(optarg, "a+b"); if (!F) { DLOG_ERR("cannot create %s\n", optarg); @@ -2997,7 +2999,7 @@ int main(int argc, char **argv) exit_clean(1); } } - if (!(dp->hostlist_auto=RegisterHostlist(dp, false, optarg))) + if (!(dp->hostlist_auto = RegisterHostlist(dp, false, optarg))) { DLOG_ERR("failed to register hostlist '%s'\n", optarg); exit_clean(1); @@ -3005,7 +3007,7 @@ int main(int argc, char **argv) break; case IDX_HOSTLIST_AUTO_FAIL_THRESHOLD: dp->hostlist_auto_fail_threshold = (uint8_t)atoi(optarg); - if (dp->hostlist_auto_fail_threshold<1 || dp->hostlist_auto_fail_threshold>20) + if (dp->hostlist_auto_fail_threshold < 1 || dp->hostlist_auto_fail_threshold>20) { DLOG_ERR("auto hostlist fail threshold must be within 1..20\n"); exit_clean(1); @@ -3013,7 +3015,7 @@ int main(int argc, char **argv) break; case IDX_HOSTLIST_AUTO_FAIL_TIME: dp->hostlist_auto_fail_time = (uint8_t)atoi(optarg); - if (dp->hostlist_auto_fail_time<1) + if (dp->hostlist_auto_fail_time < 1) { DLOG_ERR("auto hostlist fail time is not valid\n"); exit_clean(1); @@ -3021,25 +3023,25 @@ int main(int argc, char **argv) break; case IDX_HOSTLIST_AUTO_RETRANS_THRESHOLD: dp->hostlist_auto_retrans_threshold = (uint8_t)atoi(optarg); - if (dp->hostlist_auto_retrans_threshold<2 || dp->hostlist_auto_retrans_threshold>10) + if (dp->hostlist_auto_retrans_threshold < 2 || dp->hostlist_auto_retrans_threshold>10) { DLOG_ERR("auto hostlist fail threshold must be within 2..10\n"); exit_clean(1); } break; case IDX_HOSTLIST_AUTO_DEBUG: + { + FILE *F = fopen(optarg, "a+t"); + if (!F) { - FILE *F = fopen(optarg,"a+t"); - if (!F) - { - DLOG_ERR("cannot create %s\n", optarg); - exit_clean(1); - } - fclose(F); - strncpy(params.hostlist_auto_debuglog, optarg, sizeof(params.hostlist_auto_debuglog)); - params.hostlist_auto_debuglog[sizeof(params.hostlist_auto_debuglog) - 1] = '\0'; + DLOG_ERR("cannot create %s\n", optarg); + exit_clean(1); } - break; + fclose(F); + strncpy(params.hostlist_auto_debuglog, optarg, sizeof(params.hostlist_auto_debuglog)); + params.hostlist_auto_debuglog[sizeof(params.hostlist_auto_debuglog) - 1] = '\0'; + } + break; case IDX_NEW: if (bSkip) @@ -3068,16 +3070,16 @@ int main(int argc, char **argv) break; case IDX_FILTER_L3: - if (!wf_make_l3(optarg,&dp->filter_ipv4,&dp->filter_ipv6)) + if (!wf_make_l3(optarg, &dp->filter_ipv4, &dp->filter_ipv6)) { DLOG_ERR("bad value for --filter-l3\n"); exit_clean(1); } break; case IDX_FILTER_TCP: - if (!parse_pf_list(optarg,&dp->pf_tcp)) + if (!parse_pf_list(optarg, &dp->pf_tcp)) { - DLOG_ERR("Invalid port filter : %s\n",optarg); + DLOG_ERR("Invalid port filter : %s\n", optarg); exit_clean(1); } // deny tcp if not set @@ -3085,9 +3087,9 @@ int main(int argc, char **argv) exit_clean(1); break; case IDX_FILTER_UDP: - if (!parse_pf_list(optarg,&dp->pf_udp)) + if (!parse_pf_list(optarg, &dp->pf_udp)) { - DLOG_ERR("Invalid port filter : %s\n",optarg); + DLOG_ERR("Invalid port filter : %s\n", optarg); exit_clean(1); } // deny tcp if not set @@ -3095,15 +3097,15 @@ int main(int argc, char **argv) exit_clean(1); break; case IDX_FILTER_L7: - if (!parse_l7_list(optarg,&dp->filter_l7)) + if (!parse_l7_list(optarg, &dp->filter_l7)) { - DLOG_ERR("Invalid l7 filter : %s\n",optarg); + DLOG_ERR("Invalid l7 filter : %s\n", optarg); exit_clean(1); } break; #ifdef HAS_FILTER_SSID case IDX_FILTER_SSID: - if (!parse_strlist(optarg,&dp->filter_ssid)) + if (!parse_strlist(optarg, &dp->filter_ssid)) { DLOG_ERR("strlist_add failed\n"); exit_clean(1); @@ -3121,7 +3123,7 @@ int main(int argc, char **argv) break; case IDX_IPSET_IP: if (bSkip) break; - if (!anon_ips && !(anon_ips=RegisterIpset(dp, false, NULL))) + if (!anon_ips && !(anon_ips = RegisterIpset(dp, false, NULL))) { DLOG_ERR("failed to register anonymous ipset\n"); exit_clean(1); @@ -3142,7 +3144,7 @@ int main(int argc, char **argv) break; case IDX_IPSET_EXCLUDE_IP: if (bSkip) break; - if (!anon_ips_exclude && !(anon_ips_exclude=RegisterIpset(dp, true, NULL))) + if (!anon_ips_exclude && !(anon_ips_exclude = RegisterIpset(dp, true, NULL))) { DLOG_ERR("failed to register anonymous ipset\n"); exit_clean(1); @@ -3164,43 +3166,43 @@ int main(int argc, char **argv) break; #elif defined(__CYGWIN__) case IDX_WF_IFACE: - if (!sscanf(optarg,"%u.%u",&IfIdx,&SubIfIdx)) + if (!sscanf(optarg, "%u.%u", &IfIdx, &SubIfIdx)) { DLOG_ERR("bad value for --wf-iface\n"); exit_clean(1); } break; case IDX_WF_L3: - if (!wf_make_l3(optarg,&wf_ipv4,&wf_ipv6)) + if (!wf_make_l3(optarg, &wf_ipv4, &wf_ipv6)) { DLOG_ERR("bad value for --wf-l3\n"); exit_clean(1); } break; case IDX_WF_TCP: - hash_wf_tcp=hash_jen(optarg,strlen(optarg)); - if (!wf_make_pf(optarg,"tcp","SrcPort",wf_pf_tcp_src,sizeof(wf_pf_tcp_src)) || - !wf_make_pf(optarg,"tcp","DstPort",wf_pf_tcp_dst,sizeof(wf_pf_tcp_dst))) + hash_wf_tcp = hash_jen(optarg, strlen(optarg)); + if (!wf_make_pf(optarg, "tcp", "SrcPort", wf_pf_tcp_src, sizeof(wf_pf_tcp_src)) || + !wf_make_pf(optarg, "tcp", "DstPort", wf_pf_tcp_dst, sizeof(wf_pf_tcp_dst))) { DLOG_ERR("bad value for --wf-tcp\n"); exit_clean(1); } break; case IDX_WF_UDP: - hash_wf_udp=hash_jen(optarg,strlen(optarg)); - if (!wf_make_pf(optarg,"udp","SrcPort",wf_pf_udp_src,sizeof(wf_pf_udp_src)) || - !wf_make_pf(optarg,"udp","DstPort",wf_pf_udp_dst,sizeof(wf_pf_udp_dst))) + hash_wf_udp = hash_jen(optarg, strlen(optarg)); + if (!wf_make_pf(optarg, "udp", "SrcPort", wf_pf_udp_src, sizeof(wf_pf_udp_src)) || + !wf_make_pf(optarg, "udp", "DstPort", wf_pf_udp_dst, sizeof(wf_pf_udp_dst))) { DLOG_ERR("bad value for --wf-udp\n"); exit_clean(1); } break; case IDX_WF_RAW: - hash_wf_raw=hash_jen(optarg,strlen(optarg)); - if (optarg[0]=='@') + hash_wf_raw = hash_jen(optarg, strlen(optarg)); + if (optarg[0] == '@') { - size_t sz = sizeof(windivert_filter)-1; - load_file_or_exit(optarg,windivert_filter,&sz,NULL); + size_t sz = sizeof(windivert_filter) - 1; + load_file_or_exit(optarg, windivert_filter, &sz, NULL); windivert_filter[sz] = 0; } else @@ -3210,13 +3212,13 @@ int main(int argc, char **argv) } break; case IDX_WF_RAW_PART: - hash_wf_raw_part^=hash_jen(optarg,strlen(optarg)); + hash_wf_raw_part ^= hash_jen(optarg, strlen(optarg)); { char wfpart[sizeof(windivert_filter)]; - if (optarg[0]=='@') + if (optarg[0] == '@') { - size_t sz = sizeof(wfpart)-1; - load_file_or_exit(optarg,wfpart,&sz,NULL); + size_t sz = sizeof(wfpart) - 1; + load_file_or_exit(optarg, wfpart, &sz, NULL); wfpart[sz] = 0; } else @@ -3224,7 +3226,7 @@ int main(int argc, char **argv) strncpy(wfpart, optarg, sizeof(wfpart)); wfpart[sizeof(wfpart) - 1] = '\0'; } - if (!strlist_add(¶ms.wf_raw_part,wfpart)) + if (!strlist_add(¶ms.wf_raw_part, wfpart)) { DLOG_ERR("out of memory\n"); exit_clean(1); @@ -3232,30 +3234,30 @@ int main(int argc, char **argv) } break; case IDX_WF_FILTER_LAN: - wf_filter_lan=!!atoi(optarg); + wf_filter_lan = !!atoi(optarg); break; case IDX_WF_SAVE: strncpy(wf_save_file, optarg, sizeof(wf_save_file)); wf_save_file[sizeof(wf_save_file) - 1] = '\0'; break; case IDX_SSID_FILTER: - hash_ssid_filter=hash_jen(optarg,strlen(optarg)); - if (!parse_strlist(optarg,¶ms.ssid_filter)) + hash_ssid_filter = hash_jen(optarg, strlen(optarg)); + if (!parse_strlist(optarg, ¶ms.ssid_filter)) { DLOG_ERR("strlist_add failed\n"); exit_clean(1); } break; case IDX_NLM_FILTER: - hash_nlm_filter=hash_jen(optarg,strlen(optarg)); - if (!parse_strlist(optarg,¶ms.nlm_filter)) + hash_nlm_filter = hash_jen(optarg, strlen(optarg)); + if (!parse_strlist(optarg, ¶ms.nlm_filter)) { DLOG_ERR("strlist_add failed\n"); exit_clean(1); } break; case IDX_NLM_LIST: - if (!nlm_list(optarg && !strcmp(optarg,"all"))) + if (!nlm_list(optarg && !strcmp(optarg, "all"))) { DLOG_ERR("could not get list of NLM networks\n"); exit_clean(1); @@ -3267,7 +3269,7 @@ int main(int argc, char **argv) } if (bSkip) { - LIST_REMOVE(dpl,next); + LIST_REMOVE(dpl, next); dp_entry_destroy(dpl); desync_profile_count--; } @@ -3278,10 +3280,10 @@ int main(int argc, char **argv) #if !defined( __OpenBSD__) && !defined(__ANDROID__) cleanup_args(¶ms); #endif - argv=NULL; argc=0; - + argv = NULL; argc = 0; + #ifdef __linux__ - if (params.qnum<0) + if (params.qnum < 0) { DLOG_ERR("Need queue number (--qnum)\n"); exit_clean(1); @@ -3302,8 +3304,8 @@ int main(int argc, char **argv) exit_clean(1); } - DLOG_CONDUP("we have %d user defined desync profile(s) and default low priority profile 0\n",desync_profile_count); - + DLOG_CONDUP("we have %d user defined desync profile(s) and default low priority profile 0\n", desync_profile_count); + #ifndef __CYGWIN__ if (params.debug_target == LOG_TARGET_FILE && params.droproot && chown(params.debug_logfile, params.uid, -1)) fprintf(stderr, "could not chown %s. log file may not be writable after privilege drop\n", params.debug_logfile); @@ -3315,24 +3317,24 @@ int main(int argc, char **argv) dp = &dpl->dp; // not specified - use desync_ttl value instead - if (dp->desync_ttl6 == 0xFF) dp->desync_ttl6=dp->desync_ttl; - if (dp->dup_ttl6 == 0xFF) dp->dup_ttl6=dp->dup_ttl; - if (dp->orig_mod_ttl6 == 0xFF) dp->orig_mod_ttl6=dp->orig_mod_ttl; + if (dp->desync_ttl6 == 0xFF) dp->desync_ttl6 = dp->desync_ttl; + if (dp->dup_ttl6 == 0xFF) dp->dup_ttl6 = dp->dup_ttl; + if (dp->orig_mod_ttl6 == 0xFF) dp->orig_mod_ttl6 = dp->orig_mod_ttl; if (!AUTOTTL_ENABLED(dp->desync_autottl6)) dp->desync_autottl6 = dp->desync_autottl; if (!AUTOTTL_ENABLED(dp->orig_autottl6)) dp->orig_autottl6 = dp->orig_autottl; if (!AUTOTTL_ENABLED(dp->dup_autottl6)) dp->dup_autottl6 = dp->dup_autottl; if (AUTOTTL_ENABLED(dp->desync_autottl)) - DLOG("profile %d desync autottl ipv4 %s%d:%u-%u\n",dp->n,UNARY_PLUS(dp->desync_autottl.delta),dp->desync_autottl.delta,dp->desync_autottl.min,dp->desync_autottl.max); + DLOG("profile %d desync autottl ipv4 %s%d:%u-%u\n", dp->n, UNARY_PLUS(dp->desync_autottl.delta), dp->desync_autottl.delta, dp->desync_autottl.min, dp->desync_autottl.max); if (AUTOTTL_ENABLED(dp->desync_autottl6)) - DLOG("profile %d desync autottl ipv6 %s%d:%u-%u\n",dp->n,UNARY_PLUS(dp->desync_autottl6.delta),dp->desync_autottl6.delta,dp->desync_autottl6.min,dp->desync_autottl6.max); + DLOG("profile %d desync autottl ipv6 %s%d:%u-%u\n", dp->n, UNARY_PLUS(dp->desync_autottl6.delta), dp->desync_autottl6.delta, dp->desync_autottl6.min, dp->desync_autottl6.max); if (AUTOTTL_ENABLED(dp->orig_autottl)) - DLOG("profile %d orig autottl ipv4 %s%d:%u-%u\n",dp->n,UNARY_PLUS(dp->orig_autottl.delta),dp->orig_autottl.delta,dp->orig_autottl.min,dp->orig_autottl.max); + DLOG("profile %d orig autottl ipv4 %s%d:%u-%u\n", dp->n, UNARY_PLUS(dp->orig_autottl.delta), dp->orig_autottl.delta, dp->orig_autottl.min, dp->orig_autottl.max); if (AUTOTTL_ENABLED(dp->orig_autottl6)) - DLOG("profile %d orig autottl ipv6 %s%d:%u-%u\n",dp->n,UNARY_PLUS(dp->orig_autottl6.delta),dp->orig_autottl6.delta,dp->orig_autottl6.min,dp->orig_autottl6.max); + DLOG("profile %d orig autottl ipv6 %s%d:%u-%u\n", dp->n, UNARY_PLUS(dp->orig_autottl6.delta), dp->orig_autottl6.delta, dp->orig_autottl6.min, dp->orig_autottl6.max); if (AUTOTTL_ENABLED(dp->dup_autottl)) - DLOG("profile %d dup autottl ipv4 %s%d:%u-%u\n",dp->n,UNARY_PLUS(dp->dup_autottl.delta),dp->dup_autottl.delta,dp->dup_autottl.min,dp->dup_autottl.max); + DLOG("profile %d dup autottl ipv4 %s%d:%u-%u\n", dp->n, UNARY_PLUS(dp->dup_autottl.delta), dp->dup_autottl.delta, dp->dup_autottl.min, dp->dup_autottl.max); if (AUTOTTL_ENABLED(dp->dup_autottl6)) - DLOG("profile %d dup autottl ipv6 %s%d:%u-%u\n",dp->n,UNARY_PLUS(dp->dup_autottl6.delta),dp->dup_autottl6.delta,dp->dup_autottl6.min,dp->dup_autottl6.max); + DLOG("profile %d dup autottl ipv6 %s%d:%u-%u\n", dp->n, UNARY_PLUS(dp->dup_autottl6.delta), dp->dup_autottl6.delta, dp->dup_autottl6.min, dp->dup_autottl6.max); split_compat(dp); if (!dp_fake_defaults(dp)) { @@ -3363,7 +3365,7 @@ int main(int argc, char **argv) DLOG_ERR("ipset load failed\n"); exit_clean(1); } - + DLOG("\nlists summary:\n"); HostlistsDebug(); IpsetsDebug(); @@ -3386,10 +3388,10 @@ int main(int argc, char **argv) exit_clean(1); } } - DLOG("windivert filter size: %zu\nwindivert filter:\n%s\n",strlen(windivert_filter),windivert_filter); + DLOG("windivert filter size: %zu\nwindivert filter:\n%s\n", strlen(windivert_filter), windivert_filter); if (*wf_save_file) { - if (save_file(wf_save_file,windivert_filter,strlen(windivert_filter))) + if (save_file(wf_save_file, windivert_filter, strlen(windivert_filter))) { DLOG_ERR("windivert filter: raw filter saved to %s\n", wf_save_file); exit_clean(0); @@ -3403,10 +3405,10 @@ int main(int argc, char **argv) HANDLE hMutexArg; { char mutex_name[128]; - snprintf(mutex_name,sizeof(mutex_name),"Global\\winws_arg_%u_%u_%u_%u_%u_%u_%u_%u_%u_%u",hash_wf_tcp,hash_wf_udp,hash_wf_raw,hash_wf_raw_part,hash_ssid_filter,hash_nlm_filter,IfIdx,SubIfIdx,wf_ipv4,wf_ipv6); + snprintf(mutex_name, sizeof(mutex_name), "Global\\winws_arg_%u_%u_%u_%u_%u_%u_%u_%u_%u_%u", hash_wf_tcp, hash_wf_udp, hash_wf_raw, hash_wf_raw_part, hash_ssid_filter, hash_nlm_filter, IfIdx, SubIfIdx, wf_ipv4, wf_ipv6); - hMutexArg = CreateMutexA(NULL,TRUE,mutex_name); - if (hMutexArg && GetLastError()==ERROR_ALREADY_EXISTS) + hMutexArg = CreateMutexA(NULL, TRUE, mutex_name); + if (hMutexArg && GetLastError() == ERROR_ALREADY_EXISTS) { CloseHandle(hMutexArg); hMutexArg = NULL; DLOG_ERR("A copy of winws is already running with the same filter\n"); @@ -3420,7 +3422,7 @@ int main(int argc, char **argv) #ifndef __CYGWIN__ if (params.droproot) { - if (!droproot(params.uid,params.user,params.gid,params.gid_count)) + if (!droproot(params.uid, params.user, params.gid, params.gid_count)) exit_clean(1); #ifdef __linux__ if (!dropcaps()) @@ -3451,7 +3453,7 @@ int main(int argc, char **argv) #elif defined(__CYGWIN__) result = win_main(windivert_filter); #else - #error unsupported OS +#error unsupported OS #endif ex: rawsend_cleanup(); diff --git a/nfq/params.c b/nfq/params.c index fee223e7..b5bbede9 100644 --- a/nfq/params.c +++ b/nfq/params.c @@ -20,6 +20,7 @@ const char *progname = "nfqws"; #error UNKNOWN_SYSTEM_TIME #endif +const char * tld[6] = { "com","org","net","edu","gov","biz" }; int DLOG_FILE(FILE *F, const char *format, va_list args) { @@ -297,6 +298,8 @@ struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head) } static void dp_clear_dynamic(struct desync_profile *dp) { + free(dp->fsplit_pattern); + hostlist_collection_destroy(&dp->hl_collection); hostlist_collection_destroy(&dp->hl_collection_exclude); ipset_collection_destroy(&dp->ips_collection); diff --git a/nfq/params.h b/nfq/params.h index 8e3f5373..8f38644d 100644 --- a/nfq/params.h +++ b/nfq/params.h @@ -68,6 +68,8 @@ #define MAX_GIDS 64 +extern const char * tld[6]; + enum log_target { LOG_TARGET_CONSOLE=0, LOG_TARGET_FILE, LOG_TARGET_SYSLOG, LOG_TARGET_ANDROID }; struct fake_tls_mod_cache @@ -140,8 +142,9 @@ struct desync_profile uint32_t desync_ts_increment, desync_badseq_increment, desync_badseq_ack_increment; struct blob_collection_head fake_http,fake_tls,fake_unknown,fake_unknown_udp,fake_quic,fake_wg,fake_dht,fake_discord,fake_stun; - uint8_t fake_syndata[FAKE_MAX_TCP],seqovl_pattern[FAKE_MAX_TCP],fsplit_pattern[FAKE_MAX_TCP],udplen_pattern[FAKE_MAX_UDP]; - size_t fake_syndata_size; + uint8_t fake_syndata[FAKE_MAX_TCP],seqovl_pattern[FAKE_MAX_TCP],udplen_pattern[FAKE_MAX_UDP]; + uint8_t *fsplit_pattern; + size_t fake_syndata_size, fsplit_pattern_size; struct fake_tls_mod tls_mod_last; struct blob_item *tls_fake_last;