Commit Graph

165 Commits

Author SHA1 Message Date
Jason A. Donenfeld
1d96af3b98 Account for device removal before initialization
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-07-03 08:50:30 +00:00
Jason A. Donenfeld
248d4268df Use synchronize_rcu()-like semantics for exclusive transition lock
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-07-03 08:50:30 +00:00
Jason A. Donenfeld
33cac1114c Fix up comment about replacement for ->Reserved
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-07-03 08:50:30 +00:00
Jason A. Donenfeld
ae6e72a39e Simplify IRP processing after mapping
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-07-03 08:50:30 +00:00
Jason A. Donenfeld
d82a68f830 Allow buffer mapping to happen concurrently
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-07-03 08:50:30 +00:00
Jason A. Donenfeld
88bde5b28e Correct and simplify page locking
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-07-03 08:50:30 +00:00
Jason A. Donenfeld
3d84bddcc0 Separate out MJ_CLOSE
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-07-03 08:50:30 +00:00
Jason A. Donenfeld
de481cdb12 Manually clean up ugly corners 2019-07-03 08:50:30 +00:00
Jason A. Donenfeld
5ec565c7e8 Improve designated initializers
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-07-03 08:50:30 +00:00
Jason A. Donenfeld
5bbff1026f Add NDIS team's clang-format conventions
This needs clang-format 9. This reveals a lot of other things we should
clean up.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Link: https://community.osr.com/discussion/291376/clang-format-and-driver-code
2019-07-03 08:50:30 +00:00
Jason A. Donenfeld
007ea09d1b Map user buffer only once
This avoids needless page table modifications and also lets us enforce
having writable pages.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-07-03 08:50:30 +00:00
Jason A. Donenfeld
d50cab5732 Consider receive NBLs to be immutable
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-07-03 08:50:30 +00:00
Jason A. Donenfeld
be8d2cb071 Avoid allocating second MDL
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-07-03 08:50:30 +00:00
Simon Rozman
de2c48db84 Make NDIS 6.80 compliant
Implement support for synchronous OID requests and declare the Wintun as
NDIS 6.80 compliant.

https://docs.microsoft.com/en-us/windows-hardware/drivers/network/introduction-to-ndis-6-80

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-07-03 08:50:30 +00:00
Simon Rozman
c394368e88 Declare NDIS 6.70 compliant
After confirming with Microsoft Documentation that Wintun is already
NDIS 6.70 compliant, we declare it so.

Furthermore, determine NDIS version bounds from NDISxxx_MINIPORT
automatically.

https://docs.microsoft.com/en-us/windows-hardware/drivers/network/introduction-to-ndis-6-40
https://docs.microsoft.com/en-us/windows-hardware/drivers/network/introduction-to-ndis-6-50
https://docs.microsoft.com/en-us/windows-hardware/drivers/network/introduction-to-ndis-6-60
https://docs.microsoft.com/en-us/windows-hardware/drivers/network/introduction-to-ndis-6-70

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-07-03 08:50:30 +00:00
Jason A. Donenfeld
e4831b2011 Use ULONG instead of ptrdiff_t for length measurement
Even though we're comparing this with a ptrdiff_t in one place and
adding it to a void* in another place, it's still a length and as such
should be a size_t, which I guess in our weird universe here is a ULONG.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-06-21 12:20:33 +02:00
Jason A. Donenfeld
dea5bfa2d2 Synchronize accesses to MiniportAdapterHandle
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-06-20 15:17:36 +00:00
Simon Rozman
17572da83e Adopt "Tun" namespace at global AdapterCount variable
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-20 13:42:35 +02:00
Simon Rozman
faf810e8cb Fix NdisQueryMdl() NULL-buffer check
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-20 12:00:21 +02:00
Simon Rozman
9514ef37b3 Save some valuable lessons learned on Windows internals
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-20 11:54:58 +02:00
Simon Rozman
da3caadf48 Accept IRP_MJ_WRITE when paused but silently drop the packets
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-20 11:54:58 +02:00
Simon Rozman
7004db43a7 Support surprise removal
WHLK 1903 CHAOS tests are reporting lots of issues regarding surprise
removal misbehavior:

