如何把ndis filter框架利用到日膚indows驱动开发工作中 NDIS中间层驱动开发在Win7系统下和Windows XP...
\u5982\u4f55\u628aNDIS Filter\u6846\u67b6\u5229\u7528\u5230\u65e5\u8164indows\u9a71\u52a8\u5f00\u53d1\u5de5\u4f5c\u4e2dNDIS 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还能开吗 ...