- 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.
This commit is contained in:
+42
-39
@@ -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;
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
+21
-6
@@ -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;
|
||||
|
||||
@@ -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[] =
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user