ipn

package
v1.16.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 7, 2021 License: BSD-3-Clause Imports: 29 Imported by: 79

Documentation

Overview

Package ipn implements the interactions between the Tailscale cloud control plane and the local network stack.

IPN is the abbreviated name for a Tailscale network. What's less clear is what it's an abbreviation for: Identified Private Network? IP Network? Internet Private Network? I Privately Network?

Index

Constants

View Source
const (
	NoState = State(iota)
	InUseOtherUser
	NeedsLogin
	NeedsMachineAuth
	Stopped
	Starting
	Running
)
View Source
const (
	// MachineKeyStateKey is the key under which we store the machine key,
	// in its wgkey.Private.MarshalText representation.
	MachineKeyStateKey = StateKey("_machinekey")

	// GlobalDaemonStateKey is the ipn.StateKey that tailscaled
	// loads on startup.
	//
	// We have to support multiple state keys for other OSes (Windows in
	// particular), but right now Unix daemons run with a single
	// node-global state. To keep open the option of having per-user state
	// later, the global state key doesn't look like a username.
	GlobalDaemonStateKey = StateKey("_daemon")

	// ServerModeStartKey's value, if non-empty, is the value of a
	// StateKey containing the prefs to start with which to start the
	// server.
	//
	// For example, the value might be "user-1234", meaning the
	// the server should start with the Prefs JSON loaded from
	// StateKey "user-1234".
	ServerModeStartKey = StateKey("server-mode-start-key")
)
View Source
const DefaultControlURL = "https://controlplane.tailscale.com"

DefaultControlURL is the URL base of the control plane ("coordination server") for use when no explicit one is configured. The default control plane is the hosted version run by Tailscale.com.

View Source
const ErrMsgPermissionDenied = "permission denied"

ErrMsgPermissionDenied is the Notify.ErrMessage value used an operation was done from a user/context that didn't have permission.

View Source
const GoogleIDTokenType = "ts_android_google_login"

GoogleIDToken Type is the tailcfg.Oauth2Token.TokenType for the Google ID tokens used by the Android client.

View Source
const MaxMessageSize = 10 << 20

MaxMessageSize is the maximum message size, in bytes.

Variables

View Source
var ErrStateNotExist = errors.New("no state with given ID")

ErrStateNotExist is returned by StateStore.ReadState when the requested state ID doesn't exist.

Functions

func IsLoginServerSynonym added in v1.12.0

func IsLoginServerSynonym(val interface{}) bool

IsLoginServerSynonym reports whether a URL is a drop-in replacement for the primary Tailscale login server.

func IsReadonlyContext added in v1.4.0

func IsReadonlyContext(ctx context.Context) bool

IsReadonlyContext reports whether ctx is a read-only context, as currently used by Unix non-root users running the "tailscale" CLI command. They can run "status", but not much else.

func ReadMsg

func ReadMsg(r io.Reader) ([]byte, error)

TODO(apenwarr): incremental json decode?

That would let us avoid storing the whole byte array uselessly in RAM.

func ReadonlyContextOf added in v1.4.0

func ReadonlyContextOf(ctx context.Context) context.Context

ReadonlyContextOf returns ctx wrapped with a context value that will make IsReadonlyContext reports true.

func SavePrefs

func SavePrefs(filename string, p *Prefs)

func WriteMsg

func WriteMsg(w io.Writer, b []byte) error

TODO(apenwarr): incremental json encode?

That would save RAM, at the expense of having to encode once so that
we can produce the initial byte count.

Types

type Backend

