node-callbacks.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  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. // These are exported callbacks that are called from the C++ code in GoGlue.cpp
  15. //#cgo CFLAGS: -O3
  16. //#define ZT_CGO 1
  17. //#include <stdint.h>
  18. //#include <stdlib.h>
  19. //#include <string.h>
  20. //#include "../../native/GoGlue.h"
  21. import "C"
  22. import (
  23. "net"
  24. "sync"
  25. "sync/atomic"
  26. "unsafe"
  27. )
  28. const (
  29. afInet int = C.AF_INET
  30. afInet6 int = C.AF_INET6
  31. networkStatusRequestingConfiguration = C.ZT_NETWORK_STATUS_REQUESTING_CONFIGURATION
  32. networkStatusOK = C.ZT_NETWORK_STATUS_OK
  33. networkStatusAccessDenied = C.ZT_NETWORK_STATUS_ACCESS_DENIED
  34. networkStatusNotFound = C.ZT_NETWORK_STATUS_NOT_FOUND
  35. networkStatusPortError = C.ZT_NETWORK_STATUS_PORT_ERROR
  36. networkStatusClientTooOld = C.ZT_NETWORK_STATUS_CLIENT_TOO_OLD
  37. )
  38. var (
  39. nodesByUserPtr map[uintptr]*Node
  40. nodesByUserPtrLock sync.RWMutex
  41. )
  42. //export goPathCheckFunc
  43. func goPathCheckFunc(gn unsafe.Pointer, ztAddress C.uint64_t, af C.int, ip unsafe.Pointer, port C.int) C.int {
  44. nodesByUserPtrLock.RLock()
  45. node := nodesByUserPtr[uintptr(gn)]
  46. nodesByUserPtrLock.RUnlock()
  47. if node != nil && node.pathCheck(uint64(ztAddress), int(af), nil, int(port)) {
  48. return 1
  49. }
  50. return 0
  51. }
  52. //export goPathLookupFunc
  53. func goPathLookupFunc(gn unsafe.Pointer, ztAddress C.uint64_t, desiredAddressFamily int, familyP, ipP, portP unsafe.Pointer) C.int {
  54. nodesByUserPtrLock.RLock()
  55. node := nodesByUserPtr[uintptr(gn)]
  56. nodesByUserPtrLock.RUnlock()
  57. if node == nil {
  58. return 0
  59. }
  60. ip, port := node.pathLookup(uint64(ztAddress))
  61. ip4 := ip.To4()
  62. if len(ip4) == 4 {
  63. *((*C.int)(familyP)) = C.int(afInet)
  64. copy((*[4]byte)(ipP)[:], ip4)
  65. *((*C.int)(portP)) = C.int(port)
  66. } else if len(ip) == 16 {
  67. *((*C.int)(familyP)) = C.int(afInet6)
  68. copy((*[16]byte)(ipP)[:], ip)
  69. *((*C.int)(portP)) = C.int(port)
  70. }
  71. return 0
  72. }
  73. //export goStateObjectPutFunc
  74. func goStateObjectPutFunc(gn unsafe.Pointer, objType C.int, id, data unsafe.Pointer, len C.int) {
  75. nodesByUserPtrLock.RLock()
  76. node := nodesByUserPtr[uintptr(gn)]
  77. nodesByUserPtrLock.RUnlock()
  78. if node == nil {
  79. return
  80. }
  81. if len < 0 {
  82. node.stateObjectDelete(int(objType), *((*[2]uint64)(id)))
  83. } else {
  84. node.stateObjectPut(int(objType), *((*[2]uint64)(id)), C.GoBytes(data, len))
  85. }
  86. }
  87. //export goStateObjectGetFunc
  88. func goStateObjectGetFunc(gn unsafe.Pointer, objType C.int, id, data unsafe.Pointer, bufSize C.uint) C.int {
  89. nodesByUserPtrLock.RLock()
  90. node := nodesByUserPtr[uintptr(gn)]
  91. nodesByUserPtrLock.RUnlock()
  92. if node == nil {
  93. return -1
  94. }
  95. tmp, found := node.stateObjectGet(int(objType), *((*[2]uint64)(id)))
  96. if found && len(tmp) < int(bufSize) {
  97. if len(tmp) > 0 {
  98. C.memcpy(data, unsafe.Pointer(&(tmp[0])), C.ulong(len(tmp)))
  99. }
  100. return C.int(len(tmp))
  101. }
  102. return -1
  103. }
  104. //export goDNSResolverFunc
  105. func goDNSResolverFunc(gn unsafe.Pointer, dnsRecordTypes unsafe.Pointer, numDNSRecordTypes C.int, name unsafe.Pointer, requestID C.uintptr_t) {
  106. nodesByUserPtrLock.RLock()
  107. node := nodesByUserPtr[uintptr(gn)]
  108. nodesByUserPtrLock.RUnlock()
  109. if node == nil {
  110. return
  111. }
  112. recordTypes := C.GoBytes(dnsRecordTypes, numDNSRecordTypes)
  113. recordName := C.GoString((*C.char)(name))
  114. go func() {
  115. recordNameCStrCopy := C.CString(recordName)
  116. for _, rt := range recordTypes {
  117. switch rt {
  118. case C.ZT_DNS_RECORD_TXT:
  119. recs, _ := net.LookupTXT(recordName)
  120. for _, rec := range recs {
  121. if len(rec) > 0 {
  122. rnCS := C.CString(rec)
  123. C.ZT_Node_processDNSResult(unsafe.Pointer(node.zn), nil, requestID, recordNameCStrCopy, C.ZT_DNS_RECORD_TXT, unsafe.Pointer(rnCS), C.uint(len(rec)), 0)
  124. C.free(unsafe.Pointer(rnCS))
  125. }
  126. }
  127. }
  128. }
  129. C.ZT_Node_processDNSResult(unsafe.Pointer(node.zn), nil, requestID, recordNameCStrCopy, C.ZT_DNS_RECORD__END_OF_RESULTS, nil, 0, 0)
  130. C.free(unsafe.Pointer(recordNameCStrCopy))
  131. }()
  132. }
  133. //export goVirtualNetworkConfigFunc
  134. func goVirtualNetworkConfigFunc(gn, tapP unsafe.Pointer, nwid C.uint64_t, op C.int, conf unsafe.Pointer) C.int {
  135. nodesByUserPtrLock.RLock()
  136. node := nodesByUserPtr[uintptr(gn)]
  137. nodesByUserPtrLock.RUnlock()
  138. if node == nil {
  139. return 255
  140. }
  141. return C.int(node.handleNetworkConfigUpdate(int(op), (*C.ZT_VirtualNetworkConfig)(conf)))
  142. }
  143. //export goZtEvent
  144. func goZtEvent(gn unsafe.Pointer, eventType C.int, data unsafe.Pointer) {
  145. nodesByUserPtrLock.RLock()
  146. node := nodesByUserPtr[uintptr(gn)]
  147. nodesByUserPtrLock.RUnlock()
  148. if node == nil {
  149. return
  150. }
  151. switch eventType {
  152. case C.ZT_EVENT_OFFLINE:
  153. atomic.StoreUint32(&node.online, 0)
  154. case C.ZT_EVENT_ONLINE:
  155. atomic.StoreUint32(&node.online, 1)
  156. case C.ZT_EVENT_TRACE:
  157. node.handleTrace(C.GoString((*C.char)(data)))
  158. case C.ZT_EVENT_USER_MESSAGE:
  159. um := (*C.ZT_UserMessage)(data)
  160. node.handleUserMessage(uint64(um.origin), uint64(um.typeId), C.GoBytes(um.data, C.int(um.length)))
  161. case C.ZT_EVENT_REMOTE_TRACE:
  162. rt := (*C.ZT_RemoteTrace)(data)
  163. node.handleRemoteTrace(uint64(rt.origin), C.GoBytes(unsafe.Pointer(rt.data), C.int(rt.len)))
  164. }
  165. }
  166. func handleTapMulticastGroupChange(gn unsafe.Pointer, nwid, mac C.uint64_t, adi C.uint32_t, added bool) {
  167. nodesByUserPtrLock.RLock()
  168. node := nodesByUserPtr[uintptr(gn)]
  169. nodesByUserPtrLock.RUnlock()
  170. if node == nil {
  171. return
  172. }
  173. node.networksLock.RLock()
  174. network := node.networks[uint64(nwid)]
  175. node.networksLock.RUnlock()
  176. network.tapLock.Lock()
  177. tap, _ := network.tap.(*nativeTap)
  178. network.tapLock.Unlock()
  179. if tap != nil {
  180. mg := &MulticastGroup{MAC: MAC(mac), ADI: uint32(adi)}
  181. tap.multicastGroupHandlersLock.Lock()
  182. defer tap.multicastGroupHandlersLock.Unlock()
  183. for _, h := range tap.multicastGroupHandlers {
  184. h(added, mg)
  185. }
  186. }
  187. }
  188. //export goHandleTapAddedMulticastGroup
  189. func goHandleTapAddedMulticastGroup(gn, tapP unsafe.Pointer, nwid, mac C.uint64_t, adi C.uint32_t) {
  190. handleTapMulticastGroupChange(gn, nwid, mac, adi, true)
  191. }
  192. //export goHandleTapRemovedMulticastGroup
  193. func goHandleTapRemovedMulticastGroup(gn, tapP unsafe.Pointer, nwid, mac C.uint64_t, adi C.uint32_t) {
  194. handleTapMulticastGroupChange(gn, nwid, mac, adi, false)
  195. }