123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- /*
- * Copyright (c)2013-2020 ZeroTier, Inc.
- *
- * Use of this software is governed by the Business Source License included
- * in the LICENSE.TXT file in the project's root directory.
- *
- * Change Date: 2025-01-01
- *
- * On the date above, in accordance with the Business Source License, use
- * of this software will be governed by version 2.0 of the Apache License.
- */
- /****/
- package main
- import (
- "flag"
- "fmt"
- "io/ioutil"
- "os"
- "path"
- "runtime"
- "runtime/debug"
- "strings"
- "time"
- "zerotier/cmd/zerotier/cli"
- "zerotier/pkg/zerotier"
- )
- // authToken returns a function that reads the authorization token if needed.
- // If the authorization token can't be read, the function terminates the program with a fatal error.
- func authToken(basePath, tflag, tTflag string) func () string {
- savedAuthToken := new(string)
- return func() string {
- authToken := *savedAuthToken
- if len(authToken) > 0 {
- return authToken
- }
- if len(tflag) > 0 {
- at, err := ioutil.ReadFile(tflag)
- if err != nil || len(at) == 0 {
- fmt.Println("FATAL: unable to read local service API authorization token from " + tflag)
- os.Exit(1)
- return ""
- }
- authToken = string(at)
- } else if len(tTflag) > 0 {
- authToken = tTflag
- } else {
- var authTokenPaths []string
- authTokenPaths = append(authTokenPaths, path.Join(basePath, "authtoken.secret"))
- userHome, _ := os.UserHomeDir()
- if len(userHome) > 0 {
- if runtime.GOOS == "darwin" {
- authTokenPaths = append(authTokenPaths, path.Join(userHome, "Library", "Application Support", "ZeroTier", "authtoken.secret"))
- authTokenPaths = append(authTokenPaths, path.Join(userHome, "Library", "Application Support", "ZeroTier", "One", "authtoken.secret"))
- }
- authTokenPaths = append(authTokenPaths, path.Join(userHome, ".zerotierauth"))
- authTokenPaths = append(authTokenPaths, path.Join(userHome, ".zeroTierOneAuthToken"))
- }
- for _, p := range authTokenPaths {
- tmp, _ := ioutil.ReadFile(p)
- if len(tmp) > 0 {
- authToken = string(tmp)
- break
- }
- }
- if len(authToken) == 0 {
- fmt.Println("FATAL: unable to read local service API authorization token from any of:")
- for _, p := range authTokenPaths {
- fmt.Println(" " + p)
- }
- os.Exit(1)
- return ""
- }
- }
- authToken = strings.TrimSpace(authToken)
- if len(authToken) == 0 {
- fmt.Println("FATAL: unable to read API authorization token from command line or any filesystem location.")
- os.Exit(1)
- return ""
- }
- *savedAuthToken = authToken
- return authToken
- }
- }
- func main() {
- // Reduce Go's thread and memory footprint. This would slow things down if the Go code
- // were doing a lot, but it's not. It just manages the core and is not directly involved
- // in pushing a lot of packets around. If that ever changes this should be adjusted.
- runtime.GOMAXPROCS(1)
- debug.SetGCPercent(10)
- globalOpts := flag.NewFlagSet("global", flag.ContinueOnError)
- hflag := globalOpts.Bool("h", false, "") // support -h to be canonical with other Unix utilities
- jflag := globalOpts.Bool("j", false, "")
- pflag := globalOpts.String("p", "", "")
- tflag := globalOpts.String("t", "", "")
- tTflag := globalOpts.String("T", "", "")
- err := globalOpts.Parse(os.Args[1:])
- if err != nil {
- cli.Help()
- os.Exit(1)
- return
- }
- args := globalOpts.Args()
- if len(args) < 1 || *hflag {
- cli.Help()
- os.Exit(0)
- return
- }
- var cmdArgs []string
- if len(args) > 1 {
- cmdArgs = args[1:]
- }
- basePath := zerotier.PlatformDefaultHomePath
- if len(*pflag) > 0 {
- basePath = *pflag
- }
- exitCode := 0
- switch args[0] {
- default:
- cli.Help()
- exitCode = 1
- case "help":
- cli.Help()
- case "version":
- fmt.Printf("%d.%d.%d\n", zerotier.CoreVersionMajor, zerotier.CoreVersionMinor, zerotier.CoreVersionRevision)
- case "now":
- if len(args) > 2 {
- cli.Help()
- exitCode = 1
- } else if len(args) == 2 {
- d, err := time.ParseDuration(args[1])
- if err == nil {
- fmt.Printf("%d\n", zerotier.TimeMs() + d.Milliseconds())
- } else {
- fmt.Printf("FATAL: invalid duration \"%s\": %s\n", args[1], err.Error())
- exitCode = 1
- }
- } else {
- fmt.Printf("%d\n", zerotier.TimeMs())
- }
- case "service":
- exitCode = cli.Service(basePath, cmdArgs)
- case "status", "info":
- exitCode = cli.Status(basePath, authToken(basePath, *tflag, *tTflag), cmdArgs, *jflag)
- case "join":
- exitCode = cli.Join(basePath, authToken(basePath, *tflag, *tTflag), cmdArgs)
- case "leave":
- exitCode = cli.Leave(basePath, authToken(basePath, *tflag, *tTflag), cmdArgs)
- case "networks", "listnetworks":
- exitCode = cli.Network(basePath, authToken(basePath, *tflag, *tTflag), []string{"list"}, *jflag)
- case "network":
- exitCode = cli.Network(basePath, authToken(basePath, *tflag, *tTflag), cmdArgs, *jflag)
- case "peers", "listpeers":
- exitCode = cli.Peer(basePath, authToken(basePath, *tflag, *tTflag), []string{"list"}, *jflag)
- case "peer":
- exitCode = cli.Peer(basePath, authToken(basePath, *tflag, *tTflag), cmdArgs, *jflag)
- case "controller":
- exitCode = cli.Controller(basePath, authToken(basePath, *tflag, *tTflag), cmdArgs, *jflag)
- case "set":
- exitCode = cli.Set(basePath, authToken(basePath, *tflag, *tTflag), cmdArgs)
- case "identity":
- exitCode = cli.Identity(cmdArgs)
- case "locator":
- exitCode = cli.Locator(cmdArgs)
- case "certs", "listcerts", "lscerts": // same as "cert show" with no specific serial to show
- exitCode = cli.Cert(basePath, authToken(basePath, *tflag, *tTflag), []string{"show"}, *jflag)
- case "cert":
- exitCode = cli.Cert(basePath, authToken(basePath, *tflag, *tTflag), cmdArgs, *jflag)
- }
- os.Exit(exitCode)
- }
|