阅读:1487回复:3
NAT的资源释放问题,帮忙看看吧。
本人用passthru做的NAT中始终无法解决的一个问题:子网主机与NAT网关单独访问数据工作正常,
但当子网主机与NAT网关同时访问外部数据 时,NAT就死机(page fault:访问无效的系统资源或企图释放已经释放的池)。跟踪后发现总 是发生在PtTransferDataComplete()组完包后对 MPReturnPacket()的调用中,有老大告诉我 可能是不同步造成的。MPReturnPacket()应该 是NdisMIndicateReceivePacket()为pending 时的回调,代码也遵守了“谁申请谁释放”的原 则,不知如何同步,或有其他问题。下面是两个函数的代码(全部)。高手帮忙看看。 VOID PtTransferDataComplete( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet, IN NDIS_STATUS Status, IN UINT BytesTransferred ) /*++ Routine Description: Entry point called by NDIS to indicate completion of a call by us to NdisTransferData. See notes under SendComplete. Arguments: Return Value: --*/ { PADAPT OutAdapt,pAdapt = (PADAPT)ProtocolBindingContext; PUCHAR pPacketContent; PRSVD Rsvd,PRsvd=NULL; UINT OffsetSize, Result, PacketLen; PNDIS_BUFFER pPacketBuffer; PNDIS_PACKET pBakPacket; PNDIS_BUFFER pBakBuffer; PUCHAR pBakContent; UINT BufferLen; UINT CardInfo=0; UINT flags=0; //NAT转发标志 DbgPrint((\"In PtTransferDataComplete\\n\")); // // Returning the Send on the Primary, will point to itself if there is no LBFO // // pAdapt = pAdapt->pPrimaryAdapt; Rsvd = (PRSVD)(Packet->MiniportReserved); // pBakPacket 里是 HeaderBuffer + LookAheadBuffer 的内容。 pBakPacket = (PNDIS_PACKET)(Rsvd->OriginalPkt); if(pAdapt->MiniportHandle) { if(pBakPacket == NULL) NdisMTransferDataComplete(pAdapt->MiniportHandle, Packet, Status, BytesTransferred); else { Status = NdisAllocateMemory(&pPacketContent, BUFFER_SIZE, 0, HighestAcceptableMax); CopyPacket2Buffer(pBakPacket, pPacketContent, &OffsetSize); CopyPacket2Buffer(Packet, pPacketContent+OffsetSize, &PacketLen); PacketLen += OffsetSize; // 释放包描述符pBakPacket、缓冲描述符pBakBuffer、内存pBakContent。 NdisUnchainBufferAtFront(pBakPacket, &pBakBuffer); NdisQueryBufferSafe(pBakBuffer, &pBakContent, &BufferLen, 32); NdisFreeBuffer(pBakBuffer); NdisFreeMemory(pBakContent, BUFFER_SIZE, 0); NdisFreePacket(pBakPacket); memset(Packet->MiniportReserved, 0, sizeof(Packet->MiniportReserved)); NdisUnchainBufferAtFront(Packet, &pPacketBuffer); NdisQueryBufferSafe(pPacketBuffer, &pBakContent, &BufferLen, 32); NdisFreeBuffer(pPacketBuffer); NdisFreeMemory(pBakContent, BUFFER_SIZE, 0); ///////////NAT if( (((char*)pPacketContent)[12]==8&& ((char*)pPacketContent)[13]==0 ) || (((char*)pPacketContent)[12]==8&& ((char*)pPacketContent)[13]==6)) if(IpInfo.NatEnable==TRUE) { flags=CheckBuildPkt(pAdapt,pPacketContent,&CardInfo); } //////////////NAT NdisAllocateBuffer(&Status, &pPacketBuffer, pAdapt->RecvBufferPoolHandle, pPacketContent, PacketLen); NdisChainBufferAtFront(Packet, pPacketBuffer); Packet->Private.Head->Next=NULL; Packet->Private.Tail=NULL; NDIS_SET_PACKET_HEADER_SIZE(Packet,14); NdisSetPacketFlags(Packet,NDIS_FLAGS_DONT_LOOPBACK); if(flags==1) //进行转发 { PRsvd=(PRSVD)(Packet->ProtocolReserved); PRsvd->OriginalPkt=NULL; if(CardInfo==1) { for(OutAdapt=pAdaptList;OutAdapt!=NULL;OutAdapt=OutAdapt->Next) if(wcsncmp(OutAdapt->LowerDeviceName.Buffer,IpInfo.iDeviceName,wcslen(IpInfo.iDeviceName))==0) { NdisSend(&Status,OutAdapt->BindingHandle, Packet); } } else if(CardInfo==2) { for(OutAdapt=pAdaptList;OutAdapt!=NULL;OutAdapt=OutAdapt->Next) if(wcsncmp(OutAdapt->LowerDeviceName.Buffer,IpInfo.eDeviceName,wcslen(IpInfo.eDeviceName))==0) { NdisSend(&Status,OutAdapt->BindingHandle, Packet); } } if (Status != NDIS_STATUS_PENDING) { DbgPrint(\"this is senD finished!\\n\"); NdisFreeBuffer(pPacketBuffer); NdisFreeMemory(pPacketContent, BUFFER_SIZE, 0); NdisDprFreePacket(Packet); } else { DbgPrint(\"this is senD pending!\\n\"); } } else // 向上层协议驱动指示数据包,防真网卡行为。 { NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &Packet, 1); if(NDIS_GET_PACKET_STATUS(Packet)!=NDIS_STATUS_PENDING) { NdisFreeBuffer(pPacketBuffer); NdisFreeMemory(pPacketContent, BUFFER_SIZE, 0); NdisDprFreePacket(Packet); } else { } } } } return; } VOID MPReturnPacket( IN NDIS_HANDLE MiniportAdapterContext, IN PNDIS_PACKET Packet ) { PADAPT pAdapt = (PADAPT)MiniportAdapterContext; PNDIS_PACKET MyPacket; PRSVD Resvd; PNDIS_BUFFER pNdisBuffer; PUCHAR pPacketContent; UINT BufferLen; Resvd = (PRSVD)(Packet->MiniportReserved); MyPacket = Resvd->OriginalPkt; DBGPRINT((\"In MPReturnPacket()\\n\")); if(MyPacket) { NdisFreePacket(Packet); NdisReturnPackets(&MyPacket, 1); } else { NdisUnchainBufferAtFront(Packet,&pNdisBuffer); NdisQueryBufferSafe(pNdisBuffer,(PVOID *)&pPacketContent,&BufferLen,32); NdisFreeBuffer(pNdisBuffer); NdisFreeMemory(pPacketContent,BUFFER_SIZE,0); NdisFreePacket(Packet); } } [编辑 - 1/6/04 by lixiangying] |
|
沙发#
发布于:2004-01-07 13:20
没人帮忙呀,苦恼中。。。。
|
|
板凳#
发布于:2004-01-08 00:50
我觉得这段代码有问题,如果你的NAT程序是从Passthru 的基础上做的话,在Passthru中的PtReceive中同样也使用了NdisMIndicateReceivePacket 但没有用 Resvd = (PRSVD)(Packet->MiniportReserved);,所以你这里的NDISFreePacket必将引起出错。
若你在PtReceive中没用NdisMIndicateReceivePacket,我就无法分析了。 else { NdisUnchainBufferAtFront(Packet,&pNdisBuffer); NdisQueryBufferSafe(pNdisBuffer,(PVOID *)&pPacketContent,&BufferLen,32); NdisFreeBuffer(pNdisBuffer); NdisFreeMemory(pPacketContent,BUFFER_SIZE,0); NdisFreePacket(Packet); |
|
地板#
发布于:2004-01-08 12:56
我在ptreceive()中的两种情况中的确都用了ndismindicatepacket,并且
其MiniportReserved关联的OriginalPkt都设置为NULL.难道要在 mpreturnpacket()中区分加以释放吗?那又如何做呢。还望老兄 再指点一下。 |
|