WinDivert 2.0 API, service & documentation fixes.

- Make WinDivertRecv() and WinDivertSend() arg
  ordering match the Ex versions.
- Put the WinDivertHelperParsePacket() protocol
  arg after the IP headers.
- WinDivert service handling is now protected by
  a mutex.
- Debug the "uninstall" command for windivertctl.
  It can now uninstall the WinDivert driver &
  not leave the WinDivert service in a "pending"
  state.
- Document WinDivert performance tips.
This commit is contained in:
basil00
2019-03-04 08:42:34 +08:00
parent 0028aa6fff
commit 8fcb4313b6
12 changed files with 238 additions and 138 deletions
+25 -15
View File
@@ -219,10 +219,25 @@ static BOOLEAN WinDivertGetDriverFileName(LPWSTR sys_str)
*/
static SC_HANDLE WinDivertDriverInstall(VOID)
{
DWORD err, retries = 2;
DWORD err;
SC_HANDLE manager = NULL, service = NULL;
wchar_t windivert_sys[MAX_PATH+1];
SERVICE_STATUS status;
HANDLE mutex = NULL;
// Create & lock a named mutex. This is to stop two processes trying
// to start the driver at the same time.
mutex = CreateMutex(NULL, FALSE, L"WinDivertDriverInstallMutex");
if (mutex == NULL)
{
return NULL;
}
switch (WaitForSingleObject(mutex, INFINITE))
{
case WAIT_OBJECT_0: case WAIT_ABANDONED:
break;
default:
return NULL;
}
// Open the service manager:
manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
@@ -232,7 +247,6 @@ static SC_HANDLE WinDivertDriverInstall(VOID)
}
// Check if the WinDivert service already exists; if so, start it.
WinDivertDriverInstallReTry:
service = OpenService(manager, WINDIVERT_DEVICE_NAME, SERVICE_ALL_ACCESS);
if (service != NULL)
{
@@ -254,11 +268,8 @@ WinDivertDriverInstallReTry:
{
if (GetLastError() == ERROR_SERVICE_EXISTS)
{
if (retries != 0)
{
retries--;
goto WinDivertDriverInstallReTry;
}
service = OpenService(manager, WINDIVERT_DEVICE_NAME,
SERVICE_ALL_ACCESS);
}
goto WinDivertDriverInstallExit;
}
@@ -278,8 +289,6 @@ WinDivertDriverInstallExit:
else
{
// Failed to start service; clean-up:
ControlService(service, SERVICE_CONTROL_STOP, &status);
DeleteService(service);
CloseServiceHandle(service);
service = NULL;
SetLastError(err);
@@ -292,6 +301,8 @@ WinDivertDriverInstallExit:
{
CloseServiceHandle(manager);
}
ReleaseMutex(mutex);
CloseHandle(mutex);
SetLastError(err);
return service;
@@ -442,7 +453,6 @@ extern HANDLE WinDivertOpen(const char *filter, WINDIVERT_LAYER layer,
INVALID_HANDLE_VALUE);
// Schedule the service to be deleted (once all handles are closed).
DeleteService(service);
CloseServiceHandle(service);
if (handle == INVALID_HANDLE_VALUE)
@@ -492,14 +502,14 @@ extern HANDLE WinDivertOpen(const char *filter, WINDIVERT_LAYER layer,
* Receive a WinDivert packet.
*/
extern BOOL WinDivertRecv(HANDLE handle, PVOID pPacket, UINT packetLen,
PWINDIVERT_ADDRESS addr, UINT *readlen)
UINT *readLen, PWINDIVERT_ADDRESS addr)
{
WINDIVERT_IOCTL ioctl;
memset(&ioctl, 0, sizeof(ioctl));
ioctl.recv.addr = addr;
ioctl.recv.addr_len_ptr = NULL;
return WinDivertIoControl(handle, IOCTL_WINDIVERT_RECV, &ioctl,
pPacket, packetLen, readlen);
pPacket, packetLen, readLen);
}
/*
@@ -534,14 +544,14 @@ extern BOOL WinDivertRecvEx(HANDLE handle, PVOID pPacket, UINT packetLen,
* Send a WinDivert packet.
*/
extern BOOL WinDivertSend(HANDLE handle, const VOID *pPacket, UINT packetLen,
const WINDIVERT_ADDRESS *addr, UINT *writelen)
UINT *writeLen, const WINDIVERT_ADDRESS *addr)
{
WINDIVERT_IOCTL ioctl;
memset(&ioctl, 0, sizeof(ioctl));
ioctl.send.addr = addr;
ioctl.send.addr_len = sizeof(WINDIVERT_ADDRESS);
return WinDivertIoControl(handle, IOCTL_WINDIVERT_SEND, &ioctl,
(PVOID)pPacket, packetLen, writelen);
(PVOID)pPacket, packetLen, writeLen);
}
/*
+4 -4
View File
@@ -2460,7 +2460,7 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet,
return FALSE;
}
if (!WinDivertHelperParsePacket((PVOID)packet, packet_len,
&protocol, &iphdr, &ipv6hdr, &icmphdr, &icmpv6hdr,
&iphdr, &ipv6hdr, &protocol, &icmphdr, &icmpv6hdr,
&tcphdr, &udphdr, NULL, &payload_len, NULL, NULL))
{
SetLastError(ERROR_INVALID_PARAMETER);
@@ -4642,9 +4642,9 @@ extern UINT64 WinDivertHelperHashPacket(const VOID *pPacket, UINT packetLen,
PWINDIVERT_TCPHDR tcp_header = NULL;
PWINDIVERT_UDPHDR udp_header = NULL;
if (!WinDivertHelperParsePacket((PVOID)pPacket, packetLen, NULL,
&ip_header, &ipv6_header, &icmp_header, &icmpv6_header,
&tcp_header, &udp_header, NULL, NULL, NULL, NULL))
if (!WinDivertHelperParsePacket((PVOID)pPacket, packetLen, &ip_header,
&ipv6_header, NULL, &icmp_header, &icmpv6_header, &tcp_header,
&udp_header, NULL, NULL, NULL, NULL))
{
return 0;
}
+3 -3
View File
@@ -284,7 +284,7 @@ static UINT8 WinDivertSkipExtHeaders(UINT8 proto, UINT8 **header, UINT *len)
* Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet.
*/
extern BOOL WinDivertHelperParsePacket(const VOID *pPacket, UINT packetLen,
UINT8 *pProtocol, PWINDIVERT_IPHDR *ppIpHdr, PWINDIVERT_IPV6HDR *ppIpv6Hdr,
PWINDIVERT_IPHDR *ppIpHdr, PWINDIVERT_IPV6HDR *ppIpv6Hdr, UINT8 *pProtocol,
PWINDIVERT_ICMPHDR *ppIcmpHdr, PWINDIVERT_ICMPV6HDR *ppIcmpv6Hdr,
PWINDIVERT_TCPHDR *ppTcpHdr, PWINDIVERT_UDPHDR *ppUdpHdr, PVOID *ppData,
UINT *pDataLen, PVOID *ppNext, UINT *pNextLen)
@@ -491,8 +491,8 @@ extern BOOL WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
PWINDIVERT_UDPHDR udp_header;
UINT payload_len, checksum_len;
if (!WinDivertHelperParsePacket(pPacket, packetLen, NULL, &ip_header,
&ipv6_header, &icmp_header, &icmpv6_header, &tcp_header,
if (!WinDivertHelperParsePacket(pPacket, packetLen, &ip_header,
&ipv6_header, NULL, &icmp_header, &icmpv6_header, &tcp_header,
&udp_header, NULL, &payload_len, NULL, NULL))
{
return FALSE;
+106 -41
View File
@@ -61,15 +61,16 @@
<li><a href="#filter_usage">7.2 Filter Usage</a></li>
</ul>
</li>
<li><a href="#samples">8. Samples</a></li>
<li><a href="#known_issues">9. Known Issues</a></li>
<li><a href="#license">10. License</a></li>
<li><a href="#performance">8. Performance</a></li>
<li><a href="#samples">9. Samples</a></li>
<li><a href="#known_issues">10. Known Issues</a></li>
<li><a href="#license">11. License</a></li>
</ul>
<hr>
<a name="introduction"><h2>1. Introduction</h2></a>
<p>
WinDivert is a user-mode
WinDivert is a powerful user-mode
capture/sniffing/modification/blocking/re-injection package for
Windows 7, Windows 8 and Windows 10.
WinDivert can be used to implement user-mode packet filters, packet sniffers,
@@ -93,8 +94,8 @@ The main features of the WinDivert are:
</ul>
<p>
WinDivert provides similar functionality to
<code>divert</code> sockets from FreeBSD/MacOS, <code>NETLINK</code> sockets from
Linux.
<code>divert</code> sockets from FreeBSD/MacOS, <code>NETLINK</code> sockets
from Linux.
</p>
<hr>
@@ -231,17 +232,22 @@ To uninstall, simply delete the <code>WinDivert.dll</code>,
<code>WinDivert32.sys</code>, and <code>WinDivert64.sys</code> files.
If already running, the WinDivert driver will be automatically
uninstalled during the next machine reboot.
The WinDivert driver can also be manually removed by issuing the following
The WinDivert driver can also be manually removed by (1) terminating
all processes that are using WinDivert, and (2) issuing the following
commands at the command prompt
</p>
<pre>
sc stop WinDivert
sc delete WinDivert
sc stop WinDivert
sc delete WinDivert
</pre>
<p>
Note that this is not recommended as it will interfere with other
applications that depend on WinDivert.
Alternatively, the WinDivert driver can be removed by using the
<code>windivertctl.exe</code> <a href="#samples">sample program</a> by
issuing the following command:
</p>
<pre>
windivertctl uninstall
</pre>
<hr>
<a name="programming_api"><h2>5. Programming API</h2></a>
@@ -1031,7 +1037,7 @@ 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 <code>priority</code> values represent higher priorities, with
Higher <code>priority</code> values represent higher priorities, with
<code>WINDIVERT_PRIORITY_HIGHEST</code> being the highest priority,
<code>0</code> the middle (and a good default) priority,
and <code>WINDIVERT_PRIORITY_LOWEST</code> the lowest priority.
@@ -1180,8 +1186,8 @@ BOOL <b>WinDivertRecv</b>(
__in HANDLE handle,
__out_opt PVOID pPacket,
__in UINT packetLen,
__out_opt WINDIVERT_ADDRESS *pAddr,
__out_opt UINT *recvLen
__out_opt UINT *pRecvLen,
__out_opt WINDIVERT_ADDRESS *pAddr
);
</pre>
</td></tr></table>
@@ -1192,10 +1198,10 @@ BOOL <b>WinDivertRecv</b>(
<a href="#divert_open"><code>WinDivertOpen()</code></a>.</li>
<li> <code>pPacket</code>: An optional buffer for the captured packet.</li>
<li> <code>packetLen</code>: The length of the <code>pPacket</code> buffer.</li>
<li> <code>pRecvLen</code>: The total number of bytes written to <code>pPacket</code>.
Can be <code>NULL</code> if this information is not required.</li>
<li> <code>pAddr</code>: An optional buffer for the
<a href="#divert_address">address</a> of the captured packet/event.</li>
<li> <code>recvLen</code>: The total number of bytes written to <code>pPacket</code>.
Can be <code>NULL</code> if this information is not required.</li>
</ul>
<p>
<b>Return Value</b><br>
@@ -1307,7 +1313,7 @@ Data?
For layers that do support capturing, the captured packet will be written to
the <code>pPacket</code> buffer.
If non-<code>NULL</code>, then the total number of bytes
written to <code>pPacket</code> will be written to <code>recvLen</code>.
written to <code>pPacket</code> will be written to <code>pRecvLen</code>.
If the <code>pPacket</code> buffer is too small, the packet will be
truncated and the operation will fail with the
<code>ERROR_INSUFFICIENT_BUFFER</code> error code.
@@ -1347,7 +1353,7 @@ BOOL <b>WinDivertRecvEx</b>(
__in HANDLE handle,
__out VOID *pPacket,
__in UINT packetLen,
__out_opt UINT *recvLen,
__out_opt UINT *pRecvLen,
__in UINT64 flags,
__out_opt WINDIVERT_ADDRESS *pAddr,
__inout_opt UINT *pAddrLen,
@@ -1363,7 +1369,7 @@ BOOL <b>WinDivertRecvEx</b>(
<li> <code>pPacket</code>: A buffer for the captured packet(s).</li>
<li> <code>packetLen</code>: The length of the <code>pPacket</code> buffer in
bytes.</li>
<li> <code>recvLen</code>: The total number of bytes written to <code>pPacket</code>.
<li> <code>pRecvLen</code>: The total number of bytes written to <code>pPacket</code>.
Can be <code>NULL</code> if this information is not required.</li>
<li> <code>flags</code>: Reserved, set to zero.</li>
<li> <code>pAddr</code>: The
@@ -1437,8 +1443,8 @@ BOOL <b>WinDivertSend</b>(
__in HANDLE handle,
__in const VOID *pPacket,
__in UINT packetLen,
__in const WINDIVERT_ADDRESS *pAddr,
__out_opt UINT *sendLen
__out_opt UINT *pSendLen,
__in const WINDIVERT_ADDRESS *pAddr
);
</pre>
</td></tr></table>
@@ -1449,10 +1455,10 @@ BOOL <b>WinDivertSend</b>(
<a href="#divert_open"><code>WinDivertOpen()</code></a>.</li>
<li> <code>pPacket</code>: A buffer containing a packet to be injected.</li>
<li> <code>packetLen</code>: The total length of the <code>pPacket</code> buffer.</li>
<li> <code>pSendLen</code>: The total number of bytes injected.
Can be <code>NULL</code> if this information is not required.</li>
<li> <code>pAddr</code>: The
<a href="#divert_address">address</a> of the injected packet.</li>
<li> <code>sendLen</code>: The total number of bytes injected.
Can be <code>NULL</code> if this information is not required.</li>
</ul>
<p>
<b>Return Value</b><br>
@@ -1608,7 +1614,7 @@ BOOL <b>WinDivertSendEx</b>(
__in HANDLE handle,
__in const VOID *pPacket,
__in UINT packetLen,
__out_opt UINT *sendLen,
__out_opt UINT *pSendLen,
__in UINT64 flags,
__in const WINDIVERT_ADDRESS *pAddr,
__in UINT addrLen,
@@ -1623,7 +1629,7 @@ BOOL <b>WinDivertSendEx</b>(
<a href="#divert_open"><code>WinDivertOpen()</code></a>.</li>
<li> <code>pPacket</code>: A buffer containing the packet(s) to be injected.</li>
<li> <code>packetLen</code>: The total length of the buffer <code>pPacket</code>.</li>
<li> <code>sendLen</code>: The total number of bytes injected.
<li> <code>pSendLen</code>: The total number of bytes injected.
Can be <code>NULL</code> if this information is not required.</li>
<li> <code>flags</code>: Reserved, set to zero.</li>
<li> <code>pAddr</code>: The
@@ -2105,9 +2111,9 @@ UDP header definition.
BOOL <b>WinDivertHelperParsePacket</b>(
__in PVOID pPacket,
__in UINT packetLen,
__out_opt UINT8 *pProtocol,
__out_opt PWINDIVERT_IPHDR *ppIpHdr,
__out_opt PWINDIVERT_IPV6HDR *ppIpv6Hdr,
__out_opt UINT8 *pProtocol,
__out_opt PWINDIVERT_ICMPHDR *ppIcmpHdr,
__out_opt PWINDIVERT_ICMPV6HDR *ppIcmpv6Hdr,
__out_opt PWINDIVERT_TCPHDR *ppTcpHdr,
@@ -2124,9 +2130,9 @@ BOOL <b>WinDivertHelperParsePacket</b>(
<ul>
<li> <code>pPacket</code>: The packet(s) to be parsed.</li>
<li> <code>packetLen</code>: The total length of the packet(s) <code>pPacket</code>.</li>
<li> <code>pProtocol</code>: Output transport protocol.</li>
<li> <code>ppIpHdr</code>: Output pointer to a <code>WINDIVERT_IPHDR</code>.</li>
<li> <code>ppIpv6Hdr</code>: Output pointer to a <code>WINDIVERT_IPV6HDR</code>.</li>
<li> <code>pProtocol</code>: Output transport protocol.</li>
<li> <code>ppIcmpHdr</code>: Output pointer to a <code>WINDIVERT_ICMPHDR</code>.</li>
<li> <code>ppIcmpv6Hdr</code>: Output pointer to a <code>WINDIVERT_ICMPV6HDR</code>.</li>
<li> <code>ppTcpHdr</code>: Output pointer to a <code>WINDIVERT_TCPHDR</code>.</li>
@@ -2333,7 +2339,7 @@ Convert an IPv6 address into a string.
<table border="1" cellpadding="5"><tr><td>
<pre>
BOOL <b>WinDivertHelperCalcChecksums</b>(
__inout PVOID pPacket,
__inout VOID *pPacket,
__in UINT packetLen,
__out_opt WINDIVERT_ADDRESS *pAddr,
__in UINT64 flags
@@ -2874,7 +2880,65 @@ find the optimal solution.
</p>
<hr>
<a name="samples"><h2>8. Samples</h2></a>
<a name="performance"><h2>8. Performance</h2></a>
<p>
Using WinDivert to redirect network traffic to/from a user application incurs
performance overheads, such as copying packet data and user/kernel mode
context switching.
Under heavy load (&geq;1Gbps) these overheads can be significant.
The following techniques can be used to
reduce overheads (in order of importance):
</p>
<ol>
<li><i>Selective Filter</i>: Only select the subset of network traffic
the user application is interested in.
Non-matching traffic will continue to use the default path without
incurring additional overheads.</li>
<li><i>Batch Mode</i>: The
<a href="#divert_recv_ex">WinDivertRecvEx()</a> and
<a href="#divert_send_ex">WinDivertSendEx()</a> functions
support <i>batching</i> that allows several packets to be
received/sent at once.
This can significantly reduce the overheads relating to
user/kernel mode context switching.</li>
<li><i>Multi-threading</i>: It is possible to spread packet processing
over multiple threads ensuring that the user application does not
become a bottleneck.
That said, sometimes spawning too many threads can degrade performance.
</li>
<li><i>Small Buffers</i>: Large buffers generally incur more overhead
compared to smaller buffers.
In general, the buffer size should reflect the expected usage
as closely as possible.</li>
<li><i>Simple Filters</i>:
Currently WinDivert does not optimize the filter compilation, so it
is up to the user application to ensure the filter is simple/optimized.
</li>
<li><i>Overlapped I/O</i>: This allows the user application to do
additional tasks at the same time as receive/send operations, which may
improve performance for some applications.
It is also possible for a single thread to initiate several
receive/send operations at once.
However, using overlapped I/O can be tricky, and it is important
that all buffers passed to
<a href="#divert_recv_ex">WinDivertRecvEx()</a> or
<a href="#divert_send_ex">WinDivertSendEx()</a>
(including the <code>OVERLAPPED</code> structure)
are not modified by the user application until the operation
completes.</li>
<li><i>Queue length/size/time</i>: If these values are too small then some
packets may be dropped under heavy load.
These values can be controlled using the
<a href="#divert_set_param">WinDivertSetParam()</a> function.</li>
</ol>
<p>
The <code>passthru.exe</code> <a href="#samples">sample program</a> can
be used to experiment with different batch sizes and thread counts.
</p>
<hr>
<a name="samples"><h2>9. Samples</h2></a>
<p>
Some samples have been provided to demonstrate the WinDivert API.
@@ -2905,9 +2969,8 @@ The sample programs are:
<code>-j REJECT</code> option.</li>
<li><code>passthru.exe</code>: 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
This example has a configurable batch-size and thread count,
and so is useful for performance testing or as a starting point
for more interesting applications.</li>
<li><code>streamdump.exe</code>: A simple program that demonstrates how to
handle streams using WinDivert.
@@ -2924,9 +2987,11 @@ The sample programs are:
The <code>socketdump</code> sample demonstrates the
<code>WINDIVERT_LAYER_SOCKET</code> layer.</li>
<li><code>windivertctl.exe</code> allows the user to query which processes
are using WinDivert via the <code>list</code> or <code>monitor</code>
are using WinDivert via the <code>list</code> or <code>watch</code>
commands, or to terminate all such processes using the
<code>killall</code> command.
<code>kill</code> command.
The <code>windivertctl.exe</code> can also forcibly remove the
WinDivert driver using the <code>uninstall</code> command.
The <code>windivertctl</code> sample demonstrates the
<code>WINDIVERT_LAYER_REFLECT</code> layer.</li>
</ul>
@@ -2956,7 +3021,7 @@ capture-modify-reinject loop:
// Main capture-modify-inject loop:
while (TRUE)
{
if (!WinDivertRecv(handle, packet, sizeof(packet), &amp;addr, &amp;packetLen))
if (!WinDivertRecv(handle, packet, sizeof(packet), &amp;packetLen, &amp;addr))
{
// Handle recv error
continue;
@@ -2965,7 +3030,7 @@ capture-modify-reinject loop:
// Modify packet.
WinDivertHelperCalcChecksums(packet, packetLen, &amp;addr, 0);
if (!WinDivertSend(handle, packet, packetLen, &amp;addr, NULL))
if (!WinDivertSend(handle, packet, packetLen, NULL, &amp;addr))
{
// Handle send error
continue;
@@ -2981,7 +3046,7 @@ See the <code>netdump.exe</code> sample program for an example of this usage.
</p>
<hr>
<a name="known_issues"><h2>9. Known Issues</h2></a>
<a name="known_issues"><h2>10. Known Issues</h2></a>
<p>
WinDivert has some known limitations listed below:
@@ -3038,8 +3103,8 @@ WinDivert has some known limitations listed below:
<a href="#divert_recv"><code>WinDivertRecv()</code></a>,
it is possible that the process responsible for the event has already
terminated.
Furthermore, it is also possible that the <code>processId</code> has been
reassigned to an unrelated process.
Furthermore, it is theoretically possible that the
<code>processId</code> has been reassigned to an unrelated process.
This problem can be partly mitigated by comparing the timestamp
(<code>addr.Timestamp</code>) with the creation time of the process.
If the process is newer, then the ID has been reassigned.
@@ -3048,13 +3113,13 @@ WinDivert has some known limitations listed below:
In this special case, the <code>addr.Reflect.processId</code> is
guaranteed to be valid until the corresponding
<code>WINDIVERT_EVENT_REFLECT_CLOSE</code> event is
received by the user application or dropped
received by the user application or is dropped
(filter mismatch or timeout).
</li>
</ul>
<hr>
<a name="license"><h2>10. License</h2></a>
<a name="license"><h2>11. License</h2></a>
<p>
WinDivert is dual-licensed under your choice of either the
<a href="http://www.gnu.org/licenses/lgpl-3.0.txt">GNU Lesser General
+1 -1
View File
@@ -263,7 +263,7 @@ int __cdecl main(int argc, char **argv)
// Main loop:
while (TRUE)
{
if (!WinDivertRecv(handle, NULL, 0, &addr, &packet_len))
if (!WinDivertRecv(handle, NULL, 0, NULL, &addr))
{
fprintf(stderr, "failed to read packet (%d)\n", GetLastError());
continue;
+4 -4
View File
@@ -148,7 +148,7 @@ int __cdecl main(int argc, char **argv)
while (TRUE)
{
// Read a matching packet.
if (!WinDivertRecv(handle, packet, sizeof(packet), &addr, &packet_len))
if (!WinDivertRecv(handle, packet, sizeof(packet), &packet_len, &addr))
{
fprintf(stderr, "warning: failed to read packet (%d)\n",
GetLastError());
@@ -156,9 +156,9 @@ int __cdecl main(int argc, char **argv)
}
// Print info about the matching packet.
WinDivertHelperParsePacket(packet, packet_len, NULL, &ip_header,
&ipv6_header, &icmp_header, &icmpv6_header, &tcp_header,
&udp_header, NULL, NULL, NULL, NULL);
WinDivertHelperParsePacket(packet, packet_len, &ip_header, &ipv6_header,
NULL, &icmp_header, &icmpv6_header, &tcp_header, &udp_header, NULL,
NULL, NULL, NULL);
if (ip_header == NULL && ipv6_header == NULL)
{
fprintf(stderr, "warning: junk packet\n");
+10 -10
View File
@@ -193,17 +193,17 @@ int __cdecl main(int argc, char **argv)
while (TRUE)
{
// Read a matching packet.
if (!WinDivertRecv(handle, packet, sizeof(packet), &recv_addr,
&packet_len))
if (!WinDivertRecv(handle, packet, sizeof(packet), &packet_len,
&recv_addr))
{
fprintf(stderr, "warning: failed to read packet\n");
continue;
}
// Print info about the matching packet.
WinDivertHelperParsePacket(packet, packet_len, NULL, &ip_header,
&ipv6_header, &icmp_header, &icmpv6_header, &tcp_header,
&udp_header, NULL, &payload_len, NULL, NULL);
WinDivertHelperParsePacket(packet, packet_len, &ip_header, &ipv6_header,
NULL, &icmp_header, &icmpv6_header, &tcp_header, &udp_header, NULL,
&payload_len, NULL, NULL);
if (ip_header == NULL && ipv6_header == NULL)
{
continue;
@@ -292,7 +292,7 @@ int __cdecl main(int argc, char **argv)
WinDivertHelperCalcChecksums((PVOID)reset, sizeof(TCPPACKET),
&send_addr, 0);
if (!WinDivertSend(handle, (PVOID)reset, sizeof(TCPPACKET),
&send_addr, NULL))
NULL, &send_addr))
{
fprintf(stderr, "warning: failed to send TCP reset (%d)\n",
GetLastError());
@@ -319,7 +319,7 @@ int __cdecl main(int argc, char **argv)
WinDivertHelperCalcChecksums((PVOID)resetv6,
sizeof(TCPV6PACKET), &send_addr, 0);
if (!WinDivertSend(handle, (PVOID)resetv6, sizeof(TCPV6PACKET),
&send_addr, NULL))
NULL, &send_addr))
{
fprintf(stderr, "warning: failed to send TCP (IPV6) "
"reset (%d)\n", GetLastError());
@@ -344,8 +344,8 @@ int __cdecl main(int argc, char **argv)
send_addr.Outbound = !recv_addr.Outbound;
WinDivertHelperCalcChecksums((PVOID)dnr, icmp_length,
&send_addr, 0);
if (!WinDivertSend(handle, (PVOID)dnr, icmp_length, &send_addr,
NULL))
if (!WinDivertSend(handle, (PVOID)dnr, icmp_length, NULL,
&send_addr))
{
fprintf(stderr, "warning: failed to send ICMP message "
"(%d)\n", GetLastError());
@@ -368,7 +368,7 @@ int __cdecl main(int argc, char **argv)
WinDivertHelperCalcChecksums((PVOID)dnrv6, icmpv6_length,
&send_addr, 0);
if (!WinDivertSend(handle, (PVOID)dnrv6, icmpv6_length,
&send_addr, NULL))
NULL, &send_addr))
{
fprintf(stderr, "warning: failed to send ICMPv6 message "
"(%d)\n", GetLastError());
+1 -2
View File
@@ -61,7 +61,6 @@ int __cdecl main(int argc, char **argv)
char local_str[INET6_ADDRSTRLEN+1], remote_str[INET6_ADDRSTRLEN+1];
char *filename;
DWORD path_len;
UINT packet_len;
WINDIVERT_ADDRESS addr;
switch (argc)
@@ -97,7 +96,7 @@ int __cdecl main(int argc, char **argv)
console = GetStdHandle(STD_OUTPUT_HANDLE);
while (TRUE)
{
if (!WinDivertRecv(handle, NULL, 0, &addr, &packet_len))
if (!WinDivertRecv(handle, NULL, 0, NULL, &addr))
{
fprintf(stderr, "failed to read packet (%d)\n", GetLastError());
continue;
+3 -3
View File
@@ -187,13 +187,13 @@ int __cdecl main(int argc, char **argv)
// Main loop:
while (TRUE)
{
if (!WinDivertRecv(handle, packet, sizeof(packet), &addr, &packet_len))
if (!WinDivertRecv(handle, packet, sizeof(packet), &packet_len, &addr))
{
warning("failed to read packet (%d)", GetLastError());
continue;
}
WinDivertHelperParsePacket(packet, packet_len, NULL, &ip_header, NULL,
WinDivertHelperParsePacket(packet, packet_len, &ip_header, NULL, NULL,
NULL, NULL, &tcp_header, NULL, NULL, NULL, NULL, NULL);
if (ip_header == NULL || tcp_header == NULL)
{
@@ -237,7 +237,7 @@ int __cdecl main(int argc, char **argv)
}
WinDivertHelperCalcChecksums(packet, packet_len, &addr, 0);
if (!WinDivertSend(handle, packet, packet_len, &addr, NULL))
if (!WinDivertSend(handle, packet, packet_len, NULL, &addr))
{
warning("failed to send packet (%d)", GetLastError());
continue;
+7 -7
View File
@@ -197,21 +197,21 @@ int __cdecl main(int argc, char **argv)
// Main loop:
while (TRUE)
{
if (!WinDivertRecv(handle, packet, sizeof(packet), &addr, &packet_len))
if (!WinDivertRecv(handle, packet, sizeof(packet), &packet_len, &addr))
{
fprintf(stderr, "warning: failed to read packet (%d)\n",
GetLastError());
continue;
}
WinDivertHelperParsePacket(packet, packet_len, NULL, &ip_header,
WinDivertHelperParsePacket(packet, packet_len, &ip_header, NULL,
NULL, NULL, NULL, &tcp_header, NULL, &payload, &payload_len,
NULL, NULL);
if (ip_header == NULL || tcp_header == NULL || payload == NULL ||
!BlackListPayloadMatch(blacklist, payload, (UINT16)payload_len))
{
// Packet does not match the blacklist; simply reinject it.
if (!WinDivertSend(handle, packet, packet_len, &addr, NULL))
if (!WinDivertSend(handle, packet, packet_len, NULL, &addr))
{
fprintf(stderr, "warning: failed to reinject packet (%d)\n",
GetLastError());
@@ -231,7 +231,7 @@ int __cdecl main(int argc, char **argv)
reset->tcp.SeqNum = tcp_header->SeqNum;
reset->tcp.AckNum = tcp_header->AckNum;
WinDivertHelperCalcChecksums((PVOID)reset, sizeof(PACKET), &addr, 0);
if (!WinDivertSend(handle, (PVOID)reset, sizeof(PACKET), &addr, NULL))
if (!WinDivertSend(handle, (PVOID)reset, sizeof(PACKET), NULL, &addr))
{
fprintf(stderr, "warning: failed to send reset packet (%d)\n",
GetLastError());
@@ -246,8 +246,8 @@ int __cdecl main(int argc, char **argv)
htonl(ntohl(tcp_header->SeqNum) + payload_len);
addr.Outbound = !addr.Outbound; // Reverse direction.
WinDivertHelperCalcChecksums((PVOID)blockpage, blockpage_len, &addr, 0);
if (!WinDivertSend(handle, (PVOID)blockpage, blockpage_len, &addr,
NULL))
if (!WinDivertSend(handle, (PVOID)blockpage, blockpage_len, NULL,
&addr))
{
fprintf(stderr, "warning: failed to send block page packet (%d)\n",
GetLastError());
@@ -264,7 +264,7 @@ int __cdecl main(int argc, char **argv)
finish->tcp.AckNum =
htonl(ntohl(tcp_header->SeqNum) + payload_len);
WinDivertHelperCalcChecksums((PVOID)finish, sizeof(PACKET), &addr, 0);
if (!WinDivertSend(handle, (PVOID)finish, sizeof(PACKET), &addr, NULL))
if (!WinDivertSend(handle, (PVOID)finish, sizeof(PACKET), NULL, &addr))
{
fprintf(stderr, "warning: failed to send finish packet (%d)\n",
GetLastError());
+67 -41
View File
@@ -66,7 +66,7 @@ typedef enum
*/
int __cdecl main(int argc, char **argv)
{
HANDLE handle, process, console;
HANDLE handle, process, console, mutex;
INT16 priority = -333; // Arbitrary.
UINT packet_len;
static UINT8 packet[MAX_PACKET];
@@ -128,7 +128,7 @@ usage:
// Open WinDivert REFLECT handle:
handle = WinDivertOpen(filter, WINDIVERT_LAYER_REFLECT, priority,
WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_RECV_ONLY |
(mode == WATCH || mode == UNINSTALL? 0: WINDIVERT_FLAG_NO_INSTALL));
(mode == WATCH? 0: WINDIVERT_FLAG_NO_INSTALL));
if (handle == INVALID_HANDLE_VALUE)
{
if (mode != WATCH && GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
@@ -165,36 +165,11 @@ usage:
return EXIT_FAILURE;
}
// Stop the WinDivert service.
if (mode == UNINSTALL)
{
manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (manager == NULL)
{
fprintf(stderr, "error: failed to open service manager (%d)\n",
GetLastError());
return EXIT_FAILURE;
}
service = OpenService(manager, "WinDivert", SERVICE_ALL_ACCESS);
if (service == NULL)
{
fprintf(stderr, "error: failed to open WinDivert service (%d)\n",
GetLastError());
return EXIT_FAILURE;
}
if (!ControlService(service, SERVICE_CONTROL_STOP, &status))
{
fprintf(stderr, "error: failed to stop WinDivert service (%d)\n",
GetLastError());
return EXIT_FAILURE;
}
}
// Main loop:
console = GetStdHandle(STD_OUTPUT_HANDLE);
while (TRUE)
{
if (!WinDivertRecv(handle, packet, sizeof(packet), &addr, &packet_len))
if (!WinDivertRecv(handle, packet, sizeof(packet), &packet_len, &addr))
{
if (mode != WATCH && GetLastError() == ERROR_NO_DATA)
{
@@ -344,19 +319,6 @@ usage:
putchar('\n');
}
if (mode == UNINSTALL)
{
SetConsoleTextAttribute(console, FOREGROUND_RED);
fputs("UNINSTALL", stdout);
SetConsoleTextAttribute(console,
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
puts(" WinDivert");
CloseServiceHandle(service);
CloseServiceHandle(manager);
}
if (!WinDivertClose(handle))
{
fprintf(stderr, "error: failed to close WinDivert handle (%d)\n",
@@ -364,6 +326,70 @@ usage:
return EXIT_FAILURE;
}
if (mode == UNINSTALL)
{
// Stop & delete the WinDivert service:
mutex = CreateMutex(NULL, FALSE, "WinDivertDriverInstallMutex");
if (mutex == NULL)
{
fprintf(stderr, "error: failed to create WinDivert driver "
"install mutex (%d)\n", GetLastError());
return EXIT_FAILURE;
}
switch (WaitForSingleObject(mutex, INFINITE))
{
case WAIT_OBJECT_0: case WAIT_ABANDONED:
break;
default:
fprintf(stderr, "error: failed to acquire WinDivert driver "
"install mutex (%d)\n", GetLastError());
return EXIT_FAILURE;
}
manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (manager == NULL)
{
fprintf(stderr, "error: failed to open service manager (%d)\n",
GetLastError());
return EXIT_FAILURE;
}
service = OpenService(manager, "WinDivert", SERVICE_ALL_ACCESS);
if (service == NULL)
{
fprintf(stderr, "error: failed to open WinDivert service (%d)\n",
GetLastError());
return EXIT_FAILURE;
}
if (!ControlService(service, SERVICE_CONTROL_STOP, &status))
{
fprintf(stderr, "error: failed to stop WinDivert service (%d)\n",
GetLastError());
return EXIT_FAILURE;
}
if (status.dwCurrentState != SERVICE_STOPPED)
{
fprintf(stderr, "error: failed to stop WinDivert service");
return EXIT_FAILURE;
}
if (!DeleteService(service) &&
GetLastError() != ERROR_SERVICE_MARKED_FOR_DELETE)
{
fprintf(stderr, "error: failed to delete WinDivert service (%d)\n",
GetLastError());
return EXIT_FAILURE;
}
CloseServiceHandle(service);
CloseServiceHandle(manager);
SetConsoleTextAttribute(console, FOREGROUND_GREEN);
fputs("UNINSTALL", stdout);
SetConsoleTextAttribute(console,
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
puts(" WinDivert");
ReleaseMutex(mutex);
CloseHandle(mutex);
}
return 0;
}
+7 -7
View File
@@ -227,8 +227,8 @@ extern WINDIVERTEXPORT BOOL WinDivertRecv(
__in HANDLE handle,
__out_opt VOID *pPacket,
__in UINT packetLen,
__out_opt WINDIVERT_ADDRESS *pAddr,
__out_opt UINT *pReadLen);
__out_opt UINT *pRecvLen,
__out_opt WINDIVERT_ADDRESS *pAddr);
/*
* Receive (read) a packet from a WinDivert handle.
@@ -237,7 +237,7 @@ extern WINDIVERTEXPORT BOOL WinDivertRecvEx(
__in HANDLE handle,
__out_opt VOID *pPacket,
__in UINT packetLen,
__out_opt UINT *pReadLen,
__out_opt UINT *pRecvLen,
__in UINT64 flags,
__out WINDIVERT_ADDRESS *pAddr,
__inout_opt UINT *pAddrLen,
@@ -250,8 +250,8 @@ extern WINDIVERTEXPORT BOOL WinDivertSend(
__in HANDLE handle,
__in const VOID *pPacket,
__in UINT packetLen,
__in const WINDIVERT_ADDRESS *pAddr,
__out_opt UINT *pWriteLen);
__out_opt UINT *pSendLen,
__in const WINDIVERT_ADDRESS *pAddr);
/*
* Send (write/inject) a packet to a WinDivert handle.
@@ -260,7 +260,7 @@ extern WINDIVERTEXPORT BOOL WinDivertSendEx(
__in HANDLE handle,
__in const VOID *pPacket,
__in UINT packetLen,
__out_opt UINT *pWriteLen,
__out_opt UINT *pSendLen,
__in UINT64 flags,
__in const WINDIVERT_ADDRESS *pAddr,
__in UINT addrLen,
@@ -480,9 +480,9 @@ extern WINDIVERTEXPORT UINT64 WinDivertHelperHashPacket(
extern WINDIVERTEXPORT BOOL WinDivertHelperParsePacket(
__in const VOID *pPacket,
__in UINT packetLen,
__out_opt UINT8 *pProtocol,
__out_opt PWINDIVERT_IPHDR *ppIpHdr,
__out_opt PWINDIVERT_IPV6HDR *ppIpv6Hdr,
__out_opt UINT8 *pProtocol,
__out_opt PWINDIVERT_ICMPHDR *ppIcmpHdr,
__out_opt PWINDIVERT_ICMPV6HDR *ppIcmpv6Hdr,
__out_opt PWINDIVERT_TCPHDR *ppTcpHdr,