Reputation: 393
Here is a simple exmaple:
from scapy.all import *
pkts = rdpcap('/tmp/sample.pcap')
wireshark(pkts)
Then wireshark gives this error:
The capture file appears to be damaged or corrupt.
(libpcap: IrDA capture has a packet with an invalid sll_protocol field)
I am using wireshark 1.8, python 2.7.3 and scapy 2.2.0.
NOTE: I can open the smaple.pcap file using wireshark directly.
What can I do to make scapy-generated pcap files to open in wireshark?
EDIT: I tried other pcap files (from wireshark capture samples) and it worked. It seems the problem is in my packets. Here is the first packet (which don't work also):
###[ cooked linux ]###
pkttype = unicast
lladdrtype= 0x1
lladdrlen = 6
src = '\x00\x04\xed\xcb\x9b0'
proto = 0x800
###[ IP ]###
version = 4L
ihl = 5L
tos = 0xb8
len = 165
id = 47433
flags =
frag = 0L
ttl = 49
proto = udp
chksum = 0x50c9
src = 22.31.32.55
dst = 192.168.1.102
\options \
###[ UDP ]###
sport = 4566
dport = 4566
len = 145
chksum = 0x0
###[ Raw ]###
load = 'H\x84\x80\x80\x80\x80\x80\x8c\x80\x80\x86\x81\x8b\x82\x80\x82\x81\x98\xb1\xb9\xb2\xae\xb1\xb6\xb8\xae\xb1\xae\xb2\xb5\xad\xb0\xb1\xb2\xb2\xb6\xb6\xb5\xb7\xb4\xb9\xb4\xad\x81\xca\x82\x89\xb9\xb9\xb5\xb0\xb6\xb1\xb0\xb3\xb3\xa6\x81\x80\xa7\x81\x80\xa8\x82\x80\x80\x84\x89\xb9\xb9\xb5\xb0\xb6\xb1\xb0\xb3\xb3\x8a\x82\xe5\xee\x86\x88\xe3\xe3\xec\xe9\xe5\xee\xf4\xb2\x89\x84\x80\x80\x81\x80\xb8\x89\x80\x80\x80\x80\x80\x80\x80\x81\x80\x88\x84\x80\x80\x81\x80\xb7\x89\x80\x80\x80\x80\x80\x80\x80\x81\x80\x8c\x82\x80\x82\x9f\x84\x9e\xa7 \xe2\xb6\x80'
Note: changed IP addresses so checksum might not be correct.
Upvotes: 3
Views: 2822
Reputation: 9614
I have no idea what seems to be the problem, but it can be resolved in the following manner:
wireshark(pkt for pkt in pkts) # don't supply a list but rather a generator
This also outputs the following message:
WARNING: PcapWriter: unknown LL type for generator. Using type 1 (Ethernet)
Apparently, the wireshark
function doesn't handle a Linux cooked-mode capture that well. This odd situation might have something to do with the following excerpt from scapy
's wiki:
Please remember that Wireshark works with Layer 2 packets (usually called "frames"). So we had to add an
Ether()
header to our ICMP packets. Passing just IP packets (layer 3) to Wireshark will give strange results.
We can also circumvent this issue by creating a dummy Ethernet layer, if we don't really care about the layer 2 frame:
pkts = [Ether(src=pkt[0].src)/pkt[1:] for pkt in pkts]
EDIT - upon further research, and analyzing scapy's source code, I figured out why passing a generator object seems to solve this issue.
The wireshark
function creates a temporary file containing the packets and launches Wireshark with that file. The link type to be specified in the header of that file is extracted in the following manner:
if self.linktype == None:
if type(pkt) is list or type(pkt) is tuple or isinstance(pkt,BasePacketList):
pkt = pkt[0]
try:
self.linktype = conf.l2types[pkt.__class__]
except KeyError:
warning("PcapWriter: unknown LL type for %s. Using type 1 (Ethernet)" % pkt.__class__.__name__)
self.linktype = 1
When passing a generator object, the first if
statement evaluates to False
(which is obviously a bug) and an exception is raised when attempting to access conf.l2types[pkt.__class__]
since pkt.__class__
is <type 'generator'>
. Therefore, the except clause of the try-except
code block is executed and the link type is specified as 1.
However, when passing a real list, the first if
statement evaluates to True
and the first packet of the list is extracted and used to access conf.l2types
, which is:
In [2]: conf.l2types
Out[2]:
0x1 <- Dot3 (802.3)
0x1 <-> Ether (Ethernet)
0xc -> IP (IP)
0x17 -> Ether (Ethernet)
0x1f <-> IPv6 (IPv6)
0x65 <-> IP (IP)
0x69 <-> Dot11 (802.11)
0x71 -> CookedLinux (cooked linux)
0x77 <-> PrismHeader (Prism header)
0x7f <-> RadioTap (RadioTap dummy)
0x90 <-> CookedLinux (cooked linux)
0xc0 <-> PPI (Per-Packet Information header (partial))
0x304 -> Ether (Ethernet)
0x321 -> Dot11 (802.11)
0x322 -> PrismHeader (Prism header)
0x323 -> RadioTap (RadioTap dummy)
Since pkts[0].__class__
is scapy.layers.l2.CookedLinux
, the link type is set to 0x90
rather than to 0x71
(seems like yet another bug), which results in Wireshark failing to parse the file.
Therefore, I think that the best approach would be to copycat scapy's wireshark
function, with the subtle change of allowing the user to explicitly specify the link type:
def wireshark(*args, **kwargs):
"""Run wireshark on a list of packets"""
f = scapy.all.get_temp_file()
scapy.all.wrpcap(f, *args, **kwargs)
subprocess.Popen([scapy.all.conf.prog.wireshark, "-r", f])
wireshark(pkts, linktype=0x71)
EDIT - I've now noticed that the link type mapping issue was already reported and fixed by secdev. However, it hasn't reached python-scapy
just yet. I've also created a new issue on the invalid handling of a generator object in PcapWriter
.
Upvotes: 5
Reputation:
(libpcap: IrDA capture has a packet with an invalid sll_protocol field)
Linux IrDA uses something like the Linux cooked-mode header, but it's not the same:
I don't know what caused your program to choose 144 rather than 113; was your input file an Linux IrDA file rather than a Linux cooked capture file?
Upvotes: 0