diff --git a/doc/windivert.html b/doc/windivert.html index 0dc3610..832067b 100644 --- a/doc/windivert.html +++ b/doc/windivert.html @@ -1,20 +1,22 @@ - + WinDivert 2.0 Documentation +

WinDivert 2.0: Windows Packet Divert

Table of Contents

-The WINDIVERT_LAYER_NETWORK (and -WINDIVERT_LAYER_NETWORK_FORWARD) layers +The WINDIVERT_LAYER_NETWORK (and +WINDIVERT_LAYER_NETWORK_FORWARD) layers allow the user application to capture/block/inject network packets passing to/from (and through) the local machine. These represent the traditional @@ -361,22 +368,22 @@ WinDivert layers. Only a single event is supported:

Due to technical limitations, process ID information is not available at these layers.

-The WINDIVERT_LAYER_FLOW layer captures information about +The WINDIVERT_LAYER_FLOW layer captures information about network flow establishment/deletion events. Here, a flow represents either (1) a TCP connection, or (2) an implicit flow created by the first sent/received packet for non-TCP traffic, e.g., UDP. -The WINDIVERT_LAYER_FLOW layer supports two events: +The WINDIVERT_LAYER_FLOW layer supports two events:

Old flows are deleted when the corresponding connection is closed (for TCP), @@ -384,36 +391,36 @@ or on a timeout (non-TCP). Flow events can be captured, but never blocked or injected. Process ID information is available at this layer. Due to technical limitations, the -WINDIVERT_LAYER_FLOW layer cannot capture events that +WINDIVERT_LAYER_FLOW layer cannot capture events that occurred before the WinDivert handle was opened.

-The WINDIVERT_LAYER_SOCKET layer captures/blocks events that +The WINDIVERT_LAYER_SOCKET layer captures/blocks events that correspond to socket operations, such as:

Socket events can be blocked but not injected. Process ID information is available at this layer. Due to technical limitations, the -WINDIVERT_LAYER_SOCKET layer cannot capture events that +WINDIVERT_LAYER_SOCKET layer cannot capture events that occurred before the WinDivert handle was opened.

-Finally, the WINDIVERT_LAYER_REFLECT layer captures events related +Finally, the WINDIVERT_LAYER_REFLECT layer captures events related to WinDivert itself, such as:

@@ -423,7 +430,7 @@ meaning that it is possible to determine which (if any) process is using WinDivert. The layer also returns a pseudo packet that encodes the filter string associated with the event. -The WINDIVERT_LAYER_REFLECT layer can also capture events that +The WINDIVERT_LAYER_REFLECT layer can also capture events that occurred before the handle was opened.

