GoGlue.cpp 18 KB

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