diff --git a/cmd/tailscale/depaware.txt b/cmd/tailscale/depaware.txt index 76722d2fd..5d1a82974 100644 --- a/cmd/tailscale/depaware.txt +++ b/cmd/tailscale/depaware.txt @@ -51,6 +51,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep W tailscale.com/tsconst from tailscale.com/net/interfaces 💣 tailscale.com/tstime/mono from tailscale.com/tstime/rate tailscale.com/tstime/rate from tailscale.com/wgengine/filter + tailscale.com/types/dnstype from tailscale.com/tailcfg tailscale.com/types/empty from tailscale.com/ipn tailscale.com/types/ipproto from tailscale.com/net/flowtrack+ tailscale.com/types/key from tailscale.com/derp+ diff --git a/cmd/tailscaled/depaware.txt b/cmd/tailscaled/depaware.txt index 53f1815c7..41dde5cca 100644 --- a/cmd/tailscaled/depaware.txt +++ b/cmd/tailscaled/depaware.txt @@ -139,6 +139,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/tstime from tailscale.com/wgengine/magicsock 💣 tailscale.com/tstime/mono from tailscale.com/net/tstun+ tailscale.com/tstime/rate from tailscale.com/wgengine/filter + tailscale.com/types/dnstype from tailscale.com/ipn/ipnlocal+ tailscale.com/types/empty from tailscale.com/control/controlclient+ tailscale.com/types/flagtype from tailscale.com/cmd/tailscaled tailscale.com/types/ipproto from tailscale.com/net/flowtrack+ diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index f83b38a53..44b045514 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -38,6 +38,7 @@ import ( "tailscale.com/paths" "tailscale.com/portlist" "tailscale.com/tailcfg" + "tailscale.com/types/dnstype" "tailscale.com/types/empty" "tailscale.com/types/key" "tailscale.com/types/logger" @@ -1820,7 +1821,7 @@ func (b *LocalBackend) authReconfig() { } if uc.CorpDNS { - addDefault := func(resolvers []tailcfg.DNSResolver) { + addDefault := func(resolvers []dnstype.Resolver) { for _, resolver := range resolvers { res, err := parseResolver(resolver) if err != nil { @@ -1896,7 +1897,7 @@ func (b *LocalBackend) authReconfig() { b.initPeerAPIListener() } -func parseResolver(cfg tailcfg.DNSResolver) (netaddr.IPPort, error) { +func parseResolver(cfg dnstype.Resolver) (netaddr.IPPort, error) { ip, err := netaddr.ParseIP(cfg.Addr) if err != nil { return netaddr.IPPort{}, fmt.Errorf("[unexpected] non-IP resolver %q", cfg.Addr) diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index 93a47867f..0c381218e 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -4,7 +4,7 @@ package tailcfg -//go:generate go run tailscale.com/cmd/cloner --type=User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode --clonefunc=true --output=tailcfg_clone.go +//go:generate go run tailscale.com/cmd/cloner --type=User,Node,Hostinfo,NetInfo,Login,DNSConfig,RegisterResponse,DERPRegion,DERPMap,DERPNode --clonefunc=true --output=tailcfg_clone.go import ( "encoding/hex" @@ -16,6 +16,7 @@ import ( "go4.org/mem" "inet.af/netaddr" + "tailscale.com/types/dnstype" "tailscale.com/types/key" "tailscale.com/types/opt" "tailscale.com/types/structs" @@ -832,38 +833,21 @@ var FilterAllowAll = []FilterRule{ }, } -// DNSResolver is the configuration for one DNS resolver. -type DNSResolver struct { - // Addr is the address of the DNS resolver, one of: - // - A plain IP address for a "classic" UDP+TCP DNS resolver - // - [TODO] "tls://resolver.com" for DNS over TCP+TLS - // - [TODO] "https://resolver.com/query-tmpl" for DNS over HTTPS - Addr string `json:",omitempty"` - - // BootstrapResolution is an optional suggested resolution for the - // DoT/DoH resolver, if the resolver URL does not reference an IP - // address directly. - // BootstrapResolution may be empty, in which case clients should - // look up the DoT/DoH server using their local "classic" DNS - // resolver. - BootstrapResolution []netaddr.IP `json:",omitempty"` -} - // DNSConfig is the DNS configuration. type DNSConfig struct { // Resolvers are the DNS resolvers to use, in order of preference. - Resolvers []DNSResolver `json:",omitempty"` + Resolvers []dnstype.Resolver `json:",omitempty"` // Routes maps DNS name suffixes to a set of DNS resolvers to // use. It is used to implement "split DNS" and other advanced DNS // routing overlays. // Map keys must be fully-qualified DNS name suffixes, with a // trailing dot but no leading dot. - Routes map[string][]DNSResolver `json:",omitempty"` + Routes map[string][]dnstype.Resolver `json:",omitempty"` // FallbackResolvers is like Resolvers, but is only used if a // split DNS configuration is requested in a configuration that // doesn't work yet without explicit default resolvers. // https://github.com/tailscale/tailscale/issues/1743 - FallbackResolvers []DNSResolver `json:",omitempty"` + FallbackResolvers []dnstype.Resolver `json:",omitempty"` // Domains are the search domains to use. // Search domains must be FQDNs, but *without* the trailing dot. Domains []string `json:",omitempty"` diff --git a/tailcfg/tailcfg_clone.go b/tailcfg/tailcfg_clone.go index 0b67df91c..16e5f1a64 100644 --- a/tailcfg/tailcfg_clone.go +++ b/tailcfg/tailcfg_clone.go @@ -2,12 +2,13 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode; DO NOT EDIT. +// Code generated by tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,RegisterResponse,DERPRegion,DERPMap,DERPNode; DO NOT EDIT. package tailcfg import ( "inet.af/netaddr" + "tailscale.com/types/dnstype" "tailscale.com/types/opt" "tailscale.com/types/structs" "time" @@ -26,7 +27,7 @@ func (src *User) Clone() *User { } // A compilation failure here means this code must be regenerated, with command: -// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode +// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,RegisterResponse,DERPRegion,DERPMap,DERPNode var _UserNeedsRegeneration = User(struct { ID UserID LoginName string @@ -63,7 +64,7 @@ func (src *Node) Clone() *Node { } // A compilation failure here means this code must be regenerated, with command: -// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode +// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,RegisterResponse,DERPRegion,DERPMap,DERPNode var _NodeNeedsRegeneration = Node(struct { ID NodeID StableID StableNodeID @@ -107,7 +108,7 @@ func (src *Hostinfo) Clone() *Hostinfo { } // A compilation failure here means this code must be regenerated, with command: -// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode +// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,RegisterResponse,DERPRegion,DERPMap,DERPNode var _HostinfoNeedsRegeneration = Hostinfo(struct { IPNVersion string FrontendLogID string @@ -144,7 +145,7 @@ func (src *NetInfo) Clone() *NetInfo { } // A compilation failure here means this code must be regenerated, with command: -// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode +// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,RegisterResponse,DERPRegion,DERPMap,DERPNode var _NetInfoNeedsRegeneration = NetInfo(struct { MappingVariesByDestIP opt.Bool HairPinning opt.Bool @@ -171,7 +172,7 @@ func (src *Login) Clone() *Login { } // A compilation failure here means this code must be regenerated, with command: -// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode +// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,RegisterResponse,DERPRegion,DERPMap,DERPNode var _LoginNeedsRegeneration = Login(struct { _ structs.Incomparable ID LoginID @@ -190,17 +191,17 @@ func (src *DNSConfig) Clone() *DNSConfig { } dst := new(DNSConfig) *dst = *src - dst.Resolvers = make([]DNSResolver, len(src.Resolvers)) + dst.Resolvers = make([]dnstype.Resolver, len(src.Resolvers)) for i := range dst.Resolvers { dst.Resolvers[i] = *src.Resolvers[i].Clone() } if dst.Routes != nil { - dst.Routes = map[string][]DNSResolver{} + dst.Routes = map[string][]dnstype.Resolver{} for k := range src.Routes { - dst.Routes[k] = append([]DNSResolver{}, src.Routes[k]...) + dst.Routes[k] = append([]dnstype.Resolver{}, src.Routes[k]...) } } - dst.FallbackResolvers = make([]DNSResolver, len(src.FallbackResolvers)) + dst.FallbackResolvers = make([]dnstype.Resolver, len(src.FallbackResolvers)) for i := range dst.FallbackResolvers { dst.FallbackResolvers[i] = *src.FallbackResolvers[i].Clone() } @@ -212,11 +213,11 @@ func (src *DNSConfig) Clone() *DNSConfig { } // A compilation failure here means this code must be regenerated, with command: -// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode +// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,RegisterResponse,DERPRegion,DERPMap,DERPNode var _DNSConfigNeedsRegeneration = DNSConfig(struct { - Resolvers []DNSResolver - Routes map[string][]DNSResolver - FallbackResolvers []DNSResolver + Resolvers []dnstype.Resolver + Routes map[string][]dnstype.Resolver + FallbackResolvers []dnstype.Resolver Domains []string Proxied bool Nameservers []netaddr.IP @@ -225,25 +226,6 @@ var _DNSConfigNeedsRegeneration = DNSConfig(struct { ExtraRecords []DNSRecord }{}) -// Clone makes a deep copy of DNSResolver. -// The result aliases no memory with the original. -func (src *DNSResolver) Clone() *DNSResolver { - if src == nil { - return nil - } - dst := new(DNSResolver) - *dst = *src - dst.BootstrapResolution = append(src.BootstrapResolution[:0:0], src.BootstrapResolution...) - return dst -} - -// A compilation failure here means this code must be regenerated, with command: -// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode -var _DNSResolverNeedsRegeneration = DNSResolver(struct { - Addr string - BootstrapResolution []netaddr.IP -}{}) - // Clone makes a deep copy of RegisterResponse. // The result aliases no memory with the original. func (src *RegisterResponse) Clone() *RegisterResponse { @@ -257,7 +239,7 @@ func (src *RegisterResponse) Clone() *RegisterResponse { } // A compilation failure here means this code must be regenerated, with command: -// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode +// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,RegisterResponse,DERPRegion,DERPMap,DERPNode var _RegisterResponseNeedsRegeneration = RegisterResponse(struct { User User Login Login @@ -282,7 +264,7 @@ func (src *DERPRegion) Clone() *DERPRegion { } // A compilation failure here means this code must be regenerated, with command: -// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode +// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,RegisterResponse,DERPRegion,DERPMap,DERPNode var _DERPRegionNeedsRegeneration = DERPRegion(struct { RegionID int RegionCode string @@ -309,7 +291,7 @@ func (src *DERPMap) Clone() *DERPMap { } // A compilation failure here means this code must be regenerated, with command: -// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode +// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,RegisterResponse,DERPRegion,DERPMap,DERPNode var _DERPMapNeedsRegeneration = DERPMap(struct { Regions map[int]*DERPRegion OmitDefaultRegions bool @@ -327,7 +309,7 @@ func (src *DERPNode) Clone() *DERPNode { } // A compilation failure here means this code must be regenerated, with command: -// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode +// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,RegisterResponse,DERPRegion,DERPMap,DERPNode var _DERPNodeNeedsRegeneration = DERPNode(struct { Name string RegionID int @@ -344,7 +326,7 @@ var _DERPNodeNeedsRegeneration = DERPNode(struct { // Clone duplicates src into dst and reports whether it succeeded. // To succeed, must be of types <*T, *T> or <*T, **T>, -// where T is one of User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode. +// where T is one of User,Node,Hostinfo,NetInfo,Login,DNSConfig,RegisterResponse,DERPRegion,DERPMap,DERPNode. func Clone(dst, src interface{}) bool { switch src := src.(type) { case *User: @@ -401,15 +383,6 @@ func Clone(dst, src interface{}) bool { *dst = src.Clone() return true } - case *DNSResolver: - switch dst := dst.(type) { - case *DNSResolver: - *dst = *src.Clone() - return true - case **DNSResolver: - *dst = src.Clone() - return true - } case *RegisterResponse: switch dst := dst.(type) { case *RegisterResponse: diff --git a/types/dnstype/dnstype.go b/types/dnstype/dnstype.go new file mode 100644 index 000000000..367491afd --- /dev/null +++ b/types/dnstype/dnstype.go @@ -0,0 +1,27 @@ +// 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 dnstype defines types for working with DNS. +package dnstype + +//go:generate go run tailscale.com/cmd/cloner --type=Resolver --clonefunc=true --output=dnstype_clone.go + +import "inet.af/netaddr" + +// Resolver is the configuration for one DNS resolver. +type Resolver struct { + // Addr is the address of the DNS resolver, one of: + // - A plain IP address for a "classic" UDP+TCP DNS resolver + // - [TODO] "tls://resolver.com" for DNS over TCP+TLS + // - [TODO] "https://resolver.com/query-tmpl" for DNS over HTTPS + Addr string `json:",omitempty"` + + // BootstrapResolution is an optional suggested resolution for the + // DoT/DoH resolver, if the resolver URL does not reference an IP + // address directly. + // BootstrapResolution may be empty, in which case clients should + // look up the DoT/DoH server using their local "classic" DNS + // resolver. + BootstrapResolution []netaddr.IP `json:",omitempty"` +} diff --git a/types/dnstype/dnstype_clone.go b/types/dnstype/dnstype_clone.go new file mode 100644 index 000000000..049d91f94 --- /dev/null +++ b/types/dnstype/dnstype_clone.go @@ -0,0 +1,48 @@ +// Copyright (c) 2020 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. + +// Code generated by tailscale.com/cmd/cloner -type Resolver; DO NOT EDIT. + +package dnstype + +import ( + "inet.af/netaddr" +) + +// Clone makes a deep copy of Resolver. +// The result aliases no memory with the original. +func (src *Resolver) Clone() *Resolver { + if src == nil { + return nil + } + dst := new(Resolver) + *dst = *src + dst.BootstrapResolution = append(src.BootstrapResolution[:0:0], src.BootstrapResolution...) + return dst +} + +// A compilation failure here means this code must be regenerated, with command: +// tailscale.com/cmd/cloner -type Resolver +var _ResolverNeedsRegeneration = Resolver(struct { + Addr string + BootstrapResolution []netaddr.IP +}{}) + +// Clone duplicates src into dst and reports whether it succeeded. +// To succeed, must be of types <*T, *T> or <*T, **T>, +// where T is one of Resolver. +func Clone(dst, src interface{}) bool { + switch src := src.(type) { + case *Resolver: + switch dst := dst.(type) { + case *Resolver: + *dst = *src.Clone() + return true + case **Resolver: + *dst = src.Clone() + return true + } + } + return false +} diff --git a/util/deephash/deephash_test.go b/util/deephash/deephash_test.go index 235b8207d..3d2efd443 100644 --- a/util/deephash/deephash_test.go +++ b/util/deephash/deephash_test.go @@ -15,6 +15,7 @@ import ( "inet.af/netaddr" "tailscale.com/tailcfg" + "tailscale.com/types/dnstype" "tailscale.com/types/ipproto" "tailscale.com/util/dnsname" "tailscale.com/version" @@ -189,7 +190,7 @@ func getVal() []interface{} { }, }, DNSConfig: &tailcfg.DNSConfig{ - Resolvers: []tailcfg.DNSResolver{ + Resolvers: []dnstype.Resolver{ {Addr: "10.0.0.1"}, }, },