From ecd9ae59d3529ba3a6947ef1ad78fbfcecaa1357 Mon Sep 17 00:00:00 2001 From: basil00 Date: Sun, 16 Nov 2014 13:31:07 +0800 Subject: [PATCH] - Re-implement WinDivertHelperParseIPv6Address(). Previous version was just too bug-prone, so re-try from scratch. New version works for several tests. - Fix broken WinDivertAToX(). - New test case: IPv6 TCP SYN. --- dll/windivert.c | 81 +++++++++++++++++++++++++----------------------- sys/windivert.c | 2 +- test/test.c | 27 ++++++++++++---- test/test_data.c | 15 +++++++++ 4 files changed, 79 insertions(+), 46 deletions(-) diff --git a/dll/windivert.c b/dll/windivert.c index 978566e..d8eec2e 100644 --- a/dll/windivert.c +++ b/dll/windivert.c @@ -1838,12 +1838,15 @@ extern BOOL WinDivertHelperParseIPv4Address(const char *str, UINT32 *addr_ptr) */ extern BOOL WinDivertHelperParseIPv6Address(const char *str, UINT32 *addr_ptr) { - UINT16 addr[8] = {0}; - UINT part; - UINT i, j, k; - BOOL end = FALSE; + UINT16 laddr[8]; + UINT16 raddr[8]; + BOOL left = TRUE; + UINT i, j, k, l, part; char part_str[5]; + memset(laddr, 0, sizeof(laddr)); + memset(raddr, 0, sizeof(raddr)); + if (*str == ':') { str++; @@ -1852,58 +1855,54 @@ extern BOOL WinDivertHelperParseIPv6Address(const char *str, UINT32 *addr_ptr) SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } - end = TRUE; + left = FALSE; str++; } - for (i = 0, j = 7; i < 8; i++) + for (i = 0, j = 0, k = 0; k < 8; k++) { if (*str == ':') { - if (end) + if (!left) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } - end = TRUE; + left = FALSE; str++; - if (*str == '\0') - { - break; - } } - for (k = 0; k < 4 && isxdigit(*str); k++) + for (l = 0; l < 4 && isxdigit(*str); l++) { - part_str[k] = *str; + part_str[l] = *str; str++; } - if (k == 0) + if (l == 0) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } - part_str[k] = '\0'; + part_str[l] = '\0'; if (*str != ':' && *str != '\0') { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } WinDivertAToX(part_str, NULL, &part); - if (!end) + if (left) { - addr[i] = (UINT16)part; + laddr[i++] = (UINT16)part; } else { - addr[j--] = (UINT16)part; + raddr[j++] = (UINT16)part; } if (*str == '\0') { - if (end) + if (!left) { break; } - if (i == 7) + if (k == 7) { break; } @@ -1912,32 +1911,29 @@ extern BOOL WinDivertHelperParseIPv6Address(const char *str, UINT32 *addr_ptr) } str++; } - if (*str != '\0') { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } - - if (end) + + if (addr_ptr == NULL) { - j++; - for (i = 7; j < i; j++, i--) - { - UINT16 tmp = addr[i]; - addr[i] = addr[j]; - addr[j] = tmp; - } + return TRUE; } - if (addr_ptr != NULL) + + for (i = 0; i < 4; i++) { - for (i = 0; i < sizeof(addr) / sizeof(UINT32); i++) - { - addr_ptr[i] = (UINT32)addr[2 * i + 1] | - (UINT32)addr[2 * i]; - } + k = 2 * i + j; + l = k + 1; + k = (k >= 8? k - 8: k); + l = (l >= 8? l - 8: l); + addr_ptr[i] = + (UINT32)laddr[2 * i + 1] | + (UINT32)laddr[2 * i] << 16 | + (UINT32)raddr[l] | + (UINT32)raddr[k] << 16; } - return TRUE; } @@ -2021,7 +2017,14 @@ static BOOLEAN WinDivertAToX(const char *str, char **endptr, UINT32 *intptr) { num0 = num; num *= 16; - num += (UINT32)(str[i] - '0'); + if (isdigit(str[i])) + { + num += (UINT32)(str[i] - '0'); + } + else + { + num += (UINT32)(tolower(str[i]) - 'a') + 0x0A; + } if (num0 > num) { return FALSE; diff --git a/sys/windivert.c b/sys/windivert.c index f5f488b..b9d05ca 100644 --- a/sys/windivert.c +++ b/sys/windivert.c @@ -1552,7 +1552,7 @@ windivert_write_exit: if (!NT_SUCCESS(status)) { - DEBUG_ERROR("failed to (re)inject packet", status); + DEBUG_ERROR("failed to inject packet", status); if (buffers != NULL) { FwpsFreeNetBufferList0(buffers); diff --git a/test/test.c b/test/test.c index 727ec6e..b1fd969 100644 --- a/test/test.c +++ b/test/test.c @@ -59,25 +59,31 @@ static BOOL run_test(HANDLE inject_handle, const char *filter, /* * Test data. */ -struct packet pkt_echo_request = +static struct packet pkt_echo_request = { echo_request, sizeof(echo_request), "ipv4_icmp_echo_req" }; -struct packet pkt_http_request = +static struct packet pkt_http_request = { http_request, sizeof(http_request), "ipv4_tcp_http_req" }; -struct packet pkt_ipv6_exthdrs_udp = +static struct packet pkt_ipv6_tcp_syn = +{ + ipv6_tcp_syn, + sizeof(ipv6_tcp_syn), + "ipv6_tcp_syn" +}; +static struct packet pkt_ipv6_exthdrs_udp = { ipv6_exthdrs_udp, sizeof(ipv6_exthdrs_udp), "ipv6_exthdrs_udp" }; -struct test tests[] = +static struct test tests[] = { {"outbound and icmp", &pkt_echo_request, TRUE}, {"outbound", &pkt_echo_request, TRUE}, @@ -98,6 +104,15 @@ struct test tests[] = {"tcp.PayloadLength <= 469", &pkt_http_request, TRUE}, {"tcp.PayloadLength > 469", &pkt_http_request, FALSE}, {"tcp.PayloadLength < 469", &pkt_http_request, FALSE}, + {"ipv6", &pkt_ipv6_tcp_syn, TRUE}, + {"ip", &pkt_ipv6_tcp_syn, FALSE}, + {"tcp.Syn", &pkt_ipv6_tcp_syn, TRUE}, + {"tcp.Syn == 1 && tcp.Ack == 0", &pkt_ipv6_tcp_syn, TRUE}, + {"tcp.PayloadLength == 0", &pkt_ipv6_tcp_syn, TRUE}, + {"ipv6.SrcAddr == 1234:5678:1::aabb:ccdd", &pkt_ipv6_tcp_syn, TRUE}, + {"ipv6.SrcAddr == aabb:5678:1::1234:ccdd", &pkt_ipv6_tcp_syn, FALSE}, + {"tcp.SrcPort == 50046", &pkt_ipv6_tcp_syn, TRUE}, + {"tcp.SrcPort == 0x0000C37E", &pkt_ipv6_tcp_syn, TRUE}, {"true", &pkt_ipv6_exthdrs_udp, TRUE}, {"udp", &pkt_ipv6_exthdrs_udp, TRUE}, {"tcp", &pkt_ipv6_exthdrs_udp, FALSE}, @@ -233,7 +248,7 @@ static BOOL run_test(HANDLE inject_handle, const char *filter, } // (3) Wait for the packet to arrive. - // NOTE: This may fail, so set a generous time-out of 1 second. + // NOTE: This may fail, so set a generous time-out of 250ms. memset(&overlapped, 0, sizeof(overlapped)); event = CreateEvent(NULL, FALSE, FALSE, NULL); if (event == NULL) @@ -254,7 +269,7 @@ read_failed: goto failed; } - switch (WaitForSingleObject(event, 1000)) + switch (WaitForSingleObject(event, 250)) { case WAIT_OBJECT_0: break; diff --git a/test/test_data.c b/test/test_data.c index 1258020..adf2845 100644 --- a/test/test_data.c +++ b/test/test_data.c @@ -103,6 +103,21 @@ static unsigned char http_request[] = 0x0a }; +// IPV6 TCP SYN +static unsigned char ipv6_tcp_syn[] = +{ + 0x60, 0x00, 0x00, 0x00, 0x00, 0x28, 0x06, 0x40, + 0x12, 0x34, 0x56, 0x78, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xaa, 0xbb, 0xcc, 0xdd, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0xc3, 0x7e, 0x00, 0x17, 0xe1, 0xd7, 0xc8, 0xaa, + 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 0xaa, 0xaa, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0xff, 0xc4, + 0x04, 0x02, 0x08, 0x0a, 0xff, 0xff, 0x91, 0x86, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x07 +}; + // IPV6 EXTENSION HEADERS UDP static unsigned char ipv6_exthdrs_udp[] = {