Add "fragment" to filter language.
True if the packet is an IPv4/IPv6 fragment.
This commit is contained in:
+30
-6
@@ -128,6 +128,7 @@ typedef enum
|
||||
TOKEN_FALSE,
|
||||
TOKEN_INBOUND,
|
||||
TOKEN_OUTBOUND,
|
||||
TOKEN_FRAGMENT,
|
||||
TOKEN_IF_IDX,
|
||||
TOKEN_SUB_IF_IDX,
|
||||
TOKEN_LOOPBACK,
|
||||
@@ -679,6 +680,7 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer,
|
||||
{"endpointId", TOKEN_ENDPOINT_ID, L__FS_},
|
||||
{"event", TOKEN_EVENT, LNMFSR},
|
||||
{"false", TOKEN_FALSE, LNMFSR},
|
||||
{"fragment", TOKEN_FRAGMENT, LNM___},
|
||||
{"icmp", TOKEN_ICMP, LNMFS_},
|
||||
{"icmp.Body", TOKEN_ICMP_BODY, LNM___},
|
||||
{"icmp.Checksum", TOKEN_ICMP_CHECKSUM, LNM___},
|
||||
@@ -1058,6 +1060,7 @@ static PEXPR WinDivertMakeVar(KIND kind, PERROR error)
|
||||
{{{0}}, TOKEN_FALSE},
|
||||
{{{0}}, TOKEN_INBOUND},
|
||||
{{{0}}, TOKEN_OUTBOUND},
|
||||
{{{0}}, TOKEN_FRAGMENT},
|
||||
{{{0}}, TOKEN_IF_IDX},
|
||||
{{{0}}, TOKEN_SUB_IF_IDX},
|
||||
{{{0}}, TOKEN_LOOPBACK},
|
||||
@@ -1209,6 +1212,7 @@ static PEXPR WinDivertParseTest(HANDLE pool, TOKEN *toks, UINT *i, PERROR error)
|
||||
case TOKEN_FALSE:
|
||||
case TOKEN_OUTBOUND:
|
||||
case TOKEN_INBOUND:
|
||||
case TOKEN_FRAGMENT:
|
||||
case TOKEN_IF_IDX:
|
||||
case TOKEN_SUB_IF_IDX:
|
||||
case TOKEN_LOOPBACK:
|
||||
@@ -1543,6 +1547,7 @@ static BOOL WinDivertEvalTest(PEXPR test, BOOL *res)
|
||||
break;
|
||||
case TOKEN_INBOUND:
|
||||
case TOKEN_OUTBOUND:
|
||||
case TOKEN_FRAGMENT:
|
||||
case TOKEN_IP:
|
||||
case TOKEN_IPV6:
|
||||
case TOKEN_ICMP:
|
||||
@@ -1875,6 +1880,9 @@ static void WinDivertEmitTest(PEXPR test, UINT16 offset,
|
||||
case TOKEN_INBOUND:
|
||||
object->field = WINDIVERT_FILTER_FIELD_INBOUND;
|
||||
break;
|
||||
case TOKEN_FRAGMENT:
|
||||
object->field = WINDIVERT_FILTER_FIELD_FRAGMENT;
|
||||
break;
|
||||
case TOKEN_IF_IDX:
|
||||
object->field = WINDIVERT_FILTER_FIELD_IFIDX;
|
||||
break;
|
||||
@@ -2619,16 +2627,16 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet,
|
||||
PWINDIVERT_ICMPV6HDR icmpv6hdr = NULL;
|
||||
PWINDIVERT_TCPHDR tcphdr = NULL;
|
||||
PWINDIVERT_UDPHDR udphdr = NULL;
|
||||
WINDIVERT_PACKET info;
|
||||
UINT8 protocol = 0;
|
||||
UINT header_len = 0, payload_len = 0;
|
||||
UINT64 random64 = 0;
|
||||
BOOL neg;
|
||||
UINT32 val[4];
|
||||
ULARGE_INTEGER val64;
|
||||
UINT8 data8;
|
||||
UINT16 data16;
|
||||
UINT32 data32;
|
||||
BOOL pass, big;
|
||||
BOOL pass, big, neg, fragment = FALSE;
|
||||
int cmp;
|
||||
HANDLE pool;
|
||||
WINDIVERT_FILTER *object;
|
||||
@@ -2648,14 +2656,21 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet,
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
if (!WinDivertHelperParsePacket((PVOID)packet, packet_len,
|
||||
&iphdr, &ipv6hdr, &protocol, &icmphdr, &icmpv6hdr,
|
||||
&tcphdr, &udphdr, NULL, &payload_len, NULL, NULL))
|
||||
if (!WinDivertHelperParsePacketEx((PVOID)packet, packet_len, &info))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
header_len = packet_len - payload_len;
|
||||
protocol = info.Protocol;
|
||||
iphdr = info.IPHeader;
|
||||
ipv6hdr = info.IPv6Header;
|
||||
icmphdr = info.ICMPHeader;
|
||||
icmpv6hdr = info.ICMPv6Header;
|
||||
tcphdr = info.TCPHeader;
|
||||
udphdr = info.UDPHeader;
|
||||
payload_len = info.PayloadLength;
|
||||
header_len = info.HeaderLength;
|
||||
fragment = info.Fragment;
|
||||
if ((addr->IPv6 && ipv6hdr == NULL) ||
|
||||
(!addr->IPv6 && iphdr == NULL))
|
||||
{
|
||||
@@ -2759,6 +2774,7 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet,
|
||||
case WINDIVERT_FILTER_FIELD_PACKET16:
|
||||
case WINDIVERT_FILTER_FIELD_PACKET32:
|
||||
case WINDIVERT_FILTER_FIELD_LENGTH:
|
||||
case WINDIVERT_FILTER_FIELD_FRAGMENT:
|
||||
pass = (addr->Layer == WINDIVERT_LAYER_NETWORK ||
|
||||
addr->Layer == WINDIVERT_LAYER_NETWORK_FORWARD);
|
||||
break;
|
||||
@@ -2954,6 +2970,9 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet,
|
||||
case WINDIVERT_FILTER_FIELD_OUTBOUND:
|
||||
val[0] = addr->Outbound;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_FRAGMENT:
|
||||
val[0] = (UINT32)fragment;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IFIDX:
|
||||
val[0] = addr->Network.IfIdx;
|
||||
break;
|
||||
@@ -3836,6 +3855,8 @@ static PEXPR WinDivertDecompileTest(HANDLE pool, PWINDIVERT_FILTER test)
|
||||
kind = TOKEN_INBOUND; break;
|
||||
case WINDIVERT_FILTER_FIELD_OUTBOUND:
|
||||
kind = TOKEN_OUTBOUND; break;
|
||||
case WINDIVERT_FILTER_FIELD_FRAGMENT:
|
||||
kind = TOKEN_FRAGMENT; break;
|
||||
case WINDIVERT_FILTER_FIELD_IFIDX:
|
||||
kind = TOKEN_IF_IDX; break;
|
||||
case WINDIVERT_FILTER_FIELD_SUBIFIDX:
|
||||
@@ -4490,6 +4511,7 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr,
|
||||
case TOKEN_ZERO:
|
||||
case TOKEN_INBOUND:
|
||||
case TOKEN_OUTBOUND:
|
||||
case TOKEN_FRAGMENT:
|
||||
case TOKEN_IP:
|
||||
case TOKEN_IPV6:
|
||||
case TOKEN_ICMP:
|
||||
@@ -4787,6 +4809,8 @@ static void WinDivertFormatExpr(PWINDIVERT_STREAM stream, PEXPR expr,
|
||||
WinDivertPutString(stream, "inbound"); return;
|
||||
case TOKEN_OUTBOUND:
|
||||
WinDivertPutString(stream, "outbound"); return;
|
||||
case TOKEN_FRAGMENT:
|
||||
WinDivertPutString(stream, "fragment"); return;
|
||||
case TOKEN_IF_IDX:
|
||||
WinDivertPutString(stream, "ifIdx"); return;
|
||||
case TOKEN_SUB_IF_IDX:
|
||||
|
||||
@@ -2751,6 +2751,7 @@ The possible fields are:
|
||||
<tr><td><code>subIfIdx</code></td><td>✔</td><td>✔</td><td></td><td></td><td></td><td>Sub-interface index</td></tr>
|
||||
<tr><td><code>loopback</code></td><td>✔</td><td></td><td>✔</td><td>✔</td><td></td><td>Is loopback packet?</td></tr>
|
||||
<tr><td><code>impostor</code></td><td>✔</td><td>✔</td><td></td><td></td><td></td><td>Is impostor packet?</td></tr>
|
||||
<tr><td><code>fragment</code></td><td>✔</td><td>✔</td><td></td><td></td><td></td><td>Is IP fragment packet?</td></tr>
|
||||
<tr><td><code>endpointId</code></td><td></td><td></td><td>✔</td><td>✔</td><td></td><td>Endpoint ID</td></tr>
|
||||
<tr><td><code>parentEndpointId</code></td><td></td><td></td><td>✔</td><td>✔</td><td></td><td>Parent endpoint ID</td></tr>
|
||||
<tr><td><code>processId</code></td><td></td><td></td><td>✔</td><td>✔</td><td>✔</td><td>Process ID</td></tr>
|
||||
|
||||
@@ -149,8 +149,9 @@
|
||||
#define WINDIVERT_FILTER_FIELD_RANDOM8 82
|
||||
#define WINDIVERT_FILTER_FIELD_RANDOM16 83
|
||||
#define WINDIVERT_FILTER_FIELD_RANDOM32 84
|
||||
#define WINDIVERT_FILTER_FIELD_FRAGMENT 85
|
||||
#define WINDIVERT_FILTER_FIELD_MAX \
|
||||
WINDIVERT_FILTER_FIELD_RANDOM32
|
||||
WINDIVERT_FILTER_FIELD_FRAGMENT
|
||||
|
||||
#define WINDIVERT_FILTER_TEST_EQ 0
|
||||
#define WINDIVERT_FILTER_TEST_NEQ 1
|
||||
|
||||
+18
-23
@@ -472,7 +472,7 @@ static BOOL windivert_copy_data(PNET_BUFFER buffer, PVOID data, UINT size);
|
||||
static BOOL windivert_lookup_data(PNET_BUFFER buffer, UINT offset, INT idx,
|
||||
PVOID data, UINT size);
|
||||
static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
|
||||
BOOL frag_mode, PWINDIVERT_IPHDR *ip_header_ptr,
|
||||
BOOL *fragment_ptr, PWINDIVERT_IPHDR *ip_header_ptr,
|
||||
PWINDIVERT_IPV6HDR *ipv6_header_ptr, PWINDIVERT_ICMPHDR *icmp_header_ptr,
|
||||
PWINDIVERT_ICMPV6HDR *icmpv6_header_ptr, PWINDIVERT_TCPHDR *tcp_header_ptr,
|
||||
PWINDIVERT_UDPHDR *udp_header_ptr, UINT8 *proto_ptr, UINT *header_len_ptr,
|
||||
@@ -5286,7 +5286,7 @@ static BOOL windivert_lookup_data(PNET_BUFFER buffer, UINT offset, INT idx,
|
||||
* Parse packet headers.
|
||||
*/
|
||||
static __forceinline BOOL windivert_parse_headers(PNET_BUFFER buffer,
|
||||
BOOL ipv4, BOOL frag_mode, PWINDIVERT_IPHDR *ip_header_ptr,
|
||||
BOOL ipv4, BOOL *fragment_ptr, PWINDIVERT_IPHDR *ip_header_ptr,
|
||||
PWINDIVERT_IPV6HDR *ipv6_header_ptr, PWINDIVERT_ICMPHDR *icmp_header_ptr,
|
||||
PWINDIVERT_ICMPV6HDR *icmpv6_header_ptr, PWINDIVERT_TCPHDR *tcp_header_ptr,
|
||||
PWINDIVERT_UDPHDR *udp_header_ptr, UINT8 *proto_ptr, UINT *header_len_ptr,
|
||||
@@ -5300,6 +5300,7 @@ static __forceinline BOOL windivert_parse_headers(PNET_BUFFER buffer,
|
||||
PWINDIVERT_TCPHDR tcp_header = NULL;
|
||||
PWINDIVERT_UDPHDR udp_header = NULL;
|
||||
PWINDIVERT_IPV6FRAGHDR frag_header;
|
||||
BOOL fragment = FALSE;
|
||||
UINT8 protocol = 0;
|
||||
UINT16 frag_off = 0;
|
||||
UINT header_len = 0;
|
||||
@@ -5344,12 +5345,7 @@ static __forceinline BOOL windivert_parse_headers(PNET_BUFFER buffer,
|
||||
return FALSE;
|
||||
}
|
||||
frag_off = RtlUshortByteSwap(WINDIVERT_IPHDR_GET_FRAGOFF(ip_header));
|
||||
if (!frag_mode &&
|
||||
(WINDIVERT_IPHDR_GET_MF(ip_header) != 0 || frag_off != 0))
|
||||
{
|
||||
DEBUG("FILTER: REJECT (fragment)");
|
||||
return FALSE;
|
||||
}
|
||||
fragment = (frag_off != 0 || WINDIVERT_IPHDR_GET_MF(ip_header) != 0);
|
||||
protocol = ip_header->Protocol;
|
||||
NdisAdvanceNetBufferDataStart(buffer, ip_header_len, FALSE, NULL);
|
||||
}
|
||||
@@ -5381,7 +5377,6 @@ static __forceinline BOOL windivert_parse_headers(PNET_BUFFER buffer,
|
||||
NdisAdvanceNetBufferDataStart(buffer, ip_header_len, FALSE, NULL);
|
||||
|
||||
// Skip extension headers:
|
||||
frag_header = NULL;
|
||||
while (frag_off == 0)
|
||||
{
|
||||
UINT8 *ext_header = NULL;
|
||||
@@ -5390,26 +5385,15 @@ static __forceinline BOOL windivert_parse_headers(PNET_BUFFER buffer,
|
||||
switch (protocol)
|
||||
{
|
||||
case IPPROTO_FRAGMENT:
|
||||
if (frag_header != NULL)
|
||||
{
|
||||
is_ext_header = FALSE;
|
||||
break;
|
||||
}
|
||||
frag_header = (PWINDIVERT_IPV6FRAGHDR)
|
||||
NdisGetDataBuffer(buffer, 8, NULL, 1, 0);
|
||||
ext_header = (UINT8 *)frag_header;
|
||||
if (frag_header == NULL)
|
||||
if (fragment || frag_header == NULL)
|
||||
{
|
||||
is_ext_header = FALSE;
|
||||
break;
|
||||
}
|
||||
if (!frag_mode)
|
||||
{
|
||||
DEBUG("FILTER: REJECT (fragment)");
|
||||
NdisRetreatNetBufferDataStart(buffer, ip_header_len,
|
||||
0, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
fragment = TRUE;
|
||||
frag_off = RtlUshortByteSwap(
|
||||
WINDIVERT_IPV6FRAGHDR_GET_FRAGOFF(frag_header));
|
||||
ext_header_len = 8;
|
||||
@@ -5525,6 +5509,7 @@ static __forceinline BOOL windivert_parse_headers(PNET_BUFFER buffer,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*fragment_ptr = fragment;
|
||||
*ip_header_ptr = ip_header;
|
||||
*ipv6_header_ptr = ipv6_header;
|
||||
*icmp_header_ptr = icmp_header;
|
||||
@@ -5556,6 +5541,7 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
UINT header_len = 0, payload_len = 0;
|
||||
UINT64 random64 = 0;
|
||||
UINT16 ip, ttl;
|
||||
BOOL fragment = FALSE;
|
||||
PWINDIVERT_DATA_NETWORK network_data = NULL;
|
||||
PWINDIVERT_DATA_FLOW flow_data = NULL;
|
||||
PWINDIVERT_DATA_SOCKET socket_data = NULL;
|
||||
@@ -5568,12 +5554,16 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
{
|
||||
case WINDIVERT_LAYER_NETWORK:
|
||||
case WINDIVERT_LAYER_NETWORK_FORWARD:
|
||||
if (!windivert_parse_headers(buffer, ipv4, frag_mode, &ip_header,
|
||||
if (!windivert_parse_headers(buffer, ipv4, &fragment, &ip_header,
|
||||
&ipv6_header, &icmp_header, &icmpv6_header, &tcp_header,
|
||||
&udp_header, &protocol, &header_len, &payload_len))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (fragment && !frag_mode)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
network_data = (PWINDIVERT_DATA_NETWORK)layer_data;
|
||||
break;
|
||||
case WINDIVERT_LAYER_FLOW:
|
||||
@@ -5642,6 +5632,7 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
case WINDIVERT_FILTER_FIELD_PACKET16:
|
||||
case WINDIVERT_FILTER_FIELD_PACKET32:
|
||||
case WINDIVERT_FILTER_FIELD_LENGTH:
|
||||
case WINDIVERT_FILTER_FIELD_FRAGMENT:
|
||||
result = (layer == WINDIVERT_LAYER_NETWORK ||
|
||||
layer == WINDIVERT_LAYER_NETWORK_FORWARD);
|
||||
break;
|
||||
@@ -5829,6 +5820,9 @@ static BOOL windivert_filter(PNET_BUFFER buffer, WINDIVERT_LAYER layer,
|
||||
case WINDIVERT_FILTER_FIELD_OUTBOUND:
|
||||
field[0] = (UINT32)outbound;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_FRAGMENT:
|
||||
field[0] = (UINT32)fragment;
|
||||
break;
|
||||
case WINDIVERT_FILTER_FIELD_IFIDX:
|
||||
field[0] = network_data->IfIdx;
|
||||
break;
|
||||
@@ -6499,6 +6493,7 @@ static const WINDIVERT_FILTER *windivert_filter_compile(
|
||||
case WINDIVERT_FILTER_FIELD_ZERO:
|
||||
case WINDIVERT_FILTER_FIELD_INBOUND:
|
||||
case WINDIVERT_FILTER_FIELD_OUTBOUND:
|
||||
case WINDIVERT_FILTER_FIELD_FRAGMENT:
|
||||
case WINDIVERT_FILTER_FIELD_IP:
|
||||
case WINDIVERT_FILTER_FIELD_IPV6:
|
||||
case WINDIVERT_FILTER_FIELD_ICMP:
|
||||
|
||||
@@ -192,6 +192,7 @@ static const struct test tests[] =
|
||||
&pkt_echo_request, TRUE},
|
||||
{"(tcp? tcp.DstPort == 80: true) and (udp? udp.DstPort == 80: true)",
|
||||
&pkt_echo_request, TRUE},
|
||||
{"fragment", &pkt_echo_request, FALSE},
|
||||
{"ip and ip and ip and ip and ip and " // Max filter length:
|
||||
"ip and ip and ip and ip and ip and "
|
||||
"ip and ip and ip and ip and ip and "
|
||||
@@ -752,6 +753,7 @@ static const struct test tests[] =
|
||||
{"ip and !loopback and (outbound? tcp.DstPort == 80 or"
|
||||
" tcp.DstPort == 443 or udp.DstPort == 53 :"
|
||||
" icmp.Type == 11 and icmp.Code == 0)", &pkt_ipv6_echo_reply, FALSE},
|
||||
{"fragment", &pkt_ipv6_echo_reply, FALSE},
|
||||
{"random8 < 128", &pkt_ipv6_echo_reply, TRUE},
|
||||
{"(random8 < 128? random16 < 0x8000: random32 < 0x80000000)",
|
||||
&pkt_ipv6_echo_reply, TRUE},
|
||||
@@ -884,6 +886,7 @@ static const struct test tests[] =
|
||||
&pkt_ipv6_exthdrs_udp, FALSE},
|
||||
{"localAddr == ::1 and remoteAddr == 1 and localPort == 4660 and "
|
||||
"remotePort == 43690 and protocol == 17", &pkt_ipv6_exthdrs_udp, TRUE},
|
||||
{"fragment", &pkt_ipv4_fragment_0, TRUE},
|
||||
{"ip.MF or ip.FragOff != 0", &pkt_ipv4_fragment_0, TRUE},
|
||||
{"icmp", &pkt_ipv4_fragment_0, TRUE},
|
||||
{"icmp.Body != 123 || icmp.Body == 123", &pkt_ipv4_fragment_0, TRUE},
|
||||
@@ -893,6 +896,7 @@ static const struct test tests[] =
|
||||
"ip.TTL == 64 and ip.Protocol == 1 and ip.SrcAddr == 0xFFFF0A000001 and "
|
||||
"ip.DstAddr == 0xFFFF08080808 and icmp.Type == 8 and icmp.Code == 0 and "
|
||||
"icmp.Body == 0x0D560001", &pkt_ipv4_fragment_0, TRUE},
|
||||
{"fragment", &pkt_ipv4_fragment_1, TRUE},
|
||||
{"ip.MF or ip.FragOff != 0", &pkt_ipv4_fragment_1, TRUE},
|
||||
{"icmp", &pkt_ipv4_fragment_1, FALSE},
|
||||
{"icmp.Body != 123 || icmp.Body == 123", &pkt_ipv4_fragment_1, FALSE},
|
||||
@@ -901,6 +905,7 @@ static const struct test tests[] =
|
||||
"ip.Id == 0x1234 and ip.FragOff == 1 and ip.MF == 0 and ip.DF == 0 and "
|
||||
"ip.TTL == 64 and ip.Protocol == 1 and ip.SrcAddr == 0xFFFF0A000001 and "
|
||||
"ip.DstAddr == 0xFFFF08080808", &pkt_ipv4_fragment_1, TRUE},
|
||||
{"fragment", &pkt_ipv6_fragment_0, TRUE},
|
||||
{"icmpv6", &pkt_ipv6_fragment_0, TRUE},
|
||||
{"length == 104 || ipv6.Length == 64", &pkt_ipv6_fragment_0, FALSE},
|
||||
{"ipv6.TrafficClass == 0x00000000 and ipv6.FlowLabel == 0x0000 and "
|
||||
@@ -908,6 +913,7 @@ static const struct test tests[] =
|
||||
"ipv6.SrcAddr == 0:0:0:0:0:0:0:1 and ipv6.DstAddr == 0:0:0:0:0:0:0:1 and "
|
||||
"icmpv6.Type == 129 and icmpv6.Code == 0 and icmpv6.Body == 0x10720003",
|
||||
&pkt_ipv6_fragment_0, TRUE},
|
||||
{"fragment", &pkt_ipv6_fragment_1, TRUE},
|
||||
{"icmpv6", &pkt_ipv6_fragment_1, FALSE},
|
||||
{"length == 104 || ipv6.Length == 64", &pkt_ipv6_fragment_1, FALSE},
|
||||
{"ipv6.TrafficClass == 0x00000000 and ipv6.FlowLabel == 0x0000 and "
|
||||
|
||||
Reference in New Issue
Block a user