Linting and formatting of .c and .h with C/C++ IntelliSence

This commit is contained in:
conc3rned 2024-09-17 16:19:54 +03:00
parent 8c94e3230e
commit c1db09b19e
80 changed files with 9996 additions and 8587 deletions

View File

@ -35,7 +35,7 @@
#define DEFAULT_V4_ZCT_MIN 2 // /30
#define DEFAULT_V6_ZCT_MAX 72 // /56
#define DEFAULT_V6_ZCT_MIN 64 // /64
// must be no less than N ipv6 in subnet
// must be no less than N IPv6 in subnet
#define DEFAULT_V6_THRESHOLD 5
static int ucmp(const void *a, const void *b, void *arg)
@ -59,18 +59,18 @@ static uint32_t unique(uint32_t *pu, uint32_t ct)
for (i = j = 0; j < ct; i++)
{
u = pu[j++];
for (; j < ct && pu[j] == u; j++);
for (; j < ct && pu[j] == u; j++)
;
pu[i] = u;
}
return i;
}
#if defined(__GNUC__) && !defined(__llvm__)
__attribute__((optimize("no-strict-aliasing")))
#endif
static int cmp6(const void * a, const void * b, void *arg)
static int
cmp6(const void *a, const void *b, void *arg)
{
// this function is critical for sort performance
// on big endian systems cpu byte order is equal to network byte order
@ -102,7 +102,8 @@ static int cmp6(const void * a, const void * b, void *arg)
aa = ((uint64_t *)((struct in6_addr *)a)->s6_addr)[1];
bb = ((uint64_t *)((struct in6_addr *)b)->s6_addr)[1];
#endif
return aa < bb ? -1 : aa > bb ? 1 : 0;
return aa < bb ? -1 : aa > bb ? 1
: 0;
}
#else
@ -124,7 +125,8 @@ static uint32_t unique6(struct in6_addr *pu, uint32_t ct)
uint32_t i, j, k;
for (i = j = 0; j < ct; i++)
{
for (k = j++; j < ct && !memcmp(pu + j, pu + k, sizeof(struct in6_addr)); j++);
for (k = j++; j < ct && !memcmp(pu + j, pu + k, sizeof(struct in6_addr)); j++)
;
pu[i] = pu[k];
}
return i;
@ -144,14 +146,14 @@ static void mask_from_bitcount6_make(uint32_t zct, struct in6_addr *a)
static struct in6_addr ip6_mask[129];
static void mask_from_bitcount6_prepare(void)
{
for (int zct=0;zct<=128;zct++) mask_from_bitcount6_make(zct, ip6_mask+zct);
for (int zct = 0; zct <= 128; zct++)
mask_from_bitcount6_make(zct, ip6_mask + zct);
}
static inline const struct in6_addr *mask_from_bitcount6(uint32_t zct)
{
return ip6_mask + zct;
}
/*
// this is "correct" solution for strict aliasing feature
// but I don't like this style of coding
@ -178,7 +180,8 @@ static void ip6_and(const struct in6_addr *a, const struct in6_addr *b, struct i
#if defined(__GNUC__) && !defined(__llvm__)
__attribute__((optimize("no-strict-aliasing")))
#endif
static void ip6_and(const struct in6_addr * restrict a, const struct in6_addr * restrict b, struct in6_addr * restrict result)
static void
ip6_and(const struct in6_addr *restrict a, const struct in6_addr *restrict b, struct in6_addr *restrict result)
{
#ifdef __SIZEOF_INT128__
// gcc and clang have 128 bit int types on some 64-bit archs. take some advantage
@ -192,10 +195,10 @@ static void ip6_and(const struct in6_addr * restrict a, const struct in6_addr *
static void rtrim(char *s)
{
if (s)
for (char *p = s + strlen(s) - 1; p >= s && (*p == '\n' || *p == '\r'); p--) *p = '\0';
for (char *p = s + strlen(s) - 1; p >= s && (*p == '\n' || *p == '\r'); p--)
*p = '\0';
}
static struct params_s
{
bool ipv6;
@ -204,16 +207,14 @@ static struct params_s
uint32_t v6_threshold; // for v6
} params;
static void exithelp(void)
{
printf(
" -4\t\t\t\t; ipv4 list (default)\n"
" -6\t\t\t\t; ipv6 list\n"
" --prefix-length=min[-max]\t; consider prefix lengths from 'min' to 'max'. examples : 22-30 (ipv4), 56-64 (ipv6)\n"
" --v4-threshold=mul/div\t\t; ipv4 only : include subnets with more than mul/div ips. example : 3/4\n"
" --v6-threshold=N\t\t; ipv6 only : include subnets with more than N v6 ips. example : 5\n"
);
" -4\t\t\t\t; IPv4 list (default)\n"
" -6\t\t\t\t; IPv6 list\n"
" --prefix-length=min[-max]\t; consider prefix lengths from 'min' to 'max'. examples : 22-30 (IPv4), 56-64 (IPv6)\n"
" --v4-threshold=mul/div\t\t; IPv4 only : include subnets with more than mul/div ips. example : 3/4\n"
" --v6-threshold=N\t\t; IPv6 only : include subnets with more than N v6 ips. example : 5\n");
exit(1);
}
@ -236,11 +237,11 @@ static void parse_params(int argc, char *argv[])
{"prefix-length", required_argument, 0, 0}, // optidx=4
{"v4-threshold", required_argument, 0, 0}, // optidx=5
{"v6-threshold", required_argument, 0, 0}, // optidx=6
{ NULL,0,NULL,0 }
};
{NULL, 0, NULL, 0}};
while ((v = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1)
{
if (v) exithelp();
if (v)
exithelp();
switch (option_index)
{
case 0:
@ -255,7 +256,8 @@ static void parse_params(int argc, char *argv[])
break;
case 4:
i = sscanf(optarg, "%u-%u", &plen1, &plen2);
if (i == 1) plen2 = plen1;
if (i == 1)
plen2 = plen1;
if (i <= 0 || plen2 < plen1 || !plen1 || !plen2)
{
fprintf(stderr, "invalid parameter for prefix-length : %s\n", optarg);
@ -285,11 +287,12 @@ static void parse_params(int argc, char *argv[])
fprintf(stderr, "invalid parameter for prefix-length\n");
exit(1);
}
params.zct_min = params.ipv6 ? plen2==-1 ? DEFAULT_V6_ZCT_MIN : 128-plen2 : plen2==-1 ? DEFAULT_V4_ZCT_MIN : 32-plen2;
params.zct_max = params.ipv6 ? plen1==-1 ? DEFAULT_V6_ZCT_MAX : 128-plen1 : plen1==-1 ? DEFAULT_V4_ZCT_MAX : 32-plen1;
params.zct_min = params.ipv6 ? plen2 == -1 ? DEFAULT_V6_ZCT_MIN : 128 - plen2 : plen2 == -1 ? DEFAULT_V4_ZCT_MIN
: 32 - plen2;
params.zct_max = params.ipv6 ? plen1 == -1 ? DEFAULT_V6_ZCT_MAX : 128 - plen1 : plen1 == -1 ? DEFAULT_V4_ZCT_MAX
: 32 - plen1;
}
int main(int argc, char **argv)
{
char str[256], d;
@ -319,13 +322,15 @@ int main(int argc, char **argv)
// output it as is
if (sscanf(s + 1, "%u", &zct) == 1 && zct != 128)
{
if (zct<128) printf("%s/%u\n", str, zct);
if (zct < 128)
printf("%s/%u\n", str, zct);
continue;
}
}
else if (d == '-')
{
if (inet_pton(AF_INET6, s+1, &a)) printf("%s-%s\n", str, s+1);
if (inet_pton(AF_INET6, s + 1, &a))
printf("%s-%s\n", str, s + 1);
continue;
}
if (ipct >= iplist_size)
@ -371,7 +376,8 @@ int main(int argc, char **argv)
if (memcmp(&ip_start, &ip, sizeof(ip)))
break;
}
if (ip_ct == 1) break;
if (ip_ct == 1)
break;
if (ip_ct >= params.v6_threshold)
{
// network found. but is there smaller network with the same ip_ct ? dont do carpet bombing if possible, use smaller subnets
@ -411,8 +417,7 @@ int main(int argc, char **argv)
{
printf("%u.%u.%u.%u-%u.%u.%u.%u\n", u1, u2, u3, u4, u11, u22, u33, u44);
}
else
if ((i = sscanf(str, "%u.%u.%u.%u/%u", &u1, &u2, &u3, &u4, &zct)) >= 4 &&
else if ((i = sscanf(str, "%u.%u.%u.%u/%u", &u1, &u2, &u3, &u4, &zct)) >= 4 &&
!(u1 & 0xFFFFFF00) && !(u2 & 0xFFFFFF00) && !(u3 & 0xFFFFFF00) && !(u4 & 0xFFFFFF00))
{
if (i == 5 && zct != 32)
@ -459,8 +464,10 @@ int main(int argc, char **argv)
if (iplist[pos] > (ip_start + subnet_ct * (params.pctdiv - params.pctmult) / params.pctdiv))
continue; // ip is higher than (1-PCT). definitely coverage is not enough. skip searching
ip_end = ip_start | ~mask;
for (p=pos+1, ip_ct=1; p < ipct && iplist[p] <= ip_end; p++) ip_ct++; // count ips within subnet range
if (ip_ct == 1) break;
for (p = pos + 1, ip_ct = 1; p < ipct && iplist[p] <= ip_end; p++)
ip_ct++; // count ips within subnet range
if (ip_ct == 1)
break;
if (ip_ct >= (subnet_ct * params.pctmult / params.pctdiv))
{
// network found. but is there smaller network with the same ip_ct ? dont do carpet bombing if possible, use smaller subnets

View File

@ -61,7 +61,6 @@ typedef struct
#define POP(low, high) ((void)(--top, (low = top->lo), (high = top->hi)))
#define STACK_NOT_EMPTY (stack < top)
/* Order size using quicksort. This implementation incorporates
four optimizations discussed in Sedgewick:
@ -86,8 +85,7 @@ typedef struct
smaller partition. This *guarantees* no more than log (total_elems)
stack size is needed (actually O(1) in this case)! */
void
gnu_quicksort (void *const pbase, size_t total_elems, size_t size,
void gnu_quicksort(void *const pbase, size_t total_elems, size_t size,
__gnu_compar_d_fn_t cmp, void *arg)
{
char *base_ptr = (char *)pbase;
@ -160,8 +158,7 @@ gnu_quicksort (void *const pbase, size_t total_elems, size_t size,
right_ptr -= size;
break;
}
}
while (left_ptr <= right_ptr);
} while (left_ptr <= right_ptr);
/* Set up pointers for next iteration. First determine whether
left and right partitions are below the threshold size. If so,

View File

@ -34,7 +34,8 @@
static void trimstr(char *s)
{
char *p;
for (p = s + strlen(s) - 1; p >= s && (*p == '\n' || *p == '\r'); p--) *p = '\0';
for (p = s + strlen(s) - 1; p >= s && (*p == '\n' || *p == '\r'); p--)
*p = '\0';
}
static const char *eai_str(int r)
@ -76,7 +77,8 @@ static const char* eai_str(int r)
static bool dom_valid(char *dom)
{
if (!dom || *dom=='.') return false;
if (!dom || *dom == '.')
return false;
for (; *dom; dom++)
if (*dom < 0x20 || (*dom & 0x80) || !(*dom == '.' || *dom == '-' || *dom == '_' || (*dom >= '0' && *dom <= '9') || (*dom >= 'a' && *dom <= 'z') || (*dom >= 'A' && *dom <= 'Z')))
return false;
@ -86,8 +88,10 @@ static bool dom_valid(char *dom)
static void invalid_domain_beautify(char *dom)
{
for (int i = 0; *dom && i < 64; i++, dom++)
if (*dom < 0x20 || *dom>0x7F) *dom = '?';
if (*dom) *dom = 0;
if (*dom < 0x20 || *dom > 0x7F)
*dom = '?';
if (*dom)
*dom = 0;
}
#define FAMILY4 1
@ -111,7 +115,8 @@ static char interlocked_get_dom(char *dom, size_t size)
pthread_mutex_lock(&glob.flock);
s = fgets(dom, size, stdin);
pthread_mutex_unlock(&glob.flock);
if (!s) return 0;
if (!s)
return 0;
trimstr(s);
return 1;
}
@ -129,7 +134,11 @@ static void interlocked_fprintf(FILE *stream, const char * format, ...)
}
#define ELOG(format, ...) interlocked_fprintf(stderr, "[%d] " format "\n", tid, ##__VA_ARGS__)
#define VLOG(format, ...) {if (glob.verbose) ELOG(format, ##__VA_ARGS__);}
#define VLOG(format, ...) \
{ \
if (glob.verbose) \
ELOG(format, ##__VA_ARGS__); \
}
static void print_addrinfo(struct addrinfo *ai)
{
@ -170,7 +179,8 @@ static void stat_plus(bool is_ok)
ct_ok = glob.stats_ct_ok += is_ok;
pthread_mutex_unlock(&glob.slock);
if (!(ct % glob.stats_every)) stat_print(ct, ct_ok);
if (!(ct % glob.stats_every))
stat_print(ct, ct_ok);
}
}
@ -198,7 +208,8 @@ static void *t_resolver(void *arg)
VLOG("started");
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = (glob.family == FAMILY4) ? AF_INET : (glob.family == FAMILY6) ? AF_INET6 : AF_UNSPEC;
hints.ai_family = (glob.family == FAMILY4) ? AF_INET : (glob.family == FAMILY6) ? AF_INET6
: AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
while (interlocked_get_dom(dom, sizeof(dom)))
@ -211,7 +222,8 @@ static void *t_resolver(void *arg)
strncpy(s_ip, dom, sizeof(s_ip));
s_mask = strchr(s_ip, '/');
if (s_mask) *s_mask++ = 0;
if (s_mask)
*s_mask++ = 0;
family = GetAddrFamily(s_ip);
if (family)
{
@ -225,8 +237,14 @@ static void *t_resolver(void *arg)
{
switch (family)
{
case AF_INET: is_ok = mask <= 32; mask_needed = mask < 32; break;
case AF_INET6: is_ok = mask <= 128; mask_needed = mask < 128; break;
case AF_INET:
is_ok = mask <= 32;
mask_needed = mask < 32;
break;
case AF_INET6:
is_ok = mask <= 128;
mask_needed = mask < 128;
break;
}
}
}
@ -248,7 +266,8 @@ static void *t_resolver(void *arg)
if ((r = getaddrinfo(dom, NULL, &hints, &result)))
{
VLOG("failed to resolve %s : result %d (%s)", dom, r, eai_str(r));
if (r == EAI_AGAIN) continue; // temporary failure. should retry
if (r == EAI_AGAIN)
continue; // temporary failure. should retry
}
else
{
@ -327,8 +346,7 @@ static void exithelp(void)
" --verbose\t\t; print query progress to stderr\n"
" --stats=N\t\t; print resolve stats to stderr every N domains\n"
" --log-resolved=<file>\t; log successfully resolved domains to a file\n"
" --log-failed=<file>\t; log failed domains to a file\n"
);
" --log-failed=<file>\t; log failed domains to a file\n");
exit(1);
}
int main(int argc, char **argv)
@ -344,8 +362,7 @@ int main(int argc, char **argv)
{"stats", required_argument, 0, 0}, // optidx=4
{"log-resolved", required_argument, 0, 0}, // optidx=5
{"log-failed", required_argument, 0, 0}, // optidx=6
{NULL,0,NULL,0}
};
{NULL, 0, NULL, 0}};
memset(&glob, 0, sizeof(glob));
*fn1 = *fn2 = 0;
@ -353,7 +370,8 @@ int main(int argc, char **argv)
glob.threads = 1;
while ((v = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1)
{
if (v) exithelp();
if (v)
exithelp();
switch (option_index)
{
case 0: /* help */
@ -412,7 +430,8 @@ int main(int argc, char **argv)
if (!glob.F_log_resolved)
{
fprintf(stderr, "failed to create %s\n", fn1);
r=5; goto ex;
r = 5;
goto ex;
}
}
if (*fn2)
@ -421,15 +440,18 @@ int main(int argc, char **argv)
if (!glob.F_log_failed)
{
fprintf(stderr, "failed to create %s\n", fn2);
r=5; goto ex;
r = 5;
goto ex;
}
}
r = run_threads();
ex:
if (glob.F_log_resolved) fclose(glob.F_log_resolved);
if (glob.F_log_failed) fclose(glob.F_log_failed);
if (glob.F_log_resolved)
fclose(glob.F_log_resolved);
if (glob.F_log_failed)
fclose(glob.F_log_failed);
return r;
}

View File

@ -13,7 +13,7 @@ static uint16_t from64to16(uint64_t x)
// this function preserves data alignment requirements (otherwise it will be damn slow on mips arch)
// and uses 64-bit arithmetics to improve speed
// taken from linux source code
// taken from Linux source code
static uint16_t do_csum(const uint8_t *buff, size_t len)
{
uint8_t odd;
@ -21,7 +21,8 @@ static uint16_t do_csum(const uint8_t * buff, size_t len)
uint64_t result, w, carry = 0;
uint16_t u16;
if (!len) return 0;
if (!len)
return 0;
odd = (uint8_t)(1 & (size_t)buff);
if (odd)
{
@ -89,7 +90,8 @@ static uint16_t do_csum(const uint8_t * buff, size_t len)
result += u16;
}
u16 = from64to16(result);
if (odd) u16 = ((u16 >> 8) & 0xff) | ((u16 & 0xff) << 8);
if (odd)
u16 = ((u16 >> 8) & 0xff) | ((u16 & 0xff) << 8);
return u16;
}
@ -121,7 +123,6 @@ uint16_t csum_ipv6_magic(const void *saddr, const void *daddr, size_t len, uint8
return ~from64to16(a);
}
void tcp4_fix_checksum(struct tcphdr *tcp, size_t len, const struct in_addr *src_addr, const struct in_addr *dest_addr)
{
tcp->th_sum = 0;

View File

@ -49,7 +49,11 @@ static void ConntrackFreeElem(t_conntrack_pool *elem)
static void ConntrackPoolDestroyPool(t_conntrack_pool **pp)
{
t_conntrack_pool *elem, *tmp;
HASH_ITER(hh, *pp, elem, tmp) { HASH_DEL(*pp, elem); ConntrackFreeElem(elem); }
HASH_ITER(hh, *pp, elem, tmp)
{
HASH_DEL(*pp, elem);
ConntrackFreeElem(elem);
}
}
void ConntrackPoolDestroy(t_conntrack *p)
{
@ -87,7 +91,6 @@ void ConntrackExtractConn(t_conn *c, bool bReverse, const struct ip *ip, const s
extract_ports(tcphdr, udphdr, &c->l4proto, bReverse ? &c->dport : &c->sport, bReverse ? &c->sport : &c->dport);
}
static t_conntrack_pool *ConntrackPoolSearch(t_conntrack_pool *p, const t_conn *c)
{
t_conntrack_pool *t;
@ -111,11 +114,16 @@ static void ConntrackReInitTrack(t_ctrack *t)
static t_conntrack_pool *ConntrackNew(t_conntrack_pool **pp, const t_conn *c)
{
t_conntrack_pool *ctnew;
if (!(ctnew = malloc(sizeof(*ctnew)))) return NULL;
if (!(ctnew = malloc(sizeof(*ctnew))))
return NULL;
ctnew->conn = *c;
oom = false;
HASH_ADD(hh, *pp, conn, sizeof(*c), ctnew);
if (oom) { free(ctnew); return NULL; }
if (oom)
{
free(ctnew);
return NULL;
}
ConntrackInitTrack(&ctnew->track);
return ctnew;
}
@ -129,7 +137,6 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
{
t->pcounter_reply++;
t->pdcounter_reply += !!len_payload;
}
else
{
@ -141,13 +148,16 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
{
if (tcp_syn_segment(tcphdr))
{
if (t->state!=SYN) ConntrackReInitTrack(t); // erase current entry
if (t->state != SYN)
ConntrackReInitTrack(t); // erase current entry
t->seq0 = ntohl(tcphdr->th_seq);
}
else if (tcp_synack_segment(tcphdr))
{
if (t->state!=SYN) ConntrackReInitTrack(t); // erase current entry
if (!t->seq0) t->seq0 = ntohl(tcphdr->th_ack)-1;
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))
@ -159,7 +169,8 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
if (t->state == SYN)
{
t->state = ESTABLISHED;
if (!bReverse && !t->ack0) t->ack0 = ntohl(tcphdr->th_ack)-1;
if (!bReverse && !t->ack0)
t->ack0 = ntohl(tcphdr->th_ack) - 1;
}
}
scale = tcp_find_scale_factor(tcphdr);
@ -169,8 +180,8 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
t->ack_last = ntohl(tcphdr->th_seq);
t->pos_reply = t->ack_last + len_payload;
t->winsize_reply = ntohs(tcphdr->th_win);
if (scale!=SCALE_NONE) t->scale_reply = scale;
if (scale != SCALE_NONE)
t->scale_reply = scale;
}
else
{
@ -178,7 +189,8 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
t->pos_orig = t->seq_last + len_payload;
t->pos_reply = t->ack_last = ntohl(tcphdr->th_ack);
t->winsize_orig = ntohs(tcphdr->th_win);
if (scale!=SCALE_NONE) t->scale_orig = scale;
if (scale != SCALE_NONE)
t->scale_orig = scale;
}
}
else
@ -206,8 +218,10 @@ static bool ConntrackPoolDoubleSearchPool(t_conntrack_pool **pp, const struct ip
ConntrackExtractConn(&conn, false, ip, ip6, tcphdr, udphdr);
if ((ctr = ConntrackPoolSearch(*pp, &conn)))
{
if (bReverse) *bReverse = false;
if (ctrack) *ctrack = &ctr->track;
if (bReverse)
*bReverse = false;
if (ctrack)
*ctrack = &ctr->track;
return true;
}
else
@ -215,8 +229,10 @@ static bool ConntrackPoolDoubleSearchPool(t_conntrack_pool **pp, const struct ip
connswap(&conn, &connswp);
if ((ctr = ConntrackPoolSearch(*pp, &connswp)))
{
if (bReverse) *bReverse = true;
if (ctrack) *ctrack = &ctr->track;
if (bReverse)
*bReverse = true;
if (ctrack)
*ctrack = &ctr->track;
return true;
}
}
@ -259,8 +275,10 @@ static bool ConntrackPoolFeedPool(t_conntrack_pool **pp, const struct ip *ip, co
}
return false;
ok:
if (ctrack) *ctrack = &ctr->track;
if (bReverse) *bReverse = b_rev;
if (ctrack)
*ctrack = &ctr->track;
if (bReverse)
*bReverse = b_rev;
return true;
}
bool ConntrackPoolFeed(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, size_t len_payload, t_ctrack **ctrack, bool *bReverse)
@ -278,8 +296,10 @@ static bool ConntrackPoolDropPool(t_conntrack_pool **pp, const struct ip *ip, co
connswap(&conn, &connswp);
t = ConntrackPoolSearch(*pp, &connswp);
}
if (!t) return false;
HASH_DEL(*pp, t); ConntrackFreeElem(t);
if (!t)
return false;
HASH_DEL(*pp, t);
ConntrackFreeElem(t);
return true;
}
bool ConntrackPoolDrop(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr)
@ -294,17 +314,17 @@ void ConntrackPoolPurge(t_conntrack *p)
if ((tnow - p->t_last_purge) >= p->t_purge_interval)
{
HASH_ITER(hh, p->pool , t, tmp) {
HASH_ITER(hh, p->pool, t, tmp)
{
tidle = tnow - t->track.t_last;
if (t->track.b_cutoff ||
(t->conn.l4proto==IPPROTO_TCP && (
(t->track.state==SYN && tidle>=p->timeout_syn) ||
(t->conn.l4proto == IPPROTO_TCP && ((t->track.state == SYN && tidle >= p->timeout_syn) ||
(t->track.state == ESTABLISHED && tidle >= p->timeout_established) ||
(t->track.state==FIN && tidle>=p->timeout_fin))
) || (t->conn.l4proto==IPPROTO_UDP && tidle>=p->timeout_udp)
)
(t->track.state == FIN && tidle >= p->timeout_fin))) ||
(t->conn.l4proto == IPPROTO_UDP && tidle >= p->timeout_udp))
{
HASH_DEL(p->pool, t); ConntrackFreeElem(t);
HASH_DEL(p->pool, t);
ConntrackFreeElem(t);
}
}
p->t_last_purge = tnow;
@ -313,19 +333,26 @@ void ConntrackPoolPurge(t_conntrack *p)
static void taddr2str(uint8_t l3proto, const t_addr *a, char *buf, size_t bufsize)
{
if (!inet_ntop(family_from_proto(l3proto), a, buf, bufsize) && bufsize) *buf=0;
if (!inet_ntop(family_from_proto(l3proto), a, buf, bufsize) && bufsize)
*buf = 0;
}
static const char *ConntrackProtoName(t_l7proto proto)
{
switch (proto)
{
case HTTP: return "HTTP";
case TLS: return "TLS";
case QUIC: return "QUIC";
case WIREGUARD: return "WIREGUARD";
case DHT: return "DHT";
default: return "UNKNOWN";
case HTTP:
return "HTTP";
case TLS:
return "TLS";
case QUIC:
return "QUIC";
case WIREGUARD:
return "WIREGUARD";
case DHT:
return "DHT";
default:
return "UNKNOWN";
}
}
void ConntrackPoolDump(const t_conntrack *p)
@ -333,7 +360,8 @@ void ConntrackPoolDump(const t_conntrack *p)
t_conntrack_pool *t, *tmp;
char sa1[40], sa2[40];
time_t tnow = time(NULL);
HASH_ITER(hh, p->pool, t, tmp) {
HASH_ITER(hh, p->pool, t, tmp)
{
taddr2str(t->conn.l3proto, &t->conn.src, sa1, sizeof(sa1));
taddr2str(t->conn.l3proto, &t->conn.dst, sa2, sizeof(sa2));
printf("%s [%s]:%u => [%s]:%u : %s : t0=%llu last=t0+%llu now=last+%llu packets_orig=d%llu/n%llu packets_reply=d%llu/n%llu ",
@ -358,7 +386,6 @@ void ConntrackPoolDump(const t_conntrack *p)
};
}
void ReasmClear(t_reassemble *reasm)
{
if (reasm->packet)
@ -371,7 +398,8 @@ void ReasmClear(t_reassemble *reasm)
bool ReasmInit(t_reassemble *reasm, size_t size_requested, uint32_t seq_start)
{
reasm->packet = malloc(size_requested);
if (!reasm->packet) return false;
if (!reasm->packet)
return false;
reasm->size = size_requested;
reasm->size_present = 0;
reasm->seq = seq_start;
@ -380,19 +408,23 @@ bool ReasmInit(t_reassemble *reasm, size_t size_requested, uint32_t seq_start)
bool ReasmResize(t_reassemble *reasm, size_t new_size)
{
uint8_t *p = realloc(reasm->packet, new_size);
if (!p) return false;
if (!p)
return false;
reasm->packet = p;
reasm->size = new_size;
if (reasm->size_present > new_size) reasm->size_present = new_size;
if (reasm->size_present > new_size)
reasm->size_present = new_size;
return true;
}
bool ReasmFeed(t_reassemble *reasm, uint32_t seq, const void *payload, size_t len)
{
if (reasm->seq!=seq) return false; // fail session if out of sequence
if (reasm->seq != seq)
return false; // fail session if out of sequence
size_t szcopy;
szcopy = reasm->size - reasm->size_present;
if (len<szcopy) szcopy = len;
if (len < szcopy)
szcopy = len;
memcpy(reasm->packet + reasm->size_present, payload, szcopy);
reasm->size_present += szcopy;
reasm->seq += (uint32_t)szcopy;

View File

@ -1,6 +1,5 @@
#pragma once
// this conntrack is not bullet-proof
// its designed to satisfy dpi desync needs only
@ -19,7 +18,6 @@
#include <netinet/tcp.h>
#include <netinet/udp.h>
// #define HASH_BLOOM 20
#define HASH_NONFATAL_OOM 1
#undef HASH_FUNCTION
@ -28,7 +26,8 @@
#define RETRANS_COUNTER_STOP ((uint8_t) - 1)
typedef union {
typedef union
{
struct in_addr ip;
struct in6_addr ip6;
} t_addr;
@ -41,7 +40,8 @@ typedef struct
} t_conn;
// this structure helps to reassemble continuous packets streams. it does not support out-of-orders
typedef struct {
typedef struct
{
uint8_t *packet; // allocated for size during reassemble request. requestor must know the message size.
uint32_t seq; // current seq number. if a packet comes with an unexpected seq - it fails reassemble session.
size_t size; // expected message size. success means that we have received exactly 'size' bytes and have them in 'packet'
@ -51,8 +51,21 @@ typedef struct {
// SYN - SYN or SYN/ACK received
// ESTABLISHED - any except SYN or SYN/ACK received
// FIN - FIN or RST received
typedef enum {SYN=0, ESTABLISHED, FIN} t_connstate;
typedef enum {UNKNOWN=0, HTTP, TLS, QUIC, WIREGUARD, DHT} t_l7proto;
typedef enum
{
SYN = 0,
ESTABLISHED,
FIN
} t_connstate;
typedef enum
{
UNKNOWN = 0,
HTTP,
TLS,
QUIC,
WIREGUARD,
DHT
} t_l7proto;
typedef struct
{
// common state

View File

@ -58,17 +58,18 @@ static uint32_t RCON[10]; // AES round constants
* Platform Endianness Neutralizing Load and Store Macro definitions
* AES wants platform-neutral Little Endian (LE) byte ordering
*/
#define GET_UINT32_LE(n,b,i) { \
(n) = ( (uint32_t) (b)[(i) ] ) \
| ( (uint32_t) (b)[(i) + 1] << 8 ) \
| ( (uint32_t) (b)[(i) + 2] << 16 ) \
| ( (uint32_t) (b)[(i) + 3] << 24 ); }
#define GET_UINT32_LE(n, b, i) \
{ \
(n) = ((uint32_t)(b)[(i)]) | ((uint32_t)(b)[(i) + 1] << 8) | ((uint32_t)(b)[(i) + 2] << 16) | ((uint32_t)(b)[(i) + 3] << 24); \
}
#define PUT_UINT32_LE(n,b,i) { \
#define PUT_UINT32_LE(n, b, i) \
{ \
(b)[(i)] = (uchar)((n)); \
(b)[(i) + 1] = (uchar)((n) >> 8); \
(b)[(i) + 2] = (uchar)((n) >> 16); \
(b)[(i) + 3] = (uchar) ( (n) >> 24 ); }
(b)[(i) + 3] = (uchar)((n) >> 24); \
}
/*
* AES forward and reverse encryption round processing macros
@ -127,9 +128,18 @@ static uint32_t RCON[10]; // AES round constants
#define ROTL8(x) ((x << 8) & 0xFFFFFFFF) | (x >> 24)
#define XTIME(x) ((x << 1) ^ ((x & 0x80) ? 0x1B : 0x00))
#define MUL(x, y) ((x && y) ? pow[(log[x] + log[y]) % 255] : 0)
#define MIX(x,y) { y = ( (y << 1) | (y >> 7) ) & 0xFF; x ^= y; }
#define CPY128 { *RK++ = *SK++; *RK++ = *SK++; \
*RK++ = *SK++; *RK++ = *SK++; }
#define MIX(x, y) \
{ \
y = ((y << 1) | (y >> 7)) & 0xFF; \
x ^= y; \
}
#define CPY128 \
{ \
*RK++ = *SK++; \
*RK++ = *SK++; \
*RK++ = *SK++; \
*RK++ = *SK++; \
}
/******************************************************************************
*
@ -147,16 +157,19 @@ void aes_init_keygen_tables(void)
int pow[256];
int log[256];
if (aes_tables_inited) return;
if (aes_tables_inited)
return;
// fill the 'pow' and 'log' tables over GF(2^8)
for (i = 0, x = 1; i < 256; i++) {
for (i = 0, x = 1; i < 256; i++)
{
pow[i] = x;
log[x] = i;
x = (x ^ XTIME(x)) & 0xFF;
}
// compute the round constants
for (i = 0, x = 1; i < 10; i++) {
for (i = 0, x = 1; i < 10; i++)
{
RCON[i] = (uint32_t)x;
x = XTIME(x) & 0xFF;
}
@ -166,7 +179,8 @@ void aes_init_keygen_tables(void)
RSb[0x63] = 0x00;
#endif /* AES_DECRYPTION */
for (i = 1; i < 256; i++) {
for (i = 1; i < 256; i++)
{
x = y = pow[255 - log[i]];
MIX(x, y);
MIX(x, y);
@ -176,10 +190,10 @@ void aes_init_keygen_tables(void)
#if AES_DECRYPTION // whether AES decryption is supported
RSb[x] = (uchar)i;
#endif /* AES_DECRYPTION */
}
// generate the forward and reverse key expansion tables
for (i = 0; i < 256; i++) {
for (i = 0; i < 256; i++)
{
x = FSb[i];
y = XTIME(x) & 0xFF;
z = (y ^ x) & 0xFF;
@ -224,14 +238,16 @@ int aes_set_encryption_key(aes_context *ctx,
uint i; // general purpose iteration local
uint32_t *RK = ctx->rk; // initialize our RoundKey buffer pointer
for (i = 0; i < (keysize >> 2); i++) {
for (i = 0; i < (keysize >> 2); i++)
{
GET_UINT32_LE(RK[i], key, i << 2);
}
switch (ctx->rounds)
{
case 10:
for (i = 0; i < 10; i++, RK += 4) {
for (i = 0; i < 10; i++, RK += 4)
{
RK[4] = RK[0] ^ RCON[i] ^
((uint32_t)FSb[(RK[3] >> 8) & 0xFF]) ^
((uint32_t)FSb[(RK[3] >> 16) & 0xFF] << 8) ^
@ -245,7 +261,8 @@ int aes_set_encryption_key(aes_context *ctx,
break;
case 12:
for (i = 0; i < 8; i++, RK += 6) {
for (i = 0; i < 8; i++, RK += 6)
{
RK[6] = RK[0] ^ RCON[i] ^
((uint32_t)FSb[(RK[5] >> 8) & 0xFF]) ^
((uint32_t)FSb[(RK[5] >> 16) & 0xFF] << 8) ^
@ -261,7 +278,8 @@ int aes_set_encryption_key(aes_context *ctx,
break;
case 14:
for (i = 0; i < 7; i++, RK += 8) {
for (i = 0; i < 7; i++, RK += 8)
{
RK[8] = RK[0] ^ RCON[i] ^
((uint32_t)FSb[(RK[7] >> 8) & 0xFF]) ^
((uint32_t)FSb[(RK[7] >> 16) & 0xFF] << 8) ^
@ -322,8 +340,10 @@ int aes_set_decryption_key(aes_context *ctx,
CPY128 // copy a 128-bit block from *SK to *RK
for (i = ctx->rounds - 1, SK -= 8; i > 0; i--, SK -= 8) {
for (j = 0; j < 4; j++, SK++) {
for (i = ctx->rounds - 1, SK -= 8; i > 0; i--, SK -= 8)
{
for (j = 0; j < 4; j++, SK++)
{
*RK++ = RT0[FSb[(*SK) & 0xFF]] ^
RT1[FSb[(*SK >> 8) & 0xFF]] ^
RT2[FSb[(*SK >> 16) & 0xFF]] ^
@ -353,17 +373,25 @@ int aes_setkey(aes_context *ctx, // AES context provided by our caller
// system-specific mutexes and init the AES key generation tables on
// demand, or ask the developer to simply call "gcm_initialize" once during
// application startup before threading begins. That's what we choose.
if (!aes_tables_inited) return (-1); // fail the call when not inited.
if (!aes_tables_inited)
return (-1); // fail the call when not inited.
ctx->mode = mode; // capture the key type we're creating
ctx->rk = ctx->buf; // initialize our round key pointer
switch (keysize) // set the rounds count based upon the keysize
{
case 16: ctx->rounds = 10; break; // 16-byte, 128-bit key
case 24: ctx->rounds = 12; break; // 24-byte, 192-bit key
case 32: ctx->rounds = 14; break; // 32-byte, 256-bit key
default: return(-1);
case 16:
ctx->rounds = 10;
break; // 16-byte, 128-bit key
case 24:
ctx->rounds = 12;
break; // 24-byte, 192-bit key
case 32:
ctx->rounds = 14;
break; // 32-byte, 256-bit key
default:
return (-1);
}
#if AES_DECRYPTION
@ -392,10 +420,14 @@ int aes_cipher(aes_context *ctx,
RK = ctx->rk;
GET_UINT32_LE(X0, input, 0); X0 ^= *RK++; // load our 128-bit
GET_UINT32_LE(X1, input, 4); X1 ^= *RK++; // input buffer in a storage
GET_UINT32_LE(X2, input, 8); X2 ^= *RK++; // memory endian-neutral way
GET_UINT32_LE(X3, input, 12); X3 ^= *RK++;
GET_UINT32_LE(X0, input, 0);
X0 ^= *RK++; // load our 128-bit
GET_UINT32_LE(X1, input, 4);
X1 ^= *RK++; // input buffer in a storage
GET_UINT32_LE(X2, input, 8);
X2 ^= *RK++; // memory endian-neutral way
GET_UINT32_LE(X3, input, 12);
X3 ^= *RK++;
#if AES_DECRYPTION // whether AES decryption is supported
@ -409,25 +441,25 @@ int aes_cipher(aes_context *ctx,
AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3);
X0 = *RK++ ^ \
X0 = *RK++ ^
((uint32_t)RSb[(Y0) & 0xFF]) ^
((uint32_t)RSb[(Y3 >> 8) & 0xFF] << 8) ^
((uint32_t)RSb[(Y2 >> 16) & 0xFF] << 16) ^
((uint32_t)RSb[(Y1 >> 24) & 0xFF] << 24);
X1 = *RK++ ^ \
X1 = *RK++ ^
((uint32_t)RSb[(Y1) & 0xFF]) ^
((uint32_t)RSb[(Y0 >> 8) & 0xFF] << 8) ^
((uint32_t)RSb[(Y3 >> 16) & 0xFF] << 16) ^
((uint32_t)RSb[(Y2 >> 24) & 0xFF] << 24);
X2 = *RK++ ^ \
X2 = *RK++ ^
((uint32_t)RSb[(Y2) & 0xFF]) ^
((uint32_t)RSb[(Y1 >> 8) & 0xFF] << 8) ^
((uint32_t)RSb[(Y0 >> 16) & 0xFF] << 16) ^
((uint32_t)RSb[(Y3 >> 24) & 0xFF] << 24);
X3 = *RK++ ^ \
X3 = *RK++ ^
((uint32_t)RSb[(Y3) & 0xFF]) ^
((uint32_t)RSb[(Y2 >> 8) & 0xFF] << 8) ^
((uint32_t)RSb[(Y1 >> 16) & 0xFF] << 16) ^
@ -445,25 +477,25 @@ int aes_cipher(aes_context *ctx,
AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3);
X0 = *RK++ ^ \
X0 = *RK++ ^
((uint32_t)FSb[(Y0) & 0xFF]) ^
((uint32_t)FSb[(Y1 >> 8) & 0xFF] << 8) ^
((uint32_t)FSb[(Y2 >> 16) & 0xFF] << 16) ^
((uint32_t)FSb[(Y3 >> 24) & 0xFF] << 24);
X1 = *RK++ ^ \
X1 = *RK++ ^
((uint32_t)FSb[(Y1) & 0xFF]) ^
((uint32_t)FSb[(Y2 >> 8) & 0xFF] << 8) ^
((uint32_t)FSb[(Y3 >> 16) & 0xFF] << 16) ^
((uint32_t)FSb[(Y0 >> 24) & 0xFF] << 24);
X2 = *RK++ ^ \
X2 = *RK++ ^
((uint32_t)FSb[(Y2) & 0xFF]) ^
((uint32_t)FSb[(Y3 >> 8) & 0xFF] << 8) ^
((uint32_t)FSb[(Y0 >> 16) & 0xFF] << 16) ^
((uint32_t)FSb[(Y1 >> 24) & 0xFF] << 24);
X3 = *RK++ ^ \
X3 = *RK++ ^
((uint32_t)FSb[(Y3) & 0xFF]) ^
((uint32_t)FSb[(Y0 >> 8) & 0xFF] << 8) ^
((uint32_t)FSb[(Y1 >> 16) & 0xFF] << 16) ^

View File

@ -41,24 +41,22 @@ typedef UINT32 uint32_t;
typedef unsigned char uchar; // add some convienent shorter types
typedef unsigned int uint;
/******************************************************************************
* AES_INIT_KEYGEN_TABLES : MUST be called once before any AES use
******************************************************************************/
void aes_init_keygen_tables(void);
/******************************************************************************
* AES_CONTEXT : cipher context / holds inter-call data
******************************************************************************/
typedef struct {
typedef struct
{
int mode; // 1 for Encryption, 0 for Decryption
int rounds; // keysize-based rounds count
uint32_t *rk; // pointer to current round key
uint32_t buf[68]; // key expansion buffer
} aes_context;
/******************************************************************************
* AES_SETKEY : called to expand the key for encryption or decryption
******************************************************************************/

View File

@ -83,18 +83,18 @@ static const uint64_t last4[16] = {
* Platform Endianness Neutralizing Load and Store Macro definitions
* GCM wants platform-neutral Big Endian (BE) byte ordering
*/
#define GET_UINT32_BE(n,b,i) { \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); }
#define GET_UINT32_BE(n, b, i) \
{ \
(n) = ((uint32_t)(b)[(i)] << 24) | ((uint32_t)(b)[(i) + 1] << 16) | ((uint32_t)(b)[(i) + 2] << 8) | ((uint32_t)(b)[(i) + 3]); \
}
#define PUT_UINT32_BE(n,b,i) { \
#define PUT_UINT32_BE(n, b, i) \
{ \
(b)[(i)] = (uchar)((n) >> 24); \
(b)[(i) + 1] = (uchar)((n) >> 16); \
(b)[(i) + 2] = (uchar)((n) >> 8); \
(b)[(i) + 3] = (uchar) ( (n) ); }
(b)[(i) + 3] = (uchar)((n)); \
}
/******************************************************************************
*
@ -114,7 +114,6 @@ int gcm_initialize(void)
return (0);
}
/******************************************************************************
*
* GCM_MULT
@ -137,11 +136,13 @@ static void gcm_mult(gcm_context *ctx, // pointer to established context
zh = ctx->HH[lo];
zl = ctx->HL[lo];
for (i = 15; i >= 0; i--) {
for (i = 15; i >= 0; i--)
{
lo = (uchar)(x[i] & 0x0f);
hi = (uchar)(x[i] >> 4);
if (i != 15) {
if (i != 15)
{
rem = (uchar)(zl & 0x0f);
zl = (zh << 60) | (zl >> 4);
zh = (zh >> 4);
@ -162,7 +163,6 @@ static void gcm_mult(gcm_context *ctx, // pointer to established context
PUT_UINT32_BE(zl, output, 12);
}
/******************************************************************************
*
* GCM_SETKEY
@ -204,18 +204,21 @@ int gcm_setkey(gcm_context *ctx, // pointer to caller-provided gcm context
ctx->HH[0] = 0; // 0 corresponds to 0 in GF(2^128)
ctx->HL[0] = 0;
for (i = 4; i > 0; i >>= 1) {
for (i = 4; i > 0; i >>= 1)
{
uint32_t T = (uint32_t)(vl & 1) * 0xe1000000U;
vl = (vh << 63) | (vl >> 1);
vh = (vh >> 1) ^ ((uint64_t)T << 32);
ctx->HL[i] = vl;
ctx->HH[i] = vh;
}
for (i = 2; i < 16; i <<= 1) {
for (i = 2; i < 16; i <<= 1)
{
uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
vh = *HiH;
vl = *HiL;
for (j = 1; j < i; j++) {
for (j = 1; j < i; j++)
{
HiH[j] = vh ^ ctx->HH[j];
HiL[j] = vl ^ ctx->HL[j];
}
@ -223,7 +226,6 @@ int gcm_setkey(gcm_context *ctx, // pointer to caller-provided gcm context
return (0);
}
/******************************************************************************
*
* GCM processing occurs four phases: SETKEY, START, UPDATE and FINISH.
@ -268,7 +270,8 @@ int gcm_start(gcm_context *ctx, // pointer to user-provided GCM context
ctx->mode = mode; // set the GCM encryption/decryption mode
ctx->aes_ctx.mode = AES_ENCRYPT; // GCM *always* runs AES in ENCRYPTION mode
if (iv_len == 12) { // GCM natively uses a 12-byte, 96-bit IV
if (iv_len == 12)
{ // GCM natively uses a 12-byte, 96-bit IV
memcpy(ctx->y, iv, iv_len); // copy the IV to the top of the 'y' buff
ctx->y[15] = 1; // start "counting" from 1 (not 0)
}
@ -278,14 +281,17 @@ int gcm_start(gcm_context *ctx, // pointer to user-provided GCM context
PUT_UINT32_BE(iv_len * 8, work_buf, 12); // place the IV into buffer
p = iv;
while (iv_len > 0) {
while (iv_len > 0)
{
use_len = (iv_len < 16) ? iv_len : 16;
for (i = 0; i < use_len; i++) ctx->y[i] ^= p[i];
for (i = 0; i < use_len; i++)
ctx->y[i] ^= p[i];
gcm_mult(ctx, ctx->y, ctx->y);
iv_len -= use_len;
p += use_len;
}
for (i = 0; i < 16; i++) ctx->y[i] ^= work_buf[i];
for (i = 0; i < 16; i++)
ctx->y[i] ^= work_buf[i];
gcm_mult(ctx, ctx->y, ctx->y);
}
if ((ret = aes_cipher(&ctx->aes_ctx, ctx->y, ctx->base_ectr)) != 0)
@ -293,9 +299,11 @@ int gcm_start(gcm_context *ctx, // pointer to user-provided GCM context
ctx->add_len = add_len;
p = add;
while (add_len > 0) {
while (add_len > 0)
{
use_len = (add_len < 16) ? add_len : 16;
for (i = 0; i < use_len; i++) ctx->buf[i] ^= p[i];
for (i = 0; i < use_len; i++)
ctx->buf[i] ^= p[i];
gcm_mult(ctx, ctx->buf, ctx->buf);
add_len -= use_len;
p += use_len;
@ -326,12 +334,15 @@ int gcm_update(gcm_context *ctx, // pointer to user-provided GCM context
ctx->len += length; // bump the GCM context's running length count
while (length > 0) {
while (length > 0)
{
// clamp the length to process at 16 bytes
use_len = (length < 16) ? length : 16;
// increment the context's 128-bit IV||Counter 'y' vector
for (i = 16; i > 12; i--) if (++ctx->y[i - 1] != 0) break;
for (i = 16; i > 12; i--)
if (++ctx->y[i - 1] != 0)
break;
// encrypt the context's 'y' vector under the established key
if ((ret = aes_cipher(&ctx->aes_ctx, ctx->y, ectr)) != 0)
@ -340,7 +351,8 @@ int gcm_update(gcm_context *ctx, // pointer to user-provided GCM context
// encrypt or decrypt the input to the output
if (ctx->mode == AES_ENCRYPT)
{
for (i = 0; i < use_len; i++) {
for (i = 0; i < use_len; i++)
{
// XOR the cipher's ouptut vector (ectr) with our input
output[i] = (uchar)(ectr[i] ^ input[i]);
// now we mix in our data into the authentication hash.
@ -352,7 +364,8 @@ int gcm_update(gcm_context *ctx, // pointer to user-provided GCM context
}
else
{
for (i = 0; i < use_len; i++) {
for (i = 0; i < use_len; i++)
{
// but if we're DEcrypting we XOR in the input data first,
// i.e. before saving to ouput data, otherwise if the input
// and output buffer are the same (inplace decryption) we
@ -390,9 +403,11 @@ int gcm_finish(gcm_context *ctx, // pointer to user-provided GCM context
uint64_t orig_add_len = ctx->add_len * 8;
size_t i;
if (tag_len != 0) memcpy(tag, ctx->base_ectr, tag_len);
if (tag_len != 0)
memcpy(tag, ctx->base_ectr, tag_len);
if (orig_len || orig_add_len) {
if (orig_len || orig_add_len)
{
memset(work_buf, 0x00, 16);
PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0);
@ -400,14 +415,15 @@ int gcm_finish(gcm_context *ctx, // pointer to user-provided GCM context
PUT_UINT32_BE((orig_len >> 32), work_buf, 8);
PUT_UINT32_BE((orig_len), work_buf, 12);
for (i = 0; i < 16; i++) ctx->buf[i] ^= work_buf[i];
for (i = 0; i < 16; i++)
ctx->buf[i] ^= work_buf[i];
gcm_mult(ctx, ctx->buf, ctx->buf);
for (i = 0; i < tag_len; i++) tag[i] ^= ctx->buf[i];
for (i = 0; i < tag_len; i++)
tag[i] ^= ctx->buf[i];
}
return (0);
}
/******************************************************************************
*
* GCM_CRYPT_AND_TAG
@ -448,7 +464,6 @@ int gcm_crypt_and_tag(
return (0);
}
/******************************************************************************
*
* GCM_AUTH_DECRYPT
@ -488,7 +503,8 @@ int gcm_auth_decrypt(
for (diff = 0, i = 0; i < tag_len; i++)
diff |= tag[i] ^ check_tag[i];
if (diff != 0) { // see whether any bits differed?
if (diff != 0)
{ // see whether any bits differed?
memset(output, 0, length); // if so... wipe the output data
return (GCM_AUTH_FAILURE); // return GCM_AUTH_FAILURE
}

View File

@ -36,11 +36,11 @@ typedef UINT64 uint64_t;
#include <stdint.h>
#endif
/******************************************************************************
* GCM_CONTEXT : GCM context / holds keytables, instance data, and AES ctx
******************************************************************************/
typedef struct {
typedef struct
{
int mode; // cipher direction: encrypt/decrypt
uint64_t len; // cipher data length processed so far
uint64_t add_len; // total add data length
@ -52,13 +52,11 @@ typedef struct {
aes_context aes_ctx; // cipher context used
} gcm_context;
/******************************************************************************
* GCM_CONTEXT : MUST be called once before ANY use of this library
******************************************************************************/
int gcm_initialize(void);
/******************************************************************************
* GCM_SETKEY : sets the GCM (and AES) keying material for use
******************************************************************************/
@ -68,7 +66,6 @@ int gcm_setkey(gcm_context *ctx, // caller-provided context ptr
// 128, 192 or 256-bit keys respectively)
); // returns 0 for success
/******************************************************************************
*
* GCM_CRYPT_AND_TAG
@ -99,7 +96,6 @@ int gcm_crypt_and_tag(
uchar *tag, // pointer to the tag to be generated
size_t tag_len); // byte length of the tag to be generated
/******************************************************************************
*
* GCM_AUTH_DECRYPT
@ -124,7 +120,6 @@ int gcm_auth_decrypt(
const uchar *tag, // pointer to the tag to be authenticated
size_t tag_len); // byte length of the tag <= 16
/******************************************************************************
*
* GCM_START
@ -140,7 +135,6 @@ int gcm_start(gcm_context *ctx, // pointer to user-provided GCM context
const uchar *add, // pointer to additional AEAD data (NULL if none)
size_t add_len); // length of additional AEAD data (bytes)
/******************************************************************************
*
* GCM_UPDATE
@ -157,7 +151,6 @@ int gcm_update(gcm_context *ctx, // pointer to user-provided GCM context
const uchar *input, // pointer to source data
uchar *output); // pointer to destination data
/******************************************************************************
*
* GCM_FINISH
@ -170,7 +163,6 @@ int gcm_finish(gcm_context *ctx, // pointer to user-provided GCM context
uchar *tag, // ptr to tag buffer - NULL if tag_len = 0
size_t tag_len); // length, in bytes, of the tag-receiving buf
/******************************************************************************
*
* GCM_ZERO_CTX

View File

@ -98,12 +98,14 @@ int hkdfExtract(SHAversion whichSha,
uint8_t prk[USHAMaxHashSize])
{
unsigned char nullSalt[USHAMaxHashSize];
if (salt == 0) {
if (salt == 0)
{
salt = nullSalt;
salt_len = USHAHashSize(whichSha);
memset(nullSalt, '\0', salt_len);
}
else if (salt_len < 0) {
else if (salt_len < 0)
{
return shaBadParam;
}
return hmac(whichSha, ikm, ikm_len, salt, salt_len, prk);
@ -150,25 +152,33 @@ int hkdfExpand(SHAversion whichSha, const uint8_t prk[], size_t prk_len,
unsigned char T[USHAMaxHashSize];
size_t Tlen, where, i;
if (info == 0) {
if (info == 0)
{
info = (const unsigned char *)"";
info_len = 0;
}
else if (info_len < 0) {
else if (info_len < 0)
{
return shaBadParam;
}
if (okm_len <= 0) return shaBadParam;
if (!okm) return shaBadParam;
if (okm_len <= 0)
return shaBadParam;
if (!okm)
return shaBadParam;
hash_len = USHAHashSize(whichSha);
if (prk_len < hash_len) return shaBadParam;
if (prk_len < hash_len)
return shaBadParam;
N = okm_len / hash_len;
if ((okm_len % hash_len) != 0) N++;
if (N > 255) return shaBadParam;
if ((okm_len % hash_len) != 0)
N++;
if (N > 255)
return shaBadParam;
Tlen = 0;
where = 0;
for (i = 1; i <= N; i++) {
for (i = 1; i <= N; i++)
{
HMACContext context;
unsigned char c = i;
int ret = hmacReset(&context, whichSha, prk, prk_len) ||
@ -176,7 +186,8 @@ int hkdfExpand(SHAversion whichSha, const uint8_t prk[], size_t prk_len,
hmacInput(&context, info, info_len) ||
hmacInput(&context, &c, 1) ||
hmacResult(&context, T);
if (ret != shaSuccess) return ret;
if (ret != shaSuccess)
return ret;
memcpy(okm + where, T,
(i != N) ? hash_len : (okm_len - where));
where += hash_len;
@ -213,11 +224,13 @@ int hkdfReset(HKDFContext *context, enum SHAversion whichSha,
const unsigned char *salt, size_t salt_len)
{
unsigned char nullSalt[USHAMaxHashSize];
if (!context) return shaNull;
if (!context)
return shaNull;
context->whichSha = whichSha;
context->hashSize = USHAHashSize(whichSha);
if (salt == 0) {
if (salt == 0)
{
salt = nullSalt;
salt_len = context->hashSize;
memset(nullSalt, '\0', salt_len);
@ -249,9 +262,12 @@ int hkdfReset(HKDFContext *context, enum SHAversion whichSha,
int hkdfInput(HKDFContext *context, const unsigned char *ikm,
size_t ikm_len)
{
if (!context) return shaNull;
if (context->Corrupted) return context->Corrupted;
if (context->Computed) return context->Corrupted = shaStateError;
if (!context)
return shaNull;
if (context->Corrupted)
return context->Corrupted;
if (context->Computed)
return context->Corrupted = shaStateError;
return hmacInput(&context->hmacContext, ikm, ikm_len);
}
@ -278,9 +294,12 @@ int hkdfInput(HKDFContext *context, const unsigned char *ikm,
int hkdfFinalBits(HKDFContext *context, uint8_t ikm_bits,
unsigned int ikm_bit_count)
{
if (!context) return shaNull;
if (context->Corrupted) return context->Corrupted;
if (context->Computed) return context->Corrupted = shaStateError;
if (!context)
return shaNull;
if (context->Corrupted)
return context->Corrupted;
if (context->Computed)
return context->Corrupted = shaStateError;
return hmacFinalBits(&context->hmacContext, ikm_bits, ikm_bit_count);
}
@ -322,11 +341,16 @@ int hkdfResult(HKDFContext *context,
uint8_t prkbuf[USHAMaxHashSize];
int ret;
if (!context) return shaNull;
if (context->Corrupted) return context->Corrupted;
if (context->Computed) return context->Corrupted = shaStateError;
if (!okm) return context->Corrupted = shaBadParam;
if (!prk) prk = prkbuf;
if (!context)
return shaNull;
if (context->Corrupted)
return context->Corrupted;
if (context->Computed)
return context->Corrupted = shaStateError;
if (!okm)
return context->Corrupted = shaBadParam;
if (!prk)
prk = prkbuf;
ret = hmacResult(&context->hmacContext, prk) ||
hkdfExpand(context->whichSha, prk, context->hashSize, info,
@ -334,4 +358,3 @@ int hkdfResult(HKDFContext *context,
context->Computed = 1;
return context->Corrupted = ret;
}

View File

@ -87,7 +87,8 @@ int hmacReset(HMACContext *context, enum SHAversion whichSha,
/* temporary buffer when keylen > blocksize */
unsigned char tempkey[USHAMaxHashSize];
if (!context) return shaNull;
if (!context)
return shaNull;
context->Computed = 0;
context->Corrupted = shaSuccess;
@ -99,12 +100,14 @@ int hmacReset(HMACContext *context, enum SHAversion whichSha,
* If key is longer than the hash blocksize,
* reset it to key = HASH(key).
*/
if (key_len > blocksize) {
if (key_len > blocksize)
{
USHAContext tcontext;
int err = USHAReset(&tcontext, whichSha) ||
USHAInput(&tcontext, key, key_len) ||
USHAResult(&tcontext, tempkey);
if (err != shaSuccess) return err;
if (err != shaSuccess)
return err;
key = tempkey;
key_len = hashsize;
@ -122,12 +125,14 @@ int hmacReset(HMACContext *context, enum SHAversion whichSha,
*/
/* store key into the pads, XOR'd with ipad and opad values */
for (i = 0; i < key_len; i++) {
for (i = 0; i < key_len; i++)
{
k_ipad[i] = key[i] ^ 0x36;
context->k_opad[i] = key[i] ^ 0x5c;
}
/* remaining pad bytes are '\0' XOR'd with ipad and opad values */
for (; i < blocksize; i++) {
for (; i < blocksize; i++)
{
k_ipad[i] = 0x36;
context->k_opad[i] = 0x5c;
}
@ -163,9 +168,12 @@ int hmacReset(HMACContext *context, enum SHAversion whichSha,
int hmacInput(HMACContext *context, const unsigned char *text,
size_t text_len)
{
if (!context) return shaNull;
if (context->Corrupted) return context->Corrupted;
if (context->Computed) return context->Corrupted = shaStateError;
if (!context)
return shaNull;
if (context->Corrupted)
return context->Corrupted;
if (context->Computed)
return context->Corrupted = shaStateError;
/* then text of datagram */
return context->Corrupted =
USHAInput(&context->shaContext, text, text_len);
@ -193,9 +201,12 @@ int hmacInput(HMACContext *context, const unsigned char *text,
int hmacFinalBits(HMACContext *context,
uint8_t bits, unsigned int bit_count)
{
if (!context) return shaNull;
if (context->Corrupted) return context->Corrupted;
if (context->Computed) return context->Corrupted = shaStateError;
if (!context)
return shaNull;
if (context->Corrupted)
return context->Corrupted;
if (context->Computed)
return context->Corrupted = shaStateError;
/* then final bits of datagram */
return context->Corrupted =
USHAFinalBits(&context->shaContext, bits, bit_count);
@ -223,9 +234,12 @@ int hmacFinalBits(HMACContext *context,
int hmacResult(HMACContext *context, uint8_t *digest)
{
int ret;
if (!context) return shaNull;
if (context->Corrupted) return context->Corrupted;
if (context->Computed) return context->Corrupted = shaStateError;
if (!context)
return shaNull;
if (context->Corrupted)
return context->Corrupted;
if (context->Computed)
return context->Corrupted = shaStateError;
/* finish up 1st pass */
/* (Use digest here as a temporary buffer.) */

View File

@ -85,7 +85,8 @@
/*
* All SHA functions return one of these values.
*/
enum {
enum
{
shaSuccess = 0,
shaNull, /* Null pointer parameter */
shaInputTooLong, /* input data too long */
@ -98,30 +99,39 @@ enum {
* These constants hold size information for each of the SHA
* hashing operations
*/
enum {
SHA1_Message_Block_Size = 64, SHA224_Message_Block_Size = 64,
enum
{
SHA1_Message_Block_Size = 64,
SHA224_Message_Block_Size = 64,
SHA256_Message_Block_Size = 64,
USHA_Max_Message_Block_Size = SHA256_Message_Block_Size,
SHA1HashSize = 20, SHA224HashSize = 28, SHA256HashSize = 32,
SHA1HashSize = 20,
SHA224HashSize = 28,
SHA256HashSize = 32,
USHAMaxHashSize = SHA256HashSize,
SHA1HashSizeBits = 160, SHA224HashSizeBits = 224,
SHA256HashSizeBits = 256, USHAMaxHashSizeBits = SHA256HashSizeBits
SHA1HashSizeBits = 160,
SHA224HashSizeBits = 224,
SHA256HashSizeBits = 256,
USHAMaxHashSizeBits = SHA256HashSizeBits
};
/*
* These constants are used in the USHA (Unified SHA) functions.
*/
typedef enum SHAversion {
SHA224, SHA256
typedef enum SHAversion
{
SHA224,
SHA256
} SHAversion;
/*
* This structure will hold context information for the SHA-256
* hashing operation.
*/
typedef struct SHA256Context {
typedef struct SHA256Context
{
uint32_t Intermediate_Hash[SHA256HashSize / 4]; /* Message Digest */
uint32_t Length_High; /* Message length in bits */
@ -145,10 +155,13 @@ typedef struct SHA256Context SHA224Context;
* This structure holds context information for all SHA
* hashing operations.
*/
typedef struct USHAContext {
typedef struct USHAContext
{
int whichSha; /* which SHA is being used */
union {
SHA224Context sha224Context; SHA256Context sha256Context;
union
{
SHA224Context sha224Context;
SHA256Context sha256Context;
} ctx;
} USHAContext;
@ -157,7 +170,8 @@ typedef struct USHAContext {
* This structure will hold context information for the HMAC
* keyed-hashing operation.
*/
typedef struct HMACContext {
typedef struct HMACContext
{
int whichSha; /* which SHA is being used */
int hashSize; /* hash size of SHA being used */
int blockSize; /* block size of SHA being used */
@ -173,7 +187,8 @@ typedef struct HMACContext {
* This structure will hold context information for the HKDF
* extract-and-expand Key Derivation Functions.
*/
typedef struct HKDFContext {
typedef struct HKDFContext
{
int whichSha; /* which SHA is being used */
HMACContext hmacContext;
int hashSize; /* hash size of SHA being used */
@ -187,7 +202,6 @@ typedef struct HKDFContext {
* Function Prototypes
*/
/* SHA-224 */
int SHA224Reset(SHA224Context *);
int SHA224Input(SHA224Context *, const uint8_t *bytes,
@ -243,7 +257,6 @@ int hmacFinalBits(HMACContext *context, uint8_t bits,
int hmacResult(HMACContext *context,
uint8_t digest[USHAMaxHashSize]);
/*
* HKDF HMAC-based Extract-and-Expand Key Derivation Function,
* RFC 5869, for all SHAs.

View File

@ -68,8 +68,9 @@ static uint32_t addTemp;
#define SHA224_256AddLength(context, length) \
(addTemp = (context)->Length_Low, (context)->Corrupted = \
(((context)->Length_Low += (length)) < addTemp) && \
(++(context)->Length_High == 0) ? shaInputTooLong : \
(context)->Corrupted )
(++(context)->Length_High == 0) \
? shaInputTooLong \
: (context)->Corrupted)
/* Local Function Prototypes */
static int SHA224_256Reset(SHA256Context *context, uint32_t *H0);
@ -84,14 +85,12 @@ static int SHA224_256ResultN(SHA256Context *context,
/* Initial Hash Values: FIPS 180-3 section 5.3.2 */
static uint32_t SHA224_H0[SHA256HashSize / 4] = {
0xC1059ED8, 0x367CD507, 0x3070DD17, 0xF70E5939,
0xFFC00B31, 0x68581511, 0x64F98FA7, 0xBEFA4FA4
};
0xFFC00B31, 0x68581511, 0x64F98FA7, 0xBEFA4FA4};
/* Initial Hash Values: FIPS 180-3 section 5.3.3 */
static uint32_t SHA256_H0[SHA256HashSize / 4] = {
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
};
0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19};
/*
* SHA224Reset
@ -229,13 +228,19 @@ int SHA256Reset(SHA256Context *context)
int SHA256Input(SHA256Context *context, const uint8_t *message_array,
unsigned int length)
{
if (!context) return shaNull;
if (!length) return shaSuccess;
if (!message_array) return shaNull;
if (context->Computed) return context->Corrupted = shaStateError;
if (context->Corrupted) return context->Corrupted;
if (!context)
return shaNull;
if (!length)
return shaSuccess;
if (!message_array)
return shaNull;
if (context->Computed)
return context->Corrupted = shaStateError;
if (context->Corrupted)
return context->Corrupted;
while (length--) {
while (length--)
{
context->Message_Block[context->Message_Block_Index++] =
*message_array;
@ -247,7 +252,6 @@ int SHA256Input(SHA256Context *context, const uint8_t *message_array,
}
return context->Corrupted;
}
/*
@ -276,24 +280,26 @@ int SHA256FinalBits(SHA256Context *context,
/* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80,
/* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0,
/* 4 0b11110000 */ 0xF0, /* 5 0b11111000 */ 0xF8,
/* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE
};
/* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE};
static uint8_t markbit[8] = {
/* 0 0b10000000 */ 0x80, /* 1 0b01000000 */ 0x40,
/* 2 0b00100000 */ 0x20, /* 3 0b00010000 */ 0x10,
/* 4 0b00001000 */ 0x08, /* 5 0b00000100 */ 0x04,
/* 6 0b00000010 */ 0x02, /* 7 0b00000001 */ 0x01
};
/* 6 0b00000010 */ 0x02, /* 7 0b00000001 */ 0x01};
if (!context) return shaNull;
if (!length) return shaSuccess;
if (context->Corrupted) return context->Corrupted;
if (context->Computed) return context->Corrupted = shaStateError;
if (length >= 8) return context->Corrupted = shaBadParam;
if (!context)
return shaNull;
if (!length)
return shaSuccess;
if (context->Corrupted)
return context->Corrupted;
if (context->Computed)
return context->Corrupted = shaStateError;
if (length >= 8)
return context->Corrupted = shaBadParam;
SHA224_256AddLength(context, length);
SHA224_256Finalize(context, (uint8_t)
((message_bits & masks[length]) | markbit[length]));
SHA224_256Finalize(context, (uint8_t)((message_bits & masks[length]) | markbit[length]));
return context->Corrupted;
}
@ -341,7 +347,8 @@ int SHA256Result(SHA256Context *context,
*/
static int SHA224_256Reset(SHA256Context *context, uint32_t *H0)
{
if (!context) return shaNull;
if (!context)
return shaNull;
context->Length_High = context->Length_Low = 0;
context->Message_Block_Index = 0;
@ -396,8 +403,7 @@ static void SHA224_256ProcessMessageBlock(SHA256Context *context)
0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08,
0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f,
0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
int t, t4; /* Loop counter */
uint32_t temp1, temp2; /* Temporary word value */
uint32_t W[64]; /* Word sequence */
@ -424,7 +430,8 @@ static void SHA224_256ProcessMessageBlock(SHA256Context *context)
G = context->Intermediate_Hash[6];
H = context->Intermediate_Hash[7];
for (t = 0; t < 64; t++) {
for (t = 0; t < 64; t++)
{
temp1 = H + SHA256_SIGMA1(E) + SHA_Ch(E, F, G) + K[t] + W[t];
temp2 = SHA256_SIGMA0(A) + SHA_Maj(A, B, C);
H = G;
@ -513,12 +520,14 @@ static void SHA224_256PadMessage(SHA256Context *context,
* block, process it, and then continue padding into a second
* block.
*/
if (context->Message_Block_Index >= (SHA256_Message_Block_Size-8)) {
if (context->Message_Block_Index >= (SHA256_Message_Block_Size - 8))
{
context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
while (context->Message_Block_Index < SHA256_Message_Block_Size)
context->Message_Block[context->Message_Block_Index++] = 0;
SHA224_256ProcessMessageBlock(context);
} else
}
else
context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
while (context->Message_Block_Index < (SHA256_Message_Block_Size - 8))
@ -565,17 +574,18 @@ static int SHA224_256ResultN(SHA256Context *context,
{
int i;
if (!context) return shaNull;
if (!Message_Digest) return shaNull;
if (context->Corrupted) return context->Corrupted;
if (!context)
return shaNull;
if (!Message_Digest)
return shaNull;
if (context->Corrupted)
return context->Corrupted;
if (!context->Computed)
SHA224_256Finalize(context, 0x80);
for (i = 0; i < HashSize; ++i)
Message_Digest[i] = (uint8_t)
(context->Intermediate_Hash[i>>2] >> 8 * ( 3 - ( i & 0x03 ) ));
Message_Digest[i] = (uint8_t)(context->Intermediate_Hash[i >> 2] >> 8 * (3 - (i & 0x03)));
return shaSuccess;
}

View File

@ -30,12 +30,17 @@
*/
int USHAReset(USHAContext *context, enum SHAversion whichSha)
{
if (!context) return shaNull;
if (!context)
return shaNull;
context->whichSha = whichSha;
switch (whichSha) {
case SHA224: return SHA224Reset((SHA224Context*)&context->ctx);
case SHA256: return SHA256Reset((SHA256Context*)&context->ctx);
default: return shaBadParam;
switch (whichSha)
{
case SHA224:
return SHA224Reset((SHA224Context *)&context->ctx);
case SHA256:
return SHA256Reset((SHA256Context *)&context->ctx);
default:
return shaBadParam;
}
}
@ -62,15 +67,18 @@ int USHAReset(USHAContext *context, enum SHAversion whichSha)
int USHAInput(USHAContext *context,
const uint8_t *bytes, unsigned int bytecount)
{
if (!context) return shaNull;
switch (context->whichSha) {
if (!context)
return shaNull;
switch (context->whichSha)
{
case SHA224:
return SHA224Input((SHA224Context *)&context->ctx, bytes,
bytecount);
case SHA256:
return SHA256Input((SHA256Context *)&context->ctx, bytes,
bytecount);
default: return shaBadParam;
default:
return shaBadParam;
}
}
@ -96,15 +104,18 @@ int USHAInput(USHAContext *context,
int USHAFinalBits(USHAContext *context,
uint8_t bits, unsigned int bit_count)
{
if (!context) return shaNull;
switch (context->whichSha) {
if (!context)
return shaNull;
switch (context->whichSha)
{
case SHA224:
return SHA224FinalBits((SHA224Context *)&context->ctx, bits,
bit_count);
case SHA256:
return SHA256FinalBits((SHA256Context *)&context->ctx, bits,
bit_count);
default: return shaBadParam;
default:
return shaBadParam;
}
}
@ -130,15 +141,18 @@ int USHAFinalBits(USHAContext *context,
int USHAResult(USHAContext *context,
uint8_t Message_Digest[USHAMaxHashSize])
{
if (!context) return shaNull;
switch (context->whichSha) {
if (!context)
return shaNull;
switch (context->whichSha)
{
case SHA224:
return SHA224Result((SHA224Context *)&context->ctx,
Message_Digest);
case SHA256:
return SHA256Result((SHA256Context *)&context->ctx,
Message_Digest);
default: return shaBadParam;
default:
return shaBadParam;
}
}
@ -159,10 +173,13 @@ int USHAResult(USHAContext *context,
*/
int USHABlockSize(enum SHAversion whichSha)
{
switch (whichSha) {
case SHA224: return SHA224_Message_Block_Size;
switch (whichSha)
{
case SHA224:
return SHA224_Message_Block_Size;
default:
case SHA256: return SHA256_Message_Block_Size;
case SHA256:
return SHA256_Message_Block_Size;
}
}
@ -183,9 +200,12 @@ int USHABlockSize(enum SHAversion whichSha)
*/
int USHAHashSize(enum SHAversion whichSha)
{
switch (whichSha) {
case SHA224: return SHA224HashSize;
switch (whichSha)
{
case SHA224:
return SHA224HashSize;
default:
case SHA256: return SHA256HashSize;
case SHA256:
return SHA256HashSize;
}
}

View File

@ -65,7 +65,8 @@ uint32_t *tcp_find_timestamps(struct tcphdr *tcp)
uint8_t tcp_find_scale_factor(const struct tcphdr *tcp)
{
uint8_t *scale = tcp_find_option((struct tcphdr *)tcp, 3); // tcp option 3 - scale factor
if (scale && scale[1]==3) return scale[2];
if (scale && scale[1] == 3)
return scale[2];
return SCALE_NONE;
}
bool tcp_has_fastopen(const struct tcphdr *tcp)
@ -73,7 +74,8 @@ bool tcp_has_fastopen(const struct tcphdr *tcp)
uint8_t *opt;
// new style RFC7413
opt = tcp_find_option((struct tcphdr *)tcp, 34);
if (opt) return true;
if (opt)
return true;
// old style RFC6994
opt = tcp_find_option((struct tcphdr *)tcp, 254);
return opt && opt[1] >= 4 && opt[2] == 0xF9 && opt[3] == 0x89;
@ -136,16 +138,20 @@ static void fill_tcphdr(
tcpopt[t++] = 3;
tcpopt[t++] = scale_factor;
}
while (t&3) tcpopt[t++]=1; // noop
while (t & 3)
tcpopt[t++] = 1; // noop
tcp->th_off += t >> 2;
tcp->th_sum = 0;
}
static uint16_t tcpopt_len(uint32_t fooling, const uint32_t *timestamps, uint8_t scale_factor)
{
uint16_t t = 0;
if (fooling & FOOL_MD5SIG) t=18;
if ((fooling & FOOL_TS) || timestamps) t+=10;
if (scale_factor!=SCALE_NONE) t+=3;
if (fooling & FOOL_MD5SIG)
t = 18;
if ((fooling & FOOL_TS) || timestamps)
t += 10;
if (scale_factor != SCALE_NONE)
t += 3;
return (t + 3) & ~3;
}
@ -199,7 +205,8 @@ bool prepare_tcp_segment4(
uint16_t tcpoptlen = tcpopt_len(fooling, timestamps, scale_factor);
uint16_t ip_payload_len = sizeof(struct tcphdr) + tcpoptlen + len;
uint16_t pktlen = sizeof(struct ip) + ip_payload_len;
if (pktlen>*buflen) return false;
if (pktlen > *buflen)
return false;
struct ip *ip = (struct ip *)buf;
struct tcphdr *tcp = (struct tcphdr *)(ip + 1);
@ -210,7 +217,8 @@ bool prepare_tcp_segment4(
memcpy(payload, data, len);
tcp4_fix_checksum(tcp, ip_payload_len, &ip->ip_src, &ip->ip_dst);
if (fooling & FOOL_BADSUM) tcp->th_sum^=htons(0xBEAF);
if (fooling & FOOL_BADSUM)
tcp->th_sum ^= htons(0xBEAF);
*buflen = pktlen;
return true;
@ -238,7 +246,8 @@ bool prepare_tcp_segment6(
8 * !!(fooling & FOOL_DESTOPT) +
8 * !!(fooling & FOOL_IPFRAG1);
uint16_t pktlen = sizeof(struct ip6_hdr) + ip_payload_len;
if (pktlen>*buflen) return false;
if (pktlen > *buflen)
return false;
struct ip6_hdr *ip6 = (struct ip6_hdr *)buf;
struct tcphdr *tcp = (struct tcphdr *)(ip6 + 1);
@ -293,7 +302,8 @@ bool prepare_tcp_segment6(
memcpy(payload, data, len);
tcp6_fix_checksum(tcp, transport_payload_len, &ip6->ip6_src, &ip6->ip6_dst);
if (fooling & FOOL_BADSUM) tcp->th_sum^=htons(0xBEAF);
if (fooling & FOOL_BADSUM)
tcp->th_sum ^= htons(0xBEAF);
*buflen = pktlen;
return true;
@ -313,14 +323,10 @@ bool prepare_tcp_segment(
const void *data, uint16_t len,
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,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,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,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
false;
return (src->sa_family == AF_INET && dst->sa_family == AF_INET) ? prepare_tcp_segment4((struct sockaddr_in *)src, (struct sockaddr_in *)dst, tcp_flags, nseq, nack_seq, nwsize, scale_factor, timestamps, ttl, 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, nseq, nack_seq, nwsize, scale_factor, timestamps, ttl, fooling, badseq_increment, badseq_ack_increment, data, len, buf, buflen)
: false;
}
// padlen<0 means payload shrinking
bool prepare_udp_segment4(
const struct sockaddr_in *src, const struct sockaddr_in *dst,
@ -331,8 +337,10 @@ bool prepare_udp_segment4(
const void *data, uint16_t len,
uint8_t *buf, size_t *buflen)
{
if ((len+padlen)<=0) padlen=-(int)len+1; // do not allow payload to be less that 1 byte
if ((len+padlen)>0xFFFF) padlen=0xFFFF-len; // do not allow payload size to exceed u16 range
if ((len + padlen) <= 0)
padlen = -(int)len + 1; // do not allow payload to be less that 1 byte
if ((len + padlen) > 0xFFFF)
padlen = 0xFFFF - len; // do not allow payload size to exceed u16 range
if (padlen < 0)
{
len += padlen;
@ -341,13 +349,13 @@ bool prepare_udp_segment4(
uint16_t datalen = (uint16_t)(len + padlen);
uint16_t ip_payload_len = sizeof(struct udphdr) + datalen;
uint16_t pktlen = sizeof(struct ip) + ip_payload_len;
if (pktlen>*buflen) return false;
if (pktlen > *buflen)
return false;
struct ip *ip = (struct ip *)buf;
struct udphdr *udp = (struct udphdr *)(ip + 1);
uint8_t *payload = (uint8_t *)(udp + 1);
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_UDP, ttl);
fill_udphdr(udp, src->sin_port, dst->sin_port, datalen);
@ -357,7 +365,8 @@ bool prepare_udp_segment4(
else
memset(payload + len, 0, padlen);
udp4_fix_checksum(udp, ip_payload_len, &ip->ip_src, &ip->ip_dst);
if (fooling & FOOL_BADSUM) udp->uh_sum^=htons(0xBEAF);
if (fooling & FOOL_BADSUM)
udp->uh_sum ^= htons(0xBEAF);
*buflen = pktlen;
return true;
@ -371,8 +380,10 @@ bool prepare_udp_segment6(
const void *data, uint16_t len,
uint8_t *buf, size_t *buflen)
{
if ((len+padlen)<=0) padlen=-(int)len+1; // do not allow payload to be less that 1 byte
if ((len+padlen)>0xFFFF) padlen=0xFFFF-len; // do not allow payload size to exceed u16 range
if ((len + padlen) <= 0)
padlen = -(int)len + 1; // do not allow payload to be less that 1 byte
if ((len + padlen) > 0xFFFF)
padlen = 0xFFFF - len; // do not allow payload size to exceed u16 range
if (padlen < 0)
{
len += padlen;
@ -386,7 +397,8 @@ bool prepare_udp_segment6(
8 * !!(fooling & FOOL_DESTOPT) +
8 * !!(fooling & FOOL_IPFRAG1);
uint16_t pktlen = sizeof(struct ip6_hdr) + ip_payload_len;
if (pktlen>*buflen) return false;
if (pktlen > *buflen)
return false;
struct ip6_hdr *ip6 = (struct ip6_hdr *)buf;
struct udphdr *udp = (struct udphdr *)(ip6 + 1);
@ -445,7 +457,8 @@ bool prepare_udp_segment6(
else
memset(payload + len, 0, padlen);
udp6_fix_checksum(udp, transport_payload_len, &ip6->ip6_src, &ip6->ip6_dst);
if (fooling & FOOL_BADSUM) udp->uh_sum^=htons(0xBEAF);
if (fooling & FOOL_BADSUM)
udp->uh_sum ^= htons(0xBEAF);
*buflen = pktlen;
return true;
@ -459,11 +472,8 @@ bool prepare_udp_segment(
const void *data, uint16_t len,
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,ttl,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,fooling,padding,padding_size,padlen,data,len,buf,buflen) :
false;
return (src->sa_family == AF_INET && dst->sa_family == AF_INET) ? prepare_udp_segment4((struct sockaddr_in *)src, (struct sockaddr_in *)dst, ttl, 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, fooling, padding, padding_size, padlen, data, len, buf, buflen)
: false;
}
bool ip6_insert_simple_hdr(uint8_t type, uint8_t *data_pkt, size_t len_pkt, uint8_t *buf, size_t *buflen)
@ -493,17 +503,21 @@ bool ip_frag4(
{
uint16_t hdrlen, payload_len;
// frag_pos must be 8-byte aligned
if (frag_pos & 7 || pkt_size < sizeof(struct ip)) return false;
if (frag_pos & 7 || pkt_size < sizeof(struct ip))
return false;
payload_len = htons(((struct ip *)pkt)->ip_len);
hdrlen = ((struct ip *)pkt)->ip_hl << 2;
if (payload_len>pkt_size || hdrlen>pkt_size || hdrlen>payload_len) return false;
if (payload_len > pkt_size || hdrlen > pkt_size || hdrlen > payload_len)
return false;
payload_len -= hdrlen;
if (frag_pos>=payload_len || *pkt1_size<(hdrlen+frag_pos) || *pkt2_size<(hdrlen+payload_len-frag_pos)) return false;
if (frag_pos >= payload_len || *pkt1_size < (hdrlen + frag_pos) || *pkt2_size < (hdrlen + payload_len - frag_pos))
return false;
memcpy(pkt1, pkt, hdrlen + frag_pos);
((struct ip *)pkt1)->ip_off = htons(IP_MF);
((struct ip *)pkt1)->ip_len = htons(hdrlen + frag_pos);
if (ident!=(uint32_t)-1) ((struct ip*)pkt1)->ip_id = (uint16_t)ident;
if (ident != (uint32_t)-1)
((struct ip *)pkt1)->ip_id = (uint16_t)ident;
*pkt1_size = hdrlen + frag_pos;
ip4_fix_checksum((struct ip *)pkt1);
@ -511,7 +525,8 @@ bool ip_frag4(
memcpy(pkt2 + hdrlen, pkt + hdrlen + frag_pos, payload_len - frag_pos);
((struct ip *)pkt2)->ip_off = htons((uint16_t)frag_pos >> 3 & IP_OFFMASK);
((struct ip *)pkt2)->ip_len = htons(hdrlen + payload_len - frag_pos);
if (ident!=(uint32_t)-1) ((struct ip*)pkt2)->ip_id = (uint16_t)ident;
if (ident != (uint32_t)-1)
((struct ip *)pkt2)->ip_id = (uint16_t)ident;
*pkt2_size = hdrlen + payload_len - frag_pos;
ip4_fix_checksum((struct ip *)pkt2);
@ -529,9 +544,11 @@ bool ip_frag6(
struct ip6_frag *frag;
const uint8_t *payload;
if (frag_pos & 7 || pkt_size < sizeof(struct ip6_hdr)) return false;
if (frag_pos & 7 || pkt_size < sizeof(struct ip6_hdr))
return false;
payload_len = sizeof(struct ip6_hdr) + htons(((struct ip6_hdr *)pkt)->ip6_ctlun.ip6_un1.ip6_un1_plen);
if (pkt_size < payload_len) return false;
if (pkt_size < payload_len)
return false;
payload = pkt;
proto_skip_ipv6((uint8_t **)&payload, &payload_len, &proto, &last_header_type);
@ -586,16 +603,23 @@ bool ip_frag(
void rewrite_ttl(struct ip *ip, struct ip6_hdr *ip6, uint8_t ttl)
{
if (ip) ip->ip_ttl = ttl;
if (ip6) ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim = ttl;
if (ip)
ip->ip_ttl = ttl;
if (ip6)
ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim = ttl;
}
void extract_ports(const struct tcphdr *tcphdr, const struct udphdr *udphdr, uint8_t *proto, uint16_t *sport, uint16_t *dport)
{
if (sport) *sport = htons(tcphdr ? tcphdr->th_sport : udphdr ? udphdr->uh_sport : 0);
if (dport) *dport = htons(tcphdr ? tcphdr->th_dport : udphdr ? udphdr->uh_dport : 0);
if (proto) *proto = tcphdr ? IPPROTO_TCP : udphdr ? IPPROTO_UDP : -1;
if (sport)
*sport = htons(tcphdr ? tcphdr->th_sport : udphdr ? udphdr->uh_sport
: 0);
if (dport)
*dport = htons(tcphdr ? tcphdr->th_dport : udphdr ? udphdr->uh_dport
: 0);
if (proto)
*proto = tcphdr ? IPPROTO_TCP : udphdr ? IPPROTO_UDP
: -1;
}
void extract_endpoints(const struct ip *ip, const struct ip6_hdr *ip6hdr, const struct tcphdr *tcphdr, const struct udphdr *udphdr, struct sockaddr_storage *src, struct sockaddr_storage *dst)
@ -608,7 +632,8 @@ void extract_endpoints(const struct ip *ip,const struct ip6_hdr *ip6hdr,const st
{
si = (struct sockaddr_in *)dst;
si->sin_family = AF_INET;
si->sin_port = tcphdr ? tcphdr->th_dport : udphdr ? udphdr->uh_dport : 0;
si->sin_port = tcphdr ? tcphdr->th_dport : udphdr ? udphdr->uh_dport
: 0;
si->sin_addr = ip->ip_dst;
}
@ -616,7 +641,8 @@ void extract_endpoints(const struct ip *ip,const struct ip6_hdr *ip6hdr,const st
{
si = (struct sockaddr_in *)src;
si->sin_family = AF_INET;
si->sin_port = tcphdr ? tcphdr->th_sport : udphdr ? udphdr->uh_sport : 0;
si->sin_port = tcphdr ? tcphdr->th_sport : udphdr ? udphdr->uh_sport
: 0;
si->sin_addr = ip->ip_src;
}
}
@ -628,7 +654,8 @@ void extract_endpoints(const struct ip *ip,const struct ip6_hdr *ip6hdr,const st
{
si = (struct sockaddr_in6 *)dst;
si->sin6_family = AF_INET6;
si->sin6_port = tcphdr ? tcphdr->th_dport : udphdr ? udphdr->uh_dport : 0;
si->sin6_port = tcphdr ? tcphdr->th_dport : udphdr ? udphdr->uh_dport
: 0;
si->sin6_addr = ip6hdr->ip6_dst;
si->sin6_flowinfo = 0;
si->sin6_scope_id = 0;
@ -638,7 +665,8 @@ void extract_endpoints(const struct ip *ip,const struct ip6_hdr *ip6hdr,const st
{
si = (struct sockaddr_in6 *)src;
si->sin6_family = AF_INET6;
si->sin6_port = tcphdr ? tcphdr->th_sport : udphdr ? udphdr->uh_sport : 0;
si->sin6_port = tcphdr ? tcphdr->th_sport : udphdr ? udphdr->uh_sport
: 0;
si->sin6_addr = ip6hdr->ip6_src;
si->sin6_flowinfo = 0;
si->sin6_scope_id = 0;
@ -692,9 +720,12 @@ uint16_t family_from_proto(uint8_t l3proto)
{
switch (l3proto)
{
case IPPROTO_IP: return AF_INET;
case IPPROTO_IPV6: return AF_INET6;
default: return -1;
case IPPROTO_IP:
return AF_INET;
case IPPROTO_IPV6:
return AF_INET6;
default:
return -1;
}
}
@ -743,12 +774,18 @@ void print_ip6hdr(const struct ip6_hdr *ip6hdr, uint8_t proto)
void str_tcphdr(char *s, size_t s_len, const struct tcphdr *tcphdr)
{
char flags[7], *f = flags;
if (tcphdr->th_flags & TH_SYN) *f++='S';
if (tcphdr->th_flags & TH_ACK) *f++='A';
if (tcphdr->th_flags & TH_RST) *f++='R';
if (tcphdr->th_flags & TH_FIN) *f++='F';
if (tcphdr->th_flags & TH_PUSH) *f++='P';
if (tcphdr->th_flags & TH_URG) *f++='U';
if (tcphdr->th_flags & TH_SYN)
*f++ = 'S';
if (tcphdr->th_flags & TH_ACK)
*f++ = 'A';
if (tcphdr->th_flags & TH_RST)
*f++ = 'R';
if (tcphdr->th_flags & TH_FIN)
*f++ = 'F';
if (tcphdr->th_flags & TH_PUSH)
*f++ = 'P';
if (tcphdr->th_flags & TH_URG)
*f++ = 'U';
*f = 0;
snprintf(s, s_len, "sport=%u dport=%u flags=%s seq=%u ack_seq=%u", htons(tcphdr->th_sport), htons(tcphdr->th_dport), flags, htonl(tcphdr->th_seq), htonl(tcphdr->th_ack));
}
@ -769,9 +806,6 @@ void print_udphdr(const struct udphdr *udphdr)
printf("%s", s);
}
bool proto_check_ipv4(const uint8_t *data, size_t len)
{
return len >= 20 && (data[0] & 0xF0) == 0x40 &&
@ -819,11 +853,14 @@ void proto_skip_ipv6(uint8_t **data, size_t *len, uint8_t *proto_type, uint8_t *
size_t hdrlen;
uint8_t HeaderType;
if (proto_type) *proto_type = 0; // put error in advance
if (proto_type)
*proto_type = 0; // put error in advance
HeaderType = (*data)[6]; // NextHeader field
if (last_header_type) *last_header_type = (*data)+6;
*data += 40; *len -= 40; // skip ipv6 base header
if (last_header_type)
*last_header_type = (*data) + 6;
*data += 40;
*len -= 40; // skip IPv6 base header
while (*len > 0) // need at least one byte for NextHeader field
{
switch (HeaderType)
@ -835,7 +872,8 @@ void proto_skip_ipv6(uint8_t **data, size_t *len, uint8_t *proto_type, uint8_t *
case 135: // mobility
case 139: // Host Identity Protocol Version v2
case 140: // Shim6
if (*len < 2) return; // error
if (*len < 2)
return; // error
hdrlen = 8 + ((*data)[1] << 3);
break;
case 44: // fragment. length fixed to 8, hdrlen field defined as reserved
@ -844,13 +882,16 @@ void proto_skip_ipv6(uint8_t **data, size_t *len, uint8_t *proto_type, uint8_t *
case 59: // no next header
return; // error
default:
// we found some meaningful payload. it can be tcp, udp, icmp or some another exotic shit
if (proto_type) *proto_type = HeaderType;
// we found some meaningful payload. it can be TCP, UDP, ICMP or some another exotic shit
if (proto_type)
*proto_type = HeaderType;
return;
}
if (*len < hdrlen) return; // error
if (*len < hdrlen)
return; // error
HeaderType = **data;
if (last_header_type) *last_header_type = *data;
if (last_header_type)
*last_header_type = *data;
// advance to the next header location
*len -= hdrlen;
*data += hdrlen;
@ -901,7 +942,6 @@ void proto_dissect_l3l4(
*data_payload = data;
*len_payload = len;
}
else if (*proto == IPPROTO_UDP && proto_check_udp(data, len))
{
@ -915,7 +955,6 @@ void proto_dissect_l3l4(
}
}
bool tcp_synack_segment(const struct tcphdr *tcphdr)
{
/* check for set bits in TCP hdr */
@ -965,7 +1004,6 @@ void tcp_rewrite_winsize(struct tcphdr *tcp, uint16_t winsize, uint8_t scale_fac
tcp_rewrite_wscale(tcp, scale_factor);
}
#ifdef __CYGWIN__
static HANDLE w_filter = NULL;
@ -986,12 +1024,14 @@ static bool str2guid(const char* str, GUID *guid)
if (36 != strlen(str) || 11 != sscanf(str, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", u + 0, u + 1, u + 2, u + 3, u + 4, u + 5, u + 6, u + 7, u + 8, u + 9, u + 10))
return false;
guid->Data1 = u[0];
if ((u[1] & 0xFFFF0000) || (u[2] & 0xFFFF0000)) return false;
if ((u[1] & 0xFFFF0000) || (u[2] & 0xFFFF0000))
return false;
guid->Data2 = (USHORT)u[1];
guid->Data3 = (USHORT)u[2];
for (k = 0; k < 8; k++)
{
if (u[k+3] & 0xFFFFFF00) return false;
if (u[k + 3] & 0xFFFFFF00)
return false;
guid->Data4[k] = (UCHAR)u[k + 3];
}
return true;
@ -1008,7 +1048,8 @@ static bool AdapterID2Name(const GUID *guid,char *name,DWORD name_len)
WCHAR namew[128];
DWORD namew_len;
if (name_len<2) return false;
if (name_len < 2)
return false;
if ((w_win32_error = RegOpenKeyExA(HKEY_LOCAL_MACHINE, sNetworkCards, 0, KEY_ENUMERATE_SUB_KEYS, &hkNetworkCards)) == ERROR_SUCCESS)
{
@ -1044,7 +1085,8 @@ static bool AdapterID2Name(const GUID *guid,char *name,DWORD name_len)
}
RegCloseKey(hkCard);
}
if (bRet) break;
if (bRet)
break;
}
else
break;
@ -1058,8 +1100,10 @@ static bool AdapterID2Name(const GUID *guid,char *name,DWORD name_len)
bool win_dark_init(const struct str_list_head *ssid_filter, const struct str_list_head *nlm_filter)
{
win_dark_deinit();
if (LIST_EMPTY(ssid_filter)) ssid_filter=NULL;
if (LIST_EMPTY(nlm_filter)) nlm_filter=NULL;
if (LIST_EMPTY(ssid_filter))
ssid_filter = NULL;
if (LIST_EMPTY(nlm_filter))
nlm_filter = NULL;
if (nlm_filter)
{
if (SUCCEEDED(w_win32_error = CoInitialize(NULL)))
@ -1084,11 +1128,11 @@ bool win_dark_deinit(void)
pNetworkListManager->lpVtbl->Release(pNetworkListManager);
pNetworkListManager = NULL;
}
if (nlm_filter_net) CoUninitialize();
if (nlm_filter_net)
CoUninitialize();
wlan_filter_ssid = nlm_filter_net = NULL;
}
bool nlm_list(bool bAll)
{
bool bRet = true;
@ -1119,7 +1163,8 @@ bool nlm_list(bool bAll)
bRet = false;
break;
}
if (w_win32_error != S_OK) break;
if (w_win32_error != S_OK)
break;
if (SUCCEEDED(w_win32_error = pNet->lpVtbl->get_IsConnected(pNet, &bIsConnected)) &&
SUCCEEDED(w_win32_error = pNet->lpVtbl->get_IsConnectedToInternet(pNet, &bIsConnectedInet)) &&
SUCCEEDED(w_win32_error = pNet->lpVtbl->GetNetworkId(pNet, &idNet)) &&
@ -1131,13 +1176,14 @@ bool nlm_list(bool bAll)
if (WideCharToMultiByte(CP_UTF8, 0, bstrName, -1, Name, sizeof(Name), NULL, NULL))
{
printf("Name : %s", Name);
if (bIsConnected) printf(" (connected)");
if (bIsConnectedInet) printf(" (inet)");
if (bIsConnected)
printf(" (connected)");
if (bIsConnectedInet)
printf(" (inet)");
printf(" (%s)\n",
category==NLM_NETWORK_CATEGORY_PUBLIC ? "public" :
category==NLM_NETWORK_CATEGORY_PRIVATE ? "private" :
category==NLM_NETWORK_CATEGORY_DOMAIN_AUTHENTICATED ? "domain" :
"unknown");
category == NLM_NETWORK_CATEGORY_PUBLIC ? "public" : category == NLM_NETWORK_CATEGORY_PRIVATE ? "private"
: category == NLM_NETWORK_CATEGORY_DOMAIN_AUTHENTICATED ? "domain"
: "unknown");
guid2str(&idNet, Name);
printf("NetID : %s\n", Name);
if (connected && SUCCEEDED(w_win32_error = pNet->lpVtbl->GetNetworkConnections(pNet, &pEnumConnections)))
@ -1169,9 +1215,11 @@ bool nlm_list(bool bAll)
else
bRet = false;
pNet->lpVtbl->Release(pNet);
if (!bRet) break;
if (!bRet)
break;
}
if (!bRet) break;
if (!bRet)
break;
pEnumNetworks->lpVtbl->Reset(pEnumNetworks);
}
pEnumNetworks->lpVtbl->Release(pEnumNetworks);
@ -1216,7 +1264,8 @@ static bool nlm_filter_match(const struct str_list_head *nlm_list)
bRet = false;
break;
}
if (w_win32_error != S_OK) break;
if (w_win32_error != S_OK)
break;
if (SUCCEEDED(w_win32_error = pNet->lpVtbl->GetNetworkId(pNet, &idNet)) &&
SUCCEEDED(w_win32_error = pNet->lpVtbl->GetName(pNet, &bstrName)))
{
@ -1225,7 +1274,8 @@ static bool nlm_filter_match(const struct str_list_head *nlm_list)
LIST_FOREACH(nlm, nlm_list, next)
{
bMatch = !strcmp(Name, nlm->str) || str2guid(nlm->str, &g) && !memcmp(&idNet, &g, sizeof(GUID));
if (bMatch) break;
if (bMatch)
break;
}
}
else
@ -1238,7 +1288,8 @@ static bool nlm_filter_match(const struct str_list_head *nlm_list)
else
bRet = false;
pNet->lpVtbl->Release(pNet);
if (!bRet || bMatch) break;
if (!bRet || bMatch)
break;
}
pEnum->lpVtbl->Release(pEnum);
}
@ -1267,9 +1318,11 @@ static bool wlan_filter_match(const struct str_list_head *ssid_list)
}
w_win32_error = WlanOpenHandle(2, NULL, &dwCurVersion, &hClient);
if (w_win32_error != ERROR_SUCCESS) goto fail;
if (w_win32_error != ERROR_SUCCESS)
goto fail;
w_win32_error = WlanEnumInterfaces(hClient, NULL, &pIfList);
if (w_win32_error != ERROR_SUCCESS) goto fail;
if (w_win32_error != ERROR_SUCCESS)
goto fail;
for (k = 0; k < pIfList->dwNumberOfItems; k++)
{
pIfInfo = pIfList->InterfaceInfo + k;
@ -1282,7 +1335,8 @@ static bool wlan_filter_match(const struct str_list_head *ssid_list)
&connectInfoSize,
(PVOID *)&pConnectInfo,
NULL);
if (w_win32_error != ERROR_SUCCESS) goto fail;
if (w_win32_error != ERROR_SUCCESS)
goto fail;
// printf("%s\n", pConnectInfo->wlanAssociationAttributes.dot11Ssid.ucSSID);
@ -1303,8 +1357,10 @@ static bool wlan_filter_match(const struct str_list_head *ssid_list)
fail:
bRes = false;
ex:
if (pIfList) WlanFreeMemory(pIfList);
if (hClient) WlanCloseHandle(hClient, 0);
if (pIfList)
WlanFreeMemory(pIfList);
if (hClient)
WlanCloseHandle(hClient, 0);
return bRes;
found:
w_win32_error = 0;
@ -1320,7 +1376,8 @@ bool logical_net_filter_match(void)
static bool logical_net_filter_match_rate_limited(void)
{
DWORD dwTick = GetTickCount() / 1000;
if (logical_net_filter_tick == dwTick) return true;
if (logical_net_filter_tick == dwTick)
return true;
logical_net_filter_tick = dwTick;
return logical_net_filter_match();
}
@ -1345,7 +1402,8 @@ static HANDLE windivert_init_filter(const char *filter, UINT64 flags)
SetLastError(w_win32_error);
}
if (h != INVALID_HANDLE_VALUE) return h;
if (h != INVALID_HANDLE_VALUE)
return h;
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, w_win32_error, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), (LPSTR)&errormessage, 0, NULL);
@ -1506,9 +1564,12 @@ static int *rawsend_family_sock(sa_family_t family)
{
switch (family)
{
case AF_INET: return &rawsend_sock4;
case AF_INET6: return &rawsend_sock6;
default: return NULL;
case AF_INET:
return &rawsend_sock4;
case AF_INET6:
return &rawsend_sock6;
default:
return NULL;
}
}
@ -1617,7 +1678,8 @@ static bool set_socket_fwmark(int sock, uint32_t fwmark)
static int rawsend_socket(sa_family_t family)
{
int *sock = rawsend_family_sock(family);
if (!sock) return -1;
if (!sock)
return -1;
if (*sock == -1)
{
@ -1660,7 +1722,7 @@ static int rawsend_socket(sa_family_t family)
if (family == AF_INET6 && setsockopt(*sock, SOL_IPV6, IPV6_FREEBIND, &yes, sizeof(yes)) == -1)
{
// DLOG_PERROR("rawsend: setsockopt(IPV6_FREEBIND)");
// dont error because it's supported only from kernel 4.15
// don't error because it's supported only from kernel 4.15
}
#endif
}
@ -1673,21 +1735,23 @@ bool rawsend_preinit(bool bind_fix4, bool bind_fix6)
{
b_bind_fix4 = bind_fix4;
b_bind_fix6 = bind_fix6;
// allow ipv6 disabled systems
// allow IPv6 disabled systems
return rawsend_socket(AF_INET) != -1 && (rawsend_socket(AF_INET6) != -1 || errno == EAFNOSUPPORT);
}
bool rawsend(const struct sockaddr *dst, uint32_t fwmark, const char *ifout, const void *data, size_t len)
{
ssize_t bytes;
int sock = rawsend_socket(dst->sa_family);
if (sock==-1) return false;
if (!set_socket_fwmark(sock,fwmark)) return false;
if (sock == -1)
return false;
if (!set_socket_fwmark(sock, fwmark))
return false;
int salen = dst->sa_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
struct sockaddr_storage dst2;
memcpy(&dst2, dst, salen);
if (dst->sa_family == AF_INET6)
((struct sockaddr_in6 *)&dst2)->sin6_port = 0; // or will be EINVAL in linux
((struct sockaddr_in6 *)&dst2)->sin6_port = 0; // or will be EINVAL in Linux
#if defined(BSD)
bytes = rawsend_sendto_divert(dst->sa_family, sock, data, len);
@ -1705,11 +1769,13 @@ bool rawsend(const struct sockaddr* dst,uint32_t fwmark,const char *ifout,const
switch (dst->sa_family)
{
case AF_INET:
if (!b_bind_fix4) goto nofix;
if (!b_bind_fix4)
goto nofix;
extract_endpoints(data, NULL, NULL, NULL, &sa_src, NULL);
break;
case AF_INET6:
if (!b_bind_fix6) goto nofix;
if (!b_bind_fix6)
goto nofix;
extract_endpoints(NULL, data, NULL, NULL, &sa_src, NULL);
break;
default:
@ -1763,7 +1829,6 @@ bool rawsend_queue(struct rawpacket_tailhead *q)
return b;
}
// return guessed fake ttl value. 0 means unsuccessfull, should not perform autottl fooling
// ttl = TTL of incoming packet
uint8_t autottl_guess(uint8_t ttl, const autottl *attl)
@ -1786,10 +1851,13 @@ uint8_t autottl_guess(uint8_t ttl, const autottl *attl)
path = orig - ttl;
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 (fake < attl->min)
fake = attl->min;
else if (fake > attl->max)
fake = attl->max;
if (fake>=path) return 0;
if (fake >= path)
return 0;
return fake;
}
@ -1836,7 +1904,6 @@ void do_nat(bool bOutbound, struct ip *ip, struct ip6_hdr *ip6, struct tcphdr *t
}
}
void verdict_tcp_csum_fix(uint8_t verdict, struct tcphdr *tcphdr, size_t transport_len, struct ip *ip, struct ip6_hdr *ip6hdr)
{
if (!(verdict & VERDICT_NOCSUM))
@ -1844,7 +1911,7 @@ void verdict_tcp_csum_fix(uint8_t verdict, struct tcphdr *tcphdr, size_t transpo
// always fix csum for windivert. original can be partial or bad
#ifndef __CYGWIN__
#ifdef __FreeBSD__
// FreeBSD tend to pass ipv6 frames with wrong checksum
// 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
@ -1861,7 +1928,7 @@ void verdict_udp_csum_fix(uint8_t verdict, struct udphdr *udphdr, size_t transpo
// always fix csum for windivert. original can be partial or bad
#ifndef __CYGWIN__
#ifdef __FreeBSD__
// FreeBSD tend to pass ipv6 frames with wrong checksum
// 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

View File

@ -100,7 +100,6 @@ bool prepare_tcp_segment(
const void *data, uint16_t len,
uint8_t *buf, size_t *buflen);
bool prepare_udp_segment4(
const struct sockaddr_in *src, const struct sockaddr_in *dst,
uint8_t ttl,
@ -225,7 +224,12 @@ typedef struct
#define AUTOTTL_DEFAULT_MIN 3
#define AUTOTTL_DEFAULT_MAX 20
#define AUTOTTL_ENABLED(a) (!!(a).delta)
#define AUTOTTL_SET_DEFAULT(a) {(a).delta=AUTOTTL_DEFAULT_DELTA; (a).min=AUTOTTL_DEFAULT_MIN; (a).max=AUTOTTL_DEFAULT_MAX;}
#define AUTOTTL_SET_DEFAULT(a) \
{ \
(a).delta = AUTOTTL_DEFAULT_DELTA; \
(a).min = AUTOTTL_DEFAULT_MIN; \
(a).max = AUTOTTL_DEFAULT_MAX; \
}
uint8_t autottl_guess(uint8_t ttl, const autottl *attl);
void do_nat(bool bOutbound, struct ip *ip, struct ip6_hdr *ip6, struct tcphdr *tcphdr, struct udphdr *udphdr, const struct sockaddr_in *target4, const struct sockaddr_in6 *target6);

View File

@ -9,7 +9,6 @@
#include <string.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"
@ -59,8 +58,7 @@ const uint8_t fake_tls_clienthello_default[648] = {
0x64, 0x2f, 0x97, 0xd0, 0x6a, 0x06, 0x36, 0xcd, 0x25, 0xda, 0x51, 0xab, 0xd6, 0xf7, 0x5e, 0xeb,
0xd4, 0x03, 0x39, 0xa4, 0xc4, 0x2a, 0x9c, 0x17, 0xe8, 0xb0, 0x9f, 0xc0, 0xd3, 0x8c, 0x76, 0xdd,
0xa1, 0x0b, 0x76, 0x9f, 0x23, 0xfa, 0xed, 0xfb, 0xd7, 0x78, 0x0f, 0x00, 0xf7, 0x45, 0x03, 0x04,
0x84,0x66,0x6b,0xec,0xc7,0xed,0xbc,0xe4
};
0x84, 0x66, 0x6b, 0xec, 0xc7, 0xed, 0xbc, 0xe4};
static const char *tld[] = {"com", "org", "net", "edu", "gov", "biz"};
void randomize_default_tls_payload(uint8_t *p)
@ -145,7 +143,6 @@ enum dpi_desync_mode desync_mode_from_string(const char *s)
return DESYNC_INVALID;
}
// auto creates internal socket and uses it for subsequent calls
static bool rawsend_rep(const struct sockaddr *dst, uint32_t fwmark, const char *ifout, const void *data, size_t len)
{
@ -155,15 +152,18 @@ static bool rawsend_rep(const struct sockaddr* dst,uint32_t fwmark,const char *i
return true;
}
static uint64_t cutoff_get_limit(const t_ctrack *ctrack, char mode)
{
switch (mode)
{
case 'n': return ctrack->pcounter_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)
@ -181,7 +181,7 @@ static void maybe_cutoff(t_ctrack *ctrack, uint8_t proto)
// we do not need conntrack entry anymore if all cutoff conditions are either not defined or reached
// do not drop udp entry because it will be recreated when next packet arrives
if (proto == IPPROTO_TCP)
ctrack->b_cutoff |= \
ctrack->b_cutoff |=
(!params.wssize || ctrack->b_wssize_cutoff) &&
(!params.desync_cutoff || ctrack->b_desync_cutoff) &&
(!ctrack->hostname_ah_check || ctrack->req_retrans_counter == RETRANS_COUNTER_STOP) &&
@ -325,7 +325,6 @@ static bool send_delayed(t_ctrack *ctrack)
return true;
}
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);
@ -393,7 +392,6 @@ static void reasm_orig_fin(t_ctrack *ctrack)
reasm_orig_stop(ctrack, "reassemble session finished\n");
}
static uint8_t ct_new_postnat_fix(const t_ctrack *ctrack, struct ip *ip, struct ip6_hdr *ip6, uint8_t proto, struct udphdr *udp, struct tcphdr *tcp, size_t *len_pkt)
{
#ifdef __linux__
@ -403,7 +401,7 @@ static uint8_t ct_new_postnat_fix(const t_ctrack *ctrack, struct ip *ip, struct
// we also can't use fooling because DPI would accept fooled packets
if (ctrack && ctrack->pcounter_orig == 1)
{
DLOG("applying linux postnat conntrack workaround\n");
DLOG("applying Linux postnat conntrack workaround\n");
if (proto == IPPROTO_UDP && udp && len_pkt)
{
// make malformed udp packet with zero length and invalid checksum
@ -426,7 +424,8 @@ static uint8_t ct_new_postnat_fix(const t_ctrack *ctrack, struct ip *ip, struct
// make flags invalid and also corrupt checksum
tcp->th_flags = 0;
}
if (ip) ip->ip_sum ^= htons(0xBEAF);
if (ip)
ip->ip_sum ^= htons(0xBEAF);
return VERDICT_MODIFY | VERDICT_NOCSUM;
}
#endif
@ -442,7 +441,6 @@ static uint8_t ct_new_postnat_fix_udp(const t_ctrack *ctrack, struct ip *ip, str
return ct_new_postnat_fix(ctrack, ip, ip6, IPPROTO_UDP, udphdr, NULL, len_pkt);
}
static bool check_desync_interval(const t_ctrack *ctrack)
{
if (params.desync_start)
@ -519,7 +517,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
uint8_t verdict = VERDICT_PASS;
// additional safety check
if (!!ip == !!ip6hdr) return verdict;
if (!!ip == !!ip6hdr)
return verdict;
t_ctrack *ctrack = NULL, *ctrack_replay = NULL;
bool bReverse = false;
@ -610,8 +609,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
}
if (bFail)
auto_hostlist_failed(ctrack->hostname);
else
if (len_payload)
else if (len_payload)
auto_hostlist_reset_fail_counter(ctrack->hostname);
if (tcphdr->th_flags & TH_RST)
ConntrackClearHostname(ctrack); // do not react to further dup RSTs
@ -620,7 +618,6 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
return verdict; // nothing to do. do not waste cpu
}
if (params.wssize)
{
if (ctrack)
@ -631,7 +628,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
}
else
{
if (params.wssize_cutoff) DLOG("wssize-cutoff not reached (mode %c): %llu/%u\n", params.wssize_cutoff_mode, (unsigned long long)cutoff_get_limit(ctrack,params.wssize_cutoff_mode), params.wssize_cutoff);
if (params.wssize_cutoff)
DLOG("wssize-cutoff not reached (mode %c): %llu/%u\n", params.wssize_cutoff_mode, (unsigned long long)cutoff_get_limit(ctrack, params.wssize_cutoff_mode), params.wssize_cutoff);
tcp_rewrite_winsize(tcphdr, params.wssize, params.wsscale);
verdict = VERDICT_MODIFY;
}
@ -687,7 +685,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
return verdict;
}
DLOG("sending SYN with fake data : ");
hexdump_limited_dlog(params.fake_syndata,params.fake_syndata_size,PKTDATA_MAXDUMP); DLOG("\n");
hexdump_limited_dlog(params.fake_syndata, params.fake_syndata_size, PKTDATA_MAXDUMP);
DLOG("\n");
if (!rawsend_rep((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len))
return verdict;
verdict = ct_new_postnat_fix_tcp(ctrack, ip, ip6hdr, tcphdr);
@ -700,10 +699,12 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
}
// start and cutoff limiters
if (!process_desync_interval(ctrack)) return verdict;
if (!process_desync_interval(ctrack))
return verdict;
} // !replay
if (!params.wssize && params.desync_mode==DESYNC_NONE && !params.hostcase && !params.hostnospace && !params.domcase && !*params.hostlist_auto_filename) return verdict; // nothing to do. do not waste cpu
if (!params.wssize && params.desync_mode == DESYNC_NONE && !params.hostcase && !params.hostnospace && !params.domcase && !*params.hostlist_auto_filename)
return verdict; // nothing to do. do not waste cpu
if (!(tcphdr->th_flags & TH_SYN) && len_payload)
{
@ -734,7 +735,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
if ((bIsHttp = IsHttp(rdata_payload, rlen_payload)))
{
DLOG("packet contains HTTP request\n");
if (ctrack && !ctrack->l7proto) ctrack->l7proto = HTTP;
if (ctrack && !ctrack->l7proto)
ctrack->l7proto = HTTP;
// we do not reassemble http
reasm_orig_cancel(ctrack);
@ -774,7 +776,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
if (ctrack)
{
if (!ctrack->l7proto) ctrack->l7proto = TLS;
if (!ctrack->l7proto)
ctrack->l7proto = TLS;
// do not reasm retransmissions
if (!bReqFull && ReasmIsEmpty(&ctrack->reasm_orig) && !ctrack->req_seq_abandoned &&
!(ctrack->req_seq_finalized && seq_within(ctrack->seq_last, ctrack->req_seq_start, ctrack->req_seq_end)))
@ -785,7 +788,6 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
reasm_orig_cancel(ctrack);
return verdict;
}
}
if (!ctrack->req_seq_finalized)
{
@ -801,7 +803,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
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);
if (bReqFull || ReasmIsEmpty(&ctrack->reasm_orig))
forced_wssize_cutoff(ctrack);
if (!ReasmIsEmpty(&ctrack->reasm_orig))
{
@ -847,7 +850,8 @@ 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)
@ -865,7 +869,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
ctrack_replay->hostname_ah_check = *params.hostlist_auto_filename && !bBypass;
if (ctrack_replay->hostname_ah_check)
{
if (!ctrack_replay->hostname) ctrack_replay->hostname=strdup(host);
if (!ctrack_replay->hostname)
ctrack_replay->hostname = strdup(host);
}
else
ctrack_stop_retrans_counter(ctrack_replay);
@ -878,7 +883,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
if (!bKnownProtocol)
{
if (!params.desync_any_proto) return verdict;
if (!params.desync_any_proto)
return verdict;
DLOG("applying tampering to unknown protocol\n");
fake = params.fake_unknown;
fake_size = params.fake_unknown_size;
@ -919,7 +925,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
}
}
if (params.desync_mode==DESYNC_NONE) return verdict;
if (params.desync_mode == DESYNC_NONE)
return verdict;
if (params.debug)
{
@ -929,7 +936,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
DLOG("dpi desync src=%s dst=%s\n", s1, s2);
}
if (!split_pos || split_pos>rlen_payload) split_pos=1;
if (!split_pos || split_pos > rlen_payload)
split_pos = 1;
split_pos = pos_normalize(split_pos, reasm_offset, len_payload);
enum dpi_desync_mode desync_mode = params.desync_mode;
@ -953,7 +961,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
break;
}
case DESYNC_FAKE:
if (reasm_offset) break;
if (reasm_offset)
break;
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->th_seq, tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps,
ttl_fake, params.desync_fooling_mode, params.desync_badseq_increment, params.desync_badseq_ack_increment,
fake, fake_size, pkt1, &pkt1_len))
@ -961,12 +970,14 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
return verdict;
}
DLOG("sending fake request : ");
hexdump_limited_dlog(fake,fake_size,PKTDATA_MAXDUMP); DLOG("\n");
hexdump_limited_dlog(fake, fake_size, PKTDATA_MAXDUMP);
DLOG("\n");
b = true;
break;
case DESYNC_RST:
case DESYNC_RSTACK:
if (reasm_offset) break;
if (reasm_offset)
break;
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_RST | (desync_mode == DESYNC_RSTACK ? TH_ACK : 0), tcphdr->th_seq, tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps,
ttl_fake, params.desync_fooling_mode, params.desync_badseq_increment, params.desync_badseq_ack_increment,
NULL, 0, pkt1, &pkt1_len))
@ -979,7 +990,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
case DESYNC_HOPBYHOP:
case DESYNC_DESTOPT:
case DESYNC_IPFRAG1:
fooling_orig = (desync_mode==DESYNC_HOPBYHOP) ? FOOL_HOPBYHOP : (desync_mode==DESYNC_DESTOPT) ? FOOL_DESTOPT : FOOL_IPFRAG1;
fooling_orig = (desync_mode == DESYNC_HOPBYHOP) ? FOOL_HOPBYHOP : (desync_mode == DESYNC_DESTOPT) ? FOOL_DESTOPT
: FOOL_IPFRAG1;
desync_mode = params.desync_mode2;
if (ip6hdr && (desync_mode == DESYNC_NONE || !desync_valid_second_stage_tcp(desync_mode) ||
(!split_pos && (desync_mode == DESYNC_SPLIT || desync_mode == DESYNC_SPLIT2 || desync_mode == DESYNC_DISORDER || desync_mode == DESYNC_DISORDER2))))
@ -1057,12 +1069,12 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
seg, seg_len, pkt1, &pkt1_len))
return verdict;
DLOG("sending 2nd out-of-order tcp segment %zu-%zu len=%zu seqovl=%u : ", split_pos, len_payload - 1, len_payload - split_pos, params.desync_seqovl);
hexdump_limited_dlog(seg,seg_len,PKTDATA_MAXDUMP); DLOG("\n");
hexdump_limited_dlog(seg, seg_len, PKTDATA_MAXDUMP);
DLOG("\n");
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len))
return verdict;
}
if (desync_mode == DESYNC_DISORDER)
{
seg_len = sizeof(fakeseg);
@ -1071,7 +1083,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
zeropkt, split_pos, fakeseg, &seg_len))
return verdict;
DLOG("sending fake(1) 1st out-of-order tcp segment 0-%zu len=%zu : ", split_pos - 1, split_pos);
hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n");
hexdump_limited_dlog(zeropkt, split_pos, PKTDATA_MAXDUMP);
DLOG("\n");
if (!rawsend_rep((struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, seg_len))
return verdict;
}
@ -1082,14 +1095,16 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
data_payload, split_pos, pkt1, &pkt1_len))
return verdict;
DLOG("sending 1st out-of-order tcp segment 0-%zu len=%zu : ", split_pos - 1, split_pos);
hexdump_limited_dlog(data_payload,split_pos,PKTDATA_MAXDUMP); DLOG("\n");
hexdump_limited_dlog(data_payload, split_pos, PKTDATA_MAXDUMP);
DLOG("\n");
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len))
return verdict;
if (desync_mode == DESYNC_DISORDER)
{
DLOG("sending fake(2) 1st out-of-order tcp segment 0-%zu len=%zu : ", split_pos - 1, split_pos);
hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n");
hexdump_limited_dlog(zeropkt, split_pos, PKTDATA_MAXDUMP);
DLOG("\n");
if (!rawsend_rep((struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, seg_len))
return verdict;
}
@ -1112,7 +1127,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
zeropkt, split_pos, fakeseg, &fakeseg_len))
return verdict;
DLOG("sending fake(1) 1st tcp segment 0-%zu len=%zu : ", split_pos - 1, split_pos);
hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n");
hexdump_limited_dlog(zeropkt, split_pos, PKTDATA_MAXDUMP);
DLOG("\n");
if (!rawsend_rep((struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, fakeseg_len))
return verdict;
}
@ -1140,14 +1156,16 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
seg, seg_len, pkt1, &pkt1_len))
return verdict;
DLOG("sending 1st tcp segment 0-%zu len=%zu seqovl=%u : ", split_pos - 1, split_pos, params.desync_seqovl);
hexdump_limited_dlog(seg,seg_len,PKTDATA_MAXDUMP); DLOG("\n");
hexdump_limited_dlog(seg, seg_len, PKTDATA_MAXDUMP);
DLOG("\n");
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len))
return verdict;
if (desync_mode == DESYNC_SPLIT)
{
DLOG("sending fake(2) 1st tcp segment 0-%zu len=%zu : ", split_pos - 1, split_pos);
hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n");
hexdump_limited_dlog(zeropkt, split_pos, PKTDATA_MAXDUMP);
DLOG("\n");
if (!rawsend_rep((struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, fakeseg_len))
return verdict;
}
@ -1159,7 +1177,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
data_payload + split_pos, len_payload - split_pos, pkt1, &pkt1_len))
return verdict;
DLOG("sending 2nd tcp segment %zu-%zu len=%zu : ", split_pos, len_payload - 1, len_payload - split_pos);
hexdump_limited_dlog(data_payload+split_pos,len_payload-split_pos,PKTDATA_MAXDUMP); DLOG("\n");
hexdump_limited_dlog(data_payload + split_pos, len_payload - split_pos, PKTDATA_MAXDUMP);
DLOG("\n");
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len))
return verdict;
}
@ -1198,12 +1217,14 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
return verdict;
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");
hexdump_limited_dlog(pkt1, pkt1_len, IP_MAXDUMP);
DLOG("\n");
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len))
return verdict;
DLOG("sending 2nd ip fragment %zu-%zu ip_payload_len=%zu : ", ipfrag_pos, transport_len - 1, transport_len - ipfrag_pos);
hexdump_limited_dlog(pkt2,pkt2_len,IP_MAXDUMP); DLOG("\n");
hexdump_limited_dlog(pkt2, pkt2_len, IP_MAXDUMP);
DLOG("\n");
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt2, pkt2_len))
return verdict;
@ -1212,7 +1233,6 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
default:
break;
}
}
return verdict;
@ -1239,10 +1259,12 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
uint8_t verdict = VERDICT_PASS;
// additional safety check
if (!!ip == !!ip6hdr) return verdict;
if (!!ip == !!ip6hdr)
return verdict;
// no need to desync middle packets in reasm session
if (reasm_offset) return verdict;
if (reasm_offset)
return verdict;
t_ctrack *ctrack = NULL, *ctrack_replay = NULL;
bool bReverse = false;
@ -1274,17 +1296,22 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
// ConntrackPoolDump(&params.conntrack);
}
if (bReverse) return verdict; // nothing to do. do not waste cpu
if (bReverse)
return verdict; // nothing to do. do not waste cpu
if (params.desync_mode==DESYNC_NONE && !*params.hostlist_auto_filename) return verdict; // do not waste cpu
if (params.desync_mode == DESYNC_NONE && !*params.hostlist_auto_filename)
return verdict; // do not waste cpu
// start and cutoff limiters
if (!replay && !process_desync_interval(ctrack)) return verdict;
if (!replay && !process_desync_interval(ctrack))
return verdict;
uint32_t desync_fwmark = fwmark | params.desync_fwmark;
ttl_orig = ip ? ip->ip_ttl : ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_hlim;
if (ip6hdr) ttl_fake = params.desync_ttl6 ? params.desync_ttl6 : ttl_orig;
else ttl_fake = params.desync_ttl ? params.desync_ttl : ttl_orig;
if (ip6hdr)
ttl_fake = params.desync_ttl6 ? params.desync_ttl6 : ttl_orig;
else
ttl_fake = params.desync_ttl ? params.desync_ttl : ttl_orig;
extract_endpoints(ip, ip6hdr, NULL, udphdr, &src, &dst);
if (len_payload)
@ -1299,7 +1326,8 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
if (IsQUICInitial(data_payload, len_payload))
{
DLOG("packet contains QUIC initial\n");
if (ctrack && !ctrack->l7proto) ctrack->l7proto = QUIC;
if (ctrack && !ctrack->l7proto)
ctrack->l7proto = QUIC;
uint8_t clean[16384], *pclean;
size_t clean_len;
@ -1386,19 +1414,22 @@ 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")) return verdict;
if (!quic_reasm_cancel(ctrack, "QUIC initial without ClientHello"))
return verdict;
}
}
else
{
// defrag failed
if (!quic_reasm_cancel(ctrack,"QUIC initial defrag CRYPTO failed")) return verdict;
if (!quic_reasm_cancel(ctrack, "QUIC initial defrag CRYPTO failed"))
return verdict;
}
}
else
{
// decrypt failed
if (!quic_reasm_cancel(ctrack,"QUIC initial decryption failed")) return verdict;
if (!quic_reasm_cancel(ctrack, "QUIC initial decryption failed"))
return verdict;
}
fake = params.fake_quic;
@ -1414,8 +1445,9 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
if (IsWireguardHandshakeInitiation(data_payload, len_payload))
{
DLOG("packet contains wireguard handshake initiation\n");
if (ctrack && !ctrack->l7proto) ctrack->l7proto = WIREGUARD;
DLOG("packet contains WireGuard handshake initiation\n");
if (ctrack && !ctrack->l7proto)
ctrack->l7proto = WIREGUARD;
fake = params.fake_wg;
fake_size = params.fake_wg_size;
bKnownProtocol = true;
@ -1423,14 +1455,16 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
else if (IsDhtD1(data_payload, len_payload))
{
DLOG("packet contains DHT d1...e\n");
if (ctrack && !ctrack->l7proto) ctrack->l7proto = DHT;
if (ctrack && !ctrack->l7proto)
ctrack->l7proto = DHT;
fake = params.fake_dht;
fake_size = params.fake_dht_size;
bKnownProtocol = true;
}
else
{
if (!params.desync_any_proto) return verdict;
if (!params.desync_any_proto)
return verdict;
DLOG("applying tampering to unknown protocol\n");
fake = params.fake_unknown_udp;
fake_size = params.fake_unknown_udp_size;
@ -1489,7 +1523,8 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, ttl_fake, params.desync_fooling_mode, NULL, 0, 0, fake, fake_size, pkt1, &pkt1_len))
return verdict;
DLOG("sending fake request : ");
hexdump_limited_dlog(fake,fake_size,PKTDATA_MAXDUMP); DLOG("\n");
hexdump_limited_dlog(fake, fake_size, PKTDATA_MAXDUMP);
DLOG("\n");
if (!rawsend_rep((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len))
return verdict;
b = true;
@ -1497,7 +1532,8 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
case DESYNC_HOPBYHOP:
case DESYNC_DESTOPT:
case DESYNC_IPFRAG1:
fooling_orig = (desync_mode==DESYNC_HOPBYHOP) ? FOOL_HOPBYHOP : (desync_mode==DESYNC_DESTOPT) ? FOOL_DESTOPT : FOOL_IPFRAG1;
fooling_orig = (desync_mode == DESYNC_HOPBYHOP) ? FOOL_HOPBYHOP : (desync_mode == DESYNC_DESTOPT) ? FOOL_DESTOPT
: FOOL_IPFRAG1;
if (ip6hdr && (params.desync_mode2 == DESYNC_NONE || !desync_valid_second_stage_udp(params.desync_mode2)))
{
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst,
@ -1607,12 +1643,14 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
return verdict;
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");
hexdump_limited_dlog(pkt1, pkt1_len, IP_MAXDUMP);
DLOG("\n");
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len))
return verdict;
DLOG("sending 2nd ip fragment %zu-%zu ip_payload_len=%zu : ", ipfrag_pos, transport_len - 1, transport_len - ipfrag_pos);
hexdump_limited_dlog(pkt2,pkt2_len,IP_MAXDUMP); DLOG("\n");
hexdump_limited_dlog(pkt2, pkt2_len, IP_MAXDUMP);
DLOG("\n");
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt2, pkt2_len))
return verdict;
@ -1621,18 +1659,17 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
default:
break;
}
}
return verdict;
}
static void packet_debug(bool replay, uint8_t proto, const struct ip *ip, const struct ip6_hdr *ip6hdr, const struct tcphdr *tcphdr, const struct udphdr *udphdr, const uint8_t *data_payload, size_t len_payload)
{
if (params.debug)
{
if (replay) DLOG("REPLAY ");
if (replay)
DLOG("REPLAY ");
if (ip)
{
char s[66];
@ -1650,22 +1687,30 @@ static void packet_debug(bool replay, uint8_t proto, const struct ip *ip, const
char s[80];
str_tcphdr(s, sizeof(s), tcphdr);
DLOG(" %s\n", s);
if (len_payload) { DLOG("TCP: "); hexdump_limited_dlog(data_payload, len_payload, 32); DLOG("\n"); }
if (len_payload)
{
DLOG("TCP: ");
hexdump_limited_dlog(data_payload, len_payload, 32);
DLOG("\n");
}
}
else if (udphdr)
{
char s[30];
str_udphdr(s, sizeof(s), udphdr);
DLOG(" %s\n", s);
if (len_payload) { DLOG("UDP: "); hexdump_limited_dlog(data_payload, len_payload, 32); DLOG("\n"); }
if (len_payload)
{
DLOG("UDP: ");
hexdump_limited_dlog(data_payload, len_payload, 32);
DLOG("\n");
}
}
else
DLOG("\n");
}
}
static uint8_t dpi_desync_packet_play(bool replay, size_t reasm_offset, uint32_t fwmark, const char *ifout, uint8_t *data_pkt, size_t *len_pkt)
{
struct ip *ip;
@ -1706,8 +1751,6 @@ uint8_t dpi_desync_packet(uint32_t fwmark, const char *ifout, uint8_t *data_pkt,
return dpi_desync_packet_play(false, 0, fwmark, ifout, data_pkt, len_pkt);
}
static bool replay_queue(struct rawpacket_tailhead *q)
{
struct rawpacket *rp;

View File

@ -19,7 +19,8 @@
#define DPI_DESYNC_MAX_FAKE_LEN 9216
enum dpi_desync_mode {
enum dpi_desync_mode
{
DESYNC_NONE = 0,
DESYNC_INVALID,
DESYNC_FAKE,

View File

@ -21,7 +21,8 @@ int z_readfile(FILE *F, char **buf, size_t *size)
bufsize = *size = 0;
r = inflateInit2(&zs, 47);
if (r != Z_OK) return r;
if (r != Z_OK)
return r;
do
{
@ -31,7 +32,8 @@ int z_readfile(FILE *F, char **buf, size_t *size)
r = Z_ERRNO;
goto zerr;
}
if (!zs.avail_in) break;
if (!zs.avail_in)
break;
zs.next_in = in;
do
{
@ -49,7 +51,8 @@ int z_readfile(FILE *F, char **buf, size_t *size)
zs.avail_out = bufsize - *size;
zs.next_out = (unsigned char *)(*buf + *size);
r = inflate(&zs, Z_NO_FLUSH);
if (r != Z_OK && r != Z_STREAM_END) goto zerr;
if (r != Z_OK && r != Z_STREAM_END)
goto zerr;
*size = bufsize - zs.avail_out;
} while (r == Z_OK && zs.avail_in);
} while (r == Z_OK);
@ -57,7 +60,8 @@ int z_readfile(FILE *F, char **buf, size_t *size)
if (*size < bufsize)
{
// free extra space
if ((newbuf = realloc(*buf, *size))) *buf = newbuf;
if ((newbuf = realloc(*buf, *size)))
*buf = newbuf;
}
inflateEnd(&zs);

View File

@ -7,7 +7,6 @@
#include <ctype.h>
#include <sys/stat.h>
#include "params.h"
void hexdump_limited_dlog(const uint8_t *data, size_t size, size_t limit)
@ -19,11 +18,15 @@ void hexdump_limited_dlog(const uint8_t *data, size_t size, size_t limit)
size = limit;
bcut = true;
}
if (!size) return;
for (k = 0; k < size; k++) DLOG("%02X ", data[k]);
if (!size)
return;
for (k = 0; k < size; k++)
DLOG("%02X ", data[k]);
DLOG(bcut ? "... : " : ": ");
for (k = 0; k < size; k++) DLOG("%c", data[k] >= 0x20 && data[k] <= 0x7F ? (char)data[k] : '.');
if (bcut) DLOG(" ...");
for (k = 0; k < size; k++)
DLOG("%c", data[k] >= 0x20 && data[k] <= 0x7F ? (char)data[k] : '.');
if (bcut)
DLOG(" ...");
}
char *strncasestr(const char *s, const char *find, size_t slen)
@ -38,9 +41,11 @@ char *strncasestr(const char *s, const char *find, size_t slen)
{
do
{
if (slen-- < 1 || (sc = *s++) == '\0') return NULL;
if (slen-- < 1 || (sc = *s++) == '\0')
return NULL;
} while (toupper(c) != toupper(sc));
if (len > slen) return NULL;
if (len > slen)
return NULL;
} while (strncasecmp(s, find, len) != 0);
s--;
}
@ -52,7 +57,8 @@ bool load_file(const char *filename, void *buffer, size_t *buffer_size)
FILE *F;
F = fopen(filename, "rb");
if (!F) return false;
if (!F)
return false;
*buffer_size = fread(buffer, 1, *buffer_size, F);
if (ferror(F))
@ -74,7 +80,8 @@ bool save_file(const char *filename, const void *buffer, size_t buffer_size)
FILE *F;
F = fopen(filename, "wb");
if (!F) return false;
if (!F)
return false;
fwrite(buffer, 1, buffer_size, F);
if (ferror(F))
@ -89,16 +96,17 @@ bool save_file(const char *filename, const void *buffer, size_t buffer_size)
bool append_to_list_file(const char *filename, const char *s)
{
FILE *F = fopen(filename, "at");
if (!F) return false;
if (!F)
return false;
bool bOK = fprintf(F, "%s\n", s) > 0;
fclose(F);
return bOK;
}
void ntop46(const struct sockaddr *sa, char *str, size_t len)
{
if (!len) return;
if (!len)
return;
*str = 0;
switch (sa->sa_family)
{
@ -143,15 +151,18 @@ bool pton4_port(const char *s, struct sockaddr_in *sa)
unsigned int u;
p = strchr(s, ':');
if (!p) return false;
if (!p)
return false;
l = p - s;
if (l<7 || l>15) return false;
if (l < 7 || l > 15)
return false;
memcpy(ip, s, l);
ip[l] = 0;
p++;
sa->sin_family = AF_INET;
if (inet_pton(AF_INET,ip,&sa->sin_addr)!=1 || sscanf(p,"%u",&u)!=1 || !u || u>0xFFFF) return false;
if (inet_pton(AF_INET, ip, &sa->sin_addr) != 1 || sscanf(p, "%u", &u) != 1 || !u || u > 0xFFFF)
return false;
sa->sin_port = htons((uint16_t)u);
return true;
@ -162,17 +173,21 @@ bool pton6_port(const char *s, struct sockaddr_in6 *sa)
size_t l;
unsigned int u;
if (*s++!='[') return false;
if (*s++ != '[')
return false;
p = strchr(s, ']');
if (!p || p[1]!=':') return false;
if (!p || p[1] != ':')
return false;
l = p - s;
if (l<2 || l>39) return false;
if (l < 2 || l > 39)
return false;
p += 2;
memcpy(ip, s, l);
ip[l] = 0;
sa->sin6_family = AF_INET6;
if (inet_pton(AF_INET6,ip,&sa->sin6_addr)!=1 || sscanf(p,"%u",&u)!=1 || !u || u>0xFFFF) return false;
if (inet_pton(AF_INET6, ip, &sa->sin6_addr) != 1 || sscanf(p, "%u", &u) != 1 || !u || u > 0xFFFF)
return false;
sa->sin6_port = htons((uint16_t)u);
sa->sin6_flowinfo = 0;
sa->sin6_scope_id = 0;
@ -180,7 +195,6 @@ bool pton6_port(const char *s, struct sockaddr_in6 *sa)
return true;
}
void dbgprint_socket_buffers(int fd)
{
if (params.debug)
@ -247,11 +261,12 @@ bool ipv6_addr_is_zero(const struct in6_addr *a)
return !memcmp(a, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16);
}
#define INVALID_HEX_DIGIT ((uint8_t) - 1)
static inline uint8_t parse_hex_digit(char c)
{
return (c>='0' && c<='9') ? c-'0' : (c>='a' && c<='f') ? c-'a'+0xA : (c>='A' && c<='F') ? c-'A'+0xA : INVALID_HEX_DIGIT;
return (c >= '0' && c <= '9') ? c - '0' : (c >= 'a' && c <= 'f') ? c - 'a' + 0xA
: (c >= 'A' && c <= 'F') ? c - 'A' + 0xA
: INVALID_HEX_DIGIT;
}
static inline bool parse_hex_byte(const char *s, uint8_t *pbyte)
{
@ -277,7 +292,9 @@ bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size)
{
if (!parse_hex_byte(s, pbuf))
return false;
pbuf++; s+=2; (*size)++;
pbuf++;
s += 2;
(*size)++;
}
return true;
}
@ -319,7 +336,8 @@ bool pf_parse(const char *s, port_filter *pf)
{
unsigned int v1, v2;
if (!s) return false;
if (!s)
return false;
if (*s == '~')
{
pf->neg = true;
@ -329,13 +347,15 @@ bool pf_parse(const char *s, port_filter *pf)
pf->neg = false;
if (sscanf(s, "%u-%u", &v1, &v2) == 2)
{
if (!v1 || v1>65535 || v2>65535 || v1>v2) return false;
if (!v1 || v1 > 65535 || v2 > 65535 || v1 > v2)
return false;
pf->from = (uint16_t)v1;
pf->to = (uint16_t)v2;
}
else if (sscanf(s, "%u", &v1) == 1)
{
if (!v1 || v1>65535) return false;
if (!v1 || v1 > 65535)
return false;
pf->to = pf->from = (uint16_t)v1;
}
else
@ -346,13 +366,16 @@ bool pf_parse(const char *s, port_filter *pf)
void fill_random_bytes(uint8_t *p, size_t sz)
{
size_t k, sz16 = sz >> 1;
for(k=0;k<sz16;k++) ((uint16_t*)p)[k]=(uint16_t)random();
if (sz & 1) p[sz-1]=(uint8_t)random();
for (k = 0; k < sz16; k++)
((uint16_t *)p)[k] = (uint16_t)random();
if (sz & 1)
p[sz - 1] = (uint8_t)random();
}
void fill_random_az(uint8_t *p, size_t sz)
{
size_t k;
for(k=0;k<sz;k++) p[k] = 'a'+(random() % ('z'-'a'));
for (k = 0; k < sz; k++)
p[k] = 'a' + (random() % ('z' - 'a'));
}
void fill_random_az09(uint8_t *p, size_t sz)
{

View File

@ -32,14 +32,17 @@ void phton64(uint8_t *p, uint64_t v);
bool ipv6_addr_is_zero(const struct in6_addr *a);
static inline uint16_t pntoh16(const uint8_t *p) {
static inline uint16_t pntoh16(const uint8_t *p)
{
return ((uint16_t)p[0] << 8) | (uint16_t)p[1];
}
static inline void phton16(uint8_t *p, uint16_t v) {
static inline void phton16(uint8_t *p, uint16_t v)
{
p[0] = (uint8_t)(v >> 8);
p[1] = v & 0xFF;
}
static inline uint32_t pntoh32(const uint8_t *p) {
static inline uint32_t pntoh32(const uint8_t *p)
{
return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | (uint32_t)p[3];
}

View File

@ -10,7 +10,8 @@ static bool addpool(strpool **hostlist, char **s, const char *end)
char *p;
// advance until eol lowering all chars
for (p = *s; p<end && *p && *p!='\r' && *p != '\n'; p++) *p=tolower(*p);
for (p = *s; p < end && *p && *p != '\r' && *p != '\n'; p++)
*p = tolower(*p);
if (!StrPoolAddStrLen(hostlist, *s, p - *s))
{
StrPoolDestroy(hostlist);
@ -18,7 +19,8 @@ static bool addpool(strpool **hostlist, char **s, const char *end)
return false;
}
// advance to the next line
for (; p<end && (!*p || *p=='\r' || *p=='\n') ; p++);
for (; p < end && (!*p || *p == '\r' || *p == '\n'); p++)
;
*s = p;
return true;
}
@ -51,7 +53,8 @@ bool AppendHostList(strpool **hostlist, char *filename)
e = zbuf + zsize;
while (p < e)
{
if ( *p == '#' || *p == ';' || *p == '/' || *p == '\n' ) continue;
if (*p == '#' || *p == ';' || *p == '/' || *p == '\n')
continue;
if (!addpool(hostlist, &p, e))
{
DLOG_ERR("Not enough memory to store host list : %s\n", filename);
@ -75,7 +78,8 @@ bool AppendHostList(strpool **hostlist, char *filename)
while (fgets(s, 256, F))
{
p = s;
if ( *p == '#' || *p == ';' || *p == '/' || *p == '\n' ) continue;
if (*p == '#' || *p == ';' || *p == '/' || *p == '\n')
continue;
if (!addpool(hostlist, &p, p + strlen(p)))
{
DLOG_ERR("Not enough memory to store host list : %s\n", filename);
@ -103,7 +107,8 @@ bool LoadHostLists(strpool **hostlist, struct str_list_head *file_list)
LIST_FOREACH(file, file_list, next)
{
if (!AppendHostList(hostlist, file->str)) return false;
if (!AppendHostList(hostlist, file->str))
return false;
}
return true;
}
@ -114,7 +119,6 @@ bool NonEmptyHostlist(strpool **hostlist)
return *hostlist ? true : StrPoolAddStrLen(hostlist, "@&()", 4);
}
bool SearchHostList(strpool *hostlist, const char *host)
{
if (hostlist)
@ -125,9 +129,11 @@ bool SearchHostList(strpool *hostlist, const char *host)
{
bInHostList = StrPoolCheckStr(hostlist, p);
DLOG("Hostlist check for %s : %s\n", p, bInHostList ? "positive" : "negative");
if (bInHostList) return true;
if (bInHostList)
return true;
p = strchr(p, '.');
if (p) p++;
if (p)
p++;
}
}
return false;
@ -136,13 +142,15 @@ bool SearchHostList(strpool *hostlist, const char *host)
// return : true = apply fooling, false = do not apply
static bool HostlistCheck_(strpool *hostlist, strpool *hostlist_exclude, const char *host, bool *excluded)
{
if (excluded) *excluded = false;
if (excluded)
*excluded = false;
if (hostlist_exclude)
{
DLOG("Checking exclude hostlist\n");
if (SearchHostList(hostlist_exclude, host))
{
if (excluded) *excluded = true;
if (excluded)
*excluded = true;
return false;
}
}

View File

@ -94,7 +94,6 @@ static void pre_desync(void)
desync_init();
}
static uint8_t processPacketData(uint32_t *mark, const char *ifout, uint8_t *data_pkt, size_t *len_pkt)
{
#ifdef __linux__
@ -107,7 +106,6 @@ static uint8_t processPacketData(uint32_t *mark, const char *ifout, uint8_t *dat
return dpi_desync_packet(*mark, ifout, data_pkt, len_pkt);
}
#ifdef __linux__
static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *cookie)
{
@ -131,10 +129,12 @@ static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_da
uint32_t ifidx_in;
ifidx = nfq_get_outdev(nfa);
if (ifidx) if_indextoname(ifidx,ifout);
if (ifidx)
if_indextoname(ifidx, ifout);
*ifin = 0;
ifidx_in = nfq_get_indev(nfa);
if (ifidx_in) if_indextoname(ifidx_in,ifin);
if (ifidx_in)
if_indextoname(ifidx_in, ifin);
DLOG("packet: id=%d len=%d mark=%08X ifin=%s(%u) ifout=%s(%u)\n", id, ilen, mark, ifin, ifidx_in, ifout, ifidx);
}
@ -167,43 +167,49 @@ static int nfq_main(void)
DLOG_CONDUP("opening library handle\n");
h = nfq_open();
if (!h) {
if (!h)
{
DLOG_PERROR("nfq_open()");
goto exiterr;
}
DLOG_CONDUP("unbinding existing nf_queue handler for AF_INET (if any)\n");
if (nfq_unbind_pf(h, AF_INET) < 0) {
if (nfq_unbind_pf(h, AF_INET) < 0)
{
DLOG_PERROR("nfq_unbind_pf()");
goto exiterr;
}
DLOG_CONDUP("binding nfnetlink_queue as nf_queue handler for AF_INET\n");
if (nfq_bind_pf(h, AF_INET) < 0) {
if (nfq_bind_pf(h, AF_INET) < 0)
{
DLOG_PERROR("nfq_bind_pf()");
goto exiterr;
}
DLOG_CONDUP("binding this socket to queue '%u'\n", params.qnum);
qh = nfq_create_queue(h, params.qnum, &nfq_cb, &params);
if (!qh) {
if (!qh)
{
DLOG_PERROR("nfq_create_queue()");
goto exiterr;
}
DLOG_CONDUP("setting copy_packet mode\n");
if (nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff) < 0) {
if (nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff) < 0)
{
DLOG_PERROR("can't set packet_copy mode");
goto exiterr;
}
if (nfq_set_queue_maxlen(qh, Q_MAXLEN) < 0) {
if (nfq_set_queue_maxlen(qh, Q_MAXLEN) < 0)
{
DLOG_PERROR("can't set queue maxlen");
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))
{
DLOG_ERR("can't set queue flags. its OK on linux <3.6\n");
DLOG_ERR("can't set queue flags. its OK on Linux <3.6\n");
// dot not fail. not supported on old linuxes <3.6
}
@ -234,7 +240,8 @@ static int nfq_main(void)
{
dohup();
int r = nfq_handle_packet(h, (char *)buf, rv);
if (r) DLOG_ERR("nfq_handle_packet error %d\n", r);
if (r)
DLOG_ERR("nfq_handle_packet error %d\n", r);
}
DLOG_ERR("recv: errno %d\n", errno);
DLOG_PERROR("recv");
@ -256,8 +263,10 @@ static int nfq_main(void)
return 0;
exiterr:
if (qh) nfq_destroy_queue(qh);
if (h) nfq_close(h);
if (qh)
nfq_destroy_queue(qh);
if (h)
nfq_close(h);
return 1;
}
@ -282,7 +291,8 @@ static int dvt_main(void)
DLOG_CONDUP("creating divert4 socket\n");
fd[0] = socket_divert(AF_INET);
if (fd[0] == -1) {
if (fd[0] == -1)
{
DLOG_PERROR("socket (DIVERT4)");
goto exiterr;
}
@ -296,7 +306,6 @@ static int dvt_main(void)
goto exiterr;
}
#ifdef __OpenBSD__
{
// in OpenBSD must use separate divert sockets for ipv4 and ipv6
@ -307,7 +316,8 @@ static int dvt_main(void)
DLOG_CONDUP("creating divert6 socket\n");
fd[1] = socket_divert(AF_INET6);
if (fd[1] == -1) {
if (fd[1] == -1)
{
DLOG_PERROR("socket (DIVERT6)");
goto exiterr;
}
@ -337,7 +347,8 @@ static int dvt_main(void)
for (;;)
{
FD_ZERO(&fdset);
for(i=0;i<fdct;i++) FD_SET(fd[i], &fdset);
for (i = 0; i < fdct; i++)
FD_SET(fd[i], &fdset);
r = select(fdmax, &fdset, NULL, NULL, NULL);
if (r == -1)
{
@ -398,12 +409,13 @@ static int dvt_main(void)
res = 0;
exiterr:
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;
}
#elif defined(__CYGWIN__)
static int win_main(const char *windivert_filter)
@ -440,8 +452,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");
fflush(stdout);
}
@ -485,7 +496,8 @@ static int win_main(const char *windivert_filter)
return w_win32_error;
}
*ifout = 0;
if (wa.Outbound) snprintf(ifout,sizeof(ifout),"%u.%u", wa.Network.IfIdx, wa.Network.SubIfIdx);
if (wa.Outbound)
snprintf(ifout, sizeof(ifout), "%u.%u", wa.Network.IfIdx, wa.Network.SubIfIdx);
DLOG("packet: 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)
{
@ -529,14 +541,13 @@ static int win_main(const char *windivert_filter)
#endif // multiple OS divert handlers
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)
{
@ -557,8 +568,6 @@ static bool parse_ws_scale_factor(char *s, uint16_t *wsize, uint8_t *wscale)
return true;
}
static void cleanup_params(void)
{
ConntrackPoolDestroy(&params.conntrack);
@ -588,7 +597,8 @@ static bool parse_badseq_increment(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]=='-') params.desync_badseq_increment = -params.desync_badseq_increment;
if (opt[0] == '-')
params.desync_badseq_increment = -params.desync_badseq_increment;
return true;
}
else
@ -628,13 +638,16 @@ bool parse_autottl(const char *s, autottl *t)
switch (sscanf(s, "%u:%u-%u", &delta, &min, &max))
{
case 3:
if ((delta && !max) || max>255) return false;
if ((delta && !max) || max > 255)
return false;
t->max = (uint8_t)max;
case 2:
if ((delta && !min) || min>255 || min>max) return false;
if ((delta && !min) || min > 255 || min > max)
return false;
t->min = (uint8_t)min;
case 1:
if (delta>255) return false;
if (delta > 255)
return false;
t->delta = (uint8_t)delta;
break;
default:
@ -651,7 +664,8 @@ static bool wf_make_pf(char *opt, const char *l4, const char *portname, char *bu
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++)
{
@ -660,13 +674,15 @@ static bool wf_make_pf(char *opt, const char *l4, const char *portname, char *bu
c = *e;
*e = 0;
}
if (!pf_parse(p,&pf)) return false;
if (!pf_parse(p, &pf))
return false;
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);
if (n)
strncat(buf, " or ", len - strlen(buf) - 1);
strncat(buf, s1, len - strlen(buf) - 1);
if (e)
@ -694,7 +710,8 @@ static bool wf_make_l3(char *opt, bool *ipv4, bool *ipv6)
*ipv4 = true;
else if (!strcmp(p, "ipv6"))
*ipv6 = true;
else return false;
else
return false;
if (e)
{
@ -754,7 +771,8 @@ static bool wf_make_filter(
snprintf(iface, sizeof(iface), " ifIdx=%u and subIfIdx=%u and", IfIdx, SubIfIdx);
if (!*pf_tcp_src && !*pf_udp_src) return false;
if (!*pf_tcp_src && !*pf_udp_src)
return false;
if (*pf_tcp_src && *pf_udp_src)
{
snprintf(pf_dst_buf, sizeof(pf_dst_buf), "(%s or %s)", pf_tcp_dst, pf_udp_dst);
@ -774,8 +792,7 @@ static bool wf_make_filter(
*pf_tcp_src ? " and " : "",
*pf_tcp_src ? pf_tcp_src : "",
*pf_tcp_src ? " and " : "",
*pf_tcp_src ? ipv4 ? ipv6 ? DIVERT_NO_LOCALNETS_SRC : DIVERT_NO_LOCALNETSv4_SRC : DIVERT_NO_LOCALNETSv6_SRC : ""
);
*pf_tcp_src ? ipv4 ? ipv6 ? DIVERT_NO_LOCALNETS_SRC : DIVERT_NO_LOCALNETSv4_SRC : DIVERT_NO_LOCALNETSv6_SRC : "");
return true;
}
@ -789,7 +806,6 @@ static unsigned int hash_jen(const void *data,unsigned int len)
#endif
static void exithelp(void)
{
printf(
@ -884,8 +900,7 @@ static void exithelp(void)
DPI_DESYNC_MAX_FAKE_LEN, IPFRAG_UDP_DEFAULT,
DPI_DESYNC_MAX_FAKE_LEN, IPFRAG_TCP_DEFAULT,
BADSEQ_INCREMENT_DEFAULT, BADSEQ_ACK_INCREMENT_DEFAULT,
UDPLEN_INCREMENT_DEFAULT
);
UDPLEN_INCREMENT_DEFAULT);
exit(1);
}
static void exithelp_clean(void)
@ -963,7 +978,7 @@ int main(int argc, char **argv)
params.fake_unknown_size = 256;
params.fake_syndata_size = 16;
params.fake_unknown_udp_size = 64;
params.wscale=-1; // default - dont change scale factor (client)
params.wscale = -1; // default - don't change scale factor (client)
params.ctrack_t_syn = CTRACK_T_SYN;
params.ctrack_t_est = CTRACK_T_EST;
params.ctrack_t_fin = CTRACK_T_FIN;
@ -1076,12 +1091,13 @@ int main(int argc, char **argv)
{"nlm-filter", required_argument, 0, 0}, // optidx=59
{"nlm-list", optional_argument, 0, 0}, // optidx=60
#endif
{NULL,0,NULL,0}
};
if (argc < 2) exithelp();
{NULL, 0, NULL, 0}};
if (argc < 2)
exithelp();
while ((v = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1)
{
if (v) exithelp();
if (v)
exithelp();
switch (option_index)
{
case 0: /* debug */
@ -1219,9 +1235,11 @@ int main(int argc, char **argv)
{
char *mode = optarg, *mode2, *mode3;
mode2 = mode ? strchr(mode, ',') : NULL;
if (mode2) *mode2++=0;
if (mode2)
*mode2++ = 0;
mode3 = mode2 ? strchr(mode2, ',') : NULL;
if (mode3) *mode3++=0;
if (mode3)
*mode3++ = 0;
params.desync_mode0 = desync_mode_from_string(mode);
if (desync_valid_zero_stage(params.desync_mode0))
@ -1264,7 +1282,8 @@ int main(int argc, char **argv)
case 15: /* dpi-desync-fwmark/dpi-desync-sockarg */
#if defined(__linux__) || defined(SO_USER_COOKIE)
params.desync_fwmark = 0;
if (sscanf(optarg, "0x%X", &params.desync_fwmark)<=0) sscanf(optarg, "%u", &params.desync_fwmark);
if (sscanf(optarg, "0x%X", &params.desync_fwmark) <= 0)
sscanf(optarg, "%u", &params.desync_fwmark);
if (!params.desync_fwmark)
{
DLOG_ERR("fwmark/sockarg should be decimal or 0xHEX and should not be zero\n");
@ -1302,7 +1321,8 @@ int main(int argc, char **argv)
while (p)
{
e = strchr(p, ',');
if (e) *e++=0;
if (e)
*e++ = 0;
if (!strcmp(p, "md5sig"))
params.desync_fooling_mode |= FOOL_MD5SIG;
else if (!strcmp(p, "ts"))
@ -1632,14 +1652,14 @@ int main(int argc, char **argv)
while (p)
{
e = strchr(p, ',');
if (e) *e++=0;
if (e)
*e++ = 0;
if (*p && !strlist_add(&params.ssid_filter, p))
{
DLOG_ERR("strlist_add failed\n");
exit_clean(1);
}
p = e;
}
}
break;
@ -1650,14 +1670,14 @@ int main(int argc, char **argv)
while (p)
{
e = strchr(p, ',');
if (e) *e++=0;
if (e)
*e++ = 0;
if (*p && !strlist_add(&params.nlm_filter, p))
{
DLOG_ERR("strlist_add failed\n");
exit_clean(1);
}
p = e;
}
}
break;
@ -1721,23 +1741,27 @@ int main(int argc, char **argv)
hMutexArg = CreateMutexA(NULL, TRUE, mutex_name);
if (hMutexArg && GetLastError() == ERROR_ALREADY_EXISTS)
{
CloseHandle(hMutexArg); hMutexArg = NULL;
CloseHandle(hMutexArg);
hMutexArg = NULL;
DLOG_ERR("A copy of winws is already running with the same filter\n");
goto exiterr;
}
}
#endif
// not specified - use desync_ttl value instead
if (params.desync_ttl6 == 0xFF) params.desync_ttl6=params.desync_ttl;
if (!AUTOTTL_ENABLED(params.desync_autottl6)) params.desync_autottl6 = params.desync_autottl;
if (params.desync_ttl6 == 0xFF)
params.desync_ttl6 = params.desync_ttl;
if (!AUTOTTL_ENABLED(params.desync_autottl6))
params.desync_autottl6 = params.desync_autottl;
if (AUTOTTL_ENABLED(params.desync_autottl))
DLOG("autottl ipv4 %u:%u-%u\n",params.desync_autottl.delta,params.desync_autottl.min,params.desync_autottl.max);
DLOG("autottl IPv4 %u:%u-%u\n", params.desync_autottl.delta, params.desync_autottl.min, params.desync_autottl.max);
if (AUTOTTL_ENABLED(params.desync_autottl6))
DLOG("autottl ipv6 %u:%u-%u\n",params.desync_autottl6.delta,params.desync_autottl6.min,params.desync_autottl6.max);
if (params.desync_split_tls==tlspos_none && params.desync_split_pos) params.desync_split_tls=tlspos_pos;
if (params.desync_split_http_req==httpreqpos_none && params.desync_split_pos) params.desync_split_http_req=httpreqpos_pos;
DLOG("autottl IPv6 %u:%u-%u\n", params.desync_autottl6.delta, params.desync_autottl6.min, params.desync_autottl6.max);
if (params.desync_split_tls == tlspos_none && params.desync_split_pos)
params.desync_split_tls = tlspos_pos;
if (params.desync_split_http_req == httpreqpos_none && params.desync_split_pos)
params.desync_split_http_req = httpreqpos_pos;
if (!LoadIncludeHostLists())
{
@ -1752,7 +1776,8 @@ int main(int argc, char **argv)
exit_clean(1);
}
if (daemon) daemonize();
if (daemon)
daemonize();
if (*pidfile && !writepid(pidfile))
{

View File

@ -9,26 +9,30 @@ void rawpacket_queue_init(struct rawpacket_tailhead *q)
}
void rawpacket_free(struct rawpacket *rp)
{
if (rp) free(rp->packet);
if (rp)
free(rp->packet);
free(rp);
}
struct rawpacket *rawpacket_dequeue(struct rawpacket_tailhead *q)
{
struct rawpacket *rp;
rp = TAILQ_FIRST(q);
if (rp) TAILQ_REMOVE(q, rp, next);
if (rp)
TAILQ_REMOVE(q, rp, next);
return rp;
}
void rawpacket_queue_destroy(struct rawpacket_tailhead *q)
{
struct rawpacket *rp;
while((rp = rawpacket_dequeue(q))) rawpacket_free(rp);
while ((rp = rawpacket_dequeue(q)))
rawpacket_free(rp);
}
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q, const struct sockaddr_storage *dst, uint32_t fwmark, const char *ifout, const void *data, size_t len, size_t len_payload)
{
struct rawpacket *rp = malloc(sizeof(struct rawpacket));
if (!rp) return NULL;
if (!rp)
return NULL;
rp->packet = malloc(len);
if (!rp->packet)
@ -59,7 +63,8 @@ unsigned int rawpacket_queue_count(const struct rawpacket_tailhead *q)
{
const struct rawpacket *rp;
unsigned int ct = 0;
TAILQ_FOREACH(rp, q, next) ct++;
TAILQ_FOREACH(rp, q, next)
ct++;
return ct;
}
bool rawpacket_queue_empty(const struct rawpacket_tailhead *q)

View File

@ -13,7 +13,8 @@ struct rawpacket
uint32_t fwmark;
size_t len, len_payload;
uint8_t *packet;
TAILQ_ENTRY(rawpacket) next;
TAILQ_ENTRY(rawpacket)
next;
};
TAILQ_HEAD(rawpacket_tailhead, rawpacket);

View File

@ -13,7 +13,6 @@ const char *progname = "nfqws";
#error UNKNOWN_SYSTEM_TIME
#endif
int DLOG_FILE(FILE *F, const char *format, va_list args)
{
return vfprintf(F, format, args);
@ -116,7 +115,6 @@ int DLOG_PERROR(const char *s)
return DLOG_ERR("%s: %s\n", s, strerror(errno));
}
int LOG_APPEND(const char *filename, const char *format, va_list args)
{
int r;

View File

@ -33,7 +33,12 @@
#define HOSTLIST_AUTO_FAIL_TIME_DEFAULT 60
#define HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT 3
enum log_target { LOG_TARGET_CONSOLE=0, LOG_TARGET_FILE, LOG_TARGET_SYSLOG };
enum log_target
{
LOG_TARGET_CONSOLE = 0,
LOG_TARGET_FILE,
LOG_TARGET_SYSLOG
};
struct params_s
{

View File

@ -6,7 +6,8 @@
#define DESTROY_STR_POOL(etype, ppool) \
etype *elem, *tmp; \
HASH_ITER(hh, *ppool, elem, tmp) { \
HASH_ITER(hh, *ppool, elem, tmp) \
{ \
free(elem->str); \
HASH_DEL(*ppool, elem); \
free(elem); \
@ -32,7 +33,6 @@
return false; \
}
#undef uthash_nonfatal_oom
#define uthash_nonfatal_oom(elt) ut_oom_recover(elt)
static bool oom = false;
@ -65,13 +65,8 @@ void StrPoolDestroy(strpool **pp)
DESTROY_STR_POOL(strpool, pp)
}
void HostFailPoolDestroy(hostfail_pool **pp)
{
DESTROY_STR_POOL(hostfail_pool, pp)
}
hostfail_pool * HostFailPoolAdd(hostfail_pool **pp,const char *s,int fail_time)
void HostFailPoolDestroy(hostfail_pool **pp){
DESTROY_STR_POOL(hostfail_pool, pp)} hostfail_pool *HostFailPoolAdd(hostfail_pool **pp, const char *s, int fail_time)
{
size_t slen = strlen(s);
ADD_STR_POOL(hostfail_pool, pp, s, slen)
@ -123,11 +118,11 @@ void HostFailPoolDump(hostfail_pool *p)
printf("host=%s counter=%d time_left=%lld\n", elem->str, elem->counter, (long long int)elem->expire - now);
}
bool strlist_add(struct str_list_head *head, const char *filename)
{
struct str_list *entry = malloc(sizeof(struct str_list));
if (!entry) return false;
if (!entry)
return false;
entry->str = strdup(filename);
if (!entry->str)
{
@ -139,7 +134,8 @@ bool strlist_add(struct str_list_head *head, const char *filename)
}
static void strlist_entry_destroy(struct str_list *entry)
{
if (entry->str) free(entry->str);
if (entry->str)
free(entry->str);
free(entry);
}
void strlist_destroy(struct str_list_head *head)

View File

@ -10,7 +10,8 @@
#define HASH_FUNCTION HASH_BER
#include "uthash.h"
typedef struct strpool {
typedef struct strpool
{
char *str; /* key */
UT_hash_handle hh; /* makes this structure hashable */
} strpool;
@ -20,14 +21,16 @@ bool StrPoolAddStr(strpool **pp,const char *s);
bool StrPoolAddStrLen(strpool **pp, const char *s, size_t slen);
bool StrPoolCheckStr(strpool *p, const char *s);
struct str_list {
struct str_list
{
char *str;
LIST_ENTRY(str_list) next;
LIST_ENTRY(str_list)
next;
};
LIST_HEAD(str_list_head, str_list);
typedef struct hostfail_pool {
typedef struct hostfail_pool
{
char *str; /* key */
int counter; /* value */
time_t expire; /* when to expire record (unixtime) */

View File

@ -30,7 +30,8 @@ bool HttpFindHost(uint8_t **pHost,uint8_t *buf,size_t bs)
if (!*pHost)
{
*pHost = memmem(buf, bs, "\nHost:", 6);
if (*pHost) (*pHost)++;
if (*pHost)
(*pHost)++;
}
return !!*pHost;
}
@ -39,7 +40,8 @@ bool HttpFindHostConst(const uint8_t **pHost,const uint8_t *buf,size_t bs)
if (!*pHost)
{
*pHost = memmem(buf, bs, "\nHost:", 6);
if (*pHost) (*pHost)++;
if (*pHost)
(*pHost)++;
}
return !!*pHost;
}
@ -61,18 +63,23 @@ bool HttpExtractHeader(const uint8_t *data, size_t len, const char *header, char
const uint8_t *p, *s, *e = data + len;
p = (uint8_t *)strncasestr((char *)data, header, len);
if (!p) return false;
if (!p)
return false;
p += strlen(header);
while (p < e && (*p == ' ' || *p == '\t')) p++;
while (p < e && (*p == ' ' || *p == '\t'))
p++;
s = p;
while (s < e && (*s != '\r' && *s != '\n' && *s != ' ' && *s != '\t')) s++;
while (s < e && (*s != '\r' && *s != '\n' && *s != ' ' && *s != '\t'))
s++;
if (s > p)
{
size_t slen = s - p;
if (buf && len_buf)
{
if (slen >= len_buf) slen = len_buf - 1;
for (size_t i = 0; i < slen; i++) buf[i] = tolower(p[i]);
if (slen >= len_buf)
slen = len_buf - 1;
for (size_t i = 0; i < slen; i++)
buf[i] = tolower(p[i]);
buf[slen] = 0;
}
return true;
@ -88,9 +95,13 @@ const char *HttpFind2ndLevelDomain(const char *host)
const char *p = NULL;
if (*host)
{
for (p = host + strlen(host)-1; p>host && *p!='.'; p--);
if (*p=='.') for (p--; p>host && *p!='.'; p--);
if (*p=='.') p++;
for (p = host + strlen(host) - 1; p > host && *p != '.'; p--)
;
if (*p == '.')
for (p--; p > host && *p != '.'; p--)
;
if (*p == '.')
p++;
}
return p;
}
@ -100,11 +111,13 @@ bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *
char loc[256], *redirect_host, *p;
int code;
if (!host || !*host) return false;
if (!host || !*host)
return false;
code = HttpReplyCode(data, len);
if ((code!=302 && code!=307) || !HttpExtractHeader(data,len,"\nLocation:",loc,sizeof(loc))) return false;
if ((code != 302 && code != 307) || !HttpExtractHeader(data, len, "\nLocation:", loc, sizeof(loc)))
return false;
// something like : https://censor.net/badpage.php?reason=denied&source=RKN
@ -117,9 +130,11 @@ bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *
// somethinkg like : censor.net/badpage.php?reason=denied&source=RKN
for(p=redirect_host; *p && *p!='/' ; p++);
for (p = redirect_host; *p && *p != '/'; p++)
;
*p = 0;
if (!*redirect_host) return false;
if (!*redirect_host)
return false;
// somethinkg like : censor.net
@ -140,17 +155,24 @@ size_t HttpPos(enum httpreqpos tpos_type, size_t hpos_pos, const uint8_t *http,
case httpreqpos_method:
// recognize some tpws pre-applied hacks
method = http;
if (sz<10) break;
if (*method=='\n' || *method=='\r') method++;
if (*method=='\n' || *method=='\r') method++;
for (i=0;i<7;i++) if (*method>='A' && *method<='Z') method++;
if (i<3 || *method!=' ') break;
if (sz < 10)
break;
if (*method == '\n' || *method == '\r')
method++;
if (*method == '\n' || *method == '\r')
method++;
for (i = 0; i < 7; i++)
if (*method >= 'A' && *method <= 'Z')
method++;
if (i < 3 || *method != ' ')
break;
return method - http - 1;
case httpreqpos_host:
if (HttpFindHostConst(&host, http, sz) && (host - http + 7) < sz)
{
host += 5;
if (*host==' ') host++;
if (*host == ' ')
host++;
return host - http;
}
break;
@ -162,7 +184,6 @@ size_t HttpPos(enum httpreqpos tpos_type, size_t hpos_pos, const uint8_t *http,
return hpos_pos < sz ? hpos_pos : 0;
}
uint16_t TLSRecordDataLen(const uint8_t *data)
{
return pntoh16(data + 3);
@ -193,7 +214,6 @@ bool IsTLSHandshakeFull(const uint8_t *data, size_t len)
return (4 + TLSHandshakeLen(data)) <= len;
}
// bPartialIsOK=true - accept partial packets not containing the whole TLS message
bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK)
{
@ -212,40 +232,51 @@ bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const
size_t l;
if (!bPartialIsOK && !IsTLSHandshakeFull(data,len)) return false;
if (!bPartialIsOK && !IsTLSHandshakeFull(data, len))
return false;
l = 1 + 3 + 2 + 32;
// SessionIDLength
if (len < (l + 1)) return false;
if (len < (l + 1))
return false;
l += data[l] + 1;
// CipherSuitesLength
if (len < (l + 2)) return false;
if (len < (l + 2))
return false;
l += pntoh16(data + l) + 2;
// CompressionMethodsLength
if (len < (l + 1)) return false;
if (len < (l + 1))
return false;
l += data[l] + 1;
// ExtensionsLength
if (len < (l + 2)) return false;
if (len < (l + 2))
return false;
data += l; len -= l;
data += l;
len -= l;
l = pntoh16(data);
data += 2; len -= 2;
data += 2;
len -= 2;
if (bPartialIsOK)
{
if (len < l) l = len;
if (len < l)
l = len;
}
else
{
if (len < l) return false;
if (len < l)
return false;
}
while (l >= 4)
{
uint16_t etype = pntoh16(data);
size_t elen = pntoh16(data + 2);
data += 4; l -= 4;
if (l < elen) break;
data += 4;
l -= 4;
if (l < elen)
break;
if (etype == type)
{
if (ext && len_ext)
@ -255,7 +286,8 @@ bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const
}
return true;
}
data += elen; l -= elen;
data += elen;
l -= elen;
}
return false;
@ -267,9 +299,11 @@ bool TLSFindExt(const uint8_t *data, size_t len, uint16_t type, const uint8_t **
// u16 Version: TLS1.0
// u16 Length
size_t reclen;
if (!IsTLSClientHello(data, len, bPartialIsOK)) return false;
if (!IsTLSClientHello(data, len, bPartialIsOK))
return false;
reclen = TLSRecordLen(data);
if (reclen<len) len=reclen; // correct len if it has more data than the first tls record has
if (reclen < len)
len = reclen; // correct len if it has more data than the first tls record has
return TLSFindExtInHandshake(data + 5, len - 5, type, ext, len_ext, bPartialIsOK);
}
static bool TLSExtractHostFromExt(const uint8_t *ext, size_t elen, char *host, size_t len_host)
@ -277,14 +311,19 @@ static bool TLSExtractHostFromExt(const uint8_t *ext, size_t elen, char *host, s
// u16 data+0 - name list length
// u8 data+2 - server name type. 0=host_name
// u16 data+3 - server name length
if (elen < 5 || ext[2] != 0) return false;
if (elen < 5 || ext[2] != 0)
return false;
size_t slen = pntoh16(ext + 3);
ext += 5; elen -= 5;
if (slen < elen) return false;
ext += 5;
elen -= 5;
if (slen < elen)
return false;
if (host && len_host)
{
if (slen >= len_host) slen = len_host - 1;
for (size_t i = 0; i < slen; i++) host[i] = tolower(ext[i]);
if (slen >= len_host)
slen = len_host - 1;
for (size_t i = 0; i < slen; i++)
host[i] = tolower(ext[i]);
host[slen] = 0;
}
return true;
@ -294,7 +333,8 @@ bool TLSHelloExtractHost(const uint8_t *data, size_t len, char *host, size_t len
const uint8_t *ext;
size_t elen;
if (!TLSFindExt(data, len, 0, &ext, &elen, bPartialIsOK)) return false;
if (!TLSFindExt(data, len, 0, &ext, &elen, bPartialIsOK))
return false;
return TLSExtractHostFromExt(ext, elen, host, len_host);
}
bool TLSHelloExtractHostFromHandshake(const uint8_t *data, size_t len, char *host, size_t len_host, bool bPartialIsOK)
@ -302,7 +342,8 @@ bool TLSHelloExtractHostFromHandshake(const uint8_t *data, size_t len, char *hos
const uint8_t *ext;
size_t elen;
if (!TLSFindExtInHandshake(data, len, 0, &ext, &elen, bPartialIsOK)) return false;
if (!TLSFindExtInHandshake(data, len, 0, &ext, &elen, bPartialIsOK))
return false;
return TLSExtractHostFromExt(ext, elen, host, len_host);
}
size_t TLSPos(enum tlspos tpos_type, size_t tpos_pos, const uint8_t *tls, size_t sz, uint8_t type)
@ -323,27 +364,30 @@ size_t TLSPos(enum tlspos tpos_type, size_t tpos_pos, const uint8_t *tls, size_t
}
}
static uint8_t tvb_get_varint(const uint8_t *tvb, uint64_t *value)
{
switch (*tvb >> 6)
{
case 0: /* 0b00 => 1 byte length (6 bits Usable) */
if (value) *value = *tvb & 0x3F;
if (value)
*value = *tvb & 0x3F;
return 1;
case 1: /* 0b01 => 2 bytes length (14 bits Usable) */
if (value) *value = pntoh16(tvb) & 0x3FFF;
if (value)
*value = pntoh16(tvb) & 0x3FFF;
return 2;
case 2: /* 0b10 => 4 bytes length (30 bits Usable) */
if (value) *value = pntoh32(tvb) & 0x3FFFFFFF;
if (value)
*value = pntoh32(tvb) & 0x3FFFFFFF;
return 4;
case 3: /* 0b11 => 8 bytes length (62 bits Usable) */
if (value) *value = pntoh64(tvb) & 0x3FFFFFFFFFFFFFFF;
if (value)
*value = pntoh64(tvb) & 0x3FFFFFFFFFFFFFFF;
return 8;
}
// impossible case
if (*value) *value = 0;
if (*value)
*value = 0;
return 0;
}
static uint8_t tvb_get_size(uint8_t tvb)
@ -355,15 +399,21 @@ bool IsQUICCryptoHello(const uint8_t *data, size_t len, size_t *hello_offset, si
{
size_t offset = 1;
uint64_t coff, clen;
if (len < 3 || *data != 6) return false;
if ((offset+tvb_get_size(data[offset])) >= len) return false;
if (len < 3 || *data != 6)
return false;
if ((offset + tvb_get_size(data[offset])) >= len)
return false;
offset += tvb_get_varint(data + offset, &coff);
// offset must be 0 if it's a full segment, not just a chunk
if (coff || (offset+tvb_get_size(data[offset])) >= len) return false;
if (coff || (offset + tvb_get_size(data[offset])) >= len)
return false;
offset += tvb_get_varint(data + offset, &clen);
if ((offset + clen) > len || !IsTLSHandshakeClientHello(data+offset,clen)) return false;
if (hello_offset) *hello_offset = offset;
if (hello_len) *hello_len = (size_t)clen;
if ((offset + clen) > len || !IsTLSHandshakeClientHello(data + offset, clen))
return false;
if (hello_offset)
*hello_offset = offset;
if (hello_len)
*hello_len = (size_t)clen;
return true;
}
@ -371,22 +421,26 @@ bool IsQUICCryptoHello(const uint8_t *data, size_t len, size_t *hello_offset, si
uint8_t QUICDraftVersion(uint32_t version)
{
/* IETF Draft versions */
if ((version >> 8) == 0xff0000) {
if ((version >> 8) == 0xff0000)
{
return (uint8_t)version;
}
/* Facebook mvfst, based on draft -22. */
if (version == 0xfaceb001) {
if (version == 0xfaceb001)
{
return 22;
}
/* Facebook mvfst, based on draft -27. */
if (version == 0xfaceb002 || version == 0xfaceb00e) {
if (version == 0xfaceb002 || version == 0xfaceb00e)
{
return 27;
}
/* GQUIC Q050, T050 and T051: they are not really based on any drafts,
* but we must return a sensible value */
if (version == 0x51303530 ||
version == 0x54303530 ||
version == 0x54303531) {
version == 0x54303531)
{
return 27;
}
/* https://tools.ietf.org/html/draft-ietf-quic-transport-32#section-15
@ -396,17 +450,20 @@ uint8_t QUICDraftVersion(uint32_t version)
used to select a proper salt (which depends on the version itself), but
we don't have a real version here! Let's hope that we need to handle
only latest drafts... */
if ((version & 0x0F0F0F0F) == 0x0a0a0a0a) {
if ((version & 0x0F0F0F0F) == 0x0a0a0a0a)
{
return 29;
}
/* QUIC (final?) constants for v1 are defined in draft-33, but draft-34 is the
final draft version */
if (version == 0x00000001) {
if (version == 0x00000001)
{
return 34;
}
/* QUIC Version 2 */
/* TODO: for the time being use 100 as a number for V2 and let see how v2 drafts evolve */
if (version == 0x709A50C4) {
if (version == 0x709A50C4)
{
return 100;
}
return 0;
@ -426,9 +483,11 @@ static bool quic_hkdf_expand_label(const uint8_t *secret, uint8_t secret_len, co
uint8_t hkdflabel[64];
size_t label_size = strlen(label);
if (label_size > 255) return false;
if (label_size > 255)
return false;
size_t hkdflabel_size = 2 + 1 + label_size + 1;
if (hkdflabel_size > sizeof(hkdflabel)) return false;
if (hkdflabel_size > sizeof(hkdflabel))
return false;
phton16(hkdflabel, out_len);
hkdflabel[2] = (uint8_t)label_size;
@ -454,69 +513,89 @@ static bool quic_derive_initial_secret(const quic_cid_t *cid, uint8_t *client_in
*/
static const uint8_t handshake_salt_draft_22[20] = {
0x7f, 0xbc, 0xdb, 0x0e, 0x7c, 0x66, 0xbb, 0xe9, 0x19, 0x3a,
0x96, 0xcd, 0x21, 0x51, 0x9e, 0xbd, 0x7a, 0x02, 0x64, 0x4a
};
0x96, 0xcd, 0x21, 0x51, 0x9e, 0xbd, 0x7a, 0x02, 0x64, 0x4a};
static const uint8_t handshake_salt_draft_23[20] = {
0xc3, 0xee, 0xf7, 0x12, 0xc7, 0x2e, 0xbb, 0x5a, 0x11, 0xa7,
0xd2, 0x43, 0x2b, 0xb4, 0x63, 0x65, 0xbe, 0xf9, 0xf5, 0x02,
0xc3,
0xee,
0xf7,
0x12,
0xc7,
0x2e,
0xbb,
0x5a,
0x11,
0xa7,
0xd2,
0x43,
0x2b,
0xb4,
0x63,
0x65,
0xbe,
0xf9,
0xf5,
0x02,
};
static const uint8_t handshake_salt_draft_29[20] = {
0xaf, 0xbf, 0xec, 0x28, 0x99, 0x93, 0xd2, 0x4c, 0x9e, 0x97,
0x86, 0xf1, 0x9c, 0x61, 0x11, 0xe0, 0x43, 0x90, 0xa8, 0x99
};
0x86, 0xf1, 0x9c, 0x61, 0x11, 0xe0, 0x43, 0x90, 0xa8, 0x99};
static const uint8_t handshake_salt_v1[20] = {
0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17,
0x9a, 0xe6, 0xa4, 0xc8, 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a
};
0x9a, 0xe6, 0xa4, 0xc8, 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a};
static const uint8_t hanshake_salt_draft_q50[20] = {
0x50, 0x45, 0x74, 0xEF, 0xD0, 0x66, 0xFE, 0x2F, 0x9D, 0x94,
0x5C, 0xFC, 0xDB, 0xD3, 0xA7, 0xF0, 0xD3, 0xB5, 0x6B, 0x45
};
0x5C, 0xFC, 0xDB, 0xD3, 0xA7, 0xF0, 0xD3, 0xB5, 0x6B, 0x45};
static const uint8_t hanshake_salt_draft_t50[20] = {
0x7f, 0xf5, 0x79, 0xe5, 0xac, 0xd0, 0x72, 0x91, 0x55, 0x80,
0x30, 0x4c, 0x43, 0xa2, 0x36, 0x7c, 0x60, 0x48, 0x83, 0x10
};
0x30, 0x4c, 0x43, 0xa2, 0x36, 0x7c, 0x60, 0x48, 0x83, 0x10};
static const uint8_t hanshake_salt_draft_t51[20] = {
0x7a, 0x4e, 0xde, 0xf4, 0xe7, 0xcc, 0xee, 0x5f, 0xa4, 0x50,
0x6c, 0x19, 0x12, 0x4f, 0xc8, 0xcc, 0xda, 0x6e, 0x03, 0x3d
};
0x6c, 0x19, 0x12, 0x4f, 0xc8, 0xcc, 0xda, 0x6e, 0x03, 0x3d};
static const uint8_t handshake_salt_v2[20] = {
0x0d, 0xed, 0xe3, 0xde, 0xf7, 0x00, 0xa6, 0xdb, 0x81, 0x93,
0x81, 0xbe, 0x6e, 0x26, 0x9d, 0xcb, 0xf9, 0xbd, 0x2e, 0xd9
};
0x81, 0xbe, 0x6e, 0x26, 0x9d, 0xcb, 0xf9, 0xbd, 0x2e, 0xd9};
int err;
const uint8_t *salt;
uint8_t secret[USHAMaxHashSize];
uint8_t draft_version = QUICDraftVersion(version);
if (version == 0x51303530) {
if (version == 0x51303530)
{
salt = hanshake_salt_draft_q50;
}
else if (version == 0x54303530) {
else if (version == 0x54303530)
{
salt = hanshake_salt_draft_t50;
}
else if (version == 0x54303531) {
else if (version == 0x54303531)
{
salt = hanshake_salt_draft_t51;
}
else if (is_quic_draft_max(draft_version, 22)) {
else if (is_quic_draft_max(draft_version, 22))
{
salt = handshake_salt_draft_22;
}
else if (is_quic_draft_max(draft_version, 28)) {
else if (is_quic_draft_max(draft_version, 28))
{
salt = handshake_salt_draft_23;
}
else if (is_quic_draft_max(draft_version, 32)) {
else if (is_quic_draft_max(draft_version, 32))
{
salt = handshake_salt_draft_29;
}
else if (is_quic_draft_max(draft_version, 34)) {
else if (is_quic_draft_max(draft_version, 34))
{
salt = handshake_salt_v1;
}
else {
else
{
salt = handshake_salt_v2;
}
err = hkdfExtract(SHA256, salt, 20, cid->cid, cid->len, secret);
if (err) return false;
if (err)
return false;
if (client_initial_secret && !quic_hkdf_expand_label(secret, SHA256HashSize, "tls13 client in", client_initial_secret, SHA256HashSize))
return false;
@ -534,7 +613,8 @@ uint32_t QUICExtractVersion(const uint8_t *data, size_t len)
}
bool QUICExtractDCID(const uint8_t *data, size_t len, quic_cid_t *cid)
{
if (!QUICIsLongHeader(data,len) || !data[5] || data[5] > QUIC_MAX_CID_LENGTH || (6+data[5])>len) return false;
if (!QUICIsLongHeader(data, len) || !data[5] || data[5] > QUIC_MAX_CID_LENGTH || (6 + data[5]) > len)
return false;
cid->len = data[5];
memcpy(&cid->cid, data + 6, data[5]);
return true;
@ -542,13 +622,16 @@ bool QUICExtractDCID(const uint8_t *data, size_t len, quic_cid_t *cid)
bool QUICDecryptInitial(const uint8_t *data, size_t data_len, uint8_t *clean, size_t *clean_len)
{
uint32_t ver = QUICExtractVersion(data, data_len);
if (!ver) return false;
if (!ver)
return false;
quic_cid_t dcid;
if (!QUICExtractDCID(data, data_len, &dcid)) return false;
if (!QUICExtractDCID(data, data_len, &dcid))
return false;
uint8_t client_initial_secret[SHA256HashSize];
if (!quic_derive_initial_secret(&dcid, client_initial_secret, ver)) return false;
if (!quic_derive_initial_secret(&dcid, client_initial_secret, ver))
return false;
uint8_t aeskey[16], aesiv[12], aeshp[16];
bool v1_label = !is_quic_v2(ver);
@ -562,20 +645,25 @@ bool QUICDecryptInitial(const uint8_t *data, size_t data_len, uint8_t *clean, si
uint64_t payload_len, token_len;
size_t pn_offset;
pn_offset = 1 + 4 + 1 + data[5];
if (pn_offset >= data_len) return false;
if (pn_offset >= data_len)
return false;
pn_offset += 1 + data[pn_offset];
if ((pn_offset + tvb_get_size(data[pn_offset])) >= data_len) return false;
if ((pn_offset + tvb_get_size(data[pn_offset])) >= data_len)
return false;
pn_offset += tvb_get_varint(data + pn_offset, &token_len);
pn_offset += token_len;
if ((pn_offset + tvb_get_size(data[pn_offset])) >= data_len) return false;
if ((pn_offset + tvb_get_size(data[pn_offset])) >= data_len)
return false;
pn_offset += tvb_get_varint(data + pn_offset, &payload_len);
if (payload_len<20 || (pn_offset + payload_len)>data_len) return false;
if (payload_len < 20 || (pn_offset + payload_len) > data_len)
return false;
aes_init_keygen_tables();
uint8_t sample_enc[16];
aes_context ctx;
if (aes_setkey(&ctx, 1, aeshp, sizeof(aeshp)) || aes_cipher(&ctx, data + pn_offset + 4, sample_enc)) return false;
if (aes_setkey(&ctx, 1, aeshp, sizeof(aeshp)) || aes_cipher(&ctx, data + pn_offset + 4, sample_enc))
return false;
uint8_t mask[5];
memcpy(mask, sample_enc, sizeof(mask));
@ -586,21 +674,25 @@ bool QUICDecryptInitial(const uint8_t *data, size_t data_len, uint8_t *clean, si
uint8_t pkn_bytes[4];
memcpy(pkn_bytes, data + pn_offset, pkn_len);
uint32_t pkn = 0;
for (uint8_t i = 0; i < pkn_len; i++) pkn |= (uint32_t)(pkn_bytes[i] ^ mask[1 + i]) << (8 * (pkn_len - 1 - i));
for (uint8_t i = 0; i < pkn_len; i++)
pkn |= (uint32_t)(pkn_bytes[i] ^ mask[1 + i]) << (8 * (pkn_len - 1 - i));
phton64(aesiv + sizeof(aesiv) - 8, pntoh64(aesiv + sizeof(aesiv) - 8) ^ pkn);
size_t cryptlen = payload_len - pkn_len - 16;
if (cryptlen > *clean_len) return false;
if (cryptlen > *clean_len)
return false;
*clean_len = cryptlen;
const uint8_t *decrypt_begin = data + pn_offset + pkn_len;
uint8_t atag[16], header[256];
size_t header_len = pn_offset + pkn_len;
if (header_len > sizeof(header)) return false; // not likely header will be so large
if (header_len > sizeof(header))
return false; // not likely header will be so large
memcpy(header, data, header_len);
header[0] = packet0;
for(uint8_t i = 0; i < pkn_len; i++) header[header_len - 1 - i] = (uint8_t)(pkn >> (8 * i));
for (uint8_t i = 0; i < pkn_len; i++)
header[header_len - 1 - i] = (uint8_t)(pkn >> (8 * i));
if (aes_gcm_crypt(AES_DECRYPT, clean, decrypt_begin, cryptlen, aeskey, sizeof(aeskey), aesiv, sizeof(aesiv), header, header_len, atag, sizeof(atag)))
return false;
@ -615,7 +707,8 @@ bool QUICDefragCrypto(const uint8_t *clean,size_t clean_len, uint8_t *defrag,siz
// chromium randomly splits it and pads with zero/one bytes to force support the standard
// mozilla does not split
if (*defrag_len<10) return false;
if (*defrag_len < 10)
return false;
uint8_t *defrag_data = defrag + 10;
size_t defrag_data_len = *defrag_len - 10;
@ -629,25 +722,32 @@ bool QUICDefragCrypto(const uint8_t *clean,size_t clean_len, uint8_t *defrag,siz
pos++;
if (ft > 1) // 00 - padding, 01 - ping
{
if (ft!=6) return false; // dont want to know all possible frame type formats
if (ft != 6)
return false; // don't want to know all possible frame type formats
if (pos>=clean_len) return false;
if (pos >= clean_len)
return false;
if ((pos+tvb_get_size(clean[pos])>=clean_len)) return false;
if ((pos + tvb_get_size(clean[pos]) >= clean_len))
return false;
pos += tvb_get_varint(clean + pos, &offset);
if ((pos+tvb_get_size(clean[pos])>clean_len)) return false;
if ((pos + tvb_get_size(clean[pos]) > clean_len))
return false;
pos += tvb_get_varint(clean + pos, &sz);
if ((pos+sz)>clean_len) return false;
if ((pos + sz) > clean_len)
return false;
if ((offset+sz)>defrag_data_len) return false;
if ((offset + sz) > defrag_data_len)
return false;
if (zeropos < offset)
// make sure no uninitialized gaps exist in case of not full fragment coverage
memset(defrag_data + zeropos, 0, offset - zeropos);
if ((offset + sz) > zeropos)
zeropos = offset + sz;
memcpy(defrag_data + offset, clean + pos, sz);
if ((offset+sz) > szmax) szmax = offset+sz;
if ((offset + sz) > szmax)
szmax = offset + sz;
found = true;
pos += sz;
@ -668,22 +768,29 @@ bool QUICDefragCrypto(const uint8_t *clean,size_t clean_len, uint8_t *defrag,siz
bool QUICExtractHostFromInitial(const uint8_t *data, size_t data_len, char *host, size_t len_host, bool *bDecryptOK, bool *bIsCryptoHello)
{
if (bIsCryptoHello) *bIsCryptoHello=false;
if (bDecryptOK) *bDecryptOK=false;
if (bIsCryptoHello)
*bIsCryptoHello = false;
if (bDecryptOK)
*bDecryptOK = false;
uint8_t clean[1500];
size_t clean_len = sizeof(clean);
if (!QUICDecryptInitial(data,data_len,clean,&clean_len)) return false;
if (!QUICDecryptInitial(data, data_len, clean, &clean_len))
return false;
if (bDecryptOK) *bDecryptOK=true;
if (bDecryptOK)
*bDecryptOK = true;
uint8_t defrag[1500];
size_t defrag_len = sizeof(defrag);
if (!QUICDefragCrypto(clean,clean_len,defrag,&defrag_len)) return false;
if (!QUICDefragCrypto(clean, clean_len, defrag, &defrag_len))
return false;
size_t hello_offset, hello_len;
if (!IsQUICCryptoHello(defrag, defrag_len, &hello_offset, &hello_len)) return false;
if (bIsCryptoHello) *bIsCryptoHello=true;
if (!IsQUICCryptoHello(defrag, defrag_len, &hello_offset, &hello_len))
return false;
if (bIsCryptoHello)
*bIsCryptoHello = true;
return TLSHelloExtractHostFromHandshake(defrag + hello_offset, hello_len, host, len_host, true);
}
@ -692,42 +799,48 @@ bool IsQUICInitial(const uint8_t *data, size_t len)
{
// too small packets are not likely to be initials with client hello
// long header, fixed bit
if (len < 256 || (data[0] & 0xC0)!=0xC0) return false;
if (len < 256 || (data[0] & 0xC0) != 0xC0)
return false;
uint32_t ver = QUICExtractVersion(data, len);
if (QUICDraftVersion(ver) < 11) return false;
if (QUICDraftVersion(ver) < 11)
return false;
// quic v1 : initial packets are 00b
// quic v2 : initial packets are 01b
if ((data[0] & 0x30) != (is_quic_v2(ver) ? 0x10 : 0x00)) return false;
// QUIC v1 : initial packets are 00b
// QUIC v2 : initial packets are 01b
if ((data[0] & 0x30) != (is_quic_v2(ver) ? 0x10 : 0x00))
return false;
uint64_t offset = 5, sz;
// DCID. must be present
if (!data[offset] || data[offset] > QUIC_MAX_CID_LENGTH) return false;
if (!data[offset] || data[offset] > QUIC_MAX_CID_LENGTH)
return false;
offset += 1 + data[offset];
// SCID
if (data[offset] > QUIC_MAX_CID_LENGTH) return false;
if (data[offset] > QUIC_MAX_CID_LENGTH)
return false;
offset += 1 + data[offset];
// token length
offset += tvb_get_varint(data + offset, &sz);
offset += sz;
if (offset >= len) return false;
if (offset >= len)
return false;
// payload length
if ((offset + tvb_get_size(data[offset])) > len) return false;
if ((offset + tvb_get_size(data[offset])) > len)
return false;
tvb_get_varint(data + offset, &sz);
offset += sz;
if (offset > len) return false;
if (offset > len)
return false;
// client hello cannot be too small. likely ACK
// ClientHello cannot be too small. likely ACK
return sz >= 96;
}
bool IsWireguardHandshakeInitiation(const uint8_t *data, size_t len)
{
return len == 148 && data[0] == 1 && data[1] == 0 && data[2] == 0 && data[3] == 0;

View File

@ -21,7 +21,13 @@ const char *HttpFind2ndLevelDomain(const char *host);
int HttpReplyCode(const uint8_t *data, size_t len);
// must be pre-checked by IsHttpReply
bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *host);
enum httpreqpos { httpreqpos_none = 0, httpreqpos_method, httpreqpos_host, httpreqpos_pos };
enum httpreqpos
{
httpreqpos_none = 0,
httpreqpos_method,
httpreqpos_host,
httpreqpos_pos
};
size_t HttpPos(enum httpreqpos tpos_type, size_t hpos_pos, const uint8_t *http, size_t sz);
uint16_t TLSRecordDataLen(const uint8_t *data);
@ -35,14 +41,21 @@ bool TLSFindExt(const uint8_t *data, size_t len, uint16_t type, const uint8_t **
bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK);
bool TLSHelloExtractHost(const uint8_t *data, size_t len, char *host, size_t len_host, bool bPartialIsOK);
bool TLSHelloExtractHostFromHandshake(const uint8_t *data, size_t len, char *host, size_t len_host, bool bPartialIsOK);
enum tlspos { tlspos_none = 0, tlspos_sni, tlspos_sniext, tlspos_pos };
enum tlspos
{
tlspos_none = 0,
tlspos_sni,
tlspos_sniext,
tlspos_pos
};
size_t TLSPos(enum tlspos tpos_type, size_t tpos_pos, const uint8_t *tls, size_t sz, uint8_t type);
bool IsWireguardHandshakeInitiation(const uint8_t *data, size_t len);
bool IsDhtD1(const uint8_t *data, size_t len);
#define QUIC_MAX_CID_LENGTH 20
typedef struct quic_cid {
typedef struct quic_cid
{
uint8_t len;
uint8_t cid[QUIC_MAX_CID_LENGTH];
} quic_cid_t;

View File

@ -144,8 +144,7 @@ SYS_tkill,
#ifdef SYS_tgkill
SYS_tgkill,
#endif
SYS_kill, SYS_ptrace
};
SYS_kill, SYS_ptrace};
#define BLOCKED_SYSCALL_COUNT (sizeof(blocked_syscalls) / sizeof(*blocked_syscalls))
static void set_filter(struct sock_filter *filter, __u16 code, __u8 jt, __u8 jf, __u32 k)
@ -205,19 +204,18 @@ bool sec_harden(void)
if (!set_seccomp())
{
DLOG_PERROR("seccomp");
if (errno==EINVAL) DLOG_ERR("seccomp: this can be safely ignored if kernel does not support seccomp\n");
if (errno == EINVAL)
DLOG_ERR("seccomp: this can be safely ignored if kernel does not support seccomp\n");
return false;
}
#endif
return true;
}
bool checkpcap(uint64_t caps)
{
if (!caps) return true; // no special caps reqd
if (!caps)
return true; // no special caps reqd
struct __user_cap_header_struct ch = {_LINUX_CAPABILITY_VERSION_3, getpid()};
struct __user_cap_data_struct cd[2];
@ -248,7 +246,6 @@ int getmaxcap(void)
fclose(F);
}
return maxcap;
}
bool dropcaps(void)
{
@ -349,7 +346,6 @@ void print_id(void)
#endif
void daemonize(void)
{
int pid;

View File

@ -53,7 +53,7 @@ bool dropcaps(void);
#define ARCH_NR AUDIT_ARCH_MIPS64
#endif
#else
# error "Unsupported mips abi"
#error "Unsupported MIPS ABI"
#endif
#elif defined(__PPC64__)
@ -80,7 +80,6 @@ bool dropcaps(void);
#endif
#ifndef __CYGWIN__
bool sec_harden(void);
bool can_drop_root(void);

File diff suppressed because it is too large Load Diff

View File

@ -18,8 +18,7 @@ bool service_run(int argc, char *argv[])
{
SERVICE_TABLE_ENTRY ServiceTable[] = {
{SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)service_main},
{NULL, NULL}
};
{NULL, NULL}};
service_argc = argc;
service_argv = argv;
@ -76,5 +75,4 @@ void service_main(int argc __attribute__((unused)), char *argv[] __attribute__((
return;
}
#endif

View File

@ -7,4 +7,3 @@
bool service_run();
#endif

View File

@ -62,7 +62,8 @@
#endif /* __MINGW32__ */
#ifdef __cplusplus
extern "C" {
extern "C"
{
#endif
/****************************************************************************/
@ -79,7 +80,8 @@ typedef enum
WINDIVERT_LAYER_FLOW = 2, /* Flow layer. */
WINDIVERT_LAYER_SOCKET = 3, /* Socket layer. */
WINDIVERT_LAYER_REFLECT = 4, /* Reflect layer. */
} WINDIVERT_LAYER, *PWINDIVERT_LAYER;
} WINDIVERT_LAYER,
*PWINDIVERT_LAYER;
/*
* WinDivert NETWORK and NETWORK_FORWARD layer data.
@ -183,7 +185,8 @@ typedef enum
WINDIVERT_EVENT_SOCKET_CLOSE = 7, /* Socket close. */
WINDIVERT_EVENT_REFLECT_OPEN = 8, /* WinDivert handle opened. */
WINDIVERT_EVENT_REFLECT_CLOSE = 9, /* WinDivert handle closed. */
} WINDIVERT_EVENT, *PWINDIVERT_EVENT;
} WINDIVERT_EVENT,
*PWINDIVERT_EVENT;
/*
* WinDivert flags.
@ -207,7 +210,8 @@ typedef enum
WINDIVERT_PARAM_QUEUE_SIZE = 2, /* Packet queue size. */
WINDIVERT_PARAM_VERSION_MAJOR = 3, /* Driver version (major). */
WINDIVERT_PARAM_VERSION_MINOR = 4, /* Driver version (minor). */
} WINDIVERT_PARAM, *PWINDIVERT_PARAM;
} WINDIVERT_PARAM,
*PWINDIVERT_PARAM;
#define WINDIVERT_PARAM_MAX WINDIVERT_PARAM_VERSION_MINOR
/*
@ -218,7 +222,8 @@ typedef enum
WINDIVERT_SHUTDOWN_RECV = 0x1, /* Shutdown recv. */
WINDIVERT_SHUTDOWN_SEND = 0x2, /* Shutdown send. */
WINDIVERT_SHUTDOWN_BOTH = 0x3, /* Shutdown recv and send. */
} WINDIVERT_SHUTDOWN, *PWINDIVERT_SHUTDOWN;
} WINDIVERT_SHUTDOWN,
*PWINDIVERT_SHUTDOWN;
#define WINDIVERT_SHUTDOWN_MAX WINDIVERT_SHUTDOWN_BOTH
#ifndef WINDIVERT_KERNEL
@ -367,29 +372,25 @@ typedef struct
{ \
(hdr)->FragOff0 = (((hdr)->FragOff0) & 0x00E0) | \
((val) & 0xFF1F); \
} \
while (FALSE)
} while (FALSE)
#define WINDIVERT_IPHDR_SET_MF(hdr, val) \
do \
{ \
(hdr)->FragOff0 = (((hdr)->FragOff0) & 0xFFDF) | \
(((val) & 0x0001) << 5); \
} \
while (FALSE)
} while (FALSE)
#define WINDIVERT_IPHDR_SET_DF(hdr, val) \
do \
{ \
(hdr)->FragOff0 = (((hdr)->FragOff0) & 0xFFBF) | \
(((val) & 0x0001) << 6); \
} \
while (FALSE)
} while (FALSE)
#define WINDIVERT_IPHDR_SET_RESERVED(hdr, val) \
do \
{ \
(hdr)->FragOff0 = (((hdr)->FragOff0) & 0xFF7F) | \
(((val) & 0x0001) << 7); \
} \
while (FALSE)
} while (FALSE)
typedef struct
{
@ -415,15 +416,13 @@ typedef struct
{ \
(hdr)->TrafficClass0 = ((UINT8)(val) >> 4); \
(hdr)->TrafficClass1 = (UINT8)(val); \
} \
while (FALSE)
} while (FALSE)
#define WINDIVERT_IPV6HDR_SET_FLOWLABEL(hdr, val) \
do \
{ \
(hdr)->FlowLabel0 = (UINT8)((val) >> 16); \
(hdr)->FlowLabel1 = (UINT16)(val); \
} \
while (FALSE)
} while (FALSE)
typedef struct
{

View File

@ -2,7 +2,8 @@
#define SHIM_SYS_EPOLL_H
#ifdef __cplusplus
extern "C" {
extern "C"
{
#endif
#include <stdint.h>
@ -18,7 +19,10 @@ extern "C" {
#define EPOLL_CLOEXEC O_CLOEXEC
#define EPOLL_NONBLOCK O_NONBLOCK
enum EPOLL_EVENTS { __EPOLL_DUMMY };
enum EPOLL_EVENTS
{
__EPOLL_DUMMY
};
#define EPOLLIN 0x001
#define EPOLLPRI 0x002
#define EPOLLOUT 0x004
@ -40,14 +44,16 @@ enum EPOLL_EVENTS { __EPOLL_DUMMY };
#define EPOLL_CTL_DEL 2
#define EPOLL_CTL_MOD 3
typedef union epoll_data {
typedef union epoll_data
{
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
struct epoll_event {
struct epoll_event
{
uint32_t events;
epoll_data_t data;
}
@ -56,14 +62,12 @@ __attribute__ ((__packed__))
#endif
;
int epoll_create(int);
int epoll_create1(int);
int epoll_ctl(int, int, int, struct epoll_event *);
int epoll_wait(int, struct epoll_event *, int, int);
int epoll_pwait(int, struct epoll_event *, int, int, const sigset_t *);
#ifndef SHIM_SYS_SHIM_HELPERS
#define SHIM_SYS_SHIM_HELPERS
#include <unistd.h> /* IWYU pragma: keep */
@ -72,7 +76,6 @@ extern int epoll_shim_close(int);
#define close epoll_shim_close
#endif
#ifdef __cplusplus
}
#endif

View File

@ -22,10 +22,12 @@
// all supported FreeBSD versions.
#ifndef timespecsub
#define timespecsub(tsp, usp, vsp) \
do { \
do \
{ \
(vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \
(vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \
if ((vsp)->tv_nsec < 0) { \
if ((vsp)->tv_nsec < 0) \
{ \
(vsp)->tv_sec--; \
(vsp)->tv_nsec += 1000000000L; \
} \
@ -50,14 +52,16 @@ epoll_create_impl(errno_t *ec)
FDContextMapNode *node;
node = epoll_shim_ctx_create_node(&epoll_shim_ctx, ec);
if (!node) {
if (!node)
{
return NULL;
}
node->flags = 0;
if ((*ec = epollfd_ctx_init(&node->ctx.epollfd, /**/
node->fd)) != 0) {
node->fd)) != 0)
{
goto fail;
}
@ -77,7 +81,8 @@ epoll_create_common(void)
errno_t ec;
node = epoll_create_impl(&ec);
if (!node) {
if (!node)
{
errno = ec;
return -1;
}
@ -85,10 +90,10 @@ epoll_create_common(void)
return node->fd;
}
int
epoll_create(int size)
int epoll_create(int size)
{
if (size <= 0)
{
if (size <= 0) {
errno = EINVAL;
return -1;
}
@ -96,10 +101,10 @@ epoll_create(int size)
return epoll_create_common();
}
int
epoll_create1(int flags)
int epoll_create1(int flags)
{
if (flags & ~EPOLL_CLOEXEC)
{
if (flags & ~EPOLL_CLOEXEC) {
errno = EINVAL;
return -1;
}
@ -110,12 +115,14 @@ epoll_create1(int flags)
static errno_t
epoll_ctl_impl(int fd, int op, int fd2, struct epoll_event *ev)
{
if (!ev && op != EPOLL_CTL_DEL) {
if (!ev && op != EPOLL_CTL_DEL)
{
return EFAULT;
}
FDContextMapNode *node = epoll_shim_ctx_find_node(&epoll_shim_ctx, fd);
if (!node || node->vtable != &epollfd_vtable) {
if (!node || node->vtable != &epollfd_vtable)
{
struct stat sb;
return (fd < 0 || fstat(fd, &sb) < 0) ? EBADF : EINVAL;
}
@ -123,11 +130,11 @@ epoll_ctl_impl(int fd, int op, int fd2, struct epoll_event *ev)
return epollfd_ctx_ctl(&node->ctx.epollfd, op, fd2, ev);
}
int
epoll_ctl(int fd, int op, int fd2, struct epoll_event *ev)
int epoll_ctl(int fd, int op, int fd2, struct epoll_event *ev)
{
errno_t ec = epoll_ctl_impl(fd, op, fd2, ev);
if (ec != 0) {
if (ec != 0)
{
errno = ec;
return -1;
}
@ -147,29 +154,35 @@ epollfd_ctx_wait_or_block(EpollFDCtx *epollfd, struct epoll_event *ev, int cnt,
{
errno_t ec;
for (;;) {
for (;;)
{
if ((ec = epollfd_ctx_wait(epollfd, /**/
ev, cnt, actual_cnt)) != 0) {
ev, cnt, actual_cnt)) != 0)
{
return ec;
}
if (*actual_cnt || is_no_wait_deadline(deadline)) {
if (*actual_cnt || is_no_wait_deadline(deadline))
{
return 0;
}
struct timespec timeout;
if (deadline) {
if (deadline)
{
struct timespec current_time;
if (clock_gettime(CLOCK_MONOTONIC, /**/
&current_time) < 0) {
&current_time) < 0)
{
return errno;
}
timespecsub(deadline, &current_time, &timeout);
if (timeout.tv_sec < 0 ||
is_no_wait_deadline(&timeout)) {
is_no_wait_deadline(&timeout))
{
return 0;
}
}
@ -180,14 +193,16 @@ epollfd_ctx_wait_or_block(EpollFDCtx *epollfd, struct epoll_event *ev, int cnt,
size_t size;
if (__builtin_mul_overflow(nfds, sizeof(struct pollfd),
&size)) {
&size))
{
ec = ENOMEM;
(void)pthread_mutex_unlock(&epollfd->mutex);
return ec;
}
struct pollfd *pfds = malloc(size);
if (!pfds) {
if (!pfds)
{
ec = errno;
(void)pthread_mutex_unlock(&epollfd->mutex);
return ec;
@ -211,7 +226,8 @@ epollfd_ctx_wait_or_block(EpollFDCtx *epollfd, struct epoll_event *ev, int cnt,
#endif
int n = ppoll(pfds, nfds, deadline ? &timeout : NULL, sigs);
if (n < 0) {
if (n < 0)
{
ec = errno;
}
@ -219,13 +235,15 @@ epollfd_ctx_wait_or_block(EpollFDCtx *epollfd, struct epoll_event *ev, int cnt,
(void)pthread_mutex_lock(&epollfd->nr_polling_threads_mutex);
--epollfd->nr_polling_threads;
if (epollfd->nr_polling_threads == 0) {
if (epollfd->nr_polling_threads == 0)
{
(void)pthread_cond_signal(
&epollfd->nr_polling_threads_cond);
}
(void)pthread_mutex_unlock(&epollfd->nr_polling_threads_mutex);
if (n < 0) {
if (n < 0)
{
return ec;
}
}
@ -236,21 +254,27 @@ timeout_to_deadline(struct timespec *deadline, int to)
{
assert(to >= 0);
if (to == 0) {
if (to == 0)
{
*deadline = (struct timespec){0, 0};
} else if (to > 0) {
if (clock_gettime(CLOCK_MONOTONIC, deadline) < 0) {
}
else if (to > 0)
{
if (clock_gettime(CLOCK_MONOTONIC, deadline) < 0)
{
return errno;
}
if (__builtin_add_overflow(deadline->tv_sec, to / 1000 + 1,
&deadline->tv_sec)) {
&deadline->tv_sec))
{
return EINVAL;
}
deadline->tv_sec -= 1;
deadline->tv_nsec += (to % 1000) * 1000000L;
if (deadline->tv_nsec >= 1000000000) {
if (deadline->tv_nsec >= 1000000000)
{
deadline->tv_nsec -= 1000000000;
deadline->tv_sec += 1;
}
@ -263,19 +287,22 @@ static errno_t
epoll_pwait_impl(int fd, struct epoll_event *ev, int cnt, int to,
sigset_t const *sigs, int *actual_cnt)
{
if (cnt < 1 || cnt > (int)(INT_MAX / sizeof(struct epoll_event))) {
if (cnt < 1 || cnt > (int)(INT_MAX / sizeof(struct epoll_event)))
{
return EINVAL;
}
FDContextMapNode *node = epoll_shim_ctx_find_node(&epoll_shim_ctx, fd);
if (!node || node->vtable != &epollfd_vtable) {
if (!node || node->vtable != &epollfd_vtable)
{
struct stat sb;
return (fd < 0 || fstat(fd, &sb) < 0) ? EBADF : EINVAL;
}
struct timespec deadline;
errno_t ec;
if (to >= 0 && (ec = timeout_to_deadline(&deadline, to)) != 0) {
if (to >= 0 && (ec = timeout_to_deadline(&deadline, to)) != 0)
{
return ec;
}
@ -283,14 +310,14 @@ epoll_pwait_impl(int fd, struct epoll_event *ev, int cnt, int to,
actual_cnt, (to >= 0) ? &deadline : NULL, sigs);
}
int
epoll_pwait(int fd, struct epoll_event *ev, int cnt, int to,
int epoll_pwait(int fd, struct epoll_event *ev, int cnt, int to,
sigset_t const *sigs)
{
int actual_cnt;
errno_t ec = epoll_pwait_impl(fd, ev, cnt, to, sigs, &actual_cnt);
if (ec != 0) {
if (ec != 0)
{
errno = ec;
return -1;
}
@ -298,8 +325,7 @@ epoll_pwait(int fd, struct epoll_event *ev, int cnt, int to,
return actual_cnt;
}
int
epoll_wait(int fd, struct epoll_event *ev, int cnt, int to)
int epoll_wait(int fd, struct epoll_event *ev, int cnt, int to)
{
return epoll_pwait(fd, ev, cnt, to, NULL);
}

View File

@ -20,7 +20,8 @@ fd_context_map_node_create(int kq, errno_t *ec)
FDContextMapNode *node;
node = malloc(sizeof(FDContextMapNode));
if (!node) {
if (!node)
{
*ec = errno;
return NULL;
}
@ -34,7 +35,8 @@ fd_context_map_node_terminate(FDContextMapNode *node, bool close_fd)
{
errno_t ec = node->vtable ? node->vtable->close_fun(node) : 0;
if (close_fd && close(node->fd) < 0) {
if (close_fd && close(node->fd) < 0)
{
ec = ec ? ec : errno;
}
@ -107,7 +109,8 @@ epoll_shim_ctx_create_node_impl(EpollShimCtx *epoll_shim_ctx, int kq,
&epoll_shim_ctx->fd_context_map, &find);
}
if (node) {
if (node)
{
/*
* If we get here, someone must have already closed the old fd
* with a normal 'close()' call, i.e. not with our
@ -118,9 +121,12 @@ epoll_shim_ctx_create_node_impl(EpollShimCtx *epoll_shim_ctx, int kq,
*/
(void)fd_context_map_node_terminate(node, false);
fd_context_map_node_init(node, kq);
} else {
}
else
{
node = fd_context_map_node_create(kq, ec);
if (!node) {
if (!node)
{
return NULL;
}
@ -139,7 +145,8 @@ epoll_shim_ctx_create_node(EpollShimCtx *epoll_shim_ctx, errno_t *ec)
FDContextMapNode *node;
int kq = kqueue();
if (kq < 0) {
if (kq < 0)
{
*ec = errno;
return NULL;
}
@ -148,7 +155,8 @@ epoll_shim_ctx_create_node(EpollShimCtx *epoll_shim_ctx, errno_t *ec)
node = epoll_shim_ctx_create_node_impl(epoll_shim_ctx, kq, ec);
(void)pthread_mutex_unlock(&epoll_shim_ctx->mutex);
if (!node) {
if (!node)
{
close(kq);
}
@ -188,7 +196,8 @@ epoll_shim_ctx_remove_node(EpollShimCtx *epoll_shim_ctx, int fd)
(void)pthread_mutex_lock(&epoll_shim_ctx->mutex);
node = epoll_shim_ctx_find_node_impl(epoll_shim_ctx, fd);
if (node) {
if (node)
{
RB_REMOVE(fd_context_map_, /**/
&epoll_shim_ctx->fd_context_map, node);
}
@ -197,8 +206,7 @@ epoll_shim_ctx_remove_node(EpollShimCtx *epoll_shim_ctx, int fd)
return node;
}
void
epoll_shim_ctx_remove_node_explicit(EpollShimCtx *epoll_shim_ctx,
void epoll_shim_ctx_remove_node_explicit(EpollShimCtx *epoll_shim_ctx,
FDContextMapNode *node)
{
(void)pthread_mutex_lock(&epoll_shim_ctx->mutex);
@ -209,18 +217,19 @@ epoll_shim_ctx_remove_node_explicit(EpollShimCtx *epoll_shim_ctx,
/**/
int
epoll_shim_close(int fd)
int epoll_shim_close(int fd)
{
FDContextMapNode *node;
node = epoll_shim_ctx_remove_node(&epoll_shim_ctx, fd);
if (!node) {
if (!node)
{
return close(fd);
}
errno_t ec = fd_context_map_node_destroy(node);
if (ec != 0) {
if (ec != 0)
{
errno = ec;
return -1;
}
@ -234,11 +243,13 @@ epoll_shim_read(int fd, void *buf, size_t nbytes)
FDContextMapNode *node;
node = epoll_shim_ctx_find_node(&epoll_shim_ctx, fd);
if (!node) {
if (!node)
{
return read(fd, buf, nbytes);
}
if (nbytes > SSIZE_MAX) {
if (nbytes > SSIZE_MAX)
{
errno = EINVAL;
return -1;
}
@ -246,7 +257,8 @@ epoll_shim_read(int fd, void *buf, size_t nbytes)
size_t bytes_transferred;
errno_t ec = node->vtable->read_fun(node, /**/
buf, nbytes, &bytes_transferred);
if (ec != 0) {
if (ec != 0)
{
errno = ec;
return -1;
}
@ -260,11 +272,13 @@ epoll_shim_write(int fd, void const *buf, size_t nbytes)
FDContextMapNode *node;
node = epoll_shim_ctx_find_node(&epoll_shim_ctx, fd);
if (!node) {
if (!node)
{
return write(fd, buf, nbytes);
}
if (nbytes > SSIZE_MAX) {
if (nbytes > SSIZE_MAX)
{
errno = EINVAL;
return -1;
}
@ -272,7 +286,8 @@ epoll_shim_write(int fd, void const *buf, size_t nbytes)
size_t bytes_transferred;
errno_t ec = node->vtable->write_fun(node, /**/
buf, nbytes, &bytes_transferred);
if (ec != 0) {
if (ec != 0)
{
errno = ec;
return -1;
}

View File

@ -21,7 +21,8 @@ typedef errno_t (*fd_context_write_fun)(FDContextMapNode *node, /**/
const void *buf, size_t nbytes, size_t *bytes_transferred);
typedef errno_t (*fd_context_close_fun)(FDContextMapNode *node);
typedef struct {
typedef struct
{
fd_context_read_fun read_fun;
fd_context_write_fun write_fun;
fd_context_close_fun close_fun;
@ -32,11 +33,14 @@ errno_t fd_context_default_read(FDContextMapNode *node, /**/
errno_t fd_context_default_write(FDContextMapNode *node, /**/
void const *buf, size_t nbytes, size_t *bytes_transferred);
struct fd_context_map_node_ {
RB_ENTRY(fd_context_map_node_) entry;
struct fd_context_map_node_
{
RB_ENTRY(fd_context_map_node_)
entry;
int fd;
int flags;
union {
union
{
EpollFDCtx epollfd;
EventFDCtx eventfd;
TimerFDCtx timerfd;
@ -51,7 +55,8 @@ errno_t fd_context_map_node_destroy(FDContextMapNode *node);
typedef RB_HEAD(fd_context_map_, fd_context_map_node_) FDContextMap;
typedef struct {
typedef struct
{
FDContextMap fd_context_map;
pthread_mutex_t mutex;
} EpollShimCtx;

File diff suppressed because it is too large Load Diff

View File

@ -19,12 +19,14 @@
struct registered_fds_node_;
typedef struct registered_fds_node_ RegisteredFDsNode;
typedef enum {
typedef enum
{
EOF_STATE_READ_EOF = 0x01,
EOF_STATE_WRITE_EOF = 0x02,
} EOFState;
typedef enum {
typedef enum
{
NODE_TYPE_FIFO = 1,
NODE_TYPE_SOCKET = 2,
NODE_TYPE_KQUEUE = 3,
@ -32,9 +34,12 @@ typedef enum {
NODE_TYPE_POLL = 5,
} NodeType;
struct registered_fds_node_ {
RB_ENTRY(registered_fds_node_) entry;
TAILQ_ENTRY(registered_fds_node_) pollfd_list_entry;
struct registered_fds_node_
{
RB_ENTRY(registered_fds_node_)
entry;
TAILQ_ENTRY(registered_fds_node_)
pollfd_list_entry;
int fd;
epoll_data_t data;
@ -50,8 +55,10 @@ struct registered_fds_node_ {
bool got_evfilt_except;
NodeType node_type;
union {
struct {
union
{
struct
{
bool readable;
bool writable;
} fifo;
@ -72,7 +79,8 @@ struct registered_fds_node_ {
typedef TAILQ_HEAD(pollfds_list_, registered_fds_node_) PollFDList;
typedef RB_HEAD(registered_fds_set_, registered_fds_node_) RegisteredFDsSet;
typedef struct {
typedef struct
{
int kq; // non owning
pthread_mutex_t mutex;

View File

@ -11,7 +11,8 @@
#define EVENTFD_CTX_FLAG_SEMAPHORE (1 << 0)
typedef struct {
typedef struct
{
int kq_; // non owning
int flags_;
pthread_mutex_t mutex_;

View File

@ -11,7 +11,8 @@ typedef int errno_t;
#include <signal.h>
#include <poll.h>
struct itimerspec {
struct itimerspec
{
struct timespec it_interval;
struct timespec it_value;
};

View File

@ -7,7 +7,8 @@
#include <stdint.h>
#include <stdlib.h>
typedef struct {
typedef struct
{
int kq; // non owning
} SignalFDCtx;

View File

@ -11,7 +11,8 @@
#include <pthread.h>
#include <time.h>
typedef struct {
typedef struct
{
int kq; // non owning
int flags;
pthread_mutex_t mutex;

View File

@ -21,7 +21,8 @@ int z_readfile(FILE *F, char **buf, size_t *size)
bufsize = *size = 0;
r = inflateInit2(&zs, 47);
if (r != Z_OK) return r;
if (r != Z_OK)
return r;
do
{
@ -31,7 +32,8 @@ int z_readfile(FILE *F, char **buf, size_t *size)
r = Z_ERRNO;
goto zerr;
}
if (!zs.avail_in) break;
if (!zs.avail_in)
break;
zs.next_in = in;
do
{
@ -49,7 +51,8 @@ int z_readfile(FILE *F, char **buf, size_t *size)
zs.avail_out = bufsize - *size;
zs.next_out = (unsigned char *)(*buf + *size);
r = inflate(&zs, Z_NO_FLUSH);
if (r != Z_OK && r != Z_STREAM_END) goto zerr;
if (r != Z_OK && r != Z_STREAM_END)
goto zerr;
*size = bufsize - zs.avail_out;
} while (r == Z_OK && zs.avail_in);
} while (r == Z_OK);
@ -57,7 +60,8 @@ int z_readfile(FILE *F, char **buf, size_t *size)
if (*size < bufsize)
{
// free extra space
if ((newbuf = realloc(*buf, *size))) *buf = newbuf;
if ((newbuf = realloc(*buf, *size)))
*buf = newbuf;
}
inflateEnd(&zs);

View File

@ -23,9 +23,11 @@ char *strncasestr(const char *s,const char *find, size_t slen)
{
do
{
if (slen-- < 1 || (sc = *s++) == '\0') return NULL;
if (slen-- < 1 || (sc = *s++) == '\0')
return NULL;
} while (toupper(c) != toupper(sc));
if (len > slen) return NULL;
if (len > slen)
return NULL;
} while (strncasecmp(s, find, len) != 0);
s--;
}
@ -35,7 +37,8 @@ char *strncasestr(const char *s,const char *find, size_t slen)
bool append_to_list_file(const char *filename, const char *s)
{
FILE *F = fopen(filename, "at");
if (!F) return false;
if (!F)
return false;
bool bOK = fprintf(F, "%s\n", s) > 0;
fclose(F);
return bOK;
@ -43,7 +46,8 @@ bool append_to_list_file(const char *filename, const char *s)
void ntop46(const struct sockaddr *sa, char *str, size_t len)
{
if (!len) return;
if (!len)
return;
*str = 0;
switch (sa->sa_family)
{
@ -81,7 +85,6 @@ void print_sockaddr(const struct sockaddr *sa)
printf("%s", ip_port);
}
// -1 = error, 0 = not local, 1 = local
bool check_local_ip(const struct sockaddr *saddr)
{
@ -90,7 +93,8 @@ bool check_local_ip(const struct sockaddr *saddr)
if (is_localnet(saddr))
return true;
if (getifaddrs(&addrs)<0) return false;
if (getifaddrs(&addrs) < 0)
return false;
a = addrs;
bool bres = false;
@ -127,8 +131,6 @@ void print_addrinfo(const struct addrinfo *ai)
}
}
bool saismapped(const struct sockaddr_in6 *sa)
{
// ::ffff:1.2.3.4
@ -147,8 +149,8 @@ bool sacmp(const struct sockaddr *sa1,const struct sockaddr *sa2)
}
uint16_t saport(const struct sockaddr *sa)
{
return htons(sa->sa_family==AF_INET ? ((struct sockaddr_in*)sa)->sin_port :
sa->sa_family==AF_INET6 ? ((struct sockaddr_in6*)sa)->sin6_port : 0);
return htons(sa->sa_family == AF_INET ? ((struct sockaddr_in *)sa)->sin_port : sa->sa_family == AF_INET6 ? ((struct sockaddr_in6 *)sa)->sin6_port
: 0);
}
bool saconvmapped(struct sockaddr_storage *a)
{
@ -185,8 +187,6 @@ bool is_private6(const struct sockaddr_in6* a)
return (a->sin6_addr.s6_addr[0] & 0xFE) == 0xFC;
}
bool set_keepalive(int fd)
{
int yes = 1;
@ -242,7 +242,8 @@ bool pf_parse(const char *s, port_filter *pf)
{
unsigned int v1, v2;
if (!s) return false;
if (!s)
return false;
if (*s == '~')
{
pf->neg = true;
@ -252,13 +253,15 @@ bool pf_parse(const char *s, port_filter *pf)
pf->neg = false;
if (sscanf(s, "%u-%u", &v1, &v2) == 2)
{
if (!v1 || v1>65535 || v2>65535 || v1>v2) return false;
if (!v1 || v1 > 65535 || v2 > 65535 || v1 > v2)
return false;
pf->from = (uint16_t)v1;
pf->to = (uint16_t)v2;
}
else if (sscanf(s, "%u", &v1) == 1)
{
if (!v1 || v1>65535) return false;
if (!v1 || v1 > 65535)
return false;
pf->to = pf->from = (uint16_t)v1;
}
else

View File

@ -36,10 +36,12 @@ bool set_ttl_hl(int fd, int ttl);
int get_so_error(int fd);
// alignment-safe functions
static inline uint16_t pntoh16(const uint8_t *p) {
static inline uint16_t pntoh16(const uint8_t *p)
{
return ((uint16_t)p[0] << 8) | (uint16_t)p[1];
}
static inline void phton16(uint8_t *p, uint16_t v) {
static inline void phton16(uint8_t *p, uint16_t v)
{
p[0] = (uint8_t)(v >> 8);
p[1] = (uint8_t)v;
}
@ -62,8 +64,7 @@ bool pf_parse(const char *s, port_filter *pf);
#ifdef __GNUC__
#define IN6_EXTRACT_MAP4(a) \
(__extension__ \
({ const struct in6_addr *__a = (const struct in6_addr *) (a); \
(__extension__({ const struct in6_addr *__a = (const struct in6_addr *) (a); \
(((const uint32_t *) (__a))[3]); }))
#else
#define IN6_EXTRACT_MAP4(a) (((const uint32_t *)(a))[3])

View File

@ -10,7 +10,8 @@ static bool addpool(strpool **hostlist, char **s, const char *end)
char *p;
// advance until eol lowering all chars
for (p = *s; p<end && *p && *p!='\r' && *p != '\n'; p++) *p=tolower(*p);
for (p = *s; p < end && *p && *p != '\r' && *p != '\n'; p++)
*p = tolower(*p);
if (!StrPoolAddStrLen(hostlist, *s, p - *s))
{
StrPoolDestroy(hostlist);
@ -18,7 +19,8 @@ static bool addpool(strpool **hostlist, char **s, const char *end)
return false;
}
// advance to the next line
for (; p<end && (!*p || *p=='\r' || *p=='\n') ; p++);
for (; p < end && (!*p || *p == '\r' || *p == '\n'); p++)
;
*s = p;
return true;
}
@ -51,7 +53,8 @@ bool AppendHostList(strpool **hostlist, char *filename)
e = zbuf + zsize;
while (p < e)
{
if ( *p == '#' || *p == ';' || *p == '/' || *p == '\n' ) continue;
if (*p == '#' || *p == ';' || *p == '/' || *p == '\n')
continue;
if (!addpool(hostlist, &p, e))
{
DLOG_ERR("Not enough memory to store host list : %s\n", filename);
@ -75,7 +78,8 @@ bool AppendHostList(strpool **hostlist, char *filename)
while (fgets(s, 256, F))
{
p = s;
if ( *p == '#' || *p == ';' || *p == '/' || *p == '\n' ) continue;
if (*p == '#' || *p == ';' || *p == '/' || *p == '\n')
continue;
if (!addpool(hostlist, &p, p + strlen(p)))
{
DLOG_ERR("Not enough memory to store host list : %s\n", filename);
@ -103,7 +107,8 @@ bool LoadHostLists(strpool **hostlist, struct str_list_head *file_list)
LIST_FOREACH(file, file_list, next)
{
if (!AppendHostList(hostlist, file->str)) return false;
if (!AppendHostList(hostlist, file->str))
return false;
}
return true;
}
@ -114,7 +119,6 @@ bool NonEmptyHostlist(strpool **hostlist)
return *hostlist ? true : StrPoolAddStrLen(hostlist, "@&()", 4);
}
bool SearchHostList(strpool *hostlist, const char *host)
{
if (hostlist)
@ -125,9 +129,11 @@ bool SearchHostList(strpool *hostlist, const char *host)
{
bInHostList = StrPoolCheckStr(hostlist, p);
VPRINT("Hostlist check for %s : %s\n", p, bInHostList ? "positive" : "negative");
if (bInHostList) return true;
if (bInHostList)
return true;
p = strchr(p, '.');
if (p) p++;
if (p)
p++;
}
}
return false;
@ -136,13 +142,15 @@ bool SearchHostList(strpool *hostlist, const char *host)
// return : true = apply fooling, false = do not apply
static bool HostlistCheck_(strpool *hostlist, strpool *hostlist_exclude, const char *host, bool *excluded)
{
if (excluded) *excluded = false;
if (excluded)
*excluded = false;
if (hostlist_exclude)
{
VPRINT("Checking exclude hostlist\n");
if (SearchHostList(hostlist_exclude, host))
{
if (excluded) *excluded = true;
if (excluded)
*excluded = true;
return false;
}
}

View File

@ -8,10 +8,18 @@
#define DIOCNATLOOK _IOWR('D', 23, struct pfioc_natlook)
enum { PF_INOUT, PF_IN, PF_OUT, PF_FWD };
enum
{
PF_INOUT,
PF_IN,
PF_OUT,
PF_FWD
};
struct pf_addr {
union {
struct pf_addr
{
union
{
struct in_addr v4;
struct in6_addr v6;
u_int8_t addr8[16];
@ -25,13 +33,15 @@ struct pf_addr {
#define addr32 pfa.addr32
};
union pf_state_xport {
union pf_state_xport
{
u_int16_t port;
u_int16_t call_id;
u_int32_t spi;
};
struct pfioc_natlook {
struct pfioc_natlook
{
struct pf_addr saddr;
struct pf_addr daddr;
struct pf_addr rsaddr;

View File

@ -62,19 +62,23 @@
*/
#define SPLAY_HEAD(name, type) \
struct name { \
struct name \
{ \
struct type *sph_root; /* root of the tree */ \
}
#define SPLAY_INITIALIZER(root) \
{NULL}
#define SPLAY_INIT(root) do { \
#define SPLAY_INIT(root) \
do \
{ \
(root)->sph_root = NULL; \
} while (/*CONSTCOND*/ 0)
#define SPLAY_ENTRY(type) \
struct { \
struct \
{ \
struct type *spe_left; /* left element */ \
struct type *spe_right; /* right element */ \
}
@ -85,31 +89,41 @@ struct { \
#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL)
/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \
#define SPLAY_ROTATE_RIGHT(head, tmp, field) \
do \
{ \
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
(head)->sph_root = tmp; \
} while (/*CONSTCOND*/ 0)
#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
#define SPLAY_ROTATE_LEFT(head, tmp, field) \
do \
{ \
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
(head)->sph_root = tmp; \
} while (/*CONSTCOND*/ 0)
#define SPLAY_LINKLEFT(head, tmp, field) do { \
#define SPLAY_LINKLEFT(head, tmp, field) \
do \
{ \
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
tmp = (head)->sph_root; \
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
} while (/*CONSTCOND*/ 0)
#define SPLAY_LINKRIGHT(head, tmp, field) do { \
#define SPLAY_LINKRIGHT(head, tmp, field) \
do \
{ \
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
tmp = (head)->sph_root; \
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
} while (/*CONSTCOND*/ 0)
#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
#define SPLAY_ASSEMBLE(head, node, left, right, field) \
do \
{ \
SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field); \
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
@ -140,12 +154,15 @@ static __inline struct type * \
name##_SPLAY_NEXT(struct name *head, struct type *elm) \
{ \
name##_SPLAY(head, elm); \
if (SPLAY_RIGHT(elm, field) != NULL) { \
if (SPLAY_RIGHT(elm, field) != NULL) \
{ \
elm = SPLAY_RIGHT(elm, field); \
while (SPLAY_LEFT(elm, field) != NULL) { \
while (SPLAY_LEFT(elm, field) != NULL) \
{ \
elm = SPLAY_LEFT(elm, field); \
} \
} else \
} \
else \
elm = NULL; \
return (elm); \
} \
@ -164,21 +181,28 @@ name##_SPLAY_MIN_MAX(struct name *head, int val) \
struct type * \
name##_SPLAY_INSERT(struct name *head, struct type *elm) \
{ \
if (SPLAY_EMPTY(head)) { \
if (SPLAY_EMPTY(head)) \
{ \
SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \
} else { \
} \
else \
{ \
int __comp; \
name##_SPLAY(head, elm); \
__comp = (cmp)(elm, (head)->sph_root); \
if(__comp < 0) { \
if (__comp < 0) \
{ \
SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field); \
SPLAY_RIGHT(elm, field) = (head)->sph_root; \
SPLAY_LEFT((head)->sph_root, field) = NULL; \
} else if (__comp > 0) { \
} \
else if (__comp > 0) \
{ \
SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field); \
SPLAY_LEFT(elm, field) = (head)->sph_root; \
SPLAY_RIGHT((head)->sph_root, field) = NULL; \
} else \
} \
else \
return ((head)->sph_root); \
} \
(head)->sph_root = (elm); \
@ -192,10 +216,14 @@ name##_SPLAY_REMOVE(struct name *head, struct type *elm) \
if (SPLAY_EMPTY(head)) \
return (NULL); \
name##_SPLAY(head, elm); \
if ((cmp)(elm, (head)->sph_root) == 0) { \
if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
if ((cmp)(elm, (head)->sph_root) == 0) \
{ \
if (SPLAY_LEFT((head)->sph_root, field) == NULL) \
{ \
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
} else { \
} \
else \
{ \
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
name##_SPLAY(head, elm); \
@ -215,22 +243,28 @@ name##_SPLAY(struct name *head, struct type *elm) \
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL; \
__left = __right = &__node; \
\
while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \
if (__comp < 0) { \
while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) \
{ \
if (__comp < 0) \
{ \
__tmp = SPLAY_LEFT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if ((cmp)(elm, __tmp) < 0){ \
if ((cmp)(elm, __tmp) < 0) \
{ \
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
if (SPLAY_LEFT((head)->sph_root, field) == NULL) \
break; \
} \
SPLAY_LINKLEFT(head, __right, field); \
} else if (__comp > 0) { \
} \
else if (__comp > 0) \
{ \
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if ((cmp)(elm, __tmp) > 0){ \
if ((cmp)(elm, __tmp) > 0) \
{ \
SPLAY_ROTATE_LEFT(head, __tmp, field); \
if (SPLAY_RIGHT((head)->sph_root, field) == NULL) \
break; \
@ -251,22 +285,28 @@ void name##_SPLAY_MINMAX(struct name *head, int __comp) \
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL; \
__left = __right = &__node; \
\
while (1) { \
if (__comp < 0) { \
while (1) \
{ \
if (__comp < 0) \
{ \
__tmp = SPLAY_LEFT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if (__comp < 0){ \
if (__comp < 0) \
{ \
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
if (SPLAY_LEFT((head)->sph_root, field) == NULL) \
break; \
} \
SPLAY_LINKLEFT(head, __right, field); \
} else if (__comp > 0) { \
} \
else if (__comp > 0) \
{ \
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if (__comp > 0) { \
if (__comp > 0) \
{ \
SPLAY_ROTATE_LEFT(head, __tmp, field); \
if (SPLAY_RIGHT((head)->sph_root, field) == NULL) \
break; \
@ -296,21 +336,25 @@ void name##_SPLAY_MINMAX(struct name *head, int __comp) \
/* Macros that define a red-black tree */
#define RB_HEAD(name, type) \
struct name { \
struct name \
{ \
struct type *rbh_root; /* root of the tree */ \
}
#define RB_INITIALIZER(root) \
{NULL}
#define RB_INIT(root) do { \
#define RB_INIT(root) \
do \
{ \
(root)->rbh_root = NULL; \
} while (/*CONSTCOND*/ 0)
#define RB_BLACK 0
#define RB_RED 1
#define RB_ENTRY(type) \
struct { \
struct \
{ \
struct type *rbe_left; /* left element */ \
struct type *rbe_right; /* right element */ \
struct type *rbe_parent; /* parent element */ \
@ -324,33 +368,45 @@ struct { \
#define RB_ROOT(head) (head)->rbh_root
#define RB_EMPTY(head) (RB_ROOT(head) == NULL)
#define RB_SET(elm, parent, field) do { \
#define RB_SET(elm, parent, field) \
do \
{ \
RB_PARENT(elm, field) = parent; \
RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
RB_COLOR(elm, field) = RB_RED; \
} while (/*CONSTCOND*/ 0)
#define RB_SET_BLACKRED(black, red, field) do { \
#define RB_SET_BLACKRED(black, red, field) \
do \
{ \
RB_COLOR(black, field) = RB_BLACK; \
RB_COLOR(red, field) = RB_RED; \
} while (/*CONSTCOND*/ 0)
#ifndef RB_AUGMENT
#define RB_AUGMENT(x) do {} while (0)
#define RB_AUGMENT(x) \
do \
{ \
} while (0)
#endif
#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
#define RB_ROTATE_LEFT(head, elm, tmp, field) \
do \
{ \
(tmp) = RB_RIGHT(elm, field); \
if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \
if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) \
{ \
RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \
} \
RB_AUGMENT(elm); \
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) \
{ \
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
else \
RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
} else \
} \
else \
(head)->rbh_root = (tmp); \
RB_LEFT(tmp, field) = (elm); \
RB_PARENT(elm, field) = (tmp); \
@ -359,18 +415,23 @@ struct { \
RB_AUGMENT(RB_PARENT(tmp, field)); \
} while (/*CONSTCOND*/ 0)
#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
#define RB_ROTATE_RIGHT(head, elm, tmp, field) \
do \
{ \
(tmp) = RB_LEFT(elm, field); \
if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \
if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) \
{ \
RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \
} \
RB_AUGMENT(elm); \
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) \
{ \
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
else \
RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
} else \
} \
else \
(head)->rbh_root = (tmp); \
RB_RIGHT(tmp, field) = (elm); \
RB_PARENT(elm, field) = (tmp); \
@ -437,17 +498,21 @@ name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
{ \
struct type *parent, *gparent, *tmp; \
while ((parent = RB_PARENT(elm, field)) != NULL && \
RB_COLOR(parent, field) == RB_RED) { \
RB_COLOR(parent, field) == RB_RED) \
{ \
gparent = RB_PARENT(parent, field); \
if (parent == RB_LEFT(gparent, field)) { \
if (parent == RB_LEFT(gparent, field)) \
{ \
tmp = RB_RIGHT(gparent, field); \
if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
if (tmp && RB_COLOR(tmp, field) == RB_RED) \
{ \
RB_COLOR(tmp, field) = RB_BLACK; \
RB_SET_BLACKRED(parent, gparent, field); \
elm = gparent; \
continue; \
} \
if (RB_RIGHT(parent, field) == elm) { \
if (RB_RIGHT(parent, field) == elm) \
{ \
RB_ROTATE_LEFT(head, parent, tmp, field); \
tmp = parent; \
parent = elm; \
@ -455,15 +520,19 @@ name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
} \
RB_SET_BLACKRED(parent, gparent, field); \
RB_ROTATE_RIGHT(head, gparent, tmp, field); \
} else { \
} \
else \
{ \
tmp = RB_LEFT(gparent, field); \
if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
if (tmp && RB_COLOR(tmp, field) == RB_RED) \
{ \
RB_COLOR(tmp, field) = RB_BLACK; \
RB_SET_BLACKRED(parent, gparent, field); \
elm = gparent; \
continue; \
} \
if (RB_LEFT(parent, field) == elm) { \
if (RB_LEFT(parent, field) == elm) \
{ \
RB_ROTATE_RIGHT(head, parent, tmp, field); \
tmp = parent; \
parent = elm; \
@ -482,10 +551,13 @@ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm)
{ \
struct type *tmp; \
while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \
elm != RB_ROOT(head)) { \
if (RB_LEFT(parent, field) == elm) { \
elm != RB_ROOT(head)) \
{ \
if (RB_LEFT(parent, field) == elm) \
{ \
tmp = RB_RIGHT(parent, field); \
if (RB_COLOR(tmp, field) == RB_RED) { \
if (RB_COLOR(tmp, field) == RB_RED) \
{ \
RB_SET_BLACKRED(tmp, parent, field); \
RB_ROTATE_LEFT(head, parent, tmp, field); \
tmp = RB_RIGHT(parent, field); \
@ -493,16 +565,19 @@ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm)
if ((RB_LEFT(tmp, field) == NULL || \
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) && \
(RB_RIGHT(tmp, field) == NULL || \
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) \
{ \
RB_COLOR(tmp, field) = RB_RED; \
elm = parent; \
parent = RB_PARENT(elm, field); \
} else { \
} \
else \
{ \
if (RB_RIGHT(tmp, field) == NULL || \
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) \
{ \
struct type *oleft; \
if ((oleft = RB_LEFT(tmp, field)) \
!= NULL) \
if ((oleft = RB_LEFT(tmp, field)) != NULL) \
RB_COLOR(oleft, field) = RB_BLACK; \
RB_COLOR(tmp, field) = RB_RED; \
RB_ROTATE_RIGHT(head, tmp, oleft, field); \
@ -516,9 +591,12 @@ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm)
elm = RB_ROOT(head); \
break; \
} \
} else { \
} \
else \
{ \
tmp = RB_LEFT(parent, field); \
if (RB_COLOR(tmp, field) == RB_RED) { \
if (RB_COLOR(tmp, field) == RB_RED) \
{ \
RB_SET_BLACKRED(tmp, parent, field); \
RB_ROTATE_RIGHT(head, parent, tmp, field); \
tmp = RB_LEFT(parent, field); \
@ -526,16 +604,19 @@ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm)
if ((RB_LEFT(tmp, field) == NULL || \
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) && \
(RB_RIGHT(tmp, field) == NULL || \
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) \
{ \
RB_COLOR(tmp, field) = RB_RED; \
elm = parent; \
parent = RB_PARENT(elm, field); \
} else { \
} \
else \
{ \
if (RB_LEFT(tmp, field) == NULL || \
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) \
{ \
struct type *oright; \
if ((oright = RB_RIGHT(tmp, field)) \
!= NULL) \
if ((oright = RB_RIGHT(tmp, field)) != NULL) \
RB_COLOR(oright, field) = RB_BLACK; \
RB_COLOR(tmp, field) = RB_RED; \
RB_ROTATE_LEFT(head, tmp, oright, field); \
@ -565,7 +646,8 @@ name##_RB_REMOVE(struct name *head, struct type *elm) \
child = RB_RIGHT(elm, field); \
else if (RB_RIGHT(elm, field) == NULL) \
child = RB_LEFT(elm, field); \
else { \
else \
{ \
struct type *left; \
elm = RB_RIGHT(elm, field); \
while ((left = RB_LEFT(elm, field)) != NULL) \
@ -575,31 +657,37 @@ name##_RB_REMOVE(struct name *head, struct type *elm) \
color = RB_COLOR(elm, field); \
if (child) \
RB_PARENT(child, field) = parent; \
if (parent) { \
if (parent) \
{ \
if (RB_LEFT(parent, field) == elm) \
RB_LEFT(parent, field) = child; \
else \
RB_RIGHT(parent, field) = child; \
RB_AUGMENT(parent); \
} else \
} \
else \
RB_ROOT(head) = child; \
if (RB_PARENT(elm, field) == old) \
parent = elm; \
(elm)->field = (old)->field; \
if (RB_PARENT(old, field)) { \
if (RB_PARENT(old, field)) \
{ \
if (RB_LEFT(RB_PARENT(old, field), field) == old) \
RB_LEFT(RB_PARENT(old, field), field) = elm; \
else \
RB_RIGHT(RB_PARENT(old, field), field) = elm; \
RB_AUGMENT(RB_PARENT(old, field)); \
} else \
} \
else \
RB_ROOT(head) = elm; \
RB_PARENT(RB_LEFT(old, field), field) = elm; \
if (RB_RIGHT(old, field)) \
RB_PARENT(RB_RIGHT(old, field), field) = elm; \
if (parent) { \
if (parent) \
{ \
left = parent; \
do { \
do \
{ \
RB_AUGMENT(left); \
} while ((left = RB_PARENT(left, field)) != NULL); \
} \
@ -609,19 +697,21 @@ name##_RB_REMOVE(struct name *head, struct type *elm) \
color = RB_COLOR(elm, field); \
if (child) \
RB_PARENT(child, field) = parent; \
if (parent) { \
if (parent) \
{ \
if (RB_LEFT(parent, field) == elm) \
RB_LEFT(parent, field) = child; \
else \
RB_RIGHT(parent, field) = child; \
RB_AUGMENT(parent); \
} else \
} \
else \
RB_ROOT(head) = child; \
color: \
if (color == RB_BLACK) \
name##_RB_REMOVE_COLOR(head, parent, child); \
return (old); \
} \
}
#define RB_GENERATE_INSERT(name, type, field, cmp, attr) \
/* Inserts a node into the RB tree */ \
@ -632,7 +722,8 @@ name##_RB_INSERT(struct name *head, struct type *elm) \
struct type *parent = NULL; \
int comp = 0; \
tmp = RB_ROOT(head); \
while (tmp) { \
while (tmp) \
{ \
parent = tmp; \
comp = (cmp)(elm, parent); \
if (comp < 0) \
@ -643,13 +734,15 @@ name##_RB_INSERT(struct name *head, struct type *elm) \
return (tmp); \
} \
RB_SET(elm, parent, field); \
if (parent != NULL) { \
if (parent != NULL) \
{ \
if (comp < 0) \
RB_LEFT(parent, field) = elm; \
else \
RB_RIGHT(parent, field) = elm; \
RB_AUGMENT(parent); \
} else \
} \
else \
RB_ROOT(head) = elm; \
name##_RB_INSERT_COLOR(head, elm); \
return (NULL); \
@ -662,7 +755,8 @@ name##_RB_FIND(struct name *head, struct type *elm) \
{ \
struct type *tmp = RB_ROOT(head); \
int comp; \
while (tmp) { \
while (tmp) \
{ \
comp = cmp(elm, tmp); \
if (comp < 0) \
tmp = RB_LEFT(tmp, field); \
@ -682,9 +776,11 @@ name##_RB_NFIND(struct name *head, struct type *elm) \
struct type *tmp = RB_ROOT(head); \
struct type *res = NULL; \
int comp; \
while (tmp) { \
while (tmp) \
{ \
comp = cmp(elm, tmp); \
if (comp < 0) { \
if (comp < 0) \
{ \
res = tmp; \
tmp = RB_LEFT(tmp, field); \
} \
@ -701,15 +797,19 @@ name##_RB_NFIND(struct name *head, struct type *elm) \
attr struct type * \
name##_RB_NEXT(struct type *elm) \
{ \
if (RB_RIGHT(elm, field)) { \
if (RB_RIGHT(elm, field)) \
{ \
elm = RB_RIGHT(elm, field); \
while (RB_LEFT(elm, field)) \
elm = RB_LEFT(elm, field); \
} else { \
} \
else \
{ \
if (RB_PARENT(elm, field) && \
(elm == RB_LEFT(RB_PARENT(elm, field), field))) \
elm = RB_PARENT(elm, field); \
else { \
else \
{ \
while (RB_PARENT(elm, field) && \
(elm == RB_RIGHT(RB_PARENT(elm, field), field))) \
elm = RB_PARENT(elm, field); \
@ -724,15 +824,19 @@ name##_RB_NEXT(struct type *elm) \
attr struct type * \
name##_RB_PREV(struct type *elm) \
{ \
if (RB_LEFT(elm, field)) { \
if (RB_LEFT(elm, field)) \
{ \
elm = RB_LEFT(elm, field); \
while (RB_RIGHT(elm, field)) \
elm = RB_RIGHT(elm, field); \
} else { \
} \
else \
{ \
if (RB_PARENT(elm, field) && \
(elm == RB_RIGHT(RB_PARENT(elm, field), field))) \
elm = RB_PARENT(elm, field); \
else { \
else \
{ \
while (RB_PARENT(elm, field) && \
(elm == RB_LEFT(RB_PARENT(elm, field), field))) \
elm = RB_PARENT(elm, field); \
@ -748,7 +852,8 @@ name##_RB_MINMAX(struct name *head, int val) \
{ \
struct type *tmp = RB_ROOT(head); \
struct type *parent = NULL; \
while (tmp) { \
while (tmp) \
{ \
parent = tmp; \
if (val < 0) \
tmp = RB_LEFT(tmp, field); \

View File

@ -105,7 +105,6 @@ int DLOG_PERROR(const char *s)
return DLOG_ERR("%s: %s\n", s, strerror(errno));
}
int LOG_APPEND(const char *filename, const char *format, va_list args)
{
int r;

View File

@ -14,7 +14,13 @@
#define HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT 3
#define HOSTLIST_AUTO_FAIL_TIME_DEFAULT 60
enum bindll { unwanted=0, no, prefer, force };
enum bindll
{
unwanted = 0,
no,
prefer,
force
};
#define MAX_BINDS 32
struct bind_s
@ -25,7 +31,12 @@ struct bind_s
int bind_wait_ifup, bind_wait_ip, bind_wait_ip_ll;
};
enum log_target { LOG_TARGET_CONSOLE=0, LOG_TARGET_FILE, LOG_TARGET_SYSLOG };
enum log_target
{
LOG_TARGET_CONSOLE = 0,
LOG_TARGET_FILE,
LOG_TARGET_SYSLOG
};
struct params_s
{

View File

@ -6,7 +6,8 @@
#define DESTROY_STR_POOL(etype, ppool) \
etype *elem, *tmp; \
HASH_ITER(hh, *ppool, elem, tmp) { \
HASH_ITER(hh, *ppool, elem, tmp) \
{ \
free(elem->str); \
HASH_DEL(*ppool, elem); \
free(elem); \
@ -32,7 +33,6 @@
return false; \
}
#undef uthash_nonfatal_oom
#define uthash_nonfatal_oom(elt) ut_oom_recover(elt)
static bool oom = false;
@ -65,13 +65,8 @@ void StrPoolDestroy(strpool **pp)
DESTROY_STR_POOL(strpool, pp)
}
void HostFailPoolDestroy(hostfail_pool **pp)
{
DESTROY_STR_POOL(hostfail_pool, pp)
}
hostfail_pool * HostFailPoolAdd(hostfail_pool **pp,const char *s,int fail_time)
void HostFailPoolDestroy(hostfail_pool **pp){
DESTROY_STR_POOL(hostfail_pool, pp)} hostfail_pool *HostFailPoolAdd(hostfail_pool **pp, const char *s, int fail_time)
{
size_t slen = strlen(s);
ADD_STR_POOL(hostfail_pool, pp, s, slen)
@ -123,11 +118,11 @@ void HostFailPoolDump(hostfail_pool *p)
printf("host=%s counter=%d time_left=%lld\n", elem->str, elem->counter, (long long int)elem->expire - now);
}
bool strlist_add(struct str_list_head *head, const char *filename)
{
struct str_list *entry = malloc(sizeof(struct str_list));
if (!entry) return false;
if (!entry)
return false;
entry->str = strdup(filename);
if (!entry->str)
{
@ -139,7 +134,8 @@ bool strlist_add(struct str_list_head *head, const char *filename)
}
static void strlist_entry_destroy(struct str_list *entry)
{
if (entry->str) free(entry->str);
if (entry->str)
free(entry->str);
free(entry);
}
void strlist_destroy(struct str_list_head *head)

View File

@ -10,7 +10,8 @@
#define HASH_FUNCTION HASH_BER
#include "uthash.h"
typedef struct strpool {
typedef struct strpool
{
char *str; /* key */
UT_hash_handle hh; /* makes this structure hashable */
} strpool;
@ -20,14 +21,16 @@ bool StrPoolAddStr(strpool **pp,const char *s);
bool StrPoolAddStrLen(strpool **pp, const char *s, size_t slen);
bool StrPoolCheckStr(strpool *p, const char *s);
struct str_list {
struct str_list
{
char *str;
LIST_ENTRY(str_list) next;
LIST_ENTRY(str_list)
next;
};
LIST_HEAD(str_list_head, str_list);
typedef struct hostfail_pool {
typedef struct hostfail_pool
{
char *str; /* key */
int counter; /* value */
time_t expire; /* when to expire record (unixtime) */

View File

@ -7,7 +7,6 @@
#include <arpa/inet.h>
#include <string.h>
const char *http_methods[] = {"GET /", "POST /", "HEAD /", "OPTIONS /", "PUT /", "DELETE /", "CONNECT /", "TRACE /", NULL};
const char *HttpMethod(const uint8_t *data, size_t len)
{
@ -31,7 +30,8 @@ bool HttpFindHost(uint8_t **pHost,uint8_t *buf,size_t bs)
if (!*pHost)
{
*pHost = memmem(buf, bs, "\nHost:", 6);
if (*pHost) (*pHost)++;
if (*pHost)
(*pHost)++;
}
return !!*pHost;
}
@ -40,7 +40,8 @@ bool HttpFindHostConst(const uint8_t **pHost,const uint8_t *buf,size_t bs)
if (!*pHost)
{
*pHost = memmem(buf, bs, "\nHost:", 6);
if (*pHost) (*pHost)++;
if (*pHost)
(*pHost)++;
}
return !!*pHost;
}
@ -61,18 +62,23 @@ bool HttpExtractHeader(const uint8_t *data, size_t len, const char *header, char
const uint8_t *p, *s, *e = data + len;
p = (uint8_t *)strncasestr((char *)data, header, len);
if (!p) return false;
if (!p)
return false;
p += strlen(header);
while (p < e && (*p == ' ' || *p == '\t')) p++;
while (p < e && (*p == ' ' || *p == '\t'))
p++;
s = p;
while (s < e && (*s != '\r' && *s != '\n' && *s != ' ' && *s != '\t')) s++;
while (s < e && (*s != '\r' && *s != '\n' && *s != ' ' && *s != '\t'))
s++;
if (s > p)
{
size_t slen = s - p;
if (buf && len_buf)
{
if (slen >= len_buf) slen = len_buf - 1;
for (size_t i = 0; i < slen; i++) buf[i] = tolower(p[i]);
if (slen >= len_buf)
slen = len_buf - 1;
for (size_t i = 0; i < slen; i++)
buf[i] = tolower(p[i]);
buf[slen] = 0;
}
return true;
@ -88,9 +94,13 @@ const char *HttpFind2ndLevelDomain(const char *host)
const char *p = NULL;
if (*host)
{
for (p = host + strlen(host)-1; p>host && *p!='.'; p--);
if (*p=='.') for (p--; p>host && *p!='.'; p--);
if (*p=='.') p++;
for (p = host + strlen(host) - 1; p > host && *p != '.'; p--)
;
if (*p == '.')
for (p--; p > host && *p != '.'; p--)
;
if (*p == '.')
p++;
}
return p;
}
@ -100,11 +110,13 @@ bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *
char loc[256], *redirect_host, *p;
int code;
if (!host || !*host) return false;
if (!host || !*host)
return false;
code = HttpReplyCode(data, len);
if ((code!=302 && code!=307) || !HttpExtractHeader(data,len,"\nLocation:",loc,sizeof(loc))) return false;
if ((code != 302 && code != 307) || !HttpExtractHeader(data, len, "\nLocation:", loc, sizeof(loc)))
return false;
// something like : https://censor.net/badpage.php?reason=denied&source=RKN
@ -117,9 +129,11 @@ bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *
// somethinkg like : censor.net/badpage.php?reason=denied&source=RKN
for(p=redirect_host; *p && *p!='/' ; p++);
for (p = redirect_host; *p && *p != '/'; p++)
;
*p = 0;
if (!*redirect_host) return false;
if (!*redirect_host)
return false;
// somethinkg like : censor.net
@ -140,17 +154,24 @@ size_t HttpPos(enum httpreqpos tpos_type, size_t hpos_pos, const uint8_t *http,
case httpreqpos_method:
// recognize some tpws pre-applied hacks
method = http;
if (sz<10) break;
if (*method=='\n' || *method=='\r') method++;
if (*method=='\n' || *method=='\r') method++;
for (i=0;i<7;i++) if (*method>='A' && *method<='Z') method++;
if (i<3 || *method!=' ') break;
if (sz < 10)
break;
if (*method == '\n' || *method == '\r')
method++;
if (*method == '\n' || *method == '\r')
method++;
for (i = 0; i < 7; i++)
if (*method >= 'A' && *method <= 'Z')
method++;
if (i < 3 || *method != ' ')
break;
return method - http - 1;
case httpreqpos_host:
if (HttpFindHostConst(&host, http, sz) && (host - http + 7) < sz)
{
host += 5;
if (*host==' ') host++;
if (*host == ' ')
host++;
return host - http;
}
break;
@ -162,8 +183,6 @@ size_t HttpPos(enum httpreqpos tpos_type, size_t hpos_pos, const uint8_t *http,
return hpos_pos < sz ? hpos_pos : 0;
}
uint16_t TLSRecordDataLen(const uint8_t *data)
{
return pntoh16(data + 3);
@ -201,41 +220,52 @@ bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const
l = 1 + 3 + 2 + 32;
// SessionIDLength
if (len < (l + 1)) return false;
if (len < (l + 1))
return false;
if (!bPartialIsOK)
{
ll = data[1] << 16 | data[2] << 8 | data[3]; // HandshakeProtocol length
if (len < (ll + 4)) return false;
if (len < (ll + 4))
return false;
}
l += data[l] + 1;
// CipherSuitesLength
if (len < (l + 2)) return false;
if (len < (l + 2))
return false;
l += pntoh16(data + l) + 2;
// CompressionMethodsLength
if (len < (l + 1)) return false;
if (len < (l + 1))
return false;
l += data[l] + 1;
// ExtensionsLength
if (len < (l + 2)) return false;
if (len < (l + 2))
return false;
data += l; len -= l;
data += l;
len -= l;
l = pntoh16(data);
data += 2; len -= 2;
data += 2;
len -= 2;
if (bPartialIsOK)
{
if (len < l) l = len;
if (len < l)
l = len;
}
else
{
if (len < l) return false;
if (len < l)
return false;
}
while (l >= 4)
{
uint16_t etype = pntoh16(data);
size_t elen = pntoh16(data + 2);
data += 4; l -= 4;
if (l < elen) break;
data += 4;
l -= 4;
if (l < elen)
break;
if (etype == type)
{
if (ext && len_ext)
@ -245,7 +275,8 @@ bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const
}
return true;
}
data += elen; l -= elen;
data += elen;
l -= elen;
}
return false;
@ -257,9 +288,11 @@ bool TLSFindExt(const uint8_t *data, size_t len, uint16_t type, const uint8_t **
// u16 Version: TLS1.0
// u16 Length
size_t reclen;
if (!IsTLSClientHello(data, len, bPartialIsOK)) return false;
if (!IsTLSClientHello(data, len, bPartialIsOK))
return false;
reclen = TLSRecordLen(data);
if (reclen<len) len=reclen; // correct len if it has more data than the first tls record has
if (reclen < len)
len = reclen; // correct len if it has more data than the first tls record has
return TLSFindExtInHandshake(data + 5, len - 5, type, ext, len_ext, bPartialIsOK);
}
static bool TLSExtractHostFromExt(const uint8_t *ext, size_t elen, char *host, size_t len_host)
@ -267,14 +300,19 @@ static bool TLSExtractHostFromExt(const uint8_t *ext, size_t elen, char *host, s
// u16 data+0 - name list length
// u8 data+2 - server name type. 0=host_name
// u16 data+3 - server name length
if (elen < 5 || ext[2] != 0) return false;
if (elen < 5 || ext[2] != 0)
return false;
size_t slen = pntoh16(ext + 3);
ext += 5; elen -= 5;
if (slen < elen) return false;
ext += 5;
elen -= 5;
if (slen < elen)
return false;
if (host && len_host)
{
if (slen >= len_host) slen = len_host - 1;
for (size_t i = 0; i < slen; i++) host[i] = tolower(ext[i]);
if (slen >= len_host)
slen = len_host - 1;
for (size_t i = 0; i < slen; i++)
host[i] = tolower(ext[i]);
host[slen] = 0;
}
return true;
@ -284,7 +322,8 @@ bool TLSHelloExtractHost(const uint8_t *data, size_t len, char *host, size_t len
const uint8_t *ext;
size_t elen;
if (!TLSFindExt(data, len, 0, &ext, &elen, bPartialIsOK)) return false;
if (!TLSFindExt(data, len, 0, &ext, &elen, bPartialIsOK))
return false;
return TLSExtractHostFromExt(ext, elen, host, len_host);
}
bool TLSHelloExtractHostFromHandshake(const uint8_t *data, size_t len, char *host, size_t len_host, bool bPartialIsOK)
@ -292,7 +331,8 @@ bool TLSHelloExtractHostFromHandshake(const uint8_t *data, size_t len, char *hos
const uint8_t *ext;
size_t elen;
if (!TLSFindExtInHandshake(data, len, 0, &ext, &elen, bPartialIsOK)) return false;
if (!TLSFindExtInHandshake(data, len, 0, &ext, &elen, bPartialIsOK))
return false;
return TLSExtractHostFromExt(ext, elen, host, len_host);
}
size_t TLSPos(enum tlspos tpos_type, size_t tpos_pos, const uint8_t *tls, size_t sz, uint8_t type)

View File

@ -18,7 +18,13 @@ const char *HttpFind2ndLevelDomain(const char *host);
int HttpReplyCode(const uint8_t *data, size_t len);
// must be pre-checked by IsHttpReply
bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *host);
enum httpreqpos { httpreqpos_none = 0, httpreqpos_method, httpreqpos_host, httpreqpos_pos };
enum httpreqpos
{
httpreqpos_none = 0,
httpreqpos_method,
httpreqpos_host,
httpreqpos_pos
};
size_t HttpPos(enum httpreqpos tpos_type, size_t hpos_pos, const uint8_t *http, size_t sz);
uint16_t TLSRecordDataLen(const uint8_t *data);
@ -29,5 +35,11 @@ bool TLSFindExt(const uint8_t *data, size_t len, uint16_t type, const uint8_t **
bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK);
bool TLSHelloExtractHost(const uint8_t *data, size_t len, char *host, size_t len_host, bool bPartialIsOK);
bool TLSHelloExtractHostFromHandshake(const uint8_t *data, size_t len, char *host, size_t len_host, bool bPartialIsOK);
enum tlspos { tlspos_none = 0, tlspos_sni, tlspos_sniext, tlspos_pos };
enum tlspos
{
tlspos_none = 0,
tlspos_sni,
tlspos_sniext,
tlspos_pos
};
size_t TLSPos(enum tlspos tpos_type, size_t tpos_pos, const uint8_t *tls, size_t sz, uint8_t type);

View File

@ -17,7 +17,6 @@
#endif
#endif
#if defined(BSD)
#include <net/if.h>
@ -56,13 +55,16 @@ static bool destination_from_pf(const struct sockaddr *accept_sa, struct sockadd
struct pfioc_natlook nl;
struct sockaddr_storage asa2;
if (redirector_fd==-1) return false;
if (redirector_fd == -1)
return false;
if (params.debug >= 2)
{
char s[48], s2[48];
*s=0; ntop46_port(accept_sa, s, sizeof(s));
*s2=0; ntop46_port((struct sockaddr *)orig_dst, s2, sizeof(s2));
*s = 0;
ntop46_port(accept_sa, s, sizeof(s));
*s2 = 0;
ntop46_port((struct sockaddr *)orig_dst, s2, sizeof(s2));
DBGPRINT("destination_from_pf %s %s\n", s, s2);
}
@ -77,8 +79,10 @@ static bool destination_from_pf(const struct sockaddr *accept_sa, struct sockadd
if (params.debug >= 2)
{
char s[48], s2[48];
*s=0; ntop46_port(accept_sa, s, sizeof(s));
*s2=0; ntop46_port((struct sockaddr *)orig_dst, s2, sizeof(s2));
*s = 0;
ntop46_port(accept_sa, s, sizeof(s));
*s2 = 0;
ntop46_port((struct sockaddr *)orig_dst, s2, sizeof(s2));
DBGPRINT("destination_from_pf (saconvmapped) %s %s\n", s, s2);
}
@ -162,7 +166,6 @@ static bool destination_from_pf(const struct sockaddr *accept_sa, struct sockadd
return true;
}
#else
bool redir_init(void) { return true; }
@ -170,8 +173,6 @@ void redir_close(void) {};
#endif
// Store the original destination address in orig_dst
bool get_dest_addr(int sockfd, const struct sockaddr *accept_sa, struct sockaddr_storage *orig_dst)
{
@ -202,7 +203,7 @@ bool get_dest_addr(int sockfd, const struct sockaddr *accept_sa, struct sockaddr
return false;
}
if (orig_dst->ss_family == AF_INET6)
((struct sockaddr_in6*)orig_dst)->sin6_scope_id=0; // or MacOS will not connect()
((struct sockaddr_in6 *)orig_dst)->sin6_scope_id = 0; // or macOS will not connect()
#ifdef BSD
if (params.pf_enable && !destination_from_pf(accept_sa, orig_dst))
DBGPRINT("pf filter destination_from_pf failed\n");

View File

@ -47,7 +47,8 @@ static void resolver_clear_list(void)
for (;;)
{
ri = TAILQ_FIRST(&resolver.resolve_list);
if (!ri) break;
if (!ri)
break;
TAILQ_REMOVE(&resolver.resolve_list, ri, next);
free(ri);
}
@ -69,9 +70,11 @@ static void *resolver_thread(void *arg)
// printf("resolver_thread %d start\n",syscall(SYS_gettid));
for (;;)
{
if (resolver.bStop) break;
if (resolver.bStop)
break;
r = sem_wait(resolver.sem);
if (resolver.bStop) break;
if (resolver.bStop)
break;
if (r)
{
if (errno != EINTR)
@ -87,7 +90,8 @@ static void *resolver_thread(void *arg)
rlist_lock;
ri = TAILQ_FIRST(&resolver.resolve_list);
if (ri) TAILQ_REMOVE(&resolver.resolve_list, ri, next);
if (ri)
TAILQ_REMOVE(&resolver.resolve_list, ri, next);
rlist_unlock;
if (ri)
@ -170,7 +174,8 @@ bool resolver_init(int threads, int fd_signal_pipe)
int t;
struct sigaction action;
if (threads<1 || resolver.bInit) return false;
if (threads < 1 || resolver.bInit)
return false;
memset(&resolver, 0, sizeof(resolver));
resolver.bInit = true;
@ -197,22 +202,24 @@ bool resolver_init(int threads, int fd_signal_pipe)
resolver.sem = &resolver._sem;
#endif
if (pthread_mutex_init(&resolver.resolve_list_lock, NULL)) goto ex;
if (pthread_mutex_init(&resolver.resolve_list_lock, NULL))
goto ex;
resolver.fd_signal_pipe = fd_signal_pipe;
TAILQ_INIT(&resolver.resolve_list);
// start as many threads as we can up to specified number
resolver.thread = malloc(sizeof(pthread_t) * threads);
if (!resolver.thread) goto ex;
if (!resolver.thread)
goto ex;
memset(&action, 0, sizeof(action));
action.sa_handler = sigbreak;
sigaction(SIG_BREAK, &action, NULL);
pthread_attr_t attr;
if (pthread_attr_init(&attr)) goto ex;
if (pthread_attr_init(&attr))
goto ex;
// set minimum thread stack size
if (pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN > 20480 ? PTHREAD_STACK_MIN : 20480))
@ -230,7 +237,8 @@ bool resolver_init(int threads, int fd_signal_pipe)
}
}
pthread_attr_destroy(&attr);
if (!resolver.threads) goto ex;
if (!resolver.threads)
goto ex;
return true;
@ -239,12 +247,11 @@ ex:
return false;
}
struct resolve_item *resolver_queue(const char *dom, uint16_t port, void *ptr)
{
struct resolve_item *ri = calloc(1, sizeof(struct resolve_item));
if (!ri) return NULL;
if (!ri)
return NULL;
strncpy(ri->dom, dom, sizeof(ri->dom));
ri->dom[sizeof(ri->dom) - 1] = 0;

View File

@ -13,7 +13,8 @@ struct resolve_item
int ga_res; // getaddrinfo result code
uint16_t port; // request port
void *ptr;
TAILQ_ENTRY(resolve_item) next;
TAILQ_ENTRY(resolve_item)
next;
};
struct resolve_item *resolver_queue(const char *dom, uint16_t port, void *ptr);

View File

@ -117,8 +117,7 @@ SYS_process_vm_writev,
#ifdef SYS_process_madvise
SYS_process_madvise,
#endif
SYS_kill, SYS_ptrace
};
SYS_kill, SYS_ptrace};
#define BLOCKED_SYSCALL_COUNT (sizeof(blocked_syscalls) / sizeof(*blocked_syscalls))
static void set_filter(struct sock_filter *filter, __u16 code, __u8 jt, __u8 jf, __u32 k)
@ -178,19 +177,18 @@ bool sec_harden(void)
if (!set_seccomp())
{
DLOG_PERROR("seccomp");
if (errno==EINVAL) DLOG_ERR("seccomp: this can be safely ignored if kernel does not support seccomp\n");
if (errno == EINVAL)
DLOG_ERR("seccomp: this can be safely ignored if kernel does not support seccomp\n");
return false;
}
#endif
return true;
}
bool checkpcap(uint64_t caps)
{
if (!caps) return true; // no special caps reqd
if (!caps)
return true; // no special caps reqd
struct __user_cap_header_struct ch = {_LINUX_CAPABILITY_VERSION_3, getpid()};
struct __user_cap_data_struct cd[2];
@ -221,7 +219,6 @@ int getmaxcap(void)
fclose(F);
}
return maxcap;
}
bool dropcaps(void)
{
@ -257,8 +254,6 @@ bool sec_harden(void)
#endif // __linux__
bool can_drop_root(void)
{
#ifdef __linux__

View File

@ -55,7 +55,7 @@ bool dropcaps(void);
#define ARCH_NR AUDIT_ARCH_MIPS64
#endif
#else
# error "Unsupported mips abi"
#error "Unsupported MIPS ABI"
#endif
#elif defined(__PPC64__)

View File

@ -25,8 +25,6 @@ typedef struct
uint32_t ip;
} s4_rep;
#define S5_AUTH_NONE 0
#define S5_AUTH_GSSAPI 1
#define S5_AUTH_USERPASS 2
@ -50,16 +48,20 @@ typedef struct
typedef struct
{
uint8_t ver, cmd, rsv, atyp;
union {
struct {
union
{
struct
{
struct in_addr addr;
uint16_t port;
} d4;
struct {
struct
{
struct in6_addr addr;
uint16_t port;
} d6;
struct {
struct
{
uint8_t len;
char domport[255 + 2]; // max hostname + binary port
} dd;
@ -82,8 +84,10 @@ typedef struct
typedef struct
{
uint8_t ver, rep, rsv, atyp;
union {
struct {
union
{
struct
{
struct in_addr addr;
uint16_t port;
} d4;

View File

@ -25,20 +25,24 @@ void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,si
if ((method = HttpMethod(segment, *size)))
{
method_len = strlen(method) - 2;
VPRINT("Data block looks like http request start : %s\n", method);
if (!ctrack->l7proto) ctrack->l7proto=HTTP;
VPRINT("Data block looks like HTTP request start : %s\n", method);
if (!ctrack->l7proto)
ctrack->l7proto = HTTP;
// cpu saving : we search host only if and when required. we do not research host every time we need its position
if ((params.hostlist || params.hostlist_exclude) && HttpFindHost(&pHost, segment, *size))
{
p = pHost + 5;
while (p < (segment + *size) && (*p == ' ' || *p == '\t')) p++;
while (p < (segment + *size) && (*p == ' ' || *p == '\t'))
p++;
pp = p;
while (pp < (segment + *size) && (pp - p) < (sizeof(Host) - 1) && *pp != '\r' && *pp != '\n') pp++;
while (pp < (segment + *size) && (pp - p) < (sizeof(Host) - 1) && *pp != '\r' && *pp != '\n')
pp++;
memcpy(Host, p, pp - p);
Host[pp - p] = '\0';
bHaveHost = true;
VPRINT("Requested Host is : %s\n", Host);
for(pc = Host; *pc; pc++) *pc=tolower(*pc);
for (pc = Host; *pc; pc++)
*pc = tolower(*pc);
bBypass = !HostlistCheck(Host, &bHostExcluded);
}
if (!bBypass)
@ -48,7 +52,8 @@ void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,si
p = pp = segment;
while ((p = memmem(p, segment + *size - p, "\r\n", 2)))
{
*p = '\n'; p++;
*p = '\n';
p++;
memmove(p, p + 1, segment + *size - p - 1);
(*size)--;
if (pp == (p - 1))
@ -67,7 +72,8 @@ void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,si
if (params.unixeol)
{
memmove(segment + 1, segment, *size);
(*size)++;;
(*size)++;
;
segment[0] = '\n';
}
else
@ -88,12 +94,14 @@ void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,si
memmove(p + 1, p, *size - pos);
*p = ' '; // insert extra space
(*size)++; // block will grow by 1 byte
if (pHost) pHost++; // Host: position will move by 1 byte
if (pHost)
pHost++; // Host: position will move by 1 byte
}
if ((params.hostdot || params.hosttab) && *size < segment_buffer_size && HttpFindHost(&pHost, segment, *size))
{
p = pHost + 5;
while (p < (segment + *size) && *p != '\r' && *p != '\n') p++;
while (p < (segment + *size) && *p != '\r' && *p != '\n')
p++;
if (p < (segment + *size))
{
pos = p - segment;
@ -151,9 +159,11 @@ void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,si
{
#define MAX_HDR_SIZE 2048
size_t padsize = hostpad > hsize ? hostpad - hsize : 0;
if (padsize>MAX_HDR_SIZE) padsize=MAX_HDR_SIZE;
if (padsize > MAX_HDR_SIZE)
padsize = MAX_HDR_SIZE;
// if next header would be too small then add extra padding to the current one
if ((hostpad-padsize-hsize)<hsize) padsize+=hostpad-padsize-hsize;
if ((hostpad - padsize - hsize) < hsize)
padsize += hostpad - padsize - hsize;
snprintf(s, sizeof(s), "%c%04x: ", 'a' + rand() % ('z' - 'a' + 1), rand() & 0xFFFF);
memcpy(p, s, 7);
p += 7;
@ -172,8 +182,10 @@ void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,si
}
}
*split_pos = HttpPos(params.split_http_req, params.split_pos, segment, *size);
if (params.disorder_http) *split_flags |= SPLIT_FLAG_DISORDER;
if (params.oob_http) *split_flags |= SPLIT_FLAG_OOB;
if (params.disorder_http)
*split_flags |= SPLIT_FLAG_DISORDER;
if (params.oob_http)
*split_flags |= SPLIT_FLAG_OOB;
}
else
{
@ -184,7 +196,8 @@ void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,si
{
size_t tpos = 0, spos = 0;
if (!ctrack->l7proto) ctrack->l7proto=TLS;
if (!ctrack->l7proto)
ctrack->l7proto = TLS;
VPRINT("packet contains TLS ClientHello\n");
// we need host only if hostlist is present
@ -212,7 +225,8 @@ void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,si
if (l >= 2)
{
// length is checked in IsTLSClientHello and cannot exceed buffer size
if ((tpos-5)>=l) tpos=5+1;
if ((tpos - 5) >= l)
tpos = 5 + 1;
VPRINT("making 2 TLS records at pos %zu\n", tpos);
memmove(segment + tpos + 5, segment + tpos, *size - tpos);
segment[tpos] = segment[0];
@ -222,7 +236,8 @@ void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,si
phton16(segment + 3, tpos - 5);
*size += 5;
// split pos present and it is not before tlsrec split. increase split pos by tlsrec header size (5 bytes)
if (spos && spos>=tpos) spos+=5;
if (spos && spos >= tpos)
spos += 5;
}
}
}
@ -233,8 +248,10 @@ void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,si
*split_pos = spos;
}
if (params.disorder_tls) *split_flags |= SPLIT_FLAG_DISORDER;
if (params.oob_tls) *split_flags |= SPLIT_FLAG_OOB;
if (params.disorder_tls)
*split_flags |= SPLIT_FLAG_DISORDER;
if (params.oob_tls)
*split_flags |= SPLIT_FLAG_OOB;
}
}
else if (params.split_any_protocol && params.split_pos < *size)
@ -243,11 +260,14 @@ void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,si
if (bHaveHost && bBypass && !bHostExcluded && *params.hostlist_auto_filename)
{
DBGPRINT("tamper_out put hostname : %s\n", Host);
if (ctrack->hostname) free(ctrack->hostname);
if (ctrack->hostname)
free(ctrack->hostname);
ctrack->hostname = strdup(Host);
}
if (params.disorder) *split_flags |= SPLIT_FLAG_DISORDER;
if (params.oob) *split_flags |= SPLIT_FLAG_OOB;
if (params.disorder)
*split_flags |= SPLIT_FLAG_DISORDER;
if (params.oob)
*split_flags |= SPLIT_FLAG_OOB;
}
static void auto_hostlist_reset_fail_counter(const char *hostname)
@ -343,11 +363,11 @@ void tamper_in(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,siz
// received not http reply. do not monitor this connection anymore
VPRINT("incoming unknown HTTP data detected for hostname %s\n", ctrack->hostname);
}
if (bFail) auto_hostlist_failed(ctrack->hostname);
if (bFail)
auto_hostlist_failed(ctrack->hostname);
}
if (!bFail) auto_hostlist_reset_fail_counter(ctrack->hostname);
if (!bFail)
auto_hostlist_reset_fail_counter(ctrack->hostname);
}
ctrack->bTamperInCutoff = true;
}
@ -356,7 +376,8 @@ void rst_in(t_ctrack *ctrack)
{
DBGPRINT("rst_in hostname=%s\n", ctrack->hostname);
if (!*params.hostlist_auto_filename) return;
if (!*params.hostlist_auto_filename)
return;
HostFailPoolPurgeRateLimited(&params.hostlist_auto_fail_counters);
@ -371,7 +392,8 @@ void hup_out(t_ctrack *ctrack)
{
DBGPRINT("hup_out hostname=%s\n", ctrack->hostname);
if (!*params.hostlist_auto_filename) return;
if (!*params.hostlist_auto_filename)
return;
HostFailPoolPurgeRateLimited(&params.hostlist_auto_fail_counters);

View File

@ -7,7 +7,12 @@
#define SPLIT_FLAG_DISORDER 0x01
#define SPLIT_FLAG_OOB 0x02
typedef enum {UNKNOWN=0, HTTP, TLS} t_l7proto;
typedef enum
{
UNKNOWN = 0,
HTTP,
TLS
} t_l7proto;
typedef struct
{
// common state

View File

@ -71,24 +71,26 @@ static void onusr2(int sig)
printf("\n");
}
static int8_t block_sigpipe(void)
{
sigset_t sigset;
memset(&sigset, 0, sizeof(sigset));
// Get the old sigset, add SIGPIPE and update sigset
if (sigprocmask(SIG_BLOCK, NULL, &sigset) == -1) {
if (sigprocmask(SIG_BLOCK, NULL, &sigset) == -1)
{
DLOG_PERROR("sigprocmask (get)");
return -1;
}
if (sigaddset(&sigset, SIGPIPE) == -1) {
if (sigaddset(&sigset, SIGPIPE) == -1)
{
DLOG_PERROR("sigaddset");
return -1;
}
if (sigprocmask(SIG_BLOCK, &sigset, NULL) == -1) {
if (sigprocmask(SIG_BLOCK, &sigset, NULL) == -1)
{
DLOG_PERROR("sigprocmask (set)");
return -1;
}
@ -96,7 +98,6 @@ static int8_t block_sigpipe(void)
return 0;
}
static bool is_interface_online(const char *ifname)
{
struct ifreq ifr;
@ -124,7 +125,6 @@ static int get_default_ttl(void)
return ttl;
}
static void exithelp(void)
{
printf(
@ -210,8 +210,7 @@ static void exithelp(void)
#if defined(__linux__) || defined(__APPLE__)
DEFAULT_TCP_USER_TIMEOUT_LOCAL, DEFAULT_TCP_USER_TIMEOUT_REMOTE,
#endif
HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT, HOSTLIST_AUTO_FAIL_TIME_DEFAULT
);
HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT, HOSTLIST_AUTO_FAIL_TIME_DEFAULT);
exit(1);
}
static void cleanup_params(void)
@ -250,7 +249,6 @@ static void checkbind_clean(void)
}
}
void save_default_ttl(void)
{
if (!params.ttl_default)
@ -258,7 +256,7 @@ void save_default_ttl(void)
params.ttl_default = get_default_ttl();
if (!params.ttl_default)
{
DLOG_ERR("could not get default ttl\n");
DLOG_ERR("could not get default TTL\n");
exit_clean(1);
}
}
@ -285,7 +283,6 @@ bool parse_tlspos(const char *s, enum tlspos *pos)
return true;
}
void parse_params(int argc, char *argv[])
{
int option_index = 0;
@ -386,11 +383,11 @@ void parse_params(int argc, char *argv[])
#endif
#endif
{"hostlist-auto-retrans-threshold", optional_argument, 0, 0}, // ignored. for nfqws command line compatibility
{ NULL,0,NULL,0 }
};
{NULL, 0, NULL, 0}};
while ((v = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1)
{
if (v) exithelp_clean();
if (v)
exithelp_clean();
switch (option_index)
{
case 0:
@ -575,8 +572,10 @@ void parse_params(int argc, char *argv[])
case 27: /* disorder */
if (optarg)
{
if (!strcmp(optarg,"http")) params.disorder_http=true;
else if (!strcmp(optarg,"tls")) params.disorder_tls=true;
if (!strcmp(optarg, "http"))
params.disorder_http = true;
else if (!strcmp(optarg, "tls"))
params.disorder_tls = true;
else
{
DLOG_ERR("Invalid argument for disorder\n");
@ -590,8 +589,10 @@ void parse_params(int argc, char *argv[])
case 28: /* oob */
if (optarg)
{
if (!strcmp(optarg,"http")) params.oob_http=true;
else if (!strcmp(optarg,"tls")) params.oob_tls=true;
if (!strcmp(optarg, "http"))
params.oob_http = true;
else if (!strcmp(optarg, "tls"))
params.oob_tls = true;
else
{
DLOG_ERR("Invalid argument for oob\n");
@ -605,13 +606,15 @@ void parse_params(int argc, char *argv[])
{
size_t l = strlen(optarg);
unsigned int bt;
if (l==1) params.oob_byte = (uint8_t)*optarg;
if (l == 1)
params.oob_byte = (uint8_t)*optarg;
else if (l != 4 || sscanf(optarg, "0x%02X", &bt) != 1)
{
DLOG_ERR("Invalid argument for oob-data\n");
exit_clean(1);
}
else params.oob_byte = (uint8_t)bt;
else
params.oob_byte = (uint8_t)bt;
}
break;
case 30: /* methodspace */
@ -746,12 +749,14 @@ void parse_params(int argc, char *argv[])
}
if (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.debug) params.debug = 1;
if (!params.debug)
params.debug = 1;
params.debug_target = LOG_TARGET_FILE;
}
else if (!strcmp(optarg, "syslog"))
{
if (!params.debug) params.debug = 1;
if (!params.debug)
params.debug = 1;
params.debug_target = LOG_TARGET_SYSLOG;
openlog("tpws", LOG_PID, LOG_USER);
}
@ -844,7 +849,8 @@ void parse_params(int argc, char *argv[])
case 55: /* connect-bind-addr */
{
char *p = strchr(optarg, '%');
if (p) *p++=0;
if (p)
*p++ = 0;
if (inet_pton(AF_INET, optarg, &params.connect_bind4.sin_addr))
{
params.connect_bind4.sin_family = AF_INET;
@ -858,7 +864,6 @@ void parse_params(int argc, char *argv[])
strncpy(params.connect_bind6_ifname, p, sizeof(params.connect_bind6_ifname));
params.connect_bind6_ifname[sizeof(params.connect_bind6_ifname) - 1] = 0;
}
}
else
{
@ -930,17 +935,22 @@ void parse_params(int argc, char *argv[])
DLOG_ERR("Cannot split with --skip-nodelay\n");
exit_clean(1);
}
if (!params.resolver_threads) params.resolver_threads = 5 + params.maxconn/50;
if (params.split_tls==tlspos_none && params.split_pos) params.split_tls=tlspos_pos;
if (params.split_http_req==httpreqpos_none && params.split_pos) params.split_http_req=httpreqpos_pos;
if (!params.resolver_threads)
params.resolver_threads = 5 + params.maxconn / 50;
if (params.split_tls == tlspos_none && params.split_pos)
params.split_tls = tlspos_pos;
if (params.split_http_req == httpreqpos_none && params.split_pos)
params.split_http_req = httpreqpos_pos;
if (*params.hostlist_auto_filename) params.hostlist_auto_mod_time = file_mod_time(params.hostlist_auto_filename);
if (*params.hostlist_auto_filename)
params.hostlist_auto_mod_time = file_mod_time(params.hostlist_auto_filename);
if (!LoadIncludeHostLists())
{
DLOG_ERR("Include hostlist load failed\n");
exit_clean(1);
}
if (*params.hostlist_auto_filename) NonEmptyHostlist(&params.hostlist);
if (*params.hostlist_auto_filename)
NonEmptyHostlist(&params.hostlist);
if (!LoadExcludeHostLists())
{
DLOG_ERR("Exclude hostlist load failed\n");
@ -948,7 +958,6 @@ void parse_params(int argc, char *argv[])
}
}
static bool find_listen_addr(struct sockaddr_storage *salisten, const char *bindiface, bool bind_if6, enum bindll bindll, int *if_index)
{
struct ifaddrs *addrs, *a;
@ -975,21 +984,19 @@ static bool find_listen_addr(struct sockaddr_storage *salisten, const char *bind
found = true;
goto ex;
}
// ipv6 links locals are fe80::/10
else if (a->ifa_addr->sa_family==AF_INET6
&&
// IPv6 links locals are fe80::/10
else if (a->ifa_addr->sa_family == AF_INET6 &&
((!*bindiface && (bindll == prefer || bindll == force)) ||
(*bindiface && bind_if6 && !strcmp(a->ifa_name, bindiface)))
&&
(*bindiface && bind_if6 && !strcmp(a->ifa_name, bindiface))) &&
((bindll == force && is_linklocal((struct sockaddr_in6 *)a->ifa_addr)) ||
(bindll == prefer && ((pass == 0 && is_linklocal((struct sockaddr_in6 *)a->ifa_addr)) || (pass == 1 && is_private6((struct sockaddr_in6 *)a->ifa_addr)) || pass == 2)) ||
(bindll == no && ((pass == 0 && is_private6((struct sockaddr_in6 *)a->ifa_addr)) || (pass == 1 && !is_linklocal((struct sockaddr_in6 *)a->ifa_addr)))) ||
(bindll==unwanted && ((pass==0 && is_private6((struct sockaddr_in6*)a->ifa_addr)) || (pass==1 && !is_linklocal((struct sockaddr_in6*)a->ifa_addr)) || pass==2)))
)
(bindll == unwanted && ((pass == 0 && is_private6((struct sockaddr_in6 *)a->ifa_addr)) || (pass == 1 && !is_linklocal((struct sockaddr_in6 *)a->ifa_addr)) || pass == 2))))
{
salisten->ss_family = AF_INET6;
memcpy(&((struct sockaddr_in6 *)salisten)->sin6_addr, &((struct sockaddr_in6 *)a->ifa_addr)->sin6_addr, sizeof(struct in6_addr));
if (if_index) *if_index = if_nametoindex(a->ifa_name);
if (if_index)
*if_index = if_nametoindex(a->ifa_name);
found = true;
goto ex;
}
@ -1012,7 +1019,8 @@ static bool read_system_maxfiles(rlim_t *maxfile)
return false;
n = fscanf(F, "%ju", &um);
fclose(F);
if (!n) return false;
if (!n)
return false;
*maxfile = (rlim_t)um;
return true;
#elif defined(BSD)
@ -1083,7 +1091,8 @@ static bool set_ulimit(void)
struct rlimit rlim = {fdmax, fdmax};
n = setrlimit(RLIMIT_NOFILE, &rlim);
if (n==-1) DLOG_PERROR("setrlimit");
if (n == -1)
DLOG_PERROR("setrlimit");
return n != -1;
}
@ -1104,7 +1113,8 @@ int main(int argc, char *argv[])
srand(time(NULL));
parse_params(argc, argv);
if (params.daemon) daemonize();
if (params.daemon)
daemonize();
if (*params.pidfile && !writepid(params.pidfile))
{
@ -1113,7 +1123,8 @@ int main(int argc, char *argv[])
}
memset(&list, 0, sizeof(list));
for(i=0;i<=params.binds_last;i++) listen_fd[i]=-1;
for (i = 0; i <= params.binds_last; i++)
listen_fd[i] = -1;
for (i = 0; i <= params.binds_last; i++)
{
@ -1133,8 +1144,7 @@ int main(int argc, char *argv[])
{
sleep(1);
sec++;
}
while (!is_interface_online(params.binds[i].bindiface) && sec<params.binds[i].bind_wait_ifup);
} while (!is_interface_online(params.binds[i].bindiface) && sec < params.binds[i].bind_wait_ifup);
if (sec >= params.binds[i].bind_wait_ifup)
{
DLOG_CONDUP("wait timed out\n");
@ -1182,25 +1192,25 @@ int main(int argc, char *argv[])
if (params.binds[i].bindll == prefer)
DLOG_CONDUP("during the first %d second(s) accepting only link locals...\n", params.binds[i].bind_wait_ip_ll);
else if (params.binds[i].bindll == unwanted)
DLOG_CONDUP("during the first %d second(s) accepting only ipv6 globals...\n", params.binds[i].bind_wait_ip_ll);
DLOG_CONDUP("during the first %d second(s) accepting only IPv6 globals...\n", params.binds[i].bind_wait_ip_ll);
}
}
for (;;)
{
// allow, no, prefer, force
bindll_1 = (params.binds[i].bindll==prefer && sec<params.binds[i].bind_wait_ip_ll) ? force :
(params.binds[i].bindll==unwanted && sec<params.binds[i].bind_wait_ip_ll) ? no :
params.binds[i].bindll;
bindll_1 = (params.binds[i].bindll == prefer && sec < params.binds[i].bind_wait_ip_ll) ? force : (params.binds[i].bindll == unwanted && sec < params.binds[i].bind_wait_ip_ll) ? no
: params.binds[i].bindll;
if (sec && sec == params.binds[i].bind_wait_ip_ll)
{
if (params.binds[i].bindll == prefer)
DLOG_CONDUP("link local address wait timeout. now accepting globals\n");
else if (params.binds[i].bindll == unwanted)
DLOG_CONDUP("global ipv6 address wait timeout. now accepting link locals\n");
DLOG_CONDUP("global IPv6 address wait timeout. now accepting link locals\n");
}
found = find_listen_addr(&list[i].salisten, params.binds[i].bindiface, params.binds[i].bind_if6, bindll_1, &if_index);
if (found) break;
if (found)
break;
if (sec >= params.binds[i].bind_wait_ip)
break;
@ -1258,7 +1268,8 @@ int main(int argc, char *argv[])
VPRINT("Binding %d to %s\n", i, ip_port);
}
if ((listen_fd[i] = socket(list[i].salisten.ss_family, SOCK_STREAM, 0)) == -1) {
if ((listen_fd[i] = socket(list[i].salisten.ss_family, SOCK_STREAM, 0)) == -1)
{
DLOG_PERROR("socket");
goto exiterr;
}
@ -1318,7 +1329,7 @@ int main(int argc, char *argv[])
// in linux strange behaviour was observed
// just after ifup and address assignment there's short window when bind() can't bind to addresses got from getifaddrs()
// it does not happen to transparent sockets because they can bind to any non-existend ip
// also only ipv6 seem to be buggy this way
// also only IPv6 seem to be buggy this way
if (errno == EADDRNOTAVAIL && params.proxy_type != CONN_TYPE_TRANSPARENT && list[i].bind_wait_ip_left)
{
if (!bBindBug)
@ -1352,13 +1363,15 @@ int main(int argc, char *argv[])
// splice() causes the process to receive the SIGPIPE-signal if one part (for
// example a socket) is closed during splice(). I would rather have splice()
// fail and return -1, so blocking SIGPIPE.
if (block_sigpipe() == -1) {
if (block_sigpipe() == -1)
{
DLOG_ERR("Could not block SIGPIPE signal\n");
goto exiterr;
}
DLOG_CONDUP(params.proxy_type==CONN_TYPE_SOCKS ? "socks mode\n" : "transparent proxy mode\n");
if (!params.tamper) DLOG_CONDUP("TCP proxy mode (no tampering)\n");
DLOG_CONDUP(params.proxy_type == CONN_TYPE_SOCKS ? "SOCKS mode\n" : "transparent proxy mode\n");
if (!params.tamper)
DLOG_CONDUP("TCP proxy mode (no tampering)\n");
signal(SIGHUP, onhup);
signal(SIGUSR2, onusr2);
@ -1369,7 +1382,9 @@ int main(int argc, char *argv[])
exiterr:
redir_close();
for(i=0;i<=params.binds_last;i++) if (listen_fd[i]!=-1) close(listen_fd[i]);
for (i = 0; i <= params.binds_last; i++)
if (listen_fd[i] != -1)
close(listen_fd[i]);
cleanup_params();
return exit_v;
}

View File

@ -24,7 +24,6 @@
#include "helpers.h"
#include "hostlist.h"
// keep separate legs counter. counting every time thousands of legs can consume cpu
static int legs_local, legs_remote;
/*
@ -43,7 +42,6 @@ static void print_legs(void)
VPRINT("Legs : local:%d remote:%d\n", legs_local, legs_remote);
}
static bool socks5_send_rep(int fd, uint8_t rep)
{
s5_rep s5rep;
@ -59,14 +57,18 @@ static bool socks5_send_rep_errno(int fd,int errn)
switch (errn)
{
case 0:
rep=S5_REP_OK; break;
rep = S5_REP_OK;
break;
case ECONNREFUSED:
rep=S5_REP_CONN_REFUSED; break;
rep = S5_REP_CONN_REFUSED;
break;
case ENETUNREACH:
rep=S5_REP_NETWORK_UNREACHABLE; break;
rep = S5_REP_NETWORK_UNREACHABLE;
break;
case ETIMEDOUT:
case EHOSTUNREACH:
rep=S5_REP_HOST_UNREACHABLE; break;
rep = S5_REP_HOST_UNREACHABLE;
break;
default:
rep = S5_REP_GENERAL_FAILURE;
}
@ -92,7 +94,6 @@ static bool socks_send_rep_errno(uint8_t ver, int fd, int errn)
return ver == 5 ? socks5_send_rep_errno(fd, errn) : socks4_send_rep_errno(fd, errn);
}
ssize_t send_with_ttl(int fd, const void *buf, size_t len, int flags, int ttl)
{
ssize_t wr;
@ -101,21 +102,20 @@ ssize_t send_with_ttl(int fd, const void *buf, size_t len, int flags, int ttl)
{
DBGPRINT("send_with_ttl %d fd=%d\n", ttl, fd);
if (!set_ttl_hl(fd, ttl))
//DLOG_ERR("could not set ttl %d to fd=%d\n",ttl,fd);
DLOG_ERR("could not set ttl %d to fd=%d\n",ttl,fd);
// DLOG_ERR("could not set TTL %d to fd=%d\n",ttl,fd);
DLOG_ERR("could not set TTL %d to fd=%d\n", ttl, fd);
}
wr = send(fd, buf, len, flags);
if (ttl)
{
int e = errno;
if (!set_ttl_hl(fd, params.ttl_default))
DLOG_ERR("could not set ttl %d to fd=%d\n",params.ttl_default,fd);
DLOG_ERR("could not set TTL %d to fd=%d\n", params.ttl_default, fd);
errno = e;
}
return wr;
}
static bool send_buffer_create(send_buffer_t *sb, const void *data, size_t len, size_t extra_bytes, int flags, int ttl)
{
if (sb->data)
@ -129,7 +129,8 @@ static bool send_buffer_create(send_buffer_t *sb, const void *data, size_t len,
DBGPRINT("send_buffer_create failed\n");
return false;
}
if (data) memcpy(sb->data,data,len);
if (data)
memcpy(sb->data, data, len);
sb->len = len;
sb->pos = 0;
sb->ttl = ttl;
@ -197,7 +198,8 @@ static ssize_t send_buffer_send(send_buffer_t *sb, int fd)
send_buffer_free(sb);
}
}
else if (wr<0 && errno==EAGAIN) wr=0;
else if (wr < 0 && errno == EAGAIN)
wr = 0;
return wr;
}
@ -213,7 +215,8 @@ static ssize_t send_buffers_send(send_buffer_t *sb_array, int count, int fd, siz
DBGPRINT("send_buffers_send(%d) wr=%zd err=%d\n", i, wr, errno);
if (wr < 0)
{
if (real_wr) *real_wr = twr;
if (real_wr)
*real_wr = twr;
return wr; // send error
}
twr += wr;
@ -221,7 +224,8 @@ static ssize_t send_buffers_send(send_buffer_t *sb_array, int count, int fd, siz
break;
}
}
if (real_wr) *real_wr = twr;
if (real_wr)
*real_wr = twr;
return twr;
}
@ -277,7 +281,8 @@ static ssize_t send_or_buffer(send_buffer_t *sb, int fd, const void *buf, size_t
if (len)
{
wr = send_with_ttl(fd, buf, len, flags, ttl);
if (wr<0 && errno==EAGAIN) wr=0;
if (wr < 0 && errno == EAGAIN)
wr = 0;
if (wr >= 0 && wr < len)
{
if (!send_buffer_create(sb, buf + wr, len - wr, 0, flags, ttl))
@ -325,7 +330,8 @@ static bool proxy_remote_conn_ack(tproxy_conn_t *conn, int sock_err)
{
// if proxy mode acknowledge connection request
// conn = remote. conn->partner = local
if (!conn->remote || !conn_partner_alive(conn)) return false;
if (!conn->remote || !conn_partner_alive(conn))
return false;
bool bres = true;
switch (conn->partner->conn_type)
{
@ -334,7 +340,7 @@ static bool proxy_remote_conn_ack(tproxy_conn_t *conn, int sock_err)
{
conn->partner->socks_state = S_TCP;
bres = socks_send_rep_errno(conn->partner->socks_ver, conn->partner->fd, sock_err);
DBGPRINT("socks connection acknowledgement. bres=%d remote_errn=%d remote_fd=%d local_fd=%d\n",bres,sock_err,conn->fd,conn->partner->fd);
DBGPRINT("SOCKS connection acknowledgement. bres=%d remote_errn=%d remote_fd=%d local_fd=%d\n", bres, sock_err, conn->fd, conn->partner->fd);
}
break;
}
@ -364,22 +370,20 @@ static void set_user_timeout(int fd, int timeout)
#endif
//Createas a socket and initiates the connection to the host specified by
// Creates a socket and initiates the connection to the host specified by
// remote_addr.
// Returns -1 if something fails, >0 on success (socket fd).
static int connect_remote(const struct sockaddr *remote_addr, bool bApplyConnectionFooling)
{
int remote_fd = 0, yes = 1, no = 0;
if ((remote_fd = socket(remote_addr->sa_family, SOCK_STREAM, 0)) < 0)
{
DLOG_PERROR("socket (connect_remote)");
return -1;
}
// Use NONBLOCK to avoid slow connects affecting the performance of other connections
// separate fcntl call to comply with macos
// separate fcntl call to comply with macOS
if (fcntl(remote_fd, F_SETFL, O_NONBLOCK) < 0)
{
DLOG_PERROR("socket set O_NONBLOCK (connect_remote)");
@ -472,21 +476,25 @@ static int connect_remote(const struct sockaddr *remote_addr, bool bApplyConnect
return remote_fd;
}
// Free resources occupied by this connection
static void free_conn(tproxy_conn_t *conn)
{
if (!conn) return;
if (conn->fd) close(conn->fd);
if (!conn)
return;
if (conn->fd)
close(conn->fd);
if (conn->splice_pipe[0])
{
close(conn->splice_pipe[0]);
close(conn->splice_pipe[1]);
}
conn_free_buffers(conn);
if (conn->partner) conn->partner->partner=NULL;
if (conn->track.hostname) free(conn->track.hostname);
if (conn->socks_ri) conn->socks_ri->ptr = NULL; // detach conn
if (conn->partner)
conn->partner->partner = NULL;
if (conn->track.hostname)
free(conn->track.hostname);
if (conn->socks_ri)
conn->socks_ri->ptr = NULL; // detach conn
free(conn);
}
static tproxy_conn_t *new_conn(int fd, bool remote)
@ -616,7 +624,8 @@ static tproxy_conn_t* add_tcp_connection(int efd, struct tailhead *conn_list,int
if (!(conn = new_conn(local_fd, false)))
{
if (remote_fd) close(remote_fd);
if (remote_fd)
close(remote_fd);
close(local_fd);
return NULL;
}
@ -647,8 +656,8 @@ static tproxy_conn_t* add_tcp_connection(int efd, struct tailhead *conn_list,int
// Transparent proxy mode :
// Local socket can be closed while waiting for connection attempt. I need
// to detect this when waiting for connect() to complete. However, I dont
// want to get EPOLLIN-events, as I dont want to receive any data before
// to detect this when waiting for connect() to complete. However, I don't
// want to get EPOLLIN-events, as I don't want to receive any data before
// remote connection is established
// Proxy mode : I need to service proxy protocol
// remote connection not started until proxy handshake is complete
@ -714,9 +723,6 @@ static bool check_connection_attempt(tproxy_conn_t *conn, int efd)
return !errn;
}
static bool epoll_set_flow_pair(tproxy_conn_t *conn)
{
bool bHasUnsent = conn_has_unsent(conn);
@ -747,8 +753,10 @@ static bool handle_unsent(tproxy_conn_t *conn)
DBGPRINT("splice unsent=%zd wr=%zd err=%d\n", conn->wr_unsent, wr, errno);
if (wr < 0)
{
if (errno==EAGAIN) wr=0;
else return false;
if (errno == EAGAIN)
wr = 0;
else
return false;
}
conn->twr += wr;
conn->wr_unsent -= wr;
@ -758,7 +766,8 @@ static bool handle_unsent(tproxy_conn_t *conn)
{
wr = conn_buffers_send(conn);
DBGPRINT("conn_buffers_send wr=%zd\n", wr);
if (wr<0) return false;
if (wr < 0)
return false;
}
if (!conn_has_unsent(conn) && conn_partner_alive(conn) && conn->partner->state == CONN_RDHUP)
{
@ -781,7 +790,6 @@ static bool handle_unsent(tproxy_conn_t *conn)
return epoll_set_flow_pair(conn);
}
bool proxy_mode_connect_remote(const struct sockaddr *sa, tproxy_conn_t *conn, struct tailhead *conn_list)
{
int remote_fd;
@ -790,7 +798,7 @@ bool proxy_mode_connect_remote(const struct sockaddr *sa, tproxy_conn_t *conn, s
{
char ip_port[48];
ntop46_port(sa, ip_port, sizeof(ip_port));
VPRINT("socks target for fd=%d is : %s\n", conn->fd, ip_port);
VPRINT("SOCKS target for fd=%d is : %s\n", conn->fd, ip_port);
}
if (check_local_ip((struct sockaddr *)sa))
{
@ -850,7 +858,8 @@ static bool handle_proxy_mode(tproxy_conn_t *conn, struct tailhead *conn_list)
// receive proxy control message
rd = recv(conn->fd, buf, sizeof(buf), MSG_DONTWAIT);
DBGPRINT("handle_proxy_mode rd=%zd\n", rd);
if (rd<1) return false; // hangup
if (rd < 1)
return false; // hangup
switch (conn->conn_type)
{
case CONN_TYPE_SOCKS:
@ -858,9 +867,10 @@ static bool handle_proxy_mode(tproxy_conn_t *conn, struct tailhead *conn_list)
{
case S_WAIT_HANDSHAKE:
DBGPRINT("S_WAIT_HANDSHAKE\n");
if (buf[0] != 5 && buf[0] != 4) return false; // unknown socks version
if (buf[0] != 5 && buf[0] != 4)
return false; // unknown SOCKS version
conn->socks_ver = buf[0];
DBGPRINT("socks version %u\n", conn->socks_ver);
DBGPRINT("SOCKS version %u\n", conn->socks_ver);
if (conn->socks_ver == 5)
{
s5_handshake *m = (s5_handshake *)buf;
@ -873,10 +883,12 @@ static bool handle_proxy_mode(tproxy_conn_t *conn, struct tailhead *conn_list)
DBGPRINT("socks5 proxy handshake invalid\n");
return false;
}
for (k=0;k<m->nmethods;k++) if (m->methods[k]==S5_AUTH_NONE) break;
for (k = 0; k < m->nmethods; k++)
if (m->methods[k] == S5_AUTH_NONE)
break;
if (k >= m->nmethods)
{
DBGPRINT("socks5 client wants authentication but we dont support\n");
DBGPRINT("socks5 client wants authentication but we don't support\n");
ack.method = S5_AUTH_UNACCEPTABLE;
wr = send(conn->fd, &ack, sizeof(ack), MSG_DONTWAIT);
return false;
@ -895,8 +907,8 @@ static bool handle_proxy_mode(tproxy_conn_t *conn, struct tailhead *conn_list)
}
else
{
// socks4 does not have separate handshake phase. it starts with connect request
// ipv6 and domain resolving are not supported
// SOCKS4 does not have separate handshake phase. it starts with connect request
// v6 and domain resolving are not supported
s4_req *m = (s4_req *)buf;
if (!S4_REQ_HEADER_VALID(m, rd))
{
@ -1004,19 +1016,18 @@ static bool handle_proxy_mode(tproxy_conn_t *conn, struct tailhead *conn_list)
break;
default:
return false; // should not be here. S5_REQ_CONNECT_VALID checks for valid atyp
}
return proxy_mode_connect_remote((struct sockaddr *)&ss, conn, conn_list);
}
break;
case S_WAIT_RESOLVE:
DBGPRINT("socks received message while in S_WAIT_RESOLVE. hanging up\n");
DBGPRINT("SOCKS received message while in S_WAIT_RESOLVE. hanging up\n");
break;
case S_WAIT_CONNECTION:
DBGPRINT("socks received message while in S_WAIT_CONNECTION. hanging up\n");
DBGPRINT("SOCKS received message while in S_WAIT_CONNECTION. hanging up\n");
break;
default:
DBGPRINT("socks received message while in an unexpected connection state\n");
DBGPRINT("SOCKS received message while in an unexpected connection state\n");
break;
}
break;
@ -1036,7 +1047,8 @@ static bool resolve_complete(struct resolve_item *ri, struct tailhead *conn_list
if (ri->ga_res)
{
socks5_send_rep(conn->fd, S5_REP_HOST_UNREACHABLE);
return false;;
return false;
;
}
else
{
@ -1057,7 +1069,6 @@ static bool resolve_complete(struct resolve_item *ri, struct tailhead *conn_list
return true;
}
static bool in_tamper_out_range(tproxy_conn_t *conn)
{
return (params.tamper_start_n ? (conn->tnrd + 1) : conn->trd) >= params.tamper_start &&
@ -1084,7 +1095,8 @@ static void tamper(tproxy_conn_t *conn, uint8_t *segment, size_t segment_buffer_
params.tamper_start_n ? "n" : "", params.tamper_start,
params.tamper_cutoff_n ? "n" : "", params.tamper_cutoff,
in_range ? "IN RANGE" : "OUT OF RANGE");
if (in_range) tamper_out(&conn->track,segment,segment_buffer_size,segment_size,split_pos,split_flags);
if (in_range)
tamper_out(&conn->track, segment, segment_buffer_size, segment_size, split_pos, split_flags);
}
}
}
@ -1107,7 +1119,6 @@ static ssize_t send_or_buffer_oob(send_buffer_t *sb, int fd, uint8_t *buf, size_
return wr;
}
#define RD_BLOCK_SIZE 65536
#define MAX_WASTE (1024 * 1024)
static bool handle_epoll(tproxy_conn_t *conn, struct tailhead *conn_list, uint32_t evt)
@ -1116,7 +1127,6 @@ static bool handle_epoll(tproxy_conn_t *conn, struct tailhead *conn_list, uint32
ssize_t rd = 0, wr = 0;
size_t bs;
DBGPRINT("+handle_epoll\n");
if (!conn_in_tcp_mode(conn))
@ -1169,7 +1179,8 @@ static bool handle_epoll(tproxy_conn_t *conn, struct tailhead *conn_list, uint32
rd = splice(conn->fd, NULL, conn->partner->splice_pipe[1], NULL, SPLICE_LEN, SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
DBGPRINT("splice fd=%d remote=%d len=%d rd=%zd err=%d\n", conn->fd, conn->remote, SPLICE_LEN, rd, errno);
if (rd<0 && errno==EAGAIN) rd=0;
if (rd < 0 && errno == EAGAIN)
rd = 0;
if (rd > 0)
{
conn->tnrd++;
@ -1177,7 +1188,8 @@ static bool handle_epoll(tproxy_conn_t *conn, struct tailhead *conn_list, uint32
conn->partner->wr_unsent += rd;
wr = splice(conn->partner->splice_pipe[0], NULL, conn->partner->fd, NULL, conn->partner->wr_unsent, SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
DBGPRINT("splice fd=%d remote=%d wr=%zd err=%d\n", conn->partner->fd, conn->partner->remote, wr, errno);
if (wr<0 && errno==EAGAIN) wr=0;
if (wr < 0 && errno == EAGAIN)
wr = 0;
if (wr > 0)
{
conn->partner->wr_unsent -= wr;
@ -1193,7 +1205,8 @@ static bool handle_epoll(tproxy_conn_t *conn, struct tailhead *conn_list, uint32
rd = recv(conn->fd, buf, RD_BLOCK_SIZE, MSG_DONTWAIT);
DBGPRINT("recv fd=%d rd=%zd err=%d\n", conn->fd, rd, errno);
if (rd<0 && errno==EAGAIN) rd=0;
if (rd < 0 && errno == EAGAIN)
rd = 0;
if (rd > 0)
{
size_t split_pos;
@ -1218,16 +1231,19 @@ static bool handle_epoll(tproxy_conn_t *conn, struct tailhead *conn_list, uint32
conn->partner->twr += wr;
wr = send_or_buffer(conn->partner->wr_buf + 1, conn->partner->fd, buf + split_pos, bs - split_pos, 0, 0);
DBGPRINT("send_or_buffer(2) fd=%d wr=%zd err=%d\n", conn->partner->fd, wr, errno);
if (wr>0) conn->partner->twr += wr;
if (wr > 0)
conn->partner->twr += wr;
}
}
else
{
wr = send_or_buffer(conn->partner->wr_buf, conn->partner->fd, buf, bs, 0, 0);
DBGPRINT("send_or_buffer(3) fd=%d wr=%zd err=%d\n", conn->partner->fd, wr, errno);
if (wr>0) conn->partner->twr += wr;
if (wr > 0)
conn->partner->twr += wr;
}
if (wr<0 && errno==ENOMEM) oom=true;
if (wr < 0 && errno == ENOMEM)
oom = true;
}
}
@ -1236,7 +1252,8 @@ static bool handle_epoll(tproxy_conn_t *conn, struct tailhead *conn_list, uint32
}
DBGPRINT("-handle_epoll rd=%zd wr=%zd\n", rd, wr);
if (oom) DBGPRINT("handle_epoll: OUT_OF_MEMORY\n");
if (oom)
DBGPRINT("handle_epoll: OUT_OF_MEMORY\n");
// do not fail if partner fails.
// if partner fails there will be another epoll event with EPOLLHUP or EPOLLERR
@ -1255,7 +1272,10 @@ static bool remove_closed_connections(int efd, struct tailhead *close_list)
epoll_del(conn);
VPRINT("Socket fd=%d (partner_fd=%d, remote=%d) closed, connection removed. total_read=%" PRIu64 " total_write=%" PRIu64 " event_count=%u\n",
conn->fd, conn->partner ? conn->partner->fd : 0, conn->remote, conn->trd, conn->twr, conn->event_count);
if (conn->remote) legs_remote--; else legs_local--;
if (conn->remote)
legs_remote--;
else
legs_local--;
free_conn(conn);
bRemoved = true;
}
@ -1273,7 +1293,6 @@ static void close_tcp_conn(struct tailhead *conn_list, struct tailhead *close_li
}
}
static bool read_all_and_buffer(tproxy_conn_t *conn, int buffer_number)
{
if (conn_partner_alive(conn))
@ -1299,7 +1318,6 @@ static bool read_all_and_buffer(tproxy_conn_t *conn, int buffer_number)
if (epoll_update_flow(conn->partner))
return true;
}
send_buffer_free(conn->partner->wr_buf + buffer_number);
}
@ -1308,7 +1326,6 @@ static bool read_all_and_buffer(tproxy_conn_t *conn, int buffer_number)
return false;
}
static bool conn_timed_out(tproxy_conn_t *conn)
{
if (conn->orphan_since && conn->state == CONN_UNAVAILABLE)
@ -1340,7 +1357,8 @@ static void conn_close_timed_out(struct tailhead *conn_list, struct tailhead *cl
static void conn_close_both(struct tailhead *conn_list, struct tailhead *close_list, tproxy_conn_t *conn)
{
if (conn_partner_alive(conn)) close_tcp_conn(conn_list,close_list,conn->partner);
if (conn_partner_alive(conn))
close_tcp_conn(conn_list, close_list, conn->partner);
close_tcp_conn(conn_list, close_list, conn);
}
static void conn_close_with_partner_check(struct tailhead *conn_list, struct tailhead *close_list, tproxy_conn_t *conn)
@ -1356,7 +1374,6 @@ static void conn_close_with_partner_check(struct tailhead *conn_list, struct tai
}
}
static bool handle_resolve_pipe(tproxy_conn_t **conn, struct tailhead *conn_list, int fd)
{
ssize_t rd;
@ -1377,7 +1394,8 @@ static bool handle_resolve_pipe(tproxy_conn_t **conn, struct tailhead *conn_list
}
b = resolve_complete(ri, conn_list);
*conn = (tproxy_conn_t *)ri->ptr;
if (*conn) (*conn)->socks_ri = NULL;
if (*conn)
(*conn)->socks_ri = NULL;
free(ri);
return b;
}
@ -1397,7 +1415,8 @@ int event_loop(const int *listen_fd, size_t listen_fd_ct)
socklen_t accept_salen;
int resolve_pipe[2];
if (!listen_fd_ct) return -1;
if (!listen_fd_ct)
return -1;
resolve_pipe[0] = resolve_pipe[1] = 0;
@ -1406,7 +1425,8 @@ int event_loop(const int *listen_fd, size_t listen_fd_ct)
TAILQ_INIT(&conn_list);
TAILQ_INIT(&close_list);
if ((efd = epoll_create(1)) == -1) {
if ((efd = epoll_create(1)) == -1)
{
DLOG_PERROR("epoll_create");
return -1;
}
@ -1425,7 +1445,8 @@ int event_loop(const int *listen_fd, size_t listen_fd_ct)
listen_conn[sct].listener = true;
listen_conn[sct].fd = listen_fd[sct];
ev.data.ptr = listen_conn + sct;
if (epoll_ctl(efd, EPOLL_CTL_ADD, listen_conn[sct].fd, &ev) == -1) {
if (epoll_ctl(efd, EPOLL_CTL_ADD, listen_conn[sct].fd, &ev) == -1)
{
DLOG_PERROR("epoll_ctl (listen socket)");
retval = -1;
goto ex;
@ -1446,7 +1467,8 @@ int event_loop(const int *listen_fd, size_t listen_fd_ct)
goto ex;
}
ev.data.ptr = NULL;
if (epoll_ctl(efd, EPOLL_CTL_ADD, resolve_pipe[0], &ev) == -1) {
if (epoll_ctl(efd, EPOLL_CTL_ADD, resolve_pipe[0], &ev) == -1)
{
DLOG_PERROR("epoll_ctl (listen socket)");
retval = -1;
goto ex;
@ -1466,7 +1488,8 @@ int event_loop(const int *listen_fd, size_t listen_fd_ct)
if ((num_events = epoll_wait(efd, events, MAX_EPOLL_EVENTS, -1)) == -1)
{
if (errno == EINTR) continue; // system call was interrupted
if (errno == EINTR)
continue; // system call was interrupted
DLOG_PERROR("epoll_wait");
retval = -1;
break;
@ -1486,7 +1509,8 @@ int event_loop(const int *listen_fd, size_t listen_fd_ct)
if (!handle_resolve_pipe(&conn, &conn_list, resolve_pipe[0]))
{
DBGPRINT("handle_resolve_pipe false\n");
if (conn) close_tcp_conn(&conn_list,&close_list,conn);
if (conn)
close_tcp_conn(&conn_list, &close_list, conn);
}
}
continue;
@ -1499,7 +1523,7 @@ int event_loop(const int *listen_fd, size_t listen_fd_ct)
accept_salen = sizeof(accept_sa);
// Accept new connection
#if defined(__APPLE__)
// macos does not have accept4()
// macOS does not have accept4()
tmp_fd = accept(conn->fd, (struct sockaddr *)&accept_sa, &accept_salen);
#else
tmp_fd = accept4(conn->fd, (struct sockaddr *)&accept_sa, &accept_salen, SOCK_NONBLOCK);
@ -1514,7 +1538,7 @@ int event_loop(const int *listen_fd, size_t listen_fd_ct)
VPRINT("Too many local legs : %d\n", legs_local);
}
#if defined(__APPLE__)
// separate fcntl call to comply with macos
// separate fcntl call to comply with macOS
else if (fcntl(tmp_fd, F_SETFL, O_NONBLOCK) < 0)
{
DLOG_PERROR("socket set O_NONBLOCK (accept)");
@ -1558,17 +1582,25 @@ int event_loop(const int *listen_fd, size_t listen_fd_ct)
const char *se;
switch (events[i].events & (EPOLLHUP | EPOLLERR))
{
case EPOLLERR: se="EPOLLERR"; break;
case EPOLLHUP: se="EPOLLHUP"; break;
case EPOLLHUP|EPOLLERR: se="EPOLLERR EPOLLHUP"; break;
default: se=NULL;
case EPOLLERR:
se = "EPOLLERR";
break;
case EPOLLHUP:
se = "EPOLLHUP";
break;
case EPOLLHUP | EPOLLERR:
se = "EPOLLERR EPOLLHUP";
break;
default:
se = NULL;
}
VPRINT("Socket fd=%d (partner_fd=%d, remote=%d) %s so_error=%d (%s)\n", conn->fd, conn->partner ? conn->partner->fd : 0, conn->remote, se, errn, strerror(errn));
proxy_remote_conn_ack(conn, errn);
read_all_and_buffer(conn, 3);
if (errn == ECONNRESET && conn_partner_alive(conn))
{
if (conn->remote && params.tamper) rst_in(&conn->partner->track);
if (conn->remote && params.tamper)
rst_in(&conn->partner->track);
struct linger lin;
lin.l_onoff = 1;
@ -1593,7 +1625,8 @@ int event_loop(const int *listen_fd, size_t listen_fd_ct)
{
DBGPRINT("EPOLLRDHUP\n");
read_all_and_buffer(conn, 2);
if (!conn->remote && params.tamper) hup_out(&conn->track);
if (!conn->remote && params.tamper)
hup_out(&conn->track);
conn->state = CONN_RDHUP; // only writes. do not receive RDHUP anymore
if (conn_has_unsent(conn))
@ -1640,12 +1673,20 @@ int event_loop(const int *listen_fd, size_t listen_fd_ct)
const char *se;
switch (events[i].events & (EPOLLIN | EPOLLOUT))
{
case EPOLLIN: se="EPOLLIN"; break;
case EPOLLOUT: se="EPOLLOUT"; break;
case EPOLLIN|EPOLLOUT: se="EPOLLIN EPOLLOUT"; break;
default: se=NULL;
case EPOLLIN:
se = "EPOLLIN";
break;
case EPOLLOUT:
se = "EPOLLOUT";
break;
case EPOLLIN | EPOLLOUT:
se = "EPOLLIN EPOLLOUT";
break;
default:
se = NULL;
}
if (se) DBGPRINT("%s\n",se);
if (se)
DBGPRINT("%s\n", se);
// will not receive this until successful check_connection_attempt()
if (!handle_epoll(conn, &conn_list, events[i].events))
{
@ -1663,10 +1704,8 @@ int event_loop(const int *listen_fd, size_t listen_fd_ct)
continue;
}
}
}
}
}
}
tm = time(NULL);
@ -1682,14 +1721,19 @@ int event_loop(const int *listen_fd, size_t listen_fd_ct)
print_legs();
}
fflush(stderr); fflush(stdout); // for console messages
fflush(stderr);
fflush(stdout); // for console messages
}
ex:
if (efd) close(efd);
if (listen_conn) free(listen_conn);
if (efd)
close(efd);
if (listen_conn)
free(listen_conn);
resolver_deinit();
if (resolve_pipe[0]) close(resolve_pipe[0]);
if (resolve_pipe[1]) close(resolve_pipe[1]);
if (resolve_pipe[0])
close(resolve_pipe[0]);
if (resolve_pipe[1])
close(resolve_pipe[1]);
return retval;
}

View File

@ -10,7 +10,7 @@
#define BACKLOG 10
#define MAX_EPOLL_EVENTS 64
#define IP_TRANSPARENT 19 //So that application compiles on OpenWRT
#define IP_TRANSPARENT 19 // So that application compiles on OpenWrt
#define SPLICE_LEN 65536
#define DEFAULT_MAX_CONN 512
#define DEFAULT_MAX_ORPHAN_TIME 5
@ -20,7 +20,8 @@
int event_loop(const int *listen_fd, size_t listen_fd_ct);
// Three different states of a connection
enum{
enum
{
CONN_UNAVAILABLE = 0, // connecting
CONN_AVAILABLE, // operational
CONN_RDHUP, // received RDHUP, only sending unsent buffers. more RDHUPs are blocked
@ -39,7 +40,8 @@ struct send_buffer
};
typedef struct send_buffer send_buffer_t;
enum{
enum
{
CONN_TYPE_TRANSPARENT = 0,
CONN_TYPE_SOCKS
};
@ -59,7 +61,8 @@ struct tproxy_conn
time_t orphan_since;
// socks5 state machine
enum {
enum
{
S_WAIT_HANDSHAKE = 0,
S_WAIT_REQUEST,
S_WAIT_RESOLVE,
@ -70,7 +73,7 @@ struct tproxy_conn
struct resolve_item *socks_ri;
// these value are used in flow control. we do not use ET (edge triggered) polling
// if we dont disable notifications they will come endlessly until condition becomes false and will eat all cpu time
// if we don't disable notifications they will come endlessly until condition becomes false and will eat all cpu time
bool bFlowIn, bFlowOut, bShutdown, bFlowInPrev, bFlowOutPrev, bPrevRdhup;
// total read,write
@ -95,7 +98,8 @@ struct tproxy_conn
t_ctrack track;
// Create the struct which contains ptrs to next/prev element
TAILQ_ENTRY(tproxy_conn) conn_ptrs;
TAILQ_ENTRY(tproxy_conn)
conn_ptrs;
};
typedef struct tproxy_conn tproxy_conn_t;
@ -103,5 +107,4 @@ typedef struct tproxy_conn tproxy_conn_t;
// Use tail queue for efficient delete
TAILQ_HEAD(tailhead, tproxy_conn);
bool set_socket_buffers(int fd, int rcvbuf, int sndbuf);

File diff suppressed because it is too large Load Diff