Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1789526ecf | |||
| 3402f8b2f1 | |||
| 65bb889c79 | |||
| c983d554c9 | |||
| 0b164b6ba3 | |||
| 7f35b0c8f8 | |||
| ea25bab7c5 | |||
| c26ec39465 | |||
| 227a6b1e78 | |||
| 134dd37bd0 | |||
| 97056af256 | |||
| db674a6696 | |||
| 32af280add |
@@ -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.
|
||||
|
||||
@@ -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:
|
||||
|
||||
+134
-53
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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},
|
||||
|
||||
Reference in New Issue
Block a user