type Backend interface {
	// SetNotifyCallback sets the callback to be called on updates
	// from the backend to the client.
	SetNotifyCallback(func(Notify))
	// Start starts or restarts the backend, typically when a
	// frontend client connects.
	Start(Options) error
	// StartLoginInteractive requests to start a new interactive login
	// flow. This should trigger a new BrowseToURL notification
	// eventually.
	StartLoginInteractive()
	// Login logs in with an OAuth2 token.
	Login(token *tailcfg.Oauth2Token)
	// Logout terminates the current login session and stops the
	// wireguard engine.
	Logout()
	// SetPrefs installs a new set of user preferences, including
	// WantRunning. This may cause the wireguard engine to
	// reconfigure or stop.
	SetPrefs(*Prefs)
	// RequestEngineStatus polls for an update from the wireguard
	// engine. Only needed if you want to display byte
	// counts. Connection events are emitted automatically without
	// polling.
	RequestEngineStatus()
	// FakeExpireAfter pretends that the current key is going to
	// expire after duration x. This is useful for testing GUIs to
	// make sure they react properly with keys that are going to
	// expire.
	FakeExpireAfter(x time.Duration)
	// Ping attempts to start connecting to the given IP and sends a Notify
	// with its PingResult. If the host is down, there might never
	// be a PingResult sent. The cmd/tailscale CLI client adds a timeout.
	Ping(ip string, useTSMP bool)
}

Backend is the interface between Tailscale frontends (e.g. cmd/tailscale, iOS/MacOS/Windows GUIs) and the tailscale backend (e.g. cmd/tailscaled) running on the same machine. (It has nothing to do with the interface between the backends and the cloud control plane.)

type BackendClient

type BackendClient struct {

	// AllowVersionSkew controls whether to allow mismatched
	// frontend & backend versions.
	AllowVersionSkew bool
	// contains filtered or unexported fields
}

func NewBackendClient

func NewBackendClient(logf logger.Logf, sendCommandMsg func(jsonb []byte)) *BackendClient

func (*BackendClient) FakeExpireAfter

func (bc *BackendClient) FakeExpireAfter(x time.Duration)

func (*BackendClient) GotNotifyMsg

func (bc *BackendClient) GotNotifyMsg(b []byte)

func (*BackendClient) Login added in v1.0.0

func (bc *BackendClient) Login(token *tailcfg.Oauth2Token)

func (*BackendClient) Logout

func (bc *BackendClient) Logout()

func (*BackendClient) Ping added in v1.2.0

func (bc *BackendClient) Ping(ip string, useTSMP bool)

func (*BackendClient) Quit

func (bc *BackendClient) Quit() error

func (*BackendClient) RequestEngineStatus

func (bc *BackendClient) RequestEngineStatus()

func (*BackendClient) RequestStatus added in v0.98.0

func (bc *BackendClient) RequestStatus()

func (*BackendClient) SetNotifyCallback added in v0.98.0

func (bc *BackendClient) SetNotifyCallback(fn func(Notify))

func (*BackendClient) SetPrefs

func (bc *BackendClient) SetPrefs(new *Prefs)

func (*BackendClient) Start

func (bc *BackendClient) Start(opts Options) error

func (*BackendClient) StartLoginInteractive

func (bc *BackendClient) StartLoginInteractive()

type BackendServer

type BackendServer struct {
	GotQuit bool // a Quit command was received
	// contains filtered or unexported fields
}

func NewBackendServer

func NewBackendServer(logf logger.Logf, b Backend, sendNotifyMsg func(Notify)) *BackendServer

NewBackendServer creates a new BackendServer using b.

If sendNotifyMsg is non-nil, it additionally sets the Backend's notification callback to call the func with ipn.Notify messages in JSON form. If nil, it does not change the notification callback.

func (*BackendServer) GotCommand

func (bs *BackendServer) GotCommand(ctx context.Context, cmd *Command) error

func (*BackendServer) GotCommandMsg

func (bs *BackendServer) GotCommandMsg(ctx context.Context, b []byte) error

GotCommandMsg parses the incoming message b as a JSON Command and calls GotCommand with it.

func (*BackendServer) SendErrorMessage added in v1.0.0

func (bs *BackendServer) SendErrorMessage(msg string)

func (*BackendServer) SendInUseOtherUserErrorMessage added in v1.2.1

func (bs *BackendServer) SendInUseOtherUserErrorMessage(msg string)

SendInUseOtherUserErrorMessage sends a Notify message to the client that both sets the state to 'InUseOtherUser' and sets the associated reason to msg.

