all: implement router setup for ddwrt

This commit is contained in:
Cuong Manh Le
2023-03-30 01:41:30 +07:00
committed by Cuong Manh Le
parent c94be0df35
commit 8a2cdbfaa3
18 changed files with 4001 additions and 36 deletions
+53 -12
View File
@@ -3,6 +3,7 @@ package main
import (
"bytes"
"context"
"crypto/x509"
"encoding/base64"
"errors"
"fmt"
@@ -30,6 +31,7 @@ import (
"tailscale.com/net/interfaces"
"github.com/Control-D-Inc/ctrld"
"github.com/Control-D-Inc/ctrld/internal/certs"
"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"
@@ -46,6 +48,7 @@ var (
v = viper.NewWithOptions(viper.KeyDelimiter("::"))
defaultConfigWritten = false
defaultConfigFile = "ctrld.toml"
rootCertPool *x509.CertPool
)
var basicModeFlags = []string{"listen", "primary_upstream", "secondary_upstream", "domains"}
@@ -146,8 +149,13 @@ func initCLI() {
{"config", false},
{"ctrld", writeDefaultConfig},
}
dir, err := userHomeDir()
if err != nil {
log.Fatalf("failed to get config dir: %v", dir)
}
for _, config := range configs {
ctrld.SetConfigName(v, config.name)
ctrld.SetConfigNameWithPath(v, config.name, dir)
v.SetConfigFile(configPath)
if readConfigFile(config.written) {
break
@@ -200,15 +208,21 @@ func initCLI() {
os.Exit(0)
}
if router.Name() != "" {
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")
if setupRouter {
switch platform := router.Name(); {
case platform == router.DDWrt:
rootCertPool = certs.CACertPool()
fallthrough
case platform != "":
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")
}
}
}
@@ -230,6 +244,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(&setupRouter, "router", "", false, `setup for running on router platforms`)
_ = runCmd.Flags().MarkHidden("router")
rootCmd.AddCommand(runCmd)
@@ -247,7 +263,9 @@ func initCLI() {
}
setDependencies(sc)
sc.Arguments = append([]string{"run"}, osArgs...)
router.ConfigureService(sc)
if err := router.ConfigureService(sc); err != nil {
log.Fatal(err)
}
// No config path, generating config in HOME directory.
noConfigStart := isNoConfigStart(cmd)
@@ -255,7 +273,7 @@ func initCLI() {
if configPath != "" {
v.SetConfigFile(configPath)
}
if dir, err := os.UserHomeDir(); err == nil {
if dir, err := userHomeDir(); err == nil {
setWorkingDirectory(sc, dir)
if configPath == "" && writeDefaultConfig {
defaultConfigFile = filepath.Join(dir, defaultConfigFile)
@@ -332,6 +350,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(&setupRouter, "router", "", false, `setup for running on router platforms`)
_ = startCmd.Flags().MarkHidden("router")
stopCmd := &cobra.Command{
PreRun: checkHasElevatedPrivilege,
@@ -430,6 +450,7 @@ NOTE: Uninstalling will set DNS to values provided by DHCP.`,
iface = "auto"
}
prog.resetDNS()
mainLog.Debug().Msg("Router cleanup")
if err := router.Cleanup(); err != nil {
mainLog.Warn().Err(err).Msg("could not cleanup router")
}
@@ -821,3 +842,23 @@ func selfCheckStatus(status service.Status) service.Status {
func unsupportedPlatformHelp(cmd *cobra.Command) {
cmd.PrintErrln("Unsupported or incorrectly chosen router platform. Please open an issue and provide all relevant information: https://github.com/Control-D-Inc/ctrld/issues/new")
}
func userHomeDir() (string, error) {
switch router.Name() {
case router.DDWrt, router.Merlin:
exe, err := os.Executable()
if err != nil {
return "", err
}
return filepath.Dir(exe), nil
}
// viper will expand for us.
if runtime.GOOS == "windows" {
return os.UserHomeDir()
}
dir := "/etc/controld"
if err := os.MkdirAll(dir, 0750); err != nil {
return "", err
}
return dir, nil
}
+1
View File
@@ -53,6 +53,7 @@ func initRouterCLI() {
cmdArgs := []string{"start"}
cmdArgs = append(cmdArgs, osArgs(platform)...)
cmdArgs = append(cmdArgs, "--router")
command := exec.Command(exe, cmdArgs...)
command.Stdout = os.Stdout
command.Stderr = os.Stderr
+2 -1
View File
@@ -29,6 +29,7 @@ var (
cdUID string
iface string
ifaceStartStop string
setupRouter bool
mainLog = zerolog.New(io.Discard)
)
@@ -50,7 +51,7 @@ func normalizeLogFilePath(logFilePath string) string {
if homedir != "" {
return filepath.Join(homedir, logFilePath)
}
dir, _ := os.UserHomeDir()
dir, _ := userHomeDir()
if dir == "" {
return logFilePath
}
+10
View File
@@ -14,6 +14,7 @@ import (
"github.com/Control-D-Inc/ctrld"
"github.com/Control-D-Inc/ctrld/internal/dnscache"
"github.com/Control-D-Inc/ctrld/internal/router"
)
var logf = func(format string, args ...any) {
@@ -77,6 +78,7 @@ func (p *prog) run() {
} else {
mainLog.Info().Str("bootstrap_ip", uc.BootstrapIP).Msgf("Using bootstrap IP for upstream.%s", n)
}
uc.SetCertPool(rootCertPool)
uc.SetupTransport()
}
@@ -165,6 +167,10 @@ func (p *prog) deAllocateIP() error {
}
func (p *prog) setDNS() {
// On router, ctrld run as a DNS provider, it does not have to change system DNS.
if router.Name() != "" {
return
}
if cfg.Listener == nil || cfg.Listener["0"] == nil {
return
}
@@ -193,6 +199,10 @@ func (p *prog) setDNS() {
}
func (p *prog) resetDNS() {
// See comment in p.setDNS method.
if router.Name() != "" {
return
}
if iface == "" {
return
}
+4 -1
View File
@@ -2,6 +2,7 @@ package main
import (
"bytes"
"errors"
"fmt"
"os"
"os/exec"
@@ -24,12 +25,14 @@ type task struct {
}
func doTasks(tasks []task) bool {
var prevErr error
for _, task := range tasks {
if err := task.f(); err != nil {
if task.abortOnError {
stderrMsg(err.Error())
stderrMsg(errors.Join(prevErr, err).Error())
return false
}
prevErr = err
}
}
return true