如何把ndis filter框架利用到日膚indows驱动开发工作中 NDIS中间层驱动开发在Win7系统下和Windows XP...

\u5982\u4f55\u628aNDIS Filter\u6846\u67b6\u5229\u7528\u5230\u65e5\u8164indows\u9a71\u52a8\u5f00\u53d1\u5de5\u4f5c\u4e2d

NDIS Filter NET_BUFFER_LIST NET_BUFFER MDL 1 \u7f51\u7edc\u6570\u636e\u7ed3\u6784\u5982\u4e0b\u56fe: 2 \u4f60\u53ef\u4ee5\u6309\u7167\u6211\u7684\u4e0b\u8ff02\u79cd\u7a0b\u5e8f\u4ee3\u7801\u7684\u5b9e\u73b0\u65b9\u6cd5\uff0c\u6765\u83b7\u53d6\u6570\u636e\u5305\u7684\u5185\u5bb9\u3002\u4f60\u53ef\u4ee5\u628a\u4ee3\u7801\u76f4\u63a5\u6dfb\u52a0\u5230\u4f60\u7684NDIS Filter\u5de5\u7a0b\u4ee3\u7801\u91cc\u9762\u3002 3 \u4ee3\u7801\u7f16\u8bd1\u73af\u5883\uff1aVisual Studio 2013WDK8.1\u6d4b\u8bd5\u901a...

\u60a8\u597d\uff0c\u5f88\u9ad8\u5174\u4e3a\u60a8\u89e3\u7b54\u3002

\u8fd9\u4e2a\u5f88\u8be6\u7ec6\u4e86\uff1ahttp://bbs.pediy.com/showthread.php?t=137545

\u5982\u82e5\u6ee1\u610f\uff0c\u8bf7\u70b9\u51fb\u53f3\u4fa7\u3010\u91c7\u7eb3\u7b54\u6848\u3011\uff0c\u5982\u82e5\u8fd8\u6709\u95ee\u9898\uff0c\u8bf7\u70b9\u51fb\u3010\u8ffd\u95ee\u3011

\u5e0c\u671b\u6211\u7684\u56de\u7b54\u5bf9\u60a8\u6709\u6240\u5e2e\u52a9\uff0c\u671b\u91c7\u7eb3\uff01

~ O(\u2229_\u2229)O~

NDIS Filter NET_BUFFER_LIST NET_BUFFER MDL

 1

网络数据结构如下图:

 

2

你可以按照我的下述2种程序代码的实现方法,来获取数据包的内容。你可以把代码直接添加到你的NDIS Filter工程代码里面。

3

代码编译环境:Visual Studio 2013WDK8.1测试通过的Windows系统有:32位Windows764位Windows732位Windows864位Windows832位Windows8.164位Windows8.1WindowsXP,不支持 NDIS Filter框架。

步骤阅读

4

第一种方法:

5

第二种方法:

