node.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*
  2. * Copyright (c)2019 ZeroTier, Inc.
  3. *
  4. * Use of this software is governed by the Business Source License included
  5. * in the LICENSE.TXT file in the project's root directory.
  6. *
  7. * Change Date: 2023-01-01
  8. *
  9. * On the date above, in accordance with the Business Source License, use
  10. * of this software will be governed by version 2.0 of the Apache License.
  11. */
  12. /****/
  13. package zerotier
  14. import (
  15. "errors"
  16. "fmt"
  17. "io/ioutil"
  18. "net"
  19. "os"
  20. "path"
  21. "sync"
  22. "sync/atomic"
  23. "time"
  24. "unsafe"
  25. acl "github.com/hectane/go-acl"
  26. )
  27. //#cgo CFLAGS: -O3
  28. //#cgo LDFLAGS: ${SRCDIR}/../../../build/node/libzt_core.a ${SRCDIR}/../../../build/osdep/libzt_osdep.a ${SRCDIR}/../../../build/go/native/libzt_go_native.a -lc++ -lpthread
  29. //#define ZT_CGO 1
  30. //#include <stdint.h>
  31. //#include <stdlib.h>
  32. //#include <string.h>
  33. //#include "../../native/GoGlue.h"
  34. import "C"
  35. // Network status states
  36. const (
  37. NetworkStatusRequestConfiguration int = C.ZT_NETWORK_STATUS_REQUESTING_CONFIGURATION
  38. NetworkStatusOK int = C.ZT_NETWORK_STATUS_OK
  39. NetworkStatusAccessDenied int = C.ZT_NETWORK_STATUS_ACCESS_DENIED
  40. NetworkStatusNotFound int = C.ZT_NETWORK_STATUS_NOT_FOUND
  41. NetworkStatusPortError int = C.ZT_NETWORK_STATUS_PORT_ERROR
  42. NetworkStatusClientTooOld int = C.ZT_NETWORK_STATUS_CLIENT_TOO_OLD
  43. )
  44. //////////////////////////////////////////////////////////////////////////////
  45. // Node is an instance of a ZeroTier node
  46. type Node struct {
  47. path string
  48. networks map[uint64]*Network
  49. networksLock sync.RWMutex
  50. gn *C.ZT_GoNode
  51. zn *C.ZT_Node
  52. online uint32
  53. running uint32
  54. }
  55. // NewNode creates and initializes a new instance of the ZeroTier node service
  56. func NewNode(path string) (*Node, error) {
  57. n := new(Node)
  58. n.path = path
  59. n.networks = make(map[uint64]*Network)
  60. cpath := C.CString(path)
  61. n.gn = C.ZT_GoNode_new(cpath)
  62. C.free(unsafe.Pointer(cpath))
  63. if n.gn == nil {
  64. return nil, errors.New("unable to create new Node instance")
  65. }
  66. n.zn = (*C.ZT_Node)(C.ZT_GoNode_getNode(n.gn))
  67. gnRawAddr := uintptr(unsafe.Pointer(n.gn))
  68. nodesByUserPtrLock.Lock()
  69. nodesByUserPtr[gnRawAddr] = n
  70. nodesByUserPtrLock.Unlock()
  71. n.online = 0
  72. n.running = 1
  73. return n, nil
  74. }
  75. // Close closes this Node and frees its underlying C++ Node structures
  76. func (n *Node) Close() {
  77. if atomic.SwapUint32(&n.running, 0) != 0 {
  78. C.ZT_GoNode_delete(n.gn)
  79. nodesByUserPtrLock.Lock()
  80. delete(nodesByUserPtr, uintptr(unsafe.Pointer(n.gn)))
  81. nodesByUserPtrLock.Unlock()
  82. }
  83. }
  84. // Join joins a network
  85. // If tap is nil, the default system tap for this OS/platform is used (if available).
  86. func (n *Node) Join(nwid uint64, tap Tap) (*Network, error) {
  87. n.networksLock.RLock()
  88. if nw, have := n.networks[nwid]; have {
  89. return nw, nil
  90. }
  91. n.networksLock.RUnlock()
  92. if tap != nil {
  93. return nil, errors.New("not implemented yet")
  94. }
  95. ntap := C.ZT_GoNode_join(n.gn, C.uint64_t(nwid))
  96. if ntap == nil {
  97. return nil, errors.New("unable to initialize native tap (check device driver or permissions)")
  98. }
  99. nw := &Network{
  100. id: NetworkID(nwid),
  101. config: NetworkConfig{
  102. ID: NetworkID(nwid),
  103. Status: NetworkStatusRequestConfiguration,
  104. LastUpdated: time.Now(),
  105. Enabled: true,
  106. },
  107. tap: &nativeTap{tap: unsafe.Pointer(ntap), enabled: 1},
  108. }
  109. n.networksLock.Lock()
  110. n.networks[nwid] = nw
  111. n.networksLock.Unlock()
  112. return nw, nil
  113. }
  114. // Leave leaves a network
  115. func (n *Node) Leave(nwid uint64) error {
  116. return nil
  117. }
  118. //////////////////////////////////////////////////////////////////////////////
  119. func (n *Node) pathCheck(ztAddress uint64, af int, ip net.IP, port int) bool {
  120. return true
  121. }
  122. func (n *Node) pathLookup(ztAddress uint64) (net.IP, int) {
  123. return nil, 0
  124. }
  125. func (n *Node) makeStateObjectPath(objType int, id [2]uint64) (string, bool) {
  126. var fp string
  127. secret := false
  128. switch objType {
  129. case C.ZT_STATE_OBJECT_IDENTITY_PUBLIC:
  130. fp = path.Join(n.path, "identity.public")
  131. case C.ZT_STATE_OBJECT_IDENTITY_SECRET:
  132. fp = path.Join(n.path, "identity.secret")
  133. secret = true
  134. case C.ZT_STATE_OBJECT_PEER:
  135. fp = path.Join(n.path, "peers.d")
  136. os.Mkdir(fp, 0755)
  137. fp = path.Join(fp, fmt.Sprintf("%.10x.peer", id[0]))
  138. secret = true
  139. case C.ZT_STATE_OBJECT_NETWORK_CONFIG:
  140. fp = path.Join(n.path, "networks.d")
  141. os.Mkdir(fp, 0755)
  142. fp = path.Join(fp, fmt.Sprintf("%.16x.conf", id[0]))
  143. case C.ZT_STATE_OBJECT_ROOT_LIST:
  144. fp = path.Join(n.path, "roots")
  145. }
  146. return fp, secret
  147. }
  148. func (n *Node) stateObjectPut(objType int, id [2]uint64, data []byte) {
  149. fp, secret := n.makeStateObjectPath(objType, id)
  150. if len(fp) > 0 {
  151. fileMode := os.FileMode(0644)
  152. if secret {
  153. fileMode = os.FileMode(0600)
  154. }
  155. ioutil.WriteFile(fp, data, fileMode)
  156. if secret {
  157. acl.Chmod(fp, 0600) // this emulates Unix chmod on Windows and uses os.Chmod on Unix-type systems
  158. }
  159. }
  160. }
  161. func (n *Node) stateObjectDelete(objType int, id [2]uint64) {
  162. fp, _ := n.makeStateObjectPath(objType, id)
  163. if len(fp) > 0 {
  164. os.Remove(fp)
  165. }
  166. }
  167. func (n *Node) stateObjectGet(objType int, id [2]uint64) ([]byte, bool) {
  168. fp, _ := n.makeStateObjectPath(objType, id)
  169. if len(fp) > 0 {
  170. fd, err := ioutil.ReadFile(fp)
  171. if err != nil {
  172. return nil, false
  173. }
  174. return fd, true
  175. }
  176. return nil, false
  177. }
  178. func (n *Node) handleTrace(traceMessage string) {
  179. }
  180. func (n *Node) handleUserMessage(originAddress, messageTypeID uint64, data []byte) {
  181. }
  182. func (n *Node) handleRemoteTrace(originAddress uint64, dictData []byte) {
  183. }
  184. func (n *Node) handleNetworkConfigUpdate(nwid uint64, op int, config *C.ZT_VirtualNetworkConfig) int {
  185. return 0
  186. }