阅读:1834回复:12
NDIS中,在哪里接收封包的啊?
我用的是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] |
|
沙发#
发布于:2004-04-01 17:13
你可以研究一下ddk,ptReceive和ptReceivePacket函数如何调用,
由miniport driver的调用的函数决定,如果miniport driver调用 NdisXXXReceivePacket,则ndis调用ptReceivePacket函数,如果调用NdisXXXIndicateReceive,则调用ptReceive |
|
|
板凳#
发布于:2004-04-01 17:24
这里有例子,找。
|
|
地板#
发布于:2004-04-01 18:04
可是无论如何,这里的两个函数好像都不起作用啊
麻烦就麻烦在这里 PtReceivePacket()是根本不调用的 PtReceive()一进去 Packet = NdisGetReceivedPacket(pAdapt->BindingHandle, MacReceiveContext); //应该是在这里得到数据包吧,但是然后判断 if(Packet != NULL) { DBGPRINT("===================> 7 <==================="); } //这句总是不会成功的,这个意思是不是就是说Get不到ReceivedRacket了呢,但是网络一直是正常的,数据包到底是在哪里得到然后上传的啊 |
|
地下室#
发布于: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中 |
|
5楼#
发布于:2004-04-02 09:32
这好象是压水管的同志写的,很明白呀。如果这也看不动,那就先啃几天DDK在说了。
|
|
6楼#
发布于:2004-04-02 13:19
晕
|
|
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,帮忙解答一下吧,学着学着就卡住了 |
|
8楼#
发布于:2004-04-02 16:29
是一个Indicate的作用。
他告诉上层PROTOCOL,你调用NdisTransferData吧,这是包的情况。 当上层PROTOCOL调用NdisTransferData的时候,会引发MpTransferData的调用,MpTransferData会调用NdisTransferData。结果还是在IMD调用NdisTransferData。 |
|
9楼#
发布于:2004-04-02 17:57
当上层PROTOCOL调用NdisTransferData的时候,会引发MpTransferData的调用,MpTransferData会调用NdisTransferData。
NdisTransferData引发MpTransferData MpTransferData-->NdisTransferData 这个不是循环调用了吗? |
|
10楼#
发布于:2004-04-02 18:00
靠,MICROSOFT有那吗傻吗。
NdisTransferData其实是一个宏,你看NDIS。H |
|
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 ); 它又是声明又是宏定义的,这是怎么回事啊 |
|
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了吗?? 奇怪啊 |
|