map.go 22 KB

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