From 7afef3865f431a048276d862b5e575f6ca680e76 Mon Sep 17 00:00:00 2001 From: Ludvig Strigeus Date: Sun, 21 Oct 2018 23:35:40 +0200 Subject: [PATCH] Show error if tun queue grows too large. This happens because the TAP NDIS6 driver is buggy on Windows 7. --- installer/ChangeLog.txt | 2 ++ network_win32.cpp | 17 +++++++++++++++++ network_win32.h | 3 +++ 3 files changed, 22 insertions(+) diff --git a/installer/ChangeLog.txt b/installer/ChangeLog.txt index c585fa2..6942da7 100644 --- a/installer/ChangeLog.txt +++ b/installer/ChangeLog.txt @@ -22,6 +22,8 @@ Changes: 9.Resolve DNS queries using a background thread, to make it possible to interrupt slow DNS queries. 10.IPv6 endpoint was printed incorrectly on the Advanced tab +11.Show an error message and drop packets if the TUN queue grows + too large. This is a problem with the TAP NDIS6 driver on Win7. 2018-10-08 - TunSafe v1.4 diff --git a/network_win32.cpp b/network_win32.cpp index 45da5ee..5482523 100644 --- a/network_win32.cpp +++ b/network_win32.cpp @@ -26,6 +26,9 @@ enum { HARD_MAXIMUM_QUEUE_SIZE = 102400, MAX_BYTES_IN_UDP_OUT_QUEUE = 256 * 1024, MAX_BYTES_IN_UDP_OUT_QUEUE_SMALL = (256 + 64) * 1024, + + // On Windows 7 with NDIS6 sometimes the tun queue blows up. + HARD_MAXIMUM_TUN_QUEUE_SIZE = 16384, }; enum { @@ -1569,11 +1572,13 @@ bool TunWin32Adapter::RunPrePostCommand(const std::vector &vec) { TunWin32Iocp::TunWin32Iocp(DnsBlocker *blocker, TunsafeBackendWin32 *backend) : adapter_(blocker, backend->guid_), backend_(backend) { wqueue_end_ = &wqueue_; wqueue_ = NULL; + wqueue_size_ = 0; thread_ = NULL; completion_port_handle_ = NULL; packet_handler_ = NULL; exit_thread_ = false; + did_show_tun_queue_warning_ = false; } TunWin32Iocp::~TunWin32Iocp() { @@ -1716,6 +1721,7 @@ void TunWin32Iocp::ThreadMain() { pending_writes = wqueue_; wqueue_end_ = &wqueue_; wqueue_ = NULL; + wqueue_size_ = 0; mutex_.Release(); if (!pending_writes) break; @@ -1785,6 +1791,17 @@ void TunWin32Iocp::StopThread() { void TunWin32Iocp::WriteTunPacket(Packet *packet) { packet->next = NULL; mutex_.Acquire(); + if (wqueue_size_ >= HARD_MAXIMUM_TUN_QUEUE_SIZE) { + mutex_.Release(); + FreePacket(packet); + if (!did_show_tun_queue_warning_) { + did_show_tun_queue_warning_ = true; + RERROR("TUN Queue Overload! This might happen if you use the NDIS6 driver on Windows 7."); + } + return; + } + wqueue_size_++; + Packet *was_empty = wqueue_; *wqueue_end_ = packet; wqueue_end_ = &packet->next; diff --git a/network_win32.h b/network_win32.h index a75447f..78ce0c2 100644 --- a/network_win32.h +++ b/network_win32.h @@ -157,6 +157,9 @@ private: Mutex mutex_; bool exit_thread_; + bool did_show_tun_queue_warning_; + + int wqueue_size_; // All packets queued for writing Packet *wqueue_, **wqueue_end_;