Browse Source

More wiring up of addroot/removeroot etc.

Adam Ierymenko 5 years ago
parent
commit
e9656ecf11

+ 0 - 18
go/cmd/zerotier/cli/addroot.go

@@ -1,18 +0,0 @@
-/*
- * 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: 2024-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 cli
-
-// AddRoot CLI command
-func AddRoot(basePath, authToken string, args []string) {
-}

+ 3 - 3
go/cmd/zerotier/cli/help.go

@@ -41,13 +41,13 @@ Commands:
   service                              Start as service
   service                              Start as service
   status                               Show ZeroTier status and config
   status                               Show ZeroTier status and config
   peers                                Show VL1 peers and link information
   peers                                Show VL1 peers and link information
+  roots                                Show only root peers
+  addroot <identity> [IP/port]         Add root with optional bootstrap IP
+  removeroot <address|identity>        Remove root
   join <network ID>                    Join a virtual network
   join <network ID>                    Join a virtual network
   leave <network ID>                   Leave a virtual network
   leave <network ID>                   Leave a virtual network
   networks                             List joined VL2 virtual networks
   networks                             List joined VL2 virtual networks
   network <network ID>                 Show verbose network info
   network <network ID>                 Show verbose network info
-  addroot <identity> [IP/port]         Add root with optional bootstrap IP
-  removeroot <identity|address>        Remove root
-  roots                                Show configured VL1 root servers
   set <network ID> [option] [value]    Get or set a network config option
   set <network ID> [option] [value]    Get or set a network config option
     manageips <boolean>                Is IP management allowed?
     manageips <boolean>                Is IP management allowed?
     manageroutes <boolean>             Is route management allowed?
     manageroutes <boolean>             Is route management allowed?

+ 30 - 23
go/cmd/zerotier/cli/peers.go

@@ -16,45 +16,52 @@ package cli
 import (
 import (
 	"fmt"
 	"fmt"
 	"os"
 	"os"
+	"strings"
 
 
 	"zerotier/pkg/zerotier"
 	"zerotier/pkg/zerotier"
 )
 )
 
 
-// Peers CLI command
-func Peers(basePath, authToken string, args []string, jsonOutput bool) {
+// Peers CLI command (also used for 'roots' command with rootsOnly set to true)
+func Peers(basePath, authToken string, args []string, jsonOutput bool, rootsOnly bool) {
 	var peers []zerotier.Peer
 	var peers []zerotier.Peer
-	clock := apiGet(basePath, authToken, "/peer", &peers)
+	apiGet(basePath, authToken, "/peer", &peers)
+
+	if rootsOnly {
+		roots := make([]zerotier.Peer, 0, len(peers))
+		for i := range peers {
+			if peers[i].Root {
+				roots = append(roots, peers[i])
+			}
+		}
+		peers = roots
+	}
 
 
 	if jsonOutput {
 	if jsonOutput {
 		fmt.Println(jsonDump(&peers))
 		fmt.Println(jsonDump(&peers))
 	} else {
 	} else {
-		fmt.Printf("<address>  <ver>   <role> <lat> <link> <lastTX> <lastRX> <path(s)>\n")
+		fmt.Printf("<address>  <ver>   <root> <lat(ms)> <path(s)>\n")
 		for _, peer := range peers {
 		for _, peer := range peers {
-			role := "LEAF"
-			link := "RELAY"
-			lastTX, lastRX := int64(0), int64(0)
-			address := ""
+			root := ""
+			if peer.Root {
+				root = " *"
+			}
+
+			var paths strings.Builder
 			if len(peer.Paths) > 0 {
 			if len(peer.Paths) > 0 {
-				link = "DIRECT"
-				lastTX, lastRX = clock-peer.Paths[0].LastSend, clock-peer.Paths[0].LastReceive
-				if lastTX < 0 {
-					lastTX = 0
+				if paths.Len() > 0 {
+					paths.WriteRune(' ')
 				}
 				}
-				if lastRX < 0 {
-					lastRX = 0
-				}
-				address = fmt.Sprintf("%s/%d", peer.Paths[0].IP.String(), peer.Paths[0].Port)
+				paths.WriteString(fmt.Sprintf("%s/%d", peer.Paths[0].IP.String(), peer.Paths[0].Port))
+			} else {
+				paths.WriteString("(relayed)")
 			}
 			}
-			fmt.Printf("%.10x %-7s %-6s %-5d %-6s %-8d %-8d %s\n",
+
+			fmt.Printf("%.10x %-7s %-6s %-9d %s\n",
 				uint64(peer.Address),
 				uint64(peer.Address),
 				fmt.Sprintf("%d.%d.%d", peer.Version[0], peer.Version[1], peer.Version[2]),
 				fmt.Sprintf("%d.%d.%d", peer.Version[0], peer.Version[1], peer.Version[2]),
-				role,
+				root,
 				peer.Latency,
 				peer.Latency,
-				link,
-				lastTX,
-				lastRX,
-				address,
-			)
+				paths.String())
 		}
 		}
 	}
 	}
 
 

+ 0 - 18
go/cmd/zerotier/cli/removeroot.go

@@ -1,18 +0,0 @@
-/*
- * 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: 2024-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 cli
-
-// RemoveRoot CLI command
-func RemoveRoot(basePath, authToken string, args []string) {
-}

+ 0 - 18
go/cmd/zerotier/cli/roots.go

@@ -1,18 +0,0 @@
-/*
- * 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: 2024-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 cli
-
-// Roots CLI command
-func Roots(basePath, authToken string, args []string, jsonOutput bool) {
-}

+ 52 - 0
go/cmd/zerotier/cli/setroot.go

@@ -0,0 +1,52 @@
+/*
+ * 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: 2024-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 cli
+
+import (
+	"fmt"
+	"os"
+
+	"zerotier/pkg/zerotier"
+)
+
+// SetRoot CLI command, used for addroot and removeroot.
+func SetRoot(basePath, authToken string, args []string, root bool) {
+	if len(args) < 1 || len(args) > 2 {
+		Help()
+		os.Exit(1)
+	}
+
+	id := readIdentity(args[0])
+	if id == nil {
+		fmt.Printf("ERROR: invalid identity '%s' (tried literal or reading as file)\n",args[0])
+		os.Exit(1)
+	}
+
+	var bootstrap *zerotier.InetAddress
+	if len(args) == 2 {
+		bootstrap = zerotier.NewInetAddressFromString(args[1])
+		if bootstrap == nil || bootstrap.Nil() {
+			fmt.Printf("ERROR: invalid bootstrap address '%s'\n",args[1])
+			os.Exit(1)
+		}
+	}
+
+	var peer zerotier.PeerMutableFields
+	peer.Identity = id
+	peer.Bootstrap = bootstrap
+	peer.Root = &root
+	apiPost(basePath, authToken, "/peer/"+id.Address().String(), &peer, nil)
+	fmt.Printf("OK %s", id.String())
+	os.Exit(0)
+}

+ 4 - 4
go/cmd/zerotier/zerotier.go

@@ -133,16 +133,16 @@ func main() {
 		cli.Status(basePath, authToken, cmdArgs, *jflag)
 		cli.Status(basePath, authToken, cmdArgs, *jflag)
 	case "peers", "listpeers":
 	case "peers", "listpeers":
 		authTokenRequired(authToken)
 		authTokenRequired(authToken)
-		cli.Peers(basePath, authToken, cmdArgs, *jflag)
+		cli.Peers(basePath, authToken, cmdArgs, *jflag, false)
 	case "roots", "listroots":
 	case "roots", "listroots":
 		authTokenRequired(authToken)
 		authTokenRequired(authToken)
-		cli.Roots(basePath, authToken, cmdArgs, *jflag)
+		cli.Peers(basePath, authToken, cmdArgs, *jflag, true)
 	case "addroot":
 	case "addroot":
 		authTokenRequired(authToken)
 		authTokenRequired(authToken)
-		cli.AddRoot(basePath, authToken, cmdArgs)
+		cli.SetRoot(basePath, authToken, cmdArgs, true)
 	case "removeroot":
 	case "removeroot":
 		authTokenRequired(authToken)
 		authTokenRequired(authToken)
-		cli.RemoveRoot(basePath, authToken, cmdArgs)
+		cli.SetRoot(basePath, authToken, cmdArgs, false)
 	case "identity":
 	case "identity":
 		cli.Identity(cmdArgs)
 		cli.Identity(cmdArgs)
 	case "networks", "listnetworks":
 	case "networks", "listnetworks":

+ 4 - 10
go/pkg/zerotier/api.go

@@ -226,12 +226,6 @@ func apiCheckAuth(out http.ResponseWriter, req *http.Request, token string) bool
 	return false
 	return false
 }
 }
 
 
-type peerMutableFields struct {
-	Identity  *Identity    `json:"identity"`
-	Role      *int         `json:"role"`
-	Bootstrap *InetAddress `json:"bootstrap,omitempty"`
-}
-
 // createAPIServer creates and starts an HTTP server for a given node
 // createAPIServer creates and starts an HTTP server for a given node
 func createAPIServer(basePath string, node *Node) (*http.Server, *http.Server, error) {
 func createAPIServer(basePath string, node *Node) (*http.Server, *http.Server, error) {
 	// Read authorization token, automatically generating one if it's missing
 	// Read authorization token, automatically generating one if it's missing
@@ -372,14 +366,14 @@ func createAPIServer(basePath string, node *Node) (*http.Server, *http.Server, e
 				_ = apiSendObj(out, req, http.StatusNotFound, &APIErr{"peer not found"})
 				_ = apiSendObj(out, req, http.StatusNotFound, &APIErr{"peer not found"})
 				return
 				return
 			}
 			}
-			var peerChanges peerMutableFields
+			var peerChanges PeerMutableFields
 			if apiReadObj(out, req, &peerChanges) == nil {
 			if apiReadObj(out, req, &peerChanges) == nil {
-				if peerChanges.Role != nil || peerChanges.Bootstrap != nil {
+				if peerChanges.Root != nil || peerChanges.Bootstrap != nil {
 					peers := node.Peers()
 					peers := node.Peers()
 					for _, p := range peers {
 					for _, p := range peers {
 						if p.Address == queriedID && (peerChanges.Identity == nil || peerChanges.Identity.Equals(p.Identity)) {
 						if p.Address == queriedID && (peerChanges.Identity == nil || peerChanges.Identity.Equals(p.Identity)) {
-							if peerChanges.Role != nil && *peerChanges.Role != p.Role {
-								if *peerChanges.Role == PeerRoleRoot {
+							if peerChanges.Root != nil && *peerChanges.Root != p.Root {
+								if *peerChanges.Root {
 									_ = node.AddRoot(p.Identity, peerChanges.Bootstrap)
 									_ = node.AddRoot(p.Identity, peerChanges.Bootstrap)
 								} else {
 								} else {
 									node.RemoveRoot(p.Identity)
 									node.RemoveRoot(p.Identity)

+ 5 - 0
go/pkg/zerotier/inetaddress.go

@@ -105,6 +105,11 @@ type InetAddress struct {
 	Port int
 	Port int
 }
 }
 
 
+// Nil returns true if this InetAddress is empty.
+func (ina *InetAddress) Nil() bool {
+	return len(ina.IP) == 0
+}
+
 // Less returns true if this IP/port is lexicographically less than another
 // Less returns true if this IP/port is lexicographically less than another
 func (ina *InetAddress) Less(i2 *InetAddress) bool {
 func (ina *InetAddress) Less(i2 *InetAddress) bool {
 	c := bytes.Compare(ina.IP, i2.IP)
 	c := bytes.Compare(ina.IP, i2.IP)

+ 11 - 6
go/pkg/zerotier/node.go

@@ -80,6 +80,7 @@ var (
 
 
 	// This map is used to get the Go Node object from a pointer passed back in via C callbacks
 	// This map is used to get the Go Node object from a pointer passed back in via C callbacks
 	nodesByUserPtr     = make(map[uintptr]*Node)
 	nodesByUserPtr     = make(map[uintptr]*Node)
+	nodesByUserPtrCtr  = uintptr(0)
 	nodesByUserPtrLock sync.RWMutex
 	nodesByUserPtrLock sync.RWMutex
 )
 )
 
 
@@ -130,6 +131,9 @@ type Node struct {
 
 
 	// runWaitGroup is used to wait for all node goroutines on shutdown
 	// runWaitGroup is used to wait for all node goroutines on shutdown
 	runWaitGroup sync.WaitGroup
 	runWaitGroup sync.WaitGroup
+
+	// an arbitrary uintptr given to the core as its pointer back to Go's Node instance
+	cPtr uintptr
 }
 }
 
 
 // NewNode creates and initializes a new instance of the ZeroTier node service
 // NewNode creates and initializes a new instance of the ZeroTier node service
@@ -242,17 +246,18 @@ func NewNode(basePath string) (n *Node, err error) {
 	}
 	}
 
 
 	nodesByUserPtrLock.Lock()
 	nodesByUserPtrLock.Lock()
-	nodesByUserPtr[uintptr(unsafe.Pointer(n))] = n
+	nodesByUserPtrCtr++
+	n.cPtr = nodesByUserPtrCtr
+	nodesByUserPtr[n.cPtr] = n
 	nodesByUserPtrLock.Unlock()
 	nodesByUserPtrLock.Unlock()
 
 
-	// Instantiate GoNode and friends from the land of C/C++
 	cPath := C.CString(basePath)
 	cPath := C.CString(basePath)
-	n.gn = C.ZT_GoNode_new(cPath, C.uintptr_t(uintptr(unsafe.Pointer(n))))
+	n.gn = C.ZT_GoNode_new(cPath, C.uintptr_t(n.cPtr))
 	C.free(unsafe.Pointer(cPath))
 	C.free(unsafe.Pointer(cPath))
 	if n.gn == nil {
 	if n.gn == nil {
 		n.infoLog.Println("FATAL: node initialization failed")
 		n.infoLog.Println("FATAL: node initialization failed")
 		nodesByUserPtrLock.Lock()
 		nodesByUserPtrLock.Lock()
-		delete(nodesByUserPtr, uintptr(unsafe.Pointer(n)))
+		delete(nodesByUserPtr, n.cPtr)
 		nodesByUserPtrLock.Unlock()
 		nodesByUserPtrLock.Unlock()
 		return nil, ErrNodeInitFailed
 		return nil, ErrNodeInitFailed
 	}
 	}
@@ -261,7 +266,7 @@ func NewNode(basePath string) (n *Node, err error) {
 	if err != nil {
 	if err != nil {
 		n.infoLog.Printf("FATAL: error obtaining node's identity")
 		n.infoLog.Printf("FATAL: error obtaining node's identity")
 		nodesByUserPtrLock.Lock()
 		nodesByUserPtrLock.Lock()
-		delete(nodesByUserPtr, uintptr(unsafe.Pointer(n)))
+		delete(nodesByUserPtr, n.cPtr)
 		nodesByUserPtrLock.Unlock()
 		nodesByUserPtrLock.Unlock()
 		C.ZT_GoNode_delete(n.gn)
 		C.ZT_GoNode_delete(n.gn)
 		return nil, err
 		return nil, err
@@ -600,7 +605,7 @@ func (n *Node) Peers() []*Peer {
 			p2.IdentityHash = hex.EncodeToString((*[48]byte)(unsafe.Pointer(&p.identityHash[0]))[:])
 			p2.IdentityHash = hex.EncodeToString((*[48]byte)(unsafe.Pointer(&p.identityHash[0]))[:])
 			p2.Version = [3]int{int(p.versionMajor), int(p.versionMinor), int(p.versionRev)}
 			p2.Version = [3]int{int(p.versionMajor), int(p.versionMinor), int(p.versionRev)}
 			p2.Latency = int(p.latency)
 			p2.Latency = int(p.latency)
-			p2.Role = int(p.role)
+			p2.Root = p.root != 0
 			p2.Bootstrap = NewInetAddressFromSockaddr(unsafe.Pointer(&p.bootstrap))
 			p2.Bootstrap = NewInetAddressFromSockaddr(unsafe.Pointer(&p.bootstrap))
 
 
 			p2.Paths = make([]Path, 0, int(p.pathCount))
 			p2.Paths = make([]Path, 0, int(p.pathCount))

+ 8 - 9
go/pkg/zerotier/peer.go

@@ -13,14 +13,6 @@
 
 
 package zerotier
 package zerotier
 
 
-// Peer roles must be the same as in ZeroTierCore.h.
-
-// PeerRoleLeaf indicates a normal leaf node.
-const PeerRoleLeaf = 0
-
-// PeerRoleRoot indicates a root peer.
-const PeerRoleRoot = 1
-
 // Peer is another ZeroTier node
 // Peer is another ZeroTier node
 type Peer struct {
 type Peer struct {
 	Address      Address      `json:"address"`
 	Address      Address      `json:"address"`
@@ -28,7 +20,14 @@ type Peer struct {
 	IdentityHash string       `json:"identityHash"`
 	IdentityHash string       `json:"identityHash"`
 	Version      [3]int       `json:"version"`
 	Version      [3]int       `json:"version"`
 	Latency      int          `json:"latency"`
 	Latency      int          `json:"latency"`
-	Role         int          `json:"role"`
+	Root         bool         `json:"root"`
 	Bootstrap    *InetAddress `json:"bootstrap,omitempty"`
 	Bootstrap    *InetAddress `json:"bootstrap,omitempty"`
 	Paths        []Path       `json:"paths,omitempty"`
 	Paths        []Path       `json:"paths,omitempty"`
 }
 }
+
+// PeerMutableFields contains only the mutable fields of Peer as nullable pointers.
+type PeerMutableFields struct {
+	Identity  *Identity    `json:"identity"`
+	Root      *bool        `json:"root"`
+	Bootstrap *InetAddress `json:"bootstrap,omitempty"`
+}

+ 2 - 11
include/ZeroTierCore.h

@@ -1323,15 +1323,6 @@ typedef struct
 	int preferred;
 	int preferred;
 } ZT_PeerPhysicalPath;
 } ZT_PeerPhysicalPath;
 
 
-/**
- * What trust hierarchy role does this peer have?
- */
-enum ZT_PeerRole
-{
-	ZT_PEER_ROLE_LEAF = 0,
-	ZT_PEER_ROLE_ROOT = 1
-};
-
 /**
 /**
  * Peer status result buffer
  * Peer status result buffer
  */
  */
