darkread
驱动牛犊
驱动牛犊
  • 注册日期2003-01-13
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
阅读:1834回复:12

NDIS中,在哪里接收封包的啊?

楼主#
更多 发布于:2004-04-01 17:06
我用的是PASSTHRU,DDK提供的那个

我在PtReceive()和PtReceivePacket()中都做了标记DBGPRINT()输出dbgview查看
PtReceivePacket()是根本不调用的
PtReceive()只进去一下就出来了,
但是网络是正常的
NDIS_STATUS
PtReceive(
IN  NDIS_HANDLE ProtocolBindingContext,
IN  NDIS_HANDLE MacReceiveContext,
IN  PVOID HeaderBuffer,
IN  UINT HeaderBufferSize,
IN  PVOID LookAheadBuffer,
IN  UINT LookAheadBufferSize,
IN  UINT PacketSize
)
/*++

Routine Description:
LBFO - need to use primary for all receives

Arguments:


Return Value:

--*/
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
PNDIS_PACKET MyPacket, Packet;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
DBGPRINT("===================>  5  <===================");//进去的
if(!pAdapt->MiniportHandle)
{
Status = NDIS_STATUS_FAILURE;
}
else do
{
//
// We should not be getting Receives on a Secondary, this is just specific to our  LBFO driver
//
           DBGPRINT("===================>  6  <===================");//进去的

if(pAdapt->isSecondary)
{
DBGPRINT("PASSTHRU GETTING RECIEVES ON SECONDARYn");
ASSERT(0);
}

//
// If this was indicated by the miniport below as a packet, then get that packet pointer and indicate
// it as a packet as well(with appropriate status). This way the OOB stuff is accessible to the
// transport above us.
//
Packet = NdisGetReceivedPacket(pAdapt->BindingHandle, MacReceiveContext);
if(Packet != NULL)
{
                      DBGPRINT("===================>  7  <===================");//这里就不进去了进去的
 
//
// Get a packet off the pool and indicate that up
//
NdisDprAllocatePacket(&Status,
 &MyPacket,
 pAdapt->RecvPacketPoolHandle);

if(Status == NDIS_STATUS_SUCCESS)
{
 MyPacket->Private.Head = Packet->Private.Head;
 MyPacket->Private.Tail = Packet->Private.Tail;
 //
 // Get the original packet(it could be the same packet as one received or a different one
 // based on # of layered MPs) and set it on the indicated packet so the OOB stuff is visible
 // correctly at the top.
 //
 NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));
 NDIS_SET_PACKET_HEADER_SIZE(MyPacket, HeaderBufferSize);

 //
 // Set Packet Flags
 //
 NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);

 //
 // Make sure the status is set to NDIS_STATUS_RESOURCES.
 //
 NDIS_SET_PACKET_STATUS(MyPacket, NDIS_STATUS_RESOURCES);

 NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1);
 DBGPRINT("==========FUNC PtReceive!===============");
 DBGPRINT("FOLLOEINT IS THE Content of MyPacket!");
 PrintPacket(MyPacket);
 ASSERT(NDIS_GET_PACKET_STATUS(MyPacket) == NDIS_STATUS_RESOURCES);
 NdisDprFreePacket(MyPacket);
 break;


下面省略了,因为从那个if之后基本上就是return 了

好像整个代码都没有做什么实质性的工作,


[编辑 -  4/1/04 by  darkread]
start
驱动小牛
驱动小牛
  • 注册日期2001-11-05
  • 最后登录2010-09-03
  • 粉丝0
  • 关注0
  • 积分9分
  • 威望27点
  • 贡献值0点
  • 好评度9点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2004-04-01 17:13
你可以研究一下ddk,ptReceive和ptReceivePacket函数如何调用,
由miniport driver的调用的函数决定,如果miniport driver调用
NdisXXXReceivePacket,则ndis调用ptReceivePacket函数,如果调用NdisXXXIndicateReceive,则调用ptReceive
second
asmsys
驱动老牛
驱动老牛
  • 注册日期2002-03-29
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望17点
  • 贡献值0点
  • 好评度8点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2004-04-01 17:24
这里有例子,找。
darkread
驱动牛犊
驱动牛犊
  • 注册日期2003-01-13
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
地板#
发布于:2004-04-01 18:04
可是无论如何,这里的两个函数好像都不起作用啊
麻烦就麻烦在这里
PtReceivePacket()是根本不调用的
PtReceive()一进去

Packet = NdisGetReceivedPacket(pAdapt->BindingHandle, MacReceiveContext);
//应该是在这里得到数据包吧,但是然后判断
if(Packet != NULL)
{
DBGPRINT("===================> 7 <===================");
}
//这句总是不会成功的,这个意思是不是就是说Get不到ReceivedRacket了呢,但是网络一直是正常的,数据包到底是在哪里得到然后上传的啊
darkread
驱动牛犊
驱动牛犊
  • 注册日期2003-01-13
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2004-04-01 18:42
在这里我找到了一些有用的东东,那位大侠和我解释一下http://www.driverdevelop.com/forum/viewthread.php?tid=46966
1、2、3、这三中情况下,如果我想得到数据包,并分析数据包应该怎么做
或者该去哪里找资料(中英文不限)


