13 Commits

Author SHA1 Message Date
basil00 1789526ecf Bump version to 2.2.2 & other fixups 2022-09-17 10:32:57 +08:00
basil00 3402f8b2f1 Fix #315 2022-09-12 08:08:42 +08:00
basil00 65bb889c79 Bump version and copyright years 2022-07-30 11:34:25 +08:00
basil00 c983d554c9 Fix previous commit 8bda0af
Fix #294

Previous commit was incomplete.
2022-07-30 11:27:57 +08:00
basil00 0b164b6ba3 Fix handling of FwpmTransaction*() errors.
Fixes #294
2022-07-30 11:24:46 +08:00
basil00 7f35b0c8f8 Merge pull request #296 from StalkR/patch-1
windivert.html: fix 6.11 title: format not parse
2022-07-30 11:24:46 +08:00
StalkR ea25bab7c5 windivert.html: fix 6.11 title: format not parse 2022-07-30 11:24:46 +08:00
basil00 c26ec39465 Fix filter compiler test simplification logic
Fix #285
2021-09-25 07:23:08 +08:00
basil00 227a6b1e78 Fix #283 2021-09-11 07:09:51 +08:00
basil00 134dd37bd0 Insert all WinDivert sublayers at the max weight. 2020-09-03 08:12:39 +08:00
basil00 97056af256 Cleanup the provider code. 2020-06-26 08:53:18 +08:00
basil00 db674a6696 Merge pull request #241 from ruilisi/add_provider
Install provider to pass HLK test
2020-06-24 08:35:31 +08:00
Zhou Yicheng 32af280add Install provider to pass HLK test 2020-06-22 11:08:51 +08:00
10 changed files with 261 additions and 137 deletions
+6
View File
@@ -312,3 +312,9 @@ WinDivert 2.2.0
- Implement new packet parser that correctly handles IP fragments.
- Add a new "fragment" filter field that matches IP fragments.
- (Un)Loading the WinDivert driver will cause a system event to be logged.
WinDivert 2.2.1
- Fix potential driver deadlock on user-mode program crash.
- Fix filter language simplification bug.
- Fix Flow.EndpointId containing junk data.
WinDivert 2.2.2
- Fix potential WinDivertClose() BSOD for WINDIVERT_LAYER_FLOW handles.
+1 -1
View File
@@ -5,7 +5,7 @@ WinDivert 2.2: Windows Packet Divert
---------------
Windows Packet Divert (WinDivert) is a user-mode packet interception library
for Windows 7, Windows 8 and Windows 10.
for Windows 10, Windows 11, and Windows Server.
WinDivert enables user-mode capturing/modifying/dropping of network packets
sent to/from the Windows network stack. In summary, WinDivert can:
+1 -1
View File
@@ -1 +1 @@
2.2.0
2.2.2
+134 -53
View File
@@ -1,6 +1,6 @@
/*
* windivert_helper.c
* (C) 2019, all rights reserved,
* (C) 2021, all rights reserved,
*
* This file is part of WinDivert.
*
@@ -1061,7 +1061,10 @@ static PEXPR WinDivertMakeVar(KIND kind, PERROR error)
}
return (PEXPR)(vars + mid);
}
*error = MAKE_ERROR(WINDIVERT_ERROR_ASSERTION_FAILED, 0);
if (error != NULL)
{
*error = MAKE_ERROR(WINDIVERT_ERROR_ASSERTION_FAILED, 0);
}
return NULL;
}
@@ -1091,6 +1094,15 @@ static PEXPR WinDivertMakeZero(void)
return (PEXPR)&zero;
}
/*
* Construct one.
*/
static PEXPR WinDivertMakeOne(void)
{
static const EXPR one = {{{1, 0, 0, 0}}, TOKEN_NUMBER};
return (PEXPR)&one;
}
/*
* Construct a number.
*/
@@ -1480,16 +1492,17 @@ static PEXPR WinDivertParseFilter(HANDLE pool, TOKEN *toks, UINT *i, INT depth,
}
/*
* Statically evaluate a test if possible.
* Simplify a test if possible.
*/
static BOOL WinDivertEvalTest(PEXPR test, BOOL *res)
static void WinDivertSimplifyTest(PEXPR test)
{
PEXPR var = test->arg[0];
PEXPR val = test->arg[1];
BOOL neg_lb = FALSE, neg_ub = FALSE, neg;
UINT32 lb[4] = {0}, ub[4] = {0};
int result_lb, result_ub;
BOOL eq = FALSE;
BOOL eq = FALSE, result = FALSE;
KIND type = TOKEN_TRUE;
switch (var->kind)
{
@@ -1512,6 +1525,20 @@ static BOOL WinDivertEvalTest(PEXPR test, BOOL *res)
case TOKEN_EVENT:
lb[0] = 0; ub[0] = WINDIVERT_EVENT_MAX;
break;
case TOKEN_IP_DF:
case TOKEN_IP_MF:
type = TOKEN_IP;
lb[0] = 0; ub[0] = 1;
break;
case TOKEN_TCP_URG:
case TOKEN_TCP_ACK:
case TOKEN_TCP_PSH:
case TOKEN_TCP_RST:
case TOKEN_TCP_SYN:
case TOKEN_TCP_FIN:
type = TOKEN_TCP;
lb[0] = 0; ub[0] = 1;
break;
case TOKEN_INBOUND:
case TOKEN_OUTBOUND:
case TOKEN_FRAGMENT:
@@ -1521,62 +1548,95 @@ static BOOL WinDivertEvalTest(PEXPR test, BOOL *res)
case TOKEN_ICMPV6:
case TOKEN_TCP:
case TOKEN_UDP:
case TOKEN_IP_DF:
case TOKEN_IP_MF:
case TOKEN_TCP_URG:
case TOKEN_TCP_ACK:
case TOKEN_TCP_PSH:
case TOKEN_TCP_RST:
case TOKEN_TCP_SYN:
case TOKEN_TCP_FIN:
lb[0] = 0; ub[0] = 1;
break;
case TOKEN_IP_HDR_LENGTH:
type = TOKEN_IP;
lb[0] = 0; ub[0] = 0x0F;
break;
case TOKEN_TCP_HDR_LENGTH:
type = TOKEN_TCP;
lb[0] = 0; ub[0] = 0x0F;
break;
case TOKEN_IP_TTL:
case TOKEN_IP_PROTOCOL:
type = TOKEN_IP;
lb[0] = 0; ub[0] = 0xFF;
break;
case TOKEN_IPV6_TRAFFIC_CLASS:
case TOKEN_IPV6_NEXT_HDR:
case TOKEN_IPV6_HOP_LIMIT:
type = TOKEN_IPV6;
lb[0] = 0; ub[0] = 0xFF;
break;
case TOKEN_ICMP_TYPE:
case TOKEN_ICMP_CODE:
type = TOKEN_ICMP;
lb[0] = 0; ub[0] = 0xFF;
break;
case TOKEN_ICMPV6_TYPE:
case TOKEN_ICMPV6_CODE:
type = TOKEN_ICMPV6;
lb[0] = 0; ub[0] = 0xFF;
break;
case TOKEN_TCP_PAYLOAD:
type = TOKEN_TCP;
lb[0] = 0; ub[0] = 0xFF;
break;
case TOKEN_UDP_PAYLOAD:
type = TOKEN_UDP;
lb[0] = 0; ub[0] = 0xFF;
break;
case TOKEN_PROTOCOL:
case TOKEN_PACKET:
case TOKEN_TCP_PAYLOAD:
case TOKEN_UDP_PAYLOAD:
case TOKEN_RANDOM8:
lb[0] = 0; ub[0] = 0xFF;
break;
case TOKEN_IP_FRAG_OFF:
type = TOKEN_IP;
lb[0] = 0; ub[0] = 0x1FFF;
break;
case TOKEN_IP_TOS:
case TOKEN_IP_LENGTH:
case TOKEN_IP_ID:
case TOKEN_IP_CHECKSUM:
type = TOKEN_IP;
lb[0] = 0; ub[0] = 0xFFFF;
break;
case TOKEN_IPV6_LENGTH:
type = TOKEN_IPV6;
lb[0] = 0; ub[0] = 0xFFFF;
break;
case TOKEN_ICMP_CHECKSUM:
type = TOKEN_ICMP;
lb[0] = 0; ub[0] = 0xFFFF;
break;
case TOKEN_ICMPV6_CHECKSUM:
type = TOKEN_ICMPV6;
lb[0] = 0; ub[0] = 0xFFFF;
break;
case TOKEN_TCP_SRC_PORT:
case TOKEN_TCP_DST_PORT:
case TOKEN_TCP_WINDOW:
case TOKEN_TCP_CHECKSUM:
case TOKEN_TCP_URG_PTR:
case TOKEN_TCP_PAYLOAD_LENGTH:
case TOKEN_TCP_PAYLOAD16:
type = TOKEN_TCP;
lb[0] = 0; ub[0] = 0xFFFF;
break;
case TOKEN_UDP_SRC_PORT:
case TOKEN_UDP_DST_PORT:
case TOKEN_UDP_LENGTH:
case TOKEN_UDP_CHECKSUM:
case TOKEN_UDP_PAYLOAD_LENGTH:
case TOKEN_UDP_PAYLOAD16:
type = TOKEN_UDP;
lb[0] = 0; ub[0] = 0xFFFF;
break;
case TOKEN_LOCAL_PORT:
case TOKEN_REMOTE_PORT:
case TOKEN_PACKET16:
case TOKEN_TCP_PAYLOAD16:
case TOKEN_UDP_PAYLOAD16:
case TOKEN_RANDOM16:
lb[0] = 0; ub[0] = 0xFFFF;
break;
@@ -1584,10 +1644,12 @@ static BOOL WinDivertEvalTest(PEXPR test, BOOL *res)
lb[0] = sizeof(WINDIVERT_IPHDR); ub[0] = WINDIVERT_MTU_MAX;
break;
case TOKEN_IPV6_FLOW_LABEL:
type = TOKEN_IPV6;
lb[0] = 0; ub[0] = 0x000FFFFF;
break;
case TOKEN_IP_SRC_ADDR:
case TOKEN_IP_DST_ADDR:
type = TOKEN_IP;
lb[0] = 0;
lb[1] = 0xFFFF;
ub[0] = 0xFFFFFFFF;
@@ -1595,6 +1657,8 @@ static BOOL WinDivertEvalTest(PEXPR test, BOOL *res)
break;
case TOKEN_IPV6_SRC_ADDR:
case TOKEN_IPV6_DST_ADDR:
type = TOKEN_IPV6;
// Fallthrough
case TOKEN_LOCAL_ADDR:
case TOKEN_REMOTE_ADDR:
lb[0] = lb[1] = lb[2] = lb[3] = 0;
@@ -1607,14 +1671,27 @@ static BOOL WinDivertEvalTest(PEXPR test, BOOL *res)
ub[1] = 0x7FFFFFFF;
neg_lb = TRUE;
break;
case TOKEN_TCP_PAYLOAD32:
type = TOKEN_TCP;
lb[0] = 0; ub[0] = 0xFFFFFFFF;
break;
case TOKEN_UDP_PAYLOAD32:
type = TOKEN_UDP;
lb[0] = 0; ub[0] = 0xFFFFFFFF;
break;
case TOKEN_IF_IDX:
case TOKEN_SUB_IF_IDX:
case TOKEN_RANDOM32:
case TOKEN_PROCESS_ID:
lb[0] = 0; ub[0] = 0xFFFFFFFF;
break;
case TOKEN_ENDPOINT_ID:
case TOKEN_PARENT_ENDPOINT_ID:
lb[0] = lb[1] = 0;
ub[0] = ub[1] = 0xFFFFFFFF;
break;
default:
lb[0] = 0; ub[0] = 0xFFFFFFFF;
break;
return;
}
neg = (val->neg? TRUE: FALSE);
result_lb = WinDivertCompare128(neg, val->val, neg_lb, lb, /*big=*/TRUE);
@@ -1624,78 +1701,81 @@ static BOOL WinDivertEvalTest(PEXPR test, BOOL *res)
case TOKEN_EQ:
if (result_lb < 0 || result_ub > 0)
{
*res = FALSE;
return TRUE;
result = FALSE;
break;
}
if (eq && result_lb == 0)
{
*res = TRUE;
return TRUE;
result = TRUE;
break;
}
return FALSE;
return;
case TOKEN_NEQ:
if (result_lb < 0 || result_ub > 0)
{
*res = TRUE;
return TRUE;
result = TRUE;
break;
}
if (eq && result_lb == 0)
{
*res = FALSE;
return TRUE;
result = FALSE;
break;
}
return FALSE;
return;
case TOKEN_LT:
if (result_ub > 0)
{
*res = TRUE;
return TRUE;
result = TRUE;
break;
}
if (result_lb <= 0)
{
*res = FALSE;
return TRUE;
result = FALSE;
break;
}
return FALSE;
return;
case TOKEN_LEQ:
if (result_ub >= 0)
{
*res = TRUE;
return TRUE;
result = TRUE;
break;
}
if (result_lb < 0)
{
*res = FALSE;
return TRUE;
result = FALSE;
break;
}
return FALSE;
return;
case TOKEN_GT:
if (result_ub >= 0)
{
*res = FALSE;
return TRUE;
result = FALSE;
break;
}
if (result_lb < 0)
{
*res = TRUE;
return TRUE;
result = TRUE;
break;
}
return FALSE;
return;
case TOKEN_GEQ:
if (result_ub > 0)
{
*res = FALSE;
return TRUE;
result = FALSE;
break;
}
if (result_lb <= 0)
{
*res = TRUE;
return TRUE;
result = TRUE;
break;
}
return FALSE;
return;
default:
return FALSE;
return;
}
test->arg[0] = WinDivertMakeVar(type, NULL);
test->arg[1] = (result? WinDivertMakeOne(): WinDivertMakeZero());
test->kind = TOKEN_EQ;
}
/*
@@ -1705,7 +1785,6 @@ static INT16 WinDivertFlattenExpr(PEXPR expr, INT16 *label, INT16 succ,
INT16 fail, PEXPR *stack)
{
INT16 succ1, fail1;
BOOL res;
if (succ < 0 || fail < 0)
{
return -1;
@@ -1729,9 +1808,11 @@ static INT16 WinDivertFlattenExpr(PEXPR expr, INT16 *label, INT16 succ,
stack);
return succ;
default:
if (WinDivertEvalTest(expr, &res))
WinDivertSimplifyTest(expr);
if (expr->kind == TOKEN_EQ &&
expr->arg[0]->kind == TOKEN_TRUE)
{
return (res? succ: fail);
return (expr->arg[1]->val[0] != 0? succ: fail);
}
if (*label >= WINDIVERT_FILTER_MAXLEN)
{
+2 -2
View File
@@ -72,7 +72,7 @@
<p>
WinDivert is a powerful user-mode
capture/sniffing/modification/blocking/re-injection package for
Windows 7, Windows 8 and Windows 10.
Windows 10, Windows 11, and Windows Server.
WinDivert can be used to implement user-mode packet filters, packet sniffers,
firewalls, NAT, VPNs, tunneling applications, etc., without the need to
write kernel-mode code.
@@ -2317,7 +2317,7 @@ to convert the result into network-byte-order.
</p>
</dd></dl>
<a name="divert_helper_format_ipv4_address"><h3>6.11 WinDivertHelperParseIPv4Address</h3></a>
<a name="divert_helper_format_ipv4_address"><h3>6.11 WinDivertHelperFormatIPv4Address</h3></a>
<table border="1" cellpadding="5"><tr><td>
<pre>
BOOL <b>WinDivertHelperFormatIPv4Address</b>(
+1 -1
View File
@@ -4,7 +4,7 @@ Class = WFPCALLOUTS
ClassGuid = {57465043-616C-6C6F-7574-5F636C617373}
Provider = %Basil%
CatalogFile = WinDivert32.Cat
DriverVer = 08/08/2019,2.2.0
DriverVer = 01/09/2022,2.2.2
[SourceDisksNames]
1 = %DiskName%
+1 -1
View File
@@ -4,7 +4,7 @@ Class = WFPCALLOUTS
ClassGuid = {57465043-616C-6C6F-7574-5F636C617373}
Provider = %Basil%
CatalogFile = WinDivert64.Cat
DriverVer = 08/08/2019,2.2.0
DriverVer = 01/09/2022,2.2.2
[SourceDisksNames]
1 = %DiskName%
+110 -75
View File
@@ -1,6 +1,6 @@
/*
* windivert.c
* (C) 2019, all rights reserved,
* (C) 2022, all rights reserved,
*
* This file is part of WinDivert.
*
@@ -123,7 +123,6 @@ typedef enum
WINDIVERT_CONTEXT_STATE_OPEN = 0xB1, // Context is open.
WINDIVERT_CONTEXT_STATE_CLOSING = 0xC2, // Context is closing.
WINDIVERT_CONTEXT_STATE_CLOSED = 0xD3, // Context is closed.
WINDIVERT_CONTEXT_STATE_INVALID = 0xE4 // Context is invalid.
} context_state_t;
struct context_s
{
@@ -274,8 +273,6 @@ struct flow_s
UINT64 flow_id; // WFP flow ID.
UINT32 callout_id; // WFP callout ID.
UINT16 layer_id; // WFP layout ID.
BOOL inserted:1; // Flow inserted into context?
BOOL deleted:1; // Flow deleted from context?
BOOL outbound:1; // Flow is outound?
BOOL loopback:1; // Flow is loopback?
BOOL ipv6:1; // Flow is ipv6?
@@ -333,6 +330,7 @@ extern VOID windivert_worker(IN WDFWORKITEM item);
static void windivert_read_service(context_t context);
extern VOID windivert_create(IN WDFDEVICE device, IN WDFREQUEST request,
IN WDFFILEOBJECT object);
static NTSTATUS windivert_install_provider(void);
static NTSTATUS windivert_install_sublayer(layer_t layer);
static NTSTATUS windivert_install_callouts(context_t context, UINT8 layer,
UINT64 flags);
@@ -499,6 +497,15 @@ extern void windivert_reflect_worker(IN WDFWORKITEM item);
static void windivert_log_event(PEPROCESS process, PDRIVER_OBJECT driver,
const wchar_t *msg_str);
/*
* WinDivert provider GUIDs
*/
DEFINE_GUID(WINDIVERT_PROVIDER_GUID,
0x450EC398, 0x1EAF, 0x49F5,
0x85, 0xE0, 0x22, 0x8F, 0x0D, 0x29, 0x39, 0x21);
#define WINDIVERT_PROVIDER_NAME WINDIVERT_DEVICE_NAME
#define WINDIVERT_PROVIDER_DESC WINDIVERT_DEVICE_NAME L" provider"
/*
* WinDivert sublayer GUIDs
*/
@@ -680,7 +687,7 @@ static const struct layer_s windivert_layer_resource_assignment_ipv4 =
&WINDIVERT_SUBLAYER_RESOURCE_ASSIGNMENT_IPV4_GUID,
windivert_resource_assignment_v4_classify,
NULL,
0
UINT16_MAX
};
#define WINDIVERT_LAYER_RESOURCE_ASSIGNMENT_IPV4 \
(&windivert_layer_resource_assignment_ipv4)
@@ -697,7 +704,7 @@ static const struct layer_s windivert_layer_resource_assignment_ipv6 =
&WINDIVERT_SUBLAYER_RESOURCE_ASSIGNMENT_IPV6_GUID,
windivert_resource_assignment_v6_classify,
NULL,
0
UINT16_MAX
};
#define WINDIVERT_LAYER_RESOURCE_ASSIGNMENT_IPV6 \
(&windivert_layer_resource_assignment_ipv6)
@@ -714,7 +721,7 @@ static const struct layer_s windivert_layer_resource_release_ipv4 =
&WINDIVERT_SUBLAYER_RESOURCE_RELEASE_IPV4_GUID,
windivert_resource_release_v4_classify,
NULL,
0
UINT16_MAX
};
#define WINDIVERT_LAYER_RESOURCE_RELEASE_IPV4 \
(&windivert_layer_resource_release_ipv4)
@@ -731,7 +738,7 @@ static const struct layer_s windivert_layer_resource_release_ipv6 =
&WINDIVERT_SUBLAYER_RESOURCE_RELEASE_IPV6_GUID,
windivert_resource_release_v6_classify,
NULL,
0
UINT16_MAX
};
#define WINDIVERT_LAYER_RESOURCE_RELEASE_IPV6 \
(&windivert_layer_resource_release_ipv6)
@@ -748,7 +755,7 @@ static const struct layer_s windivert_layer_auth_connect_ipv4 =
&WINDIVERT_SUBLAYER_AUTH_CONNECT_IPV4_GUID,
windivert_auth_connect_v4_classify,
NULL,
0
UINT16_MAX
};
#define WINDIVERT_LAYER_AUTH_CONNECT_IPV4 \
(&windivert_layer_auth_connect_ipv4)
@@ -765,7 +772,7 @@ static const struct layer_s windivert_layer_auth_connect_ipv6 =
&WINDIVERT_SUBLAYER_AUTH_CONNECT_IPV6_GUID,
windivert_auth_connect_v6_classify,
NULL,
0
UINT16_MAX
};
#define WINDIVERT_LAYER_AUTH_CONNECT_IPV6 \
(&windivert_layer_auth_connect_ipv6)
@@ -782,7 +789,7 @@ static const struct layer_s windivert_layer_endpoint_closure_ipv4 =
&WINDIVERT_SUBLAYER_ENDPOINT_CLOSURE_IPV4_GUID,
windivert_endpoint_closure_v4_classify,
NULL,
0
UINT16_MAX
};
#define WINDIVERT_LAYER_ENDPOINT_CLOSURE_IPV4 \
(&windivert_layer_endpoint_closure_ipv4)
@@ -799,7 +806,7 @@ static const struct layer_s windivert_layer_endpoint_closure_ipv6 =
&WINDIVERT_SUBLAYER_ENDPOINT_CLOSURE_IPV6_GUID,
windivert_endpoint_closure_v6_classify,
NULL,
0
UINT16_MAX
};
#define WINDIVERT_LAYER_ENDPOINT_CLOSURE_IPV6 \
(&windivert_layer_endpoint_closure_ipv6)
@@ -816,7 +823,7 @@ static const struct layer_s windivert_layer_auth_listen_ipv4 =
&WINDIVERT_SUBLAYER_AUTH_LISTEN_IPV4_GUID,
windivert_auth_listen_v4_classify,
NULL,
0
UINT16_MAX
};
#define WINDIVERT_LAYER_AUTH_LISTEN_IPV4 \
(&windivert_layer_auth_listen_ipv4)
@@ -833,7 +840,7 @@ static const struct layer_s windivert_layer_auth_listen_ipv6 =
&WINDIVERT_SUBLAYER_AUTH_LISTEN_IPV6_GUID,
windivert_auth_listen_v6_classify,
NULL,
0
UINT16_MAX
};
#define WINDIVERT_LAYER_AUTH_LISTEN_IPV6 \
(&windivert_layer_auth_listen_ipv6)
@@ -850,7 +857,7 @@ static const struct layer_s windivert_layer_auth_recv_accept_ipv4 =
&WINDIVERT_SUBLAYER_AUTH_RECV_ACCEPT_IPV4_GUID,
windivert_auth_recv_accept_v4_classify,
NULL,
0
UINT16_MAX
};
#define WINDIVERT_LAYER_AUTH_RECV_ACCEPT_IPV4 \
(&windivert_layer_auth_recv_accept_ipv4)
@@ -867,7 +874,7 @@ static const struct layer_s windivert_layer_auth_recv_accept_ipv6 =
&WINDIVERT_SUBLAYER_AUTH_RECV_ACCEPT_IPV6_GUID,
windivert_auth_recv_accept_v6_classify,
NULL,
0
UINT16_MAX
};
#define WINDIVERT_LAYER_AUTH_RECV_ACCEPT_IPV6 \
(&windivert_layer_auth_recv_accept_ipv6)
@@ -884,7 +891,7 @@ static const struct layer_s windivert_layer_flow_established_ipv4 =
&WINDIVERT_SUBLAYER_FLOW_ESTABLISHED_IPV4_GUID,
windivert_flow_established_v4_classify,
windivert_flow_delete_notify,
0
UINT16_MAX
};
#define WINDIVERT_LAYER_FLOW_ESTABLISHED_IPV4 \
(&windivert_layer_flow_established_ipv4)
@@ -901,7 +908,7 @@ static const struct layer_s windivert_layer_flow_established_ipv6 =
&WINDIVERT_SUBLAYER_FLOW_ESTABLISHED_IPV6_GUID,
windivert_flow_established_v6_classify,
windivert_flow_delete_notify,
0
UINT16_MAX
};
#define WINDIVERT_LAYER_FLOW_ESTABLISHED_IPV6 \
(&windivert_layer_flow_established_ipv6)
@@ -1156,6 +1163,14 @@ extern NTSTATUS DriverEntry(IN PDRIVER_OBJECT driver_obj,
if (!NT_SUCCESS(status))
{
DEBUG_ERROR("failed to begin WFP transaction", status);
FwpmTransactionAbort0(engine_handle);
goto driver_entry_exit;
}
status = windivert_install_provider();
if (!NT_SUCCESS(status))
{
DEBUG_ERROR("failed to install provider", status);
FwpmTransactionAbort0(engine_handle);
goto driver_entry_exit;
}
status = windivert_install_sublayer(WINDIVERT_LAYER_INBOUND_NETWORK_IPV4);
@@ -1267,6 +1282,7 @@ driver_entry_sublayer_error:
if (!NT_SUCCESS(status))
{
DEBUG_ERROR("failed to commit WFP transaction", status);
FwpmTransactionAbort0(engine_handle);
goto driver_entry_exit;
}
@@ -1343,6 +1359,7 @@ static void windivert_driver_unload(void)
if (!NT_SUCCESS(status))
{
DEBUG_ERROR("failed to begin WFP transaction", status);
FwpmTransactionAbort0(engine_handle);
FwpmEngineClose0(engine_handle);
return;
}
@@ -1386,15 +1403,39 @@ static void windivert_driver_unload(void)
WINDIVERT_LAYER_AUTH_RECV_ACCEPT_IPV4->sublayer_guid);
FwpmSubLayerDeleteByKey0(engine_handle,
WINDIVERT_LAYER_AUTH_RECV_ACCEPT_IPV6->sublayer_guid);
FwpmProviderDeleteByKey0(engine_handle,
&WINDIVERT_PROVIDER_GUID);
status = FwpmTransactionCommit0(engine_handle);
if (!NT_SUCCESS(status))
{
FwpmTransactionAbort0(engine_handle);
DEBUG_ERROR("failed to commit WFP transaction", status);
}
FwpmEngineClose0(engine_handle);
}
}
/*
* Register provider.
*/
static NTSTATUS windivert_install_provider()
{
FWPM_PROVIDER0 provider;
NTSTATUS status;
RtlZeroMemory(&provider, sizeof(provider));
provider.providerKey = WINDIVERT_PROVIDER_GUID;
provider.displayData.name = WINDIVERT_PROVIDER_NAME;
provider.displayData.description = WINDIVERT_PROVIDER_DESC;
// We don't care about the install result as this provider
// is only for passing HLK test.
FwpmProviderAdd0(engine_handle, &provider, NULL);
return STATUS_SUCCESS;
}
/*
* Register a sub-layer.
*/
@@ -1529,7 +1570,7 @@ windivert_create_exit:
// Clean-up on error:
if (!NT_SUCCESS(status))
{
context->state = WINDIVERT_CONTEXT_STATE_INVALID;
context->state = WINDIVERT_CONTEXT_STATE_CLOSED;
if (context->read_queue != NULL)
{
WdfObjectDelete(context->read_queue);
@@ -1538,14 +1579,7 @@ windivert_create_exit:
{
WdfObjectDelete(context->worker);
}
if (context->process != NULL)
{
ObDereferenceObject(context->process);
}
if (context->engine_handle != NULL)
{
FwpmEngineClose0(context->engine_handle);
}
// process/engine_handle handled by windivert_destroy()
}
WdfRequestComplete(request, status);
@@ -1564,15 +1598,15 @@ static NTSTATUS windivert_install_callouts(context_t context, UINT8 layer,
accept, close;
NTSTATUS status = STATUS_SUCCESS;
inbound = ((flags & WINDIVERT_FILTER_FLAG_INBOUND) != 0);
outbound = ((flags & WINDIVERT_FILTER_FLAG_OUTBOUND) != 0);
ipv4 = ((flags & WINDIVERT_FILTER_FLAG_IP) != 0);
ipv6 = ((flags & WINDIVERT_FILTER_FLAG_IPV6) != 0);
bind = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_BIND) != 0);
connect = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_CONNECT) != 0);
listen = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_LISTEN) != 0);
accept = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_ACCEPT) != 0);
close = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_CLOSE) != 0);
inbound = ((flags & WINDIVERT_FILTER_FLAG_INBOUND) != 0);
outbound = ((flags & WINDIVERT_FILTER_FLAG_OUTBOUND) != 0);
ipv4 = ((flags & WINDIVERT_FILTER_FLAG_IP) != 0);
ipv6 = ((flags & WINDIVERT_FILTER_FLAG_IPV6) != 0);
bind = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_BIND) != 0);
connect = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_CONNECT) != 0);
listen = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_LISTEN) != 0);
accept = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_ACCEPT) != 0);
close = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_CLOSE) != 0);
i = 0;
switch (layer)
@@ -1764,8 +1798,7 @@ static NTSTATUS windivert_install_callout(context_t context, UINT idx,
if (!NT_SUCCESS(status))
{
DEBUG_ERROR("failed to begin WFP transaction", status);
FwpsCalloutUnregisterByKey0(&callout_guid);
return status;
goto windivert_install_callout_error;
}
status = FwpmCalloutAdd0(engine, &mcallout, NULL, NULL);
if (!NT_SUCCESS(status))
@@ -1783,8 +1816,7 @@ static NTSTATUS windivert_install_callout(context_t context, UINT idx,
if (!NT_SUCCESS(status))
{
DEBUG_ERROR("failed to commit WFP transaction", status);
FwpsCalloutUnregisterByKey0(&callout_guid);
return status;
goto windivert_install_callout_error;
}
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
@@ -1839,6 +1871,7 @@ windivert_uninstall_callouts_error:
// RPC handle was closed first. So, this path is "normal" if
// the user's app crashed or never closed the WinDivert handle.
DEBUG_ERROR("failed to begin WFP transaction", status);
FwpmTransactionAbort0(engine);
goto windivert_uninstall_callouts_unregister;
}
for (i = 0; i < WINDIVERT_CONTEXT_MAXLAYERS; i++)
@@ -1883,6 +1916,7 @@ windivert_uninstall_callouts_error:
if (!NT_SUCCESS(status))
{
DEBUG_ERROR("failed to commit WFP transaction", status);
FwpmTransactionAbort0(engine);
// continue
}
@@ -1945,17 +1979,20 @@ windivert_cleanup_error:
context->state = WINDIVERT_CONTEXT_STATE_CLOSING;
sniff_mode = ((context->flags & WINDIVERT_FLAG_SNIFF) != 0);
forward = (context->layer == WINDIVERT_LAYER_NETWORK_FORWARD);
while (!IsListEmpty(&context->flow_set))
entry = context->flow_set.Flink;
if (entry != &context->flow_set)
{
entry = RemoveHeadList(&context->flow_set);
flow = CONTAINING_RECORD(entry, struct flow_s, entry);
flow->deleted = TRUE;
KeReleaseInStackQueuedSpinLock(&lock_handle);
status = FwpsFlowRemoveContext0(flow->flow_id, flow->layer_id,
flow->callout_id);
if (!NT_SUCCESS(status))
for (; entry != &context->flow_set; entry = entry->Flink)
{
windivert_free(flow);
flow = CONTAINING_RECORD(entry, struct flow_s, entry);
status = FwpsFlowRemoveContext0(flow->flow_id, flow->layer_id,
flow->callout_id);
if (!NT_SUCCESS(status) && status != STATUS_UNSUCCESSFUL)
{
// For STATUS_UNSUCCESSFUL, flow_delete() is still called.
WdfObjectDereference((WDFOBJECT)object);
}
}
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
}
@@ -2050,6 +2087,8 @@ extern VOID windivert_destroy(IN WDFOBJECT object)
KLOCK_QUEUE_HANDLE lock_handle;
context_t context = windivert_context_get((WDFFILEOBJECT)object);
const WINDIVERT_FILTER *filter;
PLIST_ENTRY entry;
flow_t flow;
NTSTATUS status;
DEBUG("DESTROY: destroying WinDivert context (context=%p)", context);
@@ -2065,9 +2104,21 @@ extern VOID windivert_destroy(IN WDFOBJECT object)
filter = context->filter;
KeReleaseInStackQueuedSpinLock(&lock_handle);
windivert_uninstall_callouts(context, WINDIVERT_CONTEXT_STATE_CLOSED);
FwpmEngineClose0(context->engine_handle);
if (context->engine_handle != NULL)
{
FwpmEngineClose0(context->engine_handle);
}
windivert_free((PVOID)filter);
ObDereferenceObject(context->process);
while (!IsListEmpty(&context->flow_set))
{
entry = RemoveHeadList(&context->flow_set);
flow = CONTAINING_RECORD(entry, struct flow_s, entry);
windivert_free(flow);
}
if (context->process != NULL)
{
ObDereferenceObject(context->process);
}
}
/*
@@ -4022,7 +4073,7 @@ static void windivert_flow_established_v6_classify(
UNREFERENCED_PARAMETER(data);
UNREFERENCED_PARAMETER(flow_context);
flow_data.ProcessId = (UINT32)meta_vals->processId;
flow_data.EndpointId = meta_vals->transportEndpointHandle;
flow_data.ParentEndpointId = meta_vals->parentEndpointHandle;
flow_data.ProcessId = (UINT32)meta_vals->processId;
windivert_get_ipv6_addr(fixed_vals,
@@ -4137,22 +4188,11 @@ static void windivert_flow_established_classify(context_t context,
flow->flow_id = flow_id;
flow->callout_id = callout_id;
flow->layer_id = layer_id;
flow->inserted = FALSE;
flow->deleted = FALSE;
flow->outbound = outbound;
flow->loopback = loopback;
flow->ipv6 = !ipv4;
RtlCopyMemory(&flow->data, flow_data, sizeof(flow->data));
status = FwpsFlowAssociateContext0(flow_id, layer_id, callout_id,
(UINT64)flow);
if (!NT_SUCCESS(status))
{
windivert_free(flow);
WdfObjectDereference(object);
return;
}
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
if (context->state != WINDIVERT_CONTEXT_STATE_OPEN ||
context->shutdown_recv)
@@ -4162,19 +4202,16 @@ static void windivert_flow_established_classify(context_t context,
WdfObjectDereference(object);
return;
}
if (!flow->deleted)
status = FwpsFlowAssociateContext0(flow_id, layer_id, callout_id,
(UINT64)flow);
if (!NT_SUCCESS(status))
{
InsertTailList(&context->flow_set, &flow->entry);
flow->inserted = TRUE;
}
else
{
// Flow was deleted before insertion; we are responsible for cleanup.
KeReleaseInStackQueuedSpinLock(&lock_handle);
windivert_free(flow);
WdfObjectDereference(object);
return;
}
InsertTailList(&context->flow_set, &flow->entry);
KeReleaseInStackQueuedSpinLock(&lock_handle);
}
@@ -4201,18 +4238,16 @@ static void windivert_flow_delete_notify(UINT16 layer_id, UINT32 callout_id,
{
return;
}
timestamp = KeQueryPerformanceCounter(NULL).QuadPart;
context = flow->context;
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
object = (WDFOBJECT)context->object; // referenced in flow_established.
if (flow->inserted && !flow->deleted)
cleanup = (context->state == WINDIVERT_CONTEXT_STATE_OPEN);
if (cleanup)
{
RemoveEntryList(&flow->entry);
}
flow->deleted = TRUE;
cleanup = flow->inserted;
if (context->state != WINDIVERT_CONTEXT_STATE_OPEN ||
context->shutdown_recv)
{
@@ -4237,12 +4272,12 @@ static void windivert_flow_delete_notify(UINT16 layer_id, UINT32 callout_id,
}
windivert_flow_delete_notify_exit:
if (cleanup)
{
// If context->state != OPEN, then destroy() will free the flow.
windivert_free(flow);
WdfObjectDereference(object);
}
WdfObjectDereference(object);
}
/*
+2 -2
View File
@@ -1,6 +1,6 @@
/*
* windivert.rc
* (C) 2019, all rights reserved,
* (C) 2022, all rights reserved,
*
* This file is part of WinDivert.
*
@@ -48,7 +48,7 @@
#define VER_PRODUCTVERSION 2.2
#define VER_PRODUCTVERSION_STR "2.2"
#define VER_COMPANYNAME_STR "Basil"
#define VER_LEGALCOPYRIGHT_YEARS "2011-2019"
#define VER_LEGALCOPYRIGHT_YEARS "2011-2022"
#define VER_LEGALCOPYRIGHT_STR \
"Copyright \251 " VER_COMPANYNAME_STR " " VER_LEGALCOPYRIGHT_YEARS
#define VER_FILEVERSION VER_PRODUCTVERSION
+3 -1
View File
@@ -1,6 +1,6 @@
/*
* test.c
* (C) 2019, all rights reserved,
* (C) 2021, all rights reserved,
*
* This file is part of WinDivert.
*
@@ -632,6 +632,7 @@ static const struct test tests[] =
{"localAddr == 10.0.0.1 && remoteAddr == 8.8.4.4 && "
"localPort == 57413 && remotePort == 53 && protocol == 17",
&pkt_dns_request, TRUE},
{"ipv6.DstAddr >= ::", &pkt_dns_request, FALSE},
{"ipv6", &pkt_ipv6_tcp_syn, TRUE},
{"ip", &pkt_ipv6_tcp_syn, FALSE},
{"tcp.Syn", &pkt_ipv6_tcp_syn, TRUE},
@@ -815,6 +816,7 @@ static const struct test tests[] =
{"ipv6.SrcAddr != abcd::1", &pkt_ipv6_exthdrs_udp, TRUE},
{"ipv6.SrcAddr >= abcd::1", &pkt_ipv6_exthdrs_udp, FALSE},
{"ipv6.SrcAddr > abcd::1", &pkt_ipv6_exthdrs_udp, FALSE},
{"ipv6.DstAddr >= ::", &pkt_ipv6_exthdrs_udp, TRUE},
{"timestamp > -1", &pkt_ipv6_exthdrs_udp, TRUE},
{"udp.SrcPort == 4660 and udp.DstPort == 43690",
&pkt_ipv6_exthdrs_udp, TRUE},