zerotier.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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 "C"
  15. import (
  16. "flag"
  17. "fmt"
  18. "io/ioutil"
  19. "os"
  20. "path"
  21. "runtime"
  22. "runtime/debug"
  23. "strings"
  24. "zerotier/cmd/zerotier/cli"
  25. "zerotier/pkg/zerotier"
  26. )
  27. func getAuthTokenPaths(basePath string) (p []string) {
  28. p = append(p, path.Join(basePath, "authtoken.secret"))
  29. userHome, _ := os.UserHomeDir()
  30. if len(userHome) > 0 {
  31. if runtime.GOOS == "darwin" {
  32. p = append(p, path.Join(userHome, "Library", "Application Support", "ZeroTier", "authtoken.secret"))
  33. p = append(p, path.Join(userHome, "Library", "Application Support", "ZeroTier", "One", "authtoken.secret"))
  34. }
  35. p = append(p, path.Join(userHome, ".zerotierauth"))
  36. p = append(p, path.Join(userHome, ".zeroTierOneAuthToken"))
  37. }
  38. return p
  39. }
  40. func authTokenRequired(authToken string) {
  41. if len(authToken) == 0 {
  42. fmt.Println("FATAL: unable to read API authorization token from command line or any filesystem location.")
  43. os.Exit(1)
  44. }
  45. }
  46. func main() {
  47. // Reduce Go's thread and memory footprint. This would slow things down if the Go code
  48. // were doing a lot, but it's not. It just manages the core and is not directly involved
  49. // in pushing a lot of packets around. If that ever changes this should be adjusted.
  50. runtime.GOMAXPROCS(1)
  51. debug.SetGCPercent(20)
  52. globalOpts := flag.NewFlagSet("global", flag.ContinueOnError)
  53. hflag := globalOpts.Bool("h", false, "") // support -h to be canonical with other Unix utilities
  54. jflag := globalOpts.Bool("j", false, "")
  55. pflag := globalOpts.String("p", "", "")
  56. tflag := globalOpts.String("t", "", "")
  57. tTflag := globalOpts.String("T", "", "")
  58. err := globalOpts.Parse(os.Args[1:])
  59. if err != nil {
  60. cli.Help()
  61. os.Exit(1)
  62. return
  63. }
  64. args := globalOpts.Args()
  65. if len(args) < 1 || *hflag {
  66. cli.Help()
  67. os.Exit(0)
  68. return
  69. }
  70. var cmdArgs []string
  71. if len(args) > 1 {
  72. cmdArgs = args[1:]
  73. }
  74. basePath := zerotier.PlatformDefaultHomePath
  75. if len(*pflag) > 0 {
  76. basePath = *pflag
  77. }
  78. authTokenPaths := getAuthTokenPaths(basePath)
  79. var authToken string
  80. if len(*tflag) > 0 {
  81. at, err := ioutil.ReadFile(*tflag)
  82. if err != nil || len(at) == 0 {
  83. fmt.Println("FATAL: unable to read local service API authorization token from " + *tflag)
  84. os.Exit(1)
  85. }
  86. authToken = string(at)
  87. } else if len(*tTflag) > 0 {
  88. authToken = *tTflag
  89. } else {
  90. for _, p := range authTokenPaths {
  91. tmp, _ := ioutil.ReadFile(p)
  92. if len(tmp) > 0 {
  93. authToken = string(tmp)
  94. break
  95. }
  96. }
  97. if len(authToken) == 0 {
  98. fmt.Println("FATAL: unable to read local service API authorization token from any of:")
  99. for _, p := range authTokenPaths {
  100. fmt.Println(" " + p)
  101. }
  102. os.Exit(1)
  103. }
  104. }
  105. authToken = strings.TrimSpace(authToken)
  106. switch args[0] {
  107. case "help":
  108. cli.Help()
  109. os.Exit(0)
  110. case "version":
  111. fmt.Printf("%d.%d.%d\n", zerotier.CoreVersionMajor, zerotier.CoreVersionMinor, zerotier.CoreVersionRevision)
  112. os.Exit(0)
  113. case "service":
  114. cli.Service(basePath, authToken, cmdArgs)
  115. case "status", "info":
  116. authTokenRequired(authToken)
  117. cli.Status(basePath, authToken, cmdArgs, *jflag)
  118. case "join":
  119. authTokenRequired(authToken)
  120. cli.Join(basePath, authToken, cmdArgs)
  121. case "leave":
  122. authTokenRequired(authToken)
  123. cli.Leave(basePath, authToken, cmdArgs)
  124. case "networks", "listnetworks":
  125. authTokenRequired(authToken)
  126. cli.Networks(basePath, authToken, cmdArgs, *jflag)
  127. case "network":
  128. authTokenRequired(authToken)
  129. cli.Network(basePath, authToken, cmdArgs, *jflag)
  130. case "peers", "listpeers", "lspeers":
  131. authTokenRequired(authToken)
  132. cli.Peers(basePath, authToken, cmdArgs, *jflag, false)
  133. case "peer":
  134. authTokenRequired(authToken)
  135. case "roots":
  136. authTokenRequired(authToken)
  137. cli.Peers(basePath, authToken, cmdArgs, *jflag, true)
  138. case "root":
  139. authTokenRequired(authToken)
  140. cli.Root(basePath, authToken, cmdArgs, *jflag)
  141. case "set":
  142. authTokenRequired(authToken)
  143. cli.Set(basePath, authToken, cmdArgs)
  144. case "controller":
  145. authTokenRequired(authToken)
  146. cli.Controller(basePath, authToken, cmdArgs, *jflag)
  147. case "identity":
  148. cli.Identity(cmdArgs)
  149. }
  150. // Commands in the 'cli' sub-package do not return, so if we make
  151. // it here the command was not recognized.
  152. cli.Help()
  153. os.Exit(1)
  154. }