NDISLWF how to block stream

下面的代码中部分是伪代码,但关键的流程整理出来了,过滤databuffer,将允许通过的NBL和不允许通过的NBL分别加入 NBL_QUEUE_HEADER NblSendQueue;或NBL_QUEUE_HEADER NblDropQueue;链表中。然后将两个NBLs分别进行处理即可。

// Send Passthrough NetBufferLists

if( GET_NBL_QUEUE_HEAD( &NblSendQueue ) )

{
    NdisFSendNetBufferLists(
        pFilter->FilterHandle,
        GET_NBL_QUEUE_HEAD( &NblSendQueue ),
        PortNumber,
        SendFlags);
}
// Complete Blocked NetBufferLists
if( GET_NBL_QUEUE_HEAD( &NblDropQueue ) )
{
    NdisFSendNetBufferListsComplete(
        pFilter->FilterHandle,
        (PNET_BUFFER_LIST)GET_NBL_QUEUE_HEAD( &NblDropQueue ),
        DispatchLevel?NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL:0);

具体点的代码如下:

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;
	BOOLEAN             DispatchLevel;
	BOOLEAN             bFalse = FALSE;
	PNET_BUFFER_LIST    CurrNbl, NextNbl;
	PNET_BUFFER         pCurrentNetBuffer;

	UCHAR				pPakData[MAXSCANLENGTH];
	ULONG				scanlength;

	USHORT				StreamFlag = 0;
	NBL_QUEUE_HEADER NblSendQueue; 
	NBL_QUEUE_HEADER NblDropQueue; 


	INIT_NBL_QUEUE_HEADER( &NblSendQueue );
	INIT_NBL_QUEUE_HEADER( &NblDropQueue );
	NdisZeroMemory(pPakData, sizeof(pPakData));

	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)
		{
			DEBUGP(4, ("NOT SURE WHETHER IN THIS PATH.\n"));
			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
		if (pFilter->TrackSends)
		{
			CurrNbl = NetBufferLists;
			while (CurrNbl)
			{
				pFilter->OutstandingSends++;

				NextNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
				NET_BUFFER_LIST_NEXT_NBL(CurrNbl) = NULL;
				DEBUGP(4, ("===>BufferList: NBL = %p, begin the NB process.\n", NetBufferLists));
				for(pCurrentNetBuffer =  NET_BUFFER_LIST_FIRST_NB(CurrNbl);
					pCurrentNetBuffer != NULL;
					pCurrentNetBuffer =  NET_BUFFER_NEXT_NB(pCurrentNetBuffer)) 
				{
					if( NULL==NdisGetDataBuffer(pCurrentNetBuffer,scanlength,pPakData,1,0)){
						goto MoveToNextNbl;		
					} 
					...
					//TODO:filter the databuffer
					IF FOUND THE PACKET NEED TO DROP
					GO MoveToNextNbl;
					...
					DbgPrint("End one NB process!\n");
				}
MoveToNextNbl:
				//
				if( StreamFlag & STREAM_POLICY_DENY)
				{
					INSERT_TAIL_NBL_QUEUE( &NblDropQueue, CurrNbl );
				}else{
					INSERT_TAIL_NBL_QUEUE( &NblSendQueue, CurrNbl );
				}
				CurrNbl= NextNbl;
			}
		}
		// Send Passthrough NetBufferLists
		if( GET_NBL_QUEUE_HEAD( &NblSendQueue ) )
		{
    		NdisFSendNetBufferLists(
        	pFilter->FilterHandle,
        	GET_NBL_QUEUE_HEAD( &NblSendQueue ),
        							PortNumber,
        							SendFlags);
		}
		// Complete Blocked NetBufferLists
		if( GET_NBL_QUEUE_HEAD( &NblDropQueue ) )
		{
    		NdisFSendNetBufferListsComplete(
        	pFilter->FilterHandle,
        	(PNET_BUFFER_LIST)GET_NBL_QUEUE_HEAD( &NblDropQueue ),
        	DispatchLevel?NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL:0);
		}
	}
	while (bFalse);
	DEBUGP(4, ("<===SendNetBufferList. \n"));
}


注意:这个示例不是修改net buffer,也不是drop掉某一个net buffer。它针对stream进行操作,因为一个的NBL中保存的是相同的“srcIP、dstIP、srcPort、dstPort”,它们属于一个stream,如果一个NBL中有多个NETBUFFER,这些NETBUFFER都会被drop掉。

关于NBL_QUEUE_HEADER NblSendQueue;等相关的操作请参考:

http://ndis.com/ndis-ndis6/packetsort/packetsort.htm

Thanks, Thomas.

你可能感兴趣的:(NDISLWF how to block stream)