zerotier.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. * Copyright (c)2013-2020 ZeroTier, Inc.
  3. *
  4. * Use of this software is governed by the Business Source License included
  5. * in the LICENSE.TXT file in the project's root directory.
  6. *
  7. * Change Date: 2024-01-01
  8. *
  9. * On the date above, in accordance with the Business Source License, use
  10. * of this software will be governed by version 2.0 of the Apache License.
  11. */
  12. /****/
  13. package main
  14. import (
  15. "flag"
  16. "fmt"
  17. "io/ioutil"
  18. "os"
  19. "path"
  20. "runtime"
  21. "runtime/debug"
  22. "strings"
  23. "zerotier/cmd/zerotier/cli"
  24. "zerotier/pkg/zerotier"
  25. )
  26. func readAuthToken(basePath string) string {
  27. data, _ := ioutil.ReadFile(path.Join(basePath, "authtoken.secret"))
  28. if len(data) > 0 {
  29. return string(data)
  30. }
  31. userHome, _ := os.UserHomeDir()
  32. if len(userHome) > 0 {
  33. if runtime.GOOS == "darwin" {
  34. data, _ = ioutil.ReadFile(userHome + "/Library/Application Support/ZeroTier/authtoken.secret")
  35. if len(data) > 0 {
  36. return string(data)
  37. }
  38. data, _ = ioutil.ReadFile(userHome + "/Library/Application Support/ZeroTier/One/authtoken.secret")
  39. if len(data) > 0 {
  40. return string(data)
  41. }
  42. }
  43. data, _ = ioutil.ReadFile(path.Join(userHome, ".zerotierauth"))
  44. if len(data) > 0 {
  45. return string(data)
  46. }
  47. data, _ = ioutil.ReadFile(path.Join(userHome, ".zeroTierOneAuthToken"))
  48. if len(data) > 0 {
  49. return string(data)
  50. }
  51. }
  52. return ""
  53. }
  54. func authTokenRequired(authToken string) {
  55. if len(authToken) == 0 {
  56. fmt.Println("FATAL: unable to read API authorization token from service path or user home ('sudo' may be needed)")
  57. os.Exit(1)
  58. }
  59. }
  60. func main() {
  61. // Reduce Go's threads to 1-2 depending on whether this is single core or
  62. // multi-core. Note that I/O threads are in C++ and are separate and Go
  63. // code only does service control and CLI stuff, so this reduces memory
  64. // use and competition with I/O but shouldn't impact throughput. We also
  65. // crank up the GC to reduce memory usage a little bit.
  66. if runtime.NumCPU() >= 2 {
  67. runtime.GOMAXPROCS(2)
  68. } else {
  69. runtime.GOMAXPROCS(1)
  70. }
  71. debug.SetGCPercent(25)
  72. globalOpts := flag.NewFlagSet("global", flag.ContinueOnError)
  73. hflag := globalOpts.Bool("h", false, "") // support -h to be canonical with other Unix utilities
  74. jflag := globalOpts.Bool("j", false, "")
  75. pflag := globalOpts.String("p", "", "")
  76. tflag := globalOpts.String("t", "", "")
  77. err := globalOpts.Parse(os.Args[1:])
  78. if err != nil {
  79. cli.Help()
  80. os.Exit(1)
  81. return
  82. }
  83. args := globalOpts.Args()
  84. if len(args) < 1 || *hflag {
  85. cli.Help()
  86. os.Exit(0)
  87. return
  88. }
  89. var cmdArgs []string
  90. if len(args) > 1 {
  91. cmdArgs = args[1:]
  92. }
  93. if *hflag {
  94. cli.Help()
  95. os.Exit(0)
  96. }
  97. basePath := zerotier.PlatformDefaultHomePath
  98. if len(*pflag) > 0 {
  99. basePath = *pflag
  100. }
  101. var authToken string
  102. if len(*tflag) > 0 {
  103. authToken = *tflag
  104. } else {
  105. authToken = readAuthToken(basePath)
  106. }
  107. authToken = strings.TrimSpace(authToken)
  108. switch args[0] {
  109. case "help":
  110. cli.Help()
  111. os.Exit(0)
  112. case "version":
  113. fmt.Printf("%d.%d.%d\n", zerotier.CoreVersionMajor, zerotier.CoreVersionMinor, zerotier.CoreVersionRevision)
  114. os.Exit(0)
  115. case "selftest":
  116. cli.SelfTest()
  117. os.Exit(0)
  118. case "service":
  119. cli.Service(basePath, authToken, cmdArgs)
  120. case "status":
  121. authTokenRequired(authToken)
  122. cli.Status(basePath, authToken, cmdArgs, *jflag)
  123. case "peers", "listpeers":
  124. authTokenRequired(authToken)
  125. cli.Peers(basePath, authToken, cmdArgs, *jflag)
  126. case "roots", "listroots", "listmoons":
  127. authTokenRequired(authToken)
  128. cli.Roots(basePath, authToken, cmdArgs, *jflag)
  129. case "addroot":
  130. authTokenRequired(authToken)
  131. cli.AddRoot(basePath, authToken, cmdArgs)
  132. case "removeroot":
  133. authTokenRequired(authToken)
  134. cli.RemoveRoot(basePath, authToken, cmdArgs)
  135. case "identity":
  136. cli.Identity(cmdArgs)
  137. case "networks", "listnetworks":
  138. authTokenRequired(authToken)
  139. cli.Networks(basePath, authToken, cmdArgs, *jflag)
  140. case "network":
  141. authTokenRequired(authToken)
  142. cli.Network(basePath, authToken, cmdArgs, *jflag)
  143. case "join":
  144. authTokenRequired(authToken)
  145. cli.Join(basePath, authToken, cmdArgs)
  146. case "leave":
  147. authTokenRequired(authToken)
  148. cli.Leave(basePath, authToken, cmdArgs)
  149. case "set":
  150. authTokenRequired(authToken)
  151. cli.Set(basePath, authToken, cmdArgs)
  152. }
  153. cli.Help()
  154. os.Exit(1)
  155. }