Skip to content

Commit e2bc1b0

Browse files
committed
Merge tag 'v1.84.1' into sunos-1.84
2 parents 255fdfa + 72ec281 commit e2bc1b0

File tree

6 files changed

+79
-63
lines changed

6 files changed

+79
-63
lines changed

VERSION.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.84.0
1+
1.84.1

ipn/prefs.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -721,9 +721,10 @@ func (p *Prefs) ControlURLOrDefault() string {
721721
// of the platform it's running on.
722722
func (p *Prefs) DefaultRouteAll(goos string) bool {
723723
switch goos {
724-
case "windows":
724+
case "windows", "android", "ios":
725725
return true
726726
case "darwin":
727+
// Only true for macAppStore and macsys, false for darwin tailscaled.
727728
return version.IsSandboxedMacOS()
728729
default:
729730
return false

net/dns/manager.go

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import (
2525
"tailscale.com/net/netmon"
2626
"tailscale.com/net/tsdial"
2727
"tailscale.com/syncs"
28-
"tailscale.com/tstime/rate"
2928
"tailscale.com/types/dnstype"
3029
"tailscale.com/types/logger"
3130
"tailscale.com/util/clientmetric"
@@ -63,10 +62,8 @@ type Manager struct {
6362
knobs *controlknobs.Knobs // or nil
6463
goos string // if empty, gets set to runtime.GOOS
6564

66-
mu sync.Mutex // guards following
67-
// config is the last configuration we successfully compiled or nil if there
68-
// was any failure applying the last configuration.
69-
config *Config
65+
mu sync.Mutex // guards following
66+
config *Config // Tracks the last viable DNS configuration set by Set. nil on failures other than compilation failures or if set has never been called.
7067
}
7168

7269
// NewManagers created a new manager from the given config.
@@ -93,22 +90,6 @@ func NewManager(logf logger.Logf, oscfg OSConfigurator, health *health.Tracker,
9390
goos: goos,
9491
}
9592

96-
// Rate limit our attempts to correct our DNS configuration.
97-
// This is done on incoming queries, we don't want to spam it.
98-
limiter := rate.NewLimiter(1.0/5.0, 1)
99-
100-
// This will recompile the DNS config, which in turn will requery the system
101-
// DNS settings. The recovery func should triggered only when we are missing
102-
// upstream nameservers and require them to forward a query.
103-
m.resolver.SetMissingUpstreamRecovery(func() {
104-
if limiter.Allow() {
105-
m.logf("resolution failed due to missing upstream nameservers. Recompiling DNS configuration.")
106-
if err := m.RecompileDNSConfig(); err != nil {
107-
m.logf("config recompilation failed: %v", err)
108-
}
109-
}
110-
})
111-
11293
m.ctx, m.ctxCancel = context.WithCancel(context.Background())
11394
m.logf("using %T", m.os)
11495
return m
@@ -117,7 +98,7 @@ func NewManager(logf logger.Logf, oscfg OSConfigurator, health *health.Tracker,
11798
// Resolver returns the Manager's DNS Resolver.
11899
func (m *Manager) Resolver() *resolver.Resolver { return m.resolver }
119100

120-
// RecompileDNSConfig sets the DNS config to the current value, which has
101+
// RecompileDNSConfig recompiles the last attempted DNS configuration, which has
121102
// the side effect of re-querying the OS's interface nameservers. This should be used
122103
// on platforms where the interface nameservers can change. Darwin, for example,
123104
// where the nameservers aren't always available when we process a major interface
@@ -127,14 +108,14 @@ func (m *Manager) Resolver() *resolver.Resolver { return m.resolver }
127108
// give a better or different result than when [Manager.Set] was last called. The
128109
// logic for making that determination is up to the caller.
129110
//
130-
// It returns [ErrNoDNSConfig] if the [Manager] has no existing DNS configuration.
111+
// It returns [ErrNoDNSConfig] if [Manager.Set] has never been called.
131112
func (m *Manager) RecompileDNSConfig() error {
132113
m.mu.Lock()
133114
defer m.mu.Unlock()
134-
if m.config == nil {
135-
return ErrNoDNSConfig
115+
if m.config != nil {
116+
return m.setLocked(*m.config)
136117
}
137-
return m.setLocked(*m.config)
118+
return ErrNoDNSConfig
138119
}
139120

140121
func (m *Manager) Set(cfg Config) error {
@@ -154,15 +135,15 @@ func (m *Manager) GetBaseConfig() (OSConfig, error) {
154135
func (m *Manager) setLocked(cfg Config) error {
155136
syncs.AssertLocked(&m.mu)
156137

157-
// On errors, the 'set' config is cleared.
158-
m.config = nil
159-
160138
m.logf("Set: %v", logger.ArgWriter(func(w *bufio.Writer) {
161139
cfg.WriteToBufioWriter(w)
162140
}))
163141

164142
rcfg, ocfg, err := m.compileConfig(cfg)
165143
if err != nil {
144+
// On a compilation failure, set m.config set for later reuse by
145+
// [Manager.RecompileDNSConfig] and return the error.
146+
m.config = &cfg
166147
return err
167148
}
168149

@@ -174,9 +155,11 @@ func (m *Manager) setLocked(cfg Config) error {
174155
}))
175156

176157
if err := m.resolver.SetConfig(rcfg); err != nil {
158+
m.config = nil
177159
return err
178160
}
179161
if err := m.os.SetDNS(ocfg); err != nil {
162+
m.config = nil
180163
m.health.SetUnhealthy(osConfigurationSetWarnable, health.Args{health.ArgError: err.Error()})
181164
return err
182165
}
@@ -355,7 +338,10 @@ func (m *Manager) compileConfig(cfg Config) (rcfg resolver.Config, ocfg OSConfig
355338
// that as the forwarder for all DNS traffic that quad-100 doesn't handle.
356339
if isApple || !m.os.SupportsSplitDNS() {
357340
// If the OS can't do native split-dns, read out the underlying
358-
// resolver config and blend it into our config.
341+
// resolver config and blend it into our config. On apple platforms, [OSConfigurator.GetBaseConfig]
342+
// has a tendency to temporarily fail if called immediately following
343+
// an interface change. These failures should be retried if/when the OS
344+
// indicates that the DNS configuration has changed via [RecompileDNSConfig].
359345
cfg, err := m.os.GetBaseConfig()
360346
if err == nil {
361347
baseCfg = &cfg

net/dns/manager_test.go

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package dns
55

66
import (
7+
"errors"
78
"net/netip"
89
"runtime"
910
"strings"
@@ -24,8 +25,9 @@ type fakeOSConfigurator struct {
2425
SplitDNS bool
2526
BaseConfig OSConfig
2627

27-
OSConfig OSConfig
28-
ResolverConfig resolver.Config
28+
OSConfig OSConfig
29+
ResolverConfig resolver.Config
30+
GetBaseConfigErr *error
2931
}
3032

3133
func (c *fakeOSConfigurator) SetDNS(cfg OSConfig) error {
@@ -45,6 +47,9 @@ func (c *fakeOSConfigurator) SupportsSplitDNS() bool {
4547
}
4648

4749
func (c *fakeOSConfigurator) GetBaseConfig() (OSConfig, error) {
50+
if c.GetBaseConfigErr != nil {
51+
return OSConfig{}, *c.GetBaseConfigErr
52+
}
4853
return c.BaseConfig, nil
4954
}
5055

@@ -1019,3 +1024,50 @@ func upstreams(strs ...string) (ret map[dnsname.FQDN][]*dnstype.Resolver) {
10191024
}
10201025
return ret
10211026
}
1027+
1028+
func TestConfigRecompilation(t *testing.T) {
1029+
fakeErr := errors.New("fake os configurator error")
1030+
f := &fakeOSConfigurator{}
1031+
f.GetBaseConfigErr = &fakeErr
1032+
f.BaseConfig = OSConfig{
1033+
Nameservers: mustIPs("1.1.1.1"),
1034+
}
1035+
1036+
config := Config{
1037+
Routes: upstreams("ts.net", "69.4.2.0", "foo.ts.net", ""),
1038+
SearchDomains: fqdns("foo.ts.net"),
1039+
}
1040+
1041+
m := NewManager(t.Logf, f, new(health.Tracker), tsdial.NewDialer(netmon.NewStatic()), nil, nil, "darwin")
1042+
1043+
var managerConfig *resolver.Config
1044+
m.resolver.TestOnlySetHook(func(cfg resolver.Config) {
1045+
managerConfig = &cfg
1046+
})
1047+
1048+
// Initial set should error out and store the config
1049+
if err := m.Set(config); err == nil {
1050+
t.Fatalf("Want non-nil error. Got nil")
1051+
}
1052+
if m.config == nil {
1053+
t.Fatalf("Want persisted config. Got nil.")
1054+
}
1055+
if managerConfig != nil {
1056+
t.Fatalf("Want nil managerConfig. Got %v", managerConfig)
1057+
}
1058+
1059+
// Clear the error. We should take the happy path now and
1060+
// set m.manager's Config.
1061+
f.GetBaseConfigErr = nil
1062+
1063+
// Recompilation without an error should succeed and set m.config and m.manager's [resolver.Config]
1064+
if err := m.RecompileDNSConfig(); err != nil {
1065+
t.Fatalf("Want nil error. Got err %v", err)
1066+
}
1067+
if m.config == nil {
1068+
t.Fatalf("Want non-nil config. Got nil")
1069+
}
1070+
if managerConfig == nil {
1071+
t.Fatalf("Want non nil managerConfig. Got nil")
1072+
}
1073+
}

net/dns/resolver/forwarder.go

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -245,26 +245,19 @@ type forwarder struct {
245245
// /etc/resolv.conf is missing/corrupt, and the peerapi ExitDNS stub
246246
// resolver lookup.
247247
cloudHostFallback []resolverAndDelay
248-
249-
// missingUpstreamRecovery, if non-nil, is set called when a SERVFAIL is
250-
// returned due to missing upstream resolvers.
251-
//
252-
// This should attempt to properly (re)set the upstream resolvers.
253-
missingUpstreamRecovery func()
254248
}
255249

256250
func newForwarder(logf logger.Logf, netMon *netmon.Monitor, linkSel ForwardLinkSelector, dialer *tsdial.Dialer, health *health.Tracker, knobs *controlknobs.Knobs) *forwarder {
257251
if netMon == nil {
258252
panic("nil netMon")
259253
}
260254
f := &forwarder{
261-
logf: logger.WithPrefix(logf, "forward: "),
262-
netMon: netMon,
263-
linkSel: linkSel,
264-
dialer: dialer,
265-
health: health,
266-
controlKnobs: knobs,
267-
missingUpstreamRecovery: func() {},
255+
logf: logger.WithPrefix(logf, "forward: "),
256+
netMon: netMon,
257+
linkSel: linkSel,
258+
dialer: dialer,
259+
health: health,
260+
controlKnobs: knobs,
268261
}
269262
f.ctx, f.ctxCancel = context.WithCancel(context.Background())
270263
return f
@@ -962,13 +955,6 @@ func (f *forwarder) forwardWithDestChan(ctx context.Context, query packet, respo
962955
f.health.SetUnhealthy(dnsForwarderFailing, health.Args{health.ArgDNSServers: ""})
963956
f.logf("no upstream resolvers set, returning SERVFAIL")
964957

965-
// Attempt to recompile the DNS configuration
966-
// If we are being asked to forward queries and we have no
967-
// nameservers, the network is in a bad state.
968-
if f.missingUpstreamRecovery != nil {
969-
f.missingUpstreamRecovery()
970-
}
971-
972958
res, err := servfailResponse(query)
973959
if err != nil {
974960
return err

net/dns/resolver/tsdns.go

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -251,15 +251,6 @@ func New(logf logger.Logf, linkSel ForwardLinkSelector, dialer *tsdial.Dialer, h
251251
return r
252252
}
253253

254-
// SetMissingUpstreamRecovery sets a callback to be called upon encountering
255-
// a SERVFAIL due to missing upstream resolvers.
256-
//
257-
// This call should only happen before the resolver is used. It is not safe
258-
// for concurrent use.
259-
func (r *Resolver) SetMissingUpstreamRecovery(f func()) {
260-
r.forwarder.missingUpstreamRecovery = f
261-
}
262-
263254
func (r *Resolver) TestOnlySetHook(hook func(Config)) { r.saveConfigForTests = hook }
264255

265256
func (r *Resolver) SetConfig(cfg Config) error {

0 commit comments

Comments
 (0)