Skip to content
Snippets Groups Projects
Commit bc1d9d54 authored by Pierre LALET's avatar Pierre LALET
Browse files

Implement initial Pcap-NG support

parent 7d6808e5
No related branches found
No related tags found
No related merge requests found
...@@ -532,6 +532,17 @@ count: read only <count> packets""" ...@@ -532,6 +532,17 @@ count: read only <count> packets"""
with PcapReader(filename) as fdesc: with PcapReader(filename) as fdesc:
return fdesc.read_all(count=count) return fdesc.read_all(count=count)
def rdpcapng(filename, count=-1):
"""Read a pcap file and return a packet list
count: read only <count> packets"""
## Does not work with Python <= 2.5. Use this implementation as
## soon as we drop support for Python 2.5.
# with PcapNgReader(filename) as fdesc:
# return fdesc.read_all(count=count)
fdesc = PcapNgReader(filename)
result = fdesc.read_all(count=count)
fdesc.close()
return result
class RawPcapReader: class RawPcapReader:
...@@ -547,19 +558,20 @@ class RawPcapReader: ...@@ -547,19 +558,20 @@ class RawPcapReader:
magic = self.f.read(4) magic = self.f.read(4)
if magic == "\xa1\xb2\xc3\xd4": #big endian if magic == "\xa1\xb2\xc3\xd4": #big endian
self.endian = ">" self.endian = ">"
elif magic == "\xd4\xc3\xb2\xa1": #little endian elif magic == "\xd4\xc3\xb2\xa1": #little endian
self.endian = "<" self.endian = "<"
else: else:
raise Scapy_Exception("Not a pcap capture file (bad magic)") raise Scapy_Exception(
"Not a pcap capture file (bad magic: %r)" % magic
)
hdr = self.f.read(20) hdr = self.f.read(20)
if len(hdr)<20: if len(hdr)<20:
raise Scapy_Exception("Invalid pcap file (too short)") raise Scapy_Exception("Invalid pcap file (too short)")
vermaj,vermin,tz,sig,snaplen,linktype = struct.unpack(self.endian+"HHIIII",hdr) vermaj, vermin, tz, sig, snaplen, linktype = struct.unpack(
self.endian + "HHIIII", hdr
)
self.linktype = linktype self.linktype = linktype
def __iter__(self): def __iter__(self):
return self return self
...@@ -654,7 +666,104 @@ class PcapReader(RawPcapReader): ...@@ -654,7 +666,104 @@ class PcapReader(RawPcapReader):
return plist.PacketList(res,name = os.path.basename(self.filename)) return plist.PacketList(res,name = os.path.basename(self.filename))
def recv(self, size=MTU): def recv(self, size=MTU):
return self.read_packet(size=size) return self.read_packet(size=size)
class RawPcapNgReader(RawPcapReader):
"""A stateful pcapng reader. Each packet is returned as a
string.
"""
def __init__(self, filename):
self.filename = filename
# A list of (linktype, snaplen); will be populated by IDBs.
self.interfaces = []
self.blocktypes = {
1: self.read_block_idb,
6: self.read_block_epb,
}
try:
self.f = gzip.open(filename,"rb")
magic = self.f.read(4)
except IOError:
self.f = open(filename,"rb")
magic = self.f.read(4)
if magic != "\n\r\r\n": # PcapNg:
raise Scapy_Exception(
"Not a pcapng capture file (bad magic: %r)" % magic
)
# see https://github.com/pcapng/pcapng
blocklen, magic = self.f.read(4), self.f.read(4)
if magic == "\x1a\x2b\x3c\x4d":
self.endian = ">"
elif magic == "\x4d\x3c\x2b\x1a":
self.endian = "<"
else:
raise Scapy_Exception("Not a pcapng capture file (bad magic)")
self.f.seek(0)
def read_packet(self, size=MTU):
"""Read blocks until it reaches either EOF or a packet, and
returns None or (packet, (linktype, sec, usec, wirelen)),
where packet is a string.
"""
while True:
try:
blocktype, blocklen = struct.unpack(self.endian + "2I",
self.f.read(8))
except struct.error:
return None
block = self.f.read(blocklen - 12)
try:
if (blocklen,) != struct.unpack(self.endian + 'I',
self.f.read(4)):
raise Scapy_Exception(
"Invalid pcapng block (bad blocklen)"
)
except struct.error:
return None
res = self.blocktypes.get(blocktype,
lambda block, size: None)(block, size)
if res is not None:
return res
def read_block_idb(self, block, _):
"""Interface Description Block"""
self.interfaces.append(struct.unpack(self.endian + "HxxI", block[:8]))
def read_block_epb(self, block, size):
"""Enhanced Packet Block"""
intid, sec, usec, caplen, wirelen = struct.unpack(self.endian + "5I",
block[:20])
return (block[20:20 + caplen][:size],
(self.interfaces[intid][0], sec, usec, wirelen))
class PcapNgReader(RawPcapNgReader):
def __init__(self, filename):
RawPcapNgReader.__init__(self, filename)
def read_packet(self, size=MTU):
rp = RawPcapNgReader.read_packet(self, size=size)
if rp is None:
return None
s, (linktype, sec, usec, wirelen) = rp
try:
p = conf.l2types[linktype](s)
except KeyboardInterrupt:
raise
except:
if conf.debug_dissector:
raise
p = conf.raw_layer(s)
p.time = sec+0.000001*usec
return p
def read_all(self,count=-1):
res = RawPcapNgReader.read_all(self, count)
import plist
return plist.PacketList(res, name=os.path.basename(self.filename))
def recv(self, size=MTU):
return self.read_packet()
class RawPcapWriter: class RawPcapWriter:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment