Make it possible to filter based on events.
E.g., "event == FLOW_ESTABLISHED".
This commit is contained in:
+83
-1
@@ -109,6 +109,7 @@ typedef enum
|
||||
TOKEN_UDP_PAYLOAD_LENGTH,
|
||||
TOKEN_UDP_SRC_PORT,
|
||||
TOKEN_ZERO,
|
||||
TOKEN_EVENT,
|
||||
TOKEN_TRUE,
|
||||
TOKEN_FALSE,
|
||||
TOKEN_INBOUND,
|
||||
@@ -128,6 +129,12 @@ typedef enum
|
||||
TOKEN_NETWORK,
|
||||
TOKEN_NETWORK_FORWARD,
|
||||
TOKEN_REFLECT,
|
||||
TOKEN_NETWORK_PACKET,
|
||||
TOKEN_FLOW_ESTABLISHED,
|
||||
TOKEN_FLOW_DELETED,
|
||||
TOKEN_REFLECT_ESTABLISHED,
|
||||
TOKEN_REFLECT_OPEN,
|
||||
TOKEN_REFLECT_CLOSE,
|
||||
TOKEN_OPEN,
|
||||
TOKEN_CLOSE,
|
||||
TOKEN_EQ,
|
||||
@@ -820,6 +827,11 @@ static BOOL WinDivertCheckTokenKindForLayer(WINDIVERT_LAYER layer, KIND kind)
|
||||
case TOKEN_NETWORK:
|
||||
case TOKEN_NETWORK_FORWARD:
|
||||
case TOKEN_REFLECT:
|
||||
case TOKEN_FLOW_ESTABLISHED:
|
||||
case TOKEN_FLOW_DELETED:
|
||||
case TOKEN_REFLECT_ESTABLISHED:
|
||||
case TOKEN_REFLECT_OPEN:
|
||||
case TOKEN_REFLECT_CLOSE:
|
||||
return FALSE;
|
||||
default:
|
||||
return TRUE;
|
||||
@@ -882,6 +894,10 @@ static BOOL WinDivertCheckTokenKindForLayer(WINDIVERT_LAYER layer, KIND kind)
|
||||
case TOKEN_NETWORK:
|
||||
case TOKEN_NETWORK_FORWARD:
|
||||
case TOKEN_REFLECT:
|
||||
case TOKEN_NETWORK_PACKET:
|
||||
case TOKEN_REFLECT_ESTABLISHED:
|
||||
case TOKEN_REFLECT_OPEN:
|
||||
case TOKEN_REFLECT_CLOSE:
|
||||
return FALSE;
|
||||
default:
|
||||
return TRUE;
|
||||
@@ -953,6 +969,9 @@ static BOOL WinDivertCheckTokenKindForLayer(WINDIVERT_LAYER layer, KIND kind)
|
||||
case TOKEN_LOCAL_PORT:
|
||||
case TOKEN_REMOTE_PORT:
|
||||
case TOKEN_PROTOCOL:
|
||||
case TOKEN_NETWORK_PACKET:
|
||||
case TOKEN_FLOW_ESTABLISHED:
|
||||
case TOKEN_FLOW_DELETED:
|
||||
return FALSE;
|
||||
default:
|
||||
return TRUE;
|
||||
@@ -981,6 +1000,24 @@ static BOOL WinDivertExpandMacro(KIND kind, UINT32 *val)
|
||||
case TOKEN_REFLECT:
|
||||
*val = WINDIVERT_LAYER_REFLECT;
|
||||
return TRUE;
|
||||
case TOKEN_NETWORK_PACKET:
|
||||
*val = WINDIVERT_EVENT_NETWORK_PACKET;
|
||||
return TRUE;
|
||||
case TOKEN_FLOW_ESTABLISHED:
|
||||
*val = WINDIVERT_EVENT_FLOW_ESTABLISHED;
|
||||
return TRUE;
|
||||
case TOKEN_FLOW_DELETED:
|
||||
*val = WINDIVERT_EVENT_FLOW_DELETED;
|
||||
return TRUE;
|
||||
case TOKEN_REFLECT_ESTABLISHED:
|
||||
*val = WINDIVERT_EVENT_REFLECT_ESTABLISHED;
|
||||
return TRUE;
|
||||
case TOKEN_REFLECT_OPEN:
|
||||
*val = WINDIVERT_EVENT_REFLECT_OPEN;
|
||||
return TRUE;
|
||||
case TOKEN_REFLECT_CLOSE:
|
||||
*val = WINDIVERT_EVENT_REFLECT_CLOSE;
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
@@ -995,10 +1032,17 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer,
|
||||
static const TOKEN_NAME token_names[] =
|
||||
{
|
||||
{"FLOW", TOKEN_FLOW},
|
||||
{"FLOW_DELETED", TOKEN_FLOW_DELETED},
|
||||
{"FLOW_ESTABLISHED", TOKEN_FLOW_ESTABLISHED},
|
||||
{"NETWORK", TOKEN_NETWORK},
|
||||
{"NETWORK_FORWARD", TOKEN_NETWORK_FORWARD},
|
||||
{"NETWORK_PACKET", TOKEN_NETWORK_PACKET},
|
||||
{"REFLECT", TOKEN_REFLECT},
|
||||
{"REFLECT_CLOSE", TOKEN_REFLECT_CLOSE},
|
||||
{"REFLECT_ESTABLISHED", TOKEN_REFLECT_ESTABLISHED},
|
||||
{"REFLECT_OPEN", TOKEN_REFLECT_OPEN},
|
||||
{"and", TOKEN_AND},
|
||||
{"event", TOKEN_EVENT},
|
||||
{"false", TOKEN_FALSE},
|
||||
{"icmp", TOKEN_ICMP},
|
||||
{"icmp.Body", TOKEN_ICMP_BODY},
|
||||
@@ -1322,6 +1366,7 @@ static PEXPR WinDivertMakeVar(KIND kind, PERROR error)
|
||||
{{{0}}, TOKEN_UDP_PAYLOAD_LENGTH},
|
||||
{{{0}}, TOKEN_UDP_SRC_PORT},
|
||||
{{{0}}, TOKEN_ZERO},
|
||||
{{{0}}, TOKEN_EVENT},
|
||||
{{{0}}, TOKEN_TRUE},
|
||||
{{{0}}, TOKEN_FALSE},
|
||||
{{{0}}, TOKEN_INBOUND},
|
||||
@@ -1446,6 +1491,7 @@ static PEXPR WinDivertParseTest(HANDLE pool, TOKEN *toks, UINT *i, PERROR error)
|
||||
switch (toks[*i].kind)
|
||||
{
|
||||
case TOKEN_ZERO:
|
||||
case TOKEN_EVENT:
|
||||
case TOKEN_TRUE:
|
||||
case TOKEN_FALSE:
|
||||
case TOKEN_OUTBOUND:
|
||||
@@ -1696,6 +1742,9 @@ static BOOL WinDivertEvalTest(PEXPR test, BOOL *res)
|
||||
case TOKEN_LAYER:
|
||||
lb = 0; ub = WINDIVERT_LAYER_MAX;
|
||||
break;
|
||||
case TOKEN_EVENT:
|
||||
lb = 0; ub = WINDIVERT_EVENT_MAX;
|
||||
break;
|
||||
case TOKEN_INBOUND:
|
||||
case TOKEN_OUTBOUND:
|
||||
case TOKEN_IP:
|
||||
@@ -1930,6 +1979,9 @@ static void WinDivertEmitTest(PEXPR test, UINT16 offset,
|
||||
case TOKEN_ZERO:
|
||||
object->field = WINDIVERT_FILTER_FIELD_ZERO;
|
||||
break;
|
||||
case TOKEN_EVENT:
|
||||
object->field = WINDIVERT_FILTER_FIELD_EVENT;
|
||||
break;
|
||||
case TOKEN_OUTBOUND:
|
||||
object->field = WINDIVERT_FILTER_FIELD_OUTBOUND;
|
||||
break;
|
||||
@@ -2728,6 +2780,9 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, PVOID packet,
|
||||
case WINDIVERT_FILTER_FIELD_ZERO:
|
||||
val[0] = 0;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_EVENT:
|
||||
val[0] = addr->Event;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_INBOUND:
|
||||
val[0] = !addr->Outbound;
|
||||
break;
|
||||
@@ -3173,6 +3228,8 @@ static PEXPR WinDivertDecompileTest(HANDLE pool, PWINDIVERT_FILTER test)
|
||||
{
|
||||
case WINDIVERT_FILTER_FIELD_ZERO:
|
||||
kind = TOKEN_ZERO; break;
|
||||
case WINDIVERT_FILTER_FIELD_EVENT:
|
||||
kind = TOKEN_EVENT; break;
|
||||
case WINDIVERT_FILTER_FIELD_INBOUND:
|
||||
kind = TOKEN_INBOUND; break;
|
||||
case WINDIVERT_FILTER_FIELD_OUTBOUND:
|
||||
@@ -3685,7 +3742,7 @@ static void WinDivertFormatIPv6Addr(PWINDIVERT_STREAM stream,
|
||||
static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr)
|
||||
{
|
||||
PEXPR field = expr->arg[0], val = expr->arg[1];
|
||||
BOOL ipv4_addr = FALSE, ipv6_addr = FALSE, layer = FALSE;
|
||||
BOOL ipv4_addr = FALSE, ipv6_addr = FALSE, layer = FALSE, event = FALSE;
|
||||
|
||||
switch (field->kind)
|
||||
{
|
||||
@@ -3742,6 +3799,9 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr)
|
||||
case TOKEN_LAYER:
|
||||
layer = TRUE;
|
||||
break;
|
||||
case TOKEN_EVENT:
|
||||
event = TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -3786,6 +3846,26 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr)
|
||||
WinDivertFormatNumber(stream, val->val[0]); break;
|
||||
}
|
||||
}
|
||||
else if (event)
|
||||
{
|
||||
switch (val->val[0])
|
||||
{
|
||||
case WINDIVERT_EVENT_NETWORK_PACKET:
|
||||
WinDivertPutString(stream, "NETWORK_PACKET"); break;
|
||||
case WINDIVERT_EVENT_FLOW_ESTABLISHED:
|
||||
WinDivertPutString(stream, "FLOW_ESTABLISHED"); break;
|
||||
case WINDIVERT_EVENT_FLOW_DELETED:
|
||||
WinDivertPutString(stream, "FLOW_DELETED"); break;
|
||||
case WINDIVERT_EVENT_REFLECT_ESTABLISHED:
|
||||
WinDivertPutString(stream, "REFLECT_ESTABLISHED"); break;
|
||||
case WINDIVERT_EVENT_REFLECT_OPEN:
|
||||
WinDivertPutString(stream, "REFLECT_OPEN"); break;
|
||||
case WINDIVERT_EVENT_REFLECT_CLOSE:
|
||||
WinDivertPutString(stream, "REFLECT_CLOSE"); break;
|
||||
default:
|
||||
WinDivertFormatNumber(stream, val->val[0]); break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WinDivertFormatNumber(stream, val->val[0]);
|
||||
@@ -3863,6 +3943,8 @@ static void WinDivertFormatExpr(PWINDIVERT_STREAM stream, PEXPR expr,
|
||||
return;
|
||||
case TOKEN_ZERO:
|
||||
WinDivertPutString(stream, "zero"); return;
|
||||
case TOKEN_EVENT:
|
||||
WinDivertPutString(stream, "event"); return;
|
||||
case TOKEN_INBOUND:
|
||||
WinDivertPutString(stream, "inbound"); return;
|
||||
case TOKEN_OUTBOUND:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* streamdump.c
|
||||
* windivertctl.c
|
||||
* (C) 2018, all rights reserved,
|
||||
*
|
||||
* This file is part of WinDivert.
|
||||
@@ -73,15 +73,6 @@ typedef enum
|
||||
KILLALL
|
||||
} MODE;
|
||||
|
||||
/*
|
||||
* Months.
|
||||
*/
|
||||
static const char *months[12] =
|
||||
{
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
|
||||
"Nov", "Dec"
|
||||
};
|
||||
|
||||
/*
|
||||
* Add a new process.
|
||||
*/
|
||||
@@ -387,7 +378,7 @@ usage:
|
||||
if (WinDivertHelperFormatFilter((char *)object, addr.Reflect.Layer,
|
||||
filter_str, sizeof(filter_str)))
|
||||
{
|
||||
printf("\"%s\" \"%s\"", filter_str, (char *)object); // XXX
|
||||
printf("\"%s\"", filter_str);
|
||||
}
|
||||
SetConsoleTextAttribute(console,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
|
||||
@@ -129,8 +129,9 @@
|
||||
#define WINDIVERT_FILTER_FIELD_REMOTEPORT 64
|
||||
#define WINDIVERT_FILTER_FIELD_PROTOCOL 65
|
||||
#define WINDIVERT_FILTER_FIELD_LAYER 66
|
||||
#define WINDIVERT_FILTER_FIELD_EVENT 67
|
||||
#define WINDIVERT_FILTER_FIELD_MAX \
|
||||
WINDIVERT_FILTER_FIELD_LAYER
|
||||
WINDIVERT_FILTER_FIELD_EVENT
|
||||
|
||||
#define WINDIVERT_FILTER_TEST_EQ 0
|
||||
#define WINDIVERT_FILTER_TEST_NEQ 1
|
||||
@@ -151,6 +152,12 @@
|
||||
#define WINDIVERT_LAYER_DEFAULT WINDIVERT_LAYER_NETWORK
|
||||
#define WINDIVERT_LAYER_MAX WINDIVERT_LAYER_REFLECT
|
||||
|
||||
/*
|
||||
* WinDivert events.
|
||||
*/
|
||||
#define WINDIVERT_EVENT_MAX \
|
||||
WINDIVERT_EVENT_REFLECT_CLOSE
|
||||
|
||||
/*
|
||||
* WinDivert flags.
|
||||
*/
|
||||
|
||||
+27
-13
@@ -432,8 +432,8 @@ static void windivert_free_packet(packet_t packet);
|
||||
static BOOL windivert_decrement_ttl(PVOID data, BOOL ipv4, BOOL checksum);
|
||||
static int windivert_big_num_compare(const UINT32 *a, const UINT32 *b);
|
||||
static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
PVOID layer_data, BOOL ipv4, BOOL outbound, BOOL loopback, BOOL impostor,
|
||||
PWINDIVERT_FILTER filter);
|
||||
PVOID layer_data, WINDIVERT_EVENT event, BOOL ipv4, BOOL outbound,
|
||||
BOOL loopback, BOOL impostor, PWINDIVERT_FILTER filter);
|
||||
static PWINDIVERT_FILTER windivert_filter_compile(
|
||||
PWINDIVERT_FILTER ioctl_filter, size_t ioctl_filter_len);
|
||||
static NTSTATUS windivert_reflect_init(WDFOBJECT parent);
|
||||
@@ -1834,7 +1834,7 @@ static NTSTATUS windivert_write(context_t context, WDFREQUEST request,
|
||||
case WINDIVERT_LAYER_FLOW:
|
||||
case WINDIVERT_LAYER_REFLECT:
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
DEBUG_ERROR("failed to inject at FLOW layer", status);
|
||||
DEBUG_ERROR("failed to inject at layer", status);
|
||||
goto windivert_write_exit;
|
||||
default:
|
||||
break;
|
||||
@@ -2796,7 +2796,8 @@ static void windivert_network_classify(context_t context,
|
||||
do
|
||||
{
|
||||
BOOL match = windivert_filter(buffer_fst, layer, (PVOID)network_data,
|
||||
ipv4, outbound, loopback, impostor, filter);
|
||||
/*event=*/WINDIVERT_EVENT_NETWORK_PACKET, ipv4, outbound, loopback,
|
||||
impostor, filter);
|
||||
if (match)
|
||||
{
|
||||
break;
|
||||
@@ -2860,7 +2861,8 @@ static void windivert_network_classify(context_t context,
|
||||
while (buffer_itr != NULL)
|
||||
{
|
||||
BOOL match = windivert_filter(buffer_itr, layer, (PVOID)network_data,
|
||||
ipv4, outbound, loopback, impostor, filter);
|
||||
/*event=*/WINDIVERT_EVENT_NETWORK_PACKET, ipv4, outbound,
|
||||
loopback, impostor, filter);
|
||||
ok = windivert_queue_work(context, (PVOID)buffer_itr,
|
||||
NET_BUFFER_DATA_LENGTH(buffer_itr), buffers, layer,
|
||||
(PVOID)network_data, /*event=*/WINDIVERT_EVENT_NETWORK_PACKET,
|
||||
@@ -3024,7 +3026,8 @@ static void windivert_flow_established_classify(context_t context,
|
||||
KeReleaseInStackQueuedSpinLock(&lock_handle);
|
||||
|
||||
match = windivert_filter(/*buffer=*/NULL, /*layer=*/WINDIVERT_LAYER_FLOW,
|
||||
(PVOID)flow_data, ipv4, outbound, loopback, /*impostor=*/FALSE, filter);
|
||||
(PVOID)flow_data, /*event=*/WINDIVERT_EVENT_FLOW_ESTABLISHED, ipv4,
|
||||
outbound, loopback, /*impostor=*/FALSE, filter);
|
||||
if (match)
|
||||
{
|
||||
ok = windivert_queue_work(context, /*packet=*/NULL, /*packet_len=*/0,
|
||||
@@ -3135,8 +3138,9 @@ static void windivert_flow_delete_notify(UINT16 layer_id, UINT32 callout_id,
|
||||
KeReleaseInStackQueuedSpinLock(&lock_handle);
|
||||
|
||||
match = windivert_filter(/*buffer=*/NULL, /*layer=*/WINDIVERT_LAYER_FLOW,
|
||||
(PVOID)&flow->data, !flow->ipv6, flow->outbound, flow->loopback,
|
||||
/*impostor=*/FALSE, filter);
|
||||
(PVOID)&flow->data, /*event=*/WINDIVERT_EVENT_FLOW_DELETED,
|
||||
!flow->ipv6, flow->outbound, flow->loopback, /*impostor=*/FALSE,
|
||||
filter);
|
||||
if (match)
|
||||
{
|
||||
(VOID)windivert_queue_work(context, /*packet=*/NULL, /*packet_len=*/0,
|
||||
@@ -3772,8 +3776,8 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
|
||||
* Checks if the given network packet is of interest.
|
||||
*/
|
||||
static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
PVOID layer_data, BOOL ipv4, BOOL outbound, BOOL loopback, BOOL impostor,
|
||||
PWINDIVERT_FILTER filter)
|
||||
PVOID layer_data, WINDIVERT_EVENT event, BOOL ipv4, BOOL outbound,
|
||||
BOOL loopback, BOOL impostor, PWINDIVERT_FILTER filter)
|
||||
{
|
||||
PWINDIVERT_IPHDR ip_header = NULL;
|
||||
PWINDIVERT_IPV6HDR ipv6_header = NULL;
|
||||
@@ -3827,6 +3831,7 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
switch (filter[ip].field)
|
||||
{
|
||||
case WINDIVERT_FILTER_FIELD_ZERO:
|
||||
case WINDIVERT_FILTER_FIELD_EVENT:
|
||||
result = TRUE;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_INBOUND:
|
||||
@@ -3948,6 +3953,9 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
case WINDIVERT_FILTER_FIELD_ZERO:
|
||||
field[0] = 0;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_EVENT:
|
||||
field[0] = (UINT32)event;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_INBOUND:
|
||||
field[0] = (UINT32)!outbound;
|
||||
break;
|
||||
@@ -4354,6 +4362,12 @@ static PWINDIVERT_FILTER windivert_filter_compile(
|
||||
goto windivert_filter_compile_error;
|
||||
}
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_EVENT:
|
||||
if (ioctl_filter[i].arg[0] > WINDIVERT_EVENT_MAX)
|
||||
{
|
||||
goto windivert_filter_compile_error;
|
||||
}
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IP_HDRLENGTH:
|
||||
case WINDIVERT_FILTER_FIELD_TCP_HDRLENGTH:
|
||||
if (ioctl_filter[i].arg[0] > 0x0F)
|
||||
@@ -4609,7 +4623,7 @@ static void windivert_reflect_event_notify(context_t context,
|
||||
KeReleaseInStackQueuedSpinLock(&lock_handle);
|
||||
match = windivert_filter(/*buffer=*/NULL,
|
||||
/*layer=*/WINDIVERT_LAYER_REFLECT, (PVOID)&context->reflect.data,
|
||||
/*ipv4=*/TRUE, /*outbound=*/FALSE, /*loopback=*/FALSE,
|
||||
event, /*ipv4=*/TRUE, /*outbound=*/FALSE, /*loopback=*/FALSE,
|
||||
/*impostor=*/FALSE, filter);
|
||||
if (!match)
|
||||
{
|
||||
@@ -4658,8 +4672,8 @@ static void windivert_reflect_established_notify(context_t context,
|
||||
entry = entry->Flink;
|
||||
match = windivert_filter(/*buffer=*/NULL,
|
||||
/*layer=*/WINDIVERT_LAYER_REFLECT, (PVOID)&waiter->reflect.data,
|
||||
/*ipv4=*/TRUE, /*outbound=*/FALSE, /*loopback=*/FALSE,
|
||||
/*impostor=*/FALSE, filter);
|
||||
/*event=*/WINDIVERT_EVENT_REFLECT_ESTABLISHED, /*ipv4=*/TRUE,
|
||||
/*outbound=*/FALSE, /*loopback=*/FALSE, /*impostor=*/FALSE, filter);
|
||||
if (!match)
|
||||
{
|
||||
continue;
|
||||
|
||||
@@ -113,6 +113,7 @@ static struct packet pkt_ipv6_exthdrs_udp =
|
||||
};
|
||||
static struct test tests[] =
|
||||
{
|
||||
{"event = NETWORK_PACKET", &pkt_echo_request, TRUE},
|
||||
{"outbound and icmp", &pkt_echo_request, TRUE},
|
||||
{"outbound", &pkt_echo_request, TRUE},
|
||||
{"outbound and inbound", &pkt_echo_request, FALSE},
|
||||
|
||||
Reference in New Issue
Block a user