From d2fc5303166ae96b5b62a4470866357c18fdad14 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 18 May 2023 23:03:03 +0700 Subject: [PATCH] all: add support for Synology router --- cmd/ctrld/cli_router_linux.go | 2 +- internal/router/dnsmasq.go | 2 +- internal/router/openwrt.go | 1 - internal/router/router.go | 43 +++++++++++++++++---------- internal/router/synology.go | 55 +++++++++++++++++++++++++++++++++++ 5 files changed, 85 insertions(+), 18 deletions(-) create mode 100644 internal/router/synology.go diff --git a/cmd/ctrld/cli_router_linux.go b/cmd/ctrld/cli_router_linux.go index 3bd70f1..5791a7e 100644 --- a/cmd/ctrld/cli_router_linux.go +++ b/cmd/ctrld/cli_router_linux.go @@ -43,7 +43,7 @@ func initRouterCLI() { platform = router.Name() } switch platform { - case router.DDWrt, router.Merlin, router.OpenWrt, router.Ubios: + case router.DDWrt, router.Merlin, router.OpenWrt, router.Ubios, router.Synology: default: unsupportedPlatformHelp(cmd) os.Exit(1) diff --git a/internal/router/dnsmasq.go b/internal/router/dnsmasq.go index b8fad8c..77f47d7 100644 --- a/internal/router/dnsmasq.go +++ b/internal/router/dnsmasq.go @@ -49,7 +49,7 @@ func dnsMasqConf() (string, error) { var sb strings.Builder var tmplText string switch Name() { - case DDWrt, OpenWrt, Ubios: + case DDWrt, OpenWrt, Ubios, Synology: tmplText = dnsMasqConfigContentTmpl case Merlin: tmplText = merlinDNSMasqPostConfTmpl diff --git a/internal/router/openwrt.go b/internal/router/openwrt.go index 6e5881d..701913b 100644 --- a/internal/router/openwrt.go +++ b/internal/router/openwrt.go @@ -28,7 +28,6 @@ func setupOpenWrt() error { if _, err := uci("delete", "dhcp.@dnsmasq[0].port"); err != nil && !errors.Is(err, errUCIEntryNotFound) { return err } - // Disable dnsmasq as DNS server. dnsMasqConfigContent, err := dnsMasqConf() if err != nil { return err diff --git a/internal/router/router.go b/internal/router/router.go index 05d7f24..6b33a4c 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -19,10 +19,11 @@ import ( ) const ( - OpenWrt = "openwrt" - DDWrt = "ddwrt" - Merlin = "merlin" - Ubios = "ubios" + OpenWrt = "openwrt" + DDWrt = "ddwrt" + Merlin = "merlin" + Ubios = "ubios" + Synology = "synology" ) // ErrNotSupported reports the current router is not supported error. @@ -39,21 +40,22 @@ type router struct { // SupportedPlatforms return all platforms that can be configured to run with ctrld. func SupportedPlatforms() []string { - return []string{DDWrt, Merlin, OpenWrt, Ubios} + return []string{DDWrt, Merlin, OpenWrt, Ubios, Synology} } var configureFunc = map[string]func() error{ - DDWrt: setupDDWrt, - Merlin: setupMerlin, - OpenWrt: setupOpenWrt, - Ubios: setupUbiOS, + DDWrt: setupDDWrt, + Merlin: setupMerlin, + OpenWrt: setupOpenWrt, + Ubios: setupUbiOS, + Synology: setupSynology, } // Configure configures things for running ctrld on the router. func Configure(c *ctrld.Config) error { name := Name() switch name { - case DDWrt, Merlin, OpenWrt, Ubios: + case DDWrt, Merlin, OpenWrt, Ubios, Synology: if c.HasUpstreamSendClientInfo() { r := routerPlatform.Load() r.sendClientInfo = true @@ -88,7 +90,7 @@ func ConfigureService(sc *service.Config) error { } case OpenWrt: sc.Option["SysvScript"] = openWrtScript - case Merlin, Ubios: + case Merlin, Ubios, Synology: } return nil } @@ -151,6 +153,8 @@ func PostInstall() error { return postInstallOpenWrt() case Ubios: return postInstallUbiOS() + case Synology: + return postInstallSynology() } return nil } @@ -167,6 +171,8 @@ func Cleanup() error { return cleanupOpenWrt() case Ubios: return cleanupUbiOS() + case Synology: + return cleanupSynology() } return nil } @@ -175,7 +181,7 @@ func Cleanup() error { func ListenAddress() string { name := Name() switch name { - case DDWrt, Merlin, OpenWrt, Ubios: + case DDWrt, Merlin, OpenWrt, Ubios, Synology: return "127.0.0.1:5354" } return "" @@ -194,14 +200,16 @@ func Name() string { func distroName() string { switch { - case bytes.HasPrefix(uname(), []byte("DD-WRT")): + case bytes.HasPrefix(unameO(), []byte("DD-WRT")): return DDWrt - case bytes.HasPrefix(uname(), []byte("ASUSWRT-Merlin")): + case bytes.HasPrefix(unameO(), []byte("ASUSWRT-Merlin")): return Merlin case haveFile("/etc/openwrt_version"): return OpenWrt case haveDir("/data/unifi"): return Ubios + case bytes.HasPrefix(unameU(), []byte("synology")): + return Synology } return "" } @@ -216,7 +224,12 @@ func haveDir(dir string) bool { return fi != nil && fi.IsDir() } -func uname() []byte { +func unameO() []byte { out, _ := exec.Command("uname", "-o").Output() return out } + +func unameU() []byte { + out, _ := exec.Command("uname", "-u").Output() + return out +} diff --git a/internal/router/synology.go b/internal/router/synology.go new file mode 100644 index 0000000..b221be8 --- /dev/null +++ b/internal/router/synology.go @@ -0,0 +1,55 @@ +package router + +import ( + "fmt" + "os" + "os/exec" +) + +const ( + synologyDNSMasqConfigPath = "/etc/dhcpd/dhcpd-zzz-ctrld.conf" + synologyDhcpdInfoPath = "/etc/dhcpd/dhcpd-zzz-ctrld.info" +) + +func setupSynology() error { + dnsMasqConfigContent, err := dnsMasqConf() + if err != nil { + return err + } + if err := os.WriteFile(synologyDNSMasqConfigPath, []byte(dnsMasqConfigContent), 0600); err != nil { + return err + } + if err := os.WriteFile(synologyDhcpdInfoPath, []byte(`enable="yes"`), 0600); err != nil { + return err + } + if err := synologyRestartDNSMasq(); err != nil { + return err + } + return nil +} + +func cleanupSynology() error { + // Remove the custom config files. + for _, f := range []string{synologyDNSMasqConfigPath, synologyDhcpdInfoPath} { + if err := os.Remove(f); err != nil { + return err + } + } + + // Restart dnsmasq service. + if err := synologyRestartDNSMasq(); err != nil { + return err + } + return nil +} + +func postInstallSynology() error { + return nil +} + +func synologyRestartDNSMasq() error { + if out, err := exec.Command("/etc/rc.network", "nat-restart-dhcp").CombinedOutput(); err != nil { + return fmt.Errorf("synologyRestartDNSMasq: %s - %w", string(out), err) + } + return nil +}