Add "fragment" to filter language.

True if the packet is an IPv4/IPv6 fragment.
This commit is contained in:
basil00
2019-08-15 09:08:46 +08:00
parent 317e6f1099
commit a240329323
5 changed files with 57 additions and 30 deletions
+30 -6
View File
@@ -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:
+1
View File
@@ -2751,6 +2751,7 @@ The possible fields are:
<tr><td><code>subIfIdx</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>Sub-interface index</td></tr>
<tr><td><code>loopback</code></td><td>&#10004;</td><td></td><td>&#10004;</td><td>&#10004;</td><td></td><td>Is loopback packet?</td></tr>
<tr><td><code>impostor</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>Is impostor packet?</td></tr>
<tr><td><code>fragment</code></td><td>&#10004;</td><td>&#10004;</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>&#10004;</td><td>&#10004;</td><td></td><td>Endpoint ID</td></tr>
<tr><td><code>parentEndpointId</code></td><td></td><td></td><td>&#10004;</td><td>&#10004;</td><td></td><td>Parent endpoint ID</td></tr>
<tr><td><code>processId</code></td><td></td><td></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>Process ID</td></tr>
+2 -1
View File
@@ -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
View File
@@ -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:
+6
View File
@@ -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 "