Skip to content

Detect embedded IPv4 in non-canonical 6to4 addresses#110

Merged
zanbaldwin merged 2 commits into
6.xfrom
z/derived
Jun 8, 2026
Merged

Detect embedded IPv4 in non-canonical 6to4 addresses#110
zanbaldwin merged 2 commits into
6.xfrom
z/derived

Conversation

@zanbaldwin

Copy link
Copy Markdown
Member

Derived::isEmbedded() only matched canonical 6to4 addresses with the trailing 80 bits zeroed, even though every address within 2002::/16 carries an IPv4 address in bits 16-47, as per RFC 3056. Widen detection to the whole 6to4 block; extraction keeps only the embedded IPv4 address, so an extract-pack round-trip reconstructs the canonical form (2002:XXXX:XXXX::) rather than the original.

@zanbaldwin zanbaldwin self-assigned this Jun 5, 2026
@greptile-apps

greptile-apps Bot commented Jun 5, 2026

Copy link
Copy Markdown

Greptile Summary

This PR widens the Derived strategy's isEmbedded() detection to the full 2002::/16 6to4 block (RFC 3056 § 2), instead of only matching canonical addresses with the trailing 80 bits zeroed. Extraction already returned bits 16–47 correctly; only the detection predicate and documentation needed updating.

  • src/Strategy/Derived.php: Removes the trailing-zeros guard from isEmbedded(), adds a PHPDoc class comment clarifying the detection scope, and documents the non-round-trip warning on pack().
  • Tests: Adds getNonCanonicalSequences() data provider and three new test methods confirming that non-canonical 6to4 addresses are detected, correctly extracted, and canonicalised by an extract-then-pack round-trip.
  • CHANGELOG.md / docs/: Updated to reflect the widened detection and the new ???? notation for variable SLA ID/interface-ID bits.

Confidence Score: 5/5

Safe to merge — the change is a targeted, RFC-correct expansion of a detection predicate with no impact on extraction or packing logic.

The only changed logic is the removal of the trailing-zeros guard in isEmbedded(). The extract() and pack() methods are untouched in behaviour. The PR correctly documents the intentional non-round-trip for non-canonical inputs, covers both new branches with dedicated test cases, and updates all relevant data providers. The darsyn/ip-doctrine consumer uses the default Mapped strategy and is unaffected.

No files require special attention.

Important Files Changed

Filename Overview
src/Strategy/Derived.php Core fix: removes the trailing-zeros guard from isEmbedded(), matching all of 2002::/16 per RFC 3056. extract() and pack() are unchanged in logic; inline docs added to explain the non-canonical round-trip behaviour.
tests/Strategy/DerivedTest.php Adds three new test methods for non-canonical 6to4 addresses: detection, extraction, and canonicalisation via extract-then-pack. Both legacy annotation and PHPUnit Attribute styles are present, consistent with the rest of the test file.
tests/DataProvider/Strategy/Derived.php Adds getNonCanonicalSequences() with two cases: non-zero SLA ID with zeroed interface ID, and zeroed SLA ID with non-zero interface ID. Byte offsets and expected outputs are correct per RFC 3056 § 2.
tests/DataProvider/IPv6.php Adds 2002:7f00:1:1::1 (non-canonical 6to4 with non-zero SLA ID) to the integration data provider, flagged as DERIVED
src/Strategy/Compatible.php Documentation-only change: adds a PHPDoc class comment referencing RFC 4291 § 2.5.5.1. No logic changes.
src/Strategy/Mapped.php Documentation-only change: adds a PHPDoc class comment referencing RFC 4291 § 2.5.5.2. No logic changes.
CHANGELOG.md Adds a bugfix entry for the widened 6to4 detection under the current unreleased section.
docs/05-strategies.md Updates the format column for the 6to4-derived strategy from zeroed trailing bits to ?-wildcards, accurately reflecting non-canonical detection.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[16-byte binary input] --> B{Starts with 0x2002?}
    B -- No --> C[isEmbedded: false]
    B -- Yes --> D[isEmbedded: true]

    D --> E[extract: bytes 2-5 IPv4 address]
    D --> F[pack IPv4 to 6to4: 2002 + IPv4 + 10x0x00 canonical form]

    E --> G{Was input canonical? bytes 6-15 = 0?}
    G -- Yes --> H[pack·extract = identity round-trip preserved]
    G -- No --> I[pack·extract to canonical form SLA ID + interface ID zeroed not original address]

    style C fill:#f88,stroke:#c00
    style D fill:#8f8,stroke:#090
    style I fill:#ffa,stroke:#880
Loading

Reviews (2): Last reviewed commit: "test(providers): 🚨 add non-canonical de..." | Re-trigger Greptile

@zanbaldwin zanbaldwin added the enhancement Existing feature enhancement (patch version bump) label Jun 7, 2026
`Derived::isEmbedded()` only matched canonical 6to4 addresses with the trailing 80 bits zeroed, even though every address within `2002::/16` carries an IPv4 address in bits 16-47, as per RFC 3056.
Widen detection to the whole 6to4 block; extraction keeps only the embedded IPv4 address, so an extract-pack round-trip reconstructs the canonical form (`2002:XXXX:XXXX::`) rather than the original.
@zanbaldwin zanbaldwin merged commit 9536d80 into 6.x Jun 8, 2026
24 checks passed
@zanbaldwin zanbaldwin deleted the z/derived branch June 8, 2026 10:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Existing feature enhancement (patch version bump)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant