`
yexin218
  • 浏览: 970768 次
  • 性别: 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是否为自己定义的结构?能否也给出其定义?万分感谢!

相关推荐

    Filter驱动开发笔记

    Filter发送自定义数据详解 - **自定义数据**:Filter驱动可以发送自定义的数据包。 - **发送方法**:通过NdisBuildPacket等函数构建数据包,并通过适当的OID请求发送出去。 #### 47. 如何在内核中获得当前系统...

    Java_Filter过滤机制详解.

    综上所述,Java Filter提供了一种灵活的方式,允许开发者在Web应用的请求和响应处理流程中插入自定义逻辑,极大地增强了Web应用程序的功能性和安全性。理解并熟练运用Filter机制,对于开发高效、健壮的Web应用至关...

    Android 中“自定义权限”源代码

    ### Android中的自定义权限详解与实现 #### 一、引言 在Android系统中,为了保护用户隐私和数据安全,应用程序被赋予了基于权限的安全模型。Android预定义了一系列权限,如访问联系人、发送短信等,但同时也允许...

    Informatica Router Transformation组件 详解

    Router Transformation 的优点是可以根据不同的条件将数据分组,并且可以根据不同的输出 port 将数据发送到不同的目标。 在使用 Router Transformation 时需要注意以下规则: * 一个 Router Transformation 可以...

    Android_Intent和Intent_Filter详解

    Android Intent和Intent_Filter详解 Android Intent是 Android 组件间通信的载体,它们之间的通信是通过 Intent 对象在不断传递实现的。Android 的三大核心组件 Activity、Service 和 BroadcastReceiver 都是通过 ...

    MINA开发文档详解

    实现 messageReceived 方法来处理客户端发送的数据,解析表达式并计算结果;最后实现 messageSent 方法来发送计算结果回客户端。 #### 总结 通过本文档,我们深入了解了 **Apache Mina 2** 的核心概念和架构设计,...

    servlet过滤器详解

    ### Servlet过滤器详解 #### 一、Servlet过滤器的概念与作用 Servlet过滤器,作为Java Servlet规范中的一个重要组成部分,自2.3版本起被引入,主要用于在Servlet容器中对请求和响应进行预处理和后处理。它不直接...

    Android 广播接收 发送 demo

    如果你想让广播只被特定的BroadcastReceiver接收,可以使用sendOrderedBroadcast()或sendBroadcastAsUser()方法,并设置Intent的flags和extra数据。 **Demo详解** 在提供的压缩包文件中,有两个主要的部分:`...

    JavaEE Filter敏感词过滤的方法实例详解

    通过实现javax.servlet.Filter接口,我们可以自定义过滤逻辑,例如在请求处理过程中添加额外的安全检查或数据处理。 在本例中,我们的目标是过滤掉用户输入中的敏感词。前端页面提供了一个表单,用户可以输入姓名和...

    directshow_SDK开发笔记(翻译).pdf

    - **实践编写自定义Filter**:通过开发自定义Filter来解决特定问题或增加新功能。 - **深入理解Filter Graph的工作原理**:掌握Filter Graph的设计原则和状态管理机制对于构建复杂的应用程序至关重要。 综上所述,...

    ActivityandroidIntent详解.pdf

    3. 广播:使用Context.sendBroadcast、Context.sendOrderedBroadcast或Context.sendStickyBroadcast发送Intent给BroadcastReceiver。 在AndroidManifest.xml文件中,必须声明所有的Activity,以便系统知道如何正确...

    剖析web.xml详解

    21. filter-chain-filter chain元素在Servlet 3.0及以上版本中引入,允许定义一系列过滤器,它们按顺序对请求进行处理,提供了更灵活的过滤器配置。 web.xml是Java EE应用的核心配置文件,它定义了应用的结构、行为...

    [Logstash]使用详解1

    Logstash 是一款轻量级的日志收集和处理框架,它能有效地将分散的、多样的日志数据汇聚在一起,经过自定义的处理后,发送到指定的目标,如服务器或文件。这款工具简单易用,适合各种环境下的日志管理。 在安装...

    基于VC和DirectShow技术的视频采集和捕捉

    这个Filter允许开发者自定义数据处理回调函数,当新的视频帧到达时,该函数会被调用。通过分析和处理回调中的数据,你可以进行各种操作,比如显示预览、实时处理或存储原始帧。在VC中,这通常通过实现`IMediaSample`...

    基于Flink的车联网实时数据平台.zip

    《基于Flink的车联网实时数据平台详解》 在大数据领域,实时处理技术是不可或缺的一环,尤其是在车联网领域,车辆产生的海量数据需要实时分析以提供决策支持和服务优化。Apache Flink作为一个强大的流处理框架,因...

    Android Intent发送广播消息实例详解

    在发送广播消息时,Intent充当了消息的载体,包含了广播的特定标识和可能的数据。 发送广播消息的基本步骤如下: 1. 创建Intent对象:首先,你需要创建一个Intent实例,指定一个全局唯一的字符串作为动作(Action...

    SMSFilter:一个Android应用程序,可通过电话号码过滤短信

    《SMSFilter:构建Android应用程序实现电话号码筛选短信详解》 在Android开发领域,创建自定义功能的应用程序是一项常见的任务。本篇文章将详细讲解如何利用Java编程语言开发一个名为SMSFilter的Android应用程序,...

    Exper9.rar

    在Java Web开发中,Filter(过滤器)扮演着至关重要的角色,它允许我们在数据处理前后插入自定义逻辑,对HTTP请求和响应进行拦截、修改或者增强。本教程将深入探讨Java Web Filter的开发,结合Eclipse集成开发环境,...

Global site tag (gtag.js) - Google Analytics