fix(client): prefer non-link-local TAP IPv4 diagnostics
Windows can report more than one unicast address on the TAP adapter. If an APIPA address remains present next to the real LAN DHCP address, choosing the first IPv4 address can make diagnostics warn about 169.254.x.x even though the adapter already has a usable LAN address. Prefer a non-link-local IPv4 address for TAP diagnostics, then fall back to any IPv4 address, then to the first non-IPv4 address. This keeps the existing APIPA warning when APIPA is the only IPv4 signal, but reports the real DHCP address when Windows exposes both addresses. README.md and TESTING.md now document that diagnostics prefer the real LAN IPv4 when several TAP addresses are visible. Test Plan: - cargo test -p lanparty-client-win - cargo test --workspace - cargo clippy --workspace --all-targets -- -D warnings - cargo fmt --check - git diff --check Refs: PLAN.md client diagnostics; TESTING.md TAP IP verification
This commit is contained in:
@@ -259,8 +259,9 @@ It prints and reports client diagnostics snapshots with relay reachability,
|
||||
LAN-gateway presence, route-pinning, QUIC datagram budget, relay RTT, TAP
|
||||
status/IP, broadcast frame flow, frame/datagram counters, and drops. The
|
||||
periodic diagnostics refresh the TAP unicast IP so DHCP results that arrive
|
||||
after bridging starts become visible in later status lines. Each snapshot also
|
||||
emits short user-facing lines such as relay/gateway connection status,
|
||||
after bridging starts become visible in later status lines, preferring a
|
||||
non-link-local IPv4 address when Windows reports several TAP addresses. Each
|
||||
snapshot also emits short user-facing lines such as relay/gateway connection status,
|
||||
relay-route and TAP readiness warnings, DHCP address presence, relay RTT, and
|
||||
broadcast-flow confirmation when those signals are observed. Malformed frames
|
||||
read from TAP, invalid or unauthorized source-MAC frames, L2 control-plane
|
||||
|
||||
@@ -138,6 +138,9 @@ line should show:
|
||||
DHCP received: 10.x.x.x
|
||||
```
|
||||
|
||||
If Windows reports both a `169.254.x.x` TAP address and a real LAN IPv4
|
||||
address, the client diagnostics should prefer the real LAN address.
|
||||
|
||||
## What To Verify
|
||||
|
||||
1. Relay sees both peers:
|
||||
|
||||
@@ -856,11 +856,23 @@ fn tap_unicast_ip(identity: NetworkInterfaceIdentity) -> Option<IpAddr> {
|
||||
fn preferred_tap_ip(
|
||||
addresses: &[lanparty_client_route::InterfaceUnicastAddress],
|
||||
) -> Option<IpAddr> {
|
||||
preferred_tap_ip_address(addresses.iter().map(|address| address.address()))
|
||||
}
|
||||
|
||||
#[cfg_attr(not(windows), allow(dead_code))]
|
||||
fn preferred_tap_ip_address(addresses: impl IntoIterator<Item = IpAddr>) -> Option<IpAddr> {
|
||||
let addresses: Vec<_> = addresses.into_iter().collect();
|
||||
addresses
|
||||
.iter()
|
||||
.find(|address| matches!(address.address(), IpAddr::V4(_)))
|
||||
.or_else(|| addresses.first())
|
||||
.map(|address| address.address())
|
||||
.copied()
|
||||
.find(|address| matches!(address, IpAddr::V4(ip) if !ip.is_link_local()))
|
||||
.or_else(|| {
|
||||
addresses
|
||||
.iter()
|
||||
.copied()
|
||||
.find(|address| matches!(address, IpAddr::V4(_)))
|
||||
})
|
||||
.or_else(|| addresses.first().copied())
|
||||
}
|
||||
|
||||
#[cfg_attr(not(windows), allow(dead_code))]
|
||||
@@ -1180,6 +1192,30 @@ mod tests {
|
||||
assert_eq!(refreshed.ip().unwrap().to_string(), "10.73.42.51");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn prefers_non_link_local_tap_ipv4_for_diagnostics() {
|
||||
assert_eq!(
|
||||
preferred_tap_ip_address([
|
||||
"169.254.10.20".parse().unwrap(),
|
||||
"10.73.42.51".parse().unwrap(),
|
||||
"fe80::1".parse().unwrap(),
|
||||
]),
|
||||
Some("10.73.42.51".parse().unwrap())
|
||||
);
|
||||
assert_eq!(
|
||||
preferred_tap_ip_address([
|
||||
"169.254.10.20".parse().unwrap(),
|
||||
"fe80::1".parse().unwrap()
|
||||
]),
|
||||
Some("169.254.10.20".parse().unwrap())
|
||||
);
|
||||
assert_eq!(
|
||||
preferred_tap_ip_address(["fe80::1".parse().unwrap()]),
|
||||
Some("fe80::1".parse().unwrap())
|
||||
);
|
||||
assert_eq!(preferred_tap_ip_address([]), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn formats_tap_default_route_warning() {
|
||||
assert_eq!(
|
||||
|
||||
Reference in New Issue
Block a user