Template
1
0
mirror of https://github.com/bol-van/zapret2.git synced 2026-03-13 22:03:09 +00:00

icmp and ipp support

This commit is contained in:
bol-van
2026-01-26 14:22:38 +03:00
parent 90fa71d6d6
commit 78b3baa03f
35 changed files with 3213 additions and 561 deletions

View File

@@ -10,11 +10,11 @@ LIBS =
LIBS_LINUX = -lz -lnetfilter_queue -lnfnetlink -lmnl -lm
LIBS_SYSTEMD = -lsystemd
LIBS_BSD = -lz -lm
LIBS_CYGWIN = -lz -Lwindows/windivert -Iwindows -lwlanapi -lole32 -loleaut32
LIBS_CYGWIN = -lz -Lwindows/windivert -Iwindows -lwlanapi -lole32 -loleaut32 -liphlpapi -lntdll
LIBS_CYGWIN32 = -lwindivert32
LIBS_CYGWIN64 = -lwindivert64
RES_CYGWIN32 = windows/res/32/winmanifest.o windows/res/32/winicon.o
RES_CYGWIN64 = windows/res/64/winmanifest.o windows/res/64/winicon.o
RES_CYGWIN32 = windows/res/winws_res32.o
RES_CYGWIN64 = windows/res/winws_res64.o
SRC_FILES = *.c crypto/*.c
LUA_JIT?=1

View File

@@ -95,10 +95,7 @@ static uint16_t do_csum(const uint8_t *buff, size_t len)
return u16;
}
uint16_t csum_partial(const void *buff, size_t len)
{
return do_csum(buff, len);
}
#define csum_partial(buff, len) do_csum((const uint8_t*)buff,len)
uint16_t csum_tcpudp_magic(uint32_t saddr, uint32_t daddr, size_t len, uint8_t proto, uint16_t sum)
{
@@ -107,7 +104,7 @@ uint16_t csum_tcpudp_magic(uint32_t saddr, uint32_t daddr, size_t len, uint8_t p
uint16_t ip4_compute_csum(const void *buff, size_t len)
{
return ~from64to16(do_csum(buff, len));
return ~csum_partial(buff, len);
}
void ip4_fix_checksum(struct ip *ip)
{
@@ -158,3 +155,21 @@ void udp_fix_checksum(struct udphdr *udp, size_t len, const struct ip *ip, const
else if (ip6hdr)
udp6_fix_checksum(udp, len, &ip6hdr->ip6_src, &ip6hdr->ip6_dst);
}
void icmp4_fix_checksum(struct icmp46 *icmp, size_t len)
{
icmp->icmp_cksum = 0;
icmp->icmp_cksum = ~csum_partial(icmp, len);
}
void icmp6_fix_checksum(struct icmp46 *icmp, size_t len, const struct ip6_hdr *ip6hdr)
{
icmp->icmp_cksum = 0;
icmp->icmp_cksum = csum_ipv6_magic(&ip6hdr->ip6_src, &ip6hdr->ip6_dst, len, IPPROTO_ICMPV6, csum_partial(icmp, len));
}
void icmp_fix_checksum(struct icmp46 *icmp, size_t len, const struct ip6_hdr *ip6hdr)
{
if (ip6hdr)
icmp6_fix_checksum(icmp, len, ip6hdr);
else
icmp4_fix_checksum(icmp, len);
}

View File

@@ -11,6 +11,20 @@
#include <netinet/tcp.h>
#include <netinet/udp.h>
// icmp 4 and 6 are basically compatible although checksums are calculated differently
// do not use version specific structs
struct icmp46
{
uint8_t icmp_type, icmp_code;
uint16_t icmp_cksum;
union
{
uint32_t icmp_data32;
uint16_t icmp_data16[2];
uint8_t icmp_data8[4];
};
};
uint16_t csum_partial(const void *buff, size_t len);
uint16_t csum_tcpudp_magic(uint32_t saddr, uint32_t daddr, size_t len, uint8_t proto, uint16_t sum);
uint16_t csum_ipv6_magic(const void *saddr, const void *daddr, size_t len, uint8_t proto, uint16_t sum);
@@ -25,3 +39,7 @@ void tcp_fix_checksum(struct tcphdr *tcp,size_t len,const struct ip *ip,const st
void udp4_fix_checksum(struct udphdr *udp,size_t len, const struct in_addr *src_addr, const struct in_addr *dest_addr);
void udp6_fix_checksum(struct udphdr *udp,size_t len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr);
void udp_fix_checksum(struct udphdr *udp,size_t len,const struct ip *ip,const struct ip6_hdr *ip6hdr);
void icmp4_fix_checksum(struct icmp46 *icmp, size_t len);
void icmp6_fix_checksum(struct icmp46 *icmp, size_t len, const struct ip6_hdr *ip6hdr);
void icmp_fix_checksum(struct icmp46 *icmp, size_t len, const struct ip6_hdr *ip6hdr);

View File

@@ -70,7 +70,7 @@ void ConntrackPoolInit(t_conntrack *p, time_t purge_interval, uint32_t timeout_s
p->pool = NULL;
}
void ConntrackExtractConn(t_conn *c, bool bReverse, const struct dissect *dis)
bool ConntrackExtractConn(t_conn *c, bool bReverse, const struct dissect *dis)
{
memset(c, 0, sizeof(*c));
if (dis->ip)
@@ -86,8 +86,9 @@ void ConntrackExtractConn(t_conn *c, bool bReverse, const struct dissect *dis)
c->src.ip6 = bReverse ? dis->ip6->ip6_dst : dis->ip6->ip6_src;
}
else
c->l3proto = -1;
return false;
extract_ports(dis->tcp, dis->udp, &c->l4proto, bReverse ? &c->dport : &c->sport, bReverse ? &c->sport : &c->dport);
return c->l4proto!=IPPROTO_NONE;
}
@@ -225,7 +226,7 @@ static bool ConntrackPoolDoubleSearchPool(t_conntrack_pool **pp, const struct di
t_conn conn, connswp;
t_conntrack_pool *ctr;
ConntrackExtractConn(&conn, false, dis);
if (!ConntrackExtractConn(&conn, false, dis)) return false;
if ((ctr = ConntrackPoolSearch(*pp, &conn)))
{
if (bReverse) *bReverse = false;
@@ -256,7 +257,7 @@ static bool ConntrackPoolFeedPool(t_conntrack_pool **pp, const struct dissect *d
bool b_rev;
uint8_t proto = dis->tcp ? IPPROTO_TCP : dis->udp ? IPPROTO_UDP : IPPROTO_NONE;
ConntrackExtractConn(&conn, false, dis);
if (!ConntrackExtractConn(&conn, false, dis)) return false;
if ((ctr = ConntrackPoolSearch(*pp, &conn)))
{
ConntrackFeedPacket(&ctr->track, (b_rev = false), dis);
@@ -296,7 +297,7 @@ static bool ConntrackPoolDropPool(t_conntrack_pool **pp, const struct dissect *d
{
t_conn conn, connswp;
t_conntrack_pool *t;
ConntrackExtractConn(&conn, false, dis);
if (!ConntrackExtractConn(&conn, false, dis)) return false;
if (!(t = ConntrackPoolSearch(*pp, &conn)))
{
connswap(&conn, &connswp);

View File

@@ -105,7 +105,7 @@ bool ConntrackPoolFeed(t_conntrack *p, const struct dissect *dis, t_ctrack **ctr
// do not create, do not update. only find existing
bool ConntrackPoolDoubleSearch(t_conntrack *p, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse);
bool ConntrackPoolDrop(t_conntrack *p, const struct dissect *dis);
void ConntrackExtractConn(t_conn *c, bool bReverse, const struct dissect *dis);
bool ConntrackExtractConn(t_conn *c, bool bReverse, const struct dissect *dis);
void ConntrackPoolDump(const t_conntrack *p);
void ConntrackPoolPurge(t_conntrack *p);
void ConntrackClearHostname(t_ctrack *track);

View File

@@ -103,9 +103,6 @@ int hkdfExtract(SHAversion whichSha,
salt_len = USHAHashSize(whichSha);
memset(nullSalt, '\0', salt_len);
}
else if (salt_len < 0) {
return shaBadParam;
}
return hmac(whichSha, ikm, ikm_len, salt, salt_len, prk);
}
@@ -154,11 +151,7 @@ int hkdfExpand(SHAversion whichSha, const uint8_t prk[], size_t prk_len,
info = (const unsigned char *)"";
info_len = 0;
}
else if (info_len < 0) {
return shaBadParam;
}
if (okm_len <= 0) return shaBadParam;
if (!okm) return shaBadParam;
if (!okm || !okm_len) return shaBadParam;
hash_len = USHAHashSize(whichSha);
if (prk_len < hash_len) return shaBadParam;

View File

@@ -33,6 +33,8 @@
#define ERROR_INVALID_IMAGE_HASH __MSABI_LONG(577)
#endif
#include "nthacks.h"
#endif
#ifdef __linux__
@@ -102,7 +104,7 @@ void extract_ports(const struct tcphdr *tcphdr, const struct udphdr *udphdr, uin
{
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 (proto) *proto = tcphdr ? IPPROTO_TCP : udphdr ? IPPROTO_UDP : IPPROTO_NONE;
}
bool extract_dst(const uint8_t *data, size_t len, struct sockaddr* dst)
@@ -174,6 +176,11 @@ void extract_endpoints(const struct ip *ip,const struct ip6_hdr *ip6hdr,const st
si->sin6_scope_id = 0;
}
}
else
{
memset(src,0,sizeof(*src));
memset(dst,0,sizeof(*dst));
}
}
const char *proto_name(uint8_t proto)
@@ -192,8 +199,6 @@ const char *proto_name(uint8_t proto)
return "igmp";
case IPPROTO_ESP:
return "esp";
case IPPROTO_AH:
return "ah";
case IPPROTO_IPV6:
return "6in4";
case IPPROTO_IPIP:
@@ -210,7 +215,7 @@ const char *proto_name(uint8_t proto)
return NULL;
}
}
static void str_proto_name(char *s, size_t s_len, uint8_t proto)
void str_proto_name(char *s, size_t s_len, uint8_t proto)
{
const char *name = proto_name(proto);
if (name)
@@ -228,6 +233,56 @@ uint16_t family_from_proto(uint8_t l3proto)
}
}
const char *icmp_type_name(bool v6, uint8_t type)
{
if (v6)
{
switch(type)
{
case ICMP6_ECHO_REQUEST: return "echo_req6";
case ICMP6_ECHO_REPLY: return "echo_reply6";
case ICMP6_DST_UNREACH: return "dest_unreach6";
case ICMP6_PACKET_TOO_BIG: return "packet_too_big";
case ICMP6_TIME_EXCEEDED: return "time_exceeded6";
case ICMP6_PARAM_PROB: return "param_problem6";
case MLD_LISTENER_QUERY: return "mld_listener_query";
case MLD_LISTENER_REPORT: return "mld_listener_report";
case MLD_LISTENER_REDUCTION: return "mld_listener_reduction";
case ND_ROUTER_SOLICIT: return "router_sol";
case ND_ROUTER_ADVERT: return "router_adv";
case ND_NEIGHBOR_SOLICIT: return "neigh_sol";
case ND_NEIGHBOR_ADVERT: return "neigh_adv";
case ND_REDIRECT: return "redirect6";
}
}
else
{
switch(type)
{
case ICMP_ECHOREPLY: return "echo_reply";
case ICMP_DEST_UNREACH: return "dest_unreach";
case ICMP_REDIRECT: return "redirect";
case ICMP_ECHO: return "echo_req";
case ICMP_TIME_EXCEEDED: return "time_exceeded";
case ICMP_PARAMETERPROB: return "param_problem";
case ICMP_TIMESTAMP: return "ts";
case ICMP_TIMESTAMPREPLY: return "ts_reply";
case ICMP_INFO_REQUEST: return "info_req";
case ICMP_INFO_REPLY: return "info_reply";
}
}
return NULL;
}
void str_icmp_type_name(char *s, size_t s_len, bool v6, uint8_t type)
{
const char *name = icmp_type_name(v6, type);
if (name)
snprintf(s,s_len,"%s",name);
else
snprintf(s,s_len,"%u",type);
}
static void str_srcdst_ip(char *s, size_t s_len, const void *saddr,const void *daddr)
{
char s_ip[16],d_ip[16];
@@ -298,7 +353,21 @@ void print_udphdr(const struct udphdr *udphdr)
str_udphdr(s,sizeof(s),udphdr);
printf("%s",s);
}
void str_icmphdr(char *s, size_t s_len, bool v6, const struct icmp46 *icmp)
{
char stype[32];
str_icmp_type_name(stype,sizeof(stype),v6,icmp->icmp_type);
if (icmp->icmp_type==ICMP_ECHO || icmp->icmp_type==ICMP_ECHOREPLY || icmp->icmp_type==ICMP6_ECHO_REQUEST || icmp->icmp_type==ICMP6_ECHO_REPLY)
snprintf(s,s_len,"icmp_type=%s icmp_code=%u id=0x%04X seq=%u",stype,icmp->icmp_code,ntohs(icmp->icmp_data16[0]),ntohs(icmp->icmp_data16[1]));
else
snprintf(s,s_len,"icmp_type=%s icmp_code=%u data=0x%08X",stype,icmp->icmp_code,ntohl(icmp->icmp_data32));
}
void print_icmphdr(const struct icmp46 *icmp, bool v6)
{
char s[48];
str_icmphdr(s,sizeof(s),v6,icmp);
printf("%s",s);
}
@@ -340,7 +409,15 @@ void proto_skip_udp(const uint8_t **data, size_t *len)
*data += sizeof(struct udphdr);
*len -= sizeof(struct udphdr);
}
bool proto_check_icmp(const uint8_t *data, size_t len)
{
return len >= sizeof(struct icmp46);
}
void proto_skip_icmp(const uint8_t **data, size_t *len)
{
*data += sizeof(struct icmp46);
*len -= sizeof(struct icmp46);
}
bool proto_check_ipv6(const uint8_t *data, size_t len)
{
return len >= sizeof(struct ip6_hdr) && (data[0] & 0xF0) == 0x60;
@@ -449,7 +526,7 @@ uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto)
return NULL;
}
void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis)
void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis, bool no_payload_check)
{
const uint8_t *p;
@@ -466,7 +543,7 @@ void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis)
proto_skip_ipv4(&data, &len);
dis->len_l3 = data-p;
}
else if (proto_check_ipv6(data, len) && proto_check_ipv6_payload(data, len))
else if (proto_check_ipv6(data, len) && (no_payload_check || proto_check_ipv6_payload(data, len)))
{
dis->ip6 = (const struct ip6_hdr *) data;
p = data;
@@ -478,32 +555,37 @@ void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis)
return;
}
dis->transport_len = len;
if (dis->proto==IPPROTO_TCP && proto_check_tcp(data, len))
{
dis->tcp = (const struct tcphdr *) data;
dis->transport_len = len;
p = data;
proto_skip_tcp(&data, &len);
dis->len_l4 = data-p;
dis->data_payload = data;
dis->len_payload = len;
}
else if (dis->proto==IPPROTO_UDP && proto_check_udp(data, len) && proto_check_udp_payload(data, len))
else if (dis->proto==IPPROTO_UDP && proto_check_udp(data, len) && (no_payload_check || proto_check_udp_payload(data, len)))
{
dis->udp = (const struct udphdr *) data;
dis->transport_len = len;
p = data;
proto_skip_udp(&data, &len);
dis->len_l4 = data-p;
}
else if ((dis->proto==IPPROTO_ICMP || dis->proto==IPPROTO_ICMPV6) && proto_check_icmp(data, len))
{
dis->icmp = (const struct icmp46 *) data;
p = data;
proto_skip_icmp(&data, &len);
dis->len_l4 = data-p;
}
else
{
dis->len_l4 = 0;
}
dis->data_payload = data;
dis->len_payload = len;
}
}
void reverse_ip(struct ip *ip, struct ip6_hdr *ip6)
{
@@ -539,12 +621,137 @@ uint8_t ttl46(const struct ip *ip, const struct ip6_hdr *ip6)
}
bool get_source_ip4(const struct in_addr *target, struct in_addr *source)
{
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) return false;
struct sockaddr_in serv,name;
socklen_t namelen;
memset(&serv,0,sizeof(serv)); // or valgrind complains about uninitialized
serv.sin_family = AF_INET;
serv.sin_addr = *target;
serv.sin_port = 0xFFFF;
// Connect triggers the kernel's route lookup
if (!connect(sock, (const struct sockaddr*)&serv, sizeof(serv)))
{
namelen = sizeof(name);
if (!getsockname(sock, (struct sockaddr*)&name, &namelen))
{
close(sock);
*source = name.sin_addr;
return true;
}
}
close(sock);
return false;
}
bool get_source_ip6(const struct in6_addr *target, struct in6_addr *source)
{
int sock = socket(AF_INET6, SOCK_DGRAM, 0);
if (sock < 0) return false;
struct sockaddr_in6 serv,name;
socklen_t namelen;
memset(&serv,0,sizeof(serv)); // or valgrind complains about uninitialized
serv.sin6_family = AF_INET6;
serv.sin6_addr = *target;
serv.sin6_port = 0xFFFF;
// Connect triggers the kernel's route lookup
if (!connect(sock, (const struct sockaddr*)&serv, sizeof(serv)))
{
namelen = sizeof(name);
if (!getsockname(sock, (struct sockaddr*)&name, &namelen))
{
close(sock);
*source = name.sin6_addr;
return true;
}
}
close(sock);
return false;
}
#ifdef __CYGWIN__
uint32_t w_win32_error=0;
BOOL AdjustPrivileges(HANDLE hToken, const LPCTSTR *privs, BOOL bEnable)
{
DWORD dwSize, k, n;
PTOKEN_PRIVILEGES TokenPrivsData;
LUID luid;
dwSize = 0;
GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &dwSize ); // will fail
w_win32_error = GetLastError();
if (w_win32_error == ERROR_INSUFFICIENT_BUFFER)
{
w_win32_error = 0;
if (TokenPrivsData = (PTOKEN_PRIVILEGES)LocalAlloc(LMEM_FIXED, dwSize))
{
if (GetTokenInformation(hToken, TokenPrivileges, TokenPrivsData, dwSize, &dwSize))
{
n = 0;
while (privs[n])
{
if (LookupPrivilegeValue(NULL, privs[n], &luid))
{
w_win32_error = ERROR_PRIVILEGE_NOT_HELD;
for (k = 0; k < TokenPrivsData->PrivilegeCount; k++)
if (!memcmp(&TokenPrivsData->Privileges[k].Luid, &luid, sizeof(LUID)))
{
if (bEnable)
TokenPrivsData->Privileges[k].Attributes |= SE_PRIVILEGE_ENABLED;
else
TokenPrivsData->Privileges[k].Attributes &= ~SE_PRIVILEGE_ENABLED;
w_win32_error = 0;
break;
}
}
else
w_win32_error = GetLastError();
if (w_win32_error) break;
n++;
}
if (!w_win32_error)
{
if (!AdjustTokenPrivileges(hToken, FALSE, TokenPrivsData, 0, NULL, NULL))
w_win32_error = GetLastError();
}
}
else
w_win32_error = GetLastError();
LocalFree(TokenPrivsData);
}
else
w_win32_error = GetLastError();
}
return !w_win32_error;
}
BOOL AdjustPrivilegesForCurrentProcess(const LPCTSTR *privs, BOOL bEnable)
{
HANDLE hTokenThisProcess;
w_win32_error = 0;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hTokenThisProcess))
{
if (!AdjustPrivileges(hTokenThisProcess, privs, bEnable))
w_win32_error = GetLastError();
CloseHandle(hTokenThisProcess);
}
else
w_win32_error = GetLastError();
return !w_win32_error;
}
static BOOL RemoveTokenPrivs(void)
{
BOOL bRes = FALSE;
@@ -670,6 +877,26 @@ err:
if (!bRes) w_win32_error = GetLastError();
return bRes;
}
BOOL SetMandatoryLabelObject(HANDLE h, SE_OBJECT_TYPE ObjType, DWORD dwMandatoryLabelRID, DWORD dwAceRevision, DWORD dwAceFlags)
{
BOOL bRes = FALSE;
DWORD dwErr;
char buf_label[16], buf_pacl[32];
PSID label = (PSID)buf_label;
PACL pacl = (PACL)buf_pacl;
InitializeSid(label, &label_authority, 1);
*GetSidSubAuthority(label, 0) = dwMandatoryLabelRID;
if (InitializeAcl(pacl, sizeof(buf_pacl), ACL_REVISION) && AddMandatoryAce(pacl, dwAceRevision, dwAceFlags, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, label))
{
dwErr = SetSecurityInfo(h, ObjType, LABEL_SECURITY_INFORMATION, NULL, NULL, NULL, pacl);
SetLastError(dwErr);
bRes = dwErr == ERROR_SUCCESS;
}
if (!bRes) w_win32_error = GetLastError();
return bRes;
}
bool ensure_file_access(const char *filename)
{
@@ -703,6 +930,85 @@ bool prepare_low_appdata()
return b;
}
// cygwin uses nt directory to store it's state. low mandatory breaks write access there and cause some functions to fail
// it's not possible to reproduce exact directory names, have to iterate and set low integrity to all
BOOL RelaxCygwinNTDir()
{
NTSTATUS status;
PROCESS_SESSION_INFORMATION psi;
WCHAR bno_name[32], cyg_name[256];
CHAR scyg_name[256];
UNICODE_STRING bno_us, cyg_us;
OBJECT_ATTRIBUTES attr;
HANDLE hDir, hDirCyg;
BYTE buf[4096];
ULONG context, rsize;
BOOL b,ball,restart;
POBJECT_DIRECTORY_INFORMATION pdir;
LPCTSTR Privs[] = { SE_TAKE_OWNERSHIP_NAME , NULL };
if (!AdjustPrivilegesForCurrentProcess(Privs, TRUE))
return FALSE;
status = NtQueryInformationProcess(GetCurrentProcess(), ProcessSessionInformation, &psi, sizeof psi, NULL);
if (NT_SUCCESS(status))
swprintf(bno_name, sizeof(bno_name)/sizeof(*bno_name), L"\\Sessions\\BNOLINKS\\%u", psi.SessionId);
else
swprintf(bno_name, sizeof(bno_name)/sizeof(*bno_name), L"\\BaseNamedObjects");
RtlInitUnicodeString(&bno_us, bno_name);
InitializeObjectAttributes(&attr, &bno_us, 0, NULL, NULL);
ball = TRUE;
w_win32_error = 0;
status = NtOpenDirectoryObject(&hDir, DIRECTORY_QUERY, &attr);
if (NT_SUCCESS(status))
{
context = 0;
restart = TRUE;
while (NT_SUCCESS(status = NtQueryDirectoryObject(hDir, buf, sizeof(buf), restart, FALSE, &context, &rsize)))
{
for (pdir = (POBJECT_DIRECTORY_INFORMATION)buf; pdir->Name.Length; pdir++)
if (pdir->TypeName.Length == 18 && !memcmp(pdir->TypeName.Buffer, L"Directory", 18) &&
pdir->Name.Length >= 14 && !memcmp(pdir->Name.Buffer, L"cygwin1", 14))
{
swprintf(cyg_name, sizeof(cyg_name)/sizeof(*cyg_name), L"%ls\\%ls", bno_name, pdir->Name.Buffer);
if (!WideCharToMultiByte(CP_ACP, 0, cyg_name, -1, scyg_name, sizeof(scyg_name), NULL, NULL))
*scyg_name=0;
RtlInitUnicodeString(&cyg_us, cyg_name);
InitializeObjectAttributes(&attr, &cyg_us, 0, NULL, NULL);
status = NtOpenDirectoryObject(&hDirCyg, WRITE_OWNER, &attr);
if (NT_SUCCESS(status))
{
b = SetMandatoryLabelObject(hDirCyg, SE_KERNEL_OBJECT, SECURITY_MANDATORY_LOW_RID, ACL_REVISION_DS, 0);
if (!b)
{
w_win32_error = GetLastError();
DLOG_ERR("could not set integrity label on '%s' . error %u\n", scyg_name, w_win32_error);
}
else
DLOG("set low integrity label on '%s'\n", scyg_name);
ball = ball && b;
NtClose(hDirCyg);
}
}
restart = FALSE;
}
NtClose(hDir);
}
else
{
w_win32_error = RtlNtStatusToDosError(status);
return FALSE;
}
return ball;
}
BOOL JobSandbox()
{
BOOL bRes = FALSE;
@@ -734,6 +1040,9 @@ bool win_sandbox(void)
// there's no way to return privs
if (!b_sandbox_set)
{
if (!RelaxCygwinNTDir())
DLOG_ERR("could not set low mandatory label on cygwin NT directory. some functions may not work. error %u\n", w_win32_error);
if (!RemoveTokenPrivs())
return FALSE;
@@ -1961,6 +2270,23 @@ void verdict_udp_csum_fix(uint8_t verdict, struct udphdr *udphdr, size_t transpo
#endif
}
void verdict_icmp_csum_fix(uint8_t verdict, struct icmp46 *icmphdr, size_t transport_len, const struct ip6_hdr *ip6hdr)
{
// always fix csum for windivert. original can be partial or bad
// FreeBSD tend to pass ipv6 frames with wrong checksum (OBSERVED EARLIER, MAY BE FIXED NOW)
// Linux passes correct checksums
#ifndef __linux__
if (!(verdict & VERDICT_NOCSUM) && (verdict & VERDICT_MASK)==VERDICT_PASS)
{
#ifdef __FreeBSD__
if (ip6hdr)
#endif
DLOG("fixing icmp checksum\n");
icmp_fix_checksum(icmphdr,transport_len,ip6hdr);
}
#endif
}
void dbgprint_socket_buffers(int fd)
{
if (params.debug)

View File

@@ -25,6 +25,11 @@
#ifdef __CYGWIN__
#define INITGUID
#include "windivert/windivert.h"
#include "netinet/icmp6.h"
#include "netinet/ip_icmp.h"
#else
#include <netinet/icmp6.h>
#include <netinet/ip_icmp.h>
#endif
#ifndef IPPROTO_DIVERT
@@ -59,6 +64,31 @@
#define IPPROTO_SHIM6 140
#endif
#ifndef ICMP_DEST_UNREACH
#define ICMP_DEST_UNREACH 3
#endif
#ifndef ICMP_TIME_EXCEEDED
#define ICMP_TIME_EXCEEDED 11
#endif
#ifndef ICMP_PARAMETERPROB
#define ICMP_PARAMETERPROB 12
#endif
#ifndef ICMP_TIMESTAMP
#define ICMP_TIMESTAMP 13
#endif
#ifndef ICMP_TIMESTAMPREPLY
#define ICMP_TIMESTAMPREPLY 14
#endif
#ifndef ICMP_INFO_REQUEST
#define ICMP_INFO_REQUEST 15
#endif
#ifndef ICMP_INFO_REPLY
#define ICMP_INFO_REPLY 16
#endif
#ifndef MLD_LISTENER_REDUCTION
#define MLD_LISTENER_REDUCTION 132
#endif
// returns netorder value
uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment);
uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment);
@@ -85,6 +115,7 @@ uint16_t tcp_find_mss(const struct tcphdr *tcp);
bool tcp_synack_segment(const struct tcphdr *tcphdr);
bool tcp_syn_segment(const struct tcphdr *tcphdr);
bool make_writeable_dir();
bool ensure_file_access(const char *filename);
#ifdef __CYGWIN__
@@ -121,16 +152,21 @@ int socket_divert(sa_family_t family);
#endif
const char *proto_name(uint8_t proto);
void str_proto_name(char *s, size_t s_len, uint8_t proto);
const char *icmp_type_name(bool v6, uint8_t type);
void str_icmp_type_name(char *s, size_t s_len, bool v6, uint8_t type);
uint16_t family_from_proto(uint8_t l3proto);
void print_ip(const struct ip *ip);
void print_ip6hdr(const struct ip6_hdr *ip6hdr, uint8_t proto);
void print_tcphdr(const struct tcphdr *tcphdr);
void print_udphdr(const struct udphdr *udphdr);
void print_icmphdr(const struct icmp46 *icmp, bool v6);
void str_ip(char *s, size_t s_len, const struct ip *ip);
void str_ip6hdr(char *s, size_t s_len, const struct ip6_hdr *ip6hdr, uint8_t proto);
void str_srcdst_ip6(char *s, size_t s_len, const void *saddr,const void *daddr);
void str_tcphdr(char *s, size_t s_len, const struct tcphdr *tcphdr);
void str_udphdr(char *s, size_t s_len, const struct udphdr *udphdr);
void str_icmphdr(char *s, size_t s_len, bool v6, const struct icmp46 *icmp);
bool proto_check_ipv4(const uint8_t *data, size_t len);
void proto_skip_ipv4(const uint8_t **data, size_t *len);
@@ -143,6 +179,9 @@ void proto_skip_tcp(const uint8_t **data, size_t *len);
bool proto_check_udp(const uint8_t *data, size_t len);
bool proto_check_udp_payload(const uint8_t *data, size_t len);
void proto_skip_udp(const uint8_t **data, size_t *len);
bool proto_check_icmp(const uint8_t *data, size_t len);
void proto_skip_icmp(const uint8_t **data, size_t *len);
struct dissect
{
const uint8_t *data_pkt;
@@ -153,19 +192,24 @@ struct dissect
uint8_t proto;
const struct tcphdr *tcp;
const struct udphdr *udp;
const struct icmp46 *icmp;
size_t len_l4;
size_t transport_len;
const uint8_t *data_payload;
size_t len_payload;
};
void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis);
void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis, bool no_payload_check);
void reverse_ip(struct ip *ip, struct ip6_hdr *ip6);
void reverse_tcp(struct tcphdr *tcp);
uint8_t ttl46(const struct ip *ip, const struct ip6_hdr *ip6);
bool get_source_ip4(const struct in_addr *target, struct in_addr *source);
bool get_source_ip6(const struct in6_addr *target, struct in6_addr *source);
void verdict_tcp_csum_fix(uint8_t verdict, struct tcphdr *tcphdr, size_t transport_len, const struct ip *ip, const struct ip6_hdr *ip6hdr);
void verdict_udp_csum_fix(uint8_t verdict, struct udphdr *udphdr, size_t transport_len, const struct ip *ip, const struct ip6_hdr *ip6hdr);
void verdict_icmp_csum_fix(uint8_t verdict, struct icmp46 *icmphdr, size_t transport_len, const struct ip6_hdr *ip6hdr);
void dbgprint_socket_buffers(int fd);
bool set_socket_buffers(int fd, int rcvbuf, int sndbuf);

View File

@@ -132,11 +132,79 @@ static void TLSDebug(const uint8_t *tls, size_t sz)
TLSDebugHandshake(tls + 5, sz - 5);
}
static void packet_debug(bool replay, const struct dissect *dis)
{
if (params.debug)
{
if (replay) DLOG("REPLAY ");
if (dis->ip)
{
char s[66];
str_ip(s, sizeof(s), dis->ip);
DLOG("IP4: %s", s);
}
else if (dis->ip6)
{
char s[128];
str_ip6hdr(s, sizeof(s), dis->ip6, dis->proto);
DLOG("IP6: %s", s);
}
if (dis->tcp)
{
char s[80];
str_tcphdr(s, sizeof(s), dis->tcp);
DLOG(" %s\n", s);
if (dis->len_payload)
{
DLOG("TCP: len=%zu : ", dis->len_payload);
hexdump_limited_dlog(dis->data_payload, dis->len_payload, PKTDATA_MAXDUMP);
DLOG("\n");
}
}
else if (dis->udp)
{
char s[30];
str_udphdr(s, sizeof(s), dis->udp);
DLOG(" %s\n", s);
if (dis->len_payload)
{
DLOG("UDP: len=%zu : ", dis->len_payload);
hexdump_limited_dlog(dis->data_payload, dis->len_payload, PKTDATA_MAXDUMP);
DLOG("\n");
}
}
else if (dis->icmp)
{
char s[72];
str_icmphdr(s, sizeof(s), !!dis->ip6, dis->icmp);
DLOG(" %s\nICMP: len=%zu : ", s, dis->len_payload);
hexdump_limited_dlog(dis->data_payload, dis->len_payload, PKTDATA_MAXDUMP);
DLOG("\n");
}
else
{
if (dis->len_payload)
{
char s_proto[16];
str_proto_name(s_proto,sizeof(s_proto),dis->proto);
DLOG("\nIP PROTO %s: len=%zu : ", s_proto, dis->len_payload);
hexdump_limited_dlog(dis->data_payload, dis->len_payload, PKTDATA_MAXDUMP);
DLOG("\n");
}
else
DLOG("\n");
}
}
}
// ipr,ipr6 - reverse ip - ip of the other side of communication
static bool dp_match(
struct desync_profile *dp,
uint8_t l3proto,
const struct in_addr *ip, const struct in6_addr *ip6, uint16_t port,
const struct in_addr *ip, const struct in6_addr *ip6,
const struct in_addr *ipr, const struct in6_addr *ipr6,
uint16_t port, uint8_t icmp_type, uint8_t icmp_code,
const char *hostname, bool bNoSubdom, t_l7proto l7proto, const char *ssid,
bool *bCheckDone, bool *bCheckResult, bool *bExcluded)
{
@@ -150,8 +218,23 @@ static bool dp_match(
// L3 filter does not match
return false;
if ((l3proto == IPPROTO_TCP && !port_filters_in_range(&dp->pf_tcp, port)) || (l3proto == IPPROTO_UDP && !port_filters_in_range(&dp->pf_udp, port)))
// L4 filter does not match
switch(l3proto)
{
case IPPROTO_TCP:
if (!port_filters_match(&dp->pf_tcp, port)) return false;
break;
case IPPROTO_UDP:
if (!port_filters_match(&dp->pf_udp, port)) return false;
break;
case IPPROTO_ICMP:
if (!icmp_filters_match(&dp->icf, icmp_type, icmp_code)) return false;
break;
default:
if (!ipp_filters_match(&dp->ipf, l3proto)) return false;
}
if (l3proto == IPPROTO_ICMP && !icmp_filters_match(&dp->icf, icmp_type, icmp_code))
// icmp filter does not match
return false;
if (!l7_proto_match(l7proto, dp->filter_l7))
@@ -166,7 +249,7 @@ static bool dp_match(
if (!dp->hostlist_auto && !hostname && !bHostlistsEmpty)
// avoid cpu consuming ipset check. profile cannot win if regular hostlists are present without auto hostlist and hostname is unknown.
return false;
if (!IpsetCheck(dp, ip, ip6))
if (!IpsetCheck(dp, ip, ip6, ipr, ipr6))
// target ip does not match
return false;
@@ -197,7 +280,9 @@ static bool dp_match(
static struct desync_profile *dp_find(
struct desync_profile_list_head *head,
uint8_t l3proto,
const struct in_addr *ip, const struct in6_addr *ip6, uint16_t port,
const struct in_addr *ip, const struct in6_addr *ip6,
const struct in_addr *ipr, const struct in6_addr *ipr6,
uint16_t port, uint8_t icmp_type, uint8_t icmp_code,
const char *hostname, bool bNoSubdom, t_l7proto l7proto, const char *ssid,
bool *bCheckDone, bool *bCheckResult, bool *bExcluded)
{
@@ -206,12 +291,21 @@ static struct desync_profile *dp_find(
{
char s[40];
ntopa46(ip, ip6, s, sizeof(s));
DLOG("desync profile search for %s ip=%s port=%u l7proto=%s ssid='%s' hostname='%s'\n", proto_name(l3proto), s, port, l7proto_str(l7proto), ssid ? ssid : "", hostname ? hostname : "");
if (ipr || ipr6)
{
char sr[40];
ntopa46(ipr, ipr6, sr, sizeof(sr));
DLOG("desync profile search for %s ip1=%s ip2=%s port=%u icmp=%u:%u l7proto=%s ssid='%s' hostname='%s'\n",
proto_name(l3proto), s, sr, port, icmp_type, icmp_code, l7proto_str(l7proto), ssid ? ssid : "", hostname ? hostname : "");
}
else
DLOG("desync profile search for %s ip=%s port=%u icmp=%u:%u l7proto=%s ssid='%s' hostname='%s'\n",
proto_name(l3proto), s, port, icmp_type, icmp_code, l7proto_str(l7proto), ssid ? ssid : "", hostname ? hostname : "");
}
if (bCheckDone) *bCheckDone = false;
LIST_FOREACH(dpl, head, next)
{
if (dp_match(&dpl->dp, l3proto, ip, ip6, port, hostname, bNoSubdom, l7proto, ssid, bCheckDone, bCheckResult, bExcluded))
if (dp_match(&dpl->dp, l3proto, ip, ip6, ipr, ipr6, port, icmp_type, icmp_code, hostname, bNoSubdom, l7proto, ssid, bCheckDone, bCheckResult, bExcluded))
{
DLOG("desync profile %u (%s) matches\n", dpl->dp.n, PROFILE_NAME(&dpl->dp));
return &dpl->dp;
@@ -455,8 +549,8 @@ static bool reasm_start(t_ctrack *ctrack, t_reassemble *reasm, uint8_t proto, ui
static bool reasm_client_start(t_ctrack *ctrack, uint8_t proto, size_t sz, size_t szMax, const uint8_t *data_payload, size_t len_payload)
{
if (!ctrack) return false;
// if winsize_calc==0 it means we dont know server window size - no incoming packets redirected ?
if (proto==IPPROTO_TCP && ctrack->pos.server.winsize_calc && (ctrack->pos.server.winsize_calc < sz))
// if pcounter==0 it means we dont know server window size - no incoming packets redirected ?
if (proto==IPPROTO_TCP && ctrack->pos.server.pcounter && (ctrack->pos.server.winsize_calc < sz))
{
// this is rare but possible situation
// server gave us too small tcp window
@@ -640,6 +734,12 @@ static bool ipcache_get_hostname(const struct in_addr *a4, const struct in6_addr
*hostname = 0;
return true;
}
if (params.debug)
{
char s[40];
ntopa46(a4, a6, s, sizeof(s));
DLOG("ipcache hostname search for %s\n", s);
}
ip_cache_item *ipc = ipcacheTouch(&params.ipcache, a4, a6, NULL);
if (!ipc)
{
@@ -648,7 +748,12 @@ static bool ipcache_get_hostname(const struct in_addr *a4, const struct in6_addr
}
if (ipc->hostname)
{
DLOG("got cached hostname (is_ip=%u): %s\n", ipc->hostname_is_ip, ipc->hostname);
if (params.debug)
{
char s[40];
ntopa46(a4, a6, s, sizeof(s));
DLOG("got cached hostname for %s : %s (is_ip=%u)\n", s, ipc->hostname, ipc->hostname_is_ip);
}
snprintf(hostname, hostname_buf_len, "%s", ipc->hostname);
if (hostname_is_ip) *hostname_is_ip = ipc->hostname_is_ip;
}
@@ -968,7 +1073,7 @@ static uint8_t desync(
}
else
{
b = lua_reconstruct_dissect(params.L, -1, mod_pkt, len_mod_pkt, false, false);
b = lua_reconstruct_dissect(params.L, -1, mod_pkt, len_mod_pkt, false, false, false);
lua_pop(params.L, 2);
if (!b)
{
@@ -1116,7 +1221,7 @@ static bool play_prolog(
DLOG("using cached desync profile %u (%s)\n", ps->dp->n, PROFILE_NAME(ps->dp));
else if (!ps->ctrack_replay->dp_search_complete)
{
ps->dp = ps->ctrack_replay->dp = dp_find(&params.desync_profiles, dis->proto, ps->sdip4, ps->sdip6, ps->sdport, ps->ctrack_replay->hostname, ps->ctrack_replay->hostname_is_ip, ps->l7proto, ps->ssid, NULL, NULL, NULL);
ps->dp = ps->ctrack_replay->dp = dp_find(&params.desync_profiles, dis->proto, ps->sdip4, ps->sdip6, NULL, NULL, ps->sdport, 0xFF, 0xFF, ps->ctrack_replay->hostname, ps->ctrack_replay->hostname_is_ip, ps->l7proto, ps->ssid, NULL, NULL, NULL);
ps->ctrack_replay->dp_search_complete = true;
}
if (!ps->dp)
@@ -1164,7 +1269,7 @@ static bool play_prolog(
DLOG_ERR("strdup(host): out of memory\n");
}
}
ps->dp = dp_find(&params.desync_profiles, dis->proto, ps->sdip4, ps->sdip6, ps->sdport, hostname, hostname_is_ip, ps->l7proto, ps->ssid, NULL, NULL, NULL);
ps->dp = dp_find(&params.desync_profiles, dis->proto, ps->sdip4, ps->sdip6, NULL, NULL, ps->sdport, 0xFF, 0xFF, hostname, hostname_is_ip, ps->l7proto, ps->ssid, NULL, NULL, NULL);
if (ps->ctrack)
{
ps->ctrack->dp = ps->dp;
@@ -1249,7 +1354,7 @@ static bool dp_rediscovery(struct play_state *ps)
{
struct desync_profile *dp_prev = ps->dp;
// search for desync profile again. it may have changed.
ps->dp = dp_find(&params.desync_profiles, ps->dis->proto, ps->sdip4, ps->sdip6, ps->sdport,
ps->dp = dp_find(&params.desync_profiles, ps->dis->proto, ps->sdip4, ps->sdip6, NULL, NULL, ps->sdport, 0xFF, 0xFF,
ps->ctrack_replay ? ps->ctrack_replay->hostname : ps->bHaveHost ? ps->host : NULL,
ps->ctrack_replay ? ps->ctrack_replay->hostname_is_ip : bHostIsIp,
ps->l7proto, ps->ssid,
@@ -1782,43 +1887,202 @@ pass_reasm_cancel:
goto pass;
}
// conntrack is supported only for RELATED icmp
// ip matched in both directions if conntrack is unavailable
static uint8_t dpi_desync_icmp_packet(
uint32_t fwmark,
const char *ifin, const char *ifout,
const struct dissect *dis,
uint8_t *mod_pkt, size_t *len_mod_pkt)
{
uint8_t verdict = VERDICT_PASS;
static void packet_debug(bool replay, const struct dissect *dis)
// additional safety check
if (!!dis->ip == !!dis->ip6) return verdict;
const uint8_t *pkt_attached;
size_t len_attached;
const char *ifname;
struct sockaddr_storage src, dst;
const char *ssid = NULL;
struct desync_profile *dp = NULL;
t_l7payload l7payload = L7P_UNKNOWN;
t_ctrack *ctrack = NULL;
bool bReverse, bReverseFixed;
extract_endpoints(dis->ip, dis->ip6, NULL, NULL, &src, &dst);
switch(dis->icmp->icmp_type)
{
if (params.debug)
{
if (replay) DLOG("REPLAY ");
if (dis->ip)
{
char s[66];
str_ip(s, sizeof(s), dis->ip);
DLOG("IP4: %s", s);
case ICMP_DEST_UNREACH:
case ICMP_TIME_EXCEEDED:
case ICMP_PARAMETERPROB:
case ICMP_REDIRECT:
case ICMP6_DST_UNREACH:
//case ICMP6_TIME_EXCEEDED: // same as ICMP_TIME_EXCEEDED = 3
case ICMP6_PACKET_TOO_BIG:
case ICMP6_PARAM_PROB:
pkt_attached = dis->data_payload;
break;
default:
pkt_attached = NULL;
}
else if (dis->ip6)
if (pkt_attached)
{
char s[128];
str_ip6hdr(s, sizeof(s), dis->ip6, dis->proto);
DLOG("IP6: %s", s);
struct dissect adis;
len_attached = pkt_attached - dis->data_payload + dis->len_payload;
proto_dissect_l3l4(pkt_attached, len_attached, &adis, true); // dissect without payload length checks - can be partial
if (!dis->ip && !dis->ip6)
DLOG("attached packet is invalid\n");
else
{
l7payload = dis->ip ? L7P_IPV4 : L7P_IPV6;
DLOG("attached packet\n");
packet_debug(false, &adis);
if (ConntrackPoolDoubleSearch(&params.conntrack, &adis, &ctrack, &bReverse))
{
// invert direction. they are answering to this packet
bReverse = !bReverse;
DLOG("found conntrack entry. inverted reverse=%u\n",bReverse);
if (ctrack->dp_search_complete)
{
// RELATED icmp processed within base connection profile
dp = ctrack->dp;
DLOG("using desync profile %u (%s) from conntrack entry\n", dp->n, PROFILE_NAME(dp));
}
if (dis->tcp)
{
char s[80];
str_tcphdr(s, sizeof(s), dis->tcp);
DLOG(" %s\n", s);
if (dis->len_payload) { DLOG("TCP: len=%zu : ", dis->len_payload); hexdump_limited_dlog(dis->data_payload, dis->len_payload, PKTDATA_MAXDUMP); DLOG("\n"); }
}
else if (dis->udp)
{
char s[30];
str_udphdr(s, sizeof(s), dis->udp);
DLOG(" %s\n", s);
if (dis->len_payload) { DLOG("UDP: len=%zu : ", dis->len_payload); hexdump_limited_dlog(dis->data_payload, dis->len_payload, PKTDATA_MAXDUMP); DLOG("\n"); }
}
else
DLOG("\n");
DLOG("conntrack entry not found\n");
}
}
bReverseFixed = ctrack ? (bReverse ^ params.server) : (bReverse = ifin && *ifin && (!ifout || !*ifout));
#ifdef HAS_FILTER_SSID
ifname = bReverse ? ifin : ifout;
if ((ssid = wlan_ssid_search_ifname(ifname)))
DLOG("found ssid for %s : %s\n", ifname, ssid);
else if (!ctrack)
{
// we dont know direction for sure
// search opposite interface
ifname = bReverse ? ifout : ifin;
if ((ssid = wlan_ssid_search_ifname(ifname)))
DLOG("found ssid for %s : %s\n", ifname, ssid);
}
#endif
if (!dp)
{
bool hostname_is_ip = false;
char host[256];
const char *hostname = NULL;
if (ctrack && ctrack->hostname)
{
printf("ZZZZZz4 %p\n",ctrack->hostname);
hostname = ctrack->hostname;
hostname_is_ip = ctrack->hostname_is_ip;
}
else if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL, host, sizeof(host), &hostname_is_ip) && *host ||
ipcache_get_hostname(dis->ip ? &dis->ip->ip_src : NULL, dis->ip6 ? &dis->ip6->ip6_src : NULL, host, sizeof(host), &hostname_is_ip) && *host)
{
hostname = host;
}
dp = dp_find(
&params.desync_profiles,
dis->proto,
dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL,
dis->ip ? &dis->ip->ip_src : NULL, dis->ip6 ? &dis->ip6->ip6_src : NULL,
0, dis->icmp->icmp_type, dis->icmp->icmp_code,
hostname, hostname_is_ip,
L7_UNKNOWN, ssid, NULL, NULL, NULL);
if (!dp)
{
DLOG("matching desync profile not found\n");
return verdict;
}
}
const struct in_addr *sdip4;
const struct in6_addr *sdip6;
sdip6 = dis->ip6 ? bReverseFixed ? &dis->ip6->ip6_src : &dis->ip6->ip6_dst : NULL;
sdip4 = dis->ip ? bReverseFixed ? &dis->ip->ip_src : &dis->ip->ip_dst : NULL;
verdict = desync(
dp, fwmark, ifin, ifout, bReverseFixed, ctrack, NULL, l7payload, L7_UNKNOWN,
dis, sdip4, sdip6, 0, mod_pkt, len_mod_pkt, 0, 0, 0, NULL, 0, NULL, 0);
return verdict;
}
// undissected l4+
// conntrack is unsupported
// ip matched in both directions
static uint8_t dpi_desync_ip_packet(
uint32_t fwmark,
const char *ifin, const char *ifout,
const struct dissect *dis,
uint8_t *mod_pkt, size_t *len_mod_pkt)
{
uint8_t verdict = VERDICT_PASS;
// additional safety check
if (!!dis->ip == !!dis->ip6) return verdict;
struct sockaddr_storage src, dst;
const char *ssid;
struct desync_profile *dp;
extract_endpoints(dis->ip, dis->ip6, NULL, NULL, &src, &dst);
#ifdef HAS_FILTER_SSID
if ((ssid = wlan_ssid_search_ifname(ifin)))
DLOG("found ssid for %s : %s\n", ifin, ssid);
else
{
// we dont know direction for sure
// search opposite interface
if ((ssid = wlan_ssid_search_ifname(ifout)))
DLOG("found ssid for %s : %s\n", ifout, ssid);
}
#endif
bool hostname_is_ip = false;
const char *hostname = NULL;
char host[256];
if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL, host, sizeof(host), &hostname_is_ip) && *host ||
ipcache_get_hostname(dis->ip ? &dis->ip->ip_src : NULL, dis->ip6 ? &dis->ip6->ip6_src : NULL, host, sizeof(host), &hostname_is_ip) && *host)
{
hostname = host;
}
dp = dp_find(
&params.desync_profiles,
dis->proto,
dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL,
dis->ip ? &dis->ip->ip_src : NULL, dis->ip6 ? &dis->ip6->ip6_src : NULL,
0, 0xFF, 0xFF,
hostname, hostname_is_ip,
L7_UNKNOWN, ssid, NULL, NULL, NULL);
if (!dp)
{
DLOG("matching desync profile not found\n");
return verdict;
}
bool bReverse = ifin && *ifin && (!ifout || !*ifout);
const struct in_addr *sdip4;
const struct in6_addr *sdip6;
sdip6 = dis->ip6 ? bReverse ? &dis->ip6->ip6_src : &dis->ip6->ip6_dst : NULL;
sdip4 = dis->ip ? bReverse ? &dis->ip->ip_src : &dis->ip->ip_dst : NULL;
verdict = desync(
dp, fwmark, ifin, ifout, bReverse, NULL, NULL, L7P_UNKNOWN, L7_UNKNOWN,
dis, sdip4, sdip6, 0, mod_pkt, len_mod_pkt, 0, 0, 0, NULL, 0, NULL, 0);
return verdict;
}
static uint8_t dpi_desync_packet_play(
unsigned int replay_piece, unsigned int replay_piece_count, size_t reasm_offset, uint32_t fwmark, const char *ifin, const char *ifout,
@@ -1831,19 +2095,19 @@ static uint8_t dpi_desync_packet_play(
// NOTE ! OS can pass wrong checksum to queue. cannot rely on it !
proto_dissect_l3l4(data_pkt, len_pkt, &dis);
proto_dissect_l3l4(data_pkt, len_pkt, &dis, false);
if (!!dis.ip != !!dis.ip6)
{
packet_debug(!!replay_piece_count, &dis);
// fix csum if unmodified and if OS can pass wrong csum to queue (depends on OS)
// modified means we have already fixed the checksum or made it invalid intentionally
// this is the only point we VIOLATE const to fix the checksum in the original buffer to avoid copying to mod_pkt
switch (dis.proto)
{
case IPPROTO_TCP:
if (dis.tcp)
{
verdict = dpi_desync_tcp_packet_play(replay_piece, replay_piece_count, reasm_offset, fwmark, ifin, ifout, tpos, &dis, mod_pkt, len_mod_pkt);
// fix csum if unmodified and if OS can pass wrong csum to queue (depends on OS)
// modified means we have already fixed the checksum or made it invalid intentionally
// this is the only point we VIOLATE const to fix the checksum in the original buffer to avoid copying to mod_pkt
verdict_tcp_csum_fix(verdict, (struct tcphdr *)dis.tcp, dis.transport_len, dis.ip, dis.ip6);
}
break;
@@ -1851,12 +2115,19 @@ static uint8_t dpi_desync_packet_play(
if (dis.udp)
{
verdict = dpi_desync_udp_packet_play(replay_piece, replay_piece_count, reasm_offset, fwmark, ifin, ifout, tpos, &dis, mod_pkt, len_mod_pkt);
// fix csum if unmodified and if OS can pass wrong csum to queue (depends on OS)
// modified means we have already fixed the checksum or made it invalid intentionally
// this is the only point we VIOLATE const to fix the checksum in the original buffer to avoid copying to mod_pkt
verdict_udp_csum_fix(verdict, (struct udphdr *)dis.udp, dis.transport_len, dis.ip, dis.ip6);
}
break;
case IPPROTO_ICMP:
case IPPROTO_ICMPV6:
if (dis.icmp)
{
verdict = dpi_desync_icmp_packet(fwmark, ifin, ifout, &dis, mod_pkt, len_mod_pkt);
verdict_icmp_csum_fix(verdict, (struct icmp46 *)dis.icmp, dis.transport_len, dis.ip6);
}
break;
default:
verdict = dpi_desync_ip_packet(fwmark, ifin, ifout, &dis, mod_pkt, len_mod_pkt);
}
}
return verdict;

236
nfq2/filter.c Normal file
View File

@@ -0,0 +1,236 @@
#include "filter.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
bool pf_match(uint16_t port, const port_filter *pf)
{
return port && (((!pf->from && !pf->to) || (port>=pf->from && port<=pf->to)) ^ pf->neg);
}
bool pf_parse(const char *s, port_filter *pf)
{
unsigned int v1,v2;
char c;
if (!s) return false;
if (*s=='*' && s[1]==0)
{
pf->from=1; pf->to=0xFFFF;
return true;
}
if (*s=='~')
{
pf->neg=true;
s++;
}
else
pf->neg=false;
if (sscanf(s,"%u-%u%c",&v1,&v2,&c)==2)
{
if (v1>65535 || v2>65535 || v1>v2) return false;
pf->from=(uint16_t)v1;
pf->to=(uint16_t)v2;
}
else if (sscanf(s,"%u%c",&v1,&c)==1)
{
if (v1>65535) return false;
pf->to=pf->from=(uint16_t)v1;
}
else
return false;
// deny all case
if (!pf->from && !pf->to) pf->neg=true;
return true;
}
static bool fltmode_parse(const char *s, uint8_t *mode)
{
if (*s=='*' && !s[1])
{
*mode = FLTMODE_ANY;
return true;
}
else if (*s=='-' && !s[1])
{
*mode = FLTMODE_SKIP;
return true;
}
*mode = FLTMODE_SKIP;
return false;
}
bool icf_match(uint8_t type, uint8_t code, const icmp_filter *icf)
{
return icf->mode==FLTMODE_ANY || icf->mode==FLTMODE_FILTER && icf->type==type && (!icf->code_valid || icf->code==code);
}
bool icf_parse(const char *s, icmp_filter *icf)
{
unsigned int u1,u2;
char c1,c2;
icf->type = icf->code = 0;
icf->code_valid = false;
if (fltmode_parse(s, &icf->mode)) return true;
switch(sscanf(s,"%u%c%u%c",&u1,&c1,&u2,&c2))
{
case 1:
if (u1>0xFF) return false;
icf->type = (uint8_t)u1;
icf->mode = FLTMODE_FILTER;
break;
case 3:
if (c1!=':' || (u1>0xFF) || (u2>0xFF)) return false;
icf->type = (uint8_t)u1;
icf->code = (uint8_t)u2;
icf->code_valid = true;
icf->mode = FLTMODE_FILTER;
break;
default:
icf->mode = FLTMODE_SKIP;
return false;
}
return true;
}
bool ipp_match(uint8_t proto, const ipp_filter *ipp)
{
return ipp->mode==FLTMODE_ANY || ipp->mode==FLTMODE_FILTER && ipp->proto==proto;
}
bool ipp_parse(const char *s, ipp_filter *ipp)
{
unsigned int u1;
char c;
ipp->proto = 0xFF;
if (fltmode_parse(s, &ipp->mode)) return true;
if (sscanf(s,"%u%c",&u1,&c)!=1 || u1>0xFF) return false;
ipp->proto = (uint8_t)u1;
ipp->mode = FLTMODE_FILTER;
return true;
}
bool packet_pos_parse(const char *s, struct packet_pos *pos)
{
if (*s!='n' && *s!='d' && *s!='s' && *s!='p' && *s!='b' && *s!='x' && *s!='a') return false;
pos->mode=*s;
if (pos->mode=='x' || pos->mode=='a')
{
pos->pos=0;
return true;
}
return sscanf(s+1,"%u",&pos->pos)==1;
}
bool packet_range_parse(const char *s, struct packet_range *range)
{
const char *p;
range->upper_cutoff = false;
if (*s=='-' || *s=='<')
{
range->from = PACKET_POS_ALWAYS;
range->upper_cutoff = *s=='<';
}
else
{
if (!packet_pos_parse(s,&range->from)) return false;
if (range->from.mode=='x')
{
range->to = range->from;
return true;
}
if (!(p = strchr(s,'-')))
p = strchr(s,'<');
if (p)
{
s = p;
range->upper_cutoff = *s=='<';
}
else
{
if (range->from.mode=='a')
{
range->to = range->from;
return true;
}
return false;
}
}
s++;
if (*s)
{
return packet_pos_parse(s,&range->to);
}
else
{
range->to = PACKET_POS_ALWAYS;
return true;
}
}
void str_cidr4(char *s, size_t s_len, const struct cidr4 *cidr)
{
char s_ip[16];
*s_ip=0;
inet_ntop(AF_INET, &cidr->addr, s_ip, sizeof(s_ip));
snprintf(s,s_len,cidr->preflen<32 ? "%s/%u" : "%s", s_ip, cidr->preflen);
}
void print_cidr4(const struct cidr4 *cidr)
{
char s[19];
str_cidr4(s,sizeof(s),cidr);
printf("%s",s);
}
void str_cidr6(char *s, size_t s_len, const struct cidr6 *cidr)
{
char s_ip[40];
*s_ip=0;
inet_ntop(AF_INET6, &cidr->addr, s_ip, sizeof(s_ip));
snprintf(s,s_len,cidr->preflen<128 ? "%s/%u" : "%s", s_ip, cidr->preflen);
}
void print_cidr6(const struct cidr6 *cidr)
{
char s[44];
str_cidr6(s,sizeof(s),cidr);
printf("%s",s);
}
bool parse_cidr4(char *s, struct cidr4 *cidr)
{
char *p,d;
bool b;
unsigned int plen;
if ((p = strchr(s, '/')))
{
if (sscanf(p + 1, "%u", &plen)!=1 || plen>32)
return false;
cidr->preflen = (uint8_t)plen;
d=*p; *p=0; // backup char
}
else
cidr->preflen = 32;
b = (inet_pton(AF_INET, s, &cidr->addr)==1);
if (p) *p=d; // restore char
return b;
}
bool parse_cidr6(char *s, struct cidr6 *cidr)
{
char *p,d;
bool b;
unsigned int plen;
if ((p = strchr(s, '/')))
{
if (sscanf(p + 1, "%u", &plen)!=1 || plen>128)
return false;
cidr->preflen = (uint8_t)plen;
d=*p; *p=0; // backup char
}
else
cidr->preflen = 128;
b = (inet_pton(AF_INET6, s, &cidr->addr)==1);
if (p) *p=d; // restore char
return b;
}

64
nfq2/filter.h Normal file
View File

@@ -0,0 +1,64 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <netinet/in.h>
typedef struct
{
uint16_t from,to;
bool neg;
} port_filter;
bool pf_match(uint16_t port, const port_filter *pf);
bool pf_parse(const char *s, port_filter *pf);
#define FLTMODE_SKIP 0
#define FLTMODE_ANY 1
#define FLTMODE_FILTER 2
typedef struct
{
uint8_t mode, type, code;
bool code_valid;
} icmp_filter;
bool icf_match(uint8_t type, uint8_t code, const icmp_filter *icf);
bool icf_parse(const char *s, icmp_filter *icf);
typedef struct
{
uint8_t mode, proto;
} ipp_filter;
bool ipp_match(uint8_t proto, const ipp_filter *ipp);
bool ipp_parse(const char *s, ipp_filter *ipp);
struct packet_pos
{
char mode; // n - packets, d - data packets, s - relative sequence
unsigned int pos;
};
struct packet_range
{
struct packet_pos from, to;
bool upper_cutoff; // true - do not include upper limit, false - include upper limit
};
#define PACKET_POS_NEVER (struct packet_pos){'x',0}
#define PACKET_POS_ALWAYS (struct packet_pos){'a',0}
#define PACKET_RANGE_NEVER (struct packet_range){PACKET_POS_NEVER,PACKET_POS_NEVER}
#define PACKET_RANGE_ALWAYS (struct packet_range){PACKET_POS_ALWAYS,PACKET_POS_ALWAYS}
bool packet_range_parse(const char *s, struct packet_range *range);
struct cidr4
{
struct in_addr addr;
uint8_t preflen;
};
struct cidr6
{
struct in6_addr addr;
uint8_t preflen;
};
void str_cidr4(char *s, size_t s_len, const struct cidr4 *cidr);
void print_cidr4(const struct cidr4 *cidr);
void str_cidr6(char *s, size_t s_len, const struct cidr6 *cidr);
void print_cidr6(const struct cidr6 *cidr);
bool parse_cidr4(char *s, struct cidr4 *cidr);
bool parse_cidr6(char *s, struct cidr6 *cidr);

View File

@@ -448,107 +448,6 @@ bool file_open_test(const char *filename, int flags)
return false;
}
bool pf_in_range(uint16_t port, const port_filter *pf)
{
return port && (((!pf->from && !pf->to) || (port>=pf->from && port<=pf->to)) ^ pf->neg);
}
bool pf_parse(const char *s, port_filter *pf)
{
unsigned int v1,v2;
char c;
if (!s) return false;
if (*s=='*' && s[1]==0)
{
pf->from=1; pf->to=0xFFFF;
return true;
}
if (*s=='~')
{
pf->neg=true;
s++;
}
else
pf->neg=false;
if (sscanf(s,"%u-%u%c",&v1,&v2,&c)==2)
{
if (v1>65535 || v2>65535 || v1>v2) return false;
pf->from=(uint16_t)v1;
pf->to=(uint16_t)v2;
}
else if (sscanf(s,"%u%c",&v1,&c)==1)
{
if (v1>65535) return false;
pf->to=pf->from=(uint16_t)v1;
}
else
return false;
// deny all case
if (!pf->from && !pf->to) pf->neg=true;
return true;
}
bool pf_is_empty(const port_filter *pf)
{
return !pf->neg && !pf->from && !pf->to;
}
bool packet_pos_parse(const char *s, struct packet_pos *pos)
{
if (*s!='n' && *s!='d' && *s!='s' && *s!='p' && *s!='b' && *s!='x' && *s!='a') return false;
pos->mode=*s;
if (pos->mode=='x' || pos->mode=='a')
{
pos->pos=0;
return true;
}
return sscanf(s+1,"%u",&pos->pos)==1;
}
bool packet_range_parse(const char *s, struct packet_range *range)
{
const char *p;
range->upper_cutoff = false;
if (*s=='-' || *s=='<')
{
range->from = PACKET_POS_ALWAYS;
range->upper_cutoff = *s=='<';
}
else
{
if (!packet_pos_parse(s,&range->from)) return false;
if (range->from.mode=='x')
{
range->to = range->from;
return true;
}
if (!(p = strchr(s,'-')))
p = strchr(s,'<');
if (p)
{
s = p;
range->upper_cutoff = *s=='<';
}
else
{
if (range->from.mode=='a')
{
range->to = range->from;
return true;
}
return false;
}
}
s++;
if (*s)
{
return packet_pos_parse(s,&range->to);
}
else
{
range->to = PACKET_POS_ALWAYS;
return true;
}
}
void fill_random_bytes(uint8_t *p,size_t sz)
{
@@ -581,12 +480,55 @@ bool fill_crypto_random_bytes(uint8_t *p,size_t sz)
return b;
}
#if defined(__GNUC__) && !defined(__llvm__)
__attribute__((optimize ("no-strict-aliasing")))
#endif
void bxor(const uint8_t *x1, const uint8_t *x2, uint8_t *result, size_t sz)
{
for (; sz>=8 ; x1+=8, x2+=8, result+=8, sz-=8)
*(uint64_t*)result = *(uint64_t*)x1 ^ *(uint64_t*)x2;
for (; sz ; x1++, x2++, result++, sz--)
*result = *x1 ^ *x2;
}
#if defined(__GNUC__) && !defined(__llvm__)
__attribute__((optimize ("no-strict-aliasing")))
#endif
void bor(const uint8_t *x1, const uint8_t *x2, uint8_t *result, size_t sz)
{
for (; sz>=8 ; x1+=8, x2+=8, result+=8, sz-=8)
*(uint64_t*)result = *(uint64_t*)x1 | *(uint64_t*)x2;
for (; sz ; x1++, x2++, result++, sz--)
*result = *x1 | *x2;
}
#if defined(__GNUC__) && !defined(__llvm__)
__attribute__((optimize ("no-strict-aliasing")))
#endif
void band(const uint8_t *x1, const uint8_t *x2, uint8_t *result, size_t sz)
{
for (; sz>=8 ; x1+=8, x2+=8, result+=8, sz-=8)
*(uint64_t*)result = *(uint64_t*)x1 & *(uint64_t*)x2;
for (; sz ; x1++, x2++, result++, sz--)
*result = *x1 & *x2;
}
void set_console_io_buffering(void)
{
setvbuf(stdout, NULL, _IOLBF, 0);
setvbuf(stderr, NULL, _IOLBF, 0);
}
void close_std(void)
{
// free memory allocated by setvbuf
fclose(stdout);
fclose(stderr);
}
void close_std_and_exit(int code)
{
close_std();
exit(code);
}
bool set_env_exedir(const char *argv0)
{
@@ -601,73 +543,6 @@ bool set_env_exedir(const char *argv0)
return bOK;
}
void str_cidr4(char *s, size_t s_len, const struct cidr4 *cidr)
{
char s_ip[16];
*s_ip=0;
inet_ntop(AF_INET, &cidr->addr, s_ip, sizeof(s_ip));
snprintf(s,s_len,cidr->preflen<32 ? "%s/%u" : "%s", s_ip, cidr->preflen);
}
void print_cidr4(const struct cidr4 *cidr)
{
char s[19];
str_cidr4(s,sizeof(s),cidr);
printf("%s",s);
}
void str_cidr6(char *s, size_t s_len, const struct cidr6 *cidr)
{
char s_ip[40];
*s_ip=0;
inet_ntop(AF_INET6, &cidr->addr, s_ip, sizeof(s_ip));
snprintf(s,s_len,cidr->preflen<128 ? "%s/%u" : "%s", s_ip, cidr->preflen);
}
void print_cidr6(const struct cidr6 *cidr)
{
char s[44];
str_cidr6(s,sizeof(s),cidr);
printf("%s",s);
}
bool parse_cidr4(char *s, struct cidr4 *cidr)
{
char *p,d;
bool b;
unsigned int plen;
if ((p = strchr(s, '/')))
{
if (sscanf(p + 1, "%u", &plen)!=1 || plen>32)
return false;
cidr->preflen = (uint8_t)plen;
d=*p; *p=0; // backup char
}
else
cidr->preflen = 32;
b = (inet_pton(AF_INET, s, &cidr->addr)==1);
if (p) *p=d; // restore char
return b;
}
bool parse_cidr6(char *s, struct cidr6 *cidr)
{
char *p,d;
bool b;
unsigned int plen;
if ((p = strchr(s, '/')))
{
if (sscanf(p + 1, "%u", &plen)!=1 || plen>128)
return false;
cidr->preflen = (uint8_t)plen;
d=*p; *p=0; // backup char
}
else
cidr->preflen = 128;
b = (inet_pton(AF_INET6, s, &cidr->addr)==1);
if (p) *p=d; // restore char
return b;
}
bool parse_int16(const char *p, int16_t *v)
{
if (*p == '+' || *p == '-' || *p >= '0' && *p <= '9')
@@ -678,3 +553,29 @@ bool parse_int16(const char *p, int16_t *v)
}
return false;
}
uint32_t mask_from_bitcount(uint32_t zct)
{
return zct<32 ? ~((1u << zct) - 1) : 0;
}
static void mask_from_bitcount6_make(uint32_t zct, struct in6_addr *a)
{
if (zct >= 128)
memset(a->s6_addr,0x00,16);
else
{
int32_t n = (127 - zct) >> 3;
memset(a->s6_addr,0xFF,n);
memset(a->s6_addr+n,0x00,16-n);
a->s6_addr[n] = ~((1u << (zct & 7)) - 1);
}
}
static struct in6_addr ip6_mask[129];
void mask_from_bitcount6_prepare(void)
{
for (int zct=0;zct<=128;zct++) mask_from_bitcount6_make(zct, ip6_mask+zct);
}
const struct in6_addr *mask_from_bitcount6(uint32_t zct)
{
return ip6_mask+zct;
}

View File

@@ -85,55 +85,22 @@ time_t file_mod_time(const char *filename);
bool file_size(const char *filename, off_t *size);
bool file_open_test(const char *filename, int flags);
typedef struct
{
uint16_t from,to;
bool neg;
} port_filter;
bool pf_in_range(uint16_t port, const port_filter *pf);
bool pf_parse(const char *s, port_filter *pf);
bool pf_is_empty(const port_filter *pf);
struct packet_pos
{
char mode; // n - packets, d - data packets, s - relative sequence
unsigned int pos;
};
struct packet_range
{
struct packet_pos from, to;
bool upper_cutoff; // true - do not include upper limit, false - include upper limit
};
#define PACKET_POS_NEVER (struct packet_pos){'x',0}
#define PACKET_POS_ALWAYS (struct packet_pos){'a',0}
#define PACKET_RANGE_NEVER (struct packet_range){PACKET_POS_NEVER,PACKET_POS_NEVER}
#define PACKET_RANGE_ALWAYS (struct packet_range){PACKET_POS_ALWAYS,PACKET_POS_ALWAYS}
bool packet_range_parse(const char *s, struct packet_range *range);
void fill_random_bytes(uint8_t *p,size_t sz);
void fill_random_az(uint8_t *p,size_t sz);
void fill_random_az09(uint8_t *p,size_t sz);
bool fill_crypto_random_bytes(uint8_t *p,size_t sz);
void bxor(const uint8_t *x1, const uint8_t *x2, uint8_t *result, size_t sz);
void band(const uint8_t *x1, const uint8_t *x2, uint8_t *result, size_t sz);
void bor(const uint8_t *x1, const uint8_t *x2, uint8_t *result, size_t sz);
void set_console_io_buffering(void);
void close_std(void);
void close_std_and_exit(int code);
bool set_env_exedir(const char *argv0);
struct cidr4
{
struct in_addr addr;
uint8_t preflen;
};
struct cidr6
{
struct in6_addr addr;
uint8_t preflen;
};
void str_cidr4(char *s, size_t s_len, const struct cidr4 *cidr);
void print_cidr4(const struct cidr4 *cidr);
void str_cidr6(char *s, size_t s_len, const struct cidr6 *cidr);
void print_cidr6(const struct cidr6 *cidr);
bool parse_cidr4(char *s, struct cidr4 *cidr);
bool parse_cidr6(char *s, struct cidr6 *cidr);
bool parse_int16(const char *p, int16_t *v);
uint32_t mask_from_bitcount(uint32_t zct);
void mask_from_bitcount6_prepare(void);
const struct in6_addr *mask_from_bitcount6(uint32_t zct);

View File

@@ -42,7 +42,7 @@ bool AppendHostlistItem(hostlist_pool **hostlist, char *s)
bool AppendHostList(hostlist_pool **hostlist, const char *filename)
{
char *p, *e, s[256], *zbuf;
char *p, *e, s[4096], *zbuf;
size_t zsize;
int ct = 0;
FILE *F;

View File

@@ -59,7 +59,7 @@ bool AppendIpsetItem(ipset *ips, char *ip)
static bool AppendIpset(ipset *ips, const char *filename)
{
char *p, *e, s[256], *zbuf;
char *p, *e, s[4096], *zbuf;
size_t zsize;
int ct = 0;
FILE *F;
@@ -215,7 +215,11 @@ bool IpsetsReloadCheckForProfile(const struct desync_profile *dp)
return IpsetsReloadCheck(&dp->ips_collection) && IpsetsReloadCheck(&dp->ips_collection_exclude);
}
static bool IpsetCheck_(const struct ipset_collection_head *ips, const struct ipset_collection_head *ips_exclude, const struct in_addr *ipv4, const struct in6_addr *ipv6)
static bool IpsetCheck_(
const struct ipset_collection_head *ips, const struct ipset_collection_head *ips_exclude,
const struct in_addr *ipv4, const struct in6_addr *ipv6,
const struct in_addr *ipv4r, const struct in6_addr *ipv6r
)
{
struct ipset_item *item;
@@ -227,6 +231,12 @@ static bool IpsetCheck_(const struct ipset_collection_head *ips, const struct ip
DLOG("[%s] exclude ",item->hfile->filename ? item->hfile->filename : "fixed");
if (SearchIpset(&item->hfile->ipset, ipv4, ipv6))
return false;
if (ipv4r || ipv6r)
{
DLOG("[%s] exclude ",item->hfile->filename ? item->hfile->filename : "fixed");
if (SearchIpset(&item->hfile->ipset, ipv4r, ipv6r))
return false;
}
}
// old behavior compat: all include lists are empty means check passes
if (!ipset_collection_is_empty(ips))
@@ -236,17 +246,26 @@ static bool IpsetCheck_(const struct ipset_collection_head *ips, const struct ip
DLOG("[%s] include ",item->hfile->filename ? item->hfile->filename : "fixed");
if (SearchIpset(&item->hfile->ipset, ipv4, ipv6))
return true;
if (ipv4r || ipv6r)
{
DLOG("[%s] include ",item->hfile->filename ? item->hfile->filename : "fixed");
if (SearchIpset(&item->hfile->ipset, ipv4r, ipv6r))
return true;
}
}
return false;
}
return true;
}
bool IpsetCheck(const struct desync_profile *dp, const struct in_addr *ipv4, const struct in6_addr *ipv6)
bool IpsetCheck(
const struct desync_profile *dp,
const struct in_addr *ipv4, const struct in6_addr *ipv6,
const struct in_addr *ipv4r, const struct in6_addr *ipv6r)
{
if (PROFILE_IPSETS_ABSENT(dp)) return true;
DLOG("* ipset check for profile %u (%s)\n",dp->n,PROFILE_NAME(dp));
return IpsetCheck_(&dp->ips_collection,&dp->ips_collection_exclude,ipv4,ipv6);
return IpsetCheck_(&dp->ips_collection,&dp->ips_collection_exclude,ipv4,ipv6,ipv4r,ipv6r);
}

View File

@@ -6,7 +6,10 @@
#include "pools.h"
bool LoadAllIpsets();
bool IpsetCheck(const struct desync_profile *dp, const struct in_addr *ipv4, const struct in6_addr *ipv6);
bool IpsetCheck(
const struct desync_profile *dp,
const struct in_addr *ipv4, const struct in6_addr *ipv6,
const struct in_addr *ipv4r, const struct in6_addr *ipv6r);
struct ipset_file *RegisterIpset(struct desync_profile *dp, bool bExclude, const char *filename);
void IpsetsDebug();
bool AppendIpsetItem(ipset *ips, char *ip);

File diff suppressed because it is too large Load Diff

View File

@@ -42,8 +42,8 @@
void desync_instance(const char *func, unsigned int dp_n, unsigned int func_n, char *instance, size_t inst_size);
bool lua_test_init_script_files(void);
void lua_req_quit(void);
bool lua_init(void);
void lua_shutdown(void);
void lua_dlog_error(void);
@@ -54,6 +54,9 @@ int lua_absindex(lua_State *L, int idx);
#define lua_rawlen lua_objlen
#endif
const char *lua_reqlstring(lua_State *L,int idx,size_t *len);
const char *lua_reqstring(lua_State *L,int idx);
// push - create object and push to the stack
// pushf - create object and set it as a named field of a table already present on the stack
// pushi - create object and set it as a index field of a table already present on the stack
@@ -82,10 +85,19 @@ void lua_pushi_table(lua_State *L, lua_Integer idx);
void lua_push_blob(lua_State *L, int idx_desync, const char *blob);
void lua_pushf_blob(lua_State *L, int idx_desync, const char *field, const char *blob);
void lua_push_ipaddr(lua_State *L, const struct sockaddr *sa);
void lua_pushf_ipaddr(lua_State *L, const char *field, const struct sockaddr *sa);
void lua_pushi_ipaddr(lua_State *L, lua_Integer idx, const struct sockaddr *sa);
void lua_pushi_str(lua_State *L, lua_Integer idx, const char *str);
void lua_pushf_tcphdr_options(lua_State *L, const struct tcphdr *tcp, size_t len);
void lua_push_tcphdr(lua_State *L, const struct tcphdr *tcp, size_t len);
void lua_pushf_tcphdr(lua_State *L, const struct tcphdr *tcp, size_t len);
void lua_push_udphdr(lua_State *L, const struct udphdr *udp, size_t len);
void lua_pushf_udphdr(lua_State *L, const struct udphdr *udp, size_t len);
void lua_pushf_icmphdr(lua_State *L, const struct icmp46 *icmp, size_t len);
void lua_push_iphdr(lua_State *L, const struct ip *ip, size_t len);
void lua_pushf_iphdr(lua_State *L, const struct ip *ip, size_t len);
void lua_push_ip6hdr(lua_State *L, const struct ip6_hdr *ip6, size_t len);
void lua_pushf_ip6hdr(lua_State *L, const struct ip6_hdr *ip6, size_t len);
void lua_push_dissect(lua_State *L, const struct dissect *dis);
void lua_pushf_dissect(lua_State *L, const struct dissect *dis);
@@ -99,7 +111,8 @@ bool lua_reconstruct_ip6hdr(lua_State *L, int idx, struct ip6_hdr *ip6, size_t *
bool lua_reconstruct_iphdr(lua_State *L, int idx, struct ip *ip, size_t *len);
bool lua_reconstruct_tcphdr(lua_State *L, int idx, struct tcphdr *tcp, size_t *len);
bool lua_reconstruct_udphdr(lua_State *L, int idx, struct udphdr *udp);
bool lua_reconstruct_dissect(lua_State *L, int idx, uint8_t *buf, size_t *len, bool badsum, bool ip6_preserve_next);
bool lua_reconstruct_icmphdr(lua_State *L, int idx, struct icmp46 *icmp);
bool lua_reconstruct_dissect(lua_State *L, int idx, uint8_t *buf, size_t *len, bool keepsum, bool badsum, bool ip6_preserve_next);
typedef struct {
unsigned int func_n;

View File

@@ -52,7 +52,7 @@
struct params_s params;
static volatile sig_atomic_t bReload = false;
bool bQuit = false;
volatile sig_atomic_t bQuit = false;
static void onhup(int sig)
{
@@ -109,21 +109,21 @@ static void onusr2(int sig)
static void onint(int sig)
{
if (bQuit) return;
const char *msg = "INT received !\n";
size_t wr = write(1, msg, strlen(msg));
bQuit = true;
lua_req_quit();
}
static void onterm(int sig)
{
if (bQuit) return;
const char *msg = "TERM received !\n";
size_t wr = write(1, msg, strlen(msg));
bQuit = true;
lua_req_quit();
}
static void pre_desync(void)
static void catch_signals(void)
{
struct sigaction sa;
@@ -180,6 +180,26 @@ static bool test_list_files()
}
// writes and closes pidfile
static int write_pidfile(FILE **Fpid)
{
if (*Fpid)
{
int r = fprintf(*Fpid, "%d", getpid());
if (r <= 0)
{
DLOG_PERROR("write pidfile");
fclose(*Fpid);
*Fpid = NULL;
return false;
}
fclose(*Fpid);
*Fpid = NULL;
}
return true;
}
#ifdef __linux__
static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *cookie)
{
@@ -343,9 +363,24 @@ static int nfq_main(void)
if (!rawsend_preinit(params.bind_fix4, params.bind_fix6))
goto err;
if (!params.intercept)
{
if (params.daemon) daemonize();
if (!write_pidfile(&Fpid)) goto err;
notify_ready();
}
catch_signals();
if (!lua_init())
goto err;
if (!params.intercept)
{
DLOG("no intercept quit\n");
goto exok;
}
if (!nfq_init(&h, &qh))
goto err;
@@ -362,19 +397,8 @@ static int nfq_main(void)
#endif
if (params.daemon) daemonize();
if (!write_pidfile(&Fpid)) goto err;
if (Fpid)
{
if (fprintf(Fpid, "%d", getpid()) <= 0)
{
DLOG_PERROR("write pidfile");
goto err;
}
fclose(Fpid);
Fpid = NULL;
}
pre_desync();
notify_ready();
fd = nfq_fd(h);
@@ -451,6 +475,8 @@ static int dvt_main(void)
return 1;
}
if (params.intercept)
{
bp4.sin_family = AF_INET;
bp4.sin_port = htons(params.port);
bp4.sin_addr.s_addr = INADDR_ANY;
@@ -467,7 +493,6 @@ static int dvt_main(void)
goto exiterr;
}
#ifdef __OpenBSD__
// in OpenBSD must use separate divert sockets for ipv4 and ipv6
memset(&bp6, 0, sizeof(bp6));
@@ -489,12 +514,12 @@ static int dvt_main(void)
fdct++;
#endif
fdmax = (fd[0] > fd[1] ? fd[0] : fd[1]) + 1;
}
DLOG_CONDUP("initializing raw sockets\n");
if (!rawsend_preinit(false, false))
goto exiterr;
if (params.droproot && !droproot(params.uid, params.user, params.gid, params.gid_count))
goto exiterr;
print_id();
@@ -503,23 +528,25 @@ static int dvt_main(void)
if (!lua_test_init_script_files())
goto exiterr;
catch_signals();
if (!params.intercept)
{
if (params.daemon) daemonize();
if (!write_pidfile(&Fpid)) goto exiterr;
}
if (!lua_init())
goto exiterr;
if (!params.intercept)
{
DLOG("no intercept quit\n");
goto exitok;
}
if (params.daemon) daemonize();
if (Fpid)
{
if (fprintf(Fpid, "%d", getpid()) <= 0)
{
DLOG_PERROR("write pidfile");
goto exiterr;
}
fclose(Fpid);
Fpid = NULL;
}
pre_desync();
if (!write_pidfile(&Fpid)) goto exiterr;
for (;;)
{
@@ -637,6 +664,7 @@ static int win_main()
int res=0;
uint8_t packet[RECONSTRUCT_MAX_SIZE] __attribute__((aligned(16)));
// windows emulated fork logic does not cover objects outside of cygwin world. have to daemonize before inits
if (params.daemon) daemonize();
if (*params.pidfile && !writepid(params.pidfile))
@@ -651,7 +679,7 @@ static int win_main()
res=w_win32_error; goto ex;
}
pre_desync();
catch_signals();
for (;;)
{
@@ -675,6 +703,8 @@ static int win_main()
res=w_win32_error; goto ex;
}
DLOG_CONDUP(params.intercept ? "windivert initialized. capture is started.\n" : "windivert initialized\n");
if (!win_sandbox())
{
res=w_win32_error;
@@ -688,7 +718,11 @@ static int win_main()
res=ERROR_INVALID_PARAMETER; goto ex;
}
DLOG_CONDUP("windivert initialized. capture is started.\n");
if (!params.intercept)
{
DLOG("no intercept quit\n");
goto ex;
}
for (id = 0;; id++)
{
@@ -765,8 +799,7 @@ ex:
static void exit_clean(int code)
{
cleanup_params(&params);
exit(code);
close_std_and_exit(code);
}
@@ -1042,6 +1075,52 @@ static bool parse_pf_list(char *opt, struct port_filters_head *pfl)
return true;
}
static bool parse_icf_list(char *opt, struct icmp_filters_head *icfl)
{
char *e, *p, c;
icmp_filter icf;
bool b;
for (p = opt; p; )
{
if ((e = strchr(p, ',')))
{
c = *e;
*e = 0;
}
b = icf_parse(p, &icf) && icmp_filter_add(icfl, &icf);
if (e) *e++ = c;
if (!b) return false;
p = e;
}
return true;
}
static bool parse_ipp_list(char *opt, struct ipp_filters_head *ippl)
{
char *e, *p, c;
ipp_filter ipp;
bool b;
for (p = opt; p; )
{
if ((e = strchr(p, ',')))
{
c = *e;
*e = 0;
}
b = ipp_parse(p, &ipp) && ipp_filter_add(ippl, &ipp);
if (e) *e++ = c;
if (!b) return false;
p = e;
}
return true;
}
bool lua_call_param_add(char *opt, struct str2_list_head *args)
{
char c,*p;
@@ -1260,6 +1339,82 @@ static bool wf_make_pf(char *opt, const char *l4, const char *portname, char *bu
strncat(buf, ")", len - strlen(buf) - 1);
return true;
}
static bool wf_make_icf(char *opt, char *buf, size_t len)
{
char *e, *p, c, s1[80];
icmp_filter icf;
if (len < 3) return false;
for (p = opt, *buf = '(', buf[1] = 0; p;)
{
if ((e = strchr(p, ',')))
{
c = *e;
*e = 0;
}
if (!icf_parse(p, &icf)) return false;
switch(icf.mode)
{
case FLTMODE_FILTER:
if (icf.code_valid)
snprintf(s1, sizeof(s1), "icmp.Type==%u and icmp.Code==%u or icmpv6.Type==%u and icmpv6.Code==%u", icf.type, icf.code, icf.type, icf.code);
else
snprintf(s1, sizeof(s1), "icmp.Type==%u or icmpv6.Type==%u", icf.type, icf.type);
break;
case FLTMODE_ANY:
snprintf(s1, sizeof(s1), "icmp or icmpv6");
break;
default:
goto dont_add;
}
if (buf[1]) strncat(buf, " or ", len - strlen(buf) - 1);
strncat(buf, s1, len - strlen(buf) - 1);
dont_add:
if (e) *e++ = c;
p = e;
}
if (!buf[1]) return false; // nothing added
strncat(buf, ")", len - strlen(buf) - 1);
return true;
}
static bool wf_make_ipf(char *opt, char *buf, size_t len)
{
char *e, *p, c, s1[40];
ipp_filter ipf;
if (len < 3) return false;
for (p = opt, *buf = '(', buf[1] = 0; p;)
{
if ((e = strchr(p, ',')))
{
c = *e;
*e = 0;
}
if (!ipp_parse(p, &ipf)) return false;
switch(ipf.mode)
{
case FLTMODE_FILTER:
// NOTE: windivert can't walk ipv6 extension headers. instead of real protocol first ext header type will be matched
snprintf(s1, sizeof(s1), "ip.Protocol==%u or ipv6.NextHdr==%u", ipf.proto, ipf.proto);
break;
case FLTMODE_ANY:
snprintf(s1, sizeof(s1), "ip or ipv6");
break;
default:
goto dont_add;
}
if (buf[1]) strncat(buf, " or ", len - strlen(buf) - 1);
strncat(buf, s1, len - strlen(buf) - 1);
dont_add:
if (e) *e++ = c;
p = e;
}
if (!buf[1]) return false; // nothing added
strncat(buf, ")", len - strlen(buf) - 1);
return true;
}
#define DIVERT_NO_LOCALNETSv4_DST "(" \
"(ip.DstAddr < 127.0.0.1 or ip.DstAddr > 127.255.255.255) and " \
@@ -1306,6 +1461,8 @@ static bool wf_make_filter(
const char *pf_tcp_src_out, const char *pf_tcp_dst_out,
const char *pf_tcp_src_in, const char *pf_tcp_dst_in,
const char *pf_udp_src_in, const char *pf_udp_dst_out,
const char *icf_out, const char *icf_in,
const char *ipf_out, const char *ipf_in,
const struct str_list_head *wf_raw_part,
bool bFilterOutLAN, bool bFilterOutLoopback)
{
@@ -1354,6 +1511,11 @@ static bool wf_make_filter(
if (*pf_udp_dst_out) snprintf(wf + strlen(wf), len - strlen(wf), " or\n outbound and %s", pf_udp_dst_out);
if (*pf_udp_src_in) snprintf(wf + strlen(wf), len - strlen(wf), " or\n inbound and %s", pf_udp_src_in);
if (*icf_in) snprintf(wf + strlen(wf), len - strlen(wf), " or\n inbound and %s", icf_in);
if (*icf_out) snprintf(wf + strlen(wf), len - strlen(wf), " or\n outbound and %s", icf_out);
if (*ipf_in) snprintf(wf + strlen(wf), len - strlen(wf), " or\n inbound and %s", ipf_in);
if (*ipf_out) snprintf(wf + strlen(wf), len - strlen(wf), " or\n outbound and %s", ipf_out);
snprintf(wf + strlen(wf), len - strlen(wf), "\n)");
if (bFilterOutLAN)
@@ -1403,6 +1565,7 @@ static void exithelp(void)
" --version\t\t\t\t\t\t; print version and exit\n"
" --dry-run\t\t\t\t\t\t; verify parameters and exit with code 0 if successful\n"
" --comment=any_text\n"
" --intercept=0|1\t\t\t\t\t; enable interception. if disabled - run lua-init and exit\n"
#ifdef __linux__
" --qnum=<nfqueue_number>\n"
#elif defined(BSD)
@@ -1433,10 +1596,14 @@ static void exithelp(void)
" --wf-iface=<int>[.<int>]\t\t\t\t; numeric network interface and subinterface indexes\n"
" --wf-l3=ipv4|ipv6\t\t\t\t\t; L3 protocol filter. multiple comma separated values allowed.\n"
" --wf-tcp-in=[~]port1[-port2]\t\t\t\t; TCP in port filter. ~ means negation. multiple comma separated values allowed.\n"
" --wf-udp-in=[~]port1[-port2]\t\t\t\t; UDP in port filter. ~ means negation. multiple comma separated values allowed.\n"
" --wf-tcp-out=[~]port1[-port2]\t\t\t\t; TCP out port filter. ~ means negation. multiple comma separated values allowed.\n"
" --wf-udp-in=[~]port1[-port2]\t\t\t\t; UDP in port filter. ~ means negation. multiple comma separated values allowed.\n"
" --wf-udp-out=[~]port1[-port2]\t\t\t\t; UDP out port filter. ~ means negation. multiple comma separated values allowed.\n"
" --wf-tcp-empty=[0|1]\t\t\t\t\t; enable processing of empty tcp packets without flags SYN,RST,FIN (default : 0)\n"
" --wf-icmp-in=type[:code]\t\t\t\t; ICMP out filter. multiple comma separated values allowed.\n"
" --wf-icmp-out=type[:code]\t\t\t\t; ICMP in filter. multiple comma separated values allowed.\n"
" --wf-ipp-in=proto\t\t\t\t\t; IP protocol in filter. multiple comma separated values allowed.\n"
" --wf-ipp-out=proto\t\t\t\t\t; IP protocol out filter. multiple comma separated values allowed.\n"
" --wf-raw-part=<filter>|@<filename>\t\t\t; partial raw windivert filter string or filename\n"
" --wf-filter-lan=0|1\t\t\t\t\t; add excluding filter for non-global IP (default : 1)\n"
" --wf-filter-loopback=0|1\t\t\t\t; add excluding filter for loopback (default : 1)\n"
@@ -1461,8 +1628,10 @@ static void exithelp(void)
" --cookie[=<string>]\t\t\t\t\t; pass this profile-bound string to LUA\n"
" --import=<name>\t\t\t\t\t; populate current profile with template data\n"
" --filter-l3=ipv4|ipv6\t\t\t\t\t; L3 protocol filter. multiple comma separated values allowed.\n"
" --filter-tcp=[~]port1[-port2]|*\t\t\t; TCP port filter. ~ means negation. setting tcp and not setting udp filter denies udp. comma separated list allowed.\n"
" --filter-udp=[~]port1[-port2]|*\t\t\t; UDP port filter. ~ means negation. setting udp and not setting tcp filter denies tcp. comma separated list allowed.\n"
" --filter-tcp=[~]port1[-port2]|*\t\t\t; TCP port filter. ~ means negation. setting tcp filter and not setting others denies others. comma separated list allowed.\n"
" --filter-udp=[~]port1[-port2]|*\t\t\t; UDP port filter. ~ means negation. setting udp filter and not setting others denies others. comma separated list allowed.\n"
" --filter-icmp=type[:code]|*\t\t\t\t; ICMP type+code filter. setting icmp filter and not setting others denies others. comma separated list allowed.\n"
" --filter-ipp=proto\t\t\t\t\t; IP protocol filter. setting up ipp filter and not setting others denies others. comma separated list allowed.\n"
" --filter-l7=proto[,proto]\t\t\t\t; L6-L7 protocol filter : %s\n"
#ifdef HAS_FILTER_SSID
" --filter-ssid=ssid1[,ssid2,ssid3,...]\t\t\t; per profile wifi SSID filter\n"
@@ -1504,7 +1673,7 @@ static void exithelp(void)
HOSTLIST_AUTO_UDP_OUT, HOSTLIST_AUTO_UDP_IN,
all_payloads
);
exit(1);
close_std_and_exit(1);
}
static void exithelp_clean(void)
{
@@ -1553,6 +1722,7 @@ static void ApplyDefaultBlobs(struct blob_collection_head *blobs)
enum opt_indices {
IDX_DEBUG,
IDX_DRY_RUN,
IDX_INTERCEPT,
IDX_VERSION,
IDX_COMMENT,
#ifdef __linux__
@@ -1610,6 +1780,8 @@ enum opt_indices {
IDX_FILTER_L3,
IDX_FILTER_TCP,
IDX_FILTER_UDP,
IDX_FILTER_ICMP,
IDX_FILTER_IPP,
IDX_FILTER_L7,
#ifdef HAS_FILTER_SSID
IDX_FILTER_SSID,
@@ -1632,6 +1804,10 @@ enum opt_indices {
IDX_WF_UDP_IN,
IDX_WF_UDP_OUT,
IDX_WF_TCP_EMPTY,
IDX_WF_ICMP_IN,
IDX_WF_ICMP_OUT,
IDX_WF_IPP_IN,
IDX_WF_IPP_OUT,
IDX_WF_RAW,
IDX_WF_RAW_PART,
IDX_WF_FILTER_LAN,
@@ -1648,6 +1824,7 @@ enum opt_indices {
static const struct option long_options[] = {
[IDX_DEBUG] = {"debug", optional_argument, 0, 0},
[IDX_DRY_RUN] = {"dry-run", no_argument, 0, 0},
[IDX_INTERCEPT] = {"intercept", optional_argument, 0, 0},
[IDX_VERSION] = {"version", no_argument, 0, 0},
[IDX_COMMENT] = {"comment", optional_argument, 0, 0},
#ifdef __linux__
@@ -1702,6 +1879,8 @@ static const struct option long_options[] = {
[IDX_FILTER_L3] = {"filter-l3", required_argument, 0, 0},
[IDX_FILTER_TCP] = {"filter-tcp", required_argument, 0, 0},
[IDX_FILTER_UDP] = {"filter-udp", required_argument, 0, 0},
[IDX_FILTER_ICMP] = {"filter-icmp", required_argument, 0, 0},
[IDX_FILTER_IPP] = {"filter-ipp", required_argument, 0, 0},
[IDX_FILTER_L7] = {"filter-l7", required_argument, 0, 0},
#ifdef HAS_FILTER_SSID
[IDX_FILTER_SSID] = {"filter-ssid", required_argument, 0, 0},
@@ -1724,6 +1903,10 @@ static const struct option long_options[] = {
[IDX_WF_UDP_IN] = {"wf-udp-in", required_argument, 0, 0},
[IDX_WF_UDP_OUT] = {"wf-udp-out", required_argument, 0, 0},
[IDX_WF_TCP_EMPTY] = {"wf-tcp-empty", optional_argument, 0, 0},
[IDX_WF_ICMP_IN] = {"wf-icmp-in", required_argument, 0, 0},
[IDX_WF_ICMP_OUT] = {"wf-icmp-out", required_argument, 0, 0},
[IDX_WF_IPP_IN] = {"wf-ipp-in", required_argument, 0, 0},
[IDX_WF_IPP_OUT] = {"wf-ipp-out", required_argument, 0, 0},
[IDX_WF_RAW] = {"wf-raw", required_argument, 0, 0},
[IDX_WF_RAW_PART] = {"wf-raw-part", required_argument, 0, 0},
[IDX_WF_FILTER_LAN] = {"wf-filter-lan", required_argument, 0, 0},
@@ -1738,6 +1921,29 @@ static const struct option long_options[] = {
};
#ifdef __CYGWIN__
#define TITLE_ICON MAKEINTRESOURCE(1)
static void WinSetIcon(void)
{
HWND hConsole = GetConsoleWindow();
HICON hIcon,hIconOld;
if (hConsole)
{
if ((hIcon = LoadImage(GetModuleHandle(NULL),TITLE_ICON,IMAGE_ICON,32,32,LR_DEFAULTCOLOR|LR_SHARED)))
{
hIconOld = (HICON)SendMessage(hConsole, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
if (hIconOld) DestroyIcon(hIconOld);
}
if ((hIcon = LoadImage(GetModuleHandle(NULL),TITLE_ICON,IMAGE_ICON,0,0,LR_DEFAULTCOLOR|LR_SHARED)))
{
hIconOld = (HICON)SendMessage(hConsole, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
if (hIconOld) DestroyIcon(hIconOld);
}
}
}
#endif
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#if defined(ZAPRET_GH_VER) || defined (ZAPRET_GH_HASH)
@@ -1754,6 +1960,7 @@ static const struct option long_options[] = {
#endif
#endif
enum {WF_TCP_IN, WF_UDP_IN, WF_TCP_OUT, WF_UDP_OUT, WF_ICMP_IN, WF_ICMP_OUT, WF_IPP_IN, WF_IPP_OUT, WF_RAW, WF_RAWF_PART, GLOBAL_SSID_FILTER, GLOBAL_NLM_FILTER, WF_RAWF, WF_COUNT} t_wf_index;
int main(int argc, char **argv)
{
#ifdef __CYGWIN__
@@ -1762,6 +1969,9 @@ int main(int argc, char **argv)
// we were running as service. now exit.
return 0;
}
WinSetIcon();
MAKE_VER(params.verstr, sizeof(params.verstr));
printf("%s\n\n",params.verstr);
#endif
int result, v;
int option_index = 0;
@@ -1774,24 +1984,23 @@ int main(int argc, char **argv)
char wf_save_file[256]="";
bool wf_ipv4 = true, wf_ipv6 = true, wf_filter_lan = true, wf_filter_loopback = true, wf_tcp_empty = false;
unsigned int IfIdx = 0, SubIfIdx = 0;
unsigned int hash_wf_tcp_in = 0, hash_wf_udp_in = 0, hash_wf_tcp_out = 0, hash_wf_udp_out = 0, hash_wf_raw = 0, hash_wf_raw_part = 0, hash_ssid_filter = 0, hash_nlm_filter = 0;
unsigned int hash_wf[WF_COUNT];
#endif
if (argc < 2) exithelp();
srandom(time(NULL));
aes_init_keygen_tables(); // required for aes
mask_from_bitcount6_prepare();
set_env_exedir(argv[0]);
set_console_io_buffering();
#ifdef __CYGWIN__
memset(hash_wf,0,sizeof(hash_wf));
prepare_low_appdata();
#endif
init_params(&params);
MAKE_VER(params.verstr, sizeof(params.verstr));
printf("%s\n\n",params.verstr);
ApplyDefaultBlobs(&params.blobs);
struct desync_profile_list *dpl;
@@ -1818,23 +2027,11 @@ int main(int argc, char **argv)
#ifdef __CYGWIN__
params.windivert_filter = malloc(WINDIVERT_MAX);
if (!params.windivert_filter)
if (!params.windivert_filter || !alloc_windivert_portfilters(&params))
{
DLOG_ERR("out of memory\n");
exit_clean(1);
}
char **wdbufs[] =
{&params.wf_pf_tcp_src_in, &params.wf_pf_tcp_dst_in, &params.wf_pf_udp_src_in, &params.wf_pf_udp_dst_in,
&params.wf_pf_tcp_src_out, &params.wf_pf_tcp_dst_out, &params.wf_pf_udp_src_out, &params.wf_pf_udp_dst_out};
for (v=0 ; v<(sizeof(wdbufs)/sizeof(*wdbufs)) ; v++)
{
if (!(*wdbufs[v] = malloc(WINDIVERT_PORTFILTER_MAX)))
{
DLOG_ERR("out of memory\n");
exit_clean(1);
}
**wdbufs[v] = 0;
}
#endif
while ((v = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1)
@@ -1898,6 +2095,9 @@ int main(int argc, char **argv)
case IDX_DRY_RUN:
bDry = true;
break;
case IDX_INTERCEPT:
params.intercept = !optarg || atoi(optarg);
break;
case IDX_VERSION:
exit_clean(0);
break;
@@ -2289,8 +2489,10 @@ int main(int argc, char **argv)
DLOG_ERR("Invalid port filter : %s\n", optarg);
exit_clean(1);
}
// deny udp if not set
if (!port_filters_deny_if_empty(&dp->pf_udp))
// deny others if not set
if (!port_filters_deny_if_empty(&dp->pf_udp) ||
!icmp_filters_deny_if_empty(&dp->icf) ||
!ipp_filters_deny_if_empty(&dp->ipf))
exit_clean(1);
break;
case IDX_FILTER_UDP:
@@ -2299,8 +2501,34 @@ int main(int argc, char **argv)
DLOG_ERR("Invalid port filter : %s\n", optarg);
exit_clean(1);
}
// deny tcp if not set
if (!port_filters_deny_if_empty(&dp->pf_tcp))
// deny others if not set
if (!port_filters_deny_if_empty(&dp->pf_tcp) ||
!icmp_filters_deny_if_empty(&dp->icf) ||
!ipp_filters_deny_if_empty(&dp->ipf))
exit_clean(1);
break;
case IDX_FILTER_ICMP:
if (!parse_icf_list(optarg, &dp->icf))
{
DLOG_ERR("Invalid icmp filter : %s\n", optarg);
exit_clean(1);
}
// deny others if not set
if (!port_filters_deny_if_empty(&dp->pf_tcp) ||
!port_filters_deny_if_empty(&dp->pf_udp) ||
!ipp_filters_deny_if_empty(&dp->ipf))
exit_clean(1);
break;
case IDX_FILTER_IPP:
if (!parse_ipp_list(optarg, &dp->ipf))
{
DLOG_ERR("Invalid ip protocol filter : %s\n", optarg);
exit_clean(1);
}
// deny others if not set
if (!port_filters_deny_if_empty(&dp->pf_tcp) ||
!port_filters_deny_if_empty(&dp->pf_udp) ||
!icmp_filters_deny_if_empty(&dp->icf))
exit_clean(1);
break;
case IDX_FILTER_L7:
@@ -2415,7 +2643,7 @@ int main(int argc, char **argv)
}
break;
case IDX_WF_TCP_IN:
hash_wf_tcp_in = hash_jen(optarg, strlen(optarg));
hash_wf[WF_TCP_IN] = hash_jen(optarg, strlen(optarg));
if (!wf_make_pf(optarg, "tcp", "SrcPort", params.wf_pf_tcp_src_in, WINDIVERT_PORTFILTER_MAX) ||
!wf_make_pf(optarg, "tcp", "DstPort", params.wf_pf_tcp_dst_in, WINDIVERT_PORTFILTER_MAX))
{
@@ -2424,7 +2652,7 @@ int main(int argc, char **argv)
}
break;
case IDX_WF_TCP_OUT:
hash_wf_tcp_out = hash_jen(optarg, strlen(optarg));
hash_wf[WF_TCP_OUT] = hash_jen(optarg, strlen(optarg));
if (!wf_make_pf(optarg, "tcp", "SrcPort", params.wf_pf_tcp_src_out, WINDIVERT_PORTFILTER_MAX) ||
!wf_make_pf(optarg, "tcp", "DstPort", params.wf_pf_tcp_dst_out, WINDIVERT_PORTFILTER_MAX))
{
@@ -2433,7 +2661,7 @@ int main(int argc, char **argv)
}
break;
case IDX_WF_UDP_IN:
hash_wf_udp_in = hash_jen(optarg, strlen(optarg));
hash_wf[WF_UDP_IN] = hash_jen(optarg, strlen(optarg));
if (!wf_make_pf(optarg, "udp", "SrcPort", params.wf_pf_udp_src_in, WINDIVERT_PORTFILTER_MAX) ||
!wf_make_pf(optarg, "udp", "DstPort", params.wf_pf_udp_dst_in, WINDIVERT_PORTFILTER_MAX))
{
@@ -2442,7 +2670,7 @@ int main(int argc, char **argv)
}
break;
case IDX_WF_UDP_OUT:
hash_wf_udp_out = hash_jen(optarg, strlen(optarg));
hash_wf[WF_UDP_OUT] = hash_jen(optarg, strlen(optarg));
if (!wf_make_pf(optarg, "udp", "SrcPort", params.wf_pf_udp_src_out, WINDIVERT_PORTFILTER_MAX) ||
!wf_make_pf(optarg, "udp", "DstPort", params.wf_pf_udp_dst_out, WINDIVERT_PORTFILTER_MAX))
{
@@ -2450,8 +2678,40 @@ int main(int argc, char **argv)
exit_clean(1);
}
break;
case IDX_WF_ICMP_IN:
hash_wf[WF_ICMP_IN] = hash_jen(optarg, strlen(optarg));
if (!wf_make_icf(optarg, params.wf_icf_in, WINDIVERT_PORTFILTER_MAX))
{
DLOG_ERR("bad value for --wf-icmp-in\n");
exit_clean(1);
}
break;
case IDX_WF_ICMP_OUT:
hash_wf[WF_ICMP_OUT] = hash_jen(optarg, strlen(optarg));
if (!wf_make_icf(optarg, params.wf_icf_out, WINDIVERT_PORTFILTER_MAX))
{
DLOG_ERR("bad value for --wf-icmp-out\n");
exit_clean(1);
}
break;
case IDX_WF_IPP_IN:
hash_wf[WF_IPP_IN] = hash_jen(optarg, strlen(optarg));
if (!wf_make_ipf(optarg, params.wf_ipf_in, WINDIVERT_PORTFILTER_MAX))
{
DLOG_ERR("bad value for --wf-ipp-in\n");
exit_clean(1);
}
break;
case IDX_WF_IPP_OUT:
hash_wf[WF_IPP_OUT] = hash_jen(optarg, strlen(optarg));
if (!wf_make_ipf(optarg, params.wf_ipf_out, WINDIVERT_PORTFILTER_MAX))
{
DLOG_ERR("bad value for --wf-ipp-out\n");
exit_clean(1);
}
break;
case IDX_WF_RAW:
hash_wf_raw = hash_jen(optarg, strlen(optarg));
hash_wf[WF_RAWF] = hash_jen(optarg, strlen(optarg));
if (optarg[0] == '@')
{
size_t sz = WINDIVERT_MAX-1;
@@ -2460,7 +2720,7 @@ int main(int argc, char **argv)
}
else
{
strncpy(params.windivert_filter, optarg, WINDIVERT_MAX);
snprintf(params.windivert_filter, WINDIVERT_MAX, "%s", optarg);
params.windivert_filter[WINDIVERT_MAX - 1] = '\0';
}
break;
@@ -2468,7 +2728,7 @@ int main(int argc, char **argv)
wf_tcp_empty = !optarg || atoi(optarg);
break;
case IDX_WF_RAW_PART:
hash_wf_raw_part ^= hash_jen(optarg, strlen(optarg));
hash_wf[WF_RAWF_PART] ^= hash_jen(optarg, strlen(optarg));
{
char *wfpart = malloc(WINDIVERT_MAX);
if (!wfpart)
@@ -2484,7 +2744,7 @@ int main(int argc, char **argv)
}
else
{
strncpy(wfpart, optarg, WINDIVERT_MAX);
snprintf(wfpart, WINDIVERT_MAX, "%s", optarg);
wfpart[WINDIVERT_MAX - 1] = '\0';
}
if (!strlist_add(&params.wf_raw_part, wfpart))
@@ -2510,7 +2770,7 @@ int main(int argc, char **argv)
bDupCheck = !optarg || !!atoi(optarg);
break;
case IDX_SSID_FILTER:
hash_ssid_filter = hash_jen(optarg, strlen(optarg));
hash_wf[GLOBAL_SSID_FILTER] = hash_jen(optarg, strlen(optarg));
if (!parse_strlist(optarg, &params.ssid_filter))
{
DLOG_ERR("strlist_add failed\n");
@@ -2518,7 +2778,7 @@ int main(int argc, char **argv)
}
break;
case IDX_NLM_FILTER:
hash_nlm_filter = hash_jen(optarg, strlen(optarg));
hash_wf[GLOBAL_NLM_FILTER] = hash_jen(optarg, strlen(optarg));
if (!parse_strlist(optarg, &params.nlm_filter))
{
DLOG_ERR("strlist_add failed\n");
@@ -2563,6 +2823,8 @@ int main(int argc, char **argv)
#endif
argv = NULL; argc = 0;
if (params.intercept)
{
#ifdef __linux__
if (params.qnum < 0)
{
@@ -2576,6 +2838,7 @@ int main(int argc, char **argv)
exit_clean(1);
}
#endif
}
DLOG("adding low-priority default empty desync profile\n");
// add default empty profile
@@ -2659,9 +2922,11 @@ int main(int argc, char **argv)
dp_list_destroy(&params.desync_templates);
#ifdef __CYGWIN__
if (params.intercept)
{
if (!*params.windivert_filter)
{
if (!*params.wf_pf_tcp_src_in && !*params.wf_pf_udp_src_in && !*params.wf_pf_tcp_src_out && !*params.wf_pf_udp_src_out && LIST_EMPTY(&params.wf_raw_part))
if (!*params.wf_pf_tcp_src_in && !*params.wf_pf_udp_src_in && !*params.wf_pf_tcp_src_out && !*params.wf_pf_udp_src_out && !*params.wf_icf_in && !*params.wf_icf_out && !*params.wf_ipf_in && !*params.wf_ipf_out && LIST_EMPTY(&params.wf_raw_part))
{
DLOG_ERR("windivert filter : must specify port or/and partial raw filter\n");
exit_clean(1);
@@ -2673,12 +2938,16 @@ int main(int argc, char **argv)
params.wf_pf_tcp_dst_out, params.wf_pf_tcp_src_out,
params.wf_pf_tcp_dst_in, params.wf_pf_tcp_src_in,
params.wf_pf_udp_dst_in, params.wf_pf_udp_src_out,
params.wf_icf_out, params.wf_icf_in,
params.wf_ipf_out, params.wf_ipf_in,
&params.wf_raw_part, wf_filter_lan, wf_filter_loopback) :
wf_make_filter(params.windivert_filter, WINDIVERT_MAX, IfIdx, SubIfIdx, wf_ipv4, wf_ipv6,
wf_tcp_empty,
params.wf_pf_tcp_src_out, params.wf_pf_tcp_dst_out,
params.wf_pf_tcp_src_in, params.wf_pf_tcp_dst_in,
params.wf_pf_udp_src_in, params.wf_pf_udp_dst_out,
params.wf_icf_out, params.wf_icf_in,
params.wf_ipf_out, params.wf_ipf_in,
&params.wf_raw_part, wf_filter_lan, wf_filter_loopback);
cleanup_windivert_portfilters(&params);
if (!b)
@@ -2690,6 +2959,13 @@ int main(int argc, char **argv)
char *p = realloc(params.windivert_filter, strlen(params.windivert_filter)+1);
if (p) params.windivert_filter=p;
}
}
else
{
// do not intercept anything. only required for rawsend
snprintf(params.windivert_filter,WINDIVERT_MAX,"false");
}
DLOG("windivert filter size: %zu\nwindivert filter:\n%s\n", strlen(params.windivert_filter), params.windivert_filter);
if (*wf_save_file)
{
@@ -2705,11 +2981,10 @@ int main(int argc, char **argv)
}
}
HANDLE hMutexArg = NULL;
if (bDupCheck)
if (bDupCheck && params.intercept)
{
char mutex_name[128];
snprintf(mutex_name, sizeof(mutex_name), "Global\\winws2_arg_%u_%u_%u_%u_%u_%u_%u_%u_%u_%u_%u_%u",
hash_wf_tcp_in, hash_wf_udp_in, hash_wf_tcp_out, hash_wf_udp_out, hash_wf_raw, hash_wf_raw_part, hash_ssid_filter, hash_nlm_filter, IfIdx, SubIfIdx, wf_ipv4, wf_ipv6);
char mutex_name[32];
snprintf(mutex_name, sizeof(mutex_name), "Global\\winws2_arg_%u", hash_jen(hash_wf, sizeof(hash_wf)));
hMutexArg = CreateMutexA(NULL, TRUE, mutex_name);
if (hMutexArg && GetLastError() == ERROR_ALREADY_EXISTS)
@@ -2768,6 +3043,7 @@ ex:
CloseHandle(hMutexArg);
}
#endif
close_std();
return result;
exiterr:
result = 1;

View File

@@ -1,15 +1,15 @@
#pragma once
#include <stdbool.h>
#include <signal.h>
#ifdef __linux__
#define HAS_FILTER_SSID 1
#endif
#ifdef __CYGWIN__
extern bool bQuit;
extern volatile sig_atomic_t bQuit;
#endif
int main(int argc, char *argv[]);
// when something changes that can break LUA compatibility this version should be increased
#define LUA_COMPAT_VER 4
#define LUA_COMPAT_VER 5

View File

@@ -337,6 +337,8 @@ void dp_init_dynamic(struct desync_profile *dp)
LIST_INIT(&dp->ips_collection_exclude);
LIST_INIT(&dp->pf_tcp);
LIST_INIT(&dp->pf_udp);
LIST_INIT(&dp->icf);
LIST_INIT(&dp->ipf);
LIST_INIT(&dp->lua_desync);
#ifdef HAS_FILTER_SSID
LIST_INIT(&dp->filter_ssid);
@@ -368,6 +370,8 @@ static void dp_clear_dynamic(struct desync_profile *dp)
ipset_collection_destroy(&dp->ips_collection_exclude);
port_filters_destroy(&dp->pf_tcp);
port_filters_destroy(&dp->pf_udp);
icmp_filters_destroy(&dp->icf);
ipp_filters_destroy(&dp->ipf);
funclist_destroy(&dp->lua_desync);
#ifdef HAS_FILTER_SSID
strlist_destroy(&dp->filter_ssid);
@@ -475,11 +479,30 @@ void cleanup_windivert_portfilters(struct params_s *params)
{
char **wdbufs[] =
{&params->wf_pf_tcp_src_in, &params->wf_pf_tcp_dst_in, &params->wf_pf_udp_src_in, &params->wf_pf_udp_dst_in,
&params->wf_pf_tcp_src_out, &params->wf_pf_tcp_dst_out, &params->wf_pf_udp_src_out, &params->wf_pf_udp_dst_out};
&params->wf_pf_tcp_src_out, &params->wf_pf_tcp_dst_out, &params->wf_pf_udp_src_out, &params->wf_pf_udp_dst_out,
&params->wf_icf_in, &params->wf_icf_out,
&params->wf_ipf_in, &params->wf_ipf_out};
for (int i=0 ; i<(sizeof(wdbufs)/sizeof(*wdbufs)) ; i++)
{
free(*wdbufs[i]); *wdbufs[i] = NULL;
free(*wdbufs[i]);
*wdbufs[i] = NULL;
}
strlist_destroy(&params->wf_raw_part);
}
bool alloc_windivert_portfilters(struct params_s *params)
{
char **wdbufs[] =
{&params->wf_pf_tcp_src_in, &params->wf_pf_tcp_dst_in, &params->wf_pf_udp_src_in, &params->wf_pf_udp_dst_in,
&params->wf_pf_tcp_src_out, &params->wf_pf_tcp_dst_out, &params->wf_pf_udp_src_out, &params->wf_pf_udp_dst_out,
&params->wf_icf_in, &params->wf_icf_out,
&params->wf_ipf_in, &params->wf_ipf_out};
for (int i=0 ; i<(sizeof(wdbufs)/sizeof(*wdbufs)) ; i++)
{
if (!(*wdbufs[i] = malloc(WINDIVERT_PORTFILTER_MAX)))
return false;
**wdbufs[i] = 0;
}
return true;
}
#endif
void cleanup_params(struct params_s *params)
@@ -514,6 +537,7 @@ void init_params(struct params_s *params)
{
memset(params, 0, sizeof(*params));
params->intercept = true;
#ifdef __linux__
params->qnum = -1;
#elif defined(BSD)

View File

@@ -63,6 +63,8 @@ struct desync_profile
bool filter_ipv4,filter_ipv6;
struct port_filters_head pf_tcp,pf_udp;
struct icmp_filters_head icf;
struct ipp_filters_head ipf;
uint64_t filter_l7; // L7_PROTO_* bits
#ifdef HAS_FILTER_SSID
@@ -125,7 +127,7 @@ struct params_s
char debug_logfile[PATH_MAX];
bool debug;
bool daemon;
bool daemon, intercept;
#ifdef __linux__
int qnum;
@@ -144,6 +146,7 @@ struct params_s
char *windivert_filter;
char *wf_pf_tcp_src_in, *wf_pf_tcp_dst_in, *wf_pf_udp_src_in, *wf_pf_udp_dst_in;
char *wf_pf_tcp_src_out, *wf_pf_tcp_dst_out, *wf_pf_udp_src_out, *wf_pf_udp_dst_out;
char *wf_icf_in, *wf_icf_out, *wf_ipf_in, *wf_ipf_out;
#else
bool droproot;
char *user;
@@ -194,6 +197,7 @@ void init_params(struct params_s *params);
void cleanup_args(struct params_s *params);
#endif
#ifdef __CYGWIN__
bool alloc_windivert_portfilters(struct params_s *params);
void cleanup_windivert_portfilters(struct params_s *params);
#endif
void cleanup_params(struct params_s *params);

View File

@@ -742,14 +742,14 @@ void port_filters_destroy(struct port_filters_head *head)
free(entry);
}
}
bool port_filters_in_range(const struct port_filters_head *head, uint16_t port)
bool port_filters_match(const struct port_filters_head *head, uint16_t port)
{
const struct port_filter_item *item;
if (LIST_EMPTY(head)) return true;
LIST_FOREACH(item, head, next)
{
if (pf_in_range(port, &item->pf))
if (pf_match(port, &item->pf))
return true;
}
return false;
@@ -762,6 +762,83 @@ bool port_filters_deny_if_empty(struct port_filters_head *head)
}
bool icmp_filter_add(struct icmp_filters_head *head, const icmp_filter *icf)
{
struct icmp_filter_item *entry = malloc(sizeof(struct icmp_filter_item));
if (entry)
{
entry->icf = *icf;
LIST_INSERT_HEAD(head, entry, next);
}
return entry;
}
void icmp_filters_destroy(struct icmp_filters_head *head)
{
struct icmp_filter_item *entry;
while ((entry = LIST_FIRST(head)))
{
LIST_REMOVE(entry, next);
free(entry);
}
}
bool icmp_filters_match(const struct icmp_filters_head *head, uint8_t type, uint8_t code)
{
const struct icmp_filter_item *item;
if (LIST_EMPTY(head)) return true;
LIST_FOREACH(item, head, next)
{
if (icf_match(type, code, &item->icf))
return true;
}
return false;
}
bool icmp_filters_deny_if_empty(struct icmp_filters_head *head)
{
icmp_filter icf;
if (!LIST_EMPTY(head)) return true;
return icf_parse("-",&icf) && icmp_filter_add(head,&icf);
}
bool ipp_filter_add(struct ipp_filters_head *head, const ipp_filter *ipp)
{
struct ipp_filter_item *entry = malloc(sizeof(struct ipp_filter_item));
if (entry)
{
entry->ipp = *ipp;
LIST_INSERT_HEAD(head, entry, next);
}
return entry;
}
void ipp_filters_destroy(struct ipp_filters_head *head)
{
struct ipp_filter_item *entry;
while ((entry = LIST_FIRST(head)))
{
LIST_REMOVE(entry, next);
free(entry);
}
}
bool ipp_filters_match(const struct ipp_filters_head *head, uint8_t proto)
{
const struct ipp_filter_item *item;
if (LIST_EMPTY(head)) return true;
LIST_FOREACH(item, head, next)
{
if (ipp_match(proto, &item->ipp))
return true;
}
return false;
}
bool ipp_filters_deny_if_empty(struct ipp_filters_head *head)
{
ipp_filter ipp;
if (!LIST_EMPTY(head)) return true;
return ipp_parse("-",&ipp) && ipp_filter_add(head,&ipp);
}
struct blob_item *blob_collection_add(struct blob_collection_head *head)
{

View File

@@ -7,6 +7,7 @@
#include <time.h>
#include "helpers.h"
#include "filter.h"
//#define HASH_BLOOM 20
#define HASH_NONFATAL_OOM 1
@@ -186,9 +187,28 @@ struct port_filter_item {
LIST_HEAD(port_filters_head, port_filter_item);
bool port_filter_add(struct port_filters_head *head, const port_filter *pf);
void port_filters_destroy(struct port_filters_head *head);
bool port_filters_in_range(const struct port_filters_head *head, uint16_t port);
bool port_filters_match(const struct port_filters_head *head, uint16_t port);
bool port_filters_deny_if_empty(struct port_filters_head *head);
struct icmp_filter_item {
icmp_filter icf;
LIST_ENTRY(icmp_filter_item) next;
};
LIST_HEAD(icmp_filters_head, icmp_filter_item);
bool icmp_filter_add(struct icmp_filters_head *head, const icmp_filter *icf);
void icmp_filters_destroy(struct icmp_filters_head *head);
bool icmp_filters_match(const struct icmp_filters_head *head, uint8_t type, uint8_t code);
bool icmp_filters_deny_if_empty(struct icmp_filters_head *head);
struct ipp_filter_item {
ipp_filter ipp;
LIST_ENTRY(ipp_filter_item) next;
};
LIST_HEAD(ipp_filters_head, ipp_filter_item);
bool ipp_filter_add(struct ipp_filters_head *head, const ipp_filter *ipp);
void ipp_filters_destroy(struct ipp_filters_head *head);
bool ipp_filters_match(const struct ipp_filters_head *head, uint8_t proto);
bool ipp_filters_deny_if_empty(struct ipp_filters_head *head);
struct blob_item {
uint8_t *data; // main data blob

View File

@@ -49,6 +49,7 @@ bool l7_proto_match(t_l7proto l7proto, uint64_t filter_l7)
static const char *l7payload_name[] = {
"all","unknown","empty","known",
"ipv4","ipv6",
"http_req","http_reply",
"tls_client_hello","tls_server_hello",
"dtls_client_hello","dtls_server_hello",

View File

@@ -31,6 +31,8 @@ typedef enum {
L7P_UNKNOWN,
L7P_EMPTY,
L7P_KNOWN,
L7P_IPV4,
L7P_IPV6,
L7P_HTTP_REQ,
L7P_HTTP_REPLY,
L7P_TLS_CLIENT_HELLO,

View File

@@ -0,0 +1,347 @@
/* Copyright (C) 1991-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifndef _NETINET_ICMP6_H
#define _NETINET_ICMP6_H 1
#include <inttypes.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#define ICMP6_FILTER 1
#define ICMP6_FILTER_BLOCK 1
#define ICMP6_FILTER_PASS 2
#define ICMP6_FILTER_BLOCKOTHERS 3
#define ICMP6_FILTER_PASSONLY 4
struct icmp6_filter
{
uint32_t icmp6_filt[8];
};
struct icmp6_hdr
{
uint8_t icmp6_type; /* type field */
uint8_t icmp6_code; /* code field */
uint16_t icmp6_cksum; /* checksum field */
union
{
uint32_t icmp6_un_data32[1]; /* type-specific field */
uint16_t icmp6_un_data16[2]; /* type-specific field */
uint8_t icmp6_un_data8[4]; /* type-specific field */
} icmp6_dataun;
};
#define icmp6_data32 icmp6_dataun.icmp6_un_data32
#define icmp6_data16 icmp6_dataun.icmp6_un_data16
#define icmp6_data8 icmp6_dataun.icmp6_un_data8
#define icmp6_pptr icmp6_data32[0] /* parameter prob */
#define icmp6_mtu icmp6_data32[0] /* packet too big */
#define icmp6_id icmp6_data16[0] /* echo request/reply */
#define icmp6_seq icmp6_data16[1] /* echo request/reply */
#define icmp6_maxdelay icmp6_data16[0] /* mcast group membership */
#define ICMP6_DST_UNREACH 1
#define ICMP6_PACKET_TOO_BIG 2
#define ICMP6_TIME_EXCEEDED 3
#define ICMP6_PARAM_PROB 4
#define ICMP6_INFOMSG_MASK 0x80 /* all informational messages */
#define ICMP6_ECHO_REQUEST 128
#define ICMP6_ECHO_REPLY 129
#define MLD_LISTENER_QUERY 130
#define MLD_LISTENER_REPORT 131
#define MLD_LISTENER_REDUCTION 132
#define ICMPV6_EXT_ECHO_REQUEST 160
#define ICMPV6_EXT_ECHO_REPLY 161
#define ICMP6_DST_UNREACH_NOROUTE 0 /* no route to destination */
#define ICMP6_DST_UNREACH_ADMIN 1 /* communication with destination */
/* administratively prohibited */
#define ICMP6_DST_UNREACH_BEYONDSCOPE 2 /* beyond scope of source address */
#define ICMP6_DST_UNREACH_ADDR 3 /* address unreachable */
#define ICMP6_DST_UNREACH_NOPORT 4 /* bad port */
#define ICMP6_TIME_EXCEED_TRANSIT 0 /* Hop Limit == 0 in transit */
#define ICMP6_TIME_EXCEED_REASSEMBLY 1 /* Reassembly time out */
#define ICMP6_PARAMPROB_HEADER 0 /* erroneous header field */
#define ICMP6_PARAMPROB_NEXTHEADER 1 /* unrecognized Next Header */
#define ICMP6_PARAMPROB_OPTION 2 /* unrecognized IPv6 option */
#define ICMP6_FILTER_WILLPASS(type, filterp) \
((((filterp)->icmp6_filt[(type) >> 5]) & (1U << ((type) & 31))) == 0)
#define ICMP6_FILTER_WILLBLOCK(type, filterp) \
((((filterp)->icmp6_filt[(type) >> 5]) & (1U << ((type) & 31))) != 0)
#define ICMP6_FILTER_SETPASS(type, filterp) \
((((filterp)->icmp6_filt[(type) >> 5]) &= ~(1U << ((type) & 31))))
#define ICMP6_FILTER_SETBLOCK(type, filterp) \
((((filterp)->icmp6_filt[(type) >> 5]) |= (1U << ((type) & 31))))
#define ICMP6_FILTER_SETPASSALL(filterp) \
memset (filterp, 0, sizeof (struct icmp6_filter));
#define ICMP6_FILTER_SETBLOCKALL(filterp) \
memset (filterp, 0xFF, sizeof (struct icmp6_filter));
#define ND_ROUTER_SOLICIT 133
#define ND_ROUTER_ADVERT 134
#define ND_NEIGHBOR_SOLICIT 135
#define ND_NEIGHBOR_ADVERT 136
#define ND_REDIRECT 137
struct nd_router_solicit /* router solicitation */
{
struct icmp6_hdr nd_rs_hdr;
/* could be followed by options */
};
#define nd_rs_type nd_rs_hdr.icmp6_type
#define nd_rs_code nd_rs_hdr.icmp6_code
#define nd_rs_cksum nd_rs_hdr.icmp6_cksum
#define nd_rs_reserved nd_rs_hdr.icmp6_data32[0]
struct nd_router_advert /* router advertisement */
{
struct icmp6_hdr nd_ra_hdr;
uint32_t nd_ra_reachable; /* reachable time */
uint32_t nd_ra_retransmit; /* retransmit timer */
/* could be followed by options */
};
#define nd_ra_type nd_ra_hdr.icmp6_type
#define nd_ra_code nd_ra_hdr.icmp6_code
#define nd_ra_cksum nd_ra_hdr.icmp6_cksum
#define nd_ra_curhoplimit nd_ra_hdr.icmp6_data8[0]
#define nd_ra_flags_reserved nd_ra_hdr.icmp6_data8[1]
#define ND_RA_FLAG_MANAGED 0x80
#define ND_RA_FLAG_OTHER 0x40
#define ND_RA_FLAG_HOME_AGENT 0x20
#define nd_ra_router_lifetime nd_ra_hdr.icmp6_data16[1]
struct nd_neighbor_solicit /* neighbor solicitation */
{
struct icmp6_hdr nd_ns_hdr;
struct in6_addr nd_ns_target; /* target address */
/* could be followed by options */
};
#define nd_ns_type nd_ns_hdr.icmp6_type
#define nd_ns_code nd_ns_hdr.icmp6_code
#define nd_ns_cksum nd_ns_hdr.icmp6_cksum
#define nd_ns_reserved nd_ns_hdr.icmp6_data32[0]
struct nd_neighbor_advert /* neighbor advertisement */
{
struct icmp6_hdr nd_na_hdr;
struct in6_addr nd_na_target; /* target address */
/* could be followed by options */
};
#define nd_na_type nd_na_hdr.icmp6_type
#define nd_na_code nd_na_hdr.icmp6_code
#define nd_na_cksum nd_na_hdr.icmp6_cksum
#define nd_na_flags_reserved nd_na_hdr.icmp6_data32[0]
#if __BYTE_ORDER == __BIG_ENDIAN
#define ND_NA_FLAG_ROUTER 0x80000000
#define ND_NA_FLAG_SOLICITED 0x40000000
#define ND_NA_FLAG_OVERRIDE 0x20000000
#else /* __BYTE_ORDER == __LITTLE_ENDIAN */
#define ND_NA_FLAG_ROUTER 0x00000080
#define ND_NA_FLAG_SOLICITED 0x00000040
#define ND_NA_FLAG_OVERRIDE 0x00000020
#endif
struct nd_redirect /* redirect */
{
struct icmp6_hdr nd_rd_hdr;
struct in6_addr nd_rd_target; /* target address */
struct in6_addr nd_rd_dst; /* destination address */
/* could be followed by options */
};
#define nd_rd_type nd_rd_hdr.icmp6_type
#define nd_rd_code nd_rd_hdr.icmp6_code
#define nd_rd_cksum nd_rd_hdr.icmp6_cksum
#define nd_rd_reserved nd_rd_hdr.icmp6_data32[0]
struct nd_opt_hdr /* Neighbor discovery option header */
{
uint8_t nd_opt_type;
uint8_t nd_opt_len; /* in units of 8 octets */
/* followed by option specific data */
};
#define ND_OPT_SOURCE_LINKADDR 1
#define ND_OPT_TARGET_LINKADDR 2
#define ND_OPT_PREFIX_INFORMATION 3
#define ND_OPT_REDIRECTED_HEADER 4
#define ND_OPT_MTU 5
#define ND_OPT_RTR_ADV_INTERVAL 7
#define ND_OPT_HOME_AGENT_INFO 8
struct nd_opt_prefix_info /* prefix information */
{
uint8_t nd_opt_pi_type;
uint8_t nd_opt_pi_len;
uint8_t nd_opt_pi_prefix_len;
uint8_t nd_opt_pi_flags_reserved;
uint32_t nd_opt_pi_valid_time;
uint32_t nd_opt_pi_preferred_time;
uint32_t nd_opt_pi_reserved2;
struct in6_addr nd_opt_pi_prefix;
};
#define ND_OPT_PI_FLAG_ONLINK 0x80
#define ND_OPT_PI_FLAG_AUTO 0x40
#define ND_OPT_PI_FLAG_RADDR 0x20
struct nd_opt_rd_hdr /* redirected header */
{
uint8_t nd_opt_rh_type;
uint8_t nd_opt_rh_len;
uint16_t nd_opt_rh_reserved1;
uint32_t nd_opt_rh_reserved2;
/* followed by IP header and data */
};
struct nd_opt_mtu /* MTU option */
{
uint8_t nd_opt_mtu_type;
uint8_t nd_opt_mtu_len;
uint16_t nd_opt_mtu_reserved;
uint32_t nd_opt_mtu_mtu;
};
struct mld_hdr
{
struct icmp6_hdr mld_icmp6_hdr;
struct in6_addr mld_addr; /* multicast address */
};
#define mld_type mld_icmp6_hdr.icmp6_type
#define mld_code mld_icmp6_hdr.icmp6_code
#define mld_cksum mld_icmp6_hdr.icmp6_cksum
#define mld_maxdelay mld_icmp6_hdr.icmp6_data16[0]
#define mld_reserved mld_icmp6_hdr.icmp6_data16[1]
#define ICMP6_ROUTER_RENUMBERING 138
struct icmp6_router_renum /* router renumbering header */
{
struct icmp6_hdr rr_hdr;
uint8_t rr_segnum;
uint8_t rr_flags;
uint16_t rr_maxdelay;
uint32_t rr_reserved;
};
#define rr_type rr_hdr.icmp6_type
#define rr_code rr_hdr.icmp6_code
#define rr_cksum rr_hdr.icmp6_cksum
#define rr_seqnum rr_hdr.icmp6_data32[0]
/* Router renumbering flags */
#define ICMP6_RR_FLAGS_TEST 0x80
#define ICMP6_RR_FLAGS_REQRESULT 0x40
#define ICMP6_RR_FLAGS_FORCEAPPLY 0x20
#define ICMP6_RR_FLAGS_SPECSITE 0x10
#define ICMP6_RR_FLAGS_PREVDONE 0x08
struct rr_pco_match /* match prefix part */
{
uint8_t rpm_code;
uint8_t rpm_len;
uint8_t rpm_ordinal;
uint8_t rpm_matchlen;
uint8_t rpm_minlen;
uint8_t rpm_maxlen;
uint16_t rpm_reserved;
struct in6_addr rpm_prefix;
};
/* PCO code values */
#define RPM_PCO_ADD 1
#define RPM_PCO_CHANGE 2
#define RPM_PCO_SETGLOBAL 3
struct rr_pco_use /* use prefix part */
{
uint8_t rpu_uselen;
uint8_t rpu_keeplen;
uint8_t rpu_ramask;
uint8_t rpu_raflags;
uint32_t rpu_vltime;
uint32_t rpu_pltime;
uint32_t rpu_flags;
struct in6_addr rpu_prefix;
};
#define ICMP6_RR_PCOUSE_RAFLAGS_ONLINK 0x20
#define ICMP6_RR_PCOUSE_RAFLAGS_AUTO 0x10
#if __BYTE_ORDER == __BIG_ENDIAN
# define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME 0x80000000
# define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME 0x40000000
#elif __BYTE_ORDER == __LITTLE_ENDIAN
# define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME 0x80
# define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME 0x40
#endif
struct rr_result /* router renumbering result message */
{
uint16_t rrr_flags;
uint8_t rrr_ordinal;
uint8_t rrr_matchedlen;
uint32_t rrr_ifid;
struct in6_addr rrr_prefix;
};
#if __BYTE_ORDER == __BIG_ENDIAN
# define ICMP6_RR_RESULT_FLAGS_OOB 0x0002
# define ICMP6_RR_RESULT_FLAGS_FORBIDDEN 0x0001
#elif __BYTE_ORDER == __LITTLE_ENDIAN
# define ICMP6_RR_RESULT_FLAGS_OOB 0x0200
# define ICMP6_RR_RESULT_FLAGS_FORBIDDEN 0x0100
#endif
/* Mobile IPv6 extension: Advertisement Interval. */
struct nd_opt_adv_interval
{
uint8_t nd_opt_adv_interval_type;
uint8_t nd_opt_adv_interval_len;
uint16_t nd_opt_adv_interval_reserved;
uint32_t nd_opt_adv_interval_ival;
};
/* Mobile IPv6 extension: Home Agent Info. */
struct nd_opt_home_agent_info
{
uint8_t nd_opt_home_agent_info_type;
uint8_t nd_opt_home_agent_info_len;
uint16_t nd_opt_home_agent_info_reserved;
uint16_t nd_opt_home_agent_info_preference;
uint16_t nd_opt_home_agent_info_lifetime;
};
#endif /* netinet/icmpv6.h */

