mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-02-03 22:18:39 +00:00
all: initial support for setup linux router
Wiring code to configure router when running ctrld. Future commits will add implementation for each supported platforms.
This commit is contained in:
committed by
Cuong Manh Le
parent
0043fdf859
commit
4b6a976747
@@ -18,9 +18,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/fsnotify/fsnotify"
|
||||
|
||||
"github.com/cuonglm/osinfo"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/go-playground/validator/v10"
|
||||
"github.com/kardianos/service"
|
||||
"github.com/miekg/dns"
|
||||
@@ -33,6 +32,7 @@ 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"
|
||||
)
|
||||
|
||||
const selfCheckFQDN = "verify.controld.com"
|
||||
@@ -200,6 +200,18 @@ func initCLI() {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if runtime.GOOS == "linux" && onRouter {
|
||||
mainLog.Debug().Msg("Router setup")
|
||||
err := router.Configure(&cfg)
|
||||
if errors.Is(err, router.ErrNotSupported) {
|
||||
unsupportedPlatformHelp(cmd)
|
||||
os.Exit(1)
|
||||
}
|
||||
if err != nil {
|
||||
mainLog.Fatal().Err(err).Msg("failed to configure router")
|
||||
}
|
||||
}
|
||||
|
||||
close(waitCh)
|
||||
<-stopCh
|
||||
},
|
||||
@@ -218,6 +230,8 @@ func initCLI() {
|
||||
_ = runCmd.Flags().MarkHidden("homedir")
|
||||
runCmd.Flags().StringVarP(&iface, "iface", "", "", `Update DNS setting for iface, "auto" means the default interface gateway`)
|
||||
_ = runCmd.Flags().MarkHidden("iface")
|
||||
runCmd.Flags().BoolVarP(&onRouter, "router", "", false, `Configure onRouter for running ctrld`)
|
||||
_ = runCmd.Flags().MarkHidden("router")
|
||||
|
||||
rootCmd.AddCommand(runCmd)
|
||||
|
||||
@@ -315,6 +329,8 @@ func initCLI() {
|
||||
startCmd.Flags().IntVarP(&cacheSize, "cache_size", "", 0, "Enable cache with size items")
|
||||
startCmd.Flags().StringVarP(&cdUID, "cd", "", "", "Control D resolver uid")
|
||||
startCmd.Flags().StringVarP(&iface, "iface", "", "", `Update DNS setting for iface, "auto" means the default interface gateway`)
|
||||
startCmd.Flags().BoolVarP(&onRouter, "router", "", false, `Configure onRouter for running ctrld`)
|
||||
_ = startCmd.Flags().MarkHidden("router")
|
||||
|
||||
stopCmd := &cobra.Command{
|
||||
PreRun: checkHasElevatedPrivilege,
|
||||
@@ -510,11 +526,6 @@ NOTE: Uninstalling will set DNS to values provided by DHCP.`,
|
||||
stopCmdAlias.Flags().StringVarP(&ifaceStartStop, "iface", "", "auto", `Reset DNS setting for iface, "auto" means the default interface gateway`)
|
||||
stopCmdAlias.Flags().AddFlagSet(stopCmd.Flags())
|
||||
rootCmd.AddCommand(stopCmdAlias)
|
||||
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
stderrMsg(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func writeConfigFile() error {
|
||||
@@ -802,3 +813,7 @@ func selfCheckStatus(status service.Status) service.Status {
|
||||
mainLog.Debug().Msgf("self-check against %q failed", selfCheckFQDN)
|
||||
return service.StatusUnknown
|
||||
}
|
||||
|
||||
func unsupportedPlatformHelp(cmd *cobra.Command) {
|
||||
cmd.PrintErrln("Unsupported or incorrectly chosen onRouter platform. Please open an issue and provide all relevant information: https://github.com/Control-D-Inc/ctrld/issues/new")
|
||||
}
|
||||
|
||||
70
cmd/ctrld/cli_router_linux.go
Normal file
70
cmd/ctrld/cli_router_linux.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/Control-D-Inc/ctrld/internal/router"
|
||||
)
|
||||
|
||||
func initRouterCLI() {
|
||||
validArgs := append(router.SupportedPlatforms(), "auto")
|
||||
var b strings.Builder
|
||||
b.WriteString("Auto-setup Control D on a onRouter.\n\nSupported platforms:\n\n")
|
||||
for _, arg := range validArgs {
|
||||
b.WriteString(" ₒ ")
|
||||
b.WriteString(arg)
|
||||
if arg == "auto" {
|
||||
b.WriteString(" - detect the platform you are running on")
|
||||
}
|
||||
b.WriteString("\n")
|
||||
}
|
||||
|
||||
routerCmd := &cobra.Command{
|
||||
Use: "setup",
|
||||
Short: b.String(),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(args) == 0 {
|
||||
_ = cmd.Help()
|
||||
return
|
||||
}
|
||||
if len(args) != 1 {
|
||||
_ = cmd.Help()
|
||||
return
|
||||
}
|
||||
platform := args[0]
|
||||
if platform == "auto" {
|
||||
platform = router.Name()
|
||||
}
|
||||
switch platform {
|
||||
case router.DDWrt, router.Merlin, router.OpenWrt, router.Ubios:
|
||||
default:
|
||||
unsupportedPlatformHelp(cmd)
|
||||
}
|
||||
exe, err := os.Executable()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
cmdArgs := []string{"start"}
|
||||
cmdArgs = append(cmdArgs, os.Args[3:]...)
|
||||
cmdArgs = append(cmdArgs, "--router=true")
|
||||
command := exec.Command(exe, cmdArgs...)
|
||||
command.Stdout = os.Stdout
|
||||
command.Stderr = os.Stderr
|
||||
command.Stdin = os.Stdin
|
||||
if err := command.Run(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
tmpl := routerCmd.UsageTemplate()
|
||||
tmpl = strings.Replace(tmpl, "{{.UseLine}}", "{{.UseLine}} [platform]", 1)
|
||||
routerCmd.SetUsageTemplate(tmpl)
|
||||
rootCmd.AddCommand(routerCmd)
|
||||
}
|
||||
5
cmd/ctrld/cli_router_others.go
Normal file
5
cmd/ctrld/cli_router_others.go
Normal file
@@ -0,0 +1,5 @@
|
||||
//go:build !linux
|
||||
|
||||
package main
|
||||
|
||||
func initRouterCLI() {}
|
||||
@@ -26,18 +26,22 @@ var (
|
||||
cacheSize int
|
||||
cfg ctrld.Config
|
||||
verbose int
|
||||
cdUID string
|
||||
iface string
|
||||
ifaceStartStop string
|
||||
onRouter bool
|
||||
|
||||
rootLogger = zerolog.New(io.Discard)
|
||||
mainLog = rootLogger
|
||||
|
||||
cdUID string
|
||||
iface string
|
||||
ifaceStartStop string
|
||||
mainLog = zerolog.New(io.Discard)
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctrld.InitConfig(v, "ctrld")
|
||||
initCLI()
|
||||
initRouterCLI()
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
stderrMsg(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func normalizeLogFilePath(logFilePath string) string {
|
||||
|
||||
86
internal/router/router.go
Normal file
86
internal/router/router.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/Control-D-Inc/ctrld"
|
||||
)
|
||||
|
||||
const (
|
||||
OpenWrt = "openwrt"
|
||||
DDWrt = "ddwrt"
|
||||
Merlin = "merlin"
|
||||
Ubios = "ubios"
|
||||
)
|
||||
|
||||
// ErrNotSupported reports the current router is not supported error.
|
||||
var ErrNotSupported = errors.New("unsupported platform")
|
||||
|
||||
var routerAtomic atomic.Pointer[router]
|
||||
|
||||
type router struct {
|
||||
name string
|
||||
}
|
||||
|
||||
// SupportedPlatforms return all platforms that can be configured to run with ctrld.
|
||||
func SupportedPlatforms() []string {
|
||||
return []string{DDWrt, Merlin, OpenWrt, Ubios}
|
||||
}
|
||||
|
||||
// Configure change the given *ctrld.Config for running on the router.
|
||||
func Configure(c *ctrld.Config) error {
|
||||
name := Name()
|
||||
switch name {
|
||||
case DDWrt, Merlin, OpenWrt, Ubios:
|
||||
default:
|
||||
return ErrNotSupported
|
||||
}
|
||||
// TODO: implement all supported platforms.
|
||||
fmt.Printf("Configuring router for: %s\n", name)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Name returns name of the router platform.
|
||||
func Name() string {
|
||||
if r := routerAtomic.Load(); r != nil {
|
||||
return r.name
|
||||
}
|
||||
r := &router{}
|
||||
r.name = distroName()
|
||||
routerAtomic.Store(r)
|
||||
return r.name
|
||||
}
|
||||
|
||||
func distroName() string {
|
||||
switch {
|
||||
case bytes.HasPrefix(uname(), []byte("DD-WRT")):
|
||||
return DDWrt
|
||||
case bytes.HasPrefix(uname(), []byte("ASUSWRT-Merlin")):
|
||||
return Merlin
|
||||
case haveFile("/etc/openwrt_version"):
|
||||
return OpenWrt
|
||||
case haveDir("/data/unifi"):
|
||||
return Ubios
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func haveFile(file string) bool {
|
||||
_, err := os.Stat(file)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func haveDir(dir string) bool {
|
||||
fi, _ := os.Stat(dir)
|
||||
return fi != nil && fi.IsDir()
|
||||
}
|
||||
|
||||
func uname() []byte {
|
||||
out, _ := exec.Command("uname", "-o").Output()
|
||||
return out
|
||||
}
|
||||
Reference in New Issue
Block a user