Skip to content

fix(net): reject IPv4-compatible addresses in is_advertisable_ipv6 (#1955) - #144

Merged
MichaelTaylor3d merged 1 commit into
mainfrom
fix/1955-ipv4-compat-fold
Aug 2, 2026
Merged

fix(net): reject IPv4-compatible addresses in is_advertisable_ipv6 (#1955)#144
MichaelTaylor3d merged 1 commit into
mainfrom
fix/1955-ipv4-compat-fold

Conversation

@MichaelTaylor3d

Copy link
Copy Markdown
Contributor

What changed

Closes DIG-Network/dig_ecosystem#1955.

is_advertisable_ipv6 (crates/dig-node-core/src/seams/dig_peer/net.rs) decides whether an Ipv6Addr is a global-unicast address worth advertising to peers. It folded out IPv4-mapped addresses (::ffff:a.b.c.d) via to_ipv4_mapped().is_some(), but missed the IPv4-compatible form (::a.b.c.d, the ::/96 block). An IPv4-compatible address is an IPv4 address in disguise — not a dialable global IPv6 — so advertising it as a routable IPv6 candidate is wrong (§5.2 IPv6-first: IPv4-in-any-form must not masquerade as a global IPv6 peer address).

Fix: ip.to_ipv4_mapped().is_some()ip.to_ipv4().is_some(). to_ipv4() returns Some for both the mapped and the compatible forms, so both are now rejected. :: (unspecified) and ::1 (loopback) remain caught by the earlier is_unspecified()/is_loopback() checks in the same expression, so the change adds only the compatible-form rejection — it never over-rejects a genuine global address (to_ipv4() returns None for e.g. 2001:db8::1). The doc comment is updated to say "not an IPv4-mapped OR IPv4-compatible address".

Verification

  • ipv4_compatible_is_not_advertisable::1.2.3.4 (::0102:0304) → false (RED under to_ipv4_mapped, GREEN after the fix).
  • ipv4_mapped_is_still_not_advertisable::ffff:1.2.3.4false (regression guard).
  • a_real_global_unicast_ipv6_is_advertisable2001:db8::1true (no over-rejection).
  • gitnexus impact: leaf predicate, LOW risk (callers: local_ipv6_addradvertised_socket_addrs).
  • cargo fmt --all -- --check → 0 · cargo clippy -p dig-node-core --all-targets --all-features -- -D warnings → 0 · cargo test -p dig-node-core green (the only failure being the known env-limited dual_stack port-bind test, #1961).

Version

fix: (correctness — a more-restrictive address filter; no public-API/behaviour break for legitimate addresses) → [workspace.package].version 0.75.2 → 0.75.3. Cargo.lock updated + committed.


Generated by Claude Code

IPv6 addresses derived from IPv4 (both IPv4-mapped ::ffff:a.b.c.d and
IPv4-compatible ::a.b.c.d forms) are not routable global addresses and
must not be advertised as peer candidates. Previously only the mapped
form was filtered; now both forms are rejected via to_ipv4().is_some(),
which matches both the ::/96 IPv4-compatible block and the
::ffff:0:0/96 IPv4-mapped block.

Adds three unit tests: IPv4-compatible rejection, regression guard for
IPv4-mapped, and guard against over-rejecting real global addresses.

Fixes #1955.

Co-Authored-By: Claude <noreply@anthropic.com>
@MichaelTaylor3d
MichaelTaylor3d merged commit 14fe374 into main Aug 2, 2026
15 checks passed
@MichaelTaylor3d
MichaelTaylor3d deleted the fix/1955-ipv4-compat-fold branch August 2, 2026 14:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant