diff --git a/pcapkit/protocols/internet/ipv6_ext.py b/pcapkit/protocols/internet/ipv6_ext.py index 5cb5145a0..a79ed722a 100644 --- a/pcapkit/protocols/internet/ipv6_ext.py +++ b/pcapkit/protocols/internet/ipv6_ext.py @@ -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__ @@ -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 diff --git a/tests/protocols/internet/test_ipv6_ext_unit.py b/tests/protocols/internet/test_ipv6_ext_unit.py index 88fa52398..dfc46f1ba 100644 --- a/tests/protocols/internet/test_ipv6_ext_unit.py +++ b/tests/protocols/internet/test_ipv6_ext_unit.py @@ -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 + ``: : ... `` 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