diff --git a/CHANGELOG b/CHANGELOG
index e69ab72..740ed43 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -297,13 +297,14 @@ WinDivert 2.0.1-rc
- Rename the following functions for consistency:
* WinDivertHelperNtohIpv6Address -> WinDivertHelperNtohIPv6Address
* WinDivertHelperHtonIpv6Address -> WinDivertHelperHtonIPv6Address
-WinDivert 2.1.0-rc
+WinDivert 2.1.0
- WinDivertOpen() now supports a new flag:
* WINDIVERT_FLAG_FRAGMENTS: If set, the handle will capture inbound IP
fragments, but not inbound reassembled IP packets. Otherwise, if not
set (the default), the handle will capture inbound reassembled IP
packets, but not inbound IP fragments. This flag only affects
- inbound packets at the WINDIVERT_LAYER_NETWORK layer.
+ inbound packets at the NETWORK layer.
+ - Filter fields inbound/outbound are now supported at the SOCKET layer.
- Fix BSOD caused by packets with missing or incomplete transport
- headers. This bug does not affect WinDivert 1.4.*.
+ headers (introduced in 2.0.0).
- Fix missing Flow.EndpointId and Flow.ParentEndpointId for IPv6 flows.
diff --git a/README b/README
index 6798e09..0fc54ca 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-WinDivert 2.0: Windows Packet Divert
+WinDivert 2.1: Windows Packet Divert
====================================
1. Introduction
diff --git a/VERSION b/VERSION
index 904a390..7ec1d6d 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.0.2-rc
+2.1.0
diff --git a/dll/windivert_helper.c b/dll/windivert_helper.c
index 0b91cc6..0130db9 100644
--- a/dll/windivert_helper.c
+++ b/dll/windivert_helper.c
@@ -217,8 +217,6 @@ typedef struct
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 L__F_R (WINDIVERT_LAYER_FLAG_FLOW | \
WINDIVERT_LAYER_FLAG_REFLECT)
#define LN_FS_ (WINDIVERT_LAYER_FLAG_NETWORK | \
@@ -625,7 +623,7 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer,
{"icmpv6.Type", TOKEN_ICMPV6_TYPE, LNM___},
{"ifIdx", TOKEN_IF_IDX, LNM___},
{"impostor", TOKEN_IMPOSTOR, LNM___},
- {"inbound", TOKEN_INBOUND, LN_F__},
+ {"inbound", TOKEN_INBOUND, LN_FS_},
{"ip", TOKEN_IP, LNMFS_},
{"ip.Checksum", TOKEN_IP_CHECKSUM, LNM___},
{"ip.DF", TOKEN_IP_DF, LNM___},
@@ -654,7 +652,7 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer,
{"loopback", TOKEN_LOOPBACK, LN_FS_},
{"not", TOKEN_NOT, LNMFSR},
{"or", TOKEN_OR, LNMFSR},
- {"outbound", TOKEN_OUTBOUND, LN_F__},
+ {"outbound", TOKEN_OUTBOUND, LN_FS_},
{"packet", TOKEN_PACKET, LNM___},
{"packet16", TOKEN_PACKET16, LNM___},
{"packet32", TOKEN_PACKET32, LNM___},
diff --git a/doc/windivert.html b/doc/windivert.html
index 3954d00..64e71e0 100644
--- a/doc/windivert.html
+++ b/doc/windivert.html
@@ -1,11 +1,11 @@
- WinDivert 2.0 Documentation
+ WinDivert 2.1 Documentation
-WinDivert 2.0: Windows Packet Divert
+WinDivert 2.1: Windows Packet Divert
Table of Contents
- 1. Introduction
diff --git a/examples/passthru/passthru.c b/examples/passthru/passthru.c
index e7b8223..1dffa02 100644
--- a/examples/passthru/passthru.c
+++ b/examples/passthru/passthru.c
@@ -147,7 +147,7 @@ int __cdecl main(int argc, char **argv)
static DWORD passthru(LPVOID arg)
{
UINT8 *packet;
- UINT packet_len, addr_len;
+ UINT packet_len, recv_len, addr_len;
WINDIVERT_ADDRESS *addr;
PCONFIG config = (PCONFIG)arg;
HANDLE handle;
@@ -156,7 +156,10 @@ static DWORD passthru(LPVOID arg)
handle = config->handle;
batch = config->batch;
- packet = (UINT8 *)malloc(batch * MTU);
+ packet_len = batch * MTU;
+ packet_len =
+ (packet_len < WINDIVERT_MTU_MAX? WINDIVERT_MTU_MAX: packet_len);
+ packet = (UINT8 *)malloc(packet_len);
addr = (WINDIVERT_ADDRESS *)malloc(batch * sizeof(WINDIVERT_ADDRESS));
if (packet == NULL || addr == NULL)
{
@@ -169,9 +172,8 @@ static DWORD passthru(LPVOID arg)
while (TRUE)
{
// Read a matching packet.
- packet_len = batch * MTU;
- addr_len = batch * sizeof(WINDIVERT_ADDRESS);
- if (!WinDivertRecvEx(handle, packet, packet_len, &packet_len, 0,
+ addr_len = batch * sizeof(WINDIVERT_ADDRESS);
+ if (!WinDivertRecvEx(handle, packet, packet_len, &recv_len, 0,
addr, &addr_len, NULL))
{
fprintf(stderr, "warning: failed to read packet (%d)\n",
@@ -180,7 +182,7 @@ static DWORD passthru(LPVOID arg)
}
// Re-inject the matching packet.
- if (!WinDivertSendEx(handle, packet, packet_len, NULL, 0, addr,
+ if (!WinDivertSendEx(handle, packet, recv_len, NULL, 0, addr,
addr_len, NULL))
{
fprintf(stderr, "warning: failed to reinject packet (%d)\n",
diff --git a/inf/windivert32.inf b/inf/windivert32.inf
index 8e81fab..9269328 100644
--- a/inf/windivert32.inf
+++ b/inf/windivert32.inf
@@ -4,7 +4,7 @@ Class = WFPCALLOUTS
ClassGuid = {57465043-616C-6C6F-7574-5F636C617373}
Provider = %Basil%
CatalogFile = WinDivert32.Cat
-DriverVer = 01/01/2019,2.0.0
+DriverVer = 08/08/2019,2.1.0
[SourceDisksNames]
1 = %DiskName%
diff --git a/inf/windivert64.inf b/inf/windivert64.inf
index b6a9e5f..2949c2f 100644
--- a/inf/windivert64.inf
+++ b/inf/windivert64.inf
@@ -4,7 +4,7 @@ Class = WFPCALLOUTS
ClassGuid = {57465043-616C-6C6F-7574-5F636C617373}
Provider = %Basil%
CatalogFile = WinDivert64.Cat
-DriverVer = 01/01/2019,2.0.0
+DriverVer = 08/08/2019,2.1.0
[SourceDisksNames]
1 = %DiskName%
diff --git a/sys/windivert.c b/sys/windivert.c
index 5b66bf7..7b61122 100644
--- a/sys/windivert.c
+++ b/sys/windivert.c
@@ -2168,6 +2168,7 @@ static void windivert_read_service_request(context_t context, packet_t packet,
addr[i].TCPChecksum = packet->tcp_checksum;
addr[i].UDPChecksum = packet->udp_checksum;
addr[i].Reserved1 = 0;
+ addr[i].Reserved2 = 0;
layer_data = (PVOID)packet->data;
switch (packet->layer)
{
@@ -2371,6 +2372,7 @@ static void windivert_fast_read_service_request(PVOID packet, ULONG packet_len,
addr->TCPChecksum = (tcp_checksum? 1: 0);
addr->UDPChecksum = (udp_checksum? 1: 0);
addr->Reserved1 = 0;
+ addr->Reserved2 = 0;
switch (layer)
{
case WINDIVERT_LAYER_NETWORK:
@@ -4180,7 +4182,7 @@ static void windivert_resource_assignment_v4_classify(
windivert_socket_classify(context, &socket_data,
/*event=*/WINDIVERT_EVENT_SOCKET_BIND, /*ipv4=*/TRUE,
- /*outbound=*/FALSE, loopback, result);
+ /*outbound=*/TRUE, loopback, result);
}
/*
@@ -4223,7 +4225,7 @@ static void windivert_resource_assignment_v6_classify(
windivert_socket_classify(context, &socket_data,
/*event=*/WINDIVERT_EVENT_SOCKET_BIND, /*ipv4=*/FALSE,
- /*outbound=*/FALSE, loopback, result);
+ /*outbound=*/TRUE, loopback, result);
}
/*
@@ -4261,7 +4263,7 @@ static void windivert_resource_release_v4_classify(
windivert_socket_classify(context, &socket_data,
/*event=*/WINDIVERT_EVENT_SOCKET_CLOSE, /*ipv4=*/TRUE,
- /*outbound=*/FALSE, loopback, result);
+ /*outbound=*/TRUE, loopback, result);
}
/*
@@ -4299,7 +4301,7 @@ static void windivert_resource_release_v6_classify(
windivert_socket_classify(context, &socket_data,
/*event=*/WINDIVERT_EVENT_SOCKET_CLOSE, /*ipv4=*/FALSE,
- /*outbound=*/FALSE, loopback, result);
+ /*outbound=*/TRUE, loopback, result);
}
/*
@@ -4527,7 +4529,7 @@ static void windivert_auth_listen_v4_classify(
windivert_socket_classify(context, &socket_data,
/*event=*/WINDIVERT_EVENT_SOCKET_LISTEN, /*ipv4=*/TRUE,
- /*outbound=*/FALSE, loopback, result);
+ /*outbound=*/TRUE, loopback, result);
}
/*
@@ -4569,7 +4571,7 @@ static void windivert_auth_listen_v6_classify(
windivert_socket_classify(context, &socket_data,
/*event=*/WINDIVERT_EVENT_SOCKET_LISTEN, /*ipv4=*/FALSE,
- /*outbound=*/FALSE, loopback, result);
+ /*outbound=*/TRUE, loopback, result);
}
/*
@@ -5289,7 +5291,7 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
PWINDIVERT_UDPHDR *udp_header_ptr, UINT8 *proto_ptr, UINT *header_len_ptr,
UINT *payload_len_ptr)
{
- UINT tot_len, ip_header_len;
+ UINT total_len, ip_header_len = 0;
PWINDIVERT_IPHDR ip_header = NULL;
PWINDIVERT_IPV6HDR ipv6_header = NULL;
PWINDIVERT_ICMPHDR icmp_header = NULL;
@@ -5306,8 +5308,8 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
DEBUG("FILTER: REJECT (packet is NULL)");
return FALSE;
}
- tot_len = NET_BUFFER_DATA_LENGTH(buffer);
- if (tot_len < sizeof(WINDIVERT_IPHDR))
+ total_len = NET_BUFFER_DATA_LENGTH(buffer);
+ if (total_len < sizeof(WINDIVERT_IPHDR))
{
DEBUG("FILTER: REJECT (packet length too small)");
return FALSE;
@@ -5317,7 +5319,7 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
if (ipv4)
{
// IPv4:
- if (tot_len < sizeof(WINDIVERT_IPHDR))
+ if (total_len < sizeof(WINDIVERT_IPHDR))
{
DEBUG("FILTER: REJECT (packet length too small)");
return FALSE;
@@ -5331,14 +5333,14 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
}
ip_header_len = ip_header->HdrLength*sizeof(UINT32);
if (ip_header->Version != 4 ||
- RtlUshortByteSwap(ip_header->Length) != tot_len ||
+ RtlUshortByteSwap(ip_header->Length) != total_len ||
ip_header->HdrLength < 5 ||
- ip_header_len > tot_len)
+ ip_header_len > total_len)
{
DEBUG("FILTER: REJECT (bad IPv4 packet)");
return FALSE;
}
- if (!frag_mode &&
+ if (!frag_mode &&
(WINDIVERT_IPHDR_GET_MF(ip_header) != 0 ||
WINDIVERT_IPHDR_GET_FRAGOFF(ip_header) != 0))
{
@@ -5351,7 +5353,7 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
else
{
// IPv6:
- if (tot_len < sizeof(WINDIVERT_IPV6HDR))
+ if (total_len < sizeof(WINDIVERT_IPV6HDR))
{
DEBUG("FILTER: REJECT (packet length too small)");
return FALSE;
@@ -5365,9 +5367,9 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
}
ip_header_len = sizeof(WINDIVERT_IPV6HDR);
if (ipv6_header->Version != 6 ||
- ip_header_len > tot_len ||
+ ip_header_len > total_len ||
RtlUshortByteSwap(ipv6_header->Length) +
- sizeof(WINDIVERT_IPV6HDR) != tot_len)
+ sizeof(WINDIVERT_IPV6HDR) != total_len)
{
DEBUG("FILTER: REJECT (bad IPv6 packet)");
return FALSE;
@@ -5395,6 +5397,8 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
if (!frag_mode)
{
DEBUG("FILTER: REJECT (fragment)");
+ NdisRetreatNetBufferDataStart(buffer, ip_header_len,
+ 0, NULL);
return FALSE;
}
ext_header_len = 8;
@@ -5420,6 +5424,13 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
}
proto = ext_header[0];
+ if (ip_header_len + ext_header_len > total_len)
+ {
+ DEBUG("FILTER: REJECT (bad IPv6 extension header)");
+ NdisRetreatNetBufferDataStart(buffer, ip_header_len,
+ 0, NULL);
+ return FALSE;
+ }
ip_header_len += ext_header_len;
NdisAdvanceNetBufferDataStart(buffer, ext_header_len, FALSE,
NULL);
@@ -5443,8 +5454,17 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
case IPPROTO_TCP:
tcp_header = (PWINDIVERT_TCPHDR)NdisGetDataBuffer(buffer,
sizeof(WINDIVERT_TCPHDR), NULL, 1, 0);
- header_len +=
- (tcp_header == NULL? 0: tcp_header->HdrLength*sizeof(UINT32));
+ if (tcp_header != NULL)
+ {
+ UINT tcp_header_len = tcp_header->HdrLength * sizeof(UINT32);
+ if (header_len + tcp_header_len > total_len)
+ {
+ // Bad TCP options:
+ tcp_header = NULL;
+ break;
+ }
+ header_len += tcp_header_len;
+ }
break;
case IPPROTO_UDP:
udp_header = (PWINDIVERT_UDPHDR)NdisGetDataBuffer(buffer,
@@ -5454,7 +5474,6 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
default:
break;
}
-
status = NdisRetreatNetBufferDataStart(buffer, ip_header_len, 0, NULL);
if (!NT_SUCCESS(status))
{
@@ -5471,7 +5490,7 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
*udp_header_ptr = udp_header;
*proto_ptr = proto;
*header_len_ptr = header_len;
- *payload_len_ptr = (header_len > tot_len? 0: tot_len - header_len);
+ *payload_len_ptr = total_len - header_len;
return TRUE;
}