View File

@@ -0,0 +1,298 @@
/* Copyright (C) 1991-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifndef __NETINET_IP_ICMP_H
#define __NETINET_IP_ICMP_H 1
#include <sys/types.h>
#include <stdint.h>
__BEGIN_DECLS
struct icmphdr
{
uint8_t type; /* message type */
uint8_t code; /* type sub-code */
uint16_t checksum;
union
{
struct
{
uint16_t id;
uint16_t sequence;
} echo; /* echo datagram */
uint32_t gateway; /* gateway address */
struct
{
uint16_t __glibc_reserved;
uint16_t mtu;
} frag; /* path mtu discovery */
} un;
};
#define ICMP_ECHOREPLY 0 /* Echo Reply */
#define ICMP_DEST_UNREACH 3 /* Destination Unreachable */
#define ICMP_SOURCE_QUENCH 4 /* Source Quench */
#define ICMP_REDIRECT 5 /* Redirect (change route) */
#define ICMP_ECHO 8 /* Echo Request */
#define ICMP_TIME_EXCEEDED 11 /* Time Exceeded */
#define ICMP_PARAMETERPROB 12 /* Parameter Problem */
#define ICMP_TIMESTAMP 13 /* Timestamp Request */
#define ICMP_TIMESTAMPREPLY 14 /* Timestamp Reply */
#define ICMP_INFO_REQUEST 15 /* Information Request */
#define ICMP_INFO_REPLY 16 /* Information Reply */
#define ICMP_ADDRESS 17 /* Address Mask Request */
#define ICMP_ADDRESSREPLY 18 /* Address Mask Reply */
#define NR_ICMP_TYPES 18
/* Codes for UNREACH. */
#define ICMP_NET_UNREACH 0 /* Network Unreachable */
#define ICMP_HOST_UNREACH 1 /* Host Unreachable */
#define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
#define ICMP_PORT_UNREACH 3 /* Port Unreachable */
#define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
#define ICMP_SR_FAILED 5 /* Source Route failed */
#define ICMP_NET_UNKNOWN 6
#define ICMP_HOST_UNKNOWN 7
#define ICMP_HOST_ISOLATED 8
#define ICMP_NET_ANO 9
#define ICMP_HOST_ANO 10
#define ICMP_NET_UNR_TOS 11
#define ICMP_HOST_UNR_TOS 12
#define ICMP_PKT_FILTERED 13 /* Packet filtered */
#define ICMP_PREC_VIOLATION 14 /* Precedence violation */
#define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
#define NR_ICMP_UNREACH 15 /* instead of hardcoding immediate value */
/* Codes for REDIRECT. */
#define ICMP_REDIR_NET 0 /* Redirect Net */
#define ICMP_REDIR_HOST 1 /* Redirect Host */
#define ICMP_REDIR_NETTOS 2 /* Redirect Net for TOS */
#define ICMP_REDIR_HOSTTOS 3 /* Redirect Host for TOS */
/* Codes for TIME_EXCEEDED. */
#define ICMP_EXC_TTL 0 /* TTL count exceeded */
#define ICMP_EXC_FRAGTIME 1 /* Fragment Reass time exceeded */
/* Codes for ICMP_EXT_ECHO (PROBE) */
#define ICMP_EXT_ECHO 42
#define ICMP_EXT_ECHOREPLY 43
#define ICMP_EXT_CODE_MAL_QUERY 1 /* Malformed Query */
#define ICMP_EXT_CODE_NO_IF 2 /* No such Interface */
#define ICMP_EXT_CODE_NO_TABLE_ENT 3 /* No table entry */
#define ICMP_EXT_CODE_MULT_IFS 4 /* Multiple Interfaces Satisfy Query */
/* Constants for EXT_ECHO (PROBE) */
#define ICMP_EXT_ECHOREPLY_ACTIVE (1 << 2)/* active bit in reply */
#define ICMP_EXT_ECHOREPLY_IPV4 (1 << 1)/* ipv4 bit in reply */
#define ICMP_EXT_ECHOREPLY_IPV6 1 /* ipv6 bit in reply */
#define ICMP_EXT_ECHO_CTYPE_NAME 1
#define ICMP_EXT_ECHO_CTYPE_INDEX 2
#define ICMP_EXT_ECHO_CTYPE_ADDR 3
#define ICMP_AFI_IP 1 /* Address Family Identifier for IPV4 */
#define ICMP_AFI_IP6 2 /* Address Family Identifier for IPV6 */
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93
*/
#include <netinet/in.h>
#include <netinet/ip.h>
/*
* Internal of an ICMP Router Advertisement
*/
struct icmp_ra_addr
{
uint32_t ira_addr;
uint32_t ira_preference;
};
struct icmp
{
uint8_t icmp_type; /* type of message, see below */
uint8_t icmp_code; /* type sub code */
uint16_t icmp_cksum; /* ones complement checksum of struct */
union
{
unsigned char ih_pptr; /* ICMP_PARAMPROB */
struct in_addr ih_gwaddr; /* gateway address */
struct ih_idseq /* echo datagram */
{
uint16_t icd_id;
uint16_t icd_seq;
} ih_idseq;
uint32_t ih_void;
/* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */
struct ih_pmtu
{
uint16_t ipm_void;
uint16_t ipm_nextmtu;
} ih_pmtu;
struct ih_rtradv
{
uint8_t irt_num_addrs;
uint8_t irt_wpa;
uint16_t irt_lifetime;
} ih_rtradv;
} icmp_hun;
#define icmp_pptr icmp_hun.ih_pptr
#define icmp_gwaddr icmp_hun.ih_gwaddr
#define icmp_id icmp_hun.ih_idseq.icd_id
#define icmp_seq icmp_hun.ih_idseq.icd_seq
#define icmp_void icmp_hun.ih_void
#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void
#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu
#define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs
#define icmp_wpa icmp_hun.ih_rtradv.irt_wpa
#define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime
union
{
struct
{
uint32_t its_otime;
uint32_t its_rtime;
uint32_t its_ttime;
} id_ts;
struct
{
struct ip idi_ip;
/* options and then 64 bits of data */
} id_ip;
struct icmp_ra_addr id_radv;
uint32_t id_mask;
uint8_t id_data[1];
} icmp_dun;
#define icmp_otime icmp_dun.id_ts.its_otime
#define icmp_rtime icmp_dun.id_ts.its_rtime
#define icmp_ttime icmp_dun.id_ts.its_ttime
#define icmp_ip icmp_dun.id_ip.idi_ip
#define icmp_radv icmp_dun.id_radv
#define icmp_mask icmp_dun.id_mask
#define icmp_data icmp_dun.id_data
};
/*
* Lower bounds on packet lengths for various types.
* For the error advice packets must first insure that the
* packet is large enough to contain the returned ip header.
* Only then can we do the check to see if 64 bits of packet
* data have been returned, since we need to check the returned
* ip header length.
*/
#define ICMP_MINLEN 8 /* abs minimum */
#define ICMP_TSLEN (8 + 3 * sizeof (n_time)) /* timestamp */
#define ICMP_MASKLEN 12 /* address mask */
#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */
#ifndef _IP_VHL
#define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8)
/* N.B.: must separately check that ip_hl >= 5 */
#else
#define ICMP_ADVLEN(p) (8 + (IP_VHL_HL((p)->icmp_ip.ip_vhl) << 2) + 8)
/* N.B.: must separately check that header length >= 5 */
#endif
/* Definition of type and code fields. */
/* defined above: ICMP_ECHOREPLY, ICMP_REDIRECT, ICMP_ECHO */
#define ICMP_UNREACH 3 /* dest unreachable, codes: */
#define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */
#define ICMP_ROUTERADVERT 9 /* router advertisement */
#define ICMP_ROUTERSOLICIT 10 /* router solicitation */
#define ICMP_TIMXCEED 11 /* time exceeded, code: */
#define ICMP_PARAMPROB 12 /* ip header bad */
#define ICMP_TSTAMP 13 /* timestamp request */
#define ICMP_TSTAMPREPLY 14 /* timestamp reply */
#define ICMP_IREQ 15 /* information request */
#define ICMP_IREQREPLY 16 /* information reply */
#define ICMP_MASKREQ 17 /* address mask request */
#define ICMP_MASKREPLY 18 /* address mask reply */
#define ICMP_MAXTYPE 18
/* UNREACH codes */
#define ICMP_UNREACH_NET 0 /* bad net */
#define ICMP_UNREACH_HOST 1 /* bad host */
#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */
#define ICMP_UNREACH_PORT 3 /* bad port */
#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */
#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */
#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */
#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */
#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */
#define ICMP_UNREACH_NET_PROHIB 9 /* net denied */
#define ICMP_UNREACH_HOST_PROHIB 10 /* host denied */
#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */
#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */
#define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohib */
#define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host prec vio. */
#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* prec cutoff */
/* REDIRECT codes */
#define ICMP_REDIRECT_NET 0 /* for network */
#define ICMP_REDIRECT_HOST 1 /* for host */
#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */
#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */
/* TIMEXCEED codes */
#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */
#define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */
/* PARAMPROB code */
#define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */
#define ICMP_INFOTYPE(type) \
((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO \
|| (type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT \
|| (type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY \
|| (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY \
|| (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY)
__END_DECLS
#endif /* netinet/ip_icmp.h */

40
nfq2/windows/nthacks.h Normal file
View File

@@ -0,0 +1,40 @@
#pragma once
#include <winternl.h>
#define DIRECTORY_QUERY (0x0001)
#define DIRECTORY_TRAVERSE (0x0002)
#define DIRECTORY_CREATE_OBJECT (0x0004)
#define DIRECTORY_CREATE_SUBDIRECTORY (0x0008)
#define DIRECTORY_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0xF)
typedef struct _PROCESS_SESSION_INFORMATION {
ULONG SessionId;
} PROCESS_SESSION_INFORMATION, *PPROCESS_SESSION_INFORMATION;
typedef struct _OBJECT_DIRECTORY_INFORMATION {
UNICODE_STRING Name;
UNICODE_STRING TypeName;
} OBJECT_DIRECTORY_INFORMATION, *POBJECT_DIRECTORY_INFORMATION;
#ifdef __cplusplus
extern "C"
{
#endif
NTSTATUS NTAPI NtOpenDirectoryObject(
_Out_ PHANDLE DirectoryHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes
);
NTSTATUS NTAPI NtQueryDirectoryObject(
_In_ HANDLE DirectoryHandle,
_Out_opt_ PVOID Buffer,
_In_ ULONG Length,
_In_ BOOLEAN ReturnSingleEntry,
_In_ BOOLEAN RestartScan,
_Inout_ PULONG Context,
_Out_opt_ PULONG ReturnLength
);
#ifdef __cplusplus
};
#endif

View File

@@ -0,0 +1,4 @@
# in 64 bit cygwin
windres winws.rc -O coff -o winws_res64.o
# in 32 bit cygwin
windres winws.rc -O coff -o winws_res32.o

BIN
nfq2/windows/res/winws.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator"/>
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!--The ID below indicates application support for Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!--The ID below indicates application support for Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!--The ID below indicates application support for Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!--The ID below indicates application support for Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!--The ID below indicates application support for Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application>
</compatibility>
</assembly>

View File

@@ -0,0 +1,3 @@
LANGUAGE 0,0
1 ICON "winws.ico"
1 24 "winws.manifest"

Binary file not shown.

Binary file not shown.