Compare commits

..

No commits in common. "d21175b4a35a64973a6c6df1ee2ded7b8b510932" and "8b5dfcfae1aede51d0b43bdae9961dc6c3b6f166" have entirely different histories.

7 changed files with 132 additions and 180 deletions

View File

@ -143,11 +143,8 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
}
else if (tcp_synack_segment(tcphdr))
{
// ignore SA dups
uint32_t seq0 = ntohl(tcphdr->th_ack)-1;
if (t->state!=SYN && t->seq0!=seq0)
ConntrackReInitTrack(t); // erase current entry
if (!t->seq0) t->seq0 = seq0;
if (t->state!=SYN) ConntrackReInitTrack(t); // erase current entry
if (!t->seq0) t->seq0 = ntohl(tcphdr->th_ack)-1;
t->ack0 = ntohl(tcphdr->th_seq);
}
else if (tcphdr->th_flags & (TH_FIN|TH_RST))

View File

@ -38,11 +38,6 @@ uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment)
return htons(ntohs(netorder_value)+cpuorder_increment);
}
bool ip_has_df(const struct ip *ip)
{
return ip && !!(ntohs(ip->ip_off) & IP_DF);
}
uint8_t *tcp_find_option(struct tcphdr *tcp, uint8_t kind)
{
uint8_t *t = (uint8_t*)(tcp+1);
@ -194,11 +189,11 @@ static void fill_udphdr(struct udphdr *udp, uint16_t nsport, uint16_t ndport, ui
udp->uh_sum = 0;
}
static void fill_iphdr(struct ip *ip, const struct in_addr *src, const struct in_addr *dst, uint16_t pktlen, uint8_t proto, bool DF, uint8_t ttl, uint8_t tos, uint16_t ip_id)
static void fill_iphdr(struct ip *ip, const struct in_addr *src, const struct in_addr *dst, uint16_t pktlen, uint8_t proto, uint8_t ttl, uint8_t tos, uint16_t ip_id)
{
ip->ip_tos = tos;
ip->ip_sum = 0;
ip->ip_off = DF ? htons(IP_DF) : 0;
ip->ip_off = 0;
ip->ip_v = 4;
ip->ip_hl = 5;
ip->ip_len = htons(pktlen);
@ -227,7 +222,6 @@ bool prepare_tcp_segment4(
uint16_t nwsize,
uint8_t scale_factor,
uint32_t *timestamps,
bool DF,
uint8_t ttl,
uint8_t tos,
uint16_t ip_id,
@ -246,7 +240,7 @@ bool prepare_tcp_segment4(
struct tcphdr *tcp = (struct tcphdr*)(ip+1);
uint8_t *payload = (uint8_t*)(tcp+1)+tcpoptlen;
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_TCP, DF, ttl, tos, ip_id);
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_TCP, ttl, tos, ip_id);
fill_tcphdr(tcp,fooling,tcp_flags,sack,nmss,nseq,nack_seq,src->sin_port,dst->sin_port,nwsize,scale_factor,timestamps,badseq_increment,badseq_ack_increment,len);
memcpy(payload,data,len);
@ -352,7 +346,6 @@ bool prepare_tcp_segment(
uint16_t nwsize,
uint8_t scale_factor,
uint32_t *timestamps,
bool DF,
uint8_t ttl,
uint8_t tos,
uint16_t ip_id,
@ -364,7 +357,7 @@ bool prepare_tcp_segment(
uint8_t *buf, size_t *buflen)
{
return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ?
prepare_tcp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,tcp_flags,sack,nmss,nseq,nack_seq,nwsize,scale_factor,timestamps,DF,ttl,tos,ip_id,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
prepare_tcp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,tcp_flags,sack,nmss,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,tos,ip_id,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
(src->sa_family==AF_INET6 && dst->sa_family==AF_INET6) ?
prepare_tcp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,tcp_flags,sack,nmss,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,flow_label,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
false;
@ -374,7 +367,6 @@ bool prepare_tcp_segment(
// padlen<0 means payload shrinking
bool prepare_udp_segment4(
const struct sockaddr_in *src, const struct sockaddr_in *dst,
bool DF,
uint8_t ttl,
uint8_t tos,
uint16_t ip_id,
@ -401,7 +393,7 @@ bool prepare_udp_segment4(
uint8_t *payload = (uint8_t*)(udp+1);
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_UDP, DF, ttl, tos, ip_id);
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_UDP, ttl, tos, ip_id);
fill_udphdr(udp, src->sin_port, dst->sin_port, datalen);
memcpy(payload,data,len);
@ -506,7 +498,6 @@ bool prepare_udp_segment6(
}
bool prepare_udp_segment(
const struct sockaddr *src, const struct sockaddr *dst,
bool DF,
uint8_t ttl,
uint8_t tos,
uint16_t ip_id,
@ -518,7 +509,7 @@ bool prepare_udp_segment(
uint8_t *buf, size_t *buflen)
{
return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ?
prepare_udp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,DF,ttl,tos,ip_id,fooling,padding,padding_size,padlen,data,len,buf,buflen) :
prepare_udp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,ttl,tos,ip_id,fooling,padding,padding_size,padlen,data,len,buf,buflen) :
(src->sa_family==AF_INET6 && dst->sa_family==AF_INET6) ?
prepare_udp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,ttl,flow_label,fooling,padding,padding_size,padlen,data,len,buf,buflen) :
false;
@ -1837,7 +1828,6 @@ bool rawsend_queue(struct rawpacket_tailhead *q)
uint8_t autottl_guess(uint8_t ttl, const autottl *attl)
{
uint8_t orig, path, fake;
int d;
// 18.65.168.125 ( cloudfront ) 255
// 157.254.246.178 128
@ -1854,13 +1844,11 @@ uint8_t autottl_guess(uint8_t ttl, const autottl *attl)
path = orig - ttl;
d = (int)path + attl->delta;
if (d<attl->min) fake=attl->min;
else if (d>attl->max) fake=attl->max;
else fake=(uint8_t)d;
fake = path > attl->delta ? path - attl->delta : attl->min;
if (fake<attl->min) fake=attl->min;
else if (fake>attl->max) fake=attl->max;
if (attl->delta<0 && fake>=path || attl->delta>=0 && fake<path)
return 0;
if (fake>=path) return 0;
return fake;
}
@ -1912,15 +1900,15 @@ void verdict_tcp_csum_fix(uint8_t verdict, struct tcphdr *tcphdr, size_t transpo
{
if (!(verdict & VERDICT_NOCSUM))
{
#ifdef __CYGWIN__
// always fix csum for windivert. original can be partial or bad
if ((verdict & VERDICT_MASK)!=VERDICT_DROP)
#elif defined(__FreeBSD__)
#ifndef __CYGWIN__
#ifdef __FreeBSD__
// FreeBSD tend to pass ipv6 frames with wrong checksum
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
#else
// if original packet was tampered earlier it needs checksum fixed
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY)
#endif
#endif
tcp_fix_checksum(tcphdr,transport_len,ip,ip6hdr);
}
@ -1929,15 +1917,15 @@ void verdict_udp_csum_fix(uint8_t verdict, struct udphdr *udphdr, size_t transpo
{
if (!(verdict & VERDICT_NOCSUM))
{
#ifdef __CYGWIN__
// always fix csum for windivert. original can be partial or bad
if ((verdict & VERDICT_MASK)!=VERDICT_DROP)
#elif defined(__FreeBSD__)
#ifndef __CYGWIN__
#ifdef __FreeBSD__
// FreeBSD tend to pass ipv6 frames with wrong checksum
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
#else
// if original packet was tampered earlier it needs checksum fixed
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY)
#endif
#endif
udp_fix_checksum(udphdr,transport_len,ip,ip6hdr);
}

View File

@ -75,7 +75,6 @@ bool prepare_tcp_segment4(
uint16_t nwsize,
uint8_t scale_factor,
uint32_t *timestamps,
bool DF,
uint8_t ttl,
uint8_t tos,
uint16_t ip_id,
@ -109,7 +108,6 @@ bool prepare_tcp_segment(
uint16_t nwsize,
uint8_t scale_factor,
uint32_t *timestamps,
bool DF,
uint8_t ttl,
uint8_t tos,
uint16_t ip_id,
@ -123,7 +121,6 @@ bool prepare_tcp_segment(
bool prepare_udp_segment4(
const struct sockaddr_in *src, const struct sockaddr_in *dst,
bool DF,
uint8_t ttl,
uint8_t tos,
uint16_t ip_id,
@ -143,7 +140,6 @@ bool prepare_udp_segment6(
uint8_t *buf, size_t *buflen);
bool prepare_udp_segment(
const struct sockaddr *src, const struct sockaddr *dst,
bool DF,
uint8_t ttl,
uint8_t tos,
uint16_t ip_id,
@ -185,8 +181,6 @@ bool tcp_has_sack(struct tcphdr *tcp);
bool tcp_has_fastopen(const struct tcphdr *tcp);
bool ip_has_df(const struct ip *ip);
#ifdef __CYGWIN__
extern uint32_t w_win32_error;
@ -258,10 +252,9 @@ void tcp_rewrite_winsize(struct tcphdr *tcp, uint16_t winsize, uint8_t scale_fac
typedef struct
{
int8_t delta;
uint8_t min, max;
uint8_t delta, min, max;
} autottl;
#define AUTOTTL_DEFAULT_DELTA -1
#define AUTOTTL_DEFAULT_DELTA 1
#define AUTOTTL_DEFAULT_MIN 3
#define AUTOTTL_DEFAULT_MAX 20
#define AUTOTTL_ENABLED(a) (!!(a).delta)

View File

@ -879,7 +879,7 @@ static bool orig_send_rewrite(
}
// return : true - orig was sent completely, false - should send orig another way
static bool tcp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, const struct desync_profile *dp, const t_ctrack *ctrack, struct dissect *dis, bool bForceSend)
static bool tcp_orig_send(uint32_t fwmark, const char *ifout, const struct desync_profile *dp, const t_ctrack *ctrack, struct dissect *dis, bool bForceSend)
{
if (dp->dup_repeats || bForceSend)
{
@ -890,12 +890,10 @@ static bool tcp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, c
struct sockaddr_storage src, dst;
uint8_t ttl_orig,ttl_fake,flags_orig,scale_factor;
uint32_t *timestamps;
bool sack,DF;
bool sack;
extract_endpoints(dis->ip, dis->ip6, dis->tcp, NULL, &src, &dst);
verdict_tcp_csum_fix(verdict, dis->tcp, dis->transport_len, dis->ip, dis->ip6);
if (dp->dup_repeats && check_dup_interval(dp,ctrack))
{
ttl_orig = dis->ip ? dis->ip->ip_ttl : dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim;
@ -910,19 +908,19 @@ static bool tcp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, c
sack = tcp_has_sack(dis->tcp);
nmss = tcp_find_mss(dis->tcp);
ip_id = IP4_IP_ID_FIX(dis->ip);
DF = ip_has_df(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,
DF,ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
dp->dup_fooling_mode,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;
}
DLOG("sending %u dups with packet reconstruct\n", dp->dup_repeats);
// send dups
@ -958,7 +956,7 @@ static bool tcp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, c
return false;
}
// return : true - orig was sent completely, false - should send orig another way
static bool udp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, const struct desync_profile *dp, const t_ctrack *ctrack, struct dissect *dis, bool bForceSend)
static bool udp_orig_send(uint32_t fwmark, const char *ifout, const struct desync_profile *dp, const t_ctrack *ctrack, struct dissect *dis, bool bForceSend)
{
if (dp->dup_repeats || bForceSend)
{
@ -968,18 +966,14 @@ static bool udp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, c
uint16_t ip_id;
struct sockaddr_storage src, dst;
uint8_t ttl_orig,ttl_fake;
bool DF;
extract_endpoints(dis->ip, dis->ip6, NULL, dis->udp, &src, &dst);
verdict_udp_csum_fix(verdict, dis->udp, dis->transport_len, dis->ip, dis->ip6);
if (dp->dup_repeats && check_dup_interval(dp,ctrack))
{
ttl_orig = dis->ip ? dis->ip->ip_ttl : dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim;
ttl_fake = dis->ip6 ? dp->dup_ttl6 : dp->dup_ttl;
if (!ttl_fake) ttl_fake = ttl_orig;
DF = ip_has_df(dis->ip);
if (dp->dup_fooling_mode)
{
@ -987,7 +981,7 @@ static bool udp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, c
len = sizeof(pkt);
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst,
DF,ttl_fake, IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
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))
{
@ -1048,7 +1042,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
size_t pkt1_len, pkt2_len;
uint8_t ttl_orig,ttl_fake,flags_orig,scale_factor;
uint32_t *timestamps;
bool bSack,DF;
bool bSack;
uint16_t nmss;
uint32_t desync_fwmark = fwmark | params.desync_fwmark;
@ -1213,7 +1207,6 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
timestamps = tcp_find_timestamps(dis->tcp);
bSack = tcp_has_sack(dis->tcp);
nmss = tcp_find_mss(dis->tcp);
DF = ip_has_df(dis->ip);
if (!replay)
{
@ -1224,7 +1217,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
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),
ttl_fake,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6),
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
NULL, 0, pkt1, &pkt1_len))
{
@ -1248,7 +1241,7 @@ 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, 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),
ttl_orig,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6),
0,0,0, dp->fake_syndata,dp->fake_syndata_size, pkt1,&pkt1_len))
{
goto send_orig;
@ -1461,8 +1454,6 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
if (!replay)
{
maybe_cutoff(ctrack, IPPROTO_TCP);
if (orig_mod(dp,ctrack,dis)) // ttl can change !
verdict = VERDICT_MODIFY;
if (!process_desync_interval(dp, ctrack))
{
reasm_orig_cancel(ctrack);
@ -1704,7 +1695,7 @@ 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, 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),
ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
fake_data, fake_item->size, pkt1, &pkt1_len))
{
@ -1728,7 +1719,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
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),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6),
ttl_fake,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6),
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
NULL, 0, pkt1, &pkt1_len))
{
@ -1756,7 +1747,7 @@ 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, 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),
ttl_orig,0,0,IP6_FLOW(dis->ip6),
fooling_orig,0,0,
dis->data_payload, dis->len_payload, pkt1, &pkt1_len))
{
@ -1824,8 +1815,7 @@ 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, 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),
dis->tcp->th_win, scale_factor, timestamps,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
fooling_orig,0,0,
seg, seg_len, pkt1, &pkt1_len))
goto send_orig;
@ -1894,8 +1884,7 @@ 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, 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),
dis->tcp->th_win, scale_factor, timestamps,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
fooling_orig,0,0,
seg, seg_len, pkt1, &pkt1_len))
goto send_orig;
@ -1954,7 +1943,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
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),
ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
pat+split_pos, dis->len_payload-split_pos, fakeseg2, &fakeseg2_len))
goto send_orig;
@ -1966,7 +1955,7 @@ 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, 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),
ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
seg, seg_len, pkt1, &pkt1_len))
goto send_orig;
@ -1986,7 +1975,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
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),
ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
pat, split_pos, fakeseg, &seg_len))
goto send_orig;
@ -1998,7 +1987,7 @@ 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, 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),
ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
dis->data_payload, split_pos, pkt1, &pkt1_len))
goto send_orig;
@ -2034,7 +2023,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
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),
ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
pat, split_pos, fakeseg, &fakeseg_len))
goto send_orig;
@ -2070,7 +2059,7 @@ 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, 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),
ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
seg, seg_len, pkt1, &pkt1_len))
goto send_orig;
@ -2101,7 +2090,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
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),
ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
pat+split_pos, dis->len_payload-split_pos, fakeseg, &fakeseg_len))
goto send_orig;
@ -2113,7 +2102,7 @@ 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, 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),
ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
fooling_orig,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;
@ -2179,6 +2168,9 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
default:
break;
}
if (bFake)
verdict_tcp_csum_fix(verdict, dis->tcp, dis->transport_len, dis->ip, dis->ip6);
}
send_orig:
@ -2186,7 +2178,7 @@ send_orig:
if ((verdict & VERDICT_MASK)==VERDICT_DROP)
verdict = ct_new_postnat_fix_tcp(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(desync_fwmark,ifout,dp,ctrack_replay,dis,bFake))
verdict = ct_new_postnat_fix_tcp(ctrack, dis->ip, dis->ip6, dis->tcp);
return verdict;
}
@ -2224,7 +2216,6 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
uint8_t pkt1[DPI_DESYNC_MAX_FAKE_LEN+100], pkt2[DPI_DESYNC_MAX_FAKE_LEN+100];
size_t pkt1_len, pkt2_len;
uint8_t ttl_orig,ttl_fake;
bool DF;
t_l7proto l7proto = UNKNOWN;
extract_endpoints(dis->ip, dis->ip6, NULL, dis->udp, &src, &dst);
@ -2309,7 +2300,6 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
uint32_t desync_fwmark = fwmark | params.desync_fwmark;
ttl_orig = dis->ip ? dis->ip->ip_ttl : dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim;
DF = ip_has_df(dis->ip);
if (dis->len_payload)
{
@ -2560,8 +2550,6 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
if (!replay)
{
maybe_cutoff(ctrack, IPPROTO_UDP);
if (orig_mod(dp,ctrack,dis)) // ttl can change !
verdict = VERDICT_MODIFY;
if (!process_desync_interval(dp, ctrack)) goto send_orig;
}
}
@ -2651,7 +2639,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
n++;
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),
ttl_fake, IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
dp->desync_fooling_mode, NULL, 0, 0,
fake_item->data, fake_item->size, pkt1, &pkt1_len))
{
@ -2674,7 +2662,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
{
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,
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;
@ -2696,7 +2684,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
{
case DESYNC_UDPLEN:
pkt1_len = sizeof(pkt1);
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, DF, ttl_orig,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),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, ttl_orig,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),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;
@ -2721,7 +2709,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
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),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6), fooling_orig, NULL, 0 , 0, pkt2, pkt2_len, pkt1, &pkt1_len))
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, ttl_orig,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),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;
@ -2782,13 +2770,16 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
default:
break;
}
if (bFake)
verdict_udp_csum_fix(verdict, dis->udp, dis->transport_len, dis->ip, dis->ip6);
}
send_orig:
if ((verdict & VERDICT_MASK)==VERDICT_DROP)
verdict = ct_new_postnat_fix_udp(ctrack, dis->ip, dis->ip6, dis->udp, &dis->len_pkt);
else
if (udp_orig_send(verdict,desync_fwmark,ifout,dp,ctrack_replay,dis,bFake))
if (udp_orig_send(desync_fwmark,ifout,dp,ctrack_replay,dis,bFake))
verdict = ct_new_postnat_fix_udp(ctrack, dis->ip, dis->ip6, dis->udp, &dis->len_pkt);
return verdict;
}

