From a1173fe08f4a48724e34a67647ee55e19ee4ae92 Mon Sep 17 00:00:00 2001 From: basil00 Date: Sat, 17 Aug 2019 09:31:46 +0800 Subject: [PATCH] Coalesce filter interpreter implementations. Replace the dual kernel/user-mode filter interpreters with a single shared implementation. --- README | 2 +- dll/windivert.c | 17 +- dll/windivert_hash.c | 38 +- dll/windivert_helper.c | 1711 ++++++++++------------------------------ dll/windivert_shared.c | 1001 ++++++++++++++++++++++- doc/windivert.html | 4 +- sys/windivert.c | 941 ++-------------------- 7 files changed, 1482 insertions(+), 2232 deletions(-) diff --git a/README b/README index 0fc54ca..5dcbc58 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -WinDivert 2.1: Windows Packet Divert +WinDivert 2.2: Windows Packet Divert ==================================== 1. Introduction diff --git a/dll/windivert.c b/dll/windivert.c index ae100e2..77af5d8 100644 --- a/dll/windivert.c +++ b/dll/windivert.c @@ -109,7 +109,22 @@ void *memset(void *dst, int c, size_t n) return dst; } -#endif +#define WINDIVERT_INLINE __forceinline + +#else /* _MSC_VER */ + +#define WINDIVERT_INLINE __attribute__((__always_inline__)) inline + +#endif /* _MSC_VER */ + +/* + * Filter interpreter config. + */ +static BOOL WinDivertGetData(const VOID *packet, UINT packet_len, INT min, + INT max, INT idx, PVOID data, UINT size); +#define WINDIVERT_GET_DATA(packet, packet_len, min, max, index, data, size) \ + WinDivertGetData((packet), (packet_len), (min), (max), (index), (data), \ + (size)) /* * Prototypes. diff --git a/dll/windivert_hash.c b/dll/windivert_hash.c index 3efba83..460b35f 100644 --- a/dll/windivert_hash.c +++ b/dll/windivert_hash.c @@ -104,35 +104,37 @@ static UINT64 WinDivertXXH64Avalanche(UINT64 h64) /* * WinDivert packet hash function. */ -static UINT64 WinDivertHashPacket(UINT64 seed, PWINDIVERT_IPHDR ip_header, - PWINDIVERT_IPV6HDR ipv6_header, PWINDIVERT_ICMPHDR icmp_header, - PWINDIVERT_ICMPV6HDR icmpv6_header, PWINDIVERT_TCPHDR tcp_header, - PWINDIVERT_UDPHDR udp_header) +static UINT64 WinDivertHashPacket(UINT64 seed, + const WINDIVERT_IPHDR *ip_header, const WINDIVERT_IPV6HDR *ipv6_header, + const WINDIVERT_ICMPHDR *icmp_header, + const WINDIVERT_ICMPV6HDR *icmpv6_header, + const WINDIVERT_TCPHDR *tcp_header, const WINDIVERT_UDPHDR *udp_header) { - UINT64 h64, v1, v2, v3, v4, v[4], *data64; - UINT32 *data32; + UINT64 h64, v1, v2, v3, v4, v[4]; + const UINT64 *data64; + const UINT32 *data32; UINT i; static const UINT64 padding64[] = // SHA2 IV { - 0x428A2F9871374491ull, 0xB5C0FBCFE9B5DBA5ull, 0x3956C25B59F111F1ull, - 0x923F82A4AB1C5ED5ull, 0xD807AA9812835B01ull, 0x243185BE550C7DC3ull, - 0x72BE5D7480DEB1FEull, 0x9BDC06A7C19BF174ull, 0xE49B69C1EFBE4786ull, + 0x428A2F9871374491ull, 0xB5C0FBCFE9B5DBA5ull, 0x3956C25B59F111F1ull, + 0x923F82A4AB1C5ED5ull, 0xD807AA9812835B01ull, 0x243185BE550C7DC3ull, + 0x72BE5D7480DEB1FEull, 0x9BDC06A7C19BF174ull, 0xE49B69C1EFBE4786ull, }; // Set-up seed & data v1 = seed ^ padding64[0]; if (ip_header != NULL) { - data64 = (UINT64 *)ip_header; + data64 = (const UINT64 *)ip_header; v2 = data64[0] ^ padding64[1]; v3 = data64[1] ^ padding64[2]; - data32 = (UINT32 *)ip_header; + data32 = (const UINT32 *)ip_header; v4 = (UINT64)data32[4] ^ padding64[3]; i = 0; } else if (ipv6_header != NULL) { - data64 = (UINT64 *)ipv6_header; + data64 = (const UINT64 *)ipv6_header; v2 = data64[0] ^ padding64[1]; v3 = data64[1] ^ padding64[2]; v4 = data64[2] ^ padding64[3]; @@ -145,10 +147,10 @@ static UINT64 WinDivertHashPacket(UINT64 seed, PWINDIVERT_IPHDR ip_header, if (tcp_header != NULL) { - data64 = (UINT64 *)tcp_header; + data64 = (const UINT64 *)tcp_header; v[i] = data64[0] ^ padding64[i+4]; i++; v[i] = data64[1] ^ padding64[i+4]; i++; - data32 = (UINT32 *)tcp_header; + data32 = (const UINT32 *)tcp_header; if (i <= 3) { v[i] = (UINT64)data32[4] ^ padding64[i+4]; i++; @@ -162,17 +164,17 @@ static UINT64 WinDivertHashPacket(UINT64 seed, PWINDIVERT_IPHDR ip_header, { if (udp_header != NULL) { - data64 = (UINT64 *)udp_header; + data64 = (const UINT64 *)udp_header; v[i] = data64[0] ^ padding64[i+4]; i++; } else if (icmp_header != NULL) { - data64 = (UINT64 *)icmp_header; + data64 = (const UINT64 *)icmp_header; v[i] = data64[0] ^ padding64[i+4]; i++; } else if (icmpv6_header != NULL) { - data64 = (UINT64 *)icmpv6_header; + data64 = (const UINT64 *)icmpv6_header; v[i] = data64[0] ^ padding64[i+4]; i++; } } @@ -194,7 +196,7 @@ static UINT64 WinDivertHashPacket(UINT64 seed, PWINDIVERT_IPHDR ip_header, h64 = WinDivertXXH64MergeRound(h64, v3); h64 = WinDivertXXH64MergeRound(h64, v4); h64 += 32; // "length" - h64 = WinDivertXXH64Avalanche(h64); + h64 = WinDivertXXH64Avalanche(h64); return h64; } diff --git a/dll/windivert_helper.c b/dll/windivert_helper.c index c6e0862..4ad2c23 100644 --- a/dll/windivert_helper.c +++ b/dll/windivert_helper.c @@ -32,6 +32,11 @@ * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include +#include + + + /****************************************************************************/ /* WINDIVERT HELPER IMPLEMENTATION */ /****************************************************************************/ @@ -199,45 +204,6 @@ typedef struct UINT8 flags; } TOKEN_INFO, *PTOKEN_INFO; -#define WINDIVERT_LAYER_FLAG_NETWORK (1 << WINDIVERT_LAYER_NETWORK) -#define WINDIVERT_LAYER_FLAG_NETWORK_FORWARD \ - (1 << WINDIVERT_LAYER_NETWORK_FORWARD) -#define WINDIVERT_LAYER_FLAG_FLOW (1 << WINDIVERT_LAYER_FLOW) -#define WINDIVERT_LAYER_FLAG_SOCKET (1 << WINDIVERT_LAYER_SOCKET) -#define WINDIVERT_LAYER_FLAG_REFLECT (1 << WINDIVERT_LAYER_REFLECT) - -/* - * Layer flags shorthand. - */ -#define LNMFSR (WINDIVERT_LAYER_FLAG_NETWORK | \ - WINDIVERT_LAYER_FLAG_NETWORK_FORWARD | \ - WINDIVERT_LAYER_FLAG_FLOW | \ - WINDIVERT_LAYER_FLAG_SOCKET | \ - WINDIVERT_LAYER_FLAG_REFLECT) -#define LNMFS_ (WINDIVERT_LAYER_FLAG_NETWORK | \ - WINDIVERT_LAYER_FLAG_NETWORK_FORWARD | \ - WINDIVERT_LAYER_FLAG_FLOW | \ - WINDIVERT_LAYER_FLAG_SOCKET) -#define L__F_R (WINDIVERT_LAYER_FLAG_FLOW | \ - WINDIVERT_LAYER_FLAG_REFLECT) -#define LN_FS_ (WINDIVERT_LAYER_FLAG_NETWORK | \ - WINDIVERT_LAYER_FLAG_FLOW | \ - WINDIVERT_LAYER_FLAG_SOCKET) -#define L__FS_ (WINDIVERT_LAYER_FLAG_FLOW | \ - WINDIVERT_LAYER_FLAG_SOCKET) -#define L___SR (WINDIVERT_LAYER_FLAG_SOCKET | \ - WINDIVERT_LAYER_FLAG_REFLECT) -#define L__FSR (WINDIVERT_LAYER_FLAG_FLOW | \ - WINDIVERT_LAYER_FLAG_SOCKET | \ - WINDIVERT_LAYER_FLAG_REFLECT) -#define LNM___ (WINDIVERT_LAYER_FLAG_NETWORK | \ - WINDIVERT_LAYER_FLAG_NETWORK_FORWARD) -#define L__F__ WINDIVERT_LAYER_FLAG_FLOW -#define L___S_ WINDIVERT_LAYER_FLAG_SOCKET -#define L____R WINDIVERT_LAYER_FLAG_REFLECT - - - /* * Filter expressions. */ @@ -291,6 +257,7 @@ typedef UINT64 ERROR, *PERROR; /* * Prototypes. */ +static UINT32 WinDivertKindToField(KIND kind); static PEXPR WinDivertParseFilter(HANDLE pool, TOKEN *toks, UINT *i, INT depth, BOOL and, PERROR error); static BOOL WinDivertCondExecFilter(PWINDIVERT_FILTER filter, UINT length, @@ -502,10 +469,10 @@ static PTOKEN_INFO WinDivertTokenLookup(PTOKEN_INFO token_info, */ extern BOOL WinDivertHelperParsePacket(const VOID *pPacket, UINT packetLen, PWINDIVERT_IPHDR *ppIPHeader, PWINDIVERT_IPV6HDR *ppIPv6Header, - UINT8 *pProtocol, PWINDIVERT_ICMPHDR *ppICMPHeader, - PWINDIVERT_ICMPV6HDR *ppICMPv6Header, PWINDIVERT_TCPHDR *ppTCPHeader, - PWINDIVERT_UDPHDR *ppUDPHeader, PVOID *ppData, UINT *pDataLen, - PVOID *ppNext, UINT *pNextLen) + UINT8 *pProtocol, PWINDIVERT_ICMPHDR *ppICMPHeader, + PWINDIVERT_ICMPV6HDR *ppICMPv6Header, PWINDIVERT_TCPHDR *ppTCPHeader, + PWINDIVERT_UDPHDR *ppUDPHeader, PVOID *ppData, UINT *pDataLen, + PVOID *ppNext, UINT *pNextLen) { WINDIVERT_PACKET info; if (!WinDivertHelperParsePacketEx(pPacket, packetLen, &info)) @@ -656,121 +623,122 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer, { static const TOKEN_INFO token_info[] = { - {"ACCEPT", TOKEN_EVENT_ACCEPT, L___S_}, - {"BIND", TOKEN_EVENT_BIND, L___S_}, - {"CLOSE", TOKEN_EVENT_CLOSE, L___SR}, - {"CONNECT", TOKEN_EVENT_CONNECT, L___S_}, - {"DELETED", TOKEN_EVENT_DELETED, L__F__}, - {"ESTABLISHED", TOKEN_EVENT_ESTABLISHED, L__F__}, - {"FALSE", TOKEN_MACRO_FALSE, LNMFSR}, - {"FLOW", TOKEN_FLOW, L____R}, - {"ICMP", TOKEN_MACRO_ICMP, LNMFSR}, - {"ICMPV6", TOKEN_MACRO_ICMPV6, LNMFSR}, - {"LISTEN", TOKEN_EVENT_LISTEN, L___S_}, - {"NETWORK", TOKEN_NETWORK, L____R}, - {"NETWORK_FORWARD", TOKEN_NETWORK_FORWARD, L____R}, - {"OPEN", TOKEN_EVENT_OPEN, L____R}, - {"PACKET", TOKEN_EVENT_PACKET, LNM___}, - {"REFLECT", TOKEN_REFLECT, L____R}, - {"SOCKET", TOKEN_SOCKET, L____R}, - {"TCP", TOKEN_MACRO_TCP, LNMFSR}, - {"TRUE", TOKEN_MACRO_TRUE, LNMFSR}, - {"UDP", TOKEN_MACRO_UDP, LNMFSR}, - {"and", TOKEN_AND, LNMFSR}, - {"endpointId", TOKEN_ENDPOINT_ID, L__FS_}, - {"event", TOKEN_EVENT, LNMFSR}, - {"false", TOKEN_FALSE, LNMFSR}, - {"fragment", TOKEN_FRAGMENT, LNM___}, - {"icmp", TOKEN_ICMP, LNMFS_}, - {"icmp.Body", TOKEN_ICMP_BODY, LNM___}, - {"icmp.Checksum", TOKEN_ICMP_CHECKSUM, LNM___}, - {"icmp.Code", TOKEN_ICMP_CODE, LNM___}, - {"icmp.Type", TOKEN_ICMP_TYPE, LNM___}, - {"icmpv6", TOKEN_ICMPV6, LNMFS_}, - {"icmpv6.Body", TOKEN_ICMPV6_BODY, LNM___}, - {"icmpv6.Checksum", TOKEN_ICMPV6_CHECKSUM, LNM___}, - {"icmpv6.Code", TOKEN_ICMPV6_CODE, LNM___}, - {"icmpv6.Type", TOKEN_ICMPV6_TYPE, LNM___}, - {"ifIdx", TOKEN_IF_IDX, LNM___}, - {"impostor", TOKEN_IMPOSTOR, LNM___}, - {"inbound", TOKEN_INBOUND, LN_FS_}, - {"ip", TOKEN_IP, LNMFS_}, - {"ip.Checksum", TOKEN_IP_CHECKSUM, LNM___}, - {"ip.DF", TOKEN_IP_DF, LNM___}, - {"ip.DstAddr", TOKEN_IP_DST_ADDR, LNM___}, - {"ip.FragOff", TOKEN_IP_FRAG_OFF, LNM___}, - {"ip.HdrLength", TOKEN_IP_HDR_LENGTH, LNM___}, - {"ip.Id", TOKEN_IP_ID, LNM___}, - {"ip.Length", TOKEN_IP_LENGTH, LNM___}, - {"ip.MF", TOKEN_IP_MF, LNM___}, - {"ip.Protocol", TOKEN_IP_PROTOCOL, LNM___}, - {"ip.SrcAddr", TOKEN_IP_SRC_ADDR, LNM___}, - {"ip.TOS", TOKEN_IP_TOS, LNM___}, - {"ip.TTL", TOKEN_IP_TTL, LNM___}, - {"ipv6", TOKEN_IPV6, LNMFS_}, - {"ipv6.DstAddr", TOKEN_IPV6_DST_ADDR, LNM___}, - {"ipv6.FlowLabel", TOKEN_IPV6_FLOW_LABEL, LNM___}, - {"ipv6.HopLimit", TOKEN_IPV6_HOP_LIMIT, LNM___}, - {"ipv6.Length", TOKEN_IPV6_LENGTH, LNM___}, - {"ipv6.NextHdr", TOKEN_IPV6_NEXT_HDR, LNM___}, - {"ipv6.SrcAddr", TOKEN_IPV6_SRC_ADDR, LNM___}, - {"ipv6.TrafficClass", TOKEN_IPV6_TRAFFIC_CLASS, LNM___}, - {"layer", TOKEN_LAYER, L____R}, - {"length", TOKEN_LENGTH, LNM___}, - {"localAddr", TOKEN_LOCAL_ADDR, LN_FS_}, - {"localPort", TOKEN_LOCAL_PORT, LN_FS_}, - {"loopback", TOKEN_LOOPBACK, LN_FS_}, - {"not", TOKEN_NOT, LNMFSR}, - {"or", TOKEN_OR, LNMFSR}, - {"outbound", TOKEN_OUTBOUND, LN_FS_}, - {"packet", TOKEN_PACKET, LNM___}, - {"packet16", TOKEN_PACKET16, LNM___}, - {"packet32", TOKEN_PACKET32, LNM___}, - {"parentEndpointId", TOKEN_PARENT_ENDPOINT_ID, L__FS_}, - {"priority", TOKEN_PRIORITY, L____R}, - {"processId", TOKEN_PROCESS_ID, L__FSR}, - {"protocol", TOKEN_PROTOCOL, LN_FS_}, - {"random16", TOKEN_RANDOM16, LNM___}, - {"random32", TOKEN_RANDOM32, LNM___}, - {"random8", TOKEN_RANDOM8, LNM___}, - {"remoteAddr", TOKEN_REMOTE_ADDR, LN_FS_}, - {"remotePort", TOKEN_REMOTE_PORT, LN_FS_}, - {"subIfIdx", TOKEN_SUB_IF_IDX, LNM___}, - {"tcp", TOKEN_TCP, LNMFS_}, - {"tcp.Ack", TOKEN_TCP_ACK, LNM___}, - {"tcp.AckNum", TOKEN_TCP_ACK_NUM, LNM___}, - {"tcp.Checksum", TOKEN_TCP_CHECKSUM, LNM___}, - {"tcp.DstPort", TOKEN_TCP_DST_PORT, LNM___}, - {"tcp.Fin", TOKEN_TCP_FIN, LNM___}, - {"tcp.HdrLength", TOKEN_TCP_HDR_LENGTH, LNM___}, - {"tcp.Payload", TOKEN_TCP_PAYLOAD, LNM___}, - {"tcp.Payload16", TOKEN_TCP_PAYLOAD16, LNM___}, - {"tcp.Payload32", TOKEN_TCP_PAYLOAD32, LNM___}, - {"tcp.PayloadLength", TOKEN_TCP_PAYLOAD_LENGTH, LNM___}, - {"tcp.Psh", TOKEN_TCP_PSH, LNM___}, - {"tcp.Rst", TOKEN_TCP_RST, LNM___}, - {"tcp.SeqNum", TOKEN_TCP_SEQ_NUM, LNM___}, - {"tcp.SrcPort", TOKEN_TCP_SRC_PORT, LNM___}, - {"tcp.Syn", TOKEN_TCP_SYN, LNM___}, - {"tcp.Urg", TOKEN_TCP_URG, LNM___}, - {"tcp.UrgPtr", TOKEN_TCP_URG_PTR, LNM___}, - {"tcp.Window", TOKEN_TCP_WINDOW, LNM___}, - {"timestamp", TOKEN_TIMESTAMP, LNMFSR}, - {"true", TOKEN_TRUE, LNMFSR}, - {"udp", TOKEN_UDP, LNMFS_}, - {"udp.Checksum", TOKEN_UDP_CHECKSUM, LNM___}, - {"udp.DstPort", TOKEN_UDP_DST_PORT, LNM___}, - {"udp.Length", TOKEN_UDP_LENGTH, LNM___}, - {"udp.Payload", TOKEN_UDP_PAYLOAD, LNM___}, - {"udp.Payload16", TOKEN_UDP_PAYLOAD16, LNM___}, - {"udp.Payload32", TOKEN_UDP_PAYLOAD32, LNM___}, - {"udp.PayloadLength", TOKEN_UDP_PAYLOAD_LENGTH, LNM___}, - {"udp.SrcPort", TOKEN_UDP_SRC_PORT, LNM___}, - {"zero", TOKEN_ZERO, LNMFSR}, + {"ACCEPT", TOKEN_EVENT_ACCEPT }, + {"BIND", TOKEN_EVENT_BIND }, + {"CLOSE", TOKEN_EVENT_CLOSE }, + {"CONNECT", TOKEN_EVENT_CONNECT }, + {"DELETED", TOKEN_EVENT_DELETED }, + {"ESTABLISHED", TOKEN_EVENT_ESTABLISHED }, + {"FALSE", TOKEN_MACRO_FALSE }, + {"FLOW", TOKEN_FLOW }, + {"ICMP", TOKEN_MACRO_ICMP }, + {"ICMPV6", TOKEN_MACRO_ICMPV6 }, + {"LISTEN", TOKEN_EVENT_LISTEN }, + {"NETWORK", TOKEN_NETWORK }, + {"NETWORK_FORWARD", TOKEN_NETWORK_FORWARD }, + {"OPEN", TOKEN_EVENT_OPEN }, + {"PACKET", TOKEN_EVENT_PACKET }, + {"REFLECT", TOKEN_REFLECT }, + {"SOCKET", TOKEN_SOCKET }, + {"TCP", TOKEN_MACRO_TCP }, + {"TRUE", TOKEN_MACRO_TRUE }, + {"UDP", TOKEN_MACRO_UDP }, + {"and", TOKEN_AND }, + {"endpointId", TOKEN_ENDPOINT_ID }, + {"event", TOKEN_EVENT }, + {"false", TOKEN_FALSE }, + {"fragment", TOKEN_FRAGMENT }, + {"icmp", TOKEN_ICMP }, + {"icmp.Body", TOKEN_ICMP_BODY }, + {"icmp.Checksum", TOKEN_ICMP_CHECKSUM }, + {"icmp.Code", TOKEN_ICMP_CODE }, + {"icmp.Type", TOKEN_ICMP_TYPE }, + {"icmpv6", TOKEN_ICMPV6 }, + {"icmpv6.Body", TOKEN_ICMPV6_BODY }, + {"icmpv6.Checksum", TOKEN_ICMPV6_CHECKSUM }, + {"icmpv6.Code", TOKEN_ICMPV6_CODE }, + {"icmpv6.Type", TOKEN_ICMPV6_TYPE }, + {"ifIdx", TOKEN_IF_IDX }, + {"impostor", TOKEN_IMPOSTOR }, + {"inbound", TOKEN_INBOUND }, + {"ip", TOKEN_IP }, + {"ip.Checksum", TOKEN_IP_CHECKSUM }, + {"ip.DF", TOKEN_IP_DF }, + {"ip.DstAddr", TOKEN_IP_DST_ADDR }, + {"ip.FragOff", TOKEN_IP_FRAG_OFF }, + {"ip.HdrLength", TOKEN_IP_HDR_LENGTH }, + {"ip.Id", TOKEN_IP_ID }, + {"ip.Length", TOKEN_IP_LENGTH }, + {"ip.MF", TOKEN_IP_MF }, + {"ip.Protocol", TOKEN_IP_PROTOCOL }, + {"ip.SrcAddr", TOKEN_IP_SRC_ADDR }, + {"ip.TOS", TOKEN_IP_TOS }, + {"ip.TTL", TOKEN_IP_TTL }, + {"ipv6", TOKEN_IPV6 }, + {"ipv6.DstAddr", TOKEN_IPV6_DST_ADDR }, + {"ipv6.FlowLabel", TOKEN_IPV6_FLOW_LABEL }, + {"ipv6.HopLimit", TOKEN_IPV6_HOP_LIMIT }, + {"ipv6.Length", TOKEN_IPV6_LENGTH }, + {"ipv6.NextHdr", TOKEN_IPV6_NEXT_HDR }, + {"ipv6.SrcAddr", TOKEN_IPV6_SRC_ADDR }, + {"ipv6.TrafficClass", TOKEN_IPV6_TRAFFIC_CLASS}, + {"layer", TOKEN_LAYER }, + {"length", TOKEN_LENGTH }, + {"localAddr", TOKEN_LOCAL_ADDR }, + {"localPort", TOKEN_LOCAL_PORT }, + {"loopback", TOKEN_LOOPBACK }, + {"not", TOKEN_NOT }, + {"or", TOKEN_OR }, + {"outbound", TOKEN_OUTBOUND }, + {"packet", TOKEN_PACKET }, + {"packet16", TOKEN_PACKET16 }, + {"packet32", TOKEN_PACKET32 }, + {"parentEndpointId", TOKEN_PARENT_ENDPOINT_ID}, + {"priority", TOKEN_PRIORITY }, + {"processId", TOKEN_PROCESS_ID }, + {"protocol", TOKEN_PROTOCOL }, + {"random16", TOKEN_RANDOM16 }, + {"random32", TOKEN_RANDOM32 }, + {"random8", TOKEN_RANDOM8 }, + {"remoteAddr", TOKEN_REMOTE_ADDR }, + {"remotePort", TOKEN_REMOTE_PORT }, + {"subIfIdx", TOKEN_SUB_IF_IDX }, + {"tcp", TOKEN_TCP }, + {"tcp.Ack", TOKEN_TCP_ACK }, + {"tcp.AckNum", TOKEN_TCP_ACK_NUM }, + {"tcp.Checksum", TOKEN_TCP_CHECKSUM }, + {"tcp.DstPort", TOKEN_TCP_DST_PORT }, + {"tcp.Fin", TOKEN_TCP_FIN }, + {"tcp.HdrLength", TOKEN_TCP_HDR_LENGTH }, + {"tcp.Payload", TOKEN_TCP_PAYLOAD }, + {"tcp.Payload16", TOKEN_TCP_PAYLOAD16 }, + {"tcp.Payload32", TOKEN_TCP_PAYLOAD32 }, + {"tcp.PayloadLength", TOKEN_TCP_PAYLOAD_LENGTH}, + {"tcp.Psh", TOKEN_TCP_PSH }, + {"tcp.Rst", TOKEN_TCP_RST }, + {"tcp.SeqNum", TOKEN_TCP_SEQ_NUM }, + {"tcp.SrcPort", TOKEN_TCP_SRC_PORT }, + {"tcp.Syn", TOKEN_TCP_SYN }, + {"tcp.Urg", TOKEN_TCP_URG }, + {"tcp.UrgPtr", TOKEN_TCP_URG_PTR }, + {"tcp.Window", TOKEN_TCP_WINDOW }, + {"timestamp", TOKEN_TIMESTAMP }, + {"true", TOKEN_TRUE }, + {"udp", TOKEN_UDP }, + {"udp.Checksum", TOKEN_UDP_CHECKSUM }, + {"udp.DstPort", TOKEN_UDP_DST_PORT }, + {"udp.Length", TOKEN_UDP_LENGTH }, + {"udp.Payload", TOKEN_UDP_PAYLOAD }, + {"udp.Payload16", TOKEN_UDP_PAYLOAD16 }, + {"udp.Payload32", TOKEN_UDP_PAYLOAD32 }, + {"udp.PayloadLength", TOKEN_UDP_PAYLOAD_LENGTH}, + {"udp.SrcPort", TOKEN_UDP_SRC_PORT }, + {"zero", TOKEN_ZERO }, }; TOKEN_INFO *result; char c; char token[TOKEN_MAXLEN]; + UINT32 field; UINT i = 0, j; UINT tp = 0; @@ -906,9 +874,12 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer, sizeof(token_info) / sizeof(TOKEN_INFO), token); if (result != NULL) { - if ((result->flags & (1 << layer)) == 0) + field = WinDivertKindToField(result->kind); + if (field <= WINDIVERT_FILTER_FIELD_MAX && + !WinDivertValidateField(layer, field)) { - return MAKE_ERROR(WINDIVERT_ERROR_BAD_TOKEN_FOR_LAYER, i-j); + return MAKE_ERROR(WINDIVERT_ERROR_BAD_TOKEN_FOR_LAYER, + i-j); } if (WinDivertExpandMacro(result->kind, layer, &tokens[tp].val[0])) @@ -1779,15 +1750,197 @@ static INT16 WinDivertFlattenExpr(PEXPR expr, INT16 *label, INT16 succ, } } +/* + * Convert a kind to a field. + */ +static UINT32 WinDivertKindToField(KIND kind) +{ + switch (kind) + { + case TOKEN_ZERO: + return WINDIVERT_FILTER_FIELD_ZERO; + case TOKEN_EVENT: + return WINDIVERT_FILTER_FIELD_EVENT; + case TOKEN_RANDOM8: + return WINDIVERT_FILTER_FIELD_RANDOM8; + case TOKEN_RANDOM16: + return WINDIVERT_FILTER_FIELD_RANDOM16; + case TOKEN_RANDOM32: + return WINDIVERT_FILTER_FIELD_RANDOM32; + case TOKEN_PACKET: + return WINDIVERT_FILTER_FIELD_PACKET; + case TOKEN_PACKET16: + return WINDIVERT_FILTER_FIELD_PACKET16; + case TOKEN_PACKET32: + return WINDIVERT_FILTER_FIELD_PACKET32; + case TOKEN_LENGTH: + return WINDIVERT_FILTER_FIELD_LENGTH; + case TOKEN_TIMESTAMP: + return WINDIVERT_FILTER_FIELD_TIMESTAMP; + case TOKEN_TCP_PAYLOAD: + return WINDIVERT_FILTER_FIELD_TCP_PAYLOAD; + case TOKEN_TCP_PAYLOAD16: + return WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16; + case TOKEN_TCP_PAYLOAD32: + return WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32; + case TOKEN_UDP_PAYLOAD: + return WINDIVERT_FILTER_FIELD_UDP_PAYLOAD; + case TOKEN_UDP_PAYLOAD16: + return WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16; + case TOKEN_UDP_PAYLOAD32: + return WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32; + case TOKEN_OUTBOUND: + return WINDIVERT_FILTER_FIELD_OUTBOUND; + case TOKEN_INBOUND: + return WINDIVERT_FILTER_FIELD_INBOUND; + case TOKEN_FRAGMENT: + return WINDIVERT_FILTER_FIELD_FRAGMENT; + case TOKEN_IF_IDX: + return WINDIVERT_FILTER_FIELD_IFIDX; + case TOKEN_SUB_IF_IDX: + return WINDIVERT_FILTER_FIELD_SUBIFIDX; + case TOKEN_LOOPBACK: + return WINDIVERT_FILTER_FIELD_LOOPBACK; + case TOKEN_IMPOSTOR: + return WINDIVERT_FILTER_FIELD_IMPOSTOR; + case TOKEN_PROCESS_ID: + return WINDIVERT_FILTER_FIELD_PROCESSID; + case TOKEN_LOCAL_ADDR: + return WINDIVERT_FILTER_FIELD_LOCALADDR; + case TOKEN_REMOTE_ADDR: + return WINDIVERT_FILTER_FIELD_REMOTEADDR; + case TOKEN_LOCAL_PORT: + return WINDIVERT_FILTER_FIELD_LOCALPORT; + case TOKEN_REMOTE_PORT: + return WINDIVERT_FILTER_FIELD_REMOTEPORT; + case TOKEN_PROTOCOL: + return WINDIVERT_FILTER_FIELD_PROTOCOL; + case TOKEN_ENDPOINT_ID: + return WINDIVERT_FILTER_FIELD_ENDPOINTID; + case TOKEN_PARENT_ENDPOINT_ID: + return WINDIVERT_FILTER_FIELD_PARENTENDPOINTID; + case TOKEN_LAYER: + return WINDIVERT_FILTER_FIELD_LAYER; + case TOKEN_PRIORITY: + return WINDIVERT_FILTER_FIELD_PRIORITY; + case TOKEN_IP: + return WINDIVERT_FILTER_FIELD_IP; + case TOKEN_IPV6: + return WINDIVERT_FILTER_FIELD_IPV6; + case TOKEN_ICMP: + return WINDIVERT_FILTER_FIELD_ICMP; + case TOKEN_ICMPV6: + return WINDIVERT_FILTER_FIELD_ICMPV6; + case TOKEN_TCP: + return WINDIVERT_FILTER_FIELD_TCP; + case TOKEN_UDP: + return WINDIVERT_FILTER_FIELD_UDP; + case TOKEN_IP_HDR_LENGTH: + return WINDIVERT_FILTER_FIELD_IP_HDRLENGTH; + case TOKEN_IP_TOS: + return WINDIVERT_FILTER_FIELD_IP_TOS; + case TOKEN_IP_LENGTH: + return WINDIVERT_FILTER_FIELD_IP_LENGTH; + case TOKEN_IP_ID: + return WINDIVERT_FILTER_FIELD_IP_ID; + case TOKEN_IP_DF: + return WINDIVERT_FILTER_FIELD_IP_DF; + case TOKEN_IP_MF: + return WINDIVERT_FILTER_FIELD_IP_MF; + case TOKEN_IP_FRAG_OFF: + return WINDIVERT_FILTER_FIELD_IP_FRAGOFF; + case TOKEN_IP_TTL: + return WINDIVERT_FILTER_FIELD_IP_TTL; + case TOKEN_IP_PROTOCOL: + return WINDIVERT_FILTER_FIELD_IP_PROTOCOL; + case TOKEN_IP_CHECKSUM: + return WINDIVERT_FILTER_FIELD_IP_CHECKSUM; + case TOKEN_IP_SRC_ADDR: + return WINDIVERT_FILTER_FIELD_IP_SRCADDR; + case TOKEN_IP_DST_ADDR: + return WINDIVERT_FILTER_FIELD_IP_DSTADDR; + case TOKEN_IPV6_TRAFFIC_CLASS: + return WINDIVERT_FILTER_FIELD_IPV6_TRAFFICCLASS; + case TOKEN_IPV6_FLOW_LABEL: + return WINDIVERT_FILTER_FIELD_IPV6_FLOWLABEL; + case TOKEN_IPV6_LENGTH: + return WINDIVERT_FILTER_FIELD_IPV6_LENGTH; + case TOKEN_IPV6_NEXT_HDR: + return WINDIVERT_FILTER_FIELD_IPV6_NEXTHDR; + case TOKEN_IPV6_HOP_LIMIT: + return WINDIVERT_FILTER_FIELD_IPV6_HOPLIMIT; + case TOKEN_IPV6_SRC_ADDR: + return WINDIVERT_FILTER_FIELD_IPV6_SRCADDR; + case TOKEN_IPV6_DST_ADDR: + return WINDIVERT_FILTER_FIELD_IPV6_DSTADDR; + case TOKEN_ICMP_TYPE: + return WINDIVERT_FILTER_FIELD_ICMP_TYPE; + case TOKEN_ICMP_CODE: + return WINDIVERT_FILTER_FIELD_ICMP_CODE; + case TOKEN_ICMP_CHECKSUM: + return WINDIVERT_FILTER_FIELD_ICMP_CHECKSUM; + case TOKEN_ICMP_BODY: + return WINDIVERT_FILTER_FIELD_ICMP_BODY; + case TOKEN_ICMPV6_TYPE: + return WINDIVERT_FILTER_FIELD_ICMPV6_TYPE; + case TOKEN_ICMPV6_CODE: + return WINDIVERT_FILTER_FIELD_ICMPV6_CODE; + case TOKEN_ICMPV6_CHECKSUM: + return WINDIVERT_FILTER_FIELD_ICMPV6_CHECKSUM; + case TOKEN_ICMPV6_BODY: + return WINDIVERT_FILTER_FIELD_ICMPV6_BODY; + case TOKEN_TCP_SRC_PORT: + return WINDIVERT_FILTER_FIELD_TCP_SRCPORT; + case TOKEN_TCP_DST_PORT: + return WINDIVERT_FILTER_FIELD_TCP_DSTPORT; + case TOKEN_TCP_SEQ_NUM: + return WINDIVERT_FILTER_FIELD_TCP_SEQNUM; + case TOKEN_TCP_ACK_NUM: + return WINDIVERT_FILTER_FIELD_TCP_ACKNUM; + case TOKEN_TCP_HDR_LENGTH: + return WINDIVERT_FILTER_FIELD_TCP_HDRLENGTH; + case TOKEN_TCP_URG: + return WINDIVERT_FILTER_FIELD_TCP_URG; + case TOKEN_TCP_ACK: + return WINDIVERT_FILTER_FIELD_TCP_ACK; + case TOKEN_TCP_PSH: + return WINDIVERT_FILTER_FIELD_TCP_PSH; + case TOKEN_TCP_RST: + return WINDIVERT_FILTER_FIELD_TCP_RST; + case TOKEN_TCP_SYN: + return WINDIVERT_FILTER_FIELD_TCP_SYN; + case TOKEN_TCP_FIN: + return WINDIVERT_FILTER_FIELD_TCP_FIN; + case TOKEN_TCP_WINDOW: + return WINDIVERT_FILTER_FIELD_TCP_WINDOW; + case TOKEN_TCP_CHECKSUM: + return WINDIVERT_FILTER_FIELD_TCP_CHECKSUM; + case TOKEN_TCP_URG_PTR: + return WINDIVERT_FILTER_FIELD_TCP_URGPTR; + case TOKEN_TCP_PAYLOAD_LENGTH: + return WINDIVERT_FILTER_FIELD_TCP_PAYLOADLENGTH; + case TOKEN_UDP_SRC_PORT: + return WINDIVERT_FILTER_FIELD_UDP_SRCPORT; + case TOKEN_UDP_DST_PORT: + return WINDIVERT_FILTER_FIELD_UDP_DSTPORT; + case TOKEN_UDP_LENGTH: + return WINDIVERT_FILTER_FIELD_UDP_LENGTH; + case TOKEN_UDP_CHECKSUM: + return WINDIVERT_FILTER_FIELD_UDP_CHECKSUM; + case TOKEN_UDP_PAYLOAD_LENGTH: + return WINDIVERT_FILTER_FIELD_UDP_PAYLOADLENGTH; + default: + return UINT32_MAX; + } +} + /* * Emit a test. */ static void WinDivertEmitTest(PEXPR test, UINT16 offset, PWINDIVERT_FILTER object) { - BOOL big; PEXPR var = test->arg[0], val = test->arg[1]; - UINT32 val0; switch (test->kind) { case TOKEN_EQ: @@ -1811,298 +1964,28 @@ static void WinDivertEmitTest(PEXPR test, UINT16 offset, default: return; } - big = FALSE; - object->arg[1] = object->arg[2] = object->arg[3] = 0; - val0 = val->val[0]; + object->field = WinDivertKindToField(var->kind); + object->neg = (val->neg? 1: 0); + object->arg[0] = val->val[0]; + object->arg[1] = val->val[1]; + object->arg[2] = val->val[2]; + object->arg[3] = val->val[3]; switch (var->kind) { - case TOKEN_ZERO: - object->field = WINDIVERT_FILTER_FIELD_ZERO; - break; - case TOKEN_EVENT: - object->field = WINDIVERT_FILTER_FIELD_EVENT; - break; - case TOKEN_RANDOM8: - object->field = WINDIVERT_FILTER_FIELD_RANDOM8; - break; - case TOKEN_RANDOM16: - object->field = WINDIVERT_FILTER_FIELD_RANDOM16; - break; - case TOKEN_RANDOM32: - object->field = WINDIVERT_FILTER_FIELD_RANDOM32; - break; case TOKEN_PACKET: - object->field = WINDIVERT_FILTER_FIELD_PACKET; - object->arg[1] = var->val[0]; - break; case TOKEN_PACKET16: - object->field = WINDIVERT_FILTER_FIELD_PACKET16; - object->arg[1] = var->val[0]; - break; case TOKEN_PACKET32: - object->field = WINDIVERT_FILTER_FIELD_PACKET32; - object->arg[1] = var->val[0]; - break; - case TOKEN_LENGTH: - object->field = WINDIVERT_FILTER_FIELD_LENGTH; - break; - case TOKEN_TIMESTAMP: - big = TRUE; - object->field = WINDIVERT_FILTER_FIELD_TIMESTAMP; - break; case TOKEN_TCP_PAYLOAD: - object->field = WINDIVERT_FILTER_FIELD_TCP_PAYLOAD; - object->arg[1] = var->val[0]; - break; case TOKEN_TCP_PAYLOAD16: - object->field = WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16; - object->arg[1] = var->val[0]; - break; case TOKEN_TCP_PAYLOAD32: - object->field = WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32; - object->arg[1] = var->val[0]; - break; case TOKEN_UDP_PAYLOAD: - object->field = WINDIVERT_FILTER_FIELD_UDP_PAYLOAD; - object->arg[1] = var->val[0]; - break; case TOKEN_UDP_PAYLOAD16: - object->field = WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16; - object->arg[1] = var->val[0]; - break; case TOKEN_UDP_PAYLOAD32: - object->field = WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32; object->arg[1] = var->val[0]; break; - case TOKEN_OUTBOUND: - object->field = WINDIVERT_FILTER_FIELD_OUTBOUND; - break; - case TOKEN_INBOUND: - object->field = WINDIVERT_FILTER_FIELD_INBOUND; - break; - case TOKEN_FRAGMENT: - object->field = WINDIVERT_FILTER_FIELD_FRAGMENT; - break; - case TOKEN_IF_IDX: - object->field = WINDIVERT_FILTER_FIELD_IFIDX; - break; - case TOKEN_SUB_IF_IDX: - object->field = WINDIVERT_FILTER_FIELD_SUBIFIDX; - break; - case TOKEN_LOOPBACK: - object->field = WINDIVERT_FILTER_FIELD_LOOPBACK; - break; - case TOKEN_IMPOSTOR: - object->field = WINDIVERT_FILTER_FIELD_IMPOSTOR; - break; - case TOKEN_PROCESS_ID: - object->field = WINDIVERT_FILTER_FIELD_PROCESSID; - break; - case TOKEN_LOCAL_ADDR: - object->field = WINDIVERT_FILTER_FIELD_LOCALADDR; - big = TRUE; - break; - case TOKEN_REMOTE_ADDR: - object->field = WINDIVERT_FILTER_FIELD_REMOTEADDR; - big = TRUE; - break; - case TOKEN_LOCAL_PORT: - object->field = WINDIVERT_FILTER_FIELD_LOCALPORT; - break; - case TOKEN_REMOTE_PORT: - object->field = WINDIVERT_FILTER_FIELD_REMOTEPORT; - break; - case TOKEN_PROTOCOL: - object->field = WINDIVERT_FILTER_FIELD_PROTOCOL; - break; - case TOKEN_ENDPOINT_ID: - object->field = WINDIVERT_FILTER_FIELD_ENDPOINTID; - big = TRUE; - break; - case TOKEN_PARENT_ENDPOINT_ID: - object->field = WINDIVERT_FILTER_FIELD_PARENTENDPOINTID; - big = TRUE; - break; - case TOKEN_LAYER: - object->field = WINDIVERT_FILTER_FIELD_LAYER; - break; - case TOKEN_PRIORITY: - object->field = WINDIVERT_FILTER_FIELD_PRIORITY; - break; - case TOKEN_IP: - object->field = WINDIVERT_FILTER_FIELD_IP; - break; - case TOKEN_IPV6: - object->field = WINDIVERT_FILTER_FIELD_IPV6; - break; - case TOKEN_ICMP: - object->field = WINDIVERT_FILTER_FIELD_ICMP; - break; - case TOKEN_ICMPV6: - object->field = WINDIVERT_FILTER_FIELD_ICMPV6; - break; - case TOKEN_TCP: - object->field = WINDIVERT_FILTER_FIELD_TCP; - break; - case TOKEN_UDP: - object->field = WINDIVERT_FILTER_FIELD_UDP; - break; - case TOKEN_IP_HDR_LENGTH: - object->field = WINDIVERT_FILTER_FIELD_IP_HDRLENGTH; - break; - case TOKEN_IP_TOS: - object->field = WINDIVERT_FILTER_FIELD_IP_TOS; - break; - case TOKEN_IP_LENGTH: - object->field = WINDIVERT_FILTER_FIELD_IP_LENGTH; - break; - case TOKEN_IP_ID: - object->field = WINDIVERT_FILTER_FIELD_IP_ID; - break; - case TOKEN_IP_DF: - object->field = WINDIVERT_FILTER_FIELD_IP_DF; - break; - case TOKEN_IP_MF: - object->field = WINDIVERT_FILTER_FIELD_IP_MF; - break; - case TOKEN_IP_FRAG_OFF: - object->field = WINDIVERT_FILTER_FIELD_IP_FRAGOFF; - break; - case TOKEN_IP_TTL: - object->field = WINDIVERT_FILTER_FIELD_IP_TTL; - break; - case TOKEN_IP_PROTOCOL: - object->field = WINDIVERT_FILTER_FIELD_IP_PROTOCOL; - break; - case TOKEN_IP_CHECKSUM: - object->field = WINDIVERT_FILTER_FIELD_IP_CHECKSUM; - break; - case TOKEN_IP_SRC_ADDR: - object->field = WINDIVERT_FILTER_FIELD_IP_SRCADDR; - big = TRUE; - break; - case TOKEN_IP_DST_ADDR: - object->field = WINDIVERT_FILTER_FIELD_IP_DSTADDR; - big = TRUE; - break; - case TOKEN_IPV6_TRAFFIC_CLASS: - object->field = WINDIVERT_FILTER_FIELD_IPV6_TRAFFICCLASS; - break; - case TOKEN_IPV6_FLOW_LABEL: - object->field = WINDIVERT_FILTER_FIELD_IPV6_FLOWLABEL; - break; - case TOKEN_IPV6_LENGTH: - object->field = WINDIVERT_FILTER_FIELD_IPV6_LENGTH; - break; - case TOKEN_IPV6_NEXT_HDR: - object->field = WINDIVERT_FILTER_FIELD_IPV6_NEXTHDR; - break; - case TOKEN_IPV6_HOP_LIMIT: - object->field = WINDIVERT_FILTER_FIELD_IPV6_HOPLIMIT; - break; - case TOKEN_IPV6_SRC_ADDR: - object->field = WINDIVERT_FILTER_FIELD_IPV6_SRCADDR; - big = TRUE; - break; - case TOKEN_IPV6_DST_ADDR: - object->field = WINDIVERT_FILTER_FIELD_IPV6_DSTADDR; - big = TRUE; - break; - case TOKEN_ICMP_TYPE: - object->field = WINDIVERT_FILTER_FIELD_ICMP_TYPE; - break; - case TOKEN_ICMP_CODE: - object->field = WINDIVERT_FILTER_FIELD_ICMP_CODE; - break; - case TOKEN_ICMP_CHECKSUM: - object->field = WINDIVERT_FILTER_FIELD_ICMP_CHECKSUM; - break; - case TOKEN_ICMP_BODY: - object->field = WINDIVERT_FILTER_FIELD_ICMP_BODY; - break; - case TOKEN_ICMPV6_TYPE: - object->field = WINDIVERT_FILTER_FIELD_ICMPV6_TYPE; - break; - case TOKEN_ICMPV6_CODE: - object->field = WINDIVERT_FILTER_FIELD_ICMPV6_CODE; - break; - case TOKEN_ICMPV6_CHECKSUM: - object->field = WINDIVERT_FILTER_FIELD_ICMPV6_CHECKSUM; - break; - case TOKEN_ICMPV6_BODY: - object->field = WINDIVERT_FILTER_FIELD_ICMPV6_BODY; - break; - case TOKEN_TCP_SRC_PORT: - object->field = WINDIVERT_FILTER_FIELD_TCP_SRCPORT; - break; - case TOKEN_TCP_DST_PORT: - object->field = WINDIVERT_FILTER_FIELD_TCP_DSTPORT; - break; - case TOKEN_TCP_SEQ_NUM: - object->field = WINDIVERT_FILTER_FIELD_TCP_SEQNUM; - break; - case TOKEN_TCP_ACK_NUM: - object->field = WINDIVERT_FILTER_FIELD_TCP_ACKNUM; - break; - case TOKEN_TCP_HDR_LENGTH: - object->field = WINDIVERT_FILTER_FIELD_TCP_HDRLENGTH; - break; - case TOKEN_TCP_URG: - object->field = WINDIVERT_FILTER_FIELD_TCP_URG; - break; - case TOKEN_TCP_ACK: - object->field = WINDIVERT_FILTER_FIELD_TCP_ACK; - break; - case TOKEN_TCP_PSH: - object->field = WINDIVERT_FILTER_FIELD_TCP_PSH; - break; - case TOKEN_TCP_RST: - object->field = WINDIVERT_FILTER_FIELD_TCP_RST; - break; - case TOKEN_TCP_SYN: - object->field = WINDIVERT_FILTER_FIELD_TCP_SYN; - break; - case TOKEN_TCP_FIN: - object->field = WINDIVERT_FILTER_FIELD_TCP_FIN; - break; - case TOKEN_TCP_WINDOW: - object->field = WINDIVERT_FILTER_FIELD_TCP_WINDOW; - break; - case TOKEN_TCP_CHECKSUM: - object->field = WINDIVERT_FILTER_FIELD_TCP_CHECKSUM; - break; - case TOKEN_TCP_URG_PTR: - object->field = WINDIVERT_FILTER_FIELD_TCP_URGPTR; - break; - case TOKEN_TCP_PAYLOAD_LENGTH: - object->field = WINDIVERT_FILTER_FIELD_TCP_PAYLOADLENGTH; - break; - case TOKEN_UDP_SRC_PORT: - object->field = WINDIVERT_FILTER_FIELD_UDP_SRCPORT; - break; - case TOKEN_UDP_DST_PORT: - object->field = WINDIVERT_FILTER_FIELD_UDP_DSTPORT; - break; - case TOKEN_UDP_LENGTH: - object->field = WINDIVERT_FILTER_FIELD_UDP_LENGTH; - break; - case TOKEN_UDP_CHECKSUM: - object->field = WINDIVERT_FILTER_FIELD_UDP_CHECKSUM; - break; - case TOKEN_UDP_PAYLOAD_LENGTH: - object->field = WINDIVERT_FILTER_FIELD_UDP_PAYLOADLENGTH; - break; default: - return; + break; } - object->arg[0] = val0; - if (big) - { - object->arg[1] = val->val[1]; - object->arg[2] = val->val[2]; - object->arg[3] = val->val[3]; - } - object->neg = (val->neg? 1: 0); switch (test->succ) { case WINDIVERT_FILTER_RESULT_ACCEPT: @@ -2536,78 +2419,18 @@ extern BOOL WinDivertHelperCompileFilter(const char *filter_str, return !IS_ERROR(err); } -/* - * Big number comparison. - */ -static int WinDivertCompare128(BOOL neg_a, const UINT32 *a, BOOL neg_b, - const UINT32 *b, BOOL big) -{ - int neg; - if (neg_a && !neg_b) - { - return -1; - } - if (!neg_a && neg_b) - { - return 1; - } - neg = (neg_a? -1: 1); - if (big) - { - if (a[3] < b[3]) - { - return -neg; - } - if (a[3] > b[3]) - { - return neg; - } - if (a[2] < b[2]) - { - return -neg; - } - if (a[2] > b[2]) - { - return neg; - } - if (a[1] < b[1]) - { - return -neg; - } - if (a[1] > b[1]) - { - return neg; - } - } - if (a[0] < b[0]) - { - return -neg; - } - if (a[0] > b[0]) - { - return neg; - } - return 0; -} - /* * Get packet/payload data. */ -static BOOL WinDivertGetData(const VOID *packet, UINT packet_len, UINT offset, - INT idx, UINT size, PVOID data) +static BOOL WinDivertGetData(const VOID *packet, UINT packet_len, INT min, + INT max, INT idx, PVOID data, UINT size) { - if (idx < 0) - { - idx += (INT)packet_len; - } - else - { - idx += (INT)offset; - } - if (idx < (INT)offset || idx > (INT)(packet_len - size)) + idx += (idx < 0? max: min); + if (idx < min || idx > (max - (INT)size)) { return FALSE; } + memcpy(data, (UINT8 *)packet + idx, size); return TRUE; } @@ -2618,26 +2441,23 @@ static BOOL WinDivertGetData(const VOID *packet, UINT packet_len, UINT offset, extern BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet, UINT packet_len, const WINDIVERT_ADDRESS *addr) { - UINT16 pc; ERROR err; DWORD error; - PWINDIVERT_IPHDR iphdr = NULL; - PWINDIVERT_IPV6HDR ipv6hdr = NULL; - PWINDIVERT_ICMPHDR icmphdr = NULL; - PWINDIVERT_ICMPV6HDR icmpv6hdr = NULL; - PWINDIVERT_TCPHDR tcphdr = NULL; - PWINDIVERT_UDPHDR udphdr = NULL; WINDIVERT_PACKET info; + PWINDIVERT_IPHDR ip_header = NULL; + PWINDIVERT_IPV6HDR ipv6_header = NULL; + PWINDIVERT_ICMPHDR icmp_header = NULL; + PWINDIVERT_ICMPV6HDR icmpv6_header = NULL; + PWINDIVERT_TCPHDR tcp_header = NULL; + PWINDIVERT_UDPHDR udp_header = NULL; + const WINDIVERT_DATA_NETWORK *network_data = NULL; + const WINDIVERT_DATA_FLOW *flow_data = NULL; + const WINDIVERT_DATA_SOCKET *socket_data = NULL; + const WINDIVERT_DATA_REFLECT *reflect_data = NULL; + BOOL fragment = FALSE; UINT8 protocol = 0; UINT header_len = 0, payload_len = 0; - UINT64 random64 = 0; - UINT32 val[4]; - ULARGE_INTEGER val64; - UINT8 data8; - UINT16 data16; - UINT32 data32; - BOOL pass, big, neg, fragment = FALSE; - int cmp; + int result; HANDLE pool; WINDIVERT_FILTER *object; UINT obj_len; @@ -2661,18 +2481,18 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet, SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } - protocol = info.Protocol; - iphdr = info.IPHeader; - ipv6hdr = info.IPv6Header; - icmphdr = info.ICMPHeader; - icmpv6hdr = info.ICMPv6Header; - tcphdr = info.TCPHeader; - udphdr = info.UDPHeader; - payload_len = info.PayloadLength; - header_len = info.HeaderLength; - fragment = info.Fragment; - if ((addr->IPv6 && ipv6hdr == NULL) || - (!addr->IPv6 && iphdr == NULL)) + protocol = info.Protocol; + ip_header = info.IPHeader; + ipv6_header = info.IPv6Header; + icmp_header = info.ICMPHeader; + icmpv6_header = info.ICMPv6Header; + tcp_header = info.TCPHeader; + udp_header = info.UDPHeader; + payload_len = info.PayloadLength; + header_len = info.HeaderLength; + fragment = info.Fragment; + if ((addr->IPv6 && ipv6_header == NULL) || + (!addr->IPv6 && ip_header == NULL)) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; @@ -2692,6 +2512,25 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet, SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } + switch (addr->Layer) + { + case WINDIVERT_LAYER_NETWORK: + case WINDIVERT_LAYER_NETWORK_FORWARD: + network_data = &addr->Network; + break; + case WINDIVERT_LAYER_FLOW: + flow_data = &addr->Flow; + break; + case WINDIVERT_LAYER_SOCKET: + socket_data = &addr->Socket; + break; + case WINDIVERT_LAYER_REFLECT: + reflect_data = &addr->Reflect; + break; + default: + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } pool = HeapCreate(HEAP_NO_SERIALIZE, WINDIVERT_MIN_POOL_SIZE, WINDIVERT_MAX_POOL_SIZE); @@ -2712,786 +2551,46 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet, goto WinDivertHelperEvalFilterError; } - pc = 0; - while (TRUE) + result = WinDivertExecuteFilter( + object, + addr->Layer, + addr->Timestamp, + addr->Event, + (addr->IPv6 != 0? FALSE: TRUE), + (addr->Outbound != 0? TRUE: FALSE), + (addr->Loopback != 0? TRUE: FALSE), + (addr->Impostor != 0? TRUE: FALSE), + fragment, + network_data, + flow_data, + socket_data, + reflect_data, + ip_header, + ipv6_header, + icmp_header, + icmpv6_header, + tcp_header, + udp_header, + protocol, + packet, + packet_len, + header_len, + payload_len); + + HeapDestroy(pool); + if (result < 0) { - switch (pc) - { - case WINDIVERT_FILTER_RESULT_ACCEPT: - HeapDestroy(pool); - return TRUE; - case WINDIVERT_FILTER_RESULT_REJECT: - HeapDestroy(pool); - SetLastError(0); - return FALSE; - default: - if (pc >= obj_len) - { - SetLastError(ERROR_INVALID_PARAMETER); - goto WinDivertHelperEvalFilterError; - } - break; - } - pass = TRUE; - big = FALSE; - switch (object[pc].field) - { - case WINDIVERT_FILTER_FIELD_ZERO: - case WINDIVERT_FILTER_FIELD_EVENT: - case WINDIVERT_FILTER_FIELD_TIMESTAMP: - pass = TRUE; - break; - case WINDIVERT_FILTER_FIELD_INBOUND: - case WINDIVERT_FILTER_FIELD_OUTBOUND: - pass = (addr->Layer != WINDIVERT_LAYER_NETWORK_FORWARD && - addr->Layer != WINDIVERT_LAYER_REFLECT); - break; - case WINDIVERT_FILTER_FIELD_LOOPBACK: - case WINDIVERT_FILTER_FIELD_IMPOSTOR: - case WINDIVERT_FILTER_FIELD_IP: - case WINDIVERT_FILTER_FIELD_IPV6: - case WINDIVERT_FILTER_FIELD_ICMP: - case WINDIVERT_FILTER_FIELD_ICMPV6: - case WINDIVERT_FILTER_FIELD_TCP: - case WINDIVERT_FILTER_FIELD_UDP: - pass = (addr->Layer != WINDIVERT_LAYER_REFLECT); - break; - case WINDIVERT_FILTER_FIELD_RANDOM8: - case WINDIVERT_FILTER_FIELD_RANDOM16: - case WINDIVERT_FILTER_FIELD_RANDOM32: - pass = (addr->Layer == WINDIVERT_LAYER_NETWORK || - addr->Layer == WINDIVERT_LAYER_NETWORK_FORWARD); - if (pass && random64 == 0) - { - random64 = WinDivertHashPacket((UINT64)addr->Timestamp, - iphdr, ipv6hdr, icmphdr, icmpv6hdr, tcphdr, udphdr); - random64 |= 0xFF00000000000000ull; - } - break; - case WINDIVERT_FILTER_FIELD_IFIDX: - case WINDIVERT_FILTER_FIELD_SUBIFIDX: - case WINDIVERT_FILTER_FIELD_PACKET: - case WINDIVERT_FILTER_FIELD_PACKET16: - case WINDIVERT_FILTER_FIELD_PACKET32: - case WINDIVERT_FILTER_FIELD_LENGTH: - case WINDIVERT_FILTER_FIELD_FRAGMENT: - pass = (addr->Layer == WINDIVERT_LAYER_NETWORK || - addr->Layer == WINDIVERT_LAYER_NETWORK_FORWARD); - break; - case WINDIVERT_FILTER_FIELD_LOCALADDR: - case WINDIVERT_FILTER_FIELD_REMOTEADDR: - case WINDIVERT_FILTER_FIELD_LOCALPORT: - case WINDIVERT_FILTER_FIELD_REMOTEPORT: - case WINDIVERT_FILTER_FIELD_PROTOCOL: - pass = (addr->Layer == WINDIVERT_LAYER_NETWORK || - addr->Layer == WINDIVERT_LAYER_FLOW || - addr->Layer == WINDIVERT_LAYER_SOCKET); - break; - case WINDIVERT_FILTER_FIELD_ENDPOINTID: - case WINDIVERT_FILTER_FIELD_PARENTENDPOINTID: - pass = (addr->Layer == WINDIVERT_LAYER_FLOW || - addr->Layer == WINDIVERT_LAYER_SOCKET); - break; - case WINDIVERT_FILTER_FIELD_PROCESSID: - pass = (addr->Layer == WINDIVERT_LAYER_FLOW || - addr->Layer == WINDIVERT_LAYER_SOCKET || - addr->Layer == WINDIVERT_LAYER_REFLECT); - break; - case WINDIVERT_FILTER_FIELD_LAYER: - case WINDIVERT_FILTER_FIELD_PRIORITY: - pass = (addr->Layer == WINDIVERT_LAYER_REFLECT); - break; - case WINDIVERT_FILTER_FIELD_IP_HDRLENGTH: - case WINDIVERT_FILTER_FIELD_IP_TOS: - case WINDIVERT_FILTER_FIELD_IP_LENGTH: - case WINDIVERT_FILTER_FIELD_IP_ID: - case WINDIVERT_FILTER_FIELD_IP_DF: - case WINDIVERT_FILTER_FIELD_IP_MF: - case WINDIVERT_FILTER_FIELD_IP_FRAGOFF: - case WINDIVERT_FILTER_FIELD_IP_TTL: - case WINDIVERT_FILTER_FIELD_IP_PROTOCOL: - case WINDIVERT_FILTER_FIELD_IP_CHECKSUM: - case WINDIVERT_FILTER_FIELD_IP_SRCADDR: - case WINDIVERT_FILTER_FIELD_IP_DSTADDR: - pass = (addr->Layer == WINDIVERT_LAYER_NETWORK || - addr->Layer == WINDIVERT_LAYER_NETWORK_FORWARD); - pass = pass && (iphdr != NULL); - break; - case WINDIVERT_FILTER_FIELD_IPV6_TRAFFICCLASS: - case WINDIVERT_FILTER_FIELD_IPV6_FLOWLABEL: - case WINDIVERT_FILTER_FIELD_IPV6_LENGTH: - case WINDIVERT_FILTER_FIELD_IPV6_NEXTHDR: - case WINDIVERT_FILTER_FIELD_IPV6_HOPLIMIT: - case WINDIVERT_FILTER_FIELD_IPV6_SRCADDR: - case WINDIVERT_FILTER_FIELD_IPV6_DSTADDR: - pass = (addr->Layer == WINDIVERT_LAYER_NETWORK || - addr->Layer == WINDIVERT_LAYER_NETWORK_FORWARD); - pass = pass && (ipv6hdr != NULL); - break; - case WINDIVERT_FILTER_FIELD_ICMP_TYPE: - case WINDIVERT_FILTER_FIELD_ICMP_CODE: - case WINDIVERT_FILTER_FIELD_ICMP_CHECKSUM: - case WINDIVERT_FILTER_FIELD_ICMP_BODY: - pass = (addr->Layer == WINDIVERT_LAYER_NETWORK || - addr->Layer == WINDIVERT_LAYER_NETWORK_FORWARD); - pass = pass && (icmphdr != NULL); - break; - case WINDIVERT_FILTER_FIELD_ICMPV6_TYPE: - case WINDIVERT_FILTER_FIELD_ICMPV6_CODE: - case WINDIVERT_FILTER_FIELD_ICMPV6_CHECKSUM: - case WINDIVERT_FILTER_FIELD_ICMPV6_BODY: - pass = (addr->Layer == WINDIVERT_LAYER_NETWORK || - addr->Layer == WINDIVERT_LAYER_NETWORK_FORWARD); - pass = pass && (icmpv6hdr != NULL); - break; - case WINDIVERT_FILTER_FIELD_TCP_SRCPORT: - case WINDIVERT_FILTER_FIELD_TCP_DSTPORT: - case WINDIVERT_FILTER_FIELD_TCP_SEQNUM: - case WINDIVERT_FILTER_FIELD_TCP_ACKNUM: - case WINDIVERT_FILTER_FIELD_TCP_HDRLENGTH: - case WINDIVERT_FILTER_FIELD_TCP_URG: - case WINDIVERT_FILTER_FIELD_TCP_ACK: - case WINDIVERT_FILTER_FIELD_TCP_PSH: - case WINDIVERT_FILTER_FIELD_TCP_RST: - case WINDIVERT_FILTER_FIELD_TCP_SYN: - case WINDIVERT_FILTER_FIELD_TCP_FIN: - case WINDIVERT_FILTER_FIELD_TCP_WINDOW: - case WINDIVERT_FILTER_FIELD_TCP_CHECKSUM: - case WINDIVERT_FILTER_FIELD_TCP_URGPTR: - case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD: - case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16: - case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32: - case WINDIVERT_FILTER_FIELD_TCP_PAYLOADLENGTH: - pass = (addr->Layer == WINDIVERT_LAYER_NETWORK || - addr->Layer == WINDIVERT_LAYER_NETWORK_FORWARD); - pass = pass && (tcphdr != NULL); - break; - case WINDIVERT_FILTER_FIELD_UDP_SRCPORT: - case WINDIVERT_FILTER_FIELD_UDP_DSTPORT: - case WINDIVERT_FILTER_FIELD_UDP_LENGTH: - case WINDIVERT_FILTER_FIELD_UDP_CHECKSUM: - case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD: - case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16: - case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32: - case WINDIVERT_FILTER_FIELD_UDP_PAYLOADLENGTH: - pass = (addr->Layer == WINDIVERT_LAYER_NETWORK || - addr->Layer == WINDIVERT_LAYER_NETWORK_FORWARD); - pass = pass && (udphdr != NULL); - break; - default: - SetLastError(ERROR_INVALID_PARAMETER); - goto WinDivertHelperEvalFilterError; - } - if (!pass) - { - pc = object[pc].failure; - continue; - } - neg = FALSE; - switch (object[pc].field) - { - case WINDIVERT_FILTER_FIELD_ZERO: - val[0] = 0; - break; - case WINDIVERT_FILTER_FIELD_EVENT: - val[0] = addr->Event; - break; - case WINDIVERT_FILTER_FIELD_LAYER: - val[0] = addr->Reflect.Layer; - break; - case WINDIVERT_FILTER_FIELD_PRIORITY: - { - neg = (addr->Reflect.Priority < 0); - val[0] = (UINT32)(neg? -addr->Reflect.Priority: - addr->Reflect.Priority); - break; - } - case WINDIVERT_FILTER_FIELD_RANDOM8: - val64.QuadPart = random64; - val[0] = ((UINT32)val64.HighPart >> 16) & 0xFF; - break; - case WINDIVERT_FILTER_FIELD_RANDOM16: - val64.QuadPart = random64; - val[0] = (UINT32)val64.HighPart & 0xFFFF; - break; - case WINDIVERT_FILTER_FIELD_RANDOM32: - val[0] = (UINT32)random64; - break; - case WINDIVERT_FILTER_FIELD_PACKET: - pass = WinDivertGetData(packet, packet_len, /*offset=*/0, - object[pc].arg[1], sizeof(data8), &data8); - val[0] = data8; - break; - case WINDIVERT_FILTER_FIELD_PACKET16: - pass = WinDivertGetData(packet, packet_len, /*offset=*/0, - object[pc].arg[1], sizeof(data16), &data16); - val[0] = ntohs(data16); - break; - case WINDIVERT_FILTER_FIELD_PACKET32: - pass = WinDivertGetData(packet, packet_len, /*offset=*/0, - object[pc].arg[1], sizeof(data32), &data32); - val[0] = ntohl(data32); - break; - case WINDIVERT_FILTER_FIELD_LENGTH: - val[0] = packet_len; - break; - case WINDIVERT_FILTER_FIELD_TIMESTAMP: - { - neg = (addr->Timestamp < 0); - val64.QuadPart = - (UINT64)(neg? -addr->Timestamp: addr->Timestamp); - big = TRUE; - val[0] = (UINT32)val64.LowPart; - val[1] = (UINT32)val64.HighPart; - val[2] = val[3] = 0; - break; - } - case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD: - case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD: - pass = WinDivertGetData(packet, packet_len, header_len, - object[pc].arg[1], sizeof(data8), &data8); - val[0] = data8; - break; - case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16: - case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16: - pass = WinDivertGetData(packet, packet_len, header_len, - object[pc].arg[1], sizeof(data16), &data16); - val[0] = ntohs(data16); - break; - case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32: - case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32: - pass = WinDivertGetData(packet, packet_len, header_len, - object[pc].arg[1], sizeof(data32), &data32); - val[0] = ntohl(data32); - break; - case WINDIVERT_FILTER_FIELD_INBOUND: - val[0] = !addr->Outbound; - break; - case WINDIVERT_FILTER_FIELD_OUTBOUND: - val[0] = addr->Outbound; - break; - case WINDIVERT_FILTER_FIELD_FRAGMENT: - val[0] = (UINT32)fragment; - break; - case WINDIVERT_FILTER_FIELD_IFIDX: - val[0] = addr->Network.IfIdx; - break; - case WINDIVERT_FILTER_FIELD_SUBIFIDX: - val[0] = addr->Network.SubIfIdx; - break; - case WINDIVERT_FILTER_FIELD_LOOPBACK: - val[0] = addr->Loopback; - break; - case WINDIVERT_FILTER_FIELD_IMPOSTOR: - val[0] = addr->Impostor; - break; - case WINDIVERT_FILTER_FIELD_IP: - val[0] = !addr->IPv6; - break; - case WINDIVERT_FILTER_FIELD_IPV6: - val[0] = addr->IPv6; - break; - case WINDIVERT_FILTER_FIELD_ICMP: - switch (addr->Layer) - { - case WINDIVERT_LAYER_NETWORK: - case WINDIVERT_LAYER_NETWORK_FORWARD: - val[0] = (UINT32)(icmphdr != NULL); - break; - case WINDIVERT_LAYER_SOCKET: - val[0] = (UINT32)(!addr->IPv6 && - addr->Socket.Protocol == IPPROTO_ICMP); - break; - case WINDIVERT_LAYER_FLOW: - val[0] = (UINT32)(!addr->IPv6 && - addr->Flow.Protocol == IPPROTO_ICMP); - break; - default: - SetLastError(ERROR_INVALID_PARAMETER); - goto WinDivertHelperEvalFilterError; - } - break; - case WINDIVERT_FILTER_FIELD_ICMPV6: - switch (addr->Layer) - { - case WINDIVERT_LAYER_NETWORK: - case WINDIVERT_LAYER_NETWORK_FORWARD: - val[0] = (UINT32)(icmpv6hdr != NULL); - break; - case WINDIVERT_LAYER_SOCKET: - val[0] = (UINT32)(addr->IPv6 && - addr->Socket.Protocol == IPPROTO_ICMPV6); - break; - case WINDIVERT_LAYER_FLOW: - val[0] = (UINT32)(addr->IPv6 && - addr->Flow.Protocol == IPPROTO_ICMPV6); - break; - default: - SetLastError(ERROR_INVALID_PARAMETER); - goto WinDivertHelperEvalFilterError; - } - break; - case WINDIVERT_FILTER_FIELD_TCP: - switch (addr->Layer) - { - case WINDIVERT_LAYER_NETWORK: - case WINDIVERT_LAYER_NETWORK_FORWARD: - val[0] = (UINT32)(tcphdr != NULL); - break; - case WINDIVERT_LAYER_SOCKET: - val[0] = (UINT32)(addr->Socket.Protocol == IPPROTO_TCP); - break; - case WINDIVERT_LAYER_FLOW: - val[0] = (UINT32)(addr->Flow.Protocol == IPPROTO_TCP); - break; - default: - SetLastError(ERROR_INVALID_PARAMETER); - goto WinDivertHelperEvalFilterError; - } - break; - case WINDIVERT_FILTER_FIELD_UDP: - switch (addr->Layer) - { - case WINDIVERT_LAYER_NETWORK: - case WINDIVERT_LAYER_NETWORK_FORWARD: - val[0] = (UINT32)(udphdr != NULL); - break; - case WINDIVERT_LAYER_SOCKET: - val[0] = (UINT32)(addr->Socket.Protocol == IPPROTO_UDP); - break; - case WINDIVERT_LAYER_FLOW: - val[0] = (UINT32)(addr->Flow.Protocol == IPPROTO_UDP); - break; - default: - SetLastError(ERROR_INVALID_PARAMETER); - goto WinDivertHelperEvalFilterError; - } - break; - case WINDIVERT_FILTER_FIELD_IP_HDRLENGTH: - val[0] = iphdr->HdrLength; - break; - case WINDIVERT_FILTER_FIELD_IP_TOS: - val[0] = iphdr->TOS; - break; - case WINDIVERT_FILTER_FIELD_IP_LENGTH: - val[0] = ntohs(iphdr->Length); - break; - case WINDIVERT_FILTER_FIELD_IP_ID: - val[0] = ntohs(iphdr->Id); - break; - case WINDIVERT_FILTER_FIELD_IP_DF: - val[0] = WINDIVERT_IPHDR_GET_DF(iphdr); - break; - case WINDIVERT_FILTER_FIELD_IP_MF: - val[0] = WINDIVERT_IPHDR_GET_MF(iphdr); - break; - case WINDIVERT_FILTER_FIELD_IP_FRAGOFF: - val[0] = ntohs(WINDIVERT_IPHDR_GET_FRAGOFF(iphdr)); - break; - case WINDIVERT_FILTER_FIELD_IP_TTL: - val[0] = iphdr->TTL; - break; - case WINDIVERT_FILTER_FIELD_IP_PROTOCOL: - val[0] = iphdr->Protocol; - break; - case WINDIVERT_FILTER_FIELD_IP_CHECKSUM: - val[0] = ntohs(iphdr->Checksum); - break; - case WINDIVERT_FILTER_FIELD_IP_SRCADDR: - val[1] = 0x0000FFFF; - val[0] = ntohl(iphdr->SrcAddr); - break; - case WINDIVERT_FILTER_FIELD_IP_DSTADDR: - val[1] = 0x0000FFFF; - val[0] = ntohl(iphdr->DstAddr); - break; - case WINDIVERT_FILTER_FIELD_IPV6_TRAFFICCLASS: - val[0] = WINDIVERT_IPV6HDR_GET_TRAFFICCLASS(ipv6hdr); - break; - case WINDIVERT_FILTER_FIELD_IPV6_FLOWLABEL: - val[0] = ntohl(WINDIVERT_IPV6HDR_GET_FLOWLABEL(ipv6hdr)); - break; - case WINDIVERT_FILTER_FIELD_IPV6_LENGTH: - val[0] = ntohs(ipv6hdr->Length); - break; - case WINDIVERT_FILTER_FIELD_IPV6_NEXTHDR: - val[0] = ipv6hdr->NextHdr; - break; - case WINDIVERT_FILTER_FIELD_IPV6_HOPLIMIT: - val[0] = ipv6hdr->HopLimit; - break; - case WINDIVERT_FILTER_FIELD_IPV6_SRCADDR: - big = TRUE; - val[3] = ntohl(ipv6hdr->SrcAddr[0]); - val[2] = ntohl(ipv6hdr->SrcAddr[1]); - val[1] = ntohl(ipv6hdr->SrcAddr[2]); - val[0] = ntohl(ipv6hdr->SrcAddr[3]); - break; - case WINDIVERT_FILTER_FIELD_IPV6_DSTADDR: - big = TRUE; - val[3] = ntohl(ipv6hdr->DstAddr[0]); - val[2] = ntohl(ipv6hdr->DstAddr[1]); - val[1] = ntohl(ipv6hdr->DstAddr[2]); - val[0] = ntohl(ipv6hdr->DstAddr[3]); - break; - case WINDIVERT_FILTER_FIELD_ICMP_TYPE: - val[0] = icmphdr->Type; - break; - case WINDIVERT_FILTER_FIELD_ICMP_CODE: - val[0] = icmphdr->Code; - break; - case WINDIVERT_FILTER_FIELD_ICMP_CHECKSUM: - val[0] = ntohs(icmphdr->Checksum); - break; - case WINDIVERT_FILTER_FIELD_ICMP_BODY: - val[0] = ntohl(icmphdr->Body); - break; - case WINDIVERT_FILTER_FIELD_ICMPV6_TYPE: - val[0] = icmpv6hdr->Type; - break; - case WINDIVERT_FILTER_FIELD_ICMPV6_CODE: - val[0] = icmpv6hdr->Code; - break; - case WINDIVERT_FILTER_FIELD_ICMPV6_CHECKSUM: - val[0] = ntohs(icmpv6hdr->Checksum); - break; - case WINDIVERT_FILTER_FIELD_ICMPV6_BODY: - val[0] = ntohl(icmpv6hdr->Body); - break; - case WINDIVERT_FILTER_FIELD_TCP_SRCPORT: - val[0] = ntohs(tcphdr->SrcPort); - break; - case WINDIVERT_FILTER_FIELD_TCP_DSTPORT: - val[0] = ntohs(tcphdr->DstPort); - break; - case WINDIVERT_FILTER_FIELD_TCP_SEQNUM: - val[0] = ntohl(tcphdr->SeqNum); - break; - case WINDIVERT_FILTER_FIELD_TCP_ACKNUM: - val[0] = ntohl(tcphdr->AckNum); - break; - case WINDIVERT_FILTER_FIELD_TCP_HDRLENGTH: - val[0] = tcphdr->HdrLength; - break; - case WINDIVERT_FILTER_FIELD_TCP_URG: - val[0] = tcphdr->Urg; - break; - case WINDIVERT_FILTER_FIELD_TCP_ACK: - val[0] = tcphdr->Ack; - break; - case WINDIVERT_FILTER_FIELD_TCP_PSH: - val[0] = tcphdr->Psh; - break; - case WINDIVERT_FILTER_FIELD_TCP_RST: - val[0] = tcphdr->Rst; - break; - case WINDIVERT_FILTER_FIELD_TCP_SYN: - val[0] = tcphdr->Syn; - break; - case WINDIVERT_FILTER_FIELD_TCP_FIN: - val[0] = tcphdr->Fin; - break; - case WINDIVERT_FILTER_FIELD_TCP_WINDOW: - val[0] = ntohs(tcphdr->Window); - break; - case WINDIVERT_FILTER_FIELD_TCP_CHECKSUM: - val[0] = ntohs(tcphdr->Checksum); - break; - case WINDIVERT_FILTER_FIELD_TCP_URGPTR: - val[0] = ntohs(tcphdr->UrgPtr); - break; - case WINDIVERT_FILTER_FIELD_TCP_PAYLOADLENGTH: - val[0] = payload_len; - break; - case WINDIVERT_FILTER_FIELD_UDP_SRCPORT: - val[0] = ntohs(udphdr->SrcPort); - break; - case WINDIVERT_FILTER_FIELD_UDP_DSTPORT: - val[0] = ntohs(udphdr->DstPort); - break; - case WINDIVERT_FILTER_FIELD_UDP_LENGTH: - val[0] = ntohs(udphdr->Length); - break; - case WINDIVERT_FILTER_FIELD_UDP_CHECKSUM: - val[0] = ntohs(udphdr->Checksum); - break; - case WINDIVERT_FILTER_FIELD_UDP_PAYLOADLENGTH: - val[0] = payload_len; - break; - case WINDIVERT_FILTER_FIELD_LOCALADDR: - big = TRUE; - switch (addr->Layer) - { - case WINDIVERT_LAYER_NETWORK: - if (!addr->IPv6) - { - val[3] = val[2] = 0; - val[1] = 0x0000FFFF; - val[0] = ntohl((addr->Outbound? iphdr->SrcAddr: - iphdr->DstAddr)); - } - else if (addr->Outbound) - { - val[3] = ntohl(ipv6hdr->SrcAddr[0]); - val[2] = ntohl(ipv6hdr->SrcAddr[1]); - val[1] = ntohl(ipv6hdr->SrcAddr[2]); - val[0] = ntohl(ipv6hdr->SrcAddr[3]); - } - else - { - val[3] = ntohl(ipv6hdr->DstAddr[0]); - val[2] = ntohl(ipv6hdr->DstAddr[1]); - val[1] = ntohl(ipv6hdr->DstAddr[2]); - val[0] = ntohl(ipv6hdr->DstAddr[3]); - } - break; - case WINDIVERT_LAYER_FLOW: - val[0] = addr->Flow.LocalAddr[0]; - val[1] = addr->Flow.LocalAddr[1]; - val[2] = addr->Flow.LocalAddr[2]; - val[3] = addr->Flow.LocalAddr[3]; - break; - case WINDIVERT_LAYER_SOCKET: - val[0] = addr->Socket.LocalAddr[0]; - val[1] = addr->Socket.LocalAddr[1]; - val[2] = addr->Socket.LocalAddr[2]; - val[3] = addr->Socket.LocalAddr[3]; - break; - default: - SetLastError(ERROR_INVALID_PARAMETER); - goto WinDivertHelperEvalFilterError; - } - break; - case WINDIVERT_FILTER_FIELD_REMOTEADDR: - big = TRUE; - switch (addr->Layer) - { - case WINDIVERT_LAYER_NETWORK: - if (!addr->IPv6) - { - val[3] = val[2] = 0; - val[1] = 0x0000FFFF; - val[0] = ntohl((!addr->Outbound? iphdr->SrcAddr: - iphdr->DstAddr)); - } - else if (!addr->Outbound) - { - val[3] = ntohl(ipv6hdr->SrcAddr[0]); - val[2] = ntohl(ipv6hdr->SrcAddr[1]); - val[1] = ntohl(ipv6hdr->SrcAddr[2]); - val[0] = ntohl(ipv6hdr->SrcAddr[3]); - } - else - { - val[3] = ntohl(ipv6hdr->DstAddr[0]); - val[2] = ntohl(ipv6hdr->DstAddr[1]); - val[1] = ntohl(ipv6hdr->DstAddr[2]); - val[0] = ntohl(ipv6hdr->DstAddr[3]); - } - break; - case WINDIVERT_LAYER_FLOW: - val[0] = addr->Flow.RemoteAddr[0]; - val[1] = addr->Flow.RemoteAddr[1]; - val[2] = addr->Flow.RemoteAddr[2]; - val[3] = addr->Flow.RemoteAddr[3]; - break; - case WINDIVERT_LAYER_SOCKET: - val[0] = addr->Socket.RemoteAddr[0]; - val[1] = addr->Socket.RemoteAddr[1]; - val[2] = addr->Socket.RemoteAddr[2]; - val[3] = addr->Socket.RemoteAddr[3]; - break; - default: - SetLastError(ERROR_INVALID_PARAMETER); - goto WinDivertHelperEvalFilterError; - } - break; - case WINDIVERT_FILTER_FIELD_LOCALPORT: - switch (addr->Layer) - { - case WINDIVERT_LAYER_NETWORK: - if (tcphdr != NULL) - { - val[0] = ntohs((addr->Outbound? tcphdr->SrcPort: - tcphdr->DstPort)); - } - else if (udphdr != NULL) - { - val[0] = ntohs((addr->Outbound? udphdr->SrcPort: - udphdr->DstPort)); - } - else if (icmphdr != NULL) - { - val[0] = (addr->Outbound? icmphdr->Type: 0); - } - else if (icmpv6hdr != NULL) - { - val[0] = (addr->Outbound? icmpv6hdr->Type: 0); - } - else - { - val[0] = 0; - } - break; - case WINDIVERT_LAYER_FLOW: - val[0] = addr->Flow.LocalPort; - break; - case WINDIVERT_LAYER_SOCKET: - val[0] = addr->Socket.LocalPort; - break; - default: - SetLastError(ERROR_INVALID_PARAMETER); - goto WinDivertHelperEvalFilterError; - } - break; - case WINDIVERT_FILTER_FIELD_REMOTEPORT: - switch (addr->Layer) - { - case WINDIVERT_LAYER_NETWORK: - if (tcphdr != NULL) - { - val[0] = ntohs((!addr->Outbound? tcphdr->SrcPort: - tcphdr->DstPort)); - } - else if (udphdr != NULL) - { - val[0] = ntohs((!addr->Outbound? udphdr->SrcPort: - udphdr->DstPort)); - } - else if (icmphdr != NULL) - { - val[0] = (!addr->Outbound? icmphdr->Type: 0); - } - else if (icmpv6hdr != NULL) - { - val[0] = (!addr->Outbound? icmpv6hdr->Type: 0); - } - else - { - val[0] = 0; - } - break; - case WINDIVERT_LAYER_FLOW: - val[0] = addr->Flow.RemotePort; - break; - case WINDIVERT_LAYER_SOCKET: - val[0] = addr->Socket.RemotePort; - break; - default: - SetLastError(ERROR_INVALID_PARAMETER); - goto WinDivertHelperEvalFilterError; - } - break; - case WINDIVERT_FILTER_FIELD_PROTOCOL: - switch (addr->Layer) - { - case WINDIVERT_LAYER_NETWORK: - val[0] = protocol; - break; - case WINDIVERT_LAYER_FLOW: - val[0] = addr->Flow.Protocol; - break; - case WINDIVERT_LAYER_SOCKET: - val[0] = addr->Socket.Protocol; - break; - default: - SetLastError(ERROR_INVALID_PARAMETER); - goto WinDivertHelperEvalFilterError; - } - break; - case WINDIVERT_FILTER_FIELD_ENDPOINTID: - big = TRUE; - val[3] = val[2] = 0; - switch (addr->Layer) - { - case WINDIVERT_LAYER_FLOW: - val64.QuadPart = addr->Flow.EndpointId; - val[0] = (UINT32)val64.LowPart; - val[1] = (UINT32)val64.HighPart; - break; - case WINDIVERT_LAYER_SOCKET: - val64.QuadPart = addr->Socket.EndpointId; - val[0] = (UINT32)val64.LowPart; - val[1] = (UINT32)val64.HighPart; - break; - default: - SetLastError(ERROR_INVALID_PARAMETER); - goto WinDivertHelperEvalFilterError; - } - break; - case WINDIVERT_FILTER_FIELD_PARENTENDPOINTID: - big = TRUE; - val[3] = val[2] = 0; - switch (addr->Layer) - { - case WINDIVERT_LAYER_FLOW: - val64.QuadPart = addr->Flow.ParentEndpointId; - val[0] = (UINT32)val64.LowPart; - val[1] = (UINT32)val64.HighPart; - break; - case WINDIVERT_LAYER_SOCKET: - val64.QuadPart = addr->Socket.ParentEndpointId; - val[0] = (UINT32)val64.LowPart; - val[1] = (UINT32)val64.HighPart; - break; - default: - SetLastError(ERROR_INVALID_PARAMETER); - goto WinDivertHelperEvalFilterError; - } - break; - case WINDIVERT_FILTER_FIELD_PROCESSID: - switch (addr->Layer) - { - case WINDIVERT_LAYER_FLOW: - val[0] = addr->Flow.ProcessId; - break; - case WINDIVERT_LAYER_SOCKET: - val[0] = addr->Socket.ProcessId; - break; - case WINDIVERT_LAYER_REFLECT: - val[0] = addr->Reflect.ProcessId; - break; - default: - SetLastError(ERROR_INVALID_PARAMETER); - goto WinDivertHelperEvalFilterError; - } - break; - default: - SetLastError(ERROR_INVALID_PARAMETER); - goto WinDivertHelperEvalFilterError; - } - if (!pass) - { - pc = object[pc].failure; - continue; - } - cmp = WinDivertCompare128(neg, val, (object[pc].neg? TRUE: FALSE), - object[pc].arg, big); - switch (object[pc].test) - { - case WINDIVERT_FILTER_TEST_EQ: - pass = (cmp == 0); - break; - case WINDIVERT_FILTER_TEST_NEQ: - pass = (cmp != 0); - break; - case WINDIVERT_FILTER_TEST_LT: - pass = (cmp < 0); - break; - case WINDIVERT_FILTER_TEST_LEQ: - pass = (cmp <= 0); - break; - case WINDIVERT_FILTER_TEST_GT: - pass = (cmp > 0); - break; - case WINDIVERT_FILTER_TEST_GEQ: - pass = (cmp >= 0); - break; - default: - SetLastError(ERROR_INVALID_PARAMETER); - goto WinDivertHelperEvalFilterError; - } - pc = (pass? object[pc].success: object[pc].failure); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + else if (result == 0) + { + SetLastError(0); + return FALSE; + } + else + { + return TRUE; } WinDivertHelperEvalFilterError: diff --git a/dll/windivert_shared.c b/dll/windivert_shared.c index 8029125..986f43b 100644 --- a/dll/windivert_shared.c +++ b/dll/windivert_shared.c @@ -59,6 +59,42 @@ #define ntohl(x) BYTESWAP32(x) #define htonl(x) BYTESWAP32(x) +/* + * Layer flags shorthand. + */ +#define WINDIVERT_LAYER_FLAG_NETWORK (1 << WINDIVERT_LAYER_NETWORK) +#define WINDIVERT_LAYER_FLAG_NETWORK_FORWARD \ + (1 << WINDIVERT_LAYER_NETWORK_FORWARD) +#define WINDIVERT_LAYER_FLAG_FLOW (1 << WINDIVERT_LAYER_FLOW) +#define WINDIVERT_LAYER_FLAG_SOCKET (1 << WINDIVERT_LAYER_SOCKET) +#define WINDIVERT_LAYER_FLAG_REFLECT (1 << WINDIVERT_LAYER_REFLECT) +#define LNMFSR (WINDIVERT_LAYER_FLAG_NETWORK | \ + WINDIVERT_LAYER_FLAG_NETWORK_FORWARD | \ + WINDIVERT_LAYER_FLAG_FLOW | \ + WINDIVERT_LAYER_FLAG_SOCKET | \ + WINDIVERT_LAYER_FLAG_REFLECT) +#define LNMFS_ (WINDIVERT_LAYER_FLAG_NETWORK | \ + WINDIVERT_LAYER_FLAG_NETWORK_FORWARD | \ + WINDIVERT_LAYER_FLAG_FLOW | \ + WINDIVERT_LAYER_FLAG_SOCKET) +#define L__F_R (WINDIVERT_LAYER_FLAG_FLOW | \ + WINDIVERT_LAYER_FLAG_REFLECT) +#define LN_FS_ (WINDIVERT_LAYER_FLAG_NETWORK | \ + WINDIVERT_LAYER_FLAG_FLOW | \ + WINDIVERT_LAYER_FLAG_SOCKET) +#define L__FS_ (WINDIVERT_LAYER_FLAG_FLOW | \ + WINDIVERT_LAYER_FLAG_SOCKET) +#define L___SR (WINDIVERT_LAYER_FLAG_SOCKET | \ + WINDIVERT_LAYER_FLAG_REFLECT) +#define L__FSR (WINDIVERT_LAYER_FLAG_FLOW | \ + WINDIVERT_LAYER_FLAG_SOCKET | \ + WINDIVERT_LAYER_FLAG_REFLECT) +#define LNM___ (WINDIVERT_LAYER_FLAG_NETWORK | \ + WINDIVERT_LAYER_FLAG_NETWORK_FORWARD) +#define L__F__ WINDIVERT_LAYER_FLAG_FLOW +#define L___S_ WINDIVERT_LAYER_FLAG_SOCKET +#define L____R WINDIVERT_LAYER_FLAG_REFLECT + #if defined(WIN32) && defined(_MSC_VER) #pragma intrinsic(__emulu) static UINT64 WinDivertMul64(UINT64 a, UINT64 b) @@ -731,22 +767,22 @@ extern BOOL WinDivertHelperDecrementTTL(VOID *packet, UINT packetLen) ip_header = (PWINDIVERT_IPHDR)packet; switch (ip_header->Version) { - case 4: - if (ip_header->TTL <= 1) - { - return FALSE; - } - ip_header->TTL--; - - // Incremental checksum update: - if (ip_header->Checksum >= 0xFFFE) - { - ip_header->Checksum -= 0xFFFE; - } - else - { - ip_header->Checksum += 1; - } + case 4: + if (ip_header->TTL <= 1) + { + return FALSE; + } + ip_header->TTL--; + + // Incremental checksum update: + if (ip_header->Checksum >= 0xFFFE) + { + ip_header->Checksum -= 0xFFFE; + } + else + { + ip_header->Checksum += 1; + } return TRUE; case 6: @@ -767,3 +803,936 @@ extern BOOL WinDivertHelperDecrementTTL(VOID *packet, UINT packetLen) } } +/* + * Validate a WinDivert field for given layer. + */ +static BOOL WinDivertValidateField(WINDIVERT_LAYER layer, UINT32 field) +{ + static const UINT8 flags[] = + { + LNMFSR, /* WINDIVERT_FILTER_FIELD_ZERO */ + LN_FS_, /* WINDIVERT_FILTER_FIELD_INBOUND */ + LN_FS_, /* WINDIVERT_FILTER_FIELD_OUTBOUND */ + LNM___, /* WINDIVERT_FILTER_FIELD_IFIDX */ + LNM___, /* WINDIVERT_FILTER_FIELD_SUBIFIDX */ + LNMFS_, /* WINDIVERT_FILTER_FIELD_IP */ + LNMFS_, /* WINDIVERT_FILTER_FIELD_IPV6 */ + LNMFS_, /* WINDIVERT_FILTER_FIELD_ICMP */ + LNMFS_, /* WINDIVERT_FILTER_FIELD_TCP */ + LNMFS_, /* WINDIVERT_FILTER_FIELD_UDP */ + LNMFS_, /* WINDIVERT_FILTER_FIELD_ICMPV6 */ + LNM___, /* WINDIVERT_FILTER_FIELD_IP_HDRLENGTH */ + LNM___, /* WINDIVERT_FILTER_FIELD_IP_TOS */ + LNM___, /* WINDIVERT_FILTER_FIELD_IP_LENGTH */ + LNM___, /* WINDIVERT_FILTER_FIELD_IP_ID */ + LNM___, /* WINDIVERT_FILTER_FIELD_IP_DF */ + LNM___, /* WINDIVERT_FILTER_FIELD_IP_MF */ + LNM___, /* WINDIVERT_FILTER_FIELD_IP_FRAGOFF */ + LNM___, /* WINDIVERT_FILTER_FIELD_IP_TTL */ + LNM___, /* WINDIVERT_FILTER_FIELD_IP_PROTOCOL */ + LNM___, /* WINDIVERT_FILTER_FIELD_IP_CHECKSUM */ + LNM___, /* WINDIVERT_FILTER_FIELD_IP_SRCADDR */ + LNM___, /* WINDIVERT_FILTER_FIELD_IP_DSTADDR */ + LNM___, /* WINDIVERT_FILTER_FIELD_IPV6_TRAFFICCLASS */ + LNM___, /* WINDIVERT_FILTER_FIELD_IPV6_FLOWLABEL */ + LNM___, /* WINDIVERT_FILTER_FIELD_IPV6_LENGTH */ + LNM___, /* WINDIVERT_FILTER_FIELD_IPV6_NEXTHDR */ + LNM___, /* WINDIVERT_FILTER_FIELD_IPV6_HOPLIMIT */ + LNM___, /* WINDIVERT_FILTER_FIELD_IPV6_SRCADDR */ + LNM___, /* WINDIVERT_FILTER_FIELD_IPV6_DSTADDR */ + LNM___, /* WINDIVERT_FILTER_FIELD_ICMP_TYPE */ + LNM___, /* WINDIVERT_FILTER_FIELD_ICMP_CODE */ + LNM___, /* WINDIVERT_FILTER_FIELD_ICMP_CHECKSUM */ + LNM___, /* WINDIVERT_FILTER_FIELD_ICMP_BODY */ + LNM___, /* WINDIVERT_FILTER_FIELD_ICMPV6_TYPE */ + LNM___, /* WINDIVERT_FILTER_FIELD_ICMPV6_CODE */ + LNM___, /* WINDIVERT_FILTER_FIELD_ICMPV6_CHECKSUM */ + LNM___, /* WINDIVERT_FILTER_FIELD_ICMPV6_BODY */ + LNM___, /* WINDIVERT_FILTER_FIELD_TCP_SRCPORT */ + LNM___, /* WINDIVERT_FILTER_FIELD_TCP_DSTPORT */ + LNM___, /* WINDIVERT_FILTER_FIELD_TCP_SEQNUM */ + LNM___, /* WINDIVERT_FILTER_FIELD_TCP_ACKNUM */ + LNM___, /* WINDIVERT_FILTER_FIELD_TCP_HDRLENGTH */ + LNM___, /* WINDIVERT_FILTER_FIELD_TCP_URG */ + LNM___, /* WINDIVERT_FILTER_FIELD_TCP_ACK */ + LNM___, /* WINDIVERT_FILTER_FIELD_TCP_PSH */ + LNM___, /* WINDIVERT_FILTER_FIELD_TCP_RST */ + LNM___, /* WINDIVERT_FILTER_FIELD_TCP_SYN */ + LNM___, /* WINDIVERT_FILTER_FIELD_TCP_FIN */ + LNM___, /* WINDIVERT_FILTER_FIELD_TCP_WINDOW */ + LNM___, /* WINDIVERT_FILTER_FIELD_TCP_CHECKSUM */ + LNM___, /* WINDIVERT_FILTER_FIELD_TCP_URGPTR */ + LNM___, /* WINDIVERT_FILTER_FIELD_TCP_PAYLOADLENGTH */ + LNM___, /* WINDIVERT_FILTER_FIELD_UDP_SRCPORT */ + LNM___, /* WINDIVERT_FILTER_FIELD_UDP_DSTPORT */ + LNM___, /* WINDIVERT_FILTER_FIELD_UDP_LENGTH */ + LNM___, /* WINDIVERT_FILTER_FIELD_UDP_CHECKSUM */ + LNM___, /* WINDIVERT_FILTER_FIELD_UDP_PAYLOADLENGTH */ + LN_FS_, /* WINDIVERT_FILTER_FIELD_LOOPBACK */ + LNM___, /* WINDIVERT_FILTER_FIELD_IMPOSTOR */ + L__FSR, /* WINDIVERT_FILTER_FIELD_PROCESSID */ + LN_FS_, /* WINDIVERT_FILTER_FIELD_LOCALADDR */ + LN_FS_, /* WINDIVERT_FILTER_FIELD_REMOTEADDR */ + LN_FS_, /* WINDIVERT_FILTER_FIELD_LOCALPORT */ + LN_FS_, /* WINDIVERT_FILTER_FIELD_REMOTEPORT */ + LN_FS_, /* WINDIVERT_FILTER_FIELD_PROTOCOL */ + L__FS_, /* WINDIVERT_FILTER_FIELD_ENDPOINTID */ + L__FS_, /* WINDIVERT_FILTER_FIELD_PARENTENDPOINTID */ + L____R, /* WINDIVERT_FILTER_FIELD_LAYER */ + L____R, /* WINDIVERT_FILTER_FIELD_PRIORITY */ + LNMFSR, /* WINDIVERT_FILTER_FIELD_EVENT */ + LNM___, /* WINDIVERT_FILTER_FIELD_PACKET */ + LNM___, /* WINDIVERT_FILTER_FIELD_PACKET16 */ + LNM___, /* WINDIVERT_FILTER_FIELD_PACKET32 */ + LNM___, /* WINDIVERT_FILTER_FIELD_TCP_PAYLOAD */ + LNM___, /* WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16 */ + LNM___, /* WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32 */ + LNM___, /* WINDIVERT_FILTER_FIELD_UDP_PAYLOAD */ + LNM___, /* WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16 */ + LNM___, /* WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32 */ + LNM___, /* WINDIVERT_FILTER_FIELD_LENGTH */ + LNMFSR, /* WINDIVERT_FILTER_FIELD_TIMESTAMP */ + LNM___, /* WINDIVERT_FILTER_FIELD_RANDOM8 */ + LNM___, /* WINDIVERT_FILTER_FIELD_RANDOM16 */ + LNM___, /* WINDIVERT_FILTER_FIELD_RANDOM32 */ + LNM___, /* WINDIVERT_FILTER_FIELD_FRAGMENT */ + }; + + if (field > WINDIVERT_FILTER_FIELD_MAX) + { + return FALSE; + } + return ((flags[field] & (1 << layer)) != 0); +} + +/* + * Big number comparison. + */ +static int WinDivertCompare128(BOOL neg_a, const UINT32 *a, BOOL neg_b, + const UINT32 *b, BOOL big) +{ + int neg; + if (neg_a && !neg_b) + { + return -1; + } + if (!neg_a && neg_b) + { + return 1; + } + neg = (neg_a? -1: 1); + if (big) + { + if (a[3] < b[3]) + { + return -neg; + } + if (a[3] > b[3]) + { + return neg; + } + if (a[2] < b[2]) + { + return -neg; + } + if (a[2] > b[2]) + { + return neg; + } + if (a[1] < b[1]) + { + return -neg; + } + if (a[1] > b[1]) + { + return neg; + } + } + if (a[0] < b[0]) + { + return -neg; + } + if (a[0] > b[0]) + { + return neg; + } + return 0; +} + +/* + * WinDivert filter execute function. + */ +static WINDIVERT_INLINE int WinDivertExecuteFilter( + const WINDIVERT_FILTER *filter, + WINDIVERT_LAYER layer, + LONGLONG timestamp, + WINDIVERT_EVENT event, + BOOL ipv4, + BOOL outbound, + BOOL loopback, + BOOL impostor, + BOOL fragment, + const WINDIVERT_DATA_NETWORK *network_data, + const WINDIVERT_DATA_FLOW *flow_data, + const WINDIVERT_DATA_SOCKET *socket_data, + const WINDIVERT_DATA_REFLECT *reflect_data, + const WINDIVERT_IPHDR *ip_header, + const WINDIVERT_IPV6HDR *ipv6_header, + const WINDIVERT_ICMPHDR *icmp_header, + const WINDIVERT_ICMPV6HDR *icmpv6_header, + const WINDIVERT_TCPHDR *tcp_header, + const WINDIVERT_UDPHDR *udp_header, + UINT8 protocol, + const void *packet, + UINT packet_len, + UINT header_len, + UINT payload_len) +{ + UINT64 random64 = 0; + UINT16 ip, ttl; + UINT8 data8; + UINT16 data16; + UINT32 data32; + ULARGE_INTEGER val64; + + ip = 0; + ttl = WINDIVERT_FILTER_MAXLEN+1; + while (ttl-- != 0) + { + BOOL result = TRUE; + BOOL big = FALSE; + BOOL neg = FALSE; + int cmp; + UINT32 val[4]; + + if (!WinDivertValidateField(layer, filter[ip].field)) + { + return -1; + } + switch (filter[ip].field) + { + case WINDIVERT_FILTER_FIELD_RANDOM8: + case WINDIVERT_FILTER_FIELD_RANDOM16: + case WINDIVERT_FILTER_FIELD_RANDOM32: + if (random64 == 0) + { + random64 = WinDivertHashPacket((UINT64)timestamp, + ip_header, ipv6_header, icmp_header, icmpv6_header, + tcp_header, udp_header); + random64 |= 0xFF00000000000000ull; // Make non-zero. + } + break; + case WINDIVERT_FILTER_FIELD_IP_HDRLENGTH: + case WINDIVERT_FILTER_FIELD_IP_TOS: + case WINDIVERT_FILTER_FIELD_IP_LENGTH: + case WINDIVERT_FILTER_FIELD_IP_ID: + case WINDIVERT_FILTER_FIELD_IP_DF: + case WINDIVERT_FILTER_FIELD_IP_MF: + case WINDIVERT_FILTER_FIELD_IP_FRAGOFF: + case WINDIVERT_FILTER_FIELD_IP_TTL: + case WINDIVERT_FILTER_FIELD_IP_PROTOCOL: + case WINDIVERT_FILTER_FIELD_IP_CHECKSUM: + case WINDIVERT_FILTER_FIELD_IP_SRCADDR: + case WINDIVERT_FILTER_FIELD_IP_DSTADDR: + result = (ip_header != NULL); + break; + case WINDIVERT_FILTER_FIELD_IPV6_TRAFFICCLASS: + case WINDIVERT_FILTER_FIELD_IPV6_FLOWLABEL: + case WINDIVERT_FILTER_FIELD_IPV6_LENGTH: + case WINDIVERT_FILTER_FIELD_IPV6_NEXTHDR: + case WINDIVERT_FILTER_FIELD_IPV6_HOPLIMIT: + case WINDIVERT_FILTER_FIELD_IPV6_SRCADDR: + case WINDIVERT_FILTER_FIELD_IPV6_DSTADDR: + result = (ipv6_header != NULL); + break; + case WINDIVERT_FILTER_FIELD_ICMP_TYPE: + case WINDIVERT_FILTER_FIELD_ICMP_CODE: + case WINDIVERT_FILTER_FIELD_ICMP_CHECKSUM: + case WINDIVERT_FILTER_FIELD_ICMP_BODY: + result = (icmp_header != NULL); + break; + case WINDIVERT_FILTER_FIELD_ICMPV6_TYPE: + case WINDIVERT_FILTER_FIELD_ICMPV6_CODE: + case WINDIVERT_FILTER_FIELD_ICMPV6_CHECKSUM: + case WINDIVERT_FILTER_FIELD_ICMPV6_BODY: + result = (icmpv6_header != NULL); + break; + case WINDIVERT_FILTER_FIELD_TCP_SRCPORT: + case WINDIVERT_FILTER_FIELD_TCP_DSTPORT: + case WINDIVERT_FILTER_FIELD_TCP_SEQNUM: + case WINDIVERT_FILTER_FIELD_TCP_ACKNUM: + case WINDIVERT_FILTER_FIELD_TCP_HDRLENGTH: + case WINDIVERT_FILTER_FIELD_TCP_URG: + case WINDIVERT_FILTER_FIELD_TCP_ACK: + case WINDIVERT_FILTER_FIELD_TCP_PSH: + case WINDIVERT_FILTER_FIELD_TCP_RST: + case WINDIVERT_FILTER_FIELD_TCP_SYN: + case WINDIVERT_FILTER_FIELD_TCP_FIN: + case WINDIVERT_FILTER_FIELD_TCP_WINDOW: + case WINDIVERT_FILTER_FIELD_TCP_CHECKSUM: + case WINDIVERT_FILTER_FIELD_TCP_URGPTR: + case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD: + case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16: + case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32: + case WINDIVERT_FILTER_FIELD_TCP_PAYLOADLENGTH: + result = (tcp_header != NULL); + break; + case WINDIVERT_FILTER_FIELD_UDP_SRCPORT: + case WINDIVERT_FILTER_FIELD_UDP_DSTPORT: + case WINDIVERT_FILTER_FIELD_UDP_LENGTH: + case WINDIVERT_FILTER_FIELD_UDP_CHECKSUM: + case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD: + case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16: + case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32: + case WINDIVERT_FILTER_FIELD_UDP_PAYLOADLENGTH: + result = (udp_header != NULL); + break; + default: + break; + } + + if (result) + { + switch (filter[ip].field) + { + case WINDIVERT_FILTER_FIELD_ZERO: + val[0] = 0; + break; + case WINDIVERT_FILTER_FIELD_EVENT: + val[0] = (UINT32)event; + break; + case WINDIVERT_FILTER_FIELD_LENGTH: + val[0] = (UINT32)packet_len; + break; + case WINDIVERT_FILTER_FIELD_TIMESTAMP: + big = TRUE; + neg = (timestamp < 0); + val64.QuadPart = (UINT64)(neg? -timestamp: timestamp); + val[0] = (UINT32)val64.LowPart; + val[1] = (UINT32)val64.HighPart; + val[2] = val[3] = 0; + break; + case WINDIVERT_FILTER_FIELD_RANDOM8: + val64.QuadPart = random64; + val[0] = ((UINT32)val64.HighPart >> 16) & 0xFF; + break; + case WINDIVERT_FILTER_FIELD_RANDOM16: + val64.QuadPart = random64; + val[0] = (UINT32)val64.HighPart & 0xFFFF; + break; + case WINDIVERT_FILTER_FIELD_RANDOM32: + val[0] = (UINT32)random64; + break; + case WINDIVERT_FILTER_FIELD_PACKET: + result = WINDIVERT_GET_DATA(packet, packet_len, 0, + packet_len, (INT)filter[ip].arg[1], &data8, + sizeof(data8)); + val[0] = (UINT32)data8; + break; + case WINDIVERT_FILTER_FIELD_PACKET16: + result = WINDIVERT_GET_DATA(packet, packet_len, 0, + packet_len, (INT)filter[ip].arg[1], &data16, + sizeof(data16)); + val[0] = (UINT32)ntohs(data16); + break; + case WINDIVERT_FILTER_FIELD_PACKET32: + result = WINDIVERT_GET_DATA(packet, packet_len, 0, + packet_len, (INT)filter[ip].arg[1], &data32, + sizeof(data32)); + val[0] = ntohl(data32); + break; + case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD: + case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD: + result = WINDIVERT_GET_DATA(packet, packet_len, + header_len, header_len + payload_len, + (INT)filter[ip].arg[1], &data8, sizeof(data8)); + val[0] = (UINT32)data8; + break; + case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16: + case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16: + result = WINDIVERT_GET_DATA(packet, packet_len, + header_len, header_len + payload_len, + (INT)filter[ip].arg[1], &data16, sizeof(data16)); + val[0] = (UINT32)ntohs(data16); + break; + case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32: + case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32: + result = WINDIVERT_GET_DATA(packet, packet_len, + header_len, header_len + payload_len, + (INT)filter[ip].arg[1], &data32, sizeof(data32)); + val[0] = ntohl(data32); + break; + case WINDIVERT_FILTER_FIELD_INBOUND: + val[0] = (UINT32)!outbound; + break; + case WINDIVERT_FILTER_FIELD_OUTBOUND: + val[0] = (UINT32)outbound; + break; + case WINDIVERT_FILTER_FIELD_FRAGMENT: + val[0] = (UINT32)fragment; + break; + case WINDIVERT_FILTER_FIELD_IFIDX: + switch (layer) + { + case WINDIVERT_LAYER_NETWORK: + case WINDIVERT_LAYER_NETWORK_FORWARD: + val[0] = network_data->IfIdx; + break; + default: + return -1; + } + break; + case WINDIVERT_FILTER_FIELD_SUBIFIDX: + val[0] = network_data->SubIfIdx; + break; + case WINDIVERT_FILTER_FIELD_LOOPBACK: + val[0] = (UINT32)loopback; + break; + case WINDIVERT_FILTER_FIELD_IMPOSTOR: + val[0] = (UINT32)impostor; + break; + case WINDIVERT_FILTER_FIELD_IP: + val[0] = (UINT32)(ip_header != NULL); + break; + case WINDIVERT_FILTER_FIELD_IPV6: + val[0] = (UINT32)(ipv6_header != NULL); + break; + case WINDIVERT_FILTER_FIELD_ICMP: + switch (layer) + { + case WINDIVERT_LAYER_NETWORK: + case WINDIVERT_LAYER_NETWORK_FORWARD: + val[0] = (UINT32)(icmp_header != NULL); + break; + case WINDIVERT_LAYER_SOCKET: + val[0] = (UINT32)(ipv4 && + socket_data->Protocol == IPPROTO_ICMP); + break; + case WINDIVERT_LAYER_FLOW: + val[0] = (UINT32)(ipv4 && + flow_data->Protocol == IPPROTO_ICMP); + break; + default: + return -1; + } + break; + case WINDIVERT_FILTER_FIELD_ICMPV6: + switch (layer) + { + case WINDIVERT_LAYER_NETWORK: + case WINDIVERT_LAYER_NETWORK_FORWARD: + val[0] = (UINT32)(icmpv6_header != NULL); + break; + case WINDIVERT_LAYER_SOCKET: + val[0] = (UINT32)(!ipv4 && + socket_data->Protocol == IPPROTO_ICMPV6); + break; + case WINDIVERT_LAYER_FLOW: + val[0] = (UINT32)(!ipv4 && + flow_data->Protocol == IPPROTO_ICMPV6); + break; + default: + return -1; + } + break; + case WINDIVERT_FILTER_FIELD_TCP: + switch (layer) + { + case WINDIVERT_LAYER_NETWORK: + case WINDIVERT_LAYER_NETWORK_FORWARD: + val[0] = (UINT32)(tcp_header != NULL); + break; + case WINDIVERT_LAYER_SOCKET: + val[0] = + (UINT32)(socket_data->Protocol == IPPROTO_TCP); + break; + case WINDIVERT_LAYER_FLOW: + val[0] = + (UINT32)(flow_data->Protocol == IPPROTO_TCP); + break; + default: + return -1; + } + break; + case WINDIVERT_FILTER_FIELD_UDP: + switch (layer) + { + case WINDIVERT_LAYER_NETWORK: + case WINDIVERT_LAYER_NETWORK_FORWARD: + val[0] = (UINT32)(udp_header != NULL); + break; + case WINDIVERT_LAYER_SOCKET: + val[0] = + (UINT32)(socket_data->Protocol == IPPROTO_UDP); + break; + case WINDIVERT_LAYER_FLOW: + val[0] = + (UINT32)(flow_data->Protocol == IPPROTO_UDP); + break; + default: + return -1; + } + break; + case WINDIVERT_FILTER_FIELD_IP_HDRLENGTH: + val[0] = (UINT32)ip_header->HdrLength; + break; + case WINDIVERT_FILTER_FIELD_IP_TOS: + val[0] = (UINT32)ip_header->TOS; + break; + case WINDIVERT_FILTER_FIELD_IP_LENGTH: + val[0] = (UINT32)ntohs(ip_header->Length); + break; + case WINDIVERT_FILTER_FIELD_IP_ID: + val[0] = (UINT32)ntohs(ip_header->Id); + break; + case WINDIVERT_FILTER_FIELD_IP_DF: + val[0] = (UINT32)WINDIVERT_IPHDR_GET_DF(ip_header); + break; + case WINDIVERT_FILTER_FIELD_IP_MF: + val[0] = (UINT32)WINDIVERT_IPHDR_GET_MF(ip_header); + break; + case WINDIVERT_FILTER_FIELD_IP_FRAGOFF: + val[0] = (UINT32)ntohs( + WINDIVERT_IPHDR_GET_FRAGOFF(ip_header)); + break; + case WINDIVERT_FILTER_FIELD_IP_TTL: + val[0] = (UINT32)ip_header->TTL; + break; + case WINDIVERT_FILTER_FIELD_IP_PROTOCOL: + val[0] = (UINT32)ip_header->Protocol; + break; + case WINDIVERT_FILTER_FIELD_IP_CHECKSUM: + val[0] = (UINT32)ntohs(ip_header->Checksum); + break; + case WINDIVERT_FILTER_FIELD_IP_SRCADDR: + big = TRUE; + val[3] = val[2] = 0; + val[1] = 0x0000FFFF; + val[0] = (UINT32)ntohl(ip_header->SrcAddr); + break; + case WINDIVERT_FILTER_FIELD_IP_DSTADDR: + big = TRUE; + val[3] = val[2] = 0; + val[1] = 0x0000FFFF; + val[0] = (UINT32)ntohl(ip_header->DstAddr); + break; + case WINDIVERT_FILTER_FIELD_IPV6_TRAFFICCLASS: + val[0] = + (UINT32)WINDIVERT_IPV6HDR_GET_TRAFFICCLASS(ipv6_header); + break; + case WINDIVERT_FILTER_FIELD_IPV6_FLOWLABEL: + val[0] = (UINT32)ntohl( + WINDIVERT_IPV6HDR_GET_FLOWLABEL(ipv6_header)); + break; + case WINDIVERT_FILTER_FIELD_IPV6_LENGTH: + val[0] = (UINT32)ntohs(ipv6_header->Length); + break; + case WINDIVERT_FILTER_FIELD_IPV6_NEXTHDR: + val[0] = (UINT32)ipv6_header->NextHdr; + break; + case WINDIVERT_FILTER_FIELD_IPV6_HOPLIMIT: + val[0] = (UINT32)ipv6_header->HopLimit; + break; + case WINDIVERT_FILTER_FIELD_IPV6_SRCADDR: + big = TRUE; + val[3] = (UINT32)ntohl(ipv6_header->SrcAddr[0]); + val[2] = (UINT32)ntohl(ipv6_header->SrcAddr[1]); + val[1] = (UINT32)ntohl(ipv6_header->SrcAddr[2]); + val[0] = (UINT32)ntohl(ipv6_header->SrcAddr[3]); + break; + case WINDIVERT_FILTER_FIELD_IPV6_DSTADDR: + big = TRUE; + val[3] = (UINT32)ntohl(ipv6_header->DstAddr[0]); + val[2] = (UINT32)ntohl(ipv6_header->DstAddr[1]); + val[1] = (UINT32)ntohl(ipv6_header->DstAddr[2]); + val[0] = (UINT32)ntohl(ipv6_header->DstAddr[3]); + break; + case WINDIVERT_FILTER_FIELD_ICMP_TYPE: + val[0] = (UINT32)icmp_header->Type; + break; + case WINDIVERT_FILTER_FIELD_ICMP_CODE: + val[0] = (UINT32)icmp_header->Code; + break; + case WINDIVERT_FILTER_FIELD_ICMP_CHECKSUM: + val[0] = (UINT32)ntohs(icmp_header->Checksum); + break; + case WINDIVERT_FILTER_FIELD_ICMP_BODY: + val[0] = (UINT32)ntohl(icmp_header->Body); + break; + case WINDIVERT_FILTER_FIELD_ICMPV6_TYPE: + val[0] = (UINT32)icmpv6_header->Type; + break; + case WINDIVERT_FILTER_FIELD_ICMPV6_CODE: + val[0] = (UINT32)icmpv6_header->Code; + break; + case WINDIVERT_FILTER_FIELD_ICMPV6_CHECKSUM: + val[0] = (UINT32)ntohs(icmpv6_header->Checksum); + break; + case WINDIVERT_FILTER_FIELD_ICMPV6_BODY: + val[0] = (UINT32)ntohl(icmpv6_header->Body); + break; + case WINDIVERT_FILTER_FIELD_TCP_SRCPORT: + val[0] = (UINT32)ntohs(tcp_header->SrcPort); + break; + case WINDIVERT_FILTER_FIELD_TCP_DSTPORT: + val[0] = (UINT32)ntohs(tcp_header->DstPort); + break; + case WINDIVERT_FILTER_FIELD_TCP_SEQNUM: + val[0] = (UINT32)ntohl(tcp_header->SeqNum); + break; + case WINDIVERT_FILTER_FIELD_TCP_ACKNUM: + val[0] = (UINT32)ntohl(tcp_header->AckNum); + break; + case WINDIVERT_FILTER_FIELD_TCP_HDRLENGTH: + val[0] = (UINT32)tcp_header->HdrLength; + break; + case WINDIVERT_FILTER_FIELD_TCP_URG: + val[0] = (UINT32)tcp_header->Urg; + break; + case WINDIVERT_FILTER_FIELD_TCP_ACK: + val[0] = (UINT32)tcp_header->Ack; + break; + case WINDIVERT_FILTER_FIELD_TCP_PSH: + val[0] = (UINT32)tcp_header->Psh; + break; + case WINDIVERT_FILTER_FIELD_TCP_RST: + val[0] = (UINT32)tcp_header->Rst; + break; + case WINDIVERT_FILTER_FIELD_TCP_SYN: + val[0] = (UINT32)tcp_header->Syn; + break; + case WINDIVERT_FILTER_FIELD_TCP_FIN: + val[0] = (UINT32)tcp_header->Fin; + break; + case WINDIVERT_FILTER_FIELD_TCP_WINDOW: + val[0] = (UINT32)ntohs(tcp_header->Window); + break; + case WINDIVERT_FILTER_FIELD_TCP_CHECKSUM: + val[0] = (UINT32)ntohs(tcp_header->Checksum); + break; + case WINDIVERT_FILTER_FIELD_TCP_URGPTR: + val[0] = (UINT32)ntohs(tcp_header->UrgPtr); + break; + case WINDIVERT_FILTER_FIELD_TCP_PAYLOADLENGTH: + val[0] = (UINT32)payload_len; + break; + case WINDIVERT_FILTER_FIELD_UDP_SRCPORT: + val[0] = (UINT32)ntohs(udp_header->SrcPort); + break; + case WINDIVERT_FILTER_FIELD_UDP_DSTPORT: + val[0] = (UINT32)ntohs(udp_header->DstPort); + break; + case WINDIVERT_FILTER_FIELD_UDP_LENGTH: + val[0] = (UINT32)ntohs(udp_header->Length); + break; + case WINDIVERT_FILTER_FIELD_UDP_CHECKSUM: + val[0] = (UINT32)ntohs(udp_header->Checksum); + break; + case WINDIVERT_FILTER_FIELD_UDP_PAYLOADLENGTH: + val[0] = (UINT32)payload_len; + break; + case WINDIVERT_FILTER_FIELD_LOCALADDR: + big = TRUE; + switch (layer) + { + case WINDIVERT_LAYER_NETWORK: + if (ip_header != NULL) + { + val[3] = val[2] = 0; + val[1] = 0x0000FFFF; + val[0] = (UINT32)ntohl( + (outbound? ip_header->SrcAddr: + ip_header->DstAddr)); + } + else if (ipv6_header != NULL && outbound) + { + val[3] = (UINT32)ntohl(ipv6_header->SrcAddr[0]); + val[2] = (UINT32)ntohl(ipv6_header->SrcAddr[1]); + val[1] = (UINT32)ntohl(ipv6_header->SrcAddr[2]); + val[0] = (UINT32)ntohl(ipv6_header->SrcAddr[3]); + } + else if (ipv6_header != NULL) + { + val[3] = (UINT32)ntohl(ipv6_header->DstAddr[0]); + val[2] = (UINT32)ntohl(ipv6_header->DstAddr[1]); + val[1] = (UINT32)ntohl(ipv6_header->DstAddr[2]); + val[0] = (UINT32)ntohl(ipv6_header->DstAddr[3]); + } + else + { + val[3] = val[2] = val[1] = val[0] = 0; + } + break; + case WINDIVERT_LAYER_FLOW: + val[0] = flow_data->LocalAddr[0]; + val[1] = flow_data->LocalAddr[1]; + val[2] = flow_data->LocalAddr[2]; + val[3] = flow_data->LocalAddr[3]; + break; + case WINDIVERT_LAYER_SOCKET: + val[0] = socket_data->LocalAddr[0]; + val[1] = socket_data->LocalAddr[1]; + val[2] = socket_data->LocalAddr[2]; + val[3] = socket_data->LocalAddr[3]; + break; + default: + return -1; + } + break; + case WINDIVERT_FILTER_FIELD_REMOTEADDR: + big = TRUE; + switch (layer) + { + case WINDIVERT_LAYER_NETWORK: + if (ip_header != NULL) + { + val[3] = val[2] = 0; + val[1] = 0x0000FFFF; + val[0] = (UINT32)ntohl( + (!outbound? ip_header->SrcAddr: + ip_header->DstAddr)); + } + else if (ipv6_header != NULL && !outbound) + { + val[3] = (UINT32)ntohl(ipv6_header->SrcAddr[0]); + val[2] = (UINT32)ntohl(ipv6_header->SrcAddr[1]); + val[1] = (UINT32)ntohl(ipv6_header->SrcAddr[2]); + val[0] = (UINT32)ntohl(ipv6_header->SrcAddr[3]); + } + else if (ipv6_header != NULL) + { + val[3] = (UINT32)ntohl(ipv6_header->DstAddr[0]); + val[2] = (UINT32)ntohl(ipv6_header->DstAddr[1]); + val[1] = (UINT32)ntohl(ipv6_header->DstAddr[2]); + val[0] = (UINT32)ntohl(ipv6_header->DstAddr[3]); + } + else + { + val[3] = val[2] = val[1] = val[0] = 0; + } + break; + case WINDIVERT_LAYER_FLOW: + val[0] = flow_data->RemoteAddr[0]; + val[1] = flow_data->RemoteAddr[1]; + val[2] = flow_data->RemoteAddr[2]; + val[3] = flow_data->RemoteAddr[3]; + break; + case WINDIVERT_LAYER_SOCKET: + val[0] = socket_data->RemoteAddr[0]; + val[1] = socket_data->RemoteAddr[1]; + val[2] = socket_data->RemoteAddr[2]; + val[3] = socket_data->RemoteAddr[3]; + break; + default: + return -1; + } + break; + case WINDIVERT_FILTER_FIELD_LOCALPORT: + switch (layer) + { + case WINDIVERT_LAYER_NETWORK: + if (tcp_header != NULL) + { + val[0] = (UINT32)ntohs( + (outbound? tcp_header->SrcPort: + tcp_header->DstPort)); + } + else if (udp_header != NULL) + { + val[0] = (UINT32)ntohs( + (outbound? udp_header->SrcPort: + udp_header->DstPort)); + } + else if (icmp_header != NULL) + { + val[0] = (outbound? + (UINT32)icmp_header->Type: 0); + } + else if (icmpv6_header != NULL) + { + val[0] = (outbound? + (UINT32)icmpv6_header->Type: 0); + } + else + { + val[0] = 0; + } + break; + case WINDIVERT_LAYER_FLOW: + val[0] = (UINT32)flow_data->LocalPort; + break; + case WINDIVERT_LAYER_SOCKET: + val[0] = (UINT32)socket_data->LocalPort; + break; + default: + return -1; + } + break; + case WINDIVERT_FILTER_FIELD_REMOTEPORT: + switch (layer) + { + case WINDIVERT_LAYER_NETWORK: + if (tcp_header != NULL) + { + val[0] = (UINT32)ntohs( + (!outbound? tcp_header->SrcPort: + tcp_header->DstPort)); + } + else if (udp_header != NULL) + { + val[0] = (UINT32)ntohs( + (!outbound? udp_header->SrcPort: + udp_header->DstPort)); + } + else if (icmp_header != NULL) + { + val[0] = (!outbound? + (UINT32)icmp_header->Type: 0); + } + else if (icmpv6_header != NULL) + { + val[0] = (!outbound? + (UINT32)icmpv6_header->Type: 0); + } + else + { + val[0] = 0; + } + break; + case WINDIVERT_LAYER_FLOW: + val[0] = (UINT32)flow_data->RemotePort; + break; + case WINDIVERT_LAYER_SOCKET: + val[0] = (UINT32)socket_data->RemotePort; + break; + default: + return -1; + } + break; + case WINDIVERT_FILTER_FIELD_PROTOCOL: + switch (layer) + { + case WINDIVERT_LAYER_NETWORK: + val[0] = (UINT32)protocol; + break; + case WINDIVERT_LAYER_FLOW: + val[0] = (UINT32)flow_data->Protocol; + break; + case WINDIVERT_LAYER_SOCKET: + val[0] = (UINT32)socket_data->Protocol; + break; + default: + return -1; + } + break; + case WINDIVERT_FILTER_FIELD_PROCESSID: + switch (layer) + { + case WINDIVERT_LAYER_FLOW: + val[0] = flow_data->ProcessId; + break; + case WINDIVERT_LAYER_SOCKET: + val[0] = socket_data->ProcessId; + break; + case WINDIVERT_LAYER_REFLECT: + val[0] = reflect_data->ProcessId; + break; + default: + return -1; + } + break; + case WINDIVERT_FILTER_FIELD_ENDPOINTID: + big = TRUE; + val[2] = val[3] = 0; + switch (layer) + { + case WINDIVERT_LAYER_FLOW: + val64.QuadPart = flow_data->EndpointId; + val[0] = (UINT32)val64.LowPart; + val[1] = (UINT32)val64.HighPart; + break; + case WINDIVERT_LAYER_SOCKET: + val64.QuadPart = socket_data->EndpointId; + val[0] = (UINT32)val64.LowPart; + val[1] = (UINT32)val64.HighPart; + break; + default: + return -1; + } + break; + case WINDIVERT_FILTER_FIELD_PARENTENDPOINTID: + big = TRUE; + val[2] = val[3] = 0; + switch (layer) + { + case WINDIVERT_LAYER_FLOW: + val64.QuadPart = flow_data->ParentEndpointId; + val[0] = (UINT32)val64.LowPart; + val[1] = (UINT32)val64.HighPart; + break; + case WINDIVERT_LAYER_SOCKET: + val64.QuadPart = socket_data->ParentEndpointId; + val[0] = (UINT32)val64.LowPart; + val[1] = (UINT32)val64.HighPart; + break; + default: + return -1; + } + break; + case WINDIVERT_FILTER_FIELD_LAYER: + val[0] = (UINT32)reflect_data->Layer; + break; + case WINDIVERT_FILTER_FIELD_PRIORITY: + neg = (reflect_data->Priority < 0); + val[0] = (UINT32)(neg? -reflect_data->Priority: + reflect_data->Priority); + break; + default: + return -1; + } + } + + if (result) + { + cmp = WinDivertCompare128(neg, val, + (filter[ip].neg? TRUE: FALSE), filter[ip].arg, big); + switch (filter[ip].test) + { + case WINDIVERT_FILTER_TEST_EQ: + result = (cmp == 0); + break; + case WINDIVERT_FILTER_TEST_NEQ: + result = (cmp != 0); + break; + case WINDIVERT_FILTER_TEST_LT: + result = (cmp < 0); + break; + case WINDIVERT_FILTER_TEST_LEQ: + result = (cmp <= 0); + break; + case WINDIVERT_FILTER_TEST_GT: + result = (cmp > 0); + break; + case WINDIVERT_FILTER_TEST_GEQ: + result = (cmp >= 0); + break; + default: + return -1; + } + } + + ip = (UINT16)(result? filter[ip].success: filter[ip].failure); + switch (ip) + { + case WINDIVERT_FILTER_RESULT_ACCEPT: + return 1; + case WINDIVERT_FILTER_RESULT_REJECT: + return 0; + default: + break; + } + } + + return -1; +} + diff --git a/doc/windivert.html b/doc/windivert.html index 5b28903..b0d8090 100644 --- a/doc/windivert.html +++ b/doc/windivert.html @@ -1,11 +1,11 @@ - WinDivert 2.1 Documentation + WinDivert 2.2 Documentation -

