-
Notifications
You must be signed in to change notification settings - Fork 513
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.
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.
WinDivert1.2.Y extends the existing WinDivert filtering language with C-style conditional expressions, i.e.:
(Condition? TrueFilter: FalseFilter)
where Condition
, TrueFilter
and FalseFilte
r 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.
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.