📄 cipdrvr.c
字号:
l_Status = NDIS_STATUS_INVALID_LENGTH, *p_BytesNeeded = 4; if (p_BufferLength >= sizeof (ULONG)) { DbgPrint ("[%s] Setting [OID_GEN_CURRENT_PACKET_FILTER] to [0x%02lx]\n", l_Adapter->m_Name, l_Query->m_Long); l_Status = NDIS_STATUS_SUCCESS; *p_BytesRead = sizeof (ULONG); } break; case OID_GEN_CURRENT_LOOKAHEAD: if (p_BufferLength < sizeof (ULONG)) l_Status = NDIS_STATUS_INVALID_LENGTH, *p_BytesNeeded = 4; else if (l_Query->m_Long > DEFAULT_PACKET_LOOKAHEAD || l_Query->m_Long <= 0) l_Status = NDIS_STATUS_INVALID_DATA; else { DbgPrint ("[%s] Setting [OID_GEN_CURRENT_LOOKAHEAD] to [%d]\n", l_Adapter->m_Name, l_Query->m_Long); l_Adapter->m_Lookahead = l_Query->m_Long; l_Status = NDIS_STATUS_SUCCESS; *p_BytesRead = sizeof (ULONG); } break; case OID_GEN_NETWORK_LAYER_ADDRESSES: l_Status = NDIS_STATUS_SUCCESS; *p_BytesRead = *p_BytesNeeded = 0; break; case OID_GEN_TRANSPORT_HEADER_OFFSET: l_Status = NDIS_STATUS_SUCCESS; *p_BytesRead = *p_BytesNeeded = 0; break; case OID_PNP_REMOVE_WAKE_UP_PATTERN: case OID_PNP_ADD_WAKE_UP_PATTERN: l_Status = NDIS_STATUS_SUCCESS; *p_BytesRead = *p_BytesNeeded = 0; break; default: DbgPrint ("[%s] Can't set value for OID %lx\n", l_Adapter->m_Name, p_OID); l_Status = NDIS_STATUS_INVALID_OID; *p_BytesRead = *p_BytesNeeded = 0; break; } NdisReleaseSpinLock (&l_Adapter->m_Lock); return l_Status; }//===========================================================================================// Adapter Transmission//===========================================================================================NDIS_STATUS AdapterTransmit (IN NDIS_HANDLE p_AdapterContext, IN PNDIS_PACKET p_Packet, IN UINT p_Flags) { static NDIS_PHYSICAL_ADDRESS l_HighestAcceptableMax = NDIS_PHYSICAL_ADDRESS_CONST (-1,-1); CipeAdapterPointer l_Adapter = (CipeAdapterPointer) p_AdapterContext; ULONG l_Index = 0, l_BufferLength = 0, l_PacketLength = 0; CipePacketPointer l_PacketBuffer, l_Throwaway; CipeTapExtensionPointer l_Extension; PNDIS_BUFFER l_NDIS_Buffer; PUCHAR l_Buffer; NdisQueryPacket (p_Packet, NULL, NULL, &l_NDIS_Buffer, &l_PacketLength); //==================================================== // Here we abandon the transmission attempt if any of // the parameters is wrong or memory allocation fails // but we do not indicate failure. The packet is // silently dropped. //==================================================== if (l_Adapter->m_TapDevice == NULL) return NDIS_STATUS_FAILURE; else if ((l_Extension = (CipeTapExtensionPointer) l_Adapter->m_TapDevice->DeviceExtension) == NULL) return NDIS_STATUS_FAILURE; else if (l_PacketLength < ETHERNET_HEADER_SIZE) return NDIS_STATUS_FAILURE; else if (l_PacketLength > 65535) // Cap packet size to TCP/IP maximum return NDIS_STATUS_FAILURE; else if (! l_Adapter->m_TapOpens) // Nothing is bound to the TAP device return NDIS_STATUS_SUCCESS; NdisAllocateMemory (&l_PacketBuffer, sizeof (CipePacket) + l_PacketLength, 0, l_HighestAcceptableMax); if (l_PacketBuffer == NULL) return NDIS_STATUS_RESOURCES; else NdisZeroMemory (l_PacketBuffer, l_PacketLength); l_PacketBuffer->m_Size = l_PacketLength; //=========================== // Reassemble packet contents //=========================== __try { for (l_Index = 0; l_NDIS_Buffer && l_Index < l_PacketLength; l_Index += l_BufferLength) { NdisQueryBuffer (l_NDIS_Buffer, (PVOID *) &l_Buffer, &l_BufferLength); NdisMoveMemory (l_PacketBuffer->m_Data + l_Index, l_Buffer, l_BufferLength); NdisGetNextBuffer (l_NDIS_Buffer, &l_NDIS_Buffer); } if (QueuePush (&l_Extension->m_PacketQueue, l_PacketBuffer) != l_PacketBuffer) switch (OVERWRITE_OLD_PACKETS) { //******************** ALERT ************************ // If the oldest packet is discarded when a new queue // insertion is attempted, the usermode thread may // get a packet whose contents are partially invalid // I.E. the packet gets deleted while the usermode // thread is trying to fetch it //******************** ALERT ************************ case TRUE: // Try to throw away oldest packet { if (l_Throwaway = QueuePop (&l_Extension->m_PacketQueue)) { NdisFreeMemory (l_Throwaway, sizeof (CipePacket) + l_Throwaway->m_Size, 0); } if (QueuePush (&l_Extension->m_PacketQueue, l_PacketBuffer) != l_PacketBuffer) { NdisFreeMemory (l_PacketBuffer, sizeof (CipePacket) + l_PacketBuffer->m_Size, 0); } break; } case FALSE: { NdisFreeMemory (l_PacketBuffer, sizeof (CipePacket) + l_PacketBuffer->m_Size, 0); break; } } } __except (EXCEPTION_EXECUTE_HANDLER) { } while (QueueCount (&l_Extension->m_PacketQueue) && QueueCount (&l_Extension->m_IrpQueue)) { CompleteIRP (QueuePop (&l_Extension->m_IrpQueue), l_Extension); } return NDIS_STATUS_SUCCESS; }//===========================================================================================// Hook for catching tap device IRP's. Network adapter requests are forwarded on to NDIS//===========================================================================================NTSTATUS CipeTapDeviceHook (IN PDEVICE_OBJECT p_DeviceObject, IN PIRP p_IRP) { PIO_STACK_LOCATION l_IrpSp = IoGetCurrentIrpStackLocation (p_IRP); CipeTapExtensionPointer l_Extension; NTSTATUS l_Status = STATUS_SUCCESS; CipePacketPointer l_PacketBuffer; CipeAdapterPointer l_Adapter; //======================================================================= // If it's not the private data device type, call the original handler //======================================================================= if (p_DeviceObject->DeviceType != (FILE_DEVICE_PHYSICAL_NETCARD | 0x8000)) { return (*g_DispatchHook [l_IrpSp->MajorFunction]) (p_DeviceObject, p_IRP); } //======================================================================= // Only TAP device I/O requests get handled below here //======================================================================= l_Extension = (CipeTapExtensionPointer) p_DeviceObject->DeviceExtension; l_Adapter = l_Extension->m_Adapter; p_IRP->IoStatus.Status = STATUS_SUCCESS; p_IRP->IoStatus.Information = 0; switch (l_IrpSp->MajorFunction) { //----------------------------------------------------------- // Ioctl call handlers //----------------------------------------------------------- case IRP_MJ_DEVICE_CONTROL: { switch (l_IrpSp->Parameters.DeviceIoControl.IoControlCode) { case CIPE_IOCTL_GET_LASTMAC: { if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength >= sizeof (g_MAC)) { NdisMoveMemory (p_IRP->AssociatedIrp.SystemBuffer, g_MAC, sizeof (g_MAC)); p_IRP->IoStatus.Information = sizeof (g_MAC); } break; } case CIPE_IOCTL_GET_MAC: { if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength >= sizeof (g_MAC)) { NdisMoveMemory (p_IRP->AssociatedIrp.SystemBuffer, l_Adapter->m_MAC, sizeof (g_MAC)); p_IRP->IoStatus.Information = sizeof (g_MAC); } break; } case CIPE_IOCTL_SET_STATISTICS: { if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength >= (sizeof (ULONG) * 4)) { l_Adapter->m_Tx = ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer)) [0]; l_Adapter->m_Rx = ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer)) [1]; l_Adapter->m_TxErr = ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer)) [2]; l_Adapter->m_RxErr = ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer)) [3]; p_IRP->IoStatus.Information = 1; // Simple boolean value } break; } default: { 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: { p_IRP->IoStatus.Information = l_IrpSp->Parameters.Read.Length; // Save IRP accessible copy of buffer length p_IRP->AssociatedIrp.SystemBuffer = MmGetSystemAddressForMdl (p_IRP->MdlAddress); /* DO_DIRECT_IO only !!! */ if (! l_Adapter->m_InterfaceIsRunning) { DbgPrint ("[%s] is unavailable for reading via TAP %s\n", l_Adapter->m_Name, l_Adapter->m_TapName); p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; p_IRP->IoStatus.Information = 0; IoCompleteRequest (p_IRP, IO_NO_INCREMENT); } else if (QueueCount (&l_Extension->m_PacketQueue) && QueueCount (&l_Extension->m_IrpQueue) == 0) // Immediate service { l_Status = CompleteIRP (p_IRP, l_Extension); } else if (QueuePush (&l_Extension->m_IrpQueue, p_IRP) == p_IRP) // Attempt to pend read request { IoSetCancelRoutine (p_IRP, CancelIRP); l_Status = STATUS_PENDING; IoMarkIrpPending (p_IRP); } else // Can't queue anymore IRP's { DbgPrint ("[%s] TAP [%s] read IRP overrun\n", l_Adapter->m_Name, l_Adapter->m_TapName); p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; p_IRP->IoStatus.Information = 0; IoCompleteRequest (p_IRP, IO_NO_INCREMENT); } break; } //----------------------------------------------------------- // User mode thread issued a write request on the tap device // The request will always get satisfied here. The call may // fail if there are too many pending packets (queue full) //----------------------------------------------------------- case IRP_MJ_WRITE: { p_IRP->AssociatedIrp.SystemBuffer = MmGetSystemAddressForMdl (p_IRP->MdlAddress); /* DO_DIRECT_IO only !!! */ if (! l_Adapter->m_InterfaceIsRunning) { DbgPrint ("[%s] is unavailable for writing via TAP %s\n", l_Adapter->m_Name, l_Adapter->m_TapName); p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; p_IRP->IoStatus.Information = 0; l_Status = STATUS_UNSUCCESSFUL; } else if (p_IRP->AssociatedIrp.SystemBuffer && (p_IRP->IoStatus.Information = l_IrpSp->Parameters.Write.Length) >= ETHERNET_HEADER_SIZE) { __try { 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); } __except (EXCEPTION_EXECUTE_HANDLER) { p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; p_IRP->IoStatus.Information = 0; } } else { p_IRP->IoStatus.Information = 0; // ETHERNET_HEADER_SIZE; p_IRP->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; l_Status = STATUS_UNSUCCESSFUL; } IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -