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

Support nanosec precision in Pcap + fix TS in PcapNg

parent 44e8b8ac
No related branches found
No related tags found
No related merge requests found
...@@ -653,10 +653,18 @@ class RawPcapReader: ...@@ -653,10 +653,18 @@ class RawPcapReader:
def __init__(self, filename, fdesc, magic): def __init__(self, filename, fdesc, magic):
self.filename = filename self.filename = filename
self.f = fdesc self.f = fdesc
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 self.nano = False
elif magic == "\xd4\xc3\xb2\xa1": # little endian
self.endian = "<" self.endian = "<"
self.nano = False
elif magic == "\xa1\xb2\x3c\x4d": # big endian, nanosecond-precision
self.endian = ">"
self.nano = True
elif magic == "\x4d\x3c\xb2\xa1": # little endian, nanosecond-precision
self.endian = "<"
self.nano = True
else: else:
raise Scapy_Exception( raise Scapy_Exception(
"Not a pcap capture file (bad magic: %r)" % magic "Not a pcap capture file (bad magic: %r)" % magic
...@@ -755,7 +763,7 @@ class PcapReader(RawPcapReader): ...@@ -755,7 +763,7 @@ class PcapReader(RawPcapReader):
if conf.debug_dissector: if conf.debug_dissector:
raise raise
p = conf.raw_layer(s) p = conf.raw_layer(s)
p.time = sec+0.000001*usec p.time = sec + (0.000000001 if self.nano else 0.000001) * usec
return p return p
def read_all(self,count=-1): def read_all(self,count=-1):
res = RawPcapReader.read_all(self, count) res = RawPcapReader.read_all(self, count)
...@@ -824,14 +832,15 @@ class RawPcapNgReader(RawPcapReader): ...@@ -824,14 +832,15 @@ class RawPcapNgReader(RawPcapReader):
def read_block_idb(self, block, _): def read_block_idb(self, block, _):
"""Interface Description Block""" """Interface Description Block"""
# We should read options to set if_tsresol
self.interfaces.append(struct.unpack(self.endian + "HxxI", block[:8])) self.interfaces.append(struct.unpack(self.endian + "HxxI", block[:8]))
def read_block_epb(self, block, size): def read_block_epb(self, block, size):
"""Enhanced Packet Block""" """Enhanced Packet Block"""
intid, sec, usec, caplen, wirelen = struct.unpack(self.endian + "5I", intid, tshigh, tslow, caplen, wirelen = struct.unpack(self.endian + "5I",
block[:20]) block[:20])
return (block[20:20 + caplen][:size], return (block[20:20 + caplen][:size],
(self.interfaces[intid][0], sec, usec, wirelen)) (self.interfaces[intid][0], tshigh, tslow, wirelen))
class PcapNgReader(RawPcapNgReader): class PcapNgReader(RawPcapNgReader):
...@@ -845,7 +854,7 @@ class PcapNgReader(RawPcapNgReader): ...@@ -845,7 +854,7 @@ class PcapNgReader(RawPcapNgReader):
rp = RawPcapNgReader.read_packet(self, size=size) rp = RawPcapNgReader.read_packet(self, size=size)
if rp is None: if rp is None:
return None return None
s, (linktype, sec, usec, wirelen) = rp s, (linktype, tshigh, tslow, wirelen) = rp
try: try:
p = conf.l2types[linktype](s) p = conf.l2types[linktype](s)
except KeyboardInterrupt: except KeyboardInterrupt:
...@@ -854,7 +863,9 @@ class PcapNgReader(RawPcapNgReader): ...@@ -854,7 +863,9 @@ class PcapNgReader(RawPcapNgReader):
if conf.debug_dissector: if conf.debug_dissector:
raise raise
p = conf.raw_layer(s) p = conf.raw_layer(s)
p.time = sec+0.000001*usec # We should use if_tsresol when available (see
# RawPcapNgReader.read_block_idb)
p.time = float((tshigh << 32) + tslow) / 1000000
return p return p
def read_all(self,count=-1): def read_all(self,count=-1):
res = RawPcapNgReader.read_all(self, count) res = RawPcapNgReader.read_all(self, count)
...@@ -866,16 +877,18 @@ class PcapNgReader(RawPcapNgReader): ...@@ -866,16 +877,18 @@ class PcapNgReader(RawPcapNgReader):
class RawPcapWriter: class RawPcapWriter:
"""A stream PCAP writer with more control than wrpcap()""" """A stream PCAP writer with more control than wrpcap()"""
def __init__(self, filename, linktype=None, gz=False, endianness="", append=False, sync=False): def __init__(self, filename, linktype=None, gz=False, endianness="",
append=False, sync=False, nano=False):
""" """
filename: the name of the file to write packets to, or an open, filename: the name of the file to write packets to, or an open,
writable file-like object. writable file-like object.
linktype: force linktype to a given value. If None, linktype is taken linktype: force linktype to a given value. If None, linktype is taken
from the first writer packet from the first writer packet
gz: compress the capture on the fly gz: compress the capture on the fly
endianness: force an endianness (little:"<", big:">"). Default is native endianness: force an endianness (little:"<", big:">"). Default is native
append: append packets to the capture file instead of truncating it append: append packets to the capture file instead of truncating it
sync: do not bufferize writes to the capture file sync: do not bufferize writes to the capture file
nano: use nanosecond-precision (requires libpcap >= 1.5.0)
""" """
...@@ -885,6 +898,7 @@ sync: do not bufferize writes to the capture file ...@@ -885,6 +898,7 @@ sync: do not bufferize writes to the capture file
self.gz = gz self.gz = gz
self.endian = endianness self.endian = endianness
self.sync = sync self.sync = sync
self.nano = nano
bufsz=4096 bufsz=4096
if sync: if sync:
bufsz = 0 bufsz = 0
...@@ -913,7 +927,7 @@ sync: do not bufferize writes to the capture file ...@@ -913,7 +927,7 @@ sync: do not bufferize writes to the capture file
if g.read(16): if g.read(16):
return return
self.f.write(struct.pack(self.endian+"IHHIIII", 0xa1b2c3d4L, self.f.write(struct.pack(self.endian+"IHHIIII", 0xa1b23c4dL if self.nano else 0xa1b2c3d4L,
2, 4, 0, 0, MTU, self.linktype)) 2, 4, 0, 0, MTU, self.linktype))
self.f.flush() self.f.flush()
...@@ -958,7 +972,7 @@ sync: do not bufferize writes to the capture file ...@@ -958,7 +972,7 @@ sync: do not bufferize writes to the capture file
if sec is None: if sec is None:
sec = it sec = it
if usec is None: if usec is None:
usec = int(round((t-it)*1000000)) usec = int(round((t - it) * (1000000000 if self.nano else 1000000)))
self.f.write(struct.pack(self.endian+"IIII", sec, usec, caplen, wirelen)) self.f.write(struct.pack(self.endian+"IIII", sec, usec, caplen, wirelen))
self.f.write(packet) self.f.write(packet)
if self.sync: if self.sync:
...@@ -996,7 +1010,7 @@ class PcapWriter(RawPcapWriter): ...@@ -996,7 +1010,7 @@ class PcapWriter(RawPcapWriter):
self._write_packet(pkt) self._write_packet(pkt)
return return
sec = int(packet.time) sec = int(packet.time)
usec = int(round((packet.time-sec)*1000000)) usec = int(round((packet.time - sec) * (1000000000 if self.nano else 1000000)))
s = str(packet) s = str(packet)
caplen = len(s) caplen = len(s)
RawPcapWriter._write_packet(self, s, sec, usec, caplen, caplen) RawPcapWriter._write_packet(self, s, sec, usec, caplen, caplen)
......
...@@ -4609,6 +4609,7 @@ nf5.version == 5 and nf5[NetflowHeaderV5].count == 2 and isinstance(nf5[NetflowR ...@@ -4609,6 +4609,7 @@ nf5.version == 5 and nf5[NetflowHeaderV5].count == 2 and isinstance(nf5[NetflowR
import cStringIO import cStringIO
pcapfile = cStringIO.StringIO('\xd4\xc3\xb2\xa1\x02\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00e\x00\x00\x00\xcf\xc5\xacVo*\n\x00(\x00\x00\x00(\x00\x00\x00E\x00\x00(\x00\x01\x00\x00@\x06|\xcd\x7f\x00\x00\x01\x7f\x00\x00\x01\x00\x14\x00P\x00\x00\x00\x00\x00\x00\x00\x00P\x02 \x00\x91|\x00\x00\xcf\xc5\xacV_-\n\x00\x1c\x00\x00\x00\x1c\x00\x00\x00E\x00\x00\x1c\x00\x01\x00\x00@\x11|\xce\x7f\x00\x00\x01\x7f\x00\x00\x01\x005\x005\x00\x08\x01r\xcf\xc5\xacV\xf90\n\x00\x1c\x00\x00\x00\x1c\x00\x00\x00E\x00\x00\x1c\x00\x01\x00\x00@\x01|\xde\x7f\x00\x00\x01\x7f\x00\x00\x01\x08\x00\xf7\xff\x00\x00\x00\x00') pcapfile = cStringIO.StringIO('\xd4\xc3\xb2\xa1\x02\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00e\x00\x00\x00\xcf\xc5\xacVo*\n\x00(\x00\x00\x00(\x00\x00\x00E\x00\x00(\x00\x01\x00\x00@\x06|\xcd\x7f\x00\x00\x01\x7f\x00\x00\x01\x00\x14\x00P\x00\x00\x00\x00\x00\x00\x00\x00P\x02 \x00\x91|\x00\x00\xcf\xc5\xacV_-\n\x00\x1c\x00\x00\x00\x1c\x00\x00\x00E\x00\x00\x1c\x00\x01\x00\x00@\x11|\xce\x7f\x00\x00\x01\x7f\x00\x00\x01\x005\x005\x00\x08\x01r\xcf\xc5\xacV\xf90\n\x00\x1c\x00\x00\x00\x1c\x00\x00\x00E\x00\x00\x1c\x00\x01\x00\x00@\x01|\xde\x7f\x00\x00\x01\x7f\x00\x00\x01\x08\x00\xf7\xff\x00\x00\x00\x00')
pcapngfile = cStringIO.StringIO('\n\r\r\n\\\x00\x00\x00M<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x01\x00,\x00File created by merging: \nFile1: test.pcap \n\x04\x00\x08\x00mergecap\x00\x00\x00\x00\\\x00\x00\x00\x01\x00\x00\x00\\\x00\x00\x00e\x00\x00\x00\xff\xff\x00\x00\x02\x006\x00Unknown/not available in original file format(libpcap)\x00\x00\t\x00\x01\x00\x06\x00\x00\x00\x00\x00\x00\x00\\\x00\x00\x00\x06\x00\x00\x00H\x00\x00\x00\x00\x00\x00\x00\x8d*\x05\x00/\xfc[\xcd(\x00\x00\x00(\x00\x00\x00E\x00\x00(\x00\x01\x00\x00@\x06|\xcd\x7f\x00\x00\x01\x7f\x00\x00\x01\x00\x14\x00P\x00\x00\x00\x00\x00\x00\x00\x00P\x02 \x00\x91|\x00\x00H\x00\x00\x00\x06\x00\x00\x00<\x00\x00\x00\x00\x00\x00\x00\x8d*\x05\x00\x1f\xff[\xcd\x1c\x00\x00\x00\x1c\x00\x00\x00E\x00\x00\x1c\x00\x01\x00\x00@\x11|\xce\x7f\x00\x00\x01\x7f\x00\x00\x01\x005\x005\x00\x08\x01r<\x00\x00\x00\x06\x00\x00\x00<\x00\x00\x00\x00\x00\x00\x00\x8d*\x05\x00\xb9\x02\\\xcd\x1c\x00\x00\x00\x1c\x00\x00\x00E\x00\x00\x1c\x00\x01\x00\x00@\x01|\xde\x7f\x00\x00\x01\x7f\x00\x00\x01\x08\x00\xf7\xff\x00\x00\x00\x00<\x00\x00\x00') pcapngfile = cStringIO.StringIO('\n\r\r\n\\\x00\x00\x00M<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x01\x00,\x00File created by merging: \nFile1: test.pcap \n\x04\x00\x08\x00mergecap\x00\x00\x00\x00\\\x00\x00\x00\x01\x00\x00\x00\\\x00\x00\x00e\x00\x00\x00\xff\xff\x00\x00\x02\x006\x00Unknown/not available in original file format(libpcap)\x00\x00\t\x00\x01\x00\x06\x00\x00\x00\x00\x00\x00\x00\\\x00\x00\x00\x06\x00\x00\x00H\x00\x00\x00\x00\x00\x00\x00\x8d*\x05\x00/\xfc[\xcd(\x00\x00\x00(\x00\x00\x00E\x00\x00(\x00\x01\x00\x00@\x06|\xcd\x7f\x00\x00\x01\x7f\x00\x00\x01\x00\x14\x00P\x00\x00\x00\x00\x00\x00\x00\x00P\x02 \x00\x91|\x00\x00H\x00\x00\x00\x06\x00\x00\x00<\x00\x00\x00\x00\x00\x00\x00\x8d*\x05\x00\x1f\xff[\xcd\x1c\x00\x00\x00\x1c\x00\x00\x00E\x00\x00\x1c\x00\x01\x00\x00@\x11|\xce\x7f\x00\x00\x01\x7f\x00\x00\x01\x005\x005\x00\x08\x01r<\x00\x00\x00\x06\x00\x00\x00<\x00\x00\x00\x00\x00\x00\x00\x8d*\x05\x00\xb9\x02\\\xcd\x1c\x00\x00\x00\x1c\x00\x00\x00E\x00\x00\x1c\x00\x01\x00\x00@\x01|\xde\x7f\x00\x00\x01\x7f\x00\x00\x01\x08\x00\xf7\xff\x00\x00\x00\x00<\x00\x00\x00')
pcapnanofile = cStringIO.StringIO("M<\xb2\xa1\x02\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00e\x00\x00\x00\xcf\xc5\xacV\xc9\xc1\xb5'(\x00\x00\x00(\x00\x00\x00E\x00\x00(\x00\x01\x00\x00@\x06|\xcd\x7f\x00\x00\x01\x7f\x00\x00\x01\x00\x14\x00P\x00\x00\x00\x00\x00\x00\x00\x00P\x02 \x00\x91|\x00\x00\xcf\xc5\xacV-;\xc1'\x1c\x00\x00\x00\x1c\x00\x00\x00E\x00\x00\x1c\x00\x01\x00\x00@\x11|\xce\x7f\x00\x00\x01\x7f\x00\x00\x01\x005\x005\x00\x08\x01r\xcf\xc5\xacV\x9aL\xcf'\x1c\x00\x00\x00\x1c\x00\x00\x00E\x00\x00\x1c\x00\x01\x00\x00@\x01|\xde\x7f\x00\x00\x01\x7f\x00\x00\x01\x08\x00\xf7\xff\x00\x00\x00\x00")
= Read a pcap file = Read a pcap file
pktpcap = rdpcap(pcapfile) pktpcap = rdpcap(pcapfile)
...@@ -4616,17 +4617,17 @@ pktpcap = rdpcap(pcapfile) ...@@ -4616,17 +4617,17 @@ pktpcap = rdpcap(pcapfile)
= Read a pcapng file = Read a pcapng file
pktpcapng = rdpcap(pcapngfile) pktpcapng = rdpcap(pcapngfile)
= Check both packet lists are the same = Read a pcap file with nanosecond precision
assert list(pktpcap) == list(pktpcapng) pktpcapnano = rdpcap(pcapnanofile)
= Check all packet lists are the same
assert list(pktpcap) == list(pktpcapng) == list(pktpcapnano)
assert [p.time for p in pktpcap] == [p.time for p in pktpcapng] == [p.time for p in pktpcapnano]
= Check packets from pcap file = Check packets from pcap file
assert all(IP in pkt for pkt in pktpcap) assert all(IP in pkt for pkt in pktpcap)
assert all(any(proto in pkt for pkt in pktpcap) for proto in [ICMP, UDP, TCP]) assert all(any(proto in pkt for pkt in pktpcap) for proto in [ICMP, UDP, TCP])
= Check packets from pcap file
assert all(IP in pkt for pkt in pktpcapng)
assert all(any(proto in pkt for pkt in pktpcapng) for proto in [ICMP, UDP, TCP])
= Check wrpcap() = Check wrpcap()
import os, tempfile import os, tempfile
fdesc, filename = tempfile.mkstemp() fdesc, filename = tempfile.mkstemp()
...@@ -4656,6 +4657,17 @@ fdesc.close() ...@@ -4656,6 +4657,17 @@ fdesc.close()
assert list(pktpcap[TCP]) == list(pktpcap_tcp) assert list(pktpcap[TCP]) == list(pktpcap_tcp)
os.unlink(filename) os.unlink(filename)
= Check wrpcap(nano=True)
fdesc, filename = tempfile.mkstemp()
fdesc = os.fdopen(fdesc, "w")
pktpcapnano[0].time += 0.000000001
wrpcap(fdesc, pktpcapnano, nano=True)
fdesc.close()
pktpcapnanoread = rdpcap(filename)
assert pktpcapnanoread[0].time == pktpcapnano[0].time
assert pktpcapnanoread[0].time == pktpcap[0].time + 0.000000001
os.unlink(filename)
############ ############
############ ############
......
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