diff --git a/dll/windivert.c b/dll/windivert.c
index 62208c2..32a4da4 100644
--- a/dll/windivert.c
+++ b/dll/windivert.c
@@ -413,6 +413,7 @@ extern HANDLE WinDivertOpen(const char *filter, WINDIVERT_LAYER layer,
case WINDIVERT_LAYER_NETWORK:
case WINDIVERT_LAYER_NETWORK_FORWARD:
case WINDIVERT_LAYER_FLOW:
+ case WINDIVERT_LAYER_SOCKET:
case WINDIVERT_LAYER_REFLECT:
break;
default:
diff --git a/dll/windivert.def b/dll/windivert.def
index a36cd4a..c9c072f 100644
--- a/dll/windivert.def
+++ b/dll/windivert.def
@@ -13,6 +13,8 @@ EXPORTS
WinDivertHelperParsePacket
WinDivertHelperParseIPv4Address
WinDivertHelperParseIPv6Address
+ WinDivertHelperFormatIPv4Address
+ WinDivertHelperFormatIPv6Address
WinDivertHelperCompileFilter
WinDivertHelperEvalFilter
WinDivertHelperFormatFilter
diff --git a/dll/windivert_helper.c b/dll/windivert_helper.c
index 24d7ac0..06976a6 100644
--- a/dll/windivert_helper.c
+++ b/dll/windivert_helper.c
@@ -126,12 +126,17 @@ typedef enum
TOKEN_PROTOCOL,
TOKEN_LAYER,
TOKEN_FLOW,
+ TOKEN_SOCKET,
TOKEN_NETWORK,
TOKEN_NETWORK_FORWARD,
TOKEN_REFLECT,
TOKEN_NETWORK_PACKET,
TOKEN_FLOW_ESTABLISHED,
TOKEN_FLOW_DELETED,
+ TOKEN_SOCKET_BIND,
+ TOKEN_SOCKET_CONNECT,
+ TOKEN_SOCKET_LISTEN,
+ TOKEN_SOCKET_ACCEPT,
TOKEN_REFLECT_ESTABLISHED,
TOKEN_REFLECT_OPEN,
TOKEN_REFLECT_CLOSE,
@@ -158,13 +163,49 @@ typedef struct
UINT pos;
UINT32 val[4];
} TOKEN;
-#define TOKEN_MAXLEN 32
+#define TOKEN_MAXLEN 32
typedef struct
{
char *name;
KIND kind;
-} TOKEN_NAME, *PTOKEN_NAME;
+ 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 LN_F__ (WINDIVERT_LAYER_FLAG_NETWORK | \
+ WINDIVERT_LAYER_FLAG_FLOW)
+#define LN_FS_ (WINDIVERT_LAYER_FLAG_NETWORK | \
+ WINDIVERT_LAYER_FLAG_FLOW | \
+ WINDIVERT_LAYER_FLAG_SOCKET)
+#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.
@@ -280,11 +321,11 @@ static UINT8 WinDivertSkipExtHeaders(UINT8 proto, UINT8 **header, UINT *len)
/*
* Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet.
*/
-extern BOOL WinDivertHelperParsePacket(PVOID pPacket, UINT packetLen,
+static BOOL WinDivertHelperParsePacket_2(PVOID pPacket, UINT packetLen,
PWINDIVERT_IPHDR *ppIpHdr, PWINDIVERT_IPV6HDR *ppIpv6Hdr,
PWINDIVERT_ICMPHDR *ppIcmpHdr, PWINDIVERT_ICMPV6HDR *ppIcmpv6Hdr,
- PWINDIVERT_TCPHDR *ppTcpHdr, PWINDIVERT_UDPHDR *ppUdpHdr, PVOID *ppData,
- UINT *pDataLen)
+ PWINDIVERT_TCPHDR *ppTcpHdr, PWINDIVERT_UDPHDR *ppUdpHdr, UINT8 *pProto,
+ PVOID *ppData, UINT *pDataLen)
{
PWINDIVERT_IPHDR ip_header = NULL;
PWINDIVERT_IPV6HDR ipv6_header = NULL;
@@ -293,7 +334,7 @@ extern BOOL WinDivertHelperParsePacket(PVOID pPacket, UINT packetLen,
PWINDIVERT_TCPHDR tcp_header = NULL;
PWINDIVERT_UDPHDR udp_header = NULL;
UINT16 header_len;
- UINT8 trans_proto;
+ UINT8 trans_proto = 0;
PVOID data = NULL;
UINT data_len = 0;
BOOL success;
@@ -431,6 +472,10 @@ WinDivertHelperParsePacketExit:
*ppUdpHdr = udp_header;
success = success && (udp_header != NULL);
}
+ if (pProto != NULL)
+ {
+ *pProto = trans_proto;
+ }
if (ppData != NULL)
{
*ppData = data;
@@ -443,6 +488,20 @@ WinDivertHelperParsePacketExit:
return success;
}
+/*
+ * Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet.
+ */
+extern BOOL WinDivertHelperParsePacket(PVOID pPacket, UINT packetLen,
+ PWINDIVERT_IPHDR *ppIpHdr, PWINDIVERT_IPV6HDR *ppIpv6Hdr,
+ PWINDIVERT_ICMPHDR *ppIcmpHdr, PWINDIVERT_ICMPV6HDR *ppIcmpv6Hdr,
+ PWINDIVERT_TCPHDR *ppTcpHdr, PWINDIVERT_UDPHDR *ppUdpHdr, PVOID *ppData,
+ UINT *pDataLen)
+{
+ return WinDivertHelperParsePacket_2(pPacket, packetLen, ppIpHdr,
+ ppIpv6Hdr, ppIcmpHdr, ppIcmpv6Hdr, ppTcpHdr, ppUdpHdr, NULL,
+ ppData, pDataLen);
+}
+
/*
* Calculate IPv4/IPv6/ICMP/ICMPv6/TCP/UDP checksums.
*/
@@ -461,8 +520,8 @@ extern UINT WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
UINT payload_len, checksum_len;
UINT count = 0;
- WinDivertHelperParsePacket(pPacket, packetLen, &ip_header, &ipv6_header,
- &icmp_header, &icmpv6_header, &tcp_header, &udp_header, NULL,
+ WinDivertHelperParsePacket_2(pPacket, packetLen, &ip_header, &ipv6_header,
+ &icmp_header, &icmpv6_header, &tcp_header, &udp_header, NULL, NULL,
&payload_len);
if (ip_header != NULL && !(flags & WINDIVERT_HELPER_NO_IP_CHECKSUM))
@@ -675,15 +734,15 @@ extern BOOL WinDivertHelperParseIPv4Address(const char *str, UINT32 *addr_ptr)
*/
extern BOOL WinDivertHelperParseIPv6Address(const char *str, UINT32 *addr_ptr)
{
- UINT16 laddr[8];
- UINT16 raddr[8];
- BOOL left = TRUE;
+ UINT16 laddr[8] = {0};
+ UINT16 raddr[8] = {0};
+ UINT32 addr[4];
+ BOOL left = TRUE, ipv4 = FALSE;
+ UINT32 ipv4_addr;
UINT i, j, k, l, part;
char part_str[5];
- memset(laddr, 0, sizeof(laddr));
- memset(raddr, 0, sizeof(raddr));
-
+ j = 0;
if (*str == ':')
{
str++;
@@ -694,9 +753,13 @@ extern BOOL WinDivertHelperParseIPv6Address(const char *str, UINT32 *addr_ptr)
}
left = FALSE;
str++;
+ if (*str == '\0')
+ {
+ goto WinDivertHelperParseIPv6AddressSuccess;
+ }
}
- for (i = 0, j = 0, k = 0; k < 8; k++)
+ for (i = 0, k = 0; k < 8; k++)
{
if (*str == ':')
{
@@ -707,6 +770,18 @@ extern BOOL WinDivertHelperParseIPv6Address(const char *str, UINT32 *addr_ptr)
}
left = FALSE;
str++;
+ if (*str == '\0')
+ {
+ break;
+ }
+ }
+
+ if (i < 6 && WinDivertHelperParseIPv4Address(str, &ipv4_addr))
+ {
+ // Tail is IPv4 address:
+ ipv4 = TRUE;
+ j += 2;
+ goto WinDivertHelperParseIPv6AddressSuccess;
}
for (l = 0; l < 4 && WinDivertIsXDigit(*str); l++)
{
@@ -735,11 +810,7 @@ extern BOOL WinDivertHelperParseIPv6Address(const char *str, UINT32 *addr_ptr)
}
if (*str == '\0')
{
- if (!left)
- {
- break;
- }
- if (k == 7)
+ if (!left || k == 7)
{
break;
}
@@ -748,44 +819,55 @@ extern BOOL WinDivertHelperParseIPv6Address(const char *str, UINT32 *addr_ptr)
}
str++;
}
- if (*str != '\0')
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
-
- if (addr_ptr == NULL)
+
+WinDivertHelperParseIPv6AddressSuccess:
+
+ if (!ipv4 && addr_ptr == NULL)
{
return TRUE;
}
-
for (i = 0; i < 4; i++)
{
k = 2 * i + j;
l = k + 1;
k = (k >= 8? k - 8: k);
l = (l >= 8? l - 8: l);
- addr_ptr[3 - i] =
+ addr[3 - i] =
(UINT32)laddr[2 * i + 1] |
(UINT32)laddr[2 * i] << 16 |
(UINT32)raddr[l] |
(UINT32)raddr[k] << 16;
}
+ if (ipv4)
+ {
+ // Validate IPv4 address
+ if (addr[3] != 0 || addr[2] != 0 || addr[0] != 0 ||
+ (addr[1] != 0x0000FFFF && addr[1] != 0))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ addr[0] = ipv4_addr;
+ }
+ if (addr_ptr != NULL)
+ {
+ memcpy(addr_ptr, addr, sizeof(addr));
+ }
return TRUE;
}
/*
* Lookup a token.
*/
-static PTOKEN_NAME WinDivertTokenLookup(PTOKEN_NAME token_names,
- size_t token_names_len, const char *name)
+static PTOKEN_INFO WinDivertTokenLookup(PTOKEN_INFO token_info,
+ size_t token_info_len, const char *name)
{
- int lo = 0, hi = (int)token_names_len-1, mid;
+ int lo = 0, hi = (int)token_info_len-1, mid;
int cmp;
while (hi >= lo)
{
mid = (lo + hi) / 2;
- cmp = WinDivertStrCmp(token_names[mid].name, name);
+ cmp = WinDivertStrCmp(token_info[mid].name, name);
if (cmp < 0)
{
lo = mid+1;
@@ -796,191 +878,12 @@ static PTOKEN_NAME WinDivertTokenLookup(PTOKEN_NAME token_names,
}
else
{
- return &token_names[mid];
+ return &token_info[mid];
}
}
return NULL;
}
-/*
- * Validate token for layer.
- */
-static BOOL WinDivertCheckTokenKindForLayer(WINDIVERT_LAYER layer, KIND kind)
-{
- switch (layer)
- {
- case WINDIVERT_LAYER_NETWORK:
- case WINDIVERT_LAYER_NETWORK_FORWARD:
- switch (kind)
- {
- case TOKEN_INBOUND:
- case TOKEN_OUTBOUND:
- return (layer != WINDIVERT_LAYER_NETWORK_FORWARD);
- case TOKEN_PROCESS_ID:
- case TOKEN_LOCAL_ADDR:
- case TOKEN_REMOTE_ADDR:
- case TOKEN_LOCAL_PORT:
- case TOKEN_REMOTE_PORT:
- case TOKEN_PROTOCOL:
- case TOKEN_LAYER:
- case TOKEN_FLOW:
- case TOKEN_NETWORK:
- case TOKEN_NETWORK_FORWARD:
- case TOKEN_REFLECT:
- case TOKEN_FLOW_ESTABLISHED:
- case TOKEN_FLOW_DELETED:
- case TOKEN_REFLECT_ESTABLISHED:
- case TOKEN_REFLECT_OPEN:
- case TOKEN_REFLECT_CLOSE:
- return FALSE;
- default:
- return TRUE;
- }
- case WINDIVERT_LAYER_FLOW:
- switch (kind)
- {
- case TOKEN_ICMP_BODY:
- case TOKEN_ICMP_CHECKSUM:
- case TOKEN_ICMP_CODE:
- case TOKEN_ICMP_TYPE:
- case TOKEN_ICMPV6_BODY:
- case TOKEN_ICMPV6_CHECKSUM:
- case TOKEN_ICMPV6_CODE:
- case TOKEN_ICMPV6_TYPE:
- case TOKEN_IP_CHECKSUM:
- case TOKEN_IP_DF:
- case TOKEN_IP_DST_ADDR:
- case TOKEN_IP_FRAG_OFF:
- case TOKEN_IP_HDR_LENGTH:
- case TOKEN_IP_ID:
- case TOKEN_IP_LENGTH:
- case TOKEN_IP_MF:
- case TOKEN_IP_PROTOCOL:
- case TOKEN_IP_SRC_ADDR:
- case TOKEN_IP_TOS:
- case TOKEN_IP_TTL:
- case TOKEN_IPV6_DST_ADDR:
- case TOKEN_IPV6_FLOW_LABEL:
- case TOKEN_IPV6_HOP_LIMIT:
- case TOKEN_IPV6_LENGTH:
- case TOKEN_IPV6_NEXT_HDR:
- case TOKEN_IPV6_SRC_ADDR:
- case TOKEN_IPV6_TRAFFIC_CLASS:
- case TOKEN_TCP_ACK:
- case TOKEN_TCP_ACK_NUM:
- case TOKEN_TCP_CHECKSUM:
- case TOKEN_TCP_DST_PORT:
- case TOKEN_TCP_FIN:
- case TOKEN_TCP_HDR_LENGTH:
- case TOKEN_TCP_PAYLOAD_LENGTH:
- case TOKEN_TCP_PSH:
- case TOKEN_TCP_RST:
- case TOKEN_TCP_SEQ_NUM:
- case TOKEN_TCP_SRC_PORT:
- case TOKEN_TCP_SYN:
- case TOKEN_TCP_URG:
- case TOKEN_TCP_URG_PTR:
- case TOKEN_TCP_WINDOW:
- case TOKEN_UDP_CHECKSUM:
- case TOKEN_UDP_DST_PORT:
- case TOKEN_UDP_LENGTH:
- case TOKEN_UDP_PAYLOAD_LENGTH:
- case TOKEN_UDP_SRC_PORT:
- case TOKEN_IF_IDX:
- case TOKEN_SUB_IF_IDX:
- case TOKEN_IMPOSTOR:
- case TOKEN_LAYER:
- case TOKEN_FLOW:
- case TOKEN_NETWORK:
- case TOKEN_NETWORK_FORWARD:
- case TOKEN_REFLECT:
- case TOKEN_NETWORK_PACKET:
- case TOKEN_REFLECT_ESTABLISHED:
- case TOKEN_REFLECT_OPEN:
- case TOKEN_REFLECT_CLOSE:
- return FALSE;
- default:
- return TRUE;
- }
- case WINDIVERT_LAYER_REFLECT:
- switch (kind)
- {
- case TOKEN_ICMP_BODY:
- case TOKEN_ICMP_CHECKSUM:
- case TOKEN_ICMP_CODE:
- case TOKEN_ICMP_TYPE:
- case TOKEN_ICMPV6_BODY:
- case TOKEN_ICMPV6_CHECKSUM:
- case TOKEN_ICMPV6_CODE:
- case TOKEN_ICMPV6_TYPE:
- case TOKEN_IP_CHECKSUM:
- case TOKEN_IP_DF:
- case TOKEN_IP_DST_ADDR:
- case TOKEN_IP_FRAG_OFF:
- case TOKEN_IP_HDR_LENGTH:
- case TOKEN_IP_ID:
- case TOKEN_IP_LENGTH:
- case TOKEN_IP_MF:
- case TOKEN_IP_PROTOCOL:
- case TOKEN_IP_SRC_ADDR:
- case TOKEN_IP_TOS:
- case TOKEN_IP_TTL:
- case TOKEN_IPV6_DST_ADDR:
- case TOKEN_IPV6_FLOW_LABEL:
- case TOKEN_IPV6_HOP_LIMIT:
- case TOKEN_IPV6_LENGTH:
- case TOKEN_IPV6_NEXT_HDR:
- case TOKEN_IPV6_SRC_ADDR:
- case TOKEN_IPV6_TRAFFIC_CLASS:
- case TOKEN_TCP_ACK:
- case TOKEN_TCP_ACK_NUM:
- case TOKEN_TCP_CHECKSUM:
- case TOKEN_TCP_DST_PORT:
- case TOKEN_TCP_FIN:
- case TOKEN_TCP_HDR_LENGTH:
- case TOKEN_TCP_PAYLOAD_LENGTH:
- case TOKEN_TCP_PSH:
- case TOKEN_TCP_RST:
- case TOKEN_TCP_SEQ_NUM:
- case TOKEN_TCP_SRC_PORT:
- case TOKEN_TCP_SYN:
- case TOKEN_TCP_URG:
- case TOKEN_TCP_URG_PTR:
- case TOKEN_TCP_WINDOW:
- case TOKEN_UDP_CHECKSUM:
- case TOKEN_UDP_DST_PORT:
- case TOKEN_UDP_LENGTH:
- case TOKEN_UDP_PAYLOAD_LENGTH:
- case TOKEN_UDP_SRC_PORT:
- case TOKEN_IP:
- case TOKEN_IPV6:
- case TOKEN_ICMP:
- case TOKEN_ICMPV6:
- case TOKEN_TCP:
- case TOKEN_UDP:
- case TOKEN_LOOPBACK:
- case TOKEN_IF_IDX:
- case TOKEN_SUB_IF_IDX:
- case TOKEN_IMPOSTOR:
- case TOKEN_INBOUND:
- case TOKEN_OUTBOUND:
- case TOKEN_LOCAL_ADDR:
- case TOKEN_REMOTE_ADDR:
- case TOKEN_LOCAL_PORT:
- case TOKEN_REMOTE_PORT:
- case TOKEN_PROTOCOL:
- case TOKEN_NETWORK_PACKET:
- case TOKEN_FLOW_ESTABLISHED:
- case TOKEN_FLOW_DELETED:
- return FALSE;
- default:
- return TRUE;
- }
- default:
- return FALSE;
- }
-}
-
/*
* Expand a "macro" value.
*/
@@ -997,6 +900,9 @@ static BOOL WinDivertExpandMacro(KIND kind, UINT32 *val)
case TOKEN_FLOW:
*val = WINDIVERT_LAYER_FLOW;
return TRUE;
+ case TOKEN_SOCKET:
+ *val = WINDIVERT_LAYER_SOCKET;
+ return TRUE;
case TOKEN_REFLECT:
*val = WINDIVERT_LAYER_REFLECT;
return TRUE;
@@ -1009,6 +915,18 @@ static BOOL WinDivertExpandMacro(KIND kind, UINT32 *val)
case TOKEN_FLOW_DELETED:
*val = WINDIVERT_EVENT_FLOW_DELETED;
return TRUE;
+ case TOKEN_SOCKET_BIND:
+ *val = WINDIVERT_EVENT_SOCKET_BIND;
+ return TRUE;
+ case TOKEN_SOCKET_CONNECT:
+ *val = WINDIVERT_EVENT_SOCKET_CONNECT;
+ return TRUE;
+ case TOKEN_SOCKET_LISTEN:
+ *val = WINDIVERT_EVENT_SOCKET_LISTEN;
+ return TRUE;
+ case TOKEN_SOCKET_ACCEPT:
+ *val = WINDIVERT_EVENT_SOCKET_ACCEPT;
+ return TRUE;
case TOKEN_REFLECT_ESTABLISHED:
*val = WINDIVERT_EVENT_REFLECT_ESTABLISHED;
return TRUE;
@@ -1029,93 +947,98 @@ static BOOL WinDivertExpandMacro(KIND kind, UINT32 *val)
static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer,
TOKEN *tokens, UINT tokensmax)
{
- static const TOKEN_NAME token_names[] =
+ static const TOKEN_INFO token_info[] =
{
- {"FLOW", TOKEN_FLOW},
- {"FLOW_DELETED", TOKEN_FLOW_DELETED},
- {"FLOW_ESTABLISHED", TOKEN_FLOW_ESTABLISHED},
- {"NETWORK", TOKEN_NETWORK},
- {"NETWORK_FORWARD", TOKEN_NETWORK_FORWARD},
- {"NETWORK_PACKET", TOKEN_NETWORK_PACKET},
- {"REFLECT", TOKEN_REFLECT},
- {"REFLECT_CLOSE", TOKEN_REFLECT_CLOSE},
- {"REFLECT_ESTABLISHED", TOKEN_REFLECT_ESTABLISHED},
- {"REFLECT_OPEN", TOKEN_REFLECT_OPEN},
- {"and", TOKEN_AND},
- {"event", TOKEN_EVENT},
- {"false", TOKEN_FALSE},
- {"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},
- {"localAddr", TOKEN_LOCAL_ADDR},
- {"localPort", TOKEN_LOCAL_PORT},
- {"loopback", TOKEN_LOOPBACK},
- {"not", TOKEN_NOT},
- {"or", TOKEN_OR},
- {"outbound", TOKEN_OUTBOUND},
- {"processId", TOKEN_PROCESS_ID},
- {"protocol", TOKEN_PROTOCOL},
- {"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.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},
- {"true", TOKEN_TRUE},
- {"udp", TOKEN_UDP},
- {"udp.Checksum", TOKEN_UDP_CHECKSUM},
- {"udp.DstPort", TOKEN_UDP_DST_PORT},
- {"udp.Length", TOKEN_UDP_LENGTH},
- {"udp.PayloadLength", TOKEN_UDP_PAYLOAD_LENGTH},
- {"udp.SrcPort", TOKEN_UDP_SRC_PORT},
- {"zero", TOKEN_ZERO},
+ {"FLOW", TOKEN_FLOW, L____R},
+ {"FLOW_DELETED", TOKEN_FLOW_DELETED, L__F__},
+ {"FLOW_ESTABLISHED", TOKEN_FLOW_ESTABLISHED, L__F__},
+ {"NETWORK", TOKEN_NETWORK, L____R},
+ {"NETWORK_FORWARD", TOKEN_NETWORK_FORWARD, L____R},
+ {"NETWORK_PACKET", TOKEN_NETWORK_PACKET, LNM___},
+ {"REFLECT", TOKEN_REFLECT, L____R},
+ {"REFLECT_CLOSE", TOKEN_REFLECT_CLOSE, L____R},
+ {"REFLECT_ESTABLISHED", TOKEN_REFLECT_ESTABLISHED, L____R},
+ {"REFLECT_OPEN", TOKEN_REFLECT_OPEN, L____R},
+ {"SOCKET", TOKEN_SOCKET, L____R},
+ {"SOCKET_ACCEPT", TOKEN_SOCKET_ACCEPT, L___S_},
+ {"SOCKET_BIND", TOKEN_SOCKET_BIND, L___S_},
+ {"SOCKET_CONNECT", TOKEN_SOCKET_CONNECT, L___S_},
+ {"SOCKET_LISTEN", TOKEN_SOCKET_LISTEN, L___S_},
+ {"and", TOKEN_AND, LNMFSR},
+ {"event", TOKEN_EVENT, LNMFSR},
+ {"false", TOKEN_FALSE, LNMFSR},
+ {"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_F__},
+ {"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},
+ {"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_F__},
+ {"processId", TOKEN_PROCESS_ID, L__FSR},
+ {"protocol", TOKEN_PROTOCOL, LN_FS_},
+ {"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.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___},
+ {"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.PayloadLength", TOKEN_UDP_PAYLOAD_LENGTH, LNM___},
+ {"udp.SrcPort", TOKEN_UDP_SRC_PORT, LNM___},
+ {"zero", TOKEN_ZERO, LNMFSR},
};
- TOKEN_NAME *result;
+ TOKEN_INFO *result;
char c;
char token[TOKEN_MAXLEN];
UINT i = 0, j;
@@ -1240,11 +1163,11 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer,
}
// Check for symbol:
- result = WinDivertTokenLookup((PTOKEN_NAME)token_names,
- sizeof(token_names) / sizeof(TOKEN_NAME), token);
+ result = WinDivertTokenLookup((PTOKEN_INFO)token_info,
+ sizeof(token_info) / sizeof(TOKEN_INFO), token);
if (result != NULL)
{
- if (!WinDivertCheckTokenKindForLayer(layer, result->kind))
+ if ((result->flags & (1 << layer)) == 0)
{
return MAKE_ERROR(WINDIVERT_ERROR_BAD_TOKEN_FOR_LAYER, i-j);
}
@@ -2618,6 +2541,7 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, PVOID packet,
PWINDIVERT_ICMPV6HDR icmpv6hdr = NULL;
PWINDIVERT_TCPHDR tcphdr = NULL;
PWINDIVERT_UDPHDR udphdr = NULL;
+ UINT8 protocol = 0;
UINT payload_len;
UINT32 val[4];
BOOL pass;
@@ -2639,8 +2563,9 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, PVOID packet,
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
- WinDivertHelperParsePacket(packet, packet_len, &iphdr, &ipv6hdr,
- &icmphdr, &icmpv6hdr, &tcphdr, &udphdr, NULL, &payload_len);
+ WinDivertHelperParsePacket_2(packet, packet_len, &iphdr, &ipv6hdr,
+ &icmphdr, &icmpv6hdr, &tcphdr, &udphdr, &protocol, NULL,
+ &payload_len);
if ((addr->IPv6 && ipv6hdr == NULL) ||
(!addr->IPv6 && iphdr == NULL))
{
@@ -2649,6 +2574,7 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, PVOID packet,
}
break;
case WINDIVERT_LAYER_FLOW:
+ case WINDIVERT_LAYER_SOCKET:
if (packet != NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
@@ -2689,6 +2615,47 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, PVOID packet,
pass = TRUE;
switch (object[pc].field)
{
+ case WINDIVERT_FILTER_FIELD_ZERO:
+ case WINDIVERT_FILTER_FIELD_EVENT:
+ 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_IFIDX:
+ case WINDIVERT_FILTER_FIELD_SUBIFIDX:
+ 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_PROCESSID:
+ pass = (addr->Layer == WINDIVERT_LAYER_FLOW ||
+ addr->Layer == WINDIVERT_LAYER_SOCKET ||
+ addr->Layer == WINDIVERT_LAYER_REFLECT);
+ break;
+ case WINDIVERT_FILTER_FIELD_LAYER:
+ 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:
@@ -2701,7 +2668,9 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, PVOID packet,
case WINDIVERT_FILTER_FIELD_IP_CHECKSUM:
case WINDIVERT_FILTER_FIELD_IP_SRCADDR:
case WINDIVERT_FILTER_FIELD_IP_DSTADDR:
- pass = (iphdr != NULL);
+ 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:
@@ -2710,19 +2679,25 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, PVOID packet,
case WINDIVERT_FILTER_FIELD_IPV6_HOPLIMIT:
case WINDIVERT_FILTER_FIELD_IPV6_SRCADDR:
case WINDIVERT_FILTER_FIELD_IPV6_DSTADDR:
- pass = (ipv6hdr != NULL);
+ 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 = (icmphdr != NULL);
+ 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 = (icmpv6hdr != NULL);
+ 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:
@@ -2739,35 +2714,22 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, PVOID packet,
case WINDIVERT_FILTER_FIELD_TCP_CHECKSUM:
case WINDIVERT_FILTER_FIELD_TCP_URGPTR:
case WINDIVERT_FILTER_FIELD_TCP_PAYLOADLENGTH:
- pass = (tcphdr != NULL);
+ 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_PAYLOADLENGTH:
- pass = (udphdr != NULL);
- break;
- case WINDIVERT_FILTER_FIELD_INBOUND:
- case WINDIVERT_FILTER_FIELD_OUTBOUND:
- pass = (addr->Layer != WINDIVERT_LAYER_NETWORK_FORWARD);
- break;
- case WINDIVERT_FILTER_FIELD_IFIDX:
- case WINDIVERT_FILTER_FIELD_SUBIFIDX:
pass = (addr->Layer == WINDIVERT_LAYER_NETWORK ||
addr->Layer == WINDIVERT_LAYER_NETWORK_FORWARD);
- break;
- case WINDIVERT_FILTER_FIELD_PROCESSID:
- 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_FLOW);
+ pass = pass && (udphdr != NULL);
break;
default:
- pass = TRUE;
- break;
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
}
if (!pass)
{
@@ -2808,20 +2770,80 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, PVOID packet,
val[0] = addr->IPv6;
break;
case WINDIVERT_FILTER_FIELD_ICMP:
- val[0] = (addr->Layer == WINDIVERT_LAYER_FLOW?
- addr->Flow.Protocol == IPPROTO_ICMP: icmphdr != NULL);
+ 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);
+ return FALSE;
+ }
break;
case WINDIVERT_FILTER_FIELD_ICMPV6:
- val[0] = (addr->Layer == WINDIVERT_LAYER_FLOW?
- addr->Flow.Protocol == IPPROTO_ICMPV6: icmpv6hdr != NULL);
+ 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);
+ return FALSE;
+ }
break;
case WINDIVERT_FILTER_FIELD_TCP:
- val[0] = (addr->Layer == WINDIVERT_LAYER_FLOW?
- addr->Flow.Protocol == IPPROTO_TCP: tcphdr != NULL);
+ 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);
+ return FALSE;
+ }
break;
case WINDIVERT_FILTER_FIELD_UDP:
- val[0] = (addr->Layer == WINDIVERT_LAYER_FLOW?
- addr->Flow.Protocol == IPPROTO_UDP: udphdr != NULL);
+ 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);
+ return FALSE;
+ }
break;
case WINDIVERT_FILTER_FIELD_IP_HDRLENGTH:
val[0] = iphdr->HdrLength;
@@ -2972,29 +2994,183 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, PVOID packet,
case WINDIVERT_FILTER_FIELD_UDP_PAYLOADLENGTH:
val[0] = payload_len;
break;
- case WINDIVERT_FILTER_FIELD_PROCESSID:
- val[0] = addr->Flow.ProcessId;
- break;
case WINDIVERT_FILTER_FIELD_LOCALADDR:
- val[0] = addr->Flow.LocalAddr[0];
- val[1] = addr->Flow.LocalAddr[1];
- val[2] = addr->Flow.LocalAddr[2];
- val[3] = addr->Flow.LocalAddr[3];
+ switch (addr->Layer)
+ {
+ case WINDIVERT_LAYER_NETWORK:
+ if (!addr->IPv6)
+ {
+ 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);
+ return FALSE;
+ }
break;
case WINDIVERT_FILTER_FIELD_REMOTEADDR:
- val[0] = addr->Flow.RemoteAddr[0];
- val[1] = addr->Flow.RemoteAddr[1];
- val[2] = addr->Flow.RemoteAddr[2];
- val[3] = addr->Flow.RemoteAddr[3];
+ switch (addr->Layer)
+ {
+ case WINDIVERT_LAYER_NETWORK:
+ if (!addr->IPv6)
+ {
+ 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);
+ return FALSE;
+ }
break;
case WINDIVERT_FILTER_FIELD_LOCALPORT:
- val[0] = addr->Flow.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
+ {
+ 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);
+ return FALSE;
+ }
break;
case WINDIVERT_FILTER_FIELD_REMOTEPORT:
- val[0] = addr->Flow.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
+ {
+ 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);
+ return FALSE;
+ }
break;
case WINDIVERT_FILTER_FIELD_PROTOCOL:
- val[0] = addr->Flow.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);
+ return FALSE;
+ }
+ 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);
+ return FALSE;
+ }
break;
default:
SetLastError(ERROR_INVALID_PARAMETER);
@@ -3736,6 +3912,48 @@ static void WinDivertFormatIPv6Addr(PWINDIVERT_STREAM stream,
}
}
+/*
+ * Format an IPv4 address.
+ */
+extern BOOL WinDivertHelperFormatIPv4Address(UINT32 addr, char *buffer,
+ UINT bufLen)
+{
+ WINDIVERT_STREAM stream;
+ stream.data = buffer;
+ stream.pos = 0;
+ stream.max = bufLen;
+ stream.overflow = FALSE;
+ WinDivertFormatIPv4Addr(&stream, addr);
+ WinDivertPutNul(&stream);
+ if (stream.overflow)
+ {
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*
+ * Format an IPv6 address.
+ */
+extern BOOL WinDivertHelperFormatIPv6Address(const UINT32 *addr, char *buffer,
+ UINT bufLen)
+{
+ WINDIVERT_STREAM stream;
+ stream.data = buffer;
+ stream.pos = 0;
+ stream.max = bufLen;
+ stream.overflow = FALSE;
+ WinDivertFormatIPv6Addr(&stream, addr);
+ WinDivertPutNul(&stream);
+ if (stream.overflow)
+ {
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return FALSE;
+ }
+ return TRUE;
+}
+
/*
* Format a test expression.
*/
@@ -3840,6 +4058,8 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr)
WinDivertPutString(stream, "NETWORK_FORWARD"); break;
case WINDIVERT_LAYER_FLOW:
WinDivertPutString(stream, "FLOW"); break;
+ case WINDIVERT_LAYER_SOCKET:
+ WinDivertPutString(stream, "SOCKET"); break;
case WINDIVERT_LAYER_REFLECT:
WinDivertPutString(stream, "REFLECT"); break;
default:
@@ -3856,6 +4076,14 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr)
WinDivertPutString(stream, "FLOW_ESTABLISHED"); break;
case WINDIVERT_EVENT_FLOW_DELETED:
WinDivertPutString(stream, "FLOW_DELETED"); break;
+ case WINDIVERT_EVENT_SOCKET_BIND:
+ WinDivertPutString(stream, "SOCKET_BIND"); break;
+ case WINDIVERT_EVENT_SOCKET_CONNECT:
+ WinDivertPutString(stream, "SOCKET_CONNECT"); break;
+ case WINDIVERT_EVENT_SOCKET_LISTEN:
+ WinDivertPutString(stream, "SOCKET_LISTEN"); break;
+ case WINDIVERT_EVENT_SOCKET_ACCEPT:
+ WinDivertPutString(stream, "SOCKET_ACCEPT"); break;
case WINDIVERT_EVENT_REFLECT_ESTABLISHED:
WinDivertPutString(stream, "REFLECT_ESTABLISHED"); break;
case WINDIVERT_EVENT_REFLECT_OPEN:
@@ -4175,7 +4403,7 @@ BOOL WinDivertHelperFormatFilter(const char *filter, WINDIVERT_LAYER layer,
stream.max = buflen;
stream.overflow = FALSE;
WinDivertFormatExpr(&stream, expr, /*top_level=*/TRUE, /*and=*/FALSE);
- WinDivertPutChar(&stream, '\0');
+ WinDivertPutNul(&stream);
// Clean-up:
HeapDestroy(pool);
diff --git a/examples/flowtrack/flowtrack.c b/examples/flowtrack/flowtrack.c
index 83a1774..c0e935e 100644
--- a/examples/flowtrack/flowtrack.c
+++ b/examples/flowtrack/flowtrack.c
@@ -1,5 +1,5 @@
/*
- * streamdump.c
+ * flowtrack.c
* (C) 2018, all rights reserved,
*
* This file is part of WinDivert.
@@ -47,7 +47,8 @@
#include "windivert.h"
-#define MAX_FLOWS 256
+#define MAX_FLOWS 256
+#define INET6_ADDRSTRLEN 45
/*
* Flow tracking.
@@ -61,39 +62,6 @@ typedef struct FLOW
static HANDLE lock;
static PFLOW flows = NULL;
-/*
- * Print an IP address.
- */
-static void print_address(const UINT32 *addr)
-{
- if (addr[3] == 0 && addr[2] == 0 && addr[1] == 0x0000FFFF)
- {
- // IPv4 address:
- UINT32 a, b, c, d;
- a = (addr[0] >> 24) & 0xFF;
- b = (addr[0] >> 16) & 0xFF;
- c = (addr[0] >> 8) & 0xFF;
- d = (addr[0] >> 0) & 0xFF;
- printf("%u.%u.%u.%u", a, b, c, d);
- }
- else
- {
- // IPv6 address:
- int i;
- for (i = 3; i >= 0; i--)
- {
- UINT32 a, b;
- a = (addr[i] >> 16) & 0xFFFF;
- b = (addr[i] >> 0) & 0xFFFF;
- printf("%x:%x", a, b);
- if (i != 0)
- {
- putchar(':');
- }
- }
- }
-}
-
/*
* Draw flows to console in a delayed loop.
*
@@ -105,6 +73,7 @@ static DWORD draw(LPVOID arg)
HANDLE process, console = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO screen;
char path[MAX_PATH+1];
+ char addr_str[INET6_ADDRSTRLEN+1];
char *filename;
const char header[] = "PID PROGRAM PROT FLOW";
DWORD rows, columns, written, fill_len, path_len, i;
@@ -216,11 +185,13 @@ static DWORD draw(LPVOID arg)
}
SetConsoleTextAttribute(console,
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
- print_address(addr->Flow.LocalAddr);
- printf(":%u %s ", addr->Flow.LocalPort,
+ WinDivertHelperFormatIPv6Address(addr->Flow.LocalAddr, addr_str,
+ sizeof(addr_str));
+ printf("%s:%u %s ", addr_str, addr->Flow.LocalPort,
(addr->Outbound? "---->": "<----"));
- print_address(addr->Flow.RemoteAddr);
- printf(":%u", addr->Flow.RemotePort);
+ WinDivertHelperFormatIPv6Address(addr->Flow.RemoteAddr, addr_str,
+ sizeof(addr_str));
+ printf("%s:%u", addr_str, addr->Flow.RemotePort);
fflush(stdout);
}
for (; i < rows-1; i++)
diff --git a/examples/netdump/netdump.c b/examples/netdump/netdump.c
index 1785c93..c07f2ef 100644
--- a/examples/netdump/netdump.c
+++ b/examples/netdump/netdump.c
@@ -49,7 +49,8 @@
#include "windivert.h"
-#define MAXBUF 0xFFFF
+#define MAXBUF 0xFFFF
+#define INET6_ADDRSTRLEN 45
/*
* Entry.
@@ -68,6 +69,7 @@ int __cdecl main(int argc, char **argv)
PWINDIVERT_ICMPV6HDR icmpv6_header;
PWINDIVERT_TCPHDR tcp_header;
PWINDIVERT_UDPHDR udp_header;
+ char src_str[INET6_ADDRSTRLEN+1], dst_str[INET6_ADDRSTRLEN+1];
const char *err_str;
LARGE_INTEGER base, freq;
double time_passed;
@@ -166,16 +168,19 @@ int __cdecl main(int argc, char **argv)
FOREGROUND_GREEN | FOREGROUND_RED);
printf("IPv4 [Version=%u HdrLength=%u TOS=%u Length=%u Id=0x%.4X "
"Reserved=%u DF=%u MF=%u FragOff=%u TTL=%u Protocol=%u "
- "Checksum=0x%.4X SrcAddr=%u.%u.%u.%u DstAddr=%u.%u.%u.%u]\n",
+ "Checksum=0x%.4X SrcAddr=%s DstAddr=%s]\n",
ip_header->Version, ip_header->HdrLength,
ntohs(ip_header->TOS), ntohs(ip_header->Length),
ntohs(ip_header->Id), WINDIVERT_IPHDR_GET_RESERVED(ip_header),
WINDIVERT_IPHDR_GET_DF(ip_header),
WINDIVERT_IPHDR_GET_MF(ip_header),
ntohs(WINDIVERT_IPHDR_GET_FRAGOFF(ip_header)), ip_header->TTL,
- ip_header->Protocol, ntohs(ip_header->Checksum),
- src_addr[0], src_addr[1], src_addr[2], src_addr[3],
- dst_addr[0], dst_addr[1], dst_addr[2], dst_addr[3]);
+ ip_header->Protocol, ntohs(ip_header->Checksum));
+ WinDivertHelperFormatIPv4Address(ntohl(ip_header->SrcAddr),
+ src_str, sizeof(src_str));
+ WinDivertHelperFormatIPv4Address(ntohl(ip_header->DstAddr),
+ dst_str, sizeof(dst_str));
+
}
if (ipv6_header != NULL)
{
diff --git a/examples/socketdump/socketdump.c b/examples/socketdump/socketdump.c
new file mode 100644
index 0000000..705b73a
--- /dev/null
+++ b/examples/socketdump/socketdump.c
@@ -0,0 +1,210 @@
+/*
+ * socketdump.c
+ * (C) 2018, all rights reserved,
+ *
+ * This file is part of WinDivert.
+ *
+ * WinDivert is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ *
+ * WinDivert is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * DESCRIPTION:
+ *
+ * usage: socketdump.exe [filter]
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "windivert.h"
+
+#define INET6_ADDRSTRLEN 45
+
+/*
+ * Entry.
+ */
+int __cdecl main(int argc, char **argv)
+{
+ HANDLE handle, process, console;
+ INT16 priority = 1121; // Arbitrary.
+ const char *filter = "true", *err_str;
+ char path[MAX_PATH+1];
+ char local_str[INET6_ADDRSTRLEN+1], remote_str[INET6_ADDRSTRLEN+1];
+ char *filename;
+ DWORD path_len;
+ UINT packet_len;
+ WINDIVERT_ADDRESS addr;
+
+ switch (argc)
+ {
+ case 1:
+ break;
+ case 2:
+ filter = argv[1];
+ break;
+ default:
+ fprintf(stderr, "usage: %s [filter]\n");
+ exit(EXIT_FAILURE);
+ }
+
+ // Open WinDivert SOCKET handle:
+ handle = WinDivertOpen(filter, WINDIVERT_LAYER_SOCKET, priority,
+ WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_RECV_ONLY);
+ if (handle == INVALID_HANDLE_VALUE)
+ {
+ if (GetLastError() == ERROR_INVALID_PARAMETER &&
+ !WinDivertHelperCompileFilter(filter, WINDIVERT_LAYER_SOCKET,
+ NULL, 0, &err_str, NULL))
+ {
+ fprintf(stderr, "error: invalid filter \"%s\"\n", err_str);
+ exit(EXIT_FAILURE);
+ }
+ fprintf(stderr, "error: failed to open the WinDivert device (%d)\n",
+ GetLastError());
+ return EXIT_FAILURE;
+ }
+
+ // Main loop:
+ console = GetStdHandle(STD_OUTPUT_HANDLE);
+ while (TRUE)
+ {
+ if (!WinDivertRecv(handle, NULL, 0, &addr, &packet_len))
+ {
+ fprintf(stderr, "failed to read packet (%d)\n", GetLastError());
+ continue;
+ }
+
+ SetConsoleTextAttribute(console, FOREGROUND_GREEN);
+ switch (addr.Event)
+ {
+ case WINDIVERT_EVENT_SOCKET_BIND:
+ printf("BIND");
+ break;
+ case WINDIVERT_EVENT_SOCKET_LISTEN:
+ printf("LISTEN");
+ break;
+ case WINDIVERT_EVENT_SOCKET_CONNECT:
+ printf("CONNECT");
+ break;
+ case WINDIVERT_EVENT_SOCKET_ACCEPT:
+ printf("ACCEPT");
+ break;
+ default:
+ printf("???");
+ break;
+ }
+ SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN |
+ FOREGROUND_BLUE);
+
+ printf(" pid=");
+ SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
+ printf("%u", addr.Socket.ProcessId);
+ SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN |
+ FOREGROUND_BLUE);
+
+ printf(" program=");
+ process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE,
+ addr.Socket.ProcessId);
+ path_len = 0;
+ if (process != NULL)
+ {
+ path_len = GetProcessImageFileName(process, path, sizeof(path));
+ CloseHandle(process);
+ }
+ SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
+ if (path_len != 0)
+ {
+ filename = PathFindFileName(path);
+ printf("%s", filename);
+ }
+ else if (addr.Socket.ProcessId == 4)
+ {
+ printf("Windows");
+ }
+ else
+ {
+ printf("???");
+ }
+ SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN |
+ FOREGROUND_BLUE);
+
+ printf(" protocol=");
+ SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
+ switch (addr.Socket.Protocol)
+ {
+ case IPPROTO_TCP:
+ printf("TCP");
+ break;
+ case IPPROTO_UDP:
+ printf("UDP");
+ break;
+ case IPPROTO_ICMP:
+ printf("ICMP");
+ break;
+ case IPPROTO_ICMPV6:
+ printf("ICMPV6");
+ break;
+ default:
+ printf("%u", addr.Socket.Protocol);
+ break;
+ }
+ SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN |
+ FOREGROUND_BLUE);
+
+ WinDivertHelperFormatIPv6Address(addr.Socket.LocalAddr, local_str,
+ sizeof(local_str));
+ if (addr.Socket.LocalPort != 0 || strcmp(local_str, "::") != 0)
+ {
+ printf(" local=");
+ SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
+ printf("[%s]:%u", local_str, addr.Socket.LocalPort);
+ SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN |
+ FOREGROUND_BLUE);
+ }
+
+ WinDivertHelperFormatIPv6Address(addr.Socket.RemoteAddr, remote_str,
+ sizeof(remote_str));
+ if (addr.Socket.RemotePort != 0 || strcmp(remote_str, "::") != 0)
+ {
+ printf(" remote=");
+ SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
+ printf("[%s]:%u", remote_str, addr.Socket.RemotePort);
+ SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN |
+ FOREGROUND_BLUE);
+ }
+
+ putchar('\n');
+ }
+
+ return 0;
+}
+
diff --git a/examples/windivertctl/windivertctl.c b/examples/windivertctl/windivertctl.c
index 7be5d34..5e503dd 100644
--- a/examples/windivertctl/windivertctl.c
+++ b/examples/windivertctl/windivertctl.c
@@ -315,6 +315,9 @@ usage:
case WINDIVERT_LAYER_FLOW:
fputs("FLOW", stdout);
break;
+ case WINDIVERT_LAYER_SOCKET:
+ fputs("SOCKET", stdout);
+ break;
case WINDIVERT_LAYER_REFLECT:
fputs("REFLECT", stdout);
break;
diff --git a/include/windivert.h b/include/windivert.h
index 68c2131..aa35f40 100644
--- a/include/windivert.h
+++ b/include/windivert.h
@@ -77,7 +77,8 @@ typedef enum
WINDIVERT_LAYER_NETWORK = 0, /* Network layer. */
WINDIVERT_LAYER_NETWORK_FORWARD = 1,/* Network layer (forwarded packets) */
WINDIVERT_LAYER_FLOW = 2, /* Flow layer. */
- WINDIVERT_LAYER_REFLECT = 3, /* Reflect layer. */
+ WINDIVERT_LAYER_SOCKET = 3, /* Socket layer. */
+ WINDIVERT_LAYER_REFLECT = 4, /* Reflect layer. */
} WINDIVERT_LAYER, *PWINDIVERT_LAYER;
/*
@@ -102,6 +103,19 @@ typedef struct
UINT8 Protocol; /* Protocol. */
} WINDIVERT_FLOW_DATA, *PWINDIVERT_FLOW_DATA;
+/*
+ * WinDivert SOCKET layer data.
+ */
+typedef struct
+{
+ UINT32 ProcessId; /* Process ID. */
+ UINT32 LocalAddr[4]; /* Local address. */
+ UINT32 RemoteAddr[4]; /* Remote address. */
+ UINT16 LocalPort; /* Local port. */
+ UINT16 RemotePort; /* Remote port. */
+ UINT8 Protocol; /* Protocol. */
+} WINDIVERT_SOCKET_DATA, *PWINDIVERT_SOCKET_DATA;
+
/*
* WinDivert REFLECTION layer data.
*/
@@ -135,6 +149,7 @@ typedef struct
{
WINDIVERT_NETWORK_DATA Network; /* Network layer data. */
WINDIVERT_FLOW_DATA Flow; /* Flow layer data. */
+ WINDIVERT_SOCKET_DATA Socket; /* Socket layer data. */
WINDIVERT_REFLECT_DATA Reflect; /* Reflect layer data. */
};
} WINDIVERT_ADDRESS, *PWINDIVERT_ADDRESS;
@@ -148,10 +163,14 @@ typedef enum
WINDIVERT_EVENT_FLOW_ESTABLISHED = 1,
/* Flow established. */
WINDIVERT_EVENT_FLOW_DELETED = 2, /* Flow deleted. */
- WINDIVERT_EVENT_REFLECT_ESTABLISHED = 3,
+ WINDIVERT_EVENT_SOCKET_BIND = 3, /* Socket bind. */
+ WINDIVERT_EVENT_SOCKET_CONNECT = 4, /* Socket connect. */
+ WINDIVERT_EVENT_SOCKET_LISTEN = 5, /* Socket listen. */
+ WINDIVERT_EVENT_SOCKET_ACCEPT = 6, /* Socket accept. */
+ WINDIVERT_EVENT_REFLECT_ESTABLISHED = 7,
/* Previously open WinDivert handle. */
- WINDIVERT_EVENT_REFLECT_OPEN = 4, /* Open new WinDivert handle. */
- WINDIVERT_EVENT_REFLECT_CLOSE = 5, /* Close existing WinDivert handle. */
+ WINDIVERT_EVENT_REFLECT_OPEN = 8, /* Open new WinDivert handle. */
+ WINDIVERT_EVENT_REFLECT_CLOSE = 9, /* Close existing WinDivert handle. */
} WINDIVERT_EVENT, *PWINDIVERT_EVENT;
/*
@@ -434,6 +453,22 @@ extern WINDIVERTEXPORT BOOL WinDivertHelperParseIPv6Address(
__in const char *addrStr,
__out_opt UINT32 *pAddr);
+/*
+ * Format an IPv4 address.
+ */
+extern WINDIVERTEXPORT BOOL WinDivertHelperFormatIPv4Address(
+ __in UINT32 addr,
+ __out char *buffer,
+ __in UINT bufLen);
+
+/*
+ * Format an IPv6 address.
+ */
+extern WINDIVERTEXPORT BOOL WinDivertHelperFormatIPv6Address(
+ __in const UINT32 *pAddr,
+ __out char *buffer,
+ __in UINT bufLen);
+
/*
* Calculate IPv4/IPv6/ICMP/ICMPv6/TCP/UDP checksums.
*/
diff --git a/mingw-build.sh b/mingw-build.sh
index 29a550e..e0acd54 100644
--- a/mingw-build.sh
+++ b/mingw-build.sh
@@ -105,6 +105,10 @@ do
$CC -s -O2 -Iinclude/ examples/windivertctl/windivertctl.c \
-o "install/MINGW/$CPU/windivertctl.exe" -lWinDivert -lws2_32 \
-lpsapi -lshlwapi -L"install/MINGW/$CPU/"
+ echo "\tcopy install/MINGW/$CPU/socketdump.exe..."
+ $CC -s -O2 -Iinclude/ examples/socketdump/socketdump.c \
+ -o "install/MINGW/$CPU/socketdump.exe" -lWinDivert -lws2_32 \
+ -lpsapi -lshlwapi -L"install/MINGW/$CPU/"
echo "\tcopy install/MINGW/$CPU/WinDivert$BITS.sys..."
cp install/WDDK/$CPU/WinDivert$BITS.sys install/MINGW/$CPU
else
diff --git a/sys/windivert.c b/sys/windivert.c
index d174986..e6cb0f9 100644
--- a/sys/windivert.c
+++ b/sys/windivert.c
@@ -107,13 +107,14 @@ struct reflect_context_s
LONGLONG timestamp; // Open timestamp.
WINDIVERT_REFLECT_DATA data; // Reflect data.
BOOL inserted; // Entry inserted?
+ BOOL open; // Seen OPEN event?
};
/*
* WinDivert context information.
*/
#define WINDIVERT_CONTEXT_SIZE (sizeof(struct context_s))
-#define WINDIVERT_CONTEXT_MAXLAYERS 4
+#define WINDIVERT_CONTEXT_MAXLAYERS 8
#define WINDIVERT_CONTEXT_MAXWORKERS 1
typedef enum
{
@@ -412,11 +413,54 @@ static void windivert_flow_established_v6_classify(
IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
const FWPS_FILTER0 *filter, IN UINT64 flow_context,
OUT FWPS_CLASSIFY_OUT0 *result);
+static void windivert_resource_assignment_v4_classify(
+ IN const FWPS_INCOMING_VALUES0 *fixed_vals,
+ IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
+ const FWPS_FILTER0 *filter, IN UINT64 flow_context,
+ OUT FWPS_CLASSIFY_OUT0 *result);
+static void windivert_resource_assignment_v6_classify(
+ IN const FWPS_INCOMING_VALUES0 *fixed_vals,
+ IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
+ const FWPS_FILTER0 *filter, IN UINT64 flow_context,
+ OUT FWPS_CLASSIFY_OUT0 *result);
+static void windivert_auth_connect_v4_classify(
+ IN const FWPS_INCOMING_VALUES0 *fixed_vals,
+ IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
+ const FWPS_FILTER0 *filter, IN UINT64 flow_context,
+ OUT FWPS_CLASSIFY_OUT0 *result);
+static void windivert_auth_connect_v6_classify(
+ IN const FWPS_INCOMING_VALUES0 *fixed_vals,
+ IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
+ const FWPS_FILTER0 *filter, IN UINT64 flow_context,
+ OUT FWPS_CLASSIFY_OUT0 *result);
+static void windivert_auth_listen_v4_classify(
+ IN const FWPS_INCOMING_VALUES0 *fixed_vals,
+ IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
+ const FWPS_FILTER0 *filter, IN UINT64 flow_context,
+ OUT FWPS_CLASSIFY_OUT0 *result);
+static void windivert_auth_listen_v6_classify(
+ IN const FWPS_INCOMING_VALUES0 *fixed_vals,
+ IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
+ const FWPS_FILTER0 *filter, IN UINT64 flow_context,
+ OUT FWPS_CLASSIFY_OUT0 *result);
+static void windivert_auth_recv_accept_v4_classify(
+ IN const FWPS_INCOMING_VALUES0 *fixed_vals,
+ IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
+ const FWPS_FILTER0 *filter, IN UINT64 flow_context,
+ OUT FWPS_CLASSIFY_OUT0 *result);
+static void windivert_auth_recv_accept_v6_classify(
+ IN const FWPS_INCOMING_VALUES0 *fixed_vals,
+ IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
+ const FWPS_FILTER0 *filter, IN UINT64 flow_context,
+ OUT FWPS_CLASSIFY_OUT0 *result);
static void windivert_flow_established_classify(context_t context,
IN UINT64 flow_id, IN PWINDIVERT_FLOW_DATA flow_data, IN BOOL ipv4,
IN BOOL outbound, IN BOOL loopback, OUT FWPS_CLASSIFY_OUT0 *result);
static void windivert_flow_delete_notify(UINT16 layer_id, UINT32 callout_id,
UINT64 flow_context);
+static void windivert_socket_classify(context_t context,
+ PWINDIVERT_SOCKET_DATA socket_data, WINDIVERT_EVENT event, BOOL ipv4,
+ BOOL outbound, BOOL loopback, FWPS_CLASSIFY_OUT0 *result);
static void windivert_network_classify(context_t context,
IN PWINDIVERT_NETWORK_DATA network_data, IN BOOL ipv4, IN BOOL outbound,
IN BOOL loopback, IN UINT advance, IN OUT void *data,
@@ -431,6 +475,12 @@ static void windivert_reinject_packet(packet_t packet);
static void windivert_free_packet(packet_t packet);
static BOOL windivert_decrement_ttl(PVOID data, BOOL ipv4, BOOL checksum);
static int windivert_big_num_compare(const UINT32 *a, const UINT32 *b);
+static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
+ 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, PWINDIVERT_UDPHDR *udp_header_ptr,
+ UINT8 *proto_ptr, UINT *payload_len_ptr);
static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
PVOID layer_data, WINDIVERT_EVENT event, BOOL ipv4, BOOL outbound,
BOOL loopback, BOOL impostor, PWINDIVERT_FILTER filter);
@@ -449,29 +499,53 @@ static void windivert_reflect_worker(IN WDFWORKITEM item);
* WinDivert sublayer GUIDs
*/
DEFINE_GUID(WINDIVERT_SUBLAYER_INBOUND_IPV4_GUID,
- 0x09C273C5, 0x0FB1, 0x4453,
- 0x95, 0xDF, 0x7E, 0x1C, 0x28, 0x78, 0xED, 0xDF);
+ 0x82A99281, 0x0389, 0x4DE2,
+ 0xAE, 0x2D, 0xA4, 0x51, 0x59, 0x16, 0x26, 0x06);
DEFINE_GUID(WINDIVERT_SUBLAYER_OUTBOUND_IPV4_GUID,
- 0x11C342F5, 0x4276, 0x494F,
- 0xBB, 0x30, 0x84, 0x55, 0x78, 0x6C, 0x67, 0x30);
+ 0xB0BB07C6, 0x3B3B, 0x41FE,
+ 0x83, 0x8B, 0xD8, 0x37, 0xDD, 0xB8, 0x75, 0x41);
DEFINE_GUID(WINDIVERT_SUBLAYER_INBOUND_IPV6_GUID,
- 0x2E5F6801, 0xE721, 0x4A0D,
- 0x8D, 0x48, 0xC8, 0x1D, 0x4F, 0x25, 0x45, 0x93);
+ 0xD7674846, 0x3AB5, 0x4E93,
+ 0x82, 0xD0, 0x2F, 0xCC, 0x03, 0xA2, 0x88, 0x7A);
DEFINE_GUID(WINDIVERT_SUBLAYER_OUTBOUND_IPV6_GUID,
- 0xB6511564, 0xD5E6, 0x44C8,
- 0x9C, 0x73, 0xBB, 0x22, 0x15, 0x39, 0xEB, 0x8A);
+ 0x6672F761, 0xA0F2, 0x4578,
+ 0x92, 0x50, 0x09, 0x03, 0x0D, 0x4E, 0x8C, 0x46);
DEFINE_GUID(WINDIVERT_SUBLAYER_FORWARD_IPV4_GUID,
- 0xEC5C40E3, 0xE508, 0x408B,
- 0xB9, 0x86, 0x58, 0xDE, 0xC7, 0x5F, 0x86, 0xE4);
+ 0x4622DCC6, 0xBD71, 0x48ED,
+ 0x9D, 0x1A, 0x72, 0xC9, 0x0D, 0xEB, 0xA1, 0x74);
DEFINE_GUID(WINDIVERT_SUBLAYER_FORWARD_IPV6_GUID,
- 0xE70D0973, 0x935F, 0x4790,
- 0x8E, 0x64, 0xF7, 0xF7, 0x36, 0x27, 0xA5, 0x8F);
+ 0x7E5B39EC, 0xB54C, 0x41B3,
+ 0xA7, 0x99, 0x47, 0x5E, 0x57, 0x41, 0xA4, 0x33);
DEFINE_GUID(WINDIVERT_SUBLAYER_FLOW_ESTABLISHED_IPV4_GUID,
- 0x168A6CF7, 0x6080, 0x4905,
- 0xAA, 0x72, 0x03, 0x74, 0x67, 0xCD, 0x4F, 0x19);
+ 0x53D6C270, 0xEB79, 0x44CD,
+ 0x83, 0xCD, 0x14, 0x34, 0xE6, 0x13, 0x91, 0x68);
DEFINE_GUID(WINDIVERT_SUBLAYER_FLOW_ESTABLISHED_IPV6_GUID,
- 0x9EAAEB28, 0xC1BB, 0x41F5,
- 0x9F, 0x27, 0x18, 0xD4, 0xDF, 0xE1, 0x31, 0xEE);
+ 0x44B0CDED, 0xAA11, 0x4704,
+ 0x92, 0xA7, 0x99, 0xD2, 0xB7, 0x59, 0x7A, 0x68);
+DEFINE_GUID(WINDIVERT_SUBLAYER_RESOURCE_ASSIGNMENT_IPV4_GUID,
+ 0x736848B6, 0xBE0D, 0x4A8D,
+ 0xA0, 0xC2, 0xE2, 0x02, 0xDC, 0x29, 0x32, 0xBC);
+DEFINE_GUID(WINDIVERT_SUBLAYER_RESOURCE_ASSIGNMENT_IPV6_GUID,
+ 0xF3458E58, 0xD123, 0x439B,
+ 0xB6, 0x40, 0x74, 0x3C, 0xC7, 0x53, 0x9E, 0x36);
+DEFINE_GUID(WINDIVERT_SUBLAYER_AUTH_CONNECT_IPV4_GUID,
+ 0x2F97411F, 0x6350, 0x450A,
+ 0xBF, 0x45, 0x4C, 0x0B, 0xC1, 0xDB, 0x3F, 0x7E);
+DEFINE_GUID(WINDIVERT_SUBLAYER_AUTH_CONNECT_IPV6_GUID,
+ 0x7BAFEEEB, 0x84F0, 0x4BB0,
+ 0x91, 0x1F, 0x7E, 0x62, 0x2D, 0x73, 0x24, 0x2C);
+DEFINE_GUID(WINDIVERT_SUBLAYER_AUTH_LISTEN_IPV4_GUID,
+ 0x49F2A9AD, 0x805E, 0x4328,
+ 0xBB, 0xDA, 0x92, 0x57, 0xB5, 0x18, 0x3A, 0x40);
+DEFINE_GUID(WINDIVERT_SUBLAYER_AUTH_LISTEN_IPV6_GUID,
+ 0xC1BB250E, 0xDE07, 0x41AB,
+ 0x82, 0xEE, 0xAD, 0x7B, 0xFF, 0x13, 0xCE, 0x35);
+DEFINE_GUID(WINDIVERT_SUBLAYER_AUTH_RECV_ACCEPT_IPV4_GUID,
+ 0x7A012579, 0xC75A, 0x4D29,
+ 0xB7, 0x47, 0x04, 0xAD, 0x3C, 0x7B, 0x32, 0x69);
+DEFINE_GUID(WINDIVERT_SUBLAYER_AUTH_RECV_ACCEPT_IPV6_GUID,
+ 0x1C51DD53, 0x6BA4, 0x4149,
+ 0x89, 0x97, 0x1C, 0xD4, 0x8B, 0x51, 0x1B, 0x7D);
/*
* WinDivert supported layers.
@@ -572,6 +646,136 @@ static struct layer_s layer_forward_network_ipv6_0 =
};
static layer_t layer_forward_network_ipv6 = &layer_forward_network_ipv6_0;
+static struct layer_s layer_resource_assignment_ipv4_0 =
+{
+ L"" WINDIVERT_DEVICE_NAME L"_SubLayerResourceAssignmentIPv4",
+ L"" WINDIVERT_DEVICE_NAME L" sublayer flow established (IPv4)",
+ L"" WINDIVERT_DEVICE_NAME L"_CalloutResourceAssignmentIPv4",
+ L"" WINDIVERT_DEVICE_NAME L" callout flow established (IPv4)",
+ L"" WINDIVERT_DEVICE_NAME L"_FilterResourceAssignmentIPv4",
+ L"" WINDIVERT_DEVICE_NAME L" filter flow established (IPv4)",
+ {0},
+ {0},
+ windivert_resource_assignment_v4_classify,
+ NULL,
+ 0
+};
+static layer_t layer_resource_assignment_ipv4 =
+ &layer_resource_assignment_ipv4_0;
+
+static struct layer_s layer_resource_assignment_ipv6_0 =
+{
+ L"" WINDIVERT_DEVICE_NAME L"_SubLayerResourceAssignmentIPv6",
+ L"" WINDIVERT_DEVICE_NAME L" sublayer flow established (IPv6)",
+ L"" WINDIVERT_DEVICE_NAME L"_CalloutResourceAssignmentIPv6",
+ L"" WINDIVERT_DEVICE_NAME L" callout flow established (IPv6)",
+ L"" WINDIVERT_DEVICE_NAME L"_FilterResourceAssignmentIPv6",
+ L"" WINDIVERT_DEVICE_NAME L" filter flow established (IPv6)",
+ {0},
+ {0},
+ windivert_resource_assignment_v6_classify,
+ NULL,
+ 0
+};
+static layer_t layer_resource_assignment_ipv6 =
+ &layer_resource_assignment_ipv6_0;
+
+static struct layer_s layer_auth_connect_ipv4_0 =
+{
+ L"" WINDIVERT_DEVICE_NAME L"_SubLayerAuthConnectIPv4",
+ L"" WINDIVERT_DEVICE_NAME L" sublayer flow established (IPv4)",
+ L"" WINDIVERT_DEVICE_NAME L"_CalloutAuthConnectIPv4",
+ L"" WINDIVERT_DEVICE_NAME L" callout flow established (IPv4)",
+ L"" WINDIVERT_DEVICE_NAME L"_FilterAuthConnectIPv4",
+ L"" WINDIVERT_DEVICE_NAME L" filter flow established (IPv4)",
+ {0},
+ {0},
+ windivert_auth_connect_v4_classify,
+ NULL,
+ 0
+};
+static layer_t layer_auth_connect_ipv4 = &layer_auth_connect_ipv4_0;
+
+static struct layer_s layer_auth_connect_ipv6_0 =
+{
+ L"" WINDIVERT_DEVICE_NAME L"_SubLayerAuthConnectIPv6",
+ L"" WINDIVERT_DEVICE_NAME L" sublayer flow established (IPv6)",
+ L"" WINDIVERT_DEVICE_NAME L"_CalloutAuthConnectIPv6",
+ L"" WINDIVERT_DEVICE_NAME L" callout flow established (IPv6)",
+ L"" WINDIVERT_DEVICE_NAME L"_FilterAuthConnectIPv6",
+ L"" WINDIVERT_DEVICE_NAME L" filter flow established (IPv6)",
+ {0},
+ {0},
+ windivert_auth_connect_v6_classify,
+ NULL,
+ 0
+};
+static layer_t layer_auth_connect_ipv6 = &layer_auth_connect_ipv6_0;
+
+static struct layer_s layer_auth_listen_ipv4_0 =
+{
+ L"" WINDIVERT_DEVICE_NAME L"_SubLayerAuthListenIPv4",
+ L"" WINDIVERT_DEVICE_NAME L" sublayer flow established (IPv4)",
+ L"" WINDIVERT_DEVICE_NAME L"_CalloutAuthListenIPv4",
+ L"" WINDIVERT_DEVICE_NAME L" callout flow established (IPv4)",
+ L"" WINDIVERT_DEVICE_NAME L"_FilterAuthListenIPv4",
+ L"" WINDIVERT_DEVICE_NAME L" filter flow established (IPv4)",
+ {0},
+ {0},
+ windivert_auth_listen_v4_classify,
+ NULL,
+ 0
+};
+static layer_t layer_auth_listen_ipv4 = &layer_auth_listen_ipv4_0;
+
+static struct layer_s layer_auth_listen_ipv6_0 =
+{
+ L"" WINDIVERT_DEVICE_NAME L"_SubLayerAuthListenIPv6",
+ L"" WINDIVERT_DEVICE_NAME L" sublayer flow established (IPv6)",
+ L"" WINDIVERT_DEVICE_NAME L"_CalloutAuthListenIPv6",
+ L"" WINDIVERT_DEVICE_NAME L" callout flow established (IPv6)",
+ L"" WINDIVERT_DEVICE_NAME L"_FilterAuthListenIPv6",
+ L"" WINDIVERT_DEVICE_NAME L" filter flow established (IPv6)",
+ {0},
+ {0},
+ windivert_auth_listen_v6_classify,
+ NULL,
+ 0
+};
+static layer_t layer_auth_listen_ipv6 = &layer_auth_listen_ipv6_0;
+
+static struct layer_s layer_auth_recv_accept_ipv4_0 =
+{
+ L"" WINDIVERT_DEVICE_NAME L"_SubLayerAuthRecvAcceptIPv4",
+ L"" WINDIVERT_DEVICE_NAME L" sublayer flow established (IPv4)",
+ L"" WINDIVERT_DEVICE_NAME L"_CalloutAuthRecvAcceptIPv4",
+ L"" WINDIVERT_DEVICE_NAME L" callout flow established (IPv4)",
+ L"" WINDIVERT_DEVICE_NAME L"_FilterAuthRecvAcceptIPv4",
+ L"" WINDIVERT_DEVICE_NAME L" filter flow established (IPv4)",
+ {0},
+ {0},
+ windivert_auth_recv_accept_v4_classify,
+ NULL,
+ 0
+};
+static layer_t layer_auth_recv_accept_ipv4 = &layer_auth_recv_accept_ipv4_0;
+
+static struct layer_s layer_auth_recv_accept_ipv6_0 =
+{
+ L"" WINDIVERT_DEVICE_NAME L"_SubLayerAuthRecvAcceptIPv6",
+ L"" WINDIVERT_DEVICE_NAME L" sublayer flow established (IPv6)",
+ L"" WINDIVERT_DEVICE_NAME L"_CalloutAuthRecvAcceptIPv6",
+ L"" WINDIVERT_DEVICE_NAME L" callout flow established (IPv6)",
+ L"" WINDIVERT_DEVICE_NAME L"_FilterAuthRecvAcceptIPv6",
+ L"" WINDIVERT_DEVICE_NAME L" filter flow established (IPv6)",
+ {0},
+ {0},
+ windivert_auth_recv_accept_v6_classify,
+ NULL,
+ 0
+};
+static layer_t layer_auth_recv_accept_ipv6 = &layer_auth_recv_accept_ipv6_0;
+
static struct layer_s layer_flow_established_ipv4_0 =
{
L"" WINDIVERT_DEVICE_NAME L"_SubLayerFlowEstablishedIPv4",
@@ -677,6 +881,18 @@ extern NTSTATUS DriverEntry(IN PDRIVER_OBJECT driver_obj,
FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4;
layer_flow_established_ipv6->layer_guid =
FWPM_LAYER_ALE_FLOW_ESTABLISHED_V6;
+ layer_resource_assignment_ipv4->layer_guid =
+ FWPM_LAYER_ALE_RESOURCE_ASSIGNMENT_V4;
+ layer_resource_assignment_ipv6->layer_guid =
+ FWPM_LAYER_ALE_RESOURCE_ASSIGNMENT_V6;
+ layer_auth_connect_ipv4->layer_guid = FWPM_LAYER_ALE_AUTH_CONNECT_V4;
+ layer_auth_connect_ipv6->layer_guid = FWPM_LAYER_ALE_AUTH_CONNECT_V6;
+ layer_auth_listen_ipv4->layer_guid = FWPM_LAYER_ALE_AUTH_LISTEN_V4;
+ layer_auth_listen_ipv6->layer_guid = FWPM_LAYER_ALE_AUTH_LISTEN_V6;
+ layer_auth_recv_accept_ipv4->layer_guid =
+ FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4;
+ layer_auth_recv_accept_ipv6->layer_guid =
+ FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6;
layer_inbound_network_ipv4->sublayer_guid =
WINDIVERT_SUBLAYER_INBOUND_IPV4_GUID;
layer_outbound_network_ipv4->sublayer_guid =
@@ -693,6 +909,22 @@ extern NTSTATUS DriverEntry(IN PDRIVER_OBJECT driver_obj,
WINDIVERT_SUBLAYER_FLOW_ESTABLISHED_IPV4_GUID;
layer_flow_established_ipv6->sublayer_guid =
WINDIVERT_SUBLAYER_FLOW_ESTABLISHED_IPV6_GUID;
+ layer_resource_assignment_ipv4->sublayer_guid =
+ WINDIVERT_SUBLAYER_RESOURCE_ASSIGNMENT_IPV4_GUID;
+ layer_resource_assignment_ipv6->sublayer_guid =
+ WINDIVERT_SUBLAYER_RESOURCE_ASSIGNMENT_IPV6_GUID;
+ layer_auth_connect_ipv4->sublayer_guid =
+ WINDIVERT_SUBLAYER_AUTH_CONNECT_IPV4_GUID;
+ layer_auth_connect_ipv6->sublayer_guid =
+ WINDIVERT_SUBLAYER_AUTH_CONNECT_IPV6_GUID;
+ layer_auth_listen_ipv4->sublayer_guid =
+ WINDIVERT_SUBLAYER_AUTH_LISTEN_IPV4_GUID;
+ layer_auth_listen_ipv6->sublayer_guid =
+ WINDIVERT_SUBLAYER_AUTH_LISTEN_IPV6_GUID;
+ layer_auth_recv_accept_ipv4->sublayer_guid =
+ WINDIVERT_SUBLAYER_AUTH_RECV_ACCEPT_IPV4_GUID;
+ layer_auth_recv_accept_ipv6->sublayer_guid =
+ WINDIVERT_SUBLAYER_AUTH_RECV_ACCEPT_IPV6_GUID;
// Configure ourself as a non-PnP driver:
WDF_DRIVER_CONFIG_INIT(&config, WDF_NO_EVENT_CALLBACK);
@@ -873,6 +1105,46 @@ driver_entry_sublayer_error:
{
goto driver_entry_sublayer_error;
}
+ status = windivert_install_sublayer(layer_resource_assignment_ipv4);
+ if (!NT_SUCCESS(status))
+ {
+ goto driver_entry_sublayer_error;
+ }
+ status = windivert_install_sublayer(layer_resource_assignment_ipv6);
+ if (!NT_SUCCESS(status))
+ {
+ goto driver_entry_sublayer_error;
+ }
+ status = windivert_install_sublayer(layer_auth_connect_ipv4);
+ if (!NT_SUCCESS(status))
+ {
+ goto driver_entry_sublayer_error;
+ }
+ status = windivert_install_sublayer(layer_auth_connect_ipv6);
+ if (!NT_SUCCESS(status))
+ {
+ goto driver_entry_sublayer_error;
+ }
+ status = windivert_install_sublayer(layer_auth_listen_ipv4);
+ if (!NT_SUCCESS(status))
+ {
+ goto driver_entry_sublayer_error;
+ }
+ status = windivert_install_sublayer(layer_auth_listen_ipv6);
+ if (!NT_SUCCESS(status))
+ {
+ goto driver_entry_sublayer_error;
+ }
+ status = windivert_install_sublayer(layer_auth_recv_accept_ipv4);
+ if (!NT_SUCCESS(status))
+ {
+ goto driver_entry_sublayer_error;
+ }
+ status = windivert_install_sublayer(layer_auth_recv_accept_ipv6);
+ if (!NT_SUCCESS(status))
+ {
+ goto driver_entry_sublayer_error;
+ }
status = FwpmTransactionCommit0(engine_handle);
if (!NT_SUCCESS(status))
{
@@ -954,6 +1226,22 @@ static void windivert_driver_unload(void)
&layer_flow_established_ipv4->sublayer_guid);
FwpmSubLayerDeleteByKey0(engine_handle,
&layer_flow_established_ipv6->sublayer_guid);
+ FwpmSubLayerDeleteByKey0(engine_handle,
+ &layer_resource_assignment_ipv4->sublayer_guid);
+ FwpmSubLayerDeleteByKey0(engine_handle,
+ &layer_resource_assignment_ipv6->sublayer_guid);
+ FwpmSubLayerDeleteByKey0(engine_handle,
+ &layer_auth_connect_ipv4->sublayer_guid);
+ FwpmSubLayerDeleteByKey0(engine_handle,
+ &layer_auth_connect_ipv6->sublayer_guid);
+ FwpmSubLayerDeleteByKey0(engine_handle,
+ &layer_auth_listen_ipv4->sublayer_guid);
+ FwpmSubLayerDeleteByKey0(engine_handle,
+ &layer_auth_listen_ipv6->sublayer_guid);
+ FwpmSubLayerDeleteByKey0(engine_handle,
+ &layer_auth_recv_accept_ipv4->sublayer_guid);
+ FwpmSubLayerDeleteByKey0(engine_handle,
+ &layer_auth_recv_accept_ipv6->sublayer_guid);
status = FwpmTransactionCommit0(engine_handle);
if (!NT_SUCCESS(status))
{
@@ -1170,6 +1458,23 @@ static NTSTATUS windivert_install_callouts(context_t context, UINT8 layer,
}
break;
+ case WINDIVERT_LAYER_SOCKET:
+ if (ipv4)
+ {
+ layers[i++] = layer_resource_assignment_ipv4;
+ layers[i++] = layer_auth_connect_ipv4;
+ layers[i++] = layer_auth_listen_ipv4;
+ layers[i++] = layer_auth_recv_accept_ipv4;
+ }
+ if (ipv6)
+ {
+ layers[i++] = layer_resource_assignment_ipv6;
+ layers[i++] = layer_auth_connect_ipv6;
+ layers[i++] = layer_auth_listen_ipv6;
+ layers[i++] = layer_auth_recv_accept_ipv6;
+ }
+ break;
+
case WINDIVERT_LAYER_REFLECT:
break;
@@ -1436,6 +1741,9 @@ extern VOID windivert_cleanup(IN WDFFILEOBJECT object)
DEBUG("CLEANUP: cleaning up WinDivert context (context=%p)", context);
+ windivert_reflect_event(context, WINDIVERT_EVENT_REFLECT_CLOSE);
+ timestamp = KeQueryPerformanceCounter(NULL).QuadPart;
+
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
if (context->state != WINDIVERT_CONTEXT_STATE_OPENING &&
context->state != WINDIVERT_CONTEXT_STATE_OPEN)
@@ -1450,10 +1758,6 @@ windivert_cleanup_error:
sniff_mode = ((context->flags & WINDIVERT_FLAG_SNIFF) != 0);
forward = (context->layer == WINDIVERT_LAYER_NETWORK_FORWARD);
priority = context->priority;
- KeReleaseInStackQueuedSpinLock(&lock_handle);
- windivert_reflect_event(context, WINDIVERT_EVENT_REFLECT_CLOSE);
- timestamp = KeQueryPerformanceCounter(NULL).QuadPart;
- KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
while (!IsListEmpty(&context->flow_set))
{
entry = RemoveHeadList(&context->flow_set);
@@ -1671,6 +1975,7 @@ static void windivert_read_service_request(packet_t packet, WDFREQUEST request)
break;
case WINDIVERT_LAYER_FLOW:
+ case WINDIVERT_LAYER_SOCKET:
status = STATUS_SUCCESS;
dst_len = 0;
@@ -1712,6 +2017,11 @@ static void windivert_read_service_request(packet_t packet, WDFREQUEST request)
sizeof(WINDIVERT_FLOW_DATA));
break;
+ case WINDIVERT_LAYER_SOCKET:
+ RtlCopyMemory(&addr->Socket, layer_data,
+ sizeof(WINDIVERT_SOCKET_DATA));
+ break;
+
case WINDIVERT_LAYER_REFLECT:
RtlCopyMemory(&addr->Reflect, layer_data,
sizeof(WINDIVERT_REFLECT_DATA));
@@ -1832,6 +2142,7 @@ static NTSTATUS windivert_write(context_t context, WDFREQUEST request,
switch (layer)
{
case WINDIVERT_LAYER_FLOW:
+ case WINDIVERT_LAYER_SOCKET:
case WINDIVERT_LAYER_REFLECT:
status = STATUS_INVALID_PARAMETER;
DEBUG_ERROR("failed to inject at layer", status);
@@ -2289,6 +2600,13 @@ windivert_ioctl_bad_start_state:
}
break;
+ case WINDIVERT_LAYER_SOCKET:
+ if ((flags & WINDIVERT_FLAG_RECV_ONLY) == 0)
+ {
+ goto windivert_ioctl_bad_start_state;
+ }
+ break;
+
default:
break;
}
@@ -2317,6 +2635,7 @@ windivert_ioctl_bad_start_state:
case WINDIVERT_LAYER_NETWORK:
case WINDIVERT_LAYER_NETWORK_FORWARD:
case WINDIVERT_LAYER_FLOW:
+ case WINDIVERT_LAYER_SOCKET:
case WINDIVERT_LAYER_REFLECT:
break;
default:
@@ -2953,6 +3272,7 @@ static void windivert_flow_established_v6_classify(
FWPS_FIELD_ALE_FLOW_ESTABLISHED_V6_IP_LOCAL_ADDRESS]
.value.byteArray16->byteArray16[i];
}
+ addr = (UINT8 *)&flow_data.RemoteAddr;
for (i = sizeof(flow_data.RemoteAddr)-1; i >= 0; i--)
{
addr[sizeof(flow_data.RemoteAddr)-i-1] = fixed_vals->incomingValue[
@@ -3159,6 +3479,415 @@ windivert_flow_delete_notify_exit:
}
}
+/*
+ * WinDivert classify resource assignment IPv4 function.
+ */
+static void windivert_resource_assignment_v4_classify(
+ IN const FWPS_INCOMING_VALUES0 *fixed_vals,
+ IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
+ const FWPS_FILTER0 *filter, IN UINT64 flow_context,
+ OUT FWPS_CLASSIFY_OUT0 *result)
+{
+ WINDIVERT_SOCKET_DATA socket_data;
+ FWP_VALUE0 value;
+ BOOL loopback;
+
+ socket_data.ProcessId = (UINT32)meta_vals->processId;
+ value = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V4_IP_LOCAL_ADDRESS].value;
+ if (value.type == FWP_UINT32)
+ {
+ socket_data.LocalAddr[0] = value.uint32;
+ socket_data.LocalAddr[1] = 0x0000FFFF;
+ }
+ else
+ {
+ socket_data.LocalAddr[0] = 0;
+ socket_data.LocalAddr[1] = 0;
+ }
+ socket_data.LocalAddr[2] = 0;
+ socket_data.LocalAddr[3] = 0;
+ socket_data.RemoteAddr[0] = 0;
+ socket_data.RemoteAddr[1] = 0;
+ socket_data.RemoteAddr[2] = 0;
+ socket_data.RemoteAddr[3] = 0;
+ value = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V4_IP_LOCAL_PORT].value;
+ socket_data.LocalPort = (value.type == FWP_UINT16? value.uint16: 0);
+ socket_data.RemotePort = 0;
+ socket_data.Protocol = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V4_IP_PROTOCOL].value.uint8;
+
+ loopback = ((fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V4_FLAGS].value.uint32 &
+ FWP_CONDITION_FLAG_IS_LOOPBACK) != 0);
+
+ windivert_socket_classify((context_t)filter->context,
+ &socket_data, /*event=*/WINDIVERT_EVENT_SOCKET_BIND, /*ipv4=*/TRUE,
+ /*outbound=*/FALSE, loopback, result);
+}
+
+/*
+ * WinDivert classify resource assignment IPv6 function.
+ */
+static void windivert_resource_assignment_v6_classify(
+ IN const FWPS_INCOMING_VALUES0 *fixed_vals,
+ IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
+ const FWPS_FILTER0 *filter, IN UINT64 flow_context,
+ OUT FWPS_CLASSIFY_OUT0 *result)
+{
+ WINDIVERT_SOCKET_DATA socket_data;
+ FWP_VALUE0 value;
+ BOOL loopback;
+ UINT8 *addr;
+ INT i;
+
+ socket_data.ProcessId = (UINT32)meta_vals->processId;
+ addr = (UINT8 *)&socket_data.LocalAddr;
+ value = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V6_IP_LOCAL_ADDRESS].value;
+ if (value.type == FWP_BYTE_ARRAY16_TYPE)
+ {
+ for (i = sizeof(socket_data.LocalAddr)-1; i >= 0; i--)
+ {
+ addr[sizeof(socket_data.LocalAddr)-i-1] =
+ value.byteArray16->byteArray16[i];
+ }
+ }
+ else
+ {
+ socket_data.LocalAddr[0] = 0;
+ socket_data.LocalAddr[1] = 0;
+ socket_data.LocalAddr[2] = 0;
+ socket_data.LocalAddr[3] = 0;
+ }
+ socket_data.RemoteAddr[0] = 0;
+ socket_data.RemoteAddr[1] = 0;
+ socket_data.RemoteAddr[2] = 0;
+ socket_data.RemoteAddr[3] = 0;
+ value = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V6_IP_LOCAL_PORT].value;
+ socket_data.LocalPort = (value.type == FWP_UINT16? value.uint16: 0);
+ socket_data.RemotePort = 0;
+ socket_data.Protocol = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V6_IP_PROTOCOL].value.uint8;
+
+ loopback = ((fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V6_FLAGS].value.uint32 &
+ FWP_CONDITION_FLAG_IS_LOOPBACK) != 0);
+
+ windivert_socket_classify((context_t)filter->context,
+ &socket_data, /*event=*/WINDIVERT_EVENT_SOCKET_BIND, /*ipv4=*/FALSE,
+ /*outbound=*/FALSE, loopback, result);
+}
+
+/*
+ * WinDivert classify auth connect IPv4 function.
+ */
+static void windivert_auth_connect_v4_classify(
+ IN const FWPS_INCOMING_VALUES0 *fixed_vals,
+ IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
+ const FWPS_FILTER0 *filter, IN UINT64 flow_context,
+ OUT FWPS_CLASSIFY_OUT0 *result)
+{
+ WINDIVERT_SOCKET_DATA socket_data;
+ BOOL loopback;
+
+ socket_data.ProcessId = (UINT32)meta_vals->processId;
+ socket_data.LocalAddr[0] = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_LOCAL_ADDRESS].value.uint32;
+ socket_data.LocalAddr[1] = 0x0000FFFF;
+ socket_data.LocalAddr[2] = 0;
+ socket_data.LocalAddr[3] = 0;
+ socket_data.RemoteAddr[0] = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_REMOTE_ADDRESS].value.uint32;
+ socket_data.RemoteAddr[1] = 0x0000FFFF;
+ socket_data.RemoteAddr[2] = 0;
+ socket_data.RemoteAddr[3] = 0;
+ socket_data.LocalPort = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_LOCAL_PORT].value.uint16;
+ socket_data.RemotePort = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_REMOTE_PORT].value.uint16;
+ socket_data.Protocol = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_PROTOCOL].value.uint8;
+
+ loopback = ((fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_CONNECT_V4_FLAGS].value.uint32 &
+ FWP_CONDITION_FLAG_IS_LOOPBACK) != 0);
+
+ windivert_socket_classify((context_t)filter->context,
+ &socket_data, /*event=*/WINDIVERT_EVENT_SOCKET_CONNECT, /*ipv4=*/TRUE,
+ /*outbound=*/TRUE, loopback, result);
+}
+
+/*
+ * WinDivert classify auth connect IPv6 function.
+ */
+static void windivert_auth_connect_v6_classify(
+ IN const FWPS_INCOMING_VALUES0 *fixed_vals,
+ IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
+ const FWPS_FILTER0 *filter, IN UINT64 flow_context,
+ OUT FWPS_CLASSIFY_OUT0 *result)
+{
+ WINDIVERT_SOCKET_DATA socket_data;
+ BOOL loopback;
+ UINT8 *addr;
+ INT i;
+
+ socket_data.ProcessId = (UINT32)meta_vals->processId;
+ addr = (UINT8 *)&socket_data.LocalAddr;
+ for (i = sizeof(socket_data.LocalAddr)-1; i >= 0; i--)
+ {
+ addr[sizeof(socket_data.LocalAddr)-i-1] = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_CONNECT_V6_IP_LOCAL_ADDRESS]
+ .value.byteArray16->byteArray16[i];
+ }
+ addr = (UINT8 *)&socket_data.RemoteAddr;
+ for (i = sizeof(socket_data.RemoteAddr)-1; i >= 0; i--)
+ {
+ addr[sizeof(socket_data.RemoteAddr)-i-1] = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_CONNECT_V6_IP_REMOTE_ADDRESS]
+ .value.byteArray16->byteArray16[i];
+ }
+ socket_data.LocalPort = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_LOCAL_PORT].value.uint16;
+ socket_data.RemotePort = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_REMOTE_PORT].value.uint16;
+ socket_data.Protocol = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_PROTOCOL].value.uint8;
+
+ loopback = ((fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_CONNECT_V4_FLAGS].value.uint32 &
+ FWP_CONDITION_FLAG_IS_LOOPBACK) != 0);
+
+ windivert_socket_classify((context_t)filter->context,
+ &socket_data, /*event=*/WINDIVERT_EVENT_SOCKET_CONNECT, /*ipv4=*/FALSE,
+ /*outbound=*/TRUE, loopback, result);
+}
+
+/*
+ * WinDivert classify auth listen IPv4 function.
+ */
+static void windivert_auth_listen_v4_classify(
+ IN const FWPS_INCOMING_VALUES0 *fixed_vals,
+ IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
+ const FWPS_FILTER0 *filter, IN UINT64 flow_context,
+ OUT FWPS_CLASSIFY_OUT0 *result)
+{
+ WINDIVERT_SOCKET_DATA socket_data;
+ BOOL loopback;
+
+ socket_data.ProcessId = (UINT32)meta_vals->processId;
+ socket_data.LocalAddr[0] = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_LISTEN_V4_IP_LOCAL_ADDRESS].value.uint32;
+ socket_data.LocalAddr[1] = 0x0000FFFF;
+ socket_data.LocalAddr[2] = 0;
+ socket_data.LocalAddr[3] = 0;
+ socket_data.RemoteAddr[0] = 0;
+ socket_data.RemoteAddr[1] = 0;
+ socket_data.RemoteAddr[2] = 0;
+ socket_data.RemoteAddr[3] = 0;
+ socket_data.LocalPort = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_LISTEN_V4_IP_LOCAL_PORT].value.uint16;
+ socket_data.RemotePort = 0;
+ socket_data.Protocol = IPPROTO_TCP;
+
+ loopback = ((fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_LISTEN_V4_FLAGS].value.uint32 &
+ FWP_CONDITION_FLAG_IS_LOOPBACK) != 0);
+
+ windivert_socket_classify((context_t)filter->context,
+ &socket_data, /*event=*/WINDIVERT_EVENT_SOCKET_LISTEN, /*ipv4=*/TRUE,
+ /*outbound=*/FALSE, loopback, result);
+}
+
+/*
+ * WinDivert classify auth listen IPv6 function.
+ */
+static void windivert_auth_listen_v6_classify(
+ IN const FWPS_INCOMING_VALUES0 *fixed_vals,
+ IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
+ const FWPS_FILTER0 *filter, IN UINT64 flow_context,
+ OUT FWPS_CLASSIFY_OUT0 *result)
+{
+ WINDIVERT_SOCKET_DATA socket_data;
+ BOOL loopback;
+ UINT8 *addr;
+ INT i;
+
+ socket_data.ProcessId = (UINT32)meta_vals->processId;
+ addr = (UINT8 *)&socket_data.LocalAddr;
+ for (i = sizeof(socket_data.LocalAddr)-1; i >= 0; i--)
+ {
+ addr[sizeof(socket_data.LocalAddr)-i-1] = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_LISTEN_V6_IP_LOCAL_ADDRESS]
+ .value.byteArray16->byteArray16[i];
+ }
+ socket_data.RemoteAddr[0] = 0;
+ socket_data.RemoteAddr[1] = 0;
+ socket_data.RemoteAddr[2] = 0;
+ socket_data.RemoteAddr[3] = 0;
+ socket_data.LocalPort = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_LISTEN_V6_IP_LOCAL_PORT].value.uint16;
+ socket_data.RemotePort = 0;
+ socket_data.Protocol = IPPROTO_TCP;
+
+ loopback = ((fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_LISTEN_V6_FLAGS].value.uint32 &
+ FWP_CONDITION_FLAG_IS_LOOPBACK) != 0);
+
+ windivert_socket_classify((context_t)filter->context,
+ &socket_data, /*event=*/WINDIVERT_EVENT_SOCKET_LISTEN, /*ipv4=*/FALSE,
+ /*outbound=*/FALSE, loopback, result);
+}
+
+/*
+ * WinDivert classify auth recv accept IPv4 function.
+ */
+static void windivert_auth_recv_accept_v4_classify(
+ IN const FWPS_INCOMING_VALUES0 *fixed_vals,
+ IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
+ const FWPS_FILTER0 *filter, IN UINT64 flow_context,
+ OUT FWPS_CLASSIFY_OUT0 *result)
+{
+ WINDIVERT_SOCKET_DATA socket_data;
+ BOOL loopback;
+
+ socket_data.ProcessId = (UINT32)meta_vals->processId;
+ socket_data.LocalAddr[0] = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_IP_LOCAL_ADDRESS].value.uint32;
+ socket_data.LocalAddr[1] = 0x0000FFFF;
+ socket_data.LocalAddr[2] = 0;
+ socket_data.LocalAddr[3] = 0;
+ socket_data.RemoteAddr[0] = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_IP_REMOTE_ADDRESS].value.uint32;
+ socket_data.RemoteAddr[1] = 0x0000FFFF;
+ socket_data.RemoteAddr[2] = 0;
+ socket_data.RemoteAddr[3] = 0;
+ socket_data.LocalPort = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_IP_LOCAL_PORT].value.uint16;
+ socket_data.RemotePort = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_IP_REMOTE_PORT].value.uint16;
+ socket_data.Protocol = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_IP_PROTOCOL].value.uint8;
+
+ loopback = ((fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_FLAGS].value.uint32 &
+ FWP_CONDITION_FLAG_IS_LOOPBACK) != 0);
+
+ windivert_socket_classify((context_t)filter->context,
+ &socket_data, /*event=*/WINDIVERT_EVENT_SOCKET_ACCEPT, /*ipv4=*/TRUE,
+ /*outbound=*/FALSE, loopback, result);
+}
+
+/*
+ * WinDivert classify auth recv accept IPv6 function.
+ */
+static void windivert_auth_recv_accept_v6_classify(
+ IN const FWPS_INCOMING_VALUES0 *fixed_vals,
+ IN const FWPS_INCOMING_METADATA_VALUES0 *meta_vals, IN OUT void *data,
+ const FWPS_FILTER0 *filter, IN UINT64 flow_context,
+ OUT FWPS_CLASSIFY_OUT0 *result)
+{
+ WINDIVERT_SOCKET_DATA socket_data;
+ BOOL loopback;
+ UINT8 *addr;
+ INT i;
+
+ socket_data.ProcessId = (UINT32)meta_vals->processId;
+ addr = (UINT8 *)&socket_data.LocalAddr;
+ for (i = sizeof(socket_data.LocalAddr)-1; i >= 0; i--)
+ {
+ addr[sizeof(socket_data.LocalAddr)-i-1] = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V6_IP_LOCAL_ADDRESS]
+ .value.byteArray16->byteArray16[i];
+ }
+ addr = (UINT8 *)&socket_data.RemoteAddr;
+ for (i = sizeof(socket_data.RemoteAddr)-1; i >= 0; i--)
+ {
+ addr[sizeof(socket_data.RemoteAddr)-i-1] = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V6_IP_REMOTE_ADDRESS]
+ .value.byteArray16->byteArray16[i];
+ }
+ socket_data.LocalPort = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_IP_LOCAL_PORT].value.uint16;
+ socket_data.RemotePort = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_IP_REMOTE_PORT].value.uint16;
+ socket_data.Protocol = fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_IP_PROTOCOL].value.uint8;
+
+ loopback = ((fixed_vals->incomingValue[
+ FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_FLAGS].value.uint32 &
+ FWP_CONDITION_FLAG_IS_LOOPBACK) != 0);
+
+ windivert_socket_classify((context_t)filter->context,
+ &socket_data, /*event=*/WINDIVERT_EVENT_SOCKET_ACCEPT, /*ipv4=*/FALSE,
+ /*outbound=*/FALSE, loopback, result);
+}
+
+/*
+ * WinDivert socket classify function.
+ */
+static void windivert_socket_classify(context_t context,
+ PWINDIVERT_SOCKET_DATA socket_data, WINDIVERT_EVENT event, BOOL ipv4,
+ BOOL outbound, BOOL loopback, FWPS_CLASSIFY_OUT0 *result)
+{
+ KLOCK_QUEUE_HANDLE lock_handle;
+ UINT64 flags;
+ BOOL match, ok;
+ WDFOBJECT object;
+ PWINDIVERT_FILTER filter;
+ LONGLONG timestamp;
+ NTSTATUS status;
+
+ // Basic checks:
+ if (!(result->rights & FWPS_RIGHT_ACTION_WRITE))
+ {
+ return;
+ }
+
+ // Get the timestamp.
+ timestamp = KeQueryPerformanceCounter(NULL).QuadPart;
+
+ result->actionType = FWP_ACTION_CONTINUE;
+
+ KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
+ if (context->state != WINDIVERT_CONTEXT_STATE_OPEN)
+ {
+ KeReleaseInStackQueuedSpinLock(&lock_handle);
+ return;
+ }
+ filter = context->filter;
+ flags = context->flags;
+ object = (WDFOBJECT)context->object;
+ WdfObjectReference(object);
+ KeReleaseInStackQueuedSpinLock(&lock_handle);
+
+ match = windivert_filter(/*buffer=*/NULL, /*layer=*/WINDIVERT_LAYER_SOCKET,
+ (PVOID)socket_data, event, ipv4, outbound, loopback,
+ /*impostor=*/FALSE, filter);
+ if (match)
+ {
+ ok = windivert_queue_work(context, /*packet=*/NULL, /*packet_len=*/0,
+ /*buffers=*/NULL, /*layer=*/WINDIVERT_LAYER_SOCKET,
+ (PVOID)socket_data, event, flags, /*priority=*/0, ipv4, outbound,
+ loopback, /*impostor=*/FALSE, /*final=*/FALSE, match, timestamp);
+ if (!ok)
+ {
+ WdfObjectDereference(object);
+ return;
+ }
+ }
+
+ WdfObjectDereference(object);
+ if ((flags & WINDIVERT_FLAG_SNIFF) == 0)
+ {
+ result->actionType = FWP_ACTION_BLOCK;
+ result->flags |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;
+ result->rights &= ~FWPS_RIGHT_ACTION_WRITE;
+ }
+}
+
/*
* WinDivert work item routine for out-of-band filtering.
*/
@@ -3211,6 +3940,7 @@ static BOOL windivert_queue_work(context_t context, PVOID packet,
NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO checksums;
PWINDIVERT_NETWORK_DATA network_data;
PWINDIVERT_FLOW_DATA flow_data;
+ PWINDIVERT_SOCKET_DATA socket_data;
PWINDIVERT_REFLECT_DATA reflect_data;
BOOL pseudo_ip_checksum, pseudo_tcp_checksum, pseudo_udp_checksum;
@@ -3288,6 +4018,21 @@ static BOOL windivert_queue_work(context_t context, PVOID packet,
pseudo_ip_checksum = pseudo_tcp_checksum = pseudo_udp_checksum =
FALSE;
break;
+
+ case WINDIVERT_LAYER_SOCKET:
+ socket_data = (PWINDIVERT_SOCKET_DATA)layer_data;
+ work = (packet_t)windivert_malloc(
+ WINDIVERT_PACKET_SIZE(WINDIVERT_SOCKET_DATA, 0), FALSE);
+ if (work == NULL)
+ {
+ return TRUE;
+ }
+ work->packet_len = 0;
+ data = WINDIVERT_LAYER_DATA_PTR(work);
+ RtlCopyMemory(data, socket_data, sizeof(WINDIVERT_SOCKET_DATA));
+ pseudo_ip_checksum = pseudo_tcp_checksum = pseudo_udp_checksum =
+ FALSE;
+ break;
case WINDIVERT_LAYER_REFLECT:
reflect_data = (PWINDIVERT_REFLECT_DATA)layer_data;
@@ -3600,7 +4345,7 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
PWINDIVERT_ICMPHDR *icmp_header_ptr,
PWINDIVERT_ICMPV6HDR *icmpv6_header_ptr,
PWINDIVERT_TCPHDR *tcp_header_ptr, PWINDIVERT_UDPHDR *udp_header_ptr,
- UINT *payload_len_ptr)
+ UINT8 *proto_ptr, UINT *payload_len_ptr)
{
UINT tot_len, ip_header_len;
PWINDIVERT_IPHDR ip_header = NULL;
@@ -3767,6 +4512,7 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
*icmpv6_header_ptr = icmpv6_header;
*tcp_header_ptr = tcp_header;
*udp_header_ptr = udp_header;
+ *proto_ptr = proto;
*payload_len_ptr = payload_len;
return TRUE;
@@ -3785,10 +4531,12 @@ 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 payload_len = 0;
UINT16 ip, ttl;
PWINDIVERT_NETWORK_DATA network_data = NULL;
PWINDIVERT_FLOW_DATA flow_data = NULL;
+ PWINDIVERT_SOCKET_DATA socket_data = NULL;
PWINDIVERT_REFLECT_DATA reflect_data = NULL;
NTSTATUS status;
@@ -3798,7 +4546,7 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
case WINDIVERT_LAYER_NETWORK_FORWARD:
if (!windivert_parse_headers(buffer, ipv4, &ip_header, &ipv6_header,
&icmp_header, &icmpv6_header, &tcp_header, &udp_header,
- &payload_len))
+ &protocol, &payload_len))
{
return FALSE;
}
@@ -3807,6 +4555,9 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
case WINDIVERT_LAYER_FLOW:
flow_data = (PWINDIVERT_FLOW_DATA)layer_data;
break;
+ case WINDIVERT_LAYER_SOCKET:
+ socket_data = (PWINDIVERT_SOCKET_DATA)layer_data;
+ break;
case WINDIVERT_LAYER_REFLECT:
reflect_data = (PWINDIVERT_REFLECT_DATA)layer_data;
break;
@@ -3836,6 +4587,9 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
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:
@@ -3850,25 +4604,23 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
case WINDIVERT_FILTER_FIELD_SUBIFIDX:
result = (layer == WINDIVERT_LAYER_NETWORK ||
layer == WINDIVERT_LAYER_NETWORK_FORWARD);
- result = result && (network_data != NULL);
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_FLOW);
- result = result && (flow_data != NULL);
+ result = (layer == WINDIVERT_LAYER_NETWORK ||
+ layer == WINDIVERT_LAYER_FLOW ||
+ layer == WINDIVERT_LAYER_SOCKET);
break;
case WINDIVERT_FILTER_FIELD_PROCESSID:
- result = ((layer == WINDIVERT_LAYER_FLOW &&
- flow_data != NULL) ||
- (layer == WINDIVERT_LAYER_REFLECT &&
- reflect_data != NULL));
+ result = (layer == WINDIVERT_LAYER_FLOW ||
+ layer == WINDIVERT_LAYER_SOCKET ||
+ layer == WINDIVERT_LAYER_REFLECT);
break;
case WINDIVERT_FILTER_FIELD_LAYER:
result = (layer == WINDIVERT_LAYER_REFLECT);
- result = result && (reflect_data != NULL);
break;
case WINDIVERT_FILTER_FIELD_IP_HDRLENGTH:
case WINDIVERT_FILTER_FIELD_IP_TOS:
@@ -3981,24 +4733,88 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
field[0] = (UINT32)!ipv4;
break;
case WINDIVERT_FILTER_FIELD_ICMP:
- field[0] = (UINT32)(flow_data != NULL?
- flow_data->Protocol == IPPROTO_ICMP:
- icmp_header != NULL);
+ 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:
+ error = TRUE;
+ result = FALSE;
+ break;
+ }
break;
case WINDIVERT_FILTER_FIELD_ICMPV6:
- field[0] = (UINT32)(flow_data != NULL?
- flow_data->Protocol == IPPROTO_ICMPV6:
- icmpv6_header != NULL);
+ 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:
+ error = TRUE;
+ result = FALSE;
+ break;
+ }
break;
case WINDIVERT_FILTER_FIELD_TCP:
- field[0] = (UINT32)(flow_data != NULL?
- flow_data->Protocol == IPPROTO_TCP:
- tcp_header != NULL);
+ 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:
+ error = TRUE;
+ result = FALSE;
+ break;
+ }
break;
case WINDIVERT_FILTER_FIELD_UDP:
- field[0] = (UINT32)(flow_data != NULL?
- flow_data->Protocol == IPPROTO_UDP:
- udp_header != NULL);
+ 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:
+ error = TRUE;
+ result = FALSE;
+ break;
+ }
break;
case WINDIVERT_FILTER_FIELD_IP_HDRLENGTH:
field[0] = (UINT32)ip_header->HdrLength;
@@ -4164,30 +4980,209 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
field[0] = (UINT32)payload_len;
break;
case WINDIVERT_FILTER_FIELD_LOCALADDR:
- field[0] = flow_data->LocalAddr[0];
- field[1] = flow_data->LocalAddr[1];
- field[2] = flow_data->LocalAddr[2];
- field[3] = flow_data->LocalAddr[3];
+ switch (layer)
+ {
+ case WINDIVERT_LAYER_NETWORK:
+ if (ipv4)
+ {
+ 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:
+ error = TRUE;
+ result = FALSE;
+ break;
+ }
break;
case WINDIVERT_FILTER_FIELD_REMOTEADDR:
- field[0] = flow_data->RemoteAddr[0];
- field[1] = flow_data->RemoteAddr[1];
- field[2] = flow_data->RemoteAddr[2];
- field[3] = flow_data->RemoteAddr[3];
+ switch (layer)
+ {
+ case WINDIVERT_LAYER_NETWORK:
+ if (ipv4)
+ {
+ 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:
+ error = TRUE;
+ result = FALSE;
+ break;
+ }
break;
case WINDIVERT_FILTER_FIELD_LOCALPORT:
- field[0] = (UINT32)flow_data->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
+ {
+ 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:
+ error = TRUE;
+ result = FALSE;
+ break;
+ }
break;
case WINDIVERT_FILTER_FIELD_REMOTEPORT:
- field[0] = (UINT32)flow_data->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
+ {
+ 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:
+ error = TRUE;
+ result = FALSE;
+ break;
+ }
break;
case WINDIVERT_FILTER_FIELD_PROTOCOL:
- field[0] = (UINT32)flow_data->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:
+ error = TRUE;
+ result = FALSE;
+ break;
+ }
break;
case WINDIVERT_FILTER_FIELD_PROCESSID:
- field[0] = (flow_data != NULL?
- flow_data->ProcessId:
- reflect_data->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:
+ error = TRUE;
+ result = FALSE;
+ }
break;
case WINDIVERT_FILTER_FIELD_LAYER:
field[0] = reflect_data->Layer;
@@ -4520,15 +5515,24 @@ static void windivert_reflect_event(context_t context, WINDIVERT_EVENT event)
// To be released on WINDIVERT_EVENT_REFLECT_CLOSE. This ensures the
// context object remains valid until the close event has been handled.
WdfObjectReference(object);
+ context->reflect.open = TRUE;
}
KeReleaseInStackQueuedSpinLock(&lock_handle);
+ if (!context->reflect.open)
+ {
+ // Ignore CLOSE with no matching OPEN:
+ return;
+ }
// Queue the event:
reflect_event = (reflect_event_t)windivert_malloc(
sizeof(struct reflect_event_s), FALSE);
if (reflect_event == NULL)
{
- WdfObjectDereference(object);
+ if (event == WINDIVERT_EVENT_REFLECT_CLOSE && context->reflect.open)
+ {
+ WdfObjectDereference(object);
+ }
return;
}
reflect_event->context = context;
diff --git a/test/test.c b/test/test.c
index f6511fc..fa30a02 100644
--- a/test/test.c
+++ b/test/test.c
@@ -257,6 +257,8 @@ static struct test tests[] =
&pkt_dns_request, TRUE},
{"ip.SrcAddr < 10.0.0.0 or ip.SrcAddr > 10.255.255.255",
&pkt_dns_request, FALSE},
+ {"ip.DstAddr == ::ffff:8.8.4.4", &pkt_dns_request, TRUE},
+ {"ip.DstAddr == ::0:ffff:8.8.4.4", &pkt_dns_request, TRUE},
{"udp.PayloadLength == 29", &pkt_dns_request, TRUE},
{"ipv6", &pkt_ipv6_tcp_syn, TRUE},
{"ip", &pkt_ipv6_tcp_syn, FALSE},
@@ -284,8 +286,10 @@ static struct test tests[] =
{"false", &pkt_ipv6_exthdrs_udp, FALSE},
{"udp", &pkt_ipv6_exthdrs_udp, TRUE},
{"tcp", &pkt_ipv6_exthdrs_udp, FALSE},
+ {"ipv6.SrcAddr == ::", &pkt_ipv6_exthdrs_udp, FALSE},
{"ipv6.SrcAddr == ::1", &pkt_ipv6_exthdrs_udp, TRUE},
{"ipv6.SrcAddr == ::2", &pkt_ipv6_exthdrs_udp, FALSE},
+ {"ipv6.SrcAddr == ::8.8.4.4", &pkt_ipv6_exthdrs_udp, FALSE},
{"ipv6.SrcAddr < abcd::1", &pkt_ipv6_exthdrs_udp, TRUE},
{"ipv6.SrcAddr <= abcd::1", &pkt_ipv6_exthdrs_udp, TRUE},
{"ipv6.SrcAddr != abcd::1", &pkt_ipv6_exthdrs_udp, TRUE},
@@ -332,7 +336,7 @@ int main(void)
Sleep(100);
// Run tests:
- size_t num_tests = sizeof(tests) / sizeof(struct test);
+ size_t num_tests = sizeof(tests) / sizeof(struct test), passed_tests = 0;
for (i = 0; i < num_tests; i++)
{
char *filter = tests[i].filter;
@@ -352,6 +356,7 @@ int main(void)
{
SetConsoleTextAttribute(console, FOREGROUND_GREEN);
printf("PASSED");
+ passed_tests++;
}
else
{
@@ -376,6 +381,9 @@ int main(void)
WinDivertClose(upper_handle);
WinDivertClose(lower_handle);
+ printf("\npassed = %.2f%%\n",
+ ((double)passed_tests / (double)num_tests) * 100.0);
+
return 0;
}