diff --git a/wgengine/router/callback.go b/wgengine/router/callback.go new file mode 100644 index 000000000..b36e399a3 --- /dev/null +++ b/wgengine/router/callback.go @@ -0,0 +1,54 @@ +// Copyright (c) 2021 Tailscale Inc & AUTHORS All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package router + +import ( + "sync" + + "tailscale.com/net/dns" +) + +// CallbackRouter is an implementation of both Router and dns.OSConfigurator. +// When either network or DNS settings are changed, SetBoth is called with both configs. +// Mainly used as a shim for OSes that want to set both network and +// DNS configuration simultaneously (iOS, android). +type CallbackRouter struct { + SetBoth func(rcfg *Config, dcfg *dns.OSConfig) error + DNSMode dns.RoutingMode + + mu sync.Mutex // protects all the following + rcfg *Config // last applied router config + dcfg *dns.OSConfig // last applied DNS config +} + +// Up implements Router. +func (r *CallbackRouter) Up() error { + return nil // TODO: check that all callers have no need for initialization +} + +// Set implements Router. +func (r *CallbackRouter) Set(rcfg *Config) error { + r.mu.Lock() + defer r.mu.Unlock() + r.rcfg = rcfg + return r.SetBoth(r.rcfg, r.dcfg) +} + +// SetDNS implements dns.OSConfigurator. +func (r *CallbackRouter) SetDNS(dcfg dns.OSConfig) error { + r.mu.Lock() + defer r.mu.Unlock() + r.dcfg = &dcfg + return r.SetBoth(r.rcfg, r.dcfg) +} + +// RoutingMode implements dns.OSConfigurator. +func (r *CallbackRouter) RoutingMode() dns.RoutingMode { + return r.DNSMode +} + +func (r *CallbackRouter) Close() error { + return r.SetBoth(nil, nil) // TODO: check if makes sense +}