ZeroTierOne/windows/TapDriver6/tapdrvr.c

233 lines
7.5 KiB
C

/*
* 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"));
}