This commit is contained in:
Adam Ierymenko 2019-09-21 00:19:20 -07:00
parent fbf74d3baa
commit 6ce4663a31
No known key found for this signature in database
GPG Key ID: C8877CF2D7A5D7F3
6 changed files with 176 additions and 43 deletions

View File

@ -1,3 +1,5 @@
module zerotier module zerotier
go 1.13 go 1.13
require github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95

View File

@ -0,0 +1,4 @@
github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95 h1:S4qyfL2sEm5Budr4KVMyEniCy+PbS55651I/a+Kn/NQ=
github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95/go.mod h1:QiyDdbZLaJ/mZP4Zwc9g2QsfaEA4o7XvvgZegSci5/E=
golang.org/x/sys v0.0.0-20190529164535-6a60838ec259 h1:so6Hr/LodwSZ5UQDu/7PmQiDeS112WwtLvU3lpSPZTU=
golang.org/x/sys v0.0.0-20190529164535-6a60838ec259/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

@ -391,6 +391,11 @@ extern "C" void ZT_GoNode_delete(ZT_GoNode *gn)
delete gn; delete gn;
} }
extern "C" ZT_Node *ZT_GoNode_getNode(ZT_GoNode *gn)
{
return gn->node;
}
// Sets flags and socket options common to both IPv4 and IPv6 UDP sockets // Sets flags and socket options common to both IPv4 and IPv6 UDP sockets
static void setCommonUdpSocketSettings(ZT_SOCKET udpSock,const char *dev) static void setCommonUdpSocketSettings(ZT_SOCKET udpSock,const char *dev)
{ {

View File

@ -68,15 +68,19 @@ func goPathLookupFunc(gn unsafe.Pointer, ztAddress C.uint64_t, desiredAddressFam
} }
ip, port := node.pathLookup(uint64(ztAddress)) ip, port := node.pathLookup(uint64(ztAddress))
if len(ip) > 0 && port > 0 && port <= 65535 {
ip4 := ip.To4() ip4 := ip.To4()
if len(ip4) == 4 { if len(ip4) == 4 {
*((*C.int)(familyP)) = C.int(afInet) *((*C.int)(familyP)) = C.int(afInet)
copy((*[4]byte)(ipP)[:], ip4) copy((*[4]byte)(ipP)[:], ip4)
*((*C.int)(portP)) = C.int(port) *((*C.int)(portP)) = C.int(port)
return 1
} else if len(ip) == 16 { } else if len(ip) == 16 {
*((*C.int)(familyP)) = C.int(afInet6) *((*C.int)(familyP)) = C.int(afInet6)
copy((*[16]byte)(ipP)[:], ip) copy((*[16]byte)(ipP)[:], ip)
*((*C.int)(portP)) = C.int(port) *((*C.int)(portP)) = C.int(port)
return 1
}
} }
return 0 return 0
} }
@ -154,7 +158,7 @@ func goVirtualNetworkConfigFunc(gn, tapP unsafe.Pointer, nwid C.uint64_t, op C.i
if node == nil { if node == nil {
return 255 return 255
} }
return C.int(node.handleNetworkConfigUpdate(int(op), (*C.ZT_VirtualNetworkConfig)(conf))) return C.int(node.handleNetworkConfigUpdate(uint64(nwid), int(op), (*C.ZT_VirtualNetworkConfig)(conf)))
} }
//export goZtEvent //export goZtEvent
@ -181,6 +185,8 @@ func goZtEvent(gn unsafe.Pointer, eventType C.int, data unsafe.Pointer) {
} }
} }
// These are really part of nativeTap
func handleTapMulticastGroupChange(gn unsafe.Pointer, nwid, mac C.uint64_t, adi C.uint32_t, added bool) { func handleTapMulticastGroupChange(gn unsafe.Pointer, nwid, mac C.uint64_t, adi C.uint32_t, added bool) {
nodesByUserPtrLock.RLock() nodesByUserPtrLock.RLock()
node := nodesByUserPtr[uintptr(gn)] node := nodesByUserPtr[uintptr(gn)]

View File

@ -14,74 +14,77 @@
package zerotier package zerotier
import ( import (
"errors"
"fmt"
"io/ioutil"
"net" "net"
"runtime" "os"
"path"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time"
"unsafe" "unsafe"
acl "github.com/hectane/go-acl"
) )
//#cgo CFLAGS: -O3 //#cgo CFLAGS: -O3
//#cgo LDFLAGS: ${SRCDIR}/../../../build/node/libzt_core.a ${SRCDIR}/../../../build/go/native/libzt_go_native.a -lc++ -lpthread //#cgo LDFLAGS: ${SRCDIR}/../../../build/node/libzt_core.a ${SRCDIR}/../../../build/osdep/libzt_osdep.a ${SRCDIR}/../../../build/go/native/libzt_go_native.a -lc++ -lpthread
//#define ZT_CGO 1 //#define ZT_CGO 1
//#include <stdint.h> //#include <stdint.h>
//#include <stdlib.h>
//#include <string.h>
//#include "../../native/GoGlue.h" //#include "../../native/GoGlue.h"
//#if __has_include("../../../version.h")
//#include "../../../version.h"
//#else
//#define ZEROTIER_ONE_VERSION_MAJOR 255
//#define ZEROTIER_ONE_VERSION_MINOR 255
//#define ZEROTIER_ONE_VERSION_REVISION 255
//#define ZEROTIER_ONE_VERSION_BUILD 255
//#endif
import "C" import "C"
// Network status states
const ( const (
// CoreVersionMajor is the major version of the ZeroTier core NetworkStatusRequestConfiguration int = C.ZT_NETWORK_STATUS_REQUESTING_CONFIGURATION
CoreVersionMajor int = C.ZEROTIER_ONE_VERSION_MAJOR NetworkStatusOK int = C.ZT_NETWORK_STATUS_OK
NetworkStatusAccessDenied int = C.ZT_NETWORK_STATUS_ACCESS_DENIED
// CoreVersionMinor is the minor version of the ZeroTier core NetworkStatusNotFound int = C.ZT_NETWORK_STATUS_NOT_FOUND
CoreVersionMinor int = C.ZEROTIER_ONE_VERSION_MINOR NetworkStatusPortError int = C.ZT_NETWORK_STATUS_PORT_ERROR
NetworkStatusClientTooOld int = C.ZT_NETWORK_STATUS_CLIENT_TOO_OLD
// CoreVersionRevision is the revision of the ZeroTier core
CoreVersionRevision int = C.ZEROTIER_ONE_VERSION_REVISION
// CoreVersionBuild is the build version of the ZeroTier core
CoreVersionBuild int = C.ZEROTIER_ONE_VERSION_BUILD
) )
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// Node is an instance of a ZeroTier node // Node is an instance of a ZeroTier node
type Node struct { type Node struct {
gn *C.ZT_GoNode path string
zn *C.ZT_Node
networks map[uint64]*Network networks map[uint64]*Network
networksLock sync.RWMutex networksLock sync.RWMutex
gn *C.ZT_GoNode
zn *C.ZT_Node
online uint32 online uint32
running uint32 running uint32
} }
// NewNode creates and initializes a new instance of the ZeroTier node service // NewNode creates and initializes a new instance of the ZeroTier node service
func NewNode() *Node { func NewNode(path string) (*Node, error) {
n := new(Node) n := new(Node)
n.path = path
n.networks = make(map[uint64]*Network) n.networks = make(map[uint64]*Network)
cpath := C.CString(path)
n.gn = C.ZT_GoNode_new(cpath)
C.free(unsafe.Pointer(cpath))
if n.gn == nil {
return nil, errors.New("unable to create new Node instance")
}
n.zn = (*C.ZT_Node)(C.ZT_GoNode_getNode(n.gn))
gnRawAddr := uintptr(unsafe.Pointer(n.gn)) gnRawAddr := uintptr(unsafe.Pointer(n.gn))
nodesByUserPtrLock.Lock() nodesByUserPtrLock.Lock()
nodesByUserPtr[gnRawAddr] = n nodesByUserPtr[gnRawAddr] = n
nodesByUserPtrLock.Unlock() nodesByUserPtrLock.Unlock()
runtime.SetFinalizer(n, func(obj interface{}) { // make sure this always happens
nodesByUserPtrLock.Lock()
delete(nodesByUserPtr, gnRawAddr)
nodesByUserPtrLock.Unlock()
})
n.online = 0
n.running = 1 n.running = 1
return n return n, nil
} }
// Close closes this Node and frees its underlying C++ Node structures // Close closes this Node and frees its underlying C++ Node structures
@ -97,7 +100,35 @@ func (n *Node) Close() {
// Join joins a network // Join joins a network
// If tap is nil, the default system tap for this OS/platform is used (if available). // If tap is nil, the default system tap for this OS/platform is used (if available).
func (n *Node) Join(nwid uint64, tap Tap) (*Network, error) { func (n *Node) Join(nwid uint64, tap Tap) (*Network, error) {
return nil, nil n.networksLock.RLock()
if nw, have := n.networks[nwid]; have {
return nw, nil
}
n.networksLock.RUnlock()
if tap != nil {
return nil, errors.New("not implemented yet")
}
ntap := C.ZT_GoNode_join(n.gn, C.uint64_t(nwid))
if ntap == nil {
return nil, errors.New("unable to initialize native tap (check device driver or permissions)")
}
nw := &Network{
id: NetworkID(nwid),
config: NetworkConfig{
ID: NetworkID(nwid),
Status: NetworkStatusRequestConfiguration,
LastUpdated: time.Now(),
Enabled: true,
},
tap: &nativeTap{tap: unsafe.Pointer(ntap), enabled: 1},
}
n.networksLock.Lock()
n.networks[nwid] = nw
n.networksLock.Unlock()
return nw, nil
} }
// Leave leaves a network // Leave leaves a network
@ -115,13 +146,60 @@ func (n *Node) pathLookup(ztAddress uint64) (net.IP, int) {
return nil, 0 return nil, 0
} }
func (n *Node) makeStateObjectPath(objType int, id [2]uint64) (string, bool) {
var fp string
secret := false
switch objType {
case C.ZT_STATE_OBJECT_IDENTITY_PUBLIC:
fp = path.Join(n.path, "identity.public")
case C.ZT_STATE_OBJECT_IDENTITY_SECRET:
fp = path.Join(n.path, "identity.secret")
secret = true
case C.ZT_STATE_OBJECT_PEER:
fp = path.Join(n.path, "peers.d")
os.Mkdir(fp, 0755)
fp = path.Join(fp, fmt.Sprintf("%.10x.peer", id[0]))
secret = true
case C.ZT_STATE_OBJECT_NETWORK_CONFIG:
fp = path.Join(n.path, "networks.d")
os.Mkdir(fp, 0755)
fp = path.Join(fp, fmt.Sprintf("%.16x.conf", id[0]))
case C.ZT_STATE_OBJECT_ROOT_LIST:
fp = path.Join(n.path, "roots")
}
return fp, secret
}
func (n *Node) stateObjectPut(objType int, id [2]uint64, data []byte) { func (n *Node) stateObjectPut(objType int, id [2]uint64, data []byte) {
fp, secret := n.makeStateObjectPath(objType, id)
if len(fp) > 0 {
fileMode := os.FileMode(0644)
if secret {
fileMode = os.FileMode(0600)
}
ioutil.WriteFile(fp, data, fileMode)
if secret {
acl.Chmod(fp, 0600) // this emulates Unix chmod on Windows and uses os.Chmod on Unix-type systems
}
}
} }
func (n *Node) stateObjectDelete(objType int, id [2]uint64) { func (n *Node) stateObjectDelete(objType int, id [2]uint64) {
fp, _ := n.makeStateObjectPath(objType, id)
if len(fp) > 0 {
os.Remove(fp)
}
} }
func (n *Node) stateObjectGet(objType int, id [2]uint64) ([]byte, bool) { func (n *Node) stateObjectGet(objType int, id [2]uint64) ([]byte, bool) {
fp, _ := n.makeStateObjectPath(objType, id)
if len(fp) > 0 {
fd, err := ioutil.ReadFile(fp)
if err != nil {
return nil, false
}
return fd, true
}
return nil, false return nil, false
} }
@ -134,6 +212,6 @@ func (n *Node) handleUserMessage(originAddress, messageTypeID uint64, data []byt
func (n *Node) handleRemoteTrace(originAddress uint64, dictData []byte) { func (n *Node) handleRemoteTrace(originAddress uint64, dictData []byte) {
} }
func (n *Node) handleNetworkConfigUpdate(op int, config *C.ZT_VirtualNetworkConfig) int { func (n *Node) handleNetworkConfigUpdate(nwid uint64, op int, config *C.ZT_VirtualNetworkConfig) int {
return 0 return 0
} }

View File

@ -0,0 +1,38 @@
/*
* 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
//#if __has_include("../../../version.h")
//#include "../../../version.h"
//#else
//#define ZEROTIER_ONE_VERSION_MAJOR 255
//#define ZEROTIER_ONE_VERSION_MINOR 255
//#define ZEROTIER_ONE_VERSION_REVISION 255
//#define ZEROTIER_ONE_VERSION_BUILD 255
//#endif
import "C"
const (
// CoreVersionMajor is the major version of the ZeroTier core
CoreVersionMajor int = C.ZEROTIER_ONE_VERSION_MAJOR
// CoreVersionMinor is the minor version of the ZeroTier core
CoreVersionMinor int = C.ZEROTIER_ONE_VERSION_MINOR
// CoreVersionRevision is the revision of the ZeroTier core
CoreVersionRevision int = C.ZEROTIER_ONE_VERSION_REVISION
// CoreVersionBuild is the build version of the ZeroTier core
CoreVersionBuild int = C.ZEROTIER_ONE_VERSION_BUILD
)