You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
232 lines
7.5 KiB
232 lines
7.5 KiB
/* |
|
* 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-2014 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 Windows Vista or higher |
|
// versions of Windows. |
|
// |
|
// It is SMP-safe and handles 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_WIN_IOCTL_CONFIG_POINT_TO_POINT or |
|
// TAP_WIN_IOCTL_CONFIG_TUN ioctl. |
|
//====================================================== |
|
|
|
// |
|
// Include files. |
|
// |
|
|
|
#include <string.h> |
|
|
|
#include "tap.h" |
|
|
|
|
|
// Global data |
|
TAP_GLOBAL GlobalData; |
|
|
|
|
|
#ifdef ALLOC_PRAGMA |
|
#pragma alloc_text( INIT, DriverEntry ) |
|
#pragma alloc_text( PAGE, TapDriverUnload) |
|
#endif // ALLOC_PRAGMA |
|
|
|
NTSTATUS |
|
DriverEntry( |
|
__in PDRIVER_OBJECT DriverObject, |
|
__in PUNICODE_STRING RegistryPath |
|
) |
|
/*++ |
|
Routine Description: |
|
|
|
In the context of its DriverEntry function, a miniport driver associates |
|
itself with NDIS, specifies the NDIS version that it is using, and |
|
registers its entry points. |
|
|
|
|
|
Arguments: |
|
PVOID DriverObject - pointer to the driver object. |
|
PVOID RegistryPath - pointer to the driver registry path. |
|
|
|
Return Value: |
|
|
|
NTSTATUS code |
|
|
|
--*/ |
|
{ |
|
NTSTATUS status; |
|
|
|
UNREFERENCED_PARAMETER(RegistryPath); |
|
|
|
DEBUGP (("[TAP] --> DriverEntry; version [%d.%d] %s %s\n", |
|
TAP_DRIVER_MAJOR_VERSION, |
|
TAP_DRIVER_MINOR_VERSION, |
|
__DATE__, |
|
__TIME__)); |
|
|
|
DEBUGP (("[TAP] Registry Path: '%wZ'\n", RegistryPath)); |
|
|
|
// |
|
// Initialize any driver-global variables here. |
|
// |
|
NdisZeroMemory(&GlobalData, sizeof(GlobalData)); |
|
|
|
// |
|
// The ApaterList in the GlobalData structure is used to track multiple |
|
// adapters controlled by this miniport. |
|
// |
|
NdisInitializeListHead(&GlobalData.AdapterList); |
|
|
|
// |
|
// This lock protects the AdapterList. |
|
// |
|
NdisInitializeReadWriteLock(&GlobalData.Lock); |
|
|
|
do |
|
{ |
|
NDIS_MINIPORT_DRIVER_CHARACTERISTICS miniportCharacteristics; |
|
|
|
NdisZeroMemory(&miniportCharacteristics, sizeof(miniportCharacteristics)); |
|
|
|
{C_ASSERT(sizeof(miniportCharacteristics) >= NDIS_SIZEOF_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2);} |
|
miniportCharacteristics.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS; |
|
miniportCharacteristics.Header.Size = NDIS_SIZEOF_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2; |
|
miniportCharacteristics.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2; |
|
|
|
miniportCharacteristics.MajorNdisVersion = TAP_NDIS_MAJOR_VERSION; |
|
miniportCharacteristics.MinorNdisVersion = TAP_NDIS_MINOR_VERSION; |
|
|
|
miniportCharacteristics.MajorDriverVersion = TAP_DRIVER_MAJOR_VERSION; |
|
miniportCharacteristics.MinorDriverVersion = TAP_DRIVER_MINOR_VERSION; |
|
|
|
miniportCharacteristics.Flags = 0; |
|
|
|
//miniportCharacteristics.SetOptionsHandler = MPSetOptions; // Optional |
|
miniportCharacteristics.InitializeHandlerEx = AdapterCreate; |
|
miniportCharacteristics.HaltHandlerEx = AdapterHalt; |
|
miniportCharacteristics.UnloadHandler = TapDriverUnload; |
|
miniportCharacteristics.PauseHandler = AdapterPause; |
|
miniportCharacteristics.RestartHandler = AdapterRestart; |
|
miniportCharacteristics.OidRequestHandler = AdapterOidRequest; |
|
miniportCharacteristics.SendNetBufferListsHandler = AdapterSendNetBufferLists; |
|
miniportCharacteristics.ReturnNetBufferListsHandler = AdapterReturnNetBufferLists; |
|
miniportCharacteristics.CancelSendHandler = AdapterCancelSend; |
|
miniportCharacteristics.CheckForHangHandlerEx = AdapterCheckForHangEx; |
|
miniportCharacteristics.ResetHandlerEx = AdapterReset; |
|
miniportCharacteristics.DevicePnPEventNotifyHandler = AdapterDevicePnpEventNotify; |
|
miniportCharacteristics.ShutdownHandlerEx = AdapterShutdownEx; |
|
miniportCharacteristics.CancelOidRequestHandler = AdapterCancelOidRequest; |
|
|
|
// |
|
// Associate the miniport driver with NDIS by calling the |
|
// NdisMRegisterMiniportDriver. This function returns an NdisDriverHandle. |
|
// The miniport driver must retain this handle but it should never attempt |
|
// to access or interpret this handle. |
|
// |
|
// By calling NdisMRegisterMiniportDriver, the driver indicates that it |
|
// is ready for NDIS to call the driver's MiniportSetOptions and |
|
// MiniportInitializeEx handlers. |
|
// |
|
DEBUGP (("[TAP] Calling NdisMRegisterMiniportDriver...\n")); |
|
//NDIS_DECLARE_MINIPORT_DRIVER_CONTEXT(TAP_GLOBAL); |
|
status = NdisMRegisterMiniportDriver( |
|
DriverObject, |
|
RegistryPath, |
|
&GlobalData, |
|
&miniportCharacteristics, |
|
&GlobalData.NdisDriverHandle |
|
); |
|
|
|
if (NDIS_STATUS_SUCCESS == status) |
|
{ |
|
DEBUGP (("[TAP] Registered miniport successfully\n")); |
|
} |
|
else |
|
{ |
|
DEBUGP(("[TAP] NdisMRegisterMiniportDriver failed: %8.8X\n", status)); |
|
TapDriverUnload(DriverObject); |
|
status = NDIS_STATUS_FAILURE; |
|
break; |
|
} |
|
} while(FALSE); |
|
|
|
DEBUGP (("[TAP] <-- DriverEntry; status = %8.8X\n",status)); |
|
|
|
return status; |
|
} |
|
|
|
VOID |
|
TapDriverUnload( |
|
__in PDRIVER_OBJECT DriverObject |
|
) |
|
/*++ |
|
|
|
Routine Description: |
|
|
|
The unload handler is called during driver unload to free up resources |
|
acquired in DriverEntry. This handler is registered in DriverEntry through |
|
NdisMRegisterMiniportDriver. Note that an unload handler differs from |
|
a MiniportHalt function in that this unload handler releases resources that |
|
are global to the driver, while the halt handler releases resource for a |
|
particular adapter. |
|
|
|
Runs at IRQL = PASSIVE_LEVEL. |
|
|
|
Arguments: |
|
|
|
DriverObject Not used |
|
|
|
Return Value: |
|
|
|
None. |
|
|
|
--*/ |
|
{ |
|
PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject; |
|
UNICODE_STRING uniWin32NameString; |
|
|
|
DEBUGP (("[TAP] --> TapDriverUnload; version [%d.%d] %s %s unloaded\n", |
|
TAP_DRIVER_MAJOR_VERSION, |
|
TAP_DRIVER_MINOR_VERSION, |
|
__DATE__, |
|
__TIME__ |
|
)); |
|
|
|
PAGED_CODE(); |
|
|
|
// |
|
// Clean up all globals that were allocated in DriverEntry |
|
// |
|
|
|
ASSERT(IsListEmpty(&GlobalData.AdapterList)); |
|
|
|
if(GlobalData.NdisDriverHandle != NULL ) |
|
{ |
|
NdisMDeregisterMiniportDriver(GlobalData.NdisDriverHandle); |
|
} |
|
|
|
DEBUGP (("[TAP] <-- TapDriverUnload\n")); |
|
} |
|
|
|
|