This commit is contained in:
bluepython508 committed 2026-10-22 12:27:19 +01:00
1 parent 3530afb854
commit 6903fcff27
2146 files changed
+112256 -190703

No files matched your search

+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright (c) Tailscale Inc & AUTHORS
// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause
// c2n (control-to-node) API types.
+56 -10
View File
@@ -1,16 +1,21 @@
// Copyright (c) Tailscale Inc & AUTHORS
// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause
package tailcfg
import (
"fmt"
"net/netip"
"sort"
"slices"
"strconv"
"tailscale.com/types/key"
)
// DERPMap describes the set of DERP packet relay servers that are available.
//
// API maturity: this type is subject to minor changes over time, though
// its general shape is stable.
type DERPMap struct {
// HomeParams, if non-nil, is a change in home parameters.
//
@@ -22,7 +27,7 @@ type DERPMap struct {
// It's keyed by the DERPRegion.RegionID.
//
// The numbers are not necessarily contiguous.
Regions map[int]*DERPRegion
Regions map[DERPRegionID]*DERPRegion
// OmitDefaultRegions specifies to not use Tailscale's DERP servers, and only use those
// specified in this DERPMap. If there are none set outside of the defaults, this is a noop.
@@ -31,13 +36,13 @@ type DERPMap struct {
OmitDefaultRegions bool `json:"omitDefaultRegions,omitempty"`
}
// / RegionIDs returns the sorted region IDs.
func (m *DERPMap) RegionIDs() []int {
ret := make([]int, 0, len(m.Regions))
// RegionIDs returns the sorted region IDs.
func (m *DERPMap) RegionIDs() []DERPRegionID {
ret := make([]DERPRegionID, 0, len(m.Regions))
for rid := range m.Regions {
ret = append(ret, rid)
}
sort.Ints(ret)
slices.Sort(ret)
return ret
}
@@ -57,7 +62,48 @@ type DERPHomeParams struct {
//
// A nil map means no change from the previous value (if any); an empty
// non-nil map can be sent to reset all scores back to 1.0.
RegionScore map[int]float64 `json:",omitempty"`
RegionScore map[DERPRegionID]float64 `json:",omitempty"`
}
// DERPRegionID is a unique integer for a geographic region.
//
// It corresponds to the legacy derpN.tailscale.com hostnames used by older clients.
// (Older clients will continue to resolve derpN.tailscale.com when contacting peers,
// rather than use the server-provided DERPMap)
//
// It must be non-zero, positive, and guaranteed to fit in a JavaScript number.
//
// IDs in range 900-999 are reserved for end users to run their own DERP nodes.
type DERPRegionID int64
// ParseDERPRegionID parses s and returns a [DERPRegionID].
// It returns an error if s isn’t a valid region ID.
func ParseDERPRegionID(s string) (DERPRegionID, error) {
id, err := strconv.ParseInt(s, 10, 64)
if err != nil {
return 0, err
}
rid := DERPRegionID(id)
if !rid.IsValid() {
return 0, fmt.Errorf("invalid region ID: %s", s)
}
return rid, nil
}
// IsValid reports whether id is non-zero, positive, and fits in a JavaScript number.
func (id DERPRegionID) IsValid() bool {
const maxSafeJavaScriptInteger DERPRegionID = 1<<53 - 1 // Number.MAX_SAFE_INTEGER
return id > 0 && id <= maxSafeJavaScriptInteger
}
// Int64 returns the int64 representation of id.
func (id DERPRegionID) Int64() int64 {
return int64(id)
}
// String implements the [fmt.Stringer] interface.
func (id DERPRegionID) String() string {
return strconv.FormatInt(int64(id), 10)
}
// DERPRegion is a geographic region running DERP relay node(s).
@@ -81,7 +127,7 @@ type DERPRegion struct {
//
// RegionIDs in range 900-999 are reserved for end users to run their
// own DERP nodes.
RegionID int
RegionID DERPRegionID
// RegionCode is a short name for the region. It's usually a popular
// city or airport code in the region: "nyc", "sf", "sin",
@@ -147,7 +193,7 @@ type DERPNode struct {
// RegionID is the RegionID of the DERPRegion that this node
// is running in.
RegionID int
RegionID DERPRegionID
// HostName is the DERP node's hostname.
//
+450
View File
@@ -0,0 +1,450 @@
// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause
// Package nodecap defines the types of capabilities granted to tailnet nodes.
package nodecap
// Cap represents a capability granted to the self node
// as listed in [tailscale.com/tailcfg/MapResponse.Node.Capabilities].
//
// It must be a URL like "https://tailscale.com/cap/file-sharing" or "tailscale.com/cap/webui",
// or a well-known capability name like "funnel".
// The latter is only allowed for Tailscale-defined capabilities.
//
// Unlike [tailscale.com/tailcfg/peercap.Cap],
// Cap is not in context of a peer and is granted to the node itself.
//
// These are also referred to as "Node Attributes" in the ACL policy file.
type Cap string
// Prefix is a prefix for [tailscale.com/tailcfg.NodeCapMap] keys that share a common namespace,
// where each entry represents a distinct named instance (e.g. one per service).
// The full key is formed by concatenating the prefix with the instance name.
type Prefix string
// ToAttribute returns the full [Cap] key for the given value under this prefix,
// of the form prefix+value.
func (p Prefix) ToAttribute(value string) Cap {
return Cap(string(p) + value)
}
const (
FileSharing Cap = "https://tailscale.com/cap/file-sharing"
Admin Cap = "https://tailscale.com/cap/is-admin"
Owner Cap = "https://tailscale.com/cap/is-owner"
SSH Cap = "https://tailscale.com/cap/ssh" // feature enabled/available
SSHRuleIn Cap = "https://tailscale.com/cap/ssh-rule-in" // some SSH rule reach this node
DataPlaneAuditLogs Cap = "https://tailscale.com/cap/data-plane-audit-logs" // feature enabled
Debug Cap = "https://tailscale.com/cap/debug" // exposes debug endpoints over the PeerAPI
HTTPS Cap = "https"
// MacUIV2 makes the macOS GUI enable its v2 mode.
MacUIV2 Cap = "https://tailscale.com/cap/mac-ui-v2"
// ServicesInDesktopClients enables services list/menu/section in desktop clients.
// If this capability is not present, desktop clients should not show services.
ServicesInDesktopClients Cap = "https://tailscale.com/cap/services-in-desktop-clients"
// BindToInterfaceByRoute changes how Darwin nodes create
// sockets (in the net/netns package). See that package for more
// details on the behaviour of this capability.
BindToInterfaceByRoute Cap = "https://tailscale.com/cap/bind-to-interface-by-route"
// DisableAndroidBindToActiveNetwork disables binding sockets to the
// currently active network on Android, which is enabled by default.
// This allows the control plane to turn off the behavior if it causes
// problems.
DisableAndroidBindToActiveNetwork Cap = "disable-android-bind-to-active-network"
// DebugDisableAlternateDefaultRouteInterface changes how Darwin
// nodes get the default interface. There is an optional hook (used by the
// macOS and iOS clients) to override the default interface, this capability
// disables that and uses the default behavior (of parsing the routing
// table).
DebugDisableAlternateDefaultRouteInterface Cap = "https://tailscale.com/cap/debug-disable-alternate-default-route-interface"
// DebugDisableBindConnToInterface disables the automatic binding
// of connections to the default network interface on Darwin nodes.
DebugDisableBindConnToInterface Cap = "https://tailscale.com/cap/debug-disable-bind-conn-to-interface"
// DebugDisableBindConnToInterface disables the automatic binding
// of connections to the default network interface on Darwin nodes using network extensions
DebugDisableBindConnToInterfaceAppleExt Cap = "https://tailscale.com/cap/debug-disable-bind-conn-to-interface-apple-ext"
// TailnetLock indicates the node may initialize tailnet lock.
TailnetLock Cap = "https://tailscale.com/cap/tailnet-lock"
//// Funnel warning capabilities used for reporting errors to the user.
// WarnFunnelNoInvite indicates whether Funnel is enabled for the tailnet.
// This cap is no longer used 2023-08-09 onwards.
WarnFunnelNoInvite Cap = "https://tailscale.com/cap/warn-funnel-no-invite"
// WarnFunnelNoHTTPS indicates HTTPS has not been enabled for the tailnet.
// This cap is no longer used 2023-08-09 onwards.
WarnFunnelNoHTTPS Cap = "https://tailscale.com/cap/warn-funnel-no-https"
//// Debug logging capabilities
// DebugTSDNSResolution enables verbose debug logging for DNS
// resolution for Tailscale-controlled domains (the control server, log
// server, DERP servers, etc.)
DebugTSDNSResolution Cap = "https://tailscale.com/cap/debug-ts-dns-resolution"
// FunnelPorts specifies the ports that the Funnel is available on.
// The ports are specified as a comma-separated list of port numbers or port
// ranges (e.g. "80,443,8080-8090") in the ports query parameter.
// e.g. https://tailscale.com/cap/funnel-ports?ports=80,443,8080-8090
FunnelPorts Cap = "https://tailscale.com/cap/funnel-ports"
// OnlyTCP443 specifies that the client should not attempt to generate
// any outbound traffic that isn't TCP on port 443 (HTTPS). This is used for
// clients in restricted environments where only HTTPS traffic is allowed
// other types of traffic trips outbound firewall alarms. This thus implies
// all traffic is over DERP.
OnlyTCP443 Cap = "only-tcp-443"
// Funnel grants the ability for a node to host ingress traffic.
Funnel Cap = "funnel"
// SSHAggregator grants the ability for a node to collect SSH sessions.
SSHAggregator Cap = "ssh-aggregator"
// DebugForceBackgroundSTUN forces a node to always do background
// STUN queries regardless of inactivity.
DebugForceBackgroundSTUN Cap = "debug-always-stun"
// DebugDisableWGTrim disables the lazy WireGuard configuration,
// always giving WireGuard the full netmap, even for idle peers.
DebugDisableWGTrim Cap = "debug-no-wg-trim"
// DisableSubnetsIfPAC controls whether subnet routers should be
// disabled if WPAD is present on the network.
DisableSubnetsIfPAC Cap = "debug-disable-subnets-if-pac"
// DisableUPnP makes the client not perform a UPnP portmapping.
// By default, we want to enable it to see if it works on more clients.
//
// If UPnP catastrophically fails for people, this should be set kill
// new attempts at UPnP connections.
DisableUPnP Cap = "debug-disable-upnp"
// DisableDeltaUpdates makes the client not process updates via the
// delta update mechanism and should instead treat all netmap changes as
// "full" ones as tailscaled did in 1.48.x and earlier.
DisableDeltaUpdates Cap = "disable-delta-updates"
// RandomizeClientPort makes magicsock UDP bind to
// :0 to get a random local port, ignoring any configured
// fixed port.
RandomizeClientPort Cap = "randomize-client-port"
// SilentDisco makes the client suppress disco heartbeats to its
// peers.
SilentDisco Cap = "silent-disco"
// OneCGNATEnable makes the client prefer one big CGNAT /10 route
// rather than a /32 per peer. At most one of this or
// [OneCGNATDisable] may be set; if neither are, it's automatic.
OneCGNATEnable Cap = "one-cgnat?v=true"
// OneCGNATDisable makes the client prefer a /32 route per peer
// rather than one big /10 CGNAT route. At most one of this or
// [OneCGNATEnable] may be set; if neither are, it's automatic.
OneCGNATDisable Cap = "one-cgnat?v=false"
// PeerMTUEnable makes the client do path MTU discovery to its
// peers. If it isn't set, it defaults to the client default.
PeerMTUEnable Cap = "peer-mtu-enable"
// DNSForwarderDisableTCPRetries disables retrying truncated
// DNS queries over TCP if the response is truncated.
DNSForwarderDisableTCPRetries Cap = "dns-forwarder-disable-tcp-retries"
// LinuxMustUseIPTables forces Linux clients to use iptables for
// netfilter management.
// This cannot be set simultaneously with [LinuxMustUseNfTables].
LinuxMustUseIPTables Cap = "linux-netfilter?v=iptables"
// LinuxMustUseNfTables forces Linux clients to use nftables for
// netfilter management.
// This cannot be set simultaneously with [LinuxMustUseIPTables].
LinuxMustUseNfTables Cap = "linux-netfilter?v=nftables"
// ProbeUDPLifetime makes the client probe UDP path lifetime at the
// tail end of an active direct connection in magicsock.
ProbeUDPLifetime Cap = "probe-udp-lifetime"
// TaildriveShare enables sharing via Taildrive.
TaildriveShare Cap = "drive:share"
// TaildriveAccess enables accessing shares via Taildrive.
TaildriveAccess Cap = "drive:access"
// SuggestExitNode is applied to each exit node which the control plane has determined
// is a recommended exit node.
SuggestExitNode Cap = "suggest-exit-node"
// DisableWebClient disables using the web client.
DisableWebClient Cap = "disable-web-client"
// LogExitFlows enables exit node destinations in network flow logs.
LogExitFlows Cap = "log-exit-flows"
// AutoExitNode permits the automatic exit nodes feature.
AutoExitNode Cap = "auto-exit-node"
// StoreAppCRoutes configures the node to store app connector routes persistently.
StoreAppCRoutes Cap = "store-appc-routes"
// SuggestExitNodeUI allows the currently suggested exit node to appear in the client GUI.
SuggestExitNodeUI Cap = "suggest-exit-node-ui"
// UserDialUseRoutes makes UserDial use either the peer dialer or the system dialer,
// depending on the destination address and the configured routes. When present, it also makes
// the DNS forwarder use UserDial instead of SystemDial when dialing resolvers.
UserDialUseRoutes Cap = "user-dial-routes"
// SSHBehaviorV1 forces SSH to use the V1 behavior (no su, run SFTP in-process)
// Added 2024-05-29 in Tailscale version 1.68.
SSHBehaviorV1 Cap = "ssh-behavior-v1"
// SSHBehaviorV2 forces SSH to use the V2 behavior (use su, run SFTP in child process).
// This overrides [SSHBehaviorV1] if set.
// See forceV1Behavior in ssh/tailssh/incubator.go for distinction between
// V1 and V2 behavior.
// Added 2024-08-06 in Tailscale version 1.72.
SSHBehaviorV2 Cap = "ssh-behavior-v2"
// DisableSplitDNSWhenNoCustomResolvers indicates that the node's
// DNS manager should not adopt a split DNS configuration even though the
// Config of the resolver only contains routes that do not specify custom
// resolver(s), hence all DNS queries can be safely sent to the upstream
// DNS resolver and the node's DNS forwarder doesn't need to handle all
// DNS traffic.
// This is for now (2024-06-06) an iOS-specific battery life optimization,
// and this node attribute allows us to disable the optimization remotely
// if needed.
DisableSplitDNSWhenNoCustomResolvers Cap = "disable-split-dns-when-no-custom-resolvers"
// ScopeQuad100OnMacOS lets sandboxed macOS scope quad-100 for simple DNS
// configs, so public queries can use the OS resolver (including DoH).
// Custom split resolvers or unrouted forward/PTR records still require
// quad-100 as primary. Without this attribute, quad-100 stays primary.
// Has no effect on other platforms. See tailscale/corp#45534 and
// tailscale/corp#48693.
ScopeQuad100OnMacOS Cap = "scope-quad100-macos"
// DisableLocalDNSOverrideViaNRPT indicates that the node's DNS manager should not
// create a default (catch-all) Windows NRPT rule when "Override local DNS" is enabled.
// Without this rule, Windows 8.1 and newer devices issue parallel DNS requests to DNS servers
// associated with all network adapters, even when "Override local DNS" is enabled and/or
// a Mullvad exit node is being used, resulting in DNS leaks.
// We began creating this rule on 2024-06-14, and this node attribute
// allows us to disable the new behavior remotely if needed.
DisableLocalDNSOverrideViaNRPT Cap = "disable-local-dns-override-via-nrpt"
// DisableMagicSockCryptoRouting disables the use of the
// magicsock cryptorouting hook. See tailscale/corp#20732.
//
// Deprecated: [DisableMagicSockCryptoRouting] is deprecated as of
// [tailscale.com/tailcfg.CapabilityVersion] 124,
// CryptoRouting is now mandatory. See tailscale/corp#31083.
DisableMagicSockCryptoRouting Cap = "disable-magicsock-crypto-routing"
// DisableCaptivePortalDetection instructs the client to not perform captive portal detection
// automatically when the network state changes.
DisableCaptivePortalDetection Cap = "disable-captive-portal-detection"
// DisableSkipStatusQueue is set when the node should disable skipping
// of queued netmap.NetworkMap between the controlclient and LocalBackend.
// See tailscale/tailscale#14768.
DisableSkipStatusQueue Cap = "disable-skip-status-queue"
// SSHEnvironmentVariables enables logic for handling environment variables sent
// via SendEnv in the SSH server and applying them to the SSH session.
SSHEnvironmentVariables Cap = "ssh-env-vars"
// ServiceHost indicates the VIP Services for which the client is
// approved to act as a service host, and which IP addresses are assigned
// to those VIP Services. Any VIP Services that the client is not
// advertising can be ignored.
// Each value of this key in [NodeCapMap] is of type [ServiceIPMappings].
// If multiple values of this key exist, they should be merged in sequence
// (replace conflicting keys).
ServiceHost Cap = "service-host"
// MaxKeyDuration represents the MaxKeyDuration setting on the
// tailnet. The value of this key in [NodeCapMap] will be only one entry of
// type float64 representing the duration in seconds. This cap will be
// omitted if the tailnet's MaxKeyDuration is the default.
MaxKeyDuration Cap = "tailnet.maxKeyDuration"
// NativeIPV4 contains the IPV4 address of the node in its
// native tailnet. This is currently only sent to Hello, in its
// peer node list.
NativeIPV4 Cap = "native-ipv4"
// DisableRelayServer prevents the node from acting as an underlay
// UDP relay server. There are no expected values for this key; the key
// only needs to be present in [NodeCapMap] to take effect.
DisableRelayServer Cap = "disable-relay-server"
// DisableRelayClient prevents the node from both allocating UDP
// relay server endpoints itself, and from using endpoints allocated by
// its peers. This attribute can be added to the node dynamically; if added
// while the node is already running, the node will be unable to allocate
// endpoints after it next updates its network map, and will be immediately
// unable to use new paths via a UDP relay server. Setting this attribute
// dynamically does not remove any existing paths, including paths that
// traverse a UDP relay server. There are no expected values for this key
// in [NodeCapMap]; the key only needs to be present in [NodeCapMap] to
// take effect.
DisableRelayClient Cap = "disable-relay-client"
// MagicDNSPeerAAAA is a capability that tells the node's MagicDNS
// server to answer AAAA queries about its peers. See tailscale/tailscale#1152.
MagicDNSPeerAAAA Cap = "magicdns-aaaa"
// DNSSubdomainResolve, when set on Self or a Peer node, indicates
// that the subdomains of that node's MagicDNS name should resolve to the
// same IP addresses as the node itself.
// For example, if node "myserver.tailnet.ts.net" has this capability,
// then "anything.myserver.tailnet.ts.net" will resolve to myserver's IPs.
DNSSubdomainResolve Cap = "dns-subdomain-resolve"
// TrafficSteering configures the node to use the traffic
// steering subsystem for via routes. See tailscale/corp#29966.
TrafficSteering Cap = "traffic-steering"
// TailnetDisplayName is an optional alternate name for the tailnet
// to be displayed to the user.
// If empty or absent, a default is used.
// If this value is present and set by a user this will only include letters,
// numbers, apostrophe, spaces, and hyphens. This may not be true for the default.
// Values can look like "foo.com" or "Foo's Test Tailnet - Staging".
TailnetDisplayName Cap = "tailnet-display-name"
// ClientSideReachability configures the node to determine
// reachability itself when choosing connectors. When absent, the
// default behavior is to trust the control plane when it claims that a
// node is no longer online, but that is not a reliable signal.
//
// It is temporary and will be ignored once its behaviour becomes the default.
ClientSideReachability Cap = "client-side-reachability"
// ClientSideReachabilityRouteCheck configures the node to use
// the routecheck subsystem to determine reachability when choosing
// connectors. This relies on [ClientSideReachability] being set.
// See tailscale/tailscale#17367.
//
// It is temporary and will be ignored once its behaviour becomes the default.
ClientSideReachabilityRouteCheck Cap = "client-side-reachability-routecheck"
// DefaultAutoUpdate advertises the default node auto-update setting
// for this tailnet. The node is free to opt-in or out locally regardless of
// this value. Once this has been set and stored in the client, future
// changes from the control plane are ignored.
//
// The value of the key in [NodeCapMap] is a JSON boolean.
DefaultAutoUpdate Cap = "default-auto-update"
// DisableHostsFileUpdates indicates that the node's DNS manager should
// not create hosts file entries when it normally would, such as when we're not
// the primary resolver on Windows or when the host is domain-joined and its
// primary domain takes precedence over MagicDNS. As of 2026-02-12, it is only
// used on Windows.
DisableHostsFileUpdates Cap = "disable-hosts-file-updates"
// ForceRegisterMagicDNSIPv4Only forces the client to only register
// its MagicDNS IPv4 address with systemd/etc, and not both its IPv4 and IPv6 addresses.
// See https://github.com/tailscale/tailscale/issues/15404.
// TODO(bradfitz): remove this a few releases after 2026-02-16.
ForceRegisterMagicDNSIPv4Only Cap = "force-register-magicdns-ipv4-only"
// CacheNetworkMaps instructs the node to persistently cache network
// maps and use them to establish peer connectivity on start, if doing so is
// supported by the client and storage is available. When this attribute is
// absent (or removed), a node that supports netmap caching will ignore and
// discard existing cached maps, and will not store any.
CacheNetworkMaps Cap = "cache-network-maps"
// DisableCacheNetworkMaps indicates that the node should not cache
// network maps (as per [CacheNetworkMaps]) when it normally would.
// This attribute exists to allow the policy document to override the default.
// When set, it takes precedence over [CacheNetworkMaps].
DisableCacheNetworkMaps Cap = "disable-cache-network-maps"
// DisableLinuxCGNATDropRule tells Linux clients to not insert a
// blanket firewall DROP rule for inbound traffic from the CGNAT IP range
// that does not originate from the Tailscale network interface.
// This enables access to off-tailnet endpoints within that IP range.
DisableLinuxCGNATDropRule Cap = "disable-linux-cgnat-drop-rule"
// EmitRuntimeMetrics enables emission of [runtime/metrics] as
// [tailscale.com/util/clientmetric]'s.
EmitRuntimeMetrics Cap = "emit-runtime-metrics"
// ConnReject enables the node's aggregated connection-rejection diagnostic
// buffers and the debug-rejects LocalAPI and GET /debug/rejects c2n endpoints.
ConnReject Cap = "debug-conn-reject"
// DisableUDPGRO disables UDP GRO (UDP_GRO socket option on Linux)
// on the magicsock UDP socket. It exists so control can mitigate kernel
// regressions that cause throughput or correctness issues with UDP GRO on
// specific OS/kernel versions, without requiring a client release. See
// https://github.com/tailscale/tailscale/issues/19777 for example.
// Currently only consulted on Linux; may apply to other platforms as they
// gain UDP GRO support.
DisableUDPGRO Cap = "disable-udp-gro"
// DisableUDPGSO disables UDP GSO (UDP_SEGMENT socket option on
// Linux) on the magicsock UDP socket. It exists so control can mitigate
// kernel regressions that cause throughput or correctness issues with UDP
// GSO on specific OS/kernel versions, without requiring a client release.
// See https://github.com/tailscale/tailscale/issues/19777 for example.
// Currently only consulted on Linux; may apply to other platforms as they
// gain UDP GSO support.
DisableUDPGSO Cap = "disable-udp-gso"
// DisableTUNUDPGRO disables UDP GRO on the Tailscale TUN device.
// It exists so control can mitigate kernel regressions that cause
// throughput or correctness issues with TUN UDP GRO on specific OS/kernel
// versions, without requiring a client release. See
// https://github.com/tailscale/tailscale/issues/13041 for example.
// Currently only consulted on Linux; may apply to other platforms as they
// gain TUN UDP GRO support.
DisableTUNUDPGRO Cap = "disable-tun-udp-gro"
// DisableTUNTCPGRO disables TCP GRO on the Tailscale TUN device.
// It exists so control can mitigate kernel regressions that cause
// throughput or correctness issues with TUN TCP GRO on specific OS/kernel
// versions, without requiring a client release. See
// https://github.com/tailscale/tailscale/issues/13041 for example.
// Currently only consulted on Linux; may apply to other platforms as they
// gain TUN TCP GRO support.
DisableTUNTCPGRO Cap = "disable-tun-tcp-gro"
// NeverGSOEqualTail enables a sentinel-tail workaround in the
// underlay UDP packet TX path on Linux. Applies to magicsock and peer relay
// UDP sockets. The workaround avoids emitting UDP GSO batches whose
// fragments are all equal in length, at a small payload and packet overhead
// cost. It exists so control can mitigate kernel regressions that mangle
// UDP headers or checksums for equal-length GSO batches, without requiring
// a client release. See https://github.com/tailscale/tailscale/issues/19777.
NeverGSOEqualTail Cap = "never-gso-equal-tail"
// Conn25Connector specifies which conn25 apps a peer is a connector for.
// Presence of this field means that this client may try to use the peer as
// a connector for the domains specified in the named app's configuration.
Conn25Connector Cap = "conn25-connector-apps"
)
const (
// ServicesPrefix is the prefix for per-service [NodeCapMap]
// entries describing Services visible (accessible) to this node.
// Each value under such a key is of type [ServiceDetails].
// The suffix after the prefix is an opaque server-chosen identifier;
// consumers must use [ServiceDetails.Name] as the canonical service name
// rather than parsing it from the map key.
ServicesPrefix Prefix = "services/"
)
+79
View File
@@ -0,0 +1,79 @@
// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause
// Package peercap defines the capabilities that can be granted to peer nodes.
package peercap
// Cap represents a capability granted to a peer by a [tailscale.com/tailcfg.FilterRule]
// when the peer communicates with the node that has this rule.
// Its meaning is application-defined.
//
// It must be a URL like "https://tailscale.com/cap/file-send"
// or "tailscale.com/cap/webui".
type Cap string
// Prefix is a prefix for [tailscale.com/tailcfg.PeerCapMap] keys that share a
// common namespace, where each entry represents a distinct named instance (e.g.
// one per App definition). The full key is formed by concatenating the prefix
// with the instance name.
type Prefix string
// ToAttribute returns the full [Cap] key for the given value under this prefix,
// of the form prefix+value.
func (p Prefix) ToAttribute(value string) Cap {
return Cap(string(p) + value)
}
const (
// FileSharingTarget grants the current node the ability to send
// files to the peer which has this capability.
FileSharingTarget Cap = "https://tailscale.com/cap/file-sharing-target"
// FileSharingSend grants the ability to receive files from a
// node that's owned by a different user.
FileSharingSend Cap = "https://tailscale.com/cap/file-send"
// DebugPeer grants the ability for a peer to read this node's
// goroutines, metrics, magicsock internal state, etc.
DebugPeer Cap = "https://tailscale.com/cap/debug-peer"
// WakeOnLAN grants the ability to send a Wake-On-LAN packet.
WakeOnLAN Cap = "https://tailscale.com/cap/wake-on-lan"
// Ingress grants the ability for a peer to send ingress traffic.
Ingress Cap = "https://tailscale.com/cap/ingress"
// WebUI grants the ability for a peer to edit features from the
// device Web UI.
WebUI Cap = "tailscale.com/cap/webui"
// Taildrive grants the ability for a peer to access Taildrive
// shares.
Taildrive Cap = "tailscale.com/cap/drive"
// TaildriveSharer indicates that a peer has the ability to
// share folders with us.
TaildriveSharer Cap = "tailscale.com/cap/drive-sharer"
// Kubernetes grants a peer Kubernetes-specific
// capabilities, such as the ability to impersonate specific Tailscale
// user groups as Kubernetes user groups. This capability is read by
// peers that are Tailscale Kubernetes operator instances.
Kubernetes Cap = "tailscale.com/cap/kubernetes"
// Relay grants the ability for a peer to allocate relay
// endpoints.
Relay Cap = "tailscale.com/cap/relay"
// RelayTarget grants the current node the ability to allocate
// relay endpoints to the peer which has this capability.
RelayTarget Cap = "tailscale.com/cap/relay-target"
// TsIDP grants a peer tsidp-specific
// capabilities, such as the ability to add user groups to the OIDC
// claim
TsIDP Cap = "tailscale.com/cap/tsidp"
)
const (
// Conn25Prefix is the prefix for per-app [Cap] names that grant a peer
// access to an app provided by a conn25 app connector.
// Actual capabilities look like "tailscale.com/cap/conn25/example" for
// an app named "example".
// Each value under such a key is a [tailscale.com/tailcfg.ProtoPortRange].
// If multiple values are present, the union of all protocol/port
// combinations described shall be permitted.
Conn25Prefix Prefix = "tailscale.com/cap/conn25/"
)
+2 -2
View File
@@ -1,4 +1,4 @@
// Copyright (c) Tailscale Inc & AUTHORS
// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause
package tailcfg
@@ -119,7 +119,7 @@ func parseProtoPortRange(ipProtoPort string) (*ProtoPortRange, error) {
}
// ParseHostPortRange parses hostport as HOST:PORTS where HOST is
// returned unchanged and PORTS is is either "*" or PORTLOW-PORTHIGH ranges.
// returned unchanged and PORTS is either "*" or PORTLOW-PORTHIGH ranges.
func ParseHostPortRange(hostport string) (host string, ports PortRange, err error) {
hostport = strings.ToLower(hostport)
colon := strings.LastIndexByte(hostport, ':')
+431 -383
View File
File diff suppressed because it is too large. Load diff
+40 -24
View File
@@ -1,4 +1,4 @@
// Copyright (c) Tailscale Inc & AUTHORS
// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause
// Code generated by tailscale.com/cmd/cloner; DO NOT EDIT.
@@ -10,10 +10,10 @@ import (
"net/netip"
"time"
"tailscale.com/tailcfg/nodecap"
"tailscale.com/types/dnstype"
"tailscale.com/types/key"
"tailscale.com/types/opt"
"tailscale.com/types/ptr"
"tailscale.com/types/structs"
"tailscale.com/types/tkatype"
)
@@ -53,23 +53,23 @@ func (src *Node) Clone() *Node {
dst.Tags = append(src.Tags[:0:0], src.Tags...)
dst.PrimaryRoutes = append(src.PrimaryRoutes[:0:0], src.PrimaryRoutes...)
if dst.LastSeen != nil {
dst.LastSeen = ptr.To(*src.LastSeen)
dst.LastSeen = new(*src.LastSeen)
}
if dst.Online != nil {
dst.Online = ptr.To(*src.Online)
dst.Online = new(*src.Online)
}
dst.Capabilities = append(src.Capabilities[:0:0], src.Capabilities...)
if dst.CapMap != nil {
dst.CapMap = map[NodeCapability][]RawMessage{}
dst.CapMap = map[nodecap.Cap][]RawMessage{}
for k := range src.CapMap {
dst.CapMap[k] = append([]RawMessage{}, src.CapMap[k]...)
}
}
if dst.SelfNodeV4MasqAddrForThisPeer != nil {
dst.SelfNodeV4MasqAddrForThisPeer = ptr.To(*src.SelfNodeV4MasqAddrForThisPeer)
dst.SelfNodeV4MasqAddrForThisPeer = new(*src.SelfNodeV4MasqAddrForThisPeer)
}
if dst.SelfNodeV6MasqAddrForThisPeer != nil {
dst.SelfNodeV6MasqAddrForThisPeer = ptr.To(*src.SelfNodeV6MasqAddrForThisPeer)
dst.SelfNodeV6MasqAddrForThisPeer = new(*src.SelfNodeV6MasqAddrForThisPeer)
}
if src.ExitNodeDNSResolvers != nil {
dst.ExitNodeDNSResolvers = make([]*dnstype.Resolver, len(src.ExitNodeDNSResolvers))
@@ -100,7 +100,7 @@ var _NodeCloneNeedsRegeneration = Node(struct {
AllowedIPs []netip.Prefix
Endpoints []netip.AddrPort
LegacyDERPString string
HomeDERP int
HomeDERP DERPRegionID
Hostinfo HostinfoView
Created time.Time
Cap CapabilityVersion
@@ -109,7 +109,7 @@ var _NodeCloneNeedsRegeneration = Node(struct {
LastSeen *time.Time
Online *bool
MachineAuthorized bool
Capabilities []NodeCapability
Capabilities []nodecap.Cap
CapMap NodeCapMap
UnsignedPeerAPIOnly bool
ComputedName string
@@ -122,6 +122,7 @@ var _NodeCloneNeedsRegeneration = Node(struct {
IsWireGuardOnly bool
IsJailed bool
ExitNodeDNSResolvers []*dnstype.Resolver
StableTailnetID StableTailnetID
}{})
// Clone makes a deep copy of Hostinfo.
@@ -139,10 +140,10 @@ func (src *Hostinfo) Clone() *Hostinfo {
dst.NetInfo = src.NetInfo.Clone()
dst.SSH_HostKeys = append(src.SSH_HostKeys[:0:0], src.SSH_HostKeys...)
if dst.Location != nil {
dst.Location = ptr.To(*src.Location)
dst.Location = new(*src.Location)
}
if dst.TPM != nil {
dst.TPM = ptr.To(*src.TPM)
dst.TPM = new(*src.TPM)
}
return dst
}
@@ -168,6 +169,7 @@ var _HostinfoCloneNeedsRegeneration = Hostinfo(struct {
ShieldsUp bool
ShareeNode bool
NoLogsNoSupport bool
RemoteConfig bool
WireIngress bool
IngressEnabled bool
AllowsUpdate bool
@@ -186,6 +188,7 @@ var _HostinfoCloneNeedsRegeneration = Hostinfo(struct {
UserspaceRouter opt.Bool
AppConnector opt.Bool
ServicesHash string
PeerRelay bool
ExitNodeID StableNodeID
Location *Location
TPM *TPMInfo
@@ -215,7 +218,7 @@ var _NetInfoCloneNeedsRegeneration = NetInfo(struct {
UPnP opt.Bool
PMP opt.Bool
PCP opt.Bool
PreferredDERP int
PreferredDERP DERPRegionID
LinkType string
DERPLatency map[string]float64
FirewallMode string
@@ -262,8 +265,19 @@ func (src *DNSConfig) Clone() *DNSConfig {
}
if dst.Routes != nil {
dst.Routes = map[string][]*dnstype.Resolver{}
for k := range src.Routes {
dst.Routes[k] = append([]*dnstype.Resolver{}, src.Routes[k]...)
for k, sv := range src.Routes {
if sv == nil {
dst.Routes[k] = nil
continue
}
dst.Routes[k] = make([]*dnstype.Resolver, len(sv))
for i := range sv {
if sv[i] == nil {
dst.Routes[k][i] = nil
} else {
dst.Routes[k][i] = sv[i].Clone()
}
}
}
}
if src.FallbackResolvers != nil {
@@ -330,7 +344,7 @@ func (src *RegisterResponseAuth) Clone() *RegisterResponseAuth {
dst := new(RegisterResponseAuth)
*dst = *src
if dst.Oauth2Token != nil {
dst.Oauth2Token = ptr.To(*src.Oauth2Token)
dst.Oauth2Token = new(*src.Oauth2Token)
}
return dst
}
@@ -354,7 +368,7 @@ func (src *RegisterRequest) Clone() *RegisterRequest {
dst.Hostinfo = src.Hostinfo.Clone()
dst.NodeKeySignature = append(src.NodeKeySignature[:0:0], src.NodeKeySignature...)
if dst.Timestamp != nil {
dst.Timestamp = ptr.To(*src.Timestamp)
dst.Timestamp = new(*src.Timestamp)
}
dst.DeviceCert = append(src.DeviceCert[:0:0], src.DeviceCert...)
dst.Signature = append(src.Signature[:0:0], src.Signature...)
@@ -395,7 +409,7 @@ func (src *DERPHomeParams) Clone() *DERPHomeParams {
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _DERPHomeParamsCloneNeedsRegeneration = DERPHomeParams(struct {
RegionScore map[int]float64
RegionScore map[DERPRegionID]float64
}{})
// Clone makes a deep copy of DERPRegion.
@@ -412,7 +426,7 @@ func (src *DERPRegion) Clone() *DERPRegion {
if src.Nodes[i] == nil {
dst.Nodes[i] = nil
} else {
dst.Nodes[i] = ptr.To(*src.Nodes[i])
dst.Nodes[i] = new(*src.Nodes[i])
}
}
}
@@ -421,7 +435,7 @@ func (src *DERPRegion) Clone() *DERPRegion {
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _DERPRegionCloneNeedsRegeneration = DERPRegion(struct {
RegionID int
RegionID DERPRegionID
RegionCode string
RegionName string
Latitude float64
@@ -441,7 +455,7 @@ func (src *DERPMap) Clone() *DERPMap {
*dst = *src
dst.HomeParams = src.HomeParams.Clone()
if dst.Regions != nil {
dst.Regions = map[int]*DERPRegion{}
dst.Regions = map[DERPRegionID]*DERPRegion{}
for k, v := range src.Regions {
if v == nil {
dst.Regions[k] = nil
@@ -456,7 +470,7 @@ func (src *DERPMap) Clone() *DERPMap {
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _DERPMapCloneNeedsRegeneration = DERPMap(struct {
HomeParams *DERPHomeParams
Regions map[int]*DERPRegion
Regions map[DERPRegionID]*DERPRegion
OmitDefaultRegions bool
}{})
@@ -474,7 +488,7 @@ func (src *DERPNode) Clone() *DERPNode {
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _DERPNodeCloneNeedsRegeneration = DERPNode(struct {
Name string
RegionID int
RegionID DERPRegionID
HostName string
CertName string
IPv4 string
@@ -496,7 +510,7 @@ func (src *SSHRule) Clone() *SSHRule {
dst := new(SSHRule)
*dst = *src
if dst.RuleExpires != nil {
dst.RuleExpires = ptr.To(*src.RuleExpires)
dst.RuleExpires = new(*src.RuleExpires)
}
if src.Principals != nil {
dst.Principals = make([]*SSHPrincipal, len(src.Principals))
@@ -533,7 +547,7 @@ func (src *SSHAction) Clone() *SSHAction {
*dst = *src
dst.Recorders = append(src.Recorders[:0:0], src.Recorders...)
if dst.OnRecordingFailure != nil {
dst.OnRecordingFailure = ptr.To(*src.OnRecordingFailure)
dst.OnRecordingFailure = new(*src.OnRecordingFailure)
}
return dst
}
@@ -620,6 +634,7 @@ func (src *UserProfile) Clone() *UserProfile {
}
dst := new(UserProfile)
*dst = *src
dst.Groups = append(src.Groups[:0:0], src.Groups...)
return dst
}
@@ -629,6 +644,7 @@ var _UserProfileCloneNeedsRegeneration = UserProfile(struct {
LoginName string
DisplayName string
ProfilePicURL string
Groups []string
}{})
// Clone makes a deep copy of VIPService.
+61 -23
View File
@@ -1,4 +1,4 @@
// Copyright (c) Tailscale Inc & AUTHORS
// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause
// Code generated by tailscale/cmd/viewer; DO NOT EDIT.
@@ -13,6 +13,7 @@ import (
jsonv2 "github.com/go-json-experiment/json"
"github.com/go-json-experiment/json/jsontext"
"tailscale.com/tailcfg/nodecap"
"tailscale.com/types/dnstype"
"tailscale.com/types/key"
"tailscale.com/types/opt"
@@ -230,7 +231,7 @@ func (v NodeView) LegacyDERPString() string { return v.ж.LegacyDERPString }
//
// HomeDERP may be zero if not (yet) known, but ideally always be non-zero
// for magicsock connectivity to function normally.
func (v NodeView) HomeDERP() int { return v.ж.HomeDERP }
func (v NodeView) HomeDERP() DERPRegionID { return v.ж.HomeDERP }
func (v NodeView) Hostinfo() HostinfoView { return v.ж.Hostinfo }
func (v NodeView) Created() time.Time { return v.ж.Created }
@@ -277,7 +278,7 @@ func (v NodeView) MachineAuthorized() bool { return v.ж.MachineAuthorized }
// "https://tailscale.com/cap/file-sharing"
//
// Deprecated: use CapMap instead. See https://github.com/tailscale/tailscale/issues/11508
func (v NodeView) Capabilities() views.Slice[NodeCapability] { return views.SliceOf(v.ж.Capabilities) }
func (v NodeView) Capabilities() views.Slice[nodecap.Cap] { return views.SliceOf(v.ж.Capabilities) }
// CapMap is a map of capabilities to their optional argument/data values.
//
@@ -288,7 +289,7 @@ func (v NodeView) Capabilities() views.Slice[NodeCapability] { return views.Slic
// represented by the Capabilities field, but can now be represented by
// CapMap with an empty value.
//
// See NodeCapability for more information on keys.
// See [nodecap.Cap] for more information on keys.
//
// Metadata about nodes can be transmitted in 3 ways:
// 1. MapResponse.Node.CapMap describes attributes that affect behavior for
@@ -299,7 +300,7 @@ func (v NodeView) Capabilities() views.Slice[NodeCapability] { return views.Slic
// 3. MapResponse.Peers[].CapMap describes attributes regarding a peer node,
// such as which features the peer supports or if that peer is preferred
// for a particular task vs other peers that could also be chosen.
func (v NodeView) CapMap() views.MapSlice[NodeCapability, RawMessage] {
func (v NodeView) CapMap() views.MapSlice[nodecap.Cap, RawMessage] {
return views.MapSliceOf(v.ж.CapMap)
}
@@ -375,7 +376,14 @@ func (v NodeView) IsJailed() bool { return v.ж.IsJailed }
func (v NodeView) ExitNodeDNSResolvers() views.SliceView[*dnstype.Resolver, dnstype.ResolverView] {
return views.SliceOfViews[*dnstype.Resolver, dnstype.ResolverView](v.ж.ExitNodeDNSResolvers)
}
func (v NodeView) Equal(v2 NodeView) bool { return v.ж.Equal(v2.ж) }
// StableTailnetID is the identifier of the tailnet this node is a
// member of.
//
// Control only populates this for the self node in a MapResponse
// (MapResponse.Node); it is empty for peers.
func (v NodeView) StableTailnetID() StableTailnetID { return v.ж.StableTailnetID }
func (v NodeView) Equal(v2 NodeView) 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 _NodeViewNeedsRegeneration = Node(struct {
@@ -393,7 +401,7 @@ var _NodeViewNeedsRegeneration = Node(struct {
AllowedIPs []netip.Prefix
Endpoints []netip.AddrPort
LegacyDERPString string
HomeDERP int
HomeDERP DERPRegionID
Hostinfo HostinfoView
Created time.Time
Cap CapabilityVersion
@@ -402,7 +410,7 @@ var _NodeViewNeedsRegeneration = Node(struct {
LastSeen *time.Time
Online *bool
MachineAuthorized bool
Capabilities []NodeCapability
Capabilities []nodecap.Cap
CapMap NodeCapMap
UnsignedPeerAPIOnly bool
ComputedName string
@@ -415,6 +423,7 @@ var _NodeViewNeedsRegeneration = Node(struct {
IsWireGuardOnly bool
IsJailed bool
ExitNodeDNSResolvers []*dnstype.Resolver
StableTailnetID StableTailnetID
}{})
// View returns a read-only view of Hostinfo.
@@ -550,6 +559,14 @@ func (v HostinfoView) ShareeNode() bool { return v.ж.ShareeNode }
// indicates that the user has opted out of sending logs and support
func (v HostinfoView) NoLogsNoSupport() bool { return v.ж.NoLogsNoSupport }
// RemoteConfig is whether the node has both linked
// feature/remoteconfig into its binary and enabled
// Prefs.RemoteConfig: it has delegated full remote management of
// its prefs and LocalAPI to the tailnet admin via the
// /remoteapi/localapi/* c2n endpoint. See feature/remoteconfig for
// the trust model.
func (v HostinfoView) RemoteConfig() bool { return v.ж.RemoteConfig }
// WireIngress indicates that the node would like to be wired up server-side
// (DNS, etc) to be able to use Tailscale Funnel, even if it's not currently
// enabled. For example, the user might only use it for intermittent
@@ -562,7 +579,10 @@ func (v HostinfoView) WireIngress() bool { return v.ж.WireIngress }
// if the node has any funnel endpoint enabled
func (v HostinfoView) IngressEnabled() bool { return v.ж.IngressEnabled }
// indicates that the node has opted-in to admin-console-drive remote updates
// AllowsUpdate reports that the node has opted in to
// admin-console-driven remote updates and that the running binary
// includes client update support (the feature/clientupdate package,
// which tsnet apps don't include).
func (v HostinfoView) AllowsUpdate() bool { return v.ж.AllowsUpdate }
// the current host's machine type (uname -m)
@@ -606,6 +626,9 @@ func (v HostinfoView) AppConnector() opt.Bool { return v.ж.AppConnector }
// opaque hash of the most recent list of tailnet services, change in hash indicates config should be fetched via c2n
func (v HostinfoView) ServicesHash() string { return v.ж.ServicesHash }
// if the client is willing to relay traffic for other peers
func (v HostinfoView) PeerRelay() bool { return v.ж.PeerRelay }
// the client’s selected exit node, empty when unselected.
func (v HostinfoView) ExitNodeID() StableNodeID { return v.ж.ExitNodeID }
@@ -646,6 +669,7 @@ var _HostinfoViewNeedsRegeneration = Hostinfo(struct {
ShieldsUp bool
ShareeNode bool
NoLogsNoSupport bool
RemoteConfig bool
WireIngress bool
IngressEnabled bool
AllowsUpdate bool
@@ -664,6 +688,7 @@ var _HostinfoViewNeedsRegeneration = Hostinfo(struct {
UserspaceRouter opt.Bool
AppConnector opt.Bool
ServicesHash string
PeerRelay bool
ExitNodeID StableNodeID
Location *Location
TPM *TPMInfo
@@ -773,12 +798,12 @@ func (v NetInfoView) PCP() opt.Bool { return v.ж.PCP }
// PreferredDERP is this node's preferred (home) DERP region ID.
// This is where the node expects to be contacted to begin a
// peer-to-peer connection. The node might be be temporarily
// peer-to-peer connection. The node might be temporarily
// connected to multiple DERP servers (to speak to other nodes
// that are located elsewhere) but PreferredDERP is the region ID
// that the node subscribes to traffic at.
// Zero means disconnected or unknown.
func (v NetInfoView) PreferredDERP() int { return v.ж.PreferredDERP }
func (v NetInfoView) PreferredDERP() DERPRegionID { return v.ж.PreferredDERP }
// LinkType is the current link type, if known.
func (v NetInfoView) LinkType() string { return v.ж.LinkType }
@@ -813,7 +838,7 @@ var _NetInfoViewNeedsRegeneration = NetInfo(struct {
UPnP opt.Bool
PMP opt.Bool
PCP opt.Bool
PreferredDERP int
PreferredDERP DERPRegionID
LinkType string
DERPLatency map[string]float64
FirewallMode string
@@ -1345,7 +1370,7 @@ func (v RegisterRequestView) Hostinfo() HostinfoView { return v.ж.Hostinfo.View
func (v RegisterRequestView) Ephemeral() bool { return v.ж.Ephemeral }
// NodeKeySignature is the node's own node-key signature, re-signed
// for its new node key using its network-lock key.
// for its new node key using its tailnet-lock key.
//
// This field is set when the client retries registration after learning
// its NodeKeySignature (which is in need of rotation).
@@ -1483,13 +1508,13 @@ func (v *DERPHomeParamsView) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
//
// A nil map means no change from the previous value (if any); an empty
// non-nil map can be sent to reset all scores back to 1.0.
func (v DERPHomeParamsView) RegionScore() views.Map[int, float64] {
func (v DERPHomeParamsView) RegionScore() views.Map[DERPRegionID, float64] {
return views.MapOf(v.ж.RegionScore)
}
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _DERPHomeParamsViewNeedsRegeneration = DERPHomeParams(struct {
RegionScore map[int]float64
RegionScore map[DERPRegionID]float64
}{})
// View returns a read-only view of DERPRegion.
@@ -1571,7 +1596,7 @@ func (v *DERPRegionView) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
//
// RegionIDs in range 900-999 are reserved for end users to run their
// own DERP nodes.
func (v DERPRegionView) RegionID() int { return v.ж.RegionID }
func (v DERPRegionView) RegionID() DERPRegionID { return v.ж.RegionID }
// RegionCode is a short name for the region. It's usually a popular
// city or airport code in the region: "nyc", "sf", "sin",
@@ -1630,7 +1655,7 @@ func (v DERPRegionView) Nodes() views.SliceView[*DERPNode, DERPNodeView] {
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _DERPRegionViewNeedsRegeneration = DERPRegion(struct {
RegionID int
RegionID DERPRegionID
RegionCode string
RegionName string
Latitude float64
@@ -1717,7 +1742,7 @@ func (v DERPMapView) HomeParams() DERPHomeParamsView { return v.ж.HomeParams.Vi
// It's keyed by the DERPRegion.RegionID.
//
// The numbers are not necessarily contiguous.
func (v DERPMapView) Regions() views.MapFn[int, *DERPRegion, DERPRegionView] {
func (v DERPMapView) Regions() views.MapFn[DERPRegionID, *DERPRegion, DERPRegionView] {
return views.MapFnOf(v.ж.Regions, func(t *DERPRegion) DERPRegionView {
return t.View()
})
@@ -1732,7 +1757,7 @@ func (v DERPMapView) OmitDefaultRegions() bool { return v.ж.OmitDefaultRegions
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _DERPMapViewNeedsRegeneration = DERPMap(struct {
HomeParams *DERPHomeParams
Regions map[int]*DERPRegion
Regions map[DERPRegionID]*DERPRegion
OmitDefaultRegions bool
}{})
@@ -1811,7 +1836,7 @@ func (v DERPNodeView) Name() string { return v.ж.Name }
// RegionID is the RegionID of the DERPRegion that this node
// is running in.
func (v DERPNodeView) RegionID() int { return v.ж.RegionID }
func (v DERPNodeView) RegionID() DERPRegionID { return v.ж.RegionID }
// HostName is the DERP node's hostname.
//
@@ -1875,7 +1900,7 @@ func (v DERPNodeView) CanPort80() bool { return v.ж.CanPort80 }
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _DERPNodeViewNeedsRegeneration = DERPNode(struct {
Name string
RegionID int
RegionID DERPRegionID
HostName string
CertName string
IPv4 string
@@ -2091,6 +2116,11 @@ func (v SSHActionView) Accept() bool { return v.ж.Accept }
// SessionDuration, if non-zero, is how long the session can stay open
// before being forcefully terminated.
// It is encoded as an int64 of nanoseconds (Go's time.Duration
// wire format for encoding/json v1). It must not use a jsonv2
// format tag; the mere presence of one makes Go 1.27's
// encoding/json fail to decode the struct. See
// https://github.com/tailscale/tailscale/issues/20528.
func (v SSHActionView) SessionDuration() time.Duration { return v.ж.SessionDuration }
// AllowAgentForwarding, if true, allows accepted connections to forward
@@ -2501,8 +2531,15 @@ func (v UserProfileView) ID() UserID { return v.ж.ID }
func (v UserProfileView) LoginName() string { return v.ж.LoginName }
// "Alice Smith"
func (v UserProfileView) DisplayName() string { return v.ж.DisplayName }
func (v UserProfileView) ProfilePicURL() string { return v.ж.ProfilePicURL }
func (v UserProfileView) DisplayName() string { return v.ж.DisplayName }
func (v UserProfileView) ProfilePicURL() string { return v.ж.ProfilePicURL }
// Groups is a subset of SCIM groups (e.g. "engineering@example.com")
// or group names in the tailnet policy document (e.g. "group:eng")
// that contain this user and that the coordination server was
// configured to report to this node.
// The list is always sorted when loaded from storage.
func (v UserProfileView) Groups() views.Slice[string] { return views.SliceOf(v.ж.Groups) }
func (v UserProfileView) Equal(v2 UserProfileView) bool { return v.ж.Equal(v2.ж) }
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
@@ -2511,6 +2548,7 @@ var _UserProfileViewNeedsRegeneration = UserProfile(struct {
LoginName string
DisplayName string
ProfilePicURL string
Groups []string
}{})
// View returns a read-only view of VIPService.
+4 -4
View File
@@ -1,4 +1,4 @@
// Copyright (c) Tailscale Inc & AUTHORS
// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause
package tailcfg
@@ -36,7 +36,7 @@ type TKASignInfo struct {
// a NodeKeySignature (NKS), which rotates the node key.
//
// This is necessary so the node can rotate its node-key without
// talking to a node which holds a trusted network-lock key.
// talking to a node which holds a trusted tailnet-lock key.
// It does this by nesting the original NKS in a 'rotation' NKS,
// which it then signs with the key corresponding to RotationPubkey.
//
@@ -111,7 +111,7 @@ type TKABootstrapRequest struct {
NodeKey key.NodePublic
// Head represents the node's head AUMHash (tka.Authority.Head), if
// network lock is enabled.
// tailnet lock is enabled.
Head string
}
@@ -193,7 +193,7 @@ type TKASyncSendResponse struct {
Head string
}
// TKADisableRequest disables network-lock across the tailnet using the
// TKADisableRequest disables tailnet-lock across the tailnet using the
// provided disablement secret.
//
// This is the request schema for a /tka/disable noise RPC.