Update dependencies
This commit is contained in:
52
vendor/tailscale.com/net/dns/direct_linux.go
generated
vendored
52
vendor/tailscale.com/net/dns/direct_linux.go
generated
vendored
@@ -6,21 +6,25 @@ package dns
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/illarion/gonotify/v2"
|
||||
"github.com/illarion/gonotify/v3"
|
||||
"tailscale.com/health"
|
||||
)
|
||||
|
||||
func (m *directManager) runFileWatcher() {
|
||||
ctx, cancel := context.WithCancel(m.ctx)
|
||||
defer cancel()
|
||||
in, err := gonotify.NewInotify(ctx)
|
||||
if err != nil {
|
||||
// Oh well, we tried. This is all best effort for now, to
|
||||
// surface warnings to users.
|
||||
m.logf("dns: inotify new: %v", err)
|
||||
return
|
||||
if err := watchFile(m.ctx, "/etc/", resolvConf, m.checkForFileTrample); err != nil {
|
||||
// This is all best effort for now, so surface warnings to users.
|
||||
m.logf("dns: inotify: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// watchFile sets up an inotify watch for a given directory and
|
||||
// calls the callback function every time a particular file is changed.
|
||||
// The filename should be located in the provided directory.
|
||||
func watchFile(ctx context.Context, dir, filename string, cb func()) error {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
|
||||
const events = gonotify.IN_ATTRIB |
|
||||
gonotify.IN_CLOSE_WRITE |
|
||||
@@ -29,30 +33,20 @@ func (m *directManager) runFileWatcher() {
|
||||
gonotify.IN_MODIFY |
|
||||
gonotify.IN_MOVE
|
||||
|
||||
if err := in.AddWatch("/etc/", events); err != nil {
|
||||
m.logf("dns: inotify addwatch: %v", err)
|
||||
return
|
||||
watcher, err := gonotify.NewDirWatcher(ctx, events, dir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("NewDirWatcher: %w", err)
|
||||
}
|
||||
|
||||
for {
|
||||
events, err := in.Read()
|
||||
if ctx.Err() != nil {
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
m.logf("dns: inotify read: %v", err)
|
||||
return
|
||||
}
|
||||
var match bool
|
||||
for _, ev := range events {
|
||||
if ev.Name == resolvConf {
|
||||
match = true
|
||||
break
|
||||
select {
|
||||
case event := <-watcher.C:
|
||||
if event.Name == filename {
|
||||
cb()
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
}
|
||||
if !match {
|
||||
continue
|
||||
}
|
||||
m.checkForFileTrample()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
72
vendor/tailscale.com/net/dns/manager.go
generated
vendored
72
vendor/tailscale.com/net/dns/manager.go
generated
vendored
@@ -8,6 +8,7 @@ import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/netip"
|
||||
@@ -18,7 +19,6 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
xmaps "golang.org/x/exp/maps"
|
||||
"tailscale.com/control/controlknobs"
|
||||
"tailscale.com/health"
|
||||
"tailscale.com/net/dns/resolver"
|
||||
@@ -30,10 +30,14 @@ import (
|
||||
"tailscale.com/types/logger"
|
||||
"tailscale.com/util/clientmetric"
|
||||
"tailscale.com/util/dnsname"
|
||||
"tailscale.com/util/slicesx"
|
||||
)
|
||||
|
||||
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
|
||||
@@ -90,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)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -116,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()
|
||||
@@ -156,11 +177,11 @@ func (m *Manager) setLocked(cfg Config) error {
|
||||
return err
|
||||
}
|
||||
if err := m.os.SetDNS(ocfg); err != nil {
|
||||
m.health.SetDNSOSHealth(err)
|
||||
m.health.SetUnhealthy(osConfigurationSetWarnable, health.Args{health.ArgError: err.Error()})
|
||||
return err
|
||||
}
|
||||
|
||||
m.health.SetDNSOSHealth(nil)
|
||||
m.health.SetHealthy(osConfigurationSetWarnable)
|
||||
m.config = &cfg
|
||||
|
||||
return nil
|
||||
@@ -203,7 +224,7 @@ func compileHostEntries(cfg Config) (hosts []*HostEntry) {
|
||||
if len(hostsMap) == 0 {
|
||||
return nil
|
||||
}
|
||||
hosts = xmaps.Values(hostsMap)
|
||||
hosts = slicesx.MapValues(hostsMap)
|
||||
slices.SortFunc(hosts, func(a, b *HostEntry) int {
|
||||
if len(a.Hosts) == 0 && len(b.Hosts) == 0 {
|
||||
return 0
|
||||
@@ -217,6 +238,26 @@ func compileHostEntries(cfg Config) (hosts []*HostEntry) {
|
||||
return hosts
|
||||
}
|
||||
|
||||
var osConfigurationReadWarnable = health.Register(&health.Warnable{
|
||||
Code: "dns-read-os-config-failed",
|
||||
Title: "Failed to read system DNS configuration",
|
||||
Text: func(args health.Args) string {
|
||||
return fmt.Sprintf("Tailscale failed to fetch the DNS configuration of your device: %v", args[health.ArgError])
|
||||
},
|
||||
Severity: health.SeverityLow,
|
||||
DependsOn: []*health.Warnable{health.NetworkStatusWarnable},
|
||||
})
|
||||
|
||||
var osConfigurationSetWarnable = health.Register(&health.Warnable{
|
||||
Code: "dns-set-os-config-failed",
|
||||
Title: "Failed to set system DNS configuration",
|
||||
Text: func(args health.Args) string {
|
||||
return fmt.Sprintf("Tailscale failed to set the DNS configuration of your device: %v", args[health.ArgError])
|
||||
},
|
||||
Severity: health.SeverityMedium,
|
||||
DependsOn: []*health.Warnable{health.NetworkStatusWarnable},
|
||||
})
|
||||
|
||||
// compileConfig converts cfg into a quad-100 resolver configuration
|
||||
// and an OS-level configuration.
|
||||
func (m *Manager) compileConfig(cfg Config) (rcfg resolver.Config, ocfg OSConfig, err error) {
|
||||
@@ -225,8 +266,10 @@ func (m *Manager) compileConfig(cfg Config) (rcfg resolver.Config, ocfg OSConfig
|
||||
// the OS.
|
||||
rcfg.Hosts = cfg.Hosts
|
||||
routes := map[dnsname.FQDN][]*dnstype.Resolver{} // assigned conditionally to rcfg.Routes below.
|
||||
var propagateHostsToOS bool
|
||||
for suffix, resolvers := range cfg.Routes {
|
||||
if len(resolvers) == 0 {
|
||||
propagateHostsToOS = true
|
||||
rcfg.LocalDomains = append(rcfg.LocalDomains, suffix)
|
||||
} else {
|
||||
routes[suffix] = resolvers
|
||||
@@ -235,7 +278,7 @@ func (m *Manager) compileConfig(cfg Config) (rcfg resolver.Config, ocfg OSConfig
|
||||
|
||||
// Similarly, the OS always gets search paths.
|
||||
ocfg.SearchDomains = cfg.SearchDomains
|
||||
if m.goos == "windows" {
|
||||
if propagateHostsToOS && m.goos == "windows" {
|
||||
ocfg.Hosts = compileHostEntries(cfg)
|
||||
}
|
||||
|
||||
@@ -320,9 +363,10 @@ func (m *Manager) compileConfig(cfg Config) (rcfg resolver.Config, ocfg OSConfig
|
||||
// This is currently (2022-10-13) expected on certain iOS and macOS
|
||||
// builds.
|
||||
} else {
|
||||
m.health.SetDNSOSHealth(err)
|
||||
m.health.SetUnhealthy(osConfigurationReadWarnable, health.Args{health.ArgError: err.Error()})
|
||||
return resolver.Config{}, OSConfig{}, err
|
||||
}
|
||||
m.health.SetHealthy(osConfigurationReadWarnable)
|
||||
}
|
||||
|
||||
if baseCfg == nil {
|
||||
|
||||
2
vendor/tailscale.com/net/dns/manager_default.go
generated
vendored
2
vendor/tailscale.com/net/dns/manager_default.go
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build !linux && !freebsd && !openbsd && !windows && !darwin
|
||||
//go:build !linux && !freebsd && !openbsd && !windows && !darwin && !illumos && !solaris
|
||||
|
||||
package dns
|
||||
|
||||
|
||||
14
vendor/tailscale.com/net/dns/manager_solaris.go
generated
vendored
Normal file
14
vendor/tailscale.com/net/dns/manager_solaris.go
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package dns
|
||||
|
||||
import (
|
||||
"tailscale.com/control/controlknobs"
|
||||
"tailscale.com/health"
|
||||
"tailscale.com/types/logger"
|
||||
)
|
||||
|
||||
func NewOSConfigurator(logf logger.Logf, health *health.Tracker, _ *controlknobs.Knobs, iface string) (OSConfigurator, error) {
|
||||
return newDirectManager(logf, health), nil
|
||||
}
|
||||
74
vendor/tailscale.com/net/dns/manager_windows.go
generated
vendored
74
vendor/tailscale.com/net/dns/manager_windows.go
generated
vendored
@@ -8,10 +8,12 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"maps"
|
||||
"net/netip"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -140,9 +142,8 @@ func (m *windowsManager) setSplitDNS(resolvers []netip.Addr, domains []dnsname.F
|
||||
return m.nrptDB.WriteSplitDNSConfig(servers, domains)
|
||||
}
|
||||
|
||||
func setTailscaleHosts(prevHostsFile []byte, hosts []*HostEntry) ([]byte, error) {
|
||||
b := bytes.ReplaceAll(prevHostsFile, []byte("\r\n"), []byte("\n"))
|
||||
sc := bufio.NewScanner(bytes.NewReader(b))
|
||||
func setTailscaleHosts(logf logger.Logf, prevHostsFile []byte, hosts []*HostEntry) ([]byte, error) {
|
||||
sc := bufio.NewScanner(bytes.NewReader(prevHostsFile))
|
||||
const (
|
||||
header = "# TailscaleHostsSectionStart"
|
||||
footer = "# TailscaleHostsSectionEnd"
|
||||
@@ -151,6 +152,32 @@ func setTailscaleHosts(prevHostsFile []byte, hosts []*HostEntry) ([]byte, error)
|
||||
"# This section contains MagicDNS entries for Tailscale.",
|
||||
"# Do not edit this section manually.",
|
||||
}
|
||||
|
||||
prevEntries := make(map[netip.Addr][]string)
|
||||
addPrevEntry := func(line string) {
|
||||
if line == "" || line[0] == '#' {
|
||||
return
|
||||
}
|
||||
|
||||
parts := strings.Split(line, " ")
|
||||
if len(parts) < 1 {
|
||||
return
|
||||
}
|
||||
|
||||
addr, err := netip.ParseAddr(parts[0])
|
||||
if err != nil {
|
||||
logf("Parsing address from hosts: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
prevEntries[addr] = parts[1:]
|
||||
}
|
||||
|
||||
nextEntries := make(map[netip.Addr][]string, len(hosts))
|
||||
for _, he := range hosts {
|
||||
nextEntries[he.Addr] = he.Hosts
|
||||
}
|
||||
|
||||
var out bytes.Buffer
|
||||
var inSection bool
|
||||
for sc.Scan() {
|
||||
@@ -164,26 +191,34 @@ func setTailscaleHosts(prevHostsFile []byte, hosts []*HostEntry) ([]byte, error)
|
||||
continue
|
||||
}
|
||||
if inSection {
|
||||
addPrevEntry(line)
|
||||
continue
|
||||
}
|
||||
fmt.Fprintln(&out, line)
|
||||
fmt.Fprintf(&out, "%s\r\n", line)
|
||||
}
|
||||
if err := sc.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(hosts) > 0 {
|
||||
fmt.Fprintln(&out, header)
|
||||
for _, c := range comments {
|
||||
fmt.Fprintln(&out, c)
|
||||
}
|
||||
fmt.Fprintln(&out)
|
||||
for _, he := range hosts {
|
||||
fmt.Fprintf(&out, "%s %s\n", he.Addr, strings.Join(he.Hosts, " "))
|
||||
}
|
||||
fmt.Fprintln(&out)
|
||||
fmt.Fprintln(&out, footer)
|
||||
|
||||
unchanged := maps.EqualFunc(prevEntries, nextEntries, func(a, b []string) bool {
|
||||
return slices.Equal(a, b)
|
||||
})
|
||||
if unchanged {
|
||||
return nil, nil
|
||||
}
|
||||
return bytes.ReplaceAll(out.Bytes(), []byte("\n"), []byte("\r\n")), nil
|
||||
|
||||
if len(hosts) > 0 {
|
||||
fmt.Fprintf(&out, "%s\r\n", header)
|
||||
for _, c := range comments {
|
||||
fmt.Fprintf(&out, "%s\r\n", c)
|
||||
}
|
||||
fmt.Fprintf(&out, "\r\n")
|
||||
for _, he := range hosts {
|
||||
fmt.Fprintf(&out, "%s %s\r\n", he.Addr, strings.Join(he.Hosts, " "))
|
||||
}
|
||||
fmt.Fprintf(&out, "\r\n%s\r\n", footer)
|
||||
}
|
||||
return out.Bytes(), nil
|
||||
}
|
||||
|
||||
// setHosts sets the hosts file to contain the given host entries.
|
||||
@@ -197,10 +232,15 @@ func (m *windowsManager) setHosts(hosts []*HostEntry) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
outB, err := setTailscaleHosts(b, hosts)
|
||||
outB, err := setTailscaleHosts(m.logf, b, hosts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if outB == nil {
|
||||
// No change to hosts file, therefore no write necessary.
|
||||
return nil
|
||||
}
|
||||
|
||||
const fileMode = 0 // ignored on windows.
|
||||
|
||||
// This can fail spuriously with an access denied error, so retry it a
|
||||
|
||||
4
vendor/tailscale.com/net/dns/nm.go
generated
vendored
4
vendor/tailscale.com/net/dns/nm.go
generated
vendored
@@ -7,6 +7,7 @@ package dns
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
@@ -14,7 +15,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/godbus/dbus/v5"
|
||||
"github.com/josharian/native"
|
||||
"tailscale.com/net/tsaddr"
|
||||
"tailscale.com/util/dnsname"
|
||||
)
|
||||
@@ -137,7 +137,7 @@ func (m *nmManager) trySet(ctx context.Context, config OSConfig) error {
|
||||
for _, ip := range config.Nameservers {
|
||||
b := ip.As16()
|
||||
if ip.Is4() {
|
||||
dnsv4 = append(dnsv4, native.Endian.Uint32(b[12:]))
|
||||
dnsv4 = append(dnsv4, binary.NativeEndian.Uint32(b[12:]))
|
||||
} else {
|
||||
dnsv6 = append(dnsv6, b[:])
|
||||
}
|
||||
|
||||
3
vendor/tailscale.com/net/dns/resolvd.go
generated
vendored
3
vendor/tailscale.com/net/dns/resolvd.go
generated
vendored
@@ -57,6 +57,7 @@ func (m *resolvdManager) SetDNS(config OSConfig) error {
|
||||
|
||||
if len(newSearch) > 1 {
|
||||
newResolvConf = append(newResolvConf, []byte(strings.Join(newSearch, " "))...)
|
||||
newResolvConf = append(newResolvConf, '\n')
|
||||
}
|
||||
|
||||
err = m.fs.WriteFile(resolvConf, newResolvConf, 0644)
|
||||
@@ -123,6 +124,6 @@ func (m resolvdManager) readResolvConf() (config OSConfig, err error) {
|
||||
}
|
||||
|
||||
func removeSearchLines(orig []byte) []byte {
|
||||
re := regexp.MustCompile(`(?m)^search\s+.+$`)
|
||||
re := regexp.MustCompile(`(?ms)^search\s+.+$`)
|
||||
return re.ReplaceAll(orig, []byte(""))
|
||||
}
|
||||
|
||||
9
vendor/tailscale.com/net/dns/resolved.go
generated
vendored
9
vendor/tailscale.com/net/dns/resolved.go
generated
vendored
@@ -163,9 +163,9 @@ func (m *resolvedManager) run(ctx context.Context) {
|
||||
}
|
||||
conn.Signal(signals)
|
||||
|
||||
// Reset backoff and SetNSOSHealth after successful on reconnect.
|
||||
// Reset backoff and set osConfigurationSetWarnable to healthy after a successful reconnect.
|
||||
bo.BackOff(ctx, nil)
|
||||
m.health.SetDNSOSHealth(nil)
|
||||
m.health.SetHealthy(osConfigurationSetWarnable)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -243,9 +243,12 @@ func (m *resolvedManager) run(ctx context.Context) {
|
||||
// Set health while holding the lock, because this will
|
||||
// graciously serialize the resync's health outcome with a
|
||||
// concurrent SetDNS call.
|
||||
m.health.SetDNSOSHealth(err)
|
||||
|
||||
if err != nil {
|
||||
m.logf("failed to configure systemd-resolved: %v", err)
|
||||
m.health.SetUnhealthy(osConfigurationSetWarnable, health.Args{health.ArgError: err.Error()})
|
||||
} else {
|
||||
m.health.SetHealthy(osConfigurationSetWarnable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
2
vendor/tailscale.com/net/dns/resolver/tsdns.go
generated
vendored
2
vendor/tailscale.com/net/dns/resolver/tsdns.go
generated
vendored
@@ -384,7 +384,7 @@ func (r *Resolver) HandlePeerDNSQuery(ctx context.Context, q []byte, from netip.
|
||||
// but for now that's probably good enough. Later we'll
|
||||
// want to blend in everything from scutil --dns.
|
||||
fallthrough
|
||||
case "linux", "freebsd", "openbsd", "illumos", "ios":
|
||||
case "linux", "freebsd", "openbsd", "illumos", "solaris", "ios":
|
||||
nameserver, err := stubResolverForOS()
|
||||
if err != nil {
|
||||
r.logf("stubResolverForOS: %v", err)
|
||||
|
||||
Reference in New Issue
Block a user