hxsyj
驱动牛犊
驱动牛犊
  • 注册日期2004-01-19
  • 最后登录2004-11-18
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1724回复:3

利用ptreceive转发包兰屏问题求教。

楼主#
更多 发布于:2004-09-14 17:28
各位好,我参考了论坛中的贴子,写了一个接收包,然后判断是否指定的ip,是的话,则将地址对调,重新发回,代码如下。
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;
//指向一个内存块指针,用于指向原帧内容
PUCHAR           pPacketContent;
//指向一个内存块指针,用于指向新帧内容
PUCHAR           pNewPacketContent;
//帧头
pEthHdr pEth;
    //IP头
pIPHdr  pIPH;
//IP头长度
USHORT usIPHdr;
//新帧负载长度
ULONG   ulNewPayload;
//新帧长度
ULONG   PacketBufferLen;
int j;
//网卡地址转换缓冲变量
char MACBuffer;
//交换IP用
ULONG chageIP;
//缓冲区指针
PNDIS_BUFFER pPacketBuffer;
PRSVD Rsvd;

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
//

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);
//***本程序的网卡Packet是NULL***
if(Packet != NULL)
{
//
// 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);

 ASSERT(NDIS_GET_PACKET_STATUS(MyPacket) == NDIS_STATUS_RESOURCES);
 NdisDprFreePacket(MyPacket);
 break;
}
}

//
// Fall through if the miniport below us has either not indicated a packet or we could not
// allocate one
//
pAdapt->IndicateRcvComplete = TRUE;
switch(pAdapt->Medium)
{
 case NdisMedium802_3:
 //****添加程序代码***
 Status=NdisAllocateMemory(&pPacketContent,2000,0,HighestAcceptableMax);
 if (Status!=NDIS_STATUS_SUCCESS)
 {
 DbgPrint("Allocate Memory pPacketContent Failn");
 return Status;
 }
 //清空内存块
 NdisZeroMemory(pPacketContent,2000);
 //获得原帧内容。注意:整个数据帧内容>=前视缓冲区内容
 NdisMoveMemory(pPacketContent,HeaderBuffer,HeaderBufferSize);
         NdisMoveMemory(pPacketContent+HeaderBufferSize,LookAheadBuffer,LookAheadBufferSize);
 //指定原帧帧头
         NdisSend(&Status,pAdapt->BindingHandle,MyPacket);
if(Status!=NDIS_STATUS_PENDING)
{
NdisIMCopySendCompletePerPacketInfo(Packet,MyPacket);
NdisUnchainBufferAtFront(MyPacket,&pPacketBuffer);
NdisQueryBufferSafe(pPacketBuffer,(PVOID*)&pNewPacketContent,&PacketBufferLen,32);
NdisFreeBuffer(pPacketBuffer);
NdisFreeMemory(pNewPacketContent,2000,0);
NdisFreeMemory(pPacketContent,2000,0);
NdisDprFreePacket(MyPacket);

}
break;


                 }//End if(PacketSize<=LookAheadBufferSize)

 }//End if ((pIPH->DestinationAddress==0x6667c4ca)&&(pIPH->SourceAddress==0x0c67c4ca))
 NdisFreeMemory(pPacketContent,2000,0);
 //***加入程序完毕***
 NdisMEthIndicateReceive(pAdapt->MiniportHandle,
MacReceiveContext,
HeaderBuffer,
HeaderBufferSize,
LookAheadBuffer,
LookAheadBufferSize,
PacketSize);
break;

 case NdisMedium802_5:
NdisMTrIndicateReceive(pAdapt->MiniportHandle,
MacReceiveContext,
HeaderBuffer,
HeaderBufferSize,
LookAheadBuffer,
LookAheadBufferSize,
PacketSize);
break;

 case NdisMediumFddi:
NdisMFddiIndicateReceive(pAdapt->MiniportHandle,
 MacReceiveContext,
 HeaderBuffer,
 HeaderBufferSize,
 LookAheadBuffer,
 LookAheadBufferSize,
 PacketSize);
break;

 default:
