Reputation: 22893
I use Scapy's function send
to send data packets that will generate ICMP packets at routers and dump those ICMP packets with tcpdump
, launched as a child process.
Then, I will read those ICMP packets back into my program with scapy's built-in rdpcap
function.
Well, it turns out that rdpcap
sometimes messes up something and as soon as I want to peek into my captured packets, it returns the following:
(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'
Then, I will just need to call rdpcap
again on the same argument and everything will go back to normal:
>>> icmpPackets = rdpcap(tcpdumpFileName)
>>> icmpPackets
<icmpPackets.cap: TCP:0 UDP:0 ICMP:1428 Other:1>
This is some bug, right?
EDIT: Ok, the one thing I do before I get that error is the following, which might not be too orthodox, but I don't need the ethernet layer when I'm forging packets. If I remove these two lines, I won't get any such errors:
for i in range(len(icmpPackets)):
icmpPackets[i] = icmpPackets[i].getlayer(IP)
I did this before elsewhere and never got a problem. What's happening here?
Upvotes: 2
Views: 1138
Reputation: 6237
Hi,
I don't really understand why you sniff traffic with tcpdump rather than scapy, but anyway... Your problem is not a bug in Scapy but rather in your code. You're replacing each packet with its .getlayer(IP)
which returns None
if the packet has no IP
layer (e.g., ARP
packets). Hence the exception you get latter.
I think you should replace
icmpPackets = rdpcap(tcpdumpFileName)
for i in range(len(icmpPackets)):
icmpPackets[i] = icmpPackets[i].getlayer(IP)
with
icmpPackets = PacketList([p[IP] for p in PcapReader(tcpdumpFileName) if IP in p])
First of all I think it's more "Pythonic", plus it fixes the problem by removing the packets without IP
layer. Or you could also use, if you want to have all the packets without the Ether
layer:
icmpPackets = PacketList([p.payload for p in PcapReader(tcpdumpFileName)])
Plus you could filter with a BPF filter in tcpdump (icmp
if you just want ICMP
packets).
Upvotes: 1