ndis6.0 NetBufferSend

来源:互联网 发布:美工常去的网站 编辑:程序博客网 时间:2024/05/17 15:35

FilterSendNetBufferListsComplete:

NDIS calls the FilterSendNetBufferListsComplete function to complete a send request that a filter driver started by calling the NdisFSendNetBufferLists function.

FilterSendNetBufferLists:

NDIS calls the FilterSendNetBufferLists function to allow a filter driver to filter a linked list of NET_BUFFER_LISTstructures.

 

调用关系如下:

ndis6.0中NET_BUFFER_LIST和NET_BUFFER是两个很重要的数据结构。
如何在FilterSendNetBufferLists函数中读取数据包的内容呢,步骤如下:
1.pCurrentNetBuffer = NET_BUFFER_LIST_FIRST_NB(CurrNbl)
2.pMdl = NET_BUFFER_CURRENT_MDL(pCurrentNetBuffer)
3.NdisQueryMdl(
        pMdl,
        &pEthHeader,
        &ulBufferLength,
        NormalPagePriority);可以获得Mdl的地址指针保存在pEthHeader中,同时返回MDL内存块的大小ulBufferLength。
4.pEthHeader = (struct ether_header *)((PUCHAR)pEthHeader + NET_BUFFER_CURRENT_MDL_OFFSET(pCurrentNetBuffer)),这样pEthHeader 即指向我们熟悉的数据帧了(包含以太头+TCP/IP层头部)。
 
在获取数据包的过程中需要注意的是:
1).一个NET_BUFFER_LIST结构指向的是一连串的NET_BUFFER,这些NET_BUFFER中保存的数据包内容属于同一个stream(the same src-ip,dst-ip,src-port,dst-port and protocol)。通过NET_BUFFER_NEXT_NB(pCurrentNetBuffer)可以获取下一个NET_BUFFER。
2).在NET_BUFFER中包含NET_BUFFER_DATA结构
typedef struct _NET_BUFFER_DATA {
  PNET_BUFFER  Next;
  PMDL  MdlChain;
  ULONG  DataLength;
  ULONG  DataOffset;
  PMDL  CurrentMdl;
  ULONG  CurrentMdlOffset;
} NET_BUFFER_DATA, *PNET_BUFFER_DATA;
数据包的内容保存在MDL中,在上面的步骤2和3中,可通过NET_BUFFER信息获取到保存数据包内容的地址。因为MDL指示的那一块内存会有一个MDL头部信息(我并不确定),所以需要用pEthHeader + NET_BUFFER_CURRENT_MDL_OFFSET(pCurrentNetBuffer),这时才指向真正意义上的数据包内容。
3).一个NET_BUFFER因为MDL指向的内存大小有限制(我的观察是100个字节左右),所以一个NET_BUFFER会含有多个MDL(如一个1000字节的数据包,可能就会分为10个MDL进行保存),用MdlChain表示(即一个Mdl链表)。
4).通常情况下,NET_BUFFER中MdlChain与NET_BUFFER_CURRENT_MDL(pCurrentNetBuffer)获取到的CurrentMdl相同,同样的NET_BUFFER_CURRENT_MDL_OFFSET(pCurrentNetBuffer)与NET_BUFFER中DataOffset相同。
5).NET_BUFFER中DataLength代表数据包的总长度。在上面的步骤3中,获取到的ulBufferLength - NET_BUFFER_CURRENT_MDL(pCurrentNetBuffer),若所得值小于DataLength,则说明NET_BUFFER中含有多个MDL,若想获取完整包的信息则通过pMdl.next获取下一个MDL指针,在进行相关操作。
 
下面是我改写filter中FilterSendNetBufferLists函数的代码
 
VOIDFilterSendNetBufferLists(        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;PMDLpMdl;ULONGulOffset;struct ether_header *pEthHeader = NULL;ULONGulBufferLength = 0;ULONGNBDO;ULONG NBDL;//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);#endifif (pFilter->TrackSends){FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel);CurrNbl = NetBufferLists;while (CurrNbl){pFilter->OutstandingSends++;FILTER_LOG_SEND_REF(1, pFilter, CurrNbl, pFilter->OutstandingSends);NextNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);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)) {pMdl = NET_BUFFER_CURRENT_MDL(pCurrentNetBuffer);ulOffset = NET_BUFFER_CURRENT_MDL_OFFSET(pCurrentNetBuffer);NBDL = NET_BUFFER_DATA_LENGTH(pCurrentNetBuffer);NBDO = NET_BUFFER_DATA_OFFSET(pCurrentNetBuffer);do {ASSERT(pMdl != NULL);if (pMdl){NdisQueryMdl(pMdl,&pEthHeader,&ulBufferLength,NormalPagePriority);}if (NULL == pEthHeader){////  The system is low on resources. Set up to handle failure//  below.//ulBufferLength = 0;break;}if (0 == ulBufferLength){break;}ASSERT(ulBufferLength > ulOffset);//if the ulBufferLength < NBDL, then there are some more MDLs.DbgPrint("NBDL IS %d, NBD0 IS %d, MDL_OFFSET IS %d, MDL NET BUFFER LENGTH IS %d\n", NBDL, NBDO, ulOffset, ulBufferLength);ulBufferLength -= ulOffset;pEthHeader = (struct ether_header *)((PUCHAR)pEthHeader + ulOffset);if (ulBufferLength < sizeof(struct ether_header)){DEBUGP(DL_WARN,("ReceiveNetBufferList: runt nbl %p, first buffer length %d\n",CurrNbl, ulBufferLength));break;}DbgPrint("DstMAC: %.2x-%.2x-%.2x-%.2x-%.2x-%.2x\n",pEthHeader->ether_dhost[0],pEthHeader->ether_dhost[1],pEthHeader->ether_dhost[2],pEthHeader->ether_dhost[3],pEthHeader->ether_dhost[4],pEthHeader->ether_dhost[5]);DbgPrint("srcMAC: %.2x-%.2x-%.2x-%.2x-%.2x-%.2x\n",pEthHeader->ether_shost[0],pEthHeader->ether_shost[1],pEthHeader->ether_shost[2],pEthHeader->ether_shost[3],pEthHeader->ether_shost[4],pEthHeader->ether_shost[5]);}while (bFalse);DbgPrint("End one NB process!\n");}//DbgPrint("IF NOT SHOW THIE, MAYBE SOME PROBLEM.\n");CurrNbl= NextNbl;}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 (bFalse);DEBUGP(4, ("<===SendNetBufferList. \n"));}
其中用到了一个新的数据类型,可以添加到filter.h头文件中:
#defineETHER_ADDR_LEN6/* length of an Ethernet address */structether_header {UCHARether_dhost[ETHER_ADDR_LEN];UCHARether_shost[ETHER_ADDR_LEN];USHORTether_type;};
0 0
原创粉丝点击