ASSERT(0);
break;
}

} while(FALSE);

return Status;
}
VOID
PtSendComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN  PNDIS_PACKET Packet,
IN  NDIS_STATUS Status
)
/*++

Routine Description:

Interesting case:
We wish to send all sends down the secondary NIC. But when we indicate to the protocol above,
we need to revert back to the original miniport that Protocol wished to use for the Send


Arguments:


Return Value:


--*/
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
PNDIS_PACKET Pkt;
PRSVD Rsvd;
//**add**
PNDIS_BUFFER    PacketBuffer;
PUCHAR          pPacketContent;
UINT            buferLength;

//NDIS_PHYSICAL_ADDRESS HighestAcceptableddress;
    //HighestAcceptableddress.LowPart=-1;
//HighestAcceptableddress.HighPart=-1;
   //***********


//
// Returning the Send on the Primary, will point to itself if there is no bundle
//
pAdapt = pAdapt->pPrimaryAdapt;

Rsvd =(PRSVD)(Packet->ProtocolReserved);
Pkt = Rsvd->OriginalPkt;
    //***Add***
if(Rsvd->bNewBuffer)
{
 NdisIMCopySendCompletePerPacketInfo(Pkt,Packet);
 NdisUnchainBufferAtFront(Packet,&PacketBuffer);
      NdisQueryBufferSafe(PacketBuffer,(PVOID*)&pPacketContent,&buferLength,32);
      NdisFreeBuffer(PacketBuffer);
 NdisFreeMemory(pPacketContent,buferLength,0);
 ASSERT(NDIS_GET_PACKET_STATUS(Packet) == NDIS_STATUS_RESOURCES);
 NdisDprFreePacket(Packet);
}
else
{
NdisIMCopySendCompletePerPacketInfo (Pkt, Packet);
NdisDprFreePacket(Packet);
}

NdisMSendComplete(pAdapt->MiniportHandle,
Pkt,
Status);
}
此程序出现出现,提示:IRQL_NO_LESS_OR_EQUAL错误。
我用softice跟踪发现。首先在ptreceive中,我的网卡仅执行iee802.3部分,前面
Packet = NdisGetReceivedPacket(pAdapt->BindingHandle,  MacReceiveContext);
中packet是NUll.
其次,我跟踪发现
  NdisSend(&Status,pAdapt->BindingHandle,MyPacket);
Status状态==NDIS_STATUS_PENDING
。所以我猜想他调用ptsendcomplete。并跟踪进入。当从该函数出来时,报错误,蓝屏。
各位高手能否帮我解答疑问。

[编辑 -  9/14/04 by  hxsyj]

[编辑 -  9/16/04 by  hxsyj]
AllenZh
驱动老牛
驱动老牛
  • 注册日期2001-08-19
  • 最后登录2015-11-27
  • 粉丝19
  • 关注10
  • 积分1316分
  • 威望2387点
  • 贡献值7点
  • 好评度321点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2004-09-14 19:16
你可参看passthrou、packet等的代码看看,这样的bug通常需要调试程序才能比较好定位错误
1,承接Windows下驱动/应用开发 2,本人原创虚拟鼠标/键盘,触摸屏,虚拟显卡,Mirror驱动,XP无盘的SCSI虚拟磁盘驱动等 3,windows下有尝技术服务(包括BUG调试,员工培训等) 欢迎深圳和海外企业联系.msn:mfczmh@sina.com
hxsyj
驱动牛犊
驱动牛犊
  • 注册日期2004-01-19
  • 最后登录2004-11-18
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2004-09-14 20:18
我想可能是那个东西未释放导致内存出问题了,但是无法找出原因。请版主和各位高手帮帮忙。
kja57
驱动牛犊
驱动牛犊
  • 注册日期2004-08-05
  • 最后登录2016-01-09
  • 粉丝1
  • 关注1
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2004-09-16 19:05
NdisGetReceivedPacket的确可能为空,这时需要你自己将数据取出构造成包发送;

