wgengine/router: add ip rules for unifi udm-pro

Fixes: #4038

Signed-off-by: Jason Barnett <J@sonBarnett.com>
This commit is contained in:
Jason Barnett
2024-01-11 17:36:12 -07:00
committed by Adrian Dewhurst
parent 10d4057a64
commit 8d4ea4d90c
3 changed files with 110 additions and 10 deletions

View File

@@ -9,6 +9,7 @@ import (
"os"
"runtime"
"strconv"
"strings"
"tailscale.com/types/lazy"
"tailscale.com/util/lineiter"
@@ -30,6 +31,7 @@ const (
WDMyCloud = Distro("wdmycloud")
Unraid = Distro("unraid")
Alpine = Distro("alpine")
UDMPro = Distro("udmpro")
)
var distro lazy.SyncValue[Distro]
@@ -75,6 +77,9 @@ 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("/etc/debian_version"):
return Debian
case have("/etc/arch-release"):
@@ -147,3 +152,44 @@ 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
}