Skip to content

Commit 24f99f4

Browse files
authored
modpcap reader support (#633)
1 parent 85d5e94 commit 24f99f4

File tree

1 file changed

+75
-6
lines changed

1 file changed

+75
-6
lines changed

dpkt/pcap.py

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,15 @@
1111
from . import dpkt
1212
from .compat import intround
1313

14+
# big endian magics
1415
TCPDUMP_MAGIC = 0xa1b2c3d4
1516
TCPDUMP_MAGIC_NANO = 0xa1b23c4d
17+
MODPCAP_MAGIC = 0xa1b2cd34
18+
19+
# little endian magics
1620
PMUDPCT_MAGIC = 0xd4c3b2a1
1721
PMUDPCT_MAGIC_NANO = 0x4d3cb2a1
22+
PACPDOM_MAGIC = 0x34cdb2a1
1823

1924
PCAP_VERSION_MAJOR = 2
2025
PCAP_VERSION_MINOR = 4
@@ -159,9 +164,44 @@ class PktHdr(dpkt.Packet):
159164
)
160165

161166

167+
class PktModHdr(dpkt.Packet):
168+
"""modified pcap packet header.
169+
https://wiki.wireshark.org/Development/LibpcapFileFormat#modified-pcap
170+
171+
TODO: Longer class information....
172+
173+
Attributes:
174+
__hdr__: Header fields of pcap header.
175+
TODO.
176+
"""
177+
__hdr__ = (
178+
('tv_sec', 'I', 0),
179+
('tv_usec', 'I', 0),
180+
('caplen', 'I', 0),
181+
('len', 'I', 0),
182+
('ifindex', 'I', 0),
183+
('protocol', 'H', 0),
184+
('pkt_type', 'B', 0),
185+
('pad', 'B', 0),
186+
)
187+
188+
162189
class LEPktHdr(PktHdr):
163190
__byte_order__ = '<'
164191

192+
class LEPktModHdr(PktModHdr):
193+
__byte_order__ = '<'
194+
195+
196+
MAGIC_TO_PKT_HDR = {
197+
TCPDUMP_MAGIC: PktHdr,
198+
TCPDUMP_MAGIC_NANO: PktHdr,
199+
MODPCAP_MAGIC: PktModHdr,
200+
PMUDPCT_MAGIC: LEPktHdr,
201+
PMUDPCT_MAGIC_NANO: LEPktHdr,
202+
PACPDOM_MAGIC: LEPktModHdr
203+
}
204+
165205

166206
class FileHdr(dpkt.Packet):
167207
"""pcap file header.
@@ -277,17 +317,24 @@ def __init__(self, fileobj):
277317
self.__f = fileobj
278318
buf = self.__f.read(FileHdr.__hdr_len__)
279319
self.__fh = FileHdr(buf)
280-
self.__ph = PktHdr
281-
if self.__fh.magic in (PMUDPCT_MAGIC, PMUDPCT_MAGIC_NANO):
320+
321+
# save magic
322+
magic = self.__fh.magic
323+
324+
if magic in (PMUDPCT_MAGIC, PMUDPCT_MAGIC_NANO, PACPDOM_MAGIC):
282325
self.__fh = LEFileHdr(buf)
283-
self.__ph = LEPktHdr
284-
elif self.__fh.magic not in (TCPDUMP_MAGIC, TCPDUMP_MAGIC_NANO):
326+
327+
if magic not in MAGIC_TO_PKT_HDR:
285328
raise ValueError('invalid tcpdump header')
329+
330+
self.__ph = MAGIC_TO_PKT_HDR[magic]
331+
332+
286333
if self.__fh.linktype in dltoff:
287334
self.dloff = dltoff[self.__fh.linktype]
288335
else:
289336
self.dloff = 0
290-
self._divisor = 1E6 if self.__fh.magic in (TCPDUMP_MAGIC, PMUDPCT_MAGIC) else Decimal('1E9')
337+
self._divisor = Decimal('1E9') if magic in (TCPDUMP_MAGIC_NANO, PMUDPCT_MAGIC_NANO) else 1E6
291338
self.snaplen = self.__fh.snaplen
292339
self.filter = ''
293340
self.__iter = iter(self)
@@ -344,7 +391,7 @@ def loop(self, callback, *args):
344391

345392
def __iter__(self):
346393
while 1:
347-
buf = self.__f.read(PktHdr.__hdr_len__)
394+
buf = self.__f.read(self.__ph.__hdr_len__)
348395
if not buf:
349396
break
350397
hdr = self.__ph(buf)
@@ -418,6 +465,12 @@ class TestData():
418465
b'\x18\xb1\x0c\xad\x08\x00\x45\x00\x00\x38\x00\x00\x40\x00\x40\x11\x65\x47\xc0\xa8\xaa\x08\xc0\xa8'
419466
b'\xaa\x14\x80\x1b\x00\x35\x00\x24\x85\xed'
420467
)
468+
modified_pcap = (
469+
b'\x34\xcd\xb2\xa1\x02\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x01\x00\x00\x00'
470+
b'\x3c\xfb\x80\x61\x6d\x32\x08\x00\x03\x00\x00\x00\x72\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
471+
b'\xff\xff\xff'
472+
473+
)
421474

422475

423476
def test_reader():
@@ -520,6 +573,22 @@ def test_reader_fd():
520573
assert reader.fileno() == fd.fileno()
521574

522575

576+
def test_reader_modified_pcap_type():
577+
data = TestData().modified_pcap
578+
579+
import tempfile
580+
with tempfile.TemporaryFile() as fd:
581+
fd.write(data)
582+
fd.seek(0)
583+
reader = Reader(fd)
584+
assert reader.fd == fd.fileno()
585+
assert reader.fileno() == fd.fileno()
586+
587+
timestamp, pkts = next(reader)
588+
assert pkts == 3 * b'\xff'
589+
assert timestamp == 1635842876.537197000
590+
591+
523592
class WriterTestWrap:
524593
"""
525594
Decorate a writer test function with an instance of this class.

0 commit comments

Comments
 (0)