Skip to content

feat: Windows IPv6 traceroute (Icmp6SendEcho2)#50

Merged
dweekly merged 4 commits into
mainfrom
feat/ipv6-windows
Jul 18, 2026
Merged

feat: Windows IPv6 traceroute (Icmp6SendEcho2)#50
dweekly merged 4 commits into
mainfrom
feat/ipv6-windows

Conversation

@dweekly

@dweekly dweekly commented Jul 18, 2026

Copy link
Copy Markdown
Owner

Windows was the last platform without IPv6 traceroute after v0.9.0. This PR closes that gap with the IP Helper Icmp6CreateFile/Icmp6SendEcho2/Icmp6ParseReplies API, mirroring the proven v4 WindowsAsyncIcmpSocket design (event handle per probe, spawn_blocking waiter, and the Tokio-vs-Windows timeout-buffer logic from docs/WINDOWS_ASYNC_FINDINGS.md). No elevation required, same as v4. -6 now works on every supported platform.

Spike-first validation (live, before implementation)

examples/spike_windows_v6.rs (permanent in-repo diagnostic) ran in a Windows 11 ARM64 VM with native IPv6 (Sonic fiber, bridged) and confirmed every hypothesis from docs/IPV6_DESIGN.md, now recorded there as a "Validated findings (Windows)" section:

  • The required source SOCKADDR_IN6 accepts the unspecified :: with AF_INET6 — the stack picks the source; no interface enumeration/GetBestInterfaceEx needed
  • IP_OPTION_INFORMATION.Ttl sets the hop limit; expired probes return Status = IP_HOP_LIMIT_EXCEEDED (11013) with the router's address
  • ICMPV6_ECHO_REPLY_LH layout verified by hex dump: 36 bytes, packed 26-byte IPV6_ADDRESS_EX (address [u16;8] words in network byte order at byte 6), Status at 28, RoundTripTime at 32, echoed request payload at 36 for Echo Replies only (Time Exceeded doesn't echo — same asymmetry as v4)
  • Timeout: event still signals; Icmp6ParseReplies returns 0 with GetLastError() = IP_REQ_TIMED_OUT (11010)

Live results from the VM

ftr -6 -v google.com (abridged):

Using Windows ICMPv6 API mode for traceroute
 1 [LAN   ] 2001:5a8:4681:2c00::1 6.586 ms [AS46375 - AS-SONICTELECOM - Sonic Telecom LLC, US]
 2 [ISP   ] 2001:5a8:657:21::f1:4 6.553 ms [AS46375 ...]
 4 [ISP   ] ae5.cr3.colaca01.sonic.net (2001:5a8:5:403f::e3:b) 3.000 ms [AS46375 ...]
13 [ISP   ] 100.ae1.nrd1.equinix-sj.sonic.net (2001:5a8:5:403f::8a:a) 3.000 ms [AS46375 ...]
14 [DESTINATION] 2001:4860:1:1::3ab6 2.000 ms [AS15169 - GOOGLE - Google LLC, US]
17 [DESTINATION] sfo07s17-in-x0e.1e100.net (2607:f8b0:4005:80a::200e) 3.000 ms [AS15169 ...]

Detected public IP: 2001:5a8:4681:2c00:404:f2c5:dda2:1d1d
Detected ISP: AS46375 (AS-SONICTELECOM - Sonic Telecom LLC)
Destination ASN: AS15169 (GOOGLE - Google LLC, US)

Also verified in the VM: ftr -6 ::1 loopback, ftr 8.8.8.8 v4 regression trace, and the full lib test suite (231 passed, including the 8 new windows_v6 reply-parse unit tests against synthetic spike-verified buffers).

Implementation notes

  • src/socket/windows_v6.rs: new socket; replies go through Icmp6ParseReplies per the async API contract (0 parsed replies maps to a timeout response); echo-reply id/seq verification uses the payload echoed at offset 36; read_unaligned for the reply struct (Vec buffers have 1-byte alignment)
  • src/socket/factory.rs: Windows V6 arm dispatches to the new socket; explicit UDP protocol preference returns typed NotImplemented (consistent with macOS/BSD)
  • Additive API only: reuses ProbeMode::WindowsIcmp — no new public enum variants
  • CI note: GitHub's Windows runners can't receive ICMP (Azure blocks it), so live behavior there degrades to compile + unit tests, matching the existing v4 pattern

Lint debt payoff

cargo clippy --target x86_64-pc-windows-msvc --all-targets carried ~16 dead-code warnings invisible to CI (whose clippy job runs on Ubuntu): unused v4 raw-ICMP codec helpers on Windows, spike RFC constants under stub mains, and an unused new_with_config constructor. All resolved — the windows-msvc target is now clean under -D warnings. The durable fix is adding a windows-target clippy cross-check to CI (tracked in the improvement plan); this PR clears the baseline for it.

🤖 Generated with Claude Code

dweekly and others added 3 commits July 17, 2026 17:03
Add examples/spike_windows_v6.rs, run in a Windows 11 ARM64 VM with
native IPv6, and record the findings in docs/IPV6_DESIGN.md (replacing
the Windows entry in the open-questions list):

- The required source SOCKADDR_IN6 accepts the unspecified address (::)
  with AF_INET6 — the stack picks the source, no enumeration needed
- IP_OPTION_INFORMATION.Ttl caps the hop limit; expired probes return
  Status IP_HOP_LIMIT_EXCEEDED (11013) with the router address
- ICMPV6_ECHO_REPLY_LH layout confirmed (36 bytes; packed 26-byte
  IPV6_ADDRESS_EX at 0 with network-order [u16;8] words at byte 6,
  Status at 28, RoundTripTime at 32, echoed payload at 36 for Echo
  Replies only — Time Exceeded does not echo, same asymmetry as v4)
- Timeout: the event still signals; Icmp6ParseReplies returns 0 with
  GetLastError = IP_REQ_TIMED_OUT (11010)

The spike stays in-repo as a permanent diagnostic per project policy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add src/socket/windows_v6.rs mirroring the v4 WindowsAsyncIcmpSocket:
event-based Icmp6CreateFile/Icmp6SendEcho2/Icmp6ParseReplies with a
spawn_blocking waiter, the same Tokio-vs-Windows timeout-buffer logic
(WINDOWS_ICMP_* constants in config/timing.rs), and the same pending-
handle Drop optimization. Unspecified :: source (spike-validated), no
elevation required. Echo-reply id/seq verification uses the payload
echoed at offset 36; replies parse through Icmp6ParseReplies per the
async API contract, with 0 replies mapped to a timeout response.

Dispatch the Windows V6 factory arm to the new socket (UDP protocol
preference returns a typed NotImplemented, as on macOS/BSD), reuse
ProbeMode::WindowsIcmp (no new enum variant — additive-only API), and
compile the platform-neutral icmpv6 codec for its unit tests only on
Windows, since the Win32 API parses replies itself.

Unit tests cover the spike-verified reply layout: hop-limit-exceeded,
destination echo, zero-RTT fallback, foreign-identifier rejection,
timeout status, short buffers, and word byte order — all 8 pass in the
Windows 11 VM alongside the rest of the lib suite (231 tests), and a
live 17-hop ftr -6 google.com trace with full enrichment plus a v4
regression trace both succeed there.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
cargo clippy --target x86_64-pc-windows-msvc --all-targets was carrying
~16 dead-code warnings invisible to CI (whose clippy job runs on
Ubuntu): the v4 raw-ICMP codec helpers in src/socket/icmp.rs are unused
on Windows (allow dead_code there — the Win32 API parses replies), the
v6 spikes' RFC constants are unreferenced when only the stub main
compiles (file-level cfg_attr allow), and windows.rs kept an unused
new_with_config constructor (removed; the verbose variant is the only
caller path). The windows-msvc target now passes clippy --all-targets
with -D warnings; adding that cross-target check to CI is the durable
fix and is noted in the PR.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@codecov

codecov Bot commented Jul 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 84.31%. Comparing base (9eae243) to head (a640bb8).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main      #50      +/-   ##
==========================================
- Coverage   84.45%   84.31%   -0.14%     
==========================================
  Files          36       36              
  Lines        6663     6663              
==========================================
- Hits         5627     5618       -9     
- Misses       1036     1045       +9     
Flag Coverage Δ
unittests 84.31% <ø> (-0.14%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/socket/factory.rs 61.53% <ø> (ø)
src/socket/mod.rs 89.13% <ø> (ø)

... and 1 file with indirect coverage changes


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 9eae243...a640bb8. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

test_ipv6_target_platform_behavior and test_error_types still listed
Windows in their Ipv6NotSupported fallback arms; with Icmp6SendEcho2
support landed, a ::1 trace now succeeds unprivileged there (verified
in the Windows 11 VM before pushing — both suites green). Move Windows
into the unprivileged-success arm alongside macOS and Linux.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@dweekly
dweekly merged commit 1c49563 into main Jul 18, 2026
16 checks passed
@dweekly
dweekly deleted the feat/ipv6-windows branch July 18, 2026 00:19
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