From ebe1af330bebcb7f09f7c87a24c225938fb515b3 Mon Sep 17 00:00:00 2001 From: basil00 Date: Sat, 24 Nov 2018 08:00:17 +0800 Subject: [PATCH] Add "priority" filtering for the REFLECT layer. --- dll/windivert_helper.c | 59 ++++++++++++++++++++++++---- examples/windivertctl/windivertctl.c | 2 +- include/windivert_device.h | 27 +++++++------ mingw-build.sh | 11 ++++-- sys/windivert.c | 13 +++++- 5 files changed, 86 insertions(+), 26 deletions(-) diff --git a/dll/windivert_helper.c b/dll/windivert_helper.c index 678a15d..dc44a45 100644 --- a/dll/windivert_helper.c +++ b/dll/windivert_helper.c @@ -137,6 +137,7 @@ typedef enum TOKEN_REMOTE_PORT, TOKEN_PROTOCOL, TOKEN_LAYER, + TOKEN_PRIORITY, TOKEN_FLOW, TOKEN_SOCKET, TOKEN_NETWORK, @@ -238,6 +239,7 @@ struct EXPR }; UINT8 kind; UINT8 count; + BOOL neg; UINT16 succ; UINT16 fail; }; @@ -614,6 +616,7 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer, {"packet", TOKEN_PACKET, LNM___}, {"packet16", TOKEN_PACKET16, LNM___}, {"packet32", TOKEN_PACKET32, LNM___}, + {"priority", TOKEN_PRIORITY, L____R}, {"processId", TOKEN_PROCESS_ID, L__FSR}, {"protocol", TOKEN_PROTOCOL, LN_FS_}, {"random16", TOKEN_RANDOM16, LNM___}, @@ -943,6 +946,7 @@ static PEXPR WinDivertMakeVar(KIND kind, PERROR error) {{{0}}, TOKEN_REMOTE_PORT}, {{{0}}, TOKEN_PROTOCOL}, {{{0}}, TOKEN_LAYER}, + {{{0}}, TOKEN_PRIORITY}, }; // Binary search: @@ -997,10 +1001,6 @@ static PEXPR WinDivertMakeZero(void) */ static PEXPR WinDivertMakeNumber(HANDLE pool, UINT32 *val, PERROR error) { - if (val[0] == 0 && val[1] == 0 && val[2] == 0 && val[3] == 0) - { - return WinDivertMakeZero(); - } PEXPR expr = (PEXPR)HeapAlloc(pool, HEAP_ZERO_MEMORY, sizeof(EXPR)); if (expr == NULL) { @@ -1064,7 +1064,7 @@ static PEXPR WinDivertParseTest(HANDLE pool, TOKEN *toks, UINT *i, PERROR error) { PEXPR var, val; KIND kind; - BOOL not = FALSE, neg; + BOOL not = FALSE, neg, priority = FALSE; UINT idx, size; while (toks[*i].kind == TOKEN_NOT) { @@ -1073,6 +1073,9 @@ static PEXPR WinDivertParseTest(HANDLE pool, TOKEN *toks, UINT *i, PERROR error) } switch (toks[*i].kind) { + case TOKEN_PRIORITY: + priority = TRUE; + /* fallthough */ case TOKEN_ZERO: case TOKEN_EVENT: case TOKEN_RANDOM8: @@ -1261,12 +1264,19 @@ static PEXPR WinDivertParseTest(HANDLE pool, TOKEN *toks, UINT *i, PERROR error) } } *i = *i + 1; + neg = FALSE; + if (priority && toks[*i].kind == TOKEN_MINUS) + { + neg = TRUE; + *i = *i + 1; + } if (toks[*i].kind != TOKEN_NUMBER) { *error = MAKE_ERROR(WINDIVERT_ERROR_UNEXPECTED_TOKEN, toks[*i].pos); return NULL; } val = WinDivertMakeNumber(pool, toks[*i].val, error); + val->neg = neg; *i = *i + 1; return WinDivertMakeBinOp(pool, kind, var, val, error); } @@ -1395,6 +1405,9 @@ static BOOL WinDivertEvalTest(PEXPR test, BOOL *res) case TOKEN_LAYER: lb = 0; ub = WINDIVERT_LAYER_MAX; break; + case TOKEN_PRIORITY: + lb = 0; ub = WINDIVERT_PRIORITY_MAX; + break; case TOKEN_EVENT: lb = 0; ub = WINDIVERT_EVENT_MAX; break; @@ -1613,6 +1626,7 @@ static void WinDivertEmitTest(PEXPR test, UINT16 offset, { BOOL big; PEXPR var = test->arg[0], val = test->arg[1]; + UINT32 val0; switch (test->kind) { case TOKEN_EQ: @@ -1638,6 +1652,7 @@ static void WinDivertEmitTest(PEXPR test, UINT16 offset, } big = FALSE; object->arg[1] = object->arg[2] = object->arg[3] = 0; + val0 = val->val[0]; switch (var->kind) { case TOKEN_ZERO: @@ -1732,6 +1747,11 @@ static void WinDivertEmitTest(PEXPR test, UINT16 offset, case TOKEN_LAYER: object->field = WINDIVERT_FILTER_FIELD_LAYER; break; + case TOKEN_PRIORITY: + object->field = WINDIVERT_FILTER_FIELD_PRIORITY; + val0 = (val->neg? WINDIVERT_PRIORITY_MAX - val0: + WINDIVERT_PRIORITY_MAX + val0); + break; case TOKEN_IP: object->field = WINDIVERT_FILTER_FIELD_IP; break; @@ -1898,7 +1918,7 @@ static void WinDivertEmitTest(PEXPR test, UINT16 offset, default: return; } - object->arg[0] = val->val[0]; + object->arg[0] = val0; if (big) { object->arg[1] = val->val[1]; @@ -2533,6 +2553,7 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet, addr->Layer == WINDIVERT_LAYER_REFLECT); break; case WINDIVERT_FILTER_FIELD_LAYER: + case WINDIVERT_FILTER_FIELD_PRIORITY: pass = (addr->Layer == WINDIVERT_LAYER_REFLECT); break; case WINDIVERT_FILTER_FIELD_IP_HDRLENGTH: @@ -2629,6 +2650,13 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet, case WINDIVERT_FILTER_FIELD_EVENT: val[0] = addr->Event; break; + case WINDIVERT_FILTER_FIELD_LAYER: + val[0] = addr->Reflect.Layer; + break; + case WINDIVERT_FILTER_FIELD_PRIORITY: + val[0] = (UINT32)((INT32)addr->Reflect.Layer + + WINDIVERT_PRIORITY_MAX); + break; case WINDIVERT_FILTER_FIELD_RANDOM8: val[0] = (UINT32)((random64 >> 48) & 0xFF); break; @@ -3514,6 +3542,8 @@ static PEXPR WinDivertDecompileTest(HANDLE pool, PWINDIVERT_FILTER test) kind = TOKEN_PROTOCOL; break; case WINDIVERT_FILTER_FIELD_LAYER: kind = TOKEN_LAYER; break; + case WINDIVERT_FILTER_FIELD_PRIORITY: + kind = TOKEN_PRIORITY; break; default: return NULL; } @@ -3965,7 +3995,7 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr, { PEXPR field = expr->arg[0], val = expr->arg[1]; BOOL is_ipv4_addr = FALSE, is_ipv6_addr = FALSE, is_layer = FALSE, - is_event = FALSE, is_hex = FALSE; + is_priority = FALSE, is_event = FALSE, is_hex = FALSE; switch (field->kind) { @@ -4022,6 +4052,9 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr, case TOKEN_LAYER: is_layer = TRUE; break; + case TOKEN_PRIORITY: + is_priority = TRUE; + break; case TOKEN_EVENT: is_event = TRUE; break; @@ -4089,6 +4122,16 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr, WinDivertFormatNumber(stream, val->val[0]); break; } } + else if (is_priority) + { + INT32 val32 = (INT32)val->val[0]; + val32 -= WINDIVERT_PRIORITY_MAX; + if (val32 < 0) + { + WinDivertPutChar(stream, '-'); + } + WinDivertFormatNumber(stream, (val32 < 0? -val32: val32)); + } else if (is_event) { switch (layer) @@ -4387,6 +4430,8 @@ static void WinDivertFormatExpr(PWINDIVERT_STREAM stream, PEXPR expr, WinDivertPutString(stream, "protocol"); return; case TOKEN_LAYER: WinDivertPutString(stream, "layer"); return; + case TOKEN_PRIORITY: + WinDivertPutString(stream, "priority"); return; case TOKEN_NUMBER: WinDivertFormatNumber(stream, expr->val[0]); return; } diff --git a/examples/windivertctl/windivertctl.c b/examples/windivertctl/windivertctl.c index 73bc827..285ee92 100644 --- a/examples/windivertctl/windivertctl.c +++ b/examples/windivertctl/windivertctl.c @@ -228,7 +228,7 @@ usage: return 0; } if (GetLastError() == ERROR_INVALID_PARAMETER && - !WinDivertHelperCompileFilter(filter, WINDIVERT_LAYER_FLOW, + !WinDivertHelperCompileFilter(filter, WINDIVERT_LAYER_REFLECT, NULL, 0, &err_str, NULL)) { fprintf(stderr, "error: invalid filter \"%s\"\n", err_str); diff --git a/include/windivert_device.h b/include/windivert_device.h index 1384785..2589e7b 100644 --- a/include/windivert_device.h +++ b/include/windivert_device.h @@ -126,19 +126,20 @@ #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_PACKET 68 -#define WINDIVERT_FILTER_FIELD_PACKET16 69 -#define WINDIVERT_FILTER_FIELD_PACKET32 70 -#define WINDIVERT_FILTER_FIELD_TCP_PAYLOAD 71 -#define WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16 72 -#define WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32 73 -#define WINDIVERT_FILTER_FIELD_UDP_PAYLOAD 74 -#define WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16 75 -#define WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32 76 -#define WINDIVERT_FILTER_FIELD_RANDOM8 77 -#define WINDIVERT_FILTER_FIELD_RANDOM16 78 -#define WINDIVERT_FILTER_FIELD_RANDOM32 79 +#define WINDIVERT_FILTER_FIELD_PRIORITY 67 +#define WINDIVERT_FILTER_FIELD_EVENT 68 +#define WINDIVERT_FILTER_FIELD_PACKET 69 +#define WINDIVERT_FILTER_FIELD_PACKET16 70 +#define WINDIVERT_FILTER_FIELD_PACKET32 71 +#define WINDIVERT_FILTER_FIELD_TCP_PAYLOAD 72 +#define WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16 73 +#define WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32 74 +#define WINDIVERT_FILTER_FIELD_UDP_PAYLOAD 75 +#define WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16 76 +#define WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32 77 +#define WINDIVERT_FILTER_FIELD_RANDOM8 78 +#define WINDIVERT_FILTER_FIELD_RANDOM16 79 +#define WINDIVERT_FILTER_FIELD_RANDOM32 80 #define WINDIVERT_FILTER_FIELD_MAX \ WINDIVERT_FILTER_FIELD_RANDOM32 diff --git a/mingw-build.sh b/mingw-build.sh index 9280310..aa6d1ff 100644 --- a/mingw-build.sh +++ b/mingw-build.sh @@ -51,11 +51,11 @@ do BITS=64 MANGLE= fi + HAVE_SYS=yes if [ ! -d install/WDDK/$CPU ] then echo "WARNING: missing WDDK build; run wddk-build.bat first" - echo "SKIP MINGW-$CPU" - continue + HAVE_SYS=no fi echo "BUILD MINGW-$CPU" CC="$ENV-gcc" @@ -109,8 +109,11 @@ do $CC -s -O2 -Iinclude/ examples/socketdump/socketdump.c \ -o "install/MINGW/$CPU/socketdump.exe" -lWinDivert \ -lpsapi -lshlwapi -L"install/MINGW/$CPU/" - echo "\tcopy install/MINGW/$CPU/WinDivert$BITS.sys..." - cp install/WDDK/$CPU/WinDivert$BITS.sys install/MINGW/$CPU + if [ $HAVE_SYS = yes ] + then + echo "\tcopy install/MINGW/$CPU/WinDivert$BITS.sys..." + cp install/WDDK/$CPU/WinDivert$BITS.sys install/MINGW/$CPU + fi else echo "WARNING: $CC not found" fi diff --git a/sys/windivert.c b/sys/windivert.c index e6204de..c0acbd2 100644 --- a/sys/windivert.c +++ b/sys/windivert.c @@ -5063,6 +5063,7 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer, layer == WINDIVERT_LAYER_REFLECT); break; case WINDIVERT_FILTER_FIELD_LAYER: + case WINDIVERT_FILTER_FIELD_PRIORITY: result = (layer == WINDIVERT_LAYER_REFLECT); break; case WINDIVERT_FILTER_FIELD_IP_HDRLENGTH: @@ -5659,7 +5660,11 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer, } break; case WINDIVERT_FILTER_FIELD_LAYER: - field[0] = reflect_data->Layer; + field[0] = (UINT32)reflect_data->Layer; + break; + case WINDIVERT_FILTER_FIELD_PRIORITY: + field[0] = (UINT32)((INT32)reflect_data->Priority + + WINDIVERT_PRIORITY_MAX); break; default: return FALSE; @@ -5845,6 +5850,12 @@ static const WINDIVERT_FILTER *windivert_filter_compile( goto windivert_filter_compile_error; } break; + case WINDIVERT_FILTER_FIELD_PRIORITY: + if (ioctl_filter[i].arg[0] > 2 * WINDIVERT_PRIORITY_MAX) + { + goto windivert_filter_compile_error; + } + break; case WINDIVERT_FILTER_FIELD_EVENT: event = (WINDIVERT_EVENT)ioctl_filter[i].arg[0]; switch (layer)