Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -158,22 +158,18 @@ carries the same extension-mode contract as its siblings.
inside the *encrypted* trailer, so with no key material there is nothing to continue
on: ESP's own data model reports ``next`` as :obj:`None`, and
:meth:`IPv6._decode_next_layer <pcapkit.protocols.internet.ipv6.IPv6._decode_next_layer>`
ends the ordinary way one iteration later. So ESP is absent from
:attr:`IPv6.__generic_ext_codes__ <pcapkit.protocols.internet.ipv6.IPv6.__generic_ext_codes__>`
-- not because it lacks a parser, which it has, but because it cannot hand the walk a
successor.
ends the ordinary way one iteration later -- not because ESP lacks a parser, which
it has, but because it cannot hand the walk a successor.

The full reasoning, including how ESP's terminal case differs from 253/254's, is
written where the code is and is deliberately not restated at length here: see the
``#:`` comment on
:attr:`IPv6.__generic_ext_codes__ <pcapkit.protocols.internet.ipv6.IPv6.__generic_ext_codes__>`
(:file:`pcapkit/protocols/internet/ipv6.py`) and the module docstring of
:mod:`pcapkit.protocols.internet.ipv6_ext`.
written where the code is and is deliberately not restated at length here: see
:meth:`IPv6._import_next_layer <pcapkit.protocols.internet.ipv6.IPv6._import_next_layer>`
and the module docstring of :mod:`pcapkit.protocols.internet.ipv6_ext`.

.. caution::

The two facts have to be kept apart when reading any of this. "ESP is not an
extension header" (wrong, and :rfc:`8200#section-4.5` quoted out of scope) is a
different claim from "ESP cannot be walked past" (right, and about
:rfc:`4303`'s wire format). Collapsing them is how ESP ends up either dropped
from the extension-header contract or wrongly added to the generic-dispatch set.
from the extension-header contract or wrongly walked past.
3 changes: 0 additions & 3 deletions docs/source/pcapkit/protocols/internet/ipv6.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@ Octets Bits Name Description

.. automethod:: __index__

.. autoattribute:: __generic_ext_codes__
:no-value:

.. automethod:: _read_ip_hextet

Protocol Constants
Expand Down
49 changes: 21 additions & 28 deletions docs/source/pcapkit/protocols/internet/ipv6_ext.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ unavailable on a header parsed as part of an IPv6 chain. Each subclass guards
its own ``protocol`` the same way; this class's
:attr:`~pcapkit.protocols.internet.ipv6_ext.IPv6_Ext.protocol` deliberately
does not. It also implements a
**generic** extractor for IPv6 extension headers [*]_, standing in whenever a
header's own dedicated parser is unavailable or has failed. :rfc:`6564#section-4`
**generic** extractor for IPv6 extension headers [*]_, for a header with no
dedicated parser. :rfc:`6564#section-4`
requires, with an RFC 2119 **MUST**, that any IPv6 extension header defined since
April 2012 carry the same first two octets:

Expand Down Expand Up @@ -123,32 +123,25 @@ carry a ``next`` at all?) rather than on a list of codes.
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 <pcapkit.protocols.protocol.Protocol._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 <pcapkit.protocols.internet.ipv6.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 <pcapkit.protocols.protocol.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 <pcapkit.protocols.internet.ipv6.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.
This class is reached by direct dispatch only.
: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 <pcapkit.protocols.protocol.Protocol._lookup_next_layer>`
would default it to plain :class:`~pcapkit.protocols.misc.raw.Raw`, whose
missing ``next`` field would end the walk in
:meth:`IPv6._decode_next_layer <pcapkit.protocols.internet.ipv6.IPv6._decode_next_layer>`
there (: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.

A header with a dedicated class whose parser raises does not reach this class.
:func:`~pcapkit.corekit.decorators.beholder` makes it plain
:class:`~pcapkit.protocols.misc.raw.Raw`, and the walk stops there, as
:rfc:`8200#section-4` has a node discard such a packet (:issue:`2477`).

.. _ipv6-ext-overrun-guard:

Expand Down
2 changes: 1 addition & 1 deletion pcapkit/protocols/data/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@
# IPv6 Fragment Header
'IPv6_Frag',

# IPv6 Extension Header (base + generic fallback)
# IPv6 Extension Header (base + generic)
'IPv6_Ext',

# IPv6 Destination Options Header
Expand Down
4 changes: 2 additions & 2 deletions pcapkit/protocols/data/internet/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@
# IPv6 Fragment Header
from pcapkit.protocols.data.internet.ipv6_frag import IPv6_Frag

# IPv6 Extension Header (generic fallback)
# IPv6 Extension Header (generic)
from pcapkit.protocols.data.internet.ipv6_ext import IPv6_Ext

# IPv6 Destination Options
Expand Down Expand Up @@ -427,7 +427,7 @@
# IPv6 Fragment Header
'IPv6_Frag',

# IPv6 Extension Header (generic fallback)
# IPv6 Extension Header (generic)
'IPv6_Ext',

# IPv6 Destination Options Header
Expand Down
3 changes: 1 addition & 2 deletions pcapkit/protocols/data/internet/ipv6.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@ class IPv6(Protocol):
#: Extension header chain, in wire order, as pairs of the parser
#: class and its info. The per-header keys hold the same infos, but in
#: the order of the keys of this :class:`~pcapkit.corekit.infoclass.Info`,
#: which differs on PyPy, so the chain is rebuilt from this alone; the
#: parser class keeps the IPv6_Ext a header fell back to
#: which differs on PyPy, so the chain is rebuilt from this alone
#: (:issue:`1473`, :issue:`2003`).
__exthdr__: 'tuple[tuple[Type[ProtocolBase], Data], ...]'

Expand Down
5 changes: 2 additions & 3 deletions pcapkit/protocols/data/internet/ipv6_ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ class IPv6_Ext(Protocol):
length: 'int'
#: Header-specific content after the two fixed octets, as consumed.
data: 'bytes'
#: Original parsing error, if this instance was reached as a
#: :func:`~pcapkit.corekit.decorators.beholder` fallback rather than by
#: direct dispatch.
#: Parsing error a caller passed to
#: :meth:`read <pcapkit.protocols.internet.ipv6_ext.IPv6_Ext.read>`, if any.
error: 'Optional[Exception]'
Loading
Loading