WDTF_PNP: INFO  : Result: TestSurpriseRemove operation timed out waiting
   for IRP_MN_REMOVE_DEVICE..
WDTF_PNP: ERROR : Result: Failed to receive IRP_MN_REMOVE_DEVICE after
   receiving IRP_MN_SURPRISE_REMOVAL. Ensure that there are no open
   handles or references to the test device (in user mode or in kernel
   mode) preventing IRP_MN_REMOVE_DEVICE from being sent. You may need
   to terminate any processes or services that may have open user mode
   handles to this device.  ( 80004005 ).

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-20 11:54:58 +02:00
Simon Rozman
85b4a769cf Replace PnP notifications with IRP_MJ_PNP dispatch handler
By replacing the NDIS' IRP_MJ_PNP dispatch handler we get the first
chance to clear the NBL queue to make NDIS proceed to TunPause() on
device removal.

This method is simpler than PnP notifications and we are chasing
surprise removal issues in WHLK tests. If this works, I'll hopefully
come back and update this commit message.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-20 11:54:58 +02:00
Simon Rozman
6b0293b18b Distinguish NDIS_STATUS and NTSTATUS
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-20 11:54:58 +02:00
Simon Rozman
b07c268e0c Implement proper PnP notification re-registration on canceled removal
The Microsoft Documentation is clear:

"The PnP manager can still call the driver's notification callback
routine, but in such calls the file object in the NotificationStructure
is not valid."[1]

Therefore, we must not touch the notification->FileObject in
GUID_TARGET_DEVICE_REMOVE_CANCELLED.

"Because the driver closed the previous registration handle in response
to the query-remove notification, the driver must open a new handle. The
driver must:

1. Remove the old registration with IoUnregisterPlugPlayNotification.
2. Open a new handle to the device.
3. Reregister for notification on the new handle with
   IoRegisterPlugPlayNotification."

Therefore, let's do it. Unfortunately, in order to implement this, we
must save the driver object and device symbolic name.

[1](https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/handling-a-guid-target-device-query-remove-event)
[2](https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/handling-a-guid-target-device-remove-cancelled-event)

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-20 11:54:58 +02:00
Simon Rozman
838251780e Rename ActiveTransactionCount to ActiveNBLCount
As ActiveTransacrionCount is all about counting NBLs in flight (or just
about to push some more NBLs), rename it to a more suitable name.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-20 11:54:58 +02:00
Simon Rozman
e3dfeeb2be Reuse Device.RefCount value to prevent duplicate status indications
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-20 11:54:57 +02:00
Simon Rozman
54ee02ae34 Fix the cleanup order in TunDispatchWrite()
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-20 11:54:57 +02:00
Simon Rozman
dc7a6fca11 Cleanup ref-counting overflow asserts
Asserting on 63-bit overflow seems a bit excessive.

While 31-bit overflow is more likely to happen, we should introduce a
real check if we are concerned about it. Rather than using an ASSERT in
Debug configuration run by probably nobody else but me.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-20 11:54:57 +02:00
Simon Rozman
70fcfdc85d Add missing state transition lock
When we are transitioning to a state that suspends some operations, we
must get an exclusive transition lock to wait for all operations that
have a shared transition lock. And TunHaltEx() is no exception.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-20 11:54:57 +02:00
Simon Rozman
60e103cad3 Revise adapter state checking
TunCheckForPause() was inlined and adjusted: it had two calls with two
potential new ones, but each call would have a slightly different
optimal variant: some with ActiveTransactionCount increment, others
without; some with Device.RefCount check, others without... No two
particular use cases were completely identical:

1. TunSendNetBufferLists:
   - requires ActiveTransactionCount increment
   - requires Device.RefCount > 0 check
   - reports NDIS_STATUS in case of rejection
2. IRP_MJ_READ:
   - no ActiveTransactionCount increment
   - no Device.RefCount > 0 check, as IRP_MJ_READ implies it
   - reports NTSTATUS in case of rejection
