diff --git a/cmd/ctrld/cli.go b/cmd/ctrld/cli.go index 7b9a307..1b0262b 100644 --- a/cmd/ctrld/cli.go +++ b/cmd/ctrld/cli.go @@ -982,6 +982,10 @@ func uninstall(p *prog, s service.Service) { } initLogging() if doTasks(tasks) { + if err := router.PostUninstall(svcConfig); err != nil { + mainLog.Warn().Err(err).Msg("post uninstallation failed, please check system/service log for details error") + return + } // Stop already reset DNS on router. if router.Name() == "" { p.resetDNS() diff --git a/cmd/ctrld/prog.go b/cmd/ctrld/prog.go index 54cad6d..e917f88 100644 --- a/cmd/ctrld/prog.go +++ b/cmd/ctrld/prog.go @@ -235,7 +235,23 @@ func (p *prog) setDNS() { return } logger.Debug().Msg("setting DNS for interface") - if err := setDNS(netIface, []string{cfg.Listener["0"].IP}); err != nil { + ns := cfg.Listener["0"].IP + if router.Name() == router.Firewalla && ns == "127.0.0.1" { + // On Firewalla, the lo interface is excluded in all dnsmasq settings of all interfaces. + // Thus, we use "br0" as the nameserver in /etc/resolv.conf file. + logger.Warn().Msg("127.0.0.1 won't work on Firewalla") + if netIface, err := net.InterfaceByName("br0"); err == nil { + addrs, _ := netIface.Addrs() + for _, addr := range addrs { + if netIP, ok := addr.(*net.IPNet); ok && netIP.IP.To4() != nil { + logger.Warn().Msg("using br0 interface IP address as DNS server") + ns = netIP.IP.To4().String() + break + } + } + } + } + if err := setDNS(netIface, []string{ns}); err != nil { logger.Error().Err(err).Msgf("could not set DNS for interface") return } diff --git a/internal/router/dnsmasq.go b/internal/router/dnsmasq.go index 2ca3249..9df4132 100644 --- a/internal/router/dnsmasq.go +++ b/internal/router/dnsmasq.go @@ -1,7 +1,6 @@ package router import ( - "fmt" "strings" "text/template" ) @@ -50,10 +49,8 @@ func dnsMasqConf() (string, error) { var sb strings.Builder var tmplText string switch Name() { - case DDWrt, EdgeOS, OpenWrt, Ubios, Synology, Tomato: + case DDWrt, EdgeOS, Firewalla, OpenWrt, Ubios, Synology, Tomato: tmplText = dnsMasqConfigContentTmpl - case Firewalla: - tmplText = dnsMasqConfigContentTmpl + fmt.Sprintf("listen-address=127.0.0.1\n") case Merlin: tmplText = merlinDNSMasqPostConfTmpl } diff --git a/internal/router/firewalla.go b/internal/router/firewalla.go index 1182890..6d57409 100644 --- a/internal/router/firewalla.go +++ b/internal/router/firewalla.go @@ -4,42 +4,21 @@ import ( "fmt" "os" "os/exec" - "path/filepath" "strings" ) const ( - firewallaDNSMasqConfigPath = "/home/pi/.firewalla/config/dnsmasq_local" - firewallaDNSMasqBackupConfigPath = "/home/pi/.firewalla/config/dnsmasq_local.bak" - firewallaConfigPostMainDir = "/home/pi/.firewalla/config/post_main.d" - firewallaCtrldInitScriptPath = "/home/pi/.firewalla/config/post_main.d/start_ctrld.sh" + firewallaDNSMasqConfigPath = "/home/pi/.firewalla/config/dnsmasq_local/ctrld" + firewallaConfigPostMainDir = "/home/pi/.firewalla/config/post_main.d" + firewallaCtrldInitScriptPath = "/home/pi/.firewalla/config/post_main.d/start_ctrld.sh" ) func setupFirewalla() error { - fi, err := os.Stat(firewallaDNSMasqConfigPath) - if err != nil { - return fmt.Errorf("setupFirewalla: get current config directory: %w", err) - } - - _ = os.RemoveAll(firewallaDNSMasqBackupConfigPath) - - // Creating a backup. - if err := os.Rename(firewallaDNSMasqConfigPath, firewallaDNSMasqBackupConfigPath); err != nil { - return fmt.Errorf("setupFirewalla: backup current config: %w", err) - } - - // Creating our own config. - if err := os.MkdirAll(firewallaDNSMasqConfigPath, fi.Mode()); err != nil { - return fmt.Errorf("setupFirewalla: creating config dir: %w", err) - } - - // Adding ctrld listener as the only upstream. dnsMasqConfigContent, err := dnsMasqConf() if err != nil { return fmt.Errorf("setupFirewalla: generating dnsmasq config: %w", err) } - ctrldConfPath := filepath.Join(firewallaDNSMasqConfigPath, "ctrld") - if err := os.WriteFile(ctrldConfPath, []byte(dnsMasqConfigContent), 0600); err != nil { + if err := os.WriteFile(firewallaDNSMasqConfigPath, []byte(dnsMasqConfigContent), 0600); err != nil { return fmt.Errorf("setupFirewalla: writing ctrld config: %w", err) } @@ -52,21 +31,11 @@ func setupFirewalla() error { } func cleanupFirewalla() error { - // Do nothing if there's no backup config. - if _, err := os.Stat(firewallaDNSMasqBackupConfigPath); err != nil && os.IsNotExist(err) { - return nil - } - // Removing current config. - if err := os.RemoveAll(firewallaDNSMasqConfigPath); err != nil { + if err := os.Remove(firewallaDNSMasqConfigPath); err != nil { return fmt.Errorf("cleanupFirewalla: removing ctrld config: %w", err) } - // Restoring backup. - if err := os.Rename(firewallaDNSMasqBackupConfigPath, firewallaDNSMasqConfigPath); err != nil { - return fmt.Errorf("cleanupFirewalla: restoring backup config: %w", err) - } - // Restart dnsmasq service. if err := restartDNSMasq(); err != nil { return fmt.Errorf("cleanupFirewalla: restartDNSMasq: %w", err) @@ -83,6 +52,14 @@ func postInstallFirewalla() error { return nil } +func postUninstallFirewalla() error { + // Removing startup script. + if err := os.Remove(firewallaCtrldInitScriptPath); err != nil { + return fmt.Errorf("postUninstallFirewalla: removing startup script: %w", err) + } + return nil +} + func firewallaRestartDNSMasq() error { return exec.Command("systemctl", "restart", "firerouter_dns").Run() } diff --git a/internal/router/router.go b/internal/router/router.go index 79f5901..c53178f 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -174,6 +174,24 @@ func PostInstall(svc *service.Config) error { return nil } +// PostUninstall performs task after uninstalling ctrld on router. +func PostUninstall(svc *service.Config) error { + name := Name() + switch name { + case DDWrt: + case EdgeOS: + case Firewalla: + return postUninstallFirewalla() + case Merlin: + case OpenWrt: + case Pfsense: + case Synology: + case Tomato: + case Ubios: + } + return nil +} + // Cleanup cleans ctrld setup on the router. func Cleanup(svc *service.Config) error { name := Name()