Skip to content

Commit 383bc32

Browse files
committed
working on pcapng protocol impl (added all block parsing)
1 parent c999984 commit 383bc32

File tree

3 files changed

+551
-103
lines changed

3 files changed

+551
-103
lines changed

pcapkit/foundation/engines/pcapng.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -122,12 +122,13 @@ def run(self) -> 'None':
122122
"""
123123
ext = self._extractor
124124

125-
shb = P_PCAPNG(ext._ifile, num=0, ctx=None)
125+
shb = P_PCAPNG(ext._ifile, num=0, sct=1, ctx=None)
126126
if shb.info.type != Enum_BlockType.Section_Header_Block:
127127
raise FormatError(f'PCAP-NG: [SHB] invalid block type: {shb.info.type!r}')
128128

129129
self._ctx = Context(cast('Data_SectionHeaderBlock', shb.info))
130130
self._ctx_list.append(self._ctx)
131+
shb._ctx = self._ctx
131132

132133
self._write_file(shb.info, name=f'Section Header {len(self._ctx_list)}')
133134

@@ -155,8 +156,8 @@ def read_frame(self) -> 'P_PCAPNG':
155156

156157
while True:
157158
# read next block
158-
block = P_PCAPNG(ext._ifile, num=ext._frnum+1, ctx=self._ctx,
159-
layer=ext._exlyr, protocol=ext._exptl,
159+
block = P_PCAPNG(ext._ifile, num=ext._frnum+1, sct=len(self._ctx_list),
160+
ctx=self._ctx, layer=ext._exlyr, protocol=ext._exptl,
160161
__packet__={
161162
'snaplen': self._get_snaplen(),
162163
})
@@ -165,6 +166,7 @@ def read_frame(self) -> 'P_PCAPNG':
165166
if block.info.type == Enum_BlockType.Section_Header_Block:
166167
self._ctx = Context(cast('Data_SectionHeaderBlock', block.info))
167168
self._ctx_list.append(self._ctx)
169+
block._ctx = self._ctx
168170

169171
self._write_file(block.info, name=f'Section Header {len(self._ctx_list)}')
170172

@@ -288,9 +290,9 @@ def _get_snaplen(self) -> 'int':
288290
argument when parsing a Simple Packet Block (SPB).
289291
290292
Notes:
291-
If there is no interface, return ``0xFFFFFFFFFFFFFFFF``.
293+
If there is no interface, return ``0xFFFF_FFFF_FFFF_FFFF``.
292294
293295
"""
294296
if self._ctx.interfaces:
295297
return self._ctx.interfaces[0].snaplen
296-
return 0xFFFFFFFFFFFFFFFF
298+
return 0xFFFF_FFFF_FFFF_FFFF

pcapkit/protocols/data/misc/pcapng.py

Lines changed: 55 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
# -*- coding: utf-8 -*-
22
"""data models for PCAP-NG file format"""
33

4+
import datetime
45
import decimal
56
from typing import TYPE_CHECKING
67

8+
from pcapkit.corekit.multidict import MultiDict
79
from pcapkit.protocols.data.data import Data
810

911
__all__ = [
@@ -34,11 +36,10 @@
3436
]
3537

3638
if TYPE_CHECKING:
37-
from datetime import datetime
39+
from datetime import datetime as dt_type
3840
from datetime import timezone as dt_timezone
3941
from decimal import Decimal
4042
from ipaddress import IPv4Address, IPv4Interface, IPv6Address, IPv6Interface
41-
from typing import Optional
4243

4344
from typing_extensions import Literal
4445

@@ -50,7 +51,7 @@
5051
from pcapkit.const.pcapng.secrets_type import SecretsType as Enum_SecretsType
5152
from pcapkit.const.pcapng.verdict_type import VerdictType as Enum_VerdictType
5253
from pcapkit.const.reg.linktype import LinkType as Enum_LinkType
53-
from pcapkit.corekit.multidict import MultiDict, OrderedMultiDict
54+
from pcapkit.corekit.multidict import OrderedMultiDict
5455
from pcapkit.corekit.version import VersionInfo
5556
from pcapkit.protocols.misc.pcapng import (PacketDirection, PacketReception, TLSKeyLabel,
5657
WireGuardKeyLabel)
@@ -412,7 +413,7 @@ class EnhancedPacketBlock(PCAPNG):
412413
#: Interface ID.
413414
interface_id: 'int'
414415
#: Timestamp (in seconds).
415-
timestamp: 'datetime'
416+
timestamp: 'dt_type'
416417
#: Timestamp as in UNIX epoch (in seconds).
417418
timestamp_epoch: 'Decimal'
418419
#: Captured packet length.
@@ -426,7 +427,8 @@ class EnhancedPacketBlock(PCAPNG):
426427
#: Protocol chain.
427428
protocols: 'str'
428429

