?? tapdrvr.c
字號:
{ 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) { 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) { enable_non_admin = TRUE; } } } }#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) { 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)); } //================================== // 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])); //================== // Set broadcast MAC //================== { int i; for (i = 0; i < sizeof (MACADDR); ++i) l_Adapter->m_MAC_Broadcast[i] = 0xFF; } //==================================== // 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); return tap_status; } } if (!AddAdapterToInstanceList (l_Adapter)) { NOTE_ERROR (); TapDeviceFreeResources (&l_Adapter->m_Extension); AdapterFreeResources (l_Adapter); return NDIS_STATUS_RESOURCES; } l_Adapter->m_InterfaceIsRunning = TRUE;#if ENABLE_NONADMIN if (enable_non_admin) AllowNonAdmin (&l_Adapter->m_Extension);#endif return NDIS_STATUS_SUCCESS;}VOIDAdapterHalt (IN NDIS_HANDLE p_AdapterContext){ BOOLEAN status; TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext; NOTE_ERROR (); l_Adapter->m_InterfaceIsRunning = FALSE; DEBUGP (("[%s] is being halted\n", NAME (l_Adapter))); DestroyTapDevice (&l_Adapter->m_Extension); // 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)); DEBUGP (("[TAP] version [%d.%d] %s %s AdapterHalt returning\n", TAP_DRIVER_MAJOR_VERSION, TAP_DRIVER_MINOR_VERSION, __DATE__, __TIME__));}VOIDAdapterFreeResources (TapAdapterPointer p_Adapter){ 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_RegisteredAdapterShutdownHandler) NdisMDeregisterAdapterShutdownHandler (p_Adapter->m_MiniportAdapterHandle); if (p_Adapter->m_MCLockAllocated) NdisFreeSpinLock (&l_Adapter->m_MCLock);}VOIDDestroyTapDevice (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);}VOIDTapDeviceFreeResources (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_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);}//========================================================================// Tap Device Initialization//========================================================================NDIS_STATUSCreateTapDevice (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, TAPSUFFIX); 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, TAPSUFFIX); 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", 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
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -