pypcapkit 1.3.1.post7__pp38-none-any.whl → 1.3.5.post6__pp38-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. pcapkit/__init__.py +1 -3
  2. pcapkit/__main__.py +2 -2
  3. pcapkit/const/ftp/command.py +2 -2
  4. pcapkit/const/ftp/return_code.py +11 -21
  5. pcapkit/const/http/status_code.py +7 -3
  6. pcapkit/const/ipv6/extension_header.py +3 -0
  7. pcapkit/const/ipv6/router_alert.py +1 -1
  8. pcapkit/const/ipv6/routing.py +2 -4
  9. pcapkit/const/ipx/packet.py +3 -0
  10. pcapkit/const/ipx/socket.py +2 -2
  11. pcapkit/const/mh/status_code.py +1 -1
  12. pcapkit/const/reg/apptype.py +94 -32
  13. pcapkit/const/reg/ethertype.py +8 -10
  14. pcapkit/const/reg/linktype.py +48 -81
  15. pcapkit/const/reg/transtype.py +9 -3
  16. pcapkit/const/tcp/option.py +2 -2
  17. pcapkit/corekit/infoclass.py +2 -0
  18. pcapkit/dumpkit/pcap.py +13 -5
  19. pcapkit/protocols/data/application/ftp.py +2 -2
  20. pcapkit/protocols/data/application/httpv1.py +2 -1
  21. pcapkit/protocols/data/application/httpv2.py +2 -1
  22. pcapkit/protocols/data/internet/ah.py +2 -2
  23. pcapkit/protocols/data/internet/hip.py +2 -1
  24. pcapkit/protocols/data/internet/hopopt.py +2 -1
  25. pcapkit/protocols/data/internet/ipv4.py +2 -1
  26. pcapkit/protocols/data/internet/ipv6.py +2 -2
  27. pcapkit/protocols/data/internet/ipv6_frag.py +2 -2
  28. pcapkit/protocols/data/internet/ipv6_opts.py +2 -1
  29. pcapkit/protocols/data/internet/ipv6_route.py +2 -2
  30. pcapkit/protocols/data/internet/ipx.py +2 -1
  31. pcapkit/protocols/data/internet/mh.py +2 -1
  32. pcapkit/protocols/data/link/arp.py +2 -1
  33. pcapkit/protocols/data/link/ethernet.py +2 -1
  34. pcapkit/protocols/data/link/l2tp.py +4 -2
  35. pcapkit/protocols/data/link/ospf.py +4 -2
  36. pcapkit/protocols/data/link/vlan.py +2 -1
  37. pcapkit/protocols/data/misc/null.py +2 -2
  38. pcapkit/protocols/data/misc/pcap/frame.py +4 -2
  39. pcapkit/protocols/data/misc/pcap/header.py +2 -1
  40. pcapkit/protocols/data/misc/pcapng.py +16 -8
  41. pcapkit/protocols/data/misc/raw.py +3 -5
  42. pcapkit/protocols/data/protocol.py +8 -0
  43. pcapkit/protocols/data/transport/tcp.py +6 -3
  44. pcapkit/protocols/data/transport/udp.py +2 -2
  45. pcapkit/protocols/internet/internet.py +15 -6
  46. pcapkit/protocols/internet/ipv6.py +54 -3
  47. pcapkit/protocols/internet/ipv6_route.py +5 -7
  48. pcapkit/protocols/link/link.py +1 -1
  49. pcapkit/protocols/misc/pcap/frame.py +1 -1
  50. pcapkit/protocols/misc/pcapng.py +5 -2
  51. pcapkit/protocols/misc/raw.py +0 -1
  52. pcapkit/protocols/protocol.py +4 -1
  53. pcapkit/protocols/schema/__init__.py +0 -1
  54. pcapkit/protocols/schema/internet/ipv6_route.py +2 -3
  55. pcapkit/protocols/schema/schema.py +1 -1
  56. pcapkit/protocols/transport/tcp.py +1 -1
  57. pcapkit/protocols/transport/udp.py +1 -1
  58. pcapkit/toolkit/pcapng.py +1 -1
  59. pcapkit/utilities/decorators.py +4 -2
  60. pcapkit/utilities/exceptions.py +5 -5
  61. {pypcapkit-1.3.1.post7.dist-info → pypcapkit-1.3.5.post6.dist-info}/METADATA +1 -1
  62. {pypcapkit-1.3.1.post7.dist-info → pypcapkit-1.3.5.post6.dist-info}/RECORD +66 -66
  63. {pypcapkit-1.3.1.post7.dist-info → pypcapkit-1.3.5.post6.dist-info}/WHEEL +1 -1
  64. {pypcapkit-1.3.1.post7.dist-info → pypcapkit-1.3.5.post6.dist-info}/LICENSE +0 -0
  65. {pypcapkit-1.3.1.post7.dist-info → pypcapkit-1.3.5.post6.dist-info}/entry_points.txt +0 -0
  66. {pypcapkit-1.3.1.post7.dist-info → pypcapkit-1.3.5.post6.dist-info}/top_level.txt +0 -0
@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING
5
5
 
6
6
  from pcapkit.corekit.infoclass import info_final
7
7
  from pcapkit.protocols.data.data import Data
8
+ from pcapkit.protocols.data.protocol import Protocol
8
9
 
9
10
  if TYPE_CHECKING:
10
11
  from ipaddress import IPv4Address, IPv6Address
@@ -43,7 +44,7 @@ class Type(Data):
43
44
 
44
45
 
45
46
  @info_final
46
- class ARP(Data):
47
+ class ARP(Protocol):
47
48
  """Data model for ARP packet."""
48
49
 
49
50
  #: Hardware type.
@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING
5
5
 
6
6
  from pcapkit.corekit.infoclass import info_final
7
7
  from pcapkit.protocols.data.data import Data
8
+ from pcapkit.protocols.data.protocol import Protocol
8
9
 
9
10
  if TYPE_CHECKING:
10
11
  from pcapkit.const.reg.ethertype import EtherType
@@ -13,7 +14,7 @@ __all__ = ['Ethernet']
13
14
 
14
15
 
15
16
  @info_final
16
- class Ethernet(Data):
17
+ class Ethernet(Protocol):
17
18
  """Data model for ethernet packet."""
18
19
 
19
20
  #: Destination MAC address.
@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING
5
5
 
6
6
  from pcapkit.corekit.infoclass import info_final
7
7
  from pcapkit.protocols.data.data import Data
8
+ from pcapkit.protocols.data.protocol import Protocol
8
9
 
9
10
  if TYPE_CHECKING:
10
11
  from typing import Optional
@@ -34,7 +35,7 @@ class Flags(Data):
34
35
 
35
36
 
36
37
  @info_final
37
- class L2TP(Data):
38
+ class L2TP(Protocol):
38
39
  """Data model for L2TP packet."""
39
40
 
40
41
  #: Flags and version info.
@@ -58,4 +59,5 @@ class L2TP(Data):
58
59
  #: Header length.
59
60
  hdr_len: 'int'
60
61
 
61
- def __init__(self, flags: 'Flags', version: 'int', length: 'Optional[int]', tunnelid: 'int', sessionid: 'int', ns: 'Optional[int]', nr: 'Optional[int]', offset: 'Optional[int]') -> 'None': ... # pylint: disable=unused-argument,super-init-not-called,redefined-builtin,multiple-statements,line-too-long
62
+ def __init__(self, flags: 'Flags', version: 'int', length: 'Optional[int]', tunnelid: 'int', sessionid: 'int',
63
+ ns: 'Optional[int]', nr: 'Optional[int]', offset: 'Optional[int]') -> 'None': ... # pylint: disable=unused-argument,super-init-not-called,redefined-builtin,multiple-statements,line-too-long
@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING
5
5
 
6
6
  from pcapkit.corekit.infoclass import info_final
7
7
  from pcapkit.protocols.data.data import Data
8
+ from pcapkit.protocols.data.protocol import Protocol
8
9
 
9
10
  if TYPE_CHECKING:
10
11
  from ipaddress import IPv4Address
@@ -31,7 +32,7 @@ class CrytographicAuthentication(Data):
31
32
 
32
33
 
33
34
  @info_final
34
- class OSPF(Data):
35
+ class OSPF(Protocol):
35
36
  """Data model for OSPF packet."""
36
37
 
37
38
  #: Version number.
@@ -53,4 +54,5 @@ class OSPF(Data):
53
54
  #: Authentication.
54
55
  auth: 'bytes | CrytographicAuthentication'
55
56
 
56
- def __init__(self, version: 'int', type: 'Packet', len: 'int', router_id: 'IPv4Address', area_id: 'IPv4Address', chksum: 'bytes', autype: 'Authentication') -> 'None': ... # pylint: disable=super-init-not-called,unused-argument,line-too-long,multiple-statements,redefined-builtin
57
+ def __init__(self, version: 'int', type: 'Packet', len: 'int', router_id: 'IPv4Address',
58
+ area_id: 'IPv4Address', chksum: 'bytes', autype: 'Authentication') -> 'None': ... # pylint: disable=super-init-not-called,unused-argument,line-too-long,multiple-statements,redefined-builtin
@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING
5
5
 
6
6
  from pcapkit.corekit.infoclass import info_final
7
7
  from pcapkit.protocols.data.data import Data
8
+ from pcapkit.protocols.data.protocol import Protocol
8
9
 
9
10
  if TYPE_CHECKING:
10
11
  from pcapkit.const.reg.ethertype import EtherType
@@ -29,7 +30,7 @@ class TCI(Data):
29
30
 
30
31
 
31
32
  @info_final
32
- class VLAN(Data):
33
+ class VLAN(Protocol):
33
34
  """Data model for 802.1Q customer VLAN tag type."""
34
35
 
35
36
  #: Tag control information.
@@ -2,13 +2,13 @@
2
2
  """data models for no-payload packet"""
3
3
 
4
4
  from pcapkit.corekit.infoclass import info_final
5
- from pcapkit.protocols.data.data import Data
5
+ from pcapkit.protocols.data.protocol import Protocol
6
6
 
7
7
  __all__ = ['NoPayload']
8
8
 
9
9
 
10
10
  @info_final
