mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-07-04 01:07:49 +02:00
all: make router setup/cleanup works more generally
This commit is contained in:
committed by
Cuong Manh Le
parent
66cb7cc21d
commit
9ed8e49a08
+31
-28
@@ -275,22 +275,19 @@ func initCLI() {
|
|||||||
if cp := router.CertPool(); cp != nil {
|
if cp := router.CertPool(); cp != nil {
|
||||||
rootCertPool = cp
|
rootCertPool = cp
|
||||||
}
|
}
|
||||||
// Perform router setup/cleanup if ctrld could not be direct listener.
|
p.onStarted = append(p.onStarted, func() {
|
||||||
if !couldBeDirectListener(cfg.FirstListener()) {
|
mainLog.Debug().Msg("router setup")
|
||||||
p.onStarted = append(p.onStarted, func() {
|
if err := p.router.Setup(); err != nil {
|
||||||
mainLog.Debug().Msg("router setup")
|
mainLog.Error().Err(err).Msg("could not configure router")
|
||||||
if err := p.router.Setup(); err != nil {
|
}
|
||||||
mainLog.Error().Err(err).Msg("could not configure router")
|
})
|
||||||
}
|
p.onStopped = append(p.onStopped, func() {
|
||||||
})
|
mainLog.Debug().Msg("router cleanup")
|
||||||
p.onStopped = append(p.onStopped, func() {
|
if err := p.router.Cleanup(); err != nil {
|
||||||
mainLog.Debug().Msg("router cleanup")
|
mainLog.Error().Err(err).Msg("could not cleanup router")
|
||||||
if err := p.router.Cleanup(); err != nil {
|
}
|
||||||
mainLog.Error().Err(err).Msg("could not cleanup router")
|
p.resetDNS()
|
||||||
}
|
})
|
||||||
p.resetDNS()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
close(waitCh)
|
close(waitCh)
|
||||||
@@ -404,7 +401,7 @@ func initCLI() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if router.Name() != "" && !couldBeDirectListener(cfg.FirstListener()) {
|
if router.Name() != "" {
|
||||||
mainLog.Debug().Msg("cleaning up router before installing")
|
mainLog.Debug().Msg("cleaning up router before installing")
|
||||||
_ = p.router.Cleanup()
|
_ = p.router.Cleanup()
|
||||||
}
|
}
|
||||||
@@ -504,15 +501,18 @@ func initCLI() {
|
|||||||
Short: "Stop the ctrld service",
|
Short: "Stop the ctrld service",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
prog := &prog{}
|
tryReadingConfig(false)
|
||||||
s, err := newService(prog, svcConfig)
|
v.Unmarshal(&cfg)
|
||||||
|
p := &prog{router: router.New(&cfg)}
|
||||||
|
s, err := newService(p, svcConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Error().Msg(err.Error())
|
mainLog.Error().Msg(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
initLogging()
|
initLogging()
|
||||||
if doTasks([]task{{s.Stop, true}}) {
|
if doTasks([]task{{s.Stop, true}}) {
|
||||||
prog.resetDNS()
|
p.router.Cleanup()
|
||||||
|
p.resetDNS()
|
||||||
mainLog.Notice().Msg("Service stopped")
|
mainLog.Notice().Msg("Service stopped")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -591,7 +591,9 @@ func initCLI() {
|
|||||||
NOTE: Uninstalling will set DNS to values provided by DHCP.`,
|
NOTE: Uninstalling will set DNS to values provided by DHCP.`,
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
p := &prog{}
|
tryReadingConfig(false)
|
||||||
|
v.Unmarshal(&cfg)
|
||||||
|
p := &prog{router: router.New(&cfg)}
|
||||||
s, err := newService(p, svcConfig)
|
s, err := newService(p, svcConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Error().Msg(err.Error())
|
mainLog.Error().Msg(err.Error())
|
||||||
@@ -1157,19 +1159,20 @@ func uninstall(p *prog, s service.Service) {
|
|||||||
}
|
}
|
||||||
initLogging()
|
initLogging()
|
||||||
if doTasks(tasks) {
|
if doTasks(tasks) {
|
||||||
r := router.New(&cfg)
|
if err := p.router.ConfigureService(svcConfig); err != nil {
|
||||||
if err := r.Uninstall(svcConfig); err != nil {
|
mainLog.Fatal().Err(err).Msg("could not configure service")
|
||||||
|
}
|
||||||
|
if err := p.router.Uninstall(svcConfig); err != nil {
|
||||||
mainLog.Warn().Err(err).Msg("post uninstallation failed, please check system/service log for details error")
|
mainLog.Warn().Err(err).Msg("post uninstallation failed, please check system/service log for details error")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Stop already reset DNS on router.
|
p.resetDNS()
|
||||||
if router.Name() == "" {
|
if router.Name() != "" {
|
||||||
p.resetDNS()
|
mainLog.Debug().Msg("Router cleanup")
|
||||||
}
|
}
|
||||||
mainLog.Debug().Msg("Router cleanup")
|
|
||||||
// Stop already did router.Cleanup and report any error if happens,
|
// Stop already did router.Cleanup and report any error if happens,
|
||||||
// ignoring error here to prevent false positive.
|
// ignoring error here to prevent false positive.
|
||||||
_ = r.Cleanup()
|
_ = p.router.Cleanup()
|
||||||
mainLog.Notice().Msg("Service uninstalled")
|
mainLog.Notice().Msg("Service uninstalled")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ func resetDNS(iface *net.Interface) (err error) {
|
|||||||
if ctrldnet.IPv6Available(ctx) {
|
if ctrldnet.IPv6Available(ctx) {
|
||||||
c := client6.NewClient()
|
c := client6.NewClient()
|
||||||
conversation, err := c.Exchange(iface.Name)
|
conversation, err := c.Exchange(iface.Name)
|
||||||
if err != nil {
|
if err != nil && !errAddrInUse(err) {
|
||||||
mainLog.Debug().Err(err).Msg("could not exchange DHCPv6")
|
mainLog.Debug().Err(err).Msg("could not exchange DHCPv6")
|
||||||
}
|
}
|
||||||
for _, packet := range conversation {
|
for _, packet := range conversation {
|
||||||
|
|||||||
+11
-1
@@ -1,12 +1,14 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"github.com/kardianos/service"
|
"github.com/kardianos/service"
|
||||||
|
|
||||||
@@ -216,7 +218,7 @@ func (p *prog) setDNS() {
|
|||||||
logger.Debug().Msg("setting DNS for interface")
|
logger.Debug().Msg("setting DNS for interface")
|
||||||
ns := lc.IP
|
ns := lc.IP
|
||||||
switch {
|
switch {
|
||||||
case couldBeDirectListener(lc):
|
case lc.IsDirectDnsListener():
|
||||||
// If ctrld is direct listener, use 127.0.0.1 as nameserver.
|
// If ctrld is direct listener, use 127.0.0.1 as nameserver.
|
||||||
ns = "127.0.0.1"
|
ns = "127.0.0.1"
|
||||||
case lc.Port != 53:
|
case lc.Port != 53:
|
||||||
@@ -294,3 +296,11 @@ func runLogServer(sockPath string) net.Conn {
|
|||||||
}
|
}
|
||||||
return server
|
return server
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func errAddrInUse(err error) bool {
|
||||||
|
opErr, ok := err.(*net.OpError)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return errors.Is(opErr.Err, syscall.EADDRINUSE)
|
||||||
|
}
|
||||||
|
|||||||
@@ -207,6 +207,24 @@ type ListenerConfig struct {
|
|||||||
Policy *ListenerPolicyConfig `mapstructure:"policy" toml:"policy,omitempty"`
|
Policy *ListenerPolicyConfig `mapstructure:"policy" toml:"policy,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsDirectDnsListener reports whether ctrld can be a direct listener on port 53.
|
||||||
|
// It returns true only if ctrld can listen on port 53 for all interfaces. That means
|
||||||
|
// there's no other software listening on port 53.
|
||||||
|
//
|
||||||
|
// If someone listening on port 53, or ctrld could only listen on port 53 for a specific
|
||||||
|
// interface, ctrld could only be configured as a DNS forwarder.
|
||||||
|
func (lc *ListenerConfig) IsDirectDnsListener() bool {
|
||||||
|
if lc == nil || lc.Port != 53 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
switch lc.IP {
|
||||||
|
case "", "::", "0.0.0.0":
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ListenerPolicyConfig specifies the policy rules for ctrld to filter incoming requests.
|
// ListenerPolicyConfig specifies the policy rules for ctrld to filter incoming requests.
|
||||||
type ListenerPolicyConfig struct {
|
type ListenerPolicyConfig struct {
|
||||||
Name string `mapstructure:"name" toml:"name,omitempty"`
|
Name string `mapstructure:"name" toml:"name,omitempty"`
|
||||||
|
|||||||
@@ -58,6 +58,9 @@ func (d *Ddwrt) PreRun() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Ddwrt) Setup() error {
|
func (d *Ddwrt) Setup() error {
|
||||||
|
if d.cfg.FirstListener().IsDirectDnsListener() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
// Already setup.
|
// Already setup.
|
||||||
if val, _ := nvram.Run("get", nvram.CtrldSetupKey); val == "1" {
|
if val, _ := nvram.Run("get", nvram.CtrldSetupKey); val == "1" {
|
||||||
return nil
|
return nil
|
||||||
@@ -81,6 +84,9 @@ func (d *Ddwrt) Setup() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Ddwrt) Cleanup() error {
|
func (d *Ddwrt) Cleanup() error {
|
||||||
|
if d.cfg.FirstListener().IsDirectDnsListener() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
if val, _ := nvram.Run("get", nvram.CtrldSetupKey); val == "1" {
|
if val, _ := nvram.Run("get", nvram.CtrldSetupKey); val == "1" {
|
||||||
nvramKvMap["dnsmasq_options"] = ""
|
nvramKvMap["dnsmasq_options"] = ""
|
||||||
// Restore old configs.
|
// Restore old configs.
|
||||||
|
|||||||
@@ -62,6 +62,9 @@ func (e *EdgeOS) PreRun() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *EdgeOS) Setup() error {
|
func (e *EdgeOS) Setup() error {
|
||||||
|
if e.cfg.FirstListener().IsDirectDnsListener() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
if e.isUSG {
|
if e.isUSG {
|
||||||
return e.setupUSG()
|
return e.setupUSG()
|
||||||
}
|
}
|
||||||
@@ -69,6 +72,9 @@ func (e *EdgeOS) Setup() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *EdgeOS) Cleanup() error {
|
func (e *EdgeOS) Cleanup() error {
|
||||||
|
if e.cfg.FirstListener().IsDirectDnsListener() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
if e.isUSG {
|
if e.isUSG {
|
||||||
return e.cleanupUSG()
|
return e.cleanupUSG()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,9 @@ func (f *Firewalla) PreRun() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *Firewalla) Setup() error {
|
func (f *Firewalla) Setup() error {
|
||||||
|
if f.cfg.FirstListener().IsDirectDnsListener() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
data, err := dnsmasq.FirewallaConfTmpl(dnsmasq.ConfigContentTmpl, f.cfg)
|
data, err := dnsmasq.FirewallaConfTmpl(dnsmasq.ConfigContentTmpl, f.cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("generating dnsmasq config: %w", err)
|
return fmt.Errorf("generating dnsmasq config: %w", err)
|
||||||
@@ -71,6 +74,9 @@ func (f *Firewalla) Setup() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *Firewalla) Cleanup() error {
|
func (f *Firewalla) Cleanup() error {
|
||||||
|
if f.cfg.FirstListener().IsDirectDnsListener() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
// Removing current config.
|
// Removing current config.
|
||||||
if err := os.Remove(firewallaDNSMasqConfigPath); err != nil {
|
if err := os.Remove(firewallaDNSMasqConfigPath); err != nil {
|
||||||
return fmt.Errorf("removing ctrld config: %w", err)
|
return fmt.Errorf("removing ctrld config: %w", err)
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ func (m *Merlin) PreRun() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *Merlin) Setup() error {
|
func (m *Merlin) Setup() error {
|
||||||
|
if m.cfg.FirstListener().IsDirectDnsListener() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
buf, err := os.ReadFile(dnsmasq.MerlinPostConfPath)
|
buf, err := os.ReadFile(dnsmasq.MerlinPostConfPath)
|
||||||
// Already setup.
|
// Already setup.
|
||||||
if bytes.Contains(buf, []byte(dnsmasq.MerlinPostConfMarker)) {
|
if bytes.Contains(buf, []byte(dnsmasq.MerlinPostConfMarker)) {
|
||||||
@@ -86,6 +89,9 @@ func (m *Merlin) Setup() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *Merlin) Cleanup() error {
|
func (m *Merlin) Cleanup() error {
|
||||||
|
if m.cfg.FirstListener().IsDirectDnsListener() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
if val, _ := nvram.Run("get", nvram.CtrldSetupKey); val == "1" {
|
if val, _ := nvram.Run("get", nvram.CtrldSetupKey); val == "1" {
|
||||||
// Restore old configs.
|
// Restore old configs.
|
||||||
if err := nvram.Restore(nvramKvMap, nvram.CtrldSetupKey); err != nil {
|
if err := nvram.Restore(nvramKvMap, nvram.CtrldSetupKey); err != nil {
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ func (o *Openwrt) PreRun() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o *Openwrt) Setup() error {
|
func (o *Openwrt) Setup() error {
|
||||||
|
if o.cfg.FirstListener().IsDirectDnsListener() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
data, err := dnsmasq.ConfTmpl(dnsmasq.ConfigContentTmpl, o.cfg)
|
data, err := dnsmasq.ConfTmpl(dnsmasq.ConfigContentTmpl, o.cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -68,6 +71,9 @@ func (o *Openwrt) Setup() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o *Openwrt) Cleanup() error {
|
func (o *Openwrt) Cleanup() error {
|
||||||
|
if o.cfg.FirstListener().IsDirectDnsListener() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
// Remove the custom dnsmasq config
|
// Remove the custom dnsmasq config
|
||||||
if err := os.Remove(openwrtDNSMasqConfigPath); err != nil {
|
if err := os.Remove(openwrtDNSMasqConfigPath); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -66,6 +66,9 @@ func (p *Pfsense) Install(config *service.Config) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pfsense) Uninstall(config *service.Config) error {
|
func (p *Pfsense) Uninstall(config *service.Config) error {
|
||||||
|
if err := os.Remove(filepath.Join(rcPath, p.svcName+".sh")); err != nil {
|
||||||
|
return fmt.Errorf("os.Remove: %w", err)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,11 +87,10 @@ func (p *Pfsense) Setup() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pfsense) Cleanup() error {
|
func (p *Pfsense) Cleanup() error {
|
||||||
if err := os.Remove(filepath.Join(rcPath, p.svcName+".sh")); err != nil {
|
if p.cfg.FirstListener().IsDirectDnsListener() {
|
||||||
return fmt.Errorf("os.Remove: %w", err)
|
_ = exec.Command(unboundRcPath, "onerestart").Run()
|
||||||
|
_ = exec.Command(dnsmasqRcPath, "onerestart").Run()
|
||||||
}
|
}
|
||||||
_ = exec.Command(unboundRcPath, "onerestart").Run()
|
|
||||||
_ = exec.Command(dnsmasqRcPath, "onerestart").Run()
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,9 @@ func (s *Synology) PreRun() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Synology) Setup() error {
|
func (s *Synology) Setup() error {
|
||||||
|
if s.cfg.FirstListener().IsDirectDnsListener() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
data, err := dnsmasq.ConfTmpl(dnsmasq.ConfigContentTmpl, s.cfg)
|
data, err := dnsmasq.ConfTmpl(dnsmasq.ConfigContentTmpl, s.cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -61,6 +64,9 @@ func (s *Synology) Setup() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Synology) Cleanup() error {
|
func (s *Synology) Cleanup() error {
|
||||||
|
if s.cfg.FirstListener().IsDirectDnsListener() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
// Remove the custom config files.
|
// Remove the custom config files.
|
||||||
for _, f := range []string{synologyDNSMasqConfigPath, synologyDhcpdInfoPath} {
|
for _, f := range []string{synologyDNSMasqConfigPath, synologyDhcpdInfoPath} {
|
||||||
if err := os.Remove(f); err != nil {
|
if err := os.Remove(f); err != nil {
|
||||||
|
|||||||
@@ -53,6 +53,9 @@ func (f *FreshTomato) PreRun() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *FreshTomato) Setup() error {
|
func (f *FreshTomato) Setup() error {
|
||||||
|
if f.cfg.FirstListener().IsDirectDnsListener() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
// Already setup.
|
// Already setup.
|
||||||
if val, _ := nvram.Run("get", nvram.CtrldSetupKey); val == "1" {
|
if val, _ := nvram.Run("get", nvram.CtrldSetupKey); val == "1" {
|
||||||
return nil
|
return nil
|
||||||
@@ -83,6 +86,9 @@ func (f *FreshTomato) Setup() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *FreshTomato) Cleanup() error {
|
func (f *FreshTomato) Cleanup() error {
|
||||||
|
if f.cfg.FirstListener().IsDirectDnsListener() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
if val, _ := nvram.Run("get", nvram.CtrldSetupKey); val == "1" {
|
if val, _ := nvram.Run("get", nvram.CtrldSetupKey); val == "1" {
|
||||||
nvramKvMap["dnsmasq_custom"] = ""
|
nvramKvMap["dnsmasq_custom"] = ""
|
||||||
// Restore old configs.
|
// Restore old configs.
|
||||||
|
|||||||
@@ -47,6 +47,9 @@ func (u *Ubios) PreRun() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *Ubios) Setup() error {
|
func (u *Ubios) Setup() error {
|
||||||
|
if u.cfg.FirstListener().IsDirectDnsListener() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
data, err := dnsmasq.ConfTmpl(dnsmasq.ConfigContentTmpl, u.cfg)
|
data, err := dnsmasq.ConfTmpl(dnsmasq.ConfigContentTmpl, u.cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -62,6 +65,9 @@ func (u *Ubios) Setup() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *Ubios) Cleanup() error {
|
func (u *Ubios) Cleanup() error {
|
||||||
|
if u.cfg.FirstListener().IsDirectDnsListener() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
// Remove the custom dnsmasq config
|
// Remove the custom dnsmasq config
|
||||||
if err := os.Remove(ubiosDNSMasqConfigPath); err != nil {
|
if err := os.Remove(ubiosDNSMasqConfigPath); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
Reference in New Issue
Block a user