Movatterモバイル変換


[0]ホーム

URL:


ipnext

package
v1.92.2Latest Latest
Warning

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

Go to latest
Published: Dec 10, 2025 License:BSD-3-ClauseImports:14Imported by:0

Details

Repository

github.com/tailscale/tailscale

Links

Documentation

Overview

Package ipnext defines types and interfaces used for extending the core LocalBackendfunctionality with additional features and services.

Index

Constants

This section is empty.

Variables

View Source
var SkipExtension =errors.New("skipping extension")

SkipExtension is an error returned byNewExtensionFn to indicate that the extensionshould be skipped rather than prevent the LocalBackend from starting.

Skipping an extension should be reserved for cases where the extension is not supportedon the current platform or configuration, or depends on a feature that is not available,or otherwise should be disabled permanently rather than temporarily.

Specifically, it must not be returned if the extension is not required right nowbased on user preferences, policy settings, the current tailnet, or other factorsthat may change throughout the LocalBackend's lifetime.

Functions

funcExtensions

func Extensions()iter.Seq[*Definition]

Extensions iterates over the extensions in the order they were registeredviaRegisterExtension.

funcRegisterExtension

func RegisterExtension(namestring, newExtNewExtensionFn)

RegisterExtension registers a function that instantiates anExtension.The name must be the same as returned by the extension's [Extension.Name].

It must be called on the main goroutine before LocalBackend is created,such as from an init function of the package implementing the extension.

It panics if newExt is nil or if an extension with the same namehas already been registered.

Types

typeAuditLogProvider

type AuditLogProvider func()ipnauth.AuditLogFunc

AuditLogProvider is a function that returns anipnauth.AuditLogFunc forlogging auditable actions.

typeDefinition

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

Definition describes a registeredExtension.

funcDefinitionForTest

func DefinitionForTest(extExtension) *Definition

DefinitionForTest returns aDefinition for the specifiedExtension.It is primarily used for testing where the test code needs to instantiateand use an extension without registering it.

funcDefinitionWithErrForTest

func DefinitionWithErrForTest(namestring, errerror) *Definition

DefinitionWithErrForTest returns aDefinition with the specified extension namewhoseDefinition.MakeExtension method returns the specified error.It is used for testing.

func (*Definition)MakeExtension

func (d *Definition) MakeExtension(logflogger.Logf, sbSafeBackend) (Extension,error)

MakeExtension instantiates the extension.

func (*Definition)Name

func (d *Definition) Name()string

Name returns the name of the extension.

typeExtension

