VOID otLwfEventProcessingIndicateNewNetBufferLists( _In_ PMS_FILTER pFilter, _In_ BOOLEAN DispatchLevel, _In_ PNET_BUFFER_LIST NetBufferLists ) { POTLWF_NBL_EVENT Event = FILTER_ALLOC_MEM(pFilter->FilterHandle, sizeof(OTLWF_NBL_EVENT)); if (Event == NULL) { LogWarning(DRIVER_DATA_PATH, "Failed to alloc new OTLWF_NBL_EVENT"); otLwfCompleteNBLs(pFilter, DispatchLevel, NetBufferLists, STATUS_INSUFFICIENT_RESOURCES); return; } Event->NetBufferLists = NetBufferLists; // Add the event to the queue FILTER_ACQUIRE_LOCK(&pFilter->EventsLock, DispatchLevel); InsertTailList(&pFilter->NBLsHead, &Event->Link); FILTER_RELEASE_LOCK(&pFilter->EventsLock, DispatchLevel); // Set the event to indicate we have a new NBL to process KeSetEvent(&pFilter->EventWorkerThreadProcessNBLs, 0, FALSE); }
_Use_decl_annotations_ VOID FilterCancelOidRequest( NDIS_HANDLE FilterModuleContext, PVOID RequestId ) /*++ Routine Description: Cancels an OID request If your filter driver does not intercept and hold onto any OID requests, then you do not need to implement this routine. You may simply omit it. Furthermore, if the filter only holds onto OID requests so it can pass down a clone (the most common case) the filter does not need to implement this routine; NDIS will then automatically request that the lower-level filter/miniport cancel your cloned OID. Most filters do not need to implement this routine. Arguments: FilterModuleContext - our filter RequestId - identifies the request(s) to cancel --*/ { PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext; PNDIS_OID_REQUEST Request = NULL; POTLWF_REQUEST_CONTEXT Context; PNDIS_OID_REQUEST OriginalRequest = NULL; BOOLEAN bFalse = FALSE; LogFuncEntryMsg(DRIVER_OID, "Filter: %p, RequestId: %p", FilterModuleContext, RequestId); FILTER_ACQUIRE_LOCK(&pFilter->PendingOidRequestLock, bFalse); Request = pFilter->PendingOidRequest; if (Request != NULL) { Context = (POTLWF_REQUEST_CONTEXT)(&Request->SourceReserved[0]); OriginalRequest = (*Context); } if ((OriginalRequest != NULL) && (OriginalRequest->RequestId == RequestId)) { FILTER_RELEASE_LOCK(&pFilter->PendingOidRequestLock, bFalse); NdisFCancelOidRequest(pFilter->FilterHandle, RequestId); } else { FILTER_RELEASE_LOCK(&pFilter->PendingOidRequestLock, bFalse); } LogFuncExit(DRIVER_OID); }
_Use_decl_annotations_ NTSTATUS FilterDeviceIoControl( PDEVICE_OBJECT DeviceObject, PIRP Irp ) { PIO_STACK_LOCATION IrpSp; NTSTATUS Status = STATUS_SUCCESS; PFILTER_DEVICE_EXTENSION FilterDeviceExtension; PUCHAR InputBuffer; PUCHAR OutputBuffer; ULONG InputBufferLength, OutputBufferLength; PLIST_ENTRY Link; PUCHAR pInfo; ULONG InfoLength = 0; PMS_FILTER pFilter = NULL; BOOLEAN bFalse = FALSE; UNREFERENCED_PARAMETER(DeviceObject); DbgPrint("------------------FilterDeviceIoControl!\n"); IrpSp = IoGetCurrentIrpStackLocation(Irp); if (IrpSp->FileObject == NULL) { return(STATUS_UNSUCCESSFUL); } FilterDeviceExtension = (PFILTER_DEVICE_EXTENSION)NdisGetDeviceReservedExtension(DeviceObject); ASSERT(FilterDeviceExtension->Signature == 'FTDR'); Irp->IoStatus.Information = 0; switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_FILTER_RESTART_ALL: break; case IOCTL_FILTER_RESTART_ONE_INSTANCE: InputBuffer = OutputBuffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer; InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; pFilter = filterFindFilterModule (InputBuffer, InputBufferLength); if (pFilter == NULL) { break; } NdisFRestartFilter(pFilter->FilterHandle); break; case IOCTL_FILTER_ENUERATE_ALL_INSTANCES: InputBuffer = OutputBuffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer; InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; pInfo = OutputBuffer; FILTER_ACQUIRE_LOCK(&FilterListLock, bFalse); Link = FilterModuleList.Flink; while (Link != &FilterModuleList) { pFilter = CONTAINING_RECORD(Link, MS_FILTER, FilterModuleLink); InfoLength += (pFilter->FilterModuleName.Length + sizeof(USHORT)); if (InfoLength <= OutputBufferLength) { *(PUSHORT)pInfo = pFilter->FilterModuleName.Length; NdisMoveMemory(pInfo + sizeof(USHORT), (PUCHAR)(pFilter->FilterModuleName.Buffer), pFilter->FilterModuleName.Length); pInfo += (pFilter->FilterModuleName.Length + sizeof(USHORT)); } Link = Link->Flink; } FILTER_RELEASE_LOCK(&FilterListLock, bFalse); if (InfoLength <= OutputBufferLength) { Status = NDIS_STATUS_SUCCESS; } // // Buffer is small // else { Status = STATUS_BUFFER_TOO_SMALL; } break; default: DbgPrint("WRONG request received!\n"); break; } Irp->IoStatus.Status = Status; Irp->IoStatus.Information = InfoLength; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; }
_Use_decl_annotations_ VOID FilterOidRequestComplete( NDIS_HANDLE FilterModuleContext, PNDIS_OID_REQUEST Request, NDIS_STATUS Status ) /*++ Routine Description: Notification that an OID request has been completed If this filter sends a request down to a lower layer, and the request is pended, the FilterOidRequestComplete routine is invoked when the request is complete. Most requests we've sent are simply clones of requests received from a higher layer; all we need to do is complete the original higher request. However, if this filter driver sends original requests down, it must not attempt to complete a pending request to the higher layer. Arguments: FilterModuleContext - our filter context area NdisRequest - the completed request Status - completion status --*/ { PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext; PNDIS_OID_REQUEST OriginalRequest; POTLWF_REQUEST_CONTEXT Context; BOOLEAN bFalse = FALSE; LogFuncEntryMsg(DRIVER_OID, "Filter: %p, Request %p", FilterModuleContext, Request); Context = (POTLWF_REQUEST_CONTEXT)(&Request->SourceReserved[0]); OriginalRequest = (*Context); // // This is an internal request // if (OriginalRequest == NULL) { otLwfInternalRequestComplete(pFilter, Request, Status); LogFuncExit(DRIVER_OID); return; } FILTER_ACQUIRE_LOCK(&pFilter->PendingOidRequestLock, bFalse); ASSERT(pFilter->PendingOidRequest == Request); pFilter->PendingOidRequest = NULL; FILTER_RELEASE_LOCK(&pFilter->PendingOidRequestLock, bFalse); // // Copy the information from the returned request to the original request // switch(Request->RequestType) { case NdisRequestMethod: OriginalRequest->DATA.METHOD_INFORMATION.OutputBufferLength = Request->DATA.METHOD_INFORMATION.OutputBufferLength; OriginalRequest->DATA.METHOD_INFORMATION.BytesRead = Request->DATA.METHOD_INFORMATION.BytesRead; OriginalRequest->DATA.METHOD_INFORMATION.BytesNeeded = Request->DATA.METHOD_INFORMATION.BytesNeeded; OriginalRequest->DATA.METHOD_INFORMATION.BytesWritten = Request->DATA.METHOD_INFORMATION.BytesWritten; break; case NdisRequestSetInformation: OriginalRequest->DATA.SET_INFORMATION.BytesRead = Request->DATA.SET_INFORMATION.BytesRead; OriginalRequest->DATA.SET_INFORMATION.BytesNeeded = Request->DATA.SET_INFORMATION.BytesNeeded; break; case NdisRequestQueryInformation: case NdisRequestQueryStatistics: default: OriginalRequest->DATA.QUERY_INFORMATION.BytesWritten = Request->DATA.QUERY_INFORMATION.BytesWritten; OriginalRequest->DATA.QUERY_INFORMATION.BytesNeeded = Request->DATA.QUERY_INFORMATION.BytesNeeded; break; } (*Context) = NULL; LogVerbose(DRIVER_OID, "Freeing (cloned) Oid Request %p", Request); NdisFreeCloneOidRequest(pFilter->FilterHandle, Request); LogVerbose(DRIVER_OID, "Completing (external) Oid Request %p", OriginalRequest); NdisFOidRequestComplete(pFilter->FilterHandle, OriginalRequest, Status); LogFuncExit(DRIVER_OID); }
VOID otLwfEventProcessingStop( _In_ PMS_FILTER pFilter ) { PLIST_ENTRY Link = NULL; LogFuncEntryMsg(DRIVER_DEFAULT, "Filter: %p", pFilter); // By this point, we have disabled the Data Path, so no more // NBLs should be queued up. // Clean up worker thread if (pFilter->EventWorkerThread) { LogInfo(DRIVER_DEFAULT, "Stopping event processing worker thread and waiting for it to complete."); // Send event to shutdown worker thread KeSetEvent(&pFilter->EventWorkerThreadStopEvent, 0, FALSE); // Wait for worker thread to finish KeWaitForSingleObject( pFilter->EventWorkerThread, Executive, KernelMode, FALSE, NULL ); // Free worker thread ObDereferenceObject(pFilter->EventWorkerThread); pFilter->EventWorkerThread = NULL; LogInfo(DRIVER_DEFAULT, "Event processing worker thread cleaned up."); } // Clean up any left over events if (pFilter->AddressChangesHead.Flink) { Link = pFilter->AddressChangesHead.Flink; while (Link != &pFilter->AddressChangesHead) { POTLWF_ADDR_EVENT Event = CONTAINING_RECORD(Link, OTLWF_ADDR_EVENT, Link); Link = Link->Flink; // Delete the event NdisFreeMemory(Event, 0, 0); } } // Clean up any left over events if (pFilter->NBLsHead.Flink) { Link = pFilter->NBLsHead.Flink; while (Link != &pFilter->NBLsHead) { POTLWF_NBL_EVENT Event = CONTAINING_RECORD(Link, OTLWF_NBL_EVENT, Link); Link = Link->Flink; otLwfCompleteNBLs(pFilter, FALSE, Event->NetBufferLists, STATUS_CANCELLED); // Delete the event NdisFreeMemory(Event, 0, 0); } } // Clean up any left over events if (pFilter->MacFramesHead.Flink) { Link = pFilter->MacFramesHead.Flink; while (Link != &pFilter->MacFramesHead) { POTLWF_MAC_FRAME_EVENT Event = CONTAINING_RECORD(Link, OTLWF_MAC_FRAME_EVENT, Link); Link = Link->Flink; // Delete the event NdisFreeMemory(Event, 0, 0); } } // Reinitialize the list head InitializeListHead(&pFilter->AddressChangesHead); InitializeListHead(&pFilter->NBLsHead); InitializeListHead(&pFilter->MacFramesHead); if (pFilter->EventIrpListHead.Flink) { FILTER_ACQUIRE_LOCK(&pFilter->EventsLock, FALSE); // Clean up any left over IRPs Link = pFilter->EventIrpListHead.Flink; while (Link != &pFilter->EventIrpListHead) { PIRP Irp = CONTAINING_RECORD(Link, IRP, Tail.Overlay.ListEntry); Link = Link->Flink; // Before we are allowed to complete the pending IRP, we must remove the cancel routine KIRQL irql; IoAcquireCancelSpinLock(&irql); IoSetCancelRoutine(Irp, NULL); IoReleaseCancelSpinLock(irql); Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); } // Reinitialize the list head InitializeListHead(&pFilter->EventIrpListHead); FILTER_RELEASE_LOCK(&pFilter->EventsLock, FALSE); } LogFuncExit(DRIVER_DEFAULT); }
_Use_decl_annotations_ NTSTATUS FilterDeviceIoControl( PDEVICE_OBJECT DeviceObject, PIRP Irp ) { PIO_STACK_LOCATION irp_sp; NTSTATUS status = STATUS_SUCCESS; PFILTER_DEVICE_EXTENSION filter_device_extension; PUCHAR input_buffer; PUCHAR output_buffer; ULONG input_buffer_length, output_buffer_length; PLIST_ENTRY link; PUCHAR info; ULONG InfoLength = 0; PLCXL_FILTER filter = NULL; BOOLEAN bFalse = FALSE; UNREFERENCED_PARAMETER(DeviceObject); irp_sp = IoGetCurrentIrpStackLocation(Irp); if (irp_sp->FileObject == NULL) { return(STATUS_UNSUCCESSFUL); } filter_device_extension = (PFILTER_DEVICE_EXTENSION)NdisGetDeviceReservedExtension(DeviceObject); ASSERT(filter_device_extension->Signature == 'FTDR'); Irp->IoStatus.Information = 0; input_buffer = output_buffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer; input_buffer_length = output_buffer_length = irp_sp->Parameters.DeviceIoControl.InputBufferLength; switch (irp_sp->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_FILTER_RESTART_ALL: break; case IOCTL_FILTER_RESTART_ONE_INSTANCE: filter = filterFindFilterModule (input_buffer, input_buffer_length); if (filter == NULL) { break; } NdisFRestartFilter(filter->filter_handle); break; case IOCTL_FILTER_ENUERATE_ALL_INSTANCES: info = output_buffer; LockLCXLLockList(&g_filter_list); link = GetListofLCXLLockList(&g_filter_list)->Flink; //遍历列表 while (link != GetListofLCXLLockList(&g_filter_list)) { filter = CONTAINING_RECORD(link, LCXL_FILTER, filter_module_link); InfoLength += (filter->module_setting->filter_module_name->Length + sizeof(USHORT)); if (InfoLength <= output_buffer_length) { *(PUSHORT)info = filter->module_setting->filter_module_name->Length; NdisMoveMemory(info + sizeof(USHORT), (PUCHAR)(filter->module_setting->filter_module_name->Buffer), filter->module_setting->filter_module_name->Length); info += (filter->module_setting->filter_module_name->Length + sizeof(USHORT)); } link = link->Flink; } UnlockLCXLLockList(&g_filter_list); if (InfoLength <= output_buffer_length) { status = NDIS_STATUS_SUCCESS; } // // Buffer is small // else { status = STATUS_BUFFER_TOO_SMALL; } break; //添加代码 case IOCTL_LOADER_ALL_APP_MODULE: { PAPP_MODULE_INFO cur_buf; PLCXL_MODULE_SETTING_LIST_ENTRY module; cur_buf = (PAPP_MODULE_INFO)output_buffer; LockLCXLLockList(&g_setting.module_list); module = CONTAINING_RECORD(GetListofLCXLLockList(&g_setting.module_list)->Flink, LCXL_MODULE_SETTING_LIST_ENTRY, list_entry); while (&module->list_entry != GetListofLCXLLockList(&g_setting.module_list)) { //先判断缓冲区是否足够 if (output_buffer_length - (ULONG)((LONG_PTR)cur_buf - (LONG_PTR)output_buffer) < sizeof(APP_MODULE_INFO)) { status = STATUS_BUFFER_TOO_SMALL; break; } cur_buf->app_module_status = module->ref_count == 0 ? AMS_NO_FILTER : AMS_NORMAL; FILTER_ACQUIRE_LOCK(&module->lock, bFalse); cur_buf->real_addr = module->real_addr; cur_buf->virtual_ipv4 = module->virtual_ipv4; cur_buf->virtual_ipv6 = module->virtual_ipv6; LockLCXLLockList(&module->server_list); cur_buf->server_count = GetListCountofLCXLLockList(&module->server_list); UnlockLCXLLockList(&module->server_list); FILTER_RELEASE_LOCK(&module->lock, bFalse); cur_buf->miniport_net_luid = module->miniport_net_luid; cur_buf->filter_module_name_len = (sizeof(cur_buf->filter_module_name) < module->filter_module_name->Length) ? sizeof(cur_buf->filter_module_name) : module->filter_module_name->Length; RtlCopyMemory(cur_buf->filter_module_name, module->filter_module_name->Buffer, cur_buf->filter_module_name_len); cur_buf->miniport_friendly_name_len = (sizeof(cur_buf->miniport_friendly_name) < module->miniport_friendly_name->Length) ? sizeof(cur_buf->miniport_friendly_name) : module->miniport_friendly_name->Length; RtlCopyMemory(cur_buf->miniport_friendly_name, module->miniport_friendly_name->Buffer, cur_buf->miniport_friendly_name_len); cur_buf->miniport_name_len = (sizeof(cur_buf->miniport_name) < module->miniport_name->Length) ? sizeof(cur_buf->miniport_name) : module->miniport_name->Length; RtlCopyMemory(cur_buf->miniport_name, module->miniport_name->Buffer, cur_buf->miniport_name_len); cur_buf++; module = CONTAINING_RECORD(module->list_entry.Flink, LCXL_MODULE_SETTING_LIST_ENTRY, list_entry); } UnlockLCXLLockList(&g_setting.module_list); InfoLength = (ULONG)((ULONG_PTR)cur_buf - (ULONG_PTR)output_buffer); } break; case IOCTL_LOADER_SET_VIRTUAL_IP: if (input_buffer_length == sizeof(APP_IP)) { PAPP_IP ip; PLCXL_FILTER pFilter; ip = (PAPP_IP)input_buffer; LockLCXLLockList(&g_filter_list); pFilter = FindFilter(ip->miniport_net_luid); if (pFilter != NULL) { NdisAcquireSpinLock(&pFilter->module_setting->lock); switch (ip->ip.ip_mode) { //IPv4模式 case IM_IPV4: pFilter->module_setting->virtual_ipv4 = ip->ip.addr.ip_4; break; //IPv6模式 case IM_IPV6: pFilter->module_setting->virtual_ipv6 = ip->ip.addr.ip_6; break; default: status = STATUS_INVALID_PARAMETER; break; } NdisReleaseSpinLock(&pFilter->module_setting->lock); } UnlockLCXLLockList(&g_filter_list); } else { status = STATUS_INFO_LENGTH_MISMATCH; } break; case IOCTL_LOADER_GET_SERVER_LIST: if (input_buffer_length == sizeof(NET_LUID)) { PLCXL_FILTER pFilter; LockLCXLLockList(&g_filter_list); pFilter = FindFilter(*(PNET_LUID)input_buffer); if (pFilter != NULL) { if (pFilter->module_setting != NULL && (pFilter->module_setting->flag & MSF_DELETE_AFTER_RESTART) == 0) { } else { status = STATUS_NOT_FOUND; } } else { status = STATUS_NOT_FOUND; } UnlockLCXLLockList(&g_filter_list); } else { status = STATUS_INFO_LENGTH_MISMATCH; } break; case IOCTL_LOADER_ADD_SERVER: if (sizeof(APP_ADD_SERVER) == input_buffer_length) { PAPP_ADD_SERVER app_add_server; PLCXL_FILTER pFilter; app_add_server = (PAPP_ADD_SERVER)input_buffer; LockLCXLLockList(&g_filter_list); pFilter = FindFilter(app_add_server->miniport_net_luid); if (pFilter != NULL) { LockLCXLLockList(&pFilter->module_setting->server_list); UnlockLCXLLockList(&pFilter->module_setting->server_list); } UnlockLCXLLockList(&g_filter_list); } else { status = STATUS_INFO_LENGTH_MISMATCH; } break; case IOCTL_LOADER_DEL_SERVER: if (sizeof(APP_DEL_SERVER) == input_buffer_length) { PAPP_DEL_SERVER app_del_server = (PAPP_DEL_SERVER)input_buffer; PLCXL_FILTER pFilter; LockLCXLLockList(&g_filter_list); pFilter = FindFilter(app_del_server->miniport_net_luid); UnlockLCXLLockList(&g_filter_list); } else { status = STATUS_INFO_LENGTH_MISMATCH; } break; //!添加代码! default: status = STATUS_INVALID_PARAMETER; break; } Irp->IoStatus.Status = status; Irp->IoStatus.Information = InfoLength; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; }
VOID FilterSendNetBufferLists( IN NDIS_HANDLE FilterModuleContext, IN PNET_BUFFER_LIST NetBufferLists, IN NDIS_PORT_NUMBER PortNumber, IN ULONG SendFlags ) /*++ Routine Description: Send Net Buffer List handler This function is an optional function for filter drivers. If provided, NDIS will call this function to transmit a linked list of NetBuffers, described by a NetBuferList, over the network. If this handler is NULL, NDIS will skip calling this fitler when sending a NetBufferList and will call the next lower fitler in the stack with a non_NULL FilterSendNetBufferList handleror the miniport driver. A filter that doesn't provide a FilerSendNetBufferList handler can not initiate a send o its own. Arguments: FilterModuleContext: Pointer to our filter context area. NetBufferLists: Pointer to a List of NetBufferLists. PortNumber - Port Number to which this send is targetted SendFlags- Specifies if the call is at DISPATCH_LEVEL Return Value: NDIS_STATUS_SUCCESS: NDIS_STATUS_PENDING: NDIS_STATUS_INVALID_PACKET: NDIS_STATUS_RESOURCES: NDIS_STATUS_FAILURE: NOTE: The filter will act like a passthru filter. --*/ { PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext; NDIS_STATUS Status = NDIS_STATUS_SUCCESS; PNET_BUFFER_LIST CurrNbl; BOOLEAN DispatchLevel; // ++ PNET_BUFFER_LIST CurrentBufferList = NULL; PNET_BUFFER CurrentBuffer = NULL; PNET_BUFFER_DATA CurrentBufferData = NULL; PMDL PacketMdl = NULL; ULONG DataOffset = 0; ULONG PacketSize = 0; PUCHAR PacketData = NULL; ARP_PACKET* ArpPacket = NULL; BOOLEAN bWanAdapter = FALSE; // -- DEBUGP(DL_TRACE, ("===>SendNetBufferList: NBL = %p.\n", NetBufferLists)); do { DispatchLevel = NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags); #if DBG // // we should never get packets to send if we are not in running state // FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel); // // If the filter is not in running state, fail the send // if (pFilter->State != FilterRunning) { FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel); CurrNbl = NetBufferLists; while (CurrNbl) { NET_BUFFER_LIST_STATUS(CurrNbl) = NDIS_STATUS_PAUSED; CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl); } NdisFSendNetBufferListsComplete(pFilter->FilterHandle, NetBufferLists, DispatchLevel ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0); break; } FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel); #endif // ++ CurrentBufferList = NetBufferLists; while(CurrentBufferList) { // Each NET_BUFFER structure packages a packet of network data CurrentBuffer = NET_BUFFER_LIST_FIRST_NB(CurrentBufferList); while(CurrentBuffer) { // 检测其中是否有ARP协议包 PacketMdl = NET_BUFFER_FIRST_MDL(CurrentBuffer); DataOffset = NET_BUFFER_DATA_OFFSET(CurrentBuffer); PacketSize = NET_BUFFER_DATA_LENGTH(CurrentBuffer); if(PacketMdl && PacketSize) { PacketData = (UCHAR*)MmGetSystemAddressForMdlSafe(PacketMdl,NormalPagePriority); if(PacketData) { if(DataOffset) { PacketData = PacketData + DataOffset; } // PacketData 是网络包数据,PacketSize 是网络包数据长度 KdPrint((" PacketData : %p , PacketSize : %d ",PacketData,PacketSize)); ArpPacket = (ARP_PACKET*)PacketData; // 记录网关回应查询次数 NdisAcquireSpinLock(&GlobalLock); if( ArpPacket->EthType == ETHERNET_ARP) { if( g_bRecord_ARP_Reply && ArpPacket->OperateCode == ARP_QUERY && NdisEqualMemory(ArpPacket->DestIPAddress,g_Want_ARP_Reply_IP,4) ) { g_Reply_Record->ulQueryCount ++; //开始记录网关查询操作 BeginCheckGateway(); } } NdisReleaseSpinLock(&GlobalLock); } } CurrentBuffer = NET_BUFFER_NEXT_NB(CurrentBuffer); } CurrentBufferList = NET_BUFFER_LIST_NEXT_NBL(CurrentBufferList); } // -- if (pFilter->TrackSends) { FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel); CurrNbl = NetBufferLists; while (CurrNbl) { pFilter->OutstandingSends++; FILTER_LOG_SEND_REF(1, pFilter, CurrNbl, pFilter->OutstandingSends); CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl); } FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel); } // // If necessary, queue the NetBufferList in a local structure for later processing // NdisFSendNetBufferLists(pFilter->FilterHandle, NetBufferLists, PortNumber, SendFlags); } while (FALSE); DEBUGP(DL_TRACE, ("<===SendNetBufferList: Status = %8x.\n", Status)); }
VOID FilterReceiveNetBufferLists( IN NDIS_HANDLE FilterModuleContext, IN PNET_BUFFER_LIST NetBufferLists, IN NDIS_PORT_NUMBER PortNumber, IN ULONG NumberOfNetBufferLists, IN ULONG ReceiveFlags ) /*++ Routine Description: FilerReceiveNetBufferLists is an optional function for filter drivers. If provided, this function process receive indications made by underlying NIC or lower level filter drivers. This function can also be called as a result of loopback. If this handler is NULL, NDIS will skip calling this filter when processing a receive indication and will call the next upper filter in the stack with a non-NULL FitlerReceiveNetBufferLists handler or the procotol driver. A filter that doesn't provide a FilterReceiveNetBufferLists handler can not provided a FilterReturnNetBufferLists handler or a initiate a receive indication on its own. Arguments: FilterModuleContext: Pointer to our filter context area. NetBufferLists: A linked list of NetBufferLists allocated by underlying driver each containing one NetBuffer. PortNumber: Port on which the Receive is indicated ReceiveFlags: Flags associated with the Receive such as whether the filter can pend the receive Return Value: None --*/ { PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext; NDIS_STATUS ReturnStatus = NDIS_STATUS_SUCCESS; PNET_BUFFER_LIST NextNetBufferList; BOOLEAN DispatchLevel; ULONG ReturnFlags; ULONG Ref; // ++ PNET_BUFFER_LIST CurrentBufferList = NULL; PNET_BUFFER CurrentBuffer = NULL; PNET_BUFFER_DATA CurrentBufferData = NULL; BOOLEAN HaveARPPacket = FALSE; PMDL PacketMdl = NULL; ULONG DataOffset = 0; ULONG PacketSize = 0; PUCHAR PacketData = NULL; ARP_PACKET* ArpPacket = NULL; GATEWAY_ITEM* Gateway = NULL; LAN_ITEM* LanItem = NULL; WAN_ITEM* WanItem = NULL; ULONG i = 0; BOOLEAN bSameRecord = FALSE; enum ATTACH_TYPE AttachType = ATTACH_NONE; enum RAS_OPT RetOpt = OPT_PASS; BOOLEAN bWanAdapter = FALSE; // -- DEBUGP(DL_TRACE, ("===>ReceiveNetBufferList: NetBufferLists = %p.\n", NetBufferLists)); do { DispatchLevel = NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(ReceiveFlags); #if DBG FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel); if (pFilter->State != FilterRunning) { FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel); if (NDIS_TEST_RECEIVE_CAN_PEND(ReceiveFlags)) { ReturnFlags = 0; if (NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(ReceiveFlags)) { NDIS_SET_RETURN_FLAG(ReturnFlags, NDIS_RETURN_FLAGS_DISPATCH_LEVEL); } NdisFReturnNetBufferLists(pFilter->FilterHandle, NetBufferLists, ReturnFlags); } break; } FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel); #endif ASSERT(NumberOfNetBufferLists >= 1); // ++ CurrentBufferList = NetBufferLists; while(CurrentBufferList) { // Each NET_BUFFER structure packages a packet of network data CurrentBuffer = NET_BUFFER_LIST_FIRST_NB(CurrentBufferList); while(CurrentBuffer) { // 检测其中是否有ARP协议包 PacketMdl = NET_BUFFER_FIRST_MDL(CurrentBuffer); DataOffset = NET_BUFFER_DATA_OFFSET(CurrentBuffer); PacketSize = NET_BUFFER_DATA_LENGTH(CurrentBuffer); if(PacketMdl && PacketSize) { PacketData = (UCHAR*)MmGetSystemAddressForMdlSafe(PacketMdl,NormalPagePriority); if(PacketData) { if(DataOffset) { PacketData = PacketData + DataOffset; } // PacketData 是网络包数据,PacketSize 是网络包数据长度 do { ArpPacket = (ARP_PACKET*)PacketData; if( ArpPacket->EthType != ETHERNET_ARP || PacketSize < sizeof(ARP_PACKET) ) { break; } else { KdPrint((" 收到ARP数据包")); } if( ArpPacket->OperateCode != 0x100 && ArpPacket->OperateCode != 0x200 && ArpPacket->OperateCode != 0x300 && ArpPacket->OperateCode != 0x400 ) { KdPrint((" 错误ARP/RARP协议攻击")); AttachType = WRONG_PROTOCOL_ATTACH; RetOpt = OPT_DROP; goto Exit; } //进行 IP - Mac 对应查询表的建立 NdisAcquireSpinLock(&GlobalLock); if(g_ArpFw_ShareMem) { // 查询广播包 if( ArpPacket->OperateCode == ARP_QUERY && NdisEqualMemory(ArpPacket->DestMacAddress,Empty_MacAddress,6) && !NdisEqualMemory(ArpPacket->SourceMacAddress,Empty_MacAddress,6) && g_ArpFw_ShareMem->ulItemCount < MAX_IP_MAC_ITEM_COUNT ) { bSameRecord = FALSE; for( i = 0 ; i< g_ArpFw_ShareMem->ulItemCount; i++) { if(NdisEqualMemory( g_ArpFw_ShareMem->Items[i].IPAddress,ArpPacket->SourceIPAddress,4)) { bSameRecord = TRUE; break; } } //当前没有该IP地址的记录 if(!bSameRecord) { memcpy(g_ArpFw_ShareMem->Items[g_ArpFw_ShareMem->ulItemCount].IPAddress, ArpPacket->SourceIPAddress,4); memcpy(g_ArpFw_ShareMem->Items[g_ArpFw_ShareMem->ulItemCount].MacAddress, ArpPacket->SourceMacAddress,6); g_ArpFw_ShareMem->ulItemCount ++; } } } NdisReleaseSpinLock(&GlobalLock); // ARP Reply 报文记录 if( ArpPacket->OperateCode == ARP_REPLY && g_bRecord_ARP_Reply && NdisEqualMemory(ArpPacket->SourceIPAddress,g_Want_ARP_Reply_IP,4) ) { bSameRecord = FALSE; NdisAcquireSpinLock(&GlobalLock); if(g_Reply_Record->ulItemCount < MAX_REPLY_RECORD) { do { if(g_Reply_Record->ulItemCount > 0) { for(i = 0 ; i < g_Reply_Record->ulItemCount; i ++) { if(NdisEqualMemory(ArpPacket->SourceMacAddress, g_Reply_Record->Items[i].MacAddress,6)) { g_Reply_Record->Items[i].RecordCount ++; bSameRecord = TRUE; break; } } } if(!bSameRecord) { NdisMoveMemory(g_Reply_Record->Items[g_Reply_Record->ulItemCount].IPAddress, ArpPacket->SourceIPAddress,4); NdisMoveMemory(g_Reply_Record->Items[g_Reply_Record->ulItemCount].MacAddress, ArpPacket->SourceMacAddress,6); g_Reply_Record->Items[g_Reply_Record->ulItemCount].WanAddress = bWanAdapter; g_Reply_Record->Items[g_Reply_Record->ulItemCount].Gateway = TRUE; g_Reply_Record->Items[g_Reply_Record->ulItemCount].Next = NULL; g_Reply_Record->Items[g_Reply_Record->ulItemCount].RecordCount = 1; g_Reply_Record->ulItemCount ++; } } while(FALSE); } NdisReleaseSpinLock(&GlobalLock); } //检测伪造ARP/RARP Query攻击中的源Mac地址是否为正确的网关地址 if( g_EnableGatewayCheck && (ArpPacket->OperateCode == ARP_QUERY || ArpPacket->OperateCode == RARP_QUERY ) ) { // 网关地址检测,Query操作中的源地址和源MAC地址必须是正确的 if(!bWanAdapter) // 局域网网关检测 { NdisAcquireSpinLock(&GlobalLock); Gateway = g_Gateway_List; while(Gateway) { if( NdisEqualMemory(ArpPacket->SourceIPAddress,Gateway->IPAddress,4) && !NdisEqualMemory(ArpPacket->SourceMacAddress,Gateway->MacAddress,6) ) { // IP地址相同,Mac地址不同 (禁止该包往上通行) KdPrint(("伪造网关Query攻击报文")); AttachType = GATEWAY_ARP_QUERY_ATTACH; RetOpt = OPT_DROP; NdisReleaseSpinLock(&GlobalLock); goto Exit; } Gateway = Gateway->Next; } NdisReleaseSpinLock(&GlobalLock); } } //伪造的ARP/RARP Reply报文检测 if( g_EnableGatewayCheck && (ArpPacket->OperateCode == ARP_REPLY || ArpPacket->OperateCode == RARP_REPLY) ) { if(!bWanAdapter) // 局域网网关检测 { NdisAcquireSpinLock(&GlobalLock); Gateway = g_Gateway_List; while(Gateway) { if( NdisEqualMemory(Gateway->IPAddress,ArpPacket->SourceIPAddress,4) && // 是网关IP !NdisEqualMemory(Gateway->MacAddress,ArpPacket->SourceMacAddress,6) ) // Mac 地址不相同,网关攻击 { KdPrint(("伪造网关Reply攻击报文")); //禁止该包往上通行 AttachType = GATEWAY_ARP_REPLY_ATTACH; RetOpt = OPT_DROP; NdisReleaseSpinLock(&GlobalLock); goto Exit; } else if(NdisEqualMemory(Gateway->IPAddress,ArpPacket->DestIPAddress,4) && !NdisEqualMemory(Gateway->MacAddress,ArpPacket->DestMacAddress,6) ) { KdPrint(("伪造网关Reply攻击报文")); //禁止该包往上通行 RetOpt = OPT_DROP; AttachType = GATEWAY_ARP_REPLY_ATTACH; NdisReleaseSpinLock(&GlobalLock); goto Exit; } Gateway = Gateway->Next; } NdisReleaseSpinLock(&GlobalLock); } } //进行 IP 冲突攻击检测 if( g_EnableSameIPCheck && NdisEqualMemory(ArpPacket->SourceIPAddress,ArpPacket->DestIPAddress,4) ) { NdisAcquireSpinLock(&GlobalLock); if(!bWanAdapter) // 局域网检测 { LanItem = g_Lan_List; while(LanItem) { // IP 地址相同 而 源Mac 地址不同 if( NdisEqualMemory(ArpPacket->SourceIPAddress,LanItem->IPAddress,4) && !NdisEqualMemory(ArpPacket->SourceMacAddress,LanItem->MacAddress,6) ) { KdPrint(("伪造内网间IP冲突攻击报文")); RetOpt = OPT_DROP; AttachType = LAN_SAMEIP_ATTACH; NdisReleaseSpinLock(&GlobalLock); goto Exit; } LanItem = LanItem->Next; } // 局域网对外网的相同IP攻击 WanItem = g_Wan_List; while(WanItem) { if(NdisEqualMemory(ArpPacket->SourceIPAddress,WanItem->IPAddress,4)) { KdPrint(("伪造内外网间IP冲突攻击报文")); RetOpt = OPT_DROP; AttachType = WAN_SAMEIP_ATTACH; NdisReleaseSpinLock(&GlobalLock); goto Exit; } WanItem = WanItem->Next; } } NdisReleaseSpinLock(&GlobalLock); } } while(FALSE); } } CurrentBuffer = NET_BUFFER_NEXT_NB(CurrentBuffer); } CurrentBufferList = NET_BUFFER_LIST_NEXT_NBL(CurrentBufferList); } // -- // // If necessary, queue the NetBufferList in a local structure for later processing. // We may need to travel the list, some of them may not need post processing // if (pFilter->TrackReceives) { FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel); pFilter->OutstandingRcvs += NumberOfNetBufferLists; Ref = pFilter->OutstandingRcvs; FILTER_LOG_RCV_REF(1, pFilter, NetBufferLists, Ref); FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel); } KdPrint((" NdisFIndicateReceiveNetBufferLists Run ")); NdisFIndicateReceiveNetBufferLists( pFilter->FilterHandle, NetBufferLists, PortNumber, NumberOfNetBufferLists, ReceiveFlags); if (NDIS_TEST_RECEIVE_CANNOT_PEND(ReceiveFlags) && pFilter->TrackReceives) { FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel); pFilter->OutstandingRcvs -= NumberOfNetBufferLists; Ref = pFilter->OutstandingRcvs; FILTER_LOG_RCV_REF(2, pFilter, NetBufferLists, Ref); FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel); } // ++ break; Exit: KdPrint((" Drop Received Packet ")); if(ArpPacket) { NdisAcquireSpinLock(&GlobalLock); if(g_ArpFw_ShareMem && AttachType != ATTACH_NONE) { g_ArpFw_ShareMem->NotifyPacket.AttachCount = 1; g_ArpFw_ShareMem->NotifyPacket.AttachType = AttachType; g_ArpFw_ShareMem->NotifyPacket.SendPacket = FALSE; g_ArpFw_ShareMem->NotifyPacket.WanPacket = FALSE; RtlCopyMemory((PVOID)&g_ArpFw_ShareMem->NotifyPacket.ArpPacket, ArpPacket,sizeof(ARP_PACKET)); SetUserShareEvent(&g_NotifyEvent); } NdisReleaseSpinLock(&GlobalLock); } // return this packet if (NDIS_TEST_RECEIVE_CAN_PEND(ReceiveFlags)) { ReturnFlags = 0; if (NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(ReceiveFlags)) { NDIS_SET_RETURN_FLAG(ReturnFlags, NDIS_RETURN_FLAGS_DISPATCH_LEVEL); } NdisFReturnNetBufferLists(pFilter->FilterHandle, NetBufferLists, ReturnFlags); } // -- } while (FALSE); DEBUGP(DL_TRACE, ("<===ReceiveNetBufferList: Flags = %8x.\n", ReceiveFlags)); }
_Use_decl_annotations_ NTSTATUS NDISFilterDriverDeviceIoControl( PDEVICE_OBJECT DeviceObject, PIRP Irp ) { DbgPrint("NDISFilterDriverDeviceIoControl\n"); PIO_STACK_LOCATION IrpSp; NTSTATUS Status = STATUS_SUCCESS; PFILTER_DEVICE_EXTENSION FilterDeviceExtension; PUCHAR InputBuffer; PUCHAR OutputBuffer; ULONG InputBufferLength, OutputBufferLength; PLIST_ENTRY Link; PUCHAR pInfo; ULONG InfoLength = 0; PMS_FILTER pFilter = NULL; BOOLEAN bFalse = FALSE; UNREFERENCED_PARAMETER(DeviceObject); KIRQL OldIrql; IrpSp = IoGetCurrentIrpStackLocation(Irp); if (IrpSp->FileObject == NULL) { return(STATUS_UNSUCCESSFUL); } FilterDeviceExtension = (PFILTER_DEVICE_EXTENSION)NdisGetDeviceReservedExtension(DeviceObject); ASSERT(FilterDeviceExtension->Signature == 'FTDR'); Irp->IoStatus.Information = 0; KeAcquireSpinLock(&FilterDeviceExtension->QLock, &OldIrql); switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_ADD_IPV4_RULE: DbgPrint("IOCTL_ADD_IPV4_RULE BEGIN\n"); InputBuffer = Irp->UserBuffer; InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (InputBufferLength != sizeof(RULE_IPV4)) { Status = NDIS_STATUS_FAILURE; break; } PRULE_IPV4 pRuleIPv4 = ExAllocatePool(NonPagedPool, sizeof(RULE_IPV4)); RtlCopyMemory(pRuleIPv4, InputBuffer, InputBufferLength); AddIPv4Rule(FilterDeviceExtension, pRuleIPv4); DbgPrint("IOCTL_ADD_IPV4_RULE END\n"); break; case IOCTL_DEL_IPV4_RULE: DbgPrint("IOCTL_DEL_IPV4_RULE BEGIN\n"); InputBuffer = Irp->UserBuffer; InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (InputBufferLength != sizeof(ULONG)) { Status = NDIS_STATUS_FAILURE; break; } ULONG IdIPv4 = *((PULONG)(InputBuffer)); DelIPv4Rule(FilterDeviceExtension, IdIPv4); DbgPrint("IOCTL_DEL_IPV4_RULE END\n"); break; case IOCTL_ADD_IPV6_RULE: DbgPrint("IOCTL_ADD_IPV6_RULE BEGIN\n"); InputBuffer = Irp->UserBuffer; InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (InputBufferLength != sizeof(RULE_IPV6)) { Status = NDIS_STATUS_FAILURE; break; } PRULE_IPV6 pRuleIPv6 = ExAllocatePool(NonPagedPool, sizeof(RULE_IPV6)); RtlCopyMemory(pRuleIPv6, InputBuffer, InputBufferLength); AddIPv6Rule(FilterDeviceExtension, pRuleIPv6); DbgPrint("IOCTL_ADD_IPV6_RULE END\n"); break; case IOCTL_DEL_IPV6_RULE: DbgPrint("IOCTL_DEL_IPV6_RULE BEGIN\n"); InputBuffer = Irp->UserBuffer; InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (InputBufferLength != sizeof(ULONG)) { Status = NDIS_STATUS_FAILURE; break; } ULONG IdIPv6 = *((PULONG)(InputBuffer)); DelIPv6Rule(FilterDeviceExtension, IdIPv6); DbgPrint("IOCTL_END_IPV6_RULE END\n"); break; case IOCTL_ACTIVATE_FILTER: DbgPrint("IOCTL_ACTIVATE_FILTER BEGIN\n"); InputBuffer = Irp->UserBuffer; InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (InputBufferLength != 0) { Status = NDIS_STATUS_FAILURE; break; } ActivateRules(FilterDeviceExtension); DbgPrint("IOCTL_ACTIVATE_FILTER END\n"); break; case IOCTL_DEACTIVATE_FILTER: DbgPrint("IOCTL_DEACTIVATE_FILTER BEGIN\n"); InputBuffer = Irp->UserBuffer; InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (InputBufferLength != 0) { Status = NDIS_STATUS_FAILURE; break; } DeactivateRules(FilterDeviceExtension); DbgPrint("IOCTL_DEACTIVATE_FILTER END\n"); break; case IOCTL_FILTER_RESTART_ALL: break; case IOCTL_FILTER_RESTART_ONE_INSTANCE: InputBuffer = OutputBuffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer; InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; pFilter = filterFindFilterModule (InputBuffer, InputBufferLength); if (pFilter == NULL) { break; } NdisFRestartFilter(pFilter->FilterHandle); break; case IOCTL_FILTER_ENUERATE_ALL_INSTANCES: InputBuffer = OutputBuffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer; InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; pInfo = OutputBuffer; FILTER_ACQUIRE_LOCK(&FilterListLock, bFalse); Link = FilterModuleList.Flink; while (Link != &FilterModuleList) { pFilter = CONTAINING_RECORD(Link, MS_FILTER, FilterModuleLink); InfoLength += (pFilter->FilterModuleName.Length + sizeof(USHORT)); if (InfoLength <= OutputBufferLength) { *(PUSHORT)pInfo = pFilter->FilterModuleName.Length; NdisMoveMemory(pInfo + sizeof(USHORT), (PUCHAR)(pFilter->FilterModuleName.Buffer), pFilter->FilterModuleName.Length); pInfo += (pFilter->FilterModuleName.Length + sizeof(USHORT)); } Link = Link->Flink; } FILTER_RELEASE_LOCK(&FilterListLock, bFalse); if (InfoLength <= OutputBufferLength) { Status = NDIS_STATUS_SUCCESS; } // // Buffer is small // else { Status = STATUS_BUFFER_TOO_SMALL; } break; default: break; } KeReleaseSpinLock(&FilterDeviceExtension->QLock, OldIrql); Irp->IoStatus.Status = Status; Irp->IoStatus.Information = InfoLength; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; }