【转帖】Passthru IM Driver简析

来源:互联网 发布:剑三技能监控数据 编辑:程序博客网 时间:2024/05/16 07:35
如果你希望对本机发出的数据包进行修改,则涉及如下几个函数:

1)MPSendPackets

由本机协议层调用,用于发送数据包。在这里你可以针对要发送的数据包进行识别及修改,然后再调用NdisSend发送到网络上。此处涉及新内存分配、新Buffer分配以及Buffer与Packet关联NdisChainBufferAtFront。

2)PtSendComplete

当NdisSend成功将数据发出后,NDIS会回调IM的协议层,此时应释放自己分配内存及Buffer,并通过NdisMSendComplete通知真正协议层“您所提交的数据包已发送完成”,以便协议层释放该原始数据包的资源。

如果你希望对本机收到的数据包进行修改,则涉及如下几个函数:

1)PtReceivePacket

2)PtSendComplete

该两个函数与上述两个原理基本相同,只是用于接收数据包。

应该注意的是NDIS中为了提高效率,增加了内存块、缓存描述符、包描述符等实体,巧妙利用了协议分层的特点,每一层均可以在Payload之前很方便地加入自己的包头,而无需拷贝整个Payload,但这也给我们的编程带来了相当大的复杂程度。

具体使用过程中,包描述符可以使用已有的Packet Pool,如果需要组建自己的数据包,则需要分配自己的Buffer Pool,并自己维护Buffer描述符及内存的分配及释放。


附:Passthru阅读笔记


发信人: Immortal1015 (后处理~列拷贝专家), 信区: DriverDev       
标  题: Passthru阅读笔记(一) IMDriver的绑定与卸载过程
发信站: BBS 水木清华站 (Thu Aug 16 22:34:31 2001)

涂鸦第一篇
IMDriver的绑定与卸载过程
一、绑定过程
    首先是Protocol端和下层NIC驱动绑定。NDIS调用PtBindAdapter,
在PtBindAdapter中调用NdisOpenAdapter,并等待PtOpenAdapterComplete
执行,在这里用到了NDIS_EVENT。然后调用NdisIMInitializeDeviceInstanceEx
来触发Miniport端与上层协议的绑定。
    在调试的时候有一个疑问,居然跟踪不到DriverEntry的调用
份特死我了。
    PtBindAdapter中有用的参数主要是DeviceName和SystemSpecific1,其中
DeviceName是下层NIC驱动的服务名,SystemSpecific1可以用来
读取注册表中相关的值。
    1.调用NdisOpenProtocolConfiguration,参数是SystemSpecific1
获得ConfigHandle.
    2.调用NdisReadConfiguration(Status,
                                &Param,
                                ConfigHandle,
                                &DeviceStr---"Upperbind",
                                NdisParameterString);
      来获得注册表里相关的绑定信息。
    3.再调用NdisReadConfiguration来获得BundleID,其实这段可以不要,
如果你不需要LBFO的话。
    4.调用NdisOpenAdapter,参数DeviceName来绑定底层NIC驱动。
    5.调用NdisImInitializeDeviceInstanceEx来触发MpInitialize的调用。
    在MpInitialize里面主要做两件事情:
    1.判断介质类型
    2.调用NdisMSetAttributesEx设置一些特性,其中NDIS_ATTRIBUTE_DESERILIZE
和NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER值得注意。
二、卸载过程
    1.首先注意到,在DriverEntry部分:
              NdisMInitializeWrapper
   |
   |
              NdisIMRegisterLayeredMIniport
                        |
                        |
               NdisMRegisterUnloadHandler
      这个函数为驱动注册一个卸载函数PtUnload,在PtUnload里面调用
NdisDeregisterProtocol来取消注册Protocol端
   2.看看相关的Protocol端和Miniport端都做些什么工作。
     Miniport:
             **HaltHandler:这个处理函数当底层NIC已经time out且
               NDIS中止NIC驱动时,或者操作系统关机时被调用。
     Protocol:
             **UnbindAdapterHandler
             **CloseAdapterCompleteHandler
    当点击卸载IM时,ndis首先调用PtUnBindAdapter,在这个
函数里面:
    1)判断IM Driver 的Miniport Handle是否为空。
    2)如果不为空,则调用NdisImDeInitializeDeviceInstance来出发MpHalt的执行。
    3)如果为空,则调用NdisCloseAdapter,然后等待CloseAdapterCompleteHandler
    的触发。还是用了事件来等待。
    4)释放分配的资源。
    在MpHalt函数里面执行上面的第3,4。
    卸载的流程大体如下:
                            PtUnbindAdapter
                                  |                       Yes
                           MiniportHandle==NULL?------------------
      |                               |
                                  |No                             |
                                  |                               |
                       NdisImDeInitializeDeviceInstance           |
                                  |                               |
                                  |                               |
                                  |                               |
                                 MpHalt                           |
                                  |<------------------------------|
                                  |
                            NdisCloseAdapter
                                  |
                                  |
                          PtCloseAdapterComplete
                                  |
                                  |
                              PtUnload