type Command

type Command struct {

	// Version is the binary version of the frontend (the client).
	Version string

	// AllowVersionSkew controls whether it's permitted for the
	// client and server to have a different version. The default
	// (false) means to be strict.
	AllowVersionSkew bool

	// Exactly one of the following must be non-nil.
	Quit                  *NoArgs
	Start                 *StartArgs
	StartLoginInteractive *NoArgs
	Login                 *tailcfg.Oauth2Token
	Logout                *NoArgs
	SetPrefs              *SetPrefsArgs
	RequestEngineStatus   *NoArgs
	RequestStatus         *NoArgs
	FakeExpireAfter       *FakeExpireAfterArgs
	Ping                  *PingArgs
	// contains filtered or unexported fields
}

Command is a command message that is JSON encoded and sent by a frontend to a backend.

type EngineStatus

type EngineStatus struct {
	RBytes, WBytes int64
	NumLive        int
	LiveDERPs      int // number of active DERP connections
	LivePeers      map[tailcfg.NodeKey]ipnstate.PeerStatusLite
}

EngineStatus contains WireGuard engine stats.

type FakeExpireAfterArgs

type FakeExpireAfterArgs struct {
	Duration time.Duration
}

type FileStore

type FileStore struct {
	// contains filtered or unexported fields
}

FileStore is a StateStore that uses a JSON file for persistence.

func NewFileStore

func NewFileStore(path string) (*FileStore, error)

NewFileStore returns a new file store that persists to path.

func (*FileStore) Path added in v1.14.5

func (s *FileStore) Path() string

Path returns the path that NewFileStore was called with.

func (*FileStore) ReadState

func (s *FileStore) ReadState(id StateKey) ([]byte, error)

ReadState implements the StateStore interface.

func (*FileStore) String added in v1.2.0

func (s *FileStore) String() string

func (*FileStore) WriteState

func (s *FileStore) WriteState(id StateKey, bs []byte) error

WriteState implements the StateStore interface.

type Handle

type Handle struct {
	// contains filtered or unexported fields
}

func NewHandle

func NewHandle(b Backend, logf logger.Logf, notify func(Notify), opts Options) (*Handle, error)

func (*Handle) AdminPageURL

func (h *Handle) AdminPageURL() string

func (*Handle) EngineStatus

func (h *Handle) EngineStatus() EngineStatus

func (*Handle) Expiry

func (h *Handle) Expiry() time.Time

func (*Handle) FakeExpireAfter

func (h *Handle) FakeExpireAfter(x time.Duration)

func (*Handle) LocalAddrs

func (h *Handle) LocalAddrs() []netaddr.IPPrefix

func (*Handle) Login added in v1.0.0

func (h *Handle) Login(token *tailcfg.Oauth2Token)

func (*Handle) Logout

func (h *Handle) Logout()

func (*Handle) NetMap

func (h *Handle) NetMap() *netmap.NetworkMap

func (*Handle) Prefs

func (h *Handle) Prefs() *Prefs

func (*Handle) RequestEngineStatus

func (h *Handle) RequestEngineStatus()

func (*Handle) Reset

func (h *Handle) Reset()

func (*Handle) SetNotifyCallback added in v1.8.0

func (h *Handle) SetNotifyCallback(notify func(Notify))

func (*Handle) Start

func (h *Handle) Start(opts Options) error

func (*Handle) StartLoginInteractive

func (h *Handle) StartLoginInteractive()

func (*Handle) State

func (h *Handle) State() State

func (*Handle) UpdatePrefs

func (h *Handle) UpdatePrefs(updateFn func(p *Prefs))

type KubeStore added in v1.16.0

type KubeStore struct {
	// contains filtered or unexported fields
}

KubeStore is a StateStore that uses a Kubernetes Secret for persistence.

func NewKubeStore added in v1.16.0

func NewKubeStore(secretName string) (*KubeStore, error)

NewKubeStore returns a new KubeStore that persists to the named secret.

