From 8429f9544fb6d64093854a166c00c5d21fc1191c Mon Sep 17 00:00:00 2001 From: Jarry Shaw Date: Mon, 19 Oct 2026 00:36:22 -0400 Subject: [PATCH 1/2] docs(protocols): fourth whole-repo pass over internet (#1103) Rendering: - Drop the duplicated RPL, MPL and DFF flag stubs on the HOPOPT and IPv6-Opts pages, and the type prefixes on the registry comments that rendered a second, unlinked Type field. - Point load_cryptography at InvalidTag rather than an unresolved module. Reachability: - Carry the IPv6-Ext length rules, entry paths and overrun guard on its page, and point the docstrings at those sections rather than at the unrendered module docstring; likewise ESP's algorithm support. - List the per-suite ESP parameters the support tables left out. Accuracy: - Rebuild the IPv6-Ext exception table so its rows render, and title the page IPv6-Ext after the alias. - Say ESP's next is None only while its payload stays opaque. - Fill the blank IPv4 and ESP table cells, describe HIP's fixed bits as bits, and correct the PDM field acronyms. - Drop the directive on beta-only PMIPv6Timestamp and the page-level copy of NTPTimestamp's, which its class docstring already renders. Wording: "the extractor", "construction arguments", "see" for "c.f.", and spec totals worded count-free. Refs #1103 --- docs/source/pcapkit/protocols/internet/ah.rst | 2 +- .../source/pcapkit/protocols/internet/esp.rst | 29 +++- .../source/pcapkit/protocols/internet/hip.rst | 6 +- .../pcapkit/protocols/internet/hopopt.rst | 17 +-- .../pcapkit/protocols/internet/ipv4.rst | 2 +- .../pcapkit/protocols/internet/ipv6.rst | 2 +- .../pcapkit/protocols/internet/ipv6_ext.rst | 132 +++++++++++++++++- .../pcapkit/protocols/internet/ipv6_frag.rst | 2 +- .../pcapkit/protocols/internet/ipv6_opts.rst | 17 +-- .../pcapkit/protocols/internet/ipv6_route.rst | 2 +- .../source/pcapkit/protocols/internet/ipx.rst | 2 +- docs/source/pcapkit/protocols/internet/mh.rst | 12 +- pcapkit/protocols/data/internet/mh.py | 21 +-- pcapkit/protocols/internet/__init__.py | 6 +- pcapkit/protocols/internet/ah.py | 4 +- pcapkit/protocols/internet/esp.py | 24 ++-- pcapkit/protocols/internet/hip.py | 11 +- pcapkit/protocols/internet/hopopt.py | 17 ++- pcapkit/protocols/internet/internet.py | 20 +-- pcapkit/protocols/internet/ipv4.py | 19 ++- pcapkit/protocols/internet/ipv6.py | 29 ++-- pcapkit/protocols/internet/ipv6_ext.py | 81 +++++------ pcapkit/protocols/internet/ipv6_frag.py | 4 +- pcapkit/protocols/internet/ipv6_opts.py | 17 ++- pcapkit/protocols/internet/ipv6_route.py | 11 +- pcapkit/protocols/internet/ipx.py | 2 +- pcapkit/protocols/internet/mh.py | 61 ++++---- pcapkit/protocols/schema/internet/hopopt.py | 12 +- pcapkit/protocols/schema/internet/ipv4.py | 4 +- pcapkit/protocols/schema/internet/ipv6.py | 4 +- .../protocols/schema/internet/ipv6_option.py | 2 +- .../protocols/schema/internet/ipv6_opts.py | 12 +- pcapkit/protocols/schema/internet/mh.py | 22 +-- 33 files changed, 344 insertions(+), 264 deletions(-) diff --git a/docs/source/pcapkit/protocols/internet/ah.rst b/docs/source/pcapkit/protocols/internet/ah.rst index 975c3a29d7..473226b10f 100644 --- a/docs/source/pcapkit/protocols/internet/ah.rst +++ b/docs/source/pcapkit/protocols/internet/ah.rst @@ -5,7 +5,7 @@ AH - Authentication Header :mod:`pcapkit.protocols.internet.ah` contains :class:`~pcapkit.protocols.internet.ah.AH` only, -which implements extractor for Authentication +which implements the extractor for Authentication Header (AH) [*]_, whose structure is described as below: diff --git a/docs/source/pcapkit/protocols/internet/esp.rst b/docs/source/pcapkit/protocols/internet/esp.rst index a7bf049b91..409bd57c28 100644 --- a/docs/source/pcapkit/protocols/internet/esp.rst +++ b/docs/source/pcapkit/protocols/internet/esp.rst @@ -5,7 +5,7 @@ ESP - Encapsulating Security Payload :mod:`pcapkit.protocols.internet.esp` contains :class:`~pcapkit.protocols.internet.esp.ESP`, -which implements extractor for Encapsulating +which implements the extractor for Encapsulating Security Payload (ESP) [*]_, and the security association, algorithm and status types documented below. The ESP structure is described as below: @@ -132,6 +132,8 @@ are the same member. The registry spells the "no integrity algorithm" transform ``NONE`` rather than ``AUTH_NONE``, and :attr:`Integrity.NONE ` follows it. +.. _esp-algorithm-support: + Algorithm Support ----------------- @@ -206,6 +208,31 @@ MD5, DES-MAC, KPDK-MD5 MUST NOT **no** registered, delibe "MD5, DES-MAC, KPDK-MD5" above covers ``AUTH_HMAC_MD5_96``, ``AUTH_HMAC_MD5_128``, ``AUTH_DES_MAC`` and ``AUTH_KPDK_MD5``. +Each implemented suite applies its algorithm with the parameters below, as +:data:`~pcapkit.protocols.internet.esp.CIPHER_SUITES` and +:data:`~pcapkit.protocols.internet.esp.INTEGRITY_SUITES` record them. Lengths +and sizes are in octets. + +========================== =========== ============== ============== ============== ============== =============== ========================= +Encryption ``is_aead`` ``iv_length`` ``block_size`` ``icv_length`` ``key_sizes`` ``salt_length`` ``requires_cryptography`` +========================== =========== ============== ============== ============== ============== =============== ========================= +``ENCR_NULL`` no 0 1 0 0 0 no +``ENCR_AES_CBC`` no 16 16 0 16, 24, 32 0 yes +``ENCR_AES_GCM_8`` yes 8 1 8 16, 24, 32 4 yes +``ENCR_AES_GCM_12`` yes 8 1 12 16, 24, 32 4 yes +``ENCR_AES_GCM_16`` yes 8 1 16 16, 24, 32 4 yes +========================== =========== ============== ============== ============== ============== =============== ========================= + +========================== ============== ============== ============== +Integrity ``digest`` ``icv_length`` ``key_size`` +========================== ============== ============== ============== +``NONE`` :data:`None` 0 0 +``AUTH_HMAC_SHA1_96`` ``sha1`` 12 20 +``AUTH_HMAC_SHA2_256_128`` ``sha256`` 16 32 +``AUTH_HMAC_SHA2_384_192`` ``sha384`` 24 48 +``AUTH_HMAC_SHA2_512_256`` ``sha512`` 32 64 +========================== ============== ============== ============== + .. autoclass:: pcapkit.protocols.internet.esp.CipherSuite :members: :undoc-members: diff --git a/docs/source/pcapkit/protocols/internet/hip.rst b/docs/source/pcapkit/protocols/internet/hip.rst index 564867f3b0..74e3608070 100644 --- a/docs/source/pcapkit/protocols/internet/hip.rst +++ b/docs/source/pcapkit/protocols/internet/hip.rst @@ -5,7 +5,7 @@ HIP - Host Identity Protocol :mod:`pcapkit.protocols.internet.hip` contains :class:`~pcapkit.protocols.internet.hip.HIP` only, -which implements extractor for Host Identity +which implements the extractor for Host Identity Protocol (HIP) [*]_, whose structure is described as below: @@ -14,11 +14,11 @@ Octets Bits Name Description ======= ========= ====================== ================================== 0 0 ``hip.next`` Next Header 1 8 ``hip.length`` Header Length - 2 16 ``hip.packet_fixed`` Reserved (``\x00``) + 2 16 ``hip.packet_fixed`` Fixed Bit (``0``) 2 17 ``hip.type`` Packet Type 3 24 ``hip.version`` Version 3 28 ``hip.reserved`` Reserved - 3 31 ``hip.version_fixed`` Reserved (``\x01``) + 3 31 ``hip.version_fixed`` Fixed Bit (``1``) 4 32 ``hip.chksum`` Checksum 6 48 ``hip.control`` Controls 8 64 ``hip.shit`` Sender's Host Identity Tag diff --git a/docs/source/pcapkit/protocols/internet/hopopt.rst b/docs/source/pcapkit/protocols/internet/hopopt.rst index 4814396bed..d519ec44a1 100644 --- a/docs/source/pcapkit/protocols/internet/hopopt.rst +++ b/docs/source/pcapkit/protocols/internet/hopopt.rst @@ -5,7 +5,7 @@ HOPOPT - IPv6 Hop-by-Hop Options :mod:`pcapkit.protocols.internet.hopopt` contains :class:`~pcapkit.protocols.internet.hopopt.HOPOPT` -only, which implements extractor for IPv6 Hop-by-Hop +only, which implements the extractor for IPv6 Hop-by-Hop Options header (HOPOPT) [*]_, whose structure is described as below: @@ -148,18 +148,10 @@ Header Schemas :members: :show-inheritance: -.. autoclass:: pcapkit.protocols.schema.internet.hopopt.RPLFlags - :members: - :show-inheritance: - .. autoclass:: pcapkit.protocols.schema.internet.hopopt.MPLOption :members: :show-inheritance: -.. autoclass:: pcapkit.protocols.schema.internet.hopopt.MPLFlags - :members: - :show-inheritance: - .. autoclass:: pcapkit.protocols.schema.internet.hopopt.ILNPOption :members: :show-inheritance: @@ -180,10 +172,6 @@ Header Schemas :members: :show-inheritance: -.. autoclass:: pcapkit.protocols.schema.internet.hopopt.DFFFlags - :members: - :show-inheritance: - Type Stubs ~~~~~~~~~~ @@ -196,17 +184,14 @@ Type Stubs :show-inheritance: .. autoclass:: pcapkit.protocols.schema.internet.hopopt.RPLFlags - :no-index: :members: :show-inheritance: .. autoclass:: pcapkit.protocols.schema.internet.hopopt.MPLFlags - :no-index: :members: :show-inheritance: .. autoclass:: pcapkit.protocols.schema.internet.hopopt.DFFFlags - :no-index: :members: :show-inheritance: diff --git a/docs/source/pcapkit/protocols/internet/ipv4.rst b/docs/source/pcapkit/protocols/internet/ipv4.rst index 82697ba52f..7dc4885adc 100644 --- a/docs/source/pcapkit/protocols/internet/ipv4.rst +++ b/docs/source/pcapkit/protocols/internet/ipv4.rst @@ -5,7 +5,7 @@ IPv4 - Internet Protocol version 4 :mod:`pcapkit.protocols.internet.ipv4` contains :class:`~pcapkit.protocols.internet.ipv4.IPv4` only, -which implements extractor for Internet Protocol +which implements the extractor for Internet Protocol version 4 (IPv4) [*]_, whose structure is described as below: diff --git a/docs/source/pcapkit/protocols/internet/ipv6.rst b/docs/source/pcapkit/protocols/internet/ipv6.rst index 878dcaebf2..05d9d2b5ce 100644 --- a/docs/source/pcapkit/protocols/internet/ipv6.rst +++ b/docs/source/pcapkit/protocols/internet/ipv6.rst @@ -5,7 +5,7 @@ IPv6 - Internet Protocol version 6 :mod:`pcapkit.protocols.internet.ipv6` contains :class:`~pcapkit.protocols.internet.ipv6.IPv6` only, -which implements extractor for Internet Protocol +which implements the extractor for Internet Protocol version 6 (IPv6) [*]_, whose structure is described as below: diff --git a/docs/source/pcapkit/protocols/internet/ipv6_ext.rst b/docs/source/pcapkit/protocols/internet/ipv6_ext.rst index 14aadf1c63..b4d64dc436 100644 --- a/docs/source/pcapkit/protocols/internet/ipv6_ext.rst +++ b/docs/source/pcapkit/protocols/internet/ipv6_ext.rst @@ -1,4 +1,4 @@ -IPv6_Ext - IPv6 Extension Header +IPv6-Ext - IPv6 Extension Header ================================ .. module:: pcapkit.protocols.internet.ipv6_ext @@ -27,12 +27,9 @@ Octets Bits Name Description ======= ========= ===================== ===================================== so those two octets are parseable without knowing anything else about the -header. The module docstring in :file:`pcapkit/protocols/internet/ipv6_ext.py` -holds the closed exception table (``IPv6-Frag`` and ``AH`` each use their own -length rule; ``ESP`` has a dedicated parser whose own info reports no next header -rather than lacking one, and ``253`` and ``254`` have no dedicated parser at all, -so none of them ever reaches this class), the ways this class is -dispatched to, and why an overrun stops the walk instead of clipping it. +header. The sections below the class give the headers that depart from that +rule, the ways this class is dispatched to, and why an overrun stops the walk +instead of clipping it. .. autoclass:: pcapkit.protocols.internet.ipv6_ext.IPv6_Ext :no-members: @@ -54,6 +51,127 @@ dispatched to, and why an overrun stops the walk instead of clipping it. .. automethod:: __post_init__ .. automethod:: __index__ +.. _ipv6-ext-length-rules: + +Length Rules +------------ + +:rfc:`6564#section-5` is explicit that the generic layout is **not +retroactive** -- it applies only to newly defined extension headers -- which is +why the pre-existing headers need the closed exception table below rather than +being assumed to conform. (:rfc:`8200#section-4.8` restates the layout without +a MUST and mislabels the generic length field as the length of the Destination +Options header; cite :rfc:`6564#section-4` instead.) + +The exception table, verified against IANA's ``protocol-numbers-1.csv`` +*IPv6 Extension Header* column and each cited RFC: + +===================================================================== ================================================= +Header(s) Length rule +===================================================================== ================================================= +``HOPOPT``, ``IPv6-Route``, ``IPv6-Opts``, ``MH``, ``HIP``, ``Shim6`` ``(octet[1] + 1) * 8`` -- the :rfc:`6564` + generic rule +``IPv6-Frag`` constant ``8``; octet[1] is Reserved, not a + length (:rfc:`8200#section-4.5`) +``AH`` ``(octet[1] + 2) * 4`` -- :rfc:`4302#section-2.2` + counts in 4-octet units with a bias of 2, + not :rfc:`6564`'s 8-octet units and bias of 1 +``ESP`` terminal -- has a dedicated, registered parser + (:class:`~pcapkit.protocols.internet.esp.ESP`), + but its Next Header byte is inside the + encrypted trailer (:rfc:`4303`), so the walk + cannot step past it on the wire +``253``, ``254`` terminal -- no dedicated parser exists, so no + next header field is ever read at all, either +===================================================================== ================================================= + +This table classifies by *wire format* alone, over every code +:class:`~pcapkit.const.ipv6.extension_header.ExtensionHeader` enumerates, +which match IANA's *IPv6 Extension Header Types* registry exactly +(:issue:`925`). + +``Shim6`` conforms to the generic rule (:rfc:`5533`) but has no dedicated parser class; see +:ref:`ipv6-ext-entry-paths` for how it reaches this class by direct dispatch. + +:rfc:`8200#section-4.5` sets Encapsulating Security Payload aside: ESP is not +an extension header, and the RFC lists it among upper-layer headers. +:rfc:`4303` puts its Next Header inside the encrypted trailer, with no length +field in the cleartext part. 253 and 254 are reserved for private +experimentation (:rfc:`3692`) with no wire format at all. None of them is +reachable through this class, by construction; see +:meth:`IPv6._import_next_layer +`. Each still enters +:meth:`IPv6._decode_next_layer +`'s walk, being a real +:class:`~pcapkit.const.ipv6.extension_header.ExtensionHeader` member, but they +part ways there. ``ESP`` resolves to its own dedicated parser, which decodes +any plaintext it recovers itself and whose info carries a ``next`` of +:data:`None` whenever the payload stays opaque, so the walk ends the ordinary +way with ``ExtensionHeader(None)`` failing at the top of the next iteration. +``253`` and ``254`` have no dedicated parser and resolve to plain +:class:`~pcapkit.protocols.misc.raw.Raw`, whose info has no ``next`` +*attribute*. For these two, and any future IANA code without an +implementation, the walk stops on a *structural* check (does the parsed layer +carry a ``next`` at all?) rather than on a list of codes. + +.. _ipv6-ext-entry-paths: + +Entry Paths +----------- + +This class is reached in these ways: + +1. **An unrecognised protocol number.** + :attr:`~pcapkit.const.ipv6.extension_header.ExtensionHeader.Shim6` is a real + IANA extension header (:rfc:`5533`) with no dedicated parser, so + :meth:`Internet._lookup_next_layer ` + would default it to plain :class:`~pcapkit.protocols.misc.raw.Raw`. That + has no ``next`` field, so the walk in + :meth:`IPv6._decode_next_layer ` would + crash on it (:issue:`891`). This module registers this class for that code + instead, at the bottom of the module, so dispatch reaches a working generic + parser directly. The registration is global, shared by every + :class:`~pcapkit.protocols.internet.internet.Internet` subclass, so + :meth:`~pcapkit.protocols.internet.ipv6_ext.IPv6_Ext.__post_init__` gates on ``version == 6`` to + keep it from also activating for an IPv4 payload that carries protocol + number 140; see its docstring. +2. **A recognised header whose own parser raises.** ``HOPOPT``, + ``IPv6-Route``, ``IPv6-Opts``, ``MH``, ``HIP``, ``IPv6-Frag`` and ``AH`` all + have dedicated classes. When one of *those* raises, + :func:`~pcapkit.corekit.decorators.beholder` + (:meth:`Protocol._import_next_layer `) + would substitute plain :class:`~pcapkit.protocols.misc.raw.Raw`, which loses + ``next`` and crashes the walk as in path 1. + :meth:`IPv6._import_next_layer ` catches + the failure itself, one layer in from ``beholder``, and substitutes this + class: the bad header costs only itself, not the rest of the chain. + +.. _ipv6-ext-overrun-guard: + +The Overrun Guard +----------------- + +The house convention for a declared length that does not fit what remains +is warn-and-clip: emit a warning naming what was declared against what is +left, then read only what is left. See +:func:`pcapkit.protocols.schema.misc.pcapng.bounded_area` and +:meth:`pcapkit.protocols.misc.pcapng.PCAPNG.read`. + +This class follows that convention's *warning* +(:class:`~pcapkit.utilities.warnings.SchemaWarning`) and deliberately diverges +on the *action*. Clipping is right when the declared length only governs how +much of the current object to read, since there is always a well-defined +"what is left" to fall back to. Here the declared length also decides *where +the next header starts*; a clipped skip distance points at whatever bytes +end the buffer, which are not a header. Continuing from there would +fabricate a layer and record a false entry in +:class:`~pcapkit.corekit.protochain.ProtoChain`, which reads as a parsed fact +rather than a guess. So :meth:`~pcapkit.protocols.internet.ipv6_ext.IPv6_Ext.read` warns in the same +wording as the sites above, then **stops the walk**: this instance absorbs +every remaining octet and reports :data:`None` for ``next``, which the +caller's loop already reads as "no more extension headers". The chain ends +honestly at the bad header instead of inventing what follows it. + Header Schemas -------------- diff --git a/docs/source/pcapkit/protocols/internet/ipv6_frag.rst b/docs/source/pcapkit/protocols/internet/ipv6_frag.rst index 0e3453689f..a34c8a38f6 100644 --- a/docs/source/pcapkit/protocols/internet/ipv6_frag.rst +++ b/docs/source/pcapkit/protocols/internet/ipv6_frag.rst @@ -5,7 +5,7 @@ IPv6-Frag - Fragment Header for IPv6 :mod:`pcapkit.protocols.internet.ipv6_frag` contains :class:`~pcapkit.protocols.internet.ipv6_frag.IPv6_Frag` -only, which implements extractor for Fragment Header for +only, which implements the extractor for Fragment Header for IPv6 (IPv6-Frag) [*]_, whose structure is described as below: diff --git a/docs/source/pcapkit/protocols/internet/ipv6_opts.rst b/docs/source/pcapkit/protocols/internet/ipv6_opts.rst index 42ac7c95bd..6df99df980 100644 --- a/docs/source/pcapkit/protocols/internet/ipv6_opts.rst +++ b/docs/source/pcapkit/protocols/internet/ipv6_opts.rst @@ -5,7 +5,7 @@ IPv6-Opts - Destination Options for IPv6 :mod:`pcapkit.protocols.internet.ipv6_opts` contains :class:`~pcapkit.protocols.internet.ipv6_opts.IPv6_Opts` -only, which implements extractor for Destination Options +only, which implements the extractor for Destination Options for IPv6 (IPv6-Opts) [*]_, whose structure is described as below: @@ -148,18 +148,10 @@ Header Schemas :members: :show-inheritance: -.. autoclass:: pcapkit.protocols.schema.internet.ipv6_opts.RPLFlags - :members: - :show-inheritance: - .. autoclass:: pcapkit.protocols.schema.internet.ipv6_opts.MPLOption :members: :show-inheritance: -.. autoclass:: pcapkit.protocols.schema.internet.ipv6_opts.MPLFlags - :members: - :show-inheritance: - .. autoclass:: pcapkit.protocols.schema.internet.ipv6_opts.ILNPOption :members: :show-inheritance: @@ -180,10 +172,6 @@ Header Schemas :members: :show-inheritance: -.. autoclass:: pcapkit.protocols.schema.internet.ipv6_opts.DFFFlags - :members: - :show-inheritance: - Type Stubs ~~~~~~~~~~ @@ -196,17 +184,14 @@ Type Stubs :show-inheritance: .. autoclass:: pcapkit.protocols.schema.internet.ipv6_opts.RPLFlags - :no-index: :members: :show-inheritance: .. autoclass:: pcapkit.protocols.schema.internet.ipv6_opts.MPLFlags - :no-index: :members: :show-inheritance: .. autoclass:: pcapkit.protocols.schema.internet.ipv6_opts.DFFFlags - :no-index: :members: :show-inheritance: diff --git a/docs/source/pcapkit/protocols/internet/ipv6_route.rst b/docs/source/pcapkit/protocols/internet/ipv6_route.rst index 25c64fa50b..8f3162e131 100644 --- a/docs/source/pcapkit/protocols/internet/ipv6_route.rst +++ b/docs/source/pcapkit/protocols/internet/ipv6_route.rst @@ -5,7 +5,7 @@ IPv6-Route - Routing Header for IPv6 :mod:`pcapkit.protocols.internet.ipv6_route` contains :class:`~pcapkit.protocols.internet.ipv6_route.IPv6_Route` -only, which implements extractor for Routing Header for IPv6 +only, which implements the extractor for Routing Header for IPv6 (IPv6-Route) [*]_, whose structure is described as below: ======= ========= ==================== =============================== diff --git a/docs/source/pcapkit/protocols/internet/ipx.rst b/docs/source/pcapkit/protocols/internet/ipx.rst index 1c80b79282..84a67f082f 100644 --- a/docs/source/pcapkit/protocols/internet/ipx.rst +++ b/docs/source/pcapkit/protocols/internet/ipx.rst @@ -5,7 +5,7 @@ IPX - Internetwork Packet Exchange :mod:`pcapkit.protocols.internet.ipx` contains :class:`~pcapkit.protocols.internet.ipx.IPX` only, -which implements extractor for Internetwork Packet +which implements the extractor for Internetwork Packet Exchange (IPX) [*]_, whose structure is described as below: diff --git a/docs/source/pcapkit/protocols/internet/mh.rst b/docs/source/pcapkit/protocols/internet/mh.rst index 5700160b1c..0654f1214b 100644 --- a/docs/source/pcapkit/protocols/internet/mh.rst +++ b/docs/source/pcapkit/protocols/internet/mh.rst @@ -5,7 +5,7 @@ MH - Mobility Header :mod:`pcapkit.protocols.internet.mh` contains :class:`~pcapkit.protocols.internet.mh.MH`, -which implements extractor for Mobility Header +which implements the extractor for Mobility Header (MH) [*]_, whose structure is described as below: ======= ========= ================== =============================== @@ -25,16 +25,6 @@ Octets Bits Name Description :class:`pcapkit.protocols.data.internet.mh.NTPTimestamp` instead (:issue:`1886`). -.. versionchanged:: 1.5.0 - - :class:`~pcapkit.protocols.data.internet.mh.NTPTimestamp` and - :class:`~pcapkit.protocols.data.internet.mh.PMIPv6Timestamp` are - :class:`~pcapkit.corekit.infoclass.Info` data models rather than named - tuples, so they no longer index, unpack, hash or compare equal to a - :obj:`tuple`, and the dumpers write them keyed by field, as - ``{"seconds": ..., "fraction": ...}``. For ``NTPTimestamp`` this is a - breaking change from 1.4.x (:issue:`1886`). - .. autoclass:: pcapkit.protocols.internet.mh.MH :no-members: :show-inheritance: diff --git a/pcapkit/protocols/data/internet/mh.py b/pcapkit/protocols/data/internet/mh.py index bf8f2e8fb7..4e88a683e6 100644 --- a/pcapkit/protocols/data/internet/mh.py +++ b/pcapkit/protocols/data/internet/mh.py @@ -986,7 +986,7 @@ def __init__(self, type: 'Enum_Option', length: 'int', subtype: 'Enum_AuthSubtyp @info_final class NTPTimestamp(Data): - """Data model for NTP timestamp format, c.f., :rfc:`1305`. + """Data model for NTP timestamp format, see :rfc:`1305`. .. versionchanged:: 1.5.0 @@ -1017,7 +1017,7 @@ class MesgIDOption(Option): #: Timestamp. timestamp: 'dt_type' - #: NTP timestamp, c.f., :rfc:`1305`. + #: NTP timestamp, see :rfc:`1305`. ntp_timestamp: 'NTPTimestamp' if TYPE_CHECKING: @@ -1123,7 +1123,7 @@ def __init__(self, modifier: 'Enum_CGAType', prefix: 'int', collision_count: 'in class CGAParametersOption(Option): """Data model for CGA Parameters option.""" - #: CGA parameters, c.f., :rfc:`3972`. + #: CGA parameters, see :rfc:`3972`. parameters: 'tuple[CGAParameter, ...]' if TYPE_CHECKING: @@ -1199,7 +1199,7 @@ def __init__(self, type: 'Enum_Option', length: 'int', spi: 'int', data: 'bytes' class IPv6AddressPrefixOption(Option): """Data model for MH Mobility Header IPv6 Address/Prefix option.""" - #: Option code, c.f., :rfc:`5568#section-6.4.2`. The codes are defined inline + #: Option code, see :rfc:`5568#section-6.4.2`. The codes are defined inline #: by the RFC with no IANA registry behind them, so this field carries the #: module-local #: :class:`~pcapkit.protocols.internet.mh.IPv6AddressPrefixCode`. @@ -1289,7 +1289,7 @@ def __init__(self, type: 'Enum_Option', length: 'int', address: 'IPv6Address') - @info_final class PMIPv6Timestamp(Data): - """Data model for Proxy Mobile IPv6 timestamp format, c.f., :rfc:`5213#section-8.8`. + """Data model for Proxy Mobile IPv6 timestamp format, see :rfc:`5213#section-8.8`. Note: This is **not** an :rfc:`1305` NTP timestamp, which is why it is a type of @@ -1297,15 +1297,6 @@ class PMIPv6Timestamp(Data): UNIX epoch rather than NTP's 1900 one, and splits its 64 bits 48/16 rather than 32/32, so each field means something different in the two. - .. versionchanged:: 1.5.0 - - An :class:`~pcapkit.corekit.infoclass.Info` data model in this module, - rather than the named tuple in :mod:`pcapkit.protocols.internet.mh` it - was in the 1.5.0 pre-releases (:issue:`1886`). It no longer indexes, - unpacks, hashes, orders, compares equal to a :obj:`tuple`, or has - ``_replace`` and ``_asdict``. The dumpers write it keyed by field, as - ``{"seconds": ..., "fraction": ...}``. - """ #: Seconds since 1 January 1970, in the leading 48 bits. @@ -1599,7 +1590,7 @@ def __init__(self, type: 'Enum_Option', length: 'int', class LMAAddressOption(Option): """Data model for MH Local Mobility Anchor Address option.""" - #: Option code, c.f., :rfc:`5949#section-6.2.2`. The codes are defined inline + #: Option code, see :rfc:`5949#section-6.2.2`. The codes are defined inline #: by the RFC with no IANA registry behind them, so this field carries the #: module-local :class:`~pcapkit.protocols.internet.mh.LMAAddressCode`. code: 'LMAAddressCode' diff --git a/pcapkit/protocols/internet/__init__.py b/pcapkit/protocols/internet/__init__.py index d2ded0fad1..032acb6ab8 100644 --- a/pcapkit/protocols/internet/__init__.py +++ b/pcapkit/protocols/internet/__init__.py @@ -5,11 +5,11 @@ .. module:: pcapkit.protocols.internet -:mod:`pcapkit.protocols.internet` is collection of all protocols -in internet layer, with detailed implementation and methods. +:mod:`pcapkit.protocols.internet` is the collection of all protocols +in the internet layer, with detailed implementation and methods. """ -# TODO: Implements ECN, ICMP, ICMPv6, IGMP, Shim6. +# TODO: Implement ECN, ICMP, ICMPv6, IGMP, Shim6. # Base Class for Internet Layer from pcapkit.protocols.internet.internet import Internet diff --git a/pcapkit/protocols/internet/ah.py b/pcapkit/protocols/internet/ah.py index 1c3564b081..f835555187 100644 --- a/pcapkit/protocols/internet/ah.py +++ b/pcapkit/protocols/internet/ah.py @@ -6,7 +6,7 @@ :mod:`pcapkit.protocols.internet.ah` contains :class:`~pcapkit.protocols.internet.ah.AH` only, -which implements extractor for Authentication +which implements the extractor for Authentication Header (AH) [*]_, whose structure is described as below: @@ -276,7 +276,7 @@ def __post_init__(self, file: 'Optional[IO[bytes] | bytes]' = None, length: 'Opt **kwargs: Arbitrary keyword arguments. See Also: - For construction argument, please refer to :meth:`self.make `. + For construction arguments, please refer to :meth:`self.make `. """ #: bool: If the protocol is used as an IPv6 extension header. diff --git a/pcapkit/protocols/internet/esp.py b/pcapkit/protocols/internet/esp.py index f393cabb08..4561714495 100644 --- a/pcapkit/protocols/internet/esp.py +++ b/pcapkit/protocols/internet/esp.py @@ -6,7 +6,7 @@ :mod:`pcapkit.protocols.internet.esp` contains :class:`~pcapkit.protocols.internet.esp.ESP`, -which implements extractor for Encapsulating +which implements the extractor for Encapsulating Security Payload (ESP) [*]_, whose structure is described as below: @@ -16,7 +16,7 @@ 0 0 ``esp.spi`` Security Parameters Index (SPI) 4 32 ``esp.seq`` Sequence Number 8 64 ``esp.payload_data`` Payload Data (variable, encrypted) - ? ? Padding (0-255 bytes, encrypted) + ? ? ``esp.padding`` Padding (0-255 bytes, encrypted) ? ? ``esp.pad_len`` Pad Length (encrypted) ? ? ``esp.next`` Next Header (encrypted) ? ? ``esp.icv`` Integrity Check Value (ICV, variable) @@ -197,7 +197,7 @@ from pcapkit.protocols.protocol import ProtocolBase -#: Cached :mod:`cryptography` primitives, c.f. :func:`load_cryptography`. +#: Cached :mod:`cryptography` primitives, see :func:`load_cryptography`. #: :data:`NotImplemented` means the import has not been attempted yet, and #: :data:`None` that it was attempted and |cryptography|_ is not installed, and #: a tuple holds the loaded primitives, so a missing dependency is not retried @@ -209,10 +209,10 @@ def load_cryptography() -> 'Optional[tuple[Any, Any, Any, Type[Exception]]]': """Load the optional |cryptography|_ primitives. Returns: - A 4-tuple of ``(Cipher, algorithms, modes, InvalidTag)`` taken from - :mod:`cryptography.hazmat.primitives.ciphers` and - :mod:`cryptography.exceptions`, or :data:`None` when - |cryptography|_ is not installed. + A 4-tuple of ``(Cipher, algorithms, modes, InvalidTag)``, the first + three taken from :mod:`cryptography.hazmat.primitives.ciphers` and the + last being :exc:`cryptography.exceptions.InvalidTag`, or :data:`None` + when |cryptography|_ is not installed. Notes: The import is attempted at most once and the outcome is cached, so @@ -296,8 +296,8 @@ class CipherSuite(Info): A member of :class:`Cipher ` records only that IANA registered the transform. This records how to apply it, and - membership of :data:`CIPHER_SUITES` is what "supported" means -- see the - module docstring. + membership of :data:`CIPHER_SUITES` is what "supported" means -- see + :ref:`esp-algorithm-support`. """ @@ -497,14 +497,14 @@ class SecurityAssociation: spi: Security Parameters Index the SA applies to; :data:`None` matches any SPI, which is convenient for a capture holding a single tunnel. - encryption: Encryption algorithm, c.f. :meth:`CipherSuite.get`. Must + encryption: Encryption algorithm, see :meth:`CipherSuite.get`. Must be one :mod:`pcapkit` implements; being in the IANA registry is not enough. encryption_key: Encryption keying material. For an AEAD suite this is the AES key followed by the 4-octet salt [:rfc:`4106` ยง8.1], unless ``salt`` is given separately. salt: AEAD salt, when not appended to ``encryption_key``. - integrity: Integrity algorithm, c.f. :meth:`IntegritySuite.get`. Must + integrity: Integrity algorithm, see :meth:`IntegritySuite.get`. Must be :attr:`Integrity.NONE ` for an AEAD suite, which provides its own. integrity_key: Integrity key. @@ -1334,7 +1334,7 @@ def __post_init__(self, file: 'Optional[IO[bytes] | bytes]' = None, length: 'Opt **kwargs: Arbitrary keyword arguments. See Also: - For construction argument, please refer to :meth:`self.make `. + For construction arguments, please refer to :meth:`self.make `. """ #: bool: If the protocol is used as an IPv6 extension header. diff --git a/pcapkit/protocols/internet/hip.py b/pcapkit/protocols/internet/hip.py index 3031cbf08b..932c5afd03 100644 --- a/pcapkit/protocols/internet/hip.py +++ b/pcapkit/protocols/internet/hip.py @@ -6,7 +6,7 @@ :mod:`pcapkit.protocols.internet.hip` contains :class:`~pcapkit.protocols.internet.hip.HIP` only, -which implements extractor for Host Identity +which implements the extractor for Host Identity Protocol (HIP) [*]_, whose structure is described as below: @@ -15,11 +15,11 @@ ======= ========= ====================== ================================== 0 0 ``hip.next`` Next Header 1 8 ``hip.length`` Header Length - 2 16 ``hip.packet_fixed`` Reserved (``\\x00``) + 2 16 ``hip.packet_fixed`` Fixed Bit (``0``) 2 17 ``hip.type`` Packet Type 3 24 ``hip.version`` Version 3 28 ``hip.reserved`` Reserved - 3 31 ``hip.version_fixed`` Reserved (``\\x01``) + 3 31 ``hip.version_fixed`` Fixed Bit (``1``) 4 32 ``hip.chksum`` Checksum 6 48 ``hip.control`` Controls 8 64 ``hip.shit`` Sender's Host Identity Tag @@ -417,8 +417,7 @@ class HIP(IPv6_Ext[Data_HIP, Schema_HIP], Internet[Data_HIP, Schema_HIP], # Defaults. ########################################################################## - #: DefaultDict[Enum_Parameter, str | tuple[ParameterParser, ParameterConstructor]]: Parameter - #: code to method mapping, c.f. :meth:`_read_hip_param` and/or + #: Parameter code to method mapping, see :meth:`_read_hip_param` and/or #: :meth:`_make_hip_param`. A :obj:`str` value names the methods #: ``_read_param_${name}`` and ``_make_param_${name}``, falling back to #: ``_read_param_unassigned`` / ``_make_param_unassigned`` when they do not @@ -766,7 +765,7 @@ def __post_init__(self, file: 'Optional[IO[bytes] | bytes]' = None, length: 'Opt **kwargs: Arbitrary keyword arguments. See Also: - For construction argument, please refer to :meth:`self.make `. + For construction arguments, please refer to :meth:`self.make `. """ #: bool: If the protocol is used as an IPv6 extension header. diff --git a/pcapkit/protocols/internet/hopopt.py b/pcapkit/protocols/internet/hopopt.py index 1d9da85304..c933c386b8 100644 --- a/pcapkit/protocols/internet/hopopt.py +++ b/pcapkit/protocols/internet/hopopt.py @@ -6,7 +6,7 @@ :mod:`pcapkit.protocols.internet.hopopt` contains :class:`~pcapkit.protocols.internet.hopopt.HOPOPT` -only, which implements extractor for IPv6 Hop-by-Hop +only, which implements the extractor for IPv6 Hop-by-Hop Options header (HOPOPT) [*]_, whose structure is described as below: @@ -208,8 +208,7 @@ class HOPOPT(IPv6_Ext[Data_HOPOPT, Schema_HOPOPT], # Defaults. ########################################################################## - #: DefaultDict[Enum_Option, str | tuple[OptionParser, OptionConstructor]]: Option - #: code to method mapping, c.f. :meth:`_read_hopopt_options` and/or + #: Option code to method mapping, see :meth:`_read_hopopt_options` and/or #: :meth:`_make_hopopt_options`. A :obj:`str` value names the methods #: ``_read_opt_${name}`` and ``_make_opt_${name}``, falling back to #: ``_read_opt_none`` / ``_make_opt_none`` when they do not exist; any other @@ -437,7 +436,7 @@ def __post_init__(self, file: 'Optional[IO[bytes] | bytes]' = None, length: 'Opt **kwargs: Arbitrary keyword arguments. See Also: - For construction argument, please refer to :meth:`make`. + For construction arguments, please refer to :meth:`make`. """ #: bool: If the protocol is used as an IPv6 extension header. @@ -496,7 +495,7 @@ def _read_opt_type(self, kind: 'int') -> 'tuple[int, bool]': Returns: Extracted HOPOPT option type field information (unknown option - action and change flag), c.f. [:rfc:`8200#section-4.2`]. + action and change flag), see [:rfc:`8200#section-4.2`]. """ bin_ = bin(kind)[2:].zfill(8) @@ -972,7 +971,7 @@ def _read_opt_qs(self, schema: 'Schema_QuickStartOption', *, options: 'Option') Note: An option whose QS function is neither of the two above has no defined layout, so the schema keeps it as an unassigned option and - it is parsed as one, c.f. :meth:`_read_opt_none`. + it is parsed as one, see :meth:`_read_opt_none`. """ if isinstance(schema, Schema_UnassignedOption): @@ -1886,7 +1885,7 @@ def _make_opt_qs(self, code: 'Enum_Option', opt: 'Optional[Data_QuickStartOption Returns: Constructed option schema; an unassigned option schema if ``opt`` - is a Quick-Start option parsed as unassigned, c.f. :meth:`_read_opt_qs`. + is a Quick-Start option parsed as unassigned, see :meth:`_read_opt_qs`. """ if isinstance(opt, Data_UnassignedOption): @@ -2111,7 +2110,7 @@ def _make_opt_ilnp(self, code: 'Enum_Option', opt: 'Optional[Data_ILNPOption]' = ) # NOTE: ``nonce`` is packed by a NumberField whose width is this very - # ``len`` (c.f. pcapkit.protocols.schema.internet.hopopt.ILNPOption), so + # ``len`` (see pcapkit.protocols.schema.internet.hopopt.ILNPOption), so # the declared octet count must be the ceiling of the bit length over # eight. ``bit_length() // 8`` floors, and ``math.ceil`` around an # integer division is a no-op, so any nonce whose bit length is not a @@ -2230,7 +2229,7 @@ def _make_opt_ip_dff(self, code: 'Enum_Option', opt: 'Optional[Data_IPDFFOption] reserved = opt.flags.reserved seq = opt.seq - # ``OptDataLenDFF`` is 3 per RFC 6971 Errata ID 3937, c.f. _read_opt_ip_dff. + # ``OptDataLenDFF`` is 3 per RFC 6971 Errata ID 3937, see _read_opt_ip_dff. return Schema_IPDFFOption( type=code, len=3, diff --git a/pcapkit/protocols/internet/internet.py b/pcapkit/protocols/internet/internet.py index 2af8e23393..8c4f3863bb 100644 --- a/pcapkit/protocols/internet/internet.py +++ b/pcapkit/protocols/internet/internet.py @@ -39,7 +39,7 @@ #: contextvars.ContextVar[int]: Where the payload :meth:`Internet._make_payload` #: rebuilds sits in a chain of IPv6 extension headers, should it be one: one past #: the layer it is the payload of, as :meth:`Internet._next_exthdr_depth` places -#: it while parsing, c.f. :data:`~pcapkit.utilities.config.EXTENSION_HEADER_LIMIT`. +#: it while parsing, see :data:`~pcapkit.utilities.config.EXTENSION_HEADER_LIMIT`. _exthdr_rebuilt = contextvars.ContextVar('_exthdr_rebuilt', default=0) @@ -103,8 +103,8 @@ class Internet(ProtocolBase[_PT, _ST], Generic[_PT, _ST]): # pylint: disable=ab #: Layer of protocol. __layer__ = 'Internet' # type: Literal['Internet'] - #: DefaultDict[int, ModuleDescriptor[ProtocolBase] | ~typing.Type[ProtocolBase]]: Protocol index mapping for decoding next layer, - #: c.f. :meth:`self._decode_next_layer ` + #: Protocol index mapping for decoding next layer, + #: see :meth:`self._decode_next_layer ` #: & :meth:`self._import_next_layer `. __proto__ = collections.defaultdict( lambda: ModuleDescriptor('pcapkit.protocols.misc.raw', 'Raw'), @@ -130,7 +130,7 @@ class Internet(ProtocolBase[_PT, _ST], Generic[_PT, _ST]): # pylint: disable=ab # ``protocols.application`` and reports ``__layer__ = 'Application'``, # because a routing protocol computes the forwarding table rather # than forwarding packets -- the dispatch tier and the subpackage are - # deliberately decoupled, c.f. + # deliberately decoupled, see # :doc:`/contributing/conventions/protocol-layer-placement`. Enum_TransType.OSPFIGP: ModuleDescriptor('pcapkit.protocols.application.ospf', 'OSPF'), }, @@ -138,7 +138,7 @@ class Internet(ProtocolBase[_PT, _ST], Generic[_PT, _ST]): # pylint: disable=ab #: int: How many IPv6 extension headers in a row the next layer follows: #: this layer's place in such a chain, or how many headers - #: :class:`~pcapkit.protocols.internet.ipv6.IPv6` walked, else ``0``, c.f. + #: :class:`~pcapkit.protocols.internet.ipv6.IPv6` walked, else ``0``, see #: :data:`~pcapkit.utilities.config.EXTENSION_HEADER_LIMIT` and :meth:`_next_exthdr_depth`. _exthdr_depth = 0 @@ -231,7 +231,7 @@ def __post_init__(self, file: 'Optional[IO[bytes] | bytes]' = None, _exthdr_depth (int): Where this layer is in a chain of IPv6 extension headers, counting from ``1``, or ``0`` if it is not in one. Handed over by :meth:`_import_next_layer` while - parsing, c.f. :data:`~pcapkit.utilities.config.EXTENSION_HEADER_LIMIT`; a layer + parsing, see :data:`~pcapkit.utilities.config.EXTENSION_HEADER_LIMIT`; a layer constructed instead, as :meth:`from_data` rebuilds one, takes it from :meth:`_rebuilt_exthdr_depth` (:issue:`1619`). **kwargs: Arbitrary keyword arguments. @@ -285,7 +285,7 @@ def _next_exthdr_depth(self, proto: 'Optional[int]', extension: 'bool' = False) proto: next layer protocol index extension: if the next layer is parsed as an extension header by :class:`~pcapkit.protocols.internet.ipv6.IPv6`'s walk, which - counts the chain itself, c.f. :meth:`IPv6._decode_next_layer + counts the chain itself, see :meth:`IPv6._decode_next_layer ` Returns: @@ -338,7 +338,7 @@ def _make_payload(cls, data: 'Data', exclude: 'tuple[str, ...]' = ()) -> 'Protoc Args: data: protocol data - exclude: keys of ``data`` that are not the payload, c.f. + exclude: keys of ``data`` that are not the payload, see :meth:`ProtocolBase._make_payload ` @@ -364,7 +364,7 @@ def _next_layer_class(self, proto: 'Optional[int]', file_: 'bytes', length: 'int proto: next layer protocol index file\_: payload of the current layer length: valid (*non-padding*) length - extension: if is extension header, c.f. :meth:`_next_exthdr_depth` + extension: if is extension header, see :meth:`_next_exthdr_depth` Returns: :class:`~pcapkit.protocols.misc.null.NoPayload` if there is @@ -482,7 +482,7 @@ def _import_next_layer(self, proto: 'int', length: 'Optional[int]' = None, *, # :class:`~pcapkit.protocols.misc.raw.Raw`, with one :exc:`~pcapkit.utilities.warnings.ProtocolWarning` (:issue:`1604`). Each header dissects the next one from here, so the chain's depth - is handed to the next layer, c.f. :meth:`_next_layer_class`. + is handed to the next layer, see :meth:`_next_layer_class`. """ if payload is None: diff --git a/pcapkit/protocols/internet/ipv4.py b/pcapkit/protocols/internet/ipv4.py index 267eb97e5e..338b302336 100644 --- a/pcapkit/protocols/internet/ipv4.py +++ b/pcapkit/protocols/internet/ipv4.py @@ -6,13 +6,13 @@ :mod:`pcapkit.protocols.internet.ipv4` contains :class:`~pcapkit.protocols.internet.ipv4.IPv4` only, -which implements extractor for Internet Protocol +which implements the extractor for Internet Protocol version 4 (IPv4) [*]_, whose structure is described as below: -======= ========= ====================== ============================================= +======= ========= ======================= ============================================ Octets Bits Name Description -======= ========= ====================== ============================================= +======= ========= ======================= ============================================ 0 0 ``ipv4.version`` Version (``4``) 0 4 ``ipv4.hdr_len`` Internet Header Length (IHL) 1 8 ``ipv4.tos.pre`` Precedence @@ -22,7 +22,7 @@ 1 14 ``ipv4.tos.ecn`` Explicit Congestion Notification (ECN) 2 16 ``ipv4.len`` Total Length 4 32 ``ipv4.id`` Identification - 6 48 Reserved Bit (must be ``\\x00``) + 6 48 ``ipv4.flags.reserved`` Reserved Bit (must be ``0``) 6 49 ``ipv4.flags.df`` Don't Fragment (DF) 6 50 ``ipv4.flags.mf`` More Fragments (MF) 6 51 ``ipv4.offset`` Fragment Offset @@ -32,7 +32,7 @@ 12 96 ``ipv4.src`` Source IP Address 16 128 ``ipv4.dst`` Destination IP Address 20 160 ``ipv4.options`` IP Options (if IHL > ``5``) -======= ========= ====================== ============================================= +======= ========= ======================= ============================================ .. [*] https://en.wikipedia.org/wiki/IPv4 @@ -214,8 +214,7 @@ class IPv4(IP[Data_IPv4, Schema_IPv4], # Defaults. ########################################################################## - #: DefaultDict[Enum_OptionNumber, str | tuple[OptionParser, OptionConstructor]]: Option - #: code to method mapping, c.f. :meth:`_read_ipv4_options` and/or + #: Option code to method mapping, see :meth:`_read_ipv4_options` and/or #: :meth:`_make_ipv4_options`. A :obj:`str` value names the methods #: ``_read_opt_${name}`` and ``_make_opt_${name}``, falling back to #: ``_read_opt_unassigned`` / ``_make_opt_unassigned`` when they do not @@ -491,7 +490,7 @@ def make(self, total_length: Total length of the packet, header included; computed from the header and the payload when omitted. padding: Octets after the End of Option List, written as is when - ``options`` is a container that carries an ``EOOL``, c.f. + ``options`` is a container that carries an ``EOOL``, see :meth:`_make_ipv4_options`. payload: Payload of the packet. trailer: Octets after the packet, outside the Total Length, such as @@ -1317,7 +1316,7 @@ def _read_opt_qs(self, schema: 'Schema_QSOption', *, options: 'Option') -> 'Data Note: An option whose QS function is neither of the two above has no defined layout, so the schema keeps it as an unassigned option and - it is parsed as one, c.f. :meth:`_read_opt_unassigned`. + it is parsed as one, see :meth:`_read_opt_unassigned`. """ if isinstance(schema, Schema_UnassignedOption): @@ -2094,7 +2093,7 @@ def _make_opt_qs(self, kind: 'Enum_OptionNumber', option: 'Optional[Data_QuickSt Returns: Constructed option schema. An unassigned option schema if ``option`` - is a Quick-Start option parsed as unassigned, c.f. :meth:`_read_opt_qs`, + is a Quick-Start option parsed as unassigned, see :meth:`_read_opt_qs`, or if ``func`` is neither of the assigned functions, in which case the option takes the eight-octet layout of a Quick-Start Request. diff --git a/pcapkit/protocols/internet/ipv6.py b/pcapkit/protocols/internet/ipv6.py index 36275e37da..f12a18aa05 100644 --- a/pcapkit/protocols/internet/ipv6.py +++ b/pcapkit/protocols/internet/ipv6.py @@ -6,7 +6,7 @@ :mod:`pcapkit.protocols.internet.ipv6` contains :class:`~pcapkit.protocols.internet.ipv6.IPv6` only, -which implements extractor for Internet Protocol +which implements the extractor for Internet Protocol version 6 (IPv6) [*]_, whose structure is described as below: @@ -99,8 +99,8 @@ class IPv6(IP[Data_IPv6, Schema_IPv6], #: Extension header codes with a *dedicated* parser class in this #: package whose layout follows :rfc:`6564#section-4`'s generic ``next`` + - #: ``Hdr Ext Len`` format (see the module docstring of - #: :mod:`pcapkit.protocols.internet.ipv6_ext` for the exception table). + #: ``Hdr Ext Len`` format (see :ref:`ipv6-ext-length-rules` for the + #: exception table). #: When that dedicated parser raises, :meth:`_import_next_layer` #: substitutes :class:`~pcapkit.protocols.internet.ipv6_ext.IPv6_Ext` #: instead of letting the generic @@ -113,9 +113,8 @@ class IPv6(IP[Data_IPv6, Schema_IPv6], #: * :attr:`~pcapkit.const.ipv6.extension_header.ExtensionHeader.Shim6` #: has no dedicated parser class in this package, so there is no "own #: parser" for it to raise from. It reaches :class:`~pcapkit.protocols.internet.ipv6_ext.IPv6_Ext` - #: by *direct* registration (see the bottom of - #: :mod:`pcapkit.protocols.internet.ipv6_ext`), which already produces - #: exactly this class. + #: by *direct* registration (see :ref:`ipv6-ext-entry-paths`), which + #: already produces exactly this class. #: * ``ESP`` *does* have a dedicated, registered parser #: (:class:`~pcapkit.protocols.internet.esp.ESP`). It is excluded #: because :rfc:`4303` places the real Next Header byte inside the @@ -245,7 +244,7 @@ def read(self, length: 'Optional[int]' = None, *, raise ProtocolError(f"[IPv6] invalid version: {schema.hextet['version']}") # NOTE: A receiver treats each of these as an error (:issue:`1687`), so - # the frame stops here, c.f. :meth:`IPv4.read + # the frame stops here, see :meth:`IPv4.read # `. A Fragment header beside # the Jumbo Payload option is caught on the walk, see # :meth:`_decode_next_layer`. @@ -266,7 +265,7 @@ def read(self, length: 'Optional[int]' = None, *, }) # type: Data_IPv6 # NOTE: Octets captured past the Payload Length are kept as captured, - # c.f. :meth:`IPv4.read ` + # see :meth:`IPv4.read ` # (:issue:`1209`). if schema.trailer: ipv6.__update__({ @@ -274,7 +273,7 @@ def read(self, length: 'Optional[int]' = None, *, }) # NOTE: A jumbogram's extent is its Jumbo Payload Length, not the zero - # Payload Length, c.f. :meth:`Schema_IPv6.post_process + # Payload Length, see :meth:`Schema_IPv6.post_process # ` # (:issue:`1434`); the check above leaves a zero one beside it. jumbo = jumbo_payload_length(schema.next, rest) @@ -505,7 +504,7 @@ def _lookup_exthdr(cls, data: 'Data_IPv6') -> 'tuple[tuple[str, ...], tuple[tupl # NOTE: A header whose dedicated parser raised was parsed by # :class:`~pcapkit.protocols.internet.ipv6_ext.IPv6_Ext` instead, - # c.f. :meth:`_import_next_layer`, and written under that class's + # see :meth:`_import_next_layer`, and written under that class's # key rather than the dedicated one's. Rebuilding it with the # dedicated class would look for fields only that class parses # (:issue:`1473`), so the key decides the parser. @@ -773,11 +772,11 @@ def _import_next_layer(self, proto: 'int', length: 'Optional[int]' = None, *, # dedicated parser, so they reach plain ``Raw`` with no exception involved; :meth:`_decode_next_layer` stops its walk structurally on any layer whose info carries no ``next`` attribute, ``Raw`` - included. ``ESP``'s info always carries a ``next`` (:data:`None`, - since :rfc:`4303` encrypts the real value), so neither this - substitution nor that structural check engages for it, and the walk - ends after it -- see :attr:`__generic_ext_codes__`'s docstring for - the full distinction. + included. ``ESP``'s info always carries a ``next`` (:data:`None` + unless its payload was decrypted, since :rfc:`4303` encrypts the + real value), so neither this substitution nor that structural + check engages for it, and the walk ends after it -- see + :attr:`__generic_ext_codes__`'s docstring for the full distinction. The upper layer past a walk cut at :data:`EXTENSION_HEADER_LIMIT ` is the diff --git a/pcapkit/protocols/internet/ipv6_ext.py b/pcapkit/protocols/internet/ipv6_ext.py index f4217d3011..6442582b0c 100644 --- a/pcapkit/protocols/internet/ipv6_ext.py +++ b/pcapkit/protocols/internet/ipv6_ext.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""IPv6_Ext - IPv6 Extension Header -==================================== +"""IPv6-Ext - IPv6 Extension Header +================================ .. module:: pcapkit.protocols.internet.ipv6_ext @@ -11,8 +11,8 @@ stands in for a header whose dedicated parser is unavailable or has failed. The class docstring separates these roles. -Why this is safe in general ----------------------------- +Length Rules +------------ :rfc:`6564#section-4` is Standards Track and says, with an RFC 2119 **MUST**, that any IPv6 extension header defined from April 2012 @@ -39,33 +39,32 @@ The exception table, verified against IANA's ``protocol-numbers-1.csv`` *IPv6 Extension Header* column and each cited RFC: -======================================================= =========================================== -Header(s) Length rule -======================================================= =========================================== -``HOPOPT``, ``IPv6-Route``, ``IPv6-Opts``, ``MH``, ``(octet[1] + 1) * 8`` -- the :rfc:`6564` -``HIP``, ``Shim6`` generic rule -``IPv6-Frag`` constant ``8``; octet[1] is Reserved, not a - length (:rfc:`8200#section-4.5`) -``AH`` ``(octet[1] + 2) * 4`` -- :rfc:`4302#section-2.2` - counts in 4-octet units with a bias of 2, - not :rfc:`6564`'s 8-octet units and bias of 1 -``ESP`` terminal -- has a dedicated, registered parser - (:class:`~pcapkit.protocols.internet.esp.ESP`), - but its Next Header byte is inside the - encrypted trailer (:rfc:`4303`), so its own - info's ``next`` is :data:`None` rather than a - value to continue on -``253``, ``254`` terminal -- no dedicated parser exists, so no - next header field is ever read at all, either -======================================================= =========================================== +===================================================================== ================================================= +Header(s) Length rule +===================================================================== ================================================= +``HOPOPT``, ``IPv6-Route``, ``IPv6-Opts``, ``MH``, ``HIP``, ``Shim6`` ``(octet[1] + 1) * 8`` -- the :rfc:`6564` + generic rule +``IPv6-Frag`` constant ``8``; octet[1] is Reserved, not a + length (:rfc:`8200#section-4.5`) +``AH`` ``(octet[1] + 2) * 4`` -- :rfc:`4302#section-2.2` + counts in 4-octet units with a bias of 2, + not :rfc:`6564`'s 8-octet units and bias of 1 +``ESP`` terminal -- has a dedicated, registered parser + (:class:`~pcapkit.protocols.internet.esp.ESP`), + but its Next Header byte is inside the + encrypted trailer (:rfc:`4303`), so the walk + cannot step past it on the wire +``253``, ``254`` terminal -- no dedicated parser exists, so no + next header field is ever read at all, either +===================================================================== ================================================= This table classifies by *wire format* alone, over every code :class:`~pcapkit.const.ipv6.extension_header.ExtensionHeader` enumerates, which match IANA's *IPv6 Extension Header Types* registry exactly (GitHub issue :issue:`925`). -``Shim6`` conforms to it (:rfc:`5533`) but has no dedicated parser class; see -"Entry paths" below for how it reaches this class by direct dispatch. +``Shim6`` conforms to the generic rule (:rfc:`5533`) but has no dedicated parser class; see +"Entry Paths" below for how it reaches this class by direct dispatch. :rfc:`8200#section-4.5` sets Encapsulating Security Payload aside: ESP is not an extension header, and the RFC lists it among upper-layer headers. @@ -77,16 +76,17 @@ enters :meth:`IPv6._decode_next_layer `'s walk, being a real :class:`~pcapkit.const.ipv6.extension_header.ExtensionHeader` member, but -they part ways there. ``ESP`` resolves to its own dedicated parser, whose info -carries a ``next`` of :data:`None`, so the walk ends the ordinary way with -``ExtensionHeader(None)`` failing at the top of the next iteration. ``253`` +they part ways there. ``ESP`` resolves to its own dedicated parser, which +decodes any plaintext it recovers itself and whose info carries a ``next`` of +:data:`None` whenever the payload stays opaque, so the walk ends the ordinary +way with ``ExtensionHeader(None)`` failing at the top of the next iteration. ``253`` and ``254`` have no dedicated parser and resolve to plain :class:`~pcapkit.protocols.misc.raw.Raw`, whose info has no ``next`` *attribute*. For these two, and any future IANA code without an implementation, the walk stops on a *structural* check (does the parsed layer carry a ``next`` at all?) rather than on a list of codes. -Entry paths +Entry Paths ----------- This class is reached in these ways: @@ -115,8 +115,8 @@ catches the failure itself, one layer in from ``beholder``, and substitutes this class: the bad header costs only itself, not the rest of the chain. -The overrun guard -------------------- +The Overrun Guard +----------------- The house convention for a declared length that does not fit what remains is warn-and-clip: emit a warning naming what was declared against what is @@ -185,9 +185,11 @@ class IPv6_Ext(Internet[_PT, _ST], Generic[_PT, _ST], """This class implements a generic IPv6 extension header parser, and is the shared base of every IPv6 extension header in this package. - The module docstring has the RFC citations behind the length rules, the - ways this class is dispatched to, and why an overrun stops the walk rather - than clipping. + The module documentation has the RFC citations behind the + :ref:`length rules `, the + :ref:`ways this class is dispatched to `, and + :ref:`why an overrun stops the walk ` rather than + clipping. .. rubric:: Base and Fallback Roles @@ -332,8 +334,8 @@ def next(self) -> 'Optional[Enum_TransType]': their data models records the Next Header value under this name. :data:`None` when the declared length would have overrun what remained - of the chain and the walk stopped instead of trusting it; see the - module docstring's "overrun guard" section. + of the chain and the walk stopped instead of trusting it; see + :ref:`ipv6-ext-overrun-guard`. """ return cast('_NextHeaderData', self._info).next @@ -432,7 +434,7 @@ def read(self, length: 'Optional[int]' = None, *, # pylint: disable=arguments-d if nominal > length: # Warns like the house convention but stops rather than clips; see - # the module docstring's "overrun guard" section. + # the module docstring's "The Overrun Guard" section. warn(f'IPv6: extension header declares a length of {nominal} octet(s) with ' f'{length} octet(s) left in the chain; stopping the walk instead of ' f'skipping past it', SchemaWarning, stacklevel=stacklevel()) @@ -472,7 +474,8 @@ def make(self, *, next: Next header type. len: Raw ``Hdr Ext Len`` octet to emit. The caller must size it, since this class cannot know at construction time which - per-protocol rule (see the module docstring) it must satisfy. + per-protocol rule (see :ref:`ipv6-ext-length-rules`) it must + satisfy. data: Header-specific content after the two fixed octets, emitted verbatim ahead of ``payload``. payload: Payload of current instance. @@ -553,7 +556,7 @@ def __post_init__(self, file: 'Optional[IO[bytes] | bytes]' = None, length: 'Opt docstring's "Base and Fallback Roles") and ``version`` is not ``6``. See Also: - For construction argument, please refer to :meth:`make`. + For construction arguments, please refer to :meth:`make`. Note: The version gate is scoped to the fallback role by the same diff --git a/pcapkit/protocols/internet/ipv6_frag.py b/pcapkit/protocols/internet/ipv6_frag.py index f2b5c70329..0f323784fa 100644 --- a/pcapkit/protocols/internet/ipv6_frag.py +++ b/pcapkit/protocols/internet/ipv6_frag.py @@ -6,7 +6,7 @@ :mod:`pcapkit.protocols.internet.ipv6_frag` contains :class:`~pcapkit.protocols.internet.ipv6_frag.IPv6_Frag` -only, which implements extractor for Fragment Header for +only, which implements the extractor for Fragment Header for IPv6 (IPv6-Frag) [*]_, whose structure is described as below: @@ -239,7 +239,7 @@ def __post_init__(self, file: 'Optional[IO[bytes] | bytes]' = None, length: 'Opt **kwargs: Arbitrary keyword arguments. See Also: - For construction argument, please refer to :meth:`self.make `. + For construction arguments, please refer to :meth:`self.make `. """ #: bool: If the protocol is used as an IPv6 extension header. diff --git a/pcapkit/protocols/internet/ipv6_opts.py b/pcapkit/protocols/internet/ipv6_opts.py index 800cd76c1c..60f7609c21 100644 --- a/pcapkit/protocols/internet/ipv6_opts.py +++ b/pcapkit/protocols/internet/ipv6_opts.py @@ -6,7 +6,7 @@ :mod:`pcapkit.protocols.internet.ipv6_opts` contains :class:`~pcapkit.protocols.internet.ipv6_opts.IPv6_Opts` -only, which implements extractor for Destination Options +only, which implements the extractor for Destination Options for IPv6 (IPv6-Opts) [*]_, whose structure is described as below: @@ -212,8 +212,7 @@ class IPv6_Opts(IPv6_Ext[Data_IPv6_Opts, Schema_IPv6_Opts], # Defaults. ########################################################################## - #: DefaultDict[Enum_Option, str | tuple[OptionParser, OptionConstructor]]: Option - #: code to method mapping, c.f. :meth:`_read_ipv6_opts` and/or + #: Option code to method mapping, see :meth:`_read_ipv6_opts` and/or #: :meth:`_make_ipv6_opts`. A :obj:`str` value names the methods #: ``_read_opt_${name}`` and ``_make_opt_${name}``, falling back to #: ``_read_opt_none`` / ``_make_opt_none`` when they do not exist; any other @@ -429,7 +428,7 @@ def __post_init__(self, file: 'Optional[IO[bytes] | bytes]' = None, length: 'Opt **kwargs: Arbitrary keyword arguments. See Also: - For construction argument, please refer to :meth:`self.make `. + For construction arguments, please refer to :meth:`self.make `. """ #: bool: If the protocol is used as an IPv6 extension header. @@ -488,7 +487,7 @@ def _read_opt_type(self, kind: 'int') -> 'tuple[int, bool]': Returns: Extracted IPv6-Opts option type field information (unknown option - action and change flag), c.f. [:rfc:`8200#section-4.2`]. + action and change flag), see [:rfc:`8200#section-4.2`]. """ bin_ = bin(kind)[2:].zfill(8) @@ -960,7 +959,7 @@ def _read_opt_qs(self, schema: 'Schema_QuickStartOption', *, options: 'Option') Note: An option whose QS function is neither of the two above has no defined layout, so the schema keeps it as an unassigned option and - it is parsed as one, c.f. :meth:`_read_opt_none`. + it is parsed as one, see :meth:`_read_opt_none`. """ if isinstance(schema, Schema_UnassignedOption): @@ -1874,7 +1873,7 @@ def _make_opt_qs(self, code: 'Enum_Option', opt: 'Optional[Data_QuickStartOption Returns: Constructed option schema; an unassigned option schema if ``opt`` - is a Quick-Start option parsed as unassigned, c.f. :meth:`_read_opt_qs`. + is a Quick-Start option parsed as unassigned, see :meth:`_read_opt_qs`. """ if isinstance(opt, Data_UnassignedOption): @@ -2099,7 +2098,7 @@ def _make_opt_ilnp(self, code: 'Enum_Option', opt: 'Optional[Data_ILNPOption]' = ) # NOTE: ``nonce`` is packed by a NumberField whose width is this very - # ``len`` (c.f. pcapkit.protocols.schema.internet.ipv6_opts.ILNPOption), + # ``len`` (see pcapkit.protocols.schema.internet.ipv6_opts.ILNPOption), # so the declared octet count must be the ceiling of the bit length over # eight. ``bit_length() // 8`` floors, and ``math.ceil`` around an # integer division is a no-op, so any nonce whose bit length is not a @@ -2218,7 +2217,7 @@ def _make_opt_ip_dff(self, code: 'Enum_Option', opt: 'Optional[Data_IPDFFOption] reserved = opt.flags.reserved seq = opt.seq - # ``OptDataLenDFF`` is 3 per RFC 6971 Errata ID 3937, c.f. _read_opt_ip_dff. + # ``OptDataLenDFF`` is 3 per RFC 6971 Errata ID 3937, see _read_opt_ip_dff. return Schema_IPDFFOption( type=code, len=3, diff --git a/pcapkit/protocols/internet/ipv6_route.py b/pcapkit/protocols/internet/ipv6_route.py index 82a1a0211f..05fa3a12d8 100644 --- a/pcapkit/protocols/internet/ipv6_route.py +++ b/pcapkit/protocols/internet/ipv6_route.py @@ -6,7 +6,7 @@ :mod:`pcapkit.protocols.internet.ipv6_route` contains :class:`~pcapkit.protocols.internet.ipv6_route.IPv6_Route` -only, which implements extractor for Routing Header for IPv6 +only, which implements the extractor for Routing Header for IPv6 (IPv6-Route) [*]_, whose structure is described as below: ======= ========= ==================== =============================== @@ -121,8 +121,7 @@ class IPv6_Route(IPv6_Ext[Data_IPv6_Route, Schema_IPv6_Route], # Defaults. ########################################################################## - #: DefaultDict[Enum_Routing, str | tuple[TypeParser, TypeConstructor]]: Type - #: code to method mapping. A :obj:`str` value names the methods + #: Type code to method mapping. A :obj:`str` value names the methods #: ``_read_data_type_${name}`` and ``_make_data_type_${name}``, falling back #: to ``_read_data_type_none`` / ``_make_data_type_none`` when they do not #: exist; any other value is a ``(parser, constructor)`` pair of callables. @@ -306,7 +305,7 @@ def make(self, Constructed packet data. Raises: - FieldValueError: If ``dst`` is a :obj:`bool` (c.f. + FieldValueError: If ``dst`` is a :obj:`bool` (see :func:`~pcapkit.corekit.fields.ipaddress.parse_ip_address`). .. versionchanged:: 1.5.0 @@ -436,7 +435,7 @@ def __post_init__(self, file: 'Optional[IO[bytes] | bytes]' = None, length: 'Opt (GitHub issue :issue:`505`). See Also: - For construction argument, please refer to :meth:`self.make `. + For construction arguments, please refer to :meth:`self.make `. """ #: bool: If the protocol is used as an IPv6 extension header. @@ -823,7 +822,7 @@ def _make_data_type_rpl(self, type: 'Enum_Routing', route: 'Optional[Data_RPL]' Constructed route data schema. Raises: - FieldValueError: If an entry of ``ip`` is a :obj:`bool` (c.f. + FieldValueError: If an entry of ``ip`` is a :obj:`bool` (see :func:`~pcapkit.corekit.fields.ipaddress.parse_ip_address`). ProtocolError: If ``ip`` is empty. diff --git a/pcapkit/protocols/internet/ipx.py b/pcapkit/protocols/internet/ipx.py index 18670a65ca..7a6bd321dd 100644 --- a/pcapkit/protocols/internet/ipx.py +++ b/pcapkit/protocols/internet/ipx.py @@ -6,7 +6,7 @@ :mod:`pcapkit.protocols.internet.ipx` contains :class:`~pcapkit.protocols.internet.ipx.IPX` only, -which implements extractor for Internetwork Packet +which implements the extractor for Internetwork Packet Exchange (IPX) [*]_, whose structure is described as below: diff --git a/pcapkit/protocols/internet/mh.py b/pcapkit/protocols/internet/mh.py index aa2561cd15..54097cf670 100644 --- a/pcapkit/protocols/internet/mh.py +++ b/pcapkit/protocols/internet/mh.py @@ -4,7 +4,7 @@ :mod:`pcapkit.protocols.internet.mh` contains :class:`~pcapkit.protocols.internet.mh.MH`, -which implements extractor for Mobility Header +which implements the extractor for Mobility Header (MH) [*]_, whose structure is described as below: ======= ========= ================== =============================== @@ -26,16 +26,6 @@ :class:`pcapkit.protocols.data.internet.mh.NTPTimestamp` instead (:issue:`1886`). -.. versionchanged:: 1.5.0 - - :class:`~pcapkit.protocols.data.internet.mh.NTPTimestamp` and - :class:`~pcapkit.protocols.data.internet.mh.PMIPv6Timestamp` are - :class:`~pcapkit.corekit.infoclass.Info` data models rather than named - tuples, so they no longer index, unpack, hash or compare equal to a - :obj:`tuple`, and the dumpers write them keyed by field, as - ``{"seconds": ..., "fraction": ...}``. For ``NTPTimestamp`` this is a - breaking change from 1.4.x (:issue:`1886`). - """ import collections import datetime @@ -556,7 +546,7 @@ class FastBindingAcknowledgmentStatus(EnumLookup, IntEnum): """[FastBindingAcknowledgmentStatus] Fast Binding Acknowledgment Status Codes. - Status values of the fast binding acknowledgment (FBack) message, c.f., + Status values of the fast binding acknowledgment (FBack) message, see :rfc:`5568#section-6.2.3`. Values below ``128`` indicate that the fast binding update was accepted by the receiving node, values of ``128`` and above that it was rejected. @@ -632,7 +622,7 @@ class IPv6AddressPrefixCode(EnumLookup, IntEnum): """[IPv6AddressPrefixCode] Mobility Header IPv6 Address/Prefix Option Codes. Option codes of the mobility header IPv6 address/prefix option, which - identify which address the option carries, c.f., + identify which address the option carries, see :rfc:`5568#section-6.4.2`. Note: @@ -696,7 +686,7 @@ def _missing_(cls, value: 'int') -> 'NoReturn': class LocalizedRoutingStatus(EnumLookup, IntEnum): """[LocalizedRoutingStatus] Localized Routing Acknowledgment Status Codes. - Status values of the localized routing acknowledgment (LRA) message, c.f., + Status values of the localized routing acknowledgment (LRA) message, see :rfc:`6705#section-10.2`. Values below ``128`` indicate that the initiation was processed successfully, values of ``128`` and above that it was rejected. @@ -756,7 +746,7 @@ class LMAAddressCode(EnumLookup, IntEnum): """[LMAAddressCode] Local Mobility Anchor Address Option Codes. Option codes of the local mobility anchor address option, which say which - address family the option carries, c.f., :rfc:`5949#section-6.2.2`. + address family the option carries, see :rfc:`5949#section-6.2.2`. Note: :rfc:`5949#section-6.2.2` defines these values inline and IANA keeps no @@ -1156,8 +1146,7 @@ class MH(IPv6_Ext[Data_MH, Schema_MH], # Defaults. ########################################################################## - #: DefaultDict[Enum_Packet, str | tuple[PacketParser, PacketConstructor]]: Message - #: type to method mapping. A :obj:`str` value names the methods + #: Message type to method mapping. A :obj:`str` value names the methods #: ``_read_msg_${name}`` and ``_make_msg_${name}``, falling back to #: ``_read_msg_unknown`` / ``_make_msg_unknown`` when they do not exist; any #: other value is a ``(parser, constructor)`` pair of callables. @@ -1191,8 +1180,7 @@ class MH(IPv6_Ext[Data_MH, Schema_MH], }, ) # type: DefaultDict[Enum_Packet | int, str | tuple[PacketParser, PacketConstructor]] - #: DefaultDict[Enum_Option, str | tuple[OptionParser, OptionConstructor]]: Option - #: type to method mapping. A :obj:`str` value names the methods + #: Option type to method mapping. A :obj:`str` value names the methods #: ``_read_opt_${name}`` and ``_make_opt_${name}``, falling back to #: ``_read_opt_none`` / ``_make_opt_none`` when they do not exist; any other #: value is a ``(parser, constructor)`` pair of callables. @@ -1273,8 +1261,7 @@ class MH(IPv6_Ext[Data_MH, Schema_MH], }, ) # type: DefaultDict[Enum_Option | int, str | tuple[OptionParser, OptionConstructor]] - #: DefaultDict[Enum_CGAExtension, str | tuple[ExtensionParser, ExtensionConstructor]]: CGA - #: extension type to method mapping. A :obj:`str` value names the + #: CGA extension type to method mapping. A :obj:`str` value names the #: methods ``_read_ext_${name}`` and ``_make_ext_${name}``, falling back to #: ``_read_ext_none`` / ``_make_ext_none`` when they do not exist; any other #: value is a ``(parser, constructor)`` pair of callables. @@ -1605,7 +1592,7 @@ def __post_init__(self, file: 'Optional[IO[bytes] | bytes]' = None, length: 'Opt **kwargs: Arbitrary keyword arguments. See Also: - For construction argument, please refer to :meth:`self.make `. + For construction arguments, please refer to :meth:`self.make `. """ #: bool: If the protocol is used as an IPv6 extension header. @@ -3684,7 +3671,7 @@ def _read_opt_ipv6_ap(self, schema: 'Schema_IPv6AddressPrefixOption', *, | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - The option code identifies which address the option carries, c.f., + The option code identifies which address the option carries, see :class:`~pcapkit.protocols.internet.mh.IPv6AddressPrefixCode`. It, too, is defined inline by :rfc:`5568#section-6.4.2` with no IANA registry behind it, hence the enumeration is local to this module. @@ -6957,8 +6944,8 @@ def _make_msg_be(self, message: 'Optional[Data_BindingErrorMessage]' = None, *, def _make_msg_fbu(self, message: 'Optional[Data_FastBindingUpdateMessage]' = None, *, seq: 'int' = 0, - ack: 'bool' = True, # MUST be set, c.f., RFC 5568, section 6.2.2 - home: 'bool' = True, # MUST be set, c.f., RFC 5568, section 6.2.2 + ack: 'bool' = True, # MUST be set, see RFC 5568, section 6.2.2 + home: 'bool' = True, # MUST be set, see RFC 5568, section 6.2.2 lla_compat: 'bool' = False, key_mngt: 'bool' = False, lifetime: 'int | timedelta' = 4, # reasonable default value @@ -7027,7 +7014,7 @@ def _make_msg_fback(self, message: 'Optional[Data_FastBindingAcknowledgmentMessa Args: message: Message data model. - status: Status code, c.f., + status: Status code, see :class:`~pcapkit.protocols.internet.mh.FastBindingAcknowledgmentStatus`. status_default: Default status code. status_namespace: Status code namespace. @@ -7099,7 +7086,7 @@ def _make_msg_fna(self, message: 'Optional[Data_FastNeighborAdvertisementMessage ) def _make_msg_emh(self, message: 'Optional[Data_ExperimentalMessage]' = None, *, - data: 'bytes' = b'\x00\x00', # 2 bytes of padding, c.f., RFC 5096, section 3 + data: 'bytes' = b'\x00\x00', # 2 bytes of padding, see RFC 5096, section 3 **kwargs: 'Any') -> 'Schema_ExperimentalMessage': """Make MH experimental mobility header message type. @@ -7441,7 +7428,7 @@ def _make_msg_lra(self, message: 'Optional[Data_LocalizedRoutingAcknowledgmentMe message: Message data model. seq: Sequence number. unsolicited: Unsolicited flag. - status: Status, c.f., + status: Status, see :class:`~pcapkit.protocols.internet.mh.LocalizedRoutingStatus`. status_default: Default status. status_namespace: Status namespace. @@ -8198,7 +8185,7 @@ def _make_opt_mn_id(self, type: 'Enum_Option', option: 'Optional[Data_MNIDOption f'bool, not {identifier!r} -- pass int({identifier!r}) if the ' f'numeric value is what is wanted') - # NOTE: The wire format is chosen by ``subtype_val`` (c.f. ``mn_id_selector``), + # NOTE: The wire format is chosen by ``subtype_val`` (see ``mn_id_selector``), # not by the Python type of ``identifier``, so the width has to be taken from # the former. For the ``IPv6_Address`` subtype the schema always packs a fixed # 16-octet address (:class:`~pcapkit.corekit.fields.ipaddress.IPv6AddressField` @@ -8243,7 +8230,7 @@ def _make_opt_mn_id(self, type: 'Enum_Option', option: 'Optional[Data_MNIDOption id_len = 16 elif isinstance(identifier, int): if subtype_val == Enum_MNIDSubtype.NAI: - # NOTE: NAI's field is a StringField (c.f. mn_id_selector), so an + # NOTE: NAI's field is a StringField (see mn_id_selector), so an # int has to become text -- and unlike the numeric subtypes below, # there is no non-arbitrary way to do that. str(identifier) packs # and round-trips fine, but an NAI is a network access identifier @@ -8257,7 +8244,7 @@ def _make_opt_mn_id(self, type: 'Enum_Option', option: 'Optional[Data_MNIDOption f'must be str, not int -- pass str({identifier!r}) if a ' f'decimal-digit NAI is really what is wanted') # NOTE: every other subtype's field is a - # BytesField(length=pkt['length'] - 1) (c.f. mn_id_selector) -- a + # BytesField(length=pkt['length'] - 1) (see mn_id_selector) -- a # numeric identifier, so unlike NAI there IS a non-arbitrary wire # form: its own minimal big-endian encoding. That is self-consistent # with the declared length by construction and round-trips exactly. @@ -8272,7 +8259,7 @@ def _make_opt_mn_id(self, type: 'Enum_Option', option: 'Optional[Data_MNIDOption id_len = max(1, math.ceil(identifier.bit_length() / 8)) identifier = identifier.to_bytes(id_len, 'big') elif subtype_val == Enum_MNIDSubtype.NAI: - # NOTE: NAI's field is a StringField (c.f. mn_id_selector), which + # NOTE: NAI's field is a StringField (see mn_id_selector), which # calls ``identifier.encode(...)`` to pack -- so anything but a # genuine str leaks a bare stdlib exception: AttributeError for # bytes/list/dict (no ``.encode``), TypeError for float/None/an @@ -8291,7 +8278,7 @@ def _make_opt_mn_id(self, type: 'Enum_Option', option: 'Optional[Data_MNIDOption id_len = len(identifier) else: # NOTE: every other subtype's field is a - # BytesField(length=pkt['length'] - 1) (c.f. mn_id_selector), + # BytesField(length=pkt['length'] - 1) (see mn_id_selector), # which hands ``identifier`` to ``struct.pack('Ns', ...)`` # unconverted -- so anything but bytes leaks a bare stdlib # exception: struct.error for str/list/dict (struct's ``s`` @@ -8378,7 +8365,7 @@ def _make_opt_mesg_id(self, type: 'Enum_Option', option: 'Optional[Data_MesgIDOp Args: type: Option type. option: Option data model. - timestamp: NTP timestamp, c.f., :rfc:`1305`. + timestamp: NTP timestamp, see :rfc:`1305`. interval: Moment to encode when neither ``option`` nor ``timestamp`` is given (``option`` supplies its own ``ntp_timestamp``); defaults to the current time. @@ -8613,7 +8600,7 @@ def _make_opt_badf(self, type: 'Enum_Option', option: 'Optional[Data_BADFOption] Note: The ``length`` field counts the authenticator only, excluding the - SPI, c.f., :meth:`_read_opt_badf`. + SPI, see :meth:`_read_opt_badf`. """ if option is not None: @@ -8643,7 +8630,7 @@ def _make_opt_ipv6_ap(self, type: 'Enum_Option', option: 'Optional[Data_IPv6Addr Args: type: Option type. option: Option data model. - code: Option code, c.f., + code: Option code, see :class:`~pcapkit.protocols.internet.mh.IPv6AddressPrefixCode`. code_default: Default option code. code_namespace: Option code namespace. @@ -9481,7 +9468,7 @@ def _make_opt_lmaa(self, type: 'Enum_Option', option: 'Optional[Data_LMAAddressO Args: type: Option type. option: Option data model. - code: Option code, c.f., + code: Option code, see :class:`~pcapkit.protocols.internet.mh.LMAAddressCode`. code_default: Default option code. code_namespace: Option code namespace. diff --git a/pcapkit/protocols/schema/internet/hopopt.py b/pcapkit/protocols/schema/internet/hopopt.py index baef4a0515..578f329ae1 100644 --- a/pcapkit/protocols/schema/internet/hopopt.py +++ b/pcapkit/protocols/schema/internet/hopopt.py @@ -435,17 +435,17 @@ def __init__(self, type: 'Enum_Option', len: 'int', hav: 'bytes') -> 'None': ... class PDMOption(Option, code=Enum_Option.PDM): """Header schema for HOPOPT performance and diagnostic metrics (PDM) options.""" - #: Scale delta time last received (DTLR). + #: Scale delta time last received (ScaleDTLR). scaledtlr: 'int' = UInt8Field() - #: Scale delta time last sent (DTLS). + #: Scale delta time last sent (ScaleDTLS). scaledtls: 'int' = UInt8Field() - #: Packet sequence number (PSN) this packet. + #: Packet sequence number (PSN) this packet (PSNTP). psntp: 'int' = UInt16Field() - #: Packet sequence number (PSN) last received. + #: Packet sequence number (PSN) last received (PSNLR). psnlr: 'int' = UInt16Field() - #: Delta time last received (DTLR). + #: Delta time last received (DeltaTLR). deltatlr: 'int' = UInt16Field() - #: Delta time last sent (DTLS). + #: Delta time last sent (DeltaTLS). deltatls: 'int' = UInt16Field() if TYPE_CHECKING: diff --git a/pcapkit/protocols/schema/internet/ipv4.py b/pcapkit/protocols/schema/internet/ipv4.py index af2d589578..aa08caff97 100644 --- a/pcapkit/protocols/schema/internet/ipv4.py +++ b/pcapkit/protocols/schema/internet/ipv4.py @@ -160,7 +160,7 @@ def quick_start_option_length(schema: 'Type[QSOption]') -> 'int': length = 0 for name, field in schema.__fields__.items(): # NOTE: A forward match consumes nothing and contributes no octets to - # ``bytes(schema)`` either, c.f. the ``ForwardMatchField`` branches of + # ``bytes(schema)`` either, see the ``ForwardMatchField`` branches of # :meth:`Schema.pack ` and # :meth:`Schema.unpack `. if isinstance(field, ForwardMatchField): @@ -371,7 +371,7 @@ def post_process(self, packet: 'dict[str, Any]') -> 'Schema': Raises: FieldValueError: If an entry of :attr:`ts_data` that the timestamp flag makes an address is a :obj:`bool`, is not a valid IP - address, or is not IPv4 -- c.f. + address, or is not IPv4 -- see :func:`~pcapkit.corekit.fields.ipaddress.parse_ip_address`. Notes: diff --git a/pcapkit/protocols/schema/internet/ipv6.py b/pcapkit/protocols/schema/internet/ipv6.py index 92d3a353a5..43f0179379 100644 --- a/pcapkit/protocols/schema/internet/ipv6.py +++ b/pcapkit/protocols/schema/internet/ipv6.py @@ -85,7 +85,7 @@ class IPv6(Schema): payload: 'bytes' = PayloadField(length=lambda pkt: pkt['length']) #: Octets captured past the Payload Length (or a jumbogram's Jumbo Payload #: Length, see :meth:`post_process`), such as Ethernet minimum-frame - #: padding, c.f. :attr:`IPv4.trailer `. + #: padding, see :attr:`IPv4.trailer `. trailer: 'bytes' = PayloadField(default=b'') if TYPE_CHECKING: @@ -167,7 +167,7 @@ def jumbogram_error(length: 'int', next: 'int', data: 'bytes', # pylint: disabl fragment: 'Optional[Callable[[], bool]]' = None) -> 'Optional[str]': """Name the error :rfc:`2675#section-3` has a receiver detect in an IPv6 packet, if any. - The four errors that section lists for a node that understands the Jumbo + The errors that section lists for a node that understands the Jumbo Payload option, each a packet the default engine rejects (:issue:`1687`): * a Payload Length of zero, a Next Header of Hop-by-Hop Options, and no diff --git a/pcapkit/protocols/schema/internet/ipv6_option.py b/pcapkit/protocols/schema/internet/ipv6_option.py index 9bb7f543d9..d1bd865e7c 100644 --- a/pcapkit/protocols/schema/internet/ipv6_option.py +++ b/pcapkit/protocols/schema/internet/ipv6_option.py @@ -240,7 +240,7 @@ def pad_opt_data_len(pkt: 'dict[str, Any]') -> 'int': Note: A ``Pad1`` option is a single octet with neither an ``Opt Data Len`` - field nor any option data (c.f. :rfc:`8200#section-4.2`), which is why + field nor any option data (see :rfc:`8200#section-4.2`), which is why the option's ``len`` field is declared as a :class:`~pcapkit.corekit.fields.misc.ConditionalField` and is skipped for it. A skipped conditional field is *recorded* in the packet data as diff --git a/pcapkit/protocols/schema/internet/ipv6_opts.py b/pcapkit/protocols/schema/internet/ipv6_opts.py index ebe33da85c..8fd7a104a7 100644 --- a/pcapkit/protocols/schema/internet/ipv6_opts.py +++ b/pcapkit/protocols/schema/internet/ipv6_opts.py @@ -442,17 +442,17 @@ def __init__(self, type: 'Enum_Option', len: 'int', hav: 'bytes') -> 'None': ... class PDMOption(Option, code=Enum_Option.PDM): """Header schema for IPv6-Opts performance and diagnostic metrics (PDM) options.""" - #: Scale delta time last received (DTLR). + #: Scale delta time last received (ScaleDTLR). scaledtlr: 'int' = UInt8Field() - #: Scale delta time last sent (DTLS). + #: Scale delta time last sent (ScaleDTLS). scaledtls: 'int' = UInt8Field() - #: Packet sequence number (PSN) this packet. + #: Packet sequence number (PSN) this packet (PSNTP). psntp: 'int' = UInt16Field() - #: Packet sequence number (PSN) last received. + #: Packet sequence number (PSN) last received (PSNLR). psnlr: 'int' = UInt16Field() - #: Delta time last received (DTLR). + #: Delta time last received (DeltaTLR). deltatlr: 'int' = UInt16Field() - #: Delta time last sent (DTLS). + #: Delta time last sent (DeltaTLS). deltatls: 'int' = UInt16Field() if TYPE_CHECKING: diff --git a/pcapkit/protocols/schema/internet/mh.py b/pcapkit/protocols/schema/internet/mh.py index ba825c8beb..fe6cd5e7b3 100644 --- a/pcapkit/protocols/schema/internet/mh.py +++ b/pcapkit/protocols/schema/internet/mh.py @@ -139,7 +139,7 @@ from typing_extensions import TypedDict class ANSIKeyLengthTest(TypedDict): - """Length test for ASN.1 encoded data, c.f., + """Length test for ASN.1 encoded data, see :attr:`CGAParameter.public_key_test`.""" len: int @@ -408,7 +408,7 @@ def pad_opt_data_len(pkt: 'dict[str, Any]') -> 'int': Note: A ``Pad1`` option is a single octet with neither an ``Option Length`` - field nor any option data (c.f. :rfc:`6275#section-6.2.2`), which is + field nor any option data (see :rfc:`6275#section-6.2.2`), which is why :attr:`Option.length` is declared as a :class:`~pcapkit.corekit.fields.misc.ConditionalField` and is skipped for it. A skipped conditional field is *recorded* in the packet data as @@ -826,9 +826,9 @@ def __init__(self, type: 'Enum_Option', length: 'int', subtype: 'Enum_AuthSubtyp class MesgIDOption(Option, code=Enum_Option.MESG_ID_OPTION_TYPE): """Header schema for Mobility Message Replay Protection options.""" - #: Timestamp (seconds since January 1st, 1900, c.f., :rfc:`1305`). + #: Timestamp (seconds since January 1st, 1900, see :rfc:`1305`). seconds: 'int' = UInt32Field() - #: Timestamp fractions (1/2**32 seconds per unit, c.f., :rfc:`1305`). + #: Timestamp fractions (1/2**32 seconds per unit, see :rfc:`1305`). fraction: 'int' = UInt32Field() def post_process(self, packet: 'dict[str, Any]') -> 'MesgIDOption': @@ -844,7 +844,7 @@ def post_process(self, packet: 'dict[str, Any]') -> 'MesgIDOption': self = super().post_process(packet) # convert timestamp to datetime - # c.f., http://tickelton.gitlab.io/articles/ntp-timestamps/ + # see http://tickelton.gitlab.io/articles/ntp-timestamps/ ts_sec = self.seconds - 2_208_988_800 # 70 years ts_frac = self.fraction / 2**32 # fraction of a second @@ -967,7 +967,7 @@ def __init__(self, modifier: 'Enum_CGAType', prefix: 'int', collision_count: 'in class CGAParametersOption(Option, code=Enum_Option.CGA_Parameters): """Header schema for CGA Parameters options.""" - #: CGA parameters, c.f., :rfc:`3972`. + #: CGA parameters, see :rfc:`3972`. parameters: 'list[CGAParameter]' = ListField( length=lambda pkt: pkt['length'], item_type=SchemaField(schema=CGAParameter), @@ -1071,7 +1071,7 @@ class IPv6AddressPrefixOption(Option, code=Enum_Option.Mobility_Header_IPv6_Addr """ - #: Option code, c.f., + #: Option code, see #: :class:`pcapkit.protocols.internet.mh.IPv6AddressPrefixCode`. code: 'int' = UInt8Field() #: Prefix length. @@ -1482,7 +1482,7 @@ class LMAAddressOption(Option, code=Enum_Option.Local_Mobility_Anchor_Address_Op """ - #: Option code, c.f., + #: Option code, see #: :class:`pcapkit.protocols.internet.mh.LMAAddressCode`. code: 'int' = UInt8Field() #: Reserved. @@ -2830,7 +2830,7 @@ class FastBindingAcknowledgmentMessage(Packet, code=Enum_Packet.Fast_Binding_Ack """ - #: Status, c.f., + #: Status, see #: :class:`pcapkit.protocols.internet.mh.FastBindingAcknowledgmentStatus`. status: 'int' = UInt8Field() #: Flags. @@ -3074,7 +3074,7 @@ class LocalizedRoutingAcknowledgmentMessage( """Header schema for MH Localized Routing Acknowledgment messages. Note: - :rfc:`6705#section-10.2` defines this message's three status values + :rfc:`6705#section-10.2` defines this message's status values inline and IANA keeps no registry for them -- they are neither in the general *Status Codes* registry nor in one of their own -- so their enumeration lives in @@ -3092,7 +3092,7 @@ class LocalizedRoutingAcknowledgmentMessage( 'U': (0, 1), 'reserved': (1, 7), }) - #: Status, c.f., + #: Status, see #: :class:`pcapkit.protocols.internet.mh.LocalizedRoutingStatus`. status: 'int' = UInt8Field() #: Lifetime, in seconds. From 7a01c86c05a7d070a9ca67e68d6930571e10b2c9 Mon Sep 17 00:00:00 2001 From: Jarry Shaw Date: Mon, 19 Oct 2026 01:05:24 -0400 Subject: [PATCH 2/2] docs(protocols): restore RFC spec counts (#1103) - jumbogram_error: restore "four errors", the count RFC 2675 section 3 lists for a node that understands the Jumbo Payload option. - LocalizedRoutingAcknowledgmentMessage: restore "three status values", the count RFC 6705 section 10.2 defines. - Spec quantities are exempt from the no-counted-numbers rule. --- pcapkit/protocols/schema/internet/ipv6.py | 2 +- pcapkit/protocols/schema/internet/mh.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pcapkit/protocols/schema/internet/ipv6.py b/pcapkit/protocols/schema/internet/ipv6.py index 43f0179379..da65275288 100644 --- a/pcapkit/protocols/schema/internet/ipv6.py +++ b/pcapkit/protocols/schema/internet/ipv6.py @@ -167,7 +167,7 @@ def jumbogram_error(length: 'int', next: 'int', data: 'bytes', # pylint: disabl fragment: 'Optional[Callable[[], bool]]' = None) -> 'Optional[str]': """Name the error :rfc:`2675#section-3` has a receiver detect in an IPv6 packet, if any. - The errors that section lists for a node that understands the Jumbo + The four errors that section lists for a node that understands the Jumbo Payload option, each a packet the default engine rejects (:issue:`1687`): * a Payload Length of zero, a Next Header of Hop-by-Hop Options, and no diff --git a/pcapkit/protocols/schema/internet/mh.py b/pcapkit/protocols/schema/internet/mh.py index fe6cd5e7b3..6fe6e74adb 100644 --- a/pcapkit/protocols/schema/internet/mh.py +++ b/pcapkit/protocols/schema/internet/mh.py @@ -3074,7 +3074,7 @@ class LocalizedRoutingAcknowledgmentMessage( """Header schema for MH Localized Routing Acknowledgment messages. Note: - :rfc:`6705#section-10.2` defines this message's status values + :rfc:`6705#section-10.2` defines this message's three status values inline and IANA keeps no registry for them -- they are neither in the general *Status Codes* registry nor in one of their own -- so their enumeration lives in