Implement new packet parser(s) for WinDivert.
The new parser should better handle fragments as well as be consistent with the kernel-mode parser. The new parser can also handle truncated packets.
This commit is contained in:
@@ -308,3 +308,5 @@ WinDivert 2.1.0
|
||||
- Fix BSOD caused by packets with missing or incomplete transport
|
||||
headers (introduced in 2.0.0).
|
||||
- Fix missing Flow.EndpointId and Flow.ParentEndpointId for IPv6 flows.
|
||||
WinDivert 2.2.0
|
||||
- Implement new packet parser that correctly handles IP fragments.
|
||||
|
||||
@@ -85,6 +85,8 @@ static UINT32 WinDivertDivTen128(UINT32 *a);
|
||||
#define UINT32_MAX 0xFFFFFFFF
|
||||
#endif
|
||||
|
||||
#define IPPROTO_MH 135
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#pragma intrinsic(memcpy)
|
||||
|
||||
+70
-2
@@ -496,11 +496,79 @@ static PTOKEN_INFO WinDivertTokenLookup(PTOKEN_INFO token_info,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet.
|
||||
*/
|
||||
extern BOOL WinDivertHelperParsePacket(const VOID *pPacket, UINT packetLen,
|
||||
PWINDIVERT_IPHDR *ppIPHeader, PWINDIVERT_IPV6HDR *ppIPv6Header,
|
||||
UINT8 *pProtocol, PWINDIVERT_ICMPHDR *ppICMPHeader,
|
||||
PWINDIVERT_ICMPV6HDR *ppICMPv6Header, PWINDIVERT_TCPHDR *ppTCPHeader,
|
||||
PWINDIVERT_UDPHDR *ppUDPHeader, PVOID *ppData, UINT *pDataLen,
|
||||
PVOID *ppNext, UINT *pNextLen)
|
||||
{
|
||||
WINDIVERT_PACKET info;
|
||||
if (!WinDivertHelperParsePacketEx(pPacket, packetLen, &info))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (info.Truncated)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (pProtocol != NULL)
|
||||
{
|
||||
*pProtocol = info.Protocol;
|
||||
}
|
||||
if (ppIPHeader != NULL)
|
||||
{
|
||||
*ppIPHeader = info.IPHeader;
|
||||
}
|
||||
if (ppIPv6Header != NULL)
|
||||
{
|
||||
*ppIPv6Header = info.IPv6Header;
|
||||
}
|
||||
if (ppICMPHeader != NULL)
|
||||
{
|
||||
*ppICMPHeader = info.ICMPHeader;
|
||||
}
|
||||
if (ppICMPv6Header != NULL)
|
||||
{
|
||||
*ppICMPv6Header = info.ICMPv6Header;
|
||||
}
|
||||
if (ppTCPHeader != NULL)
|
||||
{
|
||||
*ppTCPHeader = info.TCPHeader;
|
||||
}
|
||||
if (ppUDPHeader != NULL)
|
||||
{
|
||||
*ppUDPHeader = info.UDPHeader;
|
||||
}
|
||||
if (ppData != NULL)
|
||||
{
|
||||
*ppData = info.Payload;
|
||||
}
|
||||
if (pDataLen != NULL)
|
||||
{
|
||||
*pDataLen = info.PayloadLength;
|
||||
}
|
||||
if (ppNext != NULL)
|
||||
{
|
||||
*ppNext = (info.Extended? (PVOID)((UINT8 *)pPacket + packetLen): NULL);
|
||||
}
|
||||
if (pNextLen != NULL)
|
||||
{
|
||||
*pNextLen = (info.Extended?
|
||||
packetLen - (info.HeaderLength + info.PayloadLength): 0);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Expand a "macro" value.
|
||||
*/
|
||||
static BOOL WinDivertExpandMacro(KIND kind, WINDIVERT_LAYER layer,
|
||||
UINT32 *val)
|
||||
static BOOL WinDivertExpandMacro(KIND kind, WINDIVERT_LAYER layer, UINT32 *val)
|
||||
{
|
||||
switch (kind)
|
||||
{
|
||||
|
||||
+192
-178
@@ -73,6 +73,21 @@ static UINT64 WinDivertMul64(UINT64 a, UINT64 b)
|
||||
#define WINDIVERT_MUL64(a, b) ((a) * (b))
|
||||
#endif /* WIN32 */
|
||||
|
||||
/*
|
||||
* IPv6 fragment header.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
UINT8 NextHdr;
|
||||
UINT8 Reserved;
|
||||
UINT16 FragOff0;
|
||||
UINT32 Id;
|
||||
} WINDIVERT_IPV6FRAGHDR, *PWINDIVERT_IPV6FRAGHDR;
|
||||
#define WINDIVERT_IPV6FRAGHDR_GET_FRAGOFF(hdr) \
|
||||
(((hdr)->FragOff0) & 0xF8FF)
|
||||
#define WINDIVERT_IPV6FRAGHDR_GET_MF(hdr) \
|
||||
((((hdr)->FragOff0) & 0x0100) != 0)
|
||||
|
||||
#include "windivert_hash.c"
|
||||
|
||||
/*
|
||||
@@ -96,6 +111,29 @@ typedef struct
|
||||
UINT32 NextHdr:8;
|
||||
} WINDIVERT_PSEUDOV6HDR, *PWINDIVERT_PSEUDOV6HDR;
|
||||
|
||||
/*
|
||||
* Packet info.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
UINT32 HeaderLength:17;
|
||||
UINT32 FragOff:13;
|
||||
UINT32 Fragment:1;
|
||||
UINT32 MF:1;
|
||||
UINT32 PayloadLength:16;
|
||||
UINT32 Protocol:8;
|
||||
UINT32 Truncated:1;
|
||||
UINT32 Extended:1;
|
||||
UINT32 Reserved1:6;
|
||||
PWINDIVERT_IPHDR IPHeader;
|
||||
PWINDIVERT_IPV6HDR IPv6Header;
|
||||
PWINDIVERT_ICMPHDR ICMPHeader;
|
||||
PWINDIVERT_ICMPV6HDR ICMPv6Header;
|
||||
PWINDIVERT_TCPHDR TCPHeader;
|
||||
PWINDIVERT_UDPHDR UDPHeader;
|
||||
UINT8 *Payload;
|
||||
} WINDIVERT_PACKET, *PWINDIVERT_PACKET;
|
||||
|
||||
/*
|
||||
* Streams.
|
||||
*/
|
||||
@@ -283,61 +321,11 @@ static void WinDivertSerializeFilter(PWINDIVERT_STREAM stream,
|
||||
WinDivertPutNul(stream);
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip well-known IPv6 extension headers.
|
||||
*/
|
||||
static UINT8 WinDivertSkipExtHeaders(UINT8 proto, UINT8 **header, UINT *len)
|
||||
{
|
||||
UINT hdrlen;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
if (*len <= 2)
|
||||
{
|
||||
return IPPROTO_NONE;
|
||||
}
|
||||
|
||||
hdrlen = (UINT)*(*header + 1);
|
||||
switch (proto)
|
||||
{
|
||||
case IPPROTO_FRAGMENT:
|
||||
hdrlen = 8;
|
||||
break;
|
||||
case IPPROTO_AH:
|
||||
hdrlen += 2;
|
||||
hdrlen *= 4;
|
||||
break;
|
||||
case IPPROTO_HOPOPTS:
|
||||
case IPPROTO_DSTOPTS:
|
||||
case IPPROTO_ROUTING:
|
||||
hdrlen++;
|
||||
hdrlen *= 8;
|
||||
break;
|
||||
case IPPROTO_NONE:
|
||||
return proto;
|
||||
default:
|
||||
return proto;
|
||||
}
|
||||
|
||||
if (hdrlen >= *len)
|
||||
{
|
||||
return IPPROTO_NONE;
|
||||
}
|
||||
|
||||
proto = **header;
|
||||
*header += hdrlen;
|
||||
*len -= hdrlen;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet.
|
||||
*/
|
||||
extern BOOL WinDivertHelperParsePacket(const VOID *pPacket, UINT packetLen,
|
||||
PWINDIVERT_IPHDR *ppIpHdr, PWINDIVERT_IPV6HDR *ppIpv6Hdr, UINT8 *pProtocol,
|
||||
PWINDIVERT_ICMPHDR *ppIcmpHdr, PWINDIVERT_ICMPV6HDR *ppIcmpv6Hdr,
|
||||
PWINDIVERT_TCPHDR *ppTcpHdr, PWINDIVERT_UDPHDR *ppUdpHdr, PVOID *ppData,
|
||||
UINT *pDataLen, PVOID *ppNext, UINT *pNextLen)
|
||||
static BOOL WinDivertHelperParsePacketEx(const VOID *pPacket, UINT packetLen,
|
||||
PWINDIVERT_PACKET pInfo)
|
||||
{
|
||||
PWINDIVERT_IPHDR ip_header = NULL;
|
||||
PWINDIVERT_IPV6HDR ipv6_header = NULL;
|
||||
@@ -345,183 +333,181 @@ extern BOOL WinDivertHelperParsePacket(const VOID *pPacket, UINT packetLen,
|
||||
PWINDIVERT_ICMPV6HDR icmpv6_header = NULL;
|
||||
PWINDIVERT_TCPHDR tcp_header = NULL;
|
||||
PWINDIVERT_UDPHDR udp_header = NULL;
|
||||
UINT16 header_len;
|
||||
PWINDIVERT_IPV6FRAGHDR frag_header;
|
||||
UINT8 protocol = 0;
|
||||
PVOID data = NULL, next = NULL;
|
||||
UINT data_len = 0, next_len = 0, packet_len;
|
||||
BOOL success = FALSE;
|
||||
UINT8 *data = NULL;
|
||||
UINT packet_len, total_len, header_len, data_len = 0, frag_off = 0;
|
||||
BOOL MF = FALSE, fragment = FALSE, is_ext_header;
|
||||
|
||||
if (pPacket == NULL || packetLen < sizeof(WINDIVERT_IPHDR))
|
||||
{
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
return FALSE;
|
||||
}
|
||||
data = (PVOID)pPacket;
|
||||
data = (UINT8 *)pPacket;
|
||||
data_len = packetLen;
|
||||
|
||||
ip_header = (PWINDIVERT_IPHDR)data;
|
||||
switch (ip_header->Version)
|
||||
{
|
||||
case 4:
|
||||
if (data_len < sizeof(WINDIVERT_IPHDR) ||
|
||||
ip_header->HdrLength < 5)
|
||||
if (packetLen < sizeof(WINDIVERT_IPHDR) ||
|
||||
ip_header->HdrLength < 5)
|
||||
{
|
||||
ip_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
return FALSE;
|
||||
}
|
||||
packet_len = (UINT)ntohs(ip_header->Length);
|
||||
header_len = ip_header->HdrLength*sizeof(UINT32);
|
||||
protocol = ip_header->Protocol;
|
||||
if (data_len < header_len || data_len < packet_len ||
|
||||
packet_len < header_len)
|
||||
total_len = (UINT)ntohs(ip_header->Length);
|
||||
protocol = ip_header->Protocol;
|
||||
header_len = ip_header->HdrLength * sizeof(UINT32);
|
||||
if (total_len < header_len || packetLen < header_len)
|
||||
{
|
||||
ip_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
return FALSE;
|
||||
}
|
||||
else if (packet_len < data_len)
|
||||
{
|
||||
next = (PVOID)((UINT8 *)data + packet_len);
|
||||
next_len = data_len - packet_len;
|
||||
}
|
||||
data = (PVOID)((UINT8 *)data + header_len);
|
||||
data_len = packet_len - header_len;
|
||||
frag_off = ntohs(WINDIVERT_IPHDR_GET_FRAGOFF(ip_header));
|
||||
MF = (WINDIVERT_IPHDR_GET_MF(ip_header) != 0);
|
||||
fragment = (MF || frag_off != 0);
|
||||
packet_len = (total_len < packetLen? total_len: packetLen);
|
||||
data += header_len;
|
||||
data_len = packet_len - header_len;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
ip_header = NULL;
|
||||
ip_header = NULL;
|
||||
ipv6_header = (PWINDIVERT_IPV6HDR)data;
|
||||
if (data_len < sizeof(WINDIVERT_IPV6HDR) ||
|
||||
data_len < ntohs(ipv6_header->Length) +
|
||||
sizeof(WINDIVERT_IPV6HDR))
|
||||
if (packetLen < sizeof(WINDIVERT_IPV6HDR))
|
||||
{
|
||||
ipv6_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
return FALSE;
|
||||
}
|
||||
protocol = ipv6_header->NextHdr;
|
||||
packet_len = ntohs(ipv6_header->Length) + sizeof(WINDIVERT_IPV6HDR);
|
||||
if (packet_len < data_len)
|
||||
protocol = ipv6_header->NextHdr;
|
||||
total_len = (UINT)ntohs(ipv6_header->Length) +
|
||||
sizeof(WINDIVERT_IPV6HDR);
|
||||
packet_len = (total_len < packetLen? total_len: packetLen);
|
||||
data += sizeof(WINDIVERT_IPV6HDR);
|
||||
data_len = packet_len - sizeof(WINDIVERT_IPV6HDR);
|
||||
|
||||
while (frag_off == 0 && data_len >= 2)
|
||||
{
|
||||
next = (PVOID)((UINT8 *)data + packet_len);
|
||||
next_len = data_len - packet_len;
|
||||
header_len = (UINT)data[1];
|
||||
is_ext_header = TRUE;
|
||||
switch (protocol)
|
||||
{
|
||||
case IPPROTO_FRAGMENT:
|
||||
header_len = 8;
|
||||
if (fragment || data_len < header_len)
|
||||
{
|
||||
is_ext_header = FALSE;
|
||||
break;
|
||||
}
|
||||
frag_header = (PWINDIVERT_IPV6FRAGHDR)data;
|
||||
frag_off = ntohs(
|
||||
WINDIVERT_IPV6FRAGHDR_GET_FRAGOFF(frag_header));
|
||||
MF = WINDIVERT_IPV6FRAGHDR_GET_MF(frag_header);
|
||||
fragment = TRUE;
|
||||
break;
|
||||
case IPPROTO_AH:
|
||||
header_len += 2;
|
||||
header_len *= 4;
|
||||
break;
|
||||
case IPPROTO_HOPOPTS:
|
||||
case IPPROTO_DSTOPTS:
|
||||
case IPPROTO_ROUTING:
|
||||
case IPPROTO_MH:
|
||||
header_len++;
|
||||
header_len *= 8;
|
||||
break;
|
||||
default:
|
||||
is_ext_header = FALSE;
|
||||
break;
|
||||
}
|
||||
if (!is_ext_header || data_len < header_len)
|
||||
{
|
||||
break;
|
||||
}
|
||||
protocol = data[0];
|
||||
data += header_len;
|
||||
data_len -= header_len;
|
||||
}
|
||||
data = (PVOID)((UINT8 *)data + sizeof(WINDIVERT_IPV6HDR));
|
||||
data_len = packet_len - sizeof(WINDIVERT_IPV6HDR);
|
||||
protocol = WinDivertSkipExtHeaders(protocol, (UINT8 **)&data,
|
||||
&data_len);
|
||||
break;
|
||||
|
||||
default:
|
||||
ip_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (frag_off != 0)
|
||||
{
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
data = (data_len == 0? NULL: data);
|
||||
success = TRUE;
|
||||
switch (protocol)
|
||||
{
|
||||
case IPPROTO_TCP:
|
||||
tcp_header = (PWINDIVERT_TCPHDR)data;
|
||||
if (data_len < sizeof(WINDIVERT_TCPHDR) ||
|
||||
tcp_header->HdrLength < 5 ||
|
||||
data_len < tcp_header->HdrLength*sizeof(UINT32))
|
||||
tcp_header->HdrLength < 5)
|
||||
{
|
||||
tcp_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
header_len = tcp_header->HdrLength*sizeof(UINT32);
|
||||
data = ((UINT8 *)data + header_len);
|
||||
data_len -= header_len;
|
||||
header_len = tcp_header->HdrLength * sizeof(UINT32);
|
||||
header_len = (header_len > data_len? data_len: header_len);
|
||||
break;
|
||||
|
||||
case IPPROTO_UDP:
|
||||
udp_header = (PWINDIVERT_UDPHDR)data;
|
||||
if (data_len < sizeof(WINDIVERT_UDPHDR) ||
|
||||
ntohs(udp_header->Length) != data_len)
|
||||
if (data_len < sizeof(WINDIVERT_UDPHDR))
|
||||
{
|
||||
udp_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
data = ((UINT8 *)data + sizeof(WINDIVERT_UDPHDR));
|
||||
data_len -= sizeof(WINDIVERT_UDPHDR);
|
||||
udp_header = (PWINDIVERT_UDPHDR)data;
|
||||
header_len = sizeof(WINDIVERT_UDPHDR);
|
||||
break;
|
||||
|
||||
case IPPROTO_ICMP:
|
||||
icmp_header = (PWINDIVERT_ICMPHDR)data;
|
||||
if (ip_header == NULL ||
|
||||
data_len < sizeof(WINDIVERT_ICMPHDR))
|
||||
{
|
||||
icmp_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
data = ((UINT8 *)data + sizeof(WINDIVERT_ICMPHDR));
|
||||
data_len -= sizeof(WINDIVERT_ICMPHDR);
|
||||
icmp_header = (PWINDIVERT_ICMPHDR)data;
|
||||
header_len = sizeof(WINDIVERT_ICMPHDR);
|
||||
break;
|
||||
|
||||
case IPPROTO_ICMPV6:
|
||||
icmpv6_header = (PWINDIVERT_ICMPV6HDR)data;
|
||||
if (ipv6_header == NULL ||
|
||||
data_len < sizeof(WINDIVERT_ICMPV6HDR))
|
||||
{
|
||||
icmpv6_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
data = ((UINT8 *)data + sizeof(WINDIVERT_ICMPV6HDR));
|
||||
data_len -= sizeof(WINDIVERT_ICMPV6HDR);
|
||||
icmpv6_header = (PWINDIVERT_ICMPV6HDR)data;
|
||||
header_len = sizeof(WINDIVERT_ICMPV6HDR);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (data_len == 0)
|
||||
{
|
||||
data = NULL;
|
||||
default:
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
data += header_len;
|
||||
data_len -= header_len;
|
||||
|
||||
WinDivertHelperParsePacketExit:
|
||||
if (pProtocol != NULL)
|
||||
if (pInfo == NULL)
|
||||
{
|
||||
*pProtocol = protocol;
|
||||
return TRUE;
|
||||
}
|
||||
if (ppIpHdr != NULL)
|
||||
{
|
||||
*ppIpHdr = ip_header;
|
||||
}
|
||||
if (ppIpv6Hdr != NULL)
|
||||
{
|
||||
*ppIpv6Hdr = ipv6_header;
|
||||
}
|
||||
if (ppIcmpHdr != NULL)
|
||||
{
|
||||
*ppIcmpHdr = icmp_header;
|
||||
}
|
||||
if (ppIcmpv6Hdr != NULL)
|
||||
{
|
||||
*ppIcmpv6Hdr = icmpv6_header;
|
||||
}
|
||||
if (ppTcpHdr != NULL)
|
||||
{
|
||||
*ppTcpHdr = tcp_header;
|
||||
}
|
||||
if (ppUdpHdr != NULL)
|
||||
{
|
||||
*ppUdpHdr = udp_header;
|
||||
}
|
||||
if (ppData != NULL)
|
||||
{
|
||||
*ppData = data;
|
||||
}
|
||||
if (pDataLen != NULL)
|
||||
{
|
||||
*pDataLen = data_len;
|
||||
}
|
||||
if (ppNext != NULL)
|
||||
{
|
||||
*ppNext = next;
|
||||
}
|
||||
if (pNextLen != NULL)
|
||||
{
|
||||
*pNextLen = next_len;
|
||||
}
|
||||
|
||||
if (ppNext == NULL && pNextLen == NULL && next != NULL)
|
||||
{
|
||||
success = FALSE;
|
||||
}
|
||||
|
||||
return success;
|
||||
data = (data_len == 0? NULL: data);
|
||||
pInfo->Protocol = (UINT32)protocol;
|
||||
pInfo->Fragment = (fragment? 1: 0);
|
||||
pInfo->MF = (MF? 1: 0);
|
||||
pInfo->FragOff = (UINT32)frag_off;
|
||||
pInfo->Truncated = (total_len < packetLen? 1: 0);
|
||||
pInfo->Extended = (total_len > packetLen? 1: 0);
|
||||
pInfo->Reserved1 = 0;
|
||||
pInfo->IPHeader = ip_header;
|
||||
pInfo->IPv6Header = ipv6_header;
|
||||
pInfo->ICMPHeader = icmp_header;
|
||||
pInfo->ICMPv6Header = icmpv6_header;
|
||||
pInfo->TCPHeader = tcp_header;
|
||||
pInfo->UDPHeader = udp_header;
|
||||
pInfo->Payload = data;
|
||||
pInfo->HeaderLength = (UINT32)(packet_len - data_len);
|
||||
pInfo->PayloadLength = (UINT32)data_len;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -539,44 +525,59 @@ extern BOOL WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
|
||||
PWINDIVERT_ICMPV6HDR icmpv6_header;
|
||||
PWINDIVERT_TCPHDR tcp_header;
|
||||
PWINDIVERT_UDPHDR udp_header;
|
||||
WINDIVERT_PACKET info;
|
||||
UINT payload_len, checksum_len;
|
||||
BOOL truncated;
|
||||
|
||||
if (!WinDivertHelperParsePacket(pPacket, packetLen, &ip_header,
|
||||
&ipv6_header, NULL, &icmp_header, &icmpv6_header, &tcp_header,
|
||||
&udp_header, NULL, &payload_len, NULL, NULL))
|
||||
if (!WinDivertHelperParsePacketEx(pPacket, packetLen, &info))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ip_header = info.IPHeader;
|
||||
if (ip_header != NULL && !(flags & WINDIVERT_HELPER_NO_IP_CHECKSUM))
|
||||
{
|
||||
ip_header->Checksum = 0;
|
||||
ip_header->Checksum = WinDivertCalcChecksum(NULL, 0, ip_header,
|
||||
ip_header->HdrLength*sizeof(UINT32));
|
||||
ip_header->HdrLength * sizeof(UINT32));
|
||||
if (pAddr != NULL)
|
||||
{
|
||||
pAddr->IPChecksum = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
payload_len = info.PayloadLength;
|
||||
truncated = (info.Truncated || info.MF || info.FragOff != 0);
|
||||
|
||||
icmp_header = info.ICMPHeader;
|
||||
if (icmp_header != NULL)
|
||||
{
|
||||
if ((flags & WINDIVERT_HELPER_NO_ICMP_CHECKSUM) != 0)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
if (truncated)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
icmp_header->Checksum = 0;
|
||||
icmp_header->Checksum = WinDivertCalcChecksum(NULL, 0,
|
||||
icmp_header, payload_len + sizeof(WINDIVERT_ICMPHDR));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
icmpv6_header = info.ICMPv6Header;
|
||||
if (icmpv6_header != NULL)
|
||||
{
|
||||
if ((flags & WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM) != 0)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
if (truncated)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
ipv6_header = info.IPv6Header;
|
||||
checksum_len = payload_len + sizeof(WINDIVERT_ICMPV6HDR);
|
||||
pseudo_header_len = WinDivertInitPseudoHeader(NULL, ipv6_header,
|
||||
IPPROTO_ICMPV6, checksum_len, pseudo_header);
|
||||
@@ -585,14 +586,20 @@ extern BOOL WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
|
||||
pseudo_header_len, icmpv6_header, checksum_len);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
tcp_header = info.TCPHeader;
|
||||
if (tcp_header != NULL)
|
||||
{
|
||||
if ((flags & WINDIVERT_HELPER_NO_TCP_CHECKSUM) != 0)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
checksum_len = payload_len + tcp_header->HdrLength*sizeof(UINT32);
|
||||
if (truncated)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
checksum_len = payload_len + tcp_header->HdrLength * sizeof(UINT32);
|
||||
ipv6_header = info.IPv6Header;
|
||||
pseudo_header_len = WinDivertInitPseudoHeader(ip_header,
|
||||
ipv6_header, IPPROTO_TCP, checksum_len, pseudo_header);
|
||||
tcp_header->Checksum = 0;
|
||||
@@ -604,15 +611,21 @@ extern BOOL WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
udp_header = info.UDPHeader;
|
||||
if (udp_header != NULL)
|
||||
{
|
||||
if ((flags & WINDIVERT_HELPER_NO_UDP_CHECKSUM) != 0)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
if (truncated)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
// Full UDP checksum
|
||||
checksum_len = payload_len + sizeof(WINDIVERT_UDPHDR);
|
||||
ipv6_header = info.IPv6Header;
|
||||
pseudo_header_len = WinDivertInitPseudoHeader(ip_header,
|
||||
ipv6_header, IPPROTO_UDP, checksum_len, pseudo_header);
|
||||
udp_header->Checksum = 0;
|
||||
@@ -626,6 +639,7 @@ extern BOOL WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
|
||||
{
|
||||
pAddr->UDPChecksum = 1;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
#include "windivert.h"
|
||||
|
||||
#define WINDIVERT_VERSION_MAJOR 2
|
||||
#define WINDIVERT_VERSION_MINOR 1
|
||||
#define WINDIVERT_VERSION_MINOR 2
|
||||
|
||||
#define WINDIVERT_MAGIC_DLL 0x4C4C447669645724ull
|
||||
#define WINDIVERT_MAGIC_SYS 0x5359537669645723ull
|
||||
|
||||
+111
-68
@@ -289,6 +289,7 @@ typedef struct flow_s *flow_t;
|
||||
#define UINT8_MAX 0xFF
|
||||
#define UINT16_MAX 0xFFFF
|
||||
#define UINT32_MAX 0xFFFFFFFF
|
||||
#define IPPROTO_MH 135
|
||||
|
||||
/*
|
||||
* Global state.
|
||||
@@ -5284,8 +5285,8 @@ static BOOL windivert_lookup_data(PNET_BUFFER buffer, UINT offset, INT idx,
|
||||
/*
|
||||
* Parse packet headers.
|
||||
*/
|
||||
static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
|
||||
BOOL frag_mode, PWINDIVERT_IPHDR *ip_header_ptr,
|
||||
static __forceinline BOOL windivert_parse_headers(PNET_BUFFER buffer,
|
||||
BOOL ipv4, BOOL frag_mode, 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,
|
||||
@@ -5298,7 +5299,9 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
|
||||
PWINDIVERT_ICMPV6HDR icmpv6_header = NULL;
|
||||
PWINDIVERT_TCPHDR tcp_header = NULL;
|
||||
PWINDIVERT_UDPHDR udp_header = NULL;
|
||||
UINT8 proto = 0;
|
||||
PWINDIVERT_IPV6FRAGHDR frag_header;
|
||||
UINT8 protocol = 0;
|
||||
UINT16 frag_off = 0;
|
||||
UINT header_len = 0;
|
||||
NTSTATUS status;
|
||||
|
||||
@@ -5340,14 +5343,14 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
|
||||
DEBUG("FILTER: REJECT (bad IPv4 packet)");
|
||||
return FALSE;
|
||||
}
|
||||
frag_off = RtlUshortByteSwap(WINDIVERT_IPHDR_GET_FRAGOFF(ip_header));
|
||||
if (!frag_mode &&
|
||||
(WINDIVERT_IPHDR_GET_MF(ip_header) != 0 ||
|
||||
WINDIVERT_IPHDR_GET_FRAGOFF(ip_header) != 0))
|
||||
(WINDIVERT_IPHDR_GET_MF(ip_header) != 0 || frag_off != 0))
|
||||
{
|
||||
DEBUG("FILTER: REJECT (fragment)");
|
||||
return FALSE;
|
||||
}
|
||||
proto = ip_header->Protocol;
|
||||
protocol = ip_header->Protocol;
|
||||
NdisAdvanceNetBufferDataStart(buffer, ip_header_len, FALSE, NULL);
|
||||
}
|
||||
else
|
||||
@@ -5374,26 +5377,32 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
|
||||
DEBUG("FILTER: REJECT (bad IPv6 packet)");
|
||||
return FALSE;
|
||||
}
|
||||
proto = ipv6_header->NextHdr;
|
||||
protocol = ipv6_header->NextHdr;
|
||||
NdisAdvanceNetBufferDataStart(buffer, ip_header_len, FALSE, NULL);
|
||||
|
||||
// Skip extension headers:
|
||||
while (TRUE)
|
||||
frag_header = NULL;
|
||||
while (frag_off == 0)
|
||||
{
|
||||
UINT8 *ext_header;
|
||||
UINT ext_header_len;
|
||||
BOOL isexthdr = TRUE;
|
||||
|
||||
ext_header = (UINT8 *)NdisGetDataBuffer(buffer, 2, NULL, 1, 0);
|
||||
if (ext_header == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ext_header_len = (UINT)ext_header[1];
|
||||
switch (proto)
|
||||
UINT8 *ext_header = NULL;
|
||||
UINT ext_header_len = 0;
|
||||
BOOL is_ext_header;
|
||||
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)
|
||||
{
|
||||
is_ext_header = FALSE;
|
||||
break;
|
||||
}
|
||||
if (!frag_mode)
|
||||
{
|
||||
DEBUG("FILTER: REJECT (fragment)");
|
||||
@@ -5401,36 +5410,48 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
|
||||
0, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
frag_off = RtlUshortByteSwap(
|
||||
WINDIVERT_IPV6FRAGHDR_GET_FRAGOFF(frag_header));
|
||||
ext_header_len = 8;
|
||||
is_ext_header = TRUE;
|
||||
break;
|
||||
|
||||
case IPPROTO_AH:
|
||||
ext_header_len += 2;
|
||||
ext_header_len *= 4;
|
||||
break;
|
||||
case IPPROTO_HOPOPTS:
|
||||
case IPPROTO_DSTOPTS:
|
||||
case IPPROTO_ROUTING:
|
||||
ext_header_len++;
|
||||
ext_header_len *= 8;
|
||||
case IPPROTO_MH:
|
||||
ext_header = (UINT8 *)NdisGetDataBuffer(buffer, 2, NULL,
|
||||
1, 0);
|
||||
if (ext_header == NULL)
|
||||
{
|
||||
is_ext_header = FALSE;
|
||||
break;
|
||||
}
|
||||
ext_header_len = (UINT)ext_header[1];
|
||||
if (protocol == IPPROTO_AH)
|
||||
{
|
||||
ext_header_len += 2;
|
||||
ext_header_len *= 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
ext_header_len++;
|
||||
ext_header_len *= 8;
|
||||
}
|
||||
is_ext_header = TRUE;
|
||||
break;
|
||||
default:
|
||||
isexthdr = FALSE;
|
||||
|
||||
is_ext_header = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!isexthdr)
|
||||
if (!is_ext_header || ip_header_len + ext_header_len > total_len)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
proto = ext_header[0];
|
||||
if (ip_header_len + ext_header_len > total_len)
|
||||
{
|
||||
DEBUG("FILTER: REJECT (bad IPv6 extension header)");
|
||||
NdisRetreatNetBufferDataStart(buffer, ip_header_len,
|
||||
0, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
protocol = ext_header[0];
|
||||
ip_header_len += ext_header_len;
|
||||
NdisAdvanceNetBufferDataStart(buffer, ext_header_len, FALSE,
|
||||
NULL);
|
||||
@@ -5438,42 +5459,64 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
|
||||
}
|
||||
|
||||
header_len = ip_header_len;
|
||||
switch (proto)
|
||||
if (frag_off == 0)
|
||||
{
|
||||
case IPPROTO_ICMP:
|
||||
icmp_header = (PWINDIVERT_ICMPHDR)NdisGetDataBuffer(buffer,
|
||||
sizeof(WINDIVERT_ICMPHDR), NULL, 1, 0);
|
||||
header_len += (icmp_header == NULL? 0: sizeof(WINDIVERT_ICMPHDR));
|
||||
break;
|
||||
case IPPROTO_ICMPV6:
|
||||
icmpv6_header = (PWINDIVERT_ICMPV6HDR)NdisGetDataBuffer(buffer,
|
||||
sizeof(WINDIVERT_ICMPV6HDR), NULL, 1, 0);
|
||||
header_len +=
|
||||
(icmpv6_header == NULL? 0: sizeof(WINDIVERT_ICMPV6HDR));
|
||||
break;
|
||||
case IPPROTO_TCP:
|
||||
tcp_header = (PWINDIVERT_TCPHDR)NdisGetDataBuffer(buffer,
|
||||
sizeof(WINDIVERT_TCPHDR), NULL, 1, 0);
|
||||
if (tcp_header != NULL)
|
||||
{
|
||||
UINT tcp_header_len = tcp_header->HdrLength * sizeof(UINT32);
|
||||
if (header_len + tcp_header_len > total_len)
|
||||
switch (protocol)
|
||||
{
|
||||
case IPPROTO_ICMP:
|
||||
if (ip_header == NULL)
|
||||
{
|
||||
// Bad TCP options:
|
||||
tcp_header = NULL;
|
||||
break;
|
||||
}
|
||||
header_len += tcp_header_len;
|
||||
}
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
udp_header = (PWINDIVERT_UDPHDR)NdisGetDataBuffer(buffer,
|
||||
sizeof(WINDIVERT_UDPHDR), NULL, 1, 0);
|
||||
header_len += (udp_header == NULL? 0: sizeof(WINDIVERT_UDPHDR));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
icmp_header = (PWINDIVERT_ICMPHDR)NdisGetDataBuffer(buffer,
|
||||
sizeof(WINDIVERT_ICMPHDR), NULL, 1, 0);
|
||||
header_len +=
|
||||
(icmp_header == NULL? 0: sizeof(WINDIVERT_ICMPHDR));
|
||||
break;
|
||||
|
||||
case IPPROTO_ICMPV6:
|
||||
if (ipv6_header == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
icmpv6_header = (PWINDIVERT_ICMPV6HDR)NdisGetDataBuffer(buffer,
|
||||
sizeof(WINDIVERT_ICMPV6HDR), NULL, 1, 0);
|
||||
header_len +=
|
||||
(icmpv6_header == NULL? 0: sizeof(WINDIVERT_ICMPV6HDR));
|
||||
break;
|
||||
|
||||
case IPPROTO_TCP:
|
||||
tcp_header = (PWINDIVERT_TCPHDR)NdisGetDataBuffer(buffer,
|
||||
sizeof(WINDIVERT_TCPHDR), NULL, 1, 0);
|
||||
if (tcp_header != NULL)
|
||||
{
|
||||
if (tcp_header->HdrLength < 5)
|
||||
{
|
||||
tcp_header = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT tcp_header_len =
|
||||
tcp_header->HdrLength * sizeof(UINT32);
|
||||
tcp_header_len =
|
||||
(header_len + tcp_header_len > total_len?
|
||||
total_len - header_len: tcp_header_len);
|
||||
header_len += tcp_header_len;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_UDP:
|
||||
udp_header = (PWINDIVERT_UDPHDR)NdisGetDataBuffer(buffer,
|
||||
sizeof(WINDIVERT_UDPHDR), NULL, 1, 0);
|
||||
header_len +=
|
||||
(udp_header == NULL? 0: sizeof(WINDIVERT_UDPHDR));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
status = NdisRetreatNetBufferDataStart(buffer, ip_header_len, 0, NULL);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
@@ -5488,7 +5531,7 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
|
||||
*icmpv6_header_ptr = icmpv6_header;
|
||||
*tcp_header_ptr = tcp_header;
|
||||
*udp_header_ptr = udp_header;
|
||||
*proto_ptr = proto;
|
||||
*proto_ptr = protocol;
|
||||
*header_len_ptr = header_len;
|
||||
*payload_len_ptr = total_len - header_len;
|
||||
|
||||
|
||||
+4
-4
@@ -38,20 +38,20 @@
|
||||
#define VER_FILETYPE VFT_DRV
|
||||
#define VER_FILESUBTYPE VFT2_DRV_NETWORK
|
||||
#define VER_FILEDESCRIPTION_STR \
|
||||
"The WinDivert 2.0 driver " \
|
||||
"The WinDivert 2.2 driver " \
|
||||
"[URL: https://reqrypt.org/windivert.html] " \
|
||||
"[Bitcoin: 1C5vZVSbizPeZ8ydTYhUfm4LA2cNwBfcYh]"
|
||||
#define VER_INTERNALNAME_STR "WinDivert.sys"
|
||||
#define VER_ORIGINALFILENAME_STR "WinDivert.sys"
|
||||
#define VER_PRODUCTVERSION 2.1
|
||||
#define VER_PRODUCTVERSION_STR "2.1"
|
||||
#define VER_PRODUCTVERSION 2.2
|
||||
#define VER_PRODUCTVERSION_STR "2.2"
|
||||
#define VER_COMPANYNAME_STR "Basil"
|
||||
#define VER_LEGALCOPYRIGHT_YEARS "2011-2019"
|
||||
#define VER_LEGALCOPYRIGHT_STR \
|
||||
"Copyright \251 " VER_COMPANYNAME_STR " " VER_LEGALCOPYRIGHT_YEARS
|
||||
#define VER_FILEVERSION VER_PRODUCTVERSION
|
||||
#define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR
|
||||
#define VER_PRODUCTNAME_STR "WinDivert 2.0 driver"
|
||||
#define VER_PRODUCTNAME_STR "WinDivert 2.2 driver"
|
||||
|
||||
#include "common.ver"
|
||||
|
||||
|
||||
+89
-6
@@ -43,6 +43,7 @@
|
||||
#include "windivert.h"
|
||||
|
||||
#define MAX_PACKET 2048
|
||||
#define MIN(a, b) ((a) < (b)? (a): (b))
|
||||
|
||||
/*
|
||||
* Packet data.
|
||||
@@ -112,6 +113,30 @@ static const struct packet pkt_ipv6_exthdrs_udp =
|
||||
sizeof(ipv6_exthdrs_udp),
|
||||
"ipv6_exthdrs_udp"
|
||||
};
|
||||
static const struct packet pkt_ipv4_fragment_0 =
|
||||
{
|
||||
ipv4_fragment_0,
|
||||
sizeof(ipv4_fragment_0),
|
||||
"ipv4_fragemnt_0"
|
||||
};
|
||||
static const struct packet pkt_ipv4_fragment_1 =
|
||||
{
|
||||
ipv4_fragment_1,
|
||||
sizeof(ipv4_fragment_1),
|
||||
"ipv4_fragment_1"
|
||||
};
|
||||
static const struct packet pkt_ipv6_fragment_0 =
|
||||
{
|
||||
ipv6_fragment_0,
|
||||
sizeof(ipv6_fragment_0),
|
||||
"ipv6_fragment_0"
|
||||
};
|
||||
static const struct packet pkt_ipv6_fragment_1 =
|
||||
{
|
||||
ipv6_fragment_1,
|
||||
sizeof(ipv6_fragment_1),
|
||||
"ipv6_fragment_1"
|
||||
};
|
||||
static const struct test tests[] =
|
||||
{
|
||||
{"event = PACKET", &pkt_echo_request, TRUE},
|
||||
@@ -309,6 +334,9 @@ static const struct test tests[] =
|
||||
{"localAddr == 10.0.0.1 && remoteAddr == 8.8.8.8 && localPort == 8 && "
|
||||
"remotePort == 0 && protocol == 1", &pkt_echo_request, TRUE},
|
||||
{"packet[0] == 0x45", &pkt_echo_request, TRUE},
|
||||
{"ip.MF or ip.FragOff != 0", &pkt_echo_request, FALSE},
|
||||
{"icmp.Body != 123 || icmp.Body == 123", &pkt_echo_request, TRUE},
|
||||
{"length == 84 && ip.Length == 84", &pkt_echo_request, TRUE},
|
||||
{"tcp", &pkt_http_request, TRUE},
|
||||
{"protocol == TCP", &pkt_http_request, TRUE},
|
||||
{"outbound and tcp and tcp.DstPort == 80", &pkt_http_request, TRUE},
|
||||
@@ -720,6 +748,7 @@ static const struct test tests[] =
|
||||
{"icmpv6.Body == 0x10720003", &pkt_ipv6_echo_reply, TRUE},
|
||||
{"ipv6.DstAddr >= 1000", &pkt_ipv6_echo_reply, FALSE},
|
||||
{"ipv6.DstAddr <= 1", &pkt_ipv6_echo_reply, TRUE},
|
||||
{"length == 104 && ipv6.Length == 64", &pkt_ipv6_echo_reply, TRUE},
|
||||
{"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},
|
||||
@@ -855,12 +884,47 @@ 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},
|
||||
{"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},
|
||||
{"length == 84 || ip.Length == 84", &pkt_ipv4_fragment_0, FALSE},
|
||||
{"ip.HdrLength == 5 and ip.TOS == 0 and ip.Length == 28 and "
|
||||
"ip.Id == 0x1234 and ip.FragOff == 0 and ip.MF == 1 and ip.DF == 0 and "
|
||||
"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},
|
||||
{"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},
|
||||
{"length == 84 || ip.Length == 84", &pkt_ipv4_fragment_1, FALSE},
|
||||
{"ip.HdrLength == 5 and ip.TOS == 0 and ip.Length == 76 and "
|
||||
"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},
|
||||
{"icmpv6", &pkt_ipv6_fragment_0, TRUE},
|
||||
{"length == 104 || ipv6.Length == 64", &pkt_ipv6_fragment_0, FALSE},
|
||||
{"ipv6.TrafficClass == 0x00000000 and ipv6.FlowLabel == 0x0000 and "
|
||||
"ipv6.Length == 32 and ipv6.NextHdr == 44 and ipv6.HopLimit == 31 and "
|
||||
"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},
|
||||
{"icmpv6", &pkt_ipv6_fragment_1, FALSE},
|
||||
{"length == 104 || ipv6.Length == 64", &pkt_ipv6_fragment_1, FALSE},
|
||||
{"ipv6.TrafficClass == 0x00000000 and ipv6.FlowLabel == 0x0000 and "
|
||||
"ipv6.Length == 48 and ipv6.NextHdr == 44 and ipv6.HopLimit == 31 and "
|
||||
"ipv6.SrcAddr == 0:0:0:0:0:0:0:1 and ipv6.DstAddr == 0:0:0:0:0:0:0:1",
|
||||
&pkt_ipv6_fragment_1, TRUE},
|
||||
};
|
||||
|
||||
/*
|
||||
* Test range.
|
||||
*/
|
||||
static size_t lo = 0, hi = UINT_MAX;
|
||||
|
||||
/*
|
||||
* Main.
|
||||
*/
|
||||
int main(void)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
HANDLE upper_handle, lower_handle;
|
||||
HANDLE console, monitor;
|
||||
@@ -869,6 +933,25 @@ int main(void)
|
||||
LARGE_INTEGER freq;
|
||||
UINT64 diff;
|
||||
size_t i;
|
||||
size_t num_tests = sizeof(tests) / sizeof(struct test), passed_tests;
|
||||
|
||||
switch (argc)
|
||||
{
|
||||
case 1:
|
||||
break;
|
||||
case 3:
|
||||
lo = atoi(argv[1]);
|
||||
hi = atoi(argv[2]);
|
||||
if (hi >= lo)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// Fallthrough
|
||||
default:
|
||||
fprintf(stderr, "usage: %s [low high]\n", argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
hi = MIN(num_tests, hi);
|
||||
|
||||
// Open handles to:
|
||||
// (1) stop normal traffic from interacting with the tests; and
|
||||
@@ -902,8 +985,8 @@ int main(void)
|
||||
Sleep(150);
|
||||
|
||||
// Run tests:
|
||||
size_t num_tests = sizeof(tests) / sizeof(struct test), passed_tests = 0;
|
||||
for (i = 0; i < num_tests; i++)
|
||||
passed_tests = 0;
|
||||
for (i = lo; i < num_tests && i <= hi; i++)
|
||||
{
|
||||
const char *filter = tests[i].filter;
|
||||
const char *packet = tests[i].packet->packet;
|
||||
@@ -961,10 +1044,10 @@ int main(void)
|
||||
}
|
||||
|
||||
printf("\npassed = %.2f%%\n",
|
||||
((double)passed_tests / (double)num_tests) * 100.0);
|
||||
((double)passed_tests / (double)(hi - lo)) * 100.0);
|
||||
|
||||
first = TRUE;
|
||||
for (i = 0; i < num_tests; i++)
|
||||
for (i = lo; i < num_tests && i <= hi; i++)
|
||||
{
|
||||
const char *filter = tests[i].filter;
|
||||
char *name = tests[i].packet->name;
|
||||
@@ -1274,7 +1357,7 @@ static DWORD monitor_worker(LPVOID arg)
|
||||
}
|
||||
|
||||
size_t num_tests = sizeof(tests) / sizeof(struct test);
|
||||
for (i = 0; i < num_tests; i++)
|
||||
for (i = lo; i < num_tests && i <= hi; i++)
|
||||
{
|
||||
// (1) Read the reflected filter:
|
||||
WinDivertHelperCompileFilter(tests[i].filter, WINDIVERT_LAYER_NETWORK,
|
||||
|
||||
@@ -181,3 +181,56 @@ static const unsigned char ipv6_exthdrs_udp[] =
|
||||
0x72, 0x6c, 0x64, 0x21, 0x01
|
||||
};
|
||||
|
||||
// IPV4 FRAGMENT #0
|
||||
static const unsigned char ipv4_fragment_0[] =
|
||||
{
|
||||
0x45, 0x00, 0x00, 0x1C, 0x12, 0x34, 0x20, 0x00,
|
||||
0x40, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x01,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x3c, 0xd2,
|
||||
0x0d, 0x56, 0x00, 0x01
|
||||
};
|
||||
|
||||
// IPV4 FRAGMENT #1
|
||||
static const unsigned char ipv4_fragment_1[] =
|
||||
{
|
||||
0x45, 0x00, 0x00, 0x4C, 0x12, 0x34, 0x00, 0x01,
|
||||
0x40, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x01,
|
||||
0x08, 0x08, 0x08, 0x08, 0x8b, 0xa6, 0x60, 0x54,
|
||||
0x00, 0x00, 0x00, 0x00, 0xf9, 0x08, 0x0a, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x12, 0x13,
|
||||
0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
|
||||
0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
|
||||
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
|
||||
0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33,
|
||||
0x34, 0x35, 0x36, 0x37
|
||||
};
|
||||
|
||||
// IPV6 FRAGMENT #0
|
||||
static const unsigned char ipv6_fragment_0[] =
|
||||
{
|
||||
0x60, 0x00, 0x00, 0x00, 0x00, 0x20, 0x2c, 0x1f,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0x3a, 0x00, 0x00, 0x01, 0xc7, 0xf6, 0xce, 0x53,
|
||||
0x81, 0x00, 0x6e, 0xd6, 0x10, 0x72, 0x00, 0x03,
|
||||
0xa4, 0xd5, 0x69, 0x54, 0x00, 0x00, 0x00, 0x00,
|
||||
0xab, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
// IPV6 FRAGMENT #1
|
||||
static const unsigned char ipv6_fragment_1[] =
|
||||
{
|
||||
0x60, 0x00, 0x00, 0x00, 0x00, 0x30, 0x2c, 0x1f,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0x3a, 0x00, 0x00, 0x18, 0xc7, 0xf6, 0xce, 0x53,
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
||||
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
||||
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user