map.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. package controlclient
  4. import (
  5. "context"
  6. "encoding/json"
  7. "fmt"
  8. "net"
  9. "net/netip"
  10. "reflect"
  11. "slices"
  12. "sort"
  13. "strconv"
  14. "sync"
  15. "time"
  16. "tailscale.com/control/controlknobs"
  17. "tailscale.com/envknob"
  18. "tailscale.com/tailcfg"
  19. "tailscale.com/tstime"
  20. "tailscale.com/types/key"
  21. "tailscale.com/types/logger"
  22. "tailscale.com/types/netmap"
  23. "tailscale.com/types/ptr"
  24. "tailscale.com/types/views"
  25. "tailscale.com/util/clientmetric"
  26. "tailscale.com/util/cmpx"
  27. "tailscale.com/wgengine/filter"
  28. )
  29. // mapSession holds the state over a long-polled "map" request to the
  30. // control plane.
  31. //
  32. // It accepts incremental tailcfg.MapResponse values to
  33. // netMapForResponse and returns fully inflated NetworkMaps, filling
  34. // in the omitted data implicit from prior MapResponse values from
  35. // within the same session (the same long-poll HTTP response to the
  36. // one MapRequest).
  37. type mapSession struct {
  38. // Immutable fields.
  39. netmapUpdater NetmapUpdater // called on changes (in addition to the optional hooks below)
  40. controlKnobs *controlknobs.Knobs // or nil
  41. privateNodeKey key.NodePrivate
  42. publicNodeKey key.NodePublic
  43. logf logger.Logf
  44. vlogf logger.Logf
  45. machinePubKey key.MachinePublic
  46. altClock tstime.Clock // if nil, regular time is used
  47. cancel context.CancelFunc // always non-nil, shuts down caller's base long poll context
  48. watchdogReset chan struct{} // send to request that the long poll activity watchdog timeout be reset
  49. // sessionAliveCtx is a Background-based context that's alive for the
  50. // duration of the mapSession that we own the lifetime of. It's closed by
  51. // sessionAliveCtxClose.
  52. sessionAliveCtx context.Context
  53. sessionAliveCtxClose context.CancelFunc // closes sessionAliveCtx
  54. // Optional hooks, set once before use.
  55. // onDebug specifies what to do with a *tailcfg.Debug message.
  56. // If the watchdogReset chan is nil, it's not used. Otherwise it can be sent to
  57. // to request that the long poll activity watchdog timeout be reset.
  58. onDebug func(_ context.Context, _ *tailcfg.Debug, watchdogReset chan<- struct{}) error
  59. // onConciseNetMapSummary, if non-nil, is called with the Netmap.VeryConcise summary
  60. // whenever a map response is received.
  61. onConciseNetMapSummary func(string)
  62. // onSelfNodeChanged is called before the NetmapUpdater if the self node was
  63. // changed.
  64. onSelfNodeChanged func(*netmap.NetworkMap)
  65. // Fields storing state over the course of multiple MapResponses.
  66. lastNode tailcfg.NodeView
  67. peers map[tailcfg.NodeID]*tailcfg.NodeView // pointer to view (oddly). same pointers as sortedPeers.
  68. sortedPeers []*tailcfg.NodeView // same pointers as peers, but sorted by Node.ID
  69. lastDNSConfig *tailcfg.DNSConfig
  70. lastDERPMap *tailcfg.DERPMap
  71. lastUserProfile map[tailcfg.UserID]tailcfg.UserProfile
  72. lastPacketFilterRules views.Slice[tailcfg.FilterRule]
  73. lastParsedPacketFilter []filter.Match
  74. lastSSHPolicy *tailcfg.SSHPolicy
  75. collectServices bool
  76. lastDomain string
  77. lastDomainAuditLogID string
  78. lastHealth []string
  79. lastPopBrowserURL string
  80. stickyDebug tailcfg.Debug // accumulated opt.Bool values
  81. lastTKAInfo *tailcfg.TKAInfo
  82. lastNetmapSummary string // from NetworkMap.VeryConcise
  83. }
  84. // newMapSession returns a mostly unconfigured new mapSession.
  85. //
  86. // Modify its optional fields on the returned value before use.
  87. //
  88. // It must have its Close method called to release resources.
  89. func newMapSession(privateNodeKey key.NodePrivate, nu NetmapUpdater, controlKnobs *controlknobs.Knobs) *mapSession {
  90. ms := &mapSession{
  91. netmapUpdater: nu,
  92. controlKnobs: controlKnobs,
  93. privateNodeKey: privateNodeKey,
  94. publicNodeKey: privateNodeKey.Public(),
  95. lastDNSConfig: new(tailcfg.DNSConfig),
  96. lastUserProfile: map[tailcfg.UserID]tailcfg.UserProfile{},
  97. watchdogReset: make(chan struct{}),
  98. // Non-nil no-op defaults, to be optionally overridden by the caller.
  99. logf: logger.Discard,
  100. vlogf: logger.Discard,
  101. cancel: func() {},
  102. onDebug: func(context.Context, *tailcfg.Debug, chan<- struct{}) error { return nil },
  103. onConciseNetMapSummary: func(string) {},
  104. onSelfNodeChanged: func(*netmap.NetworkMap) {},
  105. }
  106. ms.sessionAliveCtx, ms.sessionAliveCtxClose = context.WithCancel(context.Background())
  107. return ms
  108. }
  109. func (ms *mapSession) clock() tstime.Clock {
  110. return cmpx.Or[tstime.Clock](ms.altClock, tstime.StdClock{})
  111. }
  112. // StartWatchdog starts the session's watchdog timer.
  113. // If there's no activity in too long, it tears down the connection.
  114. // Call Close to release these resources.
  115. func (ms *mapSession) StartWatchdog() {
  116. timer, timedOutChan := ms.clock().NewTimer(watchdogTimeout)
  117. go func() {
  118. defer timer.Stop()
  119. for {
  120. select {
  121. case <-ms.sessionAliveCtx.Done():
  122. ms.vlogf("netmap: ending timeout goroutine")
  123. return
  124. case <-timedOutChan:
  125. ms.logf("map response long-poll timed out!")
  126. ms.cancel()
  127. return
  128. case <-ms.watchdogReset:
  129. if !timer.Stop() {
  130. select {
  131. case <-timedOutChan:
  132. case <-ms.sessionAliveCtx.Done():
  133. ms.vlogf("netmap: ending timeout goroutine")
  134. return
  135. }
  136. }
  137. ms.vlogf("netmap: reset timeout timer")
  138. timer.Reset(watchdogTimeout)
  139. }
  140. }
  141. }()
  142. }
  143. func (ms *mapSession) Close() {
  144. ms.sessionAliveCtxClose()
  145. }
  146. // HandleNonKeepAliveMapResponse handles a non-KeepAlive MapResponse (full or
  147. // incremental).
  148. //
  149. // All fields that are valid on a KeepAlive MapResponse have already been
  150. // handled.
  151. //
  152. // TODO(bradfitz): make this handle all fields later. For now (2023-08-20) this
  153. // is [re]factoring progress enough.
  154. func (ms *mapSession) HandleNonKeepAliveMapResponse(ctx context.Context, resp *tailcfg.MapResponse) error {
  155. if debug := resp.Debug; debug != nil {
  156. if err := ms.onDebug(ctx, debug, ms.watchdogReset); err != nil {
  157. return err
  158. }
  159. }
  160. if DevKnob.StripEndpoints() {
  161. for _, p := range resp.Peers {
  162. p.Endpoints = nil
  163. }
  164. for _, p := range resp.PeersChanged {
  165. p.Endpoints = nil
  166. }
  167. }
  168. // For responses that mutate the self node, check for updated nodeAttrs.
  169. if resp.Node != nil {
  170. if DevKnob.StripCaps() {
  171. resp.Node.Capabilities = nil
  172. resp.Node.CapMap = nil
  173. }
  174. ms.controlKnobs.UpdateFromNodeAttributes(resp.Node.Capabilities, resp.Node.CapMap)
  175. }
  176. // Call Node.InitDisplayNames on any changed nodes.
  177. initDisplayNames(cmpx.Or(resp.Node.View(), ms.lastNode), resp)
  178. ms.patchifyPeersChanged(resp)
  179. ms.updateStateFromResponse(resp)
  180. if ms.tryHandleIncrementally(resp) {
  181. ms.onConciseNetMapSummary(ms.lastNetmapSummary) // every 5s log
  182. return nil
  183. }
  184. // We have to rebuild the whole netmap (lots of garbage & work downstream of
  185. // our UpdateFullNetmap call). This is the part we tried to avoid but
  186. // some field mutations (especially rare ones) aren't yet handled.
  187. nm := ms.netmap()
  188. ms.lastNetmapSummary = nm.VeryConcise()
  189. ms.onConciseNetMapSummary(ms.lastNetmapSummary)
  190. // If the self node changed, we might need to update persist.
  191. if resp.Node != nil {
  192. ms.onSelfNodeChanged(nm)
  193. }
  194. ms.netmapUpdater.UpdateFullNetmap(nm)
  195. return nil
  196. }
  197. func (ms *mapSession) tryHandleIncrementally(res *tailcfg.MapResponse) bool {
  198. if ms.controlKnobs != nil && ms.controlKnobs.DisableDeltaUpdates.Load() {
  199. return false
  200. }
  201. nud, ok := ms.netmapUpdater.(NetmapDeltaUpdater)
  202. if !ok {
  203. return false
  204. }
  205. mutations, ok := netmap.MutationsFromMapResponse(res, time.Now())
  206. if ok && len(mutations) > 0 {
  207. return nud.UpdateNetmapDelta(mutations)
  208. }
  209. return ok
  210. }
  211. // updateStats are some stats from updateStateFromResponse, primarily for
  212. // testing. It's meant to be cheap enough to always compute, though. It doesn't
  213. // allocate.
  214. type updateStats struct {
  215. allNew bool
  216. added int
  217. removed int
  218. changed int
  219. }
  220. // updateStateFromResponse updates ms from res. It takes ownership of res.
  221. func (ms *mapSession) updateStateFromResponse(resp *tailcfg.MapResponse) {
  222. ms.updatePeersStateFromResponse(resp)
  223. if resp.Node != nil {
  224. ms.lastNode = resp.Node.View()
  225. }
  226. for _, up := range resp.UserProfiles {
  227. ms.lastUserProfile[up.ID] = up
  228. }
  229. // TODO(bradfitz): clean up old user profiles? maybe not worth it.
  230. if dm := resp.DERPMap; dm != nil {
  231. ms.vlogf("netmap: new map contains DERP map")
  232. // Zero-valued fields in a DERPMap mean that we're not changing
  233. // anything and are using the previous value(s).
  234. if ldm := ms.lastDERPMap; ldm != nil {
  235. if dm.Regions == nil {
  236. dm.Regions = ldm.Regions
  237. dm.OmitDefaultRegions = ldm.OmitDefaultRegions
  238. }
  239. if dm.HomeParams == nil {
  240. dm.HomeParams = ldm.HomeParams
  241. } else if oldhh := ldm.HomeParams; oldhh != nil {
  242. // Propagate sub-fields of HomeParams
  243. hh := dm.HomeParams
  244. if hh.RegionScore == nil {
  245. hh.RegionScore = oldhh.RegionScore
  246. }
  247. }
  248. }
  249. ms.lastDERPMap = dm
  250. }
  251. if pf := resp.PacketFilter; pf != nil {
  252. var err error
  253. ms.lastPacketFilterRules = views.SliceOf(pf)
  254. ms.lastParsedPacketFilter, err = filter.MatchesFromFilterRules(pf)
  255. if err != nil {
  256. ms.logf("parsePacketFilter: %v", err)
  257. }
  258. }
  259. if c := resp.DNSConfig; c != nil {
  260. ms.lastDNSConfig = c
  261. }
  262. if p := resp.SSHPolicy; p != nil {
  263. ms.lastSSHPolicy = p
  264. }
  265. if v, ok := resp.CollectServices.Get(); ok {
  266. ms.collectServices = v
  267. }
  268. if resp.Domain != "" {
  269. ms.lastDomain = resp.Domain
  270. }
  271. if resp.DomainDataPlaneAuditLogID != "" {
  272. ms.lastDomainAuditLogID = resp.DomainDataPlaneAuditLogID
  273. }
  274. if resp.Health != nil {
  275. ms.lastHealth = resp.Health
  276. }
  277. if resp.TKAInfo != nil {
  278. ms.lastTKAInfo = resp.TKAInfo
  279. }
  280. }
  281. var (
  282. patchDERPRegion = clientmetric.NewCounter("controlclient_patch_derp")
  283. patchEndpoints = clientmetric.NewCounter("controlclient_patch_endpoints")
  284. patchCap = clientmetric.NewCounter("controlclient_patch_capver")
  285. patchKey = clientmetric.NewCounter("controlclient_patch_key")
  286. patchDiscoKey = clientmetric.NewCounter("controlclient_patch_discokey")
  287. patchOnline = clientmetric.NewCounter("controlclient_patch_online")
  288. patchLastSeen = clientmetric.NewCounter("controlclient_patch_lastseen")
  289. patchKeyExpiry = clientmetric.NewCounter("controlclient_patch_keyexpiry")
  290. patchCapabilities = clientmetric.NewCounter("controlclient_patch_capabilities")
  291. patchCapMap = clientmetric.NewCounter("controlclient_patch_capmap")
  292. patchKeySignature = clientmetric.NewCounter("controlclient_patch_keysig")
  293. patchifiedPeer = clientmetric.NewCounter("controlclient_patchified_peer")
  294. patchifiedPeerEqual = clientmetric.NewCounter("controlclient_patchified_peer_equal")
  295. )
  296. // updatePeersStateFromResponseres updates ms.peers and ms.sortedPeers from res. It takes ownership of res.
  297. func (ms *mapSession) updatePeersStateFromResponse(resp *tailcfg.MapResponse) (stats updateStats) {
  298. defer func() {
  299. if stats.removed > 0 || stats.added > 0 {
  300. ms.rebuildSorted()
  301. }
  302. }()
  303. if ms.peers == nil {
  304. ms.peers = make(map[tailcfg.NodeID]*tailcfg.NodeView)
  305. }
  306. if len(resp.Peers) > 0 {
  307. // Not delta encoded.
  308. stats.allNew = true
  309. keep := make(map[tailcfg.NodeID]bool, len(resp.Peers))
  310. for _, n := range resp.Peers {
  311. keep[n.ID] = true
  312. if vp, ok := ms.peers[n.ID]; ok {
  313. stats.changed++
  314. *vp = n.View()
  315. } else {
  316. stats.added++
  317. ms.peers[n.ID] = ptr.To(n.View())
  318. }
  319. }
  320. for id := range ms.peers {
  321. if !keep[id] {
  322. stats.removed++
  323. delete(ms.peers, id)
  324. }
  325. }
  326. // Peers precludes all other delta operations so just return.
  327. return
  328. }
  329. for _, id := range resp.PeersRemoved {
  330. if _, ok := ms.peers[id]; ok {
  331. delete(ms.peers, id)
  332. stats.removed++
  333. }
  334. }
  335. for _, n := range resp.PeersChanged {
  336. if vp, ok := ms.peers[n.ID]; ok {
  337. stats.changed++
  338. *vp = n.View()
  339. } else {
  340. stats.added++
  341. ms.peers[n.ID] = ptr.To(n.View())
  342. }
  343. }
  344. for nodeID, seen := range resp.PeerSeenChange {
  345. if vp, ok := ms.peers[nodeID]; ok {
  346. mut := vp.AsStruct()
  347. if seen {
  348. mut.LastSeen = ptr.To(clock.Now())
  349. } else {
  350. mut.LastSeen = nil
  351. }
  352. *vp = mut.View()
  353. stats.changed++
  354. }
  355. }
  356. for nodeID, online := range resp.OnlineChange {
  357. if vp, ok := ms.peers[nodeID]; ok {
  358. mut := vp.AsStruct()
  359. mut.Online = ptr.To(online)
  360. *vp = mut.View()
  361. stats.changed++
  362. }
  363. }
  364. for _, pc := range resp.PeersChangedPatch {
  365. vp, ok := ms.peers[pc.NodeID]
  366. if !ok {
  367. continue
  368. }
  369. stats.changed++
  370. mut := vp.AsStruct()
  371. if pc.DERPRegion != 0 {
  372. mut.DERP = fmt.Sprintf("%s:%v", tailcfg.DerpMagicIP, pc.DERPRegion)
  373. patchDERPRegion.Add(1)
  374. }
  375. if pc.Cap != 0 {
  376. mut.Cap = pc.Cap
  377. patchCap.Add(1)
  378. }
  379. if pc.Endpoints != nil {
  380. mut.Endpoints = pc.Endpoints
  381. patchEndpoints.Add(1)
  382. }
  383. if pc.Key != nil {
  384. mut.Key = *pc.Key
  385. patchKey.Add(1)
  386. }
  387. if pc.DiscoKey != nil {
  388. mut.DiscoKey = *pc.DiscoKey
  389. patchDiscoKey.Add(1)
  390. }
  391. if v := pc.Online; v != nil {
  392. mut.Online = ptr.To(*v)
  393. patchOnline.Add(1)
  394. }
  395. if v := pc.LastSeen; v != nil {
  396. mut.LastSeen = ptr.To(*v)
  397. patchLastSeen.Add(1)
  398. }
  399. if v := pc.KeyExpiry; v != nil {
  400. mut.KeyExpiry = *v
  401. patchKeyExpiry.Add(1)
  402. }
  403. if v := pc.Capabilities; v != nil {
  404. mut.Capabilities = *v
  405. patchCapabilities.Add(1)
  406. }
  407. if v := pc.KeySignature; v != nil {
  408. mut.KeySignature = v
  409. patchKeySignature.Add(1)
  410. }
  411. if v := pc.CapMap; v != nil {
  412. mut.CapMap = v
  413. patchCapMap.Add(1)
  414. }
  415. *vp = mut.View()
  416. }
  417. return
  418. }
  419. // rebuildSorted rebuilds ms.sortedPeers from ms.peers. It should be called
  420. // after any additions or removals from peers.
  421. func (ms *mapSession) rebuildSorted() {
  422. if ms.sortedPeers == nil {
  423. ms.sortedPeers = make([]*tailcfg.NodeView, 0, len(ms.peers))
  424. } else {
  425. if len(ms.sortedPeers) > len(ms.peers) {
  426. clear(ms.sortedPeers[len(ms.peers):])
  427. }
  428. ms.sortedPeers = ms.sortedPeers[:0]
  429. }
  430. for _, p := range ms.peers {
  431. ms.sortedPeers = append(ms.sortedPeers, p)
  432. }
  433. sort.Slice(ms.sortedPeers, func(i, j int) bool {
  434. return ms.sortedPeers[i].ID() < ms.sortedPeers[j].ID()
  435. })
  436. }
  437. func (ms *mapSession) addUserProfile(nm *netmap.NetworkMap, userID tailcfg.UserID) {
  438. if userID == 0 {
  439. return
  440. }
  441. if _, dup := nm.UserProfiles[userID]; dup {
  442. // Already populated it from a previous peer.
  443. return
  444. }
  445. if up, ok := ms.lastUserProfile[userID]; ok {
  446. nm.UserProfiles[userID] = up
  447. }
  448. }
  449. var debugPatchifyPeer = envknob.RegisterBool("TS_DEBUG_PATCHIFY_PEER")
  450. // patchifyPeersChanged mutates resp to promote PeersChanged entries to PeersChangedPatch
  451. // when possible.
  452. func (ms *mapSession) patchifyPeersChanged(resp *tailcfg.MapResponse) {
  453. filtered := resp.PeersChanged[:0]
  454. for _, n := range resp.PeersChanged {
  455. if p, ok := ms.patchifyPeer(n); ok {
  456. patchifiedPeer.Add(1)
  457. if debugPatchifyPeer() {
  458. patchj, _ := json.Marshal(p)
  459. ms.logf("debug: patchifyPeer[ID=%v]: %s", n.ID, patchj)
  460. }
  461. if p != nil {
  462. resp.PeersChangedPatch = append(resp.PeersChangedPatch, p)
  463. } else {
  464. patchifiedPeerEqual.Add(1)
  465. }
  466. } else {
  467. filtered = append(filtered, n)
  468. }
  469. }
  470. resp.PeersChanged = filtered
  471. if len(resp.PeersChanged) == 0 {
  472. resp.PeersChanged = nil
  473. }
  474. }
  475. var nodeFields = sync.OnceValue(getNodeFields)
  476. // getNodeFields returns the fails of tailcfg.Node.
  477. func getNodeFields() []string {
  478. rt := reflect.TypeOf((*tailcfg.Node)(nil)).Elem()
  479. ret := make([]string, rt.NumField())
  480. for i := 0; i < rt.NumField(); i++ {
  481. ret[i] = rt.Field(i).Name
  482. }
  483. return ret
  484. }
  485. // patchifyPeer returns a *tailcfg.PeerChange of the session's existing copy of
  486. // the n.ID Node to n.
  487. //
  488. // It returns ok=false if a patch can't be made, (V, ok) on a delta, or (nil,
  489. // true) if all the fields were identical (a zero change).
  490. func (ms *mapSession) patchifyPeer(n *tailcfg.Node) (_ *tailcfg.PeerChange, ok bool) {
  491. was, ok := ms.peers[n.ID]
  492. if !ok {
  493. return nil, false
  494. }
  495. return peerChangeDiff(*was, n)
  496. }
  497. // peerChangeDiff returns the difference from 'was' to 'n', if possible.
  498. //
  499. // It returns (nil, true) if the fields were identical.
  500. func peerChangeDiff(was tailcfg.NodeView, n *tailcfg.Node) (_ *tailcfg.PeerChange, ok bool) {
  501. var ret *tailcfg.PeerChange
  502. pc := func() *tailcfg.PeerChange {
  503. if ret == nil {
  504. ret = new(tailcfg.PeerChange)
  505. }
  506. return ret
  507. }
  508. for _, field := range nodeFields() {
  509. switch field {
  510. default:
  511. // The whole point of using reflect in this function is to panic
  512. // here in tests if we forget to handle a new field.
  513. panic("unhandled field: " + field)
  514. case "computedHostIfDifferent", "ComputedName", "ComputedNameWithHost":
  515. // Caller's responsibility to have populated these.
  516. continue
  517. case "DataPlaneAuditLogID":
  518. // Not sent for peers.
  519. case "ID":
  520. if was.ID() != n.ID {
  521. return nil, false
  522. }
  523. case "StableID":
  524. if was.StableID() != n.StableID {
  525. return nil, false
  526. }
  527. case "Name":
  528. if was.Name() != n.Name {
  529. return nil, false
  530. }
  531. case "User":
  532. if was.User() != n.User {
  533. return nil, false
  534. }
  535. case "Sharer":
  536. if was.Sharer() != n.Sharer {
  537. return nil, false
  538. }
  539. case "Key":
  540. if was.Key() != n.Key {
  541. pc().Key = ptr.To(n.Key)
  542. }
  543. case "KeyExpiry":
  544. if !was.KeyExpiry().Equal(n.KeyExpiry) {
  545. pc().KeyExpiry = ptr.To(n.KeyExpiry)
  546. }
  547. case "KeySignature":
  548. if !was.KeySignature().Equal(n.KeySignature) {
  549. pc().KeySignature = slices.Clone(n.KeySignature)
  550. }
  551. case "Machine":
  552. if was.Machine() != n.Machine {
  553. return nil, false
  554. }
  555. case "DiscoKey":
  556. if was.DiscoKey() != n.DiscoKey {
  557. pc().DiscoKey = ptr.To(n.DiscoKey)
  558. }
  559. case "Addresses":
  560. if !views.SliceEqual(was.Addresses(), views.SliceOf(n.Addresses)) {
  561. return nil, false
  562. }
  563. case "AllowedIPs":
  564. if !views.SliceEqual(was.AllowedIPs(), views.SliceOf(n.AllowedIPs)) {
  565. return nil, false
  566. }
  567. case "Endpoints":
  568. if !views.SliceEqual(was.Endpoints(), views.SliceOf(n.Endpoints)) {
  569. pc().Endpoints = slices.Clone(n.Endpoints)
  570. }
  571. case "DERP":
  572. if was.DERP() != n.DERP {
  573. ip, portStr, err := net.SplitHostPort(n.DERP)
  574. if err != nil || ip != "127.3.3.40" {
  575. return nil, false
  576. }
  577. port, err := strconv.Atoi(portStr)
  578. if err != nil || port < 1 || port > 65535 {
  579. return nil, false
  580. }
  581. pc().DERPRegion = port
  582. }
  583. case "Hostinfo":
  584. if !was.Hostinfo().Valid() && !n.Hostinfo.Valid() {
  585. continue
  586. }
  587. if !was.Hostinfo().Valid() || !n.Hostinfo.Valid() {
  588. return nil, false
  589. }
  590. if !was.Hostinfo().Equal(n.Hostinfo) {
  591. return nil, false
  592. }
  593. case "Created":
  594. if !was.Created().Equal(n.Created) {
  595. return nil, false
  596. }
  597. case "Cap":
  598. if was.Cap() != n.Cap {
  599. pc().Cap = n.Cap
  600. }
  601. case "CapMap":
  602. if n.CapMap != nil {
  603. pc().CapMap = n.CapMap
  604. }
  605. case "Tags":
  606. if !views.SliceEqual(was.Tags(), views.SliceOf(n.Tags)) {
  607. return nil, false
  608. }
  609. case "PrimaryRoutes":
  610. if !views.SliceEqual(was.PrimaryRoutes(), views.SliceOf(n.PrimaryRoutes)) {
  611. return nil, false
  612. }
  613. case "Online":
  614. wasOnline := was.Online()
  615. if n.Online != nil && wasOnline != nil && *n.Online != *wasOnline {
  616. pc().Online = ptr.To(*n.Online)
  617. }
  618. case "LastSeen":
  619. wasSeen := was.LastSeen()
  620. if n.LastSeen != nil && wasSeen != nil && !wasSeen.Equal(*n.LastSeen) {
  621. pc().LastSeen = ptr.To(*n.LastSeen)
  622. }
  623. case "MachineAuthorized":
  624. if was.MachineAuthorized() != n.MachineAuthorized {
  625. return nil, false
  626. }
  627. case "Capabilities":
  628. if !views.SliceEqual(was.Capabilities(), views.SliceOf(n.Capabilities)) {
  629. pc().Capabilities = ptr.To(n.Capabilities)
  630. }
  631. case "UnsignedPeerAPIOnly":
  632. if was.UnsignedPeerAPIOnly() != n.UnsignedPeerAPIOnly {
  633. return nil, false
  634. }
  635. case "IsWireGuardOnly":
  636. if was.IsWireGuardOnly() != n.IsWireGuardOnly {
  637. return nil, false
  638. }
  639. case "Expired":
  640. if was.Expired() != n.Expired {
  641. return nil, false
  642. }
  643. case "SelfNodeV4MasqAddrForThisPeer":
  644. va, vb := was.SelfNodeV4MasqAddrForThisPeer(), n.SelfNodeV4MasqAddrForThisPeer
  645. if va == nil && vb == nil {
  646. continue
  647. }
  648. if va == nil || vb == nil || *va != *vb {
  649. return nil, false
  650. }
  651. case "SelfNodeV6MasqAddrForThisPeer":
  652. va, vb := was.SelfNodeV6MasqAddrForThisPeer(), n.SelfNodeV6MasqAddrForThisPeer
  653. if va == nil && vb == nil {
  654. continue
  655. }
  656. if va == nil || vb == nil || *va != *vb {
  657. return nil, false
  658. }
  659. case "ExitNodeDNSResolvers":
  660. va, vb := was.ExitNodeDNSResolvers(), views.SliceOfViews(n.ExitNodeDNSResolvers)
  661. if va.Len() != vb.Len() {
  662. return nil, false
  663. }
  664. for i := range va.LenIter() {
  665. if !va.At(i).Equal(vb.At(i)) {
  666. return nil, false
  667. }
  668. }
  669. }
  670. }
  671. if ret != nil {
  672. ret.NodeID = n.ID
  673. }
  674. return ret, true
  675. }
  676. // netmap returns a fully populated NetworkMap from the last state seen from
  677. // a call to updateStateFromResponse, filling in omitted
  678. // information from prior MapResponse values.
  679. func (ms *mapSession) netmap() *netmap.NetworkMap {
  680. peerViews := make([]tailcfg.NodeView, len(ms.sortedPeers))
  681. for i, vp := range ms.sortedPeers {
  682. peerViews[i] = *vp
  683. }
  684. nm := &netmap.NetworkMap{
  685. NodeKey: ms.publicNodeKey,
  686. PrivateKey: ms.privateNodeKey,
  687. MachineKey: ms.machinePubKey,
  688. Peers: peerViews,
  689. UserProfiles: make(map[tailcfg.UserID]tailcfg.UserProfile),
  690. Domain: ms.lastDomain,
  691. DomainAuditLogID: ms.lastDomainAuditLogID,
  692. DNS: *ms.lastDNSConfig,
  693. PacketFilter: ms.lastParsedPacketFilter,
  694. PacketFilterRules: ms.lastPacketFilterRules,
  695. SSHPolicy: ms.lastSSHPolicy,
  696. CollectServices: ms.collectServices,
  697. DERPMap: ms.lastDERPMap,
  698. ControlHealth: ms.lastHealth,
  699. TKAEnabled: ms.lastTKAInfo != nil && !ms.lastTKAInfo.Disabled,
  700. }
  701. if ms.lastTKAInfo != nil && ms.lastTKAInfo.Head != "" {
  702. if err := nm.TKAHead.UnmarshalText([]byte(ms.lastTKAInfo.Head)); err != nil {
  703. ms.logf("error unmarshalling TKAHead: %v", err)
  704. nm.TKAEnabled = false
  705. }
  706. }
  707. if node := ms.lastNode; node.Valid() {
  708. nm.SelfNode = node
  709. nm.Expiry = node.KeyExpiry()
  710. nm.Name = node.Name()
  711. }
  712. ms.addUserProfile(nm, nm.User())
  713. for _, peer := range peerViews {
  714. ms.addUserProfile(nm, peer.Sharer())
  715. ms.addUserProfile(nm, peer.User())
  716. }
  717. if DevKnob.ForceProxyDNS() {
  718. nm.DNS.Proxied = true
  719. }
  720. return nm
  721. }
  722. func nodesSorted(v []*tailcfg.Node) bool {
  723. for i, n := range v {
  724. if i > 0 && n.ID <= v[i-1].ID {
  725. return false
  726. }
  727. }
  728. return true
  729. }
  730. func sortNodes(v []*tailcfg.Node) {
  731. sort.Slice(v, func(i, j int) bool { return v[i].ID < v[j].ID })
  732. }
  733. func cloneNodes(v1 []*tailcfg.Node) []*tailcfg.Node {
  734. if v1 == nil {
  735. return nil
  736. }
  737. v2 := make([]*tailcfg.Node, len(v1))
  738. for i, n := range v1 {
  739. v2[i] = n.Clone()
  740. }
  741. return v2
  742. }
  743. var debugSelfIPv6Only = envknob.RegisterBool("TS_DEBUG_SELF_V6_ONLY")
  744. func filterSelfAddresses(in []netip.Prefix) (ret []netip.Prefix) {
  745. switch {
  746. default:
  747. return in
  748. case debugSelfIPv6Only():
  749. for _, a := range in {
  750. if a.Addr().Is6() {
  751. ret = append(ret, a)
  752. }
  753. }
  754. return ret
  755. }
  756. }