3. IRP_MJ_WRITE:
   - requires ActiveTransactionCount increment
   - no Device.RefCount > 0 check, as IRP_MJ_WRITE implies it
   - reports NTSTATUS in case of rejection
4. IRP_MJ_CREATE:
   - no ActiveTransactionCount increment
   - no Device.RefCount > 0 check to allow initial client connection
   - reports NTSTATUS in case of rejection, with slightly different
     status codes than IRP_MJ_READ and IRP_MJ_WRITE.

TUN_FLAGS_ENABLED was renamed to TUN_FLAGS_RUNNING: enabled/disabled
adapter means initialized&running/paused&halted in Windows world.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-20 11:54:57 +02:00
Simon Rozman
8162297c15 Count active transactions in NBLs rather than IRPs in receive direction
This makes ActiveTransactionCount a sum of:
- 1: initialized in TunRestart()
- count of NBLs in send queue
- count of NBLs in receive queue
- TunSendNetBufferLists() unfinished
- IRP_MJ_WRITE unfinished

Mind that we do not need to explicitly check for TUN_FLAGS_PRESENT early
in IRP_MJ_WRITE as it is implicitly checked by TunCheckForPause() along
with other flags required to run the packet flow. The later is actually
more correct by being shared-locked by the transition lock.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-20 11:54:57 +02:00
Simon Rozman
47cde0f340 Cleanup adapter power monitoring
Wintun adapter is always paused before transition to a low-power state.
Even on NDIS 6.30 we do not specify the NDIS_MINIPORT_ATTRIBUTES_NO_-
PAUSE_ON_SUSPEND flag. Since OID_PNP_SET_POWER does not do anything else
that TunPause() already takes care of it is redundant. The
TUN_FLAGS_ENABLED and TUN_FLAGS_POWERED were also mostly identical.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-20 11:54:56 +02:00
Simon Rozman
bce44d30e4 Use more appropriate status when rejecting NBLs with no client connected
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-20 11:54:56 +02:00
Simon Rozman
2392d173e7 Restore adapter on PnP remove-cancel and reuse notification file object
In case target device removal was canceled, the adapter is now restored
to present state. This is a part of research why Wintun adapters are
misbehaving in some WHLK tests.

PnP notifications already provide FILE_OBJECT of the device we are
monitoring. We don't need to store it in adapter context.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-20 11:54:56 +02:00
Simon Rozman
5c8dafcb3f Simplify state machine
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-20 11:54:56 +02:00
Sergei Mileshin
a530bb1b84 Set deny-all DACL instead of removing symlink on halting
Deleting symbolic link on device removal only still makes it possible to
open it from the real path.

Setting the deny-all DACL instead is a more reliable way of preventing
clients reopening the device when it is being removed.

Signed-off-by: Sergei Mileshin <msvsysproger@gmail.com>
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-20 11:53:08 +02:00
Simon Rozman
2e744ebde5 Revise buffer size calculation to work across 32/64-bit boundary
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-10 16:59:03 +02:00
Jason A. Donenfeld
12e9f53fe2 Do not take handle reference with verifier enabled
This is actually very much wrong. In fact, it's bound to create all
sorts of nasty issues. But without it, we can't use the reference
function to check the validity of a potentially invalid handle while the
verifier is enabled.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-06-08 09:04:32 +00:00
Simon Rozman
c848006144 Clean TunWaitForReferencesToDropToZero()
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-08 08:14:07 +02:00
Simon Rozman
5c2a9a991e Refactor IRP_MJ_CLOSE TransitionLock unlocking
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-08 08:14:07 +02:00
Simon Rozman
ced1bcdd52 Reorder source code
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-07 13:05:57 +02:00
Simon Rozman
2a5da5c58f Revise constants requiring network-byte order
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-07 12:28:07 +02:00
Simon Rozman
3306c6ec6c Use per-protocol NBL lists on write
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-07 12:28:07 +02:00
Simon Rozman
9504191ba0 Unify interlocked reference counting
- Only positive values are valid.
- Add missing overflow assert checks
- Fix spacing

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-07 12:28:07 +02:00
Simon Rozman
cc3c1fefcb Check number of packets in exchange buffer for overflow
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-07 12:28:07 +02:00
Simon Rozman
fd6300dc6f Reduce IRP reference counter to 32-bit
This unifies 32 and 64-bit platforms to both use only one PVOID in IRP
extension now.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-07 12:28:07 +02:00
Simon Rozman
14617f118f Revise TransitionLock usage
The exclusive TransitionLock hold is required with all state changes
that:
- Switch adapter TUN_STATE_RUNNING -> TUN_STATE_PAUSING
- Switch media status to MediaConnectStateDisconnected
- Switch adapter to low-power state NdisDeviceStateD1-n

