mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-05-27 12:52:27 +02:00
feat: capitalize all log messages for better readability
Capitalize the first letter of all log messages throughout the codebase to improve readability and consistency in logging output. Key improvements: - All log messages now start with capital letters - Consistent formatting across all logging statements - Improved readability for debugging and monitoring - Enhanced user experience with better formatted messages Files updated: - CLI commands and service management - Internal client information discovery - Network operations and configuration - DNS resolver and proxy operations - Platform-specific implementations This completes the final phase of the logging improvement project, ensuring all log messages follow consistent capitalization standards for better readability and professional appearance.
This commit is contained in:
committed by
Cuong Manh Le
parent
166b7f38fc
commit
d3b01dc7e8
@@ -16,11 +16,11 @@ import (
|
|||||||
func addExtraSplitDnsRule(cfg *ctrld.Config) bool {
|
func addExtraSplitDnsRule(cfg *ctrld.Config) bool {
|
||||||
domain, err := getActiveDirectoryDomain()
|
domain, err := getActiveDirectoryDomain()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Debug().Msgf("unable to get active directory domain: %v", err)
|
mainLog.Load().Debug().Msgf("Unable to get active directory domain: %v", err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if domain == "" {
|
if domain == "" {
|
||||||
mainLog.Load().Debug().Msg("no active directory domain found")
|
mainLog.Load().Debug().Msg("No active directory domain found")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// Network rules are lowercase during toml config marshaling,
|
// Network rules are lowercase during toml config marshaling,
|
||||||
@@ -40,11 +40,11 @@ func addSplitDnsRule(cfg *ctrld.Config, domain string) bool {
|
|||||||
}
|
}
|
||||||
for _, rule := range lc.Policy.Rules {
|
for _, rule := range lc.Policy.Rules {
|
||||||
if _, ok := rule[domain]; ok {
|
if _, ok := rule[domain]; ok {
|
||||||
mainLog.Load().Debug().Msgf("split-rule %q already existed for listener.%s", domain, n)
|
mainLog.Load().Debug().Msgf("Split-rule %q already existed for listener.%s", domain, n)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mainLog.Load().Debug().Msgf("adding split-rule %q for listener.%s", domain, n)
|
mainLog.Load().Debug().Msgf("Adding split-rule %q for listener.%s", domain, n)
|
||||||
lc.Policy.Rules = append(lc.Policy.Rules, ctrld.Rule{domain: []string{}})
|
lc.Policy.Rules = append(lc.Policy.Rules, ctrld.Rule{domain: []string{}})
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|||||||
+68
-67
@@ -241,11 +241,11 @@ func run(appCallback *AppCallback, stopCh chan struct{}) {
|
|||||||
p.logConn = lc
|
p.logConn = lc
|
||||||
} else {
|
} else {
|
||||||
if !errors.Is(err, os.ErrNotExist) {
|
if !errors.Is(err, os.ErrNotExist) {
|
||||||
p.Warn().Err(err).Msg("unable to create log ipc connection")
|
p.Warn().Err(err).Msg("Unable to create log ipc connection")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
p.Warn().Err(err).Msgf("unable to resolve socket address: %s", sockPath)
|
p.Warn().Err(err).Msgf("Unable to resolve socket address: %s", sockPath)
|
||||||
}
|
}
|
||||||
notifyExitToLogServer := func() {
|
notifyExitToLogServer := func() {
|
||||||
if p.logConn != nil {
|
if p.logConn != nil {
|
||||||
@@ -265,10 +265,10 @@ func run(appCallback *AppCallback, stopCh chan struct{}) {
|
|||||||
svcConfig := svcCmd.createServiceConfig()
|
svcConfig := svcCmd.createServiceConfig()
|
||||||
s, err := svcCmd.newService(p, svcConfig)
|
s, err := svcCmd.newService(p, svcConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Fatal().Err(err).Msg("failed create new service")
|
p.Fatal().Err(err).Msg("Failed to create new service")
|
||||||
}
|
}
|
||||||
if err := s.Run(); err != nil {
|
if err := s.Run(); err != nil {
|
||||||
p.Error().Err(err).Msg("failed to start service")
|
p.Error().Err(err).Msg("Failed to start service")
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
@@ -276,7 +276,7 @@ func run(appCallback *AppCallback, stopCh chan struct{}) {
|
|||||||
tryReadingConfig(writeDefaultConfig)
|
tryReadingConfig(writeDefaultConfig)
|
||||||
|
|
||||||
if err := readBase64Config(configBase64); err != nil {
|
if err := readBase64Config(configBase64); err != nil {
|
||||||
p.Fatal().Err(err).Msg("failed to read base64 config")
|
p.Fatal().Err(err).Msg("Failed to read base64 config")
|
||||||
}
|
}
|
||||||
processNoConfigFlags(noConfigStart)
|
processNoConfigFlags(noConfigStart)
|
||||||
|
|
||||||
@@ -285,7 +285,7 @@ func run(appCallback *AppCallback, stopCh chan struct{}) {
|
|||||||
p.mu.Lock()
|
p.mu.Lock()
|
||||||
if err := v.Unmarshal(&cfg); err != nil {
|
if err := v.Unmarshal(&cfg); err != nil {
|
||||||
notifyExitToLogServer()
|
notifyExitToLogServer()
|
||||||
p.Fatal().Msgf("failed to unmarshal config: %v", err)
|
p.Fatal().Msgf("Failed to unmarshal config: %v", err)
|
||||||
}
|
}
|
||||||
p.mu.Unlock()
|
p.mu.Unlock()
|
||||||
|
|
||||||
@@ -295,18 +295,18 @@ func run(appCallback *AppCallback, stopCh chan struct{}) {
|
|||||||
// so it's able to log information in processCDFlags.
|
// so it's able to log information in processCDFlags.
|
||||||
p.initLogging(true)
|
p.initLogging(true)
|
||||||
|
|
||||||
p.Info().Msgf("starting ctrld %s", curVersion())
|
p.Info().Msgf("Starting ctrld %s", curVersion())
|
||||||
p.Info().Msgf("os: %s", osVersion())
|
p.Info().Msgf("OS: %s", osVersion())
|
||||||
|
|
||||||
// Wait for network up.
|
// Wait for network up.
|
||||||
if !ctrldnet.Up() {
|
if !ctrldnet.Up() {
|
||||||
notifyExitToLogServer()
|
notifyExitToLogServer()
|
||||||
p.Fatal().Msg("network is not up yet")
|
p.Fatal().Msg("Network is not up yet")
|
||||||
}
|
}
|
||||||
|
|
||||||
cs, err := newControlServer(filepath.Join(sockDir, ControlSocketName()))
|
cs, err := newControlServer(filepath.Join(sockDir, ControlSocketName()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Warn().Err(err).Msg("could not create control server")
|
p.Warn().Err(err).Msg("Could not create control server")
|
||||||
}
|
}
|
||||||
p.cs = cs
|
p.cs = cs
|
||||||
|
|
||||||
@@ -329,7 +329,7 @@ func run(appCallback *AppCallback, stopCh chan struct{}) {
|
|||||||
_ = uninstallInvalidCdUID(p, cdLogger, false)
|
_ = uninstallInvalidCdUID(p, cdLogger, false)
|
||||||
}
|
}
|
||||||
notifyExitToLogServer()
|
notifyExitToLogServer()
|
||||||
cdLogger.Fatal().Err(err).Msg("failed to fetch resolver config")
|
cdLogger.Fatal().Err(err).Msg("Failed to fetch resolver config")
|
||||||
} else {
|
} else {
|
||||||
p.mu.Lock()
|
p.mu.Lock()
|
||||||
p.rc = rc
|
p.rc = rc
|
||||||
@@ -346,9 +346,9 @@ func run(appCallback *AppCallback, stopCh chan struct{}) {
|
|||||||
if updated {
|
if updated {
|
||||||
if err := writeConfigFile(&cfg); err != nil {
|
if err := writeConfigFile(&cfg); err != nil {
|
||||||
notifyExitToLogServer()
|
notifyExitToLogServer()
|
||||||
p.Fatal().Err(err).Msg("failed to write config file")
|
p.Fatal().Err(err).Msg("Failed to write config file")
|
||||||
} else {
|
} else {
|
||||||
p.Info().Msg("writing config file to: " + defaultConfigFile)
|
p.Info().Msg("Writing config file to: " + defaultConfigFile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,7 +360,7 @@ func run(appCallback *AppCallback, stopCh chan struct{}) {
|
|||||||
// Copy logs written so far to new log file if possible.
|
// Copy logs written so far to new log file if possible.
|
||||||
if buf, err := os.ReadFile(oldLogPath); err == nil {
|
if buf, err := os.ReadFile(oldLogPath); err == nil {
|
||||||
if err := os.WriteFile(newLogPath, buf, os.FileMode(0o600)); err != nil {
|
if err := os.WriteFile(newLogPath, buf, os.FileMode(0o600)); err != nil {
|
||||||
p.Warn().Err(err).Msg("could not copy old log file")
|
p.Warn().Err(err).Msg("Could not copy old log file")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
initLoggingWithBackup(false)
|
initLoggingWithBackup(false)
|
||||||
@@ -376,13 +376,13 @@ func run(appCallback *AppCallback, stopCh chan struct{}) {
|
|||||||
if daemon {
|
if daemon {
|
||||||
exe, err := os.Executable()
|
exe, err := os.Executable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Error().Err(err).Msg("failed to find the binary")
|
p.Error().Err(err).Msg("Failed to find the binary")
|
||||||
notifyExitToLogServer()
|
notifyExitToLogServer()
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
curDir, err := os.Getwd()
|
curDir, err := os.Getwd()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Error().Err(err).Msg("failed to get current working directory")
|
p.Error().Err(err).Msg("Failed to get current working directory")
|
||||||
notifyExitToLogServer()
|
notifyExitToLogServer()
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
@@ -390,7 +390,7 @@ func run(appCallback *AppCallback, stopCh chan struct{}) {
|
|||||||
cmd := exec.Command(exe, append(os.Args[1:], "-d=false")...)
|
cmd := exec.Command(exe, append(os.Args[1:], "-d=false")...)
|
||||||
cmd.Dir = curDir
|
cmd.Dir = curDir
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
p.Error().Err(err).Msg("failed to start process as daemon")
|
p.Error().Err(err).Msg("Failed to start process as daemon")
|
||||||
notifyExitToLogServer()
|
notifyExitToLogServer()
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
@@ -402,7 +402,7 @@ func run(appCallback *AppCallback, stopCh chan struct{}) {
|
|||||||
for _, lc := range p.cfg.Listener {
|
for _, lc := range p.cfg.Listener {
|
||||||
if shouldAllocateLoopbackIP(lc.IP) {
|
if shouldAllocateLoopbackIP(lc.IP) {
|
||||||
if err := allocateIP(lc.IP); err != nil {
|
if err := allocateIP(lc.IP); err != nil {
|
||||||
p.Error().Err(err).Msgf("could not allocate IP: %s", lc.IP)
|
p.Error().Err(err).Msgf("Could not allocate ip: %s", lc.IP)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -413,7 +413,7 @@ func run(appCallback *AppCallback, stopCh chan struct{}) {
|
|||||||
for _, lc := range p.cfg.Listener {
|
for _, lc := range p.cfg.Listener {
|
||||||
if shouldAllocateLoopbackIP(lc.IP) {
|
if shouldAllocateLoopbackIP(lc.IP) {
|
||||||
if err := deAllocateIP(lc.IP); err != nil {
|
if err := deAllocateIP(lc.IP); err != nil {
|
||||||
p.Error().Err(err).Msgf("could not de-allocate IP: %s", lc.IP)
|
p.Error().Err(err).Msgf("Could not de-allocate ip: %s", lc.IP)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -426,9 +426,9 @@ func run(appCallback *AppCallback, stopCh chan struct{}) {
|
|||||||
file := ctrld.SavedStaticDnsSettingsFilePath(i)
|
file := ctrld.SavedStaticDnsSettingsFilePath(i)
|
||||||
if _, err := os.Stat(file); err == nil {
|
if _, err := os.Stat(file); err == nil {
|
||||||
if err := restoreDNS(i); err != nil {
|
if err := restoreDNS(i); err != nil {
|
||||||
p.Error().Err(err).Msgf("Could not restore static DNS on interface %s", i.Name)
|
p.Error().Err(err).Msgf("Could not restore static dns on interface %s", i.Name)
|
||||||
} else {
|
} else {
|
||||||
p.Debug().Msgf("Restored static DNS on interface %s successfully", i.Name)
|
p.Debug().Msgf("Restored static dns on interface %s successfully", i.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -488,7 +488,7 @@ func readConfigFile(writeDefaultConfig, notice bool) bool {
|
|||||||
if notice {
|
if notice {
|
||||||
mainLog.Load().Notice().Msg("Reading config: " + v.ConfigFileUsed())
|
mainLog.Load().Notice().Msg("Reading config: " + v.ConfigFileUsed())
|
||||||
}
|
}
|
||||||
mainLog.Load().Info().Msg("loading config file from: " + v.ConfigFileUsed())
|
mainLog.Load().Info().Msg("Loading config file from: " + v.ConfigFileUsed())
|
||||||
defaultConfigFile = v.ConfigFileUsed()
|
defaultConfigFile = v.ConfigFileUsed()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -500,21 +500,21 @@ func readConfigFile(writeDefaultConfig, notice bool) bool {
|
|||||||
// If error is viper.ConfigFileNotFoundError, write default config.
|
// If error is viper.ConfigFileNotFoundError, write default config.
|
||||||
if errors.As(err, &viper.ConfigFileNotFoundError{}) {
|
if errors.As(err, &viper.ConfigFileNotFoundError{}) {
|
||||||
if err := v.Unmarshal(&cfg); err != nil {
|
if err := v.Unmarshal(&cfg); err != nil {
|
||||||
mainLog.Load().Fatal().Msgf("failed to unmarshal default config: %v", err)
|
mainLog.Load().Fatal().Msgf("Failed to unmarshal default config: %v", err)
|
||||||
}
|
}
|
||||||
_, _ = tryUpdateListenerConfig(&cfg, func() {}, true)
|
_, _ = tryUpdateListenerConfig(&cfg, func() {}, true)
|
||||||
addExtraSplitDnsRule(&cfg)
|
addExtraSplitDnsRule(&cfg)
|
||||||
if err := writeConfigFile(&cfg); err != nil {
|
if err := writeConfigFile(&cfg); err != nil {
|
||||||
mainLog.Load().Fatal().Msgf("failed to write default config file: %v", err)
|
mainLog.Load().Fatal().Msgf("Failed to write default config file: %v", err)
|
||||||
} else {
|
} else {
|
||||||
fp, err := filepath.Abs(defaultConfigFile)
|
fp, err := filepath.Abs(defaultConfigFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Fatal().Msgf("failed to get default config file path: %v", err)
|
mainLog.Load().Fatal().Msgf("Failed to get default config file path: %v", err)
|
||||||
}
|
}
|
||||||
if cdUID == "" && nextdns == "" {
|
if cdUID == "" && nextdns == "" {
|
||||||
mainLog.Load().Notice().Msg("Generating controld default config: " + fp)
|
mainLog.Load().Notice().Msg("Generating controld default config: " + fp)
|
||||||
}
|
}
|
||||||
mainLog.Load().Info().Msg("writing default config file to: " + fp)
|
mainLog.Load().Info().Msg("Writing default config file to: " + fp)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -523,12 +523,12 @@ func readConfigFile(writeDefaultConfig, notice bool) bool {
|
|||||||
if errors.As(err, &viper.ConfigParseError{}) {
|
if errors.As(err, &viper.ConfigParseError{}) {
|
||||||
if de := decoderErrorFromTomlFile(v.ConfigFileUsed()); de != nil {
|
if de := decoderErrorFromTomlFile(v.ConfigFileUsed()); de != nil {
|
||||||
row, col := de.Position()
|
row, col := de.Position()
|
||||||
mainLog.Load().Fatal().Msgf("failed to decode config file at line: %d, column: %d, error: %v", row, col, err)
|
mainLog.Load().Fatal().Msgf("Failed to decode config file at line: %d, column: %d, error: %v", row, col, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, report fatal error and exit.
|
// Otherwise, report fatal error and exit.
|
||||||
mainLog.Load().Fatal().Msgf("failed to decode config file: %v", err)
|
mainLog.Load().Fatal().Msgf("Failed to decode config file: %v", err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -653,7 +653,7 @@ func deactivationPinSet() bool {
|
|||||||
// processCDFlags processes Control D related flags
|
// processCDFlags processes Control D related flags
|
||||||
func processCDFlags(cfg *ctrld.Config) (*controld.ResolverConfig, error) {
|
func processCDFlags(cfg *ctrld.Config) (*controld.ResolverConfig, error) {
|
||||||
logger := mainLog.Load().With().Str("mode", "cd")
|
logger := mainLog.Load().With().Str("mode", "cd")
|
||||||
logger.Info().Msgf("fetching Controld D configuration from API: %s", cdUID)
|
logger.Info().Msgf("Fetching Controld D configuration from API: %s", cdUID)
|
||||||
bo := backoff.NewBackoff("processCDFlags", logf, 30*time.Second)
|
bo := backoff.NewBackoff("processCDFlags", logf, 30*time.Second)
|
||||||
bo.LogLongerThan = 30 * time.Second
|
bo.LogLongerThan = 30 * time.Second
|
||||||
ctx := ctrld.LoggerCtx(context.Background(), logger)
|
ctx := ctrld.LoggerCtx(context.Background(), logger)
|
||||||
@@ -665,7 +665,7 @@ func processCDFlags(cfg *ctrld.Config) (*controld.ResolverConfig, error) {
|
|||||||
for {
|
for {
|
||||||
if errUrlNetworkError(err) {
|
if errUrlNetworkError(err) {
|
||||||
bo.BackOff(ctx, err)
|
bo.BackOff(ctx, err)
|
||||||
logger.Warn().Msg("could not fetch resolver using bootstrap DNS, retrying...")
|
logger.Warn().Msg("Could not fetch resolver using bootstrap DNS, retrying...")
|
||||||
resolverConfig, err = controld.FetchResolverConfig(ctx, cdUID, appVersion, cdDev)
|
resolverConfig, err = controld.FetchResolverConfig(ctx, cdUID, appVersion, cdDev)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -675,23 +675,23 @@ func processCDFlags(cfg *ctrld.Config) (*controld.ResolverConfig, error) {
|
|||||||
if isMobile() {
|
if isMobile() {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
logger.Warn().Err(err).Msg("could not fetch resolver config")
|
logger.Warn().Err(err).Msg("Could not fetch resolver config")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if resolverConfig.DeactivationPin != nil {
|
if resolverConfig.DeactivationPin != nil {
|
||||||
logger.Debug().Msg("saving deactivation pin")
|
logger.Debug().Msg("Saving deactivation pin")
|
||||||
cdDeactivationPin.Store(*resolverConfig.DeactivationPin)
|
cdDeactivationPin.Store(*resolverConfig.DeactivationPin)
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info().Msg("generating ctrld config from Control-D configuration")
|
logger.Info().Msg("Generating ctrld config from Control-D configuration")
|
||||||
|
|
||||||
// Reset config to ensure clean state before applying Control-D settings
|
// Reset config to ensure clean state before applying Control-D settings
|
||||||
// This prevents mixing of old configuration with new Control-D settings
|
// This prevents mixing of old configuration with new Control-D settings
|
||||||
*cfg = ctrld.Config{}
|
*cfg = ctrld.Config{}
|
||||||
// Fetch config, unmarshal to cfg.
|
// Fetch config, unmarshal to cfg.
|
||||||
if resolverConfig.Ctrld.CustomConfig != "" {
|
if resolverConfig.Ctrld.CustomConfig != "" {
|
||||||
logger.Info().Msg("using defined custom config of Control-D resolver")
|
logger.Info().Msg("Using defined custom config of Control-D resolver")
|
||||||
var cfgErr error
|
var cfgErr error
|
||||||
if cfgErr = validateCdRemoteConfig(resolverConfig, cfg); cfgErr == nil {
|
if cfgErr = validateCdRemoteConfig(resolverConfig, cfg); cfgErr == nil {
|
||||||
setListenerDefaultValue(cfg)
|
setListenerDefaultValue(cfg)
|
||||||
@@ -700,13 +700,13 @@ func processCDFlags(cfg *ctrld.Config) (*controld.ResolverConfig, error) {
|
|||||||
return resolverConfig, nil
|
return resolverConfig, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mainLog.Load().Warn().Err(err).Msg("disregarding invalid custom config")
|
mainLog.Load().Warn().Err(err).Msg("Disregarding invalid custom config")
|
||||||
}
|
}
|
||||||
|
|
||||||
bootstrapIP := func(endpoint string) string {
|
bootstrapIP := func(endpoint string) string {
|
||||||
u, err := url.Parse(endpoint)
|
u, err := url.Parse(endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warn().Err(err).Msgf("no bootstrap IP for invalid endpoint: %s", endpoint)
|
logger.Warn().Err(err).Msgf("No bootstrap ip for invalid endpoint: %s", endpoint)
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
@@ -796,11 +796,11 @@ func processListenFlag() {
|
|||||||
|
|
||||||
host, portStr, err := net.SplitHostPort(listenAddress)
|
host, portStr, err := net.SplitHostPort(listenAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Fatal().Msgf("invalid listener address: %v", err)
|
mainLog.Load().Fatal().Msgf("Invalid listener address: %v", err)
|
||||||
}
|
}
|
||||||
port, err := strconv.Atoi(portStr)
|
port, err := strconv.Atoi(portStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Fatal().Msgf("invalid port number: %v", err)
|
mainLog.Load().Fatal().Msgf("Invalid port number: %v", err)
|
||||||
}
|
}
|
||||||
lc := &ctrld.ListenerConfig{
|
lc := &ctrld.ListenerConfig{
|
||||||
IP: host,
|
IP: host,
|
||||||
@@ -870,7 +870,7 @@ func defaultIfaceName() string {
|
|||||||
if runtime.GOOS == "linux" {
|
if runtime.GOOS == "linux" {
|
||||||
return "lo"
|
return "lo"
|
||||||
}
|
}
|
||||||
mainLog.Load().Debug().Err(err).Msg("no default route interface found")
|
mainLog.Load().Debug().Err(err).Msg("No default route interface found")
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return dri
|
return dri
|
||||||
@@ -889,7 +889,7 @@ func defaultIfaceName() string {
|
|||||||
func selfCheckStatus(ctx context.Context, s service.Service, sockDir string) (bool, service.Status, error) {
|
func selfCheckStatus(ctx context.Context, s service.Service, sockDir string) (bool, service.Status, error) {
|
||||||
status, err := s.Status()
|
status, err := s.Status()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Warn().Err(err).Msg("could not get service status")
|
mainLog.Load().Warn().Err(err).Msg("Could not get service status")
|
||||||
return false, service.StatusUnknown, err
|
return false, service.StatusUnknown, err
|
||||||
}
|
}
|
||||||
// If ctrld is not running, do nothing, just return the status as-is.
|
// If ctrld is not running, do nothing, just return the status as-is.
|
||||||
@@ -901,7 +901,7 @@ func selfCheckStatus(ctx context.Context, s service.Service, sockDir string) (bo
|
|||||||
return true, status, nil
|
return true, status, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
mainLog.Load().Debug().Msg("waiting for ctrld listener to be ready")
|
mainLog.Load().Debug().Msg("Waiting for ctrld listener to be ready")
|
||||||
cc := newSocketControlClient(ctx, s, sockDir)
|
cc := newSocketControlClient(ctx, s, sockDir)
|
||||||
if cc == nil {
|
if cc == nil {
|
||||||
return false, status, errors.New("could not connect to control server")
|
return false, status, errors.New("could not connect to control server")
|
||||||
@@ -914,13 +914,13 @@ func selfCheckStatus(ctx context.Context, s service.Service, sockDir string) (bo
|
|||||||
v.SetConfigFile(defaultConfigFile)
|
v.SetConfigFile(defaultConfigFile)
|
||||||
}
|
}
|
||||||
if err := v.ReadInConfig(); err != nil {
|
if err := v.ReadInConfig(); err != nil {
|
||||||
mainLog.Load().Error().Err(err).Msgf("failed to re-read configuration file: %s", v.ConfigFileUsed())
|
mainLog.Load().Error().Err(err).Msgf("Failed to re-read configuration file: %s", v.ConfigFileUsed())
|
||||||
return false, status, err
|
return false, status, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg = ctrld.Config{}
|
cfg = ctrld.Config{}
|
||||||
if err := v.Unmarshal(&cfg); err != nil {
|
if err := v.Unmarshal(&cfg); err != nil {
|
||||||
mainLog.Load().Error().Err(err).Msg("failed to update new config")
|
mainLog.Load().Error().Err(err).Msg("Failed to update new config")
|
||||||
return false, status, err
|
return false, status, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -930,12 +930,12 @@ func selfCheckStatus(ctx context.Context, s service.Service, sockDir string) (bo
|
|||||||
return true, status, nil
|
return true, status, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
mainLog.Load().Debug().Msg("ctrld listener is ready")
|
mainLog.Load().Debug().Msg("Ctrld listener is ready")
|
||||||
|
|
||||||
lc := cfg.FirstListener()
|
lc := cfg.FirstListener()
|
||||||
addr := net.JoinHostPort(lc.IP, strconv.Itoa(lc.Port))
|
addr := net.JoinHostPort(lc.IP, strconv.Itoa(lc.Port))
|
||||||
|
|
||||||
mainLog.Load().Debug().Msgf("performing listener test, sending queries to %s", addr)
|
mainLog.Load().Debug().Msgf("Performing listener test, sending queries to %s", addr)
|
||||||
|
|
||||||
if err := selfCheckResolveDomain(context.TODO(), addr, "internal", selfCheckInternalTestDomain); err != nil {
|
if err := selfCheckResolveDomain(context.TODO(), addr, "internal", selfCheckInternalTestDomain); err != nil {
|
||||||
return false, status, err
|
return false, status, err
|
||||||
@@ -985,20 +985,21 @@ func selfCheckResolveDomain(ctx context.Context, addr, scope string, domain stri
|
|||||||
lastErr = exErr
|
lastErr = exErr
|
||||||
bo.BackOff(ctx, fmt.Errorf("ExchangeContext: %w", exErr))
|
bo.BackOff(ctx, fmt.Errorf("ExchangeContext: %w", exErr))
|
||||||
}
|
}
|
||||||
mainLog.Load().Debug().Msgf("self-check against %q failed", domain)
|
mainLog.Load().Debug().Msgf("Self-check against %q failed", domain)
|
||||||
loggerCtx := ctrld.LoggerCtx(ctx, mainLog.Load())
|
loggerCtx := ctrld.LoggerCtx(ctx, mainLog.Load())
|
||||||
// Ping all upstreams to provide better error message to users.
|
// Ping all upstreams to provide better error message to users.
|
||||||
for name, uc := range cfg.Upstream {
|
for name, uc := range cfg.Upstream {
|
||||||
if err := uc.ErrorPing(loggerCtx); err != nil {
|
if err := uc.ErrorPing(loggerCtx); err != nil {
|
||||||
mainLog.Load().Err(err).Msgf("failed to connect to upstream.%s, endpoint: %s", name, uc.Endpoint)
|
mainLog.Load().Err(err).Msgf("Failed to connect to upstream.%s, endpoint: %s", name, uc.Endpoint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
marker := strings.Repeat("=", 32)
|
marker := strings.Repeat("=", 32)
|
||||||
mainLog.Load().Debug().Msg(marker)
|
mainLog.Load().Debug().Msg(marker)
|
||||||
mainLog.Load().Debug().Msgf("listener address : %s", addr)
|
|
||||||
mainLog.Load().Debug().Msgf("last error : %v", lastErr)
|
mainLog.Load().Debug().Msgf("Listener address : %s", addr)
|
||||||
|
mainLog.Load().Debug().Msgf("Last error : %v", lastErr)
|
||||||
if lastAnswer != nil {
|
if lastAnswer != nil {
|
||||||
mainLog.Load().Debug().Msgf("last answer from ctrld :")
|
mainLog.Load().Debug().Msgf("Last answer from ctrld :")
|
||||||
mainLog.Load().Debug().Msg(marker)
|
mainLog.Load().Debug().Msg(marker)
|
||||||
for _, s := range strings.Split(lastAnswer.String(), "\n") {
|
for _, s := range strings.Split(lastAnswer.String(), "\n") {
|
||||||
mainLog.Load().Debug().Msgf("%s", s)
|
mainLog.Load().Debug().Msgf("%s", s)
|
||||||
@@ -1069,7 +1070,7 @@ func readConfigWithNotice(writeDefaultConfig, notice bool) {
|
|||||||
|
|
||||||
dir, err := userHomeDir()
|
dir, err := userHomeDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Fatal().Msgf("failed to get user home dir: %v", err)
|
mainLog.Load().Fatal().Msgf("Failed to get user home dir: %v", err)
|
||||||
}
|
}
|
||||||
for _, config := range configs {
|
for _, config := range configs {
|
||||||
ctrld.SetConfigNameWithPath(v, config.name, dir)
|
ctrld.SetConfigNameWithPath(v, config.name, dir)
|
||||||
@@ -1099,12 +1100,12 @@ func uninstall(p *prog, s service.Service) {
|
|||||||
file := ctrld.SavedStaticDnsSettingsFilePath(i)
|
file := ctrld.SavedStaticDnsSettingsFilePath(i)
|
||||||
if _, err := os.Stat(file); err == nil {
|
if _, err := os.Stat(file); err == nil {
|
||||||
if err := restoreDNS(i); err != nil {
|
if err := restoreDNS(i); err != nil {
|
||||||
mainLog.Load().Error().Err(err).Msgf("Could not restore static DNS on interface %s", i.Name)
|
mainLog.Load().Error().Err(err).Msgf("Could not restore static dns on interface %s", i.Name)
|
||||||
} else {
|
} else {
|
||||||
mainLog.Load().Debug().Msgf("Restored static DNS on interface %s successfully", i.Name)
|
mainLog.Load().Debug().Msgf("Restored static dns on interface %s successfully", i.Name)
|
||||||
err = os.Remove(file)
|
err = os.Remove(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Debug().Err(err).Msgf("Could not remove saved static DNS file for interface %s", i.Name)
|
mainLog.Load().Debug().Err(err).Msgf("Could not remove saved static dns file for interface %s", i.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1123,7 +1124,7 @@ func validateConfig(cfg *ctrld.Config) error {
|
|||||||
var ve validator.ValidationErrors
|
var ve validator.ValidationErrors
|
||||||
if errors.As(err, &ve) {
|
if errors.As(err, &ve) {
|
||||||
for _, fe := range ve {
|
for _, fe := range ve {
|
||||||
mainLog.Load().Error().Msgf("invalid config: %s: %s", fe.Namespace(), fieldErrorMsg(fe))
|
mainLog.Load().Error().Msgf("Invalid config: %s: %s", fe.Namespace(), fieldErrorMsg(fe))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mainLog.Load().Error().Err(err).Msg("Configuration validation failed")
|
mainLog.Load().Error().Err(err).Msg("Configuration validation failed")
|
||||||
@@ -1492,14 +1493,14 @@ func cdUIDFromProvToken() string {
|
|||||||
}
|
}
|
||||||
// Validate custom hostname if provided.
|
// Validate custom hostname if provided.
|
||||||
if customHostname != "" && !validHostname(customHostname) {
|
if customHostname != "" && !validHostname(customHostname) {
|
||||||
mainLog.Load().Fatal().Msgf("invalid custom hostname: %q", customHostname)
|
mainLog.Load().Fatal().Msgf("Invalid custom hostname: %q", customHostname)
|
||||||
}
|
}
|
||||||
req := &controld.UtilityOrgRequest{ProvToken: cdOrg, Hostname: customHostname}
|
req := &controld.UtilityOrgRequest{ProvToken: cdOrg, Hostname: customHostname}
|
||||||
// Process provision token if provided.
|
// Process provision token if provided.
|
||||||
loggerCtx := ctrld.LoggerCtx(context.Background(), mainLog.Load())
|
loggerCtx := ctrld.LoggerCtx(context.Background(), mainLog.Load())
|
||||||
resolverConfig, err := controld.FetchResolverUID(loggerCtx, req, appVersion, cdDev)
|
resolverConfig, err := controld.FetchResolverUID(loggerCtx, req, appVersion, cdDev)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Fatal().Err(err).Msgf("failed to fetch resolver uid with provision token: %s", cdOrg)
|
mainLog.Load().Fatal().Err(err).Msgf("Failed to fetch resolver uid with provision token: %s", cdOrg)
|
||||||
}
|
}
|
||||||
return resolverConfig.UID
|
return resolverConfig.UID
|
||||||
}
|
}
|
||||||
@@ -1619,7 +1620,7 @@ func validateCdUpstreamProtocol() {
|
|||||||
switch cdUpstreamProto {
|
switch cdUpstreamProto {
|
||||||
case ctrld.ResolverTypeDOH, ctrld.ResolverTypeDOH3:
|
case ctrld.ResolverTypeDOH, ctrld.ResolverTypeDOH3:
|
||||||
default:
|
default:
|
||||||
mainLog.Load().Fatal().Msg(`flag "--protocol" must be "doh" or "doh3"`)
|
mainLog.Load().Fatal().Msg(`Flag "--protocol" must be "doh" or "doh3"`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1686,7 +1687,7 @@ func checkDeactivationPin(s service.Service, stopCh chan struct{}) error {
|
|||||||
mainLog.Load().Debug().Msg("Checking deactivation pin")
|
mainLog.Load().Debug().Msg("Checking deactivation pin")
|
||||||
dir, err := socketDir()
|
dir, err := socketDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Err(err).Msg("could not check deactivation pin")
|
mainLog.Load().Err(err).Msg("Could not check deactivation pin")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
mainLog.Load().Debug().Msg("Creating control client")
|
mainLog.Load().Debug().Msg("Creating control client")
|
||||||
@@ -1751,7 +1752,7 @@ func curCdUID() string {
|
|||||||
if s, _, _ := svcCmd.initializeServiceManager(); s != nil {
|
if s, _, _ := svcCmd.initializeServiceManager(); s != nil {
|
||||||
// Configure Windows service failure actions
|
// Configure Windows service failure actions
|
||||||
if err := ConfigureWindowsServiceFailureActions(ctrldServiceName); err != nil {
|
if err := ConfigureWindowsServiceFailureActions(ctrldServiceName); err != nil {
|
||||||
mainLog.Load().Debug().Err(err).Msgf("failed to configure Windows service %s failure actions", ctrldServiceName)
|
mainLog.Load().Debug().Err(err).Msgf("Failed to configure windows service %s failure actions", ctrldServiceName)
|
||||||
}
|
}
|
||||||
if dir, _ := socketDir(); dir != "" {
|
if dir, _ := socketDir(); dir != "" {
|
||||||
cc := newSocketControlClient(context.TODO(), s, dir)
|
cc := newSocketControlClient(context.TODO(), s, dir)
|
||||||
@@ -1830,7 +1831,7 @@ func doValidateCdRemoteConfig(cdUID string, fatal bool) error {
|
|||||||
if !fatal {
|
if !fatal {
|
||||||
logger = mainLog.Load().Warn()
|
logger = mainLog.Load().Warn()
|
||||||
}
|
}
|
||||||
logger.Err(err).Err(err).Msgf("failed to fetch resolver uid: %s", cdUID)
|
logger.Err(err).Err(err).Msgf("Failed to fetch resolver uid: %s", cdUID)
|
||||||
if !fatal {
|
if !fatal {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -1859,22 +1860,22 @@ func doValidateCdRemoteConfig(cdUID string, fatal bool) error {
|
|||||||
if we := os.WriteFile(tmpConfFile, configStr, 0600); we == nil {
|
if we := os.WriteFile(tmpConfFile, configStr, 0600); we == nil {
|
||||||
if de := decoderErrorFromTomlFile(tmpConfFile); de != nil {
|
if de := decoderErrorFromTomlFile(tmpConfFile); de != nil {
|
||||||
row, col := de.Position()
|
row, col := de.Position()
|
||||||
mainLog.Load().Error().Msgf("failed to parse custom config at line: %d, column: %d, error: %s", row, col, de.Error())
|
mainLog.Load().Error().Msgf("Failed to parse custom config at line: %d, column: %d, error: %s", row, col, de.Error())
|
||||||
errorLogged = true
|
errorLogged = true
|
||||||
}
|
}
|
||||||
_ = os.Remove(tmpConfFile)
|
_ = os.Remove(tmpConfFile)
|
||||||
}
|
}
|
||||||
// If we could not log details error, emit what we have already got.
|
// If we could not log details error, emit what we have already got.
|
||||||
if !errorLogged {
|
if !errorLogged {
|
||||||
mainLog.Load().Error().Msgf("failed to parse custom config: %v", cfgErr)
|
mainLog.Load().Error().Msgf("Failed to parse custom config: %v", cfgErr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mainLog.Load().Error().Msgf("failed to unmarshal custom config: %v", err)
|
mainLog.Load().Error().Msgf("Failed to unmarshal custom config: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if cfgErr != nil {
|
if cfgErr != nil {
|
||||||
mainLog.Load().Warn().Msg("disregarding invalid custom config")
|
mainLog.Load().Warn().Msg("Disregarding invalid custom config")
|
||||||
}
|
}
|
||||||
v = oldV
|
v = oldV
|
||||||
return nil
|
return nil
|
||||||
@@ -1885,7 +1886,7 @@ func uninstallInvalidCdUID(p *prog, logger *ctrld.Logger, doStop bool) bool {
|
|||||||
svcCmd := NewServiceCommand()
|
svcCmd := NewServiceCommand()
|
||||||
s, _, err := svcCmd.initializeServiceManager()
|
s, _, err := svcCmd.initializeServiceManager()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warn().Err(err).Msg("failed to create new service")
|
logger.Warn().Err(err).Msg("Failed to create new service")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// restore static DNS settings or DHCP
|
// restore static DNS settings or DHCP
|
||||||
@@ -1893,7 +1894,7 @@ func uninstallInvalidCdUID(p *prog, logger *ctrld.Logger, doStop bool) bool {
|
|||||||
|
|
||||||
tasks := []task{{s.Uninstall, true, "Uninstall"}}
|
tasks := []task{{s.Uninstall, true, "Uninstall"}}
|
||||||
if doTasks(tasks) {
|
if doTasks(tasks) {
|
||||||
logger.Info().Msg("uninstalled service")
|
logger.Info().Msg("Uninstalled service")
|
||||||
if doStop {
|
if doStop {
|
||||||
_ = s.Stop()
|
_ = s.Stop()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,11 +46,11 @@ func (cc *ClientsCommand) ListClients(cmd *cobra.Command, args []string) error {
|
|||||||
|
|
||||||
status, err := s.Status()
|
status, err := s.Status()
|
||||||
if errors.Is(err, service.ErrNotInstalled) {
|
if errors.Is(err, service.ErrNotInstalled) {
|
||||||
mainLog.Load().Warn().Msg("service not installed")
|
mainLog.Load().Warn().Msg("Service not installed")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if status == service.StatusStopped {
|
if status == service.StatusStopped {
|
||||||
mainLog.Load().Warn().Msg("service is not running")
|
mainLog.Load().Warn().Msg("Service is not running")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ func (ic *InterfacesCommand) ListInterfaces(cmd *cobra.Command, args []string) e
|
|||||||
}
|
}
|
||||||
nss, err := currentStaticDNS(i)
|
nss, err := currentStaticDNS(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Warn().Err(err).Msg("failed to get DNS")
|
mainLog.Load().Warn().Err(err).Msg("Failed to get DNS")
|
||||||
}
|
}
|
||||||
if len(nss) == 0 {
|
if len(nss) == 0 {
|
||||||
nss = currentDNS(i)
|
nss = currentDNS(i)
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ func NewLogCommand() (*LogCommand, error) {
|
|||||||
|
|
||||||
// warnRuntimeLoggingNotEnabled logs a warning about runtime logging not being enabled
|
// warnRuntimeLoggingNotEnabled logs a warning about runtime logging not being enabled
|
||||||
func (lc *LogCommand) warnRuntimeLoggingNotEnabled() {
|
func (lc *LogCommand) warnRuntimeLoggingNotEnabled() {
|
||||||
mainLog.Load().Warn().Msg("runtime debug logging is not enabled")
|
mainLog.Load().Warn().Msg("Runtime debug logging is not enabled")
|
||||||
mainLog.Load().Warn().Msg(`ctrld may be running without "--cd" flag or logging is already enabled`)
|
mainLog.Load().Warn().Msg(`ctrld may be running without "--cd" flag or logging is already enabled`)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,11 +47,11 @@ func (lc *LogCommand) SendLogs(cmd *cobra.Command, args []string) error {
|
|||||||
|
|
||||||
status, err := s.Status()
|
status, err := s.Status()
|
||||||
if errors.Is(err, service.ErrNotInstalled) {
|
if errors.Is(err, service.ErrNotInstalled) {
|
||||||
mainLog.Load().Warn().Msg("service not installed")
|
mainLog.Load().Warn().Msg("Service not installed")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if status == service.StatusStopped {
|
if status == service.StatusStopped {
|
||||||
mainLog.Load().Warn().Msg("service is not running")
|
mainLog.Load().Warn().Msg("Service is not running")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ func (lc *LogCommand) SendLogs(cmd *cobra.Command, args []string) error {
|
|||||||
|
|
||||||
switch resp.StatusCode {
|
switch resp.StatusCode {
|
||||||
case http.StatusServiceUnavailable:
|
case http.StatusServiceUnavailable:
|
||||||
mainLog.Load().Warn().Msg("runtime logs could only be sent once per minute")
|
mainLog.Load().Warn().Msg("Runtime logs could only be sent once per minute")
|
||||||
return nil
|
return nil
|
||||||
case http.StatusMovedPermanently:
|
case http.StatusMovedPermanently:
|
||||||
lc.warnRuntimeLoggingNotEnabled()
|
lc.warnRuntimeLoggingNotEnabled()
|
||||||
@@ -93,11 +93,11 @@ func (lc *LogCommand) ViewLogs(cmd *cobra.Command, args []string) error {
|
|||||||
|
|
||||||
status, err := s.Status()
|
status, err := s.Status()
|
||||||
if errors.Is(err, service.ErrNotInstalled) {
|
if errors.Is(err, service.ErrNotInstalled) {
|
||||||
mainLog.Load().Warn().Msg("service not installed")
|
mainLog.Load().Warn().Msg("Service not installed")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if status == service.StatusStopped {
|
if status == service.StatusStopped {
|
||||||
mainLog.Load().Warn().Msg("service is not running")
|
mainLog.Load().Warn().Msg("Service is not running")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,10 +112,10 @@ func (lc *LogCommand) ViewLogs(cmd *cobra.Command, args []string) error {
|
|||||||
lc.warnRuntimeLoggingNotEnabled()
|
lc.warnRuntimeLoggingNotEnabled()
|
||||||
return nil
|
return nil
|
||||||
case http.StatusBadRequest:
|
case http.StatusBadRequest:
|
||||||
mainLog.Load().Warn().Msg("runtime debugs log is not available")
|
mainLog.Load().Warn().Msg("Runtime debug logs are not available")
|
||||||
buf, err := io.ReadAll(resp.Body)
|
buf, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Fatal().Err(err).Msg("failed to read response body")
|
mainLog.Load().Fatal().Err(err).Msg("Failed to read response body")
|
||||||
}
|
}
|
||||||
mainLog.Load().Warn().Msgf("ctrld process response:\n\n%s\n", string(buf))
|
mainLog.Load().Warn().Msgf("ctrld process response:\n\n%s\n", string(buf))
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ func (uc *UpgradeCommand) Upgrade(cmd *cobra.Command, args []string) error {
|
|||||||
|
|
||||||
bin, err := os.Executable()
|
bin, err := os.Executable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Fatal().Err(err).Msg("failed to get current ctrld binary path")
|
mainLog.Load().Fatal().Err(err).Msg("Failed to get current ctrld binary path")
|
||||||
}
|
}
|
||||||
|
|
||||||
readConfig(false)
|
readConfig(false)
|
||||||
@@ -75,7 +75,7 @@ func (uc *UpgradeCommand) Upgrade(cmd *cobra.Command, args []string) error {
|
|||||||
switch channel {
|
switch channel {
|
||||||
case upgradeChannelProd, upgradeChannelDev: // ok
|
case upgradeChannelProd, upgradeChannelDev: // ok
|
||||||
default:
|
default:
|
||||||
mainLog.Load().Fatal().Msgf("uprade argument must be either %q or %q", upgradeChannelProd, upgradeChannelDev)
|
mainLog.Load().Fatal().Msgf("Upgrade argument must be either %q or %q", upgradeChannelProd, upgradeChannelDev)
|
||||||
}
|
}
|
||||||
baseUrl = upgradeChannel[channel]
|
baseUrl = upgradeChannel[channel]
|
||||||
}
|
}
|
||||||
@@ -85,20 +85,20 @@ func (uc *UpgradeCommand) Upgrade(cmd *cobra.Command, args []string) error {
|
|||||||
|
|
||||||
resp, err := getWithRetry(dlUrl, downloadServerIp)
|
resp, err := getWithRetry(dlUrl, downloadServerIp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Fatal().Err(err).Msg("failed to download binary")
|
mainLog.Load().Fatal().Err(err).Msg("Failed to download binary")
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
mainLog.Load().Fatal().Msgf("could not download binary: %s", http.StatusText(resp.StatusCode))
|
mainLog.Load().Fatal().Msgf("Could not download binary: %s", http.StatusText(resp.StatusCode))
|
||||||
}
|
}
|
||||||
|
|
||||||
mainLog.Load().Debug().Msg("Updating current binary")
|
mainLog.Load().Debug().Msg("Updating current binary")
|
||||||
if err := selfupdate.Apply(resp.Body, selfupdate.Options{OldSavePath: oldBin}); err != nil {
|
if err := selfupdate.Apply(resp.Body, selfupdate.Options{OldSavePath: oldBin}); err != nil {
|
||||||
if rerr := selfupdate.RollbackError(err); rerr != nil {
|
if rerr := selfupdate.RollbackError(err); rerr != nil {
|
||||||
mainLog.Load().Error().Err(rerr).Msg("could not rollback old binary")
|
mainLog.Load().Error().Err(rerr).Msg("Could not rollback old binary")
|
||||||
}
|
}
|
||||||
mainLog.Load().Fatal().Err(err).Msg("failed to update current binary")
|
mainLog.Load().Fatal().Err(err).Msg("Failed to update current binary")
|
||||||
}
|
}
|
||||||
|
|
||||||
doRestart := func() bool {
|
doRestart := func() bool {
|
||||||
@@ -154,10 +154,10 @@ func (uc *UpgradeCommand) Upgrade(cmd *cobra.Command, args []string) error {
|
|||||||
|
|
||||||
mainLog.Load().Warn().Msgf("Upgrade failed, restoring previous binary: %s", oldBin)
|
mainLog.Load().Warn().Msgf("Upgrade failed, restoring previous binary: %s", oldBin)
|
||||||
if err := os.Remove(bin); err != nil {
|
if err := os.Remove(bin); err != nil {
|
||||||
mainLog.Load().Fatal().Err(err).Msg("failed to remove new binary")
|
mainLog.Load().Fatal().Err(err).Msg("Failed to remove new binary")
|
||||||
}
|
}
|
||||||
if err := os.Rename(oldBin, bin); err != nil {
|
if err := os.Rename(oldBin, bin); err != nil {
|
||||||
mainLog.Load().Fatal().Err(err).Msg("failed to restore old binary")
|
mainLog.Load().Fatal().Err(err).Msg("Failed to restore old binary")
|
||||||
}
|
}
|
||||||
if doRestart() {
|
if doRestart() {
|
||||||
mainLog.Load().Notice().Msg("Restored previous binary successfully")
|
mainLog.Load().Notice().Msg("Restored previous binary successfully")
|
||||||
|
|||||||
+19
-19
@@ -81,18 +81,18 @@ func (s *controlServer) register(pattern string, handler http.Handler) {
|
|||||||
|
|
||||||
func (p *prog) registerControlServerHandler() {
|
func (p *prog) registerControlServerHandler() {
|
||||||
p.cs.register(listClientsPath, http.HandlerFunc(func(w http.ResponseWriter, request *http.Request) {
|
p.cs.register(listClientsPath, http.HandlerFunc(func(w http.ResponseWriter, request *http.Request) {
|
||||||
p.Debug().Msg("handling list clients request")
|
p.Debug().Msg("Handling list clients request")
|
||||||
|
|
||||||
clients := p.ciTable.ListClients()
|
clients := p.ciTable.ListClients()
|
||||||
p.Debug().Int("client_count", len(clients)).Msg("retrieved clients list")
|
p.Debug().Int("client_count", len(clients)).Msg("Retrieved clients list")
|
||||||
|
|
||||||
sort.Slice(clients, func(i, j int) bool {
|
sort.Slice(clients, func(i, j int) bool {
|
||||||
return clients[i].IP.Less(clients[j].IP)
|
return clients[i].IP.Less(clients[j].IP)
|
||||||
})
|
})
|
||||||
p.Debug().Msg("sorted clients by IP address")
|
p.Debug().Msg("Sorted clients by IP address")
|
||||||
|
|
||||||
if p.metricsQueryStats.Load() {
|
if p.metricsQueryStats.Load() {
|
||||||
p.Debug().Msg("metrics query stats enabled, collecting query counts")
|
p.Debug().Msg("Metrics query stats enabled, collecting query counts")
|
||||||
|
|
||||||
for idx, client := range clients {
|
for idx, client := range clients {
|
||||||
p.Debug().
|
p.Debug().
|
||||||
@@ -100,7 +100,7 @@ func (p *prog) registerControlServerHandler() {
|
|||||||
Str("ip", client.IP.String()).
|
Str("ip", client.IP.String()).
|
||||||
Str("mac", client.Mac).
|
Str("mac", client.Mac).
|
||||||
Str("hostname", client.Hostname).
|
Str("hostname", client.Hostname).
|
||||||
Msg("processing client metrics")
|
Msg("Processing client metrics")
|
||||||
|
|
||||||
client.IncludeQueryCount = true
|
client.IncludeQueryCount = true
|
||||||
dm := &dto.Metric{}
|
dm := &dto.Metric{}
|
||||||
@@ -108,7 +108,7 @@ func (p *prog) registerControlServerHandler() {
|
|||||||
if statsClientQueriesCount.MetricVec == nil {
|
if statsClientQueriesCount.MetricVec == nil {
|
||||||
p.Debug().
|
p.Debug().
|
||||||
Str("client_ip", client.IP.String()).
|
Str("client_ip", client.IP.String()).
|
||||||
Msg("skipping metrics collection: MetricVec is nil")
|
Msg("Skipping metrics collection: MetricVec is nil")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ func (p *prog) registerControlServerHandler() {
|
|||||||
Str("client_ip", client.IP.String()).
|
Str("client_ip", client.IP.String()).
|
||||||
Str("mac", client.Mac).
|
Str("mac", client.Mac).
|
||||||
Str("hostname", client.Hostname).
|
Str("hostname", client.Hostname).
|
||||||
Msg("failed to get metrics for client")
|
Msg("Failed to get metrics for client")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,30 +132,30 @@ func (p *prog) registerControlServerHandler() {
|
|||||||
p.Debug().
|
p.Debug().
|
||||||
Str("client_ip", client.IP.String()).
|
Str("client_ip", client.IP.String()).
|
||||||
Int64("query_count", client.QueryCount).
|
Int64("query_count", client.QueryCount).
|
||||||
Msg("successfully collected query count")
|
Msg("Successfully collected query count")
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
p.Debug().
|
p.Debug().
|
||||||
Err(err).
|
Err(err).
|
||||||
Str("client_ip", client.IP.String()).
|
Str("client_ip", client.IP.String()).
|
||||||
Msg("failed to write metric")
|
Msg("Failed to write metric")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
p.Debug().Msg("metrics query stats disabled, skipping query counts")
|
p.Debug().Msg("Metrics query stats disabled, skipping query counts")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := json.NewEncoder(w).Encode(&clients); err != nil {
|
if err := json.NewEncoder(w).Encode(&clients); err != nil {
|
||||||
p.Error().
|
p.Error().
|
||||||
Err(err).
|
Err(err).
|
||||||
Int("client_count", len(clients)).
|
Int("client_count", len(clients)).
|
||||||
Msg("failed to encode clients response")
|
Msg("Failed to encode clients response")
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
p.Debug().
|
p.Debug().
|
||||||
Int("client_count", len(clients)).
|
Int("client_count", len(clients)).
|
||||||
Msg("successfully sent clients list response")
|
Msg("Successfully sent clients list response")
|
||||||
}))
|
}))
|
||||||
p.cs.register(startedPath, http.HandlerFunc(func(w http.ResponseWriter, request *http.Request) {
|
p.cs.register(startedPath, http.HandlerFunc(func(w http.ResponseWriter, request *http.Request) {
|
||||||
select {
|
select {
|
||||||
@@ -177,14 +177,14 @@ func (p *prog) registerControlServerHandler() {
|
|||||||
oldSvc := p.cfg.Service
|
oldSvc := p.cfg.Service
|
||||||
p.mu.Unlock()
|
p.mu.Unlock()
|
||||||
if err := p.sendReloadSignal(); err != nil {
|
if err := p.sendReloadSignal(); err != nil {
|
||||||
p.Error().Err(err).Msg("could not send reload signal")
|
p.Error().Err(err).Msg("Could not send reload signal")
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
case <-p.reloadDoneCh:
|
case <-p.reloadDoneCh:
|
||||||
case <-time.After(5 * time.Second):
|
case <-time.After(5 * time.Second):
|
||||||
http.Error(w, "timeout waiting for ctrld reload", http.StatusInternalServerError)
|
http.Error(w, "Timeout waiting for ctrld reload", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +227,7 @@ func (p *prog) registerControlServerHandler() {
|
|||||||
cdDeactivationPin.Store(defaultDeactivationPin)
|
cdDeactivationPin.Store(defaultDeactivationPin)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
p.Warn().Err(err).Msg("could not re-fetch deactivation pin code")
|
p.Warn().Err(err).Msg("Could not re-fetch deactivation pin code")
|
||||||
}
|
}
|
||||||
|
|
||||||
// If pin code not set, allowing deactivation.
|
// If pin code not set, allowing deactivation.
|
||||||
@@ -239,7 +239,7 @@ func (p *prog) registerControlServerHandler() {
|
|||||||
var req deactivationRequest
|
var req deactivationRequest
|
||||||
if err := json.NewDecoder(request.Body).Decode(&req); err != nil {
|
if err := json.NewDecoder(request.Body).Decode(&req); err != nil {
|
||||||
w.WriteHeader(http.StatusPreconditionFailed)
|
w.WriteHeader(http.StatusPreconditionFailed)
|
||||||
p.Error().Err(err).Msg("invalid deactivation request")
|
p.Error().Err(err).Msg("Invalid deactivation request")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,15 +322,15 @@ func (p *prog) registerControlServerHandler() {
|
|||||||
UID: cdUID,
|
UID: cdUID,
|
||||||
Data: r.r,
|
Data: r.r,
|
||||||
}
|
}
|
||||||
p.Debug().Msg("sending log file to ControlD server")
|
p.Debug().Msg("Sending log file to ControlD server")
|
||||||
resp := logSentResponse{Size: r.size}
|
resp := logSentResponse{Size: r.size}
|
||||||
loggerCtx := ctrld.LoggerCtx(context.Background(), p.logger.Load())
|
loggerCtx := ctrld.LoggerCtx(context.Background(), p.logger.Load())
|
||||||
if err := controld.SendLogs(loggerCtx, req, cdDev); err != nil {
|
if err := controld.SendLogs(loggerCtx, req, cdDev); err != nil {
|
||||||
p.Error().Msgf("could not send log file to ControlD server: %v", err)
|
p.Error().Msgf("Could not send log file to ControlD server: %v", err)
|
||||||
resp.Error = err.Error()
|
resp.Error = err.Error()
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
} else {
|
} else {
|
||||||
p.Debug().Msg("sending log file successfully")
|
p.Debug().Msg("Sending log file successfully")
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
}
|
}
|
||||||
if err := json.NewEncoder(w).Encode(&resp); err != nil {
|
if err := json.NewEncoder(w).Encode(&resp); err != nil {
|
||||||
|
|||||||
+20
-20
@@ -105,7 +105,7 @@ func (p *prog) serveDNS(ctx context.Context, listenerNum string) error {
|
|||||||
|
|
||||||
listenerConfig := p.cfg.Listener[listenerNum]
|
listenerConfig := p.cfg.Listener[listenerNum]
|
||||||
if allocErr := p.allocateIP(listenerConfig.IP); allocErr != nil {
|
if allocErr := p.allocateIP(listenerConfig.IP); allocErr != nil {
|
||||||
p.Error().Err(allocErr).Str("ip", listenerConfig.IP).Msg("serveUDP: failed to allocate listen ip")
|
p.Error().Err(allocErr).Str("ip", listenerConfig.IP).Msg("serveUDP: Failed to allocate listen IP")
|
||||||
return allocErr
|
return allocErr
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +136,7 @@ func (p *prog) startListeners(ctx context.Context, cfg *ctrld.ListenerConfig, ha
|
|||||||
case <-p.stopCh:
|
case <-p.stopCh:
|
||||||
case <-gctx.Done():
|
case <-gctx.Done():
|
||||||
case err := <-errCh:
|
case err := <-errCh:
|
||||||
p.Warn().Err(err).Msg("local ipv6 listener failed")
|
p.Warn().Err(err).Msg("Local IPv6 listener failed")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@@ -154,7 +154,7 @@ func (p *prog) startListeners(ctx context.Context, cfg *ctrld.ListenerConfig, ha
|
|||||||
case <-p.stopCh:
|
case <-p.stopCh:
|
||||||
case <-gctx.Done():
|
case <-gctx.Done():
|
||||||
case err := <-errCh:
|
case err := <-errCh:
|
||||||
p.Warn().Err(err).Msgf("could not listen on %s: %s", proto, listenAddr)
|
p.Warn().Err(err).Msgf("Could not listen on %s: %s", proto, listenAddr)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
@@ -476,8 +476,8 @@ func (p *prog) proxyPrivatePtrLookup(ctx context.Context, msg *dns.Msg) *dns.Msg
|
|||||||
},
|
},
|
||||||
Ptr: dns.Fqdn(name),
|
Ptr: dns.Fqdn(name),
|
||||||
}}
|
}}
|
||||||
ctrld.Log(ctx, p.Info(), "private PTR lookup, using client info table")
|
ctrld.Log(ctx, p.Info(), "Private PTR lookup, using client info table")
|
||||||
ctrld.Log(ctx, p.Debug(), "client info: %v", ctrld.ClientInfo{
|
ctrld.Log(ctx, p.Debug(), "Client info: %v", ctrld.ClientInfo{
|
||||||
Mac: p.ciTable.LookupMac(ip.String()),
|
Mac: p.ciTable.LookupMac(ip.String()),
|
||||||
IP: ip.String(),
|
IP: ip.String(),
|
||||||
Hostname: name,
|
Hostname: name,
|
||||||
@@ -525,8 +525,8 @@ func (p *prog) proxyLanHostnameQuery(ctx context.Context, msg *dns.Msg) *dns.Msg
|
|||||||
AAAA: ip.AsSlice(),
|
AAAA: ip.AsSlice(),
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
ctrld.Log(ctx, p.Info(), "lan hostname lookup, using client info table")
|
ctrld.Log(ctx, p.Info(), "Lan hostname lookup, using client info table")
|
||||||
ctrld.Log(ctx, p.Debug(), "client info: %v", ctrld.ClientInfo{
|
ctrld.Log(ctx, p.Debug(), "Client info: %v", ctrld.ClientInfo{
|
||||||
Mac: p.ciTable.LookupMac(ip.String()),
|
Mac: p.ciTable.LookupMac(ip.String()),
|
||||||
IP: ip.String(),
|
IP: ip.String(),
|
||||||
Hostname: hostname,
|
Hostname: hostname,
|
||||||
@@ -560,7 +560,7 @@ func (p *prog) handleSpecialQueryTypes(ctx *context.Context, req *proxyRequest,
|
|||||||
}
|
}
|
||||||
*upstreams, *upstreamConfigs = p.upstreamsAndUpstreamConfigForPtr(*upstreams, *upstreamConfigs)
|
*upstreams, *upstreamConfigs = p.upstreamsAndUpstreamConfigForPtr(*upstreams, *upstreamConfigs)
|
||||||
*ctx = ctrld.LanQueryCtx(*ctx)
|
*ctx = ctrld.LanQueryCtx(*ctx)
|
||||||
ctrld.Log(*ctx, p.Debug(), "private PTR lookup, using upstreams: %v", *upstreams)
|
ctrld.Log(*ctx, p.Debug(), "Private PTR lookup, using upstreams: %v", *upstreams)
|
||||||
return nil
|
return nil
|
||||||
case isLanHostnameQuery(req.msg):
|
case isLanHostnameQuery(req.msg):
|
||||||
req.isLanOrPtrQuery = true
|
req.isLanOrPtrQuery = true
|
||||||
@@ -570,10 +570,10 @@ func (p *prog) handleSpecialQueryTypes(ctx *context.Context, req *proxyRequest,
|
|||||||
*upstreams = []string{upstreamOS}
|
*upstreams = []string{upstreamOS}
|
||||||
*upstreamConfigs = []*ctrld.UpstreamConfig{osUpstreamConfig}
|
*upstreamConfigs = []*ctrld.UpstreamConfig{osUpstreamConfig}
|
||||||
*ctx = ctrld.LanQueryCtx(*ctx)
|
*ctx = ctrld.LanQueryCtx(*ctx)
|
||||||
ctrld.Log(*ctx, p.Debug(), "lan hostname lookup, using upstreams: %v", *upstreams)
|
ctrld.Log(*ctx, p.Debug(), "Lan hostname lookup, using upstreams: %v", *upstreams)
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
ctrld.Log(*ctx, p.Debug(), "no explicit policy matched, using default routing -> %v", *upstreams)
|
ctrld.Log(*ctx, p.Debug(), "No explicit policy matched, using default routing -> %v", *upstreams)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1093,7 +1093,7 @@ func runDNSServer(addr, network string, handler dns.Handler) (*dns.Server, <-cha
|
|||||||
defer close(errCh)
|
defer close(errCh)
|
||||||
if err := s.ListenAndServe(); err != nil {
|
if err := s.ListenAndServe(); err != nil {
|
||||||
s.NotifyStartedFunc()
|
s.NotifyStartedFunc()
|
||||||
mainLog.Load().Error().Err(err).Msgf("could not listen and serve on: %s", s.Addr)
|
mainLog.Load().Error().Err(err).Msgf("Could not listen and serve on: %s", s.Addr)
|
||||||
errCh <- err
|
errCh <- err
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@@ -1195,11 +1195,11 @@ func (p *prog) doSelfUninstall(pr *proxyResponse) {
|
|||||||
p.checkingSelfUninstall = true
|
p.checkingSelfUninstall = true
|
||||||
loggerCtx := ctrld.LoggerCtx(context.Background(), p.logger.Load())
|
loggerCtx := ctrld.LoggerCtx(context.Background(), p.logger.Load())
|
||||||
_, err := controld.FetchResolverConfig(loggerCtx, cdUID, appVersion, cdDev)
|
_, err := controld.FetchResolverConfig(loggerCtx, cdUID, appVersion, cdDev)
|
||||||
logger.Debug().Msg("maximum number of refused queries reached, checking device status")
|
logger.Debug().Msg("Maximum number of refused queries reached, checking device status")
|
||||||
selfUninstallCheck(err, p, logger)
|
selfUninstallCheck(err, p, logger)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warn().Err(err).Msg("could not fetch resolver config")
|
logger.Warn().Err(err).Msg("Could not fetch resolver config")
|
||||||
}
|
}
|
||||||
// Cool-of period to prevent abusing the API.
|
// Cool-of period to prevent abusing the API.
|
||||||
go p.selfUninstallCoolOfPeriod()
|
go p.selfUninstallCoolOfPeriod()
|
||||||
@@ -1263,7 +1263,7 @@ func (p *prog) queryFromSelf(ip string) bool {
|
|||||||
netIP := netip.MustParseAddr(ip)
|
netIP := netip.MustParseAddr(ip)
|
||||||
regularIPs, loopbackIPs, err := netmon.LocalAddresses()
|
regularIPs, loopbackIPs, err := netmon.LocalAddresses()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Warn().Err(err).Msg("could not get local addresses")
|
p.Warn().Err(err).Msg("Could not get local addresses")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for _, localIP := range slices.Concat(regularIPs, loopbackIPs) {
|
for _, localIP := range slices.Concat(regularIPs, loopbackIPs) {
|
||||||
@@ -1384,7 +1384,7 @@ func isWanClient(na net.Addr) bool {
|
|||||||
// resolveInternalDomainTestQuery resolves internal test domain query, returning the answer to the caller.
|
// resolveInternalDomainTestQuery resolves internal test domain query, returning the answer to the caller.
|
||||||
func resolveInternalDomainTestQuery(ctx context.Context, domain string, m *dns.Msg) *dns.Msg {
|
func resolveInternalDomainTestQuery(ctx context.Context, domain string, m *dns.Msg) *dns.Msg {
|
||||||
logger := ctrld.LoggerFromCtx(ctx)
|
logger := ctrld.LoggerFromCtx(ctx)
|
||||||
ctrld.Log(ctx, logger.Debug(), "internal domain test query")
|
ctrld.Log(ctx, logger.Debug(), "Internal domain test query")
|
||||||
|
|
||||||
q := m.Question[0]
|
q := m.Question[0]
|
||||||
answer := new(dns.Msg)
|
answer := new(dns.Msg)
|
||||||
@@ -1521,18 +1521,18 @@ func (p *prog) monitorNetworkChanges(ctx context.Context) error {
|
|||||||
// Ensure that selfIP is an IPv4 address.
|
// Ensure that selfIP is an IPv4 address.
|
||||||
// If defaultRouteIP mistakenly returns an IPv6 (such as a ULA), clear it
|
// If defaultRouteIP mistakenly returns an IPv6 (such as a ULA), clear it
|
||||||
if ip := net.ParseIP(selfIP); ip != nil && ip.To4() == nil {
|
if ip := net.ParseIP(selfIP); ip != nil && ip.To4() == nil {
|
||||||
p.Debug().Msgf("defaultRouteIP returned a non-IPv4 address: %s, ignoring it", selfIP)
|
p.Debug().Msgf("DefaultRouteIP returned a non-ipv4 address: %s, ignoring it", selfIP)
|
||||||
selfIP = ""
|
selfIP = ""
|
||||||
}
|
}
|
||||||
var ipv6 string
|
var ipv6 string
|
||||||
|
|
||||||
if delta.New.DefaultRouteInterface != "" {
|
if delta.New.DefaultRouteInterface != "" {
|
||||||
p.Debug().Msgf("default route interface: %s, IPs: %v", delta.New.DefaultRouteInterface, delta.New.InterfaceIPs[delta.New.DefaultRouteInterface])
|
p.Debug().Msgf("Default route interface: %s, ips: %v", delta.New.DefaultRouteInterface, delta.New.InterfaceIPs[delta.New.DefaultRouteInterface])
|
||||||
for _, ip := range delta.New.InterfaceIPs[delta.New.DefaultRouteInterface] {
|
for _, ip := range delta.New.InterfaceIPs[delta.New.DefaultRouteInterface] {
|
||||||
ipAddr, _ := netip.ParsePrefix(ip.String())
|
ipAddr, _ := netip.ParsePrefix(ip.String())
|
||||||
addr := ipAddr.Addr()
|
addr := ipAddr.Addr()
|
||||||
if selfIP == "" && addr.Is4() {
|
if selfIP == "" && addr.Is4() {
|
||||||
p.Debug().Msgf("checking IP: %s", addr.String())
|
p.Debug().Msgf("Checking ip: %s", addr.String())
|
||||||
if !addr.IsLoopback() && !addr.IsLinkLocalUnicast() {
|
if !addr.IsLoopback() && !addr.IsLinkLocalUnicast() {
|
||||||
selfIP = addr.String()
|
selfIP = addr.String()
|
||||||
}
|
}
|
||||||
@@ -1543,12 +1543,12 @@ func (p *prog) monitorNetworkChanges(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If no default route interface is set yet, use the changed IPs
|
// If no default route interface is set yet, use the changed IPs
|
||||||
p.Debug().Msgf("no default route interface found, using changed IPs: %v", changeIPs)
|
p.Debug().Msgf("No default route interface found, using changed ips: %v", changeIPs)
|
||||||
for _, ip := range changeIPs {
|
for _, ip := range changeIPs {
|
||||||
ipAddr, _ := netip.ParsePrefix(ip.String())
|
ipAddr, _ := netip.ParsePrefix(ip.String())
|
||||||
addr := ipAddr.Addr()
|
addr := ipAddr.Addr()
|
||||||
if selfIP == "" && addr.Is4() {
|
if selfIP == "" && addr.Is4() {
|
||||||
p.Debug().Msgf("checking IP: %s", addr.String())
|
p.Debug().Msgf("Checking ip: %s", addr.String())
|
||||||
if !addr.IsLoopback() && !addr.IsLinkLocalUnicast() {
|
if !addr.IsLoopback() && !addr.IsLinkLocalUnicast() {
|
||||||
selfIP = addr.String()
|
selfIP = addr.String()
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -83,8 +83,8 @@ func doWithRetry(req *http.Request, maxRetries int, ip string) (*http.Response,
|
|||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
if ipReq != nil {
|
if ipReq != nil {
|
||||||
mainLog.Load().Warn().Err(err).Msgf("dial to %q failed", req.Host)
|
mainLog.Load().Warn().Err(err).Msgf("Dial to %q failed", req.Host)
|
||||||
mainLog.Load().Warn().Msgf("fallback to direct IP to download prod version: %q", ip)
|
mainLog.Load().Warn().Msgf("Fallback to direct ip to download prod version: %q", ip)
|
||||||
resp, err = client.Do(ipReq)
|
resp, err = client.Do(ipReq)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return resp, nil
|
return resp, nil
|
||||||
|
|||||||
@@ -20,19 +20,19 @@ import (
|
|||||||
const (
|
const (
|
||||||
// logWriterSize is the default buffer size for log writers
|
// logWriterSize is the default buffer size for log writers
|
||||||
// This provides sufficient space for runtime logs without excessive memory usage
|
// This provides sufficient space for runtime logs without excessive memory usage
|
||||||
logWriterSize = 1024 * 1024 * 5 // 5 MB
|
logWriterSize = 1024 * 1024 * 5 // 5 MB
|
||||||
|
|
||||||
// logWriterSmallSize is used for memory-constrained environments
|
// logWriterSmallSize is used for memory-constrained environments
|
||||||
// This reduces memory footprint while still maintaining log functionality
|
// This reduces memory footprint while still maintaining log functionality
|
||||||
logWriterSmallSize = 1024 * 1024 * 1 // 1 MB
|
logWriterSmallSize = 1024 * 1024 * 1 // 1 MB
|
||||||
|
|
||||||
// logWriterInitialSize is the initial buffer allocation
|
// logWriterInitialSize is the initial buffer allocation
|
||||||
// This provides immediate space for early log entries
|
// This provides immediate space for early log entries
|
||||||
logWriterInitialSize = 32 * 1024 // 32 KB
|
logWriterInitialSize = 32 * 1024 // 32 KB
|
||||||
|
|
||||||
// logWriterSentInterval controls how often logs are sent to external systems
|
// logWriterSentInterval controls how often logs are sent to external systems
|
||||||
// This balances real-time logging with system performance
|
// This balances real-time logging with system performance
|
||||||
logWriterSentInterval = time.Minute
|
logWriterSentInterval = time.Minute
|
||||||
|
|
||||||
// logWriterInitEndMarker marks the end of initialization logs
|
// logWriterInitEndMarker marks the end of initialization logs
|
||||||
// This helps separate startup logs from runtime logs
|
// This helps separate startup logs from runtime logs
|
||||||
@@ -40,7 +40,7 @@ const (
|
|||||||
|
|
||||||
// logWriterLogEndMarker marks the end of log sections
|
// logWriterLogEndMarker marks the end of log sections
|
||||||
// This provides clear boundaries for log parsing and analysis
|
// This provides clear boundaries for log parsing and analysis
|
||||||
logWriterLogEndMarker = "\n\n=== LOG_END ===\n\n"
|
logWriterLogEndMarker = "\n\n=== LOG_END ===\n\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Custom level encoders that handle NOTICE level
|
// Custom level encoders that handle NOTICE level
|
||||||
@@ -169,7 +169,7 @@ func (p *prog) initInternalLogging(externalCores []zapcore.Core) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
p.initInternalLogWriterOnce.Do(func() {
|
p.initInternalLogWriterOnce.Do(func() {
|
||||||
p.Notice().Msg("internal logging enabled")
|
p.Notice().Msg("Internal logging enabled")
|
||||||
p.internalLogWriter = newLogWriter()
|
p.internalLogWriter = newLogWriter()
|
||||||
p.internalLogSent = time.Now().Add(-logWriterSentInterval)
|
p.internalLogSent = time.Now().Add(-logWriterSentInterval)
|
||||||
p.internalWarnLogWriter = newSmallLogWriter()
|
p.internalWarnLogWriter = newSmallLogWriter()
|
||||||
|
|||||||
+5
-5
@@ -84,7 +84,7 @@ func (p *prog) detectLoop(msg *dns.Msg) {
|
|||||||
//
|
//
|
||||||
// See: https://thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html
|
// See: https://thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html
|
||||||
func (p *prog) checkDnsLoop() {
|
func (p *prog) checkDnsLoop() {
|
||||||
p.Debug().Msg("start checking DNS loop")
|
p.Debug().Msg("Start checking DNS loop")
|
||||||
upstream := make(map[string]*ctrld.UpstreamConfig)
|
upstream := make(map[string]*ctrld.UpstreamConfig)
|
||||||
p.loopMu.Lock()
|
p.loopMu.Lock()
|
||||||
for n, uc := range p.cfg.Upstream {
|
for n, uc := range p.cfg.Upstream {
|
||||||
@@ -93,7 +93,7 @@ func (p *prog) checkDnsLoop() {
|
|||||||
}
|
}
|
||||||
// Do not send test query to external upstream.
|
// Do not send test query to external upstream.
|
||||||
if !canBeLocalUpstream(uc.Domain) {
|
if !canBeLocalUpstream(uc.Domain) {
|
||||||
p.Debug().Msgf("skipping external: upstream.%s", n)
|
p.Debug().Msgf("Skipping external: upstream.%s", n)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
uid := uc.UID()
|
uid := uc.UID()
|
||||||
@@ -112,14 +112,14 @@ func (p *prog) checkDnsLoop() {
|
|||||||
}
|
}
|
||||||
resolver, err := ctrld.NewResolver(loggerCtx, uc)
|
resolver, err := ctrld.NewResolver(loggerCtx, uc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Warn().Err(err).Msgf("could not perform loop check for upstream: %q, endpoint: %q", uc.Name, uc.Endpoint)
|
p.Warn().Err(err).Msgf("Could not perform loop check for upstream: %q, endpoint: %q", uc.Name, uc.Endpoint)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if _, err := resolver.Resolve(context.Background(), msg); err != nil {
|
if _, err := resolver.Resolve(context.Background(), msg); err != nil {
|
||||||
p.Warn().Err(err).Msgf("could not send DNS loop check query for upstream: %q, endpoint: %q", uc.Name, uc.Endpoint)
|
p.Warn().Err(err).Msgf("Could not send DNS loop check query for upstream: %q, endpoint: %q", uc.Name, uc.Endpoint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.Debug().Msg("end checking DNS loop")
|
p.Debug().Msg("End checking DNS loop")
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkDnsLoopTicker performs p.checkDnsLoop every minute.
|
// checkDnsLoopTicker performs p.checkDnsLoop every minute.
|
||||||
|
|||||||
+3
-3
@@ -136,7 +136,7 @@ func initLoggingWithBackup(doBackup bool) []zapcore.Core {
|
|||||||
// Create parent directory if necessary.
|
// Create parent directory if necessary.
|
||||||
// This ensures log files can be created even if the directory doesn't exist
|
// This ensures log files can be created even if the directory doesn't exist
|
||||||
if err := os.MkdirAll(filepath.Dir(logFilePath), 0750); err != nil {
|
if err := os.MkdirAll(filepath.Dir(logFilePath), 0750); err != nil {
|
||||||
mainLog.Load().Error().Msgf("failed to create log path: %v", err)
|
mainLog.Load().Error().Msgf("Failed to create log path: %v", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,7 +147,7 @@ func initLoggingWithBackup(doBackup bool) []zapcore.Core {
|
|||||||
// Backup old log file with .1 suffix.
|
// Backup old log file with .1 suffix.
|
||||||
// This prevents log file corruption during rotation
|
// This prevents log file corruption during rotation
|
||||||
if err := os.Rename(logFilePath, logFilePath+oldLogSuffix); err != nil && !os.IsNotExist(err) {
|
if err := os.Rename(logFilePath, logFilePath+oldLogSuffix); err != nil && !os.IsNotExist(err) {
|
||||||
mainLog.Load().Error().Msgf("could not backup old log file: %v", err)
|
mainLog.Load().Error().Msgf("Could not backup old log file: %v", err)
|
||||||
} else {
|
} else {
|
||||||
// Backup was created, set flags for truncating old log file.
|
// Backup was created, set flags for truncating old log file.
|
||||||
// This ensures a clean start for the new log file
|
// This ensures a clean start for the new log file
|
||||||
@@ -156,7 +156,7 @@ func initLoggingWithBackup(doBackup bool) []zapcore.Core {
|
|||||||
}
|
}
|
||||||
logFile, err := openLogFile(logFilePath, flags)
|
logFile, err := openLogFile(logFilePath, flags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Error().Msgf("failed to create log file: %v", err)
|
mainLog.Load().Error().Msgf("Failed to create log file: %v", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
writers = append(writers, logFile)
|
writers = append(writers, logFile)
|
||||||
|
|||||||
+4
-4
@@ -122,7 +122,7 @@ func (p *prog) runMetricsServer(ctx context.Context, reloadCh chan struct{}) {
|
|||||||
addr := p.cfg.Service.MetricsListener
|
addr := p.cfg.Service.MetricsListener
|
||||||
ms, err := newMetricsServer(addr, reg)
|
ms, err := newMetricsServer(addr, reg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Warn().Err(err).Msg("could not create new metrics server")
|
mainLog.Load().Warn().Err(err).Msg("Could not create new metrics server")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Only start listener address if defined.
|
// Only start listener address if defined.
|
||||||
@@ -137,9 +137,9 @@ func (p *prog) runMetricsServer(ctx context.Context, reloadCh chan struct{}) {
|
|||||||
statsVersion.WithLabelValues(commit, runtime.Version(), curVersion()).Inc()
|
statsVersion.WithLabelValues(commit, runtime.Version(), curVersion()).Inc()
|
||||||
reg.MustRegister(statsTimeStart)
|
reg.MustRegister(statsTimeStart)
|
||||||
statsTimeStart.Set(float64(time.Now().Unix()))
|
statsTimeStart.Set(float64(time.Now().Unix()))
|
||||||
mainLog.Load().Debug().Msgf("starting metrics server on: %s", addr)
|
mainLog.Load().Debug().Msgf("Starting metrics server on: %s", addr)
|
||||||
if err := ms.start(); err != nil {
|
if err := ms.start(); err != nil {
|
||||||
mainLog.Load().Warn().Err(err).Msg("could not start metrics server")
|
mainLog.Load().Warn().Err(err).Msg("Could not start metrics server")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,7 +151,7 @@ func (p *prog) runMetricsServer(ctx context.Context, reloadCh chan struct{}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := ms.stop(); err != nil {
|
if err := ms.stop(); err != nil {
|
||||||
mainLog.Load().Warn().Err(err).Msg("could not stop metrics server")
|
mainLog.Load().Warn().Err(err).Msg("Could not stop metrics server")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ func virtualInterfaces(ctx context.Context) map[string]struct{} {
|
|||||||
s := make(map[string]struct{})
|
s := make(map[string]struct{})
|
||||||
entries, err := os.ReadDir("/sys/devices/virtual/net")
|
entries, err := os.ReadDir("/sys/devices/virtual/net")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error().Err(err).Msg("failed to read /sys/devices/virtual/net")
|
logger.Error().Err(err).Msg("Failed to read /sys/devices/virtual/net")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
for _, entry := range entries {
|
for _, entry := range entries {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ func (p *prog) watchLinkState(ctx context.Context) {
|
|||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
defer close(done)
|
defer close(done)
|
||||||
if err := netlink.LinkSubscribe(ch, done); err != nil {
|
if err := netlink.LinkSubscribe(ch, done); err != nil {
|
||||||
p.Warn().Err(err).Msg("could not subscribe link")
|
p.Warn().Err(err).Msg("Could not subscribe link")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
@@ -26,7 +26,7 @@ func (p *prog) watchLinkState(ctx context.Context) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if lu.Change&unix.IFF_UP != 0 {
|
if lu.Change&unix.IFF_UP != 0 {
|
||||||
p.Debug().Msgf("link state changed, re-bootstrapping")
|
p.Debug().Msgf("Link state changed, re-bootstrapping")
|
||||||
for _, uc := range p.cfg.Upstream {
|
for _, uc := range p.cfg.Upstream {
|
||||||
uc.ReBootstrap(ctrld.LoggerCtx(ctx, p.logger.Load()))
|
uc.ReBootstrap(ctrld.LoggerCtx(ctx, p.logger.Load()))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,12 +43,12 @@ func (p *prog) setupNetworkManager() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Debug().Err(err).Msg("could not write NetworkManager ctrld config file")
|
p.Debug().Err(err).Msg("Could not write NetworkManager ctrld config file")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
p.reloadNetworkManager()
|
p.reloadNetworkManager()
|
||||||
p.Debug().Msg("setup NetworkManager done")
|
p.Debug().Msg("Setup NetworkManager done")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,12 +62,12 @@ func (p *prog) restoreNetworkManager() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Debug().Err(err).Msg("could not remove NetworkManager ctrld config file")
|
p.Debug().Err(err).Msg("Could not remove NetworkManager ctrld config file")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
p.reloadNetworkManager()
|
p.reloadNetworkManager()
|
||||||
p.Debug().Msg("restore NetworkManager done")
|
p.Debug().Msg("Restore NetworkManager done")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,14 +76,14 @@ func (p *prog) reloadNetworkManager() {
|
|||||||
defer cancel()
|
defer cancel()
|
||||||
conn, err := dbus.NewSystemConnectionContext(ctx)
|
conn, err := dbus.NewSystemConnectionContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Error().Err(err).Msg("could not create new system connection")
|
p.Error().Err(err).Msg("Could not create new system connection")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
waitCh := make(chan string)
|
waitCh := make(chan string)
|
||||||
if _, err := conn.ReloadUnitContext(ctx, nmSystemdUnitName, "ignore-dependencies", waitCh); err != nil {
|
if _, err := conn.ReloadUnitContext(ctx, nmSystemdUnitName, "ignore-dependencies", waitCh); err != nil {
|
||||||
p.Debug().Err(err).Msg("could not reload NetworkManager")
|
p.Debug().Err(err).Msg("Could not reload NetworkManager")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
<-waitCh
|
<-waitCh
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ func generateNextDNSConfig(uid string) {
|
|||||||
if uid == "" {
|
if uid == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
mainLog.Load().Info().Msg("generating ctrld config for NextDNS resolver")
|
mainLog.Load().Info().Msg("Generating ctrld config for NextDNS resolver")
|
||||||
cfg = ctrld.Config{
|
cfg = ctrld.Config{
|
||||||
Listener: map[string]*ctrld.ListenerConfig{
|
Listener: map[string]*ctrld.ListenerConfig{
|
||||||
"0": {
|
"0": {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ func allocateIP(ip string) error {
|
|||||||
mainLog.Load().Debug().Str("ip", ip).Msg("Allocating IP address")
|
mainLog.Load().Debug().Str("ip", ip).Msg("Allocating IP address")
|
||||||
cmd := exec.Command("ifconfig", "lo0", "alias", ip, "up")
|
cmd := exec.Command("ifconfig", "lo0", "alias", ip, "up")
|
||||||
if err := cmd.Run(); err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
mainLog.Load().Error().Err(err).Msg("allocateIP failed")
|
mainLog.Load().Error().Err(err).Msg("AllocateIP failed")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
mainLog.Load().Debug().Str("ip", ip).Msg("IP address allocated successfully")
|
mainLog.Load().Debug().Str("ip", ip).Msg("IP address allocated successfully")
|
||||||
@@ -29,7 +29,7 @@ func deAllocateIP(ip string) error {
|
|||||||
mainLog.Load().Debug().Str("ip", ip).Msg("Deallocating IP address")
|
mainLog.Load().Debug().Str("ip", ip).Msg("Deallocating IP address")
|
||||||
cmd := exec.Command("ifconfig", "lo0", "-alias", ip)
|
cmd := exec.Command("ifconfig", "lo0", "-alias", ip)
|
||||||
if err := cmd.Run(); err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
mainLog.Load().Error().Err(err).Msg("deAllocateIP failed")
|
mainLog.Load().Error().Err(err).Msg("DeAllocateIP failed")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
mainLog.Load().Debug().Str("ip", ip).Msg("IP address deallocated successfully")
|
mainLog.Load().Debug().Str("ip", ip).Msg("IP address deallocated successfully")
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ func setDNS(iface *net.Interface, nameservers []string) error {
|
|||||||
|
|
||||||
r, err := dns.NewOSConfigurator(logf, &health.Tracker{}, &controlknobs.Knobs{}, iface.Name)
|
r, err := dns.NewOSConfigurator(logf, &health.Tracker{}, &controlknobs.Knobs{}, iface.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Error().Err(err).Msg("failed to create DNS OS configurator")
|
mainLog.Load().Error().Err(err).Msg("Failed to create DNS OS configurator")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,11 +65,11 @@ func setDNS(iface *net.Interface, nameservers []string) error {
|
|||||||
if sds, err := searchDomains(); err == nil {
|
if sds, err := searchDomains(); err == nil {
|
||||||
osConfig.SearchDomains = sds
|
osConfig.SearchDomains = sds
|
||||||
} else {
|
} else {
|
||||||
mainLog.Load().Debug().Err(err).Msg("failed to get search domains list")
|
mainLog.Load().Debug().Err(err).Msg("Failed to get search domains list")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := r.SetDNS(osConfig); err != nil {
|
if err := r.SetDNS(osConfig); err != nil {
|
||||||
mainLog.Load().Error().Err(err).Msg("failed to set DNS")
|
mainLog.Load().Error().Err(err).Msg("Failed to set DNS")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,12 +88,12 @@ func resetDNS(iface *net.Interface) error {
|
|||||||
|
|
||||||
r, err := dns.NewOSConfigurator(logf, &health.Tracker{}, &controlknobs.Knobs{}, iface.Name)
|
r, err := dns.NewOSConfigurator(logf, &health.Tracker{}, &controlknobs.Knobs{}, iface.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Error().Err(err).Msg("failed to create DNS OS configurator")
|
mainLog.Load().Error().Err(err).Msg("Failed to create DNS OS configurator")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := r.Close(); err != nil {
|
if err := r.Close(); err != nil {
|
||||||
mainLog.Load().Error().Err(err).Msg("failed to rollback DNS setting")
|
mainLog.Load().Error().Err(err).Msg("Failed to rollback DNS setting")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-8
@@ -36,7 +36,7 @@ func allocateIP(ip string) error {
|
|||||||
mainLog.Load().Debug().Str("ip", ip).Msg("Allocating IP address")
|
mainLog.Load().Debug().Str("ip", ip).Msg("Allocating IP address")
|
||||||
cmd := exec.Command("ip", "a", "add", ip+"/24", "dev", "lo")
|
cmd := exec.Command("ip", "a", "add", ip+"/24", "dev", "lo")
|
||||||
if out, err := cmd.CombinedOutput(); err != nil {
|
if out, err := cmd.CombinedOutput(); err != nil {
|
||||||
mainLog.Load().Error().Err(err).Msgf("allocateIP failed: %s", string(out))
|
mainLog.Load().Error().Err(err).Msgf("AllocateIP failed: %s", string(out))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
mainLog.Load().Debug().Str("ip", ip).Msg("IP address allocated successfully")
|
mainLog.Load().Debug().Str("ip", ip).Msg("IP address allocated successfully")
|
||||||
@@ -47,7 +47,7 @@ func deAllocateIP(ip string) error {
|
|||||||
mainLog.Load().Debug().Str("ip", ip).Msg("Deallocating IP address")
|
mainLog.Load().Debug().Str("ip", ip).Msg("Deallocating IP address")
|
||||||
cmd := exec.Command("ip", "a", "del", ip+"/24", "dev", "lo")
|
cmd := exec.Command("ip", "a", "del", ip+"/24", "dev", "lo")
|
||||||
if err := cmd.Run(); err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
mainLog.Load().Error().Err(err).Msg("deAllocateIP failed")
|
mainLog.Load().Error().Err(err).Msg("DeAllocateIP failed")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
mainLog.Load().Debug().Str("ip", ip).Msg("IP address deallocated successfully")
|
mainLog.Load().Debug().Str("ip", ip).Msg("IP address deallocated successfully")
|
||||||
@@ -66,7 +66,7 @@ func setDNS(iface *net.Interface, nameservers []string) error {
|
|||||||
|
|
||||||
r, err := dns.NewOSConfigurator(logf, &health.Tracker{}, &controlknobs.Knobs{}, iface.Name)
|
r, err := dns.NewOSConfigurator(logf, &health.Tracker{}, &controlknobs.Knobs{}, iface.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Error().Err(err).Msg("failed to create DNS OS configurator")
|
mainLog.Load().Error().Err(err).Msg("Failed to create dns os configurator")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ func setDNS(iface *net.Interface, nameservers []string) error {
|
|||||||
if sds, err := searchDomains(); err == nil {
|
if sds, err := searchDomains(); err == nil {
|
||||||
osConfig.SearchDomains = sds
|
osConfig.SearchDomains = sds
|
||||||
} else {
|
} else {
|
||||||
mainLog.Load().Debug().Err(err).Msg("failed to get search domains list")
|
mainLog.Load().Debug().Err(err).Msg("Failed to get search domains list")
|
||||||
}
|
}
|
||||||
trySystemdResolve := false
|
trySystemdResolve := false
|
||||||
if err := r.SetDNS(osConfig); err != nil {
|
if err := r.SetDNS(osConfig); err != nil {
|
||||||
@@ -149,7 +149,7 @@ func resetDNS(iface *net.Interface) (err error) {
|
|||||||
if r, oerr := dns.NewOSConfigurator(logf, &health.Tracker{}, &controlknobs.Knobs{}, iface.Name); oerr == nil {
|
if r, oerr := dns.NewOSConfigurator(logf, &health.Tracker{}, &controlknobs.Knobs{}, iface.Name); oerr == nil {
|
||||||
_ = r.SetDNS(dns.OSConfig{})
|
_ = r.SetDNS(dns.OSConfig{})
|
||||||
if err := r.Close(); err != nil {
|
if err := r.Close(); err != nil {
|
||||||
mainLog.Load().Error().Err(err).Msg("failed to rollback DNS setting")
|
mainLog.Load().Error().Err(err).Msg("Failed to rollback dns setting")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = nil
|
err = nil
|
||||||
@@ -177,18 +177,18 @@ func resetDNS(iface *net.Interface) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO(cuonglm): handle DHCPv6 properly.
|
// TODO(cuonglm): handle DHCPv6 properly.
|
||||||
mainLog.Load().Debug().Msg("checking for IPv6 availability")
|
mainLog.Load().Debug().Msg("Checking for ipv6 availability")
|
||||||
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 && !errAddrInUse(err) {
|
if err != nil && !errAddrInUse(err) {
|
||||||
mainLog.Load().Debug().Err(err).Msg("could not exchange DHCPv6")
|
mainLog.Load().Debug().Err(err).Msg("Could not exchange dhcpv6")
|
||||||
}
|
}
|
||||||
for _, packet := range conversation {
|
for _, packet := range conversation {
|
||||||
if packet.Type() == dhcpv6.MessageTypeReply {
|
if packet.Type() == dhcpv6.MessageTypeReply {
|
||||||
msg, err := packet.GetInnerMessage()
|
msg, err := packet.GetInnerMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Debug().Err(err).Msg("could not get inner DHCPv6 message")
|
mainLog.Load().Debug().Err(err).Msg("Could not get inner dhcpv6 message")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
nameservers := msg.Options.DNS()
|
nameservers := msg.Options.DNS()
|
||||||
|
|||||||
+10
-10
@@ -111,24 +111,24 @@ func restoreDNS(iface *net.Interface) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(v4ns) > 0 {
|
if len(v4ns) > 0 {
|
||||||
mainLog.Load().Debug().Msgf("restoring IPv4 static DNS for interface %q: %v", iface.Name, v4ns)
|
mainLog.Load().Debug().Msgf("Restoring IPv4 static DNS for interface %q: %v", iface.Name, v4ns)
|
||||||
if err := setDNS(iface, v4ns); err != nil {
|
if err := setDNS(iface, v4ns); err != nil {
|
||||||
return fmt.Errorf("restoreDNS (IPv4): %w", err)
|
return fmt.Errorf("restoreDNS (IPv4): %w", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mainLog.Load().Debug().Msgf("restoring IPv4 DHCP for interface %q", iface.Name)
|
mainLog.Load().Debug().Msgf("Restoring IPv4 DHCP for interface %q", iface.Name)
|
||||||
if err := luid.SetDNS(windows.AF_INET, nil, nil); err != nil {
|
if err := luid.SetDNS(windows.AF_INET, nil, nil); err != nil {
|
||||||
return fmt.Errorf("restoreDNS (IPv4 clear): %w", err)
|
return fmt.Errorf("restoreDNS (IPv4 clear): %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(v6ns) > 0 {
|
if len(v6ns) > 0 {
|
||||||
mainLog.Load().Debug().Msgf("restoring IPv6 static DNS for interface %q: %v", iface.Name, v6ns)
|
mainLog.Load().Debug().Msgf("Restoring IPv6 static DNS for interface %q: %v", iface.Name, v6ns)
|
||||||
if err := setDNS(iface, v6ns); err != nil {
|
if err := setDNS(iface, v6ns); err != nil {
|
||||||
return fmt.Errorf("restoreDNS (IPv6): %w", err)
|
return fmt.Errorf("restoreDNS (IPv6): %w", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mainLog.Load().Debug().Msgf("restoring IPv6 DHCP for interface %q", iface.Name)
|
mainLog.Load().Debug().Msgf("Restoring IPv6 DHCP for interface %q", iface.Name)
|
||||||
if err := luid.SetDNS(windows.AF_INET6, nil, nil); err != nil {
|
if err := luid.SetDNS(windows.AF_INET6, nil, nil); err != nil {
|
||||||
return fmt.Errorf("restoreDNS (IPv6 clear): %w", err)
|
return fmt.Errorf("restoreDNS (IPv6 clear): %w", err)
|
||||||
}
|
}
|
||||||
@@ -141,12 +141,12 @@ func restoreDNS(iface *net.Interface) (err error) {
|
|||||||
func currentDNS(iface *net.Interface) []string {
|
func currentDNS(iface *net.Interface) []string {
|
||||||
luid, err := winipcfg.LUIDFromIndex(uint32(iface.Index))
|
luid, err := winipcfg.LUIDFromIndex(uint32(iface.Index))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Error().Err(err).Msg("failed to get interface LUID")
|
mainLog.Load().Error().Err(err).Msg("Failed to get interface LUID")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
nameservers, err := luid.DNS()
|
nameservers, err := luid.DNS()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Error().Err(err).Msg("failed to get interface DNS")
|
mainLog.Load().Error().Err(err).Msg("Failed to get interface DNS")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
ns := make([]string, 0, len(nameservers))
|
ns := make([]string, 0, len(nameservers))
|
||||||
@@ -174,7 +174,7 @@ func currentStaticDNS(iface *net.Interface) ([]string, error) {
|
|||||||
interfaceKeyPath := path + guid.String()
|
interfaceKeyPath := path + guid.String()
|
||||||
k, err := registry.OpenKey(registry.LOCAL_MACHINE, interfaceKeyPath, registry.QUERY_VALUE)
|
k, err := registry.OpenKey(registry.LOCAL_MACHINE, interfaceKeyPath, registry.QUERY_VALUE)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Debug().Err(err).Msgf("failed to open registry key %q for interface %q; trying next key", interfaceKeyPath, iface.Name)
|
mainLog.Load().Debug().Err(err).Msgf("Failed to open registry key %q for interface %q; trying next key", interfaceKeyPath, iface.Name)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
func() {
|
func() {
|
||||||
@@ -182,11 +182,11 @@ func currentStaticDNS(iface *net.Interface) ([]string, error) {
|
|||||||
for _, keyName := range []string{"NameServer", "ProfileNameServer"} {
|
for _, keyName := range []string{"NameServer", "ProfileNameServer"} {
|
||||||
value, _, err := k.GetStringValue(keyName)
|
value, _, err := k.GetStringValue(keyName)
|
||||||
if err != nil && !errors.Is(err, registry.ErrNotExist) {
|
if err != nil && !errors.Is(err, registry.ErrNotExist) {
|
||||||
mainLog.Load().Debug().Err(err).Msgf("error reading %s registry key", keyName)
|
mainLog.Load().Debug().Err(err).Msgf("Error reading %s registry key", keyName)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if len(value) > 0 {
|
if len(value) > 0 {
|
||||||
mainLog.Load().Debug().Msgf("found static DNS for interface %q: %s", iface.Name, value)
|
mainLog.Load().Debug().Msgf("Found static DNS for interface %q: %s", iface.Name, value)
|
||||||
parsed := parseDNSServers(value)
|
parsed := parseDNSServers(value)
|
||||||
for _, pns := range parsed {
|
for _, pns := range parsed {
|
||||||
if !slices.Contains(ns, pns) {
|
if !slices.Contains(ns, pns) {
|
||||||
@@ -198,7 +198,7 @@ func currentStaticDNS(iface *net.Interface) ([]string, error) {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
if len(ns) == 0 {
|
if len(ns) == 0 {
|
||||||
mainLog.Load().Debug().Msgf("no static DNS values found for interface %q", iface.Name)
|
mainLog.Load().Debug().Msgf("No static DNS values found for interface %q", iface.Name)
|
||||||
}
|
}
|
||||||
return ns, nil
|
return ns, nil
|
||||||
}
|
}
|
||||||
|
|||||||
+88
-88
@@ -165,9 +165,9 @@ func (p *prog) runWait() {
|
|||||||
var newCfg *ctrld.Config
|
var newCfg *ctrld.Config
|
||||||
select {
|
select {
|
||||||
case sig := <-reloadSigCh:
|
case sig := <-reloadSigCh:
|
||||||
p.Notice().Msgf("got signal: %s, reloading...", sig.String())
|
p.Notice().Msgf("Got signal: %s, reloading...", sig.String())
|
||||||
case <-p.reloadCh:
|
case <-p.reloadCh:
|
||||||
p.Notice().Msg("reloading...")
|
p.Notice().Msg("Reloading...")
|
||||||
case apiCfg := <-p.apiReloadCh:
|
case apiCfg := <-p.apiReloadCh:
|
||||||
newCfg = apiCfg
|
newCfg = apiCfg
|
||||||
case <-p.stopCh:
|
case <-p.stopCh:
|
||||||
@@ -190,18 +190,18 @@ func (p *prog) runWait() {
|
|||||||
}
|
}
|
||||||
v.SetConfigFile(confFile)
|
v.SetConfigFile(confFile)
|
||||||
if err := v.ReadInConfig(); err != nil {
|
if err := v.ReadInConfig(); err != nil {
|
||||||
p.Error().Err(err).Msg("could not read new config")
|
p.Error().Err(err).Msg("Could not read new config")
|
||||||
waitOldRunDone()
|
waitOldRunDone()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := v.Unmarshal(&newCfg); err != nil {
|
if err := v.Unmarshal(&newCfg); err != nil {
|
||||||
p.Error().Err(err).Msg("could not unmarshal new config")
|
p.Error().Err(err).Msg("Could not unmarshal new config")
|
||||||
waitOldRunDone()
|
waitOldRunDone()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if cdUID != "" {
|
if cdUID != "" {
|
||||||
if rc, err := processCDFlags(newCfg); err != nil {
|
if rc, err := processCDFlags(newCfg); err != nil {
|
||||||
p.Error().Err(err).Msg("could not fetch ControlD config")
|
p.Error().Err(err).Msg("Could not fetch controld config")
|
||||||
waitOldRunDone()
|
waitOldRunDone()
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
@@ -231,29 +231,29 @@ func (p *prog) runWait() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := validateConfig(newCfg); err != nil {
|
if err := validateConfig(newCfg); err != nil {
|
||||||
p.Error().Err(err).Msg("invalid config")
|
p.Error().Err(err).Msg("Invalid config")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
addExtraSplitDnsRule(newCfg)
|
addExtraSplitDnsRule(newCfg)
|
||||||
if err := writeConfigFile(newCfg); err != nil {
|
if err := writeConfigFile(newCfg); err != nil {
|
||||||
p.Error().Err(err).Msg("could not write new config")
|
p.Error().Err(err).Msg("Could not write new config")
|
||||||
}
|
}
|
||||||
|
|
||||||
// This needs to be done here, otherwise, the DNS handler may observe an invalid
|
// This needs to be done here, otherwise, the DNS handler may observe an invalid
|
||||||
// upstream config because its initialization function have not been called yet.
|
// upstream config because its initialization function have not been called yet.
|
||||||
p.Debug().Msg("setup upstream with new config")
|
p.Debug().Msg("Setup upstream with new config")
|
||||||
p.setupUpstream(newCfg)
|
p.setupUpstream(newCfg)
|
||||||
|
|
||||||
p.mu.Lock()
|
p.mu.Lock()
|
||||||
*p.cfg = *newCfg
|
*p.cfg = *newCfg
|
||||||
p.mu.Unlock()
|
p.mu.Unlock()
|
||||||
|
|
||||||
p.Notice().Msg("reloading config successfully")
|
p.Notice().Msg("Reloading config successfully")
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case p.reloadDoneCh <- struct{}{}:
|
case p.reloadDoneCh <- struct{}{}:
|
||||||
p.Debug().Msg("reload done signal sent")
|
p.Debug().Msg("Reload done signal sent")
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -272,7 +272,7 @@ func (p *prog) postRun() {
|
|||||||
if !service.Interactive() {
|
if !service.Interactive() {
|
||||||
p.resetDNS(false, false)
|
p.resetDNS(false, false)
|
||||||
ns := ctrld.InitializeOsResolver(ctrld.LoggerCtx(context.Background(), p.logger.Load()), false)
|
ns := ctrld.InitializeOsResolver(ctrld.LoggerCtx(context.Background(), p.logger.Load()), false)
|
||||||
p.Debug().Msgf("initialized OS resolver with nameservers: %v", ns)
|
p.Debug().Msgf("Initialized os resolver with nameservers: %v", ns)
|
||||||
p.setDNS()
|
p.setDNS()
|
||||||
p.csSetDnsDone <- struct{}{}
|
p.csSetDnsDone <- struct{}{}
|
||||||
close(p.csSetDnsDone)
|
close(p.csSetDnsDone)
|
||||||
@@ -290,7 +290,7 @@ func (p *prog) apiConfigReload() {
|
|||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
|
||||||
logger := p.logger.Load().With().Str("mode", "api-reload")
|
logger := p.logger.Load().With().Str("mode", "api-reload")
|
||||||
logger.Debug().Msg("starting custom config reload timer")
|
logger.Debug().Msg("Starting custom config reload timer")
|
||||||
lastUpdated := time.Now().Unix()
|
lastUpdated := time.Now().Unix()
|
||||||
curVerStr := curVersion()
|
curVerStr := curVersion()
|
||||||
curVer, err := semver.NewVersion(curVerStr)
|
curVer, err := semver.NewVersion(curVerStr)
|
||||||
@@ -300,7 +300,7 @@ func (p *prog) apiConfigReload() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
l = l.Err(err)
|
l = l.Err(err)
|
||||||
}
|
}
|
||||||
l.Msgf("current version is not stable, skipping self-upgrade: %s", curVerStr)
|
l.Msgf("Current version is not stable, skipping self-upgrade: %s", curVerStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
doReloadApiConfig := func(forced bool, logger *ctrld.Logger) {
|
doReloadApiConfig := func(forced bool, logger *ctrld.Logger) {
|
||||||
@@ -308,7 +308,7 @@ func (p *prog) apiConfigReload() {
|
|||||||
resolverConfig, err := controld.FetchResolverConfig(loggerCtx, cdUID, appVersion, cdDev)
|
resolverConfig, err := controld.FetchResolverConfig(loggerCtx, cdUID, appVersion, cdDev)
|
||||||
selfUninstallCheck(err, p, logger)
|
selfUninstallCheck(err, p, logger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warn().Err(err).Msg("could not fetch resolver config")
|
logger.Warn().Err(err).Msg("Could not fetch resolver config")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,9 +322,9 @@ func (p *prog) apiConfigReload() {
|
|||||||
curDeactivationPin := cdDeactivationPin.Load()
|
curDeactivationPin := cdDeactivationPin.Load()
|
||||||
switch {
|
switch {
|
||||||
case curDeactivationPin != defaultDeactivationPin:
|
case curDeactivationPin != defaultDeactivationPin:
|
||||||
logger.Debug().Msg("saving deactivation pin")
|
logger.Debug().Msg("Saving deactivation pin")
|
||||||
case curDeactivationPin != newDeactivationPin:
|
case curDeactivationPin != newDeactivationPin:
|
||||||
logger.Debug().Msg("update deactivation pin")
|
logger.Debug().Msg("Update deactivation pin")
|
||||||
}
|
}
|
||||||
cdDeactivationPin.Store(newDeactivationPin)
|
cdDeactivationPin.Store(newDeactivationPin)
|
||||||
} else {
|
} else {
|
||||||
@@ -347,7 +347,7 @@ func (p *prog) apiConfigReload() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if noCustomConfig && !noExcludeListChanged {
|
if noCustomConfig && !noExcludeListChanged {
|
||||||
logger.Debug().Msg("exclude list changes detected, reloading...")
|
logger.Debug().Msg("Exclude list changes detected, reloading...")
|
||||||
p.apiReloadCh <- nil
|
p.apiReloadCh <- nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -362,16 +362,16 @@ func (p *prog) apiConfigReload() {
|
|||||||
cfgErr = validateConfig(cfg)
|
cfgErr = validateConfig(cfg)
|
||||||
}
|
}
|
||||||
if cfgErr != nil {
|
if cfgErr != nil {
|
||||||
logger.Warn().Err(err).Msg("skipping invalid custom config")
|
logger.Warn().Err(err).Msg("Skipping invalid custom config")
|
||||||
if _, err := controld.UpdateCustomLastFailed(loggerCtx, cdUID, appVersion, cdDev, true); err != nil {
|
if _, err := controld.UpdateCustomLastFailed(loggerCtx, cdUID, appVersion, cdDev, true); err != nil {
|
||||||
logger.Error().Err(err).Msg("could not mark custom last update failed")
|
logger.Error().Err(err).Msg("Could not mark custom last update failed")
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger.Debug().Msg("custom config changes detected, reloading...")
|
logger.Debug().Msg("Custom config changes detected, reloading...")
|
||||||
p.apiReloadCh <- cfg
|
p.apiReloadCh <- cfg
|
||||||
} else {
|
} else {
|
||||||
logger.Debug().Msg("custom config does not change")
|
logger.Debug().Msg("Custom config does not change")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
@@ -396,14 +396,14 @@ func (p *prog) setupUpstream(cfg *ctrld.Config) {
|
|||||||
sdns := uc.Type == ctrld.ResolverTypeSDNS
|
sdns := uc.Type == ctrld.ResolverTypeSDNS
|
||||||
uc.Init(loggerCtx)
|
uc.Init(loggerCtx)
|
||||||
if sdns {
|
if sdns {
|
||||||
p.Debug().Msgf("initialized DNS Stamps with endpoint: %s, type: %s", uc.Endpoint, uc.Type)
|
p.Debug().Msgf("Initialized dns stamps with endpoint: %s, type: %s", uc.Endpoint, uc.Type)
|
||||||
}
|
}
|
||||||
isControlDUpstream = isControlDUpstream || uc.IsControlD()
|
isControlDUpstream = isControlDUpstream || uc.IsControlD()
|
||||||
if uc.BootstrapIP == "" {
|
if uc.BootstrapIP == "" {
|
||||||
uc.SetupBootstrapIP(ctrld.LoggerCtx(context.Background(), p.logger.Load()))
|
uc.SetupBootstrapIP(ctrld.LoggerCtx(context.Background(), p.logger.Load()))
|
||||||
p.Info().Msgf("bootstrap IPs for upstream.%s: %q", n, uc.BootstrapIPs())
|
p.Info().Msgf("Bootstrap ips for upstream.%s: %q", n, uc.BootstrapIPs())
|
||||||
} else {
|
} else {
|
||||||
p.Info().Str("bootstrap_ip", uc.BootstrapIP).Msgf("using bootstrap IP for upstream.%s", n)
|
p.Info().Str("bootstrap_ip", uc.BootstrapIP).Msgf("Using bootstrap ip for upstream.%s", n)
|
||||||
}
|
}
|
||||||
uc.SetCertPool(rootCertPool)
|
uc.SetCertPool(rootCertPool)
|
||||||
go uc.Ping(loggerCtx)
|
go uc.Ping(loggerCtx)
|
||||||
@@ -444,9 +444,9 @@ func (p *prog) run(reload bool, reloadCh chan struct{}) {
|
|||||||
p.csSetDnsDone = make(chan struct{}, 1)
|
p.csSetDnsDone = make(chan struct{}, 1)
|
||||||
p.registerControlServerHandler()
|
p.registerControlServerHandler()
|
||||||
if err := p.cs.start(); err != nil {
|
if err := p.cs.start(); err != nil {
|
||||||
p.Warn().Err(err).Msg("could not start control server")
|
p.Warn().Err(err).Msg("Could not start control server")
|
||||||
}
|
}
|
||||||
p.Debug().Msgf("control server started: %s", p.cs.addr)
|
p.Debug().Msgf("Control server started: %s", p.cs.addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.onStartedDone = make(chan struct{})
|
p.onStartedDone = make(chan struct{})
|
||||||
@@ -458,7 +458,7 @@ func (p *prog) run(reload bool, reloadCh chan struct{}) {
|
|||||||
if p.cfg.Service.CacheEnable {
|
if p.cfg.Service.CacheEnable {
|
||||||
cacher, err := dnscache.NewLRUCache(p.cfg.Service.CacheSize)
|
cacher, err := dnscache.NewLRUCache(p.cfg.Service.CacheSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Error().Err(err).Msg("failed to create cacher, caching is disabled")
|
p.Error().Err(err).Msg("Failed to create cacher, caching is disabled")
|
||||||
} else {
|
} else {
|
||||||
p.cache = cacher
|
p.cache = cacher
|
||||||
p.cacheFlushDomainsMap = make(map[string]struct{}, 256)
|
p.cacheFlushDomainsMap = make(map[string]struct{}, 256)
|
||||||
@@ -475,7 +475,7 @@ func (p *prog) run(reload bool, reloadCh chan struct{}) {
|
|||||||
for _, cidr := range nc.Cidrs {
|
for _, cidr := range nc.Cidrs {
|
||||||
_, ipNet, err := net.ParseCIDR(cidr)
|
_, ipNet, err := net.ParseCIDR(cidr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Error().Err(err).Str("network", nc.Name).Str("cidr", cidr).Msg("invalid cidr")
|
p.Error().Err(err).Str("network", nc.Name).Str("cidr", cidr).Msg("Invalid cidr")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
nc.IPNets = append(nc.IPNets, ipNet)
|
nc.IPNets = append(nc.IPNets, ipNet)
|
||||||
@@ -528,17 +528,17 @@ func (p *prog) run(reload bool, reloadCh chan struct{}) {
|
|||||||
listenerConfig := p.cfg.Listener[listenerNum]
|
listenerConfig := p.cfg.Listener[listenerNum]
|
||||||
upstreamConfig := p.cfg.Upstream[listenerNum]
|
upstreamConfig := p.cfg.Upstream[listenerNum]
|
||||||
if upstreamConfig == nil {
|
if upstreamConfig == nil {
|
||||||
p.Warn().Msgf("no default upstream for: [listener.%s]", listenerNum)
|
p.Warn().Msgf("No default upstream for: [listener.%s]", listenerNum)
|
||||||
}
|
}
|
||||||
addr := net.JoinHostPort(listenerConfig.IP, strconv.Itoa(listenerConfig.Port))
|
addr := net.JoinHostPort(listenerConfig.IP, strconv.Itoa(listenerConfig.Port))
|
||||||
p.Info().Msgf("starting DNS server on listener.%s: %s", listenerNum, addr)
|
p.Info().Msgf("Starting dns server on listener.%s: %s", listenerNum, addr)
|
||||||
// serveCtx uses Background() context so listeners survive between reloads.
|
// serveCtx uses Background() context so listeners survive between reloads.
|
||||||
// Changes to listeners config require a service restart, not just reload.
|
// Changes to listeners config require a service restart, not just reload.
|
||||||
serveCtx := context.Background()
|
serveCtx := context.Background()
|
||||||
if err := p.serveDNS(serveCtx, listenerNum); err != nil {
|
if err := p.serveDNS(serveCtx, listenerNum); err != nil {
|
||||||
p.Fatal().Err(err).Msgf("unable to start dns proxy on listener.%s", listenerNum)
|
p.Fatal().Err(err).Msgf("Unable to start dns proxy on listener.%s", listenerNum)
|
||||||
}
|
}
|
||||||
p.Debug().Msgf("end of serveDNS listener.%s: %s", listenerNum, addr)
|
p.Debug().Msgf("End of serveDNS listener.%s: %s", listenerNum, addr)
|
||||||
}(listenerNum)
|
}(listenerNum)
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
@@ -599,7 +599,7 @@ func (p *prog) setupClientInfoDiscover() {
|
|||||||
selfIP := p.defaultRouteIP()
|
selfIP := p.defaultRouteIP()
|
||||||
p.ciTable = clientinfo.NewTable(&cfg, selfIP, cdUID, p.ptrNameservers, p.logger.Load())
|
p.ciTable = clientinfo.NewTable(&cfg, selfIP, cdUID, p.ptrNameservers, p.logger.Load())
|
||||||
if leaseFile := p.cfg.Service.DHCPLeaseFile; leaseFile != "" {
|
if leaseFile := p.cfg.Service.DHCPLeaseFile; leaseFile != "" {
|
||||||
p.Debug().Msgf("watching custom lease file: %s", leaseFile)
|
p.Debug().Msgf("Watching custom lease file: %s", leaseFile)
|
||||||
format := ctrld.LeaseFileFormat(p.cfg.Service.DHCPLeaseFileFormat)
|
format := ctrld.LeaseFileFormat(p.cfg.Service.DHCPLeaseFileFormat)
|
||||||
p.ciTable.AddLeaseFile(leaseFile, format)
|
p.ciTable.AddLeaseFile(leaseFile, format)
|
||||||
}
|
}
|
||||||
@@ -618,16 +618,16 @@ func (p *prog) metricsEnabled() bool {
|
|||||||
|
|
||||||
func (p *prog) Stop(_ service.Service) error {
|
func (p *prog) Stop(_ service.Service) error {
|
||||||
p.stopDnsWatchers()
|
p.stopDnsWatchers()
|
||||||
p.Debug().Msg("dns watchers stopped")
|
p.Debug().Msg("Dns watchers stopped")
|
||||||
for _, f := range p.onStopped {
|
for _, f := range p.onStopped {
|
||||||
f()
|
f()
|
||||||
}
|
}
|
||||||
p.Debug().Msg("finish running onStopped functions")
|
p.Debug().Msg("Finish running onStopped functions")
|
||||||
defer func() {
|
defer func() {
|
||||||
p.Info().Msg("Service stopped")
|
p.Info().Msg("Service stopped")
|
||||||
}()
|
}()
|
||||||
if err := p.deAllocateIP(); err != nil {
|
if err := p.deAllocateIP(); err != nil {
|
||||||
p.Error().Err(err).Msg("de-allocate ip failed")
|
p.Error().Err(err).Msg("De-allocate ip failed")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if deactivationPinSet() {
|
if deactivationPinSet() {
|
||||||
@@ -639,16 +639,16 @@ func (p *prog) Stop(_ service.Service) error {
|
|||||||
// No valid pin code was checked, that mean we are stopping
|
// No valid pin code was checked, that mean we are stopping
|
||||||
// because of OS signal sent directly from someone else.
|
// because of OS signal sent directly from someone else.
|
||||||
// In this case, restarting ctrld service by ourselves.
|
// In this case, restarting ctrld service by ourselves.
|
||||||
p.Debug().Msgf("receiving stopping signal without valid pin code")
|
p.Debug().Msgf("Receiving stopping signal without valid pin code")
|
||||||
p.Debug().Msgf("self restarting ctrld service")
|
p.Debug().Msgf("Self restarting ctrld service")
|
||||||
if exe, err := os.Executable(); err == nil {
|
if exe, err := os.Executable(); err == nil {
|
||||||
cmd := exec.Command(exe, "restart")
|
cmd := exec.Command(exe, "restart")
|
||||||
cmd.SysProcAttr = sysProcAttrForDetachedChildProcess()
|
cmd.SysProcAttr = sysProcAttrForDetachedChildProcess()
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
p.Error().Err(err).Msg("failed to run self restart command")
|
p.Error().Err(err).Msg("Failed to run self restart command")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
p.Error().Err(err).Msg("failed to self restart ctrld service")
|
p.Error().Err(err).Msg("Failed to self restart ctrld service")
|
||||||
}
|
}
|
||||||
os.Exit(deactivationPinInvalidExitCode)
|
os.Exit(deactivationPinInvalidExitCode)
|
||||||
}
|
}
|
||||||
@@ -780,29 +780,29 @@ func (p *prog) setDnsForRunningIface(nameservers []string) (runningIface *net.In
|
|||||||
if newIface != p.runningIface {
|
if newIface != p.runningIface {
|
||||||
p.runningIface = newIface
|
p.runningIface = newIface
|
||||||
logger = p.logger.Load().With().Str("iface", p.runningIface)
|
logger = p.logger.Load().With().Str("iface", p.runningIface)
|
||||||
logger.Info().Msg("switched to new interface")
|
logger.Info().Msg("Switched to new interface")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Warn().Err(err).Int("attempt", attempt).Msg("could not get interface, retrying...")
|
logger.Warn().Err(err).Int("attempt", attempt).Msg("Could not get interface, retrying...")
|
||||||
time.Sleep(retryDelay)
|
time.Sleep(retryDelay)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
logger.Error().Err(err).Msg("could not get interface after all attempts")
|
logger.Error().Err(err).Msg("Could not get interface after all attempts")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := p.setupNetworkManager(); err != nil {
|
if err := p.setupNetworkManager(); err != nil {
|
||||||
logger.Error().Err(err).Msg("could not patch NetworkManager")
|
logger.Error().Err(err).Msg("Could not patch networkmanager")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
runningIface = netIface
|
runningIface = netIface
|
||||||
logger.Debug().Msg("setting DNS for interface")
|
logger.Debug().Msg("Setting dns for interface")
|
||||||
if err := setDNS(netIface, nameservers); err != nil {
|
if err := setDNS(netIface, nameservers); err != nil {
|
||||||
logger.Error().Err(err).Msgf("could not set DNS for interface")
|
logger.Error().Err(err).Msgf("Could not set dns for interface")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger.Debug().Msg("setting DNS successfully")
|
logger.Debug().Msg("Setting dns successfully")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -831,7 +831,7 @@ func (p *prog) dnsWatchdog(iface *net.Interface, nameservers []string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
p.Debug().Msg("start DNS settings watchdog")
|
p.Debug().Msg("Start dns settings watchdog")
|
||||||
|
|
||||||
ns := nameservers
|
ns := nameservers
|
||||||
slices.Sort(ns)
|
slices.Sort(ns)
|
||||||
@@ -842,7 +842,7 @@ func (p *prog) dnsWatchdog(iface *net.Interface, nameservers []string) {
|
|||||||
case <-p.dnsWatcherStopCh:
|
case <-p.dnsWatcherStopCh:
|
||||||
return
|
return
|
||||||
case <-p.stopCh:
|
case <-p.stopCh:
|
||||||
p.Debug().Msg("stop dns watchdog")
|
p.Debug().Msg("Stop dns watchdog")
|
||||||
return
|
return
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
if p.recoveryRunning.Load() {
|
if p.recoveryRunning.Load() {
|
||||||
@@ -854,7 +854,7 @@ func (p *prog) dnsWatchdog(iface *net.Interface, nameservers []string) {
|
|||||||
// currentStaticDNS is an OS-dependent helper that returns the current static DNS.
|
// currentStaticDNS is an OS-dependent helper that returns the current static DNS.
|
||||||
staticDNS, err := currentStaticDNS(iface)
|
staticDNS, err := currentStaticDNS(iface)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Debug().Err(err).Msgf("failed to get static DNS for interface %s", iface.Name)
|
p.Debug().Err(err).Msgf("Failed to get static DNS for interface %s", iface.Name)
|
||||||
} else if len(staticDNS) > 0 {
|
} else if len(staticDNS) > 0 {
|
||||||
//filter out loopback addresses
|
//filter out loopback addresses
|
||||||
staticDNS = slices.DeleteFunc(staticDNS, func(s string) bool {
|
staticDNS = slices.DeleteFunc(staticDNS, func(s string) bool {
|
||||||
@@ -864,12 +864,12 @@ func (p *prog) dnsWatchdog(iface *net.Interface, nameservers []string) {
|
|||||||
if len(staticDNS) > 0 && len(ctrld.SavedStaticNameservers(iface)) == 0 {
|
if len(staticDNS) > 0 && len(ctrld.SavedStaticNameservers(iface)) == 0 {
|
||||||
// Save these static DNS values so that they can be restored later.
|
// Save these static DNS values so that they can be restored later.
|
||||||
if err := saveCurrentStaticDNS(iface); err != nil {
|
if err := saveCurrentStaticDNS(iface); err != nil {
|
||||||
p.Debug().Err(err).Msgf("failed to save static DNS for interface %s", iface.Name)
|
p.Debug().Err(err).Msgf("Failed to save static DNS for interface %s", iface.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := setDNS(iface, ns); err != nil {
|
if err := setDNS(iface, ns); err != nil {
|
||||||
p.Error().Err(err).Str("iface", iface.Name).Msgf("could not re-apply DNS settings")
|
p.Error().Err(err).Str("iface", iface.Name).Msgf("Could not re-apply DNS settings")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if p.requiredMultiNICsConfig {
|
if p.requiredMultiNICsConfig {
|
||||||
@@ -884,7 +884,7 @@ func (p *prog) dnsWatchdog(iface *net.Interface, nameservers []string) {
|
|||||||
// currentStaticDNS is an OS-dependent helper that returns the current static DNS.
|
// currentStaticDNS is an OS-dependent helper that returns the current static DNS.
|
||||||
staticDNS, err := currentStaticDNS(i)
|
staticDNS, err := currentStaticDNS(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Debug().Err(err).Msgf("failed to get static DNS for interface %s", i.Name)
|
p.Debug().Err(err).Msgf("Failed to get static DNS for interface %s", i.Name)
|
||||||
} else if len(staticDNS) > 0 {
|
} else if len(staticDNS) > 0 {
|
||||||
//filter out loopback addresses
|
//filter out loopback addresses
|
||||||
staticDNS = slices.DeleteFunc(staticDNS, func(s string) bool {
|
staticDNS = slices.DeleteFunc(staticDNS, func(s string) bool {
|
||||||
@@ -894,15 +894,15 @@ func (p *prog) dnsWatchdog(iface *net.Interface, nameservers []string) {
|
|||||||
if len(staticDNS) > 0 && len(ctrld.SavedStaticNameservers(i)) == 0 {
|
if len(staticDNS) > 0 && len(ctrld.SavedStaticNameservers(i)) == 0 {
|
||||||
// Save these static DNS values so that they can be restored later.
|
// Save these static DNS values so that they can be restored later.
|
||||||
if err := saveCurrentStaticDNS(i); err != nil {
|
if err := saveCurrentStaticDNS(i); err != nil {
|
||||||
p.Debug().Err(err).Msgf("failed to save static DNS for interface %s", i.Name)
|
p.Debug().Err(err).Msgf("Failed to save static DNS for interface %s", i.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := setDnsIgnoreUnusableInterface(i, nameservers); err != nil {
|
if err := setDnsIgnoreUnusableInterface(i, nameservers); err != nil {
|
||||||
p.Error().Err(err).Str("iface", i.Name).Msgf("could not re-apply DNS settings")
|
p.Error().Err(err).Str("iface", i.Name).Msgf("Could not re-apply DNS settings")
|
||||||
} else {
|
} else {
|
||||||
p.Debug().Msgf("re-applying DNS for interface %q successfully", i.Name)
|
p.Debug().Msgf("Re-applying DNS for interface %q successfully", i.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -932,18 +932,18 @@ func (p *prog) resetDNS(isStart bool, restoreStatic bool) {
|
|||||||
// Otherwise, we restore the saved configuration (if any) or reset to DHCP.
|
// Otherwise, we restore the saved configuration (if any) or reset to DHCP.
|
||||||
func (p *prog) resetDNSForRunningIface(isStart bool, restoreStatic bool) (runningIface *net.Interface) {
|
func (p *prog) resetDNSForRunningIface(isStart bool, restoreStatic bool) (runningIface *net.Interface) {
|
||||||
if p.runningIface == "" {
|
if p.runningIface == "" {
|
||||||
p.Debug().Msg("no running interface, skipping resetDNS")
|
p.Debug().Msg("No running interface, skipping resetDNS")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger := p.logger.Load().With().Str("iface", p.runningIface)
|
logger := p.logger.Load().With().Str("iface", p.runningIface)
|
||||||
netIface, err := netInterface(p.runningIface)
|
netIface, err := netInterface(p.runningIface)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error().Err(err).Msg("could not get interface")
|
logger.Error().Err(err).Msg("Could not get interface")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
runningIface = netIface
|
runningIface = netIface
|
||||||
if err := p.restoreNetworkManager(); err != nil {
|
if err := p.restoreNetworkManager(); err != nil {
|
||||||
logger.Error().Err(err).Msg("could not restore NetworkManager")
|
logger.Error().Err(err).Msg("Could not restore NetworkManager")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -951,7 +951,7 @@ func (p *prog) resetDNSForRunningIface(isStart bool, restoreStatic bool) (runnin
|
|||||||
if isStart {
|
if isStart {
|
||||||
current, err := currentStaticDNS(netIface)
|
current, err := currentStaticDNS(netIface)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warn().Err(err).Msg("unable to obtain current static DNS configuration; proceeding to restore saved config")
|
logger.Warn().Err(err).Msg("Unable to obtain current static DNS configuration; proceeding to restore saved config")
|
||||||
} else if len(current) > 0 {
|
} else if len(current) > 0 {
|
||||||
// If any static DNS value is not our own listener, assume an admin override.
|
// If any static DNS value is not our own listener, assume an admin override.
|
||||||
hasManualConfig := false
|
hasManualConfig := false
|
||||||
@@ -973,13 +973,13 @@ func (p *prog) resetDNSForRunningIface(isStart bool, restoreStatic bool) (runnin
|
|||||||
if len(saved) > 0 && restoreStatic {
|
if len(saved) > 0 && restoreStatic {
|
||||||
logger.Debug().Msgf("Restoring interface %q from saved static config: %v", netIface.Name, saved)
|
logger.Debug().Msgf("Restoring interface %q from saved static config: %v", netIface.Name, saved)
|
||||||
if err := setDNS(netIface, saved); err != nil {
|
if err := setDNS(netIface, saved); err != nil {
|
||||||
logger.Error().Err(err).Msgf("failed to restore static DNS config on interface %q", netIface.Name)
|
logger.Error().Err(err).Msgf("Failed to restore static DNS config on interface %q", netIface.Name)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.Debug().Msgf("No saved static DNS config for interface %q; resetting to DHCP", netIface.Name)
|
logger.Debug().Msgf("No saved static DNS config for interface %q; resetting to DHCP", netIface.Name)
|
||||||
if err := resetDNS(netIface); err != nil {
|
if err := resetDNS(netIface); err != nil {
|
||||||
logger.Error().Err(err).Msgf("failed to reset DNS to DHCP on interface %q", netIface.Name)
|
logger.Error().Err(err).Msgf("Failed to reset DNS to DHCP on interface %q", netIface.Name)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -990,11 +990,11 @@ func (p *prog) logInterfacesState() {
|
|||||||
withEachPhysicalInterfaces("", "", func(i *net.Interface) error {
|
withEachPhysicalInterfaces("", "", func(i *net.Interface) error {
|
||||||
addrs, err := i.Addrs()
|
addrs, err := i.Addrs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Warn().Str("interface", i.Name).Err(err).Msg("failed to get addresses")
|
p.Warn().Str("interface", i.Name).Err(err).Msg("Failed to get addresses")
|
||||||
}
|
}
|
||||||
nss, err := currentStaticDNS(i)
|
nss, err := currentStaticDNS(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Warn().Str("interface", i.Name).Err(err).Msg("failed to get DNS")
|
p.Warn().Str("interface", i.Name).Err(err).Msg("Failed to get DNS")
|
||||||
}
|
}
|
||||||
if len(nss) == 0 {
|
if len(nss) == 0 {
|
||||||
nss = currentDNS(i)
|
nss = currentDNS(i)
|
||||||
@@ -1063,7 +1063,7 @@ func (p *prog) findWorkingInterface() string {
|
|||||||
// Get all interfaces
|
// Get all interfaces
|
||||||
ifaces, err := net.Interfaces()
|
ifaces, err := net.Interfaces()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Error().Err(err).Msg("failed to list network interfaces")
|
p.Error().Err(err).Msg("Failed to list network interfaces")
|
||||||
return currentIface // Return current interface as fallback
|
return currentIface // Return current interface as fallback
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1132,7 +1132,7 @@ func (p *prog) findWorkingInterface() string {
|
|||||||
// 3. Fall back to current interface if nothing else works
|
// 3. Fall back to current interface if nothing else works
|
||||||
p.Warn().
|
p.Warn().
|
||||||
Str("current_iface", currentIface).
|
Str("current_iface", currentIface).
|
||||||
Msg("no working physical interface found, keeping current")
|
Msg("No working physical interface found, keeping current")
|
||||||
return currentIface
|
return currentIface
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1152,19 +1152,19 @@ func randomPort() int {
|
|||||||
func runLogServer(sockPath string) net.Conn {
|
func runLogServer(sockPath string) net.Conn {
|
||||||
addr, err := net.ResolveUnixAddr("unix", sockPath)
|
addr, err := net.ResolveUnixAddr("unix", sockPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Warn().Err(err).Msg("invalid log sock path")
|
mainLog.Load().Warn().Err(err).Msg("Invalid log sock path")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
ln, err := net.ListenUnix("unix", addr)
|
ln, err := net.ListenUnix("unix", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Warn().Err(err).Msg("could not listen log socket")
|
mainLog.Load().Warn().Err(err).Msg("Could not listen log socket")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
defer ln.Close()
|
defer ln.Close()
|
||||||
|
|
||||||
server, err := ln.Accept()
|
server, err := ln.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Warn().Err(err).Msg("could not accept connection")
|
mainLog.Load().Warn().Err(err).Msg("Could not accept connection")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return server
|
return server
|
||||||
@@ -1261,9 +1261,9 @@ func (p *prog) defaultRouteIP() string {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
p.Debug().Str("iface", drNetIface.Name).Msg("checking default route interface")
|
p.Debug().Str("iface", drNetIface.Name).Msg("Checking default route interface")
|
||||||
if ip := ifaceFirstPrivateIP(drNetIface); ip != "" {
|
if ip := ifaceFirstPrivateIP(drNetIface); ip != "" {
|
||||||
p.Debug().Str("ip", ip).Msg("found ip with default route interface")
|
p.Debug().Str("ip", ip).Msg("Found ip with default route interface")
|
||||||
return ip
|
return ip
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1288,7 +1288,7 @@ func (p *prog) defaultRouteIP() string {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if len(addrs) == 0 {
|
if len(addrs) == 0 {
|
||||||
p.Warn().Msg("no default route IP found")
|
p.Warn().Msg("No default route IP found")
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
sort.Slice(addrs, func(i, j int) bool {
|
sort.Slice(addrs, func(i, j int) bool {
|
||||||
@@ -1296,7 +1296,7 @@ func (p *prog) defaultRouteIP() string {
|
|||||||
})
|
})
|
||||||
|
|
||||||
ip := addrs[0].String()
|
ip := addrs[0].String()
|
||||||
p.Debug().Str("ip", ip).Msg("found LAN interface IP")
|
p.Debug().Str("ip", ip).Msg("Found LAN interface IP")
|
||||||
return ip
|
return ip
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1324,7 +1324,7 @@ func withEachPhysicalInterfaces(excludeIfaceName, contextStr string, f func(i *n
|
|||||||
}
|
}
|
||||||
netIface := i.Interface
|
netIface := i.Interface
|
||||||
if patched, err := patchNetIfaceName(netIface); err != nil {
|
if patched, err := patchNetIfaceName(netIface); err != nil {
|
||||||
mainLog.Load().Debug().Err(err).Msg("failed to patch net interface name")
|
mainLog.Load().Debug().Err(err).Msg("Failed to patch net interface name")
|
||||||
return
|
return
|
||||||
} else if !patched {
|
} else if !patched {
|
||||||
// The interface is not functional, skipping.
|
// The interface is not functional, skipping.
|
||||||
@@ -1361,7 +1361,7 @@ var errSaveCurrentStaticDNSNotSupported = errors.New("saving current DNS is not
|
|||||||
// Only works on Windows and Mac.
|
// Only works on Windows and Mac.
|
||||||
func saveCurrentStaticDNS(iface *net.Interface) error {
|
func saveCurrentStaticDNS(iface *net.Interface) error {
|
||||||
if iface == nil {
|
if iface == nil {
|
||||||
mainLog.Load().Debug().Msg("could not save current static DNS settings for nil interface")
|
mainLog.Load().Debug().Msg("Could not save current static DNS settings for nil interface")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
switch runtime.GOOS {
|
switch runtime.GOOS {
|
||||||
@@ -1372,11 +1372,11 @@ func saveCurrentStaticDNS(iface *net.Interface) error {
|
|||||||
file := ctrld.SavedStaticDnsSettingsFilePath(iface)
|
file := ctrld.SavedStaticDnsSettingsFilePath(iface)
|
||||||
ns, err := currentStaticDNS(iface)
|
ns, err := currentStaticDNS(iface)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Warn().Err(err).Msgf("could not get current static DNS settings for %q", iface.Name)
|
mainLog.Load().Warn().Err(err).Msgf("Could not get current static DNS settings for %q", iface.Name)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(ns) == 0 {
|
if len(ns) == 0 {
|
||||||
mainLog.Load().Debug().Msgf("no static DNS settings for %q, removing old static DNS settings file", iface.Name)
|
mainLog.Load().Debug().Msgf("No static DNS settings for %q, removing old static DNS settings file", iface.Name)
|
||||||
_ = os.Remove(file) // removing old static DNS settings
|
_ = os.Remove(file) // removing old static DNS settings
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -1391,15 +1391,15 @@ func saveCurrentStaticDNS(iface *net.Interface) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err := os.Remove(file); err != nil && !errors.Is(err, fs.ErrNotExist) {
|
if err := os.Remove(file); err != nil && !errors.Is(err, fs.ErrNotExist) {
|
||||||
mainLog.Load().Warn().Err(err).Msgf("could not remove old static DNS settings file: %s", file)
|
mainLog.Load().Warn().Err(err).Msgf("Could not remove old static DNS settings file: %s", file)
|
||||||
}
|
}
|
||||||
nss := strings.Join(ns, ",")
|
nss := strings.Join(ns, ",")
|
||||||
mainLog.Load().Debug().Msgf("DNS settings for %q is static: %v, saving ...", iface.Name, nss)
|
mainLog.Load().Debug().Msgf("DNS settings for %q is static: %v, saving ...", iface.Name, nss)
|
||||||
if err := os.WriteFile(file, []byte(nss), 0600); err != nil {
|
if err := os.WriteFile(file, []byte(nss), 0600); err != nil {
|
||||||
mainLog.Load().Err(err).Msgf("could not save DNS settings for iface: %s", iface.Name)
|
mainLog.Load().Err(err).Msgf("Could not save DNS settings for iface: %s", iface.Name)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
mainLog.Load().Debug().Msgf("save DNS settings for interface %q successfully", iface.Name)
|
mainLog.Load().Debug().Msgf("Save DNS settings for interface %q successfully", iface.Name)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1414,7 +1414,7 @@ func (p *prog) dnsChanged(iface *net.Interface, nameservers []string) bool {
|
|||||||
curNameservers, _ := currentStaticDNS(iface)
|
curNameservers, _ := currentStaticDNS(iface)
|
||||||
slices.Sort(curNameservers)
|
slices.Sort(curNameservers)
|
||||||
if !slices.Equal(curNameservers, nameservers) {
|
if !slices.Equal(curNameservers, nameservers) {
|
||||||
p.Debug().Msgf("interface %q current DNS settings: %v, expected: %v", iface.Name, curNameservers, nameservers)
|
p.Debug().Msgf("Interface %q current DNS settings: %v, expected: %v", iface.Name, curNameservers, nameservers)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@@ -1438,7 +1438,7 @@ func selfUninstallCheck(uninstallErr error, p *prog, logger *ctrld.Logger) {
|
|||||||
// Returns true if upgrade is allowed, false otherwise.
|
// Returns true if upgrade is allowed, false otherwise.
|
||||||
func shouldUpgrade(vt string, cv *semver.Version, logger *ctrld.Logger) bool {
|
func shouldUpgrade(vt string, cv *semver.Version, logger *ctrld.Logger) bool {
|
||||||
if vt == "" {
|
if vt == "" {
|
||||||
logger.Debug().Msg("no version target set, skipped checking self-upgrade")
|
logger.Debug().Msg("No version target set, skipped checking self-upgrade")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
vts := vt
|
vts := vt
|
||||||
@@ -1447,7 +1447,7 @@ func shouldUpgrade(vt string, cv *semver.Version, logger *ctrld.Logger) bool {
|
|||||||
}
|
}
|
||||||
targetVer, err := semver.NewVersion(vts)
|
targetVer, err := semver.NewVersion(vts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warn().Err(err).Msgf("invalid target version, skipped self-upgrade: %s", vt)
|
logger.Warn().Err(err).Msgf("Invalid target version, skipped self-upgrade: %s", vt)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1456,7 +1456,7 @@ func shouldUpgrade(vt string, cv *semver.Version, logger *ctrld.Logger) bool {
|
|||||||
logger.Warn().
|
logger.Warn().
|
||||||
Str("target", vt).
|
Str("target", vt).
|
||||||
Str("current", cv.String()).
|
Str("current", cv.String()).
|
||||||
Msgf("major version upgrade not allowed (target: %d, current: %d), skipped self-upgrade", targetVer.Major(), cv.Major())
|
Msgf("Major version upgrade not allowed (target: %d, current: %d), skipped self-upgrade", targetVer.Major(), cv.Major())
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1464,7 +1464,7 @@ func shouldUpgrade(vt string, cv *semver.Version, logger *ctrld.Logger) bool {
|
|||||||
logger.Debug().
|
logger.Debug().
|
||||||
Str("target", vt).
|
Str("target", vt).
|
||||||
Str("current", cv.String()).
|
Str("current", cv.String()).
|
||||||
Msgf("target version is not greater than current one, skipped self-upgrade")
|
Msgf("Target version is not greater than current one, skipped self-upgrade")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1476,16 +1476,16 @@ func shouldUpgrade(vt string, cv *semver.Version, logger *ctrld.Logger) bool {
|
|||||||
func performUpgrade(vt string, logger *ctrld.Logger) bool {
|
func performUpgrade(vt string, logger *ctrld.Logger) bool {
|
||||||
exe, err := os.Executable()
|
exe, err := os.Executable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error().Err(err).Msg("failed to get executable path, skipped self-upgrade")
|
logger.Error().Err(err).Msg("Failed to get executable path, skipped self-upgrade")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
cmd := exec.Command(exe, "upgrade", "prod", "-vv")
|
cmd := exec.Command(exe, "upgrade", "prod", "-vv")
|
||||||
cmd.SysProcAttr = sysProcAttrForDetachedChildProcess()
|
cmd.SysProcAttr = sysProcAttrForDetachedChildProcess()
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
logger.Error().Err(err).Msg("failed to start self-upgrade")
|
logger.Error().Err(err).Msg("Failed to start self-upgrade")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
mainLog.Load().Debug().Msgf("self-upgrade triggered, version target: %s", vt)
|
logger.Debug().Msgf("Self-upgrade triggered, version target: %s", vt)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,10 +28,10 @@ func (p *prog) watchResolvConf(iface *net.Interface, ns []netip.Addr, setDnsFn f
|
|||||||
if rp, _ := filepath.EvalSymlinks(resolvConfPath); rp != "" {
|
if rp, _ := filepath.EvalSymlinks(resolvConfPath); rp != "" {
|
||||||
resolvConfPath = rp
|
resolvConfPath = rp
|
||||||
}
|
}
|
||||||
p.Debug().Msgf("start watching %s file", resolvConfPath)
|
p.Debug().Msgf("Start watching %s file", resolvConfPath)
|
||||||
watcher, err := fsnotify.NewWatcher()
|
watcher, err := fsnotify.NewWatcher()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Warn().Err(err).Msg("could not create watcher for /etc/resolv.conf")
|
p.Warn().Err(err).Msg("Could not create watcher for /etc/resolv.conf")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer watcher.Close()
|
defer watcher.Close()
|
||||||
@@ -41,7 +41,7 @@ func (p *prog) watchResolvConf(iface *net.Interface, ns []netip.Addr, setDnsFn f
|
|||||||
// This is necessary because some systems don't properly notify on file changes
|
// This is necessary because some systems don't properly notify on file changes
|
||||||
watchDir := filepath.Dir(resolvConfPath)
|
watchDir := filepath.Dir(resolvConfPath)
|
||||||
if err := watcher.Add(watchDir); err != nil {
|
if err := watcher.Add(watchDir); err != nil {
|
||||||
p.Warn().Err(err).Msgf("could not add %s to watcher list", watchDir)
|
p.Warn().Err(err).Msgf("Could not add %s to watcher list", watchDir)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ func (p *prog) watchResolvConf(iface *net.Interface, ns []netip.Addr, setDnsFn f
|
|||||||
case <-p.dnsWatcherStopCh:
|
case <-p.dnsWatcherStopCh:
|
||||||
return
|
return
|
||||||
case <-p.stopCh:
|
case <-p.stopCh:
|
||||||
p.Debug().Msgf("stopping watcher for %s", resolvConfPath)
|
p.Debug().Msgf("Stopping watcher for %s", resolvConfPath)
|
||||||
return
|
return
|
||||||
case event, ok := <-watcher.Events:
|
case event, ok := <-watcher.Events:
|
||||||
if p.recoveryRunning.Load() {
|
if p.recoveryRunning.Load() {
|
||||||
@@ -79,7 +79,7 @@ func (p *prog) watchResolvConf(iface *net.Interface, ns []netip.Addr, setDnsFn f
|
|||||||
for retry := 0; retry < maxRetries; retry++ {
|
for retry := 0; retry < maxRetries; retry++ {
|
||||||
foundNS, err = p.parseResolvConfNameservers(resolvConfPath)
|
foundNS, err = p.parseResolvConfNameservers(resolvConfPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Error().Err(err).Msg("failed to read resolv.conf content")
|
p.Error().Err(err).Msg("Failed to read resolv.conf content")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,16 +128,16 @@ func (p *prog) watchResolvConf(iface *net.Interface, ns []netip.Addr, setDnsFn f
|
|||||||
// Only revert if the nameservers don't match
|
// Only revert if the nameservers don't match
|
||||||
if !matches {
|
if !matches {
|
||||||
if err := watcher.Remove(watchDir); err != nil {
|
if err := watcher.Remove(watchDir); err != nil {
|
||||||
p.Error().Err(err).Msg("failed to pause watcher")
|
p.Error().Err(err).Msg("Failed to pause watcher")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := setDnsFn(iface, ns); err != nil {
|
if err := setDnsFn(iface, ns); err != nil {
|
||||||
p.Error().Err(err).Msg("failed to revert /etc/resolv.conf changes")
|
p.Error().Err(err).Msg("Failed to revert /etc/resolv.conf changes")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := watcher.Add(watchDir); err != nil {
|
if err := watcher.Add(watchDir); err != nil {
|
||||||
p.Error().Err(err).Msg("failed to continue running watcher")
|
p.Error().Err(err).Msg("Failed to continue running watcher")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -147,7 +147,7 @@ func (p *prog) watchResolvConf(iface *net.Interface, ns []netip.Addr, setDnsFn f
|
|||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p.Error().Err(err).Msg("could not get event for /etc/resolv.conf")
|
p.Error().Err(err).Msg("Could not get event for /etc/resolv.conf")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ func (p *prog) setResolvConf(iface *net.Interface, ns []netip.Addr) error {
|
|||||||
if sds, err := searchDomains(); err == nil {
|
if sds, err := searchDomains(); err == nil {
|
||||||
oc.SearchDomains = sds
|
oc.SearchDomains = sds
|
||||||
} else {
|
} else {
|
||||||
p.Debug().Err(err).Msg("failed to get search domains list when reverting resolv.conf file")
|
p.Debug().Err(err).Msg("Failed to get search domains list when reverting resolv.conf file")
|
||||||
}
|
}
|
||||||
return r.SetDNS(oc)
|
return r.SetDNS(oc)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ func searchDomains() ([]dnsname.FQDN, error) {
|
|||||||
for a := aa.FirstDNSSuffix; a != nil; a = a.Next {
|
for a := aa.FirstDNSSuffix; a != nil; a = a.Next {
|
||||||
d, err := dnsname.ToFQDN(a.String())
|
d, err := dnsname.ToFQDN(a.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Debug().Err(err).Msgf("failed to parse domain: %s", a.String())
|
mainLog.Load().Debug().Err(err).Msgf("Failed to parse domain: %s", a.String())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
sds = append(sds, d)
|
sds = append(sds, d)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
// selfUninstall performs self-uninstallation on non-Unix platforms
|
// selfUninstall performs self-uninstallation on non-Unix platforms
|
||||||
func selfUninstall(p *prog, logger *ctrld.Logger) {
|
func selfUninstall(p *prog, logger *ctrld.Logger) {
|
||||||
if uninstallInvalidCdUID(p, logger, false) {
|
if uninstallInvalidCdUID(p, logger, false) {
|
||||||
logger.Warn().Msgf("service was uninstalled because device %q does not exist", cdUID)
|
logger.Warn().Msgf("Service was uninstalled because device %q does not exist", cdUID)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ func selfUninstall(p *prog, logger *ctrld.Logger) {
|
|||||||
|
|
||||||
bin, err := os.Executable()
|
bin, err := os.Executable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatal().Err(err).Msg("could not determine executable")
|
logger.Fatal().Err(err).Msg("Could not determine executable")
|
||||||
}
|
}
|
||||||
args := []string{"uninstall"}
|
args := []string{"uninstall"}
|
||||||
if deactivationPinSet() {
|
if deactivationPinSet() {
|
||||||
@@ -29,11 +29,11 @@ func selfUninstall(p *prog, logger *ctrld.Logger) {
|
|||||||
cmd := exec.Command(bin, args...)
|
cmd := exec.Command(bin, args...)
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
logger.Fatal().Err(err).Msg("could not start self uninstall command")
|
logger.Fatal().Err(err).Msg("Could not start self uninstall command")
|
||||||
}
|
}
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
logger.Warn().Msgf("service was uninstalled because device %q does not exist", cdUID)
|
logger.Warn().Msgf("Service was uninstalled because device %q does not exist", cdUID)
|
||||||
_ = cmd.Wait()
|
_ = cmd.Wait()
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
@@ -41,7 +41,7 @@ func selfUninstall(p *prog, logger *ctrld.Logger) {
|
|||||||
// selfUninstallLinux performs self-uninstallation on Linux platforms
|
// selfUninstallLinux performs self-uninstallation on Linux platforms
|
||||||
func selfUninstallLinux(p *prog, logger *ctrld.Logger) {
|
func selfUninstallLinux(p *prog, logger *ctrld.Logger) {
|
||||||
if uninstallInvalidCdUID(p, logger, true) {
|
if uninstallInvalidCdUID(p, logger, true) {
|
||||||
logger.Warn().Msgf("service was uninstalled because device %q does not exist", cdUID)
|
logger.Warn().Msgf("Service was uninstalled because device %q does not exist", cdUID)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-5
@@ -115,7 +115,7 @@ func (s *systemd) Start() error {
|
|||||||
if out, err := exec.Command("systemctl", "daemon-reload").CombinedOutput(); err != nil {
|
if out, err := exec.Command("systemctl", "daemon-reload").CombinedOutput(); err != nil {
|
||||||
return fmt.Errorf("systemctl daemon-reload failed: %w\n%s", err, string(out))
|
return fmt.Errorf("systemctl daemon-reload failed: %w\n%s", err, string(out))
|
||||||
}
|
}
|
||||||
mainLog.Load().Debug().Msg("set KillMode=process successfully")
|
mainLog.Load().Debug().Msg("Set KillMode=process successfully")
|
||||||
}
|
}
|
||||||
return s.Service.Start()
|
return s.Service.Start()
|
||||||
}
|
}
|
||||||
@@ -125,7 +125,7 @@ func (s *systemd) Start() error {
|
|||||||
func ensureSystemdKillMode(r io.Reader) (opts []*unit.UnitOption, change bool) {
|
func ensureSystemdKillMode(r io.Reader) (opts []*unit.UnitOption, change bool) {
|
||||||
opts, err := unit.DeserializeOptions(r)
|
opts, err := unit.DeserializeOptions(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Error().Err(err).Msg("failed to deserialize options")
|
mainLog.Load().Error().Err(err).Msg("Failed to deserialize options")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
change = true
|
change = true
|
||||||
@@ -185,13 +185,13 @@ func doTasks(tasks []task) bool {
|
|||||||
mainLog.Load().Debug().Msgf("Running task %s", task.Name)
|
mainLog.Load().Debug().Msgf("Running task %s", task.Name)
|
||||||
if err := task.f(); err != nil {
|
if err := task.f(); err != nil {
|
||||||
if task.abortOnError {
|
if task.abortOnError {
|
||||||
mainLog.Load().Error().Msgf("error running task %s: %v", task.Name, err)
|
mainLog.Load().Error().Msgf("Error running task %s: %v", task.Name, err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// if this is darwin stop command, dont print debug
|
// if this is darwin stop command, dont print debug
|
||||||
// since launchctl complains on every start
|
// since launchctl complains on every start
|
||||||
if runtime.GOOS != "darwin" || task.Name != "Stop" {
|
if runtime.GOOS != "darwin" || task.Name != "Stop" {
|
||||||
mainLog.Load().Debug().Msgf("error running task %s: %v", task.Name, err)
|
mainLog.Load().Debug().Msgf("Error running task %s: %v", task.Name, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,7 +202,7 @@ func doTasks(tasks []task) bool {
|
|||||||
func checkHasElevatedPrivilege() {
|
func checkHasElevatedPrivilege() {
|
||||||
ok, err := hasElevatedPrivilege()
|
ok, err := hasElevatedPrivilege()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Error().Msgf("could not detect user privilege: %v", err)
|
mainLog.Load().Error().Msgf("Could not detect user privilege: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ func (um *upstreamMonitor) increaseFailureCount(upstream string) {
|
|||||||
defer um.mu.Unlock()
|
defer um.mu.Unlock()
|
||||||
|
|
||||||
if um.recovered[upstream] {
|
if um.recovered[upstream] {
|
||||||
um.logger.Load().Debug().Msgf("upstream %q is recovered, skipping failure count increase", upstream)
|
um.logger.Load().Debug().Msgf("Upstream %q is recovered, skipping failure count increase", upstream)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ func (um *upstreamMonitor) increaseFailureCount(upstream string) {
|
|||||||
failedCount := um.failureReq[upstream]
|
failedCount := um.failureReq[upstream]
|
||||||
|
|
||||||
// Log the updated failure count.
|
// Log the updated failure count.
|
||||||
um.logger.Load().Debug().Msgf("upstream %q failure count updated to %d", upstream, failedCount)
|
um.logger.Load().Debug().Msgf("Upstream %q failure count updated to %d", upstream, failedCount)
|
||||||
|
|
||||||
// If this is the first failure and no timer is running, start a 10-second timer.
|
// If this is the first failure and no timer is running, start a 10-second timer.
|
||||||
if failedCount == 1 && !um.failureTimerActive[upstream] {
|
if failedCount == 1 && !um.failureTimerActive[upstream] {
|
||||||
@@ -78,7 +78,7 @@ func (um *upstreamMonitor) increaseFailureCount(upstream string) {
|
|||||||
// and the upstream is not in a recovered state, mark it as down.
|
// and the upstream is not in a recovered state, mark it as down.
|
||||||
if um.failureReq[upstream] > 0 && !um.recovered[upstream] {
|
if um.failureReq[upstream] > 0 && !um.recovered[upstream] {
|
||||||
um.down[upstream] = true
|
um.down[upstream] = true
|
||||||
um.logger.Load().Warn().Msgf("upstream %q marked as down after 10 seconds (failure count: %d)", upstream, um.failureReq[upstream])
|
um.logger.Load().Warn().Msgf("Upstream %q marked as down after 10 seconds (failure count: %d)", upstream, um.failureReq[upstream])
|
||||||
}
|
}
|
||||||
// Reset the timer flag so that a new timer can be spawned if needed.
|
// Reset the timer flag so that a new timer can be spawned if needed.
|
||||||
um.failureTimerActive[upstream] = false
|
um.failureTimerActive[upstream] = false
|
||||||
@@ -88,7 +88,7 @@ func (um *upstreamMonitor) increaseFailureCount(upstream string) {
|
|||||||
// If the failure count quickly reaches the threshold, mark the upstream as down immediately.
|
// If the failure count quickly reaches the threshold, mark the upstream as down immediately.
|
||||||
if failedCount >= maxFailureRequest {
|
if failedCount >= maxFailureRequest {
|
||||||
um.down[upstream] = true
|
um.down[upstream] = true
|
||||||
um.logger.Load().Warn().Msgf("upstream %q marked as down immediately (failure count: %d)", upstream, failedCount)
|
um.logger.Load().Warn().Msgf("Upstream %q marked as down immediately (failure count: %d)", upstream, failedCount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -114,8 +114,9 @@ func SetConfigNameWithPath(v *viper.Viper, name, configPath string) {
|
|||||||
|
|
||||||
// InitConfig initializes default config values for given *viper.Viper instance.
|
// InitConfig initializes default config values for given *viper.Viper instance.
|
||||||
func InitConfig(v *viper.Viper, name string) {
|
func InitConfig(v *viper.Viper, name string) {
|
||||||
logger := LoggerFromCtx(context.Background())
|
ctx := context.Background()
|
||||||
Log(context.Background(), logger.Debug(), "Config initialization started")
|
logger := LoggerFromCtx(ctx)
|
||||||
|
Log(ctx, logger.Debug(), "Config initialization started")
|
||||||
|
|
||||||
v.SetDefault("listener", map[string]*ListenerConfig{
|
v.SetDefault("listener", map[string]*ListenerConfig{
|
||||||
"0": {
|
"0": {
|
||||||
@@ -156,7 +157,7 @@ func InitConfig(v *viper.Viper, name string) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
Log(context.Background(), logger.Debug(), "Config initialization completed")
|
Log(ctx, logger.Debug(), "Config initialization completed")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config represents ctrld supported configuration.
|
// Config represents ctrld supported configuration.
|
||||||
@@ -333,7 +334,7 @@ type Rule map[string][]string
|
|||||||
func (uc *UpstreamConfig) Init(ctx context.Context) {
|
func (uc *UpstreamConfig) Init(ctx context.Context) {
|
||||||
logger := LoggerFromCtx(ctx)
|
logger := LoggerFromCtx(ctx)
|
||||||
if err := uc.initDnsStamps(); err != nil {
|
if err := uc.initDnsStamps(); err != nil {
|
||||||
logger.Fatal().Err(err).Msg("invalid DNS Stamps")
|
logger.Fatal().Err(err).Msg("Invalid dns stamps")
|
||||||
}
|
}
|
||||||
uc.initDoHScheme()
|
uc.initDoHScheme()
|
||||||
uc.uid = upstreamUID(ctx)
|
uc.uid = upstreamUID(ctx)
|
||||||
@@ -469,7 +470,7 @@ func (uc *UpstreamConfig) SetupBootstrapIP(ctx context.Context) {
|
|||||||
uc.bootstrapIPs = uc.bootstrapIPs[:n]
|
uc.bootstrapIPs = uc.bootstrapIPs[:n]
|
||||||
if len(uc.bootstrapIPs) == 0 {
|
if len(uc.bootstrapIPs) == 0 {
|
||||||
uc.bootstrapIPs = bootstrapIPsFromControlDDomain(uc.Domain)
|
uc.bootstrapIPs = bootstrapIPsFromControlDDomain(uc.Domain)
|
||||||
logger.Warn().Msgf("No record found for %q, lookup from direct IP table", uc.Domain)
|
logger.Warn().Msgf("No record found for %q, lookup from direct ip table", uc.Domain)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(uc.bootstrapIPs) == 0 {
|
if len(uc.bootstrapIPs) == 0 {
|
||||||
@@ -480,7 +481,7 @@ func (uc *UpstreamConfig) SetupBootstrapIP(ctx context.Context) {
|
|||||||
if len(uc.bootstrapIPs) > 0 {
|
if len(uc.bootstrapIPs) > 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
logger.Warn().Msg("Could not resolve bootstrap IPs, retrying...")
|
logger.Warn().Msg("Could not resolve bootstrap ips, retrying...")
|
||||||
b.BackOff(context.Background(), errors.New("no bootstrap IPs"))
|
b.BackOff(context.Background(), errors.New("no bootstrap IPs"))
|
||||||
}
|
}
|
||||||
for _, ip := range uc.bootstrapIPs {
|
for _, ip := range uc.bootstrapIPs {
|
||||||
@@ -490,7 +491,7 @@ func (uc *UpstreamConfig) SetupBootstrapIP(ctx context.Context) {
|
|||||||
uc.bootstrapIPs4 = append(uc.bootstrapIPs4, ip)
|
uc.bootstrapIPs4 = append(uc.bootstrapIPs4, ip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.Debug().Msgf("Bootstrap IPs: %v", uc.bootstrapIPs)
|
logger.Debug().Msgf("Bootstrap ips: %v", uc.bootstrapIPs)
|
||||||
Log(ctx, logger.Debug(), "Bootstrap IP setup completed for upstream: %s", uc.Name)
|
Log(ctx, logger.Debug(), "Bootstrap IP setup completed for upstream: %s", uc.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -566,7 +567,7 @@ func (uc *UpstreamConfig) newDOHTransport(ctx context.Context, addrs []string) *
|
|||||||
if uc.BootstrapIP != "" {
|
if uc.BootstrapIP != "" {
|
||||||
dialer := net.Dialer{Timeout: dialerTimeout, KeepAlive: dialerTimeout}
|
dialer := net.Dialer{Timeout: dialerTimeout, KeepAlive: dialerTimeout}
|
||||||
addr := net.JoinHostPort(uc.BootstrapIP, port)
|
addr := net.JoinHostPort(uc.BootstrapIP, port)
|
||||||
Log(ctx, logger.Debug(), "sending doh request to: %s", addr)
|
Log(ctx, logger.Debug(), "Sending doh request to: %s", addr)
|
||||||
return dialer.DialContext(ctx, network, addr)
|
return dialer.DialContext(ctx, network, addr)
|
||||||
}
|
}
|
||||||
pd := &ctrldnet.ParallelDialer{}
|
pd := &ctrldnet.ParallelDialer{}
|
||||||
@@ -580,7 +581,7 @@ func (uc *UpstreamConfig) newDOHTransport(ctx context.Context, addrs []string) *
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
Log(ctx, logger.Debug(), "sending doh request to: %s", conn.RemoteAddr())
|
Log(ctx, logger.Debug(), "Sending doh request to: %s", conn.RemoteAddr())
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
runtime.SetFinalizer(transport, func(transport *http.Transport) {
|
runtime.SetFinalizer(transport, func(transport *http.Transport) {
|
||||||
@@ -593,7 +594,7 @@ func (uc *UpstreamConfig) newDOHTransport(ctx context.Context, addrs []string) *
|
|||||||
func (uc *UpstreamConfig) Ping(ctx context.Context) {
|
func (uc *UpstreamConfig) Ping(ctx context.Context) {
|
||||||
if err := uc.ping(ctx); err != nil {
|
if err := uc.ping(ctx); err != nil {
|
||||||
logger := LoggerFromCtx(ctx)
|
logger := LoggerFromCtx(ctx)
|
||||||
logger.Debug().Err(err).Msgf("upstream ping failed: %s", uc.Endpoint)
|
logger.Debug().Err(err).Msgf("Upstream ping failed: %s", uc.Endpoint)
|
||||||
_ = uc.FallbackToDirectIP(ctx)
|
_ = uc.FallbackToDirectIP(ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -973,7 +974,7 @@ func upstreamUID(ctx context.Context) string {
|
|||||||
b := make([]byte, 4)
|
b := make([]byte, 4)
|
||||||
for {
|
for {
|
||||||
if _, err := crand.Read(b); err != nil {
|
if _, err := crand.Read(b); err != nil {
|
||||||
logger.Warn().Err(err).Msg("could not generate uid for upstream, retrying...")
|
logger.Warn().Err(err).Msg("Could not generate uid for upstream, retrying...")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return hex.EncodeToString(b)
|
return hex.EncodeToString(b)
|
||||||
|
|||||||
+2
-2
@@ -42,7 +42,7 @@ func (uc *UpstreamConfig) newDOH3Transport(ctx context.Context, addrs []string)
|
|||||||
// if we have a bootstrap ip set, use it to avoid DNS lookup
|
// if we have a bootstrap ip set, use it to avoid DNS lookup
|
||||||
if uc.BootstrapIP != "" {
|
if uc.BootstrapIP != "" {
|
||||||
addr = net.JoinHostPort(uc.BootstrapIP, port)
|
addr = net.JoinHostPort(uc.BootstrapIP, port)
|
||||||
Log(ctx, logger.Debug(), "sending doh3 request to: %s", addr)
|
Log(ctx, logger.Debug(), "Sending doh3 request to: %s", addr)
|
||||||
udpConn, err := net.ListenUDP("udp", nil)
|
udpConn, err := net.ListenUDP("udp", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -62,7 +62,7 @@ func (uc *UpstreamConfig) newDOH3Transport(ctx context.Context, addrs []string)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
Log(ctx, logger.Debug(), "sending doh3 request to: %s", conn.RemoteAddr())
|
Log(ctx, logger.Debug(), "Sending doh3 request to: %s", conn.RemoteAddr())
|
||||||
return conn, err
|
return conn, err
|
||||||
}
|
}
|
||||||
runtime.SetFinalizer(rt, func(rt *http3.Transport) {
|
runtime.SetFinalizer(rt, func(rt *http3.Transport) {
|
||||||
|
|||||||
@@ -196,14 +196,14 @@ func (t *Table) initSelfDiscover() {
|
|||||||
func (t *Table) init() {
|
func (t *Table) init() {
|
||||||
// Custom client ID presents, use it as the only source.
|
// Custom client ID presents, use it as the only source.
|
||||||
if _, clientID := controld.ParseRawUID(t.cdUID); clientID != "" {
|
if _, clientID := controld.ParseRawUID(t.cdUID); clientID != "" {
|
||||||
t.logger.Debug().Msg("start self discovery with custom client id")
|
t.logger.Debug().Msg("Start self discovery with custom client id")
|
||||||
t.initSelfDiscover()
|
t.initSelfDiscover()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are running on platforms that should only do self discover, use it as the only source, too.
|
// If we are running on platforms that should only do self discover, use it as the only source, too.
|
||||||
if ctrld.SelfDiscover() {
|
if ctrld.SelfDiscover() {
|
||||||
t.logger.Debug().Msg("start self discovery on desktop platforms")
|
t.logger.Debug().Msg("Start self discovery on desktop platforms")
|
||||||
t.initSelfDiscover()
|
t.initSelfDiscover()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -211,9 +211,9 @@ func (t *Table) init() {
|
|||||||
// Hosts file mapping.
|
// Hosts file mapping.
|
||||||
if t.discoverHosts() {
|
if t.discoverHosts() {
|
||||||
t.hf = &hostsFile{logger: t.logger}
|
t.hf = &hostsFile{logger: t.logger}
|
||||||
t.logger.Debug().Msg("start hosts file discovery")
|
t.logger.Debug().Msg("Start hosts file discovery")
|
||||||
if err := t.hf.init(); err != nil {
|
if err := t.hf.init(); err != nil {
|
||||||
t.logger.Error().Err(err).Msg("could not init hosts file discover")
|
t.logger.Error().Err(err).Msg("Could not init hosts file discover")
|
||||||
} else {
|
} else {
|
||||||
t.hostnameResolvers = append(t.hostnameResolvers, t.hf)
|
t.hostnameResolvers = append(t.hostnameResolvers, t.hf)
|
||||||
t.refreshers = append(t.refreshers, t.hf)
|
t.refreshers = append(t.refreshers, t.hf)
|
||||||
@@ -223,9 +223,9 @@ func (t *Table) init() {
|
|||||||
// DHCP lease files.
|
// DHCP lease files.
|
||||||
if t.discoverDHCP() {
|
if t.discoverDHCP() {
|
||||||
t.dhcp = &dhcp{selfIP: t.selfIP, logger: t.logger}
|
t.dhcp = &dhcp{selfIP: t.selfIP, logger: t.logger}
|
||||||
t.logger.Debug().Msg("start dhcp discovery")
|
t.logger.Debug().Msg("Start dhcp discovery")
|
||||||
if err := t.dhcp.init(); err != nil {
|
if err := t.dhcp.init(); err != nil {
|
||||||
t.logger.Error().Err(err).Msg("could not init DHCP discover")
|
t.logger.Error().Err(err).Msg("Could not init dhcp discover")
|
||||||
} else {
|
} else {
|
||||||
t.ipResolvers = append(t.ipResolvers, t.dhcp)
|
t.ipResolvers = append(t.ipResolvers, t.dhcp)
|
||||||
t.macResolvers = append(t.macResolvers, t.dhcp)
|
t.macResolvers = append(t.macResolvers, t.dhcp)
|
||||||
@@ -237,7 +237,7 @@ func (t *Table) init() {
|
|||||||
if t.discoverARP() {
|
if t.discoverARP() {
|
||||||
t.arp = &arpDiscover{}
|
t.arp = &arpDiscover{}
|
||||||
t.ndp = &ndpDiscover{logger: t.logger}
|
t.ndp = &ndpDiscover{logger: t.logger}
|
||||||
t.logger.Debug().Msg("start arp discovery")
|
t.logger.Debug().Msg("Start arp discovery")
|
||||||
discovers := map[string]interface {
|
discovers := map[string]interface {
|
||||||
refresher
|
refresher
|
||||||
IpResolver
|
IpResolver
|
||||||
@@ -249,7 +249,7 @@ func (t *Table) init() {
|
|||||||
|
|
||||||
for protocol, discover := range discovers {
|
for protocol, discover := range discovers {
|
||||||
if err := discover.refresh(); err != nil {
|
if err := discover.refresh(); err != nil {
|
||||||
t.logger.Error().Err(err).Msgf("could not init %s discover", protocol)
|
t.logger.Error().Err(err).Msgf("Could not init %s discover", protocol)
|
||||||
} else {
|
} else {
|
||||||
t.ipResolvers = append(t.ipResolvers, discover)
|
t.ipResolvers = append(t.ipResolvers, discover)
|
||||||
t.macResolvers = append(t.macResolvers, discover)
|
t.macResolvers = append(t.macResolvers, discover)
|
||||||
@@ -282,18 +282,18 @@ func (t *Table) init() {
|
|||||||
if _, portErr := strconv.Atoi(port); portErr == nil && port != "0" && net.ParseIP(host) != nil {
|
if _, portErr := strconv.Atoi(port); portErr == nil && port != "0" && net.ParseIP(host) != nil {
|
||||||
nss = append(nss, net.JoinHostPort(host, port))
|
nss = append(nss, net.JoinHostPort(host, port))
|
||||||
} else {
|
} else {
|
||||||
t.logger.Warn().Msgf("ignoring invalid nameserver for ptr discover: %q", ns)
|
t.logger.Warn().Msgf("Ignoring invalid nameserver for ptr discover: %q", ns)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(nss) > 0 {
|
if len(nss) > 0 {
|
||||||
t.ptr.resolver = ctrld.NewResolverWithNameserver(nss)
|
t.ptr.resolver = ctrld.NewResolverWithNameserver(nss)
|
||||||
t.logger.Debug().Msgf("using nameservers %v for ptr discovery", nss)
|
t.logger.Debug().Msgf("Using nameservers %v for ptr discovery", nss)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
t.logger.Debug().Msg("start ptr discovery")
|
t.logger.Debug().Msg("Start ptr discovery")
|
||||||
if err := t.ptr.refresh(); err != nil {
|
if err := t.ptr.refresh(); err != nil {
|
||||||
t.logger.Error().Err(err).Msg("could not init PTR discover")
|
t.logger.Error().Err(err).Msg("Could not init ptr discover")
|
||||||
} else {
|
} else {
|
||||||
t.hostnameResolvers = append(t.hostnameResolvers, t.ptr)
|
t.hostnameResolvers = append(t.hostnameResolvers, t.ptr)
|
||||||
t.refreshers = append(t.refreshers, t.ptr)
|
t.refreshers = append(t.refreshers, t.ptr)
|
||||||
@@ -302,9 +302,9 @@ func (t *Table) init() {
|
|||||||
// mdns.
|
// mdns.
|
||||||
if t.discoverMDNS() {
|
if t.discoverMDNS() {
|
||||||
t.mdns = &mdns{logger: t.logger}
|
t.mdns = &mdns{logger: t.logger}
|
||||||
t.logger.Debug().Msg("start mdns discovery")
|
t.logger.Debug().Msg("Start mdns discovery")
|
||||||
if err := t.mdns.init(t.quitCh); err != nil {
|
if err := t.mdns.init(t.quitCh); err != nil {
|
||||||
t.logger.Error().Err(err).Msg("could not init mDNS discover")
|
t.logger.Error().Err(err).Msg("Could not init mdns discover")
|
||||||
} else {
|
} else {
|
||||||
t.hostnameResolvers = append(t.hostnameResolvers, t.mdns)
|
t.hostnameResolvers = append(t.hostnameResolvers, t.mdns)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ func (d *dhcp) watchChanges() {
|
|||||||
if event.Has(fsnotify.Create) {
|
if event.Has(fsnotify.Create) {
|
||||||
if format, ok := clientInfoFiles[event.Name]; ok {
|
if format, ok := clientInfoFiles[event.Name]; ok {
|
||||||
if err := d.addLeaseFile(event.Name, format); err != nil {
|
if err := d.addLeaseFile(event.Name, format); err != nil {
|
||||||
d.logger.Err(err).Str("file", event.Name).Msg("could not add lease file")
|
d.logger.Err(err).Str("file", event.Name).Msg("Could not add lease file")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
@@ -63,14 +63,14 @@ func (d *dhcp) watchChanges() {
|
|||||||
if event.Has(fsnotify.Write) || event.Has(fsnotify.Rename) || event.Has(fsnotify.Chmod) || event.Has(fsnotify.Remove) {
|
if event.Has(fsnotify.Write) || event.Has(fsnotify.Rename) || event.Has(fsnotify.Chmod) || event.Has(fsnotify.Remove) {
|
||||||
format := clientInfoFiles[event.Name]
|
format := clientInfoFiles[event.Name]
|
||||||
if err := d.readLeaseFile(event.Name, format); err != nil && !os.IsNotExist(err) {
|
if err := d.readLeaseFile(event.Name, format); err != nil && !os.IsNotExist(err) {
|
||||||
d.logger.Err(err).Str("file", event.Name).Msg("leases file changed but failed to update client info")
|
d.logger.Err(err).Str("file", event.Name).Msg("Leases file changed but failed to update client info")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case err, ok := <-d.watcher.Errors:
|
case err, ok := <-d.watcher.Errors:
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
d.logger.Err(err).Msg("could not watch client info file")
|
d.logger.Err(err).Msg("Could not watch client info file")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,7 +216,7 @@ func (d *dhcp) dnsmasqReadClientInfoReader(reader io.Reader) error {
|
|||||||
}
|
}
|
||||||
ip := normalizeIP(string(fields[2]))
|
ip := normalizeIP(string(fields[2]))
|
||||||
if net.ParseIP(ip) == nil {
|
if net.ParseIP(ip) == nil {
|
||||||
d.logger.Warn().Msgf("invalid ip address entry: %q", ip)
|
d.logger.Warn().Msgf("Invalid ip address entry: %q", ip)
|
||||||
ip = ""
|
ip = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,7 +271,7 @@ func (d *dhcp) iscDHCPReadClientInfoReader(reader io.Reader) error {
|
|||||||
// DHCP lease files may contain mixed-case IP addresses
|
// DHCP lease files may contain mixed-case IP addresses
|
||||||
ip = normalizeIP(strings.ToLower(fields[1]))
|
ip = normalizeIP(strings.ToLower(fields[1]))
|
||||||
if net.ParseIP(ip) == nil {
|
if net.ParseIP(ip) == nil {
|
||||||
d.logger.Warn().Msgf("invalid ip address entry: %q", ip)
|
d.logger.Warn().Msgf("Invalid ip address entry: %q", ip)
|
||||||
ip = ""
|
ip = ""
|
||||||
}
|
}
|
||||||
case "hardware":
|
case "hardware":
|
||||||
@@ -328,7 +328,7 @@ func (d *dhcp) keaDhcp4ReadClientInfoReader(r io.Reader) error {
|
|||||||
}
|
}
|
||||||
ip := normalizeIP(record[0])
|
ip := normalizeIP(record[0])
|
||||||
if net.ParseIP(ip) == nil {
|
if net.ParseIP(ip) == nil {
|
||||||
d.logger.Warn().Msgf("invalid ip address entry: %q", ip)
|
d.logger.Warn().Msgf("Invalid ip address entry: %q", ip)
|
||||||
ip = ""
|
ip = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,7 +350,7 @@ func (d *dhcp) keaDhcp4ReadClientInfoReader(r io.Reader) error {
|
|||||||
func (d *dhcp) addSelf() {
|
func (d *dhcp) addSelf() {
|
||||||
hostname, err := os.Hostname()
|
hostname, err := os.Hostname()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
d.logger.Err(err).Msg("could not get hostname")
|
d.logger.Err(err).Msg("Could not get hostname")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
hostname = normalizeHostname(hostname)
|
hostname = normalizeHostname(hostname)
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ func (hf *hostsFile) refresh() error {
|
|||||||
// override hosts file with host_entries.conf content if present.
|
// override hosts file with host_entries.conf content if present.
|
||||||
hem, err := parseHostEntriesConf(hostEntriesConfPath)
|
hem, err := parseHostEntriesConf(hostEntriesConfPath)
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
hf.logger.Debug().Err(err).Msg("could not read host_entries.conf file")
|
hf.logger.Debug().Err(err).Msg("Could not read host_entries.conf file")
|
||||||
}
|
}
|
||||||
for k, v := range hem {
|
for k, v := range hem {
|
||||||
hf.m[k] = v
|
hf.m[k] = v
|
||||||
@@ -78,14 +78,14 @@ func (hf *hostsFile) watchChanges() {
|
|||||||
}
|
}
|
||||||
if event.Has(fsnotify.Write) || event.Has(fsnotify.Rename) || event.Has(fsnotify.Chmod) || event.Has(fsnotify.Remove) {
|
if event.Has(fsnotify.Write) || event.Has(fsnotify.Rename) || event.Has(fsnotify.Chmod) || event.Has(fsnotify.Remove) {
|
||||||
if err := hf.refresh(); err != nil && !os.IsNotExist(err) {
|
if err := hf.refresh(); err != nil && !os.IsNotExist(err) {
|
||||||
hf.logger.Err(err).Msg("hosts file changed but failed to update client info")
|
hf.logger.Err(err).Msg("Hosts file changed but Failed to update client info")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case err, ok := <-hf.watcher.Errors:
|
case err, ok := <-hf.watcher.Errors:
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
hf.logger.Err(err).Msg("could not watch client info file")
|
hf.logger.Err(err).Msg("Could not watch client info file")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-10
@@ -94,9 +94,9 @@ func (m *mdns) init(quitCh chan struct{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if IPv6 is available once and use the result for the rest of the function.
|
// Check if IPv6 is available once and use the result for the rest of the function.
|
||||||
m.logger.Debug().Msgf("checking for IPv6 availability in mdns init")
|
m.logger.Debug().Msgf("Checking for ipv6 availability in mdns init")
|
||||||
ipv6 := ctrldnet.IPv6Available(context.Background())
|
ipv6 := ctrldnet.IPv6Available(context.Background())
|
||||||
m.logger.Debug().Msgf("IPv6 is %v in mdns init", ipv6)
|
m.logger.Debug().Msgf("ipv6 is %v in mdns init", ipv6)
|
||||||
|
|
||||||
v4ConnList := make([]*net.UDPConn, 0, len(ifaces))
|
v4ConnList := make([]*net.UDPConn, 0, len(ifaces))
|
||||||
v6ConnList := make([]*net.UDPConn, 0, len(ifaces))
|
v6ConnList := make([]*net.UDPConn, 0, len(ifaces))
|
||||||
@@ -130,11 +130,11 @@ func (m *mdns) probeLoop(conns []*net.UDPConn, remoteAddr net.Addr, quitCh chan
|
|||||||
for {
|
for {
|
||||||
err := m.probe(conns, remoteAddr)
|
err := m.probe(conns, remoteAddr)
|
||||||
if shouldStopProbing(err) {
|
if shouldStopProbing(err) {
|
||||||
m.logger.Warn().Msgf("stop probing %q: %v", remoteAddr, err)
|
m.logger.Warn().Msgf("Stop probing %q: %v", remoteAddr, err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
m.logger.Warn().Err(err).Msg("error while probing mdns")
|
m.logger.Warn().Err(err).Msg("Error while probing mdns")
|
||||||
bo.BackOff(context.Background(), errors.New("mdns probe backoff"))
|
bo.BackOff(context.Background(), errors.New("mdns probe backoff"))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -162,7 +162,7 @@ func (m *mdns) readLoop(conn *net.UDPConn) {
|
|||||||
if errors.Is(err, net.ErrClosed) {
|
if errors.Is(err, net.ErrClosed) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
m.logger.Debug().Err(err).Msg("mdns readLoop error")
|
m.logger.Debug().Err(err).Msg("Mdns readLoop error")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,11 +185,11 @@ func (m *mdns) readLoop(conn *net.UDPConn) {
|
|||||||
if ip != "" && name != "" {
|
if ip != "" && name != "" {
|
||||||
name = normalizeHostname(name)
|
name = normalizeHostname(name)
|
||||||
if val, loaded := m.name.LoadOrStore(ip, name); !loaded {
|
if val, loaded := m.name.LoadOrStore(ip, name); !loaded {
|
||||||
m.logger.Debug().Msgf("found hostname: %q, ip: %q via mdns", name, ip)
|
m.logger.Debug().Msgf("Found hostname: %q, ip: %q via mdns", name, ip)
|
||||||
} else {
|
} else {
|
||||||
old := val.(string)
|
old := val.(string)
|
||||||
if old != name {
|
if old != name {
|
||||||
m.logger.Debug().Msgf("update hostname: %q, ip: %q, old: %q via mdns", name, ip, old)
|
m.logger.Debug().Msgf("Update hostname: %q, ip: %q, old: %q via mdns", name, ip, old)
|
||||||
m.name.Store(ip, name)
|
m.name.Store(ip, name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -230,7 +230,7 @@ func (m *mdns) probe(conns []*net.UDPConn, remoteAddr net.Addr) error {
|
|||||||
// getDataFromAvahiDaemonCache reads entries from avahi-daemon cache to update mdns data.
|
// getDataFromAvahiDaemonCache reads entries from avahi-daemon cache to update mdns data.
|
||||||
func (m *mdns) getDataFromAvahiDaemonCache() {
|
func (m *mdns) getDataFromAvahiDaemonCache() {
|
||||||
if _, err := exec.LookPath("avahi-browse"); err != nil {
|
if _, err := exec.LookPath("avahi-browse"); err != nil {
|
||||||
m.logger.Debug().Err(err).Msg("could not find avahi-browse binary, skipping.")
|
m.logger.Debug().Err(err).Msg("Could not find avahi-browse binary, skipping.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Run avahi-browse to discover services from cache:
|
// Run avahi-browse to discover services from cache:
|
||||||
@@ -240,7 +240,7 @@ func (m *mdns) getDataFromAvahiDaemonCache() {
|
|||||||
// - "-c" -> read from cache.
|
// - "-c" -> read from cache.
|
||||||
out, err := exec.Command("avahi-browse", "-a", "-r", "-p", "-c").Output()
|
out, err := exec.Command("avahi-browse", "-a", "-r", "-p", "-c").Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
m.logger.Debug().Err(err).Msg("could not browse services from avahi cache")
|
m.logger.Debug().Err(err).Msg("Could not browse services from avahi cache")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
m.storeDataFromAvahiBrowseOutput(bytes.NewReader(out))
|
m.storeDataFromAvahiBrowseOutput(bytes.NewReader(out))
|
||||||
@@ -260,7 +260,7 @@ func (m *mdns) storeDataFromAvahiBrowseOutput(r io.Reader) {
|
|||||||
name := normalizeHostname(fields[6])
|
name := normalizeHostname(fields[6])
|
||||||
// Only using cache value if we don't have existed one.
|
// Only using cache value if we don't have existed one.
|
||||||
if _, loaded := m.name.LoadOrStore(ip, name); !loaded {
|
if _, loaded := m.name.LoadOrStore(ip, name); !loaded {
|
||||||
m.logger.Debug().Msgf("found hostname: %q, ip: %q via avahi cache", name, ip)
|
m.logger.Debug().Msgf("Found hostname: %q, ip: %q via avahi cache", name, ip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ func (nd *ndpDiscover) saveInfo(ip, mac string) {
|
|||||||
func (nd *ndpDiscover) listen(ctx context.Context) {
|
func (nd *ndpDiscover) listen(ctx context.Context) {
|
||||||
ifis, err := allInterfacesWithV6LinkLocal()
|
ifis, err := allInterfacesWithV6LinkLocal()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
nd.logger.Debug().Err(err).Msg("failed to find valid ipv6 interfaces")
|
nd.logger.Debug().Err(err).Msg("Failed to find valid ipv6 interfaces")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, ifi := range ifis {
|
for _, ifi := range ifis {
|
||||||
@@ -111,11 +111,11 @@ func (nd *ndpDiscover) listen(ctx context.Context) {
|
|||||||
func (nd *ndpDiscover) listenOnInterface(ctx context.Context, ifi *net.Interface) {
|
func (nd *ndpDiscover) listenOnInterface(ctx context.Context, ifi *net.Interface) {
|
||||||
c, ip, err := ndp.Listen(ifi, ndp.Unspecified)
|
c, ip, err := ndp.Listen(ifi, ndp.Unspecified)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
nd.logger.Debug().Err(err).Msg("ndp listen failed")
|
nd.logger.Debug().Err(err).Msg("Ndp listen failed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
nd.logger.Debug().Msgf("listening ndp on: %s", ip.String())
|
nd.logger.Debug().Msgf("Listening ndp on: %s", ip.String())
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
@@ -129,7 +129,7 @@ func (nd *ndpDiscover) listenOnInterface(ctx context.Context, ifi *net.Interface
|
|||||||
if errors.As(readErr, &opErr) && (opErr.Timeout() || opErr.Temporary()) {
|
if errors.As(readErr, &opErr) && (opErr.Timeout() || opErr.Temporary()) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
nd.logger.Debug().Err(readErr).Msg("ndp read loop error")
|
nd.logger.Debug().Err(readErr).Msg("Ndp read loop error")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
func (nd *ndpDiscover) scan() {
|
func (nd *ndpDiscover) scan() {
|
||||||
neighs, err := netlink.NeighList(0, netlink.FAMILY_V6)
|
neighs, err := netlink.NeighList(0, netlink.FAMILY_V6)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
nd.logger.Warn().Err(err).Msg("could not get neigh list")
|
nd.logger.Warn().Err(err).Msg("Could not get neighbor list")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ func (nd *ndpDiscover) subscribe(ctx context.Context) {
|
|||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
defer close(done)
|
defer close(done)
|
||||||
if err := netlink.NeighSubscribe(ch, done); err != nil {
|
if err := netlink.NeighSubscribe(ch, done); err != nil {
|
||||||
nd.logger.Err(err).Msg("could not perform neighbor subscribing")
|
nd.logger.Err(err).Msg("Could not perform neighbor subscribing")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
@@ -45,7 +45,7 @@ func (nd *ndpDiscover) subscribe(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
ip := normalizeIP(nu.IP.String())
|
ip := normalizeIP(nu.IP.String())
|
||||||
if nu.Type == unix.RTM_DELNEIGH {
|
if nu.Type == unix.RTM_DELNEIGH {
|
||||||
nd.logger.Debug().Msgf("removing NDP neighbor: %s", ip)
|
nd.logger.Debug().Msgf("Removing ndp neighbor: %s", ip)
|
||||||
nd.mac.Delete(ip)
|
nd.mac.Delete(ip)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -54,7 +54,7 @@ func (nd *ndpDiscover) subscribe(ctx context.Context) {
|
|||||||
case netlink.NUD_REACHABLE:
|
case netlink.NUD_REACHABLE:
|
||||||
nd.saveInfo(ip, mac)
|
nd.saveInfo(ip, mac)
|
||||||
case netlink.NUD_FAILED:
|
case netlink.NUD_FAILED:
|
||||||
nd.logger.Debug().Msgf("removing NDP neighbor with failed state: %s", ip)
|
nd.logger.Debug().Msgf("Removing ndp neighbor with failed state: %s", ip)
|
||||||
nd.mac.Delete(ip)
|
nd.mac.Delete(ip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,14 +15,14 @@ func (nd *ndpDiscover) scan() {
|
|||||||
case "windows":
|
case "windows":
|
||||||
data, err := exec.Command("netsh", "interface", "ipv6", "show", "neighbors").Output()
|
data, err := exec.Command("netsh", "interface", "ipv6", "show", "neighbors").Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
nd.logger.Warn().Err(err).Msg("could not query ndp table")
|
nd.logger.Warn().Err(err).Msg("Could not query ndp table")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
nd.scanWindows(bytes.NewReader(data))
|
nd.scanWindows(bytes.NewReader(data))
|
||||||
default:
|
default:
|
||||||
data, err := exec.Command("ndp", "-an").Output()
|
data, err := exec.Command("ndp", "-an").Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
nd.logger.Warn().Err(err).Msg("could not query ndp table")
|
nd.logger.Warn().Err(err).Msg("Could not query ndp table")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
nd.scanUnix(bytes.NewReader(data))
|
nd.scanUnix(bytes.NewReader(data))
|
||||||
|
|||||||
@@ -74,14 +74,14 @@ func (p *ptrDiscover) lookupHostname(ip string) string {
|
|||||||
msg := new(dns.Msg)
|
msg := new(dns.Msg)
|
||||||
addr, err := dns.ReverseAddr(ip)
|
addr, err := dns.ReverseAddr(ip)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.logger.Info().Str("discovery", "ptr").Err(err).Msg("invalid ip address")
|
p.logger.Info().Str("discovery", "ptr").Err(err).Msg("Invalid ip address")
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
msg.SetQuestion(addr, dns.TypePTR)
|
msg.SetQuestion(addr, dns.TypePTR)
|
||||||
ans, err := p.resolver.Resolve(ctx, msg)
|
ans, err := p.resolver.Resolve(ctx, msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if p.serverDown.CompareAndSwap(false, true) {
|
if p.serverDown.CompareAndSwap(false, true) {
|
||||||
p.logger.Info().Str("discovery", "ptr").Err(err).Msg("could not perform PTR lookup")
|
p.logger.Info().Str("discovery", "ptr").Err(err).Msg("Could not perform ptr lookup")
|
||||||
go p.checkServer()
|
go p.checkServer()
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
|
|||||||
@@ -287,7 +287,7 @@ func apiTransport(loggerCtx context.Context, cdDev bool) *http.Transport {
|
|||||||
ips := ctrld.LookupIP(loggerCtx, apiDomain)
|
ips := ctrld.LookupIP(loggerCtx, apiDomain)
|
||||||
if len(ips) == 0 {
|
if len(ips) == 0 {
|
||||||
logger := ctrld.LoggerFromCtx(loggerCtx)
|
logger := ctrld.LoggerFromCtx(loggerCtx)
|
||||||
logger.Warn().Msgf("No IPs found for %s, use direct IPs: %v", apiDomain, apiIPs)
|
logger.Warn().Msgf("No ips found for %s, use direct ips: %v", apiDomain, apiIPs)
|
||||||
ips = apiIPs
|
ips = apiIPs
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,7 +348,7 @@ func doWithFallback(ctx context.Context, client *http.Client, req *http.Request,
|
|||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger := ctrld.LoggerFromCtx(ctx)
|
logger := ctrld.LoggerFromCtx(ctx)
|
||||||
logger.Warn().Err(err).Msgf("failed to send request, fallback to direct IP: %s", apiIp)
|
logger.Warn().Err(err).Msgf("Failed to send request, fallback to direct ip: %s", apiIp)
|
||||||
ipReq := req.Clone(req.Context())
|
ipReq := req.Clone(req.Context())
|
||||||
ipReq.Host = apiIp
|
ipReq.Host = apiIp
|
||||||
ipReq.URL.Host = apiIp
|
ipReq.URL.Host = apiIp
|
||||||
|
|||||||
+4
-4
@@ -180,16 +180,16 @@ func (d *ParallelDialer) DialContext(ctx context.Context, network string, addrs
|
|||||||
for _, addr := range addrs {
|
for _, addr := range addrs {
|
||||||
go func(addr string) {
|
go func(addr string) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
logger.Debug("dialing to", zap.String("address", addr))
|
logger.Debug("Dialing to", zap.String("address", addr))
|
||||||
conn, err := d.Dialer.DialContext(ctx, network, addr)
|
conn, err := d.Dialer.DialContext(ctx, network, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Debug("failed to dial", zap.String("address", addr), zap.Error(err))
|
logger.Debug("Failed to dial", zap.String("address", addr), zap.Error(err))
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
case ch <- ¶llelDialerResult{conn: conn, err: err}:
|
case ch <- ¶llelDialerResult{conn: conn, err: err}:
|
||||||
case <-done:
|
case <-done:
|
||||||
if conn != nil {
|
if conn != nil {
|
||||||
logger.Debug("connection closed", zap.String("remote_address", conn.RemoteAddr().String()))
|
logger.Debug("Connection closed", zap.String("remote_address", conn.RemoteAddr().String()))
|
||||||
conn.Close()
|
conn.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -200,7 +200,7 @@ func (d *ParallelDialer) DialContext(ctx context.Context, network string, addrs
|
|||||||
for res := range ch {
|
for res := range ch {
|
||||||
if res.err == nil {
|
if res.err == nil {
|
||||||
cancel()
|
cancel()
|
||||||
logger.Debug("connected to", zap.String("remote_address", res.conn.RemoteAddr().String()))
|
logger.Debug("Connected to", zap.String("remote_address", res.conn.RemoteAddr().String()))
|
||||||
return res.conn, res.err
|
return res.conn, res.err
|
||||||
}
|
}
|
||||||
errs = append(errs, res.err)
|
errs = append(errs, res.err)
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ func getDNSFromScutil(ctx context.Context) []string {
|
|||||||
cmd := exec.Command("scutil", "--dns")
|
cmd := exec.Command("scutil", "--dns")
|
||||||
output, err := cmd.Output()
|
output, err := cmd.Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Log(context.Background(), logger.Error(), "failed to execute scutil --dns (attempt %d/%d): %v", attempt+1, maxRetries, err)
|
Log(context.Background(), logger.Error(), "Failed to execute scutil --dns (attempt %d/%d): %v", attempt+1, maxRetries, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ func getDNSFromScutil(ctx context.Context) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := scanner.Err(); err != nil {
|
if err := scanner.Err(); err != nil {
|
||||||
Log(context.Background(), logger.Error(), "error scanning scutil output (attempt %d/%d): %v", attempt+1, maxRetries, err)
|
Log(context.Background(), logger.Error(), "Error scanning scutil output (attempt %d/%d): %v", attempt+1, maxRetries, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,7 +172,7 @@ func getAllDHCPNameservers(ctx context.Context) []string {
|
|||||||
|
|
||||||
// if we have static DNS servers saved for the current default route, we should add them to the list
|
// if we have static DNS servers saved for the current default route, we should add them to the list
|
||||||
drIfaceName, err := netmon.DefaultRouteInterface()
|
drIfaceName, err := netmon.DefaultRouteInterface()
|
||||||
Log(context.Background(), logger.Debug(), "checking for static DNS servers for default route interface: %s", drIfaceName)
|
Log(context.Background(), logger.Debug(), "Checking for static DNS servers for default route interface: %s", drIfaceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Log(context.Background(), logger.Debug(),
|
Log(context.Background(), logger.Debug(),
|
||||||
"Failed to get default route interface: %v", err)
|
"Failed to get default route interface: %v", err)
|
||||||
|
|||||||
@@ -281,7 +281,7 @@ func getDNSServers(ctx context.Context) ([]string, error) {
|
|||||||
logger.Debug().Msgf("Failed to get interface by name %s: %v", drIfaceName, err)
|
logger.Debug().Msgf("Failed to get interface by name %s: %v", drIfaceName, err)
|
||||||
} else {
|
} else {
|
||||||
staticNs, file := SavedStaticNameserversAndPath(drIface)
|
staticNs, file := SavedStaticNameserversAndPath(drIface)
|
||||||
logger.Debug().Msgf("static dns servers from %s: %v", file, staticNs)
|
logger.Debug().Msgf("Static dns servers from %s: %v", file, staticNs)
|
||||||
if len(staticNs) > 0 {
|
if len(staticNs) > 0 {
|
||||||
logger.Debug().Msgf("Adding static DNS servers from %s: %v", drIfaceName, staticNs)
|
logger.Debug().Msgf("Adding static DNS servers from %s: %v", drIfaceName, staticNs)
|
||||||
ns = append(ns, staticNs...)
|
ns = append(ns, staticNs...)
|
||||||
@@ -392,20 +392,20 @@ func ValidInterfaces(ctx context.Context) map[string]struct{} {
|
|||||||
defer instances.Close()
|
defer instances.Close()
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warn().Msgf("failed to get wmi network adapter: %v", err)
|
logger.Warn().Msgf("Failed to get wmi network adapter: %v", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var adapters []string
|
var adapters []string
|
||||||
for _, i := range instances {
|
for _, i := range instances {
|
||||||
adapter, err := netadapter.NewNetworkAdapter(i)
|
adapter, err := netadapter.NewNetworkAdapter(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warn().Msgf("failed to get network adapter: %v", err)
|
logger.Warn().Msgf("Failed to get network adapter: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
name, err := adapter.GetPropertyName()
|
name, err := adapter.GetPropertyName()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warn().Msgf("failed to get interface name: %v", err)
|
logger.Warn().Msgf("Failed to get interface name: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,11 +415,11 @@ func ValidInterfaces(ctx context.Context) map[string]struct{} {
|
|||||||
// if this is a physical adapter or FALSE if this is not a physical adapter."
|
// if this is a physical adapter or FALSE if this is not a physical adapter."
|
||||||
physical, err := adapter.GetPropertyConnectorPresent()
|
physical, err := adapter.GetPropertyConnectorPresent()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Debug().Msgf("failed to get network adapter connector present property: %v", err)
|
logger.Debug().Msgf("Failed to get network adapter connector present property: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !physical {
|
if !physical {
|
||||||
logger.Debug().Msgf("skipping non-physical adapter: %s", name)
|
logger.Debug().Msgf("Skipping non-physical adapter: %s", name)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -427,11 +427,11 @@ func ValidInterfaces(ctx context.Context) map[string]struct{} {
|
|||||||
// because some interfaces are not physical but have a connector.
|
// because some interfaces are not physical but have a connector.
|
||||||
hardware, err := adapter.GetPropertyHardwareInterface()
|
hardware, err := adapter.GetPropertyHardwareInterface()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Debug().Msgf("failed to get network adapter hardware interface property: %v", err)
|
logger.Debug().Msgf("Failed to get network adapter hardware interface property: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !hardware {
|
if !hardware {
|
||||||
logger.Debug().Msgf("skipping non-hardware interface: %s", name)
|
logger.Debug().Msgf("Skipping non-hardware interface: %s", name)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ var (
|
|||||||
func HasIPv6(ctx context.Context) bool {
|
func HasIPv6(ctx context.Context) bool {
|
||||||
hasIPv6Once.Do(func() {
|
hasIPv6Once.Do(func() {
|
||||||
logger := LoggerFromCtx(ctx)
|
logger := LoggerFromCtx(ctx)
|
||||||
logger.Debug().Msg("checking for IPv6 availability once")
|
logger.Debug().Msg("Checking for ipv6 availability once")
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
val := ctrldnet.IPv6Available(ctx)
|
val := ctrldnet.IPv6Available(ctx)
|
||||||
@@ -28,7 +28,7 @@ func HasIPv6(ctx context.Context) bool {
|
|||||||
logger.Debug().Msgf("ipv6 availability: %v", val)
|
logger.Debug().Msgf("ipv6 availability: %v", val)
|
||||||
mon, err := netmon.New(func(format string, args ...any) {})
|
mon, err := netmon.New(func(format string, args ...any) {})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Debug().Err(err).Msg("failed to monitor IPv6 state")
|
logger.Debug().Err(err).Msg("Failed to monitor ipv6 state")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
mon.RegisterChangeCallback(func(delta *netmon.ChangeDelta) {
|
mon.RegisterChangeCallback(func(delta *netmon.ChangeDelta) {
|
||||||
@@ -37,7 +37,7 @@ func HasIPv6(ctx context.Context) bool {
|
|||||||
if old != cur {
|
if old != cur {
|
||||||
logger.Warn().Msgf("ipv6 availability changed, old: %v, new: %v", old, cur)
|
logger.Warn().Msgf("ipv6 availability changed, old: %v, new: %v", old, cur)
|
||||||
} else {
|
} else {
|
||||||
logger.Debug().Msg("ipv6 availability does not changed")
|
logger.Debug().Msg("ipv6 availability does not Changed")
|
||||||
}
|
}
|
||||||
ipv6Available.Store(cur)
|
ipv6Available.Store(cur)
|
||||||
})
|
})
|
||||||
@@ -50,6 +50,6 @@ func HasIPv6(ctx context.Context) bool {
|
|||||||
func DisableIPv6(ctx context.Context) {
|
func DisableIPv6(ctx context.Context) {
|
||||||
if ipv6Available.CompareAndSwap(true, false) {
|
if ipv6Available.CompareAndSwap(true, false) {
|
||||||
logger := LoggerFromCtx(ctx)
|
logger := LoggerFromCtx(ctx)
|
||||||
logger.Debug().Msg("turned off IPv6 availability")
|
logger.Debug().Msg("Turned off ipv6 availability")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-12
@@ -427,7 +427,7 @@ func (o *osResolver) resolve(ctx context.Context, msg *dns.Msg) (*dns.Msg, error
|
|||||||
switch {
|
switch {
|
||||||
case res.lan:
|
case res.lan:
|
||||||
// Always prefer LAN responses immediately
|
// Always prefer LAN responses immediately
|
||||||
Log(ctx, logger.Debug(), "using LAN answer from: %s", res.server)
|
Log(ctx, logger.Debug(), "Using LAN answer from: %s", res.server)
|
||||||
cancel()
|
cancel()
|
||||||
logAnswer(res.server)
|
logAnswer(res.server)
|
||||||
return res.answer, nil
|
return res.answer, nil
|
||||||
@@ -437,7 +437,7 @@ func (o *osResolver) resolve(ctx context.Context, msg *dns.Msg) (*dns.Msg, error
|
|||||||
// if there are no LAN nameservers, we should not wait
|
// if there are no LAN nameservers, we should not wait
|
||||||
// just use the first response
|
// just use the first response
|
||||||
if len(nss) == 0 {
|
if len(nss) == 0 {
|
||||||
Log(ctx, logger.Debug(), "using public answer from: %s", res.server)
|
Log(ctx, logger.Debug(), "Using public answer from: %s", res.server)
|
||||||
cancel()
|
cancel()
|
||||||
logAnswer(res.server)
|
logAnswer(res.server)
|
||||||
return res.answer, nil
|
return res.answer, nil
|
||||||
@@ -448,12 +448,12 @@ func (o *osResolver) resolve(ctx context.Context, msg *dns.Msg) (*dns.Msg, error
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
case res.answer != nil:
|
case res.answer != nil:
|
||||||
Log(ctx, logger.Debug(), "got non-success answer from: %s with code: %d",
|
Log(ctx, logger.Debug(), "Got non-success answer from: %s with code: %d",
|
||||||
res.server, res.answer.Rcode)
|
res.server, res.answer.Rcode)
|
||||||
// When there are no LAN nameservers, we should not wait
|
// When there are no LAN nameservers, we should not wait
|
||||||
// for other nameservers to respond.
|
// for other nameservers to respond.
|
||||||
if len(nss) == 0 {
|
if len(nss) == 0 {
|
||||||
Log(ctx, logger.Debug(), "no lan nameservers using public non success answer")
|
Log(ctx, logger.Debug(), "No lan nameservers using public non success answer")
|
||||||
cancel()
|
cancel()
|
||||||
logAnswer(res.server)
|
logAnswer(res.server)
|
||||||
return res.answer, nil
|
return res.answer, nil
|
||||||
@@ -466,17 +466,17 @@ func (o *osResolver) resolve(ctx context.Context, msg *dns.Msg) (*dns.Msg, error
|
|||||||
|
|
||||||
if len(publicResponses) > 0 {
|
if len(publicResponses) > 0 {
|
||||||
resp := publicResponses[0]
|
resp := publicResponses[0]
|
||||||
Log(ctx, logger.Debug(), "using public answer from: %s", resp.server)
|
Log(ctx, logger.Debug(), "Using public answer from: %s", resp.server)
|
||||||
logAnswer(resp.server)
|
logAnswer(resp.server)
|
||||||
return resp.answer, nil
|
return resp.answer, nil
|
||||||
}
|
}
|
||||||
if controldSuccessAnswer != nil {
|
if controldSuccessAnswer != nil {
|
||||||
Log(ctx, logger.Debug(), "using ControlD answer from: %s", controldPublicDnsWithPort)
|
Log(ctx, logger.Debug(), "Using ControlD answer from: %s", controldPublicDnsWithPort)
|
||||||
logAnswer(controldPublicDnsWithPort)
|
logAnswer(controldPublicDnsWithPort)
|
||||||
return controldSuccessAnswer, nil
|
return controldSuccessAnswer, nil
|
||||||
}
|
}
|
||||||
if nonSuccessAnswer != nil {
|
if nonSuccessAnswer != nil {
|
||||||
Log(ctx, logger.Debug(), "using non-success answer from: %s", nonSuccessServer)
|
Log(ctx, logger.Debug(), "Using non-success answer from: %s", nonSuccessServer)
|
||||||
logAnswer(nonSuccessServer)
|
logAnswer(nonSuccessServer)
|
||||||
return nonSuccessAnswer, nil
|
return nonSuccessAnswer, nil
|
||||||
}
|
}
|
||||||
@@ -563,12 +563,12 @@ func lookupIP(ctx context.Context, domain string, timeout int, bootstrapDNS []st
|
|||||||
}
|
}
|
||||||
logger := LoggerFromCtx(ctx)
|
logger := LoggerFromCtx(ctx)
|
||||||
if bootstrapDNS == nil {
|
if bootstrapDNS == nil {
|
||||||
logger.Debug().Msgf("empty bootstrap DNS")
|
logger.Debug().Msgf("Empty bootstrap dns")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
resolver := newResolverWithNameserver(bootstrapDNS)
|
resolver := newResolverWithNameserver(bootstrapDNS)
|
||||||
logger.Debug().Msgf("resolving %q using bootstrap DNS %q", domain, bootstrapDNS)
|
logger.Debug().Msgf("Resolving %q using bootstrap dns %q", domain, bootstrapDNS)
|
||||||
|
|
||||||
timeoutMs := 2000
|
timeoutMs := 2000
|
||||||
if timeout > 0 && timeout < timeoutMs {
|
if timeout > 0 && timeout < timeoutMs {
|
||||||
@@ -612,15 +612,15 @@ func lookupIP(ctx context.Context, domain string, timeout int, bootstrapDNS []st
|
|||||||
|
|
||||||
r, err := resolver.Resolve(ctx, m)
|
r, err := resolver.Resolve(ctx, m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error().Err(err).Msgf("could not lookup %q record for domain %q", dns.TypeToString[dnsType], domain)
|
logger.Error().Err(err).Msgf("Could not lookup %q record for domain %q", dns.TypeToString[dnsType], domain)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if r.Rcode != dns.RcodeSuccess {
|
if r.Rcode != dns.RcodeSuccess {
|
||||||
logger.Error().Msgf("could not resolve domain %q, return code: %s", domain, dns.RcodeToString[r.Rcode])
|
logger.Error().Msgf("Could not resolve domain %q, return code: %s", domain, dns.RcodeToString[r.Rcode])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(r.Answer) == 0 {
|
if len(r.Answer) == 0 {
|
||||||
logger.Error().Msg("no answer from OS resolver")
|
logger.Error().Msg("No answer from os resolver")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
target := targetDomain(r.Answer)
|
target := targetDomain(r.Answer)
|
||||||
|
|||||||
Reference in New Issue
Block a user