diff --git a/dll/windivert_helper.c b/dll/windivert_helper.c index 833f79a..84f7d59 100644 --- a/dll/windivert_helper.c +++ b/dll/windivert_helper.c @@ -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; } diff --git a/doc/windivert.html b/doc/windivert.html index 640bef6..d7ff45a 100644 --- a/doc/windivert.html +++ b/doc/windivert.html @@ -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 checksum offloading 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 WinDivertHelperCalcChecksums() @@ -730,6 +730,15 @@ fields are currently ignored and may be arbitrary values. Injecting an inbound packet on the outbound path may work (for some types of packets), however this should be considered "undocumented" behavior, and may be changed in the future. +
+Injected packets should have correct checksums. +Correct checksums can be calculated using the +WinDivertHelperCalcChecksums() +function. +Note that packets returned by +WinDivertRecv() are not +guaranteed to have correct checksums.
@@ -1246,6 +1255,8 @@ UINT WinDivertHelperCalcChecksums( checksum.@@ -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 WinDivertSend().
-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). -
+
+If the WINDIVERT_HELPER_NO_REPLACE 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 +WinDivertRecv(), where +non-zero checksum fields do not need to be recalculated. +