Skip to content

WinDivert 1.2 Upgrade Guide

basil00 edited this page Dec 28, 2015 · 1 revision

WinDivert 1.2 Upgrade Guide

This is a quick guide for developers who wish to upgrade their applications from WinDivert1.1.X to WinDivert1.2.Y.

1 Checksums

WinDivert1.1.X will automatically calculate checksums by default unless explicitly disabled by the WINDIVERT_FLAG_NO_CHECKSUM flag. This was inefficient for many applications that did not bother to set the flag. WinDivert1.2.Y changes the behavior by effectively making the "no checksum" mode the default.

Under the new behavior, checksum fields returned by WinDivertRecv() or WinDivertRecvEx() will either be valid (if already present) or be set to zero (if absent).

If your application already used the WINDIVERT_FLAG_NO_CHECKSUM flag, you can simply remove that flag, e.g.:

HANDLE handle = WinDivertOpen(filter, layer, priority,
    flags | WINDIVERT_FLAG_NO_CHECKSUM);

becomes:

HANDLE handle = WinDivertOpen(filter, layer, priority, flags);

For applications that desire the old behavior, the checksums can be recovered via an explicit call to WinDivertHelperCalcChecksums() as follows:

BOOL res = WinDivertRecv(handle, packet, &packet_len, &addr, &read_len);
if (!res)
{
    // Handle errors
}
WinDivertHelperCalcChecksums(packet, packet_len,
    WINDIVERT_HELPER_NO_REPLACE);

The WINDIVERT_HELPER_NO_REPLACE flag ensures WinDivertHelperCalcChecksums() does not replace non-zero checksum fields that are already valid.

2 New Filter Syntax

WinDivert1.2.Y extends the existing WinDivert filtering language with C-style conditional expressions, i.e.:

(Condition? TrueFilter: FalseFilter)

where Condition, TrueFilter and FalseFilter are themselves filter language expressions. For example, the following filter captures all TCP/UDP traffic with destination port 1000.

(tcp? tcp.DstPort == 1000: udp and udp.DstPort == 1000)

Conditional expressions can also be used for negation:

(Filter? false: true)

Conditional expressions allow for higher-level rule-based style filters that are generally easier to define.

3 New Filter Functions

Passing an invalid filter string to WinDivertOpen() will cause failure with GetLastError() returning ERROR_INVALID_PARAMETER. Under WinDivert1.1.X there was no way to determine the exact cause of the error.

WinDivert1.2.Y introduces a new function, WinDivertHelperCheckFilter(), that can be used to determine the cause of filter string errors more accurately. This can be used for better error messages, e.g.:

BOOL res = WinDivertOpen(filter, layer, ...);
if (!res)
{
    // Handle errors:
    const char *errStr;
    UINT errPos;
    res = WinDivertHelperCheckFilter(filter, layer, &errStr, &errPos);
    if (!res)
    {
        fprintf(stderr, "bad filter string: %s (pos=%u)\n", errStr, errPos);
        exit(EXIT_FAILURE);
    }
    ...
}

For example, if filter=ip and tcp.Port == 80 then the error will be:

bad filter string: Filter expression contains a bad token (pos=7)

The error is that "tcp.Port" is an invalid token (should be tcp.DstPort or tcp.SrcPort)

WinDivert1.2.Y also introduces a WinDivertHelperEvalFilter() that can be used to evaluate a filter on a given packet outside of the driver. This function is mainly intended for debugging purposes.