Because, those transitions require NBL queue to clear and stay empty.

The parts of the code that fill the NBL queue get a shared lock
before state check and release it after they are done filling the queue.

This prevents intermediate state changes while filling, and the queue
clearing parts of the code to wait for the filling parts to prevent a
race.

Starting up adapter (TUN_STATE_RESTARTING -> TUN_STATE_RUNNING,
MediaConnectStateDisconnected -> MediaConnectStateConnected, or
NdisDeviceStateDx -> NdisDeviceStateD0) does not require emptying NBL
queue and it does not need TransitionLock held.

This commit also moves TunQueueClear() out of exclusive TransitionLock
hold, because it is not necessary.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-07 12:28:07 +02:00
Simon Rozman
486b1c374b Simplify NdisMSendNetBufferListsComplete() flags
At the time of the NdisMSendNetBufferListsComplete() call, we're always
at Dispatch IRQL, because of ctx->TransitionLock being held.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-07 12:28:07 +02:00
Jason A. Donenfeld
ea26894a99 Delete symlink before forcing handles closed 2019-06-07 12:28:07 +02:00
Jason A. Donenfeld
86e425a0dc Document TransitionLock semantics and RCU intent
Rumor has it, NT is one of the few kernels that actually has RCU
(alongside Linux and maybe some IBM things). So maybe if we ever learn
how to use NT's RCU functionality, we'll be able to replace this with
that.
2019-06-07 12:28:07 +02:00
Jason A. Donenfeld
888cad7f2a Delay exit from HaltEx
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-06-07 12:28:07 +02:00
Simon Rozman
c19da2a99e Revise TunCompleteRequest() and make it universal
TunCompleteRequest() no longer sets Information field in IRP and allows
to specify custom priority boost. This makes it suitable replacement for
all "set status; complete request; release remove lock"-tuples
throughout the code.

Functional changes in this patch:

- We no longer reset Information field to 0 for canceled IRPs. In other
  words: ReadFile() of a canceled IRP will get the number of bytes read
  before request was canceled in the lpNumberOfBytesRead, instead of
  always 0.

- After write is complete, we boost user thread priority by +2
  (IO_NETWORK_INCREMENT).

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-03 10:53:11 +00:00
Simon Rozman
b9d0b301b8 Revise IRP_MJ_WRITE error reporting
The NDIS reason why TunCheckForPause() reported the adapter unavailable,
might not make much sense to a client. In case adapter is paused or in
low power state, the STATUS_CANCELLED (ERROR_OPERATION_ABORTED) is
returned.

Exchange buffer size overflow - total TUN_EXCH_MAX_IP_PACKET_SIZE or
individual packet - rejects entire exchange buffer now.

Exchange buffers containing non-IPv4 or non-IPv6 packets are now
rejected as a whole.

Allocation errors while preparing NBLs from the exchange buffer are now
considered fatal.

Ensure write buffer has at least sizeof(TUN_PACKET) left, or reject
entire exchange buffer.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-03 10:53:11 +00:00
Simon Rozman
adefe271a1 Switch to pending writes
Commentary from Jason:

Problem statement:
  We call IoCompleteRequest(Irp) immediately after
  NdisMIndicateReceiveNetBufferLists, which frees Irp->MdlAddress.
  Since we've just given the same memory to
  NdisMIndicateReceiveNetBufferLists (in a different MDL), we wind up
  freeing the memory before NDIS finishes processing them.

