lixiangying
驱动牛犊
驱动牛犊
  • 注册日期2002-05-03
  • 最后登录2007-09-09
  • 粉丝0
  • 关注0
  • 积分9分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
阅读:1436回复:3

NAT的资源释放问题,帮忙看看吧。

楼主#
更多 发布于:2004-01-06 18:59
本人用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]
lixiangying
驱动牛犊
驱动牛犊
  • 注册日期2002-05-03
  • 最后登录2007-09-09
  • 粉丝0
  • 关注0
  • 积分9分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2004-01-07 13:20
没人帮忙呀,苦恼中。。。。
xiongcs
驱动牛犊
驱动牛犊
  • 注册日期2003-12-17
  • 最后登录2004-03-21
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于: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);

lixiangying
驱动牛犊
驱动牛犊
  • 注册日期2002-05-03
  • 最后登录2007-09-09
  • 粉丝0
  • 关注0
  • 积分9分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
地板#
发布于:2004-01-08 12:56
我在ptreceive()中的两种情况中的确都用了ndismindicatepacket,并且
其MiniportReserved关联的OriginalPkt都设置为NULL.难道要在
mpreturnpacket()中区分加以释放吗?那又如何做呢。还望老兄
再指点一下。
游客

返回顶部