9.2.2 过滤表达式
WinPcap的过滤表达式是一个ASCII字符串形式的高层布尔表达式(与libpcap、Tcpdump和WinDump的相同),原语(primitive)是其基本组成单元。一个表达式由一个或多个原语组成,原语之间通过and、or或not连接。基本语法结构如下:
[not]原语[and|or[not]原语…]
数据包过滤机制实际上是针对数据包的布尔值操作的函数,如果函数最终返回true,则通过过滤;反之则丢弃。形式上,数据包过滤由一个或多个谓词判断的“与”操作(and)和“或”操作(or)构成。每一个谓词判断基本上对应数据包的某个协议类型或某个特定值(比如,只需要TCP协议类型且端口为110的数据包或ARP协议类型的数据包)。
过滤表达式转换为内核级指令的过程如图9-5所示,先从一个用户所定义的过滤表达式(比如,捕获所有UDP数据包)开始,由wpcap.dll库中的pcap_compile函数将过滤表达式编译成虚拟机指令(比如,若数据包是IP协议且协议类型字段为17,则返回true)。然后由wpcap.dll库中的pcap_setfilte函数将编译后的指令应用到某个已打开的网络捕获设备(网卡)上。
图 9-5 过滤表达式转换为内核级指令的过程
内核模块必须能够执行这些指令,因此对所有进入的数据包,WinPcap必须有一个类似于“BPF的虚拟机”来执行这些指令。内核中与BPF兼容的虚拟机(也就是“NPF虚拟机”)是获得高性能的一个关键点。
在实际过滤时,NPF过滤器会检查每个网络数据包头部相应字段的值,检查范围包括数据链路层首部(如以太网帧的源/目的MAC地址和协议类型字段)、网络层首部(如源/目的IP地址和协议字段等)、传输层首部(如源/目的端口号字段等),然后所有符合要求的数据包(即与过滤条件比较后,布尔表达式为真的数据包)将会被WinPcap继续传递。