mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2024-11-22 21:40:19 -08:00
233 lines
7.5 KiB
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"));
|
|
}
|
|
|