Fix possibility 1:
  Move IoCompleteRequest(Irp) to TunReturnNetBufferLists. This requires
  reference counting how many NBLs are currently in flight that are
  using an IRP. When that drops to zero, we can call IoCompleteRequest
  (Irp).
Problem:
  This means we have to block future wireguard-go Writes until *all*
  NBLs have completed processing in the networking stack. Is that safe
  to do? Will that introduce latency? Can userspace processes sabotage
  it by refusing to read from a TCP socket buffer? We don't know enough
  about how NdisMIndicateReceiveNetBufferLists works to assess its
  characteristics here.

Fix possibility 2:
  Use NDIS_RECEIVE_FLAGS_RESOURCES, so that
  NdisMIndicateReceiveNetBufferLists makes a copy, and then we'll simply
  free everything immediately after. This is slow, and it could
  potentially lead to wireguard-go making the kernel allocate lots of
  memory in the case that NdisAllocateNetBufferAndNetBufferList doesn't
  ratelimit its creation in the same way Linux's skb_alloc does.
  However, it does make the lifetime of Irps shorter, which is easier to
  analyze, and it might lead to better latency, since we don't need to
  wait until userspace sends its next packets, so long as Ndis'
  ingestion queue doesn't become too large.

This commit switches from (2) to (1).

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-03 10:53:11 +00:00
Jason A. Donenfeld
b6cc08d574 Force handles closed if required
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-06-03 10:53:11 +00:00
Jason A. Donenfeld
44ddfbe357 Clear NBLs on PnP notification
Otherwise Pause&Halt aren't called.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-06-03 10:53:11 +00:00
Simon Rozman
156294bb6e Clear internal NBL queue on transition to MediaConnectStateDisconnected
When adapter is in disconnected state, NDIS does not send it any NBLs.
After transition to disconnected state it should return all pending NBLs
back to NDIS, otherwise a deadlock occurs on pause attempt later.

Likewise when the adapter is in low-power state.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-03 10:53:11 +00:00
Simon Rozman
17e9e17826 Upgrade to VS2019 and update CSQ locking for analysis
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-06-03 12:47:05 +02:00
Simon Rozman
207144965a Revise OID request return statuses
MINIPORT_OID_REQUEST handler should return:
- NDIS_STATUS_NOT_SUPPORTED => NDIS_STATUS_INVALID_OID if the OID
  request was not recognized.
- NDIS_STATUS_INVALID_OID => NDIS_STATUS_NOT_SUPPORTED if particular OID
  is not supported.
- NDIS_STATUS_INVALID_LENGTH => NDIS_STATUS_BUFFER_TOO_SHORT if output
  buffer is too short.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-12 15:35:39 +02:00
Simon Rozman
207e1c4896 Assist SDV in realizing that non-NULL IRP => non-NULL buffer
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-12 15:35:39 +02:00
Simon Rozman
4c47c2fbbf TunCanFitIntoIrp => TunWontFitIntoIrp
The function name was inverted and misleading.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-12 15:35:39 +02:00
Simon Rozman
50a09cad71 Move #define NDIS... to ClCompile/PreprocessorDefinitions
These constants must be defined in the project file in order for Static
Driver Verifier to work correctly. Otherwise, SDV returns error MSB3073:
The command "staticdv /check:*" exited with code -1.

Since the ClCompile/PreprocessorDefinitions management became
cumbersome, all platform and configuration independent MSVC settings
were rearranged in a single <ItemDefinitionGroup>, while platform
independent but configuration dependent were rearranged to a conditional
<ItemDefinitionGroup>(s).

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-12 15:35:38 +02:00
Simon Rozman
9cda719d85 Fix indentation
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-12 08:09:33 +02:00
Simon Rozman
d9831a9197 InterlockedAdd/Subtract(val, 1) => InterlockedIncrement/Decrement(val)
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-12 08:09:33 +02:00
Simon Rozman
1770ac146d Wait for handles to close before returning from TunHaltEx()
This allows Windows to unload the driver from memory when the last
adapter is halted. Hence driver can be updated without a reboot.

Unfortunately, a client refusing to close device pipe handle can block
adapter halting indefinitely. So, we now have a new challenge to
address.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-11 19:30:23 +02:00
Simon Rozman
ca79fd1368 Revise I/O errors
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-11 19:30:23 +02:00
Simon Rozman
d3cc0570de Initialize ActiveTransactionCount to 1
This always sets the reference counter to predictable state on resume
and eliminates the need to bump it on pausing.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-11 19:30:23 +02:00
Simon Rozman
5cecd1536c Clean excessive miniport adapter state checks
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-11 14:08:20 +02:00
Simon Rozman
6d230d616e Clean unneeded TunSetOptions()
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-11 14:08:20 +02:00
Simon Rozman
83d3e175d9 Merge TUN_CTX and TUN_DEVEXT and save entire context in device extension
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-10 13:45:36 +02:00
Simon Rozman
cb741f4d1e Cancel pending IRPs and selectively block new ones when halted
This unblocks waiting clients and prevents new handles to be opened on
device pipe while allowing graceful cleanup.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-10 13:43:13 +02:00
Simon Rozman
df23e41a7f Fix spacing
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-10 13:43:13 +02:00
Simon Rozman
04f2cc318e Migrate device-specific data to device extension
This allows to keep all device pipe specific information to persist as
long as device is in use.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-09 15:20:03 +02:00
Simon Rozman
2fa408a92f Rename TunDriverUnload() => TunUnload()
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-09 15:17:02 +02:00
Simon Rozman
b5cf1f927b Adjust OID_GEN_TRANSMIT_BUFFER_SPACE hint properly
When transmitting, the adapter can actually take TUN_QUEUE_MAX_NBLS
packets at a time.

When receiving, the adapter gets up to TUN_EXCH_MAX_PACKETS packets at
a time.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-05 20:23:23 +02:00
Simon Rozman
5b529a9c50 Stop rewarding user thread on IRP buffer error
When driver cannot access IRP's MDL it shouldn't grand calling user
thread any priority boost. The IO_NETWORK_INCREMENT was overlooked on
copy&paste.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-05 20:23:22 +02:00
Simon Rozman
1369525e3a Don't cancel pending IRPs on adapter pause
Pausing an adapter requires it to stop processing network traffic. We
may still process I/O of the adapter device pipe.

By canceling all pending IRPs and refusing to serve any new IRPs on
adapter pause, we forcibly cut the client off to release resources and
allow graceful driver unload. This enabled a hot driver update without a
restart.

However, using a modified Wintun driver for NDISTEST utility the client
didn't behave the same way, keeping handles open when NDISTEST paused
Wintun adapter. The pause reset ctx->Device.RefCount to 0 which caused
negative reference count when client finally decided to close the Wintun
adapter device pipe handle.

Rather than introducing a complex fix to the adapter device pipe
reference counting, this commit simplifies it by allowing IRPs even when
adapter is paused. IRP_MJ_WRITE is an exception: client cannot write to
the adapter when it's paused.

This allows the client to stay connected, reduces ActiveTransactionCount
to NBL counting only, and cancels pending IRPs much later in
TunHaltEx().

Since there is still I/O going on after TunHaltEx() returns now, the
driver is not unloaded from memory. This prevents driver updates without
a reboot. How can one gracefully terminate I/O in TunHaltEx() remains a
subject of further study.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-05 20:23:22 +02:00
Simon Rozman
7176236b4e Mark canceled NBL status as NDIS_STATUS_SEND_ABORTED
NDIS expects this from a miniport driver.

References: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ndis/nc-ndis-miniport_cancel_send
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-05 12:57:31 +02:00
Simon Rozman
bf48214c8c Upgrade OID_GEN_XMIT_OK and OID_GEN_RCV_OK to support 64-bit counters
This commit addresses issues reported by NDISTEST/1c_64bitoids.