func (*KubeStore) ReadState added in v1.16.0

func (s *KubeStore) ReadState(id StateKey) ([]byte, error)

ReadState implements the StateStore interface.

func (*KubeStore) String added in v1.16.0

func (s *KubeStore) String() string

func (*KubeStore) WriteState added in v1.16.0

func (s *KubeStore) WriteState(id StateKey, bs []byte) error

WriteState implements the StateStore interface.

type MaskedPrefs added in v1.8.0

type MaskedPrefs struct {
	Prefs

	ControlURLSet             bool `json:",omitempty"`
	RouteAllSet               bool `json:",omitempty"`
	AllowSingleHostsSet       bool `json:",omitempty"`
	ExitNodeIDSet             bool `json:",omitempty"`
	ExitNodeIPSet             bool `json:",omitempty"`
	ExitNodeAllowLANAccessSet bool `json:",omitempty"`
	CorpDNSSet                bool `json:",omitempty"`
	WantRunningSet            bool `json:",omitempty"`
	LoggedOutSet              bool `json:",omitempty"`
	ShieldsUpSet              bool `json:",omitempty"`
	AdvertiseTagsSet          bool `json:",omitempty"`
	HostnameSet               bool `json:",omitempty"`
	NotepadURLsSet            bool `json:",omitempty"`
	ForceDaemonSet            bool `json:",omitempty"`
	AdvertiseRoutesSet        bool `json:",omitempty"`
	NoSNATSet                 bool `json:",omitempty"`
	NetfilterModeSet          bool `json:",omitempty"`
	OperatorUserSet           bool `json:",omitempty"`
}

MaskedPrefs is a Prefs with an associated bitmask of which fields are set.

func (*MaskedPrefs) Pretty added in v1.8.0

func (m *MaskedPrefs) Pretty() string

type MemoryStore

type MemoryStore struct {
	// contains filtered or unexported fields
}

MemoryStore is a store that keeps state in memory only.

func (*MemoryStore) ReadState

func (s *MemoryStore) ReadState(id StateKey) ([]byte, error)

ReadState implements the StateStore interface.

func (*MemoryStore) String added in v1.2.0

func (s *MemoryStore) String() string

func (*MemoryStore) WriteState

func (s *MemoryStore) WriteState(id StateKey, bs []byte) error

WriteState implements the StateStore interface.

type NoArgs

type NoArgs struct{}

type Notify

type Notify struct {
	Version string // version number of IPN backend

	// ErrMessage, if non-nil, contains a critical error message.
	// For State InUseOtherUser, ErrMessage is not critical and just contains the details.
	ErrMessage *string

	LoginFinished *empty.Message       // non-nil when/if the login process succeeded
	State         *State               // if non-nil, the new or current IPN state
	Prefs         *Prefs               // if non-nil, the new or current preferences
	NetMap        *netmap.NetworkMap   // if non-nil, the new or current netmap
	Engine        *EngineStatus        // if non-nil, the new or urrent wireguard stats
	BrowseToURL   *string              // if non-nil, UI should open a browser right now
	BackendLogID  *string              // if non-nil, the public logtail ID used by backend
	PingResult    *ipnstate.PingResult // if non-nil, a ping response arrived

	// FilesWaiting if non-nil means that files are buffered in
	// the Tailscale daemon and ready for local transfer to the
	// user's preferred storage location.
	FilesWaiting *empty.Message `json:",omitempty"`

	// IncomingFiles, if non-nil, specifies which files are in the
	// process of being received. A nil IncomingFiles means this
	// Notify should not update the state of file transfers. A non-nil
	// but empty IncomingFiles means that no files are in the middle
	// of being transferred.
	IncomingFiles []PartialFile `json:",omitempty"`

	// LocalTCPPort, if non-nil, informs the UI frontend which
	// (non-zero) localhost TCP port it's listening on.
	// This is currently only used by Tailscale when run in the
	// macOS Network Extension.
	LocalTCPPort *uint16 `json:",omitempty"`
	// contains filtered or unexported fields
}

