Removing router platforms support

This commit is contained in:
Cuong Manh Le
2025-06-30 22:00:03 +07:00
committed by Cuong Manh Le
parent b2a54db4b5
commit 2e63624f6c
46 changed files with 31 additions and 4724 deletions
+8 -70
View File
@@ -40,7 +40,6 @@ import (
"github.com/Control-D-Inc/ctrld"
"github.com/Control-D-Inc/ctrld/internal/controld"
ctrldnet "github.com/Control-D-Inc/ctrld/internal/net"
"github.com/Control-D-Inc/ctrld/internal/router"
)
// selfCheckInternalTestDomain is used for testing ctrld self response to clients.
@@ -290,21 +289,12 @@ func run(appCallback *AppCallback, stopCh chan struct{}) {
p.Fatal().Msg("network is not up yet")
}
p.router = router.New(&cfg, cdUID != "")
cs, err := newControlServer(filepath.Join(sockDir, ControlSocketName()))
if err != nil {
p.Warn().Err(err).Msg("could not create control server")
}
p.cs = cs
// Processing --cd flag require connecting to ControlD API, which needs valid
// time for validating server certificate. Some routers need NTP synchronization
// to set the current time, so this check must happen before processCDFlags.
if err := p.router.PreRun(); err != nil {
notifyExitToLogServer()
p.Fatal().Err(err).Msg("failed to perform router pre-run check")
}
oldLogPath := cfg.Service.LogPath
if uid := cdUIDFromProvToken(); uid != "" {
cdUID = uid
@@ -413,25 +403,6 @@ func run(appCallback *AppCallback, stopCh chan struct{}) {
}
}
})
if platform := router.Name(); platform != "" {
if cp := router.CertPool(); cp != nil {
rootCertPool = cp
}
if iface != "" {
p.onStarted = append(p.onStarted, func() {
p.Debug().Msg("router setup on start")
if err := p.router.Setup(); err != nil {
p.Error().Err(err).Msg("could not configure router")
}
})
p.onStopped = append(p.onStopped, func() {
p.Debug().Msg("router cleanup on stop")
if err := p.router.Cleanup(); err != nil {
p.Error().Err(err).Msg("could not cleanup router")
}
})
}
}
p.onStopped = append(p.onStopped, func() {
// restore static DNS settings or DHCP
p.resetDNS(false, true)
@@ -809,9 +780,6 @@ func netInterface(ifaceName string) (*net.Interface, error) {
}
func defaultIfaceName() string {
if ifaceName := router.DefaultInterfaceName(); ifaceName != "" {
return ifaceName
}
dri, err := netmon.DefaultRouteInterface()
if err != nil {
// On WSL 1, the route table does not have any default route. But the fact that
@@ -962,13 +930,6 @@ func selfCheckResolveDomain(ctx context.Context, addr, scope string, domain stri
}
func userHomeDir() (string, error) {
dir, err := router.HomeDir()
if err != nil {
return "", err
}
if dir != "" {
return dir, nil
}
// Mobile platform should provide a rw dir path for this.
if isMobile() {
return homedir, nil
@@ -1051,13 +1012,6 @@ func uninstall(p *prog, s service.Service) {
}
initInteractiveLogging()
if doTasks(tasks) {
if err := p.router.ConfigureService(svcConfig); err != nil {
mainLog.Load().Fatal().Err(err).Msg("could not configure service")
}
if err := p.router.Uninstall(svcConfig); err != nil {
mainLog.Load().Warn().Err(err).Msg("post uninstallation failed, please check system/service log for details error")
return
}
// restore static DNS settings or DHCP
p.resetDNS(false, true)
@@ -1078,12 +1032,6 @@ func uninstall(p *prog, s service.Service) {
return nil
})
if router.Name() != "" {
mainLog.Load().Debug().Msg("Router cleanup")
}
// Stop already did router.Cleanup and report any error if happens,
// ignoring error here to prevent false positive.
_ = p.router.Cleanup()
mainLog.Load().Notice().Msg("Service uninstalled")
return
}
@@ -1201,7 +1149,6 @@ func tryUpdateListenerConfig(cfg *ctrld.Config, notifyFunc func(), fatal bool) (
nextdnsMode := nextdns != ""
// For Windows server with local Dns server running, we can only try on random local IP.
hasLocalDnsServer := hasLocalDnsServerRunning()
notRouter := router.Name() == ""
isDesktop := ctrld.IsDesktopPlatform()
for n, listener := range cfg.Listener {
lcc[n] = &listenerConfigCheck{}
@@ -1309,21 +1256,19 @@ func tryUpdateListenerConfig(cfg *ctrld.Config, notifyFunc func(), fatal bool) (
// On firewalla, we don't need to check localhost, because the lo interface is excluded in dnsmasq
// config, so we can always listen on localhost port 53, but no traffic could be routed there.
tryLocalhost := !isLoopback(listener.IP) && router.CanListenLocalhost()
tryLocalhost := !isLoopback(listener.IP)
tryAllPort53 := true
tryOldIPPort5354 := true
tryPort5354 := true
// We should not try to listen on any port other than 53,
// if we do, this will break the dns resolution for the system.
// TODO: cleanup these codes when refactoring this function.
tryOldIPPort5354 := false
tryPort5354 := false
if hasLocalDnsServer {
tryAllPort53 = false
tryOldIPPort5354 = false
tryPort5354 = false
}
// if not running on a router, we should not try to listen on any port other than 53
// if we do, this will break the dns resolution for the system.
if notRouter {
tryOldIPPort5354 = false
tryPort5354 = false
}
attempts := 0
maxAttempts := 10
for {
@@ -1400,9 +1345,7 @@ func tryUpdateListenerConfig(cfg *ctrld.Config, notifyFunc func(), fatal bool) (
} else {
listener.IP = oldIP
}
// if we are not running on a router, we should not try to listen on any port other than 53
// if we do, this will break the dns resolution for the system.
if check.Port && !notRouter {
if check.Port {
listener.Port = randomPort()
} else {
listener.Port = oldPort
@@ -1738,11 +1681,6 @@ func exchangeContextWithTimeout(c *dns.Client, timeout time.Duration, msg *dns.M
return c.ExchangeContext(ctx, msg, addr)
}
// runInCdMode reports whether ctrld service is running in cd mode.
func runInCdMode() bool {
return curCdUID() != ""
}
// curCdUID returns the current ControlD UID used by running ctrld process.
func curCdUID() string {
if s, _ := newService(&prog{}, svcConfig); s != nil {
+11 -116
View File
@@ -23,11 +23,9 @@ import (
"github.com/minio/selfupdate"
"github.com/olekukonko/tablewriter"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/Control-D-Inc/ctrld"
"github.com/Control-D-Inc/ctrld/internal/clientinfo"
"github.com/Control-D-Inc/ctrld/internal/router"
)
// dialSocketControlServerTimeout is the default timeout to wait when ping control server.
@@ -47,7 +45,7 @@ func initLogCmd() *cobra.Command {
},
Run: func(cmd *cobra.Command, args []string) {
p := &prog{router: router.New(&cfg, false)}
p := &prog{}
s, _ := newService(p, svcConfig)
status, err := s.Status()
@@ -100,7 +98,7 @@ func initLogCmd() *cobra.Command {
},
Run: func(cmd *cobra.Command, args []string) {
p := &prog{router: router.New(&cfg, false)}
p := &prog{}
s, _ := newService(p, svcConfig)
status, err := s.Status()
@@ -225,10 +223,7 @@ NOTE: running "ctrld start" without any arguments will start already installed c
setDependencies(sc)
sc.Arguments = append([]string{"run"}, osArgs...)
p := &prog{
router: router.New(&cfg, cdUID != ""),
cfg: &cfg,
}
p := &prog{cfg: &cfg}
s, err := newService(p, sc)
if err != nil {
mainLog.Load().Error().Msg(err.Error())
@@ -400,10 +395,6 @@ NOTE: running "ctrld start" without any arguments will start already installed c
validateCdUpstreamProtocol()
}
if err := p.router.ConfigureService(sc); err != nil {
mainLog.Load().Fatal().Err(err).Msg("failed to configure service on router")
}
if configPath != "" {
v.SetConfigFile(configPath)
}
@@ -427,11 +418,6 @@ NOTE: running "ctrld start" without any arguments will start already installed c
sc.Arguments = append(sc.Arguments, "--config="+defaultConfigFile)
}
if router.Name() != "" && iface != "" {
mainLog.Load().Debug().Msg("cleaning up router before installing")
_ = p.router.Cleanup()
}
tasks := []task{
{s.Stop, false, "Stop"},
{func() error { return doGenerateNextDNSConfig(nextdns) }, true, "Checking config"},
@@ -458,11 +444,6 @@ NOTE: running "ctrld start" without any arguments will start already installed c
}
mainLog.Load().Notice().Msg("Starting service")
if doTasks(tasks) {
if err := p.router.Install(sc); err != nil {
mainLog.Load().Warn().Err(err).Msg("post installation failed, please check system/service log for details error")
return
}
// add a small delay to ensure the service is started and did not crash
time.Sleep(1 * time.Second)
@@ -529,33 +510,6 @@ NOTE: running "ctrld start" without any arguments will start already installed c
startCmd.Flags().BoolVarP(&startOnly, "start_only", "", false, "Do not install new service")
_ = startCmd.Flags().MarkHidden("start_only")
routerCmd := &cobra.Command{
Use: "setup",
Run: func(cmd *cobra.Command, _ []string) {
exe, err := os.Executable()
if err != nil {
mainLog.Load().Fatal().Msgf("could not find executable path: %v", err)
os.Exit(1)
}
flags := make([]string, 0)
cmd.Flags().Visit(func(flag *pflag.Flag) {
flags = append(flags, fmt.Sprintf("--%s=%s", flag.Name, flag.Value))
})
cmdArgs := []string{"start"}
cmdArgs = append(cmdArgs, flags...)
command := exec.Command(exe, cmdArgs...)
command.Stdout = os.Stdout
command.Stderr = os.Stderr
command.Stdin = os.Stdin
if err := command.Run(); err != nil {
mainLog.Load().Fatal().Msg(err.Error())
}
},
}
routerCmd.Flags().AddFlagSet(startCmd.Flags())
routerCmd.Hidden = true
rootCmd.AddCommand(routerCmd)
startCmdAlias := &cobra.Command{
PreRun: func(cmd *cobra.Command, args []string) {
checkHasElevatedPrivilege()
@@ -601,7 +555,7 @@ func initStopCmd() *cobra.Command {
Run: func(cmd *cobra.Command, args []string) {
readConfig(false)
v.Unmarshal(&cfg)
p := &prog{router: router.New(&cfg, runInCdMode())}
p := &prog{}
s, err := newService(p, svcConfig)
if err != nil {
mainLog.Load().Error().Msg(err.Error())
@@ -629,23 +583,6 @@ func initStopCmd() *cobra.Command {
os.Exit(deactivationPinInvalidExitCode)
}
if doTasks([]task{{s.Stop, true, "Stop"}}) {
if router.WaitProcessExited() {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
for {
select {
case <-ctx.Done():
mainLog.Load().Error().Msg("timeout while waiting for service to stop")
return
default:
}
time.Sleep(time.Second)
if status, _ := s.Status(); status == service.StatusStopped {
break
}
}
}
mainLog.Load().Notice().Msg("Service stopped")
}
},
@@ -689,7 +626,7 @@ func initRestartCmd() *cobra.Command {
cdUID = curCdUID()
cdMode := cdUID != ""
p := &prog{router: router.New(&cfg, cdMode)}
p := &prog{}
s, err := newService(p, svcConfig)
if err != nil {
mainLog.Load().Error().Msg(err.Error())
@@ -723,7 +660,6 @@ func initRestartCmd() *cobra.Command {
tasks := []task{
{s.Stop, true, "Stop"},
{func() error {
p.router.Cleanup()
// restore static DNS settings or DHCP
p.resetDNS(false, true)
return nil
@@ -733,27 +669,7 @@ func initRestartCmd() *cobra.Command {
return nil
}, false, "Waiting for service to stop"},
}
if doTasks(tasks) {
if router.WaitProcessExited() {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
loop:
for {
select {
case <-ctx.Done():
mainLog.Load().Error().Msg("timeout while waiting for service to stop")
break loop
default:
}
time.Sleep(time.Second)
if status, _ := s.Status(); status == service.StatusStopped {
break
}
}
}
} else {
if !doTasks(tasks) {
return false
}
@@ -814,7 +730,7 @@ func initReloadCmd(restartCmd *cobra.Command) *cobra.Command {
Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
p := &prog{router: router.New(&cfg, false)}
p := &prog{}
s, _ := newService(p, svcConfig)
status, err := s.Status()
@@ -939,7 +855,7 @@ NOTE: Uninstalling will set DNS to values provided by DHCP.`,
Run: func(cmd *cobra.Command, args []string) {
readConfig(false)
v.Unmarshal(&cfg)
p := &prog{router: router.New(&cfg, runInCdMode())}
p := &prog{}
s, err := newService(p, svcConfig)
if err != nil {
mainLog.Load().Error().Msg(err.Error())
@@ -1115,7 +1031,7 @@ func initClientsCmd() *cobra.Command {
},
Run: func(cmd *cobra.Command, args []string) {
p := &prog{router: router.New(&cfg, false)}
p := &prog{}
s, _ := newService(p, svcConfig)
status, err := s.Status()
@@ -1228,7 +1144,7 @@ func initUpgradeCmd() *cobra.Command {
sc.Executable = bin
readConfig(false)
v.Unmarshal(&cfg)
p := &prog{router: router.New(&cfg, runInCdMode())}
p := &prog{}
s, err := newService(p, sc)
if err != nil {
mainLog.Load().Error().Msg(err.Error())
@@ -1285,7 +1201,6 @@ func initUpgradeCmd() *cobra.Command {
tasks := []task{
{s.Stop, true, "Stop"},
{func() error {
p.router.Cleanup()
// restore static DNS settings or DHCP
p.resetDNS(false, true)
return nil
@@ -1295,27 +1210,7 @@ func initUpgradeCmd() *cobra.Command {
return nil
}, false, "Waiting for service to stop"},
}
if doTasks(tasks) {
if router.WaitProcessExited() {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
loop:
for {
select {
case <-ctx.Done():
mainLog.Load().Error().Msg("timeout while waiting for service to stop")
break loop
default:
}
time.Sleep(time.Second)
if status, _ := s.Status(); status == service.StatusStopped {
break
}
}
}
}
doTasks(tasks)
tasks = []task{
{s.Start, true, "Start"},
+1 -5
View File
@@ -25,7 +25,6 @@ import (
"github.com/Control-D-Inc/ctrld/internal/controld"
"github.com/Control-D-Inc/ctrld/internal/dnscache"
ctrldnet "github.com/Control-D-Inc/ctrld/internal/net"
"github.com/Control-D-Inc/ctrld/internal/router"
)
const (
@@ -1405,10 +1404,7 @@ func (p *prog) monitorNetworkChanges(ctx context.Context) error {
}
p.Debug().Msgf("Set default local IPv4: %s, IPv6: %s", selfIP, ipv6)
// we only trigger recovery flow for network changes on non router devices
if router.Name() == "" {
p.handleRecovery(RecoveryReasonNetworkChange)
}
p.handleRecovery(RecoveryReasonNetworkChange)
})
mon.Start()
+1 -16
View File
@@ -34,8 +34,6 @@ import (
"github.com/Control-D-Inc/ctrld/internal/clientinfo"
"github.com/Control-D-Inc/ctrld/internal/controld"
"github.com/Control-D-Inc/ctrld/internal/dnscache"
"github.com/Control-D-Inc/ctrld/internal/router"
"github.com/Control-D-Inc/ctrld/internal/router/dnsmasq"
)
const (
@@ -120,7 +118,6 @@ type prog struct {
sema semaphore
ciTable *clientinfo.Table
um *upstreamMonitor
router router.Router
ptrLoopGuard *loopGuard
lanLoopGuard *loopGuard
metricsQueryStats atomic.Bool
@@ -612,12 +609,6 @@ func (p *prog) setupClientInfoDiscover() {
format := ctrld.LeaseFileFormat(p.cfg.Service.DHCPLeaseFileFormat)
p.ciTable.AddLeaseFile(leaseFile, format)
}
if leaseFiles := dnsmasq.AdditionalLeaseFiles(); len(leaseFiles) > 0 {
mainLog.Load().Debug().Msgf("watching additional lease files: %v", leaseFiles)
for _, leaseFile := range leaseFiles {
p.ciTable.AddLeaseFile(leaseFile, ctrld.Dnsmasq)
}
}
}
// runClientInfoDiscover runs the client info discover.
@@ -724,9 +715,6 @@ func (p *prog) setDNS() {
ns = "127.0.0.1"
case lc.Port != 53:
ns = "127.0.0.1"
if resolver := router.LocalResolverIP(); resolver != "" {
ns = resolver
}
default:
// If we ever reach here, it means ctrld is running on lc.IP port 53,
// so we could just use lc.IP as nameserver.
@@ -1493,10 +1481,7 @@ func (p *prog) leakOnUpstreamFailure() bool {
if ptr := p.cfg.Service.LeakOnUpstreamFailure; ptr != nil {
return *ptr
}
// Default is false on routers, since this leaking is only useful for devices that move between networks.
if router.Name() != "" {
return false
}
// if we are running on ADDC, we should not leak on upstream failure
if p.runningOnDomainController {
return false
-5
View File
@@ -9,8 +9,6 @@ import (
"strings"
"github.com/kardianos/service"
"github.com/Control-D-Inc/ctrld/internal/router"
)
func init() {
@@ -37,9 +35,6 @@ func setDependencies(svc *service.Config) {
svc.Dependencies = append(svc.Dependencies, "Wants=systemd-networkd-wait-online.service")
}
}
if routerDeps := router.ServiceDependencies(); len(routerDeps) > 0 {
svc.Dependencies = append(svc.Dependencies, routerDeps...)
}
}
func setWorkingDirectory(svc *service.Config, dir string) {
+1 -46
View File
@@ -11,9 +11,6 @@ import (
"github.com/coreos/go-systemd/v22/unit"
"github.com/kardianos/service"
"github.com/Control-D-Inc/ctrld/internal/router"
"github.com/Control-D-Inc/ctrld/internal/router/openwrt"
)
// newService wraps service.New call to return service.Service
@@ -24,10 +21,6 @@ func newService(i service.Interface, c *service.Config) (service.Service, error)
return nil, err
}
switch {
case router.IsOldOpenwrt(), router.IsNetGearOrbi():
return &procd{sysV: &sysV{s}, svcConfig: c}, nil
case router.IsGLiNet():
return &sysV{s}, nil
case s.Platform() == "unix-systemv":
return &sysV{s}, nil
case s.Platform() == "linux-systemd":
@@ -42,7 +35,7 @@ func newService(i service.Interface, c *service.Config) (service.Service, error)
// sysV wraps a service.Service, and provide start/stop/status command
// base on "/etc/init.d/<service_name>".
//
// Use this on system where "service" command is not available, like GL.iNET router.
// Use this on system where "service" command is not available.
type sysV struct {
service.Service
}
@@ -89,37 +82,6 @@ func (s *sysV) Status() (service.Status, error) {
return unixSystemVServiceStatus()
}
// procd wraps a service.Service, and provide start/stop command
// base on "/etc/init.d/<service_name>", status command base on parsing "ps" command output.
//
// Use this on system where "/etc/init.d/<service_name> status" command is not available,
// like old GL.iNET Opal router.
type procd struct {
*sysV
svcConfig *service.Config
}
func (s *procd) Status() (service.Status, error) {
if !s.installed() {
return service.StatusUnknown, service.ErrNotInstalled
}
bin := s.svcConfig.Executable
if bin == "" {
exe, err := os.Executable()
if err != nil {
return service.StatusUnknown, nil
}
bin = exe
}
// Looking for something like "/sbin/ctrld run ".
shellCmd := fmt.Sprintf("ps | grep -q %q", bin+" [r]un ")
if err := exec.Command("sh", "-c", shellCmd).Run(); err != nil {
return service.StatusStopped, nil
}
return service.StatusRunning, nil
}
// systemd wraps a service.Service, and provide status command to
// report the status correctly.
type systemd struct {
@@ -249,13 +211,6 @@ func checkHasElevatedPrivilege() {
func unixSystemVServiceStatus() (service.Status, error) {
out, err := exec.Command("/etc/init.d/ctrld", "status").CombinedOutput()
if err != nil {
// Specific case for openwrt >= 24.10, it returns non-success code
// for above status command, which may not right.
if router.Name() == openwrt.Name {
if string(bytes.ToLower(bytes.TrimSpace(out))) == "inactive" {
return service.StatusStopped, nil
}
}
return service.StatusUnknown, nil
}