|
11 | 11 | from . import dpkt |
12 | 12 | from .compat import intround |
13 | 13 |
|
| 14 | +# big endian magics |
14 | 15 | TCPDUMP_MAGIC = 0xa1b2c3d4 |
15 | 16 | TCPDUMP_MAGIC_NANO = 0xa1b23c4d |
| 17 | +MODPCAP_MAGIC = 0xa1b2cd34 |
| 18 | + |
| 19 | +# little endian magics |
16 | 20 | PMUDPCT_MAGIC = 0xd4c3b2a1 |
17 | 21 | PMUDPCT_MAGIC_NANO = 0x4d3cb2a1 |
| 22 | +PACPDOM_MAGIC = 0x34cdb2a1 |
18 | 23 |
|
19 | 24 | PCAP_VERSION_MAJOR = 2 |
20 | 25 | PCAP_VERSION_MINOR = 4 |
@@ -159,9 +164,44 @@ class PktHdr(dpkt.Packet): |
159 | 164 | ) |
160 | 165 |
|
161 | 166 |
|
| 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 | + |
162 | 189 | class LEPktHdr(PktHdr): |
163 | 190 | __byte_order__ = '<' |
164 | 191 |
|
| 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 | + |
165 | 205 |
|
166 | 206 | class FileHdr(dpkt.Packet): |
167 | 207 | """pcap file header. |
@@ -277,17 +317,24 @@ def __init__(self, fileobj): |
277 | 317 | self.__f = fileobj |
278 | 318 | buf = self.__f.read(FileHdr.__hdr_len__) |
279 | 319 | 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): |
282 | 325 | 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: |
285 | 328 | raise ValueError('invalid tcpdump header') |
| 329 | + |
| 330 | + self.__ph = MAGIC_TO_PKT_HDR[magic] |
| 331 | + |
| 332 | + |
286 | 333 | if self.__fh.linktype in dltoff: |
287 | 334 | self.dloff = dltoff[self.__fh.linktype] |
288 | 335 | else: |
289 | 336 | 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 |
291 | 338 | self.snaplen = self.__fh.snaplen |
292 | 339 | self.filter = '' |
293 | 340 | self.__iter = iter(self) |
@@ -344,7 +391,7 @@ def loop(self, callback, *args): |
344 | 391 |
|
345 | 392 | def __iter__(self): |
346 | 393 | while 1: |
347 | | - buf = self.__f.read(PktHdr.__hdr_len__) |
| 394 | + buf = self.__f.read(self.__ph.__hdr_len__) |
348 | 395 | if not buf: |
349 | 396 | break |
350 | 397 | hdr = self.__ph(buf) |
@@ -418,6 +465,12 @@ class TestData(): |
418 | 465 | 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' |
419 | 466 | b'\xaa\x14\x80\x1b\x00\x35\x00\x24\x85\xed' |
420 | 467 | ) |
| 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 | + ) |
421 | 474 |
|
422 | 475 |
|
423 | 476 | def test_reader(): |
@@ -520,6 +573,22 @@ def test_reader_fd(): |
520 | 573 | assert reader.fileno() == fd.fileno() |
521 | 574 |
|
522 | 575 |
|
| 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 | + |
523 | 592 | class WriterTestWrap: |
524 | 593 | """ |
525 | 594 | Decorate a writer test function with an instance of this class. |
|
0 commit comments