Notify is a communication from a backend (e.g. tailscaled) to a frontend (cmd/tailscale, iOS, macOS, Win Tasktray). In any given notification, any or all of these may be nil, meaning that they have not changed. They are JSON-encoded on the wire, despite the lack of struct tags.

func (Notify) String added in v1.8.0

func (n Notify) String() string

type Options

type Options struct {
	// FrontendLogID is the public logtail id used by the frontend.
	FrontendLogID string
	// StateKey and Prefs together define the state the backend should
	// use:
	//  - StateKey=="" && Prefs!=nil: use Prefs for internal state,
	//    don't persist changes in the backend, except for the machine key
	//    for migration purposes.
	//  - StateKey!="" && Prefs==nil: load the given backend-side
	//    state and use/update that.
	//  - StateKey!="" && Prefs!=nil: like the previous case, but do
	//    an initial overwrite of backend state with Prefs.
	//
	// NOTE(apenwarr): The above means that this Prefs field does not do
	// what you probably think it does. It will overwrite your encryption
	// keys. Do not use unless you know what you're doing.
	StateKey StateKey
	Prefs    *Prefs
	// UpdatePrefs, if provided, overrides Options.Prefs *and* the Prefs
	// already stored in the backend state, *except* for the Persist
	// Persist member. If you just want to provide prefs, this is
	// probably what you want.
	//
	// UpdatePrefs.Persist is always ignored. Prefs.Persist will still
	// be used even if UpdatePrefs is provided. Other than Persist,
	// UpdatePrefs takes precedence over Prefs.
	//
	// This is intended as a purely temporary workaround for the
	// currently unexpected behaviour of Options.Prefs.
	//
	// TODO(apenwarr): Remove this, or rename Prefs to something else
	//   and rename this to Prefs. Or, move Prefs.Persist elsewhere
	//   entirely (as it always should have been), and then we wouldn't
	//   need two separate fields at all. Or, move the fancy state
	//   migration stuff out of Start().
	UpdatePrefs *Prefs
	// AuthKey is an optional node auth key used to authorize a
	// new node key without user interaction.
	AuthKey string
}

type PartialFile added in v1.8.0

type PartialFile struct {
	Name         string    // e.g. "foo.jpg"
	Started      time.Time // time transfer started
	DeclaredSize int64     // or -1 if unknown
	Received     int64     // bytes copied thus far

	// PartialPath is set non-empty in "direct" file mode to the
	// in-progress '*.partial' file's path when the peerapi isn't
	// being used; see LocalBackend.SetDirectFileRoot.
	PartialPath string `json:",omitempty"`

	// Done is set in "direct" mode when the partial file has been
	// closed and is ready for the caller to rename away the
	// ".partial" suffix.
	Done bool `json:",omitempty"`
}

PartialFile represents an in-progress file transfer.

type PingArgs added in v1.2.0

type PingArgs struct {
	IP      string
	UseTSMP bool
}

type Prefs