type Extension interface {// Name is a unique name of the extension.// It must be the same as the name used to register the extension.Name()string// Init is called to initialize the extension when LocalBackend's// Start method is called. Extensions are created but not initialized// unless LocalBackend is started.//// If the extension cannot be initialized, it must return an error,// and its Shutdown method will not be called on the host's shutdown.// Returned errors are not fatal; they are used for logging.// A [SkipExtension] error indicates an intentional decision rather than a failure.Init(Host)error// Shutdown is called when LocalBackend is shutting down,// provided the extension was initialized. For multiple extensions,// Shutdown is called in the reverse order of Init.// Returned errors are not fatal; they are used for logging.// After a call to Shutdown, the extension will not be called again.Shutdown()error}

Extension augments LocalBackend with additional functionality.

An extension uses the providedHost to register callbacksand interact with the backend in a controlled, well-definedand thread-safe manner.

Extensions are registered usingRegisterExtension.

They must be safe for concurrent use.

typeExtensionServices

type ExtensionServices interface {// FindExtensionByName returns an active extension with the given name,// or nil if no such extension exists.FindExtensionByName(namestring)any// FindMatchingExtension finds the first active extension that matches target,// and if one is found, sets target to that extension and returns true.// Otherwise, it returns false.//// It panics if target is not a non-nil pointer to either a type// that implements [ipnext.Extension], or to any interface type.FindMatchingExtension(targetany)bool}

ExtensionServices provides access to theHost's extension management services,such as fetching active extensions.

typeHooks

type Hooks struct {// BackendStateChange is called when the backend state changes.BackendStateChangefeature.Hooks[func(ipn.State)]// ProfileStateChange contains callbacks that are invoked when the current login profile// or its [ipn.Prefs] change, after those changes have been made. The current login profile// may be changed either because of a profile switch, or because the profile information// was updated by [LocalBackend.SetControlClientStatus], including when the profile// is first populated and persisted.ProfileStateChangefeature.Hooks[ProfileStateChangeCallback]// BackgroundProfileResolvers are registered background profile resolvers.// They're used to determine the profile to use when no GUI/CLI client is connected.//// TODO(nickkhyl): allow specifying some kind of priority/altitude for the resolver.// TODO(nickkhyl): make it a "profile resolver" instead of a "background profile resolver".// The concepts of the "current user", "foreground profile" and "background profile"// only exist on Windows, and we're moving away from them anyway.BackgroundProfileResolversfeature.Hooks[ProfileResolver]// AuditLoggers are registered [AuditLogProvider]s.// Each provider is called to get an [ipnauth.AuditLogFunc] when an auditable action// is about to be performed. If an audit logger returns an error, the action is denied.AuditLoggersfeature.Hooks[AuditLogProvider]// NewControlClient are the functions to be called when a new control client// is created. It is called with the LocalBackend locked.NewControlClientfeature.Hooks[NewControlClientCallback]// OnSelfChange is called (with LocalBackend.mu held) when the self node// changes, including changing to nothing (an invalid view).OnSelfChangefeature.Hooks[func(tailcfg.NodeView)]// MutateNotifyLocked is called to optionally mutate the provided Notify// before sending it to the IPN bus. It is called with LocalBackend.mu held.MutateNotifyLockedfeature.Hooks[func(*ipn.Notify)]// SetPeerStatus is called to mutate PeerStatus.// Callers must only use NodeBackend to read data.SetPeerStatusfeature.Hooks[func(*ipnstate.PeerStatus,tailcfg.NodeView,NodeBackend)]// ShouldUploadServices reports whether this node should include services// in Hostinfo from the portlist extension.ShouldUploadServicesfeature.Hook[func()bool]}

Hooks is a collection of hooks that extensions can add to (non-concurrently)during program initialization and can be called by LocalBackend and others atruntime.

Each hook has its own rules about when it's called and what environment ithas access to and what it's allowed to do.

typeHost

type Host interface {// Extensions returns the host's [ExtensionServices].Extensions()ExtensionServices// Profiles returns the host's [ProfileServices].Profiles()ProfileServices// AuditLogger returns a function that calls all currently registered audit loggers.// The function fails if any logger returns an error, indicating that the action// cannot be logged and must not be performed.//// The returned function captures the current state (e.g., the current profile) at// the time of the call and must not be persisted.AuditLogger()ipnauth.AuditLogFunc// Hooks returns a non-nil pointer to a [Hooks] struct.// Hooks must not be modified concurrently or after Tailscale has started.Hooks() *Hooks// SendNotifyAsync sends a notification to the IPN bus,// typically to the GUI client.SendNotifyAsync(ipn.Notify)// NodeBackend returns the [NodeBackend] for the currently active node// (which is approximately the same as the current profile).NodeBackend()NodeBackend}

Host is the API surface used by [Extension]s to interact with LocalBackendin a controlled manner.

Extensions can register callbacks, request information, or perform actionsvia theHost interface.

Typically, the host invokes registered callbacks when one of the following occurs:

  • LocalBackend notifies it of an event or state change that may beof interest to extensions, such as when switchingipn.LoginProfile.
  • LocalBackend needs to consult extensions for information, for example,determining the most appropriate profile for the current state of the system.
  • LocalBackend performs an extensible action, such as logging an auditable event,and delegates its execution to the extension.

The callbacks are invoked synchronously, and the LocalBackend's stateremains unchanged while callbacks execute.

In contrast, actions initiated by extensions are generally asynchronous,as indicated by the "Async" suffix in their names.Performing actions may result in callbacks being invoked as described above.

To prevent conflicts between extensions competing for shared state,such as the current profile or prefs, the host must not expose methodsthat directly modify that state. For example, instead of allowing extensionsto switch profiles at-will, the host'sProfileServices provides a methodto switch to the "best" profile. The host can then consult extensionsto determine the appropriate profile to use and resolve any conflictsin a controlled manner.

A host must be safe for concurrent use.

typeNewControlClientCallback

type NewControlClientCallback func(controlclient.Client,ipn.LoginProfileView) (cleanup func())

NewControlClientCallback is a function to be called when a newcontrolclient.Clientis created and before it is first used. The specified profile represents the nodefor which the cc is created and is always valid. Itsipn.LoginProfileView.IDreturns "" if it is a new node whose profile has never been persisted.

If thecontrolclient.Client is created due to a profile switch, any registered[ProfileStateChangeCallback]s are called first.

It returns a function to be called when the cc is being shut down,or nil if no cleanup is needed. That cleanup function should not callback into LocalBackend, which may be locked during shutdown.

typeNewExtensionFn

type NewExtensionFn func(logger.Logf,SafeBackend) (Extension,error)

NewExtensionFn is a function that instantiates anExtension.If a registered extension cannot be instantiated, the function must return an error.If the extension should be skipped at runtime, it must return eitherSkipExtensionor a wrappedSkipExtension. Any other error returned is fatal and will preventthe LocalBackend from starting.

typeNodeBackend

type NodeBackend interface {// AppendMatchingPeers appends all peers that match the predicate// to the base slice and returns it.AppendMatchingPeers(base []tailcfg.NodeView, pred func(tailcfg.NodeView)bool) []tailcfg.NodeView// PeerCaps returns the capabilities that src has to this node.PeerCaps(srcnetip.Addr)tailcfg.PeerCapMap// PeerHasCap reports whether the peer has the specified peer capability.PeerHasCap(peertailcfg.NodeView, captailcfg.PeerCapability)bool// PeerAPIBase returns the "http://ip:port" URL base to reach peer's// PeerAPI, or the empty string if the peer is invalid or doesn't support// PeerAPI.PeerAPIBase(tailcfg.NodeView)string// PeerHasPeerAPI whether the provided peer supports PeerAPI.//// It effectively just reports whether PeerAPIBase(node) is non-empty, but// potentially more efficiently.PeerHasPeerAPI(tailcfg.NodeView)bool// CollectServices reports whether the control plane is telling this// node that the portlist service collection is desirable, should it// choose to report them.CollectServices()bool}

NodeBackend is an interface to query the current node and its peers.

It is not a snapshot in time but is locked to a particular node.

typeProfileResolver

type ProfileResolver func(ProfileStore)ipn.LoginProfileView

ProfileResolver is a function that returns a read-only view of a login profile.An invalid view indicates no profile. A valid profile view with an emptyipn.ProfileIDindicates that the profile is new and has not been persisted yet.The providedProfileStore can only be used for the duration of the callback.

typeProfileServices

type ProfileServices interface {// CurrentProfileState returns read-only views of the current profile// and its preferences. The returned views are always valid,// but the profile's [ipn.LoginProfileView.ID] returns ""// if the profile is new and has not been persisted yet.//// The returned views are immutable snapshots of the current profile// and prefs at the time of the call. The actual state is only guaranteed// to remain unchanged and match these views for the duration// of a callback invoked by the host, if used within that callback.//// Extensions that need the current profile or prefs at other times// should typically subscribe to [ProfileStateChangeCallback]// to be notified if the profile or prefs change after retrieval.// CurrentProfileState returns both the profile and prefs// to guarantee that they are consistent with each other.CurrentProfileState() (ipn.LoginProfileView,ipn.PrefsView)// CurrentPrefs is like [CurrentProfileState] but only returns prefs.CurrentPrefs()ipn.PrefsView// SwitchToBestProfileAsync asynchronously selects the best profile to use// and switches to it, unless it is already the current profile.//// If an extension needs to know when a profile switch occurs,// it must use [ProfileServices.RegisterProfileStateChangeCallback]// to register a [ProfileStateChangeCallback].//// The reason indicates why the profile is being switched, such as due// to a client connecting or disconnecting or a change in the desktop// session state. It is used for logging.SwitchToBestProfileAsync(reasonstring)}

ProfileServices provides access to theHost's profile management services,such as switching profiles and registering profile change callbacks.

typeProfileStateChangeCallback

type ProfileStateChangeCallback func(_ipn.LoginProfileView, _ipn.PrefsView, sameNodebool)

ProfileStateChangeCallback is a function to be called when the current login profileor its preferences change.

The sameNode parameter indicates whether the profile represents the same node as before,which is true when:

It can be used to decide whether to reset state bound to the current profile or node identity.

The profile and prefs are always valid, but the profile'sipn.LoginProfileView.IDreturns "" if the profile is new and has not been persisted yet.

typeProfileStore

type ProfileStore interface {// CurrentUserID returns the current user ID. It is only non-empty on// Windows where we have a multi-user system.//// Deprecated: this method exists for compatibility with the current (as of 2024-08-27)// permission model and will be removed as we progress on tailscale/corp#18342.CurrentUserID()ipn.WindowsUserID// CurrentProfile returns a read-only [ipn.LoginProfileView] of the current profile.// The returned view is always valid, but the profile's [ipn.LoginProfileView.ID]// returns "" if the profile is new and has not been persisted yet.CurrentProfile()ipn.LoginProfileView// CurrentPrefs returns a read-only view of the current prefs.// The returned view is always valid.CurrentPrefs()ipn.PrefsView// DefaultUserProfile returns a read-only view of the default (last used) profile for the specified user.// It returns a read-only view of a new, non-persisted profile if the specified user does not have a default profile.DefaultUserProfile(uidipn.WindowsUserID)ipn.LoginProfileView}

ProfileStore provides read-only access to available login profiles and their preferences.It is not safe for concurrent use and can only be used from the callback it is passed to.

typeSafeBackend

type SafeBackend interface {Sys() *tsd.SystemClock()tstime.ClockTailscaleVarRoot()string}

SafeBackend is a subset of the [ipnlocal.LocalBackend] type's methods thatare safe to call from extension hooks at any time (even hooks called whileLocalBackend's internal mutex is held).

Source Files

View all Source files

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f orF : Jump to
y orY : Canonical URL
go.dev uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic.Learn more.

[8]ページ先頭

©2009-2025 Movatter.jp