?? tapdrvr.c
字號:
if (NewDeviceState > NdisDeviceStateD0) { l_Adapter->m_InterfaceIsRunning = FALSE; DEBUGP (("[%s] Power management device state OFF\n", NAME (l_Adapter))); } else { l_Adapter->m_InterfaceIsRunning = TRUE; DEBUGP (("[%s] Power management device state ON\n", NAME (l_Adapter))); } l_Status = NDIS_STATUS_SUCCESS; } while (FALSE); if (l_Status == NDIS_STATUS_SUCCESS) { *p_BytesRead = sizeof (NDIS_DEVICE_POWER_STATE); *p_BytesNeeded = 0; } else { *p_BytesRead = 0; *p_BytesNeeded = sizeof (NDIS_DEVICE_POWER_STATE); } 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: DEBUGP (("[%s] Can't set value for OID %lx\n", NAME (l_Adapter), p_OID)); l_Status = NDIS_STATUS_INVALID_OID; *p_BytesRead = *p_BytesNeeded = 0; break; } return l_Status;}//====================================================================// Adapter Transmission//====================================================================NDIS_STATUSAdapterTransmit (IN NDIS_HANDLE p_AdapterContext, IN PNDIS_PACKET p_Packet, IN UINT p_Flags){ TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext; ULONG l_Index = 0, l_BufferLength = 0, l_PacketLength = 0; PIRP l_IRP; TapPacketPointer l_PacketBuffer; PNDIS_BUFFER l_NDIS_Buffer; PUCHAR l_Buffer; PVOID result; 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_PacketLength < ETHERNET_HEADER_SIZE || l_PacketLength > 65535) goto exit_fail; else if (!l_Adapter->m_Extension.m_TapOpens || !l_Adapter->m_MediaState) goto exit_success; // Nothing is bound to the TAP device if (NdisAllocateMemoryWithTag (&l_PacketBuffer, TAP_PACKET_SIZE (l_PacketLength), '5PAT') != NDIS_STATUS_SUCCESS) goto exit_no_resources; if (l_PacketBuffer == NULL) goto exit_no_resources; l_PacketBuffer->m_SizeFlags = (l_PacketLength & TP_SIZE_MASK); //=========================== // Reassemble packet contents //=========================== __try { l_Index = 0; while (l_NDIS_Buffer && l_Index < l_PacketLength) { ULONG newlen; NdisQueryBuffer (l_NDIS_Buffer, (PVOID *) & l_Buffer, &l_BufferLength); newlen = l_Index + l_BufferLength; if (newlen > l_PacketLength) { NOTE_ERROR (); goto no_queue; /* overflow */ } NdisMoveMemory (l_PacketBuffer->m_Data + l_Index, l_Buffer, l_BufferLength); l_Index = newlen; NdisGetNextBuffer (l_NDIS_Buffer, &l_NDIS_Buffer); } if (l_Index != l_PacketLength) { NOTE_ERROR (); goto no_queue; /* underflow */ } DUMP_PACKET ("AdapterTransmit", l_PacketBuffer->m_Data, l_PacketLength); //===================================================== // If IPv4 packet, check whether or not packet // was truncated. //=====================================================#if PACKET_TRUNCATION_CHECK IPv4PacketSizeVerify (l_PacketBuffer->m_Data, l_PacketLength, FALSE, "TX", &l_Adapter->m_TxTrunc);#endif //===================================================== // Are we running in DHCP server masquerade mode? // // If so, catch both DHCP requests and ARP queries // to resolve the address of our virtual DHCP server. //===================================================== if (l_Adapter->m_dhcp_enabled) { const ETH_HEADER *eth = (ETH_HEADER *) l_PacketBuffer->m_Data; const IPHDR *ip = (IPHDR *) (l_PacketBuffer->m_Data + sizeof (ETH_HEADER)); const UDPHDR *udp = (UDPHDR *) (l_PacketBuffer->m_Data + sizeof (ETH_HEADER) + sizeof (IPHDR)); // ARP packet? if (l_PacketLength == sizeof (ARP_PACKET) && eth->proto == htons (ETH_P_ARP) && l_Adapter->m_dhcp_server_arp) { if (ProcessARP (l_Adapter, (PARP_PACKET) l_PacketBuffer->m_Data, l_Adapter->m_dhcp_addr, l_Adapter->m_dhcp_server_ip, ~0, l_Adapter->m_dhcp_server_mac)) goto no_queue; } // DHCP packet? else if (l_PacketLength >= sizeof (ETH_HEADER) + sizeof (IPHDR) + sizeof (UDPHDR) + sizeof (DHCP) && eth->proto == htons (ETH_P_IP) && ip->version_len == 0x45 // IPv4, 20 byte header && ip->protocol == IPPROTO_UDP && udp->dest == htons (BOOTPS_PORT)) { const DHCP *dhcp = (DHCP *) (l_PacketBuffer->m_Data + sizeof (ETH_HEADER) + sizeof (IPHDR) + sizeof (UDPHDR)); const int optlen = l_PacketLength - sizeof (ETH_HEADER) - sizeof (IPHDR) - sizeof (UDPHDR) - sizeof (DHCP); if (optlen > 0) // we must have at least one DHCP option { if (ProcessDHCP (l_Adapter, eth, ip, udp, dhcp, optlen)) goto no_queue; } else goto no_queue; } } //=============================================== // In Point-To-Point mode, check to see whether // packet is ARP or IPv4 (if neither, then drop). //=============================================== if (l_Adapter->m_tun) { ETH_HEADER *e; if (l_PacketLength < ETHERNET_HEADER_SIZE) goto no_queue; e = (ETH_HEADER *) l_PacketBuffer->m_Data; switch (ntohs (e->proto)) { case ETH_P_ARP: // Make sure that packet is the // right size for ARP. if (l_PacketLength != sizeof (ARP_PACKET)) goto no_queue; ProcessARP (l_Adapter, (PARP_PACKET) l_PacketBuffer->m_Data, l_Adapter->m_localIP, l_Adapter->m_remoteNetwork, l_Adapter->m_remoteNetmask, l_Adapter->m_TapToUser.dest); default: goto no_queue; case ETH_P_IP: // Make sure that packet is large // enough to be IPv4. if (l_PacketLength < ETHERNET_HEADER_SIZE + IP_HEADER_SIZE) goto no_queue; // Only accept directed packets, // not broadcasts. if (memcmp (e, &l_Adapter->m_TapToUser, ETHERNET_HEADER_SIZE)) goto no_queue; // Packet looks like IPv4, queue it. l_PacketBuffer->m_SizeFlags |= TP_TUN; } } //=============================================== // Push packet onto queue to wait for read from // userspace. //=============================================== NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock); result = NULL; if (IS_UP (l_Adapter)) result = QueuePush (l_Adapter->m_Extension.m_PacketQueue, l_PacketBuffer); NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock); if ((TapPacketPointer) result != l_PacketBuffer) { // adapter receive overrun INCREMENT_STAT (l_Adapter->m_TxErr); goto no_queue; } else { INCREMENT_STAT (l_Adapter->m_Tx); } //============================================================ // Cycle through IRPs and packets, try to satisfy each pending // IRP with a queued packet. //============================================================ while (TRUE) { l_IRP = NULL; 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)) { l_IRP = (PIRP) QueuePop (l_Adapter->m_Extension.m_IrpQueue); l_PacketBuffer = (TapPacketPointer) QueuePop (l_Adapter->m_Extension.m_PacketQueue); } NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock); MYASSERT ((l_IRP != NULL) + (l_PacketBuffer != NULL) != 1); if (l_IRP && l_PacketBuffer) { CompleteIRP (l_IRP, l_PacketBuffer, IO_NETWORK_INCREMENT); } else break; } } __except (EXCEPTION_EXECUTE_HANDLER) { } return NDIS_STATUS_SUCCESS; no_queue: NdisFreeMemory (l_PacketBuffer, TAP_PACKET_SIZE (l_PacketLength), 0); exit_success: return NDIS_STATUS_SUCCESS; exit_fail: return NDIS_STATUS_FAILURE; exit_no_resources: return NDIS_STATUS_RESOURCES;}//======================================================================// Hooks for catching TAP device IRP's.//======================================================================NTSTATUSTapDeviceHook (IN PDEVICE_OBJECT p_DeviceObject, IN PIRP p_IRP){ TapAdapterPointer l_Adapter = LookupAdapterInInstanceList (p_DeviceObject); PIO_STACK_LOCATION l_IrpSp; NTSTATUS l_Status = STATUS_SUCCESS; BOOLEAN accessible; l_IrpSp = IoGetCurrentIrpStackLocation (p_IRP); p_IRP->IoStatus.Status = STATUS_SUCCESS; p_IRP->IoStatus.Information = 0; if (!l_Adapter || l_Adapter->m_Extension.m_Halt) { DEBUGP (("TapDeviceHook called when TAP device is halted, MajorFunction=%d\n", (int)l_IrpSp->MajorFunction)); if (l_IrpSp->MajorFunction == IRP_MJ_CLOSE) { IoCompleteRequest (p_IRP, IO_NO_INCREMENT); return STATUS_SUCCESS; } else { p_IRP->IoStatus.Status = STATUS_NO_SUCH_DEVICE; IoCompleteRequest (p_IRP, IO_NO_INCREMENT); return STATUS_NO_SUCH_DEVICE; } } switch (l_IrpSp->MajorFunction) { //=========================================================== // Ioctl call handlers //=========================================================== case IRP_MJ_DEVICE_CONTROL: { switch (l_IrpSp->Parameters.DeviceIoControl.IoControlCode) { case TAP_IOCTL_GET_MAC: { if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength >= sizeof (MACADDR)) { COPY_MAC (p_IRP->AssociatedIrp.SystemBuffer, l_Adapter->m_MAC); p_IRP->IoStatus.Information = sizeof (MACADDR); } else { NOTE_ERROR (); p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL; } break; } case TAP_IOCTL_GET_VERSION: { const ULONG size = sizeof (ULONG) * 3; if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength >= size) { ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[0] = TAP_DRIVER_MAJOR_VERSION; ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[1] = TAP_DRIVER_MINOR_VERSION; ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[2]#if DBG = 1;#else = 0;#endif p_IRP->IoStatus.Information = size; } else { NOTE_ERROR (); p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL; } break; } case TAP_IOCTL_GET_MTU: { const ULONG size = sizeof (ULONG) * 1; if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength >= size) { ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[0] = l_Adapter->m_MTU; p_IRP->IoStatus.Information = size; } else { NOTE_ERROR (); p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL; } break; } case TAP_IOCTL_GET_INFO: { char state[16]; if (l_Adapter->m_InterfaceIsRunning) state[0] = 'A'; else state[0] = 'a'; if (l_Adapter->m_Extension.m_TapIsRunning) state[1] = 'T'; else state[1] = 't'; state[2] = l_Adapter->m_DeviceState; if (l_Adapter->m_MediaStateAlwaysConnected) state[3] = 'C'; else state[3] = 'c'; state[4] = '\0'; p_IRP->IoStatus.Status = l_Status = RtlStringCchPrintfExA ( ((LPTSTR) (p_IRP->AssociatedIrp.SystemBuffer)), l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength, NULL, NULL, STRSAFE_FILL_BEHIND_NULL | STRSAFE_IGNORE_NULLS,#if PACKET_TRUNCATION_CHECK "State=%s Err=[%s/%d] #O=%d Tx=[%d,%d,%d] Rx=[%d,%d,%d] IrpQ=[%d,%d,%d] PktQ=[%d,%d,%d]",#else "State=%s Err=[%s/%d] #O=%d Tx=[%d,%d] Rx=[%d,%d] IrpQ=[%d,%d,%d] PktQ=[%d,%d,%d]",#endif state, g_LastErrorFilename, g_LastErrorLineNumber, (int)l_Adapter->m_Extension.m_NumTapOpens, (int)l_Adapter->m_Tx, (int)l_Adapter->m_TxErr,#if PACKET_TRUNCATION_CHECK (int)l_Adapter->m_TxTrunc,
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -