- 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:
basil00
2014-11-16 13:31:07 +08:00
parent 5eaf312730
commit ecd9ae59d3
4 changed files with 79 additions and 46 deletions
+42 -39
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+15
View File
@@ -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[] =
{