Bläddra i källkod

Rooting around

Adam Ierymenko 5 år sedan
förälder
incheckning
3341c4a670
2 ändrade filer med 164 tillägg och 23 borttagningar
  1. 139 23
      go/pkg/zerotier/node.go
  2. 25 0
      go/pkg/zerotier/root.go

+ 139 - 23
go/pkg/zerotier/node.go

@@ -58,8 +58,8 @@ const (
 	// CoreVersionBuild is the build version of the ZeroTier core
 	CoreVersionBuild int = C.ZEROTIER_ONE_VERSION_BUILD
 
-	afInet  int = C.AF_INET
-	afInet6 int = C.AF_INET6
+	afInet  = C.AF_INET
+	afInet6 = C.AF_INET6
 )
 
 var (
@@ -67,6 +67,67 @@ var (
 	nodesByUserPtrLock sync.RWMutex
 )
 
+func sockaddrStorageToIPNet(ss *C.struct_sockaddr_storage) *net.IPNet {
+	var a net.IPNet
+	switch ss.ss_family {
+	case afInet:
+		sa4 := (*C.struct_sockaddr_in)(unsafe.Pointer(ss))
+		var ip4 [4]byte
+		copy(ip4[:], (*[4]byte)(unsafe.Pointer(&sa4.sin_addr))[:])
+		a.IP = net.IP(ip4[:])
+		a.Mask = net.CIDRMask(int(binary.BigEndian.Uint16(((*[2]byte)(unsafe.Pointer(&sa4.sin_port)))[:])), 32)
+		return &a
+	case afInet6:
+		sa6 := (*C.struct_sockaddr_in6)(unsafe.Pointer(ss))
+		var ip6 [16]byte
+		copy(ip6[:], (*[16]byte)(unsafe.Pointer(&sa6.sin6_addr))[:])
+		a.IP = net.IP(ip6[:])
+		a.Mask = net.CIDRMask(int(binary.BigEndian.Uint16(((*[2]byte)(unsafe.Pointer(&sa6.sin6_port)))[:])), 128)
+		return &a
+	}
+	return nil
+}
+
+func sockaddrStorageToUDPAddr(ss *C.struct_sockaddr_storage) *net.UDPAddr {
+	var a net.UDPAddr
+	switch ss.ss_family {
+	case afInet:
+		sa4 := (*C.struct_sockaddr_in)(unsafe.Pointer(ss))
+		var ip4 [4]byte
+		copy(ip4[:], (*[4]byte)(unsafe.Pointer(&sa4.sin_addr))[:])
+		a.IP = net.IP(ip4[:])
+		a.Port = int(binary.BigEndian.Uint16(((*[2]byte)(unsafe.Pointer(&sa4.sin_port)))[:]))
+		return &a
+	case afInet6:
+		sa6 := (*C.struct_sockaddr_in6)(unsafe.Pointer(ss))
+		var ip6 [16]byte
+		copy(ip6[:], (*[16]byte)(unsafe.Pointer(&sa6.sin6_addr))[:])
+		a.IP = net.IP(ip6[:])
+		a.Port = int(binary.BigEndian.Uint16(((*[2]byte)(unsafe.Pointer(&sa6.sin6_port)))[:]))
+		return &a
+	}
+	return nil
+}
+
+func makeSockaddrStorage(ip net.IP, port int, ss *C.struct_sockaddr_storage) bool {
+	C.memset(unsafe.Pointer(ss), 0, C.sizeof_struct_sockaddr_storage)
+	if len(ip) == 4 {
+		sa4 := (*C.struct_sockaddr_in)(unsafe.Pointer(ss))
+		sa4.sin_family = afInet
+		copy(((*[4]byte)(unsafe.Pointer(&sa4.sin_addr)))[:], ip)
+		binary.BigEndian.PutUint16(((*[2]byte)(unsafe.Pointer(&sa4.sin_port)))[:], uint16(port))
+		return true
+	}
+	if len(ip) == 16 {
+		sa6 := (*C.struct_sockaddr_in6)(unsafe.Pointer(ss))
+		sa6.sin6_family = afInet6
+		copy(((*[16]byte)(unsafe.Pointer(&sa6.sin6_addr)))[:], ip)
+		binary.BigEndian.PutUint16(((*[2]byte)(unsafe.Pointer(&sa6.sin6_port)))[:], uint16(port))
+		return true
+	}
+	return false
+}
+
 //////////////////////////////////////////////////////////////////////////////
 
 // Node represents an instance of the ZeroTier core node and related C++ I/O code
@@ -160,6 +221,82 @@ func (n *Node) Leave(nwid uint64) error {
 	return nil
 }
 
+// AddStaticRoot adds a statically defined root server to this node.
+// If a static root with the given identity already exists this will update its IP and port information.
+func (n *Node) AddStaticRoot(id *Identity, addrs []net.Addr) {
+	var saddrs []*C.struct_sockaddr_storage
+	for _, a := range addrs {
+		aa, _ := a.(*net.UDPAddr)
+		if aa != nil {
+			ss := new(C.struct_sockaddr_storage)
+			if makeSockaddrStorage(aa.IP, aa.Port, ss) {
+				saddrs = append(saddrs, ss)
+			}
+		}
+	}
+	if len(saddrs) > 0 {
+		ids := C.CString(id.String())
+		C.ZT_Node_setStaticRoot(n.zn, ids, &saddrs[0], C.uint(len(saddrs)))
+		C.free(unsafe.Pointer(ids))
+	}
+}
+
+// RemoveStaticRoot removes a statically defined root server from this node.
+func (n *Node) RemoveStaticRoot(id *Identity) {
+	ids := C.CString(id.String())
+	C.ZT_Node_removeStaticRoot(n.zn, ids)
+	C.free(unsafe.Pointer(ids))
+}
+
+// AddDynamicRoot adds a dynamic root to this node.
+// If the locator parameter is non-empty it can contain a binary serialized locator
+// to use if (or until) one can be fetched via DNS.
+func (n *Node) AddDynamicRoot(dnsName string, locator []byte) {
+	dn := C.CString(dnsName)
+	if len(locator) > 0 {
+		C.ZT_Node_setDynamicRoot(n.zn, dn, unsafe.Pointer(&locator[0]), C.uint(len(locator)))
+	} else {
+		C.ZT_Node_setDynamicRoot(n.zn, dn, nil, 0)
+	}
+	C.free(unsafe.Pointer(dn))
+}
+
+// RemoveDynamicRoot removes a dynamic root from this node.
+func (n *Node) RemoveDynamicRoot(dnsName string) {
+	dn := C.CString(dnsName)
+	C.ZT_Node_removeDynamicRoot(n.zn, dn)
+	C.free(unsafe.Pointer(dn))
+}
+
+// ListRoots retrieves a list of root servers on this node and their preferred and online status.
+func (n *Node) ListRoots() []Root {
+	var roots []Root
+	rl := C.ZT_Node_listRoots(n.zn, C.int64_t(TimeMs()))
+	if rl != nil {
+		for i := 0; i < int(rl.count); i++ {
+			id, err := NewIdentityFromString(C.GoString(rl.roots[i].identity))
+			if err == nil {
+				var addrs []net.Addr
+				for j := 0; j < int(rl.roots[i].addressCount); j++ {
+					a := sockaddrStorageToUDPAddr(&rl.roots[i].addresses[j])
+					if a != nil {
+						addrs = append(addrs, a)
+					}
+				}
+				roots = append(roots, Root{
+					DNSName:   C.GoString(rl.roots[i].dnsName),
+					Identity:  id,
+					Addresses: addrs,
+					Preferred: (rl.roots[i].preferred != 0),
+					Online:    (rl.roots[i].online != 0),
+				})
+			}
+		}
+		defer C.ZT_Node_freeQueryResult(n.zn, unsafe.Pointer(rl))
+	}
+	return roots
+}
+
 //////////////////////////////////////////////////////////////////////////////
 
 func (n *Node) pathCheck(ztAddress uint64, af int, ip net.IP, port int) bool {
@@ -345,27 +482,6 @@ func goDNSResolverFunc(gn unsafe.Pointer, dnsRecordTypes unsafe.Pointer, numDNSR
 	}()
 }
 
-func sockaddrStorageToIPNet(ss *C.struct_sockaddr_storage) *net.IPNet {
-	var a net.IPNet
-	switch ss.ss_family {
-	case afInet:
-		sa4 := (*C.struct_sockaddr_in)(unsafe.Pointer(ss))
-		var ip4 [4]byte
-		copy(ip4[:], (*[4]byte)(unsafe.Pointer(&sa4.sin_addr))[:])
-		a.IP = net.IP(ip4[:])
-		a.Mask = net.CIDRMask(int(binary.BigEndian.Uint16(((*[2]byte)(unsafe.Pointer(&sa4.sin_port)))[:])), 32)
-		return &a
-	case afInet6:
-		sa6 := (*C.struct_sockaddr_in6)(unsafe.Pointer(ss))
-		var ip6 [16]byte
-		copy(ip6[:], (*[16]byte)(unsafe.Pointer(&sa6.sin6_addr))[:])
-		a.IP = net.IP(ip6[:])
-		a.Mask = net.CIDRMask(int(binary.BigEndian.Uint16(((*[2]byte)(unsafe.Pointer(&sa6.sin6_port)))[:])), 128)
-		return &a
-	}
-	return nil
-}
-
 //export goVirtualNetworkConfigFunc
 func goVirtualNetworkConfigFunc(gn, tapP unsafe.Pointer, nwid C.uint64_t, op C.int, conf unsafe.Pointer) {
 	go func() {

+ 25 - 0
go/pkg/zerotier/root.go

@@ -0,0 +1,25 @@
+/*
+ * Copyright (c)2019 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: 2023-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 zerotier
+
+import "net"
+
+// Root describes a root server used to find and establish communication with other nodes.
+type Root struct {
+	DNSName   string
+	Identity  *Identity
+	Addresses []net.Addr
+	Preferred bool
+	Online    bool
+}