diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index 0a0b2280d..1f9f7e8b2 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -4968,7 +4968,7 @@ func (b *LocalBackend) authReconfig() { return } - oneCGNATRoute := shouldUseOneCGNATRoute(b.logf, b.sys.ControlKnobs(), version.OS()) + oneCGNATRoute := shouldUseOneCGNATRoute(b.logf, b.sys.NetMon.Get(), b.sys.ControlKnobs(), version.OS()) rcfg := b.routerConfig(cfg, prefs, oneCGNATRoute) err = b.e.Reconfig(cfg, rcfg, dcfg) @@ -4992,7 +4992,7 @@ func (b *LocalBackend) authReconfig() { // // The versionOS is a Tailscale-style version ("iOS", "macOS") and not // a runtime.GOOS. -func shouldUseOneCGNATRoute(logf logger.Logf, controlKnobs *controlknobs.Knobs, versionOS string) bool { +func shouldUseOneCGNATRoute(logf logger.Logf, mon *netmon.Monitor, controlKnobs *controlknobs.Knobs, versionOS string) bool { if controlKnobs != nil { // Explicit enabling or disabling always take precedence. if v, ok := controlKnobs.OneCGNAT.Load().Get(); ok { @@ -5007,7 +5007,7 @@ func shouldUseOneCGNATRoute(logf logger.Logf, controlKnobs *controlknobs.Knobs, // use fine-grained routes if another interfaces is also using the CGNAT // IP range. if versionOS == "macOS" { - hasCGNATInterface, err := netmon.HasCGNATInterface() + hasCGNATInterface, err := mon.HasCGNATInterface() if err != nil { logf("shouldUseOneCGNATRoute: Could not determine if any interfaces use CGNAT: %v", err) return false diff --git a/ipn/ipnlocal/peerapi.go b/ipn/ipnlocal/peerapi.go index ab2093c13..f20ea7524 100644 --- a/ipn/ipnlocal/peerapi.go +++ b/ipn/ipnlocal/peerapi.go @@ -481,7 +481,7 @@ func (h *peerAPIHandler) handleServeInterfaces(w http.ResponseWriter, r *http.Re fmt.Fprintf(w, "
There is another interface using the CGNAT range.
") } else if err != nil { fmt.Fprintf(w, "Could not check for CGNAT interfaces: %s
\n", html.EscapeString(err.Error())) diff --git a/net/netmon/interfaces_test.go b/net/netmon/interfaces_test.go index 5fec274ca..e4274819f 100644 --- a/net/netmon/interfaces_test.go +++ b/net/netmon/interfaces_test.go @@ -13,7 +13,7 @@ import ( ) func TestGetState(t *testing.T) { - st, err := getState() + st, err := getState("") if err != nil { t.Fatal(err) } diff --git a/net/netmon/netmon.go b/net/netmon/netmon.go index b58356d33..bd62ab270 100644 --- a/net/netmon/netmon.go +++ b/net/netmon/netmon.go @@ -161,7 +161,7 @@ func (m *Monitor) InterfaceState() *State { } func (m *Monitor) interfaceStateUncached() (*State, error) { - return getState() + return getState(m.tsIfName) } // SetTailscaleInterfaceName sets the name of the Tailscale interface. For diff --git a/net/netmon/state.go b/net/netmon/state.go index b6a6b2ab8..bd0960768 100644 --- a/net/netmon/state.go +++ b/net/netmon/state.go @@ -461,21 +461,22 @@ func isTailscaleInterface(name string, ips []netip.Prefix) bool { // getPAC, if non-nil, returns the current PAC file URL. var getPAC func() string -// GetState returns the state of all the current machine's network interfaces. +// getState returns the state of all the current machine's network interfaces. // // It does not set the returned State.IsExpensive. The caller can populate that. // -// Deprecated: use netmon.Monitor.InterfaceState instead. -func getState() (*State, error) { +// optTSInterfaceName is the name of the Tailscale interface, if known. +func getState(optTSInterfaceName string) (*State, error) { s := &State{ InterfaceIPs: make(map[string][]netip.Prefix), Interface: make(map[string]Interface), } if err := ForeachInterface(func(ni Interface, pfxs []netip.Prefix) { + isTSInterfaceName := optTSInterfaceName != "" && ni.Name == optTSInterfaceName ifUp := ni.IsUp() s.Interface[ni.Name] = ni s.InterfaceIPs[ni.Name] = append(s.InterfaceIPs[ni.Name], pfxs...) - if !ifUp || isTailscaleInterface(ni.Name, pfxs) { + if !ifUp || isTSInterfaceName || isTailscaleInterface(ni.Name, pfxs) { return } for _, pfx := range pfxs { @@ -755,11 +756,12 @@ func DefaultRoute() (DefaultRouteDetails, error) { // HasCGNATInterface reports whether there are any non-Tailscale interfaces that // use a CGNAT IP range. -func HasCGNATInterface() (bool, error) { +func (m *Monitor) HasCGNATInterface() (bool, error) { hasCGNATInterface := false cgnatRange := tsaddr.CGNATRange() err := ForeachInterface(func(i Interface, pfxs []netip.Prefix) { - if hasCGNATInterface || !i.IsUp() || isTailscaleInterface(i.Name, pfxs) { + isTSInterfaceName := m.tsIfName != "" && i.Name == m.tsIfName + if hasCGNATInterface || !i.IsUp() || isTSInterfaceName || isTailscaleInterface(i.Name, pfxs) { return } for _, pfx := range pfxs {