最近把我那个NDIS过滤驱动重写了一遍,又发现一点东西,呵呵~
1、关于读取数据封包
在Passthru的实例中,能读出封包内容的数据格式有两种,一种是PNDIS_PACKET格式的网络封包,另一种是PUCHAR格式的字符串指针。
第一种数据涵盖了绝大多数的地方,第二种数据只有一个地方返回,那就是PtReceive中,Packet==NULL,且PacketSize<=LookAheadBufferSize。这样所有的数据保存在两个PUCHAR中。
一个是HeadBuffer,另一个是LookAheadBuffer。前者一般表示以太网首部(如果在以太网中),后者是从IP首部开始的全部数据。
封包读取,最好搞成一个函数,返回一个PUCHAR数据,所有的数据包数据都放在这这里,方便过滤。
比如:
VOID FltReadPacketData( IN PNDIS_PACKET pPacket, OUT PUCHAR lpBufferIn)
2、关于长度的问题
PtReceive入口参数中的PacketSize,是全部数据的长度(从IP首部到最后),不包括HeadBufferSize(一般是以太首部)。整个数据包的『全部长度』=PacketSize+HeadBufferSize
在PtReceive中,如果PacketSize>LookAheadBufferSize,就说明数据包没有收全,需要调用NdisTransferData接收剩下的数据。
sizeof是不可以用于指针型数据的求长的,只会返回指针本身占用的空间。
需要对一个PNDIS_PACKET数据求长,可以用NdisQueryPacket函数,该函数求得的数据包长度是『整个』数据包的全长,包括以太网首部及后面的所有数据。
3、关于过滤
过滤最好写成一个函数,读入一个PUCHAR格式的数据包,然后给出一个True或False的值。
当然,这里需要提及一下旋转锁这个东西。我也是第一次遇到的,呵呵~旋转锁通过提高优先级,保证多处理器下的数据同步。
过滤函数的入口处,加入这个参数。然后通过下面语句获取和释放旋转锁。记得获取后一定要释放,否则蓝屏。
NdisDprAcquireSpinLock(&pAdapt->Lock); //获取
NdisDprReleaseSpinLock(&pAdapt->Lock); //释放