123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738 |
- /*
- * Copyright (c)2013-2020 ZeroTier, Inc.
- *
- * Use of this software is governed by the Business Source License included
- * in the LICENSE.TXT file in the project's root directory.
- *
- * Change Date: 2025-01-01
- *
- * On the date above, in accordance with the Business Source License, use
- * of this software will be governed by version 2.0 of the Apache License.
- */
- /****/
- #ifndef _WIN32_WINNT
- #define _WIN32_WINNT 0x06010000
- #endif
- #include "GoGlue.h"
- #include "../core/Constants.hpp"
- #include "../core/InetAddress.hpp"
- #include "../core/Node.hpp"
- #include "../core/Utils.hpp"
- #include "../core/MAC.hpp"
- #include "../core/Address.hpp"
- #include "../core/Containers.hpp"
- #include "../core/Certificate.hpp"
- #include "../osdep/OSUtils.hpp"
- #include "../osdep/EthernetTap.hpp"
- #ifndef __WINDOWS__
- #include <unistd.h>
- #include <sys/socket.h>
- #include <sys/un.h>
- #include <sys/types.h>
- #include <sys/ioctl.h>
- #include <ifaddrs.h>
- #include <net/if.h>
- #include <netinet/in.h>
- #ifdef __BSD__
- #include <netinet6/in6_var.h>
- #endif
- #include <arpa/inet.h>
- #include <errno.h>
- #ifdef __LINUX__
- #ifndef IPV6_DONTFRAG
- #define IPV6_DONTFRAG 62
- #endif
- #endif
- #endif // !__WINDOWS__
- #include <thread>
- #include <mutex>
- #include <memory>
- #include <atomic>
- #ifdef __WINDOWS__
- #define SETSOCKOPT_FLAG_TYPE BOOL
- #define SETSOCKOPT_FLAG_TRUE TRUE
- #define SETSOCKOPT_FLAG_FALSE FALSE
- #else
- #define SETSOCKOPT_FLAG_TYPE int
- #define SETSOCKOPT_FLAG_TRUE 1
- #define SETSOCKOPT_FLAG_FALSE 0
- #endif
- #ifndef MSG_DONTWAIT
- #define MSG_DONTWAIT 0
- #endif
- using namespace ZeroTier;
- struct ZT_GoNodeThread
- {
- String ip;
- int port;
- int af;
- bool primary;
- std::atomic< bool > run;
- std::thread thr;
- };
- struct ZT_GoNode_Impl
- {
- void *goUserPtr;
- Node *node;
- volatile int64_t nextBackgroundTaskDeadline;
- String path;
- std::atomic< bool > run;
- Map< ZT_SOCKET, ZT_GoNodeThread > threads;
- Map< uint64_t, std::shared_ptr< EthernetTap > > taps;
- std::mutex threads_l;
- std::mutex taps_l;
- std::thread backgroundTaskThread;
- };
- static const String defaultHomePath(OSUtils::platformDefaultHomePath());
- const char *const ZT_PLATFORM_DEFAULT_HOMEPATH = defaultHomePath.c_str();
- // These are implemented in Go code.
- extern "C" int goPathCheckFunc(void *, const ZT_Identity *, int, const void *, int);
- extern "C" int goPathLookupFunc(void *, uint64_t, int, const ZT_Identity *, int *, uint8_t [16], int *);
- extern "C" void goStateObjectPutFunc(void *, int, const uint64_t *, const void *, int);
- extern "C" int goStateObjectGetFunc(void *, int, const uint64_t *, void **);
- extern "C" void goVirtualNetworkConfigFunc(void *, ZT_GoTap *, uint64_t, int, const ZT_VirtualNetworkConfig *);
- extern "C" void goZtEvent(void *, int, const void *);
- extern "C" void goHandleTapAddedMulticastGroup(void *, ZT_GoTap *, uint64_t, uint64_t, uint32_t);
- extern "C" void goHandleTapRemovedMulticastGroup(void *, ZT_GoTap *, uint64_t, uint64_t, uint32_t);
- static void ZT_GoNode_VirtualNetworkConfigFunction(
- ZT_Node *node,
- void *uptr,
- void *tptr,
- uint64_t nwid,
- void **nptr,
- enum ZT_VirtualNetworkConfigOperation op,
- const ZT_VirtualNetworkConfig *cfg)
- {
- goVirtualNetworkConfigFunc(reinterpret_cast<ZT_GoNode *>(uptr)->goUserPtr, reinterpret_cast<ZT_GoTap *>(*nptr), nwid, op, cfg);
- }
- static void ZT_GoNode_VirtualNetworkFrameFunction(
- ZT_Node *node,
- void *uptr,
- void *tptr,
- uint64_t nwid,
- void **nptr,
- uint64_t srcMac,
- uint64_t destMac,
- unsigned int etherType,
- unsigned int vlanId,
- const void *data,
- unsigned int len)
- {
- if (*nptr)
- reinterpret_cast<EthernetTap *>(*nptr)->put(MAC(srcMac), MAC(destMac), etherType, data, len);
- }
- static void ZT_GoNode_EventCallback(
- ZT_Node *node,
- void *uptr,
- void *tptr,
- enum ZT_Event et,
- const void *data)
- {
- goZtEvent(reinterpret_cast<ZT_GoNode *>(uptr)->goUserPtr, et, data);
- }
- static void ZT_GoNode_StatePutFunction(
- ZT_Node *node,
- void *uptr,
- void *tptr,
- enum ZT_StateObjectType objType,
- const uint64_t id[2],
- const void *data,
- int len)
- {
- goStateObjectPutFunc(
- reinterpret_cast<ZT_GoNode *>(uptr)->goUserPtr,
- objType,
- id,
- data,
- len);
- }
- static void _freeFunc(void *p)
- { if (p) free(p); }
- static int ZT_GoNode_StateGetFunction(
- ZT_Node *node,
- void *uptr,
- void *tptr,
- enum ZT_StateObjectType objType,
- const uint64_t id[2],
- void **data,
- void (**freeFunc)(void *))
- {
- *freeFunc = &_freeFunc;
- return goStateObjectGetFunc(
- reinterpret_cast<ZT_GoNode *>(uptr)->goUserPtr,
- (int)objType,
- id,
- data);
- }
- static ZT_INLINE void doUdpSend(ZT_SOCKET sock, const struct sockaddr_storage *addr, const void *data, const unsigned int len, const unsigned int ipTTL)
- {
- switch (addr->ss_family) {
- case AF_INET:
- if (unlikely((ipTTL > 0) && (ipTTL < 255))) {
- #ifdef __WINDOWS__
- DWORD tmp = (DWORD)ipTTL;
- #else
- int tmp = (int)ipTTL;
- #endif
- setsockopt(sock, IPPROTO_IP, IP_TTL, reinterpret_cast<const char *>(&tmp), sizeof(tmp));
- sendto(sock, reinterpret_cast<const char *>(data), len, MSG_DONTWAIT, (const sockaddr *)addr, sizeof(struct sockaddr_in));
- tmp = 255;
- setsockopt(sock, IPPROTO_IP, IP_TTL, reinterpret_cast<const char *>(&tmp), sizeof(tmp));
- } else {
- sendto(sock, reinterpret_cast<const char *>(data), len, MSG_DONTWAIT, (const sockaddr *)addr, sizeof(struct sockaddr_in));
- }
- break;
- case AF_INET6:
- // The ipTTL option isn't currently used with IPv6. It's only used
- // with IPv4 "firewall opener" / "NAT buster" preamble packets as part
- // of IPv4 NAT traversal.
- sendto(sock, reinterpret_cast<const char *>(data), len, MSG_DONTWAIT, (const sockaddr *)addr, sizeof(struct sockaddr_in6));
- break;
- }
- }
- static int ZT_GoNode_WirePacketSendFunction(
- ZT_Node *node,
- void *uptr,
- void *tptr,
- int64_t localSocket,
- const struct sockaddr_storage *addr,
- const void *data,
- unsigned int len,
- unsigned int ipTTL)
- {
- if (likely(localSocket > 0)) {
- doUdpSend((ZT_SOCKET)localSocket, addr, data, len, ipTTL);
- } else {
- ZT_GoNode *const gn = reinterpret_cast<ZT_GoNode *>(uptr);
- std::lock_guard< std::mutex > l(gn->threads_l);
- for (auto t = gn->threads.begin(); t != gn->threads.end(); ++t) {
- if ((t->second.af == addr->ss_family) && (t->second.primary)) {
- doUdpSend(t->first, addr, data, len, ipTTL);
- break;
- }
- }
- }
- return 0;
- }
- static int ZT_GoNode_PathCheckFunction(
- ZT_Node *node,
- void *uptr,
- void *tptr,
- uint64_t ztAddress,
- const ZT_Identity *id,
- int64_t localSocket,
- const struct sockaddr_storage *sa)
- {
- switch (sa->ss_family) {
- case AF_INET:
- return goPathCheckFunc(
- reinterpret_cast<ZT_GoNode *>(uptr)->goUserPtr,
- id,
- AF_INET,
- &(reinterpret_cast<const struct sockaddr_in *>(sa)->sin_addr.s_addr),
- Utils::ntoh((uint16_t)reinterpret_cast<const struct sockaddr_in *>(sa)->sin_port));
- case AF_INET6:
- return goPathCheckFunc(
- reinterpret_cast<ZT_GoNode *>(uptr)->goUserPtr,
- id,
- AF_INET6,
- reinterpret_cast<const struct sockaddr_in6 *>(sa)->sin6_addr.s6_addr,
- Utils::ntoh((uint16_t)reinterpret_cast<const struct sockaddr_in6 *>(sa)->sin6_port));
- }
- return 0;
- }
- static int ZT_GoNode_PathLookupFunction(
- ZT_Node *node,
- void *uptr,
- void *tptr,
- uint64_t ztAddress,
- const ZT_Identity *id,
- int desiredAddressFamily,
- struct sockaddr_storage *sa)
- {
- int family = 0;
- uint8_t ip[16];
- int port = 0;
- const int result = goPathLookupFunc(
- reinterpret_cast<ZT_GoNode *>(uptr)->goUserPtr,
- ztAddress,
- desiredAddressFamily,
- id,
- &family,
- ip,
- &port
- );
- if (result != 0) {
- switch (family) {
- case AF_INET:
- reinterpret_cast<struct sockaddr_in *>(sa)->sin_family = AF_INET;
- memcpy(&(reinterpret_cast<struct sockaddr_in *>(sa)->sin_addr.s_addr), ip, 4);
- reinterpret_cast<struct sockaddr_in *>(sa)->sin_port = Utils::hton((uint16_t)port);
- return 1;
- case AF_INET6:
- reinterpret_cast<struct sockaddr_in6 *>(sa)->sin6_family = AF_INET6;
- memcpy(reinterpret_cast<struct sockaddr_in6 *>(sa)->sin6_addr.s6_addr, ip, 16);
- reinterpret_cast<struct sockaddr_in6 *>(sa)->sin6_port = Utils::hton((uint16_t)port);
- return 1;
- }
- }
- return 0;
- }
- extern "C" ZT_GoNode *ZT_GoNode_new(const char *workingPath, uintptr_t userPtr)
- {
- try {
- struct ZT_Node_Callbacks cb;
- cb.statePutFunction = &ZT_GoNode_StatePutFunction;
- cb.stateGetFunction = &ZT_GoNode_StateGetFunction;
- cb.wirePacketSendFunction = &ZT_GoNode_WirePacketSendFunction;
- cb.virtualNetworkFrameFunction = &ZT_GoNode_VirtualNetworkFrameFunction;
- cb.virtualNetworkConfigFunction = &ZT_GoNode_VirtualNetworkConfigFunction;
- cb.eventCallback = &ZT_GoNode_EventCallback;
- cb.pathCheckFunction = &ZT_GoNode_PathCheckFunction;
- cb.pathLookupFunction = &ZT_GoNode_PathLookupFunction;
- ZT_GoNode_Impl *gn = new ZT_GoNode_Impl;
- const int64_t now = OSUtils::now();
- gn->goUserPtr = reinterpret_cast<void *>(userPtr);
- gn->node = new Node(reinterpret_cast<void *>(gn), nullptr, &cb, now);
- gn->nextBackgroundTaskDeadline = now;
- gn->path = workingPath;
- gn->run = true;
- gn->backgroundTaskThread = std::thread([gn] {
- int64_t lastCheckedTaps = 0;
- while (gn->run) {
- std::this_thread::sleep_for(std::chrono::milliseconds(500));
- const int64_t now = OSUtils::now();
- if (now >= gn->nextBackgroundTaskDeadline)
- gn->node->processBackgroundTasks(nullptr, now, &(gn->nextBackgroundTaskDeadline));
- if ((now - lastCheckedTaps) > 10000) {
- lastCheckedTaps = now;
- std::vector< MulticastGroup > added, removed;
- std::lock_guard< std::mutex > tl(gn->taps_l);
- for (auto t = gn->taps.begin(); t != gn->taps.end(); ++t) {
- added.clear();
- removed.clear();
- t->second->scanMulticastGroups(added, removed);
- for (auto g = added.begin(); g != added.end(); ++g)
- goHandleTapAddedMulticastGroup(gn, (ZT_GoTap *)t->second.get(), t->first, g->mac().toInt(), g->adi());
- for (auto g = removed.begin(); g != removed.end(); ++g)
- goHandleTapRemovedMulticastGroup(gn, (ZT_GoTap *)t->second.get(), t->first, g->mac().toInt(), g->adi());
- }
- }
- }
- });
- return gn;
- } catch (...) {
- fprintf(stderr, "FATAL: unable to create new instance of Node (out of memory?)" ZT_EOL_S);
- exit(1);
- }
- }
- extern "C" void ZT_GoNode_delete(ZT_GoNode *gn)
- {
- gn->run = false;
- gn->threads_l.lock();
- for (auto t = gn->threads.begin(); t != gn->threads.end(); ++t) {
- t->second.run = false;
- #ifdef __WINDOWS__
- shutdown(t->first, SD_BOTH);
- closesocket(t->first);
- #else
- shutdown(t->first, SHUT_RDWR);
- close(t->first);
- #endif
- t->second.thr.join();
- }
- gn->threads_l.unlock();
- gn->taps_l.lock();
- for (auto t = gn->taps.begin(); t != gn->taps.end(); ++t)
- gn->node->leave(t->first, nullptr, nullptr);
- gn->taps.clear();
- gn->taps_l.unlock();
- gn->backgroundTaskThread.join();
- gn->node->shutdown(nullptr);
- delete gn->node;
- delete gn;
- }
- extern "C" ZT_Node *ZT_GoNode_getNode(ZT_GoNode *gn)
- {
- return gn->node;
- }
- static void setCommonUdpSocketSettings(ZT_SOCKET udpSock, const char *dev)
- {
- int bufSize = 1048576;
- while (bufSize > 131072) {
- if (setsockopt(udpSock, SOL_SOCKET, SO_RCVBUF, (const char *)&bufSize, sizeof(bufSize)) == 0)
- break;
- bufSize -= 131072;
- }
- bufSize = 1048576;
- while (bufSize > 131072) {
- if (setsockopt(udpSock, SOL_SOCKET, SO_SNDBUF, (const char *)&bufSize, sizeof(bufSize)) == 0)
- break;
- bufSize -= 131072;
- }
- SETSOCKOPT_FLAG_TYPE fl;
- #ifdef SO_REUSEPORT
- fl = SETSOCKOPT_FLAG_TRUE;
- setsockopt(udpSock, SOL_SOCKET, SO_REUSEPORT, &fl, sizeof(fl));
- #endif
- #ifndef __LINUX__ // linux wants just SO_REUSEPORT
- fl = SETSOCKOPT_FLAG_TRUE;
- setsockopt(udpSock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char *>(&fl), sizeof(fl));
- #endif
- fl = SETSOCKOPT_FLAG_TRUE;
- setsockopt(udpSock, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<const char *>(&fl), sizeof(fl));
- #ifdef IP_DONTFRAG
- fl = SETSOCKOPT_FLAG_FALSE;
- setsockopt(udpSock,IPPROTO_IP,IP_DONTFRAG,&fl,sizeof(fl));
- #endif
- #ifdef IP_MTU_DISCOVER
- fl = SETSOCKOPT_FLAG_FALSE;
- setsockopt(udpSock,IPPROTO_IP,IP_MTU_DISCOVER,&fl,sizeof(fl));
- #endif
- #ifdef SO_BINDTODEVICE
- if ((dev)&&(strlen(dev)))
- setsockopt(udpSock,SOL_SOCKET,SO_BINDTODEVICE,dev,strlen(dev));
- #endif
- #if defined(__BSD__) && defined(IP_BOUND_IF)
- if ((dev) && (strlen(dev))) {
- int idx = if_nametoindex(dev);
- if (idx != 0)
- setsockopt(udpSock, IPPROTO_IP, IP_BOUND_IF, (void *)&idx, sizeof(idx));
- }
- #endif
- }
- extern "C" int ZT_GoNode_phyStartListen(ZT_GoNode *gn, const char *dev, const char *ip, const int port, const int primary)
- {
- if (strchr(ip, ':')) {
- struct sockaddr_in6 in6;
- memset(&in6, 0, sizeof(in6));
- in6.sin6_family = AF_INET6;
- if (inet_pton(AF_INET6, ip, &(in6.sin6_addr)) <= 0)
- return errno;
- in6.sin6_port = htons((uint16_t)port);
- ZT_SOCKET udpSock = socket(AF_INET6, SOCK_DGRAM, 0);
- if (udpSock == ZT_INVALID_SOCKET)
- return errno;
- setCommonUdpSocketSettings(udpSock, dev);
- SETSOCKOPT_FLAG_TYPE fl = SETSOCKOPT_FLAG_TRUE;
- setsockopt(udpSock, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&fl, sizeof(fl));
- #ifdef IPV6_DONTFRAG
- fl = SETSOCKOPT_FLAG_FALSE;
- setsockopt(udpSock, IPPROTO_IPV6, IPV6_DONTFRAG, reinterpret_cast<const char *>(&fl), sizeof(fl));
- #endif
- if (bind(udpSock, reinterpret_cast<const struct sockaddr *>(&in6), sizeof(in6)) != 0)
- return errno;
- {
- std::lock_guard< std::mutex > l(gn->threads_l);
- ZT_GoNodeThread &gnt = gn->threads[udpSock];
- gnt.ip = ip;
- gnt.port = port;
- gnt.af = AF_INET6;
- gnt.primary = (primary != 0);
- gnt.run = true;
- gnt.thr = std::thread([udpSock, gn, &gnt] {
- struct sockaddr_in6 in6;
- socklen_t salen;
- while (gnt.run) {
- salen = sizeof(in6);
- void *buf = ZT_getBuffer();
- if (buf) {
- int s = (int)recvfrom(udpSock, reinterpret_cast<char *>(buf), 16384, 0, reinterpret_cast<struct sockaddr *>(&in6), &salen);
- if (s > 0) {
- ZT_Node_processWirePacket(
- reinterpret_cast<ZT_Node *>(gn->node),
- nullptr,
- OSUtils::now(),
- (int64_t)udpSock,
- reinterpret_cast<const struct sockaddr_storage *>(&in6),
- buf,
- (unsigned int)s,
- 1,
- &(gn->nextBackgroundTaskDeadline));
- } else {
- ZT_freeBuffer(buf);
- std::this_thread::sleep_for(std::chrono::milliseconds(10));
- }
- }
- }
- });
- }
- } else {
- struct sockaddr_in in;
- memset(&in, 0, sizeof(in));
- in.sin_family = AF_INET;
- if (inet_pton(AF_INET, ip, &(in.sin_addr)) <= 0)
- return errno;
- in.sin_port = htons((uint16_t)port);
- ZT_SOCKET udpSock = socket(AF_INET, SOCK_DGRAM, 0);
- if (udpSock == ZT_INVALID_SOCKET)
- return errno;
- setCommonUdpSocketSettings(udpSock, dev);
- #ifdef SO_NO_CHECK
- SETSOCKOPT_FLAG_TYPE fl = SETSOCKOPT_FLAG_TRUE;
- setsockopt(udpSock,SOL_SOCKET,SO_NO_CHECK,&fl,sizeof(fl));
- #endif
- if (bind(udpSock, reinterpret_cast<const struct sockaddr *>(&in), sizeof(in)) != 0)
- return errno;
- {
- std::lock_guard< std::mutex > l(gn->threads_l);
- ZT_GoNodeThread &gnt = gn->threads[udpSock];
- gnt.ip = ip;
- gnt.port = port;
- gnt.af = AF_INET6;
- gnt.primary = (primary != 0);
- gnt.run = true;
- gnt.thr = std::thread([udpSock, gn, &gnt] {
- struct sockaddr_in in4;
- socklen_t salen;
- while (gnt.run) {
- salen = sizeof(in4);
- void *buf = ZT_getBuffer();
- if (buf) {
- int s = (int)recvfrom(udpSock, reinterpret_cast<char *>(buf), sizeof(buf), 0, reinterpret_cast<struct sockaddr *>(&in4), &salen);
- if (s > 0) {
- ZT_Node_processWirePacket(
- reinterpret_cast<ZT_Node *>(gn->node),
- nullptr,
- OSUtils::now(),
- (int64_t)udpSock,
- reinterpret_cast<const struct sockaddr_storage *>(&in4),
- buf,
- (unsigned int)s,
- 1,
- &(gn->nextBackgroundTaskDeadline));
- } else {
- ZT_freeBuffer(buf);
- std::this_thread::sleep_for(std::chrono::milliseconds(10));
- }
- }
- }
- });
- }
- }
- return 0;
- }
- extern "C" int ZT_GoNode_phyStopListen(ZT_GoNode *gn, const char *dev, const char *ip, const int port)
- {
- {
- std::lock_guard< std::mutex > l(gn->threads_l);
- for (auto t = gn->threads.begin(); t != gn->threads.end();) {
- if ((t->second.ip == ip) && (t->second.port == port)) {
- t->second.run = false;
- #ifdef __WINDOWS__
- shutdown(t->first, SD_BOTH);
- closesocket(t->first);
- #else
- shutdown(t->first, SHUT_RDWR);
- close(t->first);
- #endif
- t->second.thr.join();
- gn->threads.erase(t++);
- } else ++t;
- }
- }
- return 0;
- }
- 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)
- {
- ZT_Node_processVirtualNetworkFrame(
- reinterpret_cast<ZT_Node *>(reinterpret_cast<ZT_GoNode *>(uptr)->node),
- tptr,
- OSUtils::now(),
- nwid,
- from.toInt(),
- to.toInt(),
- etherType,
- vlanId,
- data,
- len,
- 0,
- &(reinterpret_cast<ZT_GoNode *>(uptr)->nextBackgroundTaskDeadline));
- }
- extern "C" ZT_GoTap *ZT_GoNode_join(ZT_GoNode *gn, uint64_t nwid, const ZT_Fingerprint *const controllerFingerprint)
- {
- try {
- std::lock_guard< std::mutex > l(gn->taps_l);
- auto existingTap = gn->taps.find(nwid);
- if (existingTap != gn->taps.end())
- return (ZT_GoTap *)existingTap->second.get();
- char tmp[256];
- OSUtils::ztsnprintf(tmp, sizeof(tmp), "ZeroTier Network %.16llx", (unsigned long long)nwid);
- 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));
- if (!tap)
- return nullptr;
- gn->taps[nwid] = tap;
- gn->node->join(nwid, controllerFingerprint, tap.get(), nullptr);
- return (ZT_GoTap *)tap.get();
- } catch (...) {
- return nullptr;
- }
- }
- extern "C" void ZT_GoNode_leave(ZT_GoNode *gn, uint64_t nwid)
- {
- std::lock_guard< std::mutex > l(gn->taps_l);
- auto existingTap = gn->taps.find(nwid);
- if (existingTap != gn->taps.end()) {
- gn->node->leave(nwid, nullptr, nullptr);
- gn->taps.erase(existingTap);
- }
- }
- extern "C" void ZT_GoTap_setEnabled(ZT_GoTap *tap, int enabled)
- {
- reinterpret_cast<EthernetTap *>(tap)->setEnabled(enabled != 0);
- }
- extern "C" int ZT_GoTap_addIp(ZT_GoTap *tap, int af, const void *ip, int netmaskBits)
- {
- switch (af) {
- case AF_INET:
- return (reinterpret_cast<EthernetTap *>(tap)->addIp(InetAddress(ip, 4, (unsigned int)netmaskBits)) ? 1 : 0);
- case AF_INET6:
- return (reinterpret_cast<EthernetTap *>(tap)->addIp(InetAddress(ip, 16, (unsigned int)netmaskBits)) ? 1 : 0);
- }
- return 0;
- }
- extern "C" int ZT_GoTap_removeIp(ZT_GoTap *tap, int af, const void *ip, int netmaskBits)
- {
- switch (af) {
- case AF_INET:
- return (reinterpret_cast<EthernetTap *>(tap)->removeIp(InetAddress(ip, 4, (unsigned int)netmaskBits)) ? 1 : 0);
- case AF_INET6:
- return (reinterpret_cast<EthernetTap *>(tap)->removeIp(InetAddress(ip, 16, (unsigned int)netmaskBits)) ? 1 : 0);
- }
- return 0;
- }
- extern "C" int ZT_GoTap_ips(ZT_GoTap *tap, void *buf, unsigned int bufSize)
- {
- auto ips = reinterpret_cast<EthernetTap *>(tap)->ips();
- unsigned int p = 0;
- uint8_t *const b = reinterpret_cast<uint8_t *>(buf);
- for (auto ip = ips.begin(); ip != ips.end(); ++ip) {
- if ((p + 6) > bufSize)
- break;
- const uint8_t *const ipd = reinterpret_cast<const uint8_t *>(ip->rawIpData());
- if (ip->isV4()) {
- b[p++] = AF_INET;
- b[p++] = ipd[0];
- b[p++] = ipd[1];
- b[p++] = ipd[2];
- b[p++] = ipd[3];
- b[p++] = (uint8_t)ip->netmaskBits();
- } else if (ip->isV6()) {
- if ((p + 18) <= bufSize) {
- b[p++] = AF_INET6;
- for (int j = 0; j < 16; ++j)
- b[p++] = ipd[j];
- b[p++] = (uint8_t)ip->netmaskBits();
- }
- }
- }
- return (int)p;
- }
- extern "C" void ZT_GoTap_deviceName(ZT_GoTap *tap, char nbuf[256])
- {
- Utils::scopy(nbuf, 256, reinterpret_cast<EthernetTap *>(tap)->deviceName().c_str());
- }
- extern "C" void ZT_GoTap_setFriendlyName(ZT_GoTap *tap, const char *friendlyName)
- {
- reinterpret_cast<EthernetTap *>(tap)->setFriendlyName(friendlyName);
- }
- extern "C" void ZT_GoTap_setMtu(ZT_GoTap *tap, unsigned int mtu)
- {
- reinterpret_cast<EthernetTap *>(tap)->setMtu(mtu);
- }
- #if defined(IFA_F_SECONDARY) && !defined(IFA_F_TEMPORARY)
- #define IFA_F_TEMPORARY IFA_F_SECONDARY
- #endif
- extern "C" int ZT_isTemporaryV6Address(const char *ifname, const struct sockaddr_storage *a)
- {
- #if defined(IN6_IFF_TEMPORARY) && defined(SIOCGIFAFLAG_IN6)
- static ZT_SOCKET s_tmpV6Socket = ZT_INVALID_SOCKET;
- static std::mutex s_lock;
- std::lock_guard< std::mutex > l(s_lock);
- if (s_tmpV6Socket == ZT_INVALID_SOCKET) {
- s_tmpV6Socket = socket(AF_INET6, SOCK_DGRAM, 0);
- if (s_tmpV6Socket <= 0)
- return 0;
- }
- struct in6_ifreq ifr;
- memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
- memcpy(&(ifr.ifr_addr), a, sizeof(sockaddr_in6));
- if (ioctl(s_tmpV6Socket, SIOCGIFAFLAG_IN6, &ifr) < 0) {
- return 0;
- }
- return ((ifr.ifr_ifru.ifru_flags6 & IN6_IFF_TEMPORARY) != 0) ? 1 : 0;
- #else
- return 0;
- #endif
- }
- extern "C" void *ZT_malloc(unsigned long s)
- { return (void *)malloc((size_t)s); }
|