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
6 changes: 3 additions & 3 deletions pcapkit/protocols/internet/ipv6_ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -584,8 +584,8 @@ def __post_init__(self, file: 'Optional[IO[bytes] | bytes]' = None, length: 'Opt
:class:`~pcapkit.protocols.internet.ah.AH` and
:class:`~pcapkit.protocols.internet.esp.ESP` both default to
``version=4`` and are valid under IPv4, so an unconditional gate
would reject them (``ProtocolError: ESP: only valid for IPv6, got
version=4``).
would reject them (``ProtocolError: ESP: invalid version: must be
6, not 4``).

The gate exists because this class is registered into
:attr:`Internet.__proto__
Expand All @@ -608,7 +608,7 @@ def __post_init__(self, file: 'Optional[IO[bytes] | bytes]' = None, length: 'Opt
"""
if self.__data__ is Data_IPv6_Ext and version != 6:
raise ProtocolError(
f'{self.__class__.__name__}: only valid for IPv6, got version={version}')
f'{self.__class__.__name__}: invalid version: must be 6, not {version!r}')

#: bool: If the protocol is used as an IPv6 extension header.
self._extf = extension
Expand Down
25 changes: 25 additions & 0 deletions tests/protocols/internet/test_ipv6_ext_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,31 @@ def test_version_gate_rejects_non_ipv6_construction(self) -> None:
IPv6_Ext(io.BytesIO(raw), len(raw), version=4, extension=True,
alias=int(ExtensionHeader.HOPOPT))

def test_version_gate_message_is_in_the_house_form(self) -> None:
"""GitHub issue #2302: the gate said ``only valid for IPv6, got
version=4``, which carries the prefix but not the
``<prefix>: <lowercase description>: ... <value>`` tail #2232 and
#2257 gave the rest of the library, and never named the version it
wanted. Both the issue's own bare-bytes call and the stream form are
pinned whole, since the two reach the gate by different routes.
"""
from pcapkit.const.ipv6.extension_header import ExtensionHeader
from pcapkit.const.reg.transtype import TransType
from pcapkit.protocols.internet.ipv6_ext import IPv6_Ext
from pcapkit.utilities.exceptions import ProtocolError

expected = 'IPv6_Ext: invalid version: must be 6, not 4'

with self.assertRaises(ProtocolError) as context:
IPv6_Ext(b'\x06\x00\x00\x00\x00\x00\x00\x00', version=4)
self.assertEqual(str(context.exception), expected)

raw = bytes([int(TransType.UDP), 1]) + b'\x00' * 14
with self.assertRaises(ProtocolError) as context:
IPv6_Ext(io.BytesIO(raw), len(raw), version=4, extension=True,
alias=int(ExtensionHeader.HOPOPT))
self.assertEqual(str(context.exception), expected)

def test_shim6_registration_does_not_leak_into_ipv4_parsing(self) -> None:
"""GitHub issue #891: registering ``IPv6_Ext``
into the shared ``Internet.__proto__`` for Shim6 must not make an
Expand Down
Loading