mirror of
https://github.com/tailscale/tailscale.git
synced 2025-12-23 00:56:20 +00:00
This adds a new node capability 'dns-subdomain-resolve' that signals that all of hosts' subdomains should resolve to the same IP address. It allows wildcard matching on any node marked with this capability. This change also includes an util/dnsname utility function that lets us access the parent of a full qualified domain name. MagicDNS takes this function and recursively searchs for a matching real node name. One important thing to observe is that, in this context, a subdomain can have multiple sub labels. This means that for a given node named machine, both my.machine and be.my.machine will be a positive match. Updates #1196 Signed-off-by: Fernando Serboncini <fserb@tailscale.com>
148 lines
4.8 KiB
Go
148 lines
4.8 KiB
Go
// Copyright (c) Tailscale Inc & AUTHORS
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
// Code generated by tailscale/cmd/viewer; DO NOT EDIT.
|
|
|
|
package dns
|
|
|
|
import (
|
|
jsonv1 "encoding/json"
|
|
"errors"
|
|
"net/netip"
|
|
|
|
jsonv2 "github.com/go-json-experiment/json"
|
|
"github.com/go-json-experiment/json/jsontext"
|
|
"tailscale.com/types/dnstype"
|
|
"tailscale.com/types/views"
|
|
"tailscale.com/util/dnsname"
|
|
)
|
|
|
|
//go:generate go run tailscale.com/cmd/cloner -clonefunc=true -type=Config
|
|
|
|
// View returns a read-only view of Config.
|
|
func (p *Config) View() ConfigView {
|
|
return ConfigView{ж: p}
|
|
}
|
|
|
|
// ConfigView provides a read-only view over Config.
|
|
//
|
|
// Its methods should only be called if `Valid()` returns true.
|
|
type ConfigView struct {
|
|
// ж is the underlying mutable value, named with a hard-to-type
|
|
// character that looks pointy like a pointer.
|
|
// It is named distinctively to make you think of how dangerous it is to escape
|
|
// to callers. You must not let callers be able to mutate it.
|
|
ж *Config
|
|
}
|
|
|
|
// Valid reports whether v's underlying value is non-nil.
|
|
func (v ConfigView) Valid() bool { return v.ж != nil }
|
|
|
|
// AsStruct returns a clone of the underlying value which aliases no memory with
|
|
// the original.
|
|
func (v ConfigView) AsStruct() *Config {
|
|
if v.ж == nil {
|
|
return nil
|
|
}
|
|
return v.ж.Clone()
|
|
}
|
|
|
|
// MarshalJSON implements [jsonv1.Marshaler].
|
|
func (v ConfigView) MarshalJSON() ([]byte, error) {
|
|
return jsonv1.Marshal(v.ж)
|
|
}
|
|
|
|
// MarshalJSONTo implements [jsonv2.MarshalerTo].
|
|
func (v ConfigView) MarshalJSONTo(enc *jsontext.Encoder) error {
|
|
return jsonv2.MarshalEncode(enc, v.ж)
|
|
}
|
|
|
|
// UnmarshalJSON implements [jsonv1.Unmarshaler].
|
|
func (v *ConfigView) UnmarshalJSON(b []byte) error {
|
|
if v.ж != nil {
|
|
return errors.New("already initialized")
|
|
}
|
|
if len(b) == 0 {
|
|
return nil
|
|
}
|
|
var x Config
|
|
if err := jsonv1.Unmarshal(b, &x); err != nil {
|
|
return err
|
|
}
|
|
v.ж = &x
|
|
return nil
|
|
}
|
|
|
|
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
|
|
func (v *ConfigView) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
|
|
if v.ж != nil {
|
|
return errors.New("already initialized")
|
|
}
|
|
var x Config
|
|
if err := jsonv2.UnmarshalDecode(dec, &x); err != nil {
|
|
return err
|
|
}
|
|
v.ж = &x
|
|
return nil
|
|
}
|
|
|
|
// DefaultResolvers are the DNS resolvers to use for DNS names
|
|
// which aren't covered by more specific per-domain routes below.
|
|
// If empty, the OS's default resolvers (the ones that predate
|
|
// Tailscale altering the configuration) are used.
|
|
func (v ConfigView) DefaultResolvers() views.SliceView[*dnstype.Resolver, dnstype.ResolverView] {
|
|
return views.SliceOfViews[*dnstype.Resolver, dnstype.ResolverView](v.ж.DefaultResolvers)
|
|
}
|
|
|
|
// Routes maps a DNS suffix to the resolvers that should be used
|
|
// for queries that fall within that suffix.
|
|
// If a query doesn't match any entry in Routes, the
|
|
// DefaultResolvers are used.
|
|
// A Routes entry with no resolvers means the route should be
|
|
// authoritatively answered using the contents of Hosts.
|
|
func (v ConfigView) Routes() views.MapFn[dnsname.FQDN, []*dnstype.Resolver, views.SliceView[*dnstype.Resolver, dnstype.ResolverView]] {
|
|
return views.MapFnOf(v.ж.Routes, func(t []*dnstype.Resolver) views.SliceView[*dnstype.Resolver, dnstype.ResolverView] {
|
|
return views.SliceOfViews[*dnstype.Resolver, dnstype.ResolverView](t)
|
|
})
|
|
}
|
|
|
|
// SearchDomains are DNS suffixes to try when expanding
|
|
// single-label queries.
|
|
func (v ConfigView) SearchDomains() views.Slice[dnsname.FQDN] {
|
|
return views.SliceOf(v.ж.SearchDomains)
|
|
}
|
|
|
|
// Hosts maps DNS FQDNs to their IPs, which can be a mix of IPv4
|
|
// and IPv6.
|
|
// Queries matching entries in Hosts are resolved locally by
|
|
// 100.100.100.100 without leaving the machine.
|
|
// Adding an entry to Hosts merely creates the record. If you want
|
|
// it to resolve, you also need to add appropriate routes to
|
|
// Routes.
|
|
func (v ConfigView) Hosts() views.MapSlice[dnsname.FQDN, netip.Addr] {
|
|
return views.MapSliceOf(v.ж.Hosts)
|
|
}
|
|
|
|
// SubdomainHosts is a set of FQDNs from Hosts that should also
|
|
// resolve subdomain queries to the same IPs. For example, if
|
|
// "node.tailnet.ts.net" is in SubdomainHosts, then queries for
|
|
// "anything.node.tailnet.ts.net" will resolve to node's IPs.
|
|
func (v ConfigView) SubdomainHosts() views.Map[dnsname.FQDN, bool] {
|
|
return views.MapOf(v.ж.SubdomainHosts)
|
|
}
|
|
|
|
// OnlyIPv6, if true, uses the IPv6 service IP (for MagicDNS)
|
|
// instead of the IPv4 version (100.100.100.100).
|
|
func (v ConfigView) OnlyIPv6() bool { return v.ж.OnlyIPv6 }
|
|
func (v ConfigView) Equal(v2 ConfigView) 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 _ConfigViewNeedsRegeneration = Config(struct {
|
|
DefaultResolvers []*dnstype.Resolver
|
|
Routes map[dnsname.FQDN][]*dnstype.Resolver
|
|
SearchDomains []dnsname.FQDN
|
|
Hosts map[dnsname.FQDN][]netip.Addr
|
|
SubdomainHosts map[dnsname.FQDN]bool
|
|
OnlyIPv6 bool
|
|
}{})
|