Add a NO_REPLACE for WinDivertHelperCalcChecksums
The WINDIVERT_HELPER_NO_REPLACE flag tells WinDivertHelperCalcChecksums not to recalculate and replace non-zero checksum fields. This is useful for reconstructing the checksums for packets returned by WinDivertRecv(), where all non-zero checksum fields are already valid. This allows WinDivert1.2 to achieve similar efficiency as WinDivert1.1, where checksums were calculated by the driver. Note that for modified packets, the WINDIVERT_HELPER_NO_REPLACE flag should not be used, as all checksums need to be recalculated from scratch anyway.
This commit is contained in:
+21
-6
@@ -423,8 +423,14 @@ extern UINT WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
|
||||
PWINDIVERT_UDPHDR udp_header;
|
||||
UINT payload_len, checksum_len;
|
||||
UINT count = 0;
|
||||
UINT64 flags_all =
|
||||
(WINDIVERT_HELPER_NO_IP_CHECKSUM |
|
||||
WINDIVERT_HELPER_NO_ICMP_CHECKSUM |
|
||||
WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM |
|
||||
WINDIVERT_HELPER_NO_TCP_CHECKSUM |
|
||||
WINDIVERT_HELPER_NO_UDP_CHECKSUM);
|
||||
|
||||
if ((flags & 0x1F) == 0x1F)
|
||||
if ((flags & flags_all) == flags_all)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -433,7 +439,8 @@ extern UINT WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
|
||||
&icmp_header, &icmpv6_header, &tcp_header, &udp_header, NULL,
|
||||
&payload_len);
|
||||
|
||||
if (ip_header != NULL && !(flags & WINDIVERT_HELPER_NO_IP_CHECKSUM))
|
||||
if (ip_header != NULL && !(flags & WINDIVERT_HELPER_NO_IP_CHECKSUM) &&
|
||||
(!(flags & WINDIVERT_HELPER_NO_REPLACE) || ip_header->Checksum == 0))
|
||||
{
|
||||
ip_header->Checksum = 0;
|
||||
ip_header->Checksum = WinDivertHelperCalcChecksum(NULL, 0,
|
||||
@@ -443,7 +450,9 @@ extern UINT WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
|
||||
|
||||
if (icmp_header != NULL)
|
||||
{
|
||||
if (flags & WINDIVERT_HELPER_NO_ICMP_CHECKSUM)
|
||||
if ((flags & WINDIVERT_HELPER_NO_ICMP_CHECKSUM) ||
|
||||
((flags & WINDIVERT_HELPER_NO_REPLACE) &&
|
||||
icmp_header->Checksum != 0))
|
||||
{
|
||||
return count;
|
||||
}
|
||||
@@ -456,7 +465,9 @@ extern UINT WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
|
||||
|
||||
if (icmpv6_header != NULL)
|
||||
{
|
||||
if (flags & WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM)
|
||||
if ((flags & WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM) ||
|
||||
((flags & WINDIVERT_HELPER_NO_REPLACE) &&
|
||||
icmpv6_header->Checksum != 0))
|
||||
{
|
||||
return count;
|
||||
}
|
||||
@@ -472,7 +483,9 @@ extern UINT WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
|
||||
|
||||
if (tcp_header != NULL)
|
||||
{
|
||||
if (flags & WINDIVERT_HELPER_NO_TCP_CHECKSUM)
|
||||
if ((flags & WINDIVERT_HELPER_NO_TCP_CHECKSUM) ||
|
||||
((flags & WINDIVERT_HELPER_NO_REPLACE) &&
|
||||
tcp_header->Checksum != 0))
|
||||
{
|
||||
return count;
|
||||
}
|
||||
@@ -499,7 +512,9 @@ extern UINT WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
|
||||
|
||||
if (udp_header != NULL)
|
||||
{
|
||||
if (flags & WINDIVERT_HELPER_NO_UDP_CHECKSUM)
|
||||
if ((flags & WINDIVERT_HELPER_NO_UDP_CHECKSUM) ||
|
||||
((flags & WINDIVERT_HELPER_NO_REPLACE) &&
|
||||
udp_header->Checksum != 0))
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
+22
-4
@@ -614,7 +614,7 @@ WinDivert sometimes captures outbound or loopback packets before the
|
||||
IP/TCP/UDP checksum fields have been calculated.
|
||||
For outbound packets, this occurs when <i>checksum offloading</i> is enabled,
|
||||
which defers checksum calculation to a compatible NIC card.
|
||||
If the checksum is absent the corresponding
|
||||
If the checksum is absent then the corresponding
|
||||
checksum field will be set to zero.
|
||||
Correct checksums can be reconstructed using the
|
||||
<a href="#divert_helper_calc_checksums"><tt>WinDivertHelperCalcChecksums()</tt></a>
|
||||
@@ -730,6 +730,15 @@ fields are currently ignored and may be arbitrary values.
|
||||
Injecting an inbound packet on the outbound path <i>may</i> work (for some
|
||||
types of packets), however this should be considered "undocumented" behavior,
|
||||
and may be changed in the future.
|
||||
</p><p>
|
||||
Injected packets should have correct checksums.
|
||||
Correct checksums can be calculated using the
|
||||
<a
|
||||
href="#divert_helper_calc_checksums"><tt>WinDivertHelperCalcChecksums()</tt></a>
|
||||
function.
|
||||
Note that packets returned by
|
||||
<a href="#divert_recv"><tt>WinDivertRecv()</tt></a> are not
|
||||
guaranteed to have correct checksums.
|
||||
</p>
|
||||
</dd></dl>
|
||||
|
||||
@@ -1246,6 +1255,8 @@ UINT <b>WinDivertHelperCalcChecksums</b>(
|
||||
checksum.</li>
|
||||
<li> <tt>WINDIVERT_HELPER_NO_UDP_CHECKSUM</tt>: Do not calculate the UDP
|
||||
checksum.</li>
|
||||
<li> <tt>WINDIVERT_HELPER_NO_REPLACE</tt>: Do not replace non-zero
|
||||
checksums.</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</p><p>
|
||||
@@ -1259,12 +1270,19 @@ Individual checksum calculations may be disabled via the appropriate flag.
|
||||
Typically this function should be invoked on a modified packet before it is
|
||||
injected with <a href="#divert_send"><tt>WinDivertSend()</tt></a>.
|
||||
</p><p>
|
||||
This function will calculate each checksum from scratch, even if the existing
|
||||
checksum is correct.
|
||||
By default this function will calculate each checksum from scratch, even if
|
||||
the existing checksum is correct.
|
||||
This may be inefficient for some applications.
|
||||
For better performance, incremental checksum calculations should be used
|
||||
instead (not provided by this API).
|
||||
<p>
|
||||
</p><p>
|
||||
If the <tt>WINDIVERT_HELPER_NO_REPLACE</tt> flag is used, this function will
|
||||
assume that all non-zero checksum fields are already valid and will not
|
||||
replace them.
|
||||
This is useful for reconstructing checksums for packets returned by
|
||||
<a href="#divert_recv"><tt>WinDivertRecv()</tt></a>, where
|
||||
non-zero checksum fields do not need to be recalculated.
|
||||
</p>
|
||||
</dd></dl>
|
||||
|
||||
<a name="divert_helper_check_filter"><h3>6.11 WinDivertHelperCheckFilter</h3></a>
|
||||
|
||||
@@ -118,11 +118,9 @@ int __cdecl main(int argc, char **argv)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Calculate checksums for outbound packets.
|
||||
if (addr.Direction == WINDIVERT_DIRECTION_OUTBOUND)
|
||||
{
|
||||
WinDivertHelperCalcChecksums(packet, packet_len, 0);
|
||||
}
|
||||
// Calculate checksums.
|
||||
WinDivertHelperCalcChecksums(packet, packet_len,
|
||||
WINDIVERT_HELPER_NO_REPLACE);
|
||||
|
||||
// Print info about the matching packet.
|
||||
WinDivertHelperParsePacket(packet, packet_len, &ip_header,
|
||||
|
||||
@@ -107,14 +107,11 @@ static DWORD passthru(LPVOID arg)
|
||||
continue;
|
||||
}
|
||||
|
||||
// NOTE: Since WinDivert1.2 outbound packets are not guaranteed
|
||||
// to have correct checksums.
|
||||
if (addr.Direction == WINDIVERT_DIRECTION_OUTBOUND)
|
||||
{
|
||||
WinDivertHelperCalcChecksums(packet, packet_len, 0);
|
||||
}
|
||||
|
||||
// Re-inject the matching packet.
|
||||
// NOTE: Only use the WINDIVERT_HELPER_NO_REPLACE flag if the packet
|
||||
// was not modified.
|
||||
WinDivertHelperCalcChecksums(packet, packet_len,
|
||||
WINDIVERT_HELPER_NO_REPLACE);
|
||||
if (!WinDivertSend(handle, packet, packet_len, &addr, NULL))
|
||||
{
|
||||
fprintf(stderr, "warning: failed to reinject packet (%d)\n",
|
||||
|
||||
@@ -188,7 +188,8 @@ int __cdecl main(int argc, char **argv)
|
||||
!BlackListPayloadMatch(blacklist, payload, (UINT16)payload_len))
|
||||
{
|
||||
// Packet does not match the blacklist; simply reinject it.
|
||||
WinDivertHelperCalcChecksums(packet, packet_len, 0);
|
||||
WinDivertHelperCalcChecksums(packet, packet_len,
|
||||
WINDIVERT_HELPER_NO_REPLACE);
|
||||
if (!WinDivertSend(handle, packet, packet_len, &addr, NULL))
|
||||
{
|
||||
fprintf(stderr, "warning: failed to reinject packet (%d)\n",
|
||||
|
||||
@@ -313,6 +313,7 @@ typedef struct
|
||||
#define WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM 4
|
||||
#define WINDIVERT_HELPER_NO_TCP_CHECKSUM 8
|
||||
#define WINDIVERT_HELPER_NO_UDP_CHECKSUM 16
|
||||
#define WINDIVERT_HELPER_NO_REPLACE 2048
|
||||
|
||||
/*
|
||||
* Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet.
|
||||
|
||||
Reference in New Issue
Block a user