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 SxLibSendNetBufferListsIngress( _In_ PSX_SWITCH_OBJECT Switch, _In_ PNET_BUFFER_LIST NetBufferLists, _In_ ULONG SendFlags, _In_ ULONG NumInjectedNetBufferLists ) { BOOLEAN dispatch; BOOLEAN sameSource; ULONG sendCompleteFlags; PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO fwdDetail; PNET_BUFFER_LIST curNbl, nextNbl; ULONG numNbls = 0; PNET_BUFFER_LIST dropNbl = NULL; PNET_BUFFER_LIST *curDropNbl = &dropNbl; NDIS_SWITCH_PORT_ID curSourcePort; NDIS_STRING filterReason; dispatch = NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags); sameSource = NDIS_TEST_SEND_FLAG(SendFlags, NDIS_SEND_FLAGS_SWITCH_SINGLE_SOURCE); InterlockedAdd(&Switch->PendingInjectedNblCount, NumInjectedNetBufferLists); KeMemoryBarrier(); if (Switch->DataFlowState != SxSwitchRunning) { RtlInitUnicodeString(&filterReason, L"Extension Paused"); sendCompleteFlags = (dispatch) ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0; sendCompleteFlags |= (sameSource) ? NDIS_SEND_COMPLETE_FLAGS_SWITCH_SINGLE_SOURCE : 0; fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(NetBufferLists); if (sameSource) { for (curNbl = NetBufferLists; curNbl != NULL; curNbl = curNbl->Next) { ++numNbls; } Switch->NdisSwitchHandlers.ReportFilteredNetBufferLists( Switch->NdisSwitchContext, &SxExtensionGuid, &SxExtensionFriendlyName, fwdDetail->SourcePortId, NDIS_SWITCH_REPORT_FILTERED_NBL_FLAGS_IS_INCOMING, numNbls, NetBufferLists, &filterReason); SxExtStartCompleteNetBufferListsIngress(Switch, Switch->ExtensionContext, NetBufferLists, sendCompleteFlags); } else { curSourcePort = fwdDetail->SourcePortId; for (curNbl = NetBufferLists; curNbl != NULL; curNbl = nextNbl) { nextNbl = curNbl->Next; curNbl->Next = NULL; fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(curNbl); if(curSourcePort == fwdDetail->SourcePortId) { *curDropNbl = curNbl; curDropNbl = &(curNbl->Next); ++numNbls; } else { Switch->NdisSwitchHandlers.ReportFilteredNetBufferLists( Switch->NdisSwitchContext, &SxExtensionGuid, &SxExtensionFriendlyName, curSourcePort, NDIS_SWITCH_REPORT_FILTERED_NBL_FLAGS_IS_INCOMING, numNbls, dropNbl, &filterReason); SxExtStartCompleteNetBufferListsIngress(Switch, Switch->ExtensionContext, dropNbl, sendCompleteFlags); numNbls = 1; dropNbl = curNbl; curDropNbl = &(curNbl->Next); curSourcePort = fwdDetail->SourcePortId; } } Switch->NdisSwitchHandlers.ReportFilteredNetBufferLists( Switch->NdisSwitchContext, &SxExtensionGuid, &SxExtensionFriendlyName, curSourcePort, NDIS_SWITCH_REPORT_FILTERED_NBL_FLAGS_IS_INCOMING, numNbls, dropNbl, &filterReason); SxExtStartCompleteNetBufferListsIngress(Switch, Switch->ExtensionContext, dropNbl, sendCompleteFlags); } goto Cleanup; } NdisFSendNetBufferLists(Switch->NdisFilterHandle, NetBufferLists, NDIS_DEFAULT_PORT_NUMBER, SendFlags); Cleanup: return; }