From ff98e9505fd1163c983f23dd6e88038c6847d99e Mon Sep 17 00:00:00 2001 From: Jarry Shaw Date: Thu, 15 Oct 2026 13:09:11 -0400 Subject: [PATCH] docs(protocols): second pass over the IPv6 extension headers (#1103) Reads the MH, HOPOPT, IPv6-Opts, IPv6-Route and ESP prose phase 1 left unread, with their schemas, data models and pages. - Data models: versionchanged on the 31 classes that gained a required field since 1.4.1.post2, each citing the issue the field came from. - HOPOPT/IPv6-Opts, IPv6-Route and MH class directives gain the missing #1235 reserved-bit, IP_DFF length and #1223 padding rows; MH's also cites #1329 for its reserved fields and flag bits. - MH dispatch note: Schema subclasses each have their own ABC cache (#439). - Drop four stale TODOs: every MH type, option and CGA extension has a handler. MH and ESP modules are not "MH/ESP only"; esp.rst drops an unchecked "unlike every other protocol"; MH's table names mh.reserved. - Field comments: lengths are octets, an option length includes its header, Type 2 holds one address; fix typos (router alter, cation, Retune, ANSI.1, LAA), two mislabelled data models, a from_dict link. AST guard: 16 .py files identical; tests/project and related tests pass. Refs #1103 --- .../source/pcapkit/protocols/internet/esp.rst | 3 +- docs/source/pcapkit/protocols/internet/mh.rst | 4 +- pcapkit/protocols/data/internet/ah.py | 10 +- pcapkit/protocols/data/internet/hopopt.py | 77 ++++++++++++--- pcapkit/protocols/data/internet/ipv6.py | 3 +- pcapkit/protocols/data/internet/ipv6_frag.py | 9 +- pcapkit/protocols/data/internet/ipv6_opts.py | 77 ++++++++++++--- pcapkit/protocols/data/internet/ipv6_route.py | 27 +++++- pcapkit/protocols/data/internet/mh.py | 96 +++++++++++++++---- pcapkit/protocols/internet/esp.py | 2 +- pcapkit/protocols/internet/hopopt.py | 5 + pcapkit/protocols/internet/ipv6_opts.py | 5 + pcapkit/protocols/internet/ipv6_route.py | 4 + pcapkit/protocols/internet/mh.py | 43 +++------ pcapkit/protocols/schema/internet/hopopt.py | 2 +- .../protocols/schema/internet/ipv6_opts.py | 2 +- .../protocols/schema/internet/ipv6_route.py | 2 +- pcapkit/protocols/schema/internet/mh.py | 10 +- 18 files changed, 278 insertions(+), 103 deletions(-) diff --git a/docs/source/pcapkit/protocols/internet/esp.rst b/docs/source/pcapkit/protocols/internet/esp.rst index 459765399a..733c69b0d6 100644 --- a/docs/source/pcapkit/protocols/internet/esp.rst +++ b/docs/source/pcapkit/protocols/internet/esp.rst @@ -21,8 +21,7 @@ Octets Bits Name Description ? ? ``esp.icv`` Integrity Check Value (ICV, variable) ======= ========= ===================== ============================================== -Unlike every other protocol in :mod:`pcapkit`, ESP is **not** self -describing. :rfc:`4303` places the ``Pad Length`` and ``Next Header`` +ESP is **not** self describing. :rfc:`4303` places the ``Pad Length`` and ``Next Header`` fields *inside* the ciphertext, and leaves the length of the ``Integrity Check Value`` to be determined by the Security Association (SA), which is negotiated out of band. Therefore: diff --git a/docs/source/pcapkit/protocols/internet/mh.rst b/docs/source/pcapkit/protocols/internet/mh.rst index a60c5b0603..514362dde7 100644 --- a/docs/source/pcapkit/protocols/internet/mh.rst +++ b/docs/source/pcapkit/protocols/internet/mh.rst @@ -4,7 +4,7 @@ MH - Mobility Header .. module:: pcapkit.protocols.internet.mh :mod:`pcapkit.protocols.internet.mh` contains -:class:`~pcapkit.protocols.internet.mh.MH` only, +:class:`~pcapkit.protocols.internet.mh.MH`, which implements extractor for Mobility Header (MH) [*]_, whose structure is described as below: @@ -14,7 +14,7 @@ Octets Bits Name Description 0 0 ``mh.next`` Next Header 1 8 ``mh.length`` Header Length 2 16 ``mh.type`` Mobility Header Type - 3 24 Reserved + 3 24 ``mh.reserved`` Reserved 4 32 ``mh.chksum`` Checksum 6 48 ``mh.data`` Message Data ======= ========= ================== =============================== diff --git a/pcapkit/protocols/data/internet/ah.py b/pcapkit/protocols/data/internet/ah.py index 54308cf1f0..ffc942d07f 100644 --- a/pcapkit/protocols/data/internet/ah.py +++ b/pcapkit/protocols/data/internet/ah.py @@ -14,11 +14,17 @@ @info_final class AH(Protocol): - """Data model for AH protocol.""" + """Data model for AH protocol. + + .. versionchanged:: 1.5.0 + + New required field ``reserved`` (:issue:`1327`). + + """ #: Next header. next: 'TransType' - #: Payload length. + #: Header length, in octets, decoded from the Payload Len field. length: 'int' #: Reserved. reserved: 'int' diff --git a/pcapkit/protocols/data/internet/hopopt.py b/pcapkit/protocols/data/internet/hopopt.py index 4cf1e529f1..0066952d08 100644 --- a/pcapkit/protocols/data/internet/hopopt.py +++ b/pcapkit/protocols/data/internet/hopopt.py @@ -43,11 +43,11 @@ class Option(Data): #: Option type. type: 'Enum_Option' - #: Unknown option cation. + #: Unknown option action. action: 'OptionAction' #: Change flag. change: 'bool' - #: Content length. + #: Option length (incl. type and length fields). length: 'int' @@ -57,7 +57,7 @@ class HOPOPT(Protocol): #: Next header. next: 'TransType' - #: Header extension length. + #: Header length, in octets, decoded from ``Hdr Ext Len``. length: 'int' #: HOPOPT options. options: 'OrderedMultiInfo[Enum_Option, Option]' @@ -79,7 +79,13 @@ def __init__(self, type: 'Enum_Option', action: 'int', change: 'bool', length: ' @info_final class PadOption(Option): - """Data model for HOPOPT padding options.""" + """Data model for HOPOPT padding options. + + .. versionchanged:: 1.5.0 + + New required field ``pad`` (:issue:`1223`). + + """ #: Padding octets, i.e. the ``PadN`` option data as captured (empty for #: a ``Pad1``). @@ -102,9 +108,9 @@ def __init__(self, type: 'Enum_Option', action: 'int', change: 'bool', length: ' @info_final class RouterAlertOption(Option): - """Data model for HOPOPT router alter option.""" + """Data model for HOPOPT router alert option.""" - #: Router alter value. + #: Router alert value. value: 'RouterAlert' if TYPE_CHECKING: @@ -113,7 +119,13 @@ def __init__(self, type: 'Enum_Option', action: 'int', change: 'bool', length: ' @info_final class CALIPSOOption(Option): - """Data model for HOPOPT Common Architecture Label IPv6 Security Option (CALIPSO) option.""" + """Data model for HOPOPT Common Architecture Label IPv6 Security Option (CALIPSO) option. + + .. versionchanged:: 1.5.0 + + New required field ``pad`` (:issue:`1403`). + + """ #: CALIPSO domain of interpretation. domain: 'int' @@ -200,7 +212,13 @@ class QuickStartOption(Option): @info_final class QuickStartRequestOption(QuickStartOption): - """Data model for HOPOPT Quick Start request option.""" + """Data model for HOPOPT Quick Start request option. + + .. versionchanged:: 1.5.0 + + New required field ``reserved`` (:issue:`1235`). + + """ #: TTL. ttl: 'timedelta' @@ -216,7 +234,14 @@ def __init__(self, type: 'Enum_Option', action: 'int', change: 'bool', length: ' @info_final class QuickStartReportOption(QuickStartOption): - """Data model for HOPOPT Quick Start report of approved rate option.""" + """Data model for HOPOPT Quick Start report of approved rate option. + + .. versionchanged:: 1.5.0 + + New required fields ``reserved`` (:issue:`1235`) and ``unused`` + (:issue:`1223`). + + """ #: Nonce. nonce: 'int' @@ -231,7 +256,13 @@ def __init__(self, type: 'Enum_Option', action: 'int', change: 'bool', length: ' @info_final class RPLFlags(Data): - """Data model for HOPOPT RPL option flags fields.""" + """Data model for HOPOPT RPL option flags fields. + + .. versionchanged:: 1.5.0 + + New required field ``reserved`` (:issue:`1199`). + + """ #: Down flag. down: 'bool' @@ -248,7 +279,13 @@ def __init__(self, down: 'bool', rank_err: 'bool', fwd_err: 'bool', reserved: 'i @info_final class RPLOption(Option): - """Data model for HOPOPT Routing Protocol for Low-Power and Lossy Networks (RPL) option.""" + """Data model for HOPOPT Routing Protocol for Low-Power and Lossy Networks (RPL) option. + + .. versionchanged:: 1.5.0 + + New required field ``sub_tlvs`` (:issue:`1199`). + + """ #: Flags. flags: 'RPLFlags' @@ -265,11 +302,17 @@ def __init__(self, type: 'Enum_Option', action: 'int', change: 'bool', length: ' @info_final class MPLFlags(Data): - """Data model for HOPOPT MPL option flags fields.""" + """Data model for HOPOPT MPL option flags fields. + + .. versionchanged:: 1.5.0 + + New required field ``reserved`` (:issue:`1235`). + + """ #: Max flag. max: 'bool' - #: Non-conformation flag. + #: Non-conformance flag. drop: 'bool' #: Reserved bits (``rsv``). reserved: 'int' @@ -344,7 +387,13 @@ def __init__(self, type: 'Enum_Option', action: 'int', change: 'bool', length: ' @info_final class DFFFlags(Data): - """Data model for HOPOPT ``IP_DFF`` option flags.""" + """Data model for HOPOPT ``IP_DFF`` option flags. + + .. versionchanged:: 1.5.0 + + New required field ``reserved`` (:issue:`1235`). + + """ #: Duplicate flag. dup: 'bool' diff --git a/pcapkit/protocols/data/internet/ipv6.py b/pcapkit/protocols/data/internet/ipv6.py index 3c7062b9fe..4181e9e13b 100644 --- a/pcapkit/protocols/data/internet/ipv6.py +++ b/pcapkit/protocols/data/internet/ipv6.py @@ -27,7 +27,8 @@ class IPv6(Protocol): """Data model for Internet Protocol version 6. Important: - Due to the reserved keyword conflict, please use :meth:`from_dict` + Due to the reserved keyword conflict, please use + :meth:`~pcapkit.corekit.infoclass.Info.from_dict` to create an instance of this data model. """ diff --git a/pcapkit/protocols/data/internet/ipv6_frag.py b/pcapkit/protocols/data/internet/ipv6_frag.py index 8004280458..8a1826fb9e 100644 --- a/pcapkit/protocols/data/internet/ipv6_frag.py +++ b/pcapkit/protocols/data/internet/ipv6_frag.py @@ -14,7 +14,14 @@ @info_final class IPv6_Frag(Protocol): - """Data model for IPv6 fragment header.""" + """Data model for IPv6 fragment header. + + .. versionchanged:: 1.5.0 + + New required fields ``reserved_octet`` (:issue:`1223`) and ``reserved`` + (:issue:`1235`). + + """ #: Next header. next: 'TransType' diff --git a/pcapkit/protocols/data/internet/ipv6_opts.py b/pcapkit/protocols/data/internet/ipv6_opts.py index 126a9ee5ea..1e42ee5024 100644 --- a/pcapkit/protocols/data/internet/ipv6_opts.py +++ b/pcapkit/protocols/data/internet/ipv6_opts.py @@ -43,11 +43,11 @@ class Option(Data): #: Option type. type: 'Enum_Option' - #: Unknown option cation. + #: Unknown option action. action: 'OptionAction' #: Change flag. change: 'bool' - #: Content length. + #: Option length (incl. type and length fields). length: 'int' @@ -57,7 +57,7 @@ class IPv6_Opts(Protocol): #: Next header. next: 'TransType' - #: Header extension length. + #: Header length, in octets, decoded from ``Hdr Ext Len``. length: 'int' #: IPv6-Opts options. options: 'OrderedMultiInfo[Enum_Option, Option]' @@ -81,7 +81,13 @@ def __init__(self, type: 'Enum_Option', action: 'int', change: 'bool', length: ' @info_final class PadOption(Option): - """Data model for IPv6-Opts padding options.""" + """Data model for IPv6-Opts padding options. + + .. versionchanged:: 1.5.0 + + New required field ``pad`` (:issue:`1223`). + + """ #: Padding octets, i.e. the ``PadN`` option data as captured (empty for #: a ``Pad1``). @@ -106,9 +112,9 @@ def __init__(self, type: 'Enum_Option', action: 'int', change: 'bool', length: ' @info_final class RouterAlertOption(Option): - """Data model for IPv6-Opts router alter option.""" + """Data model for IPv6-Opts router alert option.""" - #: Router alter value. + #: Router alert value. value: 'RouterAlert' if TYPE_CHECKING: @@ -118,7 +124,13 @@ def __init__(self, type: 'Enum_Option', action: 'int', change: 'bool', length: ' @info_final class CALIPSOOption(Option): - """Data model for IPv6-Opts Common Architecture Label IPv6 Security Option (CALIPSO) option.""" + """Data model for IPv6-Opts Common Architecture Label IPv6 Security Option (CALIPSO) option. + + .. versionchanged:: 1.5.0 + + New required field ``pad`` (:issue:`1403`). + + """ #: CALIPSO domain of interpretation. domain: 'int' @@ -209,7 +221,13 @@ class QuickStartOption(Option): @info_final class QuickStartRequestOption(QuickStartOption): - """Data model for IPv6-Opts Quick Start request option.""" + """Data model for IPv6-Opts Quick Start request option. + + .. versionchanged:: 1.5.0 + + New required field ``reserved`` (:issue:`1235`). + + """ #: TTL. ttl: 'timedelta' @@ -225,7 +243,14 @@ def __init__(self, type: 'Enum_Option', action: 'int', change: 'bool', length: ' @info_final class QuickStartReportOption(QuickStartOption): - """Data model for IPv6-Opts Quick Start report of approved rate option.""" + """Data model for IPv6-Opts Quick Start report of approved rate option. + + .. versionchanged:: 1.5.0 + + New required fields ``reserved`` (:issue:`1235`) and ``unused`` + (:issue:`1223`). + + """ #: Nonce. nonce: 'int' @@ -241,7 +266,13 @@ def __init__(self, type: 'Enum_Option', action: 'int', change: 'bool', length: ' @info_final class RPLFlags(Data): - """Data model for IPv6-Opts RPL option flags fields.""" + """Data model for IPv6-Opts RPL option flags fields. + + .. versionchanged:: 1.5.0 + + New required field ``reserved`` (:issue:`1199`). + + """ #: Down flag. down: 'bool' @@ -259,7 +290,13 @@ def __init__(self, down: 'bool', rank_err: 'bool', @info_final class RPLOption(Option): - """Data model for IPv6-Opts Routing Protocol for Low-Power and Lossy Networks (RPL) option.""" + """Data model for IPv6-Opts Routing Protocol for Low-Power and Lossy Networks (RPL) option. + + .. versionchanged:: 1.5.0 + + New required field ``sub_tlvs`` (:issue:`1199`). + + """ #: Flags. flags: 'RPLFlags' @@ -277,11 +314,17 @@ def __init__(self, type: 'Enum_Option', action: 'int', change: 'bool', length: ' @info_final class MPLFlags(Data): - """Data model for IPv6-Opts MPL option flags fields.""" + """Data model for IPv6-Opts MPL option flags fields. + + .. versionchanged:: 1.5.0 + + New required field ``reserved`` (:issue:`1235`). + + """ #: Max flag. max: 'bool' - #: Non-conformation flag. + #: Non-conformance flag. drop: 'bool' #: Reserved bits (``rsv``). reserved: 'int' @@ -360,7 +403,13 @@ def __init__(self, type: 'Enum_Option', action: 'int', change: 'bool', length: ' @info_final class DFFFlags(Data): - """Data model for IPv6-Opts ``IP_DFF`` option flags.""" + """Data model for IPv6-Opts ``IP_DFF`` option flags. + + .. versionchanged:: 1.5.0 + + New required field ``reserved`` (:issue:`1235`). + + """ #: Duplicate flag. dup: 'bool' diff --git a/pcapkit/protocols/data/internet/ipv6_route.py b/pcapkit/protocols/data/internet/ipv6_route.py index a172c5d7ed..5c173b514e 100644 --- a/pcapkit/protocols/data/internet/ipv6_route.py +++ b/pcapkit/protocols/data/internet/ipv6_route.py @@ -24,7 +24,7 @@ class IPv6_Route(Protocol): #: Next header. next: 'TransType' - #: Header extension length. + #: Header length, in octets, decoded from ``Hdr Ext Len``. length: 'int' #: Routing type. type: 'Routing' @@ -46,7 +46,13 @@ def __init__(self, next: 'TransType', length: 'int', type: 'Routing', seg_left: @info_final class SourceRoute(IPv6_Route): - """Data model for IPv6-Route Source Route data type.""" + """Data model for IPv6-Route Source Route data type. + + .. versionchanged:: 1.5.0 + + New required field ``reserved`` (:issue:`1223`). + + """ #: The four reserved octets, as captured. reserved: 'bytes' @@ -60,7 +66,13 @@ def __init__(self, next: 'TransType', length: 'int', type: 'Routing', seg_left: @info_final class Type2(IPv6_Route): - """Data model for IPv6-Route Type 2 data type.""" + """Data model for IPv6-Route Type 2 data type. + + .. versionchanged:: 1.5.0 + + New required field ``reserved`` (:issue:`1223`). + + """ #: The four reserved octets, as captured. reserved: 'bytes' @@ -74,7 +86,14 @@ def __init__(self, next: 'TransType', length: 'int', type: 'Routing', seg_left: @info_final class RPL(IPv6_Route): - """Data model for RPL Source data type.""" + """Data model for RPL Source data type. + + .. versionchanged:: 1.5.0 + + New required fields ``reserved`` (:issue:`1235`) and ``padding`` + (:issue:`1223`). + + """ #: CmprI. cmpr_i: 'int' diff --git a/pcapkit/protocols/data/internet/mh.py b/pcapkit/protocols/data/internet/mh.py index 70ca468086..f02376659d 100644 --- a/pcapkit/protocols/data/internet/mh.py +++ b/pcapkit/protocols/data/internet/mh.py @@ -138,7 +138,14 @@ class MH(Protocol): - """Data model for MH protocol.""" + """Data model for MH protocol. + + .. versionchanged:: 1.5.0 + + New required field ``reserved``, which every message data model + inherits (:issue:`1329`). + + """ #: Next header. next: 'TransType' @@ -165,7 +172,13 @@ def __init__(self, next: 'TransType', length: 'int', type: 'Packet', reserved: ' @info_final class BindingRefreshRequestMessage(MH): - """Data model for MH Binding Refresh Request (BRR) message type.""" + """Data model for MH Binding Refresh Request (BRR) message type. + + .. versionchanged:: 1.5.0 + + New required field ``msg_reserved`` (:issue:`1329`). + + """ #: Reserved field of the message body, before the mobility options. Named #: apart from :attr:`MH.reserved`, the reserved octet of the fixed header. @@ -180,7 +193,13 @@ def __init__(self, next: 'TransType', length: 'int', type: 'Packet', reserved: ' @info_final class HomeTestInitMessage(MH): - """Data model for MH Home Test Init (HoTI) message type.""" + """Data model for MH Home Test Init (HoTI) message type. + + .. versionchanged:: 1.5.0 + + New required field ``msg_reserved`` (:issue:`1437`). + + """ #: The two reserved octets of the message body, as captured. Named apart #: from :attr:`MH.reserved`, the reserved octet of the fixed header. @@ -198,7 +217,13 @@ def __init__(self, next: 'TransType', length: 'int', type: 'Packet', reserved: ' @info_final class CareofTestInitMessage(MH): - """Data model for MH Care-of Test Init (CoTI) message type.""" + """Data model for MH Care-of Test Init (CoTI) message type. + + .. versionchanged:: 1.5.0 + + New required field ``msg_reserved`` (:issue:`1437`). + + """ #: The two reserved octets of the message body, as captured. Named apart #: from :attr:`MH.reserved`, the reserved octet of the fixed header. @@ -254,13 +279,20 @@ def __init__(self, next: 'TransType', length: 'int', type: 'Packet', reserved: ' @info_final class BindingUpdateMessage(MH): - """Data model for MH Binding Update message type.""" + """Data model for MH Binding Update message type. + + .. versionchanged:: 1.5.0 + + New required fields for the flag bits later RFCs assign, ``map_reg`` + through ``dmm``, and ``flags_reserved`` for the rest (:issue:`1329`). + + """ #: Sequence number. seq: 'int' #: Acknowledge flag. ack: 'bool' - #: home registration flag. + #: Home registration flag. home: 'bool' #: Link-local address compatibility flag. lla_compat: 'bool' @@ -300,7 +332,15 @@ def __init__(self, next: 'TransType', length: 'int', type: 'Packet', reserved: ' @info_final class BindingAcknowledgementMessage(MH): - """Data model for MH Binding Acknowledge (BA) message type.""" + """Data model for MH Binding Acknowledge (BA) message type. + + .. versionchanged:: 1.5.0 + + New required fields for the flag bits later RFCs assign, + ``mobile_router`` through ``dmm``, and ``flags_reserved`` for the rest + (:issue:`1329`). + + """ #: Status. status: 'Enum_StatusCode' @@ -337,7 +377,13 @@ def __init__(self, next: 'TransType', length: 'int', type: 'Packet', reserved: ' @info_final class BindingErrorMessage(MH): - """Data model for MH Binding Error (BE) message type.""" + """Data model for MH Binding Error (BE) message type. + + .. versionchanged:: 1.5.0 + + New required field ``msg_reserved`` (:issue:`1437`). + + """ #: Status. status: 'Enum_BindingError' @@ -736,9 +782,6 @@ def __init__(self, next: 'TransType', length: 'int', type: 'Packet', reserved: ' options: 'OrderedMultiDict[Enum_Option, Option]') -> 'None': ... -# TODO: Implement other message types. - - class Option(Data): """Data model for MH options.""" @@ -761,7 +804,13 @@ def __init__(self, type: 'Enum_Option', length: 'int', data: 'bytes') -> 'None': @info_final class PadOption(Option): - """Data model for Pad option.""" + """Data model for Pad option. + + .. versionchanged:: 1.5.0 + + New required field ``data`` (:issue:`1223`). + + """ #: Padding octets, i.e. the ``PadN`` option data as captured (empty for a #: ``Pad1``). @@ -820,7 +869,13 @@ def __init__(self, type: 'Enum_Option', length: 'int', data: 'bytes') -> 'None': @info_final class MobileNetworkPrefixOption(Option): - """Data model for Mobile Network Prefix option.""" + """Data model for Mobile Network Prefix option. + + .. versionchanged:: 1.5.0 + + New required field ``reserved`` (:issue:`1437`). + + """ #: The reserved octet, as captured. reserved: 'bytes' @@ -931,7 +986,13 @@ def __init__(self, type: 'Enum_CGAExtension', length: 'int', data: 'bytes') -> ' @info_final class MultiPrefixExtension(CGAExtension): - """Data model for Multi-Prefix CGA extension.""" + """Data model for Multi-Prefix CGA extension. + + .. versionchanged:: 1.5.0 + + New required field ``reserved`` (:issue:`1418`). + + """ #: P flag. Set if a public key is included in the Public Key field of #: the CGA Parameter Data Structure, reset otherwise. @@ -1001,7 +1062,7 @@ def __init__(self, type: 'Enum_Option', length: 'int', token: 'bytes') -> 'None' @info_final class CareofTestInitOption(Option): - """Header schema for MH Care-of Test Init options.""" + """Data model for MH Care-of Test Init option.""" if TYPE_CHECKING: def __init__(self, type: 'Enum_Option', length: 'int') -> 'None': ... @@ -1009,7 +1070,7 @@ def __init__(self, type: 'Enum_Option', length: 'int') -> 'None': ... @info_final class CareofTestOption(Option): - """Header schema for MH Care-of Test options.""" + """Data model for MH Care-of Test option.""" #: Care-of keygen token. token: 'bytes' @@ -2258,6 +2319,3 @@ class DLIFLinkLayerAddressOption(Option): if TYPE_CHECKING: def __init__(self, type: 'Enum_Option', length: 'int', reserved: 'bytes', lla: 'bytes') -> 'None': ... - - -# TODO: Implement other options. diff --git a/pcapkit/protocols/internet/esp.py b/pcapkit/protocols/internet/esp.py index d2ad231400..6aca80e43b 100644 --- a/pcapkit/protocols/internet/esp.py +++ b/pcapkit/protocols/internet/esp.py @@ -5,7 +5,7 @@ .. module:: pcapkit.protocols.internet.esp :mod:`pcapkit.protocols.internet.esp` contains -:class:`~pcapkit.protocols.internet.esp.ESP` only, +:class:`~pcapkit.protocols.internet.esp.ESP`, which implements extractor for Encapsulating Security Payload (ESP) [*]_, whose structure is described as below: diff --git a/pcapkit/protocols/internet/hopopt.py b/pcapkit/protocols/internet/hopopt.py index c3e72f5953..34ba7e6abf 100644 --- a/pcapkit/protocols/internet/hopopt.py +++ b/pcapkit/protocols/internet/hopopt.py @@ -196,6 +196,11 @@ class HOPOPT(IPv6_Ext[Data_HOPOPT, Schema_HOPOPT], :issue:`1228`, :issue:`1229`, :issue:`1232` to :issue:`1234`, :issue:`1237`); a CALIPSO option keeps its trailing pad and its length (:issue:`1403`). + * The MPL, ``IP_DFF`` and Quick-Start options keep their reserved bits + on rebuild, and ``IP_DFF`` takes the ``Opt Data Len`` of ``3`` that + :rfc:`6971` Errata ID 3937 gives, where it took ``2`` (:issue:`1235`). + * A PadN option's data and the "Not Used" octet of a Quick-Start report + are kept as captured rather than zeroed (:issue:`1223`). """ diff --git a/pcapkit/protocols/internet/ipv6_opts.py b/pcapkit/protocols/internet/ipv6_opts.py index 303bc4e0a5..16cea5cd66 100644 --- a/pcapkit/protocols/internet/ipv6_opts.py +++ b/pcapkit/protocols/internet/ipv6_opts.py @@ -200,6 +200,11 @@ class IPv6_Opts(IPv6_Ext[Data_IPv6_Opts, Schema_IPv6_Opts], :issue:`1228`, :issue:`1229`, :issue:`1232` to :issue:`1234`, :issue:`1237`); a CALIPSO option keeps its trailing pad and its length (:issue:`1403`). + * The MPL, ``IP_DFF`` and Quick-Start options keep their reserved bits + on rebuild, and ``IP_DFF`` takes the ``Opt Data Len`` of ``3`` that + :rfc:`6971` Errata ID 3937 gives, where it took ``2`` (:issue:`1235`). + * A PadN option's data and the "Not Used" octet of a Quick-Start report + are kept as captured rather than zeroed (:issue:`1223`). """ diff --git a/pcapkit/protocols/internet/ipv6_route.py b/pcapkit/protocols/internet/ipv6_route.py index e71f7c08f7..27492d240f 100644 --- a/pcapkit/protocols/internet/ipv6_route.py +++ b/pcapkit/protocols/internet/ipv6_route.py @@ -104,6 +104,10 @@ class IPv6_Route(IPv6_Ext[Data_IPv6_Route, Schema_IPv6_Route], (:issue:`1236`), and an RPL source route rebuilds byte for byte, its address compression and a truncated address list included (:issue:`1456`, :issue:`1457`). + * A rebuild keeps the reserved bits of an RPL source route + (:issue:`1235`), and the reserved octets of a Source Route or Type 2 + header and the ``Pad`` octets of an RPL one as captured + (:issue:`1223`). """ diff --git a/pcapkit/protocols/internet/mh.py b/pcapkit/protocols/internet/mh.py index b072583b39..65cbebda48 100644 --- a/pcapkit/protocols/internet/mh.py +++ b/pcapkit/protocols/internet/mh.py @@ -3,7 +3,7 @@ """Mobility Header :mod:`pcapkit.protocols.internet.mh` contains -:class:`~pcapkit.protocols.internet.mh.MH` only, +:class:`~pcapkit.protocols.internet.mh.MH`, which implements extractor for Mobility Header (MH) [*]_, whose structure is described as below: @@ -13,7 +13,7 @@ 0 0 ``mh.next`` Next Header 1 8 ``mh.length`` Header Length 2 16 ``mh.type`` Mobility Header Type - 3 24 Reserved + 3 24 ``mh.reserved`` Reserved 4 32 ``mh.chksum`` Checksum 6 48 ``mh.data`` Message Data ======= ========= ================== =============================== @@ -1159,7 +1159,8 @@ class MH(IPv6_Ext[Data_MH, Schema_MH], :rfc:`5568` (:issue:`493`). * A rebuild keeps a PadN with no data, the reserved fields, the reserved bits of the flag fields and the octets each padding field captured - (:issue:`1324`, :issue:`1418`, :issue:`1437`). + (:issue:`1223`, :issue:`1324`, :issue:`1329`, :issue:`1418`, + :issue:`1437`). """ @@ -4829,35 +4830,13 @@ def _read_fid_suboptions( :attr:`self.__option__ `. Note: - Dispatch is on the sub-option **type code**, never on ``isinstance`` of - the schema class, and that is load-bearing rather than a matter of - taste. Every schema class descends from - :class:`collections.abc.Mapping`, and on Python 3.10 and older they do - **not** each get their own ``_abc_impl`` -- they share - :class:`~pcapkit.protocols.schema.schema.Schema`'s. One - :class:`abc.ABCMeta` cache therefore serves the whole family, and it is - keyed only on the class being *tested*, not on the class being tested - *against*. So one ``issubclass`` answer poisons every later question - about the same class: - - .. code-block:: python - - >>> issubclass(ANIGeoLocationSuboption, Schema) # True, cached - True - >>> issubclass(ANIGeoLocationSuboption, ANINetworkIdentifierSuboption) - True # wrong -- the cached True for Schema is handed back - - The wrong answer goes both ways: a correct ``False`` against a sibling - then makes ``isinstance(sub, Schema)`` ``False``, which is what - :meth:`ListField.pack - ` consults, so - packing a perfectly good option fails with - :exc:`~pcapkit.utilities.exceptions.FieldValueError`. Python 3.11 and - newer give each class its own cache, so the checks behave there. - - The code is on the wire and the registry keys on it, so it is both the - cheaper discriminator and the only one that cannot be poisoned. The - same reasoning applies to :meth:`_read_ani_suboptions`, + Dispatch is on the sub-option **type code** rather than on + ``isinstance`` of the schema class: the code is on the wire and the + registry keys on it, so it is the cheaper discriminator. A class test + would also be sound, since every + :class:`~pcapkit.protocols.schema.schema.Schema` subclass carries its + own :class:`abc.ABCMeta` cache (:issue:`439`). The same reasoning + applies to :meth:`_read_ani_suboptions`, :meth:`_read_qos_attributes`, :meth:`_read_lcmp_suboptions` and their four constructor counterparts. diff --git a/pcapkit/protocols/schema/internet/hopopt.py b/pcapkit/protocols/schema/internet/hopopt.py index 613e51ac9d..ee822d9c42 100644 --- a/pcapkit/protocols/schema/internet/hopopt.py +++ b/pcapkit/protocols/schema/internet/hopopt.py @@ -99,7 +99,7 @@ class DFFFlags(TypedDict): ver: int #: Duplicate flag. dup: int - #: Retune flag. + #: Return flag. ret: int #: Reserved bits. reserved: int diff --git a/pcapkit/protocols/schema/internet/ipv6_opts.py b/pcapkit/protocols/schema/internet/ipv6_opts.py index 44256ad0f0..b62e6b088d 100644 --- a/pcapkit/protocols/schema/internet/ipv6_opts.py +++ b/pcapkit/protocols/schema/internet/ipv6_opts.py @@ -99,7 +99,7 @@ class DFFFlags(TypedDict): ver: int #: Duplicate flag. dup: int - #: Retune flag. + #: Return flag. ret: int #: Reserved bits. reserved: int diff --git a/pcapkit/protocols/schema/internet/ipv6_route.py b/pcapkit/protocols/schema/internet/ipv6_route.py index b7a08c717e..d399f68c65 100644 --- a/pcapkit/protocols/schema/internet/ipv6_route.py +++ b/pcapkit/protocols/schema/internet/ipv6_route.py @@ -177,7 +177,7 @@ class Type2(RoutingType, code=Enum_Routing.Type_2_Routing_Header): #: Reserved. reserved: 'bytes' = PaddingField(length=4) - #: Addresses. + #: Home address. ip: 'IPv6Address' = IPv6AddressField() if TYPE_CHECKING: diff --git a/pcapkit/protocols/schema/internet/mh.py b/pcapkit/protocols/schema/internet/mh.py index 9791374803..f809e15443 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 ANSI.1 encoded data, c.f., + """Length test for ASN.1 encoded data, c.f., :attr:`CGAParameter.public_key_test`.""" len: int @@ -745,7 +745,7 @@ class LinkLayerAddressOption(Option, code=Enum_Option.Mobility_Header_Link_Layer #: Option code. code: 'Enum_LLACode' = EnumField(length=1, namespace=Enum_LLACode) - #: Link-layer address (LAA). + #: Link-layer address (LLA). lla: 'bytes' = BytesField(length=lambda pkt: pkt['length'] - 1) if TYPE_CHECKING: @@ -2526,9 +2526,6 @@ class DLIFLinkLayerAddressOption(Option, code=Enum_Option.DLIF_Link_Layer_Addres def __init__(self, type: 'Enum_Option', length: 'int', reserved: 'bytes', lla: 'bytes') -> 'None': ... -# TODO: Implement other options. - - class Packet(EnumSchema[Enum_Packet]): """Header schema for MH packet data.""" @@ -3234,6 +3231,3 @@ class SubscriptionResponseMessage(Packet, code=Enum_Packet.Subscription_Response if TYPE_CHECKING: def __init__(self, seq: 'int', flags: 'SubscriptionResponseMessageFlags', options: 'list[Option | bytes]') -> 'None': ... - - -# TODO: Implement other message types.