📄 tapdrvr.c
字号:
p_IRP->AssociatedIrp.SystemBuffer, l_IrpSp->Parameters.DeviceIoControl.InputBufferLength); l_Adapter->m_dhcp_user_supplied_options_buffer_len = l_IrpSp->Parameters.DeviceIoControl.InputBufferLength; p_IRP->IoStatus.Information = 1; // Simple boolean value } else { NOTE_ERROR (); p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER; } break; } default: { NOTE_ERROR (); p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER; break; } } IoCompleteRequest (p_IRP, IO_NO_INCREMENT); break; } //=========================================================== // User mode thread issued a read request on the tap device // If there are packets waiting to be read, then the request // will be satisfied here. If not, then the request will be // queued and satisfied by any packet that is not used to // satisfy requests ahead of it. //=========================================================== case IRP_MJ_READ: { TapPacketPointer l_PacketBuffer; BOOLEAN pending = FALSE; // Save IRP-accessible copy of buffer length p_IRP->IoStatus.Information = l_IrpSp->Parameters.Read.Length; if (p_IRP->MdlAddress == NULL) { DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_READ\n", NAME (l_Adapter))); NOTE_ERROR (); p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER; p_IRP->IoStatus.Information = 0; IoCompleteRequest (p_IRP, IO_NO_INCREMENT); break; } else if ((p_IRP->AssociatedIrp.SystemBuffer = MmGetSystemAddressForMdlSafe (p_IRP->MdlAddress, NormalPagePriority)) == NULL) { DEBUGP (("[%s] Could not map address in IRP_MJ_READ\n", NAME (l_Adapter))); NOTE_ERROR (); p_IRP->IoStatus.Status = l_Status = STATUS_INSUFFICIENT_RESOURCES; p_IRP->IoStatus.Information = 0; IoCompleteRequest (p_IRP, IO_NO_INCREMENT); break; } else if (!l_Adapter->m_InterfaceIsRunning) { DEBUGP (("[%s] Interface is down in IRP_MJ_READ\n", NAME (l_Adapter))); NOTE_ERROR (); p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; p_IRP->IoStatus.Information = 0; IoCompleteRequest (p_IRP, IO_NO_INCREMENT); break; } //================================== // Can we provide immediate service? //================================== l_PacketBuffer = NULL; NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock); if (IS_UP (l_Adapter) && QueueCount (l_Adapter->m_Extension.m_PacketQueue) && QueueCount (l_Adapter->m_Extension.m_IrpQueue) == 0) { l_PacketBuffer = (TapPacketPointer) QueuePop (l_Adapter->m_Extension.m_PacketQueue); } NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock); if (l_PacketBuffer) { l_Status = CompleteIRP (p_IRP, l_PacketBuffer, IO_NO_INCREMENT); break; } //============================= // Attempt to pend read request //============================= NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock); if (IS_UP (l_Adapter) && QueuePush (l_Adapter->m_Extension.m_IrpQueue, p_IRP) == (PIRP) p_IRP) { IoSetCancelRoutine (p_IRP, CancelIRPCallback); l_Status = STATUS_PENDING; IoMarkIrpPending (p_IRP); pending = TRUE; } NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock); if (pending) break; // Can't queue anymore IRP's DEBUGP (("[%s] TAP [%s] read IRP overrun\n", NAME (l_Adapter), l_Adapter->m_Extension.m_TapName)); NOTE_ERROR (); p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; p_IRP->IoStatus.Information = 0; IoCompleteRequest (p_IRP, IO_NO_INCREMENT); break; } //============================================================== // User mode issued a WriteFile request on the TAP file handle. // The request will always get satisfied here. The call may // fail if there are too many pending packets (queue full). //============================================================== case IRP_MJ_WRITE: { if (p_IRP->MdlAddress == NULL) { DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_WRITE\n", NAME (l_Adapter))); NOTE_ERROR (); p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER; p_IRP->IoStatus.Information = 0; } else if ((p_IRP->AssociatedIrp.SystemBuffer = MmGetSystemAddressForMdlSafe (p_IRP->MdlAddress, NormalPagePriority)) == NULL) { DEBUGP (("[%s] Could not map address in IRP_MJ_WRITE\n", NAME (l_Adapter))); NOTE_ERROR (); p_IRP->IoStatus.Status = l_Status = STATUS_INSUFFICIENT_RESOURCES; p_IRP->IoStatus.Information = 0; } else if (!l_Adapter->m_InterfaceIsRunning) { DEBUGP (("[%s] Interface is down in IRP_MJ_WRITE\n", NAME (l_Adapter))); NOTE_ERROR (); p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; p_IRP->IoStatus.Information = 0; } else if (!l_Adapter->m_PointToPoint && ((l_IrpSp->Parameters.Write.Length) >= ETHERNET_HEADER_SIZE)) { __try { p_IRP->IoStatus.Information = l_IrpSp->Parameters.Write.Length; DUMP_PACKET ("IRP_MJ_WRITE ETH", (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer, l_IrpSp->Parameters.Write.Length); NdisMEthIndicateReceive (l_Adapter->m_MiniportAdapterHandle, (NDIS_HANDLE) l_Adapter, (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer, ETHERNET_HEADER_SIZE, (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer + ETHERNET_HEADER_SIZE, l_IrpSp->Parameters.Write.Length - ETHERNET_HEADER_SIZE, l_IrpSp->Parameters.Write.Length - ETHERNET_HEADER_SIZE); NdisMEthIndicateReceiveComplete (l_Adapter->m_MiniportAdapterHandle); p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS; } __except (EXCEPTION_EXECUTE_HANDLER) { DEBUGP (("[%s] NdisMEthIndicateReceive failed in IRP_MJ_WRITE\n", NAME (l_Adapter))); NOTE_ERROR (); p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; p_IRP->IoStatus.Information = 0; } } else if (l_Adapter->m_PointToPoint && ((l_IrpSp->Parameters.Write.Length) >= IP_HEADER_SIZE)) { __try { p_IRP->IoStatus.Information = l_IrpSp->Parameters.Write.Length; DUMP_PACKET2 ("IRP_MJ_WRITE P2P", &l_Adapter->m_UserToTap, (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer, l_IrpSp->Parameters.Write.Length); NdisMEthIndicateReceive (l_Adapter->m_MiniportAdapterHandle, (NDIS_HANDLE) l_Adapter, (unsigned char *) &l_Adapter->m_UserToTap, sizeof (l_Adapter->m_UserToTap), (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer, l_IrpSp->Parameters.Write.Length, l_IrpSp->Parameters.Write.Length); NdisMEthIndicateReceiveComplete (l_Adapter->m_MiniportAdapterHandle); p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS; } __except (EXCEPTION_EXECUTE_HANDLER) { DEBUGP (("[%s] NdisMEthIndicateReceive failed in IRP_MJ_WRITE (P2P)\n", NAME (l_Adapter))); NOTE_ERROR (); p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; p_IRP->IoStatus.Information = 0; } } else { DEBUGP (("[%s] Bad buffer size in IRP_MJ_WRITE, len=%d\n", NAME (l_Adapter), l_IrpSp->Parameters.Write.Length)); NOTE_ERROR (); p_IRP->IoStatus.Information = 0; // ETHERNET_HEADER_SIZE; p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL; } if (l_Status == STATUS_SUCCESS) INCREMENT_STAT (l_Adapter->m_Rx); else INCREMENT_STAT (l_Adapter->m_RxErr); IoCompleteRequest (p_IRP, IO_NO_INCREMENT); break; } //-------------------------------------------------------------- // User mode thread has called CreateFile() on the tap device //-------------------------------------------------------------- case IRP_MJ_CREATE: { BOOLEAN succeeded = FALSE; BOOLEAN mutex_succeeded; DEBUGP (("[%s] [TAP] release [%d.%d] open request (m_TapOpens=%d)\n", NAME (l_Adapter), TAP_DRIVER_MAJOR_VERSION, TAP_DRIVER_MINOR_VERSION, l_Adapter->m_Extension.m_TapOpens)); ACQUIRE_MUTEX_ADAPTIVE (&l_Adapter->m_Extension.m_OpenCloseMutex, mutex_succeeded); if (mutex_succeeded) { if (l_Adapter->m_Extension.m_TapIsRunning && !l_Adapter->m_Extension.m_TapOpens) { ResetTapAdapterState (l_Adapter); l_Adapter->m_Extension.m_TapOpens = 1; succeeded = TRUE; } if (succeeded) { INCREMENT_STAT (l_Adapter->m_Extension.m_NumTapOpens); p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS; p_IRP->IoStatus.Information = 0; } else { DEBUGP (("[%s] TAP is presently unavailable (m_TapOpens=%d)\n", NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens)); NOTE_ERROR (); p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; p_IRP->IoStatus.Information = 0; } RELEASE_MUTEX (&l_Adapter->m_Extension.m_OpenCloseMutex); } else { DEBUGP (("[%s] TAP is presently locked (m_TapOpens=%d)\n", NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens)); NOTE_ERROR (); p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; p_IRP->IoStatus.Information = 0; } IoCompleteRequest (p_IRP, IO_NO_INCREMENT); break; } //----------------------------------------------------------- // User mode thread called CloseHandle() on the tap device //----------------------------------------------------------- case IRP_MJ_CLOSE: { BOOLEAN mutex_succeeded; DEBUGP (("[%s] [TAP] release [%d.%d] close/cleanup request\n", NAME (l_Adapter), TAP_DRIVER_MAJOR_VERSION, TAP_DRIVER_MINOR_VERSION)); ACQUIRE_MUTEX_ADAPTIVE (&l_Adapter->m_Extension.m_OpenCloseMutex, mutex_succeeded); if (mutex_succeeded) { l_Adapter->m_Extension.m_TapOpens = 0; ResetTapAdapterState (l_Adapter); FlushQueues (&l_Adapter->m_Extension); SetMediaStatus (l_Adapter, FALSE); RELEASE_MUTEX (&l_Adapter->m_Extension.m_OpenCloseMutex); } else { DEBUGP (("[%s] TAP is presently locked (m_TapOpens=%d)\n", NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens)); NOTE_ERROR (); p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; p_IRP->IoStatus.Information = 0; } IoCompleteRequest (p_IRP, IO_NO_INCREMENT); break; } //------------------ // Strange Request //------------------ default: { //NOTE_ERROR (); p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; IoCompleteRequest (p_IRP, IO_NO_INCREMENT); break; } } return l_Status;}//=============================================================// CompleteIRP is normally called with an adapter -> userspace// network packet and an IRP (Pending I/O request) from userspace.//// The IRP will normally represent a queued overlapped read// operation from userspace that is in a wait state.//// Use the ethernet packet to satisfy the IRP.//=============================================================NTSTATUSCompleteIRP (IN PIRP p_IRP, IN TapPacketPointer p_PacketBuffer, IN CCHAR PriorityBoost){ NTSTATUS l_Status = STATUS_UNSUCCESSFUL; int offset; int len; MYASSERT (p_IRP); MYASSERT (p_PacketBuffer); IoSetCancelRoutine (p_IRP, NULL); // Disable cancel routine //------------------------------------------- // While p_PacketBuffer always contains a // full ethernet packet, including the // ethernet header, in point-to-point mode, // we only want to return the IPv4 // component. //------------------------------------------- if (p_PacketBuffer->m_SizeFlags & TP_POINT_TO_POINT) { offset = ETHERNET_HEADER_SIZE; len = (int) (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK) - ETHERNET_HEADER_SIZE; } else { offset = 0; len = (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK); } if (len < 0 || (int) p_IRP->IoStatus.Information < len) { p_IRP->IoStatus.Information = 0; p_IRP->IoStatus.Status = STATUS_BUFFER_OVERFLOW; NOTE_ERROR (); } else { p_IRP->IoStatus.Information = len; p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS; __try { NdisMoveMemory (p_IRP->AssociatedIrp.SystemBuffer, p_PacketBuffer->m_Data + offset, len); } __except (EXCEPTION_EXECUTE_HANDLER) { NOTE_ERROR (); p_IRP->IoStatus.Status = STATUS_UNSUCCESSFUL; p_IRP->IoStatus.Information = 0; } } __try { NdisFreeMemory (p_PacketBuffer, TAP_PACKET_SIZE (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK), 0); } __except (EXCEPTION_EXECUTE_HANDLER) { } if (l_Status == STATUS_SUCCESS) { IoCompleteRequest (p_IRP, PriorityBoost); } else IoCompleteRequest (p_IRP, IO_NO_INCREMENT); return l_Status;}//==============================================// IRPs get cancelled for a number of reasons.//// The TAP device could be closed by userspace// when there are still pending read operations.//// The user could disable the TAP adapter in the// network connections control panel, while the// device is still open by a process.//==============================================VOID
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -