`
yexin218
  • 浏览: 958132 次
  • 性别: Icon_minigender_1
  • 来自: 珠海
社区版块
存档分类
最新评论

Filter发送自定义数据详解

阅读更多

                                                    

这里介绍如何从创建数据到最后发送数据的一个过程。

首先要做准你要发送的数据,注意你的数据大小至少要不少于64Byte。我们这里设置数据包的大小为80Byte.里面的内容包含一个14ByteEthernet Header,其他空位用无用数据填充。下面是具体流程:

一、创建缓冲区----用于保存自定义的数据

Ndis中创建新的一块内存的函数是:NdisAllocateMemoryWithTagPriority(),其他函数自行参考MSDN. 下面是用例:

pWriteBuf = (PUCHAR)NdisAllocateMemoryWithTagPriority(pFilter->FilterHandle,BufferSize,FILTER_ALLOC_TAG, LowPoolPriority);

其中BufferSize等于80(比这个大也可以!根据需要。)

二、封装自定义数据

因为Ethernet Header是一个Struct结构,定义如下:

typedef struct _TESTPROV_ETH_HEADER

{

    UCHAR       DstAddr[TESTPROV_MAC_ADDR_LEN];

    UCHAR       SrcAddr[TESTPROV_MAC_ADDR_LEN];

    USHORT      EthType;

 

} TESTPROV_ETH_HEADER;

所以我们要把这些成员变量都赋值。首先申明一个TESTPROV_ETH_HEADER的一个指针变量,然后指向PwriteBuf所指的那块内存:

pEthHeader = (PTESTPROV_ETH_HEADER)pWriteBuf;

然后开始给TESTPROV_ETH_HEADER中的每个成员函数赋值,其中EthType= 0x8e88.

 

三、创建MDL

由于我们最终要把自定义的数据封装成NBL,然后发送出去。如果了解NBL结构,知道NBL由一个或者多个NB构成,每个NB又由一个或者多个MDL构成。所以这里我们先分配一个MDL,用来保存自定义的数据。

pMdl = NdisAllocateMdl(pFilter->FilterHandle,

                               pEthFrameNew,  

                               BufferSize);

注意这里pEthFrameNew是一个Virtual Address.指向的是MDL缓冲区的基地址。需要事先分配:

pEthFrameNew = (PUCHAR)NdisAllocateMemoryWithTagPriority(pFilter->FilterHandle,BufferSize,FILTER_ALLOC_TAG, LowPoolPriority);

 

四、拷贝数据到MDL,并且释放pWriteBuf

如果你的MDL创建成功之后,MDL中是没有内容的,需要把之前自定义在pWriteBuf中的数据拷贝到MDL中:

NdisMoveMemory(pEthFrameNew,pEthHeader, BufferSize);

之后释放pWriteBuf(勿忘)

 NdisFreeMemory(pWriteBuf,BufferSize,0);

五、创建NBL

在创建NBL之前,有一件很重要的工作,那就是要分配好NetBufferListsPool.因为之后所有从Filter创建的NBL都要建立在这个Pool之上。从方便和多次利用考虑,我们把Pool分配工作在FilterAttach中完成:

        NdisZeroMemory(&PoolParameters,            sizeof(NET_BUFFER_LIST_POOL_PARAMETERS));

 

        PoolParameters.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;

        PoolParameters.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;

        PoolParameters.Header.Size = sizeof(PoolParameters);

        PoolParameters.ProtocolId = NDIS_PROTOCOL_ID_DEFAULT ;

        PoolParameters.ContextSize = sizeof(FILTER_SEND_NETBUFLIST_RSVD);

        PoolParameters.fAllocateNetBuffer = TRUE;

        PoolParameters.PoolTag = FILTER_ALLOC_TAG;

        pFilter->SendNetBufferListPool = NdisAllocateNetBufferListPool(

                                                    NdisFilterHandle,

                                                    &PoolParameters);

需要注意的是,Ndis为每个Filter module instance 各自分配一个Pool. 还有sizeof(FILTER_SEND_NETBUFFER_RSVD)的值必须为8的整数倍(0亦可)

这里我们采用函数NdisAllocateNetBufferAndNetBufferList()来创建NBL,因为它不需要事先创建NB就可以直接跳过这一步创建NBL,有兴趣可以参考NdisAllocateNetBufferList().需要的参数为之前创建的Pool,以及预分配的MDL等。

                              pNetBufferList = NdisAllocateNetBufferAndNetBufferList(

                                pFilter->SendNetBufferListPool,

                                sizeof(FILTER_SEND_NETBUFLIST_RSVD),

                                0,           // back fill size

                                pMdl,

                                0,          // Data offset

                                BufferSize);

注意:如果没有成功创建NBL,需要释放MDL.免得内存泄露。

六、发送NBL

发送之前需要制定NBLSourceHandle,为了后面处理需要,以辨别是自己定义的数据。其次制定发送的Dispatch_level.

                              pNetBufferList->SourceHandle = pFilter->FilterHandle;

             

                              //NDIS_MDL_LINKAGE(pMdl) = NULL;

                              SendFlags = NDIS_SEND_FLAGS_DISPATCH_LEVEL;

                              NdisFSendNetBufferLists(       

                        pFilter->FilterHandle,

                        pNetBufferList,

                        NDIS_DEFAULT_PORT_NUMBER,

                        SendFlags);

七、处理NdisFSengNetBufferListComplete

这里需要注意:如果不是你自己发送的数据,需要通知Protocol层,该数据已经提交给底层了。如果是自己的创建和发送的,需要额外处理,销毁证据,因为上层Protocol没有让Filter发送该数据,如果也通知发送完毕就会出事,最显而易见的就是Blue Screen. 所以你要做的:

1.       判断是否是自己发送的数据:

if(NetBufferLists->SourceHandle == pFilter->FilterHandle){}

2.       如果是,销毁自定义数据

pMdl = NET_BUFFER_FIRST_MDL(NET_BUFFER_LIST_FIRST_NB(NetBufferLists));

                                             

FILTER_ASSERT(pMdl != NULL);

NdisQueryMdl(

                pMdl,

                (PVOID *)&pCopyData,

                &BufferLength,

                NormalPagePriority);

                                                             

FILTER_ASSERT(pCopyData != NULL);

FILTER_DEREF_SEND_NBL(NetBufferLists, DispatchLevel);

  NdisFreeMdl(pMdl);

pCopyData = NULL;

3.       如果不是,调用NdisFSendNetBufferListsComplete()通知上层驱动

NdisFSendNetBufferListsComplete(pFilter->FilterHandle, NetBufferLists, SendCompleteFlags);

到这里,该数据包发送完毕!

八、卸载释放Pool

这里是题外话:你在FilterAttach分配的Pool,你需要在FilterDetach时释放:

                if(pFilter->SendNetBufferListPool !=NULL)

              {

                  NdisFreeNetBufferListPool(pFilter->SendNetBufferListPool);

                              pFilter->SendNetBufferListPool = NULL;

              }

不要担心,各自的Filter Module Instance都会各自释放自己的Pool.

九、整理暂时结束

 

一路风尘  整理

   

分享到:
评论
1 楼 sanny81 2014-02-05  
     此文真棒!感谢一路风尘的奉献!
     但我有一疑问想在此请教:

     pFilter->SendNetBufferListPool、FILTER_SEND_NETBUFLIST_RSVD是否为自己定义的结构?能否也给出其定义?万分感谢!

相关推荐

    windows驱动开发技术详解-part2

     9.4 自定义的StartIO  9.4.1 多个串行化队列  9.4.2 示例  9.5 中断服务例程  9.5.1 中断操作的必要性  9.5.2 中断优先级  9.5.3 中断服务例程(ISR)  9.6 DPC例程  9.6.1 延迟过程调用例程(DPC...

    Windows驱动开发技术详解的光盘-part1

     9.4 自定义的StartIO  9.4.1 多个串行化队列  9.4.2 示例  9.5 中断服务例程  9.5.1 中断操作的必要性  9.5.2 中断优先级  9.5.3 中断服务例程(ISR)  9.6 DPC例程  9.6.1 延迟过程调用例程(DPC...

    最新Python3.5零基础+高级+完整项目(28周全)培训视频学习资料

    自定义filter 自定义分页 Cookie是什么鬼 基于Cookie实现用户登录 基于cookie实现定制显示数据条数 带签名的Cookie CBV和FBV用户认证装饰器 本周作业 第22周 上节回顾 Django之url、Views Django之Model操作 ...

    python入门到高级全栈工程师培训 第3期 附课件代码

    07 通过form向server端发送数据 08 form表单之select标签 09 table标签 第38章 01 css的四种引入方式 02 css的四种基本选择器 03 css的组合选择器 04 css的属性选择器 05 css的伪类 06 css的选择器优先级 07 css的...

    asp.net知识库

    与DotNet数据对象结合的自定义数据对象设计 (二) 数据集合与DataTable 与DotNet数据对象结合的自定义数据对象设计 (一) 数据对象与DataRow ASP.NET中大结果集的分页[翻译] .net 2.0 访问Oracle --与Sql Server的...

    疯狂Android讲义源码

     5.1 Intent对象详解 197  5.1.1 使用Intent启动系统组件 197  5.2 Intent的属性及intent-filter  配置 198  5.2.1 Component属性 198  5.2.2 Action、Category属性与  intent-filter配置 200  5.2.3 指定...

    疯狂Android讲义.part2

    5.1 Intent对象详解 197 5.1.1 使用Intent启动系统组件 197 5.2 Intent的属性及intent-filter 配置 198 5.2.1 Component属性 198 5.2.2 Action、Category属性与 intent-filter配置 200 5.2.3 指定Action、Category...

    疯狂Android讲义.part1

    5.1 Intent对象详解 197 5.1.1 使用Intent启动系统组件 197 5.2 Intent的属性及intent-filter 配置 198 5.2.1 Component属性 198 5.2.2 Action、Category属性与 intent-filter配置 200 5.2.3 指定Action、Category...

Global site tag (gtag.js) - Google Analytics