11
- class NoPayload(Data):
11
+ class NoPayload(Protocol):
12
12
  """No-payload packet is an empty packet."""
13
13
 
14
14
  # NOTE: We add this method for both type annotation and to mark that this
@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING
5
5
 
6
6
  from pcapkit.corekit.infoclass import info_final
7
7
  from pcapkit.protocols.data.data import Data
8
+ from pcapkit.protocols.data.protocol import Protocol
8
9
 
9
10
  if TYPE_CHECKING:
10
11
  from datetime import datetime
@@ -31,7 +32,7 @@ class FrameInfo(Data):
31
32
 
32
33
 
33
34
  @info_final
34
- class Frame(Data):
35
+ class Frame(Protocol):
35
36
  """Frame header of PCAP file."""
36
37
 
37
38
  #: Metadata information.
@@ -51,4 +52,5 @@ class Frame(Data):
51
52
  #: Protocol chain.
52
53
  protocols: 'str'
53
54
 
54
- def __init__(self, frame_info: 'FrameInfo', time: 'datetime', number: 'int', time_epoch: 'Decimal', len: 'int', cap_len: 'int') -> 'None': ... # pylint: disable=unused-argument,multiple-statements,super-init-not-called,line-too-long,redefined-builtin
55
+ def __init__(self, frame_info: 'FrameInfo', time: 'datetime', number: 'int', time_epoch: 'Decimal',
56
+ len: 'int', cap_len: 'int') -> 'None': ... # pylint: disable=unused-argument,multiple-statements,super-init-not-called,line-too-long,redefined-builtin
@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING
5
5
 
6
6
  from pcapkit.corekit.infoclass import info_final
7
7
  from pcapkit.protocols.data.data import Data
8
+ from pcapkit.protocols.data.protocol import Protocol
8
9
 
9
10
  if TYPE_CHECKING:
10
11
  from typing_extensions import Literal
@@ -31,7 +32,7 @@ class MagicNumber(Data):
31
32
 
32
33
 
33
34
  @info_final
34
- class Header(Data):
35
+ class Header(Protocol):
35
36
  """Global header of PCAP file."""
36
37
 
37
38
  #: Magic number.
@@ -8,6 +8,7 @@ from typing import TYPE_CHECKING
8
8
  from pcapkit.corekit.infoclass import info_final
9
9
  from pcapkit.corekit.multidict import MultiDict
10
10
  from pcapkit.protocols.data.data import Data
11
+ from pcapkit.protocols.data.protocol import Protocol
11
12
  from pcapkit.utilities.compat import localcontext
12
13
 
13
14
  __all__ = [
@@ -59,7 +60,7 @@ if TYPE_CHECKING:
59
60
  WireGuardKeyLabel)
60
61
 
61
62
 
62
- class PCAPNG(Data):
63
+ class PCAPNG(Protocol):
63
64
  """Data model for PCAP-NG file blocks."""
64
65
 
65
66
  #: Block type.
@@ -145,7 +146,8 @@ class SectionHeaderBlock(PCAPNG):
145
146
  options: 'OrderedMultiDict[Enum_OptionType, Option]'
146
147
 
147
148
  if TYPE_CHECKING:
