From 905f2d08c55189575a1b8b04c2e2ead7d7a0602f Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 25 Jul 2024 22:23:01 +0700 Subject: [PATCH] cmd/cli: fix reset DNS when doing self-uninstall While at it, also using "ctrld uninstall" on unix platform, ensuring everything is cleanup properly. --- cmd/cli/cli.go | 20 ++++--------- cmd/cli/dns_proxy.go | 5 ++-- cmd/cli/self_kill_others.go | 16 +++++++++++ cmd/cli/self_kill_unix.go | 56 +++++++++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 18 deletions(-) create mode 100644 cmd/cli/self_kill_others.go create mode 100644 cmd/cli/self_kill_unix.go diff --git a/cmd/cli/cli.go b/cmd/cli/cli.go index 42e20b6..9ed3602 100644 --- a/cmd/cli/cli.go +++ b/cmd/cli/cli.go @@ -1157,7 +1157,7 @@ func run(appCallback *AppCallback, stopCh chan struct{}) { } cdLogger := mainLog.Load().With().Str("mode", "cd").Logger() - _ = uninstallIfInvalidCdUID(err, cdLogger) + _ = uninstallIfInvalidCdUID(err, p, cdLogger) cdLogger.Fatal().Err(err).Msg("failed to fetch resolver config") } } @@ -2617,26 +2617,16 @@ func doValidateCdRemoteConfig(cdUID string) { } // uninstallIfInvalidCdUID performs self-uninstallation if the ControlD device does not exist. -func uninstallIfInvalidCdUID(err error, logger zerolog.Logger) bool { +func uninstallIfInvalidCdUID(err error, p *prog, logger zerolog.Logger) bool { var uer *controld.UtilityErrorResponse if errors.As(err, &uer) && uer.ErrorField.Code == controld.InvalidConfigCode { - s, err := newService(&prog{}, svcConfig) + s, err := newService(p, svcConfig) if err != nil { logger.Warn().Err(err).Msg("failed to create new service") return false } - if netIface, _ := netInterface(iface); netIface != nil { - if err := restoreNetworkManager(); err != nil { - logger.Error().Err(err).Msg("could not restore NetworkManager") - return false - } - logger.Debug().Str("iface", netIface.Name).Msg("Restoring DNS for interface") - if err := resetDNS(netIface); err != nil { - logger.Warn().Err(err).Msg("something went wrong while restoring DNS") - } else { - logger.Debug().Str("iface", netIface.Name).Msg("Restoring DNS successfully") - } - } + + p.resetDNS() tasks := []task{{s.Uninstall, true}} if doTasks(tasks) { diff --git a/cmd/cli/dns_proxy.go b/cmd/cli/dns_proxy.go index 6e8c1fa..9519468 100644 --- a/cmd/cli/dns_proxy.go +++ b/cmd/cli/dns_proxy.go @@ -862,9 +862,8 @@ func (p *prog) doSelfUninstall(answer *dns.Msg) { p.checkingSelfUninstall = true _, err := controld.FetchResolverConfig(cdUID, rootCmd.Version, cdDev) logger.Debug().Msg("maximum number of refused queries reached, checking device status") - if uninstallIfInvalidCdUID(err, logger) { - logger.Fatal().Msgf("service was uninstalled because device %q does not exist", cdUID) - } + selfUninstall(err, p, logger) + if err != nil { logger.Warn().Err(err).Msg("could not fetch resolver config") } diff --git a/cmd/cli/self_kill_others.go b/cmd/cli/self_kill_others.go new file mode 100644 index 0000000..1fe9b8a --- /dev/null +++ b/cmd/cli/self_kill_others.go @@ -0,0 +1,16 @@ +//go:build !unix + +package cli + +import ( + "os" + + "github.com/rs/zerolog" +) + +func selfUninstall(err error, p *prog, logger zerolog.Logger) { + if uninstallIfInvalidCdUID(err, p, logger) { + logger.Warn().Msgf("service was uninstalled because device %q does not exist", cdUID) + os.Exit(0) + } +} diff --git a/cmd/cli/self_kill_unix.go b/cmd/cli/self_kill_unix.go new file mode 100644 index 0000000..95767fe --- /dev/null +++ b/cmd/cli/self_kill_unix.go @@ -0,0 +1,56 @@ +//go:build unix + +package cli + +import ( + "errors" + "fmt" + "os" + "os/exec" + "runtime" + "syscall" + + "github.com/Control-D-Inc/ctrld/internal/controld" + "github.com/rs/zerolog" +) + +func selfUninstall(err error, p *prog, logger zerolog.Logger) { + var uer *controld.UtilityErrorResponse + if errors.As(err, &uer) && uer.ErrorField.Code == controld.InvalidConfigCode { + if runtime.GOOS == "linux" { + s, err := newService(p, svcConfig) + if err != nil { + logger.Warn().Err(err).Msg("failed to create new service") + } else { + selfUninstallLinux(err, p, logger) + _ = s.Stop() + os.Exit(0) + } + } + + bin, err := os.Executable() + if err != nil { + logger.Fatal().Err(err).Msg("could not determine executable") + } + args := []string{"uninstall"} + if !deactivationPinNotSet() { + args = append(args, fmt.Sprintf("--pin=%d", cdDeactivationPin)) + } + cmd := exec.Command(bin, args...) + cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} + if err := cmd.Start(); err != nil { + logger.Fatal().Err(err).Msg("could not start self uninstall command") + } + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + logger.Warn().Msgf("service was uninstalled because device %q does not exist", cdUID) + _ = cmd.Wait() + os.Exit(0) + } +} + +func selfUninstallLinux(err error, p *prog, logger zerolog.Logger) { + if uninstallIfInvalidCdUID(err, p, logger) { + logger.Warn().Msgf("service was uninstalled because device %q does not exist", cdUID) + } +}