@@ -1373,9 +1364,9 @@ typedef struct
 	int latency;
 	int latency;
 
 
 	/**
 	/**
-	 * What trust hierarchy role does this device have?
+	 * If non-zero this peer is a root
 	 */
 	 */
-	enum ZT_PeerRole role;
+	int root;
 
 
 	/**
 	/**
 	 * Bootstrap address
 	 * Bootstrap address

+ 1 - 1
node/Node.cpp

@@ -446,7 +446,7 @@ ZT_PeerList *Node::peers() const
 		p->latency = (int)(*pi)->latency();
 		p->latency = (int)(*pi)->latency();
 		if (p->latency >= 0xffff)
 		if (p->latency >= 0xffff)
 			p->latency = -1;
 			p->latency = -1;
-		p->role = RR->topology->isRoot((*pi)->identity()) ? ZT_PEER_ROLE_ROOT : ZT_PEER_ROLE_LEAF;
+		p->root = RR->topology->isRoot((*pi)->identity()) ? 1 : 0;
 		memcpy(&p->bootstrap,&((*pi)->bootstrap()),sizeof(sockaddr_storage));
 		memcpy(&p->bootstrap,&((*pi)->bootstrap()),sizeof(sockaddr_storage));
 
 
 		std::vector< SharedPtr<Path> > paths;
 		std::vector< SharedPtr<Path> > paths;