Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 97101072db | |||
| 8bda0aff7b | |||
| 34b565de65 | |||
| 90396ffa2b | |||
| 8cdddce6ac | |||
| c26ec39465 | |||
| 227a6b1e78 | |||
| 134dd37bd0 | |||
| 97056af256 | |||
| db674a6696 | |||
| 32af280add |
+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)
|
||||
{
|
||||
|
||||
+1
-1
@@ -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>(
|
||||
|
||||
+363
-224
@@ -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
|
||||
{
|
||||
@@ -243,8 +242,9 @@ struct packet_s
|
||||
UINT32 ip_checksum:1; // Packet has IPv4 checksum?
|
||||
UINT32 tcp_checksum:1; // Packet has TCP checksum?
|
||||
UINT32 udp_checksum:1; // Packet has UDP checksum?
|
||||
UINT32 icmp_checksum:1; // Packet has ICMP(V6) checksum?
|
||||
UINT32 match:1; // Packet matches filter?
|
||||
UINT32 padding:7; // Padding for alignment.
|
||||
UINT32 padding:6; // Padding for alignment.
|
||||
UINT32 packet_size; // Packet total size.
|
||||
PVOID object; // Object associated with packet.
|
||||
UINT32 priority; // Packet priority.
|
||||
@@ -333,6 +333,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);
|
||||
@@ -347,8 +348,7 @@ static NTSTATUS windivert_write(context_t context, WDFREQUEST request,
|
||||
req_context_t req_context);
|
||||
static void NTAPI windivert_inject_complete(VOID *context,
|
||||
NET_BUFFER_LIST *packets, BOOLEAN dispatch_level);
|
||||
static void NTAPI windivert_reinject_complete(VOID *context,
|
||||
NET_BUFFER_LIST *packets, BOOLEAN dispatch_level);
|
||||
static void windivert_inject_packet_too_big(packet_t packet);
|
||||
static NTSTATUS windivert_notify(IN FWPS_CALLOUT_NOTIFY_TYPE type,
|
||||
IN const GUID *filter_key, IN const FWPS_FILTER0 *filter);
|
||||
static void windivert_outbound_network_v4_classify(
|
||||
@@ -469,7 +469,7 @@ static BOOL windivert_queue_work(context_t context, PVOID packet,
|
||||
UINT64 flags, UINT32 priority, BOOL ipv4, BOOL outbound, BOOL loopback,
|
||||
BOOL impostor, BOOL match, LONGLONG timestamp);
|
||||
static void windivert_queue_packet(context_t context, packet_t packet);
|
||||
static void windivert_reinject_packet(packet_t packet);
|
||||
static NTSTATUS windivert_inject_packet(packet_t packet);
|
||||
static void windivert_free_packet(packet_t packet);
|
||||
static BOOL windivert_copy_data(PNET_BUFFER buffer, PVOID data, UINT size);
|
||||
static BOOL windivert_get_data(PNET_BUFFER buffer, UINT length, INT min,
|
||||
@@ -499,6 +499,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 +689,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 +706,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 +723,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 +740,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 +757,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 +774,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 +791,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 +808,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 +825,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 +842,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 +859,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 +876,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 +893,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 +910,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 +1165,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 +1284,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 +1361,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 +1405,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 +1572,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 +1581,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 +1600,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 +1800,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 +1818,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 +1873,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 +1918,7 @@ windivert_uninstall_callouts_error:
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_ERROR("failed to commit WFP transaction", status);
|
||||
FwpmTransactionAbort0(engine);
|
||||
// continue
|
||||
}
|
||||
|
||||
@@ -1969,7 +2005,7 @@ windivert_cleanup_error:
|
||||
timeout = WINDIVERT_TIMEOUT(context, packet->timestamp, timestamp);
|
||||
if (!sniff_mode && !timeout)
|
||||
{
|
||||
windivert_reinject_packet(packet);
|
||||
windivert_inject_packet(packet);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1991,7 +2027,7 @@ windivert_cleanup_error:
|
||||
timeout = WINDIVERT_TIMEOUT(context, work->timestamp, timestamp);
|
||||
if (!sniff_mode && !timeout)
|
||||
{
|
||||
windivert_reinject_packet(work);
|
||||
windivert_inject_packet(work);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2065,9 +2101,15 @@ 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);
|
||||
if (context->process != NULL)
|
||||
{
|
||||
ObDereferenceObject(context->process);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2548,19 +2590,20 @@ static NTSTATUS windivert_write(context_t context, WDFREQUEST request,
|
||||
req_context_t req_context)
|
||||
{
|
||||
KLOCK_QUEUE_HANDLE lock_handle;
|
||||
PMDL mdl = NULL, mdl_copy = NULL;
|
||||
PVOID data, data_copy = NULL;
|
||||
UINT data_len, packet_len, inject_len;
|
||||
PMDL mdl = NULL;
|
||||
PVOID data, data_copy;
|
||||
packet_t packet;
|
||||
UINT data_len, packet_len, packet_size, inject_len;
|
||||
PWINDIVERT_DATA_NETWORK network_data;
|
||||
PWINDIVERT_IPHDR ip_header;
|
||||
PWINDIVERT_IPV6HDR ipv6_header;
|
||||
BOOL ipv4;
|
||||
UINT8 layer;
|
||||
UINT32 priority;
|
||||
UINT64 flags, checksums;
|
||||
HANDLE handle;
|
||||
PNET_BUFFER_LIST buffers = NULL;
|
||||
PWINDIVERT_ADDRESS addr;
|
||||
UINT i, addr_len, addr_len_max;
|
||||
UINT i, addr_len, addr_len_max, version;
|
||||
NTSTATUS status = STATUS_SUCCESS, status_soft_error = STATUS_SUCCESS;
|
||||
|
||||
DEBUG("WRITE: writing/injecting a packet (context=%p, request=%p)",
|
||||
@@ -2629,10 +2672,6 @@ static NTSTATUS windivert_write(context_t context, WDFREQUEST request,
|
||||
i < WINDIVERT_BATCH_MAX;
|
||||
i++, addr_len += sizeof(WINDIVERT_ADDRESS))
|
||||
{
|
||||
buffers = NULL;
|
||||
mdl_copy = NULL;
|
||||
data_copy = NULL;
|
||||
|
||||
// Get the packet length:
|
||||
if (data_len < sizeof(WINDIVERT_IPHDR))
|
||||
{
|
||||
@@ -2642,11 +2681,15 @@ windivert_write_too_small_packet:
|
||||
goto windivert_write_hard_error;
|
||||
}
|
||||
ip_header = (PWINDIVERT_IPHDR)data;
|
||||
switch (ip_header->Version)
|
||||
version = ip_header->Version;
|
||||
switch (version)
|
||||
{
|
||||
case 4:
|
||||
packet_len = RtlUshortByteSwap(ip_header->Length);
|
||||
ipv4 = TRUE;
|
||||
if (packet_len < sizeof(WINDIVERT_IPHDR))
|
||||
{
|
||||
goto windivert_write_invalid_packet;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
if (data_len < sizeof(WINDIVERT_IPV6HDR))
|
||||
@@ -2656,11 +2699,11 @@ windivert_write_too_small_packet:
|
||||
ipv6_header = (PWINDIVERT_IPV6HDR)data;
|
||||
packet_len = RtlUshortByteSwap(ipv6_header->Length) +
|
||||
sizeof(WINDIVERT_IPV6HDR);
|
||||
ipv4 = FALSE;
|
||||
break;
|
||||
default:
|
||||
windivert_write_invalid_packet:
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
DEBUG_ERROR("failed to inject non-IP packet", status);
|
||||
DEBUG_ERROR("failed to inject invalid packet", status);
|
||||
goto windivert_write_hard_error;
|
||||
}
|
||||
if (data_len < packet_len)
|
||||
@@ -2668,100 +2711,77 @@ windivert_write_too_small_packet:
|
||||
goto windivert_write_too_small_packet;
|
||||
}
|
||||
|
||||
// Copy packet data:
|
||||
data_copy = windivert_malloc(packet_len, FALSE);
|
||||
if (data_copy == NULL)
|
||||
// Copy packet & data:
|
||||
packet_size = WINDIVERT_PACKET_SIZE(WINDIVERT_DATA_NETWORK,
|
||||
packet_len);
|
||||
packet = (packet_t)windivert_malloc(packet_size, FALSE);
|
||||
if (packet == NULL)
|
||||
{
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
DEBUG_ERROR("failed to allocate memory for injected packet data",
|
||||
DEBUG_ERROR("failed to allocate memory for injected packet",
|
||||
status);
|
||||
goto windivert_write_hard_error;
|
||||
}
|
||||
packet->layer = layer;
|
||||
packet->event = WINDIVERT_EVENT_NETWORK_PACKET;
|
||||
packet->sniffed = 0; // Unused
|
||||
packet->outbound = addr[i].Outbound;
|
||||
packet->loopback = 0; // Unused
|
||||
packet->impostor = addr[i].Impostor;
|
||||
packet->ipv6 = (version == 6? 1: 0);
|
||||
packet->ip_checksum = addr[i].IPChecksum;
|
||||
packet->tcp_checksum = addr[i].TCPChecksum;
|
||||
packet->udp_checksum = addr[i].UDPChecksum;
|
||||
packet->icmp_checksum = 1; // Assumed valid
|
||||
packet->match = 0; // Unused
|
||||
packet->packet_size = packet_size;
|
||||
packet->packet_len = packet_len;
|
||||
packet->priority = priority;
|
||||
packet->timestamp = 0; // Unused
|
||||
packet->object = NULL;
|
||||
network_data =
|
||||
(PWINDIVERT_DATA_NETWORK)WINDIVERT_LAYER_DATA_PTR(packet);
|
||||
RtlCopyMemory(network_data, &addr[i].Network, sizeof(network_data));
|
||||
data_copy = WINDIVERT_PACKET_DATA_PTR(WINDIVERT_DATA_NETWORK, packet);
|
||||
RtlCopyMemory(data_copy, data, packet_len);
|
||||
switch (version)
|
||||
{
|
||||
case 4:
|
||||
ip_header = (PWINDIVERT_IPHDR)data_copy;
|
||||
if (ip_header->Version != 4 ||
|
||||
packet_len != RtlUshortByteSwap(ip_header->Length))
|
||||
{
|
||||
windivert_free(packet);
|
||||
goto windivert_write_invalid_packet;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
ipv6_header = (PWINDIVERT_IPV6HDR)data_copy;
|
||||
if (ipv6_header->Version != 6 ||
|
||||
packet_len != RtlUshortByteSwap(ipv6_header->Length) +
|
||||
sizeof(WINDIVERT_IPV6HDR))
|
||||
{
|
||||
windivert_free(packet);
|
||||
goto windivert_write_invalid_packet;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Check bounds:
|
||||
DEBUG_BOUNDS_CHECK((PVOID)addr, (UINT8 *)addr + addr_len_max,
|
||||
(PVOID)&addr[i], (PVOID)&addr[i+1]);
|
||||
|
||||
// Fix checksums:
|
||||
if (addr[i].IPChecksum == 0 || addr[i].TCPChecksum == 0 ||
|
||||
addr[i].UDPChecksum == 0)
|
||||
{
|
||||
checksums =
|
||||
(addr[i].IPChecksum == 0? 0:
|
||||
WINDIVERT_HELPER_NO_IP_CHECKSUM) |
|
||||
(addr[i].TCPChecksum == 0? 0:
|
||||
WINDIVERT_HELPER_NO_TCP_CHECKSUM) |
|
||||
(addr[i].UDPChecksum == 0? 0:
|
||||
WINDIVERT_HELPER_NO_UDP_CHECKSUM) |
|
||||
WINDIVERT_HELPER_NO_ICMP_CHECKSUM |
|
||||
WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM;
|
||||
WinDivertHelperCalcChecksums(data_copy, packet_len, NULL,
|
||||
checksums);
|
||||
}
|
||||
|
||||
// Decrement TTL for impostor packets:
|
||||
if (addr[i].Impostor &&
|
||||
!WinDivertHelperDecrementTTL(data_copy, packet_len))
|
||||
{
|
||||
status_soft_error = STATUS_HOPLIMIT_EXCEEDED;
|
||||
windivert_free(data_copy);
|
||||
goto windivert_write_loop;
|
||||
}
|
||||
|
||||
// Allocate packet:
|
||||
mdl_copy = IoAllocateMdl(data_copy, packet_len, FALSE, FALSE, NULL);
|
||||
if (mdl_copy == NULL)
|
||||
{
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
DEBUG_ERROR("failed to allocate MDL for injected packet", status);
|
||||
goto windivert_write_hard_error;
|
||||
}
|
||||
MmBuildMdlForNonPagedPool(mdl_copy);
|
||||
status = FwpsAllocateNetBufferAndNetBufferList0(nbl_pool_handle, 0, 0,
|
||||
mdl_copy, 0, packet_len, &buffers);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_ERROR("failed to create NET_BUFFER_LIST for injected packet",
|
||||
status);
|
||||
goto windivert_write_hard_error;
|
||||
}
|
||||
|
||||
// Inject packet:
|
||||
if (layer == WINDIVERT_LAYER_NETWORK_FORWARD)
|
||||
{
|
||||
handle = (ipv4? inject_handle_forward: injectv6_handle_forward);
|
||||
status = FwpsInjectForwardAsync0(handle, (HANDLE)priority, 0,
|
||||
(ipv4? AF_INET: AF_INET6), UNSPECIFIED_COMPARTMENT_ID,
|
||||
addr[i].Network.IfIdx, buffers, windivert_inject_complete,
|
||||
data_copy);
|
||||
}
|
||||
else if (addr[i].Outbound != 0)
|
||||
{
|
||||
handle = (ipv4? inject_handle_out: injectv6_handle_out);
|
||||
status = FwpsInjectNetworkSendAsync0(handle, (HANDLE)priority, 0,
|
||||
UNSPECIFIED_COMPARTMENT_ID, buffers, windivert_inject_complete,
|
||||
data_copy);
|
||||
}
|
||||
else
|
||||
{
|
||||
handle = (ipv4? inject_handle_in: injectv6_handle_in);
|
||||
status = FwpsInjectNetworkReceiveAsync0(handle, (HANDLE)priority, 0,
|
||||
UNSPECIFIED_COMPARTMENT_ID, addr[i].Network.IfIdx,
|
||||
addr[i].Network.SubIfIdx, buffers, windivert_inject_complete,
|
||||
data_copy);
|
||||
}
|
||||
|
||||
status = windivert_inject_packet(packet);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
if (status == STATUS_INSUFFICIENT_RESOURCES)
|
||||
{
|
||||
goto windivert_write_hard_error;
|
||||
}
|
||||
status_soft_error = status;
|
||||
FwpsFreeNetBufferList0(buffers);
|
||||
IoFreeMdl(mdl_copy);
|
||||
windivert_free(data_copy);
|
||||
}
|
||||
|
||||
windivert_write_loop:
|
||||
|
||||
// Reset state:
|
||||
inject_len += packet_len;
|
||||
data = (PVOID)((UINT8 *)data + packet_len);
|
||||
@@ -2776,54 +2796,9 @@ windivert_write_loop:
|
||||
windivert_write_hard_error:
|
||||
|
||||
// Request to be completed in windivert_ioctl()
|
||||
if (buffers != NULL)
|
||||
{
|
||||
FwpsFreeNetBufferList0(buffers);
|
||||
}
|
||||
if (mdl_copy != NULL)
|
||||
{
|
||||
IoFreeMdl(mdl_copy);
|
||||
}
|
||||
windivert_free(data_copy);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* WinDivert inject complete routine.
|
||||
*/
|
||||
static void NTAPI windivert_inject_complete(VOID *data,
|
||||
NET_BUFFER_LIST *buffers, BOOLEAN dispatch_level)
|
||||
{
|
||||
PMDL mdl;
|
||||
PNET_BUFFER buffer;
|
||||
UNREFERENCED_PARAMETER(dispatch_level);
|
||||
|
||||
buffer = NET_BUFFER_LIST_FIRST_NB(buffers);
|
||||
mdl = NET_BUFFER_FIRST_MDL(buffer);
|
||||
windivert_free(data);
|
||||
IoFreeMdl(mdl);
|
||||
FwpsFreeNetBufferList0(buffers);
|
||||
}
|
||||
|
||||
/*
|
||||
* WinDivert reinject complete routine.
|
||||
*/
|
||||
static void NTAPI windivert_reinject_complete(VOID *context,
|
||||
NET_BUFFER_LIST *buffers, BOOLEAN dispatch_level)
|
||||
{
|
||||
PMDL mdl;
|
||||
PNET_BUFFER buffer;
|
||||
packet_t packet;
|
||||
UNREFERENCED_PARAMETER(dispatch_level);
|
||||
|
||||
buffer = NET_BUFFER_LIST_FIRST_NB(buffers);
|
||||
packet = (packet_t)context;
|
||||
mdl = NET_BUFFER_FIRST_MDL(buffer);
|
||||
windivert_free_packet(packet);
|
||||
IoFreeMdl(mdl);
|
||||
FwpsFreeNetBufferList0(buffers);
|
||||
}
|
||||
|
||||
/*
|
||||
* WinDivert caller context preprocessing.
|
||||
@@ -4022,7 +3997,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,
|
||||
@@ -4869,7 +4844,7 @@ VOID windivert_worker(IN WDFWORKITEM item)
|
||||
}
|
||||
else
|
||||
{
|
||||
windivert_reinject_packet(work);
|
||||
windivert_inject_packet(work);
|
||||
}
|
||||
|
||||
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
|
||||
@@ -5030,21 +5005,22 @@ static BOOL windivert_queue_work(context_t context, PVOID packet,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
work->layer = layer;
|
||||
work->event = event;
|
||||
work->sniffed = (sniffed? 1: 0);
|
||||
work->outbound = (outbound? 1: 0);
|
||||
work->loopback = (loopback? 1: 0);
|
||||
work->impostor = (impostor? 1: 0);
|
||||
work->ipv6 = (!ipv4? 1: 0);
|
||||
work->ip_checksum = (ip_checksum? 1: 0);
|
||||
work->tcp_checksum = (tcp_checksum? 1: 0);
|
||||
work->udp_checksum = (udp_checksum? 1: 0);
|
||||
work->match = match;
|
||||
work->packet_size = packet_size;
|
||||
work->priority = priority;
|
||||
work->timestamp = timestamp;
|
||||
work->object = object;
|
||||
work->layer = layer;
|
||||
work->event = event;
|
||||
work->sniffed = (sniffed? 1: 0);
|
||||
work->outbound = (outbound? 1: 0);
|
||||
work->loopback = (loopback? 1: 0);
|
||||
work->impostor = (impostor? 1: 0);
|
||||
work->ipv6 = (!ipv4? 1: 0);
|
||||
work->ip_checksum = (ip_checksum? 1: 0);
|
||||
work->tcp_checksum = (tcp_checksum? 1: 0);
|
||||
work->udp_checksum = (udp_checksum? 1: 0);
|
||||
work->icmp_checksum = 1;
|
||||
work->match = match;
|
||||
work->packet_size = packet_size;
|
||||
work->priority = priority;
|
||||
work->timestamp = timestamp;
|
||||
work->object = object;
|
||||
if (object != NULL)
|
||||
{
|
||||
ObfReferenceObject(object);
|
||||
@@ -5106,7 +5082,7 @@ static void windivert_queue_packet(context_t context, packet_t packet)
|
||||
if (context->state != WINDIVERT_CONTEXT_STATE_OPEN)
|
||||
{
|
||||
KeReleaseInStackQueuedSpinLock(&lock_handle);
|
||||
windivert_reinject_packet(packet);
|
||||
windivert_inject_packet(packet);
|
||||
return;
|
||||
}
|
||||
if (packet->packet_size > context->packet_queue_maxsize)
|
||||
@@ -5158,9 +5134,9 @@ static void windivert_queue_packet(context_t context, packet_t packet)
|
||||
}
|
||||
|
||||
/*
|
||||
* Re-inject a packet.
|
||||
* Inject a packet.
|
||||
*/
|
||||
static void windivert_reinject_packet(packet_t packet)
|
||||
static NTSTATUS windivert_inject_packet(packet_t packet)
|
||||
{
|
||||
UINT8 *packet_data;
|
||||
UINT32 packet_len;
|
||||
@@ -5176,7 +5152,7 @@ static void windivert_reinject_packet(packet_t packet)
|
||||
packet->layer != WINDIVERT_LAYER_NETWORK_FORWARD)
|
||||
{
|
||||
windivert_free_packet(packet);
|
||||
return;
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
network_data = (PWINDIVERT_DATA_NETWORK)WINDIVERT_LAYER_DATA_PTR(packet);
|
||||
@@ -5184,47 +5160,43 @@ static void windivert_reinject_packet(packet_t packet)
|
||||
packet_len = packet->packet_len;
|
||||
|
||||
// Fix checksums:
|
||||
if (packet->ip_checksum == 0 || packet->tcp_checksum == 0 ||
|
||||
packet->udp_checksum == 0)
|
||||
{
|
||||
checksums =
|
||||
(packet->ip_checksum == 0? 0: WINDIVERT_HELPER_NO_IP_CHECKSUM) |
|
||||
(packet->tcp_checksum == 0? 0: WINDIVERT_HELPER_NO_TCP_CHECKSUM) |
|
||||
(packet->udp_checksum == 0? 0: WINDIVERT_HELPER_NO_UDP_CHECKSUM) |
|
||||
WINDIVERT_HELPER_NO_ICMP_CHECKSUM |
|
||||
WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM;
|
||||
WinDivertHelperCalcChecksums(packet_data, packet_len, NULL, checksums);
|
||||
}
|
||||
checksums =
|
||||
(packet->ip_checksum == 0? 0: WINDIVERT_HELPER_NO_IP_CHECKSUM) |
|
||||
(packet->tcp_checksum == 0? 0: WINDIVERT_HELPER_NO_TCP_CHECKSUM) |
|
||||
(packet->udp_checksum == 0? 0: WINDIVERT_HELPER_NO_UDP_CHECKSUM) |
|
||||
(packet->icmp_checksum == 0? 0: WINDIVERT_HELPER_NO_ICMP_CHECKSUM |
|
||||
WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM);
|
||||
WinDivertHelperCalcChecksums(packet_data, packet_len, NULL, checksums);
|
||||
|
||||
// Decrement TTL for impostor packets:
|
||||
if (packet->impostor != 0 &&
|
||||
!WinDivertHelperDecrementTTL(packet_data, packet_len))
|
||||
{
|
||||
status = STATUS_HOPLIMIT_EXCEEDED;
|
||||
DEBUG_ERROR("failed to reinject ttl-exceeded impostor packet", status);
|
||||
DEBUG_ERROR("failed to inject ttl-exceeded impostor packet", status);
|
||||
windivert_free_packet(packet);
|
||||
return;
|
||||
return status;
|
||||
}
|
||||
|
||||
// Reinject packet:
|
||||
// Inject packet:
|
||||
mdl = IoAllocateMdl(packet_data, packet_len, FALSE, FALSE, NULL);
|
||||
if (mdl == NULL)
|
||||
{
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
DEBUG_ERROR("failed to allocate MDL for reinjected packet", status);
|
||||
DEBUG_ERROR("failed to allocate MDL for injected packet", status);
|
||||
windivert_free_packet(packet);
|
||||
return;
|
||||
return status;
|
||||
}
|
||||
MmBuildMdlForNonPagedPool(mdl);
|
||||
status = FwpsAllocateNetBufferAndNetBufferList0(nbl_pool_handle, 0, 0,
|
||||
mdl, 0, packet_len, &buffers);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_ERROR("failed to create NET_BUFFER_LIST for reinjected packet",
|
||||
DEBUG_ERROR("failed to create NET_BUFFER_LIST for injected packet",
|
||||
status);
|
||||
IoFreeMdl(mdl);
|
||||
windivert_free_packet(packet);
|
||||
return;
|
||||
return status;
|
||||
}
|
||||
priority = packet->priority;
|
||||
if (packet->layer == WINDIVERT_LAYER_NETWORK_FORWARD)
|
||||
@@ -5232,14 +5204,14 @@ static void windivert_reinject_packet(packet_t packet)
|
||||
handle = (packet->ipv6? injectv6_handle_forward: inject_handle_forward);
|
||||
status = FwpsInjectForwardAsync0(handle, (HANDLE)priority, 0,
|
||||
(packet->ipv6? AF_INET6: AF_INET), UNSPECIFIED_COMPARTMENT_ID,
|
||||
network_data->IfIdx, buffers, windivert_reinject_complete,
|
||||
network_data->IfIdx, buffers, windivert_inject_complete,
|
||||
(HANDLE)packet);
|
||||
}
|
||||
else if (packet->outbound)
|
||||
{
|
||||
handle = (packet->ipv6? injectv6_handle_out: inject_handle_out);
|
||||
status = FwpsInjectNetworkSendAsync0(handle, (HANDLE)priority, 0,
|
||||
UNSPECIFIED_COMPARTMENT_ID, buffers, windivert_reinject_complete,
|
||||
UNSPECIFIED_COMPARTMENT_ID, buffers, windivert_inject_complete,
|
||||
(HANDLE)packet);
|
||||
}
|
||||
else
|
||||
@@ -5247,17 +5219,18 @@ static void windivert_reinject_packet(packet_t packet)
|
||||
handle = (packet->ipv6? injectv6_handle_in: inject_handle_in);
|
||||
status = FwpsInjectNetworkReceiveAsync0(handle, (HANDLE)priority, 0,
|
||||
UNSPECIFIED_COMPARTMENT_ID, network_data->IfIdx,
|
||||
network_data->SubIfIdx, buffers, windivert_reinject_complete,
|
||||
network_data->SubIfIdx, buffers, windivert_inject_complete,
|
||||
(HANDLE)packet);
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_ERROR("failed to reinject (packet=%p)", status, packet);
|
||||
DEBUG_ERROR("failed to inject (packet=%p)", status, packet);
|
||||
FwpsFreeNetBufferList0(buffers);
|
||||
IoFreeMdl(mdl);
|
||||
windivert_free_packet(packet);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -5272,6 +5245,172 @@ static void windivert_free_packet(packet_t packet)
|
||||
windivert_free(packet);
|
||||
}
|
||||
|
||||
/*
|
||||
* WinDivert inject complete routine.
|
||||
*/
|
||||
static void NTAPI windivert_inject_complete(VOID *context,
|
||||
NET_BUFFER_LIST *buffers, BOOLEAN dispatch_level)
|
||||
{
|
||||
PMDL mdl;
|
||||
PNET_BUFFER buffer;
|
||||
packet_t packet;
|
||||
UNREFERENCED_PARAMETER(dispatch_level);
|
||||
|
||||
packet = (packet_t)context;
|
||||
if (buffers->Status == STATUS_INVALID_BUFFER_SIZE)
|
||||
{
|
||||
// STATUS_INVALID_BUFFER_SIZE indicates that the send failed because
|
||||
// the packet was larger than the MTU. We generate an ICMP
|
||||
// Fragmentation Needed (for IPv4) or an ICMPV6 Packet Too Big (for
|
||||
// IPv6) message to allow for PMTU discovery.
|
||||
windivert_inject_packet_too_big(packet);
|
||||
}
|
||||
|
||||
buffer = NET_BUFFER_LIST_FIRST_NB(buffers);
|
||||
mdl = NET_BUFFER_FIRST_MDL(buffer);
|
||||
IoFreeMdl(mdl);
|
||||
FwpsFreeNetBufferList0(buffers);
|
||||
windivert_free_packet(packet);
|
||||
}
|
||||
|
||||
/*
|
||||
* WinDivert inject an ICMP(V6) Packet Too Big message.
|
||||
*/
|
||||
static void windivert_inject_packet_too_big(packet_t packet)
|
||||
{
|
||||
const UINT mtus[] =
|
||||
{
|
||||
568, 768, 1024, 1192, 1280, 1372, 1452, 1500, 4096, UINT16_MAX,
|
||||
UINT32_MAX
|
||||
};
|
||||
PWINDIVERT_IPHDR ip_header, ip_header_2;
|
||||
PWINDIVERT_IPV6HDR ipv6_header, ipv6_header_2;
|
||||
PWINDIVERT_ICMPHDR icmp_header;
|
||||
PWINDIVERT_ICMPV6HDR icmpv6_header;
|
||||
packet_t icmp;
|
||||
UINT version, packet_len, copy_len, icmp_len;
|
||||
UINT icmp_size;
|
||||
UINT i, min_mtu = /*ipv4 min MTU=*/568, mtu;
|
||||
UINT32 flowlabel;
|
||||
UINT8 *data;
|
||||
|
||||
if (packet->layer != WINDIVERT_LAYER_NETWORK || !packet->outbound ||
|
||||
packet->loopback)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ip_header = (PWINDIVERT_IPHDR)WINDIVERT_PACKET_DATA_PTR(
|
||||
WINDIVERT_DATA_NETWORK, packet);
|
||||
version = ip_header->Version;
|
||||
switch (version)
|
||||
{
|
||||
case 4:
|
||||
packet_len = RtlUshortByteSwap(ip_header->Length);
|
||||
copy_len = ip_header->HdrLength * sizeof(UINT32) + 8;
|
||||
copy_len = (packet_len < copy_len? packet_len: copy_len);
|
||||
icmp_len = sizeof(WINDIVERT_IPHDR) + sizeof(WINDIVERT_ICMPHDR) +
|
||||
copy_len;
|
||||
break;
|
||||
case 6:
|
||||
ipv6_header = (PWINDIVERT_IPV6HDR)ip_header;
|
||||
packet_len = RtlUshortByteSwap(ipv6_header->Length) +
|
||||
sizeof(WINDIVERT_IPV6HDR);
|
||||
min_mtu = /*ipv6 min MTU=*/1280;
|
||||
copy_len = min_mtu - sizeof(WINDIVERT_IPV6HDR) -
|
||||
sizeof(WINDIVERT_ICMPV6HDR);
|
||||
copy_len = (packet_len < copy_len? packet_len: copy_len);
|
||||
icmp_len = sizeof(WINDIVERT_IPV6HDR) +
|
||||
sizeof(WINDIVERT_ICMPV6HDR) + copy_len;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if (packet_len <= min_mtu)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// We do not actually know the MTU value, so we make an educated guess.
|
||||
for (i = 0; packet_len > mtus[i]; i++)
|
||||
;
|
||||
mtu = (i == 0? min_mtu: mtus[i-1]);
|
||||
mtu = (mtu < min_mtu? min_mtu: mtu);
|
||||
|
||||
icmp_size = WINDIVERT_PACKET_SIZE(WINDIVERT_DATA_NETWORK, icmp_len);
|
||||
icmp = (packet_t)windivert_malloc(icmp_size, FALSE);
|
||||
if (icmp == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
icmp->layer = WINDIVERT_LAYER_NETWORK;
|
||||
icmp->event = WINDIVERT_EVENT_NETWORK_PACKET;
|
||||
icmp->sniffed = 0; // Unused
|
||||
icmp->outbound = 0; // Inbound
|
||||
icmp->loopback = 0; // Unused
|
||||
icmp->impostor = 0; // Treat as non-impostor
|
||||
icmp->ipv6 = (version == 6? 1: 0);
|
||||
icmp->ip_checksum = 0; // IP checksum valid
|
||||
icmp->tcp_checksum = 0; // Unused
|
||||
icmp->udp_checksum = 0; // Unused
|
||||
icmp->icmp_checksum = 0; // ICMP(V6) checksum invalid
|
||||
icmp->match = 0; // Unused
|
||||
icmp->packet_size = icmp_size;
|
||||
icmp->packet_len = icmp_len;
|
||||
icmp->priority = packet->priority;
|
||||
icmp->timestamp = 0; // Unused
|
||||
icmp->object = NULL;
|
||||
RtlCopyMemory(WINDIVERT_LAYER_DATA_PTR(icmp),
|
||||
WINDIVERT_LAYER_DATA_PTR(packet), sizeof(WINDIVERT_DATA_NETWORK));
|
||||
data = WINDIVERT_PACKET_DATA_PTR(WINDIVERT_DATA_NETWORK, icmp);
|
||||
switch (version)
|
||||
{
|
||||
case 4:
|
||||
ip_header_2 = (PWINDIVERT_IPHDR)data;
|
||||
ip_header_2->Version = 4;
|
||||
ip_header_2->HdrLength = sizeof(WINDIVERT_IPHDR) / sizeof(UINT32);
|
||||
ip_header_2->TOS = 0x0;
|
||||
ip_header_2->Length = RtlUshortByteSwap(icmp_len);
|
||||
ip_header_2->Id = 0x0;
|
||||
ip_header_2->TTL = 64;
|
||||
ip_header_2->Protocol = IPPROTO_ICMP;
|
||||
ip_header_2->SrcAddr = ip_header->DstAddr;
|
||||
ip_header_2->DstAddr = ip_header->SrcAddr;
|
||||
WINDIVERT_IPHDR_SET_FRAGOFF(ip_header_2, 0x0);
|
||||
WINDIVERT_IPHDR_SET_MF(ip_header_2, 0);
|
||||
WINDIVERT_IPHDR_SET_DF(ip_header_2, 1);
|
||||
WINDIVERT_IPHDR_SET_RESERVED(ip_header_2, 0x0);
|
||||
icmp_header = (PWINDIVERT_ICMPHDR)(ip_header_2 + 1);
|
||||
icmp_header->Type = /*Destination Unreachable=*/3;
|
||||
icmp_header->Code = /*Fragmentation required=*/4;
|
||||
icmp_header->Body = ((UINT32)RtlUshortByteSwap(mtu)) << 16;
|
||||
data = (UINT8 *)(icmp_header + 1);
|
||||
RtlCopyMemory(data, ip_header, copy_len);
|
||||
break;
|
||||
case 6:
|
||||
icmp_len -= sizeof(WINDIVERT_IPV6HDR);
|
||||
ipv6_header_2 = (PWINDIVERT_IPV6HDR)data;
|
||||
ipv6_header_2->Version = 6;
|
||||
ipv6_header_2->Length = RtlUshortByteSwap(icmp_len);
|
||||
ipv6_header_2->NextHdr = IPPROTO_ICMPV6;
|
||||
ipv6_header_2->HopLimit = 64;
|
||||
RtlCopyMemory(ipv6_header_2->SrcAddr, ipv6_header->DstAddr,
|
||||
sizeof(ipv6_header_2->SrcAddr));
|
||||
RtlCopyMemory(ipv6_header_2->DstAddr, ipv6_header->SrcAddr,
|
||||
sizeof(ipv6_header_2->DstAddr));
|
||||
WINDIVERT_IPV6HDR_SET_TRAFFICCLASS(ipv6_header_2, 0x0);
|
||||
flowlabel = WINDIVERT_IPV6HDR_GET_FLOWLABEL(ipv6_header);
|
||||
WINDIVERT_IPV6HDR_SET_FLOWLABEL(ipv6_header_2, flowlabel);
|
||||
icmpv6_header = (PWINDIVERT_ICMPV6HDR)(ipv6_header_2 + 1);
|
||||
icmpv6_header->Type = /*Packet Too Big=*/2;
|
||||
icmpv6_header->Code = 0;
|
||||
icmpv6_header->Body = RtlUlongByteSwap(mtu);
|
||||
data = (UINT8 *)(icmpv6_header + 1);
|
||||
RtlCopyMemory(data, ipv6_header, copy_len);
|
||||
break;
|
||||
}
|
||||
windivert_inject_packet(icmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy data from a NET_BUFFER.
|
||||
*/
|
||||
|
||||
+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