WinDivert 2.1: Windows Packet Divert

+

WinDivert 2.2: Windows Packet Divert

Table of Contents

  • 1. Introduction
  • diff --git a/sys/windivert.c b/sys/windivert.c index d3d54a2..8ba004b 100644 --- a/sys/windivert.c +++ b/sys/windivert.c @@ -466,11 +466,9 @@ static BOOL windivert_queue_work(context_t context, PVOID packet, static void windivert_queue_packet(context_t context, packet_t packet); static void windivert_reinject_packet(packet_t packet); static void windivert_free_packet(packet_t packet); -static int windivert_big_num_compare(BOOL neg_a, const UINT32 *a, BOOL neg_b, - const UINT32 *b, BOOL big); static BOOL windivert_copy_data(PNET_BUFFER buffer, PVOID data, UINT size); -static BOOL windivert_lookup_data(PNET_BUFFER buffer, UINT offset, INT idx, - PVOID data, UINT size); +static BOOL windivert_get_data(PNET_BUFFER buffer, UINT length, INT min, + INT max, INT idx, PVOID data, UINT size); static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4, BOOL *fragment_ptr, PWINDIVERT_IPHDR *ip_header_ptr, PWINDIVERT_IPV6HDR *ipv6_header_ptr, PWINDIVERT_ICMPHDR *icmp_header_ptr, @@ -901,6 +899,14 @@ static const struct layer_s windivert_layer_flow_established_ipv6 = #define WINDIVERT_LAYER_FLOW_ESTABLISHED_IPV6 \ (&windivert_layer_flow_established_ipv6) +/* + * Filter interpreter config. + */ +#define WINDIVERT_INLINE __forceinline +#define WINDIVERT_GET_DATA(packet, packet_len, min, max, index, data, size) \ + windivert_get_data((PNET_BUFFER)(packet), (packet_len), (min), (max), \ + (index), (data), (size)) + /* * Shared functions. */ @@ -5168,60 +5174,6 @@ static void windivert_free_packet(packet_t packet) windivert_free(packet); } -/* - * Big number comparison. - */ -static int windivert_big_num_compare(BOOL neg_a, const UINT32 *a, BOOL neg_b, - const UINT32 *b, BOOL big) -{ - int neg; - if (neg_a && !neg_b) - { - return -1; - } - if (!neg_a && neg_b) - { - return 1; - } - neg = (neg_a? -1: 1); - if (big) - { - if (a[3] < b[3]) - { - return -neg; - } - if (a[3] > b[3]) - { - return neg; - } - if (a[2] < b[2]) - { - return -neg; - } - if (a[2] > b[2]) - { - return neg; - } - if (a[1] < b[1]) - { - return -neg; - } - if (a[1] > b[1]) - { - return neg; - } - } - if (a[0] < b[0]) - { - return -neg; - } - if (a[0] > b[0]) - { - return neg; - } - return 0; -} - /* * Copy data from a NET_BUFFER. */ @@ -5251,21 +5203,14 @@ static BOOL windivert_copy_data(PNET_BUFFER buffer, PVOID data, UINT size) /* * Lookup packet/payload data at given index. */ -static BOOL windivert_lookup_data(PNET_BUFFER buffer, UINT offset, INT idx, - PVOID data, UINT size) +static BOOL windivert_get_data(PNET_BUFFER buffer, UINT length, INT min, + INT max, INT idx, PVOID data, UINT size) { - UINT length = NET_BUFFER_DATA_LENGTH(buffer); BOOL success; + UNREFERENCED_PARAMETER(length); - if (idx < 0) - { - idx += (INT)length; - } - else - { - idx += (INT)offset; - } - if (idx < (INT)offset || idx > (INT)(length - size)) + idx += (idx < 0? max: min); + if (idx < min || idx > (max - (INT)size)) { return FALSE; // OOB } @@ -5285,7 +5230,7 @@ static BOOL windivert_lookup_data(PNET_BUFFER buffer, UINT offset, INT idx, /* * Parse packet headers. */ -static __forceinline BOOL windivert_parse_headers(PNET_BUFFER buffer, +static WINDIVERT_INLINE BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4, BOOL *fragment_ptr, PWINDIVERT_IPHDR *ip_header_ptr, PWINDIVERT_IPV6HDR *ipv6_header_ptr, PWINDIVERT_ICMPHDR *icmp_header_ptr, PWINDIVERT_ICMPV6HDR *icmpv6_header_ptr, PWINDIVERT_TCPHDR *tcp_header_ptr, @@ -5537,18 +5482,14 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer, PWINDIVERT_ICMPV6HDR icmpv6_header = NULL; PWINDIVERT_TCPHDR tcp_header = NULL; PWINDIVERT_UDPHDR udp_header = NULL; - UINT8 protocol = 0; - UINT header_len = 0, payload_len = 0; - UINT64 random64 = 0; - UINT16 ip, ttl; BOOL fragment = FALSE; + UINT8 protocol = 0; + UINT header_len = 0, payload_len = 0, total_len = 0; PWINDIVERT_DATA_NETWORK network_data = NULL; PWINDIVERT_DATA_FLOW flow_data = NULL; PWINDIVERT_DATA_SOCKET socket_data = NULL; PWINDIVERT_DATA_REFLECT reflect_data = NULL; - UINT8 data8; - UINT16 data16; - UINT32 data32; + int result; switch (layer) { @@ -5580,815 +5521,33 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer, return FALSE; } - // Execute the filter: - ip = 0; - ttl = WINDIVERT_FILTER_MAXLEN+1; // Additional safety - while (ttl-- != 0) - { - BOOL result = FALSE; - BOOL big = FALSE; - BOOL neg = FALSE; - int cmp; - UINT32 field[4]; + result = WinDivertExecuteFilter( + filter, + layer, + timestamp, + event, + ipv4, + outbound, + loopback, + impostor, + fragment, + network_data, + flow_data, + socket_data, + reflect_data, + ip_header, + ipv6_header, + icmp_header, + icmpv6_header, + tcp_header, + udp_header, + protocol, + (const VOID *)buffer, + header_len + payload_len, + header_len, + payload_len); - switch (filter[ip].field) - { - case WINDIVERT_FILTER_FIELD_ZERO: - case WINDIVERT_FILTER_FIELD_EVENT: - case WINDIVERT_FILTER_FIELD_TIMESTAMP: - result = TRUE; - break; - case WINDIVERT_FILTER_FIELD_INBOUND: - case WINDIVERT_FILTER_FIELD_OUTBOUND: - result = (layer != WINDIVERT_LAYER_NETWORK_FORWARD && - layer != WINDIVERT_LAYER_REFLECT); - break; - case WINDIVERT_FILTER_FIELD_LOOPBACK: - case WINDIVERT_FILTER_FIELD_IMPOSTOR: - case WINDIVERT_FILTER_FIELD_IP: - case WINDIVERT_FILTER_FIELD_IPV6: - case WINDIVERT_FILTER_FIELD_ICMP: - case WINDIVERT_FILTER_FIELD_ICMPV6: - case WINDIVERT_FILTER_FIELD_TCP: - case WINDIVERT_FILTER_FIELD_UDP: - result = (layer != WINDIVERT_LAYER_REFLECT); - break; - case WINDIVERT_FILTER_FIELD_RANDOM8: - case WINDIVERT_FILTER_FIELD_RANDOM16: - case WINDIVERT_FILTER_FIELD_RANDOM32: - result = (layer == WINDIVERT_LAYER_NETWORK || - layer == WINDIVERT_LAYER_NETWORK_FORWARD); - if (result && random64 == 0) - { - random64 = WinDivertHashPacket((UINT64)timestamp, - ip_header, ipv6_header, icmp_header, icmpv6_header, - tcp_header, udp_header); - random64 |= 0xFF00000000000000ull; // Make non-zero. - } - break; - case WINDIVERT_FILTER_FIELD_IFIDX: - case WINDIVERT_FILTER_FIELD_SUBIFIDX: - case WINDIVERT_FILTER_FIELD_PACKET: - case WINDIVERT_FILTER_FIELD_PACKET16: - case WINDIVERT_FILTER_FIELD_PACKET32: - case WINDIVERT_FILTER_FIELD_LENGTH: - case WINDIVERT_FILTER_FIELD_FRAGMENT: - result = (layer == WINDIVERT_LAYER_NETWORK || - layer == WINDIVERT_LAYER_NETWORK_FORWARD); - break; - case WINDIVERT_FILTER_FIELD_LOCALADDR: - case WINDIVERT_FILTER_FIELD_REMOTEADDR: - case WINDIVERT_FILTER_FIELD_LOCALPORT: - case WINDIVERT_FILTER_FIELD_REMOTEPORT: - case WINDIVERT_FILTER_FIELD_PROTOCOL: - result = (layer == WINDIVERT_LAYER_NETWORK || - layer == WINDIVERT_LAYER_FLOW || - layer == WINDIVERT_LAYER_SOCKET); - break; - case WINDIVERT_FILTER_FIELD_PROCESSID: - result = (layer == WINDIVERT_LAYER_FLOW || - layer == WINDIVERT_LAYER_SOCKET || - layer == WINDIVERT_LAYER_REFLECT); - break; - case WINDIVERT_FILTER_FIELD_ENDPOINTID: - case WINDIVERT_FILTER_FIELD_PARENTENDPOINTID: - result = (layer == WINDIVERT_LAYER_FLOW || - layer == WINDIVERT_LAYER_SOCKET); - break; - case WINDIVERT_FILTER_FIELD_LAYER: - case WINDIVERT_FILTER_FIELD_PRIORITY: - result = (layer == WINDIVERT_LAYER_REFLECT); - break; - case WINDIVERT_FILTER_FIELD_IP_HDRLENGTH: - case WINDIVERT_FILTER_FIELD_IP_TOS: - case WINDIVERT_FILTER_FIELD_IP_LENGTH: - case WINDIVERT_FILTER_FIELD_IP_ID: - case WINDIVERT_FILTER_FIELD_IP_DF: - case WINDIVERT_FILTER_FIELD_IP_MF: - case WINDIVERT_FILTER_FIELD_IP_FRAGOFF: - case WINDIVERT_FILTER_FIELD_IP_TTL: - case WINDIVERT_FILTER_FIELD_IP_PROTOCOL: - case WINDIVERT_FILTER_FIELD_IP_CHECKSUM: - case WINDIVERT_FILTER_FIELD_IP_SRCADDR: - case WINDIVERT_FILTER_FIELD_IP_DSTADDR: - result = (layer == WINDIVERT_LAYER_NETWORK || - layer == WINDIVERT_LAYER_NETWORK_FORWARD); - result = result && (ip_header != NULL); - break; - case WINDIVERT_FILTER_FIELD_IPV6_TRAFFICCLASS: - case WINDIVERT_FILTER_FIELD_IPV6_FLOWLABEL: - case WINDIVERT_FILTER_FIELD_IPV6_LENGTH: - case WINDIVERT_FILTER_FIELD_IPV6_NEXTHDR: - case WINDIVERT_FILTER_FIELD_IPV6_HOPLIMIT: - case WINDIVERT_FILTER_FIELD_IPV6_SRCADDR: - case WINDIVERT_FILTER_FIELD_IPV6_DSTADDR: - result = (layer == WINDIVERT_LAYER_NETWORK || - layer == WINDIVERT_LAYER_NETWORK_FORWARD); - result = result && (ipv6_header != NULL); - break; - case WINDIVERT_FILTER_FIELD_ICMP_TYPE: - case WINDIVERT_FILTER_FIELD_ICMP_CODE: - case WINDIVERT_FILTER_FIELD_ICMP_CHECKSUM: - case WINDIVERT_FILTER_FIELD_ICMP_BODY: - result = (layer == WINDIVERT_LAYER_NETWORK || - layer == WINDIVERT_LAYER_NETWORK_FORWARD); - result = result && (icmp_header != NULL); - break; - case WINDIVERT_FILTER_FIELD_ICMPV6_TYPE: - case WINDIVERT_FILTER_FIELD_ICMPV6_CODE: - case WINDIVERT_FILTER_FIELD_ICMPV6_CHECKSUM: - case WINDIVERT_FILTER_FIELD_ICMPV6_BODY: - result = (layer == WINDIVERT_LAYER_NETWORK || - layer == WINDIVERT_LAYER_NETWORK_FORWARD); - result = result && (icmpv6_header != NULL); - break; - case WINDIVERT_FILTER_FIELD_TCP_SRCPORT: - case WINDIVERT_FILTER_FIELD_TCP_DSTPORT: - case WINDIVERT_FILTER_FIELD_TCP_SEQNUM: - case WINDIVERT_FILTER_FIELD_TCP_ACKNUM: - case WINDIVERT_FILTER_FIELD_TCP_HDRLENGTH: - case WINDIVERT_FILTER_FIELD_TCP_URG: - case WINDIVERT_FILTER_FIELD_TCP_ACK: - case WINDIVERT_FILTER_FIELD_TCP_PSH: - case WINDIVERT_FILTER_FIELD_TCP_RST: - case WINDIVERT_FILTER_FIELD_TCP_SYN: - case WINDIVERT_FILTER_FIELD_TCP_FIN: - case WINDIVERT_FILTER_FIELD_TCP_WINDOW: - case WINDIVERT_FILTER_FIELD_TCP_CHECKSUM: - case WINDIVERT_FILTER_FIELD_TCP_URGPTR: - case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD: - case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16: - case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32: - case WINDIVERT_FILTER_FIELD_TCP_PAYLOADLENGTH: - result = (layer == WINDIVERT_LAYER_NETWORK || - layer == WINDIVERT_LAYER_NETWORK_FORWARD); - result = result && (tcp_header != NULL); - break; - case WINDIVERT_FILTER_FIELD_UDP_SRCPORT: - case WINDIVERT_FILTER_FIELD_UDP_DSTPORT: - case WINDIVERT_FILTER_FIELD_UDP_LENGTH: - case WINDIVERT_FILTER_FIELD_UDP_CHECKSUM: - case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD: - case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16: - case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32: - case WINDIVERT_FILTER_FIELD_UDP_PAYLOADLENGTH: - result = (layer == WINDIVERT_LAYER_NETWORK || - layer == WINDIVERT_LAYER_NETWORK_FORWARD); - result = result && (udp_header != NULL); - break; - default: - return FALSE; - } - if (result) - { - switch (filter[ip].field) - { - case WINDIVERT_FILTER_FIELD_ZERO: - field[0] = 0; - break; - case WINDIVERT_FILTER_FIELD_EVENT: - field[0] = (UINT32)event; - break; - case WINDIVERT_FILTER_FIELD_LENGTH: - if (ipv4) - { - field[0] = (UINT32)RtlUshortByteSwap(ip_header->Length); - } - else - { - field[0] = - (UINT32)RtlUshortByteSwap(ipv6_header->Length) + - sizeof(WINDIVERT_IPV6HDR); - } - break; - case WINDIVERT_FILTER_FIELD_TIMESTAMP: - { - UINT64 val64; - neg = (timestamp < 0); - val64 = (UINT64)(neg? -timestamp: timestamp); - big = TRUE; - field[3] = field[2] = 0; - field[0] = (UINT32)val64; - field[1] = (UINT32)(val64 >> 32); - break; - } - case WINDIVERT_FILTER_FIELD_RANDOM8: - field[0] = (UINT32)((random64 >> 48) & 0xFF); - break; - case WINDIVERT_FILTER_FIELD_RANDOM16: - field[0] = (UINT32)((random64 >> 32) & 0xFFFF); - break; - case WINDIVERT_FILTER_FIELD_RANDOM32: - field[0] = (UINT32)random64; - break; - case WINDIVERT_FILTER_FIELD_PACKET: - result = windivert_lookup_data(buffer, /*offset=*/0, - (INT)filter[ip].arg[1], &data8, sizeof(data8)); - field[0] = (UINT32)data8; - break; - case WINDIVERT_FILTER_FIELD_PACKET16: - result = windivert_lookup_data(buffer, /*offset=*/0, - (INT)filter[ip].arg[1], &data16, sizeof(data16)); - field[0] = (UINT32)RtlUshortByteSwap(data16); - break; - case WINDIVERT_FILTER_FIELD_PACKET32: - result = windivert_lookup_data(buffer, /*offset=*/0, - (INT)filter[ip].arg[1], &data32, sizeof(data32)); - field[0] = (UINT32)RtlUlongByteSwap(data32); - break; - case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD: - case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD: - result = windivert_lookup_data(buffer, header_len, - (INT)filter[ip].arg[1], &data8, sizeof(data8)); - field[0] = (UINT32)data8; - break; - case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16: - case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16: - result = windivert_lookup_data(buffer, header_len, - (INT)filter[ip].arg[1], &data16, sizeof(data16)); - field[0] = (UINT32)RtlUshortByteSwap(data16); - break; - case WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32: - case WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32: - result = windivert_lookup_data(buffer, header_len, - (INT)filter[ip].arg[1], &data32, sizeof(data32)); - field[0] = (UINT32)RtlUlongByteSwap(data32); - break; - case WINDIVERT_FILTER_FIELD_INBOUND: - field[0] = (UINT32)!outbound; - break; - case WINDIVERT_FILTER_FIELD_OUTBOUND: - field[0] = (UINT32)outbound; - break; - case WINDIVERT_FILTER_FIELD_FRAGMENT: - field[0] = (UINT32)fragment; - break; - case WINDIVERT_FILTER_FIELD_IFIDX: - field[0] = network_data->IfIdx; - break; - case WINDIVERT_FILTER_FIELD_SUBIFIDX: - field[0] = network_data->SubIfIdx; - break; - case WINDIVERT_FILTER_FIELD_LOOPBACK: - field[0] = (UINT32)loopback; - break; - case WINDIVERT_FILTER_FIELD_IMPOSTOR: - field[0] = (UINT32)impostor; - break; - case WINDIVERT_FILTER_FIELD_IP: - field[0] = (UINT32)ipv4; - break; - case WINDIVERT_FILTER_FIELD_IPV6: - field[0] = (UINT32)!ipv4; - break; - case WINDIVERT_FILTER_FIELD_ICMP: - switch (layer) - { - case WINDIVERT_LAYER_NETWORK: - case WINDIVERT_LAYER_NETWORK_FORWARD: - field[0] = (UINT32)(icmp_header != NULL); - break; - case WINDIVERT_LAYER_SOCKET: - field[0] = (UINT32)(ipv4 && - socket_data->Protocol == IPPROTO_ICMP); - break; - case WINDIVERT_LAYER_FLOW: - field[0] = (UINT32)(ipv4 && - flow_data->Protocol == IPPROTO_ICMP); - break; - default: - return FALSE; - } - break; - case WINDIVERT_FILTER_FIELD_ICMPV6: - switch (layer) - { - case WINDIVERT_LAYER_NETWORK: - case WINDIVERT_LAYER_NETWORK_FORWARD: - field[0] = (UINT32)(icmpv6_header != NULL); - break; - case WINDIVERT_LAYER_SOCKET: - field[0] = (UINT32)(!ipv4 && - socket_data->Protocol == IPPROTO_ICMPV6); - break; - case WINDIVERT_LAYER_FLOW: - field[0] = (UINT32)(!ipv4 && - flow_data->Protocol == IPPROTO_ICMPV6); - break; - default: - return FALSE; - } - break; - case WINDIVERT_FILTER_FIELD_TCP: - switch (layer) - { - case WINDIVERT_LAYER_NETWORK: - case WINDIVERT_LAYER_NETWORK_FORWARD: - field[0] = (UINT32)(tcp_header != NULL); - break; - case WINDIVERT_LAYER_SOCKET: - field[0] = - (UINT32)(socket_data->Protocol == IPPROTO_TCP); - break; - case WINDIVERT_LAYER_FLOW: - field[0] = - (UINT32)(flow_data->Protocol == IPPROTO_TCP); - break; - default: - return FALSE; - } - break; - case WINDIVERT_FILTER_FIELD_UDP: - switch (layer) - { - case WINDIVERT_LAYER_NETWORK: - case WINDIVERT_LAYER_NETWORK_FORWARD: - field[0] = (UINT32)(udp_header != NULL); - break; - case WINDIVERT_LAYER_SOCKET: - field[0] = - (UINT32)(socket_data->Protocol == IPPROTO_UDP); - break; - case WINDIVERT_LAYER_FLOW: - field[0] = - (UINT32)(flow_data->Protocol == IPPROTO_UDP); - break; - default: - return FALSE; - } - break; - case WINDIVERT_FILTER_FIELD_IP_HDRLENGTH: - field[0] = (UINT32)ip_header->HdrLength; - break; - case WINDIVERT_FILTER_FIELD_IP_TOS: - field[0] = (UINT32)ip_header->TOS; - break; - case WINDIVERT_FILTER_FIELD_IP_LENGTH: - field[0] = (UINT32)RtlUshortByteSwap(ip_header->Length); - break; - case WINDIVERT_FILTER_FIELD_IP_ID: - field[0] = (UINT32)RtlUshortByteSwap(ip_header->Id); - break; - case WINDIVERT_FILTER_FIELD_IP_DF: - field[0] = (UINT32)WINDIVERT_IPHDR_GET_DF(ip_header); - break; - case WINDIVERT_FILTER_FIELD_IP_MF: - field[0] = (UINT32)WINDIVERT_IPHDR_GET_MF(ip_header); - break; - case WINDIVERT_FILTER_FIELD_IP_FRAGOFF: - field[0] = (UINT32)RtlUshortByteSwap( - WINDIVERT_IPHDR_GET_FRAGOFF(ip_header)); - break; - case WINDIVERT_FILTER_FIELD_IP_TTL: - field[0] = (UINT32)ip_header->TTL; - break; - case WINDIVERT_FILTER_FIELD_IP_PROTOCOL: - field[0] = (UINT32)ip_header->Protocol; - break; - case WINDIVERT_FILTER_FIELD_IP_CHECKSUM: - field[0] = (UINT32)RtlUshortByteSwap(ip_header->Checksum); - break; - case WINDIVERT_FILTER_FIELD_IP_SRCADDR: - field[1] = 0x0000FFFF; - field[0] = (UINT32)RtlUlongByteSwap(ip_header->SrcAddr); - break; - case WINDIVERT_FILTER_FIELD_IP_DSTADDR: - field[1] = 0x0000FFFF; - field[0] = (UINT32)RtlUlongByteSwap(ip_header->DstAddr); - break; - case WINDIVERT_FILTER_FIELD_IPV6_TRAFFICCLASS: - field[0] = - (UINT32)WINDIVERT_IPV6HDR_GET_TRAFFICCLASS(ipv6_header); - break; - case WINDIVERT_FILTER_FIELD_IPV6_FLOWLABEL: - field[0] = (UINT32)RtlUlongByteSwap( - WINDIVERT_IPV6HDR_GET_FLOWLABEL(ipv6_header)); - break; - case WINDIVERT_FILTER_FIELD_IPV6_LENGTH: - field[0] = (UINT32)RtlUshortByteSwap(ipv6_header->Length); - break; - case WINDIVERT_FILTER_FIELD_IPV6_NEXTHDR: - field[0] = (UINT32)ipv6_header->NextHdr; - break; - case WINDIVERT_FILTER_FIELD_IPV6_HOPLIMIT: - field[0] = (UINT32)ipv6_header->HopLimit; - break; - case WINDIVERT_FILTER_FIELD_IPV6_SRCADDR: - big = TRUE; - field[3] = - (UINT32)RtlUlongByteSwap(ipv6_header->SrcAddr[0]); - field[2] = - (UINT32)RtlUlongByteSwap(ipv6_header->SrcAddr[1]); - field[1] = - (UINT32)RtlUlongByteSwap(ipv6_header->SrcAddr[2]); - field[0] = - (UINT32)RtlUlongByteSwap(ipv6_header->SrcAddr[3]); - break; - case WINDIVERT_FILTER_FIELD_IPV6_DSTADDR: - big = TRUE; - field[3] = - (UINT32)RtlUlongByteSwap(ipv6_header->DstAddr[0]); - field[2] = - (UINT32)RtlUlongByteSwap(ipv6_header->DstAddr[1]); - field[1] = - (UINT32)RtlUlongByteSwap(ipv6_header->DstAddr[2]); - field[0] = - (UINT32)RtlUlongByteSwap(ipv6_header->DstAddr[3]); - break; - case WINDIVERT_FILTER_FIELD_ICMP_TYPE: - field[0] = (UINT32)icmp_header->Type; - break; - case WINDIVERT_FILTER_FIELD_ICMP_CODE: - field[0] = (UINT32)icmp_header->Code; - break; - case WINDIVERT_FILTER_FIELD_ICMP_CHECKSUM: - field[0] = - (UINT32)RtlUshortByteSwap(icmp_header->Checksum); - break; - case WINDIVERT_FILTER_FIELD_ICMP_BODY: - field[0] = (UINT32)RtlUlongByteSwap(icmp_header->Body); - break; - case WINDIVERT_FILTER_FIELD_ICMPV6_TYPE: - field[0] = (UINT32)icmpv6_header->Type; - break; - case WINDIVERT_FILTER_FIELD_ICMPV6_CODE: - field[0] = (UINT32)icmpv6_header->Code; - break; - case WINDIVERT_FILTER_FIELD_ICMPV6_CHECKSUM: - field[0] = - (UINT32)RtlUshortByteSwap(icmpv6_header->Checksum); - break; - case WINDIVERT_FILTER_FIELD_ICMPV6_BODY: - field[0] = - (UINT32)RtlUlongByteSwap(icmpv6_header->Body); - break; - case WINDIVERT_FILTER_FIELD_TCP_SRCPORT: - field[0] = (UINT32)RtlUshortByteSwap(tcp_header->SrcPort); - break; - case WINDIVERT_FILTER_FIELD_TCP_DSTPORT: - field[0] = (UINT32)RtlUshortByteSwap(tcp_header->DstPort); - break; - case WINDIVERT_FILTER_FIELD_TCP_SEQNUM: - field[0] = (UINT32)RtlUlongByteSwap(tcp_header->SeqNum); - break; - case WINDIVERT_FILTER_FIELD_TCP_ACKNUM: - field[0] = (UINT32)RtlUlongByteSwap(tcp_header->AckNum); - break; - case WINDIVERT_FILTER_FIELD_TCP_HDRLENGTH: - field[0] = (UINT32)tcp_header->HdrLength; - break; - case WINDIVERT_FILTER_FIELD_TCP_URG: - field[0] = (UINT32)tcp_header->Urg; - break; - case WINDIVERT_FILTER_FIELD_TCP_ACK: - field[0] = (UINT32)tcp_header->Ack; - break; - case WINDIVERT_FILTER_FIELD_TCP_PSH: - field[0] = (UINT32)tcp_header->Psh; - break; - case WINDIVERT_FILTER_FIELD_TCP_RST: - field[0] = (UINT32)tcp_header->Rst; - break; - case WINDIVERT_FILTER_FIELD_TCP_SYN: - field[0] = (UINT32)tcp_header->Syn; - break; - case WINDIVERT_FILTER_FIELD_TCP_FIN: - field[0] = (UINT32)tcp_header->Fin; - break; - case WINDIVERT_FILTER_FIELD_TCP_WINDOW: - field[0] = (UINT32)RtlUshortByteSwap(tcp_header->Window); - break; - case WINDIVERT_FILTER_FIELD_TCP_CHECKSUM: - field[0] = (UINT32)RtlUshortByteSwap(tcp_header->Checksum); - break; - case WINDIVERT_FILTER_FIELD_TCP_URGPTR: - field[0] = (UINT32)RtlUshortByteSwap(tcp_header->UrgPtr); - break; - case WINDIVERT_FILTER_FIELD_TCP_PAYLOADLENGTH: - field[0] = (UINT32)payload_len; - break; - case WINDIVERT_FILTER_FIELD_UDP_SRCPORT: - field[0] = (UINT32)RtlUshortByteSwap(udp_header->SrcPort); - break; - case WINDIVERT_FILTER_FIELD_UDP_DSTPORT: - field[0] = (UINT32)RtlUshortByteSwap(udp_header->DstPort); - break; - case WINDIVERT_FILTER_FIELD_UDP_LENGTH: - field[0] = (UINT32)RtlUshortByteSwap(udp_header->Length); - break; - case WINDIVERT_FILTER_FIELD_UDP_CHECKSUM: - field[0] = (UINT32)RtlUshortByteSwap(udp_header->Checksum); - break; - case WINDIVERT_FILTER_FIELD_UDP_PAYLOADLENGTH: - field[0] = (UINT32)payload_len; - break; - case WINDIVERT_FILTER_FIELD_LOCALADDR: - big = TRUE; - switch (layer) - { - case WINDIVERT_LAYER_NETWORK: - if (ipv4) - { - field[3] = field[2] = 0; - field[1] = 0x0000FFFF; - field[0] = (UINT32)RtlUlongByteSwap( - (outbound? ip_header->SrcAddr: - ip_header->DstAddr)); - } - else if (outbound) - { - field[3] = (UINT32)RtlUlongByteSwap( - ipv6_header->SrcAddr[0]); - field[2] = (UINT32)RtlUlongByteSwap( - ipv6_header->SrcAddr[1]); - field[1] = (UINT32)RtlUlongByteSwap( - ipv6_header->SrcAddr[2]); - field[0] = (UINT32)RtlUlongByteSwap( - ipv6_header->SrcAddr[3]); - } - else - { - field[3] = (UINT32)RtlUlongByteSwap( - ipv6_header->DstAddr[0]); - field[2] = (UINT32)RtlUlongByteSwap( - ipv6_header->DstAddr[1]); - field[1] = (UINT32)RtlUlongByteSwap( - ipv6_header->DstAddr[2]); - field[0] = (UINT32)RtlUlongByteSwap( - ipv6_header->DstAddr[3]); - } - break; - case WINDIVERT_LAYER_FLOW: - field[0] = flow_data->LocalAddr[0]; - field[1] = flow_data->LocalAddr[1]; - field[2] = flow_data->LocalAddr[2]; - field[3] = flow_data->LocalAddr[3]; - break; - case WINDIVERT_LAYER_SOCKET: - field[0] = socket_data->LocalAddr[0]; - field[1] = socket_data->LocalAddr[1]; - field[2] = socket_data->LocalAddr[2]; - field[3] = socket_data->LocalAddr[3]; - break; - default: - return FALSE; - } - break; - case WINDIVERT_FILTER_FIELD_REMOTEADDR: - big = TRUE; - switch (layer) - { - case WINDIVERT_LAYER_NETWORK: - if (ipv4) - { - field[3] = field[2] = 0; - field[1] = 0x0000FFFF; - field[0] = (UINT32)RtlUlongByteSwap( - (!outbound? ip_header->SrcAddr: - ip_header->DstAddr)); - } - else if (!outbound) - { - field[3] = (UINT32)RtlUlongByteSwap( - ipv6_header->SrcAddr[0]); - field[2] = (UINT32)RtlUlongByteSwap( - ipv6_header->SrcAddr[1]); - field[1] = (UINT32)RtlUlongByteSwap( - ipv6_header->SrcAddr[2]); - field[0] = (UINT32)RtlUlongByteSwap( - ipv6_header->SrcAddr[3]); - } - else - { - field[3] = (UINT32)RtlUlongByteSwap( - ipv6_header->DstAddr[0]); - field[2] = (UINT32)RtlUlongByteSwap( - ipv6_header->DstAddr[1]); - field[1] = (UINT32)RtlUlongByteSwap( - ipv6_header->DstAddr[2]); - field[0] = (UINT32)RtlUlongByteSwap( - ipv6_header->DstAddr[3]); - } - break; - case WINDIVERT_LAYER_FLOW: - field[0] = flow_data->RemoteAddr[0]; - field[1] = flow_data->RemoteAddr[1]; - field[2] = flow_data->RemoteAddr[2]; - field[3] = flow_data->RemoteAddr[3]; - break; - case WINDIVERT_LAYER_SOCKET: - field[0] = socket_data->RemoteAddr[0]; - field[1] = socket_data->RemoteAddr[1]; - field[2] = socket_data->RemoteAddr[2]; - field[3] = socket_data->RemoteAddr[3]; - break; - default: - return FALSE; - } - break; - case WINDIVERT_FILTER_FIELD_LOCALPORT: - switch (layer) - { - case WINDIVERT_LAYER_NETWORK: - if (tcp_header != NULL) - { - field[0] = (UINT32)RtlUshortByteSwap( - (outbound? tcp_header->SrcPort: - tcp_header->DstPort)); - } - else if (udp_header != NULL) - { - field[0] = (UINT32)RtlUshortByteSwap( - (outbound? udp_header->SrcPort: - udp_header->DstPort)); - } - else if (icmp_header != NULL) - { - field[0] = (outbound? - (UINT32)icmp_header->Type: 0); - } - else if (icmpv6_header != NULL) - { - field[0] = (outbound? - (UINT32)icmpv6_header->Type: 0); - } - else - { - field[0] = 0; - } - break; - case WINDIVERT_LAYER_FLOW: - field[0] = (UINT32)flow_data->LocalPort; - break; - case WINDIVERT_LAYER_SOCKET: - field[0] = (UINT32)socket_data->LocalPort; - break; - default: - return FALSE; - } - break; - case WINDIVERT_FILTER_FIELD_REMOTEPORT: - switch (layer) - { - case WINDIVERT_LAYER_NETWORK: - if (tcp_header != NULL) - { - field[0] = (UINT32)RtlUshortByteSwap( - (!outbound? tcp_header->SrcPort: - tcp_header->DstPort)); - } - else if (udp_header != NULL) - { - field[0] = (UINT32)RtlUshortByteSwap( - (!outbound? udp_header->SrcPort: - udp_header->DstPort)); - } - else if (icmp_header != NULL) - { - field[0] = (!outbound? - (UINT32)icmp_header->Type: 0); - } - else if (icmpv6_header != NULL) - { - field[0] = (!outbound? - (UINT32)icmpv6_header->Type: 0); - } - else - { - field[0] = 0; - } - break; - case WINDIVERT_LAYER_FLOW: - field[0] = (UINT32)flow_data->RemotePort; - break; - case WINDIVERT_LAYER_SOCKET: - field[0] = (UINT32)socket_data->RemotePort; - break; - default: - return FALSE; - } - break; - case WINDIVERT_FILTER_FIELD_PROTOCOL: - switch (layer) - { - case WINDIVERT_LAYER_NETWORK: - field[0] = (UINT32)protocol; - break; - case WINDIVERT_LAYER_FLOW: - field[0] = (UINT32)flow_data->Protocol; - break; - case WINDIVERT_LAYER_SOCKET: - field[0] = (UINT32)socket_data->Protocol; - break; - default: - return FALSE; - } - break; - case WINDIVERT_FILTER_FIELD_PROCESSID: - switch (layer) - { - case WINDIVERT_LAYER_FLOW: - field[0] = flow_data->ProcessId; - break; - case WINDIVERT_LAYER_SOCKET: - field[0] = socket_data->ProcessId; - break; - case WINDIVERT_LAYER_REFLECT: - field[0] = reflect_data->ProcessId; - break; - default: - return FALSE; - } - break; - case WINDIVERT_FILTER_FIELD_ENDPOINTID: - big = TRUE; - field[2] = field[3] = 0; - switch (layer) - { - case WINDIVERT_LAYER_FLOW: - field[0] = (UINT32)flow_data->EndpointId; - field[1] = (UINT32)(flow_data->EndpointId >> 32); - break; - case WINDIVERT_LAYER_SOCKET: - field[0] = (UINT32)socket_data->EndpointId; - field[1] = (UINT32)(socket_data->EndpointId >> 32); - break; - default: - return FALSE; - } - break; - case WINDIVERT_FILTER_FIELD_PARENTENDPOINTID: - big = TRUE; - field[2] = field[3] = 0; - switch (layer) - { - case WINDIVERT_LAYER_FLOW: - field[0] = (UINT32)flow_data->ParentEndpointId; - field[1] = - (UINT32)(flow_data->ParentEndpointId >> 32); - break; - case WINDIVERT_LAYER_SOCKET: - field[0] = (UINT32)socket_data->ParentEndpointId; - field[1] = - (UINT32)(socket_data->ParentEndpointId >> 32); - break; - default: - return FALSE; - } - break; - case WINDIVERT_FILTER_FIELD_LAYER: - field[0] = (UINT32)reflect_data->Layer; - break; - case WINDIVERT_FILTER_FIELD_PRIORITY: - neg = (reflect_data->Priority < 0); - field[0] = (UINT32)(neg? -reflect_data->Priority: - reflect_data->Priority); - break; - default: - return FALSE; - } - } - if (result) - { - cmp = windivert_big_num_compare(neg, field, - (filter[ip].neg? TRUE: FALSE), filter[ip].arg, big); - switch (filter[ip].test) - { - case WINDIVERT_FILTER_TEST_EQ: - result = (cmp == 0); - break; - case WINDIVERT_FILTER_TEST_NEQ: - result = (cmp != 0); - break; - case WINDIVERT_FILTER_TEST_LT: - result = (cmp < 0); - break; - case WINDIVERT_FILTER_TEST_LEQ: - result = (cmp <= 0); - break; - case WINDIVERT_FILTER_TEST_GT: - result = (cmp > 0); - break; - case WINDIVERT_FILTER_TEST_GEQ: - result = (cmp >= 0); - break; - default: - return FALSE; - } - } - ip = (UINT16)(result? filter[ip].success: filter[ip].failure); - if (ip == WINDIVERT_FILTER_RESULT_ACCEPT) - { - return TRUE; - } - if (ip == WINDIVERT_FILTER_RESULT_REJECT) - { - return FALSE; - } - } - - DEBUG("FILTER: REJECT (filter TTL exceeded)"); - return FALSE; + return (result == 1); } /* @@ -6457,6 +5616,12 @@ static const WINDIVERT_FILTER *windivert_filter_compile( break; } + // Enforce layers: + if (!WinDivertValidateField(layer, ioctl_filter[i].field)) + { + goto windivert_filter_compile_error; + } + // Enforce ranges: neg_lb = neg_ub = 0; lb[0] = lb[1] = lb[2] = lb[3] = 0; @@ -6639,13 +5804,13 @@ static const WINDIVERT_FILTER *windivert_filter_compile( break; } neg = (ioctl_filter[i].neg? TRUE: FALSE); - result = windivert_big_num_compare(neg, ioctl_filter[i].arg, neg_lb, + result = WinDivertCompare128(neg, ioctl_filter[i].arg, neg_lb, lb, /*big=*/TRUE); if (result < 0) { goto windivert_filter_compile_error; } - result = windivert_big_num_compare(neg, ioctl_filter[i].arg, neg_ub, + result = WinDivertCompare128(neg, ioctl_filter[i].arg, neg_ub, ub, /*big=*/TRUE); if (result > 0) {