node-callbacks.go 6.2 KB

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