| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383 | //go:generate goversioninfo -icon=windowsdata/resource/netmaker.ico -manifest=netclient.exe.manifest.xml -64=true -o=netclient.sysopackage mainimport (	"errors"	"log"	"os"	"os/exec"	"os/signal"	"runtime/debug"	"strconv"	"syscall"	"github.com/gravitl/netmaker/netclient/command"	"github.com/gravitl/netmaker/netclient/config"	"github.com/gravitl/netmaker/netclient/local"	"github.com/gravitl/netmaker/netclient/ncutils"	"github.com/gravitl/netmaker/netclient/ncwindows"	"github.com/urfave/cli/v2")func main() {	app := cli.NewApp()	app.Name = "Netclient CLI"	app.Usage = "Netmaker's netclient agent and CLI. Used to perform interactions with Netmaker server and set local WireGuard config."	app.Version = "v0.8.3"	cliFlags := []cli.Flag{		&cli.StringFlag{			Name:    "network",			Aliases: []string{"n"},			EnvVars: []string{"NETCLIENT_NETWORK"},			Value:   "all",			Usage:   "Network to perform specified action against.",		},		&cli.StringFlag{			Name:    "password",			Aliases: []string{"p"},			EnvVars: []string{"NETCLIENT_PASSWORD"},			Value:   "",			Usage:   "Password for authenticating with netmaker.",		},		&cli.StringFlag{			Name:    "endpoint",			Aliases: []string{"e"},			EnvVars: []string{"NETCLIENT_ENDPOINT"},			Value:   "",			Usage:   "Reachable (usually public) address for WireGuard (not the private WG address).",		},		&cli.StringFlag{			Name:    "macaddress",			Aliases: []string{"m"},			EnvVars: []string{"NETCLIENT_MACADDRESS"},			Value:   "",			Usage:   "Mac Address for this machine. Used as a unique identifier within Netmaker network.",		},		&cli.StringFlag{			Name:    "publickey",			Aliases: []string{"pubkey"},			EnvVars: []string{"NETCLIENT_PUBLICKEY"},			Value:   "",			Usage:   "Public Key for WireGuard Interface.",		},		&cli.StringFlag{			Name:    "privatekey",			Aliases: []string{"privkey"},			EnvVars: []string{"NETCLIENT_PRIVATEKEY"},			Value:   "",			Usage:   "Private Key for WireGuard Interface.",		},		&cli.StringFlag{			Name:    "port",			EnvVars: []string{"NETCLIENT_PORT"},			Value:   "",			Usage:   "Port for WireGuard Interface.",		},		&cli.IntFlag{			Name:    "keepalive",			EnvVars: []string{"NETCLIENT_KEEPALIVE"},			Value:   0,			Usage:   "Default PersistentKeepAlive for Peers in WireGuard Interface.",		},		&cli.StringFlag{			Name:    "operatingsystem",			Aliases: []string{"os"},			EnvVars: []string{"NETCLIENT_OS"},			Value:   "",			Usage:   "Identifiable name for machine within Netmaker network.",		},		&cli.StringFlag{			Name:    "name",			EnvVars: []string{"NETCLIENT_NAME"},			Value:   "",			Usage:   "Identifiable name for machine within Netmaker network.",		},		&cli.StringFlag{			Name:    "localaddress",			EnvVars: []string{"NETCLIENT_LOCALADDRESS"},			Value:   "",			Usage:   "Local address for machine. Can be used in place of Endpoint for machines on the same LAN.",		},		&cli.StringFlag{			Name:    "address",			Aliases: []string{"a"},			EnvVars: []string{"NETCLIENT_ADDRESS"},			Value:   "",			Usage:   "WireGuard address for machine within Netmaker network.",		},		&cli.StringFlag{			Name:    "addressIPv6",			Aliases: []string{"a6"},			EnvVars: []string{"NETCLIENT_ADDRESSIPV6"},			Value:   "",			Usage:   "WireGuard address for machine within Netmaker network.",		},		&cli.StringFlag{			Name:    "interface",			Aliases: []string{"i"},			EnvVars: []string{"NETCLIENT_INTERFACE"},			Value:   "",			Usage:   "WireGuard local network interface name.",		},		&cli.StringFlag{			Name:    "apiserver",			EnvVars: []string{"NETCLIENT_API_SERVER"},			Value:   "",			Usage:   "Address + GRPC Port (e.g. 1.2.3.4:50051) of Netmaker server.",		},		&cli.StringFlag{			Name:    "grpcserver",			EnvVars: []string{"NETCLIENT_GRPC_SERVER"},			Value:   "",			Usage:   "Address + API Port (e.g. 1.2.3.4:8081) of Netmaker server.",		},		&cli.StringFlag{			Name:    "key",			Aliases: []string{"k"},			EnvVars: []string{"NETCLIENT_ACCESSKEY"},			Value:   "",			Usage:   "Access Key for signing up machine with Netmaker server during initial 'add'.",		},		&cli.StringFlag{			Name:    "token",			Aliases: []string{"t"},			EnvVars: []string{"NETCLIENT_ACCESSTOKEN"},			Value:   "",			Usage:   "Access Token for signing up machine with Netmaker server during initial 'add'.",		},		&cli.StringFlag{			Name:    "localrange",			EnvVars: []string{"NETCLIENT_LOCALRANGE"},			Value:   "",			Usage:   "Local Range if network is local, for instance 192.168.1.0/24.",		},		&cli.StringFlag{			Name:    "dnson",			EnvVars: []string{"NETCLIENT_DNS"},			Value:   "yes",			Usage:   "Sets private dns if 'yes'. Ignores if 'no'. Will retrieve from network if unset.",		},		&cli.StringFlag{			Name:    "islocal",			EnvVars: []string{"NETCLIENT_IS_LOCAL"},			Value:   "",			Usage:   "Sets endpoint to local address if 'yes'. Ignores if 'no'. Will retrieve from network if unset.",		},		&cli.StringFlag{			Name:    "isdualstack",			EnvVars: []string{"NETCLIENT_IS_DUALSTACK"},			Value:   "",			Usage:   "Sets ipv6 address if 'yes'. Ignores if 'no'. Will retrieve from network if unset.",		},		&cli.StringFlag{			Name:    "udpholepunch",			EnvVars: []string{"NETCLIENT_UDP_HOLEPUNCH"},			Value:   "",			Usage:   "Turns on udp holepunching if 'yes'. Ignores if 'no'. Will retrieve from network if unset.",		},		&cli.StringFlag{			Name:    "ipforwarding",			EnvVars: []string{"NETCLIENT_IPFORWARDING"},			Value:   "on",			Usage:   "Sets ip forwarding on if 'on'. Ignores if 'off'. On by default.",		},		&cli.StringFlag{			Name:    "postup",			EnvVars: []string{"NETCLIENT_POSTUP"},			Value:   "",			Usage:   "Sets PostUp command for WireGuard.",		},		&cli.StringFlag{			Name:    "postdown",			EnvVars: []string{"NETCLIENT_POSTDOWN"},			Value:   "",			Usage:   "Sets PostDown command for WireGuard.",		},		&cli.StringFlag{			Name:    "daemon",			EnvVars: []string{"NETCLIENT_DAEMON"},			Value:   "on",			Usage:   "Installs daemon if 'on'. Ignores if 'off'. On by default.",		},		&cli.StringFlag{			Name:    "roaming",			EnvVars: []string{"NETCLIENT_ROAMING"},			Value:   "on",			Usage:   "Checks for IP changes if 'on'. Ignores if 'off'. On by default.",		},	}	app.Commands = []*cli.Command{		{			Name:  "join",			Usage: "Join a Netmaker network.",			Flags: cliFlags,			Action: func(c *cli.Context) error {				cfg, pvtKey, err := config.GetCLIConfig(c)				if err != nil {					return err				}				if cfg.Network == "all" {					err = errors.New("No network provided.")					return err				}				if cfg.Server.GRPCAddress == "" {					err = errors.New("No server address provided.")					return err				}				err = command.Join(cfg, pvtKey)				return err			},		},		{			Name:  "leave",			Usage: "Leave a Netmaker network.",			Flags: cliFlags,			// the action, or code that will be executed when			// we execute our `ns` command			Action: func(c *cli.Context) error {				cfg, _, err := config.GetCLIConfig(c)				if err != nil {					return err				}				err = command.Leave(cfg)				return err			},		},		{			Name:  "checkin",			Usage: "Checks for local changes and then checks into the specified Netmaker network to ask about remote changes.",			Flags: cliFlags,			// the action, or code that will be executed when			// we execute our `ns` command			Action: func(c *cli.Context) error {				cfg, _, err := config.GetCLIConfig(c)				if err != nil {					return err				}				err = command.CheckIn(cfg)				return err			},		},		{			Name:  "push",			Usage: "Push configuration changes to server.",			Flags: cliFlags,			// the action, or code that will be executed when			// we execute our `ns` command			Action: func(c *cli.Context) error {				cfg, _, err := config.GetCLIConfig(c)				if err != nil {					return err				}				err = command.Push(cfg)				return err			},		},		{			Name:  "pull",			Usage: "Pull latest configuration and peers from server.",			Flags: cliFlags,			// the action, or code that will be executed when			// we execute our `ns` command			Action: func(c *cli.Context) error {				cfg, _, err := config.GetCLIConfig(c)				if err != nil {					return err				}				err = command.Pull(cfg)				return err			},		},		{			Name:  "list",			Usage: "Get list of networks.",			Flags: cliFlags,			// the action, or code that will be executed when			// we execute our `ns` command			Action: func(c *cli.Context) error {				cfg, _, err := config.GetCLIConfig(c)				if err != nil {					return err				}				err = command.List(cfg)				return err			},		},		{			Name:  "uninstall",			Usage: "Uninstall the netclient system service.",			Flags: cliFlags,			// the action, or code that will be executed when			// we execute our `ns` command			Action: func(c *cli.Context) error {				err := command.Uninstall()				return err			},		},	}	setGarbageCollection()	if ncutils.IsWindows() {		ncwindows.InitWindows()	} else {		// start our application		out, err := ncutils.RunCmd("id -u", true)		if err != nil {			log.Fatal(out, err)		}		id, err := strconv.Atoi(string(out[:len(out)-1]))		if err != nil {			log.Fatal(err)		}		if id != 0 {			log.Fatal("This program must be run with elevated privileges (sudo). This program installs a SystemD service and configures WireGuard and networking rules. Please re-run with sudo/root.")		}		_, err = exec.LookPath("wg")		uspace := ncutils.GetWireGuard()		if err != nil {			if uspace == "wg" {				log.Println(err)				log.Fatal("WireGuard not installed. Please install WireGuard (wireguard-tools) and try again.")			}			ncutils.PrintLog("Running with userspace wireguard: "+uspace, 0)		} else if uspace != "wg" {			log.Println("running userspace WireGuard with " + uspace)		}	}	if !ncutils.IsKernel() {		if !local.IsWGInstalled() {			log.Fatal("Please install WireGuard before using Gravitl Netclient. https://download.wireguard.com")		}	}	if len(os.Args) == 1 && ncutils.IsWindows() {		c := make(chan os.Signal)		signal.Notify(c, os.Interrupt, syscall.SIGTERM)		go func() {			<-c			log.Println("closing Gravitl Netclient")			os.Exit(0)		}()		command.RunUserspaceDaemon()	} else {		err := app.Run(os.Args)		if err != nil {			log.Fatal(err)		}	}}func setGarbageCollection() {	_, gcset := os.LookupEnv("GOGC")	if !gcset {		debug.SetGCPercent(ncutils.DEFAULT_GC_PERCENT)	}}
 |