Skip to content

fix(ipv6): parse unrecognised extension headers generically so the chain survives #891

Description

@JarryShaw

Describe the bug

When an IPv6 extension header fails to parse, @beholder substitutes a Raw — but IPv6's own chain-walk then reads .next off it, which Raw does not carry:

ipv6.py:329   info = next_.info      # next_ is whatever _import_next_layer returned
ipv6.py:338   proto = info.next      # AttributeError when next_ is the Raw fallback

The consequence is not confined to the extension header. The AttributeError escapes IPv6.read before IPv6's own info is returned, so the @beholder one level up turns the whole IPv6 packet into Raw — source, destination, hop limit and flow label lost along with the extension header.

Reproduction

Measured on main at 21b121c0e, and on PR #889's head, with PYTHONSAFEPATH=1 and pcapkit.__file__ asserted to the tree under test. A well-formed Mobility Header (an IPv6 extension header — Mobility_Header = 135 is in pcapkit/const/ipv6/extension_header.py:42) whose status byte is unassigned:

Ethernet/IPv6  assigned status   -> payload=IPv6 protochain=Ethernet:IPv6:MH
Ethernet/IPv6  unassigned status -> payload=Raw  protochain=Ethernet:Internet_Protocol_version_6
IPv6 alone     unassigned status -> AttributeError: 'Raw' object has no attribute 'next'

Note both IPv6 and MH are absent from the degraded protochain.

It is not specific to that enum. On unmodified main, two unrelated MH failure modes raise the identical AttributeError: a truncated MH (6 bytes) and an absurd Header Len of 0xff. So any extension-header parse failure reaches it.

Expected behavior

A failed extension header degrades to Raw in place, leaving the IPv6 header's own parsed fields intact and the rest of the chain walked as far as it can be — which is what @beholder exists to provide. At minimum the walk should stop cleanly on a Raw rather than raising AttributeError, since Raw is a value _import_next_layer is documented to return.

System information

  • Python 3.14.7, CPython, checkout at 21b121c0e.

Additional context

Surfaced while reviewing #889, which stops four mh.py helper enums from minting on an unassigned byte. #889 does not introduce this — it makes it far more reachable, turning a malformed-packet-only path into one a well-formed packet with an unrecognised status byte takes. It is out of scope there and #889 documents the real cost instead.

This also corrects a claim I made on #877 when recommending those enums raise: I said the cost was one MH message's parse. On the IPv6 path it is the whole IPv6 packet. See issues/877 for the correction.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    breakingBreaks public-facing behaviour or API (apply alongside the type label)bugIssues reporting a defect (set by the bug report template; a default, not an assessment)fixPull requests that fix a defect (fix: subject prefix)

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions