Digital
驱动牛犊
驱动牛犊
  • 注册日期2001-08-08
  • 最后登录2008-07-08
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望6点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:2969回复:10

如何取得以太包的包头??大赏50分

楼主#
更多 发布于:2001-08-13 12:50
我用以下方法取得包头,并且过滤ICMP包,好像没用!
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;
//UINT  PhysicalBufferCount, BufferCount,TotalPacketLength;
//PNDIS_BUFFER  *FirstBuffer;
PVOID           virtualAddress;
PNDIS_BUFFER    firstBuffer, nextBuffer;
ULONG           totalLength;

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);
}

//
// 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)
{
NdisQueryPacket(Packet, NULL, NULL, &firstBuffer, &totalLength);
while( firstBuffer != NULL)
{
NdisQueryBuffer(firstBuffer, &virtualAddress,
&totalLength);
if(!virtualAddress)
{
//
// System is running low on memory resources.
// So fail the read.
//
//status = STATUS_INSUFFICIENT_RESOURCES;
//goto CleanExit;
break;
}
else
{
if ((((char*)virtualAddress)[12] == 8)&&
(((char*)virtualAddress)[13] == 0)&&
(((char*)virtualAddress)[23] == 1))
{
Status = NDIS_STATUS_FAILURE;
return Status;
}
}
NdisGetNextBuffer(firstBuffer,  &nextBuffer);
firstBuffer = nextBuffer;
}
//
// 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:
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;
}

最新喜欢:

xiaojian521xiaoji... txysptxysp
相信自已!
lxf
lxf
驱动小牛
驱动小牛
  • 注册日期2001-03-26
  • 最后登录2013-05-04
  • 粉丝4
  • 关注0
  • 积分76分
  • 威望30点
  • 贡献值0点
  • 好评度7点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2001-08-13 14:30
