From 17b881538ad4ded64b655c2b901a70628b00e921 Mon Sep 17 00:00:00 2001 From: Jason Barnett Date: Sun, 22 Dec 2024 13:18:40 -0700 Subject: [PATCH] wgengine/router: refactor udm-pro into broader ubnt support Fixes #14453 Signed-off-by: Jason Barnett --- version/distro/distro.go | 53 ++++------------------------ wgengine/router/router_linux.go | 14 ++++---- wgengine/router/router_linux_test.go | 6 ++-- 3 files changed, 17 insertions(+), 56 deletions(-) diff --git a/version/distro/distro.go b/version/distro/distro.go index 8128ce395..f7997e1d9 100644 --- a/version/distro/distro.go +++ b/version/distro/distro.go @@ -9,7 +9,6 @@ import ( "os" "runtime" "strconv" - "strings" "tailscale.com/types/lazy" "tailscale.com/util/lineiter" @@ -31,7 +30,7 @@ const ( WDMyCloud = Distro("wdmycloud") Unraid = Distro("unraid") Alpine = Distro("alpine") - UDMPro = Distro("udmpro") + UBNT = Distro("ubnt") // Ubiquiti Networks ) var distro lazy.SyncValue[Distro] @@ -77,9 +76,12 @@ func linuxDistro() Distro { case have("/usr/local/bin/freenas-debug"): // TrueNAS Scale runs on debian return TrueNAS - case isUDMPro(): - // UDM-Pro runs on debian - return UDMPro + case have("/usr/bin/ubnt-device-info"): + // UBNT runs on Debian-based systems. This MUST be checked before Debian. + // + // Currently supported product families: + // - UDM (UniFi Dream Machine, UDM-Pro) + return UBNT case have("/etc/debian_version"): return Debian case have("/etc/arch-release"): @@ -152,44 +154,3 @@ func DSMVersion() int { return 0 }) } - -// isUDMPro checks a couple of files known to exist on a UDM-Pro and returns -// true if the expected content exists in the files. -func isUDMPro() bool { - // This is a performance guardrail against trying to load both - // /etc/board.info and /sys/firmware/devicetree/base/soc/board-cfg/id when - // not running on Debian so we don't make unnecessary calls in situations - // where we definitely are NOT on a UDM Pro. In other words, the have() call - // is much cheaper than the two os.ReadFile() in fileContainsAnyString(). - // That said, on Debian systems we will still be making the two - // os.ReadFile() in fileContainsAnyString(). - if !have("/etc/debian_version") { - return false - } - if exists, err := fileContainsAnyString("/etc/board.info", "UDMPRO", "Dream Machine PRO"); err == nil && exists { - return true - } - if exists, err := fileContainsAnyString("/sys/firmware/devicetree/base/soc/board-cfg/id", "udm pro"); err == nil && exists { - return true - } - return false -} - -// fileContainsAnyString is used to determine if one or more of the provided -// strings exists in a file. This is not efficient for larger files. If you want -// to use this function to parse large files, please refactor to use -// `io.LimitedReader`. -func fileContainsAnyString(filePath string, searchStrings ...string) (bool, error) { - data, err := os.ReadFile(filePath) - if err != nil { - return false, err - } - - content := string(data) - for _, searchString := range searchStrings { - if strings.Contains(content, searchString) { - return true, nil - } - } - return false, nil -} diff --git a/wgengine/router/router_linux.go b/wgengine/router/router_linux.go index e154a30fa..80191b248 100644 --- a/wgengine/router/router_linux.go +++ b/wgengine/router/router_linux.go @@ -1184,7 +1184,7 @@ var ( ) // baseIPRules are the policy routing rules that Tailscale uses, when not -// running on a UDM-Pro. +// running on a UBNT device. // // The priority is the value represented here added to r.ipPolicyPrefBase, // which is usually 5200. @@ -1236,15 +1236,15 @@ var baseIPRules = []netlink.Rule{ // usual rules (pref 32766 and 32767, ie. main and default). } -// udmProIPRules are the policy routing rules that Tailscale uses, when running -// on a UDM-Pro. +// ubntIPRules are the policy routing rules that Tailscale uses, when running +// on a UBNT device. // // The priority is the value represented here added to // r.ipPolicyPrefBase, which is usually 5200. // // This represents an experiment that will be used to gather more information. // If this goes well, Tailscale may opt to use this for all of Linux. -var udmProIPRules = []netlink.Rule{ +var ubntIPRules = []netlink.Rule{ // non-fwmark packets fall through to the usual rules (pref 32766 and 32767, // ie. main and default). { @@ -1256,10 +1256,10 @@ var udmProIPRules = []netlink.Rule{ } // ipRules returns the appropriate list of ip rules to be used by Tailscale. See -// comments on baseIPRules and udmProIPRules for more details. +// comments on baseIPRules and ubntIPRules for more details. func ipRules() []netlink.Rule { - if getDistroFunc() == distro.UDMPro { - return udmProIPRules + if getDistroFunc() == distro.UBNT { + return ubntIPRules } return baseIPRules } diff --git a/wgengine/router/router_linux_test.go b/wgengine/router/router_linux_test.go index 7718f17c4..9a159aea8 100644 --- a/wgengine/router/router_linux_test.go +++ b/wgengine/router/router_linux_test.go @@ -1233,14 +1233,14 @@ func adjustFwmask(t *testing.T, s string) string { return fwmaskAdjustRe.ReplaceAllString(s, "$1") } -func TestIPRulesForUDMPro(t *testing.T) { +func TestIPRulesForUBNT(t *testing.T) { // Override the global getDistroFunc getDistroFunc = func() distro.Distro { - return distro.UDMPro + return distro.UBNT } defer func() { getDistroFunc = distro.Get }() // Restore original after the test - expected := udmProIPRules + expected := ubntIPRules actual := ipRules() if len(expected) != len(actual) {