From 1191c7ced2b855305b9d6e1e38ec7e664c7e2bbf Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Sat, 22 Mar 2025 16:15:14 -0700 Subject: [PATCH] more plan9 fixes, to be cleaned up and merged separately later Change-Id: I4c89609d7eb83bbe208aa87025365427d961b048 Signed-off-by: Brad Fitzpatrick --- net/dns/manager_default.go | 2 +- net/dns/manager_plan9.go | 79 +++++++++++++++++++++++++++++++++++ net/netmon/interfaces_test.go | 2 +- net/netmon/netmon.go | 6 +-- net/netmon/state.go | 8 +++- net/tsdial/tsdial.go | 2 +- 6 files changed, 91 insertions(+), 8 deletions(-) create mode 100644 net/dns/manager_plan9.go diff --git a/net/dns/manager_default.go b/net/dns/manager_default.go index 99ff017da..e14454e76 100644 --- a/net/dns/manager_default.go +++ b/net/dns/manager_default.go @@ -1,7 +1,7 @@ // Copyright (c) Tailscale Inc & AUTHORS // SPDX-License-Identifier: BSD-3-Clause -//go:build !linux && !freebsd && !openbsd && !windows && !darwin && !illumos && !solaris +//go:build !linux && !freebsd && !openbsd && !windows && !darwin && !illumos && !solaris && !plan9 package dns diff --git a/net/dns/manager_plan9.go b/net/dns/manager_plan9.go new file mode 100644 index 000000000..47666886a --- /dev/null +++ b/net/dns/manager_plan9.go @@ -0,0 +1,79 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +// TODO: man 6 ndb | grep -e 'suffix.*same line' +// to detect Russ's https://9fans.topicbox.com/groups/9fans/T9c9d81b5801a0820/ndb-suffix-specific-dns-changes + +package dns + +import ( + "bufio" + "bytes" + "log" + "net/netip" + "os" + "regexp" + + "tailscale.com/control/controlknobs" + "tailscale.com/health" + "tailscale.com/types/logger" +) + +func NewOSConfigurator(logf logger.Logf, ht *health.Tracker, knobs *controlknobs.Knobs, interfaceName string) (OSConfigurator, error) { + return &plan9DNSManager{ + logf: logf, + ht: ht, + knobs: knobs, + }, nil +} + +type plan9DNSManager struct { + logf logger.Logf + ht *health.Tracker + knobs *controlknobs.Knobs +} + +func (m *plan9DNSManager) SetDNS(c OSConfig) error { + var buf bytes.Buffer + bw := bufio.NewWriter(&buf) + c.WriteToBufioWriter(bw) + bw.Flush() + + log.Printf("XXX: TODO: plan9 SetDNS: %s", buf.Bytes()) + return nil +} + +func (m *plan9DNSManager) SupportsSplitDNS() bool { return false } + +func (m *plan9DNSManager) Close() error { + // TODO(bradfitz): remove the Tailscale bits from /net/ndb ideally + return nil +} + +var dnsRegex = regexp.MustCompile(`\bdns=(\d+\.\d+\.\d+\.\d+)\b`) + +func (m *plan9DNSManager) GetBaseConfig() (OSConfig, error) { + var oc OSConfig + f, err := os.Open("/net/ndb") + if err != nil { + return oc, err + } + defer f.Close() + bs := bufio.NewScanner(f) + for bs.Scan() { + m := dnsRegex.FindSubmatch(bs.Bytes()) + if m == nil { + continue + } + addr, err := netip.ParseAddr(string(m[1])) + if err != nil { + continue + } + oc.Nameservers = append(oc.Nameservers, addr) + } + if err := bs.Err(); err != nil { + return oc, err + } + + return oc, nil +} diff --git a/net/netmon/interfaces_test.go b/net/netmon/interfaces_test.go index edd4f6d6e..8645c00c9 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 47b540d6a..50530ddfa 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 @@ -491,7 +491,7 @@ func (m *Monitor) IsMajorChangeFrom(s1, s2 *State) bool { return true } for iname, i := range s1.Interface { - if iname == m.tsIfName { + if iname == m.tsIfName || iname == "/net/ipifc/2" { // Ignore changes in the Tailscale interface itself. continue } @@ -596,7 +596,7 @@ func (m *Monitor) pollWallTime() { // // We don't do this on mobile platforms for battery reasons, and because these // platforms don't really sleep in the same way. -const shouldMonitorTimeJump = runtime.GOOS != "android" && runtime.GOOS != "ios" +const shouldMonitorTimeJump = runtime.GOOS != "android" && runtime.GOOS != "ios" && runtime.GOOS != "plan9" // checkWallTimeAdvanceLocked reports whether wall time jumped more than 150% of // pollWallTimeInterval, indicating we probably just came out of sleep. Once a diff --git a/net/netmon/state.go b/net/netmon/state.go index a612dd06d..25c251f10 100644 --- a/net/netmon/state.go +++ b/net/netmon/state.go @@ -454,6 +454,9 @@ func isTailscaleInterface(name string, ips []netip.Prefix) bool { // macOS NetworkExtensions and utun devices. return true } + if runtime.GOOS == "plan9" && (hasTailscaleIP(ips) || name == "/net/ipifc/2") { // XXX fix; use tun name + return true + } return name == "Tailscale" || // as it is on Windows strings.HasPrefix(name, "tailscale") // TODO: use --tun flag value, etc; see TODO in method doc } @@ -466,16 +469,17 @@ var getPAC func() string // It does not set the returned State.IsExpensive. The caller can populate that. // // Deprecated: use netmon.Monitor.InterfaceState instead. -func GetState() (*State, error) { +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) { + isTS := 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 || isTS || isTailscaleInterface(ni.Name, pfxs) { return } for _, pfx := range pfxs { diff --git a/net/tsdial/tsdial.go b/net/tsdial/tsdial.go index 3606dd67f..8d287fdb0 100644 --- a/net/tsdial/tsdial.go +++ b/net/tsdial/tsdial.go @@ -242,7 +242,7 @@ func changeAffectsConn(delta *netmon.ChangeDelta, conn net.Conn) bool { // In a few cases, we don't have a new DefaultRouteInterface (e.g. on // Android; see tailscale/corp#19124); if so, pessimistically assume // that all connections are affected. - if delta.New.DefaultRouteInterface == "" { + if delta.New.DefaultRouteInterface == "" && runtime.GOOS != "plan9" { return true }