View File

@ -692,18 +692,11 @@ static void load_file_or_exit(const char *filename, void *buf, size_t *size)
static bool parse_autottl(const char *s, autottl *t)
{
bool neg=true;
unsigned int delta,min,max;
AUTOTTL_SET_DEFAULT(*t);
if (s)
{
max = t->max;
if (*s=='+')
{
neg=false;
s++;
} else if (*s=='-')
s++;
switch (sscanf(s,"%u:%u-%u",&delta,&min,&max))
{
case 3:
@ -713,8 +706,8 @@ static bool parse_autottl(const char *s, autottl *t)
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);
if (delta>255) return false;
t->delta=(uint8_t)delta;
break;
default:
return false;
@ -1350,7 +1343,8 @@ static bool wf_make_filter(
char pf_dst_buf[512],iface[64];
const char *pf_dst;
const char *f_tcpin = *pf_tcp_src ? dp_list_have_autohostlist(&params.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(&params.desync_profiles)) ? DIVERT_TCP_NOT_EMPTY " and " : "";
const char *f_tcp_not_empty = *pf_tcp_src ? DIVERT_TCP_NOT_EMPTY " and " : "";
snprintf(iface,sizeof(iface)," ifIdx=%u and subIfIdx=%u and",IfIdx,SubIfIdx);
if (!*pf_tcp_src && !*pf_udp_src) return false;
@ -1459,14 +1453,14 @@ static void exithelp(void)
" --orig-mod-start=[n|d|s]N\t\t\t; apply orig TTL mod to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N\n"
" --orig-mod-cutoff=[n|d|s]N\t\t\t; apply orig TTL mod to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N\n"
" --dup=<int>\t\t\t\t\t; duplicate original packets. send N dups before original.\n"
" --dup-replace=[0|1]\t\t\t\t; 1 or no argument means do not send original, only dups\n"
" --dup-ttl=<int>\t\t\t\t; set TTL for dups\n"
" --dup-replace=[0|1]\t\t\t\t; 1 or no argument means do not send original, only dups\n"
" --dup-ttl6=<int>\t\t\t\t; set ipv6 hop limit for dups. by default ttl value is used\n"
" --dup-fooling=<mode>[,<mode>]\t\t\t; can use multiple comma separated values. modes : none md5sig badseq badsum datanoack hopbyhop hopbyhop2\n"
" --dup-badseq-increment=<int|0xHEX>\t\t; badseq fooling seq signed increment for dup. default %d\n"
" --dup-badack-increment=<int|0xHEX>\t\t; badseq fooling ackseq signed increment for dup. default %d\n"
" --dup-start=[n|d|s]N\t\t\t\t; apply dup to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N\n"
" --dup-cutoff=[n|d|s]N\t\t\t\t; apply dup to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N\n"
" --dup-badseq-increment=<int|0xHEX>\t\t; badseq fooling seq signed increment for dup. default %d\n"
" --dup-desync-badack-increment=<int|0xHEX>\t; badseq fooling ackseq signed increment for dup. default %d\n"
" --hostcase\t\t\t\t\t; change Host: => host:\n"
" --hostspell\t\t\t\t\t; exact spelling of \"Host\" header. must be 4 chars. default is \"host\"\n"
" --hostnospace\t\t\t\t\t; remove space after Host: and add it to User-Agent: to preserve packet size\n"
@ -1482,7 +1476,7 @@ static void exithelp(void)
#endif
" --dpi-desync-ttl=<int>\t\t\t\t; set ttl for fakes packets\n"
" --dpi-desync-ttl6=<int>\t\t\t; set ipv6 hop limit for fake packet. by default --dpi-desync-ttl value is used.\n"
" --dpi-desync-autottl=[<delta>[:<min>[-<max>]]]\t; auto ttl mode for both ipv4 and ipv6. default: %d:%u-%u\n"
" --dpi-desync-autottl=[<delta>[:<min>[-<max>]]]\t; auto ttl mode for both ipv4 and ipv6. default: %u:%u-%u\n"
" --dpi-desync-autottl6=[<delta>[:<min>[-<max>]]] ; overrides --dpi-desync-autottl for ipv6 only\n"
" --dpi-desync-fooling=<mode>[,<mode>]\t\t; can use multiple comma separated values. modes : none md5sig badseq badsum datanoack hopbyhop hopbyhop2\n"
" --dpi-desync-repeats=<N>\t\t\t; send every desync packet N times\n"
@ -2763,73 +2757,7 @@ int main(int argc, char **argv)
DLOG_ERR("Need divert port (--port)\n");
exit_clean(1);
}
#endif
DLOG("adding low-priority default empty desync profile\n");
// add default empty profile
if (!(dpl = dp_list_add(&params.desync_profiles)))
{
DLOG_ERR("desync_profile_add: out of memory\n");
exit_clean(1);
}
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);
if (params.droproot && *params.hostlist_auto_debuglog && chown(params.hostlist_auto_debuglog, params.uid, -1))
DLOG_ERR("could not chown %s. auto hostlist debug log may not be writable after privilege drop\n", params.hostlist_auto_debuglog);
#endif
LIST_FOREACH(dpl, &params.desync_profiles, next)
{
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 (!AUTOTTL_ENABLED(dp->desync_autottl6)) dp->desync_autottl6 = dp->desync_autottl;
if (AUTOTTL_ENABLED(dp->desync_autottl))
DLOG("profile %d autottl ipv4 %d:%u-%u\n",dp->n,dp->desync_autottl.delta,dp->desync_autottl.min,dp->desync_autottl.max);
if (AUTOTTL_ENABLED(dp->desync_autottl6))
DLOG("profile %d autottl ipv6 %d:%u-%u\n",dp->n,dp->desync_autottl6.delta,dp->desync_autottl6.min,dp->desync_autottl6.max);
split_compat(dp);
if (!dp_fake_defaults(dp))
{
DLOG_ERR("could not fill fake defaults\n");
exit_clean(1);
}
if (!onetime_tls_mod(dp))
{
DLOG_ERR("could not mod tls\n");
exit_clean(1);
}
#ifndef __CYGWIN__
if (params.droproot && dp->hostlist_auto && chown(dp->hostlist_auto->filename, params.uid, -1))
DLOG_ERR("could not chown %s. auto hostlist file may not be writable after privilege drop\n", dp->hostlist_auto->filename);
#endif
}
if (!LoadAllHostLists())
{
DLOG_ERR("hostlists load failed\n");
exit_clean(1);
}
if (!LoadAllIpsets())
{
DLOG_ERR("ipset load failed\n");
exit_clean(1);
}
DLOG("\nlists summary:\n");
HostlistsDebug();
IpsetsDebug();
DLOG("\nsplits summary:\n");
SplitDebug();
DLOG("\n");
#ifdef __CYGWIN__
#elif defined(__CYGWIN__)
if (!*windivert_filter)
{
if (!*wf_pf_tcp_src && !*wf_pf_udp_src)
@ -2869,9 +2797,74 @@ int main(int argc, char **argv)
DLOG_ERR("A copy of winws is already running with the same filter\n");
goto exiterr;
}
}
#endif
DLOG("adding low-priority default empty desync profile\n");
// add default empty profile
if (!(dpl = dp_list_add(&params.desync_profiles)))
{
DLOG_ERR("desync_profile_add: out of memory\n");
exit_clean(1);
}
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);
if (params.droproot && *params.hostlist_auto_debuglog && chown(params.hostlist_auto_debuglog, params.uid, -1))
DLOG_ERR("could not chown %s. auto hostlist debug log may not be writable after privilege drop\n", params.hostlist_auto_debuglog);
#endif
LIST_FOREACH(dpl, &params.desync_profiles, next)
{
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 (!AUTOTTL_ENABLED(dp->desync_autottl6)) dp->desync_autottl6 = dp->desync_autottl;
if (AUTOTTL_ENABLED(dp->desync_autottl))
DLOG("profile %d autottl ipv4 %u:%u-%u\n",dp->n,dp->desync_autottl.delta,dp->desync_autottl.min,dp->desync_autottl.max);
if (AUTOTTL_ENABLED(dp->desync_autottl6))
DLOG("profile %d autottl ipv6 %u:%u-%u\n",dp->n,dp->desync_autottl6.delta,dp->desync_autottl6.min,dp->desync_autottl6.max);
split_compat(dp);
if (!dp_fake_defaults(dp))
{
DLOG_ERR("could not fill fake defaults\n");
exit_clean(1);
}
if (!onetime_tls_mod(dp))
{
DLOG_ERR("could not mod tls\n");
exit_clean(1);
}
#ifndef __CYGWIN__
if (params.droproot && dp->hostlist_auto && chown(dp->hostlist_auto->filename, params.uid, -1))
DLOG_ERR("could not chown %s. auto hostlist file may not be writable after privilege drop\n", dp->hostlist_auto->filename);
#endif
}
if (!LoadAllHostLists())
{
DLOG_ERR("hostlists load failed\n");
exit_clean(1);
}
if (!LoadAllIpsets())
{
DLOG_ERR("ipset load failed\n");
exit_clean(1);
}
DLOG("\nlists summary:\n");
HostlistsDebug();
IpsetsDebug();
DLOG("\nsplits summary:\n");
SplitDebug();
DLOG("\n");
if (bDry)
{
DLOG_CONDUP("command line parameters verified\n");

View File

@ -294,12 +294,3 @@ bool dp_list_have_autohostlist(struct desync_profile_list_head *head)
return true;
return false;
}
// check if we need empty outgoing ACK
bool dp_list_need_all_out(struct desync_profile_list_head *head)
{
struct desync_profile_list *dpl;
LIST_FOREACH(dpl, head, next)
if (dpl->dp.dup_repeats || PROFILE_HAS_ORIG_MOD(&dpl->dp))
return true;
return false;
}