429-
def __init__(self, section_number: 'int', number: 'int', interface_id: 'int', timestamp: 'datetime',
430+
def __init__(self, type: 'Enum_BlockType', length: 'int', section_number: 'int',
431+
number: 'int', interface_id: 'int', timestamp: 'dt_type',
430432
timestamp_epoch: 'Decimal', captured_len: 'int', original_len: 'int',
431433
options: 'OrderedMultiDict[Enum_OptionType, Option]') -> 'None': ...
432434

@@ -441,15 +443,17 @@ class SimplePacketBlock(PCAPNG):
441443

442444
#: Original packet length.
443445
original_len: 'int'
446+
#: Captured packet length.
447+
captured_len: 'int'
444448

445-
def __post_init__(self) -> None:
449+
def __post_init__(self) -> 'None':
446450
"""Post-initialization handling."""
447-
self.__update__(
448-
interface_id=0,
449-
timestamp=datetime.utcfromtimestamp(0),
450-
timestamp_epoch=decimal.Decimal(0),
451-
captured_len=self.length - 16,
452-
)
451+
with decimal.localcontext(prec=64):
452+
self.__update__(
453+
interface_id=0,
454+
timestamp=datetime.datetime.fromtimestamp(0, datetime.timezone.utc),
455+
timestamp_epoch=decimal.Decimal(0),
456+
)
453457

454458
if TYPE_CHECKING:
455459
#: Protocol chain.
@@ -458,14 +462,12 @@ def __post_init__(self) -> None:
458462
#: Interface ID.
459463
interface_id: 'int'
460464
#: Timestamp (in seconds).
461-
timestamp: 'datetime'
465+
timestamp: 'dt_type'
462466
#: Timestamp as in UNIX epoch (in seconds).
463467
timestamp_epoch: 'Decimal'
464-
#: Captured packet length.
465-
captured_len: 'int'
466468

467469
def __init__(self, section_number: 'int', number: 'int', type: 'Enum_BlockType',
468-
length: 'int', original_len: 'int') -> 'None': ...
470+
length: 'int', original_len: 'int', captured_len: 'int') -> 'None': ...
469471

470472

471473
class NameResolutionRecord(Data):
@@ -553,42 +555,60 @@ def __init__(self, type: 'Enum_OptionType', length: 'int', ip: 'IPv6Address') ->
553555
class NameResolutionBlock(PCAPNG):
554556
"""Data model for PCAP-NG Name Resolution Block (NRB)."""
555557

556-
#: Name resolution mapping (IP address -> name).
557-
mapping: 'MultiDict[IPv4Address | IPv6Address, str]'
558-
#: Name resolution mapping (name -> IP address).
559-
reverse_mapping: 'MultiDict[str, IPv4Address | IPv6Address]'
558+
#: Records.
559+
records: 'OrderedMultiDict[Enum_RecordType, NameResolutionRecord]'
560560
#: Options.
561561
options: 'OrderedMultiDict[Enum_OptionType, Option]'
562562

