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:
@@ -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