Fix GetLanIPv4 to skip Tailscale/VPN/APIPA addresses
Some checks failed
CI / build-and-test (push) Failing after 26s
Some checks failed
CI / build-and-test (push) Failing after 26s
On a Windows host with both Ethernet (10.0.0.123) and Tailscale (169.254.83.107 link-local), the original first-hit-wins picker returned the Tailscale address — useless for the headless-host + thin-client scenario the LAN-reachable mode is designed for. New picker prefers physical NICs (Ethernet/GigabitEthernet/Wireless80211), skips Tunnel-typed virtuals, and ranks: physical-routable > virtual-routable > APIPA. Verified against this host: now returns 10.0.0.123 instead of 169.254.83.107.
This commit is contained in:
parent
6d9407a61f
commit
d9eb02a9af
1 changed files with 27 additions and 6 deletions
|
|
@ -349,25 +349,46 @@ public sealed class GlobalSettingsViewModel : ObservableObject
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Best-effort first IPv4 address that isn't loopback. Returns null if
|
||||
/// no LAN interface is up. The first hit is good enough for the URL —
|
||||
/// operators with multi-NIC setups can manually substitute.
|
||||
/// Best-effort routable IPv4 address suitable for showing the operator a
|
||||
/// "paste me into the thin client" URL. Skips:
|
||||
/// • loopback interfaces (127.x)
|
||||
/// • tunnel/virtual interfaces (NetworkInterfaceType.Tunnel — e.g. WSL,
|
||||
/// Hyper-V, Tailscale, OpenVPN-style virtuals)
|
||||
/// • APIPA/link-local addresses (169.254.x — assigned when DHCP fails;
|
||||
/// a host with one of these AND a real DHCP lease should pick the lease)
|
||||
/// Prefers Ethernet/Wi-Fi over everything else, then falls back to the
|
||||
/// first non-link-local non-loopback IPv4. Returns null only if no
|
||||
/// usable address exists at all.
|
||||
/// </summary>
|
||||
private static string? GetLanIPv4()
|
||||
{
|
||||
try
|
||||
{
|
||||
string? linkLocalFallback = null;
|
||||
string? otherFallback = null;
|
||||
foreach (var ni in System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces())
|
||||
{
|
||||
if (ni.OperationalStatus != System.Net.NetworkInformation.OperationalStatus.Up) continue;
|
||||
if (ni.NetworkInterfaceType == System.Net.NetworkInformation.NetworkInterfaceType.Loopback) continue;
|
||||
if (ni.NetworkInterfaceType == System.Net.NetworkInformation.NetworkInterfaceType.Tunnel) continue;
|
||||
var isPhysical =
|
||||
ni.NetworkInterfaceType == System.Net.NetworkInformation.NetworkInterfaceType.Ethernet ||
|
||||
ni.NetworkInterfaceType == System.Net.NetworkInformation.NetworkInterfaceType.GigabitEthernet ||
|
||||
ni.NetworkInterfaceType == System.Net.NetworkInformation.NetworkInterfaceType.Wireless80211;
|
||||
|
||||
foreach (var ua in ni.GetIPProperties().UnicastAddresses)
|
||||
{
|
||||
if (ua.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork
|
||||
&& !System.Net.IPAddress.IsLoopback(ua.Address))
|
||||
return ua.Address.ToString();
|
||||
if (ua.Address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork) continue;
|
||||
if (System.Net.IPAddress.IsLoopback(ua.Address)) continue;
|
||||
var addr = ua.Address.ToString();
|
||||
var isLinkLocal = addr.StartsWith("169.254.", StringComparison.Ordinal);
|
||||
|
||||
if (isPhysical && !isLinkLocal) return addr; // best
|
||||
if (!isLinkLocal) otherFallback ??= addr; // routable but virtual NIC
|
||||
if (isLinkLocal) linkLocalFallback ??= addr; // worst
|
||||
}
|
||||
}
|
||||
return otherFallback ?? linkLocalFallback;
|
||||
}
|
||||
catch { /* best-effort */ }
|
||||
return null;
|
||||
|
|
|
|||
Loading…
Reference in a new issue