summaryrefslogtreecommitdiffhomepage
path: root/net/dns/dns_view.go
blob: b10861cca882103b4c58c9b267c96c9459db71a9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Copyright (c) Tailscale Inc & contributors
// 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)
}

// 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
	OnlyIPv6         bool
}{})