From bd6c5c7062588fa0d728787fe6a937de1b32af2b Mon Sep 17 00:00:00 2001 From: Keith Moyer Date: Mon, 20 Jul 2009 08:45:27 -0500 Subject: [PATCH] Update to OpenVPN 2.1rc19 --- release/src/router/openvpn/ChangeLog | 12 ++ release/src/router/openvpn/config-win32.h | 2 +- release/src/router/openvpn/configure | 20 ++-- release/src/router/openvpn/configure.ac | 2 +- release/src/router/openvpn/install-win32/maketap | 1 + .../openvpn/install-win32/openssl/.svn/entries | 2 +- .../src/router/openvpn/install-win32/settings.in | 12 +- release/src/router/openvpn/openvpn.spec | 2 +- release/src/router/openvpn/tap-win32/constants.h | 1 + release/src/router/openvpn/tap-win32/dhcp.c | 6 +- release/src/router/openvpn/tap-win32/prototypes.h | 21 +++- release/src/router/openvpn/tap-win32/tapdrvr.c | 125 ++++++++++++++++++--- release/src/router/openvpn/tap-win32/types.h | 15 +++ release/src/router/openvpn/version.m4 | 2 +- 14 files changed, 181 insertions(+), 42 deletions(-) diff --git a/release/src/router/openvpn/ChangeLog b/release/src/router/openvpn/ChangeLog index 40f3d5b787..48f6fd8be9 100644 --- a/release/src/router/openvpn/ChangeLog +++ b/release/src/router/openvpn/ChangeLog @@ -1,6 +1,18 @@ OpenVPN Change Log Copyright (C) 2002-2009 OpenVPN Technologies, Inc. +2009.07.16 -- Version 2.1_rc19 + +* In Windows TAP driver, refactor DHCP/ARP packet injection code to + use a DPC (deferred procedure call) to defer packet injection until + IRQL < DISPATCH_LEVEL, rather than calling NdisMEthIndicateReceive + in the context of AdapterTransmit. This is an attempt to reduce kernel + stack usage, and prevent EXCEPTION_DOUBLE_FAULT BSODs that have been + observed on Vista. Updated TAP driver version number to 9.6. + +* In configure.ac, use datadir instead of datarootdir for compatibility + with . # @@ -574,8 +574,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='OpenVPN' PACKAGE_TARNAME='openvpn' -PACKAGE_VERSION='2.1_rc18' -PACKAGE_STRING='OpenVPN 2.1_rc18' +PACKAGE_VERSION='2.1_rc19' +PACKAGE_STRING='OpenVPN 2.1_rc19' PACKAGE_BUGREPORT='openvpn-users@lists.sourceforge.net' ac_unique_file="syshead.h" @@ -1233,7 +1233,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures OpenVPN 2.1_rc18 to adapt to many kinds of systems. +\`configure' configures OpenVPN 2.1_rc19 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1304,7 +1304,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of OpenVPN 2.1_rc18:";; + short | recursive ) echo "Configuration of OpenVPN 2.1_rc19:";; esac cat <<\_ACEOF @@ -1426,7 +1426,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -OpenVPN configure 2.1_rc18 +OpenVPN configure 2.1_rc19 generated by GNU Autoconf 2.61 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -1440,7 +1440,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by OpenVPN $as_me 2.1_rc18, which was +It was created by OpenVPN $as_me 2.1_rc19, which was generated by GNU Autoconf 2.61. Invocation command line was $ $0 $@ @@ -12828,7 +12828,7 @@ fi # workaround for &1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by OpenVPN $as_me 2.1_rc18, which was +This file was extended by OpenVPN $as_me 2.1_rc19, which was generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -13309,7 +13309,7 @@ Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -OpenVPN config.status 2.1_rc18 +OpenVPN config.status 2.1_rc19 configured by $0, generated by GNU Autoconf 2.61, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" diff --git a/release/src/router/openvpn/configure.ac b/release/src/router/openvpn/configure.ac index bf883b212f..c6d19f96b0 100644 --- a/release/src/router/openvpn/configure.ac +++ b/release/src/router/openvpn/configure.ac @@ -857,7 +857,7 @@ AM_CONDITIONAL(WIN32, test "${WIN32}" = "yes") # workaround for /dev/null diff --git a/release/src/router/openvpn/install-win32/openssl/.svn/entries b/release/src/router/openvpn/install-win32/openssl/.svn/entries index 2b1d306bea..118f811ea6 100644 --- a/release/src/router/openvpn/install-win32/openssl/.svn/entries +++ b/release/src/router/openvpn/install-win32/openssl/.svn/entries @@ -1,7 +1,7 @@ 8 dir -4475 +4707 https://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn/install-win32/openssl https://svn.openvpn.net/projects/openvpn diff --git a/release/src/router/openvpn/install-win32/settings.in b/release/src/router/openvpn/install-win32/settings.in index 742fd317b1..cbfe58d233 100644 --- a/release/src/router/openvpn/install-win32/settings.in +++ b/release/src/router/openvpn/install-win32/settings.in @@ -30,20 +30,20 @@ # Optional directory of prebuilt OpenVPN binary components, # to be used as a source when build-from-scratch prerequisites # are not met. -!define GENOUT_PREBUILT "../gen-prebuilt" +;!define GENOUT_PREBUILT "../gen-prebuilt" # tapinstall.exe source code. # Not needed if DRVBINSRC is defined # (or if using pre-built mode). -;!define TISRC "../tapinstall" +!define TISRC "../tapinstall" # TAP Adapter parameters. Note that PRODUCT_TAP_ID is # defined in version.m4. !define PRODUCT_TAP_DEVICE_DESCRIPTION "TAP-Win32 Adapter V9" !define PRODUCT_TAP_PROVIDER "TAP-Win32 Provider V9" !define PRODUCT_TAP_MAJOR_VER 9 -!define PRODUCT_TAP_MINOR_VER 5 -!define PRODUCT_TAP_RELDATE "05/13/2009" +!define PRODUCT_TAP_MINOR_VER 6 +!define PRODUCT_TAP_RELDATE "06/22/2009" # TAP adapter icon -- visible=0x81 or hidden=0x89 !define PRODUCT_TAP_CHARACTERISTICS 0x81 @@ -53,8 +53,8 @@ # DDK Version. # DDK distribution is assumed to be in C:\WINDDK\${DDKVER} -;!define DDKVER 6001.18002 -;!define DDKVER_MAJOR 6001 +!define DDKVER 6001.18002 +!define DDKVER_MAJOR 6001 # Code Signing. # If undefined, don't sign any files. diff --git a/release/src/router/openvpn/openvpn.spec b/release/src/router/openvpn/openvpn.spec index 04f7a3b61d..5a5203782a 100644 --- a/release/src/router/openvpn/openvpn.spec +++ b/release/src/router/openvpn/openvpn.spec @@ -16,7 +16,7 @@ Summary: OpenVPN is a robust and highly flexible VPN daemon by James Yonan. Name: openvpn -Version: 2.1_rc18 +Version: 2.1_rc19 Release: 1 URL: http://openvpn.net/ Source0: http://prdownloads.sourceforge.net/openvpn/%{name}-%{version}.tar.gz diff --git a/release/src/router/openvpn/tap-win32/constants.h b/release/src/router/openvpn/tap-win32/constants.h index b6a3d56626..fc7855dcd0 100755 --- a/release/src/router/openvpn/tap-win32/constants.h +++ b/release/src/router/openvpn/tap-win32/constants.h @@ -51,5 +51,6 @@ #define PACKET_QUEUE_SIZE 64 // tap -> userspace queue size #define IRP_QUEUE_SIZE 16 // max number of simultaneous i/o operations from userspace +#define INJECT_QUEUE_SIZE 16 // DHCP/ARP -> tap injection queue #define TAP_LITTLE_ENDIAN // affects ntohs, htonl, etc. functions diff --git a/release/src/router/openvpn/tap-win32/dhcp.c b/release/src/router/openvpn/tap-win32/dhcp.c index 47e2995952..b6b28bb7f3 100755 --- a/release/src/router/openvpn/tap-win32/dhcp.c +++ b/release/src/router/openvpn/tap-win32/dhcp.c @@ -379,9 +379,9 @@ SendDHCPMsg (const TapAdapterPointer a, DHCPMSG_LEN_FULL (pkt)); // Return DHCP response to kernel - InjectPacket (a, - DHCPMSG_BUF (pkt), - DHCPMSG_LEN_FULL (pkt)); + InjectPacketDeferred (a, + DHCPMSG_BUF (pkt), + DHCPMSG_LEN_FULL (pkt)); } else { diff --git a/release/src/router/openvpn/tap-win32/prototypes.h b/release/src/router/openvpn/tap-win32/prototypes.h index c342ad3b01..29502d6039 100755 --- a/release/src/router/openvpn/tap-win32/prototypes.h +++ b/release/src/router/openvpn/tap-win32/prototypes.h @@ -171,13 +171,32 @@ VOID SetMediaStatus BOOLEAN state ); -VOID InjectPacket +VOID InjectPacketDeferred ( TapAdapterPointer p_Adapter, UCHAR *packet, const unsigned int len ); +VOID InjectPacketNow + ( + TapAdapterPointer p_Adapter, + UCHAR *packet, + const unsigned int len + ); + +// for KDEFERRED_ROUTINE and Static Driver Verifier +//#include +//KDEFERRED_ROUTINE InjectPacketDpc; + +VOID InjectPacketDpc + ( + KDPC *Dpc, + PVOID DeferredContext, + PVOID SystemArgument1, + PVOID SystemArgument2 + ); + VOID CheckIfDhcpAndTunMode ( TapAdapterPointer p_Adapter diff --git a/release/src/router/openvpn/tap-win32/tapdrvr.c b/release/src/router/openvpn/tap-win32/tapdrvr.c index cd4d179ef7..a856734bdc 100755 --- a/release/src/router/openvpn/tap-win32/tapdrvr.c +++ b/release/src/router/openvpn/tap-win32/tapdrvr.c @@ -692,6 +692,8 @@ TapDeviceFreeResources (TapExtensionPointer p_Extension) QueueFree (p_Extension->m_PacketQueue); if (p_Extension->m_IrpQueue) QueueFree (p_Extension->m_IrpQueue); + if (p_Extension->m_InjectQueue) + QueueFree (p_Extension->m_InjectQueue); if (p_Extension->m_CreatedUnicodeLinkName) RtlFreeUnicodeString (&p_Extension->m_UnicodeLinkName); @@ -717,8 +719,14 @@ TapDeviceFreeResources (TapExtensionPointer p_Extension) if (p_Extension->m_TapName) MemFree (p_Extension->m_TapName, NAME_BUFFER_SIZE); + if (p_Extension->m_InjectDpcInitialized) + KeRemoveQueueDpc (&p_Extension->m_InjectDpc); + if (p_Extension->m_AllocatedSpinlocks) - NdisFreeSpinLock (&p_Extension->m_QueueLock); + { + NdisFreeSpinLock (&p_Extension->m_QueueLock); + NdisFreeSpinLock (&p_Extension->m_InjectLock); + } } //======================================================================== @@ -932,19 +940,28 @@ CreateTapDevice (TapExtensionPointer p_Extension, const char *p_Name) //======================================================== NdisAllocateSpinLock (&p_Extension->m_QueueLock); + NdisAllocateSpinLock (&p_Extension->m_InjectLock); p_Extension->m_AllocatedSpinlocks = TRUE; p_Extension->m_PacketQueue = QueueInit (PACKET_QUEUE_SIZE); p_Extension->m_IrpQueue = QueueInit (IRP_QUEUE_SIZE); - + p_Extension->m_InjectQueue = QueueInit (INJECT_QUEUE_SIZE); if (!p_Extension->m_PacketQueue - || !p_Extension->m_IrpQueue) + || !p_Extension->m_IrpQueue + || !p_Extension->m_InjectQueue) { DEBUGP (("[%s] couldn't alloc TAP queues\n", p_Name)); l_Return = NDIS_STATUS_RESOURCES; goto cleanup; } + //================================================================= + // Initialize deferred procedure call for DHCP/ARP packet injection + //================================================================= + + KeInitializeDpc (&p_Extension->m_InjectDpc, InjectPacketDpc, NULL); + p_Extension->m_InjectDpcInitialized = TRUE; + //======================== // Finalize initialization //======================== @@ -1808,9 +1825,9 @@ TapDeviceHook (IN PDEVICE_OBJECT p_DeviceObject, IN PIRP p_IRP) NULL, STRSAFE_FILL_BEHIND_NULL | STRSAFE_IGNORE_NULLS, #if PACKET_TRUNCATION_CHECK - "State=%s Err=[%s/%d] #O=%d Tx=[%d,%d,%d] Rx=[%d,%d,%d] IrpQ=[%d,%d,%d] PktQ=[%d,%d,%d]", + "State=%s Err=[%s/%d] #O=%d Tx=[%d,%d,%d] Rx=[%d,%d,%d] IrpQ=[%d,%d,%d] PktQ=[%d,%d,%d] InjQ=[%d,%d,%d]", #else - "State=%s Err=[%s/%d] #O=%d Tx=[%d,%d] Rx=[%d,%d] IrpQ=[%d,%d,%d] PktQ=[%d,%d,%d]", + "State=%s Err=[%s/%d] #O=%d Tx=[%d,%d] Rx=[%d,%d] IrpQ=[%d,%d,%d] PktQ=[%d,%d,%d] InjQ=[%d,%d,%d]", #endif state, g_LastErrorFilename, @@ -1831,7 +1848,10 @@ TapDeviceHook (IN PDEVICE_OBJECT p_DeviceObject, IN PIRP p_IRP) (int)IRP_QUEUE_SIZE, (int)l_Adapter->m_Extension.m_PacketQueue->size, (int)l_Adapter->m_Extension.m_PacketQueue->max_size, - (int)PACKET_QUEUE_SIZE + (int)PACKET_QUEUE_SIZE, + (int)l_Adapter->m_Extension.m_InjectQueue->size, + (int)l_Adapter->m_Extension.m_InjectQueue->max_size, + (int)INJECT_QUEUE_SIZE ); p_IRP->IoStatus.Information @@ -2519,15 +2539,16 @@ CancelIRP (TapExtensionPointer p_Extension, IoCompleteRequest (p_IRP, IO_NO_INCREMENT); } -//==================================== -// Exhaust packet and IRP queues. -//==================================== +//=========================================== +// Exhaust packet, IRP, and injection queues. +//=========================================== VOID FlushQueues (TapExtensionPointer p_Extension) { PIRP l_IRP; TapPacketPointer l_PacketBuffer; - int n_IRP=0, n_Packet=0; + InjectPacketPointer l_InjectBuffer; + int n_IRP=0, n_Packet=0, n_Inject=0; MYASSERT (p_Extension); MYASSERT (p_Extension->m_TapDevice); @@ -2560,15 +2581,32 @@ FlushQueues (TapExtensionPointer p_Extension) break; } + while (TRUE) + { + NdisAcquireSpinLock (&p_Extension->m_InjectLock); + l_InjectBuffer = QueuePop (p_Extension->m_InjectQueue); + NdisReleaseSpinLock (&p_Extension->m_InjectLock); + if (l_InjectBuffer) + { + ++n_Inject; + INJECT_PACKET_FREE(l_InjectBuffer); + } + else + break; + } + DEBUGP (( - "[%s] [TAP] FlushQueues n_IRP=[%d,%d,%d] n_Packet=[%d,%d,%d]\n", + "[%s] [TAP] FlushQueues n_IRP=[%d,%d,%d] n_Packet=[%d,%d,%d] n_Inject=[%d,%d,%d]\n", p_Extension->m_TapName, n_IRP, p_Extension->m_IrpQueue->max_size, IRP_QUEUE_SIZE, n_Packet, p_Extension->m_PacketQueue->max_size, - PACKET_QUEUE_SIZE + PACKET_QUEUE_SIZE, + n_Inject, + p_Extension->m_InjectQueue->max_size, + INJECT_QUEUE_SIZE )); } @@ -2667,7 +2705,7 @@ ProcessARP (TapAdapterPointer p_Adapter, (unsigned char *) arp, sizeof (ARP_PACKET)); - InjectPacket (p_Adapter, (UCHAR *) arp, sizeof (ARP_PACKET)); + InjectPacketDeferred (p_Adapter, (UCHAR *) arp, sizeof (ARP_PACKET)); MemFree (arp, sizeof (ARP_PACKET)); } @@ -2684,10 +2722,60 @@ ProcessARP (TapAdapterPointer p_Adapter, // seen as an incoming packet "arriving" on the interface. //=============================================================== +// Defer packet injection till IRQL < DISPATCH_LEVEL VOID -InjectPacket (TapAdapterPointer p_Adapter, - UCHAR *packet, - const unsigned int len) +InjectPacketDeferred (TapAdapterPointer p_Adapter, + UCHAR *packet, + const unsigned int len) +{ + InjectPacketPointer l_InjectBuffer; + PVOID result; + + if (NdisAllocateMemoryWithTag (&l_InjectBuffer, + INJECT_PACKET_SIZE (len), + 'IPAT') == NDIS_STATUS_SUCCESS) + { + l_InjectBuffer->m_Size = len; + NdisMoveMemory (l_InjectBuffer->m_Data, packet, len); + NdisAcquireSpinLock (&p_Adapter->m_Extension.m_InjectLock); + result = QueuePush (p_Adapter->m_Extension.m_InjectQueue, l_InjectBuffer); + NdisReleaseSpinLock (&p_Adapter->m_Extension.m_InjectLock); + if (result) + KeInsertQueueDpc (&p_Adapter->m_Extension.m_InjectDpc, p_Adapter, NULL); + else + INJECT_PACKET_FREE(l_InjectBuffer); + } +} + +// Handle the injection of previously deferred packets +VOID +InjectPacketDpc(KDPC *Dpc, + PVOID DeferredContext, + PVOID SystemArgument1, + PVOID SystemArgument2) +{ + InjectPacketPointer l_InjectBuffer; + TapAdapterPointer l_Adapter = (TapAdapterPointer)SystemArgument1; + while (TRUE) + { + NdisAcquireSpinLock (&l_Adapter->m_Extension.m_InjectLock); + l_InjectBuffer = QueuePop (l_Adapter->m_Extension.m_InjectQueue); + NdisReleaseSpinLock (&l_Adapter->m_Extension.m_InjectLock); + if (l_InjectBuffer) + { + InjectPacketNow(l_Adapter, l_InjectBuffer->m_Data, l_InjectBuffer->m_Size); + INJECT_PACKET_FREE(l_InjectBuffer); + } + else + break; + } +} + +// Do packet injection now +VOID +InjectPacketNow (TapAdapterPointer p_Adapter, + UCHAR *packet, + const unsigned int len) { MYASSERT (len >= ETHERNET_HEADER_SIZE); @@ -2699,6 +2787,9 @@ InjectPacket (TapAdapterPointer p_Adapter, // TapDeviceHook/IRP_MJ_WRITE. // // The DDK docs imply that this is okay. + // + // Note that reentrant behavior could only occur if the + // non-deferred version of InjectPacket is used. //------------------------------------------------------------ NdisMEthIndicateReceive (p_Adapter->m_MiniportAdapterHandle, @@ -2713,7 +2804,7 @@ InjectPacket (TapAdapterPointer p_Adapter, } __except (EXCEPTION_EXECUTE_HANDLER) { - DEBUGP (("[%s] NdisMEthIndicateReceive failed in InjectPacket\n", + DEBUGP (("[%s] NdisMEthIndicateReceive failed in InjectPacketNow\n", NAME (p_Adapter))); NOTE_ERROR (); } diff --git a/release/src/router/openvpn/tap-win32/types.h b/release/src/router/openvpn/tap-win32/types.h index d424521392..4adee6a6f3 100755 --- a/release/src/router/openvpn/tap-win32/types.h +++ b/release/src/router/openvpn/tap-win32/types.h @@ -86,6 +86,12 @@ typedef struct _TapExtension // Flags BOOLEAN m_TapIsRunning; BOOLEAN m_CalledTapDeviceFreeResources; + + // DPC queue for deferred packet injection + BOOLEAN m_InjectDpcInitialized; + KDPC m_InjectDpc; + NDIS_SPIN_LOCK m_InjectLock; + Queue *m_InjectQueue; } TapExtension, *TapExtensionPointer; @@ -99,6 +105,15 @@ typedef struct _TapPacket } TapPacket, *TapPacketPointer; +typedef struct _InjectPacket + { +# define INJECT_PACKET_SIZE(data_size) (sizeof (InjectPacket) + (data_size)) +# define INJECT_PACKET_FREE(ib) NdisFreeMemory ((ib), INJECT_PACKET_SIZE ((ib)->m_Size), 0) + ULONG m_Size; + UCHAR m_Data []; // m_Data must be the last struct member + } +InjectPacket, *InjectPacketPointer; + typedef struct _TapAdapter { # define NAME(a) ((a)->m_NameAnsi.Buffer) diff --git a/release/src/router/openvpn/version.m4 b/release/src/router/openvpn/version.m4 index 370f7eb239..5c84929e36 100644 --- a/release/src/router/openvpn/version.m4 +++ b/release/src/router/openvpn/version.m4 @@ -1,5 +1,5 @@ dnl define the OpenVPN version -define(PRODUCT_VERSION,[2.1_rc18]) +define(PRODUCT_VERSION,[2.1_rc19]) dnl define the TAP version define(PRODUCT_TAP_ID,[tap0901]) define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9]) -- 2.11.4.GIT