View File

@ -126,10 +126,10 @@ struct desync_profile
hostfail_pool *hostlist_auto_fail_counters;
};
#define PROFILE_IPSETS_ABSENT(dp) (!LIST_FIRST(&(dp)->ips_collection) && !LIST_FIRST(&(dp)->ips_collection_exclude))
#define PROFILE_IPSETS_EMPTY(dp) (ipset_collection_is_empty(&(dp)->ips_collection) && ipset_collection_is_empty(&(dp)->ips_collection_exclude))
#define PROFILE_HOSTLISTS_EMPTY(dp) (hostlist_collection_is_empty(&(dp)->hl_collection) && hostlist_collection_is_empty(&(dp)->hl_collection_exclude))
#define PROFILE_HAS_ORIG_MOD(dp) ((dp)->orig_mod_ttl || (dp)->orig_mod_ttl6)
#define PROFILE_IPSETS_ABSENT(dp) (!LIST_FIRST(&dp->ips_collection) && !LIST_FIRST(&dp->ips_collection_exclude))
#define PROFILE_IPSETS_EMPTY(dp) (ipset_collection_is_empty(&dp->ips_collection) && ipset_collection_is_empty(&dp->ips_collection_exclude))
#define PROFILE_HOSTLISTS_EMPTY(dp) (hostlist_collection_is_empty(&dp->hl_collection) && hostlist_collection_is_empty(&dp->hl_collection_exclude))
#define PROFILE_HAS_ORIG_MOD(dp) (dp->orig_mod_ttl || dp->orig_mod_ttl6)
struct desync_profile_list {
struct desync_profile dp;
@ -140,7 +140,6 @@ struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head);
void dp_entry_destroy(struct desync_profile_list *entry);
void dp_list_destroy(struct desync_profile_list_head *head);
bool dp_list_have_autohostlist(struct desync_profile_list_head *head);
bool dp_list_need_all_out(struct desync_profile_list_head *head);
void dp_init(struct desync_profile *dp);
bool dp_fake_defaults(struct desync_profile *dp);
void dp_clear(struct desync_profile *dp);