?? tapdrvr.c
字號(hào):
/* * TAP-Win32 -- A kernel driver to provide virtual tap device * functionality on Windows. Originally derived * from the CIPE-Win32 project by Damion K. Wilson, * with extensive modifications by James Yonan. * * All source code which derives from the CIPE-Win32 project is * Copyright (C) Damion K. Wilson, 2003, and is released under the * GPL version 2 (see below). * * All other source code is Copyright (C) 2002-2005 OpenVPN Solutions LLC, * 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// versions of Windows.//// It is SMP-safe and handles NDIS 5 power management.//// By default we operate as a "tap" virtual ethernet// 802.3 interface, but we can emulate a "tun"// interface (point-to-point IPv4) through the// TAP_IOCTL_CONFIG_POINT_TO_POINT or// TAP_IOCTL_CONFIG_TUN ioctl.//======================================================#define NDIS_MINIPORT_DRIVER#define BINARY_COMPATIBLE 0#define NDIS50_MINIPORT 1#define NDIS_WDM 0#define NDIS50 1#define NTSTRSAFE_LIB// Debug info output#define ALSO_DBGPRINT 1#define DEBUGP_AT_DISPATCH 0//========================================================// Check for truncated IPv4 packets, log errors if found.//========================================================#define PACKET_TRUNCATION_CHECK 0 // JYFIXME//========================================================// 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 // JYFIXME#include <ndis.h>#include <ntstrsafe.h>#include <ntddk.h>#include "lock.h"#include "constants.h"#include "common.h"#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)#define INCREMENT_STAT(s) ++(s)#define NAME_BUFFER_SIZE 80//========================================================// Globals//========================================================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};//============================================================// Driver Entry//============================================================#pragma NDIS_INIT_FUNCTION (DriverEntry)NTSTATUSDriverEntry (IN PDRIVER_OBJECT p_DriverObject, IN PUNICODE_STRING p_RegistryPath){ NDIS_STATUS l_Status = NDIS_STATUS_FAILURE; NDIS_MINIPORT_CHARACTERISTICS *l_Properties = NULL; //======================================================== // Notify NDIS that a new miniport driver is initializing. //======================================================== NdisMInitializeWrapper (&g_NdisWrapperHandle, p_DriverObject, p_RegistryPath, NULL); //====================== // Global initialization //======================#if DBG 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->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;}//============================================================// Driver Unload//============================================================VOID 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 //==============================#if DBG MyDebugFree ();#endif}//==========================================================// 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){ TapAdapterPointer l_Adapter = NULL; 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 //==================================== // 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 //========================================= 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 key = NDIS_STRING_CONST("MiniportName"); NdisReadConfiguration (&status, &parm, configHandle, &key, NdisParameterString); if (status == NDIS_STATUS_SUCCESS) { if (parm->ParameterType == NdisParameterString) { DEBUGP (("[TAP] NdisReadConfiguration (MiniportName=%s)\n", parm->ParameterData.StringData.Buffer)); if (RtlUnicodeStringToAnsiString ( &l_Adapter->m_NameAnsi, &parm->ParameterData.StringData, TRUE) != STATUS_SUCCESS) { DEBUGP (("[TAP] RtlUnicodeStringToAnsiString MiniportName failed\n")); status = NDIS_STATUS_RESOURCES; } } } else { /* "MiniportName" is available only XP and above. Not on Windows 2000. */ NDIS_STRING key = NDIS_STRING_CONST("NdisVersion"); NdisReadConfiguration (&status, &parm, configHandle, &key, NdisParameterInteger); if (status == NDIS_STATUS_SUCCESS) { if (parm->ParameterData.IntegerData == 0x50000) { /* Fallback for Windows 2000 with NDIS version 5.00.00 Don't use this on Vista, 'NDIS_MINIPORT_BLOCK' was changed! */ DEBUGP (("[TAP] NdisReadConfiguration NdisVersion (Int=%X)\n", parm->ParameterData.IntegerData)); if (RtlUnicodeStringToAnsiString ( &l_Adapter->m_NameAnsi, &((PNDIS_MINIPORT_BLOCK) p_AdapterHandle)->MiniportName, TRUE) != STATUS_SUCCESS) { DEBUGP (("[TAP] RtlUnicodeStringToAnsiString MiniportName (W2K) failed\n")); status = NDIS_STATUS_RESOURCES; } } } } } /* Can't continue without name (see macro 'NAME') */ if (status != NDIS_STATUS_SUCCESS || !l_Adapter->m_NameAnsi.Buffer) { NdisCloseConfiguration (configHandle); AdapterFreeResources (l_Adapter); 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)
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -