jackieky
驱动牛犊
驱动牛犊
  • 注册日期2004-02-10
  • 最后登录2004-08-13
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:3446回复:21

关于在ptreceive中数据包的转发问题,各位大侠帮帮忙了

楼主#
更多 发布于:2004-06-04 21:58
我在做一个网关,所以需要在ptreceive中作数据的转发。我用了两种办法,但是都不理想。方法一的运行结果是:当内网机器联网时,可以打开网页,上网等,不过只能在不到半分钟的时间之内。然后网关机就死机了。不知为何。下面是我的部分代码:
PtReceive(
IN  NDIS_HANDLE ProtocolBindingContext,
IN  NDIS_HANDLE MacReceiveContext,
IN  PVOID HeaderBuffer,
IN  UINT HeaderBufferSize,
IN  PVOID LookAheadBuffer,
IN  UINT LookAheadBufferSize,
IN  UINT PacketSize
)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
PNDIS_PACKET MyPacket, Packet;
NDIS_STATUS ntStatus,Status;
PNDIS_BUFFER    pPacketBuffer,pBakBuffer;

PUCHAR pPacketContent,pBakContent;
UINT            PacketBufferLen;
PIPHeader       pIPHeader;
PUDPHeader      pUDPHeader;
PTCPHeader      pTCPHeader;
PRSVD Rsvd;

ntStatus = NdisAllocateMemory(&pPacketContent,2000,0,HighestAcceptableMax);
if(ntStatus != NDIS_STATUS_SUCCESS)
{
return ntStatus;
}
NdisZeroMemory(pPacketContent,2000);
//将数据包的内容全部拷贝到pPacketContent中
NdisMoveMemory(
pPacketContent,
HeaderBuffer,
HeaderBufferSize
);
NdisMoveMemory(
pPacketContent+HeaderBufferSize,
LookAheadBuffer,
PacketSize//注意:在此我用的不是lookaheadbuffersize,而是packetsize,因为在我这里,我注意到好像packetsize总是>=lookaheadbuffersize,所以我就用packetsize拷贝整个数据包了,我曾经作过一个测试,在微软的passthru里加上这段代码,将这片内存的数据打印出来,和sniffer截获的数据是一模一样的,所以我想这个时候整个数据包的内容都在pPacketContent里了
);

//对给网关机的数据的处理在此不写了,那个是好的,我测试过
//下面是对需要进行转发,需要进行NAT的数据的处理
//修改MAC地址,IP头,TCP头,各个校验和等,经过测试这些都是正确的,下面是重新封包的处理。我想主要问题就处在这了
NdisAllocatePacket(&Status, &MyPacket, pAdapt->SendPacketPoolHandle);

if (Status != NDIS_STATUS_SUCCESS)
{
DbgPrint(\"allocate packet failed\\n\");
return(Status);
}
NdisAllocateBuffer(&Status,
&pPacketBuffer,
pAdapt->SendBufferPoolHandle,
pPacketContent,
PacketBufferLen
);

if (Status != NDIS_STATUS_SUCCESS)
{
DbgPrint(\"allocate buffer failed\\n\");
return(Status);
}
        
DbgPrint(\"\\n copy packet\\n\");

NdisChainBufferAtFront( MyPacket, pPacketBuffer);
Rsvd = (PRSVD)(MyPacket->ProtocolReserved);
Rsvd->OriginalPkt = NULL;
MyPacket->Private.Head->Next=NULL;
MyPacket->Private.Tail=NULL;
NdisSetPacketFlags(MyPacket, NDIS_FLAGS_DONT_LOOPBACK);
NdisSend(&Status, pAdapt->BindingHandle, MyPacket);//发送

if (Status != NDIS_STATUS_PENDING)
 {
DbgPrint(\"\\n Status != NDIS_STATUS_PENDING\\n\");
NdisIMCopySendCompletePerPacketInfo (Packet, MyPacket);
NdisUnchainBufferAtFront(MyPacket ,&pPacketBuffer);
NdisQueryBufferSafe(pPacketBuffer,(PVOID *)&pPacketContent,&PacketBufferLen,32);
NdisFreeBuffer(pPacketBuffer);
NdisFreeMemory(pPacketContent,2000,0);
NdisDprFreePacket(MyPacket);

 }
 return(Status);
}
这种方法的大致思路就是,先把包的数据全部拷贝到内存区,然后再分配buffer,packet,然后就直接转发出去。当程序运行的时候,内网机器只能上一会(不到半分钟)但是还是可以打开几个网页的。不知道这是什么问题引起的,我想可能是资源处理不当引起的,但是我看了好像我申请的资源我都释放了
下面是mpsendcomplete函数;
VOID
PtSendComplete( NDIS_HANDLE ProtocolBindingContext ,
  PNDIS_PACKET Packet , NDIS_STATUS Status)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
PNDIS_PACKET Pkt;
UINT i;
PUCHAR pPacketContent;
PNDIS_BUFFER PacketBuffer;
PRSVD Rsvd;
UINT PacketLen;
UINT bufLength;

NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress;
HighestAcceptableAddress.LowPart = -1;
HighestAcceptableAddress.HighPart = -1;


pAdapt = pAdapt->pPrimaryAdapt;
Rsvd =(PRSVD)(Packet->ProtocolReserved);
Pkt = Rsvd->OriginalPkt;//自己分配包的时候已经把原来的包放在这里面了

if(Pkt) NdisIMCopySendCompletePerPacketInfo (Pkt, Packet);

NdisUnchainBufferAtFront(Packet,&PacketBuffer);
NdisQueryBufferSafe(PacketBuffer,(PVOID *)&pPacketContent,&bufLength,32);

NdisFreeBuffer(PacketBuffer);
NdisFreeMemory(pPacketContent,bufLength,0);
NdisDprFreePacket(Packet); //释放

if(pAdapt->MiniportHandle)
{
if(Pkt)
{
NdisMSendComplete(pAdapt->MiniportHandle, Pkt, Status);
}
}
}
我在包的发送模块里面的重新封包的思路和这里是一样的,然后当Status == NDIS_STATUS_PENDING时就进入这个函数,发掘系统也是运行正常的,所以我认为这个函数处理好像也没有多大问题。
但是整个系统的运行情况让我感到不解,为何内网机器能上一会?然后网关才死机?还请各位大侠指点指点,在此谢谢了

最新喜欢:

wingmanwingma...
jackieky
驱动牛犊
驱动牛犊
  • 注册日期2004-02-10
  • 最后登录2004-08-13
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2004-06-04 22:20
我的方案二的思路是:先不是将整个数据包拷贝到一个内存,而是先将HeaderBuffer和LookAheadBuffer拷贝出来作为firstbuffer,然后对于packetsize>loolaheadbuffersize的数据包用NdisTransferData将剩余的数据拷贝出来组成一个包mypacket,再由ndissend转发出去,但是我用其他的监控机器查看进出网关机的数据包时,对于其他一些packetsiz<=loolaheadbuffersize的数据包按预定计划都给发出去了,但是对于packetsize>loolaheadbuffersize的这些包,并没有被检测到,也就是说这些报并没有被转发出去,我想是不是在用NdisTransferData的时候被直接送给系统了然后直接返回了!如果是这样的话,当然不会执行后面的ndissend了。
下面是我方案二的部分代码:
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
)
{
//拷贝HeaderBuffer和LookAheadBufferSize到pPacketContent
ntStatus = NdisAllocateMemory(&pPacketContent,2000,0,HighestAcceptableMax);
if(ntStatus != NDIS_STATUS_SUCCESS)
{
return ntStatus;
}
NdisZeroMemory(pPacketContent,2000);

NdisMoveMemory(
pPacketContent,
HeaderBuffer,
HeaderBufferSize
);
NdisMoveMemory(
pPacketContent+HeaderBufferSize,
LookAheadBuffer,
LookAheadBufferSize
);

//对需要转发的包对包头进行修改,重新校验和等
if(PacketSize<=LookAheadBufferSize)
{
//当PacketSize<=LookAheadBufferSize时,数据包能够正确的转发出去
DbgPrint(\"PacketSize<=LookAheadBufferSize\");
NdisAllocatePacket(&Status, &MyPacket, pAdapt->SendPacketPoolHandle);

if (Status != NDIS_STATUS_SUCCESS)
{
DbgPrint(\"allocate packet failed\\n\");
return(Status);
}
NdisAllocateBuffer(&Status,
&pPacketBuffer,
pAdapt->SendBufferPoolHandle,
pPacketContent,
PacketBufferLen
);

if (Status != NDIS_STATUS_SUCCESS)
{
DbgPrint(\"allocate buffer failed\\n\");
return(Status);
}
        
DbgPrint(\"\\n copy packet\\n\");

NdisChainBufferAtFront( MyPacket, pPacketBuffer);
Rsvd = (PRSVD)(MyPacket->ProtocolReserved);
Rsvd->OriginalPkt = NULL;
MyPacket->Private.Head->Next=NULL;
MyPacket->Private.Tail=NULL;
NdisSetPacketFlags(MyPacket, NDIS_FLAGS_DONT_LOOPBACK);//自己定义的包
NdisSend(&Status, pAdapt->BindingHandle, MyPacket);//发送
//PrintPacket(MyPacket);
DbgPrint(\"\\n copy packet over\\n\");

if (Status != NDIS_STATUS_PENDING)
 {
DbgPrint(\"\\n Status != NDIS_STATUS_PENDING\\n\");
NdisIMCopySendCompletePerPacketInfo (Packet, MyPacket);
NdisUnchainBufferAtFront(MyPacket ,&pPacketBuffer);
NdisQueryBufferSafe(pPacketBuffer,(PVOID *)&pPacketContent,&PacketBufferLen,32);
NdisFreeBuffer(pPacketBuffer);
NdisFreeMemory(pPacketContent,2000,0);
NdisDprFreePacket(MyPacket);

 }
 return(Status);
}
 else
 {    
//当PacketSize>LookAheadBufferSize时数据包没有转发出去,我怀疑是NdisTransferData句的问题,不知道他是不是将数据包直接给上层,然后直接返回了?
NdisDprAllocatePacket(&Status,&MyPacket,pAdapt->RecvPacketPoolHandle);

Status=NdisAllocateMemory(&pBakContent,BUFFER_SIZE,0,HighestAcceptableMax);
if(Status!=NDIS_STATUS_SUCCESS)
{
DbgPrint(\"PtReceive:NdisAllocateMemory Failed.\\n\");
return(NDIS_STATUS_NOT_ACCEPTED);
}
NdisZeroMemory(pBakContent,BUFFER_SIZE);
if(pBakContent==NULL)
{
DbgPrint(\"PTReceive:pPacketContent==NULL\\n\");
return(NDIS_STATUS_NOT_ACCEPTED);
}
// NdisZeroMemory(pBakContent,BUFFER_SIZE);
// NdisMoveMemory(pBakContent,HeaderBuffer,HeaderBufferSize);
// NdisMoveMemory(pBakContent+HeaderBufferSize,LookAheadBuffer,LookAheadBufferSize);
PacketLen=HeaderBufferSize+PacketSize;
NdisAllocateBuffer(&Status,&pBakBuffer,pAdapt->RecvBufferPoolHandle,pBakContent,PacketSize-LookAheadBufferSize);

NdisChainBufferAtFront(MyPacket,pBakBuffer);
MyPacket->Private.Head->Next=NULL;
MyPacket->Private.Tail=NULL;

OffsetSize=HeaderBufferSize+LookAheadBufferSize;

NdisDprAllocatePacket(&Status,&MyPacket1,pAdapt->RecvPacketPoolHandle);
NdisAllocateBuffer(&Status,&pPacketBuffer,pAdapt->RecvBufferPoolHandle,pPacketContent,OffsetSize);
NdisChainBufferAtFront(MyPacket1,pPacketBuffer);

Rsvd=(PRSVD)(MyPacket->MiniportReserved);
Rsvd->OriginalPkt=(PNDIS_PACKET)MyPacket1;

NDIS_SET_PACKET_HEADER_SIZE(MyPacket,HeaderBufferSize);

//不知道是不是这个地方出问题了。调用NdisTransferData 后系统是不是直接返回了?而不再执行后面的NdisSend(&Status, pAdapt->BindingHandle, MyPacket);?? NdisTransferData(&Status,pAdapt->BindingHandle,MacReceiveContext,LookAheadBufferSize,PacketSize-LookAheadBufferSize,MyPacket,&BytesTransferred);
// if(Status!=NDIS_STATUS_PENDING)
// {
// PtTransferDataComplete((NDIS_HANDLE)pAdapt,MyPacket,Status,BytesTransferred);
// }
NdisSend(&Status, pAdapt->BindingHandle, MyPacket);//发送

if (Status != NDIS_STATUS_PENDING)
 {
DbgPrint(\"\\n Status != NDIS_STATUS_PENDING\\n\");
// NdisIMCopySendCompletePerPacketInfo (Packet, MyPacket);
NdisUnchainBufferAtFront(MyPacket ,&pPacketBuffer);
NdisQueryBufferSafe(pPacketBuffer,(PVOID *)&pPacketContent,&PacketBufferLen,32);
NdisFreeBuffer(pPacketBuffer);
NdisFreeMemory(pPacketContent,2000,0);
NdisDprFreePacket(MyPacket);

NdisUnchainBufferAtFront(MyPacket1 ,&pBakBuffer);
NdisQueryBufferSafe(pBakBuffer,(PVOID *)&pBakContent,&PacketBufferLen,32);
NdisFreeBuffer(pBakBuffer);
NdisFreeMemory(pBakContent,2000,0);
NdisDprFreePacket(MyPacket1);

 }
return(Status);
}
各位大侠帮帮忙了,谢谢了
asmsys
驱动老牛
驱动老牛
  • 注册日期2002-03-29
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望17点
  • 贡献值0点
  • 好评度8点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2004-06-05 10:29
注意:在此我用的不是lookaheadbuffersize,而是packetsize,因为在我这里,我注意到好像packetsize总是>=lookaheadbuffersize,所以我就用packetsize拷贝整个数据包了,我曾经作过一个测试,在微软的passthru里加上这段代码,将这片内存的数据打印出来,和sniffer截获的数据是一模一样的,所以我想这个时候整个数据包的内容都在pPacketContent里了
=========================================================
这种假设绝对不合理。发一个PING包看看。
而且packetsize>=lookaheadbuffersize时,你不可能一次COPY完。
必须调用NdistransferData来取得剩余的数据。本来没有那么多数据,却要COPY那么多数据,不死机还干什么。

[编辑 -  6/5/04 by  asmsys]
asmsys
驱动老牛
驱动老牛
  • 注册日期2002-03-29
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望17点
  • 贡献值0点
  • 好评度8点
  • 原创分0分
  • 专家分0分
地板#
发布于:2004-06-05 10:48
//不知道是不是这个地方出问题了。调用NdisTransferData 后系统是不是直接返回了?而不再执行后面的NdisSend(&Status, pAdapt->BindingHandle, MyPacket);?? NdisTransferData(&Status,pAdapt->BindingHandle,MacReceiveContext,LookAheadBufferSize,PacketSize-LookAheadBufferSize,MyPacket,&BytesTransferred);
// if(Status!=NDIS_STATUS_PENDING)
// {
// PtTransferDataComplete((NDIS_HANDLE)pAdapt,MyPacket,Status,BytesTransferred);
// }
NdisSend(&Status, pAdapt->BindingHandle, MyPacket);//发送

============================================================
此处你并没有把NdisTransferData 得到的数据放到你的包中,自然包的校验和不对被丢弃了。而且NdisTransferData 的参数也不对。
ljjlovernet
驱动小牛
驱动小牛
  • 注册日期2003-10-10
  • 最后登录2004-12-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2004-06-05 10:49
if (Status != NDIS_STATUS_PENDING)
{
===========================================
此时也应当调用NdsiSend.
我是来学习的。不打扫卫生
jackieky
驱动牛犊
驱动牛犊
  • 注册日期2004-02-10
  • 最后登录2004-08-13
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2004-06-05 10:52
呵呵,是asmsys大侠呀,谢谢了:)
在我这一个ping包才74个字节,这个时候packetsize==lookaheadbuffersize的,所以内网机器不管怎么ping外网机器网关并没有死机。而是当包的长度很大的时候(只要大于142个字节的时候)问题就出现了,这个时候packetsize>lookaheadbuffersize
还有关于是否能一次copy完,做过测试,好像当包的长度为1514的时候,我打印出来的内存和sniffer监控得到的结果是一致的,这个不能表明得到了全部数据包的内容吗?

最后关于ndistransferdata,我在方案二中用过,但是我用了以后,再用ndissend就一点作用都没有了,这个时候packetsize>lookaheadbuffersize的包怎么也发不出去。不知为什么?
jackieky
驱动牛犊
驱动牛犊
  • 注册日期2004-02-10
  • 最后登录2004-08-13
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2004-06-05 11:04
谢谢 ljjlovernet 我等下试试,但是如果Status == NDIS_STATUS_PENDING呢?那我的包怎么发出去?我的资源怎么回收呀?
还有asmsys大佬,呵呵,一眼就看出了,是的,确实应该重新校验和了:)
但是我监控的是另外一台机器,即使校验和出错,但终究还是转发出去了呀!应该就在我这台监控的机器上会显示出来的,只不过在校验和字段的后面加个注释(校验和错误。校验和should be ....),但是我并没有看到这个错误的包被转发出来!我想程序根本就没有运行ndissend这行,所以也就没有转发了
还有NdisTransferData(&Status,pAdapt->BindingHandle,MacReceiveContext,LookAheadBufferSize,PacketSize-LookAheadBufferSize,MyPacket,&BytesTransferred);
这个函数不是直接把剩余的数据拷贝到mypacket了吗?也就是放到mypacket的了吗?


[编辑 -  6/5/04 by  jackieky]
jackieky
驱动牛犊
驱动牛犊
  • 注册日期2004-02-10
  • 最后登录2004-08-13
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2004-06-05 11:13
还有asmsys你说的ndistransfer的参数不对,是不是指的NdisTransferData(&Status,pAdapt->BindingHandle,MacReceiveContext,LookAheadBufferSize,PacketSize-LookAheadBufferSize,MyPacket,&BytesTransferred);
这里面的LookAheadBufferSize?是不是应该改为LookAheadBufferSize+HeaderBufferSize?

youngyt
驱动牛犊
驱动牛犊
  • 注册日期2003-11-23
  • 最后登录2006-12-29
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2004-06-05 22:58
这是PacketSize > LookAheadBufferSize的情况下的处理


DbgPrint("In ptreceive PacketSize > LookAheadBufferSize\n");
Status = NdisAllocateMemory(&pPacketContent,BUFFER_SIZE,0,HighestAcceptableAddress);
if (Status != NDIS_STATUS_SUCCESS )
{
return NDIS_STATUS_NOT_ACCEPTED;
}
if (pPacketContent == NULL)
{
return NDIS_STATUS_NOT_ACCEPTED;
}
RtlZeroMemory(pPacketContent, BUFFER_SIZE );

NdisDprAllocatePacket(&Status,&MyPacket,pAdapt->RecvPacketPoolHandle);

//再申请一个备份后方缓冲区
NdisAllocateMemory(&pBakContent,BUFFER_SIZE,0,HighestAcceptableAddress);
if(Status != NDIS_STATUS_SUCCESS)
{
DbgPrint("ptreceive:allcate bak buffer failed\n");
return NDIS_STATUS_NOT_ACCEPTED;
}

//将已经获得的数据拷贝到pakBuffer
NdisMoveMemory(pBakContent,HeaderBuffer,HeaderBufferSize);
NdisMoveMemory(pBakContent+HeaderBufferSize,LookAheadBuffer,LookAheadBufferSize);

//整个数据包长,但此处只有一部分
PacketLen = HeaderBufferSize + PacketSize;

//
//对于还没有获得的数据,则重新申请空间,生成请求Packet
//从NdisTransferData再次获得数据
NdisAllocateBuffer(&Status,
&PacketBuffer,
pAdapt->RecvPacketPoolHandle,
pPacketContent,
PacketSize-LookAheadBufferSize);
NdisChainBufferAtFront( MyPacket, PacketBuffer );
MyPacket->Private.Head->Next = NULL;
MyPacket->Private.Tail = NULL;

//
// 把本处得到的所有数据存放在MyPacket2包描述符中
//
OffsetSize = HeaderBufferSize + LookAheadBufferSize;
NdisDprAllocatePacket(&Status,
 &MyPacket2,
 pAdapt->RecvPacketPoolHandle);
NdisAllocateBuffer(&Status,
&OffsetBuffer,
pAdapt->RecvPacketPoolHandle ,
pBakContent,
OffsetSize);
NdisChainBufferAtFront(MyPacket2,OffsetBuffer);

//
// 把packet保留packet为已在此收到的数据
//
Resvd =(PRECV_RSVD)(MyPacket->MiniportReserved);
Resvd->OriginalPkt = (PNDIS_PACKET)MyPacket2;

NDIS_SET_PACKET_HEADER_SIZE( MyPacket, HeaderBufferSize );
//
//通知下层发送没有发送完的部分数据
//
NdisTransferData(&Status,
pAdapt->BindingHandle,
MacReceiveContext,
LookAheadBufferSize,
PacketSize-LookAheadBufferSize ,
MyPacket,
&BytesTransferred);

if ( Status != NDIS_STATUS_PENDING )
{
DbgPrint("High layer call PtTransferDataComplete\n");
//传输完毕,直接调用PtTransferDataComplete
PtTransferDataComplete( (NDIS_HANDLE)pAdapt, MyPacket, Status, BytesTransferred );
}
else
{
//没有传输完毕,则等着传输完后系统自己调用PtTransferDataComplete
//DbgPrint("PtRecv:NdisTransferDataPending!\n");
DbgPrint("Own call PtTransferDataComplete\n");
}
break;
}




然后在ptTransferDataComplete里:
DbgPrint("In PtTransferDataComplete!\n");

Resvd = (PRECV_RSVD)(Packet->MiniportReserved);
OffsetPacket = (PNDIS_PACKET)Resvd->OriginalPkt;

if(pAdapt->MiniportHandle)
{
if (OffsetPacket == NULL)
{
//如果为空,则说明不是自己请求的传输动作,直接调用结束即可
NdisMTransferDataComplete(pAdapt->MiniportHandle,Packet,Status,BytesTransferred);
}
else
{
//
//分配内存并把所有数据copy到pPacketContent内存中
//
status = NdisAllocateMemory(&pPacketContent,BUFFER_SIZE,0,HighestAcceptableAddress);
if (status != NDIS_STATUS_SUCCESS )
{
DbgPrint("allocatememory failed\n");
return;
}
if(pPacketContent == NULL)
{
DbgPrint("pPacketContent == NULL\n");
return;
}
//
//把所有数据全部copy到分配的内存pPacketContent中
//
CopyPacket2Buffer(OffsetPacket,pPacketContent,&OffsetSize);
CopyPacket2Buffer(Packet,pPacketContent+OffsetSize,&PacketLen);
PacketLen = PacketLen+OffsetSize;

//释放packet,也就是ptReceive中创建的MyPakcet的数据内存,但不释放
//包描述符
NdisUnchainBufferAtFront(Packet,&PacketBuffer );
NdisQueryBufferSafe(PacketBuffer,&pBakContent,&bufLength,32);
NdisFreeBuffer(PacketBuffer);
NdisFreeMemory(pBakContent,BUFFER_SIZE,0);

// 手动释放原来的offsetpacket
NdisUnchainBufferAtFront( OffsetPacket,&OffsetBuffer );
NdisQueryBufferSafe(OffsetBuffer,&pBakContent,&bufLength, 32 );
NdisFreeBuffer(OffsetBuffer);
NdisFreeMemory(pBakContent,BUFFER_SIZE,0);
NdisFreePacket(OffsetPacket);
}


仔细阅读!用在纸上画出内存分配图,一目了然。
jackieky
驱动牛犊
驱动牛犊
  • 注册日期2004-02-10
  • 最后登录2004-08-13
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2004-06-06 09:17
youngyt:谢谢了,谢谢你的多次相助!
在程序中我有点不明白.就是在ptTransferDataComplete里把内存都给释放掉了,留着一个空的包的描述符干嘛?这样子我还能在ptreceive里用ndissend(mypacket)把这个包给发出去吗?
不过我先试试了
jackieky
驱动牛犊
驱动牛犊
  • 注册日期2004-02-10
  • 最后登录2004-08-13
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2004-06-06 19:38
youngyt,我今天用你的代码测试了,修改了ptTransferDataComplete
和ptreceive但是还是不行,没有修改ptTransferDataComplete时,我在NdisTransferData(&Status,pAdapt->BindingHandle,MacReceiveContext,LookAheadBufferSize,PacketSize-LookAheadBufferSize,MyPacket,&BytesTransferred);后打印了mypacket发现里面的内容都乱七八糟的,但是我打印了MyPacket1,这个里面的内容是正确的,是包的前部分内容,其中
Rsvd=(PRSVD)(MyPacket->MiniportReserved);
Rsvd->OriginalPkt=(PNDIS_PACKET)MyPacket1;

如果对ptTransferDataComplete作了相应的修改以后,内网机器一发包,网关就立刻重起了。我看了你的ptTransferDataComplete发现里面的内存缓冲区pBakContent没有分配就直接使用了,这个是不是有可能导致重起?还有另外一些未分配的buffer,未申请就直接使用了。但是我修改了以后系统还是重起。再说我现在也不是很明白为什么这么修改。听说你也在华工,我就住在紫菘。什么时候有时间能否当面请教一二?我不胜感激!
youngyt
驱动牛犊
驱动牛犊
  • 注册日期2003-11-23
  • 最后登录2006-12-29
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2004-06-08 09:17
怎么会呢?
在PTRECEIVE中有:

//再申请一个备份后方缓冲区
NdisAllocateMemory(&pBakContent,BUFFER_SIZE,0,HighestAcceptableAddress);
if(Status != NDIS_STATUS_SUCCESS)
{
DbgPrint("ptreceive:allcate bak buffer failedn");
return NDIS_STATUS_NOT_ACCEPTED;
}

代码不是完整的,所以有些地方没有分配的你自己要分配。
我住在C16-321

jackieky
驱动牛犊
驱动牛犊
  • 注册日期2004-02-10
  • 最后登录2004-08-13
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2004-06-08 12:44
那些我都分配了,不过老是出问题,现在碰到1500B的数据包网关就重新启动了。
中午到你寝室找你,你去吃饭去了
不知道你什么时候有空。
jackieky
驱动牛犊
驱动牛犊
  • 注册日期2004-02-10
  • 最后登录2004-08-13
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2004-06-08 21:00
现在是可以了,但是网关只能持续3分钟的样子,然后就死机了
我这用的是实达的认证上网的,好像他的认证服务器不允许一个端口有多个IP,因为我的网关配置了多个IP,所以第一次连上去后,过了两分钟就被认证服务器给踢出来了.当我再次连上去的时候,过了不到一分钟系统就死掉了,不知道是怎么回事
什么时候有时间是否能当面指教一二?

还有,别忘了!我开了一个新帖子的-----胡大侠,asmsys,youngyt各位版主,大侠帮帮忙了   过去拿分了:)
youngyt
驱动牛犊
驱动牛犊
  • 注册日期2003-11-23
  • 最后登录2006-12-29
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
14楼#
发布于:2004-06-09 14:22
802.3的最大包长度是1500字节,包括那些MAC、IP、TCP头的长度。长了要分片~~~论坛里有胡老大的分片代码。

这星期我值班,所以回去的晚,你什么时候答辩。
jackieky
驱动牛犊
驱动牛犊
  • 注册日期2004-02-10
  • 最后登录2004-08-13
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
15楼#
发布于:2004-06-09 23:44
这个周日:(
youngyt
驱动牛犊
驱动牛犊
  • 注册日期2003-11-23
  • 最后登录2006-12-29
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
16楼#
发布于:2004-06-10 18:11
明天中午12点半后我在寝室等你。
jackieky
驱动牛犊
驱动牛犊
  • 注册日期2004-02-10
  • 最后登录2004-08-13
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
17楼#
发布于:2004-06-10 20:11
好的 谢谢!
jackieky
驱动牛犊
驱动牛犊
  • 注册日期2004-02-10
  • 最后登录2004-08-13
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
18楼#
发布于:2004-06-10 20:14
呵呵 看来有救了:)
jackieky
驱动牛犊
驱动牛犊
  • 注册日期2004-02-10
  • 最后登录2004-08-13
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
19楼#
发布于:2004-06-11 13:08
youngyt谢谢了 答辩完后请你吃饭:)
上一页
游客

返回顶部