Do not complete pause if we're not running
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
parent
7437155446
commit
34e61dc3b0
60
wintun.c
60
wintun.c
@ -799,9 +799,6 @@ static NTSTATUS
|
|||||||
TunDispatchWrite(_Inout_ TUN_CTX *Ctx, _Inout_ IRP *Irp)
|
TunDispatchWrite(_Inout_ TUN_CTX *Ctx, _Inout_ IRP *Irp)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
InterlockedIncrement64(&Ctx->ActiveNBLCount);
|
|
||||||
|
|
||||||
IO_STACK_LOCATION *Stack = IoGetCurrentIrpStackLocation(Irp);
|
IO_STACK_LOCATION *Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
ULONG Size = Stack->Parameters.Write.Length;
|
ULONG Size = Stack->Parameters.Write.Length;
|
||||||
if (Status = STATUS_INVALID_USER_BUFFER, (Size < TUN_EXCH_MIN_BUFFER_SIZE_WRITE || Size > TUN_EXCH_MAX_BUFFER_SIZE))
|
if (Status = STATUS_INVALID_USER_BUFFER, (Size < TUN_EXCH_MIN_BUFFER_SIZE_WRITE || Size > TUN_EXCH_MAX_BUFFER_SIZE))
|
||||||
@ -823,11 +820,6 @@ TunDispatchWrite(_Inout_ TUN_CTX *Ctx, _Inout_ IRP *Irp)
|
|||||||
if (Status = STATUS_INSUFFICIENT_RESOURCES, !Mdl)
|
if (Status = STATUS_INSUFFICIENT_RESOURCES, !Mdl)
|
||||||
goto cleanup_ExFreePoolWithTag;
|
goto cleanup_ExFreePoolWithTag;
|
||||||
|
|
||||||
KIRQL Irql = ExAcquireSpinLockShared(&Ctx->TransitionLock);
|
|
||||||
LONG Flags = InterlockedGet(&Ctx->Flags);
|
|
||||||
if (Status = STATUS_FILE_FORCED_CLOSED, !(Flags & TUN_FLAGS_PRESENT))
|
|
||||||
goto cleanup_ExReleaseSpinLockShared;
|
|
||||||
|
|
||||||
const UCHAR *BufferPos = BufferStart, *BufferEnd = BufferStart + Size;
|
const UCHAR *BufferPos = BufferStart, *BufferEnd = BufferStart + Size;
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
@ -852,24 +844,14 @@ TunDispatchWrite(_Inout_ TUN_CTX *Ctx, _Inout_ IRP *Irp)
|
|||||||
LONG NblCount = 0;
|
LONG NblCount = 0;
|
||||||
while (BufferEnd - BufferPos >= sizeof(TUN_PACKET))
|
while (BufferEnd - BufferPos >= sizeof(TUN_PACKET))
|
||||||
{
|
{
|
||||||
if (NblCount >= MAXLONG)
|
if (Status = STATUS_INVALID_USER_BUFFER, NblCount >= MAXLONG)
|
||||||
{
|
|
||||||
Status = STATUS_INVALID_USER_BUFFER;
|
|
||||||
goto cleanup_nbl_queues;
|
goto cleanup_nbl_queues;
|
||||||
}
|
|
||||||
|
|
||||||
TUN_PACKET *Packet = (TUN_PACKET *)BufferPos;
|
TUN_PACKET *Packet = (TUN_PACKET *)BufferPos;
|
||||||
if (Packet->Size > TUN_EXCH_MAX_IP_PACKET_SIZE)
|
if (Status = STATUS_INVALID_USER_BUFFER, Packet->Size > TUN_EXCH_MAX_IP_PACKET_SIZE)
|
||||||
{
|
|
||||||
Status = STATUS_INVALID_USER_BUFFER;
|
|
||||||
goto cleanup_nbl_queues;
|
goto cleanup_nbl_queues;
|
||||||
}
|
|
||||||
ULONG AlignedPacketSize = TunPacketAlign(sizeof(TUN_PACKET) + Packet->Size);
|
ULONG AlignedPacketSize = TunPacketAlign(sizeof(TUN_PACKET) + Packet->Size);
|
||||||
if (BufferEnd - BufferPos < (ptrdiff_t)AlignedPacketSize)
|
if (Status = STATUS_INVALID_USER_BUFFER, (BufferEnd - BufferPos < (ptrdiff_t)AlignedPacketSize))
|
||||||
{
|
|
||||||
Status = STATUS_INVALID_USER_BUFFER;
|
|
||||||
goto cleanup_nbl_queues;
|
goto cleanup_nbl_queues;
|
||||||
}
|
|
||||||
|
|
||||||
EtherTypeIndex Index;
|
EtherTypeIndex Index;
|
||||||
if (Packet->Size >= 20 && Packet->Data[0] >> 4 == 4)
|
if (Packet->Size >= 20 && Packet->Data[0] >> 4 == 4)
|
||||||
@ -884,11 +866,8 @@ TunDispatchWrite(_Inout_ TUN_CTX *Ctx, _Inout_ IRP *Irp)
|
|||||||
|
|
||||||
NET_BUFFER_LIST *Nbl = NdisAllocateNetBufferAndNetBufferList(
|
NET_BUFFER_LIST *Nbl = NdisAllocateNetBufferAndNetBufferList(
|
||||||
Ctx->NBLPool, 0, 0, Mdl, (ULONG)(Packet->Data - BufferStart), Packet->Size);
|
Ctx->NBLPool, 0, 0, Mdl, (ULONG)(Packet->Data - BufferStart), Packet->Size);
|
||||||
if (!Nbl)
|
if (Status = STATUS_INSUFFICIENT_RESOURCES, !Nbl)
|
||||||
{
|
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
goto cleanup_nbl_queues;
|
goto cleanup_nbl_queues;
|
||||||
}
|
|
||||||
|
|
||||||
Nbl->SourceHandle = Ctx->MiniportAdapterHandle;
|
Nbl->SourceHandle = Ctx->MiniportAdapterHandle;
|
||||||
NdisSetNblFlag(Nbl, EtherTypeConstants[Index].NblFlags);
|
NdisSetNblFlag(Nbl, EtherTypeConstants[Index].NblFlags);
|
||||||
@ -901,29 +880,25 @@ TunDispatchWrite(_Inout_ TUN_CTX *Ctx, _Inout_ IRP *Irp)
|
|||||||
BufferPos += AlignedPacketSize;
|
BufferPos += AlignedPacketSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ULONG)(BufferPos - BufferStart) != Size)
|
if (Status = STATUS_INVALID_USER_BUFFER, (ULONG)(BufferPos - BufferStart) != Size)
|
||||||
{
|
|
||||||
Status = STATUS_INVALID_USER_BUFFER;
|
|
||||||
goto cleanup_nbl_queues;
|
goto cleanup_nbl_queues;
|
||||||
}
|
|
||||||
Irp->IoStatus.Information = Size;
|
Irp->IoStatus.Information = Size;
|
||||||
|
|
||||||
if (!NblCount)
|
if (Status = STATUS_SUCCESS, !NblCount)
|
||||||
{
|
goto cleanup_nbl_queues;
|
||||||
Status = STATUS_SUCCESS;
|
|
||||||
goto cleanup_ExReleaseSpinLockShared;
|
KIRQL Irql = ExAcquireSpinLockShared(&Ctx->TransitionLock);
|
||||||
}
|
LONG Flags = InterlockedGet(&Ctx->Flags);
|
||||||
if (!(Flags & TUN_FLAGS_RUNNING))
|
if ((Status = STATUS_FILE_FORCED_CLOSED, !(Flags & TUN_FLAGS_PRESENT)) ||
|
||||||
|
(Status = STATUS_SUCCESS, !(Flags & TUN_FLAGS_RUNNING)))
|
||||||
{
|
{
|
||||||
InterlockedAdd64((LONG64 *)&Ctx->Statistics.ifInDiscards, NblCount);
|
InterlockedAdd64((LONG64 *)&Ctx->Statistics.ifInDiscards, NblCount);
|
||||||
InterlockedAdd64((LONG64 *)&Ctx->Statistics.ifInErrors, NblCount);
|
InterlockedAdd64((LONG64 *)&Ctx->Statistics.ifInErrors, NblCount);
|
||||||
Status = STATUS_SUCCESS;
|
goto cleanup_ExReleaseSpinLockShared;
|
||||||
goto cleanup_nbl_queues;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InterlockedAdd64(&Ctx->ActiveNBLCount, NblCount);
|
InterlockedAdd64(&Ctx->ActiveNBLCount, NblCount + 1);
|
||||||
*MdlRefcount = NblCount;
|
*MdlRefcount = NblCount;
|
||||||
|
|
||||||
for (EtherTypeIndex Index = EtherTypeIndexStart; Index < EtherTypeIndexEnd; Index++)
|
for (EtherTypeIndex Index = EtherTypeIndexStart; Index < EtherTypeIndexEnd; Index++)
|
||||||
{
|
{
|
||||||
if (!NblQueue[Index].Head)
|
if (!NblQueue[Index].Head)
|
||||||
@ -937,10 +912,12 @@ TunDispatchWrite(_Inout_ TUN_CTX *Ctx, _Inout_ IRP *Irp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ExReleaseSpinLockShared(&Ctx->TransitionLock, Irql);
|
ExReleaseSpinLockShared(&Ctx->TransitionLock, Irql);
|
||||||
TunCompleteRequest(Ctx, Irp, STATUS_SUCCESS, IO_NETWORK_INCREMENT);
|
|
||||||
TunCompletePause(Ctx, TRUE);
|
TunCompletePause(Ctx, TRUE);
|
||||||
|
TunCompleteRequest(Ctx, Irp, STATUS_SUCCESS, IO_NETWORK_INCREMENT);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
cleanup_ExReleaseSpinLockShared:
|
||||||
|
ExReleaseSpinLockShared(&Ctx->TransitionLock, Irql);
|
||||||
cleanup_nbl_queues:
|
cleanup_nbl_queues:
|
||||||
for (EtherTypeIndex Index = EtherTypeIndexStart; Index < EtherTypeIndexEnd; Index++)
|
for (EtherTypeIndex Index = EtherTypeIndexStart; Index < EtherTypeIndexEnd; Index++)
|
||||||
{
|
{
|
||||||
@ -951,14 +928,11 @@ cleanup_nbl_queues:
|
|||||||
NdisFreeNetBufferList(Nbl);
|
NdisFreeNetBufferList(Nbl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cleanup_ExReleaseSpinLockShared:
|
|
||||||
ExReleaseSpinLockShared(&Ctx->TransitionLock, Irql);
|
|
||||||
NdisFreeMdl(Mdl);
|
NdisFreeMdl(Mdl);
|
||||||
cleanup_ExFreePoolWithTag:
|
cleanup_ExFreePoolWithTag:
|
||||||
ExFreePoolWithTag(BufferStart, TUN_MEMORY_TAG);
|
ExFreePoolWithTag(BufferStart, TUN_MEMORY_TAG);
|
||||||
cleanup_CompleteRequest:
|
cleanup_CompleteRequest:
|
||||||
TunCompleteRequest(Ctx, Irp, Status, IO_NO_INCREMENT);
|
TunCompleteRequest(Ctx, Irp, Status, IO_NO_INCREMENT);
|
||||||
TunCompletePause(Ctx, TRUE);
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user