/******************************************************************* GetNetBufferData函数的功能: 从1个NET_BUFFER里面获取数据。1个NET_BUFFER里面含有1个或者多个的MDL *******************************************************************/VOID GetNetBufferData(  PNET_BUFFER    NetBuffer,  PUCHAR      OutputBuffer,  ULONG      OutputBufferSize,  PULONG      OutputBytesCopied  ){  PMDL  Mdl = NetBuffer->CurrentMdl;  *OutputBytesCopied = 0;  if (NetBuffer->DataLength > OutputBufferSize)  {#if DBG    DbgPrint("Not enough output buffer space, in: %d, out : %d
",       NetBuffer->DataLength,       OutputBufferSize);#endif    return;  }  NdisMoveMemory(OutputBuffer,    (PUCHAR)MmGetSystemAddressForMdlSafe(Mdl, LowPagePriority) + NetBuffer->CurrentMdlOffset,    Mdl->ByteCount - NetBuffer->CurrentMdlOffset);    OutputBuffer += Mdl->ByteCount - NetBuffer->CurrentMdlOffset;  *OutputBytesCopied += Mdl->ByteCount - NetBuffer->CurrentMdlOffset;  //  //循环 MDL链表,获取每一个结点的数据,数据被保存到 OutputBuffer里面  //OutputBuffer的空间不断地扩大。  //当链表不为空, 并且 OutputBuffer的长度 < 1个NET_BUFFER的总长度  while ( ((Mdl = Mdl->Next)!=NULL) && (*OutputBytesCopied < NetBuffer->DataLength) )  {    NdisMoveMemory(OutputBuffer,      MmGetSystemAddressForMdlSafe(Mdl, LowPagePriority),      Mdl->ByteCount);    OutputBuffer += Mdl->ByteCount;          //数据被保存到 OutputBuffer里面    *OutputBytesCopied += Mdl->ByteCount;    //OutputBuffer的空间不断地扩大  }  if (Mdl != NULL)  {    NdisMoveMemory(OutputBuffer,      MmGetSystemAddressForMdlSafe(Mdl, LowPagePriority),      NetBuffer->DataLength);    OutputBuffer += Mdl->ByteCount;    *OutputBytesCopied += Mdl->ByteCount;  }#if DBG  DbgPrint("buffer copied: %d bytes
", *OutputBytesCopied);#endif}

6

上面的2种方法,只是获取数据。而原本NDIS Filter框架提供的这4个函数默认的代码,都没有做任何操作,没有实质性质的功能,这4个函数原本默认的代码,我们都不需要, 因为我们的驱动程序需要处理网络数据包。这4个函数分别是:FilterSendNetBufferListsCompleteFilterSendNetBufferListsFilterReturnNetBufferListsFilterReceiveNetBufferLists

7

在我们的NDIS Filter工程里面,我们需要修改掉这4个函数的功能,把它们替换成我们所想要的功能。比如,你在发送数据包或者接收数据包的时候,需要实现自己的一些业务逻辑,而不是去使用Microsoft NDIS Filter提供的原始代码的功能。

8

 FilterSendNetBufferListsComplete函数的功能:   NDIS调用 FilterSendNetBufferListsComplete 把发送的结构和数据返还给 Filter Driver。NDIS可以收集多次NdisFSendNetBufferLists发送的结构和数据形成一个单链表传递给FilterSendNetBufferListsComplete。除非到NDIS调用FilterSendNetBufferListsComplete,否则一个发送请求的当前状态总是未知的。   一个过滤驱动是不能在NDIS调用FilterSendNetBufferListsComplete返回结构之前对NET_BUFFER_LIST和其关联的数据做检查的。FilterSendNetBufferListsComplete要完成一个发送请求完成后的任何必要的后继处理。当NDIS调用FilterSendNetBufferListsComplete时,Filter Driver就重新获地对结构及结构相关资源的所有权。可以在 FilterSendNetBufferListsComplete中释放相关的资源和准备下一个NdisFSendNetBufferLists调用。      NDIS总是按照过滤驱动调用NdisFSendNetBufferLists提交的顺序传递给下层驱动,但是回返FilterSendNetBufferListsComplete 的顺序则是任意的。Filter Driver可以请求一个回环发送请求,只要把NdisFSendNetBufferLists的SendFlags设置成NDIS_SEND_FLAGS_CHECK_FOR_LOOPBACK就行了。NDIS会引发一个包含发送数据的接收包指示。

9

 一个Filter Driver应该对自己引发的发送请求保持跟踪并确保在完成时不调用NdisFSendNetBufferComplete例程。

步骤阅读

10

 FilterSendNetBufferLists函数的功能:   NDIS调用一个Filter Driver的FilterSendNetBufferLists例程来过滤上层驱动的发送请求。Filter Driver不能改变其它驱动传来的NET_BUFFER_LIST结构中的SourceHandle成员的值。它可以过滤数据并发送过滤的数据到下层驱动。

11

 对每一个提交到FilterSendNetBufferLists的NDIS_BUFFER_LIST,我们可做下面的操作:

 1)可以把缓冲区通过 NdisFSendBufferLists 传递给下层驱动,NDIS 保证上下文空间对FilterDriver的有效性。过滤驱动可以在发送前修改缓冲区的内容。可以像处理自己引发的发送请求的缓冲区一样处理这个缓冲区。      2)可以调用 NdisFSendNetBufferListsComplete 拒绝传递这个包    3)排队缓冲区内容到本地的供以后处理。例如要在一定超时后处理或要接收到特定包后才处理等。如果支持这种处理方式就要支持取消请求的操作。        4)可以拷贝缓冲区并引发一个发送请求。它类似自己引发一个发送请求,但必须先调用 NdisFSendNetBufferComplete返回上层驱动的缓冲区。

12

发送请求在驱动栈继续完成,当一个微端口驱动调用NdisMSendNetBufferListsComplete完成一个发送请求时,NDIS会调用微端口

13

在一个发送操作完成后,Filter Driver可以做在FilterSendNetBufferLists中所有修改的相反操作。FilterSendNetBufferListsComplete返回一个NET_BUFFER_LIST结构的单链表和发送请求的最终状态给上层的驱动。当最顶层的 Filter Module的FilterSendNetBufferListsComplete被调用完成后NDIS会调用引发发送请求的协议驱动的ProtocolSendNetBufferListsComplete。如果Filter Driver不提供FilterSendNetBufferLists它还是可以引发一个发送操作的,但它必须提供一个FilterSendNetBufferListsComplete并且不能在这个例程里把这个事件传递给上层驱动。

14

一个Filter Driver可以传递或过滤一个上层驱动的回环请求,要传递一个回环请求,NDIS会设置FilterSendNetBufferLists的SendFlags参数为NDIS_SEND_FLAGS_CHECK_FOR_LOOPBACK,Filter Driver在调用NdisFSendNetBufferLists时把这个标记传给它即可。在回环请求的情况下NDIS会指示一个包含发送数据的接收包。

15

如果一个Filter Driver修改的任何行为不是NDIS提供的标准服务,那么它应该当自己为NDIS提供相应的服务。例如,如果一个Filter Driver修改了一个硬件地址请求,就必须处理直接到这个新地址回环包。在这种情况下, 因为Filter Driver已经更改了地址NDIS是不能提供一个回环服务的。

16

_Use_decl_annotations_VOIDFilterSendNetBufferLists(  NDIS_HANDLE         FilterModuleContext,  PNET_BUFFER_LIST    NetBufferLists,  NDIS_PORT_NUMBER    PortNumber,  ULONG               SendFlags  ){  PMS_FILTER          pFilter = (PMS_FILTER)FilterModuleContext;  PNET_BUFFER      NetBuffer;  UCHAR        TempBuffer[MAX_BUFFER_SIZE];  ULONG        BytesCopied;  pEthHdr        EthernetHeader;  pIPHdr        IpHeader;#if DBG  DbgPrint(">>> FilterSendNetBufferLists: %p
", NetBufferLists);#endif  for (NetBuffer = NetBufferLists->FirstNetBuffer;    NetBuffer!= NULL;    NetBuffer = NetBuffer->Next)  {    GetNetBufferData(NetBuffer, TempBuffer, MAX_BUFFER_SIZE, &BytesCopied);    if (BytesCopied == 0)    {#if DBG      DbgPrint("Net buffer catch error
");#endif    }    else    {      EthernetHeader = TempBuffer;      if (EthernetHeader->Type == 0x0800)//以太网类型      {        IpHeader = EthernetHeader + sizeof(EthHdr); //去掉以太网头,抓出IP头#if DBG        DbgPrint("Get ip packet
");#endif      }    }  }  NdisFSendNetBufferLists(pFilter->FilterHandle, NetBufferLists, PortNumber, SendFlags);}

17

FilterReturnNetBufferLists函数的功能:   如果Filter Driver设置了NdisFIndicateReceiveNetBufferLists的状态为NDIS_STATUS_SUCCESS, NDIS通过驱动的FilterReturnNetBufferLists   返回指示数据。在这种情况下 Filter Driver失去了对NET_BUFFER_LIST的所有权,直到FilterReturnNetBufferLists被调用。   Filter Driver调用NdisFIndicateNetBufferLists 传递接收指示给驱动栈上的上层驱动,如果上层驱动保留了对缓冲区(NET_BUFFER_LIST)的所有权,NDIS会调用Filter Driver的FilterReturnNetBufferLists 例程。      在FilterReturnNetBufferLists中应该撤消在接收路径上(如在 FilterReciveNetBufferLists中做的一些处理)的操作。当最底层的Filter Module完成对缓冲区(NET_BUFFER_LIST)的处理后,NDIS把缓冲区返回给微端口驱动。如果FilterReceiveNetBufferLists的ReceiveFlags没有设置NDIS_RECEIVE_FLAGS_RESOURCES标记, FilterDriver调用NdisFReturnNetBufferList返回这个缓冲区数据,如果设置了FilterReceiveNetBufferLists直接返回时就把缓冲区返还给了下层微端口驱动。 

步骤阅读

18

FilterReceiveNetBufferLists函数的功能:   Filter Driver调用 NdisFIndicateReceiveNetBufferLists来指示发送数据。这个函数通过NET_BUFFER_LIST结构给上层驱动指示数据。Filter Driver可以从池中分配这个结构。如果Filter Driver设置了NdisFIndicateReceiveNetBufferLists的状态为 NDIS_STATUS_SUCCESS, NDIS通过驱动的FilterReturnNetBufferLists返回指示数据。在这种情况下Filter Driver失去了对NET_BUFFER_LIST的所有权直到FilterReturnNetBufferLists被调用。如果Filter Driver在调用NdisFIndicateReceiveNetBufferLists时设置ReceiveFlags为NDIS_RECEIVE_FLAGS_RESOURCES,在函数返回后Filter Driver会立即恢复对NET_BUFFER_LIST的所有权,这时Filter Driver必须立即处理这个NET_BUFFER_LIST的返回,因为NDIS在这种情况下是不会调用FilterReturnNetBufferLists返回NET_BUFFER_LIST结构的。    注意: 一个Filter Driver应该跟踪自己引发的接收指示确保它在FilterReturnNetBufferLists   中不调用NdisFReturnNetBufferLists。 

19

_Use_decl_annotations_VOIDFilterReceiveNetBufferLists(  NDIS_HANDLE         FilterModuleContext,  PNET_BUFFER_LIST    NetBufferLists,  NDIS_PORT_NUMBER    PortNumber,  ULONG               NumberOfNetBufferLists,  ULONG               ReceiveFlags  ){  PMS_FILTER          pFilter = (PMS_FILTER)FilterModuleContext;  PNET_BUFFER          NetBuffer;  UCHAR            TempBuffer[MAX_BUFFER_SIZE];  ULONG            BytesCopied;  pEthHdr            EthernetHeader;  pIPHdr            IpHeader;#if DBG  DbgPrint(">>> FilterReceiveNetBufferLists: %p
", NetBufferLists, ReceiveFlags, NumberOfNetBufferLists);#endif  do  {    for (NetBuffer = NetBufferLists->FirstNetBuffer;      NetBuffer != NULL;      NetBuffer = NetBuffer->Next)    {      GetNetBufferData(NetBuffer, TempBuffer, MAX_BUFFER_SIZE, &BytesCopied);      if (BytesCopied == 0)      {#if DBG        DbgPrint("Net buffer catch error
");#endif      }      else      {        EthernetHeader = TempBuffer;        if (EthernetHeader->Type == 0x0800)        {          IpHeader = EthernetHeader + sizeof(EthHdr);#if DBG          DbgPrint("IP packet exist
");#endif        }      }    }  } while (FALSE);

20

调用 NdisFIndicateReceiveNetBufferLists来指示发送数据。 如果Filter Driver设置了NdisFIndicateReceiveNetBufferLists的状态为NDIS_STATUS_SUCCESS, NDIS通过驱动的FilterReturnNetBufferLists 返回指示数据。      如果Filter Driver设置了NdisFIndicateReceiveNetBufferLists的ReceiveFlags值为NDIS_RECEIVE_FLAGS_RESOURCES, 那么在函数返回后Filter Driver会立即恢复对NET_BUFFER_LIST的所有权,这时Filter Driver必须立即处理这个NET_BUFFER_LIST的返回。 在这种情况下是不会调用FilterReturnNetBufferLists返回NET_BUFFER_LIST结构的。



扩展阅读:stable diffusion ... disable filter ... savitar2 ndis filter ... personality ... flyff universe ... filter cleaning怎么消除 ... 天籁oil filter怎么消除 ... ds file 官方下载 ... 显示oil filter还能开吗 ...

本站交流只代表网友个人观点,与本站立场无关
欢迎反馈与建议,请联系电邮
2024© 车视网