📄 tapdrvr.c
字号:
//===================================================== // 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, 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_PointToPoint) { 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_remoteIP, 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_POINT_TO_POINT; } } //=============================================== // 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, "State=%s Err=[%s/%d] #O=%d Tx=[%d,%d] Rx=[%d,%d] IrpQ=[%d,%d,%d] PktQ=[%d,%d,%d]", state, g_LastErrorFilename, g_LastErrorLineNumber, (int)l_Adapter->m_Extension.m_NumTapOpens, (int)l_Adapter->m_Tx, (int)l_Adapter->m_TxErr, (int)l_Adapter->m_Rx, (int)l_Adapter->m_RxErr, (int)l_Adapter->m_Extension.m_IrpQueue->size, (int)l_Adapter->m_Extension.m_IrpQueue->max_size, (int)IRP_QUEUE_SIZE, (int)l_Adapter->m_Extension.m_PacketQueue->size, (int)l_Adapter->m_Extension.m_PacketQueue->max_size, (int)PACKET_QUEUE_SIZE ); p_IRP->IoStatus.Information = l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength; break; }#if DBG case TAP_IOCTL_GET_LOG_LINE: { if (GetDebugLine ((LPTSTR)p_IRP->AssociatedIrp.SystemBuffer, l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength)) p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS; else p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; p_IRP->IoStatus.Information = l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength; break; }#endif case TAP_IOCTL_CONFIG_POINT_TO_POINT: { if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength >= (sizeof (IPADDR) * 2)) { MACADDR dest; l_Adapter->m_PointToPoint = FALSE; GenerateRelatedMAC (dest, l_Adapter->m_MAC, 1); l_Adapter->m_localIP = ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[0]; l_Adapter->m_remoteIP = ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[1]; COPY_MAC (l_Adapter->m_TapToUser.src, l_Adapter->m_MAC); COPY_MAC (l_Adapter->m_TapToUser.dest, dest); COPY_MAC (l_Adapter->m_UserToTap.src, dest); COPY_MAC (l_Adapter->m_UserToTap.dest, l_Adapter->m_MAC); l_Adapter->m_TapToUser.proto = l_Adapter->m_UserToTap.proto = htons (ETH_P_IP); l_Adapter->m_PointToPoint = TRUE; CheckIfDhcpAndPointToPointMode (l_Adapter); p_IRP->IoStatus.Information = 1; // Simple boolean value } else { NOTE_ERROR (); p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER; } break; } case TAP_IOCTL_SET_MEDIA_STATUS: { if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength >= (sizeof (ULONG) * 1)) { ULONG parm = ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[0]; SetMediaStatus (l_Adapter, (BOOLEAN) parm); p_IRP->IoStatus.Information = 1; } else { NOTE_ERROR (); p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER; } break; } case TAP_IOCTL_CONFIG_DHCP_MASQ: { if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength >= (sizeof (IPADDR) * 4)) { l_Adapter->m_dhcp_enabled = FALSE; l_Adapter->m_dhcp_server_arp = FALSE; l_Adapter->m_dhcp_user_supplied_options_buffer_len = 0; // Adapter IP addr / netmask l_Adapter->m_dhcp_addr = ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[0]; l_Adapter->m_dhcp_netmask = ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[1]; // IP addr of DHCP masq server l_Adapter->m_dhcp_server_ip = ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[2]; // Lease time in seconds l_Adapter->m_dhcp_lease_time = ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[3]; GenerateRelatedMAC (l_Adapter->m_dhcp_server_mac, l_Adapter->m_MAC, 2); l_Adapter->m_dhcp_enabled = TRUE; l_Adapter->m_dhcp_server_arp = TRUE; CheckIfDhcpAndPointToPointMode (l_Adapter); p_IRP->IoStatus.Information = 1; // Simple boolean value } else { NOTE_ERROR (); p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER; } break; } case TAP_IOCTL_CONFIG_DHCP_SET_OPT: { if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength <= DHCP_USER_SUPPLIED_OPTIONS_BUFFER_SIZE && l_Adapter->m_dhcp_enabled) { l_Adapter->m_dhcp_user_supplied_options_buffer_len = 0; NdisMoveMemory (l_Adapter->m_dhcp_user_supplied_options_buffer,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -