|
|
|
|
@ -876,6 +876,7 @@ func (b *LocalBackend) initPrefsFromConfig(conf *conffile.Config) error {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *LocalBackend) setStaticEndpointsFromConfigLocked(conf *conffile.Config) {
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
if conf.Parsed.StaticEndpoints == nil && (b.conf == nil || b.conf.Parsed.StaticEndpoints == nil) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
@ -894,6 +895,7 @@ func (b *LocalBackend) setStaticEndpointsFromConfigLocked(conf *conffile.Config)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *LocalBackend) setStateLocked(state ipn.State) {
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
if b.state == state {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
@ -906,6 +908,7 @@ func (b *LocalBackend) setStateLocked(state ipn.State) {
|
|
|
|
|
// setConfigLocked uses the provided config to update the backend's prefs
|
|
|
|
|
// and other state.
|
|
|
|
|
func (b *LocalBackend) setConfigLocked(conf *conffile.Config) error {
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
p := b.pm.CurrentPrefs().AsStruct()
|
|
|
|
|
mp, err := conf.Parsed.ToPrefs()
|
|
|
|
|
if err != nil {
|
|
|
|
|
@ -927,6 +930,7 @@ var assumeNetworkUpdateForTest = envknob.RegisterBool("TS_ASSUME_NETWORK_UP_FOR_
|
|
|
|
|
//
|
|
|
|
|
// b.mu must be held.
|
|
|
|
|
func (b *LocalBackend) pauseOrResumeControlClientLocked() {
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
if b.cc == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
@ -1204,6 +1208,7 @@ func (b *LocalBackend) Prefs() ipn.PrefsView {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *LocalBackend) sanitizedPrefsLocked() ipn.PrefsView {
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
return stripKeysFromPrefs(b.pm.CurrentPrefs())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -1335,6 +1340,7 @@ func (b *LocalBackend) UpdateStatus(sb *ipnstate.StatusBuilder) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *LocalBackend) populatePeerStatusLocked(sb *ipnstate.StatusBuilder) {
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
cn := b.currentNode()
|
|
|
|
|
nm := cn.NetMap()
|
|
|
|
|
if nm == nil {
|
|
|
|
|
@ -1873,6 +1879,8 @@ func (b *LocalBackend) applySysPolicyLocked(prefs *ipn.Prefs) (anyChange bool) {
|
|
|
|
|
if !buildfeatures.HasSystemPolicy {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
|
|
|
|
|
if controlURL, err := b.polc.GetString(pkey.ControlURL, prefs.ControlURL); err == nil && prefs.ControlURL != controlURL {
|
|
|
|
|
prefs.ControlURL = controlURL
|
|
|
|
|
anyChange = true
|
|
|
|
|
@ -1941,6 +1949,8 @@ func (b *LocalBackend) applyExitNodeSysPolicyLocked(prefs *ipn.Prefs) (anyChange
|
|
|
|
|
if !buildfeatures.HasUseExitNode {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
|
|
|
|
|
if exitNodeIDStr, _ := b.polc.GetString(pkey.ExitNodeID, ""); exitNodeIDStr != "" {
|
|
|
|
|
exitNodeID := tailcfg.StableNodeID(exitNodeIDStr)
|
|
|
|
|
|
|
|
|
|
@ -2182,6 +2192,8 @@ func (b *LocalBackend) resolveAutoExitNodeLocked(prefs *ipn.Prefs) (prefsChanged
|
|
|
|
|
if !buildfeatures.HasUseExitNode {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
|
|
|
|
|
// As of 2025-07-08, the only supported auto exit node expression is [ipn.AnyExitNode].
|
|
|
|
|
//
|
|
|
|
|
// However, to maintain forward compatibility with future auto exit node expressions,
|
|
|
|
|
@ -2295,6 +2307,8 @@ func (b *LocalBackend) setWgengineStatus(s *wgengine.Status, err error) {
|
|
|
|
|
//
|
|
|
|
|
// b.mu must be held.
|
|
|
|
|
func (b *LocalBackend) setWgengineStatusLocked(s *wgengine.Status) {
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
|
|
|
|
|
es := b.parseWgStatusLocked(s)
|
|
|
|
|
cc := b.cc
|
|
|
|
|
|
|
|
|
|
@ -4312,6 +4326,7 @@ func (b *LocalBackend) EditPrefsAs(mp *ipn.MaskedPrefs, actor ipnauth.Actor) (ip
|
|
|
|
|
//
|
|
|
|
|
// b.mu must be held.
|
|
|
|
|
func (b *LocalBackend) checkEditPrefsAccessLocked(actor ipnauth.Actor, prefs ipn.PrefsView, mp *ipn.MaskedPrefs) error {
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
var errs []error
|
|
|
|
|
|
|
|
|
|
if mp.RunSSHSet && mp.RunSSH && !envknob.CanSSHD() {
|
|
|
|
|
@ -4362,6 +4377,7 @@ func (b *LocalBackend) checkEditPrefsAccessLocked(actor ipnauth.Actor, prefs ipn
|
|
|
|
|
//
|
|
|
|
|
// b.mu must be held.
|
|
|
|
|
func (b *LocalBackend) changeDisablesExitNodeLocked(prefs ipn.PrefsView, change *ipn.MaskedPrefs) bool {
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
if !buildfeatures.HasUseExitNode {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
@ -4403,6 +4419,7 @@ func (b *LocalBackend) changeDisablesExitNodeLocked(prefs ipn.PrefsView, change
|
|
|
|
|
//
|
|
|
|
|
// b.mu must be held.
|
|
|
|
|
func (b *LocalBackend) adjustEditPrefsLocked(prefs ipn.PrefsView, mp *ipn.MaskedPrefs) {
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
// Zeroing the ExitNodeID via localAPI must also zero the prior exit node.
|
|
|
|
|
if mp.ExitNodeIDSet && mp.ExitNodeID == "" && !mp.InternalExitNodePriorSet {
|
|
|
|
|
mp.InternalExitNodePrior = ""
|
|
|
|
|
@ -4480,6 +4497,7 @@ func (b *LocalBackend) onEditPrefsLocked(_ ipnauth.Actor, mp *ipn.MaskedPrefs, o
|
|
|
|
|
// startReconnectTimerLocked sets a timer to automatically set WantRunning to true
|
|
|
|
|
// after the specified duration.
|
|
|
|
|
func (b *LocalBackend) startReconnectTimerLocked(d time.Duration) {
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
if b.reconnectTimer != nil {
|
|
|
|
|
// Stop may return false if the timer has already fired,
|
|
|
|
|
// and the function has been called in its own goroutine,
|
|
|
|
|
@ -4522,11 +4540,13 @@ func (b *LocalBackend) startReconnectTimerLocked(d time.Duration) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *LocalBackend) resetAlwaysOnOverrideLocked() {
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
b.overrideAlwaysOn = false
|
|
|
|
|
b.stopReconnectTimerLocked()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *LocalBackend) stopReconnectTimerLocked() {
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
if b.reconnectTimer != nil {
|
|
|
|
|
// Stop may return false if the timer has already fired,
|
|
|
|
|
// and the function has been called in its own goroutine,
|
|
|
|
|
@ -4542,6 +4562,7 @@ func (b *LocalBackend) stopReconnectTimerLocked() {
|
|
|
|
|
|
|
|
|
|
// b.mu must be held.
|
|
|
|
|
func (b *LocalBackend) editPrefsLocked(actor ipnauth.Actor, mp *ipn.MaskedPrefs) (ipn.PrefsView, error) {
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
p0 := b.pm.CurrentPrefs()
|
|
|
|
|
|
|
|
|
|
// Check if the changes in mp are allowed.
|
|
|
|
|
@ -5660,6 +5681,7 @@ func (b *LocalBackend) enterStateLocked(newState ipn.State) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *LocalBackend) hasNodeKeyLocked() bool {
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
// we can't use b.Prefs(), because it strips the keys, oops!
|
|
|
|
|
p := b.pm.CurrentPrefs()
|
|
|
|
|
return p.Valid() && p.Persist().Valid() && !p.Persist().PrivateNodeKey().IsZero()
|
|
|
|
|
@ -5680,9 +5702,11 @@ func (b *LocalBackend) NodeKey() key.NodePublic {
|
|
|
|
|
//
|
|
|
|
|
// b.mu must be held
|
|
|
|
|
func (b *LocalBackend) nextStateLocked() ipn.State {
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
if b.health.IsUnhealthy(ipn.StateStoreHealth) {
|
|
|
|
|
return ipn.NoState
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var (
|
|
|
|
|
cc = b.cc
|
|
|
|
|
cn = b.currentNode()
|
|
|
|
|
@ -5758,6 +5782,8 @@ func (b *LocalBackend) nextStateLocked() ipn.State {
|
|
|
|
|
//
|
|
|
|
|
// requires b.mu to be held.
|
|
|
|
|
func (b *LocalBackend) stateMachineLocked() {
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
|
|
|
|
|
b.enterStateLocked(b.nextStateLocked())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -5767,6 +5793,7 @@ func (b *LocalBackend) stateMachineLocked() {
|
|
|
|
|
//
|
|
|
|
|
// b.mu must be held.
|
|
|
|
|
func (b *LocalBackend) stopEngineAndWaitLocked() {
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
b.logf("stopEngineAndWait...")
|
|
|
|
|
st, _ := b.e.ResetAndStop() // TODO: what should we do if this returns an error?
|
|
|
|
|
b.setWgengineStatusLocked(st)
|
|
|
|
|
@ -5787,6 +5814,7 @@ func (b *LocalBackend) setControlClientLocked(cc controlclient.Client) {
|
|
|
|
|
// returned value is non-nil, the caller must call Shutdown on it after
|
|
|
|
|
// releasing b.mu.
|
|
|
|
|
func (b *LocalBackend) resetControlClientLocked() controlclient.Client {
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
if b.cc == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
@ -5813,6 +5841,8 @@ func (b *LocalBackend) resetControlClientLocked() controlclient.Client {
|
|
|
|
|
|
|
|
|
|
// resetAuthURLLocked resets authURL, canceling any pending interactive login.
|
|
|
|
|
func (b *LocalBackend) resetAuthURLLocked() {
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
|
|
|
|
|
b.authURL = ""
|
|
|
|
|
b.authURLTime = time.Time{}
|
|
|
|
|
b.authActor = nil
|
|
|
|
|
@ -5842,6 +5872,8 @@ func (b *LocalBackend) ShouldExposeRemoteWebClient() bool {
|
|
|
|
|
//
|
|
|
|
|
// b.mu must be held.
|
|
|
|
|
func (b *LocalBackend) setWebClientAtomicBoolLocked(nm *netmap.NetworkMap) {
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
|
|
|
|
|
shouldRun := !nm.HasCap(tailcfg.NodeAttrDisableWebClient)
|
|
|
|
|
wasRunning := b.webClientAtomicBool.Swap(shouldRun)
|
|
|
|
|
if wasRunning && !shouldRun {
|
|
|
|
|
@ -5854,6 +5886,8 @@ func (b *LocalBackend) setWebClientAtomicBoolLocked(nm *netmap.NetworkMap) {
|
|
|
|
|
//
|
|
|
|
|
// b.mu must be held.
|
|
|
|
|
func (b *LocalBackend) setExposeRemoteWebClientAtomicBoolLocked(prefs ipn.PrefsView) {
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
|
|
|
|
|
if !buildfeatures.HasWebClient {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
@ -5982,6 +6016,8 @@ func (b *LocalBackend) RefreshExitNode() {
|
|
|
|
|
|
|
|
|
|
// refreshExitNodeLocked is like RefreshExitNode but requires b.mu be held.
|
|
|
|
|
func (b *LocalBackend) refreshExitNodeLocked() {
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
|
|
|
|
|
if b.resolveExitNodeLocked() {
|
|
|
|
|
b.authReconfigLocked()
|
|
|
|
|
}
|
|
|
|
|
@ -5997,6 +6033,8 @@ func (b *LocalBackend) refreshExitNodeLocked() {
|
|
|
|
|
//
|
|
|
|
|
// b.mu must be held.
|
|
|
|
|
func (b *LocalBackend) resolveExitNodeLocked() (changed bool) {
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
|
|
|
|
|
if !buildfeatures.HasUseExitNode {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
@ -6058,6 +6096,7 @@ func (b *LocalBackend) reconcilePrefsLocked(prefs *ipn.Prefs) (changed bool) {
|
|
|
|
|
//
|
|
|
|
|
// b.mu must be held.
|
|
|
|
|
func (b *LocalBackend) resolveExitNodeInPrefsLocked(prefs *ipn.Prefs) (changed bool) {
|
|
|
|
|
syncs.RequiresMutex(&b.mu)
|
|
|
|
|
if !buildfeatures.HasUseExitNode {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|