type Prefs struct {
	// ControlURL is the URL of the control server to use.
	//
	// If empty, the default for new installs, DefaultControlURL
	// is used. It's set non-empty once the daemon has been started
	// for the first time.
	//
	// TODO(apenwarr): Make it safe to update this with SetPrefs().
	// Right now, you have to pass it in the initial prefs in Start(),
	// which is the only code that actually uses the ControlURL value.
	// It would be more consistent to restart controlclient
	// automatically whenever this variable changes.
	//
	// Meanwhile, you have to provide this as part of Options.Prefs or
	// Options.UpdatePrefs when calling Backend.Start().
	ControlURL string

	// RouteAll specifies whether to accept subnets advertised by
	// other nodes on the Tailscale network. Note that this does not
	// include default routes (0.0.0.0/0 and ::/0), those are
	// controlled by ExitNodeID/IP below.
	RouteAll bool

	// AllowSingleHosts specifies whether to install routes for each
	// node IP on the tailscale network, in addition to a route for
	// the whole network.
	// This corresponds to the "tailscale up --host-routes" value,
	// which defaults to true.
	//
	// TODO(danderson): why do we have this? It dumps a lot of stuff
	// into the routing table, and a single network route _should_ be
	// all that we need. But when I turn this off in my tailscaled,
	// packets stop flowing. What's up with that?
	AllowSingleHosts bool

	// ExitNodeID and ExitNodeIP specify the node that should be used
	// as an exit node for internet traffic. At most one of these
	// should be non-zero.
	//
	// The preferred way to express the chosen node is ExitNodeID, but
	// in some cases it's not possible to use that ID (e.g. in the
	// linux CLI, before tailscaled has a netmap). For those
	// situations, we allow specifying the exit node by IP, and
	// ipnlocal.LocalBackend will translate the IP into an ID when the
	// node is found in the netmap.
	//
	// If the selected exit node doesn't exist (e.g. it's not part of
	// the current tailnet), or it doesn't offer exit node services, a
	// blackhole route will be installed on the local system to
	// prevent any traffic escaping to the local network.
	ExitNodeID tailcfg.StableNodeID
	ExitNodeIP netaddr.IP

	// ExitNodeAllowLANAccess indicates whether locally accessible subnets should be
	// routed directly or via the exit node.
	ExitNodeAllowLANAccess bool

	// CorpDNS specifies whether to install the Tailscale network's
	// DNS configuration, if it exists.
	CorpDNS bool

	// WantRunning indicates whether networking should be active on
	// this node.
	WantRunning bool

	// LoggedOut indicates whether the user intends to be logged out.
	// There are other reasons we may be logged out, including no valid
	// keys.
	// We need to remember this state so that, on next startup, we can
	// generate the "Login" vs "Connect" buttons correctly, without having
	// to contact the server to confirm our nodekey status first.
	LoggedOut bool

	// ShieldsUp indicates whether to block all incoming connections,
	// regardless of the control-provided packet filter. If false, we
	// use the packet filter as provided. If true, we block incoming
	// connections. This overrides tailcfg.Hostinfo's ShieldsUp.
	ShieldsUp bool

	// AdvertiseTags specifies groups that this node wants to join, for
	// purposes of ACL enforcement. These can be referenced from the ACL
	// security policy. Note that advertising a tag doesn't guarantee that
	// the control server will allow you to take on the rights for that
	// tag.
	AdvertiseTags []string

	// Hostname is the hostname to use for identifying the node. If
	// not set, os.Hostname is used.
	Hostname string

	// NotepadURLs is a debugging setting that opens OAuth URLs in
	// notepad.exe on Windows, rather than loading them in a browser.
	//
	// apenwarr 2020-04-29: Unfortunately this is still needed sometimes.
	// Windows' default browser setting is sometimes screwy and this helps
	// users narrow it down a bit.
	NotepadURLs bool

	// ForceDaemon specifies whether a platform that normally
	// operates in "client mode" (that is, requires an active user
	// logged in with the GUI app running) should keep running after the
	// GUI ends and/or the user logs out.
	//
	// The only current applicable platform is Windows. This
	// forced Windows to go into "server mode" where Tailscale is
	// running even with no users logged in. This might also be
	// used for macOS in the future. This setting has no effect
	// for Linux/etc, which always operate in daemon mode.
	ForceDaemon bool `json:"ForceDaemon,omitempty"`

	// AdvertiseRoutes specifies CIDR prefixes to advertise into the
	// Tailscale network as reachable through the current
	// node.
	AdvertiseRoutes []netaddr.IPPrefix

	// NoSNAT specifies whether to source NAT traffic going to
	// destinations in AdvertiseRoutes. The default is to apply source
	// NAT, which makes the traffic appear to come from the router
	// machine rather than the peer's Tailscale IP.
	//
	// Disabling SNAT requires additional manual configuration in your
	// network to route Tailscale traffic back to the subnet relay
	// machine.
	//
	// Linux-only.
	NoSNAT bool

	// NetfilterMode specifies how much to manage netfilter rules for
	// Tailscale, if at all.
	NetfilterMode preftype.NetfilterMode

	// OperatorUser is the local machine user name who is allowed to
	// operate tailscaled without being root or using sudo.
	OperatorUser string `json:",omitempty"`

	// The Persist field is named 'Config' in the file for backward
	// compatibility with earlier versions.
	// TODO(apenwarr): We should move this out of here, it's not a pref.
	//  We can maybe do that once we're sure which module should persist
	//  it (backend or frontend?)
	Persist *persist.Persist `json:"Config"`
}