在IE上不好看代码,我给你一段我的代码,参考了论坛上以前发表的文章:
NDIS_STATUS
PtReceive(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_HANDLE MacReceiveContext,
IN PVOID HeaderBuffer, // 包头
IN UINT HeaderBufferSize, // 包头大小,以太网环境下为14
IN PVOID LookAheadBuffer, // 前视缓冲
IN UINT LookAheadBufferSize, //
IN UINT PacketSize // 数据包总大小(不包括包头)
)
/*-----------------------------------------------------------------------------------
ProtocolReceive这个函数是在低层面向无连接的NIC驱动程序调用NdisMXxxIndicateReceive 函

数向上Indicate数据包时被 NDIS 调 用 的。 同 时 传 递 了 一 个 LookAheadBuffer,但 这

个LookAheadBuffer 里 面 可 能 不 是 数 据 包 的 全 部 内 容, 如  果  不  是  的  话

(LookAheadBufferSize < PacketSize)则需要调用NdisTransferData来获得这个数据包其余的内

容,NdisTransferData只是传递在LookaheadBuffer中没有出现的数据内容, 不是传递整个数据

包。
-----------------------------------------------------------------------------------*/
{
PADAPT OutAdapt, pAdapt =(PADAPT)ProtocolBindingContext;
PNDIS_PACKET MyPacket, Packet, MyPacketFront, MyPacketBack;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;

PNDIS_BUFFER pPacketBuffer, pFrontBuffer, pBackBuffer;
PUCHAR pPacketContent, pFrontContent, pBackContent;
UINT PacketLen, FrontLen, BackLen;
UINT OffsetSize;
UINT BytesTransferred;

PRSVD Rsvd = NULL;
PVOID MediaSpecificInfo = NULL;
ULONG MediaSpecificSize= 0;

#ifdef _LZYDBG
char cTestBuf[400];
#endif

BOOLEAN bIsNeedDiscard, *pIsNeedDiscard;
unsigned char *pEthHead, *pIpHead;

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
if(pAdapt->isSecondary)
{
DbgPrint("PASSTHRU GETTING RECIEVES ON SECONDARY\n");
ASSERT(0);
}

pIsNeedDiscard = &bIsNeedDiscard;
pEthHead = (unsigned char*)HeaderBuffer;
pIpHead = (unsigned char*)LookAheadBuffer;

FiltratePacketAccordBuffer(pAdapt, pEthHead, pIpHead, pIsNeedDiscard);
if(*pIsNeedDiscard == TRUE)
{
#ifdef _LZYDBG
sprintf(cTestBuf, "\nPtReceive():丢弃数据包!");
DBGPRINT(cTestBuf);
#endif
//丢弃此数据包
return NDIS_STATUS_NOT_ACCEPTED;
}

// 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.

// (NdisGetReceivedPacket 一般都会失败)
Packet = NdisGetReceivedPacket(pAdapt->BindingHandle, MacReceiveContext);
if(Packet != NULL)
{
//
// 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);
#ifdef _LZYDBG
sprintf(cTestBuf, "\nPtReceive():数据包,调用NdisGetReceivedPacket()");
DbgPrint(cTestBuf);
#endif

NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1);

ASSERT(NDIS_GET_PACKET_STATUS(MyPacket) == NDIS_STATUS_RESOURCES);
NdisDprFreePacket(MyPacket);
break;
}
}
else
{/*NdisGetReceivedPacket 失败*/
if(PacketSize <= LookAheadBufferSize)  // 如果 LookAheadBuffer 中包含了全部数据
{
PacketLen = PacketSize+HeaderBufferSize;
// 分配内存
Status = NdisAllocateMemory(&pPacketContent, PacketLen, 0, HighestAcceptableMax);
if(Status != NDIS_STATUS_SUCCESS)
{
DbgPrint("PTReceive:NdisAllocateMemory Failed\n");
return NDIS_STATUS_NOT_ACCEPTED;
}
if(pPacketContent == NULL)
{
DbgPrint("PTReceive:pPacketContent==NULL\n");
return NDIS_STATUS_NOT_ACCEPTED;
}
NdisZeroMemory(pPacketContent, PacketLen);

// 将包头和 LookAheadBuffer 复制到新分配的内存中
NdisMoveMemory(pPacketContent, HeaderBuffer, HeaderBufferSize);
NdisMoveMemory(pPacketContent+ HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize);

#ifdef _LZYDBG
sprintf(cTestBuf, "\nPtReceive():LookAheadBuffer 中包含了全部数据:HeaderBufferSize=%u, PacketSize =%u,  LookAheadBufferSize=%u!\n", HeaderBufferSize, PacketSize , LookAheadBufferSize);
DbgPrint(cTestBuf);
#endif
// 在包池中分配包描述符
NdisDprAllocatePacket(&Status, &MyPacket, pAdapt->RecvPacketPoolHandle);
if(Status != NDIS_STATUS_SUCCESS)
{
NdisFreeMemory(pPacketContent, PacketLen, 0);
return NDIS_STATUS_NOT_ACCEPTED;
}
// 在缓冲池中分配缓冲描述符,将包描述符与缓冲描述符关联。
NdisAllocateBuffer(&Status, &pPacketBuffer, pAdapt->RecvBufferPoolHandle, pPacketContent, PacketLen);
if(Status != NDIS_STATUS_SUCCESS)
{
NdisDprFreePacket(MyPacket);
NdisFreeMemory(pPacketContent, PacketLen, 0);
return NDIS_STATUS_NOT_ACCEPTED;
}
NdisChainBufferAtFront(MyPacket, pPacketBuffer);

MyPacket->Private.Head->Next = NULL;
MyPacket->Private.Tail = NULL;
Rsvd=(PRSVD)(MyPacket->MiniportReserved);
Rsvd->OriginalPkt = NULL;
NDIS_SET_PACKET_HEADER_SIZE(MyPacket, HeaderBufferSize);

#ifdef _LZYDBG
sprintf(cTestBuf, "\n\tPtReceive():PacketSize <= LookAheadBufferSize, pAdapt->MiniportHandle=%u", (ULONG)pAdapt->MiniportHandle);
DbgPrint(cTestBuf);
#endif
// 向上层协议驱动指示数据包,防真网卡行为。
NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1);
if(NDIS_GET_PACKET_STATUS(MyPacket) != NDIS_STATUS_PENDING)
{
NdisFreeBuffer(pPacketBuffer);
NdisDprFreePacket(MyPacket);
NdisFreeMemory(pPacketContent, PacketLen, 0);
}
break;
}
else  /* LookAheadBuffer 中没有包含全部数据(LookAheadBufferSize最大为128字节)*/
{
FrontLen = HeaderBufferSize+LookAheadBufferSize;
// 分配前视缓冲内存
Status = NdisAllocateMemory(&pFrontContent, FrontLen, 0, HighestAcceptableMax);
if(Status != NDIS_STATUS_SUCCESS)
{
NdisFreeMemory(pFrontContent, FrontLen, 0);
return NDIS_STATUS_NOT_ACCEPTED;
}
if(pFrontContent == NULL)
{
NdisFreeMemory(pFrontContent, FrontLen, 0);
return NDIS_STATUS_NOT_ACCEPTED;
}
NdisZeroMemory(pFrontContent, FrontLen);

// 将 HeaderBuffer + LookAheadBuffer 复制到 pFrontContent 指向的内存中。
NdisMoveMemory(pFrontContent, HeaderBuffer, HeaderBufferSize);
NdisMoveMemory(pFrontContent+HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize);

// 分配包描述符 MyPacketFront。
NdisDprAllocatePacket(&Status, &MyPacketFront, pAdapt->RecvPacketPoolHandle);
if(Status != NDIS_STATUS_SUCCESS)
{
NdisFreeMemory(pFrontContent, FrontLen, 0);
return NDIS_STATUS_NOT_ACCEPTED;
}
NdisAllocateBuffer(&Status, &pFrontBuffer, pAdapt->RecvBufferPoolHandle, pFrontContent, FrontLen);
if(Status != NDIS_STATUS_SUCCESS)
{
NdisDprFreePacket(MyPacketFront);
NdisFreeMemory(pFrontContent, FrontLen, 0);
return NDIS_STATUS_NOT_ACCEPTED;
}
// 关联包描述符 MyPacket 与缓冲描述符 pPacketBuffer。
NdisChainBufferAtFront(MyPacketFront, pFrontBuffer);
MyPacketFront->Private.Head->Next=NULL;
MyPacketFront->Private.Tail=NULL;
NDIS_SET_PACKET_HEADER_SIZE(MyPacketFront, HeaderBufferSize);



//需要传输的超长数据长度
BackLen = PacketSize-LookAheadBufferSize;
Status = NdisAllocateMemory(&pBackContent, BackLen, 0, HighestAcceptableMax);
if(Status != NDIS_STATUS_SUCCESS)
{
NdisFreeBuffer(pFrontBuffer);
NdisDprFreePacket(MyPacketFront);
NdisFreeMemory(pFrontContent, FrontLen, 0);
return NDIS_STATUS_NOT_ACCEPTED;
}
if(pBackContent == NULL)
{
NdisFreeBuffer(pFrontBuffer);
NdisDprFreePacket(MyPacketFront);
NdisFreeMemory(pFrontContent, FrontLen, 0);
return NDIS_STATUS_NOT_ACCEPTED;
}
NdisZeroMemory(pBackContent, BackLen);

// 分配包描述符 MyPacketBack以获取超出长度的数据内容。
NdisDprAllocatePacket(&Status, &MyPacketBack, pAdapt->RecvPacketPoolHandle);
if(Status != NDIS_STATUS_SUCCESS)
{
NdisFreeMemory(pBackContent, BackLen, 0);

NdisFreeBuffer(pFrontBuffer);
NdisDprFreePacket(MyPacketFront);
NdisFreeMemory(pFrontContent, FrontLen, 0);
return NDIS_STATUS_NOT_ACCEPTED;
}
NdisAllocateBuffer(&Status, &pBackBuffer, pAdapt->RecvBufferPoolHandle, pBackContent, BackLen);
if(Status != NDIS_STATUS_SUCCESS)
{
NdisDprFreePacket(MyPacketBack);
NdisFreeMemory(pBackContent, BackLen, 0);

NdisFreeBuffer(pFrontBuffer);
NdisDprFreePacket(MyPacketFront);
NdisFreeMemory(pFrontContent, FrontLen, 0);
return NDIS_STATUS_NOT_ACCEPTED;
}
NdisChainBufferAtFront(MyPacketBack, pBackBuffer);
MyPacketBack->Private.Head->Next=NULL;
MyPacketBack->Private.Tail=NULL;

Rsvd = (PRSVD)(MyPacketBack->MiniportReserved);
Rsvd->OriginalPkt = (PNDIS_PACKET)MyPacketFront; //MyPacketFront中为包头和前视缓冲区中的数据

NDIS_SET_PACKET_HEADER_SIZE(MyPacketBack, HeaderBufferSize);

// 取得 LookAheadBuffer 之后的数据
NdisTransferData(&Status,
pAdapt->BindingHandle,
MacReceiveContext,
LookAheadBufferSize, // 数据起始地址
BackLen, // 字节数
MyPacketBack,
&BytesTransferred);

#ifdef _LZYDBG
sprintf(cTestBuf, "\n\tPtReceive():大数据包,PacketSize > LookAheadBufferSize, 调用NdisTransferData()完");
DbgPrint(cTestBuf);
#endif
if(Status != NDIS_STATUS_PENDING)
{
PtTransferDataComplete((NDIS_HANDLE)pAdapt, MyPacketBack, Status, BytesTransferred);
}
break;
}
}
pAdapt->IndicateRcvComplete = TRUE;
// Fall through if the miniport below us has either not indicated a packet or we could not
// allocate one

} while(FALSE);

return Status;
}

需要注意的是如传输大数据包,要在PtTransferDataComplete中释放资源
游客

返回顶部