summaryrefslogtreecommitdiffhomepage
path: root/net/dns/manager.go
diff options
context:
space:
mode:
Diffstat (limited to 'net/dns/manager.go')
-rw-r--r--net/dns/manager.go36
1 files changed, 28 insertions, 8 deletions
diff --git a/net/dns/manager.go b/net/dns/manager.go
index ebf91811a..1e9eb7fe7 100644
--- a/net/dns/manager.go
+++ b/net/dns/manager.go
@@ -35,6 +35,9 @@ import (
var (
errFullQueue = errors.New("request queue full")
+ // ErrNoDNSConfig is returned by RecompileDNSConfig when the Manager
+ // has no existing DNS configuration.
+ ErrNoDNSConfig = errors.New("no DNS configuration")
)
// maxActiveQueries returns the maximal number of DNS requests that can
@@ -91,21 +94,18 @@ func NewManager(logf logger.Logf, oscfg OSConfigurator, health *health.Tracker,
}
// Rate limit our attempts to correct our DNS configuration.
+ // This is done on incoming queries, we don't want to spam it.
limiter := rate.NewLimiter(1.0/5.0, 1)
// This will recompile the DNS config, which in turn will requery the system
// DNS settings. The recovery func should triggered only when we are missing
// upstream nameservers and require them to forward a query.
m.resolver.SetMissingUpstreamRecovery(func() {
- m.mu.Lock()
- defer m.mu.Unlock()
- if m.config == nil {
- return
- }
-
if limiter.Allow() {
- m.logf("DNS resolution failed due to missing upstream nameservers. Recompiling DNS configuration.")
- m.setLocked(*m.config)
+ m.logf("resolution failed due to missing upstream nameservers. Recompiling DNS configuration.")
+ if err := m.RecompileDNSConfig(); err != nil {
+ m.logf("config recompilation failed: %v", err)
+ }
}
})
@@ -117,6 +117,26 @@ func NewManager(logf logger.Logf, oscfg OSConfigurator, health *health.Tracker,
// Resolver returns the Manager's DNS Resolver.
func (m *Manager) Resolver() *resolver.Resolver { return m.resolver }
+// RecompileDNSConfig sets the DNS config to the current value, which has
+// the side effect of re-querying the OS's interface nameservers. This should be used
+// on platforms where the interface nameservers can change. Darwin, for example,
+// where the nameservers aren't always available when we process a major interface
+// change event, or platforms where the nameservers may change while tunnel is up.
+//
+// This should be called if it is determined that [OSConfigurator.GetBaseConfig] may
+// give a better or different result than when [Manager.Set] was last called. The
+// logic for making that determination is up to the caller.
+//
+// It returns [ErrNoDNSConfig] if the [Manager] has no existing DNS configuration.
+func (m *Manager) RecompileDNSConfig() error {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+ if m.config == nil {
+ return ErrNoDNSConfig
+ }
+ return m.setLocked(*m.config)
+}
+
func (m *Manager) Set(cfg Config) error {
m.mu.Lock()
defer m.mu.Unlock()