一、数据从网卡进入机器总共有4种可能性及对NAT的处理:
1。当网卡为老式网卡或不需要OOB数据时miniport调用ndisxxxindicatepacket时,NDIS调用ptreceive函数。并且packet==NULL。这时如果PACKETSIZE<=lookaheadbuffersize,那么说明所要数据已经传上来。
我们可以立即对数据进行组包,然后做NAT。如果NAT的返回值不是PENDING那么我们立即释放我们刚刚所
申请的资源。如果是PENDING那么我们应该在ptsendcomplete中释放我们的资源。

2。当系统资源不足时,miniport自己组装一个packet,但是这个packet只是一个指针而已!
miniport将这个packet的status设为NDIS_STATUS_RESOURCE
并调用ndisindicatepacket函数通知NDIS,那么NDIS也会调用ptreceive函数,但是在ptreceive
函数中,packet=ndisgetpacket的值不会==NULL。在ptreceive我们同样也申请一个包mypacket,
但是真正的内容还是在底层的miniport中,现在开始做NAT,那么如果返回不是PENDING那么
我们立即释放刚刚所申请的资源。否则我们应该在ptsendcomplete中释放我们的资源。
这个mypacket的释放要特别注意!


3。
当网卡为老式网卡或不需要OOB数据时miniport调用ndisxxxindicatepacket时,NDIS调用ptreceive函数,
并且packet==NULL。这时如果PACKETSIZE>lookaheadbuffersize;那么说明数据还有一部分在miniport上,
我们需要先transferdata,如果transferdata等于PENDING,那么还要transferdatacomplet。
通知miniport数据已经全部上来了。
在transferdata之前我们可以先申请pbakcontext,offsetbuffer,mypacket,把先传上来的raw数据
放在mypacket中。然后我们再申请一个ppacketbuffer,buffer,natpacket来存放接下来要transfer的
data。
如果transferdata返回了NDIS―STATUS-SUCCESS,那么立刻释放我们的资源,否则的话:
在ptsendcomplete中释放


4。miniport调用NDISINDICATEpacket,并且包的状态不是RESOURCE,那么miniport将复制一份packet
给上层的ptreceivepacket,那么意味着我们可以在ptreceivepacket中对包进行任意修改。

//好久没写过这么长了,辛苦啊.
//有些地方可能有漏洞,欢迎大家指出来
你说的就是第一种情况了.因为你的是老网卡,或者不需要OOB数据.
底层认为只要传上来一些原始数据就可以了,所以没有组包.
第1.2.3种都在Ptreceive中.
第4种在ptreceivepacket中
asmsys
驱动老牛
驱动老牛
  • 注册日期2002-03-29
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望17点
  • 贡献值0点
  • 好评度8点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2004-04-02 09:32
这好象是压水管的同志写的,很明白呀。如果这也看不动,那就先啃几天DDK在说了。
darkread
驱动牛犊
驱动牛犊
  • 注册日期2003-01-13
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2004-04-02 13:19
darkread
驱动牛犊
驱动牛犊
  • 注册日期2003-01-13
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2004-04-02 16:18
是不是说,如果是情况1,那么“我们可以立即对数据进行组包”,在哪里啊,
如果是情况3,上来的数据应该是一个miniport的拷贝吧?

我花了一张图
        protocol    
                        \
            |              IMD

         MINIPORT       /

IMD的作用是监管的作用而不是像下面这个图
       PROTOCOL
         |
        IMD
         |
      MINIPORT
所以的数据都是经过IMD传给PROTOCOL对吗?
因为我在资料上看到这么一段话
- - 207
“如果NIC 驱动程序调用了NdisMXxxIndicate 函数,那么驱动程序将总是调用
ProtocolReceive 函数来处理接收数据包。如果中间层驱动程序接受该数据包的话,
ProtocolReceive 必须以包描述符为参数调用NdisTransferData 函数,复制前视缓冲区及包的
其余部分到中间层驱动程序已分配的缓冲区。NdisTransferData 必须在ProtocolReceive 环境
中调用,而且只能调用一次。中间层驱动程序应该设置拥有足够尺寸的链式缓冲区包描述
符来保存所有的接收数据。当NdisTransferData 返回之后,从低层NIC 驱动程序接收来的
数据将不再有用。”

那么,为什么passthru中的PtReceive()没有这NdisTransferData
网络仍然正常,是不是只是一个Indicate的作用,指示上层的驱动收取数据包,感觉这样是有点说不通的,但是有不知道该怎么解释了,
asmsys,帮忙解答一下吧,学着学着就卡住了
asmsys
驱动老牛
驱动老牛
  • 注册日期2002-03-29
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望17点
  • 贡献值0点
  • 好评度8点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2004-04-02 16:29
