GoGlue.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  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 vergnn 2.0 of the Apache License.
  11. */
  12. /****/
  13. #include "GoGlue.h"
  14. #include "../../node/Constants.hpp"
  15. #include "../../node/InetAddress.hpp"
  16. #include "../../node/Node.hpp"
  17. #include "../../node/Utils.hpp"
  18. #include "../../node/MAC.hpp"
  19. #include "../../node/Address.hpp"
  20. #include "../../osdep/OSUtils.hpp"
  21. #include "../../osdep/BlockingQueue.hpp"
  22. #include "../../osdep/EthernetTap.hpp"
  23. #include <string.h>
  24. #include <stdlib.h>
  25. #include <errno.h>
  26. #ifndef __WINDOWS__
  27. #include <errno.h>
  28. #include <signal.h>
  29. #include <unistd.h>
  30. #include <fcntl.h>
  31. #include <sys/time.h>
  32. #include <sys/types.h>
  33. #include <sys/select.h>
  34. #include <sys/socket.h>
  35. #include <sys/un.h>
  36. #include <arpa/inet.h>
  37. #include <netinet/in.h>
  38. #include <netinet/ip6.h>
  39. #include <netinet/tcp.h>
  40. #ifdef __BSD__
  41. #include <net/if.h>
  42. #endif
  43. #ifdef __LINUX__
  44. #ifndef IPV6_DONTFRAG
  45. #define IPV6_DONTFRAG 62
  46. #endif
  47. #endif
  48. #endif // !__WINDOWS__
  49. #include <thread>
  50. #include <mutex>
  51. #include <map>
  52. #include <vector>
  53. #include <array>
  54. #include <set>
  55. #include <memory>
  56. #ifdef __WINDOWS__
  57. #define SETSOCKOPT_FLAG_TYPE BOOL
  58. #define SETSOCKOPT_FLAG_TRUE TRUE
  59. #define SETSOCKOPT_FLAG_FALSE FALSE
  60. #else
  61. #define SETSOCKOPT_FLAG_TYPE int
  62. #define SETSOCKOPT_FLAG_TRUE 1
  63. #define SETSOCKOPT_FLAG_FALSE 0
  64. #endif
  65. #ifndef MSG_DONTWAIT
  66. #define MSG_DONTWAIT 0
  67. #endif
  68. using namespace ZeroTier;
  69. struct ZT_GoNodeThread
  70. {
  71. std::string ip;
  72. int port;
  73. int af;
  74. std::atomic_bool run;
  75. std::thread thr;
  76. };
  77. struct ZT_GoNode_Impl
  78. {
  79. Node *node;
  80. volatile int64_t nextBackgroundTaskDeadline;
  81. int (*goPathCheckFunc)(ZT_GoNode *,ZT_Node *,uint64_t ztAddress,const void *);
  82. int (*goPathLookupFunc)(ZT_GoNode *,ZT_Node *,int desiredAddressFamily,void *);
  83. int (*goStateObjectGetFunc)(ZT_GoNode *,ZT_Node *,int objType,const uint64_t id[2],void *buf,unsigned int bufSize);
  84. std::string path;
  85. std::atomic_bool run;
  86. std::map< ZT_SOCKET,ZT_GoNodeThread > threads;
  87. std::mutex threads_l;
  88. std::map< uint64_t,std::shared_ptr<EthernetTap> > taps;
  89. std::mutex taps_l;
  90. BlockingQueue<ZT_GoNodeEvent> eq;
  91. std::thread backgroundTaskThread;
  92. };
  93. //////////////////////////////////////////////////////////////////////////////
  94. static int ZT_GoNode_VirtualNetworkConfigFunction(
  95. ZT_Node *node,
  96. void *uptr,
  97. void *tptr,
  98. uint64_t nwid,
  99. void **nptr,
  100. enum ZT_VirtualNetworkConfigOperation op,
  101. const ZT_VirtualNetworkConfig *cfg)
  102. {
  103. ZT_GoNodeEvent ev;
  104. ev.type = ZT_GONODE_EVENT_NETWORK_CONFIG_UPDATE;
  105. ev.data.nconf.op = op;
  106. if (cfg)
  107. ev.data.nconf.conf = *cfg;
  108. reinterpret_cast<ZT_GoNode *>(uptr)->eq.post(ev);
  109. }
  110. static void ZT_GoNode_VirtualNetworkFrameFunction(
  111. ZT_Node *node,
  112. void *uptr,
  113. void *tptr,
  114. uint64_t nwid,
  115. void **nptr,
  116. uint64_t srcMac,
  117. uint64_t destMac,
  118. unsigned int etherType,
  119. unsigned int vlanId,
  120. const void *data,
  121. unsigned int len)
  122. {
  123. if (*nptr)
  124. reinterpret_cast<EthernetTap *>(*nptr)->put(MAC(srcMac),MAC(destMac),etherType,data,len);
  125. }
  126. static void ZT_GoNode_EventCallback(
  127. ZT_Node *node,
  128. void *uptr,
  129. void *tptr,
  130. enum ZT_Event et,
  131. const void *data)
  132. {
  133. ZT_GoNodeEvent ev;
  134. ev.type = ZT_GONODE_EVENT_ZTEVENT;
  135. ev.data.zt.type = et;
  136. reinterpret_cast<ZT_GoNode *>(uptr)->eq.post(ev);
  137. }
  138. static void ZT_GoNode_StatePutFunction(
  139. ZT_Node *node,
  140. void *uptr,
  141. void *tptr,
  142. enum ZT_StateObjectType objType,
  143. const uint64_t id[2],
  144. const void *data,
  145. int len)
  146. {
  147. if (len < ZT_MAX_STATE_OBJECT_SIZE) { // sanity check
  148. ZT_GoNodeEvent ev;
  149. ev.type = (len >= 0) ? ZT_GONODE_EVENT_STATE_PUT : ZT_GONODE_EVENT_STATE_DELETE;
  150. if (len > 0) {
  151. memcpy(ev.data.sobj.data,data,len);
  152. ev.data.sobj.len = (unsigned int)len;
  153. }
  154. ev.data.sobj.objType = objType;
  155. ev.data.sobj.id[0] = id[0];
  156. ev.data.sobj.id[1] = id[1];
  157. reinterpret_cast<ZT_GoNode *>(uptr)->eq.post(ev);
  158. }
  159. }
  160. static int ZT_GoNode_StateGetFunction(
  161. ZT_Node *node,
  162. void *uptr,
  163. void *tptr,
  164. enum ZT_StateObjectType objType,
  165. const uint64_t id[2],
  166. void *buf,
  167. unsigned int buflen)
  168. {
  169. return reinterpret_cast<ZT_GoNode *>(uptr)->goStateObjectGetFunc(reinterpret_cast<ZT_GoNode *>(uptr),reinterpret_cast<ZT_GoNode *>(uptr)->node,(int)objType,id,buf,buflen);
  170. }
  171. static ZT_ALWAYS_INLINE void doUdpSend(ZT_SOCKET sock,const struct sockaddr_storage *addr,const void *data,const unsigned int len,const unsigned int ipTTL)
  172. {
  173. switch(addr->ss_family) {
  174. case AF_INET:
  175. if ((ipTTL > 0)&&(ipTTL < 255)) {
  176. #ifdef __WINDOWS__
  177. DWORD tmp = (DWORD)ipTTL;
  178. #else
  179. int tmp = (int)ipTTL;
  180. #endif
  181. setsockopt(sock,IPPROTO_IP,IP_TTL,&tmp,sizeof(tmp));
  182. sendto(sock,data,len,MSG_DONTWAIT,(const sockaddr *)addr,sizeof(struct sockaddr_in));
  183. tmp = 255;
  184. setsockopt(sock,IPPROTO_IP,IP_TTL,&tmp,sizeof(tmp));
  185. } else {
  186. sendto(sock,data,len,MSG_DONTWAIT,(const sockaddr *)addr,sizeof(struct sockaddr_in));
  187. }
  188. break;
  189. case AF_INET6:
  190. // The ipTTL option isn't currently used with IPv6. It's only used
  191. // with IPv4 "firewall opener" / "NAT buster" preamble packets as part
  192. // of IPv4 NAT traversal.
  193. sendto(sock,data,len,MSG_DONTWAIT,(const sockaddr *)addr,sizeof(struct sockaddr_in6));
  194. break;
  195. }
  196. }
  197. static void ZT_GoNode_WirePacketSendFunction(
  198. ZT_Node *node,
  199. void *uptr,
  200. void *tptr,
  201. int64_t localSocket,
  202. const struct sockaddr_storage *addr,
  203. const void *data,
  204. unsigned int len,
  205. unsigned int ipTTL)
  206. {
  207. if ((localSocket != -1)&&(localSocket != ZT_INVALID_SOCKET)) {
  208. doUdpSend((ZT_SOCKET)localSocket,addr,data,len,ipTTL);
  209. } else {
  210. ZT_GoNode *const gn = reinterpret_cast<ZT_GoNode *>(uptr);
  211. std::set<std::string> ipsSentFrom;
  212. std::lock_guard<std::mutex> l(gn->threads_l);
  213. for(auto t=gn->threads.begin();t!=gn->threads.end();++t) {
  214. if (t->second.af == addr->ss_family) {
  215. if (ipsSentFrom.insert(t->second.ip).second) {
  216. doUdpSend(t->first,addr,data,len,ipTTL);
  217. }
  218. }
  219. }
  220. }
  221. }
  222. static int ZT_GoNode_PathCheckFunction(
  223. ZT_Node *node,
  224. void *uptr,
  225. void *tptr,
  226. uint64_t ztAddress,
  227. int64_t localSocket,
  228. const struct sockaddr_storage *sa)
  229. {
  230. return reinterpret_cast<ZT_GoNode *>(uptr)->goPathCheckFunc(reinterpret_cast<ZT_GoNode *>(uptr),reinterpret_cast<ZT_GoNode *>(uptr)->node,ztAddress,sa);
  231. }
  232. static int ZT_GoNode_PathLookupFunction(
  233. ZT_Node *node,
  234. void *uptr,
  235. void *tptr,
  236. uint64_t ztAddress,
  237. int desiredAddressFamily,
  238. struct sockaddr_storage *sa)
  239. {
  240. return reinterpret_cast<ZT_GoNode *>(uptr)->goPathLookupFunc(reinterpret_cast<ZT_GoNode *>(uptr),reinterpret_cast<ZT_GoNode *>(uptr)->node,desiredAddressFamily,sa);
  241. }
  242. static void ZT_GoNode_DNSResolver(
  243. ZT_Node *node,
  244. void *uptr,
  245. void *tptr,
  246. const enum ZT_DNSRecordType *types,
  247. unsigned int numTypes,
  248. const char *name,
  249. uintptr_t requestId)
  250. {
  251. ZT_GoNodeEvent ev;
  252. ev.type = ZT_GONODE_EVENT_DNS_GET_TXT;
  253. Utils::scopy(ev.data.dns.dnsName,sizeof(ev.data.dns.dnsName),name);
  254. reinterpret_cast<ZT_GoNode *>(uptr)->eq.post(ev);
  255. }
  256. //////////////////////////////////////////////////////////////////////////////
  257. extern "C" ZT_GoNode *ZT_GoNode_new(
  258. const char *workingPath,
  259. int (*goPathCheckFunc)(ZT_GoNode *,ZT_Node *,uint64_t ztAddress,const void *),
  260. int (*goPathLookupFunc)(ZT_GoNode *,ZT_Node *,int desiredAddressFamily,void *),
  261. int (*goStateObjectGetFunc)(ZT_GoNode *,ZT_Node *,int objType,const uint64_t id[2],void *buf,unsigned int bufSize))
  262. {
  263. try {
  264. struct ZT_Node_Callbacks cb;
  265. cb.virtualNetworkConfigFunction = &ZT_GoNode_VirtualNetworkConfigFunction;
  266. cb.virtualNetworkFrameFunction = &ZT_GoNode_VirtualNetworkFrameFunction;
  267. cb.eventCallback = &ZT_GoNode_EventCallback;
  268. cb.statePutFunction = &ZT_GoNode_StatePutFunction;
  269. cb.stateGetFunction = &ZT_GoNode_StateGetFunction;
  270. cb.pathCheckFunction = &ZT_GoNode_PathCheckFunction;
  271. cb.pathLookupFunction = &ZT_GoNode_PathLookupFunction;
  272. cb.dnsResolver = &ZT_GoNode_DNSResolver;
  273. ZT_GoNode_Impl *gn = new ZT_GoNode_Impl;
  274. const int64_t now = OSUtils::now();
  275. gn->node = new Node(reinterpret_cast<void *>(gn),nullptr,&cb,now);
  276. gn->nextBackgroundTaskDeadline = now;
  277. gn->goPathCheckFunc = goPathCheckFunc;
  278. gn->goPathLookupFunc = goPathLookupFunc;
  279. gn->goStateObjectGetFunc = goStateObjectGetFunc;
  280. gn->path = workingPath;
  281. gn->run = true;
  282. gn->backgroundTaskThread = std::thread([gn] {
  283. while (gn->run) {
  284. std::this_thread::sleep_for(std::chrono::milliseconds(250));
  285. const int64_t now = OSUtils::now();
  286. if (now >= gn->nextBackgroundTaskDeadline)
  287. gn->node->processBackgroundTasks(nullptr,now,&(gn->nextBackgroundTaskDeadline));
  288. }
  289. });
  290. return gn;
  291. } catch ( ... ) {
  292. fprintf(stderr,"FATAL: unable to create new instance of Node (out of memory?)" ZT_EOL_S);
  293. exit(1);
  294. }
  295. }
  296. extern "C" void ZT_GoNode_delete(ZT_GoNode *gn)
  297. {
  298. gn->run = false;
  299. ZT_GoNodeEvent sd;
  300. sd.type = ZT_GONODE_EVENT_SHUTDOWN;
  301. gn->eq.post(sd);
  302. std::vector<std::thread> th;
  303. gn->threads_l.lock();
  304. for(auto t=gn->threads.begin();t!=gn->threads.end();++t) {
  305. t->second.run = false;
  306. shutdown(t->first,SHUT_RDWR);
  307. close(t->first);
  308. th.emplace_back(t->second.thr);
  309. }
  310. gn->threads_l.unlock();
  311. for(auto t=th.begin();t!=th.end();++t)
  312. t->join();
  313. gn->taps_l.lock();
  314. for(auto t=gn->taps.begin();t!=gn->taps.end();++t)
  315. gn->node->leave(t->first,nullptr,nullptr);
  316. gn->taps.clear();
  317. gn->taps_l.unlock();
  318. gn->backgroundTaskThread.join();
  319. delete gn->node;
  320. delete gn;
  321. }
  322. extern "C" ZT_Node *ZT_GoNode_getNode(ZT_GoNode *gn)
  323. {
  324. return gn->node;
  325. }
  326. // Sets flags and socket options common to both IPv4 and IPv6 UDP sockets
  327. static void setCommonUdpSocketSettings(ZT_SOCKET udpSock,const char *dev)
  328. {
  329. int bufSize = 1048576;
  330. while (bufSize > 131072) {
  331. if (setsockopt(udpSock,SOL_SOCKET,SO_RCVBUF,(const char *)&bufSize,sizeof(bufSize)) == 0)
  332. break;
  333. bufSize -= 131072;
  334. }
  335. bufSize = 1048576;
  336. while (bufSize > 131072) {
  337. if (setsockopt(udpSock,SOL_SOCKET,SO_SNDBUF,(const char *)&bufSize,sizeof(bufSize)) == 0)
  338. break;
  339. bufSize -= 131072;
  340. }
  341. SETSOCKOPT_FLAG_TYPE fl;
  342. #ifdef SO_REUSEPORT
  343. fl = SETSOCKOPT_FLAG_TRUE;
  344. setsockopt(udpSock,SOL_SOCKET,SO_REUSEPORT,(void *)&fl,sizeof(fl));
  345. #endif
  346. #ifndef __LINUX__ // linux wants just SO_REUSEPORT
  347. fl = SETSOCKOPT_FLAG_TRUE;
  348. setsockopt(udpSock,SOL_SOCKET,SO_REUSEADDR,(void *)&fl,sizeof(fl));
  349. #endif
  350. fl = SETSOCKOPT_FLAG_TRUE;
  351. setsockopt(udpSock,SOL_SOCKET,SO_BROADCAST,(void *)&fl,sizeof(fl));
  352. #ifdef IP_DONTFRAG
  353. fl = SETSOCKOPT_FLAG_FALSE;
  354. setsockopt(udpSock,IPPROTO_IP,IP_DONTFRAG,(void *)&fl,sizeof(fl));
  355. #endif
  356. #ifdef IP_MTU_DISCOVER
  357. fl = SETSOCKOPT_FLAG_FALSE;
  358. setsockopt(udpSock,IPPROTO_IP,IP_MTU_DISCOVER,(void *)&fl,sizeof(fl));
  359. #endif
  360. #ifdef SO_BINDTODEVICE
  361. if ((dev)&&(strlen(dev)))
  362. setsockopt(udpSock,SOL_SOCKET,SO_BINDTODEVICE,dev,strlen(dev));
  363. #endif
  364. #if defined(__BSD__) && defined(IP_BOUND_IF)
  365. if ((dev)&&(strlen(dev))) {
  366. int idx = if_nametoindex(dev);
  367. if (idx != 0)
  368. setsockopt(udpSock,IPPROTO_IP,IP_BOUND_IF,(void *)&idx,sizeof(idx));
  369. }
  370. #endif
  371. }
  372. extern "C" int ZT_GoNode_phyStartListen(ZT_GoNode *gn,const char *dev,const char *ip,const int port)
  373. {
  374. if (strchr(ip,':')) {
  375. struct sockaddr_in6 in6;
  376. memset(&in6,0,sizeof(in6));
  377. in6.sin6_family = AF_INET6;
  378. if (inet_pton(AF_INET6,ip,&(in6.sin6_addr)) <= 0)
  379. return errno;
  380. in6.sin6_port = htons((uint16_t)port);
  381. ZT_SOCKET udpSock = socket(AF_INET6,SOCK_DGRAM,0);
  382. if (udpSock == ZT_INVALID_SOCKET)
  383. return errno;
  384. setCommonUdpSocketSettings(udpSock,dev);
  385. SETSOCKOPT_FLAG_TYPE fl = SETSOCKOPT_FLAG_TRUE;
  386. setsockopt(udpSock,IPPROTO_IPV6,IPV6_V6ONLY,(const char *)&fl,sizeof(fl));
  387. #ifdef IPV6_DONTFRAG
  388. fl = SETSOCKOPT_FLAG_FALSE;
  389. setsockopt(udpSock,IPPROTO_IPV6,IPV6_DONTFRAG,&fl,sizeof(fl));
  390. #endif
  391. if (bind(udpSock,reinterpret_cast<const struct sockaddr *>(&in6),sizeof(in6)) != 0)
  392. return errno;
  393. {
  394. std::lock_guard<std::mutex> l(gn->threads_l);
  395. ZT_GoNodeThread &gnt = gn->threads[udpSock];
  396. gnt.ip = ip;
  397. gnt.port = port;
  398. gnt.af = AF_INET6;
  399. gnt.run = true;
  400. gnt.thr = std::thread([udpSock,gn,&gnt] {
  401. struct sockaddr_in6 in6;
  402. socklen_t salen;
  403. char buf[16384];
  404. while (gnt.run) {
  405. salen = sizeof(in6);
  406. int s = (int)recvfrom(udpSock,buf,sizeof(buf),0,reinterpret_cast<struct sockaddr *>(&in6),&salen);
  407. if (s > 0) {
  408. gn->node->processWirePacket(&gnt,OSUtils::now(),(int64_t)udpSock,reinterpret_cast<const struct sockaddr_storage *>(&in6),buf,(unsigned int)s,&(gn->nextBackgroundTaskDeadline));
  409. }
  410. }
  411. });
  412. }
  413. } else {
  414. struct sockaddr_in in;
  415. memset(&in,0,sizeof(in));
  416. in.sin_family = AF_INET;
  417. if (inet_pton(AF_INET,ip,&(in.sin_addr)) <= 0)
  418. return errno;
  419. in.sin_port = htons((uint16_t)port);
  420. ZT_SOCKET udpSock = socket(AF_INET,SOCK_DGRAM,0);
  421. if (udpSock == ZT_INVALID_SOCKET)
  422. return errno;
  423. setCommonUdpSocketSettings(udpSock,dev);
  424. #ifdef SO_NO_CHECK
  425. SETSOCKOPT_FLAG_TYPE fl = SETSOCKOPT_FLAG_TRUE;
  426. setsockopt(udpSock,SOL_SOCKET,SO_NO_CHECK,&fl,sizeof(fl));
  427. #endif
  428. if (bind(udpSock,reinterpret_cast<const struct sockaddr *>(&in),sizeof(in)) != 0)
  429. return errno;
  430. {
  431. std::lock_guard<std::mutex> l(gn->threads_l);
  432. ZT_GoNodeThread &gnt = gn->threads[udpSock];
  433. gnt.ip = ip;
  434. gnt.port = port;
  435. gnt.af = AF_INET6;
  436. gnt.run = true;
  437. gnt.thr = std::thread([udpSock,gn,&gnt] {
  438. struct sockaddr_in in4;
  439. socklen_t salen;
  440. char buf[16384];
  441. while (gnt.run) {
  442. salen = sizeof(in4);
  443. int s = (int)recvfrom(udpSock,buf,sizeof(buf),0,reinterpret_cast<struct sockaddr *>(&in4),&salen);
  444. if (s > 0) {
  445. gn->node->processWirePacket(&gnt,OSUtils::now(),(int64_t)udpSock,reinterpret_cast<const struct sockaddr_storage *>(&in4),buf,(unsigned int)s,&(gn->nextBackgroundTaskDeadline));
  446. }
  447. }
  448. });
  449. }
  450. }
  451. return 0;
  452. }
  453. extern "C" int ZT_GoNode_phyStopListen(ZT_GoNode *gn,const char *dev,const char *ip,const int port)
  454. {
  455. {
  456. std::lock_guard<std::mutex> l(gn->threads_l);
  457. for(auto t=gn->threads.begin();t!=gn->threads.end();) {
  458. if ((t->second.ip == ip)&&(t->second.port == port)) {
  459. t->second.run = false;
  460. shutdown(t->first,SHUT_RDWR);
  461. close(t->first);
  462. t->second.thr.join();
  463. gn->threads.erase(t++);
  464. } else ++t;
  465. }
  466. }
  467. }
  468. extern "C" int ZT_GoNode_waitForEvent(ZT_GoNode *gn,ZT_GoNodeEvent *ev)
  469. {
  470. gn->eq.get(*ev);
  471. }
  472. static void tapFrameHandler(void *uptr,void *tptr,uint64_t nwid,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len)
  473. {
  474. ZT_GoNode *const gn = reinterpret_cast<ZT_GoNode *>(uptr);
  475. gn->node->processVirtualNetworkFrame(tptr,OSUtils::now(),nwid,from.toInt(),to.toInt(),etherType,vlanId,data,len,&(gn->nextBackgroundTaskDeadline));
  476. }
  477. extern "C" ZT_GoTap *ZT_GoNode_join(ZT_GoNode *gn,uint64_t nwid)
  478. {
  479. try {
  480. std::lock_guard<std::mutex> l(gn->taps_l);
  481. auto existingTap = gn->taps.find(nwid);
  482. if (existingTap != gn->taps.end())
  483. return (ZT_GoTap *)existingTap->second.get();
  484. char tmp[256];
  485. OSUtils::ztsnprintf(tmp,sizeof(tmp),"ZeroTier Network %.16llx",(unsigned long long)nwid);
  486. std::shared_ptr<EthernetTap> tap(EthernetTap::newInstance(nullptr,gn->path.c_str(),MAC(Address(gn->node->address()),nwid),ZT_DEFAULT_MTU,0,nwid,tmp,&tapFrameHandler,gn));
  487. if (!tap)
  488. return nullptr;
  489. gn->taps[nwid] = tap;
  490. gn->node->join(nwid,tap.get(),nullptr);
  491. return (ZT_GoTap *)tap.get();
  492. } catch ( ... ) {
  493. return nullptr;
  494. }
  495. }
  496. extern "C" void ZT_GoNode_leave(ZT_GoNode *gn,uint64_t nwid)
  497. {
  498. std::lock_guard<std::mutex> l(gn->taps_l);
  499. auto existingTap = gn->taps.find(nwid);
  500. if (existingTap != gn->taps.end()) {
  501. gn->node->leave(nwid,nullptr,nullptr);
  502. gn->taps.erase(existingTap);
  503. }
  504. }