2023-01-27 13:37:20 -08:00
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
2022-05-01 16:23:55 -07:00
2022-05-01 16:24:54 -07:00
// Code generated by tailscale/cmd/viewer; DO NOT EDIT.
2022-05-01 16:23:55 -07:00
package tailcfg
import (
2025-08-14 13:46:48 -07:00
jsonv1 "encoding/json"
2022-05-01 16:23:55 -07:00
"errors"
2022-07-24 20:08:42 -07:00
"net/netip"
2022-05-01 16:24:54 -07:00
"time"
2022-05-01 16:23:55 -07:00
2025-08-14 13:46:48 -07:00
jsonv2 "github.com/go-json-experiment/json"
"github.com/go-json-experiment/json/jsontext"
2022-05-01 16:24:54 -07:00
"tailscale.com/types/dnstype"
"tailscale.com/types/key"
2022-05-01 16:23:55 -07:00
"tailscale.com/types/opt"
2022-05-01 16:24:54 -07:00
"tailscale.com/types/structs"
2022-08-12 12:34:25 -07:00
"tailscale.com/types/tkatype"
2022-05-01 16:23:55 -07:00
"tailscale.com/types/views"
)
2025-10-04 17:40:09 -07:00
//go:generate go run tailscale.com/cmd/cloner -clonefunc=true -type=User,Node,Hostinfo,NetInfo,Login,DNSConfig,RegisterResponse,RegisterResponseAuth,RegisterRequest,DERPHomeParams,DERPRegion,DERPMap,DERPNode,SSHRule,SSHAction,SSHPrincipal,ControlDialPlan,Location,UserProfile,VIPService,SSHPolicy
2022-05-01 16:23:55 -07:00
2025-01-14 08:15:27 -08:00
// View returns a read-only view of User.
2022-05-01 16:24:54 -07:00
func ( p * User ) View ( ) UserView {
return UserView { ж : p }
}
// UserView provides a read-only view over User.
//
// Its methods should only be called if `Valid()` returns true.
type UserView struct {
// ж is the underlying mutable value, named with a hard-to-type
// character that looks pointy like a pointer.
2022-05-01 16:23:55 -07:00
// 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.
2022-05-01 16:24:54 -07:00
ж * User
2022-05-01 16:23:55 -07:00
}
2025-01-14 08:15:27 -08:00
// Valid reports whether v's underlying value is non-nil.
2022-05-01 16:24:54 -07:00
func ( v UserView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v UserView ) AsStruct ( ) * User {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
2022-05-01 16:23:55 -07:00
}
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v UserView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v UserView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
2022-05-01 16:24:54 -07:00
2025-08-14 13:46:48 -07:00
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2022-05-01 16:24:54 -07:00
func ( v * UserView ) UnmarshalJSON ( b [ ] byte ) error {
2022-05-01 16:23:55 -07:00
if v . ж != nil {
2022-05-01 16:24:54 -07:00
return errors . New ( "already initialized" )
2022-05-01 16:23:55 -07:00
}
if len ( b ) == 0 {
return nil
}
2022-05-01 16:24:54 -07:00
var x User
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * UserView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x User
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2022-05-01 16:23:55 -07:00
return err
}
2022-05-01 16:24:54 -07:00
v . ж = & x
2022-05-01 16:23:55 -07:00
return nil
}
2025-08-27 00:06:28 -07:00
func ( v UserView ) ID ( ) UserID { return v . ж . ID }
// if non-empty overrides Login field
func ( v UserView ) DisplayName ( ) string { return v . ж . DisplayName }
// if non-empty overrides Login field
2025-01-06 09:54:11 -08:00
func ( v UserView ) ProfilePicURL ( ) string { return v . ж . ProfilePicURL }
func ( v UserView ) Created ( ) time . Time { return v . ж . Created }
2022-05-01 16:23:55 -07:00
2022-05-01 16:24:54 -07:00
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _UserViewNeedsRegeneration = User ( struct {
ID UserID
DisplayName string
ProfilePicURL string
Created time . Time
} { } )
2022-05-01 16:23:55 -07:00
2025-01-14 08:15:27 -08:00
// View returns a read-only view of Node.
2022-05-01 16:24:54 -07:00
func ( p * Node ) View ( ) NodeView {
return NodeView { ж : p }
}
// NodeView provides a read-only view over Node.
//
// Its methods should only be called if `Valid()` returns true.
type NodeView 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.
ж * Node
}
2025-01-14 08:15:27 -08:00
// Valid reports whether v's underlying value is non-nil.
2022-05-01 16:24:54 -07:00
func ( v NodeView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v NodeView ) AsStruct ( ) * Node {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v NodeView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v NodeView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
2022-05-01 16:24:54 -07:00
2025-08-14 13:46:48 -07:00
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2022-05-01 16:24:54 -07:00
func ( v * NodeView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x Node
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * NodeView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x Node
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2022-05-01 16:24:54 -07:00
return err
}
v . ж = & x
return nil
2022-05-01 16:23:55 -07:00
}
2023-08-20 14:35:39 -04:00
func ( v NodeView ) ID ( ) NodeID { return v . ж . ID }
func ( v NodeView ) StableID ( ) StableNodeID { return v . ж . StableID }
2025-08-27 00:06:28 -07:00
// Name is the FQDN of the node.
// It is also the MagicDNS name for the node.
// It has a trailing dot.
// e.g. "host.tail-scale.ts.net."
func ( v NodeView ) Name ( ) string { return v . ж . Name }
// User is the user who created the node. If ACL tags are in use for the
// node then it doesn't reflect the ACL identity that the node is running
// as.
func ( v NodeView ) User ( ) UserID { return v . ж . User }
// Sharer, if non-zero, is the user who shared this node, if different than User.
func ( v NodeView ) Sharer ( ) UserID { return v . ж . Sharer }
func ( v NodeView ) Key ( ) key . NodePublic { return v . ж . Key }
// the zero value if this node does not expire
func ( v NodeView ) KeyExpiry ( ) time . Time { return v . ж . KeyExpiry }
2023-08-20 14:35:39 -04:00
func ( v NodeView ) KeySignature ( ) views . ByteSlice [ tkatype . MarshaledSignature ] {
return views . ByteSliceOf ( v . ж . KeySignature )
}
2025-08-27 00:06:28 -07:00
func ( v NodeView ) Machine ( ) key . MachinePublic { return v . ж . Machine }
func ( v NodeView ) DiscoKey ( ) key . DiscoPublic { return v . ж . DiscoKey }
// Addresses are the IP addresses of this Node directly.
func ( v NodeView ) Addresses ( ) views . Slice [ netip . Prefix ] { return views . SliceOf ( v . ж . Addresses ) }
// AllowedIPs are the IP ranges to route to this node.
//
// As of CapabilityVersion 112, this may be nil (null or undefined) on the wire
// to mean the same as Addresses. Internally, it is always filled in with
// its possibly-implicit value.
func ( v NodeView ) AllowedIPs ( ) views . Slice [ netip . Prefix ] { return views . SliceOf ( v . ж . AllowedIPs ) }
// IP+port (public via STUN, and local LANs)
func ( v NodeView ) Endpoints ( ) views . Slice [ netip . AddrPort ] { return views . SliceOf ( v . ж . Endpoints ) }
// LegacyDERPString is this node's home LegacyDERPString region ID integer, but shoved into an
// IP:port string for legacy reasons. The IP address is always "127.3.3.40"
// (a loopback address (127) followed by the digits over the letters DERP on
// a QWERTY keyboard (3.3.40)). The "port number" is the home LegacyDERPString region ID
// integer.
//
// Deprecated: HomeDERP has replaced this, but old servers might still send
// this field. See tailscale/tailscale#14636. Do not use this field in code
// other than in the upgradeNode func, which canonicalizes it to HomeDERP
// if it arrives as a LegacyDERPString string on the wire.
func ( v NodeView ) LegacyDERPString ( ) string { return v . ж . LegacyDERPString }
// HomeDERP is the modern version of the DERP string field, with just an
// integer. The client advertises support for this as of capver 111.
//
// 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 ) Hostinfo ( ) HostinfoView { return v . ж . Hostinfo }
func ( v NodeView ) Created ( ) time . Time { return v . ж . Created }
// if non-zero, the node's capability version; old servers might not send
func ( v NodeView ) Cap ( ) CapabilityVersion { return v . ж . Cap }
// Tags are the list of ACL tags applied to this node.
// Tags take the form of `tag:<value>` where value starts
// with a letter and only contains alphanumerics and dashes `-`.
// Some valid tag examples:
//
// `tag:prod`
// `tag:database`
// `tag:lab-1`
func ( v NodeView ) Tags ( ) views . Slice [ string ] { return views . SliceOf ( v . ж . Tags ) }
// PrimaryRoutes are the routes from AllowedIPs that this node
// is currently the primary subnet router for, as determined
// by the control plane. It does not include the self address
// values from Addresses that are in AllowedIPs.
2023-08-18 10:57:04 -07:00
func ( v NodeView ) PrimaryRoutes ( ) views . Slice [ netip . Prefix ] { return views . SliceOf ( v . ж . PrimaryRoutes ) }
2025-08-27 00:06:28 -07:00
// LastSeen is when the node was last online. It is not
// updated when Online is true. It is nil if the current
// node doesn't have permission to know, or the node
// has never been online.
2025-01-08 17:21:44 -06:00
func ( v NodeView ) LastSeen ( ) views . ValuePointer [ time . Time ] {
return views . ValuePointerOf ( v . ж . LastSeen )
2022-05-01 16:23:55 -07:00
}
2025-08-27 00:06:28 -07:00
// Online is whether the node is currently connected to the
// coordination server. A value of nil means unknown, or the
// current node doesn't have permission to know.
2025-01-08 17:21:44 -06:00
func ( v NodeView ) Online ( ) views . ValuePointer [ bool ] { return views . ValuePointerOf ( v . ж . Online ) }
2022-05-01 16:23:55 -07:00
2025-08-27 00:06:28 -07:00
// TODO(crawshaw): replace with MachineStatus
func ( v NodeView ) MachineAuthorized ( ) bool { return v . ж . MachineAuthorized }
// Capabilities are capabilities that the node has.
// They're free-form strings, but should be in the form of URLs/URIs
// such as:
//
// "https://tailscale.com/cap/is-admin"
// "https://tailscale.com/cap/file-sharing"
//
// Deprecated: use CapMap instead. See https://github.com/tailscale/tailscale/issues/11508
2023-09-06 10:17:25 -07:00
func ( v NodeView ) Capabilities ( ) views . Slice [ NodeCapability ] { return views . SliceOf ( v . ж . Capabilities ) }
2023-09-18 08:52:22 -07:00
2025-08-27 00:06:28 -07:00
// CapMap is a map of capabilities to their optional argument/data values.
//
// It is valid for a capability to not have any argument/data values; such
// capabilities can be tested for using the HasCap method. These type of
// capabilities are used to indicate that a node has a capability, but there
// is no additional data associated with it. These were previously
// represented by the Capabilities field, but can now be represented by
// CapMap with an empty value.
//
// See NodeCapability for more information on keys.
//
// Metadata about nodes can be transmitted in 3 ways:
// 1. MapResponse.Node.CapMap describes attributes that affect behavior for
// this node, such as which features have been enabled through the admin
// panel and any associated configuration details.
// 2. MapResponse.PacketFilter(s) describes access (both IP and application
// based) that should be granted to peers.
// 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.
2024-06-15 21:42:34 -07:00
func ( v NodeView ) CapMap ( ) views . MapSlice [ NodeCapability , RawMessage ] {
return views . MapSliceOf ( v . ж . CapMap )
2023-09-18 08:52:22 -07:00
}
2025-08-27 00:06:28 -07:00
// UnsignedPeerAPIOnly means that this node is not signed nor subject to TKA
// restrictions. However, in exchange for that privilege, it does not get
// network access. It can only access this node's peerapi, which may not let
// it do anything. It is the tailscaled client's job to double-check the
// MapResponse's PacketFilter to verify that its AllowedIPs will not be
// accepted by the packet filter.
func ( v NodeView ) UnsignedPeerAPIOnly ( ) bool { return v . ж . UnsignedPeerAPIOnly }
// MagicDNS base name (for normal non-shared-in nodes), FQDN (without trailing dot, for shared-in nodes), or Hostname (if no MagicDNS)
func ( v NodeView ) ComputedName ( ) string { return v . ж . ComputedName }
// either "ComputedName" or "ComputedName (computedHostIfDifferent)", if computedHostIfDifferent is set
2023-09-18 08:52:22 -07:00
func ( v NodeView ) ComputedNameWithHost ( ) string { return v . ж . ComputedNameWithHost }
2025-08-27 00:06:28 -07:00
// DataPlaneAuditLogID is the per-node logtail ID used for data plane audit logging.
func ( v NodeView ) DataPlaneAuditLogID ( ) string { return v . ж . DataPlaneAuditLogID }
// Expired is whether this node's key has expired. Control may send
// this; clients are only allowed to set this from false to true. On
// the client, this is calculated client-side based on a timestamp sent
// from control, to avoid clock skew issues.
func ( v NodeView ) Expired ( ) bool { return v . ж . Expired }
// SelfNodeV4MasqAddrForThisPeer is the IPv4 that this peer knows the current node as.
// It may be empty if the peer knows the current node by its native
// IPv4 address.
// This field is only populated in a MapResponse for peers and not
// for the current node.
//
// If set, it should be used to masquerade traffic originating from the
// current node to this peer. The masquerade address is only relevant
// for this peer and not for other peers.
//
// This only applies to traffic originating from the current node to the
// peer or any of its subnets. Traffic originating from subnet routes will
// not be masqueraded (e.g. in case of --snat-subnet-routes).
2025-01-08 17:21:44 -06:00
func ( v NodeView ) SelfNodeV4MasqAddrForThisPeer ( ) views . ValuePointer [ netip . Addr ] {
return views . ValuePointerOf ( v . ж . SelfNodeV4MasqAddrForThisPeer )
2023-03-02 16:05:07 -08:00
}
2023-04-13 10:12:31 -07:00
2025-08-27 00:06:28 -07:00
// SelfNodeV6MasqAddrForThisPeer is the IPv6 that this peer knows the current node as.
// It may be empty if the peer knows the current node by its native
// IPv6 address.
// This field is only populated in a MapResponse for peers and not
// for the current node.
//
// If set, it should be used to masquerade traffic originating from the
// current node to this peer. The masquerade address is only relevant
// for this peer and not for other peers.
//
// This only applies to traffic originating from the current node to the
// peer or any of its subnets. Traffic originating from subnet routes will
// not be masqueraded (e.g. in case of --snat-subnet-routes).
2025-01-08 17:21:44 -06:00
func ( v NodeView ) SelfNodeV6MasqAddrForThisPeer ( ) views . ValuePointer [ netip . Addr ] {
return views . ValuePointerOf ( v . ж . SelfNodeV6MasqAddrForThisPeer )
2023-09-18 17:03:53 -07:00
}
2025-08-27 00:06:28 -07:00
// IsWireGuardOnly indicates that this is a non-Tailscale WireGuard peer, it
// is not expected to speak Disco or DERP, and it must have Endpoints in
// order to be reachable.
2023-09-14 10:04:31 -07:00
func ( v NodeView ) IsWireGuardOnly ( ) bool { return v . ж . IsWireGuardOnly }
2025-08-27 00:06:28 -07:00
// IsJailed indicates that this node is jailed and should not be allowed
// initiate connections, however outbound connections to it should still be
// allowed.
func ( v NodeView ) IsJailed ( ) bool { return v . ж . IsJailed }
// ExitNodeDNSResolvers is the list of DNS servers that should be used when this
// node is marked IsWireGuardOnly and being used as an exit node.
2023-09-14 10:04:31 -07:00
func ( v NodeView ) ExitNodeDNSResolvers ( ) views . SliceView [ * dnstype . Resolver , dnstype . ResolverView ] {
return views . SliceOfViews [ * dnstype . Resolver , dnstype . ResolverView ] ( v . ж . ExitNodeDNSResolvers )
}
2023-03-02 16:05:07 -08:00
func ( v NodeView ) Equal ( v2 NodeView ) bool { return v . ж . Equal ( v2 . ж ) }
2022-05-01 16:24:54 -07:00
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _NodeViewNeedsRegeneration = Node ( struct {
2023-03-02 16:05:07 -08:00
ID NodeID
StableID StableNodeID
Name string
User UserID
Sharer UserID
Key key . NodePublic
KeyExpiry time . Time
KeySignature tkatype . MarshaledSignature
Machine key . MachinePublic
DiscoKey key . DiscoPublic
Addresses [ ] netip . Prefix
AllowedIPs [ ] netip . Prefix
2023-09-30 21:05:02 -07:00
Endpoints [ ] netip . AddrPort
2025-01-14 10:19:52 -08:00
LegacyDERPString string
HomeDERP int
2023-03-02 16:05:07 -08:00
Hostinfo HostinfoView
Created time . Time
Cap CapabilityVersion
Tags [ ] string
PrimaryRoutes [ ] netip . Prefix
LastSeen * time . Time
Online * bool
MachineAuthorized bool
2023-09-06 10:17:25 -07:00
Capabilities [ ] NodeCapability
2023-09-18 08:52:22 -07:00
CapMap NodeCapMap
2023-03-02 16:05:07 -08:00
UnsignedPeerAPIOnly bool
ComputedName string
computedHostIfDifferent string
ComputedNameWithHost string
DataPlaneAuditLogID string
Expired bool
2023-04-13 10:12:31 -07:00
SelfNodeV4MasqAddrForThisPeer * netip . Addr
2023-09-18 17:03:53 -07:00
SelfNodeV6MasqAddrForThisPeer * netip . Addr
2023-04-05 17:28:28 -07:00
IsWireGuardOnly bool
2024-05-06 11:08:25 -07:00
IsJailed bool
2023-09-14 10:04:31 -07:00
ExitNodeDNSResolvers [ ] * dnstype . Resolver
2022-05-01 16:24:54 -07:00
} { } )
2025-01-14 08:15:27 -08:00
// View returns a read-only view of Hostinfo.
2022-05-01 16:24:54 -07:00
func ( p * Hostinfo ) View ( ) HostinfoView {
return HostinfoView { ж : p }
2022-05-01 16:23:55 -07:00
}
2022-05-01 16:24:54 -07:00
// HostinfoView provides a read-only view over Hostinfo.
//
// Its methods should only be called if `Valid()` returns true.
type HostinfoView 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.
ж * Hostinfo
}
2025-01-14 08:15:27 -08:00
// Valid reports whether v's underlying value is non-nil.
2022-05-01 16:24:54 -07:00
func ( v HostinfoView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v HostinfoView ) AsStruct ( ) * Hostinfo {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
2022-05-01 16:23:55 -07:00
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v HostinfoView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v HostinfoView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
2022-05-01 16:23:55 -07:00
2025-08-14 13:46:48 -07:00
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2022-05-01 16:24:54 -07:00
func ( v * HostinfoView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x Hostinfo
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * HostinfoView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x Hostinfo
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2022-05-01 16:24:54 -07:00
return err
}
v . ж = & x
return nil
}
2025-08-27 00:06:28 -07:00
// version of this code (in version.Long format)
func ( v HostinfoView ) IPNVersion ( ) string { return v . ж . IPNVersion }
// logtail ID of frontend instance
func ( v HostinfoView ) FrontendLogID ( ) string { return v . ж . FrontendLogID }
// logtail ID of backend instance
func ( v HostinfoView ) BackendLogID ( ) string { return v . ж . BackendLogID }
// operating system the client runs on (a version.OS value)
func ( v HostinfoView ) OS ( ) string { return v . ж . OS }
// OSVersion is the version of the OS, if available.
//
// For Android, it's like "10", "11", "12", etc. For iOS and macOS it's like
// "15.6.1" or "12.4.0". For Windows it's like "10.0.19044.1889". For
// FreeBSD it's like "12.3-STABLE".
//
// For Linux, prior to Tailscale 1.32, we jammed a bunch of fields into this
// string on Linux, like "Debian 10.4; kernel=xxx; container; env=kn" and so
// on. As of Tailscale 1.32, this is simply the kernel version on Linux, like
// "5.10.0-17-amd64".
func ( v HostinfoView ) OSVersion ( ) string { return v . ж . OSVersion }
// best-effort whether the client is running in a container
func ( v HostinfoView ) Container ( ) opt . Bool { return v . ж . Container }
// a hostinfo.EnvType in string form
func ( v HostinfoView ) Env ( ) string { return v . ж . Env }
// "debian", "ubuntu", "nixos", ...
func ( v HostinfoView ) Distro ( ) string { return v . ж . Distro }
// "20.04", ...
func ( v HostinfoView ) DistroVersion ( ) string { return v . ж . DistroVersion }
// "jammy", "bullseye", ...
func ( v HostinfoView ) DistroCodeName ( ) string { return v . ж . DistroCodeName }
// App is used to disambiguate Tailscale clients that run using tsnet.
func ( v HostinfoView ) App ( ) string { return v . ж . App }
// if a desktop was detected on Linux
func ( v HostinfoView ) Desktop ( ) opt . Bool { return v . ж . Desktop }
// Tailscale package to disambiguate ("choco", "appstore", etc; "" for unknown)
func ( v HostinfoView ) Package ( ) string { return v . ж . Package }
// mobile phone model ("Pixel 3a", "iPhone12,3")
func ( v HostinfoView ) DeviceModel ( ) string { return v . ж . DeviceModel }
// macOS/iOS APNs device token for notifications (and Android in the future)
func ( v HostinfoView ) PushDeviceToken ( ) string { return v . ж . PushDeviceToken }
// name of the host the client runs on
func ( v HostinfoView ) Hostname ( ) string { return v . ж . Hostname }
// indicates whether the host is blocking incoming connections
func ( v HostinfoView ) ShieldsUp ( ) bool { return v . ж . ShieldsUp }
// indicates this node exists in netmap because it's owned by a shared-to user
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 }
// 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
// foreground CLI serve sessions, for which they'd like it to work right
// away, even if it's disabled most of the time. As an optimization, this is
// only sent if IngressEnabled is false, as IngressEnabled implies that this
// option is true.
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
func ( v HostinfoView ) AllowsUpdate ( ) bool { return v . ж . AllowsUpdate }
// the current host's machine type (uname -m)
func ( v HostinfoView ) Machine ( ) string { return v . ж . Machine }
// GOARCH value (of the built binary)
func ( v HostinfoView ) GoArch ( ) string { return v . ж . GoArch }
// GOARM, GOAMD64, etc (of the built binary)
func ( v HostinfoView ) GoArchVar ( ) string { return v . ж . GoArchVar }
// Go version binary was built with
func ( v HostinfoView ) GoVersion ( ) string { return v . ж . GoVersion }
// set of IP ranges this client can route
2023-08-18 10:57:04 -07:00
func ( v HostinfoView ) RoutableIPs ( ) views . Slice [ netip . Prefix ] { return views . SliceOf ( v . ж . RoutableIPs ) }
2025-05-02 11:01:13 -07:00
2025-08-27 00:06:28 -07:00
// set of ACL tags this node wants to claim
func ( v HostinfoView ) RequestTags ( ) views . Slice [ string ] { return views . SliceOf ( v . ж . RequestTags ) }
// MAC address(es) to send Wake-on-LAN packets to wake this node (lowercase hex w/ colons)
func ( v HostinfoView ) WoLMACs ( ) views . Slice [ string ] { return views . SliceOf ( v . ж . WoLMACs ) }
// services advertised by this machine
func ( v HostinfoView ) Services ( ) views . Slice [ Service ] { return views . SliceOf ( v . ж . Services ) }
func ( v HostinfoView ) NetInfo ( ) NetInfoView { return v . ж . NetInfo . View ( ) }
// if advertised
func ( v HostinfoView ) SSH_HostKeys ( ) views . Slice [ string ] { return views . SliceOf ( v . ж . SSH_HostKeys ) }
func ( v HostinfoView ) Cloud ( ) string { return v . ж . Cloud }
// if the client is running in userspace (netstack) mode
func ( v HostinfoView ) Userspace ( ) opt . Bool { return v . ж . Userspace }
// if the client's subnet router is running in userspace (netstack) mode
func ( v HostinfoView ) UserspaceRouter ( ) opt . Bool { return v . ж . UserspaceRouter }
// if the client is running the app-connector service
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 }
// the client’ s selected exit node, empty when unselected.
func ( v HostinfoView ) ExitNodeID ( ) StableNodeID { return v . ж . ExitNodeID }
// Location represents geographical location data about a
// Tailscale host. Location is optional and only set if
// explicitly declared by a node.
func ( v HostinfoView ) Location ( ) LocationView { return v . ж . Location . View ( ) }
// TPM device metadata, if available
func ( v HostinfoView ) TPM ( ) views . ValuePointer [ TPMInfo ] { return views . ValuePointerOf ( v . ж . TPM ) }
// StateEncrypted reports whether the node state is stored encrypted on
// disk. The actual mechanism is platform-specific:
// - Apple nodes use the Keychain
// - Linux and Windows nodes use the TPM
// - Android apps use EncryptedSharedPreferences
2025-07-02 10:52:00 -07:00
func ( v HostinfoView ) StateEncrypted ( ) opt . Bool { return v . ж . StateEncrypted }
2025-05-02 11:01:13 -07:00
func ( v HostinfoView ) Equal ( v2 HostinfoView ) bool { return v . ж . Equal ( v2 . ж ) }
2022-05-01 16:24:54 -07:00
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _HostinfoViewNeedsRegeneration = Hostinfo ( struct {
2022-08-30 12:30:55 -07:00
IPNVersion string
FrontendLogID string
BackendLogID string
OS string
OSVersion string
2022-09-11 10:57:18 -07:00
Container opt . Bool
Env string
Distro string
DistroVersion string
DistroCodeName string
2023-02-27 09:58:54 -08:00
App string
2022-08-30 12:30:55 -07:00
Desktop opt . Bool
Package string
DeviceModel string
2023-01-29 14:04:40 -08:00
PushDeviceToken string
2022-08-30 12:30:55 -07:00
Hostname string
ShieldsUp bool
ShareeNode bool
2022-09-13 07:09:57 -07:00
NoLogsNoSupport bool
2022-11-15 20:30:53 -08:00
WireIngress bool
2025-01-21 05:17:27 +00:00
IngressEnabled bool
2023-01-21 10:04:43 -08:00
AllowsUpdate bool
2023-01-22 10:16:15 -08:00
Machine string
2022-08-30 12:30:55 -07:00
GoArch string
2023-01-22 10:16:15 -08:00
GoArchVar string
2022-08-30 12:30:55 -07:00
GoVersion string
RoutableIPs [ ] netip . Prefix
RequestTags [ ] string
2023-10-05 09:49:30 -07:00
WoLMACs [ ] string
2022-08-30 12:30:55 -07:00
Services [ ] Service
NetInfo * NetInfo
SSH_HostKeys [ ] string
Cloud string
Userspace opt . Bool
UserspaceRouter opt . Bool
2023-11-09 18:00:56 -08:00
AppConnector opt . Bool
2024-11-15 16:14:06 -05:00
ServicesHash string
2025-07-22 13:54:28 -07:00
ExitNodeID StableNodeID
2023-06-16 10:04:07 -07:00
Location * Location
2025-05-02 11:01:13 -07:00
TPM * TPMInfo
2025-07-02 10:52:00 -07:00
StateEncrypted opt . Bool
2022-05-01 16:24:54 -07:00
} { } )
2025-01-14 08:15:27 -08:00
// View returns a read-only view of NetInfo.
2022-05-01 16:24:54 -07:00
func ( p * NetInfo ) View ( ) NetInfoView {
return NetInfoView { ж : p }
}
// NetInfoView provides a read-only view over NetInfo.
//
// Its methods should only be called if `Valid()` returns true.
2022-05-01 16:23:55 -07:00
type NetInfoView struct {
2022-05-01 16:24:54 -07:00
// ж is the underlying mutable value, named with a hard-to-type
// character that looks pointy like a pointer.
2022-05-01 16:23:55 -07:00
// 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.
ж * NetInfo
}
2025-01-14 08:15:27 -08:00
// Valid reports whether v's underlying value is non-nil.
2022-05-01 16:23:55 -07:00
func ( v NetInfoView ) Valid ( ) bool { return v . ж != nil }
2022-05-01 16:24:54 -07:00
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v NetInfoView ) AsStruct ( ) * NetInfo {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v NetInfoView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v NetInfoView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
2022-05-01 16:24:54 -07:00
2025-08-14 13:46:48 -07:00
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2022-05-01 16:24:54 -07:00
func ( v * NetInfoView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x NetInfo
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * NetInfoView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x NetInfo
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2022-05-01 16:24:54 -07:00
return err
}
v . ж = & x
return nil
}
2022-05-01 16:23:55 -07:00
2025-08-27 00:06:28 -07:00
// MappingVariesByDestIP says whether the host's NAT mappings
// vary based on the destination IP.
2022-05-01 16:23:55 -07:00
func ( v NetInfoView ) MappingVariesByDestIP ( ) opt . Bool { return v . ж . MappingVariesByDestIP }
2022-05-09 09:30:39 -07:00
2025-08-27 00:06:28 -07:00
// HairPinning is their router does hairpinning.
// It reports true even if there's no NAT involved.
func ( v NetInfoView ) HairPinning ( ) opt . Bool { return v . ж . HairPinning }
// WorkingIPv6 is whether the host has IPv6 internet connectivity.
func ( v NetInfoView ) WorkingIPv6 ( ) opt . Bool { return v . ж . WorkingIPv6 }
// OSHasIPv6 is whether the OS supports IPv6 at all, regardless of
// whether IPv6 internet connectivity is available.
func ( v NetInfoView ) OSHasIPv6 ( ) opt . Bool { return v . ж . OSHasIPv6 }
// WorkingUDP is whether the host has UDP internet connectivity.
func ( v NetInfoView ) WorkingUDP ( ) opt . Bool { return v . ж . WorkingUDP }
// WorkingICMPv4 is whether ICMPv4 works.
// Empty means not checked.
func ( v NetInfoView ) WorkingICMPv4 ( ) opt . Bool { return v . ж . WorkingICMPv4 }
// HavePortMap is whether we have an existing portmap open
// (UPnP, PMP, or PCP).
func ( v NetInfoView ) HavePortMap ( ) bool { return v . ж . HavePortMap }
// UPnP is whether UPnP appears present on the LAN.
// Empty means not checked.
func ( v NetInfoView ) UPnP ( ) opt . Bool { return v . ж . UPnP }
// PMP is whether NAT-PMP appears present on the LAN.
// Empty means not checked.
func ( v NetInfoView ) PMP ( ) opt . Bool { return v . ж . PMP }
// PCP is whether PCP appears present on the LAN.
// Empty means not checked.
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
// 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 }
// LinkType is the current link type, if known.
func ( v NetInfoView ) LinkType ( ) string { return v . ж . LinkType }
// DERPLatency is the fastest recent time to reach various
// DERP STUN servers, in seconds. The map key is the
// "regionID-v4" or "-v6"; it was previously the DERP server's
// STUN host:port.
//
// This should only be updated rarely, or when there's a
// material change, as any change here also gets uploaded to
// the control plane.
2022-05-09 09:30:39 -07:00
func ( v NetInfoView ) DERPLatency ( ) views . Map [ string , float64 ] { return views . MapOf ( v . ж . DERPLatency ) }
2025-08-27 00:06:28 -07:00
// FirewallMode encodes both which firewall mode was selected and why.
// It is Linux-specific (at least as of 2023-08-19) and is meant to help
// debug iptables-vs-nftables issues. The string is of the form
// "{nft,ift}-REASON", like "nft-forced" or "ipt-default". Empty means
// either not Linux or a configuration in which the host firewall rules
// are not managed by tailscaled.
func ( v NetInfoView ) FirewallMode ( ) string { return v . ж . FirewallMode }
func ( v NetInfoView ) String ( ) string { return v . ж . String ( ) }
2022-05-01 16:23:55 -07:00
2022-05-01 16:24:54 -07:00
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _NetInfoViewNeedsRegeneration = NetInfo ( struct {
MappingVariesByDestIP opt . Bool
HairPinning opt . Bool
WorkingIPv6 opt . Bool
2022-07-18 16:56:10 -07:00
OSHasIPv6 opt . Bool
2022-05-01 16:24:54 -07:00
WorkingUDP opt . Bool
2022-08-04 17:10:13 -04:00
WorkingICMPv4 opt . Bool
2022-05-01 16:24:54 -07:00
HavePortMap bool
UPnP opt . Bool
PMP opt . Bool
PCP opt . Bool
PreferredDERP int
LinkType string
DERPLatency map [ string ] float64
2023-08-15 21:52:04 +00:00
FirewallMode string
2022-05-01 16:24:54 -07:00
} { } )
2025-01-14 08:15:27 -08:00
// View returns a read-only view of Login.
2022-05-01 16:24:54 -07:00
func ( p * Login ) View ( ) LoginView {
return LoginView { ж : p }
}
// LoginView provides a read-only view over Login.
//
// Its methods should only be called if `Valid()` returns true.
type LoginView 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.
ж * Login
}
2025-01-14 08:15:27 -08:00
// Valid reports whether v's underlying value is non-nil.
2022-05-01 16:24:54 -07:00
func ( v LoginView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v LoginView ) AsStruct ( ) * Login {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v LoginView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v LoginView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
2022-05-01 16:24:54 -07:00
2025-08-14 13:46:48 -07:00
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2022-05-01 16:24:54 -07:00
func ( v * LoginView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x Login
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * LoginView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x Login
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2022-05-01 16:24:54 -07:00
return err
2022-05-01 16:23:55 -07:00
}
2022-05-01 16:24:54 -07:00
v . ж = & x
return nil
}
2025-08-27 00:06:28 -07:00
// unused in the Tailscale client
func ( v LoginView ) ID ( ) LoginID { return v . ж . ID }
// "google", "github", "okta_foo", etc.
func ( v LoginView ) Provider ( ) string { return v . ж . Provider }
// an email address or "email-ish" string (like alice@github)
func ( v LoginView ) LoginName ( ) string { return v . ж . LoginName }
// from the IdP
func ( v LoginView ) DisplayName ( ) string { return v . ж . DisplayName }
// from the IdP
2022-05-01 16:24:54 -07:00
func ( v LoginView ) ProfilePicURL ( ) string { return v . ж . ProfilePicURL }
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _LoginViewNeedsRegeneration = Login ( struct {
_ structs . Incomparable
ID LoginID
Provider string
LoginName string
DisplayName string
ProfilePicURL string
} { } )
2025-01-14 08:15:27 -08:00
// View returns a read-only view of DNSConfig.
2022-05-01 16:24:54 -07:00
func ( p * DNSConfig ) View ( ) DNSConfigView {
return DNSConfigView { ж : p }
}
// DNSConfigView provides a read-only view over DNSConfig.
//
// Its methods should only be called if `Valid()` returns true.
type DNSConfigView 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.
ж * DNSConfig
2022-05-01 16:23:55 -07:00
}
2022-05-01 16:24:54 -07:00
2025-01-14 08:15:27 -08:00
// Valid reports whether v's underlying value is non-nil.
2022-05-01 16:24:54 -07:00
func ( v DNSConfigView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v DNSConfigView ) AsStruct ( ) * DNSConfig {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v DNSConfigView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v DNSConfigView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
2022-05-01 16:24:54 -07:00
2025-08-14 13:46:48 -07:00
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2022-05-01 16:24:54 -07:00
func ( v * DNSConfigView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x DNSConfig
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * DNSConfigView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x DNSConfig
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2022-05-01 16:24:54 -07:00
return err
}
v . ж = & x
return nil
}
2025-08-27 00:06:28 -07:00
// Resolvers are the DNS resolvers to use, in order of preference.
2022-05-01 16:24:54 -07:00
func ( v DNSConfigView ) Resolvers ( ) views . SliceView [ * dnstype . Resolver , dnstype . ResolverView ] {
return views . SliceOfViews [ * dnstype . Resolver , dnstype . ResolverView ] ( v . ж . Resolvers )
}
2022-05-09 09:30:39 -07:00
2025-08-27 00:06:28 -07:00
// 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 are fully-qualified DNS name suffixes; they may
// optionally contain a trailing dot but no leading dot.
//
// If the value is an empty slice, that means the suffix should still
// be handled by Tailscale's built-in resolver (100.100.100.100), such
// as for the purpose of handling ExtraRecords.
2022-05-09 09:30:39 -07:00
func ( v DNSConfigView ) Routes ( ) views . MapFn [ string , [ ] * 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 )
} )
}
2025-08-27 00:06:28 -07:00
// 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
2022-05-01 16:24:54 -07:00
func ( v DNSConfigView ) FallbackResolvers ( ) views . SliceView [ * dnstype . Resolver , dnstype . ResolverView ] {
return views . SliceOfViews [ * dnstype . Resolver , dnstype . ResolverView ] ( v . ж . FallbackResolvers )
}
2025-08-27 00:06:28 -07:00
// Domains are the search domains to use.
// Search domains must be FQDNs, but *without* the trailing dot.
func ( v DNSConfigView ) Domains ( ) views . Slice [ string ] { return views . SliceOf ( v . ж . Domains ) }
// Proxied turns on automatic resolution of hostnames for devices
// in the network map, aka MagicDNS.
// Despite the (legacy) name, does not necessarily cause request
// proxying to be enabled.
func ( v DNSConfigView ) Proxied ( ) bool { return v . ж . Proxied }
// Nameservers are the IP addresses of the global nameservers to use.
//
// Deprecated: this is only set and used by MapRequest.Version >=9 and <14. Use Resolvers instead.
2022-07-24 20:08:42 -07:00
func ( v DNSConfigView ) Nameservers ( ) views . Slice [ netip . Addr ] { return views . SliceOf ( v . ж . Nameservers ) }
2025-08-27 00:06:28 -07:00
// CertDomains are the set of DNS names for which the control
// plane server will assist with provisioning TLS
// certificates. See SetDNSRequest, which can be used to
// answer dns-01 ACME challenges for e.g. LetsEncrypt.
// These names are FQDNs without trailing periods, and without
// any "_acme-challenge." prefix.
func ( v DNSConfigView ) CertDomains ( ) views . Slice [ string ] { return views . SliceOf ( v . ж . CertDomains ) }
// ExtraRecords contains extra DNS records to add to the
// MagicDNS config.
2022-05-01 16:24:54 -07:00
func ( v DNSConfigView ) ExtraRecords ( ) views . Slice [ DNSRecord ] { return views . SliceOf ( v . ж . ExtraRecords ) }
2025-08-27 00:06:28 -07:00
// ExitNodeFilteredSuffixes are the DNS suffixes that the
// node, when being an exit node DNS proxy, should not answer.
//
// The entries do not contain trailing periods and are always
// all lowercase.
//
// If an entry starts with a period, it's a suffix match (but
// suffix ".a.b" doesn't match "a.b"; a prefix is required).
//
// If an entry does not start with a period, it's an exact
// match.
//
// Matches are case insensitive.
2022-05-01 16:24:54 -07:00
func ( v DNSConfigView ) ExitNodeFilteredSet ( ) views . Slice [ string ] {
return views . SliceOf ( v . ж . ExitNodeFilteredSet )
}
2025-08-27 00:06:28 -07:00
// TempCorpIssue13969 is a temporary (2023-08-16) field for an internal hack day prototype.
// It contains a user inputed URL that should have a list of domains to be blocked.
// See https://github.com/tailscale/corp/issues/13969.
2023-08-16 15:27:33 -07:00
func ( v DNSConfigView ) TempCorpIssue13969 ( ) string { return v . ж . TempCorpIssue13969 }
2022-05-01 16:24:54 -07:00
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _DNSConfigViewNeedsRegeneration = DNSConfig ( struct {
Resolvers [ ] * dnstype . Resolver
Routes map [ string ] [ ] * dnstype . Resolver
FallbackResolvers [ ] * dnstype . Resolver
Domains [ ] string
Proxied bool
2022-07-24 20:08:42 -07:00
Nameservers [ ] netip . Addr
2022-05-01 16:24:54 -07:00
CertDomains [ ] string
ExtraRecords [ ] DNSRecord
ExitNodeFilteredSet [ ] string
2023-08-16 15:27:33 -07:00
TempCorpIssue13969 string
2022-05-01 16:24:54 -07:00
} { } )
2025-01-14 08:15:27 -08:00
// View returns a read-only view of RegisterResponse.
2022-05-01 16:24:54 -07:00
func ( p * RegisterResponse ) View ( ) RegisterResponseView {
return RegisterResponseView { ж : p }
}
// RegisterResponseView provides a read-only view over RegisterResponse.
//
// Its methods should only be called if `Valid()` returns true.
type RegisterResponseView 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.
ж * RegisterResponse
}
2025-01-14 08:15:27 -08:00
// Valid reports whether v's underlying value is non-nil.
2022-05-01 16:24:54 -07:00
func ( v RegisterResponseView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v RegisterResponseView ) AsStruct ( ) * RegisterResponse {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v RegisterResponseView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v RegisterResponseView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
2022-05-01 16:24:54 -07:00
2025-08-14 13:46:48 -07:00
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2022-05-01 16:24:54 -07:00
func ( v * RegisterResponseView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x RegisterResponse
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * RegisterResponseView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x RegisterResponse
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2022-05-01 16:24:54 -07:00
return err
}
v . ж = & x
return nil
}
2025-08-27 00:06:28 -07:00
func ( v RegisterResponseView ) User ( ) User { return v . ж . User }
func ( v RegisterResponseView ) Login ( ) Login { return v . ж . Login }
// if true, the NodeKey needs to be replaced
func ( v RegisterResponseView ) NodeKeyExpired ( ) bool { return v . ж . NodeKeyExpired }
// TODO(crawshaw): move to using MachineStatus
2023-08-20 14:35:39 -04:00
func ( v RegisterResponseView ) MachineAuthorized ( ) bool { return v . ж . MachineAuthorized }
2025-08-27 00:06:28 -07:00
// if set, authorization pending
func ( v RegisterResponseView ) AuthURL ( ) string { return v . ж . AuthURL }
// If set, this is the current node-key signature that needs to be
// re-signed for the node's new node-key.
2023-08-20 14:35:39 -04:00
func ( v RegisterResponseView ) NodeKeySignature ( ) views . ByteSlice [ tkatype . MarshaledSignature ] {
return views . ByteSliceOf ( v . ж . NodeKeySignature )
}
2025-08-27 00:06:28 -07:00
// Error indicates that authorization failed. If this is non-empty,
// other status fields should be ignored.
2023-08-20 14:35:39 -04:00
func ( v RegisterResponseView ) Error ( ) string { return v . ж . Error }
2022-05-01 16:24:54 -07:00
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _RegisterResponseViewNeedsRegeneration = RegisterResponse ( struct {
User User
Login Login
NodeKeyExpired bool
MachineAuthorized bool
AuthURL string
2022-10-13 10:43:00 -07:00
NodeKeySignature tkatype . MarshaledSignature
2022-05-01 16:24:54 -07:00
Error string
} { } )
2025-01-14 08:15:27 -08:00
// View returns a read-only view of RegisterResponseAuth.
2023-08-19 23:14:32 -04:00
func ( p * RegisterResponseAuth ) View ( ) RegisterResponseAuthView {
return RegisterResponseAuthView { ж : p }
}
// RegisterResponseAuthView provides a read-only view over RegisterResponseAuth.
//
// Its methods should only be called if `Valid()` returns true.
type RegisterResponseAuthView 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.
ж * RegisterResponseAuth
}
2025-01-14 08:15:27 -08:00
// Valid reports whether v's underlying value is non-nil.
2023-08-19 23:14:32 -04:00
func ( v RegisterResponseAuthView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v RegisterResponseAuthView ) AsStruct ( ) * RegisterResponseAuth {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v RegisterResponseAuthView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v RegisterResponseAuthView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
2023-08-19 23:14:32 -04:00
2025-08-14 13:46:48 -07:00
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2023-08-19 23:14:32 -04:00
func ( v * RegisterResponseAuthView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x RegisterResponseAuth
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * RegisterResponseAuthView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x RegisterResponseAuth
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2023-08-19 23:14:32 -04:00
return err
}
v . ж = & x
return nil
}
2025-08-27 00:06:28 -07:00
// used by pre-1.66 Android only
2025-01-08 17:21:44 -06:00
func ( v RegisterResponseAuthView ) Oauth2Token ( ) views . ValuePointer [ Oauth2Token ] {
return views . ValuePointerOf ( v . ж . Oauth2Token )
2023-08-19 23:14:32 -04:00
}
func ( v RegisterResponseAuthView ) AuthKey ( ) string { return v . ж . AuthKey }
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _RegisterResponseAuthViewNeedsRegeneration = RegisterResponseAuth ( struct {
_ structs . Incomparable
Oauth2Token * Oauth2Token
AuthKey string
} { } )
2025-01-14 08:15:27 -08:00
// View returns a read-only view of RegisterRequest.
2023-08-19 23:14:32 -04:00
func ( p * RegisterRequest ) View ( ) RegisterRequestView {
return RegisterRequestView { ж : p }
}
// RegisterRequestView provides a read-only view over RegisterRequest.
//
// Its methods should only be called if `Valid()` returns true.
type RegisterRequestView 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.
ж * RegisterRequest
}
2025-01-14 08:15:27 -08:00
// Valid reports whether v's underlying value is non-nil.
2023-08-19 23:14:32 -04:00
func ( v RegisterRequestView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v RegisterRequestView ) AsStruct ( ) * RegisterRequest {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v RegisterRequestView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v RegisterRequestView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
2023-08-19 23:14:32 -04:00
2025-08-14 13:46:48 -07:00
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2023-08-19 23:14:32 -04:00
func ( v * RegisterRequestView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x RegisterRequest
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * RegisterRequestView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x RegisterRequest
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2023-08-19 23:14:32 -04:00
return err
}
v . ж = & x
return nil
}
2025-08-27 00:06:28 -07:00
// Version is the client's capabilities when using the Noise
// transport.
//
// When using the original nacl crypto_box transport, the
// value must be 1.
2023-08-19 23:14:32 -04:00
func ( v RegisterRequestView ) Version ( ) CapabilityVersion { return v . ж . Version }
func ( v RegisterRequestView ) NodeKey ( ) key . NodePublic { return v . ж . NodeKey }
func ( v RegisterRequestView ) OldNodeKey ( ) key . NodePublic { return v . ж . OldNodeKey }
func ( v RegisterRequestView ) NLKey ( ) key . NLPublic { return v . ж . NLKey }
func ( v RegisterRequestView ) Auth ( ) RegisterResponseAuthView { return v . ж . Auth . View ( ) }
2025-08-27 00:06:28 -07:00
// Expiry optionally specifies the requested key expiry.
// The server policy may override.
// As a special case, if Expiry is in the past and NodeKey is
// the node's current key, the key is expired.
func ( v RegisterRequestView ) Expiry ( ) time . Time { return v . ж . Expiry }
// response waits until AuthURL is visited
func ( v RegisterRequestView ) Followup ( ) string { return v . ж . Followup }
func ( v RegisterRequestView ) Hostinfo ( ) HostinfoView { return v . ж . Hostinfo . View ( ) }
// Ephemeral is whether the client is requesting that this
// node be considered ephemeral and be automatically deleted
// when it stops being active.
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.
//
// This field is set when the client retries registration after learning
// its NodeKeySignature (which is in need of rotation).
2023-08-20 14:35:39 -04:00
func ( v RegisterRequestView ) NodeKeySignature ( ) views . ByteSlice [ tkatype . MarshaledSignature ] {
return views . ByteSliceOf ( v . ж . NodeKeySignature )
}
2025-08-27 00:06:28 -07:00
// The following fields are not used for SignatureNone and are required for
// SignatureV1:
2023-08-20 14:35:39 -04:00
func ( v RegisterRequestView ) SignatureType ( ) SignatureType { return v . ж . SignatureType }
2025-08-27 00:06:28 -07:00
// creation time of request to prevent replay
2025-01-08 17:21:44 -06:00
func ( v RegisterRequestView ) Timestamp ( ) views . ValuePointer [ time . Time ] {
return views . ValuePointerOf ( v . ж . Timestamp )
2023-08-19 23:14:32 -04:00
}
2025-08-27 00:06:28 -07:00
// X.509 certificate for client device
2023-08-20 14:35:39 -04:00
func ( v RegisterRequestView ) DeviceCert ( ) views . ByteSlice [ [ ] byte ] {
return views . ByteSliceOf ( v . ж . DeviceCert )
}
2025-08-27 00:06:28 -07:00
// as described by SignatureType
2023-08-20 14:35:39 -04:00
func ( v RegisterRequestView ) Signature ( ) views . ByteSlice [ [ ] byte ] {
return views . ByteSliceOf ( v . ж . Signature )
}
2025-08-27 00:06:28 -07:00
// Tailnet is an optional identifier specifying the name of the recommended or required
// network that the node should join. Its exact form should not be depended on; new
// forms are coming later. The identifier is generally a domain name (for an organization)
// or e-mail address (for a personal account on a shared e-mail provider). It is the same name
// used by the API, as described in /api.md#tailnet.
// If Tailnet begins with the prefix "required:" then the server should prevent logging in to a different
// network than the one specified. Otherwise, the server should recommend the specified network
// but still permit logging in to other networks.
// If empty, no recommendation is offered to the server and the login page should show all options.
2023-10-13 14:13:41 -04:00
func ( v RegisterRequestView ) Tailnet ( ) string { return v . ж . Tailnet }
2023-08-19 23:14:32 -04:00
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _RegisterRequestViewNeedsRegeneration = RegisterRequest ( struct {
_ structs . Incomparable
Version CapabilityVersion
NodeKey key . NodePublic
OldNodeKey key . NodePublic
NLKey key . NLPublic
2024-04-20 10:04:04 -07:00
Auth * RegisterResponseAuth
2023-08-19 23:14:32 -04:00
Expiry time . Time
Followup string
Hostinfo * Hostinfo
Ephemeral bool
NodeKeySignature tkatype . MarshaledSignature
SignatureType SignatureType
Timestamp * time . Time
DeviceCert [ ] byte
Signature [ ] byte
2023-10-13 14:13:41 -04:00
Tailnet string
2023-08-19 23:14:32 -04:00
} { } )
2025-01-14 08:15:27 -08:00
// View returns a read-only view of DERPHomeParams.
2023-07-12 14:45:46 -04:00
func ( p * DERPHomeParams ) View ( ) DERPHomeParamsView {
return DERPHomeParamsView { ж : p }
}
// DERPHomeParamsView provides a read-only view over DERPHomeParams.
//
// Its methods should only be called if `Valid()` returns true.
type DERPHomeParamsView 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.
ж * DERPHomeParams
}
2025-01-14 08:15:27 -08:00
// Valid reports whether v's underlying value is non-nil.
2023-07-12 14:45:46 -04:00
func ( v DERPHomeParamsView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v DERPHomeParamsView ) AsStruct ( ) * DERPHomeParams {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v DERPHomeParamsView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v DERPHomeParamsView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
2023-07-12 14:45:46 -04:00
2025-08-14 13:46:48 -07:00
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2023-07-12 14:45:46 -04:00
func ( v * DERPHomeParamsView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x DERPHomeParams
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * DERPHomeParamsView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x DERPHomeParams
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2023-07-12 14:45:46 -04:00
return err
}
v . ж = & x
return nil
}
2025-08-27 00:06:28 -07:00
// RegionScore scales latencies of DERP regions by a given scaling
// factor when determining which region to use as the home
// ("preferred") DERP. Scores in the range (0, 1) will cause this
// region to be proportionally more preferred, and scores in the range
// (1, ∞) will penalize a region.
//
// If a region is not present in this map, it is treated as having a
// score of 1.0.
//
// Scores should not be 0 or negative; such scores will be ignored.
//
// 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.
2023-07-12 14:45:46 -04:00
func ( v DERPHomeParamsView ) RegionScore ( ) views . Map [ int , 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
} { } )
2025-01-14 08:15:27 -08:00
// View returns a read-only view of DERPRegion.
2022-05-01 16:24:54 -07:00
func ( p * DERPRegion ) View ( ) DERPRegionView {
return DERPRegionView { ж : p }
}
// DERPRegionView provides a read-only view over DERPRegion.
//
// Its methods should only be called if `Valid()` returns true.
type DERPRegionView 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.
ж * DERPRegion
}
2025-01-14 08:15:27 -08:00
// Valid reports whether v's underlying value is non-nil.
2022-05-01 16:24:54 -07:00
func ( v DERPRegionView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v DERPRegionView ) AsStruct ( ) * DERPRegion {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v DERPRegionView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v DERPRegionView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
2022-05-01 16:24:54 -07:00
2025-08-14 13:46:48 -07:00
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2022-05-01 16:24:54 -07:00
func ( v * DERPRegionView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x DERPRegion
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * DERPRegionView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x DERPRegion
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2022-05-01 16:24:54 -07:00
return err
}
v . ж = & x
return nil
}
2025-08-27 00:06:28 -07:00
// RegionID 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)
//
// RegionIDs must be non-zero, positive, and guaranteed to fit
// in a JavaScript number.
//
// RegionIDs in range 900-999 are reserved for end users to run their
// own DERP nodes.
func ( v DERPRegionView ) RegionID ( ) int { 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",
// "fra", etc.
func ( v DERPRegionView ) RegionCode ( ) string { return v . ж . RegionCode }
// RegionName is a long English name for the region: "New York City",
// "San Francisco", "Singapore", "Frankfurt", etc.
func ( v DERPRegionView ) RegionName ( ) string { return v . ж . RegionName }
// Latitude, Longitude are optional geographical coordinates of the DERP region's city, in degrees.
func ( v DERPRegionView ) Latitude ( ) float64 { return v . ж . Latitude }
func ( v DERPRegionView ) Longitude ( ) float64 { return v . ж . Longitude }
// Avoid is whether the client should avoid picking this as its home region.
// The region should only be used if a peer is there. Clients already using
// this region as their home should migrate away to a new region without
// Avoid set.
//
// Deprecated: because of bugs in past implementations combined with unclear
// docs that caused people to think the bugs were intentional, this field is
// deprecated. It was never supposed to cause STUN/DERP measurement probes,
// but due to bugs, it sometimes did. And then some parts of the code began
// to rely on that property. But then we were unable to use this field for
// its original purpose, nor its later imagined purpose, because various
// parts of the codebase thought it meant one thing and others thought it
// meant another. But it did something in the middle instead. So we're retiring
// it. Use NoMeasureNoHome instead.
func ( v DERPRegionView ) Avoid ( ) bool { return v . ж . Avoid }
// NoMeasureNoHome says that this regions should not be measured for its
// latency distance (STUN, HTTPS, etc) or availability (e.g. captive portal
// checks) and should never be selected as the node's home region. However,
// if a peer declares this region as its home, then this client is allowed
// to connect to it for the purpose of communicating with that peer.
//
// This is what the now deprecated Avoid bool was supposed to mean
// originally but had implementation bugs and documentation omissions.
2025-03-07 17:12:07 -07:00
func ( v DERPRegionView ) NoMeasureNoHome ( ) bool { return v . ж . NoMeasureNoHome }
2025-08-27 00:06:28 -07:00
// Nodes are the DERP nodes running in this region, in
// priority order for the current client. Client TLS
// connections should ideally only go to the first entry
// (falling back to the second if necessary). STUN packets
// should go to the first 1 or 2.
//
// If nodes within a region route packets amongst themselves,
// but not to other regions. That said, each user/domain
// should get a the same preferred node order, so if all nodes
// for a user/network pick the first one (as they should, when
// things are healthy), the inter-cluster routing is minimal
// to zero.
2022-05-01 16:24:54 -07:00
func ( v DERPRegionView ) Nodes ( ) views . SliceView [ * DERPNode , DERPNodeView ] {
return views . SliceOfViews [ * DERPNode , DERPNodeView ] ( v . ж . Nodes )
}
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _DERPRegionViewNeedsRegeneration = DERPRegion ( struct {
2025-03-07 17:12:07 -07:00
RegionID int
RegionCode string
RegionName string
Latitude float64
Longitude float64
Avoid bool
NoMeasureNoHome bool
Nodes [ ] * DERPNode
2022-05-01 16:24:54 -07:00
} { } )
2025-01-14 08:15:27 -08:00
// View returns a read-only view of DERPMap.
2022-05-01 16:24:54 -07:00
func ( p * DERPMap ) View ( ) DERPMapView {
return DERPMapView { ж : p }
}
// DERPMapView provides a read-only view over DERPMap.
//
// Its methods should only be called if `Valid()` returns true.
type DERPMapView 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.
ж * DERPMap
}
2025-01-14 08:15:27 -08:00
// Valid reports whether v's underlying value is non-nil.
2022-05-01 16:24:54 -07:00
func ( v DERPMapView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v DERPMapView ) AsStruct ( ) * DERPMap {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v DERPMapView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v DERPMapView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
2022-05-01 16:24:54 -07:00
2025-08-14 13:46:48 -07:00
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2022-05-01 16:24:54 -07:00
func ( v * DERPMapView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x DERPMap
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * DERPMapView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x DERPMap
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2022-05-01 16:24:54 -07:00
return err
}
v . ж = & x
return nil
}
2025-08-27 00:06:28 -07:00
// HomeParams, if non-nil, is a change in home parameters.
//
// The rest of the DEPRMap fields, if zero, means unchanged.
2023-07-12 14:45:46 -04:00
func ( v DERPMapView ) HomeParams ( ) DERPHomeParamsView { return v . ж . HomeParams . View ( ) }
2025-08-27 00:06:28 -07:00
// Regions is the set of geographic regions running DERP node(s).
//
// It's keyed by the DERPRegion.RegionID.
//
// The numbers are not necessarily contiguous.
2022-05-09 09:30:39 -07:00
func ( v DERPMapView ) Regions ( ) views . MapFn [ int , * DERPRegion , DERPRegionView ] {
return views . MapFnOf ( v . ж . Regions , func ( t * DERPRegion ) DERPRegionView {
return t . View ( )
} )
}
2025-08-27 00:06:28 -07:00
// 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.
//
// This field is only meaningful if the Regions map is non-nil (indicating a change).
2022-05-01 16:24:54 -07:00
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 {
2023-07-12 14:45:46 -04:00
HomeParams * DERPHomeParams
2022-05-01 16:24:54 -07:00
Regions map [ int ] * DERPRegion
OmitDefaultRegions bool
} { } )
2025-01-14 08:15:27 -08:00
// View returns a read-only view of DERPNode.
2022-05-01 16:24:54 -07:00
func ( p * DERPNode ) View ( ) DERPNodeView {
return DERPNodeView { ж : p }
}
// DERPNodeView provides a read-only view over DERPNode.
//
// Its methods should only be called if `Valid()` returns true.
type DERPNodeView 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.
ж * DERPNode
}
2025-01-14 08:15:27 -08:00
// Valid reports whether v's underlying value is non-nil.
2022-05-01 16:24:54 -07:00
func ( v DERPNodeView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v DERPNodeView ) AsStruct ( ) * DERPNode {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v DERPNodeView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v DERPNodeView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
2022-05-01 16:24:54 -07:00
2025-08-14 13:46:48 -07:00
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2022-05-01 16:24:54 -07:00
func ( v * DERPNodeView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x DERPNode
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * DERPNodeView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x DERPNode
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2022-05-01 16:24:54 -07:00
return err
}
v . ж = & x
return nil
}
2025-08-27 00:06:28 -07:00
// Name is a unique node name (across all regions).
// It is not a host name.
// It's typically of the form "1b", "2a", "3b", etc. (region
// ID + suffix within that region)
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 }
// HostName is the DERP node's hostname.
//
// It is required but need not be unique; multiple nodes may
// have the same HostName but vary in configuration otherwise.
func ( v DERPNodeView ) HostName ( ) string { return v . ж . HostName }
// CertName optionally specifies the expected TLS cert common
// name. If empty, HostName is used. If CertName is non-empty,
// HostName is only used for the TCP dial (if IPv4/IPv6 are
// not present) + TLS ClientHello.
//
// As a special case, if CertName starts with "sha256-raw:",
// then the rest of the string is a hex-encoded SHA256 of the
// cert to expect. This is used for self-signed certs.
// In this case, the HostName field will typically be an IP
// address literal.
func ( v DERPNodeView ) CertName ( ) string { return v . ж . CertName }
// IPv4 optionally forces an IPv4 address to use, instead of using DNS.
// If empty, A record(s) from DNS lookups of HostName are used.
// If the string is not an IPv4 address, IPv4 is not used; the
// conventional string to disable IPv4 (and not use DNS) is
// "none".
func ( v DERPNodeView ) IPv4 ( ) string { return v . ж . IPv4 }
// IPv6 optionally forces an IPv6 address to use, instead of using DNS.
// If empty, AAAA record(s) from DNS lookups of HostName are used.
// If the string is not an IPv6 address, IPv6 is not used; the
// conventional string to disable IPv6 (and not use DNS) is
// "none".
func ( v DERPNodeView ) IPv6 ( ) string { return v . ж . IPv6 }
// Port optionally specifies a STUN port to use.
// Zero means 3478.
// To disable STUN on this node, use -1.
func ( v DERPNodeView ) STUNPort ( ) int { return v . ж . STUNPort }
// STUNOnly marks a node as only a STUN server and not a DERP
// server.
func ( v DERPNodeView ) STUNOnly ( ) bool { return v . ж . STUNOnly }
// DERPPort optionally provides an alternate TLS port number
// for the DERP HTTPS server.
//
// If zero, 443 is used.
func ( v DERPNodeView ) DERPPort ( ) int { return v . ж . DERPPort }
// InsecureForTests is used by unit tests to disable TLS verification.
// It should not be set by users.
2022-05-01 16:24:54 -07:00
func ( v DERPNodeView ) InsecureForTests ( ) bool { return v . ж . InsecureForTests }
2025-08-27 00:06:28 -07:00
// STUNTestIP is used in tests to override the STUN server's IP.
// If empty, it's assumed to be the same as the DERP server.
func ( v DERPNodeView ) STUNTestIP ( ) string { return v . ж . STUNTestIP }
// CanPort80 specifies whether this DERP node is accessible over HTTP
// on port 80 specifically. This is used for captive portal checks.
func ( v DERPNodeView ) CanPort80 ( ) bool { return v . ж . CanPort80 }
2022-05-01 16:24:54 -07:00
// 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
HostName string
CertName string
IPv4 string
IPv6 string
STUNPort int
STUNOnly bool
DERPPort int
InsecureForTests bool
STUNTestIP string
2023-04-20 10:21:46 -04:00
CanPort80 bool
2022-05-01 16:24:54 -07:00
} { } )
2022-07-26 20:48:38 -07:00
2025-01-14 08:15:27 -08:00
// View returns a read-only view of SSHRule.
2022-07-26 20:48:38 -07:00
func ( p * SSHRule ) View ( ) SSHRuleView {
return SSHRuleView { ж : p }
}
// SSHRuleView provides a read-only view over SSHRule.
//
// Its methods should only be called if `Valid()` returns true.
type SSHRuleView 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.
ж * SSHRule
}
2025-01-14 08:15:27 -08:00
// Valid reports whether v's underlying value is non-nil.
2022-07-26 20:48:38 -07:00
func ( v SSHRuleView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v SSHRuleView ) AsStruct ( ) * SSHRule {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v SSHRuleView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v SSHRuleView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
2022-07-26 20:48:38 -07:00
2025-08-14 13:46:48 -07:00
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2022-07-26 20:48:38 -07:00
func ( v * SSHRuleView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x SSHRule
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * SSHRuleView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x SSHRule
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2022-07-26 20:48:38 -07:00
return err
}
v . ж = & x
return nil
}
2025-08-27 00:06:28 -07:00
// RuleExpires, if non-nil, is when this rule expires.
//
// For example, a (principal,sshuser) tuple might be granted
// prompt-free SSH access for N minutes, so this rule would be
// before a expiration-free rule for the same principal that
// required an auth prompt. This permits the control plane to
// be out of the path for already-authorized SSH pairs.
//
// Once a rule matches, the lifetime of any accepting connection
// is subject to the SSHAction.SessionExpires time, if any.
2025-01-08 17:21:44 -06:00
func ( v SSHRuleView ) RuleExpires ( ) views . ValuePointer [ time . Time ] {
return views . ValuePointerOf ( v . ж . RuleExpires )
2022-07-26 20:48:38 -07:00
}
2025-08-27 00:06:28 -07:00
// Principals matches an incoming connection. If the connection
// matches anything in this list and also matches SSHUsers,
// then Action is applied.
2022-07-26 20:48:38 -07:00
func ( v SSHRuleView ) Principals ( ) views . SliceView [ * SSHPrincipal , SSHPrincipalView ] {
return views . SliceOfViews [ * SSHPrincipal , SSHPrincipalView ] ( v . ж . Principals )
}
2025-08-27 00:06:28 -07:00
// SSHUsers are the SSH users that this rule matches. It is a
// map from either ssh-user|"*" => local-user. The map must
// contain a key for either ssh-user or, as a fallback, "*" to
// match anything. If it does, the map entry's value is the
// actual user that's logged in.
// If the map value is the empty string (for either the
// requested SSH user or "*"), the rule doesn't match.
// If the map value is "=", it means the ssh-user should map
// directly to the local-user.
// It may be nil if the Action is reject.
2022-07-26 20:48:38 -07:00
func ( v SSHRuleView ) SSHUsers ( ) views . Map [ string , string ] { return views . MapOf ( v . ж . SSHUsers ) }
2025-08-27 00:06:28 -07:00
// Action is the outcome to task.
// A nil or invalid action means to deny.
func ( v SSHRuleView ) Action ( ) SSHActionView { return v . ж . Action . View ( ) }
// AcceptEnv is a slice of environment variable names that are allowlisted
// for the SSH rule in the policy file.
//
// AcceptEnv values may contain * and ? wildcard characters which match against
// an arbitrary number of characters or a single character respectively.
func ( v SSHRuleView ) AcceptEnv ( ) views . Slice [ string ] { return views . SliceOf ( v . ж . AcceptEnv ) }
2023-03-21 12:29:24 -07:00
2022-07-26 20:48:38 -07:00
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _SSHRuleViewNeedsRegeneration = SSHRule ( struct {
RuleExpires * time . Time
Principals [ ] * SSHPrincipal
SSHUsers map [ string ] string
Action * SSHAction
2024-09-22 20:15:26 -06:00
AcceptEnv [ ] string
2023-03-21 12:59:05 -07:00
} { } )
2025-01-14 08:15:27 -08:00
// View returns a read-only view of SSHAction.
2023-03-21 12:59:05 -07:00
func ( p * SSHAction ) View ( ) SSHActionView {
return SSHActionView { ж : p }
}
// SSHActionView provides a read-only view over SSHAction.
//
// Its methods should only be called if `Valid()` returns true.
type SSHActionView 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.
ж * SSHAction
}
2025-01-14 08:15:27 -08:00
// Valid reports whether v's underlying value is non-nil.
2023-03-21 12:59:05 -07:00
func ( v SSHActionView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v SSHActionView ) AsStruct ( ) * SSHAction {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v SSHActionView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v SSHActionView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
2023-03-21 12:59:05 -07:00
2025-08-14 13:46:48 -07:00
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2023-03-21 12:59:05 -07:00
func ( v * SSHActionView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x SSHAction
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * SSHActionView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x SSHAction
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2023-03-21 12:59:05 -07:00
return err
}
v . ж = & x
return nil
}
2025-08-27 00:06:28 -07:00
// Message, if non-empty, is shown to the user before the
// action occurs.
func ( v SSHActionView ) Message ( ) string { return v . ж . Message }
// Reject, if true, terminates the connection. This action
// has higher priority that Accept, if given.
// The reason this is exists is primarily so a response
// from HoldAndDelegate has a way to stop the poll.
func ( v SSHActionView ) Reject ( ) bool { return v . ж . Reject }
// Accept, if true, accepts the connection immediately
// without further prompts.
func ( v SSHActionView ) Accept ( ) bool { return v . ж . Accept }
// SessionDuration, if non-zero, is how long the session can stay open
// before being forcefully terminated.
func ( v SSHActionView ) SessionDuration ( ) time . Duration { return v . ж . SessionDuration }
// AllowAgentForwarding, if true, allows accepted connections to forward
// the ssh agent if requested.
func ( v SSHActionView ) AllowAgentForwarding ( ) bool { return v . ж . AllowAgentForwarding }
// HoldAndDelegate, if non-empty, is a URL that serves an
// outcome verdict. The connection will be accepted and will
// block until the provided long-polling URL serves a new
// SSHAction JSON value. The URL must be fetched using the
// Noise transport (in package control/control{base,http}).
// If the long poll breaks before returning a complete HTTP
// response, it should be re-fetched as long as the SSH
// session is open.
//
// The following variables in the URL are expanded by tailscaled:
//
// - $SRC_NODE_IP (URL escaped)
// - $SRC_NODE_ID (Node.ID as int64 string)
// - $DST_NODE_IP (URL escaped)
// - $DST_NODE_ID (Node.ID as int64 string)
// - $SSH_USER (URL escaped, ssh user requested)
// - $LOCAL_USER (URL escaped, local user mapped)
func ( v SSHActionView ) HoldAndDelegate ( ) string { return v . ж . HoldAndDelegate }
// AllowLocalPortForwarding, if true, allows accepted connections
// to use local port forwarding if requested.
func ( v SSHActionView ) AllowLocalPortForwarding ( ) bool { return v . ж . AllowLocalPortForwarding }
// AllowRemotePortForwarding, if true, allows accepted connections
// to use remote port forwarding if requested.
func ( v SSHActionView ) AllowRemotePortForwarding ( ) bool { return v . ж . AllowRemotePortForwarding }
// Recorders defines the destinations of the SSH session recorders.
// The recording will be uploaded to http://addr:port/record.
2023-03-21 12:59:05 -07:00
func ( v SSHActionView ) Recorders ( ) views . Slice [ netip . AddrPort ] { return views . SliceOf ( v . ж . Recorders ) }
2025-08-27 00:06:28 -07:00
// OnRecorderFailure is the action to take if recording fails.
// If nil, the default action is to fail open.
2025-01-08 17:21:44 -06:00
func ( v SSHActionView ) OnRecordingFailure ( ) views . ValuePointer [ SSHRecorderFailureAction ] {
return views . ValuePointerOf ( v . ж . OnRecordingFailure )
2023-04-19 21:10:55 -07:00
}
2023-03-21 12:59:05 -07:00
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _SSHActionViewNeedsRegeneration = SSHAction ( struct {
2023-06-08 18:39:27 -07:00
Message string
Reject bool
Accept bool
SessionDuration time . Duration
AllowAgentForwarding bool
HoldAndDelegate string
AllowLocalPortForwarding bool
AllowRemotePortForwarding bool
Recorders [ ] netip . AddrPort
OnRecordingFailure * SSHRecorderFailureAction
2022-07-26 20:48:38 -07:00
} { } )
2025-01-14 08:15:27 -08:00
// View returns a read-only view of SSHPrincipal.
2022-07-26 20:48:38 -07:00
func ( p * SSHPrincipal ) View ( ) SSHPrincipalView {
return SSHPrincipalView { ж : p }
}
// SSHPrincipalView provides a read-only view over SSHPrincipal.
//
// Its methods should only be called if `Valid()` returns true.
type SSHPrincipalView 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.
ж * SSHPrincipal
}
2025-01-14 08:15:27 -08:00
// Valid reports whether v's underlying value is non-nil.
2022-07-26 20:48:38 -07:00
func ( v SSHPrincipalView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v SSHPrincipalView ) AsStruct ( ) * SSHPrincipal {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v SSHPrincipalView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v SSHPrincipalView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
2022-07-26 20:48:38 -07:00
2025-08-14 13:46:48 -07:00
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2022-07-26 20:48:38 -07:00
func ( v * SSHPrincipalView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x SSHPrincipal
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * SSHPrincipalView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x SSHPrincipal
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2022-07-26 20:48:38 -07:00
return err
}
v . ж = & x
return nil
}
2024-12-12 09:38:07 -08:00
func ( v SSHPrincipalView ) Node ( ) StableNodeID { return v . ж . Node }
func ( v SSHPrincipalView ) NodeIP ( ) string { return v . ж . NodeIP }
2025-08-27 00:06:28 -07:00
// email-ish: foo@example.com, bar@github
func ( v SSHPrincipalView ) UserLogin ( ) string { return v . ж . UserLogin }
// if true, match any connection
func ( v SSHPrincipalView ) Any ( ) bool { return v . ж . Any }
// UnusedPubKeys was public key support. It never became an official product
// feature and so as of 2024-12-12 is being removed.
// This stub exists to remind us not to re-use the JSON field name "pubKeys"
// in the future if we bring it back with different semantics.
//
// Deprecated: do not use. It does nothing.
2024-12-12 09:38:07 -08:00
func ( v SSHPrincipalView ) UnusedPubKeys ( ) views . Slice [ string ] {
return views . SliceOf ( v . ж . UnusedPubKeys )
}
2022-07-26 20:48:38 -07:00
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _SSHPrincipalViewNeedsRegeneration = SSHPrincipal ( struct {
2024-12-12 09:38:07 -08:00
Node StableNodeID
NodeIP string
UserLogin string
Any bool
UnusedPubKeys [ ] string
2022-07-26 20:48:38 -07:00
} { } )
2022-10-05 16:18:26 +02:00
2025-01-14 08:15:27 -08:00
// View returns a read-only view of ControlDialPlan.
2022-10-05 16:18:26 +02:00
func ( p * ControlDialPlan ) View ( ) ControlDialPlanView {
return ControlDialPlanView { ж : p }
}
// ControlDialPlanView provides a read-only view over ControlDialPlan.
//
// Its methods should only be called if `Valid()` returns true.
type ControlDialPlanView 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.
ж * ControlDialPlan
}
2025-01-14 08:15:27 -08:00
// Valid reports whether v's underlying value is non-nil.
2022-10-05 16:18:26 +02:00
func ( v ControlDialPlanView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v ControlDialPlanView ) AsStruct ( ) * ControlDialPlan {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v ControlDialPlanView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v ControlDialPlanView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
2022-10-05 16:18:26 +02:00
2025-08-14 13:46:48 -07:00
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2022-10-05 16:18:26 +02:00
func ( v * ControlDialPlanView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x ControlDialPlan
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * ControlDialPlanView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x ControlDialPlan
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2022-10-05 16:18:26 +02:00
return err
}
v . ж = & x
return nil
}
2025-08-27 00:06:28 -07:00
// An empty list means the default: use DNS (unspecified which DNS).
2022-10-05 16:18:26 +02:00
func ( v ControlDialPlanView ) Candidates ( ) views . Slice [ ControlIPCandidate ] {
return views . SliceOf ( v . ж . Candidates )
}
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _ControlDialPlanViewNeedsRegeneration = ControlDialPlan ( struct {
Candidates [ ] ControlIPCandidate
} { } )
2023-06-16 10:04:07 -07:00
2025-01-14 08:15:27 -08:00
// View returns a read-only view of Location.
2023-06-16 10:04:07 -07:00
func ( p * Location ) View ( ) LocationView {
return LocationView { ж : p }
}
// LocationView provides a read-only view over Location.
//
// Its methods should only be called if `Valid()` returns true.
type LocationView 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.
ж * Location
}
2025-01-14 08:15:27 -08:00
// Valid reports whether v's underlying value is non-nil.
2023-06-16 10:04:07 -07:00
func ( v LocationView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v LocationView ) AsStruct ( ) * Location {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v LocationView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v LocationView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
2023-06-16 10:04:07 -07:00
2025-08-14 13:46:48 -07:00
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2023-06-16 10:04:07 -07:00
func ( v * LocationView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x Location
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * LocationView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x Location
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2023-06-16 10:04:07 -07:00
return err
}
v . ж = & x
return nil
}
2025-08-27 00:06:28 -07:00
// User friendly country name, with proper capitalization ("Canada")
func ( v LocationView ) Country ( ) string { return v . ж . Country }
// ISO 3166-1 alpha-2 in upper case ("CA")
2023-06-16 10:04:07 -07:00
func ( v LocationView ) CountryCode ( ) string { return v . ж . CountryCode }
2025-08-27 00:06:28 -07:00
// User friendly city name, with proper capitalization ("Squamish")
func ( v LocationView ) City ( ) string { return v . ж . City }
// CityCode is a short code representing the city in upper case.
// CityCode is used to disambiguate a city from another location
// with the same city name. It uniquely identifies a particular
// geographical location, within the tailnet.
// IATA, ICAO or ISO 3166-2 codes are recommended ("YSE")
func ( v LocationView ) CityCode ( ) string { return v . ж . CityCode }
// Latitude, Longitude are optional geographical coordinates of the node, in degrees.
// No particular accuracy level is promised; the coordinates may simply be the center of the city or country.
func ( v LocationView ) Latitude ( ) float64 { return v . ж . Latitude }
func ( v LocationView ) Longitude ( ) float64 { return v . ж . Longitude }
// Priority determines the order of use of an exit node when a
// location based preference matches more than one exit node,
// the node with the highest priority wins. Nodes of equal
// probability may be selected arbitrarily.
//
// A value of 0 means the exit node does not have a priority
// preference. A negative int is not allowed.
func ( v LocationView ) Priority ( ) int { return v . ж . Priority }
2023-06-16 10:04:07 -07:00
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _LocationViewNeedsRegeneration = Location ( struct {
Country string
CountryCode string
City string
CityCode string
2024-02-27 15:02:06 -05:00
Latitude float64
Longitude float64
2023-06-16 10:04:07 -07:00
Priority int
} { } )
2023-07-23 14:48:03 -07:00
2025-01-14 08:15:27 -08:00
// View returns a read-only view of UserProfile.
2023-07-23 14:48:03 -07:00
func ( p * UserProfile ) View ( ) UserProfileView {
return UserProfileView { ж : p }
}
// UserProfileView provides a read-only view over UserProfile.
//
// Its methods should only be called if `Valid()` returns true.
type UserProfileView 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.
ж * UserProfile
}
2025-01-14 08:15:27 -08:00
// Valid reports whether v's underlying value is non-nil.
2023-07-23 14:48:03 -07:00
func ( v UserProfileView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v UserProfileView ) AsStruct ( ) * UserProfile {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v UserProfileView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v UserProfileView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
2023-07-23 14:48:03 -07:00
2025-08-14 13:46:48 -07:00
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2023-07-23 14:48:03 -07:00
func ( v * UserProfileView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x UserProfile
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * UserProfileView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x UserProfile
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2023-07-23 14:48:03 -07:00
return err
}
v . ж = & x
return nil
}
2025-08-27 00:06:28 -07:00
func ( v UserProfileView ) ID ( ) UserID { return v . ж . ID }
// "alice@smith.com"; for display purposes only (provider is not listed)
func ( v UserProfileView ) LoginName ( ) string { return v . ж . LoginName }
// "Alice Smith"
2023-07-23 14:48:03 -07:00
func ( v UserProfileView ) DisplayName ( ) string { return v . ж . DisplayName }
func ( v UserProfileView ) ProfilePicURL ( ) string { return v . ж . ProfilePicURL }
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.
var _UserProfileViewNeedsRegeneration = UserProfile ( struct {
ID UserID
LoginName string
DisplayName string
ProfilePicURL string
} { } )
2025-04-01 19:05:45 -04:00
// View returns a read-only view of VIPService.
func ( p * VIPService ) View ( ) VIPServiceView {
return VIPServiceView { ж : p }
}
// VIPServiceView provides a read-only view over VIPService.
//
// Its methods should only be called if `Valid()` returns true.
type VIPServiceView 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.
ж * VIPService
}
// Valid reports whether v's underlying value is non-nil.
func ( v VIPServiceView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v VIPServiceView ) AsStruct ( ) * VIPService {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v VIPServiceView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v VIPServiceView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
2025-04-01 19:05:45 -04:00
2025-08-14 13:46:48 -07:00
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2025-04-01 19:05:45 -04:00
func ( v * VIPServiceView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x VIPService
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * VIPServiceView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x VIPService
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2025-04-01 19:05:45 -04:00
return err
}
v . ж = & x
return nil
}
2025-08-27 00:06:28 -07:00
// Name is the name of the service. The Name uniquely identifies a service
// on a particular tailnet, and so also corresponds uniquely to the pair of
// IP addresses belonging to the VIP service.
func ( v VIPServiceView ) Name ( ) ServiceName { return v . ж . Name }
// Ports specify which ProtoPorts are made available by this node
// on the service's IPs.
2025-04-01 19:05:45 -04:00
func ( v VIPServiceView ) Ports ( ) views . Slice [ ProtoPortRange ] { return views . SliceOf ( v . ж . Ports ) }
2025-08-27 00:06:28 -07:00
// Active specifies whether new requests for the service should be
// sent to this node by control.
func ( v VIPServiceView ) Active ( ) bool { return v . ж . Active }
2025-04-01 19:05:45 -04:00
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _VIPServiceViewNeedsRegeneration = VIPService ( struct {
Name ServiceName
Ports [ ] ProtoPortRange
Active bool
} { } )
2025-10-04 17:40:09 -07:00
// View returns a read-only view of SSHPolicy.
func ( p * SSHPolicy ) View ( ) SSHPolicyView {
return SSHPolicyView { ж : p }
}
// SSHPolicyView provides a read-only view over SSHPolicy.
//
// Its methods should only be called if `Valid()` returns true.
type SSHPolicyView 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.
ж * SSHPolicy
}
// Valid reports whether v's underlying value is non-nil.
func ( v SSHPolicyView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v SSHPolicyView ) AsStruct ( ) * SSHPolicy {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
// MarshalJSON implements [jsonv1.Marshaler].
func ( v SSHPolicyView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v SSHPolicyView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
// UnmarshalJSON implements [jsonv1.Unmarshaler].
func ( v * SSHPolicyView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x SSHPolicy
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * SSHPolicyView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x SSHPolicy
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// Rules are the rules to process for an incoming SSH connection. The first
// matching rule takes its action and stops processing further rules.
//
// When an incoming connection first starts, all rules are evaluated in
// "none" auth mode, where the client hasn't even been asked to send a
// public key. All SSHRule.Principals requiring a public key won't match. If
// a rule matches on the first pass and its Action is reject, the
// authentication fails with that action's rejection message, if any.
//
// If the first pass rule evaluation matches nothing without matching an
// Action with Reject set, the rules are considered to see whether public
// keys might still result in a match. If not, "none" auth is terminated
// before proceeding to public key mode. If so, the client is asked to try
// public key authentication and the rules are evaluated again for each of
// the client's present keys.
func ( v SSHPolicyView ) Rules ( ) views . SliceView [ * SSHRule , SSHRuleView ] {
return views . SliceOfViews [ * SSHRule , SSHRuleView ] ( v . ж . Rules )
}
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _SSHPolicyViewNeedsRegeneration = SSHPolicy ( struct {
Rules [ ] * SSHRule
} { } )