diff options
author | Adam Ierymenko <adam.ierymenko@zerotier.com> | 2014-01-20 11:18:55 -0800 |
---|---|---|
committer | Adam Ierymenko <adam.ierymenko@zerotier.com> | 2014-01-20 11:18:55 -0800 |
commit | a365a0e3ba1afdc4151f84efc953a756cc00378d (patch) | |
tree | db3be30c16a60539ccd742013cadaf4799063df9 /windows/TapDriver/tapdrvr.c | |
parent | 45c5b66e9ef4d8a2afafe4250e40557290f07997 (diff) | |
download | infinitytier-a365a0e3ba1afdc4151f84efc953a756cc00378d.tar.gz infinitytier-a365a0e3ba1afdc4151f84efc953a756cc00378d.zip |
Remove a lot of code that we don't need from tap-windows, further winnowing down this fork of OpenVPN's tap-windows to a more minimal version that does only basic Ethernet tap functionality.
Diffstat (limited to 'windows/TapDriver/tapdrvr.c')
-rw-r--r-- | windows/TapDriver/tapdrvr.c | 4616 |
1 files changed, 1780 insertions, 2836 deletions
diff --git a/windows/TapDriver/tapdrvr.c b/windows/TapDriver/tapdrvr.c index 4781c872..031b0b4e 100644 --- a/windows/TapDriver/tapdrvr.c +++ b/windows/TapDriver/tapdrvr.c @@ -1,26 +1,26 @@ /* - * TAP-Windows -- A kernel driver to provide virtual tap - * device functionality on Windows. - * - * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. - * - * This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc., - * and is released under the GPL version 2 (see below). - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program (see the file COPYING included with this - * distribution); if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ +* TAP-Windows -- A kernel driver to provide virtual tap +* device functionality on Windows. +* +* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. +* +* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc., +* and is released under the GPL version 2 (see below). +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 +* as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program (see the file COPYING included with this +* distribution); if not, write to the Free Software Foundation, Inc., +* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ //====================================================== // This driver is designed to work on Win 2000 or higher @@ -49,21 +49,6 @@ #define ALSO_DBGPRINT 1 #define DEBUGP_AT_DISPATCH 0 -//======================================================== -// Check for truncated IPv4 packets, log errors if found. -//======================================================== -#define PACKET_TRUNCATION_CHECK 0 - -//======================================================== -// EXPERIMENTAL -- Configure TAP device object to be -// accessible from non-administrative accounts, based -// on an advanced properties setting. -// -// Duplicates the functionality of OpenVPN's -// --allow-nonadmin directive. -//======================================================== -//#define ENABLE_NONADMIN 1 - #if defined(DDKVER_MAJOR) && DDKVER_MAJOR < 5600 #include <ndis.h> #include <ntstrsafe.h> @@ -79,18 +64,16 @@ #include "proto.h" #include "error.h" #include "endian.h" -#include "dhcp.h" #include "types.h" #include "prototypes.h" #include "mem.c" #include "macinfo.c" #include "error.c" -#include "dhcp.c" #include "instance.c" #define IS_UP(ta) \ - ((ta)->m_InterfaceIsRunning && (ta)->m_Extension.m_TapIsRunning) + ((ta)->m_InterfaceIsRunning && (ta)->m_Extension.m_TapIsRunning) #define INCREMENT_STAT(s) ++(s) @@ -103,40 +86,40 @@ NDIS_HANDLE g_NdisWrapperHandle; const UINT g_SupportedOIDList[] = { - OID_GEN_HARDWARE_STATUS, - OID_GEN_MEDIA_SUPPORTED, - OID_GEN_MEDIA_IN_USE, - OID_GEN_MAXIMUM_LOOKAHEAD, - OID_GEN_MAC_OPTIONS, - OID_GEN_LINK_SPEED, - OID_GEN_TRANSMIT_BLOCK_SIZE, - OID_GEN_RECEIVE_BLOCK_SIZE, - OID_GEN_VENDOR_DESCRIPTION, - OID_GEN_DRIVER_VERSION, - OID_GEN_XMIT_OK, - OID_GEN_RCV_OK, - OID_GEN_XMIT_ERROR, - OID_GEN_RCV_ERROR, - OID_802_3_PERMANENT_ADDRESS, - OID_802_3_CURRENT_ADDRESS, - OID_GEN_RCV_NO_BUFFER, - OID_802_3_RCV_ERROR_ALIGNMENT, - OID_802_3_XMIT_ONE_COLLISION, - OID_802_3_XMIT_MORE_COLLISIONS, - OID_802_3_MULTICAST_LIST, - OID_802_3_MAXIMUM_LIST_SIZE, - OID_GEN_VENDOR_ID, - OID_GEN_CURRENT_LOOKAHEAD, - OID_GEN_CURRENT_PACKET_FILTER, - OID_GEN_PROTOCOL_OPTIONS, - OID_GEN_MAXIMUM_TOTAL_SIZE, - OID_GEN_TRANSMIT_BUFFER_SPACE, - OID_GEN_RECEIVE_BUFFER_SPACE, - OID_GEN_MAXIMUM_FRAME_SIZE, - OID_GEN_VENDOR_DRIVER_VERSION, - OID_GEN_MAXIMUM_SEND_PACKETS, - OID_GEN_MEDIA_CONNECT_STATUS, - OID_GEN_SUPPORTED_LIST + OID_GEN_HARDWARE_STATUS, + OID_GEN_MEDIA_SUPPORTED, + OID_GEN_MEDIA_IN_USE, + OID_GEN_MAXIMUM_LOOKAHEAD, + OID_GEN_MAC_OPTIONS, + OID_GEN_LINK_SPEED, + OID_GEN_TRANSMIT_BLOCK_SIZE, + OID_GEN_RECEIVE_BLOCK_SIZE, + OID_GEN_VENDOR_DESCRIPTION, + OID_GEN_DRIVER_VERSION, + OID_GEN_XMIT_OK, + OID_GEN_RCV_OK, + OID_GEN_XMIT_ERROR, + OID_GEN_RCV_ERROR, + OID_802_3_PERMANENT_ADDRESS, + OID_802_3_CURRENT_ADDRESS, + OID_GEN_RCV_NO_BUFFER, + OID_802_3_RCV_ERROR_ALIGNMENT, + OID_802_3_XMIT_ONE_COLLISION, + OID_802_3_XMIT_MORE_COLLISIONS, + OID_802_3_MULTICAST_LIST, + OID_802_3_MAXIMUM_LIST_SIZE, + OID_GEN_VENDOR_ID, + OID_GEN_CURRENT_LOOKAHEAD, + OID_GEN_CURRENT_PACKET_FILTER, + OID_GEN_PROTOCOL_OPTIONS, + OID_GEN_MAXIMUM_TOTAL_SIZE, + OID_GEN_TRANSMIT_BUFFER_SPACE, + OID_GEN_RECEIVE_BUFFER_SPACE, + OID_GEN_MAXIMUM_FRAME_SIZE, + OID_GEN_VENDOR_DRIVER_VERSION, + OID_GEN_MAXIMUM_SEND_PACKETS, + OID_GEN_MEDIA_CONNECT_STATUS, + OID_GEN_SUPPORTED_LIST }; //============================================================ @@ -146,112 +129,112 @@ const UINT g_SupportedOIDList[] = { DRIVER_INITIALIZE DriverEntry; NTSTATUS -DriverEntry (IN PDRIVER_OBJECT p_DriverObject, - IN PUNICODE_STRING p_RegistryPath) + DriverEntry (IN PDRIVER_OBJECT p_DriverObject, + IN PUNICODE_STRING p_RegistryPath) { - NDIS_STATUS l_Status = NDIS_STATUS_FAILURE; - NDIS_MINIPORT_CHARACTERISTICS *l_Properties = NULL; + NDIS_STATUS l_Status = NDIS_STATUS_FAILURE; + NDIS_MINIPORT_CHARACTERISTICS *l_Properties = NULL; - //======================================================== - // Notify NDIS that a new miniport driver is initializing. - //======================================================== + //======================================================== + // Notify NDIS that a new miniport driver is initializing. + //======================================================== - NdisMInitializeWrapper (&g_NdisWrapperHandle, - p_DriverObject, - p_RegistryPath, NULL); + NdisMInitializeWrapper (&g_NdisWrapperHandle, + p_DriverObject, + p_RegistryPath, NULL); - //====================== - // Global initialization - //====================== + //====================== + // Global initialization + //====================== #if DBG - MyDebugInit (10000); // Allocate debugging text space + MyDebugInit (10000); // Allocate debugging text space #endif - if (!InitInstanceList ()) - { - DEBUGP (("[TAP] Allocation failed for adapter instance list\n")); - goto cleanup; - } - - //======================================= - // Set and register miniport entry points - //======================================= - - l_Properties = MemAlloc (sizeof (NDIS_MINIPORT_CHARACTERISTICS), TRUE); - - if (l_Properties == NULL) - { - DEBUGP (("[TAP] Allocation failed for miniport entry points\n")); - goto cleanup; - } - - l_Properties->MajorNdisVersion = TAP_NDIS_MAJOR_VERSION; - l_Properties->MinorNdisVersion = TAP_NDIS_MINOR_VERSION; - l_Properties->InitializeHandler = AdapterCreate; - l_Properties->HaltHandler = AdapterHalt; - l_Properties->ResetHandler = AdapterReset; /* DISPATCH_LEVEL */ - l_Properties->TransferDataHandler = AdapterReceive; /* DISPATCH_LEVEL */ - l_Properties->SendHandler = AdapterTransmit; /* DISPATCH_LEVEL */ - l_Properties->QueryInformationHandler = AdapterQuery; /* DISPATCH_LEVEL */ - l_Properties->SetInformationHandler = AdapterModify; /* DISPATCH_LEVEL */ - - switch (l_Status = - NdisMRegisterMiniport (g_NdisWrapperHandle, l_Properties, - sizeof (NDIS_MINIPORT_CHARACTERISTICS))) - { - case NDIS_STATUS_SUCCESS: - { - DEBUGP (("[TAP] version [%d.%d] %s %s registered miniport successfully\n", - TAP_DRIVER_MAJOR_VERSION, - TAP_DRIVER_MINOR_VERSION, - __DATE__, - __TIME__)); - DEBUGP (("Registry Path: '%.*S'\n", p_RegistryPath->Length/2, p_RegistryPath->Buffer)); - break; - } - - case NDIS_STATUS_BAD_CHARACTERISTICS: - { - DEBUGP (("[TAP] Miniport characteristics were badly defined\n")); - NdisTerminateWrapper (g_NdisWrapperHandle, NULL); - break; - } - - case NDIS_STATUS_BAD_VERSION: - { - DEBUGP - (("[TAP] NDIS Version is wrong for the given characteristics\n")); - NdisTerminateWrapper (g_NdisWrapperHandle, NULL); - break; - } - - case NDIS_STATUS_RESOURCES: - { - DEBUGP (("[TAP] Insufficient resources\n")); - NdisTerminateWrapper (g_NdisWrapperHandle, NULL); - break; - } - - default: - case NDIS_STATUS_FAILURE: - { - DEBUGP (("[TAP] Unknown fatal registration error\n")); - NdisTerminateWrapper (g_NdisWrapperHandle, NULL); - break; - } - } - - cleanup: - if (l_Properties) - MemFree (l_Properties, sizeof (NDIS_MINIPORT_CHARACTERISTICS)); - - if (l_Status == NDIS_STATUS_SUCCESS) - NdisMRegisterUnloadHandler (g_NdisWrapperHandle, TapDriverUnload); - else - TapDriverUnload (p_DriverObject); - - return l_Status; + if (!InitInstanceList ()) + { + DEBUGP (("[TAP] Allocation failed for adapter instance list\n")); + goto cleanup; + } + + //======================================= + // Set and register miniport entry points + //======================================= + + l_Properties = (NDIS_MINIPORT_CHARACTERISTICS *)MemAlloc (sizeof (NDIS_MINIPORT_CHARACTERISTICS), TRUE); + + if (l_Properties == NULL) + { + DEBUGP (("[TAP] Allocation failed for miniport entry points\n")); + goto cleanup; + } + + l_Properties->MajorNdisVersion = TAP_NDIS_MAJOR_VERSION; + l_Properties->MinorNdisVersion = TAP_NDIS_MINOR_VERSION; + l_Properties->InitializeHandler = AdapterCreate; + l_Properties->HaltHandler = AdapterHalt; + l_Properties->ResetHandler = AdapterReset; /* DISPATCH_LEVEL */ + l_Properties->TransferDataHandler = AdapterReceive; /* DISPATCH_LEVEL */ + l_Properties->SendHandler = AdapterTransmit; /* DISPATCH_LEVEL */ + l_Properties->QueryInformationHandler = AdapterQuery; /* DISPATCH_LEVEL */ + l_Properties->SetInformationHandler = AdapterModify; /* DISPATCH_LEVEL */ + + switch (l_Status = + NdisMRegisterMiniport (g_NdisWrapperHandle, l_Properties, + sizeof (NDIS_MINIPORT_CHARACTERISTICS))) + { + case NDIS_STATUS_SUCCESS: + { + DEBUGP (("[TAP] version [%d.%d] %s %s registered miniport successfully\n", + TAP_DRIVER_MAJOR_VERSION, + TAP_DRIVER_MINOR_VERSION, + __DATE__, + __TIME__)); + DEBUGP (("Registry Path: '%.*S'\n", p_RegistryPath->Length/2, p_RegistryPath->Buffer)); + break; + } + + case NDIS_STATUS_BAD_CHARACTERISTICS: + { + DEBUGP (("[TAP] Miniport characteristics were badly defined\n")); + NdisTerminateWrapper (g_NdisWrapperHandle, NULL); + break; + } + + case NDIS_STATUS_BAD_VERSION: + { + DEBUGP + (("[TAP] NDIS Version is wrong for the given characteristics\n")); + NdisTerminateWrapper (g_NdisWrapperHandle, NULL); + break; + } + + case NDIS_STATUS_RESOURCES: + { + DEBUGP (("[TAP] Insufficient resources\n")); + NdisTerminateWrapper (g_NdisWrapperHandle, NULL); + break; + } + + default: + case NDIS_STATUS_FAILURE: + { + DEBUGP (("[TAP] Unknown fatal registration error\n")); + NdisTerminateWrapper (g_NdisWrapperHandle, NULL); + break; + } + } + +cleanup: + if (l_Properties) + MemFree (l_Properties, sizeof (NDIS_MINIPORT_CHARACTERISTICS)); + + if (l_Status == NDIS_STATUS_SUCCESS) + NdisMRegisterUnloadHandler (g_NdisWrapperHandle, TapDriverUnload); + else + TapDriverUnload (p_DriverObject); + + return l_Status; } //============================================================ @@ -259,23 +242,23 @@ DriverEntry (IN PDRIVER_OBJECT p_DriverObject, //============================================================ DRIVER_UNLOAD TapDriverUnload; VOID -TapDriverUnload (IN PDRIVER_OBJECT p_DriverObject) + TapDriverUnload (IN PDRIVER_OBJECT p_DriverObject) { - DEBUGP (("[TAP] version [%d.%d] %s %s unloaded, instances=%d, imbs=%d\n", - TAP_DRIVER_MAJOR_VERSION, - TAP_DRIVER_MINOR_VERSION, - __DATE__, - __TIME__, - NInstances(), - InstanceMaxBucketSize())); - - FreeInstanceList (); - - //============================== - // Free debugging text space - //============================== + DEBUGP (("[TAP] version [%d.%d] %s %s unloaded, instances=%d, imbs=%d\n", + TAP_DRIVER_MAJOR_VERSION, + TAP_DRIVER_MINOR_VERSION, + __DATE__, + __TIME__, + NInstances(), + InstanceMaxBucketSize())); + + FreeInstanceList (); + + //============================== + // Free debugging text space + //============================== #if DBG - MyDebugFree (); + MyDebugFree (); #endif } @@ -283,449 +266,404 @@ TapDriverUnload (IN PDRIVER_OBJECT p_DriverObject) // Adapter Initialization //========================================================== NDIS_STATUS AdapterCreate -(OUT PNDIS_STATUS p_ErrorStatus, - OUT PUINT p_MediaIndex, - IN PNDIS_MEDIUM p_Media, - IN UINT p_MediaCount, - IN NDIS_HANDLE p_AdapterHandle, - IN NDIS_HANDLE p_ConfigurationHandle) + (OUT PNDIS_STATUS p_ErrorStatus, + OUT PUINT p_MediaIndex, + IN PNDIS_MEDIUM p_Media, + IN UINT p_MediaCount, + IN NDIS_HANDLE p_AdapterHandle, + IN NDIS_HANDLE p_ConfigurationHandle) { - TapAdapterPointer l_Adapter = NULL; + TapAdapterPointer l_Adapter = NULL; - NDIS_MEDIUM l_PreferredMedium = NdisMedium802_3; // Ethernet - BOOLEAN l_MacFromRegistry = FALSE; - UINT l_Index; - NDIS_STATUS status; + NDIS_MEDIUM l_PreferredMedium = NdisMedium802_3; // Ethernet + BOOLEAN l_MacFromRegistry = FALSE; + UINT l_Index; + NDIS_STATUS status; -#if ENABLE_NONADMIN - BOOLEAN enable_non_admin = FALSE; -#endif + DEBUGP (("[TAP] AdapterCreate called\n")); - DEBUGP (("[TAP] AdapterCreate called\n")); - - //==================================== - // Make sure adapter type is supported - //==================================== - - for (l_Index = 0; - l_Index < p_MediaCount && p_Media[l_Index] != l_PreferredMedium; - ++l_Index); - - if (l_Index == p_MediaCount) - { - DEBUGP (("[TAP] Unsupported adapter type [wanted: %d]\n", - l_PreferredMedium)); - return NDIS_STATUS_UNSUPPORTED_MEDIA; - } - - *p_MediaIndex = l_Index; - - //========================================= - // Allocate memory for TapAdapter structure - //========================================= - - l_Adapter = MemAlloc (sizeof (TapAdapter), TRUE); - - if (l_Adapter == NULL) - { - DEBUGP (("[TAP] Couldn't allocate adapter memory\n")); - return NDIS_STATUS_RESOURCES; - } - - //========================================== - // Inform the NDIS library about significant - // features of our virtual NIC. - //========================================== - - NdisMSetAttributesEx - (p_AdapterHandle, - (NDIS_HANDLE) l_Adapter, - 16, - NDIS_ATTRIBUTE_DESERIALIZE - | NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT - | NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT - | NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND, - NdisInterfaceInternal); - - //===================================== - // Initialize simple Adapter parameters - //===================================== - - l_Adapter->m_Lookahead = DEFAULT_PACKET_LOOKAHEAD; - l_Adapter->m_Medium = l_PreferredMedium; - l_Adapter->m_DeviceState = '?'; - l_Adapter->m_MiniportAdapterHandle = p_AdapterHandle; - - //================================== - // Allocate spinlock for controlling - // access to multicast address list. - //================================== - NdisAllocateSpinLock (&l_Adapter->m_MCLock); - l_Adapter->m_MCLockAllocated = TRUE; - - //==================================================== - // Register a shutdown handler which will be called - // on system restart/shutdown to halt our virtual NIC. - //==================================================== - - NdisMRegisterAdapterShutdownHandler (p_AdapterHandle, l_Adapter, - AdapterHalt); - l_Adapter->m_RegisteredAdapterShutdownHandler = TRUE; - - //============================================ - // Get parameters from registry which were set - // in the adapter advanced properties dialog. - //============================================ - { - NDIS_STATUS status; - NDIS_HANDLE configHandle; - NDIS_CONFIGURATION_PARAMETER *parm; - - // set defaults in case our registry query fails - l_Adapter->m_MTU = ETHERNET_MTU; - l_Adapter->m_MediaStateAlwaysConnected = FALSE; - l_Adapter->m_MediaState = FALSE; - - NdisOpenConfiguration (&status, &configHandle, p_ConfigurationHandle); - if (status != NDIS_STATUS_SUCCESS) - { - DEBUGP (("[TAP] Couldn't open adapter registry\n")); - AdapterFreeResources (l_Adapter); - return status; - } - - //==================================== - // Allocate and construct adapter name - //==================================== - { - - NDIS_STRING mkey = NDIS_STRING_CONST("MiniportName"); - NDIS_STRING vkey = NDIS_STRING_CONST("NdisVersion"); - NDIS_STATUS vstatus; - NDIS_CONFIGURATION_PARAMETER *vparm; - - NdisReadConfiguration (&vstatus, &vparm, configHandle, &vkey, NdisParameterInteger); - if (vstatus == NDIS_STATUS_SUCCESS) - DEBUGP (("[TAP] NdisReadConfiguration NdisVersion=%X\n", vparm->ParameterData.IntegerData)); - - NdisReadConfiguration (&status, &parm, configHandle, &mkey, NdisParameterString); - if (status == NDIS_STATUS_SUCCESS) + //==================================== + // Make sure adapter type is supported + //==================================== + + for (l_Index = 0; + l_Index < p_MediaCount && p_Media[l_Index] != l_PreferredMedium; + ++l_Index); + + if (l_Index == p_MediaCount) { - if (parm->ParameterType == NdisParameterString) - { - DEBUGP (("[TAP] NdisReadConfiguration (MiniportName=%.*S)\n", - parm->ParameterData.StringData.Length/2, - parm->ParameterData.StringData.Buffer)); + DEBUGP (("[TAP] Unsupported adapter type [wanted: %d]\n", + l_PreferredMedium)); + return NDIS_STATUS_UNSUPPORTED_MEDIA; + } + + *p_MediaIndex = l_Index; + + //========================================= + // Allocate memory for TapAdapter structure + //========================================= + + l_Adapter = MemAlloc (sizeof (TapAdapter), TRUE); + + if (l_Adapter == NULL) + { + DEBUGP (("[TAP] Couldn't allocate adapter memory\n")); + return NDIS_STATUS_RESOURCES; + } + + //========================================== + // Inform the NDIS library about significant + // features of our virtual NIC. + //========================================== + + NdisMSetAttributesEx + (p_AdapterHandle, + (NDIS_HANDLE) l_Adapter, + 16, + NDIS_ATTRIBUTE_DESERIALIZE + | NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT + | NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT + | NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND, + NdisInterfaceInternal); + + //===================================== + // Initialize simple Adapter parameters + //===================================== + + l_Adapter->m_Lookahead = DEFAULT_PACKET_LOOKAHEAD; + l_Adapter->m_Medium = l_PreferredMedium; + l_Adapter->m_DeviceState = '?'; + l_Adapter->m_MiniportAdapterHandle = p_AdapterHandle; + + //================================== + // Allocate spinlock for controlling + // access to multicast address list. + //================================== + NdisAllocateSpinLock (&l_Adapter->m_MCLock); + l_Adapter->m_MCLockAllocated = TRUE; + + //==================================================== + // Register a shutdown handler which will be called + // on system restart/shutdown to halt our virtual NIC. + //==================================================== + + NdisMRegisterAdapterShutdownHandler (p_AdapterHandle, l_Adapter, + AdapterHalt); + l_Adapter->m_RegisteredAdapterShutdownHandler = TRUE; + + //============================================ + // Get parameters from registry which were set + // in the adapter advanced properties dialog. + //============================================ + { + NDIS_STATUS status; + NDIS_HANDLE configHandle; + NDIS_CONFIGURATION_PARAMETER *parm; + + // set defaults in case our registry query fails + l_Adapter->m_MTU = ETHERNET_MTU; + l_Adapter->m_MediaStateAlwaysConnected = FALSE; + l_Adapter->m_MediaState = FALSE; + + NdisOpenConfiguration (&status, &configHandle, p_ConfigurationHandle); + if (status != NDIS_STATUS_SUCCESS) + { + DEBUGP (("[TAP] Couldn't open adapter registry\n")); + AdapterFreeResources (l_Adapter); + return status; + } + + //==================================== + // Allocate and construct adapter name + //==================================== + { - if (RtlUnicodeStringToAnsiString ( + NDIS_STRING mkey = NDIS_STRING_CONST("MiniportName"); + NDIS_STRING vkey = NDIS_STRING_CONST("NdisVersion"); + NDIS_STATUS vstatus; + NDIS_CONFIGURATION_PARAMETER *vparm; + + NdisReadConfiguration (&vstatus, &vparm, configHandle, &vkey, NdisParameterInteger); + if (vstatus == NDIS_STATUS_SUCCESS) + DEBUGP (("[TAP] NdisReadConfiguration NdisVersion=%X\n", vparm->ParameterData.IntegerData)); + + NdisReadConfiguration (&status, &parm, configHandle, &mkey, NdisParameterString); + if (status == NDIS_STATUS_SUCCESS) + { + if (parm->ParameterType == NdisParameterString) + { + DEBUGP (("[TAP] NdisReadConfiguration (MiniportName=%.*S)\n", + parm->ParameterData.StringData.Length/2, + parm->ParameterData.StringData.Buffer)); + + if (RtlUnicodeStringToAnsiString ( &l_Adapter->m_NameAnsi, &parm->ParameterData.StringData, TRUE) != STATUS_SUCCESS) - { - DEBUGP (("[TAP] MiniportName failed\n")); - status = NDIS_STATUS_RESOURCES; - } - } - } - else - { - /* "MiniportName" is available only XP and above. Not on Windows 2000. */ - if (vstatus == NDIS_STATUS_SUCCESS && vparm->ParameterData.IntegerData == 0x50000) - { - /* Fallback for Windows 2000 with NDIS version 5.00.00 - Don't use this on Vista, 'NDIS_MINIPORT_BLOCK' was changed! */ - if (RtlUnicodeStringToAnsiString (&l_Adapter->m_NameAnsi, + { + DEBUGP (("[TAP] MiniportName failed\n")); + status = NDIS_STATUS_RESOURCES; + } + } + } + else + { + /* "MiniportName" is available only XP and above. Not on Windows 2000. */ + if (vstatus == NDIS_STATUS_SUCCESS && vparm->ParameterData.IntegerData == 0x50000) + { + /* Fallback for Windows 2000 with NDIS version 5.00.00 + Don't use this on Vista, 'NDIS_MINIPORT_BLOCK' was changed! */ + if (RtlUnicodeStringToAnsiString (&l_Adapter->m_NameAnsi, &((struct WIN2K_NDIS_MINIPORT_BLOCK *) p_AdapterHandle)->MiniportName, TRUE) != STATUS_SUCCESS) + { + DEBUGP (("[TAP] MiniportName (W2K) failed\n")); + status = NDIS_STATUS_RESOURCES; + } + else + { + DEBUGP (("[TAP] MiniportName (W2K) succeeded: %s\n", l_Adapter->m_NameAnsi.Buffer)); + status = NDIS_STATUS_SUCCESS; + } + } + } + } + + /* Can't continue without name (see macro 'NAME') */ + if (status != NDIS_STATUS_SUCCESS || !l_Adapter->m_NameAnsi.Buffer) { - DEBUGP (("[TAP] MiniportName (W2K) failed\n")); - status = NDIS_STATUS_RESOURCES; + NdisCloseConfiguration (configHandle); + AdapterFreeResources (l_Adapter); + DEBUGP (("[TAP] failed to get miniport name\n")); + return NDIS_STATUS_RESOURCES; } - else + + /* Read MTU setting from registry */ { - DEBUGP (("[TAP] MiniportName (W2K) succeeded: %s\n", l_Adapter->m_NameAnsi.Buffer)); - status = NDIS_STATUS_SUCCESS; + NDIS_STRING key = NDIS_STRING_CONST("MTU"); + NdisReadConfiguration (&status, &parm, configHandle, + &key, NdisParameterInteger); + if (status == NDIS_STATUS_SUCCESS) + { + if (parm->ParameterType == NdisParameterInteger) + { + int mtu = parm->ParameterData.IntegerData; + if (mtu < MINIMUM_MTU) + mtu = MINIMUM_MTU; + if (mtu > MAXIMUM_MTU) + mtu = MAXIMUM_MTU; + l_Adapter->m_MTU = mtu; + } + } } - } - } - } - /* Can't continue without name (see macro 'NAME') */ - if (status != NDIS_STATUS_SUCCESS || !l_Adapter->m_NameAnsi.Buffer) - { - NdisCloseConfiguration (configHandle); - AdapterFreeResources (l_Adapter); - DEBUGP (("[TAP] failed to get miniport name\n")); - return NDIS_STATUS_RESOURCES; - } - - /* Read MTU setting from registry */ - { - NDIS_STRING key = NDIS_STRING_CONST("MTU"); - NdisReadConfiguration (&status, &parm, configHandle, - &key, NdisParameterInteger); - if (status == NDIS_STATUS_SUCCESS) - { - if (parm->ParameterType == NdisParameterInteger) - { - int mtu = parm->ParameterData.IntegerData; - if (mtu < MINIMUM_MTU) - mtu = MINIMUM_MTU; - if (mtu > MAXIMUM_MTU) - mtu = MAXIMUM_MTU; - l_Adapter->m_MTU = mtu; - } - } - } - - /* Read Media Status setting from registry */ - { - NDIS_STRING key = NDIS_STRING_CONST("MediaStatus"); - NdisReadConfiguration (&status, &parm, configHandle, - &key, NdisParameterInteger); - if (status == NDIS_STATUS_SUCCESS) - { - if (parm->ParameterType == NdisParameterInteger) - { - if (parm->ParameterData.IntegerData) + /* Read Media Status setting from registry */ { - l_Adapter->m_MediaStateAlwaysConnected = TRUE; - l_Adapter->m_MediaState = TRUE; + NDIS_STRING key = NDIS_STRING_CONST("MediaStatus"); + NdisReadConfiguration (&status, &parm, configHandle, + &key, NdisParameterInteger); + if (status == NDIS_STATUS_SUCCESS) + { + if (parm->ParameterType == NdisParameterInteger) + { + if (parm->ParameterData.IntegerData) + { + l_Adapter->m_MediaStateAlwaysConnected = TRUE; + l_Adapter->m_MediaState = TRUE; + } + } + } } - } - } - } - -#if ENABLE_NONADMIN - /* Read AllowNonAdmin setting from registry */ - { - NDIS_STRING key = NDIS_STRING_CONST("AllowNonAdmin"); - NdisReadConfiguration (&status, &parm, configHandle, - &key, NdisParameterInteger); - if (status == NDIS_STATUS_SUCCESS) - { - if (parm->ParameterType == NdisParameterInteger) - { - if (parm->ParameterData.IntegerData) + + /* Read optional MAC setting from registry */ { - enable_non_admin = TRUE; + NDIS_STRING key = NDIS_STRING_CONST("MAC"); + ANSI_STRING mac_string; + NdisReadConfiguration (&status, &parm, configHandle, + &key, NdisParameterString); + if (status == NDIS_STATUS_SUCCESS) + { + if (parm->ParameterType == NdisParameterString) + { + if (RtlUnicodeStringToAnsiString (&mac_string, &parm->ParameterData.StringData, TRUE) == STATUS_SUCCESS) + { + l_MacFromRegistry = ParseMAC (l_Adapter->m_MAC, mac_string.Buffer); + RtlFreeAnsiString (&mac_string); + } + } + } } - } + + NdisCloseConfiguration (configHandle); + + DEBUGP (("[%s] MTU=%d\n", NAME (l_Adapter), l_Adapter->m_MTU)); } - } -#endif - /* Read optional MAC setting from registry */ - { - NDIS_STRING key = NDIS_STRING_CONST("MAC"); - ANSI_STRING mac_string; - NdisReadConfiguration (&status, &parm, configHandle, - &key, NdisParameterString); - if (status == NDIS_STATUS_SUCCESS) + //================================== + // Store and update MAC address info + //================================== + + if (!l_MacFromRegistry) + GenerateRandomMac (l_Adapter->m_MAC, (const unsigned char *)NAME (l_Adapter)); + + DEBUGP (("[%s] Using MAC %x:%x:%x:%x:%x:%x\n", + NAME (l_Adapter), + l_Adapter->m_MAC[0], l_Adapter->m_MAC[1], l_Adapter->m_MAC[2], + l_Adapter->m_MAC[3], l_Adapter->m_MAC[4], l_Adapter->m_MAC[5])); + + //==================================== + // Initialize TAP device + //==================================== { - if (parm->ParameterType == NdisParameterString) - { - if (RtlUnicodeStringToAnsiString (&mac_string, &parm->ParameterData.StringData, TRUE) == STATUS_SUCCESS) + NDIS_STATUS tap_status; + tap_status = CreateTapDevice (&l_Adapter->m_Extension, NAME (l_Adapter)); + if (tap_status != NDIS_STATUS_SUCCESS) { - l_MacFromRegistry = ParseMAC (l_Adapter->m_MAC, mac_string.Buffer); - RtlFreeAnsiString (&mac_string); + AdapterFreeResources (l_Adapter); + DEBUGP (("[TAP] CreateTapDevice failed\n")); + return tap_status; } - } } - } - - NdisCloseConfiguration (configHandle); - - DEBUGP (("[%s] MTU=%d\n", NAME (l_Adapter), l_Adapter->m_MTU)); - } - - //================================== - // Store and update MAC address info - //================================== - - if (!l_MacFromRegistry) - GenerateRandomMac (l_Adapter->m_MAC, NAME (l_Adapter)); - - DEBUGP (("[%s] Using MAC %x:%x:%x:%x:%x:%x\n", - NAME (l_Adapter), - l_Adapter->m_MAC[0], l_Adapter->m_MAC[1], l_Adapter->m_MAC[2], - l_Adapter->m_MAC[3], l_Adapter->m_MAC[4], l_Adapter->m_MAC[5])); - -#if 0 - //================== - // Set broadcast MAC - //================== - { - int i; - for (i = 0; i < sizeof (MACADDR); ++i) - l_Adapter->m_MAC_Broadcast[i] = 0xFF; - } -#endif - //==================================== - // Initialize TAP device - //==================================== - { - NDIS_STATUS tap_status; - tap_status = CreateTapDevice (&l_Adapter->m_Extension, NAME (l_Adapter)); - if (tap_status != NDIS_STATUS_SUCCESS) - { - AdapterFreeResources (l_Adapter); - DEBUGP (("[TAP] CreateTapDevice failed\n")); - return tap_status; - } - } - - if (!AddAdapterToInstanceList (l_Adapter)) - { - NOTE_ERROR (); - TapDeviceFreeResources (&l_Adapter->m_Extension); - AdapterFreeResources (l_Adapter); - DEBUGP (("[TAP] AddAdapterToInstanceList failed\n")); - return NDIS_STATUS_RESOURCES; - } - - l_Adapter->m_InterfaceIsRunning = TRUE; - -#if ENABLE_NONADMIN - if (enable_non_admin) - AllowNonAdmin (&l_Adapter->m_Extension); -#endif + if (!AddAdapterToInstanceList (l_Adapter)) + { + NOTE_ERROR (); + TapDeviceFreeResources (&l_Adapter->m_Extension); + AdapterFreeResources (l_Adapter); + DEBUGP (("[TAP] AddAdapterToInstanceList failed\n")); + return NDIS_STATUS_RESOURCES; + } + + l_Adapter->m_InterfaceIsRunning = TRUE; - return NDIS_STATUS_SUCCESS; + return NDIS_STATUS_SUCCESS; } VOID -AdapterHalt (IN NDIS_HANDLE p_AdapterContext) + AdapterHalt (IN NDIS_HANDLE p_AdapterContext) { - BOOLEAN status; + BOOLEAN status; - TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext; + TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext; - NOTE_ERROR (); + NOTE_ERROR (); + + l_Adapter->m_InterfaceIsRunning = FALSE; - l_Adapter->m_InterfaceIsRunning = FALSE; + DEBUGP (("[%s] is being halted\n", NAME (l_Adapter))); - DEBUGP (("[%s] is being halted\n", NAME (l_Adapter))); - - DestroyTapDevice (&l_Adapter->m_Extension); + DestroyTapDevice (&l_Adapter->m_Extension); - // Free resources - DEBUGP (("[%s] Freeing Resources\n", NAME (l_Adapter))); - AdapterFreeResources (l_Adapter); + // Free resources + DEBUGP (("[%s] Freeing Resources\n", NAME (l_Adapter))); + AdapterFreeResources (l_Adapter); - status = RemoveAdapterFromInstanceList (l_Adapter); - DEBUGP (("[TAP] RemoveAdapterFromInstanceList returned %d\n", (int) status)); + status = RemoveAdapterFromInstanceList (l_Adapter); + DEBUGP (("[TAP] RemoveAdapterFromInstanceList returned %d\n", (int) status)); - DEBUGP (("[TAP] version [%d.%d] %s %s AdapterHalt returning\n", - TAP_DRIVER_MAJOR_VERSION, - TAP_DRIVER_MINOR_VERSION, - __DATE__, - __TIME__)); + DEBUGP (("[TAP] version [%d.%d] %s %s AdapterHalt returning\n", + TAP_DRIVER_MAJOR_VERSION, + TAP_DRIVER_MINOR_VERSION, + __DATE__, + __TIME__)); } VOID -AdapterFreeResources (TapAdapterPointer p_Adapter) + AdapterFreeResources (TapAdapterPointer p_Adapter) { - MYASSERT (!p_Adapter->m_CalledAdapterFreeResources); - p_Adapter->m_CalledAdapterFreeResources = TRUE; + MYASSERT (!p_Adapter->m_CalledAdapterFreeResources); + p_Adapter->m_CalledAdapterFreeResources = TRUE; + + if (p_Adapter->m_NameAnsi.Buffer) + RtlFreeAnsiString (&p_Adapter->m_NameAnsi); - if (p_Adapter->m_NameAnsi.Buffer) - RtlFreeAnsiString (&p_Adapter->m_NameAnsi); - - if (p_Adapter->m_RegisteredAdapterShutdownHandler) - NdisMDeregisterAdapterShutdownHandler (p_Adapter->m_MiniportAdapterHandle); + if (p_Adapter->m_RegisteredAdapterShutdownHandler) + NdisMDeregisterAdapterShutdownHandler (p_Adapter->m_MiniportAdapterHandle); - if (p_Adapter->m_MCLockAllocated) - NdisFreeSpinLock (&p_Adapter->m_MCLock); + if (p_Adapter->m_MCLockAllocated) + NdisFreeSpinLock (&p_Adapter->m_MCLock); } VOID -DestroyTapDevice (TapExtensionPointer p_Extension) + DestroyTapDevice (TapExtensionPointer p_Extension) { - DEBUGP (("[%s] Destroying tap device\n", p_Extension->m_TapName)); - - //====================================== - // Let clients know we are shutting down - //====================================== - p_Extension->m_TapIsRunning = FALSE; - p_Extension->m_TapOpens = 0; - p_Extension->m_Halt = TRUE; - - //===================================== - // If we are concurrently executing in - // TapDeviceHook or AdapterTransmit, - // give those calls time to finish. - // Note that we must be running at IRQL - // < DISPATCH_LEVEL in order to call - // NdisMSleep. - //===================================== - NdisMSleep (500000); - - //=========================================================== - // Exhaust IRP and packet queues. Any pending IRPs will - // be cancelled, causing user-space to get this error - // on overlapped reads: - // The I/O operation has been aborted because of either a - // thread exit or an application request. (code=995) - // It's important that user-space close the device handle - // when this code is returned, so that when we finally - // do a NdisMDeregisterDevice, the device reference count - // is 0. Otherwise the driver will not unload even if the - // the last adapter has been halted. - //=========================================================== - FlushQueues (p_Extension); - NdisMSleep (500000); // give user space time to respond to IRP cancel - - TapDeviceFreeResources (p_Extension); + DEBUGP (("[%s] Destroying tap device\n", p_Extension->m_TapName)); + + //====================================== + // Let clients know we are shutting down + //====================================== + p_Extension->m_TapIsRunning = FALSE; + p_Extension->m_TapOpens = 0; + p_Extension->m_Halt = TRUE; + + //===================================== + // If we are concurrently executing in + // TapDeviceHook or AdapterTransmit, + // give those calls time to finish. + // Note that we must be running at IRQL + // < DISPATCH_LEVEL in order to call + // NdisMSleep. + //===================================== + NdisMSleep (500000); + + //=========================================================== + // Exhaust IRP and packet queues. Any pending IRPs will + // be cancelled, causing user-space to get this error + // on overlapped reads: + // The I/O operation has been aborted because of either a + // thread exit or an application request. (code=995) + // It's important that user-space close the device handle + // when this code is returned, so that when we finally + // do a NdisMDeregisterDevice, the device reference count + // is 0. Otherwise the driver will not unload even if the + // the last adapter has been halted. + //=========================================================== + FlushQueues (p_Extension); + NdisMSleep (500000); // give user space time to respond to IRP cancel + + TapDeviceFreeResources (p_Extension); } VOID -TapDeviceFreeResources (TapExtensionPointer p_Extension) + TapDeviceFreeResources (TapExtensionPointer p_Extension) { - MYASSERT (p_Extension); - MYASSERT (!p_Extension->m_CalledTapDeviceFreeResources); - p_Extension->m_CalledTapDeviceFreeResources = TRUE; - - if (p_Extension->m_PacketQueue) - 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); - - //========================================================== - // According to DDK docs, the device is not actually deleted - // until its reference count falls to zero. That means we - // still need to gracefully fail TapDeviceHook requests - // after this point, otherwise ugly things would happen if - // the device was disabled (e.g. in the network connections - // control panel) while a userspace app still held an open - // file handle to it. - //========================================================== - - if (p_Extension->m_TapDevice) - { - BOOLEAN status; - status = (NdisMDeregisterDevice (p_Extension->m_TapDeviceHandle) - == NDIS_STATUS_SUCCESS); - DEBUGP (("[TAP] Deregistering TAP device, status=%d\n", (int)status)); - } - - 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_InjectLock); - } + MYASSERT (p_Extension); + MYASSERT (!p_Extension->m_CalledTapDeviceFreeResources); + p_Extension->m_CalledTapDeviceFreeResources = TRUE; + + if (p_Extension->m_PacketQueue) + QueueFree (p_Extension->m_PacketQueue); + if (p_Extension->m_IrpQueue) + QueueFree (p_Extension->m_IrpQueue); + + if (p_Extension->m_CreatedUnicodeLinkName) + RtlFreeUnicodeString (&p_Extension->m_UnicodeLinkName); + + //========================================================== + // According to DDK docs, the device is not actually deleted + // until its reference count falls to zero. That means we + // still need to gracefully fail TapDeviceHook requests + // after this point, otherwise ugly things would happen if + // the device was disabled (e.g. in the network connections + // control panel) while a userspace app still held an open + // file handle to it. + //========================================================== + + if (p_Extension->m_TapDevice) + { + BOOLEAN status; + status = (NdisMDeregisterDevice (p_Extension->m_TapDeviceHandle) + == NDIS_STATUS_SUCCESS); + DEBUGP (("[TAP] Deregistering TAP device, status=%d\n", (int)status)); + } + + if (p_Extension->m_TapName) + MemFree (p_Extension->m_TapName, NAME_BUFFER_SIZE); + + if (p_Extension->m_AllocatedSpinlocks) + { + NdisFreeSpinLock (&p_Extension->m_QueueLock); + } } //======================================================================== @@ -733,1878 +671,1250 @@ TapDeviceFreeResources (TapExtensionPointer p_Extension) //======================================================================== NDIS_STATUS -CreateTapDevice (TapExtensionPointer p_Extension, const char *p_Name) + CreateTapDevice (TapExtensionPointer p_Extension, const char *p_Name) { # define SIZEOF_DISPATCH (sizeof(PDRIVER_DISPATCH) * (IRP_MJ_MAXIMUM_FUNCTION + 1)) - PDRIVER_DISPATCH *l_Dispatch = NULL; - ANSI_STRING l_TapString, l_LinkString; - UNICODE_STRING l_TapUnicode; - BOOLEAN l_FreeTapUnicode = FALSE; - NTSTATUS l_Status, l_Return = NDIS_STATUS_SUCCESS; - const char *l_UsableName; - - DEBUGP (("[TAP] version [%d.%d] creating tap device: %s\n", - TAP_DRIVER_MAJOR_VERSION, - TAP_DRIVER_MINOR_VERSION, - p_Name)); - - NdisZeroMemory (p_Extension, sizeof (TapExtension)); - - INIT_MUTEX (&p_Extension->m_OpenCloseMutex); - - l_LinkString.Buffer = NULL; - l_TapString.Buffer = NULL; - - l_TapString.MaximumLength = l_LinkString.MaximumLength = NAME_BUFFER_SIZE; - - //======================================= - // Set TAP device entry points - //======================================= - - if ((l_Dispatch = MemAlloc (SIZEOF_DISPATCH, TRUE)) == NULL) - { - DEBUGP (("[%s] couldn't alloc TAP dispatch table\n", p_Name)); - l_Return = NDIS_STATUS_RESOURCES; - goto cleanup; - } - - l_Dispatch[IRP_MJ_DEVICE_CONTROL] = TapDeviceHook; - l_Dispatch[IRP_MJ_READ] = TapDeviceHook; - l_Dispatch[IRP_MJ_WRITE] = TapDeviceHook; - l_Dispatch[IRP_MJ_CREATE] = TapDeviceHook; - l_Dispatch[IRP_MJ_CLOSE] = TapDeviceHook; - - //================================== - // Find the beginning of the GUID - //================================== - l_UsableName = p_Name; - while (*l_UsableName != '{') - { - if (*l_UsableName == '\0') - { - DEBUGP (("[%s] couldn't find leading '{' in name\n", p_Name)); - l_Return = NDIS_STATUS_RESOURCES; - goto cleanup; - } - ++l_UsableName; - } - - //================================== - // Allocate pool for TAP device name - //================================== - - if ((p_Extension->m_TapName = l_TapString.Buffer = - MemAlloc (NAME_BUFFER_SIZE, TRUE)) == NULL) - { - DEBUGP (("[%s] couldn't alloc TAP name buffer\n", p_Name)); - l_Return = NDIS_STATUS_RESOURCES; - goto cleanup; - } - - //================================================ - // Allocate pool for TAP symbolic link name buffer - //================================================ - - if ((l_LinkString.Buffer = - MemAlloc (NAME_BUFFER_SIZE, TRUE)) == NULL) - { - DEBUGP (("[%s] couldn't alloc TAP symbolic link name buffer\n", - p_Name)); - l_Return = NDIS_STATUS_RESOURCES; - goto cleanup; - } - - //======================================================= - // Set TAP device name - //======================================================= - - l_Status = RtlStringCchPrintfExA - (l_TapString.Buffer, - l_TapString.MaximumLength, - NULL, - NULL, - STRSAFE_FILL_BEHIND_NULL | STRSAFE_IGNORE_NULLS, - "%s%s%s", - SYSDEVICEDIR, - l_UsableName, - TAP_WIN_SUFFIX); - - if (l_Status != STATUS_SUCCESS) - { - DEBUGP (("[%s] couldn't format TAP device name\n", - p_Name)); - l_Return = NDIS_STATUS_RESOURCES; - goto cleanup; - } - l_TapString.Length = (USHORT) strlen (l_TapString.Buffer); - - DEBUGP (("TAP DEV NAME: '%s'\n", l_TapString.Buffer)); - - //======================================================= - // Set TAP link name - //======================================================= - - l_Status = RtlStringCchPrintfExA - (l_LinkString.Buffer, - l_LinkString.MaximumLength, - NULL, - NULL, - STRSAFE_FILL_BEHIND_NULL | STRSAFE_IGNORE_NULLS, - "%s%s%s", - USERDEVICEDIR, - l_UsableName, - TAP_WIN_SUFFIX); - - if (l_Status != STATUS_SUCCESS) - { - DEBUGP (("[%s] couldn't format TAP device symbolic link\n", - p_Name)); - l_Return = NDIS_STATUS_RESOURCES; - goto cleanup; - } - l_LinkString.Length = (USHORT) strlen (l_LinkString.Buffer); - - DEBUGP (("TAP LINK NAME: '%s'\n", l_LinkString.Buffer)); - - //================================================== - // Convert strings to unicode - //================================================== - if (RtlAnsiStringToUnicodeString (&l_TapUnicode, &l_TapString, TRUE) != - STATUS_SUCCESS) - { - DEBUGP (("[%s] couldn't alloc TAP unicode name buffer\n", + PDRIVER_DISPATCH *l_Dispatch = NULL; + ANSI_STRING l_TapString, l_LinkString; + UNICODE_STRING l_TapUnicode; + BOOLEAN l_FreeTapUnicode = FALSE; + NTSTATUS l_Status, l_Return = NDIS_STATUS_SUCCESS; + const char *l_UsableName; + + DEBUGP (("[TAP] version [%d.%d] creating tap device: %s\n", + TAP_DRIVER_MAJOR_VERSION, + TAP_DRIVER_MINOR_VERSION, p_Name)); - l_Return = NDIS_STATUS_RESOURCES; - goto cleanup; - } - l_FreeTapUnicode = TRUE; - - if (RtlAnsiStringToUnicodeString - (&p_Extension->m_UnicodeLinkName, &l_LinkString, TRUE) - != STATUS_SUCCESS) - { - DEBUGP - (("[%s] Couldn't allocate unicode string for symbolic link name\n", - p_Name)); - l_Return = NDIS_STATUS_RESOURCES; - goto cleanup; - } - p_Extension->m_CreatedUnicodeLinkName = TRUE; - - //================================================== - // Create new TAP device with symbolic - // link and associate with adapter. - //================================================== - - l_Status = NdisMRegisterDevice - (g_NdisWrapperHandle, - &l_TapUnicode, - &p_Extension->m_UnicodeLinkName, - l_Dispatch, - &p_Extension->m_TapDevice, - &p_Extension->m_TapDeviceHandle - ); - - if (l_Status != STATUS_SUCCESS) - { - DEBUGP (("[%s] couldn't be created\n", p_Name)); - l_Return = NDIS_STATUS_RESOURCES; - goto cleanup; - } - - /* Set TAP device flags */ - p_Extension->m_TapDevice->Flags |= DO_DIRECT_IO; - - //======================================================== - // Initialize Packet and IRP queues. - // - // The packet queue is used to buffer data which has been - // "transmitted" by the virtual NIC, before user space - // has had a chance to read it. - // - // The IRP queue is used to buffer pending I/O requests - // from userspace, i.e. read requests on the TAP device - // waiting for the system to "transmit" something through - // the virtual NIC. - // - // Basically, packets in the packet queue are used - // to satisfy IRP requests in the IRP queue. - // - // QueueLock is used to lock the packet queue used - // for the TAP-Windows NIC -> User Space packet flow direction. - // - // All accesses to packet or IRP queues should be - // bracketed by the QueueLock spinlock, - // in order to be SMP-safe. - //======================================================== - - 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_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 - //======================== - - p_Extension->m_TapIsRunning = TRUE; - - DEBUGP (("[%s] successfully created TAP device [%s]\n", p_Name, - p_Extension->m_TapName)); - - cleanup: - if (l_FreeTapUnicode) - RtlFreeUnicodeString (&l_TapUnicode); - if (l_LinkString.Buffer) - MemFree (l_LinkString.Buffer, NAME_BUFFER_SIZE); - if (l_Dispatch) - MemFree (l_Dispatch, SIZEOF_DISPATCH); - - if (l_Return != NDIS_STATUS_SUCCESS) - TapDeviceFreeResources (p_Extension); - - return l_Return; -} -#undef SIZEOF_DISPATCH -//======================================================== -// Adapter Control -//======================================================== -NDIS_STATUS -AdapterReset (OUT PBOOLEAN p_AddressingReset, IN NDIS_HANDLE p_AdapterContext) -{ - TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext; - DEBUGP (("[%s] is resetting\n", NAME (l_Adapter))); - return NDIS_STATUS_SUCCESS; -} + NdisZeroMemory (p_Extension, sizeof (TapExtension)); -NDIS_STATUS AdapterReceive - (OUT PNDIS_PACKET p_Packet, - OUT PUINT p_Transferred, - IN NDIS_HANDLE p_AdapterContext, - IN NDIS_HANDLE p_ReceiveContext, - IN UINT p_Offset, - IN UINT p_ToTransfer) -{ - return NDIS_STATUS_SUCCESS; -} + INIT_MUTEX (&p_Extension->m_OpenCloseMutex); -//============================================================== -// Adapter Option Query/Modification -//============================================================== -NDIS_STATUS AdapterQuery -(IN NDIS_HANDLE p_AdapterContext, - IN NDIS_OID p_OID, - IN PVOID p_Buffer, - IN ULONG p_BufferLength, - OUT PULONG p_BytesWritten, OUT PULONG p_BytesNeeded) -{ - TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext; - TapAdapterQuery l_Query, *l_QueryPtr = &l_Query; - NDIS_STATUS l_Status = NDIS_STATUS_SUCCESS; - UINT l_QueryLength = 4; - BOOLEAN lock_succeeded; - - NdisZeroMemory (&l_Query, sizeof (l_Query)); - - switch (p_OID) - { - //=================================================================== - // Vendor & Driver version Info - //=================================================================== - case OID_GEN_VENDOR_DESCRIPTION: - l_QueryPtr = (TapAdapterQueryPointer) PRODUCT_TAP_WIN_DEVICE_DESCRIPTION; - l_QueryLength = strlen (PRODUCT_TAP_WIN_DEVICE_DESCRIPTION) + 1; - break; - - case OID_GEN_VENDOR_ID: - l_Query.m_Long = 0xffffff; - break; - - case OID_GEN_DRIVER_VERSION: - l_Query.m_Short = - (((USHORT) TAP_NDIS_MAJOR_VERSION) << 8 | (USHORT) - TAP_NDIS_MINOR_VERSION); - l_QueryLength = sizeof (unsigned short); - break; - - case OID_GEN_VENDOR_DRIVER_VERSION: - l_Query.m_Long = - (((USHORT) PRODUCT_TAP_WIN_MAJOR) << 8 | (USHORT) - PRODUCT_TAP_WIN_MINOR); - break; - - //================================================================= - // Statistics - //================================================================= - case OID_GEN_RCV_NO_BUFFER: - l_Query.m_Long = 0; - break; - - case OID_802_3_RCV_ERROR_ALIGNMENT: - l_Query.m_Long = 0; - break; - - case OID_802_3_XMIT_ONE_COLLISION: - l_Query.m_Long = 0; - break; - - case OID_802_3_XMIT_MORE_COLLISIONS: - l_Query.m_Long = 0; - break; - - case OID_GEN_XMIT_OK: - l_Query.m_Long = l_Adapter->m_Tx; - break; - - case OID_GEN_RCV_OK: - l_Query.m_Long = l_Adapter->m_Rx; - break; - - case OID_GEN_XMIT_ERROR: - l_Query.m_Long = l_Adapter->m_TxErr; - break; - - case OID_GEN_RCV_ERROR: - l_Query.m_Long = l_Adapter->m_RxErr; - break; - - //=================================================================== - // Device & Protocol Options - //=================================================================== - case OID_GEN_SUPPORTED_LIST: - l_QueryPtr = (TapAdapterQueryPointer) g_SupportedOIDList; - l_QueryLength = sizeof (g_SupportedOIDList); - break; - - case OID_GEN_MAC_OPTIONS: - // This MUST be here !!! - l_Query.m_Long = (NDIS_MAC_OPTION_RECEIVE_SERIALIZED - | NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA - | NDIS_MAC_OPTION_NO_LOOPBACK - | NDIS_MAC_OPTION_TRANSFERS_NOT_PEND); + l_LinkString.Buffer = NULL; + l_TapString.Buffer = NULL; - break; - - case OID_GEN_CURRENT_PACKET_FILTER: - l_Query.m_Long = - (NDIS_PACKET_TYPE_ALL_LOCAL | - NDIS_PACKET_TYPE_BROADCAST | - NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_ALL_FUNCTIONAL); - - break; - - case OID_GEN_PROTOCOL_OPTIONS: - l_Query.m_Long = 0; - break; - - //================================================================== - // Device Info - //================================================================== - case OID_GEN_MEDIA_CONNECT_STATUS: - l_Query.m_Long = l_Adapter->m_MediaState - ? NdisMediaStateConnected : NdisMediaStateDisconnected; - break; - - case OID_GEN_HARDWARE_STATUS: - l_Query.m_HardwareStatus = NdisHardwareStatusReady; - l_QueryLength = sizeof (NDIS_HARDWARE_STATUS); - break; - - case OID_GEN_MEDIA_SUPPORTED: - case OID_GEN_MEDIA_IN_USE: - l_Query.m_Medium = l_Adapter->m_Medium; - l_QueryLength = sizeof (NDIS_MEDIUM); - break; - - case OID_GEN_PHYSICAL_MEDIUM: - l_Query.m_PhysicalMedium = NdisPhysicalMediumUnspecified; - l_QueryLength = sizeof (NDIS_PHYSICAL_MEDIUM); - break; - - case OID_GEN_LINK_SPEED: - l_Query.m_Long = 100000; // rate / 100 bps - break; - - case OID_802_3_PERMANENT_ADDRESS: - case OID_802_3_CURRENT_ADDRESS: - COPY_MAC (l_Query.m_MacAddress, l_Adapter->m_MAC); - l_QueryLength = sizeof (MACADDR); - break; - - //================================================================== - // Limits - //================================================================== - - case OID_GEN_MAXIMUM_SEND_PACKETS: - l_Query.m_Long = 1; - break; - - case OID_802_3_MAXIMUM_LIST_SIZE: - l_Query.m_Long = NIC_MAX_MCAST_LIST; - break; - - case OID_GEN_CURRENT_LOOKAHEAD: - l_Query.m_Long = l_Adapter->m_Lookahead; - break; - - case OID_GEN_MAXIMUM_LOOKAHEAD: - case OID_GEN_MAXIMUM_TOTAL_SIZE: - case OID_GEN_RECEIVE_BUFFER_SPACE: - case OID_GEN_RECEIVE_BLOCK_SIZE: - l_Query.m_Long = DEFAULT_PACKET_LOOKAHEAD; - break; - - case OID_GEN_MAXIMUM_FRAME_SIZE: - case OID_GEN_TRANSMIT_BLOCK_SIZE: - case OID_GEN_TRANSMIT_BUFFER_SPACE: - l_Query.m_Long = l_Adapter->m_MTU; - break; - - case OID_PNP_CAPABILITIES: - do - { - PNDIS_PNP_CAPABILITIES pPNPCapabilities; - PNDIS_PM_WAKE_UP_CAPABILITIES pPMstruct; - - if (p_BufferLength >= sizeof (NDIS_PNP_CAPABILITIES)) - { - pPNPCapabilities = (PNDIS_PNP_CAPABILITIES) (p_Buffer); - - // - // Setting up the buffer to be returned - // to the Protocol above the Passthru miniport - // - pPMstruct = &pPNPCapabilities->WakeUpCapabilities; - pPMstruct->MinMagicPacketWakeUp = NdisDeviceStateUnspecified; - pPMstruct->MinPatternWakeUp = NdisDeviceStateUnspecified; - pPMstruct->MinLinkChangeWakeUp = NdisDeviceStateUnspecified; - } - l_QueryLength = sizeof (NDIS_PNP_CAPABILITIES); - } - while (FALSE); - break; - case OID_PNP_QUERY_POWER: - break; - - // Required OIDs that we don't support - - case OID_GEN_SUPPORTED_GUIDS: - case OID_GEN_MEDIA_CAPABILITIES: - case OID_TCP_TASK_OFFLOAD: - case OID_FFP_SUPPORT: - l_Status = NDIS_STATUS_INVALID_OID; - break; - - // Optional stats OIDs - - case OID_GEN_DIRECTED_BYTES_XMIT: - case OID_GEN_DIRECTED_FRAMES_XMIT: - case OID_GEN_MULTICAST_BYTES_XMIT: - case OID_GEN_MULTICAST_FRAMES_XMIT: - case OID_GEN_BROADCAST_BYTES_XMIT: - case OID_GEN_BROADCAST_FRAMES_XMIT: - case OID_GEN_DIRECTED_BYTES_RCV: - case OID_GEN_DIRECTED_FRAMES_RCV: - case OID_GEN_MULTICAST_BYTES_RCV: - case OID_GEN_MULTICAST_FRAMES_RCV: - case OID_GEN_BROADCAST_BYTES_RCV: - case OID_GEN_BROADCAST_FRAMES_RCV: - l_Status = NDIS_STATUS_INVALID_OID; - break; - - //=================================================================== - // Not Handled - //=================================================================== - default: - DEBUGP (("[%s] Unhandled OID %lx\n", NAME (l_Adapter), p_OID)); - l_Status = NDIS_STATUS_INVALID_OID; - break; - } - - if (l_Status != NDIS_STATUS_SUCCESS) - ; - else if (l_QueryLength > p_BufferLength) - { - l_Status = NDIS_STATUS_INVALID_LENGTH; - *p_BytesNeeded = l_QueryLength; - } - else - NdisMoveMemory (p_Buffer, (PVOID) l_QueryPtr, - (*p_BytesWritten = l_QueryLength)); - - return l_Status; -} + l_TapString.MaximumLength = l_LinkString.MaximumLength = NAME_BUFFER_SIZE; -NDIS_STATUS AdapterModify -(IN NDIS_HANDLE p_AdapterContext, - IN NDIS_OID p_OID, - IN PVOID p_Buffer, - IN ULONG p_BufferLength, - OUT PULONG p_BytesRead, - OUT PULONG p_BytesNeeded) -{ - TapAdapterQueryPointer l_Query = (TapAdapterQueryPointer) p_Buffer; - TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext; - NDIS_STATUS l_Status = NDIS_STATUS_INVALID_OID; - ULONG l_Long; - - switch (p_OID) - { - //================================================================== - // Device Info - //================================================================== - case OID_802_3_MULTICAST_LIST: - DEBUGP (("[%s] Setting [OID_802_3_MULTICAST_LIST]\n", - NAME (l_Adapter))); - - *p_BytesNeeded = sizeof (ETH_ADDR); - *p_BytesRead = p_BufferLength; - - if (p_BufferLength % sizeof (ETH_ADDR)) - l_Status = NDIS_STATUS_INVALID_LENGTH; - else if (p_BufferLength > sizeof (MC_LIST)) + //======================================= + // Set TAP device entry points + //======================================= + + if ((l_Dispatch = MemAlloc (SIZEOF_DISPATCH, TRUE)) == NULL) { - l_Status = NDIS_STATUS_MULTICAST_FULL; - *p_BytesNeeded = sizeof (MC_LIST); + DEBUGP (("[%s] couldn't alloc TAP dispatch table\n", p_Name)); + l_Return = NDIS_STATUS_RESOURCES; + goto cleanup; } - else - { - NdisAcquireSpinLock (&l_Adapter->m_MCLock); - NdisZeroMemory(&l_Adapter->m_MCList, sizeof (MC_LIST)); - - NdisMoveMemory(&l_Adapter->m_MCList, - p_Buffer, - p_BufferLength); + l_Dispatch[IRP_MJ_DEVICE_CONTROL] = TapDeviceHook; + l_Dispatch[IRP_MJ_READ] = TapDeviceHook; + l_Dispatch[IRP_MJ_WRITE] = TapDeviceHook; + l_Dispatch[IRP_MJ_CREATE] = TapDeviceHook; + l_Dispatch[IRP_MJ_CLOSE] = TapDeviceHook; - l_Adapter->m_MCListSize = p_BufferLength / sizeof (ETH_ADDR); - - NdisReleaseSpinLock (&l_Adapter->m_MCLock); - - l_Status = NDIS_STATUS_SUCCESS; + //================================== + // Find the beginning of the GUID + //================================== + l_UsableName = p_Name; + while (*l_UsableName != '{') + { + if (*l_UsableName == '\0') + { + DEBUGP (("[%s] couldn't find leading '{' in name\n", p_Name)); + l_Return = NDIS_STATUS_RESOURCES; + goto cleanup; + } + ++l_UsableName; } - break; - case OID_GEN_CURRENT_PACKET_FILTER: - l_Status = NDIS_STATUS_INVALID_LENGTH; - *p_BytesNeeded = 4; + //================================== + // Allocate pool for TAP device name + //================================== - if (p_BufferLength >= sizeof (ULONG)) + if ((p_Extension->m_TapName = l_TapString.Buffer = + MemAlloc (NAME_BUFFER_SIZE, TRUE)) == NULL) { - DEBUGP - (("[%s] Setting [OID_GEN_CURRENT_PACKET_FILTER] to [0x%02lx]\n", - NAME (l_Adapter), l_Query->m_Long)); - l_Status = NDIS_STATUS_SUCCESS; - *p_BytesRead = sizeof (ULONG); + DEBUGP (("[%s] couldn't alloc TAP name buffer\n", p_Name)); + l_Return = NDIS_STATUS_RESOURCES; + goto cleanup; } - break; - case OID_GEN_CURRENT_LOOKAHEAD: - if (p_BufferLength < sizeof (ULONG)) + //================================================ + // Allocate pool for TAP symbolic link name buffer + //================================================ + + if ((l_LinkString.Buffer = + (PCHAR)MemAlloc (NAME_BUFFER_SIZE, TRUE)) == NULL) { - l_Status = NDIS_STATUS_INVALID_LENGTH; - *p_BytesNeeded = 4; + DEBUGP (("[%s] couldn't alloc TAP symbolic link name buffer\n", + p_Name)); + l_Return = NDIS_STATUS_RESOURCES; + goto cleanup; } - else if (l_Query->m_Long > DEFAULT_PACKET_LOOKAHEAD - || l_Query->m_Long <= 0) + + //======================================================= + // Set TAP device name + //======================================================= + + l_Status = RtlStringCchPrintfExA + (l_TapString.Buffer, + l_TapString.MaximumLength, + NULL, + NULL, + STRSAFE_FILL_BEHIND_NULL | STRSAFE_IGNORE_NULLS, + "%s%s%s", + SYSDEVICEDIR, + l_UsableName, + TAP_WIN_SUFFIX); + + if (l_Status != STATUS_SUCCESS) { - l_Status = NDIS_STATUS_INVALID_DATA; + DEBUGP (("[%s] couldn't format TAP device name\n", + p_Name)); + l_Return = NDIS_STATUS_RESOURCES; + goto cleanup; } - else + l_TapString.Length = (USHORT) strlen (l_TapString.Buffer); + + DEBUGP (("TAP DEV NAME: '%s'\n", l_TapString.Buffer)); + + //======================================================= + // Set TAP link name + //======================================================= + + l_Status = RtlStringCchPrintfExA + (l_LinkString.Buffer, + l_LinkString.MaximumLength, + NULL, + NULL, + STRSAFE_FILL_BEHIND_NULL | STRSAFE_IGNORE_NULLS, + "%s%s%s", + USERDEVICEDIR, + l_UsableName, + TAP_WIN_SUFFIX); + + if (l_Status != STATUS_SUCCESS) { - DEBUGP (("[%s] Setting [OID_GEN_CURRENT_LOOKAHEAD] to [%d]\n", - NAME (l_Adapter), l_Query->m_Long)); - l_Adapter->m_Lookahead = l_Query->m_Long; - l_Status = NDIS_STATUS_SUCCESS; - *p_BytesRead = sizeof (ULONG); + DEBUGP (("[%s] couldn't format TAP device symbolic link\n", + p_Name)); + l_Return = NDIS_STATUS_RESOURCES; + goto cleanup; } - break; + l_LinkString.Length = (USHORT) strlen (l_LinkString.Buffer); - case OID_GEN_NETWORK_LAYER_ADDRESSES: - l_Status = NDIS_STATUS_SUCCESS; - *p_BytesRead = *p_BytesNeeded = 0; - break; + DEBUGP (("TAP LINK NAME: '%s'\n", l_LinkString.Buffer)); - case OID_GEN_TRANSPORT_HEADER_OFFSET: - l_Status = NDIS_STATUS_SUCCESS; - *p_BytesRead = *p_BytesNeeded = 0; - break; + //================================================== + // Convert strings to unicode + //================================================== + if (RtlAnsiStringToUnicodeString (&l_TapUnicode, &l_TapString, TRUE) != + STATUS_SUCCESS) + { + DEBUGP (("[%s] couldn't alloc TAP unicode name buffer\n", + p_Name)); + l_Return = NDIS_STATUS_RESOURCES; + goto cleanup; + } + l_FreeTapUnicode = TRUE; - case OID_PNP_SET_POWER: - do + if (RtlAnsiStringToUnicodeString + (&p_Extension->m_UnicodeLinkName, &l_LinkString, TRUE) + != STATUS_SUCCESS) { - NDIS_DEVICE_POWER_STATE NewDeviceState; - - NewDeviceState = (*(PNDIS_DEVICE_POWER_STATE) p_Buffer); - - switch (NewDeviceState) - { - case NdisDeviceStateD0: - l_Adapter->m_DeviceState = '0'; - break; - case NdisDeviceStateD1: - l_Adapter->m_DeviceState = '1'; - break; - case NdisDeviceStateD2: - l_Adapter->m_DeviceState = '2'; - break; - case NdisDeviceStateD3: - l_Adapter->m_DeviceState = '3'; - break; - default: - l_Adapter->m_DeviceState = '?'; - break; - } - - l_Status = NDIS_STATUS_FAILURE; - - // - // Check for invalid length - // - if (p_BufferLength < sizeof (NDIS_DEVICE_POWER_STATE)) - { - l_Status = NDIS_STATUS_INVALID_LENGTH; - break; - } - - if (NewDeviceState > NdisDeviceStateD0) - { - l_Adapter->m_InterfaceIsRunning = FALSE; - DEBUGP (("[%s] Power management device state OFF\n", - NAME (l_Adapter))); - } - else - { - l_Adapter->m_InterfaceIsRunning = TRUE; - DEBUGP (("[%s] Power management device state ON\n", - NAME (l_Adapter))); - } - - l_Status = NDIS_STATUS_SUCCESS; + DEBUGP + (("[%s] Couldn't allocate unicode string for symbolic link name\n", + p_Name)); + l_Return = NDIS_STATUS_RESOURCES; + goto cleanup; } - while (FALSE); + p_Extension->m_CreatedUnicodeLinkName = TRUE; + + //================================================== + // Create new TAP device with symbolic + // link and associate with adapter. + //================================================== + + l_Status = NdisMRegisterDevice + (g_NdisWrapperHandle, + &l_TapUnicode, + &p_Extension->m_UnicodeLinkName, + l_Dispatch, + &p_Extension->m_TapDevice, + &p_Extension->m_TapDeviceHandle + ); - if (l_Status == NDIS_STATUS_SUCCESS) + if (l_Status != STATUS_SUCCESS) { - *p_BytesRead = sizeof (NDIS_DEVICE_POWER_STATE); - *p_BytesNeeded = 0; + DEBUGP (("[%s] couldn't be created\n", p_Name)); + l_Return = NDIS_STATUS_RESOURCES; + goto cleanup; } - else + + /* Set TAP device flags */ + p_Extension->m_TapDevice->Flags |= DO_DIRECT_IO; + + //======================================================== + // Initialize Packet and IRP queues. + // + // The packet queue is used to buffer data which has been + // "transmitted" by the virtual NIC, before user space + // has had a chance to read it. + // + // The IRP queue is used to buffer pending I/O requests + // from userspace, i.e. read requests on the TAP device + // waiting for the system to "transmit" something through + // the virtual NIC. + // + // Basically, packets in the packet queue are used + // to satisfy IRP requests in the IRP queue. + // + // QueueLock is used to lock the packet queue used + // for the TAP-Windows NIC -> User Space packet flow direction. + // + // All accesses to packet or IRP queues should be + // bracketed by the QueueLock spinlock, + // in order to be SMP-safe. + //======================================================== + + NdisAllocateSpinLock (&p_Extension->m_QueueLock); + p_Extension->m_AllocatedSpinlocks = TRUE; + + p_Extension->m_PacketQueue = QueueInit (PACKET_QUEUE_SIZE); + p_Extension->m_IrpQueue = QueueInit (IRP_QUEUE_SIZE); + if (!p_Extension->m_PacketQueue + || !p_Extension->m_IrpQueue) { - *p_BytesRead = 0; - *p_BytesNeeded = sizeof (NDIS_DEVICE_POWER_STATE); + DEBUGP (("[%s] couldn't alloc TAP queues\n", p_Name)); + l_Return = NDIS_STATUS_RESOURCES; + goto cleanup; } - break; - - case OID_PNP_REMOVE_WAKE_UP_PATTERN: - case OID_PNP_ADD_WAKE_UP_PATTERN: - l_Status = NDIS_STATUS_SUCCESS; - *p_BytesRead = *p_BytesNeeded = 0; - break; - - default: - DEBUGP (("[%s] Can't set value for OID %lx\n", NAME (l_Adapter), - p_OID)); - l_Status = NDIS_STATUS_INVALID_OID; - *p_BytesRead = *p_BytesNeeded = 0; - break; - } - - return l_Status; + + //======================== + // Finalize initialization + //======================== + + p_Extension->m_TapIsRunning = TRUE; + + DEBUGP (("[%s] successfully created TAP device [%s]\n", p_Name, + p_Extension->m_TapName)); + +cleanup: + if (l_FreeTapUnicode) + RtlFreeUnicodeString (&l_TapUnicode); + if (l_LinkString.Buffer) + MemFree (l_LinkString.Buffer, NAME_BUFFER_SIZE); + if (l_Dispatch) + MemFree (l_Dispatch, SIZEOF_DISPATCH); + + if (l_Return != NDIS_STATUS_SUCCESS) + TapDeviceFreeResources (p_Extension); + + return l_Return; } +#undef SIZEOF_DISPATCH -// checksum code for ICMPv6 packet, taken from dhcp.c / udp_checksum -// see RFC 4443, 2.3, and RFC 2460, 8.1 -USHORT -icmpv6_checksum (const UCHAR *buf, - const int len_icmpv6, - const UCHAR *saddr6, - const UCHAR *daddr6) +//======================================================== +// Adapter Control +//======================================================== +NDIS_STATUS + AdapterReset (OUT PBOOLEAN p_AddressingReset, IN NDIS_HANDLE p_AdapterContext) { - USHORT word16; - ULONG sum = 0; - int i; - - // make 16 bit words out of every two adjacent 8 bit words and - // calculate the sum of all 16 bit words - for (i = 0; i < len_icmpv6; i += 2){ - word16 = ((buf[i] << 8) & 0xFF00) + ((i + 1 < len_icmpv6) ? (buf[i+1] & 0xFF) : 0); - sum += word16; - } - - // add the IPv6 pseudo header which contains the IP source and destination addresses - for (i = 0; i < 16; i += 2){ - word16 =((saddr6[i] << 8) & 0xFF00) + (saddr6[i+1] & 0xFF); - sum += word16; - } - for (i = 0; i < 16; i += 2){ - word16 =((daddr6[i] << 8) & 0xFF00) + (daddr6[i+1] & 0xFF); - sum += word16; - } - - // the next-header number and the length of the ICMPv6 packet - sum += (USHORT) IPPROTO_ICMPV6 + (USHORT) len_icmpv6; - - // keep only the last 16 bits of the 32 bit calculated sum and add the carries - while (sum >> 16) - sum = (sum & 0xFFFF) + (sum >> 16); - - // Take the one's complement of sum - return ((USHORT) ~sum); + TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext; + DEBUGP (("[%s] is resetting\n", NAME (l_Adapter))); + return NDIS_STATUS_SUCCESS; } -// check IPv6 packet for "is this an IPv6 Neighbor Solicitation that -// the tap driver needs to answer?" -// see RFC 4861 4.3 for the different cases -static IPV6ADDR IPV6_NS_TARGET_MCAST = - { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x08 }; -static IPV6ADDR IPV6_NS_TARGET_UNICAST = - { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08 }; - -#if 0 -BOOLEAN -HandleIPv6NeighborDiscovery( TapAdapterPointer p_Adapter, UCHAR * m_Data ) +NDIS_STATUS AdapterReceive + (OUT PNDIS_PACKET p_Packet, + OUT PUINT p_Transferred, + IN NDIS_HANDLE p_AdapterContext, + IN NDIS_HANDLE p_ReceiveContext, + IN UINT p_Offset, + IN UINT p_ToTransfer) { - const ETH_HEADER * e = (ETH_HEADER *) m_Data; - const IPV6HDR *ipv6 = (IPV6HDR *) (m_Data + sizeof (ETH_HEADER)); - const ICMPV6_NS * icmpv6_ns = (ICMPV6_NS *) (m_Data + sizeof (ETH_HEADER) + sizeof (IPV6HDR)); - ICMPV6_NA_PKT *na; - USHORT icmpv6_len, icmpv6_csum; - - // we don't really care about the destination MAC address here - // - it's either a multicast MAC, or the userland destination MAC - // but since the TAP driver is point-to-point, all packets are "for us" - - // IPv6 target address must be ff02::1::ff00:8 (multicast for - // initial NS) or fe80::1 (unicast for recurrent NUD) - if ( memcmp( ipv6->daddr, IPV6_NS_TARGET_MCAST, - sizeof(IPV6ADDR) ) != 0 && - memcmp( ipv6->daddr, IPV6_NS_TARGET_UNICAST, - sizeof(IPV6ADDR) ) != 0 ) - { - return FALSE; // wrong target address - } - - // IPv6 Next-Header must be ICMPv6 - if ( ipv6->nexthdr != IPPROTO_ICMPV6 ) - { - return FALSE; // wrong next-header - } - - // ICMPv6 type+code must be 135/0 for NS - if ( icmpv6_ns->type != ICMPV6_TYPE_NS || - icmpv6_ns->code != ICMPV6_CODE_0 ) - { - return FALSE; // wrong ICMPv6 type - } - - // ICMPv6 target address must be fe80::8 (magic) - if ( memcmp( icmpv6_ns->target_addr, IPV6_NS_TARGET_UNICAST, - sizeof(IPV6ADDR) ) != 0 ) - { - return FALSE; // not for us - } - - // packet identified, build magic response packet - - na = (ICMPV6_NA_PKT *) MemAlloc (sizeof (ICMPV6_NA_PKT), TRUE); - if ( !na ) return FALSE; - - //------------------------------------------------ - // Initialize Neighbour Advertisement reply packet - //------------------------------------------------ - - // ethernet header - na->eth.proto = htons(ETH_P_IPV6); - COPY_MAC(na->eth.dest, p_Adapter->m_MAC); - COPY_MAC(na->eth.src, p_Adapter->m_TapToUser.dest); - - // IPv6 header - na->ipv6.version_prio = ipv6->version_prio; - NdisMoveMemory( na->ipv6.flow_lbl, ipv6->flow_lbl, - sizeof(na->ipv6.flow_lbl) ); - icmpv6_len = sizeof(ICMPV6_NA_PKT) - sizeof(ETH_HEADER) - sizeof(IPV6HDR); - na->ipv6.payload_len = htons(icmpv6_len); - na->ipv6.nexthdr = IPPROTO_ICMPV6; - na->ipv6.hop_limit = 255; - NdisMoveMemory( na->ipv6.saddr, IPV6_NS_TARGET_UNICAST, - sizeof(IPV6ADDR) ); - NdisMoveMemory( na->ipv6.daddr, ipv6->saddr, - sizeof(IPV6ADDR) ); - - // ICMPv6 - na->icmpv6.type = ICMPV6_TYPE_NA; - na->icmpv6.code = ICMPV6_CODE_0; - na->icmpv6.checksum = 0; - na->icmpv6.rso_bits = 0x60; // Solicited + Override - NdisZeroMemory( na->icmpv6.reserved, sizeof(na->icmpv6.reserved) ); - NdisMoveMemory( na->icmpv6.target_addr, IPV6_NS_TARGET_UNICAST, - sizeof(IPV6ADDR) ); - - // ICMPv6 option "Target Link Layer Address" - na->icmpv6.opt_type = ICMPV6_OPTION_TLLA; - na->icmpv6.opt_length = ICMPV6_LENGTH_TLLA; - COPY_MAC( na->icmpv6.target_macaddr, p_Adapter->m_TapToUser.dest ); - - // calculate and set checksum - icmpv6_csum = icmpv6_checksum ( (UCHAR*) &(na->icmpv6), - icmpv6_len, - na->ipv6.saddr, - na->ipv6.daddr ); - na->icmpv6.checksum = htons( icmpv6_csum ); - - DUMP_PACKET ("HandleIPv6NeighborDiscovery", - (unsigned char *) na, - sizeof (ICMPV6_NA_PKT)); - - InjectPacketDeferred (p_Adapter, (UCHAR *) na, sizeof (ICMPV6_NA_PKT)); - - MemFree (na, sizeof (ICMPV6_NA_PKT)); - - return TRUE; // all fine + return NDIS_STATUS_SUCCESS; } -#endif -//==================================================================== -// Adapter Transmission -//==================================================================== -NDIS_STATUS -AdapterTransmit (IN NDIS_HANDLE p_AdapterContext, - IN PNDIS_PACKET p_Packet, - IN UINT p_Flags) +//============================================================== +// Adapter Option Query/Modification +//============================================================== +NDIS_STATUS AdapterQuery + (IN NDIS_HANDLE p_AdapterContext, + IN NDIS_OID p_OID, + IN PVOID p_Buffer, + IN ULONG p_BufferLength, + OUT PULONG p_BytesWritten, OUT PULONG p_BytesNeeded) { - TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext; - ULONG l_Index = 0, l_PacketLength = 0; - UINT l_BufferLength = 0; - PIRP l_IRP; - TapPacketPointer l_PacketBuffer; - PNDIS_BUFFER l_NDIS_Buffer; - PUCHAR l_Buffer; - PVOID result; - - NdisQueryPacket (p_Packet, NULL, NULL, &l_NDIS_Buffer, &l_PacketLength); - - //==================================================== - // Here we abandon the transmission attempt if any of - // the parameters is wrong or memory allocation fails - // but we do not indicate failure. The packet is - // silently dropped. - //==================================================== - - if (l_PacketLength < ETHERNET_HEADER_SIZE || l_PacketLength > 65535) - goto exit_fail; - else if (!l_Adapter->m_Extension.m_TapOpens || !l_Adapter->m_MediaState) - goto exit_success; // Nothing is bound to the TAP device - - if (NdisAllocateMemoryWithTag (&l_PacketBuffer, - TAP_PACKET_SIZE (l_PacketLength), - '5PAT') != NDIS_STATUS_SUCCESS) - goto exit_no_resources; - - if (l_PacketBuffer == NULL) - goto exit_no_resources; - - l_PacketBuffer->m_SizeFlags = (l_PacketLength & TP_SIZE_MASK); - - //=========================== - // Reassemble packet contents - //=========================== - - __try - { - l_Index = 0; - while (l_NDIS_Buffer && l_Index < l_PacketLength) - { - ULONG newlen; - NdisQueryBuffer (l_NDIS_Buffer, (PVOID *) & l_Buffer, - &l_BufferLength); - newlen = l_Index + l_BufferLength; - if (newlen > l_PacketLength) - { - NOTE_ERROR (); - goto no_queue; /* overflow */ - } - NdisMoveMemory (l_PacketBuffer->m_Data + l_Index, l_Buffer, - l_BufferLength); - l_Index = newlen; - NdisGetNextBuffer (l_NDIS_Buffer, &l_NDIS_Buffer); - } - if (l_Index != l_PacketLength) - { - NOTE_ERROR (); - goto no_queue; /* underflow */ - } - - DUMP_PACKET ("AdapterTransmit", l_PacketBuffer->m_Data, l_PacketLength); + TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext; + TapAdapterQuery l_Query, *l_QueryPtr = &l_Query; + NDIS_STATUS l_Status = NDIS_STATUS_SUCCESS; + UINT l_QueryLength = 4; + BOOLEAN lock_succeeded; - //===================================================== - // If IPv4 packet, check whether or not packet - // was truncated. - //===================================================== -#if PACKET_TRUNCATION_CHECK - IPv4PacketSizeVerify (l_PacketBuffer->m_Data, l_PacketLength, FALSE, "TX", &l_Adapter->m_TxTrunc); -#endif + NdisZeroMemory (&l_Query, sizeof (l_Query)); -#if 0 - //===================================================== - // Are we running in DHCP server masquerade mode? - // - // If so, catch both DHCP requests and ARP queries - // to resolve the address of our virtual DHCP server. - //===================================================== - if (l_Adapter->m_dhcp_enabled) - { - const ETH_HEADER *eth = (ETH_HEADER *) l_PacketBuffer->m_Data; - const IPHDR *ip = (IPHDR *) (l_PacketBuffer->m_Data + sizeof (ETH_HEADER)); - const UDPHDR *udp = (UDPHDR *) (l_PacketBuffer->m_Data + sizeof (ETH_HEADER) + sizeof (IPHDR)); - - // ARP packet? - if (l_PacketLength == sizeof (ARP_PACKET) - && eth->proto == htons (ETH_P_ARP) - && l_Adapter->m_dhcp_server_arp) - { - if (ProcessARP (l_Adapter, - (PARP_PACKET) l_PacketBuffer->m_Data, - l_Adapter->m_dhcp_addr, - l_Adapter->m_dhcp_server_ip, - ~0, - l_Adapter->m_dhcp_server_mac)) - goto no_queue; - } -#endif - -#if 0 - // DHCP packet? - else if (l_PacketLength >= sizeof (ETH_HEADER) + sizeof (IPHDR) + sizeof (UDPHDR) + sizeof (DHCP) - && eth->proto == htons (ETH_P_IP) - && ip->version_len == 0x45 // IPv4, 20 byte header - && ip->protocol == IPPROTO_UDP - && udp->dest == htons (BOOTPS_PORT)) - { - const DHCP *dhcp = (DHCP *) (l_PacketBuffer->m_Data - + sizeof (ETH_HEADER) - + sizeof (IPHDR) - + sizeof (UDPHDR)); - - const int optlen = l_PacketLength - - sizeof (ETH_HEADER) - - sizeof (IPHDR) - - sizeof (UDPHDR) - - sizeof (DHCP); - - if (optlen > 0) // we must have at least one DHCP option - { - if (ProcessDHCP (l_Adapter, eth, ip, udp, dhcp, optlen)) - goto no_queue; - } - else - goto no_queue; - } - } -#endif + switch (p_OID) + { + //=================================================================== + // Vendor & Driver version Info + //=================================================================== + case OID_GEN_VENDOR_DESCRIPTION: + l_QueryPtr = (TapAdapterQueryPointer) PRODUCT_TAP_WIN_DEVICE_DESCRIPTION; + l_QueryLength = strlen (PRODUCT_TAP_WIN_DEVICE_DESCRIPTION) + 1; + break; + + case OID_GEN_VENDOR_ID: + l_Query.m_Long = 0xffffff; + break; + + case OID_GEN_DRIVER_VERSION: + l_Query.m_Short = + (((USHORT) TAP_NDIS_MAJOR_VERSION) << 8 | (USHORT) + TAP_NDIS_MINOR_VERSION); + l_QueryLength = sizeof (unsigned short); + break; + + case OID_GEN_VENDOR_DRIVER_VERSION: + l_Query.m_Long = + (((USHORT) PRODUCT_TAP_WIN_MAJOR) << 8 | (USHORT) + PRODUCT_TAP_WIN_MINOR); + break; + + //================================================================= + // Statistics + //================================================================= + case OID_GEN_RCV_NO_BUFFER: + l_Query.m_Long = 0; + break; + + case OID_802_3_RCV_ERROR_ALIGNMENT: + l_Query.m_Long = 0; + break; + + case OID_802_3_XMIT_ONE_COLLISION: + l_Query.m_Long = 0; + break; + + case OID_802_3_XMIT_MORE_COLLISIONS: + l_Query.m_Long = 0; + break; + + case OID_GEN_XMIT_OK: + l_Query.m_Long = l_Adapter->m_Tx; + break; + + case OID_GEN_RCV_OK: + l_Query.m_Long = l_Adapter->m_Rx; + break; + + case OID_GEN_XMIT_ERROR: + l_Query.m_Long = l_Adapter->m_TxErr; + break; + + case OID_GEN_RCV_ERROR: + l_Query.m_Long = l_Adapter->m_RxErr; + break; + + //=================================================================== + // Device & Protocol Options + //=================================================================== + case OID_GEN_SUPPORTED_LIST: + l_QueryPtr = (TapAdapterQueryPointer) g_SupportedOIDList; + l_QueryLength = sizeof (g_SupportedOIDList); + break; + + case OID_GEN_MAC_OPTIONS: + // This MUST be here !!! + l_Query.m_Long = (NDIS_MAC_OPTION_RECEIVE_SERIALIZED + | NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA + | NDIS_MAC_OPTION_NO_LOOPBACK + | NDIS_MAC_OPTION_TRANSFERS_NOT_PEND); - //=============================================== - // In Point-To-Point mode, check to see whether - // packet is ARP (handled) or IPv4 (sent to app). - // IPv6 packets are inspected for neighbour discovery - // (to be handled locally), and the rest is forwarded - // all other protocols are dropped - //=============================================== -#if 0 - if (l_Adapter->m_tun) - { - ETH_HEADER *e; - - if (l_PacketLength < ETHERNET_HEADER_SIZE) - goto no_queue; - - e = (ETH_HEADER *) l_PacketBuffer->m_Data; - - switch (ntohs (e->proto)) - { - case ETH_P_ARP: - - // Make sure that packet is the - // right size for ARP. - if (l_PacketLength != sizeof (ARP_PACKET)) - goto no_queue; - - ProcessARP (l_Adapter, - (PARP_PACKET) l_PacketBuffer->m_Data, - l_Adapter->m_localIP, - l_Adapter->m_remoteNetwork, - l_Adapter->m_remoteNetmask, - l_Adapter->m_TapToUser.dest); - - default: - goto no_queue; - - case ETH_P_IP: - - // Make sure that packet is large - // enough to be IPv4. - if (l_PacketLength - < ETHERNET_HEADER_SIZE + IP_HEADER_SIZE) - goto no_queue; - - // Only accept directed packets, - // not broadcasts. - if (memcmp (e, &l_Adapter->m_TapToUser, ETHERNET_HEADER_SIZE)) - goto no_queue; - - // Packet looks like IPv4, queue it. - l_PacketBuffer->m_SizeFlags |= TP_TUN; - break; - - case ETH_P_IPV6: - // make sure that packet is large - // enough to be IPv6 - if (l_PacketLength - < ETHERNET_HEADER_SIZE + IPV6_HEADER_SIZE) - goto no_queue; - - // broadcasts and multicasts are handled specially - // (to be implemented) - - // neighbor discovery packets to fe80::8 are special - // OpenVPN sets this next-hop to signal "handled by tapdrv" - if ( HandleIPv6NeighborDiscovery( l_Adapter, - l_PacketBuffer->m_Data )) - { - goto no_queue; - } - - // Packet looks like IPv6, queue it :-) - l_PacketBuffer->m_SizeFlags |= TP_TUN; - } - } -#endif + break; + + case OID_GEN_CURRENT_PACKET_FILTER: + l_Query.m_Long = + (NDIS_PACKET_TYPE_ALL_LOCAL | + NDIS_PACKET_TYPE_BROADCAST | + NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_ALL_FUNCTIONAL); + + break; + + case OID_GEN_PROTOCOL_OPTIONS: + l_Query.m_Long = 0; + break; + + //================================================================== + // Device Info + //================================================================== + case OID_GEN_MEDIA_CONNECT_STATUS: + l_Query.m_Long = l_Adapter->m_MediaState + ? NdisMediaStateConnected : NdisMediaStateDisconnected; + break; + + case OID_GEN_HARDWARE_STATUS: + l_Query.m_HardwareStatus = NdisHardwareStatusReady; + l_QueryLength = sizeof (NDIS_HARDWARE_STATUS); + break; + + case OID_GEN_MEDIA_SUPPORTED: + case OID_GEN_MEDIA_IN_USE: + l_Query.m_Medium = l_Adapter->m_Medium; + l_QueryLength = sizeof (NDIS_MEDIUM); + break; + + case OID_GEN_PHYSICAL_MEDIUM: + l_Query.m_PhysicalMedium = NdisPhysicalMediumUnspecified; + l_QueryLength = sizeof (NDIS_PHYSICAL_MEDIUM); + break; + + case OID_GEN_LINK_SPEED: + l_Query.m_Long = 100000; // rate / 100 bps + break; + + case OID_802_3_PERMANENT_ADDRESS: + case OID_802_3_CURRENT_ADDRESS: + COPY_MAC (l_Query.m_MacAddress, l_Adapter->m_MAC); + l_QueryLength = sizeof (MACADDR); + break; + + //================================================================== + // Limits + //================================================================== + + case OID_GEN_MAXIMUM_SEND_PACKETS: + l_Query.m_Long = 1; + break; + + case OID_802_3_MAXIMUM_LIST_SIZE: + l_Query.m_Long = NIC_MAX_MCAST_LIST; + break; + + case OID_GEN_CURRENT_LOOKAHEAD: + l_Query.m_Long = l_Adapter->m_Lookahead; + break; + + case OID_GEN_MAXIMUM_LOOKAHEAD: + case OID_GEN_MAXIMUM_TOTAL_SIZE: + case OID_GEN_RECEIVE_BUFFER_SPACE: + case OID_GEN_RECEIVE_BLOCK_SIZE: + l_Query.m_Long = DEFAULT_PACKET_LOOKAHEAD; + break; + + case OID_GEN_MAXIMUM_FRAME_SIZE: + case OID_GEN_TRANSMIT_BLOCK_SIZE: + case OID_GEN_TRANSMIT_BUFFER_SPACE: + l_Query.m_Long = l_Adapter->m_MTU; + break; + + case OID_PNP_CAPABILITIES: + do + { + PNDIS_PNP_CAPABILITIES pPNPCapabilities; + PNDIS_PM_WAKE_UP_CAPABILITIES pPMstruct; + + if (p_BufferLength >= sizeof (NDIS_PNP_CAPABILITIES)) + { + pPNPCapabilities = (PNDIS_PNP_CAPABILITIES) (p_Buffer); + + // + // Setting up the buffer to be returned + // to the Protocol above the Passthru miniport + // + pPMstruct = &pPNPCapabilities->WakeUpCapabilities; + pPMstruct->MinMagicPacketWakeUp = NdisDeviceStateUnspecified; + pPMstruct->MinPatternWakeUp = NdisDeviceStateUnspecified; + pPMstruct->MinLinkChangeWakeUp = NdisDeviceStateUnspecified; + } + l_QueryLength = sizeof (NDIS_PNP_CAPABILITIES); + } + while (FALSE); + break; + case OID_PNP_QUERY_POWER: + break; + + // Required OIDs that we don't support + + case OID_GEN_SUPPORTED_GUIDS: + case OID_GEN_MEDIA_CAPABILITIES: + case OID_TCP_TASK_OFFLOAD: + case OID_FFP_SUPPORT: + l_Status = NDIS_STATUS_INVALID_OID; + break; + + // Optional stats OIDs + + case OID_GEN_DIRECTED_BYTES_XMIT: + case OID_GEN_DIRECTED_FRAMES_XMIT: + case OID_GEN_MULTICAST_BYTES_XMIT: + case OID_GEN_MULTICAST_FRAMES_XMIT: + case OID_GEN_BROADCAST_BYTES_XMIT: + case OID_GEN_BROADCAST_FRAMES_XMIT: + case OID_GEN_DIRECTED_BYTES_RCV: + case OID_GEN_DIRECTED_FRAMES_RCV: + case OID_GEN_MULTICAST_BYTES_RCV: + case OID_GEN_MULTICAST_FRAMES_RCV: + case OID_GEN_BROADCAST_BYTES_RCV: + case OID_GEN_BROADCAST_FRAMES_RCV: + l_Status = NDIS_STATUS_INVALID_OID; + break; + + //=================================================================== + // Not Handled + //=================================================================== + default: + DEBUGP (("[%s] Unhandled OID %lx\n", NAME (l_Adapter), p_OID)); + l_Status = NDIS_STATUS_INVALID_OID; + break; + } - //=============================================== - // Push packet onto queue to wait for read from - // userspace. - //=============================================== - - NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock); - - result = NULL; - if (IS_UP (l_Adapter)) - result = QueuePush (l_Adapter->m_Extension.m_PacketQueue, l_PacketBuffer); - - NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock); - - if ((TapPacketPointer) result != l_PacketBuffer) - { - // adapter receive overrun - INCREMENT_STAT (l_Adapter->m_TxErr); - goto no_queue; - } - else - { - INCREMENT_STAT (l_Adapter->m_Tx); - } - - //============================================================ - // Cycle through IRPs and packets, try to satisfy each pending - // IRP with a queued packet. - //============================================================ - while (TRUE) - { - l_IRP = NULL; - l_PacketBuffer = NULL; - - NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock); - - if (IS_UP (l_Adapter) - && QueueCount (l_Adapter->m_Extension.m_PacketQueue) - && QueueCount (l_Adapter->m_Extension.m_IrpQueue)) - { - l_IRP = (PIRP) QueuePop (l_Adapter->m_Extension.m_IrpQueue); - l_PacketBuffer = (TapPacketPointer) - QueuePop (l_Adapter->m_Extension.m_PacketQueue); - } - - NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock); - - MYASSERT ((l_IRP != NULL) + (l_PacketBuffer != NULL) != 1); - - if (l_IRP && l_PacketBuffer) - { - CompleteIRP (l_IRP, - l_PacketBuffer, - IO_NETWORK_INCREMENT); - } + if (l_Status != NDIS_STATUS_SUCCESS) + ; + else if (l_QueryLength > p_BufferLength) + { + l_Status = NDIS_STATUS_INVALID_LENGTH; + *p_BytesNeeded = l_QueryLength; + } else - break; - } - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - } - - return NDIS_STATUS_SUCCESS; - - no_queue: - NdisFreeMemory (l_PacketBuffer, - TAP_PACKET_SIZE (l_PacketLength), - 0); - - exit_success: - return NDIS_STATUS_SUCCESS; - - exit_fail: - return NDIS_STATUS_FAILURE; - - exit_no_resources: - return NDIS_STATUS_RESOURCES; -} + NdisMoveMemory (p_Buffer, (PVOID) l_QueryPtr, + (*p_BytesWritten = l_QueryLength)); -//====================================================================== -// Hooks for catching TAP device IRP's. -//====================================================================== + return l_Status; +} -DRIVER_DISPATCH TapDeviceHook; -NTSTATUS -TapDeviceHook (IN PDEVICE_OBJECT p_DeviceObject, IN PIRP p_IRP) +NDIS_STATUS AdapterModify + (IN NDIS_HANDLE p_AdapterContext, + IN NDIS_OID p_OID, + IN PVOID p_Buffer, + IN ULONG p_BufferLength, + OUT PULONG p_BytesRead, + OUT PULONG p_BytesNeeded) { - TapAdapterPointer l_Adapter = LookupAdapterInInstanceList (p_DeviceObject); - PIO_STACK_LOCATION l_IrpSp; - NTSTATUS l_Status = STATUS_SUCCESS; - BOOLEAN accessible; - - l_IrpSp = IoGetCurrentIrpStackLocation (p_IRP); - - p_IRP->IoStatus.Status = STATUS_SUCCESS; - p_IRP->IoStatus.Information = 0; + TapAdapterQueryPointer l_Query = (TapAdapterQueryPointer) p_Buffer; + TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext; + NDIS_STATUS l_Status = NDIS_STATUS_INVALID_OID; + ULONG l_Long; - if (!l_Adapter || l_Adapter->m_Extension.m_Halt) - { - DEBUGP (("TapDeviceHook called when TAP device is halted, MajorFunction=%d\n", - (int)l_IrpSp->MajorFunction)); - - if (l_IrpSp->MajorFunction == IRP_MJ_CLOSE) - { - IoCompleteRequest (p_IRP, IO_NO_INCREMENT); - return STATUS_SUCCESS; - } - else + switch (p_OID) { - p_IRP->IoStatus.Status = STATUS_NO_SUCH_DEVICE; - IoCompleteRequest (p_IRP, IO_NO_INCREMENT); - return STATUS_NO_SUCH_DEVICE; - } - } - - switch (l_IrpSp->MajorFunction) - { - //=========================================================== - // Ioctl call handlers - //=========================================================== - case IRP_MJ_DEVICE_CONTROL: - { - switch (l_IrpSp->Parameters.DeviceIoControl.IoControlCode) - { - case TAP_WIN_IOCTL_GET_MAC: - { - if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength - >= sizeof (MACADDR)) + //================================================================== + // Device Info + //================================================================== + case OID_802_3_MULTICAST_LIST: + DEBUGP (("[%s] Setting [OID_802_3_MULTICAST_LIST]\n", + NAME (l_Adapter))); + + *p_BytesNeeded = sizeof (ETH_ADDR); + *p_BytesRead = p_BufferLength; + + if (p_BufferLength % sizeof (ETH_ADDR)) + l_Status = NDIS_STATUS_INVALID_LENGTH; + else if (p_BufferLength > sizeof (MC_LIST)) { - COPY_MAC (p_IRP->AssociatedIrp.SystemBuffer, - l_Adapter->m_MAC); - p_IRP->IoStatus.Information = sizeof (MACADDR); + l_Status = NDIS_STATUS_MULTICAST_FULL; + *p_BytesNeeded = sizeof (MC_LIST); } - else + else { - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL; + NdisAcquireSpinLock (&l_Adapter->m_MCLock); + + NdisZeroMemory(&l_Adapter->m_MCList, sizeof (MC_LIST)); + + NdisMoveMemory(&l_Adapter->m_MCList, + p_Buffer, + p_BufferLength); + + l_Adapter->m_MCListSize = p_BufferLength / sizeof (ETH_ADDR); + + NdisReleaseSpinLock (&l_Adapter->m_MCLock); + + l_Status = NDIS_STATUS_SUCCESS; } - break; - } - case TAP_WIN_IOCTL_GET_VERSION: - { - const ULONG size = sizeof (ULONG) * 3; - if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength - >= size) + break; + + case OID_GEN_CURRENT_PACKET_FILTER: + l_Status = NDIS_STATUS_INVALID_LENGTH; + *p_BytesNeeded = 4; + + if (p_BufferLength >= sizeof (ULONG)) { - ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[0] - = TAP_DRIVER_MAJOR_VERSION; - ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[1] - = TAP_DRIVER_MINOR_VERSION; - ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[2] -#if DBG - = 1; -#else - = 0; -#endif - p_IRP->IoStatus.Information = size; + DEBUGP + (("[%s] Setting [OID_GEN_CURRENT_PACKET_FILTER] to [0x%02lx]\n", + NAME (l_Adapter), l_Query->m_Long)); + l_Status = NDIS_STATUS_SUCCESS; + *p_BytesRead = sizeof (ULONG); } - else + break; + + case OID_GEN_CURRENT_LOOKAHEAD: + if (p_BufferLength < sizeof (ULONG)) { - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL; + l_Status = NDIS_STATUS_INVALID_LENGTH; + *p_BytesNeeded = 4; } - - break; - } - case TAP_WIN_IOCTL_GET_MTU: - { - const ULONG size = sizeof (ULONG) * 1; - if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength - >= size) + else if (l_Query->m_Long > DEFAULT_PACKET_LOOKAHEAD + || l_Query->m_Long <= 0) { - ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[0] - = l_Adapter->m_MTU; - p_IRP->IoStatus.Information = size; + l_Status = NDIS_STATUS_INVALID_DATA; } - else + else { - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL; + DEBUGP (("[%s] Setting [OID_GEN_CURRENT_LOOKAHEAD] to [%d]\n", + NAME (l_Adapter), l_Query->m_Long)); + l_Adapter->m_Lookahead = l_Query->m_Long; + l_Status = NDIS_STATUS_SUCCESS; + *p_BytesRead = sizeof (ULONG); } + break; - break; - } - case TAP_WIN_IOCTL_GET_INFO: - { - char state[16]; - if (l_Adapter->m_InterfaceIsRunning) - state[0] = 'A'; - else - state[0] = 'a'; - if (l_Adapter->m_Extension.m_TapIsRunning) - state[1] = 'T'; - else - state[1] = 't'; - state[2] = l_Adapter->m_DeviceState; - if (l_Adapter->m_MediaStateAlwaysConnected) - state[3] = 'C'; - else - state[3] = 'c'; - state[4] = '\0'; - - p_IRP->IoStatus.Status = l_Status = RtlStringCchPrintfExA ( - ((LPTSTR) (p_IRP->AssociatedIrp.SystemBuffer)), - l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength, - NULL, - 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] 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] InjQ=[%d,%d,%d]", -#endif - state, - g_LastErrorFilename, - g_LastErrorLineNumber, - (int)l_Adapter->m_Extension.m_NumTapOpens, - (int)l_Adapter->m_Tx, - (int)l_Adapter->m_TxErr, -#if PACKET_TRUNCATION_CHECK - (int)l_Adapter->m_TxTrunc, -#endif - (int)l_Adapter->m_Rx, - (int)l_Adapter->m_RxErr, -#if PACKET_TRUNCATION_CHECK - (int)l_Adapter->m_RxTrunc, -#endif - (int)l_Adapter->m_Extension.m_IrpQueue->size, - (int)l_Adapter->m_Extension.m_IrpQueue->max_size, - (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)l_Adapter->m_Extension.m_InjectQueue->size, - (int)l_Adapter->m_Extension.m_InjectQueue->max_size, - (int)INJECT_QUEUE_SIZE - ); - - p_IRP->IoStatus.Information - = l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength; + case OID_GEN_NETWORK_LAYER_ADDRESSES: + l_Status = NDIS_STATUS_SUCCESS; + *p_BytesRead = *p_BytesNeeded = 0; + break; - break; - } + case OID_GEN_TRANSPORT_HEADER_OFFSET: + l_Status = NDIS_STATUS_SUCCESS; + *p_BytesRead = *p_BytesNeeded = 0; + break; -#if DBG - case TAP_WIN_IOCTL_GET_LOG_LINE: - { - if (GetDebugLine ((LPTSTR)p_IRP->AssociatedIrp.SystemBuffer, - l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength)) - p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS; - else - p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; - - p_IRP->IoStatus.Information - = l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength; - - break; - } -#endif - -#if 0 - case TAP_WIN_IOCTL_CONFIG_TUN: - { - if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength >= - (sizeof (IPADDR) * 3)) + case OID_PNP_SET_POWER: + do { - MACADDR dest; - - l_Adapter->m_tun = FALSE; - - GenerateRelatedMAC (dest, l_Adapter->m_MAC, 1); - - l_Adapter->m_localIP = ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[0]; - l_Adapter->m_remoteNetwork = ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[1]; - l_Adapter->m_remoteNetmask = ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[2]; - - // sanity check on network/netmask - if ((l_Adapter->m_remoteNetwork & l_Adapter->m_remoteNetmask) != l_Adapter->m_remoteNetwork) - { - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER; - break; - } - - COPY_MAC (l_Adapter->m_TapToUser.src, l_Adapter->m_MAC); - COPY_MAC (l_Adapter->m_TapToUser.dest, dest); - COPY_MAC (l_Adapter->m_UserToTap.src, dest); - COPY_MAC (l_Adapter->m_UserToTap.dest, l_Adapter->m_MAC); - - l_Adapter->m_TapToUser.proto = l_Adapter->m_UserToTap.proto = htons (ETH_P_IP); - l_Adapter->m_UserToTap_IPv6 = l_Adapter->m_UserToTap; - l_Adapter->m_UserToTap_IPv6.proto = htons(ETH_P_IPV6); - - l_Adapter->m_tun = TRUE; - - CheckIfDhcpAndTunMode (l_Adapter); + NDIS_DEVICE_POWER_STATE NewDeviceState; + + NewDeviceState = (*(PNDIS_DEVICE_POWER_STATE) p_Buffer); + + switch (NewDeviceState) + { + case NdisDeviceStateD0: + l_Adapter->m_DeviceState = '0'; + break; + case NdisDeviceStateD1: + l_Adapter->m_DeviceState = '1'; + break; + case NdisDeviceStateD2: + l_Adapter->m_DeviceState = '2'; + break; + case NdisDeviceStateD3: + l_Adapter->m_DeviceState = '3'; + break; + default: + l_Adapter->m_DeviceState = '?'; + break; + } + + l_Status = NDIS_STATUS_FAILURE; + + // + // Check for invalid length + // + if (p_BufferLength < sizeof (NDIS_DEVICE_POWER_STATE)) + { + l_Status = NDIS_STATUS_INVALID_LENGTH; + break; + } + + if (NewDeviceState > NdisDeviceStateD0) + { + l_Adapter->m_InterfaceIsRunning = FALSE; + DEBUGP (("[%s] Power management device state OFF\n", + NAME (l_Adapter))); + } + else + { + l_Adapter->m_InterfaceIsRunning = TRUE; + DEBUGP (("[%s] Power management device state ON\n", + NAME (l_Adapter))); + } + + l_Status = NDIS_STATUS_SUCCESS; + } + while (FALSE); - p_IRP->IoStatus.Information = 1; // Simple boolean value + if (l_Status == NDIS_STATUS_SUCCESS) + { + *p_BytesRead = sizeof (NDIS_DEVICE_POWER_STATE); + *p_BytesNeeded = 0; } - else + else { - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER; + *p_BytesRead = 0; + *p_BytesNeeded = sizeof (NDIS_DEVICE_POWER_STATE); } - - break; - } -#endif + break; + + case OID_PNP_REMOVE_WAKE_UP_PATTERN: + case OID_PNP_ADD_WAKE_UP_PATTERN: + l_Status = NDIS_STATUS_SUCCESS; + *p_BytesRead = *p_BytesNeeded = 0; + break; + + default: + DEBUGP (("[%s] Can't set value for OID %lx\n", NAME (l_Adapter), + p_OID)); + l_Status = NDIS_STATUS_INVALID_OID; + *p_BytesRead = *p_BytesNeeded = 0; + break; + } -#if 0 - case TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT: // Obsoleted by TAP_WIN_IOCTL_CONFIG_TUN - { - if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength >= - (sizeof (IPADDR) * 2)) - { - MACADDR dest; + return l_Status; +} - l_Adapter->m_tun = FALSE; +//==================================================================== +// Adapter Transmission +//==================================================================== +NDIS_STATUS + AdapterTransmit (IN NDIS_HANDLE p_AdapterContext, + IN PNDIS_PACKET p_Packet, + IN UINT p_Flags) +{ + TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext; + ULONG l_Index = 0, l_PacketLength = 0; + UINT l_BufferLength = 0; + PIRP l_IRP; + TapPacketPointer l_PacketBuffer; + PNDIS_BUFFER l_NDIS_Buffer; + PUCHAR l_Buffer; + PVOID result; - GenerateRelatedMAC (dest, l_Adapter->m_MAC, 1); + NdisQueryPacket (p_Packet, NULL, NULL, &l_NDIS_Buffer, &l_PacketLength); - l_Adapter->m_localIP = ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[0]; - l_Adapter->m_remoteNetwork = ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[1]; - l_Adapter->m_remoteNetmask = ~0; + //==================================================== + // Here we abandon the transmission attempt if any of + // the parameters is wrong or memory allocation fails + // but we do not indicate failure. The packet is + // silently dropped. + //==================================================== - COPY_MAC (l_Adapter->m_TapToUser.src, l_Adapter->m_MAC); - COPY_MAC (l_Adapter->m_TapToUser.dest, dest); - COPY_MAC (l_Adapter->m_UserToTap.src, dest); - COPY_MAC (l_Adapter->m_UserToTap.dest, l_Adapter->m_MAC); + if (l_PacketLength < ETHERNET_HEADER_SIZE || l_PacketLength > 65535) + goto exit_fail; + else if (!l_Adapter->m_Extension.m_TapOpens || !l_Adapter->m_MediaState) + goto exit_success; // Nothing is bound to the TAP device - l_Adapter->m_TapToUser.proto = l_Adapter->m_UserToTap.proto = htons (ETH_P_IP); - l_Adapter->m_UserToTap_IPv6 = l_Adapter->m_UserToTap; - l_Adapter->m_UserToTap_IPv6.proto = htons(ETH_P_IPV6); + if (NdisAllocateMemoryWithTag (&l_PacketBuffer, + TAP_PACKET_SIZE (l_PacketLength), + '5PAT') != NDIS_STATUS_SUCCESS) + goto exit_no_resources; - l_Adapter->m_tun = TRUE; + if (l_PacketBuffer == NULL) + goto exit_no_resources; - CheckIfDhcpAndTunMode (l_Adapter); + l_PacketBuffer->m_SizeFlags = (l_PacketLength & TP_SIZE_MASK); - p_IRP->IoStatus.Information = 1; // Simple boolean value - } - else - { - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER; - } - - break; - } -#endif + //=========================== + // Reassemble packet contents + //=========================== - case TAP_WIN_IOCTL_SET_MEDIA_STATUS: - { - if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength >= - (sizeof (ULONG) * 1)) + __try + { + l_Index = 0; + while (l_NDIS_Buffer && l_Index < l_PacketLength) { - ULONG parm = ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[0]; - SetMediaStatus (l_Adapter, (BOOLEAN) parm); - p_IRP->IoStatus.Information = 1; + ULONG newlen; + NdisQueryBuffer (l_NDIS_Buffer, (PVOID *) & l_Buffer, + &l_BufferLength); + newlen = l_Index + l_BufferLength; + if (newlen > l_PacketLength) + { + NOTE_ERROR (); + goto no_queue; /* overflow */ + } + NdisMoveMemory (l_PacketBuffer->m_Data + l_Index, l_Buffer, + l_BufferLength); + l_Index = newlen; + NdisGetNextBuffer (l_NDIS_Buffer, &l_NDIS_Buffer); } - else + if (l_Index != l_PacketLength) { - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER; + NOTE_ERROR (); + goto no_queue; /* underflow */ } - break; - } - -#if 0 - case TAP_WIN_IOCTL_CONFIG_DHCP_MASQ: - { - if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength >= - (sizeof (IPADDR) * 4)) - { - l_Adapter->m_dhcp_enabled = FALSE; - l_Adapter->m_dhcp_server_arp = FALSE; - l_Adapter->m_dhcp_user_supplied_options_buffer_len = 0; - // Adapter IP addr / netmask - l_Adapter->m_dhcp_addr = - ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[0]; - l_Adapter->m_dhcp_netmask = - ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[1]; + DUMP_PACKET ("AdapterTransmit", l_PacketBuffer->m_Data, l_PacketLength); - // IP addr of DHCP masq server - l_Adapter->m_dhcp_server_ip = - ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[2]; + //=============================================== + // Push packet onto queue to wait for read from + // userspace. + //=============================================== - // Lease time in seconds - l_Adapter->m_dhcp_lease_time = - ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[3]; + NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock); - GenerateRelatedMAC (l_Adapter->m_dhcp_server_mac, l_Adapter->m_MAC, 2); + result = NULL; + if (IS_UP (l_Adapter)) + result = QueuePush (l_Adapter->m_Extension.m_PacketQueue, l_PacketBuffer); - l_Adapter->m_dhcp_enabled = TRUE; - l_Adapter->m_dhcp_server_arp = TRUE; + NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock); - CheckIfDhcpAndTunMode (l_Adapter); - - p_IRP->IoStatus.Information = 1; // Simple boolean value - } - else + if ((TapPacketPointer) result != l_PacketBuffer) { - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER; + // adapter receive overrun + INCREMENT_STAT (l_Adapter->m_TxErr); + goto no_queue; } - - break; - } - - case TAP_WIN_IOCTL_CONFIG_DHCP_SET_OPT: - { - if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength <= - DHCP_USER_SUPPLIED_OPTIONS_BUFFER_SIZE - && l_Adapter->m_dhcp_enabled) + else { - l_Adapter->m_dhcp_user_supplied_options_buffer_len = 0; - - NdisMoveMemory (l_Adapter->m_dhcp_user_supplied_options_buffer, - p_IRP->AssociatedIrp.SystemBuffer, - l_IrpSp->Parameters.DeviceIoControl.InputBufferLength); - - l_Adapter->m_dhcp_user_supplied_options_buffer_len = - l_IrpSp->Parameters.DeviceIoControl.InputBufferLength; - - p_IRP->IoStatus.Information = 1; // Simple boolean value + INCREMENT_STAT (l_Adapter->m_Tx); } - else + + //============================================================ + // Cycle through IRPs and packets, try to satisfy each pending + // IRP with a queued packet. + //============================================================ + while (TRUE) { - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER; + l_IRP = NULL; + l_PacketBuffer = NULL; + + NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock); + + if (IS_UP (l_Adapter) + && QueueCount (l_Adapter->m_Extension.m_PacketQueue) + && QueueCount (l_Adapter->m_Extension.m_IrpQueue)) + { + l_IRP = (PIRP) QueuePop (l_Adapter->m_Extension.m_IrpQueue); + l_PacketBuffer = (TapPacketPointer) + QueuePop (l_Adapter->m_Extension.m_PacketQueue); + } + + NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock); + + MYASSERT ((l_IRP != NULL) + (l_PacketBuffer != NULL) != 1); + + if (l_IRP && l_PacketBuffer) + { + CompleteIRP (l_IRP, + l_PacketBuffer, + IO_NETWORK_INCREMENT); + } + else + break; } - - break; - } -#endif + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + } - default: - { - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER; - break; - } - } - - IoCompleteRequest (p_IRP, IO_NO_INCREMENT); - break; - } - - //=========================================================== - // User mode thread issued a read request on the tap device - // If there are packets waiting to be read, then the request - // will be satisfied here. If not, then the request will be - // queued and satisfied by any packet that is not used to - // satisfy requests ahead of it. - //=========================================================== - case IRP_MJ_READ: - { - TapPacketPointer l_PacketBuffer; - BOOLEAN pending = FALSE; - - // Save IRP-accessible copy of buffer length - p_IRP->IoStatus.Information = l_IrpSp->Parameters.Read.Length; - - if (p_IRP->MdlAddress == NULL) - { - DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_READ\n", - NAME (l_Adapter))); - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER; - p_IRP->IoStatus.Information = 0; - IoCompleteRequest (p_IRP, IO_NO_INCREMENT); - break; - } - else if ((p_IRP->AssociatedIrp.SystemBuffer = - MmGetSystemAddressForMdlSafe - (p_IRP->MdlAddress, NormalPagePriority)) == NULL) - { - DEBUGP (("[%s] Could not map address in IRP_MJ_READ\n", - NAME (l_Adapter))); - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_INSUFFICIENT_RESOURCES; - p_IRP->IoStatus.Information = 0; - IoCompleteRequest (p_IRP, IO_NO_INCREMENT); - break; - } - else if (!l_Adapter->m_InterfaceIsRunning) - { - DEBUGP (("[%s] Interface is down in IRP_MJ_READ\n", - NAME (l_Adapter))); - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; - p_IRP->IoStatus.Information = 0; - IoCompleteRequest (p_IRP, IO_NO_INCREMENT); - break; - } + return NDIS_STATUS_SUCCESS; - //================================== - // Can we provide immediate service? - //================================== +no_queue: + NdisFreeMemory (l_PacketBuffer, + TAP_PACKET_SIZE (l_PacketLength), + 0); - l_PacketBuffer = NULL; +exit_success: + return NDIS_STATUS_SUCCESS; - NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock); +exit_fail: + return NDIS_STATUS_FAILURE; - if (IS_UP (l_Adapter) - && QueueCount (l_Adapter->m_Extension.m_PacketQueue) - && QueueCount (l_Adapter->m_Extension.m_IrpQueue) == 0) - { - l_PacketBuffer = (TapPacketPointer) - QueuePop (l_Adapter->m_Extension.m_PacketQueue); - } +exit_no_resources: + return NDIS_STATUS_RESOURCES; +} - NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock); +//====================================================================== +// Hooks for catching TAP device IRP's. +//====================================================================== - if (l_PacketBuffer) - { - l_Status = CompleteIRP (p_IRP, - l_PacketBuffer, - IO_NO_INCREMENT); - break; - } +DRIVER_DISPATCH TapDeviceHook; +NTSTATUS + TapDeviceHook (IN PDEVICE_OBJECT p_DeviceObject, IN PIRP p_IRP) +{ + TapAdapterPointer l_Adapter = LookupAdapterInInstanceList (p_DeviceObject); + PIO_STACK_LOCATION l_IrpSp; + NTSTATUS l_Status = STATUS_SUCCESS; + BOOLEAN accessible; - //============================= - // Attempt to pend read request - //============================= + l_IrpSp = IoGetCurrentIrpStackLocation (p_IRP); - NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock); + p_IRP->IoStatus.Status = STATUS_SUCCESS; + p_IRP->IoStatus.Information = 0; - if (IS_UP (l_Adapter) - && QueuePush (l_Adapter->m_Extension.m_IrpQueue, p_IRP) == (PIRP) p_IRP) - { - IoSetCancelRoutine (p_IRP, CancelIRPCallback); - l_Status = STATUS_PENDING; - IoMarkIrpPending (p_IRP); - pending = TRUE; - } + if (!l_Adapter || l_Adapter->m_Extension.m_Halt) + { + DEBUGP (("TapDeviceHook called when TAP device is halted, MajorFunction=%d\n", + (int)l_IrpSp->MajorFunction)); - NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock); + if (l_IrpSp->MajorFunction == IRP_MJ_CLOSE) + { + IoCompleteRequest (p_IRP, IO_NO_INCREMENT); + return STATUS_SUCCESS; + } + else + { + p_IRP->IoStatus.Status = STATUS_NO_SUCH_DEVICE; + IoCompleteRequest (p_IRP, IO_NO_INCREMENT); + return STATUS_NO_SUCH_DEVICE; + } + } - if (pending) - break; + switch (l_IrpSp->MajorFunction) + { + //=========================================================== + // Ioctl call handlers + //=========================================================== + case IRP_MJ_DEVICE_CONTROL: + { + switch (l_IrpSp->Parameters.DeviceIoControl.IoControlCode) + { + case TAP_WIN_IOCTL_GET_MAC: + { + if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength + >= sizeof (MACADDR)) + { + COPY_MAC (p_IRP->AssociatedIrp.SystemBuffer, + l_Adapter->m_MAC); + p_IRP->IoStatus.Information = sizeof (MACADDR); + } + else + { + NOTE_ERROR (); + p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL; + } + break; + } + case TAP_WIN_IOCTL_GET_VERSION: + { + const ULONG size = sizeof (ULONG) * 3; + if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength + >= size) + { + ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[0] + = TAP_DRIVER_MAJOR_VERSION; + ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[1] + = TAP_DRIVER_MINOR_VERSION; + ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[2] +#if DBG + = 1; +#else + = 0; +#endif + p_IRP->IoStatus.Information = size; + } + else + { + NOTE_ERROR (); + p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL; + } + + break; + } + case TAP_WIN_IOCTL_GET_MTU: + { + const ULONG size = sizeof (ULONG) * 1; + if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength + >= size) + { + ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[0] + = l_Adapter->m_MTU; + p_IRP->IoStatus.Information = size; + } + else + { + NOTE_ERROR (); + p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL; + } + + break; + } - // Can't queue anymore IRP's - DEBUGP (("[%s] TAP [%s] read IRP overrun\n", - NAME (l_Adapter), l_Adapter->m_Extension.m_TapName)); - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; - p_IRP->IoStatus.Information = 0; - IoCompleteRequest (p_IRP, IO_NO_INCREMENT); - break; - } - - //============================================================== - // User mode issued a WriteFile request on the TAP file handle. - // The request will always get satisfied here. The call may - // fail if there are too many pending packets (queue full). - //============================================================== - case IRP_MJ_WRITE: - { - if (p_IRP->MdlAddress == NULL) - { - DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_WRITE\n", - NAME (l_Adapter))); - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER; - p_IRP->IoStatus.Information = 0; - } - else if ((p_IRP->AssociatedIrp.SystemBuffer = - MmGetSystemAddressForMdlSafe - (p_IRP->MdlAddress, NormalPagePriority)) == NULL) - { - DEBUGP (("[%s] Could not map address in IRP_MJ_WRITE\n", - NAME (l_Adapter))); - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_INSUFFICIENT_RESOURCES; - p_IRP->IoStatus.Information = 0; - } - else if (!l_Adapter->m_InterfaceIsRunning) - { - DEBUGP (("[%s] Interface is down in IRP_MJ_WRITE\n", - NAME (l_Adapter))); - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; - p_IRP->IoStatus.Information = 0; - } -#if 0 - else if (!l_Adapter->m_tun && ((l_IrpSp->Parameters.Write.Length) >= ETHERNET_HEADER_SIZE)) - { - __try - { - p_IRP->IoStatus.Information = l_IrpSp->Parameters.Write.Length; - - DUMP_PACKET ("IRP_MJ_WRITE ETH", - (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer, - l_IrpSp->Parameters.Write.Length); - - //===================================================== - // If IPv4 packet, check whether or not packet - // was truncated. - //===================================================== -#if PACKET_TRUNCATION_CHECK - IPv4PacketSizeVerify ((unsigned char *) p_IRP->AssociatedIrp.SystemBuffer, - l_IrpSp->Parameters.Write.Length, - FALSE, - "RX", - &l_Adapter->m_RxTrunc); +#if DBG + case TAP_WIN_IOCTL_GET_LOG_LINE: + { + if (GetDebugLine ((LPTSTR)p_IRP->AssociatedIrp.SystemBuffer, + l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength)) + p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS; + else + p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; + + p_IRP->IoStatus.Information + = l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength; + + break; + } #endif - NdisMEthIndicateReceive - (l_Adapter->m_MiniportAdapterHandle, - (NDIS_HANDLE) l_Adapter, - (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer, - ETHERNET_HEADER_SIZE, - (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer + ETHERNET_HEADER_SIZE, - l_IrpSp->Parameters.Write.Length - ETHERNET_HEADER_SIZE, - l_IrpSp->Parameters.Write.Length - ETHERNET_HEADER_SIZE); - - NdisMEthIndicateReceiveComplete (l_Adapter->m_MiniportAdapterHandle); + case TAP_WIN_IOCTL_SET_MEDIA_STATUS: + { + if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength >= + (sizeof (ULONG) * 1)) + { + ULONG parm = ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[0]; + SetMediaStatus (l_Adapter, (BOOLEAN) parm); + p_IRP->IoStatus.Information = 1; + } + else + { + NOTE_ERROR (); + p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER; + } + break; + } + + default: + { + NOTE_ERROR (); + p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER; + break; + } + } + + IoCompleteRequest (p_IRP, IO_NO_INCREMENT); + break; + } - p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS; - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - DEBUGP (("[%s] NdisMEthIndicateReceive failed in IRP_MJ_WRITE\n", - NAME (l_Adapter))); - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; - p_IRP->IoStatus.Information = 0; - } - } -#endif -#if 0 - else if (l_Adapter->m_tun && ((l_IrpSp->Parameters.Write.Length) >= IP_HEADER_SIZE)) - { - __try - { - ETH_HEADER * p_UserToTap = &l_Adapter->m_UserToTap; - - // for IPv6, need to use ethernet header with IPv6 proto - if ( IPH_GET_VER( ((IPHDR*) p_IRP->AssociatedIrp.SystemBuffer)->version_len) == 6 ) - { - p_UserToTap = &l_Adapter->m_UserToTap_IPv6; - } - - p_IRP->IoStatus.Information = l_IrpSp->Parameters.Write.Length; - - DUMP_PACKET2 ("IRP_MJ_WRITE P2P", - p_UserToTap, - (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer, - l_IrpSp->Parameters.Write.Length); - - //===================================================== - // If IPv4 packet, check whether or not packet - // was truncated. - //===================================================== -#if PACKET_TRUNCATION_CHECK - IPv4PacketSizeVerify ((unsigned char *) p_IRP->AssociatedIrp.SystemBuffer, - l_IrpSp->Parameters.Write.Length, - TRUE, - "RX", - &l_Adapter->m_RxTrunc); -#endif + //=========================================================== + // User mode thread issued a read request on the tap device + // If there are packets waiting to be read, then the request + // will be satisfied here. If not, then the request will be + // queued and satisfied by any packet that is not used to + // satisfy requests ahead of it. + //=========================================================== + case IRP_MJ_READ: + { + TapPacketPointer l_PacketBuffer; + BOOLEAN pending = FALSE; + + // Save IRP-accessible copy of buffer length + p_IRP->IoStatus.Information = l_IrpSp->Parameters.Read.Length; + + if (p_IRP->MdlAddress == NULL) + { + DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_READ\n", + NAME (l_Adapter))); + NOTE_ERROR (); + p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER; + p_IRP->IoStatus.Information = 0; + IoCompleteRequest (p_IRP, IO_NO_INCREMENT); + break; + } + else if ((p_IRP->AssociatedIrp.SystemBuffer = + MmGetSystemAddressForMdlSafe + (p_IRP->MdlAddress, NormalPagePriority)) == NULL) + { + DEBUGP (("[%s] Could not map address in IRP_MJ_READ\n", + NAME (l_Adapter))); + NOTE_ERROR (); + p_IRP->IoStatus.Status = l_Status = STATUS_INSUFFICIENT_RESOURCES; + p_IRP->IoStatus.Information = 0; + IoCompleteRequest (p_IRP, IO_NO_INCREMENT); + break; + } + else if (!l_Adapter->m_InterfaceIsRunning) + { + DEBUGP (("[%s] Interface is down in IRP_MJ_READ\n", + NAME (l_Adapter))); + NOTE_ERROR (); + p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; + p_IRP->IoStatus.Information = 0; + IoCompleteRequest (p_IRP, IO_NO_INCREMENT); + break; + } + + //================================== + // Can we provide immediate service? + //================================== + + l_PacketBuffer = NULL; + + NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock); + + if (IS_UP (l_Adapter) + && QueueCount (l_Adapter->m_Extension.m_PacketQueue) + && QueueCount (l_Adapter->m_Extension.m_IrpQueue) == 0) + { + l_PacketBuffer = (TapPacketPointer) + QueuePop (l_Adapter->m_Extension.m_PacketQueue); + } + + NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock); + + if (l_PacketBuffer) + { + l_Status = CompleteIRP (p_IRP, + l_PacketBuffer, + IO_NO_INCREMENT); + break; + } + + //============================= + // Attempt to pend read request + //============================= + + NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock); + + if (IS_UP (l_Adapter) + && QueuePush (l_Adapter->m_Extension.m_IrpQueue, p_IRP) == (PIRP) p_IRP) + { + IoSetCancelRoutine (p_IRP, CancelIRPCallback); + l_Status = STATUS_PENDING; + IoMarkIrpPending (p_IRP); + pending = TRUE; + } + + NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock); + + if (pending) + break; + + // Can't queue anymore IRP's + DEBUGP (("[%s] TAP [%s] read IRP overrun\n", + NAME (l_Adapter), l_Adapter->m_Extension.m_TapName)); + NOTE_ERROR (); + p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; + p_IRP->IoStatus.Information = 0; + IoCompleteRequest (p_IRP, IO_NO_INCREMENT); + break; + } - NdisMEthIndicateReceive - (l_Adapter->m_MiniportAdapterHandle, - (NDIS_HANDLE) l_Adapter, - (unsigned char *) p_UserToTap, - sizeof (ETH_HEADER), - (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer, - l_IrpSp->Parameters.Write.Length, - l_IrpSp->Parameters.Write.Length); + //============================================================== + // User mode issued a WriteFile request on the TAP file handle. + // The request will always get satisfied here. The call may + // fail if there are too many pending packets (queue full). + //============================================================== + case IRP_MJ_WRITE: + { + if (p_IRP->MdlAddress == NULL) + { + DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_WRITE\n", + NAME (l_Adapter))); + NOTE_ERROR (); + p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER; + p_IRP->IoStatus.Information = 0; + } + else if ((p_IRP->AssociatedIrp.SystemBuffer = + MmGetSystemAddressForMdlSafe + (p_IRP->MdlAddress, NormalPagePriority)) == NULL) + { + DEBUGP (("[%s] Could not map address in IRP_MJ_WRITE\n", + NAME (l_Adapter))); + NOTE_ERROR (); + p_IRP->IoStatus.Status = l_Status = STATUS_INSUFFICIENT_RESOURCES; + p_IRP->IoStatus.Information = 0; + } + else if (!l_Adapter->m_InterfaceIsRunning) + { + DEBUGP (("[%s] Interface is down in IRP_MJ_WRITE\n", + NAME (l_Adapter))); + NOTE_ERROR (); + p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; + p_IRP->IoStatus.Information = 0; + } + else + { + DEBUGP (("[%s] Bad buffer size in IRP_MJ_WRITE, len=%d\n", + NAME (l_Adapter), + l_IrpSp->Parameters.Write.Length)); + NOTE_ERROR (); + p_IRP->IoStatus.Information = 0; // ETHERNET_HEADER_SIZE; + p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL; + } + + if (l_Status == STATUS_SUCCESS) + INCREMENT_STAT (l_Adapter->m_Rx); + else + INCREMENT_STAT (l_Adapter->m_RxErr); + + IoCompleteRequest (p_IRP, IO_NO_INCREMENT); + break; + } - NdisMEthIndicateReceiveComplete (l_Adapter->m_MiniportAdapterHandle); + //-------------------------------------------------------------- + // User mode thread has called CreateFile() on the tap device + //-------------------------------------------------------------- + case IRP_MJ_CREATE: + { + BOOLEAN succeeded = FALSE; + BOOLEAN mutex_succeeded; + + DEBUGP + (("[%s] [TAP] release [%d.%d] open request (m_TapOpens=%d)\n", + NAME (l_Adapter), TAP_DRIVER_MAJOR_VERSION, + TAP_DRIVER_MINOR_VERSION, l_Adapter->m_Extension.m_TapOpens)); + + ACQUIRE_MUTEX_ADAPTIVE (&l_Adapter->m_Extension.m_OpenCloseMutex, mutex_succeeded); + if (mutex_succeeded) + { + if (l_Adapter->m_Extension.m_TapIsRunning && !l_Adapter->m_Extension.m_TapOpens) + { + l_Adapter->m_Extension.m_TapOpens = 1; + succeeded = TRUE; + } + + if (succeeded) + { + INCREMENT_STAT (l_Adapter->m_Extension.m_NumTapOpens); + p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS; + p_IRP->IoStatus.Information = 0; + } + else + { + DEBUGP (("[%s] TAP is presently unavailable (m_TapOpens=%d)\n", + NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens)); + NOTE_ERROR (); + p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; + p_IRP->IoStatus.Information = 0; + } + + RELEASE_MUTEX (&l_Adapter->m_Extension.m_OpenCloseMutex); + } + else + { + DEBUGP (("[%s] TAP is presently locked (m_TapOpens=%d)\n", + NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens)); + NOTE_ERROR (); + p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; + p_IRP->IoStatus.Information = 0; + } + + IoCompleteRequest (p_IRP, IO_NO_INCREMENT); + break; + } - p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS; - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - DEBUGP (("[%s] NdisMEthIndicateReceive failed in IRP_MJ_WRITE (P2P)\n", - NAME (l_Adapter))); - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; - p_IRP->IoStatus.Information = 0; - } - } -#endif - else - { - DEBUGP (("[%s] Bad buffer size in IRP_MJ_WRITE, len=%d\n", - NAME (l_Adapter), - l_IrpSp->Parameters.Write.Length)); - NOTE_ERROR (); - p_IRP->IoStatus.Information = 0; // ETHERNET_HEADER_SIZE; - p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL; - } + //----------------------------------------------------------- + // User mode thread called CloseHandle() on the tap device + //----------------------------------------------------------- + case IRP_MJ_CLOSE: + { + BOOLEAN mutex_succeeded; + + DEBUGP (("[%s] [TAP] release [%d.%d] close/cleanup request\n", + NAME (l_Adapter), TAP_DRIVER_MAJOR_VERSION, + TAP_DRIVER_MINOR_VERSION)); + + ACQUIRE_MUTEX_ADAPTIVE (&l_Adapter->m_Extension.m_OpenCloseMutex, mutex_succeeded); + if (mutex_succeeded) + { + l_Adapter->m_Extension.m_TapOpens = 0; + FlushQueues (&l_Adapter->m_Extension); + SetMediaStatus (l_Adapter, FALSE); + RELEASE_MUTEX (&l_Adapter->m_Extension.m_OpenCloseMutex); + } + else + { + DEBUGP (("[%s] TAP is presently locked (m_TapOpens=%d)\n", + NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens)); + NOTE_ERROR (); + p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; + p_IRP->IoStatus.Information = 0; + } + + IoCompleteRequest (p_IRP, IO_NO_INCREMENT); + break; + } - if (l_Status == STATUS_SUCCESS) - INCREMENT_STAT (l_Adapter->m_Rx); - else - INCREMENT_STAT (l_Adapter->m_RxErr); - - IoCompleteRequest (p_IRP, IO_NO_INCREMENT); - break; - } - - //-------------------------------------------------------------- - // User mode thread has called CreateFile() on the tap device - //-------------------------------------------------------------- - case IRP_MJ_CREATE: - { - BOOLEAN succeeded = FALSE; - BOOLEAN mutex_succeeded; - - DEBUGP - (("[%s] [TAP] release [%d.%d] open request (m_TapOpens=%d)\n", - NAME (l_Adapter), TAP_DRIVER_MAJOR_VERSION, - TAP_DRIVER_MINOR_VERSION, l_Adapter->m_Extension.m_TapOpens)); - - ACQUIRE_MUTEX_ADAPTIVE (&l_Adapter->m_Extension.m_OpenCloseMutex, mutex_succeeded); - if (mutex_succeeded) - { - if (l_Adapter->m_Extension.m_TapIsRunning && !l_Adapter->m_Extension.m_TapOpens) - { - ResetTapAdapterState (l_Adapter); - l_Adapter->m_Extension.m_TapOpens = 1; - succeeded = TRUE; - } - - if (succeeded) - { - INCREMENT_STAT (l_Adapter->m_Extension.m_NumTapOpens); - p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS; - p_IRP->IoStatus.Information = 0; - } - else - { - DEBUGP (("[%s] TAP is presently unavailable (m_TapOpens=%d)\n", - NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens)); - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; - p_IRP->IoStatus.Information = 0; - } + //------------------ + // Strange Request + //------------------ + default: + { + //NOTE_ERROR (); + p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; + IoCompleteRequest (p_IRP, IO_NO_INCREMENT); + break; + } + } - RELEASE_MUTEX (&l_Adapter->m_Extension.m_OpenCloseMutex); - } - else - { - DEBUGP (("[%s] TAP is presently locked (m_TapOpens=%d)\n", - NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens)); - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; - p_IRP->IoStatus.Information = 0; - } - - IoCompleteRequest (p_IRP, IO_NO_INCREMENT); - break; - } - - //----------------------------------------------------------- - // User mode thread called CloseHandle() on the tap device - //----------------------------------------------------------- - case IRP_MJ_CLOSE: - { - BOOLEAN mutex_succeeded; - - DEBUGP (("[%s] [TAP] release [%d.%d] close/cleanup request\n", - NAME (l_Adapter), TAP_DRIVER_MAJOR_VERSION, - TAP_DRIVER_MINOR_VERSION)); - - ACQUIRE_MUTEX_ADAPTIVE (&l_Adapter->m_Extension.m_OpenCloseMutex, mutex_succeeded); - if (mutex_succeeded) - { - l_Adapter->m_Extension.m_TapOpens = 0; - ResetTapAdapterState (l_Adapter); - FlushQueues (&l_Adapter->m_Extension); - SetMediaStatus (l_Adapter, FALSE); - RELEASE_MUTEX (&l_Adapter->m_Extension.m_OpenCloseMutex); - } - else - { - DEBUGP (("[%s] TAP is presently locked (m_TapOpens=%d)\n", - NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens)); - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; - p_IRP->IoStatus.Information = 0; - } - - IoCompleteRequest (p_IRP, IO_NO_INCREMENT); - break; - } - - //------------------ - // Strange Request - //------------------ - default: - { - //NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; - IoCompleteRequest (p_IRP, IO_NO_INCREMENT); - break; - } - } - - return l_Status; + return l_Status; } //============================================================= @@ -2618,82 +1928,82 @@ TapDeviceHook (IN PDEVICE_OBJECT p_DeviceObject, IN PIRP p_IRP) //============================================================= NTSTATUS -CompleteIRP (IN PIRP p_IRP, - IN TapPacketPointer p_PacketBuffer, - IN CCHAR PriorityBoost) + CompleteIRP (IN PIRP p_IRP, + IN TapPacketPointer p_PacketBuffer, + IN CCHAR PriorityBoost) { - NTSTATUS l_Status = STATUS_UNSUCCESSFUL; - - int offset; - int len; - - MYASSERT (p_IRP); - MYASSERT (p_PacketBuffer); - - IoSetCancelRoutine (p_IRP, NULL); // Disable cancel routine - - //------------------------------------------- - // While p_PacketBuffer always contains a - // full ethernet packet, including the - // ethernet header, in point-to-point mode, - // we only want to return the IPv4 - // component. - //------------------------------------------- - - if (p_PacketBuffer->m_SizeFlags & TP_TUN) - { - offset = ETHERNET_HEADER_SIZE; - len = (int) (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK) - ETHERNET_HEADER_SIZE; - } - else - { - offset = 0; - len = (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK); - } - - if (len < 0 || (int) p_IRP->IoStatus.Information < len) - { - p_IRP->IoStatus.Information = 0; - p_IRP->IoStatus.Status = STATUS_BUFFER_OVERFLOW; - NOTE_ERROR (); - } - else - { - p_IRP->IoStatus.Information = len; - p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS; - - __try + NTSTATUS l_Status = STATUS_UNSUCCESSFUL; + + int offset; + int len; + + MYASSERT (p_IRP); + MYASSERT (p_PacketBuffer); + + IoSetCancelRoutine (p_IRP, NULL); // Disable cancel routine + + //------------------------------------------- + // While p_PacketBuffer always contains a + // full ethernet packet, including the + // ethernet header, in point-to-point mode, + // we only want to return the IPv4 + // component. + //------------------------------------------- + + if (p_PacketBuffer->m_SizeFlags & TP_TUN) + { + offset = ETHERNET_HEADER_SIZE; + len = (int) (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK) - ETHERNET_HEADER_SIZE; + } + else + { + offset = 0; + len = (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK); + } + + if (len < 0 || (int) p_IRP->IoStatus.Information < len) { - NdisMoveMemory (p_IRP->AssociatedIrp.SystemBuffer, - p_PacketBuffer->m_Data + offset, - len); + p_IRP->IoStatus.Information = 0; + p_IRP->IoStatus.Status = STATUS_BUFFER_OVERFLOW; + NOTE_ERROR (); } - __except (EXCEPTION_EXECUTE_HANDLER) + else + { + p_IRP->IoStatus.Information = len; + p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS; + + __try + { + NdisMoveMemory (p_IRP->AssociatedIrp.SystemBuffer, + p_PacketBuffer->m_Data + offset, + len); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + NOTE_ERROR (); + p_IRP->IoStatus.Status = STATUS_UNSUCCESSFUL; + p_IRP->IoStatus.Information = 0; + } + } + + __try + { + NdisFreeMemory (p_PacketBuffer, + TAP_PACKET_SIZE (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK), + 0); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + } + + if (l_Status == STATUS_SUCCESS) { - NOTE_ERROR (); - p_IRP->IoStatus.Status = STATUS_UNSUCCESSFUL; - p_IRP->IoStatus.Information = 0; + IoCompleteRequest (p_IRP, PriorityBoost); } - } - - __try - { - NdisFreeMemory (p_PacketBuffer, - TAP_PACKET_SIZE (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK), - 0); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - } - - if (l_Status == STATUS_SUCCESS) - { - IoCompleteRequest (p_IRP, PriorityBoost); - } - else - IoCompleteRequest (p_IRP, IO_NO_INCREMENT); - - return l_Status; + else + IoCompleteRequest (p_IRP, IO_NO_INCREMENT); + + return l_Status; } //============================================== @@ -2707,467 +2017,101 @@ CompleteIRP (IN PIRP p_IRP, // device is still open by a process. //============================================== VOID -CancelIRPCallback (IN PDEVICE_OBJECT p_DeviceObject, - IN PIRP p_IRP) + CancelIRPCallback (IN PDEVICE_OBJECT p_DeviceObject, + IN PIRP p_IRP) { - TapAdapterPointer l_Adapter = LookupAdapterInInstanceList (p_DeviceObject); - CancelIRP (l_Adapter ? &l_Adapter->m_Extension : NULL, p_IRP, TRUE); + TapAdapterPointer l_Adapter = LookupAdapterInInstanceList (p_DeviceObject); + CancelIRP (l_Adapter ? &l_Adapter->m_Extension : NULL, p_IRP, TRUE); } VOID -CancelIRP (TapExtensionPointer p_Extension, - IN PIRP p_IRP, - BOOLEAN callback) + CancelIRP (TapExtensionPointer p_Extension, + IN PIRP p_IRP, + BOOLEAN callback) { - BOOLEAN exists = FALSE; - - MYASSERT (p_IRP); - - if (p_Extension) - { - NdisAcquireSpinLock (&p_Extension->m_QueueLock); - exists = (QueueExtract (p_Extension->m_IrpQueue, p_IRP) == p_IRP); - NdisReleaseSpinLock (&p_Extension->m_QueueLock); - } - else - exists = TRUE; - - if (exists) - { - IoSetCancelRoutine (p_IRP, NULL); - p_IRP->IoStatus.Status = STATUS_CANCELLED; - p_IRP->IoStatus.Information = 0; - } - - if (callback) - IoReleaseCancelSpinLock (p_IRP->CancelIrql); - - if (exists) - IoCompleteRequest (p_IRP, IO_NO_INCREMENT); -} + BOOLEAN exists = FALSE; -//=========================================== -// Exhaust packet, IRP, and injection queues. -//=========================================== -VOID -FlushQueues (TapExtensionPointer p_Extension) -{ - PIRP l_IRP; - TapPacketPointer l_PacketBuffer; - InjectPacketPointer l_InjectBuffer; - int n_IRP=0, n_Packet=0, n_Inject=0; - - MYASSERT (p_Extension); - MYASSERT (p_Extension->m_TapDevice); - - while (TRUE) - { - NdisAcquireSpinLock (&p_Extension->m_QueueLock); - l_IRP = QueuePop (p_Extension->m_IrpQueue); - NdisReleaseSpinLock (&p_Extension->m_QueueLock); - if (l_IRP) - { - ++n_IRP; - CancelIRP (NULL, l_IRP, FALSE); - } - else - break; - } - - while (TRUE) - { - NdisAcquireSpinLock (&p_Extension->m_QueueLock); - l_PacketBuffer = QueuePop (p_Extension->m_PacketQueue); - NdisReleaseSpinLock (&p_Extension->m_QueueLock); - if (l_PacketBuffer) - { - ++n_Packet; - MemFree (l_PacketBuffer, TAP_PACKET_SIZE (l_PacketBuffer->m_SizeFlags & TP_SIZE_MASK)); - } - else - 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_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, - n_Inject, - p_Extension->m_InjectQueue->max_size, - INJECT_QUEUE_SIZE - )); -} + MYASSERT (p_IRP); -//=================================================== -// Tell Windows whether the TAP device should be -// considered "connected" or "disconnected". -//=================================================== -VOID -SetMediaStatus (TapAdapterPointer p_Adapter, BOOLEAN state) -{ - if (p_Adapter->m_MediaState != state && !p_Adapter->m_MediaStateAlwaysConnected) - { - if (state) - NdisMIndicateStatus (p_Adapter->m_MiniportAdapterHandle, - NDIS_STATUS_MEDIA_CONNECT, NULL, 0); - else - NdisMIndicateStatus (p_Adapter->m_MiniportAdapterHandle, - NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0); - - NdisMIndicateStatusComplete (p_Adapter->m_MiniportAdapterHandle); - p_Adapter->m_MediaState = state; - } -} - - -//====================================================== -// If DHCP mode is used together with tun -// mode, consider the fact that the P2P remote subnet -// might enclose the DHCP masq server address. -//====================================================== -VOID -CheckIfDhcpAndTunMode (TapAdapterPointer p_Adapter) -{ -#if 0 - if (p_Adapter->m_tun && p_Adapter->m_dhcp_enabled) - { - if ((p_Adapter->m_dhcp_server_ip & p_Adapter->m_remoteNetmask) == p_Adapter->m_remoteNetwork) + if (p_Extension) { - COPY_MAC (p_Adapter->m_dhcp_server_mac, p_Adapter->m_TapToUser.dest); - p_Adapter->m_dhcp_server_arp = FALSE; + NdisAcquireSpinLock (&p_Extension->m_QueueLock); + exists = (QueueExtract (p_Extension->m_IrpQueue, p_IRP) == p_IRP); + NdisReleaseSpinLock (&p_Extension->m_QueueLock); } - } -#endif -} + else + exists = TRUE; -#if 0 -//=================================================== -// Generate an ARP reply message for specific kinds -// ARP queries. -//=================================================== -BOOLEAN -ProcessARP (TapAdapterPointer p_Adapter, - const PARP_PACKET src, - const IPADDR adapter_ip, - const IPADDR ip_network, - const IPADDR ip_netmask, - const MACADDR mac) -{ - //----------------------------------------------- - // Is this the kind of packet we are looking for? - //----------------------------------------------- - if (src->m_Proto == htons (ETH_P_ARP) - && MAC_EQUAL (src->m_MAC_Source, p_Adapter->m_MAC) - && MAC_EQUAL (src->m_ARP_MAC_Source, p_Adapter->m_MAC) - && MAC_EQUAL (src->m_MAC_Destination, p_Adapter->m_MAC_Broadcast) - && src->m_ARP_Operation == htons (ARP_REQUEST) - && src->m_MAC_AddressType == htons (MAC_ADDR_TYPE) - && src->m_MAC_AddressSize == sizeof (MACADDR) - && src->m_PROTO_AddressType == htons (ETH_P_IP) - && src->m_PROTO_AddressSize == sizeof (IPADDR) - && src->m_ARP_IP_Source == adapter_ip - && (src->m_ARP_IP_Destination & ip_netmask) == ip_network - && src->m_ARP_IP_Destination != adapter_ip) - { - ARP_PACKET *arp = (ARP_PACKET *) MemAlloc (sizeof (ARP_PACKET), TRUE); - if (arp) + if (exists) { - //---------------------------------------------- - // Initialize ARP reply fields - //---------------------------------------------- - arp->m_Proto = htons (ETH_P_ARP); - arp->m_MAC_AddressType = htons (MAC_ADDR_TYPE); - arp->m_PROTO_AddressType = htons (ETH_P_IP); - arp->m_MAC_AddressSize = sizeof (MACADDR); - arp->m_PROTO_AddressSize = sizeof (IPADDR); - arp->m_ARP_Operation = htons (ARP_REPLY); - - //---------------------------------------------- - // ARP addresses - //---------------------------------------------- - COPY_MAC (arp->m_MAC_Source, mac); - COPY_MAC (arp->m_MAC_Destination, p_Adapter->m_MAC); - COPY_MAC (arp->m_ARP_MAC_Source, mac); - COPY_MAC (arp->m_ARP_MAC_Destination, p_Adapter->m_MAC); - arp->m_ARP_IP_Source = src->m_ARP_IP_Destination; - arp->m_ARP_IP_Destination = adapter_ip; - - DUMP_PACKET ("ProcessARP", - (unsigned char *) arp, - sizeof (ARP_PACKET)); - - InjectPacketDeferred (p_Adapter, (UCHAR *) arp, sizeof (ARP_PACKET)); - - MemFree (arp, sizeof (ARP_PACKET)); + IoSetCancelRoutine (p_IRP, NULL); + p_IRP->IoStatus.Status = STATUS_CANCELLED; + p_IRP->IoStatus.Information = 0; } - return TRUE; - } - else - return FALSE; -} -#endif - -//=============================================================== -// Used in cases where internally generated packets such as -// ARP or DHCP replies must be returned to the kernel, to be -// seen as an incoming packet "arriving" on the interface. -//=============================================================== + if (callback) + IoReleaseCancelSpinLock (p_IRP->CancelIrql); -// Defer packet injection till IRQL < DISPATCH_LEVEL -VOID -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); - } + if (exists) + IoCompleteRequest (p_IRP, IO_NO_INCREMENT); } -// 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 +//=========================================== +// Exhaust packet, IRP, and injection queues. +//=========================================== VOID -InjectPacketNow (TapAdapterPointer p_Adapter, - UCHAR *packet, - const unsigned int len) + FlushQueues (TapExtensionPointer p_Extension) { - MYASSERT (len >= ETHERNET_HEADER_SIZE); - - __try - { - //------------------------------------------------------------ - // NdisMEthIndicateReceive and NdisMEthIndicateReceiveComplete - // could potentially be called reentrantly both here and in - // 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, - (NDIS_HANDLE) p_Adapter, - packet, - ETHERNET_HEADER_SIZE, - packet + ETHERNET_HEADER_SIZE, - len - ETHERNET_HEADER_SIZE, - len - ETHERNET_HEADER_SIZE); - - NdisMEthIndicateReceiveComplete (p_Adapter->m_MiniportAdapterHandle); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - DEBUGP (("[%s] NdisMEthIndicateReceive failed in InjectPacketNow\n", - NAME (p_Adapter))); - NOTE_ERROR (); - } -} + PIRP l_IRP; + TapPacketPointer l_PacketBuffer; -//=================================================================== -// Go back to default TAP mode from Point-To-Point mode. -// Also reset (i.e. disable) DHCP Masq mode. -//=================================================================== -VOID ResetTapAdapterState (TapAdapterPointer p_Adapter) -{ -#if 0 - // Point-To-Point - p_Adapter->m_tun = FALSE; - p_Adapter->m_localIP = 0; - p_Adapter->m_remoteNetwork = 0; - p_Adapter->m_remoteNetmask = 0; - NdisZeroMemory (&p_Adapter->m_TapToUser, sizeof (p_Adapter->m_TapToUser)); - NdisZeroMemory (&p_Adapter->m_UserToTap, sizeof (p_Adapter->m_UserToTap)); - NdisZeroMemory (&p_Adapter->m_UserToTap_IPv6, sizeof (p_Adapter->m_UserToTap_IPv6)); - - // DHCP Masq - p_Adapter->m_dhcp_enabled = FALSE; - p_Adapter->m_dhcp_server_arp = FALSE; - p_Adapter->m_dhcp_user_supplied_options_buffer_len = 0; - p_Adapter->m_dhcp_addr = 0; - p_Adapter->m_dhcp_netmask = 0; - p_Adapter->m_dhcp_server_ip = 0; - p_Adapter->m_dhcp_lease_time = 0; - p_Adapter->m_dhcp_received_discover = FALSE; - p_Adapter->m_dhcp_bad_requests = 0; - NdisZeroMemory (p_Adapter->m_dhcp_server_mac, sizeof (MACADDR)); -#endif -} + MYASSERT (p_Extension); + MYASSERT (p_Extension->m_TapDevice); -#if ENABLE_NONADMIN + while (TRUE) + { + NdisAcquireSpinLock (&p_Extension->m_QueueLock); + l_IRP = (PIRP)QueuePop (p_Extension->m_IrpQueue); + NdisReleaseSpinLock (&p_Extension->m_QueueLock); + if (l_IRP) + { + CancelIRP (NULL, l_IRP, FALSE); + } + else + break; + } -//=================================================================== -// Set TAP device handle to be accessible without admin privileges. -//=================================================================== -VOID AllowNonAdmin (TapExtensionPointer p_Extension) -{ - NTSTATUS stat; - SECURITY_DESCRIPTOR sd; - OBJECT_ATTRIBUTES oa; - IO_STATUS_BLOCK isb; - HANDLE hand = NULL; - - NdisZeroMemory (&sd, sizeof (sd)); - NdisZeroMemory (&oa, sizeof (oa)); - NdisZeroMemory (&isb, sizeof (isb)); - - if (!p_Extension->m_CreatedUnicodeLinkName) - { - DEBUGP (("[TAP] AllowNonAdmin: UnicodeLinkName is uninitialized\n")); - NOTE_ERROR (); - return; - } - - stat = RtlCreateSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION); - if (stat != STATUS_SUCCESS) - { - DEBUGP (("[TAP] AllowNonAdmin: RtlCreateSecurityDescriptor failed\n")); - NOTE_ERROR (); - return; - } - - InitializeObjectAttributes ( - &oa, - &p_Extension->m_UnicodeLinkName, - OBJ_KERNEL_HANDLE, - NULL, - NULL - ); - - stat = ZwOpenFile ( - &hand, - WRITE_DAC, - &oa, - &isb, - 0, - 0 - ); - if (stat != STATUS_SUCCESS) - { - DEBUGP (("[TAP] AllowNonAdmin: ZwOpenFile failed, status=0x%08x\n", (unsigned int)stat)); - NOTE_ERROR (); - return; - } - - stat = ZwSetSecurityObject (hand, DACL_SECURITY_INFORMATION, &sd); - if (stat != STATUS_SUCCESS) - { - DEBUGP (("[TAP] AllowNonAdmin: ZwSetSecurityObject failed\n")); - NOTE_ERROR (); - return; - } - - stat = ZwClose (hand); - if (stat != STATUS_SUCCESS) - { - DEBUGP (("[TAP] AllowNonAdmin: ZwClose failed\n")); - NOTE_ERROR (); - return; - } - - DEBUGP (("[TAP] AllowNonAdmin: SUCCEEDED\n")); + while (TRUE) + { + NdisAcquireSpinLock (&p_Extension->m_QueueLock); + l_PacketBuffer = (TapPacketPointer)QueuePop (p_Extension->m_PacketQueue); + NdisReleaseSpinLock (&p_Extension->m_QueueLock); + if (l_PacketBuffer) + { + MemFree (l_PacketBuffer, TAP_PACKET_SIZE (l_PacketBuffer->m_SizeFlags & TP_SIZE_MASK)); + } + else + break; + } } -#endif - -#if PACKET_TRUNCATION_CHECK - +//=================================================== +// Tell Windows whether the TAP device should be +// considered "connected" or "disconnected". +//=================================================== VOID -IPv4PacketSizeVerify (const UCHAR *data, ULONG length, BOOLEAN tun, const char *prefix, LONG *counter) + SetMediaStatus (TapAdapterPointer p_Adapter, BOOLEAN state) { - const IPHDR *ip; - int len = length; - - if (tun) - { - ip = (IPHDR *) data; - } - else - { - if (length >= sizeof (ETH_HEADER)) + if (p_Adapter->m_MediaState != state && !p_Adapter->m_MediaStateAlwaysConnected) { - const ETH_HEADER *eth = (ETH_HEADER *) data; - - if (eth->proto != htons (ETH_P_IP)) - return; - - ip = (IPHDR *) (data + sizeof (ETH_HEADER)); - len -= sizeof (ETH_HEADER); + if (state) + NdisMIndicateStatus (p_Adapter->m_MiniportAdapterHandle, + NDIS_STATUS_MEDIA_CONNECT, NULL, 0); + else + NdisMIndicateStatus (p_Adapter->m_MiniportAdapterHandle, + NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0); + + NdisMIndicateStatusComplete (p_Adapter->m_MiniportAdapterHandle); + p_Adapter->m_MediaState = state; } - else - return; - } - - if (len >= sizeof (IPHDR)) - { - const int totlen = ntohs (ip->tot_len); - - DEBUGP (("[TAP] IPv4PacketSizeVerify %s len=%d totlen=%d\n", prefix, len, totlen)); - - if (len != totlen) - ++(*counter); - } } - -#endif - -//====================================================================== -// End of Source -//====================================================================== |