防火墙驱动原理

 ICMP包的格式 
IP数据包的源主机经过本机的数据链路层把IP包发送到物理网络,之后就是陆游器来完成。ICMP协议负责差错控制和报文控制。 
ICMP包分为报文头+数据两个部分。 
IP = IP报文头+ IP数据; 
IP数据 = ICMP报文头 + ICMP数据 
所有  IP包 =  IP报文头 + ICMP报文头 + ICMP数据 

miniport.c里面有mpsend()的包发送函数 

protocol.c里面是ptreceive()以及ptreceivepacket()函数 

在函数PtReceivePacket及PtReceive里面 
对于第一个,需要调用函数 
NdisGetFirstBufferFromPacket 
NdisQueryBuffer 
NdisGetNextBuffer 
来得到当前数据包的地址! 
而后一个就需要把数据包取得连续了! 
PtReceive( 
IN PVOID HeaderBuffer, 
IN UINT HeaderBufferSize, 
IN PVOID LookAheadBuffer, 
IN UINT LookAheadBufferSize, 
IN UINT PacketSize 

在HeaderBufferSize里面 
而发送的时候是在函数 
MPSend( 
IN NDIS_HANDLE MiniportAdapterContext, 
IN PNDIS_PACKET Packet, 
IN UINT Flags 

也是通过 
NdisGetFirstBufferFromPacket 
NdisQueryBuffer 
NdisGetNextBuffer 
来得到数据包,在WINDOWS 2000下有一个数据包捕获器的!在管理工具里面,叫做网络监视器 

关于passthru两个安装文件和DLL的问题: 

一个是协议驱动用的,一个是miniport 

passthru其实是一个imd,所以要两个inf 

安装只指定协议驱动的inf,它自己会找那个miniport的。 
当然,要放在同一目录下才行。你可以打开协议的inf,里面有miniport的inf文件名。 
那个dll是coinstall dll, 是一个com组件。 

它的作用是在添加删除网卡时辅助绑定imd. 

imd 需要在物理卡上绑定,每个卡都要用。所以它在系统添加 
删除网卡起作用。 

在以太网中,得到的数据报大致是如下结构, 
以太帧头14个字节,放在pPacketContent[0]到pPacketContent[13]中, 
其中前六个字节是目的MAC地址, 
然后六个字节源MAC地址, 
然后两个字节是协议类型,(12...13) 
通常的协议类型有 
0x08 0x00 ->IP, 
0x08 0x06 ->ARP, 
0x08 0x35 ->RARP, 
所以,可以通过pPacketContent[12]和pPacketContent[13]来判断协议类型。 
如果是IP包,然后pPacketContent中存放的是IP头,根据IP头的格式,可以得到第23个字节pPacketContent[23]表示传输层协议: 
1 ->ICMP, 
2 ->IGMP, 
6 ->TCP, 
17 ->UDP, 
剩下的就是数据报内容了 


int  aiptoi(char  *  pszip,unsigned  int*  piip)  
  {  
  char  psziphere[17],*psztmp1,*psztmp2,*pchar;  
  int  i;  
  bzero(psziphere,17);  
  strcpy(psziphere,pszip);  
  strcat(psziphere,".");  
  for(i=0,psztmp1=psziphere,pchar=(char  *)piip;i <4;i++)  
  {  
  if((psztmp2=strstr(psztmp1,"."))==NULL)  
  return  0;  
  psztmp2[0]=0;  
  *(pchar+i)=atoi(psztmp1);  
  psztmp1=psztmp2+1;  
  }  
  return  1;  
  } 


1. 底层驱动使用NdisMIndicateReceive / NdisMEthIndicateReceive通知上层已经收到数据报文 
  NdisMIndicateReceive在protocol.c中调用 
  (1)PtTransferDataComplete中调用NdisMIndicateReceivePacket 
  (2)PtReceive 中调用NdisMIndicateReceivePacket,但是被新的接受方式      取缔,转换成自己的代码,使用了一次这个函数。
  (3)PtReceivePacket中调用NdisMIndicateReceivePacket 

2. 在PtReceive中如果通过NdisGetReceivedPacket得到了一个完整的packet,就分配我们自己的MyPacket,根据底下传上来的packet设置MyPacket,然后调用NdisMIndicateReceivePacket通知NDIS,NDIS会接着调用上层协议驱动的相应PtReceive例程。 
如果此时MyPacket的status是NDIS_STATUS_RESOURCES,我们就在本函数中释放我们分配的MyPacket; 
否则我们在上层发送4的时候,在MPReturnPacket中释放MyPacket. 
  NDIS_STATUS_RESOURCES在protocol.c中调用 
  
3. 在PtReceive中如果通过NdisGetReceivedPacket不能得到一个完整的packet,那我们就直接调用NdisMEthIndicateReceive等函数通知NDIS。 

4. 当上层协议驱动得到了一个完整的数据报文并且处理完毕以后,它会调用NdisReturnPacket,然后NDIS会调用我们的MPReturnPacket.。
  NdisReturnPacket在miniport.c中调用,MPReturnPacket中含有NdisReturnPacket。 

5. 在我们的MPReturnPacket中,释放我们自己分配的MyPacket,然后同样的向下层调用NdisReturnPacket。下层会释放他们自己分配的packet 。

 

6. 如果3发生,当底层miniport驱动收到了一个完整的数据报文,它会调用NdisMEthIndicateReceiveComplete,然后NDIS会调用我们的PtReceiveComplete 。PtReceiveComplete发生在protocol.c中,没有发现重载的现象 。

7. 我们的PtReceiveComplete同样的,会调用NdisMEthIndicateReceiveComplete,通知NDIS“我们已经收到了完整的报文” 。

8. 当上层协议驱动得知底层已经收到了完整的数据报文以后,可能会调用NdisTransferData,要求下层把剩余的数据传上来。

 
9. 8的调用会导致NDIS调用我们的MPTransferData例程。在MPTransferData中,做同样的调用NdisTransferData。注意该函数的返回值:如果返回success,说明剩余的数据立刻就传上来了。此时会立即返回。10、11两步骤就不会调用;如果返回pending,表明底层在此阻塞,底层会在稍后的时候调用10 MPTransferData发生在miniport.c中。如果阻塞会发生10的调用。也就是调用NdisTransferDataComplete。


10. 当底层miniport驱动做好了一个完整的packet,它会调用NdisTransferDataComplete 。


11. 同样在我们的PtTransferDataComplete中,会作出同样的调用。 

  /PassThru - Windows DDK Build 3790 PassThru工程文件夹; 

        /Driver – PassThru驱动源程序 

                  PassThru.c – DriveEntry函数和其它PassThru小端口驱动程序与协议驱动程序共用的代码部分。 

                  PassThru.h – PassThru的头文件; 

                  Miniport.c – PassThru中与Miniport相关的函数; 

                  Protocol.c – PassThru中与Protocol相关的函数; 

                  Precomp.h – 预编译的头文件; 

                  Sources – 编译工具所用的源文件列表文件; 

                  IOCommon.h – 驱动和用户态下程序所共用的头文件; 

交互的程序部分在passthru.c 中包含,主要功能是接收来自上层的控制消息,以及共享的内存进行判断。 
1.10 呵呵 passthru终于完成了对ICMP以及IP包的分类和拦截。但是程序交互该什么做呢,SystemVirtualAddress每次的地址是不是固定的呢。 

1.11交互程序完成了! 果然还是用在SystemVirtualAddress上,不过为什么我要发三次命令来初始化,太麻烦。接下来需要对程序进行调整。 
  为什么XP下的程序不能使用呢。 
  NdisAllocateMemory是在2K下使用的,XP下应该使用NdisAllocateMemoryWithTag。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值