tailcfg: add DNS address list for IsWireGuardOnly nodes

Tailscale exit nodes provide DNS service over the peer API, however
IsWireGuardOnly nodes do not have a peer API, and instead need client
DNS parameters passed in their node description.

For Mullvad nodes this will contain the in network 10.64.0.1 address.

Updates #9377

Signed-off-by: James Tucker <james@tailscale.com>
This commit is contained in:
James Tucker
2023-09-14 10:04:31 -07:00
committed by James Tucker
parent 335a5aaf9a
commit e7727db553
9 changed files with 160 additions and 2 deletions

View File

@@ -8,6 +8,7 @@ package dnstype
import (
"net/netip"
"slices"
)
// Resolver is the configuration for one DNS resolver.
@@ -51,3 +52,15 @@ func (r *Resolver) IPPort() (ipp netip.AddrPort, ok bool) {
}
return
}
// Equal reports whether r and other are equal.
func (r *Resolver) Equal(other *Resolver) bool {
if r == nil || other == nil {
return r == other
}
if r == other {
return true
}
return r.Addr == other.Addr && slices.Equal(r.BootstrapResolution, other.BootstrapResolution)
}

View File

@@ -0,0 +1,81 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
package dnstype
import (
"net/netip"
"reflect"
"slices"
"sort"
"testing"
)
func TestResolverEqual(t *testing.T) {
var fieldNames []string
for _, field := range reflect.VisibleFields(reflect.TypeOf(Resolver{})) {
fieldNames = append(fieldNames, field.Name)
}
sort.Strings(fieldNames)
if !slices.Equal(fieldNames, []string{"Addr", "BootstrapResolution"}) {
t.Errorf("Resolver fields changed; update test")
}
tests := []struct {
name string
a, b *Resolver
want bool
}{
{
name: "nil",
a: nil,
b: nil,
want: true,
},
{
name: "nil vs non-nil",
a: nil,
b: &Resolver{},
want: false,
},
{
name: "non-nil vs nil",
a: &Resolver{},
b: nil,
want: false,
},
{
name: "equal",
a: &Resolver{Addr: "dns.example.com"},
b: &Resolver{Addr: "dns.example.com"},
want: true,
},
{
name: "not equal addrs",
a: &Resolver{Addr: "dns.example.com"},
b: &Resolver{Addr: "dns2.example.com"},
want: false,
},
{
name: "not equal bootstrap",
a: &Resolver{
Addr: "dns.example.com",
BootstrapResolution: []netip.Addr{netip.MustParseAddr("8.8.8.8")},
},
b: &Resolver{
Addr: "dns.example.com",
BootstrapResolution: []netip.Addr{netip.MustParseAddr("8.8.4.4")},
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := tt.a.Equal(tt.b)
if got != tt.want {
t.Errorf("got %v; want %v", got, tt.want)
}
})
}
}

View File

@@ -64,6 +64,7 @@ func (v ResolverView) Addr() string { return v.ж.Addr }
func (v ResolverView) BootstrapResolution() views.Slice[netip.Addr] {
return views.SliceOf(v.ж.BootstrapResolution)
}
func (v ResolverView) Equal(v2 ResolverView) bool { return v.ж.Equal(v2.ж) }
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _ResolverViewNeedsRegeneration = Resolver(struct {