563+
def __post_init__(self) -> 'None':
564+
"""Post-initialization handling."""
565+
mapping = MultiDict() # type: MultiDict[IPv4Address | IPv6Address, str]
566+
reverse_mapping = MultiDict() # type: MultiDict[str, IPv4Address | IPv6Address]
567+
568+
for record in self.records:
569+
if isinstance(record, (IPv4Record, IPv6Record)):
570+
for name in record.names:
571+
mapping.add(record.ip, name)
572+
reverse_mapping.add(name, record.ip)
573+
574+
self.__update__(
575+
mapping=mapping,
576+
reverse_mapping=reverse_mapping,
577+
)
578+
563579
if TYPE_CHECKING:
564-
def __init__(self, type: 'Enum_BlockType', length: 'int', mapping: 'MultiDict[IPv4Address | IPv6Address, str]',
565-
reverse_mapping: 'MultiDict[str, IPv4Address | IPv6Address]',
580+
#: Name resolution mapping (IP address -> name).
581+
mapping: 'MultiDict[IPv4Address | IPv6Address, str]'
582+
#: Name resolution mapping (name -> IP address).
583+
reverse_mapping: 'MultiDict[str, IPv4Address | IPv6Address]'
584+
585+
def __init__(self, type: 'Enum_BlockType', length: 'int', records: 'OrderedMultiDict[Enum_RecordType, NameResolutionRecord]',
566586
options: 'OrderedMultiDict[Enum_OptionType, Option]') -> 'None': ...
567587

568588

569589
class ISB_StartTimeOption(Option):
570590
"""Data model for PCAP-NG ``isb_starttime`` option."""
571591

572592
#: Start time.
573-
timestamp: 'datetime'
593+
timestamp: 'dt_type'
574594
#: Start time as in UNIX epoch (in seconds).
575595
timestamp_epoch: 'Decimal'
576596

577597
if TYPE_CHECKING:
578-
def __init__(self, type: 'Enum_OptionType', length: 'int', timestamp: 'datetime',
598+
def __init__(self, type: 'Enum_OptionType', length: 'int', timestamp: 'dt_type',
579599
timestamp_epoch: 'Decimal') -> 'None': ...
580600

581601

582602
class ISB_EndTimeOption(Option):
583603
"""Data model for PCAP-NG ``isb_endtime`` option."""
584604

585605
#: End time.
586-
timestamp: 'datetime'
606+
timestamp: 'dt_type'
587607
#: End time as in UNIX epoch (in seconds).
588608
timestamp_epoch: 'Decimal'
589609

590610
if TYPE_CHECKING:
591-
def __init__(self, type: 'Enum_OptionType', length: 'int', timestamp: 'datetime',
611+
def __init__(self, type: 'Enum_OptionType', length: 'int', timestamp: 'dt_type',
592612
timestamp_epoch: 'Decimal') -> 'None': ...
593613

594614

@@ -648,25 +668,25 @@ class InterfaceStatisticsBlock(PCAPNG):
648668
#: Interface ID.
649669
interface_id: 'int'
650670
#: Timestamp.
651-
timestamp: 'datetime'
671+
timestamp: 'dt_type'
652672
#: Timestamp as in UNIX epoch (in seconds).
653673
timestamp_epoch: 'Decimal'
654674
#: Options.
655675
options: 'OrderedMultiDict[Enum_OptionType, Option]'
656676

657677
if TYPE_CHECKING:
658-
def __init__(self, type: 'Enum_BlockType', length: 'int', interface_id: 'int', timestamp: 'datetime',
678+
def __init__(self, type: 'Enum_BlockType', length: 'int', interface_id: 'int', timestamp: 'dt_type',
659679
timestamp_epoch: 'Decimal', options: 'OrderedMultiDict[Enum_OptionType, Option]') -> 'None': ...
660680

661681

662682
class SystemdJournalExportBlock(PCAPNG):
663683
"""Data model for PCAP-NG :manpage:`systemd(1)` Journal Export Block."""
664684

665685
#: Journal entry.
666-
data: 'tuple[OrderedMultiDict[str, str | bytes]]'
686+
data: 'tuple[OrderedMultiDict[str, str | bytes], ...]'
667687

668688
if TYPE_CHECKING:
669-
def __init__(self, type: 'Enum_BlockType', length: 'int', data: 'tuple[OrderedMultiDict[str, str | bytes]]') -> 'None': ...
689+
def __init__(self, type: 'Enum_BlockType', length: 'int', data: 'tuple[OrderedMultiDict[str, str | bytes], ...]') -> 'None': ...
670690

671691

672692
class DSBSecrets(Data):
@@ -752,7 +772,7 @@ class CustomBlock(PCAPNG):
752772

753773
#: Private enterprise number.
754774
pen: 'int'
755-
#: Custom block data.
775+
#: Custom block data (incl. data, options and padding).
756776
data: 'bytes'
757777

758778
if TYPE_CHECKING:
@@ -817,7 +837,7 @@ class PacketBlock(PCAPNG):
817837
#: Drops count.
818838
drop_count: 'int'
819839
#: Timestamp.
820-
timestamp: 'datetime'
840+
timestamp: 'dt_type'
821841
#: Timestamp as in UNIX epoch (in seconds).
822842
timestamp_epoch: 'Decimal'
823843
#: Captured packet length.
@@ -831,7 +851,7 @@ class PacketBlock(PCAPNG):
831851
#: Protocol chain.
832852
protocols: 'str'
833853

834-
def __init__(self, section_number: 'int', number: 'int', type: 'Enum_BlockType',
835-
length: 'int', interface_id: 'int', drop_count: 'int', timestamp: 'datetime',
854+
def __init__(self, type: 'Enum_BlockType', length: 'int', section_number: 'int', number: 'int',
855+
interface_id: 'int', drop_count: 'int', timestamp: 'dt_type',
836856
timestamp_epoch: 'Decimal', captured_length: 'int', original_length: 'int',
837-
protocols: 'str', options: 'OrderedMultiDict[Enum_OptionType, Option]') -> 'None': ...
857+
options: 'OrderedMultiDict[Enum_OptionType, Option]') -> 'None': ...

0 commit comments

Comments
 (0)