今天本来想发篇正式点的BLOG,没想到没有保存住, 以后word打开不敢随便关闭啥提示了。
以下是网络上的文章的摘录,但已经能反应整个的思路过程。
其中,最上层是一个NDIS Protocol Driver,它向上提供一个Transport Driver Interface(TDI),向下通过NDIS接口与下面的NDIS中间层的上边界交互,NDIS中间层的下边界通过NDIS接口与下层的NDIS Miniport Driver交互。最后,由NDIS Miniport Driver利用NDIS接口与物理网络设备NetCard交互。NetCard是由不同的网卡设备产商提供的,而NDIS接口库是由Microsoft开发好的,为什么NDIS Miniport Driver不是直接与物理网卡交互,而是通过NDIS接口与下物理网卡交互呢?(我想很多人都会和我当初一样,有这个疑问)。
事实上,这是由于Windows系统为了提高可移植性,而设计出一个硬件抽象层(HAL),硬件抽象层在内部处理不同的硬件之间的差异,并且暴露出一个统一的接口给核心驱动开发者。例如:在Intel构架的系统中,内存和外部设备的端口采用分别编址,如果要从某个外部设备的端口上读写数据的话,可能要通过专用指令IN/OUT读写,而在Alpha构架的系统上,采用的是统一编址的方式,所以对外部设备的IO端口进行读写的话还是通过访问内存的指令,HAL提供一组服务支持函数,如果要访问外部设备上的端口数据可以使用READ_PORT_UCHAR/WRITE_PORT_UCHAR等等,核心驱动开发者不用去考虑不同硬件构架的之间的差异。在NDIS Miniport Driver中,NetCard驱动的程序,正是这样通过NDIS接口提供的一组类似功能的函数,与物理的网络设备进行交互。其中,最上层是一个NDIS Protocol Driver,它向上提供一个Transport Driver Interface(TDI),向下通过NDIS接口与下面的NDIS中间层的上边界交互,NDIS中间层的下边界通过NDIS接口与下层的NDIS Miniport Driver交互。最后,由NDIS Miniport Driver利用NDIS接口与物理网络设备NetCard交互。
原来的通信可以看成下面的样子:
协议栈处理过信息后发给Minport,或则Minport接受信息后发给协议栈,而我们在中间加了一层后变成下图所示:
在wddk中passthru的例子来说具体的各个接口如下图所示:
发送示例如下:
1.Protocol driver调用NdisSend向下层发送数据报文。
2. Passthru的MPSend/MPSendPacket例程根据上层传下来的数据报文分配MyPacket,调用NdisSend发送到下层。如果返回pending,就在PtSendComplete中释放我们的MyPacket;否则就在本函数中紧接着释放MyPacket。
3. 当下层miniport driver发送完成MyPacket以后,会调用NdisMSendComplete
4. NDIS接着调用passthru的PtSendComplete,在这个函数里边,我们应该释放MyPacket,并且通知上层protocol driver去释放它们的packet。
知道这个过程之后就可以模拟丢包,整体架构如下:
下面为丢包模拟结构图:
(1)协议驱动调用NdisSend 向下层发送数据包Packet;
(2)NDIS 调用中间层驱动的MPSendPackets 函数将上层传递下来的数据包构建另一个数据包MyPacket,同样调用NdisSend 将此数据包传递到下一层驱动。如果返回pending,就在步骤(5)中释放MyPacket 的资源,否则在本函数中立即释放资源;
(3)网卡驱动收到从中间层传递下来的MyPacket;
(4)网卡驱动调用NdisSend 发送MyPacket;
(5)网卡驱动调用NdisMSendComplete,NDIS 接着调用中间层的PtSendComplete 函数释放步骤(2)中MyPacket 的所有资源,并通知上层协议驱动释放步骤(1)中Packet 的资源;
(6)协议驱动释放Packet 的所有资源。
本文对中间层驱动程序进行修改,在步骤(2)中间层中的MPSendPackets 函数中完成步骤(5),网卡驱动就无法得到上层传递的数据包从而实现了包丢弃。修改后发送流程如图3中虚线所示。
本文的例子也是网络上最多的(本来就是抄袭网络),但是其中Passthru的例子只适应于 wddk6.0以下,如果您的操作系统我一样是win7 64的则需要通过另外的方式来实现,请参考wddk下的filter例子。以后会再说。