是一个Indicate的作用。
他告诉上层PROTOCOL,你调用NdisTransferData吧,这是包的情况。
当上层PROTOCOL调用NdisTransferData的时候,会引发MpTransferData的调用,MpTransferData会调用NdisTransferData。结果还是在IMD调用NdisTransferData。
darkread
驱动牛犊
驱动牛犊
  • 注册日期2003-01-13
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2004-04-02 17:57
当上层PROTOCOL调用NdisTransferData的时候,会引发MpTransferData的调用,MpTransferData会调用NdisTransferData。
NdisTransferData引发MpTransferData
MpTransferData-->NdisTransferData
这个不是循环调用了吗?

asmsys
驱动老牛
驱动老牛
  • 注册日期2002-03-29
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望17点
  • 贡献值0点
  • 好评度8点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2004-04-02 18:00
靠,MICROSOFT有那吗傻吗。
NdisTransferData其实是一个宏,你看NDIS。H
darkread
驱动牛犊
驱动牛犊
  • 注册日期2003-01-13
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2004-04-02 19:57
你说的是不是这个啊
#define NdisTransferData(Status, \
NdisBindingHandle, \
MacReceiveContext, \
ByteOffset, \
BytesToTransfer, \
Packet, \
BytesTransferred) \
{ \
*(Status) = \
(((PNDIS_OPEN_BLOCK)(NdisBindingHandle))->TransferDataHandler)( \
((PNDIS_OPEN_BLOCK)(NdisBindingHandle))->MacBindingHandle, \
(MacReceiveContext), \
(ByteOffset), \
(BytesToTransfer), \
(Packet), \
(BytesTransferred)); \
}
不过上面还有这样的一个东东啊

NdisTransferData(
OUT PNDIS_STATUS Status,
IN NDIS_HANDLE NdisBindingHandle,
IN NDIS_HANDLE MacReceiveContext,
IN UINT ByteOffset,
IN UINT BytesToTransfer,
IN OUT PNDIS_PACKET Packet,
OUT PUINT BytesTransferred
);

它又是声明又是宏定义的,这是怎么回事啊
darkread
驱动牛犊
驱动牛犊
  • 注册日期2003-01-13
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2004-04-04 11:38
是不是可以这样认为
上层Protocol调用NdisTransferData引发IMD的miniport的MPTransferData,然后在MPTransferData中调用
NdisTransferData(&Status,
pAdapt->BindingHandle,
MiniportReceiveContext,
ByteOffset,
BytesToTransfer,
Packet,
BytesTransferred);  
这个地方的pAdapt->BindingHandle中,pAdapt指的是什么?IMD的miniport还是,真正网卡的Miniport?BindingHandle又指的是什么是IMD Miniport的绑定的的什么呢还是,IMD protocol绑定的真实网卡的句柄
我的猜想是BindingHandle应该是真实网卡的句柄了,因为ndis.h中有这样的定义
#define NdisTransferData(Status, \
NdisBindingHandle, \
MacReceiveContext, \
ByteOffset, \
BytesToTransfer, \
Packet, \
BytesTransferred) \
{ \
*(Status) = \
(((PNDIS_OPEN_BLOCK)(NdisBindingHandle))->TransferDataHandler)( \
((PNDIS_OPEN_BLOCK)(NdisBindingHandle))->MacBindingHandle, \
(MacReceiveContext), \
(ByteOffset), \
(BytesToTransfer), \
(Packet), \
(BytesTransferred)); \
}
可见,如果BindingHandle是IMD Minport的句柄的话,那么根据#define的意思好像是在循环调用了,因此BindingHandle应该是真实网卡的miniport的句柄,那么pAdapt->BindingHandle中的pAdapt又应该是什么呢??ddk上是没没有的
我在胡老大的PtReceive的PacketSize < LookAheadBufferSize的情况下找到这样的一句
//调用NdisTransferData()把下面的数据调上来
NdisTransferData(&Status,pAdapt->BindingHandle,MacReceiveContext,LookAheadBufferSize,PacketSize-LookAheadBufferSize,MyPacket,&BytesTransferred);
这里的pAdapt的意思应该是IMD protocol吧
它的bindingHandle那么就是 真实网卡的miniport了

这个又说不通了,再看再passthru中的MPTransferData中的
NdisTransferData(&Status,
pAdapt->BindingHandle,
MiniportReceiveContext,
ByteOffset,
BytesToTransfer,
Packet,
BytesTransferred);
怎么解释呢,这个pAdapt是上层的Protocol传进来的,如果指的是上层的protocol,那么它的bindinghandle按照我上面的猜测就应该是IMD miniport,根据ndis.h中的定义那么应该调用的是IMD miniport的TransferDataHandle,那么不就又调用MPTransferData了吗??
奇怪啊
游客

返回顶部