转MDL中数据读取

别来无恙 提交于 2020-08-13 06:35:54

http://yexin218.iteye.com/blog/532184
 

  1. 澄清一个误区:每个Net_BuFFER包含的是一个linked-list的MDL,而不仅仅是一个MDL。所以你要访问Net_BuFFER 中数据,你需要在代码中根据需要的offset遍历MDL链表。比如第一个MDL只有14byte有数据(忽略unused data,backfill..),那么它就包含了EtherNet Header,那么下一个可能包含IP Header,再下一个包含TCP header,最后一个(或者多个)包含了TCP数据。至于那些数据是否真的可以完整放在某个MDL中,比如Ethernet Header是否就放在第一个中,而不会跨越第二个MDL,那就取决于NIC容量~
  2. 如果你得到一个MDL,那么你可以遍历的道,Ethernet header->Layer 3 header-->Layer 4 header(if available),假如Net_BuFFER->next(应该是pMDL->next吧) 不是NULL,那么要检查下是什么样的Layer3协议。比如它可能是ARP.
  3. 现在讨论下如何访问会更加简单些,了解下基础知识。

     
  • 假设一个MDL,它描述了事实上是一个连续的内存区域。其包含了一连串的page frame。到第一个page的‘距离’可用MmGetMdlByteOffset()得到。大多数情况你会忽略了这个长度以及 MmGetSystemAddressFroMdlSafe()返回的第一Byte的连续内存空间的虚拟地址。内存空间的长度可以由 MmGetMdlByteCount()返回。 也可以参考NdisQueryMdl ().
  • 如果是一串的MDL结构, 那么这个串的MDL描述的是逻辑上一块连续内存空间,而在物理上是不连续的,它有很多个内存片组成,每个内存片这里用MDL来描述。这也就是说每个MDL 都有一个虚拟地址和长度。那么逻辑缓存的总长度就是所有MDL长度的总和。所以对于存放在缓冲区的数据来说,可能恰好存放在某个MDL中,而又可能延伸到 其他MDL中,简单说就是存放在多个MDL中。所以可能需要多次读写操作才能处理。
  • 对于NDIS6来说Buffer还支持advance和reteat操作。所以这个看起来连续的、事实上不连续的Buffer,在器某个地方存放着数据。NET_BUFFER 可能还需要额外的空间来容纳更多的数据,所以需要有一种方法来辨别‘head’和'tail',用来秒速这块内存空间的起始和结束。结束比较简单:因为 NET_BUFFER包含了一个长度(dataLength??)。一般缓冲区的长度都是大于这个长度。大于这个长度的而在缓冲区结束前的数据都不是属于 这个packet的。至于开始的地方,一个简单的方法就是逻辑缓冲区起始地址+偏移量 offset<=NET_BUFFER_DATA_OFFSET()。而假如你是使用NET_BUFFER_FIRST_MDL()来找到你的起始 逻辑空间,那么你就要NET_BUFFER_DATA_OFFSET()bytes才能到data的起始处。 有一种比较有效的方式(尤其是当你有很长的一串MDL)就是使用 NET_BUFFER_CURRENT_MDL()得到你正在使用的data所在的第一个MDL,然后跳过这个MDL的dataoffset--- NET_BUFFER_CURRENT_MDL_OFFSET(). 这是一种较快的方式就可以访问得到真正有数据的第一个MDL。 所以要得到Ethernet header:
    Cpp代码   收藏代码
    1. ethHeader = (PEthHeader) (PUCHAR)MmGetSystemAddressForMdlSafe(NET_BUFFER_CURRENT_MDL()) + NET_BUFFER_CURRENT_MDL_OFFSET()   
     那么如果你Advance(释放used data space)Ethernet_header_size的空间,那么你很容易得到你IP_Header:
    Cpp代码   收藏代码
    1. iPHeader = (IPHeader)(PUCHAR)MmGetSystemAddressForMdlSafe(NET_BUFFER_CURRENT_MDL()) + NET_BUFFER_CURRENT_MDL_OFFSET()   
    注意的是,Advance,Retreat操作改变了NET_BUFFER_CURRENT_MDL()的返回值甚至需要的时候改变NET_BUFFER_CURRENT_MDL_OFFSET()的返回值。如图~
  • 以上从http://www.osronline.com/ShowThread.cfm?link=168715  摘取出来!

----------------------------------------------------------------------------------------------------------------------------------

An NBL contains a list of NET_BUFFERs (NB); each NB describes an IP packet.

 

On recv path, one NBL only contains one NB. So nbl->FirstNetBuffer is the packet.

 

Each NB contains a chain of MDLs with the CurrentMdl referring to the MDL where the beginning of the packet resides. So nb->CurrentMdl contains the IP header.

 

The MappedSystemVa field inside the MDL points to the system virtual memory. Advance this pointer by the amount of nb->DataOffset you will be looking at the beginning of the IP header.

 

Yes the NBL referred to the clone on which you had invoked FwpsConstructXxx api function.

 

Here would be an example you can try with the code you posted --

Cpp代码   收藏代码
  1. NET_BUFFER* netBuffer =  
  2.   
  3.    NET_BUFFER_LIST_FIRST_NB(clonedNetBufferList);  
  4.   
  5. ULONG netBufferOffset = netBuffer->DataOffset;  
  6.   
  7. MDL* currentMdl = netBuffer->CurrentMdl;  
  8.   
  9.    
  10.   
  11. UCHAR* packet = currentMdl->MappedSystemVa + netBufferOffset;  
  12.   
  13. // beginning of the IP header  

 

netBuffer->DataLength is the length of your packet (starting from the "packet" variable).

 

It is possible that one packet consists of multiple MDLs, in which case CurrentMdl->Next is not NULL. If that's the case the ByteCount field of the MDL will be smaller than netBuffer->DataLength and you will need to traverse to the next MDL for more data.

-->http://social.msdn.microsoft.com/forums/en-US/wfp/thread/3ccb32da-c240-477b-bd28-ea584784bd48/

 

附上:MDL struct:

Cpp代码   收藏代码
  1. typedef struct _MDL  
  2. {  
  3.      PMDL Next;  
  4.      SHORT Size;  
  5.      SHORT MdlFlags;  
  6.      PEPROCESS Process;  
  7.      PVOID MappedSystemVa;  
  8.      PVOID StartVa;  
  9.      ULONG ByteCount;  
  10.      ULONG ByteOffset;  
  11. } MDL, *PMDL; 
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!