It also revises the OID request writing, as adaptive 32/64-bit responses
required by OID_GEN_XMIT_OK and OID_GEN_RCV_OK would grow the current
TunOidQuery() design quite complex and introduce duplicated code.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-05 12:57:22 +02:00
Simon Rozman
1c13736068 Access PowerState interlocked
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-05 12:51:15 +02:00
Simon Rozman
480000f429 Revert "Implement NDIS 6.30's NDIS_MINIPORT_ATTRIBUTES_NO_PAUSE_ON_SUSPEND"
This reverts commit 683cf83befbc8d95de3b13994851087306b19963.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-03 05:47:47 +02:00
Simon Rozman
1b9fee728b Upgrade NDIS_PM_CAPABILITIES to NDIS 6.30
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-03 05:47:47 +02:00
Simon Rozman
9436da8f7e Report correct NDIS version to NdisMRegisterMiniportDriver
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-03 05:47:47 +02:00
Simon Rozman
b6056b95d3 Add extra ASSERT to check PoweredTransactionCount is 0 on power-on
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-03 05:47:47 +02:00
Simon Rozman
e7d5cdc4f0 Implement NDIS 6.30's NDIS_MINIPORT_ATTRIBUTES_NO_PAUSE_ON_SUSPEND
NDIS >=6.30 allows bringing adapter to low-power state without pausing
it. As Wintun's pause cancels all pending IRP and we want to keep
disturbing client to a minimum, OID_PNP_SET_POWER cancels pending NBLs
and wait for active NBLs to finish only.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-03 03:37:24 +02:00
Simon Rozman
58900a4841 Implement dynamic NDIS 6.30 detection
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-03 03:37:24 +02:00
Simon Rozman
934923bbc1 Change TunOidSet/TunOidQuery() parameters
All parameters to TunOidSet/TunOidQuery() are contained inside a
NDIS_OID_REQUEST struct. But, the main rationale behind this commit is
that OID_PNP_SET_POWER set request will require pointer to original
NDIS_OID_REQUEST struct for NdisMOidRequestComplete() call, should we
want to implement pending PnP power-down.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-03 03:37:24 +02:00
Simon Rozman
8eefe85bb2 Move packet queue clearing into a reusable function
We will need this in OID_PNP_SET_POWER.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-04-03 03:37:23 +02:00
Jason A. Donenfeld
bba0f6aecf Do not call NdisMPauseComplete before TunPause returns
Otherwise we trigger a bugcheck on Server 2019.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-03-29 21:42:46 +01:00
Simon Rozman
7b3ea2a8a9 Reintroduce outgoing statistics
Outgoing statistics-keeping was accidentally dropped in
ed93692ca0049123979e0497aa3c4a4698f844cd. This commit reintroduces it.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-03-29 16:23:24 +01:00
Simon Rozman
cf01a7ded2 Use tabs for indentation and spaces for horizontal alignment
Screen is a valuable real-estate on small displays or when working in
less than maximized or full-screen Visual Studio IDE.

This commit replaces tabulators used for horizontal alignment with
spaces, and stops imposing 8-space tabulators on everyone.

Signed-off-by: Simon Rozman <simon@rozman.si>
2019-03-29 06:05:17 +01:00
Simon Rozman
5e5cb74553 Limit minimum size of exchange buffer
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-03-28 12:08:14 +01:00
Simon Rozman
6085957d9d Check buffer for oversize after MDL size consultation
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-03-28 11:48:01 +01:00
Simon Rozman
69d6f003e4 Clean TunQueueProcess()
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-03-28 11:48:01 +01:00
Simon Rozman
745acc8b95 Tighten code analysis annotations
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-03-28 11:22:16 +01:00
Simon Rozman
49847b5508 Skip IRPs we fail to get MDL access from
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-03-28 11:12:59 +01:00
Jason A. Donenfeld
f0275285a3 Skip impossibly large NBs when removing
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-03-28 09:11:06 +01:00
Jason A. Donenfeld
64c408a2e4 Don't discard unfitting NBLs and fix prepend ref counting
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-03-28 08:30:37 +01:00
Simon Rozman
9294d4b498 Fix uninitialized status and remove redundant locking in TunQueueProcess
Signed-off-by: Simon Rozman <simon@rozman.si>
2019-03-28 07:41:44 +01:00