tsd.go 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. // Package tsd (short for "Tailscale Daemon") contains a System type that
  4. // containing all the subsystems a Tailscale node (tailscaled or platform
  5. // equivalent) uses.
  6. //
  7. // The goal of this package (as of 2023-05-03) is to eventually unify
  8. // initialization across tailscaled, tailscaled as a Windows services, the mac
  9. // GUI, tsnet, wasm, tests, and other places that wire up all the subsystems.
  10. // And doing so without weird optional interface accessors on some subsystems
  11. // that return other subsystems. It's all a work in progress.
  12. //
  13. // This package depends on nearly all parts of Tailscale, so it should not be
  14. // imported by (or thus passed to) any package that does not want to depend on
  15. // the world. In practice this means that only things like cmd/tailscaled,
  16. // ipn/ipnlocal, and ipn/ipnserver should import this package.
  17. package tsd
  18. import (
  19. "fmt"
  20. "reflect"
  21. "tailscale.com/control/controlknobs"
  22. "tailscale.com/drive"
  23. "tailscale.com/health"
  24. "tailscale.com/ipn"
  25. "tailscale.com/ipn/conffile"
  26. "tailscale.com/net/dns"
  27. "tailscale.com/net/netmon"
  28. "tailscale.com/net/tsdial"
  29. "tailscale.com/net/tstun"
  30. "tailscale.com/proxymap"
  31. "tailscale.com/types/netmap"
  32. "tailscale.com/util/eventbus"
  33. "tailscale.com/util/syspolicy/policyclient"
  34. "tailscale.com/util/usermetric"
  35. "tailscale.com/wgengine"
  36. "tailscale.com/wgengine/magicsock"
  37. "tailscale.com/wgengine/router"
  38. )
  39. // System contains all the subsystems of a Tailscale node (tailscaled, etc.)
  40. //
  41. // A valid System value must always have a non-nil Bus populated. Callers must
  42. // ensure this before using the value further. Call [NewSystem] to obtain a
  43. // value ready to use.
  44. type System struct {
  45. Bus SubSystem[*eventbus.Bus]
  46. Dialer SubSystem[*tsdial.Dialer]
  47. DNSManager SubSystem[*dns.Manager] // can get its *resolver.Resolver from DNSManager.Resolver
  48. Engine SubSystem[wgengine.Engine]
  49. NetMon SubSystem[*netmon.Monitor]
  50. MagicSock SubSystem[*magicsock.Conn]
  51. NetstackRouter SubSystem[bool] // using Netstack at all (either entirely or at least for subnets)
  52. Router SubSystem[router.Router]
  53. Tun SubSystem[*tstun.Wrapper]
  54. StateStore SubSystem[ipn.StateStore]
  55. Netstack SubSystem[NetstackImpl] // actually a *netstack.Impl
  56. DriveForLocal SubSystem[drive.FileSystemForLocal]
  57. DriveForRemote SubSystem[drive.FileSystemForRemote]
  58. PolicyClient SubSystem[policyclient.Client]
  59. HealthTracker SubSystem[*health.Tracker]
  60. // InitialConfig is initial server config, if any.
  61. // It is nil if the node is not in declarative mode.
  62. // This value is never updated after startup.
  63. // LocalBackend tracks the current config after any reloads.
  64. InitialConfig *conffile.Config
  65. // onlyNetstack is whether the Tun value is a fake TUN device
  66. // and we're using netstack for everything.
  67. onlyNetstack bool
  68. controlKnobs controlknobs.Knobs
  69. proxyMap proxymap.Mapper
  70. userMetricsRegistry usermetric.Registry
  71. }
  72. // NewSystem constructs a new otherwise-empty [System] with a
  73. // freshly-constructed event bus populated.
  74. func NewSystem() *System { return NewSystemWithBus(eventbus.New()) }
  75. // NewSystemWithBus constructs a new otherwise-empty [System] with an
  76. // eventbus provided by the caller. The provided bus must not be nil.
  77. // This is mainly intended for testing; for production use call [NewBus].
  78. func NewSystemWithBus(bus *eventbus.Bus) *System {
  79. if bus == nil {
  80. panic("nil eventbus")
  81. }
  82. sys := new(System)
  83. sys.Set(bus)
  84. tracker := health.NewTracker(bus)
  85. sys.Set(tracker)
  86. return sys
  87. }
  88. // LocalBackend is a fake name for *ipnlocal.LocalBackend to avoid an import cycle.
  89. type LocalBackend = any
  90. // NetstackImpl is the interface that *netstack.Impl implements.
  91. // It's an interface for circular dependency reasons: netstack.Impl
  92. // references LocalBackend, and LocalBackend has a tsd.System.
  93. type NetstackImpl interface {
  94. Start(LocalBackend) error
  95. UpdateNetstackIPs(*netmap.NetworkMap)
  96. }
  97. // Set is a convenience method to set a subsystem value.
  98. // It panics if the type is unknown or has that type
  99. // has already been set.
  100. func (s *System) Set(v any) {
  101. switch v := v.(type) {
  102. case *eventbus.Bus:
  103. s.Bus.Set(v)
  104. case *netmon.Monitor:
  105. s.NetMon.Set(v)
  106. case *dns.Manager:
  107. s.DNSManager.Set(v)
  108. case *tsdial.Dialer:
  109. s.Dialer.Set(v)
  110. case wgengine.Engine:
  111. s.Engine.Set(v)
  112. case router.Router:
  113. s.Router.Set(v)
  114. case *tstun.Wrapper:
  115. type ft interface {
  116. IsFakeTun() bool
  117. }
  118. if _, ok := v.Unwrap().(ft); ok {
  119. s.onlyNetstack = true
  120. }
  121. s.Tun.Set(v)
  122. case *magicsock.Conn:
  123. s.MagicSock.Set(v)
  124. case ipn.StateStore:
  125. s.StateStore.Set(v)
  126. case NetstackImpl:
  127. s.Netstack.Set(v)
  128. case drive.FileSystemForLocal:
  129. s.DriveForLocal.Set(v)
  130. case drive.FileSystemForRemote:
  131. s.DriveForRemote.Set(v)
  132. case policyclient.Client:
  133. s.PolicyClient.Set(v)
  134. case *health.Tracker:
  135. s.HealthTracker.Set(v)
  136. default:
  137. panic(fmt.Sprintf("unknown type %T", v))
  138. }
  139. }
  140. // IsNetstackRouter reports whether Tailscale is either fully netstack based
  141. // (without TUN) or is at least using netstack for routing.
  142. func (s *System) IsNetstackRouter() bool {
  143. if v, ok := s.NetstackRouter.GetOK(); ok && v {
  144. return true
  145. }
  146. return s.IsNetstack()
  147. }
  148. // IsNetstack reports whether Tailscale is running as a netstack-based TUN-free engine.
  149. func (s *System) IsNetstack() bool {
  150. return s.onlyNetstack
  151. }
  152. // ControlKnobs returns the control knobs for this node.
  153. func (s *System) ControlKnobs() *controlknobs.Knobs {
  154. return &s.controlKnobs
  155. }
  156. // ProxyMapper returns the ephemeral ip:port mapper.
  157. func (s *System) ProxyMapper() *proxymap.Mapper {
  158. return &s.proxyMap
  159. }
  160. // UserMetricsRegistry returns the system usermetrics.
  161. func (s *System) UserMetricsRegistry() *usermetric.Registry {
  162. return &s.userMetricsRegistry
  163. }
  164. // PolicyClientOrDefault returns the policy client if set or a no-op default
  165. // otherwise. It always returns a non-nil value.
  166. func (s *System) PolicyClientOrDefault() policyclient.Client {
  167. if client, ok := s.PolicyClient.GetOK(); ok {
  168. return client
  169. }
  170. return policyclient.Get()
  171. }
  172. // SubSystem represents some subsystem of the Tailscale node daemon.
  173. //
  174. // A subsystem can be set to a value, and then later retrieved. A subsystem
  175. // value tracks whether it's been set and, once set, doesn't allow the value to
  176. // change.
  177. type SubSystem[T any] struct {
  178. set bool
  179. v T
  180. }
  181. // Set sets p to v.
  182. //
  183. // It panics if p is already set to a different value.
  184. //
  185. // Set must not be called concurrently with other Sets or Gets.
  186. func (p *SubSystem[T]) Set(v T) {
  187. if p.set {
  188. var oldVal any = p.v
  189. var newVal any = v
  190. if oldVal == newVal {
  191. // Allow setting to the same value.
  192. // Note we had to box them through "any" to force them to be comparable.
  193. // We can't set the type constraint T to be "comparable" because the interfaces
  194. // aren't comparable. (See https://github.com/golang/go/issues/52531 and
  195. // https://github.com/golang/go/issues/52614 for some background)
  196. return
  197. }
  198. var z *T
  199. panic(fmt.Sprintf("%v is already set", reflect.TypeOf(z).Elem().String()))
  200. }
  201. p.v = v
  202. p.set = true
  203. }
  204. // Get returns the value of p, panicking if it hasn't been set.
  205. func (p *SubSystem[T]) Get() T {
  206. if !p.set {
  207. var z *T
  208. panic(fmt.Sprintf("%v is not set", reflect.TypeOf(z).Elem().String()))
  209. }
  210. return p.v
  211. }
  212. // GetOK returns the value of p (if any) and whether it's been set.
  213. func (p *SubSystem[T]) GetOK() (_ T, ok bool) {
  214. return p.v, p.set
  215. }