ZeroTierOne/go/pkg/zerotier/node.go

231 lines
5.6 KiB
Go
Raw Normal View History

2019-09-21 01:48:48 +00:00
/*
* 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
2019-09-21 02:51:57 +00:00
import (
2019-09-21 07:19:20 +00:00
"errors"
"fmt"
"io/ioutil"
2019-09-21 02:51:57 +00:00
"net"
2019-09-21 07:19:20 +00:00
"os"
"path"
2019-09-21 02:51:57 +00:00
"sync"
"sync/atomic"
2019-09-21 07:19:20 +00:00
"time"
2019-09-21 02:51:57 +00:00
"unsafe"
2019-09-21 07:19:20 +00:00
acl "github.com/hectane/go-acl"
2019-09-21 02:51:57 +00:00
)
2019-09-21 01:48:48 +00:00
//#cgo CFLAGS: -O3
2019-09-21 07:19:20 +00:00
//#cgo LDFLAGS: ${SRCDIR}/../../../build/node/libzt_core.a ${SRCDIR}/../../../build/osdep/libzt_osdep.a ${SRCDIR}/../../../build/go/native/libzt_go_native.a -lc++ -lpthread
2019-09-21 01:48:48 +00:00
//#define ZT_CGO 1
//#include <stdint.h>
2019-09-21 07:19:20 +00:00
//#include <stdlib.h>
//#include <string.h>
2019-09-21 01:48:48 +00:00
//#include "../../native/GoGlue.h"
import "C"
2019-09-21 07:19:20 +00:00
// Network status states
2019-09-21 01:48:48 +00:00
const (
2019-09-21 07:19:20 +00:00
NetworkStatusRequestConfiguration int = C.ZT_NETWORK_STATUS_REQUESTING_CONFIGURATION
NetworkStatusOK int = C.ZT_NETWORK_STATUS_OK
NetworkStatusAccessDenied int = C.ZT_NETWORK_STATUS_ACCESS_DENIED
NetworkStatusNotFound int = C.ZT_NETWORK_STATUS_NOT_FOUND
NetworkStatusPortError int = C.ZT_NETWORK_STATUS_PORT_ERROR
NetworkStatusClientTooOld int = C.ZT_NETWORK_STATUS_CLIENT_TOO_OLD
2019-09-21 01:48:48 +00:00
)
//////////////////////////////////////////////////////////////////////////////
2019-09-21 19:54:45 +00:00
// Node represents an instance of the ZeroTier core node and related C++ I/O code
2019-09-21 01:48:48 +00:00
type Node struct {
2019-09-21 07:19:20 +00:00
path string
2019-09-21 02:51:57 +00:00
networks map[uint64]*Network
networksLock sync.RWMutex
2019-09-21 01:48:48 +00:00
2019-09-21 07:19:20 +00:00
gn *C.ZT_GoNode
zn *C.ZT_Node
2019-09-21 01:48:48 +00:00
online uint32
running uint32
}
// NewNode creates and initializes a new instance of the ZeroTier node service
2019-09-21 07:19:20 +00:00
func NewNode(path string) (*Node, error) {
2019-09-21 18:56:31 +00:00
os.MkdirAll(path, 0755)
if _, err := os.Stat(path); err != nil {
return nil, err
}
2019-09-21 01:48:48 +00:00
n := new(Node)
2019-09-21 07:19:20 +00:00
n.path = path
2019-09-21 02:51:57 +00:00
n.networks = make(map[uint64]*Network)
2019-09-21 01:48:48 +00:00
2019-09-21 07:19:20 +00:00
cpath := C.CString(path)
n.gn = C.ZT_GoNode_new(cpath)
C.free(unsafe.Pointer(cpath))
if n.gn == nil {
2019-09-21 18:56:31 +00:00
return nil, ErrNodeInitFailed
2019-09-21 07:19:20 +00:00
}
n.zn = (*C.ZT_Node)(C.ZT_GoNode_getNode(n.gn))
2019-09-21 01:48:48 +00:00
gnRawAddr := uintptr(unsafe.Pointer(n.gn))
nodesByUserPtrLock.Lock()
nodesByUserPtr[gnRawAddr] = n
nodesByUserPtrLock.Unlock()
2019-09-21 07:19:20 +00:00
n.online = 0
2019-09-21 01:48:48 +00:00
n.running = 1
2019-09-21 07:19:20 +00:00
return n, nil
2019-09-21 01:48:48 +00:00
}
// Close closes this Node and frees its underlying C++ Node structures
func (n *Node) Close() {
if atomic.SwapUint32(&n.running, 0) != 0 {
C.ZT_GoNode_delete(n.gn)
nodesByUserPtrLock.Lock()
delete(nodesByUserPtr, uintptr(unsafe.Pointer(n.gn)))
nodesByUserPtrLock.Unlock()
}
}
// Join joins a network
// 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) {
2019-09-21 07:19:20 +00:00
n.networksLock.RLock()
if nw, have := n.networks[nwid]; have {
return nw, nil
}
n.networksLock.RUnlock()
if tap != nil {
2019-09-21 18:56:31 +00:00
return nil, errors.New("non-native taps not implemented yet")
2019-09-21 07:19:20 +00:00
}
ntap := C.ZT_GoNode_join(n.gn, C.uint64_t(nwid))
if ntap == nil {
2019-09-21 18:56:31 +00:00
return nil, ErrTapInitFailed
2019-09-21 07:19:20 +00:00
}
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
func (n *Node) Leave(nwid uint64) error {
2019-09-21 18:56:31 +00:00
C.ZT_GoNode_leave(n.gn, C.uint64_t(nwid))
n.networksLock.Lock()
delete(n.networks, nwid)
n.networksLock.Unlock()
return nil
}
//////////////////////////////////////////////////////////////////////////////
2019-09-21 01:48:48 +00:00
func (n *Node) pathCheck(ztAddress uint64, af int, ip net.IP, port int) bool {
return true
}
func (n *Node) pathLookup(ztAddress uint64) (net.IP, int) {
return nil, 0
}
2019-09-21 07:19:20 +00:00
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")
2019-09-21 18:56:31 +00:00
os.Mkdir(fp, 0700)
2019-09-21 07:19:20 +00:00
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
}
2019-09-21 01:48:48 +00:00
func (n *Node) stateObjectPut(objType int, id [2]uint64, data []byte) {
2019-09-21 18:56:31 +00:00
go func() {
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
}
2019-09-21 07:19:20 +00:00
}
2019-09-21 18:56:31 +00:00
}()
2019-09-21 01:48:48 +00:00
}
func (n *Node) stateObjectDelete(objType int, id [2]uint64) {
2019-09-21 18:56:31 +00:00
go func() {
fp, _ := n.makeStateObjectPath(objType, id)
if len(fp) > 0 {
os.Remove(fp)
}
}()
2019-09-21 01:48:48 +00:00
}
func (n *Node) stateObjectGet(objType int, id [2]uint64) ([]byte, bool) {
2019-09-21 07:19:20 +00:00
fp, _ := n.makeStateObjectPath(objType, id)
if len(fp) > 0 {
fd, err := ioutil.ReadFile(fp)
if err != nil {
return nil, false
}
return fd, true
}
2019-09-21 01:48:48 +00:00
return nil, false
}
func (n *Node) handleTrace(traceMessage string) {
}
func (n *Node) handleUserMessage(originAddress, messageTypeID uint64, data []byte) {
}
func (n *Node) handleRemoteTrace(originAddress uint64, dictData []byte) {
}
2019-09-21 07:19:20 +00:00
func (n *Node) handleNetworkConfigUpdate(nwid uint64, op int, config *C.ZT_VirtualNetworkConfig) int {
2019-09-21 01:48:48 +00:00
return 0
}