@@ -475,9 +482,9 @@ typedef struct UINT64 Loopback:1; UINT64 Impostor:1; UINT64 IPv6:1; - UINT64 PseudoIPChecksum:1; - UINT64 PseudoTCPChecksum:1; - UINT64 PseudoUDPChecksum:1; + UINT64 IPChecksum:1; + UINT64 TCPChecksum:1; + UINT64 UDPChecksum:1; union { WINDIVERT_DATA_NETWORK Network; @@ -489,80 +496,79 @@ typedef struct
-

-Fields +

Fields

-

+

Remarks
-The WINDIVERT_ADDRESS structure +The WINDIVERT_ADDRESS structure represents the "address" of a captured or injected packet. The address includes the packet's timestamp, layer, event, flags, and layer-specific data. -All fields are set by WinDivertRecv() +All fields are set by WinDivertRecv() when the packet/event is captured. Only some fields are used by -WinDivertSend() when a packet +WinDivertSend() when a packet is injected.

-The Timestamp indicates when the packet/event was first +The Timestamp indicates when the packet/event was first captured by WinDivert. It uses the same clock as -QueryPerformanceCounter(). +QueryPerformanceCounter().

-The Layer indicates the layer parameter -(WINDIVERT_LAYER_*) that was passed to -WinDivertOpen(). +The Layer indicates the layer parameter +(WINDIVERT_LAYER_*) that was passed to +WinDivertOpen(). It is included in the address to make the structure self-contained.

-The Event indicates the layer-specific event -(WINDIVERT_EVENT_*) that was captured. +The Event indicates the layer-specific event +(WINDIVERT_EVENT_*) that was captured.

-The Outbound flag is set for outbound +The Outbound flag is set for outbound packets/events, and is cleared for inbound or direction-less packets/events.

-The Loopback flag is set for loopback packets. +The Loopback flag is set for loopback packets. Note that Windows considers any packet originating from, and destined to, the current machine to be a loopback packet, so loopback packets are not limited to localhost addresses. @@ -570,82 +576,80 @@ Note that WinDivert considers loopback packets to be outbound only, and will not capture loopback packets on the inbound path.

-The Impostor flag is set for impostor packets. +The Impostor flag is set for impostor packets. An impostor packet is any packet injected by another driver rather than originating from the network or Windows TCP/IP stack. Impostor packets are problematic since they can cause infinite loops, -where a packet injected by WinDivertSend() -is captured again by WinDivertRecv(). -For more information, see WinDivertSend(). +where a packet injected by WinDivertSend() +is captured again by WinDivertRecv(). +For more information, see WinDivertSend().

-The IPv6 flag is set for IPv6 packets/events, and cleared +The IPv6 flag is set for IPv6 packets/events, and cleared for IPv4 packets/events.

-The Pseudo*Checksum flags indicate whether the packet uses -full or pseudo checksums. -Pseudo checksums are used when -IP/TCP/UDP checksum offloading is enabled, meaning that the network -hardware calculates/validates checksums rather than the Windows TCP/IP stack. -Pseudo checksums may be arbitrary values. -Typically, modified packets should preserve the Pseudo*Checksum flags. +The *Checksum flags indicate whether the packet has valid checksums +or not. +When IP/TCP/UDP checksum offloading is enabled, it is possible that +captured packets do not have valid checksums. +Invalid checksums may be arbitrary values.

-The Network.* fields are only valid at the -WINDIVERT_LAYER_NETWORK and -WINDIVERT_LAYER_NETWORK_FORWARD layers. -The Network.IfIdx/Network.SubIfIdx indicate the packet's +The Network.* fields are only valid at the +WINDIVERT_LAYER_NETWORK and +WINDIVERT_LAYER_NETWORK_FORWARD layers. +The Network.IfIdx/Network.SubIfIdx indicate the packet's network adapter (a.k.a. interface) index. These values are ignored for outbound packets.

-The Flow.* fields are only valid at the -WINDIVERT_LAYER_FLOW layer. -The Flow.ProcessId is the ID of the process that +The Flow.* fields are only valid at the +WINDIVERT_LAYER_FLOW layer. +The Flow.ProcessId is the ID of the process that created the flow (for outbound), or receives the flow (for inbound). The -(Flow.LocalAddr, Flow.LocalPort, - Flow.RemoteAddr, Flow.RemotePort, Flow.Protocol) +(Flow.LocalAddr, Flow.LocalPort, + Flow.RemoteAddr, Flow.RemotePort, Flow.Protocol) fields form the network 5-tuple associated with the flow. -For IPv4, the Flow.LocalAddr and Flow.RemoteAddr +For IPv4, the Flow.LocalAddr and Flow.RemoteAddr fields will be IPv4-mapped IPv6 addresses, -e.g. the IPv4 address X.Y.Z.W will be represented by -::ffff:X.Y.Z.W. +e.g. the IPv4 address X.Y.Z.W will be represented by +::ffff:X.Y.Z.W.

-The Socket.* fields are only valid at the -WINDIVERT_LAYER_SOCKET layer. -The Socket.ProcessId is the ID of the process that executed +The Socket.* fields are only valid at the +WINDIVERT_LAYER_SOCKET layer. +The Socket.ProcessId is the ID of the process that executed the socket operation. The -(Socket.LocalAddr, Socket.LocalPort, - Socket.RemoteAddr, Socket.RemotePort, - Socket.Protocol) +(Socket.LocalAddr, Socket.LocalPort, + Socket.RemoteAddr, Socket.RemotePort, + Socket.Protocol) fields form the network 5-tuple associated with the operation. -For IPv4, the Socket.LocalAddr and Socket.RemoteAddr +For IPv4, the Socket.LocalAddr and Socket.RemoteAddr fields will be IPv4-mapped IPv6 addresses. -The WINDIVERT_EVENT_SOCKET_BIND and -WINDIVERT_EVENT_SOCKET_LISTEN events will occur before a +The WINDIVERT_EVENT_SOCKET_BIND and +WINDIVERT_EVENT_SOCKET_LISTEN events will occur before a connection attempt has been made, meaning that the -Socket.RemoteAddr and Socket.RemotePort fields +Socket.RemoteAddr and Socket.RemotePort fields for these events will be zero.

-The Reflect.* fields are only valid at the -WINDIVERT_LAYER_REFLECT layer. -The Reflect.ProcessId is the ID of the process that +The Reflect.* fields are only valid at the +WINDIVERT_LAYER_REFLECT layer. +The Reflect.ProcessId is the ID of the process that opened the WinDivert handle. -The Reflect.Timestamp field is a timestamp indicating when the +The Reflect.Timestamp field is a timestamp indicating when the handle was opened, using the same clock as -QueryPerformanceCounter(). -The Reflect.Layer, Reflect.Flags, and - Reflect.Priority fields correspond to the -WinDivertOpen() parameters of +QueryPerformanceCounter(). +The Reflect.Layer, Reflect.Flags, and + Reflect.Priority fields correspond to the +WinDivertOpen() parameters of the opened handle.

Most address fields are ignored by -WinDivertSend(). +WinDivertSend(). The exceptions are -Outbound (for WINDIVERT_LAYER_NETWORK only), -Impostor, PseudoIPChecksum, PseudoTCPChecksum, -PseudoUDPChecksum, Network.IfIdx and -Network.SubIfIdx. +Outbound (for WINDIVERT_LAYER_NETWORK only), +Impostor, IPChecksum, TCPChecksum, +UDPChecksum, Network.IfIdx and +Network.SubIfIdx.

@@ -661,21 +665,21 @@ HANDLE WinDivertOpen(
-

-Parameters
+

Parameters

-

+

Return Value
A valid WinDivert handle on success, or -INVALID_HANDLE_VALUE if an error occurred. -Use GetLastError() to get the reason for the error. +INVALID_HANDLE_VALUE if an error occurred. +Use GetLastError() to get the reason for the error. Common errors include: +

@@ -691,20 +695,20 @@ Description
-ERROR_FILE_NOT_FOUND +ERROR_FILE_NOT_FOUND 2 The driver files -WinDivert32.sys or WinDivert64.sys +WinDivert32.sys or WinDivert64.sys were not found.
-ERROR_ACCESS_DENIED +ERROR_ACCESS_DENIED 5 @@ -715,7 +719,7 @@ The calling application does not have Administrator privileges.
-ERROR_INVALID_PARAMETER +ERROR_INVALID_PARAMETER 87 @@ -726,32 +730,32 @@ This indicates an invalid packet filter string, layer, priority, or flags.
-ERROR_INVALID_IMAGE_HASH +ERROR_INVALID_IMAGE_HASH 577 -The WinDivert32.sys or WinDivert64.sys driver does not +The WinDivert32.sys or WinDivert64.sys driver does not have a valid digital signature (see the driver signing requirements above).
-ERROR_SERVICE_DOES_NOT_EXIST +ERROR_SERVICE_DOES_NOT_EXIST 1060 -The handle was opened with the WINDIVERT_FLAG_NO_INSTALL flag and +The handle was opened with the WINDIVERT_FLAG_NO_INSTALL flag and the WinDivert driver is not already installed.
-ERROR_DRIVER_BLOCKED +ERROR_DRIVER_BLOCKED 1275 @@ -767,7 +771,7 @@ drivers.
-EPT_S_NOT_REGISTERED +EPT_S_NOT_REGISTERED 1753 @@ -779,13 +783,13 @@ disabled.
-

+

Remarks
Opens a WinDivert handle for the given filter. -Unless otherwise specified by flags, any packet or event that +Unless otherwise specified by flags, any packet or event that matches the filter will be diverted to the handle. Diverted packets/events can be read by the application with -WinDivertRecv(). +WinDivertRecv().

A typical application is only interested in a subset of all network traffic @@ -798,9 +802,9 @@ See the filter language section for more information.

-The layer of the WinDivert handle is determined by the layer +The layer of the WinDivert handle is determined by the layer parameter. -See WINDIVERT_LAYER for more +See WINDIVERT_LAYER for more information. Currently the following layers are supported:

@@ -816,7 +820,7 @@ Description -WINDIVERT_LAYER_NETWORK = 0 +WINDIVERT_LAYER_NETWORK = 0 Network packets to/from the local machine. @@ -825,7 +829,7 @@ This is the default layer. -WINDIVERT_LAYER_NETWORK_FORWARD +WINDIVERT_LAYER_NETWORK_FORWARD Network packets passing through the local machine. @@ -833,7 +837,7 @@ Network packets passing through the local machine. -WINDIVERT_LAYER_FLOW +WINDIVERT_LAYER_FLOW Network flow established/deleted events. @@ -841,7 +845,7 @@ Network flow established/deleted events. -WINDIVERT_LAYER_SOCKET +WINDIVERT_LAYER_SOCKET Socket operation events. @@ -849,7 +853,7 @@ Socket operation events. -WINDIVERT_LAYER_REFLECT +WINDIVERT_LAYER_REFLECT WinDivert handle events. @@ -859,7 +863,7 @@ WinDivert handle events.

Different WinDivert handles can be assigned different priorities by the -priority parameter. +priority parameter. Packets are diverted to higher priority handles before lower priority handles. Packets injected by a handle are then diverted to the next priority handle, @@ -867,9 +871,10 @@ and so on, provided the packet matches the handle's filter. A packet is only diverted once per priority level, so handles should not share priority levels unless they use mutually exclusive filters. Otherwise it is not defined which handle will receive the packet first. -Lower priority values represent higher priorities, with --30000 being the highest priority, 0 the middle -(and a good default) priority, and 30000 the lowest priority. +Lower priority values represent higher priorities, with +WINDIVERT_PRIORITY_HIGHEST being the highest priority, +0 the middle (and a good default) priority, +and WINDIVERT_PRIORITY_LOWEST the lowest priority.

Different flags affect how the opened handle behaves. @@ -887,23 +892,23 @@ Description -WINDIVERT_FLAG_SNIFF +WINDIVERT_FLAG_SNIFF This flag opens the WinDivert handle in packet sniffing mode. In packet sniffing mode the original packet is not dropped-and-diverted (the default) but copied-and-diverted. This mode is useful for implementing packet sniffing tools similar to those -applications that currently use Winpcap. +applications that currently use Winpcap. -WINDIVERT_FLAG_DROP +WINDIVERT_FLAG_DROP This flag indicates that the user application does not intend to read matching -packets with WinDivertRecv(), instead the +packets with WinDivertRecv(), instead the packets should be silently dropped. This is useful for implementing simple packet filters using the WinDivert filter language. @@ -911,75 +916,76 @@ WinDivert filter language. -WINDIVERT_FLAG_RECV_ONLY +WINDIVERT_FLAG_RECV_ONLY This flags forces the handle into receive only mode which effectively -disables WinDivertSend(). +disables WinDivertSend(). This means that it is possible to block/capture packets or events but not inject them. -WINDIVERT_FLAG_READ_ONLY +WINDIVERT_FLAG_READ_ONLY -An alias for WINDIVERT_FLAG_RECV_ONLY. +An alias for WINDIVERT_FLAG_RECV_ONLY. -WINDIVERT_FLAG_SEND_ONLY +WINDIVERT_FLAG_SEND_ONLY This flags forces the handle into send only mode which effectively -disables WinDivertRecv(). +disables WinDivertRecv(). This means that it is possible to inject packets or events, but not block/capture them. -WINDIVERT_FLAG_WRITE_ONLY +WINDIVERT_FLAG_WRITE_ONLY -An alias for WINDIVERT_FLAG_SEND_ONLY. +An alias for WINDIVERT_FLAG_SEND_ONLY. -WINDIVERT_FLAG_RECV_PARTIAL +WINDIVERT_FLAG_RECV_PARTIAL This flags enables partial receives. By default, if a packet is too big for the buffer passed to -WinDivertRecv(), the operation -will fail with ERROR_INSUFFICIENT_BUFFER. +WinDivertRecv(), the operation +will fail with ERROR_INSUFFICIENT_BUFFER. This flag silences this error and only copies part of the packet up to the buffer size. -The WINDIVERT_FLAG_RECV_PARTIAL behavior was the default +The WINDIVERT_FLAG_RECV_PARTIAL behavior was the default on older (pre-2.0) versions of WinDivert. + -WINDIVERT_FLAG_NO_INSTALL +WINDIVERT_FLAG_NO_INSTALL -This flags causes WinDivertOpen() to fail with -ERROR_SERVICE_DOES_NOT_EXIST if the WinDivert driver +This flags causes WinDivertOpen() to fail with +ERROR_SERVICE_DOES_NOT_EXIST if the WinDivert driver is not already installed. This flag is useful for querying the WinDivert state using a -WINDIVERT_LAYER_REFLECT handle. +WINDIVERT_LAYER_REFLECT handle.

Note that any combination of -(WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_DROP) or -(WINDIVERT_FLAG_RECV_ONLY | WINDIVERT_FLAG_SEND_ONLY) or -(WINDIVERT_FLAG_RECV_PARTIAL | WINDIVERT_FLAG_SEND_ONLY) +(WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_DROP) or +(WINDIVERT_FLAG_RECV_ONLY | WINDIVERT_FLAG_SEND_ONLY) or +(WINDIVERT_FLAG_RECV_PARTIAL | WINDIVERT_FLAG_SEND_ONLY) are considered invalid.

@@ -997,26 +1003,26 @@ Required Flags -WINDIVERT_LAYER_FLOW +WINDIVERT_LAYER_FLOW -WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_RECV_ONLY +WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_RECV_ONLY -WINDIVERT_LAYER_SOCKET +WINDIVERT_LAYER_SOCKET -WINDIVERT_FLAG_RECV_ONLY +WINDIVERT_FLAG_RECV_ONLY -WINDIVERT_LAYER_REFLECT +WINDIVERT_LAYER_REFLECT -WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_RECV_ONLY +WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_RECV_ONLY @@ -1036,23 +1042,22 @@ BOOL WinDivertRecv(

-

-Parameters
+

Parameters

    -
  • handle: A valid WinDivert handle created by - WinDivertOpen().
  • -
  • pPacket: An optional buffer for the captured packet.
  • -
  • packetLen: The length of the pPacket buffer.
  • -
  • pAddr: An optional buffer for the +
  • handle: A valid WinDivert handle created by + WinDivertOpen().
  • +
  • pPacket: An optional buffer for the captured packet.
  • +
  • packetLen: The length of the pPacket buffer.
  • +
  • pAddr: An optional buffer for the address of the captured packet/event.
  • -
  • recvLen: The total number of bytes written to pPacket. - Can be NULL if this information is not required.
  • +
  • recvLen: The total number of bytes written to pPacket. + Can be NULL if this information is not required.
-

+

Return Value
-TRUE if a packet/event was successfully received, or FALSE if +TRUE if a packet/event was successfully received, or FALSE if an error occurred. -Use GetLastError() to get the reason for the error. +Use GetLastError() to get the reason for the error.

Common errors include:

@@ -1071,33 +1076,34 @@ Description -ERROR_INSUFFICIENT_BUFFER +ERROR_INSUFFICIENT_BUFFER 122 -The captured packet is larger than the pPacket buffer. +The captured packet is larger than the pPacket buffer. -ERROR_NO_DATA +ERROR_NO_DATA 232 -The handle has been shutdown using -WinDivertShutdown() +The handle has been shutdown using +WinDivertShutdown() and the packet queue is empty. +

Remarks
Receives a single captured packet/event matching the filter passed to -WinDivertOpen(). +WinDivertOpen(). The received packet/event is guaranteed to match the filter.

Only some layers can capture packet data, as @@ -1115,7 +1121,7 @@ Data? -WINDIVERT_LAYER_NETWORK +WINDIVERT_LAYER_NETWORK ✔ @@ -1123,7 +1129,7 @@ Data? -WINDIVERT_LAYER_NETWORK_FORWARD +WINDIVERT_LAYER_NETWORK_FORWARD ✔ @@ -1131,21 +1137,21 @@ Data? -WINDIVERT_LAYER_FLOW +WINDIVERT_LAYER_FLOW -WINDIVERT_LAYER_SOCKET +WINDIVERT_LAYER_SOCKET -WINDIVERT_LAYER_REFLECT +WINDIVERT_LAYER_REFLECT ✔ @@ -1155,37 +1161,37 @@ Data?

For layers that do support capturing, the captured packet will be written to -the pPacket buffer. -If non-NULL, then the total number of bytes -written to pPacket will be written to recvLen. +the pPacket buffer. +If non-NULL, then the total number of bytes +written to pPacket will be written to recvLen. Partial receives (where the packet data is truncated) is supported provided -the handle was opened with the WINDIVERT_FLAG_RECV_PARTIAL flag set, -otherwise the operation will fail with ERROR_INSUFFICIENT_BUFFER -if the pPacket buffer is too small. -For layers that do not capture packets, the pPacket parameter -should be NULL and packetLen should be zero. +the handle was opened with the WINDIVERT_FLAG_RECV_PARTIAL flag set, +otherwise the operation will fail with ERROR_INSUFFICIENT_BUFFER +if the pPacket buffer is too small. +For layers that do not capture packets, the pPacket parameter +should be NULL and packetLen should be zero.

-If non-NULL, the address of the -packet/event will be written to the pAddr buffer. +If non-NULL, the address of the +packet/event will be written to the pAddr buffer.

-An application should call WinDivertRecv() +An application should call WinDivertRecv() as soon as possible -after a successful call to WinDivertOpen(). +after a successful call to WinDivertOpen(). When a WinDivert handle is open, any packet/event that matches the filter will be captured and queued until handled by -WinDivertRecv(). +WinDivertRecv(). Packets/events are not queued indefinitely, and if not handled in a timely manner, data may be lost. The amount of time a packet/event is queued can be controlled using the -WinDivertSetParam() function. +WinDivertSetParam() function.

Captured packets are guaranteed to have correct checksums or have the corresponding -Pseudo*Checksum flag set -(see WINDIVERT_ADDRESS). +*Checksum flag unset +(see WINDIVERT_ADDRESS).

-WinDivertRecv() should not be used on any -WinDivert handle created with the WINDIVERT_FLAG_DROP set. +WinDivertRecv() should not be used on any +WinDivert handle created with the WINDIVERT_FLAG_DROP set.

@@ -1205,59 +1211,62 @@ BOOL WinDivertRecvEx(
-

-Parameters
+

Parameters

    -
  • handle: A valid WinDivert handle created by - WinDivertOpen().
  • -
  • pPacket: A buffer for the captured packet(s).
  • -
  • packetLen: The length of the pPacket buffer in +
  • handle: A valid WinDivert handle created by + WinDivertOpen().
  • +
  • pPacket: A buffer for the captured packet(s).
  • +
  • packetLen: The length of the pPacket buffer in bytes.
  • -
  • recvLen: The total number of bytes written to pPacket. - Can be NULL if this information is not required.
  • -
  • flags: Reserved, set to zero.
  • -
  • pAddr: The - WINDIVERT_ADDRESS of the captured +
  • recvLen: The total number of bytes written to pPacket. + Can be NULL if this information is not required.
  • +
  • flags: Reserved, set to zero.
  • +
  • pAddr: The + WINDIVERT_ADDRESS of the captured packet(s).
  • -
  • pAddrLen: Initially, a pointer to the length of the - pAddr buffer in bytes. - This value is updated to the total bytes written to pAddr. - If NULL, a fixed length of sizeof(WINDIVERT_ADDRESS) is +
  • pAddrLen: Initially, a pointer to the length of the + pAddr buffer in bytes. + This value is updated to the total bytes written to pAddr. + If NULL, a fixed length of sizeof(WINDIVERT_ADDRESS) is assumed.
  • -
  • lpOverlapped: An optional pointer to a OVERLAPPED +
  • lpOverlapped: An optional pointer to a OVERLAPPED structure.
-

+

Return Value
-TRUE if a packet was successfully received, or FALSE +TRUE if a packet was successfully received, or FALSE otherwise. -Use GetLastError() to get the reason. -The error code ERROR_IO_PENDING indicates that the overlapped +Use GetLastError() to get the reason. +The error code ERROR_IO_PENDING indicates that the overlapped operation has been successfully initiated and that completion will be indicated at a later time. All other codes indicate an error.

Remarks
This function is equivalent to -WinDivertRecv() except: +WinDivertRecv() except:

    -
  • Overlapped I/O is supported via the lpOverlapped +
  • Overlapped I/O is supported via the lpOverlapped parameter.
  • Batched I/O (i.e., receiving multiple packets at once) is supported.

-Batched I/O makes it possible to receive multiple packets at once using a -single operation, reducing the number of kernel/user-mode context switches -and improving performance. -To enable batched I/O, -(1) pass an array of more than one WINDIVERT_ADDRESS - to pAddr, -(2) set pAddrLen to be the size (in bytes) of the pAddr - buffer, and -(3) ensure that pPacket points to a sufficiently large buffer - capable of receiving multiple packets. +Batched I/O makes it possible to receive up to WINDIVERT_BATCH_MAX +packets at once using a single operation, reducing the number of +kernel/user-mode context switches and improving performance. +To enable batched I/O: +

+
    +
  1. pass an array of more than one WINDIVERT_ADDRESS + to pAddr;
  2. +
  3. set pAddrLen to be the total size (in bytes) of the + pAddr buffer; and
  4. +
  5. ensure that pPacket points to a sufficiently large buffer + capable of receiving multiple packets.
  6. +
+

For example:

@@ -1267,13 +1276,13 @@ For example:
     BOOL result = WinDivertRecvEx(handle, packets, ..., addr, &addr_len, ...);
 

-When the operation completes, the value pointed to by pAddrLen +upon successful completion, the value pointed to by pAddrLen is updated to the total number of address bytes actually received. -For example, if a total of 5 packets were received, then -the value pointed to by pAddrLen will be set to -(5*sizeof(WINDIVERT_ADDRESS)). -The received packets are packed contiguously into the pPacket -buffer. +For example, if a total of 5 packets were received, then +the value pointed to by pAddrLen will be set to +(5*sizeof(WINDIVERT_ADDRESS)). +The received packets are packed contiguously (i.e., no gaps) into the +pPacket buffer.

5.6 WinDivertSend

@@ -1289,23 +1298,22 @@ BOOL WinDivertSend(
-

-Parameters
+

Parameters

    -
  • handle: A valid WinDivert handle created by - WinDivertOpen().
  • -
  • pPacket: A buffer containing a packet to be injected.
  • -
  • packetLen: The total length of the pPacket buffer.
  • -
  • pAddr: The +
  • handle: A valid WinDivert handle created by + WinDivertOpen().
  • +
  • pPacket: A buffer containing a packet to be injected.
  • +
  • packetLen: The total length of the pPacket buffer.
  • +
  • pAddr: The address of the injected packet.
  • -
  • sendLen: The total number of bytes injected. - Can be NULL if this information is not required.
  • +
  • sendLen: The total number of bytes injected. + Can be NULL if this information is not required.
-

+

Return Value
-TRUE if a packet was successfully injected, or FALSE if +TRUE if a packet was successfully injected, or FALSE if an error occurred. -Use GetLastError() to get the reason for the error. +Use GetLastError() to get the reason for the error.

Common errors include:

@@ -1324,15 +1332,15 @@ Description -ERROR_HOST_UNREACHABLE +ERROR_HOST_UNREACHABLE 1232 This error occurs when an impostor packet (with -pAddr->Impostor set to 1) is injected and the -ip.TTL or ipv6.HopLimit field goes to zero. +pAddr->Impostor set to 1) is injected and the +ip.TTL or ipv6.HopLimit field goes to zero. This is a defense of last resort against infinite loops caused by impostor packets. @@ -1343,13 +1351,13 @@ impostor packets. Remarks
Injects a packet into the network stack. The injected packet may be one received from -WinDivertRecv(), or a +WinDivertRecv(), or a modified version, or a completely new packet. Injected packets can be captured and diverted again by other WinDivert handles with lower priorities.

-Only the WINDIVERT_LAYER_NETWORK and -WINDIVERT_LAYER_NETWORK_FORWARD layers +Only the WINDIVERT_LAYER_NETWORK and +WINDIVERT_LAYER_NETWORK_FORWARD layers support packet injection, as summarized below:

@@ -1364,7 +1372,7 @@ Inject? -WINDIVERT_LAYER_NETWORK +WINDIVERT_LAYER_NETWORK ✔ @@ -1372,7 +1380,7 @@ Inject? -WINDIVERT_LAYER_NETWORK_FORWARD +WINDIVERT_LAYER_NETWORK_FORWARD ✔ @@ -1380,21 +1388,21 @@ Inject? -WINDIVERT_LAYER_FLOW +WINDIVERT_LAYER_FLOW -WINDIVERT_LAYER_SOCKET +WINDIVERT_LAYER_SOCKET -WINDIVERT_LAYER_REFLECT +WINDIVERT_LAYER_REFLECT @@ -1402,47 +1410,48 @@ Inject?

-For the WINDIVERT_LAYER_NETWORK layer the -pAddr->Outbound value determines which direction the packet +For the WINDIVERT_LAYER_NETWORK layer the +pAddr->Outbound value determines which direction the packet is injected. -If the pAddr->Outbound field is 1, +If the pAddr->Outbound field is 1, the packet will be injected into the outbound path (i.e. a packet leaving the local machine). -Else, if pAddr->Outbound is 0, +Else, if pAddr->Outbound is 0, the packet is injected into the inbound path (i.e. a packet arriving to the local machine). -Note that only the Outbound field, and not the IP addresses in +Note that only the Outbound field, and not the IP addresses in the injected packet, determines the packet's direction.

For packets injected into the inbound path, the -pAddr->Network.IfIdx and -pAddr->Network.SubIfIdx fields are assumed to contain valid +pAddr->Network.IfIdx and +pAddr->Network.SubIfIdx fields are assumed to contain valid interface numbers. -These may be retrieved from WinDivertRecv() +These may be retrieved from WinDivertRecv() (for packet modification), or from the IP Helper API.

-For outbound injected packets, the IfIdx and SubIfIdx +For outbound injected packets, the IfIdx and SubIfIdx 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.

-For impostor packets (where pAddr->Impostor is set to -1) WinDivert will automatically decrement the -ip.TTL or ipv6.HopLimit fields before reinjection. +For impostor packets (where pAddr->Impostor is set to +1) WinDivert will automatically decrement the +ip.TTL or ipv6.HopLimit fields before reinjection. This is to mitigate infinite loops since WinDivert cannot prevent impostor packets from being captured again by -WinDivertRecv(). +WinDivertRecv().

Injected packets must have the correct checksums or have the corresponding -pAddr->Pseudo*Checksum flag set to 1. +pAddr->*Checksum flag unset. A packet/address pair captured by -WinDivertRecv() is guaranteed to satisfy -this condition, so can be reinjected unmodified without recalculating checksums. +WinDivertRecv() is guaranteed to satisfy +this condition, so can be reinjected unmodified without recalculating +checksums. Otherwise, if a modification is necessary, checksums can be recalculated using the -WinDivertHelperCalcChecksums() +WinDivertHelperCalcChecksums() function.

@@ -1463,58 +1472,57 @@ BOOL WinDivertSendEx(
-

-Parameters
+

Parameters

    -
  • handle: A valid WinDivert handle created by - WinDivertOpen().
  • -
  • pPacket: A buffer containing the packet(s) to be injected.
  • -
  • packetLen: The total length of the buffer pPacket.
  • -
  • sendLen: The total number of bytes injected. - Can be NULL if this information is not required.
  • -
  • flags: Reserved, set to zero.
  • -
  • pAddr: The - address(es) of the injected +
  • handle: A valid WinDivert handle created by + WinDivertOpen().
  • +
  • pPacket: A buffer containing the packet(s) to be injected.
  • +
  • packetLen: The total length of the buffer pPacket.
  • +
  • sendLen: The total number of bytes injected. + Can be NULL if this information is not required.
  • +
  • flags: Reserved, set to zero.
  • +
  • pAddr: The + address(es) of the injected packet(s).
  • -
  • addrLen: The total length (in bytes) of the pAddr +
  • addrLen: The total length (in bytes) of the pAddr buffer.
  • -
  • lpOverlapped: An optional pointer to a OVERLAPPED +
  • lpOverlapped: An optional pointer to a OVERLAPPED structure.
-

+

Return Value
-TRUE if a packet was successfully injected, or FALSE +TRUE if a packet was successfully injected, or FALSE otherwise. -Use GetLastError() to get the reason. -The error code ERROR_IO_PENDING indicates that the overlapped +Use GetLastError() to get the reason. +The error code ERROR_IO_PENDING indicates that the overlapped operation has been successfully initiated and that completion will be indicated at a later time. All other codes indicate an error.

Remarks
This function is equivalent to -WinDivertSend() except: +WinDivertSend() except:

    -
  • Overlapped I/O is supported via the lpOverlapped +
  • Overlapped I/O is supported via the lpOverlapped parameter.
  • Batched I/O (i.e., sending multiple packets at once) is supported.

-Batched I/O makes it possible to send multiple packets at once using a -single operation, reducing the number of kernel/user-mode context switches -and improving performance. +Batched I/O makes it possible to send up to WINDIVERT_BATCH_MAX +packets at once using a single operation, reducing the number of +kernel/user-mode context switches and improving performance. To use batched I/O:

    -
  1. pack N packets into the pPacket buffer +
  2. pack N packets into the pPacket buffer (with no gaps between packets);
  3. -
  4. set packetLen to be the total sum of the N packet lengths; +
  5. set packetLen to be the total sum of the N packet lengths;
  6. -
  7. pack the corresponding N WINDIVERT_ADDRESS - address structures into the pAddr buffer; and
  8. -
  9. set addrLen to be the total size (in bytes) of the pAddr +
  10. pack the corresponding N WINDIVERT_ADDRESS + address structures into the pAddr buffer; and
  11. +
  12. set addrLen to be the total size (in bytes) of the pAddr buffer.
@@ -1529,24 +1537,22 @@ BOOL WinDivertShutdown(
-

-Parameters
+

Parameters

    -
  • handle: A valid WinDivert handle created by - WinDivertOpen().
  • -
  • how: A WINDIVERT_SHUTDOWN value to indicate how +
  • handle: A valid WinDivert handle created by + WinDivertOpen().
  • +
  • how: A WINDIVERT_SHUTDOWN value to indicate how the handle should be shutdown.
-

+

Return Value
-TRUE if successful, FALSE if an error occurred. -Use GetLastError() to get the reason for the error. +TRUE if successful, FALSE if an error occurred. +Use GetLastError() to get the reason for the error.

Remarks
This operation causes all or part of a WinDivert handle to be shut down. -The possible values for how are: +The possible values for how are:

-

@@ -1559,39 +1565,38 @@ Description
-WINDIVERT_SHUTDOWN_RECV +WINDIVERT_SHUTDOWN_RECV Stop new packets being queued for -WinDivertRecv(). +WinDivertRecv().
-WINDIVERT_SHUTDOWN_SEND +WINDIVERT_SHUTDOWN_SEND Stop new packets being injected via -WinDivertSend(). +WinDivertSend().
-WINDIVERT_SHUTDOWN_BOTH +WINDIVERT_SHUTDOWN_BOTH -Equivalent to (WINDIVERT_SHUTDOWN_RECV | WINDIVERT_SHUTDOWN_SEND). +Equivalent to (WINDIVERT_SHUTDOWN_RECV | WINDIVERT_SHUTDOWN_SEND).
-

Note that previously queued packets can still be received after -WINDIVERT_SHUTDOWN_RECV. +WINDIVERT_SHUTDOWN_RECV. When the packet queue is empty, -WinDivertRecv() -will fail with ERROR_NO_DATA. +WinDivertRecv() +will fail with ERROR_NO_DATA.

@@ -1604,20 +1609,19 @@ BOOL WinDivertClose(
-

-Parameters
+

Parameters

-

+

Return Value
-TRUE if successful, FALSE if an error occurred. -Use GetLastError() to get the reason for the error. +TRUE if successful, FALSE if an error occurred. +Use GetLastError() to get the reason for the error.

Remarks
Closes a WinDivert handle created by -WinDivertOpen(). +WinDivertOpen().

@@ -1631,22 +1635,22 @@ BOOL WinDivertSetParam(
-

-Parameters
+

Parameters

    -
  • handle: A valid WinDivert handle created by - WinDivertOpen().
  • -
  • param: A WinDivert parameter name.
  • -
  • value: The parameter's new value.
  • +
  • handle: A valid WinDivert handle created by + WinDivertOpen().
  • +
  • param: A WinDivert parameter name.
  • +
  • value: The parameter's new value.
-

+

Return Value
-TRUE if successful, FALSE if an error occurred. -Use GetLastError() to get the reason for the error. +TRUE if successful, FALSE if an error occurred. +Use GetLastError() to get the reason for the error.

Remarks
Sets a WinDivert parameter. Currently, the following WinDivert parameters are defined. +

@@ -1659,18 +1663,19 @@ Description
-WINDIVERT_PARAM_QUEUE_LEN +WINDIVERT_PARAM_QUEUE_LEN Sets the maximum length of the packet queue for -WinDivertRecv(). -Currently the default value is 2048, the minimum is 16, and the maximum -is 16384. +WinDivertRecv(). +The default value is WINDIVERT_PARAM_QUEUE_LEN_DEFAULT, +the minimum is WINDIVERT_PARAM_QUEUE_LEN_MIN, and the maximum +is WINDIVERT_PARAM_QUEUE_LEN_MAX.
-WINDIVERT_PARAM_QUEUE_TIME +WINDIVERT_PARAM_QUEUE_TIME Sets the minimum time, in milliseconds, a packet can be queued before it is @@ -1680,24 +1685,25 @@ processed by the application as soon as is possible. Note that this sets the minimum time a packet can be queued before it can be dropped. The actual time may be exceed this value. -Currently the default value is 1000 (1s), the minimum is 20 (20ms), and the -maximum is 8000 (8s). +Currently the default value is WINDIVERT_PARAM_QUEUE_TIME_DEFAULT, +the minimum is WINDIVERT_PARAM_QUEUE_TIME_MIN, and the +maximum is WINDIVERT_PARAM_QUEUE_TIME_MAX.
-WINDIVERT_PARAM_QUEUE_SIZE +WINDIVERT_PARAM_QUEUE_SIZE Sets the maximum number of bytes that can be stored in the packet queue for -WinDivertRecv(). -Currently the default value is 4194304 (4MB), the minimum is 65535 (64KB), -and the maximum is 33554432 (32MB). +WinDivertRecv(). +Currently the default value is WINDIVERT_PARAM_QUEUE_SIZE_DEFAULT, +the minimum is WINDIVERT_PARAM_QUEUE_SIZE_MIN, +and the maximum is WINDIVERT_PARAM_QUEUE_SIZE_MAX.
-

5.11 WinDivertGetParam

@@ -1710,22 +1716,21 @@ BOOL WinDivertGetParam(
-

-Parameters
+

Parameters

    -
  • handle: A valid WinDivert handle created by - WinDivertOpen().
  • -
  • param: A WinDivert parameter name.
  • -
  • value: The parameter's current value.
  • +
  • handle: A valid WinDivert handle created by + WinDivertOpen().
  • +
  • param: A WinDivert parameter name.
  • +
  • value: The parameter's current value.
-

+

Return Value
-TRUE if successful, FALSE if an error occurred. -Use GetLastError() to get the reason for the error. +TRUE if successful, FALSE if an error occurred. +Use GetLastError() to get the reason for the error.

Remarks
Gets a WinDivert parameter. -See WinDivertSetParam() for the list +See WinDivertSetParam() for the list of parameters.

@@ -1737,7 +1742,7 @@ The WinDivert helper programming API is a collection of definitions and functions designed to make writing WinDivert applications easier. The use of the helper API is optional. -

6.1 WINDIVERT_IPHDR

+

6.1 WINDIVERT_IPHDR

 typedef struct
@@ -1767,17 +1772,17 @@ IPv4 header definition.
 

The following fields can only be get/set using the following macro definitions: -

    -
  • FragOff with WINDIVERT_IPHDR_GET_FRAGOFF(hdr) and - WINDIVERT_IPHDR_SET_FRAGOFF(hdr, val)
  • -
  • MF with WINDIVERT_IPHDR_GET_MF(hdr) and - WINDIVERT_IPHDR_SET_MF(hdr, val)
  • -
  • DF with WINDIVERT_IPHDR_GET_DF(hdr) and - WINDIVERT_IPHDR_SET_DF(hdr, val)
  • -
  • Reserved with WINDIVERT_IPHDR_GET_RESERVED(hdr) and - WINDIVERT_IPHDR_SET_RESERVED(hdr, val)
  • -

+
    +
  • FragOff with WINDIVERT_IPHDR_GET_FRAGOFF(hdr) and + WINDIVERT_IPHDR_SET_FRAGOFF(hdr, val)
  • +
  • MF with WINDIVERT_IPHDR_GET_MF(hdr) and + WINDIVERT_IPHDR_SET_MF(hdr, val)
  • +
  • DF with WINDIVERT_IPHDR_GET_DF(hdr) and + WINDIVERT_IPHDR_SET_DF(hdr, val)
  • +
  • Reserved with WINDIVERT_IPHDR_GET_RESERVED(hdr) and + WINDIVERT_IPHDR_SET_RESERVED(hdr, val)
  • +

6.2 WINDIVERT_IPV6HDR

@@ -1796,6 +1801,7 @@ typedef struct
+

Fields
See here for more information. @@ -1805,14 +1811,14 @@ IPv6 header definition.

The following fields can only be get/set using the following macro definitions: +

  • TrafficClass with - WINDIVERT_IPV6HDR_GET_TRAFFICCLASS(hdr) and - WINDIVERT_IPV6HDR_SET_TRAFFICCLASS(hdr, val)
  • -
  • FlowLabel with WINDIVERT_IPV6HDR_GET_FLOWLABEL(hdr) and - WINDIVERT_IPV6HDR_SET_FLOWLABEL(hdr, val)
  • + WINDIVERT_IPV6HDR_GET_TRAFFICCLASS(hdr) and + WINDIVERT_IPV6HDR_SET_TRAFFICCLASS(hdr, val) +
  • FlowLabel with WINDIVERT_IPV6HDR_GET_FLOWLABEL(hdr) and + WINDIVERT_IPV6HDR_SET_FLOWLABEL(hdr, val)
-

6.3 WINDIVERT_ICMPHDR

@@ -1828,6 +1834,7 @@ typedef struct
+

Fields
See here for more information. @@ -1850,6 +1857,7 @@ typedef struct

+

Fields
See here for more information. @@ -1884,6 +1892,7 @@ typedef struct

+

Fields
See here for more information. @@ -1906,6 +1915,7 @@ typedef struct

+

Fields
See here for more information. @@ -1921,6 +1931,7 @@ UDP header definition. BOOL WinDivertHelperParsePacket( __in PVOID pPacket, __in UINT packetLen, + __out_opt UINT8 *pProtocol, __out_opt PWINDIVERT_IPHDR *ppIpHdr, __out_opt PWINDIVERT_IPV6HDR *ppIpv6Hdr, __out_opt PWINDIVERT_ICMPHDR *ppIcmpHdr, @@ -1928,51 +1939,72 @@ BOOL WinDivertHelperParsePacket( __out_opt PWINDIVERT_TCPHDR *ppTcpHdr, __out_opt PWINDIVERT_UDPHDR *ppUdpHdr, __out_opt PVOID *ppData, - __out_opt UINT *pDataLen + __out_opt UINT *pDataLen, + __out_opt PVOID *ppNext, + __out_opt UINT *pNextLen );

-

-Parameters
+

Parameters

    -
  • pPacket: The packet to be parsed.
  • -
  • packetLen: The total length of the packet pPacket.
  • -
  • ppIpHdr: Output pointer to a WINDIVERT_IPHDR.
  • -
  • ppIpv6Hdr: Output pointer to a WINDIVERT_IPV6HDR.
  • -
  • ppIcmpHdr: Output pointer to a WINDIVERT_ICMPHDR.
  • -
  • ppIcmpv6Hdr: Output pointer to a WINDIVERT_ICMPV6HDR.
  • -
  • ppTcpHdr: Output pointer to a WINDIVERT_TCPHDR.
  • -
  • ppUdpHdr: Output pointer to a WINDIVERT_UDPHDR.
  • -
  • ppData: Output pointer to the packet's data/payload.
  • -
  • pDataLen Output data/payload length.
  • +
  • pPacket: The packet(s) to be parsed.
  • +
  • packetLen: The total length of the packet(s) pPacket.
  • +
  • pProtocol: Output transport protocol.
  • +
  • ppIpHdr: Output pointer to a WINDIVERT_IPHDR.
  • +
  • ppIpv6Hdr: Output pointer to a WINDIVERT_IPV6HDR.
  • +
  • ppIcmpHdr: Output pointer to a WINDIVERT_ICMPHDR.
  • +
  • ppIcmpv6Hdr: Output pointer to a WINDIVERT_ICMPV6HDR.
  • +
  • ppTcpHdr: Output pointer to a WINDIVERT_TCPHDR.
  • +
  • ppUdpHdr: Output pointer to a WINDIVERT_UDPHDR.
  • +
  • ppData: Output pointer to the packet's data/payload.
  • +
  • pDataLen: Output data/payload length.
  • +
  • ppNext: Output pointer to the next packet (if present).
  • +
  • pNextLen: Output next packet length.
-

+

Return Value
-TRUE if all expected (non-NULL) outputs were present, -FALSE otherwise. -Note that FALSE may sometimes be a legitimate return value, e.g., -when both ppIpHdr and ppIpv6Hdr are non-NULL. +TRUE if successful, FALSE if an error occurred. +Use GetLastError() to get the reason for the error.

Remarks
-Parses a raw packet (e.g. from WinDivertRecv()) into the +Parses a raw packet or batch of packets (e.g. from WinDivertRecv()) into the various packet headers and/or payloads that may or may not be present.

-Each output parameter may be NULL or non-NULL. -For non-NULL parameters, this function will write the pointer to -the corresponding header/payload if it exists, or will write NULL +Each output parameter may be NULL or non-NULL. +For non-NULL parameters, this function will write the pointer to +the corresponding header/payload if it exists, or will write NULL otherwise. -Any non-NULL pointer that is returned +Any non-NULL pointer that is returned: +

    -
  1. Is a pointer into the original pPacket packet; and
  2. -
  3. There is enough space in pPacket to fit the header.
  4. +
  5. Is a pointer into the original pPacket packet buffer; and
  6. +
  7. There is enough space in pPacket to fit the header.
-

+

This function does not do any verification of the header/payload contents beyond checking the header length and any other minimal information required for parsing. +

+The pPacket parameter may also point to a batch (>1) of +packets. +In this case, packetLen should be the total length of the batch. +Each call will parse the first packet, and a pointer to the +remaining packets will be written to ppNext +and the remaining length will be written to pNextLen. +This makes it convenient to loop over every packet in the batch as follows: +

+
+    while (WinDivertHelperParsePacket(pPacket, packetLen, ..., &pPacket, &packetLen))
+    {
+        ...
+    }
+

+This function will always succeed provided the pPacket buffer +contains at least an IPv4 or IPv6 header. +

6.8 WinDivertHelperHashPacket

@@ -1986,14 +2018,13 @@ UINT64 WinDivertHelperHashPacket(
-

-Parameters
+

Parameters

    -
  • pPacket: The packet to be hashed.
  • -
  • packetLen: The total length of the packet pPacket.
  • -
  • seed: An optional seed value.
  • +
  • pPacket: The packet to be hashed.
  • +
  • packetLen: The total length of the packet pPacket.
  • +
  • seed: An optional seed value.
-

+

Return Value
A 64bit hash value.

@@ -2007,7 +2038,7 @@ The hash function itself is based on the xxHash algorithm and is not cryptographic.

-The optional seed value is also incorporated into the hash. +The optional seed value is also incorporated into the hash.

@@ -2021,22 +2052,21 @@ BOOL WinDivertHelperParseIPv4Address(
-

-Parameters
+

Parameters

    -
  • addrStr: The address string.
  • -
  • pAddr: Output address.
  • +
  • addrStr: The address string.
  • +
  • pAddr: Output address.
-

+

Return Value
-TRUE if successful, FALSE if an error occurred. -Use GetLastError() to get the reason for the error. +TRUE if successful, FALSE if an error occurred. +Use GetLastError() to get the reason for the error.

Remarks
-Parses an IPv4 address stored in addrStr. -If pAddr is non-NULL, the result is be stored in +Parses an IPv4 address stored in addrStr. +If pAddr is non-NULL, the result is be stored in host-byte-order. -Use WinDivertHelperHtonl() +Use WinDivertHelperHtonl() to convert the result into network-byte-order.

@@ -2051,23 +2081,22 @@ BOOL WinDivertHelperParseIPv6Address(
-

-Parameters
+

Parameters

    -
  • addrStr: The address string.
  • -
  • pAddr: Output address.
  • +
  • addrStr: The address string.
  • +
  • pAddr: Output address.
-

+

Return Value
-TRUE if successful, FALSE if an error occurred. -Use GetLastError() to get the reason for the error. +TRUE if successful, FALSE if an error occurred. +Use GetLastError() to get the reason for the error.

Remarks
-Parses an IPv6 address stored in addrStr. -If pAddr is non-NULL, the buffer assumed +Parses an IPv6 address stored in addrStr. +If pAddr is non-NULL, the buffer assumed to be large enough to hold a 16-byte IPv6 address. The result is stored in host-byte-order. -Use WinDivertHelperHtonIpv6Address() +Use WinDivertHelperHtonIpv6Address() to convert the result into network-byte-order.

@@ -2083,17 +2112,16 @@ BOOL WinDivertHelperFormatIPv4Address(
-

-Parameters
+

Parameters

    -
  • addr: The IPv4 address in host-byte order.
  • -
  • buffer: The buffer to store the formatted string.
  • -
  • bufLen: The length of buffer. +
  • addr: The IPv4 address in host-byte order.
  • +
  • buffer: The buffer to store the formatted string.
  • +
  • bufLen: The length of buffer.
-

+

Return Value
-TRUE if successful, FALSE if an error occurred. -Use GetLastError() to get the reason for the error. +TRUE if successful, FALSE if an error occurred. +Use GetLastError() to get the reason for the error.

Remarks
Convert an IPv4 address into a string. @@ -2111,17 +2139,16 @@ BOOL WinDivertHelperFormatIPv6Address(

-

-Parameters
+

Parameters

    -
  • pAddr: The IPv6 address in host-byte order.
  • -
  • buffer: The buffer to store the formatted string.
  • -
  • bufLen: The length of buffer. +
  • pAddr: The IPv6 address in host-byte order.
  • +
  • buffer: The buffer to store the formatted string.
  • +
  • bufLen: The length of buffer.
-

+

Return Value
-TRUE if successful, FALSE if an error occurred. -Use GetLastError() to get the reason for the error. +TRUE if successful, FALSE if an error occurred. +Use GetLastError() to get the reason for the error.

Remarks
Convert an IPv6 address into a string. @@ -2134,34 +2161,33 @@ Convert an IPv6 address into a string. UINT WinDivertHelperCalcChecksums( __inout PVOID pPacket, __in UINT packetLen, - __in_opt PWINDIVERT_ADDRESS pAddr, + __out_opt WINDIVERT_ADDRESS *pAddr, __in UINT64 flags );

-

-Parameters
+

Parameters

    -
  • pPacket: The packet to be modified.
  • -
  • packetLen: The total length of the packet pPacket.
  • -
  • pAddr: Optional pointer to a - WINDIVERT_ADDRESS structure.
  • -
  • flags: One or more of the following flags: +
  • pPacket: The packet to be modified.
  • +
  • packetLen: The total length of the packet pPacket.
  • +
  • pAddr: Optional pointer to a + WINDIVERT_ADDRESS structure.
  • +
  • flags: One or more of the following flags:
      -
    • WINDIVERT_HELPER_NO_IP_CHECKSUM: Do not calculate the IPv4 +
    • WINDIVERT_HELPER_NO_IP_CHECKSUM: Do not calculate the IPv4 checksum.
    • -
    • WINDIVERT_HELPER_NO_ICMP_CHECKSUM: Do not calculate the ICMP +
    • WINDIVERT_HELPER_NO_ICMP_CHECKSUM: Do not calculate the ICMP checksum.
    • -
    • WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM: Do not calculate the ICMPv6 +
    • WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM: Do not calculate the ICMPv6 checksum.
    • -
    • WINDIVERT_HELPER_NO_TCP_CHECKSUM: Do not calculate the TCP +
    • WINDIVERT_HELPER_NO_TCP_CHECKSUM: Do not calculate the TCP checksum.
    • -
    • WINDIVERT_HELPER_NO_UDP_CHECKSUM: Do not calculate the UDP +
    • WINDIVERT_HELPER_NO_UDP_CHECKSUM: Do not calculate the UDP checksum.
-

+

Return Value
The number of checksums calculated.

@@ -2170,7 +2196,13 @@ The number of checksums calculated. in the given packet. 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(). +injected with WinDivertSend(). +

+The pPacket parameter may also point to a batch (>1) of +packets. +In this case, packetLen should be the total length of the batch, +and this function will (re)calculate the checksums for all packets in the +batch.

By default this function will calculate each checksum from scratch, even if the existing checksum is correct. @@ -2178,13 +2210,9 @@ This may be inefficient for some applications. For better performance, incremental checksum calculations should be used instead (not provided by this API).

-If pAddr is non-NULL, this function will avoid calculating -the full checksum if the Pseudo*Checksum flag is -set in the corresponding -WINDIVERT_ADDRESS structure. -The address structure should be the same as -the one passed to WinDivertSend() in -order to (re)inject the packet. +If pAddr is non-NULL, this function sets +the corresponding *Checksum flag +(wee WINDIVERT_ADDRESS).

@@ -2202,28 +2230,27 @@ BOOL WinDivertHelperCompileFilter(
-

-Parameters
+

Parameters

    -
  • filter: The packet filter string to be checked.
  • -
  • layer: The layer.
  • -
  • object: The compiled filter object.
  • -
  • objLen: The length of the object buffer.
  • -
  • errorStr: The error description.
  • -
  • errorPos: The error position.
  • +
  • filter: The packet filter string to be checked.
  • +
  • layer: The layer.
  • +
  • object: The compiled filter object.
  • +
  • objLen: The length of the object buffer.
  • +
  • errorStr: The error description.
  • +
  • errorPos: The error position.
-

+

Return Value
-TRUE if the packet filter compilation is successful, FALSE +TRUE if the packet filter compilation is successful, FALSE otherwise.

Remarks
Compiles the given packet filter string into a compact object -representation that is optionally stored in object if non-NULL. +representation that is optionally stored in object if non-NULL. The object representation is a valid null terminated C string, but is otherwise opaque and not meant to be human readable. The object representation can be passed to all WinDivert functions, -such as WinDivertOpen(), in place of the +such as WinDivertOpen(), in place of the human-readable filter string equivalent.

@@ -2232,10 +2259,10 @@ valid with respect to the filter language. Otherwise, if the filter is invalid, then a human readable description of the error is -returned by errorStr (if non-NULL), and the error's -position is returned by errorPos (if non-NULL). +returned by errorStr (if non-NULL), and the error's +position is returned by errorPos (if non-NULL).

-Note that all strings returned through errorStr are global static +Note that all strings returned through errorStr are global static objects, and therefore do not need to be deallocated.

@@ -2245,42 +2272,41 @@ objects, and therefore do not need to be deallocated.
 BOOL WinDivertHelperEvalFilter(
     __in const char *filter,
-    __in PVOID pPacket,
+    __in const VOID *pPacket,
     __in UINT packetLen,
-    __in PWINDIVERT_ADDRESS pAddr
+    __in const WINDIVERT_ADDRESS *pAddr
 );
 
-

-Parameters
+

Parameters

    -
  • filter: The packet filter string to be evaluated.
  • -
  • pPacket: The packet.
  • -
  • packetLen: The total length of the packet pPacket.
  • -
  • pAddr: The WINDIVERT_ADDRESS of the packet - pPacket.
  • +
  • filter: The packet filter string to be evaluated.
  • +
  • pPacket: The packet.
  • +
  • packetLen: The total length of the packet pPacket.
  • +
  • pAddr: The WINDIVERT_ADDRESS of the packet + pPacket.
-

+

Return Value
-TRUE if the packet matches the filter string, - FALSE otherwise. +TRUE if the packet matches the filter string, + FALSE otherwise.

Remarks
Evaluates the given packet against the given packet filter string. -This function returns TRUE if the packet matches, and -returns FALSE otherwise. +This function returns TRUE if the packet matches, and +returns FALSE otherwise.

-This function also returns FALSE if an error occurs, in which -case GetLastError() can be used to get the reason for the error. -Otherwise, if no error occurred, GetLastError() will return -0. +This function also returns FALSE if an error occurs, in which +case GetLastError() can be used to get the reason for the error. +Otherwise, if no error occurred, GetLastError() will return +0.

Note that this function is relatively slow since the packet filter string will be (re)compiled for each call. This overhead can be minimized by pre-compiling the filter string into the object representation using the -WinDivertHelperCompileFilter() +WinDivertHelperCompileFilter() function.

@@ -2297,26 +2323,25 @@ BOOL WinDivertHelperEvalFilter(
-

-Parameters
+

Parameters

    -
  • filter: The packet filter string to be evaluated.
  • -
  • layer: The layer.
  • -
  • buffer: A buffer for the formatted filter.
  • -
  • bufLen: The length of buffer.
  • +
  • filter: The packet filter string to be evaluated.
  • +
  • layer: The layer.
  • +
  • buffer: A buffer for the formatted filter.
  • +
  • bufLen: The length of buffer.
-

+

Return Value
-TRUE if successful, FALSE if an error occurred. -Use GetLastError() to get the reason for the error. +TRUE if successful, FALSE if an error occurred. +Use GetLastError() to get the reason for the error.

Remarks
Formats the given filter string or object. This function is mainly useful for decompiling the filter object representation back into a human-readable filter string representation. -One application is the WINDIVERT_LAYER_REFLECT layer, -where a pseudo packet containing a filter object is returned by -WinDivertRecv(). +One application is the WINDIVERT_LAYER_REFLECT layer, +where a pseudo packet containing a filter object is returned by +WinDivertRecv().

@@ -2339,14 +2364,14 @@ void WinDivertHelperNtohIpv6Address(
-Parameters
+

Parameters

    -
  • x: The input value in network byte-order.
  • -
  • inAddr: The input IPv6 address in network byte-order.
  • -
  • outAddr: A buffer for the output IPv6 address in host +
  • x: The input value in network byte-order.
  • +
  • inAddr: The input IPv6 address in network byte-order.
  • +
  • outAddr: A buffer for the output IPv6 address in host byte-order.
-

+

Return Value
The output value in host byte order.

@@ -2374,14 +2399,14 @@ void WinDivertHelperHtonIpv6Address(

-Parameters
+

Parameters

    -
  • x: The input value in host byte-order.
  • -
  • inAddr: The input IPv6 address in host byte-order.
  • -
  • outAddr: A buffer for the output IPv6 address in network +
  • x: The input value in host byte-order.
  • +
  • inAddr: The input IPv6 address in host byte-order.
  • +
  • outAddr: A buffer for the output IPv6 address in network byte-order.
-

+

Return Value
The output value in network byte order.

@@ -2394,7 +2419,7 @@ Converts a value/IPv6-address from host to network byte-order.

7. Filter Language

-The WinDivertOpen() function accepts a +The WinDivertOpen() function accepts a string containing a filter. Only packets/events that match the filter will be blocked and/or captured. All other non-matching packets/events will be allowed to continue as normal. @@ -2404,145 +2429,154 @@ interest. For example, a HTTP blacklist filter is only interested in packets that might contain URLs. This could be achieved using the following filter. +

 HANDLE handle = WinDivertOpen(
     "outbound and "
     "tcp.PayloadLength > 0 and "
     "tcp.DstPort == 80", 0, 0, 0);
 
+

This filter selects only the subset of all traffic that is: +

  1. outbound;
  2. contains a non-empty payload; and
  3. has TCP destination port 80 (i.e. HTTP web traffic).
-

+

A filter is a Boolean expression of the form: +

         FILTER := true | false | FILTER and FILTER | FILTER or FILTER | (FILTER) | (FILTER? FILTER: FILTER) | TEST
 
-C-style syntax &&, ||, and ! may also -be used instead of and, or, and not, respectively. +

+C-style syntax &&, ||, and ! may also +be used instead of and, or, and not, respectively. C-style conditional operators are also supported, -where the expression (A? B: C) evaluates to: +where the expression (A? B: C) evaluates to: +

    -
  • B if A evaluates to true; or
  • -
  • C if A evaluates to false. +
  • B if A evaluates to true; or
  • +
  • C if A evaluates to false.
+

A test is of the following form: +

         TEST := TEST0 | not TEST0
         TEST0 := FIELD | FIELD op VAL
 
-where op is one of the following: -

+

+where op is one of the following: +

- - - - - - + + + + + +
OperatorDescription
== or =Equal
!=Not equal
<Less-than
>Greater-than
<=Less-than-or-equal
>=Greater-than-or-equal
== or =Equal
!=Not equal
<Less-than
>Greater-than
<=Less-than-or-equal
>=Greater-than-or-equal
-

-and VAL is a decimal number, hexadecimal number, IPv4 +

+and VAL is a decimal number, hexadecimal number, IPv4 address, IPv6 address or a layer-specific macro. -If the op VAL is missing, the test is implicitly -FIELD != 0. +If the op VAL is missing, the test is implicitly +FIELD != 0.

Finally, a field is some layer-specific property matching the packet or event. The possible fields are: -

+

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldLayerDescription
NETWORKFORWARDFLOW   SOCKET REFLECT
zero✔✔✔✔✔The value zero
event✔✔✔✔✔The event
outbound✔✔Is outbound?
inbound✔✔Is inbound?
ifIdx✔✔Interface index
subIfIdx✔✔Sub-interface index
loopback✔✔✔Is loopback packet?
impostor✔✔Is impostor packet?
processId✔✔✔Process ID
random8✔✔8-bit random number
random16✔✔16-bit random number
random32✔✔32-bit random number
layer✔The handle's layer
priority✔The handle's priority
packet[i]✔✔The ith 8-bit word of the packet
packet16[i]✔✔The ith 16-bit word of the packet
packet32[i]✔✔The ith 32-bit word of the packet
ip✔✔✔✔Is IPv4?
ipv6✔✔✔✔Is IPv6?
icmp✔✔✔✔Is ICMP?
icmpv6✔✔✔✔Is ICMPv6?
tcp✔✔✔✔Is TCP?
udp✔✔✔✔Is UDP?
protocol✔✔✔The protocol
localAddr✔✔✔The local address
localPort✔✔✔The local port
remoteAddr✔✔✔The remote address
remotePort✔✔✔The remote port
ip.*✔✔IPv4 fields (see WINDIVERT_IPHDR)
ipv6.*✔✔IPv6 fields (see WINDIVERT_IPV6HDR)
icmp.*✔✔ICMP fields (see WINDIVERT_ICMPHDR)
icmpv6.*✔✔ICMPV6 fields (see WINDIVERT_ICMPV6HDR)
tcp.*✔✔TCP fields (see WINDIVERT_TCPHDR)
tcp.PayloadLength✔✔The TCP payload length
tcp.Payload[i]✔✔The ith 8-bit word of the TCP payload
tcp.Payload16[i]✔✔The ith 16-bit word of the TCP payload
tcp.Payload32[i]✔✔The ith 32-bit word of the TCP payload
udp.*✔✔UDP fields (see WINDIVERT_UDPHDR)
udp.PayloadLength✔✔The UDP payload length
udp.Payload[i]✔✔The ith 8-bit word of the UDP payload
udp.Payload16[i]✔✔The ith 16-bit word of the UDP payload
udp.Payload32[i]✔✔The ith 32-bit word of the UDP payload
NETWORKFORWARDFLOW   SOCKET REFLECT
zero✔✔✔✔✔The value zero
event✔✔✔✔✔The event
outbound✔✔Is outbound?
inbound✔✔Is inbound?
ifIdx✔✔Interface index
subIfIdx✔✔Sub-interface index
loopback✔✔✔Is loopback packet?
impostor✔✔Is impostor packet?
processId✔✔✔Process ID
random8✔✔8-bit random number
random16✔✔16-bit random number
random32✔✔32-bit random number
layer✔The handle's layer
priority✔The handle's priority
packet[i]✔✔The ith 8-bit word of the packet
packet16[i]✔✔The ith 16-bit word of the packet
packet32[i]✔✔The ith 32-bit word of the packet
ip✔✔✔✔Is IPv4?
ipv6✔✔✔✔Is IPv6?
icmp✔✔✔✔Is ICMP?
icmpv6✔✔✔✔Is ICMPv6?
tcp✔✔✔✔Is TCP?
udp✔✔✔✔Is UDP?
protocol✔✔✔The protocol
localAddr✔✔✔The local address
localPort✔✔✔The local port
remoteAddr✔✔✔The remote address
remotePort✔✔✔The remote port
ip.*✔✔IPv4 fields (see WINDIVERT_IPHDR)
ipv6.*✔✔IPv6 fields (see WINDIVERT_IPV6HDR)
icmp.*✔✔ICMP fields (see WINDIVERT_ICMPHDR)
icmpv6.*✔✔ICMPV6 fields (see WINDIVERT_ICMPV6HDR)
tcp.*✔✔TCP fields (see WINDIVERT_TCPHDR)
tcp.PayloadLength✔✔The TCP payload length
tcp.Payload[i]✔✔The ith 8-bit word of the TCP payload
tcp.Payload16[i]✔✔The ith 16-bit word of the TCP payload
tcp.Payload32[i]✔✔The ith 32-bit word of the TCP payload
udp.*✔✔UDP fields (see WINDIVERT_UDPHDR)
udp.PayloadLength✔✔The UDP payload length
udp.Payload[i]✔✔The ith 8-bit word of the UDP payload
udp.Payload16[i]✔✔The ith 16-bit word of the UDP payload
udp.Payload32[i]✔✔The ith 32-bit word of the UDP payload
-

+

A test will also fails if the field is not relevant. -For example, the test tcp.DstPort == 80 will fail if the +For example, the test tcp.DstPort == 80 will fail if the packet does not contain a TCP header.

-The processId field matches the ID of the process associated +The processId field matches the ID of the process associated to an event. Due to technical limitations, this field is not supported by the -WINDIVERT_LAYER_NETWORK* layers. +WINDIVERT_LAYER_NETWORK* layers. That said, it is usually possible to associate process IDs to network packets matching the same network 5-tuple.

-Note that a fundamental race condition exists between the processId +Note that a fundamental race condition exists between the processId and the termination of the corresponding process. By the time an event is received using -WinDivertRecv(), +WinDivertRecv(), it is possible that the process has already terminated and the ID has been reassigned to an unrelated process. This problem can be partly mitigated by comparing the timestamp -(addr.Timestamp) with the creation time of the process. +(addr.Timestamp) with the creation time of the process. If the process is newer, then the ID has been reassigned.

-The packet*[i], tcp.Payload*[i] and -udp.Payload*[i] fields take an index parameter (i). +The packet*[i], tcp.Payload*[i] and +udp.Payload*[i] fields take an index parameter (i). The following indexing schemes are supported:

    -
  • Undecorated integer (e.g., packet32[10]): - evaluates to the ith word from the start of +
  • Undecorated integer (e.g., packet32[10]): + evaluates to the ith word from the start of the packet/payload. This is essentially C-style array indexing;
  • -
  • Negative decorated integer (e.g., packet32[-10]): - evaluates to the ith word from the end +
  • Negative decorated integer (e.g., packet32[-10]): + evaluates to the ith word from the end of the packet/payload. - Here the index (-1) is the first full word that fits; and
  • -
  • Byte decorated (negative) integer (e.g., packet32[10b] - or packet32[-10b]): - evaluated to the word offset by i bytes from the + Here the index (-1) is the first full word that fits; and
  • +
  • Byte decorated (negative) integer (e.g., packet32[10b] + or packet32[-10b]): + evaluated to the word offset by i bytes from the start (or end) of the packet/payload.

@@ -2552,40 +2586,39 @@ Words are assumed to be in network-byte ordering. If the index is out-of-bounds then the corresponding test is deemed to have failed.

-The random* fields are not really random but use a +The random* fields are not really random but use a deterministic hash value calculated using the -WinDivertHelperHashPacket() +WinDivertHelperHashPacket() function. -

+

Layer-specific macros make it possible to match events -and layers symbolically, e.g., event == CONNECT or -layer == SOCKET. +and layers symbolically, e.g., event == CONNECT or +layer == SOCKET. The possible macros are:

- - - - - - - - - - - - - - - + + + + + + + + + + + + + + +
MacroLayerValue
NETWORKFORWARDFLOW   SOCKET REFLECT
PACKET✔✔WINDIVERT_EVENT_NETWORK_PACKET
ESTABLISHED✔WINDIVERT_EVENT_FLOW_ESTABLISHED
DELETED✔WINDIVERT_EVENT_FLOW_DELETED
ACCEPT✔WINDIVERT_EVENT_SOCKET_ACCEPT
BIND✔WINDIVERT_EVENT_SOCKET_BIND
CONNECT✔WINDIVERT_EVENT_SOCKET_CONNECT
LISTEN✔WINDIVERT_EVENT_SOCKET_LISTEN
OPEN✔WINDIVERT_EVENT_REFLECT_OPEN
CLOSE✔WINDIVERT_EVENT_REFLECT_CLOSE
NETWORK✔WINDIVERT_LAYER_FLOW_NETWORK
NETWORK_FORWARD✔WINDIVERT_LAYER_FLOW_NETWORK_FORWARD
FLOW✔WINDIVERT_LAYER_FLOW_FLOW
SOCKET✔WINDIVERT_LAYER_FLOW_SOCKET
REFLECT✔WINDIVERT_LAYER_FLOW_REFLECT
NETWORKFORWARDFLOW   SOCKET REFLECT
PACKET✔✔WINDIVERT_EVENT_NETWORK_PACKET
ESTABLISHED✔WINDIVERT_EVENT_FLOW_ESTABLISHED
DELETED✔WINDIVERT_EVENT_FLOW_DELETED
ACCEPT✔WINDIVERT_EVENT_SOCKET_ACCEPT
BIND✔WINDIVERT_EVENT_SOCKET_BIND
CONNECT✔WINDIVERT_EVENT_SOCKET_CONNECT
LISTEN✔WINDIVERT_EVENT_SOCKET_LISTEN
OPEN✔WINDIVERT_EVENT_REFLECT_OPEN
CLOSE✔WINDIVERT_EVENT_REFLECT_CLOSE
NETWORK✔WINDIVERT_LAYER_FLOW_NETWORK
NETWORK_FORWARD✔WINDIVERT_LAYER_FLOW_NETWORK_FORWARD
FLOW✔WINDIVERT_LAYER_FLOW_FLOW
SOCKET✔WINDIVERT_LAYER_FLOW_SOCKET
REFLECT✔WINDIVERT_LAYER_FLOW_REFLECT

7.1 Filter Examples

-

  1. Divert all outbound (non-local) web traffic: @@ -2627,10 +2660,12 @@ This is useful for packet injection. The purpose of the filter is to help applications select the subset of all network traffic that the application is interested in. Ideally the filter should be +

    1. As short as possible; and
    2. As selective as possible.
    +

    For some applications these two objectives can conflict. That is, a selective filter is not short, and a short filter is not selective. For such applications the developer should experiment with different @@ -2644,50 +2679,52 @@ find the optimal solution.

    Some samples have been provided to demonstrate the WinDivert API. The sample programs are: +

      -
    • webfilter.exe: A simple URL blacklist filter. +
    • webfilter.exe: A simple URL blacklist filter. This program monitors outbound HTTP traffic. If it finds a URL request that matches the blacklist, it hijacks the TCP connection, reseting the connection at the server's end, and sending a simple block-page to the browser. The blacklist(s) are specified at the command-line.
    • -
    • netdump.exe: A simple packet sniffer based on the +
    • netdump.exe: A simple packet sniffer based on the WinDivert filter language. This program takes a filter specified at the command line, and prints information about any packet that matches the filter. This example uses WinDivert in "packet sniffing" mode, similar to - winpcap. - However, unlike winpcap, WinDivert can see local (loopback) + winpcap. + However, unlike winpcap, WinDivert can see local (loopback) packets. -
    • netfilter.exe: A simple firewall based on the WinDivert +
    • netfilter.exe: A simple firewall based on the WinDivert filter language. This program takes a filter specified at the command line, and blocks any packet that matches the filter. It blocks TCP by sending a TCP reset, UDP by an ICMP message, and all other traffic it simply drops. - This is similar to the Linux iptables command with the - -j REJECT option.
    • -
    • passthru.exe: A simple program that simply re-injects every + This is similar to the Linux iptables command with the + -j REJECT option.
    • +
    • passthru.exe: A simple program that simply re-injects every packet it captures. This example is multi-threaded, where multiple threads are processing packets from a single handle. This example is useful for performance testing, and as a starting point for more interesting applications.
    • -
    • streamdump.exe: A simple program that demonstrates how to +
    • streamdump.exe: A simple program that demonstrates how to handle streams using WinDivert. The basic idea is to divert outbound TCP connections to a local proxy server which can capture or manipulate the stream. - The streamdump sample program also demonstrates usage of the - WinDivertRecvEx() and - WinDivertSendEx() functions.
    • + The streamdump sample program also demonstrates usage of the + WinDivertRecvEx() and + WinDivertSendEx() functions.
    -

    +

    The samples are intended for educational purposes only, and are not fully-featured applications.

    The following basic template for a WinDivert application. The basic idea is to open a WinDivert handle, then enter a capture-modify-reinject loop: +

         HANDLE handle;          // WinDivert handle
         WINDIVERT_ADDRESS addr; // Packet address
    @@ -2720,11 +2757,12 @@ capture-modify-reinject loop:
             }
         }
     
    +

    For applications that do not need to modify the packet, a better approach is -to open the WinDivert handle with the WINDIVERT_FLAG_SNIFF flag set, +to open the WinDivert handle with the WINDIVERT_FLAG_SNIFF flag set, and not re-inject the packet with -WinDivertSend(). -See the netdump.exe sample program for an example of this usage. +WinDivertSend(). +See the netdump.exe sample program for an example of this usage.


    @@ -2732,10 +2770,11 @@ See the netdump.exe sample program for an example of this usage.

    There are some limitations to the WinDivert package. -They are +They are: +

    • Injecting inbound ICMP/ICMPv6 messages: - Calling WinDivertSend() will fail with + Calling WinDivertSend() will fail with an error for certain types of inbound ICMP/ICMPv6 messages. This is probably because the Windows TCP/IP stack does not handle such messages. @@ -2751,12 +2790,12 @@ They are (including WinDivert applications) block and inject unmodified copies of packets then this can lead to an infinite loop. If such a loop occurs, - WinDivertSend() will eventually fail - with error ERROR_HOST_UNREACHABLE. + WinDivertSend() will eventually fail + with error ERROR_HOST_UNREACHABLE. Unfortunately, such errors are not easy to fix. Some crude solutions include: (1) removing the incompatible driver, or - (2) ignoring all packets with ip.TTL or - ipv6.HopLimit less than the Windows DefaultTTL + (2) ignoring all packets with ip.TTL or + ipv6.HopLimit less than the Windows DefaultTTL registry value. See GitHub issue #41 for more information. @@ -2771,7 +2810,7 @@ They are GitHub issue #26 for more information.
    • WinDivert can cause packets to be out-of-order: - Simply running the passthru.exe sample program can cause + Simply running the passthru.exe sample program can cause packets to become out-of-order. This is not a bug, since there is no requirement for packets to remain in-order. @@ -2780,7 +2819,6 @@ They are that incorrectly assume packets to be in-order.
    -


    10. License

    @@ -2794,6 +2832,7 @@ Please see the notices below:

    LGPL version 3: +

     WinDivert is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
    @@ -2808,9 +2847,9 @@ GNU Lesser General Public License for more details.
     You should have received a copy of the GNU Lesser General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    -

    GPL version 2: +

     WinDivert is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
    @@ -2826,6 +2865,5 @@ You should have received a copy of the GNU General Public License along
     with this program; if not, write to the Free Software Foundation, Inc.,
     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     
    -