diff --git a/doc/windivert.html b/doc/windivert.html
index a4b2670..ca9dec3 100644
--- a/doc/windivert.html
+++ b/doc/windivert.html
@@ -753,6 +753,16 @@ have a valid digital signature
+ERROR_DRIVER_FAILED_PRIOR_UNLOAD
+ |
+
+654
+ |
+
+An incompatible version of the WinDivert driver is currently loaded.
+ |
+
+
ERROR_SERVICE_DOES_NOT_EXIST
|
@@ -1658,14 +1668,14 @@ Description
|
-WINDIVERT_PARAM_QUEUE_LEN
+WINDIVERT_PARAM_QUEUE_LENGTH
|
Sets the maximum length of the packet queue for
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.
+The default value is WINDIVERT_PARAM_QUEUE_LENGTH_DEFAULT,
+the minimum is WINDIVERT_PARAM_QUEUE_LENGTH_MIN, and the maximum
+is WINDIVERT_PARAM_QUEUE_LENGTH_MAX.
|
@@ -1725,9 +1735,38 @@ Use GetLastError() to get the reason for the error.
Remarks
Gets a WinDivert parameter.
-See WinDivertSetParam() for the list
-of parameters.
+This function supports all the parameters from
+WinDivertSetParam(),
+and the following additional read-only
parameters:
+
+
+
+|
+Parameter
+ |
+
+Description
+ |
+
+
+
+WINDIVERT_PARAM_VERSION_MAJOR
+ |
+
+Returns the major version of the driver.
+ |
+
+
+
+WINDIVERT_PARAM_VERSION_MINOR
+ |
+
+Returns the minor version of the driver.
+ |
+
+
+
@@ -2576,16 +2615,9 @@ Due to technical limitations, this field is not supported by the
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
-and the termination of the corresponding process.
-By the time an event is received using
-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.
-If the process is newer, then the ID has been reassigned.
+and the termination of the corresponding process, see
+the know issues listed below.
The packet*[i], tcp.Payload*[i] and
udp.Payload*[i] fields take an index parameter (i).
@@ -2812,13 +2844,12 @@ See the netdump.exe sample program for an example of this usage.
9. Known Issues
-There are some limitations to the WinDivert package.
-They are:
+WinDivert has some known limitations listed below:
- Injecting inbound ICMP/ICMPv6 messages:
- Calling
WinDivertSend() will fail with
- an error for certain types of inbound ICMP/ICMPv6 messages.
+ 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.
Such errors are harmless and can be ignored.
@@ -2861,6 +2892,22 @@ They are:
(e.g. some buggy NAT implementations)
that incorrectly assume packets to be in-order.
+- A race condition exists between
addr.*.processId
and
+ process termination.
+ By the time an event is received using
+ WinDivertRecv(),
+ it is possible that the process responsible for the event has already
+ terminated.
+ Furthermore, it is also possible that the processId 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.
+ If the process is newer, then the ID has been reassigned.
+ This race condition does not affect the
+ WINDIVERT_EVENT_REFLECT_OPEN event.
+ In this special case, the addr.Reflect.processId is
+ guaranteed to be valid until the corresponding close event is
+ received or dropped.
diff --git a/examples/netdump/netdump.c b/examples/netdump/netdump.c
index ad8566d..8811c03 100644
--- a/examples/netdump/netdump.c
+++ b/examples/netdump/netdump.c
@@ -1,6 +1,6 @@
/*
* netdump.c
- * (C) 2018, all rights reserved,
+ * (C) 2019, all rights reserved,
*
* This file is part of WinDivert.
*
@@ -118,18 +118,27 @@ int __cdecl main(int argc, char **argv)
}
// Max-out the packet queue:
- if (!WinDivertSetParam(handle, WINDIVERT_PARAM_QUEUE_LEN, 8192))
+ if (!WinDivertSetParam(handle, WINDIVERT_PARAM_QUEUE_LENGTH,
+ WINDIVERT_PARAM_QUEUE_LENGTH_MAX))
{
fprintf(stderr, "error: failed to set packet queue length (%d)\n",
GetLastError());
exit(EXIT_FAILURE);
}
- if (!WinDivertSetParam(handle, WINDIVERT_PARAM_QUEUE_TIME, 2048))
+ if (!WinDivertSetParam(handle, WINDIVERT_PARAM_QUEUE_TIME,
+ WINDIVERT_PARAM_QUEUE_TIME_MAX))
{
fprintf(stderr, "error: failed to set packet queue time (%d)\n",
GetLastError());
exit(EXIT_FAILURE);
}
+ if (!WinDivertSetParam(handle, WINDIVERT_PARAM_QUEUE_SIZE,
+ WINDIVERT_PARAM_QUEUE_SIZE_MAX))
+ {
+ fprintf(stderr, "error: failed to set packet queue size (%d)\n",
+ GetLastError());
+ exit(EXIT_FAILURE);
+ }
// Set up timing:
QueryPerformanceFrequency(&freq);
diff --git a/examples/windivertctl/windivertctl.c b/examples/windivertctl/windivertctl.c
index 93a0c93..a34d5ec 100644
--- a/examples/windivertctl/windivertctl.c
+++ b/examples/windivertctl/windivertctl.c
@@ -141,8 +141,8 @@ usage:
GetLastError());
return EXIT_FAILURE;
}
- if (!WinDivertSetParam(handle, WINDIVERT_PARAM_QUEUE_LEN,
- WINDIVERT_PARAM_QUEUE_LEN_MAX) ||
+ if (!WinDivertSetParam(handle, WINDIVERT_PARAM_QUEUE_LENGTH,
+ WINDIVERT_PARAM_QUEUE_LENGTH_MAX) ||
!WinDivertSetParam(handle, WINDIVERT_PARAM_QUEUE_SIZE,
WINDIVERT_PARAM_QUEUE_SIZE_MAX) ||
!WinDivertSetParam(handle, WINDIVERT_PARAM_QUEUE_TIME,
@@ -163,7 +163,7 @@ usage:
{
break;
}
- fprintf(stderr, "failed to event (%d)\n", GetLastError());
+ fprintf(stderr, "failed to receive event (%d)\n", GetLastError());
continue;
}
diff --git a/include/windivert.h b/include/windivert.h
index 524c720..e930c54 100644
--- a/include/windivert.h
+++ b/include/windivert.h
@@ -190,11 +190,13 @@ typedef enum
*/
typedef enum
{
- WINDIVERT_PARAM_QUEUE_LEN = 0, /* Packet queue length. */
+ WINDIVERT_PARAM_QUEUE_LENGTH = 0, /* Packet queue length. */
WINDIVERT_PARAM_QUEUE_TIME = 1, /* Packet queue time. */
WINDIVERT_PARAM_QUEUE_SIZE = 2, /* Packet queue size. */
+ WINDIVERT_PARAM_VERSION_MAJOR = 3, /* Driver version (major). */
+ WINDIVERT_PARAM_VERSION_MINOR = 4, /* Driver version (minor). */
} WINDIVERT_PARAM, *PWINDIVERT_PARAM;
-#define WINDIVERT_PARAM_MAX WINDIVERT_PARAM_QUEUE_SIZE
+#define WINDIVERT_PARAM_MAX WINDIVERT_PARAM_VERSION_MINOR
/*
* WinDivert shutdown parameter.
@@ -298,18 +300,18 @@ extern WINDIVERTEXPORT BOOL WinDivertGetParam(
/*
* WinDivert constants.
*/
-#define WINDIVERT_PRIORITY_LOWEST 30000
-#define WINDIVERT_PRIORITY_HIGHEST (-WINDIVERT_PRIORITY_LOWEST)
-#define WINDIVERT_PARAM_QUEUE_LEN_DEFAULT 4096
-#define WINDIVERT_PARAM_QUEUE_LEN_MIN 32
-#define WINDIVERT_PARAM_QUEUE_LEN_MAX 16384
-#define WINDIVERT_PARAM_QUEUE_TIME_DEFAULT 2000 /* 2s */
-#define WINDIVERT_PARAM_QUEUE_TIME_MIN 100 /* 100ms */
-#define WINDIVERT_PARAM_QUEUE_TIME_MAX 16000 /* 16s */
-#define WINDIVERT_PARAM_QUEUE_SIZE_DEFAULT 4194304 /* 4MB */
-#define WINDIVERT_PARAM_QUEUE_SIZE_MIN 65535 /* 64KB */
-#define WINDIVERT_PARAM_QUEUE_SIZE_MAX 33554432 /* 32MB */
-#define WINDIVERT_BATCH_MAX 0xFF /* 255 */
+#define WINDIVERT_PRIORITY_LOWEST 30000
+#define WINDIVERT_PRIORITY_HIGHEST (-WINDIVERT_PRIORITY_LOWEST)
+#define WINDIVERT_PARAM_QUEUE_LENGTH_DEFAULT 4096
+#define WINDIVERT_PARAM_QUEUE_LENGTH_MIN 32
+#define WINDIVERT_PARAM_QUEUE_LENGTH_MAX 16384
+#define WINDIVERT_PARAM_QUEUE_TIME_DEFAULT 2000 /* 2s */
+#define WINDIVERT_PARAM_QUEUE_TIME_MIN 100 /* 100ms */
+#define WINDIVERT_PARAM_QUEUE_TIME_MAX 16000 /* 16s */
+#define WINDIVERT_PARAM_QUEUE_SIZE_DEFAULT 4194304 /* 4MB */
+#define WINDIVERT_PARAM_QUEUE_SIZE_MIN 65535 /* 64KB */
+#define WINDIVERT_PARAM_QUEUE_SIZE_MAX 33554432 /* 32MB */
+#define WINDIVERT_BATCH_MAX 0xFF /* 255 */
/****************************************************************************/
/* WINDIVERT HELPER API */
diff --git a/sys/windivert.c b/sys/windivert.c
index 732f97b..ba830be 100644
--- a/sys/windivert.c
+++ b/sys/windivert.c
@@ -234,7 +234,7 @@ WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(req_context_s, windivert_req_context_get);
*
* Note the packet data must be pointer-aligned.
*/
-#define WINDIVERT_WORK_QUEUE_LEN_MAX 4096
+#define WINDIVERT_WORK_QUEUE_LENGTH_MAX 4096
#ifdef _WIN64
#define WINDIVERT_ALIGN_SIZE 8
#define WINDIVERT_DATA_ALIGN __declspec(align(8))
@@ -1385,7 +1385,7 @@ extern VOID windivert_create(IN WDFDEVICE device, IN WDFREQUEST request,
context->object = object;
context->work_queue_length = 0;
context->packet_queue_length = 0;
- context->packet_queue_maxlength = WINDIVERT_PARAM_QUEUE_LEN_DEFAULT;
+ context->packet_queue_maxlength = WINDIVERT_PARAM_QUEUE_LENGTH_DEFAULT;
context->packet_queue_size = 0;
context->packet_queue_maxsize = WINDIVERT_PARAM_QUEUE_SIZE_DEFAULT;
context->packet_queue_maxcounts =
@@ -3240,9 +3240,9 @@ windivert_ioctl_bad_flags:
}
switch ((UINT32)param)
{
- case WINDIVERT_PARAM_QUEUE_LEN:
- if (value < WINDIVERT_PARAM_QUEUE_LEN_MIN ||
- value > WINDIVERT_PARAM_QUEUE_LEN_MAX)
+ case WINDIVERT_PARAM_QUEUE_LENGTH:
+ if (value < WINDIVERT_PARAM_QUEUE_LENGTH_MIN ||
+ value > WINDIVERT_PARAM_QUEUE_LENGTH_MAX)
{
KeReleaseInStackQueuedSpinLock(&lock_handle);
status = STATUS_INVALID_PARAMETER;
@@ -3315,7 +3315,7 @@ windivert_ioctl_bad_flags:
}
switch ((UINT32)param)
{
- case WINDIVERT_PARAM_QUEUE_LEN:
+ case WINDIVERT_PARAM_QUEUE_LENGTH:
*valptr = context->packet_queue_maxlength;
break;
case WINDIVERT_PARAM_QUEUE_TIME:
@@ -3324,6 +3324,12 @@ windivert_ioctl_bad_flags:
case WINDIVERT_PARAM_QUEUE_SIZE:
*valptr = context->packet_queue_maxsize;
break;
+ case WINDIVERT_PARAM_VERSION_MAJOR:
+ *valptr = WINDIVERT_VERSION_MAJOR;
+ break;
+ case WINDIVERT_PARAM_VERSION_MINOR:
+ *valptr = WINDIVERT_VERSION_MINOR;
+ break;
default:
KeReleaseInStackQueuedSpinLock(&lock_handle);
status = STATUS_INVALID_PARAMETER;
@@ -4819,7 +4825,7 @@ static BOOL windivert_queue_work(context_t context, PVOID packet,
work->match = FALSE;
}
context->work_queue_length++;
- if (context->work_queue_length > WINDIVERT_WORK_QUEUE_LEN_MAX)
+ if (context->work_queue_length > WINDIVERT_WORK_QUEUE_LENGTH_MAX)
{
// The work queue is full; as an emergency we drop packets.
old_entry = RemoveHeadList(&context->work_queue);
diff --git a/test/test.c b/test/test.c
index 79d60bf..3e13a28 100644
--- a/test/test.c
+++ b/test/test.c
@@ -1004,6 +1004,7 @@ static BOOL run_test(HANDLE inject_handle, const char *filter,
HANDLE event[2] = {NULL, NULL};
BOOL random, result, ipv4;
LARGE_INTEGER end;
+ UINT64 val;
*diff = 0;
@@ -1031,6 +1032,33 @@ static BOOL run_test(HANDLE inject_handle, const char *filter,
"(err = %d)\n", GetLastError());
goto failed;
}
+ if (!WinDivertSetParam(handle[0], WINDIVERT_PARAM_QUEUE_LENGTH,
+ WINDIVERT_PARAM_QUEUE_LENGTH_MAX) ||
+ !WinDivertGetParam(handle[0], WINDIVERT_PARAM_QUEUE_LENGTH, &val) ||
+ val != WINDIVERT_PARAM_QUEUE_LENGTH_MAX)
+ {
+ fprintf(stderr, "error: failed to set WINDIVERT_PARAM_QUEUE_LENGTH "
+ "parameter (err = %d)\n", GetLastError());
+ goto failed;
+ }
+ if (!WinDivertSetParam(handle[0], WINDIVERT_PARAM_QUEUE_SIZE,
+ WINDIVERT_PARAM_QUEUE_SIZE_MAX) ||
+ !WinDivertGetParam(handle[0], WINDIVERT_PARAM_QUEUE_SIZE, &val) ||
+ val != WINDIVERT_PARAM_QUEUE_SIZE_MAX)
+ {
+ fprintf(stderr, "error: failed to set WINDIVERT_PARAM_QUEUE_SIZE "
+ "parameter (err = %d)\n", GetLastError());
+ goto failed;
+ }
+ if (!WinDivertSetParam(handle[0], WINDIVERT_PARAM_QUEUE_TIME,
+ WINDIVERT_PARAM_QUEUE_TIME_MAX) ||
+ !WinDivertGetParam(handle[0], WINDIVERT_PARAM_QUEUE_TIME, &val) ||
+ val != WINDIVERT_PARAM_QUEUE_TIME_MAX)
+ {
+ fprintf(stderr, "error: failed to set WINDIVERT_PARAM_QUEUE_TIME "
+ "parameter (err = %d)\n", GetLastError());
+ goto failed;
+ }
// (2) Create pended recv requests:
event[0] = CreateEvent(NULL, FALSE, FALSE, NULL);