--

※ 来源:·BBS 水木清华站 smth.org·[FROM: 166.111.37.73]


发信人: Immortal1015 (后处理~列拷贝专家), 信区: DriverDev       
标  题: Passthru阅读笔记(二) IP地址的获得
发信站: BBS 水木清华站 (Sun Sep  2 15:40:40 2001)

呵呵,不好意思。前面说过要分析一下安装过程,还是
先写点小东西吧。

在IMD里面如何获得网卡所绑定的TCP/IP协议设置的IP地址?
2KDDK文档的Network Reference Part 2 ch2.1
中列出了一堆的oid,其中一个是OID_GEN_NETWORK_LAYER_ADDRESSES
看看它的说明:
This OID notifies underlying miniport and other layered drivers about the l
ist of network-layer addresses that are associated with bound instances. A b
ound instance is the binding between the calling transport and a driver set 
up by a call to NdisOpenAdapter. Transports use TRANSPORT_ADDRESS and TA_ADD
RESS structures to notify underlying miniport and other layered drivers abou
t the list of network-layer addresses.
也就是说,协议栈会向它所绑定的NIC Miniport通知自己的网络地址的信息。
那么,在passthru miniport端的SetInformationHandler 就会被触发,我们
可以等到PtRequestComplete的时候来获得网卡的ip地址。

正好,winxp 2462 ddk中的例子e100bex提供了一段代码,大家可以去看看。
下面是我写的代码:
NETWORK_ADDRESS_LIST UNALIGNED *        pAddrList = NULL;
NETWORK_ADDRESS UNALIGNED *             pAddr = NULL;
NETWORK_ADDRESS_IP UNALIGNED *          pIpAddr= NULL;
ULONG                                     Size;
ULONG                                     iplong;
if(NdisRequest->DATA.SET_INFORMATION.Oid ==
          OID_GEN_NETWORK_LAYER_ADDRESSES)
{
    pAddrList = (NETWORK_ADDRESS_LIST UNALIGNED *)NdisRequest->DATA.SET_INFO
RMATION.InformationBuffer;
    if (pAddrList->AddressCount <= 0)
    {
       return;
    }
    pAddr = (NETWORK_ADDRESS UNALIGNED *)&pAddrList->Address[0];
    if (pAddr->AddressType != NDIS_PROTOCOL_ID_TCP_IP)
    {
       return;
    }
    pIpAddr = (NETWORK_ADDRESS_IP UNALIGNED *)&pAddr->Address[0];
 Size = sizeof(pIpAddr->in_addr);
    iplong = pIpAddr->in_addr;
}


--

※ 来源:·BBS 水木清华站 smth.org·[FROM: 166.111.37.73]


发信人: Immortal1015 (后处理~列拷贝专家), 信区: DriverDev       
标  题: Passthru阅读笔记(三) 拨号网络
发信站: BBS 水木清华站 (Wed Oct  3 17:23:44 2001)

呵呵,这个问题搞了我好长时间,就因为一个低级错误。
其实这个也不算新鲜的了,相信有不少人知道。
Passthru怎么和拨号网络绑定呢,首先看一下这个图:

                TCPIP        IPX/SPX       NBF
                  |             |           |
                  NDISWAN INTERMEDIATE DRIVER
                               |
                              WAN miniport
其中,协议层和NDISWAN IMD之间是ndis,而NDISWAN IMD
和WAN miniport之间的通讯是通过ndis miniport 进行的。
在ddk network dirver Part 2, ch8, 8.3中有很详细的讲解。

看看passthru如何和拨号网络绑定:
   1. 修改inf。netsf.inf文件中有这么一行:
HKR, Ndi/Interfaces, FilterMediaTypes,   
 , "ethernet, tokenring, fddi"
其中ethernet,tokenring,fddi指定了要绑定的介质类型。
把这句话改为:ethernet, tokenring, fddi, wan
   2. passthru.c里面定义了
NDIS_MEDIUM      MediumArray[3]=NdisMedium802_3,
NdisMedium802_5,NdisMediumFddi
    现在需要加上NdisMediumWan.
   3. 在miniport.c的MpInitialize函数的开头:
    NDIS_MEDIUM    medium;
    if(pAdapt->Medium ==NdisMediumWan)
       medium = NdisMedium802_3;
    for (i = 0; i < MediumArraySize; i++)
{
  if (MediumArray[i] == medium)
  {
 *SelectedMediumIndex = i;
 break;
  }
}
ok,就这些。







        

--

※ 来源:·BBS 水木清华站 smth.org·[FROM: 166.111.37.73]