This allows projects that are strictly "GPLv2
only" to use WinDivert without licensing issues.
See the FSF's compatibility matrix here:
https://www.gnu.org/licenses/gpl-faq.en.html
This change does not affect existing projects
that can continue to use the LGPLv3 as before.
Also, bump the WinDivert version to 1.4.1.
This hardens WinDivert against other drivers that
attempt to modify packets after they were blocked
& absorbed by WinDivert, leading to BSODs. This
is also a fix for issue #110.
WinDivert will now mark any packet injected by
another driver as an "impostor", meaning that it
did not originate from the network. Changes are:
- User programs may filter impostor packets.
- WinDivertSend() automatically decrements the TTL
for imposter packets, see #41.
Most NIC cards support checksum offloading,
meaning that it is not necessary to calculate the
full IP/TCP/UDP checksums for injected packets.
WINDIVERT_ADDRESS has been extended to include 3
extra flags that indicate if the packet has full
or pseudo checksums. This is a WIP.
- A partial fix for #41
- Decrements the TTL for reinjected packets.
- If (TTL==0), WinDivertRecv() will fail with:
ERROR_HOST_UNREACHABLE = 1232
which is better than looping.
- Immediately reinject in SNIFF mode.
- Use a NET_BUFFER pool for cloned packets.
- Fix bug caused by pool mix up for cloned packets.
- Copy NET_BUFFER_LIST info for non-matching packets.
- Keep reference to original NET_BUFFER_LIST after cloning.
(might not be necessary, but some sample drivers do).
This is a major update designed to modernize the WinDivert driver, including
optimizations, design improvements and bug fixes. The new version has not
been fully tested and should be considered **UNSTABLE**.
- Most of the packet processing is now (almost) fully out-of-band. This is a
good since the classify function runs at DISPATCH_LEVEL. The driver will
still try to match at least one packet before moving the work out-of-band.
- Re-injected non-matching packets are now clones rather than copies.
- Queued packets are still copied. This is because the driver should avoid
keeping a reference to the original packet for very long. Since we do not
trust the user application to handle the packet in a timely fashion, it is
better to copy rather than keep a reference. That said, the driver now
implements an optimization where it will service a read request immediately
if possible (saving 1 packet copy).
- SNIFF mode also now works differently. Previously, SNIFF mode would not
block the original packet. However, this is problematic under the new
design since WinDivert cannot permit the packet and retain a reference to it
at the same time. The new version will block & absorb the original packet
and re-inject a clone out-of-band.
- Packet time management has been replaced. Previously, a timer was used to
periodically wake up a function that would sweep away expired packets. The
new version explicitly timestamps every packet, and expired packets are
cleaned up by the read service routine.
- The context->filter is now deallocated in the destroy callback to avoid
possible a race condition with the callout function. It is unclear if this
is really necessary, however.
Currently, WinDivert waits until injection completes before completing the
corresponding IO request. However, packet injection may take an arbitrarily
long time, such as waiting for a user-mode application.
The new version completes the IO request immediately, provided the call to the
corresponding WFP packet injection function did not return an error, thus
eliminating the problem. The disadvantage is that some packet injection
errors may no longer be detected.
on the WinDivert handle, the driver's cleanup function cannot make FWPM
calls. The cleanup function detects this FWPM error and returns
without ever calling the Fwps cleanup functions (which are independent
of fwpm).
As a result, the driver will not unregister the callouts, which leaves
the Windows kernel confused. You can reproduce the problem by having
a user app close uncleanly, then "sc stop windivert1.2", then try to
re-run the app. You'll get "file not found" when StartService() is called.
WinDivert now treats all offloaded checksum fields as zero:
- WinDivertRecv() will zero all offloaded checksum fields.
- Filter matching will treat offloaded fields as zero.
Bump version and change magic numbers to make the driver incompatible with
older versions. Also cleanup some driver checksum code missed by previous
commit.
- As discussed in #37, the WINDIVERT_FLAG_NO_CHECKSUM behavior has become the
default. This means that outbound packets returned by WinDivertRecv() are
no longer guaranteed to have valid checksums, thanks to TCP checksum
offloading by the Windows TCP/IP stack. The checksums can still be
recovered by calling WinDivertHelperCalcChecksums() manually.
- Remove the old WinDivert1.0 legacy API, as nobody should still be using it.