diff --git a/Driver.cpp b/Driver.cpp index 97c0e65..01f343f 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -261,6 +261,45 @@ OvpnSetMode(POVPN_DEVICE device, WDFREQUEST request) return status; } +static NTSTATUS +OvpnStopVPN(_In_ POVPN_DEVICE device) +{ + LOG_ENTER(); + + KIRQL kirql = ExAcquireSpinLockExclusive(&device->SpinLock); + PWSK_SOCKET socket = device->Socket.Socket; + device->Socket.Socket = NULL; + + OvpnFlushPeers(device); + + RtlZeroMemory(&device->Socket.TcpState, sizeof(OvpnSocketTcpState)); + RtlZeroMemory(&device->Socket.UdpState, sizeof(OvpnSocketUdpState)); + + ExReleaseSpinLockExclusive(&device->SpinLock, kirql); + + if (socket != NULL) { + LOG_IF_NOT_NT_SUCCESS(OvpnSocketClose(socket)); + } + + // flush buffers in control queue so that client won't get control channel messages from previous session + while (LIST_ENTRY* entry = OvpnBufferQueueDequeue(device->ControlRxBufferQueue)) { + OVPN_RX_BUFFER* buffer = CONTAINING_RECORD(entry, OVPN_RX_BUFFER, QueueListEntry); + // return buffer back to pool + OvpnRxBufferPoolPut(buffer); + } + + WDFREQUEST request; + while (NT_SUCCESS(WdfIoQueueRetrieveNextRequest(device->PendingReadsQueue, &request))) { + ULONG_PTR bytesCopied = 0; + LOG_INFO("Cancel IO request from manual queue"); + WdfRequestCompleteWithInformation(request, STATUS_CANCELLED, bytesCopied); + } + + LOG_EXIT(); + + return STATUS_SUCCESS; +} + EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL OvpnEvtIoDeviceControl; _Use_decl_annotations_ @@ -288,7 +327,7 @@ OvpnEvtIoDeviceControl(WDFQUEUE queue, WDFREQUEST request, size_t outputBufferLe break; case OVPN_IOCTL_DEL_PEER: - status = OvpnPeerDel(device); + status = OvpnStopVPN(device); break; case OVPN_IOCTL_START_VPN: @@ -347,8 +386,7 @@ VOID OvpnEvtFileCleanup(WDFFILEOBJECT fileObject) { POVPN_DEVICE device = OvpnGetDeviceContext(WdfFileObjectGetDevice(fileObject)); - // peer might already be deleted - (VOID)OvpnPeerDel(device); + (VOID)OvpnStopVPN(device); if (device->Adapter != NULL) { OvpnAdapterSetLinkState(OvpnGetAdapterContext(device->Adapter), MediaConnectStateDisconnected); diff --git a/peer.cpp b/peer.cpp index a2fa688..4f36386 100644 --- a/peer.cpp +++ b/peer.cpp @@ -161,46 +161,6 @@ OvpnPeerNew(POVPN_DEVICE device, WDFREQUEST request) return status; } -_Use_decl_annotations_ -NTSTATUS -OvpnPeerDel(POVPN_DEVICE device) -{ - LOG_ENTER(); - - KIRQL kirql = ExAcquireSpinLockExclusive(&device->SpinLock); - - PWSK_SOCKET socket = device->Socket.Socket; - - device->Socket.Socket = NULL; - OvpnFlushPeers(device); - - RtlZeroMemory(&device->Socket.TcpState, sizeof(OvpnSocketTcpState)); - RtlZeroMemory(&device->Socket.UdpState, sizeof(OvpnSocketUdpState)); - - // OvpnSocketClose requires PASSIVE_LEVEL, so must release lock - ExReleaseSpinLockExclusive(&device->SpinLock, kirql); - - LOG_IF_NOT_NT_SUCCESS(OvpnSocketClose(socket)); - - // flush buffers in control queue so that client won't get control channel messages from previous session - while (LIST_ENTRY* entry = OvpnBufferQueueDequeue(device->ControlRxBufferQueue)) { - OVPN_RX_BUFFER* buffer = CONTAINING_RECORD(entry, OVPN_RX_BUFFER, QueueListEntry); - // return buffer back to pool - OvpnRxBufferPoolPut(buffer); - } - - WDFREQUEST request; - while (NT_SUCCESS(WdfIoQueueRetrieveNextRequest(device->PendingReadsQueue, &request))) { - ULONG_PTR bytesCopied = 0; - LOG_INFO("Cancel IO request from manual queue"); - WdfRequestCompleteWithInformation(request, STATUS_CANCELLED, bytesCopied); - } - - LOG_EXIT(); - - return STATUS_SUCCESS; -} - _Use_decl_annotations_ NTSTATUS OvpnPeerSet(POVPN_DEVICE device, WDFREQUEST request) { diff --git a/peer.h b/peer.h index fc780f8..11a80f8 100644 --- a/peer.h +++ b/peer.h @@ -59,11 +59,6 @@ _IRQL_requires_(PASSIVE_LEVEL) NTSTATUS OvpnPeerNew(_In_ POVPN_DEVICE device, WDFREQUEST request); -_Must_inspect_result_ -_IRQL_requires_(PASSIVE_LEVEL) -NTSTATUS -OvpnPeerDel(_In_ POVPN_DEVICE device); - _Must_inspect_result_ _Requires_exclusive_lock_held_(device->SpinLock) NTSTATUS