Minor API improvements.
- addr.Pseudo*Checksum flags replaced by simpler addr.*Checksum flags. - WinDivertHelperParsePacket() can now handle batched packets. - WinDivertHelperParsePacket() can now return the transport protocol. - WinDivertHelperCalcChecksums() can now handle batched packets. - WinDivertHelperCalcChecksums() now sets address checksum flags that were calculated. - A bunch of WINDIVERT_* macros have been moved to windivert.h for windivert_device.h.
This commit is contained in:
+7
-20
@@ -284,19 +284,6 @@ static BOOL WinDivertDeserializeFilter(PWINDIVERT_STREAM stream,
|
||||
static void WinDivertFormatExpr(PWINDIVERT_STREAM stream, PEXPR expr,
|
||||
WINDIVERT_LAYER layer, BOOL top_level, BOOL and);
|
||||
|
||||
/*
|
||||
* 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,
|
||||
PWINDIVERT_ICMPHDR *ppIcmpHdr, PWINDIVERT_ICMPV6HDR *ppIcmpv6Hdr,
|
||||
PWINDIVERT_TCPHDR *ppTcpHdr, PWINDIVERT_UDPHDR *ppUdpHdr, PVOID *ppData,
|
||||
UINT *pDataLen)
|
||||
{
|
||||
return WinDivertParsePacket((PVOID)pPacket, packetLen, ppIpHdr, ppIpv6Hdr,
|
||||
ppIcmpHdr, ppIcmpv6Hdr, ppTcpHdr, ppUdpHdr, NULL, ppData, pDataLen);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse an IPv4 address.
|
||||
*/
|
||||
@@ -2446,9 +2433,9 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet,
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
WinDivertParsePacket((PVOID)packet, packet_len, &iphdr, &ipv6hdr,
|
||||
&icmphdr, &icmpv6hdr, &tcphdr, &udphdr, &protocol, NULL,
|
||||
&payload_len);
|
||||
WinDivertHelperParsePacket((PVOID)packet, packet_len, &protocol,
|
||||
&iphdr, &ipv6hdr, &icmphdr, &icmpv6hdr, &tcphdr, &udphdr,
|
||||
NULL, &payload_len, NULL, NULL);
|
||||
header_len = packet_len - payload_len;
|
||||
if ((addr->IPv6 && ipv6hdr == NULL) ||
|
||||
(!addr->IPv6 && iphdr == NULL))
|
||||
@@ -4599,9 +4586,9 @@ extern UINT64 WinDivertHelperHashPacket(const VOID *pPacket, UINT packetLen,
|
||||
PWINDIVERT_TCPHDR tcp_header = NULL;
|
||||
PWINDIVERT_UDPHDR udp_header = NULL;
|
||||
|
||||
WinDivertParsePacket((PVOID)pPacket, packetLen, &ip_header, &ipv6_header,
|
||||
&icmp_header, &icmpv6_header, &tcp_header, &udp_header, NULL,
|
||||
NULL, NULL);
|
||||
WinDivertHelperParsePacket((PVOID)pPacket, packetLen, NULL, &ip_header,
|
||||
&ipv6_header, &icmp_header, &icmpv6_header, &tcp_header, &udp_header,
|
||||
NULL, NULL, NULL, NULL);
|
||||
return WinDivertHashPacket(seed, ip_header, ipv6_header, icmp_header,
|
||||
icmpv6_header, tcp_header, udp_header);
|
||||
}
|
||||
@@ -4635,7 +4622,7 @@ extern UINT64 WinDivertHelperHtonll(UINT64 x)
|
||||
}
|
||||
static void WinDivertByteSwap128(const UINT *inAddr, UINT *outAddr)
|
||||
{
|
||||
UINT32 tmp[4], i; // tmp[] allows overlapping
|
||||
UINT32 tmp[4], i; // tmp[] allows overlapping inAddr/outAddr
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
tmp[3-i] = BYTESWAP32(inAddr[0]);
|
||||
|
||||
+102
-93
@@ -283,11 +283,11 @@ static UINT8 WinDivertSkipExtHeaders(UINT8 proto, UINT8 **header, UINT *len)
|
||||
/*
|
||||
* Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet.
|
||||
*/
|
||||
static BOOL WinDivertParsePacket(PVOID pPacket, UINT packetLen,
|
||||
PWINDIVERT_IPHDR *ppIpHdr, PWINDIVERT_IPV6HDR *ppIpv6Hdr,
|
||||
extern BOOL WinDivertHelperParsePacket(const VOID *pPacket, UINT packetLen,
|
||||
UINT8 *pProtocol, PWINDIVERT_IPHDR *ppIpHdr, PWINDIVERT_IPV6HDR *ppIpv6Hdr,
|
||||
PWINDIVERT_ICMPHDR *ppIcmpHdr, PWINDIVERT_ICMPV6HDR *ppIcmpv6Hdr,
|
||||
PWINDIVERT_TCPHDR *ppTcpHdr, PWINDIVERT_UDPHDR *ppUdpHdr, UINT8 *pProto,
|
||||
PVOID *ppData, UINT *pDataLen)
|
||||
PWINDIVERT_TCPHDR *ppTcpHdr, PWINDIVERT_UDPHDR *ppUdpHdr, PVOID *ppData,
|
||||
UINT *pDataLen, PVOID *ppNext, UINT *pNextLen)
|
||||
{
|
||||
PWINDIVERT_IPHDR ip_header = NULL;
|
||||
PWINDIVERT_IPV6HDR ipv6_header = NULL;
|
||||
@@ -297,15 +297,15 @@ static BOOL WinDivertParsePacket(PVOID pPacket, UINT packetLen,
|
||||
PWINDIVERT_UDPHDR udp_header = NULL;
|
||||
UINT16 header_len;
|
||||
UINT8 trans_proto = 0;
|
||||
PVOID data = NULL;
|
||||
UINT data_len = 0;
|
||||
BOOL success;
|
||||
PVOID data = NULL, next = NULL;
|
||||
UINT data_len = 0, next_len = 0, packet_len;
|
||||
BOOL success = FALSE;
|
||||
|
||||
if (pPacket == NULL || packetLen < sizeof(UINT8))
|
||||
if (pPacket == NULL || packetLen < sizeof(WINDIVERT_IPHDR))
|
||||
{
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
data = pPacket;
|
||||
data = (PVOID)pPacket;
|
||||
data_len = packetLen;
|
||||
|
||||
ip_header = (PWINDIVERT_IPHDR)data;
|
||||
@@ -315,29 +315,41 @@ static BOOL WinDivertParsePacket(PVOID pPacket, UINT packetLen,
|
||||
if (data_len < sizeof(WINDIVERT_IPHDR) ||
|
||||
ip_header->HdrLength < 5 ||
|
||||
data_len < ip_header->HdrLength*sizeof(UINT32) ||
|
||||
ntohs(ip_header->Length) != data_len)
|
||||
(UINT)ntohs(ip_header->Length) > data_len)
|
||||
{
|
||||
ip_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
trans_proto = ip_header->Protocol;
|
||||
packet_len = (UINT)ntohs(ip_header->Length);
|
||||
header_len = ip_header->HdrLength*sizeof(UINT32);
|
||||
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 -= header_len;
|
||||
data_len = packet_len - header_len;
|
||||
break;
|
||||
case 6:
|
||||
ip_header = NULL;
|
||||
ipv6_header = (PWINDIVERT_IPV6HDR)data;
|
||||
if (data_len < sizeof(WINDIVERT_IPV6HDR) ||
|
||||
ntohs(ipv6_header->Length) !=
|
||||
data_len - sizeof(WINDIVERT_IPV6HDR))
|
||||
ntohs(ipv6_header->Length) + sizeof(WINDIVERT_IPV6HDR) >
|
||||
data_len)
|
||||
{
|
||||
ipv6_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
trans_proto = ipv6_header->NextHdr;
|
||||
packet_len = ntohs(ipv6_header->Length) + sizeof(WINDIVERT_IPV6HDR);
|
||||
if (packet_len < data_len)
|
||||
{
|
||||
next = (PVOID)((UINT8 *)data + packet_len);
|
||||
next_len = data_len - packet_len;
|
||||
}
|
||||
data = (PVOID)((UINT8 *)data + sizeof(WINDIVERT_IPV6HDR));
|
||||
data_len -= sizeof(WINDIVERT_IPV6HDR);
|
||||
data_len = packet_len - sizeof(WINDIVERT_IPV6HDR);
|
||||
trans_proto = WinDivertSkipExtHeaders(trans_proto, (UINT8 **)&data,
|
||||
&data_len);
|
||||
break;
|
||||
@@ -345,6 +357,7 @@ static BOOL WinDivertParsePacket(PVOID pPacket, UINT packetLen,
|
||||
ip_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
success = TRUE;
|
||||
switch (trans_proto)
|
||||
{
|
||||
case IPPROTO_TCP:
|
||||
@@ -403,50 +416,51 @@ static BOOL WinDivertParsePacket(PVOID pPacket, UINT packetLen,
|
||||
}
|
||||
|
||||
WinDivertHelperParsePacketExit:
|
||||
success = TRUE;
|
||||
if (pProtocol != NULL)
|
||||
{
|
||||
*pProtocol = trans_proto;
|
||||
}
|
||||
if (ppIpHdr != NULL)
|
||||
{
|
||||
*ppIpHdr = ip_header;
|
||||
success = success && (ip_header != NULL);
|
||||
}
|
||||
if (ppIpv6Hdr != NULL)
|
||||
{
|
||||
*ppIpv6Hdr = ipv6_header;
|
||||
success = success && (ipv6_header != NULL);
|
||||
}
|
||||
if (ppIcmpHdr != NULL)
|
||||
{
|
||||
*ppIcmpHdr = icmp_header;
|
||||
success = success && (icmp_header != NULL);
|
||||
}
|
||||
if (ppIcmpv6Hdr != NULL)
|
||||
{
|
||||
*ppIcmpv6Hdr = icmpv6_header;
|
||||
success = success && (icmpv6_header != NULL);
|
||||
}
|
||||
if (ppTcpHdr != NULL)
|
||||
{
|
||||
*ppTcpHdr = tcp_header;
|
||||
success = success && (tcp_header != NULL);
|
||||
}
|
||||
if (ppUdpHdr != NULL)
|
||||
{
|
||||
*ppUdpHdr = udp_header;
|
||||
success = success && (udp_header != NULL);
|
||||
}
|
||||
if (pProto != NULL)
|
||||
{
|
||||
*pProto = trans_proto;
|
||||
}
|
||||
if (ppData != NULL)
|
||||
{
|
||||
*ppData = data;
|
||||
success = success && (data != NULL);
|
||||
}
|
||||
if (pDataLen != NULL)
|
||||
{
|
||||
*pDataLen = data_len;
|
||||
}
|
||||
if (ppNext != NULL)
|
||||
{
|
||||
*ppNext = next;
|
||||
}
|
||||
if (pNextLen != NULL)
|
||||
{
|
||||
*pNextLen = next_len;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@@ -454,7 +468,7 @@ WinDivertHelperParsePacketExit:
|
||||
* Calculate IPv4/IPv6/ICMP/ICMPv6/TCP/UDP checksums.
|
||||
*/
|
||||
extern UINT WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
|
||||
const WINDIVERT_ADDRESS *pAddr, UINT64 flags)
|
||||
WINDIVERT_ADDRESS *pAddr, UINT64 flags)
|
||||
{
|
||||
UINT8 pseudo_header[
|
||||
MAX(sizeof(WINDIVERT_PSEUDOHDR), sizeof(WINDIVERT_PSEUDOV6HDR))];
|
||||
@@ -468,83 +482,78 @@ extern UINT WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
|
||||
UINT payload_len, checksum_len;
|
||||
UINT count = 0;
|
||||
|
||||
WinDivertParsePacket(pPacket, packetLen, &ip_header, &ipv6_header,
|
||||
&icmp_header, &icmpv6_header, &tcp_header, &udp_header, NULL, NULL,
|
||||
&payload_len);
|
||||
|
||||
if (ip_header != NULL && !(flags & WINDIVERT_HELPER_NO_IP_CHECKSUM))
|
||||
while (WinDivertHelperParsePacket(pPacket, packetLen, NULL, &ip_header,
|
||||
&ipv6_header, &icmp_header, &icmpv6_header, &tcp_header,
|
||||
&udp_header, NULL, &payload_len, &pPacket, &packetLen))
|
||||
{
|
||||
ip_header->Checksum = 0;
|
||||
if (pAddr == NULL || pAddr->PseudoIPChecksum == 0)
|
||||
{
|
||||
ip_header->Checksum = WinDivertCalcChecksum(NULL, 0,
|
||||
ip_header, ip_header->HdrLength*sizeof(UINT32));
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
if (icmp_header != NULL)
|
||||
{
|
||||
if ((flags & WINDIVERT_HELPER_NO_ICMP_CHECKSUM) != 0)
|
||||
if (ip_header != NULL && !(flags & WINDIVERT_HELPER_NO_IP_CHECKSUM))
|
||||
{
|
||||
return count;
|
||||
ip_header->Checksum = 0;
|
||||
ip_header->Checksum = WinDivertCalcChecksum(NULL, 0, ip_header,
|
||||
ip_header->HdrLength*sizeof(UINT32));
|
||||
if (pAddr != NULL)
|
||||
{
|
||||
pAddr->IPChecksum = 1;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
icmp_header->Checksum = 0;
|
||||
icmp_header->Checksum = WinDivertCalcChecksum(NULL, 0,
|
||||
icmp_header, payload_len + sizeof(WINDIVERT_ICMPHDR));
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
if (icmpv6_header != NULL)
|
||||
{
|
||||
if ((flags & WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM) != 0)
|
||||
|
||||
if (icmp_header != NULL)
|
||||
{
|
||||
return count;
|
||||
if ((flags & WINDIVERT_HELPER_NO_ICMP_CHECKSUM) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
icmp_header->Checksum = 0;
|
||||
icmp_header->Checksum = WinDivertCalcChecksum(NULL, 0,
|
||||
icmp_header, payload_len + sizeof(WINDIVERT_ICMPHDR));
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
checksum_len = payload_len + sizeof(WINDIVERT_ICMPV6HDR);
|
||||
pseudo_header_len = WinDivertInitPseudoHeader(NULL, ipv6_header,
|
||||
IPPROTO_ICMPV6, checksum_len, pseudo_header);
|
||||
icmpv6_header->Checksum = 0;
|
||||
icmpv6_header->Checksum = WinDivertCalcChecksum(pseudo_header,
|
||||
pseudo_header_len, icmpv6_header, checksum_len);
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
if (tcp_header != NULL)
|
||||
{
|
||||
if ((flags & WINDIVERT_HELPER_NO_TCP_CHECKSUM) != 0)
|
||||
|
||||
if (icmpv6_header != NULL)
|
||||
{
|
||||
return count;
|
||||
if ((flags & WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
checksum_len = payload_len + sizeof(WINDIVERT_ICMPV6HDR);
|
||||
pseudo_header_len = WinDivertInitPseudoHeader(NULL, ipv6_header,
|
||||
IPPROTO_ICMPV6, checksum_len, pseudo_header);
|
||||
icmpv6_header->Checksum = 0;
|
||||
icmpv6_header->Checksum = WinDivertCalcChecksum(pseudo_header,
|
||||
pseudo_header_len, icmpv6_header, checksum_len);
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
if (pAddr == NULL || pAddr->PseudoTCPChecksum == 0)
|
||||
|
||||
if (tcp_header != NULL)
|
||||
{
|
||||
// Full TCP checksum
|
||||
if ((flags & WINDIVERT_HELPER_NO_TCP_CHECKSUM) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
checksum_len = payload_len + tcp_header->HdrLength*sizeof(UINT32);
|
||||
pseudo_header_len = WinDivertInitPseudoHeader(ip_header,
|
||||
ipv6_header, IPPROTO_TCP, checksum_len, pseudo_header);
|
||||
tcp_header->Checksum = 0;
|
||||
tcp_header->Checksum = WinDivertCalcChecksum(
|
||||
pseudo_header, pseudo_header_len, tcp_header, checksum_len);
|
||||
if (pAddr != NULL)
|
||||
{
|
||||
pAddr->TCPChecksum = 1;
|
||||
}
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
else if (pAddr->Outbound)
|
||||
{
|
||||
// Pseudo TCP checksum
|
||||
tcp_header->Checksum = 0;
|
||||
}
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
if (udp_header != NULL)
|
||||
{
|
||||
if ((flags & WINDIVERT_HELPER_NO_UDP_CHECKSUM) != 0)
|
||||
{
|
||||
return count;
|
||||
}
|
||||
if (pAddr == NULL || pAddr->PseudoUDPChecksum == 0)
|
||||
|
||||
if (udp_header != NULL)
|
||||
{
|
||||
if ((flags & WINDIVERT_HELPER_NO_UDP_CHECKSUM) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// Full UDP checksum
|
||||
checksum_len = payload_len + sizeof(WINDIVERT_UDPHDR);
|
||||
pseudo_header_len = WinDivertInitPseudoHeader(ip_header,
|
||||
@@ -556,14 +565,14 @@ extern UINT WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
|
||||
{
|
||||
udp_header->Checksum = 0xFFFF;
|
||||
}
|
||||
if (pAddr != NULL)
|
||||
{
|
||||
pAddr->UDPChecksum = 1;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
else if (pAddr->Outbound)
|
||||
{
|
||||
// Pseudo UDP checksum
|
||||
udp_header->Checksum = 0;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
@@ -147,9 +147,9 @@ int __cdecl main(int argc, char **argv)
|
||||
}
|
||||
|
||||
// Print info about the matching packet.
|
||||
WinDivertHelperParsePacket(packet, packet_len, &ip_header,
|
||||
WinDivertHelperParsePacket(packet, packet_len, NULL, &ip_header,
|
||||
&ipv6_header, &icmp_header, &icmpv6_header, &tcp_header,
|
||||
&udp_header, NULL, NULL);
|
||||
&udp_header, NULL, NULL, NULL, NULL);
|
||||
if (ip_header == NULL && ipv6_header == NULL)
|
||||
{
|
||||
fprintf(stderr, "warning: junk packet\n");
|
||||
|
||||
@@ -201,9 +201,9 @@ int __cdecl main(int argc, char **argv)
|
||||
}
|
||||
|
||||
// Print info about the matching packet.
|
||||
WinDivertHelperParsePacket(packet, packet_len, &ip_header,
|
||||
WinDivertHelperParsePacket(packet, packet_len, NULL, &ip_header,
|
||||
&ipv6_header, &icmp_header, &icmpv6_header, &tcp_header,
|
||||
&udp_header, NULL, &payload_len);
|
||||
&udp_header, NULL, &payload_len, NULL, NULL);
|
||||
if (ip_header == NULL && ipv6_header == NULL)
|
||||
{
|
||||
continue;
|
||||
|
||||
@@ -250,8 +250,9 @@ read_failed:
|
||||
}
|
||||
cleanup(ioport, &overlapped);
|
||||
|
||||
if (!WinDivertHelperParsePacket(packet, packet_len, &ip_header, NULL,
|
||||
NULL, NULL, &tcp_header, NULL, NULL, NULL))
|
||||
WinDivertHelperParsePacket(packet, packet_len, NULL, &ip_header, NULL,
|
||||
NULL, NULL, &tcp_header, NULL, NULL, NULL, NULL, NULL);
|
||||
if (ip_header == NULL || tcp_header == NULL)
|
||||
{
|
||||
warning("failed to parse packet (%d)", GetLastError());
|
||||
continue;
|
||||
|
||||
@@ -204,8 +204,10 @@ int __cdecl main(int argc, char **argv)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!WinDivertHelperParsePacket(packet, packet_len, &ip_header, NULL,
|
||||
NULL, NULL, &tcp_header, NULL, &payload, &payload_len) ||
|
||||
WinDivertHelperParsePacket(packet, packet_len, NULL, &ip_header,
|
||||
NULL, NULL, NULL, &tcp_header, NULL, &payload, &payload_len,
|
||||
NULL, NULL);
|
||||
if (ip_header == NULL || tcp_header == NULL || payload == NULL ||
|
||||
!BlackListPayloadMatch(blacklist, payload, (UINT16)payload_len))
|
||||
{
|
||||
// Packet does not match the blacklist; simply reinject it.
|
||||
|
||||
@@ -390,7 +390,7 @@ usage:
|
||||
fputs(" filter=", stdout);
|
||||
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
WinDivertHelperParsePacket(packet, packet_len, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, &object, NULL);
|
||||
NULL, NULL, NULL, &object, NULL, NULL, NULL);
|
||||
if (WinDivertHelperFormatFilter((char *)object, addr.Reflect.Layer,
|
||||
filter_str, sizeof(filter_str)))
|
||||
{
|
||||
|
||||
+24
-5
@@ -140,9 +140,9 @@ typedef struct
|
||||
UINT64 Loopback:1; /* Packet is loopback? */
|
||||
UINT64 Impostor:1; /* Packet is impostor? */
|
||||
UINT64 IPv6:1; /* Packet is IPv6? */
|
||||
UINT64 PseudoIPChecksum:1; /* Packet has pseudo IPv4 checksum? */
|
||||
UINT64 PseudoTCPChecksum:1; /* Packet has pseudo TCP checksum? */
|
||||
UINT64 PseudoUDPChecksum:1; /* Packet has pseudo UDP checksum? */
|
||||
UINT64 IPChecksum:1; /* Packet has valid IPv4 checksum? */
|
||||
UINT64 TCPChecksum:1; /* Packet has valid TCP checksum? */
|
||||
UINT64 UDPChecksum:1; /* Packet has valid UDP checksum? */
|
||||
UINT64 Reserved:41;
|
||||
union
|
||||
{
|
||||
@@ -292,6 +292,22 @@ extern WINDIVERTEXPORT BOOL WinDivertGetParam(
|
||||
|
||||
#endif /* WINDIVERT_KERNEL */
|
||||
|
||||
/*
|
||||
* WinDivert constants.
|
||||
*/
|
||||
#define WINDIVERT_PRIORITY_LOWEST 30000
|
||||
#define WINDIVERT_PRIORITY_HIGHEST (-WINDIVERT_PRIORITY_LOWEST)
|
||||
#define WINDIVERT_PARAM_QUEUE_LEN_DEFAULT 2048
|
||||
#define WINDIVERT_PARAM_QUEUE_LEN_MIN 16
|
||||
#define WINDIVERT_PARAM_QUEUE_LEN_MAX 16384
|
||||
#define WINDIVERT_PARAM_QUEUE_TIME_DEFAULT 1000 /* 1s */
|
||||
#define WINDIVERT_PARAM_QUEUE_TIME_MIN 20 /* 20ms */
|
||||
#define WINDIVERT_PARAM_QUEUE_TIME_MAX 8000 /* 8s */
|
||||
#define WINDIVERT_PARAM_QUEUE_SIZE_DEFAULT 4194304 /* 4MB */
|
||||
#define WINDIVERT_PARAM_QUEUE_SIZE_MIN 65535 /* 64KB */
|
||||
#define WINDIVERT_PARAM_QUEUE_SIZE_MAX 33554432 /* 32MB */
|
||||
#define WINDIVERT_BATCH_MAX 0xFF /* 255 */
|
||||
|
||||
/****************************************************************************/
|
||||
/* WINDIVERT HELPER API */
|
||||
/****************************************************************************/
|
||||
@@ -459,6 +475,7 @@ extern WINDIVERTEXPORT UINT64 WinDivertHelperHashPacket(
|
||||
extern WINDIVERTEXPORT BOOL WinDivertHelperParsePacket(
|
||||
__in const VOID *pPacket,
|
||||
__in UINT packetLen,
|
||||
__out_opt UINT8 *pProtocol,
|
||||
__out_opt PWINDIVERT_IPHDR *ppIpHdr,
|
||||
__out_opt PWINDIVERT_IPV6HDR *ppIpv6Hdr,
|
||||
__out_opt PWINDIVERT_ICMPHDR *ppIcmpHdr,
|
||||
@@ -466,7 +483,9 @@ extern WINDIVERTEXPORT BOOL WinDivertHelperParsePacket(
|
||||
__out_opt PWINDIVERT_TCPHDR *ppTcpHdr,
|
||||
__out_opt PWINDIVERT_UDPHDR *ppUdpHdr,
|
||||
__out_opt PVOID *ppData,
|
||||
__out_opt UINT *pDataLen);
|
||||
__out_opt UINT *pDataLen,
|
||||
__out_opt PVOID *ppNext,
|
||||
__out_opt UINT *pNextLen);
|
||||
|
||||
/*
|
||||
* Parse an IPv4 address.
|
||||
@@ -504,7 +523,7 @@ extern WINDIVERTEXPORT BOOL WinDivertHelperFormatIPv6Address(
|
||||
extern WINDIVERTEXPORT UINT WinDivertHelperCalcChecksums(
|
||||
__inout VOID *pPacket,
|
||||
__in UINT packetLen,
|
||||
__in_opt const WINDIVERT_ADDRESS *pAddr,
|
||||
__out_opt WINDIVERT_ADDRESS *pAddr,
|
||||
__in UINT64 flags);
|
||||
|
||||
/*
|
||||
|
||||
@@ -212,26 +212,8 @@
|
||||
* WinDivert priorities.
|
||||
*/
|
||||
#define WINDIVERT_PRIORITY_DEFAULT 0
|
||||
#define WINDIVERT_PRIORITY_MAX 30000
|
||||
#define WINDIVERT_PRIORITY_MIN -WINDIVERT_PRIORITY_MAX
|
||||
|
||||
/*
|
||||
* WinDivert parameters.
|
||||
*/
|
||||
#define WINDIVERT_PARAM_QUEUE_LEN_DEFAULT 2048
|
||||
#define WINDIVERT_PARAM_QUEUE_LEN_MIN 16
|
||||
#define WINDIVERT_PARAM_QUEUE_LEN_MAX 16384
|
||||
#define WINDIVERT_PARAM_QUEUE_TIME_DEFAULT 1000 // 1s
|
||||
#define WINDIVERT_PARAM_QUEUE_TIME_MIN 20 // 20ms
|
||||
#define WINDIVERT_PARAM_QUEUE_TIME_MAX 8000 // 8s
|
||||
#define WINDIVERT_PARAM_QUEUE_SIZE_MIN 65535 // 64KB
|
||||
#define WINDIVERT_PARAM_QUEUE_SIZE_MAX 33554432 // 32MB
|
||||
#define WINDIVERT_PARAM_QUEUE_SIZE_DEFAULT 4194304 // 4MB
|
||||
|
||||
/*
|
||||
* WinDivert batch limits.
|
||||
*/
|
||||
#define WINDIVERT_BATCH_MAX 0xFF
|
||||
#define WINDIVERT_PRIORITY_MAX WINDIVERT_PRIORITY_LOWEST
|
||||
#define WINDIVERT_PRIORITY_MIN WINDIVERT_PRIORITY_HIGHEST
|
||||
|
||||
/*
|
||||
* WinDivert message definitions.
|
||||
|
||||
+66
-80
@@ -251,9 +251,9 @@ struct packet_s
|
||||
UINT64 loopback:1; // Packet is loopback?
|
||||
UINT64 impostor:1; // Packet is impostor?
|
||||
UINT64 ipv6:1; // Packet is IPv6?
|
||||
UINT64 pseudo_ip_checksum:1; // Packet has pseudo IPv4 check?
|
||||
UINT64 pseudo_tcp_checksum:1; // Packet has pseudo TCP check?
|
||||
UINT64 pseudo_udp_checksum:1; // Packet has pseudo UDP check?
|
||||
UINT64 ip_checksum:1; // Packet has IPv4 checksum?
|
||||
UINT64 tcp_checksum:1; // Packet has TCP checksum?
|
||||
UINT64 udp_checksum:1; // Packet has UDP checksum?
|
||||
UINT64 match:1; // Packet matches filter?
|
||||
UINT32 priority; // Packet priority.
|
||||
UINT32 packet_len; // Length of the packet.
|
||||
@@ -2006,17 +2006,17 @@ static void windivert_read_service_request(context_t context, packet_t packet,
|
||||
// Copy the address data:
|
||||
if (addr != NULL)
|
||||
{
|
||||
addr[i].Timestamp = (INT64)packet->timestamp;
|
||||
addr[i].Layer = packet->layer;
|
||||
addr[i].Event = packet->event;
|
||||
addr[i].Outbound = packet->outbound;
|
||||
addr[i].Loopback = packet->loopback;
|
||||
addr[i].Impostor = packet->impostor;
|
||||
addr[i].IPv6 = packet->ipv6;
|
||||
addr[i].PseudoIPChecksum = packet->pseudo_ip_checksum;
|
||||
addr[i].PseudoTCPChecksum = packet->pseudo_tcp_checksum;
|
||||
addr[i].PseudoUDPChecksum = packet->pseudo_udp_checksum;
|
||||
addr[i].Reserved = 0;
|
||||
addr[i].Timestamp = (INT64)packet->timestamp;
|
||||
addr[i].Layer = packet->layer;
|
||||
addr[i].Event = packet->event;
|
||||
addr[i].Outbound = packet->outbound;
|
||||
addr[i].Loopback = packet->loopback;
|
||||
addr[i].Impostor = packet->impostor;
|
||||
addr[i].IPv6 = packet->ipv6;
|
||||
addr[i].IPChecksum = packet->ip_checksum;
|
||||
addr[i].TCPChecksum = packet->tcp_checksum;
|
||||
addr[i].UDPChecksum = packet->udp_checksum;
|
||||
addr[i].Reserved = 0;
|
||||
layer_data = (PVOID)packet->data;
|
||||
switch (packet->layer)
|
||||
{
|
||||
@@ -2119,7 +2119,7 @@ static void windivert_fast_read_service_request(PVOID packet, ULONG packet_len,
|
||||
PWINDIVERT_ADDRESS addr;
|
||||
UINT *addr_len_ptr;
|
||||
NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO checksums;
|
||||
BOOL pseudo_ip_checksum, pseudo_tcp_checksum, pseudo_udp_checksum;
|
||||
BOOL ip_checksum, tcp_checksum, udp_checksum;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
|
||||
// This function bypasses the normal work_queue -> packet_queue flow, but
|
||||
@@ -2184,18 +2184,15 @@ static void windivert_fast_read_service_request(PVOID packet, ULONG packet_len,
|
||||
TcpIpChecksumNetBufferListInfo);
|
||||
if (outbound)
|
||||
{
|
||||
pseudo_ip_checksum = (checksums.Transmit.IpHeaderChecksum != 0);
|
||||
pseudo_tcp_checksum = (checksums.Transmit.TcpChecksum != 0);
|
||||
pseudo_udp_checksum = (checksums.Transmit.UdpChecksum != 0);
|
||||
ip_checksum = (checksums.Transmit.IpHeaderChecksum == 0);
|
||||
tcp_checksum = (checksums.Transmit.TcpChecksum == 0);
|
||||
udp_checksum = (checksums.Transmit.UdpChecksum == 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
pseudo_ip_checksum =
|
||||
(checksums.Receive.IpChecksumSucceeded != 0);
|
||||
pseudo_tcp_checksum =
|
||||
(checksums.Receive.TcpChecksumSucceeded != 0);
|
||||
pseudo_udp_checksum =
|
||||
(checksums.Receive.UdpChecksumSucceeded != 0);
|
||||
ip_checksum = (checksums.Receive.IpChecksumSucceeded == 0);
|
||||
tcp_checksum = (checksums.Receive.TcpChecksumSucceeded == 0);
|
||||
udp_checksum = (checksums.Receive.UdpChecksumSucceeded == 0);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2203,14 +2200,12 @@ static void windivert_fast_read_service_request(PVOID packet, ULONG packet_len,
|
||||
dst_len = (dst_len < packet_len? dst_len: packet_len);
|
||||
RtlCopyMemory(dst, packet, dst_len);
|
||||
read_len = dst_len;
|
||||
pseudo_ip_checksum = pseudo_tcp_checksum = pseudo_udp_checksum =
|
||||
FALSE;
|
||||
ip_checksum = tcp_checksum = udp_checksum = FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
read_len = 0;
|
||||
pseudo_ip_checksum = pseudo_tcp_checksum = pseudo_udp_checksum =
|
||||
FALSE;
|
||||
ip_checksum = tcp_checksum = udp_checksum = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2220,17 +2215,17 @@ static void windivert_fast_read_service_request(PVOID packet, ULONG packet_len,
|
||||
|
||||
if (addr != NULL)
|
||||
{
|
||||
addr->Timestamp = timestamp;
|
||||
addr->Layer = layer;
|
||||
addr->Event = event;
|
||||
addr->Outbound = (outbound? 1: 0);
|
||||
addr->Loopback = (loopback? 1: 0);
|
||||
addr->Impostor = (impostor? 1: 0);
|
||||
addr->IPv6 = (ipv4? 0: 1);
|
||||
addr->PseudoIPChecksum = (pseudo_ip_checksum? 1: 0);
|
||||
addr->PseudoTCPChecksum = (pseudo_tcp_checksum? 1: 0);
|
||||
addr->PseudoUDPChecksum = (pseudo_udp_checksum? 1: 0);
|
||||
addr->Reserved = 0;
|
||||
addr->Timestamp = timestamp;
|
||||
addr->Layer = layer;
|
||||
addr->Event = event;
|
||||
addr->Outbound = (outbound? 1: 0);
|
||||
addr->Loopback = (loopback? 1: 0);
|
||||
addr->Impostor = (impostor? 1: 0);
|
||||
addr->IPv6 = (ipv4? 0: 1);
|
||||
addr->IPChecksum = (ip_checksum? 1: 0);
|
||||
addr->TCPChecksum = (tcp_checksum? 1: 0);
|
||||
addr->UDPChecksum = (udp_checksum? 1: 0);
|
||||
addr->Reserved = 0;
|
||||
switch (layer)
|
||||
{
|
||||
case WINDIVERT_LAYER_NETWORK:
|
||||
@@ -2474,15 +2469,15 @@ windivert_write_too_small_packet:
|
||||
RtlCopyMemory(data_copy, data, packet_len);
|
||||
|
||||
// Fix checksums:
|
||||
if (addr[i].PseudoIPChecksum != 0 || addr[i].PseudoTCPChecksum != 0 ||
|
||||
addr[i].PseudoUDPChecksum != 0)
|
||||
if (addr[i].IPChecksum == 0 || addr[i].TCPChecksum == 0 ||
|
||||
addr[i].UDPChecksum == 0)
|
||||
{
|
||||
checksums =
|
||||
(addr[i].PseudoIPChecksum? 0:
|
||||
(addr[i].IPChecksum == 0? 0:
|
||||
WINDIVERT_HELPER_NO_IP_CHECKSUM) |
|
||||
(addr[i].PseudoTCPChecksum? 0:
|
||||
(addr[i].TCPChecksum == 0? 0:
|
||||
WINDIVERT_HELPER_NO_TCP_CHECKSUM) |
|
||||
(addr[i].PseudoUDPChecksum? 0:
|
||||
(addr[i].UDPChecksum == 0? 0:
|
||||
WINDIVERT_HELPER_NO_UDP_CHECKSUM) |
|
||||
WINDIVERT_HELPER_NO_ICMP_CHECKSUM |
|
||||
WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM;
|
||||
@@ -4276,7 +4271,7 @@ static BOOL windivert_queue_work(context_t context, PVOID packet,
|
||||
PWINDIVERT_DATA_FLOW flow_data;
|
||||
PWINDIVERT_DATA_SOCKET socket_data;
|
||||
PWINDIVERT_DATA_REFLECT reflect_data;
|
||||
BOOL pseudo_ip_checksum, pseudo_tcp_checksum, pseudo_udp_checksum;
|
||||
BOOL ip_checksum, tcp_checksum, udp_checksum;
|
||||
WDFREQUEST request = NULL;
|
||||
NTSTATUS status;
|
||||
|
||||
@@ -4347,18 +4342,15 @@ static BOOL windivert_queue_work(context_t context, PVOID packet,
|
||||
TcpIpChecksumNetBufferListInfo);
|
||||
if (outbound)
|
||||
{
|
||||
pseudo_ip_checksum = (checksums.Transmit.IpHeaderChecksum != 0);
|
||||
pseudo_tcp_checksum = (checksums.Transmit.TcpChecksum != 0);
|
||||
pseudo_udp_checksum = (checksums.Transmit.UdpChecksum != 0);
|
||||
ip_checksum = (checksums.Transmit.IpHeaderChecksum == 0);
|
||||
tcp_checksum = (checksums.Transmit.TcpChecksum == 0);
|
||||
udp_checksum = (checksums.Transmit.UdpChecksum == 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
pseudo_ip_checksum =
|
||||
(checksums.Receive.IpChecksumSucceeded != 0);
|
||||
pseudo_tcp_checksum =
|
||||
(checksums.Receive.TcpChecksumSucceeded != 0);
|
||||
pseudo_udp_checksum =
|
||||
(checksums.Receive.UdpChecksumSucceeded != 0);
|
||||
ip_checksum = (checksums.Receive.IpChecksumSucceeded == 0);
|
||||
tcp_checksum = (checksums.Receive.TcpChecksumSucceeded == 0);
|
||||
udp_checksum = (checksums.Receive.UdpChecksumSucceeded == 0);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -4373,8 +4365,7 @@ static BOOL windivert_queue_work(context_t context, PVOID packet,
|
||||
work->packet_len = 0;
|
||||
data = WINDIVERT_LAYER_DATA_PTR(work);
|
||||
RtlCopyMemory(data, flow_data, sizeof(WINDIVERT_DATA_FLOW));
|
||||
pseudo_ip_checksum = pseudo_tcp_checksum = pseudo_udp_checksum =
|
||||
FALSE;
|
||||
ip_checksum = tcp_checksum = udp_checksum = FALSE;
|
||||
break;
|
||||
|
||||
case WINDIVERT_LAYER_SOCKET:
|
||||
@@ -4388,8 +4379,7 @@ static BOOL windivert_queue_work(context_t context, PVOID packet,
|
||||
work->packet_len = 0;
|
||||
data = WINDIVERT_LAYER_DATA_PTR(work);
|
||||
RtlCopyMemory(data, socket_data, sizeof(WINDIVERT_DATA_SOCKET));
|
||||
pseudo_ip_checksum = pseudo_tcp_checksum = pseudo_udp_checksum =
|
||||
FALSE;
|
||||
ip_checksum = tcp_checksum = udp_checksum = FALSE;
|
||||
break;
|
||||
|
||||
case WINDIVERT_LAYER_REFLECT:
|
||||
@@ -4406,26 +4396,25 @@ static BOOL windivert_queue_work(context_t context, PVOID packet,
|
||||
RtlCopyMemory(data, reflect_data, sizeof(WINDIVERT_DATA_REFLECT));
|
||||
data = WINDIVERT_PACKET_DATA_PTR(WINDIVERT_DATA_REFLECT, work);
|
||||
RtlCopyMemory(data, packet, packet_len);
|
||||
pseudo_ip_checksum = TRUE;
|
||||
pseudo_tcp_checksum = pseudo_udp_checksum = FALSE;
|
||||
ip_checksum = tcp_checksum = udp_checksum = FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
work->layer = layer;
|
||||
work->event = event;
|
||||
work->outbound = (outbound? 1: 0);
|
||||
work->loopback = (loopback? 1: 0);
|
||||
work->impostor = (impostor? 1: 0);
|
||||
work->ipv6 = (!ipv4? 1: 0);
|
||||
work->pseudo_ip_checksum = (pseudo_ip_checksum? 1: 0);
|
||||
work->pseudo_tcp_checksum = (pseudo_tcp_checksum? 1: 0);
|
||||
work->pseudo_udp_checksum = (pseudo_udp_checksum? 1: 0);
|
||||
work->match = match;
|
||||
work->priority = priority;
|
||||
work->timestamp = timestamp;
|
||||
work->layer = layer;
|
||||
work->event = event;
|
||||
work->outbound = (outbound? 1: 0);
|
||||
work->loopback = (loopback? 1: 0);
|
||||
work->impostor = (impostor? 1: 0);
|
||||
work->ipv6 = (!ipv4? 1: 0);
|
||||
work->ip_checksum = (ip_checksum? 1: 0);
|
||||
work->tcp_checksum = (tcp_checksum? 1: 0);
|
||||
work->udp_checksum = (udp_checksum? 1: 0);
|
||||
work->match = match;
|
||||
work->priority = priority;
|
||||
work->timestamp = timestamp;
|
||||
|
||||
old_entry = NULL;
|
||||
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
|
||||
@@ -4561,16 +4550,13 @@ static void windivert_reinject_packet(packet_t packet)
|
||||
packet_len = packet->packet_len;
|
||||
|
||||
// Fix checksums:
|
||||
if (packet->pseudo_ip_checksum != 0 || packet->pseudo_tcp_checksum != 0 ||
|
||||
packet->pseudo_udp_checksum != 0)
|
||||
if (packet->ip_checksum == 0 || packet->tcp_checksum == 0 ||
|
||||
packet->udp_checksum == 0)
|
||||
{
|
||||
checksums =
|
||||
(packet->pseudo_ip_checksum != 0? 0:
|
||||
WINDIVERT_HELPER_NO_IP_CHECKSUM) |
|
||||
(packet->pseudo_tcp_checksum != 0? 0:
|
||||
WINDIVERT_HELPER_NO_TCP_CHECKSUM) |
|
||||
(packet->pseudo_udp_checksum != 0? 0:
|
||||
WINDIVERT_HELPER_NO_UDP_CHECKSUM) |
|
||||
(packet->ip_checksum == 0? 0: WINDIVERT_HELPER_NO_IP_CHECKSUM) |
|
||||
(packet->tcp_checksum == 0? 0: WINDIVERT_HELPER_NO_TCP_CHECKSUM) |
|
||||
(packet->udp_checksum == 0? 0: WINDIVERT_HELPER_NO_UDP_CHECKSUM) |
|
||||
WINDIVERT_HELPER_NO_ICMP_CHECKSUM |
|
||||
WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM;
|
||||
WinDivertHelperCalcChecksums(packet_data, packet_len, NULL, checksums);
|
||||
|
||||
+5
-5
@@ -1061,10 +1061,10 @@ static BOOL run_test(HANDLE inject_handle, const char *filter,
|
||||
|
||||
// (2) Inject the packet:
|
||||
memset(&addr_send, 0, sizeof(addr_send));
|
||||
addr_send.Outbound = TRUE;
|
||||
addr_send.PseudoIPChecksum = TRUE;
|
||||
addr_send.PseudoTCPChecksum = TRUE;
|
||||
addr_send.PseudoUDPChecksum = TRUE;
|
||||
addr_send.Outbound = TRUE;
|
||||
addr_send.IPChecksum = FALSE;
|
||||
addr_send.TCPChecksum = FALSE;
|
||||
addr_send.UDPChecksum = FALSE;
|
||||
if (!WinDivertSend(inject_handle, (PVOID)packet, packet_len, &addr_send,
|
||||
NULL))
|
||||
{
|
||||
@@ -1242,7 +1242,7 @@ static DWORD monitor_worker(LPVOID arg)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
WinDivertHelperParsePacket(packet, packet_len, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, (void **)&object_2, NULL);
|
||||
NULL, NULL, NULL, (void **)&object_2, NULL, NULL, NULL);
|
||||
if (strcmp(object_1, object_2) != 0)
|
||||
{
|
||||
// Filter is not the same.
|
||||
|
||||
Reference in New Issue
Block a user