好多分呀!
你这个例程运行了吗?
别着急,慢慢来!
blue
驱动大牛
驱动大牛
  • 注册日期2001-04-25
  • 最后登录2010-10-15
  • 粉丝0
  • 关注0
  • 积分55分
  • 威望12点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2001-08-13 16:25
{
if ((((char*)virtualAddress)[12] == 8)&&
(((char*)virtualAddress)[13] == 0)&&
(((char*)virtualAddress)[23] == 1))
{
Status = NDIS_STATUS_FAILURE;
return Status;
}
你在这里对这个包处理,不知你具体想干什么?你是不是不想让本机收到这个包呀!如果是这样,你并不能阻止,此包依然能上传,你若要阻止,可试着改一下MAC地址,这样系统认为不是发向本机的数据而抛弃,可能可行!
hustfyb
驱动牛犊
驱动牛犊
  • 注册日期2001-05-28
  • 最后登录2002-01-23
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2001-08-13 16:41
按照你的程序当buffer chain上的
first buffer的长度小于23时
if ((((char*)virtualAddress)[12] == 8)&&
(((char*)virtualAddress)[13] == 0)&&
(((char*)virtualAddress)[23] == 1))
这个判断就会出问题

另外你的那个
do
while有什么意义啊
再见了白云 永别了黄鹤
Digital
驱动牛犊
驱动牛犊
  • 注册日期2001-08-08
  • 最后登录2008-07-08
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望6点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2001-08-13 16:57
是这样的,我只是想做一个拦截ICMP包的例子,开始以为GET..NEXT取得是下一个包,后来发现是一个包的不同部分。哪请问,直接用:

NdisGetFirstBufferFromPacket(Packet,&pFirstBuffer,&pVirtualAddress,
&iFirstBufferLength,&iTotalLength);
if ((((char*)pVirtualAddress)[12] == 8)&&
(((char*)pVirtualAddress)[13] == 0))
return  NDIS_STATUS_FAILURE;

可否拦截所有的IP包?

另外如何使IMD DRIVER与应用程序通讯?
相信自已!
Dino
驱动牛犊
驱动牛犊
  • 注册日期2001-08-07
  • 最后登录2007-01-10
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2001-08-13 18:40
有没有可能是NDIS是传递给你的IM一个Packet的描述符,调用了你的PtReceivePacket例程.
Death is only the beginning
Digital
驱动牛犊
驱动牛犊
  • 注册日期2001-08-08
  • 最后登录2008-07-08
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望6点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2001-08-13 20:03
我的QQ:15614487
个人主页:www.ishacker.com

请版本和各位高人指教啊!
相信自已!
hustfyb
驱动牛犊
驱动牛犊
  • 注册日期2001-05-28
  • 最后登录2002-01-23
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2001-08-15 14:01
一个packet的buffer不是一个区域
应该是一个buffer chain
你的写法实际上只是对这个buffer chain上的第一个
buffer进行了判断当第一个buffer的长度大于13时没有问题,
但是当一个buffer小于这个长度就不对了
你应该判断一下如果不够用getnextbuffer取出下一段
平到一起判断,
具体的packet结构ddk上有专门的描述
再见了白云 永别了黄鹤
lyx210
驱动牛犊
驱动牛犊
  • 注册日期2001-03-23
  • 最后登录
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2001-08-16 18:42
网卡驱动程序可能通过两种方式向协议通知接收到数据包,
1.PtReceive,PtTransferDataComplete,还可能有PtReceiveComplete(非一一对应,可以不考虑)
2.PtReceivePacket
方法1常用于使用从dma方式的网卡,
方法2常用于使用主dma方式的网卡。
在方法1中,PtReceive给出了网络帧的头14字节和LookAhead部分(长度不定),在PtTransferDataComplete中给出了网络帧的后续部分。
方法2中,PtReceivePacket给出了整个网络帧。

你只处理了PtReceive,但如果网卡使用方法2,......

并且,我在PtReceive没有使用过NdisGetReceivedPacket,
也没有如此使用过MacReceiveContext,MacReceiveContext好像是供NdisTransferData用的。
请阅读 win2000 DDK 的 src\network\ndis\packet\driver
的源代码。

lyx210
驱动牛犊
驱动牛犊
  • 注册日期2001-03-23
  • 最后登录
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2001-08-16 19:03
没有想到你使用了passthru的代码。
根据我的体会:
passthru的PtReceive中NdisGetReceivedPacket返回的Packet好象基本上为NULL。
其实,其重要部分在switch(pAdapt->Medium)之后,passthru在此通知上层协议下层网卡接收了一个数据帧。
你可以在switch(pAdapt->Medium)前面加入自己的代码,进行帧头处理,并决定是否上转。
passthru仅仅执行了一个传达功能。

HuYuguang
论坛版主
论坛版主
  • 注册日期2001-04-25
  • 最后登录2013-04-29
  • 粉丝3
  • 关注1
  • 积分92分
  • 威望11点
  • 贡献值0点
  • 好评度9点
  • 原创分1分
  • 专家分0分
10楼#
发布于:2001-08-16 21:15
我实在是受不了...


看情况你是要过滤icmp包,类似于firewall之类。
此外看情况你是用的passthru。因此平台是w2k,
因为NdisGetReceivedPacket这个函数并不存在于
nt ddk中的ndis4中。我仔细看了看你的代码,发现
我说的全都是废话,因为你的代码很显然就是
passthru。


我不知道你的具体现象,过滤不了icmp,有如下可能
1、包根本就没有走ptrecevie,走的是ptrecievpacket。
2、NdisGetReceivedPacket返回了null
这两种可能都将使你的代码根本没有得到执行。不知道
你用osftice跟踪的结果。

我在这里详细说一下ptreceive的处理情况,然后简单介绍
ptreceivepacket中的处理情况。

对于ptreceive来说,你根本就不需要写这么多代码,
因为ptrecieve的参数headerbuffer只有两种情况,
一种是headbuffersize=14,还有一种就是=packetsize。
先说=14的情况,对于拨号和eth来说,两个地址+一个
类型码,就是14。对于fddi什么的,我记不清是多少。
因此,如果你不过是要过滤icmp的话,根本都不需要
transferdata,此外,你的代码写的颇为垃圾,为什么
要一个字节一个字节比较?为什么不直接强制类型转换
到icmp头的数据结构,这岂不是一下就得到了icmp头了吗?
你的代码里面似乎并不是过滤掉全部icmp,似乎还需要
判断icmp类型,这样的话,你需要得到所有的数据才行。
你需要调用transferdata来得到这些数据,我不喜欢贴
代码,下面简单的说一下transferdata的策略
1、继续按照原有代码的结构,完全仿真真正的miniport行为,
继续用transferdata结构,在imd的协议层的transferdatacomplete
里面得到所有数据包后进行处理,然后调用dismtransferdatacomlete,
2、屏蔽真正的miniport动作,在下面不调用这个函数,直接用imd的
协议身份调用ndistransferdata, 让ndis去调用miniport的
transferdata,miniport driver发送结束后就会调用imd的协议层的
transferdatacomplete,这样imd的协议层就得到所有数据,然后修
改包内容,然后用imd的miniport身份调用
ndismindicatereceivepacket,通知ip层说来了一个数据包。这样的
话,ip层永远不会调用imd里面的miniport的transferdata函数,
这样做的效率节省了ip调用imd miniport的transferdata过程,效率
相对要高一些。

你的情况用第2种策略比较合适,虽然passthru显然是用第一种。
用第2种策略的话,根本就不需要调用那一堆介质相关的
NdisMEthIndicateReceive,NdisMTrIndicateReceive之类。

如果NdisGetReceivedPacket不返回null的话,那么你直接
得到了ndispacket结构,你要做的事情就是从这个结构中
得到所有的数据。调用如下函数:
UINT
CopyPacket2Buf(
IN PNDIS_PACKET Packet,
OUT PUCHAR pPacketContent,
OUT UINT* pPacketSize)
{
UINT  bufLength;
MDL* pNext;
UINT i;
PUCHAR pbuf;

NdisQueryPacket(Packet,NULL,NULL,NULL,pPacketSize);

NdisQueryBufferSafe(Packet->Private.Head,&pbuf,&bufLength, 32 );
NdisMoveMemory(pPacketContent,pbuf,bufLength);
i=bufLength;
pNext=Packet->Private.Head;  // next 是一个mdl

for(;;)
{
if(pNext==Packet->Private.Tail)
break;
pNext=pNext->Next;  // next 是一个mdl
if (pNext==NULL)  break;
NdisQueryBufferSafe(pNext,&pbuf,&bufLength,32);
NdisMoveMemory(pPacketContent+i,pbuf,bufLength);
i+=bufLength;
}
ASSERT(*pPacketSize == i);
return *pPacketSize;
}
这个函数是我很早以前写的,当时萝卜快了不洗泥,犯规的用了很多
的内部参数,ms说应该用它提供的宏,但是我当时实在没有时间去慢
慢找那些宏。

得到了buf之后,解析数据包,《程序设计指南》里面专门
提到了如何用可变参数函数简洁的解析各种数据包,建议好好看看。

对于ptreceivepacket,情况一样,因为一下子就从入口参数
得到了ndis提交的一个ndispacket。

不再回忆从前,我已经生活在幸福当中。
游客

返回顶部