tsd.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  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. // SocketPath is the path to the tailscaled Unix socket.
  66. // It is used to prevent serve from proxying to our own socket.
  67. SocketPath string
  68. // onlyNetstack is whether the Tun value is a fake TUN device
  69. // and we're using netstack for everything.
  70. onlyNetstack bool
  71. controlKnobs controlknobs.Knobs
  72. proxyMap proxymap.Mapper
  73. userMetricsRegistry usermetric.Registry
  74. }
  75. // NewSystem constructs a new otherwise-empty [System] with a
  76. // freshly-constructed event bus populated.
  77. func NewSystem() *System { return NewSystemWithBus(eventbus.New()) }
  78. // NewSystemWithBus constructs a new otherwise-empty [System] with an
  79. // eventbus provided by the caller. The provided bus must not be nil.
  80. // This is mainly intended for testing; for production use call [NewBus].
  81. func NewSystemWithBus(bus *eventbus.Bus) *System {
  82. if bus == nil {
  83. panic("nil eventbus")
  84. }
  85. sys := new(System)
  86. sys.Set(bus)
  87. tracker := health.NewTracker(bus)
  88. sys.Set(tracker)
  89. return sys
  90. }
  91. // LocalBackend is a fake name for *ipnlocal.LocalBackend to avoid an import cycle.
  92. type LocalBackend = any
  93. // NetstackImpl is the interface that *netstack.Impl implements.
  94. // It's an interface for circular dependency reasons: netstack.Impl
  95. // references LocalBackend, and LocalBackend has a tsd.System.
  96. type NetstackImpl interface {
  97. Start(LocalBackend) error
  98. UpdateNetstackIPs(*netmap.NetworkMap)
  99. }
  100. // Set is a convenience method to set a subsystem value.
  101. // It panics if the type is unknown or has that type
  102. // has already been set.
  103. func (s *System) Set(v any) {
  104. switch v := v.(type) {
  105. case *eventbus.Bus:
  106. s.Bus.Set(v)
  107. case *netmon.Monitor:
  108. s.NetMon.Set(v)
  109. case *dns.Manager:
  110. s.DNSManager.Set(v)
  111. case *tsdial.Dialer:
  112. s.Dialer.Set(v)
  113. case wgengine.Engine:
  114. s.Engine.Set(v)
  115. case router.Router:
  116. s.Router.Set(v)
  117. case *tstun.Wrapper:
  118. type ft interface {
  119. IsFakeTun() bool
  120. }
  121. if _, ok := v.Unwrap().(ft); ok {
  122. s.onlyNetstack = true
  123. }
  124. s.Tun.Set(v)
  125. case *magicsock.Conn:
  126. s.MagicSock.Set(v)
  127. case ipn.StateStore:
  128. s.StateStore.Set(v)
  129. case NetstackImpl:
  130. s.Netstack.Set(v)
  131. case drive.FileSystemForLocal:
  132. s.DriveForLocal.Set(v)
  133. case drive.FileSystemForRemote:
  134. s.DriveForRemote.Set(v)
  135. case policyclient.Client:
  136. s.PolicyClient.Set(v)
  137. case *health.Tracker:
  138. s.HealthTracker.Set(v)
  139. default:
  140. panic(fmt.Sprintf("unknown type %T", v))
  141. }
  142. }
  143. // IsNetstackRouter reports whether Tailscale is either fully netstack based
  144. // (without TUN) or is at least using netstack for routing.
  145. func (s *System) IsNetstackRouter() bool {
  146. if v, ok := s.NetstackRouter.GetOK(); ok && v {
  147. return true
  148. }
  149. return s.IsNetstack()
  150. }
  151. // IsNetstack reports whether Tailscale is running as a netstack-based TUN-free engine.
  152. func (s *System) IsNetstack() bool {
  153. return s.onlyNetstack
  154. }
  155. // ControlKnobs returns the control knobs for this node.
  156. func (s *System) ControlKnobs() *controlknobs.Knobs {
  157. return &s.controlKnobs
  158. }
  159. // ProxyMapper returns the ephemeral ip:port mapper.
  160. func (s *System) ProxyMapper() *proxymap.Mapper {
  161. return &s.proxyMap
  162. }
  163. // UserMetricsRegistry returns the system usermetrics.
  164. func (s *System) UserMetricsRegistry() *usermetric.Registry {
  165. return &s.userMetricsRegistry
  166. }
  167. // PolicyClientOrDefault returns the policy client if set or a no-op default
  168. // otherwise. It always returns a non-nil value.
  169. func (s *System) PolicyClientOrDefault() policyclient.Client {
  170. if client, ok := s.PolicyClient.GetOK(); ok {
  171. return client
  172. }
  173. return policyclient.Get()
  174. }
  175. // SubSystem represents some subsystem of the Tailscale node daemon.
  176. //
  177. // A subsystem can be set to a value, and then later retrieved. A subsystem
  178. // value tracks whether it's been set and, once set, doesn't allow the value to
  179. // change.
  180. type SubSystem[T any] struct {
  181. set bool
  182. v T
  183. }
  184. // Set sets p to v.
  185. //
  186. // It panics if p is already set to a different value.
  187. //
  188. // Set must not be called concurrently with other Sets or Gets.
  189. func (p *SubSystem[T]) Set(v T) {
  190. if p.set {
  191. var oldVal any = p.v
  192. var newVal any = v
  193. if oldVal == newVal {
  194. // Allow setting to the same value.
  195. // Note we had to box them through "any" to force them to be comparable.
  196. // We can't set the type constraint T to be "comparable" because the interfaces
  197. // aren't comparable. (See https://github.com/golang/go/issues/52531 and
  198. // https://github.com/golang/go/issues/52614 for some background)
  199. return
  200. }
  201. var z *T
  202. panic(fmt.Sprintf("%v is already set", reflect.TypeOf(z).Elem().String()))
  203. }
  204. p.v = v
  205. p.set = true
  206. }
  207. // Get returns the value of p, panicking if it hasn't been set.
  208. func (p *SubSystem[T]) Get() T {
  209. if !p.set {
  210. var z *T
  211. panic(fmt.Sprintf("%v is not set", reflect.TypeOf(z).Elem().String()))
  212. }
  213. return p.v
  214. }
  215. // GetOK returns the value of p (if any) and whether it's been set.
  216. func (p *SubSystem[T]) GetOK() (_ T, ok bool) {
  217. return p.v, p.set
  218. }