node.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  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. //#cgo LDFLAGS: ${SRCDIR}/../../../build/node/libzt_core.a ${SRCDIR}/../../../build/osdep/libzt_osdep.a ${SRCDIR}/../../../build/go/native/libzt_go_native.a -lc++ -lpthread
  16. //#define ZT_CGO 1
  17. //#include "../../native/GoGlue.h"
  18. import "C"
  19. import (
  20. "encoding/binary"
  21. "errors"
  22. "fmt"
  23. "io/ioutil"
  24. "net"
  25. "os"
  26. "path"
  27. "sync"
  28. "sync/atomic"
  29. "unsafe"
  30. acl "github.com/hectane/go-acl"
  31. )
  32. // Network status states
  33. const (
  34. NetworkStatusRequestConfiguration int = C.ZT_NETWORK_STATUS_REQUESTING_CONFIGURATION
  35. NetworkStatusOK int = C.ZT_NETWORK_STATUS_OK
  36. NetworkStatusAccessDenied int = C.ZT_NETWORK_STATUS_ACCESS_DENIED
  37. NetworkStatusNotFound int = C.ZT_NETWORK_STATUS_NOT_FOUND
  38. NetworkStatusPortError int = C.ZT_NETWORK_STATUS_PORT_ERROR
  39. NetworkStatusClientTooOld int = C.ZT_NETWORK_STATUS_CLIENT_TOO_OLD
  40. NetworkTypePrivate int = C.ZT_NETWORK_TYPE_PRIVATE
  41. NetworkTypePublic int = C.ZT_NETWORK_TYPE_PUBLIC
  42. // CoreVersionMajor is the major version of the ZeroTier core
  43. CoreVersionMajor int = C.ZEROTIER_ONE_VERSION_MAJOR
  44. // CoreVersionMinor is the minor version of the ZeroTier core
  45. CoreVersionMinor int = C.ZEROTIER_ONE_VERSION_MINOR
  46. // CoreVersionRevision is the revision of the ZeroTier core
  47. CoreVersionRevision int = C.ZEROTIER_ONE_VERSION_REVISION
  48. // CoreVersionBuild is the build version of the ZeroTier core
  49. CoreVersionBuild int = C.ZEROTIER_ONE_VERSION_BUILD
  50. afInet int = C.AF_INET
  51. afInet6 int = C.AF_INET6
  52. )
  53. var (
  54. nodesByUserPtr map[uintptr]*Node
  55. nodesByUserPtrLock sync.RWMutex
  56. )
  57. //////////////////////////////////////////////////////////////////////////////
  58. // Node represents an instance of the ZeroTier core node and related C++ I/O code
  59. type Node struct {
  60. path string
  61. networks map[uint64]*Network
  62. networksLock sync.RWMutex
  63. gn *C.ZT_GoNode
  64. zn *C.ZT_Node
  65. online uint32
  66. running uint32
  67. }
  68. // NewNode creates and initializes a new instance of the ZeroTier node service
  69. func NewNode(path string) (*Node, error) {
  70. os.MkdirAll(path, 0755)
  71. if _, err := os.Stat(path); err != nil {
  72. return nil, err
  73. }
  74. n := new(Node)
  75. n.path = path
  76. n.networks = make(map[uint64]*Network)
  77. cpath := C.CString(path)
  78. n.gn = C.ZT_GoNode_new(cpath)
  79. C.free(unsafe.Pointer(cpath))
  80. if n.gn == nil {
  81. return nil, ErrNodeInitFailed
  82. }
  83. n.zn = (*C.ZT_Node)(C.ZT_GoNode_getNode(n.gn))
  84. gnRawAddr := uintptr(unsafe.Pointer(n.gn))
  85. nodesByUserPtrLock.Lock()
  86. nodesByUserPtr[gnRawAddr] = n
  87. nodesByUserPtrLock.Unlock()
  88. n.online = 0
  89. n.running = 1
  90. return n, nil
  91. }
  92. // Close closes this Node and frees its underlying C++ Node structures
  93. func (n *Node) Close() {
  94. if atomic.SwapUint32(&n.running, 0) != 0 {
  95. C.ZT_GoNode_delete(n.gn)
  96. nodesByUserPtrLock.Lock()
  97. delete(nodesByUserPtr, uintptr(unsafe.Pointer(n.gn)))
  98. nodesByUserPtrLock.Unlock()
  99. }
  100. }
  101. // Join joins a network
  102. // If tap is nil, the default system tap for this OS/platform is used (if available).
  103. func (n *Node) Join(nwid uint64, tap Tap) (*Network, error) {
  104. n.networksLock.RLock()
  105. if nw, have := n.networks[nwid]; have {
  106. return nw, nil
  107. }
  108. n.networksLock.RUnlock()
  109. if tap != nil {
  110. return nil, errors.New("non-native taps not implemented yet")
  111. }
  112. ntap := C.ZT_GoNode_join(n.gn, C.uint64_t(nwid))
  113. if ntap == nil {
  114. return nil, ErrTapInitFailed
  115. }
  116. nw, err := NewNetwork(NetworkID(nwid), &nativeTap{tap: unsafe.Pointer(ntap), enabled: 1})
  117. if err != nil {
  118. C.ZT_GoNode_leave(n.gn, C.uint64_t(nwid))
  119. return nil, err
  120. }
  121. n.networksLock.Lock()
  122. n.networks[nwid] = nw
  123. n.networksLock.Unlock()
  124. return nw, nil
  125. }
  126. // Leave leaves a network
  127. func (n *Node) Leave(nwid uint64) error {
  128. C.ZT_GoNode_leave(n.gn, C.uint64_t(nwid))
  129. n.networksLock.Lock()
  130. delete(n.networks, nwid)
  131. n.networksLock.Unlock()
  132. return nil
  133. }
  134. //////////////////////////////////////////////////////////////////////////////
  135. func (n *Node) pathCheck(ztAddress uint64, af int, ip net.IP, port int) bool {
  136. return true
  137. }
  138. func (n *Node) pathLookup(ztAddress uint64) (net.IP, int) {
  139. return nil, 0
  140. }
  141. func (n *Node) makeStateObjectPath(objType int, id [2]uint64) (string, bool) {
  142. var fp string
  143. secret := false
  144. switch objType {
  145. case C.ZT_STATE_OBJECT_IDENTITY_PUBLIC:
  146. fp = path.Join(n.path, "identity.public")
  147. case C.ZT_STATE_OBJECT_IDENTITY_SECRET:
  148. fp = path.Join(n.path, "identity.secret")
  149. secret = true
  150. case C.ZT_STATE_OBJECT_PEER:
  151. fp = path.Join(n.path, "peers.d")
  152. os.Mkdir(fp, 0700)
  153. fp = path.Join(fp, fmt.Sprintf("%.10x.peer", id[0]))
  154. secret = true
  155. case C.ZT_STATE_OBJECT_NETWORK_CONFIG:
  156. fp = path.Join(n.path, "networks.d")
  157. os.Mkdir(fp, 0755)
  158. fp = path.Join(fp, fmt.Sprintf("%.16x.conf", id[0]))
  159. case C.ZT_STATE_OBJECT_ROOT_LIST:
  160. fp = path.Join(n.path, "roots")
  161. }
  162. return fp, secret
  163. }
  164. func (n *Node) stateObjectPut(objType int, id [2]uint64, data []byte) {
  165. go func() {
  166. fp, secret := n.makeStateObjectPath(objType, id)
  167. if len(fp) > 0 {
  168. fileMode := os.FileMode(0644)
  169. if secret {
  170. fileMode = os.FileMode(0600)
  171. }
  172. ioutil.WriteFile(fp, data, fileMode)
  173. if secret {
  174. acl.Chmod(fp, 0600) // this emulates Unix chmod on Windows and uses os.Chmod on Unix-type systems
  175. }
  176. }
  177. }()
  178. }
  179. func (n *Node) stateObjectDelete(objType int, id [2]uint64) {
  180. go func() {
  181. fp, _ := n.makeStateObjectPath(objType, id)
  182. if len(fp) > 0 {
  183. os.Remove(fp)
  184. }
  185. }()
  186. }
  187. func (n *Node) stateObjectGet(objType int, id [2]uint64) ([]byte, bool) {
  188. fp, _ := n.makeStateObjectPath(objType, id)
  189. if len(fp) > 0 {
  190. fd, err := ioutil.ReadFile(fp)
  191. if err != nil {
  192. return nil, false
  193. }
  194. return fd, true
  195. }
  196. return nil, false
  197. }
  198. func (n *Node) handleTrace(traceMessage string) {
  199. }
  200. func (n *Node) handleUserMessage(originAddress, messageTypeID uint64, data []byte) {
  201. }
  202. func (n *Node) handleRemoteTrace(originAddress uint64, dictData []byte) {
  203. }
  204. //////////////////////////////////////////////////////////////////////////////
  205. //export goPathCheckFunc
  206. func goPathCheckFunc(gn unsafe.Pointer, ztAddress C.uint64_t, af C.int, ip unsafe.Pointer, port C.int) C.int {
  207. nodesByUserPtrLock.RLock()
  208. node := nodesByUserPtr[uintptr(gn)]
  209. nodesByUserPtrLock.RUnlock()
  210. if node != nil && node.pathCheck(uint64(ztAddress), int(af), nil, int(port)) {
  211. return 1
  212. }
  213. return 0
  214. }
  215. //export goPathLookupFunc
  216. func goPathLookupFunc(gn unsafe.Pointer, ztAddress C.uint64_t, desiredAddressFamily int, familyP, ipP, portP unsafe.Pointer) C.int {
  217. nodesByUserPtrLock.RLock()
  218. node := nodesByUserPtr[uintptr(gn)]
  219. nodesByUserPtrLock.RUnlock()
  220. if node == nil {
  221. return 0
  222. }
  223. ip, port := node.pathLookup(uint64(ztAddress))
  224. if len(ip) > 0 && port > 0 && port <= 65535 {
  225. ip4 := ip.To4()
  226. if len(ip4) == 4 {
  227. *((*C.int)(familyP)) = C.int(afInet)
  228. copy((*[4]byte)(ipP)[:], ip4)
  229. *((*C.int)(portP)) = C.int(port)
  230. return 1
  231. } else if len(ip) == 16 {
  232. *((*C.int)(familyP)) = C.int(afInet6)
  233. copy((*[16]byte)(ipP)[:], ip)
  234. *((*C.int)(portP)) = C.int(port)
  235. return 1
  236. }
  237. }
  238. return 0
  239. }
  240. //export goStateObjectPutFunc
  241. func goStateObjectPutFunc(gn unsafe.Pointer, objType C.int, id, data unsafe.Pointer, len C.int) {
  242. nodesByUserPtrLock.RLock()
  243. node := nodesByUserPtr[uintptr(gn)]
  244. nodesByUserPtrLock.RUnlock()
  245. if node == nil {
  246. return
  247. }
  248. if len < 0 {
  249. node.stateObjectDelete(int(objType), *((*[2]uint64)(id)))
  250. } else {
  251. node.stateObjectPut(int(objType), *((*[2]uint64)(id)), C.GoBytes(data, len))
  252. }
  253. }
  254. //export goStateObjectGetFunc
  255. func goStateObjectGetFunc(gn unsafe.Pointer, objType C.int, id, data unsafe.Pointer, bufSize C.uint) C.int {
  256. nodesByUserPtrLock.RLock()
  257. node := nodesByUserPtr[uintptr(gn)]
  258. nodesByUserPtrLock.RUnlock()
  259. if node == nil {
  260. return -1
  261. }
  262. tmp, found := node.stateObjectGet(int(objType), *((*[2]uint64)(id)))
  263. if found && len(tmp) < int(bufSize) {
  264. if len(tmp) > 0 {
  265. C.memcpy(data, unsafe.Pointer(&(tmp[0])), C.ulong(len(tmp)))
  266. }
  267. return C.int(len(tmp))
  268. }
  269. return -1
  270. }
  271. //export goDNSResolverFunc
  272. func goDNSResolverFunc(gn unsafe.Pointer, dnsRecordTypes unsafe.Pointer, numDNSRecordTypes C.int, name unsafe.Pointer, requestID C.uintptr_t) {
  273. nodesByUserPtrLock.RLock()
  274. node := nodesByUserPtr[uintptr(gn)]
  275. nodesByUserPtrLock.RUnlock()
  276. if node == nil {
  277. return
  278. }
  279. recordTypes := C.GoBytes(dnsRecordTypes, numDNSRecordTypes)
  280. recordName := C.GoString((*C.char)(name))
  281. go func() {
  282. recordNameCStrCopy := C.CString(recordName)
  283. for _, rt := range recordTypes {
  284. switch rt {
  285. case C.ZT_DNS_RECORD_TXT:
  286. recs, _ := net.LookupTXT(recordName)
  287. for _, rec := range recs {
  288. if len(rec) > 0 {
  289. rnCS := C.CString(rec)
  290. C.ZT_Node_processDNSResult(unsafe.Pointer(node.zn), nil, requestID, recordNameCStrCopy, C.ZT_DNS_RECORD_TXT, unsafe.Pointer(rnCS), C.uint(len(rec)), 0)
  291. C.free(unsafe.Pointer(rnCS))
  292. }
  293. }
  294. }
  295. }
  296. C.ZT_Node_processDNSResult(unsafe.Pointer(node.zn), nil, requestID, recordNameCStrCopy, C.ZT_DNS_RECORD__END_OF_RESULTS, nil, 0, 0)
  297. C.free(unsafe.Pointer(recordNameCStrCopy))
  298. }()
  299. }
  300. func sockaddrStorageToIPNet(ss *C.struct_sockaddr_storage) *net.IPNet {
  301. var a net.IPNet
  302. switch ss.ss_family {
  303. case afInet:
  304. sa4 := (*C.struct_sockaddr_in)(unsafe.Pointer(ss))
  305. var ip4 [4]byte
  306. copy(ip4[:], (*[4]byte)(unsafe.Pointer(&sa4.sin_addr))[:])
  307. a.IP = net.IP(ip4[:])
  308. a.Mask = net.CIDRMask(int(binary.BigEndian.Uint16(((*[2]byte)(unsafe.Pointer(&sa4.sin_port)))[:])), 32)
  309. return &a
  310. case afInet6:
  311. sa6 := (*C.struct_sockaddr_in6)(unsafe.Pointer(ss))
  312. var ip6 [16]byte
  313. copy(ip6[:], (*[16]byte)(unsafe.Pointer(&sa6.sin6_addr))[:])
  314. a.IP = net.IP(ip6[:])
  315. a.Mask = net.CIDRMask(int(binary.BigEndian.Uint16(((*[2]byte)(unsafe.Pointer(&sa6.sin6_port)))[:])), 128)
  316. return &a
  317. }
  318. return nil
  319. }
  320. //export goVirtualNetworkConfigFunc
  321. func goVirtualNetworkConfigFunc(gn, tapP unsafe.Pointer, nwid C.uint64_t, op C.int, conf unsafe.Pointer) {
  322. go func() {
  323. nodesByUserPtrLock.RLock()
  324. node := nodesByUserPtr[uintptr(gn)]
  325. nodesByUserPtrLock.RUnlock()
  326. if node == nil {
  327. return
  328. }
  329. node.networksLock.RLock()
  330. network := node.networks[uint64(nwid)]
  331. node.networksLock.RUnlock()
  332. if network != nil {
  333. ncc := (*C.ZT_VirtualNetworkConfig)(conf)
  334. if network.networkConfigRevision() > uint64(ncc.netconfRevision) {
  335. return
  336. }
  337. var nc NetworkConfig
  338. nc.ID = uint64(ncc.nwid)
  339. nc.MAC = MAC(ncc.mac)
  340. nc.Name = C.GoString(ncc.name)
  341. nc.Status = int(ncc.status)
  342. nc.Type = int(ncc._type)
  343. nc.MTU = int(ncc.mtu)
  344. nc.Bridge = (ncc.bridge != 0)
  345. nc.BroadcastEnabled = (ncc.broadcastEnabled != 0)
  346. nc.NetconfRevision = uint64(ncc.netconfRevision)
  347. for i := 0; i < int(ncc.assignedAddressCount); i++ {
  348. a := sockaddrStorageToIPNet(&ncc.assignedAddresses[i])
  349. if a != nil {
  350. nc.AssignedAddresses = append(nc.AssignedAddresses, *a)
  351. }
  352. }
  353. for i := 0; i < int(ncc.routeCount); i++ {
  354. tgt := sockaddrStorageToIPNet(&ncc.routes[i].target)
  355. viaN := sockaddrStorageToIPNet(&ncc.routes[i].via)
  356. var via net.IP
  357. if viaN != nil {
  358. via = viaN.IP
  359. }
  360. if tgt != nil {
  361. nc.Routes = append(nc.Routes, Route{
  362. Target: *tgt,
  363. Via: via,
  364. Flags: uint16(ncc.routes[i].flags),
  365. Metric: uint16(ncc.routes[i].metric),
  366. })
  367. }
  368. }
  369. network.updateConfig(&nc, nil)
  370. }
  371. }()
  372. }
  373. //export goZtEvent
  374. func goZtEvent(gn unsafe.Pointer, eventType C.int, data unsafe.Pointer) {
  375. go func() {
  376. nodesByUserPtrLock.RLock()
  377. node := nodesByUserPtr[uintptr(gn)]
  378. nodesByUserPtrLock.RUnlock()
  379. if node == nil {
  380. return
  381. }
  382. switch eventType {
  383. case C.ZT_EVENT_OFFLINE:
  384. atomic.StoreUint32(&node.online, 0)
  385. case C.ZT_EVENT_ONLINE:
  386. atomic.StoreUint32(&node.online, 1)
  387. case C.ZT_EVENT_TRACE:
  388. node.handleTrace(C.GoString((*C.char)(data)))
  389. case C.ZT_EVENT_USER_MESSAGE:
  390. um := (*C.ZT_UserMessage)(data)
  391. node.handleUserMessage(uint64(um.origin), uint64(um.typeId), C.GoBytes(um.data, C.int(um.length)))
  392. case C.ZT_EVENT_REMOTE_TRACE:
  393. rt := (*C.ZT_RemoteTrace)(data)
  394. node.handleRemoteTrace(uint64(rt.origin), C.GoBytes(unsafe.Pointer(rt.data), C.int(rt.len)))
  395. }
  396. }()
  397. }
  398. //////////////////////////////////////////////////////////////////////////////
  399. // nativeTap is a Tap implementation that wraps a native C++ interface to a system tun/tap device
  400. type nativeTap struct {
  401. tap unsafe.Pointer
  402. networkStatus uint32
  403. enabled uint32
  404. multicastGroupHandlers []func(bool, *MulticastGroup)
  405. multicastGroupHandlersLock sync.Mutex
  406. }
  407. // Type returns a human-readable description of this tap implementation
  408. func (t *nativeTap) Type() string {
  409. return "native"
  410. }
  411. // Error gets this tap device's error status
  412. func (t *nativeTap) Error() (int, string) {
  413. return 0, ""
  414. }
  415. // SetEnabled sets this tap's enabled state
  416. func (t *nativeTap) SetEnabled(enabled bool) {
  417. if enabled && atomic.SwapUint32(&t.enabled, 1) == 0 {
  418. C.ZT_GoTap_setEnabled(t.tap, 1)
  419. } else if !enabled && atomic.SwapUint32(&t.enabled, 0) == 1 {
  420. C.ZT_GoTap_setEnabled(t.tap, 0)
  421. }
  422. }
  423. // Enabled returns true if this tap is currently processing packets
  424. func (t *nativeTap) Enabled() bool {
  425. return atomic.LoadUint32(&t.enabled) != 0
  426. }
  427. // AddIP adds an IP address (with netmask) to this tap
  428. func (t *nativeTap) AddIP(ip *net.IPNet) error {
  429. bits, _ := ip.Mask.Size()
  430. if len(ip.IP) == 16 {
  431. if bits > 128 || bits < 0 {
  432. return ErrInvalidParameter
  433. }
  434. C.ZT_GoTap_addIp(t.tap, C.int(afInet6), unsafe.Pointer(&ip.IP[0]), C.int(bits))
  435. } else if len(ip.IP) == 4 {
  436. if bits > 32 || bits < 0 {
  437. return ErrInvalidParameter
  438. }
  439. C.ZT_GoTap_addIp(t.tap, C.int(afInet), unsafe.Pointer(&ip.IP[0]), C.int(bits))
  440. }
  441. return ErrInvalidParameter
  442. }
  443. // RemoveIP removes this IP address (with netmask) from this tap
  444. func (t *nativeTap) RemoveIP(ip *net.IPNet) error {
  445. bits, _ := ip.Mask.Size()
  446. if len(ip.IP) == 16 {
  447. if bits > 128 || bits < 0 {
  448. return ErrInvalidParameter
  449. }
  450. C.ZT_GoTap_removeIp(t.tap, C.int(afInet6), unsafe.Pointer(&ip.IP[0]), C.int(bits))
  451. return nil
  452. }
  453. if len(ip.IP) == 4 {
  454. if bits > 32 || bits < 0 {
  455. return ErrInvalidParameter
  456. }
  457. C.ZT_GoTap_removeIp(t.tap, C.int(afInet), unsafe.Pointer(&ip.IP[0]), C.int(bits))
  458. return nil
  459. }
  460. return ErrInvalidParameter
  461. }
  462. // IPs returns IPs currently assigned to this tap (including externally or system-assigned IPs)
  463. func (t *nativeTap) IPs() (ips []net.IPNet, err error) {
  464. defer func() {
  465. e := recover()
  466. if e != nil {
  467. err = fmt.Errorf("%v", e)
  468. }
  469. }()
  470. var ipbuf [16384]byte
  471. count := int(C.ZT_GoTap_ips(t.tap, unsafe.Pointer(&ipbuf[0]), 16384))
  472. ipptr := 0
  473. for i := 0; i < count; i++ {
  474. af := int(ipbuf[ipptr])
  475. ipptr++
  476. switch af {
  477. case afInet:
  478. var ip [4]byte
  479. for j := 0; j < 4; j++ {
  480. ip[j] = ipbuf[ipptr]
  481. ipptr++
  482. }
  483. bits := ipbuf[ipptr]
  484. ipptr++
  485. ips = append(ips, net.IPNet{IP: net.IP(ip[:]), Mask: net.CIDRMask(int(bits), 32)})
  486. case afInet6:
  487. var ip [16]byte
  488. for j := 0; j < 16; j++ {
  489. ip[j] = ipbuf[ipptr]
  490. ipptr++
  491. }
  492. bits := ipbuf[ipptr]
  493. ipptr++
  494. ips = append(ips, net.IPNet{IP: net.IP(ip[:]), Mask: net.CIDRMask(int(bits), 128)})
  495. }
  496. }
  497. return
  498. }
  499. // DeviceName gets this tap's OS-specific device name
  500. func (t *nativeTap) DeviceName() string {
  501. var dn [256]byte
  502. C.ZT_GoTap_deviceName(t.tap, (*C.char)(unsafe.Pointer(&dn[0])))
  503. for i, b := range dn {
  504. if b == 0 {
  505. return string(dn[0:i])
  506. }
  507. }
  508. return ""
  509. }
  510. // AddMulticastGroupChangeHandler adds a function to be called when the tap subscribes or unsubscribes to a multicast group.
  511. func (t *nativeTap) AddMulticastGroupChangeHandler(handler func(bool, *MulticastGroup)) {
  512. t.multicastGroupHandlersLock.Lock()
  513. t.multicastGroupHandlers = append(t.multicastGroupHandlers, handler)
  514. t.multicastGroupHandlersLock.Unlock()
  515. }
  516. // AddRoute adds or updates a managed route on this tap's interface
  517. func (t *nativeTap) AddRoute(r *Route) error {
  518. rc := 0
  519. if r != nil {
  520. if len(r.Target.IP) == 4 {
  521. mask, _ := r.Target.Mask.Size()
  522. if len(r.Via) == 4 {
  523. rc = int(C.ZT_GoTap_addRoute(t.tap, afInet, unsafe.Pointer(&r.Target.IP[0]), C.int(mask), afInet, unsafe.Pointer(&r.Via[0]), C.int(r.Metric)))
  524. } else {
  525. rc = int(C.ZT_GoTap_addRoute(t.tap, afInet, unsafe.Pointer(&r.Target.IP[0]), C.int(mask), 0, nil, C.int(r.Metric)))
  526. }
  527. } else if len(r.Target.IP) == 16 {
  528. mask, _ := r.Target.Mask.Size()
  529. if len(r.Via) == 4 {
  530. rc = int(C.ZT_GoTap_addRoute(t.tap, afInet6, unsafe.Pointer(&r.Target.IP[0]), C.int(mask), afInet6, unsafe.Pointer(&r.Via[0]), C.int(r.Metric)))
  531. } else {
  532. rc = int(C.ZT_GoTap_addRoute(t.tap, afInet6, unsafe.Pointer(&r.Target.IP[0]), C.int(mask), 0, nil, C.int(r.Metric)))
  533. }
  534. }
  535. }
  536. if rc != 0 {
  537. return fmt.Errorf("tap device error adding route: %d", rc)
  538. }
  539. return nil
  540. }
  541. // RemoveRoute removes a managed route on this tap's interface
  542. func (t *nativeTap) RemoveRoute(r *Route) error {
  543. rc := 0
  544. if r != nil {
  545. if len(r.Target.IP) == 4 {
  546. mask, _ := r.Target.Mask.Size()
  547. if len(r.Via) == 4 {
  548. rc = int(C.ZT_GoTap_removeRoute(t.tap, afInet, unsafe.Pointer(&r.Target.IP[0]), C.int(mask), afInet, unsafe.Pointer(&r.Via[0]), C.int(r.Metric)))
  549. } else {
  550. rc = int(C.ZT_GoTap_removeRoute(t.tap, afInet, unsafe.Pointer(&r.Target.IP[0]), C.int(mask), 0, nil, C.int(r.Metric)))
  551. }
  552. } else if len(r.Target.IP) == 16 {
  553. mask, _ := r.Target.Mask.Size()
  554. if len(r.Via) == 4 {
  555. rc = int(C.ZT_GoTap_removeRoute(t.tap, afInet6, unsafe.Pointer(&r.Target.IP[0]), C.int(mask), afInet6, unsafe.Pointer(&r.Via[0]), C.int(r.Metric)))
  556. } else {
  557. rc = int(C.ZT_GoTap_removeRoute(t.tap, afInet6, unsafe.Pointer(&r.Target.IP[0]), C.int(mask), 0, nil, C.int(r.Metric)))
  558. }
  559. }
  560. }
  561. if rc != 0 {
  562. return fmt.Errorf("tap device error removing route: %d", rc)
  563. }
  564. return nil
  565. }
  566. // SyncRoutes synchronizes managed routes
  567. func (t *nativeTap) SyncRoutes() error {
  568. C.ZT_GoTap_syncRoutes(t.tap)
  569. return nil
  570. }
  571. //////////////////////////////////////////////////////////////////////////////
  572. func handleTapMulticastGroupChange(gn unsafe.Pointer, nwid, mac C.uint64_t, adi C.uint32_t, added bool) {
  573. go func() {
  574. nodesByUserPtrLock.RLock()
  575. node := nodesByUserPtr[uintptr(gn)]
  576. nodesByUserPtrLock.RUnlock()
  577. if node == nil {
  578. return
  579. }
  580. node.networksLock.RLock()
  581. network := node.networks[uint64(nwid)]
  582. node.networksLock.RUnlock()
  583. if network != nil {
  584. tap, _ := network.tap.(*nativeTap)
  585. if tap != nil {
  586. mg := &MulticastGroup{MAC: MAC(mac), ADI: uint32(adi)}
  587. tap.multicastGroupHandlersLock.Lock()
  588. defer tap.multicastGroupHandlersLock.Unlock()
  589. for _, h := range tap.multicastGroupHandlers {
  590. h(added, mg)
  591. }
  592. }
  593. }
  594. }()
  595. }
  596. //export goHandleTapAddedMulticastGroup
  597. func goHandleTapAddedMulticastGroup(gn, tapP unsafe.Pointer, nwid, mac C.uint64_t, adi C.uint32_t) {
  598. handleTapMulticastGroupChange(gn, nwid, mac, adi, true)
  599. }
  600. //export goHandleTapRemovedMulticastGroup
  601. func goHandleTapRemovedMulticastGroup(gn, tapP unsafe.Pointer, nwid, mac C.uint64_t, adi C.uint32_t) {
  602. handleTapMulticastGroupChange(gn, nwid, mac, adi, false)
  603. }