148
- def __init__(self, type: 'Enum_BlockType', length: 'int', byteorder: 'Literal["big", "little"]', version: 'VersionInfo', # pylint: disable=unused-argument
149
+ def __init__(self, type: 'Enum_BlockType', length: 'int', byteorder: 'Literal["big", "little"]',
150
+ version: 'VersionInfo', # pylint: disable=unused-argument
149
151
  section_length: 'int', options: 'OrderedMultiDict[Enum_OptionType, Option]') -> None: ...
150
152
 
151
153
 
@@ -255,7 +257,8 @@ class IF_FilterOption(Option):
255
257
  expression: 'bytes'
256
258
 
257
259
  if TYPE_CHECKING:
258
- def __init__(self, type: 'Enum_OptionType', length: 'int', code: 'Enum_FilterType', expression: 'bytes') -> None: ...
260
+ def __init__(self, type: 'Enum_OptionType', length: 'int', code: 'Enum_FilterType',
261
+ expression: 'bytes') -> None: ...
259
262
 
260
263
 
261
264
  @info_final
@@ -384,7 +387,8 @@ class EPB_HashOption(Option):
384
387
  hash: 'bytes'
385
388
 
386
389
  if TYPE_CHECKING:
387
- def __init__(self, type: 'Enum_OptionType', length: 'int', algorithm: 'Enum_HashAlgorithm', hash: 'bytes') -> 'None': ...
390
+ def __init__(self, type: 'Enum_OptionType', length: 'int', algorithm: 'Enum_HashAlgorithm',
391
+ hash: 'bytes') -> 'None': ...
388
392
 
389
393
 
390
394
  @info_final
@@ -430,7 +434,8 @@ class EPB_VerdictOption(Option):
430
434
  value: 'bytes'
431
435
 
432
436
  if TYPE_CHECKING:
433
- def __init__(self, type: 'Enum_OptionType', length: 'int', verdict: 'Enum_VerdictType', value: 'bytes') -> 'None': ...
437
+ def __init__(self, type: 'Enum_OptionType', length: 'int', verdict: 'Enum_VerdictType',
438
+ value: 'bytes') -> 'None': ...
434
439
 
435
440
 
436
441
  @info_final
@@ -623,7 +628,8 @@ class NameResolutionBlock(PCAPNG):
623
628
  #: Name resolution mapping (name -> IP address).
624
629
  reverse_mapping: 'MultiDict[str, IPv4Address | IPv6Address]'
625
630
 
626
- def __init__(self, type: 'Enum_BlockType', length: 'int', records: 'OrderedMultiDict[Enum_RecordType, NameResolutionRecord]',
631
+ def __init__(self, type: 'Enum_BlockType', length: 'int',
632
+ records: 'OrderedMultiDict[Enum_RecordType, NameResolutionRecord]',
627
633
  options: 'OrderedMultiDict[Enum_OptionType, Option]') -> 'None': ...
628
634
 
629
635
 
@@ -736,7 +742,8 @@ class SystemdJournalExportBlock(PCAPNG):
736
742
  data: 'tuple[OrderedMultiDict[str, str | bytes], ...]'
737
743
 
738
744
  if TYPE_CHECKING:
739
- def __init__(self, type: 'Enum_BlockType', length: 'int', data: 'tuple[OrderedMultiDict[str, str | bytes], ...]') -> 'None': ...
745
+ def __init__(self, type: 'Enum_BlockType', length: 'int',
746
+ data: 'tuple[OrderedMultiDict[str, str | bytes], ...]') -> 'None': ...
740
747
 
741
748
 
742
749
  class DSBSecrets(Data):
@@ -880,7 +887,8 @@ class PACK_HashOption(Option):
880
887
  hash: 'bytes'
881
888
 
882
889
  if TYPE_CHECKING:
883
- def __init__(self, type: 'Enum_OptionType', length: 'int', algorithm: 'Enum_HashAlgorithm', hash: 'bytes') -> 'None': ...
890
+ def __init__(self, type: 'Enum_OptionType', length: 'int', algorithm: 'Enum_HashAlgorithm',
891
+ hash: 'bytes') -> 'None': ...
884
892
 
885
893
 
886
894
  @info_final
@@ -4,7 +4,7 @@
4
4
  from typing import TYPE_CHECKING
5
5
 
6
6
  from pcapkit.corekit.infoclass import info_final
7
- from pcapkit.protocols.data.data import Data
7
+ from pcapkit.protocols.data.protocol import Protocol
8
8
 
9
9
  if TYPE_CHECKING:
10
10
  from typing import Optional
@@ -13,15 +13,13 @@ __all__ = ['Raw']
13
13
 
14
14
 
15
15
  @info_final
16
- class Raw(Data):
16
+ class Raw(Protocol):
17
17
  """Raw packet is an unknown protocol."""
18
18
 
19
19
  #: Original enumeration of this protocol.
20
20
  protocol: 'Optional[int]'
21
- #: packet data
22
- packet: 'bytes'
23
21
  #: error instance when parsing packet data
24
22
  error: 'Optional[Exception]'
25
23
 
26
24
  if TYPE_CHECKING:
27
- def __init__(self, protocol: 'Optional[int]', packet: 'bytes', error: 'Optional[Exception]') -> 'None': ... # pylint: disable=unused-argument,super-init-not-called,multiple-statements
25
+ def __init__(self, protocol: 'Optional[int]', error: 'Optional[Exception]') -> 'None': ... # pylint: disable=unused-argument,super-init-not-called,multiple-statements
@@ -11,6 +11,14 @@ __all__ = [
11
11
  ]
12
12
 
13
13
 
14
+ class Protocol(Data):
15
+ """Root protocol."""
16
+
17
+ if TYPE_CHECKING:
18
+ #: Packet payload.
19
+ packet: 'bytes'
20
+
21
+
14
22
  @info_final
15
23
  class Packet(Data):
16
24
  """Header and payload data."""
@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING
5
5
 
6
6
  from pcapkit.corekit.infoclass import info_final
7
7
  from pcapkit.protocols.data.data import Data
8
+ from pcapkit.protocols.data.protocol import Protocol
8
9
 
9
10
  if TYPE_CHECKING:
10
11
  from datetime import timedelta
@@ -67,11 +68,12 @@ class Flags(Data):
67
68
  fin: 'bool'
68
69
 
69
70
  if TYPE_CHECKING:
70
- def __init__(self, cwr: 'bool', ece: 'bool', urg: 'bool', ack: 'bool', psh: 'bool', rst: 'bool', syn: 'bool', fin: 'bool') -> 'None': ... # pylint: disable=unused-argument,super-init-not-called,multiple-statements,line-too-long,redefined-builtin
71
+ def __init__(self, cwr: 'bool', ece: 'bool', urg: 'bool', ack: 'bool',
72
+ psh: 'bool', rst: 'bool', syn: 'bool', fin: 'bool') -> 'None': ... # pylint: disable=unused-argument,super-init-not-called,multiple-statements,line-too-long,redefined-builtin
71
73
 
72
74
 
73
75
  @info_final
74
- class TCP(Data):
76
+ class TCP(Protocol):
75
77
  """Data model for TCP packet."""
76
78
 
77
79
  #: Source port.
@@ -99,7 +101,8 @@ class TCP(Data):
99
101
  #: Connection control flags.
100
102
  connection: 'TCP_Flags'
101
103
 
102
- def __init__(self, srcport: 'AppType', dstport: 'AppType', seq: 'int', ack: 'int', hdr_len: 'int', flags: 'Flags', window_size: 'int', checksum: 'bytes', urgent_pointer: 'int') -> 'None': ... # pylint: disable=unused-argument,super-init-not-called,multiple-statements,line-too-long,redefined-builtin
104
+ def __init__(self, srcport: 'AppType', dstport: 'AppType', seq: 'int', ack: 'int', hdr_len: 'int',
105
+ flags: 'Flags', window_size: 'int', checksum: 'bytes', urgent_pointer: 'int') -> 'None': ... # pylint: disable=unused-argument,super-init-not-called,multiple-statements,line-too-long,redefined-builtin
103
106
 
104
107
 
105
108
  class Option(Data):
@@ -4,7 +4,7 @@
4
4
  from typing import TYPE_CHECKING
5
5
 
6
6
  from pcapkit.corekit.infoclass import info_final
7
- from pcapkit.protocols.data.data import Data
7
+ from pcapkit.protocols.data.protocol import Protocol
8
8
 
9
9
  if TYPE_CHECKING:
10
10
  from pcapkit.const.reg.apptype import AppType
@@ -13,7 +13,7 @@ __all__ = ['UDP']
13
13
 
14
14
 
15
15
  @info_final
16
- class UDP(Data):
16
+ class UDP(Protocol):
17
17
  """Data model for UDP protocol."""
18
18
 
19
19
  #: Source port.
@@ -83,7 +83,7 @@ class Internet(Protocol[_PT, _ST], Generic[_PT, _ST]): # pylint: disable=abstra
83
83
  #: c.f. :meth:`self._decode_next_layer <pcapkit.protocols.internet.internet.Internet._decode_next_layer>`
84
84
  #: & :meth:`self._import_next_layer <pcapkit.protocols.internet.internet.Internet._import_next_layer>`.
85
85
  __proto__ = collections.defaultdict(
86
- lambda: ModuleDescriptor('pcapkit.protocols.misc.raw', 'Raw'), # type: ignore[return-value,arg-type]
86
+ lambda: ModuleDescriptor('pcapkit.protocols.misc.raw', 'Raw'),
87
87
  {
88
88
  Enum_TransType.HOPOPT: ModuleDescriptor('pcapkit.protocols.internet.hopopt', 'HOPOPT'),
89
89
  Enum_TransType.IPv4: ModuleDescriptor('pcapkit.protocols.internet.ipv4', 'IPv4'),
@@ -157,7 +157,8 @@ class Internet(Protocol[_PT, _ST], Generic[_PT, _ST]): # pylint: disable=abstra
157
157
 
158
158
  def _decode_next_layer(self, dict_: '_PT', proto: 'Optional[int]' = None, # pylint: disable=arguments-differ
159
159
  length: 'Optional[int]' = None, *, packet: 'Optional[dict[str, Any]]' = None,
160
- version: 'Literal[4, 6]' = 4, ipv6_exthdr: 'Optional[ProtoChain]' = None) -> '_PT':
160
+ version: 'Literal[4, 6]' = 4, ipv6_exthdr: 'Optional[ProtoChain]' = None,
161
+ payload: 'Optional[bytes]' = None) -> '_PT':
161
162
  r"""Decode next layer extractor.
162
163
 
163
164
  Arguments:
@@ -167,6 +168,8 @@ class Internet(Protocol[_PT, _ST], Generic[_PT, _ST]): # pylint: disable=abstra
167
168
  packet: packet info (passed from :meth:`self.unpack <pcapkit.protocols.protocol.Protocol.unpack>`)
168
169
  version: IP version
169
170
  ipv6_exthdr: protocol chain of IPv6 extension headers
171
+ payload: payload from packet. If not provided, will extract from
172
+ :meth:`self.__header__.get_payload <pcapkit.protocols.schema.schema.Schema.get_payload>`
170
173
 
171
174
  Returns:
172
175
  Current protocol with next layer extracted.
@@ -179,7 +182,8 @@ class Internet(Protocol[_PT, _ST], Generic[_PT, _ST]): # pylint: disable=abstra
179
182
 
180
183
  """
181
184
  next_ = cast('Protocol', # type: ignore[redundant-cast]
182
- self._import_next_layer(proto, length, packet=packet, version=version)) # type: ignore[arg-type,misc,call-arg]
185
+ self._import_next_layer(proto, length, packet=packet, version=version,
186
+ payload=payload)) # type: ignore[arg-type,misc,call-arg]
183
187
  info, chain = next_.info, next_.protochain
184
188
 
185
189
  # make next layer protocol name
@@ -203,8 +207,8 @@ class Internet(Protocol[_PT, _ST], Generic[_PT, _ST]): # pylint: disable=abstra
203
207
 
204
208
  @beholder # type: ignore[arg-type]
205
209
  def _import_next_layer(self, proto: 'int', length: 'Optional[int]' = None, *, # pylint: disable=arguments-differ
206
- packet: 'Optional[dict[str, Any]]' = None,
207
- version: 'Literal[4, 6]' = 4, extension: 'bool' = False) -> 'Protocol':
210
+ packet: 'Optional[dict[str, Any]]' = None, version: 'Literal[4, 6]' = 4,
211
+ extension: 'bool' = False, payload: 'Optional[bytes]' = None) -> 'Protocol':
208
212
  """Import next layer extractor.
209
213
 
210
214
  Arguments:
@@ -213,6 +217,8 @@ class Internet(Protocol[_PT, _ST], Generic[_PT, _ST]): # pylint: disable=abstra
213
217
  packet: packet info (passed from :meth:`self.unpack <pcapkit.protocols.protocol.Protocol.unpack>`)
214
218
  version: IP protocol version
215
219
  extension: if is extension header
220
+ payload: payload from packet. If not provided, will extract from
221
+ :meth:`self.__header__.get_payload <pcapkit.protocols.schema.schema.Schema.get_payload>`
216
222
 
217
223
  Returns:
218
224
  Instance of next layer.
@@ -221,7 +227,10 @@ class Internet(Protocol[_PT, _ST], Generic[_PT, _ST]): # pylint: disable=abstra
221
227
  if TYPE_CHECKING:
222
228
  protocol: 'Type[Protocol]'
223
229
 
224
- file_ = self.__header__.get_payload()
230
+ if payload is None:
231
+ file_ = self.__header__.get_payload()
232
+ else:
233
+ file_ = payload
225
234
  if length is None:
226
235
  length = len(file_)
227
236
 
@@ -31,11 +31,13 @@ from typing import TYPE_CHECKING
31
31
 
32
32
  from pcapkit.const.ipv6.extension_header import ExtensionHeader as Enum_ExtensionHeader
33
33
  from pcapkit.const.reg.transtype import TransType as Enum_TransType
34
+ from pcapkit.corekit.module import ModuleDescriptor
34
35
  from pcapkit.corekit.multidict import OrderedMultiDict
35
36
  from pcapkit.corekit.protochain import ProtoChain
36
37
  from pcapkit.protocols.data.internet.ipv6 import IPv6 as Data_IPv6
37
38
  from pcapkit.protocols.internet.ip import IP
38
39
  from pcapkit.protocols.schema.internet.ipv6 import IPv6 as Schema_IPv6
40
+ from pcapkit.utilities.decorators import beholder
39
41
 
40
42
  if TYPE_CHECKING:
41
43
  from enum import IntEnum as StdlibEnum
@@ -46,7 +48,6 @@ if TYPE_CHECKING:
46
48
  from typing_extensions import Literal
47
49
 
48
50
  from pcapkit.protocols.protocol import ProtocolBase as Protocol
49
- from pcapkit.protocols.schema.schema import Schema
50
51
 
51
52
  __all__ = ['IPv6']
52
53
 
@@ -310,6 +311,7 @@ class IPv6(IP[Data_IPv6, Schema_IPv6],
310
311
  _protos = [] # ProtoChain buffer
311
312
 
312
313
  # traverse if next header is an extensive header
314
+ payload = self.__header__.get_payload()
313
315
  while True:
314
316
  try:
315
317
  ex_proto = Enum_ExtensionHeader(proto)
@@ -322,7 +324,8 @@ class IPv6(IP[Data_IPv6, Schema_IPv6],
322
324
  # break
323
325
 
324
326
  # make protocol name
325
- next_ = self._import_next_layer(proto, packet=packet, version=6, extension=True) # type: ignore[misc,call-arg,arg-type]
327
+ next_ = self._import_next_layer(proto, packet=packet, version=6, extension=True,
328
+ payload=payload) # type: ignore[misc,call-arg,arg-type]
326
329
  info = next_.info
327
330
  name = next_.alias.lstrip('IPv6-').lower()
328
331
  ipv6.__update__({
@@ -348,6 +351,9 @@ class IPv6(IP[Data_IPv6, Schema_IPv6],
348
351
  })
349
352
  break
350
353
 
354
+ # update payload for next extension header
355
+ payload = payload[next_.length:]
356
+
351
357
  # record real header & payload length (headers exclude)
352
358
  ipv6.__update__({
353
359
  'hdr_len': hdr_len,
@@ -358,4 +364,49 @@ class IPv6(IP[Data_IPv6, Schema_IPv6],
358
364
  })
359
365
 
360
366
  ipv6_exthdr = ProtoChain.from_list(_protos) # type: ignore[arg-type]
361
- return super()._decode_next_layer(ipv6, proto, raw_len, packet=packet, ipv6_exthdr=ipv6_exthdr)
367
+ return super()._decode_next_layer(ipv6, proto, raw_len, packet=packet, ipv6_exthdr=ipv6_exthdr, payload=payload)
368
+
369
+ @beholder # type: ignore[arg-type]
370
+ def _import_next_layer(self, proto: 'int', length: 'Optional[int]' = None, *, # pylint: disable=arguments-differ
371
+ packet: 'Optional[dict[str, Any]]' = None, version: 'Literal[4, 6]' = 4,
372
+ extension: 'bool' = False, payload: 'Optional[bytes]' = None) -> 'Protocol':
373
+ """Import next layer extractor.
374
+
375
+ Arguments:
376
+ proto: next layer protocol index
377
+ length: valid (*non-padding*) length
378
+ packet: packet info (passed from :meth:`self.unpack <pcapkit.protocols.protocol.Protocol.unpack>`)
379
+ version: IP protocol version
380
+ extension: if is extension header
381
+ payload: payload from packet. If not provided, will extract from
382
+ :meth:`self.__header__.get_payload <pcapkit.protocols.schema.schema.Schema.get_payload>`
383
+
384
+ Returns:
385
+ Instance of next layer.
386
+
387
+ """
388
+ if TYPE_CHECKING:
389
+ protocol: 'Type[Protocol]'
390
+
391
+ if payload is None:
392
+ file_ = self.__header__.get_payload()
393
+ else:
394
+ file_ = payload
395
+ if length is None:
396
+ length = len(file_)
397
+
398
+ if length == 0:
399
+ from pcapkit.protocols.misc.null import \
400
+ NoPayload as protocol # isort: skip # pylint: disable=import-outside-toplevel
401
+ elif self._sigterm:
402
+ from pcapkit.protocols.misc.raw import \
403
+ Raw as protocol # isort: skip # pylint: disable=import-outside-toplevel
404
+ else:
405
+ protocol = self.__proto__[proto] # type: ignore[assignment]
406
+ if isinstance(protocol, ModuleDescriptor):
407
+ protocol = protocol.klass # type: ignore[unreachable]
408
+ self.__proto__[proto] = protocol # update mapping upon import
409
+
410
+ next_ = protocol(file_, length, version=version, extension=extension, # type: ignore[abstract]
411
+ alias=proto, packet=packet, layer=self._exlayer, protocol=self._exproto)
412
+ return next_
@@ -48,14 +48,12 @@ from pcapkit.utilities.warnings import RegistryWarning, warn
48
48
  if TYPE_CHECKING:
49
49
  from enum import IntEnum as StdlibEnum
50
50
  from ipaddress import IPv6Address
51
- from typing import IO, Any, Callable, DefaultDict, NoReturn, Optional, Type
51
+ from typing import IO, Any, Callable, DefaultDict, Optional, Type
52
52
 
53
53
  from aenum import IntEnum as AenumEnum
54
54
  from mypy_extensions import DefaultArg, KwArg, NamedArg
55
55
  from typing_extensions import Literal
56
56
 
57
- from pcapkit.corekit.protochain import ProtoChain
58
- from pcapkit.protocols.protocol import ProtocolBase as Protocol
59
57
  from pcapkit.protocols.schema.internet.ipv6_route import RoutingType as Schema_RoutingType
60
58
 
61
59
  TypeParser = Callable[[Schema_RoutingType, NamedArg(Schema_IPv6_Route, 'header')], Data_IPv6_Route]
@@ -402,7 +400,7 @@ class IPv6_Route(Internet[Data_IPv6_Route, Schema_IPv6_Route],
402
400
  """
403
401
  ipv6_route = Data_UnknownType(
404
402
  next=header.next,
405
- length=header.length,
403
+ length=header.length * 8 + 8,
406
404
  type=header.type,
407
405
  seg_left=header.seg_left,
408
406
  data=schema.data,
@@ -463,7 +461,7 @@ class IPv6_Route(Internet[Data_IPv6_Route, Schema_IPv6_Route],
463
461
 
464
462
  ipv6_route = Data_SourceRoute(
465
463
  next=header.next,
466
- length=header.length,
464
+ length=header.length * 8 + 8,
467
465
  type=header.type,
468
466
  seg_left=header.seg_left,
469
467
  ip=tuple(schema.ip),
@@ -507,7 +505,7 @@ class IPv6_Route(Internet[Data_IPv6_Route, Schema_IPv6_Route],
507
505
 
508
506
  ipv6_route = Data_Type2(
509
507
  next=header.next,
510
- length=header.length,
508
+ length=header.length * 8 + 8,
511
509
  type=header.type,
512
510
  seg_left=header.seg_left,
513
511
  ip=schema.ip,
@@ -547,7 +545,7 @@ class IPv6_Route(Internet[Data_IPv6_Route, Schema_IPv6_Route],
547
545
 
548
546
  ipv6_route = Data_RPL(
549
547
  next=header.next,
550
- length=header.length,
548
+ length=header.length * 8 + 8,
551
549
  type=header.type,
552
550
  seg_left=header.seg_left,
553
551
  cmpr_i=schema.cmpr_i,
@@ -72,7 +72,7 @@ class Link(Protocol[_PT, _ST], Generic[_PT, _ST]): # pylint: disable=abstract-m
72
72
  #: c.f. :meth:`self._decode_next_layer <pcapkit.protocols.protocol.Protocol._decode_next_layer>`
73
73
  #: & :meth:`self._import_next_layer <pcapkit.protocols.protocol.Protocol._import_next_layer>`.
74
74
  __proto__ = collections.defaultdict(
75
- lambda: ModuleDescriptor('pcapkit.protocols.misc.raw', 'Raw'), # type: ignore[arg-type,return-value]
75
+ lambda: ModuleDescriptor('pcapkit.protocols.misc.raw', 'Raw'),
76
76
  {
77
77
  Enum_EtherType.Address_Resolution_Protocol: ModuleDescriptor('pcapkit.protocols.link.arp', 'ARP'),
78
78
  Enum_EtherType.Reverse_Address_Resolution_Protocol: ModuleDescriptor('pcapkit.protocols.link.rarp', 'RARP'),
@@ -88,7 +88,7 @@ class Frame(Protocol[Data_Frame, Schema_Frame],
88
88
  #: The values should be a tuple representing the module name and class name, or
89
89
  #: a :class:`~pcapkit.protocols.protocol.Protocol` subclass.
90
90
  __proto__ = collections.defaultdict(
91
- lambda: ModuleDescriptor('pcapkit.protocols.misc.raw', 'Raw'), # type: ignore[return-value,arg-type]
91
+ lambda: ModuleDescriptor('pcapkit.protocols.misc.raw', 'Raw'),
92
92
  {
93
93
  Enum_LinkType.ETHERNET: ModuleDescriptor('pcapkit.protocols.link', 'Ethernet'),
94
94
  Enum_LinkType.IPV4: ModuleDescriptor('pcapkit.protocols.internet', 'IPv4'),
@@ -524,7 +524,7 @@ class PCAPNG(Protocol[Data_PCAPNG, Schema_PCAPNG],
524
524
  #: The values should be a tuple representing the module name and class name,
525
525
  #: or a :class:`~pcapkit.protocols.protocol.Protocol` subclass.
526
526
  __proto__ = collections.defaultdict(
527
- lambda: ModuleDescriptor('pcapkit.protocols.misc.raw', 'Raw'), # type: ignore[arg-type,return-value]
527
+ lambda: ModuleDescriptor('pcapkit.protocols.misc.raw', 'Raw'),
528
528
  {
529
529
  Enum_LinkType.ETHERNET: ModuleDescriptor('pcapkit.protocols.link', 'Ethernet'),
530
530
  Enum_LinkType.IPV4: ModuleDescriptor('pcapkit.protocols.internet', 'IPv4'),
@@ -862,7 +862,10 @@ class PCAPNG(Protocol[Data_PCAPNG, Schema_PCAPNG],
862
862
  self._byte = self._ctx.section.byteorder
863
863
  packet['byteorder'] = self._byte
864
864
  self.__header__ = cast('Schema_PCAPNG', self.__schema__.unpack(self._file, length, packet)) # type: ignore[call-arg,misc]
865
- return self.read(length, **kwargs)
865
+
866
+ data = self.read(length, **kwargs)
867
+ data.__update__(packet=self.packet.payload)
868
+ return data
866
869
 
867
870
  def read(self, length: 'Optional[int]' = None, *, _read: 'bool' = True,
868
871
  _seek_set: 'int' = 0, **kwargs: 'Any') -> 'Data_PCAPNG':
@@ -79,7 +79,6 @@ class Raw(Protocol[Data_Raw, Schema_Raw],
79
79
  """
80
80
  raw = Data_Raw(
81
81
  protocol=alias,
82
- packet=self._data,
83
82
  error=error,
84
83
  )
85
84
 
@@ -116,7 +116,7 @@ class ProtocolBase(Generic[_PT, _ST], metaclass=ProtocolMeta):
116
116
  #: The values should be a tuple representing the module name and class name,
117
117
  #: or a :class:`Protocol` subclass.
118
118
  __proto__: 'DefaultDict[int, ModuleDescriptor[ProtocolBase] | Type[ProtocolBase]]' = collections.defaultdict(
119
- lambda: ModuleDescriptor('pcapkit.protocols.misc.raw', 'Raw'), # type: ignore[return-value,arg-type]
119
+ lambda: ModuleDescriptor('pcapkit.protocols.misc.raw', 'Raw'),
120
120
  )
121
121
 
122
122
  ##########################################################################
@@ -520,6 +520,9 @@ class ProtocolBase(Generic[_PT, _ST], metaclass=ProtocolMeta):
520
520
  # post-init customisations
521
521
  self.__post_init__(file, length, **kwargs) # type: ignore[arg-type]
522
522
 
523
+ # inject packet payload to the info dict
524
+ self._info.__update__(packet=self.packet.payload)
525
+
523
526
  @overload
524
527
  def __post_init__(self, file: 'IO[bytes] | bytes', length: 'Optional[int]' = ..., **kwargs: 'Any') -> 'None': ...
525
528
  @overload
@@ -50,7 +50,6 @@ __all__ = [
50
50
  'HIP_RelayToParameter', 'HIP_RouteViaParameter', 'HIP_FromParameter',
51
51
  'HIP_RVSHMACParameter', 'HIP_RelayHMACParameter',
52
52
  'IPv4',
53
- 'IPv4_OptionType',
54
53
  'IPv4_UnassignedOption', 'IPv4_EOOLOption', 'IPv4_NOPOption',
55
54
  'IPv4_SECOption', 'IPv4_LSROption', 'IPv4_TSOption',
56
55
  'IPv4_ESECOption', 'IPv4_RROption', 'IPv4_SIDOption',