2012-08-07 72 views
2

我使用Scapy的函數send來發送數據包,這些數據包將在路由器上生成ICMP數據包並轉儲那些作爲子進程啓動的tcpdump的ICMP數據包。Scapy中的小車行爲

然後,我會用scapy的內置rdpcap函數將這些ICMP數據包讀回到我的程序中。

嗯,事實證明,rdpcap有時弄亂的東西,只要我想偷看我的捕獲的數據包,它返回如下:

(InteractiveConsole) 
>>> icmpPackets 
Traceback (most recent call last): 
    File "<console>", line 1, in <module> 
    File "/usr/lib/python2.7/dist-packages/scapy/plist.py", line 57, in __repr__ 
    if self._elt2pkt(r).haslayer(p): 
AttributeError: 'NoneType' object has no attribute 'haslayer' 

然後,我將只需要再次調用rdpcap相同說法,一切都將回到正常:

>>> icmpPackets = rdpcap(tcpdumpFileName) 
>>> icmpPackets 
<icmpPackets.cap: TCP:0 UDP:0 ICMP:1428 Other:1> 

這是一些bug,對不對?

編輯:好吧,我得到這個錯誤之前我做的一件事是以下,這可能不是太正統,但我不需要以太網層,當我僞造數據包。如果我刪除這兩條線,我不會得到任何這樣的錯誤:

for i in range(len(icmpPackets)): 
     icmpPackets[i] = icmpPackets[i].getlayer(IP) 

我這樣做,其他地方之前,從來沒有得到一個問題。這裏發生了什麼事?

+0

你可能在不知不覺中更新了你的Scapy版本? – 2012-08-07 22:15:02

+0

我不這麼認爲...... – 2012-08-08 09:40:15

回答

1

嗨,

我真的不明白,爲什麼你嗅出使用tcpdump而不是Scapy的流量,但無論如何...您的問題並不在Scapy的,而是在你的代碼中的錯誤。如果數據包沒有IP層(例如,ARP數據包),則用.getlayer(IP)替換每個數據包,如果數據包沒有層,則返回None。因此你會得到後者的例外。

我想你應該

icmpPackets = PacketList([p[IP] for p in PcapReader(tcpdumpFileName) if IP in p]) 

首先的替代

icmpPackets = rdpcap(tcpdumpFileName) 
for i in range(len(icmpPackets)): 
    icmpPackets[i] = icmpPackets[i].getlayer(IP) 

我覺得它更「Python化」,再加上它的不IP層去除包解決了這個問題。或者你也可以使用,如果你想擁有所有沒有Ether層的報文:

icmpPackets = PacketList([p.payload for p in PcapReader(tcpdumpFileName)]) 

另外,您可以用tcpdump的一個BPF過濾器過濾(icmp如果你只是想ICMP包)。