我有filter="ip或vlan",我像下面这样将它传递给libpcap,它在我的应用程序中工作了很长一段时间,没有任何问题。
pcap_set_filter(pdesc->pd, filter, 0, netp);
现在我也被要求解析arp-trafic。所以我设置了我的过滤器
"ip或vlan或arp或rarp">
。但是我的回调函数并没有被arp数据包调用,即使对于ip数据包,我的函数仍在被调用。
简而言之,我的问题是如何正确设置libpcap过滤器以从系统中获取arp数据包?
我检查了WireShark中的BPF指令,以了解发生了什么。以下是各种过滤器的BPF过滤器程序:
1.简单案例:
过滤器:vlan
if the frame is VLAN-tagged then
return true
else
return false
过滤器:ip
if the frame is not VLAN-tagged and the protocol is IP then
return true
else
return false
过滤器:arp
if the frame is not VLAN-tagged and the protocol is ARP then
return true
else
return false
过滤器:rarp
if the frame is not VLAN-tagged and the protocol is RARP then
return true
else
return false
过滤器:ip or arp or rarp
if the frame is not VLAN-tagged and the protocol is either IP, ARP or RARP then
return true
else
return false
2.将ip
与vlan
相结合表明搜索标签的顺序很重要:
您的第一个筛选器是ip or vlan
。其伪代码如下:
if either the frame is not VLAN-tagged and the protocol is IP
or the frame is VLAN-tagged
then
return true
else
return false
对于滤波器vlan or ip
,我们希望看到:
if either the frame is VLAN-tagged
or the frame is not VLAN-tagged and the protocol is IP
then
return true
else
return false
这意味着相同,这是可以的,因为A or B
的意思应该和B or A
的意思相同,不是吗?但我们得到了这个:
(000) ldh [12]
(001) jeq #0x8100 jt 4 jf 2
(002) ldh [16]
(003) jeq #0x800 jt 4 jf 5
(004) ret #65535
(005) ret #0
这意味着类似于以下伪代码:
if either the frame is VLAN-tagged
or the frame is not VLAN-tagged but it has an EtherType field shifted 4 bytes right, which says the protocol is IP
then
return true
else
return false
这没有道理。行(002)是不必要的。说明应该是这样的:
(000) ldh [12]
(001) jeq #0x8100 jt 3 jf 2
(002) jeq #0x800 jt 3 jf 4
(003) ret #65535
(004) ret #0
也许我会因为这样说而被杀,但我认为这是libpcap中的错误。上面的(002) ldh [16]
线是从哪里来的?如果过滤器是vlan and ip
,那么检查偏移量16处的字节是有意义的:现在我们想找到包含IP数据包的VLAN标记帧。在这样的帧中,有两个EtherType字段:第一个(偏移量12)包含VLAN EtherType值(0x8100),第二个(偏移值16)包含IP协议的EtherType(#0x800):
(000) ldh [12]
(001) jeq #0x8100 jt 2 jf 5
(002) ldh [16]
(003) jeq #0x800 jt 4 jf 5
(004) ret #65535
(005) ret #0
3.为什么您的过滤器没有找到ARP和RARP数据包?
您的筛选器是ip or vlan or arp or rarp
。这编译为:
(000) ldh [12]
(001) jeq #0x800 jt 6 jf 2
(002) jeq #0x8100 jt 6 jf 3
(003) ldh [16]
(004) jeq #0x806 jt 6 jf 5
(005) jeq #0x8035 jt 6 jf 7
(006) ret #65535
(007) ret #0
这段代码有上面的错误:libpcap试图在偏移量16处找到ARP和RARP EtherTypes。
4.问题的解决方案
您可以通过在过滤器的开头添加它们来避免该错误:arp or rarp or ip or vlan
。这编译为:
(000) ldh [12]
(001) jeq #0x806 jt 5 jf 2
(002) jeq #0x8035 jt 5 jf 3
(003) jeq #0x800 jt 5 jf 4
(004) jeq #0x8100 jt 5 jf 6
(005) ret #65535
(006) ret #0
意思是:
if either the frame is not VLAN-tagged and the protocol is either IP, ARP or RARP,
or the frame is VLAN-tagged
then
return true
else
return false