Prefs are the user modifiable settings of the Tailscale node agent.

func LoadPrefs

func LoadPrefs(filename string) (*Prefs, error)

LoadPrefs loads a legacy relaynode config file into Prefs with sensible migration defaults set.

func NewPrefs

func NewPrefs() *Prefs

NewPrefs returns the default preferences to use.

func PrefsFromBytes

func PrefsFromBytes(b []byte, enforceDefaults bool) (*Prefs, error)

PrefsFromBytes deserializes Prefs from a JSON blob. If enforceDefaults is true, Prefs.RouteAll and Prefs.AllowSingleHosts are forced on.

func (*Prefs) AdminPageURL added in v1.12.0

func (p *Prefs) AdminPageURL() string

AdminPageURL returns the admin web site URL for the current ControlURL.

func (*Prefs) ApplyEdits added in v1.8.0

func (p *Prefs) ApplyEdits(m *MaskedPrefs)

ApplyEdits mutates p, assigning fields from m.Prefs for each MaskedPrefs Set field that's true.

func (*Prefs) Clone

func (src *Prefs) Clone() *Prefs

Clone makes a deep copy of Prefs. The result aliases no memory with the original.

func (*Prefs) ControlURLOrDefault added in v1.8.0

func (p *Prefs) ControlURLOrDefault() string

ControlURLOrDefault returns the coordination server's URL base. If not configured, DefaultControlURL is returned instead.

func (*Prefs) Equals

func (p *Prefs) Equals(p2 *Prefs) bool

func (*Prefs) IsEmpty

func (p *Prefs) IsEmpty() bool

IsEmpty reports whether p is nil or pointing to a Prefs zero value.

func (*Prefs) Pretty

func (p *Prefs) Pretty() string

func (*Prefs) ToBytes

func (p *Prefs) ToBytes() []byte

type SetPrefsArgs

type SetPrefsArgs struct {
	New *Prefs
}

type StartArgs

type StartArgs struct {
	Opts Options
}

type State

type State int

func (State) String

func (s State) String() string

type StateKey

type StateKey string

StateKey is an opaque identifier for a set of LocalBackend state (preferences, private keys, etc.).

The reason we need this is that the Tailscale agent may be running on a multi-user machine, in a context where a single daemon is shared by several consecutive users. Ideally we would just use the username of the connected frontend as the StateKey.

Various platforms currently set StateKey in different ways:

  • the macOS/iOS GUI apps set it to "ipn-go-bridge"
  • the Android app sets it to "ipn-android"
  • on Windows, it's the empty string (in client mode) or, via LocalBackend.userID, a string like "user-$USER_ID" (used in server mode).
  • on Linux/etc, it's always "_daemon" (ipn.GlobalDaemonStateKey)

type StateStore

type StateStore interface {
	// ReadState returns the bytes associated with ID. Returns (nil,
	// ErrStateNotExist) if the ID doesn't have associated state.
	ReadState(id StateKey) ([]byte, error)
	// WriteState saves bs as the state associated with ID.
	WriteState(id StateKey, bs []byte) error
}

StateStore persists state, and produces it back on request.

Directories

Path Synopsis
Package ipnstate captures the entire state of the Tailscale network.
Package ipnstate captures the entire state of the Tailscale network.
Package localapi contains the HTTP server handlers for tailscaled's API server.
Package localapi contains the HTTP server handlers for tailscaled's API server.
Package policy contains various policy decisions that need to be shared between the node client & control server.
Package policy contains various policy decisions that need to be shared between the node client & control server.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL