From 001ba1a4a7e9fe0fbafee4c64b852c8f623ba453 Mon Sep 17 00:00:00 2001 From: Travis LaDuke Date: Wed, 9 Jan 2019 10:19:02 -0800 Subject: [PATCH 001/185] Update link to knowledge base. --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 60f96888..92a26742 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -6,7 +6,7 @@ about: Create a report to help us improve **Alternative, faster ways to get help** If you have just started using ZeroTier, here are some places to get help: - my.zerotier.com has a _Community_ tab. It's a live chat with other users and the developers. -- [ZeroTier Knowledge Base](https://support.zerotier.com/knowledgebase.php?s=MQ__) +- [ZeroTier Knowledge Base](https://zerotier.atlassian.net/wiki/spaces/SD/overview) - www.zerotier.com has a Contact Us button - email contact@zerotier.com From 99c3f02343a7cb704dbde0b2e324451090875d93 Mon Sep 17 00:00:00 2001 From: Travis LaDuke Date: Tue, 12 Mar 2019 13:02:49 -0700 Subject: [PATCH 002/185] Update controller readme Delete `/controller/network//active` docs re: #921 --- controller/README.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/controller/README.md b/controller/README.md index 23bd931d..20fb69a0 100644 --- a/controller/README.md +++ b/controller/README.md @@ -208,14 +208,6 @@ Important notes about rules engine behavior: This returns a JSON object containing all member IDs as keys and their `memberRevisionCounter` values as values. -#### `/controller/network//active` - - * Purpose: Get a set of all active members on this network - * Methods: GET - * Returns: { object } - -This returns an object containing all currently online members and the most recent `recentLog` entries for their last request. - #### `/controller/network//member/
` * Purpose: Create, authorize, or remove a network member From cacdb445c786f97d5d9af200b17665bb171a42d9 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 14 May 2019 13:54:27 -0700 Subject: [PATCH 003/185] Bump protocol version to 10 --- controller/EmbeddedNetworkController.cpp | 4 +- node/Packet.hpp | 51 +++++++++++++----------- node/Peer.cpp | 4 +- node/Peer.hpp | 2 +- 4 files changed, 33 insertions(+), 28 deletions(-) diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index 28115a03..cc012929 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -1620,7 +1620,7 @@ void EmbeddedNetworkController::_request( if ( (ipRangeStartIA.ss_family == AF_INET) && (ipRangeEndIA.ss_family == AF_INET) ) { uint32_t ipRangeStart = Utils::ntoh((uint32_t)(reinterpret_cast(&ipRangeStartIA)->sin_addr.s_addr)); uint32_t ipRangeEnd = Utils::ntoh((uint32_t)(reinterpret_cast(&ipRangeEndIA)->sin_addr.s_addr)); - + if ((ipRangeEnd < ipRangeStart)||(ipRangeStart == 0)) continue; uint32_t ipRangeLen = ipRangeEnd - ipRangeStart; @@ -1671,7 +1671,7 @@ void EmbeddedNetworkController::_request( } } } - + // Issue a certificate of ownership for all static IPs if (nc->staticIpCount) { nc->certificatesOfOwnership[0] = CertificateOfOwnership(nwid,now,identity.address(),1); diff --git a/node/Packet.hpp b/node/Packet.hpp index ef52d87d..8b17bcd0 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -45,31 +45,34 @@ /** * Protocol version -- incremented only for major changes * - * 1 - 0.2.0 ... 0.2.5 - * 2 - 0.3.0 ... 0.4.5 - * + Added signature and originating peer to multicast frame - * + Double size of multicast frame bloom filter - * 3 - 0.5.0 ... 0.6.0 - * + Yet another multicast redesign - * + New crypto completely changes key agreement cipher - * 4 - 0.6.0 ... 1.0.6 - * + BREAKING CHANGE: New identity format based on hashcash design - * 5 - 1.1.0 ... 1.1.5 - * + Supports echo - * + Supports in-band world (root server definition) updates - * + Clustering! (Though this will work with protocol v4 clients.) - * + Otherwise backward compatible with protocol v4 - * 6 - 1.1.5 ... 1.1.10 - * + Network configuration format revisions including binary values - * 7 - 1.1.10 ... 1.1.17 - * + Introduce trusted paths for local SDN use - * 8 - 1.1.17 ... 1.2.0 - * + Multipart network configurations for large network configs - * + Tags and Capabilities - * + Inline push of CertificateOfMembership deprecated - * 9 - 1.2.0 ... CURRENT + * 1 - 0.2.0 ... 0.2.5 + * 2 - 0.3.0 ... 0.4.5 + * + Added signature and originating peer to multicast frame + * + Double size of multicast frame bloom filter + * 3 - 0.5.0 ... 0.6.0 + * + Yet another multicast redesign + * + New crypto completely changes key agreement cipher + * 4 - 0.6.0 ... 1.0.6 + * + BREAKING CHANGE: New identity format based on hashcash design + * 5 - 1.1.0 ... 1.1.5 + * + Supports echo + * + Supports in-band world (root server definition) updates + * + Clustering! (Though this will work with protocol v4 clients.) + * + Otherwise backward compatible with protocol v4 + * 6 - 1.1.5 ... 1.1.10 + * + Network configuration format revisions including binary values + * 7 - 1.1.10 ... 1.1.17 + * + Introduce trusted paths for local SDN use + * 8 - 1.1.17 ... 1.2.0 + * + Multipart network configurations for large network configs + * + Tags and Capabilities + * + Inline push of CertificateOfMembership deprecated + * 9 - 1.2.0 ... 1.2.14 + * 10 - 1.4.0 ... CURRENT + * + Multipath capability and load balancing + * + Certificates of Delegation (CoDs) for full root decentralization */ -#define ZT_PROTO_VERSION 9 +#define ZT_PROTO_VERSION 10 /** * Minimum supported protocol version diff --git a/node/Peer.cpp b/node/Peer.cpp index b0c7db77..95a26003 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -650,10 +650,11 @@ void Peer::introduce(void *const tPtr,const int64_t now,const SharedPtr &o } } -inline void Peer::processBackgroundPeerTasks(int64_t now) +inline void Peer::processBackgroundPeerTasks(const int64_t now) { // Determine current multipath compatibility with other peer if ((now - _lastMultipathCompatibilityCheck) >= ZT_PATH_QUALITY_COMPUTE_INTERVAL) { + // // Cache number of available paths so that we can short-circuit multipath logic elsewhere // // We also take notice of duplicate paths (same IP only) because we may have @@ -663,6 +664,7 @@ inline void Peer::processBackgroundPeerTasks(int64_t now) // // This is done to support the behavior of auto multipath enable/disable // without user intervention. + // int currAlivePathCount = 0; int duplicatePathsFound = 0; for (unsigned int i=0;i Date: Fri, 17 May 2019 10:15:40 -0700 Subject: [PATCH 004/185] Fixed ZT_SDK build issue. Moved ZT_SDK preprocessor directives to more permanent homes --- node/Constants.hpp | 4 ++++ node/NetworkConfig.hpp | 9 ++++++++- node/Node.cpp | 2 +- node/Switch.cpp | 6 +++--- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/node/Constants.hpp b/node/Constants.hpp index e8a3e020..4f45f616 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -482,7 +482,11 @@ /** * Timeout for overall peer activity (measured from last receive) */ +#ifndef ZT_SDK #define ZT_PEER_ACTIVITY_TIMEOUT 500000 +#else +#define ZT_PEER_ACTIVITY_TIMEOUT 30000 +#endif /** * General rate limit timeout for multiple packet types (HELLO, etc.) diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp index 6367b8ec..be8c03dd 100644 --- a/node/NetworkConfig.hpp +++ b/node/NetworkConfig.hpp @@ -274,7 +274,14 @@ public: /** * @return True if frames should not be compressed */ - inline bool disableCompression() const { return ((this->flags & ZT_NETWORKCONFIG_FLAG_DISABLE_COMPRESSION) != 0); } + inline bool disableCompression() const + { +#ifndef ZT_SDK + return ((this->flags & ZT_NETWORKCONFIG_FLAG_DISABLE_COMPRESSION) != 0); +#else + return false; // Compression is disabled for SDK builds since it doesn't play nice with lwIP +#endif + } /** * @return Network type is public (no access control) diff --git a/node/Node.cpp b/node/Node.cpp index ffa4a700..c9f38ad3 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -340,7 +340,7 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64 // Update online status, post status change as event const bool oldOnline = _online; - _online = (((now - lastReceivedFromUpstream) < (ZT_PEER_ACTIVITY_TIMEOUT / (ZT_SDK ? 16 : 1)))||(RR->topology->amUpstream())); + _online = (((now - lastReceivedFromUpstream) < ZT_PEER_ACTIVITY_TIMEOUT)||(RR->topology->amUpstream())); if (oldOnline != _online) postEvent(tptr,_online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE); } catch ( ... ) { diff --git a/node/Switch.cpp b/node/Switch.cpp index eeab051e..55275dc3 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -425,7 +425,7 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr &network,const from.appendTo(outp); outp.append((uint16_t)etherType); outp.append(data,len); - if (!network->config().disableCompression() && !ZT_SDK) + if (!network->config().disableCompression()) outp.compress(); aqm_enqueue(tPtr,network,outp,true,qosBucket); } else { @@ -433,7 +433,7 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr &network,const outp.append(network->id()); outp.append((uint16_t)etherType); outp.append(data,len); - if (!network->config().disableCompression() && !ZT_SDK) + if (!network->config().disableCompression()) outp.compress(); aqm_enqueue(tPtr,network,outp,true,qosBucket); } @@ -490,7 +490,7 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr &network,const from.appendTo(outp); outp.append((uint16_t)etherType); outp.append(data,len); - if (!network->config().disableCompression() && !ZT_SDK) + if (!network->config().disableCompression()) outp.compress(); aqm_enqueue(tPtr,network,outp,true,qosBucket); } else { From 541e5c510ef0c2178777b041a5f81294f9fd5c0d Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Fri, 31 May 2019 11:41:24 -0700 Subject: [PATCH 005/185] CLI improvements (peers, and get/set ip, ip4, ip6, etc) --- one.cpp | 143 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 136 insertions(+), 7 deletions(-) diff --git a/one.cpp b/one.cpp index 1830f8c6..89acaace 100644 --- a/one.cpp +++ b/one.cpp @@ -69,6 +69,7 @@ #include #include #include +#include #include "version.h" #include "include/ZeroTierOne.h" @@ -129,6 +130,7 @@ static void cliPrintHelp(const char *pn,FILE *out) fprintf(out,ZT_EOL_S"Available commands:" ZT_EOL_S); fprintf(out," info - Display status info" ZT_EOL_S); fprintf(out," listpeers - List all peers" ZT_EOL_S); + fprintf(out," peers - List all peers (prettier)" ZT_EOL_S); fprintf(out," listnetworks - List all networks" ZT_EOL_S); fprintf(out," join - Join a network" ZT_EOL_S); fprintf(out," leave - Leave a network" ZT_EOL_S); @@ -137,6 +139,12 @@ static void cliPrintHelp(const char *pn,FILE *out) fprintf(out," listmoons - List moons (federated root sets)" ZT_EOL_S); fprintf(out," orbit - Join a moon via any member root" ZT_EOL_S); fprintf(out," deorbit - Leave a moon" ZT_EOL_S); + fprintf(out,ZT_EOL_S"Available settings:" ZT_EOL_S); + fprintf(out," Settings to use with [get/set] may include property names from " ZT_EOL_S); + fprintf(out," the JSON output of \"zerotier-cli -j listnetworks\". Additionally, " ZT_EOL_S); + fprintf(out," (ip, ip4, ip6, ip6plane, and ip6prefix can be used). For instance:" ZT_EOL_S); + fprintf(out," zerotier-cli get ip6plane will return the 6PLANE address" ZT_EOL_S); + fprintf(out," assigned to this node." ZT_EOL_S); } static std::string cliFixJsonCRs(const std::string &s) @@ -409,6 +417,73 @@ static int cli(int argc,char **argv) printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str()); return 1; } + } else if (command == "peers") { + const unsigned int scode = Http::GET(1024 * 1024 * 16,60000,(const struct sockaddr *)&addr,"/peer",requestHeaders,responseHeaders,responseBody); + + if (scode == 0) { + printf("Error connecting to the ZeroTier service: %s\n\nPlease check that the service is running and that TCP port 9993 can be contacted via 127.0.0.1." ZT_EOL_S, responseBody.c_str()); + return 1; + } + + nlohmann::json j; + try { + j = OSUtils::jsonParse(responseBody); + } catch (std::exception &exc) { + printf("%u %s invalid JSON response (%s)" ZT_EOL_S,scode,command.c_str(),exc.what()); + return 1; + } catch ( ... ) { + printf("%u %s invalid JSON response (unknown exception)" ZT_EOL_S,scode,command.c_str()); + return 1; + } + + if (scode == 200) { + if (json) { + printf("%s" ZT_EOL_S,OSUtils::jsonDump(j).c_str()); + } else { + printf("200 peers\n " ZT_EOL_S); + if (j.is_array()) { + for(unsigned long k=0;k= 0) { + OSUtils::ztsnprintf(ver,sizeof(ver),"%lld.%lld.%lld",vmaj,vmin,vrev); + } else { + ver[0] = '-'; + ver[1] = (char)0; + } + printf("%s %-6s %-6s %5d %s" ZT_EOL_S, + OSUtils::jsonString(p["address"],"-").c_str(), + ver, + OSUtils::jsonString(p["role"],"-").c_str(), + (int)OSUtils::jsonInt(p["latency"],0), + bestPath.c_str()); + } + } + } + return 0; + } else { + printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str()); + return 1; + } } else if (command == "listnetworks") { const unsigned int scode = Http::GET(1024 * 1024 * 16,60000,(const struct sockaddr *)&addr,"/network",requestHeaders,responseHeaders,responseBody); @@ -468,7 +543,7 @@ static int cli(int argc,char **argv) } } else if (command == "join") { if (arg1.length() != 16) { - printf("invalid network id" ZT_EOL_S); + printf("invalid network id" ZT_EOL_S); return 2; } requestHeaders["Content-Type"] = "application/json"; @@ -496,7 +571,7 @@ static int cli(int argc,char **argv) } } else if (command == "leave") { if (arg1.length() != 16) { - printf("invalid network id" ZT_EOL_S); + printf("invalid network id" ZT_EOL_S); return 2; } unsigned int scode = Http::DEL( @@ -594,7 +669,11 @@ static int cli(int argc,char **argv) } } else if (command == "set") { if (arg1.length() != 16) { - printf("invalid network id" ZT_EOL_S); + fprintf(stderr,"invalid format: must be a 16-digit (network) ID\n"); + return 2; + } + if (!arg2.length()) { + fprintf(stderr,"invalid format: include a property name to set\n"); return 2; } std::size_t eqidx = arg2.find('='); @@ -632,16 +711,18 @@ static int cli(int argc,char **argv) } } else if (command == "get") { if (arg1.length() != 16) { - fprintf(stderr,"invalid network ID format, must be a 16-digit hexidecimal number\n"); + fprintf(stderr,"invalid format: must be a 16-digit (network) ID\n"); + return 2; + } + if (!arg2.length()) { + fprintf(stderr,"invalid format: include a property name to get\n"); return 2; } const unsigned int scode = Http::GET(1024 * 1024 * 16,60000,(const struct sockaddr *)&addr,"/network",requestHeaders,responseHeaders,responseBody); - if (scode == 0) { printf("Error connecting to the ZeroTier service: %s\n\nPlease check that the service is running and that TCP port 9993 can be contacted via 127.0.0.1." ZT_EOL_S, responseBody.c_str()); return 1; } - nlohmann::json j; try { j = OSUtils::jsonParse(responseBody); @@ -658,8 +739,56 @@ static int cli(int argc,char **argv) nlohmann::json &n = j[i]; if (n.is_object()) { if (n["id"] == arg1) { - printf("%s\n", OSUtils::jsonString(n[arg2],"-").c_str()); bNetworkFound = true; + std::string aa; + if (arg2 != "ip" && arg2 != "ip4" && arg2 != "ip6" && arg2 != "ip6plane" && arg2 != "ip6prefix") { + aa.append(OSUtils::jsonString(n[arg2],"-")); // Standard network property field + if (aa == "-") { + printf("error, unknown property name\n"); + break; + } + printf("%s\n",aa.c_str()); + break; + } + nlohmann::json &assignedAddresses = n["assignedAddresses"]; + if (assignedAddresses.is_array()) { + int matchingIdxs[ZT_MAX_ZT_ASSIGNED_ADDRESSES]; + int addressCountOfType = 0; + for (int k = 0; k().find(".") != std::string::npos) + || ((arg2.find("ip6") == 0) && addr.get().find(":") != std::string::npos) + || (arg2 == "ip") + ) { + matchingIdxs[addressCountOfType++] = k; + } + } + for (int k=0; k().find("fc") == 0) { + aa.append(addr.get().substr(0,addr.get().find("/"))); + if (k < addressCountOfType-1) aa.append("\n"); + } + } + if (arg2 == "ip6prefix") { + if (addr.get().find("fc") == 0) { + aa.append(addr.get().substr(0,addr.get().find("/")).substr(0,24)); + if (k < addressCountOfType-1) aa.append("\n"); + } + } + } + else { + aa.append(addr.get().substr(0,addr.get().find("/"))); + if (k < addressCountOfType-1) aa.append("\n"); + } + } + } + printf("%s\n",aa.c_str()); } } } From 37d321afc80aaced7e0473e33893787d9a42ef78 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Fri, 31 May 2019 15:10:45 -0700 Subject: [PATCH 006/185] dont spin as much in the onlineNotificationThread --- controller/PostgreSQL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/PostgreSQL.cpp b/controller/PostgreSQL.cpp index 9aa4fbaa..de6b4f46 100644 --- a/controller/PostgreSQL.cpp +++ b/controller/PostgreSQL.cpp @@ -1512,7 +1512,7 @@ void PostgreSQL::onlineNotificationThread() // PQclear(res); // } - std::this_thread::sleep_for(std::chrono::milliseconds(0)); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); } fprintf(stderr, "%s: Fell out of run loop in onlineNotificationThread\n", _myAddressStr.c_str()); PQfinish(conn); From d4199ddb3ef59b8f754129bfc91f91c18f84759c Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Mon, 3 Jun 2019 11:00:04 -0700 Subject: [PATCH 007/185] Commented out RingBuffer::dump() as an alternative solution to PR #952 --- node/RingBuffer.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/node/RingBuffer.hpp b/node/RingBuffer.hpp index e9f17e1c..8b11e9b1 100644 --- a/node/RingBuffer.hpp +++ b/node/RingBuffer.hpp @@ -312,6 +312,7 @@ public: /** * Print the contents of the buffer */ + /* inline void dump() { size_t iterator = begin; @@ -325,6 +326,7 @@ public: } } } + */ }; } // namespace ZeroTier From 87bce1a36bf6599cb94dbe745ce4b38c740de2cd Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 11 Jun 2019 10:53:35 -0700 Subject: [PATCH 008/185] GitHub issue #886 --- make-bsd.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make-bsd.mk b/make-bsd.mk index e226a2dc..8c7a6ad2 100644 --- a/make-bsd.mk +++ b/make-bsd.mk @@ -128,7 +128,7 @@ endif override DEFS+=-DZT_BUILD_PLATFORM=$(ZT_BUILD_PLATFORM) -DZT_BUILD_ARCHITECTURE=$(ZT_ARCHITECTURE) -DZT_SOFTWARE_UPDATE_DEFAULT="\"disable\"" -CXXFLAGS+=$(CFLAGS) -fno-rtti -std=c++11 #-D_GLIBCXX_USE_C99 -D_GLIBCXX_USE_C99_MATH -D_GLIBCXX_USE_C99_MATH_TR1 +CXXFLAGS+=$(CFLAGS) -std=c++11 #-D_GLIBCXX_USE_C99 -D_GLIBCXX_USE_C99_MATH -D_GLIBCXX_USE_C99_MATH_TR1 all: one From ebadc6f2030aa9cd335fa7a6b65e97c7dc24477a Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Tue, 11 Jun 2019 10:54:06 -0700 Subject: [PATCH 009/185] Added s390x arch flags to makefile and ZeroTierOne.h for ticket #950 --- include/ZeroTierOne.h | 3 ++- make-linux.mk | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 324036bd..74600989 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -1096,7 +1096,8 @@ enum ZT_Architecture ZT_ARCHITECTURE_SPARC64 = 12, ZT_ARCHITECTURE_DOTNET_CLR = 13, ZT_ARCHITECTURE_JAVA_JVM = 14, - ZT_ARCHITECTURE_WEB = 15 + ZT_ARCHITECTURE_WEB = 15, + ZT_ARCHITECTURE_S390X = 16 }; /** diff --git a/make-linux.mk b/make-linux.mk index dc238c4f..d0745fe9 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -224,6 +224,9 @@ ifeq ($(CC_MACH),mips64el) ZT_ARCHITECTURE=6 override DEFS+=-DZT_NO_TYPE_PUNNING endif +ifeq ($(CC_MACH),s390x) + ZT_ARCHITECTURE=16 +endif # Fail if system architecture could not be determined ifeq ($(ZT_ARCHITECTURE),999) From 700cc92083bfe0727c4a1ce0f8716dcbdd510da3 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 11 Jun 2019 11:01:12 -0700 Subject: [PATCH 010/185] Indent fix --- controller/EmbeddedNetworkController.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index cc012929..99c664f0 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -1053,7 +1053,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpDELETE( json network,member; _db->get(nwid,network,address,member); - _db->eraseMember(nwid, address); + _db->eraseMember(nwid, address); { std::lock_guard l(_memberStatus_l); From 0bdfad52e7513e65ce2e654a9653e9d63fcd07a9 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 11 Jun 2019 13:51:10 -0700 Subject: [PATCH 011/185] docs --- service/README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/service/README.md b/service/README.md index 3b9901fd..08a3a63f 100644 --- a/service/README.md +++ b/service/README.md @@ -25,7 +25,9 @@ Settings available in `local.conf` (this is not valid JSON, and JSON does not al } }, "settings": { /* Other global settings */ - "primaryPort": 0-65535, /* If set, override default port of 9993 and any command line port */ + "primaryPort": 1-65535, /* If set, override default port of 9993 and any command line port */ + "secondaryPort": 1-65535, /* If set, override default random secondary port */ + "tertiaryPort": 1-65535, /* If set, override default random tertiary port */ "portMappingEnabled": true|false, /* If true (the default), try to use uPnP or NAT-PMP to map ports */ "softwareUpdate": "apply"|"download"|"disable", /* Automatically apply updates, just download, or disable built-in software updates */ "softwareUpdateChannel": "release"|"beta", /* Software update channel */ @@ -33,7 +35,8 @@ Settings available in `local.conf` (this is not valid JSON, and JSON does not al "interfacePrefixBlacklist": [ "XXX",... ], /* Array of interface name prefixes (e.g. eth for eth#) to blacklist for ZT traffic */ "allowManagementFrom": [ "NETWORK/bits", ...] |null, /* If non-NULL, allow JSON/HTTP management from this IP network. Default is 127.0.0.1 only. */ "bind": [ "ip",... ], /* If present and non-null, bind to these IPs instead of to each interface (wildcard IP allowed) */ - "allowTcpFallbackRelay": true|false /* Allow or disallow establishment of TCP relay connections (true by default) */ + "allowTcpFallbackRelay": true|false, /* Allow or disallow establishment of TCP relay connections (true by default) */ + "multipathMode": 0|1|2 /* multipath mode: none (0), random (1), proportional (2) */ } } ``` From 5b2b0887141da25c290608632c2e609764abbf73 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 11 Jun 2019 14:58:23 -0700 Subject: [PATCH 012/185] Cleanup, version bump. --- node/Packet.hpp | 1 - node/Peer.cpp | 20 ---------- node/SelfAwareness.cpp | 85 ------------------------------------------ node/SelfAwareness.hpp | 9 ----- version.h | 4 +- 5 files changed, 2 insertions(+), 117 deletions(-) diff --git a/node/Packet.hpp b/node/Packet.hpp index 8b17bcd0..fcb81489 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -70,7 +70,6 @@ * 9 - 1.2.0 ... 1.2.14 * 10 - 1.4.0 ... CURRENT * + Multipath capability and load balancing - * + Certificates of Delegation (CoDs) for full root decentralization */ #define ZT_PROTO_VERSION 10 diff --git a/node/Peer.cpp b/node/Peer.cpp index 95a26003..da73e9cb 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -208,31 +208,12 @@ void Peer::received( const uint64_t sinceLastPush = now - _lastDirectPathPushSent; if (sinceLastPush >= ZT_DIRECT_PATH_PUSH_INTERVAL) { _lastDirectPathPushSent = now; - - // Start with explicitly known direct endpoint paths. std::vector pathsToPush(RR->node->directPaths()); - -#if 0 - // Do symmetric NAT prediction if we are communicating indirectly. - if (hops > 0) { - std::vector sym(RR->sa->getSymmetricNatPredictions()); - for(unsigned long i=0,added=0;inode->prng() % sym.size()]); - if (std::find(pathsToPush.begin(),pathsToPush.end(),tmp) == pathsToPush.end()) { - pathsToPush.push_back(tmp); - if (++added >= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) - break; - } - } - } -#endif - if (pathsToPush.size() > 0) { std::vector::const_iterator p(pathsToPush.begin()); while (p != pathsToPush.end()) { Packet outp(_id.address(),RR->identity.address(),Packet::VERB_PUSH_DIRECT_PATHS); outp.addSize(2); // leave room for count - unsigned int count = 0; while ((p != pathsToPush.end())&&((outp.size() + 24) < 1200)) { uint8_t addressType = 4; @@ -257,7 +238,6 @@ void Peer::received( ++count; ++p; } - if (count) { outp.setAt(ZT_PACKET_IDX_PAYLOAD,(uint16_t)count); outp.compress(); diff --git a/node/SelfAwareness.cpp b/node/SelfAwareness.cpp index 225d1dc2..0fb9e4a4 100644 --- a/node/SelfAwareness.cpp +++ b/node/SelfAwareness.cpp @@ -124,89 +124,4 @@ void SelfAwareness::clean(int64_t now) } } -#if 0 -std::vector SelfAwareness::getSymmetricNatPredictions() -{ - /* This is based on ideas and strategies found here: - * https://tools.ietf.org/html/draft-takeda-symmetric-nat-traversal-00 - * - * For each IP address reported by a trusted (upstream) peer, we find - * the external port most recently reported by ANY peer for that IP. - * - * We only do any of this for global IPv4 addresses since private IPs - * and IPv6 are not going to have symmetric NAT. - * - * SECURITY NOTE: - * - * We never use IPs reported by non-trusted peers, since this could lead - * to a minor vulnerability whereby a peer could poison our cache with - * bad external surface reports via OK(HELLO) and then possibly coax us - * into suggesting their IP to other peers via PUSH_DIRECT_PATHS. This - * in turn could allow them to MITM flows. - * - * Since flows are encrypted and authenticated they could not actually - * read or modify traffic, but they could gather meta-data for forensics - * purposes or use this as a DOS attack vector. */ - - std::map< uint32_t,unsigned int > maxPortByIp; - InetAddress theOneTrueSurface; - { - Mutex::Lock _l(_phy_m); - - // First check to see if this is a symmetric NAT and enumerate external IPs learned from trusted peers - bool symmetric = false; - { - Hashtable< PhySurfaceKey,PhySurfaceEntry >::Iterator i(_phy); - PhySurfaceKey *k = (PhySurfaceKey *)0; - PhySurfaceEntry *e = (PhySurfaceEntry *)0; - while (i.next(k,e)) { - if ((e->trusted)&&(e->mySurface.ss_family == AF_INET)&&(e->mySurface.ipScope() == InetAddress::IP_SCOPE_GLOBAL)) { - if (!theOneTrueSurface) - theOneTrueSurface = e->mySurface; - else if (theOneTrueSurface != e->mySurface) - symmetric = true; - maxPortByIp[reinterpret_cast(&(e->mySurface))->sin_addr.s_addr] = e->mySurface.port(); - } - } - } - if (!symmetric) - return std::vector(); - - { // Then find the highest issued port per IP - Hashtable< PhySurfaceKey,PhySurfaceEntry >::Iterator i(_phy); - PhySurfaceKey *k = (PhySurfaceKey *)0; - PhySurfaceEntry *e = (PhySurfaceEntry *)0; - while (i.next(k,e)) { - if ((e->mySurface.ss_family == AF_INET)&&(e->mySurface.ipScope() == InetAddress::IP_SCOPE_GLOBAL)) { - const unsigned int port = e->mySurface.port(); - std::map< uint32_t,unsigned int >::iterator mp(maxPortByIp.find(reinterpret_cast(&(e->mySurface))->sin_addr.s_addr)); - if ((mp != maxPortByIp.end())&&(mp->second < port)) - mp->second = port; - } - } - } - } - - std::vector r; - - // Try next port up from max for each - for(std::map< uint32_t,unsigned int >::iterator i(maxPortByIp.begin());i!=maxPortByIp.end();++i) { - unsigned int p = i->second + 1; - if (p > 65535) p -= 64511; - const InetAddress pred(&(i->first),4,p); - if (std::find(r.begin(),r.end(),pred) == r.end()) - r.push_back(pred); - } - - // Try a random port for each -- there are only 65535 so eventually it should work - for(std::map< uint32_t,unsigned int >::iterator i(maxPortByIp.begin());i!=maxPortByIp.end();++i) { - const InetAddress pred(&(i->first),4,1024 + ((unsigned int)RR->node->prng() % 64511)); - if (std::find(r.begin(),r.end(),pred) == r.end()) - r.push_back(pred); - } - - return r; -} -#endif - } // namespace ZeroTier diff --git a/node/SelfAwareness.hpp b/node/SelfAwareness.hpp index c03d4cb6..7940f5ac 100644 --- a/node/SelfAwareness.hpp +++ b/node/SelfAwareness.hpp @@ -64,15 +64,6 @@ public: */ void clean(int64_t now); -#if 0 - /** - * If we appear to be behind a symmetric NAT, get predictions for possible external endpoints - * - * @return Symmetric NAT predictions or empty vector if none - */ - std::vector getSymmetricNatPredictions(); -#endif - private: struct PhySurfaceKey { diff --git a/version.h b/version.h index 01a66ff8..82013819 100644 --- a/version.h +++ b/version.h @@ -35,12 +35,12 @@ /** * Minor version */ -#define ZEROTIER_ONE_VERSION_MINOR 2 +#define ZEROTIER_ONE_VERSION_MINOR 4 /** * Revision */ -#define ZEROTIER_ONE_VERSION_REVISION 13 +#define ZEROTIER_ONE_VERSION_REVISION 0 /** * Build version From c3bfcf560b1db720c9bb08021b50bd31094e737c Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Wed, 12 Jun 2019 13:14:14 -0700 Subject: [PATCH 013/185] Removed check for port number in multipath path replacement logic --- node/Peer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/Peer.cpp b/node/Peer.cpp index 95a26003..3357bb2a 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -157,7 +157,7 @@ void Peer::received( break; } // If the path is the same address and port, simply assume this is a replacement - if ( (_paths[i].p->address().ipsEqual2(path->address()) && (_paths[i].p->address().port() == path->address().port()))) { + if ( (_paths[i].p->address().ipsEqual2(path->address()))) { replacePath = i; break; } From f411eb1651bbfaa276eab02cf368e9fcb3905a15 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Thu, 13 Jun 2019 10:15:45 -0700 Subject: [PATCH 014/185] Remove old RethinkDB.cpp/.hpp files from visual studio project --- windows/ZeroTierOne/ZeroTierOne.vcxproj | 2 -- windows/ZeroTierOne/ZeroTierOne.vcxproj.filters | 6 ------ 2 files changed, 8 deletions(-) diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj b/windows/ZeroTierOne/ZeroTierOne.vcxproj index 8e08d3fb..60c87d3b 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj @@ -30,7 +30,6 @@ - @@ -115,7 +114,6 @@ - diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters b/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters index 22f8aa3e..f7df2034 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters @@ -258,9 +258,6 @@ Source Files\controller - - Source Files\controller - @@ -494,9 +491,6 @@ Header Files\controller - - Header Files\controller - Header Files\node From 47d29ddcaf677a5376f54e6901bcdc38e499b16d Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Thu, 13 Jun 2019 10:27:54 -0700 Subject: [PATCH 015/185] Compiler warning cleanup --- node/Node.cpp | 2 +- node/Path.hpp | 4 ++-- node/Peer.cpp | 10 +++++----- node/RingBuffer.hpp | 2 +- node/Switch.cpp | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/node/Node.cpp b/node/Node.cpp index c9f38ad3..237da463 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -500,7 +500,7 @@ ZT_PeerList *Node::peers() const p->paths[p->pathCount].trustedPathId = RR->topology->getOutboundPathTrust((*path)->address()); p->paths[p->pathCount].expired = 0; p->paths[p->pathCount].preferred = ((*path) == bestp) ? 1 : 0; - p->paths[p->pathCount].latency = (*path)->latency(); + p->paths[p->pathCount].latency = (float)(*path)->latency(); p->paths[p->pathCount].packetDelayVariance = (*path)->packetDelayVariance(); p->paths[p->pathCount].throughputDisturbCoeff = (*path)->throughputDisturbanceCoefficient(); p->paths[p->pathCount].packetErrorRatio = (*path)->packetErrorRatio(); diff --git a/node/Path.hpp b/node/Path.hpp index e1e65cb4..5b966f6b 100644 --- a/node/Path.hpp +++ b/node/Path.hpp @@ -351,7 +351,7 @@ public: _unackedBytes = (ackedBytes > _unackedBytes) ? 0 : _unackedBytes - ackedBytes; int64_t timeSinceThroughputEstimate = (now - _lastThroughputEstimation); if (timeSinceThroughputEstimate >= ZT_PATH_THROUGHPUT_MEASUREMENT_INTERVAL) { - uint64_t throughput = (float)(_bytesAckedSinceLastThroughputEstimation * 8) / ((float)timeSinceThroughputEstimate / (float)1000); + uint64_t throughput = (uint64_t)((float)(_bytesAckedSinceLastThroughputEstimation * 8) / ((float)timeSinceThroughputEstimate / (float)1000)); _throughputSamples.push(throughput); _maxLifetimeThroughput = throughput > _maxLifetimeThroughput ? throughput : _maxLifetimeThroughput; _lastThroughputEstimation = now; @@ -416,7 +416,7 @@ public: if (it != _outQoSRecords.end()) { uint16_t rtt = (uint16_t)(now - it->second); uint16_t rtt_compensated = rtt - rx_ts[j]; - float latency = rtt_compensated / 2.0; + uint16_t latency = rtt_compensated / 2; updateLatency(latency, now); _outQoSRecords.erase(it); } diff --git a/node/Peer.cpp b/node/Peer.cpp index a0b0c1c4..029e45e7 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -285,7 +285,7 @@ void Peer::computeAggregateProportionalAllocation(int64_t now) for(unsigned int i=0;ilastComputedStability(); - relThroughput[i] = _paths[i].p->maxLifetimeThroughput(); + relThroughput[i] = (float)_paths[i].p->maxLifetimeThroughput(); maxStability = relStability[i] > maxStability ? relStability[i] : maxStability; maxThroughput = relThroughput[i] > maxThroughput ? relThroughput[i] : maxThroughput; maxScope = _paths[i].p->ipScope() > maxScope ? _paths[i].p->ipScope() : maxScope; @@ -296,7 +296,7 @@ void Peer::computeAggregateProportionalAllocation(int64_t now) if (_paths[i].p) { relStability[i] /= maxStability ? maxStability : 1; relThroughput[i] /= maxThroughput ? maxThroughput : 1; - float normalized_ma = Utils::normalize(_paths[i].p->ackAge(now), 0, ZT_PATH_MAX_AGE, 0, 10); + float normalized_ma = Utils::normalize((float)_paths[i].p->ackAge(now), 0, ZT_PATH_MAX_AGE, 0, 10); float age_contrib = exp((-1)*normalized_ma); float relScope = ((float)(_paths[i].p->ipScope()+1) / (maxScope + 1)); float relQuality = @@ -314,7 +314,7 @@ void Peer::computeAggregateProportionalAllocation(int64_t now) // Convert set of relative performances into an allocation set for(uint16_t i=0;iupdateComponentAllocationOfAggregateLink((_paths[i].p->relativeQuality() / totalRelativeQuality) * 255); + _paths[i].p->updateComponentAllocationOfAggregateLink((unsigned char)((_paths[i].p->relativeQuality() / totalRelativeQuality) * 255)); } } } @@ -327,7 +327,7 @@ int Peer::computeAggregateLinkPacketDelayVariance() pdv += _paths[i].p->relativeQuality() * _paths[i].p->packetDelayVariance(); } } - return pdv; + return (int)pdv; } int Peer::computeAggregateLinkMeanLatency() @@ -337,7 +337,7 @@ int Peer::computeAggregateLinkMeanLatency() for(unsigned int i=0;irelativeQuality() * _paths[i].p->meanLatency(); + ml += (int)(_paths[i].p->relativeQuality() * _paths[i].p->meanLatency()); } } return ml / pathCount; diff --git a/node/RingBuffer.hpp b/node/RingBuffer.hpp index 8b11e9b1..0f29a89a 100644 --- a/node/RingBuffer.hpp +++ b/node/RingBuffer.hpp @@ -268,7 +268,7 @@ public: for (size_t i=0; i &network, Packet & uint64_t Switch::control_law(uint64_t t, int count) { - return t + ZT_QOS_INTERVAL / sqrt(count); + return (uint64_t)(t + ZT_QOS_INTERVAL / sqrt(count)); } Switch::dqr Switch::dodequeue(ManagedQueue *q, uint64_t now) From eb84d61debd267b3446cd2f1a36d7f4fd354674a Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Thu, 13 Jun 2019 10:35:54 -0700 Subject: [PATCH 016/185] remove these from jenkins for now --- Jenkinsfile | 62 ++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index e729c334..9e9cb51a 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -24,42 +24,42 @@ parallel 'centos7': { throw err } } -}, 'android-ndk': { - node('android-ndk') { - try { - checkout scm +// }, 'android-ndk': { +// node('android-ndk') { +// try { +// checkout scm - stage('Build Android NDK') { - sh "/android/android-ndk-r15b/ndk-build -C $WORKSPACE/java ZT1=${WORKSPACE}" - } - } - catch (err) { - currentBuild.result = "FAILURE" - mattermostSend color: '#ff0000', message: "${env.JOB_NAME} broken on Android NDK (<${env.BUILD_URL}|Open>)" +// stage('Build Android NDK') { +// sh "/android/android-ndk-r15b/ndk-build -C $WORKSPACE/java ZT1=${WORKSPACE}" +// } +// } +// catch (err) { +// currentBuild.result = "FAILURE" +// mattermostSend color: '#ff0000', message: "${env.JOB_NAME} broken on Android NDK (<${env.BUILD_URL}|Open>)" - throw err - } - } -}, 'macOS': { - node('macOS') { - try { - checkout scm +// throw err +// } +// } +// }, 'macOS': { +// node('macOS') { +// try { +// checkout scm - stage('Build macOS') { - sh 'make -f make-mac.mk' - } +// stage('Build macOS') { +// sh 'make -f make-mac.mk' +// } - stage('Build macOS UI') { - sh 'cd macui && xcodebuild -target "ZeroTier One" -configuration Debug' - } - } - catch (err) { - currentBuild.result = "FAILURE" - mattermostSend color: '#ff0000', message: "${env.JOB_NAME} broken on macOS (<${env.BUILD_URL}|Open>)" +// stage('Build macOS UI') { +// sh 'cd macui && xcodebuild -target "ZeroTier One" -configuration Debug' +// } +// } +// catch (err) { +// currentBuild.result = "FAILURE" +// mattermostSend color: '#ff0000', message: "${env.JOB_NAME} broken on macOS (<${env.BUILD_URL}|Open>)" - throw err - } - } +// throw err +// } +// } }, 'windows': { node('windows') { try { From 3b188ba672559ff80264a8fab32699ebdbf928fe Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Thu, 13 Jun 2019 10:38:42 -0700 Subject: [PATCH 017/185] no message --- Jenkinsfile | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 9e9cb51a..88989327 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -60,25 +60,25 @@ parallel 'centos7': { // throw err // } // } -}, 'windows': { - node('windows') { - try { - checkout scm +// }, 'windows': { +// node('windows') { +// try { +// checkout scm - stage('Build Windows') { - bat '''CALL "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\vcvarsall.bat" amd64 -git clean -dfx -msbuild windows\\ZeroTierOne.sln -''' - } - } - catch (err) { - currentBuild.result = "FAILURE" - mattermostSend color: '#ff0000', message: "${env.JOB_NAME} broken on Windows (<${env.BUILD_URL}|Open>)" +// stage('Build Windows') { +// bat '''CALL "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\vcvarsall.bat" amd64 +// git clean -dfx +// msbuild windows\\ZeroTierOne.sln +// ''' +// } +// } +// catch (err) { +// currentBuild.result = "FAILURE" +// mattermostSend color: '#ff0000', message: "${env.JOB_NAME} broken on Windows (<${env.BUILD_URL}|Open>)" - throw err - } - } +// throw err +// } +// } } mattermostSend color: "#00ff00", message: "${env.JOB_NAME} #${env.BUILD_NUMBER} Complete (<${env.BUILD_URL}|Show More...>)" From ce2338c24a46558a2e0fdb7ebbcf2e6ce9c8b615 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 13 Jun 2019 12:52:38 -0700 Subject: [PATCH 018/185] Fix null ptr on managed routes if no IPs are set. --- service/OneService.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/service/OneService.cpp b/service/OneService.cpp index 17f7debc..b3d6739a 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -190,6 +190,8 @@ namespace ZeroTier { namespace { +static const InetAddress NULL_INET_ADDR; + // Fake TLS hello for TCP tunnel outgoing connections (TUNNELED mode) static const char ZT_TCP_TUNNEL_HELLO[9] = { 0x17,0x03,0x03,0x00,0x04,(char)ZEROTIER_ONE_VERSION_MAJOR,(char)ZEROTIER_ONE_VERSION_MINOR,(char)((ZEROTIER_ONE_VERSION_REVISION >> 8) & 0xff),(char)(ZEROTIER_ONE_VERSION_REVISION & 0xff) }; @@ -1855,7 +1857,7 @@ public: const InetAddress *const target = reinterpret_cast(&(n.config.routes[i].target)); const InetAddress *const via = reinterpret_cast(&(n.config.routes[i].via)); - InetAddress *src = NULL; + const InetAddress *src = NULL; for (unsigned int j=0; j(&(n.config.assignedAddresses[j])); if (target->isV4() && tmp->isV4()) { @@ -1866,6 +1868,8 @@ public: break; } } + if (!src) + src = &NULL_INET_ADDR; if ( (!checkIfManagedIsAllowed(n,*target)) || ((via->ss_family == target->ss_family)&&(matchIpOnly(myIps,*via))) ) continue; From 9c51ce9c40c1eadd20e943f74f0694a0a6a05ae1 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 17 Jun 2019 13:32:41 -0700 Subject: [PATCH 019/185] Windows build fixes, fix double/float types to get rid of warnings. --- node/Path.hpp | 8 ++++---- node/Peer.cpp | 14 +++++++------- osdep/Binder.hpp | 2 +- windows/ZeroTierOne/ZeroTierOne.vcxproj | 4 ++++ windows/ZeroTierOne/ZeroTierOne.vcxproj.filters | 12 ++++++++++++ 5 files changed, 28 insertions(+), 12 deletions(-) diff --git a/node/Path.hpp b/node/Path.hpp index 5b966f6b..9203eee3 100644 --- a/node/Path.hpp +++ b/node/Path.hpp @@ -440,7 +440,7 @@ public: uint64_t id = it->first; memcpy(qosBuffer, &id, sizeof(uint64_t)); qosBuffer+=sizeof(uint64_t); - uint16_t holdingTime = (now - it->second); + uint16_t holdingTime = (uint16_t)(now - it->second); memcpy(qosBuffer, &holdingTime, sizeof(uint16_t)); qosBuffer+=sizeof(uint16_t); len+=sizeof(uint64_t)+sizeof(uint16_t); @@ -592,11 +592,11 @@ public: float throughput_cv = _throughputSamples.mean() > 0 ? _throughputSamples.stddev() / _throughputSamples.mean() : 1; // Form an exponential cutoff and apply contribution weights - float pdv_contrib = exp((-1)*normalized_pdv) * ZT_PATH_CONTRIB_PDV; - float latency_contrib = exp((-1)*normalized_la) * ZT_PATH_CONTRIB_LATENCY; + float pdv_contrib = expf((-1.0f)*normalized_pdv) * (float)ZT_PATH_CONTRIB_PDV; + float latency_contrib = expf((-1.0f)*normalized_la) * (float)ZT_PATH_CONTRIB_LATENCY; // Throughput Disturbance Coefficient - float throughput_disturbance_contrib = exp((-1)*throughput_cv) * ZT_PATH_CONTRIB_THROUGHPUT_DISTURBANCE; + float throughput_disturbance_contrib = expf((-1.0f)*throughput_cv) * (float)ZT_PATH_CONTRIB_THROUGHPUT_DISTURBANCE; _throughputDisturbanceSamples.push(throughput_cv); _lastComputedThroughputDistCoeff = _throughputDisturbanceSamples.mean(); diff --git a/node/Peer.cpp b/node/Peer.cpp index 029e45e7..a053ee48 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -300,13 +300,13 @@ void Peer::computeAggregateProportionalAllocation(int64_t now) float age_contrib = exp((-1)*normalized_ma); float relScope = ((float)(_paths[i].p->ipScope()+1) / (maxScope + 1)); float relQuality = - (relStability[i] * ZT_PATH_CONTRIB_STABILITY) - + (fmax(1, relThroughput[i]) * ZT_PATH_CONTRIB_THROUGHPUT) - + relScope * ZT_PATH_CONTRIB_SCOPE; + (relStability[i] * (float)ZT_PATH_CONTRIB_STABILITY) + + (fmaxf(1.0f, relThroughput[i]) * (float)ZT_PATH_CONTRIB_THROUGHPUT) + + relScope * (float)ZT_PATH_CONTRIB_SCOPE; relQuality *= age_contrib; // Arbitrary cutoffs - relQuality = relQuality > (1.00 / 100.0) ? relQuality : 0.0; - relQuality = relQuality < (99.0 / 100.0) ? relQuality : 1.0; + relQuality = relQuality > (1.00f / 100.0f) ? relQuality : 0.0f; + relQuality = relQuality < (99.0f / 100.0f) ? relQuality : 1.0f; totalRelativeQuality += relQuality; _paths[i].p->updateRelativeQuality(relQuality); } @@ -479,8 +479,8 @@ char *Peer::interfaceListStr() if (_paths[i].p && _paths[i].p->alive(now)) { int ipv = _paths[i].p->address().isV4(); // If this is acting as an aggregate link, check allocations - float targetAllocation = 1.0 / alivePathCount; - float currentAllocation = 1.0; + float targetAllocation = 1.0f / (float)alivePathCount; + float currentAllocation = 1.0f; if (alivePathCount > 1) { currentAllocation = (float)_pathChoiceHist.countValue(i) / (float)_pathChoiceHist.count(); if (fabs(targetAllocation - currentAllocation) > ZT_PATH_IMBALANCE_THRESHOLD) { diff --git a/osdep/Binder.hpp b/osdep/Binder.hpp index 10ffbb06..bf7aef28 100644 --- a/osdep/Binder.hpp +++ b/osdep/Binder.hpp @@ -389,7 +389,7 @@ public: _bindings[_bindingCount].udpSock = udps; _bindings[_bindingCount].tcpListenSock = tcps; _bindings[_bindingCount].address = ii->first; - phy.setIfName(udps, (char*)ii->second.c_str(), ii->second.length()); + phy.setIfName(udps,(char*)ii->second.c_str(),(int)ii->second.length()); ++_bindingCount; } } else { diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj b/windows/ZeroTierOne/ZeroTierOne.vcxproj index 60c87d3b..3f6397ca 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj @@ -30,6 +30,8 @@ + + @@ -114,6 +116,8 @@ + + diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters b/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters index f7df2034..1fcf7b69 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters @@ -258,6 +258,12 @@ Source Files\controller + + Source Files\controller + + + Source Files\controller + @@ -494,6 +500,12 @@ Header Files\node + + Header Files\controller + + + Header Files\controller + From f66fac398297c6153fa223d49efac7f08930eb99 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 17 Jun 2019 13:48:42 -0700 Subject: [PATCH 020/185] Win32 build fix --- ext/installfiles/windows/ZeroTier One.aip | 12 ++++++------ windows/ZeroTierOne.sln | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ext/installfiles/windows/ZeroTier One.aip b/ext/installfiles/windows/ZeroTier One.aip index de973bf1..a82263e2 100644 --- a/ext/installfiles/windows/ZeroTier One.aip +++ b/ext/installfiles/windows/ZeroTier One.aip @@ -27,10 +27,10 @@ - + - + @@ -64,7 +64,7 @@ - + @@ -82,7 +82,7 @@ - + @@ -454,10 +454,10 @@ - + - + diff --git a/windows/ZeroTierOne.sln b/windows/ZeroTierOne.sln index 1ccdf88b..76d579a8 100644 --- a/windows/ZeroTierOne.sln +++ b/windows/ZeroTierOne.sln @@ -106,9 +106,9 @@ Global {B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Release|Mixed Platforms.Build.0 = Release|Win32 {B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Release|Mixed Platforms.Deploy.0 = Release|Win32 - {B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Release|Win32.ActiveCfg = Release|x64 - {B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Release|Win32.Build.0 = Release|x64 - {B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Release|Win32.Deploy.0 = Release|x64 + {B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Release|Win32.ActiveCfg = Release|Win32 + {B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Release|Win32.Build.0 = Release|Win32 + {B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Release|Win32.Deploy.0 = Release|Win32 {B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Release|x64.ActiveCfg = Release|x64 {B00A4957-5977-4AC1-9EF4-571DC27EADA2}.SingleImage|Any CPU.ActiveCfg = Release|Win32 {B00A4957-5977-4AC1-9EF4-571DC27EADA2}.SingleImage|Mixed Platforms.ActiveCfg = Release|Win32 From 523df47a654efffd22168384d9c8b2e8b26aafb0 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 17 Jun 2019 14:02:35 -0700 Subject: [PATCH 021/185] Check for null data ptr --- service/OneService.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/OneService.cpp b/service/OneService.cpp index b3d6739a..566b4750 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -2449,7 +2449,7 @@ public: return; } - if (len >= 0) { + if ((len >= 0)&&(data)) { // Check to see if we've already written this first. This reduces // redundant writes and I/O overhead on most platforms and has // little effect on others. From 2dc783214c25cdba80b2188e91a973cc8968aee4 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 17 Jun 2019 14:38:27 -0700 Subject: [PATCH 022/185] Allocate outp on heap in Peer. --- node/Peer.cpp | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/node/Peer.cpp b/node/Peer.cpp index a053ee48..cbd07799 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -212,10 +212,10 @@ void Peer::received( if (pathsToPush.size() > 0) { std::vector::const_iterator p(pathsToPush.begin()); while (p != pathsToPush.end()) { - Packet outp(_id.address(),RR->identity.address(),Packet::VERB_PUSH_DIRECT_PATHS); - outp.addSize(2); // leave room for count + Packet *outp = new Packet(_id.address(),RR->identity.address(),Packet::VERB_PUSH_DIRECT_PATHS); + outp->addSize(2); // leave room for count unsigned int count = 0; - while ((p != pathsToPush.end())&&((outp.size() + 24) < 1200)) { + while ((p != pathsToPush.end())&&((outp->size() + 24) < 1200)) { uint8_t addressType = 4; switch(p->ss_family) { case AF_INET: @@ -228,22 +228,23 @@ void Peer::received( continue; } - outp.append((uint8_t)0); // no flags - outp.append((uint16_t)0); // no extensions - outp.append(addressType); - outp.append((uint8_t)((addressType == 4) ? 6 : 18)); - outp.append(p->rawIpData(),((addressType == 4) ? 4 : 16)); - outp.append((uint16_t)p->port()); + outp->append((uint8_t)0); // no flags + outp->append((uint16_t)0); // no extensions + outp->append(addressType); + outp->append((uint8_t)((addressType == 4) ? 6 : 18)); + outp->append(p->rawIpData(),((addressType == 4) ? 4 : 16)); + outp->append((uint16_t)p->port()); ++count; ++p; } if (count) { - outp.setAt(ZT_PACKET_IDX_PAYLOAD,(uint16_t)count); - outp.compress(); - outp.armor(_key,true); - path->send(RR,tPtr,outp.data(),outp.size(),now); + outp->setAt(ZT_PACKET_IDX_PAYLOAD,(uint16_t)count); + outp->compress(); + outp->armor(_key,true); + path->send(RR,tPtr,outp->data(),outp->size(),now); } + delete outp; } } } From aa831dd843f21c092e99cbdd37496b2c668f4598 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 17 Jun 2019 14:55:33 -0700 Subject: [PATCH 023/185] More stack->heap... --- node/Network.cpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/node/Network.cpp b/node/Network.cpp index 92b10671..9f78ec68 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -1493,25 +1493,27 @@ void Network::_sendUpdatesToMembers(void *tPtr,const MulticastGroup *const newMu void Network::_announceMulticastGroupsTo(void *tPtr,const Address &peer,const std::vector &allMulticastGroups) { // Assumes _lock is locked - Packet outp(peer,RR->identity.address(),Packet::VERB_MULTICAST_LIKE); + Packet *const outp = new Packet(peer,RR->identity.address(),Packet::VERB_MULTICAST_LIKE); for(std::vector::const_iterator mg(allMulticastGroups.begin());mg!=allMulticastGroups.end();++mg) { - if ((outp.size() + 24) >= ZT_PROTO_MAX_PACKET_LENGTH) { - outp.compress(); - RR->sw->send(tPtr,outp,true); - outp.reset(peer,RR->identity.address(),Packet::VERB_MULTICAST_LIKE); + if ((outp->size() + 24) >= ZT_PROTO_MAX_PACKET_LENGTH) { + outp->compress(); + RR->sw->send(tPtr,*outp,true); + outp->reset(peer,RR->identity.address(),Packet::VERB_MULTICAST_LIKE); } // network ID, MAC, ADI - outp.append((uint64_t)_id); - mg->mac().appendTo(outp); - outp.append((uint32_t)mg->adi()); + outp->append((uint64_t)_id); + mg->mac().appendTo(*outp); + outp->append((uint32_t)mg->adi()); } - if (outp.size() > ZT_PROTO_MIN_PACKET_LENGTH) { - outp.compress(); - RR->sw->send(tPtr,outp,true); + if (outp->size() > ZT_PROTO_MIN_PACKET_LENGTH) { + outp->compress(); + RR->sw->send(tPtr,*outp,true); } + + delete outp; } std::vector Network::_allMulticastGroups() const From e2900f4f3c8631e6d777de7c4f79f9c5cb1d1fec Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 17 Jun 2019 15:23:52 -0700 Subject: [PATCH 024/185] Fix valgrind warning... not sure if it is an actual issue. --- node/CertificateOfOwnership.hpp | 27 ++++++++------------------- node/Network.cpp | 2 +- 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/node/CertificateOfOwnership.hpp b/node/CertificateOfOwnership.hpp index bae7ef2f..fdffec3b 100644 --- a/node/CertificateOfOwnership.hpp +++ b/node/CertificateOfOwnership.hpp @@ -67,29 +67,18 @@ public: THING_IPV6_ADDRESS = 3 }; - CertificateOfOwnership() : - _networkId(0), - _ts(0), - _flags(0), - _id(0), - _thingCount(0) + CertificateOfOwnership() { - memset(_thingTypes,0,sizeof(_thingTypes)); - memset(_thingValues,0,sizeof(_thingValues)); - memset(_signature.data,0,sizeof(_signature.data)); + memset(reinterpret_cast(this),0,sizeof(CertificateOfOwnership)); } - CertificateOfOwnership(const uint64_t nwid,const int64_t ts,const Address &issuedTo,const uint32_t id) : - _networkId(nwid), - _ts(ts), - _flags(0), - _id(id), - _thingCount(0), - _issuedTo(issuedTo) + CertificateOfOwnership(const uint64_t nwid,const int64_t ts,const Address &issuedTo,const uint32_t id) { - memset(_thingTypes,0,sizeof(_thingTypes)); - memset(_thingValues,0,sizeof(_thingValues)); - memset(_signature.data,0,sizeof(_signature.data)); + memset(reinterpret_cast(this),0,sizeof(CertificateOfOwnership)); + _networkId = nwid; + _ts = ts; + _id = id; + _issuedTo = issuedTo; } inline uint64_t networkId() const { return _networkId; } diff --git a/node/Network.cpp b/node/Network.cpp index 9f78ec68..1e151b61 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -1036,7 +1036,7 @@ int Network::setConfiguration(void *tPtr,const NetworkConfig &nconf,bool saveToD _portError = RR->node->configureVirtualNetworkPort(tPtr,_id,&_uPtr,(oldPortInitialized) ? ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE : ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP,&ctmp); if (saveToDisk) { - Dictionary *d = new Dictionary(); + Dictionary *const d = new Dictionary(); try { if (nconf.toDictionary(*d,false)) { uint64_t tmp[2]; From c5a07c7f20dc54d88a2f6b8b5c4462510b042325 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 17 Jun 2019 15:28:02 -0700 Subject: [PATCH 025/185] More stack->heap --- service/OneService.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/service/OneService.cpp b/service/OneService.cpp index 566b4750..0043204c 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -2455,11 +2455,16 @@ public: // little effect on others. f = fopen(p,"rb"); if (f) { - char buf[65535]; - long l = (long)fread(buf,1,sizeof(buf),f); - fclose(f); - if ((l == (long)len)&&(memcmp(data,buf,l) == 0)) - return; + char *const buf = (char *)malloc(len*4); + if (buf) { + long l = (long)fread(buf,1,(size_t)(len*4),f); + fclose(f); + if ((l == (long)len)&&(memcmp(data,buf,l) == 0)) { + free(buf); + return; + } + free(buf); + } } f = fopen(p,"wb"); From 4e2439bd127c399bc31a44611c5226ed51681728 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Mon, 17 Jun 2019 15:32:21 -0700 Subject: [PATCH 026/185] Don't call _phy->getIfName if localSocket is -1 --- node/Path.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/node/Path.hpp b/node/Path.hpp index 5b966f6b..f0198bde 100644 --- a/node/Path.hpp +++ b/node/Path.hpp @@ -158,7 +158,9 @@ public: { memset(_ifname, 0, 16); memset(_addrString, 0, sizeof(_addrString)); - _phy->getIfName((PhySocket *)((uintptr_t)_localSocket), _ifname, 16); + if (_localSocket != -1) { + _phy->getIfName((PhySocket *) ((uintptr_t) _localSocket), _ifname, 16); + } } /** From b041de831a6d6a68c138cb97b0ad7549712d9516 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 17 Jun 2019 15:50:05 -0700 Subject: [PATCH 027/185] More stack->heap --- node/OutboundMulticast.cpp | 4 ++-- node/OutboundMulticast.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/node/OutboundMulticast.cpp b/node/OutboundMulticast.cpp index dc513e84..5b5b726b 100644 --- a/node/OutboundMulticast.cpp +++ b/node/OutboundMulticast.cpp @@ -91,8 +91,8 @@ void OutboundMulticast::sendOnly(const RuntimeEnvironment *RR,void *tPtr,const A _packet.setDestination(toAddr2); RR->node->expectReplyTo(_packet.packetId()); - Packet tmp(_packet); // make a copy of packet so as not to garble the original -- GitHub issue #461 - RR->sw->send(tPtr,tmp,true); + _tmp = _packet; + RR->sw->send(tPtr,_tmp,true); } } diff --git a/node/OutboundMulticast.hpp b/node/OutboundMulticast.hpp index c549eacf..42063995 100644 --- a/node/OutboundMulticast.hpp +++ b/node/OutboundMulticast.hpp @@ -161,7 +161,7 @@ private: unsigned int _limit; unsigned int _frameLen; unsigned int _etherType; - Packet _packet; + Packet _packet,_tmp; std::vector
_alreadySentTo; uint8_t _frameData[ZT_MAX_MTU]; }; From bb0808c99c37eaf8cfbf8d90647933d5899f48a6 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 19 Jun 2019 10:19:59 -0700 Subject: [PATCH 028/185] Remove current multithreaded receive path, which is not that efficient. We will do something better in the future. --- service/OneService.cpp | 85 ++++++------------------------------------ 1 file changed, 12 insertions(+), 73 deletions(-) diff --git a/service/OneService.cpp b/service/OneService.cpp index 0043204c..63ee3373 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -147,6 +147,10 @@ namespace ZeroTier { typedef BSDEthernetTap EthernetTap; } #endif // ZT_USE_TEST_TAP +#ifndef ZT_SOFTWARE_UPDATE_DEFAULT +#define ZT_SOFTWARE_UPDATE_DEFAULT "disable" +#endif + // Sanity limits for HTTP #define ZT_MAX_HTTP_MESSAGE_SIZE (1024 * 1024 * 64) #define ZT_MAX_HTTP_CONNECTIONS 65536 @@ -477,12 +481,6 @@ public: unsigned int _tertiaryPort; volatile unsigned int _udpPortPickerCounter; - unsigned long _incomingPacketConcurrency; - std::vector _incomingPacketMemoryPool; - BlockingQueue _incomingPacketQueue; - std::vector _incomingPacketThreads; - Mutex _incomingPacketMemoryPoolLock,_incomingPacketThreadsLock; - // Local configuration and memo-ized information from it json _localConfig; Hashtable< uint64_t,std::vector > _v4Hints; @@ -615,43 +613,6 @@ public: _ports[1] = 0; _ports[2] = 0; - _incomingPacketConcurrency = std::max((unsigned long)1,std::min((unsigned long)16,(unsigned long)std::thread::hardware_concurrency())); - char *envPool = std::getenv("INCOMING_PACKET_CONCURRENCY"); - if (envPool != NULL) { - int tmp = atoi(envPool); - if (tmp > 0) { - _incomingPacketConcurrency = tmp; - } - } - for(unsigned long t=0;t<_incomingPacketConcurrency;++t) { - _incomingPacketThreads.push_back(std::thread([this]() { - OneServiceIncomingPacket *pkt = nullptr; - for(;;) { - if (!_incomingPacketQueue.get(pkt)) - break; - if (!pkt) - break; - if (!_run) - break; - - const ZT_ResultCode rc = _node->processWirePacket(nullptr,pkt->now,pkt->sock,&(pkt->from),pkt->data,pkt->size,&_nextBackgroundTaskDeadline); - { - Mutex::Lock l(_incomingPacketMemoryPoolLock); - _incomingPacketMemoryPool.push_back(pkt); - } - if (ZT_ResultCode_isFatal(rc)) { - char tmp[256]; - OSUtils::ztsnprintf(tmp,sizeof(tmp),"fatal error code from processWirePacket: %d",(int)rc); - Mutex::Lock _l(_termReason_m); - _termReason = ONE_UNRECOVERABLE_ERROR; - _fatalErrorMessage = tmp; - this->terminate(); - break; - } - } - })); - } - #if ZT_VAULT_SUPPORT curl_global_init(CURL_GLOBAL_DEFAULT); #endif @@ -659,12 +620,6 @@ public: virtual ~OneServiceImpl() { - _incomingPacketQueue.stop(); - _incomingPacketThreadsLock.lock(); - for(auto t=_incomingPacketThreads.begin();t!=_incomingPacketThreads.end();++t) - t->join(); - _incomingPacketThreadsLock.unlock(); - _binder.closeAll(_phy); _phy.close(_localControlSocket4); _phy.close(_localControlSocket6); @@ -673,13 +628,6 @@ public: curl_global_cleanup(); #endif - _incomingPacketMemoryPoolLock.lock(); - while (!_incomingPacketMemoryPool.empty()) { - delete _incomingPacketMemoryPool.back(); - _incomingPacketMemoryPool.pop_back(); - } - _incomingPacketMemoryPoolLock.unlock(); - #ifdef ZT_USE_MINIUPNPC delete _portMapper; #endif @@ -1917,24 +1865,15 @@ public: const uint64_t now = OSUtils::now(); if ((len >= 16)&&(reinterpret_cast(from)->ipScope() == InetAddress::IP_SCOPE_GLOBAL)) _lastDirectReceiveFromGlobal = now; - - OneServiceIncomingPacket *pkt; - _incomingPacketMemoryPoolLock.lock(); - if (_incomingPacketMemoryPool.empty()) { - pkt = new OneServiceIncomingPacket; - } else { - pkt = _incomingPacketMemoryPool.back(); - _incomingPacketMemoryPool.pop_back(); + const ZT_ResultCode rc = _node->processWirePacket(nullptr,now,reinterpret_cast(sock),reinterpret_cast(from),data,len,&_nextBackgroundTaskDeadline); + if (ZT_ResultCode_isFatal(rc)) { + char tmp[256]; + OSUtils::ztsnprintf(tmp,sizeof(tmp),"fatal error code from processWirePacket: %d",(int)rc); + Mutex::Lock _l(_termReason_m); + _termReason = ONE_UNRECOVERABLE_ERROR; + _fatalErrorMessage = tmp; + this->terminate(); } - _incomingPacketMemoryPoolLock.unlock(); - - pkt->now = now; - pkt->sock = reinterpret_cast(sock); - memcpy(&(pkt->from),from,sizeof(struct sockaddr_storage)); - pkt->size = (unsigned int)len; - memcpy(pkt->data,data,len); - - _incomingPacketQueue.postLimit(pkt,16 * _incomingPacketConcurrency); } inline void phyOnTcpConnect(PhySocket *sock,void **uptr,bool success) From af5d3a7f0bdc76d6fc4387c4fef8aaaa78977915 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Thu, 20 Jun 2019 14:17:38 -0700 Subject: [PATCH 029/185] dockerfile updates --- docker/Dockerfile | 2 +- docker/main.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index f13a2bc6..0f0750c6 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -4,7 +4,7 @@ MAINTAINER Adam Ierymekno , Grant Limberg Date: Thu, 20 Jun 2019 15:20:42 -0700 Subject: [PATCH 030/185] Windows build changes for 1.2.99 (1.4.0pre) --- ext/installfiles/windows/ZeroTier One.aip | 12 ++++++------ version.h | 4 ++-- windows/WinUI/AboutView.xaml | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ext/installfiles/windows/ZeroTier One.aip b/ext/installfiles/windows/ZeroTier One.aip index a82263e2..0e7907bc 100644 --- a/ext/installfiles/windows/ZeroTier One.aip +++ b/ext/installfiles/windows/ZeroTier One.aip @@ -27,10 +27,10 @@ - + - + @@ -64,7 +64,7 @@ - + @@ -82,7 +82,7 @@ - + @@ -454,10 +454,10 @@ - + - + diff --git a/version.h b/version.h index 82013819..699def7a 100644 --- a/version.h +++ b/version.h @@ -35,12 +35,12 @@ /** * Minor version */ -#define ZEROTIER_ONE_VERSION_MINOR 4 +#define ZEROTIER_ONE_VERSION_MINOR 2 /** * Revision */ -#define ZEROTIER_ONE_VERSION_REVISION 0 +#define ZEROTIER_ONE_VERSION_REVISION 99 /** * Build version diff --git a/windows/WinUI/AboutView.xaml b/windows/WinUI/AboutView.xaml index 118a61b1..8d715fd2 100644 --- a/windows/WinUI/AboutView.xaml +++ b/windows/WinUI/AboutView.xaml @@ -19,9 +19,9 @@ - + - + From a3ef9b8a15554326aaffdf14ebcf7795e5b73aff Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 25 Jun 2019 10:06:50 -0700 Subject: [PATCH 031/185] Cleanup --- node/CertificateOfMembership.hpp | 4 +--- node/Constants.hpp | 12 +++++------- node/IncomingPacket.cpp | 3 --- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/node/CertificateOfMembership.hpp b/node/CertificateOfMembership.hpp index 457b4c1f..b2c63f9d 100644 --- a/node/CertificateOfMembership.hpp +++ b/node/CertificateOfMembership.hpp @@ -113,9 +113,7 @@ public: * Create an empty certificate of membership */ CertificateOfMembership() : - _qualifierCount(0) - { - } + _qualifierCount(0) {} /** * Create from required fields common to all networks diff --git a/node/Constants.hpp b/node/Constants.hpp index 4f45f616..a51d378e 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -225,11 +225,6 @@ */ #define ZT_RECEIVE_QUEUE_TIMEOUT 5000 -/** - * Maximum latency to allow for OK(HELLO) before packet is discarded - */ -#define ZT_HELLO_MAX_ALLOWABLE_LATENCY 120000 - /** * Maximum number of ZT hops allowed (this is not IP hops/TTL) * @@ -265,7 +260,7 @@ #define ZT_PING_CHECK_INVERVAL 5000 /** - * How often the local.conf file is checked for changes + * How often the local.conf file is checked for changes (service, should be moved there) */ #define ZT_LOCAL_CONF_FILE_CHECK_INTERVAL 10000 @@ -464,8 +459,11 @@ /** * Delay between full-fledge pings of directly connected peers. + * * With multipath bonding enabled ping peers more often to measure - * packet loss and latency. + * packet loss and latency. This uses more bandwidth so is disabled + * by default to avoid increasing idle bandwidth use for regular + * links. */ #define ZT_MULTIPATH_PEER_PING_PERIOD 5000 diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 9caa3093..7a1193c0 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -473,9 +473,6 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedP case Packet::VERB_HELLO: { const uint64_t latency = RR->node->now() - at(ZT_PROTO_VERB_HELLO__OK__IDX_TIMESTAMP); - if (latency > ZT_HELLO_MAX_ALLOWABLE_LATENCY) - return true; - const unsigned int vProto = (*this)[ZT_PROTO_VERB_HELLO__OK__IDX_PROTOCOL_VERSION]; const unsigned int vMajor = (*this)[ZT_PROTO_VERB_HELLO__OK__IDX_MAJOR_VERSION]; const unsigned int vMinor = (*this)[ZT_PROTO_VERB_HELLO__OK__IDX_MINOR_VERSION]; From a019c3dd5d141d07a1554e36b6b4c942edfc4d70 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 25 Jun 2019 13:42:20 -0700 Subject: [PATCH 032/185] Tighten up credential push just a bit for faster up-time with older nodes, should not have significant impact on bandwidth. Also some cleanup and push direct path timing fixes. --- node/Constants.hpp | 9 +++++++-- node/InetAddress.cpp | 3 --- node/Membership.cpp | 3 +++ node/Membership.hpp | 11 +++++++++++ node/Network.hpp | 15 +++++++++++++++ node/OutboundMulticast.cpp | 7 +++---- node/Peer.cpp | 21 +++++++++++---------- node/Switch.cpp | 3 ++- 8 files changed, 52 insertions(+), 20 deletions(-) diff --git a/node/Constants.hpp b/node/Constants.hpp index a51d378e..98df998d 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -530,14 +530,19 @@ #define ZT_MAX_BRIDGE_ROUTES 67108864 /** - * If there is no known route, spam to up to this many active bridges + * If there is no known L2 bridging route, spam to up to this many active bridges */ #define ZT_MAX_BRIDGE_SPAM 32 /** * Interval between direct path pushes in milliseconds */ -#define ZT_DIRECT_PATH_PUSH_INTERVAL 120000 +#define ZT_DIRECT_PATH_PUSH_INTERVAL 15000 + +/** + * Interval between direct path pushes in milliseconds if we already have a path + */ +#define ZT_DIRECT_PATH_PUSH_INTERVAL_HAVEPATH 120000 /** * Time horizon for push direct paths cutoff diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp index 35457dc6..9207613e 100644 --- a/node/InetAddress.cpp +++ b/node/InetAddress.cpp @@ -185,15 +185,12 @@ bool InetAddress::fromString(const char *ipSlashPort) inet_pton(AF_INET6, buf, &in6->sin6_addr.s6_addr); in6->sin6_family = AF_INET6; in6->sin6_port = Utils::hton((uint16_t)port); - - return true; } else if (strchr(buf,'.')) { struct sockaddr_in *const in = reinterpret_cast(this); inet_pton(AF_INET, buf, &in->sin_addr.s_addr); in->sin_family = AF_INET; in->sin_port = Utils::hton((uint16_t)port); - return true; } else { return false; diff --git a/node/Membership.cpp b/node/Membership.cpp index aa6d4359..92dd30cb 100644 --- a/node/Membership.cpp +++ b/node/Membership.cpp @@ -40,6 +40,7 @@ namespace ZeroTier { Membership::Membership() : _lastUpdatedMulticast(0), _comRevocationThreshold(0), + _lastPushedCredentials(0), _revocations(4), _remoteTags(4), _remoteCaps(4), @@ -103,6 +104,8 @@ void Membership::pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const i outp.compress(); RR->sw->send(tPtr,outp,true); } + + _lastPushedCredentials = now; } Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const CertificateOfMembership &com) diff --git a/node/Membership.hpp b/node/Membership.hpp index 90b6be6a..6f2d0339 100644 --- a/node/Membership.hpp +++ b/node/Membership.hpp @@ -78,6 +78,14 @@ public: */ void pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const int64_t now,const Address &peerAddress,const NetworkConfig &nconf,int localCapabilityIndex); + /** + * @return True if we haven't pushed credentials in a long time (to cause proactive credential push) + */ + inline bool shouldPushCredentials(const int64_t now) const + { + return ((now - _lastPushedCredentials) > ZT_PEER_ACTIVITY_TIMEOUT); + } + /** * Check whether we should push MULTICAST_LIKEs to this peer, and update last sent time if true * @@ -213,6 +221,9 @@ private: // Revocation threshold for COM or 0 if none int64_t _comRevocationThreshold; + // Time we last pushed credentials + int64_t _lastPushedCredentials; + // Remote member's latest network COM CertificateOfMembership _com; diff --git a/node/Network.hpp b/node/Network.hpp index 9350b3b5..969e1f14 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -368,6 +368,21 @@ public: _membership(to).pushCredentials(RR,tPtr,now,to,_config,-1); } + /** + * Push credentials if we haven't done so in a very long time + * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call + * @param to Destination peer address + * @param now Current time + */ + inline void pushCredentialsIfNeeded(void *tPtr,const Address &to,const int64_t now) + { + Mutex::Lock _l(_lock); + Membership &m = _membership(to); + if (m.shouldPushCredentials(now)) + m.pushCredentials(RR,tPtr,now,to,_config,-1); + } + /** * Destroy this network * diff --git a/node/OutboundMulticast.cpp b/node/OutboundMulticast.cpp index 5b5b726b..a162c8a5 100644 --- a/node/OutboundMulticast.cpp +++ b/node/OutboundMulticast.cpp @@ -84,13 +84,12 @@ void OutboundMulticast::init( void OutboundMulticast::sendOnly(const RuntimeEnvironment *RR,void *tPtr,const Address &toAddr) { const SharedPtr nw(RR->node->network(_nwid)); - const Address toAddr2(toAddr); uint8_t QoSBucket = 255; // Dummy value - if ((nw)&&(nw->filterOutgoingPacket(tPtr,true,RR->identity.address(),toAddr2,_macSrc,_macDest,_frameData,_frameLen,_etherType,0,QoSBucket))) { + if ((nw)&&(nw->filterOutgoingPacket(tPtr,true,RR->identity.address(),toAddr,_macSrc,_macDest,_frameData,_frameLen,_etherType,0,QoSBucket))) { + nw->pushCredentialsIfNeeded(tPtr,toAddr,RR->node->now()); _packet.newInitializationVector(); - _packet.setDestination(toAddr2); + _packet.setDestination(toAddr); RR->node->expectReplyTo(_packet.packetId()); - _tmp = _packet; RR->sw->send(tPtr,_tmp,true); } diff --git a/node/Peer.cpp b/node/Peer.cpp index cbd07799..5f5d1462 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -39,6 +39,8 @@ namespace ZeroTier { +static unsigned char s_freeRandomByteCounter = 0; + Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Identity &peerIdentity) : RR(renv), _lastReceive(0), @@ -55,7 +57,7 @@ Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Ident _lastACKWindowReset(0), _lastQoSWindowReset(0), _lastMultipathCompatibilityCheck(0), - _freeRandomByte(0), + _freeRandomByte((unsigned char)((uintptr_t)this >> 4) ^ ++s_freeRandomByteCounter), _uniqueAlivePathCount(0), _localMultipathSupported(false), _remoteMultipathSupported(false), @@ -73,7 +75,6 @@ Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Ident _lastAggregateStatsReport(0), _lastAggregateAllocation(0) { - Utils::getSecureRandom(&_freeRandomByte, 1); if (!myIdentity.agree(peerIdentity,_key,ZT_PEER_SECRET_KEY_LENGTH)) throw ZT_EXCEPTION_INVALID_ARGUMENT; } @@ -101,7 +102,8 @@ void Peer::received( case Packet::VERB_MULTICAST_FRAME: _lastNontrivialReceive = now; break; - default: break; + default: + break; } if (trustEstablished) { @@ -202,17 +204,17 @@ void Peer::received( } // If we have a trust relationship periodically push a message enumerating - // all known external addresses for ourselves. We now do this even if we - // have a current path since we'll want to use new ones too. + // all known external addresses for ourselves. If we already have a path this + // is done less frequently. if (this->trustEstablished(now)) { - const uint64_t sinceLastPush = now - _lastDirectPathPushSent; - if (sinceLastPush >= ZT_DIRECT_PATH_PUSH_INTERVAL) { + const int64_t sinceLastPush = now - _lastDirectPathPushSent; + if (sinceLastPush >= ((hops == 0) ? ZT_DIRECT_PATH_PUSH_INTERVAL_HAVEPATH : ZT_DIRECT_PATH_PUSH_INTERVAL)) { _lastDirectPathPushSent = now; std::vector pathsToPush(RR->node->directPaths()); if (pathsToPush.size() > 0) { std::vector::const_iterator p(pathsToPush.begin()); while (p != pathsToPush.end()) { - Packet *outp = new Packet(_id.address(),RR->identity.address(),Packet::VERB_PUSH_DIRECT_PATHS); + Packet *const outp = new Packet(_id.address(),RR->identity.address(),Packet::VERB_PUSH_DIRECT_PATHS); outp->addSize(2); // leave room for count unsigned int count = 0; while ((p != pathsToPush.end())&&((outp->size() + 24) < 1200)) { @@ -254,8 +256,7 @@ void Peer::received( void Peer::recordOutgoingPacket(const SharedPtr &path, const uint64_t packetId, uint16_t payloadLength, const Packet::Verb verb, int64_t now) { - // Grab second byte from packetId to use as a source of entropy in the next path selection - _freeRandomByte = (packetId & 0xFF00) >> 8; + _freeRandomByte += (unsigned char)(packetId >> 8); // grab entropy to use in path selection logic for multipath if (_canUseMultipath) { path->recordOutgoingPacket(now, packetId, payloadLength, verb); } diff --git a/node/Switch.cpp b/node/Switch.cpp index a9c882fb..a6852d9f 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -417,6 +417,8 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr &network,const return; } + network->pushCredentialsIfNeeded(tPtr,toZT,RR->node->now()); + if (fromBridged) { Packet outp(toZT,RR->identity.address(),Packet::VERB_EXT_FRAME); outp.append(network->id()); @@ -437,7 +439,6 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr &network,const outp.compress(); aqm_enqueue(tPtr,network,outp,true,qosBucket); } - } else { // Destination is bridged behind a remote peer From 54d2fa65ddca8e4c98d47272d2c8538a59b04018 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 27 Jun 2019 14:31:10 -0700 Subject: [PATCH 033/185] Version bump, cleanup --- attic/Cluster.cpp | 1042 ----------------- attic/Cluster.hpp | 463 -------- attic/ClusterDefinition.hpp | 168 --- attic/ClusterGeoIpService.cpp | 243 ---- attic/ClusterGeoIpService.hpp | 151 --- attic/FCV.hpp | 101 -- attic/OSXEthernetTap.cpp | 703 ----------- .../OSXEthernetTap.cpp.pcap-with-bridge-test | 650 ---------- .../OSXEthernetTap.cpp.utun-work-in-progress | 831 ------------- attic/OSXEthernetTap.hpp | 95 -- .../OSXEthernetTap.hpp.pcap-with-bridge-test | 96 -- .../OSXEthernetTap.hpp.utun-work-in-progress | 101 -- attic/RethinkDB.cpp | 497 -------- attic/RethinkDB.hpp | 84 -- attic/kubernetes_docs/.zerotierCliSettings | 18 - attic/kubernetes_docs/Dockerfile | 19 - attic/kubernetes_docs/README.md | 150 --- attic/kubernetes_docs/entrypoint.sh | 23 - attic/kubernetes_docs/server.js | 8 - debian/changelog | 6 + ext/installfiles/mac/ZeroTier One.pkgproj | 2 +- .../chocolatey/zerotier-one/tools/LICENSE.txt | 11 - .../zerotier-one/tools/VERIFICATION.txt | 5 - .../zerotier-one/tools/chocolateyinstall.ps1 | 8 - .../tools/chocolateyuninstall.ps1 | 30 - .../zerotier-one/zerotier-one.nuspec | 76 -- zerotier-one.spec | 2 +- 27 files changed, 8 insertions(+), 5575 deletions(-) delete mode 100644 attic/Cluster.cpp delete mode 100644 attic/Cluster.hpp delete mode 100644 attic/ClusterDefinition.hpp delete mode 100644 attic/ClusterGeoIpService.cpp delete mode 100644 attic/ClusterGeoIpService.hpp delete mode 100644 attic/FCV.hpp delete mode 100644 attic/OSXEthernetTap.cpp delete mode 100644 attic/OSXEthernetTap.cpp.pcap-with-bridge-test delete mode 100644 attic/OSXEthernetTap.cpp.utun-work-in-progress delete mode 100644 attic/OSXEthernetTap.hpp delete mode 100644 attic/OSXEthernetTap.hpp.pcap-with-bridge-test delete mode 100644 attic/OSXEthernetTap.hpp.utun-work-in-progress delete mode 100644 attic/RethinkDB.cpp delete mode 100644 attic/RethinkDB.hpp delete mode 100644 attic/kubernetes_docs/.zerotierCliSettings delete mode 100644 attic/kubernetes_docs/Dockerfile delete mode 100644 attic/kubernetes_docs/README.md delete mode 100644 attic/kubernetes_docs/entrypoint.sh delete mode 100644 attic/kubernetes_docs/server.js delete mode 100644 ext/installfiles/windows/chocolatey/zerotier-one/tools/LICENSE.txt delete mode 100644 ext/installfiles/windows/chocolatey/zerotier-one/tools/VERIFICATION.txt delete mode 100644 ext/installfiles/windows/chocolatey/zerotier-one/tools/chocolateyinstall.ps1 delete mode 100644 ext/installfiles/windows/chocolatey/zerotier-one/tools/chocolateyuninstall.ps1 delete mode 100644 ext/installfiles/windows/chocolatey/zerotier-one/zerotier-one.nuspec diff --git a/attic/Cluster.cpp b/attic/Cluster.cpp deleted file mode 100644 index 119aec29..00000000 --- a/attic/Cluster.cpp +++ /dev/null @@ -1,1042 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -#ifdef ZT_ENABLE_CLUSTER - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "../version.h" - -#include "Cluster.hpp" -#include "RuntimeEnvironment.hpp" -#include "MulticastGroup.hpp" -#include "CertificateOfMembership.hpp" -#include "Salsa20.hpp" -#include "Poly1305.hpp" -#include "Identity.hpp" -#include "Topology.hpp" -#include "Packet.hpp" -#include "Switch.hpp" -#include "Node.hpp" -#include "Network.hpp" -#include "Array.hpp" - -namespace ZeroTier { - -static inline double _dist3d(int x1,int y1,int z1,int x2,int y2,int z2) - throw() -{ - double dx = ((double)x2 - (double)x1); - double dy = ((double)y2 - (double)y1); - double dz = ((double)z2 - (double)z1); - return sqrt((dx * dx) + (dy * dy) + (dz * dz)); -} - -// An entry in _ClusterSendQueue -struct _ClusterSendQueueEntry -{ - uint64_t timestamp; - Address fromPeerAddress; - Address toPeerAddress; - // if we ever support larger transport MTUs this must be increased - unsigned char data[ZT_CLUSTER_SEND_QUEUE_DATA_MAX]; - unsigned int len; - bool unite; -}; - -// A multi-index map with entry memory pooling -- this allows our queue to -// be O(log(N)) and is complex enough that it makes the code a lot cleaner -// to break it out from Cluster. -class _ClusterSendQueue -{ -public: - _ClusterSendQueue() : - _poolCount(0) {} - ~_ClusterSendQueue() {} // memory is automatically freed when _chunks is destroyed - - inline void enqueue(uint64_t now,const Address &from,const Address &to,const void *data,unsigned int len,bool unite) - { - if (len > ZT_CLUSTER_SEND_QUEUE_DATA_MAX) - return; - - Mutex::Lock _l(_lock); - - // Delete oldest queue entry for this sender if this enqueue() would take them over the per-sender limit - { - std::set< std::pair >::iterator qi(_bySrc.lower_bound(std::pair(from,(_ClusterSendQueueEntry *)0))); - std::set< std::pair >::iterator oldest(qi); - unsigned long countForSender = 0; - while ((qi != _bySrc.end())&&(qi->first == from)) { - if (qi->second->timestamp < oldest->second->timestamp) - oldest = qi; - ++countForSender; - ++qi; - } - if (countForSender >= ZT_CLUSTER_MAX_QUEUE_PER_SENDER) { - _byDest.erase(std::pair(oldest->second->toPeerAddress,oldest->second)); - _pool[_poolCount++] = oldest->second; - _bySrc.erase(oldest); - } - } - - _ClusterSendQueueEntry *e; - if (_poolCount > 0) { - e = _pool[--_poolCount]; - } else { - if (_chunks.size() >= ZT_CLUSTER_MAX_QUEUE_CHUNKS) - return; // queue is totally full! - _chunks.push_back(Array<_ClusterSendQueueEntry,ZT_CLUSTER_QUEUE_CHUNK_SIZE>()); - e = &(_chunks.back().data[0]); - for(unsigned int i=1;itimestamp = now; - e->fromPeerAddress = from; - e->toPeerAddress = to; - memcpy(e->data,data,len); - e->len = len; - e->unite = unite; - - _bySrc.insert(std::pair(from,e)); - _byDest.insert(std::pair(to,e)); - } - - inline void expire(uint64_t now) - { - Mutex::Lock _l(_lock); - for(std::set< std::pair >::iterator qi(_bySrc.begin());qi!=_bySrc.end();) { - if ((now - qi->second->timestamp) > ZT_CLUSTER_QUEUE_EXPIRATION) { - _byDest.erase(std::pair(qi->second->toPeerAddress,qi->second)); - _pool[_poolCount++] = qi->second; - _bySrc.erase(qi++); - } else ++qi; - } - } - - /** - * Get and dequeue entries for a given destination address - * - * After use these entries must be returned with returnToPool()! - * - * @param dest Destination address - * @param results Array to fill with results - * @param maxResults Size of results[] in pointers - * @return Number of actual results returned - */ - inline unsigned int getByDest(const Address &dest,_ClusterSendQueueEntry **results,unsigned int maxResults) - { - unsigned int count = 0; - Mutex::Lock _l(_lock); - std::set< std::pair >::iterator qi(_byDest.lower_bound(std::pair(dest,(_ClusterSendQueueEntry *)0))); - while ((qi != _byDest.end())&&(qi->first == dest)) { - _bySrc.erase(std::pair(qi->second->fromPeerAddress,qi->second)); - results[count++] = qi->second; - if (count == maxResults) - break; - _byDest.erase(qi++); - } - return count; - } - - /** - * Return entries to pool after use - * - * @param entries Array of entries - * @param count Number of entries - */ - inline void returnToPool(_ClusterSendQueueEntry **entries,unsigned int count) - { - Mutex::Lock _l(_lock); - for(unsigned int i=0;i > _chunks; - _ClusterSendQueueEntry *_pool[ZT_CLUSTER_QUEUE_CHUNK_SIZE * ZT_CLUSTER_MAX_QUEUE_CHUNKS]; - unsigned long _poolCount; - std::set< std::pair > _bySrc; - std::set< std::pair > _byDest; - Mutex _lock; -}; - -Cluster::Cluster( - const RuntimeEnvironment *renv, - uint16_t id, - const std::vector &zeroTierPhysicalEndpoints, - int32_t x, - int32_t y, - int32_t z, - void (*sendFunction)(void *,unsigned int,const void *,unsigned int), - void *sendFunctionArg, - int (*addressToLocationFunction)(void *,const struct sockaddr_storage *,int *,int *,int *), - void *addressToLocationFunctionArg) : - RR(renv), - _sendQueue(new _ClusterSendQueue()), - _sendFunction(sendFunction), - _sendFunctionArg(sendFunctionArg), - _addressToLocationFunction(addressToLocationFunction), - _addressToLocationFunctionArg(addressToLocationFunctionArg), - _x(x), - _y(y), - _z(z), - _id(id), - _zeroTierPhysicalEndpoints(zeroTierPhysicalEndpoints), - _members(new _Member[ZT_CLUSTER_MAX_MEMBERS]), - _lastFlushed(0), - _lastCleanedRemotePeers(0), - _lastCleanedQueue(0) -{ - uint16_t stmp[ZT_SHA512_DIGEST_LEN / sizeof(uint16_t)]; - - // Generate master secret by hashing the secret from our Identity key pair - RR->identity.sha512PrivateKey(_masterSecret); - - // Generate our inbound message key, which is the master secret XORed with our ID and hashed twice - memcpy(stmp,_masterSecret,sizeof(stmp)); - stmp[0] ^= Utils::hton(id); - SHA512::hash(stmp,stmp,sizeof(stmp)); - SHA512::hash(stmp,stmp,sizeof(stmp)); - memcpy(_key,stmp,sizeof(_key)); - Utils::burn(stmp,sizeof(stmp)); -} - -Cluster::~Cluster() -{ - Utils::burn(_masterSecret,sizeof(_masterSecret)); - Utils::burn(_key,sizeof(_key)); - delete [] _members; - delete _sendQueue; -} - -void Cluster::handleIncomingStateMessage(const void *msg,unsigned int len) -{ - Buffer dmsg; - { - // FORMAT: <[16] iv><[8] MAC><... data> - if ((len < 24)||(len > ZT_CLUSTER_MAX_MESSAGE_LENGTH)) - return; - - // 16-byte IV: first 8 bytes XORed with key, last 8 bytes used as Salsa20 64-bit IV - char keytmp[32]; - memcpy(keytmp,_key,32); - for(int i=0;i<8;++i) - keytmp[i] ^= reinterpret_cast(msg)[i]; - Salsa20 s20(keytmp,reinterpret_cast(msg) + 8); - Utils::burn(keytmp,sizeof(keytmp)); - - // One-time-use Poly1305 key from first 32 bytes of Salsa20 keystream (as per DJB/NaCl "standard") - char polykey[ZT_POLY1305_KEY_LEN]; - memset(polykey,0,sizeof(polykey)); - s20.crypt12(polykey,polykey,sizeof(polykey)); - - // Compute 16-byte MAC - char mac[ZT_POLY1305_MAC_LEN]; - Poly1305::compute(mac,reinterpret_cast(msg) + 24,len - 24,polykey); - - // Check first 8 bytes of MAC against 64-bit MAC in stream - if (!Utils::secureEq(mac,reinterpret_cast(msg) + 16,8)) - return; - - // Decrypt! - dmsg.setSize(len - 24); - s20.crypt12(reinterpret_cast(msg) + 24,const_cast(dmsg.data()),dmsg.size()); - } - - if (dmsg.size() < 4) - return; - const uint16_t fromMemberId = dmsg.at(0); - unsigned int ptr = 2; - if (fromMemberId == _id) // sanity check: we don't talk to ourselves - return; - const uint16_t toMemberId = dmsg.at(ptr); - ptr += 2; - if (toMemberId != _id) // sanity check: message not for us? - return; - - { // make sure sender is actually considered a member - Mutex::Lock _l3(_memberIds_m); - if (std::find(_memberIds.begin(),_memberIds.end(),fromMemberId) == _memberIds.end()) - return; - } - - try { - while (ptr < dmsg.size()) { - const unsigned int mlen = dmsg.at(ptr); ptr += 2; - const unsigned int nextPtr = ptr + mlen; - if (nextPtr > dmsg.size()) - break; - - int mtype = -1; - try { - switch((StateMessageType)(mtype = (int)dmsg[ptr++])) { - default: - break; - - case CLUSTER_MESSAGE_ALIVE: { - _Member &m = _members[fromMemberId]; - Mutex::Lock mlck(m.lock); - ptr += 7; // skip version stuff, not used yet - m.x = dmsg.at(ptr); ptr += 4; - m.y = dmsg.at(ptr); ptr += 4; - m.z = dmsg.at(ptr); ptr += 4; - ptr += 8; // skip local clock, not used - m.load = dmsg.at(ptr); ptr += 8; - m.peers = dmsg.at(ptr); ptr += 8; - ptr += 8; // skip flags, unused -#ifdef ZT_TRACE - std::string addrs; -#endif - unsigned int physicalAddressCount = dmsg[ptr++]; - m.zeroTierPhysicalEndpoints.clear(); - for(unsigned int i=0;i 0) - addrs.push_back(','); - addrs.append(m.zeroTierPhysicalEndpoints.back().toString()); - } -#endif - } -#ifdef ZT_TRACE - if ((RR->node->now() - m.lastReceivedAliveAnnouncement) >= ZT_CLUSTER_TIMEOUT) { - TRACE("[%u] I'm alive! peers close to %d,%d,%d can be redirected to: %s",(unsigned int)fromMemberId,m.x,m.y,m.z,addrs.c_str()); - } -#endif - m.lastReceivedAliveAnnouncement = RR->node->now(); - } break; - - case CLUSTER_MESSAGE_HAVE_PEER: { - Identity id; - ptr += id.deserialize(dmsg,ptr); - if (id) { - { - Mutex::Lock _l(_remotePeers_m); - _RemotePeer &rp = _remotePeers[std::pair(id.address(),(unsigned int)fromMemberId)]; - if (!rp.lastHavePeerReceived) { - RR->topology->saveIdentity((void *)0,id); - RR->identity.agree(id,rp.key,ZT_PEER_SECRET_KEY_LENGTH); - } - rp.lastHavePeerReceived = RR->node->now(); - } - - _ClusterSendQueueEntry *q[16384]; // 16384 is "tons" - unsigned int qc = _sendQueue->getByDest(id.address(),q,16384); - for(unsigned int i=0;irelayViaCluster(q[i]->fromPeerAddress,q[i]->toPeerAddress,q[i]->data,q[i]->len,q[i]->unite); - _sendQueue->returnToPool(q,qc); - - TRACE("[%u] has %s (retried %u queued sends)",(unsigned int)fromMemberId,id.address().toString().c_str(),qc); - } - } break; - - case CLUSTER_MESSAGE_WANT_PEER: { - const Address zeroTierAddress(dmsg.field(ptr,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); ptr += ZT_ADDRESS_LENGTH; - SharedPtr peer(RR->topology->getPeerNoCache(zeroTierAddress)); - if ( (peer) && (peer->hasLocalClusterOptimalPath(RR->node->now())) ) { - Buffer<1024> buf; - peer->identity().serialize(buf); - Mutex::Lock _l2(_members[fromMemberId].lock); - _send(fromMemberId,CLUSTER_MESSAGE_HAVE_PEER,buf.data(),buf.size()); - } - } break; - - case CLUSTER_MESSAGE_REMOTE_PACKET: { - const unsigned int plen = dmsg.at(ptr); ptr += 2; - if (plen) { - Packet remotep(dmsg.field(ptr,plen),plen); ptr += plen; - //TRACE("remote %s from %s via %u (%u bytes)",Packet::verbString(remotep.verb()),remotep.source().toString().c_str(),fromMemberId,plen); - switch(remotep.verb()) { - case Packet::VERB_WHOIS: _doREMOTE_WHOIS(fromMemberId,remotep); break; - case Packet::VERB_MULTICAST_GATHER: _doREMOTE_MULTICAST_GATHER(fromMemberId,remotep); break; - default: break; // ignore things we don't care about across cluster - } - } - } break; - - case CLUSTER_MESSAGE_PROXY_UNITE: { - const Address localPeerAddress(dmsg.field(ptr,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); ptr += ZT_ADDRESS_LENGTH; - const Address remotePeerAddress(dmsg.field(ptr,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); ptr += ZT_ADDRESS_LENGTH; - const unsigned int numRemotePeerPaths = dmsg[ptr++]; - InetAddress remotePeerPaths[256]; // size is 8-bit, so 256 is max - for(unsigned int i=0;inode->now(); - SharedPtr localPeer(RR->topology->getPeerNoCache(localPeerAddress)); - if ((localPeer)&&(numRemotePeerPaths > 0)) { - InetAddress bestLocalV4,bestLocalV6; - localPeer->getRendezvousAddresses(now,bestLocalV4,bestLocalV6); - - InetAddress bestRemoteV4,bestRemoteV6; - for(unsigned int i=0;iidentity.address(),Packet::VERB_RENDEZVOUS); - rendezvousForLocal.append((uint8_t)0); - remotePeerAddress.appendTo(rendezvousForLocal); - - Buffer<2048> rendezvousForRemote; - remotePeerAddress.appendTo(rendezvousForRemote); - rendezvousForRemote.append((uint8_t)Packet::VERB_RENDEZVOUS); - rendezvousForRemote.addSize(2); // space for actual packet payload length - rendezvousForRemote.append((uint8_t)0); // flags == 0 - localPeerAddress.appendTo(rendezvousForRemote); - - bool haveMatch = false; - if ((bestLocalV6)&&(bestRemoteV6)) { - haveMatch = true; - - rendezvousForLocal.append((uint16_t)bestRemoteV6.port()); - rendezvousForLocal.append((uint8_t)16); - rendezvousForLocal.append(bestRemoteV6.rawIpData(),16); - - rendezvousForRemote.append((uint16_t)bestLocalV6.port()); - rendezvousForRemote.append((uint8_t)16); - rendezvousForRemote.append(bestLocalV6.rawIpData(),16); - rendezvousForRemote.setAt(ZT_ADDRESS_LENGTH + 1,(uint16_t)(9 + 16)); - } else if ((bestLocalV4)&&(bestRemoteV4)) { - haveMatch = true; - - rendezvousForLocal.append((uint16_t)bestRemoteV4.port()); - rendezvousForLocal.append((uint8_t)4); - rendezvousForLocal.append(bestRemoteV4.rawIpData(),4); - - rendezvousForRemote.append((uint16_t)bestLocalV4.port()); - rendezvousForRemote.append((uint8_t)4); - rendezvousForRemote.append(bestLocalV4.rawIpData(),4); - rendezvousForRemote.setAt(ZT_ADDRESS_LENGTH + 1,(uint16_t)(9 + 4)); - } - - if (haveMatch) { - { - Mutex::Lock _l2(_members[fromMemberId].lock); - _send(fromMemberId,CLUSTER_MESSAGE_PROXY_SEND,rendezvousForRemote.data(),rendezvousForRemote.size()); - } - RR->sw->send((void *)0,rendezvousForLocal,true); - } - } - } break; - - case CLUSTER_MESSAGE_PROXY_SEND: { - const Address rcpt(dmsg.field(ptr,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); ptr += ZT_ADDRESS_LENGTH; - const Packet::Verb verb = (Packet::Verb)dmsg[ptr++]; - const unsigned int len = dmsg.at(ptr); ptr += 2; - Packet outp(rcpt,RR->identity.address(),verb); - outp.append(dmsg.field(ptr,len),len); ptr += len; - RR->sw->send((void *)0,outp,true); - //TRACE("[%u] proxy send %s to %s length %u",(unsigned int)fromMemberId,Packet::verbString(verb),rcpt.toString().c_str(),len); - } break; - - case CLUSTER_MESSAGE_NETWORK_CONFIG: { - const SharedPtr network(RR->node->network(dmsg.at(ptr))); - if (network) { - // Copy into a Packet just to conform to Network API. Eventually - // will want to refactor. - network->handleConfigChunk((void *)0,0,Address(),Buffer(dmsg),ptr); - } - } break; - } - } catch ( ... ) { - TRACE("invalid message of size %u type %d (inner decode), discarding",mlen,mtype); - // drop invalids - } - - ptr = nextPtr; - } - } catch ( ... ) { - TRACE("invalid message (outer loop), discarding"); - // drop invalids - } -} - -void Cluster::broadcastHavePeer(const Identity &id) -{ - Buffer<1024> buf; - id.serialize(buf); - Mutex::Lock _l(_memberIds_m); - for(std::vector::const_iterator mid(_memberIds.begin());mid!=_memberIds.end();++mid) { - Mutex::Lock _l2(_members[*mid].lock); - _send(*mid,CLUSTER_MESSAGE_HAVE_PEER,buf.data(),buf.size()); - } -} - -void Cluster::broadcastNetworkConfigChunk(const void *chunk,unsigned int len) -{ - Mutex::Lock _l(_memberIds_m); - for(std::vector::const_iterator mid(_memberIds.begin());mid!=_memberIds.end();++mid) { - Mutex::Lock _l2(_members[*mid].lock); - _send(*mid,CLUSTER_MESSAGE_NETWORK_CONFIG,chunk,len); - } -} - -int Cluster::checkSendViaCluster(const Address &toPeerAddress,uint64_t &mostRecentTs,void *peerSecret) -{ - const uint64_t now = RR->node->now(); - mostRecentTs = 0; - int mostRecentMemberId = -1; - { - Mutex::Lock _l2(_remotePeers_m); - std::map< std::pair,_RemotePeer >::const_iterator rpe(_remotePeers.lower_bound(std::pair(toPeerAddress,0))); - for(;;) { - if ((rpe == _remotePeers.end())||(rpe->first.first != toPeerAddress)) - break; - else if (rpe->second.lastHavePeerReceived > mostRecentTs) { - mostRecentTs = rpe->second.lastHavePeerReceived; - memcpy(peerSecret,rpe->second.key,ZT_PEER_SECRET_KEY_LENGTH); - mostRecentMemberId = (int)rpe->first.second; - } - ++rpe; - } - } - - const uint64_t ageOfMostRecentHavePeerAnnouncement = now - mostRecentTs; - if (ageOfMostRecentHavePeerAnnouncement >= (ZT_PEER_ACTIVITY_TIMEOUT / 3)) { - if (ageOfMostRecentHavePeerAnnouncement >= ZT_PEER_ACTIVITY_TIMEOUT) - mostRecentMemberId = -1; - - bool sendWantPeer = true; - { - Mutex::Lock _l(_remotePeers_m); - _RemotePeer &rp = _remotePeers[std::pair(toPeerAddress,(unsigned int)_id)]; - if ((now - rp.lastSentWantPeer) >= ZT_CLUSTER_WANT_PEER_EVERY) { - rp.lastSentWantPeer = now; - } else { - sendWantPeer = false; // don't flood WANT_PEER - } - } - if (sendWantPeer) { - char tmp[ZT_ADDRESS_LENGTH]; - toPeerAddress.copyTo(tmp,ZT_ADDRESS_LENGTH); - { - Mutex::Lock _l(_memberIds_m); - for(std::vector::const_iterator mid(_memberIds.begin());mid!=_memberIds.end();++mid) { - Mutex::Lock _l2(_members[*mid].lock); - _send(*mid,CLUSTER_MESSAGE_WANT_PEER,tmp,ZT_ADDRESS_LENGTH); - } - } - } - } - - return mostRecentMemberId; -} - -bool Cluster::sendViaCluster(int mostRecentMemberId,const Address &toPeerAddress,const void *data,unsigned int len) -{ - if ((mostRecentMemberId < 0)||(mostRecentMemberId >= ZT_CLUSTER_MAX_MEMBERS)) // sanity check - return false; - Mutex::Lock _l2(_members[mostRecentMemberId].lock); - for(std::vector::const_iterator i1(_zeroTierPhysicalEndpoints.begin());i1!=_zeroTierPhysicalEndpoints.end();++i1) { - for(std::vector::const_iterator i2(_members[mostRecentMemberId].zeroTierPhysicalEndpoints.begin());i2!=_members[mostRecentMemberId].zeroTierPhysicalEndpoints.end();++i2) { - if (i1->ss_family == i2->ss_family) { - TRACE("sendViaCluster sending %u bytes to %s by way of %u (%s->%s)",len,toPeerAddress.toString().c_str(),(unsigned int)mostRecentMemberId,i1->toString().c_str(),i2->toString().c_str()); - RR->node->putPacket((void *)0,*i1,*i2,data,len); - return true; - } - } - } - return false; -} - -void Cluster::relayViaCluster(const Address &fromPeerAddress,const Address &toPeerAddress,const void *data,unsigned int len,bool unite) -{ - if (len > ZT_PROTO_MAX_PACKET_LENGTH) // sanity check - return; - - const uint64_t now = RR->node->now(); - - uint64_t mostRecentTs = 0; - int mostRecentMemberId = -1; - { - Mutex::Lock _l2(_remotePeers_m); - std::map< std::pair,_RemotePeer >::const_iterator rpe(_remotePeers.lower_bound(std::pair(toPeerAddress,0))); - for(;;) { - if ((rpe == _remotePeers.end())||(rpe->first.first != toPeerAddress)) - break; - else if (rpe->second.lastHavePeerReceived > mostRecentTs) { - mostRecentTs = rpe->second.lastHavePeerReceived; - mostRecentMemberId = (int)rpe->first.second; - } - ++rpe; - } - } - - const uint64_t ageOfMostRecentHavePeerAnnouncement = now - mostRecentTs; - if (ageOfMostRecentHavePeerAnnouncement >= (ZT_PEER_ACTIVITY_TIMEOUT / 3)) { - // Enqueue and wait if peer seems alive, but do WANT_PEER to refresh homing - const bool enqueueAndWait = ((ageOfMostRecentHavePeerAnnouncement >= ZT_PEER_ACTIVITY_TIMEOUT)||(mostRecentMemberId < 0)); - - // Poll everyone with WANT_PEER if the age of our most recent entry is - // approaching expiration (or has expired, or does not exist). - bool sendWantPeer = true; - { - Mutex::Lock _l(_remotePeers_m); - _RemotePeer &rp = _remotePeers[std::pair(toPeerAddress,(unsigned int)_id)]; - if ((now - rp.lastSentWantPeer) >= ZT_CLUSTER_WANT_PEER_EVERY) { - rp.lastSentWantPeer = now; - } else { - sendWantPeer = false; // don't flood WANT_PEER - } - } - if (sendWantPeer) { - char tmp[ZT_ADDRESS_LENGTH]; - toPeerAddress.copyTo(tmp,ZT_ADDRESS_LENGTH); - { - Mutex::Lock _l(_memberIds_m); - for(std::vector::const_iterator mid(_memberIds.begin());mid!=_memberIds.end();++mid) { - Mutex::Lock _l2(_members[*mid].lock); - _send(*mid,CLUSTER_MESSAGE_WANT_PEER,tmp,ZT_ADDRESS_LENGTH); - } - } - } - - // If there isn't a good place to send via, then enqueue this for retrying - // later and return after having broadcasted a WANT_PEER. - if (enqueueAndWait) { - TRACE("relayViaCluster %s -> %s enqueueing to wait for HAVE_PEER",fromPeerAddress.toString().c_str(),toPeerAddress.toString().c_str()); - _sendQueue->enqueue(now,fromPeerAddress,toPeerAddress,data,len,unite); - return; - } - } - - if (mostRecentMemberId >= 0) { - Buffer<1024> buf; - if (unite) { - InetAddress v4,v6; - if (fromPeerAddress) { - SharedPtr fromPeer(RR->topology->getPeerNoCache(fromPeerAddress)); - if (fromPeer) - fromPeer->getRendezvousAddresses(now,v4,v6); - } - uint8_t addrCount = 0; - if (v4) - ++addrCount; - if (v6) - ++addrCount; - if (addrCount) { - toPeerAddress.appendTo(buf); - fromPeerAddress.appendTo(buf); - buf.append(addrCount); - if (v4) - v4.serialize(buf); - if (v6) - v6.serialize(buf); - } - } - - { - Mutex::Lock _l2(_members[mostRecentMemberId].lock); - if (buf.size() > 0) - _send(mostRecentMemberId,CLUSTER_MESSAGE_PROXY_UNITE,buf.data(),buf.size()); - - for(std::vector::const_iterator i1(_zeroTierPhysicalEndpoints.begin());i1!=_zeroTierPhysicalEndpoints.end();++i1) { - for(std::vector::const_iterator i2(_members[mostRecentMemberId].zeroTierPhysicalEndpoints.begin());i2!=_members[mostRecentMemberId].zeroTierPhysicalEndpoints.end();++i2) { - if (i1->ss_family == i2->ss_family) { - TRACE("relayViaCluster relaying %u bytes from %s to %s by way of %u (%s->%s)",len,fromPeerAddress.toString().c_str(),toPeerAddress.toString().c_str(),(unsigned int)mostRecentMemberId,i1->toString().c_str(),i2->toString().c_str()); - RR->node->putPacket((void *)0,*i1,*i2,data,len); - return; - } - } - } - - TRACE("relayViaCluster relaying %u bytes from %s to %s by way of %u failed: no common endpoints with the same address family!",len,fromPeerAddress.toString().c_str(),toPeerAddress.toString().c_str(),(unsigned int)mostRecentMemberId); - } - } -} - -void Cluster::sendDistributedQuery(const Packet &pkt) -{ - Buffer<4096> buf; - buf.append((uint16_t)pkt.size()); - buf.append(pkt.data(),pkt.size()); - Mutex::Lock _l(_memberIds_m); - for(std::vector::const_iterator mid(_memberIds.begin());mid!=_memberIds.end();++mid) { - Mutex::Lock _l2(_members[*mid].lock); - _send(*mid,CLUSTER_MESSAGE_REMOTE_PACKET,buf.data(),buf.size()); - } -} - -void Cluster::doPeriodicTasks() -{ - const uint64_t now = RR->node->now(); - - if ((now - _lastFlushed) >= ZT_CLUSTER_FLUSH_PERIOD) { - _lastFlushed = now; - - Mutex::Lock _l(_memberIds_m); - for(std::vector::const_iterator mid(_memberIds.begin());mid!=_memberIds.end();++mid) { - Mutex::Lock _l2(_members[*mid].lock); - - if ((now - _members[*mid].lastAnnouncedAliveTo) >= ((ZT_CLUSTER_TIMEOUT / 2) - 1000)) { - _members[*mid].lastAnnouncedAliveTo = now; - - Buffer<2048> alive; - alive.append((uint16_t)ZEROTIER_ONE_VERSION_MAJOR); - alive.append((uint16_t)ZEROTIER_ONE_VERSION_MINOR); - alive.append((uint16_t)ZEROTIER_ONE_VERSION_REVISION); - alive.append((uint8_t)ZT_PROTO_VERSION); - if (_addressToLocationFunction) { - alive.append((int32_t)_x); - alive.append((int32_t)_y); - alive.append((int32_t)_z); - } else { - alive.append((int32_t)0); - alive.append((int32_t)0); - alive.append((int32_t)0); - } - alive.append((uint64_t)now); - alive.append((uint64_t)0); // TODO: compute and send load average - alive.append((uint64_t)RR->topology->countActive(now)); - alive.append((uint64_t)0); // unused/reserved flags - alive.append((uint8_t)_zeroTierPhysicalEndpoints.size()); - for(std::vector::const_iterator pe(_zeroTierPhysicalEndpoints.begin());pe!=_zeroTierPhysicalEndpoints.end();++pe) - pe->serialize(alive); - _send(*mid,CLUSTER_MESSAGE_ALIVE,alive.data(),alive.size()); - } - - _flush(*mid); - } - } - - if ((now - _lastCleanedRemotePeers) >= (ZT_PEER_ACTIVITY_TIMEOUT * 2)) { - _lastCleanedRemotePeers = now; - - Mutex::Lock _l(_remotePeers_m); - for(std::map< std::pair,_RemotePeer >::iterator rp(_remotePeers.begin());rp!=_remotePeers.end();) { - if ((now - rp->second.lastHavePeerReceived) >= ZT_PEER_ACTIVITY_TIMEOUT) - _remotePeers.erase(rp++); - else ++rp; - } - } - - if ((now - _lastCleanedQueue) >= ZT_CLUSTER_QUEUE_EXPIRATION) { - _lastCleanedQueue = now; - _sendQueue->expire(now); - } -} - -void Cluster::addMember(uint16_t memberId) -{ - if ((memberId >= ZT_CLUSTER_MAX_MEMBERS)||(memberId == _id)) - return; - - Mutex::Lock _l2(_members[memberId].lock); - - { - Mutex::Lock _l(_memberIds_m); - if (std::find(_memberIds.begin(),_memberIds.end(),memberId) != _memberIds.end()) - return; - _memberIds.push_back(memberId); - std::sort(_memberIds.begin(),_memberIds.end()); - } - - _members[memberId].clear(); - - // Generate this member's message key from the master and its ID - uint16_t stmp[ZT_SHA512_DIGEST_LEN / sizeof(uint16_t)]; - memcpy(stmp,_masterSecret,sizeof(stmp)); - stmp[0] ^= Utils::hton(memberId); - SHA512::hash(stmp,stmp,sizeof(stmp)); - SHA512::hash(stmp,stmp,sizeof(stmp)); - memcpy(_members[memberId].key,stmp,sizeof(_members[memberId].key)); - Utils::burn(stmp,sizeof(stmp)); - - // Prepare q - _members[memberId].q.clear(); - char iv[16]; - Utils::getSecureRandom(iv,16); - _members[memberId].q.append(iv,16); - _members[memberId].q.addSize(8); // room for MAC - _members[memberId].q.append((uint16_t)_id); - _members[memberId].q.append((uint16_t)memberId); -} - -void Cluster::removeMember(uint16_t memberId) -{ - Mutex::Lock _l(_memberIds_m); - std::vector newMemberIds; - for(std::vector::const_iterator mid(_memberIds.begin());mid!=_memberIds.end();++mid) { - if (*mid != memberId) - newMemberIds.push_back(*mid); - } - _memberIds = newMemberIds; -} - -bool Cluster::findBetterEndpoint(InetAddress &redirectTo,const Address &peerAddress,const InetAddress &peerPhysicalAddress,bool offload) -{ - if (_addressToLocationFunction) { - // Pick based on location if it can be determined - int px = 0,py = 0,pz = 0; - if (_addressToLocationFunction(_addressToLocationFunctionArg,reinterpret_cast(&peerPhysicalAddress),&px,&py,&pz) == 0) { - TRACE("no geolocation data for %s",peerPhysicalAddress.toIpString().c_str()); - return false; - } - - // Find member closest to this peer - const uint64_t now = RR->node->now(); - std::vector best; - const double currentDistance = _dist3d(_x,_y,_z,px,py,pz); - double bestDistance = (offload ? 2147483648.0 : currentDistance); -#ifdef ZT_TRACE - unsigned int bestMember = _id; -#endif - { - Mutex::Lock _l(_memberIds_m); - for(std::vector::const_iterator mid(_memberIds.begin());mid!=_memberIds.end();++mid) { - _Member &m = _members[*mid]; - Mutex::Lock _ml(m.lock); - - // Consider member if it's alive and has sent us a location and one or more physical endpoints to send peers to - if ( ((now - m.lastReceivedAliveAnnouncement) < ZT_CLUSTER_TIMEOUT) && ((m.x != 0)||(m.y != 0)||(m.z != 0)) && (m.zeroTierPhysicalEndpoints.size() > 0) ) { - const double mdist = _dist3d(m.x,m.y,m.z,px,py,pz); - if (mdist < bestDistance) { - bestDistance = mdist; -#ifdef ZT_TRACE - bestMember = *mid; -#endif - best = m.zeroTierPhysicalEndpoints; - } - } - } - } - - // Redirect to a closer member if it has a ZeroTier endpoint address in the same ss_family - for(std::vector::const_iterator a(best.begin());a!=best.end();++a) { - if (a->ss_family == peerPhysicalAddress.ss_family) { - TRACE("%s at [%d,%d,%d] is %f from us but %f from %u, can redirect to %s",peerAddress.toString().c_str(),px,py,pz,currentDistance,bestDistance,bestMember,a->toString().c_str()); - redirectTo = *a; - return true; - } - } - TRACE("%s at [%d,%d,%d] is %f from us, no better endpoints found",peerAddress.toString().c_str(),px,py,pz,currentDistance); - return false; - } else { - // TODO: pick based on load if no location info? - return false; - } -} - -bool Cluster::isClusterPeerFrontplane(const InetAddress &ip) const -{ - Mutex::Lock _l(_memberIds_m); - for(std::vector::const_iterator mid(_memberIds.begin());mid!=_memberIds.end();++mid) { - Mutex::Lock _l2(_members[*mid].lock); - for(std::vector::const_iterator i2(_members[*mid].zeroTierPhysicalEndpoints.begin());i2!=_members[*mid].zeroTierPhysicalEndpoints.end();++i2) { - if (ip == *i2) - return true; - } - } - return false; -} - -void Cluster::status(ZT_ClusterStatus &status) const -{ - const uint64_t now = RR->node->now(); - memset(&status,0,sizeof(ZT_ClusterStatus)); - - status.myId = _id; - - { - ZT_ClusterMemberStatus *const s = &(status.members[status.clusterSize++]); - s->id = _id; - s->alive = 1; - s->x = _x; - s->y = _y; - s->z = _z; - s->load = 0; // TODO - s->peers = RR->topology->countActive(now); - for(std::vector::const_iterator ep(_zeroTierPhysicalEndpoints.begin());ep!=_zeroTierPhysicalEndpoints.end();++ep) { - if (s->numZeroTierPhysicalEndpoints >= ZT_CLUSTER_MAX_ZT_PHYSICAL_ADDRESSES) // sanity check - break; - memcpy(&(s->zeroTierPhysicalEndpoints[s->numZeroTierPhysicalEndpoints++]),&(*ep),sizeof(struct sockaddr_storage)); - } - } - - { - Mutex::Lock _l1(_memberIds_m); - for(std::vector::const_iterator mid(_memberIds.begin());mid!=_memberIds.end();++mid) { - if (status.clusterSize >= ZT_CLUSTER_MAX_MEMBERS) // sanity check - break; - - _Member &m = _members[*mid]; - Mutex::Lock ml(m.lock); - - ZT_ClusterMemberStatus *const s = &(status.members[status.clusterSize++]); - s->id = *mid; - s->msSinceLastHeartbeat = (unsigned int)std::min((uint64_t)(~((unsigned int)0)),(now - m.lastReceivedAliveAnnouncement)); - s->alive = (s->msSinceLastHeartbeat < ZT_CLUSTER_TIMEOUT) ? 1 : 0; - s->x = m.x; - s->y = m.y; - s->z = m.z; - s->load = m.load; - s->peers = m.peers; - for(std::vector::const_iterator ep(m.zeroTierPhysicalEndpoints.begin());ep!=m.zeroTierPhysicalEndpoints.end();++ep) { - if (s->numZeroTierPhysicalEndpoints >= ZT_CLUSTER_MAX_ZT_PHYSICAL_ADDRESSES) // sanity check - break; - memcpy(&(s->zeroTierPhysicalEndpoints[s->numZeroTierPhysicalEndpoints++]),&(*ep),sizeof(struct sockaddr_storage)); - } - } - } -} - -void Cluster::_send(uint16_t memberId,StateMessageType type,const void *msg,unsigned int len) -{ - if ((len + 3) > (ZT_CLUSTER_MAX_MESSAGE_LENGTH - (24 + 2 + 2))) // sanity check - return; - _Member &m = _members[memberId]; - // assumes m.lock is locked! - if ((m.q.size() + len + 3) > ZT_CLUSTER_MAX_MESSAGE_LENGTH) - _flush(memberId); - m.q.append((uint16_t)(len + 1)); - m.q.append((uint8_t)type); - m.q.append(msg,len); -} - -void Cluster::_flush(uint16_t memberId) -{ - _Member &m = _members[memberId]; - // assumes m.lock is locked! - if (m.q.size() > (24 + 2 + 2)) { // 16-byte IV + 8-byte MAC + 2 byte from-member-ID + 2 byte to-member-ID - // Create key from member's key and IV - char keytmp[32]; - memcpy(keytmp,m.key,32); - for(int i=0;i<8;++i) - keytmp[i] ^= m.q[i]; - Salsa20 s20(keytmp,m.q.field(8,8)); - Utils::burn(keytmp,sizeof(keytmp)); - - // One-time-use Poly1305 key from first 32 bytes of Salsa20 keystream (as per DJB/NaCl "standard") - char polykey[ZT_POLY1305_KEY_LEN]; - memset(polykey,0,sizeof(polykey)); - s20.crypt12(polykey,polykey,sizeof(polykey)); - - // Encrypt m.q in place - s20.crypt12(reinterpret_cast(m.q.data()) + 24,const_cast(reinterpret_cast(m.q.data())) + 24,m.q.size() - 24); - - // Add MAC for authentication (encrypt-then-MAC) - char mac[ZT_POLY1305_MAC_LEN]; - Poly1305::compute(mac,reinterpret_cast(m.q.data()) + 24,m.q.size() - 24,polykey); - memcpy(m.q.field(16,8),mac,8); - - // Send! - _sendFunction(_sendFunctionArg,memberId,m.q.data(),m.q.size()); - - // Prepare for more - m.q.clear(); - char iv[16]; - Utils::getSecureRandom(iv,16); - m.q.append(iv,16); - m.q.addSize(8); // room for MAC - m.q.append((uint16_t)_id); // from member ID - m.q.append((uint16_t)memberId); // to member ID - } -} - -void Cluster::_doREMOTE_WHOIS(uint64_t fromMemberId,const Packet &remotep) -{ - if (remotep.payloadLength() >= ZT_ADDRESS_LENGTH) { - Identity queried(RR->topology->getIdentity((void *)0,Address(remotep.payload(),ZT_ADDRESS_LENGTH))); - if (queried) { - Buffer<1024> routp; - remotep.source().appendTo(routp); - routp.append((uint8_t)Packet::VERB_OK); - routp.addSize(2); // space for length - routp.append((uint8_t)Packet::VERB_WHOIS); - routp.append(remotep.packetId()); - queried.serialize(routp); - routp.setAt(ZT_ADDRESS_LENGTH + 1,(uint16_t)(routp.size() - ZT_ADDRESS_LENGTH - 3)); - - TRACE("responding to remote WHOIS from %s @ %u with identity of %s",remotep.source().toString().c_str(),(unsigned int)fromMemberId,queried.address().toString().c_str()); - Mutex::Lock _l2(_members[fromMemberId].lock); - _send(fromMemberId,CLUSTER_MESSAGE_PROXY_SEND,routp.data(),routp.size()); - } - } -} - -void Cluster::_doREMOTE_MULTICAST_GATHER(uint64_t fromMemberId,const Packet &remotep) -{ - const uint64_t nwid = remotep.at(ZT_PROTO_VERB_MULTICAST_GATHER_IDX_NETWORK_ID); - const MulticastGroup mg(MAC(remotep.field(ZT_PROTO_VERB_MULTICAST_GATHER_IDX_MAC,6),6),remotep.at(ZT_PROTO_VERB_MULTICAST_GATHER_IDX_ADI)); - unsigned int gatherLimit = remotep.at(ZT_PROTO_VERB_MULTICAST_GATHER_IDX_GATHER_LIMIT); - const Address remotePeerAddress(remotep.source()); - - if (gatherLimit) { - Buffer routp; - remotePeerAddress.appendTo(routp); - routp.append((uint8_t)Packet::VERB_OK); - routp.addSize(2); // space for length - routp.append((uint8_t)Packet::VERB_MULTICAST_GATHER); - routp.append(remotep.packetId()); - routp.append(nwid); - mg.mac().appendTo(routp); - routp.append((uint32_t)mg.adi()); - - if (gatherLimit > ((ZT_CLUSTER_MAX_MESSAGE_LENGTH - 80) / 5)) - gatherLimit = ((ZT_CLUSTER_MAX_MESSAGE_LENGTH - 80) / 5); - if (RR->mc->gather(remotePeerAddress,nwid,mg,routp,gatherLimit)) { - routp.setAt(ZT_ADDRESS_LENGTH + 1,(uint16_t)(routp.size() - ZT_ADDRESS_LENGTH - 3)); - - TRACE("responding to remote MULTICAST_GATHER from %s @ %u with %u bytes",remotePeerAddress.toString().c_str(),(unsigned int)fromMemberId,routp.size()); - Mutex::Lock _l2(_members[fromMemberId].lock); - _send(fromMemberId,CLUSTER_MESSAGE_PROXY_SEND,routp.data(),routp.size()); - } - } -} - -} // namespace ZeroTier - -#endif // ZT_ENABLE_CLUSTER diff --git a/attic/Cluster.hpp b/attic/Cluster.hpp deleted file mode 100644 index 74b091f5..00000000 --- a/attic/Cluster.hpp +++ /dev/null @@ -1,463 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -#ifndef ZT_CLUSTER_HPP -#define ZT_CLUSTER_HPP - -#ifdef ZT_ENABLE_CLUSTER - -#include - -#include "Constants.hpp" -#include "../include/ZeroTierOne.h" -#include "Address.hpp" -#include "InetAddress.hpp" -#include "SHA512.hpp" -#include "Utils.hpp" -#include "Buffer.hpp" -#include "Mutex.hpp" -#include "SharedPtr.hpp" -#include "Hashtable.hpp" -#include "Packet.hpp" -#include "SharedPtr.hpp" - -/** - * Timeout for cluster members being considered "alive" - * - * A cluster member is considered dead and will no longer have peers - * redirected to it if we have not heard a heartbeat in this long. - */ -#define ZT_CLUSTER_TIMEOUT 5000 - -/** - * Desired period between doPeriodicTasks() in milliseconds - */ -#define ZT_CLUSTER_PERIODIC_TASK_PERIOD 20 - -/** - * How often to flush outgoing message queues (maximum interval) - */ -#define ZT_CLUSTER_FLUSH_PERIOD ZT_CLUSTER_PERIODIC_TASK_PERIOD - -/** - * Maximum number of queued outgoing packets per sender address - */ -#define ZT_CLUSTER_MAX_QUEUE_PER_SENDER 16 - -/** - * Expiration time for send queue entries - */ -#define ZT_CLUSTER_QUEUE_EXPIRATION 3000 - -/** - * Chunk size for allocating queue entries - * - * Queue entries are allocated in chunks of this many and are added to a pool. - * ZT_CLUSTER_MAX_QUEUE_GLOBAL must be evenly divisible by this. - */ -#define ZT_CLUSTER_QUEUE_CHUNK_SIZE 32 - -/** - * Maximum number of chunks to ever allocate - * - * This is a global sanity limit to prevent resource exhaustion attacks. It - * works out to about 600mb of RAM. You'll never see this on a normal edge - * node. We're unlikely to see this on a root server unless someone is DOSing - * us. In that case cluster relaying will be affected but other functions - * should continue to operate normally. - */ -#define ZT_CLUSTER_MAX_QUEUE_CHUNKS 8194 - -/** - * Max data per queue entry - */ -#define ZT_CLUSTER_SEND_QUEUE_DATA_MAX 1500 - -/** - * We won't send WANT_PEER to other members more than every (ms) per recipient - */ -#define ZT_CLUSTER_WANT_PEER_EVERY 1000 - -namespace ZeroTier { - -class RuntimeEnvironment; -class MulticastGroup; -class Peer; -class Identity; - -// Internal class implemented inside Cluster.cpp -class _ClusterSendQueue; - -/** - * Multi-homing cluster state replication and packet relaying - * - * Multi-homing means more than one node sharing the same ZeroTier identity. - * There is nothing in the protocol to prevent this, but to make it work well - * requires the devices sharing an identity to cooperate and share some - * information. - * - * There are three use cases we want to fulfill: - * - * (1) Multi-homing of root servers with handoff for efficient routing, - * HA, and load balancing across many commodity nodes. - * (2) Multi-homing of network controllers for the same reason. - * (3) Multi-homing of nodes on virtual networks, such as domain servers - * and other important endpoints. - * - * These use cases are in order of escalating difficulty. The initial - * version of Cluster is aimed at satisfying the first, though you are - * free to try #2 and #3. - */ -class Cluster -{ -public: - /** - * State message types - */ - enum StateMessageType - { - CLUSTER_MESSAGE_NOP = 0, - - /** - * This cluster member is alive: - * <[2] version minor> - * <[2] version major> - * <[2] version revision> - * <[1] protocol version> - * <[4] X location (signed 32-bit)> - * <[4] Y location (signed 32-bit)> - * <[4] Z location (signed 32-bit)> - * <[8] local clock at this member> - * <[8] load average> - * <[8] number of peers> - * <[8] flags (currently unused, must be zero)> - * <[1] number of preferred ZeroTier endpoints> - * <[...] InetAddress(es) of preferred ZeroTier endpoint(s)> - * - * Cluster members constantly broadcast an alive heartbeat and will only - * receive peer redirects if they've done so within the timeout. - */ - CLUSTER_MESSAGE_ALIVE = 1, - - /** - * Cluster member has this peer: - * <[...] serialized identity of peer> - * - * This is typically sent in response to WANT_PEER but can also be pushed - * to prepopulate if this makes sense. - */ - CLUSTER_MESSAGE_HAVE_PEER = 2, - - /** - * Cluster member wants this peer: - * <[5] ZeroTier address of peer> - * - * Members that have a direct link to this peer will respond with - * HAVE_PEER. - */ - CLUSTER_MESSAGE_WANT_PEER = 3, - - /** - * A remote packet that we should also possibly respond to: - * <[2] 16-bit length of remote packet> - * <[...] remote packet payload> - * - * Cluster members may relay requests by relaying the request packet. - * These may include requests such as WHOIS and MULTICAST_GATHER. The - * packet must be already decrypted, decompressed, and authenticated. - * - * This can only be used for small request packets as per the cluster - * message size limit, but since these are the only ones in question - * this is fine. - * - * If a response is generated it is sent via PROXY_SEND. - */ - CLUSTER_MESSAGE_REMOTE_PACKET = 4, - - /** - * Request that VERB_RENDEZVOUS be sent to a peer that we have: - * <[5] ZeroTier address of peer on recipient's side> - * <[5] ZeroTier address of peer on sender's side> - * <[1] 8-bit number of sender's peer's active path addresses> - * <[...] series of serialized InetAddresses of sender's peer's paths> - * - * This requests that we perform NAT-t introduction between a peer that - * we have and one on the sender's side. The sender furnishes contact - * info for its peer, and we send VERB_RENDEZVOUS to both sides: to ours - * directly and with PROXY_SEND to theirs. - */ - CLUSTER_MESSAGE_PROXY_UNITE = 5, - - /** - * Request that a cluster member send a packet to a locally-known peer: - * <[5] ZeroTier address of recipient> - * <[1] packet verb> - * <[2] length of packet payload> - * <[...] packet payload> - * - * This differs from RELAY in that it requests the receiving cluster - * member to actually compose a ZeroTier Packet from itself to the - * provided recipient. RELAY simply says "please forward this blob." - * RELAY is used to implement peer-to-peer relaying with RENDEZVOUS, - * while PROXY_SEND is used to implement proxy sending (which right - * now is only used to send RENDEZVOUS). - */ - CLUSTER_MESSAGE_PROXY_SEND = 6, - - /** - * Replicate a network config for a network we belong to: - * <[...] network config chunk> - * - * This is used by clusters to avoid every member having to query - * for the same netconf for networks all members belong to. - * - * The first field of a network config chunk is the network ID, - * so this can be checked to look up the network on receipt. - */ - CLUSTER_MESSAGE_NETWORK_CONFIG = 7 - }; - - /** - * Construct a new cluster - */ - Cluster( - const RuntimeEnvironment *renv, - uint16_t id, - const std::vector &zeroTierPhysicalEndpoints, - int32_t x, - int32_t y, - int32_t z, - void (*sendFunction)(void *,unsigned int,const void *,unsigned int), - void *sendFunctionArg, - int (*addressToLocationFunction)(void *,const struct sockaddr_storage *,int *,int *,int *), - void *addressToLocationFunctionArg); - - ~Cluster(); - - /** - * @return This cluster member's ID - */ - inline uint16_t id() const throw() { return _id; } - - /** - * Handle an incoming intra-cluster message - * - * @param data Message data - * @param len Message length (max: ZT_CLUSTER_MAX_MESSAGE_LENGTH) - */ - void handleIncomingStateMessage(const void *msg,unsigned int len); - - /** - * Broadcast that we have a given peer - * - * This should be done when new peers are first contacted. - * - * @param id Identity of peer - */ - void broadcastHavePeer(const Identity &id); - - /** - * Broadcast a network config chunk to other members of cluster - * - * @param chunk Chunk data - * @param len Length of chunk - */ - void broadcastNetworkConfigChunk(const void *chunk,unsigned int len); - - /** - * If the cluster has this peer, prepare the packet to send via cluster - * - * Note that outp is only armored (or modified at all) if the return value is a member ID. - * - * @param toPeerAddress Value of outp.destination(), simply to save additional lookup - * @param ts Result: set to time of last HAVE_PEER from the cluster - * @param peerSecret Result: Buffer to fill with peer secret on valid return value, must be at least ZT_PEER_SECRET_KEY_LENGTH bytes - * @return -1 if cluster does not know this peer, or a member ID to pass to sendViaCluster() - */ - int checkSendViaCluster(const Address &toPeerAddress,uint64_t &mostRecentTs,void *peerSecret); - - /** - * Send data via cluster front plane (packet head or fragment) - * - * @param haveMemberId Member ID that has this peer as returned by prepSendviaCluster() - * @param toPeerAddress Destination peer address - * @param data Packet or packet fragment data - * @param len Length of packet or fragment - * @return True if packet was sent (and outp was modified via armoring) - */ - bool sendViaCluster(int haveMemberId,const Address &toPeerAddress,const void *data,unsigned int len); - - /** - * Relay a packet via the cluster - * - * This is used in the outgoing packet and relaying logic in Switch to - * relay packets to other cluster members. It isn't PROXY_SEND-- that is - * used internally in Cluster to send responses to peer queries. - * - * @param fromPeerAddress Source peer address (if known, should be NULL for fragments) - * @param toPeerAddress Destination peer address - * @param data Packet or packet fragment data - * @param len Length of packet or fragment - * @param unite If true, also request proxy unite across cluster - */ - void relayViaCluster(const Address &fromPeerAddress,const Address &toPeerAddress,const void *data,unsigned int len,bool unite); - - /** - * Send a distributed query to other cluster members - * - * Some queries such as WHOIS or MULTICAST_GATHER need a response from other - * cluster members. Replies (if any) will be sent back to the peer via - * PROXY_SEND across the cluster. - * - * @param pkt Packet to distribute - */ - void sendDistributedQuery(const Packet &pkt); - - /** - * Call every ~ZT_CLUSTER_PERIODIC_TASK_PERIOD milliseconds. - */ - void doPeriodicTasks(); - - /** - * Add a member ID to this cluster - * - * @param memberId Member ID - */ - void addMember(uint16_t memberId); - - /** - * Remove a member ID from this cluster - * - * @param memberId Member ID to remove - */ - void removeMember(uint16_t memberId); - - /** - * Find a better cluster endpoint for this peer (if any) - * - * @param redirectTo InetAddress to be set to a better endpoint (if there is one) - * @param peerAddress Address of peer to (possibly) redirect - * @param peerPhysicalAddress Physical address of peer's current best path (where packet was most recently received or getBestPath()->address()) - * @param offload Always redirect if possible -- can be used to offload peers during shutdown - * @return True if redirectTo was set to a new address, false if redirectTo was not modified - */ - bool findBetterEndpoint(InetAddress &redirectTo,const Address &peerAddress,const InetAddress &peerPhysicalAddress,bool offload); - - /** - * @param ip Address to check - * @return True if this is a cluster frontplane address (excluding our addresses) - */ - bool isClusterPeerFrontplane(const InetAddress &ip) const; - - /** - * Fill out ZT_ClusterStatus structure (from core API) - * - * @param status Reference to structure to hold result (anything there is replaced) - */ - void status(ZT_ClusterStatus &status) const; - -private: - void _send(uint16_t memberId,StateMessageType type,const void *msg,unsigned int len); - void _flush(uint16_t memberId); - - void _doREMOTE_WHOIS(uint64_t fromMemberId,const Packet &remotep); - void _doREMOTE_MULTICAST_GATHER(uint64_t fromMemberId,const Packet &remotep); - - // These are initialized in the constructor and remain immutable ------------ - uint16_t _masterSecret[ZT_SHA512_DIGEST_LEN / sizeof(uint16_t)]; - unsigned char _key[ZT_PEER_SECRET_KEY_LENGTH]; - const RuntimeEnvironment *RR; - _ClusterSendQueue *const _sendQueue; - void (*_sendFunction)(void *,unsigned int,const void *,unsigned int); - void *_sendFunctionArg; - int (*_addressToLocationFunction)(void *,const struct sockaddr_storage *,int *,int *,int *); - void *_addressToLocationFunctionArg; - const int32_t _x; - const int32_t _y; - const int32_t _z; - const uint16_t _id; - const std::vector _zeroTierPhysicalEndpoints; - // end immutable fields ----------------------------------------------------- - - struct _Member - { - unsigned char key[ZT_PEER_SECRET_KEY_LENGTH]; - - uint64_t lastReceivedAliveAnnouncement; - uint64_t lastAnnouncedAliveTo; - - uint64_t load; - uint64_t peers; - int32_t x,y,z; - - std::vector zeroTierPhysicalEndpoints; - - Buffer q; - - Mutex lock; - - inline void clear() - { - lastReceivedAliveAnnouncement = 0; - lastAnnouncedAliveTo = 0; - load = 0; - peers = 0; - x = 0; - y = 0; - z = 0; - zeroTierPhysicalEndpoints.clear(); - q.clear(); - } - - _Member() { this->clear(); } - ~_Member() { Utils::burn(key,sizeof(key)); } - }; - _Member *const _members; - - std::vector _memberIds; - Mutex _memberIds_m; - - struct _RemotePeer - { - _RemotePeer() : lastHavePeerReceived(0),lastSentWantPeer(0) {} - ~_RemotePeer() { Utils::burn(key,ZT_PEER_SECRET_KEY_LENGTH); } - uint64_t lastHavePeerReceived; - uint64_t lastSentWantPeer; - uint8_t key[ZT_PEER_SECRET_KEY_LENGTH]; // secret key from identity agreement - }; - std::map< std::pair,_RemotePeer > _remotePeers; // we need ordered behavior and lower_bound here - Mutex _remotePeers_m; - - uint64_t _lastFlushed; - uint64_t _lastCleanedRemotePeers; - uint64_t _lastCleanedQueue; -}; - -} // namespace ZeroTier - -#endif // ZT_ENABLE_CLUSTER - -#endif diff --git a/attic/ClusterDefinition.hpp b/attic/ClusterDefinition.hpp deleted file mode 100644 index b6317ff7..00000000 --- a/attic/ClusterDefinition.hpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -#ifndef ZT_CLUSTERDEFINITION_HPP -#define ZT_CLUSTERDEFINITION_HPP - -#ifdef ZT_ENABLE_CLUSTER - -#include -#include - -#include "../node/Constants.hpp" -#include "../node/Utils.hpp" -#include "../node/NonCopyable.hpp" -#include "../osdep/OSUtils.hpp" - -#include "ClusterGeoIpService.hpp" - -namespace ZeroTier { - -/** - * Parser for cluster definition file - */ -class ClusterDefinition : NonCopyable -{ -public: - struct MemberDefinition - { - MemberDefinition() : id(0),x(0),y(0),z(0) { name[0] = (char)0; } - - unsigned int id; - int x,y,z; - char name[256]; - InetAddress clusterEndpoint; - std::vector zeroTierEndpoints; - }; - - /** - * Load and initialize cluster definition and GeoIP data if any - * - * @param myAddress My ZeroTier address - * @param pathToClusterFile Path to cluster definition file - * @throws std::runtime_error Invalid cluster definition or unable to load data - */ - ClusterDefinition(uint64_t myAddress,const char *pathToClusterFile) - { - std::string cf; - if (!OSUtils::readFile(pathToClusterFile,cf)) - return; - - char myAddressStr[64]; - Utils::ztsnprintf(myAddressStr,sizeof(myAddressStr),"%.10llx",myAddress); - - std::vector lines(OSUtils::split(cf.c_str(),"\r\n","","")); - for(std::vector::iterator l(lines.begin());l!=lines.end();++l) { - std::vector fields(OSUtils::split(l->c_str()," \t","","")); - if ((fields.size() < 5)||(fields[0][0] == '#')||(fields[0] != myAddressStr)) - continue; - - //
geo - if (fields[1] == "geo") { - if ((fields.size() >= 7)&&(OSUtils::fileExists(fields[2].c_str()))) { - int ipStartColumn = Utils::strToInt(fields[3].c_str()); - int ipEndColumn = Utils::strToInt(fields[4].c_str()); - int latitudeColumn = Utils::strToInt(fields[5].c_str()); - int longitudeColumn = Utils::strToInt(fields[6].c_str()); - if (_geo.load(fields[2].c_str(),ipStartColumn,ipEndColumn,latitudeColumn,longitudeColumn) <= 0) - throw std::runtime_error(std::string("failed to load geo-ip data from ")+fields[2]); - } - continue; - } - - //
- int id = Utils::strToUInt(fields[1].c_str()); - if ((id < 0)||(id > ZT_CLUSTER_MAX_MEMBERS)) - throw std::runtime_error(std::string("invalid cluster member ID: ")+fields[1]); - MemberDefinition &md = _md[id]; - - md.id = (unsigned int)id; - if (fields.size() >= 6) { - std::vector xyz(OSUtils::split(fields[5].c_str(),",","","")); - md.x = (xyz.size() > 0) ? Utils::strToInt(xyz[0].c_str()) : 0; - md.y = (xyz.size() > 1) ? Utils::strToInt(xyz[1].c_str()) : 0; - md.z = (xyz.size() > 2) ? Utils::strToInt(xyz[2].c_str()) : 0; - } - Utils::scopy(md.name,sizeof(md.name),fields[2].c_str()); - md.clusterEndpoint.fromString(fields[3]); - if (!md.clusterEndpoint) - continue; - std::vector zips(OSUtils::split(fields[4].c_str(),",","","")); - for(std::vector::iterator zip(zips.begin());zip!=zips.end();++zip) { - InetAddress i; - i.fromString(*zip); - if (i) - md.zeroTierEndpoints.push_back(i); - } - - _ids.push_back((unsigned int)id); - } - - std::sort(_ids.begin(),_ids.end()); - } - - /** - * @return All member definitions in this cluster by ID (ID is array index) - */ - inline const MemberDefinition &operator[](unsigned int id) const throw() { return _md[id]; } - - /** - * @return Number of members in this cluster - */ - inline unsigned int size() const throw() { return (unsigned int)_ids.size(); } - - /** - * @return IDs of members in this cluster sorted by ID - */ - inline const std::vector &ids() const throw() { return _ids; } - - /** - * @return GeoIP service for this cluster - */ - inline ClusterGeoIpService &geo() throw() { return _geo; } - - /** - * @return A vector (new copy) containing all cluster members - */ - inline std::vector members() const - { - std::vector m; - for(std::vector::const_iterator i(_ids.begin());i!=_ids.end();++i) - m.push_back(_md[*i]); - return m; - } - -private: - MemberDefinition _md[ZT_CLUSTER_MAX_MEMBERS]; - std::vector _ids; - ClusterGeoIpService _geo; -}; - -} // namespace ZeroTier - -#endif // ZT_ENABLE_CLUSTER - -#endif diff --git a/attic/ClusterGeoIpService.cpp b/attic/ClusterGeoIpService.cpp deleted file mode 100644 index 2dcc9179..00000000 --- a/attic/ClusterGeoIpService.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -#ifdef ZT_ENABLE_CLUSTER - -#include - -#include - -#include "ClusterGeoIpService.hpp" - -#include "../node/Utils.hpp" -#include "../osdep/OSUtils.hpp" - -#define ZT_CLUSTERGEOIPSERVICE_FILE_MODIFICATION_CHECK_EVERY 10000 - -namespace ZeroTier { - -ClusterGeoIpService::ClusterGeoIpService() : - _pathToCsv(), - _ipStartColumn(-1), - _ipEndColumn(-1), - _latitudeColumn(-1), - _longitudeColumn(-1), - _lastFileCheckTime(0), - _csvModificationTime(0), - _csvFileSize(0) -{ -} - -ClusterGeoIpService::~ClusterGeoIpService() -{ -} - -bool ClusterGeoIpService::locate(const InetAddress &ip,int &x,int &y,int &z) -{ - Mutex::Lock _l(_lock); - - if ((_pathToCsv.length() > 0)&&((OSUtils::now() - _lastFileCheckTime) > ZT_CLUSTERGEOIPSERVICE_FILE_MODIFICATION_CHECK_EVERY)) { - _lastFileCheckTime = OSUtils::now(); - if ((_csvFileSize != OSUtils::getFileSize(_pathToCsv.c_str()))||(_csvModificationTime != OSUtils::getLastModified(_pathToCsv.c_str()))) - _load(_pathToCsv.c_str(),_ipStartColumn,_ipEndColumn,_latitudeColumn,_longitudeColumn); - } - - /* We search by looking up the upper bound of the sorted vXdb vectors - * and then iterating down for a matching IP range. We stop when we hit - * the beginning or an entry whose start and end are before the IP we - * are searching. */ - - if ((ip.ss_family == AF_INET)&&(_v4db.size() > 0)) { - _V4E key; - key.start = Utils::ntoh((uint32_t)(reinterpret_cast(&ip)->sin_addr.s_addr)); - std::vector<_V4E>::const_iterator i(std::upper_bound(_v4db.begin(),_v4db.end(),key)); - while (i != _v4db.begin()) { - --i; - if ((key.start >= i->start)&&(key.start <= i->end)) { - x = i->x; - y = i->y; - z = i->z; - //printf("%s : %f,%f %d,%d,%d\n",ip.toIpString().c_str(),i->lat,i->lon,x,y,z); - return true; - } else if ((key.start > i->start)&&(key.start > i->end)) - break; - } - } else if ((ip.ss_family == AF_INET6)&&(_v6db.size() > 0)) { - _V6E key; - memcpy(key.start,reinterpret_cast(&ip)->sin6_addr.s6_addr,16); - std::vector<_V6E>::const_iterator i(std::upper_bound(_v6db.begin(),_v6db.end(),key)); - while (i != _v6db.begin()) { - --i; - const int s_vs_s = memcmp(key.start,i->start,16); - const int s_vs_e = memcmp(key.start,i->end,16); - if ((s_vs_s >= 0)&&(s_vs_e <= 0)) { - x = i->x; - y = i->y; - z = i->z; - //printf("%s : %f,%f %d,%d,%d\n",ip.toIpString().c_str(),i->lat,i->lon,x,y,z); - return true; - } else if ((s_vs_s > 0)&&(s_vs_e > 0)) - break; - } - } - - return false; -} - -void ClusterGeoIpService::_parseLine(const char *line,std::vector<_V4E> &v4db,std::vector<_V6E> &v6db,int ipStartColumn,int ipEndColumn,int latitudeColumn,int longitudeColumn) -{ - std::vector ls(OSUtils::split(line,",\t","\\","\"'")); - if ( ((ipStartColumn >= 0)&&(ipStartColumn < (int)ls.size()))&& - ((ipEndColumn >= 0)&&(ipEndColumn < (int)ls.size()))&& - ((latitudeColumn >= 0)&&(latitudeColumn < (int)ls.size()))&& - ((longitudeColumn >= 0)&&(longitudeColumn < (int)ls.size())) ) { - InetAddress ipStart(ls[ipStartColumn].c_str(),0); - InetAddress ipEnd(ls[ipEndColumn].c_str(),0); - const double lat = strtod(ls[latitudeColumn].c_str(),(char **)0); - const double lon = strtod(ls[longitudeColumn].c_str(),(char **)0); - - if ((ipStart.ss_family == ipEnd.ss_family)&&(ipStart)&&(ipEnd)&&(std::isfinite(lat))&&(std::isfinite(lon))) { - const double latRadians = lat * 0.01745329251994; // PI / 180 - const double lonRadians = lon * 0.01745329251994; // PI / 180 - const double cosLat = cos(latRadians); - const int x = (int)round((-6371.0) * cosLat * cos(lonRadians)); // 6371 == Earth's approximate radius in kilometers - const int y = (int)round(6371.0 * sin(latRadians)); - const int z = (int)round(6371.0 * cosLat * sin(lonRadians)); - - if (ipStart.ss_family == AF_INET) { - v4db.push_back(_V4E()); - v4db.back().start = Utils::ntoh((uint32_t)(reinterpret_cast(&ipStart)->sin_addr.s_addr)); - v4db.back().end = Utils::ntoh((uint32_t)(reinterpret_cast(&ipEnd)->sin_addr.s_addr)); - v4db.back().lat = (float)lat; - v4db.back().lon = (float)lon; - v4db.back().x = x; - v4db.back().y = y; - v4db.back().z = z; - //printf("%s - %s : %d,%d,%d\n",ipStart.toIpString().c_str(),ipEnd.toIpString().c_str(),x,y,z); - } else if (ipStart.ss_family == AF_INET6) { - v6db.push_back(_V6E()); - memcpy(v6db.back().start,reinterpret_cast(&ipStart)->sin6_addr.s6_addr,16); - memcpy(v6db.back().end,reinterpret_cast(&ipEnd)->sin6_addr.s6_addr,16); - v6db.back().lat = (float)lat; - v6db.back().lon = (float)lon; - v6db.back().x = x; - v6db.back().y = y; - v6db.back().z = z; - //printf("%s - %s : %d,%d,%d\n",ipStart.toIpString().c_str(),ipEnd.toIpString().c_str(),x,y,z); - } - } - } -} - -long ClusterGeoIpService::_load(const char *pathToCsv,int ipStartColumn,int ipEndColumn,int latitudeColumn,int longitudeColumn) -{ - // assumes _lock is locked - - FILE *f = fopen(pathToCsv,"rb"); - if (!f) - return -1; - - std::vector<_V4E> v4db; - std::vector<_V6E> v6db; - v4db.reserve(16777216); - v6db.reserve(16777216); - - char buf[4096]; - char linebuf[1024]; - unsigned int lineptr = 0; - for(;;) { - int n = (int)fread(buf,1,sizeof(buf),f); - if (n <= 0) - break; - for(int i=0;i 0)||(v6db.size() > 0)) { - std::sort(v4db.begin(),v4db.end()); - std::sort(v6db.begin(),v6db.end()); - - _pathToCsv = pathToCsv; - _ipStartColumn = ipStartColumn; - _ipEndColumn = ipEndColumn; - _latitudeColumn = latitudeColumn; - _longitudeColumn = longitudeColumn; - - _lastFileCheckTime = OSUtils::now(); - _csvModificationTime = OSUtils::getLastModified(pathToCsv); - _csvFileSize = OSUtils::getFileSize(pathToCsv); - - _v4db.swap(v4db); - _v6db.swap(v6db); - - return (long)(_v4db.size() + _v6db.size()); - } else { - return 0; - } -} - -} // namespace ZeroTier - -#endif // ZT_ENABLE_CLUSTER - -/* -int main(int argc,char **argv) -{ - char buf[1024]; - - ZeroTier::ClusterGeoIpService gip; - printf("loading...\n"); - gip.load("/Users/api/Code/ZeroTier/Infrastructure/root-servers/zerotier-one/cluster-geoip.csv",0,1,5,6); - printf("... done!\n"); fflush(stdout); - - while (gets(buf)) { // unsafe, testing only - ZeroTier::InetAddress addr(buf,0); - printf("looking up: %s\n",addr.toString().c_str()); fflush(stdout); - int x = 0,y = 0,z = 0; - if (gip.locate(addr,x,y,z)) { - //printf("%s: %d,%d,%d\n",addr.toString().c_str(),x,y,z); fflush(stdout); - } else { - printf("%s: not found!\n",addr.toString().c_str()); fflush(stdout); - } - } - - return 0; -} -*/ diff --git a/attic/ClusterGeoIpService.hpp b/attic/ClusterGeoIpService.hpp deleted file mode 100644 index 380f944f..00000000 --- a/attic/ClusterGeoIpService.hpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -#ifndef ZT_CLUSTERGEOIPSERVICE_HPP -#define ZT_CLUSTERGEOIPSERVICE_HPP - -#ifdef ZT_ENABLE_CLUSTER - -#include -#include -#include -#include - -#include -#include -#include - -#include "../node/Constants.hpp" -#include "../node/Mutex.hpp" -#include "../node/NonCopyable.hpp" -#include "../node/InetAddress.hpp" - -namespace ZeroTier { - -/** - * Loads a GeoIP CSV into memory for fast lookup, reloading as needed - * - * This was designed around the CSV from https://db-ip.com but can be used - * with any similar GeoIP CSV database that is presented in the form of an - * IP range and lat/long coordinates. - * - * It loads the whole database into memory, which can be kind of large. If - * the CSV file changes, the changes are loaded automatically. - */ -class ClusterGeoIpService : NonCopyable -{ -public: - ClusterGeoIpService(); - ~ClusterGeoIpService(); - - /** - * Load or reload CSV file - * - * CSV column indexes start at zero. CSVs can be quoted with single or - * double quotes. Whitespace before or after commas is ignored. Backslash - * may be used for escaping whitespace as well. - * - * @param pathToCsv Path to (uncompressed) CSV file - * @param ipStartColumn Column with IP range start - * @param ipEndColumn Column with IP range end (inclusive) - * @param latitudeColumn Column with latitude - * @param longitudeColumn Column with longitude - * @return Number of valid records loaded or -1 on error (invalid file, not found, etc.) - */ - inline long load(const char *pathToCsv,int ipStartColumn,int ipEndColumn,int latitudeColumn,int longitudeColumn) - { - Mutex::Lock _l(_lock); - return _load(pathToCsv,ipStartColumn,ipEndColumn,latitudeColumn,longitudeColumn); - } - - /** - * Attempt to locate an IP - * - * This returns true if x, y, and z are set. If the return value is false - * the values of x, y, and z are undefined. - * - * @param ip IPv4 or IPv6 address - * @param x Reference to variable to receive X - * @param y Reference to variable to receive Y - * @param z Reference to variable to receive Z - * @return True if coordinates were set - */ - bool locate(const InetAddress &ip,int &x,int &y,int &z); - - /** - * @return True if IP database/service is available for queries (otherwise locate() will always be false) - */ - inline bool available() const - { - Mutex::Lock _l(_lock); - return ((_v4db.size() + _v6db.size()) > 0); - } - -private: - struct _V4E - { - uint32_t start; - uint32_t end; - float lat,lon; - int16_t x,y,z; - - inline bool operator<(const _V4E &e) const { return (start < e.start); } - }; - - struct _V6E - { - uint8_t start[16]; - uint8_t end[16]; - float lat,lon; - int16_t x,y,z; - - inline bool operator<(const _V6E &e) const { return (memcmp(start,e.start,16) < 0); } - }; - - static void _parseLine(const char *line,std::vector<_V4E> &v4db,std::vector<_V6E> &v6db,int ipStartColumn,int ipEndColumn,int latitudeColumn,int longitudeColumn); - long _load(const char *pathToCsv,int ipStartColumn,int ipEndColumn,int latitudeColumn,int longitudeColumn); - - std::string _pathToCsv; - int _ipStartColumn; - int _ipEndColumn; - int _latitudeColumn; - int _longitudeColumn; - - uint64_t _lastFileCheckTime; - uint64_t _csvModificationTime; - int64_t _csvFileSize; - - std::vector<_V4E> _v4db; - std::vector<_V6E> _v6db; - - Mutex _lock; -}; - -} // namespace ZeroTier - -#endif // ZT_ENABLE_CLUSTER - -#endif diff --git a/attic/FCV.hpp b/attic/FCV.hpp deleted file mode 100644 index 0fb9e250..00000000 --- a/attic/FCV.hpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -#include "Constants.hpp" - -namespace ZeroTier { - -/** - * A really simple fixed capacity vector - * - * This class does no bounds checking, so the user must ensure that - * no more than C elements are ever added and that accesses are in - * bounds. - * - * @tparam T Type to contain - * @tparam C Capacity of vector - */ -template -class FCV -{ -public: - FCV() : _s(0) {} - ~FCV() { clear(); } - - FCV(const FCV &v) : - _s(v._s) - { - for(unsigned long i=0;i<_s;++i) { - new (reinterpret_cast(_mem + (sizeof(T) * i))) T(reinterpret_cast(v._mem)[i]); - } - } - - inline FCV &operator=(const FCV &v) - { - clear(); - _s = v._s; - for(unsigned long i=0;i<_s;++i) { - new (reinterpret_cast(_mem + (sizeof(T) * i))) T(reinterpret_cast(v._mem)[i]); - } - return *this; - } - - typedef T * iterator; - typedef const T * const_iterator; - typedef unsigned long size_type; - - inline iterator begin() { return (T *)_mem; } - inline iterator end() { return (T *)(_mem + (sizeof(T) * _s)); } - inline iterator begin() const { return (const T *)_mem; } - inline iterator end() const { return (const T *)(_mem + (sizeof(T) * _s)); } - - inline T &operator[](const size_type i) { return reinterpret_cast(_mem)[i]; } - inline const T &operator[](const size_type i) const { return reinterpret_cast(_mem)[i]; } - - inline T &front() { return reinterpret_cast(_mem)[0]; } - inline const T &front() const { return reinterpret_cast(_mem)[0]; } - inline T &back() { return reinterpret_cast(_mem)[_s - 1]; } - inline const T &back() const { return reinterpret_cast(_mem)[_s - 1]; } - - inline void push_back(const T &v) { new (reinterpret_cast(_mem + (sizeof(T) * _s++))) T(v); } - inline void pop_back() { reinterpret_cast(_mem + (sizeof(T) * --_s))->~T(); } - - inline size_type size() const { return _s; } - inline size_type capacity() const { return C; } - - inline void clear() - { - for(unsigned long i=0;i<_s;++i) - reinterpret_cast(_mem + (sizeof(T) * i))->~T(); - _s = 0; - } - -private: - char _mem[sizeof(T) * C]; - unsigned long _s; -}; - -} // namespace ZeroTier diff --git a/attic/OSXEthernetTap.cpp b/attic/OSXEthernetTap.cpp deleted file mode 100644 index dbff6200..00000000 --- a/attic/OSXEthernetTap.cpp +++ /dev/null @@ -1,703 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// OSX compile fix... in6_var defines this in a struct which namespaces it for C++ ... why?!? -struct prf_ra { - u_char onlink : 1; - u_char autonomous : 1; - u_char reserved : 6; -} prf_ra; - -#include -#include - -// These are KERNEL_PRIVATE... why? -#ifndef SIOCAUTOCONF_START -#define SIOCAUTOCONF_START _IOWR('i', 132, struct in6_ifreq) /* accept rtadvd on this interface */ -#endif -#ifndef SIOCAUTOCONF_STOP -#define SIOCAUTOCONF_STOP _IOWR('i', 133, struct in6_ifreq) /* stop accepting rtadv for this interface */ -#endif - -// -------------------------------------------------------------------------- -// -------------------------------------------------------------------------- -// This source is from: -// http://www.opensource.apple.com/source/Libinfo/Libinfo-406.17/gen.subproj/getifmaddrs.c?txt -// It's here because OSX 10.6 does not have this convenience function. - -#define SALIGN (sizeof(uint32_t) - 1) -#define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : \ -(SALIGN + 1)) -#define MAX_SYSCTL_TRY 5 -#define RTA_MASKS (RTA_GATEWAY | RTA_IFP | RTA_IFA) - -/* FreeBSD uses NET_RT_IFMALIST and RTM_NEWMADDR from */ -/* We can use NET_RT_IFLIST2 and RTM_NEWMADDR2 on Darwin */ -//#define DARWIN_COMPAT - -//#ifdef DARWIN_COMPAT -#define GIM_SYSCTL_MIB NET_RT_IFLIST2 -#define GIM_RTM_ADDR RTM_NEWMADDR2 -//#else -//#define GIM_SYSCTL_MIB NET_RT_IFMALIST -//#define GIM_RTM_ADDR RTM_NEWMADDR -//#endif - -// Not in 10.6 includes so use our own -struct _intl_ifmaddrs { - struct _intl_ifmaddrs *ifma_next; - struct sockaddr *ifma_name; - struct sockaddr *ifma_addr; - struct sockaddr *ifma_lladdr; -}; - -static inline int _intl_getifmaddrs(struct _intl_ifmaddrs **pif) -{ - int icnt = 1; - int dcnt = 0; - int ntry = 0; - size_t len; - size_t needed; - int mib[6]; - int i; - char *buf; - char *data; - char *next; - char *p; - struct ifma_msghdr2 *ifmam; - struct _intl_ifmaddrs *ifa, *ift; - struct rt_msghdr *rtm; - struct sockaddr *sa; - - mib[0] = CTL_NET; - mib[1] = PF_ROUTE; - mib[2] = 0; /* protocol */ - mib[3] = 0; /* wildcard address family */ - mib[4] = GIM_SYSCTL_MIB; - mib[5] = 0; /* no flags */ - do { - if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) - return (-1); - if ((buf = (char *)malloc(needed)) == NULL) - return (-1); - if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { - if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) { - free(buf); - return (-1); - } - free(buf); - buf = NULL; - } - } while (buf == NULL); - - for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { - rtm = (struct rt_msghdr *)(void *)next; - if (rtm->rtm_version != RTM_VERSION) - continue; - switch (rtm->rtm_type) { - case GIM_RTM_ADDR: - ifmam = (struct ifma_msghdr2 *)(void *)rtm; - if ((ifmam->ifmam_addrs & RTA_IFA) == 0) - break; - icnt++; - p = (char *)(ifmam + 1); - for (i = 0; i < RTAX_MAX; i++) { - if ((RTA_MASKS & ifmam->ifmam_addrs & - (1 << i)) == 0) - continue; - sa = (struct sockaddr *)(void *)p; - len = SA_RLEN(sa); - dcnt += len; - p += len; - } - break; - } - } - - data = (char *)malloc(sizeof(struct _intl_ifmaddrs) * icnt + dcnt); - if (data == NULL) { - free(buf); - return (-1); - } - - ifa = (struct _intl_ifmaddrs *)(void *)data; - data += sizeof(struct _intl_ifmaddrs) * icnt; - - memset(ifa, 0, sizeof(struct _intl_ifmaddrs) * icnt); - ift = ifa; - - for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { - rtm = (struct rt_msghdr *)(void *)next; - if (rtm->rtm_version != RTM_VERSION) - continue; - - switch (rtm->rtm_type) { - case GIM_RTM_ADDR: - ifmam = (struct ifma_msghdr2 *)(void *)rtm; - if ((ifmam->ifmam_addrs & RTA_IFA) == 0) - break; - - p = (char *)(ifmam + 1); - for (i = 0; i < RTAX_MAX; i++) { - if ((RTA_MASKS & ifmam->ifmam_addrs & - (1 << i)) == 0) - continue; - sa = (struct sockaddr *)(void *)p; - len = SA_RLEN(sa); - switch (i) { - case RTAX_GATEWAY: - ift->ifma_lladdr = - (struct sockaddr *)(void *)data; - memcpy(data, p, len); - data += len; - break; - - case RTAX_IFP: - ift->ifma_name = - (struct sockaddr *)(void *)data; - memcpy(data, p, len); - data += len; - break; - - case RTAX_IFA: - ift->ifma_addr = - (struct sockaddr *)(void *)data; - memcpy(data, p, len); - data += len; - break; - - default: - data += len; - break; - } - p += len; - } - ift->ifma_next = ift + 1; - ift = ift->ifma_next; - break; - } - } - - free(buf); - - if (ift > ifa) { - ift--; - ift->ifma_next = NULL; - *pif = ifa; - } else { - *pif = NULL; - free(ifa); - } - return (0); -} - -static inline void _intl_freeifmaddrs(struct _intl_ifmaddrs *ifmp) -{ - free(ifmp); -} - -// -------------------------------------------------------------------------- -// -------------------------------------------------------------------------- - -#include -#include -#include -#include - -#include "../node/Constants.hpp" -#include "../node/Utils.hpp" -#include "../node/Mutex.hpp" -#include "../node/Dictionary.hpp" -#include "OSUtils.hpp" -#include "OSXEthernetTap.hpp" - -// ff:ff:ff:ff:ff:ff with no ADI -static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff),0); - -static inline bool _setIpv6Stuff(const char *ifname,bool performNUD,bool acceptRouterAdverts) -{ - struct in6_ndireq nd; - struct in6_ifreq ifr; - - int s = socket(AF_INET6,SOCK_DGRAM,0); - if (s <= 0) - return false; - - memset(&nd,0,sizeof(nd)); - strncpy(nd.ifname,ifname,sizeof(nd.ifname)); - - if (ioctl(s,SIOCGIFINFO_IN6,&nd)) { - close(s); - return false; - } - - unsigned long oldFlags = (unsigned long)nd.ndi.flags; - - if (performNUD) - nd.ndi.flags |= ND6_IFF_PERFORMNUD; - else nd.ndi.flags &= ~ND6_IFF_PERFORMNUD; - - if (oldFlags != (unsigned long)nd.ndi.flags) { - if (ioctl(s,SIOCSIFINFO_FLAGS,&nd)) { - close(s); - return false; - } - } - - memset(&ifr,0,sizeof(ifr)); - strncpy(ifr.ifr_name,ifname,sizeof(ifr.ifr_name)); - if (ioctl(s,acceptRouterAdverts ? SIOCAUTOCONF_START : SIOCAUTOCONF_STOP,&ifr)) { - close(s); - return false; - } - - close(s); - return true; -} - -namespace ZeroTier { - -static long globalTapsRunning = 0; -static Mutex globalTapCreateLock; - -OSXEthernetTap::OSXEthernetTap( - const char *homePath, - const MAC &mac, - unsigned int mtu, - unsigned int metric, - uint64_t nwid, - const char *friendlyName, - void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *data,unsigned int len), - void *arg) : - _handler(handler), - _arg(arg), - _nwid(nwid), - _homePath(homePath), - _mtu(mtu), - _metric(metric), - _fd(0), - _enabled(true) -{ - char devpath[64],ethaddr[64],mtustr[32],metstr[32],nwids[32]; - struct stat stattmp; - - OSUtils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid); - - Mutex::Lock _gl(globalTapCreateLock); - - if (::stat("/dev/zt0",&stattmp)) { - long kextpid = (long)vfork(); - if (kextpid == 0) { - ::chdir(homePath); - OSUtils::redirectUnixOutputs("/dev/null",(const char *)0); - ::execl("/sbin/kextload","/sbin/kextload","-q","-repository",homePath,"tap.kext",(const char *)0); - ::_exit(-1); - } else if (kextpid > 0) { - int exitcode = -1; - ::waitpid(kextpid,&exitcode,0); - } - ::usleep(500); // give tap device driver time to start up and try again - if (::stat("/dev/zt0",&stattmp)) - throw std::runtime_error("/dev/zt# tap devices do not exist and cannot load tap.kext"); - } - - // Try to reopen the last device we had, if we had one and it's still unused. - std::map globalDeviceMap; - FILE *devmapf = fopen((_homePath + ZT_PATH_SEPARATOR_S + "devicemap").c_str(),"r"); - if (devmapf) { - char buf[256]; - while (fgets(buf,sizeof(buf),devmapf)) { - char *x = (char *)0; - char *y = (char *)0; - char *saveptr = (char *)0; - for(char *f=Utils::stok(buf,"\r\n=",&saveptr);(f);f=Utils::stok((char *)0,"\r\n=",&saveptr)) { - if (!x) x = f; - else if (!y) y = f; - else break; - } - if ((x)&&(y)&&(x[0])&&(y[0])) - globalDeviceMap[x] = y; - } - fclose(devmapf); - } - bool recalledDevice = false; - std::map::const_iterator gdmEntry = globalDeviceMap.find(nwids); - if (gdmEntry != globalDeviceMap.end()) { - std::string devpath("/dev/"); devpath.append(gdmEntry->second); - if (stat(devpath.c_str(),&stattmp) == 0) { - _fd = ::open(devpath.c_str(),O_RDWR); - if (_fd > 0) { - _dev = gdmEntry->second; - recalledDevice = true; - } - } - } - - // Open the first unused tap device if we didn't recall a previous one. - if (!recalledDevice) { - for(int i=0;i<64;++i) { - OSUtils::ztsnprintf(devpath,sizeof(devpath),"/dev/zt%d",i); - if (stat(devpath,&stattmp)) - throw std::runtime_error("no more TAP devices available"); - _fd = ::open(devpath,O_RDWR); - if (_fd > 0) { - char foo[16]; - OSUtils::ztsnprintf(foo,sizeof(foo),"zt%d",i); - _dev = foo; - break; - } - } - } - - if (_fd <= 0) - throw std::runtime_error("unable to open TAP device or no more devices available"); - - if (fcntl(_fd,F_SETFL,fcntl(_fd,F_GETFL) & ~O_NONBLOCK) == -1) { - ::close(_fd); - throw std::runtime_error("unable to set flags on file descriptor for TAP device"); - } - - // Configure MAC address and MTU, bring interface up - OSUtils::ztsnprintf(ethaddr,sizeof(ethaddr),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)mac[0],(int)mac[1],(int)mac[2],(int)mac[3],(int)mac[4],(int)mac[5]); - OSUtils::ztsnprintf(mtustr,sizeof(mtustr),"%u",_mtu); - OSUtils::ztsnprintf(metstr,sizeof(metstr),"%u",_metric); - long cpid = (long)vfork(); - if (cpid == 0) { - ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"lladdr",ethaddr,"mtu",mtustr,"metric",metstr,"up",(const char *)0); - ::_exit(-1); - } else if (cpid > 0) { - int exitcode = -1; - ::waitpid(cpid,&exitcode,0); - if (exitcode) { - ::close(_fd); - throw std::runtime_error("ifconfig failure setting link-layer address and activating tap interface"); - } - } - - _setIpv6Stuff(_dev.c_str(),true,false); - - // Set close-on-exec so that devices cannot persist if we fork/exec for update - fcntl(_fd,F_SETFD,fcntl(_fd,F_GETFD) | FD_CLOEXEC); - - ::pipe(_shutdownSignalPipe); - - ++globalTapsRunning; - - globalDeviceMap[nwids] = _dev; - devmapf = fopen((_homePath + ZT_PATH_SEPARATOR_S + "devicemap").c_str(),"w"); - if (devmapf) { - gdmEntry = globalDeviceMap.begin(); - while (gdmEntry != globalDeviceMap.end()) { - fprintf(devmapf,"%s=%s\n",gdmEntry->first.c_str(),gdmEntry->second.c_str()); - ++gdmEntry; - } - fclose(devmapf); - } - - _thread = Thread::start(this); -} - -OSXEthernetTap::~OSXEthernetTap() -{ - ::write(_shutdownSignalPipe[1],"\0",1); // causes thread to exit - Thread::join(_thread); - - ::close(_fd); - ::close(_shutdownSignalPipe[0]); - ::close(_shutdownSignalPipe[1]); - - { - Mutex::Lock _gl(globalTapCreateLock); - if (--globalTapsRunning <= 0) { - globalTapsRunning = 0; // sanity check -- should not be possible - - char tmp[16384]; - sprintf(tmp,"%s/%s",_homePath.c_str(),"tap.kext"); - long kextpid = (long)vfork(); - if (kextpid == 0) { - OSUtils::redirectUnixOutputs("/dev/null",(const char *)0); - ::execl("/sbin/kextunload","/sbin/kextunload",tmp,(const char *)0); - ::_exit(-1); - } else if (kextpid > 0) { - int exitcode = -1; - ::waitpid(kextpid,&exitcode,0); - } - } - } -} - -void OSXEthernetTap::setEnabled(bool en) -{ - _enabled = en; - // TODO: interface status change -} - -bool OSXEthernetTap::enabled() const -{ - return _enabled; -} - -bool OSXEthernetTap::addIp(const InetAddress &ip) -{ - if (!ip) - return false; - - long cpid = (long)vfork(); - if (cpid == 0) { - char tmp[128]; - ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),(ip.ss_family == AF_INET6) ? "inet6" : "inet",ip.toString(tmp),"alias",(const char *)0); - ::_exit(-1); - } else if (cpid > 0) { - int exitcode = -1; - ::waitpid(cpid,&exitcode,0); - return (exitcode == 0); - } // else return false... - - return false; -} - -bool OSXEthernetTap::removeIp(const InetAddress &ip) -{ - if (!ip) - return true; - std::vector allIps(ips()); - for(std::vector::iterator i(allIps.begin());i!=allIps.end();++i) { - if (*i == ip) { - long cpid = (long)vfork(); - if (cpid == 0) { - char tmp[128]; - execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),(ip.ss_family == AF_INET6) ? "inet6" : "inet",ip.toIpString(tmp),"-alias",(const char *)0); - _exit(-1); - } else if (cpid > 0) { - int exitcode = -1; - waitpid(cpid,&exitcode,0); - return (exitcode == 0); - } - } - } - return false; -} - -std::vector OSXEthernetTap::ips() const -{ - struct ifaddrs *ifa = (struct ifaddrs *)0; - if (getifaddrs(&ifa)) - return std::vector(); - - std::vector r; - - struct ifaddrs *p = ifa; - while (p) { - if ((!strcmp(p->ifa_name,_dev.c_str()))&&(p->ifa_addr)&&(p->ifa_netmask)&&(p->ifa_addr->sa_family == p->ifa_netmask->sa_family)) { - switch(p->ifa_addr->sa_family) { - case AF_INET: { - struct sockaddr_in *sin = (struct sockaddr_in *)p->ifa_addr; - struct sockaddr_in *nm = (struct sockaddr_in *)p->ifa_netmask; - r.push_back(InetAddress(&(sin->sin_addr.s_addr),4,Utils::countBits((uint32_t)nm->sin_addr.s_addr))); - } break; - case AF_INET6: { - struct sockaddr_in6 *sin = (struct sockaddr_in6 *)p->ifa_addr; - struct sockaddr_in6 *nm = (struct sockaddr_in6 *)p->ifa_netmask; - uint32_t b[4]; - memcpy(b,nm->sin6_addr.s6_addr,sizeof(b)); - r.push_back(InetAddress(sin->sin6_addr.s6_addr,16,Utils::countBits(b[0]) + Utils::countBits(b[1]) + Utils::countBits(b[2]) + Utils::countBits(b[3]))); - } break; - } - } - p = p->ifa_next; - } - - if (ifa) - freeifaddrs(ifa); - - std::sort(r.begin(),r.end()); - r.erase(std::unique(r.begin(),r.end()),r.end()); - - return r; -} - -void OSXEthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len) -{ - char putBuf[ZT_MAX_MTU + 64]; - if ((_fd > 0)&&(len <= _mtu)&&(_enabled)) { - to.copyTo(putBuf,6); - from.copyTo(putBuf + 6,6); - *((uint16_t *)(putBuf + 12)) = htons((uint16_t)etherType); - memcpy(putBuf + 14,data,len); - len += 14; - ::write(_fd,putBuf,len); - } -} - -std::string OSXEthernetTap::deviceName() const -{ - return _dev; -} - -void OSXEthernetTap::setFriendlyName(const char *friendlyName) -{ -} - -void OSXEthernetTap::scanMulticastGroups(std::vector &added,std::vector &removed) -{ - std::vector newGroups; - - struct _intl_ifmaddrs *ifmap = (struct _intl_ifmaddrs *)0; - if (!_intl_getifmaddrs(&ifmap)) { - struct _intl_ifmaddrs *p = ifmap; - while (p) { - if (p->ifma_addr->sa_family == AF_LINK) { - struct sockaddr_dl *in = (struct sockaddr_dl *)p->ifma_name; - struct sockaddr_dl *la = (struct sockaddr_dl *)p->ifma_addr; - if ((la->sdl_alen == 6)&&(in->sdl_nlen <= _dev.length())&&(!memcmp(_dev.data(),in->sdl_data,in->sdl_nlen))) - newGroups.push_back(MulticastGroup(MAC(la->sdl_data + la->sdl_nlen,6),0)); - } - p = p->ifma_next; - } - _intl_freeifmaddrs(ifmap); - } - - std::vector allIps(ips()); - for(std::vector::iterator ip(allIps.begin());ip!=allIps.end();++ip) - newGroups.push_back(MulticastGroup::deriveMulticastGroupForAddressResolution(*ip)); - - std::sort(newGroups.begin(),newGroups.end()); - std::unique(newGroups.begin(),newGroups.end()); - - for(std::vector::iterator m(newGroups.begin());m!=newGroups.end();++m) { - if (!std::binary_search(_multicastGroups.begin(),_multicastGroups.end(),*m)) - added.push_back(*m); - } - for(std::vector::iterator m(_multicastGroups.begin());m!=_multicastGroups.end();++m) { - if (!std::binary_search(newGroups.begin(),newGroups.end(),*m)) - removed.push_back(*m); - } - - _multicastGroups.swap(newGroups); -} - -void OSXEthernetTap::setMtu(unsigned int mtu) -{ - if (mtu != _mtu) { - _mtu = mtu; - long cpid = (long)vfork(); - if (cpid == 0) { - char tmp[64]; - OSUtils::ztsnprintf(tmp,sizeof(tmp),"%u",mtu); - execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"mtu",tmp,(const char *)0); - _exit(-1); - } else if (cpid > 0) { - int exitcode = -1; - waitpid(cpid,&exitcode,0); - } - } -} - -void OSXEthernetTap::threadMain() - throw() -{ - fd_set readfds,nullfds; - MAC to,from; - int n,nfds,r; - char getBuf[ZT_MAX_MTU + 64]; - - Thread::sleep(500); - - FD_ZERO(&readfds); - FD_ZERO(&nullfds); - nfds = (int)std::max(_shutdownSignalPipe[0],_fd) + 1; - - r = 0; - for(;;) { - FD_SET(_shutdownSignalPipe[0],&readfds); - FD_SET(_fd,&readfds); - select(nfds,&readfds,&nullfds,&nullfds,(struct timeval *)0); - - if (FD_ISSET(_shutdownSignalPipe[0],&readfds)) // writes to shutdown pipe terminate thread - break; - - if (FD_ISSET(_fd,&readfds)) { - n = (int)::read(_fd,getBuf + r,sizeof(getBuf) - r); - if (n < 0) { - if ((errno != EINTR)&&(errno != ETIMEDOUT)) - break; - } else { - // Some tap drivers like to send the ethernet frame and the - // payload in two chunks, so handle that by accumulating - // data until we have at least a frame. - r += n; - if (r > 14) { - if (r > ((int)_mtu + 14)) // sanity check for weird TAP behavior on some platforms - r = _mtu + 14; - - if (_enabled) { - to.setTo(getBuf,6); - from.setTo(getBuf + 6,6); - unsigned int etherType = ntohs(((const uint16_t *)getBuf)[6]); - // TODO: VLAN support - _handler(_arg,(void *)0,_nwid,from,to,etherType,0,(const void *)(getBuf + 14),r - 14); - } - - r = 0; - } - } - } - } -} - -} // namespace ZeroTier diff --git a/attic/OSXEthernetTap.cpp.pcap-with-bridge-test b/attic/OSXEthernetTap.cpp.pcap-with-bridge-test deleted file mode 100644 index baae0a4b..00000000 --- a/attic/OSXEthernetTap.cpp.pcap-with-bridge-test +++ /dev/null @@ -1,650 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2015 ZeroTier, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * ZeroTier may be used and distributed under the terms of the GPLv3, which - * are available at: http://www.gnu.org/licenses/gpl-3.0.html - * - * If you would like to embed ZeroTier into a commercial application or - * redistribute it in a modified binary form, please contact ZeroTier Networks - * LLC. Start here: http://www.zerotier.com/ - */ - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -// OSX compile fix... in6_var defines this in a struct which namespaces it for C++ ... why?!? -struct prf_ra { - u_char onlink : 1; - u_char autonomous : 1; - u_char reserved : 6; -} prf_ra; - -#include -#include - -// These are KERNEL_PRIVATE... why? -#ifndef SIOCAUTOCONF_START -#define SIOCAUTOCONF_START _IOWR('i', 132, struct in6_ifreq) /* accept rtadvd on this interface */ -#endif -#ifndef SIOCAUTOCONF_STOP -#define SIOCAUTOCONF_STOP _IOWR('i', 133, struct in6_ifreq) /* stop accepting rtadv for this interface */ -#endif - -#ifndef ETH_ALEN -#define ETH_ALEN 6 -#endif - -// -------------------------------------------------------------------------- -// -------------------------------------------------------------------------- -// This source is from: -// http://www.opensource.apple.com/source/Libinfo/Libinfo-406.17/gen.subproj/getifmaddrs.c?txt -// It's here because OSX 10.6 does not have this convenience function. - -#define SALIGN (sizeof(uint32_t) - 1) -#define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : \ -(SALIGN + 1)) -#define MAX_SYSCTL_TRY 5 -#define RTA_MASKS (RTA_GATEWAY | RTA_IFP | RTA_IFA) - -/* FreeBSD uses NET_RT_IFMALIST and RTM_NEWMADDR from */ -/* We can use NET_RT_IFLIST2 and RTM_NEWMADDR2 on Darwin */ -//#define DARWIN_COMPAT - -//#ifdef DARWIN_COMPAT -#define GIM_SYSCTL_MIB NET_RT_IFLIST2 -#define GIM_RTM_ADDR RTM_NEWMADDR2 -//#else -//#define GIM_SYSCTL_MIB NET_RT_IFMALIST -//#define GIM_RTM_ADDR RTM_NEWMADDR -//#endif - -// Not in 10.6 includes so use our own -struct _intl_ifmaddrs { - struct _intl_ifmaddrs *ifma_next; - struct sockaddr *ifma_name; - struct sockaddr *ifma_addr; - struct sockaddr *ifma_lladdr; -}; - -static inline int _intl_getifmaddrs(struct _intl_ifmaddrs **pif) -{ - int icnt = 1; - int dcnt = 0; - int ntry = 0; - size_t len; - size_t needed; - int mib[6]; - int i; - char *buf; - char *data; - char *next; - char *p; - struct ifma_msghdr2 *ifmam; - struct _intl_ifmaddrs *ifa, *ift; - struct rt_msghdr *rtm; - struct sockaddr *sa; - - mib[0] = CTL_NET; - mib[1] = PF_ROUTE; - mib[2] = 0; /* protocol */ - mib[3] = 0; /* wildcard address family */ - mib[4] = GIM_SYSCTL_MIB; - mib[5] = 0; /* no flags */ - do { - if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) - return (-1); - if ((buf = (char *)malloc(needed)) == NULL) - return (-1); - if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { - if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) { - free(buf); - return (-1); - } - free(buf); - buf = NULL; - } - } while (buf == NULL); - - for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { - rtm = (struct rt_msghdr *)(void *)next; - if (rtm->rtm_version != RTM_VERSION) - continue; - switch (rtm->rtm_type) { - case GIM_RTM_ADDR: - ifmam = (struct ifma_msghdr2 *)(void *)rtm; - if ((ifmam->ifmam_addrs & RTA_IFA) == 0) - break; - icnt++; - p = (char *)(ifmam + 1); - for (i = 0; i < RTAX_MAX; i++) { - if ((RTA_MASKS & ifmam->ifmam_addrs & - (1 << i)) == 0) - continue; - sa = (struct sockaddr *)(void *)p; - len = SA_RLEN(sa); - dcnt += len; - p += len; - } - break; - } - } - - data = (char *)malloc(sizeof(struct _intl_ifmaddrs) * icnt + dcnt); - if (data == NULL) { - free(buf); - return (-1); - } - - ifa = (struct _intl_ifmaddrs *)(void *)data; - data += sizeof(struct _intl_ifmaddrs) * icnt; - - memset(ifa, 0, sizeof(struct _intl_ifmaddrs) * icnt); - ift = ifa; - - for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { - rtm = (struct rt_msghdr *)(void *)next; - if (rtm->rtm_version != RTM_VERSION) - continue; - - switch (rtm->rtm_type) { - case GIM_RTM_ADDR: - ifmam = (struct ifma_msghdr2 *)(void *)rtm; - if ((ifmam->ifmam_addrs & RTA_IFA) == 0) - break; - - p = (char *)(ifmam + 1); - for (i = 0; i < RTAX_MAX; i++) { - if ((RTA_MASKS & ifmam->ifmam_addrs & - (1 << i)) == 0) - continue; - sa = (struct sockaddr *)(void *)p; - len = SA_RLEN(sa); - switch (i) { - case RTAX_GATEWAY: - ift->ifma_lladdr = - (struct sockaddr *)(void *)data; - memcpy(data, p, len); - data += len; - break; - - case RTAX_IFP: - ift->ifma_name = - (struct sockaddr *)(void *)data; - memcpy(data, p, len); - data += len; - break; - - case RTAX_IFA: - ift->ifma_addr = - (struct sockaddr *)(void *)data; - memcpy(data, p, len); - data += len; - break; - - default: - data += len; - break; - } - p += len; - } - ift->ifma_next = ift + 1; - ift = ift->ifma_next; - break; - } - } - - free(buf); - - if (ift > ifa) { - ift--; - ift->ifma_next = NULL; - *pif = ifa; - } else { - *pif = NULL; - free(ifa); - } - return (0); -} - -static inline void _intl_freeifmaddrs(struct _intl_ifmaddrs *ifmp) -{ - free(ifmp); -} - -// -------------------------------------------------------------------------- -// -------------------------------------------------------------------------- - -#include -#include -#include -#include - -#include "../node/Constants.hpp" -#include "../node/Utils.hpp" -#include "../node/Mutex.hpp" -#include "../node/Dictionary.hpp" -#include "OSUtils.hpp" -#include "OSXEthernetTap.hpp" - -// ff:ff:ff:ff:ff:ff with no ADI -static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff),0); - -static inline bool _setIpv6Stuff(const char *ifname,bool performNUD,bool acceptRouterAdverts) -{ - struct in6_ndireq nd; - struct in6_ifreq ifr; - - int s = socket(AF_INET6,SOCK_DGRAM,0); - if (s <= 0) - return false; - - memset(&nd,0,sizeof(nd)); - strncpy(nd.ifname,ifname,sizeof(nd.ifname)); - - if (ioctl(s,SIOCGIFINFO_IN6,&nd)) { - close(s); - return false; - } - - unsigned long oldFlags = (unsigned long)nd.ndi.flags; - - if (performNUD) - nd.ndi.flags |= ND6_IFF_PERFORMNUD; - else nd.ndi.flags &= ~ND6_IFF_PERFORMNUD; - - if (oldFlags != (unsigned long)nd.ndi.flags) { - if (ioctl(s,SIOCSIFINFO_FLAGS,&nd)) { - close(s); - return false; - } - } - - memset(&ifr,0,sizeof(ifr)); - strncpy(ifr.ifr_name,ifname,sizeof(ifr.ifr_name)); - if (ioctl(s,acceptRouterAdverts ? SIOCAUTOCONF_START : SIOCAUTOCONF_STOP,&ifr)) { - close(s); - return false; - } - - close(s); - return true; -} - -namespace ZeroTier { - -static std::set globalDeviceNames; -static Mutex globalTapCreateLock; - -OSXEthernetTap::OSXEthernetTap( - const char *homePath, - const MAC &mac, - unsigned int mtu, - unsigned int metric, - uint64_t nwid, - const char *friendlyName, - void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *data,unsigned int len), - void *arg) : - _handler(handler), - _arg(arg), - _pcap((void *)0), - _nwid(nwid), - _mac(mac), - _homePath(homePath), - _mtu(mtu), - _metric(metric), - _enabled(true) -{ - char errbuf[PCAP_ERRBUF_SIZE]; - char devname[64],ethaddr[64],mtustr[32],metstr[32],nwids[32]; - - Utils::snprintf(nwids,sizeof(nwids),"%.16llx",nwid); - - if (mtu > 2800) - throw std::runtime_error("max tap MTU is 2800"); - - Mutex::Lock _gl(globalTapCreateLock); - - std::string desiredDevice; - Dictionary devmap; - { - std::string devmapbuf; - if (OSUtils::readFile((_homePath + ZT_PATH_SEPARATOR_S + "devicemap").c_str(),devmapbuf)) { - devmap.fromString(devmapbuf); - desiredDevice = devmap.get(nwids,""); - } - } - - if ((desiredDevice.length() >= 9)&&(desiredDevice.substr(0,6) == "bridge")) { - // length() >= 9 matches bridge### or bridge#### - _dev = desiredDevice; - } else { - if (globalDeviceNames.size() >= (10000 - 128)) // sanity check... this would be nuts - throw std::runtime_error("too many devices!"); - unsigned int pseudoBridgeNo = (unsigned int)((nwid ^ (nwid >> 32)) % (10000 - 128)) + 128; // range: bridge128 to bridge9999 - sprintf(devname,"bridge%u",pseudoBridgeNo); - while (globalDeviceNames.count(std::string(devname)) > 0) { - ++pseudoBridgeNo; - if (pseudoBridgeNo > 9999) - pseudoBridgeNo = 64; - sprintf(devname,"bridge%u",pseudoBridgeNo); - } - _dev = devname; - } - - // Configure MAC address and MTU, bring interface up - long cpid = (long)vfork(); - if (cpid == 0) { - ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"create",(const char *)0); - ::_exit(-1); - } else if (cpid > 0) { - int exitcode = -1; - ::waitpid(cpid,&exitcode,0); - if (exitcode != 0) - throw std::runtime_error("ifconfig failure setting link-layer address and activating tap interface"); - } else throw std::runtime_error("unable to fork()"); - Utils::snprintf(ethaddr,sizeof(ethaddr),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)mac[0],(int)mac[1],(int)mac[2],(int)mac[3],(int)mac[4],(int)mac[5]); - Utils::snprintf(mtustr,sizeof(mtustr),"%u",_mtu); - Utils::snprintf(metstr,sizeof(metstr),"%u",_metric); - cpid = (long)vfork(); - if (cpid == 0) { - ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"lladdr",ethaddr,"mtu",mtustr,"metric",metstr,"up",(const char *)0); - ::_exit(-1); - } else if (cpid > 0) { - int exitcode = -1; - ::waitpid(cpid,&exitcode,0); - if (exitcode != 0) - throw std::runtime_error("ifconfig failure setting link-layer address and activating tap interface"); - } else throw std::runtime_error("unable to fork()"); - - _setIpv6Stuff(_dev.c_str(),true,false); - - _pcap = (void *)pcap_create(_dev.c_str(),errbuf); - if (!_pcap) { - cpid = (long)vfork(); - if (cpid == 0) { - ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"destroy",(const char *)0); - ::_exit(-1); - } else if (cpid > 0) { - int exitcode = -1; - ::waitpid(cpid,&exitcode,0); - } - throw std::runtime_error((std::string("pcap_create() on new bridge device failed: ") + errbuf).c_str()); - } - pcap_set_promisc(reinterpret_cast(_pcap),1); - pcap_set_timeout(reinterpret_cast(_pcap),120000); - pcap_set_immediate_mode(reinterpret_cast(_pcap),1); - if (pcap_set_buffer_size(reinterpret_cast(_pcap),1024 * 1024 * 16) != 0) // 16MB - fprintf(stderr,"WARNING: pcap_set_buffer_size() failed!\n"); - if (pcap_set_snaplen(reinterpret_cast(_pcap),4096) != 0) - fprintf(stderr,"WARNING: pcap_set_snaplen() failed!\n"); - if (pcap_activate(reinterpret_cast(_pcap)) != 0) { - pcap_close(reinterpret_cast(_pcap)); - cpid = (long)vfork(); - if (cpid == 0) { - ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"destroy",(const char *)0); - ::_exit(-1); - } else if (cpid > 0) { - int exitcode = -1; - ::waitpid(cpid,&exitcode,0); - } - throw std::runtime_error("pcap_activate() on new bridge device failed."); - } - - globalDeviceNames.insert(_dev); - - devmap[nwids] = _dev; - OSUtils::writeFile((_homePath + ZT_PATH_SEPARATOR_S + "devicemap").c_str(),devmap.toString()); - - _thread = Thread::start(this); -} - -OSXEthernetTap::~OSXEthernetTap() -{ - _enabled = false; - - Mutex::Lock _gl(globalTapCreateLock); - globalDeviceNames.erase(_dev); - - long cpid = (long)vfork(); - if (cpid == 0) { - ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"destroy",(const char *)0); - ::_exit(-1); - } else if (cpid > 0) { - int exitcode = -1; - ::waitpid(cpid,&exitcode,0); - if (exitcode == 0) { - // Destroying the interface nukes pcap and terminates the thread. - Thread::join(_thread); - } - } - - pcap_close(reinterpret_cast(_pcap)); -} - -static bool ___removeIp(const std::string &_dev,const InetAddress &ip) -{ - long cpid = (long)vfork(); - if (cpid == 0) { - execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"inet",ip.toIpString().c_str(),"-alias",(const char *)0); - _exit(-1); - } else if (cpid > 0) { - int exitcode = -1; - waitpid(cpid,&exitcode,0); - return (exitcode == 0); - } - return false; // never reached, make compiler shut up about return value -} - -bool OSXEthernetTap::addIp(const InetAddress &ip) -{ - if (!ip) - return false; - - std::vector allIps(ips()); - if (std::binary_search(allIps.begin(),allIps.end(),ip)) - return true; - - // Remove and reconfigure if address is the same but netmask is different - for(std::vector::iterator i(allIps.begin());i!=allIps.end();++i) { - if ((i->ipsEqual(ip))&&(i->netmaskBits() != ip.netmaskBits())) { - if (___removeIp(_dev,*i)) - break; - } - } - - long cpid = (long)vfork(); - if (cpid == 0) { - ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),ip.isV4() ? "inet" : "inet6",ip.toString().c_str(),"alias",(const char *)0); - ::_exit(-1); - } else if (cpid > 0) { - int exitcode = -1; - ::waitpid(cpid,&exitcode,0); - return (exitcode == 0); - } // else return false... - - return false; -} - -bool OSXEthernetTap::removeIp(const InetAddress &ip) -{ - if (!ip) - return true; - std::vector allIps(ips()); - if (!std::binary_search(allIps.begin(),allIps.end(),ip)) { - if (___removeIp(_dev,ip)) - return true; - } - return false; -} - -std::vector OSXEthernetTap::ips() const -{ - struct ifaddrs *ifa = (struct ifaddrs *)0; - if (getifaddrs(&ifa)) - return std::vector(); - - std::vector r; - - struct ifaddrs *p = ifa; - while (p) { - if ((!strcmp(p->ifa_name,_dev.c_str()))&&(p->ifa_addr)&&(p->ifa_netmask)&&(p->ifa_addr->sa_family == p->ifa_netmask->sa_family)) { - switch(p->ifa_addr->sa_family) { - case AF_INET: { - struct sockaddr_in *sin = (struct sockaddr_in *)p->ifa_addr; - struct sockaddr_in *nm = (struct sockaddr_in *)p->ifa_netmask; - r.push_back(InetAddress(&(sin->sin_addr.s_addr),4,Utils::countBits((uint32_t)nm->sin_addr.s_addr))); - } break; - case AF_INET6: { - struct sockaddr_in6 *sin = (struct sockaddr_in6 *)p->ifa_addr; - struct sockaddr_in6 *nm = (struct sockaddr_in6 *)p->ifa_netmask; - uint32_t b[4]; - memcpy(b,nm->sin6_addr.s6_addr,sizeof(b)); - r.push_back(InetAddress(sin->sin6_addr.s6_addr,16,Utils::countBits(b[0]) + Utils::countBits(b[1]) + Utils::countBits(b[2]) + Utils::countBits(b[3]))); - } break; - } - } - p = p->ifa_next; - } - - if (ifa) - freeifaddrs(ifa); - - std::sort(r.begin(),r.end()); - std::unique(r.begin(),r.end()); - - return r; -} - -void OSXEthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len) -{ - char putBuf[4096]; - if ((len <= _mtu)&&(_enabled)) { - to.copyTo(putBuf,6); - from.copyTo(putBuf + 6,6); - *((uint16_t *)(putBuf + 12)) = htons((uint16_t)etherType); - memcpy(putBuf + 14,data,len); - len += 14; - int r = pcap_inject(reinterpret_cast(_pcap),putBuf,len); - if (r <= 0) { - printf("%s: pcap_inject() failed\n",_dev.c_str()); - return; - } - printf("%s: inject %s -> %s etherType==%u len=%u r==%d\n",_dev.c_str(),from.toString().c_str(),to.toString().c_str(),etherType,len,r); - } -} - -std::string OSXEthernetTap::deviceName() const -{ - return _dev; -} - -void OSXEthernetTap::setFriendlyName(const char *friendlyName) -{ -} - -void OSXEthernetTap::scanMulticastGroups(std::vector &added,std::vector &removed) -{ - std::vector newGroups; - - struct _intl_ifmaddrs *ifmap = (struct _intl_ifmaddrs *)0; - if (!_intl_getifmaddrs(&ifmap)) { - struct _intl_ifmaddrs *p = ifmap; - while (p) { - if (p->ifma_addr->sa_family == AF_LINK) { - struct sockaddr_dl *in = (struct sockaddr_dl *)p->ifma_name; - struct sockaddr_dl *la = (struct sockaddr_dl *)p->ifma_addr; - if ((la->sdl_alen == 6)&&(in->sdl_nlen <= _dev.length())&&(!memcmp(_dev.data(),in->sdl_data,in->sdl_nlen))) - newGroups.push_back(MulticastGroup(MAC(la->sdl_data + la->sdl_nlen,6),0)); - } - p = p->ifma_next; - } - _intl_freeifmaddrs(ifmap); - } - - std::vector allIps(ips()); - for(std::vector::iterator ip(allIps.begin());ip!=allIps.end();++ip) - newGroups.push_back(MulticastGroup::deriveMulticastGroupForAddressResolution(*ip)); - - std::sort(newGroups.begin(),newGroups.end()); - std::unique(newGroups.begin(),newGroups.end()); - - for(std::vector::iterator m(newGroups.begin());m!=newGroups.end();++m) { - if (!std::binary_search(_multicastGroups.begin(),_multicastGroups.end(),*m)) - added.push_back(*m); - } - for(std::vector::iterator m(_multicastGroups.begin());m!=_multicastGroups.end();++m) { - if (!std::binary_search(newGroups.begin(),newGroups.end(),*m)) - removed.push_back(*m); - } - - _multicastGroups.swap(newGroups); -} - -static void _pcapHandler(u_char *ptr,const struct pcap_pkthdr *hdr,const u_char *data) -{ - OSXEthernetTap *tap = reinterpret_cast(ptr); - if (hdr->caplen > 14) { - MAC to(data,6); - MAC from(data + 6,6); - if (from == tap->_mac) { - unsigned int etherType = ntohs(((const uint16_t *)data)[6]); - printf("%s: %s -> %s etherType==%u len==%u\n",tap->_dev.c_str(),from.toString().c_str(),to.toString().c_str(),etherType,(unsigned int)hdr->caplen); - // TODO: VLAN support - tap->_handler(tap->_arg,tap->_nwid,from,to,etherType,0,(const void *)(data + 14),hdr->len - 14); - } - } -} - -void OSXEthernetTap::threadMain() - throw() -{ - pcap_loop(reinterpret_cast(_pcap),-1,&_pcapHandler,reinterpret_cast(this)); -} - -} // namespace ZeroTier diff --git a/attic/OSXEthernetTap.cpp.utun-work-in-progress b/attic/OSXEthernetTap.cpp.utun-work-in-progress deleted file mode 100644 index f40483e8..00000000 --- a/attic/OSXEthernetTap.cpp.utun-work-in-progress +++ /dev/null @@ -1,831 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2015 ZeroTier, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * ZeroTier may be used and distributed under the terms of the GPLv3, which - * are available at: http://www.gnu.org/licenses/gpl-3.0.html - * - * If you would like to embed ZeroTier into a commercial application or - * redistribute it in a modified binary form, please contact ZeroTier Networks - * LLC. Start here: http://www.zerotier.com/ - */ - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// OSX compile fix... in6_var defines this in a struct which namespaces it for C++ ... why?!? -struct prf_ra { - u_char onlink : 1; - u_char autonomous : 1; - u_char reserved : 6; -} prf_ra; - -#include -#include - -// These are KERNEL_PRIVATE... why? -#ifndef SIOCAUTOCONF_START -#define SIOCAUTOCONF_START _IOWR('i', 132, struct in6_ifreq) /* accept rtadvd on this interface */ -#endif -#ifndef SIOCAUTOCONF_STOP -#define SIOCAUTOCONF_STOP _IOWR('i', 133, struct in6_ifreq) /* stop accepting rtadv for this interface */ -#endif - -// -------------------------------------------------------------------------- -// -------------------------------------------------------------------------- -// This source is from: -// http://www.opensource.apple.com/source/Libinfo/Libinfo-406.17/gen.subproj/getifmaddrs.c?txt -// It's here because OSX 10.6 does not have this convenience function. - -#define SALIGN (sizeof(uint32_t) - 1) -#define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : \ -(SALIGN + 1)) -#define MAX_SYSCTL_TRY 5 -#define RTA_MASKS (RTA_GATEWAY | RTA_IFP | RTA_IFA) - -/* FreeBSD uses NET_RT_IFMALIST and RTM_NEWMADDR from */ -/* We can use NET_RT_IFLIST2 and RTM_NEWMADDR2 on Darwin */ -//#define DARWIN_COMPAT - -//#ifdef DARWIN_COMPAT -#define GIM_SYSCTL_MIB NET_RT_IFLIST2 -#define GIM_RTM_ADDR RTM_NEWMADDR2 -//#else -//#define GIM_SYSCTL_MIB NET_RT_IFMALIST -//#define GIM_RTM_ADDR RTM_NEWMADDR -//#endif - -// Not in 10.6 includes so use our own -struct _intl_ifmaddrs { - struct _intl_ifmaddrs *ifma_next; - struct sockaddr *ifma_name; - struct sockaddr *ifma_addr; - struct sockaddr *ifma_lladdr; -}; - -static inline int _intl_getifmaddrs(struct _intl_ifmaddrs **pif) -{ - int icnt = 1; - int dcnt = 0; - int ntry = 0; - size_t len; - size_t needed; - int mib[6]; - int i; - char *buf; - char *data; - char *next; - char *p; - struct ifma_msghdr2 *ifmam; - struct _intl_ifmaddrs *ifa, *ift; - struct rt_msghdr *rtm; - struct sockaddr *sa; - - mib[0] = CTL_NET; - mib[1] = PF_ROUTE; - mib[2] = 0; /* protocol */ - mib[3] = 0; /* wildcard address family */ - mib[4] = GIM_SYSCTL_MIB; - mib[5] = 0; /* no flags */ - do { - if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) - return (-1); - if ((buf = (char *)malloc(needed)) == NULL) - return (-1); - if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { - if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) { - free(buf); - return (-1); - } - free(buf); - buf = NULL; - } - } while (buf == NULL); - - for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { - rtm = (struct rt_msghdr *)(void *)next; - if (rtm->rtm_version != RTM_VERSION) - continue; - switch (rtm->rtm_type) { - case GIM_RTM_ADDR: - ifmam = (struct ifma_msghdr2 *)(void *)rtm; - if ((ifmam->ifmam_addrs & RTA_IFA) == 0) - break; - icnt++; - p = (char *)(ifmam + 1); - for (i = 0; i < RTAX_MAX; i++) { - if ((RTA_MASKS & ifmam->ifmam_addrs & - (1 << i)) == 0) - continue; - sa = (struct sockaddr *)(void *)p; - len = SA_RLEN(sa); - dcnt += len; - p += len; - } - break; - } - } - - data = (char *)malloc(sizeof(struct _intl_ifmaddrs) * icnt + dcnt); - if (data == NULL) { - free(buf); - return (-1); - } - - ifa = (struct _intl_ifmaddrs *)(void *)data; - data += sizeof(struct _intl_ifmaddrs) * icnt; - - memset(ifa, 0, sizeof(struct _intl_ifmaddrs) * icnt); - ift = ifa; - - for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { - rtm = (struct rt_msghdr *)(void *)next; - if (rtm->rtm_version != RTM_VERSION) - continue; - - switch (rtm->rtm_type) { - case GIM_RTM_ADDR: - ifmam = (struct ifma_msghdr2 *)(void *)rtm; - if ((ifmam->ifmam_addrs & RTA_IFA) == 0) - break; - - p = (char *)(ifmam + 1); - for (i = 0; i < RTAX_MAX; i++) { - if ((RTA_MASKS & ifmam->ifmam_addrs & - (1 << i)) == 0) - continue; - sa = (struct sockaddr *)(void *)p; - len = SA_RLEN(sa); - switch (i) { - case RTAX_GATEWAY: - ift->ifma_lladdr = - (struct sockaddr *)(void *)data; - memcpy(data, p, len); - data += len; - break; - - case RTAX_IFP: - ift->ifma_name = - (struct sockaddr *)(void *)data; - memcpy(data, p, len); - data += len; - break; - - case RTAX_IFA: - ift->ifma_addr = - (struct sockaddr *)(void *)data; - memcpy(data, p, len); - data += len; - break; - - default: - data += len; - break; - } - p += len; - } - ift->ifma_next = ift + 1; - ift = ift->ifma_next; - break; - } - } - - free(buf); - - if (ift > ifa) { - ift--; - ift->ifma_next = NULL; - *pif = ifa; - } else { - *pif = NULL; - free(ifa); - } - return (0); -} - -static inline void _intl_freeifmaddrs(struct _intl_ifmaddrs *ifmp) -{ - free(ifmp); -} - -// -------------------------------------------------------------------------- -// -------------------------------------------------------------------------- - -#include -#include -#include -#include - -#include "../node/Constants.hpp" -#include "../node/Utils.hpp" -#include "../node/Mutex.hpp" -#include "../node/Dictionary.hpp" -#include "Arp.hpp" -#include "OSUtils.hpp" -#include "OSXEthernetTap.hpp" - -// ff:ff:ff:ff:ff:ff with no ADI -static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff),0); - -static inline bool _setIpv6Stuff(const char *ifname,bool performNUD,bool acceptRouterAdverts) -{ - struct in6_ndireq nd; - struct in6_ifreq ifr; - - int s = socket(AF_INET6,SOCK_DGRAM,0); - if (s <= 0) - return false; - - memset(&nd,0,sizeof(nd)); - strncpy(nd.ifname,ifname,sizeof(nd.ifname)); - - if (ioctl(s,SIOCGIFINFO_IN6,&nd)) { - close(s); - return false; - } - - unsigned long oldFlags = (unsigned long)nd.ndi.flags; - - if (performNUD) - nd.ndi.flags |= ND6_IFF_PERFORMNUD; - else nd.ndi.flags &= ~ND6_IFF_PERFORMNUD; - - if (oldFlags != (unsigned long)nd.ndi.flags) { - if (ioctl(s,SIOCSIFINFO_FLAGS,&nd)) { - close(s); - return false; - } - } - - memset(&ifr,0,sizeof(ifr)); - strncpy(ifr.ifr_name,ifname,sizeof(ifr.ifr_name)); - if (ioctl(s,acceptRouterAdverts ? SIOCAUTOCONF_START : SIOCAUTOCONF_STOP,&ifr)) { - close(s); - return false; - } - - close(s); - return true; -} - -// Create an OSX-native utun device (utun# where # is desiredNumber) -// Adapted from public domain utun example code by Jonathan Levin -static int _make_utun(int desiredNumber) -{ - struct sockaddr_ctl sc; - struct ctl_info ctlInfo; - struct ifreq ifr; - - memset(&ctlInfo, 0, sizeof(ctlInfo)); - if (strlcpy(ctlInfo.ctl_name, UTUN_CONTROL_NAME, sizeof(ctlInfo.ctl_name)) >= sizeof(ctlInfo.ctl_name)) { - return -1; - } - - int fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL); - if (fd == -1) - return -1; - if (ioctl(fd, CTLIOCGINFO, &ctlInfo) == -1) { - close(fd); - return -1; - } - - sc.sc_id = ctlInfo.ctl_id; - sc.sc_len = sizeof(sc); - sc.sc_family = AF_SYSTEM; - sc.ss_sysaddr = AF_SYS_CONTROL; - sc.sc_unit = desiredNumber + 1; - - if (connect(fd, (struct sockaddr *)&sc, sizeof(sc)) == -1) { - close(fd); - return -1; - } - - memset(&ifr,0,sizeof(ifr)); - sprintf(ifr.ifr_name,"utun%d",desiredNumber); - if (ioctl(fd,SIOCGIFFLAGS,(void *)&ifr) < 0) { - printf("SIOCGIFFLAGS failed\n"); - } - ifr.ifr_flags &= ~IFF_POINTOPOINT; - if (ioctl(fd,SIOCSIFFLAGS,(void *)&ifr) < 0) { - printf("clear IFF_POINTOPOINT failed\n"); - } - - return fd; -} - -namespace ZeroTier { - -static long globalTapsRunning = 0; -static Mutex globalTapCreateLock; - -OSXEthernetTap::OSXEthernetTap( - const char *homePath, - const MAC &mac, - unsigned int mtu, - unsigned int metric, - uint64_t nwid, - const char *friendlyName, - void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *data,unsigned int len), - void *arg) : - _handler(handler), - _arg(arg), - _arp((Arp *)0), - _nwid(nwid), - _homePath(homePath), - _mtu(mtu), - _metric(metric), - _fd(0), - _utun(false), - _enabled(true) -{ - char devpath[64],ethaddr[64],mtustr[32],metstr[32],nwids[32]; - struct stat stattmp; - - Utils::snprintf(nwids,sizeof(nwids),"%.16llx",nwid); - - if (mtu > 2800) - throw std::runtime_error("max tap MTU is 2800"); - - Mutex::Lock _gl(globalTapCreateLock); - - // Read remembered previous device name, if any -- we'll try to reuse - Dictionary devmap; - std::string desiredDevice; - { - std::string devmapbuf; - if (OSUtils::readFile((_homePath + ZT_PATH_SEPARATOR_S + "devicemap").c_str(),devmapbuf)) { - devmap.fromString(devmapbuf); - desiredDevice = devmap.get(nwids,""); - } - } - - if (::stat((_homePath + ZT_PATH_SEPARATOR_S + "tap.kext").c_str(),&stattmp) == 0) { - // Try to init kext if it's there, otherwise revert to utun mode - - if (::stat("/dev/zt0",&stattmp)) { - long kextpid = (long)vfork(); - if (kextpid == 0) { - ::chdir(homePath); - OSUtils::redirectUnixOutputs("/dev/null",(const char *)0); - ::execl("/sbin/kextload","/sbin/kextload","-q","-repository",homePath,"tap.kext",(const char *)0); - ::_exit(-1); - } else if (kextpid > 0) { - int exitcode = -1; - ::waitpid(kextpid,&exitcode,0); - } - ::usleep(500); // give tap device driver time to start up and try again - if (::stat("/dev/zt0",&stattmp)) - _utun = true; - } - - if (!_utun) { - // See if we can re-use the last device we had. - bool recalledDevice = false; - if (desiredDevice.length() > 2) { - Utils::snprintf(devpath,sizeof(devpath),"/dev/%s",desiredDevice.c_str()); - if (stat(devpath,&stattmp) == 0) { - _fd = ::open(devpath,O_RDWR); - if (_fd > 0) { - _dev = desiredDevice; - recalledDevice = true; - } - } - } - - // Open the first unused tap device if we didn't recall a previous one. - if (!recalledDevice) { - for(int i=0;i<64;++i) { - Utils::snprintf(devpath,sizeof(devpath),"/dev/zt%d",i); - if (stat(devpath,&stattmp)) { - _utun = true; - break; - } - _fd = ::open(devpath,O_RDWR); - if (_fd > 0) { - char foo[16]; - Utils::snprintf(foo,sizeof(foo),"zt%d",i); - _dev = foo; - break; - } - } - } - if (_fd <= 0) - _utun = true; - } - } else { - _utun = true; - } - - if (_utun) { - // Use OSX built-in utun device if kext is not available or doesn't work - - int utunNo = 0; - - if ((desiredDevice.length() > 4)&&(desiredDevice.substr(0,4) == "utun")) { - utunNo = Utils::strToInt(desiredDevice.substr(4).c_str()); - if (utunNo >= 0) - _fd = _make_utun(utunNo); - } - - if (_fd <= 0) { - // Start at utun8 to leave lower utuns unused since other stuff might - // want them -- OpenVPN, cjdns, etc. I'm not sure if those are smart - // enough to scan upward like this. - for(utunNo=8;utunNo<=256;++utunNo) { - if ((_fd = _make_utun(utunNo)) > 0) - break; - } - } - - if (_fd <= 0) - throw std::runtime_error("unable to find/load ZeroTier tap driver OR use built-in utun driver in OSX; permission or system problem or too many open devices?"); - - Utils::snprintf(devpath,sizeof(devpath),"utun%d",utunNo); - _dev = devpath; - - // Configure address and bring it up - Utils::snprintf(mtustr,sizeof(mtustr),"%u",_mtu); - Utils::snprintf(metstr,sizeof(metstr),"%u",_metric); - long cpid = (long)vfork(); - if (cpid == 0) { - ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"mtu",mtustr,"metric",metstr,"up",(const char *)0); - ::_exit(-1); - } else if (cpid > 0) { - int exitcode = -1; - ::waitpid(cpid,&exitcode,0); - if (exitcode) { - ::close(_fd); - throw std::runtime_error("ifconfig failure activating utun interface"); - } - } - - } else { - // Use our ZeroTier OSX tun/tap driver for zt# Ethernet tap device - - if (fcntl(_fd,F_SETFL,fcntl(_fd,F_GETFL) & ~O_NONBLOCK) == -1) { - ::close(_fd); - throw std::runtime_error("unable to set flags on file descriptor for TAP device"); - } - - // Configure MAC address and MTU, bring interface up - Utils::snprintf(ethaddr,sizeof(ethaddr),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)mac[0],(int)mac[1],(int)mac[2],(int)mac[3],(int)mac[4],(int)mac[5]); - Utils::snprintf(mtustr,sizeof(mtustr),"%u",_mtu); - Utils::snprintf(metstr,sizeof(metstr),"%u",_metric); - long cpid = (long)vfork(); - if (cpid == 0) { - ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"lladdr",ethaddr,"mtu",mtustr,"metric",metstr,"up",(const char *)0); - ::_exit(-1); - } else if (cpid > 0) { - int exitcode = -1; - ::waitpid(cpid,&exitcode,0); - if (exitcode) { - ::close(_fd); - throw std::runtime_error("ifconfig failure setting link-layer address and activating tap interface"); - } - } - - _setIpv6Stuff(_dev.c_str(),true,false); - } - - // Set close-on-exec so that devices cannot persist if we fork/exec for update - fcntl(_fd,F_SETFD,fcntl(_fd,F_GETFD) | FD_CLOEXEC); - - ::pipe(_shutdownSignalPipe); - - ++globalTapsRunning; - - devmap[nwids] = _dev; - OSUtils::writeFile((_homePath + ZT_PATH_SEPARATOR_S + "devicemap").c_str(),devmap.toString()); - - _thread = Thread::start(this); -} - -OSXEthernetTap::~OSXEthernetTap() -{ - Mutex::Lock _gl(globalTapCreateLock); - - ::write(_shutdownSignalPipe[1],(const void *)this,1); // writing a byte causes thread to exit - Thread::join(_thread); - - ::close(_fd); - ::close(_shutdownSignalPipe[0]); - ::close(_shutdownSignalPipe[1]); - - if (_utun) { - delete _arp; - } else { - if (--globalTapsRunning <= 0) { - globalTapsRunning = 0; // sanity check -- should not be possible - - char tmp[16384]; - sprintf(tmp,"%s/%s",_homePath.c_str(),"tap.kext"); - long kextpid = (long)vfork(); - if (kextpid == 0) { - OSUtils::redirectUnixOutputs("/dev/null",(const char *)0); - ::execl("/sbin/kextunload","/sbin/kextunload",tmp,(const char *)0); - ::_exit(-1); - } else if (kextpid > 0) { - int exitcode = -1; - ::waitpid(kextpid,&exitcode,0); - } - } - } -} - -void OSXEthernetTap::setEnabled(bool en) -{ - _enabled = en; - // TODO: interface status change -} - -bool OSXEthernetTap::enabled() const -{ - return _enabled; -} - -static bool ___removeIp(const std::string &_dev,const InetAddress &ip) -{ - long cpid = (long)vfork(); - if (cpid == 0) { - execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"inet",ip.toIpString().c_str(),"-alias",(const char *)0); - _exit(-1); - } else if (cpid > 0) { - int exitcode = -1; - waitpid(cpid,&exitcode,0); - return (exitcode == 0); - } - return false; // never reached, make compiler shut up about return value -} - -bool OSXEthernetTap::addIp(const InetAddress &ip) -{ - if (!ip) - return false; - - std::vector allIps(ips()); - if (std::binary_search(allIps.begin(),allIps.end(),ip)) - return true; - - // Remove and reconfigure if address is the same but netmask is different - for(std::vector::iterator i(allIps.begin());i!=allIps.end();++i) { - if ((i->ipsEqual(ip))&&(i->netmaskBits() != ip.netmaskBits())) { - if (___removeIp(_dev,*i)) - break; - } - } - - if (_utun) { - long cpid = (long)vfork(); - if (cpid == 0) { - if (ip.ss_family == AF_INET6) { - ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"inet6",ip.toString().c_str(),"alias",(const char *)0); - } else { - ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),ip.toString().c_str(),ip.toIpString().c_str(),"alias",(const char *)0); - } - ::_exit(-1); - } else if (cpid > 0) { - int exitcode = -1; - ::waitpid(cpid,&exitcode,0); - - if (exitcode == 0) { - if (ip.ss_family == AF_INET) { - // Add route to network over tun for IPv4 -- otherwise it behaves - // as a simple point to point tunnel instead of a true route. - cpid = (long)vfork(); - if (cpid == 0) { - ::close(STDERR_FILENO); - ::close(STDOUT_FILENO); - ::execl("/sbin/route","/sbin/route","add",ip.network().toString().c_str(),ip.toIpString().c_str(),(const char *)0); - ::exit(-1); - } else if (cpid > 0) { - int exitcode = -1; - ::waitpid(cpid,&exitcode,0); - return (exitcode == 0); - } - } else return true; - } - } - } else { - long cpid = (long)vfork(); - if (cpid == 0) { - ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),ip.isV4() ? "inet" : "inet6",ip.toString().c_str(),"alias",(const char *)0); - ::_exit(-1); - } else if (cpid > 0) { - int exitcode = -1; - ::waitpid(cpid,&exitcode,0); - return (exitcode == 0); - } - } - - return false; -} - -bool OSXEthernetTap::removeIp(const InetAddress &ip) -{ - if (!ip) - return true; - std::vector allIps(ips()); - if (!std::binary_search(allIps.begin(),allIps.end(),ip)) { - if (___removeIp(_dev,ip)) - return true; - } - return false; -} - -std::vector OSXEthernetTap::ips() const -{ - struct ifaddrs *ifa = (struct ifaddrs *)0; - if (getifaddrs(&ifa)) - return std::vector(); - - std::vector r; - - struct ifaddrs *p = ifa; - while (p) { - if ((!strcmp(p->ifa_name,_dev.c_str()))&&(p->ifa_addr)&&(p->ifa_netmask)&&(p->ifa_addr->sa_family == p->ifa_netmask->sa_family)) { - switch(p->ifa_addr->sa_family) { - case AF_INET: { - struct sockaddr_in *sin = (struct sockaddr_in *)p->ifa_addr; - struct sockaddr_in *nm = (struct sockaddr_in *)p->ifa_netmask; - r.push_back(InetAddress(&(sin->sin_addr.s_addr),4,Utils::countBits((uint32_t)nm->sin_addr.s_addr))); - } break; - case AF_INET6: { - struct sockaddr_in6 *sin = (struct sockaddr_in6 *)p->ifa_addr; - struct sockaddr_in6 *nm = (struct sockaddr_in6 *)p->ifa_netmask; - uint32_t b[4]; - memcpy(b,nm->sin6_addr.s6_addr,sizeof(b)); - r.push_back(InetAddress(sin->sin6_addr.s6_addr,16,Utils::countBits(b[0]) + Utils::countBits(b[1]) + Utils::countBits(b[2]) + Utils::countBits(b[3]))); - } break; - } - } - p = p->ifa_next; - } - - if (ifa) - freeifaddrs(ifa); - - std::sort(r.begin(),r.end()); - std::unique(r.begin(),r.end()); - - return r; -} - -void OSXEthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len) -{ - char putBuf[4096]; - if ((_fd > 0)&&(len <= _mtu)&&(_enabled)) { - to.copyTo(putBuf,6); - from.copyTo(putBuf + 6,6); - *((uint16_t *)(putBuf + 12)) = htons((uint16_t)etherType); - memcpy(putBuf + 14,data,len); - len += 14; - ::write(_fd,putBuf,len); - } -} - -std::string OSXEthernetTap::deviceName() const -{ - return _dev; -} - -void OSXEthernetTap::setFriendlyName(const char *friendlyName) -{ -} - -void OSXEthernetTap::scanMulticastGroups(std::vector &added,std::vector &removed) -{ - std::vector newGroups; - - struct _intl_ifmaddrs *ifmap = (struct _intl_ifmaddrs *)0; - if (!_intl_getifmaddrs(&ifmap)) { - struct _intl_ifmaddrs *p = ifmap; - while (p) { - if (p->ifma_addr->sa_family == AF_LINK) { - struct sockaddr_dl *in = (struct sockaddr_dl *)p->ifma_name; - struct sockaddr_dl *la = (struct sockaddr_dl *)p->ifma_addr; - if ((la->sdl_alen == 6)&&(in->sdl_nlen <= _dev.length())&&(!memcmp(_dev.data(),in->sdl_data,in->sdl_nlen))) - newGroups.push_back(MulticastGroup(MAC(la->sdl_data + la->sdl_nlen,6),0)); - } - p = p->ifma_next; - } - _intl_freeifmaddrs(ifmap); - } - - std::vector allIps(ips()); - for(std::vector::iterator ip(allIps.begin());ip!=allIps.end();++ip) - newGroups.push_back(MulticastGroup::deriveMulticastGroupForAddressResolution(*ip)); - - std::sort(newGroups.begin(),newGroups.end()); - std::unique(newGroups.begin(),newGroups.end()); - - for(std::vector::iterator m(newGroups.begin());m!=newGroups.end();++m) { - if (!std::binary_search(_multicastGroups.begin(),_multicastGroups.end(),*m)) - added.push_back(*m); - } - for(std::vector::iterator m(_multicastGroups.begin());m!=_multicastGroups.end();++m) { - if (!std::binary_search(newGroups.begin(),newGroups.end(),*m)) - removed.push_back(*m); - } - - _multicastGroups.swap(newGroups); -} - -void OSXEthernetTap::threadMain() - throw() -{ - fd_set readfds,nullfds; - MAC to,from; - int n,nfds,r; - char getBuf[8194]; - - Thread::sleep(500); - - FD_ZERO(&readfds); - FD_ZERO(&nullfds); - nfds = (int)std::max(_shutdownSignalPipe[0],_fd) + 1; - - r = 0; - for(;;) { - FD_SET(_shutdownSignalPipe[0],&readfds); - FD_SET(_fd,&readfds); - select(nfds,&readfds,&nullfds,&nullfds,(struct timeval *)0); - - if (FD_ISSET(_shutdownSignalPipe[0],&readfds)) // writes to shutdown pipe terminate thread - break; - - if (FD_ISSET(_fd,&readfds)) { - n = (int)::read(_fd,getBuf + r,sizeof(getBuf) - r); - if (n < 0) { - if ((errno != EINTR)&&(errno != ETIMEDOUT)) - break; - } else { - // Some tap drivers like to send the ethernet frame and the - // payload in two chunks, so handle that by accumulating - // data until we have at least a frame. - r += n; - if (r > 14) { - if (r > ((int)_mtu + 14)) // sanity check for weird TAP behavior on some platforms - r = _mtu + 14; - - if (_enabled) { - to.setTo(getBuf,6); - from.setTo(getBuf + 6,6); - unsigned int etherType = ntohs(((const uint16_t *)getBuf)[6]); - // TODO: VLAN support - _handler(_arg,_nwid,from,to,etherType,0,(const void *)(getBuf + 14),r - 14); - } - - r = 0; - } - } - } - } -} - -} // namespace ZeroTier diff --git a/attic/OSXEthernetTap.hpp b/attic/OSXEthernetTap.hpp deleted file mode 100644 index fe402901..00000000 --- a/attic/OSXEthernetTap.hpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -#ifndef ZT_OSXETHERNETTAP_HPP -#define ZT_OSXETHERNETTAP_HPP - -#include -#include - -#include -#include -#include - -#include "../node/Constants.hpp" -#include "../node/MAC.hpp" -#include "../node/InetAddress.hpp" -#include "../node/MulticastGroup.hpp" - -#include "Thread.hpp" - -namespace ZeroTier { - -/** - * OSX Ethernet tap using ZeroTier kernel extension zt# devices - */ -class OSXEthernetTap -{ -public: - OSXEthernetTap( - const char *homePath, - const MAC &mac, - unsigned int mtu, - unsigned int metric, - uint64_t nwid, - const char *friendlyName, - void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), - void *arg); - - ~OSXEthernetTap(); - - void setEnabled(bool en); - bool enabled() const; - bool addIp(const InetAddress &ip); - bool removeIp(const InetAddress &ip); - std::vector ips() const; - void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len); - std::string deviceName() const; - void setFriendlyName(const char *friendlyName); - void scanMulticastGroups(std::vector &added,std::vector &removed); - void setMtu(unsigned int mtu); - - void threadMain() - throw(); - -private: - void (*_handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int); - void *_arg; - uint64_t _nwid; - Thread _thread; - std::string _homePath; - std::string _dev; - std::vector _multicastGroups; - unsigned int _mtu; - unsigned int _metric; - int _fd; - int _shutdownSignalPipe[2]; - volatile bool _enabled; -}; - -} // namespace ZeroTier - -#endif diff --git a/attic/OSXEthernetTap.hpp.pcap-with-bridge-test b/attic/OSXEthernetTap.hpp.pcap-with-bridge-test deleted file mode 100644 index 33f1948c..00000000 --- a/attic/OSXEthernetTap.hpp.pcap-with-bridge-test +++ /dev/null @@ -1,96 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2015 ZeroTier, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * ZeroTier may be used and distributed under the terms of the GPLv3, which - * are available at: http://www.gnu.org/licenses/gpl-3.0.html - * - * If you would like to embed ZeroTier into a commercial application or - * redistribute it in a modified binary form, please contact ZeroTier Networks - * LLC. Start here: http://www.zerotier.com/ - */ - -#ifndef ZT_OSXETHERNETTAP_HPP -#define ZT_OSXETHERNETTAP_HPP - -#include -#include - -#include -#include -#include - -#include "../node/Constants.hpp" -#include "../node/MAC.hpp" -#include "../node/InetAddress.hpp" -#include "../node/MulticastGroup.hpp" - -#include "Thread.hpp" - -namespace ZeroTier { - -/** - * OSX Ethernet tap using ZeroTier kernel extension zt# devices - */ -class OSXEthernetTap -{ -public: - OSXEthernetTap( - const char *homePath, - const MAC &mac, - unsigned int mtu, - unsigned int metric, - uint64_t nwid, - const char *friendlyName, - void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), - void *arg); - - ~OSXEthernetTap(); - - inline void setEnabled(bool en) { _enabled = en; } - inline bool enabled() const { return _enabled; } - bool addIp(const InetAddress &ip); - bool removeIp(const InetAddress &ip); - std::vector ips() const; - void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len); - std::string deviceName() const; - void setFriendlyName(const char *friendlyName); - void scanMulticastGroups(std::vector &added,std::vector &removed); - - void threadMain() - throw(); - - // Private members of OSXEthernetTap have public visibility to be accessable - // from an internal bounce function; don't modify directly. - void (*_handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int); - void *_arg; - void *_pcap; // pcap_t * - uint64_t _nwid; - MAC _mac; - Thread _thread; - std::string _homePath; - std::string _dev; - std::vector _multicastGroups; - unsigned int _mtu; - unsigned int _metric; - volatile bool _enabled; -}; - -} // namespace ZeroTier - -#endif diff --git a/attic/OSXEthernetTap.hpp.utun-work-in-progress b/attic/OSXEthernetTap.hpp.utun-work-in-progress deleted file mode 100644 index 8ece87b3..00000000 --- a/attic/OSXEthernetTap.hpp.utun-work-in-progress +++ /dev/null @@ -1,101 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2015 ZeroTier, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * ZeroTier may be used and distributed under the terms of the GPLv3, which - * are available at: http://www.gnu.org/licenses/gpl-3.0.html - * - * If you would like to embed ZeroTier into a commercial application or - * redistribute it in a modified binary form, please contact ZeroTier Networks - * LLC. Start here: http://www.zerotier.com/ - */ - -#ifndef ZT_OSXETHERNETTAP_HPP -#define ZT_OSXETHERNETTAP_HPP - -#include -#include - -#include -#include -#include - -#include "../node/Constants.hpp" -#include "../node/MAC.hpp" -#include "../node/InetAddress.hpp" -#include "../node/MulticastGroup.hpp" - -#include "Thread.hpp" - -namespace ZeroTier { - -class Arp; - -/** - * OSX Ethernet tap supporting either ZeroTier tun/tap kext or OSX-native utun - */ -class OSXEthernetTap -{ -public: - OSXEthernetTap( - const char *homePath, - const MAC &mac, - unsigned int mtu, - unsigned int metric, - uint64_t nwid, - const char *friendlyName, - void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), - void *arg); - - ~OSXEthernetTap(); - - void setEnabled(bool en); - bool enabled() const; - bool addIp(const InetAddress &ip); - bool removeIp(const InetAddress &ip); - std::vector ips() const; - void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len); - std::string deviceName() const; - void setFriendlyName(const char *friendlyName); - void scanMulticastGroups(std::vector &added,std::vector &removed); - - inline bool isNativeUtun() const { return _utun; } - - void threadMain() - throw(); - -private: - void (*_handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int); - void *_arg; - Arp *_arp; // created and used if utun is enabled - uint64_t _nwid; - Thread _thread; - std::string _homePath; - std::string _dev; - std::vector _multicastGroups; - unsigned int _mtu; - unsigned int _metric; - int _fd; - int _shutdownSignalPipe[2]; - bool _utun; - volatile bool _enabled; -}; - -} // namespace ZeroTier - -#endif diff --git a/attic/RethinkDB.cpp b/attic/RethinkDB.cpp deleted file mode 100644 index d54b30b6..00000000 --- a/attic/RethinkDB.cpp +++ /dev/null @@ -1,497 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2018 ZeroTier, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -//#define ZT_CONTROLLER_USE_RETHINKDB - -#ifdef ZT_CONTROLLER_USE_RETHINKDB - -#include -#include -#include -#include - -#include "RethinkDB.hpp" -#include "EmbeddedNetworkController.hpp" - -#include "../version.h" - -#include -#include -#include - -#include "../ext/librethinkdbxx/build/include/rethinkdb.h" - -namespace R = RethinkDB; -using json = nlohmann::json; - -namespace ZeroTier { - -static const char *_timestr() -{ - time_t t = time(0); - char *ts = ctime(&t); - char *p = ts; - if (!p) - return ""; - while (*p) { - if (*p == '\n') { - *p = (char)0; - break; - } - ++p; - } - return ts; -} - -RethinkDB::RethinkDB(EmbeddedNetworkController *const nc,const Identity &myId,const char *path) : - DB(nc,myId,path), - _ready(2), // two tables need to be synchronized before we're ready, so this is ready when it reaches 0 - _run(1), - _waitNoticePrinted(false) -{ - // rethinkdb:host:port:db[:auth] - std::vector ps(OSUtils::split(path,":","","")); - if ((ps.size() < 4)||(ps[0] != "rethinkdb")) - throw std::runtime_error("invalid rethinkdb database url"); - _host = ps[1]; - _port = Utils::strToInt(ps[2].c_str()); - _db = ps[3]; - if (ps.size() > 4) - _auth = ps[4]; - - _readyLock.lock(); - - _membersDbWatcher = std::thread([this]() { - try { - while (_run == 1) { - try { - std::unique_ptr rdb(R::connect(this->_host,this->_port,this->_auth)); - if (rdb) { - _membersDbWatcherConnection = (void *)rdb.get(); - auto cur = R::db(this->_db).table("Member",R::optargs("read_mode","outdated")).get_all(this->_myAddressStr,R::optargs("index","controllerId")).changes(R::optargs("squash",0.05,"include_initial",true,"include_types",true,"include_states",true)).run(*rdb); - while (cur.has_next()) { - if (_run != 1) break; - json tmp(json::parse(cur.next().as_json())); - if ((tmp["type"] == "state")&&(tmp["state"] == "ready")) { - if (++this->_ready == 2) { - if (_waitNoticePrinted) - fprintf(stderr,"[%s] NOTICE: %.10llx controller RethinkDB data download complete." ZT_EOL_S,_timestr(),(unsigned long long)_myAddress.toInt()); - this->_readyLock.unlock(); - } - } else { - try { - json &ov = tmp["old_val"]; - json &nv = tmp["new_val"]; - json oldConfig,newConfig; - if (ov.is_object()) oldConfig = ov["config"]; - if (nv.is_object()) newConfig = nv["config"]; - if (oldConfig.is_object()||newConfig.is_object()) - this->_memberChanged(oldConfig,newConfig,(this->_ready <= 0)); - } catch ( ... ) {} // ignore bad records - } - } - } - } catch (std::exception &e) { - fprintf(stderr,"[%s] ERROR: %.10llx controller RethinkDB (member change stream): %s" ZT_EOL_S,_timestr(),(unsigned long long)_myAddress.toInt(),e.what()); - } catch (R::Error &e) { - fprintf(stderr,"[%s] ERROR: %.10llx controller RethinkDB (member change stream): %s" ZT_EOL_S,_timestr(),(unsigned long long)_myAddress.toInt(),e.message.c_str()); - } catch ( ... ) { - fprintf(stderr,"[%s] ERROR: %.10llx controller RethinkDB (member change stream): unknown exception" ZT_EOL_S,_timestr(),(unsigned long long)_myAddress.toInt()); - } - std::this_thread::sleep_for(std::chrono::milliseconds(250)); - } - } catch ( ... ) {} - }); - - _networksDbWatcher = std::thread([this]() { - try { - while (_run == 1) { - try { - std::unique_ptr rdb(R::connect(this->_host,this->_port,this->_auth)); - if (rdb) { - _networksDbWatcherConnection = (void *)rdb.get(); - auto cur = R::db(this->_db).table("Network",R::optargs("read_mode","outdated")).get_all(this->_myAddressStr,R::optargs("index","controllerId")).changes(R::optargs("squash",0.05,"include_initial",true,"include_types",true,"include_states",true)).run(*rdb); - while (cur.has_next()) { - if (_run != 1) break; - json tmp(json::parse(cur.next().as_json())); - if ((tmp["type"] == "state")&&(tmp["state"] == "ready")) { - if (--this->_ready == 0) { - if (_waitNoticePrinted) - fprintf(stderr,"[%s] NOTICE: %.10llx controller RethinkDB data download complete." ZT_EOL_S,_timestr(),(unsigned long long)_myAddress.toInt()); - this->_readyLock.unlock(); - } - } else { - try { - json &ov = tmp["old_val"]; - json &nv = tmp["new_val"]; - json oldConfig,newConfig; - if (ov.is_object()) oldConfig = ov["config"]; - if (nv.is_object()) newConfig = nv["config"]; - if (oldConfig.is_object()||newConfig.is_object()) - this->_networkChanged(oldConfig,newConfig,(this->_ready <= 0)); - } catch ( ... ) {} // ignore bad records - } - } - } - } catch (std::exception &e) { - fprintf(stderr,"[%s] ERROR: %.10llx controller RethinkDB (network change stream): %s" ZT_EOL_S,_timestr(),(unsigned long long)_myAddress.toInt(),e.what()); - } catch (R::Error &e) { - fprintf(stderr,"[%s] ERROR: %.10llx controller RethinkDB (network change stream): %s" ZT_EOL_S,_timestr(),(unsigned long long)_myAddress.toInt(),e.message.c_str()); - } catch ( ... ) { - fprintf(stderr,"[%s] ERROR: %.10llx controller RethinkDB (network change stream): unknown exception" ZT_EOL_S,_timestr(),(unsigned long long)_myAddress.toInt()); - } - std::this_thread::sleep_for(std::chrono::milliseconds(250)); - } - } catch ( ... ) {} - }); - - for(int t=0;t rdb; - nlohmann::json *config = (nlohmann::json *)0; - while ((this->_commitQueue.get(config))&&(_run == 1)) { - if (!config) - continue; - nlohmann::json record; - const char *table = (const char *)0; - std::string deleteId; - try { - const std::string objtype = (*config)["objtype"]; - if (objtype == "member") { - const std::string nwid = (*config)["nwid"]; - const std::string id = (*config)["id"]; - record["id"] = nwid + "-" + id; - record["controllerId"] = this->_myAddressStr; - record["networkId"] = nwid; - record["nodeId"] = id; - record["config"] = *config; - table = "Member"; - } else if (objtype == "network") { - const std::string id = (*config)["id"]; - record["id"] = id; - record["controllerId"] = this->_myAddressStr; - record["config"] = *config; - table = "Network"; - } else if (objtype == "trace") { - record = *config; - table = "RemoteTrace"; - } else if (objtype == "_delete_network") { - deleteId = (*config)["id"]; - table = "Network"; - } else if (objtype == "_delete_member") { - deleteId = (*config)["nwid"]; - deleteId.push_back('-'); - const std::string tmp = (*config)["id"]; - deleteId.append(tmp); - table = "Member"; - } - } catch (std::exception &e) { - fprintf(stderr,"[%s] ERROR: %.10llx controller RethinkDB (insert/update record creation): %s" ZT_EOL_S,_timestr(),(unsigned long long)_myAddress.toInt(),e.what()); - table = (const char *)0; - } catch (R::Error &e) { - fprintf(stderr,"[%s] ERROR: %.10llx controller RethinkDB (insert/update record creation): %s" ZT_EOL_S,_timestr(),(unsigned long long)_myAddress.toInt(),e.message.c_str()); - table = (const char *)0; - } catch ( ... ) { - fprintf(stderr,"[%s] ERROR: %.10llx controller RethinkDB (insert/update record creation): unknown exception" ZT_EOL_S,_timestr(),(unsigned long long)_myAddress.toInt()); - table = (const char *)0; - } - delete config; - if (!table) - continue; - const std::string jdump(OSUtils::jsonDump(record,-1)); - - while (_run == 1) { - try { - if (!rdb) - rdb = R::connect(this->_host,this->_port,this->_auth); - if (rdb) { - if (deleteId.length() > 0) { - //printf("DELETE: %s" ZT_EOL_S,deleteId.c_str()); - R::db(this->_db).table(table).get(deleteId).delete_().run(*rdb); - } else { - //printf("UPSERT: %s" ZT_EOL_S,record.dump().c_str()); - R::db(this->_db).table(table).insert(R::Datum::from_json(jdump),R::optargs("conflict","update","return_changes",false)).run(*rdb); - } - break; - } else { - fprintf(stderr,"[%s] ERROR: %.10llx controller RethinkDB (insert/update): connect failed (will retry)" ZT_EOL_S,_timestr(),(unsigned long long)_myAddress.toInt()); - rdb.reset(); - } - } catch (std::exception &e) { - fprintf(stderr,"[%s] ERROR: %.10llx controller RethinkDB (insert/update): %s [%s]" ZT_EOL_S,_timestr(),(unsigned long long)_myAddress.toInt(),e.what(),jdump.c_str()); - rdb.reset(); - } catch (R::Error &e) { - fprintf(stderr,"[%s] ERROR: %.10llx controller RethinkDB (insert/update): %s [%s]" ZT_EOL_S,_timestr(),(unsigned long long)_myAddress.toInt(),e.message.c_str(),jdump.c_str()); - rdb.reset(); - } catch ( ... ) { - fprintf(stderr,"[%s] ERROR: %.10llx controller RethinkDB (insert/update): unknown exception [%s]" ZT_EOL_S,_timestr(),(unsigned long long)_myAddress.toInt(),jdump.c_str()); - rdb.reset(); - } - std::this_thread::sleep_for(std::chrono::milliseconds(250)); - } - } - } catch (std::exception &e) { - fprintf(stderr,"[%s] ERROR: %.10llx controller RethinkDB (insert/update outer loop): %s" ZT_EOL_S,_timestr(),(unsigned long long)_myAddress.toInt(),e.what()); - } catch (R::Error &e) { - fprintf(stderr,"[%s] ERROR: %.10llx controller RethinkDB (insert/update outer loop): %s" ZT_EOL_S,_timestr(),(unsigned long long)_myAddress.toInt(),e.message.c_str()); - } catch ( ... ) { - fprintf(stderr,"[%s] ERROR: %.10llx controller RethinkDB (insert/update outer loop): unknown exception" ZT_EOL_S,_timestr(),(unsigned long long)_myAddress.toInt()); - } - }); - } - - _onlineNotificationThread = std::thread([this]() { - int64_t lastUpdatedNetworkStatus = 0; - std::unordered_map< std::pair,int64_t,_PairHasher > lastOnlineCumulative; - try { - std::unique_ptr rdb; - while (_run == 1) { - try { - if (!rdb) { - _connected = 0; - rdb = R::connect(this->_host,this->_port,this->_auth); - } - - if (rdb) { - _connected = 1; - R::Array batch; - R::Object tmpobj; - - std::unordered_map< std::pair,std::pair,_PairHasher > lastOnline; - { - std::lock_guard l(_lastOnline_l); - lastOnline.swap(_lastOnline); - } - - for(auto i=lastOnline.begin();i!=lastOnline.end();++i) { - lastOnlineCumulative[i->first] = i->second.first; - char tmp[64],tmp2[64]; - OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.16llx-%.10llx",i->first.first,i->first.second); - tmpobj["id"] = tmp; - tmpobj["ts"] = i->second.first; - tmpobj["phy"] = i->second.second.toIpString(tmp2); - batch.emplace_back(tmpobj); - if (batch.size() >= 1024) { - R::db(this->_db).table("MemberStatus",R::optargs("read_mode","outdated")).insert(batch,R::optargs("conflict","update")).run(*rdb); - batch.clear(); - } - } - if (batch.size() > 0) { - R::db(this->_db).table("MemberStatus",R::optargs("read_mode","outdated")).insert(batch,R::optargs("conflict","update")).run(*rdb); - batch.clear(); - } - tmpobj.clear(); - - const int64_t now = OSUtils::now(); - if ((now - lastUpdatedNetworkStatus) > 10000) { - lastUpdatedNetworkStatus = now; - - std::vector< std::pair< uint64_t,std::shared_ptr<_Network> > > networks; - { - std::lock_guard l(_networks_l); - networks.reserve(_networks.size() + 1); - for(auto i=_networks.begin();i!=_networks.end();++i) - networks.push_back(*i); - } - - for(auto i=networks.begin();i!=networks.end();++i) { - char tmp[64]; - Utils::hex(i->first,tmp); - tmpobj["id"] = tmp; - { - std::lock_guard l2(i->second->lock); - tmpobj["authorizedMemberCount"] = i->second->authorizedMembers.size(); - tmpobj["totalMemberCount"] = i->second->members.size(); - unsigned long onlineMemberCount = 0; - for(auto m=i->second->members.begin();m!=i->second->members.end();++m) { - auto lo = lastOnlineCumulative.find(std::pair(i->first,m->first)); - if (lo != lastOnlineCumulative.end()) { - if ((now - lo->second) <= (ZT_NETWORK_AUTOCONF_DELAY * 2)) - ++onlineMemberCount; - else lastOnlineCumulative.erase(lo); - } - } - tmpobj["onlineMemberCount"] = onlineMemberCount; - tmpobj["bridgeCount"] = i->second->activeBridgeMembers.size(); - tmpobj["ts"] = now; - } - batch.emplace_back(tmpobj); - if (batch.size() >= 1024) { - R::db(this->_db).table("NetworkStatus",R::optargs("read_mode","outdated")).insert(batch,R::optargs("conflict","update")).run(*rdb); - batch.clear(); - } - } - if (batch.size() > 0) { - R::db(this->_db).table("NetworkStatus",R::optargs("read_mode","outdated")).insert(batch,R::optargs("conflict","update")).run(*rdb); - batch.clear(); - } - } - } - } catch (std::exception &e) { - fprintf(stderr,"[%s] ERROR: %.10llx controller RethinkDB (node status update): %s" ZT_EOL_S,_timestr(),(unsigned long long)_myAddress.toInt(),e.what()); - rdb.reset(); - } catch (R::Error &e) { - fprintf(stderr,"[%s] ERROR: %.10llx controller RethinkDB (node status update): %s" ZT_EOL_S,_timestr(),(unsigned long long)_myAddress.toInt(),e.message.c_str()); - rdb.reset(); - } catch ( ... ) { - fprintf(stderr,"[%s] ERROR: %.10llx controller RethinkDB (node status update): unknown exception" ZT_EOL_S,_timestr(),(unsigned long long)_myAddress.toInt()); - rdb.reset(); - } - std::this_thread::sleep_for(std::chrono::milliseconds(250)); - } - } catch ( ... ) {} - }); - - _heartbeatThread = std::thread([this]() { - try { - R::Object controllerRecord; - std::unique_ptr rdb; - - { - char publicId[1024]; - //char secretId[1024]; - char hostname[1024]; - this->_myId.toString(false,publicId); - //this->_myId.toString(true,secretId); - if (gethostname(hostname,sizeof(hostname)) != 0) { - hostname[0] = (char)0; - } else { - for(int i=0;i_myAddressStr.c_str(); - controllerRecord["publicIdentity"] = publicId; - //controllerRecord["secretIdentity"] = secretId; - if (hostname[0]) - controllerRecord["clusterHost"] = hostname; - controllerRecord["vMajor"] = ZEROTIER_ONE_VERSION_MAJOR; - controllerRecord["vMinor"] = ZEROTIER_ONE_VERSION_MINOR; - controllerRecord["vRev"] = ZEROTIER_ONE_VERSION_REVISION; - controllerRecord["vBuild"] = ZEROTIER_ONE_VERSION_BUILD; - } - - while (_run == 1) { - try { - if (!rdb) - rdb = R::connect(this->_host,this->_port,this->_auth); - if (rdb) { - controllerRecord["lastAlive"] = OSUtils::now(); - //printf("HEARTBEAT: %s" ZT_EOL_S,tmp); - R::db(this->_db).table("Controller",R::optargs("read_mode","outdated")).insert(controllerRecord,R::optargs("conflict","update")).run(*rdb); - } - } catch ( ... ) { - rdb.reset(); - } - std::this_thread::sleep_for(std::chrono::milliseconds(1000)); - } - } catch ( ... ) {} - }); -} - -RethinkDB::~RethinkDB() -{ - _run = 0; - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - _commitQueue.stop(); - for(int t=0;tclose(); - if (_networksDbWatcherConnection) - ((R::Connection *)_networksDbWatcherConnection)->close(); - _membersDbWatcher.join(); - _networksDbWatcher.join(); - _heartbeatThread.join(); - _onlineNotificationThread.join(); -} - -bool RethinkDB::waitForReady() -{ - while (_ready > 0) { - if (!_waitNoticePrinted) { - _waitNoticePrinted = true; - fprintf(stderr,"[%s] NOTICE: %.10llx controller RethinkDB waiting for initial data download..." ZT_EOL_S,_timestr(),(unsigned long long)_myAddress.toInt()); - } - _readyLock.lock(); - _readyLock.unlock(); - } - return true; -} - -bool RethinkDB::isReady() -{ - return ((_ready)&&(_connected)); -} - -void RethinkDB::save(nlohmann::json *orig,nlohmann::json &record) -{ - if (!record.is_object()) // sanity check - return; - waitForReady(); - if (orig) { - if (*orig != record) { - record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1; - _commitQueue.post(new nlohmann::json(record)); - } - } else { - record["revision"] = 1; - _commitQueue.post(new nlohmann::json(record)); - } -} - -void RethinkDB::eraseNetwork(const uint64_t networkId) -{ - char tmp2[24]; - waitForReady(); - Utils::hex(networkId,tmp2); - json *tmp = new json(); - (*tmp)["id"] = tmp2; - (*tmp)["objtype"] = "_delete_network"; // pseudo-type, tells thread to delete network - _commitQueue.post(tmp); -} - -void RethinkDB::eraseMember(const uint64_t networkId,const uint64_t memberId) -{ - char tmp2[24]; - json *tmp = new json(); - waitForReady(); - Utils::hex(networkId,tmp2); - (*tmp)["nwid"] = tmp2; - Utils::hex10(memberId,tmp2); - (*tmp)["id"] = tmp2; - (*tmp)["objtype"] = "_delete_member"; // pseudo-type, tells thread to delete network - _commitQueue.post(tmp); -} - -void RethinkDB::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress) -{ - std::lock_guard l(_lastOnline_l); - std::pair &i = _lastOnline[std::pair(networkId,memberId)]; - i.first = OSUtils::now(); - if (physicalAddress) - i.second = physicalAddress; -} - -} // namespace ZeroTier - -#endif // ZT_CONTROLLER_USE_RETHINKDB diff --git a/attic/RethinkDB.hpp b/attic/RethinkDB.hpp deleted file mode 100644 index 60f04c5b..00000000 --- a/attic/RethinkDB.hpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2018 ZeroTier, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifdef ZT_CONTROLLER_USE_RETHINKDB - -#ifndef ZT_CONTROLLER_RETHINKDB_HPP -#define ZT_CONTROLLER_RETHINKDB_HPP - -#include "DB.hpp" - -#define ZT_CONTROLLER_RETHINKDB_COMMIT_THREADS 4 - -namespace ZeroTier -{ - -/** - * A controller database driver that talks to RethinkDB - * - * This is for use with ZeroTier Central. Others are free to build and use it - * but be aware that we might change it at any time. - */ -class RethinkDB : public DB -{ -public: - RethinkDB(EmbeddedNetworkController *const nc,const Identity &myId,const char *path); - virtual ~RethinkDB(); - - virtual bool waitForReady(); - virtual bool isReady(); - virtual void save(nlohmann::json *orig,nlohmann::json &record); - virtual void eraseNetwork(const uint64_t networkId); - virtual void eraseMember(const uint64_t networkId,const uint64_t memberId); - virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress); - -protected: - struct _PairHasher - { - inline std::size_t operator()(const std::pair &p) const { return (std::size_t)(p.first ^ p.second); } - }; - - std::string _host; - std::string _db; - std::string _auth; - int _port; - - void *_networksDbWatcherConnection; - void *_membersDbWatcherConnection; - std::thread _networksDbWatcher; - std::thread _membersDbWatcher; - - BlockingQueue< nlohmann::json * > _commitQueue; - std::thread _commitThread[ZT_CONTROLLER_RETHINKDB_COMMIT_THREADS]; - - std::unordered_map< std::pair,std::pair,_PairHasher > _lastOnline; - mutable std::mutex _lastOnline_l; - std::thread _onlineNotificationThread; - - std::thread _heartbeatThread; - - mutable std::mutex _readyLock; // locked until ready - std::atomic _ready,_connected,_run; - mutable volatile bool _waitNoticePrinted; -}; - -} // namespace ZeroTier - -#endif - -#endif // ZT_CONTROLLER_USE_RETHINKDB diff --git a/attic/kubernetes_docs/.zerotierCliSettings b/attic/kubernetes_docs/.zerotierCliSettings deleted file mode 100644 index 0e7df9b6..00000000 --- a/attic/kubernetes_docs/.zerotierCliSettings +++ /dev/null @@ -1,18 +0,0 @@ -{ - "configVersion": 1, - "defaultCentral": "@my.zerotier.com", - "defaultController": "@my.zerotier.com", - "defaultOne": "@local", - "things": { - "local": { - "auth": "local_service_auth_token_replaced_automatically", - "type": "one", - "url": "http://127.0.0.1:9993/" - }, - "my.zerotier.com": { - "auth": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", - "type": "central", - "url": "https://my.zerotier.com/" - } - } -} diff --git a/attic/kubernetes_docs/Dockerfile b/attic/kubernetes_docs/Dockerfile deleted file mode 100644 index 6437a2bb..00000000 --- a/attic/kubernetes_docs/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -FROM node:4.4 -EXPOSE 8080/tcp 9993/udp - -# Install ZT network conf files -RUN mkdir -p /var/lib/zerotier-one/networks.d -ADD *.conf /var/lib/zerotier-one/networks.d/ -ADD *.conf / -ADD zerotier-one / -ADD zerotier-cli / -ADD .zerotierCliSettings / - -# Install App -ADD server.js / - -# script which will start/auth VM on ZT network -ADD entrypoint.sh / -RUN chmod -v +x /entrypoint.sh - -CMD ["./entrypoint.sh"] \ No newline at end of file diff --git a/attic/kubernetes_docs/README.md b/attic/kubernetes_docs/README.md deleted file mode 100644 index 482e77e5..00000000 --- a/attic/kubernetes_docs/README.md +++ /dev/null @@ -1,150 +0,0 @@ -Kubernetes + ZeroTier -==== - -A self-authorizing Kubernetes cluster deployment over a private ZeroTier network. - -This is a quick tutorial for setting up a Kubernetes deployment which can self-authorize each new replica onto your private ZeroTier network with no additional configuration needed when you scale. The Kubernetes-specific instructions and content is based on the [hellonode](http://kubernetes.io/docs/hellonode/) tutorial. All of the files discussed below can be found [here](); - - - -## Preliminary tasks - -**Step 1: Go to [my.zerotier.com](https://my.zerotier.com) and generate a network controller API key. This key will be used by ZeroTier to automatically authorize new instances of your VMs to join your secure deployment network during replication.** - -**Step 2: Create a new `private` network. Take note of the network ID, henceforth: `nwid`** - -**Step 3: Follow the instructions from the [hellonode](ttp://kubernetes.io/docs/hellonode/) tutorial to set up your development system.** - -*** -## Construct docker image - -**Step 4: Create necessary files for inclusion into image, your resultant directory should contain:** - - - `ztkube/.conf` - - `ztkube/Dockerfile` - - `ztkube/entrypoint.sh` - - `ztkube/server.js` - - `ztkube/zerotier-cli` - - `ztkube/zerotier-one` - -Start by creating a build directory to copy all required files into `mkdir ztkube`. Then build the following: - - `make one` - - `make cli` - -Add the following files to the `ztkube` directory. These files will be compiled into the Docker image. - - - Create an empty `.conf` file to specify the private deployment network you created in *Step 2*: - - - Create a CLI tool config file `.zerotierCliSettings` which should only contain your network controller API key to authorize new devices on your network (the local service API key will be filled in automatically). In this example the default controller is hosted by us at [my.zerotier.com](https://my.zerotier.com). Alternatively, you can host your own network controller but you'll need to modify the CLI config file accordingly. - -``` -{ - "configVersion": 1, - "defaultCentral": "@my.zerotier.com", - "defaultController": "@my.zerotier.com", - "defaultOne": "@local", - "things": { - "local": { - "auth": "local_service_auth_token_replaced_automatically", - "type": "one", - "url": "http://127.0.0.1:9993/" - }, - "my.zerotier.com": { - "auth": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", - "type": "central", - "url": "https://my.zerotier.com/" - } - } -} -``` - - - - Create a `Dockerfile` which will copy the ZeroTier service as well as the ZeroTier CLI to the image: - -``` -FROM node:4.4 -EXPOSE 8080/tcp 9993/udp - -# Install ZT network conf files -RUN mkdir -p /var/lib/zerotier-one/networks.d -ADD *.conf /var/lib/zerotier-one/networks.d/ -ADD *.conf / -ADD zerotier-one / -ADD zerotier-cli / -ADD .zerotierCliSettings / - -# Install App -ADD server.js / - -# script which will start/auth VM on ZT network -ADD entrypoint.sh / -RUN chmod -v +x /entrypoint.sh - -CMD ["./entrypoint.sh"] -``` - - - Create the `entrypoint.sh` script which will start the ZeroTier service in the VM, attempt to join your deployment network and automatically authorize the new VM if your network is set to private: - -``` -#!/bin/bash - -echo '*** ZeroTier-Kubernetes self-auth test script' -chown -R daemon /var/lib/zerotier-one -chgrp -R daemon /var/lib/zerotier-one -su daemon -s /bin/bash -c '/zerotier-one -d -U -p9993 >>/tmp/zerotier-one.out 2>&1' -dev="" -nwconf=$(ls *.conf) -nwid="${nwconf%.*}" - -sleep 10 -dev=$(cat /var/lib/zerotier-one/identity.public| cut -d ':' -f 1) - -echo '*** Joining' -./zerotier-cli join "$nwid".conf -# Fill out local service auth token -AUTHTOKEN=$(cat /var/lib/zerotier-one/authtoken.secret) -sed "s|\local_service_auth_token_replaced_automatically|${AUTHTOKEN}|" .zerotierCliSettings > /root/.zerotierCliSettings -echo '*** Authorizing' -./zerotier-cli net-auth @my.zerotier.com "$nwid" "$dev" -echo '*** Cleaning up' # Remove controller auth token -rm -rf .zerotierCliSettings /root/.zerotierCliSettings -node server.js -``` - -**Step 5: Build the image:** - - - `docker build -t gcr.io/$PROJECT_ID/hello-node .` - - - -**Step 6: Push the docker image to your *Container Registry*** - - - `gcloud docker push gcr.io/$PROJECT_ID/hello-node:v1` - -*** -## Deploy! - -**Step 7: Create Kubernetes Cluster** - - - `gcloud config set compute/zone us-central1-a` - - - `gcloud container clusters create hello-world` - - - `gcloud container clusters get-credentials hello-world` - - - -**Step 8: Create your pod** - - - `kubectl run hello-node --image=gcr.io/$PROJECT_ID/hello-node:v1 --port=8080` - - - -**Step 9: Scale** - - - `kubectl scale deployment hello-node --replicas=4` - -*** -## Verify - -Now, after a minute or so you can use `zerotier-cli net-members ` to show all of your VM instances on your ZeroTier deployment network. If you haven't [configured your local CLI](https://github.com/zerotier/ZeroTierOne/tree/dev/cli), you can simply log into [my.zerotier.com](https://my.zerotier.com), go to *Networks -> nwid* to check that your VMs are indeed members of your private network. You should also note that the `entrypoint.sh` script will automatically delete your network controller API key once it has authorized your VM. This is merely a security measure and can be removed if needed. diff --git a/attic/kubernetes_docs/entrypoint.sh b/attic/kubernetes_docs/entrypoint.sh deleted file mode 100644 index 80cd278e..00000000 --- a/attic/kubernetes_docs/entrypoint.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -echo '*** ZeroTier-Kubernetes self-auth test script' -chown -R daemon /var/lib/zerotier-one -chgrp -R daemon /var/lib/zerotier-one -su daemon -s /bin/bash -c '/zerotier-one -d -U -p9993 >>/tmp/zerotier-one.out 2>&1' -dev="" -nwconf=$(ls *.conf) -nwid="${nwconf%.*}" - -sleep 10 -dev=$(cat /var/lib/zerotier-one/identity.public| cut -d ':' -f 1) - -echo '*** Joining' -./zerotier-cli join "$nwid".conf -# Fill out local service auth token -AUTHTOKEN=$(cat /var/lib/zerotier-one/authtoken.secret) -sed "s|\local_service_auth_token_replaced_automatically|${AUTHTOKEN}|" .zerotierCliSettings > /root/.zerotierCliSettings -echo '*** Authorizing' -./zerotier-cli net-auth @my.zerotier.com "$nwid" "$dev" -echo '*** Cleaning up' # Remove controller auth token -rm -rf .zerotierCliSettings /root/.zerotierCliSettings -node server.js \ No newline at end of file diff --git a/attic/kubernetes_docs/server.js b/attic/kubernetes_docs/server.js deleted file mode 100644 index a4b08bb8..00000000 --- a/attic/kubernetes_docs/server.js +++ /dev/null @@ -1,8 +0,0 @@ -var http = require('http'); -var handleRequest = function(request, response) { - console.log('Received request for URL: ' + request.url); - response.writeHead(200); - response.end('Hello World!'); -}; -var www = http.createServer(handleRequest); -www.listen(8080); diff --git a/debian/changelog b/debian/changelog index 490fbedc..778a875f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +zerotier-one (1.2.99) unstable; urgency=medium + + * 1.4.0pre release + + -- Adam Ierymenko Thu, 27 Jun 2019 01:00:00 -0700 + zerotier-one (1.2.12) unstable; urgency=medium * See https://github.com/zerotier/ZeroTierOne for release notes. diff --git a/ext/installfiles/mac/ZeroTier One.pkgproj b/ext/installfiles/mac/ZeroTier One.pkgproj index 0d3d0bda..e10b49ec 100755 --- a/ext/installfiles/mac/ZeroTier One.pkgproj +++ b/ext/installfiles/mac/ZeroTier One.pkgproj @@ -664,7 +664,7 @@ USE_HFS+_COMPRESSION VERSION - 1.2.12 + 1.2.99 PROJECT_COMMENTS diff --git a/ext/installfiles/windows/chocolatey/zerotier-one/tools/LICENSE.txt b/ext/installfiles/windows/chocolatey/zerotier-one/tools/LICENSE.txt deleted file mode 100644 index ce0564ac..00000000 --- a/ext/installfiles/windows/chocolatey/zerotier-one/tools/LICENSE.txt +++ /dev/null @@ -1,11 +0,0 @@ -From: https://raw.githubusercontent.com/zerotier/ZeroTierOne/master/COPYING - -LICENSE - -ZeroTier One is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3 of the License, or (at -your option) any later version. - -See the file ‘LICENSE.GPL-3’ for the text of the GNU GPL version 3. -If that file is not present, see . diff --git a/ext/installfiles/windows/chocolatey/zerotier-one/tools/VERIFICATION.txt b/ext/installfiles/windows/chocolatey/zerotier-one/tools/VERIFICATION.txt deleted file mode 100644 index 0a5bc760..00000000 --- a/ext/installfiles/windows/chocolatey/zerotier-one/tools/VERIFICATION.txt +++ /dev/null @@ -1,5 +0,0 @@ -VERIFICATION -Verification is intended to assist the Chocolatey moderators and community -in verifying that this package's contents are trustworthy. - -Our MSI installer should be signed by ZeroTier, Inc. using a certificate from DigiCert. diff --git a/ext/installfiles/windows/chocolatey/zerotier-one/tools/chocolateyinstall.ps1 b/ext/installfiles/windows/chocolatey/zerotier-one/tools/chocolateyinstall.ps1 deleted file mode 100644 index 9a0f6bac..00000000 --- a/ext/installfiles/windows/chocolatey/zerotier-one/tools/chocolateyinstall.ps1 +++ /dev/null @@ -1,8 +0,0 @@ -$packageName = 'zerotier-one' -$installerType = 'msi' -$url = 'https://download.zerotier.com/RELEASES/1.2.4/dist/ZeroTier%20One.msi' -$url64 = 'https://download.zerotier.com/RELEASES/1.2.4/dist/ZeroTier%20One.msi' -$silentArgs = '/quiet' -$validExitCodes = @(0,3010) - -Install-ChocolateyPackage $packageName $installerType $silentArgs $url $url64 -validExitCodes $validExitCodes diff --git a/ext/installfiles/windows/chocolatey/zerotier-one/tools/chocolateyuninstall.ps1 b/ext/installfiles/windows/chocolatey/zerotier-one/tools/chocolateyuninstall.ps1 deleted file mode 100644 index 81f7a5ac..00000000 --- a/ext/installfiles/windows/chocolatey/zerotier-one/tools/chocolateyuninstall.ps1 +++ /dev/null @@ -1,30 +0,0 @@ -$ErrorActionPreference = 'Stop'; - -$packageName = 'zerotier-one' -$softwareName = 'ZeroTier One*' -$installerType = 'MSI' - -$silentArgs = '/qn /norestart' -$validExitCodes = @(0, 3010, 1605, 1614, 1641) -$uninstalled = $false - -[array]$key = Get-UninstallRegistryKey -SoftwareName $softwareName - -if ($key.Count -eq 1) { - $key | % { - $silentArgs = "$($_.PSChildName) $silentArgs" - $file = '' - Uninstall-ChocolateyPackage -PackageName $packageName ` - -FileType $installerType ` - -SilentArgs "$silentArgs" ` - -ValidExitCodes $validExitCodes ` - -File "$file" - } -} elseif ($key.Count -eq 0) { - Write-Warning "$packageName has already been uninstalled by other means." -} elseif ($key.Count -gt 1) { - Write-Warning "$key.Count matches found!" - Write-Warning "To prevent accidental data loss, no programs will be uninstalled." - Write-Warning "Please alert package maintainer the following keys were matched:" - $key | % {Write-Warning "- $_.DisplayName"} -} diff --git a/ext/installfiles/windows/chocolatey/zerotier-one/zerotier-one.nuspec b/ext/installfiles/windows/chocolatey/zerotier-one/zerotier-one.nuspec deleted file mode 100644 index 2fb4fe57..00000000 --- a/ext/installfiles/windows/chocolatey/zerotier-one/zerotier-one.nuspec +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - zerotier-one - - - - 1.2.12 - - - - - - - - zerotier-one (Install) - ZeroTier, Inc. - - https://www.zerotier.com/ - - - - - - - - - zerotier-one admin - ZeroTier One Virtual Network Endpoint for Windows - ZeroTier is a smart switch for Earth with VLAN capability. See https://www.zerotier.com/ for more information. - - - - - - - - - - - - - - - - - diff --git a/zerotier-one.spec b/zerotier-one.spec index 55cc1fb0..72a5a96a 100644 --- a/zerotier-one.spec +++ b/zerotier-one.spec @@ -1,5 +1,5 @@ Name: zerotier-one -Version: 1.2.12 +Version: 1.2.99 Release: 1%{?dist} Summary: ZeroTier One network virtualization service From a17c7601811161489218f0d87d40387713c4b9c3 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 27 Jun 2019 14:36:31 -0700 Subject: [PATCH 034/185] Fix Mac installer --- ext/installfiles/mac/ZeroTier One.pkgproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/installfiles/mac/ZeroTier One.pkgproj b/ext/installfiles/mac/ZeroTier One.pkgproj index e10b49ec..71c2f2db 100755 --- a/ext/installfiles/mac/ZeroTier One.pkgproj +++ b/ext/installfiles/mac/ZeroTier One.pkgproj @@ -109,9 +109,9 @@ CHILDREN GID - 0 + 80 PATH - ../../bin/tap-mac/tap.kext + ../../../MacEthernetTapAgent PATH_TYPE 1 PERMISSIONS From 3c02c2e4bdf8cb0af0bf125a6984186b5866505e Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 28 Jun 2019 08:48:06 -0700 Subject: [PATCH 035/185] Windows installer bump --- ext/installfiles/windows/ZeroTier One.aip | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/installfiles/windows/ZeroTier One.aip b/ext/installfiles/windows/ZeroTier One.aip index 0e7907bc..df9a5064 100644 --- a/ext/installfiles/windows/ZeroTier One.aip +++ b/ext/installfiles/windows/ZeroTier One.aip @@ -27,7 +27,7 @@ - + From 7db073d9935069a5ecfaaa49d9756cd11147dee0 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 28 Jun 2019 11:20:38 -0700 Subject: [PATCH 036/185] Start 1.4.0 release notes. --- RELEASE-NOTES.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 1b6da759..9e153ff6 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,6 +1,17 @@ ZeroTier Release Notes ====== +# 2019-??-?? -- Version 1.4.0 (currently in prerelease as 1.2.99) + + * Added support for concurrent multipath (multiple paths at once) with traffic weighting by link quality and faster recovery from lost links. + * Added under-the-hood support for QoS (not yet exposed) that will eventually be configurable via our rules engine. + * Modified credential push and direct path push timings and algorithms to somewhat reduce "chattiness" of the protocol when idle. More radical background overhead reductions will have to wait for the 2.x line. + * Mac version no longer requires a kernel extension, instead making use of the [feth interfaces](https://apple.stackexchange.com/questions/337715/fake-ethernet-interfaces-feth-if-fake-anyone-ever-seen-this). + * Removed our beta/half-baked integration of Central with the Windows UI. We're going to do a whole new UI of some kind in the future at least for Windows and Mac. + * Fixed stack overflow issues on Linux versions using musl libc. + * Fixed some alignment problems reported on ARM and ARM64, but some reports we could not reproduce so please report any issues with exact chip, OS/distro, and ZeroTier version in use. + * Fixed numerous other small issues and bugs. + # 2018-07-27 -- Version 1.2.12 * Fixed a bug that caused exits to take a long time on Mac due to huge numbers of redundant attempts to delete managed routes. From 9ccbe8592379759b0962f303f4382df295f50c12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksandar=20Topuzovi=C4=87?= Date: Mon, 1 Jul 2019 14:56:02 +0100 Subject: [PATCH 037/185] Fix compiling on Raspberry PI Zero W on Arch Linux * Should also fix it for Raspberry PI 1 * "gcc -dumpmachine | cut -d '-' -f 1" reports armv6l --- make-linux.mk | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/make-linux.mk b/make-linux.mk index 24e054dc..7aec6522 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -156,6 +156,11 @@ ifeq ($(CC_MACH),armv6) override DEFS+=-DZT_NO_TYPE_PUNNING ZT_USE_ARM32_NEON_ASM_CRYPTO=1 endif +ifeq ($(CC_MACH),armv6l) + ZT_ARCHITECTURE=3 + override DEFS+=-DZT_NO_TYPE_PUNNING + ZT_USE_ARM32_NEON_ASM_CRYPTO=1 +endif ifeq ($(CC_MACH),armv6zk) ZT_ARCHITECTURE=3 override DEFS+=-DZT_NO_TYPE_PUNNING From ac0082a67e2eec80fb674e8d37f81d80f75ad7b3 Mon Sep 17 00:00:00 2001 From: Travis LaDuke Date: Tue, 2 Jul 2019 11:56:19 -0700 Subject: [PATCH 038/185] Update README.md --- service/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/README.md b/service/README.md index 3b9901fd..59d414aa 100644 --- a/service/README.md +++ b/service/README.md @@ -5,7 +5,7 @@ This is the actual implementation of ZeroTier One, a service providing connectiv ### Local Configuration File -A file called `local.conf` in the ZeroTier home folder contains configuration options that apply to the local node. It can be used to set up trusted paths, blacklist physical paths, set up physical path hints for certain nodes, and define trusted upstream devices (federated roots). In a large deployment it can be deployed using a tool like Puppet, Chef, SaltStack, etc. to set a uniform configuration across systems. It's a JSON format file that can also be edited and rewritten by ZeroTier One itself, so ensure that proper JSON formatting is used. +A file called `local.conf` in the ZeroTier home folder contains configuration options that apply to the local node. (It does not exist unless you create it). It can be used to set up trusted paths, blacklist physical paths, set up physical path hints for certain nodes, and define trusted upstream devices (federated roots). In a large deployment it can be deployed using a tool like Puppet, Chef, SaltStack, etc. to set a uniform configuration across systems. It's a JSON format file that can also be edited and rewritten by ZeroTier One itself, so ensure that proper JSON formatting is used. Settings available in `local.conf` (this is not valid JSON, and JSON does not allow comments): From 203414910fc07786821a11067b0397d3d3544707 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Mon, 8 Jul 2019 12:33:26 -0700 Subject: [PATCH 039/185] Give up to a second for the interface to appear to assign IP addresses --- osdep/LinuxNetLink.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osdep/LinuxNetLink.cpp b/osdep/LinuxNetLink.cpp index 6645a856..a276b407 100644 --- a/osdep/LinuxNetLink.cpp +++ b/osdep/LinuxNetLink.cpp @@ -850,6 +850,10 @@ void LinuxNetLink::addAddress(const InetAddress &addr, const char *iface) #endif int interface_index = _indexForInterface(iface); + for (int reps = 0; interface_index == -1 && reps < 10; ++reps) { + Thread::sleep(100); + interface_index == _indexForInterface(iface); + } if (interface_index == -1) { fprintf(stderr, "Unable to find index for interface %s\n", iface); From 409406d114d1157e283c50937c895f7c927ed839 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Mon, 8 Jul 2019 12:36:49 -0700 Subject: [PATCH 040/185] Whoops --- osdep/LinuxNetLink.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osdep/LinuxNetLink.cpp b/osdep/LinuxNetLink.cpp index a276b407..6bebfe2e 100644 --- a/osdep/LinuxNetLink.cpp +++ b/osdep/LinuxNetLink.cpp @@ -852,7 +852,7 @@ void LinuxNetLink::addAddress(const InetAddress &addr, const char *iface) int interface_index = _indexForInterface(iface); for (int reps = 0; interface_index == -1 && reps < 10; ++reps) { Thread::sleep(100); - interface_index == _indexForInterface(iface); + interface_index = _indexForInterface(iface); } if (interface_index == -1) { From fee6aae442d86146063fa903626a95f7adcf8764 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 9 Jul 2019 10:31:08 -0400 Subject: [PATCH 041/185] Drop in faster C25519 agreement code. --- .gitignore | 2 + attic/README.md | 4 - attic/lat_lon_to_xyz.js | 25 - attic/world/build.sh | 4 +- attic/world/mkworld.cpp | 21 +- attic/world/old/earth-2015-11-16.bin | Bin 494 -> 0 bytes attic/world/old/earth-2015-11-20.bin | Bin 792 -> 0 bytes attic/world/old/earth-2015-12-17.bin | Bin 732 -> 0 bytes attic/world/old/earth-2016-01-13.bin | Bin 634 -> 0 bytes attic/world/world.bin | Bin 634 -> 732 bytes attic/world/world.c | 4 +- node/C25519.cpp | 718 ++++++++++++++++++++++++++- 12 files changed, 733 insertions(+), 45 deletions(-) delete mode 100644 attic/README.md delete mode 100644 attic/lat_lon_to_xyz.js delete mode 100644 attic/world/old/earth-2015-11-16.bin delete mode 100644 attic/world/old/earth-2015-11-20.bin delete mode 100644 attic/world/old/earth-2015-12-17.bin delete mode 100644 attic/world/old/earth-2016-01-13.bin diff --git a/.gitignore b/.gitignore index 94ebeeb6..44b5eb56 100755 --- a/.gitignore +++ b/.gitignore @@ -118,3 +118,5 @@ ext/librethinkdbxx/build .vscode __pycache__ *~ +attic/world/*.c25519 +attic/world/mkworld diff --git a/attic/README.md b/attic/README.md deleted file mode 100644 index 768bccd4..00000000 --- a/attic/README.md +++ /dev/null @@ -1,4 +0,0 @@ -Retired Code and Miscellaneous Junk -====== - -This directory is for old code that isn't used but we don't want to lose track of, and for anything else random like debug scripts. diff --git a/attic/lat_lon_to_xyz.js b/attic/lat_lon_to_xyz.js deleted file mode 100644 index 692a3687..00000000 --- a/attic/lat_lon_to_xyz.js +++ /dev/null @@ -1,25 +0,0 @@ -'use strict' - -/* This is a utility to convert latitude/longitude into X,Y,Z coordinates as used by clustering. */ - -if (process.argv.length !== 4) { - console.log('Usage: node lat_lon_to_xyz.js roots; const uint64_t id = ZT_WORLD_ID_EARTH; - const uint64_t ts = 1532555817048ULL; // July 25th, 2018 + const uint64_t ts = 1562631342273ULL; // July 8th, 2019 + + roots.push_back(World::Root()); + roots.back().identity = Identity("3a46f1bf30:0:76e66fab33e28549a62ee2064d1843273c2c300ba45c3f20bef02dbad225723bb59a9bb4b13535730961aeecf5a163ace477cceb0727025b99ac14a5166a09a3"); + roots.back().stableEndpoints.push_back(InetAddress("185.180.13.82/9993")); + roots.back().stableEndpoints.push_back(InetAddress("2a02:6ea0:c815::/9993")); // Alice roots.push_back(World::Root()); @@ -118,7 +123,7 @@ int main(int argc,char **argv) // END WORLD DEFINITION // ========================================================================= - fprintf(stderr,"INFO: generating and signing id==%llu ts==%llu"ZT_EOL_S,(unsigned long long)id,(unsigned long long)ts); + fprintf(stderr,"INFO: generating and signing id==%llu ts==%llu" ZT_EOL_S,(unsigned long long)id,(unsigned long long)ts); World nw = World::make(World::TYPE_PLANET,id,ts,currentKP.pub,roots,previousKP); @@ -127,15 +132,15 @@ int main(int argc,char **argv) World testw; testw.deserialize(outtmp,0); if (testw != nw) { - fprintf(stderr,"FATAL: serialization test failed!"ZT_EOL_S); + fprintf(stderr,"FATAL: serialization test failed!" ZT_EOL_S); return 1; } OSUtils::writeFile("world.bin",std::string((const char *)outtmp.data(),outtmp.size())); - fprintf(stderr,"INFO: world.bin written with %u bytes of binary world data."ZT_EOL_S,outtmp.size()); + fprintf(stderr,"INFO: world.bin written with %u bytes of binary world data." ZT_EOL_S,outtmp.size()); fprintf(stdout,ZT_EOL_S); - fprintf(stdout,"#define ZT_DEFAULT_WORLD_LENGTH %u"ZT_EOL_S,outtmp.size()); + fprintf(stdout,"#define ZT_DEFAULT_WORLD_LENGTH %u" ZT_EOL_S,outtmp.size()); fprintf(stdout,"static const unsigned char ZT_DEFAULT_WORLD[ZT_DEFAULT_WORLD_LENGTH] = {"); for(unsigned int i=0;i25mq)IuzEdXVj$;cS%fH9|`@&9L=L$f2 zm(Dh#Jq5~#$5|&_iw#V)yCyGp7hbnbxYM-hBVEj*aj4(%Bcrlrbn4~YjqlS6sjSP| zlf7)sLmj7>YTj_b#vHHk{eOzNb`#;=PxICj1b!KZYPtX_ZYv`glMi6)34d_V^sp$h z&22plW55)-1E2F#kmM18@)r9pZ>ZT^9_eOrRzVpB!`#p6c-Y3@uexY~aI^XV0R+a! zVcaJPh(SP#E&#h7G4jJB;$-ROL2|*TPj`uxRqYUU9Mx`yKwRDtjRN2PRb56b&uWFW zV;mAS42@mH3Azxu0$mS8T=YrVD;xj;1Z%%8(kBUu&jp|307x%x<=^Q7F`Gf1<-Nyc zAe;`(ql`^%PtOfAWrLWsQhm)L`7sjvoA1ys*NgWi8#6z_1<{hGBg&po{9vy49h^ zeD=521kGWe^taey*($}=E0%QrUAM%`a=$J^>a3F|BwoMZ`nu`#&bK*Z< z*2n(2ZeFeQW@W|7b2~4b-a4haQ!%{gTfxG+=@#c*T@UrTyt23 z^G_$P2Fj?htZ3k1U|0y22}uCyS!vmy0g_?=a6y)lAsniQ2`H1j>L?#n4+A5E0!W65 z;Q>fb!||gxfifx#i48zOhzqtm0A)HH9lG=wcFP)mI;{LC<>fQSqJzu*%R8rrz7;5y zxtiDJ5OYtkm+Ah$&{#K}^I5H1lVyZVd3s}yaPAV=$rQ`)67$9LrnU^wkGcxSnt(Pa zFiL(%VQ4%Y!ocwVpM-28&~Cld1wVl@VBa%C?and)xhi|V-X*A>42I?9k-XLItm=vIds z^V#286Euf?(%)i-WvdiduUOLgcij>%%l*0xsk2U=ka*p7>XU7u-XTlZw9PLqD>sH7 zS@~zrpV0MP`W7e7zGRASTUqp7jKOq!%gH}aeogECBDX7HeyhkKcJIFzb0jk_|KyxA z_wmkt!HUA=UaU9HBrIY}o9}+8a7ReP99J=cl^6DYXP&D#!SXW$9mqp`r@TKi(j?8uWeobEKz=o{fF(2 zYB#y^7{Unkpn4b>85BS= zObib|dK!)&y$O_2VMuHM3PN14-2o`m;pot%$FN)0@Y7-CM=39#ITjsU?qA+HHT11O zsm#^9Hiwvdg1t=l|Aof7>737M-I^>TWXjVUdxUeBz)q%EewUapo;S5+fPU0fIMxKT zL4i^7LkdIV;SdIf|NkUp6M=T?r7rjhlmYvm8ESWy0mxO^`}HnC^<*$KF9Eq12vUGD zx(eSmLuDcux_^L86Wu%uEb}8ADpSBP`y@o>$XB4u{L@T81>g|lSqrsCtpI3Gon(8~ zE(WbUZDonc{0Xl)>kBS?*`TrMY_2U&@&S>Z%=147Pk18O_(|-yUjB-kF>)`{3d0;F nSr6Yi|El7~vHR8w=a_o5G9jFbk@MSpq0cZmNi#QIk diff --git a/attic/world/old/earth-2016-01-13.bin b/attic/world/old/earth-2016-01-13.bin deleted file mode 100644 index 5dea4d215716ccf10c3a529c5d45ba69b8a0ec58..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 634 zcmZQ%00NFzC%G6H7=vt#0;G0q?pTtkBry49h^ zeD=521kGWe^taey*($}=E0%QrUAM%`a=$J^>a3F|Bwl-cZ(HGTE$G#{c~$#;rl+me z&0l{~+v@+@YX){lvQj_oZ4UbC@bV0AUZ?%61v~CLUD9uP#;nG_;_(?)R_6CY4ZP>< zwnbRWuULCr^`~>;@|ao2A1>a}aiK70%FJR%ZfTDern!m}EI%_aewd^+dVPVys%>+N_W639nbR|AN=0~~YR<)*PAhq(FJ8K{_*KjM+Sc{Y66Lqpf7tG* zc9ScQfrn+!vbc@voNQXm8xAlqF;Mg z#P9&5r{Va~n?M;AhQtP-AjAdR9e^?&jt*UV47+6wKOI(nl=AYKW6{Co{^gxhL*ELN z%3RHBbBMVo*voYPUudkG&iSm?t;sS%raZl|M>uy0>|~1NcZvDpc~e^k=to_JV@*IC z6c{Bxq%brd4q;&U|4%|T5ootw>Vls@8L;n}p>}5(fLxWmU+)rBPX)*yJxy_bS{HSbLoH%glc)9J3$HE0>+` zF1BitzkrzS@i&(z%)40fXY*F}Ilfbmig(*`CzQPi+`Y}VWUFFx^;B7=*=N_s*iE}{ zt`nB~tCas%Xshs-GO09Q>)!K1Crx(pCNf*OecW%rQ1&c;weh1?&t-a#*nB0N)opYP zxR=D(E4b|Ypu6jmYLWHUS+lonG&L>eOkDTo>%!zUPs-1{W>;s5p1DS3saO{0Vg@Fb zom+T=)H&I-nDQ2!5C!=K0@OJtZi=i2v1=I^)j3&aIUQ95D%0Wr5x^M2I323W7$`IU zbmD5Dj2g>|1`Y;>gwST=*ekqM$?K{=Zj^zKiBDBH;v z#2CEqOo*$S?ZPfZMzS&2otoH<%`iFhMT2j0W@T2A~i47?|KP z*{hE7LG=J_P+($sz{v3rtf%4l(VIXS6^2Bh9xjFp4BH*RQj@}1zDQC oU+)r7nF6EahYW`1B@8KNIT{$xa!l@Fa_3YlVEiX~> 32); + /* Set to all 1s if v was negative; else set to 0s. */ + const int32_t sign = ((int32_t) highword) >> 31; + /* Set to 0x3ffffff if v was negative; else set to 0. */ + const int32_t roundoff = ((uint32_t) sign) >> 6; + /* Should return v / (1<<26) */ + return (v + roundoff) >> 26; +} + +static inline limb div_by_2_25(const limb v) +{ + /* High word of v; no shift needed*/ + const uint32_t highword = (uint32_t) (((uint64_t) v) >> 32); + /* Set to all 1s if v was negative; else set to 0s. */ + const int32_t sign = ((int32_t) highword) >> 31; + /* Set to 0x1ffffff if v was negative; else set to 0. */ + const int32_t roundoff = ((uint32_t) sign) >> 7; + /* Should return v / (1<<25) */ + return (v + roundoff) >> 25; +} + +static inline void freduce_coefficients(limb *output) { + unsigned i; + + output[10] = 0; + + for (i = 0; i < 10; i += 2) { + limb over = div_by_2_26(output[i]); + /* The entry condition (that |output[i]| < 280*2^54) means that over is, at + * most, 280*2^28 in the first iteration of this loop. This is added to the + * next limb and we can approximate the resulting bound of that limb by + * 281*2^54. */ + output[i] -= over << 26; + output[i+1] += over; + + /* For the first iteration, |output[i+1]| < 281*2^54, thus |over| < + * 281*2^29. When this is added to the next limb, the resulting bound can + * be approximated as 281*2^54. + * + * For subsequent iterations of the loop, 281*2^54 remains a conservative + * bound and no overflow occurs. */ + over = div_by_2_25(output[i+1]); + output[i+1] -= over << 25; + output[i+2] += over; + } + /* Now |output[10]| < 281*2^29 and all other coefficients are reduced. */ + output[0] += output[10] << 4; + output[0] += output[10] << 1; + output[0] += output[10]; + + output[10] = 0; + + /* Now output[1..9] are reduced, and |output[0]| < 2^26 + 19*281*2^29 + * So |over| will be no more than 2^16. */ + { + limb over = div_by_2_26(output[0]); + output[0] -= over << 26; + output[1] += over; + } + + /* Now output[0,2..9] are reduced, and |output[1]| < 2^25 + 2^16 < 2^26. The + * bound on |output[1]| is sufficient to meet our needs. */ +} + +static inline void fmul(limb *output, const limb *in, const limb *in2) { + limb t[19]; + fproduct(t, in, in2); + /* |t[i]| < 14*2^54 */ + freduce_degree(t); + freduce_coefficients(t); + /* |t[i]| < 2^26 */ + memcpy(output, t, sizeof(limb) * 10); +} + +static inline void fsquare_inner(limb *output, const limb *in) { + output[0] = ((limb) ((s32) in[0])) * ((s32) in[0]); + output[1] = 2 * ((limb) ((s32) in[0])) * ((s32) in[1]); + output[2] = 2 * (((limb) ((s32) in[1])) * ((s32) in[1]) + + ((limb) ((s32) in[0])) * ((s32) in[2])); + output[3] = 2 * (((limb) ((s32) in[1])) * ((s32) in[2]) + + ((limb) ((s32) in[0])) * ((s32) in[3])); + output[4] = ((limb) ((s32) in[2])) * ((s32) in[2]) + + 4 * ((limb) ((s32) in[1])) * ((s32) in[3]) + + 2 * ((limb) ((s32) in[0])) * ((s32) in[4]); + output[5] = 2 * (((limb) ((s32) in[2])) * ((s32) in[3]) + + ((limb) ((s32) in[1])) * ((s32) in[4]) + + ((limb) ((s32) in[0])) * ((s32) in[5])); + output[6] = 2 * (((limb) ((s32) in[3])) * ((s32) in[3]) + + ((limb) ((s32) in[2])) * ((s32) in[4]) + + ((limb) ((s32) in[0])) * ((s32) in[6]) + + 2 * ((limb) ((s32) in[1])) * ((s32) in[5])); + output[7] = 2 * (((limb) ((s32) in[3])) * ((s32) in[4]) + + ((limb) ((s32) in[2])) * ((s32) in[5]) + + ((limb) ((s32) in[1])) * ((s32) in[6]) + + ((limb) ((s32) in[0])) * ((s32) in[7])); + output[8] = ((limb) ((s32) in[4])) * ((s32) in[4]) + + 2 * (((limb) ((s32) in[2])) * ((s32) in[6]) + + ((limb) ((s32) in[0])) * ((s32) in[8]) + + 2 * (((limb) ((s32) in[1])) * ((s32) in[7]) + + ((limb) ((s32) in[3])) * ((s32) in[5]))); + output[9] = 2 * (((limb) ((s32) in[4])) * ((s32) in[5]) + + ((limb) ((s32) in[3])) * ((s32) in[6]) + + ((limb) ((s32) in[2])) * ((s32) in[7]) + + ((limb) ((s32) in[1])) * ((s32) in[8]) + + ((limb) ((s32) in[0])) * ((s32) in[9])); + output[10] = 2 * (((limb) ((s32) in[5])) * ((s32) in[5]) + + ((limb) ((s32) in[4])) * ((s32) in[6]) + + ((limb) ((s32) in[2])) * ((s32) in[8]) + + 2 * (((limb) ((s32) in[3])) * ((s32) in[7]) + + ((limb) ((s32) in[1])) * ((s32) in[9]))); + output[11] = 2 * (((limb) ((s32) in[5])) * ((s32) in[6]) + + ((limb) ((s32) in[4])) * ((s32) in[7]) + + ((limb) ((s32) in[3])) * ((s32) in[8]) + + ((limb) ((s32) in[2])) * ((s32) in[9])); + output[12] = ((limb) ((s32) in[6])) * ((s32) in[6]) + + 2 * (((limb) ((s32) in[4])) * ((s32) in[8]) + + 2 * (((limb) ((s32) in[5])) * ((s32) in[7]) + + ((limb) ((s32) in[3])) * ((s32) in[9]))); + output[13] = 2 * (((limb) ((s32) in[6])) * ((s32) in[7]) + + ((limb) ((s32) in[5])) * ((s32) in[8]) + + ((limb) ((s32) in[4])) * ((s32) in[9])); + output[14] = 2 * (((limb) ((s32) in[7])) * ((s32) in[7]) + + ((limb) ((s32) in[6])) * ((s32) in[8]) + + 2 * ((limb) ((s32) in[5])) * ((s32) in[9])); + output[15] = 2 * (((limb) ((s32) in[7])) * ((s32) in[8]) + + ((limb) ((s32) in[6])) * ((s32) in[9])); + output[16] = ((limb) ((s32) in[8])) * ((s32) in[8]) + + 4 * ((limb) ((s32) in[7])) * ((s32) in[9]); + output[17] = 2 * ((limb) ((s32) in[8])) * ((s32) in[9]); + output[18] = 2 * ((limb) ((s32) in[9])) * ((s32) in[9]); +} + +static void fsquare(limb *output, const limb *in) { + limb t[19]; + fsquare_inner(t, in); + /* |t[i]| < 14*2^54 because the largest product of two limbs will be < + * 2^(27+27) and fsquare_inner adds together, at most, 14 of those + * products. */ + freduce_degree(t); + freduce_coefficients(t); + /* |t[i]| < 2^26 */ + memcpy(output, t, sizeof(limb) * 10); +} + +static inline void fexpand(limb *output, const u8 *input) { +#define F(n,start,shift,mask) \ + output[n] = ((((limb) input[start + 0]) | \ + ((limb) input[start + 1]) << 8 | \ + ((limb) input[start + 2]) << 16 | \ + ((limb) input[start + 3]) << 24) >> shift) & mask; + F(0, 0, 0, 0x3ffffff); + F(1, 3, 2, 0x1ffffff); + F(2, 6, 3, 0x3ffffff); + F(3, 9, 5, 0x1ffffff); + F(4, 12, 6, 0x3ffffff); + F(5, 16, 0, 0x1ffffff); + F(6, 19, 1, 0x3ffffff); + F(7, 22, 3, 0x1ffffff); + F(8, 25, 4, 0x3ffffff); + F(9, 28, 6, 0x1ffffff); +#undef F +} + +#if (-32 >> 1) != -16 +#error "This code only works when >> does sign-extension on negative numbers" +#endif + +static inline s32 s32_eq(s32 a, s32 b) { + a = ~(a ^ b); + a &= a << 16; + a &= a << 8; + a &= a << 4; + a &= a << 2; + a &= a << 1; + return a >> 31; +} + +static inline s32 s32_gte(s32 a, s32 b) { + a -= b; + /* a >= 0 iff a >= b. */ + return ~(a >> 31); +} + +static inline void fcontract(u8 *output, limb *input_limbs) { + int i; + int j; + s32 input[10]; + s32 mask; + + /* |input_limbs[i]| < 2^26, so it's valid to convert to an s32. */ + for (i = 0; i < 10; i++) { + input[i] = input_limbs[i]; + } + + for (j = 0; j < 2; ++j) { + for (i = 0; i < 9; ++i) { + if ((i & 1) == 1) { + /* This calculation is a time-invariant way to make input[i] + * non-negative by borrowing from the next-larger limb. */ + const s32 mask = input[i] >> 31; + const s32 carry = -((input[i] & mask) >> 25); + input[i] = input[i] + (carry << 25); + input[i+1] = input[i+1] - carry; + } else { + const s32 mask = input[i] >> 31; + const s32 carry = -((input[i] & mask) >> 26); + input[i] = input[i] + (carry << 26); + input[i+1] = input[i+1] - carry; + } + } + + /* There's no greater limb for input[9] to borrow from, but we can multiply + * by 19 and borrow from input[0], which is valid mod 2^255-19. */ + { + const s32 mask = input[9] >> 31; + const s32 carry = -((input[9] & mask) >> 25); + input[9] = input[9] + (carry << 25); + input[0] = input[0] - (carry * 19); + } + + /* After the first iteration, input[1..9] are non-negative and fit within + * 25 or 26 bits, depending on position. However, input[0] may be + * negative. */ + } + + /* The first borrow-propagation pass above ended with every limb + except (possibly) input[0] non-negative. + + If input[0] was negative after the first pass, then it was because of a + carry from input[9]. On entry, input[9] < 2^26 so the carry was, at most, + one, since (2**26-1) >> 25 = 1. Thus input[0] >= -19. + + In the second pass, each limb is decreased by at most one. Thus the second + borrow-propagation pass could only have wrapped around to decrease + input[0] again if the first pass left input[0] negative *and* input[1] + through input[9] were all zero. In that case, input[1] is now 2^25 - 1, + and this last borrow-propagation step will leave input[1] non-negative. */ + { + const s32 mask = input[0] >> 31; + const s32 carry = -((input[0] & mask) >> 26); + input[0] = input[0] + (carry << 26); + input[1] = input[1] - carry; + } + + /* All input[i] are now non-negative. However, there might be values between + * 2^25 and 2^26 in a limb which is, nominally, 25 bits wide. */ + for (j = 0; j < 2; j++) { + for (i = 0; i < 9; i++) { + if ((i & 1) == 1) { + const s32 carry = input[i] >> 25; + input[i] &= 0x1ffffff; + input[i+1] += carry; + } else { + const s32 carry = input[i] >> 26; + input[i] &= 0x3ffffff; + input[i+1] += carry; + } + } + + { + const s32 carry = input[9] >> 25; + input[9] &= 0x1ffffff; + input[0] += 19*carry; + } + } + + /* If the first carry-chain pass, just above, ended up with a carry from + * input[9], and that caused input[0] to be out-of-bounds, then input[0] was + * < 2^26 + 2*19, because the carry was, at most, two. + * + * If the second pass carried from input[9] again then input[0] is < 2*19 and + * the input[9] -> input[0] carry didn't push input[0] out of bounds. */ + + /* It still remains the case that input might be between 2^255-19 and 2^255. + * In this case, input[1..9] must take their maximum value and input[0] must + * be >= (2^255-19) & 0x3ffffff, which is 0x3ffffed. */ + mask = s32_gte(input[0], 0x3ffffed); + for (i = 1; i < 10; i++) { + if ((i & 1) == 1) { + mask &= s32_eq(input[i], 0x1ffffff); + } else { + mask &= s32_eq(input[i], 0x3ffffff); + } + } + + /* mask is either 0xffffffff (if input >= 2^255-19) and zero otherwise. Thus + * this conditionally subtracts 2^255-19. */ + input[0] -= mask & 0x3ffffed; + + for (i = 1; i < 10; i++) { + if ((i & 1) == 1) { + input[i] -= mask & 0x1ffffff; + } else { + input[i] -= mask & 0x3ffffff; + } + } + + input[1] <<= 2; + input[2] <<= 3; + input[3] <<= 5; + input[4] <<= 6; + input[6] <<= 1; + input[7] <<= 3; + input[8] <<= 4; + input[9] <<= 6; +#define F(i, s) \ + output[s+0] |= input[i] & 0xff; \ + output[s+1] = (input[i] >> 8) & 0xff; \ + output[s+2] = (input[i] >> 16) & 0xff; \ + output[s+3] = (input[i] >> 24) & 0xff; + output[0] = 0; + output[16] = 0; + F(0,0); + F(1,3); + F(2,6); + F(3,9); + F(4,12); + F(5,16); + F(6,19); + F(7,22); + F(8,25); + F(9,28); +#undef F +} + +static inline void fmonty(limb *x2, limb *z2, /* output 2Q */ + limb *x3, limb *z3, /* output Q + Q' */ + limb *x, limb *z, /* input Q */ + limb *xprime, limb *zprime, /* input Q' */ + const limb *qmqp /* input Q - Q' */) { + limb origx[10], origxprime[10], zzz[19], xx[19], zz[19], xxprime[19], + zzprime[19], zzzprime[19], xxxprime[19]; + + memcpy(origx, x, 10 * sizeof(limb)); + fsum(x, z); + /* |x[i]| < 2^27 */ + fdifference(z, origx); /* does x - z */ + /* |z[i]| < 2^27 */ + + memcpy(origxprime, xprime, sizeof(limb) * 10); + fsum(xprime, zprime); + /* |xprime[i]| < 2^27 */ + fdifference(zprime, origxprime); + /* |zprime[i]| < 2^27 */ + fproduct(xxprime, xprime, z); + /* |xxprime[i]| < 14*2^54: the largest product of two limbs will be < + * 2^(27+27) and fproduct adds together, at most, 14 of those products. + * (Approximating that to 2^58 doesn't work out.) */ + fproduct(zzprime, x, zprime); + /* |zzprime[i]| < 14*2^54 */ + freduce_degree(xxprime); + freduce_coefficients(xxprime); + /* |xxprime[i]| < 2^26 */ + freduce_degree(zzprime); + freduce_coefficients(zzprime); + /* |zzprime[i]| < 2^26 */ + memcpy(origxprime, xxprime, sizeof(limb) * 10); + fsum(xxprime, zzprime); + /* |xxprime[i]| < 2^27 */ + fdifference(zzprime, origxprime); + /* |zzprime[i]| < 2^27 */ + fsquare(xxxprime, xxprime); + /* |xxxprime[i]| < 2^26 */ + fsquare(zzzprime, zzprime); + /* |zzzprime[i]| < 2^26 */ + fproduct(zzprime, zzzprime, qmqp); + /* |zzprime[i]| < 14*2^52 */ + freduce_degree(zzprime); + freduce_coefficients(zzprime); + /* |zzprime[i]| < 2^26 */ + memcpy(x3, xxxprime, sizeof(limb) * 10); + memcpy(z3, zzprime, sizeof(limb) * 10); + + fsquare(xx, x); + /* |xx[i]| < 2^26 */ + fsquare(zz, z); + /* |zz[i]| < 2^26 */ + fproduct(x2, xx, zz); + /* |x2[i]| < 14*2^52 */ + freduce_degree(x2); + freduce_coefficients(x2); + /* |x2[i]| < 2^26 */ + fdifference(zz, xx); // does zz = xx - zz + /* |zz[i]| < 2^27 */ + memset(zzz + 10, 0, sizeof(limb) * 9); + fscalar_product(zzz, zz, 121665); + /* |zzz[i]| < 2^(27+17) */ + /* No need to call freduce_degree here: + fscalar_product doesn't increase the degree of its input. */ + freduce_coefficients(zzz); + /* |zzz[i]| < 2^26 */ + fsum(zzz, xx); + /* |zzz[i]| < 2^27 */ + fproduct(z2, zz, zzz); + /* |z2[i]| < 14*2^(26+27) */ + freduce_degree(z2); + freduce_coefficients(z2); + /* |z2|i| < 2^26 */ +} + +static inline void swap_conditional(limb a[19], limb b[19], limb iswap) { + unsigned i; + const s32 swap = (s32) -iswap; + + for (i = 0; i < 10; ++i) { + const s32 x = swap & ( ((s32)a[i]) ^ ((s32)b[i]) ); + a[i] = ((s32)a[i]) ^ x; + b[i] = ((s32)b[i]) ^ x; + } +} + +static inline void cmult(limb *resultx, limb *resultz, const u8 *n, const limb *q) { + limb a[19] = {0}, b[19] = {1}, c[19] = {1}, d[19] = {0}; + limb *nqpqx = a, *nqpqz = b, *nqx = c, *nqz = d, *t; + limb e[19] = {0}, f[19] = {1}, g[19] = {0}, h[19] = {1}; + limb *nqpqx2 = e, *nqpqz2 = f, *nqx2 = g, *nqz2 = h; + + unsigned i, j; + + memcpy(nqpqx, q, sizeof(limb) * 10); + + for (i = 0; i < 32; ++i) { + u8 byte = n[31 - i]; + for (j = 0; j < 8; ++j) { + const limb bit = byte >> 7; + + swap_conditional(nqx, nqpqx, bit); + swap_conditional(nqz, nqpqz, bit); + fmonty(nqx2, nqz2, + nqpqx2, nqpqz2, + nqx, nqz, + nqpqx, nqpqz, + q); + swap_conditional(nqx2, nqpqx2, bit); + swap_conditional(nqz2, nqpqz2, bit); + + t = nqx; + nqx = nqx2; + nqx2 = t; + t = nqz; + nqz = nqz2; + nqz2 = t; + t = nqpqx; + nqpqx = nqpqx2; + nqpqx2 = t; + t = nqpqz; + nqpqz = nqpqz2; + nqpqz2 = t; + + byte <<= 1; + } + } + + memcpy(resultx, nqx, sizeof(limb) * 10); + memcpy(resultz, nqz, sizeof(limb) * 10); +} + +static inline void crecip(limb *out, const limb *z) { + limb z2[10]; + limb z9[10]; + limb z11[10]; + limb z2_5_0[10]; + limb z2_10_0[10]; + limb z2_20_0[10]; + limb z2_50_0[10]; + limb z2_100_0[10]; + limb t0[10]; + limb t1[10]; + int i; + + /* 2 */ fsquare(z2,z); + /* 4 */ fsquare(t1,z2); + /* 8 */ fsquare(t0,t1); + /* 9 */ fmul(z9,t0,z); + /* 11 */ fmul(z11,z9,z2); + /* 22 */ fsquare(t0,z11); + /* 2^5 - 2^0 = 31 */ fmul(z2_5_0,t0,z9); + + /* 2^6 - 2^1 */ fsquare(t0,z2_5_0); + /* 2^7 - 2^2 */ fsquare(t1,t0); + /* 2^8 - 2^3 */ fsquare(t0,t1); + /* 2^9 - 2^4 */ fsquare(t1,t0); + /* 2^10 - 2^5 */ fsquare(t0,t1); + /* 2^10 - 2^0 */ fmul(z2_10_0,t0,z2_5_0); + + /* 2^11 - 2^1 */ fsquare(t0,z2_10_0); + /* 2^12 - 2^2 */ fsquare(t1,t0); + /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } + /* 2^20 - 2^0 */ fmul(z2_20_0,t1,z2_10_0); + + /* 2^21 - 2^1 */ fsquare(t0,z2_20_0); + /* 2^22 - 2^2 */ fsquare(t1,t0); + /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } + /* 2^40 - 2^0 */ fmul(t0,t1,z2_20_0); + + /* 2^41 - 2^1 */ fsquare(t1,t0); + /* 2^42 - 2^2 */ fsquare(t0,t1); + /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t1,t0); fsquare(t0,t1); } + /* 2^50 - 2^0 */ fmul(z2_50_0,t0,z2_10_0); + + /* 2^51 - 2^1 */ fsquare(t0,z2_50_0); + /* 2^52 - 2^2 */ fsquare(t1,t0); + /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } + /* 2^100 - 2^0 */ fmul(z2_100_0,t1,z2_50_0); + + /* 2^101 - 2^1 */ fsquare(t1,z2_100_0); + /* 2^102 - 2^2 */ fsquare(t0,t1); + /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { fsquare(t1,t0); fsquare(t0,t1); } + /* 2^200 - 2^0 */ fmul(t1,t0,z2_100_0); + + /* 2^201 - 2^1 */ fsquare(t0,t1); + /* 2^202 - 2^2 */ fsquare(t1,t0); + /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } + /* 2^250 - 2^0 */ fmul(t0,t1,z2_50_0); + + /* 2^251 - 2^1 */ fsquare(t1,t0); + /* 2^252 - 2^2 */ fsquare(t0,t1); + /* 2^253 - 2^3 */ fsquare(t1,t0); + /* 2^254 - 2^4 */ fsquare(t0,t1); + /* 2^255 - 2^5 */ fsquare(t1,t0); + /* 2^255 - 21 */ fmul(out,t1,z11); +} + +static void crypto_scalarmult(u8 *mypublic, const u8 *secret, const u8 *basepoint) { + limb bp[10], x[10], z[11], zmone[10]; + uint8_t e[32]; + int i; + + for (i = 0; i < 32; ++i) e[i] = secret[i]; + e[0] &= 248; + e[31] &= 127; + e[31] |= 64; + + fexpand(bp, basepoint); + cmult(x, z, e, bp); + crecip(zmone, z); + fmul(z, x, zmone); + fcontract(mypublic, z); +} + +#if 0 void add(unsigned int out[32],const unsigned int a[32],const unsigned int b[32]) { unsigned int j; @@ -287,11 +994,12 @@ int crypto_scalarmult(unsigned char *q,const unsigned char *n,const unsigned cha for (i = 0;i < 32;++i) q[i] = work[64 + i]; return 0; } +#endif static const unsigned char base[32] = {9}; -int crypto_scalarmult_base(unsigned char *q,const unsigned char *n) +static inline void crypto_scalarmult_base(unsigned char *q,const unsigned char *n) { - return crypto_scalarmult(q,n,base); + crypto_scalarmult(q,n,base); } ////////////////////////////////////////////////////////////////////////////// From b2c4b7e99fbb9cf7ea3e88813b22d73d4d799661 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 9 Jul 2019 10:36:25 -0400 Subject: [PATCH 042/185] Version bunmp --- version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.h b/version.h index 699def7a..82013819 100644 --- a/version.h +++ b/version.h @@ -35,12 +35,12 @@ /** * Minor version */ -#define ZEROTIER_ONE_VERSION_MINOR 2 +#define ZEROTIER_ONE_VERSION_MINOR 4 /** * Revision */ -#define ZEROTIER_ONE_VERSION_REVISION 99 +#define ZEROTIER_ONE_VERSION_REVISION 0 /** * Build version From 389331ca2954d2fb602e8369349047adefbadd66 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Tue, 9 Jul 2019 10:31:03 -0700 Subject: [PATCH 043/185] Ticket #915, added allowSecondaryPort to optionally force ZT to use a single port --- service/OneService.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/service/OneService.cpp b/service/OneService.cpp index 63ee3373..40ffce2f 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -475,6 +475,7 @@ public: PhySocket *_localControlSocket6; bool _updateAutoApply; bool _allowTcpFallbackRelay; + bool _allowSecondaryPort; unsigned int _multipathMode; unsigned int _primaryPort; unsigned int _secondaryPort; @@ -722,16 +723,18 @@ public: // This exists because there are buggy NATs out there that fail if more // than one device behind the same NAT tries to use the same internal // private address port number. Buggy NATs are a running theme. - _ports[1] = (_secondaryPort == 0) ? 20000 + ((unsigned int)_node->address() % 45500) : _secondaryPort; - for(int i=0;;++i) { - if (i > 1000) { - _ports[1] = 0; - break; - } else if (++_ports[1] >= 65536) { - _ports[1] = 20000; + if (_allowSecondaryPort) { + _ports[1] = (_secondaryPort == 0) ? 20000 + ((unsigned int)_node->address() % 45500) : _secondaryPort; + for(int i=0;;++i) { + if (i > 1000) { + _ports[1] = 0; + break; + } else if (++_ports[1] >= 65536) { + _ports[1] = 20000; + } + if (_trialBind(_ports[1])) + break; } - if (_trialBind(_ports[1])) - break; } #ifdef ZT_USE_MINIUPNPC @@ -1603,6 +1606,7 @@ public: _primaryPort = (unsigned int)OSUtils::jsonInt(settings["primaryPort"],(uint64_t)_primaryPort) & 0xffff; _allowTcpFallbackRelay = OSUtils::jsonBool(settings["allowTcpFallbackRelay"],true); + _allowSecondaryPort = OSUtils::jsonBool(settings["allowSecondaryPort"],true); _secondaryPort = (unsigned int)OSUtils::jsonInt(settings["secondaryPort"],0); _tertiaryPort = (unsigned int)OSUtils::jsonInt(settings["tertiaryPort"],0); if (_secondaryPort != 0 || _tertiaryPort != 0) { From d3728d585983ba9092d79a1e06f3d5fa7c4ff699 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 10 Jul 2019 21:30:11 -0400 Subject: [PATCH 044/185] cleanup --- osdep/NetBSDEthernetTap.hpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osdep/NetBSDEthernetTap.hpp b/osdep/NetBSDEthernetTap.hpp index a80b776f..32b6dfa6 100644 --- a/osdep/NetBSDEthernetTap.hpp +++ b/osdep/NetBSDEthernetTap.hpp @@ -39,10 +39,6 @@ #include "../node/MAC.hpp" #include "Thread.hpp" - - - - namespace ZeroTier { class NetBSDEthernetTap From 692733fffbf97b561f7fa62349f14b2399335bf4 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Mon, 15 Jul 2019 13:00:16 -0700 Subject: [PATCH 045/185] Don't write to ztc_network_status table anymore in central controller --- controller/PostgreSQL.cpp | 123 -------------------------------------- 1 file changed, 123 deletions(-) diff --git a/controller/PostgreSQL.cpp b/controller/PostgreSQL.cpp index de6b4f46..4d3da958 100644 --- a/controller/PostgreSQL.cpp +++ b/controller/PostgreSQL.cpp @@ -1389,129 +1389,6 @@ void PostgreSQL::onlineNotificationThread() PQclear(res); } - const int64_t now = OSUtils::now(); - if ((now - lastUpdatedNetworkStatus) > 10000) { - lastUpdatedNetworkStatus = now; - - std::vector>> networks; - { - std::lock_guard l(_networks_l); - for (auto i = _networks.begin(); i != _networks.end(); ++i) { - networks.push_back(*i); - } - } - - std::stringstream networkUpdate; - networkUpdate << "INSERT INTO ztc_network_status (network_id, bridge_count, authorized_member_count, online_member_count, total_member_count, last_modified) VALUES "; - bool nwFirstRun = true; - bool networkAdded = false; - for (auto i = networks.begin(); i != networks.end(); ++i) { - char tmp[64]; - Utils::hex(i->first, tmp); - - std::string networkId(tmp); - - std::vector &_notUsed = updateMap[networkId]; - (void)_notUsed; - - uint64_t authMemberCount = 0; - uint64_t totalMemberCount = 0; - uint64_t onlineMemberCount = 0; - uint64_t bridgeCount = 0; - uint64_t ts = now; - { - std::lock_guard l2(i->second->lock); - authMemberCount = i->second->authorizedMembers.size(); - totalMemberCount = i->second->members.size(); - bridgeCount = i->second->activeBridgeMembers.size(); - for (auto m=i->second->members.begin(); m != i->second->members.end(); ++m) { - auto lo = lastOnlineCumulative.find(std::pair(i->first, m->first)); - if (lo != lastOnlineCumulative.end()) { - if ((now - lo->second) <= (ZT_NETWORK_AUTOCONF_DELAY * 2)) { - ++onlineMemberCount; - } else { - lastOnlineCumulative.erase(lo); - } - } - } - } - - const char *nvals[1] = { - networkId.c_str() - }; - - res = PQexecParams(conn, - "SELECT id FROM ztc_network WHERE id = $1", - 1, - NULL, - nvals, - NULL, - NULL, - 0); - - if (PQresultStatus(res) != PGRES_TUPLES_OK) { - fprintf(stderr, "Network lookup failed: %s", PQerrorMessage(conn)); - PQclear(res); - continue; - } - - int nrows = PQntuples(res); - PQclear(res); - - if (nrows == 1) { - std::string bc = std::to_string(bridgeCount); - std::string amc = std::to_string(authMemberCount); - std::string omc = std::to_string(onlineMemberCount); - std::string tmc = std::to_string(totalMemberCount); - std::string timestamp = std::to_string(ts); - - if (nwFirstRun) { - nwFirstRun = false; - } else { - networkUpdate << ", "; - } - - networkUpdate << "('" << networkId << "', " << bc << ", " << amc << ", " << omc << ", " << tmc << ", " - << "TO_TIMESTAMP(" << timestamp << "::double precision/1000))"; - - networkAdded = true; - - } else if (nrows > 1) { - fprintf(stderr, "Number of networks > 1?!?!?"); - continue; - } else { - continue; - } - } - networkUpdate << " ON CONFLICT (network_id) DO UPDATE SET bridge_count = EXCLUDED.bridge_count, " - << "authorized_member_count = EXCLUDED.authorized_member_count, online_member_count = EXCLUDED.online_member_count, " - << "total_member_count = EXCLUDED.total_member_count, last_modified = EXCLUDED.last_modified"; - if (networkAdded) { - res = PQexec(conn, networkUpdate.str().c_str()); - if (PQresultStatus(res) != PGRES_COMMAND_OK) { - fprintf(stderr, "Error during multiple network upsert: %s", PQresultErrorMessage(res)); - } - PQclear(res); - } - } - - // for (auto it = updateMap.begin(); it != updateMap.end(); ++it) { - // std::string networkId = it->first; - // std::vector members = it->second; - // std::stringstream queryBuilder; - - // std::string membersStr = ::join(members, ","); - - // queryBuilder << "NOTIFY controller, '" << networkId << ":" << membersStr << "'"; - // std::string query = queryBuilder.str(); - - // PGresult *res = PQexec(conn,query.c_str()); - // if (PQresultStatus(res) != PGRES_COMMAND_OK) { - // fprintf(stderr, "ERROR: Error sending NOTIFY: %s\n", PQresultErrorMessage(res)); - // } - // PQclear(res); - // } - std::this_thread::sleep_for(std::chrono::milliseconds(10)); } fprintf(stderr, "%s: Fell out of run loop in onlineNotificationThread\n", _myAddressStr.c_str()); From bdc2ec1f5e2074c067ce225352de3e0dd92b1356 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 15 Jul 2019 15:27:53 -0500 Subject: [PATCH 046/185] Track online status in FileDB --- controller/DB.hpp | 1 + controller/FileDB.cpp | 103 +++++++++++++++++++++++++++++++++--------- controller/FileDB.hpp | 5 ++ 3 files changed, 87 insertions(+), 22 deletions(-) diff --git a/controller/DB.hpp b/controller/DB.hpp index ec54a8eb..e59230e1 100644 --- a/controller/DB.hpp +++ b/controller/DB.hpp @@ -40,6 +40,7 @@ #include #include #include +#include #include "../ext/json/json.hpp" diff --git a/controller/FileDB.cpp b/controller/FileDB.cpp index 300455fa..917784ba 100644 --- a/controller/FileDB.cpp +++ b/controller/FileDB.cpp @@ -32,7 +32,9 @@ namespace ZeroTier FileDB::FileDB(EmbeddedNetworkController *const nc,const Identity &myId,const char *path) : DB(nc,myId,path), _networksPath(_path + ZT_PATH_SEPARATOR_S + "network"), - _tracePath(_path + ZT_PATH_SEPARATOR_S + "trace") + _tracePath(_path + ZT_PATH_SEPARATOR_S + "trace"), + _onlineChanged(false), + _running(true) { OSUtils::mkdir(_path.c_str()); OSUtils::lockDownFile(_path.c_str(),true); @@ -69,9 +71,64 @@ FileDB::FileDB(EmbeddedNetworkController *const nc,const Identity &myId,const ch } catch ( ... ) {} } } + + _onlineUpdateThread = std::thread([this]() { + unsigned int cnt = 0; + while (this->_running) { + usleep(250); + if ((++cnt % 20) == 0) { // 5 seconds + std::lock_guard l(this->_online_l); + if (!this->_running) return; + if (this->_onlineChanged) { + char p[4096],atmp[64]; + for(auto nw=this->_online.begin();nw!=this->_online.end();++nw) { + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx-online.json",_networksPath.c_str(),(unsigned long long)nw->first); + FILE *f = fopen(p,"wb"); + if (f) { + fprintf(f,"{"); + char *memberPrefix = ""; + for(auto m=nw->second.begin();m!=nw->second.end();++m) { + fprintf(f,"%s\"%.10llx\":{" ZT_EOL_S,memberPrefix,(unsigned long long)m->first); + memberPrefix = ","; + InetAddress lastAddr; + char *timestampPrefix = " "; + int cnt = 0; + for(auto ts=m->second.rbegin();ts!=m->second.rend();++ts) { + if (cnt < 25) { + if (lastAddr != ts->second) { + lastAddr = ts->second; + fprintf(f,"%s\"%lld\":\"%s\"" ZT_EOL_S,timestampPrefix,(long long)ts->first,ts->second.toString(atmp)); + timestampPrefix = ","; + ++cnt; + } else { + m->second.erase(ts.base()); // erase previous entries for same IP/port + } + } else { + m->second.erase(ts.base()); // erase entries beyond the 25 max written to log + } + } + fprintf(f,"}"); + } + fprintf(f,"}" ZT_EOL_S); + fclose(f); + } + } + this->_onlineChanged = false; + } + } + } + }); } -FileDB::~FileDB() {} +FileDB::~FileDB() +{ + try { + _online_l.lock(); + _running = false; + _online_l.unlock(); + _onlineUpdateThread.join(); + } catch ( ... ) {} +} bool FileDB::waitForReady() { return true; } bool FileDB::isReady() { return true; } @@ -94,14 +151,10 @@ void FileDB::save(nlohmann::json *orig,nlohmann::json &record) if (nwid) { nlohmann::json old; get(nwid,old); - if ((!old.is_object())||(old != record)) { - OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%.16llx.json.new",_networksPath.c_str(),nwid); - OSUtils::ztsnprintf(p2,sizeof(p2),"%s" ZT_PATH_SEPARATOR_S "%.16llx.json",_networksPath.c_str(),nwid); + OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%.16llx.json",_networksPath.c_str(),nwid); if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) fprintf(stderr,"WARNING: controller unable to write to path: %s" ZT_EOL_S,p1); - OSUtils::rename(p1,p2); - _networkChanged(old,record,true); } } @@ -111,10 +164,9 @@ void FileDB::save(nlohmann::json *orig,nlohmann::json &record) if ((id)&&(nwid)) { nlohmann::json network,old; get(nwid,network,id,old); - if ((!old.is_object())||(old != record)) { OSUtils::ztsnprintf(pb,sizeof(pb),"%s" ZT_PATH_SEPARATOR_S "%.16llx" ZT_PATH_SEPARATOR_S "member",_networksPath.c_str(),(unsigned long long)nwid); - OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%.10llx.json.new",pb,(unsigned long long)id); + OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%.10llx.json",pb,(unsigned long long)id); if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) { OSUtils::ztsnprintf(p2,sizeof(p2),"%s" ZT_PATH_SEPARATOR_S "%.16llx",_networksPath.c_str(),(unsigned long long)nwid); OSUtils::mkdir(p2); @@ -122,9 +174,6 @@ void FileDB::save(nlohmann::json *orig,nlohmann::json &record) if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) fprintf(stderr,"WARNING: controller unable to write to path: %s" ZT_EOL_S,p1); } - OSUtils::ztsnprintf(p2,sizeof(p2),"%s" ZT_PATH_SEPARATOR_S "%.10llx.json",pb,(unsigned long long)id); - OSUtils::rename(p1,p2); - _memberChanged(old,record,true); } } @@ -144,29 +193,39 @@ void FileDB::eraseNetwork(const uint64_t networkId) get(networkId,network); char p[16384]; OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx.json",_networksPath.c_str(),networkId); - - if (OSUtils::fileExists(p,false)){ - OSUtils::rm(p); - } + OSUtils::rm(p); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx-online.json",_networksPath.c_str(),networkId); + OSUtils::rm(p); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx" ZT_PATH_SEPARATOR_S "member",_networksPath.c_str(),(unsigned long long)networkId); + OSUtils::rmDashRf(p); _networkChanged(network,nullJson,true); + std::lock_guard l(this->_online_l); + this->_online.erase(networkId); + this->_onlineChanged = true; } void FileDB::eraseMember(const uint64_t networkId,const uint64_t memberId) { nlohmann::json network,member,nullJson; get(networkId,network); - get(memberId,member); - char p[16384]; + get(memberId,member); + char p[4096]; OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx" ZT_PATH_SEPARATOR_S "member" ZT_PATH_SEPARATOR_S "%.10llx.json",_networksPath.c_str(),networkId,memberId); - if (OSUtils::fileExists(p,false)){ - OSUtils::rm(p); - } + OSUtils::rm(p); _memberChanged(member,nullJson,true); + std::lock_guard l(this->_online_l); + this->_online[networkId].erase(memberId); + this->_onlineChanged = true; } void FileDB::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress) { - // Nothing to do here right now in the filesystem store mode since we can just get this from the peer list + char mid[32],atmp[64]; + OSUtils::ztsnprintf(mid,sizeof(mid),"%.10llx",(unsigned long long)memberId); + physicalAddress.toString(atmp); + std::lock_guard l(this->_online_l); + this->_online[networkId][memberId][OSUtils::now()] = physicalAddress; + this->_onlineChanged = true; } } // namespace ZeroTier diff --git a/controller/FileDB.hpp b/controller/FileDB.hpp index 89c4d814..0a8b9d2e 100644 --- a/controller/FileDB.hpp +++ b/controller/FileDB.hpp @@ -48,6 +48,11 @@ public: protected: std::string _networksPath; std::string _tracePath; + std::thread _onlineUpdateThread; + std::map< uint64_t,std::map > > _online; + std::mutex _online_l; + bool _onlineChanged; + bool _running; }; } // namespace ZeroTier From 90872c906fa0f415804873bb7388fea417e4252c Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 15 Jul 2019 16:30:34 -0500 Subject: [PATCH 047/185] Fix FileDB stuff and latency measurement. --- controller/FileDB.cpp | 11 ++++++----- node/IncomingPacket.cpp | 6 +++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/controller/FileDB.cpp b/controller/FileDB.cpp index 917784ba..64c305bb 100644 --- a/controller/FileDB.cpp +++ b/controller/FileDB.cpp @@ -86,25 +86,26 @@ FileDB::FileDB(EmbeddedNetworkController *const nc,const Identity &myId,const ch FILE *f = fopen(p,"wb"); if (f) { fprintf(f,"{"); - char *memberPrefix = ""; + const char *memberPrefix = ""; for(auto m=nw->second.begin();m!=nw->second.end();++m) { fprintf(f,"%s\"%.10llx\":{" ZT_EOL_S,memberPrefix,(unsigned long long)m->first); memberPrefix = ","; InetAddress lastAddr; - char *timestampPrefix = " "; + const char *timestampPrefix = " "; int cnt = 0; - for(auto ts=m->second.rbegin();ts!=m->second.rend();++ts) { + for(auto ts=m->second.rbegin();ts!=m->second.rend();) { if (cnt < 25) { if (lastAddr != ts->second) { lastAddr = ts->second; fprintf(f,"%s\"%lld\":\"%s\"" ZT_EOL_S,timestampPrefix,(long long)ts->first,ts->second.toString(atmp)); timestampPrefix = ","; ++cnt; + ++ts; } else { - m->second.erase(ts.base()); // erase previous entries for same IP/port + ts = std::map::reverse_iterator(m->second.erase(std::next(ts).base())); } } else { - m->second.erase(ts.base()); // erase entries beyond the 25 max written to log + ts = std::map::reverse_iterator(m->second.erase(std::next(ts).base())); } } fprintf(f,"}"); diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 7a1193c0..b774f1df 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -502,8 +502,8 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedP } } - if (!hops() && (RR->node->getMultipathMode() != ZT_MULTIPATH_NONE)) { - _path->updateLatency((unsigned int)latency, RR->node->now()); + if (!hops()) { + _path->updateLatency((unsigned int)latency,RR->node->now()); } peer->setRemoteVersion(vProto,vMajor,vMinor,vRevision); @@ -614,7 +614,7 @@ bool IncomingPacket::_doRENDEZVOUS(const RuntimeEnvironment *RR,void *tPtr,const const unsigned int port = at(ZT_PROTO_VERB_RENDEZVOUS_IDX_PORT); const unsigned int addrlen = (*this)[ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRLEN]; if ((port > 0)&&((addrlen == 4)||(addrlen == 16))) { - const InetAddress atAddr(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS,addrlen),addrlen,port); + InetAddress atAddr(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS,addrlen),addrlen,port); if (RR->node->shouldUsePathForZeroTierTraffic(tPtr,with,_path->localSocket(),atAddr)) { const uint64_t junk = RR->node->prng(); RR->node->putPacket(tPtr,_path->localSocket(),atAddr,&junk,4,2); // send low-TTL junk packet to 'open' local NAT(s) and stateful firewalls From 2ab2f687253f27e6c8736f8fbb2767cac0d52890 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Tue, 16 Jul 2019 12:15:38 -0700 Subject: [PATCH 048/185] Add a central database schema version check to central controller startup --- controller/PostgreSQL.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/controller/PostgreSQL.cpp b/controller/PostgreSQL.cpp index de6b4f46..594591bd 100644 --- a/controller/PostgreSQL.cpp +++ b/controller/PostgreSQL.cpp @@ -39,6 +39,8 @@ using json = nlohmann::json; namespace { +static const int DB_MINIMUM_VERSION = 5; + static const char *_timestr() { time_t t = time(0); @@ -86,6 +88,36 @@ PostgreSQL::PostgreSQL(EmbeddedNetworkController *const nc, const Identity &myId { _connString = std::string(path) + " application_name=controller_" +_myAddressStr; + // Database Schema Version Check + PGconn *conn = getPgConn(); + if (PQstatus(conn) != CONNECTION_OK) { + fprintf(stderr, "Bad Database Connection: %s", PQerrorMessage(conn)); + exit(1); + } + + PGresult *res = PQexec(conn, "SELECT version FROM ztc_database"); + if (PQresultStatus(res) != PGRES_TUPLES_OK) { + fprintf(stderr, "Error determining database version"); + exit(1); + } + + if (PQntuples(res) != 1) { + fprintf(stderr, "Invalid number of db version tuples returned."); + exit(1); + } + + int dbVersion = std::stoi(PQgetvalue(res, 0, 0)); + + if (dbVersion < DB_MINIMUM_VERSION) { + fprintf(stderr, "Central database schema version too low. This controller version requires a minimum schema version of %d. Please upgrade your Central instance", DB_MINIMUM_VERSION); + exit(1); + } + + PQclear(res); + res = NULL; + PQfinish(conn); + conn = NULL; + _readyLock.lock(); _heartbeatThread = std::thread(&PostgreSQL::heartbeat, this); _membersDbWatcher = std::thread(&PostgreSQL::membersDbWatcher, this); From 7afcc1702410557ba8dda2481455b54eac6091a7 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Tue, 16 Jul 2019 13:09:10 -0700 Subject: [PATCH 049/185] no usleep() on Windows --- controller/FileDB.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/FileDB.cpp b/controller/FileDB.cpp index 917784ba..69573306 100644 --- a/controller/FileDB.cpp +++ b/controller/FileDB.cpp @@ -75,7 +75,7 @@ FileDB::FileDB(EmbeddedNetworkController *const nc,const Identity &myId,const ch _onlineUpdateThread = std::thread([this]() { unsigned int cnt = 0; while (this->_running) { - usleep(250); + std::this_thread::sleep_for(std::chrono::microseconds(100)); if ((++cnt % 20) == 0) { // 5 seconds std::lock_guard l(this->_online_l); if (!this->_running) return; From d43e810ecbcb264e57d2b52138a3729b7667388a Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Tue, 16 Jul 2019 15:16:49 -0700 Subject: [PATCH 050/185] Finally figured out how to update the network interface names on Windows so that they'll be visible in `ipconfig`, `Get-NetAdapter` etc. --- osdep/WindowsEthernetTap.cpp | 57 ++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/osdep/WindowsEthernetTap.cpp b/osdep/WindowsEthernetTap.cpp index 65335dca..773c56c1 100644 --- a/osdep/WindowsEthernetTap.cpp +++ b/osdep/WindowsEthernetTap.cpp @@ -58,6 +58,8 @@ #include "..\windows\TapDriver6\tap-windows.h" +#include + // Create a fake unused default route to force detection of network type on networks without gateways #define ZT_WINDOWS_CREATE_FAKE_DEFAULT_ROUTE @@ -824,6 +826,61 @@ void WindowsEthernetTap::setFriendlyName(const char *dn) RegSetKeyValueA(ifp,"Connection","Name",REG_SZ,(LPCVOID)dn,(DWORD)(strlen(dn)+1)); RegCloseKey(ifp); } + + HRESULT hr = CoInitialize(nullptr); + if (hr != S_OK) return; + CoInitializeSecurity(NULL, -1, NULL, NULL, + RPC_C_AUTHN_LEVEL_PKT, + RPC_C_IMP_LEVEL_IMPERSONATE, + NULL, EOAC_NONE, NULL); + if (hr != S_OK) return; + + INetSharingManager *nsm; + hr = CoCreateInstance(__uuidof(NetSharingManager), NULL, CLSCTX_ALL, __uuidof(INetSharingManager), (void**)&nsm); + if (hr != S_OK) return; + + bool found = false; + INetSharingEveryConnectionCollection *nsecc = nullptr; + hr = nsm->get_EnumEveryConnection(&nsecc); + if (!nsecc) { + fprintf(stderr, "Failed to get NSM connections"); + return; + } + + IEnumVARIANT *ev = nullptr; + IUnknown *unk = nullptr; + hr = nsecc->get__NewEnum(&unk); + if (unk) { + hr = unk->QueryInterface(__uuidof(IEnumVARIANT), (void**)&ev); + unk->Release(); + } + if (ev) { + VARIANT v; + VariantInit(&v); + + while ((S_OK == ev->Next(1, &v, NULL)) && found == FALSE) { + if (V_VT(&v) == VT_UNKNOWN) { + INetConnection *nc = nullptr; + V_UNKNOWN(&v)->QueryInterface(__uuidof(INetConnection), (void**)&nc); + if (nc) { + NETCON_PROPERTIES *ncp = nullptr; + nc->GetProperties(&ncp); + + GUID curId = ncp->guidId; + if (curId == _deviceGuid) { + wchar_t wtext[255]; + mbstowcs(wtext, dn, strlen(dn)+1); + nc->Rename(wtext); + found = true; + } + nc->Release(); + } + } + VariantClear(&v); + } + ev->Release(); + } + nsecc->Release(); } void WindowsEthernetTap::scanMulticastGroups(std::vector &added,std::vector &removed) From 80124bb753c4a03d2918c8a7ee3e648dab69afd3 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Tue, 16 Jul 2019 15:34:26 -0700 Subject: [PATCH 051/185] Update release notes --- RELEASE-NOTES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 9e153ff6..67bd2e58 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -11,6 +11,7 @@ ZeroTier Release Notes * Fixed stack overflow issues on Linux versions using musl libc. * Fixed some alignment problems reported on ARM and ARM64, but some reports we could not reproduce so please report any issues with exact chip, OS/distro, and ZeroTier version in use. * Fixed numerous other small issues and bugs. + * Windows now sets the adapter name such that it is consistent in both the Windows UI and command line utilities. # 2018-07-27 -- Version 1.2.12 From daa88390057f2f84d4304a14d17c383f41708795 Mon Sep 17 00:00:00 2001 From: Michael Adams Date: Thu, 18 Jul 2019 17:48:41 -0700 Subject: [PATCH 052/185] Update Dockerfile Update Dockerfile to use Debian 10 + pull the main.sh directly from Github; works for Portainer use. --- .../linux/zerotier-containerized/Dockerfile | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/ext/installfiles/linux/zerotier-containerized/Dockerfile b/ext/installfiles/linux/zerotier-containerized/Dockerfile index e0ba5ca6..fd18eebb 100644 --- a/ext/installfiles/linux/zerotier-containerized/Dockerfile +++ b/ext/installfiles/linux/zerotier-containerized/Dockerfile @@ -1,30 +1,32 @@ -FROM debian:stretch as builder +## NOTE: to retain configuration; mount a Docker volume, or use a bind-mount, on /var/lib/zerotier-one + +FROM debian:buster-slim as builder ## Supports x86_64, x86, arm, and arm64 RUN apt-get update && apt-get install -y curl gnupg RUN apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys 0x1657198823e52a61 && \ - echo "deb http://download.zerotier.com/debian/stretch stretch main" > /etc/apt/sources.list.d/zerotier.list + echo "deb http://download.zerotier.com/debian/buster buster main" > /etc/apt/sources.list.d/zerotier.list RUN apt-get update && apt-get install -y zerotier-one=1.2.12 +RUN curl https://raw.githubusercontent.com/zerotier/ZeroTierOne/master/ext/installfiles/linux/zerotier-containerized/main.sh > /var/lib/zerotier-one/main.sh FROM alpine:latest -MAINTAINER Adam Ierymenko - LABEL version="1.2.12" LABEL description="Containerized ZeroTier One for use on CoreOS or other Docker-only Linux hosts." # Uncomment to build in container -#RUN apk add --update alpine-sdk linux-headers - +# RUN apk add --update alpine-sdk linux-headers RUN apk add --update libgcc libstdc++ -RUN mkdir -p /var/lib/zerotier-one +# ZeroTier relies on UDP port 9993 +EXPOSE 9993/udp -COPY --from=builder /var/lib/zerotier-one/zerotier-cli /usr/sbin/zerotier-cli -COPY --from=builder /var/lib/zerotier-one/zerotier-idtool /usr/sbin/zerotier-idtool +RUN mkdir -p /var/lib/zerotier-one +COPY --from=builder /usr/sbin/zerotier-cli /usr/sbin/zerotier-cli +COPY --from=builder /usr/sbin/zerotier-idtool /usr/sbin/zerotier-idtool COPY --from=builder /usr/sbin/zerotier-one /usr/sbin/zerotier-one +COPY --from=builder /var/lib/zerotier-one/main.sh /main.sh -ADD main.sh / RUN chmod 0755 /main.sh ENTRYPOINT ["/main.sh"] -CMD ["zerotier-one"] \ No newline at end of file +CMD ["zerotier-one"] From 1b2d9e202e055b911e89bc43c4b2b2d7274324f8 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 19 Jul 2019 13:33:14 -0700 Subject: [PATCH 053/185] Remove 44/8 as pseudoprivate since it is now partly global. --- node/InetAddress.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp index 9207613e..15d2f878 100644 --- a/node/InetAddress.cpp +++ b/node/InetAddress.cpp @@ -57,7 +57,6 @@ InetAddress::IpScope InetAddress::ipScope() const case 0x1c: return IP_SCOPE_PSEUDOPRIVATE; // 28.0.0.0/8 (US DSI-North) case 0x1d: return IP_SCOPE_PSEUDOPRIVATE; // 29.0.0.0/8 (US DISA) case 0x1e: return IP_SCOPE_PSEUDOPRIVATE; // 30.0.0.0/8 (US DISA) - case 0x2c: return IP_SCOPE_PSEUDOPRIVATE; // 44.0.0.0/8 (Amateur Radio) case 0x33: return IP_SCOPE_PSEUDOPRIVATE; // 51.0.0.0/8 (UK Department of Social Security) case 0x37: return IP_SCOPE_PSEUDOPRIVATE; // 55.0.0.0/8 (US DoD) case 0x38: return IP_SCOPE_PSEUDOPRIVATE; // 56.0.0.0/8 (US Postal Service) From a0f47b12b43c99100c8db87f5a127221d513784b Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Fri, 19 Jul 2019 16:34:31 -0700 Subject: [PATCH 054/185] Removed Synology-specific home path, changes made elsewhere in SPK --- osdep/OSUtils.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osdep/OSUtils.cpp b/osdep/OSUtils.cpp index 2834fd22..83c615de 100644 --- a/osdep/OSUtils.cpp +++ b/osdep/OSUtils.cpp @@ -399,10 +399,6 @@ std::string OSUtils::platformDefaultHomePath() return homeDir; #endif -#ifdef __SYNOLOGY__ - return std::string("/var/packages/zerotier/target/var"); -#endif - // Check for user-defined environment variable before using defaults #ifdef __WINDOWS__ DWORD bufferSize = 65535; From eb2f851e6557812a4549788bf9ce03256dcef67b Mon Sep 17 00:00:00 2001 From: Ellen Wang Date: Sun, 21 Jul 2019 21:37:01 -0700 Subject: [PATCH 055/185] Don't relink zerotier-one every time. Because zerotier-one depends on "one", which is a phony target, making it relinks zerotier-one every time, which is probably not the desired behavior. In any case, zerotier-one, zerotier-cli, and zerotier-idtool are real target, so they should have real dependencies and actions. The "one" target now depends on these three files. Behavior is mostly unchanged otherwise. --- make-linux.mk | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/make-linux.mk b/make-linux.mk index 24e054dc..a9414d0c 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -257,19 +257,21 @@ ifeq ($(ZT_USE_ARM32_NEON_ASM_CRYPTO),1) override CORE_OBJS+=ext/arm32-neon-salsa2012-asm/salsa2012.o endif +.PHONY: all all: one -one: $(CORE_OBJS) $(ONE_OBJS) one.o +.PHONY: one +one: zerotier-one zerotier-idtool zerotier-cli + +zerotier-one: $(CORE_OBJS) $(ONE_OBJS) one.o $(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-one $(CORE_OBJS) $(ONE_OBJS) one.o $(LDLIBS) $(STRIP) zerotier-one - ln -sf zerotier-one zerotier-idtool - ln -sf zerotier-one zerotier-cli -zerotier-one: one - -zerotier-idtool: one +zerotier-idtool: zerotier-one + ln -sf zerotier-one zerotier-idtool -zerotier-cli: one +zerotier-cli: zerotier-one + ln -sf zerotier-one zerotier-cli libzerotiercore.a: FORCE make CFLAGS="-O3 -fstack-protector -fPIC" CXXFLAGS="-O3 -std=c++11 -fstack-protector -fPIC" $(CORE_OBJS) From 5edd04638d0bea58a619969cbb19bac2abb3f98e Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 22 Jul 2019 13:43:06 -0700 Subject: [PATCH 056/185] LFDB work in progress --- controller/EmbeddedNetworkController.cpp | 46 +- controller/EmbeddedNetworkController.hpp | 4 - controller/LFDB.cpp | 360 +++ controller/LFDB.hpp | 97 + ext/cpp-httplib/LICENSE | 22 + ext/cpp-httplib/README.md | 259 ++ ext/cpp-httplib/httplib.h | 2779 ++++++++++++++++++++++ 7 files changed, 3561 insertions(+), 6 deletions(-) create mode 100644 controller/LFDB.cpp create mode 100644 controller/LFDB.hpp create mode 100644 ext/cpp-httplib/LICENSE create mode 100644 ext/cpp-httplib/README.md create mode 100644 ext/cpp-httplib/httplib.h diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index 99c664f0..007a4112 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -46,6 +46,11 @@ #include "../version.h" #include "EmbeddedNetworkController.hpp" +#include "LFDB.hpp" +#include "FileDB.hpp" +#ifdef ZT_CONTROLLER_USE_LIBPQ +#include "PostgreSQL.hpp" +#endif #include "../node/Node.hpp" #include "../node/CertificateOfMembership.hpp" @@ -488,12 +493,49 @@ void EmbeddedNetworkController::init(const Identity &signingId,Sender *sender) _signingId = signingId; _sender = sender; _signingIdAddressString = signingId.address().toString(tmp); + #ifdef ZT_CONTROLLER_USE_LIBPQ - if ((_path.length() > 9)&&(_path.substr(0,9) == "postgres:")) + if ((_path.length() > 9)&&(_path.substr(0,9) == "postgres:")) { _db.reset(new PostgreSQL(this,_signingId,_path.substr(9).c_str(), _listenPort, _mqc)); - else // else use FileDB after endif + } else { #endif + + std::string lfJSON; + OSUtils::readFile((_path + ZT_PATH_SEPARATOR_S "local.conf").c_str(),lfJSON); + if (lfJSON.length() > 0) { + nlohmann::json lfConfig(OSUtils::jsonParse(lfJSON)); + nlohmann::json &settings = lfConfig["settings"]; + if (settings.is_object()) { + nlohmann::json &controllerDb = lfConfig["controllerDb"]; + if (controllerDb.is_object()) { + std::string type = controllerDb["type"]; + if (type == "lf") { + std::string lfOwner = controllerDb["owner"]; + std::string lfHost = controllerDb["host"]; + int lfPort = controllerDb["port"]; + bool storeOnlineState = controllerDb["storeOnlineState"]; + if ((lfOwner.length())&&(lfHost.length())&&(lfPort > 0)&&(lfPort < 65536)) { + std::size_t pubHdrLoc = lfOwner.find("Public: "); + if ((pubHdrLoc > 0)&&((pubHdrLoc + 8) < lfOwner.length())) { + std::string lfOwnerPublic = lfOwner.substr(pubHdrLoc + 8); + std::size_t pubHdrEnd = lfOwnerPublic.find_first_of("\n\r\t "); + if (pubHdrEnd != std::string::npos) { + lfOwnerPublic = lfOwnerPublic.substr(0,pubHdrEnd); + _db.reset(new LFDB(this,_signingId,_path.c_str(),lfOwner.c_str(),lfOwnerPublic.c_str(),lfHost.c_str(),lfPort,storeOnlineState)); + } + } + } + } + } + } + } + if (!_db) _db.reset(new FileDB(this,_signingId,_path.c_str())); + +#ifdef ZT_CONTROLLER_USE_LIBPQ + } +#endif + _db->waitForReady(); } diff --git a/controller/EmbeddedNetworkController.hpp b/controller/EmbeddedNetworkController.hpp index 269442a8..6ce0b5cf 100644 --- a/controller/EmbeddedNetworkController.hpp +++ b/controller/EmbeddedNetworkController.hpp @@ -51,10 +51,6 @@ #include "../ext/json/json.hpp" #include "DB.hpp" -#include "FileDB.hpp" -#ifdef ZT_CONTROLLER_USE_LIBPQ -#include "PostgreSQL.hpp" -#endif namespace ZeroTier { diff --git a/controller/LFDB.cpp b/controller/LFDB.cpp new file mode 100644 index 00000000..82858b50 --- /dev/null +++ b/controller/LFDB.cpp @@ -0,0 +1,360 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + +#include "LFDB.hpp" + +#include +#include +#include + +#include "../osdep/OSUtils.hpp" +#include "../ext/cpp-httplib/httplib.h" + +namespace ZeroTier +{ + +LFDB::LFDB(EmbeddedNetworkController *const nc,const Identity &myId,const char *path,const char *lfOwnerPrivate,const char *lfOwnerPublic,const char *lfNodeHost,int lfNodePort,bool storeOnlineState) : + DB(nc,myId,path), + _nc(nc), + _myId(myId), + _lfOwnerPrivate(lfOwnerPrivate), + _lfOwnerPublic(lfOwnerPublic), + _lfNodeHost(lfNodeHost), + _lfNodePort(lfNodePort), + _running(true), + _ready(false), + _storeOnlineState(storeOnlineState) +{ + _syncThread = std::thread([this]() { + char controllerAddress[24]; + _myId.address().toString(controllerAddress); + + httplib::Client htcli(_lfNodeHost.c_str(),_lfNodePort,600); + while (_running) { + std::ostringstream query; + query + << '{' + << "\"Ranges\":[{" + << "\"Name\": \"com.zerotier.controller.lfdb:" << controllerAddress << "\"" + << "}]," + << "\"MaskingKey\":\"" << controllerAddress << "\"," + << "\"Owners\":[\"" << _lfOwnerPublic << "\"]," + << "\"Open\":true" + << '}'; + auto resp = htcli.Post("/query",query.str(),"application/json"); + if (resp->status == 200) { + fprintf(stderr,"%d %s\n",resp->status,resp->body.c_str()); + } else { + fprintf(stderr,"ERROR: LFDB: %d from node: %s" ZT_EOL_S,resp->status,resp->body.c_str()); + } + + _ready = true; + + for(int k=0;k<10;++k) { + if (!_running) + return; + usleep(100000); + } + } + }); +} + +LFDB::~LFDB() +{ + _running = false; + _syncThread.join(); +} + +bool LFDB::waitForReady() +{ + while (!_ready) + usleep(10000); +} + +bool LFDB::isReady() +{ + return (_ready); +} + +void LFDB::save(nlohmann::json *orig,nlohmann::json &record) +{ + if (orig) { + if (*orig != record) { + record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1; + } + } else { + record["revision"] = 1; + } + + const std::string objtype = record["objtype"]; + if (objtype == "network") { + const uint64_t nwid = OSUtils::jsonIntHex(record["id"],0ULL); + if (nwid) { + nlohmann::json old; + get(nwid,old); + if ((!old.is_object())||(old != record)) { + } + } + } else if (objtype == "member") { + const uint64_t nwid = OSUtils::jsonIntHex(record["nwid"],0ULL); + const uint64_t id = OSUtils::jsonIntHex(record["id"],0ULL); + if ((id)&&(nwid)) { + nlohmann::json network,old; + get(nwid,network,id,old); + if ((!old.is_object())||(old != record)) { + } + } + } +} + +void LFDB::eraseNetwork(const uint64_t networkId) +{ + // TODO +} + +void LFDB::eraseMember(const uint64_t networkId,const uint64_t memberId) +{ + // TODO +} + +void LFDB::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress) +{ + std::lock_guard l(_state_l); + auto nw = _state.find(networkId); + if (nw != _state.end()) { + auto m = nw->second.members.find(memberId); + if (m != nw->second.members.end()) { + m->second.lastOnlineTime = OSUtils::now(); + if (physicalAddress) + m->second.lastOnlineAddress = physicalAddress; + m->second.lastOnlineDirty = true; + } + } +} + +#if 0 +FileDB::FileDB(EmbeddedNetworkController *const nc,const Identity &myId,const char *path) : + DB(nc,myId,path), + _networksPath(_path + ZT_PATH_SEPARATOR_S + "network"), + _tracePath(_path + ZT_PATH_SEPARATOR_S + "trace"), + _onlineChanged(false), + _running(true) +{ + OSUtils::mkdir(_path.c_str()); + OSUtils::lockDownFile(_path.c_str(),true); + OSUtils::mkdir(_networksPath.c_str()); + OSUtils::mkdir(_tracePath.c_str()); + + std::vector networks(OSUtils::listDirectory(_networksPath.c_str(),false)); + std::string buf; + for(auto n=networks.begin();n!=networks.end();++n) { + buf.clear(); + if ((n->length() == 21)&&(OSUtils::readFile((_networksPath + ZT_PATH_SEPARATOR_S + *n).c_str(),buf))) { + try { + nlohmann::json network(OSUtils::jsonParse(buf)); + const std::string nwids = network["id"]; + if (nwids.length() == 16) { + nlohmann::json nullJson; + _networkChanged(nullJson,network,false); + std::string membersPath(_networksPath + ZT_PATH_SEPARATOR_S + nwids + ZT_PATH_SEPARATOR_S "member"); + std::vector members(OSUtils::listDirectory(membersPath.c_str(),false)); + for(auto m=members.begin();m!=members.end();++m) { + buf.clear(); + if ((m->length() == 15)&&(OSUtils::readFile((membersPath + ZT_PATH_SEPARATOR_S + *m).c_str(),buf))) { + try { + nlohmann::json member(OSUtils::jsonParse(buf)); + const std::string addrs = member["id"]; + if (addrs.length() == 10) { + nlohmann::json nullJson2; + _memberChanged(nullJson2,member,false); + } + } catch ( ... ) {} + } + } + } + } catch ( ... ) {} + } + } + + _onlineUpdateThread = std::thread([this]() { + unsigned int cnt = 0; + while (this->_running) { + std::this_thread::sleep_for(std::chrono::microseconds(100)); + if ((++cnt % 20) == 0) { // 5 seconds + std::lock_guard l(this->_online_l); + if (!this->_running) return; + if (this->_onlineChanged) { + char p[4096],atmp[64]; + for(auto nw=this->_online.begin();nw!=this->_online.end();++nw) { + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx-online.json",_networksPath.c_str(),(unsigned long long)nw->first); + FILE *f = fopen(p,"wb"); + if (f) { + fprintf(f,"{"); + const char *memberPrefix = ""; + for(auto m=nw->second.begin();m!=nw->second.end();++m) { + fprintf(f,"%s\"%.10llx\":{" ZT_EOL_S,memberPrefix,(unsigned long long)m->first); + memberPrefix = ","; + InetAddress lastAddr; + const char *timestampPrefix = " "; + int cnt = 0; + for(auto ts=m->second.rbegin();ts!=m->second.rend();) { + if (cnt < 25) { + if (lastAddr != ts->second) { + lastAddr = ts->second; + fprintf(f,"%s\"%lld\":\"%s\"" ZT_EOL_S,timestampPrefix,(long long)ts->first,ts->second.toString(atmp)); + timestampPrefix = ","; + ++cnt; + ++ts; + } else { + ts = std::map::reverse_iterator(m->second.erase(std::next(ts).base())); + } + } else { + ts = std::map::reverse_iterator(m->second.erase(std::next(ts).base())); + } + } + fprintf(f,"}"); + } + fprintf(f,"}" ZT_EOL_S); + fclose(f); + } + } + this->_onlineChanged = false; + } + } + } + }); +} + +FileDB::~FileDB() +{ + try { + _online_l.lock(); + _running = false; + _online_l.unlock(); + _onlineUpdateThread.join(); + } catch ( ... ) {} +} + +bool FileDB::waitForReady() { return true; } +bool FileDB::isReady() { return true; } + +void FileDB::save(nlohmann::json *orig,nlohmann::json &record) +{ + char p1[4096],p2[4096],pb[4096]; + try { + if (orig) { + if (*orig != record) { + record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1; + } + } else { + record["revision"] = 1; + } + + const std::string objtype = record["objtype"]; + if (objtype == "network") { + const uint64_t nwid = OSUtils::jsonIntHex(record["id"],0ULL); + if (nwid) { + nlohmann::json old; + get(nwid,old); + if ((!old.is_object())||(old != record)) { + OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%.16llx.json",_networksPath.c_str(),nwid); + if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) + fprintf(stderr,"WARNING: controller unable to write to path: %s" ZT_EOL_S,p1); + _networkChanged(old,record,true); + } + } + } else if (objtype == "member") { + const uint64_t id = OSUtils::jsonIntHex(record["id"],0ULL); + const uint64_t nwid = OSUtils::jsonIntHex(record["nwid"],0ULL); + if ((id)&&(nwid)) { + nlohmann::json network,old; + get(nwid,network,id,old); + if ((!old.is_object())||(old != record)) { + OSUtils::ztsnprintf(pb,sizeof(pb),"%s" ZT_PATH_SEPARATOR_S "%.16llx" ZT_PATH_SEPARATOR_S "member",_networksPath.c_str(),(unsigned long long)nwid); + OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%.10llx.json",pb,(unsigned long long)id); + if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) { + OSUtils::ztsnprintf(p2,sizeof(p2),"%s" ZT_PATH_SEPARATOR_S "%.16llx",_networksPath.c_str(),(unsigned long long)nwid); + OSUtils::mkdir(p2); + OSUtils::mkdir(pb); + if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) + fprintf(stderr,"WARNING: controller unable to write to path: %s" ZT_EOL_S,p1); + } + _memberChanged(old,record,true); + } + } + } else if (objtype == "trace") { + const std::string id = record["id"]; + if (id.length() > 0) { + OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%s.json",_tracePath.c_str(),id.c_str()); + OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1)); + } + } + } catch ( ... ) {} // drop invalid records missing fields +} + +void FileDB::eraseNetwork(const uint64_t networkId) +{ + nlohmann::json network,nullJson; + get(networkId,network); + char p[16384]; + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx.json",_networksPath.c_str(),networkId); + OSUtils::rm(p); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx-online.json",_networksPath.c_str(),networkId); + OSUtils::rm(p); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx" ZT_PATH_SEPARATOR_S "member",_networksPath.c_str(),(unsigned long long)networkId); + OSUtils::rmDashRf(p); + _networkChanged(network,nullJson,true); + std::lock_guard l(this->_online_l); + this->_online.erase(networkId); + this->_onlineChanged = true; +} + +void FileDB::eraseMember(const uint64_t networkId,const uint64_t memberId) +{ + nlohmann::json network,member,nullJson; + get(networkId,network); + get(memberId,member); + char p[4096]; + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx" ZT_PATH_SEPARATOR_S "member" ZT_PATH_SEPARATOR_S "%.10llx.json",_networksPath.c_str(),networkId,memberId); + OSUtils::rm(p); + _memberChanged(member,nullJson,true); + std::lock_guard l(this->_online_l); + this->_online[networkId].erase(memberId); + this->_onlineChanged = true; +} + +void FileDB::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress) +{ + char mid[32],atmp[64]; + OSUtils::ztsnprintf(mid,sizeof(mid),"%.10llx",(unsigned long long)memberId); + physicalAddress.toString(atmp); + std::lock_guard l(this->_online_l); + this->_online[networkId][memberId][OSUtils::now()] = physicalAddress; + this->_onlineChanged = true; +} +#endif + +} // namespace ZeroTier diff --git a/controller/LFDB.hpp b/controller/LFDB.hpp new file mode 100644 index 00000000..a01e78e6 --- /dev/null +++ b/controller/LFDB.hpp @@ -0,0 +1,97 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + +#ifndef ZT_CONTROLLER_LFDB_HPP +#define ZT_CONTROLLER_LFDB_HPP + +#include "DB.hpp" + +#include +#include +#include +#include + +namespace ZeroTier { + +/** + * DB implementation for controller that stores data in LF + */ +class LFDB : public DB +{ +public: + /** + * @param nc Network controller + * @param myId Identity of controller node (with secret) + * @param path Base path for ZeroTier node itself + * @param lfOwnerPrivate LF owner private in PEM format + * @param lfOwnerPublic LF owner public in @base62 format + * @param lfNodeHost LF node host + * @param lfNodePort LF node http (not https) port + * @param storeOnlineState If true, store online/offline state and IP info in LF (a lot of data, only for private networks!) + */ + LFDB(EmbeddedNetworkController *const nc,const Identity &myId,const char *path,const char *lfOwnerPrivate,const char *lfOwnerPublic,const char *lfNodeHost,int lfNodePort,bool storeOnlineState); + virtual ~LFDB(); + + virtual bool waitForReady(); + virtual bool isReady(); + virtual void save(nlohmann::json *orig,nlohmann::json &record); + virtual void eraseNetwork(const uint64_t networkId); + virtual void eraseMember(const uint64_t networkId,const uint64_t memberId); + virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress); + +protected: + EmbeddedNetworkController *const _nc; + const Identity _myId; + + std::string _lfOwnerPrivate; + std::string _lfOwnerPublic; + std::string _lfNodeHost; + int _lfNodePort; + + struct _MemberState + { + InetAddress lastOnlineAddress; + int64_t lastOnlineTime; + bool dirty; + bool lastOnlineDirty; + }; + struct _NetworkState + { + std::unordered_map members; + bool dirty; + }; + std::unordered_map _state; + std::mutex _state_l; + + std::atomic_bool _running; + std::atomic_bool _ready; + std::thread _syncThread; + bool _storeOnlineState; +}; + +} // namespace ZeroTier + +#endif diff --git a/ext/cpp-httplib/LICENSE b/ext/cpp-httplib/LICENSE new file mode 100644 index 00000000..3e5ed359 --- /dev/null +++ b/ext/cpp-httplib/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2017 yhirose + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/ext/cpp-httplib/README.md b/ext/cpp-httplib/README.md new file mode 100644 index 00000000..2bd23454 --- /dev/null +++ b/ext/cpp-httplib/README.md @@ -0,0 +1,259 @@ +cpp-httplib +=========== + +[![Build Status](https://travis-ci.org/yhirose/cpp-httplib.svg?branch=master)](https://travis-ci.org/yhirose/cpp-httplib) +[![Bulid Status](https://ci.appveyor.com/api/projects/status/github/yhirose/cpp-httplib?branch=master&svg=true)](https://ci.appveyor.com/project/yhirose/cpp-httplib) + +A C++ header-only cross platform HTTP/HTTPS library. + +It's extremely easy to setup. Just include **httplib.h** file in your code! + +Inspired by [Sinatra](http://www.sinatrarb.com/) and [express](https://github.com/visionmedia/express). + +Server Example +-------------- + +```c++ +#include + +int main(void) +{ + using namespace httplib; + + Server svr; + + svr.Get("/hi", [](const Request& req, Response& res) { + res.set_content("Hello World!", "text/plain"); + }); + + svr.Get(R"(/numbers/(\d+))", [&](const Request& req, Response& res) { + auto numbers = req.matches[1]; + res.set_content(numbers, "text/plain"); + }); + + svr.listen("localhost", 1234); +} +``` + +`Post`, `Put`, `Delete` and `Options` methods are also supported. + +### Bind a socket to multiple interfaces and any available port + +```cpp +int port = svr.bind_to_any_port("0.0.0.0"); +svr.listen_after_bind(); +``` + +### Method Chain + +```cpp +svr.Get("/get", [](const auto& req, auto& res) { + res.set_content("get", "text/plain"); + }) + .Post("/post", [](const auto& req, auto& res) { + res.set_content(req.body(), "text/plain"); + }) + .listen("localhost", 1234); +``` + +### Static File Server + +```cpp +svr.set_base_dir("./www"); +``` + +### Logging + +```cpp +svr.set_logger([](const auto& req, const auto& res) { + your_logger(req, res); +}); +``` + +### Error Handler + +```cpp +svr.set_error_handler([](const auto& req, auto& res) { + const char* fmt = "

Error Status: %d

"; + char buf[BUFSIZ]; + snprintf(buf, sizeof(buf), fmt, res.status); + res.set_content(buf, "text/html"); +}); +``` + +### 'multipart/form-data' POST data + +```cpp +svr.Post("/multipart", [&](const auto& req, auto& res) { + auto size = req.files.size(); + auto ret = req.has_file("name1")); + const auto& file = req.get_file_value("name1"); + // file.filename; + // file.content_type; + auto body = req.body.substr(file.offset, file.length)); +}) +``` + +Client Example +-------------- + +### GET + +```c++ +#include +#include + +int main(void) +{ + httplib::Client cli("localhost", 1234); + + auto res = cli.Get("/hi"); + if (res && res->status == 200) { + std::cout << res->body << std::endl; + } +} +``` + +### GET with Content Receiver + +```c++ + std::string body; + auto res = cli.Get("/large-data", [&](const char *data, size_t len) { + body.append(data, len); + }); + assert(res->body.empty()); +``` + +### POST + +```c++ +res = cli.Post("/post", "text", "text/plain"); +res = cli.Post("/person", "name=john1¬e=coder", "application/x-www-form-urlencoded"); +``` + +### POST with parameters + +```c++ +httplib::Params params; +params.emplace("name", "john"); +params.emplace("note", "coder"); + +auto res = cli.Post("/post", params); +``` + or + +```c++ +httplib::Params params{ + { "name", "john" }, + { "note", "coder" } +}; + +auto res = cli.Post("/post", params); +``` + +### PUT + +```c++ +res = cli.Put("/resource/foo", "text", "text/plain"); +``` + +### DELETE + +```c++ +res = cli.Delete("/resource/foo"); +``` + +### OPTIONS + +```c++ +res = cli.Options("*"); +res = cli.Options("/resource/foo"); +``` + +### Connection Timeout + +```c++ +httplib::Client cli("localhost", 8080, 5); // timeouts in 5 seconds +``` +### With Progress Callback + +```cpp +httplib::Client client(url, port); + +// prints: 0 / 000 bytes => 50% complete +std::shared_ptr res = + cli.Get("/", [](uint64_t len, uint64_t total) { + printf("%lld / %lld bytes => %d%% complete\n", + len, total, + (int)((len/total)*100)); + return true; // return 'false' if you want to cancel the request. + } +); +``` + +![progress](https://user-images.githubusercontent.com/236374/33138910-495c4ecc-cf86-11e7-8693-2fc6d09615c4.gif) + +This feature was contributed by [underscorediscovery](https://github.com/yhirose/cpp-httplib/pull/23). + +### Basic Authentication + +```cpp +httplib::Client cli("httplib.org"); + +auto res = cli.Get("/basic-auth/hello/world", { + httplib::make_basic_authentication_header("hello", "world") +}); +// res->status should be 200 +// res->body should be "{\n \"authenticated\": true, \n \"user\": \"hello\"\n}\n". +``` + +### Range + +```cpp +httplib::Client cli("httpbin.org"); + +auto res = cli.Get("/range/32", { + httplib::make_range_header(1, 10) // 'Range: bytes=1-10' +}); +// res->status should be 206. +// res->body should be "bcdefghijk". +``` + +OpenSSL Support +--------------- + +SSL support is available with `CPPHTTPLIB_OPENSSL_SUPPORT`. `libssl` and `libcrypto` should be linked. + +```c++ +#define CPPHTTPLIB_OPENSSL_SUPPORT + +SSLServer svr("./cert.pem", "./key.pem"); + +SSLClient cli("localhost", 8080); +cli.set_ca_cert_path("./ca-bundle.crt"); +cli.enable_server_certificate_verification(true); +``` + +Zlib Support +------------ + +'gzip' compression is available with `CPPHTTPLIB_ZLIB_SUPPORT`. + +The server applies gzip compression to the following MIME type contents: + + * all text types + * image/svg+xml + * application/javascript + * application/json + * application/xml + * application/xhtml+xml + +NOTE +---- + +g++ 4.8 cannot build this library since `` in g++4.8 is [broken](https://stackoverflow.com/questions/12530406/is-gcc-4-8-or-earlier-buggy-about-regular-expressions). + +License +------- + +MIT license (© 2019 Yuji Hirose) diff --git a/ext/cpp-httplib/httplib.h b/ext/cpp-httplib/httplib.h new file mode 100644 index 00000000..5adfc2af --- /dev/null +++ b/ext/cpp-httplib/httplib.h @@ -0,0 +1,2779 @@ +// +// httplib.h +// +// Copyright (c) 2019 Yuji Hirose. All rights reserved. +// MIT License +// + +#ifndef CPPHTTPLIB_HTTPLIB_H +#define CPPHTTPLIB_HTTPLIB_H + +#ifdef _WIN32 +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS +#endif //_CRT_SECURE_NO_WARNINGS + +#ifndef _CRT_NONSTDC_NO_DEPRECATE +#define _CRT_NONSTDC_NO_DEPRECATE +#endif //_CRT_NONSTDC_NO_DEPRECATE + +#if defined(_MSC_VER) && _MSC_VER < 1900 +#define snprintf _snprintf_s +#endif // _MSC_VER + +#ifndef S_ISREG +#define S_ISREG(m) (((m)&S_IFREG) == S_IFREG) +#endif // S_ISREG + +#ifndef S_ISDIR +#define S_ISDIR(m) (((m)&S_IFDIR) == S_IFDIR) +#endif // S_ISDIR + +#ifndef NOMINMAX +#define NOMINMAX +#endif // NOMINMAX + +#include +#include +#include + +#pragma comment(lib, "ws2_32.lib") + +#ifndef strcasecmp +#define strcasecmp _stricmp +#endif // strcasecmp + +typedef SOCKET socket_t; +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef int socket_t; +#define INVALID_SOCKET (-1) +#endif //_WIN32 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CPPHTTPLIB_OPENSSL_SUPPORT +#include +#include +#include + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +inline const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *asn1) { + return M_ASN1_STRING_data(asn1); +} +#endif +#endif + +#ifdef CPPHTTPLIB_ZLIB_SUPPORT +#include +#endif + +/* + * Configuration + */ +#define CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND 5 +#define CPPHTTPLIB_KEEPALIVE_TIMEOUT_USECOND 0 +#define CPPHTTPLIB_KEEPALIVE_MAX_COUNT 5 +#define CPPHTTPLIB_READ_TIMEOUT_SECOND 5 +#define CPPHTTPLIB_READ_TIMEOUT_USECOND 0 +#define CPPHTTPLIB_REQUEST_URI_MAX_LENGTH 8192 +#define CPPHTTPLIB_PAYLOAD_MAX_LENGTH (std::numeric_limits::max)() +#define CPPHTTPLIB_RECV_BUFSIZ size_t(4096u) + +namespace httplib { + +namespace detail { + +struct ci { + bool operator()(const std::string &s1, const std::string &s2) const { + return std::lexicographical_compare( + s1.begin(), s1.end(), s2.begin(), s2.end(), + [](char c1, char c2) { return ::tolower(c1) < ::tolower(c2); }); + } +}; + +} // namespace detail + +enum class HttpVersion { v1_0 = 0, v1_1 }; + +typedef std::multimap Headers; + +template +std::pair make_range_header(uint64_t value, + Args... args); + +typedef std::multimap Params; +typedef std::smatch Match; + +typedef std::function ContentProducer; +typedef std::function ContentReceiver; +typedef std::function Progress; + +struct MultipartFile { + std::string filename; + std::string content_type; + size_t offset = 0; + size_t length = 0; +}; +typedef std::multimap MultipartFiles; + +struct Request { + std::string version; + std::string method; + std::string target; + std::string path; + Headers headers; + std::string body; + Params params; + MultipartFiles files; + Match matches; + +#ifdef CPPHTTPLIB_OPENSSL_SUPPORT + const SSL *ssl; +#endif + + bool has_header(const char *key) const; + std::string get_header_value(const char *key, size_t id = 0) const; + size_t get_header_value_count(const char *key) const; + void set_header(const char *key, const char *val); + + bool has_param(const char *key) const; + std::string get_param_value(const char *key, size_t id = 0) const; + size_t get_param_value_count(const char *key) const; + + bool has_file(const char *key) const; + MultipartFile get_file_value(const char *key) const; +}; + +struct Response { + std::string version; + int status; + Headers headers; + std::string body; + + ContentProducer content_producer; + ContentReceiver content_receiver; + Progress progress; + + bool has_header(const char *key) const; + std::string get_header_value(const char *key, size_t id = 0) const; + size_t get_header_value_count(const char *key) const; + void set_header(const char *key, const char *val); + + void set_redirect(const char *uri); + void set_content(const char *s, size_t n, const char *content_type); + void set_content(const std::string &s, const char *content_type); + + Response() : status(-1) {} +}; + +class Stream { +public: + virtual ~Stream() {} + virtual int read(char *ptr, size_t size) = 0; + virtual int write(const char *ptr, size_t size1) = 0; + virtual int write(const char *ptr) = 0; + virtual std::string get_remote_addr() const = 0; + + template + void write_format(const char *fmt, const Args &... args); +}; + +class SocketStream : public Stream { +public: + SocketStream(socket_t sock); + virtual ~SocketStream(); + + virtual int read(char *ptr, size_t size); + virtual int write(const char *ptr, size_t size); + virtual int write(const char *ptr); + virtual std::string get_remote_addr() const; + +private: + socket_t sock_; +}; + +class BufferStream : public Stream { +public: + BufferStream() {} + virtual ~BufferStream() {} + + virtual int read(char *ptr, size_t size); + virtual int write(const char *ptr, size_t size); + virtual int write(const char *ptr); + virtual std::string get_remote_addr() const; + + const std::string &get_buffer() const; + +private: + std::string buffer; +}; + +class Server { +public: + typedef std::function Handler; + typedef std::function Logger; + + Server(); + + virtual ~Server(); + + virtual bool is_valid() const; + + Server &Get(const char *pattern, Handler handler); + Server &Post(const char *pattern, Handler handler); + + Server &Put(const char *pattern, Handler handler); + Server &Patch(const char *pattern, Handler handler); + Server &Delete(const char *pattern, Handler handler); + Server &Options(const char *pattern, Handler handler); + + bool set_base_dir(const char *path); + + void set_error_handler(Handler handler); + void set_logger(Logger logger); + + void set_keep_alive_max_count(size_t count); + void set_payload_max_length(uint64_t length); + + int bind_to_any_port(const char *host, int socket_flags = 0); + bool listen_after_bind(); + + bool listen(const char *host, int port, int socket_flags = 0); + + bool is_running() const; + void stop(); + +protected: + bool process_request(Stream &strm, bool last_connection, + bool &connection_close, + std::function setup_request = nullptr); + + size_t keep_alive_max_count_; + size_t payload_max_length_; + +private: + typedef std::vector> Handlers; + + socket_t create_server_socket(const char *host, int port, + int socket_flags) const; + int bind_internal(const char *host, int port, int socket_flags); + bool listen_internal(); + + bool routing(Request &req, Response &res); + bool handle_file_request(Request &req, Response &res); + bool dispatch_request(Request &req, Response &res, Handlers &handlers); + + bool parse_request_line(const char *s, Request &req); + void write_response(Stream &strm, bool last_connection, const Request &req, + Response &res); + + virtual bool read_and_close_socket(socket_t sock); + + std::atomic is_running_; + std::atomic svr_sock_; + std::string base_dir_; + Handlers get_handlers_; + Handlers post_handlers_; + Handlers put_handlers_; + Handlers patch_handlers_; + Handlers delete_handlers_; + Handlers options_handlers_; + Handler error_handler_; + Logger logger_; + + // TODO: Use thread pool... + std::mutex running_threads_mutex_; + int running_threads_; +}; + +class Client { +public: + Client(const char *host, int port = 80, time_t timeout_sec = 300); + + virtual ~Client(); + + virtual bool is_valid() const; + + std::shared_ptr Get(const char *path, Progress progress = nullptr); + std::shared_ptr Get(const char *path, const Headers &headers, + Progress progress = nullptr); + + std::shared_ptr Get(const char *path, + ContentReceiver content_receiver, + Progress progress = nullptr); + std::shared_ptr Get(const char *path, const Headers &headers, + ContentReceiver content_receiver, + Progress progress = nullptr); + + std::shared_ptr Head(const char *path); + std::shared_ptr Head(const char *path, const Headers &headers); + + std::shared_ptr Post(const char *path, const std::string &body, + const char *content_type); + std::shared_ptr Post(const char *path, const Headers &headers, + const std::string &body, + const char *content_type); + + std::shared_ptr Post(const char *path, const Params ¶ms); + std::shared_ptr Post(const char *path, const Headers &headers, + const Params ¶ms); + + std::shared_ptr Put(const char *path, const std::string &body, + const char *content_type); + std::shared_ptr Put(const char *path, const Headers &headers, + const std::string &body, + const char *content_type); + + std::shared_ptr Patch(const char *path, const std::string &body, + const char *content_type); + std::shared_ptr Patch(const char *path, const Headers &headers, + const std::string &body, + const char *content_type); + + std::shared_ptr Delete(const char *path, + const std::string &body = std::string(), + const char *content_type = nullptr); + std::shared_ptr Delete(const char *path, const Headers &headers, + const std::string &body = std::string(), + const char *content_type = nullptr); + + std::shared_ptr Options(const char *path); + std::shared_ptr Options(const char *path, const Headers &headers); + + bool send(Request &req, Response &res); + +protected: + bool process_request(Stream &strm, Request &req, Response &res, + bool &connection_close); + + const std::string host_; + const int port_; + time_t timeout_sec_; + const std::string host_and_port_; + +private: + socket_t create_client_socket() const; + bool read_response_line(Stream &strm, Response &res); + void write_request(Stream &strm, Request &req); + + virtual bool read_and_close_socket(socket_t sock, Request &req, + Response &res); + virtual bool is_ssl() const; +}; + +#ifdef CPPHTTPLIB_OPENSSL_SUPPORT +class SSLSocketStream : public Stream { +public: + SSLSocketStream(socket_t sock, SSL *ssl); + virtual ~SSLSocketStream(); + + virtual int read(char *ptr, size_t size); + virtual int write(const char *ptr, size_t size); + virtual int write(const char *ptr); + virtual std::string get_remote_addr() const; + +private: + socket_t sock_; + SSL *ssl_; +}; + +class SSLServer : public Server { +public: + SSLServer(const char *cert_path, const char *private_key_path, + const char *client_ca_cert_file_path = nullptr, + const char *client_ca_cert_dir_path = nullptr); + + virtual ~SSLServer(); + + virtual bool is_valid() const; + +private: + virtual bool read_and_close_socket(socket_t sock); + + SSL_CTX *ctx_; + std::mutex ctx_mutex_; +}; + +class SSLClient : public Client { +public: + SSLClient(const char *host, int port = 443, time_t timeout_sec = 300, + const char *client_cert_path = nullptr, + const char *client_key_path = nullptr); + + virtual ~SSLClient(); + + virtual bool is_valid() const; + + void set_ca_cert_path(const char *ca_ceert_file_path, + const char *ca_cert_dir_path = nullptr); + void enable_server_certificate_verification(bool enabled); + + long get_openssl_verify_result() const; + +private: + virtual bool read_and_close_socket(socket_t sock, Request &req, + Response &res); + virtual bool is_ssl() const; + + bool verify_host(X509 *server_cert) const; + bool verify_host_with_subject_alt_name(X509 *server_cert) const; + bool verify_host_with_common_name(X509 *server_cert) const; + bool check_host_name(const char *pattern, size_t pattern_len) const; + + SSL_CTX *ctx_; + std::mutex ctx_mutex_; + std::vector host_components_; + std::string ca_cert_file_path_; + std::string ca_cert_dir_path_; + bool server_certificate_verification_ = false; + long verify_result_ = 0; +}; +#endif + +/* + * Implementation + */ +namespace detail { + +inline bool is_hex(char c, int &v) { + if (0x20 <= c && isdigit(c)) { + v = c - '0'; + return true; + } else if ('A' <= c && c <= 'F') { + v = c - 'A' + 10; + return true; + } else if ('a' <= c && c <= 'f') { + v = c - 'a' + 10; + return true; + } + return false; +} + +inline bool from_hex_to_i(const std::string &s, size_t i, size_t cnt, + int &val) { + if (i >= s.size()) { return false; } + + val = 0; + for (; cnt; i++, cnt--) { + if (!s[i]) { return false; } + int v = 0; + if (is_hex(s[i], v)) { + val = val * 16 + v; + } else { + return false; + } + } + return true; +} + +inline std::string from_i_to_hex(uint64_t n) { + const char *charset = "0123456789abcdef"; + std::string ret; + do { + ret = charset[n & 15] + ret; + n >>= 4; + } while (n > 0); + return ret; +} + +inline size_t to_utf8(int code, char *buff) { + if (code < 0x0080) { + buff[0] = (code & 0x7F); + return 1; + } else if (code < 0x0800) { + buff[0] = (0xC0 | ((code >> 6) & 0x1F)); + buff[1] = (0x80 | (code & 0x3F)); + return 2; + } else if (code < 0xD800) { + buff[0] = (0xE0 | ((code >> 12) & 0xF)); + buff[1] = (0x80 | ((code >> 6) & 0x3F)); + buff[2] = (0x80 | (code & 0x3F)); + return 3; + } else if (code < 0xE000) { // D800 - DFFF is invalid... + return 0; + } else if (code < 0x10000) { + buff[0] = (0xE0 | ((code >> 12) & 0xF)); + buff[1] = (0x80 | ((code >> 6) & 0x3F)); + buff[2] = (0x80 | (code & 0x3F)); + return 3; + } else if (code < 0x110000) { + buff[0] = (0xF0 | ((code >> 18) & 0x7)); + buff[1] = (0x80 | ((code >> 12) & 0x3F)); + buff[2] = (0x80 | ((code >> 6) & 0x3F)); + buff[3] = (0x80 | (code & 0x3F)); + return 4; + } + + // NOTREACHED + return 0; +} + +// NOTE: This code came up with the following stackoverflow post: +// https://stackoverflow.com/questions/180947/base64-decode-snippet-in-c +inline std::string base64_encode(const std::string &in) { + static const auto lookup = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + std::string out; + out.reserve(in.size()); + + int val = 0; + int valb = -6; + + for (uint8_t c : in) { + val = (val << 8) + c; + valb += 8; + while (valb >= 0) { + out.push_back(lookup[(val >> valb) & 0x3F]); + valb -= 6; + } + } + + if (valb > -6) { + out.push_back(lookup[((val << 8) >> (valb + 8)) & 0x3F]); + } + + while (out.size() % 4) { + out.push_back('='); + } + + return out; +} + +inline bool is_file(const std::string &path) { + struct stat st; + return stat(path.c_str(), &st) >= 0 && S_ISREG(st.st_mode); +} + +inline bool is_dir(const std::string &path) { + struct stat st; + return stat(path.c_str(), &st) >= 0 && S_ISDIR(st.st_mode); +} + +inline bool is_valid_path(const std::string &path) { + size_t level = 0; + size_t i = 0; + + // Skip slash + while (i < path.size() && path[i] == '/') { + i++; + } + + while (i < path.size()) { + // Read component + auto beg = i; + while (i < path.size() && path[i] != '/') { + i++; + } + + auto len = i - beg; + assert(len > 0); + + if (!path.compare(beg, len, ".")) { + ; + } else if (!path.compare(beg, len, "..")) { + if (level == 0) { return false; } + level--; + } else { + level++; + } + + // Skip slash + while (i < path.size() && path[i] == '/') { + i++; + } + } + + return true; +} + +inline void read_file(const std::string &path, std::string &out) { + std::ifstream fs(path, std::ios_base::binary); + fs.seekg(0, std::ios_base::end); + auto size = fs.tellg(); + fs.seekg(0); + out.resize(static_cast(size)); + fs.read(&out[0], size); +} + +inline std::string file_extension(const std::string &path) { + std::smatch m; + auto pat = std::regex("\\.([a-zA-Z0-9]+)$"); + if (std::regex_search(path, m, pat)) { return m[1].str(); } + return std::string(); +} + +template void split(const char *b, const char *e, char d, Fn fn) { + int i = 0; + int beg = 0; + + while (e ? (b + i != e) : (b[i] != '\0')) { + if (b[i] == d) { + fn(&b[beg], &b[i]); + beg = i + 1; + } + i++; + } + + if (i) { fn(&b[beg], &b[i]); } +} + +// NOTE: until the read size reaches `fixed_buffer_size`, use `fixed_buffer` +// to store data. The call can set memory on stack for performance. +class stream_line_reader { +public: + stream_line_reader(Stream &strm, char *fixed_buffer, size_t fixed_buffer_size) + : strm_(strm), fixed_buffer_(fixed_buffer), + fixed_buffer_size_(fixed_buffer_size) {} + + const char *ptr() const { + if (glowable_buffer_.empty()) { + return fixed_buffer_; + } else { + return glowable_buffer_.data(); + } + } + + size_t size() const { + if (glowable_buffer_.empty()) { + return fixed_buffer_used_size_; + } else { + return glowable_buffer_.size(); + } + } + + bool getline() { + fixed_buffer_used_size_ = 0; + glowable_buffer_.clear(); + + for (size_t i = 0;; i++) { + char byte; + auto n = strm_.read(&byte, 1); + + if (n < 0) { + return false; + } else if (n == 0) { + if (i == 0) { + return false; + } else { + break; + } + } + + append(byte); + + if (byte == '\n') { break; } + } + + return true; + } + +private: + void append(char c) { + if (fixed_buffer_used_size_ < fixed_buffer_size_ - 1) { + fixed_buffer_[fixed_buffer_used_size_++] = c; + fixed_buffer_[fixed_buffer_used_size_] = '\0'; + } else { + if (glowable_buffer_.empty()) { + assert(fixed_buffer_[fixed_buffer_used_size_] == '\0'); + glowable_buffer_.assign(fixed_buffer_, fixed_buffer_used_size_); + } + glowable_buffer_ += c; + } + } + + Stream &strm_; + char *fixed_buffer_; + const size_t fixed_buffer_size_; + size_t fixed_buffer_used_size_; + std::string glowable_buffer_; +}; + +inline int close_socket(socket_t sock) { +#ifdef _WIN32 + return closesocket(sock); +#else + return close(sock); +#endif +} + +inline int select_read(socket_t sock, time_t sec, time_t usec) { + fd_set fds; + FD_ZERO(&fds); + FD_SET(sock, &fds); + + timeval tv; + tv.tv_sec = static_cast(sec); + tv.tv_usec = static_cast(usec); + + return select(static_cast(sock + 1), &fds, nullptr, nullptr, &tv); +} + +inline bool wait_until_socket_is_ready(socket_t sock, time_t sec, time_t usec) { + fd_set fdsr; + FD_ZERO(&fdsr); + FD_SET(sock, &fdsr); + + auto fdsw = fdsr; + auto fdse = fdsr; + + timeval tv; + tv.tv_sec = static_cast(sec); + tv.tv_usec = static_cast(usec); + + if (select(static_cast(sock + 1), &fdsr, &fdsw, &fdse, &tv) < 0) { + return false; + } else if (FD_ISSET(sock, &fdsr) || FD_ISSET(sock, &fdsw)) { + int error = 0; + socklen_t len = sizeof(error); + if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&error, &len) < 0 || + error) { + return false; + } + } else { + return false; + } + + return true; +} + +template +inline bool read_and_close_socket(socket_t sock, size_t keep_alive_max_count, + T callback) { + bool ret = false; + + if (keep_alive_max_count > 0) { + auto count = keep_alive_max_count; + while (count > 0 && + detail::select_read(sock, CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND, + CPPHTTPLIB_KEEPALIVE_TIMEOUT_USECOND) > 0) { + SocketStream strm(sock); + auto last_connection = count == 1; + auto connection_close = false; + + ret = callback(strm, last_connection, connection_close); + if (!ret || connection_close) { break; } + + count--; + } + } else { + SocketStream strm(sock); + auto dummy_connection_close = false; + ret = callback(strm, true, dummy_connection_close); + } + + close_socket(sock); + return ret; +} + +inline int shutdown_socket(socket_t sock) { +#ifdef _WIN32 + return shutdown(sock, SD_BOTH); +#else + return shutdown(sock, SHUT_RDWR); +#endif +} + +template +socket_t create_socket(const char *host, int port, Fn fn, + int socket_flags = 0) { +#ifdef _WIN32 +#define SO_SYNCHRONOUS_NONALERT 0x20 +#define SO_OPENTYPE 0x7008 + + int opt = SO_SYNCHRONOUS_NONALERT; + setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *)&opt, + sizeof(opt)); +#endif + + // Get address info + struct addrinfo hints; + struct addrinfo *result; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = socket_flags; + hints.ai_protocol = 0; + + auto service = std::to_string(port); + + if (getaddrinfo(host, service.c_str(), &hints, &result)) { + return INVALID_SOCKET; + } + + for (auto rp = result; rp; rp = rp->ai_next) { + // Create a socket +#ifdef _WIN32 + auto sock = WSASocketW(rp->ai_family, rp->ai_socktype, rp->ai_protocol, + nullptr, 0, WSA_FLAG_NO_HANDLE_INHERIT); +#else + auto sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); +#endif + if (sock == INVALID_SOCKET) { continue; } + +#ifndef _WIN32 + if (fcntl(sock, F_SETFD, FD_CLOEXEC) == -1) { continue; } +#endif + + // Make 'reuse address' option available + int yes = 1; + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)); +#ifdef SO_REUSEPORT + setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (char *)&yes, sizeof(yes)); +#endif + + // bind or connect + if (fn(sock, *rp)) { + freeaddrinfo(result); + return sock; + } + + close_socket(sock); + } + + freeaddrinfo(result); + return INVALID_SOCKET; +} + +inline void set_nonblocking(socket_t sock, bool nonblocking) { +#ifdef _WIN32 + auto flags = nonblocking ? 1UL : 0UL; + ioctlsocket(sock, FIONBIO, &flags); +#else + auto flags = fcntl(sock, F_GETFL, 0); + fcntl(sock, F_SETFL, + nonblocking ? (flags | O_NONBLOCK) : (flags & (~O_NONBLOCK))); +#endif +} + +inline bool is_connection_error() { +#ifdef _WIN32 + return WSAGetLastError() != WSAEWOULDBLOCK; +#else + return errno != EINPROGRESS; +#endif +} + +inline std::string get_remote_addr(socket_t sock) { + struct sockaddr_storage addr; + socklen_t len = sizeof(addr); + + if (!getpeername(sock, (struct sockaddr *)&addr, &len)) { + char ipstr[NI_MAXHOST]; + + if (!getnameinfo((struct sockaddr *)&addr, len, ipstr, sizeof(ipstr), + nullptr, 0, NI_NUMERICHOST)) { + return ipstr; + } + } + + return std::string(); +} + +inline const char *find_content_type(const std::string &path) { + auto ext = file_extension(path); + if (ext == "txt") { + return "text/plain"; + } else if (ext == "html") { + return "text/html"; + } else if (ext == "css") { + return "text/css"; + } else if (ext == "jpeg" || ext == "jpg") { + return "image/jpg"; + } else if (ext == "png") { + return "image/png"; + } else if (ext == "gif") { + return "image/gif"; + } else if (ext == "svg") { + return "image/svg+xml"; + } else if (ext == "ico") { + return "image/x-icon"; + } else if (ext == "json") { + return "application/json"; + } else if (ext == "pdf") { + return "application/pdf"; + } else if (ext == "js") { + return "application/javascript"; + } else if (ext == "xml") { + return "application/xml"; + } else if (ext == "xhtml") { + return "application/xhtml+xml"; + } + return nullptr; +} + +inline const char *status_message(int status) { + switch (status) { + case 200: return "OK"; + case 301: return "Moved Permanently"; + case 302: return "Found"; + case 303: return "See Other"; + case 304: return "Not Modified"; + case 400: return "Bad Request"; + case 403: return "Forbidden"; + case 404: return "Not Found"; + case 413: return "Payload Too Large"; + case 414: return "Request-URI Too Long"; + case 415: return "Unsupported Media Type"; + default: + case 500: return "Internal Server Error"; + } +} + +#ifdef CPPHTTPLIB_ZLIB_SUPPORT +inline bool can_compress(const std::string &content_type) { + return !content_type.find("text/") || content_type == "image/svg+xml" || + content_type == "application/javascript" || + content_type == "application/json" || + content_type == "application/xml" || + content_type == "application/xhtml+xml"; +} + +inline bool compress(std::string &content) { + z_stream strm; + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + + auto ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 31, 8, + Z_DEFAULT_STRATEGY); + if (ret != Z_OK) { return false; } + + strm.avail_in = content.size(); + strm.next_in = (Bytef *)content.data(); + + std::string compressed; + + const auto bufsiz = 16384; + char buff[bufsiz]; + do { + strm.avail_out = bufsiz; + strm.next_out = (Bytef *)buff; + ret = deflate(&strm, Z_FINISH); + assert(ret != Z_STREAM_ERROR); + compressed.append(buff, bufsiz - strm.avail_out); + } while (strm.avail_out == 0); + + assert(ret == Z_STREAM_END); + assert(strm.avail_in == 0); + + content.swap(compressed); + + deflateEnd(&strm); + return true; +} + +class decompressor { +public: + decompressor() { + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + + // 15 is the value of wbits, which should be at the maximum possible value + // to ensure that any gzip stream can be decoded. The offset of 16 specifies + // that the stream to decompress will be formatted with a gzip wrapper. + is_valid_ = inflateInit2(&strm, 16 + 15) == Z_OK; + } + + ~decompressor() { inflateEnd(&strm); } + + bool is_valid() const { return is_valid_; } + + template + bool decompress(const char *data, size_t data_len, T callback) { + int ret = Z_OK; + std::string decompressed; + + // strm.avail_in = content.size(); + // strm.next_in = (Bytef *)content.data(); + strm.avail_in = data_len; + strm.next_in = (Bytef *)data; + + const auto bufsiz = 16384; + char buff[bufsiz]; + do { + strm.avail_out = bufsiz; + strm.next_out = (Bytef *)buff; + + ret = inflate(&strm, Z_NO_FLUSH); + assert(ret != Z_STREAM_ERROR); + switch (ret) { + case Z_NEED_DICT: + case Z_DATA_ERROR: + case Z_MEM_ERROR: inflateEnd(&strm); return false; + } + + decompressed.append(buff, bufsiz - strm.avail_out); + } while (strm.avail_out == 0); + + if (ret == Z_STREAM_END) { + callback(decompressed.data(), decompressed.size()); + return true; + } + + return false; + } + +private: + bool is_valid_; + z_stream strm; +}; +#endif + +inline bool has_header(const Headers &headers, const char *key) { + return headers.find(key) != headers.end(); +} + +inline const char *get_header_value(const Headers &headers, const char *key, + size_t id = 0, const char *def = nullptr) { + auto it = headers.find(key); + std::advance(it, id); + if (it != headers.end()) { return it->second.c_str(); } + return def; +} + +inline uint64_t get_header_value_uint64(const Headers &headers, const char *key, + int def = 0) { + auto it = headers.find(key); + if (it != headers.end()) { + return std::strtoull(it->second.data(), nullptr, 10); + } + return def; +} + +inline bool read_headers(Stream &strm, Headers &headers) { + static std::regex re(R"((.+?):\s*(.+?)\s*\r\n)"); + + const auto bufsiz = 2048; + char buf[bufsiz]; + + stream_line_reader reader(strm, buf, bufsiz); + + for (;;) { + if (!reader.getline()) { return false; } + if (!strcmp(reader.ptr(), "\r\n")) { break; } + std::cmatch m; + if (std::regex_match(reader.ptr(), m, re)) { + auto key = std::string(m[1]); + auto val = std::string(m[2]); + headers.emplace(key, val); + } + } + + return true; +} + +template +inline bool read_content_with_length(Stream &strm, size_t len, + Progress progress, T callback) { + char buf[CPPHTTPLIB_RECV_BUFSIZ]; + + size_t r = 0; + while (r < len) { + auto n = strm.read(buf, std::min((len - r), CPPHTTPLIB_RECV_BUFSIZ)); + if (n <= 0) { return false; } + + callback(buf, n); + + r += n; + + if (progress) { + if (!progress(r, len)) { return false; } + } + } + + return true; +} + +inline void skip_content_with_length(Stream &strm, size_t len) { + char buf[CPPHTTPLIB_RECV_BUFSIZ]; + size_t r = 0; + while (r < len) { + auto n = strm.read(buf, std::min((len - r), CPPHTTPLIB_RECV_BUFSIZ)); + if (n <= 0) { return; } + r += n; + } +} + +template +inline bool read_content_without_length(Stream &strm, T callback) { + char buf[CPPHTTPLIB_RECV_BUFSIZ]; + for (;;) { + auto n = strm.read(buf, CPPHTTPLIB_RECV_BUFSIZ); + if (n < 0) { + return false; + } else if (n == 0) { + return true; + } + callback(buf, n); + } + + return true; +} + +template +inline bool read_content_chunked(Stream &strm, T callback) { + const auto bufsiz = 16; + char buf[bufsiz]; + + stream_line_reader reader(strm, buf, bufsiz); + + if (!reader.getline()) { return false; } + + auto chunk_len = std::stoi(reader.ptr(), 0, 16); + + while (chunk_len > 0) { + if (!read_content_with_length(strm, chunk_len, nullptr, callback)) { + return false; + } + + if (!reader.getline()) { return false; } + + if (strcmp(reader.ptr(), "\r\n")) { break; } + + if (!reader.getline()) { return false; } + + chunk_len = std::stoi(reader.ptr(), 0, 16); + } + + if (chunk_len == 0) { + // Reader terminator after chunks + if (!reader.getline() || strcmp(reader.ptr(), "\r\n")) return false; + } + + return true; +} + +inline bool is_chunked_transfer_encoding(const Headers &headers) { + return !strcasecmp(get_header_value(headers, "Transfer-Encoding", 0, ""), + "chunked"); +} + +template +bool read_content(Stream &strm, T &x, uint64_t payload_max_length, int &status, + Progress progress, U callback) { + + ContentReceiver out = [&](const char *buf, size_t n) { callback(buf, n); }; + +#ifdef CPPHTTPLIB_ZLIB_SUPPORT + detail::decompressor decompressor; + + if (!decompressor.is_valid()) { + status = 500; + return false; + } + + if (x.get_header_value("Content-Encoding") == "gzip") { + out = [&](const char *buf, size_t n) { + decompressor.decompress( + buf, n, [&](const char *buf, size_t n) { callback(buf, n); }); + }; + } +#else + if (x.get_header_value("Content-Encoding") == "gzip") { + status = 415; + return false; + } +#endif + + auto ret = true; + auto exceed_payload_max_length = false; + + if (is_chunked_transfer_encoding(x.headers)) { + ret = read_content_chunked(strm, out); + } else if (!has_header(x.headers, "Content-Length")) { + ret = read_content_without_length(strm, out); + } else { + auto len = get_header_value_uint64(x.headers, "Content-Length", 0); + if (len > 0) { + if ((len > payload_max_length) || + // For 32-bit platform + (sizeof(size_t) < sizeof(uint64_t) && + len > std::numeric_limits::max())) { + exceed_payload_max_length = true; + skip_content_with_length(strm, len); + ret = false; + } else { + ret = read_content_with_length(strm, len, progress, out); + } + } + } + + if (!ret) { status = exceed_payload_max_length ? 413 : 400; } + + return ret; +} + +template inline void write_headers(Stream &strm, const T &info) { + for (const auto &x : info.headers) { + strm.write_format("%s: %s\r\n", x.first.c_str(), x.second.c_str()); + } + strm.write("\r\n"); +} + +template +inline void write_content_chunked(Stream &strm, const T &x) { + auto chunked_response = !x.has_header("Content-Length"); + uint64_t offset = 0; + auto data_available = true; + while (data_available) { + auto chunk = x.content_producer(offset); + offset += chunk.size(); + data_available = !chunk.empty(); + + // Emit chunked response header and footer for each chunk + if (chunked_response) { + chunk = from_i_to_hex(chunk.size()) + "\r\n" + chunk + "\r\n"; + } + + if (strm.write(chunk.c_str(), chunk.size()) < 0) { + break; // Stop on error + } + } +} + +inline std::string encode_url(const std::string &s) { + std::string result; + + for (auto i = 0; s[i]; i++) { + switch (s[i]) { + case ' ': result += "%20"; break; + case '+': result += "%2B"; break; + case '\r': result += "%0D"; break; + case '\n': result += "%0A"; break; + case '\'': result += "%27"; break; + case ',': result += "%2C"; break; + case ':': result += "%3A"; break; + case ';': result += "%3B"; break; + default: + auto c = static_cast(s[i]); + if (c >= 0x80) { + result += '%'; + char hex[4]; + size_t len = snprintf(hex, sizeof(hex) - 1, "%02X", c); + assert(len == 2); + result.append(hex, len); + } else { + result += s[i]; + } + break; + } + } + + return result; +} + +inline std::string decode_url(const std::string &s) { + std::string result; + + for (size_t i = 0; i < s.size(); i++) { + if (s[i] == '%' && i + 1 < s.size()) { + if (s[i + 1] == 'u') { + int val = 0; + if (from_hex_to_i(s, i + 2, 4, val)) { + // 4 digits Unicode codes + char buff[4]; + size_t len = to_utf8(val, buff); + if (len > 0) { result.append(buff, len); } + i += 5; // 'u0000' + } else { + result += s[i]; + } + } else { + int val = 0; + if (from_hex_to_i(s, i + 1, 2, val)) { + // 2 digits hex codes + result += val; + i += 2; // '00' + } else { + result += s[i]; + } + } + } else if (s[i] == '+') { + result += ' '; + } else { + result += s[i]; + } + } + + return result; +} + +inline void parse_query_text(const std::string &s, Params ¶ms) { + split(&s[0], &s[s.size()], '&', [&](const char *b, const char *e) { + std::string key; + std::string val; + split(b, e, '=', [&](const char *b, const char *e) { + if (key.empty()) { + key.assign(b, e); + } else { + val.assign(b, e); + } + }); + params.emplace(key, decode_url(val)); + }); +} + +inline bool parse_multipart_boundary(const std::string &content_type, + std::string &boundary) { + auto pos = content_type.find("boundary="); + if (pos == std::string::npos) { return false; } + + boundary = content_type.substr(pos + 9); + return true; +} + +inline bool parse_multipart_formdata(const std::string &boundary, + const std::string &body, + MultipartFiles &files) { + static std::string dash = "--"; + static std::string crlf = "\r\n"; + + static std::regex re_content_type("Content-Type: (.*?)", + std::regex_constants::icase); + + static std::regex re_content_disposition( + "Content-Disposition: form-data; name=\"(.*?)\"(?:; filename=\"(.*?)\")?", + std::regex_constants::icase); + + auto dash_boundary = dash + boundary; + + auto pos = body.find(dash_boundary); + if (pos != 0) { return false; } + + pos += dash_boundary.size(); + + auto next_pos = body.find(crlf, pos); + if (next_pos == std::string::npos) { return false; } + + pos = next_pos + crlf.size(); + + while (pos < body.size()) { + next_pos = body.find(crlf, pos); + if (next_pos == std::string::npos) { return false; } + + std::string name; + MultipartFile file; + + auto header = body.substr(pos, (next_pos - pos)); + + while (pos != next_pos) { + std::smatch m; + if (std::regex_match(header, m, re_content_type)) { + file.content_type = m[1]; + } else if (std::regex_match(header, m, re_content_disposition)) { + name = m[1]; + file.filename = m[2]; + } + + pos = next_pos + crlf.size(); + + next_pos = body.find(crlf, pos); + if (next_pos == std::string::npos) { return false; } + + header = body.substr(pos, (next_pos - pos)); + } + + pos = next_pos + crlf.size(); + + next_pos = body.find(crlf + dash_boundary, pos); + + if (next_pos == std::string::npos) { return false; } + + file.offset = pos; + file.length = next_pos - pos; + + pos = next_pos + crlf.size() + dash_boundary.size(); + + next_pos = body.find(crlf, pos); + if (next_pos == std::string::npos) { return false; } + + files.emplace(name, file); + + pos = next_pos + crlf.size(); + } + + return true; +} + +inline std::string to_lower(const char *beg, const char *end) { + std::string out; + auto it = beg; + while (it != end) { + out += ::tolower(*it); + it++; + } + return out; +} + +inline void make_range_header_core(std::string &) {} + +template +inline void make_range_header_core(std::string &field, uint64_t value) { + if (!field.empty()) { field += ", "; } + field += std::to_string(value) + "-"; +} + +template +inline void make_range_header_core(std::string &field, uint64_t value1, + uint64_t value2, Args... args) { + if (!field.empty()) { field += ", "; } + field += std::to_string(value1) + "-" + std::to_string(value2); + make_range_header_core(field, args...); +} + +#ifdef _WIN32 +class WSInit { +public: + WSInit() { + WSADATA wsaData; + WSAStartup(0x0002, &wsaData); + } + + ~WSInit() { WSACleanup(); } +}; + +static WSInit wsinit_; +#endif + +} // namespace detail + +// Header utilities +template +inline std::pair make_range_header(uint64_t value, + Args... args) { + std::string field; + detail::make_range_header_core(field, value, args...); + field.insert(0, "bytes="); + return std::make_pair("Range", field); +} + + +inline std::pair +make_basic_authentication_header(const std::string& username, const std::string& password) { + auto field = "Basic " + detail::base64_encode(username + ":" + password); + return std::make_pair("Authorization", field); +} +// Request implementation +inline bool Request::has_header(const char *key) const { + return detail::has_header(headers, key); +} + +inline std::string Request::get_header_value(const char *key, size_t id) const { + return detail::get_header_value(headers, key, id, ""); +} + +inline size_t Request::get_header_value_count(const char *key) const { + auto r = headers.equal_range(key); + return std::distance(r.first, r.second); +} + +inline void Request::set_header(const char *key, const char *val) { + headers.emplace(key, val); +} + +inline bool Request::has_param(const char *key) const { + return params.find(key) != params.end(); +} + +inline std::string Request::get_param_value(const char *key, size_t id) const { + auto it = params.find(key); + std::advance(it, id); + if (it != params.end()) { return it->second; } + return std::string(); +} + +inline size_t Request::get_param_value_count(const char *key) const { + auto r = params.equal_range(key); + return std::distance(r.first, r.second); +} + +inline bool Request::has_file(const char *key) const { + return files.find(key) != files.end(); +} + +inline MultipartFile Request::get_file_value(const char *key) const { + auto it = files.find(key); + if (it != files.end()) { return it->second; } + return MultipartFile(); +} + +// Response implementation +inline bool Response::has_header(const char *key) const { + return headers.find(key) != headers.end(); +} + +inline std::string Response::get_header_value(const char *key, + size_t id) const { + return detail::get_header_value(headers, key, id, ""); +} + +inline size_t Response::get_header_value_count(const char *key) const { + auto r = headers.equal_range(key); + return std::distance(r.first, r.second); +} + +inline void Response::set_header(const char *key, const char *val) { + headers.emplace(key, val); +} + +inline void Response::set_redirect(const char *url) { + set_header("Location", url); + status = 302; +} + +inline void Response::set_content(const char *s, size_t n, + const char *content_type) { + body.assign(s, n); + set_header("Content-Type", content_type); +} + +inline void Response::set_content(const std::string &s, + const char *content_type) { + body = s; + set_header("Content-Type", content_type); +} + +// Rstream implementation +template +inline void Stream::write_format(const char *fmt, const Args &... args) { + const auto bufsiz = 2048; + char buf[bufsiz]; + +#if defined(_MSC_VER) && _MSC_VER < 1900 + auto n = _snprintf_s(buf, bufsiz, bufsiz - 1, fmt, args...); +#else + auto n = snprintf(buf, bufsiz - 1, fmt, args...); +#endif + if (n > 0) { + if (n >= bufsiz - 1) { + std::vector glowable_buf(bufsiz); + + while (n >= static_cast(glowable_buf.size() - 1)) { + glowable_buf.resize(glowable_buf.size() * 2); +#if defined(_MSC_VER) && _MSC_VER < 1900 + n = _snprintf_s(&glowable_buf[0], glowable_buf.size(), + glowable_buf.size() - 1, fmt, args...); +#else + n = snprintf(&glowable_buf[0], glowable_buf.size() - 1, fmt, args...); +#endif + } + write(&glowable_buf[0], n); + } else { + write(buf, n); + } + } +} + +// Socket stream implementation +inline SocketStream::SocketStream(socket_t sock) : sock_(sock) {} + +inline SocketStream::~SocketStream() {} + +inline int SocketStream::read(char *ptr, size_t size) { + if (detail::select_read(sock_, CPPHTTPLIB_READ_TIMEOUT_SECOND, + CPPHTTPLIB_READ_TIMEOUT_USECOND) > 0) { + return recv(sock_, ptr, static_cast(size), 0); + } + return -1; +} + +inline int SocketStream::write(const char *ptr, size_t size) { + return send(sock_, ptr, static_cast(size), 0); +} + +inline int SocketStream::write(const char *ptr) { + return write(ptr, strlen(ptr)); +} + +inline std::string SocketStream::get_remote_addr() const { + return detail::get_remote_addr(sock_); +} + +// Buffer stream implementation +inline int BufferStream::read(char *ptr, size_t size) { +#if defined(_MSC_VER) && _MSC_VER < 1900 + return static_cast(buffer._Copy_s(ptr, size, size)); +#else + return static_cast(buffer.copy(ptr, size)); +#endif +} + +inline int BufferStream::write(const char *ptr, size_t size) { + buffer.append(ptr, size); + return static_cast(size); +} + +inline int BufferStream::write(const char *ptr) { + size_t size = strlen(ptr); + buffer.append(ptr, size); + return static_cast(size); +} + +inline std::string BufferStream::get_remote_addr() const { return ""; } + +inline const std::string &BufferStream::get_buffer() const { return buffer; } + +// HTTP server implementation +inline Server::Server() + : keep_alive_max_count_(CPPHTTPLIB_KEEPALIVE_MAX_COUNT), + payload_max_length_(CPPHTTPLIB_PAYLOAD_MAX_LENGTH), is_running_(false), + svr_sock_(INVALID_SOCKET), running_threads_(0) { +#ifndef _WIN32 + signal(SIGPIPE, SIG_IGN); +#endif +} + +inline Server::~Server() {} + +inline Server &Server::Get(const char *pattern, Handler handler) { + get_handlers_.push_back(std::make_pair(std::regex(pattern), handler)); + return *this; +} + +inline Server &Server::Post(const char *pattern, Handler handler) { + post_handlers_.push_back(std::make_pair(std::regex(pattern), handler)); + return *this; +} + +inline Server &Server::Put(const char *pattern, Handler handler) { + put_handlers_.push_back(std::make_pair(std::regex(pattern), handler)); + return *this; +} + +inline Server &Server::Patch(const char *pattern, Handler handler) { + patch_handlers_.push_back(std::make_pair(std::regex(pattern), handler)); + return *this; +} + +inline Server &Server::Delete(const char *pattern, Handler handler) { + delete_handlers_.push_back(std::make_pair(std::regex(pattern), handler)); + return *this; +} + +inline Server &Server::Options(const char *pattern, Handler handler) { + options_handlers_.push_back(std::make_pair(std::regex(pattern), handler)); + return *this; +} + +inline bool Server::set_base_dir(const char *path) { + if (detail::is_dir(path)) { + base_dir_ = path; + return true; + } + return false; +} + +inline void Server::set_error_handler(Handler handler) { + error_handler_ = handler; +} + +inline void Server::set_logger(Logger logger) { logger_ = logger; } + +inline void Server::set_keep_alive_max_count(size_t count) { + keep_alive_max_count_ = count; +} + +inline void Server::set_payload_max_length(uint64_t length) { + payload_max_length_ = length; +} + +inline int Server::bind_to_any_port(const char *host, int socket_flags) { + return bind_internal(host, 0, socket_flags); +} + +inline bool Server::listen_after_bind() { return listen_internal(); } + +inline bool Server::listen(const char *host, int port, int socket_flags) { + if (bind_internal(host, port, socket_flags) < 0) return false; + return listen_internal(); +} + +inline bool Server::is_running() const { return is_running_; } + +inline void Server::stop() { + if (is_running_) { + assert(svr_sock_ != INVALID_SOCKET); + std::atomic sock(svr_sock_.exchange(INVALID_SOCKET)); + detail::shutdown_socket(sock); + detail::close_socket(sock); + } +} + +inline bool Server::parse_request_line(const char *s, Request &req) { + static std::regex re("(GET|HEAD|POST|PUT|PATCH|DELETE|OPTIONS) " + "(([^?]+)(?:\\?(.+?))?) (HTTP/1\\.[01])\r\n"); + + std::cmatch m; + if (std::regex_match(s, m, re)) { + req.version = std::string(m[5]); + req.method = std::string(m[1]); + req.target = std::string(m[2]); + req.path = detail::decode_url(m[3]); + + // Parse query text + auto len = std::distance(m[4].first, m[4].second); + if (len > 0) { detail::parse_query_text(m[4], req.params); } + + return true; + } + + return false; +} + +inline void Server::write_response(Stream &strm, bool last_connection, + const Request &req, Response &res) { + assert(res.status != -1); + + if (400 <= res.status && error_handler_) { error_handler_(req, res); } + + // Response line + strm.write_format("HTTP/1.1 %d %s\r\n", res.status, + detail::status_message(res.status)); + + // Headers + if (last_connection || req.get_header_value("Connection") == "close") { + res.set_header("Connection", "close"); + } + + if (!last_connection && req.get_header_value("Connection") == "Keep-Alive") { + res.set_header("Connection", "Keep-Alive"); + } + + if (res.body.empty()) { + if (!res.has_header("Content-Length")) { + if (res.content_producer) { + // Streamed response + res.set_header("Transfer-Encoding", "chunked"); + } else { + res.set_header("Content-Length", "0"); + } + } + } else { +#ifdef CPPHTTPLIB_ZLIB_SUPPORT + // TODO: 'Accpet-Encoding' has gzip, not gzip;q=0 + const auto &encodings = req.get_header_value("Accept-Encoding"); + if (encodings.find("gzip") != std::string::npos && + detail::can_compress(res.get_header_value("Content-Type"))) { + if (detail::compress(res.body)) { + res.set_header("Content-Encoding", "gzip"); + } + } +#endif + + if (!res.has_header("Content-Type")) { + res.set_header("Content-Type", "text/plain"); + } + + auto length = std::to_string(res.body.size()); + res.set_header("Content-Length", length.c_str()); + } + + detail::write_headers(strm, res); + + // Body + if (req.method != "HEAD") { + if (!res.body.empty()) { + strm.write(res.body.c_str(), res.body.size()); + } else if (res.content_producer) { + detail::write_content_chunked(strm, res); + } + } + + // Log + if (logger_) { logger_(req, res); } +} + +inline bool Server::handle_file_request(Request &req, Response &res) { + if (!base_dir_.empty() && detail::is_valid_path(req.path)) { + std::string path = base_dir_ + req.path; + + if (!path.empty() && path.back() == '/') { path += "index.html"; } + + if (detail::is_file(path)) { + detail::read_file(path, res.body); + auto type = detail::find_content_type(path); + if (type) { res.set_header("Content-Type", type); } + res.status = 200; + return true; + } + } + + return false; +} + +inline socket_t Server::create_server_socket(const char *host, int port, + int socket_flags) const { + return detail::create_socket( + host, port, + [](socket_t sock, struct addrinfo &ai) -> bool { + if (::bind(sock, ai.ai_addr, static_cast(ai.ai_addrlen))) { + return false; + } + if (::listen(sock, 5)) { // Listen through 5 channels + return false; + } + return true; + }, + socket_flags); +} + +inline int Server::bind_internal(const char *host, int port, int socket_flags) { + if (!is_valid()) { return -1; } + + svr_sock_ = create_server_socket(host, port, socket_flags); + if (svr_sock_ == INVALID_SOCKET) { return -1; } + + if (port == 0) { + struct sockaddr_storage address; + socklen_t len = sizeof(address); + if (getsockname(svr_sock_, reinterpret_cast(&address), + &len) == -1) { + return -1; + } + if (address.ss_family == AF_INET) { + return ntohs(reinterpret_cast(&address)->sin_port); + } else if (address.ss_family == AF_INET6) { + return ntohs( + reinterpret_cast(&address)->sin6_port); + } else { + return -1; + } + } else { + return port; + } +} + +inline bool Server::listen_internal() { + auto ret = true; + + is_running_ = true; + + for (;;) { + if (svr_sock_ == INVALID_SOCKET) { + // The server socket was closed by 'stop' method. + break; + } + + auto val = detail::select_read(svr_sock_, 0, 100000); + + if (val == 0) { // Timeout + continue; + } + + socket_t sock = accept(svr_sock_, nullptr, nullptr); + + if (sock == INVALID_SOCKET) { + if (svr_sock_ != INVALID_SOCKET) { + detail::close_socket(svr_sock_); + ret = false; + } else { + ; // The server socket was closed by user. + } + break; + } + + // TODO: Use thread pool... + std::thread([=]() { + { + std::lock_guard guard(running_threads_mutex_); + running_threads_++; + } + + read_and_close_socket(sock); + + { + std::lock_guard guard(running_threads_mutex_); + running_threads_--; + } + }).detach(); + } + + // TODO: Use thread pool... + for (;;) { + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + std::lock_guard guard(running_threads_mutex_); + if (!running_threads_) { break; } + } + + is_running_ = false; + + return ret; +} + +inline bool Server::routing(Request &req, Response &res) { + if (req.method == "GET" && handle_file_request(req, res)) { return true; } + + if (req.method == "GET" || req.method == "HEAD") { + return dispatch_request(req, res, get_handlers_); + } else if (req.method == "POST") { + return dispatch_request(req, res, post_handlers_); + } else if (req.method == "PUT") { + return dispatch_request(req, res, put_handlers_); + } else if (req.method == "PATCH") { + return dispatch_request(req, res, patch_handlers_); + } else if (req.method == "DELETE") { + return dispatch_request(req, res, delete_handlers_); + } else if (req.method == "OPTIONS") { + return dispatch_request(req, res, options_handlers_); + } + return false; +} + +inline bool Server::dispatch_request(Request &req, Response &res, + Handlers &handlers) { + for (const auto &x : handlers) { + const auto &pattern = x.first; + const auto &handler = x.second; + + if (std::regex_match(req.path, req.matches, pattern)) { + handler(req, res); + return true; + } + } + return false; +} + +inline bool +Server::process_request(Stream &strm, bool last_connection, + bool &connection_close, + std::function setup_request) { + const auto bufsiz = 2048; + char buf[bufsiz]; + + detail::stream_line_reader reader(strm, buf, bufsiz); + + // Connection has been closed on client + if (!reader.getline()) { return false; } + + Request req; + Response res; + + res.version = "HTTP/1.1"; + + // Check if the request URI doesn't exceed the limit + if (reader.size() > CPPHTTPLIB_REQUEST_URI_MAX_LENGTH) { + res.status = 414; + write_response(strm, last_connection, req, res); + return true; + } + + // Request line and headers + if (!parse_request_line(reader.ptr(), req) || + !detail::read_headers(strm, req.headers)) { + res.status = 400; + write_response(strm, last_connection, req, res); + return true; + } + + if (req.get_header_value("Connection") == "close") { + connection_close = true; + } + + req.set_header("REMOTE_ADDR", strm.get_remote_addr().c_str()); + + // Body + if (req.method == "POST" || req.method == "PUT" || req.method == "PATCH") { + if (!detail::read_content( + strm, req, payload_max_length_, res.status, Progress(), + [&](const char *buf, size_t n) { req.body.append(buf, n); })) { + write_response(strm, last_connection, req, res); + return true; + } + + const auto &content_type = req.get_header_value("Content-Type"); + + if (!content_type.find("application/x-www-form-urlencoded")) { + detail::parse_query_text(req.body, req.params); + } else if (!content_type.find("multipart/form-data")) { + std::string boundary; + if (!detail::parse_multipart_boundary(content_type, boundary) || + !detail::parse_multipart_formdata(boundary, req.body, req.files)) { + res.status = 400; + write_response(strm, last_connection, req, res); + return true; + } + } + } + + // TODO: Add additional request info + if (setup_request) { setup_request(req); } + + if (routing(req, res)) { + if (res.status == -1) { res.status = 200; } + } else { + res.status = 404; + } + + write_response(strm, last_connection, req, res); + return true; +} + +inline bool Server::is_valid() const { return true; } + +inline bool Server::read_and_close_socket(socket_t sock) { + return detail::read_and_close_socket( + sock, keep_alive_max_count_, + [this](Stream &strm, bool last_connection, bool &connection_close) { + return process_request(strm, last_connection, connection_close); + }); +} + +// HTTP client implementation +inline Client::Client(const char *host, int port, time_t timeout_sec) + : host_(host), port_(port), timeout_sec_(timeout_sec), + host_and_port_(host_ + ":" + std::to_string(port_)) {} + +inline Client::~Client() {} + +inline bool Client::is_valid() const { return true; } + +inline socket_t Client::create_client_socket() const { + return detail::create_socket( + host_.c_str(), port_, [=](socket_t sock, struct addrinfo &ai) -> bool { + detail::set_nonblocking(sock, true); + + auto ret = connect(sock, ai.ai_addr, static_cast(ai.ai_addrlen)); + if (ret < 0) { + if (detail::is_connection_error() || + !detail::wait_until_socket_is_ready(sock, timeout_sec_, 0)) { + detail::close_socket(sock); + return false; + } + } + + detail::set_nonblocking(sock, false); + return true; + }); +} + +inline bool Client::read_response_line(Stream &strm, Response &res) { + const auto bufsiz = 2048; + char buf[bufsiz]; + + detail::stream_line_reader reader(strm, buf, bufsiz); + + if (!reader.getline()) { return false; } + + const static std::regex re("(HTTP/1\\.[01]) (\\d+?) .*\r\n"); + + std::cmatch m; + if (std::regex_match(reader.ptr(), m, re)) { + res.version = std::string(m[1]); + res.status = std::stoi(std::string(m[2])); + } + + return true; +} + +inline bool Client::send(Request &req, Response &res) { + if (req.path.empty()) { return false; } + + auto sock = create_client_socket(); + if (sock == INVALID_SOCKET) { return false; } + + return read_and_close_socket(sock, req, res); +} + +inline void Client::write_request(Stream &strm, Request &req) { + BufferStream bstrm; + + // Request line + auto path = detail::encode_url(req.path); + + bstrm.write_format("%s %s HTTP/1.1\r\n", req.method.c_str(), path.c_str()); + + // Headers + if (!req.has_header("Host")) { + if (is_ssl()) { + if (port_ == 443) { + req.set_header("Host", host_.c_str()); + } else { + req.set_header("Host", host_and_port_.c_str()); + } + } else { + if (port_ == 80) { + req.set_header("Host", host_.c_str()); + } else { + req.set_header("Host", host_and_port_.c_str()); + } + } + } + + if (!req.has_header("Accept")) { req.set_header("Accept", "*/*"); } + + if (!req.has_header("User-Agent")) { + req.set_header("User-Agent", "cpp-httplib/0.2"); + } + + // TODO: Support KeepAlive connection + // if (!req.has_header("Connection")) { + req.set_header("Connection", "close"); + // } + + if (req.body.empty()) { + if (req.method == "POST" || req.method == "PUT" || req.method == "PATCH") { + req.set_header("Content-Length", "0"); + } + } else { + if (!req.has_header("Content-Type")) { + req.set_header("Content-Type", "text/plain"); + } + + if (!req.has_header("Content-Length")) { + auto length = std::to_string(req.body.size()); + req.set_header("Content-Length", length.c_str()); + } + } + + detail::write_headers(bstrm, req); + + // Body + if (!req.body.empty()) { bstrm.write(req.body.c_str(), req.body.size()); } + + // Flush buffer + auto &data = bstrm.get_buffer(); + strm.write(data.data(), data.size()); +} + +inline bool Client::process_request(Stream &strm, Request &req, Response &res, + bool &connection_close) { + // Send request + write_request(strm, req); + + // Receive response and headers + if (!read_response_line(strm, res) || + !detail::read_headers(strm, res.headers)) { + return false; + } + + if (res.get_header_value("Connection") == "close" || + res.version == "HTTP/1.0") { + connection_close = true; + } + + // Body + if (req.method != "HEAD") { + ContentReceiver out = [&](const char *buf, size_t n) { + res.body.append(buf, n); + }; + + if (res.content_receiver) { + out = [&](const char *buf, size_t n) { res.content_receiver(buf, n); }; + } + + int dummy_status; + if (!detail::read_content(strm, res, std::numeric_limits::max(), + dummy_status, res.progress, out)) { + return false; + } + } + + return true; +} + +inline bool Client::read_and_close_socket(socket_t sock, Request &req, + Response &res) { + return detail::read_and_close_socket( + sock, 0, + [&](Stream &strm, bool /*last_connection*/, bool &connection_close) { + return process_request(strm, req, res, connection_close); + }); +} + +inline bool Client::is_ssl() const { return false; } + +inline std::shared_ptr Client::Get(const char *path, + Progress progress) { + return Get(path, Headers(), progress); +} + +inline std::shared_ptr +Client::Get(const char *path, const Headers &headers, Progress progress) { + Request req; + req.method = "GET"; + req.path = path; + req.headers = headers; + + auto res = std::make_shared(); + res->progress = progress; + + return send(req, *res) ? res : nullptr; +} + +inline std::shared_ptr Client::Get(const char *path, + ContentReceiver content_receiver, + Progress progress) { + return Get(path, Headers(), content_receiver, progress); +} + +inline std::shared_ptr Client::Get(const char *path, + const Headers &headers, + ContentReceiver content_receiver, + Progress progress) { + Request req; + req.method = "GET"; + req.path = path; + req.headers = headers; + + auto res = std::make_shared(); + res->content_receiver = content_receiver; + res->progress = progress; + + return send(req, *res) ? res : nullptr; +} + +inline std::shared_ptr Client::Head(const char *path) { + return Head(path, Headers()); +} + +inline std::shared_ptr Client::Head(const char *path, + const Headers &headers) { + Request req; + req.method = "HEAD"; + req.headers = headers; + req.path = path; + + auto res = std::make_shared(); + + return send(req, *res) ? res : nullptr; +} + +inline std::shared_ptr Client::Post(const char *path, + const std::string &body, + const char *content_type) { + return Post(path, Headers(), body, content_type); +} + +inline std::shared_ptr Client::Post(const char *path, + const Headers &headers, + const std::string &body, + const char *content_type) { + Request req; + req.method = "POST"; + req.headers = headers; + req.path = path; + + req.headers.emplace("Content-Type", content_type); + req.body = body; + + auto res = std::make_shared(); + + return send(req, *res) ? res : nullptr; +} + +inline std::shared_ptr Client::Post(const char *path, + const Params ¶ms) { + return Post(path, Headers(), params); +} + +inline std::shared_ptr +Client::Post(const char *path, const Headers &headers, const Params ¶ms) { + std::string query; + for (auto it = params.begin(); it != params.end(); ++it) { + if (it != params.begin()) { query += "&"; } + query += it->first; + query += "="; + query += detail::encode_url(it->second); + } + + return Post(path, headers, query, "application/x-www-form-urlencoded"); +} + +inline std::shared_ptr Client::Put(const char *path, + const std::string &body, + const char *content_type) { + return Put(path, Headers(), body, content_type); +} + +inline std::shared_ptr Client::Put(const char *path, + const Headers &headers, + const std::string &body, + const char *content_type) { + Request req; + req.method = "PUT"; + req.headers = headers; + req.path = path; + + req.headers.emplace("Content-Type", content_type); + req.body = body; + + auto res = std::make_shared(); + + return send(req, *res) ? res : nullptr; +} + +inline std::shared_ptr Client::Patch(const char *path, + const std::string &body, + const char *content_type) { + return Patch(path, Headers(), body, content_type); +} + +inline std::shared_ptr Client::Patch(const char *path, + const Headers &headers, + const std::string &body, + const char *content_type) { + Request req; + req.method = "PATCH"; + req.headers = headers; + req.path = path; + + req.headers.emplace("Content-Type", content_type); + req.body = body; + + auto res = std::make_shared(); + + return send(req, *res) ? res : nullptr; +} + +inline std::shared_ptr Client::Delete(const char *path, + const std::string &body, + const char *content_type) { + return Delete(path, Headers(), body, content_type); +} + +inline std::shared_ptr Client::Delete(const char *path, + const Headers &headers, + const std::string &body, + const char *content_type) { + Request req; + req.method = "DELETE"; + req.headers = headers; + req.path = path; + + if (content_type) { req.headers.emplace("Content-Type", content_type); } + req.body = body; + + auto res = std::make_shared(); + + return send(req, *res) ? res : nullptr; +} + +inline std::shared_ptr Client::Options(const char *path) { + return Options(path, Headers()); +} + +inline std::shared_ptr Client::Options(const char *path, + const Headers &headers) { + Request req; + req.method = "OPTIONS"; + req.path = path; + req.headers = headers; + + auto res = std::make_shared(); + + return send(req, *res) ? res : nullptr; +} + +/* + * SSL Implementation + */ +#ifdef CPPHTTPLIB_OPENSSL_SUPPORT +namespace detail { + +template +inline bool +read_and_close_socket_ssl(socket_t sock, size_t keep_alive_max_count, + // TODO: OpenSSL 1.0.2 occasionally crashes... + // The upcoming 1.1.0 is going to be thread safe. + SSL_CTX *ctx, std::mutex &ctx_mutex, + U SSL_connect_or_accept, V setup, T callback) { + SSL *ssl = nullptr; + { + std::lock_guard guard(ctx_mutex); + ssl = SSL_new(ctx); + } + + if (!ssl) { + close_socket(sock); + return false; + } + + auto bio = BIO_new_socket(sock, BIO_NOCLOSE); + SSL_set_bio(ssl, bio, bio); + + if (!setup(ssl)) { + SSL_shutdown(ssl); + { + std::lock_guard guard(ctx_mutex); + SSL_free(ssl); + } + + close_socket(sock); + return false; + } + + bool ret = false; + + if (SSL_connect_or_accept(ssl) == 1) { + if (keep_alive_max_count > 0) { + auto count = keep_alive_max_count; + while (count > 0 && + detail::select_read(sock, CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND, + CPPHTTPLIB_KEEPALIVE_TIMEOUT_USECOND) > 0) { + SSLSocketStream strm(sock, ssl); + auto last_connection = count == 1; + auto connection_close = false; + + ret = callback(ssl, strm, last_connection, connection_close); + if (!ret || connection_close) { break; } + + count--; + } + } else { + SSLSocketStream strm(sock, ssl); + auto dummy_connection_close = false; + ret = callback(ssl, strm, true, dummy_connection_close); + } + } + + SSL_shutdown(ssl); + { + std::lock_guard guard(ctx_mutex); + SSL_free(ssl); + } + + close_socket(sock); + + return ret; +} + +class SSLInit { +public: + SSLInit() { + SSL_load_error_strings(); + SSL_library_init(); + } + + ~SSLInit() { ERR_free_strings(); } +}; + +static SSLInit sslinit_; + +} // namespace detail + +// SSL socket stream implementation +inline SSLSocketStream::SSLSocketStream(socket_t sock, SSL *ssl) + : sock_(sock), ssl_(ssl) {} + +inline SSLSocketStream::~SSLSocketStream() {} + +inline int SSLSocketStream::read(char *ptr, size_t size) { + if (SSL_pending(ssl_) > 0 || + detail::select_read(sock_, CPPHTTPLIB_READ_TIMEOUT_SECOND, + CPPHTTPLIB_READ_TIMEOUT_USECOND) > 0) { + return SSL_read(ssl_, ptr, size); + } + return -1; +} + +inline int SSLSocketStream::write(const char *ptr, size_t size) { + return SSL_write(ssl_, ptr, size); +} + +inline int SSLSocketStream::write(const char *ptr) { + return write(ptr, strlen(ptr)); +} + +inline std::string SSLSocketStream::get_remote_addr() const { + return detail::get_remote_addr(sock_); +} + +// SSL HTTP server implementation +inline SSLServer::SSLServer(const char *cert_path, const char *private_key_path, + const char *client_ca_cert_file_path, + const char *client_ca_cert_dir_path) { + ctx_ = SSL_CTX_new(SSLv23_server_method()); + + if (ctx_) { + SSL_CTX_set_options(ctx_, + SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | + SSL_OP_NO_COMPRESSION | + SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); + + // auto ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + // SSL_CTX_set_tmp_ecdh(ctx_, ecdh); + // EC_KEY_free(ecdh); + + if (SSL_CTX_use_certificate_chain_file(ctx_, cert_path) != 1 || + SSL_CTX_use_PrivateKey_file(ctx_, private_key_path, SSL_FILETYPE_PEM) != + 1) { + SSL_CTX_free(ctx_); + ctx_ = nullptr; + } else if (client_ca_cert_file_path || client_ca_cert_dir_path) { + // if (client_ca_cert_file_path) { + // auto list = SSL_load_client_CA_file(client_ca_cert_file_path); + // SSL_CTX_set_client_CA_list(ctx_, list); + // } + + SSL_CTX_load_verify_locations(ctx_, client_ca_cert_file_path, + client_ca_cert_dir_path); + + SSL_CTX_set_verify( + ctx_, + SSL_VERIFY_PEER | + SSL_VERIFY_FAIL_IF_NO_PEER_CERT, // SSL_VERIFY_CLIENT_ONCE, + nullptr); + } + } +} + +inline SSLServer::~SSLServer() { + if (ctx_) { SSL_CTX_free(ctx_); } +} + +inline bool SSLServer::is_valid() const { return ctx_; } + +inline bool SSLServer::read_and_close_socket(socket_t sock) { + return detail::read_and_close_socket_ssl( + sock, keep_alive_max_count_, ctx_, ctx_mutex_, SSL_accept, + [](SSL * /*ssl*/) { return true; }, + [this](SSL *ssl, Stream &strm, bool last_connection, + bool &connection_close) { + return process_request(strm, last_connection, connection_close, + [&](Request &req) { req.ssl = ssl; }); + }); +} + +// SSL HTTP client implementation +inline SSLClient::SSLClient(const char *host, int port, time_t timeout_sec, + const char *client_cert_path, + const char *client_key_path) + : Client(host, port, timeout_sec) { + ctx_ = SSL_CTX_new(SSLv23_client_method()); + + detail::split(&host_[0], &host_[host_.size()], '.', + [&](const char *b, const char *e) { + host_components_.emplace_back(std::string(b, e)); + }); + if (client_cert_path && client_key_path) { + if (SSL_CTX_use_certificate_file(ctx_, client_cert_path, + SSL_FILETYPE_PEM) != 1 || + SSL_CTX_use_PrivateKey_file(ctx_, client_key_path, SSL_FILETYPE_PEM) != + 1) { + SSL_CTX_free(ctx_); + ctx_ = nullptr; + } + } +} + +inline SSLClient::~SSLClient() { + if (ctx_) { SSL_CTX_free(ctx_); } +} + +inline bool SSLClient::is_valid() const { return ctx_; } + +inline void SSLClient::set_ca_cert_path(const char *ca_cert_file_path, + const char *ca_cert_dir_path) { + if (ca_cert_file_path) { ca_cert_file_path_ = ca_cert_file_path; } + if (ca_cert_dir_path) { ca_cert_dir_path_ = ca_cert_dir_path; } +} + +inline void SSLClient::enable_server_certificate_verification(bool enabled) { + server_certificate_verification_ = enabled; +} + +inline long SSLClient::get_openssl_verify_result() const { + return verify_result_; +} + +inline bool SSLClient::read_and_close_socket(socket_t sock, Request &req, + Response &res) { + + return is_valid() && + detail::read_and_close_socket_ssl( + sock, 0, ctx_, ctx_mutex_, + [&](SSL *ssl) { + if (ca_cert_file_path_.empty()) { + SSL_CTX_set_verify(ctx_, SSL_VERIFY_NONE, nullptr); + } else { + if (!SSL_CTX_load_verify_locations( + ctx_, ca_cert_file_path_.c_str(), nullptr)) { + return false; + } + SSL_CTX_set_verify(ctx_, SSL_VERIFY_PEER, nullptr); + } + + if (SSL_connect(ssl) != 1) { return false; } + + if (server_certificate_verification_) { + verify_result_ = SSL_get_verify_result(ssl); + + if (verify_result_ != X509_V_OK) { return false; } + + auto server_cert = SSL_get_peer_certificate(ssl); + + if (server_cert == nullptr) { return false; } + + if (!verify_host(server_cert)) { + X509_free(server_cert); + return false; + } + X509_free(server_cert); + } + + return true; + }, + [&](SSL *ssl) { + SSL_set_tlsext_host_name(ssl, host_.c_str()); + return true; + }, + [&](SSL * /*ssl*/, Stream &strm, bool /*last_connection*/, + bool &connection_close) { + return process_request(strm, req, res, connection_close); + }); +} + +inline bool SSLClient::is_ssl() const { return true; } + +inline bool SSLClient::verify_host(X509 *server_cert) const { + /* Quote from RFC2818 section 3.1 "Server Identity" + + If a subjectAltName extension of type dNSName is present, that MUST + be used as the identity. Otherwise, the (most specific) Common Name + field in the Subject field of the certificate MUST be used. Although + the use of the Common Name is existing practice, it is deprecated and + Certification Authorities are encouraged to use the dNSName instead. + + Matching is performed using the matching rules specified by + [RFC2459]. If more than one identity of a given type is present in + the certificate (e.g., more than one dNSName name, a match in any one + of the set is considered acceptable.) Names may contain the wildcard + character * which is considered to match any single domain name + component or component fragment. E.g., *.a.com matches foo.a.com but + not bar.foo.a.com. f*.com matches foo.com but not bar.com. + + In some cases, the URI is specified as an IP address rather than a + hostname. In this case, the iPAddress subjectAltName must be present + in the certificate and must exactly match the IP in the URI. + + */ + return verify_host_with_subject_alt_name(server_cert) || + verify_host_with_common_name(server_cert); +} + +inline bool +SSLClient::verify_host_with_subject_alt_name(X509 *server_cert) const { + auto ret = false; + + auto type = GEN_DNS; + + struct in6_addr addr6; + struct in_addr addr; + size_t addr_len = 0; + + if (inet_pton(AF_INET6, host_.c_str(), &addr6)) { + type = GEN_IPADD; + addr_len = sizeof(struct in6_addr); + } else if (inet_pton(AF_INET, host_.c_str(), &addr)) { + type = GEN_IPADD; + addr_len = sizeof(struct in_addr); + } + + auto alt_names = static_cast( + X509_get_ext_d2i(server_cert, NID_subject_alt_name, nullptr, nullptr)); + + if (alt_names) { + auto dsn_matched = false; + auto ip_mached = false; + + auto count = sk_GENERAL_NAME_num(alt_names); + + for (auto i = 0; i < count && !dsn_matched; i++) { + auto val = sk_GENERAL_NAME_value(alt_names, i); + if (val->type == type) { + auto name = (const char *)ASN1_STRING_get0_data(val->d.ia5); + auto name_len = (size_t)ASN1_STRING_length(val->d.ia5); + + if (strlen(name) == name_len) { + switch (type) { + case GEN_DNS: dsn_matched = check_host_name(name, name_len); break; + + case GEN_IPADD: + if (!memcmp(&addr6, name, addr_len) || + !memcmp(&addr, name, addr_len)) { + ip_mached = true; + } + break; + } + } + } + } + + if (dsn_matched || ip_mached) { ret = true; } + } + + GENERAL_NAMES_free((STACK_OF(GENERAL_NAME) *)alt_names); + + return ret; +} + +inline bool SSLClient::verify_host_with_common_name(X509 *server_cert) const { + const auto subject_name = X509_get_subject_name(server_cert); + + if (subject_name != nullptr) { + char name[BUFSIZ]; + auto name_len = X509_NAME_get_text_by_NID(subject_name, NID_commonName, + name, sizeof(name)); + + if (name_len != -1) { return check_host_name(name, name_len); } + } + + return false; +} + +inline bool SSLClient::check_host_name(const char *pattern, + size_t pattern_len) const { + if (host_.size() == pattern_len && host_ == pattern) { return true; } + + // Wildcard match + // https://bugs.launchpad.net/ubuntu/+source/firefox-3.0/+bug/376484 + std::vector pattern_components; + detail::split(&pattern[0], &pattern[pattern_len], '.', + [&](const char *b, const char *e) { + pattern_components.emplace_back(std::string(b, e)); + }); + + if (host_components_.size() != pattern_components.size()) { return false; } + + auto itr = pattern_components.begin(); + for (const auto &h : host_components_) { + auto &p = *itr; + if (p != h && p != "*") { + auto partial_match = (p.size() > 0 && p[p.size() - 1] == '*' && + !p.compare(0, p.size() - 1, h)); + if (!partial_match) { return false; } + } + ++itr; + } + + return true; +} +#endif + +} // namespace httplib + +#endif // CPPHTTPLIB_HTTPLIB_H From 9cf74657e0f2af93cc7ff051895afd2ea7d4a5d6 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Mon, 22 Jul 2019 14:12:21 -0700 Subject: [PATCH 057/185] Commented out rtnetlink error debug trace --- osdep/LinuxNetLink.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osdep/LinuxNetLink.cpp b/osdep/LinuxNetLink.cpp index 6bebfe2e..da75ccdf 100644 --- a/osdep/LinuxNetLink.cpp +++ b/osdep/LinuxNetLink.cpp @@ -124,9 +124,9 @@ int LinuxNetLink::_doRecv(int fd) if(nlp->nlmsg_type == NLMSG_ERROR && (nlp->nlmsg_flags & NLM_F_ACK) != NLM_F_ACK) { struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(nlp); if (err->error != 0) { -//#ifdef ZT_TRACE - fprintf(stderr, "rtnetlink error: %s\n", strerror(-(err->error))); -//#endif +#ifdef ZT_TRACE + //fprintf(stderr, "rtnetlink error: %s\n", strerror(-(err->error))); +#endif } p = buf; nll = 0; From 8a0b75c83a839d7c35f63ffc18197854055f77fa Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Mon, 22 Jul 2019 15:24:16 -0700 Subject: [PATCH 058/185] Added LFDB.o to objects.mk --- objects.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/objects.mk b/objects.mk index eb348dca..fcda13fd 100644 --- a/objects.mk +++ b/objects.mk @@ -30,6 +30,7 @@ ONE_OBJS=\ controller/EmbeddedNetworkController.o \ controller/DB.o \ controller/FileDB.o \ + controller/LFDB.o \ controller/PostgreSQL.o \ controller/RabbitMQ.o \ osdep/ManagedRoute.o \ From d4d350a2850aaf78b9abc443e41eaa75e626045d Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 23 Jul 2019 09:29:08 -0700 Subject: [PATCH 059/185] Work in progress --- controller/EmbeddedNetworkController.cpp | 4 +- controller/LFDB.cpp | 85 +++++++++++++++++++++--- controller/LFDB.hpp | 12 ++++ objects.mk | 1 + 4 files changed, 91 insertions(+), 11 deletions(-) diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index 007a4112..3ebdccf9 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -501,12 +501,12 @@ void EmbeddedNetworkController::init(const Identity &signingId,Sender *sender) #endif std::string lfJSON; - OSUtils::readFile((_path + ZT_PATH_SEPARATOR_S "local.conf").c_str(),lfJSON); + OSUtils::readFile((_path + ZT_PATH_SEPARATOR_S ".." ZT_PATH_SEPARATOR_S "local.conf").c_str(),lfJSON); if (lfJSON.length() > 0) { nlohmann::json lfConfig(OSUtils::jsonParse(lfJSON)); nlohmann::json &settings = lfConfig["settings"]; if (settings.is_object()) { - nlohmann::json &controllerDb = lfConfig["controllerDb"]; + nlohmann::json &controllerDb = settings["controllerDb"]; if (controllerDb.is_object()) { std::string type = controllerDb["type"]; if (type == "lf") { diff --git a/controller/LFDB.cpp b/controller/LFDB.cpp index 82858b50..9404f310 100644 --- a/controller/LFDB.cpp +++ b/controller/LFDB.cpp @@ -27,6 +27,7 @@ #include "LFDB.hpp" #include +#include #include #include @@ -53,30 +54,95 @@ LFDB::LFDB(EmbeddedNetworkController *const nc,const Identity &myId,const char * _myId.address().toString(controllerAddress); httplib::Client htcli(_lfNodeHost.c_str(),_lfNodePort,600); + std::ostringstream query; + int64_t timeRangeStart = 0; while (_running) { - std::ostringstream query; + query.clear(); query << '{' << "\"Ranges\":[{" - << "\"Name\": \"com.zerotier.controller.lfdb:" << controllerAddress << "\"" + << "\"Name\": \"com.zerotier.controller.lfdb:" << controllerAddress << "/network\"," + << "\"Range\": [ 0,18446744073709551615 ]" << "}]," + << "\"TimeRange\": [ " << timeRangeStart << ",18446744073709551615 ]," << "\"MaskingKey\":\"" << controllerAddress << "\"," - << "\"Owners\":[\"" << _lfOwnerPublic << "\"]," - << "\"Open\":true" + << "\"Owners\":[\"" << _lfOwnerPublic << "\"]" << '}'; auto resp = htcli.Post("/query",query.str(),"application/json"); if (resp->status == 200) { - fprintf(stderr,"%d %s\n",resp->status,resp->body.c_str()); + nlohmann::json results(OSUtils::jsonParse(resp->body)); + if ((results.is_array())&&(results.size() > 0)) { + for(std::size_t ri=0;ri 0)) { + nlohmann::json &result = rset[0]; + if (result.is_object()) { + nlohmann::json &record = result["Record"]; + if (record.is_object()) { + int64_t ts = record["Timestamp"]; + std::string value = result["Value"]; + nlohmann::json network(OSUtils::jsonParse(value)); + if (network.is_object()) { + std::string idstr = network["id"]; + } + } + } + } + } + } } else { fprintf(stderr,"ERROR: LFDB: %d from node: %s" ZT_EOL_S,resp->status,resp->body.c_str()); } + query.clear(); + query + << '{' + << "\"Ranges\":[{" + << "\"Name\": \"com.zerotier.controller.lfdb:" << controllerAddress << "/network\"," + << "\"Range\": [ 0,18446744073709551615 ]" + << "},{" + << "\"Name\": \"com.zerotier.controller.lfdb:" << controllerAddress << "/network/member\"," + << "\"Range\": [ 0,18446744073709551615 ]" + << "}]," + << "\"TimeRange\": [ " << timeRangeStart << ",18446744073709551615 ]," + << "\"MaskingKey\":\"" << controllerAddress << "\"," + << "\"Owners\":[\"" << _lfOwnerPublic << "\"]" + << '}'; + auto resp = htcli.Post("/query",query.str(),"application/json"); + if (resp->status == 200) { + nlohmann::json results(OSUtils::jsonParse(resp->body)); + if ((results.is_array())&&(results.size() > 0)) { + for(std::size_t ri=0;ri 0)) { + nlohmann::json &result = rset[0]; + if (result.is_object()) { + nlohmann::json &record = result["Record"]; + if (record.is_object()) { + int64_t ts = record["Timestamp"]; + std::string value = result["Value"]; + nlohmann::json member(OSUtils::jsonParse(value)); + if (member.is_object()) { + std::string nwidstr = member["nwid"]; + std::string idstr = member["id"]; + } + } + } + } + } + } + } else { + fprintf(stderr,"ERROR: LFDB: %d from node: %s" ZT_EOL_S,resp->status,resp->body.c_str()); + } + + timeRangeStart = time(nullptr) - 120; // start next query 2m before now to avoid losing updates _ready = true; - for(int k=0;k<10;++k) { + // Delay 2s between queries, checking running flag every 100ms + for(int k=0;k<20;++k) { if (!_running) return; - usleep(100000); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); } } }); @@ -90,8 +156,9 @@ LFDB::~LFDB() bool LFDB::waitForReady() { - while (!_ready) - usleep(10000); + while (!_ready) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } } bool LFDB::isReady() diff --git a/controller/LFDB.hpp b/controller/LFDB.hpp index a01e78e6..2fcb47ba 100644 --- a/controller/LFDB.hpp +++ b/controller/LFDB.hpp @@ -73,14 +73,26 @@ protected: struct _MemberState { + _MemberState() : + lastOnlineAddress(), + lastOnlineTime(0), + recordTimestamp(0), + dirty(false), + lastOnlineDirty(false) {} InetAddress lastOnlineAddress; int64_t lastOnlineTime; + int64_t recordTimestamp; bool dirty; bool lastOnlineDirty; }; struct _NetworkState { + _NetworkState() : + members(), + recordTimestamp(0), + dirty(false) {} std::unordered_map members; + int64_t recordTimestamp; bool dirty; }; std::unordered_map _state; diff --git a/objects.mk b/objects.mk index eb348dca..fcda13fd 100644 --- a/objects.mk +++ b/objects.mk @@ -30,6 +30,7 @@ ONE_OBJS=\ controller/EmbeddedNetworkController.o \ controller/DB.o \ controller/FileDB.o \ + controller/LFDB.o \ controller/PostgreSQL.o \ controller/RabbitMQ.o \ osdep/ManagedRoute.o \ From 5f11daadf20cc92dc451d0fdd41dd930b2524e8a Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 23 Jul 2019 09:30:40 -0700 Subject: [PATCH 060/185] Build fix --- controller/LFDB.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/controller/LFDB.cpp b/controller/LFDB.cpp index 9404f310..826d7cba 100644 --- a/controller/LFDB.cpp +++ b/controller/LFDB.cpp @@ -108,7 +108,7 @@ LFDB::LFDB(EmbeddedNetworkController *const nc,const Identity &myId,const char * << "\"MaskingKey\":\"" << controllerAddress << "\"," << "\"Owners\":[\"" << _lfOwnerPublic << "\"]" << '}'; - auto resp = htcli.Post("/query",query.str(),"application/json"); + resp = htcli.Post("/query",query.str(),"application/json"); if (resp->status == 200) { nlohmann::json results(OSUtils::jsonParse(resp->body)); if ((results.is_array())&&(results.size() > 0)) { @@ -159,6 +159,7 @@ bool LFDB::waitForReady() while (!_ready) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); } + return true; } bool LFDB::isReady() From 6958ba9557f4c9969f0decd1e70c7dafb7ca6209 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Tue, 23 Jul 2019 12:39:07 -0700 Subject: [PATCH 061/185] Added ZT_DISABLE_COMPRESSION build flag for SDK and low-end NAS builds --- node/NetworkConfig.hpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp index be8c03dd..ddad52a5 100644 --- a/node/NetworkConfig.hpp +++ b/node/NetworkConfig.hpp @@ -276,10 +276,14 @@ public: */ inline bool disableCompression() const { -#ifndef ZT_SDK +#ifndef ZT_DISABLE_COMPRESSION return ((this->flags & ZT_NETWORKCONFIG_FLAG_DISABLE_COMPRESSION) != 0); #else - return false; // Compression is disabled for SDK builds since it doesn't play nice with lwIP + /* Compression is disabled for libzt builds since it causes non-obvious chaotic + interference with lwIP's TCP congestion algorithm. Compression is also disabled + for some NAS builds due to the usage of low-performance processors in certain + older and budget models. */ + return false; #endif } From d2af12b6a0bd37bdecd1edbdfdfda37e082f8844 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Tue, 23 Jul 2019 13:33:25 -0700 Subject: [PATCH 062/185] Forgot to add ZT_DISABLE_COMPRESSION to linux makefile --- make-linux.mk | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/make-linux.mk b/make-linux.mk index d0745fe9..b777f67e 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -96,6 +96,10 @@ ifeq ($(ZT_SYNOLOGY), 1) override DEFS+=-D__SYNOLOGY__ endif +ifeq ($(ZT_DISABLE_COMPRESSION), 1) + override DEFS+=-DZT_DISABLE_COMPRESSION +endif + ifeq ($(ZT_TRACE),1) override DEFS+=-DZT_TRACE endif From ac2688de5853160a1d4afb02395488594e6cca8e Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 23 Jul 2019 16:06:35 -0700 Subject: [PATCH 063/185] More LFDB work --- controller/LFDB.cpp | 324 ++++++++++++++------------------------------ controller/LFDB.hpp | 7 +- 2 files changed, 100 insertions(+), 231 deletions(-) diff --git a/controller/LFDB.cpp b/controller/LFDB.cpp index 826d7cba..8779c47e 100644 --- a/controller/LFDB.cpp +++ b/controller/LFDB.cpp @@ -41,30 +41,77 @@ LFDB::LFDB(EmbeddedNetworkController *const nc,const Identity &myId,const char * DB(nc,myId,path), _nc(nc), _myId(myId), - _lfOwnerPrivate(lfOwnerPrivate), - _lfOwnerPublic(lfOwnerPublic), - _lfNodeHost(lfNodeHost), - _lfNodePort(lfNodePort), + _lfOwnerPrivate((lfOwnerPrivate) ? lfOwnerPrivate : ""), + _lfOwnerPublic((lfOwnerPublic) ? lfOwnerPublic : ""), + _lfNodeHost((lfNodeHost) ? lfNodeHost : "127.0.0.1"), + _lfNodePort(((lfNodePort > 0)&&(lfNodePort < 65536)) ? lfNodePort : 9980), _running(true), _ready(false), _storeOnlineState(storeOnlineState) { _syncThread = std::thread([this]() { char controllerAddress[24]; + const uint64_t controllerAddressInt = _myId.address().toInt(); _myId.address().toString(controllerAddress); + std::string networksSelectorName("com.zerotier.controller.lfdb:"); networksSelectorName.append(controllerAddress); networksSelectorName.append("/network"); + std::string membersSelectorName("com.zerotier.controller.lfdb:"); membersSelectorName.append(controllerAddress); membersSelectorName.append("/network/member"); httplib::Client htcli(_lfNodeHost.c_str(),_lfNodePort,600); std::ostringstream query; int64_t timeRangeStart = 0; while (_running) { + { + std::lock_guard sl(_state_l); + for(auto ns=_state.begin();ns!=_state.end();++ns) { + if (ns->second.dirty) { + nlohmann::json network; + if (get(ns->first,network)) { + nlohmann::json newrec; + newrec["Selectors"] = {{ { { "Name",networksSelectorName },{ "Ordinal",ns->first } } }}; + newrec["Value"] = network.dump(); + newrec["OwnerPrivate"] = _lfOwnerPrivate; + newrec["MaskingKey"] = controllerAddress; + auto resp = htcli.Post("/make",newrec.dump(),"application/json"); + if (resp->status == 200) { + ns->second.dirty = false; + } else { + fprintf(stderr,"ERROR: LFDB: %d from node (create/update network): %s" ZT_EOL_S,resp->status,resp->body.c_str()); + } + } + } + + for(auto ms=ns->second.members.begin();ms!=ns->second.members.end();++ms) { + if ((_storeOnlineState)&&(ms->second.lastOnlineDirty)) { + } + + if (ms->second.dirty) { + nlohmann::json network,member; + if (get(ns->first,network,ms->first,member)) { + nlohmann::json newrec; + newrec["Selectors"] = {{ { { "Name",networksSelectorName },{ "Ordinal",ns->first } },{ { "Name",membersSelectorName },{ "Ordinal",ms->first } } }}; + newrec["Value"] = member.dump(); + newrec["OwnerPrivate"] = _lfOwnerPrivate; + newrec["MaskingKey"] = controllerAddress; + auto resp = htcli.Post("/make",newrec.dump(),"application/json"); + if (resp->status == 200) { + ms->second.dirty = false; + } else { + fprintf(stderr,"ERROR: LFDB: %d from node (create/update member): %s" ZT_EOL_S,resp->status,resp->body.c_str()); + } + } + } + } + } + } + query.clear(); query << '{' << "\"Ranges\":[{" - << "\"Name\": \"com.zerotier.controller.lfdb:" << controllerAddress << "/network\"," - << "\"Range\": [ 0,18446744073709551615 ]" + << "\"Name\":\"" << networksSelectorName << "\"," + << "\"Range\":[0,18446744073709551615]" << "}]," - << "\"TimeRange\": [ " << timeRangeStart << ",18446744073709551615 ]," + << "\"TimeRange\":[" << timeRangeStart << ",18446744073709551615]," << "\"MaskingKey\":\"" << controllerAddress << "\"," << "\"Owners\":[\"" << _lfOwnerPublic << "\"]" << '}'; @@ -79,11 +126,19 @@ LFDB::LFDB(EmbeddedNetworkController *const nc,const Identity &myId,const char * if (result.is_object()) { nlohmann::json &record = result["Record"]; if (record.is_object()) { - int64_t ts = record["Timestamp"]; - std::string value = result["Value"]; - nlohmann::json network(OSUtils::jsonParse(value)); + const std::string recordValue = result["Value"]; + nlohmann::json network(OSUtils::jsonParse(recordValue)); if (network.is_object()) { - std::string idstr = network["id"]; + const std::string idstr = network["id"]; + const uint64_t id = Utils::hexStrToU64(idstr.c_str()); + if ((id >> 24) == controllerAddressInt) { + std::lock_guard sl(_state_l); + _NetworkState &ns = _state[id]; + if (!ns.dirty) { + nlohmann::json nullJson; + _networkChanged(nullJson,network,false); + } + } } } } @@ -98,13 +153,13 @@ LFDB::LFDB(EmbeddedNetworkController *const nc,const Identity &myId,const char * query << '{' << "\"Ranges\":[{" - << "\"Name\": \"com.zerotier.controller.lfdb:" << controllerAddress << "/network\"," - << "\"Range\": [ 0,18446744073709551615 ]" + << "\"Name\":\"" << networksSelectorName << "\"," + << "\"Range\":[0,18446744073709551615]" << "},{" - << "\"Name\": \"com.zerotier.controller.lfdb:" << controllerAddress << "/network/member\"," - << "\"Range\": [ 0,18446744073709551615 ]" + << "\"Name\":\"" << membersSelectorName << "\"," + << "\"Range\":[0,18446744073709551615]" << "}]," - << "\"TimeRange\": [ " << timeRangeStart << ",18446744073709551615 ]," + << "\"TimeRange\":[" << timeRangeStart << ",18446744073709551615]," << "\"MaskingKey\":\"" << controllerAddress << "\"," << "\"Owners\":[\"" << _lfOwnerPublic << "\"]" << '}'; @@ -119,12 +174,24 @@ LFDB::LFDB(EmbeddedNetworkController *const nc,const Identity &myId,const char * if (result.is_object()) { nlohmann::json &record = result["Record"]; if (record.is_object()) { - int64_t ts = record["Timestamp"]; - std::string value = result["Value"]; - nlohmann::json member(OSUtils::jsonParse(value)); + const std::string recordValue = result["Value"]; + nlohmann::json member(OSUtils::jsonParse(recordValue)); if (member.is_object()) { - std::string nwidstr = member["nwid"]; - std::string idstr = member["id"]; + const std::string nwidstr = member["nwid"]; + const std::string idstr = member["id"]; + const uint64_t nwid = Utils::hexStrToU64(nwidstr.c_str()); + const uint64_t id = Utils::hexStrToU64(idstr.c_str()); + if ((id)&&((nwid >> 24) == controllerAddressInt)) { + std::lock_guard sl(_state_l); + auto ns = _state.find(nwid); + if (ns != _state.end()) { + _MemberState &ms = ns->second.members[id]; + if (!ms.dirty) { + nlohmann::json nullJson; + _memberChanged(nullJson,member,false); + } + } + } } } } @@ -138,8 +205,7 @@ LFDB::LFDB(EmbeddedNetworkController *const nc,const Identity &myId,const char * timeRangeStart = time(nullptr) - 120; // start next query 2m before now to avoid losing updates _ready = true; - // Delay 2s between queries, checking running flag every 100ms - for(int k=0;k<20;++k) { + for(int k=0;k<20;++k) { // 2s delay between queries for remotely modified networks or members if (!_running) return; std::this_thread::sleep_for(std::chrono::milliseconds(100)); @@ -184,6 +250,11 @@ void LFDB::save(nlohmann::json *orig,nlohmann::json &record) nlohmann::json old; get(nwid,old); if ((!old.is_object())||(old != record)) { + _networkChanged(old,record,true); + { + std::lock_guard l(_state_l); + _state[nwid].dirty = true; + } } } } else if (objtype == "member") { @@ -193,6 +264,11 @@ void LFDB::save(nlohmann::json *orig,nlohmann::json &record) nlohmann::json network,old; get(nwid,network,id,old); if ((!old.is_object())||(old != record)) { + _memberChanged(old,record,true); + { + std::lock_guard l(_state_l); + _state[nwid].members[id].dirty = true; + } } } } @@ -223,206 +299,4 @@ void LFDB::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const I } } -#if 0 -FileDB::FileDB(EmbeddedNetworkController *const nc,const Identity &myId,const char *path) : - DB(nc,myId,path), - _networksPath(_path + ZT_PATH_SEPARATOR_S + "network"), - _tracePath(_path + ZT_PATH_SEPARATOR_S + "trace"), - _onlineChanged(false), - _running(true) -{ - OSUtils::mkdir(_path.c_str()); - OSUtils::lockDownFile(_path.c_str(),true); - OSUtils::mkdir(_networksPath.c_str()); - OSUtils::mkdir(_tracePath.c_str()); - - std::vector networks(OSUtils::listDirectory(_networksPath.c_str(),false)); - std::string buf; - for(auto n=networks.begin();n!=networks.end();++n) { - buf.clear(); - if ((n->length() == 21)&&(OSUtils::readFile((_networksPath + ZT_PATH_SEPARATOR_S + *n).c_str(),buf))) { - try { - nlohmann::json network(OSUtils::jsonParse(buf)); - const std::string nwids = network["id"]; - if (nwids.length() == 16) { - nlohmann::json nullJson; - _networkChanged(nullJson,network,false); - std::string membersPath(_networksPath + ZT_PATH_SEPARATOR_S + nwids + ZT_PATH_SEPARATOR_S "member"); - std::vector members(OSUtils::listDirectory(membersPath.c_str(),false)); - for(auto m=members.begin();m!=members.end();++m) { - buf.clear(); - if ((m->length() == 15)&&(OSUtils::readFile((membersPath + ZT_PATH_SEPARATOR_S + *m).c_str(),buf))) { - try { - nlohmann::json member(OSUtils::jsonParse(buf)); - const std::string addrs = member["id"]; - if (addrs.length() == 10) { - nlohmann::json nullJson2; - _memberChanged(nullJson2,member,false); - } - } catch ( ... ) {} - } - } - } - } catch ( ... ) {} - } - } - - _onlineUpdateThread = std::thread([this]() { - unsigned int cnt = 0; - while (this->_running) { - std::this_thread::sleep_for(std::chrono::microseconds(100)); - if ((++cnt % 20) == 0) { // 5 seconds - std::lock_guard l(this->_online_l); - if (!this->_running) return; - if (this->_onlineChanged) { - char p[4096],atmp[64]; - for(auto nw=this->_online.begin();nw!=this->_online.end();++nw) { - OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx-online.json",_networksPath.c_str(),(unsigned long long)nw->first); - FILE *f = fopen(p,"wb"); - if (f) { - fprintf(f,"{"); - const char *memberPrefix = ""; - for(auto m=nw->second.begin();m!=nw->second.end();++m) { - fprintf(f,"%s\"%.10llx\":{" ZT_EOL_S,memberPrefix,(unsigned long long)m->first); - memberPrefix = ","; - InetAddress lastAddr; - const char *timestampPrefix = " "; - int cnt = 0; - for(auto ts=m->second.rbegin();ts!=m->second.rend();) { - if (cnt < 25) { - if (lastAddr != ts->second) { - lastAddr = ts->second; - fprintf(f,"%s\"%lld\":\"%s\"" ZT_EOL_S,timestampPrefix,(long long)ts->first,ts->second.toString(atmp)); - timestampPrefix = ","; - ++cnt; - ++ts; - } else { - ts = std::map::reverse_iterator(m->second.erase(std::next(ts).base())); - } - } else { - ts = std::map::reverse_iterator(m->second.erase(std::next(ts).base())); - } - } - fprintf(f,"}"); - } - fprintf(f,"}" ZT_EOL_S); - fclose(f); - } - } - this->_onlineChanged = false; - } - } - } - }); -} - -FileDB::~FileDB() -{ - try { - _online_l.lock(); - _running = false; - _online_l.unlock(); - _onlineUpdateThread.join(); - } catch ( ... ) {} -} - -bool FileDB::waitForReady() { return true; } -bool FileDB::isReady() { return true; } - -void FileDB::save(nlohmann::json *orig,nlohmann::json &record) -{ - char p1[4096],p2[4096],pb[4096]; - try { - if (orig) { - if (*orig != record) { - record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1; - } - } else { - record["revision"] = 1; - } - - const std::string objtype = record["objtype"]; - if (objtype == "network") { - const uint64_t nwid = OSUtils::jsonIntHex(record["id"],0ULL); - if (nwid) { - nlohmann::json old; - get(nwid,old); - if ((!old.is_object())||(old != record)) { - OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%.16llx.json",_networksPath.c_str(),nwid); - if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) - fprintf(stderr,"WARNING: controller unable to write to path: %s" ZT_EOL_S,p1); - _networkChanged(old,record,true); - } - } - } else if (objtype == "member") { - const uint64_t id = OSUtils::jsonIntHex(record["id"],0ULL); - const uint64_t nwid = OSUtils::jsonIntHex(record["nwid"],0ULL); - if ((id)&&(nwid)) { - nlohmann::json network,old; - get(nwid,network,id,old); - if ((!old.is_object())||(old != record)) { - OSUtils::ztsnprintf(pb,sizeof(pb),"%s" ZT_PATH_SEPARATOR_S "%.16llx" ZT_PATH_SEPARATOR_S "member",_networksPath.c_str(),(unsigned long long)nwid); - OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%.10llx.json",pb,(unsigned long long)id); - if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) { - OSUtils::ztsnprintf(p2,sizeof(p2),"%s" ZT_PATH_SEPARATOR_S "%.16llx",_networksPath.c_str(),(unsigned long long)nwid); - OSUtils::mkdir(p2); - OSUtils::mkdir(pb); - if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) - fprintf(stderr,"WARNING: controller unable to write to path: %s" ZT_EOL_S,p1); - } - _memberChanged(old,record,true); - } - } - } else if (objtype == "trace") { - const std::string id = record["id"]; - if (id.length() > 0) { - OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%s.json",_tracePath.c_str(),id.c_str()); - OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1)); - } - } - } catch ( ... ) {} // drop invalid records missing fields -} - -void FileDB::eraseNetwork(const uint64_t networkId) -{ - nlohmann::json network,nullJson; - get(networkId,network); - char p[16384]; - OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx.json",_networksPath.c_str(),networkId); - OSUtils::rm(p); - OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx-online.json",_networksPath.c_str(),networkId); - OSUtils::rm(p); - OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx" ZT_PATH_SEPARATOR_S "member",_networksPath.c_str(),(unsigned long long)networkId); - OSUtils::rmDashRf(p); - _networkChanged(network,nullJson,true); - std::lock_guard l(this->_online_l); - this->_online.erase(networkId); - this->_onlineChanged = true; -} - -void FileDB::eraseMember(const uint64_t networkId,const uint64_t memberId) -{ - nlohmann::json network,member,nullJson; - get(networkId,network); - get(memberId,member); - char p[4096]; - OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx" ZT_PATH_SEPARATOR_S "member" ZT_PATH_SEPARATOR_S "%.10llx.json",_networksPath.c_str(),networkId,memberId); - OSUtils::rm(p); - _memberChanged(member,nullJson,true); - std::lock_guard l(this->_online_l); - this->_online[networkId].erase(memberId); - this->_onlineChanged = true; -} - -void FileDB::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress) -{ - char mid[32],atmp[64]; - OSUtils::ztsnprintf(mid,sizeof(mid),"%.10llx",(unsigned long long)memberId); - physicalAddress.toString(atmp); - std::lock_guard l(this->_online_l); - this->_online[networkId][memberId][OSUtils::now()] = physicalAddress; - this->_onlineChanged = true; -} -#endif - } // namespace ZeroTier diff --git a/controller/LFDB.hpp b/controller/LFDB.hpp index 2fcb47ba..6659c0bf 100644 --- a/controller/LFDB.hpp +++ b/controller/LFDB.hpp @@ -66,8 +66,7 @@ protected: EmbeddedNetworkController *const _nc; const Identity _myId; - std::string _lfOwnerPrivate; - std::string _lfOwnerPublic; + std::string _lfOwnerPrivate,_lfOwnerPublic; std::string _lfNodeHost; int _lfNodePort; @@ -76,12 +75,10 @@ protected: _MemberState() : lastOnlineAddress(), lastOnlineTime(0), - recordTimestamp(0), dirty(false), lastOnlineDirty(false) {} InetAddress lastOnlineAddress; int64_t lastOnlineTime; - int64_t recordTimestamp; bool dirty; bool lastOnlineDirty; }; @@ -89,10 +86,8 @@ protected: { _NetworkState() : members(), - recordTimestamp(0), dirty(false) {} std::unordered_map members; - int64_t recordTimestamp; bool dirty; }; std::unordered_map _state; From c8c33db1d12359e38dbe0cae80143963ea0b8c8a Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 26 Jul 2019 16:03:21 -0700 Subject: [PATCH 064/185] . --- controller/LFDB.cpp | 243 +++++++++++++++++++++++++++----------------- 1 file changed, 152 insertions(+), 91 deletions(-) diff --git a/controller/LFDB.cpp b/controller/LFDB.cpp index 8779c47e..5c5b687d 100644 --- a/controller/LFDB.cpp +++ b/controller/LFDB.cpp @@ -57,7 +57,6 @@ LFDB::LFDB(EmbeddedNetworkController *const nc,const Identity &myId,const char * std::string membersSelectorName("com.zerotier.controller.lfdb:"); membersSelectorName.append(controllerAddress); membersSelectorName.append("/network/member"); httplib::Client htcli(_lfNodeHost.c_str(),_lfNodePort,600); - std::ostringstream query; int64_t timeRangeStart = 0; while (_running) { { @@ -66,37 +65,85 @@ LFDB::LFDB(EmbeddedNetworkController *const nc,const Identity &myId,const char * if (ns->second.dirty) { nlohmann::json network; if (get(ns->first,network)) { - nlohmann::json newrec; - newrec["Selectors"] = {{ { { "Name",networksSelectorName },{ "Ordinal",ns->first } } }}; + nlohmann::json newrec,selector0; + selector0["Name"] = networksSelectorName; + selector0["Ordinal"] = ns->first; + newrec["Selectors"].push_back(selector0); newrec["Value"] = network.dump(); newrec["OwnerPrivate"] = _lfOwnerPrivate; newrec["MaskingKey"] = controllerAddress; - auto resp = htcli.Post("/make",newrec.dump(),"application/json"); - if (resp->status == 200) { - ns->second.dirty = false; + newrec["PulseIfUnchanged"] = true; + printf("%s\n",newrec.dump().c_str()); + auto resp = htcli.Post("/makerecord",newrec.dump(),"application/json"); + if (resp) { + if (resp->status == 200) { + ns->second.dirty = false; + printf("SET network %.16llx %s\n",ns->first,resp->body.c_str()); + } else { + fprintf(stderr,"ERROR: LFDB: %d from node (create/update network): %s" ZT_EOL_S,resp->status,resp->body.c_str()); + } } else { - fprintf(stderr,"ERROR: LFDB: %d from node (create/update network): %s" ZT_EOL_S,resp->status,resp->body.c_str()); + fprintf(stderr,"ERROR: LFDB: node is offline" ZT_EOL_S); } } } for(auto ms=ns->second.members.begin();ms!=ns->second.members.end();++ms) { - if ((_storeOnlineState)&&(ms->second.lastOnlineDirty)) { + if ((_storeOnlineState)&&(ms->second.lastOnlineDirty)&&(ms->second.lastOnlineAddress)) { + char tmp[1024],tmp2[128]; + OSUtils::ztsnprintf(tmp,sizeof(tmp),"com.zerotier.controller.lfdb:%s/network/%.16llx/online",controllerAddress,(unsigned long long)ns->first); + ms->second.lastOnlineAddress.toIpString(tmp2); + nlohmann::json newrec,selector0,selector1,selectors; + selector0["Name"] = tmp; + selector0["Ordinal"] = ms->first; + selector1["Name"] = tmp2; + selector1["Ordinal"] = 0; + selectors.push_back(selector0); + selectors.push_back(selector1); + newrec["Selectors"] = selectors; + newrec["Value"] = tmp2; + newrec["OwnerPrivate"] = _lfOwnerPrivate; + newrec["MaskingKey"] = controllerAddress; + newrec["Timestamp"] = ms->second.lastOnlineTime; + newrec["PulseIfUnchanged"] = true; + auto resp = htcli.Post("/makerecord",newrec.dump(),"application/json"); + if (resp) { + if (resp->status == 200) { + ms->second.lastOnlineDirty = false; + printf("SET member online %.16llx %.10llx %s\n",ns->first,ms->first,resp->body.c_str()); + } else { + fprintf(stderr,"ERROR: LFDB: %d from node (create/update member): %s" ZT_EOL_S,resp->status,resp->body.c_str()); + } + } else { + fprintf(stderr,"ERROR: LFDB: node is offline" ZT_EOL_S); + } } if (ms->second.dirty) { nlohmann::json network,member; if (get(ns->first,network,ms->first,member)) { - nlohmann::json newrec; - newrec["Selectors"] = {{ { { "Name",networksSelectorName },{ "Ordinal",ns->first } },{ { "Name",membersSelectorName },{ "Ordinal",ms->first } } }}; + nlohmann::json newrec,selector0,selector1,selectors; + selector0["Name"] = networksSelectorName; + selector0["Ordinal"] = ns->first; + selector1["Name"] = membersSelectorName; + selector1["Ordinal"] = ms->first; + selectors.push_back(selector0); + selectors.push_back(selector1); + newrec["Selectors"] = selectors; newrec["Value"] = member.dump(); newrec["OwnerPrivate"] = _lfOwnerPrivate; newrec["MaskingKey"] = controllerAddress; - auto resp = htcli.Post("/make",newrec.dump(),"application/json"); - if (resp->status == 200) { - ms->second.dirty = false; + newrec["PulseIfUnchanged"] = true; + auto resp = htcli.Post("/makerecord",newrec.dump(),"application/json"); + if (resp) { + if (resp->status == 200) { + ms->second.dirty = false; + printf("SET member %.16llx %.10llx %s\n",ns->first,ms->first,resp->body.c_str()); + } else { + fprintf(stderr,"ERROR: LFDB: %d from node (create/update member): %s" ZT_EOL_S,resp->status,resp->body.c_str()); + } } else { - fprintf(stderr,"ERROR: LFDB: %d from node (create/update member): %s" ZT_EOL_S,resp->status,resp->body.c_str()); + fprintf(stderr,"ERROR: LFDB: node is offline" ZT_EOL_S); } } } @@ -104,91 +151,103 @@ LFDB::LFDB(EmbeddedNetworkController *const nc,const Identity &myId,const char * } } - query.clear(); - query - << '{' - << "\"Ranges\":[{" - << "\"Name\":\"" << networksSelectorName << "\"," - << "\"Range\":[0,18446744073709551615]" - << "}]," - << "\"TimeRange\":[" << timeRangeStart << ",18446744073709551615]," - << "\"MaskingKey\":\"" << controllerAddress << "\"," - << "\"Owners\":[\"" << _lfOwnerPublic << "\"]" - << '}'; - auto resp = htcli.Post("/query",query.str(),"application/json"); - if (resp->status == 200) { - nlohmann::json results(OSUtils::jsonParse(resp->body)); - if ((results.is_array())&&(results.size() > 0)) { - for(std::size_t ri=0;ri 0)) { - nlohmann::json &result = rset[0]; - if (result.is_object()) { - nlohmann::json &record = result["Record"]; - if (record.is_object()) { - const std::string recordValue = result["Value"]; - nlohmann::json network(OSUtils::jsonParse(recordValue)); - if (network.is_object()) { - const std::string idstr = network["id"]; - const uint64_t id = Utils::hexStrToU64(idstr.c_str()); - if ((id >> 24) == controllerAddressInt) { - std::lock_guard sl(_state_l); - _NetworkState &ns = _state[id]; - if (!ns.dirty) { - nlohmann::json nullJson; - _networkChanged(nullJson,network,false); + { + std::ostringstream query; + query + << '{' + << "\"Ranges\":[{" + << "\"Name\":\"" << networksSelectorName << "\"," + << "\"Range\":[0,18446744073709551615]" + << "}]," + << "\"TimeRange\":[" << timeRangeStart << ",18446744073709551615]," + << "\"MaskingKey\":\"" << controllerAddress << "\"," + << "\"Owners\":[\"" << _lfOwnerPublic << "\"]" + << '}'; + auto resp = htcli.Post("/query",query.str(),"application/json"); + if (resp) { + if (resp->status == 200) { + nlohmann::json results(OSUtils::jsonParse(resp->body)); + if ((results.is_array())&&(results.size() > 0)) { + for(std::size_t ri=0;ri 0)) { + nlohmann::json &result = rset[0]; + if (result.is_object()) { + nlohmann::json &record = result["Record"]; + if (record.is_object()) { + const std::string recordValue = result["Value"]; + printf("GET network %s\n",recordValue.c_str()); + nlohmann::json network(OSUtils::jsonParse(recordValue)); + if (network.is_object()) { + const std::string idstr = network["id"]; + const uint64_t id = Utils::hexStrToU64(idstr.c_str()); + if ((id >> 24) == controllerAddressInt) { + std::lock_guard sl(_state_l); + _NetworkState &ns = _state[id]; + if (!ns.dirty) { + nlohmann::json nullJson; + _networkChanged(nullJson,network,false); + } + } } } } } } } + } else { + fprintf(stderr,"ERROR: LFDB: %d from node: %s" ZT_EOL_S,resp->status,resp->body.c_str()); } + } else { + fprintf(stderr,"ERROR: LFDB: node is offline" ZT_EOL_S); } - } else { - fprintf(stderr,"ERROR: LFDB: %d from node: %s" ZT_EOL_S,resp->status,resp->body.c_str()); } - query.clear(); - query - << '{' - << "\"Ranges\":[{" - << "\"Name\":\"" << networksSelectorName << "\"," - << "\"Range\":[0,18446744073709551615]" - << "},{" - << "\"Name\":\"" << membersSelectorName << "\"," - << "\"Range\":[0,18446744073709551615]" - << "}]," - << "\"TimeRange\":[" << timeRangeStart << ",18446744073709551615]," - << "\"MaskingKey\":\"" << controllerAddress << "\"," - << "\"Owners\":[\"" << _lfOwnerPublic << "\"]" - << '}'; - resp = htcli.Post("/query",query.str(),"application/json"); - if (resp->status == 200) { - nlohmann::json results(OSUtils::jsonParse(resp->body)); - if ((results.is_array())&&(results.size() > 0)) { - for(std::size_t ri=0;ri 0)) { - nlohmann::json &result = rset[0]; - if (result.is_object()) { - nlohmann::json &record = result["Record"]; - if (record.is_object()) { - const std::string recordValue = result["Value"]; - nlohmann::json member(OSUtils::jsonParse(recordValue)); - if (member.is_object()) { - const std::string nwidstr = member["nwid"]; - const std::string idstr = member["id"]; - const uint64_t nwid = Utils::hexStrToU64(nwidstr.c_str()); - const uint64_t id = Utils::hexStrToU64(idstr.c_str()); - if ((id)&&((nwid >> 24) == controllerAddressInt)) { - std::lock_guard sl(_state_l); - auto ns = _state.find(nwid); - if (ns != _state.end()) { - _MemberState &ms = ns->second.members[id]; - if (!ms.dirty) { - nlohmann::json nullJson; - _memberChanged(nullJson,member,false); + { + std::ostringstream query; + query + << '{' + << "\"Ranges\":[{" + << "\"Name\":\"" << networksSelectorName << "\"," + << "\"Range\":[0,18446744073709551615]" + << "},{" + << "\"Name\":\"" << membersSelectorName << "\"," + << "\"Range\":[0,18446744073709551615]" + << "}]," + << "\"TimeRange\":[" << timeRangeStart << ",18446744073709551615]," + << "\"MaskingKey\":\"" << controllerAddress << "\"," + << "\"Owners\":[\"" << _lfOwnerPublic << "\"]" + << '}'; + auto resp = htcli.Post("/query",query.str(),"application/json"); + if (resp) { + if (resp->status == 200) { + nlohmann::json results(OSUtils::jsonParse(resp->body)); + if ((results.is_array())&&(results.size() > 0)) { + for(std::size_t ri=0;ri 0)) { + nlohmann::json &result = rset[0]; + if (result.is_object()) { + nlohmann::json &record = result["Record"]; + if (record.is_object()) { + const std::string recordValue = result["Value"]; + printf("GET member %s\n",recordValue.c_str()); + nlohmann::json member(OSUtils::jsonParse(recordValue)); + if (member.is_object()) { + const std::string nwidstr = member["nwid"]; + const std::string idstr = member["id"]; + const uint64_t nwid = Utils::hexStrToU64(nwidstr.c_str()); + const uint64_t id = Utils::hexStrToU64(idstr.c_str()); + if ((id)&&((nwid >> 24) == controllerAddressInt)) { + std::lock_guard sl(_state_l); + auto ns = _state.find(nwid); + if (ns != _state.end()) { + _MemberState &ms = ns->second.members[id]; + if (!ms.dirty) { + nlohmann::json nullJson; + _memberChanged(nullJson,member,false); + } + } } } } @@ -196,10 +255,12 @@ LFDB::LFDB(EmbeddedNetworkController *const nc,const Identity &myId,const char * } } } + } else { + fprintf(stderr,"ERROR: LFDB: %d from node: %s" ZT_EOL_S,resp->status,resp->body.c_str()); } + } else { + fprintf(stderr,"ERROR: LFDB: node is offline" ZT_EOL_S); } - } else { - fprintf(stderr,"ERROR: LFDB: %d from node: %s" ZT_EOL_S,resp->status,resp->body.c_str()); } timeRangeStart = time(nullptr) - 120; // start next query 2m before now to avoid losing updates From f6b080b8a2c071266270de23c7b99722b2cef21a Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 26 Jul 2019 17:39:00 -0700 Subject: [PATCH 065/185] Abstract out change listener from controller itself to permit DBs to shadow changes from other DBs. --- controller/DB.cpp | 47 ++++++++++++++---------- controller/DB.hpp | 47 +++++++++++------------- controller/EmbeddedNetworkController.cpp | 12 +++--- controller/EmbeddedNetworkController.hpp | 9 ++--- controller/FileDB.cpp | 4 +- controller/FileDB.hpp | 2 +- controller/LFDB.cpp | 27 ++++++++++---- controller/LFDB.hpp | 4 +- controller/PostgreSQL.cpp | 4 +- controller/PostgreSQL.hpp | 6 +-- 10 files changed, 88 insertions(+), 74 deletions(-) diff --git a/controller/DB.cpp b/controller/DB.cpp index bdd37c3b..bb734dc8 100644 --- a/controller/DB.cpp +++ b/controller/DB.cpp @@ -104,8 +104,7 @@ void DB::cleanMember(nlohmann::json &member) member.erase("lastRequestMetaData"); } -DB::DB(EmbeddedNetworkController *const nc,const Identity &myId,const char *path) : - _controller(nc), +DB::DB(const Identity &myId,const char *path) : _myId(myId), _myAddress(myId.address()), _path((path) ? path : "") @@ -115,9 +114,7 @@ DB::DB(EmbeddedNetworkController *const nc,const Identity &myId,const char *path _myAddressStr = tmp; } -DB::~DB() -{ -} +DB::~DB() {} bool DB::get(const uint64_t networkId,nlohmann::json &network) { @@ -229,7 +226,7 @@ void DB::networks(std::vector &networks) networks.push_back(n->first); } -void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool push) +void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool initialized) { uint64_t memberId = 0; uint64_t networkId = 0; @@ -313,8 +310,12 @@ void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool pu } } - if (push) - _controller->onNetworkMemberUpdate(networkId,memberId); + if (initialized) { + std::lock_guard ll(_changeListeners_l); + for(auto i=_changeListeners.begin();i!=_changeListeners.end();++i) { + (*i)->onNetworkMemberUpdate(networkId,memberId,memberConfig); + } + } } else if (memberId) { if (nw) { std::lock_guard l(nw->lock); @@ -332,20 +333,24 @@ void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool pu } } - if ((push)&&((wasAuth)&&(!isAuth)&&(networkId)&&(memberId))) - _controller->onNetworkMemberDeauthorize(networkId,memberId); + if ((initialized)&&((wasAuth)&&(!isAuth)&&(networkId)&&(memberId))) { + std::lock_guard ll(_changeListeners_l); + for(auto i=_changeListeners.begin();i!=_changeListeners.end();++i) { + (*i)->onNetworkMemberDeauthorize(networkId,memberId); + } + } } -void DB::_networkChanged(nlohmann::json &old,nlohmann::json &networkConfig,bool push) +void DB::_networkChanged(nlohmann::json &old,nlohmann::json &networkConfig,bool initialized) { if (networkConfig.is_object()) { const std::string ids = networkConfig["id"]; - const uint64_t id = Utils::hexStrToU64(ids.c_str()); - if (id) { + const uint64_t networkId = Utils::hexStrToU64(ids.c_str()); + if (networkId) { std::shared_ptr<_Network> nw; { std::lock_guard l(_networks_l); - std::shared_ptr<_Network> &nw2 = _networks[id]; + std::shared_ptr<_Network> &nw2 = _networks[networkId]; if (!nw2) nw2.reset(new _Network); nw = nw2; @@ -354,15 +359,19 @@ void DB::_networkChanged(nlohmann::json &old,nlohmann::json &networkConfig,bool std::lock_guard l2(nw->lock); nw->config = networkConfig; } - if (push) - _controller->onNetworkUpdate(id); + if (initialized) { + std::lock_guard ll(_changeListeners_l); + for(auto i=_changeListeners.begin();i!=_changeListeners.end();++i) { + (*i)->onNetworkUpdate(networkId,networkConfig); + } + } } } else if (old.is_object()) { const std::string ids = old["id"]; - const uint64_t id = Utils::hexStrToU64(ids.c_str()); - if (id) { + const uint64_t networkId = Utils::hexStrToU64(ids.c_str()); + if (networkId) { std::lock_guard l(_networks_l); - _networks.erase(id); + _networks.erase(networkId); } } } diff --git a/controller/DB.hpp b/controller/DB.hpp index e59230e1..f499d387 100644 --- a/controller/DB.hpp +++ b/controller/DB.hpp @@ -47,14 +47,22 @@ namespace ZeroTier { -class EmbeddedNetworkController; - /** * Base class with common infrastructure for all controller DB implementations */ class DB { public: + class ChangeListener + { + public: + ChangeListener() {} + virtual ~ChangeListener() {} + virtual void onNetworkUpdate(uint64_t networkId,const nlohmann::json &network) {} + virtual void onNetworkMemberUpdate(uint64_t networkId,uint64_t memberId,const nlohmann::json &member) {} + virtual void onNetworkMemberDeauthorize(uint64_t networkId,uint64_t memberId) {} + }; + struct NetworkSummaryInfo { NetworkSummaryInfo() : authorizedMemberCount(0),totalMemberCount(0),mostRecentDeauthTime(0) {} @@ -65,27 +73,12 @@ public: int64_t mostRecentDeauthTime; }; - /** - * Ensure that all network fields are present - */ static void initNetwork(nlohmann::json &network); - - /** - * Ensure that all member fields are present - */ static void initMember(nlohmann::json &member); - - /** - * Remove old and temporary network fields - */ static void cleanNetwork(nlohmann::json &network); - - /** - * Remove old and temporary member fields - */ static void cleanMember(nlohmann::json &member); - DB(EmbeddedNetworkController *const nc,const Identity &myId,const char *path); + DB(const Identity &myId,const char *path); virtual ~DB(); virtual bool waitForReady() = 0; @@ -101,19 +94,20 @@ public: bool get(const uint64_t networkId,nlohmann::json &network,const uint64_t memberId,nlohmann::json &member); bool get(const uint64_t networkId,nlohmann::json &network,const uint64_t memberId,nlohmann::json &member,NetworkSummaryInfo &info); bool get(const uint64_t networkId,nlohmann::json &network,std::vector &members); - bool summary(const uint64_t networkId,NetworkSummaryInfo &info); - void networks(std::vector &networks); virtual void save(nlohmann::json *orig,nlohmann::json &record) = 0; - virtual void eraseNetwork(const uint64_t networkId) = 0; - virtual void eraseMember(const uint64_t networkId,const uint64_t memberId) = 0; - virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress) = 0; + inline void addListener(DB::ChangeListener *const listener) + { + std::lock_guard l(_changeListeners_l); + _changeListeners.push_back(listener); + } + protected: struct _Network { @@ -127,18 +121,19 @@ protected: std::mutex lock; }; - void _memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool push); - void _networkChanged(nlohmann::json &old,nlohmann::json &networkConfig,bool push); + void _memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool initialized); + void _networkChanged(nlohmann::json &old,nlohmann::json &networkConfig,bool initialized); void _fillSummaryInfo(const std::shared_ptr<_Network> &nw,NetworkSummaryInfo &info); - EmbeddedNetworkController *const _controller; const Identity _myId; const Address _myAddress; const std::string _path; std::string _myAddressStr; + std::vector _changeListeners; std::unordered_map< uint64_t,std::shared_ptr<_Network> > _networks; std::unordered_multimap< uint64_t,uint64_t > _networkByMember; + mutable std::mutex _changeListeners_l; mutable std::mutex _networks_l; }; diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index 3ebdccf9..bf568527 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -496,7 +496,7 @@ void EmbeddedNetworkController::init(const Identity &signingId,Sender *sender) #ifdef ZT_CONTROLLER_USE_LIBPQ if ((_path.length() > 9)&&(_path.substr(0,9) == "postgres:")) { - _db.reset(new PostgreSQL(this,_signingId,_path.substr(9).c_str(), _listenPort, _mqc)); + _db.reset(new PostgreSQL(_signingId,_path.substr(9).c_str(), _listenPort, _mqc)); } else { #endif @@ -521,7 +521,7 @@ void EmbeddedNetworkController::init(const Identity &signingId,Sender *sender) std::size_t pubHdrEnd = lfOwnerPublic.find_first_of("\n\r\t "); if (pubHdrEnd != std::string::npos) { lfOwnerPublic = lfOwnerPublic.substr(0,pubHdrEnd); - _db.reset(new LFDB(this,_signingId,_path.c_str(),lfOwner.c_str(),lfOwnerPublic.c_str(),lfHost.c_str(),lfPort,storeOnlineState)); + _db.reset(new LFDB(_signingId,_path.c_str(),lfOwner.c_str(),lfOwnerPublic.c_str(),lfHost.c_str(),lfPort,storeOnlineState)); } } } @@ -530,7 +530,9 @@ void EmbeddedNetworkController::init(const Identity &signingId,Sender *sender) } } if (!_db) - _db.reset(new FileDB(this,_signingId,_path.c_str())); + _db.reset(new FileDB(_signingId,_path.c_str())); + + _db->addListener(this); #ifdef ZT_CONTROLLER_USE_LIBPQ } @@ -1188,7 +1190,7 @@ void EmbeddedNetworkController::handleRemoteTrace(const ZT_RemoteTrace &rt) } } -void EmbeddedNetworkController::onNetworkUpdate(const uint64_t networkId) +void EmbeddedNetworkController::onNetworkUpdate(const uint64_t networkId,const nlohmann::json &network) { // Send an update to all members of the network that are online const int64_t now = OSUtils::now(); @@ -1199,7 +1201,7 @@ void EmbeddedNetworkController::onNetworkUpdate(const uint64_t networkId) } } -void EmbeddedNetworkController::onNetworkMemberUpdate(const uint64_t networkId,const uint64_t memberId) +void EmbeddedNetworkController::onNetworkMemberUpdate(const uint64_t networkId,const uint64_t memberId,const nlohmann::json &member) { // Push update to member if online try { diff --git a/controller/EmbeddedNetworkController.hpp b/controller/EmbeddedNetworkController.hpp index 6ce0b5cf..7bc37be2 100644 --- a/controller/EmbeddedNetworkController.hpp +++ b/controller/EmbeddedNetworkController.hpp @@ -58,7 +58,7 @@ class Node; struct MQConfig; -class EmbeddedNetworkController : public NetworkController +class EmbeddedNetworkController : public NetworkController,public DB::ChangeListener { public: /** @@ -101,10 +101,9 @@ public: void handleRemoteTrace(const ZT_RemoteTrace &rt); - // Called on update via POST or by JSONDB on external update of network or network member records - void onNetworkUpdate(const uint64_t networkId); - void onNetworkMemberUpdate(const uint64_t networkId,const uint64_t memberId); - void onNetworkMemberDeauthorize(const uint64_t networkId,const uint64_t memberId); + virtual void onNetworkUpdate(const uint64_t networkId,const nlohmann::json &network); + virtual void onNetworkMemberUpdate(const uint64_t networkId,const uint64_t memberId,const nlohmann::json &member); + virtual void onNetworkMemberDeauthorize(const uint64_t networkId,const uint64_t memberId); private: void _request(uint64_t nwid,const InetAddress &fromAddr,uint64_t requestPacketId,const Identity &identity,const Dictionary &metaData); diff --git a/controller/FileDB.cpp b/controller/FileDB.cpp index eb2ec00d..7b997c49 100644 --- a/controller/FileDB.cpp +++ b/controller/FileDB.cpp @@ -29,8 +29,8 @@ namespace ZeroTier { -FileDB::FileDB(EmbeddedNetworkController *const nc,const Identity &myId,const char *path) : - DB(nc,myId,path), +FileDB::FileDB(const Identity &myId,const char *path) : + DB(myId,path), _networksPath(_path + ZT_PATH_SEPARATOR_S + "network"), _tracePath(_path + ZT_PATH_SEPARATOR_S + "trace"), _onlineChanged(false), diff --git a/controller/FileDB.hpp b/controller/FileDB.hpp index 0a8b9d2e..5d55d0a4 100644 --- a/controller/FileDB.hpp +++ b/controller/FileDB.hpp @@ -35,7 +35,7 @@ namespace ZeroTier class FileDB : public DB { public: - FileDB(EmbeddedNetworkController *const nc,const Identity &myId,const char *path); + FileDB(const Identity &myId,const char *path); virtual ~FileDB(); virtual bool waitForReady(); diff --git a/controller/LFDB.cpp b/controller/LFDB.cpp index 5c5b687d..1f7f701a 100644 --- a/controller/LFDB.cpp +++ b/controller/LFDB.cpp @@ -37,9 +37,8 @@ namespace ZeroTier { -LFDB::LFDB(EmbeddedNetworkController *const nc,const Identity &myId,const char *path,const char *lfOwnerPrivate,const char *lfOwnerPublic,const char *lfNodeHost,int lfNodePort,bool storeOnlineState) : - DB(nc,myId,path), - _nc(nc), +LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,const char *lfOwnerPublic,const char *lfNodeHost,int lfNodePort,bool storeOnlineState) : + DB(myId,path), _myId(myId), _lfOwnerPrivate((lfOwnerPrivate) ? lfOwnerPrivate : ""), _lfOwnerPublic((lfOwnerPublic) ? lfOwnerPublic : ""), @@ -54,7 +53,7 @@ LFDB::LFDB(EmbeddedNetworkController *const nc,const Identity &myId,const char * const uint64_t controllerAddressInt = _myId.address().toInt(); _myId.address().toString(controllerAddress); std::string networksSelectorName("com.zerotier.controller.lfdb:"); networksSelectorName.append(controllerAddress); networksSelectorName.append("/network"); - std::string membersSelectorName("com.zerotier.controller.lfdb:"); membersSelectorName.append(controllerAddress); membersSelectorName.append("/network/member"); + std::string membersSelectorName("com.zerotier.controller.lfdb:"); membersSelectorName.append(controllerAddress); membersSelectorName.append("/member"); httplib::Client htcli(_lfNodeHost.c_str(),_lfNodePort,600); int64_t timeRangeStart = 0; @@ -90,10 +89,10 @@ LFDB::LFDB(EmbeddedNetworkController *const nc,const Identity &myId,const char * for(auto ms=ns->second.members.begin();ms!=ns->second.members.end();++ms) { if ((_storeOnlineState)&&(ms->second.lastOnlineDirty)&&(ms->second.lastOnlineAddress)) { + nlohmann::json newrec,selector0,selector1,selectors,ip; char tmp[1024],tmp2[128]; OSUtils::ztsnprintf(tmp,sizeof(tmp),"com.zerotier.controller.lfdb:%s/network/%.16llx/online",controllerAddress,(unsigned long long)ns->first); ms->second.lastOnlineAddress.toIpString(tmp2); - nlohmann::json newrec,selector0,selector1,selectors; selector0["Name"] = tmp; selector0["Ordinal"] = ms->first; selector1["Name"] = tmp2; @@ -101,7 +100,21 @@ LFDB::LFDB(EmbeddedNetworkController *const nc,const Identity &myId,const char * selectors.push_back(selector0); selectors.push_back(selector1); newrec["Selectors"] = selectors; - newrec["Value"] = tmp2; + const uint8_t *const rawip = (const uint8_t *)ms->second.lastOnlineAddress.rawIpData(); + switch(ms->second.lastOnlineAddress) { + case AF_INET: + for(int j=0;j<4;++j) + ip.push_back((unsigned int)rawip[j]); + break; + case AF_INET6: + for(int j=0;j<16;++j) + ip.push_back((unsigned int)rawip[j]); + break; + default: + ip = tmp2; // should never happen since only IP transport is currently supported + break; + } + newrec["Value"] = ip; newrec["OwnerPrivate"] = _lfOwnerPrivate; newrec["MaskingKey"] = controllerAddress; newrec["Timestamp"] = ms->second.lastOnlineTime; @@ -112,7 +125,7 @@ LFDB::LFDB(EmbeddedNetworkController *const nc,const Identity &myId,const char * ms->second.lastOnlineDirty = false; printf("SET member online %.16llx %.10llx %s\n",ns->first,ms->first,resp->body.c_str()); } else { - fprintf(stderr,"ERROR: LFDB: %d from node (create/update member): %s" ZT_EOL_S,resp->status,resp->body.c_str()); + fprintf(stderr,"ERROR: LFDB: %d from node (create/update member online status): %s" ZT_EOL_S,resp->status,resp->body.c_str()); } } else { fprintf(stderr,"ERROR: LFDB: node is offline" ZT_EOL_S); diff --git a/controller/LFDB.hpp b/controller/LFDB.hpp index 6659c0bf..73187462 100644 --- a/controller/LFDB.hpp +++ b/controller/LFDB.hpp @@ -43,7 +43,6 @@ class LFDB : public DB { public: /** - * @param nc Network controller * @param myId Identity of controller node (with secret) * @param path Base path for ZeroTier node itself * @param lfOwnerPrivate LF owner private in PEM format @@ -52,7 +51,7 @@ public: * @param lfNodePort LF node http (not https) port * @param storeOnlineState If true, store online/offline state and IP info in LF (a lot of data, only for private networks!) */ - LFDB(EmbeddedNetworkController *const nc,const Identity &myId,const char *path,const char *lfOwnerPrivate,const char *lfOwnerPublic,const char *lfNodeHost,int lfNodePort,bool storeOnlineState); + LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,const char *lfOwnerPublic,const char *lfNodeHost,int lfNodePort,bool storeOnlineState); virtual ~LFDB(); virtual bool waitForReady(); @@ -63,7 +62,6 @@ public: virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress); protected: - EmbeddedNetworkController *const _nc; const Identity _myId; std::string _lfOwnerPrivate,_lfOwnerPublic; diff --git a/controller/PostgreSQL.cpp b/controller/PostgreSQL.cpp index 594591bd..c6b9ada4 100644 --- a/controller/PostgreSQL.cpp +++ b/controller/PostgreSQL.cpp @@ -77,8 +77,8 @@ std::string join(const std::vector &elements, const char * const se using namespace ZeroTier; -PostgreSQL::PostgreSQL(EmbeddedNetworkController *const nc, const Identity &myId, const char *path, int listenPort, MQConfig *mqc) - : DB(nc, myId, path) +PostgreSQL::PostgreSQL(const Identity &myId, const char *path, int listenPort, MQConfig *mqc) + : DB(myId, path) , _ready(0) , _connected(1) , _run(1) diff --git a/controller/PostgreSQL.hpp b/controller/PostgreSQL.hpp index 779d47bd..f35f89fc 100644 --- a/controller/PostgreSQL.hpp +++ b/controller/PostgreSQL.hpp @@ -51,7 +51,7 @@ struct MQConfig; class PostgreSQL : public DB { public: - PostgreSQL(EmbeddedNetworkController *const nc, const Identity &myId, const char *path, int listenPort, MQConfig *mqc = NULL); + PostgreSQL(const Identity &myId, const char *path, int listenPort, MQConfig *mqc = NULL); virtual ~PostgreSQL(); virtual bool waitForReady(); @@ -78,7 +78,6 @@ private: void _networksWatcher_Postgres(PGconn *conn); void _networksWatcher_RabbitMQ(); - void commitThread(); void onlineNotificationThread(); @@ -93,7 +92,6 @@ private: BlockingQueue _commitQueue; - std::thread _heartbeatThread; std::thread _membersDbWatcher; std::thread _networksDbWatcher; @@ -116,4 +114,4 @@ private: #endif // ZT_CONTROLLER_LIBPQ_HPP -#endif // ZT_CONTROLLER_USE_LIBPQ \ No newline at end of file +#endif // ZT_CONTROLLER_USE_LIBPQ From 0618452615ddedc8ba5fe797488ab53a89446590 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 26 Jul 2019 17:44:05 -0700 Subject: [PATCH 066/185] LF masking key should be a secret --- controller/LFDB.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/controller/LFDB.cpp b/controller/LFDB.cpp index 1f7f701a..d0363819 100644 --- a/controller/LFDB.cpp +++ b/controller/LFDB.cpp @@ -55,6 +55,13 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons std::string networksSelectorName("com.zerotier.controller.lfdb:"); networksSelectorName.append(controllerAddress); networksSelectorName.append("/network"); std::string membersSelectorName("com.zerotier.controller.lfdb:"); membersSelectorName.append(controllerAddress); membersSelectorName.append("/member"); + // LF record masking key is the first 32 bytes of SHA512(controller private key) in hex, + // hiding record values from anything but the controller or someone who has its key. + uint8_t sha512pk[64]; + _myId.sha512PrivateKey(sha512pk); + char maskingKey [128]; + Utils::hex(sha512pk,32,maskingKey); + httplib::Client htcli(_lfNodeHost.c_str(),_lfNodePort,600); int64_t timeRangeStart = 0; while (_running) { @@ -70,7 +77,7 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons newrec["Selectors"].push_back(selector0); newrec["Value"] = network.dump(); newrec["OwnerPrivate"] = _lfOwnerPrivate; - newrec["MaskingKey"] = controllerAddress; + newrec["MaskingKey"] = maskingKey; newrec["PulseIfUnchanged"] = true; printf("%s\n",newrec.dump().c_str()); auto resp = htcli.Post("/makerecord",newrec.dump(),"application/json"); @@ -116,7 +123,7 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons } newrec["Value"] = ip; newrec["OwnerPrivate"] = _lfOwnerPrivate; - newrec["MaskingKey"] = controllerAddress; + newrec["MaskingKey"] = maskingKey; newrec["Timestamp"] = ms->second.lastOnlineTime; newrec["PulseIfUnchanged"] = true; auto resp = htcli.Post("/makerecord",newrec.dump(),"application/json"); @@ -145,7 +152,7 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons newrec["Selectors"] = selectors; newrec["Value"] = member.dump(); newrec["OwnerPrivate"] = _lfOwnerPrivate; - newrec["MaskingKey"] = controllerAddress; + newrec["MaskingKey"] = maskingKey; newrec["PulseIfUnchanged"] = true; auto resp = htcli.Post("/makerecord",newrec.dump(),"application/json"); if (resp) { @@ -173,7 +180,7 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons << "\"Range\":[0,18446744073709551615]" << "}]," << "\"TimeRange\":[" << timeRangeStart << ",18446744073709551615]," - << "\"MaskingKey\":\"" << controllerAddress << "\"," + << "\"MaskingKey\":\"" << maskingKey << "\"," << "\"Owners\":[\"" << _lfOwnerPublic << "\"]" << '}'; auto resp = htcli.Post("/query",query.str(),"application/json"); @@ -228,7 +235,7 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons << "\"Range\":[0,18446744073709551615]" << "}]," << "\"TimeRange\":[" << timeRangeStart << ",18446744073709551615]," - << "\"MaskingKey\":\"" << controllerAddress << "\"," + << "\"MaskingKey\":\"" << maskingKey << "\"," << "\"Owners\":[\"" << _lfOwnerPublic << "\"]" << '}'; auto resp = htcli.Post("/query",query.str(),"application/json"); From d9befe3fb38973a014f383a38fa126ca218ca732 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 26 Jul 2019 18:51:50 -0700 Subject: [PATCH 067/185] Debug code removal --- controller/LFDB.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/controller/LFDB.cpp b/controller/LFDB.cpp index d0363819..a303d15d 100644 --- a/controller/LFDB.cpp +++ b/controller/LFDB.cpp @@ -79,7 +79,6 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons newrec["OwnerPrivate"] = _lfOwnerPrivate; newrec["MaskingKey"] = maskingKey; newrec["PulseIfUnchanged"] = true; - printf("%s\n",newrec.dump().c_str()); auto resp = htcli.Post("/makerecord",newrec.dump(),"application/json"); if (resp) { if (resp->status == 200) { From eb7081d2a35dbd80f54c2932182c7be940ac5285 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 26 Jul 2019 19:28:09 -0700 Subject: [PATCH 068/185] Fix for detecting changes in LF from other instances of the same controller. --- controller/LFDB.cpp | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/controller/LFDB.cpp b/controller/LFDB.cpp index a303d15d..f0c8ebfb 100644 --- a/controller/LFDB.cpp +++ b/controller/LFDB.cpp @@ -107,7 +107,7 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons selectors.push_back(selector1); newrec["Selectors"] = selectors; const uint8_t *const rawip = (const uint8_t *)ms->second.lastOnlineAddress.rawIpData(); - switch(ms->second.lastOnlineAddress) { + switch(ms->second.lastOnlineAddress.ss_family) { case AF_INET: for(int j=0;j<4;++j) ip.push_back((unsigned int)rawip[j]); @@ -200,13 +200,24 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons if (network.is_object()) { const std::string idstr = network["id"]; const uint64_t id = Utils::hexStrToU64(idstr.c_str()); - if ((id >> 24) == controllerAddressInt) { + if ((id >> 24) == controllerAddressInt) { // sanity check + std::lock_guard sl(_state_l); _NetworkState &ns = _state[id]; if (!ns.dirty) { - nlohmann::json nullJson; - _networkChanged(nullJson,network,false); + nlohmann::json oldNetwork; + if (get(id,oldNetwork)) { + const uint64_t revision = network["revision"]; + const uint64_t prevRevision = oldNetwork["revision"]; + if (prevRevision < revision) { + _networkChanged(oldNetwork,network,timeRangeStart > 0); + } + } else { + nlohmann::json nullJson; + _networkChanged(nullJson,network,timeRangeStart > 0); + } } + } } } @@ -257,16 +268,23 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons const std::string idstr = member["id"]; const uint64_t nwid = Utils::hexStrToU64(nwidstr.c_str()); const uint64_t id = Utils::hexStrToU64(idstr.c_str()); - if ((id)&&((nwid >> 24) == controllerAddressInt)) { + if ((id)&&((nwid >> 24) == controllerAddressInt)) { // sanity check + std::lock_guard sl(_state_l); auto ns = _state.find(nwid); - if (ns != _state.end()) { - _MemberState &ms = ns->second.members[id]; - if (!ms.dirty) { - nlohmann::json nullJson; - _memberChanged(nullJson,member,false); + if ((ns == _state.end())||(!ns->second.members[id].dirty)) { + nlohmann::json network,oldMember; + if (get(nwid,network,id,oldMember)) { + const uint64_t revision = member["revision"]; + const uint64_t prevRevision = oldMember["revision"]; + if (prevRevision < revision) + _memberChanged(oldMember,member,timeRangeStart > 0); } + } else { + nlohmann::json nullJson; + _memberChanged(nullJson,member,timeRangeStart > 0); } + } } } From d9432f2f1eccb624d772f532d514f9d74f0dc98c Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 29 Jul 2019 10:19:20 -0700 Subject: [PATCH 069/185] cleanup --- node/Constants.hpp | 45 +++++++++++++++++++-------------------------- node/Switch.hpp | 10 ++++++++++ 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/node/Constants.hpp b/node/Constants.hpp index 98df998d..d58e408f 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -72,14 +72,6 @@ #include #endif -// Defined this macro to disable "type punning" on a number of targets that -// have issues with unaligned memory access. -#if defined(__arm__) || defined(__ARMEL__) || (defined(__APPLE__) && ( (defined(TARGET_OS_IPHONE) && (TARGET_OS_IPHONE != 0)) || (defined(TARGET_OS_WATCH) && (TARGET_OS_WATCH != 0)) || (defined(TARGET_IPHONE_SIMULATOR) && (TARGET_IPHONE_SIMULATOR != 0)) ) ) -#ifndef ZT_NO_TYPE_PUNNING -#define ZT_NO_TYPE_PUNNING -#endif -#endif - #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) #ifndef __UNIX_LIKE__ #define __UNIX_LIKE__ @@ -107,13 +99,23 @@ #pragma warning(disable : 4101) #undef __UNIX_LIKE__ #undef __BSD__ -#define ZT_PATH_SEPARATOR '\\' -#define ZT_PATH_SEPARATOR_S "\\" -#define ZT_EOL_S "\r\n" #include #include #endif +#ifdef __NetBSD__ +#ifndef RTF_MULTICAST +#define RTF_MULTICAST 0x20000000 +#endif +#endif + +// Define ZT_NO_TYPE_PUNNING to disable reckless casts on anything other than x86/x64. +#if (!(defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_AMD64) || defined(_M_X64) || defined(i386) || defined(__i386) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(_M_IX86) || defined(__X86__) || defined(_X86_) || defined(__I86__) || defined(__INTEL__) || defined(__386))) +#ifndef ZT_NO_TYPE_PUNNING +#define ZT_NO_TYPE_PUNNING +#endif +#endif + // Assume little endian if not defined #if (defined(__APPLE__) || defined(__WINDOWS__)) && (!defined(__BYTE_ORDER)) #undef __BYTE_ORDER @@ -124,7 +126,11 @@ #define __BYTE_ORDER 1234 #endif -#ifdef __UNIX_LIKE__ +#ifdef __WINDOWS__ +#define ZT_PATH_SEPARATOR '\\' +#define ZT_PATH_SEPARATOR_S "\\" +#define ZT_EOL_S "\r\n" +#else #define ZT_PATH_SEPARATOR '/' #define ZT_PATH_SEPARATOR_S "/" #define ZT_EOL_S "\n" @@ -134,10 +140,6 @@ #include #endif -#ifdef __NetBSD__ -#define RTF_MULTICAST 0x20000000 -#endif - #if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__) #ifndef likely #define likely(x) __builtin_expect((x),1) @@ -627,16 +629,7 @@ */ #define ZT_THREAD_MIN_STACK_SIZE 1048576 -/* Ethernet frame types that might be relevant to us */ -#define ZT_ETHERTYPE_IPV4 0x0800 -#define ZT_ETHERTYPE_ARP 0x0806 -#define ZT_ETHERTYPE_RARP 0x8035 -#define ZT_ETHERTYPE_ATALK 0x809b -#define ZT_ETHERTYPE_AARP 0x80f3 -#define ZT_ETHERTYPE_IPX_A 0x8137 -#define ZT_ETHERTYPE_IPX_B 0x8138 -#define ZT_ETHERTYPE_IPV6 0x86dd - +// Exceptions thrown in core ZT code #define ZT_EXCEPTION_OUT_OF_BOUNDS 100 #define ZT_EXCEPTION_OUT_OF_MEMORY 101 #define ZT_EXCEPTION_PRIVATE_KEY_REQUIRED 102 diff --git a/node/Switch.hpp b/node/Switch.hpp index 5e3739fb..a531b268 100644 --- a/node/Switch.hpp +++ b/node/Switch.hpp @@ -44,6 +44,16 @@ #include "IncomingPacket.hpp" #include "Hashtable.hpp" +/* Ethernet frame types that might be relevant to us */ +#define ZT_ETHERTYPE_IPV4 0x0800 +#define ZT_ETHERTYPE_ARP 0x0806 +#define ZT_ETHERTYPE_RARP 0x8035 +#define ZT_ETHERTYPE_ATALK 0x809b +#define ZT_ETHERTYPE_AARP 0x80f3 +#define ZT_ETHERTYPE_IPX_A 0x8137 +#define ZT_ETHERTYPE_IPX_B 0x8138 +#define ZT_ETHERTYPE_IPV6 0x86dd + namespace ZeroTier { class RuntimeEnvironment; From a8f2b39f15c4d9521c719cfd879303376b07e035 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 29 Jul 2019 11:05:46 -0700 Subject: [PATCH 070/185] Windows project fixes --- windows/ZeroTierOne/ZeroTierOne.vcxproj | 3 +++ windows/ZeroTierOne/ZeroTierOne.vcxproj.filters | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj b/windows/ZeroTierOne/ZeroTierOne.vcxproj index 3f6397ca..2346dabc 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj @@ -30,6 +30,7 @@ + @@ -116,8 +117,10 @@ + + diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters b/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters index 1fcf7b69..f761d920 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters @@ -82,6 +82,9 @@ {7dc22e9c-f869-41e7-b43d-f07f5b94f6fb} + + {4dfde4c7-2950-40ee-92f2-05e0916d36c5} + @@ -264,6 +267,9 @@ Source Files\controller + + Source Files\controller + @@ -506,6 +512,12 @@ Header Files\controller + + Header Files\controller + + + Header Files\ext\cpp-httplib + From 678e11530efe794c7a4eba4e69d714985c3d68ea Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 29 Jul 2019 12:07:44 -0700 Subject: [PATCH 071/185] 1.4 bump --- OFFICIAL-RELEASE-STEPS.md | 16 ----------- README.md | 33 ++++++++++------------- RELEASE-NOTES.md | 12 ++++++--- debian/changelog | 6 ++--- ext/installfiles/mac/ZeroTier One.pkgproj | 2 +- windows/WinUI/AboutView.xaml | 2 +- zerotier-one.spec | 5 +++- 7 files changed, 32 insertions(+), 44 deletions(-) diff --git a/OFFICIAL-RELEASE-STEPS.md b/OFFICIAL-RELEASE-STEPS.md index 4db5169f..6de3526c 100644 --- a/OFFICIAL-RELEASE-STEPS.md +++ b/OFFICIAL-RELEASE-STEPS.md @@ -13,7 +13,6 @@ The version must be incremented in all of the following files: /zerotier-one.spec /debian/changelog /ext/installfiles/mac/ZeroTier One.pkgproj - /ext/installfiles/windows/chocolatey/zerotier-one.nuspec /ext/installfiles/windows/ZeroTier One.aip /windows/WinUI/AboutView.xaml @@ -29,21 +28,6 @@ Mac's easy. Just type: You will need [Packages](http://s.sudre.free.fr/Software/Packages/about.html) and our release signing key in the keychain. -## Linux - -See `LinuxBuild` environment on `linux-build` VM and use: `chroots/mount-build.sh`, `chroots/build.sh`, and the scripts in `build/` to make APT and RPM repositories. - ## Windows First load the Visual Studio solution and rebuild the UI and ZeroTier One in both x64 and i386 `Release` mode. Then load [Advanced Installer Enterprise](http://www.advancedinstaller.com/), check that the version is correct, and build. The build will fail if any build artifacts are missing, and Windows must have our product singing key (from DigiCert) available to sign the resulting MSI file. The MSI must then be tested on at least a few different CLEAN Windows VMs to ensure that the installer is valid and properly signed. - -*After the MSI is published to download.zerotier.com in the proper RELEASE/#.#.#/dist subfolder for its version* the Chocolatey package must be rebuilt and published. Open a command prompt, change to `ext/installfiles/windows/chocolatey`, and type `choco pack`. Then use `choco push` to push it to Chocolatey (API key required). - - choco pack - choco push zerotier-one.#.#.#.nupkg -s https://chocolatey.org/ - -Note that this does not cover rebuilding the drivers or their containing MSI projects, as this is typically not necessary and they are shipped in binary form in the repository for convenience. - -## iOS, Android - -... no docs here yet since this is done entirely out of band with regular installs. diff --git a/README.md b/README.md index 37f04982..6fecf2fd 100644 --- a/README.md +++ b/README.md @@ -1,62 +1,57 @@ -ZeroTier - A Planetary Ethernet Switch +ZeroTier - Global Area Networking ====== -ZeroTier is a smart programmable Ethernet switch for planet Earth. +ZeroTier is a smart programmable Ethernet switch for planet Earth. It allows networked devices and applications to be managed as if the entire world is one data center or cloud region. It replaces the physical LAN/WAN boundary with a virtual one, allowing devices of any type at any location to be managed as if they all reside in the same cloud region or data center. All traffic is encrypted end-to-end and takes the most direct path available for minimum latency and maximum performance. The goals and design of ZeroTier are inspired by among other things the original [Google BeyondCorp](https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/43231.pdf) paper and the [Jericho Forum](https://en.wikipedia.org/wiki/Jericho_Forum). -Visit [ZeroTier's site](https://www.zerotier.com/?pk_campaign=github_ZeroTierOne) for more information and [pre-built binary packages](https://www.zerotier.com/download.shtml?pk_campaign=github_ZeroTierOne). Apps for Android and iOS are available for free in the Google Play and Apple app stores. +Visit [ZeroTier's site](https://www.zerotier.com/) for more information and [pre-built binary packages](https://www.zerotier.com/download/). Apps for Android and iOS are available for free in the Google Play and Apple app stores. ### Getting Started Everything in the ZeroTier world is controlled by two types of identifier: 40-bit/10-digit *ZeroTier addresses* and 64-bit/16-digit *network IDs*. A ZeroTier address identifies a node or "device" (laptop, phone, server, VM, app, etc.) while a network ID identifies a virtual Ethernet network that can be joined by devices. -Another way of thinking about it is that ZeroTier addresses are port numbers on a giant planetary-sized smart switch while network IDs are VLANs to which these ports can be assigned. For more details read about VL1 and VL2 in [the ZeroTier manual](https://www.zerotier.com/manual.shtml). +Another way of thinking about it is that ZeroTier addresses are port numbers on a giant planetary-sized smart switch while network IDs are VLANs to which these ports can be assigned. For more details read about VL1 and VL2 in [the ZeroTier manual](https://www.zerotier.com/manual/). *Network controllers* are ZeroTier nodes that act as access control certificate authorities and configuration managers for virtual networks. The first 40 bits (or 10 digits) of a network ID is the ZeroTier address of its controller. You can create networks with our [hosted controllers](https://my.zerotier.com/) and web UI/API or [host your own](controller/) if you don't mind posting some JSON configuration info or writing a script to do so. ### Project Layout +The base path contains the ZeroTier One service main entry point (`one.cpp`), self test code, makefiles, etc. + - `artwork/`: icons, logos, etc. - `attic/`: old stuff and experimental code that we want to keep around for reference. - `controller/`: the reference network controller implementation, which is built and included by default on desktop and server build targets. - `debian/`: files for building Debian packages on Linux. - `doc/`: manual pages and other documentation. + - `docker/`: Dockerfile to build as a container for containerized Linux systems and Kubernetes clusters. - `ext/`: third party libraries, binaries that we ship for convenience on some platforms (Mac and Windows), and installation support files. - `include/`: include files for the ZeroTier core. - `java/`: a JNI wrapper used with our Android mobile app. (The whole Android app is not open source but may be made so in the future.) - `macui/`: a Macintosh menu-bar app for controlling ZeroTier One, written in Objective C. - `node/`: the ZeroTier virtual Ethernet switch core, which is designed to be entirely separate from the rest of the code and able to be built as a stand-alone OS-independent library. Note to developers: do not use C++11 features in here, since we want this to build on old embedded platforms that lack C++11 support. C++11 can be used elsewhere. - `osdep/`: code to support and integrate with OSes, including platform-specific stuff only built for certain targets. + - `rule-compiler/`: JavaScript rules language compiler for defining network-level rules. - `service/`: the ZeroTier One service, which wraps the ZeroTier core and provides VPN-like connectivity to virtual networks for desktops, laptops, servers, VMs, and containers. - - `tcp-proxy/`: TCP proxy code run by ZeroTier, Inc. to provide TCP fallback (this will die soon!). - `windows/`: Visual Studio solution files, Windows service code for ZeroTier One, and the Windows task bar app UI. -The base path contains the ZeroTier One service main entry point (`one.cpp`), self test code, makefiles, etc. - ### Build and Platform Notes To build on Mac and Linux just type `make`. On FreeBSD and OpenBSD `gmake` (GNU make) is required and can be installed from packages or ports. For Windows there is a Visual Studio solution in `windows/'. - **Mac** - - Xcode command line tools for OSX 10.7 or newer are required. - - Tap device driver kext source is in `ext/tap-mac` and a signed pre-built binary can be found in `ext/bin/tap-mac`. You should not need to build it yourself. It's a fork of [tuntaposx](http://tuntaposx.sourceforge.net) with device names changed to `zt#`, support for a larger MTU, and tun functionality removed. + - Xcode command line tools for OSX 10.8 or newer are required. - **Linux** - - The minimum compiler versions required are GCC/G++ 4.9.3 or CLANG/CLANG++ 3.4.2. + - The minimum compiler versions required are GCC/G++ 4.9.3 or CLANG/CLANG++ 3.4.2. (Install `clang` on CentOS 7 as G++ is too old.) - Linux makefiles automatically detect and prefer clang/clang++ if present as it produces smaller and slightly faster binaries in most cases. You can override by supplying CC and CXX variables on the make command line. - - CentOS 7 ships with a version of GCC/G++ that is too old, but a new enough version of CLANG can be found in the *epel* repositories. Type `yum install epel-release` and then `yum install clang` to build there. - **Windows** - Windows 7 or newer is supported. This *may* work on Vista but isn't officially supported there. It will not work on Windows XP. - - We build with Visual Studio 2015. Older versions may not work. Clang or MinGW will also probably work but may require some makefile hacking. - - Pre-built signed Windows drivers are included in `ext/bin/tap-windows-ndis6`. The MSI files found there will install them on 32-bit and 64-bit systems. We don't recommend trying to build Windows drivers from scratch unless you know what you're doing. One does not simply "build" a Windows driver. + - We build with Visual Studio 2017. Older versions may not work. Clang or MinGW will also probably work but may require some makefile hacking. - **FreeBSD** - - Tested most recently on FreeBSD-11. Older versions may work but we're not sure. - - GCC/G++ 4.9 and gmake are required. These can be installed from packages or ports. Type `gmake` to build. + - GNU make is required. Type `gmake` to build. - **OpenBSD** - - There is a limit of four network memberships on OpenBSD as there are only four tap devices (`/dev/tap0` through `/dev/tap3`). We're not sure if this can be increased. - - OpenBSD lacks `getifmaddrs` (or any equivalent method) to get interface multicast memberships. As a result multicast will only work on OpenBSD for ARP and NDP (IP/MAC lookup) and not for other purposes. - - Only tested on OpenBSD 6.0. Older versions may not work. - - GCC/G++ 4.9 and gmake are required and can be installed using `pkg_add` or from ports. They get installed in `/usr/local/bin` as `egcc` and `eg++` and our makefile is pre-configured to use them on OpenBSD. + - There is a limit of four network memberships on OpenBSD as there are only four tap devices (`/dev/tap0` through `/dev/tap3`). + - GNU make is required. Type `gmake` to build. Typing `make selftest` will build a *zerotier-selftest* binary which unit tests various internals and reports on a few aspects of the build environment. It's a good idea to try this on novel platforms or architectures. diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 67bd2e58..3ae31f0f 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,16 +1,22 @@ ZeroTier Release Notes ====== -# 2019-??-?? -- Version 1.4.0 (currently in prerelease as 1.2.99) +# 2019-07-29 -- Version 1.4.0 +### Major Changes + + * Mac version no longer requires a kernel extension, instead making use of the [feth interfaces](https://apple.stackexchange.com/questions/337715/fake-ethernet-interfaces-feth-if-fake-anyone-ever-seen-this). * Added support for concurrent multipath (multiple paths at once) with traffic weighting by link quality and faster recovery from lost links. * Added under-the-hood support for QoS (not yet exposed) that will eventually be configurable via our rules engine. + +### Minor Changes and Bug Fixes + + * Experimental DB driver for [LF](https://github.com/zerotier/lf) to store network controller data (LFDB.cpp / LFDB.hpp). * Modified credential push and direct path push timings and algorithms to somewhat reduce "chattiness" of the protocol when idle. More radical background overhead reductions will have to wait for the 2.x line. - * Mac version no longer requires a kernel extension, instead making use of the [feth interfaces](https://apple.stackexchange.com/questions/337715/fake-ethernet-interfaces-feth-if-fake-anyone-ever-seen-this). * Removed our beta/half-baked integration of Central with the Windows UI. We're going to do a whole new UI of some kind in the future at least for Windows and Mac. * Fixed stack overflow issues on Linux versions using musl libc. * Fixed some alignment problems reported on ARM and ARM64, but some reports we could not reproduce so please report any issues with exact chip, OS/distro, and ZeroTier version in use. - * Fixed numerous other small issues and bugs. + * Fixed numerous other small issues and bugs such as ARM alignment issues causing crashes on some devices. * Windows now sets the adapter name such that it is consistent in both the Windows UI and command line utilities. # 2018-07-27 -- Version 1.2.12 diff --git a/debian/changelog b/debian/changelog index 778a875f..d290ba94 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,8 @@ -zerotier-one (1.2.99) unstable; urgency=medium +zerotier-one (1.4.0) unstable; urgency=medium - * 1.4.0pre release + * See https://github.com/zerotier/ZeroTierOne for release notes. - -- Adam Ierymenko Thu, 27 Jun 2019 01:00:00 -0700 + -- Adam Ierymenko Thu, 29 Jul 2019 01:00:00 -0700 zerotier-one (1.2.12) unstable; urgency=medium diff --git a/ext/installfiles/mac/ZeroTier One.pkgproj b/ext/installfiles/mac/ZeroTier One.pkgproj index 71c2f2db..7652041d 100755 --- a/ext/installfiles/mac/ZeroTier One.pkgproj +++ b/ext/installfiles/mac/ZeroTier One.pkgproj @@ -664,7 +664,7 @@ USE_HFS+_COMPRESSION VERSION - 1.2.99 + 1.4.0
PROJECT_COMMENTS diff --git a/windows/WinUI/AboutView.xaml b/windows/WinUI/AboutView.xaml index 8d715fd2..d8525f2a 100644 --- a/windows/WinUI/AboutView.xaml +++ b/windows/WinUI/AboutView.xaml @@ -19,7 +19,7 @@ - + diff --git a/zerotier-one.spec b/zerotier-one.spec index 72a5a96a..72217215 100644 --- a/zerotier-one.spec +++ b/zerotier-one.spec @@ -1,5 +1,5 @@ Name: zerotier-one -Version: 1.2.99 +Version: 1.4.0 Release: 1%{?dist} Summary: ZeroTier One network virtualization service @@ -145,6 +145,9 @@ esac %endif %changelog +* Mon Jul 29 2019 Adam Ierymenko - 1.4.0-0.1 +- see https://github.com/zerotier/ZeroTierOne for release notes + * Tue May 08 2018 Adam Ierymenko - 1.2.10-0.1 - see https://github.com/zerotier/ZeroTierOne for release notes From 79c4d98b61604f40991009d8ff440d21b6b5492e Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 29 Jul 2019 12:10:39 -0700 Subject: [PATCH 072/185] docs --- AUTHORS.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/AUTHORS.md b/AUTHORS.md index ca47fef0..c4c0c730 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -65,3 +65,9 @@ ZeroTier includes the following third party code, either in ext/ or incorporated * Files: ext/libnatpmp/* ext/miniupnpc/* * Home page: http://miniupnp.free.fr/ * License grant: BSD attribution no-endorsement + + * cpp-httplib by yhirose + + * Files: ext/cpp-httplib/* + * Home page: https://github.com/yhirose/cpp-httplib + * License grant: MIT From 5cc0dd7f55a5061785a1422a015950e6e4dec06d Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 29 Jul 2019 12:36:10 -0700 Subject: [PATCH 073/185] Windows installer version bump --- ext/installfiles/windows/ZeroTier One.aip | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ext/installfiles/windows/ZeroTier One.aip b/ext/installfiles/windows/ZeroTier One.aip index df9a5064..26b529d7 100644 --- a/ext/installfiles/windows/ZeroTier One.aip +++ b/ext/installfiles/windows/ZeroTier One.aip @@ -27,10 +27,10 @@ - + - + @@ -64,7 +64,7 @@ - + @@ -454,10 +454,10 @@ - + - + From 8c3c07cb5d6849d6f232c93c528fe44bcc3cd03b Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 29 Jul 2019 13:50:02 -0700 Subject: [PATCH 074/185] docs --- COPYING | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/COPYING b/COPYING index 8008d3e0..c43e8e7b 100644 --- a/COPYING +++ b/COPYING @@ -1,5 +1,5 @@ ZeroTier One, an endpoint server for the ZeroTier virtual network layer. -Copyright © 2011–2018 ZeroTier, Inc. +Copyright © 2011–2019 ZeroTier, Inc. ZeroTier One is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by From 837c6270f2c4ab859d5c51fa0c422194b2fb4db3 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 29 Jul 2019 15:14:37 -0700 Subject: [PATCH 075/185] More docs --- LICENSE.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE.txt b/LICENSE.txt index 8fd274be..3807fea3 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,5 +1,5 @@ ZeroTier One - Network Virtualization Everywhere -Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ +Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by From db813db7e875c257e42c41ab8091c3df1e9300a5 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 29 Jul 2019 16:11:06 -0700 Subject: [PATCH 076/185] 2019-07-29 -- Version 1.4.0 Major Changes * Mac version no longer requires a kernel extension, instead making use of the [feth interfaces](https://apple.stackexc * Added support for concurrent multipath (multiple paths at once) with traffic weighting by link quality and faster rec * Added under-the-hood support for QoS (not yet exposed) that will eventually be configurable via our rules engine. Minor Changes and Bug Fixes * Experimental DB driver for [LF](https://github.com/zerotier/lf) to store network controller data (LFDB.cpp / LFDB.hpp * Modified credential push and direct path push timings and algorithms to somewhat reduce "chattiness" of the protocol * Removed our beta/half-baked integration of Central with the Windows UI. We're going to do a whole new UI of some kind * Fixed stack overflow issues on Linux versions using musl libc. * Fixed some alignment problems reported on ARM and ARM64, but some reports we could not reproduce so please report any * Fixed numerous other small issues and bugs such as ARM alignment issues causing crashes on some devices. * Windows now sets the adapter name such that it is consistent in both the Windows UI and command line utilities. --- RELEASE-NOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 3ae31f0f..1dd56b9f 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -11,7 +11,7 @@ ZeroTier Release Notes ### Minor Changes and Bug Fixes - * Experimental DB driver for [LF](https://github.com/zerotier/lf) to store network controller data (LFDB.cpp / LFDB.hpp). + * Experimental controller DB driver for [LF](https://github.com/zerotier/lf) to store network controller data (LFDB.cpp / LFDB.hpp). * Modified credential push and direct path push timings and algorithms to somewhat reduce "chattiness" of the protocol when idle. More radical background overhead reductions will have to wait for the 2.x line. * Removed our beta/half-baked integration of Central with the Windows UI. We're going to do a whole new UI of some kind in the future at least for Windows and Mac. * Fixed stack overflow issues on Linux versions using musl libc. From 632d6e04ad76bd45307d2706e62416e64a89a736 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 31 Jul 2019 13:25:58 -0700 Subject: [PATCH 077/185] Mac multicast bug fix -- GitHub issue #986 --- osdep/MacEthernetTap.cpp | 5 +++-- version.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/osdep/MacEthernetTap.cpp b/osdep/MacEthernetTap.cpp index 0f534299..a11a75e2 100644 --- a/osdep/MacEthernetTap.cpp +++ b/osdep/MacEthernetTap.cpp @@ -165,6 +165,7 @@ MacEthernetTap::MacEthernetTap( break; } } + _dev = devstr; if (::pipe(_shutdownSignalPipe)) throw std::runtime_error("pipe creation failed"); @@ -285,7 +286,7 @@ std::vector MacEthernetTap::ips() const if (!getifaddrs(&ifa)) { struct ifaddrs *p = ifa; while (p) { - if ((!strcmp(p->ifa_name,_dev.c_str()))&&(p->ifa_addr)&&(p->ifa_netmask)&&(p->ifa_addr->sa_family == p->ifa_netmask->sa_family)) { + if ((p->ifa_name)&&(!strcmp(p->ifa_name,_dev.c_str()))&&(p->ifa_addr)) { switch(p->ifa_addr->sa_family) { case AF_INET: { struct sockaddr_in *sin = (struct sockaddr_in *)p->ifa_addr; @@ -361,7 +362,7 @@ void MacEthernetTap::scanMulticastGroups(std::vector &added,std: newGroups.push_back(MulticastGroup::deriveMulticastGroupForAddressResolution(*ip)); std::sort(newGroups.begin(),newGroups.end()); - std::unique(newGroups.begin(),newGroups.end()); + newGroups.erase(std::unique(newGroups.begin(),newGroups.end()),newGroups.end()); for(std::vector::iterator m(newGroups.begin());m!=newGroups.end();++m) { if (!std::binary_search(_multicastGroups.begin(),_multicastGroups.end(),*m)) diff --git a/version.h b/version.h index 82013819..8e380a1d 100644 --- a/version.h +++ b/version.h @@ -49,7 +49,7 @@ * to force a minor update without an actual version number change. It's * not part of the actual release version number. */ -#define ZEROTIER_ONE_VERSION_BUILD 0 +#define ZEROTIER_ONE_VERSION_BUILD 1 #ifndef ZT_BUILD_ARCHITECTURE #define ZT_BUILD_ARCHITECTURE 0 From b3891e5506985ee28730364b0ef5d2f7857a3ea9 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 31 Jul 2019 13:27:08 -0700 Subject: [PATCH 078/185] Version 1.4.0.1: bug fix for Mac multicast and IPv4 issues, no change for other platforms --- ext/installfiles/mac/ZeroTier One.pkgproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/installfiles/mac/ZeroTier One.pkgproj b/ext/installfiles/mac/ZeroTier One.pkgproj index 7652041d..ea67928b 100755 --- a/ext/installfiles/mac/ZeroTier One.pkgproj +++ b/ext/installfiles/mac/ZeroTier One.pkgproj @@ -664,7 +664,7 @@ USE_HFS+_COMPRESSION VERSION - 1.4.0 + 1.4.0.1 PROJECT_COMMENTS From bb99ef1351b72260836db29d5863ca1ee6dc0478 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 31 Jul 2019 16:41:12 -0700 Subject: [PATCH 079/185] Get rid of online status stuff in FileDB, not necessary at all. --- controller/FileDB.cpp | 50 ------------------------------------------- 1 file changed, 50 deletions(-) diff --git a/controller/FileDB.cpp b/controller/FileDB.cpp index 7b997c49..cda978b8 100644 --- a/controller/FileDB.cpp +++ b/controller/FileDB.cpp @@ -71,54 +71,6 @@ FileDB::FileDB(const Identity &myId,const char *path) : } catch ( ... ) {} } } - - _onlineUpdateThread = std::thread([this]() { - unsigned int cnt = 0; - while (this->_running) { - std::this_thread::sleep_for(std::chrono::microseconds(100)); - if ((++cnt % 20) == 0) { // 5 seconds - std::lock_guard l(this->_online_l); - if (!this->_running) return; - if (this->_onlineChanged) { - char p[4096],atmp[64]; - for(auto nw=this->_online.begin();nw!=this->_online.end();++nw) { - OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx-online.json",_networksPath.c_str(),(unsigned long long)nw->first); - FILE *f = fopen(p,"wb"); - if (f) { - fprintf(f,"{"); - const char *memberPrefix = ""; - for(auto m=nw->second.begin();m!=nw->second.end();++m) { - fprintf(f,"%s\"%.10llx\":{" ZT_EOL_S,memberPrefix,(unsigned long long)m->first); - memberPrefix = ","; - InetAddress lastAddr; - const char *timestampPrefix = " "; - int cnt = 0; - for(auto ts=m->second.rbegin();ts!=m->second.rend();) { - if (cnt < 25) { - if (lastAddr != ts->second) { - lastAddr = ts->second; - fprintf(f,"%s\"%lld\":\"%s\"" ZT_EOL_S,timestampPrefix,(long long)ts->first,ts->second.toString(atmp)); - timestampPrefix = ","; - ++cnt; - ++ts; - } else { - ts = std::map::reverse_iterator(m->second.erase(std::next(ts).base())); - } - } else { - ts = std::map::reverse_iterator(m->second.erase(std::next(ts).base())); - } - } - fprintf(f,"}"); - } - fprintf(f,"}" ZT_EOL_S); - fclose(f); - } - } - this->_onlineChanged = false; - } - } - } - }); } FileDB::~FileDB() @@ -195,8 +147,6 @@ void FileDB::eraseNetwork(const uint64_t networkId) char p[16384]; OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx.json",_networksPath.c_str(),networkId); OSUtils::rm(p); - OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx-online.json",_networksPath.c_str(),networkId); - OSUtils::rm(p); OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx" ZT_PATH_SEPARATOR_S "member",_networksPath.c_str(),(unsigned long long)networkId); OSUtils::rmDashRf(p); _networkChanged(network,nullJson,true); From 34364ab8ee5be36b975ea5fc141a31e3c508aae1 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 31 Jul 2019 16:41:35 -0700 Subject: [PATCH 080/185] Bump version --- version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.h b/version.h index 8e380a1d..808cf8dd 100644 --- a/version.h +++ b/version.h @@ -40,7 +40,7 @@ /** * Revision */ -#define ZEROTIER_ONE_VERSION_REVISION 0 +#define ZEROTIER_ONE_VERSION_REVISION 1 /** * Build version @@ -49,7 +49,7 @@ * to force a minor update without an actual version number change. It's * not part of the actual release version number. */ -#define ZEROTIER_ONE_VERSION_BUILD 1 +#define ZEROTIER_ONE_VERSION_BUILD 0 #ifndef ZT_BUILD_ARCHITECTURE #define ZT_BUILD_ARCHITECTURE 0 From 67beea1e3d0615d0053ba0be6bed8f62d0207d02 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 1 Aug 2019 13:21:36 -0700 Subject: [PATCH 081/185] Batch file to clean Windows build dir --- windows-clean.bat | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 windows-clean.bat diff --git a/windows-clean.bat b/windows-clean.bat new file mode 100644 index 00000000..09e5e28b --- /dev/null +++ b/windows-clean.bat @@ -0,0 +1,9 @@ +DEL "ZeroTier One.msi" +DEL zt1_update*.exe +RMDIR /Q /S windows\Build +RMDIR /Q /S windows\copyutil\bin +RMDIR /Q /S windows\copyutil\obj +RMDIR /Q /S windows\WinUI\bin +RMDIR /Q /S windows\WinUI\obj +RMDIR /Q /S windows\ZeroTierOne\Release +RMDIR /Q /S windows\ZeroTierOne\x64 From fdc708a624873da84409af4466e0d432e98253ac Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 2 Aug 2019 13:59:03 -0700 Subject: [PATCH 082/185] GitHub issue #979 --- service/OneService.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/service/OneService.cpp b/service/OneService.cpp index 40ffce2f..43f5d9c9 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -994,15 +994,17 @@ public: Mutex::Lock _l2(_localConfig_m); std::string lcbuf; if (OSUtils::readFile((_homePath + ZT_PATH_SEPARATOR_S "local.conf").c_str(),lcbuf)) { - try { - _localConfig = OSUtils::jsonParse(lcbuf); - if (!_localConfig.is_object()) { - fprintf(stderr,"ERROR: unable to parse local.conf (root element is not a JSON object)" ZT_EOL_S); + if (lcbuf.length() > 0) { + try { + _localConfig = OSUtils::jsonParse(lcbuf); + if (!_localConfig.is_object()) { + fprintf(stderr,"ERROR: unable to parse local.conf (root element is not a JSON object)" ZT_EOL_S); + exit(1); + } + } catch ( ... ) { + fprintf(stderr,"ERROR: unable to parse local.conf (invalid JSON)" ZT_EOL_S); exit(1); } - } catch ( ... ) { - fprintf(stderr,"ERROR: unable to parse local.conf (invalid JSON)" ZT_EOL_S); - exit(1); } } From 75ebe5172f6eac21f2d113efae478c4b01f2fd0c Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 2 Aug 2019 20:43:02 -0700 Subject: [PATCH 083/185] Fix for sharing of capabilities in 1.4 (problem introduced when push frequency was reduced) --- node/Membership.cpp | 23 +++++++++++++++-------- node/Membership.hpp | 3 +-- node/Network.hpp | 4 ++-- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/node/Membership.cpp b/node/Membership.cpp index 92dd30cb..031eb0b7 100644 --- a/node/Membership.cpp +++ b/node/Membership.cpp @@ -48,9 +48,12 @@ Membership::Membership() : { } -void Membership::pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const int64_t now,const Address &peerAddress,const NetworkConfig &nconf,int localCapabilityIndex) +void Membership::pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const int64_t now,const Address &peerAddress,const NetworkConfig &nconf) { - const Capability *sendCap = (localCapabilityIndex >= 0) ? &(nconf.capabilities[localCapabilityIndex]) : (const Capability *)0; + const Capability *sendCaps[ZT_MAX_NETWORK_CAPABILITIES]; + unsigned int sendCapCount = 0; + for(unsigned int c=0;cidentity.address(),Packet::VERB_NETWORK_CREDENTIALS); if (sendCom) { @@ -74,11 +78,14 @@ void Membership::pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const i } outp.append((uint8_t)0x00); - if (sendCap) { - outp.append((uint16_t)1); - sendCap->serialize(outp); - sendCap = (const Capability *)0; - } else outp.append((uint16_t)0); + const unsigned int capCountAt = outp.size(); + outp.addSize(2); + unsigned int thisPacketCapCount = 0; + while ((capPtr < sendCapCount)&&((outp.size() + sizeof(Capability) + 16) < ZT_PROTO_MAX_PACKET_LENGTH)) { + sendCaps[capPtr++]->serialize(outp); + ++thisPacketCapCount; + } + outp.setAt(capCountAt,(uint16_t)thisPacketCapCount); const unsigned int tagCountAt = outp.size(); outp.addSize(2); diff --git a/node/Membership.hpp b/node/Membership.hpp index 6f2d0339..506573ed 100644 --- a/node/Membership.hpp +++ b/node/Membership.hpp @@ -74,9 +74,8 @@ public: * @param now Current time * @param peerAddress Address of member peer (the one that this Membership describes) * @param nconf My network config - * @param localCapabilityIndex Index of local capability to include (in nconf.capabilities[]) or -1 if none */ - void pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const int64_t now,const Address &peerAddress,const NetworkConfig &nconf,int localCapabilityIndex); + void pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const int64_t now,const Address &peerAddress,const NetworkConfig &nconf); /** * @return True if we haven't pushed credentials in a long time (to cause proactive credential push) diff --git a/node/Network.hpp b/node/Network.hpp index 969e1f14..5e573812 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -365,7 +365,7 @@ public: inline void pushCredentialsNow(void *tPtr,const Address &to,const int64_t now) { Mutex::Lock _l(_lock); - _membership(to).pushCredentials(RR,tPtr,now,to,_config,-1); + _membership(to).pushCredentials(RR,tPtr,now,to,_config); } /** @@ -380,7 +380,7 @@ public: Mutex::Lock _l(_lock); Membership &m = _membership(to); if (m.shouldPushCredentials(now)) - m.pushCredentials(RR,tPtr,now,to,_config,-1); + m.pushCredentials(RR,tPtr,now,to,_config); } /** From 639fc602572bfa61c86041c954149370355b4c24 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Sun, 4 Aug 2019 15:08:33 -0700 Subject: [PATCH 084/185] GitHub issue #990 --- node/Membership.hpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/node/Membership.hpp b/node/Membership.hpp index 506573ed..73e11c6c 100644 --- a/node/Membership.hpp +++ b/node/Membership.hpp @@ -136,7 +136,7 @@ public: if (_isCredentialTimestampValid(nconf,*v)&&(v->owns(r))) return true; } - return false; + return _isV6NDPEmulated(nconf,r); } /** @@ -191,6 +191,15 @@ public: static uint64_t credentialKey(const Credential::Type &t,const uint32_t i) { return (((uint64_t)t << 32) | (uint64_t)i); } private: + inline bool _isV6NDPEmulated(const NetworkConfig &nconf,const MAC &m) const { return false; } + inline bool _isV6NDPEmulated(const NetworkConfig &nconf,const InetAddress &ip) const + { + if ((ip.isV6())&&(nconf.ndpEmulation())&&((InetAddress::makeIpv66plane(nconf.networkId,nconf.issuedTo.toInt()).ipsEqual(ip))||(InetAddress::makeIpv6rfc4193(nconf.networkId,nconf.issuedTo.toInt()).ipsEqual(ip)))) { + return true; + } + return false; + } + template inline bool _isCredentialTimestampValid(const NetworkConfig &nconf,const C &remoteCredential) const { From 00d63f604682c9e16bcfa179ca3de0822b87affd Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Sun, 4 Aug 2019 15:15:02 -0700 Subject: [PATCH 085/185] GitHub issue #993 (???) --- node/Multicaster.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/node/Multicaster.hpp b/node/Multicaster.hpp index 2cdcfb82..c55c6f3c 100644 --- a/node/Multicaster.hpp +++ b/node/Multicaster.hpp @@ -168,6 +168,7 @@ private: MulticastGroup mg; inline bool operator==(const Key &k) const { return ((nwid == k.nwid)&&(mg == k.mg)); } + inline bool operator!=(const Key &k) const { return ((nwid != k.nwid)||(mg != k.mg)); } inline unsigned long hashCode() const { return (mg.hashCode() ^ (unsigned long)(nwid ^ (nwid >> 32))); } }; From 818b7e4a2e35adfc241aed38e90b34580e6b5d9d Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Sun, 4 Aug 2019 15:35:43 -0700 Subject: [PATCH 086/185] GitHub issue #993 (???) --- node/Multicaster.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/node/Multicaster.hpp b/node/Multicaster.hpp index c55c6f3c..971f84af 100644 --- a/node/Multicaster.hpp +++ b/node/Multicaster.hpp @@ -177,6 +177,9 @@ private: MulticastGroupMember() {} MulticastGroupMember(const Address &a,uint64_t ts) : address(a),timestamp(ts) {} + inline bool operator<(const MulticastGroupMember &a) const { return (address < a.address); } + inline bool operator==(const MulticastGroupMember &a) const { return (address == a.address); } + inline bool operator!=(const MulticastGroupMember &a) const { return (address != a.address); } inline bool operator<(const Address &a) const { return (address < a); } inline bool operator==(const Address &a) const { return (address == a); } inline bool operator!=(const Address &a) const { return (address != a); } From a77b4ecddb43cd8581c7ebaeb8fcc9b5dac10573 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Sun, 4 Aug 2019 19:55:52 -0700 Subject: [PATCH 087/185] Add optional function in DB change listener for member online events. --- controller/DB.hpp | 1 + controller/FileDB.cpp | 15 +++++++++------ controller/FileDB.hpp | 1 - controller/LFDB.cpp | 25 ++++++++++++++++--------- controller/PostgreSQL.cpp | 17 ++++++++++++----- 5 files changed, 38 insertions(+), 21 deletions(-) diff --git a/controller/DB.hpp b/controller/DB.hpp index f499d387..85920eec 100644 --- a/controller/DB.hpp +++ b/controller/DB.hpp @@ -61,6 +61,7 @@ public: virtual void onNetworkUpdate(uint64_t networkId,const nlohmann::json &network) {} virtual void onNetworkMemberUpdate(uint64_t networkId,uint64_t memberId,const nlohmann::json &member) {} virtual void onNetworkMemberDeauthorize(uint64_t networkId,uint64_t memberId) {} + virtual void onNetworkMemberOnline(uint64_t networkId,uint64_t memberId,const InetAddress &physicalAddress) {} }; struct NetworkSummaryInfo diff --git a/controller/FileDB.cpp b/controller/FileDB.cpp index cda978b8..484aefa5 100644 --- a/controller/FileDB.cpp +++ b/controller/FileDB.cpp @@ -33,7 +33,6 @@ FileDB::FileDB(const Identity &myId,const char *path) : DB(myId,path), _networksPath(_path + ZT_PATH_SEPARATOR_S + "network"), _tracePath(_path + ZT_PATH_SEPARATOR_S + "trace"), - _onlineChanged(false), _running(true) { OSUtils::mkdir(_path.c_str()); @@ -152,7 +151,6 @@ void FileDB::eraseNetwork(const uint64_t networkId) _networkChanged(network,nullJson,true); std::lock_guard l(this->_online_l); this->_online.erase(networkId); - this->_onlineChanged = true; } void FileDB::eraseMember(const uint64_t networkId,const uint64_t memberId) @@ -166,7 +164,6 @@ void FileDB::eraseMember(const uint64_t networkId,const uint64_t memberId) _memberChanged(member,nullJson,true); std::lock_guard l(this->_online_l); this->_online[networkId].erase(memberId); - this->_onlineChanged = true; } void FileDB::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress) @@ -174,9 +171,15 @@ void FileDB::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const char mid[32],atmp[64]; OSUtils::ztsnprintf(mid,sizeof(mid),"%.10llx",(unsigned long long)memberId); physicalAddress.toString(atmp); - std::lock_guard l(this->_online_l); - this->_online[networkId][memberId][OSUtils::now()] = physicalAddress; - this->_onlineChanged = true; + { + std::lock_guard l(this->_online_l); + this->_online[networkId][memberId][OSUtils::now()] = physicalAddress; + } + { + std::lock_guard l2(_changeListeners_l); + for(auto i=_changeListeners.begin();i!=_changeListeners.end();++i) + (*i)->onNetworkMemberOnline(networkId,memberId,physicalAddress); + } } } // namespace ZeroTier diff --git a/controller/FileDB.hpp b/controller/FileDB.hpp index 5d55d0a4..33efb725 100644 --- a/controller/FileDB.hpp +++ b/controller/FileDB.hpp @@ -51,7 +51,6 @@ protected: std::thread _onlineUpdateThread; std::map< uint64_t,std::map > > _online; std::mutex _online_l; - bool _onlineChanged; bool _running; }; diff --git a/controller/LFDB.cpp b/controller/LFDB.cpp index f0c8ebfb..999eca72 100644 --- a/controller/LFDB.cpp +++ b/controller/LFDB.cpp @@ -384,17 +384,24 @@ void LFDB::eraseMember(const uint64_t networkId,const uint64_t memberId) void LFDB::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress) { - std::lock_guard l(_state_l); - auto nw = _state.find(networkId); - if (nw != _state.end()) { - auto m = nw->second.members.find(memberId); - if (m != nw->second.members.end()) { - m->second.lastOnlineTime = OSUtils::now(); - if (physicalAddress) - m->second.lastOnlineAddress = physicalAddress; - m->second.lastOnlineDirty = true; + { + std::lock_guard l(_state_l); + auto nw = _state.find(networkId); + if (nw != _state.end()) { + auto m = nw->second.members.find(memberId); + if (m != nw->second.members.end()) { + m->second.lastOnlineTime = OSUtils::now(); + if (physicalAddress) + m->second.lastOnlineAddress = physicalAddress; + m->second.lastOnlineDirty = true; + } } } + { + std::lock_guard l2(_changeListeners_l); + for(auto i=_changeListeners.begin();i!=_changeListeners.end();++i) + (*i)->onNetworkMemberOnline(networkId,memberId,physicalAddress); + } } } // namespace ZeroTier diff --git a/controller/PostgreSQL.cpp b/controller/PostgreSQL.cpp index e2bcfe58..709712b5 100644 --- a/controller/PostgreSQL.cpp +++ b/controller/PostgreSQL.cpp @@ -210,11 +210,18 @@ void PostgreSQL::eraseMember(const uint64_t networkId, const uint64_t memberId) void PostgreSQL::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress &physicalAddress) { - std::lock_guard l(_lastOnline_l); - std::pair &i = _lastOnline[std::pair(networkId, memberId)]; - i.first = OSUtils::now(); - if (physicalAddress) { - i.second = physicalAddress; + { + std::lock_guard l(_lastOnline_l); + std::pair &i = _lastOnline[std::pair(networkId, memberId)]; + i.first = OSUtils::now(); + if (physicalAddress) { + i.second = physicalAddress; + } + } + { + std::lock_guard l2(_changeListeners_l); + for(auto i=_changeListeners.begin();i!=_changeListeners.end();++i) + (*i)->onNetworkMemberOnline(networkId,memberId,physicalAddress); } } From 772235017892b30054013d9d10af93f42a421efa Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Sun, 4 Aug 2019 20:13:12 -0700 Subject: [PATCH 088/185] Version bump to 1.4.2 for all but Windows AIP --- debian/changelog | 6 ++++++ ext/installfiles/mac/ZeroTier One.pkgproj | 2 +- version.h | 2 +- windows/WinUI/AboutView.xaml | 2 +- zerotier-one.spec | 5 ++++- 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/debian/changelog b/debian/changelog index d290ba94..d5c049ad 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +zerotier-one (1.4.2) unstable; urgency=medium + + * See https://github.com/zerotier/ZeroTierOne for release notes. + + -- Adam Ierymenko Thu, 04 Aug 2019 01:00:00 -0700 + zerotier-one (1.4.0) unstable; urgency=medium * See https://github.com/zerotier/ZeroTierOne for release notes. diff --git a/ext/installfiles/mac/ZeroTier One.pkgproj b/ext/installfiles/mac/ZeroTier One.pkgproj index ea67928b..afda6554 100755 --- a/ext/installfiles/mac/ZeroTier One.pkgproj +++ b/ext/installfiles/mac/ZeroTier One.pkgproj @@ -664,7 +664,7 @@ USE_HFS+_COMPRESSION VERSION - 1.4.0.1 + 1.4.2 PROJECT_COMMENTS diff --git a/version.h b/version.h index 808cf8dd..10678793 100644 --- a/version.h +++ b/version.h @@ -40,7 +40,7 @@ /** * Revision */ -#define ZEROTIER_ONE_VERSION_REVISION 1 +#define ZEROTIER_ONE_VERSION_REVISION 2 /** * Build version diff --git a/windows/WinUI/AboutView.xaml b/windows/WinUI/AboutView.xaml index d8525f2a..43dca4c0 100644 --- a/windows/WinUI/AboutView.xaml +++ b/windows/WinUI/AboutView.xaml @@ -19,7 +19,7 @@ - + diff --git a/zerotier-one.spec b/zerotier-one.spec index 72217215..6123eb70 100644 --- a/zerotier-one.spec +++ b/zerotier-one.spec @@ -1,5 +1,5 @@ Name: zerotier-one -Version: 1.4.0 +Version: 1.4.2 Release: 1%{?dist} Summary: ZeroTier One network virtualization service @@ -145,6 +145,9 @@ esac %endif %changelog +* Mon Aug 04 2019 Adam Ierymenko - 1.4.2-0.1 +- see https://github.com/zerotier/ZeroTierOne for release notes + * Mon Jul 29 2019 Adam Ierymenko - 1.4.0-0.1 - see https://github.com/zerotier/ZeroTierOne for release notes From cd2e3c79f217ec9f105d9c480a509633c4cd910d Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Sun, 4 Aug 2019 20:27:09 -0700 Subject: [PATCH 089/185] Windows AIP version bump --- ext/installfiles/windows/ZeroTier One.aip | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/installfiles/windows/ZeroTier One.aip b/ext/installfiles/windows/ZeroTier One.aip index 26b529d7..1694f87f 100644 --- a/ext/installfiles/windows/ZeroTier One.aip +++ b/ext/installfiles/windows/ZeroTier One.aip @@ -27,10 +27,10 @@ - + - + @@ -64,7 +64,7 @@ - + @@ -454,7 +454,7 @@ - + From f4f8fef82ed336d3a50dced91462462fbe61d58e Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 5 Aug 2019 15:30:03 -0500 Subject: [PATCH 090/185] LFDB fix --- controller/LFDB.cpp | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/controller/LFDB.cpp b/controller/LFDB.cpp index 999eca72..a7bbf81d 100644 --- a/controller/LFDB.cpp +++ b/controller/LFDB.cpp @@ -64,7 +64,7 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons httplib::Client htcli(_lfNodeHost.c_str(),_lfNodePort,600); int64_t timeRangeStart = 0; - while (_running) { + while (_running.load()) { { std::lock_guard sl(_state_l); for(auto ns=_state.begin();ns!=_state.end();++ns) { @@ -178,7 +178,7 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons << "\"Name\":\"" << networksSelectorName << "\"," << "\"Range\":[0,18446744073709551615]" << "}]," - << "\"TimeRange\":[" << timeRangeStart << ",18446744073709551615]," + << "\"TimeRange\":[" << timeRangeStart << ",9223372036854775807]," << "\"MaskingKey\":\"" << maskingKey << "\"," << "\"Owners\":[\"" << _lfOwnerPublic << "\"]" << '}'; @@ -190,6 +190,7 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons for(std::size_t ri=0;ri 0)) { + nlohmann::json &result = rset[0]; if (result.is_object()) { nlohmann::json &record = result["Record"]; @@ -206,7 +207,7 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons _NetworkState &ns = _state[id]; if (!ns.dirty) { nlohmann::json oldNetwork; - if (get(id,oldNetwork)) { + if ((timeRangeStart > 0)&&(get(id,oldNetwork))) { const uint64_t revision = network["revision"]; const uint64_t prevRevision = oldNetwork["revision"]; if (prevRevision < revision) { @@ -222,6 +223,7 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons } } } + } } } @@ -244,7 +246,7 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons << "\"Name\":\"" << membersSelectorName << "\"," << "\"Range\":[0,18446744073709551615]" << "}]," - << "\"TimeRange\":[" << timeRangeStart << ",18446744073709551615]," + << "\"TimeRange\":[" << timeRangeStart << ",9223372036854775807]," << "\"MaskingKey\":\"" << maskingKey << "\"," << "\"Owners\":[\"" << _lfOwnerPublic << "\"]" << '}'; @@ -256,6 +258,7 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons for(std::size_t ri=0;ri 0)) { + nlohmann::json &result = rset[0]; if (result.is_object()) { nlohmann::json &record = result["Record"]; @@ -274,7 +277,7 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons auto ns = _state.find(nwid); if ((ns == _state.end())||(!ns->second.members[id].dirty)) { nlohmann::json network,oldMember; - if (get(nwid,network,id,oldMember)) { + if ((timeRangeStart > 0)&&(get(nwid,network,id,oldMember))) { const uint64_t revision = member["revision"]; const uint64_t prevRevision = oldMember["revision"]; if (prevRevision < revision) @@ -289,6 +292,7 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons } } } + } } } @@ -301,12 +305,12 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons } timeRangeStart = time(nullptr) - 120; // start next query 2m before now to avoid losing updates - _ready = true; + _ready.store(true); - for(int k=0;k<20;++k) { // 2s delay between queries for remotely modified networks or members - if (!_running) + for(int k=0;k<4;++k) { // 2s delay between queries for remotely modified networks or members + if (!_running.load()) return; - std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); } } }); @@ -314,21 +318,21 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons LFDB::~LFDB() { - _running = false; + _running.store(false); _syncThread.join(); } bool LFDB::waitForReady() { - while (!_ready) { - std::this_thread::sleep_for(std::chrono::milliseconds(100)); + while (!_ready.load()) { + std::this_thread::sleep_for(std::chrono::milliseconds(500)); } return true; } bool LFDB::isReady() { - return (_ready); + return (_ready.load()); } void LFDB::save(nlohmann::json *orig,nlohmann::json &record) From 37d508ab969afaf16c2aee1838a225022de34177 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 6 Aug 2019 07:51:50 -0500 Subject: [PATCH 091/185] Refactoring in prep for mirroring --- controller/DB.cpp | 6 +- controller/DB.hpp | 11 +- controller/EmbeddedNetworkController.cpp | 6 +- controller/EmbeddedNetworkController.hpp | 6 +- controller/FileDB.cpp | 2 +- controller/LFDB.cpp | 2 +- controller/PostgreSQL.cpp | 29 +++-- controller/PostgreSQL.hpp | 89 +++++++-------- controller/RabbitMQ.cpp | 134 +++++++++++------------ controller/RabbitMQ.hpp | 32 +++--- 10 files changed, 163 insertions(+), 154 deletions(-) diff --git a/controller/DB.cpp b/controller/DB.cpp index bb734dc8..75adf53e 100644 --- a/controller/DB.cpp +++ b/controller/DB.cpp @@ -313,7 +313,7 @@ void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool in if (initialized) { std::lock_guard ll(_changeListeners_l); for(auto i=_changeListeners.begin();i!=_changeListeners.end();++i) { - (*i)->onNetworkMemberUpdate(networkId,memberId,memberConfig); + (*i)->onNetworkMemberUpdate(this,networkId,memberId,memberConfig); } } } else if (memberId) { @@ -336,7 +336,7 @@ void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool in if ((initialized)&&((wasAuth)&&(!isAuth)&&(networkId)&&(memberId))) { std::lock_guard ll(_changeListeners_l); for(auto i=_changeListeners.begin();i!=_changeListeners.end();++i) { - (*i)->onNetworkMemberDeauthorize(networkId,memberId); + (*i)->onNetworkMemberDeauthorize(this,networkId,memberId); } } } @@ -362,7 +362,7 @@ void DB::_networkChanged(nlohmann::json &old,nlohmann::json &networkConfig,bool if (initialized) { std::lock_guard ll(_changeListeners_l); for(auto i=_changeListeners.begin();i!=_changeListeners.end();++i) { - (*i)->onNetworkUpdate(networkId,networkConfig); + (*i)->onNetworkUpdate(this,networkId,networkConfig); } } } diff --git a/controller/DB.hpp b/controller/DB.hpp index 85920eec..461f385e 100644 --- a/controller/DB.hpp +++ b/controller/DB.hpp @@ -58,10 +58,10 @@ public: public: ChangeListener() {} virtual ~ChangeListener() {} - virtual void onNetworkUpdate(uint64_t networkId,const nlohmann::json &network) {} - virtual void onNetworkMemberUpdate(uint64_t networkId,uint64_t memberId,const nlohmann::json &member) {} - virtual void onNetworkMemberDeauthorize(uint64_t networkId,uint64_t memberId) {} - virtual void onNetworkMemberOnline(uint64_t networkId,uint64_t memberId,const InetAddress &physicalAddress) {} + virtual void onNetworkUpdate(const DB *db,uint64_t networkId,const nlohmann::json &network) {} + virtual void onNetworkMemberUpdate(const DB *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member) {} + virtual void onNetworkMemberDeauthorize(const DB *db,uint64_t networkId,uint64_t memberId) {} + virtual void onNetworkMemberOnline(const DB *db,uint64_t networkId,uint64_t memberId,const InetAddress &physicalAddress) {} }; struct NetworkSummaryInfo @@ -95,12 +95,15 @@ public: bool get(const uint64_t networkId,nlohmann::json &network,const uint64_t memberId,nlohmann::json &member); bool get(const uint64_t networkId,nlohmann::json &network,const uint64_t memberId,nlohmann::json &member,NetworkSummaryInfo &info); bool get(const uint64_t networkId,nlohmann::json &network,std::vector &members); + bool summary(const uint64_t networkId,NetworkSummaryInfo &info); void networks(std::vector &networks); virtual void save(nlohmann::json *orig,nlohmann::json &record) = 0; + virtual void eraseNetwork(const uint64_t networkId) = 0; virtual void eraseMember(const uint64_t networkId,const uint64_t memberId) = 0; + virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress) = 0; inline void addListener(DB::ChangeListener *const listener) diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index bf568527..80331578 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -1190,7 +1190,7 @@ void EmbeddedNetworkController::handleRemoteTrace(const ZT_RemoteTrace &rt) } } -void EmbeddedNetworkController::onNetworkUpdate(const uint64_t networkId,const nlohmann::json &network) +void EmbeddedNetworkController::onNetworkUpdate(const DB *db,uint64_t networkId,const nlohmann::json &network) { // Send an update to all members of the network that are online const int64_t now = OSUtils::now(); @@ -1201,7 +1201,7 @@ void EmbeddedNetworkController::onNetworkUpdate(const uint64_t networkId,const n } } -void EmbeddedNetworkController::onNetworkMemberUpdate(const uint64_t networkId,const uint64_t memberId,const nlohmann::json &member) +void EmbeddedNetworkController::onNetworkMemberUpdate(const DB *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member) { // Push update to member if online try { @@ -1212,7 +1212,7 @@ void EmbeddedNetworkController::onNetworkMemberUpdate(const uint64_t networkId,c } catch ( ... ) {} } -void EmbeddedNetworkController::onNetworkMemberDeauthorize(const uint64_t networkId,const uint64_t memberId) +void EmbeddedNetworkController::onNetworkMemberDeauthorize(const DB *db,uint64_t networkId,uint64_t memberId) { const int64_t now = OSUtils::now(); Revocation rev((uint32_t)_node->prng(),networkId,0,now,ZT_REVOCATION_FLAG_FAST_PROPAGATE,Address(memberId),Revocation::CREDENTIAL_TYPE_COM); diff --git a/controller/EmbeddedNetworkController.hpp b/controller/EmbeddedNetworkController.hpp index 7bc37be2..c0f14f8b 100644 --- a/controller/EmbeddedNetworkController.hpp +++ b/controller/EmbeddedNetworkController.hpp @@ -101,9 +101,9 @@ public: void handleRemoteTrace(const ZT_RemoteTrace &rt); - virtual void onNetworkUpdate(const uint64_t networkId,const nlohmann::json &network); - virtual void onNetworkMemberUpdate(const uint64_t networkId,const uint64_t memberId,const nlohmann::json &member); - virtual void onNetworkMemberDeauthorize(const uint64_t networkId,const uint64_t memberId); + virtual void onNetworkUpdate(const DB *db,uint64_t networkId,const nlohmann::json &network); + virtual void onNetworkMemberUpdate(const DB *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member); + virtual void onNetworkMemberDeauthorize(const DB *db,uint64_t networkId,uint64_t memberId); private: void _request(uint64_t nwid,const InetAddress &fromAddr,uint64_t requestPacketId,const Identity &identity,const Dictionary &metaData); diff --git a/controller/FileDB.cpp b/controller/FileDB.cpp index 484aefa5..acc8680e 100644 --- a/controller/FileDB.cpp +++ b/controller/FileDB.cpp @@ -178,7 +178,7 @@ void FileDB::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const { std::lock_guard l2(_changeListeners_l); for(auto i=_changeListeners.begin();i!=_changeListeners.end();++i) - (*i)->onNetworkMemberOnline(networkId,memberId,physicalAddress); + (*i)->onNetworkMemberOnline(this,networkId,memberId,physicalAddress); } } diff --git a/controller/LFDB.cpp b/controller/LFDB.cpp index a7bbf81d..9203a5a1 100644 --- a/controller/LFDB.cpp +++ b/controller/LFDB.cpp @@ -404,7 +404,7 @@ void LFDB::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const I { std::lock_guard l2(_changeListeners_l); for(auto i=_changeListeners.begin();i!=_changeListeners.end();++i) - (*i)->onNetworkMemberOnline(networkId,memberId,physicalAddress); + (*i)->onNetworkMemberOnline(this,networkId,memberId,physicalAddress); } } diff --git a/controller/PostgreSQL.cpp b/controller/PostgreSQL.cpp index 709712b5..45be3e51 100644 --- a/controller/PostgreSQL.cpp +++ b/controller/PostgreSQL.cpp @@ -24,9 +24,11 @@ * of your own application. */ +#include "PostgreSQL.hpp" + #ifdef ZT_CONTROLLER_USE_LIBPQ -#include "PostgreSQL.hpp" +#include "../node/Constants.hpp" #include "EmbeddedNetworkController.hpp" #include "RabbitMQ.hpp" #include "../version.h" @@ -37,6 +39,7 @@ #include using json = nlohmann::json; + namespace { static const int DB_MINIMUM_VERSION = 5; @@ -73,16 +76,16 @@ std::string join(const std::vector &elements, const char * const se } } -} +} // anonymous namespace using namespace ZeroTier; PostgreSQL::PostgreSQL(const Identity &myId, const char *path, int listenPort, MQConfig *mqc) - : DB(myId, path) - , _ready(0) + : DB(myId, path) + , _ready(0) , _connected(1) - , _run(1) - , _waitNoticePrinted(false) + , _run(1) + , _waitNoticePrinted(false) , _listenPort(listenPort) , _mqc(mqc) { @@ -221,7 +224,7 @@ void PostgreSQL::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, { std::lock_guard l2(_changeListeners_l); for(auto i=_changeListeners.begin();i!=_changeListeners.end();++i) - (*i)->onNetworkMemberOnline(networkId,memberId,physicalAddress); + (*i)->onNetworkMemberOnline(this,networkId,memberId,physicalAddress); } } @@ -602,8 +605,8 @@ void PostgreSQL::heartbeat() "public_identity = EXCLUDED.public_identity, v_major = EXCLUDED.v_major, v_minor = EXCLUDED.v_minor, " "v_rev = EXCLUDED.v_rev, v_build = EXCLUDED.v_rev, host_port = EXCLUDED.host_port, " "use_rabbitmq = EXCLUDED.use_rabbitmq", - 10, // number of parameters - NULL, // oid field. ignore + 10, // number of parameters + NULL, // oid field. ignore values, // values for substitution NULL, // lengths in bytes of each value NULL, // binary? @@ -724,7 +727,7 @@ void PostgreSQL::_membersWatcher_RabbitMQ() { fprintf(stderr, "RABBITMQ ERROR member change: %s\n", e.what()); } catch(...) { fprintf(stderr, "RABBITMQ ERROR member change: unknown error\n"); - } + } } } @@ -1324,7 +1327,7 @@ void PostgreSQL::onlineNotificationThread() int64_t lastUpdatedNetworkStatus = 0; std::unordered_map< std::pair,int64_t,_PairHasher > lastOnlineCumulative; - + while (_run == 1) { if (PQstatus(conn) != CONNECTION_OK) { fprintf(stderr, "ERROR: Online Notification thread lost connection to Postgres."); @@ -1438,7 +1441,8 @@ void PostgreSQL::onlineNotificationThread() } } -PGconn *PostgreSQL::getPgConn(OverrideMode m) { +PGconn *PostgreSQL::getPgConn(OverrideMode m) +{ if (m == ALLOW_PGBOUNCER_OVERRIDE) { char *connStr = getenv("PGBOUNCER_CONNSTR"); if (connStr != NULL) { @@ -1452,4 +1456,5 @@ PGconn *PostgreSQL::getPgConn(OverrideMode m) { return PQconnectdb(_connString.c_str()); } + #endif //ZT_CONTROLLER_USE_LIBPQ diff --git a/controller/PostgreSQL.hpp b/controller/PostgreSQL.hpp index f35f89fc..fe69635d 100644 --- a/controller/PostgreSQL.hpp +++ b/controller/PostgreSQL.hpp @@ -24,6 +24,8 @@ * of your own application. */ +#define ZT_CONTROLLER_USE_LIBPQ + #ifdef ZT_CONTROLLER_USE_LIBPQ #ifndef ZT_CONTROLLER_LIBPQ_HPP @@ -34,11 +36,10 @@ #define ZT_CENTRAL_CONTROLLER_COMMIT_THREADS 4 extern "C" { - typedef struct pg_conn PGconn; +typedef struct pg_conn PGconn; } -namespace ZeroTier -{ +namespace ZeroTier { struct MQConfig; @@ -51,66 +52,66 @@ struct MQConfig; class PostgreSQL : public DB { public: - PostgreSQL(const Identity &myId, const char *path, int listenPort, MQConfig *mqc = NULL); - virtual ~PostgreSQL(); + PostgreSQL(const Identity &myId, const char *path, int listenPort, MQConfig *mqc = NULL); + virtual ~PostgreSQL(); - virtual bool waitForReady(); - virtual bool isReady(); - virtual void save(nlohmann::json *orig, nlohmann::json &record); - virtual void eraseNetwork(const uint64_t networkId); - virtual void eraseMember(const uint64_t networkId, const uint64_t memberId); - virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress &physicalAddress); + virtual bool waitForReady(); + virtual bool isReady(); + virtual void save(nlohmann::json *orig, nlohmann::json &record); + virtual void eraseNetwork(const uint64_t networkId); + virtual void eraseMember(const uint64_t networkId, const uint64_t memberId); + virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress &physicalAddress); protected: - struct _PairHasher + struct _PairHasher { inline std::size_t operator()(const std::pair &p) const { return (std::size_t)(p.first ^ p.second); } }; private: - void initializeNetworks(PGconn *conn); - void initializeMembers(PGconn *conn); - void heartbeat(); - void membersDbWatcher(); - void _membersWatcher_Postgres(PGconn *conn); - void _membersWatcher_RabbitMQ(); - void networksDbWatcher(); - void _networksWatcher_Postgres(PGconn *conn); - void _networksWatcher_RabbitMQ(); - - void commitThread(); - void onlineNotificationThread(); - - enum OverrideMode { - ALLOW_PGBOUNCER_OVERRIDE = 0, - NO_OVERRIDE = 1 - }; + void initializeNetworks(PGconn *conn); + void initializeMembers(PGconn *conn); + void heartbeat(); + void membersDbWatcher(); + void _membersWatcher_Postgres(PGconn *conn); + void _membersWatcher_RabbitMQ(); + void networksDbWatcher(); + void _networksWatcher_Postgres(PGconn *conn); + void _networksWatcher_RabbitMQ(); + + void commitThread(); + void onlineNotificationThread(); + + enum OverrideMode { + ALLOW_PGBOUNCER_OVERRIDE = 0, + NO_OVERRIDE = 1 + }; - PGconn * getPgConn( OverrideMode m = ALLOW_PGBOUNCER_OVERRIDE ); + PGconn * getPgConn( OverrideMode m = ALLOW_PGBOUNCER_OVERRIDE ); - std::string _connString; + std::string _connString; - BlockingQueue _commitQueue; + BlockingQueue _commitQueue; - std::thread _heartbeatThread; - std::thread _membersDbWatcher; - std::thread _networksDbWatcher; - std::thread _commitThread[ZT_CENTRAL_CONTROLLER_COMMIT_THREADS]; - std::thread _onlineNotificationThread; + std::thread _heartbeatThread; + std::thread _membersDbWatcher; + std::thread _networksDbWatcher; + std::thread _commitThread[ZT_CENTRAL_CONTROLLER_COMMIT_THREADS]; + std::thread _onlineNotificationThread; std::unordered_map< std::pair,std::pair,_PairHasher > _lastOnline; - mutable std::mutex _lastOnline_l; - mutable std::mutex _readyLock; - std::atomic _ready, _connected, _run; - mutable volatile bool _waitNoticePrinted; + mutable std::mutex _lastOnline_l; + mutable std::mutex _readyLock; + std::atomic _ready, _connected, _run; + mutable volatile bool _waitNoticePrinted; - int _listenPort; + int _listenPort; - MQConfig *_mqc; + MQConfig *_mqc; }; -} +} // namespace ZeroTier #endif // ZT_CONTROLLER_LIBPQ_HPP diff --git a/controller/RabbitMQ.cpp b/controller/RabbitMQ.cpp index eec9745d..cf5c567d 100644 --- a/controller/RabbitMQ.cpp +++ b/controller/RabbitMQ.cpp @@ -11,95 +11,95 @@ namespace ZeroTier { RabbitMQ::RabbitMQ(MQConfig *cfg, const char *queueName) - : _mqc(cfg) - , _qName(queueName) - , _socket(NULL) - , _status(0) + : _mqc(cfg) + , _qName(queueName) + , _socket(NULL) + , _status(0) { } RabbitMQ::~RabbitMQ() { - amqp_channel_close(_conn, _channel, AMQP_REPLY_SUCCESS); - amqp_connection_close(_conn, AMQP_REPLY_SUCCESS); - amqp_destroy_connection(_conn); + amqp_channel_close(_conn, _channel, AMQP_REPLY_SUCCESS); + amqp_connection_close(_conn, AMQP_REPLY_SUCCESS); + amqp_destroy_connection(_conn); } void RabbitMQ::init() { - struct timeval tval; - memset(&tval, 0, sizeof(struct timeval)); - tval.tv_sec = 5; + struct timeval tval; + memset(&tval, 0, sizeof(struct timeval)); + tval.tv_sec = 5; - fprintf(stderr, "Initializing RabbitMQ %s\n", _qName); - _conn = amqp_new_connection(); - _socket = amqp_tcp_socket_new(_conn); - if (!_socket) { - throw std::runtime_error("Can't create socket for RabbitMQ"); - } - - _status = amqp_socket_open_noblock(_socket, _mqc->host, _mqc->port, &tval); - if (_status) { - throw std::runtime_error("Can't connect to RabbitMQ"); - } - - amqp_rpc_reply_t r = amqp_login(_conn, "/", 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, - _mqc->username, _mqc->password); - if (r.reply_type != AMQP_RESPONSE_NORMAL) { - throw std::runtime_error("RabbitMQ Login Error"); - } + fprintf(stderr, "Initializing RabbitMQ %s\n", _qName); + _conn = amqp_new_connection(); + _socket = amqp_tcp_socket_new(_conn); + if (!_socket) { + throw std::runtime_error("Can't create socket for RabbitMQ"); + } + + _status = amqp_socket_open_noblock(_socket, _mqc->host, _mqc->port, &tval); + if (_status) { + throw std::runtime_error("Can't connect to RabbitMQ"); + } + + amqp_rpc_reply_t r = amqp_login(_conn, "/", 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, + _mqc->username, _mqc->password); + if (r.reply_type != AMQP_RESPONSE_NORMAL) { + throw std::runtime_error("RabbitMQ Login Error"); + } - static int chan = 0; + static int chan = 0; { Mutex::Lock l(_chan_m); - _channel = ++chan; + _channel = ++chan; + } + amqp_channel_open(_conn, _channel); + r = amqp_get_rpc_reply(_conn); + if(r.reply_type != AMQP_RESPONSE_NORMAL) { + throw std::runtime_error("Error opening communication channel"); + } + + _q = amqp_queue_declare(_conn, _channel, amqp_cstring_bytes(_qName), 0, 0, 0, 0, amqp_empty_table); + r = amqp_get_rpc_reply(_conn); + if (r.reply_type != AMQP_RESPONSE_NORMAL) { + throw std::runtime_error("Error declaring queue " + std::string(_qName)); } - amqp_channel_open(_conn, _channel); - r = amqp_get_rpc_reply(_conn); - if(r.reply_type != AMQP_RESPONSE_NORMAL) { - throw std::runtime_error("Error opening communication channel"); - } - - _q = amqp_queue_declare(_conn, _channel, amqp_cstring_bytes(_qName), 0, 0, 0, 0, amqp_empty_table); - r = amqp_get_rpc_reply(_conn); - if (r.reply_type != AMQP_RESPONSE_NORMAL) { - throw std::runtime_error("Error declaring queue " + std::string(_qName)); - } - amqp_basic_consume(_conn, _channel, amqp_cstring_bytes(_qName), amqp_empty_bytes, 0, 1, 0, amqp_empty_table); - r = amqp_get_rpc_reply(_conn); - if (r.reply_type != AMQP_RESPONSE_NORMAL) { - throw std::runtime_error("Error consuming queue " + std::string(_qName)); - } - fprintf(stderr, "RabbitMQ Init OK %s\n", _qName); + amqp_basic_consume(_conn, _channel, amqp_cstring_bytes(_qName), amqp_empty_bytes, 0, 1, 0, amqp_empty_table); + r = amqp_get_rpc_reply(_conn); + if (r.reply_type != AMQP_RESPONSE_NORMAL) { + throw std::runtime_error("Error consuming queue " + std::string(_qName)); + } + fprintf(stderr, "RabbitMQ Init OK %s\n", _qName); } std::string RabbitMQ::consume() { - amqp_rpc_reply_t res; - amqp_envelope_t envelope; - amqp_maybe_release_buffers(_conn); + amqp_rpc_reply_t res; + amqp_envelope_t envelope; + amqp_maybe_release_buffers(_conn); - struct timeval timeout; - timeout.tv_sec = 1; - timeout.tv_usec = 0; + struct timeval timeout; + timeout.tv_sec = 1; + timeout.tv_usec = 0; - res = amqp_consume_message(_conn, &envelope, &timeout, 0); - if (res.reply_type != AMQP_RESPONSE_NORMAL) { - if (res.reply_type == AMQP_RESPONSE_LIBRARY_EXCEPTION && res.library_error == AMQP_STATUS_TIMEOUT) { - // timeout waiting for message. Return empty string - return ""; - } else { - throw std::runtime_error("Error getting message"); - } - } + res = amqp_consume_message(_conn, &envelope, &timeout, 0); + if (res.reply_type != AMQP_RESPONSE_NORMAL) { + if (res.reply_type == AMQP_RESPONSE_LIBRARY_EXCEPTION && res.library_error == AMQP_STATUS_TIMEOUT) { + // timeout waiting for message. Return empty string + return ""; + } else { + throw std::runtime_error("Error getting message"); + } + } - std::string msg( - (const char*)envelope.message.body.bytes, - envelope.message.body.len - ); - amqp_destroy_envelope(&envelope); - return msg; + std::string msg( + (const char*)envelope.message.body.bytes, + envelope.message.body.len + ); + amqp_destroy_envelope(&envelope); + return msg; } } diff --git a/controller/RabbitMQ.hpp b/controller/RabbitMQ.hpp index d341681b..6bac68da 100644 --- a/controller/RabbitMQ.hpp +++ b/controller/RabbitMQ.hpp @@ -23,16 +23,17 @@ * directly against ZeroTier software without disclosing the source code * of your own application. */ + #ifndef ZT_CONTROLLER_RABBITMQ_HPP #define ZT_CONTROLLER_RABBITMQ_HPP namespace ZeroTier { struct MQConfig { - const char *host; - int port; - const char *username; - const char *password; + const char *host; + int port; + const char *username; + const char *password; }; } @@ -49,26 +50,25 @@ namespace ZeroTier class RabbitMQ { public: - RabbitMQ(MQConfig *cfg, const char *queueName); - ~RabbitMQ(); + RabbitMQ(MQConfig *cfg, const char *queueName); + ~RabbitMQ(); - void init(); + void init(); - std::string consume(); + std::string consume(); private: - MQConfig *_mqc; - const char *_qName; + MQConfig *_mqc; + const char *_qName; - amqp_socket_t *_socket; - amqp_connection_state_t _conn; - amqp_queue_declare_ok_t *_q; - int _status; + amqp_socket_t *_socket; + amqp_connection_state_t _conn; + amqp_queue_declare_ok_t *_q; + int _status; - int _channel; + int _channel; Mutex _chan_m; - }; } From 3c776675b3824d4497d913386793efaece2ee7d1 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 6 Aug 2019 08:51:23 -0500 Subject: [PATCH 092/185] Cruftectomy, work in progress on mirrorring --- controller/DB.hpp | 4 +- controller/DBMirrorSet.cpp | 112 +++++++++++++++++++++++ controller/DBMirrorSet.hpp | 70 ++++++++++++++ controller/EmbeddedNetworkController.cpp | 15 ++- controller/FileDB.cpp | 22 ++--- controller/FileDB.hpp | 2 +- controller/LFDB.cpp | 12 +-- controller/LFDB.hpp | 2 +- controller/PostgreSQL.cpp | 28 +++++- controller/PostgreSQL.hpp | 8 +- controller/RabbitMQ.cpp | 27 ++++++ controller/RabbitMQ.hpp | 2 + 12 files changed, 261 insertions(+), 43 deletions(-) create mode 100644 controller/DBMirrorSet.cpp create mode 100644 controller/DBMirrorSet.hpp diff --git a/controller/DB.hpp b/controller/DB.hpp index 461f385e..732a6e25 100644 --- a/controller/DB.hpp +++ b/controller/DB.hpp @@ -27,6 +27,8 @@ #ifndef ZT_CONTROLLER_DB_HPP #define ZT_CONTROLLER_DB_HPP +#define ZT_CONTROLLER_USE_LIBPQ + #include "../node/Constants.hpp" #include "../node/Identity.hpp" #include "../node/InetAddress.hpp" @@ -99,7 +101,7 @@ public: bool summary(const uint64_t networkId,NetworkSummaryInfo &info); void networks(std::vector &networks); - virtual void save(nlohmann::json *orig,nlohmann::json &record) = 0; + virtual void save(nlohmann::json &record) = 0; virtual void eraseNetwork(const uint64_t networkId) = 0; virtual void eraseMember(const uint64_t networkId,const uint64_t memberId) = 0; diff --git a/controller/DBMirrorSet.cpp b/controller/DBMirrorSet.cpp new file mode 100644 index 00000000..bccdefdd --- /dev/null +++ b/controller/DBMirrorSet.cpp @@ -0,0 +1,112 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + +#include "DBMirrorSet.hpp" + +namespace ZeroTier { + +DBMirrorSet::DBMirrorSet() +{ +} + +DBMirrorSet::~DBMirrorSet() +{ +} + +bool DBMirrorSet::waitForReady() +{ + bool r = false; + std::lock_guard l(_dbs_l); + for(auto d=_dbs.begin();d!=_dbs.end();++d) { + r |= (*d)->waitForReady(); + } + return r; +} + +bool DBMirrorSet::isReady() +{ + std::lock_guard l(_dbs_l); + for(auto d=_dbs.begin();d!=_dbs.end();++d) { + if (!(*d)->isReady()) + return false; + } + return true; +} + +void DBMirrorSet::save(nlohmann::json &record) +{ + std::lock_guard l(_dbs_l); + for(auto d=_dbs.begin();d!=_dbs.end();++d) { + (*d)->save(record); + } +} + +void DBMirrorSet::eraseNetwork(const uint64_t networkId) +{ + std::lock_guard l(_dbs_l); + for(auto d=_dbs.begin();d!=_dbs.end();++d) { + (*d)->eraseNetwork(networkId); + } +} + +void DBMirrorSet::eraseMember(const uint64_t networkId,const uint64_t memberId) +{ + std::lock_guard l(_dbs_l); + for(auto d=_dbs.begin();d!=_dbs.end();++d) { + (*d)->eraseMember(networkId,memberId); + } +} + +void DBMirrorSet::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress) +{ + std::lock_guard l(_dbs_l); + for(auto d=_dbs.begin();d!=_dbs.end();++d) { + (*d)->nodeIsOnline(networkId,memberId,physicalAddress); + } +} + +void DBMirrorSet::onNetworkUpdate(const DB *db,uint64_t networkId,const nlohmann::json &network) +{ + std::lock_guard l(_dbs_l); + for(auto d=_dbs.begin();d!=_dbs.end();++d) { + if (d->get() != db) { + } + } +} + +void DBMirrorSet::onNetworkMemberUpdate(const DB *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member) +{ +} + +void DBMirrorSet::onNetworkMemberDeauthorize(const DB *db,uint64_t networkId,uint64_t memberId) +{ +} + +void DBMirrorSet::onNetworkMemberOnline(const DB *db,uint64_t networkId,uint64_t memberId,const InetAddress &physicalAddress) +{ +} + +} // namespace ZeroTier diff --git a/controller/DBMirrorSet.hpp b/controller/DBMirrorSet.hpp new file mode 100644 index 00000000..1af0018e --- /dev/null +++ b/controller/DBMirrorSet.hpp @@ -0,0 +1,70 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + +#ifndef ZT_DBMIRRORSET_HPP +#define ZT_DBMIRRORSET_HPP + +#include "DB.hpp" + +#include +#include +#include + +namespace ZeroTier { + +class DBMirrorSet : public DB::ChangeListener +{ +public: + DBMirrorSet(); + virtual ~DBMirrorSet(); + + bool waitForReady(); + bool isReady(); + void save(nlohmann::json &record); + void eraseNetwork(const uint64_t networkId); + void eraseMember(const uint64_t networkId,const uint64_t memberId); + void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress); + + // These are called by various DB instances when changes occur. + virtual void onNetworkUpdate(const DB *db,uint64_t networkId,const nlohmann::json &network); + virtual void onNetworkMemberUpdate(const DB *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member); + virtual void onNetworkMemberDeauthorize(const DB *db,uint64_t networkId,uint64_t memberId); + virtual void onNetworkMemberOnline(const DB *db,uint64_t networkId,uint64_t memberId,const InetAddress &physicalAddress); + + inline void addDB(const std::shared_ptr &db) + { + std::lock_guard l(_dbs_l); + _dbs.push_back(db); + } + +private: + std::vector< std::shared_ptr< DB > > _dbs; + std::mutex _dbs_l; +}; + +} // namespace ZeroTier + +#endif diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index 80331578..d9c6364b 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -705,7 +705,6 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( json member,network; _db->get(nwid,network,address,member); - json origMember(member); // for detecting changes DB::initMember(member); try { @@ -799,7 +798,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( member["nwid"] = nwids; DB::cleanMember(member); - _db->save(&origMember,member); + _db->save(member); responseBody = OSUtils::jsonDump(member); responseContentType = "application/json"; @@ -830,7 +829,6 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( json network; _db->get(nwid,network); - json origNetwork(network); // for detecting changes DB::initNetwork(network); try { @@ -1061,7 +1059,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( network["nwid"] = nwids; // legacy DB::cleanNetwork(network); - _db->save(&origNetwork,network); + _db->save(network); responseBody = OSUtils::jsonDump(network); responseContentType = "application/json"; @@ -1184,7 +1182,7 @@ void EmbeddedNetworkController::handleRemoteTrace(const ZT_RemoteTrace &rt) d["objtype"] = "trace"; d["ts"] = now; d["nodeId"] = Utils::hex10(rt.origin,tmp); - _db->save((nlohmann::json *)0,d); + _db->save(d); } catch ( ... ) { // drop invalid trace messages if an error occurs } @@ -1235,7 +1233,7 @@ void EmbeddedNetworkController::_request( { char nwids[24]; DB::NetworkSummaryInfo ns; - json network,member,origMember; + json network,member; if (!_db) return; @@ -1261,7 +1259,6 @@ void EmbeddedNetworkController::_request( _sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_OBJECT_NOT_FOUND); return; } - origMember = member; const bool newMember = ((!member.is_object())||(member.size() == 0)); DB::initMember(member); @@ -1362,7 +1359,7 @@ void EmbeddedNetworkController::_request( } else { // If they are not authorized, STOP! DB::cleanMember(member); - _db->save(&origMember,member); + _db->save(member); _sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_ACCESS_DENIED); return; } @@ -1734,7 +1731,7 @@ void EmbeddedNetworkController::_request( } DB::cleanMember(member); - _db->save(&origMember,member); + _db->save(member); _sender->ncSendConfig(nwid,requestPacketId,identity.address(),*(nc.get()),metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_VERSION,0) < 6); } diff --git a/controller/FileDB.cpp b/controller/FileDB.cpp index acc8680e..66b3d2c2 100644 --- a/controller/FileDB.cpp +++ b/controller/FileDB.cpp @@ -85,38 +85,35 @@ FileDB::~FileDB() bool FileDB::waitForReady() { return true; } bool FileDB::isReady() { return true; } -void FileDB::save(nlohmann::json *orig,nlohmann::json &record) +void FileDB::save(nlohmann::json &record) { char p1[4096],p2[4096],pb[4096]; try { - if (orig) { - if (*orig != record) { - record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1; - } - } else { - record["revision"] = 1; - } - const std::string objtype = record["objtype"]; if (objtype == "network") { + const uint64_t nwid = OSUtils::jsonIntHex(record["id"],0ULL); if (nwid) { nlohmann::json old; get(nwid,old); if ((!old.is_object())||(old != record)) { + record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL; OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%.16llx.json",_networksPath.c_str(),nwid); if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) fprintf(stderr,"WARNING: controller unable to write to path: %s" ZT_EOL_S,p1); _networkChanged(old,record,true); } } + } else if (objtype == "member") { + const uint64_t id = OSUtils::jsonIntHex(record["id"],0ULL); const uint64_t nwid = OSUtils::jsonIntHex(record["nwid"],0ULL); if ((id)&&(nwid)) { nlohmann::json network,old; get(nwid,network,id,old); if ((!old.is_object())||(old != record)) { + record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL; OSUtils::ztsnprintf(pb,sizeof(pb),"%s" ZT_PATH_SEPARATOR_S "%.16llx" ZT_PATH_SEPARATOR_S "member",_networksPath.c_str(),(unsigned long long)nwid); OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%.10llx.json",pb,(unsigned long long)id); if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) { @@ -129,12 +126,7 @@ void FileDB::save(nlohmann::json *orig,nlohmann::json &record) _memberChanged(old,record,true); } } - } else if (objtype == "trace") { - const std::string id = record["id"]; - if (id.length() > 0) { - OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%s.json",_tracePath.c_str(),id.c_str()); - OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1)); - } + } } catch ( ... ) {} // drop invalid records missing fields } diff --git a/controller/FileDB.hpp b/controller/FileDB.hpp index 33efb725..deef8854 100644 --- a/controller/FileDB.hpp +++ b/controller/FileDB.hpp @@ -40,7 +40,7 @@ public: virtual bool waitForReady(); virtual bool isReady(); - virtual void save(nlohmann::json *orig,nlohmann::json &record); + virtual void save(nlohmann::json &record); virtual void eraseNetwork(const uint64_t networkId); virtual void eraseMember(const uint64_t networkId,const uint64_t memberId); virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress); diff --git a/controller/LFDB.cpp b/controller/LFDB.cpp index 9203a5a1..5bf0aaf7 100644 --- a/controller/LFDB.cpp +++ b/controller/LFDB.cpp @@ -335,16 +335,8 @@ bool LFDB::isReady() return (_ready.load()); } -void LFDB::save(nlohmann::json *orig,nlohmann::json &record) +void LFDB::save(nlohmann::json &record) { - if (orig) { - if (*orig != record) { - record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1; - } - } else { - record["revision"] = 1; - } - const std::string objtype = record["objtype"]; if (objtype == "network") { const uint64_t nwid = OSUtils::jsonIntHex(record["id"],0ULL); @@ -352,6 +344,7 @@ void LFDB::save(nlohmann::json *orig,nlohmann::json &record) nlohmann::json old; get(nwid,old); if ((!old.is_object())||(old != record)) { + record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL; _networkChanged(old,record,true); { std::lock_guard l(_state_l); @@ -366,6 +359,7 @@ void LFDB::save(nlohmann::json *orig,nlohmann::json &record) nlohmann::json network,old; get(nwid,network,id,old); if ((!old.is_object())||(old != record)) { + record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL; _memberChanged(old,record,true); { std::lock_guard l(_state_l); diff --git a/controller/LFDB.hpp b/controller/LFDB.hpp index 73187462..646da65d 100644 --- a/controller/LFDB.hpp +++ b/controller/LFDB.hpp @@ -56,7 +56,7 @@ public: virtual bool waitForReady(); virtual bool isReady(); - virtual void save(nlohmann::json *orig,nlohmann::json &record); + virtual void save(nlohmann::json &record); virtual void eraseNetwork(const uint64_t networkId); virtual void eraseMember(const uint64_t networkId,const uint64_t memberId); virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress); diff --git a/controller/PostgreSQL.cpp b/controller/PostgreSQL.cpp index 45be3e51..121d00df 100644 --- a/controller/PostgreSQL.cpp +++ b/controller/PostgreSQL.cpp @@ -165,12 +165,35 @@ bool PostgreSQL::isReady() return ((_ready == 2)&&(_connected)); } -void PostgreSQL::save(nlohmann::json *orig, nlohmann::json &record) +void PostgreSQL::save(nlohmann::json &record) { try { - if (!record.is_object()) { + if (!record.is_object()) return; + const std::string objtype = record["objtype"]; + if (objtype == "network") { + const uint64_t nwid = OSUtils::jsonIntHex(record["id"],0ULL); + if (nwid) { + nlohmann::json old; + get(nwid,old); + if ((!old.is_object())||(old != record)) { + record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL; + _commitQueue.post(new nlohmann::json(record)); + } + } + } else if (objtype == "member") { + const uint64_t nwid = OSUtils::jsonIntHex(record["nwid"],0ULL); + const uint64_t id = OSUtils::jsonIntHex(record["id"],0ULL); + if ((id)&&(nwid)) { + nlohmann::json network,old; + get(nwid,network,id,old); + if ((!old.is_object())||(old != record)) { + record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL; + _commitQueue.post(new nlohmann::json(record)); + } + } } + /* waitForReady(); if (orig) { if (*orig != record) { @@ -181,6 +204,7 @@ void PostgreSQL::save(nlohmann::json *orig, nlohmann::json &record) record["revision"] = 1; _commitQueue.post(new nlohmann::json(record)); } + */ } catch (std::exception &e) { fprintf(stderr, "Error on PostgreSQL::save: %s\n", e.what()); } catch (...) { diff --git a/controller/PostgreSQL.hpp b/controller/PostgreSQL.hpp index fe69635d..ce6fb242 100644 --- a/controller/PostgreSQL.hpp +++ b/controller/PostgreSQL.hpp @@ -23,16 +23,14 @@ * directly against ZeroTier software without disclosing the source code * of your own application. */ - -#define ZT_CONTROLLER_USE_LIBPQ + +#include "DB.hpp" #ifdef ZT_CONTROLLER_USE_LIBPQ #ifndef ZT_CONTROLLER_LIBPQ_HPP #define ZT_CONTROLLER_LIBPQ_HPP -#include "DB.hpp" - #define ZT_CENTRAL_CONTROLLER_COMMIT_THREADS 4 extern "C" { @@ -57,7 +55,7 @@ public: virtual bool waitForReady(); virtual bool isReady(); - virtual void save(nlohmann::json *orig, nlohmann::json &record); + virtual void save(nlohmann::json &record); virtual void eraseNetwork(const uint64_t networkId); virtual void eraseMember(const uint64_t networkId, const uint64_t memberId); virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress &physicalAddress); diff --git a/controller/RabbitMQ.cpp b/controller/RabbitMQ.cpp index cf5c567d..e14fbf3f 100644 --- a/controller/RabbitMQ.cpp +++ b/controller/RabbitMQ.cpp @@ -1,3 +1,30 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + + #include "RabbitMQ.hpp" #ifdef ZT_CONTROLLER_USE_LIBPQ diff --git a/controller/RabbitMQ.hpp b/controller/RabbitMQ.hpp index 6bac68da..c8ef31ca 100644 --- a/controller/RabbitMQ.hpp +++ b/controller/RabbitMQ.hpp @@ -27,6 +27,8 @@ #ifndef ZT_CONTROLLER_RABBITMQ_HPP #define ZT_CONTROLLER_RABBITMQ_HPP +#include "DB.hpp" + namespace ZeroTier { struct MQConfig { From 00fb9c475e7bd68a12d6d581539862c31aeb2e74 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 6 Aug 2019 10:42:54 -0500 Subject: [PATCH 093/185] More work on DB mirroring. --- controller/DB.cpp | 44 ++-------- controller/DB.hpp | 24 ++--- controller/DBMirrorSet.cpp | 106 ++++++++++++++++++++--- controller/DBMirrorSet.hpp | 25 ++++-- controller/EmbeddedNetworkController.cpp | 6 +- controller/EmbeddedNetworkController.hpp | 6 +- controller/FileDB.cpp | 26 +++--- controller/FileDB.hpp | 5 +- controller/LFDB.cpp | 37 ++++---- controller/LFDB.hpp | 4 +- controller/PostgreSQL.cpp | 71 ++++++++------- controller/PostgreSQL.hpp | 7 +- 12 files changed, 210 insertions(+), 151 deletions(-) diff --git a/controller/DB.cpp b/controller/DB.cpp index 75adf53e..a4440f38 100644 --- a/controller/DB.cpp +++ b/controller/DB.cpp @@ -104,16 +104,7 @@ void DB::cleanMember(nlohmann::json &member) member.erase("lastRequestMetaData"); } -DB::DB(const Identity &myId,const char *path) : - _myId(myId), - _myAddress(myId.address()), - _path((path) ? path : "") -{ - char tmp[32]; - _myAddress.toString(tmp); - _myAddressStr = tmp; -} - +DB::DB() {} DB::~DB() {} bool DB::get(const uint64_t networkId,nlohmann::json &network) @@ -199,34 +190,15 @@ bool DB::get(const uint64_t networkId,nlohmann::json &network,std::vector nw; - { - std::lock_guard l(_networks_l); - auto nwi = _networks.find(networkId); - if (nwi == _networks.end()) - return false; - nw = nwi->second; - } - { - std::lock_guard l2(nw->lock); - _fillSummaryInfo(nw,info); - } - return true; -} - -void DB::networks(std::vector &networks) +void DB::networks(std::set &networks) { waitForReady(); std::lock_guard l(_networks_l); - networks.reserve(_networks.size() + 1); for(auto n=_networks.begin();n!=_networks.end();++n) - networks.push_back(n->first); + networks.insert(n->first); } -void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool initialized) +void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool notifyListeners) { uint64_t memberId = 0; uint64_t networkId = 0; @@ -310,7 +282,7 @@ void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool in } } - if (initialized) { + if (notifyListeners) { std::lock_guard ll(_changeListeners_l); for(auto i=_changeListeners.begin();i!=_changeListeners.end();++i) { (*i)->onNetworkMemberUpdate(this,networkId,memberId,memberConfig); @@ -333,7 +305,7 @@ void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool in } } - if ((initialized)&&((wasAuth)&&(!isAuth)&&(networkId)&&(memberId))) { + if ((notifyListeners)&&((wasAuth)&&(!isAuth)&&(networkId)&&(memberId))) { std::lock_guard ll(_changeListeners_l); for(auto i=_changeListeners.begin();i!=_changeListeners.end();++i) { (*i)->onNetworkMemberDeauthorize(this,networkId,memberId); @@ -341,7 +313,7 @@ void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool in } } -void DB::_networkChanged(nlohmann::json &old,nlohmann::json &networkConfig,bool initialized) +void DB::_networkChanged(nlohmann::json &old,nlohmann::json &networkConfig,bool notifyListeners) { if (networkConfig.is_object()) { const std::string ids = networkConfig["id"]; @@ -359,7 +331,7 @@ void DB::_networkChanged(nlohmann::json &old,nlohmann::json &networkConfig,bool std::lock_guard l2(nw->lock); nw->config = networkConfig; } - if (initialized) { + if (notifyListeners) { std::lock_guard ll(_changeListeners_l); for(auto i=_changeListeners.begin();i!=_changeListeners.end();++i) { (*i)->onNetworkUpdate(this,networkId,networkConfig); diff --git a/controller/DB.hpp b/controller/DB.hpp index 732a6e25..e391538e 100644 --- a/controller/DB.hpp +++ b/controller/DB.hpp @@ -43,6 +43,7 @@ #include #include #include +#include #include "../ext/json/json.hpp" @@ -60,10 +61,9 @@ public: public: ChangeListener() {} virtual ~ChangeListener() {} - virtual void onNetworkUpdate(const DB *db,uint64_t networkId,const nlohmann::json &network) {} - virtual void onNetworkMemberUpdate(const DB *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member) {} - virtual void onNetworkMemberDeauthorize(const DB *db,uint64_t networkId,uint64_t memberId) {} - virtual void onNetworkMemberOnline(const DB *db,uint64_t networkId,uint64_t memberId,const InetAddress &physicalAddress) {} + virtual void onNetworkUpdate(const void *db,uint64_t networkId,const nlohmann::json &network) {} + virtual void onNetworkMemberUpdate(const void *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member) {} + virtual void onNetworkMemberDeauthorize(const void *db,uint64_t networkId,uint64_t memberId) {} }; struct NetworkSummaryInfo @@ -81,7 +81,7 @@ public: static void cleanNetwork(nlohmann::json &network); static void cleanMember(nlohmann::json &member); - DB(const Identity &myId,const char *path); + DB(); virtual ~DB(); virtual bool waitForReady() = 0; @@ -98,10 +98,9 @@ public: bool get(const uint64_t networkId,nlohmann::json &network,const uint64_t memberId,nlohmann::json &member,NetworkSummaryInfo &info); bool get(const uint64_t networkId,nlohmann::json &network,std::vector &members); - bool summary(const uint64_t networkId,NetworkSummaryInfo &info); - void networks(std::vector &networks); + void networks(std::set &networks); - virtual void save(nlohmann::json &record) = 0; + virtual bool save(nlohmann::json &record,bool notifyListeners) = 0; virtual void eraseNetwork(const uint64_t networkId) = 0; virtual void eraseMember(const uint64_t networkId,const uint64_t memberId) = 0; @@ -127,15 +126,10 @@ protected: std::mutex lock; }; - void _memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool initialized); - void _networkChanged(nlohmann::json &old,nlohmann::json &networkConfig,bool initialized); + void _memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool notifyListeners); + void _networkChanged(nlohmann::json &old,nlohmann::json &networkConfig,bool notifyListeners); void _fillSummaryInfo(const std::shared_ptr<_Network> &nw,NetworkSummaryInfo &info); - const Identity _myId; - const Address _myAddress; - const std::string _path; - std::string _myAddressStr; - std::vector _changeListeners; std::unordered_map< uint64_t,std::shared_ptr<_Network> > _networks; std::unordered_multimap< uint64_t,uint64_t > _networkByMember; diff --git a/controller/DBMirrorSet.cpp b/controller/DBMirrorSet.cpp index bccdefdd..63c0f58b 100644 --- a/controller/DBMirrorSet.cpp +++ b/controller/DBMirrorSet.cpp @@ -28,7 +28,8 @@ namespace ZeroTier { -DBMirrorSet::DBMirrorSet() +DBMirrorSet::DBMirrorSet(DB::ChangeListener *listener) : + _listener(listener) { } @@ -36,6 +37,65 @@ DBMirrorSet::~DBMirrorSet() { } +bool DBMirrorSet::hasNetwork(const uint64_t networkId) const +{ + std::lock_guard l(_dbs_l); + for(auto d=_dbs.begin();d!=_dbs.end();++d) { + if ((*d)->hasNetwork(networkId)) + return true; + } + return false; +} + +bool DBMirrorSet::get(const uint64_t networkId,nlohmann::json &network) +{ + std::lock_guard l(_dbs_l); + for(auto d=_dbs.begin();d!=_dbs.end();++d) { + if (get(networkId,network)) { + return true; + } + } + return false; +} + +bool DBMirrorSet::get(const uint64_t networkId,nlohmann::json &network,const uint64_t memberId,nlohmann::json &member) +{ + std::lock_guard l(_dbs_l); + for(auto d=_dbs.begin();d!=_dbs.end();++d) { + if (get(networkId,network,memberId,member)) + return true; + } + return false; +} + +bool DBMirrorSet::get(const uint64_t networkId,nlohmann::json &network,const uint64_t memberId,nlohmann::json &member,DB::NetworkSummaryInfo &info) +{ + std::lock_guard l(_dbs_l); + for(auto d=_dbs.begin();d!=_dbs.end();++d) { + if (get(networkId,network,memberId,member,info)) + return true; + } + return false; +} + +bool DBMirrorSet::get(const uint64_t networkId,nlohmann::json &network,std::vector &members) +{ + std::lock_guard l(_dbs_l); + for(auto d=_dbs.begin();d!=_dbs.end();++d) { + if (get(networkId,network,members)) + return true; + } + return false; +} + +void DBMirrorSet::networks(std::set &networks) +{ + std::lock_guard l(_dbs_l); + for(auto d=_dbs.begin();d!=_dbs.end();++d) { + (*d)->networks(networks); + } +} + bool DBMirrorSet::waitForReady() { bool r = false; @@ -56,11 +116,21 @@ bool DBMirrorSet::isReady() return true; } -void DBMirrorSet::save(nlohmann::json &record) +bool DBMirrorSet::save(nlohmann::json &record,bool notifyListeners) { std::lock_guard l(_dbs_l); - for(auto d=_dbs.begin();d!=_dbs.end();++d) { - (*d)->save(record); + if (notifyListeners) { + for(auto d=_dbs.begin();d!=_dbs.end();++d) { + if ((*d)->save(record,notifyListeners)) + return true; + } + return false; + } else { + bool modified = false; + for(auto d=_dbs.begin();d!=_dbs.end();++d) { + modified |= (*d)->save(record,notifyListeners); + } + return modified; } } @@ -88,25 +158,39 @@ void DBMirrorSet::nodeIsOnline(const uint64_t networkId,const uint64_t memberId, } } -void DBMirrorSet::onNetworkUpdate(const DB *db,uint64_t networkId,const nlohmann::json &network) +void DBMirrorSet::onNetworkUpdate(const void *db,uint64_t networkId,const nlohmann::json &network) { + bool modified = false; + nlohmann::json record(network); std::lock_guard l(_dbs_l); for(auto d=_dbs.begin();d!=_dbs.end();++d) { if (d->get() != db) { + modified |= (*d)->save(record,false); } } + if (modified) { + _listener->onNetworkUpdate(this,networkId,network); + } } -void DBMirrorSet::onNetworkMemberUpdate(const DB *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member) -{ -} - -void DBMirrorSet::onNetworkMemberDeauthorize(const DB *db,uint64_t networkId,uint64_t memberId) +void DBMirrorSet::onNetworkMemberUpdate(const void *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member) { + bool modified = false; + nlohmann::json record(member); + std::lock_guard l(_dbs_l); + for(auto d=_dbs.begin();d!=_dbs.end();++d) { + if (d->get() != db) { + modified |= (*d)->save(record,false); + } + } + if (modified) { + _listener->onNetworkMemberUpdate(this,networkId,memberId,member); + } } -void DBMirrorSet::onNetworkMemberOnline(const DB *db,uint64_t networkId,uint64_t memberId,const InetAddress &physicalAddress) +void DBMirrorSet::onNetworkMemberDeauthorize(const void *db,uint64_t networkId,uint64_t memberId) { + _listener->onNetworkMemberDeauthorize(this,networkId,memberId); } } // namespace ZeroTier diff --git a/controller/DBMirrorSet.hpp b/controller/DBMirrorSet.hpp index 1af0018e..aee598af 100644 --- a/controller/DBMirrorSet.hpp +++ b/controller/DBMirrorSet.hpp @@ -32,37 +32,48 @@ #include #include #include +#include namespace ZeroTier { class DBMirrorSet : public DB::ChangeListener { public: - DBMirrorSet(); + DBMirrorSet(DB::ChangeListener *listener); virtual ~DBMirrorSet(); + bool hasNetwork(const uint64_t networkId) const; + + bool get(const uint64_t networkId,nlohmann::json &network); + bool get(const uint64_t networkId,nlohmann::json &network,const uint64_t memberId,nlohmann::json &member); + bool get(const uint64_t networkId,nlohmann::json &network,const uint64_t memberId,nlohmann::json &member,DB::NetworkSummaryInfo &info); + bool get(const uint64_t networkId,nlohmann::json &network,std::vector &members); + + void networks(std::set &networks); + bool waitForReady(); bool isReady(); - void save(nlohmann::json &record); + bool save(nlohmann::json &record,bool notifyListeners); void eraseNetwork(const uint64_t networkId); void eraseMember(const uint64_t networkId,const uint64_t memberId); void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress); // These are called by various DB instances when changes occur. - virtual void onNetworkUpdate(const DB *db,uint64_t networkId,const nlohmann::json &network); - virtual void onNetworkMemberUpdate(const DB *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member); - virtual void onNetworkMemberDeauthorize(const DB *db,uint64_t networkId,uint64_t memberId); - virtual void onNetworkMemberOnline(const DB *db,uint64_t networkId,uint64_t memberId,const InetAddress &physicalAddress); + virtual void onNetworkUpdate(const void *db,uint64_t networkId,const nlohmann::json &network); + virtual void onNetworkMemberUpdate(const void *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member); + virtual void onNetworkMemberDeauthorize(const void *db,uint64_t networkId,uint64_t memberId); inline void addDB(const std::shared_ptr &db) { + db->addListener(this); std::lock_guard l(_dbs_l); _dbs.push_back(db); } private: + DB::ChangeListener *const _listener; std::vector< std::shared_ptr< DB > > _dbs; - std::mutex _dbs_l; + mutable std::mutex _dbs_l; }; } // namespace ZeroTier diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index d9c6364b..64acda0f 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -1188,7 +1188,7 @@ void EmbeddedNetworkController::handleRemoteTrace(const ZT_RemoteTrace &rt) } } -void EmbeddedNetworkController::onNetworkUpdate(const DB *db,uint64_t networkId,const nlohmann::json &network) +void EmbeddedNetworkController::onNetworkUpdate(const void *db,uint64_t networkId,const nlohmann::json &network) { // Send an update to all members of the network that are online const int64_t now = OSUtils::now(); @@ -1199,7 +1199,7 @@ void EmbeddedNetworkController::onNetworkUpdate(const DB *db,uint64_t networkId, } } -void EmbeddedNetworkController::onNetworkMemberUpdate(const DB *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member) +void EmbeddedNetworkController::onNetworkMemberUpdate(const void *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member) { // Push update to member if online try { @@ -1210,7 +1210,7 @@ void EmbeddedNetworkController::onNetworkMemberUpdate(const DB *db,uint64_t netw } catch ( ... ) {} } -void EmbeddedNetworkController::onNetworkMemberDeauthorize(const DB *db,uint64_t networkId,uint64_t memberId) +void EmbeddedNetworkController::onNetworkMemberDeauthorize(const void *db,uint64_t networkId,uint64_t memberId) { const int64_t now = OSUtils::now(); Revocation rev((uint32_t)_node->prng(),networkId,0,now,ZT_REVOCATION_FLAG_FAST_PROPAGATE,Address(memberId),Revocation::CREDENTIAL_TYPE_COM); diff --git a/controller/EmbeddedNetworkController.hpp b/controller/EmbeddedNetworkController.hpp index c0f14f8b..85223dc4 100644 --- a/controller/EmbeddedNetworkController.hpp +++ b/controller/EmbeddedNetworkController.hpp @@ -101,9 +101,9 @@ public: void handleRemoteTrace(const ZT_RemoteTrace &rt); - virtual void onNetworkUpdate(const DB *db,uint64_t networkId,const nlohmann::json &network); - virtual void onNetworkMemberUpdate(const DB *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member); - virtual void onNetworkMemberDeauthorize(const DB *db,uint64_t networkId,uint64_t memberId); + virtual void onNetworkUpdate(const void *db,uint64_t networkId,const nlohmann::json &network); + virtual void onNetworkMemberUpdate(const void *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member); + virtual void onNetworkMemberDeauthorize(const void *db,uint64_t networkId,uint64_t memberId); private: void _request(uint64_t nwid,const InetAddress &fromAddr,uint64_t requestPacketId,const Identity &identity,const Dictionary &metaData); diff --git a/controller/FileDB.cpp b/controller/FileDB.cpp index 66b3d2c2..1dc2498a 100644 --- a/controller/FileDB.cpp +++ b/controller/FileDB.cpp @@ -29,8 +29,9 @@ namespace ZeroTier { -FileDB::FileDB(const Identity &myId,const char *path) : - DB(myId,path), +FileDB::FileDB(const char *path) : + DB(), + _path(path), _networksPath(_path + ZT_PATH_SEPARATOR_S + "network"), _tracePath(_path + ZT_PATH_SEPARATOR_S + "trace"), _running(true) @@ -85,9 +86,10 @@ FileDB::~FileDB() bool FileDB::waitForReady() { return true; } bool FileDB::isReady() { return true; } -void FileDB::save(nlohmann::json &record) +bool FileDB::save(nlohmann::json &record,bool notifyListeners) { char p1[4096],p2[4096],pb[4096]; + bool modified = false; try { const std::string objtype = record["objtype"]; if (objtype == "network") { @@ -101,7 +103,8 @@ void FileDB::save(nlohmann::json &record) OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%.16llx.json",_networksPath.c_str(),nwid); if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) fprintf(stderr,"WARNING: controller unable to write to path: %s" ZT_EOL_S,p1); - _networkChanged(old,record,true); + _networkChanged(old,record,notifyListeners); + modified = true; } } @@ -123,12 +126,14 @@ void FileDB::save(nlohmann::json &record) if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) fprintf(stderr,"WARNING: controller unable to write to path: %s" ZT_EOL_S,p1); } - _memberChanged(old,record,true); + _memberChanged(old,record,notifyListeners); + modified = true; } } } } catch ( ... ) {} // drop invalid records missing fields + return modified; } void FileDB::eraseNetwork(const uint64_t networkId) @@ -163,15 +168,8 @@ void FileDB::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const char mid[32],atmp[64]; OSUtils::ztsnprintf(mid,sizeof(mid),"%.10llx",(unsigned long long)memberId); physicalAddress.toString(atmp); - { - std::lock_guard l(this->_online_l); - this->_online[networkId][memberId][OSUtils::now()] = physicalAddress; - } - { - std::lock_guard l2(_changeListeners_l); - for(auto i=_changeListeners.begin();i!=_changeListeners.end();++i) - (*i)->onNetworkMemberOnline(this,networkId,memberId,physicalAddress); - } + std::lock_guard l(this->_online_l); + this->_online[networkId][memberId][OSUtils::now()] = physicalAddress; } } // namespace ZeroTier diff --git a/controller/FileDB.hpp b/controller/FileDB.hpp index deef8854..8aa2c18e 100644 --- a/controller/FileDB.hpp +++ b/controller/FileDB.hpp @@ -35,17 +35,18 @@ namespace ZeroTier class FileDB : public DB { public: - FileDB(const Identity &myId,const char *path); + FileDB(const char *path); virtual ~FileDB(); virtual bool waitForReady(); virtual bool isReady(); - virtual void save(nlohmann::json &record); + virtual bool save(nlohmann::json &record,bool notifyListeners); virtual void eraseNetwork(const uint64_t networkId); virtual void eraseMember(const uint64_t networkId,const uint64_t memberId); virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress); protected: + std::string _path; std::string _networksPath; std::string _tracePath; std::thread _onlineUpdateThread; diff --git a/controller/LFDB.cpp b/controller/LFDB.cpp index 5bf0aaf7..5dd6d082 100644 --- a/controller/LFDB.cpp +++ b/controller/LFDB.cpp @@ -38,7 +38,7 @@ namespace ZeroTier { LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,const char *lfOwnerPublic,const char *lfNodeHost,int lfNodePort,bool storeOnlineState) : - DB(myId,path), + DB(), _myId(myId), _lfOwnerPrivate((lfOwnerPrivate) ? lfOwnerPrivate : ""), _lfOwnerPublic((lfOwnerPublic) ? lfOwnerPublic : ""), @@ -335,8 +335,9 @@ bool LFDB::isReady() return (_ready.load()); } -void LFDB::save(nlohmann::json &record) +bool LFDB::save(nlohmann::json &record,bool notifyListeners) { + bool modified = false; const std::string objtype = record["objtype"]; if (objtype == "network") { const uint64_t nwid = OSUtils::jsonIntHex(record["id"],0ULL); @@ -345,11 +346,12 @@ void LFDB::save(nlohmann::json &record) get(nwid,old); if ((!old.is_object())||(old != record)) { record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL; - _networkChanged(old,record,true); + _networkChanged(old,record,notifyListeners); { std::lock_guard l(_state_l); _state[nwid].dirty = true; } + modified = true; } } } else if (objtype == "member") { @@ -360,14 +362,16 @@ void LFDB::save(nlohmann::json &record) get(nwid,network,id,old); if ((!old.is_object())||(old != record)) { record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL; - _memberChanged(old,record,true); + _memberChanged(old,record,notifyListeners); { std::lock_guard l(_state_l); _state[nwid].members[id].dirty = true; } + modified = true; } } } + return modified; } void LFDB::eraseNetwork(const uint64_t networkId) @@ -382,24 +386,17 @@ void LFDB::eraseMember(const uint64_t networkId,const uint64_t memberId) void LFDB::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress) { - { - std::lock_guard l(_state_l); - auto nw = _state.find(networkId); - if (nw != _state.end()) { - auto m = nw->second.members.find(memberId); - if (m != nw->second.members.end()) { - m->second.lastOnlineTime = OSUtils::now(); - if (physicalAddress) - m->second.lastOnlineAddress = physicalAddress; - m->second.lastOnlineDirty = true; - } + std::lock_guard l(_state_l); + auto nw = _state.find(networkId); + if (nw != _state.end()) { + auto m = nw->second.members.find(memberId); + if (m != nw->second.members.end()) { + m->second.lastOnlineTime = OSUtils::now(); + if (physicalAddress) + m->second.lastOnlineAddress = physicalAddress; + m->second.lastOnlineDirty = true; } } - { - std::lock_guard l2(_changeListeners_l); - for(auto i=_changeListeners.begin();i!=_changeListeners.end();++i) - (*i)->onNetworkMemberOnline(this,networkId,memberId,physicalAddress); - } } } // namespace ZeroTier diff --git a/controller/LFDB.hpp b/controller/LFDB.hpp index 646da65d..bcd6cdd0 100644 --- a/controller/LFDB.hpp +++ b/controller/LFDB.hpp @@ -43,7 +43,7 @@ class LFDB : public DB { public: /** - * @param myId Identity of controller node (with secret) + * @param myId This controller's identity * @param path Base path for ZeroTier node itself * @param lfOwnerPrivate LF owner private in PEM format * @param lfOwnerPublic LF owner public in @base62 format @@ -56,7 +56,7 @@ public: virtual bool waitForReady(); virtual bool isReady(); - virtual void save(nlohmann::json &record); + virtual bool save(nlohmann::json &record,bool notifyListeners); virtual void eraseNetwork(const uint64_t networkId); virtual void eraseMember(const uint64_t networkId,const uint64_t memberId); virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress); diff --git a/controller/PostgreSQL.cpp b/controller/PostgreSQL.cpp index 121d00df..13b7b8d8 100644 --- a/controller/PostgreSQL.cpp +++ b/controller/PostgreSQL.cpp @@ -81,7 +81,9 @@ std::string join(const std::vector &elements, const char * const se using namespace ZeroTier; PostgreSQL::PostgreSQL(const Identity &myId, const char *path, int listenPort, MQConfig *mqc) - : DB(myId, path) + : DB() + , _myId(myId) + , _myAddress(myId.address()) , _ready(0) , _connected(1) , _run(1) @@ -89,7 +91,9 @@ PostgreSQL::PostgreSQL(const Identity &myId, const char *path, int listenPort, M , _listenPort(listenPort) , _mqc(mqc) { - _connString = std::string(path) + " application_name=controller_" +_myAddressStr; + char myAddress[64]; + _myAddressStr = myId.address().toString(myAddress); + _connString = std::string(path) + " application_name=controller_" + _myAddressStr; // Database Schema Version Check PGconn *conn = getPgConn(); @@ -165,8 +169,9 @@ bool PostgreSQL::isReady() return ((_ready == 2)&&(_connected)); } -void PostgreSQL::save(nlohmann::json &record) +bool PostgreSQL::save(nlohmann::json &record,bool notifyListeners) { + bool modified = false; try { if (!record.is_object()) return; @@ -178,7 +183,8 @@ void PostgreSQL::save(nlohmann::json &record) get(nwid,old); if ((!old.is_object())||(old != record)) { record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL; - _commitQueue.post(new nlohmann::json(record)); + _commitQueue.post(std::pair(record,notifyListeners)); + modified = true; } } } else if (objtype == "member") { @@ -189,7 +195,8 @@ void PostgreSQL::save(nlohmann::json &record) get(nwid,network,id,old); if ((!old.is_object())||(old != record)) { record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL; - _commitQueue.post(new nlohmann::json(record)); + _commitQueue.post(std::pair(record,notifyListeners)); + modified = true; } } } @@ -210,6 +217,7 @@ void PostgreSQL::save(nlohmann::json &record) } catch (...) { fprintf(stderr, "Unknown error on PostgreSQL::save\n"); } + return modified; } void PostgreSQL::eraseNetwork(const uint64_t networkId) @@ -217,38 +225,33 @@ void PostgreSQL::eraseNetwork(const uint64_t networkId) char tmp2[24]; waitForReady(); Utils::hex(networkId, tmp2); - json *tmp = new json(); - (*tmp)["id"] = tmp2; - (*tmp)["objtype"] = "_delete_network"; + std::pair tmp; + tmp.first["id"] = tmp2; + tmp.first["objtype"] = "_delete_network"; + tmp.second = true; _commitQueue.post(tmp); } void PostgreSQL::eraseMember(const uint64_t networkId, const uint64_t memberId) { char tmp2[24]; - json *tmp = new json(); + std::pair tmp; Utils::hex(networkId, tmp2); - (*tmp)["nwid"] = tmp2; + tmp.first["nwid"] = tmp2; Utils::hex(memberId, tmp2); - (*tmp)["id"] = tmp2; - (*tmp)["objtype"] = "_delete_member"; + tmp.first["id"] = tmp2; + tmp.first["objtype"] = "_delete_member"; + tmp.second = true; _commitQueue.post(tmp); } void PostgreSQL::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress &physicalAddress) { - { - std::lock_guard l(_lastOnline_l); - std::pair &i = _lastOnline[std::pair(networkId, memberId)]; - i.first = OSUtils::now(); - if (physicalAddress) { - i.second = physicalAddress; - } - } - { - std::lock_guard l2(_changeListeners_l); - for(auto i=_changeListeners.begin();i!=_changeListeners.end();++i) - (*i)->onNetworkMemberOnline(this,networkId,memberId,physicalAddress); + std::lock_guard l(_lastOnline_l); + std::pair &i = _lastOnline[std::pair(networkId, memberId)]; + i.first = OSUtils::now(); + if (physicalAddress) { + i.second = physicalAddress; } } @@ -868,18 +871,18 @@ void PostgreSQL::commitThread() exit(1); } - json *config = nullptr; - while(_commitQueue.get(config)&(_run == 1)) { - if (!config) { + std::pair qitem; + while(_commitQueue.get(qitem)&(_run == 1)) { + if (!qitem.first.is_object()) { continue; } if (PQstatus(conn) == CONNECTION_BAD) { fprintf(stderr, "ERROR: Connection to database failed: %s\n", PQerrorMessage(conn)); PQfinish(conn); - delete config; exit(1); } - try { + try { + nlohmann::json *config = &(qitem.first); const std::string objtype = (*config)["objtype"]; if (objtype == "member") { try { @@ -1034,10 +1037,10 @@ void PostgreSQL::commitThread() nlohmann::json memOrig; nlohmann::json memNew(*config); - + get(nwidInt, nwOrig, memberidInt, memOrig); - _memberChanged(memOrig, memNew, (this->_ready>=2)); + _memberChanged(memOrig, memNew, qitem.second); } else { fprintf(stderr, "Can't notify of change. Error parsing nwid or memberid: %lu-%lu\n", nwidInt, memberidInt); } @@ -1260,7 +1263,7 @@ void PostgreSQL::commitThread() get(nwidInt, nwOrig); - _networkChanged(nwOrig, nwNew, true); + _networkChanged(nwOrig, nwNew, qitem.second); } else { fprintf(stderr, "Can't notify network changed: %lu\n", nwidInt); } @@ -1268,8 +1271,6 @@ void PostgreSQL::commitThread() } catch (std::exception &e) { fprintf(stderr, "ERROR: Error updating member: %s\n", e.what()); } - } else if (objtype == "trace") { - fprintf(stderr, "ERROR: Trace not yet implemented"); } else if (objtype == "_delete_network") { try { std::string networkId = (*config)["nwid"]; @@ -1326,8 +1327,6 @@ void PostgreSQL::commitThread() } catch (std::exception &e) { fprintf(stderr, "ERROR: Error getting objtype: %s\n", e.what()); } - delete config; - config = nullptr; std::this_thread::sleep_for(std::chrono::milliseconds(10)); } diff --git a/controller/PostgreSQL.hpp b/controller/PostgreSQL.hpp index ce6fb242..6b0ea996 100644 --- a/controller/PostgreSQL.hpp +++ b/controller/PostgreSQL.hpp @@ -55,7 +55,7 @@ public: virtual bool waitForReady(); virtual bool isReady(); - virtual void save(nlohmann::json &record); + virtual bool save(nlohmann::json &record,bool notifyListeners); virtual void eraseNetwork(const uint64_t networkId); virtual void eraseMember(const uint64_t networkId, const uint64_t memberId); virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress &physicalAddress); @@ -87,9 +87,12 @@ private: PGconn * getPgConn( OverrideMode m = ALLOW_PGBOUNCER_OVERRIDE ); + const Identity _myId; + const Address _myAddress; + std::string _myAddressStr; std::string _connString; - BlockingQueue _commitQueue; + BlockingQueue< std::pair > _commitQueue; std::thread _heartbeatThread; std::thread _membersDbWatcher; From 5289d3327c12ec16f4e76dc97ba1f6f673586675 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 6 Aug 2019 11:00:35 -0500 Subject: [PATCH 094/185] Build fixes --- controller/EmbeddedNetworkController.cpp | 74 ++++++++++-------------- controller/EmbeddedNetworkController.hpp | 3 +- controller/PostgreSQL.cpp | 10 ++-- objects.mk | 1 + 4 files changed, 38 insertions(+), 50 deletions(-) diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index 64acda0f..893c0239 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -475,6 +475,7 @@ EmbeddedNetworkController::EmbeddedNetworkController(Node *node,const char *dbPa _node(node), _path(dbPath), _sender((NetworkController::Sender *)0), + _db(this), _mqc(mqc) { } @@ -496,9 +497,13 @@ void EmbeddedNetworkController::init(const Identity &signingId,Sender *sender) #ifdef ZT_CONTROLLER_USE_LIBPQ if ((_path.length() > 9)&&(_path.substr(0,9) == "postgres:")) { - _db.reset(new PostgreSQL(_signingId,_path.substr(9).c_str(), _listenPort, _mqc)); + _db.addDB(std::shared_ptr(new PostgreSQL(_signingId,_path.substr(9).c_str(), _listenPort, _mqc))); } else { #endif + _db.addDB(std::shared_ptr(new FileDB(_path.c_str()))); +#ifdef ZT_CONTROLLER_USE_LIBPQ + } +#endif std::string lfJSON; OSUtils::readFile((_path + ZT_PATH_SEPARATOR_S ".." ZT_PATH_SEPARATOR_S "local.conf").c_str(),lfJSON); @@ -521,7 +526,7 @@ void EmbeddedNetworkController::init(const Identity &signingId,Sender *sender) std::size_t pubHdrEnd = lfOwnerPublic.find_first_of("\n\r\t "); if (pubHdrEnd != std::string::npos) { lfOwnerPublic = lfOwnerPublic.substr(0,pubHdrEnd); - _db.reset(new LFDB(_signingId,_path.c_str(),lfOwner.c_str(),lfOwnerPublic.c_str(),lfHost.c_str(),lfPort,storeOnlineState)); + _db.addDB(std::shared_ptr(new LFDB(_signingId,_path.c_str(),lfOwner.c_str(),lfOwnerPublic.c_str(),lfHost.c_str(),lfPort,storeOnlineState))); } } } @@ -529,16 +534,8 @@ void EmbeddedNetworkController::init(const Identity &signingId,Sender *sender) } } } - if (!_db) - _db.reset(new FileDB(_signingId,_path.c_str())); - - _db->addListener(this); -#ifdef ZT_CONTROLLER_USE_LIBPQ - } -#endif - - _db->waitForReady(); + _db.waitForReady(); } void EmbeddedNetworkController::request( @@ -569,15 +566,12 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( std::string &responseBody, std::string &responseContentType) { - if (!_db) - return 500; - if ((path.size() > 0)&&(path[0] == "network")) { if ((path.size() >= 2)&&(path[1].length() == 16)) { const uint64_t nwid = Utils::hexStrToU64(path[1].c_str()); json network; - if (!_db->get(nwid,network)) + if (!_db.get(nwid,network)) return 404; if (path.size() >= 3) { @@ -589,7 +583,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( const uint64_t address = Utils::hexStrToU64(path[3].c_str()); json member; - if (!_db->get(nwid,network,address,member)) + if (!_db.get(nwid,network,address,member)) return 404; responseBody = OSUtils::jsonDump(member); responseContentType = "application/json"; @@ -599,7 +593,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( responseBody = "{"; std::vector members; - if (_db->get(nwid,network,members)) { + if (_db.get(nwid,network,members)) { responseBody.reserve((members.size() + 2) * 32); std::string mid; for(auto member=members.begin();member!=members.end();++member) { @@ -628,12 +622,12 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( } else if (path.size() == 1) { // List networks - std::vector networkIds; - _db->networks(networkIds); + std::set networkIds; + _db.networks(networkIds); char tmp[64]; responseBody = "["; responseBody.reserve((networkIds.size() + 1) * 24); - for(std::vector::const_iterator i(networkIds.begin());i!=networkIds.end();++i) { + for(std::set::const_iterator i(networkIds.begin());i!=networkIds.end();++i) { if (responseBody.length() > 1) responseBody.push_back(','); OSUtils::ztsnprintf(tmp,sizeof(tmp),"\"%.16llx\"",(unsigned long long)*i); @@ -650,7 +644,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( // Controller status char tmp[4096]; - const bool dbOk = _db->isReady(); + const bool dbOk = _db.isReady(); OSUtils::ztsnprintf(tmp,sizeof(tmp),"{\n\t\"controller\": true,\n\t\"apiVersion\": %d,\n\t\"clock\": %llu,\n\t\"databaseReady\": %s\n}\n",ZT_NETCONF_CONTROLLER_API_VERSION,(unsigned long long)OSUtils::now(),dbOk ? "true" : "false"); responseBody = tmp; responseContentType = "application/json"; @@ -669,8 +663,6 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( std::string &responseBody, std::string &responseContentType) { - if (!_db) - return 500; if (path.empty()) return 404; @@ -704,7 +696,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( OSUtils::ztsnprintf(addrs,sizeof(addrs),"%.10llx",(unsigned long long)address); json member,network; - _db->get(nwid,network,address,member); + _db.get(nwid,network,address,member); DB::initMember(member); try { @@ -798,7 +790,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( member["nwid"] = nwids; DB::cleanMember(member); - _db->save(member); + _db.save(member,true); responseBody = OSUtils::jsonDump(member); responseContentType = "application/json"; @@ -817,7 +809,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( Utils::getSecureRandom(&nwidPostfix,sizeof(nwidPostfix)); uint64_t tryNwid = nwidPrefix | (nwidPostfix & 0xffffffULL); if ((tryNwid & 0xffffffULL) == 0ULL) tryNwid |= 1ULL; - if (!_db->hasNetwork(tryNwid)) { + if (!_db.hasNetwork(tryNwid)) { nwid = tryNwid; break; } @@ -828,7 +820,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( OSUtils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid); json network; - _db->get(nwid,network); + _db.get(nwid,network); DB::initNetwork(network); try { @@ -1059,7 +1051,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( network["nwid"] = nwids; // legacy DB::cleanNetwork(network); - _db->save(network); + _db.save(network,true); responseBody = OSUtils::jsonDump(network); responseContentType = "application/json"; @@ -1081,8 +1073,6 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpDELETE( std::string &responseBody, std::string &responseContentType) { - if (!_db) - return 500; if (path.empty()) return 404; @@ -1094,8 +1084,8 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpDELETE( const uint64_t address = Utils::hexStrToU64(path[3].c_str()); json network,member; - _db->get(nwid,network,address,member); - _db->eraseMember(nwid, address); + _db.get(nwid,network,address,member); + _db.eraseMember(nwid, address); { std::lock_guard l(_memberStatus_l); @@ -1110,8 +1100,8 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpDELETE( } } else { json network; - _db->get(nwid,network); - _db->eraseNetwork(nwid); + _db.get(nwid,network); + _db.eraseNetwork(nwid); { std::lock_guard l(_memberStatus_l); @@ -1141,9 +1131,6 @@ void EmbeddedNetworkController::handleRemoteTrace(const ZT_RemoteTrace &rt) char id[128],tmp[128]; std::string k,v; - if (!_db) - return; - try { // Convert Dictionary into JSON object json d; @@ -1182,7 +1169,7 @@ void EmbeddedNetworkController::handleRemoteTrace(const ZT_RemoteTrace &rt) d["objtype"] = "trace"; d["ts"] = now; d["nodeId"] = Utils::hex10(rt.origin,tmp); - _db->save(d); + _db.save(d,true); } catch ( ... ) { // drop invalid trace messages if an error occurs } @@ -1235,9 +1222,6 @@ void EmbeddedNetworkController::_request( DB::NetworkSummaryInfo ns; json network,member; - if (!_db) - return; - if (((!_signingId)||(!_signingId.hasPrivate()))||(_signingId.address().toInt() != (nwid >> 24))||(!_sender)) return; @@ -1251,10 +1235,10 @@ void EmbeddedNetworkController::_request( ms.lastRequestTime = now; } - _db->nodeIsOnline(nwid,identity.address().toInt(),fromAddr); + _db.nodeIsOnline(nwid,identity.address().toInt(),fromAddr); Utils::hex(nwid,nwids); - _db->get(nwid,network,identity.address().toInt(),member,ns); + _db.get(nwid,network,identity.address().toInt(),member,ns); if ((!network.is_object())||(network.size() == 0)) { _sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_OBJECT_NOT_FOUND); return; @@ -1359,7 +1343,7 @@ void EmbeddedNetworkController::_request( } else { // If they are not authorized, STOP! DB::cleanMember(member); - _db->save(member); + _db.save(member,true); _sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_ACCESS_DENIED); return; } @@ -1731,7 +1715,7 @@ void EmbeddedNetworkController::_request( } DB::cleanMember(member); - _db->save(member); + _db.save(member,true); _sender->ncSendConfig(nwid,requestPacketId,identity.address(),*(nc.get()),metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_VERSION,0) < 6); } diff --git a/controller/EmbeddedNetworkController.hpp b/controller/EmbeddedNetworkController.hpp index 85223dc4..904f0959 100644 --- a/controller/EmbeddedNetworkController.hpp +++ b/controller/EmbeddedNetworkController.hpp @@ -51,6 +51,7 @@ #include "../ext/json/json.hpp" #include "DB.hpp" +#include "DBMirrorSet.hpp" namespace ZeroTier { @@ -153,7 +154,7 @@ private: std::string _signingIdAddressString; NetworkController::Sender *_sender; - std::unique_ptr _db; + DBMirrorSet _db; BlockingQueue< _RQEntry * > _queue; std::vector _threads; diff --git a/controller/PostgreSQL.cpp b/controller/PostgreSQL.cpp index 13b7b8d8..012946b4 100644 --- a/controller/PostgreSQL.cpp +++ b/controller/PostgreSQL.cpp @@ -61,6 +61,7 @@ static const char *_timestr() return ts; } +/* std::string join(const std::vector &elements, const char * const separator) { switch(elements.size()) { @@ -75,6 +76,7 @@ std::string join(const std::vector &elements, const char * const se return os.str(); } } +*/ } // anonymous namespace @@ -174,7 +176,7 @@ bool PostgreSQL::save(nlohmann::json &record,bool notifyListeners) bool modified = false; try { if (!record.is_object()) - return; + return false; const std::string objtype = record["objtype"]; if (objtype == "network") { const uint64_t nwid = OSUtils::jsonIntHex(record["id"],0ULL); @@ -1042,7 +1044,7 @@ void PostgreSQL::commitThread() _memberChanged(memOrig, memNew, qitem.second); } else { - fprintf(stderr, "Can't notify of change. Error parsing nwid or memberid: %lu-%lu\n", nwidInt, memberidInt); + fprintf(stderr, "Can't notify of change. Error parsing nwid or memberid: %llu-%llu\n", (unsigned long long)nwidInt, (unsigned long long)memberidInt); } } catch (std::exception &e) { @@ -1265,7 +1267,7 @@ void PostgreSQL::commitThread() _networkChanged(nwOrig, nwNew, qitem.second); } else { - fprintf(stderr, "Can't notify network changed: %lu\n", nwidInt); + fprintf(stderr, "Can't notify network changed: %llu\n", (unsigned long long)nwidInt); } } catch (std::exception &e) { @@ -1348,7 +1350,7 @@ void PostgreSQL::onlineNotificationThread() } _connected = 1; - int64_t lastUpdatedNetworkStatus = 0; + //int64_t lastUpdatedNetworkStatus = 0; std::unordered_map< std::pair,int64_t,_PairHasher > lastOnlineCumulative; while (_run == 1) { diff --git a/objects.mk b/objects.mk index fcda13fd..e25ed36c 100644 --- a/objects.mk +++ b/objects.mk @@ -28,6 +28,7 @@ CORE_OBJS=\ ONE_OBJS=\ controller/EmbeddedNetworkController.o \ + controller/DBMirrorSet.o \ controller/DB.o \ controller/FileDB.o \ controller/LFDB.o \ From 9cc76d11153c9e8526612519b798c9d1ed3e4150 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 6 Aug 2019 11:01:08 -0500 Subject: [PATCH 095/185] Remove debug line --- controller/DB.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/DB.hpp b/controller/DB.hpp index e391538e..efb08d63 100644 --- a/controller/DB.hpp +++ b/controller/DB.hpp @@ -27,7 +27,7 @@ #ifndef ZT_CONTROLLER_DB_HPP #define ZT_CONTROLLER_DB_HPP -#define ZT_CONTROLLER_USE_LIBPQ +//#define ZT_CONTROLLER_USE_LIBPQ #include "../node/Constants.hpp" #include "../node/Identity.hpp" From 8898cb342b476bbfc4e09ea07d27309cf9265ab0 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 6 Aug 2019 13:12:45 -0500 Subject: [PATCH 096/185] . --- controller/DBMirrorSet.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/controller/DBMirrorSet.cpp b/controller/DBMirrorSet.cpp index 63c0f58b..f435698e 100644 --- a/controller/DBMirrorSet.cpp +++ b/controller/DBMirrorSet.cpp @@ -160,32 +160,26 @@ void DBMirrorSet::nodeIsOnline(const uint64_t networkId,const uint64_t memberId, void DBMirrorSet::onNetworkUpdate(const void *db,uint64_t networkId,const nlohmann::json &network) { - bool modified = false; nlohmann::json record(network); std::lock_guard l(_dbs_l); for(auto d=_dbs.begin();d!=_dbs.end();++d) { if (d->get() != db) { - modified |= (*d)->save(record,false); + (*d)->save(record,false); } } - if (modified) { - _listener->onNetworkUpdate(this,networkId,network); - } + _listener->onNetworkUpdate(this,networkId,network); } void DBMirrorSet::onNetworkMemberUpdate(const void *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member) { - bool modified = false; nlohmann::json record(member); std::lock_guard l(_dbs_l); for(auto d=_dbs.begin();d!=_dbs.end();++d) { if (d->get() != db) { - modified |= (*d)->save(record,false); + (*d)->save(record,false); } } - if (modified) { - _listener->onNetworkMemberUpdate(this,networkId,memberId,member); - } + _listener->onNetworkMemberUpdate(this,networkId,memberId,member); } void DBMirrorSet::onNetworkMemberDeauthorize(const void *db,uint64_t networkId,uint64_t memberId) From 6174c0c103ee2339912589ba4cb8549d19b0d900 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 6 Aug 2019 13:20:37 -0500 Subject: [PATCH 097/185] Fix deadlock bug. --- controller/DBMirrorSet.cpp | 18 +++++++++++------- controller/LFDB.cpp | 10 +++++----- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/controller/DBMirrorSet.cpp b/controller/DBMirrorSet.cpp index f435698e..5d9ea050 100644 --- a/controller/DBMirrorSet.cpp +++ b/controller/DBMirrorSet.cpp @@ -51,7 +51,7 @@ bool DBMirrorSet::get(const uint64_t networkId,nlohmann::json &network) { std::lock_guard l(_dbs_l); for(auto d=_dbs.begin();d!=_dbs.end();++d) { - if (get(networkId,network)) { + if ((*d)->get(networkId,network)) { return true; } } @@ -62,7 +62,7 @@ bool DBMirrorSet::get(const uint64_t networkId,nlohmann::json &network,const uin { std::lock_guard l(_dbs_l); for(auto d=_dbs.begin();d!=_dbs.end();++d) { - if (get(networkId,network,memberId,member)) + if ((*d)->get(networkId,network,memberId,member)) return true; } return false; @@ -72,7 +72,7 @@ bool DBMirrorSet::get(const uint64_t networkId,nlohmann::json &network,const uin { std::lock_guard l(_dbs_l); for(auto d=_dbs.begin();d!=_dbs.end();++d) { - if (get(networkId,network,memberId,member,info)) + if ((*d)->get(networkId,network,memberId,member,info)) return true; } return false; @@ -82,7 +82,7 @@ bool DBMirrorSet::get(const uint64_t networkId,nlohmann::json &network,std::vect { std::lock_guard l(_dbs_l); for(auto d=_dbs.begin();d!=_dbs.end();++d) { - if (get(networkId,network,members)) + if ((*d)->get(networkId,network,members)) return true; } return false; @@ -118,16 +118,20 @@ bool DBMirrorSet::isReady() bool DBMirrorSet::save(nlohmann::json &record,bool notifyListeners) { - std::lock_guard l(_dbs_l); + std::vector< std::shared_ptr > dbs; + { + std::lock_guard l(_dbs_l); + dbs = _dbs; + } if (notifyListeners) { - for(auto d=_dbs.begin();d!=_dbs.end();++d) { + for(auto d=dbs.begin();d!=dbs.end();++d) { if ((*d)->save(record,notifyListeners)) return true; } return false; } else { bool modified = false; - for(auto d=_dbs.begin();d!=_dbs.end();++d) { + for(auto d=dbs.begin();d!=dbs.end();++d) { modified |= (*d)->save(record,notifyListeners); } return modified; diff --git a/controller/LFDB.cpp b/controller/LFDB.cpp index 5dd6d082..812b2f38 100644 --- a/controller/LFDB.cpp +++ b/controller/LFDB.cpp @@ -83,7 +83,7 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons if (resp) { if (resp->status == 200) { ns->second.dirty = false; - printf("SET network %.16llx %s\n",ns->first,resp->body.c_str()); + //printf("SET network %.16llx %s\n",ns->first,resp->body.c_str()); } else { fprintf(stderr,"ERROR: LFDB: %d from node (create/update network): %s" ZT_EOL_S,resp->status,resp->body.c_str()); } @@ -129,7 +129,7 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons if (resp) { if (resp->status == 200) { ms->second.lastOnlineDirty = false; - printf("SET member online %.16llx %.10llx %s\n",ns->first,ms->first,resp->body.c_str()); + //printf("SET member online %.16llx %.10llx %s\n",ns->first,ms->first,resp->body.c_str()); } else { fprintf(stderr,"ERROR: LFDB: %d from node (create/update member online status): %s" ZT_EOL_S,resp->status,resp->body.c_str()); } @@ -157,7 +157,7 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons if (resp) { if (resp->status == 200) { ms->second.dirty = false; - printf("SET member %.16llx %.10llx %s\n",ns->first,ms->first,resp->body.c_str()); + //printf("SET member %.16llx %.10llx %s\n",ns->first,ms->first,resp->body.c_str()); } else { fprintf(stderr,"ERROR: LFDB: %d from node (create/update member): %s" ZT_EOL_S,resp->status,resp->body.c_str()); } @@ -196,7 +196,7 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons nlohmann::json &record = result["Record"]; if (record.is_object()) { const std::string recordValue = result["Value"]; - printf("GET network %s\n",recordValue.c_str()); + //printf("GET network %s\n",recordValue.c_str()); nlohmann::json network(OSUtils::jsonParse(recordValue)); if (network.is_object()) { const std::string idstr = network["id"]; @@ -264,7 +264,7 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons nlohmann::json &record = result["Record"]; if (record.is_object()) { const std::string recordValue = result["Value"]; - printf("GET member %s\n",recordValue.c_str()); + //printf("GET member %s\n",recordValue.c_str()); nlohmann::json member(OSUtils::jsonParse(recordValue)); if (member.is_object()) { const std::string nwidstr = member["nwid"]; From 3db019786506492bd217ebf37aa1ab9261c8808e Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 6 Aug 2019 15:22:57 -0500 Subject: [PATCH 098/185] Add try/catch in LFDB and add introspection into multicast subscriptions in client network status API --- controller/LFDB.cpp | 82 +++++++++++++++++++++++++++--------------- include/ZeroTierOne.h | 18 ++++++++++ node/Network.cpp | 6 ++++ service/OneService.cpp | 9 +++++ 4 files changed, 87 insertions(+), 28 deletions(-) diff --git a/controller/LFDB.cpp b/controller/LFDB.cpp index 812b2f38..3672dfa9 100644 --- a/controller/LFDB.cpp +++ b/controller/LFDB.cpp @@ -79,16 +79,22 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons newrec["OwnerPrivate"] = _lfOwnerPrivate; newrec["MaskingKey"] = maskingKey; newrec["PulseIfUnchanged"] = true; - auto resp = htcli.Post("/makerecord",newrec.dump(),"application/json"); - if (resp) { - if (resp->status == 200) { - ns->second.dirty = false; - //printf("SET network %.16llx %s\n",ns->first,resp->body.c_str()); + try { + auto resp = htcli.Post("/makerecord",newrec.dump(),"application/json"); + if (resp) { + if (resp->status == 200) { + ns->second.dirty = false; + //printf("SET network %.16llx %s\n",ns->first,resp->body.c_str()); + } else { + fprintf(stderr,"ERROR: LFDB: %d from node (create/update network): %s" ZT_EOL_S,resp->status,resp->body.c_str()); + } } else { - fprintf(stderr,"ERROR: LFDB: %d from node (create/update network): %s" ZT_EOL_S,resp->status,resp->body.c_str()); + fprintf(stderr,"ERROR: LFDB: node is offline" ZT_EOL_S); } - } else { - fprintf(stderr,"ERROR: LFDB: node is offline" ZT_EOL_S); + } catch (std::exception &e) { + fprintf(stderr,"ERROR: LFDB: unexpected exception querying node (create/update network): %s" ZT_EOL_S,e.what()); + } catch ( ... ) { + fprintf(stderr,"ERROR: LFDB: unexpected exception querying node (create/update network): unknown exception" ZT_EOL_S); } } } @@ -125,16 +131,22 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons newrec["MaskingKey"] = maskingKey; newrec["Timestamp"] = ms->second.lastOnlineTime; newrec["PulseIfUnchanged"] = true; - auto resp = htcli.Post("/makerecord",newrec.dump(),"application/json"); - if (resp) { - if (resp->status == 200) { - ms->second.lastOnlineDirty = false; - //printf("SET member online %.16llx %.10llx %s\n",ns->first,ms->first,resp->body.c_str()); + try { + auto resp = htcli.Post("/makerecord",newrec.dump(),"application/json"); + if (resp) { + if (resp->status == 200) { + ms->second.lastOnlineDirty = false; + //printf("SET member online %.16llx %.10llx %s\n",ns->first,ms->first,resp->body.c_str()); + } else { + fprintf(stderr,"ERROR: LFDB: %d from node (create/update member online status): %s" ZT_EOL_S,resp->status,resp->body.c_str()); + } } else { - fprintf(stderr,"ERROR: LFDB: %d from node (create/update member online status): %s" ZT_EOL_S,resp->status,resp->body.c_str()); + fprintf(stderr,"ERROR: LFDB: node is offline" ZT_EOL_S); } - } else { - fprintf(stderr,"ERROR: LFDB: node is offline" ZT_EOL_S); + } catch (std::exception &e) { + fprintf(stderr,"ERROR: LFDB: unexpected exception querying node (create/update member online status): %s" ZT_EOL_S,e.what()); + } catch ( ... ) { + fprintf(stderr,"ERROR: LFDB: unexpected exception querying node (create/update member online status): unknown exception" ZT_EOL_S); } } @@ -153,16 +165,22 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons newrec["OwnerPrivate"] = _lfOwnerPrivate; newrec["MaskingKey"] = maskingKey; newrec["PulseIfUnchanged"] = true; - auto resp = htcli.Post("/makerecord",newrec.dump(),"application/json"); - if (resp) { - if (resp->status == 200) { - ms->second.dirty = false; - //printf("SET member %.16llx %.10llx %s\n",ns->first,ms->first,resp->body.c_str()); + try { + auto resp = htcli.Post("/makerecord",newrec.dump(),"application/json"); + if (resp) { + if (resp->status == 200) { + ms->second.dirty = false; + //printf("SET member %.16llx %.10llx %s\n",ns->first,ms->first,resp->body.c_str()); + } else { + fprintf(stderr,"ERROR: LFDB: %d from node (create/update member): %s" ZT_EOL_S,resp->status,resp->body.c_str()); + } } else { - fprintf(stderr,"ERROR: LFDB: %d from node (create/update member): %s" ZT_EOL_S,resp->status,resp->body.c_str()); + fprintf(stderr,"ERROR: LFDB: node is offline" ZT_EOL_S); } - } else { - fprintf(stderr,"ERROR: LFDB: node is offline" ZT_EOL_S); + } catch (std::exception &e) { + fprintf(stderr,"ERROR: LFDB: unexpected exception querying node (create/update member): %s" ZT_EOL_S,e.what()); + } catch ( ... ) { + fprintf(stderr,"ERROR: LFDB: unexpected exception querying node (create/update member): unknown exception" ZT_EOL_S); } } } @@ -170,7 +188,7 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons } } - { + try { std::ostringstream query; query << '{' @@ -228,14 +246,18 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons } } } else { - fprintf(stderr,"ERROR: LFDB: %d from node: %s" ZT_EOL_S,resp->status,resp->body.c_str()); + fprintf(stderr,"ERROR: LFDB: %d from node (check for network updates): %s" ZT_EOL_S,resp->status,resp->body.c_str()); } } else { fprintf(stderr,"ERROR: LFDB: node is offline" ZT_EOL_S); } + } catch (std::exception &e) { + fprintf(stderr,"ERROR: LFDB: unexpected exception querying node (check for network updates): %s" ZT_EOL_S,e.what()); + } catch ( ... ) { + fprintf(stderr,"ERROR: LFDB: unexpected exception querying node (check for network updates): unknown exception" ZT_EOL_S); } - { + try { std::ostringstream query; query << '{' @@ -297,11 +319,15 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons } } } else { - fprintf(stderr,"ERROR: LFDB: %d from node: %s" ZT_EOL_S,resp->status,resp->body.c_str()); + fprintf(stderr,"ERROR: LFDB: %d from node (check for member updates): %s" ZT_EOL_S,resp->status,resp->body.c_str()); } } else { fprintf(stderr,"ERROR: LFDB: node is offline" ZT_EOL_S); } + } catch (std::exception &e) { + fprintf(stderr,"ERROR: LFDB: unexpected exception querying node (check for member updates): %s" ZT_EOL_S,e.what()); + } catch ( ... ) { + fprintf(stderr,"ERROR: LFDB: unexpected exception querying node (check for member updates): unknown exception" ZT_EOL_S); } timeRangeStart = time(nullptr) - 120; // start next query 2m before now to avoid losing updates diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 74600989..b0be0105 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -198,6 +198,11 @@ extern "C" { */ #define ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH 7 +/** + * Maximum number of multicast groups a device / network interface can be subscribed to at once + */ +#define ZT_MAX_MULTICAST_SUBSCRIPTIONS 1024 + /** * Maximum value for link quality (min is 0) */ @@ -1193,6 +1198,19 @@ typedef struct * Routes (excluding those implied by assigned addresses and their masks) */ ZT_VirtualNetworkRoute routes[ZT_MAX_NETWORK_ROUTES]; + + /** + * Number of multicast groups subscribed + */ + unsigned int multicastSubscriptionCount; + + /** + * Multicast groups to which this network's device is subscribed + */ + struct { + uint64_t mac; /* MAC in lower 48 bits */ + uint32_t adi; /* Additional distinguishing information, usually zero except for IPv4 ARP groups */ + } multicastSubscriptions[ZT_MAX_MULTICAST_SUBSCRIPTIONS]; } ZT_VirtualNetworkConfig; /** diff --git a/node/Network.cpp b/node/Network.cpp index 1e151b61..4458c9b0 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -1433,6 +1433,12 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const memset(&(ec->routes[i]),0,sizeof(ZT_VirtualNetworkRoute)); } } + + ec->multicastSubscriptionCount = (unsigned int)_myMulticastGroups.size(); + for(unsigned long i=0;i<(unsigned long)_myMulticastGroups.size();++i) { + ec->multicastSubscriptions[i].mac = _myMulticastGroups[i].mac().toInt(); + ec->multicastSubscriptions[i].adi = _myMulticastGroups[i].adi(); + } } void Network::_sendUpdatesToMembers(void *tPtr,const MulticastGroup *const newMulticastGroup) diff --git a/service/OneService.cpp b/service/OneService.cpp index 43f5d9c9..7c9671e5 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -273,6 +273,15 @@ static void _networkToJson(nlohmann::json &nj,const ZT_VirtualNetworkConfig *nc, ra.push_back(rj); } nj["routes"] = ra; + + nlohmann::json mca = nlohmann::json::array(); + for(unsigned int i=0;imulticastSubscriptionCount;++i) { + nlohmann::json m; + m["mac"] = MAC(nc->multicastSubscriptions[i].mac).toString(tmp); + m["adi"] = nc->multicastSubscriptions[i].adi; + mca.push_back(m); + } + nj["multicastSubscriptions"] = mca; } static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer) From 3ed8e46782aec83991aa8dbe4936ab36beca2501 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 6 Aug 2019 16:46:41 -0500 Subject: [PATCH 099/185] Use devtoolset-8 on RHEL/CentOS 7 --- make-linux.mk | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/make-linux.mk b/make-linux.mk index b81c7aeb..db386306 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -1,12 +1,12 @@ # Automagically pick clang or gcc, with preference for clang # This is only done if we have not overridden these with an environment or CLI variable ifeq ($(origin CC),default) - CC:=$(shell if [ -e /usr/bin/clang ]; then echo clang; else echo gcc; fi) - CC:=$(shell if [ -e /opt/intel/bin/icc ]; then echo /opt/intel/bin/icc -ipo -ansi-alias; else echo $(CC); fi) + CC:=$(shell if [ -e /usr/bin/clang ]; then echo clang; else echo gcc; fi) + CC:=$(shell if [ -e /opt/rh/devtoolset-8/root/usr/bin/gcc ]; then echo /opt/rh/devtoolset-8/root/usr/bin/gcc; else echo $(CC); fi) endif ifeq ($(origin CXX),default) - CXX:=$(shell if [ -e /usr/bin/clang++ ]; then echo clang++; else echo g++; fi) - CXX:=$(shell if [ -e /opt/intel/bin/icc ]; then echo /opt/intel/bin/icc -ipo -ansi-alias; else echo $(CXX); fi) + CXX:=$(shell if [ -e /usr/bin/clang++ ]; then echo clang++; else echo g++; fi) + CXX:=$(shell if [ -e /opt/rh/devtoolset-8/root/usr/bin/g++ ]; then echo /opt/rh/devtoolset-8/root/usr/bin/g++; else echo $(CXX); fi) endif INCLUDES?= From 87016ae81593c07406107989824a4e7d5e4397e8 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Tue, 6 Aug 2019 15:30:50 -0700 Subject: [PATCH 100/185] network update to upsert --- controller/PostgreSQL.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/controller/PostgreSQL.cpp b/controller/PostgreSQL.cpp index 012946b4..8a34ec1d 100644 --- a/controller/PostgreSQL.cpp +++ b/controller/PostgreSQL.cpp @@ -1092,11 +1092,19 @@ void PostgreSQL::commitThread() }; PGresult *res = PQexecParams(conn, - "UPDATE ztc_network SET controller_id = $2, capabilities = $3, enable_broadcast = $4, " - "last_updated = $5, mtu = $6, multicast_limit = $7, name = $8, private = $9, " - "remote_trace_level = $10, remote_trace_target = $11, rules = $12, rules_source = $13, " - "tags = $14, v4_assign_mode = $15, v6_assign_mode = $16 " - "WHERE id = $1", + "INSERT INTO ztc_network (id, controller_id, capabilities, enable_broadcast, " + "last_updated, mtu, multicast_limit, name, private, " + "remote_trace_level, remote_trace_target, rules, rules_source, " + "tags, v4_assign_mode, v6_assign_mode) VALUES (" + "$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16) " + "ON CONFLICT (id) DO UPDATE set controller_id = EXCLUDED.controller_id, " + "capabilities = EXCLUDED.capabilities, enable_broadcast = EXCLUDED.enable_broadcast, " + "last_updated = EXCLUDED.last_updated, mtu = EXCLUDED.mtu, " + "multicast_limit = EXCLUDED.multicast_limit, name = EXCLUDED.name, " + "private = EXCLUDED.private, remote_trace_level = EXCLUDED.remote_trace_level, " + "remote_trace_target = EXCLUDED.remote_trace_target, rules = EXCLUDED.rules, " + "rules_source = EXCLUDED.rules_source, tags = EXCLUDED.tags, " + "v4_assign_mode = EXCLUDED.v4_assign_mode, v6_assign_mode = EXCLUDED.v6_assign_mode", 16, NULL, values, From f7e8d8f1ddc142c5f788fb941c096ac2fea8cb44 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 7 Aug 2019 11:23:48 -0500 Subject: [PATCH 101/185] Fix LFDB path issue when using with Postgress in DBMirrorSet config --- controller/EmbeddedNetworkController.cpp | 5 +++-- controller/EmbeddedNetworkController.hpp | 3 ++- service/OneService.cpp | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index 893c0239..08d31bee 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -469,10 +469,11 @@ static bool _parseRule(json &r,ZT_VirtualNetworkRule &rule) } // anonymous namespace -EmbeddedNetworkController::EmbeddedNetworkController(Node *node,const char *dbPath, int listenPort, MQConfig *mqc) : +EmbeddedNetworkController::EmbeddedNetworkController(Node *node,const char *ztPath,const char *dbPath, int listenPort, MQConfig *mqc) : _startTime(OSUtils::now()), _listenPort(listenPort), _node(node), + _ztPath(ztPath), _path(dbPath), _sender((NetworkController::Sender *)0), _db(this), @@ -506,7 +507,7 @@ void EmbeddedNetworkController::init(const Identity &signingId,Sender *sender) #endif std::string lfJSON; - OSUtils::readFile((_path + ZT_PATH_SEPARATOR_S ".." ZT_PATH_SEPARATOR_S "local.conf").c_str(),lfJSON); + OSUtils::readFile((_ztPath + ZT_PATH_SEPARATOR_S "local.conf").c_str(),lfJSON); if (lfJSON.length() > 0) { nlohmann::json lfConfig(OSUtils::jsonParse(lfJSON)); nlohmann::json &settings = lfConfig["settings"]; diff --git a/controller/EmbeddedNetworkController.hpp b/controller/EmbeddedNetworkController.hpp index 904f0959..adc2a2ec 100644 --- a/controller/EmbeddedNetworkController.hpp +++ b/controller/EmbeddedNetworkController.hpp @@ -66,7 +66,7 @@ public: * @param node Parent node * @param dbPath Database path (file path or database credentials) */ - EmbeddedNetworkController(Node *node,const char *dbPath, int listenPort, MQConfig *mqc = NULL); + EmbeddedNetworkController(Node *node,const char *ztPath,const char *dbPath, int listenPort, MQConfig *mqc = NULL); virtual ~EmbeddedNetworkController(); virtual void init(const Identity &signingId,Sender *sender); @@ -149,6 +149,7 @@ private: const int64_t _startTime; int _listenPort; Node *const _node; + std::string _ztPath; std::string _path; Identity _signingId; std::string _signingIdAddressString; diff --git a/service/OneService.cpp b/service/OneService.cpp index 7c9671e5..13dca4b0 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -776,7 +776,7 @@ public: OSUtils::rmDashRf((_homePath + ZT_PATH_SEPARATOR_S "iddb.d").c_str()); // Network controller is now enabled by default for desktop and server - _controller = new EmbeddedNetworkController(_node,_controllerDbPath.c_str(),_ports[0], _mqc); + _controller = new EmbeddedNetworkController(_node,_homePath.c_str(),_controllerDbPath.c_str(),_ports[0], _mqc); _node->setNetconfMaster((void *)_controller); // Join existing networks in networks.d From aca31c7055bb500cc3783a07ce7158d3ec4e07b7 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 7 Aug 2019 18:14:12 -0500 Subject: [PATCH 102/185] Put kext back in Mac distro and use on versions older than High Sierra (which lack the feth device) --- ext/bin/tap-mac/tap.kext/Contents/Info.plist | 36 + ext/bin/tap-mac/tap.kext/Contents/MacOS/tap | Bin 0 -> 50496 bytes .../Contents/_CodeSignature/CodeResources | 105 ++ ext/installfiles/mac/ZeroTier One.pkgproj | 1505 ++++++++++------- ext/installfiles/mac/postinst.sh | 9 +- osdep/BSDEthernetTap.hpp | 25 +- osdep/EthernetTap.cpp | 117 ++ osdep/EthernetTap.hpp | 72 + osdep/LinuxEthernetTap.cpp | 21 +- osdep/LinuxEthernetTap.hpp | 31 +- osdep/MacEthernetTap.cpp | 21 +- osdep/MacEthernetTap.hpp | 40 +- osdep/MacKextEthernetTap.cpp | 703 ++++++++ osdep/MacKextEthernetTap.hpp | 93 + osdep/NetBSDEthernetTap.hpp | 23 +- osdep/TestEthernetTap.hpp | 161 -- osdep/WindowsEthernetTap.hpp | 27 +- 17 files changed, 2084 insertions(+), 905 deletions(-) create mode 100644 ext/bin/tap-mac/tap.kext/Contents/Info.plist create mode 100755 ext/bin/tap-mac/tap.kext/Contents/MacOS/tap create mode 100644 ext/bin/tap-mac/tap.kext/Contents/_CodeSignature/CodeResources create mode 100644 osdep/EthernetTap.cpp create mode 100644 osdep/EthernetTap.hpp create mode 100644 osdep/MacKextEthernetTap.cpp create mode 100644 osdep/MacKextEthernetTap.hpp delete mode 100644 osdep/TestEthernetTap.hpp diff --git a/ext/bin/tap-mac/tap.kext/Contents/Info.plist b/ext/bin/tap-mac/tap.kext/Contents/Info.plist new file mode 100644 index 00000000..c20eefa5 --- /dev/null +++ b/ext/bin/tap-mac/tap.kext/Contents/Info.plist @@ -0,0 +1,36 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + tap + CFBundleIdentifier + com.zerotier.tap + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + tap + CFBundlePackageType + KEXT + CFBundleShortVersionString + 20150118 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + OSBundleLibraries + + com.apple.kpi.mach + 8.0 + com.apple.kpi.bsd + 8.0 + com.apple.kpi.libkern + 8.0 + com.apple.kpi.unsupported + 8.0 + + + + diff --git a/ext/bin/tap-mac/tap.kext/Contents/MacOS/tap b/ext/bin/tap-mac/tap.kext/Contents/MacOS/tap new file mode 100755 index 0000000000000000000000000000000000000000..48bf9625551ea8af1d97fe3a0868e499ab55a48c GIT binary patch literal 50496 zcmeIb3tW`N_dmWMAR@Ztz0_RqnwJ(t#XBggtAgSMwJaBeMNn=6t7xIDg1N3FmX>9j zm;7jENok5&3TlF8ispsPip*>&Q#4I1i~sw~%=7H-1Dc=j@ALnD{=fgreZAQ8oS8E- zXU?2CbLPxE%gH}}{kyhG3zM6rYHianz}D z$DganHW<>3>1lRaWqo1ZJa7AG4heU&lM|BZh#Cx0sc9*3iPJ=)vc9UxJmV&H3?B*S zn4K>Pr+zMWp?(GjjSrGi0VBk-kAMoC`bkYlyn?T!#8i7n?^j=#;EU>)9#KuTkHHWf znHFhJR@N65#q;`tclr?i;QFGH5)zUUId%2^=0@`zA5sMIk@`lcXhzC{yr!n6%2@UK z*2VM8W)3ut{3+|BanR$>UKQ?BD-!0FRX{LKVhi@z!O`=?L90+s4C5utrj)#mu4cC4G;^4hW4zuAG?JC}$2 zlse)mr1{`a`n1FY;T3OVjM_`7kKiK-Jd(g82|SX(BMCf`z#|F#-!Fl1z2!&!!mC=n zC8I)bG1>Iyj0)&3l;cl@60Ed3i*^gB%*IfQ?qZSdUPB~Vb@%iO4{M)46r*mHMI}_#__2gj!-6Lr zC>(hzMOG;lQ)iKn2A)bePg@ukZnK=zTTy|;8L`1Qd#Ls;rmK3V<_EJ{?ILk#zKv7! zdBChF{cvr^#Kd%0^gmD@4`RR)N-YT)&_>Bo1|`TUK^kPxk7emfxD4_chH)V-tQn=K zvKW$pkN`pp^p?U9tF9oZs)WX@X2}F%WY|Z^Uzn1=5DS`>c{H%5?Sd*sRx#3KwE_!F zcM2Gxokws~f~vtB@d*%`&-e_@58}F2GoNA4A5yovvxM;~Z4wizgI)KoEU`ru!_Yaa&w+fc|(MbHrA{wY*#9?|p$r-_* z(e$FRB}N{s!y1x+qP_p&e5MJdw>r${nq|&fl;rJ${#8QCl_-lr*0L%xD%o_0?WnL1 zfDg+;3Oa`_EiVJkjm5&lKF=Q#^WP_*%mb^`Vyb|RK$cVgobxT=us)$>paWN=uu6T^ z$n+M|Elg^gCG@hLx;nkReWGX0!$b-BlJZw#Mpf#IhIxWbmA;6!v#O$D)HxN%J(c>% z<%1%&eN|Oeyh6D?*k5}-1$C|uMSAmSX zqCkl)2uG4HRX|oms@L|a%vX)_WAwB>SWOk?c|Ms`zr|Fh&aQ)}Bf2V8IR!R+3oJ)a zD>w5Xg;JBAtJK+z@D1Kj9>Zh_!q~f%(;gdXWqNBm6x}41A|jNu3`L@@%&PY>7gD6a zqW3{NE=zP(?OfEm3LqnNCs*`GBlky^4|uCb4HW5^QkL`ej4xW2P_)5i=6jmf2x7{` zfpfGQ=3_nxnN(TAe2`E2g#pl2@^+Q$m5)BhJu(EXxikHi2Fp@gZ>iL~2M`}@fi1F4 zMic|}ROsFHEValsTuzxJQhLiNKIl27iS6URpfzl017ks?Iue+SznLx=<8;D{GBXL_ zqj%4uZveBwy;Ec_h_dQ~x-Z zq)bJ&)x>Fzdlm_U^vhgCy{du`bKH~ciPU+X_^dsV6YYGQwkO*85ay(sJ(1@t4Qo~7StEFFnanx+iuEYQLQ}0G z#-h7MVo~olU9*nHEXXLc+_9XnWuxc5M}zY7Ap4MEgh4ISLz}I7 zsSKO0ZlF-ir$8~E!Ymp0ET&4U>0aTLW_3-KU|pEBKxcbTCeS>ewM(5-XR!%KYHCeS z=d$2B%SrgKR`(}@CI(Fi3J)4TPH(8FmiU zrL%M;M_Epx^#B2s6O+b+qo zBkLutKB9}dTe2jP>OP58Mk~jdNw6?gW3eviY)kYhnKxX1FLY67yMv&d0?CxFptp|I z=*@))Zi6$7@rkO_<@?#dRimVuo3R=shS~B{6vX;v(FwoB*}f$E{=PSeRW8I}9Tp1_ zK*{(zpwFSD8@P3TtVOqzN!vjV*_S1*X`e?1!yJGV2QGoul|o-nvI@W# z(&ivdw~i(3rNsftoYR<&WYFFgkgN-`6bL!8e0>h~9<;z)2SOrzIXPj`y~S!!?+QO< z{==23(XCQvF^P5smj8I1Cew0IltrrpsVBipbf>^juHJGdNWH59wlEjl1jfI+CozuR zly_rdmVAj4K_EVMQF%dmwC z|8OD3;{No3fr~3hIE!_6$h&6FxHYu$cQZK?Epf(DyX_ z$HI`D&{FlT4Ac`^KpRx17Z%+abH*9aKs0oOBh_;p^;pBtNL4+HEJ&!BJ2B+Ym7=rI z{P41B)jZ))%~n(cBAYc-s>)sqGBQe8X>^}NTa$krsLw&@0W!m$)82oGk57kOoo2YW(Oe&nhZs{Go%6Klc*4Ff%!gZOdvMc@Nf8#9ttckWg-ie<6Ej6%2H};01kNkr3QWZxBIh#JE)>R)RmmdJl1MBNgG_UgN-%b2Vto-+w?(2-L; z`V~sJ7fDgA!a|qEg3dTC|@Hih1QI>U|xMu&Z7H7rm~vwOtyzF zd5-giOop9KOdQ_JCCIYsKB=WU0~;gLuwg)(Y~K4GU3^SG0CcLw;j7gzlOoDPw6b8a zZuJt~>Ma`W18BcKSEXVXNC3>q!J|ZR8qCE@apQT7$BWYT7JNxPK)C-u~ zwi*fMj8E_l*TsTw`!ESJWX@Pext8oSG_1~k8qZQsf?=kW-B1kKM97jeZ{qd&9;HAB znLFwcR=#Z7h;b$*L9)>-=Zh~EWHz43u@X%&?Z-}7vf~}ffrtk4Q@+K!BS;0xg+kLk zqnP&RELS!Ga7^K(TEll*vY(S`^gRvQ+z@N+P-|cWRc*U$}P0Y0y79x4)E1*|DHLO}~{t`^^(elTYvYbNF4&!Onohj1MiVw4x zZ)?nYm=F6NR^7g{&Y|W?^L+A1Rq7Q54x6GH{a-3l!SsO~EphBeCQxFTiM{+S>JA(| zrzHUXj>5evkd16L_o^BA0c$p<^U#4n;1FE-U{DoJqY>~le` zqY0}czx;1NHXc$3)LEO61co71+84|I0BJH3Wj~vSocXWZyF6mczRA`)c(iN;Sv)oORrWlrb_N{ktH>CzA)kvn+?)QWLrx{{~P8ijPmZ}~`=1~%uMm{3Vf z2s6T2WQroCkha$WnV3!7ktUUJI*&A8Eh85A_J(FW=4l1aq%0NP`p5YmLdc4&qvd0= za@?M&mo1l=vohn?tr>0Lv&Vx%y^My2D?ZQjW_e`a)LAA)o)60-*9zwy7}xSqSgJ*x zEGUpo5jk~M7bH8@>Cegqv%Gy&u8FM0+joJIqz zI!!w#8f{H9>@@y>8zbzwAMSwAa51FiG#S*pbnA)ZKE>*64Jd(sDB;8=@IrxStp$F7 zygbCrU}ms|A~(6g zOG3{FFAiNV;D-Xj>hl1q6x0blkM%DAqr>AmH$to{3A1GT<2$J8wA8ba7&_^B5VtHe zf|;1UnP5*P+a8+W)tfZMEos0zK_ zilNBYK%?~5Psz*ZlFiCQVV%w)X<03qAQU5E$<`vNyfZI4|9(Yf>aL)c`ZbLTG0n`T z=(67YDFGxZdWQgpeWcRi7UU3}b*7JGD5;2r#lOqN+DIwF#N3O)Ghgh>@T8po3$F%3 zQ6XFVnr97%c+T5nUnR`hr??lK@RxpN=BNye!$^k16<9z4D{JU2%Mv#>XczIVvMmFh zFP-Ee0^uCb^vNfVs6i|uHJ$&mEZYCj`Pw9+wT_-d77Bb+jqyRt6$tveNO_?cm^qW+ zFlpr|EY5^jB$k*Y?~9J)ctu1!6O|QJO`vU+2I6qu|48SxES`oSAUj7L2yL}xkjZ7| z9J&1CaNb&3q`L)1;S}GZtIz73w#0Uh`yQ-H`l!%b`XaYt%7>>wu>mY=x5`T}h)3LC z>rX*6R;{QnjJhh_PZ7pAr4ubkddu8Eg#4jo2tK+$$4X*M_(3fQifwVEM|{PC-{1*4 zGE75YCJrD6Sv`M3Y?A2>b5Mr{nCH>_gNxn~#L{9~zz!+H%Y@p}p^{j-%1?uRtL`fN zxx(*jS&FgP+-^!E6belU!U)V^+&Ndb;r`VvM0FUSV#J@d*6^$FtqQNyl7i51YN)G- zhV|23Rp(HAfzx^lO^6D`;F4=SQLDGO9n(iq0ChCD=wC<$)mc;V%~Qdjb&OVTbvvlH z`snHGZDv4><&M=<5))*>*q-tETLNIYy{KZjQo)lj5EPopnJB~t#f`PBF zsgw+Ra98v>r`{|E+Yy(ut12JMm8JxaDA&xaen=_OT?PR(3(>>Sl72y*)C*^DoNZJ}aAZhYbb^TZ z-7AnfWLdqj9rcBtR!s z1iNMBQ^77vw108#KLal`2Ih2bL$VN~fa>*J*qx_a)A>D&0jK~Lh9Y&6GxL3CPJ#ou zKw)KIE|-wQ0U_w4#st7*ve{o0#42|l>qsBme+V3`R#}eW#vzmo<6Fcu1QQy&Y)@># zJK+?VlGy&+QBm5Va6jEeb@mqOm?Kv&)WlVW4P#rRD}~yq7VC;^?Gcq;qAQZNP1V;o zbi@~16UiCjicI$y%;X;+1NL2=)smjrc{(g#SSN1zEH|N3mUFg3=rXFAPSsekW=ZOQ zQocf=ZYAy4H6Sd+(WKm-(`0jQ7w4v;T^qBw%65nIc5hO3bTLNJE-jb$SufdoP4^{+ zva-@GJZ2S~*MALw5CL1qV_+9%M5T?;DI0tZe#hNr>R}@`tFAIQBmRbX6B#B+k%&|@UWZxzEL3A z9_;@u;T4w9tB8J-LBFVaq?cGu+DzDevum!U#2Vdd9BwWkMWc{TI!qgGagav#8`epk zLko~O<08IQ>ZSC46zo27Y2CtVWbS{En z?jkjW9GJ<2%uFH_`~}k3q7z=yZ?LSYWgxVxDpdbIs%p=XRP~iil!RA_DSi3AstVnA zRMk3Od^nk^ivEy(I>>M6Jtn`T&JQEM#~E?G!HoF-Tz*Ti3%sxVav;e6sQecH`|>-= zc(}-?x{#k%$WQ143|J|t*55dJ!tSRr-9Cn)IZ03`C;Eb#sF#)EBrxpVPjb>jS`~s}TX7$w)J97uN+E0o2DD^rYC6vf6ZVw&fyFNi#^lDODU41iS5zFC zw}vUjO@|^~F>!(%1P+DAchc4l2A6JUBb7Y0oOqC!GmhgMifSPGD4y$VQ+3K5Sy6K- zhus~>D6=BKO)AMR)IdA)!DpV{au7YtV;9rmF46HdB#o83$Top-Q;Z%92U+Rw3j2y` zDx?K&0UeL!)O)W3@rpUv{}d{7mi^^&SYIala85i=5X%c3`d`6TxJDp!T;ZJJd95Fh^gs8!fEb2Yj-mvA1JHiDYCQ?^BEQ8;duBCDP)pZl$=tSbhJ_c2za_ zBR(WATH>YiR>gU0wftrndmp>M;G;JWI7@?vk2-rezV$f+qFeDpM;oQ;E$;as0NwjC zT??d3+wEWwJ8ZSfX<*8!pyCoI8pQ;2);IHjXQVo_un~t|4+ud5Z@0+3zsN*M>3rDU z9|(^}Rcte7oVS|4!DdQ-VTj0-RU;Z^W>xy zhLU=h`=s1EE;vVh4MVGEG;*ubNT6kQEwv_lBJ*$S0u7L=43^KY$RGY55>@)chh zv0bP>Yxh+w`%Iwrc1sZvs6-!OU27OW^0z&xX*9$~;(_{Y@4xeXUQdUzO8t`JVKhJf zXXP~z1r&{p0ODyvMSx>3LJNrR?|WzrAY)hv5<@ue3M?G@O*;-peG%`o@%m^%pynxdA%Jna>)4(J5nnrh6ewxc9Xml1fWAI~?WAmOI6Kbd;BU zem%zgI`=oR`BKcUB4XXvn)0z3EDCG}R8Lf9w79AMs9kCOO1Tu>7*v zNe`+!hxAitvxYS@AEW`Wgf+87SNWpTZdH0*IVk&SuYwPhq zdd%N{;6Ii6?Z`iHyvxD)=g%!{^N5HkkR$(Ll3>j9nTXXCqv5Zd;8G|XP$&B;(_4p; z*(VyOd^sM*_P>Z%({M61*@i$c zjW@#KLMT%FKr7ErX+9wq!9ypAlcJ8XotPn`2@1=}Z=3;y!#2?tw3Jl|110(Ia((h8 zS_gi#|Hu#7@0mCNm+iNWrZOrON>rPj3$Q8~J4IEEU5T9Rw``=V&1W_~WG_1~+JCT@ zc75e)?dX5_u>Spf_1W#8{XF6SJ%0pq-#lPMJ7^+4>TFVU-`^p`N*g8UE$)4hSLEIa z-^}##KC<=2JfMM8E{k^Zdh39CNMHqv+<$LN70@A)qkMTh1?%Py$mUJ38ihVEdC`3e zFkmInc%L(!I8Kq)H(F2Up=~zeOmT~BtudKxOYs7T{i4J@IEbq9kMWhS#}_sA;QvE22TA)2{GFS!>=P zkxuXW5xLd@vbr*S9$7-+)sjrKDH6)0m@Td{5T%7rkXv`$Q?Hi zSSd=Xv&Nzfnp;fGfvpl-by);*5~CwWWim%)a?}?b4Ujm>$0Z(HErfJLw>VqO=u7rN z)^}T7YJd&xedYtyoZLo?7g6T8kHBi?yxxh@naH=-kN3Yw=-ly?7cTf~d~tN64G}9S zX-f6;H&QOL3!?p?;;O1WfoOxyvE2{ZYnME-qOMQ}rZLPO6=l+mSo%Dmf3}*}TWyS` zB*t=MFWZ)#!<$Wo@P3Jr7)$6iycCAm9laEW!>x&)A(ml2MZ=o8qM@Q;EfDBZ4YyPx ze5j$8Va=plVWKjq;}yIJO8N_75D|GUbPgY^-mSw;P2Pi?daOyD?BI@VC!F2VD`?nd zSDm8iLc0k%J1TeM500-{)}(*(c#}MF1(l1G#8efg;o^Zy7A(fke3f?7`>88fw@Vo{ z`g=rI+USVxs|H7O-+CO;eFp}`UqO7SDz0JTDW)H8+ z{a3`Iak8TOW_VO(uzG*+fU+QS+25emEiMdR95SFxnORI?l`75ntW=& zLf01H5SsGnqNmsbQ)`Gohqx5d5fi8=ydl4wz)S!o?yo@D3IajV^jJo=zdn+wNxHX( z>v}wq_>mJ$Tdd(*EV_4icLgc-#Cajspje1v6~-P{hEN0XY~O!D2q8q;>x4AFRerjTs)(XU_X*YRTd=qgmqerSxH#tp7;tqCIk$}7oG;Bc^@>8C zyCj=vI+PfA|m#rI;vi*=q6^E5HN{ zrSOM;cp$x2q7!!vfR^H(fhRapFSOtrmkQW%VCnB!$H=VVT=97%qi4|X^jNx@am>22 zM2jreZ@jZF|5O3Hm`jEMA!=_jH97TM0jNp}&6EaNSFnN(_kNhz*q7sNhUp|{)*{WS z$1ty}#s(-8v@F44@Uu>$X|dZa(lPFE!H`r&owFU^`)NE8ZaB!)6BQqzAs4;4YRxF!N)WSuw3Nz3@jGeU)M zcj<+!?kEYDSSXsUoUWsBjS?G5X?=^pfGO{DRCEi7>skOGI^Sa2$D%}2;?2^rh1A1(ff^wJNC+{WX6?&xIX+X$1KqOb9sPhDdQS%wZ4 z%WucfOS*%7G@!ty9gnnLipOTPBZpWevg-cba(zrnKq5|OW^h6?eH0!EZyqvE@Re7Z&@780yB1$a-0NX4aP1iPt& zc-@EOO*4*OQVGwu4sJ#v`@x=A!NIr&nR>i^i&$cOb5%W&=;I2ln9-{*1Q4K26|r|T;9rZFZs`7)+bg}B8aFek=*L=baD zM{OmzyHy9UI40OK+*=3%?v^}d<@k4?gFU9-4?@5Zx1i8A8V@gqiKDwA3uA#}_LIdc z)W;oVo=Yuy8GsHjj@crRjae%HM3q>9z_+L3cYV+iiwUn^9d;a%Gh*2|Q@)gs2&#h~ z&@W~MD(_1=^2?dMh%z)^%FKhv#u3}Hc`P%h`_Po(zvLxdx0!-NE3sREXqfruuNhO! zJJ2)6>WR(D1tA7Fyj(e7XH1a*V6g4VIgYB|t-F9XYBAt&4%NGto+AaNE6Bc%WrSkV z?LDU(*GoYJKFFe%XVMpm7w1gWFLgEzEn8_WGW``wY!}&cppuD&mFP{i^u(7qpejC+ zRmgmy7;E?iN{g|qC?p=qq64+;ETkzT^hB0CMc9=7S~CZuUZkr)8<2R04K5Uy(jX*Y zbHt=%lY4xNkBFRcg!^XFl&la6P*J`UyN0#bcLtO^&<$WkI!h&)% zi1Zg)rrtHiT_1H!y??x?r}+{(s51Y7FZ;?*h;&JqhDv!!Si}Z1iB5{&6t8On)dl7lcXz%| zRK5Px3;#y_yB?-~@FLDHSU=c(VCH_*7|)RS7w>OAcqyB6jTyzBtrbQ_XBC;lA_Y$H7Uj@Q%Y)FQX-WyMx_~}yJ{k*CZ(jIcy~MF zF_Cfc#%N7ik|rv}NNlGjMa?j#IkU>sG`!;W(HdUJk){SgOfy1UQ%x}rjoIZGm6SY3 zLqFiHiAhOH(3nzLeu_6E&TZD_^F!Ukl`VQVBNSO2Hp5) z!gPLeaT?=)_*AeRl1i0HE~UdKPvDufj^k4zpbx$4h>s7syfu8n=(yG4lPvIDauxB( zZOLH-4(#cp!O1dxGRfH_*g?RK9Oic7Fd4_z^hw6G--r2>Npw#?m|EM5=jRFdU}`ux zL7YM}n8Ppua|J9BP($7|KA8e?tcLGlJS|MXJRQd?1k}ff27o^=9N zr}+0$N}d(;lR3;ADd0ouM_vf0_X*=r(vM7${-4s1k}?w3@JP;|kATSn#tIlA;3NUV1k?){C}4qr`2yw%xJAHq06en9La49}^P~cMB>=y~w^7?#g^Y)~8*#LoOiupQS;M%^N zex<<6L|pEWz)M6t?l*xa_v7@fJbC?rWO(oyE$}>HKj`frHDr)0#($H9M|1i^f?m~w z<39*oiVu3%5&VnzU=M*yapw?$OYvxj~BQ~;IRUi&I?`?cwjIuzg*zb`N3v^OXmo5nV9uo)OSYU()q$K0@sN8 z?n(JWc>VR%ynLQm?>Z6gu2QXv=lS^A6jr}BkmJt^TskjF61a3;vPj_4xyf3AOXn&d z3tT!+`9h)(;`M(g@Ceb~4Jm&x&#wiCgZe9--!v9@peWywaM)-~6sPYi;Zr$2THvZk zjvFOBg5wzi&lLGqfolc+CgHHr1)}~6*&Dv4afGDEATA}e3t_MLV;gV z;J+yF+X`HTb<44RZw1~|fwxuQ{tA4c0w1Zs!xi{c1)i+HUsB+!75Ik={D1;4Rp3_@ z_+15FyNR< zR^UG>@Ja>l)zn#jjTQKl3S1MRQoVyMQkZ~~1dJ81SilkiO9dUIS1ZNMnNb%1XHt_OS@`m+J> zWG@Z}4dyUu7>5T0Y=!+J(ajeyaJWjf5%^~8s|Yq71z!*F8O+ar0oL>7Fl8i%wL>`k zY8;2twJOzS(4FQhfrr5jepO;VRXqfW0PixCrI;17D1K z4gj`A`vlj6zXHGt@JH|~;DvxaKu7SWP!5j+9t55XcnI+2u^jq!SE&vI-;H#Fsqkk$ z1FT(-!$ktttgEBxIS%{`ye41(7>o8U0WJ`*RKRGo{{zxr0AB?CP>x_zz{`M}(cd2dzY#DJ z{1Lt!{1F_9daeNO6Yw$2x1WHA4`;7Wbqhql%Yly@!eW-)IzOpW{Q|r)M5Ve4*dFuz zSHLcfRH|!$KOz4*;E1O<+ylL@0RA5Ih+tkf4!;%9AN5drI`s1fU|+zSfWJY1e*+8w z-7Ua?@hnE#ZNwP-Y%uVr0Pg@6A-xi?3VhxLOom<%{HQI5B?9I^K9t@8`F{Yq04I1B z{Qe0T0DcK>Mn4H^R0hMdz3JXEu9!}rPS~hEk*2gH1Kq+L;;RemotDO)6<^( zUUU;QYDTqme|u_=gt$b}if?azf7(E|fDJQEMw79pF(El^PPOtw{O-%eLonDgA#!?B z3hP-71rH9Z#-yYPYe5GENlrmism=iO0YDdQZ;D9pOl*(||Ns~fM^jWrA&J31(MNYJ?PhM?f!u`H`sTw)w<=(A_^bQ(SMKyiY; zez*i~NR2h6MJLTpGWMQ3gDwzV1{d@V(Z&Q*I=)k* z1P6+`sbI7*UMg5)xh=bNpibj@8)}k~eX={ZC!0p)bobTL1Te7I zAarqYabf<@5vHu8?nBD^6_*ee^$^6fQ!s6GabZ17aY=EUVTHYMQs3z~bY=RhB=Tik zrW)h%q72v!oAn?*{i2iDv^LPo9{bio4Ff5_8@nI5e_V9D@xFZ5u-;T_&}qUwP@^4Y z+yga~Rw@1hpRAwvQBV8wQ;jYAyse%kd#=^9{e z=MLJFoqH&!%U!gmNID^>$m(xTk+j~PB1(;);Iu&?o{{A2=!rzdQYTWYO(UKzjR42w zW>p4x=czJCE2P6d!ZFdojdx6zw+_yUaG{+O_)6rM#=T$16t=)RCL|^$CEIs3)pBZV zo0Vako@(^mk~t<`#XAk<)5OqMaYfnAQ-2iL(;`3{mNk zhGbKU(J(76CCwBWuc9RpZwq5}#^YRLN|H+KQmMD{a|+%(o`w48O>JcIU3HQ zf)cyRgvitxL_!-(=|y1~7yXj9pS+ij7~e+Xm0_s}+r3FhOnl@t#uimh0+m?BPA`@5 zPZ?wr1!GR>vC%2<#zd(u_RhM5#K*IalQa!e=cF0sMiSCY5=|m@WYTjA_9Bs~GD@1^ z#2Y0zH%BSF6{!wNai~5uDJBj3A1(}X!(r|b14y7jjgz@nWU!&i;w znb{NlzJPcXvSZ1d3;7X~#QrRXlO2@R$@8u`YkV@bQB@7q= z{(A$WtUcLY(4LkOH7hPgqD(PjcZq4nTB4DRN;M@IlJS!gNht{wDv~l-*Dw!hQb=j` z+EJ1?vuD})G$uqPBqIYb87mPWhyle2Bt|CUw+o_@5~EWMh!#gqO-+i&+xTg5q@=Wq zH{fRuR0c8z2K;6~bP@!K{UUyMA}Iywc;uFXxl0V^>lhvrlT+Z5qN~jPXWL!zEUYj~ zr!Qg%ri1kdFp+V}>m{uazqJ9Y%8ZgBIVnCaY7U8APD(Mx7-6@fz%+scU^kVx#v?ax zf+xh#zx6IqsoLVGMO6!b^g(1@<%-kabh=Q0$4;Oje7wpPfPa<(_~Vbtc;Q5~qLGWr zn`g0aT~ty+cQUeRaro5zzRbQ~WzF*M+Q^Zm4f3%YxvUQUyf zgQp(eqx!j9<{aHO>w}G1>)Zd_X;b*^zRSLzH21B-X|vxl7rv2Hx5=sQyWhO7>HF6? z&3V_+Hz8A!ZXW&!k{lZ$4M6o4{wU1@e^cYC%&Ukm$XhTBKieCo0;*l}hpt zJyAY=kqV<9(7nd^;~MZuFKSB zy1KadsO?HkyBKS^xw^Qk9EnhB-GcgQ+68WI+6Asx*VS@$adq`;wZKKKLb{jh0v8vRW!7kq$!`W-+tjv;>qf)*)IkM3^Q>83gFM>J-@J0rFQe}~tm+l~9oJNEn`KZCk# z?EJu=_iyuzUOD;b6L0;Pd92m+;1=-%59f7g)$-~K+o!CXK493plN$IA(#-0V(6U9| z!BLOJb+CSZuH>-=M@Ok|Oh_yF%5!8)`iA$mZN79mLURTce3hf8B8M;)|=+`;^_=|5CTEH-Bh4UaO|;hAu8uZtmJz0NPfR(AKS)wn=8A zE+uipR?MpN_pKQ@-2?x1XISWb&nepOM9|8uqqe=a?Yh?MS}kfBo0gW`_vxpjQsTQu zlKyqaOnf>8YSbM`+WJJVrWV|w)Qhw}9`X!x^>A~AHajafhSEhfxKG-Q^%sx4v#j@1 zOLw&N3jSne*ZH43lfNzU&)T`K`0Y7!pkHBFpXtGA8?H`nmHgw@Z$`$qXgjl;;nZiZ z?!UHrNwRUlnkGLy;nUR8ZOa#bd8bbr?%ipAk87&A&3De)w(H}4qrcnId`Q7#vi|Lil z`lp$GdHK6_S}p(j$zfr?xc@q3PFA;HdTp2(g8%0BxaHfsBjaz^ey@$z)z)laWmugr z=Lc_q`GvK!_!#h1u{P&5E_tgJtN{e%!5BRw6`?u8fRj<_juyvE}X=nS_`+91V z_cqRaW!Sjz!tGB7?Wp|ohvYA=Yz)!OYZWph?6n}v;k2oBeHI42)MJVHL+zxi&${_7 zjoq=V<+sMvs%cY&X&#`UvT9PP$u`U01^uzj->Q_Z9L zn#iaqV{#fV6N55F`b*SM8(8b6Vl~8`B{3RdS`8vh2`G>ljh}2wjK=Y3QevtmDTaPu ztgBN)+)?C|a{IJuCe!b6v0viC28r#BQoAdrCNp2p^?DPbfiHJG^I>j-(*3tmS6@3Ft^Rz@X#dg;1Mj9+%_y#YHKWf$ z>p0Dq0f#?4@aAZ*8C6~GJ+s-p&WlY0Cp`9K+LybnZTk(|cs8lsrC(0%PX11<`@Z9` z8wu&Z{`7Ivrduw~Yt!>s`?FuE&&@cqp?B4BOf z+XFgG(=6#R{Z73FC%^q=+npU7% z^CsUXw9P!c>b%my^6Jg5(Jn6DUUo;%SEn6QOs{)s=HId|dEuR~snzIJHp(8r!wa^5W=cKfo#-G^OAcwO$; z=t_%;XTJBSeMlHcR}XmAuG&D!-nh89`C~29O1Rc#Q9I$rBt@krI~XfMwf@}@t%{3= zzSu43h>zB|H(YdmN~6KgCO>w<7}Wm5F4MK%WFDD2<*HRV`BF7{UkhAlsF^)&h@n*D zudb6l{Y%?ZViESVvtZHLoI03D+}z?`z0$OL|KDj^oqWgInc5~Kt@h+gdTYHT!PKgy zZD{u?UFuObxs{HI4Wz^xe9e(@zeGI$`lnr0&6c>;Sw6LO_?1}WPaP(wt(cx{I-OY3 z{QD6f*1whZ;)k<6e_xh5eQbxoCHDfqu6t%_^S3q}kJQYWIJ)upFFoDPjk)y7@DHYJ z{P@`9v96~|%U#Z{sY)!FooyL+@3($EA4^TO-QKxx&-9kf_cthe{fXs=Zm#b-aJF$l z*L@z=FAADIx2fA8kNAwUkN23b-Y{gX_kg#T4F6_(-@LG2+HE~B;_L0RCibhmoBBo* zxACv6s`?!n{8QteR=A~XTC^qU7p_i)Ji`?Xe?Dzpn4T*Veu zYtH^J8f8~c$A!XSqr5H-rdZkl*QwgiSq`iIi_0k4|{_Z&Z@n;gAiT?27Ya55( z?eE$Cm&7i|JO=dldoy)+=S5!)>~(9R_pv?CdoG)B@y9OtKSuQSDxPw^s?KlM%ZKIf zxTJdSZnqm}=Iz~gFSyRvD0U$I&Z!0y}~1^vaRW8z2~Mh{B(BJlxw5^ zSbAXJk%?0cRagGH?h-X*+W2pp`+JrDlDB`}u{ZbJ`6gj(qAIxI`7viRkGmEai=G&~ zyM6=xxu*&;LORSp;vU%)tS--%iM7zM}xJO+Pf~e!;THkkp4>l-1yJhhr%(1{{ z3zFV(b-@TBJmKD@el6E0FcDvHDCy$1F5YdrHWtd};r>)DH+K&hRp+pXo2I>&+m*A^ zJCB|-cy;%(vo5^V?6o^Rcdp7>iNHu?{z=0YpP9wY)bz`H@__q2tHmDE z#kG!Vuh#}$(v6SSu3JzK%)7f{Gxf9ZMqY^i`|2AzU5gxtn!J%0eYI?Ji&ecNE#yYc zctkVdJtidoFT^y+Awfs5-}3Vd@T1)pP(R;Z0@Vijw$wH!zo3?PBRgN?;-=xQnI>fP zD9M-b`k#kQY^~gmUkleX-{Cb&-BaCfO4Yi% zIR2Aq%a)X^hGCixm8Ukn@vV00qQ!kT=V`~fy!Ti370)^wmY($T_I@Gb^5%ULi>j6u zW<0&bbfI?i(22pnes`+NYTpxi4S!o(`Q(M)QafkvJvU%O=dG5L-_}~u?(y>Ng~m$5 zzpnX@b9rUpcRjvnpfkU-HtdJhYkkZqtyVnex_#BmhO6uR+FDBTcd5zbt6nif za?fP-TzOCJ6<_u8fx}OooblPz`3b*y?>qeGxW_!^1st2!d(E(x$NxHfZH#-~jpFV} zack-~bo=0|%(1%NQ-9bPr}N+cV_|m38)vF!OPi@eEW@8Vtn}kM`AI*+LNE4B|36vVd(c|m%B`#RDQ%~99oDs5)JAmLIgUgp3TzHm4<_B$A@Ed8 zZMG*{^V*p!hZ>)$XuQ35*FU~}X49O&xy{?=Ja6?Z)%u+;XzcyL;a~Gh#=WBHRP@p= z@9wVe8<*AHI=b71*R8iM{#|dbr~1muFNc=>)h1!os5d{@yzBG6@4er@%k-Y}drWTe z)mz!eH+6jP@(Z~OwT;#;oL{gYvB8+VbtY`NqJ49G>gBJy{q>Eu=d!IE@3eWpxcdssdwQQq%+m;EV4?S1%W6Gb`FV6b= z`m0N_4u9YKg>JM_qP)x z;-cN(7+Q9r=V4>BCyzAQ*dTIe_uCbgdP^@3_}$}V(xUbubq+Q!uAja*r?5@_-qsCQ zAG@|>?Kdw>uG(0BYNL7H-&I$Z4!_*b>#ongQhMy`dU(XMDPDcT(!S}GIL9z=^Oi;@ zC+wIIzp1?9@CSE)*1X)Ts8iY{&rnN;!E>hk9`S>2()vHg44?AKh|oRP&!m2Q!R>_~ z#=iae#>b!EHe*%%+Dli{x&;p`iyT;6H_zYHVO8L2)7oO~uOko4UdGL&GP+!&)%)*8 zm+Rawy4>sZ?Qds}t9`U>Y5Hp8C%>JYT%JF_dE255CwIQvsl4)=GPMfTUo`381=Swe6pWgSIU&d$r+Gxga=LWu7oG^F1;pUK+eM)9M zw_4@ha@4W@U;J_9&cT5xyYs)b`EPB!?t|y1ZSmf=`bp!CAJp2x{^cKh>GI{~Zw9BD zUK}$d`^^ZSiyw46J!9I@9=fEXtDao<=KRpdUj06<>gq_{Z=;U2sXy_2o7z9N+4)lW zTVLuvPaO2)%lY?)o_+3U-h1wS6MA>rxMip@DSUnG;-AM3JbLTQl|Kf(bGbw2$9-p< zJM`mSKXb9)2L1Ohdu)9C@{Z5@jr^|cc>RyIuR68xQFNIfasAUwe-vG&bEHSnQofph! z7Y2GPw?;SIocZ3UR%rnKzJatsv+t%n`y>GZo`+Q2B xR#X1C^mY5rb>7`I(W?JxiRQzm^S57}{nF^pUyM(kdHKU7;y%YC@L!U^{{v?2psfG^ literal 0 HcmV?d00001 diff --git a/ext/bin/tap-mac/tap.kext/Contents/_CodeSignature/CodeResources b/ext/bin/tap-mac/tap.kext/Contents/_CodeSignature/CodeResources new file mode 100644 index 00000000..0710b400 --- /dev/null +++ b/ext/bin/tap-mac/tap.kext/Contents/_CodeSignature/CodeResources @@ -0,0 +1,105 @@ + + + + + files + + files2 + + rules + + ^Resources/ + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ + + nested + + weight + 10 + + ^.* + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^Resources/ + + weight + 20 + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^[^/]+$ + + nested + + weight + 10 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/ext/installfiles/mac/ZeroTier One.pkgproj b/ext/installfiles/mac/ZeroTier One.pkgproj index afda6554..d962e96d 100755 --- a/ext/installfiles/mac/ZeroTier One.pkgproj +++ b/ext/installfiles/mac/ZeroTier One.pkgproj @@ -2,670 +2,731 @@ - PROJECT - - PACKAGE_FILES + PACKAGES + - DEFAULT_INSTALL_LOCATION - / - HIERARCHY + MUST-CLOSE-APPLICATION-ITEMS + + MUST-CLOSE-APPLICATIONS + + PACKAGE_FILES - CHILDREN - - - CHILDREN - - - CHILDREN - - GID - 80 - PATH - Utilities - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 80 - PATH - ../../../macui/build/Release/ZeroTier One.app - PATH_TYPE - 1 - PERMISSIONS - 493 - TYPE - 3 - UID - 0 - - - GID - 80 - PATH - Applications - PATH_TYPE - 0 - PERMISSIONS - 509 - TYPE - 1 - UID - 0 - - - CHILDREN - - - CHILDREN - - - CHILDREN - - - CHILDREN - - - CHILDREN - - GID - 0 - PATH - get-proxy-settings.sh - PATH_TYPE - 1 - PERMISSIONS - 493 - TYPE - 3 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - launch.sh - PATH_TYPE - 1 - PERMISSIONS - 493 - TYPE - 3 - UID - 0 - - - CHILDREN - - GID - 80 - PATH - ../../../MacEthernetTapAgent - PATH_TYPE - 1 - PERMISSIONS - 493 - TYPE - 3 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - uninstall.sh - PATH_TYPE - 1 - PERMISSIONS - 493 - TYPE - 3 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - ../../../zerotier-one - PATH_TYPE - 1 - PERMISSIONS - 493 - TYPE - 3 - UID - 0 - - - GID - 80 - PATH - One - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 2 - UID - 0 - - - GID - 80 - PATH - ZeroTier - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 2 - UID - 0 - - - GID - 80 - PATH - Application Support - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - Automator - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - Documentation - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - Filesystems - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - Frameworks - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - Input Methods - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - Internet Plug-Ins - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - LaunchAgents - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - - CHILDREN - - GID - 0 - PATH - com.zerotier.one.plist - PATH_TYPE - 1 - PERMISSIONS - 420 - TYPE - 3 - UID - 0 - - - GID - 0 - PATH - LaunchDaemons - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - PreferencePanes - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - Preferences - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 80 - PATH - Printers - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - PrivilegedHelperTools - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - QuickLook - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - QuickTime - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - Screen Savers - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - Scripts - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - Services - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - GID - 0 - PATH - Widgets - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - GID - 0 - PATH - Library - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - - CHILDREN - - - CHILDREN - - GID - 0 - PATH - Extensions - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - GID - 0 - PATH - Library - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - GID - 0 - PATH - System - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - CHILDREN - - - CHILDREN - - GID - 0 - PATH - Shared - PATH_TYPE - 0 - PERMISSIONS - 1023 - TYPE - 1 - UID - 0 - - - GID - 80 - PATH - Users - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - - GID - 0 - PATH + DEFAULT_INSTALL_LOCATION / - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID + HIERARCHY + + CHILDREN + + + CHILDREN + + + CHILDREN + + GID + 80 + PATH + Utilities + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 80 + PATH + ../../../macui/build/Release/ZeroTier One.app + PATH_TYPE + 1 + PERMISSIONS + 493 + TYPE + 3 + UID + 0 + + + GID + 80 + PATH + Applications + PATH_TYPE + 0 + PERMISSIONS + 509 + TYPE + 1 + UID + 0 + + + CHILDREN + + + CHILDREN + + + CHILDREN + + + CHILDREN + + + CHILDREN + + GID + 0 + PATH + get-proxy-settings.sh + PATH_TYPE + 1 + PERMISSIONS + 493 + TYPE + 3 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + launch.sh + PATH_TYPE + 1 + PERMISSIONS + 493 + TYPE + 3 + UID + 0 + + + CHILDREN + + GID + 80 + PATH + ../../../MacEthernetTapAgent + PATH_TYPE + 1 + PERMISSIONS + 493 + TYPE + 3 + UID + 0 + + + BUNDLE_CAN_DOWNGRADE + + BUNDLE_POSTINSTALL_PATH + + PATH_TYPE + 0 + + BUNDLE_PREINSTALL_PATH + + PATH_TYPE + 0 + + CHILDREN + + GID + 0 + PATH + ../../bin/tap-mac/tap.kext + PATH_TYPE + 1 + PERMISSIONS + 493 + TYPE + 3 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + uninstall.sh + PATH_TYPE + 1 + PERMISSIONS + 493 + TYPE + 3 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + ../../../zerotier-one + PATH_TYPE + 1 + PERMISSIONS + 493 + TYPE + 3 + UID + 0 + + + GID + 80 + PATH + One + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 2 + UID + 0 + + + GID + 80 + PATH + ZeroTier + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 2 + UID + 0 + + + GID + 80 + PATH + Application Support + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Automator + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Documentation + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Filesystems + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Frameworks + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Input Methods + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Internet Plug-Ins + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + LaunchAgents + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + + CHILDREN + + GID + 0 + PATH + com.zerotier.one.plist + PATH_TYPE + 1 + PERMISSIONS + 420 + TYPE + 3 + UID + 0 + + + GID + 0 + PATH + LaunchDaemons + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + PreferencePanes + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Preferences + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 80 + PATH + Printers + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + PrivilegedHelperTools + PATH_TYPE + 0 + PERMISSIONS + 1005 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + QuickLook + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + QuickTime + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Screen Savers + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Scripts + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Services + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Widgets + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Extensions + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + GID + 0 + PATH + Library + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + + CHILDREN + + + CHILDREN + + GID + 0 + PATH + Extensions + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + GID + 0 + PATH + Library + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + GID + 0 + PATH + System + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + + CHILDREN + + GID + 0 + PATH + Shared + PATH_TYPE + 0 + PERMISSIONS + 1023 + TYPE + 1 + UID + 0 + + + GID + 80 + PATH + Users + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + GID + 0 + PATH + / + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + PAYLOAD_TYPE 0 + PRESERVE_EXTENDED_ATTRIBUTES + + SHOW_INVISIBLE + + SPLIT_FORKS + + TREAT_MISSING_FILES_AS_WARNING + + VERSION + 5 - PAYLOAD_TYPE - 0 - SHOW_INVISIBLE - - SPLIT_FORKS - - TREAT_MISSING_FILES_AS_WARNING - - VERSION - 3 - - PACKAGE_SCRIPTS - - POSTINSTALL_PATH + PACKAGE_SCRIPTS - PATH - postinst.sh - PATH_TYPE - 1 + POSTINSTALL_PATH + + PATH + postinst.sh + PATH_TYPE + 1 + + PREINSTALL_PATH + + PATH + preinst.sh + PATH_TYPE + 1 + + RESOURCES + - PREINSTALL_PATH + PACKAGE_SETTINGS - PATH - preinst.sh - PATH_TYPE + AUTHENTICATION 1 + CONCLUSION_ACTION + 0 + FOLLOW_SYMBOLIC_LINKS + + IDENTIFIER + com.zerotier.pkg.ZeroTierOne + LOCATION + 0 + NAME + ZeroTier One + OVERWRITE_PERMISSIONS + + PAYLOAD_SIZE + -1 + REFERENCE_PATH + + RELOCATABLE + + USE_HFS+_COMPRESSION + + VERSION + 1.4.2 - RESOURCES - - - PACKAGE_SETTINGS - - AUTHENTICATION - 1 - CONCLUSION_ACTION + TYPE 0 - FOLLOW_SYMBOLIC_LINKS - - IDENTIFIER - com.zerotier.pkg.ZeroTierOne - LOCATION - 0 - NAME - - OVERWRITE_PERMISSIONS - - PAYLOAD_SIZE - -1 - RELOCATABLE - - USE_HFS+_COMPRESSION - - VERSION - 1.4.2 + UUID + 1B6AFC3A-9EA5-4401-83D4-37F06CD13CD6 + + PROJECT + PROJECT_COMMENTS NOTES @@ -701,8 +762,139 @@ dG1sPgo= + PROJECT_PRESENTATION + + BACKGROUND + + APPAREANCES + + DARK_AQUA + + LIGHT_AQUA + + + SHARED_SETTINGS_FOR_ALL_APPAREANCES + + + INSTALLATION_STEPS + + + ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS + ICPresentationViewIntroductionController + INSTALLER_PLUGIN + Introduction + LIST_TITLE_KEY + InstallerSectionTitle + + + ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS + ICPresentationViewReadMeController + INSTALLER_PLUGIN + ReadMe + LIST_TITLE_KEY + InstallerSectionTitle + + + ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS + ICPresentationViewLicenseController + INSTALLER_PLUGIN + License + LIST_TITLE_KEY + InstallerSectionTitle + + + ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS + ICPresentationViewDestinationSelectController + INSTALLER_PLUGIN + TargetSelect + LIST_TITLE_KEY + InstallerSectionTitle + + + ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS + ICPresentationViewInstallationTypeController + INSTALLER_PLUGIN + PackageSelection + LIST_TITLE_KEY + InstallerSectionTitle + + + ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS + ICPresentationViewInstallationController + INSTALLER_PLUGIN + Install + LIST_TITLE_KEY + InstallerSectionTitle + + + ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS + ICPresentationViewSummaryController + INSTALLER_PLUGIN + Summary + LIST_TITLE_KEY + InstallerSectionTitle + + + INTRODUCTION + + LOCALIZATIONS + + + LICENSE + + LOCALIZATIONS + + MODE + 0 + + README + + LOCALIZATIONS + + + TITLE + + LOCALIZATIONS + + + + PROJECT_REQUIREMENTS + + LIST + + + BEHAVIOR + 3 + DICTIONARY + + IC_REQUIREMENT_OS_DISK_TYPE + 0 + IC_REQUIREMENT_OS_DISTRIBUTION_TYPE + 0 + IC_REQUIREMENT_OS_MINIMUM_VERSION + 100900 + + IC_REQUIREMENT_CHECK_TYPE + 1 + IDENTIFIER + fr.whitebox.Packages.requirement.os + MESSAGE + + NAME + Operating System + STATE + + + + RESOURCES + + ROOT_VOLUME_ONLY + + PROJECT_SETTINGS + BUILD_FORMAT + 0 BUILD_PATH PATH @@ -882,10 +1074,17 @@ ZeroTier One PAYLOAD_ONLY + TREAT_MISSING_PRESENTATION_DOCUMENTS_AS_WARNING + + SHARED_GLOBAL_DATA + + IC_REQUIREMENT_JAVASCRIPT_SHARED_SOURCE_CODE + + TYPE - 1 + 0 VERSION 2 diff --git a/ext/installfiles/mac/postinst.sh b/ext/installfiles/mac/postinst.sh index b4ea2ee2..95301a4e 100755 --- a/ext/installfiles/mac/postinst.sh +++ b/ext/installfiles/mac/postinst.sh @@ -3,6 +3,7 @@ export PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin OSX_RELEASE=`sw_vers -productVersion | cut -d . -f 1,2` +DARWIN_MAJOR=`uname -r | cut -d . -f 1` launchctl unload /Library/LaunchDaemons/com.zerotier.one.plist >>/dev/null 2>&1 sleep 0.5 @@ -43,9 +44,11 @@ rm -f zerotier-cli zerotier-idtool ln -sf "/Library/Application Support/ZeroTier/One/zerotier-one" zerotier-cli ln -sf "/Library/Application Support/ZeroTier/One/zerotier-one" zerotier-idtool -cd "/Library/Application Support/ZeroTier/One" -kextload -r . tap.kext >>/dev/null 2>&1 & -disown %1 +if [ $DARWIN_MAJOR -le 16 ]; then + cd "/Library/Application Support/ZeroTier/One" + kextload -r . tap.kext >>/dev/null 2>&1 & + disown %1 +fi launchctl load /Library/LaunchDaemons/com.zerotier.one.plist >>/dev/null 2>&1 diff --git a/osdep/BSDEthernetTap.hpp b/osdep/BSDEthernetTap.hpp index deefd5c7..5b1fe2dc 100644 --- a/osdep/BSDEthernetTap.hpp +++ b/osdep/BSDEthernetTap.hpp @@ -38,10 +38,11 @@ #include "../node/MulticastGroup.hpp" #include "../node/MAC.hpp" #include "Thread.hpp" +#include "EthernetTap.hpp" namespace ZeroTier { -class BSDEthernetTap +class BSDEthernetTap : public EthernetTap { public: BSDEthernetTap( @@ -54,18 +55,18 @@ public: void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), void *arg); - ~BSDEthernetTap(); + virtual ~BSDEthernetTap(); - void setEnabled(bool en); - bool enabled() const; - bool addIp(const InetAddress &ip); - bool removeIp(const InetAddress &ip); - std::vector ips() const; - void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len); - std::string deviceName() const; - void setFriendlyName(const char *friendlyName); - void scanMulticastGroups(std::vector &added,std::vector &removed); - void setMtu(unsigned int mtu); + virtual void setEnabled(bool en); + virtual bool enabled() const; + virtual bool addIp(const InetAddress &ip); + virtual bool removeIp(const InetAddress &ip); + virtual std::vector ips() const; + virtual void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len); + virtual std::string deviceName() const; + virtual void setFriendlyName(const char *friendlyName); + virtual void scanMulticastGroups(std::vector &added,std::vector &removed); + virtual void setMtu(unsigned int mtu); void threadMain() throw(); diff --git a/osdep/EthernetTap.cpp b/osdep/EthernetTap.cpp new file mode 100644 index 00000000..a10db55f --- /dev/null +++ b/osdep/EthernetTap.cpp @@ -0,0 +1,117 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + +#include "EthernetTap.hpp" +#include "OSUtils.hpp" + +#include +#include + +#ifdef __APPLE__ +#include +#include +#include "MacEthernetTap.hpp" +#include "MacKextEthernetTap.hpp" +#endif // __APPLE__ + +#ifdef __LINUX__ +#include "LinuxEthernetTap.hpp" +#endif // __LINUX__ + +#ifdef __WINDOWS__ +#include "WindowsEthernetTap.hpp" +#endif // __WINDOWS__ + +#ifdef __FreeBSD__ +#include "BSDEthernetTap.hpp" +#endif // __FreeBSD__ + +#ifdef __NetBSD__ +#include "NetBSDEthernetTap.hpp" +#endif // __NetBSD__ + +#ifdef __OpenBSD__ +#include "BSDEthernetTap.hpp" +#endif // __OpenBSD__ + +namespace ZeroTier { + +std::shared_ptr EthernetTap::newInstance( + const char *tapDeviceType, // OS-specific, NULL for default + const char *homePath, + const MAC &mac, + unsigned int mtu, + unsigned int metric, + uint64_t nwid, + const char *friendlyName, + void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), + void *arg) +{ +#ifdef __APPLE__ + char osrelease[256]; + size_t size = sizeof(osrelease); + if (sysctlbyname("kern.osrelease",osrelease,&size,nullptr,0) == 0) { + char *dotAt = strchr(osrelease,'.'); + if (dotAt) { + *dotAt = (char)0; + // The "feth" virtual Ethernet device type appeared in Darwin 17.x.x. Older versions + // (Sierra and earlier) must use the a kernel extension. + if (strtol(osrelease,(char **)0,10) < 17) { + return std::shared_ptr(new MacKextEthernetTap(homePath,mac,mtu,metric,nwid,friendlyName,handler,arg)); + } else { + return std::shared_ptr(new MacEthernetTap(homePath,mac,mtu,metric,nwid,friendlyName,handler,arg)); + } + } + } +#endif // __APPLE__ + +#ifdef __LINUX__ + return std::shared_ptr(new LinuxEthernetTap(homePath,mac,mtu,metric,nwid,friendlyName,handler,arg)); +#endif // __LINUX__ + +#ifdef __WINDOWS__ + return std::shared_ptr(new WindowsEthernetTap(homePath,mac,mtu,metric,nwid,friendlyName,handler,arg)); +#endif // __WINDOWS__ + +#ifdef __FreeBSD__ + return std::shared_ptr(new BSDEthernetTap(homePath,mac,mtu,metric,nwid,friendlyName,handler,arg)); +#endif // __FreeBSD__ + +#ifdef __NetBSD__ + return std::shared_ptr(new NetBSDEthernetTap(homePath,mac,mtu,metric,nwid,friendlyName,handler,arg)); +#endif // __NetBSD__ + +#ifdef __OpenBSD__ + return std::shared_ptr(new BSDEthernetTap(homePath,mac,mtu,metric,nwid,friendlyName,handler,arg)); +#endif // __OpenBSD__ + + return std::shared_ptr(); +} + +EthernetTap::EthernetTap() {} +EthernetTap::~EthernetTap() {} + +} // namespace ZeroTier diff --git a/osdep/EthernetTap.hpp b/osdep/EthernetTap.hpp new file mode 100644 index 00000000..fc8fc848 --- /dev/null +++ b/osdep/EthernetTap.hpp @@ -0,0 +1,72 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + +#ifndef ZT_ETHERNETTAP_HPP +#define ZT_ETHERNETTAP_HPP + +#include "../node/Constants.hpp" +#include "../node/MAC.hpp" +#include "../node/InetAddress.hpp" +#include "../node/MulticastGroup.hpp" + +#include +#include +#include + +namespace ZeroTier { + +class EthernetTap +{ +public: + static std::shared_ptr newInstance( + const char *tapDeviceType, // OS-specific, NULL for default + const char *homePath, + const MAC &mac, + unsigned int mtu, + unsigned int metric, + uint64_t nwid, + const char *friendlyName, + void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), + void *arg); + + EthernetTap(); + virtual ~EthernetTap(); + + virtual void setEnabled(bool en) = 0; + virtual bool enabled() const = 0; + virtual bool addIp(const InetAddress &ip) = 0; + virtual bool removeIp(const InetAddress &ip) = 0; + virtual std::vector ips() const = 0; + virtual void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len) = 0; + virtual std::string deviceName() const = 0; + virtual void setFriendlyName(const char *friendlyName) = 0; + virtual void scanMulticastGroups(std::vector &added,std::vector &removed) = 0; + virtual void setMtu(unsigned int mtu) = 0; +}; + +} // namespace ZeroTier + +#endif diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index 2ea93dd1..5ed49eef 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -24,6 +24,17 @@ * of your own application. */ +#include "../node/Constants.hpp" + +#ifdef __LINUX__ + +#include "../node/Utils.hpp" +#include "../node/Mutex.hpp" +#include "../node/Dictionary.hpp" +#include "OSUtils.hpp" +#include "LinuxEthernetTap.hpp" +#include "LinuxNetLink.hpp" + #include #include #include @@ -50,14 +61,6 @@ #include #include -#include "../node/Constants.hpp" -#include "../node/Utils.hpp" -#include "../node/Mutex.hpp" -#include "../node/Dictionary.hpp" -#include "OSUtils.hpp" -#include "LinuxEthernetTap.hpp" -#include "LinuxNetLink.hpp" - // ff:ff:ff:ff:ff:ff with no ADI static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff),0); @@ -519,3 +522,5 @@ void LinuxEthernetTap::threadMain() } } // namespace ZeroTier + +#endif // __LINUX__ diff --git a/osdep/LinuxEthernetTap.hpp b/osdep/LinuxEthernetTap.hpp index 050bec34..1acecb4b 100644 --- a/osdep/LinuxEthernetTap.hpp +++ b/osdep/LinuxEthernetTap.hpp @@ -33,16 +33,15 @@ #include #include #include +#include #include "../node/MulticastGroup.hpp" #include "Thread.hpp" +#include "EthernetTap.hpp" namespace ZeroTier { -/** - * Linux Ethernet tap using kernel tun/tap driver - */ -class LinuxEthernetTap +class LinuxEthernetTap : public EthernetTap { public: LinuxEthernetTap( @@ -55,21 +54,21 @@ public: void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), void *arg); - ~LinuxEthernetTap(); + virtual ~LinuxEthernetTap(); - void setEnabled(bool en); - bool enabled() const; - bool addIp(const InetAddress &ip); + virtual void setEnabled(bool en); + virtual bool enabled() const; + virtual bool addIp(const InetAddress &ip); #ifdef __SYNOLOGY__ bool addIpSyn(std::vector ips); #endif - bool removeIp(const InetAddress &ip); - std::vector ips() const; - void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len); - std::string deviceName() const; - void setFriendlyName(const char *friendlyName); - void scanMulticastGroups(std::vector &added,std::vector &removed); - void setMtu(unsigned int mtu); + virtual bool removeIp(const InetAddress &ip); + virtual std::vector ips() const; + virtual void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len); + virtual std::string deviceName() const; + virtual void setFriendlyName(const char *friendlyName); + virtual void scanMulticastGroups(std::vector &added,std::vector &removed); + virtual void setMtu(unsigned int mtu); void threadMain() throw(); @@ -85,7 +84,7 @@ private: unsigned int _mtu; int _fd; int _shutdownSignalPipe[2]; - volatile bool _enabled; + std::atomic_bool _enabled; }; } // namespace ZeroTier diff --git a/osdep/MacEthernetTap.cpp b/osdep/MacEthernetTap.cpp index a11a75e2..237df470 100644 --- a/osdep/MacEthernetTap.cpp +++ b/osdep/MacEthernetTap.cpp @@ -24,6 +24,17 @@ * of your own application. */ +#include "../node/Constants.hpp" + +#ifdef __APPLE__ + +#include "../node/Utils.hpp" +#include "../node/Mutex.hpp" +#include "../node/Dictionary.hpp" +#include "OSUtils.hpp" +#include "MacEthernetTap.hpp" +#include "MacEthernetTapAgent.h" + #include #include #include @@ -57,14 +68,6 @@ #include #include -#include "../node/Constants.hpp" -#include "../node/Utils.hpp" -#include "../node/Mutex.hpp" -#include "../node/Dictionary.hpp" -#include "OSUtils.hpp" -#include "MacEthernetTap.hpp" -#include "MacEthernetTapAgent.h" - static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff),0); namespace ZeroTier { @@ -463,3 +466,5 @@ void MacEthernetTap::threadMain() } } // namespace ZeroTier + +#endif // __APPLE__ diff --git a/osdep/MacEthernetTap.hpp b/osdep/MacEthernetTap.hpp index fb5bc6db..2eef59be 100644 --- a/osdep/MacEthernetTap.hpp +++ b/osdep/MacEthernetTap.hpp @@ -27,24 +27,24 @@ #ifndef ZT_OSXETHERNETTAP_HPP #define ZT_OSXETHERNETTAP_HPP -#include -#include - -#include -#include -#include - #include "../node/Constants.hpp" #include "../node/MAC.hpp" #include "../node/InetAddress.hpp" #include "../node/MulticastGroup.hpp" #include "../node/Mutex.hpp" - #include "Thread.hpp" +#include "EthernetTap.hpp" + +#include +#include + +#include +#include +#include namespace ZeroTier { -class MacEthernetTap +class MacEthernetTap : public EthernetTap { public: MacEthernetTap( @@ -57,18 +57,18 @@ public: void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), void *arg); - ~MacEthernetTap(); + virtual ~MacEthernetTap(); - void setEnabled(bool en); - bool enabled() const; - bool addIp(const InetAddress &ip); - bool removeIp(const InetAddress &ip); - std::vector ips() const; - void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len); - std::string deviceName() const; - void setFriendlyName(const char *friendlyName); - void scanMulticastGroups(std::vector &added,std::vector &removed); - void setMtu(unsigned int mtu); + virtual void setEnabled(bool en); + virtual bool enabled() const; + virtual bool addIp(const InetAddress &ip); + virtual bool removeIp(const InetAddress &ip); + virtual std::vector ips() const; + virtual void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len); + virtual std::string deviceName() const; + virtual void setFriendlyName(const char *friendlyName); + virtual void scanMulticastGroups(std::vector &added,std::vector &removed); + virtual void setMtu(unsigned int mtu); void threadMain() throw(); diff --git a/osdep/MacKextEthernetTap.cpp b/osdep/MacKextEthernetTap.cpp new file mode 100644 index 00000000..4f0520a6 --- /dev/null +++ b/osdep/MacKextEthernetTap.cpp @@ -0,0 +1,703 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// OSX compile fix... in6_var defines this in a struct which namespaces it for C++ ... why?!? +struct prf_ra { + u_char onlink : 1; + u_char autonomous : 1; + u_char reserved : 6; +} prf_ra; + +#include +#include + +// These are KERNEL_PRIVATE... why? +#ifndef SIOCAUTOCONF_START +#define SIOCAUTOCONF_START _IOWR('i', 132, struct in6_ifreq) /* accept rtadvd on this interface */ +#endif +#ifndef SIOCAUTOCONF_STOP +#define SIOCAUTOCONF_STOP _IOWR('i', 133, struct in6_ifreq) /* stop accepting rtadv for this interface */ +#endif + +// -------------------------------------------------------------------------- +// -------------------------------------------------------------------------- +// This source is from: +// http://www.opensource.apple.com/source/Libinfo/Libinfo-406.17/gen.subproj/getifmaddrs.c?txt +// It's here because OSX 10.6 does not have this convenience function. + +#define SALIGN (sizeof(uint32_t) - 1) +#define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : \ +(SALIGN + 1)) +#define MAX_SYSCTL_TRY 5 +#define RTA_MASKS (RTA_GATEWAY | RTA_IFP | RTA_IFA) + +/* FreeBSD uses NET_RT_IFMALIST and RTM_NEWMADDR from */ +/* We can use NET_RT_IFLIST2 and RTM_NEWMADDR2 on Darwin */ +//#define DARWIN_COMPAT + +//#ifdef DARWIN_COMPAT +#define GIM_SYSCTL_MIB NET_RT_IFLIST2 +#define GIM_RTM_ADDR RTM_NEWMADDR2 +//#else +//#define GIM_SYSCTL_MIB NET_RT_IFMALIST +//#define GIM_RTM_ADDR RTM_NEWMADDR +//#endif + +// Not in 10.6 includes so use our own +struct _intl_ifmaddrs { + struct _intl_ifmaddrs *ifma_next; + struct sockaddr *ifma_name; + struct sockaddr *ifma_addr; + struct sockaddr *ifma_lladdr; +}; + +static inline int _intl_getifmaddrs(struct _intl_ifmaddrs **pif) +{ + int icnt = 1; + int dcnt = 0; + int ntry = 0; + size_t len; + size_t needed; + int mib[6]; + int i; + char *buf; + char *data; + char *next; + char *p; + struct ifma_msghdr2 *ifmam; + struct _intl_ifmaddrs *ifa, *ift; + struct rt_msghdr *rtm; + struct sockaddr *sa; + + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[2] = 0; /* protocol */ + mib[3] = 0; /* wildcard address family */ + mib[4] = GIM_SYSCTL_MIB; + mib[5] = 0; /* no flags */ + do { + if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) + return (-1); + if ((buf = (char *)malloc(needed)) == NULL) + return (-1); + if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { + if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) { + free(buf); + return (-1); + } + free(buf); + buf = NULL; + } + } while (buf == NULL); + + for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { + rtm = (struct rt_msghdr *)(void *)next; + if (rtm->rtm_version != RTM_VERSION) + continue; + switch (rtm->rtm_type) { + case GIM_RTM_ADDR: + ifmam = (struct ifma_msghdr2 *)(void *)rtm; + if ((ifmam->ifmam_addrs & RTA_IFA) == 0) + break; + icnt++; + p = (char *)(ifmam + 1); + for (i = 0; i < RTAX_MAX; i++) { + if ((RTA_MASKS & ifmam->ifmam_addrs & + (1 << i)) == 0) + continue; + sa = (struct sockaddr *)(void *)p; + len = SA_RLEN(sa); + dcnt += len; + p += len; + } + break; + } + } + + data = (char *)malloc(sizeof(struct _intl_ifmaddrs) * icnt + dcnt); + if (data == NULL) { + free(buf); + return (-1); + } + + ifa = (struct _intl_ifmaddrs *)(void *)data; + data += sizeof(struct _intl_ifmaddrs) * icnt; + + memset(ifa, 0, sizeof(struct _intl_ifmaddrs) * icnt); + ift = ifa; + + for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { + rtm = (struct rt_msghdr *)(void *)next; + if (rtm->rtm_version != RTM_VERSION) + continue; + + switch (rtm->rtm_type) { + case GIM_RTM_ADDR: + ifmam = (struct ifma_msghdr2 *)(void *)rtm; + if ((ifmam->ifmam_addrs & RTA_IFA) == 0) + break; + + p = (char *)(ifmam + 1); + for (i = 0; i < RTAX_MAX; i++) { + if ((RTA_MASKS & ifmam->ifmam_addrs & + (1 << i)) == 0) + continue; + sa = (struct sockaddr *)(void *)p; + len = SA_RLEN(sa); + switch (i) { + case RTAX_GATEWAY: + ift->ifma_lladdr = + (struct sockaddr *)(void *)data; + memcpy(data, p, len); + data += len; + break; + + case RTAX_IFP: + ift->ifma_name = + (struct sockaddr *)(void *)data; + memcpy(data, p, len); + data += len; + break; + + case RTAX_IFA: + ift->ifma_addr = + (struct sockaddr *)(void *)data; + memcpy(data, p, len); + data += len; + break; + + default: + data += len; + break; + } + p += len; + } + ift->ifma_next = ift + 1; + ift = ift->ifma_next; + break; + } + } + + free(buf); + + if (ift > ifa) { + ift--; + ift->ifma_next = NULL; + *pif = ifa; + } else { + *pif = NULL; + free(ifa); + } + return (0); +} + +static inline void _intl_freeifmaddrs(struct _intl_ifmaddrs *ifmp) +{ + free(ifmp); +} + +// -------------------------------------------------------------------------- +// -------------------------------------------------------------------------- + +#include +#include +#include +#include + +#include "../node/Constants.hpp" +#include "../node/Utils.hpp" +#include "../node/Mutex.hpp" +#include "../node/Dictionary.hpp" +#include "OSUtils.hpp" +#include "MacKextEthernetTap.hpp" + +// ff:ff:ff:ff:ff:ff with no ADI +static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff),0); + +static inline bool _setIpv6Stuff(const char *ifname,bool performNUD,bool acceptRouterAdverts) +{ + struct in6_ndireq nd; + struct in6_ifreq ifr; + + int s = socket(AF_INET6,SOCK_DGRAM,0); + if (s <= 0) + return false; + + memset(&nd,0,sizeof(nd)); + strncpy(nd.ifname,ifname,sizeof(nd.ifname)); + + if (ioctl(s,SIOCGIFINFO_IN6,&nd)) { + close(s); + return false; + } + + unsigned long oldFlags = (unsigned long)nd.ndi.flags; + + if (performNUD) + nd.ndi.flags |= ND6_IFF_PERFORMNUD; + else nd.ndi.flags &= ~ND6_IFF_PERFORMNUD; + + if (oldFlags != (unsigned long)nd.ndi.flags) { + if (ioctl(s,SIOCSIFINFO_FLAGS,&nd)) { + close(s); + return false; + } + } + + memset(&ifr,0,sizeof(ifr)); + strncpy(ifr.ifr_name,ifname,sizeof(ifr.ifr_name)); + if (ioctl(s,acceptRouterAdverts ? SIOCAUTOCONF_START : SIOCAUTOCONF_STOP,&ifr)) { + close(s); + return false; + } + + close(s); + return true; +} + +namespace ZeroTier { + +static long globalTapsRunning = 0; +static Mutex globalTapCreateLock; + +MacKextEthernetTap::MacKextEthernetTap( + const char *homePath, + const MAC &mac, + unsigned int mtu, + unsigned int metric, + uint64_t nwid, + const char *friendlyName, + void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *data,unsigned int len), + void *arg) : + _handler(handler), + _arg(arg), + _nwid(nwid), + _homePath(homePath), + _mtu(mtu), + _metric(metric), + _fd(0), + _enabled(true) +{ + char devpath[64],ethaddr[64],mtustr[32],metstr[32],nwids[32]; + struct stat stattmp; + + OSUtils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid); + + Mutex::Lock _gl(globalTapCreateLock); + + if (::stat("/dev/zt0",&stattmp)) { + long kextpid = (long)vfork(); + if (kextpid == 0) { + ::chdir(homePath); + OSUtils::redirectUnixOutputs("/dev/null",(const char *)0); + ::execl("/sbin/kextload","/sbin/kextload","-q","-repository",homePath,"tap.kext",(const char *)0); + ::_exit(-1); + } else if (kextpid > 0) { + int exitcode = -1; + ::waitpid(kextpid,&exitcode,0); + } + ::usleep(500); // give tap device driver time to start up and try again + if (::stat("/dev/zt0",&stattmp)) + throw std::runtime_error("/dev/zt# tap devices do not exist and cannot load tap.kext"); + } + + // Try to reopen the last device we had, if we had one and it's still unused. + std::map globalDeviceMap; + FILE *devmapf = fopen((_homePath + ZT_PATH_SEPARATOR_S + "devicemap").c_str(),"r"); + if (devmapf) { + char buf[256]; + while (fgets(buf,sizeof(buf),devmapf)) { + char *x = (char *)0; + char *y = (char *)0; + char *saveptr = (char *)0; + for(char *f=Utils::stok(buf,"\r\n=",&saveptr);(f);f=Utils::stok((char *)0,"\r\n=",&saveptr)) { + if (!x) x = f; + else if (!y) y = f; + else break; + } + if ((x)&&(y)&&(x[0])&&(y[0])) + globalDeviceMap[x] = y; + } + fclose(devmapf); + } + bool recalledDevice = false; + std::map::const_iterator gdmEntry = globalDeviceMap.find(nwids); + if (gdmEntry != globalDeviceMap.end()) { + std::string devpath("/dev/"); devpath.append(gdmEntry->second); + if (stat(devpath.c_str(),&stattmp) == 0) { + _fd = ::open(devpath.c_str(),O_RDWR); + if (_fd > 0) { + _dev = gdmEntry->second; + recalledDevice = true; + } + } + } + + // Open the first unused tap device if we didn't recall a previous one. + if (!recalledDevice) { + for(int i=0;i<64;++i) { + OSUtils::ztsnprintf(devpath,sizeof(devpath),"/dev/zt%d",i); + if (stat(devpath,&stattmp)) + throw std::runtime_error("no more TAP devices available"); + _fd = ::open(devpath,O_RDWR); + if (_fd > 0) { + char foo[16]; + OSUtils::ztsnprintf(foo,sizeof(foo),"zt%d",i); + _dev = foo; + break; + } + } + } + + if (_fd <= 0) + throw std::runtime_error("unable to open TAP device or no more devices available"); + + if (fcntl(_fd,F_SETFL,fcntl(_fd,F_GETFL) & ~O_NONBLOCK) == -1) { + ::close(_fd); + throw std::runtime_error("unable to set flags on file descriptor for TAP device"); + } + + // Configure MAC address and MTU, bring interface up + OSUtils::ztsnprintf(ethaddr,sizeof(ethaddr),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)mac[0],(int)mac[1],(int)mac[2],(int)mac[3],(int)mac[4],(int)mac[5]); + OSUtils::ztsnprintf(mtustr,sizeof(mtustr),"%u",_mtu); + OSUtils::ztsnprintf(metstr,sizeof(metstr),"%u",_metric); + long cpid = (long)vfork(); + if (cpid == 0) { + ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"lladdr",ethaddr,"mtu",mtustr,"metric",metstr,"up",(const char *)0); + ::_exit(-1); + } else if (cpid > 0) { + int exitcode = -1; + ::waitpid(cpid,&exitcode,0); + if (exitcode) { + ::close(_fd); + throw std::runtime_error("ifconfig failure setting link-layer address and activating tap interface"); + } + } + + _setIpv6Stuff(_dev.c_str(),true,false); + + // Set close-on-exec so that devices cannot persist if we fork/exec for update + fcntl(_fd,F_SETFD,fcntl(_fd,F_GETFD) | FD_CLOEXEC); + + ::pipe(_shutdownSignalPipe); + + ++globalTapsRunning; + + globalDeviceMap[nwids] = _dev; + devmapf = fopen((_homePath + ZT_PATH_SEPARATOR_S + "devicemap").c_str(),"w"); + if (devmapf) { + gdmEntry = globalDeviceMap.begin(); + while (gdmEntry != globalDeviceMap.end()) { + fprintf(devmapf,"%s=%s\n",gdmEntry->first.c_str(),gdmEntry->second.c_str()); + ++gdmEntry; + } + fclose(devmapf); + } + + _thread = Thread::start(this); +} + +MacKextEthernetTap::~MacKextEthernetTap() +{ + ::write(_shutdownSignalPipe[1],"\0",1); // causes thread to exit + Thread::join(_thread); + + ::close(_fd); + ::close(_shutdownSignalPipe[0]); + ::close(_shutdownSignalPipe[1]); + + { + Mutex::Lock _gl(globalTapCreateLock); + if (--globalTapsRunning <= 0) { + globalTapsRunning = 0; // sanity check -- should not be possible + + char tmp[16384]; + sprintf(tmp,"%s/%s",_homePath.c_str(),"tap.kext"); + long kextpid = (long)vfork(); + if (kextpid == 0) { + OSUtils::redirectUnixOutputs("/dev/null",(const char *)0); + ::execl("/sbin/kextunload","/sbin/kextunload",tmp,(const char *)0); + ::_exit(-1); + } else if (kextpid > 0) { + int exitcode = -1; + ::waitpid(kextpid,&exitcode,0); + } + } + } +} + +void MacKextEthernetTap::setEnabled(bool en) +{ + _enabled = en; + // TODO: interface status change +} + +bool MacKextEthernetTap::enabled() const +{ + return _enabled; +} + +bool MacKextEthernetTap::addIp(const InetAddress &ip) +{ + if (!ip) + return false; + + long cpid = (long)vfork(); + if (cpid == 0) { + char tmp[128]; + ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),(ip.ss_family == AF_INET6) ? "inet6" : "inet",ip.toString(tmp),"alias",(const char *)0); + ::_exit(-1); + } else if (cpid > 0) { + int exitcode = -1; + ::waitpid(cpid,&exitcode,0); + return (exitcode == 0); + } // else return false... + + return false; +} + +bool MacKextEthernetTap::removeIp(const InetAddress &ip) +{ + if (!ip) + return true; + std::vector allIps(ips()); + for(std::vector::iterator i(allIps.begin());i!=allIps.end();++i) { + if (*i == ip) { + long cpid = (long)vfork(); + if (cpid == 0) { + char tmp[128]; + execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),(ip.ss_family == AF_INET6) ? "inet6" : "inet",ip.toIpString(tmp),"-alias",(const char *)0); + _exit(-1); + } else if (cpid > 0) { + int exitcode = -1; + waitpid(cpid,&exitcode,0); + return (exitcode == 0); + } + } + } + return false; +} + +std::vector MacKextEthernetTap::ips() const +{ + struct ifaddrs *ifa = (struct ifaddrs *)0; + if (getifaddrs(&ifa)) + return std::vector(); + + std::vector r; + + struct ifaddrs *p = ifa; + while (p) { + if ((!strcmp(p->ifa_name,_dev.c_str()))&&(p->ifa_addr)&&(p->ifa_netmask)&&(p->ifa_addr->sa_family == p->ifa_netmask->sa_family)) { + switch(p->ifa_addr->sa_family) { + case AF_INET: { + struct sockaddr_in *sin = (struct sockaddr_in *)p->ifa_addr; + struct sockaddr_in *nm = (struct sockaddr_in *)p->ifa_netmask; + r.push_back(InetAddress(&(sin->sin_addr.s_addr),4,Utils::countBits((uint32_t)nm->sin_addr.s_addr))); + } break; + case AF_INET6: { + struct sockaddr_in6 *sin = (struct sockaddr_in6 *)p->ifa_addr; + struct sockaddr_in6 *nm = (struct sockaddr_in6 *)p->ifa_netmask; + uint32_t b[4]; + memcpy(b,nm->sin6_addr.s6_addr,sizeof(b)); + r.push_back(InetAddress(sin->sin6_addr.s6_addr,16,Utils::countBits(b[0]) + Utils::countBits(b[1]) + Utils::countBits(b[2]) + Utils::countBits(b[3]))); + } break; + } + } + p = p->ifa_next; + } + + if (ifa) + freeifaddrs(ifa); + + std::sort(r.begin(),r.end()); + r.erase(std::unique(r.begin(),r.end()),r.end()); + + return r; +} + +void MacKextEthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len) +{ + char putBuf[ZT_MAX_MTU + 64]; + if ((_fd > 0)&&(len <= _mtu)&&(_enabled)) { + to.copyTo(putBuf,6); + from.copyTo(putBuf + 6,6); + *((uint16_t *)(putBuf + 12)) = htons((uint16_t)etherType); + memcpy(putBuf + 14,data,len); + len += 14; + ::write(_fd,putBuf,len); + } +} + +std::string MacKextEthernetTap::deviceName() const +{ + return _dev; +} + +void MacKextEthernetTap::setFriendlyName(const char *friendlyName) +{ +} + +void MacKextEthernetTap::scanMulticastGroups(std::vector &added,std::vector &removed) +{ + std::vector newGroups; + + struct _intl_ifmaddrs *ifmap = (struct _intl_ifmaddrs *)0; + if (!_intl_getifmaddrs(&ifmap)) { + struct _intl_ifmaddrs *p = ifmap; + while (p) { + if (p->ifma_addr->sa_family == AF_LINK) { + struct sockaddr_dl *in = (struct sockaddr_dl *)p->ifma_name; + struct sockaddr_dl *la = (struct sockaddr_dl *)p->ifma_addr; + if ((la->sdl_alen == 6)&&(in->sdl_nlen <= _dev.length())&&(!memcmp(_dev.data(),in->sdl_data,in->sdl_nlen))) + newGroups.push_back(MulticastGroup(MAC(la->sdl_data + la->sdl_nlen,6),0)); + } + p = p->ifma_next; + } + _intl_freeifmaddrs(ifmap); + } + + std::vector allIps(ips()); + for(std::vector::iterator ip(allIps.begin());ip!=allIps.end();++ip) + newGroups.push_back(MulticastGroup::deriveMulticastGroupForAddressResolution(*ip)); + + std::sort(newGroups.begin(),newGroups.end()); + std::unique(newGroups.begin(),newGroups.end()); + + for(std::vector::iterator m(newGroups.begin());m!=newGroups.end();++m) { + if (!std::binary_search(_multicastGroups.begin(),_multicastGroups.end(),*m)) + added.push_back(*m); + } + for(std::vector::iterator m(_multicastGroups.begin());m!=_multicastGroups.end();++m) { + if (!std::binary_search(newGroups.begin(),newGroups.end(),*m)) + removed.push_back(*m); + } + + _multicastGroups.swap(newGroups); +} + +void MacKextEthernetTap::setMtu(unsigned int mtu) +{ + if (mtu != _mtu) { + _mtu = mtu; + long cpid = (long)vfork(); + if (cpid == 0) { + char tmp[64]; + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%u",mtu); + execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"mtu",tmp,(const char *)0); + _exit(-1); + } else if (cpid > 0) { + int exitcode = -1; + waitpid(cpid,&exitcode,0); + } + } +} + +void MacKextEthernetTap::threadMain() + throw() +{ + fd_set readfds,nullfds; + MAC to,from; + int n,nfds,r; + char getBuf[ZT_MAX_MTU + 64]; + + Thread::sleep(500); + + FD_ZERO(&readfds); + FD_ZERO(&nullfds); + nfds = (int)std::max(_shutdownSignalPipe[0],_fd) + 1; + + r = 0; + for(;;) { + FD_SET(_shutdownSignalPipe[0],&readfds); + FD_SET(_fd,&readfds); + select(nfds,&readfds,&nullfds,&nullfds,(struct timeval *)0); + + if (FD_ISSET(_shutdownSignalPipe[0],&readfds)) // writes to shutdown pipe terminate thread + break; + + if (FD_ISSET(_fd,&readfds)) { + n = (int)::read(_fd,getBuf + r,sizeof(getBuf) - r); + if (n < 0) { + if ((errno != EINTR)&&(errno != ETIMEDOUT)) + break; + } else { + // Some tap drivers like to send the ethernet frame and the + // payload in two chunks, so handle that by accumulating + // data until we have at least a frame. + r += n; + if (r > 14) { + if (r > ((int)_mtu + 14)) // sanity check for weird TAP behavior on some platforms + r = _mtu + 14; + + if (_enabled) { + to.setTo(getBuf,6); + from.setTo(getBuf + 6,6); + unsigned int etherType = ntohs(((const uint16_t *)getBuf)[6]); + // TODO: VLAN support + _handler(_arg,(void *)0,_nwid,from,to,etherType,0,(const void *)(getBuf + 14),r - 14); + } + + r = 0; + } + } + } + } +} + +} // namespace ZeroTier diff --git a/osdep/MacKextEthernetTap.hpp b/osdep/MacKextEthernetTap.hpp new file mode 100644 index 00000000..fbf2694b --- /dev/null +++ b/osdep/MacKextEthernetTap.hpp @@ -0,0 +1,93 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + +#ifndef ZT_MacKextEthernetTap_HPP +#define ZT_MacKextEthernetTap_HPP + +#include +#include + +#include +#include +#include + +#include "../node/Constants.hpp" +#include "../node/MAC.hpp" +#include "../node/InetAddress.hpp" +#include "../node/MulticastGroup.hpp" + +#include "Thread.hpp" +#include "EthernetTap.hpp" + +namespace ZeroTier { + +class MacKextEthernetTap : public EthernetTap +{ +public: + MacKextEthernetTap( + const char *homePath, + const MAC &mac, + unsigned int mtu, + unsigned int metric, + uint64_t nwid, + const char *friendlyName, + void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), + void *arg); + + virtual ~MacKextEthernetTap(); + + virtual void setEnabled(bool en); + virtual bool enabled() const; + virtual bool addIp(const InetAddress &ip); + virtual bool removeIp(const InetAddress &ip); + virtual std::vector ips() const; + virtual void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len); + virtual std::string deviceName() const; + virtual void setFriendlyName(const char *friendlyName); + virtual void scanMulticastGroups(std::vector &added,std::vector &removed); + virtual void setMtu(unsigned int mtu); + + void threadMain() + throw(); + +private: + void (*_handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int); + void *_arg; + uint64_t _nwid; + Thread _thread; + std::string _homePath; + std::string _dev; + std::vector _multicastGroups; + unsigned int _mtu; + unsigned int _metric; + int _fd; + int _shutdownSignalPipe[2]; + volatile bool _enabled; +}; + +} // namespace ZeroTier + +#endif diff --git a/osdep/NetBSDEthernetTap.hpp b/osdep/NetBSDEthernetTap.hpp index 32b6dfa6..a174816e 100644 --- a/osdep/NetBSDEthernetTap.hpp +++ b/osdep/NetBSDEthernetTap.hpp @@ -38,10 +38,11 @@ #include "../node/MulticastGroup.hpp" #include "../node/MAC.hpp" #include "Thread.hpp" +#include "EthernetTap.hpp" namespace ZeroTier { -class NetBSDEthernetTap +class NetBSDEthernetTap : public EthernetTap { public: NetBSDEthernetTap( @@ -54,17 +55,17 @@ public: void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), void *arg); - ~NetBSDEthernetTap(); + virtual ~NetBSDEthernetTap(); - void setEnabled(bool en); - bool enabled() const; - bool addIp(const InetAddress &ip); - bool removeIp(const InetAddress &ip); - std::vector ips() const; - void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len); - std::string deviceName() const; - void setFriendlyName(const char *friendlyName); - void scanMulticastGroups(std::vector &added,std::vector &removed); + virtual void setEnabled(bool en); + virtual bool enabled() const; + virtual bool addIp(const InetAddress &ip); + virtual bool removeIp(const InetAddress &ip); + virtual std::vector ips() const; + virtual void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len); + virtual std::string deviceName() const; + virtual void setFriendlyName(const char *friendlyName); + virtual void scanMulticastGroups(std::vector &added,std::vector &removed); void threadMain() throw(); diff --git a/osdep/TestEthernetTap.hpp b/osdep/TestEthernetTap.hpp deleted file mode 100644 index 6b44d48e..00000000 --- a/osdep/TestEthernetTap.hpp +++ /dev/null @@ -1,161 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -#ifndef ZT_TESTETHERNETTAP_HPP -#define ZT_TESTETHERNETTAP_HPP - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "../node/Constants.hpp" -#include "../node/InetAddress.hpp" -#include "../node/MulticastGroup.hpp" -#include "../node/Mutex.hpp" -#include "../node/Utils.hpp" -#include "../osdep/OSUtils.hpp" - -namespace ZeroTier { - -/** - * Dummy test Ethernet tap that does not actually open a device on the system - */ -class TestEthernetTap -{ -public: - TestEthernetTap( - const char *homePath, - const MAC &mac, - unsigned int mtu, - unsigned int metric, - uint64_t nwid, - const char *friendlyName, - void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), - void *arg) : - _nwid(nwid), - _dev("zt_test_"), - _enabled(true) - { - char tmp[32]; - OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",(unsigned long long)_nwid); - _dev.append(tmp); -#ifdef ZT_TEST_TAP_REPORT_TO - _reportTo.fromString(ZT_TEST_TAP_REPORT_TO); - if (_reportTo.ss_family == AF_INET) - _reportsock = socket(AF_INET,SOCK_DGRAM,0); - else if (_reportTo.ss_family == AF_INET6) - _reportsock = socket(AF_INET6,SOCK_DGRAM,0); - else _reportsock = -1; -#endif - } - - ~TestEthernetTap() - { -#ifdef ZT_TEST_TAP_REPORT_TO - if (_reportsock >= 0) - close(_reportsock); -#endif - } - - inline void setEnabled(bool en) { _enabled = en; } - inline bool enabled() const { return _enabled; } - - inline bool addIp(const InetAddress &ip) - { - Mutex::Lock _l(_lock); - _ips.insert(ip); - return true; - } - - inline bool removeIp(const InetAddress &ip) - { - Mutex::Lock _l(_lock); - _ips.erase(ip); - return true; - } - - inline std::vector ips() const - { - Mutex::Lock _l(_lock); - return std::vector(_ips.begin(),_ips.end()); - } - - inline void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len) - { -#ifdef ZT_TEST_TAP_REPORT_TO - char tmp[10000]; - if ((_reportsock >= 0)&&(len < (sizeof(tmp) - 22))) { - const uint64_t nwid2 = Utils::hton(_nwid); - memcpy(tmp,&nwid2,8); - from.copyTo(tmp + 8,6); - to.copyTo(tmp + 14,6); - const uint16_t etherType2 = Utils::hton((uint16_t)etherType); - memcpy(tmp + 20,ðerType2,2); - memcpy(tmp + 22,data,len); - sendto(_reportsock,tmp,len + 22,0,reinterpret_cast(&_reportTo),(_reportTo.ss_family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)); - } -#endif - } - - inline std::string deviceName() const - { - return _dev; - } - - inline void setFriendlyName(const char *friendlyName) - { - } - - inline void scanMulticastGroups(std::vector &added,std::vector &removed) - { - } - - inline void setMtu(unsigned int mtu) - { - } - -private: - uint64_t _nwid; - std::string _dev; - std::set _ips; - InetAddress _reportTo; -#ifdef ZT_TEST_TAP_REPORT_TO - int _reportsock; -#endif - bool _enabled; - Mutex _lock; -}; - -} // namespace ZeroTier - -#endif diff --git a/osdep/WindowsEthernetTap.hpp b/osdep/WindowsEthernetTap.hpp index 78a95672..7a863875 100644 --- a/osdep/WindowsEthernetTap.hpp +++ b/osdep/WindowsEthernetTap.hpp @@ -41,10 +41,11 @@ #include "../node/MulticastGroup.hpp" #include "../node/InetAddress.hpp" #include "../osdep/Thread.hpp" +#include "EthernetTap.hpp" namespace ZeroTier { -class WindowsEthernetTap +class WindowsEthernetTap : public EthernetTap { public: /** @@ -97,18 +98,18 @@ public: void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), void *arg); - ~WindowsEthernetTap(); + virtual ~WindowsEthernetTap(); - void setEnabled(bool en); - bool enabled() const; - bool addIp(const InetAddress &ip); - bool removeIp(const InetAddress &ip); - std::vector ips() const; - void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len); - std::string deviceName() const; - void setFriendlyName(const char *friendlyName); - void scanMulticastGroups(std::vector &added,std::vector &removed); - void setMtu(unsigned int mtu); + virtual void setEnabled(bool en); + virtual bool enabled() const; + virtual bool addIp(const InetAddress &ip); + virtual bool removeIp(const InetAddress &ip); + virtual std::vector ips() const; + virtual void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len); + virtual std::string deviceName() const; + virtual void setFriendlyName(const char *friendlyName); + virtual void scanMulticastGroups(std::vector &added,std::vector &removed); + virtual void setMtu(unsigned int mtu); inline const NET_LUID &luid() const { return _deviceLuid; } inline const GUID &guid() const { return _deviceGuid; } @@ -118,7 +119,7 @@ public: void threadMain() throw(); - bool isInitialized() const { return _initialized; }; + bool isInitialized() const { return _initialized; }; private: NET_IFINDEX _getDeviceIndex(); // throws on failure From 237c379866116a24cb9e83c4d03cb121a063323e Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 7 Aug 2019 18:20:17 -0500 Subject: [PATCH 103/185] Choose which tap to use (feth or kext) on Mac based on Darwin version. --- make-mac.mk | 2 +- objects.mk | 1 + service/OneService.cpp | 34 +++++----------------------------- 3 files changed, 7 insertions(+), 30 deletions(-) diff --git a/make-mac.mk b/make-mac.mk index 0735a47f..c71b3f77 100644 --- a/make-mac.mk +++ b/make-mac.mk @@ -19,7 +19,7 @@ ZT_VERSION_BUILD=$(shell cat version.h | grep -F VERSION_BUILD | cut -d ' ' -f 3 DEFS+=-DZT_BUILD_PLATFORM=$(ZT_BUILD_PLATFORM) -DZT_BUILD_ARCHITECTURE=$(ZT_BUILD_ARCHITECTURE) include objects.mk -ONE_OBJS+=osdep/MacEthernetTap.o ext/http-parser/http_parser.o +ONE_OBJS+=osdep/MacEthernetTap.o osdep/MacKextEthernetTap.o ext/http-parser/http_parser.o ifeq ($(ZT_CONTROLLER),1) LIBS+=-lpq -lrabbitmq diff --git a/objects.mk b/objects.mk index e25ed36c..32f62588 100644 --- a/objects.mk +++ b/objects.mk @@ -34,6 +34,7 @@ ONE_OBJS=\ controller/LFDB.o \ controller/PostgreSQL.o \ controller/RabbitMQ.o \ + osdep/EthernetTap.o \ osdep/ManagedRoute.o \ osdep/Http.o \ osdep/OSUtils.o \ diff --git a/service/OneService.cpp b/service/OneService.cpp index 13dca4b0..a434f484 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -118,30 +118,7 @@ namespace ZeroTier { typedef VirtualTap EthernetTap; } #else -#ifdef __APPLE__ -#include "../osdep/MacEthernetTap.hpp" -namespace ZeroTier { typedef MacEthernetTap EthernetTap; } -#endif // __APPLE__ -#ifdef __LINUX__ -#include "../osdep/LinuxEthernetTap.hpp" -namespace ZeroTier { typedef LinuxEthernetTap EthernetTap; } -#endif // __LINUX__ -#ifdef __WINDOWS__ -#include "../osdep/WindowsEthernetTap.hpp" -namespace ZeroTier { typedef WindowsEthernetTap EthernetTap; } -#endif // __WINDOWS__ -#ifdef __FreeBSD__ -#include "../osdep/BSDEthernetTap.hpp" -namespace ZeroTier { typedef BSDEthernetTap EthernetTap; } -#endif // __FreeBSD__ -#ifdef __NetBSD__ -#include "../osdep/NetBSDEthernetTap.hpp" -namespace ZeroTier { typedef NetBSDEthernetTap EthernetTap; } -#endif // __NetBSD__ -#ifdef __OpenBSD__ -#include "../osdep/BSDEthernetTap.hpp" -namespace ZeroTier { typedef BSDEthernetTap EthernetTap; } -#endif // __OpenBSD__ +#include "../osdep/EthernetTap.hpp" #endif // ZT_SDK @@ -543,7 +520,7 @@ public: settings.allowDefault = false; } - EthernetTap *tap; + std::shared_ptr tap; ZT_VirtualNetworkConfig config; // memcpy() of raw config from core std::vector managedIps; std::list< SharedPtr > managedRoutes; @@ -955,8 +932,6 @@ public: { Mutex::Lock _l(_nets_m); - for(std::map::iterator n(_nets.begin());n!=_nets.end();++n) - delete n->second.tap; _nets.clear(); } @@ -2142,7 +2117,8 @@ public: char friendlyName[128]; OSUtils::ztsnprintf(friendlyName,sizeof(friendlyName),"ZeroTier One [%.16llx]",nwid); - n.tap = new EthernetTap( + n.tap = EthernetTap::newInstance( + nullptr, _homePath.c_str(), MAC(nwc->mac), nwc->mtu, @@ -2232,7 +2208,7 @@ public: std::string winInstanceId(n.tap->instanceId()); #endif *nuptr = (void *)0; - delete n.tap; + n.tap.reset(); _nets.erase(nwid); #if defined(__WINDOWS__) && !defined(ZT_SDK) if ((op == ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY)&&(winInstanceId.length() > 0)) From 7436f85ad087732a79cf1b99c5448187401c6da3 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 7 Aug 2019 18:22:03 -0500 Subject: [PATCH 104/185] Require MacOS 10.10 --- ext/installfiles/mac/ZeroTier One.pkgproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/installfiles/mac/ZeroTier One.pkgproj b/ext/installfiles/mac/ZeroTier One.pkgproj index d962e96d..2bd19123 100755 --- a/ext/installfiles/mac/ZeroTier One.pkgproj +++ b/ext/installfiles/mac/ZeroTier One.pkgproj @@ -872,7 +872,7 @@ IC_REQUIREMENT_OS_DISTRIBUTION_TYPE 0 IC_REQUIREMENT_OS_MINIMUM_VERSION - 100900 + 101000 IC_REQUIREMENT_CHECK_TYPE 1 From b11627a8bc37a51455538f45484f3eae1ce195de Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 7 Aug 2019 18:45:04 -0500 Subject: [PATCH 105/185] add SDK VirtualTap to new factory method --- osdep/EthernetTap.cpp | 15 ++++++++++++++- service/OneService.cpp | 22 ---------------------- 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/osdep/EthernetTap.cpp b/osdep/EthernetTap.cpp index a10db55f..21618a58 100644 --- a/osdep/EthernetTap.cpp +++ b/osdep/EthernetTap.cpp @@ -31,7 +31,6 @@ #include #ifdef __APPLE__ -#include #include #include "MacEthernetTap.hpp" #include "MacKextEthernetTap.hpp" @@ -57,6 +56,12 @@ #include "BSDEthernetTap.hpp" #endif // __OpenBSD__ +#ifdef ZT_SDK +#include "../controller/EmbeddedNetworkController.hpp" +#include "../node/Node.hpp" +#include "../include/VirtualTap.hpp" +#endif + namespace ZeroTier { std::shared_ptr EthernetTap::newInstance( @@ -70,6 +75,11 @@ std::shared_ptr EthernetTap::newInstance( void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), void *arg) { + +#ifdef ZT_SDK + return std::shared_ptr(new VirtualTap(homePath,mac,mtu,metric,nwid,friendlyName,handler,arg)); +#else // not ZT_SDK + #ifdef __APPLE__ char osrelease[256]; size_t size = sizeof(osrelease); @@ -77,6 +87,7 @@ std::shared_ptr EthernetTap::newInstance( char *dotAt = strchr(osrelease,'.'); if (dotAt) { *dotAt = (char)0; + printf("%s\n",osrelease); // The "feth" virtual Ethernet device type appeared in Darwin 17.x.x. Older versions // (Sierra and earlier) must use the a kernel extension. if (strtol(osrelease,(char **)0,10) < 17) { @@ -108,6 +119,8 @@ std::shared_ptr EthernetTap::newInstance( return std::shared_ptr(new BSDEthernetTap(homePath,mac,mtu,metric,nwid,friendlyName,handler,arg)); #endif // __OpenBSD__ +#endif // ZT_SDK? + return std::shared_ptr(); } diff --git a/service/OneService.cpp b/service/OneService.cpp index a434f484..b38e8f42 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -100,30 +100,8 @@ using json = nlohmann::json; #include "../controller/EmbeddedNetworkController.hpp" #include "../controller/RabbitMQ.hpp" - -#ifdef ZT_USE_TEST_TAP - -#include "../osdep/TestEthernetTap.hpp" -namespace ZeroTier { typedef TestEthernetTap EthernetTap; } - -#else - -#ifdef ZT_SDK - -#include "../controller/EmbeddedNetworkController.hpp" -#include "../node/Node.hpp" -// Use the virtual netcon endpoint instead of a tun/tap port driver -#include "../include/VirtualTap.hpp" -namespace ZeroTier { typedef VirtualTap EthernetTap; } - -#else - #include "../osdep/EthernetTap.hpp" -#endif // ZT_SDK - -#endif // ZT_USE_TEST_TAP - #ifndef ZT_SOFTWARE_UPDATE_DEFAULT #define ZT_SOFTWARE_UPDATE_DEFAULT "disable" #endif From 4d70640a156cf9568a72a1279d1f8aececbc5694 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 7 Aug 2019 19:06:02 -0500 Subject: [PATCH 106/185] Remove debug line --- osdep/EthernetTap.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/osdep/EthernetTap.cpp b/osdep/EthernetTap.cpp index 21618a58..c3bb4ca1 100644 --- a/osdep/EthernetTap.cpp +++ b/osdep/EthernetTap.cpp @@ -87,7 +87,6 @@ std::shared_ptr EthernetTap::newInstance( char *dotAt = strchr(osrelease,'.'); if (dotAt) { *dotAt = (char)0; - printf("%s\n",osrelease); // The "feth" virtual Ethernet device type appeared in Darwin 17.x.x. Older versions // (Sierra and earlier) must use the a kernel extension. if (strtol(osrelease,(char **)0,10) < 17) { From af7a70bf022a04654eb4c46fa658ef66e9d86a93 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 7 Aug 2019 21:11:48 -0500 Subject: [PATCH 107/185] cleanup --- controller/LFDB.cpp | 49 ++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/controller/LFDB.cpp b/controller/LFDB.cpp index 3672dfa9..3b800ec2 100644 --- a/controller/LFDB.cpp +++ b/controller/LFDB.cpp @@ -53,7 +53,6 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons const uint64_t controllerAddressInt = _myId.address().toInt(); _myId.address().toString(controllerAddress); std::string networksSelectorName("com.zerotier.controller.lfdb:"); networksSelectorName.append(controllerAddress); networksSelectorName.append("/network"); - std::string membersSelectorName("com.zerotier.controller.lfdb:"); membersSelectorName.append(controllerAddress); membersSelectorName.append("/member"); // LF record masking key is the first 32 bytes of SHA512(controller private key) in hex, // hiding record values from anything but the controller or someone who has its key. @@ -156,7 +155,7 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons nlohmann::json newrec,selector0,selector1,selectors; selector0["Name"] = networksSelectorName; selector0["Ordinal"] = ns->first; - selector1["Name"] = membersSelectorName; + selector1["Name"] = "member"; selector1["Ordinal"] = ms->first; selectors.push_back(selector0); selectors.push_back(selector1); @@ -190,16 +189,16 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons try { std::ostringstream query; - query - << '{' - << "\"Ranges\":[{" - << "\"Name\":\"" << networksSelectorName << "\"," - << "\"Range\":[0,18446744073709551615]" - << "}]," - << "\"TimeRange\":[" << timeRangeStart << ",9223372036854775807]," - << "\"MaskingKey\":\"" << maskingKey << "\"," - << "\"Owners\":[\"" << _lfOwnerPublic << "\"]" - << '}'; + query << + "{" + "\"Ranges\":[{" + "\"Name\":\"" << networksSelectorName << "\"," + "\"Range\":[0,18446744073709551615]" + "}]," + "\"TimeRange\":[" << timeRangeStart << ",9223372036854775807]," + "\"MaskingKey\":\"" << maskingKey << "\"," + "\"Owners\":[\"" << _lfOwnerPublic << "\"]" + "}"; auto resp = htcli.Post("/query",query.str(),"application/json"); if (resp) { if (resp->status == 200) { @@ -259,19 +258,19 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons try { std::ostringstream query; - query - << '{' - << "\"Ranges\":[{" - << "\"Name\":\"" << networksSelectorName << "\"," - << "\"Range\":[0,18446744073709551615]" - << "},{" - << "\"Name\":\"" << membersSelectorName << "\"," - << "\"Range\":[0,18446744073709551615]" - << "}]," - << "\"TimeRange\":[" << timeRangeStart << ",9223372036854775807]," - << "\"MaskingKey\":\"" << maskingKey << "\"," - << "\"Owners\":[\"" << _lfOwnerPublic << "\"]" - << '}'; + query << + "{" + "\"Ranges\":[{" + "\"Name\":\"" << networksSelectorName << "\"," + "\"Range\":[0,18446744073709551615]" + "},{" + "\"Name\":\"member\"," + "\"Range\":[0,18446744073709551615]" + "}]," + "\"TimeRange\":[" << timeRangeStart << ",9223372036854775807]," + "\"MaskingKey\":\"" << maskingKey << "\"," + "\"Owners\":[\"" << _lfOwnerPublic << "\"]" + "}"; auto resp = htcli.Post("/query",query.str(),"application/json"); if (resp) { if (resp->status == 200) { From c83a4aef552bfa081e415eb55a05f8c59d5f17d4 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 7 Aug 2019 21:47:06 -0500 Subject: [PATCH 108/185] cleanup --- osdep/EthernetTap.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/osdep/EthernetTap.cpp b/osdep/EthernetTap.cpp index c3bb4ca1..82290fc2 100644 --- a/osdep/EthernetTap.cpp +++ b/osdep/EthernetTap.cpp @@ -30,6 +30,14 @@ #include #include +#ifdef ZT_SDK + +#include "../controller/EmbeddedNetworkController.hpp" +#include "../node/Node.hpp" +#include "../include/VirtualTap.hpp" + +#else + #ifdef __APPLE__ #include #include "MacEthernetTap.hpp" @@ -56,10 +64,6 @@ #include "BSDEthernetTap.hpp" #endif // __OpenBSD__ -#ifdef ZT_SDK -#include "../controller/EmbeddedNetworkController.hpp" -#include "../node/Node.hpp" -#include "../include/VirtualTap.hpp" #endif namespace ZeroTier { @@ -77,7 +81,9 @@ std::shared_ptr EthernetTap::newInstance( { #ifdef ZT_SDK + return std::shared_ptr(new VirtualTap(homePath,mac,mtu,metric,nwid,friendlyName,handler,arg)); + #else // not ZT_SDK #ifdef __APPLE__ From fb3b2820b5515586e58879e04c8f930d08cf6e90 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 8 Aug 2019 09:50:05 -0500 Subject: [PATCH 109/185] centos 7 docs --- make-linux.mk | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/make-linux.mk b/make-linux.mk index db386306..53537de8 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -14,7 +14,6 @@ DEFS?= LDLIBS?= DESTDIR?= - include objects.mk ONE_OBJS+=osdep/LinuxEthernetTap.o ONE_OBJS+=osdep/LinuxNetLink.o @@ -402,4 +401,11 @@ debian-clean: FORCE redhat: FORCE rpmbuild -ba zerotier-one.spec +# This installs the packages needed to build ZT locally on CentOS 7 and +# is here largely for documentation purposes. +centos-7-setup: FORCE + yum install -y gcc gcc-c++ make epel-release git + yum install -y centos-release-scl + yum install -y devtoolset-8-gcc devtoolset-8-gcc-c++ + FORCE: From c8e7031198d1bf61112ec34310cc5a40ae2d4138 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 8 Aug 2019 10:01:57 -0500 Subject: [PATCH 110/185] warning cleanup --- node/C25519.cpp | 361 +++++++----------------------------------------- 1 file changed, 50 insertions(+), 311 deletions(-) diff --git a/node/C25519.cpp b/node/C25519.cpp index 4384f8fd..38cfd614 100644 --- a/node/C25519.cpp +++ b/node/C25519.cpp @@ -739,263 +739,6 @@ static void crypto_scalarmult(u8 *mypublic, const u8 *secret, const u8 *basepoin fcontract(mypublic, z); } -#if 0 -void add(unsigned int out[32],const unsigned int a[32],const unsigned int b[32]) -{ - unsigned int j; - unsigned int u; - u = 0; - for (j = 0;j < 31;++j) { u += a[j] + b[j]; out[j] = u & 255; u >>= 8; } - u += a[31] + b[31]; out[31] = u; -} - -void sub(unsigned int out[32],const unsigned int a[32],const unsigned int b[32]) -{ - unsigned int j; - unsigned int u; - u = 218; - for (j = 0;j < 31;++j) { - u += a[j] + 65280 - b[j]; - out[j] = u & 255; - u >>= 8; - } - u += a[31] - b[31]; - out[31] = u; -} - -void squeeze(unsigned int a[32]) -{ - unsigned int j; - unsigned int u; - u = 0; - for (j = 0;j < 31;++j) { u += a[j]; a[j] = u & 255; u >>= 8; } - u += a[31]; a[31] = u & 127; - u = 19 * (u >> 7); - for (j = 0;j < 31;++j) { u += a[j]; a[j] = u & 255; u >>= 8; } - u += a[31]; a[31] = u; -} - -static const unsigned int minusp[32] = { - 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128 -} ; - -void freeze(unsigned int a[32]) -{ - unsigned int aorig[32]; - unsigned int j; - unsigned int negative; - - for (j = 0;j < 32;++j) aorig[j] = a[j]; - add(a,a,minusp); - negative = -((a[31] >> 7) & 1); - for (j = 0;j < 32;++j) a[j] ^= negative & (aorig[j] ^ a[j]); -} - -void mult(unsigned int out[32],const unsigned int a[32],const unsigned int b[32]) -{ - unsigned int i; - unsigned int j; - unsigned int u; - - for (i = 0;i < 32;++i) { - u = 0; - for (j = 0;j <= i;++j) u += a[j] * b[i - j]; - for (j = i + 1;j < 32;++j) u += 38 * a[j] * b[i + 32 - j]; - out[i] = u; - } - squeeze(out); -} - -void mult121665(unsigned int out[32],const unsigned int a[32]) -{ - unsigned int j; - unsigned int u; - - u = 0; - for (j = 0;j < 31;++j) { u += 121665 * a[j]; out[j] = u & 255; u >>= 8; } - u += 121665 * a[31]; out[31] = u & 127; - u = 19 * (u >> 7); - for (j = 0;j < 31;++j) { u += out[j]; out[j] = u & 255; u >>= 8; } - u += out[j]; out[j] = u; -} - -void square(unsigned int out[32],const unsigned int a[32]) -{ - unsigned int i; - unsigned int j; - unsigned int u; - - for (i = 0;i < 32;++i) { - u = 0; - for (j = 0;j < i - j;++j) u += a[j] * a[i - j]; - for (j = i + 1;j < i + 32 - j;++j) u += 38 * a[j] * a[i + 32 - j]; - u *= 2; - if ((i & 1) == 0) { - u += a[i / 2] * a[i / 2]; - u += 38 * a[i / 2 + 16] * a[i / 2 + 16]; - } - out[i] = u; - } - squeeze(out); -} - -void select(unsigned int p[64],unsigned int q[64],const unsigned int r[64],const unsigned int s[64],unsigned int b) -{ - unsigned int j; - unsigned int t; - unsigned int bminus1; - - bminus1 = b - 1; - for (j = 0;j < 64;++j) { - t = bminus1 & (r[j] ^ s[j]); - p[j] = s[j] ^ t; - q[j] = r[j] ^ t; - } -} - -static void mainloop(unsigned int work[64],const unsigned char e[32]) -{ - unsigned int xzm1[64]; - unsigned int xzm[64]; - unsigned int xzmb[64]; - unsigned int xzm1b[64]; - unsigned int xznb[64]; - unsigned int xzn1b[64]; - unsigned int a0[64]; - unsigned int a1[64]; - unsigned int b0[64]; - unsigned int b1[64]; - unsigned int c1[64]; - unsigned int r[32]; - unsigned int s[32]; - unsigned int t[32]; - unsigned int u[32]; - //unsigned int i; - unsigned int j; - unsigned int b; - int pos; - - for (j = 0;j < 32;++j) xzm1[j] = work[j]; - xzm1[32] = 1; - for (j = 33;j < 64;++j) xzm1[j] = 0; - - xzm[0] = 1; - for (j = 1;j < 64;++j) xzm[j] = 0; - - for (pos = 254;pos >= 0;--pos) { - b = e[pos / 8] >> (pos & 7); - b &= 1; - select(xzmb,xzm1b,xzm,xzm1,b); - add(a0,xzmb,xzmb + 32); - sub(a0 + 32,xzmb,xzmb + 32); - add(a1,xzm1b,xzm1b + 32); - sub(a1 + 32,xzm1b,xzm1b + 32); - square(b0,a0); - square(b0 + 32,a0 + 32); - mult(b1,a1,a0 + 32); - mult(b1 + 32,a1 + 32,a0); - add(c1,b1,b1 + 32); - sub(c1 + 32,b1,b1 + 32); - square(r,c1 + 32); - sub(s,b0,b0 + 32); - mult121665(t,s); - add(u,t,b0); - mult(xznb,b0,b0 + 32); - mult(xznb + 32,s,u); - square(xzn1b,c1); - mult(xzn1b + 32,r,work); - select(xzm,xzm1,xznb,xzn1b,b); - } - - for (j = 0;j < 64;++j) work[j] = xzm[j]; -} - -static void recip(unsigned int out[32],const unsigned int z[32]) -{ - unsigned int z2[32]; - unsigned int z9[32]; - unsigned int z11[32]; - unsigned int z2_5_0[32]; - unsigned int z2_10_0[32]; - unsigned int z2_20_0[32]; - unsigned int z2_50_0[32]; - unsigned int z2_100_0[32]; - unsigned int t0[32]; - unsigned int t1[32]; - int i; - - /* 2 */ square(z2,z); - /* 4 */ square(t1,z2); - /* 8 */ square(t0,t1); - /* 9 */ mult(z9,t0,z); - /* 11 */ mult(z11,z9,z2); - /* 22 */ square(t0,z11); - /* 2^5 - 2^0 = 31 */ mult(z2_5_0,t0,z9); - - /* 2^6 - 2^1 */ square(t0,z2_5_0); - /* 2^7 - 2^2 */ square(t1,t0); - /* 2^8 - 2^3 */ square(t0,t1); - /* 2^9 - 2^4 */ square(t1,t0); - /* 2^10 - 2^5 */ square(t0,t1); - /* 2^10 - 2^0 */ mult(z2_10_0,t0,z2_5_0); - - /* 2^11 - 2^1 */ square(t0,z2_10_0); - /* 2^12 - 2^2 */ square(t1,t0); - /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { square(t0,t1); square(t1,t0); } - /* 2^20 - 2^0 */ mult(z2_20_0,t1,z2_10_0); - - /* 2^21 - 2^1 */ square(t0,z2_20_0); - /* 2^22 - 2^2 */ square(t1,t0); - /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { square(t0,t1); square(t1,t0); } - /* 2^40 - 2^0 */ mult(t0,t1,z2_20_0); - - /* 2^41 - 2^1 */ square(t1,t0); - /* 2^42 - 2^2 */ square(t0,t1); - /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { square(t1,t0); square(t0,t1); } - /* 2^50 - 2^0 */ mult(z2_50_0,t0,z2_10_0); - - /* 2^51 - 2^1 */ square(t0,z2_50_0); - /* 2^52 - 2^2 */ square(t1,t0); - /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { square(t0,t1); square(t1,t0); } - /* 2^100 - 2^0 */ mult(z2_100_0,t1,z2_50_0); - - /* 2^101 - 2^1 */ square(t1,z2_100_0); - /* 2^102 - 2^2 */ square(t0,t1); - /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { square(t1,t0); square(t0,t1); } - /* 2^200 - 2^0 */ mult(t1,t0,z2_100_0); - - /* 2^201 - 2^1 */ square(t0,t1); - /* 2^202 - 2^2 */ square(t1,t0); - /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { square(t0,t1); square(t1,t0); } - /* 2^250 - 2^0 */ mult(t0,t1,z2_50_0); - - /* 2^251 - 2^1 */ square(t1,t0); - /* 2^252 - 2^2 */ square(t0,t1); - /* 2^253 - 2^3 */ square(t1,t0); - /* 2^254 - 2^4 */ square(t0,t1); - /* 2^255 - 2^5 */ square(t1,t0); - /* 2^255 - 21 */ mult(out,t1,z11); -} - -int crypto_scalarmult(unsigned char *q,const unsigned char *n,const unsigned char *p) -{ - unsigned int work[96]; - unsigned char e[32]; - unsigned int i; - for (i = 0;i < 32;++i) e[i] = n[i]; - e[0] &= 248; - e[31] &= 127; - e[31] |= 64; - for (i = 0;i < 32;++i) work[i] = p[i]; - mainloop(work,e); - recip(work + 32,work + 32); - mult(work + 64,work,work + 32); - freeze(work + 64); - for (i = 0;i < 32;++i) q[i] = work[64 + i]; - return 0; -} -#endif - static const unsigned char base[32] = {9}; static inline void crypto_scalarmult_base(unsigned char *q,const unsigned char *n) { @@ -1056,9 +799,9 @@ typedef struct fe25519 y; } ge25519_aff; -static void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y); +static inline void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y); -crypto_uint32 equal(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ +static inline crypto_uint32 equal(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ { crypto_uint32 x = a ^ b; /* 0: yes; 1..65535: no */ x -= 1; /* 4294967295: yes; 0..65534: no */ @@ -1066,7 +809,7 @@ crypto_uint32 equal(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ return x; } -crypto_uint32 ge(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ +static inline crypto_uint32 ge(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ { unsigned int x = a; x -= (unsigned int) b; /* 0..65535: yes; 4294901761..4294967295: no */ @@ -1075,17 +818,17 @@ crypto_uint32 ge(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ return x; } -crypto_uint32 times19(crypto_uint32 a) +static inline crypto_uint32 times19(crypto_uint32 a) { return (a << 4) + (a << 1) + a; } -crypto_uint32 times38(crypto_uint32 a) +static inline crypto_uint32 times38(crypto_uint32 a) { return (a << 5) + (a << 2) + (a << 1); } -void reduce_add_sub(fe25519 *r) +static inline void reduce_add_sub(fe25519 *r) { crypto_uint32 t; int i,rep; @@ -1105,7 +848,7 @@ void reduce_add_sub(fe25519 *r) } } -void reduce_mul(fe25519 *r) +static inline void reduce_mul(fe25519 *r) { crypto_uint32 t; int i,rep; @@ -1126,7 +869,7 @@ void reduce_mul(fe25519 *r) } /* reduction modulo 2^255-19 */ -void fe25519_freeze(fe25519 *r) +static inline void fe25519_freeze(fe25519 *r) { int i; crypto_uint32 m = equal(r->v[31],127); @@ -1142,7 +885,7 @@ void fe25519_freeze(fe25519 *r) r->v[0] -= m&237; } -void fe25519_unpack(fe25519 *r, const unsigned char x[32]) +static inline void fe25519_unpack(fe25519 *r, const unsigned char x[32]) { int i; for(i=0;i<32;i++) r->v[i] = x[i]; @@ -1150,7 +893,7 @@ void fe25519_unpack(fe25519 *r, const unsigned char x[32]) } /* Assumes input x being reduced below 2^255 */ -void fe25519_pack(unsigned char r[32], const fe25519 *x) +static inline void fe25519_pack(unsigned char r[32], const fe25519 *x) { int i; fe25519 y = *x; @@ -1159,7 +902,7 @@ void fe25519_pack(unsigned char r[32], const fe25519 *x) r[i] = y.v[i]; } -int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y) +static inline int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y) { int i; fe25519 t1 = *x; @@ -1171,7 +914,7 @@ int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y) return 1; } -void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b) +static inline void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b) { int i; crypto_uint32 mask = b; @@ -1179,27 +922,27 @@ void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b) for(i=0;i<32;i++) r->v[i] ^= mask & (x->v[i] ^ r->v[i]); } -unsigned char fe25519_getparity(const fe25519 *x) +static inline unsigned char fe25519_getparity(const fe25519 *x) { fe25519 t = *x; fe25519_freeze(&t); return t.v[0] & 1; } -void fe25519_setone(fe25519 *r) +static inline void fe25519_setone(fe25519 *r) { int i; r->v[0] = 1; for(i=1;i<32;i++) r->v[i]=0; } -void fe25519_setzero(fe25519 *r) +static inline void fe25519_setzero(fe25519 *r) { int i; for(i=0;i<32;i++) r->v[i]=0; } -void fe25519_neg(fe25519 *r, const fe25519 *x) +static inline void fe25519_neg(fe25519 *r, const fe25519 *x) { fe25519 t; int i; @@ -1208,14 +951,14 @@ void fe25519_neg(fe25519 *r, const fe25519 *x) fe25519_sub(r, r, &t); } -void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y) +static inline void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y) { int i; for(i=0;i<32;i++) r->v[i] = x->v[i] + y->v[i]; reduce_add_sub(r); } -void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y) +static inline void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y) { int i; crypto_uint32 t[32]; @@ -1226,7 +969,7 @@ void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y) reduce_add_sub(r); } -void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y) +static inline void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y) { int i,j; crypto_uint32 t[63]; @@ -1243,12 +986,12 @@ void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y) reduce_mul(r); } -void fe25519_square(fe25519 *r, const fe25519 *x) +static inline void fe25519_square(fe25519 *r, const fe25519 *x) { fe25519_mul(r, x, x); } -void fe25519_invert(fe25519 *r, const fe25519 *x) +static inline void fe25519_invert(fe25519 *r, const fe25519 *x) { fe25519 z2; fe25519 z9; @@ -1315,7 +1058,7 @@ void fe25519_invert(fe25519 *r, const fe25519 *x) /* 2^255 - 21 */ fe25519_mul(r,&t1,&z11); } -void fe25519_pow2523(fe25519 *r, const fe25519 *x) +static inline void fe25519_pow2523(fe25519 *r, const fe25519 *x) { fe25519 z2; fe25519 z9; @@ -1369,13 +1112,10 @@ void fe25519_pow2523(fe25519 *r, const fe25519 *x) /* 2^252 - 3 */ fe25519_mul(r,&t,x); } -static const crypto_uint32 m[32] = {0xED, 0xD3, 0xF5, 0x5C, 0x1A, 0x63, 0x12, 0x58, 0xD6, 0x9C, 0xF7, 0xA2, 0xDE, 0xF9, 0xDE, 0x14, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; - -static const crypto_uint32 mu[33] = {0x1B, 0x13, 0x2C, 0x0A, 0xA3, 0xE5, 0x9C, 0xED, 0xA7, 0x29, 0x63, 0x08, 0x5D, 0x21, 0x06, 0x21, - 0xEB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F}; +static const crypto_uint32 m[32] = {0xED, 0xD3, 0xF5, 0x5C, 0x1A, 0x63, 0x12, 0x58, 0xD6, 0x9C, 0xF7, 0xA2, 0xDE, 0xF9, 0xDE, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; +static const crypto_uint32 mu[33] = {0x1B, 0x13, 0x2C, 0x0A, 0xA3, 0xE5, 0x9C, 0xED, 0xA7, 0x29, 0x63, 0x08, 0x5D, 0x21, 0x06, 0x21, 0xEB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F}; -crypto_uint32 lt(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ +static inline crypto_uint32 lt(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ { unsigned int x = a; x -= (unsigned int) b; /* 0..65535: no; 4294901761..4294967295: yes */ @@ -1384,7 +1124,7 @@ crypto_uint32 lt(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ } /* Reduce coefficients of r before calling reduce_add_sub */ -void reduce_add_sub(sc25519 *r) +static inline void reduce_add_sub(sc25519 *r) { crypto_uint32 pb = 0; crypto_uint32 b; @@ -1405,7 +1145,7 @@ void reduce_add_sub(sc25519 *r) } /* Reduce coefficients of x before calling barrett_reduce */ -void barrett_reduce(sc25519 *r, const crypto_uint32 x[64]) +static inline void barrett_reduce(sc25519 *r, const crypto_uint32 x[64]) { /* See HAC, Alg. 14.42 */ int i,j; @@ -1456,7 +1196,7 @@ void barrett_reduce(sc25519 *r, const crypto_uint32 x[64]) reduce_add_sub(r); } -void sc25519_from32bytes(sc25519 *r, const unsigned char x[32]) +static inline void sc25519_from32bytes(sc25519 *r, const unsigned char x[32]) { int i; crypto_uint32 t[64]; @@ -1465,7 +1205,7 @@ void sc25519_from32bytes(sc25519 *r, const unsigned char x[32]) barrett_reduce(r, t); } -void sc25519_from64bytes(sc25519 *r, const unsigned char x[64]) +static inline void sc25519_from64bytes(sc25519 *r, const unsigned char x[64]) { int i; crypto_uint32 t[64]; @@ -1473,13 +1213,13 @@ void sc25519_from64bytes(sc25519 *r, const unsigned char x[64]) barrett_reduce(r, t); } -void sc25519_to32bytes(unsigned char r[32], const sc25519 *x) +static inline void sc25519_to32bytes(unsigned char r[32], const sc25519 *x) { int i; for(i=0;i<32;i++) r[i] = x->v[i]; } -void sc25519_add(sc25519 *r, const sc25519 *x, const sc25519 *y) +static inline void sc25519_add(sc25519 *r, const sc25519 *x, const sc25519 *y) { int i, carry; for(i=0;i<32;i++) r->v[i] = x->v[i] + y->v[i]; @@ -1492,7 +1232,7 @@ void sc25519_add(sc25519 *r, const sc25519 *x, const sc25519 *y) reduce_add_sub(r); } -void sc25519_mul(sc25519 *r, const sc25519 *x, const sc25519 *y) +static inline void sc25519_mul(sc25519 *r, const sc25519 *x, const sc25519 *y) { int i,j,carry; crypto_uint32 t[64]; @@ -1512,7 +1252,7 @@ void sc25519_mul(sc25519 *r, const sc25519 *x, const sc25519 *y) barrett_reduce(r, t); } -void sc25519_window3(signed char r[85], const sc25519 *s) +static inline void sc25519_window3(signed char r[85], const sc25519 *s) { char carry; int i; @@ -1549,7 +1289,7 @@ void sc25519_window3(signed char r[85], const sc25519 *s) r[84] += carry; } -void sc25519_2interleave2(unsigned char r[127], const sc25519 *s1, const sc25519 *s2) +static inline void sc25519_2interleave2(unsigned char r[127], const sc25519 *s1, const sc25519 *s2) { int i; for(i=0;i<31;i++) @@ -2438,27 +2178,27 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x69, 0x3e, 0x47, 0x97, 0x2c, 0xaf, 0x52, 0x7c, 0x78, 0x83, 0xad, 0x1b, 0x39, 0x82, 0x2f, 0x02, 0x6f, 0x47, 0xdb, 0x2a, 0xb0, 0xe1, 0x91, 0x99, 0x55, 0xb8, 0x99, 0x3a, 0xa0, 0x44, 0x11, 0x51}}} }; -void p1p1_to_p2(ge25519_p2 *r, const ge25519_p1p1 *p) +static inline void p1p1_to_p2(ge25519_p2 *r, const ge25519_p1p1 *p) { fe25519_mul(&r->x, &p->x, &p->t); fe25519_mul(&r->y, &p->y, &p->z); fe25519_mul(&r->z, &p->z, &p->t); } -void p1p1_to_p2_2(ge25519_p3 *r, const ge25519_p1p1 *p) +static inline void p1p1_to_p2_2(ge25519_p3 *r, const ge25519_p1p1 *p) { fe25519_mul(&r->x, &p->x, &p->t); fe25519_mul(&r->y, &p->y, &p->z); fe25519_mul(&r->z, &p->z, &p->t); } -void p1p1_to_p3(ge25519_p3 *r, const ge25519_p1p1 *p) +static inline void p1p1_to_p3(ge25519_p3 *r, const ge25519_p1p1 *p) { p1p1_to_p2_2(r, p); fe25519_mul(&r->t, &p->x, &p->y); } -void ge25519_mixadd2(ge25519_p3 *r, const ge25519_aff *q) +static inline void ge25519_mixadd2(ge25519_p3 *r, const ge25519_aff *q) { fe25519 a,b,t1,t2,c,d,e,f,g,h,qt; fe25519_mul(&qt, &q->x, &q->y); @@ -2481,7 +2221,7 @@ void ge25519_mixadd2(ge25519_p3 *r, const ge25519_aff *q) fe25519_mul(&r->t, &e, &h); } -void add_p1p1(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_p3 *q) +static inline void add_p1p1(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_p3 *q) { fe25519 a, b, c, d, t; @@ -2502,7 +2242,7 @@ void add_p1p1(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_p3 *q) } /* See http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-dbl-2008-hwcd */ -void dbl_p1p1(ge25519_p1p1 *r, const ge25519_p2 *p) +static inline void dbl_p1p1(ge25519_p1p1 *r, const ge25519_p2 *p) { fe25519 a,b,c,d; fe25519_square(&a, &p->x); @@ -2521,13 +2261,13 @@ void dbl_p1p1(ge25519_p1p1 *r, const ge25519_p2 *p) } /* Constant-time version of: if(b) r = p */ -void cmov_aff(ge25519_aff *r, const ge25519_aff *p, unsigned char b) +static inline void cmov_aff(ge25519_aff *r, const ge25519_aff *p, unsigned char b) { fe25519_cmov(&r->x, &p->x, b); fe25519_cmov(&r->y, &p->y, b); } -unsigned char equal(signed char b,signed char c) +static inline unsigned char equal(signed char b,signed char c) { unsigned char ub = b; unsigned char uc = c; @@ -2538,14 +2278,14 @@ unsigned char equal(signed char b,signed char c) return (unsigned char)y; } -unsigned char negative(signed char b) +static inline unsigned char negative(signed char b) { unsigned long long x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */ x >>= 63; /* 1: yes; 0: no */ return (unsigned char)x; } -void choose_t(ge25519_aff *t, unsigned long long pos, signed char b) +static inline void choose_t(ge25519_aff *t, unsigned long long pos, signed char b) { /* constant time */ fe25519 v; @@ -2558,7 +2298,7 @@ void choose_t(ge25519_aff *t, unsigned long long pos, signed char b) fe25519_cmov(&t->x, &v, negative(b)); } -void setneutral(ge25519 *r) +static inline void setneutral(ge25519 *r) { fe25519_setzero(&r->x); fe25519_setone(&r->y); @@ -2567,7 +2307,7 @@ void setneutral(ge25519 *r) } /* return 0 on success, -1 otherwise */ -int ge25519_unpackneg_vartime(ge25519_p3 *r, const unsigned char p[32]) +static inline int ge25519_unpackneg_vartime(ge25519_p3 *r, const unsigned char p[32]) { unsigned char par; fe25519 t, chk, num, den, den2, den4, den6; @@ -2614,7 +2354,7 @@ int ge25519_unpackneg_vartime(ge25519_p3 *r, const unsigned char p[32]) return 0; } -void ge25519_pack(unsigned char r[32], const ge25519_p3 *p) +static inline void ge25519_pack(unsigned char r[32], const ge25519_p3 *p) { fe25519 tx, ty, zi; fe25519_invert(&zi, &p->z); @@ -2625,7 +2365,7 @@ void ge25519_pack(unsigned char r[32], const ge25519_p3 *p) } /* computes [s1]p1 + [s2]p2 */ -void ge25519_double_scalarmult_vartime(ge25519_p3 *r, const ge25519_p3 *p1, const sc25519 *s1, const ge25519_p3 *p2, const sc25519 *s2) +static inline void ge25519_double_scalarmult_vartime(ge25519_p3 *r, const ge25519_p3 *p1, const sc25519 *s1, const ge25519_p3 *p2, const sc25519 *s2) { ge25519_p1p1 tp1p1; ge25519_p3 pre[16]; @@ -2670,7 +2410,7 @@ void ge25519_double_scalarmult_vartime(ge25519_p3 *r, const ge25519_p3 *p1, cons } } -void ge25519_scalarmult_base(ge25519_p3 *r, const sc25519 *s) +static inline void ge25519_scalarmult_base(ge25519_p3 *r, const sc25519 *s) { signed char b[85]; int i; @@ -2687,7 +2427,7 @@ void ge25519_scalarmult_base(ge25519_p3 *r, const sc25519 *s) } } -void get_hram(unsigned char *hram, const unsigned char *sm, const unsigned char *pk, unsigned char *playground, unsigned long long smlen) +static inline void get_hram(unsigned char *hram, const unsigned char *sm, const unsigned char *pk, unsigned char *playground, unsigned long long smlen) { unsigned long long i; @@ -2695,7 +2435,6 @@ void get_hram(unsigned char *hram, const unsigned char *sm, const unsigned char for (i = 32;i < 64;++i) playground[i] = pk[i-32]; for (i = 64;i < smlen;++i) playground[i] = sm[i]; - //crypto_hash_sha512(hram,playground,smlen); ZeroTier::SHA512::hash(hram,playground,(unsigned int)smlen); } From 6c44fcc290ae6a4c636d3c4694e908cb17dd3cfc Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 8 Aug 2019 10:28:57 -0500 Subject: [PATCH 111/185] more warning cleanup --- node/C25519.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/node/C25519.cpp b/node/C25519.cpp index 38cfd614..d7c7011f 100644 --- a/node/C25519.cpp +++ b/node/C25519.cpp @@ -22,6 +22,10 @@ Derived from public domain code by D. J. Bernstein. #pragma warning(disable: 4146) #endif +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wunused-function" +#endif + namespace { #define crypto_int32 int32_t From 7bb0d9be1b2606a77c9f4e5f5c599ca5c7ff2fb6 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 8 Aug 2019 11:04:11 -0500 Subject: [PATCH 112/185] warning removal --- controller/PostgreSQL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/PostgreSQL.cpp b/controller/PostgreSQL.cpp index 8a34ec1d..a43e2118 100644 --- a/controller/PostgreSQL.cpp +++ b/controller/PostgreSQL.cpp @@ -583,7 +583,7 @@ void PostgreSQL::heartbeat() if (gethostname(hostnameTmp, sizeof(hostnameTmp))!= 0) { hostnameTmp[0] = (char)0; } else { - for (int i = 0; i < sizeof(hostnameTmp); ++i) { + for (int i = 0; i < (int)sizeof(hostnameTmp); ++i) { if ((hostnameTmp[i] == '.')||(hostnameTmp[i] == 0)) { hostnameTmp[i] = (char)0; break; From 8b97755fc51cd57ca7e5a214a86bde8c03aba70b Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 8 Aug 2019 14:08:35 -0500 Subject: [PATCH 113/185] Windows fixes. --- service/OneService.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/service/OneService.cpp b/service/OneService.cpp index b38e8f42..93e97bde 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -101,6 +101,9 @@ using json = nlohmann::json; #include "../controller/EmbeddedNetworkController.hpp" #include "../controller/RabbitMQ.hpp" #include "../osdep/EthernetTap.hpp" +#ifdef __WINDOWS__ +#include "../osdep/WindowsEthernetTap.hpp" +#endif #ifndef ZT_SOFTWARE_UPDATE_DEFAULT #define ZT_SOFTWARE_UPDATE_DEFAULT "disable" @@ -1741,7 +1744,7 @@ public: if (syncRoutes) { char tapdev[64]; #if defined(__WINDOWS__) && !defined(ZT_SDK) - OSUtils::ztsnprintf(tapdev,sizeof(tapdev),"%.16llx",(unsigned long long)n.tap->luid().Value); + OSUtils::ztsnprintf(tapdev,sizeof(tapdev),"%.16llx",(unsigned long long)((WindowsEthernetTap *)(n.tap.get()))->luid().Value); #else Utils::scopy(tapdev,sizeof(tapdev),n.tap->deviceName().c_str()); #endif @@ -2167,7 +2170,7 @@ public: // without WindowsEthernetTap::isInitialized() returning true, the won't actually // be online yet and setting managed routes on it will fail. const int MAX_SLEEP_COUNT = 500; - for (int i = 0; !n.tap->isInitialized() && i < MAX_SLEEP_COUNT; i++) { + for (int i = 0; !((WindowsEthernetTap *)(n.tap.get()))->isInitialized() && i < MAX_SLEEP_COUNT; i++) { Sleep(10); } #endif @@ -2183,7 +2186,7 @@ public: case ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY: if (n.tap) { // sanity check #if defined(__WINDOWS__) && !defined(ZT_SDK) - std::string winInstanceId(n.tap->instanceId()); + std::string winInstanceId(((WindowsEthernetTap *)(n.tap.get()))->instanceId()); #endif *nuptr = (void *)0; n.tap.reset(); From ad2a7c2590467270486c15144330f2c3e87ec080 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 8 Aug 2019 15:15:12 -0500 Subject: [PATCH 114/185] More windows build fixes --- windows/ZeroTierOne/ZeroTierOne.vcxproj | 4 ++++ windows/ZeroTierOne/ZeroTierOne.vcxproj.filters | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj b/windows/ZeroTierOne/ZeroTierOne.vcxproj index 2346dabc..2bcc8603 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj @@ -28,6 +28,7 @@ + @@ -94,6 +95,7 @@ false false + @@ -115,6 +117,7 @@ + @@ -182,6 +185,7 @@ + diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters b/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters index f761d920..78e088c7 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters @@ -270,6 +270,12 @@ Source Files\controller + + Source Files\controller + + + Source Files\osdep + @@ -518,6 +524,12 @@ Header Files\ext\cpp-httplib + + Header Files\controller + + + Header Files\osdep + From 28d0070ce2e791727c388646f22119e350ab6d78 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 8 Aug 2019 15:29:13 -0500 Subject: [PATCH 115/185] Fix race in multiple DB mirroring configurations. --- controller/DB.hpp | 22 ++++++++++++++++++++++ controller/DBMirrorSet.cpp | 4 ++-- controller/FileDB.cpp | 4 ++-- controller/LFDB.cpp | 4 ++-- controller/PostgreSQL.cpp | 16 ++-------------- 5 files changed, 30 insertions(+), 20 deletions(-) diff --git a/controller/DB.hpp b/controller/DB.hpp index efb08d63..aebe4e11 100644 --- a/controller/DB.hpp +++ b/controller/DB.hpp @@ -114,6 +114,28 @@ public: } protected: + inline bool _compareRecords(const nlohmann::json &a,const nlohmann::json &b) + { + if (a.is_object() == b.is_object()) { + if (a.is_object()) { + if (a.size() != b.size()) + return false; + auto amap = a.get(); + auto bmap = b.get(); + for(auto ai=amap.begin();ai!=amap.end();++ai) { + if (ai->first != "revision") { // ignore revision, compare only non-revision-counter fields + auto bi = bmap.find(ai->first); + if ((bi == bmap.end())||(bi->second != ai->second)) + return false; + } + } + return true; + } + return (a == b); + } + return false; + } + struct _Network { _Network() : mostRecentDeauthTime(0) {} diff --git a/controller/DBMirrorSet.cpp b/controller/DBMirrorSet.cpp index 5d9ea050..5b491216 100644 --- a/controller/DBMirrorSet.cpp +++ b/controller/DBMirrorSet.cpp @@ -125,14 +125,14 @@ bool DBMirrorSet::save(nlohmann::json &record,bool notifyListeners) } if (notifyListeners) { for(auto d=dbs.begin();d!=dbs.end();++d) { - if ((*d)->save(record,notifyListeners)) + if ((*d)->save(record,true)) return true; } return false; } else { bool modified = false; for(auto d=dbs.begin();d!=dbs.end();++d) { - modified |= (*d)->save(record,notifyListeners); + modified |= (*d)->save(record,false); } return modified; } diff --git a/controller/FileDB.cpp b/controller/FileDB.cpp index 1dc2498a..cf5847d6 100644 --- a/controller/FileDB.cpp +++ b/controller/FileDB.cpp @@ -98,7 +98,7 @@ bool FileDB::save(nlohmann::json &record,bool notifyListeners) if (nwid) { nlohmann::json old; get(nwid,old); - if ((!old.is_object())||(old != record)) { + if ((!old.is_object())||(!_compareRecords(old,record))) { record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL; OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%.16llx.json",_networksPath.c_str(),nwid); if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) @@ -115,7 +115,7 @@ bool FileDB::save(nlohmann::json &record,bool notifyListeners) if ((id)&&(nwid)) { nlohmann::json network,old; get(nwid,network,id,old); - if ((!old.is_object())||(old != record)) { + if ((!old.is_object())||(!_compareRecords(old,record))) { record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL; OSUtils::ztsnprintf(pb,sizeof(pb),"%s" ZT_PATH_SEPARATOR_S "%.16llx" ZT_PATH_SEPARATOR_S "member",_networksPath.c_str(),(unsigned long long)nwid); OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%.10llx.json",pb,(unsigned long long)id); diff --git a/controller/LFDB.cpp b/controller/LFDB.cpp index 3b800ec2..35068321 100644 --- a/controller/LFDB.cpp +++ b/controller/LFDB.cpp @@ -369,7 +369,7 @@ bool LFDB::save(nlohmann::json &record,bool notifyListeners) if (nwid) { nlohmann::json old; get(nwid,old); - if ((!old.is_object())||(old != record)) { + if ((!old.is_object())||(!_compareRecords(old,record))) { record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL; _networkChanged(old,record,notifyListeners); { @@ -385,7 +385,7 @@ bool LFDB::save(nlohmann::json &record,bool notifyListeners) if ((id)&&(nwid)) { nlohmann::json network,old; get(nwid,network,id,old); - if ((!old.is_object())||(old != record)) { + if ((!old.is_object())||(!_compareRecords(old,record))) { record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL; _memberChanged(old,record,notifyListeners); { diff --git a/controller/PostgreSQL.cpp b/controller/PostgreSQL.cpp index a43e2118..66b49394 100644 --- a/controller/PostgreSQL.cpp +++ b/controller/PostgreSQL.cpp @@ -183,7 +183,7 @@ bool PostgreSQL::save(nlohmann::json &record,bool notifyListeners) if (nwid) { nlohmann::json old; get(nwid,old); - if ((!old.is_object())||(old != record)) { + if ((!old.is_object())||(!_compareRecords(old,record))) { record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL; _commitQueue.post(std::pair(record,notifyListeners)); modified = true; @@ -195,25 +195,13 @@ bool PostgreSQL::save(nlohmann::json &record,bool notifyListeners) if ((id)&&(nwid)) { nlohmann::json network,old; get(nwid,network,id,old); - if ((!old.is_object())||(old != record)) { + if ((!old.is_object())||(!_compareRecords(old,record))) { record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL; _commitQueue.post(std::pair(record,notifyListeners)); modified = true; } } } - /* - waitForReady(); - if (orig) { - if (*orig != record) { - record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1; - _commitQueue.post(new nlohmann::json(record)); - } - } else { - record["revision"] = 1; - _commitQueue.post(new nlohmann::json(record)); - } - */ } catch (std::exception &e) { fprintf(stderr, "Error on PostgreSQL::save: %s\n", e.what()); } catch (...) { From 760ae07d7243b8e7ff6ec03cf508058c287c219f Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 8 Aug 2019 16:30:52 -0500 Subject: [PATCH 116/185] Sync bug fix --- controller/LFDB.cpp | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/controller/LFDB.cpp b/controller/LFDB.cpp index 35068321..d00d8631 100644 --- a/controller/LFDB.cpp +++ b/controller/LFDB.cpp @@ -220,20 +220,16 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons const uint64_t id = Utils::hexStrToU64(idstr.c_str()); if ((id >> 24) == controllerAddressInt) { // sanity check - std::lock_guard sl(_state_l); - _NetworkState &ns = _state[id]; - if (!ns.dirty) { - nlohmann::json oldNetwork; - if ((timeRangeStart > 0)&&(get(id,oldNetwork))) { - const uint64_t revision = network["revision"]; - const uint64_t prevRevision = oldNetwork["revision"]; - if (prevRevision < revision) { - _networkChanged(oldNetwork,network,timeRangeStart > 0); - } - } else { - nlohmann::json nullJson; - _networkChanged(nullJson,network,timeRangeStart > 0); + nlohmann::json oldNetwork; + if ((timeRangeStart > 0)&&(get(id,oldNetwork))) { + const uint64_t revision = network["revision"]; + const uint64_t prevRevision = oldNetwork["revision"]; + if (prevRevision < revision) { + _networkChanged(oldNetwork,network,timeRangeStart > 0); } + } else { + nlohmann::json nullJson; + _networkChanged(nullJson,network,timeRangeStart > 0); } } @@ -294,17 +290,13 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons const uint64_t id = Utils::hexStrToU64(idstr.c_str()); if ((id)&&((nwid >> 24) == controllerAddressInt)) { // sanity check - std::lock_guard sl(_state_l); - auto ns = _state.find(nwid); - if ((ns == _state.end())||(!ns->second.members[id].dirty)) { - nlohmann::json network,oldMember; - if ((timeRangeStart > 0)&&(get(nwid,network,id,oldMember))) { - const uint64_t revision = member["revision"]; - const uint64_t prevRevision = oldMember["revision"]; - if (prevRevision < revision) - _memberChanged(oldMember,member,timeRangeStart > 0); - } - } else { + nlohmann::json network,oldMember; + if ((timeRangeStart > 0)&&(get(nwid,network,id,oldMember))) { + const uint64_t revision = member["revision"]; + const uint64_t prevRevision = oldMember["revision"]; + if (prevRevision < revision) + _memberChanged(oldMember,member,timeRangeStart > 0); + } else if (network.is_object()) { nlohmann::json nullJson; _memberChanged(nullJson,member,timeRangeStart > 0); } From 55087521f6db9aaa874cccd86e424d77e6c820c3 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 8 Aug 2019 17:20:50 -0500 Subject: [PATCH 117/185] Add periodic sync check when syncing LF<>another DB --- controller/DB.hpp | 15 +++++++++++- controller/DBMirrorSet.cpp | 48 ++++++++++++++++++++++++++++++++++++-- controller/DBMirrorSet.hpp | 3 +++ controller/LFDB.cpp | 2 +- 4 files changed, 64 insertions(+), 4 deletions(-) diff --git a/controller/DB.hpp b/controller/DB.hpp index aebe4e11..6c518426 100644 --- a/controller/DB.hpp +++ b/controller/DB.hpp @@ -100,6 +100,19 @@ public: void networks(std::set &networks); + template + inline void each(F f) + { + nlohmann::json nullJson; + std::lock_guard lck(_networks_l); + for(auto nw=_networks.begin();nw!=_networks.end();++nw) { + f(nw->first,nw->second->config,0,nullJson); // first provide network with 0 for member ID + for(auto m=nw->second->members.begin();m!=nw->second->members.end();++m) { + f(nw->first,nw->second->config,m->first,m->second); + } + } + } + virtual bool save(nlohmann::json &record,bool notifyListeners) = 0; virtual void eraseNetwork(const uint64_t networkId) = 0; @@ -114,7 +127,7 @@ public: } protected: - inline bool _compareRecords(const nlohmann::json &a,const nlohmann::json &b) + static inline bool _compareRecords(const nlohmann::json &a,const nlohmann::json &b) { if (a.is_object() == b.is_object()) { if (a.is_object()) { diff --git a/controller/DBMirrorSet.cpp b/controller/DBMirrorSet.cpp index 5b491216..852e70f3 100644 --- a/controller/DBMirrorSet.cpp +++ b/controller/DBMirrorSet.cpp @@ -29,8 +29,52 @@ namespace ZeroTier { DBMirrorSet::DBMirrorSet(DB::ChangeListener *listener) : - _listener(listener) -{ + _listener(listener), + _running(true) +{ + _syncCheckerThread = std::thread([this]() { + for(;;) { + for(int i=0;i<120;++i) { // 1 minute delay between checks + if (!_running) + return; + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + } + + std::vector< std::shared_ptr > dbs; + { + std::lock_guard l(_dbs_l); + if (_dbs.size() <= 1) + continue; // no need to do this if there's only one DB, so skip the iteration + dbs = _dbs; + } + + for(auto db=dbs.begin();db!=dbs.end();++db) { + (*db)->each([this,&dbs,&db](uint64_t networkId,const nlohmann::json &network,uint64_t memberId,const nlohmann::json &member) { + if (memberId == 0) { + for(auto db2=dbs.begin();db2!=dbs.end();++db2) { + if (db->get() != db2->get()) { + nlohmann::json nw2; + if ((!(*db2)->get(networkId,nw2))||(OSUtils::jsonInt(nw2["revision"],0) < OSUtils::jsonInt(network["revision"],0))) { + nw2 = network; + (*db2)->save(nw2,false); + } + } + } + } else { + for(auto db2=dbs.begin();db2!=dbs.end();++db2) { + if (db->get() != db2->get()) { + nlohmann::json nw2,m2; + if ((!(*db2)->get(networkId,nw2,memberId,m2))||(OSUtils::jsonInt(nw2["revision"],0) < OSUtils::jsonInt(network["revision"],0))) { + m2 = member; + (*db2)->save(m2,false); + } + } + } + } + }); + } + } + }); } DBMirrorSet::~DBMirrorSet() diff --git a/controller/DBMirrorSet.hpp b/controller/DBMirrorSet.hpp index aee598af..23cb25e7 100644 --- a/controller/DBMirrorSet.hpp +++ b/controller/DBMirrorSet.hpp @@ -33,6 +33,7 @@ #include #include #include +#include namespace ZeroTier { @@ -72,6 +73,8 @@ public: private: DB::ChangeListener *const _listener; + std::atomic_bool _running; + std::thread _syncCheckerThread; std::vector< std::shared_ptr< DB > > _dbs; mutable std::mutex _dbs_l; }; diff --git a/controller/LFDB.cpp b/controller/LFDB.cpp index d00d8631..b6dc6657 100644 --- a/controller/LFDB.cpp +++ b/controller/LFDB.cpp @@ -296,7 +296,7 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons const uint64_t prevRevision = oldMember["revision"]; if (prevRevision < revision) _memberChanged(oldMember,member,timeRangeStart > 0); - } else if (network.is_object()) { + } else if (hasNetwork(nwid)) { nlohmann::json nullJson; _memberChanged(nullJson,member,timeRangeStart > 0); } From f8f2432ece59fbc0913d011423ecc1e369924bcd Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 8 Aug 2019 17:22:20 -0500 Subject: [PATCH 118/185] Shutdown fix --- controller/DBMirrorSet.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/controller/DBMirrorSet.cpp b/controller/DBMirrorSet.cpp index 852e70f3..c1be6b9c 100644 --- a/controller/DBMirrorSet.cpp +++ b/controller/DBMirrorSet.cpp @@ -79,6 +79,8 @@ DBMirrorSet::DBMirrorSet(DB::ChangeListener *listener) : DBMirrorSet::~DBMirrorSet() { + _running = false; + _syncCheckerThread.join(); } bool DBMirrorSet::hasNetwork(const uint64_t networkId) const From 730305ecc7961752d10dae2bcb195e4de1c45464 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 8 Aug 2019 17:31:32 -0500 Subject: [PATCH 119/185] One more sync fix. --- controller/DBMirrorSet.cpp | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/controller/DBMirrorSet.cpp b/controller/DBMirrorSet.cpp index c1be6b9c..c3cd7841 100644 --- a/controller/DBMirrorSet.cpp +++ b/controller/DBMirrorSet.cpp @@ -50,27 +50,31 @@ DBMirrorSet::DBMirrorSet(DB::ChangeListener *listener) : for(auto db=dbs.begin();db!=dbs.end();++db) { (*db)->each([this,&dbs,&db](uint64_t networkId,const nlohmann::json &network,uint64_t memberId,const nlohmann::json &member) { - if (memberId == 0) { - for(auto db2=dbs.begin();db2!=dbs.end();++db2) { - if (db->get() != db2->get()) { - nlohmann::json nw2; - if ((!(*db2)->get(networkId,nw2))||(OSUtils::jsonInt(nw2["revision"],0) < OSUtils::jsonInt(network["revision"],0))) { - nw2 = network; - (*db2)->save(nw2,false); + try { + if (network.is_object()) { + if (memberId == 0) { + for(auto db2=dbs.begin();db2!=dbs.end();++db2) { + if (db->get() != db2->get()) { + nlohmann::json nw2; + if ((!(*db2)->get(networkId,nw2))||((nw2.is_object())&&(OSUtils::jsonInt(nw2["revision"],0) < OSUtils::jsonInt(network["revision"],0)))) { + nw2 = network; + (*db2)->save(nw2,false); + } + } } - } - } - } else { - for(auto db2=dbs.begin();db2!=dbs.end();++db2) { - if (db->get() != db2->get()) { - nlohmann::json nw2,m2; - if ((!(*db2)->get(networkId,nw2,memberId,m2))||(OSUtils::jsonInt(nw2["revision"],0) < OSUtils::jsonInt(network["revision"],0))) { - m2 = member; - (*db2)->save(m2,false); + } else if (member.is_object()) { + for(auto db2=dbs.begin();db2!=dbs.end();++db2) { + if (db->get() != db2->get()) { + nlohmann::json nw2,m2; + if ((!(*db2)->get(networkId,nw2,memberId,m2))||((m2.is_object())&&(OSUtils::jsonInt(m2["revision"],0) < OSUtils::jsonInt(member["revision"],0)))) { + m2 = member; + (*db2)->save(m2,false); + } + } } } } - } + } catch ( ... ) {} // skip entries that generate JSON errors }); } } From 6a9a577c599875b821afa285ae3a964dd78d3301 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 8 Aug 2019 17:56:27 -0500 Subject: [PATCH 120/185] rulesSource needs to be required in network or pgsql has issues --- controller/DB.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/controller/DB.cpp b/controller/DB.cpp index a4440f38..0c6274b9 100644 --- a/controller/DB.cpp +++ b/controller/DB.cpp @@ -52,6 +52,7 @@ void DB::initNetwork(nlohmann::json &network) if (!network.count("mtu")) network["mtu"] = ZT_DEFAULT_MTU; if (!network.count("remoteTraceTarget")) network["remoteTraceTarget"] = nlohmann::json(); if (!network.count("removeTraceLevel")) network["remoteTraceLevel"] = 0; + if (!network.count("rulesSource")) network["rulesSource"] = ""; if (!network.count("rules")) { // If unspecified, rules are set to allow anything and behave like a flat L2 segment network["rules"] = {{ From 72ccd1020a47970e622912b2f30b8a0dbb03bb55 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 8 Aug 2019 18:11:06 -0500 Subject: [PATCH 121/185] Another exception fix --- controller/PostgreSQL.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/controller/PostgreSQL.cpp b/controller/PostgreSQL.cpp index 66b49394..cd913f87 100644 --- a/controller/PostgreSQL.cpp +++ b/controller/PostgreSQL.cpp @@ -1047,7 +1047,10 @@ void PostgreSQL::commitThread() if (!(*config)["remoteTraceTarget"].is_null()) { remoteTraceTarget = (*config)["remoteTraceTarget"]; } - std::string rulesSource = (*config)["rulesSource"]; + std::string rulesSource; + if ((*config)["rulesSource"].is_string()) { + rulesSource = (*config)["rulesSource"]; + } std::string caps = OSUtils::jsonDump((*config)["capabilitles"], -1); std::string now = std::to_string(OSUtils::now()); std::string mtu = std::to_string((int)(*config)["mtu"]); From d4dc983a01973d4148c5f4344d86b9534fd61432 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 8 Aug 2019 18:31:41 -0500 Subject: [PATCH 122/185] fix bad column name --- controller/PostgreSQL.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/controller/PostgreSQL.cpp b/controller/PostgreSQL.cpp index cd913f87..07bb5825 100644 --- a/controller/PostgreSQL.cpp +++ b/controller/PostgreSQL.cpp @@ -1084,13 +1084,13 @@ void PostgreSQL::commitThread() PGresult *res = PQexecParams(conn, "INSERT INTO ztc_network (id, controller_id, capabilities, enable_broadcast, " - "last_updated, mtu, multicast_limit, name, private, " + "last_modified, mtu, multicast_limit, name, private, " "remote_trace_level, remote_trace_target, rules, rules_source, " "tags, v4_assign_mode, v6_assign_mode) VALUES (" "$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16) " "ON CONFLICT (id) DO UPDATE set controller_id = EXCLUDED.controller_id, " "capabilities = EXCLUDED.capabilities, enable_broadcast = EXCLUDED.enable_broadcast, " - "last_updated = EXCLUDED.last_updated, mtu = EXCLUDED.mtu, " + "last_modified = EXCLUDED.last_modified, mtu = EXCLUDED.mtu, " "multicast_limit = EXCLUDED.multicast_limit, name = EXCLUDED.name, " "private = EXCLUDED.private, remote_trace_level = EXCLUDED.remote_trace_level, " "remote_trace_target = EXCLUDED.remote_trace_target, rules = EXCLUDED.rules, " From 783b49e383f90ac046680a94d4491e44dcea1f6c Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 8 Aug 2019 18:58:22 -0500 Subject: [PATCH 123/185] more worky less not worky --- controller/PostgreSQL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/PostgreSQL.cpp b/controller/PostgreSQL.cpp index 07bb5825..30b3f70d 100644 --- a/controller/PostgreSQL.cpp +++ b/controller/PostgreSQL.cpp @@ -1087,7 +1087,7 @@ void PostgreSQL::commitThread() "last_modified, mtu, multicast_limit, name, private, " "remote_trace_level, remote_trace_target, rules, rules_source, " "tags, v4_assign_mode, v6_assign_mode) VALUES (" - "$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16) " + "$1, $2, $3, $4, TO_TIMESTAMP($5::double precision/1000), $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16) " "ON CONFLICT (id) DO UPDATE set controller_id = EXCLUDED.controller_id, " "capabilities = EXCLUDED.capabilities, enable_broadcast = EXCLUDED.enable_broadcast, " "last_modified = EXCLUDED.last_modified, mtu = EXCLUDED.mtu, " From 96a0c3d764306c0cbdf93e0c229ca33194648ab2 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 8 Aug 2019 19:16:11 -0500 Subject: [PATCH 124/185] ugly query is ugly --- controller/PostgreSQL.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/controller/PostgreSQL.cpp b/controller/PostgreSQL.cpp index 30b3f70d..476ee708 100644 --- a/controller/PostgreSQL.cpp +++ b/controller/PostgreSQL.cpp @@ -1083,11 +1083,14 @@ void PostgreSQL::commitThread() }; PGresult *res = PQexecParams(conn, - "INSERT INTO ztc_network (id, controller_id, capabilities, enable_broadcast, " + "INSERT INTO ztc_network (id, creation_time, owner_id, controller_id, capabilities, enable_broadcast, " "last_modified, mtu, multicast_limit, name, private, " "remote_trace_level, remote_trace_target, rules, rules_source, " "tags, v4_assign_mode, v6_assign_mode) VALUES (" - "$1, $2, $3, $4, TO_TIMESTAMP($5::double precision/1000), $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16) " + "$1, TO_TIMESTAMP($5::double precision/1000), " + "(SELECT user_id AS owner_id FROM ztc_global_permissions WHERE authorize = true AND del = true AND modify = true AND read = true LIMIT 1)," + "$2, $3, $4, TO_TIMESTAMP($5::double precision/1000), " + "$6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16) " "ON CONFLICT (id) DO UPDATE set controller_id = EXCLUDED.controller_id, " "capabilities = EXCLUDED.capabilities, enable_broadcast = EXCLUDED.enable_broadcast, " "last_modified = EXCLUDED.last_modified, mtu = EXCLUDED.mtu, " From 5341c216a703f7499f1eb085d24a4f78e394c389 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 8 Aug 2019 19:20:01 -0500 Subject: [PATCH 125/185] Comment ugly query --- controller/PostgreSQL.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/controller/PostgreSQL.cpp b/controller/PostgreSQL.cpp index 476ee708..0c345c90 100644 --- a/controller/PostgreSQL.cpp +++ b/controller/PostgreSQL.cpp @@ -1082,6 +1082,12 @@ void PostgreSQL::commitThread() v6mode.c_str(), }; + // This ugly query exists because when we want to mirror networks to/from + // another data store (e.g. FileDB or LFDB) it is possible to get a network + // that doesn't exist in Central's database. This does an upsert and sets + // the owner_id to the "first" global admin in the user DB if the record + // did not previously exist. If the record already exists owner_id is left + // unchanged, so owner_id should be left out of the update clause. PGresult *res = PQexecParams(conn, "INSERT INTO ztc_network (id, creation_time, owner_id, controller_id, capabilities, enable_broadcast, " "last_modified, mtu, multicast_limit, name, private, " From 98af3c0dc192ea89df797dd45df7d7efe5ad3d09 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 12 Aug 2019 13:25:12 -0700 Subject: [PATCH 126/185] * Fix high CPU use bug on some platforms * Fix issues with PostgreSQL controller DB (only affects Central) * Restore backward compatibility with MacOS versions prior to 10.13 --- RELEASE-NOTES.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 1dd56b9f..a781392d 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,6 +1,12 @@ ZeroTier Release Notes ====== +# 2019-08-12 -- Version 1.4.2 + + * Fix high CPU use bug on some platforms + * Fix issues with PostgreSQL controller DB (only affects Central) + * Restore backward compatibility with MacOS versions prior to 10.13 + # 2019-07-29 -- Version 1.4.0 ### Major Changes From 83e6864b78d014901a49d34be92b53157e13e9b0 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 13 Aug 2019 09:34:56 -0700 Subject: [PATCH 127/185] Version bump in Linux packages for new binaries. --- debian/changelog | 7 +++++++ zerotier-one.spec | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index d5c049ad..0bf2307a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +zerotier-one (1.4.2-2) unstable; urgency=medium + + * See https://github.com/zerotier/ZeroTierOne for release notes. + * This is a new build that fixes a binary build issue with containers and SELinux + + -- Adam Ierymenko Thu, 04 Aug 2019 01:00:00 -0700 + zerotier-one (1.4.2) unstable; urgency=medium * See https://github.com/zerotier/ZeroTierOne for release notes. diff --git a/zerotier-one.spec b/zerotier-one.spec index 6123eb70..46e166fd 100644 --- a/zerotier-one.spec +++ b/zerotier-one.spec @@ -1,6 +1,6 @@ Name: zerotier-one Version: 1.4.2 -Release: 1%{?dist} +Release: 2%{?dist} Summary: ZeroTier One network virtualization service License: GPLv3 From a0fb5196962ddd885edba83c23c82376eae4e122 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 13 Aug 2019 12:58:14 -0700 Subject: [PATCH 128/185] Make sure libstdc++ is in RH spec file --- zerotier-one.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zerotier-one.spec b/zerotier-one.spec index 46e166fd..6649e653 100644 --- a/zerotier-one.spec +++ b/zerotier-one.spec @@ -14,7 +14,7 @@ BuildRequires: systemd BuildRequires: systemd %endif -Requires: iproute +Requires: iproute libstdc++ %if 0%{?rhel} >= 7 Requires: systemd From 1c7b553331bc2e1f688912108d1ab37fd8f0bd24 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 14 Aug 2019 10:47:58 -0700 Subject: [PATCH 129/185] GitHub issue #1000 --- osdep/LinuxNetLink.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osdep/LinuxNetLink.cpp b/osdep/LinuxNetLink.cpp index da75ccdf..be6e22c3 100644 --- a/osdep/LinuxNetLink.cpp +++ b/osdep/LinuxNetLink.cpp @@ -103,7 +103,11 @@ void LinuxNetLink::_setSocketTimeout(int fd, int seconds) #define ZT_NL_BUF_SIZE 16384 int LinuxNetLink::_doRecv(int fd) { - char *const buf = (char *)valloc(ZT_NL_BUF_SIZE); + char *buf = nullptr; + if (posix_memalign((void **)&buf,16,ZT_NL_BUF_SIZE) != 0) { + fprintf(stderr,"malloc failed!\n"); + ::exit(1); + } if (!buf) { fprintf(stderr,"malloc failed!\n"); ::exit(1); From 2ec53df7abe554a22c3bdd985cbe101e22aaef7c Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 14 Aug 2019 10:52:21 -0700 Subject: [PATCH 130/185] Put a limit on the multicast TX queue to prevent memory use ridiculousness. --- node/Multicaster.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/node/Multicaster.cpp b/node/Multicaster.cpp index 67e133c0..a25b7f05 100644 --- a/node/Multicaster.cpp +++ b/node/Multicaster.cpp @@ -275,6 +275,11 @@ void Multicaster::send( } } } else { + if (gs.txQueue.size() >= ZT_TX_QUEUE_SIZE) { + RR->t->outgoingNetworkFrameDropped(tPtr,network,src,mg.mac(),etherType,0,len,"multicast TX queue is full"); + return; + } + const unsigned int gatherLimit = (limit - (unsigned int)gs.members.size()) + 1; if ((gs.members.empty())||((now - gs.lastExplicitGather) >= ZT_MULTICAST_EXPLICIT_GATHER_DELAY)) { From fe185790614a074b5b9085ee27ccf4448571d05a Mon Sep 17 00:00:00 2001 From: wendelb Date: Sat, 17 Aug 2019 22:50:13 +0200 Subject: [PATCH 131/185] Removed duplicate line `creationTime` --- controller/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/controller/README.md b/controller/README.md index c93c08f5..368613a6 100644 --- a/controller/README.md +++ b/controller/README.md @@ -92,7 +92,6 @@ Example: | v6AssignMode | object | IPv6 management and assign options (see below) | YES | | mtu | integer | Network MTU (default: 2800) | YES | | multicastLimit | integer | Maximum recipients for a multicast packet | YES | -| creationTime | integer | Time network was first created | no | | revision | integer | Network config revision counter | no | | routes | array[object] | Managed IPv4 and IPv6 routes; see below | YES | | ipAssignmentPools | array[object] | IP auto-assign ranges; see below | YES | From 52a166a71f4e0124c7b22123884911338aa0d698 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 23 Aug 2019 09:23:39 -0700 Subject: [PATCH 132/185] Relicense: GPLv3 -> ZeroTier BSL 1.1 --- AUTHORS.md | 4 +- COPYING | 9 +- LICENSE.GPL-2 | 339 ----------- LICENSE.GPL-3 | 674 --------------------- LICENSE.txt | 166 ++++- README.md | 32 +- RELEASE-NOTES.md | 5 + controller/DB.cpp | 27 +- controller/DB.hpp | 27 +- controller/DBMirrorSet.cpp | 27 +- controller/DBMirrorSet.hpp | 27 +- controller/EmbeddedNetworkController.cpp | 29 +- controller/EmbeddedNetworkController.hpp | 27 +- controller/FileDB.cpp | 27 +- controller/FileDB.hpp | 27 +- controller/LFDB.cpp | 27 +- controller/LFDB.hpp | 29 +- controller/PostgreSQL.cpp | 67 +- controller/PostgreSQL.hpp | 27 +- controller/RabbitMQ.cpp | 36 +- controller/RabbitMQ.hpp | 27 +- include/ZeroTierDebug.h | 29 +- include/ZeroTierOne.h | 29 +- node/Address.hpp | 27 +- node/AtomicCounter.hpp | 27 +- node/Buffer.hpp | 27 +- node/C25519.hpp | 27 +- node/Capability.cpp | 27 +- node/Capability.hpp | 27 +- node/CertificateOfMembership.cpp | 27 +- node/CertificateOfMembership.hpp | 27 +- node/CertificateOfOwnership.cpp | 27 +- node/CertificateOfOwnership.hpp | 27 +- node/Constants.hpp | 29 +- node/Credential.hpp | 27 +- node/Dictionary.hpp | 33 +- node/Hashtable.hpp | 27 +- node/Identity.cpp | 27 +- node/Identity.hpp | 27 +- node/IncomingPacket.cpp | 27 +- node/IncomingPacket.hpp | 27 +- node/InetAddress.cpp | 27 +- node/InetAddress.hpp | 27 +- node/MAC.hpp | 27 +- node/Membership.cpp | 27 +- node/Membership.hpp | 27 +- node/MulticastGroup.hpp | 27 +- node/Multicaster.cpp | 27 +- node/Multicaster.hpp | 27 +- node/Mutex.hpp | 31 +- node/Network.cpp | 27 +- node/Network.hpp | 29 +- node/NetworkConfig.cpp | 27 +- node/NetworkConfig.hpp | 27 +- node/NetworkController.hpp | 27 +- node/Node.cpp | 29 +- node/Node.hpp | 27 +- node/OutboundMulticast.cpp | 27 +- node/OutboundMulticast.hpp | 27 +- node/Packet.cpp | 27 +- node/Packet.hpp | 27 +- node/Path.cpp | 27 +- node/Path.hpp | 27 +- node/Peer.cpp | 27 +- node/Peer.hpp | 27 +- node/Poly1305.hpp | 27 +- node/Revocation.cpp | 27 +- node/Revocation.hpp | 27 +- node/RingBuffer.hpp | 37 +- node/RuntimeEnvironment.hpp | 27 +- node/SHA512.hpp | 27 +- node/SelfAwareness.cpp | 27 +- node/SelfAwareness.hpp | 27 +- node/SharedPtr.hpp | 27 +- node/Switch.cpp | 33 +- node/Switch.hpp | 27 +- node/Tag.cpp | 27 +- node/Tag.hpp | 27 +- node/Topology.cpp | 27 +- node/Topology.hpp | 27 +- node/Trace.cpp | 27 +- node/Trace.hpp | 27 +- node/Utils.cpp | 27 +- node/Utils.hpp | 27 +- node/World.hpp | 27 +- one.cpp | 27 +- osdep/Arp.cpp | 27 +- osdep/Arp.hpp | 27 +- osdep/BSDEthernetTap.cpp | 27 +- osdep/BSDEthernetTap.hpp | 27 +- osdep/Binder.hpp | 27 +- osdep/BlockingQueue.hpp | 27 +- osdep/EthernetTap.cpp | 27 +- osdep/EthernetTap.hpp | 27 +- osdep/Http.cpp | 27 +- osdep/Http.hpp | 27 +- osdep/LinuxEthernetTap.cpp | 29 +- osdep/LinuxEthernetTap.hpp | 27 +- osdep/LinuxNetLink.cpp | 45 +- osdep/LinuxNetLink.hpp | 31 +- osdep/MacEthernetTap.cpp | 27 +- osdep/MacEthernetTap.hpp | 27 +- osdep/MacEthernetTapAgent.c | 41 +- osdep/MacEthernetTapAgent.h | 27 +- osdep/MacKextEthernetTap.cpp | 27 +- osdep/MacKextEthernetTap.hpp | 27 +- osdep/ManagedRoute.cpp | 27 +- osdep/ManagedRoute.hpp | 27 +- osdep/NeighborDiscovery.cpp | 37 +- osdep/NeighborDiscovery.hpp | 27 +- osdep/NetBSDEthernetTap.cpp | 27 +- osdep/NetBSDEthernetTap.hpp | 27 +- osdep/OSUtils.cpp | 27 +- osdep/OSUtils.hpp | 27 +- osdep/Phy.hpp | 27 +- osdep/PortMapper.cpp | 27 +- osdep/PortMapper.hpp | 27 +- osdep/Thread.hpp | 27 +- osdep/WindowsEthernetTap.cpp | 27 +- osdep/WindowsEthernetTap.hpp | 27 +- rule-compiler/rule-compiler.js | 13 + selftest.cpp | 27 +- service/OneService.cpp | 29 +- service/OneService.hpp | 27 +- service/SoftwareUpdater.cpp | 27 +- service/SoftwareUpdater.hpp | 27 +- version.h | 29 +- windows/ZeroTierOne/ZeroTierOneService.cpp | 19 +- windows/ZeroTierOne/ZeroTierOneService.h | 19 +- 129 files changed, 1094 insertions(+), 3540 deletions(-) delete mode 100644 LICENSE.GPL-2 delete mode 100644 LICENSE.GPL-3 diff --git a/AUTHORS.md b/AUTHORS.md index c4c0c730..84bb8631 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -1,3 +1,5 @@ +# Authors and Third Party Code Licensing Information + ## Primary Authors * ZeroTier Core and ZeroTier One virtual networking service
@@ -26,7 +28,7 @@ ## Third-Party Code -ZeroTier includes the following third party code, either in ext/ or incorporated into the ZeroTier core. +ZeroTier includes the following third party code, either in ext/ or incorporated into the ZeroTier core. This third party code remains licensed under its original license and is not subject to ZeroTier's BSL license. * LZ4 compression algorithm by Yann Collet diff --git a/COPYING b/COPYING index c43e8e7b..d07f3524 100644 --- a/COPYING +++ b/COPYING @@ -1,13 +1,8 @@ ZeroTier One, an endpoint server for the ZeroTier virtual network layer. Copyright © 2011–2019 ZeroTier, Inc. -ZeroTier One is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3 of the License, or (at -your option) any later version. - -See the file ‘LICENSE.GPL-3’ for the text of the GNU GPL version 3. -If that file is not present, see . +ZeroTier is released under the terms of the BSL version 1.1. See the +file LICENSE.txt for details. .. Local variables: diff --git a/LICENSE.GPL-2 b/LICENSE.GPL-2 deleted file mode 100644 index d159169d..00000000 --- a/LICENSE.GPL-2 +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/LICENSE.GPL-3 b/LICENSE.GPL-3 deleted file mode 100644 index 94a9ed02..00000000 --- a/LICENSE.GPL-3 +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/LICENSE.txt b/LICENSE.txt index 3807fea3..c0c40aed 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,37 +1,147 @@ -ZeroTier One - Network Virtualization Everywhere -Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ +----------------------------------------------------------------------------- -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. +Business Source License 1.1 -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. +License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved. +"Business Source License" is a trademark of MariaDB Corporation Ab. -You should have received a copy of the GNU General Public License -along with this program. If not, see . +----------------------------------------------------------------------------- -See LICENSE.GPL-3 for the full GNU GPL v3 license. +Parameters --- +Licensor: ZeroTier, Inc. +Licensed Work: ZeroTier Network Virtualization Engine 1.4.4 + The Licensed Work is (c)2019 ZeroTier, Inc. +Additional Use Grant: You may make use of the Licensed Work, provided you + do not use it in any of the following ways: -You can be released from the requirements of the license by purchasing -a commercial license. Buying such a license is mandatory as soon as you -develop commercial closed-source software that incorporates or links -directly against ZeroTier software without disclosing the source code -of your own application. + * Sell hosted ZeroTier services as a "SaaS" Product --- + (1) Operate or sell access to ZeroTier root servers, + network controllers, or authorization key or certificate + generation components of the Licensed Work as a + for-profit service, regardless of whether the use of + these components is sold alone or is bundled with other + services. -The above license does not apply to third party code included with or -linked against by ZeroTier software. See the third party code section -of the AUTHORS.md for an index of third party software included in -this software repository. + * Create Non-Open-Source Commercial Derviative Works -Licenses for third party code are all relatively permissive: MIT, -BSD, and public domain. The only exception is the tap-windows driver -which is under the GPLv2, but this is only needed to produce the -binary tap device driver used by the ZeroTier service on Windows. + (2) Link or directly include the Licensed Work in a + commercial or for-profit application or other product + not distributed under an Open Source Initiative (OSI) + compliant license. See: https://opensource.org/licenses + + (3) Remove the name, logo, copyright, or other branding + material from the Licensed Work to create a "rebranded" + or "white labeled" version to distribute as part of + any commercial or for-profit product or service. + + * Certain Government Uses + + (4) Use or deploy the Licensed Work in a government + setting in support of any active government function + or operation with the exception of the following: + physical or mental health care, family and social + services, social welfare, senior care, child care, and + the care of persons with disabilities. + +Change Date: 2023-01-01 + +Change License: Apache License version 2.0 as published by the Apache + Software Foundation + https://www.apache.org/licenses/ + +Alternative Licensing + +If you would like to use the Licensed Work in any way that conflicts with +the stipulations of the Additional Use Grant, contact ZeroTier, Inc. to +obtain an alternative commercial license. + +Visit us on the web at: https://www.zerotier.com/ + +Notice + +The Business Source License (this document, or the "License") is not an Open +Source license. However, the Licensed Work will eventually be made available +under an Open Source License, as stated in this License. + +For more information on the use of the Business Source License for ZeroTier +products, please visit our pricing page which contains license details and +and license FAQ: https://zerotier.com/pricing + +For more information on the use of the Business Source License generally, +please visit the Adopting and Developing Business Source License FAQ at +https://mariadb.com/bsl-faq-adopting. + +----------------------------------------------------------------------------- + +Business Source License 1.1 + +Terms + +The Licensor hereby grants you the right to copy, modify, create derivative +works, redistribute, and make non-production use of the Licensed Work. The +Licensor may make an Additional Use Grant, above, permitting limited +production use. + +Effective on the Change Date, or the fourth anniversary of the first publicly +available distribution of a specific version of the Licensed Work under this +License, whichever comes first, the Licensor hereby grants you rights under +the terms of the Change License, and the rights granted in the paragraph +above terminate. + +If your use of the Licensed Work does not comply with the requirements +currently in effect as described in this License, you must purchase a +commercial license from the Licensor, its affiliated entities, or authorized +resellers, or you must refrain from using the Licensed Work. + +All copies of the original and modified Licensed Work, and derivative works +of the Licensed Work, are subject to this License. This License applies +separately for each version of the Licensed Work and the Change Date may vary +for each version of the Licensed Work released by Licensor. + +You must conspicuously display this License on each original or modified copy +of the Licensed Work. If you receive the Licensed Work in original or +modified form from a third party, the terms and conditions set forth in this +License apply to your use of that work. + +Any use of the Licensed Work in violation of this License will automatically +terminate your rights under this License for the current and all other +versions of the Licensed Work. + +This License does not grant you any right in any trademark or logo of +Licensor or its affiliates (provided that you may use a trademark or logo of +Licensor as expressly required by this License). + +TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON +AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, +EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND +TITLE. + +----------------------------------------------------------------------------- + +MariaDB hereby grants you permission to use this License’s text to license +your works, and to refer to it using the trademark "Business Source License", +as long as you comply with the Covenants of Licensor below. + +Covenants of Licensor + +In consideration of the right to use this License’s text and the "Business +Source License" name and trademark, Licensor covenants to MariaDB, and to all +other recipients of the licensed work to be provided by Licensor: + +1. To specify as the Change License the GPL Version 2.0 or any later version, + or a license that is compatible with GPL Version 2.0 or a later version, + where "compatible" means that software provided under the Change License can + be included in a program with software provided under GPL Version 2.0 or a + later version. Licensor may specify additional Change Licenses without + limitation. + +2. To either: (a) specify an additional grant of rights to use that does not + impose any additional restriction on the right granted in this License, as + the Additional Use Grant; or (b) insert the text "None". + +3. To specify a Change Date. + +4. Not to modify this License in any other way. diff --git a/README.md b/README.md index 6fecf2fd..3b9326ac 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,27 @@ ZeroTier - Global Area Networking ====== -ZeroTier is a smart programmable Ethernet switch for planet Earth. It allows networked devices and applications to be managed as if the entire world is one data center or cloud region. +ZeroTier is a smart programmable Ethernet switch for planet Earth. It allows all networked devices, VMs, containers, and applications to communicate as if they all reside in the same physical data center or cloud region. -It replaces the physical LAN/WAN boundary with a virtual one, allowing devices of any type at any location to be managed as if they all reside in the same cloud region or data center. All traffic is encrypted end-to-end and takes the most direct path available for minimum latency and maximum performance. The goals and design of ZeroTier are inspired by among other things the original [Google BeyondCorp](https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/43231.pdf) paper and the [Jericho Forum](https://en.wikipedia.org/wiki/Jericho_Forum). +This is accomplished by combining a cryptographically addressed and secure peer to peer network (termed VL1) with an Ethernet emulation layer somewhat similar to VXLAN (termed VL2). Our VL2 Ethernet virtualization layer includes advanced enterprise SDN features like fine grained access control rules for network micro-segmentation and security monitoring. + +All ZeroTier traffic is encrypted end-to-end using secret keys that only you control. Most traffic flows peer to peer, though we offer free (but slow) relaying for users who cannot establish peer to peer connetions. + +The goals and design principles of ZeroTier are inspired by among other things the original [Google BeyondCorp](https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/43231.pdf) paper and the [Jericho Forum](https://en.wikipedia.org/wiki/Jericho_Forum) with its notion of "deperimeterization." Visit [ZeroTier's site](https://www.zerotier.com/) for more information and [pre-built binary packages](https://www.zerotier.com/download/). Apps for Android and iOS are available for free in the Google Play and Apple app stores. +ZeroTier is licensed under the [BSL version 1.1](https://mariadb.com/bsl11/). See [LICENSE.txt](LICENSE.txt) and the [ZeroTier pricing page](https://www.zerotier.com/pricing) for details. ZeroTier is free to use internally in businesses and academic institutions and for non-commercial purposes. Certain types of commercial use such as building closed-source apps and devices based on ZeroTier or offering ZeroTier network controllers and network management as a SaaS service require a commercial license. + +A small amount of third party code is also included in ZeroTier and is not subject to our BSL license. See [AUTHORS.md] for a list of third party code, where it is included, and the licenses that apply to it. All of the third party code in ZeroTier is liberally licensed (MIT, BSD, Apache, public domain, etc.). + ### Getting Started -Everything in the ZeroTier world is controlled by two types of identifier: 40-bit/10-digit *ZeroTier addresses* and 64-bit/16-digit *network IDs*. A ZeroTier address identifies a node or "device" (laptop, phone, server, VM, app, etc.) while a network ID identifies a virtual Ethernet network that can be joined by devices. +Everything in the ZeroTier world is controlled by two types of identifier: 40-bit/10-digit *ZeroTier addresses* and 64-bit/16-digit *network IDs*. These identifiers are easily distinguished by their length. A ZeroTier address identifies a node or "device" (laptop, phone, server, VM, app, etc.) while a network ID identifies a virtual Ethernet network that can be joined by devices. -Another way of thinking about it is that ZeroTier addresses are port numbers on a giant planetary-sized smart switch while network IDs are VLANs to which these ports can be assigned. For more details read about VL1 and VL2 in [the ZeroTier manual](https://www.zerotier.com/manual/). +ZeroTier addresses can be thought of as port numbers on an enormous planet-wide enterprise Ethernet smart switch supporting VLANs. Network IDs are VLAN IDs to which these ports may be assigned. A single port can be assigned to more than one VLAN. -*Network controllers* are ZeroTier nodes that act as access control certificate authorities and configuration managers for virtual networks. The first 40 bits (or 10 digits) of a network ID is the ZeroTier address of its controller. You can create networks with our [hosted controllers](https://my.zerotier.com/) and web UI/API or [host your own](controller/) if you don't mind posting some JSON configuration info or writing a script to do so. +A ZeroTier address looks like `8056c2e21c` and a network ID looks like `8056c2e21c000001`. Network IDs are composed of the ZeroTier address of that network's primary controller and an arbitrary 24-bit ID that identifies the network on this controller. Network controllers are roughly analogous to SDN controllers in SDN protocols like [OpenFlow](https://en.wikipedia.org/wiki/OpenFlow), though as with the analogy between VXLAN and VL2 this should not be read to imply that the protocols or design are the same. You can use our convenient and inexpensive SaaS hosted controllers at [my.zerotier.com](https://my.zerotier.com/) or [run your own controller](controller/) if you don't mind messing around with JSON configuration files or writing scripts to do so. ### Project Layout @@ -33,7 +41,7 @@ The base path contains the ZeroTier One service main entry point (`one.cpp`), se - `osdep/`: code to support and integrate with OSes, including platform-specific stuff only built for certain targets. - `rule-compiler/`: JavaScript rules language compiler for defining network-level rules. - `service/`: the ZeroTier One service, which wraps the ZeroTier core and provides VPN-like connectivity to virtual networks for desktops, laptops, servers, VMs, and containers. - - `windows/`: Visual Studio solution files, Windows service code for ZeroTier One, and the Windows task bar app UI. + - `windows/`: Visual Studio solution files, Windows service code, and the Windows task bar app UI. ### Build and Platform Notes @@ -80,7 +88,7 @@ Running ZeroTier One on a Mac is the same, but OSX requires a kernel extension. This will create the home folder for Mac, place *tap.kext* there, and set its modes correctly to enable ZeroTier One to manage it with *kextload* and *kextunload*. -### Troubleshooting +### Basic Troubleshooting For most users, it just works. @@ -96,14 +104,6 @@ ZeroTier One peers will automatically locate each other and communicate directly Users behind certain types of firewalls and "symmetric" NAT devices may not able able to connect to external peers directly at all. ZeroTier has limited support for port prediction and will *attempt* to traverse symmetric NATs, but this doesn't always work. If P2P connectivity fails you'll be bouncing UDP packets off our relay servers resulting in slower performance. Some NAT router(s) have a configurable NAT mode, and setting this to "full cone" will eliminate this problem. If you do this you may also see a magical improvement for things like VoIP phones, Skype, BitTorrent, WebRTC, certain games, etc., since all of these use NAT traversal techniques similar to ours. -If you're interested, there's a [technical deep dive about NAT traversal on our blog](https://www.zerotier.com/blog/?p=226?pk_campaign=github_ZeroTierOne). A troubleshooting tool to help you diagnose NAT issues is planned for the future as are uPnP/IGD/NAT-PMP and IPv6 transport. - If a firewall between you and the Internet blocks ZeroTier's UDP traffic, you will fall back to last-resort TCP tunneling to rootservers over port 443 (https impersonation). This will work almost anywhere but is *very slow* compared to UDP or direct peer to peer connectivity. -### Contributing - -Please make pull requests against the `dev` branch. The `master` branch is release, and `edge` is for unstable and work in progress changes and is not likely to work. - -### License - -The ZeroTier source code is open source and is licensed under the GNU GPL v3 (not LGPL). If you'd like to embed it in a closed-source commercial product or appliance, please e-mail [contact@zerotier.com](mailto:contact@zerotier.com) to discuss commercial licensing. Otherwise it can be used for free. +Additional help [can be found in our knowledge base](https://zerotier.atlassian.net/wiki/spaces/SD/overview). diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index a781392d..3b0902cb 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,6 +1,11 @@ ZeroTier Release Notes ====== +# 2019-08-23 -- Version 1.4.4 + + * Change license to BSL 1.1, see LICENSE.txt + * Fix an issue with the "ipauth" rule and auto-generated unforgeable IPv6 addresses + # 2019-08-12 -- Version 1.4.2 * Fix high CPU use bug on some platforms diff --git a/controller/DB.cpp b/controller/DB.cpp index 0c6274b9..dfa4fa09 100644 --- a/controller/DB.cpp +++ b/controller/DB.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include "DB.hpp" #include "EmbeddedNetworkController.hpp" diff --git a/controller/DB.hpp b/controller/DB.hpp index 6c518426..8a3c05e0 100644 --- a/controller/DB.hpp +++ b/controller/DB.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_CONTROLLER_DB_HPP #define ZT_CONTROLLER_DB_HPP diff --git a/controller/DBMirrorSet.cpp b/controller/DBMirrorSet.cpp index c3cd7841..b2c7c71b 100644 --- a/controller/DBMirrorSet.cpp +++ b/controller/DBMirrorSet.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include "DBMirrorSet.hpp" diff --git a/controller/DBMirrorSet.hpp b/controller/DBMirrorSet.hpp index 23cb25e7..6ca6c452 100644 --- a/controller/DBMirrorSet.hpp +++ b/controller/DBMirrorSet.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_DBMIRRORSET_HPP #define ZT_DBMIRRORSET_HPP diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index 08d31bee..e0e2a3ea 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include #include @@ -1650,7 +1637,7 @@ void EmbeddedNetworkController::_request( if ((ipRangeEnd < ipRangeStart)||(ipRangeStart == 0)) continue; uint32_t ipRangeLen = ipRangeEnd - ipRangeStart; - + // Start with the LSB of the member's address uint32_t ipTrialCounter = (uint32_t)(identity.address().toInt() & 0xffffffff); diff --git a/controller/EmbeddedNetworkController.hpp b/controller/EmbeddedNetworkController.hpp index adc2a2ec..1db4cf42 100644 --- a/controller/EmbeddedNetworkController.hpp +++ b/controller/EmbeddedNetworkController.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_SQLITENETWORKCONTROLLER_HPP #define ZT_SQLITENETWORKCONTROLLER_HPP diff --git a/controller/FileDB.cpp b/controller/FileDB.cpp index cf5847d6..b4eaf58c 100644 --- a/controller/FileDB.cpp +++ b/controller/FileDB.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include "FileDB.hpp" diff --git a/controller/FileDB.hpp b/controller/FileDB.hpp index 8aa2c18e..fcd7af0f 100644 --- a/controller/FileDB.hpp +++ b/controller/FileDB.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_CONTROLLER_FILEDB_HPP #define ZT_CONTROLLER_FILEDB_HPP diff --git a/controller/LFDB.cpp b/controller/LFDB.cpp index b6dc6657..d11b77a0 100644 --- a/controller/LFDB.cpp +++ b/controller/LFDB.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include "LFDB.hpp" diff --git a/controller/LFDB.hpp b/controller/LFDB.hpp index bcd6cdd0..0849ae57 100644 --- a/controller/LFDB.hpp +++ b/controller/LFDB.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_CONTROLLER_LFDB_HPP #define ZT_CONTROLLER_LFDB_HPP @@ -96,7 +83,7 @@ protected: std::thread _syncThread; bool _storeOnlineState; }; - + } // namespace ZeroTier #endif diff --git a/controller/PostgreSQL.cpp b/controller/PostgreSQL.cpp index 0c345c90..08e06ee9 100644 --- a/controller/PostgreSQL.cpp +++ b/controller/PostgreSQL.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include "PostgreSQL.hpp" @@ -141,7 +128,7 @@ PostgreSQL::~PostgreSQL() { _run = 0; std::this_thread::sleep_for(std::chrono::milliseconds(100)); - + _heartbeatThread.join(); _membersDbWatcher.join(); _networksDbWatcher.join(); @@ -222,7 +209,7 @@ void PostgreSQL::eraseNetwork(const uint64_t networkId) _commitQueue.post(tmp); } -void PostgreSQL::eraseMember(const uint64_t networkId, const uint64_t memberId) +void PostgreSQL::eraseMember(const uint64_t networkId, const uint64_t memberId) { char tmp2[24]; std::pair tmp; @@ -267,7 +254,7 @@ void PostgreSQL::initializeNetworks(PGconn *conn) NULL, NULL, 0); - + if (PQresultStatus(res) != PGRES_TUPLES_OK) { fprintf(stderr, "Networks Initialization Failed: %s", PQerrorMessage(conn)); PQclear(res); @@ -339,7 +326,7 @@ void PostgreSQL::initializeNetworks(PGconn *conn) NULL, NULL, 0); - + if (PQresultStatus(r2) != PGRES_TUPLES_OK) { fprintf(stderr, "ERROR: Error retreiving IP pools for network: %s\n", PQresultErrorMessage(r2)); PQclear(r2); @@ -391,7 +378,7 @@ void PostgreSQL::initializeNetworks(PGconn *conn) } PQclear(r2); - + _networkChanged(empty, config, false); } @@ -616,7 +603,7 @@ void PostgreSQL::heartbeat() }; PGresult *res = PQexecParams(conn, - "INSERT INTO ztc_controller (id, cluster_host, last_alive, public_identity, v_major, v_minor, v_rev, v_build, host_port, use_rabbitmq) " + "INSERT INTO ztc_controller (id, cluster_host, last_alive, public_identity, v_major, v_minor, v_rev, v_build, host_port, use_rabbitmq) " "VALUES ($1, $2, TO_TIMESTAMP($3::double precision/1000), $4, $5, $6, $7, $8, $9, $10) " "ON CONFLICT (id) DO UPDATE SET cluster_host = EXCLUDED.cluster_host, last_alive = EXCLUDED.last_alive, " "public_identity = EXCLUDED.public_identity, v_major = EXCLUDED.v_major, v_minor = EXCLUDED.v_minor, " @@ -768,7 +755,7 @@ void PostgreSQL::networksDbWatcher() PQfinish(conn); conn = NULL; } - + if (_run == 1) { fprintf(stderr, "ERROR: %s networksDbWatcher should still be running! Exiting Controller.\n", _myAddressStr.c_str()); exit(8); @@ -934,7 +921,7 @@ void PostgreSQL::commitThread() NULL, NULL, 0); - + if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "ERROR: Error updating member: %s\n", PQresultErrorMessage(res)); fprintf(stderr, "%s", OSUtils::jsonDump(*config, 2).c_str()); @@ -1004,7 +991,7 @@ void PostgreSQL::commitThread() NULL, NULL, 0); - + if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "ERROR: Error setting IP addresses for member: %s\n", PQresultErrorMessage(res)); PQclear(res); @@ -1029,7 +1016,7 @@ void PostgreSQL::commitThread() nlohmann::json memNew(*config); get(nwidInt, nwOrig, memberidInt, memOrig); - + _memberChanged(memOrig, memNew, qitem.second); } else { fprintf(stderr, "Can't notify of change. Error parsing nwid or memberid: %llu-%llu\n", (unsigned long long)nwidInt, (unsigned long long)memberidInt); @@ -1111,7 +1098,7 @@ void PostgreSQL::commitThread() NULL, NULL, 0); - + if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "ERROR: Error updating network record: %s\n", PQresultErrorMessage(res)); PQclear(res); @@ -1136,7 +1123,7 @@ void PostgreSQL::commitThread() const char *params[1] = { id.c_str() }; - res = PQexecParams(conn, + res = PQexecParams(conn, "DELETE FROM ztc_network_assignment_pool WHERE network_id = $1", 1, NULL, @@ -1190,7 +1177,7 @@ void PostgreSQL::commitThread() continue; } - res = PQexecParams(conn, + res = PQexecParams(conn, "DELETE FROM ztc_network_route WHERE network_id = $1", 1, NULL, @@ -1295,7 +1282,7 @@ void PostgreSQL::commitThread() NULL, NULL, 0); - + if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "ERROR: Error deleting network: %s\n", PQresultErrorMessage(res)); } @@ -1395,16 +1382,16 @@ void PostgreSQL::onlineNotificationThread() if (found == _networks.end()) { continue; // skip members trying to join non-existant networks } - + std::string networkId(nwidTmp); std::string memberId(memTmp); - + std::vector &members = updateMap[networkId]; members.push_back(memberId); lastOnlineCumulative[i->first] = i->second.first; - - + + const char *qvals[2] = { networkId.c_str(), memberId.c_str() @@ -1432,7 +1419,7 @@ void PostgreSQL::onlineNotificationThread() int64_t ts = i->second.first; std::string ipAddr = i->second.second.toIpString(ipTmp); std::string timestamp = std::to_string(ts); - + if (firstRun) { firstRun = false; } else { @@ -1481,7 +1468,7 @@ PGconn *PostgreSQL::getPgConn(OverrideMode m) if (connStr != NULL) { fprintf(stderr, "PGBouncer Override\n"); std::string conn(connStr); - conn += " application_name=controller-"; + conn += " application_name=controller-"; conn += _myAddressStr.c_str(); return PQconnectdb(conn.c_str()); } diff --git a/controller/PostgreSQL.hpp b/controller/PostgreSQL.hpp index 6b0ea996..035f5b5a 100644 --- a/controller/PostgreSQL.hpp +++ b/controller/PostgreSQL.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include "DB.hpp" diff --git a/controller/RabbitMQ.cpp b/controller/RabbitMQ.cpp index e14fbf3f..41ebcc87 100644 --- a/controller/RabbitMQ.cpp +++ b/controller/RabbitMQ.cpp @@ -1,29 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ - +/****/ #include "RabbitMQ.hpp" @@ -42,7 +28,7 @@ RabbitMQ::RabbitMQ(MQConfig *cfg, const char *queueName) , _qName(queueName) , _socket(NULL) , _status(0) -{ +{ } RabbitMQ::~RabbitMQ() @@ -64,12 +50,12 @@ void RabbitMQ::init() if (!_socket) { throw std::runtime_error("Can't create socket for RabbitMQ"); } - + _status = amqp_socket_open_noblock(_socket, _mqc->host, _mqc->port, &tval); if (_status) { throw std::runtime_error("Can't connect to RabbitMQ"); } - + amqp_rpc_reply_t r = amqp_login(_conn, "/", 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, _mqc->username, _mqc->password); if (r.reply_type != AMQP_RESPONSE_NORMAL) { @@ -86,7 +72,7 @@ void RabbitMQ::init() if(r.reply_type != AMQP_RESPONSE_NORMAL) { throw std::runtime_error("Error opening communication channel"); } - + _q = amqp_queue_declare(_conn, _channel, amqp_cstring_bytes(_qName), 0, 0, 0, 0, amqp_empty_table); r = amqp_get_rpc_reply(_conn); if (r.reply_type != AMQP_RESPONSE_NORMAL) { diff --git a/controller/RabbitMQ.hpp b/controller/RabbitMQ.hpp index c8ef31ca..c60af8ec 100644 --- a/controller/RabbitMQ.hpp +++ b/controller/RabbitMQ.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_CONTROLLER_RABBITMQ_HPP #define ZT_CONTROLLER_RABBITMQ_HPP diff --git a/include/ZeroTierDebug.h b/include/ZeroTierDebug.h index 561b5a63..aa7ab4fe 100644 --- a/include/ZeroTierDebug.h +++ b/include/ZeroTierDebug.h @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ /** * @file @@ -80,7 +67,7 @@ #define ZT_THREAD_ID (long)0 // (long)gettid() #endif #ifdef _WIN32 - #define ZT_THREAD_ID (long)0 // + #define ZT_THREAD_ID (long)0 // #endif #if defined(__JNI_LIB__) #include diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index b0be0105..c93b4dbf 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ /* * This defines the external C API for ZeroTier's core network virtualization @@ -657,7 +644,7 @@ typedef struct /** * Internal node statistics - * + * * This structure is subject to change between versions. */ typedef struct diff --git a/node/Address.hpp b/node/Address.hpp index ae0566fe..0749adbf 100644 --- a/node/Address.hpp +++ b/node/Address.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_ADDRESS_HPP #define ZT_ADDRESS_HPP diff --git a/node/AtomicCounter.hpp b/node/AtomicCounter.hpp index b18ba540..ea84259b 100644 --- a/node/AtomicCounter.hpp +++ b/node/AtomicCounter.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_ATOMICCOUNTER_HPP #define ZT_ATOMICCOUNTER_HPP diff --git a/node/Buffer.hpp b/node/Buffer.hpp index fe63eb2e..d0e152b9 100644 --- a/node/Buffer.hpp +++ b/node/Buffer.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_BUFFER_HPP #define ZT_BUFFER_HPP diff --git a/node/C25519.hpp b/node/C25519.hpp index 640aedf5..db34f621 100644 --- a/node/C25519.hpp +++ b/node/C25519.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_C25519_HPP #define ZT_C25519_HPP diff --git a/node/Capability.cpp b/node/Capability.cpp index fdf98bae..ad1b0f45 100644 --- a/node/Capability.cpp +++ b/node/Capability.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include "Capability.hpp" #include "RuntimeEnvironment.hpp" diff --git a/node/Capability.hpp b/node/Capability.hpp index 0704c513..12730028 100644 --- a/node/Capability.hpp +++ b/node/Capability.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_CAPABILITY_HPP #define ZT_CAPABILITY_HPP diff --git a/node/CertificateOfMembership.cpp b/node/CertificateOfMembership.cpp index 614c6887..20ae229e 100644 --- a/node/CertificateOfMembership.cpp +++ b/node/CertificateOfMembership.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include "CertificateOfMembership.hpp" #include "RuntimeEnvironment.hpp" diff --git a/node/CertificateOfMembership.hpp b/node/CertificateOfMembership.hpp index b2c63f9d..5043f4e6 100644 --- a/node/CertificateOfMembership.hpp +++ b/node/CertificateOfMembership.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_CERTIFICATEOFMEMBERSHIP_HPP #define ZT_CERTIFICATEOFMEMBERSHIP_HPP diff --git a/node/CertificateOfOwnership.cpp b/node/CertificateOfOwnership.cpp index d7266cd2..d6cd7d71 100644 --- a/node/CertificateOfOwnership.cpp +++ b/node/CertificateOfOwnership.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include "CertificateOfOwnership.hpp" #include "RuntimeEnvironment.hpp" diff --git a/node/CertificateOfOwnership.hpp b/node/CertificateOfOwnership.hpp index fdffec3b..17c843bb 100644 --- a/node/CertificateOfOwnership.hpp +++ b/node/CertificateOfOwnership.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_CERTIFICATEOFOWNERSHIP_HPP #define ZT_CERTIFICATEOFOWNERSHIP_HPP diff --git a/node/Constants.hpp b/node/Constants.hpp index d58e408f..6ea911ba 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_CONSTANTS_HPP #define ZT_CONSTANTS_HPP @@ -461,7 +448,7 @@ /** * Delay between full-fledge pings of directly connected peers. - * + * * With multipath bonding enabled ping peers more often to measure * packet loss and latency. This uses more bandwidth so is disabled * by default to avoid increasing idle bandwidth use for regular diff --git a/node/Credential.hpp b/node/Credential.hpp index e7962fbb..5b58da2b 100644 --- a/node/Credential.hpp +++ b/node/Credential.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_CREDENTIAL_HPP #define ZT_CREDENTIAL_HPP diff --git a/node/Dictionary.hpp b/node/Dictionary.hpp index 8eb10a0b..5374b9e6 100644 --- a/node/Dictionary.hpp +++ b/node/Dictionary.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_DICTIONARY_HPP #define ZT_DICTIONARY_HPP @@ -387,7 +374,7 @@ public: return this->add(key,(value) ? "1" : "0",1); } - /** + /** * Add a 64-bit integer (unsigned) as a hex value */ inline bool add(const char *key,uint64_t value) @@ -396,7 +383,7 @@ public: return this->add(key,Utils::hex(value,tmp),-1); } - /** + /** * Add a 64-bit integer (unsigned) as a hex value */ inline bool add(const char *key,int64_t value) @@ -410,7 +397,7 @@ public: } } - /** + /** * Add a 64-bit integer (unsigned) as a hex value */ inline bool add(const char *key,const Address &a) diff --git a/node/Hashtable.hpp b/node/Hashtable.hpp index 10aab736..9a0f3e20 100644 --- a/node/Hashtable.hpp +++ b/node/Hashtable.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_HASHTABLE_HPP #define ZT_HASHTABLE_HPP diff --git a/node/Identity.cpp b/node/Identity.cpp index e914b270..4e92765f 100644 --- a/node/Identity.cpp +++ b/node/Identity.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include #include diff --git a/node/Identity.hpp b/node/Identity.hpp index f559bcc5..28d1f004 100644 --- a/node/Identity.hpp +++ b/node/Identity.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_IDENTITY_HPP #define ZT_IDENTITY_HPP diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index b774f1df..57d691b9 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include #include diff --git a/node/IncomingPacket.hpp b/node/IncomingPacket.hpp index 5c4f896b..cf9a6474 100644 --- a/node/IncomingPacket.hpp +++ b/node/IncomingPacket.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_INCOMINGPACKET_HPP #define ZT_INCOMINGPACKET_HPP diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp index 15d2f878..3eee1d4b 100644 --- a/node/InetAddress.cpp +++ b/node/InetAddress.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include #include diff --git a/node/InetAddress.hpp b/node/InetAddress.hpp index ce65bcd0..e16ae43b 100644 --- a/node/InetAddress.hpp +++ b/node/InetAddress.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_INETADDRESS_HPP #define ZT_INETADDRESS_HPP diff --git a/node/MAC.hpp b/node/MAC.hpp index e1e20e37..3f7b0060 100644 --- a/node/MAC.hpp +++ b/node/MAC.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_MAC_HPP #define ZT_MAC_HPP diff --git a/node/Membership.cpp b/node/Membership.cpp index 031eb0b7..100946b2 100644 --- a/node/Membership.cpp +++ b/node/Membership.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include diff --git a/node/Membership.hpp b/node/Membership.hpp index 73e11c6c..f3e6d720 100644 --- a/node/Membership.hpp +++ b/node/Membership.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_MEMBERSHIP_HPP #define ZT_MEMBERSHIP_HPP diff --git a/node/MulticastGroup.hpp b/node/MulticastGroup.hpp index 184df1ce..a38b284d 100644 --- a/node/MulticastGroup.hpp +++ b/node/MulticastGroup.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_MULTICASTGROUP_HPP #define ZT_MULTICASTGROUP_HPP diff --git a/node/Multicaster.cpp b/node/Multicaster.cpp index a25b7f05..82babae0 100644 --- a/node/Multicaster.cpp +++ b/node/Multicaster.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include diff --git a/node/Multicaster.hpp b/node/Multicaster.hpp index 971f84af..f4c80108 100644 --- a/node/Multicaster.hpp +++ b/node/Multicaster.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_MULTICASTER_HPP #define ZT_MULTICASTER_HPP diff --git a/node/Mutex.hpp b/node/Mutex.hpp index 1c8fb81e..14b6c81f 100644 --- a/node/Mutex.hpp +++ b/node/Mutex.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_MUTEX_HPP #define ZT_MUTEX_HPP @@ -51,11 +38,11 @@ public: inline void lock() const { - const uint16_t myTicket = __sync_fetch_and_add(&(const_cast(this)->nextTicket),1); + const uint16_t myTicket = __sync_fetch_and_add(&(const_cast(this)->nextTicket),1); while (nowServing != myTicket) { __asm__ __volatile__("rep;nop"::); __asm__ __volatile__("":::"memory"); - } + } } inline void unlock() const diff --git a/node/Network.cpp b/node/Network.cpp index 4458c9b0..cfdbb376 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include #include diff --git a/node/Network.hpp b/node/Network.hpp index 5e573812..701a4611 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_NETWORK_HPP #define ZT_NETWORK_HPP @@ -370,7 +357,7 @@ public: /** * Push credentials if we haven't done so in a very long time - * + * * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param to Destination peer address * @param now Current time diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp index 20ad2e25..e45a111d 100644 --- a/node/NetworkConfig.cpp +++ b/node/NetworkConfig.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp index ddad52a5..12bbf775 100644 --- a/node/NetworkConfig.hpp +++ b/node/NetworkConfig.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_NETWORKCONFIG_HPP #define ZT_NETWORKCONFIG_HPP diff --git a/node/NetworkController.hpp b/node/NetworkController.hpp index 1cbbd3ff..b344787b 100644 --- a/node/NetworkController.hpp +++ b/node/NetworkController.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_NETWORKCONFIGMASTER_HPP #define ZT_NETWORKCONFIGMASTER_HPP diff --git a/node/Node.cpp b/node/Node.cpp index 237da463..5330b74c 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include #include @@ -501,7 +488,7 @@ ZT_PeerList *Node::peers() const p->paths[p->pathCount].expired = 0; p->paths[p->pathCount].preferred = ((*path) == bestp) ? 1 : 0; p->paths[p->pathCount].latency = (float)(*path)->latency(); - p->paths[p->pathCount].packetDelayVariance = (*path)->packetDelayVariance(); + p->paths[p->pathCount].packetDelayVariance = (*path)->packetDelayVariance(); p->paths[p->pathCount].throughputDisturbCoeff = (*path)->throughputDisturbanceCoefficient(); p->paths[p->pathCount].packetErrorRatio = (*path)->packetErrorRatio(); p->paths[p->pathCount].packetLossRatio = (*path)->packetLossRatio(); diff --git a/node/Node.hpp b/node/Node.hpp index a6f92eb1..21d49f51 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_NODE_HPP #define ZT_NODE_HPP diff --git a/node/OutboundMulticast.cpp b/node/OutboundMulticast.cpp index a162c8a5..1f2090ec 100644 --- a/node/OutboundMulticast.cpp +++ b/node/OutboundMulticast.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include "Constants.hpp" #include "RuntimeEnvironment.hpp" diff --git a/node/OutboundMulticast.hpp b/node/OutboundMulticast.hpp index 42063995..a40dc80f 100644 --- a/node/OutboundMulticast.hpp +++ b/node/OutboundMulticast.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_OUTBOUNDMULTICAST_HPP #define ZT_OUTBOUNDMULTICAST_HPP diff --git a/node/Packet.cpp b/node/Packet.cpp index 5d0885d3..25006416 100644 --- a/node/Packet.cpp +++ b/node/Packet.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include #include diff --git a/node/Packet.hpp b/node/Packet.hpp index fcb81489..53a1883c 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_N_PACKET_HPP #define ZT_N_PACKET_HPP diff --git a/node/Path.cpp b/node/Path.cpp index 2adb351c..e209e9c0 100644 --- a/node/Path.cpp +++ b/node/Path.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include "Path.hpp" #include "RuntimeEnvironment.hpp" diff --git a/node/Path.hpp b/node/Path.hpp index ed3e907f..c8beb970 100644 --- a/node/Path.hpp +++ b/node/Path.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_PATH_HPP #define ZT_PATH_HPP diff --git a/node/Peer.cpp b/node/Peer.cpp index 5f5d1462..c70e89d7 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include "../version.h" #include "Constants.hpp" diff --git a/node/Peer.hpp b/node/Peer.hpp index b4cbe057..525a7272 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_PEER_HPP #define ZT_PEER_HPP diff --git a/node/Poly1305.hpp b/node/Poly1305.hpp index 4614826e..936c7b4a 100644 --- a/node/Poly1305.hpp +++ b/node/Poly1305.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_POLY1305_HPP #define ZT_POLY1305_HPP diff --git a/node/Revocation.cpp b/node/Revocation.cpp index 04342569..6cc6c99d 100644 --- a/node/Revocation.cpp +++ b/node/Revocation.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include "Revocation.hpp" #include "RuntimeEnvironment.hpp" diff --git a/node/Revocation.hpp b/node/Revocation.hpp index 1d001a40..7fda5c66 100644 --- a/node/Revocation.hpp +++ b/node/Revocation.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_REVOCATION_HPP #define ZT_REVOCATION_HPP diff --git a/node/RingBuffer.hpp b/node/RingBuffer.hpp index 0f29a89a..2d6cd194 100644 --- a/node/RingBuffer.hpp +++ b/node/RingBuffer.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_RINGBUFFER_H #define ZT_RINGBUFFER_H @@ -40,7 +27,7 @@ namespace ZeroTier { * A circular buffer * * For fast handling of continuously-evolving variables (such as path quality metrics). - * Using this, we can maintain longer sliding historical windows for important path + * Using this, we can maintain longer sliding historical windows for important path * metrics without the need for potentially expensive calls to memcpy/memmove. * * Some basic statistical functionality is implemented here in an attempt @@ -73,7 +60,7 @@ public: return buf + begin; } - /** + /** * Adjust buffer index pointer as if we copied data in * @param n Number of elements to copy in * @return Number of elements we copied in @@ -96,13 +83,13 @@ public: return n; } - /** - * Fast erase, O(1). + /** + * Fast erase, O(1). * Merely reset the buffer pointer, doesn't erase contents */ inline void reset() { consume(count()); } - /** + /** * adjust buffer index pointer as if we copied data out * @param n Number of elements we copied from the buffer * @return Number of elements actually available from the buffer diff --git a/node/RuntimeEnvironment.hpp b/node/RuntimeEnvironment.hpp index e8ee4c59..07ab4333 100644 --- a/node/RuntimeEnvironment.hpp +++ b/node/RuntimeEnvironment.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_RUNTIMEENVIRONMENT_HPP #define ZT_RUNTIMEENVIRONMENT_HPP diff --git a/node/SHA512.hpp b/node/SHA512.hpp index cb7b40a8..676f35d5 100644 --- a/node/SHA512.hpp +++ b/node/SHA512.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_SHA512_HPP #define ZT_SHA512_HPP diff --git a/node/SelfAwareness.cpp b/node/SelfAwareness.cpp index 0fb9e4a4..f4684d82 100644 --- a/node/SelfAwareness.cpp +++ b/node/SelfAwareness.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include #include diff --git a/node/SelfAwareness.hpp b/node/SelfAwareness.hpp index 7940f5ac..0b7774b6 100644 --- a/node/SelfAwareness.hpp +++ b/node/SelfAwareness.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_SELFAWARENESS_HPP #define ZT_SELFAWARENESS_HPP diff --git a/node/SharedPtr.hpp b/node/SharedPtr.hpp index c7f9ea97..84b1d7b5 100644 --- a/node/SharedPtr.hpp +++ b/node/SharedPtr.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_SHAREDPTR_HPP #define ZT_SHAREDPTR_HPP diff --git a/node/Switch.cpp b/node/Switch.cpp index a6852d9f..60cd3a26 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include #include @@ -523,7 +510,7 @@ void Switch::aqm_enqueue(void *tPtr, const SharedPtr &network, Packet & // DEBUG_INFO("skipping, no QoS for this packet, verb=%x", packet.verb()); // just send packet normally, no QoS for ZT protocol traffic send(tPtr, packet, encrypt); - } + } _aqm_m.lock(); @@ -531,7 +518,7 @@ void Switch::aqm_enqueue(void *tPtr, const SharedPtr &network, Packet & const Address dest(packet.destination()); TXQueueEntry *txEntry = new TXQueueEntry(dest,RR->node->now(),packet,encrypt); - + ManagedQueue *selectedQueue = nullptr; for (size_t i=0; ioldQueues.size()) { // search old queues first (I think this is best since old would imply most recent usage of the queue) @@ -605,7 +592,7 @@ uint64_t Switch::control_law(uint64_t t, int count) return (uint64_t)(t + ZT_QOS_INTERVAL / sqrt(count)); } -Switch::dqr Switch::dodequeue(ManagedQueue *q, uint64_t now) +Switch::dqr Switch::dodequeue(ManagedQueue *q, uint64_t now) { dqr r; r.ok_to_drop = false; diff --git a/node/Switch.hpp b/node/Switch.hpp index a531b268..d1bf14eb 100644 --- a/node/Switch.hpp +++ b/node/Switch.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_N_SWITCH_HPP #define ZT_N_SWITCH_HPP diff --git a/node/Tag.cpp b/node/Tag.cpp index 6c78f3e4..69a17a28 100644 --- a/node/Tag.cpp +++ b/node/Tag.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include "Tag.hpp" #include "RuntimeEnvironment.hpp" diff --git a/node/Tag.hpp b/node/Tag.hpp index 3f888ba9..ada31b8f 100644 --- a/node/Tag.hpp +++ b/node/Tag.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_TAG_HPP #define ZT_TAG_HPP diff --git a/node/Topology.cpp b/node/Topology.cpp index 6d6beda3..46db4c94 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include "Constants.hpp" #include "Topology.hpp" diff --git a/node/Topology.hpp b/node/Topology.hpp index b6690f58..56d4591c 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_TOPOLOGY_HPP #define ZT_TOPOLOGY_HPP diff --git a/node/Trace.cpp b/node/Trace.cpp index cccab9c9..451c197c 100644 --- a/node/Trace.cpp +++ b/node/Trace.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ //#define ZT_TRACE diff --git a/node/Trace.hpp b/node/Trace.hpp index 2effb7f0..71169ebb 100644 --- a/node/Trace.hpp +++ b/node/Trace.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_TRACE_HPP #define ZT_TRACE_HPP diff --git a/node/Utils.cpp b/node/Utils.cpp index 16d81f65..e714967a 100644 --- a/node/Utils.cpp +++ b/node/Utils.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include #include diff --git a/node/Utils.hpp b/node/Utils.hpp index 86db8b02..5ba5b035 100644 --- a/node/Utils.hpp +++ b/node/Utils.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_UTILS_HPP #define ZT_UTILS_HPP diff --git a/node/World.hpp b/node/World.hpp index 823d304d..3921f380 100644 --- a/node/World.hpp +++ b/node/World.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_WORLD_HPP #define ZT_WORLD_HPP diff --git a/one.cpp b/one.cpp index 89acaace..b229b98e 100644 --- a/one.cpp +++ b/one.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include #include diff --git a/osdep/Arp.cpp b/osdep/Arp.cpp index 86f047a8..43f7868d 100644 --- a/osdep/Arp.cpp +++ b/osdep/Arp.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include #include diff --git a/osdep/Arp.hpp b/osdep/Arp.hpp index 1a21a207..93a8450b 100644 --- a/osdep/Arp.hpp +++ b/osdep/Arp.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_ARP_HPP #define ZT_ARP_HPP diff --git a/osdep/BSDEthernetTap.cpp b/osdep/BSDEthernetTap.cpp index a1e7a945..ae4f2165 100644 --- a/osdep/BSDEthernetTap.cpp +++ b/osdep/BSDEthernetTap.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include #include diff --git a/osdep/BSDEthernetTap.hpp b/osdep/BSDEthernetTap.hpp index 5b1fe2dc..d99cebef 100644 --- a/osdep/BSDEthernetTap.hpp +++ b/osdep/BSDEthernetTap.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_BSDETHERNETTAP_HPP #define ZT_BSDETHERNETTAP_HPP diff --git a/osdep/Binder.hpp b/osdep/Binder.hpp index bf7aef28..660e6f0c 100644 --- a/osdep/Binder.hpp +++ b/osdep/Binder.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_BINDER_HPP #define ZT_BINDER_HPP diff --git a/osdep/BlockingQueue.hpp b/osdep/BlockingQueue.hpp index f8b79342..0a317288 100644 --- a/osdep/BlockingQueue.hpp +++ b/osdep/BlockingQueue.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_BLOCKINGQUEUE_HPP #define ZT_BLOCKINGQUEUE_HPP diff --git a/osdep/EthernetTap.cpp b/osdep/EthernetTap.cpp index 82290fc2..a293991e 100644 --- a/osdep/EthernetTap.cpp +++ b/osdep/EthernetTap.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include "EthernetTap.hpp" #include "OSUtils.hpp" diff --git a/osdep/EthernetTap.hpp b/osdep/EthernetTap.hpp index fc8fc848..26503de0 100644 --- a/osdep/EthernetTap.hpp +++ b/osdep/EthernetTap.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_ETHERNETTAP_HPP #define ZT_ETHERNETTAP_HPP diff --git a/osdep/Http.cpp b/osdep/Http.cpp index 1ab58836..9ff1a068 100644 --- a/osdep/Http.cpp +++ b/osdep/Http.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include #include diff --git a/osdep/Http.hpp b/osdep/Http.hpp index a277bc4e..d9cad4dc 100644 --- a/osdep/Http.hpp +++ b/osdep/Http.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_HTTP_HPP #define ZT_HTTP_HPP diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index 5ed49eef..06a87bdc 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include "../node/Constants.hpp" @@ -103,7 +90,7 @@ LinuxEthernetTap::LinuxEthernetTap( // ensure netlink connection is started (void)LinuxNetLink::getInstance(); - + OSUtils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid); Mutex::Lock _l(__tapCreateLock); // create only one tap at a time, globally diff --git a/osdep/LinuxEthernetTap.hpp b/osdep/LinuxEthernetTap.hpp index 1acecb4b..3660fb39 100644 --- a/osdep/LinuxEthernetTap.hpp +++ b/osdep/LinuxEthernetTap.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_LINUXETHERNETTAP_HPP #define ZT_LINUXETHERNETTAP_HPP diff --git a/osdep/LinuxNetLink.cpp b/osdep/LinuxNetLink.cpp index be6e22c3..8c2fc9d2 100644 --- a/osdep/LinuxNetLink.cpp +++ b/osdep/LinuxNetLink.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include "LinuxNetLink.hpp" @@ -88,7 +75,7 @@ LinuxNetLink::~LinuxNetLink() ::close(_fd); } -void LinuxNetLink::_setSocketTimeout(int fd, int seconds) +void LinuxNetLink::_setSocketTimeout(int fd, int seconds) { struct timeval tv; tv.tv_sec = seconds; @@ -161,7 +148,7 @@ int LinuxNetLink::_doRecv(int fd) nll = 0; break; } - + nll += rtn; _processMessage(nlp, nll); @@ -196,7 +183,7 @@ void LinuxNetLink::_processMessage(struct nlmsghdr *nlp, int nll) { for(; NLMSG_OK(nlp, nll); nlp=NLMSG_NEXT(nlp, nll)) { - switch(nlp->nlmsg_type) + switch(nlp->nlmsg_type) { case RTM_NEWLINK: _linkAdded(nlp); @@ -232,7 +219,7 @@ void LinuxNetLink::_ipAddressAdded(struct nlmsghdr *nlp) char local[40] = {0}; char label[40] = {0}; char bcast[40] = {0}; - + for(;RTA_OK(rtap, ifal); rtap=RTA_NEXT(rtap,ifal)) { switch(rtap->rta_type) { @@ -653,7 +640,7 @@ void LinuxNetLink::addRoute(const InetAddress &target, const InetAddress &via, c if(src.isV4()) { rtap->rta_len = RTA_LENGTH(sizeof(struct in_addr)); memcpy(RTA_DATA(rtap), &((struct sockaddr_in*)&src)->sin_addr, sizeof(struct in_addr)); - + } else { rtap->rta_len = RTA_LENGTH(sizeof(struct in6_addr)); memcpy(RTA_DATA(rtap), &((struct sockaddr_in6*)&src)->sin6_addr, sizeof(struct in6_addr)); @@ -768,7 +755,7 @@ void LinuxNetLink::delRoute(const InetAddress &target, const InetAddress &via, c if(src.isV4()) { rtap->rta_len = RTA_LENGTH(sizeof(struct in_addr)); memcpy(RTA_DATA(rtap), &((struct sockaddr_in*)&src)->sin_addr, sizeof(struct in_addr)); - + } else { rtap->rta_len = RTA_LENGTH(sizeof(struct in6_addr)); memcpy(RTA_DATA(rtap), &((struct sockaddr_in6*)&src)->sin6_addr, sizeof(struct in6_addr)); @@ -864,7 +851,7 @@ void LinuxNetLink::addAddress(const InetAddress &addr, const char *iface) close(fd); return; } - + int rtl = sizeof(struct ifaddrmsg); struct nl_adr_req req; bzero(&req, sizeof(struct nl_adr_req)); @@ -976,7 +963,7 @@ void LinuxNetLink::removeAddress(const InetAddress &addr, const char *iface) close(fd); return; } - + int rtl = sizeof(struct ifaddrmsg); struct nl_adr_req req; bzero(&req, sizeof(struct nl_adr_req)); @@ -1052,7 +1039,7 @@ void LinuxNetLink::removeAddress(const InetAddress &addr, const char *iface) close(fd); } -RouteList LinuxNetLink::getIPV4Routes() const +RouteList LinuxNetLink::getIPV4Routes() const { return _routes_ipv4; } diff --git a/osdep/LinuxNetLink.hpp b/osdep/LinuxNetLink.hpp index b0bf24b3..70cd14e7 100644 --- a/osdep/LinuxNetLink.hpp +++ b/osdep/LinuxNetLink.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_LINUX_NETLINK_HPP #define ZT_LINUX_NETLINK_HPP @@ -53,7 +40,7 @@ struct route_entry { typedef std::vector RouteList; /** - * Interface with Linux's RTNETLINK + * Interface with Linux's RTNETLINK */ class LinuxNetLink { @@ -122,7 +109,7 @@ private: // socket communication vars; int _fd; struct sockaddr_nl _la; -}; +}; } diff --git a/osdep/MacEthernetTap.cpp b/osdep/MacEthernetTap.cpp index 237df470..028f8556 100644 --- a/osdep/MacEthernetTap.cpp +++ b/osdep/MacEthernetTap.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include "../node/Constants.hpp" diff --git a/osdep/MacEthernetTap.hpp b/osdep/MacEthernetTap.hpp index 2eef59be..6d5ce894 100644 --- a/osdep/MacEthernetTap.hpp +++ b/osdep/MacEthernetTap.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_OSXETHERNETTAP_HPP #define ZT_OSXETHERNETTAP_HPP diff --git a/osdep/MacEthernetTapAgent.c b/osdep/MacEthernetTapAgent.c index b5ad1f62..a58a8d70 100644 --- a/osdep/MacEthernetTapAgent.c +++ b/osdep/MacEthernetTapAgent.c @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ /* * This creates a pair of feth devices with the lower numbered device @@ -30,10 +17,10 @@ * used to actually read and write packets. The latter gets no IP config * and is only used for I/O. The behavior of feth is similar to the * veth pairs that exist on Linux. - * + * * The feth device has only existed since MacOS Sierra, but that's fairly * long ago in Mac terms. - * + * * I/O with feth must be done using two different sockets. The BPF socket * is used to receive packets, while an AF_NDRV (low-level network driver * access) socket must be used to inject. AF_NDRV can't read IP frames @@ -41,20 +28,20 @@ * been handled, and while BPF can inject its MTU for injected packets * is limited to 2048. AF_NDRV packet injection is required to inject * ZeroTier's large MTU frames. - * + * * Benchmarks show that this performs similarly to the old tap.kext driver, * and a kext is no longer required. Splitting it off into an agent will * also make it easier to have zerotier-one itself drop permissions. - * + * * All this stuff is basically undocumented. A lot of tracing through * the Darwin/XNU kernel source was required to figure out how to make * this actually work. - * + * * See also: - * + * * https://apple.stackexchange.com/questions/337715/fake-ethernet-interfaces-feth-if-fake-anyone-ever-seen-this * https://opensource.apple.com/source/xnu/xnu-4570.41.2/bsd/net/if_fake.c.auto.html - * + * */ #include diff --git a/osdep/MacEthernetTapAgent.h b/osdep/MacEthernetTapAgent.h index f6459523..2c891c36 100644 --- a/osdep/MacEthernetTapAgent.h +++ b/osdep/MacEthernetTapAgent.h @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_MACETHERNETTAPAGENT_H #define ZT_MACETHERNETTAPAGENT_H diff --git a/osdep/MacKextEthernetTap.cpp b/osdep/MacKextEthernetTap.cpp index 4f0520a6..2325d594 100644 --- a/osdep/MacKextEthernetTap.cpp +++ b/osdep/MacKextEthernetTap.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include #include diff --git a/osdep/MacKextEthernetTap.hpp b/osdep/MacKextEthernetTap.hpp index fbf2694b..f1a6f36f 100644 --- a/osdep/MacKextEthernetTap.hpp +++ b/osdep/MacKextEthernetTap.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_MacKextEthernetTap_HPP #define ZT_MacKextEthernetTap_HPP diff --git a/osdep/ManagedRoute.cpp b/osdep/ManagedRoute.cpp index 56e7b094..a5dc5b3c 100644 --- a/osdep/ManagedRoute.cpp +++ b/osdep/ManagedRoute.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include "../node/Constants.hpp" diff --git a/osdep/ManagedRoute.hpp b/osdep/ManagedRoute.hpp index e1a43c26..d1f60d3f 100644 --- a/osdep/ManagedRoute.hpp +++ b/osdep/ManagedRoute.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_MANAGEDROUTE_HPP #define ZT_MANAGEDROUTE_HPP diff --git a/osdep/NeighborDiscovery.cpp b/osdep/NeighborDiscovery.cpp index 134bd246..21c02b48 100644 --- a/osdep/NeighborDiscovery.cpp +++ b/osdep/NeighborDiscovery.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include "NeighborDiscovery.hpp" #include "OSUtils.hpp" @@ -32,7 +19,7 @@ #include namespace ZeroTier { - + uint16_t calc_checksum (uint16_t *addr, int len) { int count = len; @@ -56,10 +43,10 @@ uint16_t calc_checksum (uint16_t *addr, int len) while (sum >> 16) { sum = (sum & 0xffff) + (sum >> 16); } - + // Checksum is one's compliment of sum. answer = ~sum; - + return (answer); } @@ -78,14 +65,14 @@ struct _option { { memset(mac, 0, sizeof(mac)); } - + uint8_t type; uint8_t length; uint8_t mac[6]; }; struct _neighbor_solicitation { - _neighbor_solicitation() + _neighbor_solicitation() : type(135) , code(0) , checksum(0) diff --git a/osdep/NeighborDiscovery.hpp b/osdep/NeighborDiscovery.hpp index b660068a..5abf3129 100644 --- a/osdep/NeighborDiscovery.hpp +++ b/osdep/NeighborDiscovery.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_NEIGHBORDISCOVERY_HPP #define ZT_NEIGHBORDISCOVERY_HPP diff --git a/osdep/NetBSDEthernetTap.cpp b/osdep/NetBSDEthernetTap.cpp index 027f2ec3..1c0f017c 100644 --- a/osdep/NetBSDEthernetTap.cpp +++ b/osdep/NetBSDEthernetTap.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include #include diff --git a/osdep/NetBSDEthernetTap.hpp b/osdep/NetBSDEthernetTap.hpp index a174816e..534712e4 100644 --- a/osdep/NetBSDEthernetTap.hpp +++ b/osdep/NetBSDEthernetTap.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_NetBSDEthernetTap_HPP #define ZT_NetBSDEthernetTap_HPP diff --git a/osdep/OSUtils.cpp b/osdep/OSUtils.cpp index 83c615de..0299b12b 100644 --- a/osdep/OSUtils.cpp +++ b/osdep/OSUtils.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include #include diff --git a/osdep/OSUtils.hpp b/osdep/OSUtils.hpp index afdb1bf1..172575a0 100644 --- a/osdep/OSUtils.hpp +++ b/osdep/OSUtils.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_OSUTILS_HPP #define ZT_OSUTILS_HPP diff --git a/osdep/Phy.hpp b/osdep/Phy.hpp index 333e5c24..b65a520e 100644 --- a/osdep/Phy.hpp +++ b/osdep/Phy.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_PHY_HPP #define ZT_PHY_HPP diff --git a/osdep/PortMapper.cpp b/osdep/PortMapper.cpp index 6b2409b6..caad3ed4 100644 --- a/osdep/PortMapper.cpp +++ b/osdep/PortMapper.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #ifdef ZT_USE_MINIUPNPC diff --git a/osdep/PortMapper.hpp b/osdep/PortMapper.hpp index a075b774..be2c6468 100644 --- a/osdep/PortMapper.hpp +++ b/osdep/PortMapper.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #ifdef ZT_USE_MINIUPNPC diff --git a/osdep/Thread.hpp b/osdep/Thread.hpp index 4d32ce86..4cd56994 100644 --- a/osdep/Thread.hpp +++ b/osdep/Thread.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_THREAD_HPP #define ZT_THREAD_HPP diff --git a/osdep/WindowsEthernetTap.cpp b/osdep/WindowsEthernetTap.cpp index 773c56c1..fb4b498d 100644 --- a/osdep/WindowsEthernetTap.cpp +++ b/osdep/WindowsEthernetTap.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include #include diff --git a/osdep/WindowsEthernetTap.hpp b/osdep/WindowsEthernetTap.hpp index 7a863875..ea08b2fc 100644 --- a/osdep/WindowsEthernetTap.hpp +++ b/osdep/WindowsEthernetTap.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_WINDOWSETHERNETTAP_HPP #define ZT_WINDOWSETHERNETTAP_HPP diff --git a/rule-compiler/rule-compiler.js b/rule-compiler/rule-compiler.js index 6e21c2dc..f9b3aafa 100644 --- a/rule-compiler/rule-compiler.js +++ b/rule-compiler/rule-compiler.js @@ -1,3 +1,16 @@ +/* + * Copyright (c)2019 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: 2023-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. + */ +/****/ + 'use strict'; // Names for bits in characteristics -- 0==LSB, 63==MSB diff --git a/selftest.cpp b/selftest.cpp index 77c06cc0..115bc4cb 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include #include diff --git a/service/OneService.cpp b/service/OneService.cpp index 93e97bde..77b60b37 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include #include @@ -925,7 +912,7 @@ public: } void readLocalSettings() - { + { // Read local configuration std::map ppc; diff --git a/service/OneService.hpp b/service/OneService.hpp index e5125676..53bbe2b8 100644 --- a/service/OneService.hpp +++ b/service/OneService.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_ONESERVICE_HPP #define ZT_ONESERVICE_HPP diff --git a/service/SoftwareUpdater.cpp b/service/SoftwareUpdater.cpp index df3d89c2..5800f860 100644 --- a/service/SoftwareUpdater.cpp +++ b/service/SoftwareUpdater.cpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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. */ +/****/ #include #include diff --git a/service/SoftwareUpdater.hpp b/service/SoftwareUpdater.hpp index 1fab7740..24a2bc72 100644 --- a/service/SoftwareUpdater.hpp +++ b/service/SoftwareUpdater.hpp @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 ZT_SOFTWAREUPDATER_HPP #define ZT_SOFTWAREUPDATER_HPP diff --git a/version.h b/version.h index 10678793..7c175456 100644 --- a/version.h +++ b/version.h @@ -1,28 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. + * 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 _ZT_VERSION_H #define _ZT_VERSION_H @@ -40,7 +27,7 @@ /** * Revision */ -#define ZEROTIER_ONE_VERSION_REVISION 2 +#define ZEROTIER_ONE_VERSION_REVISION 4 /** * Build version diff --git a/windows/ZeroTierOne/ZeroTierOneService.cpp b/windows/ZeroTierOne/ZeroTierOneService.cpp index 8e0b9c34..c2d74fa1 100644 --- a/windows/ZeroTierOne/ZeroTierOneService.cpp +++ b/windows/ZeroTierOne/ZeroTierOneService.cpp @@ -1,20 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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. */ +/****/ #pragma region Includes diff --git a/windows/ZeroTierOne/ZeroTierOneService.h b/windows/ZeroTierOne/ZeroTierOneService.h index 9c23d0f5..142dd8af 100644 --- a/windows/ZeroTierOne/ZeroTierOneService.h +++ b/windows/ZeroTierOne/ZeroTierOneService.h @@ -1,20 +1,15 @@ /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (c)2019 ZeroTier, Inc. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Change Date: 2023-01-01 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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. */ +/****/ #pragma once From e8ae3334433216a43ba772f5b96350a29a92190f Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 23 Aug 2019 10:15:13 -0700 Subject: [PATCH 133/185] Version bumps, license fixed, and GitHub issue #990 take two --- debian/changelog | 7 +++++++ debian/copyright | 28 +++++++++++----------------- node/Membership.hpp | 34 ++++++++++++++++++++++++++++++++-- zerotier-one.spec | 7 +++++-- 4 files changed, 55 insertions(+), 21 deletions(-) diff --git a/debian/changelog b/debian/changelog index 0bf2307a..8dedcfe9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +zerotier-one (1.4.4) unstable; urgency=medium + + * See https://github.com/zerotier/ZeroTierOne for release notes. + * License changed to BSL 1.1 + + -- Adam Ierymenko Thu, 23 Aug 2019 01:00:00 -0700 + zerotier-one (1.4.2-2) unstable; urgency=medium * See https://github.com/zerotier/ZeroTierOne for release notes. diff --git a/debian/copyright b/debian/copyright index cd728a0d..493e6a27 100644 --- a/debian/copyright +++ b/debian/copyright @@ -4,21 +4,15 @@ Source: https://github.com/zerotier/ZeroTierOne Files: * Copyright: 2011-2016 ZeroTier, Inc. -License: GPL-3.0+ +License: ZeroTier BSL 1.1 -License: GPL-3.0+ - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - . - This package is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - . - You should have received a copy of the GNU General Public License - along with this program. If not, see . - . - On Debian systems, the complete text of the GNU General - Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". +License: ZeroTier BSL 1.1 + Copyright (c)2019 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: 2023-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. diff --git a/node/Membership.hpp b/node/Membership.hpp index f3e6d720..e9fbd540 100644 --- a/node/Membership.hpp +++ b/node/Membership.hpp @@ -181,8 +181,38 @@ private: inline bool _isV6NDPEmulated(const NetworkConfig &nconf,const MAC &m) const { return false; } inline bool _isV6NDPEmulated(const NetworkConfig &nconf,const InetAddress &ip) const { - if ((ip.isV6())&&(nconf.ndpEmulation())&&((InetAddress::makeIpv66plane(nconf.networkId,nconf.issuedTo.toInt()).ipsEqual(ip))||(InetAddress::makeIpv6rfc4193(nconf.networkId,nconf.issuedTo.toInt()).ipsEqual(ip)))) { - return true; + if ((ip.isV6())&&(nconf.ndpEmulation())) { + const InetAddress sixpl(InetAddress::makeIpv66plane(nconf.networkId,nconf.issuedTo.toInt())); + for(int i=0;isin6_addr.s6_addr)[j] != (((const struct sockaddr_in6 *)&sixpl)->sin6_addr.s6_addr)[j]) { + prefixMatches = false; + break; + } + } + if (prefixMatches) + return true; + break; + } + } + + const InetAddress rfc4193(InetAddress::makeIpv6rfc4193(nconf.networkId,nconf.issuedTo.toInt())); + for(int i=0;isin6_addr.s6_addr)[j] != (((const struct sockaddr_in6 *)&rfc4193)->sin6_addr.s6_addr)[j]) { + prefixMatches = false; + break; + } + } + if (prefixMatches) + return true; + break; + } + } } return false; } diff --git a/zerotier-one.spec b/zerotier-one.spec index 6649e653..d0daacf1 100644 --- a/zerotier-one.spec +++ b/zerotier-one.spec @@ -1,9 +1,9 @@ Name: zerotier-one -Version: 1.4.2 +Version: 1.4.4 Release: 2%{?dist} Summary: ZeroTier One network virtualization service -License: GPLv3 +License: ZeroTier BSL 1.1 URL: https://www.zerotier.com %if 0%{?rhel} >= 7 @@ -145,6 +145,9 @@ esac %endif %changelog +* Mon Aug 23 2019 Adam Ierymenko - 1.4.4-0.1 +- see https://github.com/zerotier/ZeroTierOne for release notes + * Mon Aug 04 2019 Adam Ierymenko - 1.4.2-0.1 - see https://github.com/zerotier/ZeroTierOne for release notes From 2f74bd5150569ea4251cd699f5cb249c59ffe530 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 23 Aug 2019 10:19:59 -0700 Subject: [PATCH 134/185] Add "make docker" for GitHub issue #1013 --- docker/Dockerfile | 8 ++++---- make-linux.mk | 6 +++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 0f0750c6..ae3eed6b 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -4,11 +4,11 @@ MAINTAINER Adam Ierymekno , Grant Limberg Date: Fri, 23 Aug 2019 10:31:12 -0700 Subject: [PATCH 135/185] Tolerate any libstdc++6 package "version" for Mint and other distros with weird versions on libstdc++6. --- debian/control | 2 +- debian/control.wheezy | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/control b/debian/control index 1eb147e0..910334c4 100644 --- a/debian/control +++ b/debian/control @@ -10,7 +10,7 @@ Homepage: https://www.zerotier.com/ Package: zerotier-one Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, iproute2, adduser, libstdc++6 +Depends: ${shlibs:Depends}, ${misc:Depends}, iproute2, adduser, libstdc++6 (>= 1) Homepage: https://www.zerotier.com/ Description: ZeroTier network virtualization service ZeroTier One lets you join ZeroTier virtual networks and diff --git a/debian/control.wheezy b/debian/control.wheezy index a8e24084..a5140ebf 100644 --- a/debian/control.wheezy +++ b/debian/control.wheezy @@ -10,7 +10,7 @@ Homepage: https://www.zerotier.com/ Package: zerotier-one Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, iproute, libstdc++6 +Depends: ${shlibs:Depends}, ${misc:Depends}, iproute, libstdc++6 (>= 1) Homepage: https://www.zerotier.com/ Description: ZeroTier network virtualization service ZeroTier One lets you join ZeroTier virtual networks and From 51ebefc3ab1f377caf16e483d3a6c7b9ac8bb29f Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 23 Aug 2019 10:34:37 -0700 Subject: [PATCH 136/185] Ifdef these to stop non-Windows IDEs from complaining. --- windows/ZeroTierOne/ZeroTierOneService.cpp | 4 ++++ windows/ZeroTierOne/ZeroTierOneService.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/windows/ZeroTierOne/ZeroTierOneService.cpp b/windows/ZeroTierOne/ZeroTierOneService.cpp index c2d74fa1..9b274d34 100644 --- a/windows/ZeroTierOne/ZeroTierOneService.cpp +++ b/windows/ZeroTierOne/ZeroTierOneService.cpp @@ -13,6 +13,8 @@ #pragma region Includes +#if defined(_WIN32) || defined(_WIN64) + #include #include #include @@ -150,3 +152,5 @@ void ZeroTierOneService::OnShutdown() // stop thread on system shutdown (if it hasn't happened already) OnStop(); } + +#endif diff --git a/windows/ZeroTierOne/ZeroTierOneService.h b/windows/ZeroTierOne/ZeroTierOneService.h index 142dd8af..dbcd8c6d 100644 --- a/windows/ZeroTierOne/ZeroTierOneService.h +++ b/windows/ZeroTierOne/ZeroTierOneService.h @@ -13,6 +13,8 @@ #pragma once +#if defined(_WIN32) || defined(_WIN64) + #include #include "ServiceBase.h" @@ -64,3 +66,5 @@ private: ZeroTier::Mutex _lock; ZeroTier::Thread _thread; }; + +#endif From 43e98930e9d4652bfc1ca0afba7ced71923f0466 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 23 Aug 2019 11:12:25 -0700 Subject: [PATCH 137/185] distro cleanup --- debian/changelog | 2 +- debian/control | 4 ++-- zerotier-one.spec | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/debian/changelog b/debian/changelog index 8dedcfe9..83ae0c1d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -3,7 +3,7 @@ zerotier-one (1.4.4) unstable; urgency=medium * See https://github.com/zerotier/ZeroTierOne for release notes. * License changed to BSL 1.1 - -- Adam Ierymenko Thu, 23 Aug 2019 01:00:00 -0700 + -- Adam Ierymenko Fri, 23 Aug 2019 01:00:00 -0700 zerotier-one (1.4.2-2) unstable; urgency=medium diff --git a/debian/control b/debian/control index 910334c4..52f8daea 100644 --- a/debian/control +++ b/debian/control @@ -10,8 +10,8 @@ Homepage: https://www.zerotier.com/ Package: zerotier-one Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, iproute2, adduser, libstdc++6 (>= 1) -Homepage: https://www.zerotier.com/ +Depends: ${shlibs:Depends}, ${misc:Depends}, iproute2, adduser, libstdc++6 +apt-caHomepage: https://www.zerotier.com/ Description: ZeroTier network virtualization service ZeroTier One lets you join ZeroTier virtual networks and have them appear as tun/tap ports on your system. See diff --git a/zerotier-one.spec b/zerotier-one.spec index d0daacf1..ccec532a 100644 --- a/zerotier-one.spec +++ b/zerotier-one.spec @@ -145,7 +145,7 @@ esac %endif %changelog -* Mon Aug 23 2019 Adam Ierymenko - 1.4.4-0.1 +* Fri Aug 23 2019 Adam Ierymenko - 1.4.4-0.1 - see https://github.com/zerotier/ZeroTierOne for release notes * Mon Aug 04 2019 Adam Ierymenko - 1.4.2-0.1 From 6f9e3e3b787afc9be4223d94d3d98339fd9d4c6d Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 23 Aug 2019 11:14:17 -0700 Subject: [PATCH 138/185] Back out unnecessary hack --- debian/control.wheezy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control.wheezy b/debian/control.wheezy index a5140ebf..a8e24084 100644 --- a/debian/control.wheezy +++ b/debian/control.wheezy @@ -10,7 +10,7 @@ Homepage: https://www.zerotier.com/ Package: zerotier-one Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, iproute, libstdc++6 (>= 1) +Depends: ${shlibs:Depends}, ${misc:Depends}, iproute, libstdc++6 Homepage: https://www.zerotier.com/ Description: ZeroTier network virtualization service ZeroTier One lets you join ZeroTier virtual networks and From de0a5aa8402523fc152495ba647974a8cb06c0e8 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 23 Aug 2019 12:09:31 -0700 Subject: [PATCH 139/185] GitHub issue #994 --- osdep/LinuxNetLink.cpp | 22 ++++++++++++++-------- osdep/LinuxNetLink.hpp | 6 ++++++ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/osdep/LinuxNetLink.cpp b/osdep/LinuxNetLink.cpp index 8c2fc9d2..13e7176e 100644 --- a/osdep/LinuxNetLink.cpp +++ b/osdep/LinuxNetLink.cpp @@ -11,6 +11,10 @@ */ /****/ +#include "../node/Constants.hpp" + +#ifdef __LINUX__ + #include "LinuxNetLink.hpp" #include @@ -53,7 +57,7 @@ LinuxNetLink::LinuxNetLink() _setSocketTimeout(_fd, 1); _la.nl_family = AF_NETLINK; - _la.nl_pid = getpid()+1; + _la.nl_pid = 0; //getpid()+1; _la.nl_groups = RTMGRP_LINK|RTMGRP_IPV4_IFADDR|RTMGRP_IPV6_IFADDR|RTMGRP_IPV4_ROUTE|RTMGRP_IPV6_ROUTE|RTMGRP_NOTIFY; if (bind(_fd, (struct sockaddr*)&_la, sizeof(_la))) { fprintf(stderr, "Error connecting to RTNETLINK: %s\n", strerror(errno)); @@ -433,7 +437,7 @@ void LinuxNetLink::_requestIPv4Routes() struct sockaddr_nl la; la.nl_family = AF_NETLINK; - la.nl_pid = getpid(); + la.nl_pid = 0; //getpid(); la.nl_groups = RTMGRP_IPV4_ROUTE; if(bind(fd, (struct sockaddr*)&la, sizeof(la))) { fprintf(stderr, "Error binding RTNETLINK (_requiestIPv4Routes #1): %s\n", strerror(errno)); @@ -486,7 +490,7 @@ void LinuxNetLink::_requestIPv6Routes() struct sockaddr_nl la; la.nl_family = AF_NETLINK; - la.nl_pid = getpid(); + la.nl_pid = 0; //getpid(); la.nl_groups = RTMGRP_IPV6_ROUTE; if(bind(fd, (struct sockaddr*)&la, sizeof(struct sockaddr_nl))) { fprintf(stderr, "Error binding RTNETLINK (_requestIPv6Routes #1): %s\n", strerror(errno)); @@ -539,7 +543,7 @@ void LinuxNetLink::_requestInterfaceList() struct sockaddr_nl la; la.nl_family = AF_NETLINK; - la.nl_pid = getpid(); + la.nl_pid = 0; //getpid(); la.nl_groups = RTMGRP_LINK; if(bind(fd, (struct sockaddr*)&la, sizeof(struct sockaddr_nl))) { fprintf(stderr, "Error binding RTNETLINK (_requestInterfaceList #1): %s\n", strerror(errno)); @@ -593,7 +597,7 @@ void LinuxNetLink::addRoute(const InetAddress &target, const InetAddress &via, c struct sockaddr_nl la; bzero(&la, sizeof(la)); la.nl_family = AF_NETLINK; - la.nl_pid = getpid(); + la.nl_pid = 0; //getpid(); if(bind(fd, (struct sockaddr*)&la, sizeof(struct sockaddr_nl))) { fprintf(stderr, "Error binding RTNETLINK (addRoute #1): %s\n", strerror(errno)); @@ -708,7 +712,7 @@ void LinuxNetLink::delRoute(const InetAddress &target, const InetAddress &via, c struct sockaddr_nl la; la.nl_family = AF_NETLINK; - la.nl_pid = getpid(); + la.nl_pid = 0; //getpid(); if(bind(fd, (struct sockaddr*)&la, sizeof(struct sockaddr_nl))) { fprintf(stderr, "Error binding RTNETLINK (delRoute #1): %s\n", strerror(errno)); @@ -822,7 +826,7 @@ void LinuxNetLink::addAddress(const InetAddress &addr, const char *iface) struct sockaddr_nl la; memset(&la,0,sizeof(la)); la.nl_family = AF_NETLINK; - la.nl_pid = getpid(); + la.nl_pid = 0; //getpid(); if (addr.isV4()) { la.nl_groups = RTMGRP_IPV4_IFADDR; } else { @@ -939,7 +943,7 @@ void LinuxNetLink::removeAddress(const InetAddress &addr, const char *iface) struct sockaddr_nl la; la.nl_family = AF_NETLINK; - la.nl_pid = getpid(); + la.nl_pid = 0; //getpid(); if (addr.isV4()) { la.nl_groups = RTMGRP_IPV4_IFADDR; } else { @@ -1066,3 +1070,5 @@ int LinuxNetLink::_indexForInterface(const char *iface) } } // namespace ZeroTier + +#endif diff --git a/osdep/LinuxNetLink.hpp b/osdep/LinuxNetLink.hpp index 70cd14e7..01bde04b 100644 --- a/osdep/LinuxNetLink.hpp +++ b/osdep/LinuxNetLink.hpp @@ -14,6 +14,10 @@ #ifndef ZT_LINUX_NETLINK_HPP #define ZT_LINUX_NETLINK_HPP +#include "../node/Constants.hpp" + +#ifdef __LINUX__ + #include #include @@ -113,4 +117,6 @@ private: } +#endif + #endif // ZT_LINUX_NETLINK_HPPS \ No newline at end of file From d214a5437f160700021cf8e9ca2f090e19c385da Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 23 Aug 2019 15:24:52 -0700 Subject: [PATCH 140/185] Bump Mac pkg version --- ext/installfiles/mac/ZeroTier One.pkgproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/installfiles/mac/ZeroTier One.pkgproj b/ext/installfiles/mac/ZeroTier One.pkgproj index 2bd19123..948070cc 100755 --- a/ext/installfiles/mac/ZeroTier One.pkgproj +++ b/ext/installfiles/mac/ZeroTier One.pkgproj @@ -717,7 +717,7 @@ USE_HFS+_COMPRESSION VERSION - 1.4.2 + 1.4.4
TYPE 0 From 25a48f2f44e81690a6a652c960a09606a3cdfc20 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 23 Aug 2019 21:24:05 -0700 Subject: [PATCH 141/185] Fix RedHat sub-version. --- zerotier-one.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zerotier-one.spec b/zerotier-one.spec index ccec532a..eb13e679 100644 --- a/zerotier-one.spec +++ b/zerotier-one.spec @@ -1,6 +1,6 @@ Name: zerotier-one Version: 1.4.4 -Release: 2%{?dist} +Release: 1%{?dist} Summary: ZeroTier One network virtualization service License: ZeroTier BSL 1.1 From 633cf9ec04a60e8b0aa7a9a2911e35564d61d481 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 23 Aug 2019 21:28:26 -0700 Subject: [PATCH 142/185] Warning removal --- node/Membership.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/node/Membership.hpp b/node/Membership.hpp index e9fbd540..caff957b 100644 --- a/node/Membership.hpp +++ b/node/Membership.hpp @@ -183,10 +183,10 @@ private: { if ((ip.isV6())&&(nconf.ndpEmulation())) { const InetAddress sixpl(InetAddress::makeIpv66plane(nconf.networkId,nconf.issuedTo.toInt())); - for(int i=0;isin6_addr.s6_addr)[j] != (((const struct sockaddr_in6 *)&sixpl)->sin6_addr.s6_addr)[j]) { prefixMatches = false; break; @@ -199,10 +199,10 @@ private: } const InetAddress rfc4193(InetAddress::makeIpv6rfc4193(nconf.networkId,nconf.issuedTo.toInt())); - for(int i=0;isin6_addr.s6_addr)[j] != (((const struct sockaddr_in6 *)&rfc4193)->sin6_addr.s6_addr)[j]) { prefixMatches = false; break; From 05470bf202efb4647162863e577592c606ec6fd7 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 23 Aug 2019 21:38:04 -0700 Subject: [PATCH 143/185] Fix RPM targets --- make-linux.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make-linux.mk b/make-linux.mk index 6fdfb8a4..32972662 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -403,7 +403,7 @@ debian-clean: FORCE rm -rf debian/files debian/zerotier-one*.debhelper debian/zerotier-one.substvars debian/*.log debian/zerotier-one debian/.debhelper debian/debhelper-build-stamp redhat: FORCE - rpmbuild -ba zerotier-one.spec + rpmbuild --target `rpm -q bash --qf "%{arch}"` -ba zerotier-one.spec # This installs the packages needed to build ZT locally on CentOS 7 and # is here largely for documentation purposes. From 609873e6d1eb7f892ee2365939371cd42488c01b Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 23 Aug 2019 22:10:15 -0700 Subject: [PATCH 144/185] Windows version bump --- ext/installfiles/windows/ZeroTier One.aip | 8 ++++---- windows/WinUI/AboutView.xaml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ext/installfiles/windows/ZeroTier One.aip b/ext/installfiles/windows/ZeroTier One.aip index 1694f87f..83b07c25 100644 --- a/ext/installfiles/windows/ZeroTier One.aip +++ b/ext/installfiles/windows/ZeroTier One.aip @@ -27,10 +27,10 @@ - + - + @@ -64,7 +64,7 @@
- + @@ -454,7 +454,7 @@ - + diff --git a/windows/WinUI/AboutView.xaml b/windows/WinUI/AboutView.xaml index 43dca4c0..3e7b2bd6 100644 --- a/windows/WinUI/AboutView.xaml +++ b/windows/WinUI/AboutView.xaml @@ -19,7 +19,7 @@
- + From 91b16310ea47a6de96edb488a61494f8ed8c139c Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 26 Aug 2019 10:33:26 -0700 Subject: [PATCH 145/185] * Change license from GPL3 to BSL 1.1, see LICENSE.txt * Fix an issue with the "ipauth" rule and auto-generated unforgeable IPv6 addresses * Fix socket/bind errors setting IPs and routes on Linux --- RELEASE-NOTES.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 3b0902cb..5b6d24b7 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -3,8 +3,9 @@ ZeroTier Release Notes # 2019-08-23 -- Version 1.4.4 - * Change license to BSL 1.1, see LICENSE.txt + * Change license from GPL3 to BSL 1.1, see LICENSE.txt * Fix an issue with the "ipauth" rule and auto-generated unforgeable IPv6 addresses + * Fix socket/bind errors setting IPs and routes on Linux # 2019-08-12 -- Version 1.4.2 From ca896952706bfbe46b6cf7f8224d0e5a218e507d Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 26 Aug 2019 12:19:50 -0700 Subject: [PATCH 146/185] Fix make central-controller-docker --- ext/central-controller-docker/Dockerfile | 19 ++++++ ext/central-controller-docker/main.sh | 80 ++++++++++++++++++++++++ make-linux.mk | 2 +- 3 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 ext/central-controller-docker/Dockerfile create mode 100755 ext/central-controller-docker/main.sh diff --git a/ext/central-controller-docker/Dockerfile b/ext/central-controller-docker/Dockerfile new file mode 100644 index 00000000..2fc92e6f --- /dev/null +++ b/ext/central-controller-docker/Dockerfile @@ -0,0 +1,19 @@ +# Dockerfile for ZeroTier Central Controllers +FROM centos:7 +MAINTAINER Adam Ierymekno , Grant Limberg + +RUN yum update -y +RUN yum install -y https://download.postgresql.org/pub/repos/yum/10/redhat/rhel-7-x86_64/pgdg-centos10-10-2.noarch.rpm +RUN yum install -y bash postgresql10 libpqxx-devel + +RUN yum -y install epel-release && yum -y update && yum clean all +RUN yum -y install clang jemalloc jemalloc-devel + + +ADD zerotier-one /usr/local/bin/zerotier-one +RUN chmod a+x /usr/local/bin/zerotier-one + +ADD docker/main.sh / +RUN chmod a+x /main.sh + +ENTRYPOINT /main.sh diff --git a/ext/central-controller-docker/main.sh b/ext/central-controller-docker/main.sh new file mode 100755 index 00000000..b8d3b142 --- /dev/null +++ b/ext/central-controller-docker/main.sh @@ -0,0 +1,80 @@ +#!/bin/bash + +if [ -z "$ZT_IDENTITY_PATH" ]; then + echo '*** FAILED: ZT_IDENTITY_PATH environment variable is not defined' + exit 1 +fi +if [ -z "$ZT_DB_HOST" ]; then + echo '*** FAILED: ZT_DB_HOST environment variable not defined' + exit 1 +fi +if [ -z "$ZT_DB_PORT" ]; then + echo '*** FAILED: ZT_DB_PORT environment variable not defined' + exit 1 +fi +if [ -z "$ZT_DB_NAME" ]; then + echo '*** FAILED: ZT_DB_NAME environment variable not defined' + exit 1 +fi +if [ -z "$ZT_DB_USER" ]; then + echo '*** FAILED: ZT_DB_USER environment variable not defined' + exit 1 +fi +if [ -z "$ZT_DB_PASSWORD" ]; then + echo '*** FAILED: ZT_DB_PASSWORD environment variable not defined' + exit 1 +fi + +RMQ="" +if [ "$ZT_USE_RABBITMQ" == "true" ]; then + if [ -z "$RABBITMQ_HOST" ]; then + echo '*** FAILED: RABBITMQ_HOST environment variable not defined' + exit 1 + fi + if [ -z "$RABBITMQ_PORT" ]; then + echo '*** FAILED: RABBITMQ_PORT environment variable not defined' + exit 1 + fi + if [ -z "$RABBITMQ_USERNAME" ]; then + echo '*** FAILED: RABBITMQ_USERNAME environment variable not defined' + exit 1 + fi + if [ -z "$RABBITMQ_PASSWORD" ]; then + echo '*** FAILED: RABBITMQ_PASSWORD environment variable not defined' + exit 1 + fi + RMQ=", \"rabbitmq\": { + \"host\": \"${RABBITMQ_HOST}\", + \"port\": ${RABBITMQ_PORT}, + \"username\": \"${RABBITMQ_USERNAME}\", + \"password\": \"${RABBITMQ_PASSWORD}\" + }" +fi + +mkdir -p /var/lib/zerotier-one + +pushd /var/lib/zerotier-one +ln -s $ZT_IDENTITY_PATH/identity.public identity.public +ln -s $ZT_IDENTITY_PATH/identity.secret identity.secret +popd + +DEFAULT_PORT=9993 + +echo "{ + \"settings\": { + \"portMappingEnabled\": true, + \"softwareUpdate\": \"disable\", + \"interfacePrefixBlacklist\": [ + \"inot\", + \"nat64\" + ], + \"controllerDbPath\": \"postgres:host=${ZT_DB_HOST} port=${ZT_DB_PORT} dbname=${ZT_DB_NAME} user=${ZT_DB_USER} password=${ZT_DB_PASSWORD} sslmode=prefer sslcert=${DB_CLIENT_CERT} sslkey=${DB_CLIENT_KEY} sslrootcert=${DB_SERVER_CA}\" + ${RMQ} + } +} +" > /var/lib/zerotier-one/local.conf + +export GLIBCXX_FORCE_NEW=1 +export GLIBCPP_FORCE_NEW=1 +export LD_PRELOAD="/usr/lib64/libjemalloc.so" +exec /usr/local/bin/zerotier-one -p${ZT_CONTROLLER_PORT:-$DEFAULT_PORT} /var/lib/zerotier-one diff --git a/make-linux.mk b/make-linux.mk index 32972662..d4869706 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -339,7 +339,7 @@ central-controller: FORCE make -j4 LDLIBS="-L/usr/pgsql-10/lib/ -lpq -Lext/librabbitmq/centos_x64/lib/ -lrabbitmq" CXXFLAGS="-I/usr/pgsql-10/include -I./ext/librabbitmq/centos_x64/include -fPIC" DEFS="-DZT_CONTROLLER_USE_LIBPQ -DZT_CONTROLLER" ZT_OFFICIAL=1 ZT_USE_X64_ASM_ED25519=1 one central-controller-docker: central-controller - docker build -t docker.zerotier.com/zerotier-central/ztcentral-controller:${TIMESTAMP} -f docker/Dockerfile . + docker build -t docker.zerotier.com/zerotier-central/ztcentral-controller:${TIMESTAMP} -f ext/central-controller-docker/Dockerfile . debug: FORCE make ZT_DEBUG=1 one From d8de837c607acf1a233ed2e2c1913e1a0d566ed2 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Tue, 27 Aug 2019 14:43:30 -0700 Subject: [PATCH 147/185] LinuxEthernetTap addIps virtual function fix for SYNOLOGY builds --- osdep/EthernetTap.hpp | 1 + osdep/LinuxEthernetTap.cpp | 10 +++++----- osdep/LinuxEthernetTap.hpp | 4 +--- service/OneService.cpp | 3 ++- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/osdep/EthernetTap.hpp b/osdep/EthernetTap.hpp index 26503de0..e39b4150 100644 --- a/osdep/EthernetTap.hpp +++ b/osdep/EthernetTap.hpp @@ -45,6 +45,7 @@ public: virtual void setEnabled(bool en) = 0; virtual bool enabled() const = 0; virtual bool addIp(const InetAddress &ip) = 0; + virtual bool addIps(std::vector ips) = 0; virtual bool removeIp(const InetAddress &ip) = 0; virtual std::vector ips() const = 0; virtual void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len) = 0; diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index 06a87bdc..b340561e 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -261,10 +261,9 @@ static bool ___removeIp(const std::string &_dev,const InetAddress &ip) return true; } -#ifdef __SYNOLOGY__ -bool LinuxEthernetTap::addIpSyn(std::vector ips) +bool LinuxEthernetTap::addIps(std::vector ips) { - // Here we fill out interface config (ifcfg-dev) to prevent it from being killed +#ifdef __SYNOLOGY__ std::string filepath = "/etc/sysconfig/network-scripts/ifcfg-"+_dev; std::string cfg_contents = "DEVICE="+_dev+"\nBOOTPROTO=static"; int ip4=0,ip6=0,ip4_tot=0,ip6_tot=0; @@ -292,13 +291,14 @@ bool LinuxEthernetTap::addIpSyn(std::vector ips) } } OSUtils::writeFile(filepath.c_str(), cfg_contents.c_str(), cfg_contents.length()); - // Finaly, add IPs + // Finally, add IPs for(int i=0; i<(int)ips.size(); i++){ LinuxNetLink::getInstance().addAddress(ips[i], _dev.c_str()); } return true; -} #endif // __SYNOLOGY__ + return false; +} bool LinuxEthernetTap::addIp(const InetAddress &ip) { diff --git a/osdep/LinuxEthernetTap.hpp b/osdep/LinuxEthernetTap.hpp index 3660fb39..7503c523 100644 --- a/osdep/LinuxEthernetTap.hpp +++ b/osdep/LinuxEthernetTap.hpp @@ -46,9 +46,7 @@ public: virtual void setEnabled(bool en); virtual bool enabled() const; virtual bool addIp(const InetAddress &ip); -#ifdef __SYNOLOGY__ - bool addIpSyn(std::vector ips); -#endif + virtual bool addIps(std::vector ips); virtual bool removeIp(const InetAddress &ip); virtual std::vector ips() const; virtual void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len); diff --git a/service/OneService.cpp b/service/OneService.cpp index 77b60b37..f3ec3e66 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1715,8 +1715,9 @@ public: } } #ifdef __SYNOLOGY__ - if (!n.tap->addIpSyn(newManagedIps)) + if (!n.tap->addIps(newManagedIps)) { fprintf(stderr,"ERROR: unable to add ip addresses to ifcfg" ZT_EOL_S); + } #else for(std::vector::iterator ip(newManagedIps.begin());ip!=newManagedIps.end();++ip) { if (std::find(n.managedIps.begin(),n.managedIps.end(),*ip) == n.managedIps.end()) { From e51cf0d4d28605a0663cb14345378075868df1e6 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Tue, 27 Aug 2019 15:14:55 -0700 Subject: [PATCH 148/185] moved elsewhere for controller builds --- docker/Dockerfile | 19 ----------- docker/main.sh | 80 ----------------------------------------------- 2 files changed, 99 deletions(-) delete mode 100644 docker/Dockerfile delete mode 100644 docker/main.sh diff --git a/docker/Dockerfile b/docker/Dockerfile deleted file mode 100644 index ae3eed6b..00000000 --- a/docker/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -# Dockerfile for ZeroTier Central Controllers -FROM centos:7 -MAINTAINER Adam Ierymekno , Grant Limberg - -RUN yum update -y -RUN yum install -y https://download.postgresql.org/pub/repos/yum/10/redhat/rhel-7-x86_64/pgdg-centos10-10-2.noarch.rpm -RUN yum install -y bash postgresql10 libpqxx-devel librabbitmq -RUN yum clean all - -#RUN yum -y install epel-release && yum -y update && yum clean all -#RUN yum -y install clang jemalloc jemalloc-devel - -ADD zerotier-one /usr/local/bin/zerotier-one -RUN chmod a+x /usr/local/bin/zerotier-one - -ADD docker/main.sh / -RUN chmod a+x /main.sh - -ENTRYPOINT /main.sh diff --git a/docker/main.sh b/docker/main.sh deleted file mode 100644 index b8d3b142..00000000 --- a/docker/main.sh +++ /dev/null @@ -1,80 +0,0 @@ -#!/bin/bash - -if [ -z "$ZT_IDENTITY_PATH" ]; then - echo '*** FAILED: ZT_IDENTITY_PATH environment variable is not defined' - exit 1 -fi -if [ -z "$ZT_DB_HOST" ]; then - echo '*** FAILED: ZT_DB_HOST environment variable not defined' - exit 1 -fi -if [ -z "$ZT_DB_PORT" ]; then - echo '*** FAILED: ZT_DB_PORT environment variable not defined' - exit 1 -fi -if [ -z "$ZT_DB_NAME" ]; then - echo '*** FAILED: ZT_DB_NAME environment variable not defined' - exit 1 -fi -if [ -z "$ZT_DB_USER" ]; then - echo '*** FAILED: ZT_DB_USER environment variable not defined' - exit 1 -fi -if [ -z "$ZT_DB_PASSWORD" ]; then - echo '*** FAILED: ZT_DB_PASSWORD environment variable not defined' - exit 1 -fi - -RMQ="" -if [ "$ZT_USE_RABBITMQ" == "true" ]; then - if [ -z "$RABBITMQ_HOST" ]; then - echo '*** FAILED: RABBITMQ_HOST environment variable not defined' - exit 1 - fi - if [ -z "$RABBITMQ_PORT" ]; then - echo '*** FAILED: RABBITMQ_PORT environment variable not defined' - exit 1 - fi - if [ -z "$RABBITMQ_USERNAME" ]; then - echo '*** FAILED: RABBITMQ_USERNAME environment variable not defined' - exit 1 - fi - if [ -z "$RABBITMQ_PASSWORD" ]; then - echo '*** FAILED: RABBITMQ_PASSWORD environment variable not defined' - exit 1 - fi - RMQ=", \"rabbitmq\": { - \"host\": \"${RABBITMQ_HOST}\", - \"port\": ${RABBITMQ_PORT}, - \"username\": \"${RABBITMQ_USERNAME}\", - \"password\": \"${RABBITMQ_PASSWORD}\" - }" -fi - -mkdir -p /var/lib/zerotier-one - -pushd /var/lib/zerotier-one -ln -s $ZT_IDENTITY_PATH/identity.public identity.public -ln -s $ZT_IDENTITY_PATH/identity.secret identity.secret -popd - -DEFAULT_PORT=9993 - -echo "{ - \"settings\": { - \"portMappingEnabled\": true, - \"softwareUpdate\": \"disable\", - \"interfacePrefixBlacklist\": [ - \"inot\", - \"nat64\" - ], - \"controllerDbPath\": \"postgres:host=${ZT_DB_HOST} port=${ZT_DB_PORT} dbname=${ZT_DB_NAME} user=${ZT_DB_USER} password=${ZT_DB_PASSWORD} sslmode=prefer sslcert=${DB_CLIENT_CERT} sslkey=${DB_CLIENT_KEY} sslrootcert=${DB_SERVER_CA}\" - ${RMQ} - } -} -" > /var/lib/zerotier-one/local.conf - -export GLIBCXX_FORCE_NEW=1 -export GLIBCPP_FORCE_NEW=1 -export LD_PRELOAD="/usr/lib64/libjemalloc.so" -exec /usr/local/bin/zerotier-one -p${ZT_CONTROLLER_PORT:-$DEFAULT_PORT} /var/lib/zerotier-one From 5cda292d159db9ebd2ce0b208b16fd4e120b95ca Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Tue, 27 Aug 2019 15:16:05 -0700 Subject: [PATCH 149/185] comment out `docker` docker target from makefile because broken --- make-linux.mk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/make-linux.mk b/make-linux.mk index d4869706..60dd2c7c 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -331,9 +331,9 @@ realclean: distclean official: FORCE make -j4 ZT_OFFICIAL=1 all -docker: FORCE - make clean ; make -j4 one - docker build -f docker/Dockerfile . +#docker: FORCE +# make clean ; make -j4 one +# docker build -f docker/Dockerfile . central-controller: FORCE make -j4 LDLIBS="-L/usr/pgsql-10/lib/ -lpq -Lext/librabbitmq/centos_x64/lib/ -lrabbitmq" CXXFLAGS="-I/usr/pgsql-10/include -I./ext/librabbitmq/centos_x64/include -fPIC" DEFS="-DZT_CONTROLLER_USE_LIBPQ -DZT_CONTROLLER" ZT_OFFICIAL=1 ZT_USE_X64_ASM_ED25519=1 one From ddc904a50246ef9350f99c3c3e952527a7f7dd8d Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Tue, 27 Aug 2019 15:27:41 -0700 Subject: [PATCH 150/185] remove docker line from readme --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 3b9326ac..b571459d 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,6 @@ The base path contains the ZeroTier One service main entry point (`one.cpp`), se - `controller/`: the reference network controller implementation, which is built and included by default on desktop and server build targets. - `debian/`: files for building Debian packages on Linux. - `doc/`: manual pages and other documentation. - - `docker/`: Dockerfile to build as a container for containerized Linux systems and Kubernetes clusters. - `ext/`: third party libraries, binaries that we ship for convenience on some platforms (Mac and Windows), and installation support files. - `include/`: include files for the ZeroTier core. - `java/`: a JNI wrapper used with our Android mobile app. (The whole Android app is not open source but may be made so in the future.) From e5bf4565da8e83526797e75d0d594cb4f16ece24 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Tue, 27 Aug 2019 15:43:11 -0700 Subject: [PATCH 151/185] readme in central controller docker folder --- ext/central-controller-docker/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 ext/central-controller-docker/README.md diff --git a/ext/central-controller-docker/README.md b/ext/central-controller-docker/README.md new file mode 100644 index 00000000..a954b1c3 --- /dev/null +++ b/ext/central-controller-docker/README.md @@ -0,0 +1,3 @@ +# ZeroTier Central Controller Docker Image + +Dockerfile & startup script for use with [ZeroTier Central](https://my.zerotier.com). Not intended for public use. From 1cf953c046cb001c1860826793c3e84e1a2d2911 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Tue, 27 Aug 2019 16:57:07 -0700 Subject: [PATCH 152/185] working docker image for end users. GitHub Issue #1013 --- .../linux/zerotier-containerized/Dockerfile | 12 ++++-------- make-linux.mk | 5 ++--- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/ext/installfiles/linux/zerotier-containerized/Dockerfile b/ext/installfiles/linux/zerotier-containerized/Dockerfile index fd18eebb..3d580566 100644 --- a/ext/installfiles/linux/zerotier-containerized/Dockerfile +++ b/ext/installfiles/linux/zerotier-containerized/Dockerfile @@ -7,17 +7,13 @@ FROM debian:buster-slim as builder RUN apt-get update && apt-get install -y curl gnupg RUN apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys 0x1657198823e52a61 && \ echo "deb http://download.zerotier.com/debian/buster buster main" > /etc/apt/sources.list.d/zerotier.list -RUN apt-get update && apt-get install -y zerotier-one=1.2.12 -RUN curl https://raw.githubusercontent.com/zerotier/ZeroTierOne/master/ext/installfiles/linux/zerotier-containerized/main.sh > /var/lib/zerotier-one/main.sh +RUN apt-get update && apt-get install -y zerotier-one=1.4.4 +COPY ext/installfiles/linux/zerotier-containerized/main.sh /var/lib/zerotier-one/main.sh -FROM alpine:latest -LABEL version="1.2.12" +FROM debian:buster-slim +LABEL version="1.4.4" LABEL description="Containerized ZeroTier One for use on CoreOS or other Docker-only Linux hosts." -# Uncomment to build in container -# RUN apk add --update alpine-sdk linux-headers -RUN apk add --update libgcc libstdc++ - # ZeroTier relies on UDP port 9993 EXPOSE 9993/udp diff --git a/make-linux.mk b/make-linux.mk index 60dd2c7c..0fe1f051 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -331,9 +331,8 @@ realclean: distclean official: FORCE make -j4 ZT_OFFICIAL=1 all -#docker: FORCE -# make clean ; make -j4 one -# docker build -f docker/Dockerfile . +docker: FORCE + docker build -f ext/installfiles/linux/zerotier-containerized/Dockerfile -t zerotier-containerized . central-controller: FORCE make -j4 LDLIBS="-L/usr/pgsql-10/lib/ -lpq -Lext/librabbitmq/centos_x64/lib/ -lrabbitmq" CXXFLAGS="-I/usr/pgsql-10/include -I./ext/librabbitmq/centos_x64/include -fPIC" DEFS="-DZT_CONTROLLER_USE_LIBPQ -DZT_CONTROLLER" ZT_OFFICIAL=1 ZT_USE_X64_ASM_ED25519=1 one From 1b6b38e39534711dae6e05c5e824051dc12190d3 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 28 Aug 2019 07:43:18 -0700 Subject: [PATCH 153/185] Add default addIps() implementation to EthernetTap base class to fix build on systems that do not need addIps(). --- osdep/EthernetTap.cpp | 9 +++++++++ osdep/EthernetTap.hpp | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/osdep/EthernetTap.cpp b/osdep/EthernetTap.cpp index a293991e..10fe6d89 100644 --- a/osdep/EthernetTap.cpp +++ b/osdep/EthernetTap.cpp @@ -119,4 +119,13 @@ std::shared_ptr EthernetTap::newInstance( EthernetTap::EthernetTap() {} EthernetTap::~EthernetTap() {} +bool EthernetTap::addIps(std::vector ips) +{ + for(std::vector::const_iterator i(ips.begin());i!=ips.end();++i) { + if (!addIp(*i)) + return false; + } + return true; +} + } // namespace ZeroTier diff --git a/osdep/EthernetTap.hpp b/osdep/EthernetTap.hpp index e39b4150..db52e6b4 100644 --- a/osdep/EthernetTap.hpp +++ b/osdep/EthernetTap.hpp @@ -45,7 +45,7 @@ public: virtual void setEnabled(bool en) = 0; virtual bool enabled() const = 0; virtual bool addIp(const InetAddress &ip) = 0; - virtual bool addIps(std::vector ips) = 0; + virtual bool addIps(std::vector ips); // uses addIp() unless overridden virtual bool removeIp(const InetAddress &ip) = 0; virtual std::vector ips() const = 0; virtual void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len) = 0; From 7c6d0d3c0ff813f2cb1e3b0299ccd5b8572aa0d4 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 30 Aug 2019 09:50:37 -0700 Subject: [PATCH 154/185] ARM wrestling --- make-linux.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/make-linux.mk b/make-linux.mk index 0fe1f051..fbb4e14e 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -267,8 +267,8 @@ ifeq ($(ZT_ARCHITECTURE),3) override CXXFLAGS+=-march=armv5 -mfloat-abi=soft -msoft-float -mno-unaligned-access -marm ZT_USE_ARM32_NEON_ASM_CRYPTO=0 else - override CFLAGS+=-march=armv5 -mno-unaligned-access -marm - override CXXFLAGS+=-march=armv5 -mno-unaligned-access -marm + override CFLAGS+=-mcpu=arm1176jzf-s -mfpu=vfp -mno-unaligned-access + override CXXFLAGS+=-mcpu=arm1176jzf-s -mfpu=vfp -mno-unaligned-access ZT_USE_ARM32_NEON_ASM_CRYPTO=0 endif endif From ebb5f1256f4255a6e7875867a8ecda330b22a13e Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 30 Aug 2019 10:03:07 -0700 Subject: [PATCH 155/185] ARM wrestling --- make-linux.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/make-linux.mk b/make-linux.mk index fbb4e14e..0fe1f051 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -267,8 +267,8 @@ ifeq ($(ZT_ARCHITECTURE),3) override CXXFLAGS+=-march=armv5 -mfloat-abi=soft -msoft-float -mno-unaligned-access -marm ZT_USE_ARM32_NEON_ASM_CRYPTO=0 else - override CFLAGS+=-mcpu=arm1176jzf-s -mfpu=vfp -mno-unaligned-access - override CXXFLAGS+=-mcpu=arm1176jzf-s -mfpu=vfp -mno-unaligned-access + override CFLAGS+=-march=armv5 -mno-unaligned-access -marm + override CXXFLAGS+=-march=armv5 -mno-unaligned-access -marm ZT_USE_ARM32_NEON_ASM_CRYPTO=0 endif endif From 5e8e935189e25600d5b7e5c9cded3b892a8406d1 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 30 Aug 2019 11:57:18 -0700 Subject: [PATCH 156/185] world! --- attic/world/build.sh | 2 +- attic/world/mkworld.cpp | 77 +++++++++++++++++++++++++--------------- attic/world/world.bin | Bin 732 -> 570 bytes node/Topology.cpp | 29 ++------------- 4 files changed, 51 insertions(+), 57 deletions(-) diff --git a/attic/world/build.sh b/attic/world/build.sh index aeb3b87f..d8800cd4 100755 --- a/attic/world/build.sh +++ b/attic/world/build.sh @@ -1,3 +1,3 @@ #!/bin/bash -c++ -std=c++11 -I../.. -I.. -O -o mkworld ../../node/C25519.cpp ../../node/Salsa20.cpp ../../node/SHA512.cpp ../../node/Identity.cpp ../../node/Utils.cpp ../../node/InetAddress.cpp ../../osdep/OSUtils.cpp mkworld.cpp -lm +c++ -std=c++11 -I../.. -I.. -g -o mkworld ../../node/C25519.cpp ../../node/Salsa20.cpp ../../node/SHA512.cpp ../../node/Identity.cpp ../../node/Utils.cpp ../../node/InetAddress.cpp ../../osdep/OSUtils.cpp mkworld.cpp -lm diff --git a/attic/world/mkworld.cpp b/attic/world/mkworld.cpp index b8cb027b..6b9bbe8d 100644 --- a/attic/world/mkworld.cpp +++ b/attic/world/mkworld.cpp @@ -81,44 +81,63 @@ int main(int argc,char **argv) std::vector roots; const uint64_t id = ZT_WORLD_ID_EARTH; - const uint64_t ts = 1562631342273ULL; // July 8th, 2019 + const uint64_t ts = 1567191349589ULL; // August 30th, 2019 + // Los Angeles roots.push_back(World::Root()); roots.back().identity = Identity("3a46f1bf30:0:76e66fab33e28549a62ee2064d1843273c2c300ba45c3f20bef02dbad225723bb59a9bb4b13535730961aeecf5a163ace477cceb0727025b99ac14a5166a09a3"); roots.back().stableEndpoints.push_back(InetAddress("185.180.13.82/9993")); roots.back().stableEndpoints.push_back(InetAddress("2a02:6ea0:c815::/9993")); - // Alice + // Miami roots.push_back(World::Root()); - roots.back().identity = Identity("9d219039f3:0:01f0922a98e3b34ebcbff333269dc265d7a020aab69d72be4d4acc9c8c9294785771256cd1d942a90d1bd1d2dca3ea84ef7d85afe6611fb43ff0b74126d90a6e"); - roots.back().stableEndpoints.push_back(InetAddress("188.166.94.177/9993")); // Amsterdam - roots.back().stableEndpoints.push_back(InetAddress("2a03:b0c0:2:d0::7d:1/9993")); // Amsterdam - roots.back().stableEndpoints.push_back(InetAddress("154.66.197.33/9993")); // Johannesburg - roots.back().stableEndpoints.push_back(InetAddress("2c0f:f850:154:197::33/9993")); // Johannesburg - roots.back().stableEndpoints.push_back(InetAddress("159.203.97.171/9993")); // New York - roots.back().stableEndpoints.push_back(InetAddress("2604:a880:800:a1::54:6001/9993")); // New York - roots.back().stableEndpoints.push_back(InetAddress("131.255.6.16/9993")); // Buenos Aires - roots.back().stableEndpoints.push_back(InetAddress("2803:eb80:0:e::2/9993")); // Buenos Aires - roots.back().stableEndpoints.push_back(InetAddress("107.170.197.14/9993")); // San Francisco - roots.back().stableEndpoints.push_back(InetAddress("2604:a880:1:20::200:e001/9993")); // San Francisco - roots.back().stableEndpoints.push_back(InetAddress("128.199.197.217/9993")); // Singapore - roots.back().stableEndpoints.push_back(InetAddress("2400:6180:0:d0::b7:4001/9993")); // Singapore + roots.back().identity = Identity("de8950a8b2:0:1b3ada8251b91b6b6fa6535b8c7e2460918f4f729abdec97d3c7f3796868fb02f0de0b0ee554b2d59fc3524743eebfcf5315e790ed6d92db5bd10c28c09b40ef"); + roots.back().stableEndpoints.push_back(InetAddress("207.246.73.245/443")); + roots.back().stableEndpoints.push_back(InetAddress("2001:19f0:9002:5cb:ec4:7aff:fe8f:69d9/443")); - // Bob + // Tokyo + roots.push_back(World::Root()); + roots.back().identity = Identity("34e0a5e174:0:93efb50934788f856d5cfb9ca5be88e85b40965586b75befac900df77352c145a1ba7007569d37c77bfe52c0999f3bdc67a47a4a6000b720a883ce47aa2fb7f8"); + roots.back().stableEndpoints.push_back(InetAddress("147.75.92.2/443")); + roots.back().stableEndpoints.push_back(InetAddress("2604:1380:3000:7100::1/443")); + + // Amsterdam roots.push_back(World::Root()); - roots.back().identity = Identity("8841408a2e:0:bb1d31f2c323e264e9e64172c1a74f77899555ed10751cd56e86405cde118d02dffe555d462ccf6a85b5631c12350c8d5dc409ba10b9025d0f445cf449d92b1c"); - roots.back().stableEndpoints.push_back(InetAddress("45.32.198.130/9993")); // Dallas - roots.back().stableEndpoints.push_back(InetAddress("2001:19f0:6400:81c3:5400:00ff:fe18:1d61/9993")); // Dallas - roots.back().stableEndpoints.push_back(InetAddress("46.101.160.249/9993")); // Frankfurt - roots.back().stableEndpoints.push_back(InetAddress("2a03:b0c0:3:d0::6a:3001/9993")); // Frankfurt - roots.back().stableEndpoints.push_back(InetAddress("107.191.46.210/9993")); // Paris - roots.back().stableEndpoints.push_back(InetAddress("2001:19f0:6800:83a4::64/9993")); // Paris - roots.back().stableEndpoints.push_back(InetAddress("45.32.246.179/9993")); // Sydney - roots.back().stableEndpoints.push_back(InetAddress("2001:19f0:5800:8bf8:5400:ff:fe15:b39a/9993")); // Sydney - roots.back().stableEndpoints.push_back(InetAddress("45.32.248.87/9993")); // Tokyo - roots.back().stableEndpoints.push_back(InetAddress("2001:19f0:7000:9bc9:5400:00ff:fe15:c4f5/9993")); // Tokyo - roots.back().stableEndpoints.push_back(InetAddress("159.203.2.154/9993")); // Toronto - roots.back().stableEndpoints.push_back(InetAddress("2604:a880:cad:d0::26:7001/9993")); // Toronto + roots.back().identity = Identity("992fcf1db7:0:206ed59350b31916f749a1f85dffb3a8787dcbf83b8c6e9448d4e3ea0e3369301be716c3609344a9d1533850fb4460c50af43322bcfc8e13d3301a1f1003ceb6"); + roots.back().stableEndpoints.push_back(InetAddress("195.181.173.159/443")); + roots.back().stableEndpoints.push_back(InetAddress("2a02:6ea0:c024::/443")); + + // Alice + //roots.push_back(World::Root()); + //roots.back().identity = Identity("9d219039f3:0:01f0922a98e3b34ebcbff333269dc265d7a020aab69d72be4d4acc9c8c9294785771256cd1d942a90d1bd1d2dca3ea84ef7d85afe6611fb43ff0b74126d90a6e"); + //roots.back().stableEndpoints.push_back(InetAddress("188.166.94.177/9993")); // Amsterdam + //roots.back().stableEndpoints.push_back(InetAddress("2a03:b0c0:2:d0::7d:1/9993")); // Amsterdam + //roots.back().stableEndpoints.push_back(InetAddress("154.66.197.33/9993")); // Johannesburg + //roots.back().stableEndpoints.push_back(InetAddress("2c0f:f850:154:197::33/9993")); // Johannesburg + //roots.back().stableEndpoints.push_back(InetAddress("159.203.97.171/9993")); // New York + //roots.back().stableEndpoints.push_back(InetAddress("2604:a880:800:a1::54:6001/9993")); // New York + //roots.back().stableEndpoints.push_back(InetAddress("131.255.6.16/9993")); // Buenos Aires + //roots.back().stableEndpoints.push_back(InetAddress("2803:eb80:0:e::2/9993")); // Buenos Aires + //roots.back().stableEndpoints.push_back(InetAddress("107.170.197.14/9993")); // San Francisco + //roots.back().stableEndpoints.push_back(InetAddress("2604:a880:1:20::200:e001/9993")); // San Francisco + //roots.back().stableEndpoints.push_back(InetAddress("128.199.197.217/9993")); // Singapore + //roots.back().stableEndpoints.push_back(InetAddress("2400:6180:0:d0::b7:4001/9993")); // Singapore + + // Bob + //roots.push_back(World::Root()); + //roots.back().identity = Identity("8841408a2e:0:bb1d31f2c323e264e9e64172c1a74f77899555ed10751cd56e86405cde118d02dffe555d462ccf6a85b5631c12350c8d5dc409ba10b9025d0f445cf449d92b1c"); + //roots.back().stableEndpoints.push_back(InetAddress("45.32.198.130/9993")); // Dallas + //roots.back().stableEndpoints.push_back(InetAddress("2001:19f0:6400:81c3:5400:00ff:fe18:1d61/9993")); // Dallas + //roots.back().stableEndpoints.push_back(InetAddress("46.101.160.249/9993")); // Frankfurt + //roots.back().stableEndpoints.push_back(InetAddress("2a03:b0c0:3:d0::6a:3001/9993")); // Frankfurt + //roots.back().stableEndpoints.push_back(InetAddress("107.191.46.210/9993")); // Paris + //roots.back().stableEndpoints.push_back(InetAddress("2001:19f0:6800:83a4::64/9993")); // Paris + //roots.back().stableEndpoints.push_back(InetAddress("45.32.246.179/9993")); // Sydney + //roots.back().stableEndpoints.push_back(InetAddress("2001:19f0:5800:8bf8:5400:ff:fe15:b39a/9993")); // Sydney + //roots.back().stableEndpoints.push_back(InetAddress("45.32.248.87/9993")); // Tokyo + //roots.back().stableEndpoints.push_back(InetAddress("2001:19f0:7000:9bc9:5400:00ff:fe15:c4f5/9993")); // Tokyo + //roots.back().stableEndpoints.push_back(InetAddress("159.203.2.154/9993")); // Toronto + //roots.back().stableEndpoints.push_back(InetAddress("2604:a880:cad:d0::26:7001/9993")); // Toronto // END WORLD DEFINITION // ========================================================================= diff --git a/attic/world/world.bin b/attic/world/world.bin index fff7e2a99462f929185788f1e74875c6c83b7b91..88049ccdc83167db4887d147d432c80e5102951b 100644 GIT binary patch delta 453 zcmV;$0XqKN1-b+g0RR9100`>I3IG5BY~$iNRgn=ue;NK+yD}Sexlu!2^P#~@&aW|Z zdZwAR+?m79x1Wjq-;Ok*z!j*{sgI3(mWzcQB6MaWMwije&#}A&Ktr!Y0|0ity`$)K zcWkYM7lfD7EXTWQwH^!x%Uq-XGCHa@(gZq2@xL$tcII!ZGvb9wrY_)*yJxy_bS{HSbLoH%glc)9J3$HE0>+` zF1BitzkrzS@i&(z%)40fXY*F}Ilfbmig(*`CzQPi+`Y}VWUFFx^;B7=*=N_s*iE}{ zt`nB~tCas%Xshs-GO09Q>)!K1Crx(pCNf*OecW%rQ1&c;weh1?&t-a#*nB0N)opYP zxR=D(D@?rLQa@L5g5_rh#t)OUW<1{Pw`c!nW3{=5Qm-#iSha0#(LP_VGjn<-O{oYk zRL!|~(`hBI^uMT2j0W@T2B0V(R1*_WCVSOUKByiBMg|3t3=_ixke-I)M{fdUR2UK)fPxSwYCsw(0Dk6f#Lr@3E4!T<$9?L zegb8{{%3|-o@D@XR`!0qOHe%-49!bG4hDi0pp349_qWYZsR)MdA7JA|H_rk~{RoH3 f6fn#_36VMS6(}?RG!sw(ILvs~LM>7&09ph9c!AK) diff --git a/node/Topology.cpp b/node/Topology.cpp index 46db4c94..9b674c21 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -22,33 +22,8 @@ namespace ZeroTier { -/* - * 2018-07-26 ZeroTier planet definition for the third planet of Sol: - * - * There are two roots, each of which is a cluster spread across multiple - * continents and providers. They are named Alice and Bob after the - * canonical example names used in cryptography. - * - * Alice: - * - * root-alice-ams-01: Amsterdam, Netherlands - * root-alice-joh-01: Johannesburg, South Africa - * root-alice-nyc-01: New York, New York, USA - * root-alice-arg-01: Buenos Aires, Argentina - * root-alice-sfo-01: San Francisco, California, USA - * root-alice-sgp-01: Singapore - * - * Bob: - * - * root-bob-dfw-01: Dallas, Texas, USA - * root-bob-fra-01: Frankfurt, Germany - * root-bob-par-01: Paris, France - * root-bob-syd-01: Sydney, Australia - * root-bob-tok-01: Tokyo, Japan - * root-bob-tor-01: Toronto, Canada - */ -#define ZT_DEFAULT_WORLD_LENGTH 634 -static const unsigned char ZT_DEFAULT_WORLD[ZT_DEFAULT_WORLD_LENGTH] = {0x01,0x00,0x00,0x00,0x00,0x08,0xea,0xc9,0x0a,0x00,0x00,0x01,0x64,0xd3,0x71,0xf0,0x58,0xb8,0xb3,0x88,0xa4,0x69,0x22,0x14,0x91,0xaa,0x9a,0xcd,0x66,0xcc,0x76,0x4c,0xde,0xfd,0x56,0x03,0x9f,0x10,0x67,0xae,0x15,0xe6,0x9c,0x6f,0xb4,0x2d,0x7b,0x55,0x33,0x0e,0x3f,0xda,0xac,0x52,0x9c,0x07,0x92,0xfd,0x73,0x40,0xa6,0xaa,0x21,0xab,0xa8,0xa4,0x89,0xfd,0xae,0xa4,0x4a,0x39,0xbf,0x2d,0x00,0x65,0x9a,0xc9,0xc8,0x18,0xeb,0xbf,0xfd,0xd5,0x32,0xf7,0x15,0x6e,0x02,0x6f,0xb9,0x01,0x0d,0xb5,0x7b,0x04,0xd8,0x3a,0xc5,0x17,0x39,0x04,0x36,0xfd,0x9d,0xc6,0x3d,0xa8,0xf3,0x8e,0x79,0xe7,0xc8,0x77,0x8d,0xcc,0x79,0xb8,0xab,0xc6,0x98,0x7c,0x9f,0x34,0x25,0x14,0xe1,0x2f,0xd7,0x97,0x11,0xec,0x34,0x4c,0x9f,0x0f,0xb4,0x85,0x0d,0x9b,0x11,0xd1,0xc2,0xce,0x00,0xc4,0x0a,0x13,0x4b,0xcb,0xc3,0xae,0x2e,0x16,0x00,0x4b,0xdc,0x90,0x5e,0x7e,0x9b,0x44,0x07,0x15,0x36,0x61,0x3c,0x64,0xaa,0xe9,0x46,0x78,0x3c,0xa7,0x18,0xc8,0xd8,0x02,0x9d,0x21,0x90,0x39,0xf3,0x00,0x01,0xf0,0x92,0x2a,0x98,0xe3,0xb3,0x4e,0xbc,0xbf,0xf3,0x33,0x26,0x9d,0xc2,0x65,0xd7,0xa0,0x20,0xaa,0xb6,0x9d,0x72,0xbe,0x4d,0x4a,0xcc,0x9c,0x8c,0x92,0x94,0x78,0x57,0x71,0x25,0x6c,0xd1,0xd9,0x42,0xa9,0x0d,0x1b,0xd1,0xd2,0xdc,0xa3,0xea,0x84,0xef,0x7d,0x85,0xaf,0xe6,0x61,0x1f,0xb4,0x3f,0xf0,0xb7,0x41,0x26,0xd9,0x0a,0x6e,0x00,0x0c,0x04,0xbc,0xa6,0x5e,0xb1,0x27,0x09,0x06,0x2a,0x03,0xb0,0xc0,0x00,0x02,0x00,0xd0,0x00,0x7d,0x00,0x01,0x00,0x00,0x00,0x00,0x27,0x09,0x04,0x9a,0x42,0xc5,0x21,0x27,0x09,0x06,0x2c,0x0f,0xf8,0x50,0x01,0x54,0x01,0x97,0x00,0x33,0xcc,0x08,0xf8,0xfa,0xcc,0x08,0x27,0x09,0x04,0x9f,0xcb,0x61,0xab,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x08,0x00,0x00,0xa1,0x00,0x54,0x60,0x01,0x00,0xfc,0xcc,0x08,0x27,0x09,0x04,0x83,0xff,0x06,0x10,0x27,0x09,0x06,0x28,0x03,0xeb,0x80,0x00,0x00,0x00,0x0e,0x00,0x02,0x60,0x01,0x00,0xfc,0xcc,0x08,0x27,0x09,0x04,0x6b,0xaa,0xc5,0x0e,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x00,0x01,0x00,0x20,0x02,0x00,0xe0,0x01,0x08,0xfe,0xcc,0x08,0x27,0x09,0x04,0x80,0xc7,0xc5,0xd9,0x27,0x09,0x06,0x24,0x00,0x61,0x80,0x00,0x00,0x00,0xd0,0x00,0xb7,0x40,0x01,0x08,0xfe,0xcc,0x08,0x27,0x09,0x88,0x41,0x40,0x8a,0x2e,0x00,0xbb,0x1d,0x31,0xf2,0xc3,0x23,0xe2,0x64,0xe9,0xe6,0x41,0x72,0xc1,0xa7,0x4f,0x77,0x89,0x95,0x55,0xed,0x10,0x75,0x1c,0xd5,0x6e,0x86,0x40,0x5c,0xde,0x11,0x8d,0x02,0xdf,0xfe,0x55,0x5d,0x46,0x2c,0xcf,0x6a,0x85,0xb5,0x63,0x1c,0x12,0x35,0x0c,0x8d,0x5d,0xc4,0x09,0xba,0x10,0xb9,0x02,0x5d,0x0f,0x44,0x5c,0xf4,0x49,0xd9,0x2b,0x1c,0x00,0x0c,0x04,0x2d,0x20,0xc6,0x82,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x64,0x00,0x81,0xc3,0x54,0x00,0x00,0xff,0xfe,0x18,0x1d,0x61,0x27,0x09,0x04,0x2e,0x65,0xa0,0xf9,0x27,0x09,0x06,0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x6a,0x30,0x01,0x78,0x00,0xcd,0x08,0x27,0x09,0x04,0x6b,0xbf,0x2e,0xd2,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x68,0x00,0x83,0xa4,0x00,0x64,0xcd,0x08,0x80,0x01,0xcd,0x08,0x27,0x09,0x04,0x2d,0x20,0xf6,0xb3,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x58,0x00,0x8b,0xf8,0x54,0x00,0x00,0xff,0xfe,0x15,0xb3,0x9a,0x27,0x09,0x04,0x2d,0x20,0xf8,0x57,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x70,0x00,0x9b,0xc9,0x54,0x00,0x00,0xff,0xfe,0x15,0xc4,0xf5,0x27,0x09,0x04,0x9f,0xcb,0x02,0x9a,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x0c,0xad,0x00,0xd0,0x00,0x26,0x70,0x01,0xfe,0x15,0xc4,0xf5,0x27,0x09}; +#define ZT_DEFAULT_WORLD_LENGTH 570 +static const unsigned char ZT_DEFAULT_WORLD[ZT_DEFAULT_WORLD_LENGTH] = {0x01,0x00,0x00,0x00,0x00,0x08,0xea,0xc9,0x0a,0x00,0x00,0x01,0x6c,0xe3,0xe2,0x39,0x55,0xb8,0xb3,0x88,0xa4,0x69,0x22,0x14,0x91,0xaa,0x9a,0xcd,0x66,0xcc,0x76,0x4c,0xde,0xfd,0x56,0x03,0x9f,0x10,0x67,0xae,0x15,0xe6,0x9c,0x6f,0xb4,0x2d,0x7b,0x55,0x33,0x0e,0x3f,0xda,0xac,0x52,0x9c,0x07,0x92,0xfd,0x73,0x40,0xa6,0xaa,0x21,0xab,0xa8,0xa4,0x89,0xfd,0xae,0xa4,0x4a,0x39,0xbf,0x2d,0x00,0x65,0x9a,0xc9,0xc8,0x18,0xeb,0x19,0xfe,0x59,0xbb,0x32,0x1b,0x74,0xb9,0x51,0x43,0x5e,0xf3,0xa1,0xc1,0x4b,0xce,0xaf,0x31,0x73,0x7a,0xa6,0x99,0xb5,0xdc,0x99,0xc3,0xce,0xb7,0x9f,0x89,0xfd,0xdf,0x8e,0x34,0xa2,0xc0,0x15,0xa8,0xd2,0xa9,0x8f,0x8d,0x7c,0x96,0x8b,0x85,0x1d,0x22,0x74,0x66,0x23,0x46,0x97,0xd1,0xcd,0xcf,0xb1,0xbc,0x04,0x40,0x43,0xaf,0x44,0x03,0x00,0x76,0xbd,0xbd,0xa3,0xe8,0x74,0x77,0x6c,0xad,0x84,0x17,0x84,0x97,0xd3,0x2c,0xc7,0xbb,0x6a,0xb5,0x1e,0x0c,0x06,0xcb,0x5c,0xa3,0xff,0x32,0x3a,0xaa,0x36,0xd2,0x04,0x3a,0x46,0xf1,0xbf,0x30,0x00,0x76,0xe6,0x6f,0xab,0x33,0xe2,0x85,0x49,0xa6,0x2e,0xe2,0x06,0x4d,0x18,0x43,0x27,0x3c,0x2c,0x30,0x0b,0xa4,0x5c,0x3f,0x20,0xbe,0xf0,0x2d,0xba,0xd2,0x25,0x72,0x3b,0xb5,0x9a,0x9b,0xb4,0xb1,0x35,0x35,0x73,0x09,0x61,0xae,0xec,0xf5,0xa1,0x63,0xac,0xe4,0x77,0xcc,0xeb,0x07,0x27,0x02,0x5b,0x99,0xac,0x14,0xa5,0x16,0x6a,0x09,0xa3,0x00,0x02,0x04,0xb9,0xb4,0x0d,0x52,0x27,0x09,0x06,0x2a,0x02,0x6e,0xa0,0xc8,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0x09,0xde,0x89,0x50,0xa8,0xb2,0x00,0x1b,0x3a,0xda,0x82,0x51,0xb9,0x1b,0x6b,0x6f,0xa6,0x53,0x5b,0x8c,0x7e,0x24,0x60,0x91,0x8f,0x4f,0x72,0x9a,0xbd,0xec,0x97,0xd3,0xc7,0xf3,0x79,0x68,0x68,0xfb,0x02,0xf0,0xde,0x0b,0x0e,0xe5,0x54,0xb2,0xd5,0x9f,0xc3,0x52,0x47,0x43,0xee,0xbf,0xcf,0x53,0x15,0xe7,0x90,0xed,0x6d,0x92,0xdb,0x5b,0xd1,0x0c,0x28,0xc0,0x9b,0x40,0xef,0x00,0x02,0x04,0xcf,0xf6,0x49,0xf5,0x01,0xbb,0x06,0x20,0x01,0x19,0xf0,0x90,0x02,0x05,0xcb,0x0e,0xc4,0x7a,0xff,0xfe,0x8f,0x69,0xd9,0x01,0xbb,0x34,0xe0,0xa5,0xe1,0x74,0x00,0x93,0xef,0xb5,0x09,0x34,0x78,0x8f,0x85,0x6d,0x5c,0xfb,0x9c,0xa5,0xbe,0x88,0xe8,0x5b,0x40,0x96,0x55,0x86,0xb7,0x5b,0xef,0xac,0x90,0x0d,0xf7,0x73,0x52,0xc1,0x45,0xa1,0xba,0x70,0x07,0x56,0x9d,0x37,0xc7,0x7b,0xfe,0x52,0xc0,0x99,0x9f,0x3b,0xdc,0x67,0xa4,0x7a,0x4a,0x60,0x00,0xb7,0x20,0xa8,0x83,0xce,0x47,0xaa,0x2f,0xb7,0xf8,0x00,0x02,0x04,0x93,0x4b,0x5c,0x02,0x01,0xbb,0x06,0x26,0x04,0x13,0x80,0x30,0x00,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0xbb,0x99,0x2f,0xcf,0x1d,0xb7,0x00,0x20,0x6e,0xd5,0x93,0x50,0xb3,0x19,0x16,0xf7,0x49,0xa1,0xf8,0x5d,0xff,0xb3,0xa8,0x78,0x7d,0xcb,0xf8,0x3b,0x8c,0x6e,0x94,0x48,0xd4,0xe3,0xea,0x0e,0x33,0x69,0x30,0x1b,0xe7,0x16,0xc3,0x60,0x93,0x44,0xa9,0xd1,0x53,0x38,0x50,0xfb,0x44,0x60,0xc5,0x0a,0xf4,0x33,0x22,0xbc,0xfc,0x8e,0x13,0xd3,0x30,0x1a,0x1f,0x10,0x03,0xce,0xb6,0x00,0x02,0x04,0xc3,0xb5,0xad,0x9f,0x01,0xbb,0x06,0x2a,0x02,0x6e,0xa0,0xc0,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xbb}; Topology::Topology(const RuntimeEnvironment *renv,void *tPtr) : RR(renv), From 075321fd0db19dd945a8fb81df7b332b40022f0d Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 30 Aug 2019 15:16:05 -0700 Subject: [PATCH 157/185] debian build version bump --- debian/changelog | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/debian/changelog b/debian/changelog index 83ae0c1d..064848b8 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +zerotier-one (1.4.4-2) unstable; urgency=medium + + * Re-build with new planet/world file and a flags and build process + update for armhf (32-bit ARM) targets. + + -- Adam Ierymenko Fri, 30 Aug 2019 01:00:00 -0700 + zerotier-one (1.4.4) unstable; urgency=medium * See https://github.com/zerotier/ZeroTierOne for release notes. From 6897f602bf68ec0bde65539fd54534fd1faae1dc Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 30 Aug 2019 15:30:37 -0700 Subject: [PATCH 158/185] 1.4.6 version bump --- LICENSE.txt | 4 +++- debian/changelog | 9 ++++++--- ext/installfiles/mac/ZeroTier One.pkgproj | 2 +- one.cpp | 8 ++------ version.h | 2 +- windows/WinUI/AboutView.xaml | 2 +- zerotier-one.spec | 2 +- 7 files changed, 15 insertions(+), 14 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index c0c40aed..78daf4c2 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -22,7 +22,9 @@ Additional Use Grant: You may make use of the Licensed Work, provided you generation components of the Licensed Work as a for-profit service, regardless of whether the use of these components is sold alone or is bundled with other - services. + services. Note that this does not apply to the use of + ZeroTier behind the scenes to operate a service not + related to ZeroTier network administration. * Create Non-Open-Source Commercial Derviative Works diff --git a/debian/changelog b/debian/changelog index 064848b8..dc836339 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,7 +1,10 @@ -zerotier-one (1.4.4-2) unstable; urgency=medium +zerotier-one (1.4.6) unstable; urgency=medium - * Re-build with new planet/world file and a flags and build process - update for armhf (32-bit ARM) targets. + * Update default root server list + * Fix build flags on "armhf" (32-bit ARM) platforms for better + compatibility with Pi Zero and other devices. + * Fix license text in one.cpp. + * Add a clarification to LICENSE.txt. -- Adam Ierymenko Fri, 30 Aug 2019 01:00:00 -0700 diff --git a/ext/installfiles/mac/ZeroTier One.pkgproj b/ext/installfiles/mac/ZeroTier One.pkgproj index 948070cc..c55ae733 100755 --- a/ext/installfiles/mac/ZeroTier One.pkgproj +++ b/ext/installfiles/mac/ZeroTier One.pkgproj @@ -717,7 +717,7 @@ USE_HFS+_COMPRESSION VERSION - 1.4.4 + 1.4.6
TYPE 0 diff --git a/one.cpp b/one.cpp index b229b98e..06d56e7a 100644 --- a/one.cpp +++ b/one.cpp @@ -83,12 +83,8 @@ using namespace ZeroTier; static OneService *volatile zt1Service = (OneService *)0; #define PROGRAM_NAME "ZeroTier One" -#define COPYRIGHT_NOTICE "Copyright (c) 2011-2018 ZeroTier, Inc." -#define LICENSE_GRANT \ - "This is free software: you may copy, modify, and/or distribute this" ZT_EOL_S \ - "work under the terms of the GNU General Public License, version 3 or" ZT_EOL_S \ - "later as published by the Free Software Foundation." ZT_EOL_S \ - "No warranty expressed or implied." ZT_EOL_S +#define COPYRIGHT_NOTICE "Copyright (c) 2019 ZeroTier, Inc." +#define LICENSE_GRANT "Licensed under the ZeroTier BSL 1.1 (see LICENSE.txt)" /****************************************************************************/ /* zerotier-cli personality */ diff --git a/version.h b/version.h index 7c175456..2e427cc8 100644 --- a/version.h +++ b/version.h @@ -27,7 +27,7 @@ /** * Revision */ -#define ZEROTIER_ONE_VERSION_REVISION 4 +#define ZEROTIER_ONE_VERSION_REVISION 6 /** * Build version diff --git a/windows/WinUI/AboutView.xaml b/windows/WinUI/AboutView.xaml index 3e7b2bd6..d07a8947 100644 --- a/windows/WinUI/AboutView.xaml +++ b/windows/WinUI/AboutView.xaml @@ -19,7 +19,7 @@ - + diff --git a/zerotier-one.spec b/zerotier-one.spec index eb13e679..3767b540 100644 --- a/zerotier-one.spec +++ b/zerotier-one.spec @@ -1,5 +1,5 @@ Name: zerotier-one -Version: 1.4.4 +Version: 1.4.6 Release: 1%{?dist} Summary: ZeroTier One network virtualization service From 4281b6b44826d5f9dcc9cc29677a0f693524866f Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 30 Aug 2019 17:45:10 -0700 Subject: [PATCH 159/185] Ignore MULTICAST_GATHER replies with the wrong count. --- node/IncomingPacket.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 57d691b9..550ab3e5 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -519,7 +519,8 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedP if (network) { const MulticastGroup mg(MAC(field(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_MAC,6),6),at(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_ADI)); const unsigned int count = at(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS + 4); - RR->mc->addMultiple(tPtr,RR->node->now(),networkId,mg,field(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS + 6,count * 5),count,at(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS)); + if (((ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS + 6) + (count * 5)) <= size()) + RR->mc->addMultiple(tPtr,RR->node->now(),networkId,mg,field(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS + 6,count * 5),count,at(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS)); } } break; From a6dff8ff2fe4e6b59a68f14e5aef40721712a70c Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 30 Aug 2019 17:47:13 -0700 Subject: [PATCH 160/185] Add an extra catch as workaround for possible cause of ARM crash. --- node/IncomingPacket.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 550ab3e5..331446ce 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -113,6 +113,9 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr) RR->sw->requestWhois(tPtr,RR->node->now(),sourceAddress); return false; } + } catch (int ztExcCode) { + RR->t->incomingPacketInvalid(tPtr,_path,packetId(),sourceAddress,hops(),verb(),"unexpected exception in tryDecode()"); + return true; } catch ( ... ) { RR->t->incomingPacketInvalid(tPtr,_path,packetId(),sourceAddress,hops(),verb(),"unexpected exception in tryDecode()"); return true; From e6ead3588469c6638028c08e291544873b97ae8d Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 30 Aug 2019 17:48:22 -0700 Subject: [PATCH 161/185] docs --- RELEASE-NOTES.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 5b6d24b7..d56ebac3 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,6 +1,12 @@ ZeroTier Release Notes ====== +# 2019-08-30 -- Version 1.4.6 + + * Update default root list to new roots + * ARM32 platform fixes + * Fix license message in CLI + # 2019-08-23 -- Version 1.4.4 * Change license from GPL3 to BSL 1.1, see LICENSE.txt From 3c0f54257b579fe587b3efcfcdb253b859df8b9c Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 4 Sep 2019 08:19:33 -0700 Subject: [PATCH 162/185] Debian typo fix --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 52f8daea..1eb147e0 100644 --- a/debian/control +++ b/debian/control @@ -11,7 +11,7 @@ Homepage: https://www.zerotier.com/ Package: zerotier-one Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, iproute2, adduser, libstdc++6 -apt-caHomepage: https://www.zerotier.com/ +Homepage: https://www.zerotier.com/ Description: ZeroTier network virtualization service ZeroTier One lets you join ZeroTier virtual networks and have them appear as tun/tap ports on your system. See From 27c8eb0d6d4ed98700550053ba29b1c9a5452a20 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 4 Sep 2019 12:21:51 -0700 Subject: [PATCH 163/185] GitHub issue #1019 --- windows/ZeroTierOne/ZeroTierOne.vcxproj | 15 ++++++++++++++- windows/ZeroTierOne/ZeroTierOneService.cpp | 12 ++++++++---- windows/ZeroTierOne/ZeroTierOneService.h | 5 +++-- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj b/windows/ZeroTierOne/ZeroTierOne.vcxproj index 2bcc8603..1cfe8ae0 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj @@ -113,7 +113,20 @@ - + + false + false + false + true + StreamingSIMDExtensions2 + NoExtensions + false + false + false + false + StreamingSIMDExtensions2 + NoExtensions + diff --git a/windows/ZeroTierOne/ZeroTierOneService.cpp b/windows/ZeroTierOne/ZeroTierOneService.cpp index 9b274d34..7e4cbf02 100644 --- a/windows/ZeroTierOne/ZeroTierOneService.cpp +++ b/windows/ZeroTierOne/ZeroTierOneService.cpp @@ -76,9 +76,7 @@ restart_node: ZeroTier::Mutex::Lock _l(_lock); delete _service; _service = (ZeroTier::OneService *)0; // in case newInstance() fails - _service = ZeroTier::OneService::newInstance( - ZeroTier::OneService::platformDefaultHomePath().c_str(), - ZT_DEFAULT_PORT); + _service = ZeroTier::OneService::newInstance(_path.c_str(), ZT_DEFAULT_PORT); } switch(_service->run()) { case ZeroTier::OneService::ONE_UNRECOVERABLE_ERROR: { @@ -120,10 +118,16 @@ restart_node: } } -void ZeroTierOneService::OnStart(DWORD dwArgc, LPSTR *lpszArgv) +void ZeroTierOneService::OnStart(DWORD dwArgc, PSTR *lpszArgv) { ZT_SVCDBG("ZeroTierOneService::OnStart()\r\n"); + if ((dwArgc > 1)&&(lpszArgv[1])&&(strlen(lpszArgv[1]) > 0)) { + this->_path = lpszArgv[1]; + } else { + this->_path = ZeroTier::OneService::platformDefaultHomePath(); + } + try { _thread = ZeroTier::Thread::start(this); } catch ( ... ) { diff --git a/windows/ZeroTierOne/ZeroTierOneService.h b/windows/ZeroTierOne/ZeroTierOneService.h index dbcd8c6d..c4edb820 100644 --- a/windows/ZeroTierOne/ZeroTierOneService.h +++ b/windows/ZeroTierOne/ZeroTierOneService.h @@ -57,11 +57,12 @@ public: throw(); protected: - virtual void OnStart(DWORD dwArgc, PSTR *pszArgv); - virtual void OnStop(); + virtual void OnStart(DWORD dwArgc, PSTR *pszArgv); + virtual void OnStop(); virtual void OnShutdown(); private: + std::string _path; ZeroTier::OneService *volatile _service; ZeroTier::Mutex _lock; ZeroTier::Thread _thread; From ef69f1bb27f70c4f730af1d976224c50fcd6e7f4 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 4 Sep 2019 12:37:54 -0700 Subject: [PATCH 164/185] ARM wrestling --- make-linux.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/make-linux.mk b/make-linux.mk index 0fe1f051..9b951cbd 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -267,8 +267,8 @@ ifeq ($(ZT_ARCHITECTURE),3) override CXXFLAGS+=-march=armv5 -mfloat-abi=soft -msoft-float -mno-unaligned-access -marm ZT_USE_ARM32_NEON_ASM_CRYPTO=0 else - override CFLAGS+=-march=armv5 -mno-unaligned-access -marm - override CXXFLAGS+=-march=armv5 -mno-unaligned-access -marm + override CFLAGS+=-march=armv5 -mno-unaligned-access -marm -fexceptions + override CXXFLAGS+=-march=armv5 -mno-unaligned-access -marm -fexceptions ZT_USE_ARM32_NEON_ASM_CRYPTO=0 endif endif From a16377cea52aebd669de1b523ddd81b8399a8086 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 4 Sep 2019 12:48:28 -0700 Subject: [PATCH 165/185] Add mitigations against borked ARM32 exception unrollers, possibly fix GitHub issue #1003 --- service/OneService.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/service/OneService.cpp b/service/OneService.cpp index f3ec3e66..1c55ef94 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1353,8 +1353,8 @@ public: if (j.is_object()) { seed = Utils::hexStrToU64(OSUtils::jsonString(j["seed"],"0").c_str()); } + } catch (std::exception &exc) { } catch ( ... ) { - // discard invalid JSON } std::vector moons(_node->moons()); @@ -1403,8 +1403,8 @@ public: json &allowDefault = j["allowDefault"]; if (allowDefault.is_boolean()) localSettings.allowDefault = (bool)allowDefault; } + } catch (std::exception &exc) { } catch ( ... ) { - // discard invalid JSON } setNetworkSettings(nws->networks[i].nwid,localSettings); @@ -2035,6 +2035,8 @@ public: return; } + } catch (std::exception &exc) { + _phy.close(sock); } catch ( ... ) { _phy.close(sock); } @@ -2143,6 +2145,10 @@ public: #endif _nets.erase(nwid); return -999; + } catch (std::exception &exc) { + return -999; + } catch (int exc) { + return -999; } catch ( ... ) { return -999; // tap init failed } From bcdab95e4c5be66c077abd2280a1515dd66a6308 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 4 Sep 2019 14:13:45 -0700 Subject: [PATCH 166/185] Windows installer version bump, build fix. --- ext/installfiles/windows/ZeroTier One.aip | 8 ++++---- service/OneService.cpp | 2 -- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/ext/installfiles/windows/ZeroTier One.aip b/ext/installfiles/windows/ZeroTier One.aip index 83b07c25..4064fda9 100644 --- a/ext/installfiles/windows/ZeroTier One.aip +++ b/ext/installfiles/windows/ZeroTier One.aip @@ -27,10 +27,10 @@ - + - + @@ -64,7 +64,7 @@ - + @@ -454,7 +454,7 @@ - + diff --git a/service/OneService.cpp b/service/OneService.cpp index 1c55ef94..69b439ae 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -2145,8 +2145,6 @@ public: #endif _nets.erase(nwid); return -999; - } catch (std::exception &exc) { - return -999; } catch (int exc) { return -999; } catch ( ... ) { From ecee3100876b03cd8c27ae12142d2eb5233732b3 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 4 Sep 2019 14:17:41 -0700 Subject: [PATCH 167/185] Update built-in root list. --- node/Topology.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/node/Topology.cpp b/node/Topology.cpp index 9b674c21..01a81fcc 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -22,8 +22,8 @@ namespace ZeroTier { -#define ZT_DEFAULT_WORLD_LENGTH 570 -static const unsigned char ZT_DEFAULT_WORLD[ZT_DEFAULT_WORLD_LENGTH] = {0x01,0x00,0x00,0x00,0x00,0x08,0xea,0xc9,0x0a,0x00,0x00,0x01,0x6c,0xe3,0xe2,0x39,0x55,0xb8,0xb3,0x88,0xa4,0x69,0x22,0x14,0x91,0xaa,0x9a,0xcd,0x66,0xcc,0x76,0x4c,0xde,0xfd,0x56,0x03,0x9f,0x10,0x67,0xae,0x15,0xe6,0x9c,0x6f,0xb4,0x2d,0x7b,0x55,0x33,0x0e,0x3f,0xda,0xac,0x52,0x9c,0x07,0x92,0xfd,0x73,0x40,0xa6,0xaa,0x21,0xab,0xa8,0xa4,0x89,0xfd,0xae,0xa4,0x4a,0x39,0xbf,0x2d,0x00,0x65,0x9a,0xc9,0xc8,0x18,0xeb,0x19,0xfe,0x59,0xbb,0x32,0x1b,0x74,0xb9,0x51,0x43,0x5e,0xf3,0xa1,0xc1,0x4b,0xce,0xaf,0x31,0x73,0x7a,0xa6,0x99,0xb5,0xdc,0x99,0xc3,0xce,0xb7,0x9f,0x89,0xfd,0xdf,0x8e,0x34,0xa2,0xc0,0x15,0xa8,0xd2,0xa9,0x8f,0x8d,0x7c,0x96,0x8b,0x85,0x1d,0x22,0x74,0x66,0x23,0x46,0x97,0xd1,0xcd,0xcf,0xb1,0xbc,0x04,0x40,0x43,0xaf,0x44,0x03,0x00,0x76,0xbd,0xbd,0xa3,0xe8,0x74,0x77,0x6c,0xad,0x84,0x17,0x84,0x97,0xd3,0x2c,0xc7,0xbb,0x6a,0xb5,0x1e,0x0c,0x06,0xcb,0x5c,0xa3,0xff,0x32,0x3a,0xaa,0x36,0xd2,0x04,0x3a,0x46,0xf1,0xbf,0x30,0x00,0x76,0xe6,0x6f,0xab,0x33,0xe2,0x85,0x49,0xa6,0x2e,0xe2,0x06,0x4d,0x18,0x43,0x27,0x3c,0x2c,0x30,0x0b,0xa4,0x5c,0x3f,0x20,0xbe,0xf0,0x2d,0xba,0xd2,0x25,0x72,0x3b,0xb5,0x9a,0x9b,0xb4,0xb1,0x35,0x35,0x73,0x09,0x61,0xae,0xec,0xf5,0xa1,0x63,0xac,0xe4,0x77,0xcc,0xeb,0x07,0x27,0x02,0x5b,0x99,0xac,0x14,0xa5,0x16,0x6a,0x09,0xa3,0x00,0x02,0x04,0xb9,0xb4,0x0d,0x52,0x27,0x09,0x06,0x2a,0x02,0x6e,0xa0,0xc8,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0x09,0xde,0x89,0x50,0xa8,0xb2,0x00,0x1b,0x3a,0xda,0x82,0x51,0xb9,0x1b,0x6b,0x6f,0xa6,0x53,0x5b,0x8c,0x7e,0x24,0x60,0x91,0x8f,0x4f,0x72,0x9a,0xbd,0xec,0x97,0xd3,0xc7,0xf3,0x79,0x68,0x68,0xfb,0x02,0xf0,0xde,0x0b,0x0e,0xe5,0x54,0xb2,0xd5,0x9f,0xc3,0x52,0x47,0x43,0xee,0xbf,0xcf,0x53,0x15,0xe7,0x90,0xed,0x6d,0x92,0xdb,0x5b,0xd1,0x0c,0x28,0xc0,0x9b,0x40,0xef,0x00,0x02,0x04,0xcf,0xf6,0x49,0xf5,0x01,0xbb,0x06,0x20,0x01,0x19,0xf0,0x90,0x02,0x05,0xcb,0x0e,0xc4,0x7a,0xff,0xfe,0x8f,0x69,0xd9,0x01,0xbb,0x34,0xe0,0xa5,0xe1,0x74,0x00,0x93,0xef,0xb5,0x09,0x34,0x78,0x8f,0x85,0x6d,0x5c,0xfb,0x9c,0xa5,0xbe,0x88,0xe8,0x5b,0x40,0x96,0x55,0x86,0xb7,0x5b,0xef,0xac,0x90,0x0d,0xf7,0x73,0x52,0xc1,0x45,0xa1,0xba,0x70,0x07,0x56,0x9d,0x37,0xc7,0x7b,0xfe,0x52,0xc0,0x99,0x9f,0x3b,0xdc,0x67,0xa4,0x7a,0x4a,0x60,0x00,0xb7,0x20,0xa8,0x83,0xce,0x47,0xaa,0x2f,0xb7,0xf8,0x00,0x02,0x04,0x93,0x4b,0x5c,0x02,0x01,0xbb,0x06,0x26,0x04,0x13,0x80,0x30,0x00,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0xbb,0x99,0x2f,0xcf,0x1d,0xb7,0x00,0x20,0x6e,0xd5,0x93,0x50,0xb3,0x19,0x16,0xf7,0x49,0xa1,0xf8,0x5d,0xff,0xb3,0xa8,0x78,0x7d,0xcb,0xf8,0x3b,0x8c,0x6e,0x94,0x48,0xd4,0xe3,0xea,0x0e,0x33,0x69,0x30,0x1b,0xe7,0x16,0xc3,0x60,0x93,0x44,0xa9,0xd1,0x53,0x38,0x50,0xfb,0x44,0x60,0xc5,0x0a,0xf4,0x33,0x22,0xbc,0xfc,0x8e,0x13,0xd3,0x30,0x1a,0x1f,0x10,0x03,0xce,0xb6,0x00,0x02,0x04,0xc3,0xb5,0xad,0x9f,0x01,0xbb,0x06,0x2a,0x02,0x6e,0xa0,0xc0,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xbb}; +#define ZT_DEFAULT_WORLD_LENGTH 674 +static const unsigned char ZT_DEFAULT_WORLD[ZT_DEFAULT_WORLD_LENGTH] = {0x01,0x00,0x00,0x00,0x00,0x08,0xea,0xc9,0x0a,0x00,0x00,0x01,0x6c,0xf9,0x10,0xd4,0x79,0xb8,0xb3,0x88,0xa4,0x69,0x22,0x14,0x91,0xaa,0x9a,0xcd,0x66,0xcc,0x76,0x4c,0xde,0xfd,0x56,0x03,0x9f,0x10,0x67,0xae,0x15,0xe6,0x9c,0x6f,0xb4,0x2d,0x7b,0x55,0x33,0x0e,0x3f,0xda,0xac,0x52,0x9c,0x07,0x92,0xfd,0x73,0x40,0xa6,0xaa,0x21,0xab,0xa8,0xa4,0x89,0xfd,0xae,0xa4,0x4a,0x39,0xbf,0x2d,0x00,0x65,0x9a,0xc9,0xc8,0x18,0xeb,0x3e,0x3a,0xe9,0xeb,0x4e,0x78,0x27,0xb8,0xeb,0x78,0xe7,0x0f,0x64,0xa0,0x14,0xce,0x3d,0x30,0x21,0x96,0x23,0x9d,0x07,0x85,0xa4,0x0b,0xc6,0xf3,0x03,0x48,0x12,0x66,0x09,0x2a,0x6f,0xa1,0x5b,0x55,0x71,0x43,0xe7,0x2d,0xb3,0xfc,0xfc,0x8e,0x6f,0xe5,0xbb,0x5d,0x80,0x76,0x28,0x8d,0x32,0x87,0x24,0x3e,0x59,0x32,0x3d,0x9f,0xd1,0x00,0x54,0xd4,0xa2,0x90,0x0d,0xfc,0x3a,0xc9,0x5e,0xd8,0x6b,0x11,0x24,0xf9,0x70,0x8b,0x6e,0xd9,0x09,0xec,0xce,0x59,0x06,0xa6,0x73,0xf4,0x46,0x34,0x45,0xcd,0x57,0x44,0x04,0x3a,0x46,0xf1,0xbf,0x30,0x00,0x76,0xe6,0x6f,0xab,0x33,0xe2,0x85,0x49,0xa6,0x2e,0xe2,0x06,0x4d,0x18,0x43,0x27,0x3c,0x2c,0x30,0x0b,0xa4,0x5c,0x3f,0x20,0xbe,0xf0,0x2d,0xba,0xd2,0x25,0x72,0x3b,0xb5,0x9a,0x9b,0xb4,0xb1,0x35,0x35,0x73,0x09,0x61,0xae,0xec,0xf5,0xa1,0x63,0xac,0xe4,0x77,0xcc,0xeb,0x07,0x27,0x02,0x5b,0x99,0xac,0x14,0xa5,0x16,0x6a,0x09,0xa3,0x00,0x04,0x04,0xb9,0xb4,0x0d,0x52,0x27,0x09,0x06,0x2a,0x02,0x6e,0xa0,0xc8,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0x09,0x04,0xb9,0xb4,0x0d,0x52,0x01,0xbb,0x06,0x2a,0x02,0x6e,0xa0,0xc8,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xbb,0xde,0x89,0x50,0xa8,0xb2,0x00,0x1b,0x3a,0xda,0x82,0x51,0xb9,0x1b,0x6b,0x6f,0xa6,0x53,0x5b,0x8c,0x7e,0x24,0x60,0x91,0x8f,0x4f,0x72,0x9a,0xbd,0xec,0x97,0xd3,0xc7,0xf3,0x79,0x68,0x68,0xfb,0x02,0xf0,0xde,0x0b,0x0e,0xe5,0x54,0xb2,0xd5,0x9f,0xc3,0x52,0x47,0x43,0xee,0xbf,0xcf,0x53,0x15,0xe7,0x90,0xed,0x6d,0x92,0xdb,0x5b,0xd1,0x0c,0x28,0xc0,0x9b,0x40,0xef,0x00,0x04,0x04,0xcf,0xf6,0x49,0xf5,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x90,0x02,0x05,0xcb,0x0e,0xc4,0x7a,0xff,0xfe,0x8f,0x69,0xd9,0x27,0x09,0x04,0xcf,0xf6,0x49,0xf5,0x01,0xbb,0x06,0x20,0x01,0x19,0xf0,0x90,0x02,0x05,0xcb,0x0e,0xc4,0x7a,0xff,0xfe,0x8f,0x69,0xd9,0x01,0xbb,0x34,0xe0,0xa5,0xe1,0x74,0x00,0x93,0xef,0xb5,0x09,0x34,0x78,0x8f,0x85,0x6d,0x5c,0xfb,0x9c,0xa5,0xbe,0x88,0xe8,0x5b,0x40,0x96,0x55,0x86,0xb7,0x5b,0xef,0xac,0x90,0x0d,0xf7,0x73,0x52,0xc1,0x45,0xa1,0xba,0x70,0x07,0x56,0x9d,0x37,0xc7,0x7b,0xfe,0x52,0xc0,0x99,0x9f,0x3b,0xdc,0x67,0xa4,0x7a,0x4a,0x60,0x00,0xb7,0x20,0xa8,0x83,0xce,0x47,0xaa,0x2f,0xb7,0xf8,0x00,0x04,0x04,0x93,0x4b,0x5c,0x02,0x27,0x09,0x06,0x26,0x04,0x13,0x80,0x30,0x00,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x27,0x09,0x04,0x93,0x4b,0x5c,0x02,0x01,0xbb,0x06,0x26,0x04,0x13,0x80,0x30,0x00,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0xbb,0x99,0x2f,0xcf,0x1d,0xb7,0x00,0x20,0x6e,0xd5,0x93,0x50,0xb3,0x19,0x16,0xf7,0x49,0xa1,0xf8,0x5d,0xff,0xb3,0xa8,0x78,0x7d,0xcb,0xf8,0x3b,0x8c,0x6e,0x94,0x48,0xd4,0xe3,0xea,0x0e,0x33,0x69,0x30,0x1b,0xe7,0x16,0xc3,0x60,0x93,0x44,0xa9,0xd1,0x53,0x38,0x50,0xfb,0x44,0x60,0xc5,0x0a,0xf4,0x33,0x22,0xbc,0xfc,0x8e,0x13,0xd3,0x30,0x1a,0x1f,0x10,0x03,0xce,0xb6,0x00,0x04,0x04,0xc3,0xb5,0xad,0x9f,0x27,0x09,0x06,0x2a,0x02,0x6e,0xa0,0xc0,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0x09,0x04,0xc3,0xb5,0xad,0x9f,0x01,0xbb,0x06,0x2a,0x02,0x6e,0xa0,0xc0,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xbb}; Topology::Topology(const RuntimeEnvironment *renv,void *tPtr) : RR(renv), From 8454a14eaca041438e79ff6a376ccfd3df19f5fe Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 4 Sep 2019 14:25:57 -0700 Subject: [PATCH 168/185] new Windows GUID for build #2 --- ext/installfiles/windows/ZeroTier One.aip | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/installfiles/windows/ZeroTier One.aip b/ext/installfiles/windows/ZeroTier One.aip index 4064fda9..61b6ec33 100644 --- a/ext/installfiles/windows/ZeroTier One.aip +++ b/ext/installfiles/windows/ZeroTier One.aip @@ -27,7 +27,7 @@ - + From 0767ea5d693f6c79874e0ddfbc6b4796e64e6951 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 5 Sep 2019 11:02:16 -0700 Subject: [PATCH 169/185] * Update default root list to latest * ARM32 platform build and flag fixes * Add a clarification line to LICENSE.txt * Fix license message in CLI * Windows service now looks for service command line arguments * Fixed a bug that could cause excessive queued multicasts --- RELEASE-NOTES.md | 7 +++++-- make-linux.mk | 8 +------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index d56ebac3..2f3777b4 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -3,9 +3,12 @@ ZeroTier Release Notes # 2019-08-30 -- Version 1.4.6 - * Update default root list to new roots - * ARM32 platform fixes + * Update default root list to latest + * ARM32 platform build and flag fixes + * Add a clarification line to LICENSE.txt * Fix license message in CLI + * Windows service now looks for service command line arguments + * Fixed a bug that could cause excessive queued multicasts # 2019-08-23 -- Version 1.4.4 diff --git a/make-linux.mk b/make-linux.mk index 9b951cbd..9fd4f7b9 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -1,4 +1,4 @@ -# Automagically pick clang or gcc, with preference for clang +# Automagically pick CLANG or RH/CentOS newer GCC if present # This is only done if we have not overridden these with an environment or CLI variable ifeq ($(origin CC),default) CC:=$(shell if [ -e /usr/bin/clang ]; then echo clang; else echo gcc; fi) @@ -18,9 +18,6 @@ include objects.mk ONE_OBJS+=osdep/LinuxEthernetTap.o ONE_OBJS+=osdep/LinuxNetLink.o -NLTEST_OBJS+=osdep/LinuxNetLink.o node/InetAddress.o node/Utils.o node/Salsa20.o -NLTEST_OBJS+=nltest.o - # for central controller builds TIMESTAMP=$(shell date +"%Y%m%d%H%M") @@ -344,9 +341,6 @@ debug: FORCE make ZT_DEBUG=1 one make ZT_DEBUG=1 selftest -nltest: $(NLTEST_OBJS) - $(CXX) $(CXXFLAGS) $(LDFLAGS) -o nltest $(NLTEST_OBJS) $(LDLIBS) - # Note: keep the symlinks in /var/lib/zerotier-one to the binaries since these # provide backward compatibility with old releases where the binaries actually # lived here. Folks got scripts. From de127056c2e7a8de5beb23085d3f18ef962840bf Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 16 Sep 2019 20:13:20 -0700 Subject: [PATCH 170/185] Add notarization to "make official". --- make-mac.mk | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/make-mac.mk b/make-mac.mk index c71b3f77..1fe2d7a4 100644 --- a/make-mac.mk +++ b/make-mac.mk @@ -8,6 +8,8 @@ CODESIGN=echo PRODUCTSIGN=echo CODESIGN_APP_CERT= CODESIGN_INSTALLER_CERT= +NOTARIZE=echo +NOTARIZE_USER_ID=null ZT_BUILD_PLATFORM=3 ZT_BUILD_ARCHITECTURE=2 @@ -34,6 +36,8 @@ ifeq ($(ZT_OFFICIAL_RELEASE),1) PRODUCTSIGN=productsign CODESIGN_APP_CERT="Developer ID Application: ZeroTier, Inc (8ZD9JUCZ4V)" CODESIGN_INSTALLER_CERT="Developer ID Installer: ZeroTier, Inc (8ZD9JUCZ4V)" + NOTARIZE=xcrun altool + NOTARIZE_USER_ID="adam.ierymenko@gmail.com" else DEFS+=-DZT_SOFTWARE_UPDATE_DEFAULT="\"download\"" endif @@ -76,7 +80,7 @@ ifeq ($(ZT_VAULT_SUPPORT),1) LIBS+=-lcurl endif -CXXFLAGS=$(CFLAGS) -std=c++11 -stdlib=libc++ +CXXFLAGS=$(CFLAGS) -std=c++11 -stdlib=libc++ all: one macui @@ -131,6 +135,8 @@ mac-dist-pkg: FORCE if [ -f "ZeroTier One Signed.pkg" ]; then mv -f "ZeroTier One Signed.pkg" "ZeroTier One.pkg"; fi rm -f zt1_update_$(ZT_BUILD_PLATFORM)_$(ZT_BUILD_ARCHITECTURE)_* cat ext/installfiles/mac-update/updater.tmpl.sh "ZeroTier One.pkg" >zt1_update_$(ZT_BUILD_PLATFORM)_$(ZT_BUILD_ARCHITECTURE)_$(ZT_VERSION_MAJOR).$(ZT_VERSION_MINOR).$(ZT_VERSION_REV)_$(ZT_VERSION_BUILD).exe + $(NOTARIZE) -t osx -f "ZeroTier One.pkg" --primary-bundle-id --output-format xml --notarize-app -u $(NOTARIZE_USER_ID) + echo '*** When Apple notifies that the app is notarized, run: xcrun stapler staple "ZeroTier One.pkg"' # For ZeroTier, Inc. to build official signed packages official: FORCE From bad95d7c675f04aa10773d46901d65342382c03c Mon Sep 17 00:00:00 2001 From: Travis LaDuke Date: Tue, 15 Oct 2019 13:13:08 -0700 Subject: [PATCH 171/185] Update cli help to say instead of Closes #1054 --- one.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/one.cpp b/one.cpp index 06d56e7a..99a3a575 100644 --- a/one.cpp +++ b/one.cpp @@ -115,10 +115,10 @@ static void cliPrintHelp(const char *pn,FILE *out) fprintf(out," listpeers - List all peers" ZT_EOL_S); fprintf(out," peers - List all peers (prettier)" ZT_EOL_S); fprintf(out," listnetworks - List all networks" ZT_EOL_S); - fprintf(out," join - Join a network" ZT_EOL_S); - fprintf(out," leave - Leave a network" ZT_EOL_S); - fprintf(out," set - Set a network setting" ZT_EOL_S); - fprintf(out," get - Get a network setting" ZT_EOL_S); + fprintf(out," join - Join a network" ZT_EOL_S); + fprintf(out," leave - Leave a network" ZT_EOL_S); + fprintf(out," set - Set a network setting" ZT_EOL_S); + fprintf(out," get - Get a network setting" ZT_EOL_S); fprintf(out," listmoons - List moons (federated root sets)" ZT_EOL_S); fprintf(out," orbit - Join a moon via any member root" ZT_EOL_S); fprintf(out," deorbit - Leave a moon" ZT_EOL_S); @@ -126,7 +126,7 @@ static void cliPrintHelp(const char *pn,FILE *out) fprintf(out," Settings to use with [get/set] may include property names from " ZT_EOL_S); fprintf(out," the JSON output of \"zerotier-cli -j listnetworks\". Additionally, " ZT_EOL_S); fprintf(out," (ip, ip4, ip6, ip6plane, and ip6prefix can be used). For instance:" ZT_EOL_S); - fprintf(out," zerotier-cli get ip6plane will return the 6PLANE address" ZT_EOL_S); + fprintf(out," zerotier-cli get ip6plane will return the 6PLANE address" ZT_EOL_S); fprintf(out," assigned to this node." ZT_EOL_S); } From 74478b24b0542e8b454f60cb99ff78099f550464 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Thu, 31 Oct 2019 14:04:25 -0700 Subject: [PATCH 172/185] add librabbitmq binaries for macos for testing central controller --- ext/librabbitmq/macos/include/amqp.h | 2538 +++++++++++++++++ ext/librabbitmq/macos/include/amqp_framing.h | 1144 ++++++++ .../macos/include/amqp_tcp_socket.h | 68 + ext/librabbitmq/macos/lib/librabbitmq.a | Bin 0 -> 95704 bytes make-mac.mk | 3 +- 5 files changed, 3752 insertions(+), 1 deletion(-) create mode 100644 ext/librabbitmq/macos/include/amqp.h create mode 100644 ext/librabbitmq/macos/include/amqp_framing.h create mode 100644 ext/librabbitmq/macos/include/amqp_tcp_socket.h create mode 100644 ext/librabbitmq/macos/lib/librabbitmq.a diff --git a/ext/librabbitmq/macos/include/amqp.h b/ext/librabbitmq/macos/include/amqp.h new file mode 100644 index 00000000..2983b166 --- /dev/null +++ b/ext/librabbitmq/macos/include/amqp.h @@ -0,0 +1,2538 @@ +/** \file */ +/* + * ***** BEGIN LICENSE BLOCK ***** + * Version: MIT + * + * Portions created by Alan Antonuk are Copyright (c) 2012-2014 + * Alan Antonuk. All Rights Reserved. + * + * Portions created by VMware are Copyright (c) 2007-2012 VMware, Inc. + * All Rights Reserved. + * + * Portions created by Tony Garnock-Jones are Copyright (c) 2009-2010 + * VMware, Inc. and Tony Garnock-Jones. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * ***** END LICENSE BLOCK ***** + */ + +#ifndef AMQP_H +#define AMQP_H + +/** \cond HIDE_FROM_DOXYGEN */ + +#ifdef __cplusplus +#define AMQP_BEGIN_DECLS extern "C" { +#define AMQP_END_DECLS } +#else +#define AMQP_BEGIN_DECLS +#define AMQP_END_DECLS +#endif + +/* + * \internal + * Important API decorators: + * AMQP_PUBLIC_FUNCTION - a public API function + * AMQP_PUBLIC_VARIABLE - a public API external variable + * AMQP_CALL - calling convension (used on Win32) + */ + +#if defined(_WIN32) && defined(_MSC_VER) +#if defined(AMQP_BUILD) && !defined(AMQP_STATIC) +#define AMQP_PUBLIC_FUNCTION __declspec(dllexport) +#define AMQP_PUBLIC_VARIABLE __declspec(dllexport) extern +#else +#define AMQP_PUBLIC_FUNCTION +#if !defined(AMQP_STATIC) +#define AMQP_PUBLIC_VARIABLE __declspec(dllimport) extern +#else +#define AMQP_PUBLIC_VARIABLE extern +#endif +#endif +#define AMQP_CALL __cdecl + +#elif defined(_WIN32) && defined(__BORLANDC__) +#if defined(AMQP_BUILD) && !defined(AMQP_STATIC) +#define AMQP_PUBLIC_FUNCTION __declspec(dllexport) +#define AMQP_PUBLIC_VARIABLE __declspec(dllexport) extern +#else +#define AMQP_PUBLIC_FUNCTION +#if !defined(AMQP_STATIC) +#define AMQP_PUBLIC_VARIABLE __declspec(dllimport) extern +#else +#define AMQP_PUBLIC_VARIABLE extern +#endif +#endif +#define AMQP_CALL __cdecl + +#elif defined(_WIN32) && defined(__MINGW32__) +#if defined(AMQP_BUILD) && !defined(AMQP_STATIC) +#define AMQP_PUBLIC_FUNCTION __declspec(dllexport) +#define AMQP_PUBLIC_VARIABLE __declspec(dllexport) extern +#else +#define AMQP_PUBLIC_FUNCTION +#if !defined(AMQP_STATIC) +#define AMQP_PUBLIC_VARIABLE __declspec(dllimport) extern +#else +#define AMQP_PUBLIC_VARIABLE extern +#endif +#endif +#define AMQP_CALL __cdecl + +#elif defined(_WIN32) && defined(__CYGWIN__) +#if defined(AMQP_BUILD) && !defined(AMQP_STATIC) +#define AMQP_PUBLIC_FUNCTION __declspec(dllexport) +#define AMQP_PUBLIC_VARIABLE __declspec(dllexport) +#else +#define AMQP_PUBLIC_FUNCTION +#if !defined(AMQP_STATIC) +#define AMQP_PUBLIC_VARIABLE __declspec(dllimport) extern +#else +#define AMQP_PUBLIC_VARIABLE extern +#endif +#endif +#define AMQP_CALL __cdecl + +#elif defined(__GNUC__) && __GNUC__ >= 4 +#define AMQP_PUBLIC_FUNCTION __attribute__((visibility("default"))) +#define AMQP_PUBLIC_VARIABLE __attribute__((visibility("default"))) extern +#define AMQP_CALL +#else +#define AMQP_PUBLIC_FUNCTION +#define AMQP_PUBLIC_VARIABLE extern +#define AMQP_CALL +#endif + +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) +#define AMQP_DEPRECATED(function) function __attribute__((__deprecated__)) +#elif defined(_MSC_VER) +#define AMQP_DEPRECATED(function) __declspec(deprecated) function +#else +#define AMQP_DEPRECATED(function) +#endif + +/* Define ssize_t on Win32/64 platforms + See: http://lists.cs.uiuc.edu/pipermail/llvmdev/2010-April/030649.html for + details + */ +#if !defined(_W64) +#if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +#define _W64 __w64 +#else +#define _W64 +#endif +#endif + +#ifdef _MSC_VER +#ifdef _WIN64 +typedef __int64 ssize_t; +#else +typedef _W64 int ssize_t; +#endif +#endif + +#if defined(_WIN32) && defined(__MINGW32__) +#include +#endif + +/** \endcond */ + +#include +#include + +struct timeval; + +AMQP_BEGIN_DECLS + +/** + * \def AMQP_VERSION_MAJOR + * + * Major library version number compile-time constant + * + * The major version is incremented when backwards incompatible API changes + * are made. + * + * \sa AMQP_VERSION, AMQP_VERSION_STRING + * + * \since v0.4.0 + */ + +/** + * \def AMQP_VERSION_MINOR + * + * Minor library version number compile-time constant + * + * The minor version is incremented when new APIs are added. Existing APIs + * are left alone. + * + * \sa AMQP_VERSION, AMQP_VERSION_STRING + * + * \since v0.4.0 + */ + +/** + * \def AMQP_VERSION_PATCH + * + * Patch library version number compile-time constant + * + * The patch version is incremented when library code changes, but the API + * is not changed. + * + * \sa AMQP_VERSION, AMQP_VERSION_STRING + * + * \since v0.4.0 + */ + +/** + * \def AMQP_VERSION_IS_RELEASE + * + * Version constant set to 1 for tagged release, 0 otherwise + * + * NOTE: versions that are not tagged releases are not guaranteed to be API/ABI + * compatible with older releases, and may change commit-to-commit. + * + * \sa AMQP_VERSION, AMQP_VERSION_STRING + * + * \since v0.4.0 + */ +/* + * Developer note: when changing these, be sure to update SOVERSION constants + * in CMakeLists.txt and configure.ac + */ + +#define AMQP_VERSION_MAJOR 0 +#define AMQP_VERSION_MINOR 10 +#define AMQP_VERSION_PATCH 0 +#define AMQP_VERSION_IS_RELEASE 0 + +/** + * \def AMQP_VERSION_CODE + * + * Helper macro to geneate a packed version code suitable for + * comparison with AMQP_VERSION. + * + * \sa amqp_version_number() AMQP_VERSION_MAJOR, AMQP_VERSION_MINOR, + * AMQP_VERSION_PATCH, AMQP_VERSION_IS_RELEASE, AMQP_VERSION + * + * \since v0.6.1 + */ +#define AMQP_VERSION_CODE(major, minor, patch, release) \ + ((major << 24) | (minor << 16) | (patch << 8) | (release)) + +/** + * \def AMQP_VERSION + * + * Packed version number + * + * AMQP_VERSION is a 4-byte unsigned integer with the most significant byte + * set to AMQP_VERSION_MAJOR, the second most significant byte set to + * AMQP_VERSION_MINOR, third most significant byte set to AMQP_VERSION_PATCH, + * and the lowest byte set to AMQP_VERSION_IS_RELEASE. + * + * For example version 2.3.4 which is released version would be encoded as + * 0x02030401 + * + * \sa amqp_version_number() AMQP_VERSION_MAJOR, AMQP_VERSION_MINOR, + * AMQP_VERSION_PATCH, AMQP_VERSION_IS_RELEASE, AMQP_VERSION_CODE + * + * \since v0.4.0 + */ +#define AMQP_VERSION \ + AMQP_VERSION_CODE(AMQP_VERSION_MAJOR, AMQP_VERSION_MINOR, \ + AMQP_VERSION_PATCH, AMQP_VERSION_IS_RELEASE) + +/** \cond HIDE_FROM_DOXYGEN */ +#define AMQ_STRINGIFY(s) AMQ_STRINGIFY_HELPER(s) +#define AMQ_STRINGIFY_HELPER(s) #s + +#define AMQ_VERSION_STRING \ + AMQ_STRINGIFY(AMQP_VERSION_MAJOR) \ + "." AMQ_STRINGIFY(AMQP_VERSION_MINOR) "." AMQ_STRINGIFY(AMQP_VERSION_PATCH) +/** \endcond */ + +/** + * \def AMQP_VERSION_STRING + * + * Version string compile-time constant + * + * Non-released versions of the library will have "-pre" appended to the + * version string + * + * \sa amqp_version() + * + * \since v0.4.0 + */ +#if AMQP_VERSION_IS_RELEASE +#define AMQP_VERSION_STRING AMQ_VERSION_STRING +#else +#define AMQP_VERSION_STRING AMQ_VERSION_STRING "-pre" +#endif + +/** + * Returns the rabbitmq-c version as a packed integer. + * + * See \ref AMQP_VERSION + * + * \return packed 32-bit integer representing version of library at runtime + * + * \sa AMQP_VERSION, amqp_version() + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +uint32_t AMQP_CALL amqp_version_number(void); + +/** + * Returns the rabbitmq-c version as a string. + * + * See \ref AMQP_VERSION_STRING + * + * \return a statically allocated string describing the version of rabbitmq-c. + * + * \sa amqp_version_number(), AMQP_VERSION_STRING, AMQP_VERSION + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +char const *AMQP_CALL amqp_version(void); + +/** + * \def AMQP_DEFAULT_FRAME_SIZE + * + * Default frame size (128Kb) + * + * \sa amqp_login(), amqp_login_with_properties() + * + * \since v0.4.0 + */ +#define AMQP_DEFAULT_FRAME_SIZE 131072 + +/** + * \def AMQP_DEFAULT_MAX_CHANNELS + * + * Default maximum number of channels (2047, RabbitMQ default limit of 2048, + * minus 1 for channel 0). RabbitMQ set a default limit of 2048 channels per + * connection in v3.7.5 to prevent broken clients from leaking too many + * channels. + * + * \sa amqp_login(), amqp_login_with_properties() + * + * \since v0.4.0 + */ +#define AMQP_DEFAULT_MAX_CHANNELS 2047 + +/** + * \def AMQP_DEFAULT_HEARTBEAT + * + * Default heartbeat interval (0, heartbeat disabled) + * + * \sa amqp_login(), amqp_login_with_properties() + * + * \since v0.4.0 + */ +#define AMQP_DEFAULT_HEARTBEAT 0 + +/** + * \def AMQP_DEFAULT_VHOST + * + * Default RabbitMQ vhost: "/" + * + * \sa amqp_login(), amqp_login_with_properties() + * + * \since v0.9.0 + */ +#define AMQP_DEFAULT_VHOST "/" + +/** + * boolean type 0 = false, true otherwise + * + * \since v0.1 + */ +typedef int amqp_boolean_t; + +/** + * Method number + * + * \since v0.1 + */ +typedef uint32_t amqp_method_number_t; + +/** + * Bitmask for flags + * + * \since v0.1 + */ +typedef uint32_t amqp_flags_t; + +/** + * Channel type + * + * \since v0.1 + */ +typedef uint16_t amqp_channel_t; + +/** + * Buffer descriptor + * + * \since v0.1 + */ +typedef struct amqp_bytes_t_ { + size_t len; /**< length of the buffer in bytes */ + void *bytes; /**< pointer to the beginning of the buffer */ +} amqp_bytes_t; + +/** + * Decimal data type + * + * \since v0.1 + */ +typedef struct amqp_decimal_t_ { + uint8_t decimals; /**< the location of the decimal point */ + uint32_t value; /**< the value before the decimal point is applied */ +} amqp_decimal_t; + +/** + * AMQP field table + * + * An AMQP field table is a set of key-value pairs. + * A key is a UTF-8 encoded string up to 128 bytes long, and are not null + * terminated. + * A value can be one of several different datatypes. \sa + * amqp_field_value_kind_t + * + * \sa amqp_table_entry_t + * + * \since v0.1 + */ +typedef struct amqp_table_t_ { + int num_entries; /**< length of entries array */ + struct amqp_table_entry_t_ *entries; /**< an array of table entries */ +} amqp_table_t; + +/** + * An AMQP Field Array + * + * A repeated set of field values, all must be of the same type + * + * \since v0.1 + */ +typedef struct amqp_array_t_ { + int num_entries; /**< Number of entries in the table */ + struct amqp_field_value_t_ *entries; /**< linked list of field values */ +} amqp_array_t; + +/* + 0-9 0-9-1 Qpid/Rabbit Type Remarks +--------------------------------------------------------------------------- + t t Boolean + b b Signed 8-bit + B Unsigned 8-bit + U s Signed 16-bit (A1) + u Unsigned 16-bit + I I I Signed 32-bit + i Unsigned 32-bit + L l Signed 64-bit (B) + l Unsigned 64-bit + f f 32-bit float + d d 64-bit float + D D D Decimal + s Short string (A2) + S S S Long string + A Nested Array + T T T Timestamp (u64) + F F F Nested Table + V V V Void + x Byte array + +Remarks: + + A1, A2: Notice how the types **CONFLICT** here. In Qpid and Rabbit, + 's' means a signed 16-bit integer; in 0-9-1, it means a + short string. + + B: Notice how the signednesses **CONFLICT** here. In Qpid and Rabbit, + 'l' means a signed 64-bit integer; in 0-9-1, it means an unsigned + 64-bit integer. + +I'm going with the Qpid/Rabbit types, where there's a conflict, and +the 0-9-1 types otherwise. 0-8 is a subset of 0-9, which is a subset +of the other two, so this will work for both 0-8 and 0-9-1 branches of +the code. +*/ + +/** + * A field table value + * + * \since v0.1 + */ +typedef struct amqp_field_value_t_ { + uint8_t kind; /**< the type of the entry /sa amqp_field_value_kind_t */ + union { + amqp_boolean_t boolean; /**< boolean type AMQP_FIELD_KIND_BOOLEAN */ + int8_t i8; /**< int8_t type AMQP_FIELD_KIND_I8 */ + uint8_t u8; /**< uint8_t type AMQP_FIELD_KIND_U8 */ + int16_t i16; /**< int16_t type AMQP_FIELD_KIND_I16 */ + uint16_t u16; /**< uint16_t type AMQP_FIELD_KIND_U16 */ + int32_t i32; /**< int32_t type AMQP_FIELD_KIND_I32 */ + uint32_t u32; /**< uint32_t type AMQP_FIELD_KIND_U32 */ + int64_t i64; /**< int64_t type AMQP_FIELD_KIND_I64 */ + uint64_t u64; /**< uint64_t type AMQP_FIELD_KIND_U64, + AMQP_FIELD_KIND_TIMESTAMP */ + float f32; /**< float type AMQP_FIELD_KIND_F32 */ + double f64; /**< double type AMQP_FIELD_KIND_F64 */ + amqp_decimal_t decimal; /**< amqp_decimal_t AMQP_FIELD_KIND_DECIMAL */ + amqp_bytes_t bytes; /**< amqp_bytes_t type AMQP_FIELD_KIND_UTF8, + AMQP_FIELD_KIND_BYTES */ + amqp_table_t table; /**< amqp_table_t type AMQP_FIELD_KIND_TABLE */ + amqp_array_t array; /**< amqp_array_t type AMQP_FIELD_KIND_ARRAY */ + } value; /**< a union of the value */ +} amqp_field_value_t; + +/** + * An entry in a field-table + * + * \sa amqp_table_encode(), amqp_table_decode(), amqp_table_clone() + * + * \since v0.1 + */ +typedef struct amqp_table_entry_t_ { + amqp_bytes_t key; /**< the table entry key. Its a null-terminated UTF-8 + * string, with a maximum size of 128 bytes */ + amqp_field_value_t value; /**< the table entry values */ +} amqp_table_entry_t; + +/** + * Field value types + * + * \since v0.1 + */ +typedef enum { + AMQP_FIELD_KIND_BOOLEAN = + 't', /**< boolean type. 0 = false, 1 = true @see amqp_boolean_t */ + AMQP_FIELD_KIND_I8 = 'b', /**< 8-bit signed integer, datatype: int8_t */ + AMQP_FIELD_KIND_U8 = 'B', /**< 8-bit unsigned integer, datatype: uint8_t */ + AMQP_FIELD_KIND_I16 = 's', /**< 16-bit signed integer, datatype: int16_t */ + AMQP_FIELD_KIND_U16 = 'u', /**< 16-bit unsigned integer, datatype: uint16_t */ + AMQP_FIELD_KIND_I32 = 'I', /**< 32-bit signed integer, datatype: int32_t */ + AMQP_FIELD_KIND_U32 = 'i', /**< 32-bit unsigned integer, datatype: uint32_t */ + AMQP_FIELD_KIND_I64 = 'l', /**< 64-bit signed integer, datatype: int64_t */ + AMQP_FIELD_KIND_U64 = 'L', /**< 64-bit unsigned integer, datatype: uint64_t */ + AMQP_FIELD_KIND_F32 = + 'f', /**< single-precision floating point value, datatype: float */ + AMQP_FIELD_KIND_F64 = + 'd', /**< double-precision floating point value, datatype: double */ + AMQP_FIELD_KIND_DECIMAL = + 'D', /**< amqp-decimal value, datatype: amqp_decimal_t */ + AMQP_FIELD_KIND_UTF8 = 'S', /**< UTF-8 null-terminated character string, + datatype: amqp_bytes_t */ + AMQP_FIELD_KIND_ARRAY = 'A', /**< field array (repeated values of another + datatype. datatype: amqp_array_t */ + AMQP_FIELD_KIND_TIMESTAMP = 'T', /**< 64-bit timestamp. datatype uint64_t */ + AMQP_FIELD_KIND_TABLE = 'F', /**< field table. encapsulates a table inside a + table entry. datatype: amqp_table_t */ + AMQP_FIELD_KIND_VOID = 'V', /**< empty entry */ + AMQP_FIELD_KIND_BYTES = + 'x' /**< unformatted byte string, datatype: amqp_bytes_t */ +} amqp_field_value_kind_t; + +/** + * A list of allocation blocks + * + * \since v0.1 + */ +typedef struct amqp_pool_blocklist_t_ { + int num_blocks; /**< Number of blocks in the block list */ + void **blocklist; /**< Array of memory blocks */ +} amqp_pool_blocklist_t; + +/** + * A memory pool + * + * \since v0.1 + */ +typedef struct amqp_pool_t_ { + size_t pagesize; /**< the size of the page in bytes. Allocations less than or + * equal to this size are allocated in the pages block list. + * Allocations greater than this are allocated in their own + * own block in the large_blocks block list */ + + amqp_pool_blocklist_t pages; /**< blocks that are the size of pagesize */ + amqp_pool_blocklist_t + large_blocks; /**< allocations larger than the pagesize */ + + int next_page; /**< an index to the next unused page block */ + char *alloc_block; /**< pointer to the current allocation block */ + size_t alloc_used; /**< number of bytes in the current allocation block that + has been used */ +} amqp_pool_t; + +/** + * An amqp method + * + * \since v0.1 + */ +typedef struct amqp_method_t_ { + amqp_method_number_t id; /**< the method id number */ + void *decoded; /**< pointer to the decoded method, + * cast to the appropriate type to use */ +} amqp_method_t; + +/** + * An AMQP frame + * + * \since v0.1 + */ +typedef struct amqp_frame_t_ { + uint8_t frame_type; /**< frame type. The types: + * - AMQP_FRAME_METHOD - use the method union member + * - AMQP_FRAME_HEADER - use the properties union member + * - AMQP_FRAME_BODY - use the body_fragment union member + */ + amqp_channel_t channel; /**< the channel the frame was received on */ + union { + amqp_method_t + method; /**< a method, use if frame_type == AMQP_FRAME_METHOD */ + struct { + uint16_t class_id; /**< the class for the properties */ + uint64_t body_size; /**< size of the body in bytes */ + void *decoded; /**< the decoded properties */ + amqp_bytes_t raw; /**< amqp-encoded properties structure */ + } properties; /**< message header, a.k.a., properties, + use if frame_type == AMQP_FRAME_HEADER */ + amqp_bytes_t body_fragment; /**< a body fragment, use if frame_type == + AMQP_FRAME_BODY */ + struct { + uint8_t transport_high; /**< @internal first byte of handshake */ + uint8_t transport_low; /**< @internal second byte of handshake */ + uint8_t protocol_version_major; /**< @internal third byte of handshake */ + uint8_t protocol_version_minor; /**< @internal fourth byte of handshake */ + } protocol_header; /**< Used only when doing the initial handshake with the + broker, don't use otherwise */ + } payload; /**< the payload of the frame */ +} amqp_frame_t; + +/** + * Response type + * + * \since v0.1 + */ +typedef enum amqp_response_type_enum_ { + AMQP_RESPONSE_NONE = 0, /**< the library got an EOF from the socket */ + AMQP_RESPONSE_NORMAL, /**< response normal, the RPC completed successfully */ + AMQP_RESPONSE_LIBRARY_EXCEPTION, /**< library error, an error occurred in the + library, examine the library_error */ + AMQP_RESPONSE_SERVER_EXCEPTION /**< server exception, the broker returned an + error, check replay */ +} amqp_response_type_enum; + +/** + * Reply from a RPC method on the broker + * + * \since v0.1 + */ +typedef struct amqp_rpc_reply_t_ { + amqp_response_type_enum reply_type; /**< the reply type: + * - AMQP_RESPONSE_NORMAL - the RPC + * completed successfully + * - AMQP_RESPONSE_SERVER_EXCEPTION - the + * broker returned + * an exception, check the reply field + * - AMQP_RESPONSE_LIBRARY_EXCEPTION - the + * library + * encountered an error, check the + * library_error field + */ + amqp_method_t reply; /**< in case of AMQP_RESPONSE_SERVER_EXCEPTION this + * field will be set to the method returned from the + * broker */ + int library_error; /**< in case of AMQP_RESPONSE_LIBRARY_EXCEPTION this + * field will be set to an error code. An error + * string can be retrieved using amqp_error_string */ +} amqp_rpc_reply_t; + +/** + * SASL method type + * + * \since v0.1 + */ +typedef enum amqp_sasl_method_enum_ { + AMQP_SASL_METHOD_UNDEFINED = -1, /**< Invalid SASL method */ + AMQP_SASL_METHOD_PLAIN = + 0, /**< the PLAIN SASL method for authentication to the broker */ + AMQP_SASL_METHOD_EXTERNAL = + 1 /**< the EXTERNAL SASL method for authentication to the broker */ +} amqp_sasl_method_enum; + +/** + * connection state object + * + * \since v0.1 + */ +typedef struct amqp_connection_state_t_ *amqp_connection_state_t; + +/** + * Socket object + * + * \since v0.4.0 + */ +typedef struct amqp_socket_t_ amqp_socket_t; + +/** + * Status codes + * + * \since v0.4.0 + */ +/* NOTE: When updating this enum, update the strings in librabbitmq/amqp_api.c + */ +typedef enum amqp_status_enum_ { + AMQP_STATUS_OK = 0x0, /**< Operation successful */ + AMQP_STATUS_NO_MEMORY = -0x0001, /**< Memory allocation + failed */ + AMQP_STATUS_BAD_AMQP_DATA = -0x0002, /**< Incorrect or corrupt + data was received from + the broker. This is a + protocol error. */ + AMQP_STATUS_UNKNOWN_CLASS = -0x0003, /**< An unknown AMQP class + was received. This is + a protocol error. */ + AMQP_STATUS_UNKNOWN_METHOD = -0x0004, /**< An unknown AMQP method + was received. This is + a protocol error. */ + AMQP_STATUS_HOSTNAME_RESOLUTION_FAILED = -0x0005, /**< Unable to resolve the + * hostname */ + AMQP_STATUS_INCOMPATIBLE_AMQP_VERSION = -0x0006, /**< The broker advertised + an incompaible AMQP + version */ + AMQP_STATUS_CONNECTION_CLOSED = -0x0007, /**< The connection to the + broker has been closed + */ + AMQP_STATUS_BAD_URL = -0x0008, /**< malformed AMQP URL */ + AMQP_STATUS_SOCKET_ERROR = -0x0009, /**< A socket error + occurred */ + AMQP_STATUS_INVALID_PARAMETER = -0x000A, /**< An invalid parameter + was passed into the + function */ + AMQP_STATUS_TABLE_TOO_BIG = -0x000B, /**< The amqp_table_t object + cannot be serialized + because the output + buffer is too small */ + AMQP_STATUS_WRONG_METHOD = -0x000C, /**< The wrong method was + received */ + AMQP_STATUS_TIMEOUT = -0x000D, /**< Operation timed out */ + AMQP_STATUS_TIMER_FAILURE = -0x000E, /**< The underlying system + timer facility failed */ + AMQP_STATUS_HEARTBEAT_TIMEOUT = -0x000F, /**< Timed out waiting for + heartbeat */ + AMQP_STATUS_UNEXPECTED_STATE = -0x0010, /**< Unexpected protocol + state */ + AMQP_STATUS_SOCKET_CLOSED = -0x0011, /**< Underlying socket is + closed */ + AMQP_STATUS_SOCKET_INUSE = -0x0012, /**< Underlying socket is + already open */ + AMQP_STATUS_BROKER_UNSUPPORTED_SASL_METHOD = -0x0013, /**< Broker does not + support the requested + SASL mechanism */ + AMQP_STATUS_UNSUPPORTED = -0x0014, /**< Parameter is unsupported + in this version */ + _AMQP_STATUS_NEXT_VALUE = -0x0015, /**< Internal value */ + + AMQP_STATUS_TCP_ERROR = -0x0100, /**< A generic TCP error + occurred */ + AMQP_STATUS_TCP_SOCKETLIB_INIT_ERROR = -0x0101, /**< An error occurred trying + to initialize the + socket library*/ + _AMQP_STATUS_TCP_NEXT_VALUE = -0x0102, /**< Internal value */ + + AMQP_STATUS_SSL_ERROR = -0x0200, /**< A generic SSL error + occurred. */ + AMQP_STATUS_SSL_HOSTNAME_VERIFY_FAILED = -0x0201, /**< SSL validation of + hostname against + peer certificate + failed */ + AMQP_STATUS_SSL_PEER_VERIFY_FAILED = -0x0202, /**< SSL validation of peer + certificate failed. */ + AMQP_STATUS_SSL_CONNECTION_FAILED = -0x0203, /**< SSL handshake failed. */ + _AMQP_STATUS_SSL_NEXT_VALUE = -0x0204 /**< Internal value */ +} amqp_status_enum; + +/** + * AMQP delivery modes. + * Use these values for the #amqp_basic_properties_t::delivery_mode field. + * + * \since v0.5 + */ +typedef enum { + AMQP_DELIVERY_NONPERSISTENT = 1, /**< Non-persistent message */ + AMQP_DELIVERY_PERSISTENT = 2 /**< Persistent message */ +} amqp_delivery_mode_enum; + +AMQP_END_DECLS + +#include + +AMQP_BEGIN_DECLS + +/** + * Empty bytes structure + * + * \since v0.2 + */ +AMQP_PUBLIC_VARIABLE const amqp_bytes_t amqp_empty_bytes; + +/** + * Empty table structure + * + * \since v0.2 + */ +AMQP_PUBLIC_VARIABLE const amqp_table_t amqp_empty_table; + +/** + * Empty table array structure + * + * \since v0.2 + */ +AMQP_PUBLIC_VARIABLE const amqp_array_t amqp_empty_array; + +/* Compatibility macros for the above, to avoid the need to update + code written against earlier versions of librabbitmq. */ + +/** + * \def AMQP_EMPTY_BYTES + * + * Deprecated, use \ref amqp_empty_bytes instead + * + * \deprecated use \ref amqp_empty_bytes instead + * + * \since v0.1 + */ +#define AMQP_EMPTY_BYTES amqp_empty_bytes + +/** + * \def AMQP_EMPTY_TABLE + * + * Deprecated, use \ref amqp_empty_table instead + * + * \deprecated use \ref amqp_empty_table instead + * + * \since v0.1 + */ +#define AMQP_EMPTY_TABLE amqp_empty_table + +/** + * \def AMQP_EMPTY_ARRAY + * + * Deprecated, use \ref amqp_empty_array instead + * + * \deprecated use \ref amqp_empty_array instead + * + * \since v0.1 + */ +#define AMQP_EMPTY_ARRAY amqp_empty_array + +/** + * Initializes an amqp_pool_t memory allocation pool for use + * + * Readies an allocation pool for use. An amqp_pool_t + * must be initialized before use + * + * \param [in] pool the amqp_pool_t structure to initialize. + * Calling this function on a pool a pool that has + * already been initialized will result in undefined + * behavior + * \param [in] pagesize the unit size that the pool will allocate + * memory chunks in. Anything allocated against the pool + * with a requested size will be carved out of a block + * this size. Allocations larger than this will be + * allocated individually + * + * \sa recycle_amqp_pool(), empty_amqp_pool(), amqp_pool_alloc(), + * amqp_pool_alloc_bytes(), amqp_pool_t + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +void AMQP_CALL init_amqp_pool(amqp_pool_t *pool, size_t pagesize); + +/** + * Recycles an amqp_pool_t memory allocation pool + * + * Recycles the space allocate by the pool + * + * This invalidates all allocations made against the pool before this call is + * made, any use of any allocations made before recycle_amqp_pool() is called + * will result in undefined behavior. + * + * Note: this may or may not release memory, to force memory to be released + * call empty_amqp_pool(). + * + * \param [in] pool the amqp_pool_t to recycle + * + * \sa recycle_amqp_pool(), empty_amqp_pool(), amqp_pool_alloc(), + * amqp_pool_alloc_bytes() + * + * \since v0.1 + * + */ +AMQP_PUBLIC_FUNCTION +void AMQP_CALL recycle_amqp_pool(amqp_pool_t *pool); + +/** + * Empties an amqp memory pool + * + * Releases all memory associated with an allocation pool + * + * \param [in] pool the amqp_pool_t to empty + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +void AMQP_CALL empty_amqp_pool(amqp_pool_t *pool); + +/** + * Allocates a block of memory from an amqp_pool_t memory pool + * + * Memory will be aligned on a 8-byte boundary. If a 0-length allocation is + * requested, a NULL pointer will be returned. + * + * \param [in] pool the allocation pool to allocate the memory from + * \param [in] amount the size of the allocation in bytes. + * \return a pointer to the memory block, or NULL if the allocation cannot + * be satisfied. + * + * \sa init_amqp_pool(), recycle_amqp_pool(), empty_amqp_pool(), + * amqp_pool_alloc_bytes() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +void *AMQP_CALL amqp_pool_alloc(amqp_pool_t *pool, size_t amount); + +/** + * Allocates a block of memory from an amqp_pool_t to an amqp_bytes_t + * + * Memory will be aligned on a 8-byte boundary. If a 0-length allocation is + * requested, output.bytes = NULL. + * + * \param [in] pool the allocation pool to allocate the memory from + * \param [in] amount the size of the allocation in bytes + * \param [in] output the location to store the pointer. On success + * output.bytes will be set to the beginning of the buffer + * output.len will be set to amount + * On error output.bytes will be set to NULL and output.len + * set to 0 + * + * \sa init_amqp_pool(), recycle_amqp_pool(), empty_amqp_pool(), + * amqp_pool_alloc() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +void AMQP_CALL amqp_pool_alloc_bytes(amqp_pool_t *pool, size_t amount, + amqp_bytes_t *output); + +/** + * Wraps a c string in an amqp_bytes_t + * + * Takes a string, calculates its length and creates an + * amqp_bytes_t that points to it. The string is not duplicated. + * + * For a given input cstr, The amqp_bytes_t output.bytes is the + * same as cstr, output.len is the length of the string not including + * the \0 terminator + * + * This function uses strlen() internally so cstr must be properly + * terminated + * + * \param [in] cstr the c string to wrap + * \return an amqp_bytes_t that describes the string + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +amqp_bytes_t AMQP_CALL amqp_cstring_bytes(char const *cstr); + +/** + * Duplicates an amqp_bytes_t buffer. + * + * The buffer is cloned and the contents copied. + * + * The memory associated with the output is allocated + * with amqp_bytes_malloc() and should be freed with + * amqp_bytes_free() + * + * \param [in] src + * \return a clone of the src + * + * \sa amqp_bytes_free(), amqp_bytes_malloc() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +amqp_bytes_t AMQP_CALL amqp_bytes_malloc_dup(amqp_bytes_t src); + +/** + * Allocates a amqp_bytes_t buffer + * + * Creates an amqp_bytes_t buffer of the specified amount, the buffer should be + * freed using amqp_bytes_free() + * + * \param [in] amount the size of the buffer in bytes + * \returns an amqp_bytes_t with amount bytes allocated. + * output.bytes will be set to NULL on error + * + * \sa amqp_bytes_free(), amqp_bytes_malloc_dup() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +amqp_bytes_t AMQP_CALL amqp_bytes_malloc(size_t amount); + +/** + * Frees an amqp_bytes_t buffer + * + * Frees a buffer allocated with amqp_bytes_malloc() or amqp_bytes_malloc_dup() + * + * Calling amqp_bytes_free on buffers not allocated with one + * of those two functions will result in undefined behavior + * + * \param [in] bytes the buffer to free + * + * \sa amqp_bytes_malloc(), amqp_bytes_malloc_dup() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +void AMQP_CALL amqp_bytes_free(amqp_bytes_t bytes); + +/** + * Allocate and initialize a new amqp_connection_state_t object + * + * amqp_connection_state_t objects created with this function + * should be freed with amqp_destroy_connection() + * + * \returns an opaque pointer on success, NULL or 0 on failure. + * + * \sa amqp_destroy_connection() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +amqp_connection_state_t AMQP_CALL amqp_new_connection(void); + +/** + * Get the underlying socket descriptor for the connection + * + * \warning Use the socket returned from this function carefully, incorrect use + * of the socket outside of the library will lead to undefined behavior. + * Additionally rabbitmq-c may use the socket differently version-to-version, + * what may work in one version, may break in the next version. Be sure to + * throughly test any applications that use the socket returned by this + * function especially when using a newer version of rabbitmq-c + * + * \param [in] state the connection object + * \returns the socket descriptor if one has been set, -1 otherwise + * + * \sa amqp_tcp_socket_new(), amqp_ssl_socket_new(), amqp_socket_open() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_get_sockfd(amqp_connection_state_t state); + +/** + * Deprecated, use amqp_tcp_socket_new() or amqp_ssl_socket_new() + * + * \deprecated Use amqp_tcp_socket_new() or amqp_ssl_socket_new() + * + * Sets the socket descriptor associated with the connection. The socket + * should be connected to a broker, and should not be read to or written from + * before calling this function. A socket descriptor can be created and opened + * using amqp_open_socket() + * + * \param [in] state the connection object + * \param [in] sockfd the socket + * + * \sa amqp_open_socket(), amqp_tcp_socket_new(), amqp_ssl_socket_new() + * + * \since v0.1 + */ +AMQP_DEPRECATED(AMQP_PUBLIC_FUNCTION void AMQP_CALL + amqp_set_sockfd(amqp_connection_state_t state, int sockfd)); + +/** + * Tune client side parameters + * + * \warning This function may call abort() if the connection is in a certain + * state. As such it should probably not be called code outside the library. + * connection parameters should be specified when calling amqp_login() or + * amqp_login_with_properties() + * + * This function changes channel_max, frame_max, and heartbeat parameters, on + * the client side only. It does not try to renegotiate these parameters with + * the broker. Using this function will lead to unexpected results. + * + * \param [in] state the connection object + * \param [in] channel_max the maximum number of channels. + * The largest this can be is 65535 + * \param [in] frame_max the maximum size of an frame. + * The smallest this can be is 4096 + * The largest this can be is 2147483647 + * Unless you know what you're doing the recommended + * size is 131072 or 128KB + * \param [in] heartbeat the number of seconds between heartbeats + * + * \return AMQP_STATUS_OK on success, an amqp_status_enum value otherwise. + * Possible error codes include: + * - AMQP_STATUS_NO_MEMORY memory allocation failed. + * - AMQP_STATUS_TIMER_FAILURE the underlying system timer indicated it + * failed. + * + * \sa amqp_login(), amqp_login_with_properties() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_tune_connection(amqp_connection_state_t state, + int channel_max, int frame_max, + int heartbeat); + +/** + * Get the maximum number of channels the connection can handle + * + * The maximum number of channels is set when connection negotiation takes + * place in amqp_login() or amqp_login_with_properties(). + * + * \param [in] state the connection object + * \return the maximum number of channels. 0 if there is no limit + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_get_channel_max(amqp_connection_state_t state); + +/** + * Get the maximum size of an frame the connection can handle + * + * The maximum size of an frame is set when connection negotiation takes + * place in amqp_login() or amqp_login_with_properties(). + * + * \param [in] state the connection object + * \return the maximum size of an frame. + * + * \since v0.6 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_get_frame_max(amqp_connection_state_t state); + +/** + * Get the number of seconds between heartbeats of the connection + * + * The number of seconds between heartbeats is set when connection + * negotiation takes place in amqp_login() or amqp_login_with_properties(). + * + * \param [in] state the connection object + * \return the number of seconds between heartbeats. + * + * \since v0.6 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_get_heartbeat(amqp_connection_state_t state); + +/** + * Destroys an amqp_connection_state_t object + * + * Destroys a amqp_connection_state_t object that was created with + * amqp_new_connection(). If the connection with the broker is open, it will be + * implicitly closed with a reply code of 200 (success). Any memory that + * would be freed with amqp_maybe_release_buffers() or + * amqp_maybe_release_buffers_on_channel() will be freed, and use of that + * memory will caused undefined behavior. + * + * \param [in] state the connection object + * \return AMQP_STATUS_OK on success. amqp_status_enum value failure + * + * \sa amqp_new_connection() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_destroy_connection(amqp_connection_state_t state); + +/** + * Process incoming data + * + * \warning This is a low-level function intended for those who want to + * have greater control over input and output over the socket from the + * broker. Correctly using this function requires in-depth knowledge of AMQP + * and rabbitmq-c. + * + * For a given buffer of data received from the broker, decode the first + * frame in the buffer. If more than one frame is contained in the input buffer + * the return value will be less than the received_data size, the caller should + * adjust received_data buffer descriptor to point to the beginning of the + * buffer + the return value. + * + * \param [in] state the connection object + * \param [in] received_data a buffer of data received from the broker. The + * function will return the number of bytes of the buffer it used. The + * function copies these bytes to an internal buffer: this part of the buffer + * may be reused after this function successfully completes. + * \param [in,out] decoded_frame caller should pass in a pointer to an + * amqp_frame_t struct. If there is enough data in received_data for a + * complete frame, decoded_frame->frame_type will be set to something OTHER + * than 0. decoded_frame may contain members pointing to memory owned by + * the state object. This memory can be recycled with + * amqp_maybe_release_buffers() or amqp_maybe_release_buffers_on_channel(). + * \return number of bytes consumed from received_data or 0 if a 0-length + * buffer was passed. A negative return value indicates failure. Possible + * errors: + * - AMQP_STATUS_NO_MEMORY failure in allocating memory. The library is likely + * in an indeterminate state making recovery unlikely. Client should note the + * error and terminate the application + * - AMQP_STATUS_BAD_AMQP_DATA bad AMQP data was received. The connection + * should be shutdown immediately + * - AMQP_STATUS_UNKNOWN_METHOD: an unknown method was received from the + * broker. This is likely a protocol error and the connection should be + * shutdown immediately + * - AMQP_STATUS_UNKNOWN_CLASS: a properties frame with an unknown class + * was received from the broker. This is likely a protocol error and the + * connection should be shutdown immediately + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_handle_input(amqp_connection_state_t state, + amqp_bytes_t received_data, + amqp_frame_t *decoded_frame); + +/** + * Check to see if connection memory can be released + * + * \deprecated This function is deprecated in favor of + * amqp_maybe_release_buffers() or amqp_maybe_release_buffers_on_channel() + * + * Checks the state of an amqp_connection_state_t object to see if + * amqp_release_buffers() can be called successfully. + * + * \param [in] state the connection object + * \returns TRUE if the buffers can be released FALSE otherwise + * + * \sa amqp_release_buffers() amqp_maybe_release_buffers() + * amqp_maybe_release_buffers_on_channel() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +amqp_boolean_t AMQP_CALL amqp_release_buffers_ok(amqp_connection_state_t state); + +/** + * Release amqp_connection_state_t owned memory + * + * \deprecated This function is deprecated in favor of + * amqp_maybe_release_buffers() or amqp_maybe_release_buffers_on_channel() + * + * \warning caller should ensure amqp_release_buffers_ok() returns true before + * calling this function. Failure to do so may result in abort() being called. + * + * Release memory owned by the amqp_connection_state_t for reuse by the + * library. Use of any memory returned by the library before this function is + * called will result in undefined behavior. + * + * \note internally rabbitmq-c tries to reuse memory when possible. As a result + * its possible calling this function may not have a noticeable effect on + * memory usage. + * + * \param [in] state the connection object + * + * \sa amqp_release_buffers_ok() amqp_maybe_release_buffers() + * amqp_maybe_release_buffers_on_channel() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +void AMQP_CALL amqp_release_buffers(amqp_connection_state_t state); + +/** + * Release amqp_connection_state_t owned memory + * + * Release memory owned by the amqp_connection_state_t object related to any + * channel, allowing reuse by the library. Use of any memory returned by the + * library before this function is called with result in undefined behavior. + * + * \note internally rabbitmq-c tries to reuse memory when possible. As a result + * its possible calling this function may not have a noticeable effect on + * memory usage. + * + * \param [in] state the connection object + * + * \sa amqp_maybe_release_buffers_on_channel() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +void AMQP_CALL amqp_maybe_release_buffers(amqp_connection_state_t state); + +/** + * Release amqp_connection_state_t owned memory related to a channel + * + * Release memory owned by the amqp_connection_state_t object related to the + * specified channel, allowing reuse by the library. Use of any memory returned + * the library for a specific channel will result in undefined behavior. + * + * \note internally rabbitmq-c tries to reuse memory when possible. As a result + * its possible calling this function may not have a noticeable effect on + * memory usage. + * + * \param [in] state the connection object + * \param [in] channel the channel specifier for which memory should be + * released. Note that the library does not care about the state of the + * channel when calling this function + * + * \sa amqp_maybe_release_buffers() + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +void AMQP_CALL amqp_maybe_release_buffers_on_channel( + amqp_connection_state_t state, amqp_channel_t channel); + +/** + * Send a frame to the broker + * + * \param [in] state the connection object + * \param [in] frame the frame to send to the broker + * \return AMQP_STATUS_OK on success, an amqp_status_enum value on error. + * Possible error codes: + * - AMQP_STATUS_BAD_AMQP_DATA the serialized form of the method or + * properties was too large to fit in a single AMQP frame, or the + * method contains an invalid value. The frame was not sent. + * - AMQP_STATUS_TABLE_TOO_BIG the serialized form of an amqp_table_t is + * too large to fit in a single AMQP frame. Frame was not sent. + * - AMQP_STATUS_UNKNOWN_METHOD an invalid method type was passed in + * - AMQP_STATUS_UNKNOWN_CLASS an invalid properties type was passed in + * - AMQP_STATUS_TIMER_FAILURE system timer indicated failure. The frame + * was sent + * - AMQP_STATUS_SOCKET_ERROR + * - AMQP_STATUS_SSL_ERROR + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_send_frame(amqp_connection_state_t state, + amqp_frame_t const *frame); + +/** + * Compare two table entries + * + * Works just like strcmp(), comparing two the table keys, datatype, then values + * + * \param [in] entry1 the entry on the left + * \param [in] entry2 the entry on the right + * \return 0 if entries are equal, 0 < if left is greater, 0 > if right is + * greater + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_table_entry_cmp(void const *entry1, void const *entry2); + +/** + * Open a socket to a remote host + * + * \deprecated This function is deprecated in favor of amqp_socket_open() + * + * Looks up the hostname, then attempts to open a socket to the host using + * the specified portnumber. It also sets various options on the socket to + * improve performance and correctness. + * + * \param [in] hostname this can be a hostname or IP address. + * Both IPv4 and IPv6 are acceptable + * \param [in] portnumber the port to connect on. RabbitMQ brokers + * listen on port 5672, and 5671 for SSL + * \return a positive value indicates success and is the sockfd. A negative + * value (see amqp_status_enum)is returned on failure. Possible error codes: + * - AMQP_STATUS_TCP_SOCKETLIB_INIT_ERROR Initialization of underlying socket + * library failed. + * - AMQP_STATUS_HOSTNAME_RESOLUTION_FAILED hostname lookup failed. + * - AMQP_STATUS_SOCKET_ERROR a socket error occurred. errno or + * WSAGetLastError() may return more useful information. + * + * \note IPv6 support was added in v0.3 + * + * \sa amqp_socket_open() amqp_set_sockfd() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_open_socket(char const *hostname, int portnumber); + +/** + * Send initial AMQP header to the broker + * + * \warning this is a low level function intended for those who want to + * interact with the broker at a very low level. Use of this function without + * understanding what it does will result in AMQP protocol errors. + * + * This function sends the AMQP protocol header to the broker. + * + * \param [in] state the connection object + * \return AMQP_STATUS_OK on success, a negative value on failure. Possible + * error codes: + * - AMQP_STATUS_CONNECTION_CLOSED the connection to the broker was closed. + * - AMQP_STATUS_SOCKET_ERROR a socket error occurred. It is likely the + * underlying socket has been closed. errno or WSAGetLastError() may provide + * further information. + * - AMQP_STATUS_SSL_ERROR a SSL error occurred. The connection to the broker + * was closed. + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_send_header(amqp_connection_state_t state); + +/** + * Checks to see if there are any incoming frames ready to be read + * + * Checks to see if there are any amqp_frame_t objects buffered by the + * amqp_connection_state_t object. Having one or more frames buffered means + * that amqp_simple_wait_frame() or amqp_simple_wait_frame_noblock() will + * return a frame without potentially blocking on a read() call. + * + * \param [in] state the connection object + * \return TRUE if there are frames enqueued, FALSE otherwise + * + * \sa amqp_simple_wait_frame() amqp_simple_wait_frame_noblock() + * amqp_data_in_buffer() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +amqp_boolean_t AMQP_CALL amqp_frames_enqueued(amqp_connection_state_t state); + +/** + * Read a single amqp_frame_t + * + * Waits for the next amqp_frame_t frame to be read from the broker. + * This function has the potential to block for a long time in the case of + * waiting for a basic.deliver method frame from the broker. + * + * The library may buffer frames. When an amqp_connection_state_t object + * has frames buffered calling amqp_simple_wait_frame() will return an + * amqp_frame_t without entering a blocking read(). You can test to see if + * an amqp_connection_state_t object has frames buffered by calling the + * amqp_frames_enqueued() function. + * + * The library has a socket read buffer. When there is data in an + * amqp_connection_state_t read buffer, amqp_simple_wait_frame() may return an + * amqp_frame_t without entering a blocking read(). You can test to see if an + * amqp_connection_state_t object has data in its read buffer by calling the + * amqp_data_in_buffer() function. + * + * \param [in] state the connection object + * \param [out] decoded_frame the frame + * \return AMQP_STATUS_OK on success, an amqp_status_enum value + * is returned otherwise. Possible errors include: + * - AMQP_STATUS_NO_MEMORY failure in allocating memory. The library is likely + * in an indeterminate state making recovery unlikely. Client should note the + * error and terminate the application + * - AMQP_STATUS_BAD_AMQP_DATA bad AMQP data was received. The connection + * should be shutdown immediately + * - AMQP_STATUS_UNKNOWN_METHOD: an unknown method was received from the + * broker. This is likely a protocol error and the connection should be + * shutdown immediately + * - AMQP_STATUS_UNKNOWN_CLASS: a properties frame with an unknown class + * was received from the broker. This is likely a protocol error and the + * connection should be shutdown immediately + * - AMQP_STATUS_HEARTBEAT_TIMEOUT timed out while waiting for heartbeat + * from the broker. The connection has been closed. + * - AMQP_STATUS_TIMER_FAILURE system timer indicated failure. + * - AMQP_STATUS_SOCKET_ERROR a socket error occurred. The connection has + * been closed + * - AMQP_STATUS_SSL_ERROR a SSL socket error occurred. The connection has + * been closed. + * + * \sa amqp_simple_wait_frame_noblock() amqp_frames_enqueued() + * amqp_data_in_buffer() + * + * \note as of v0.4.0 this function will no longer return heartbeat frames + * when enabled by specifying a non-zero heartbeat value in amqp_login(). + * Heartbeating is handled internally by the library. + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_simple_wait_frame(amqp_connection_state_t state, + amqp_frame_t *decoded_frame); + +/** + * Read a single amqp_frame_t with a timeout. + * + * Waits for the next amqp_frame_t frame to be read from the broker, up to + * a timespan specified by tv. The function will return AMQP_STATUS_TIMEOUT + * if the timeout is reached. The tv value is not modified by the function. + * + * If a 0 timeval is specified, the function behaves as if its non-blocking: it + * will test to see if a frame can be read from the broker, and return + * immediately. + * + * If NULL is passed in for tv, the function will behave like + * amqp_simple_wait_frame() and block until a frame is received from the broker + * + * The library may buffer frames. When an amqp_connection_state_t object + * has frames buffered calling amqp_simple_wait_frame_noblock() will return an + * amqp_frame_t without entering a blocking read(). You can test to see if an + * amqp_connection_state_t object has frames buffered by calling the + * amqp_frames_enqueued() function. + * + * The library has a socket read buffer. When there is data in an + * amqp_connection_state_t read buffer, amqp_simple_wait_frame_noblock() may + * return + * an amqp_frame_t without entering a blocking read(). You can test to see if an + * amqp_connection_state_t object has data in its read buffer by calling the + * amqp_data_in_buffer() function. + * + * \note This function does not return heartbeat frames. When enabled, + * heartbeating is handed internally internally by the library. + * + * \param [in,out] state the connection object + * \param [out] decoded_frame the frame + * \param [in] tv the maximum time to wait for a frame to be read. Setting + * tv->tv_sec = 0 and tv->tv_usec = 0 will do a non-blocking read. Specifying + * NULL for tv will make the function block until a frame is read. + * \return AMQP_STATUS_OK on success. An amqp_status_enum value is returned + * otherwise. Possible errors include: + * - AMQP_STATUS_TIMEOUT the timeout was reached while waiting for a frame + * from the broker. + * - AMQP_STATUS_INVALID_PARAMETER the tv parameter contains an invalid value. + * - AMQP_STATUS_NO_MEMORY failure in allocating memory. The library is likely + * in an indeterminate state making recovery unlikely. Client should note the + * error and terminate the application + * - AMQP_STATUS_BAD_AMQP_DATA bad AMQP data was received. The connection + * should be shutdown immediately + * - AMQP_STATUS_UNKNOWN_METHOD: an unknown method was received from the + * broker. This is likely a protocol error and the connection should be + * shutdown immediately + * - AMQP_STATUS_UNKNOWN_CLASS: a properties frame with an unknown class + * was received from the broker. This is likely a protocol error and the + * connection should be shutdown immediately + * - AMQP_STATUS_HEARTBEAT_TIMEOUT timed out while waiting for heartbeat + * from the broker. The connection has been closed. + * - AMQP_STATUS_TIMER_FAILURE system timer indicated failure. + * - AMQP_STATUS_SOCKET_ERROR a socket error occurred. The connection has + * been closed + * - AMQP_STATUS_SSL_ERROR a SSL socket error occurred. The connection has + * been closed. + * + * \sa amqp_simple_wait_frame() amqp_frames_enqueued() amqp_data_in_buffer() + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_simple_wait_frame_noblock(amqp_connection_state_t state, + amqp_frame_t *decoded_frame, + struct timeval *tv); + +/** + * Waits for a specific method from the broker + * + * \warning You probably don't want to use this function. If this function + * doesn't receive exactly the frame requested it closes the whole connection. + * + * Waits for a single method on a channel from the broker. + * If a frame is received that does not match expected_channel + * or expected_method the program will abort + * + * \param [in] state the connection object + * \param [in] expected_channel the channel that the method should be delivered + * on + * \param [in] expected_method the method to wait for + * \param [out] output the method + * \returns AMQP_STATUS_OK on success. An amqp_status_enum value is returned + * otherwise. Possible errors include: + * - AMQP_STATUS_WRONG_METHOD a frame containing the wrong method, wrong frame + * type or wrong channel was received. The connection is closed. + * - AMQP_STATUS_NO_MEMORY failure in allocating memory. The library is likely + * in an indeterminate state making recovery unlikely. Client should note the + * error and terminate the application + * - AMQP_STATUS_BAD_AMQP_DATA bad AMQP data was received. The connection + * should be shutdown immediately + * - AMQP_STATUS_UNKNOWN_METHOD: an unknown method was received from the + * broker. This is likely a protocol error and the connection should be + * shutdown immediately + * - AMQP_STATUS_UNKNOWN_CLASS: a properties frame with an unknown class + * was received from the broker. This is likely a protocol error and the + * connection should be shutdown immediately + * - AMQP_STATUS_HEARTBEAT_TIMEOUT timed out while waiting for heartbeat + * from the broker. The connection has been closed. + * - AMQP_STATUS_TIMER_FAILURE system timer indicated failure. + * - AMQP_STATUS_SOCKET_ERROR a socket error occurred. The connection has + * been closed + * - AMQP_STATUS_SSL_ERROR a SSL socket error occurred. The connection has + * been closed. + * + * \since v0.1 + */ + +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_simple_wait_method(amqp_connection_state_t state, + amqp_channel_t expected_channel, + amqp_method_number_t expected_method, + amqp_method_t *output); + +/** + * Sends a method to the broker + * + * This is a thin wrapper around amqp_send_frame(), providing a way to send + * a method to the broker on a specified channel. + * + * \param [in] state the connection object + * \param [in] channel the channel object + * \param [in] id the method number + * \param [in] decoded the method object + * \returns AMQP_STATUS_OK on success, an amqp_status_enum value otherwise. + * Possible errors include: + * - AMQP_STATUS_BAD_AMQP_DATA the serialized form of the method or + * properties was too large to fit in a single AMQP frame, or the + * method contains an invalid value. The frame was not sent. + * - AMQP_STATUS_TABLE_TOO_BIG the serialized form of an amqp_table_t is + * too large to fit in a single AMQP frame. Frame was not sent. + * - AMQP_STATUS_UNKNOWN_METHOD an invalid method type was passed in + * - AMQP_STATUS_UNKNOWN_CLASS an invalid properties type was passed in + * - AMQP_STATUS_TIMER_FAILURE system timer indicated failure. The frame + * was sent + * - AMQP_STATUS_SOCKET_ERROR + * - AMQP_STATUS_SSL_ERROR + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_send_method(amqp_connection_state_t state, + amqp_channel_t channel, amqp_method_number_t id, + void *decoded); + +/** + * Sends a method to the broker and waits for a method response + * + * \param [in] state the connection object + * \param [in] channel the channel object + * \param [in] request_id the method number of the request + * \param [in] expected_reply_ids a 0 terminated array of expected response + * method numbers + * \param [in] decoded_request_method the method to be sent to the broker + * \return a amqp_rpc_reply_t: + * - r.reply_type == AMQP_RESPONSE_NORMAL. RPC completed successfully + * - r.reply_type == AMQP_RESPONSE_SERVER_EXCEPTION. The broker returned an + * exception: + * - If r.reply.id == AMQP_CHANNEL_CLOSE_METHOD a channel exception + * occurred, cast r.reply.decoded to amqp_channel_close_t* to see details + * of the exception. The client should amqp_send_method() a + * amqp_channel_close_ok_t. The channel must be re-opened before it + * can be used again. Any resources associated with the channel + * (auto-delete exchanges, auto-delete queues, consumers) are invalid + * and must be recreated before attempting to use them again. + * - If r.reply.id == AMQP_CONNECTION_CLOSE_METHOD a connection exception + * occurred, cast r.reply.decoded to amqp_connection_close_t* to see + * details of the exception. The client amqp_send_method() a + * amqp_connection_close_ok_t and disconnect from the broker. + * - r.reply_type == AMQP_RESPONSE_LIBRARY_EXCEPTION. An exception occurred + * within the library. Examine r.library_error and compare it against + * amqp_status_enum values to determine the error. + * + * \sa amqp_simple_rpc_decoded() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +amqp_rpc_reply_t AMQP_CALL amqp_simple_rpc( + amqp_connection_state_t state, amqp_channel_t channel, + amqp_method_number_t request_id, amqp_method_number_t *expected_reply_ids, + void *decoded_request_method); + +/** + * Sends a method to the broker and waits for a method response + * + * \param [in] state the connection object + * \param [in] channel the channel object + * \param [in] request_id the method number of the request + * \param [in] reply_id the method number expected in response + * \param [in] decoded_request_method the request method + * \return a pointer to the method returned from the broker, or NULL on error. + * On error amqp_get_rpc_reply() will return an amqp_rpc_reply_t with + * details on the error that occurred. + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +void *AMQP_CALL amqp_simple_rpc_decoded(amqp_connection_state_t state, + amqp_channel_t channel, + amqp_method_number_t request_id, + amqp_method_number_t reply_id, + void *decoded_request_method); + +/** + * Get the last global amqp_rpc_reply + * + * The API methods corresponding to most synchronous AMQP methods + * return a pointer to the decoded method result. Upon error, they + * return NULL, and we need some way of discovering what, if anything, + * went wrong. amqp_get_rpc_reply() returns the most recent + * amqp_rpc_reply_t instance corresponding to such an API operation + * for the given connection. + * + * Only use it for operations that do not themselves return + * amqp_rpc_reply_t; operations that do return amqp_rpc_reply_t + * generally do NOT update this per-connection-global amqp_rpc_reply_t + * instance. + * + * \param [in] state the connection object + * \return the most recent amqp_rpc_reply_t: + * - r.reply_type == AMQP_RESPONSE_NORMAL. RPC completed successfully + * - r.reply_type == AMQP_RESPONSE_SERVER_EXCEPTION. The broker returned an + * exception: + * - If r.reply.id == AMQP_CHANNEL_CLOSE_METHOD a channel exception + * occurred, cast r.reply.decoded to amqp_channel_close_t* to see details + * of the exception. The client should amqp_send_method() a + * amqp_channel_close_ok_t. The channel must be re-opened before it + * can be used again. Any resources associated with the channel + * (auto-delete exchanges, auto-delete queues, consumers) are invalid + * and must be recreated before attempting to use them again. + * - If r.reply.id == AMQP_CONNECTION_CLOSE_METHOD a connection exception + * occurred, cast r.reply.decoded to amqp_connection_close_t* to see + * details of the exception. The client amqp_send_method() a + * amqp_connection_close_ok_t and disconnect from the broker. + * - r.reply_type == AMQP_RESPONSE_LIBRARY_EXCEPTION. An exception occurred + * within the library. Examine r.library_error and compare it against + * amqp_status_enum values to determine the error. + * + * \sa amqp_simple_rpc_decoded() + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +amqp_rpc_reply_t AMQP_CALL amqp_get_rpc_reply(amqp_connection_state_t state); + +/** + * Login to the broker + * + * After using amqp_open_socket and amqp_set_sockfd, call + * amqp_login to complete connecting to the broker + * + * \param [in] state the connection object + * \param [in] vhost the virtual host to connect to on the broker. The default + * on most brokers is "/" + * \param [in] channel_max the limit for number of channels for the connection. + * 0 means no limit, and is a good default + * (AMQP_DEFAULT_MAX_CHANNELS) + * Note that the maximum number of channels the protocol supports + * is 65535 (2^16, with the 0-channel reserved). The server can + * set a lower channel_max and then the client will use the lowest + * of the two + * \param [in] frame_max the maximum size of an AMQP frame on the wire to + * request of the broker for this connection. 4096 is the minimum + * size, 2^31-1 is the maximum, a good default is 131072 (128KB), + * or AMQP_DEFAULT_FRAME_SIZE + * \param [in] heartbeat the number of seconds between heartbeat frames to + * request of the broker. A value of 0 disables heartbeats. + * Note rabbitmq-c only has partial support for heartbeats, as of + * v0.4.0 they are only serviced during amqp_basic_publish() and + * amqp_simple_wait_frame()/amqp_simple_wait_frame_noblock() + * \param [in] sasl_method the SASL method to authenticate with the broker. + * followed by the authentication information. The following SASL + * methods are implemented: + * - AMQP_SASL_METHOD_PLAIN, the AMQP_SASL_METHOD_PLAIN argument + * should be followed by two arguments in this order: + * const char* username, and const char* password. + * - AMQP_SASL_METHOD_EXTERNAL, the AMQP_SASL_METHOD_EXTERNAL + * argument should be followed one argument: + * const char* identity. + * \return amqp_rpc_reply_t indicating success or failure. + * - r.reply_type == AMQP_RESPONSE_NORMAL. Login completed successfully + * - r.reply_type == AMQP_RESPONSE_LIBRARY_EXCEPTION. In most cases errors + * from the broker when logging in will be represented by the broker closing + * the socket. In this case r.library_error will be set to + * AMQP_STATUS_CONNECTION_CLOSED. This error can represent a number of + * error conditions including: invalid vhost, authentication failure. + * - r.reply_type == AMQP_RESPONSE_SERVER_EXCEPTION. The broker returned an + * exception: + * - If r.reply.id == AMQP_CHANNEL_CLOSE_METHOD a channel exception + * occurred, cast r.reply.decoded to amqp_channel_close_t* to see details + * of the exception. The client should amqp_send_method() a + * amqp_channel_close_ok_t. The channel must be re-opened before it + * can be used again. Any resources associated with the channel + * (auto-delete exchanges, auto-delete queues, consumers) are invalid + * and must be recreated before attempting to use them again. + * - If r.reply.id == AMQP_CONNECTION_CLOSE_METHOD a connection exception + * occurred, cast r.reply.decoded to amqp_connection_close_t* to see + * details of the exception. The client amqp_send_method() a + * amqp_connection_close_ok_t and disconnect from the broker. + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +amqp_rpc_reply_t AMQP_CALL amqp_login(amqp_connection_state_t state, + char const *vhost, int channel_max, + int frame_max, int heartbeat, + amqp_sasl_method_enum sasl_method, ...); + +/** + * Login to the broker passing a properties table + * + * This function is similar to amqp_login() and differs in that it provides a + * way to pass client properties to the broker. This is commonly used to + * negotiate newer protocol features as they are supported by the broker. + * + * \param [in] state the connection object + * \param [in] vhost the virtual host to connect to on the broker. The default + * on most brokers is "/" + * \param [in] channel_max the limit for the number of channels for the + * connection. + * 0 means no limit, and is a good default + * (AMQP_DEFAULT_MAX_CHANNELS) + * Note that the maximum number of channels the protocol supports + * is 65535 (2^16, with the 0-channel reserved). The server can + * set a lower channel_max and then the client will use the lowest + * of the two + * \param [in] frame_max the maximum size of an AMQP frame ont he wire to + * request of the broker for this connection. 4096 is the minimum + * size, 2^31-1 is the maximum, a good default is 131072 (128KB), + * or AMQP_DEFAULT_FRAME_SIZE + * \param [in] heartbeat the number of seconds between heartbeat frame to + * request of the broker. A value of 0 disables heartbeats. + * Note rabbitmq-c only has partial support for hearts, as of + * v0.4.0 heartbeats are only serviced during amqp_basic_publish(), + * and amqp_simple_wait_frame()/amqp_simple_wait_frame_noblock() + * \param [in] properties a table of properties to send the broker. + * \param [in] sasl_method the SASL method to authenticate with the broker + * followed by the authentication information. The following SASL + * methods are implemented: + * - AMQP_SASL_METHOD_PLAIN, the AMQP_SASL_METHOD_PLAIN argument + * should be followed by two arguments in this order: + * const char* username, and const char* password. + * - AMQP_SASL_METHOD_EXTERNAL, the AMQP_SASL_METHOD_EXTERNAL + * argument should be followed one argument: + * const char* identity. + * \return amqp_rpc_reply_t indicating success or failure. + * - r.reply_type == AMQP_RESPONSE_NORMAL. Login completed successfully + * - r.reply_type == AMQP_RESPONSE_LIBRARY_EXCEPTION. In most cases errors + * from the broker when logging in will be represented by the broker closing + * the socket. In this case r.library_error will be set to + * AMQP_STATUS_CONNECTION_CLOSED. This error can represent a number of + * error conditions including: invalid vhost, authentication failure. + * - r.reply_type == AMQP_RESPONSE_SERVER_EXCEPTION. The broker returned an + * exception: + * - If r.reply.id == AMQP_CHANNEL_CLOSE_METHOD a channel exception + * occurred, cast r.reply.decoded to amqp_channel_close_t* to see details + * of the exception. The client should amqp_send_method() a + * amqp_channel_close_ok_t. The channel must be re-opened before it + * can be used again. Any resources associated with the channel + * (auto-delete exchanges, auto-delete queues, consumers) are invalid + * and must be recreated before attempting to use them again. + * - If r.reply.id == AMQP_CONNECTION_CLOSE_METHOD a connection exception + * occurred, cast r.reply.decoded to amqp_connection_close_t* to see + * details of the exception. The client amqp_send_method() a + * amqp_connection_close_ok_t and disconnect from the broker. + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +amqp_rpc_reply_t AMQP_CALL amqp_login_with_properties( + amqp_connection_state_t state, char const *vhost, int channel_max, + int frame_max, int heartbeat, const amqp_table_t *properties, + amqp_sasl_method_enum sasl_method, ...); + +struct amqp_basic_properties_t_; + +/** + * Publish a message to the broker + * + * Publish a message on an exchange with a routing key. + * + * Note that at the AMQ protocol level basic.publish is an async method: + * this means error conditions that occur on the broker (such as publishing to + * a non-existent exchange) will not be reflected in the return value of this + * function. + * + * \param [in] state the connection object + * \param [in] channel the channel identifier + * \param [in] exchange the exchange on the broker to publish to + * \param [in] routing_key the routing key to use when publishing the message + * \param [in] mandatory indicate to the broker that the message MUST be routed + * to a queue. If the broker cannot do this it should respond with + * a basic.return method. + * \param [in] immediate indicate to the broker that the message MUST be + * delivered to a consumer immediately. If the broker cannot do this + * it should respond with a basic.return method. + * \param [in] properties the properties associated with the message + * \param [in] body the message body + * \return AMQP_STATUS_OK on success, amqp_status_enum value on failure. Note + * that basic.publish is an async method, the return value from this + * function only indicates that the message data was successfully + * transmitted to the broker. It does not indicate failures that occur + * on the broker, such as publishing to a non-existent exchange. + * Possible error values: + * - AMQP_STATUS_TIMER_FAILURE: system timer facility returned an error + * the message was not sent. + * - AMQP_STATUS_HEARTBEAT_TIMEOUT: connection timed out waiting for a + * heartbeat from the broker. The message was not sent. + * - AMQP_STATUS_NO_MEMORY: memory allocation failed. The message was + * not sent. + * - AMQP_STATUS_TABLE_TOO_BIG: a table in the properties was too large + * to fit in a single frame. Message was not sent. + * - AMQP_STATUS_CONNECTION_CLOSED: the connection was closed. + * - AMQP_STATUS_SSL_ERROR: a SSL error occurred. + * - AMQP_STATUS_TCP_ERROR: a TCP error occurred. errno or + * WSAGetLastError() may provide more information + * + * Note: this function does heartbeat processing as of v0.4.0 + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_basic_publish( + amqp_connection_state_t state, amqp_channel_t channel, + amqp_bytes_t exchange, amqp_bytes_t routing_key, amqp_boolean_t mandatory, + amqp_boolean_t immediate, struct amqp_basic_properties_t_ const *properties, + amqp_bytes_t body); + +/** + * Closes an channel + * + * \param [in] state the connection object + * \param [in] channel the channel identifier + * \param [in] code the reason for closing the channel, AMQP_REPLY_SUCCESS is a + * good default + * \return amqp_rpc_reply_t indicating success or failure + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +amqp_rpc_reply_t AMQP_CALL amqp_channel_close(amqp_connection_state_t state, + amqp_channel_t channel, int code); + +/** + * Closes the entire connection + * + * Implicitly closes all channels and informs the broker the connection + * is being closed, after receiving acknowledgment from the broker it closes + * the socket. + * + * \param [in] state the connection object + * \param [in] code the reason code for closing the connection. + * AMQP_REPLY_SUCCESS is a good default. + * \return amqp_rpc_reply_t indicating the result + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +amqp_rpc_reply_t AMQP_CALL amqp_connection_close(amqp_connection_state_t state, + int code); + +/** + * Acknowledges a message + * + * Does a basic.ack on a received message + * + * \param [in] state the connection object + * \param [in] channel the channel identifier + * \param [in] delivery_tag the delivery tag of the message to be ack'd + * \param [in] multiple if true, ack all messages up to this delivery tag, if + * false ack only this delivery tag + * \return 0 on success, 0 > on failing to send the ack to the broker. + * this will not indicate failure if something goes wrong on the + * broker + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_basic_ack(amqp_connection_state_t state, + amqp_channel_t channel, uint64_t delivery_tag, + amqp_boolean_t multiple); + +/** + * Do a basic.get + * + * Synchonously polls the broker for a message in a queue, and + * retrieves the message if a message is in the queue. + * + * \param [in] state the connection object + * \param [in] channel the channel identifier to use + * \param [in] queue the queue name to retrieve from + * \param [in] no_ack if true the message is automatically ack'ed + * if false amqp_basic_ack should be called once the message + * retrieved has been processed + * \return amqp_rpc_reply indicating success or failure + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +amqp_rpc_reply_t AMQP_CALL amqp_basic_get(amqp_connection_state_t state, + amqp_channel_t channel, + amqp_bytes_t queue, + amqp_boolean_t no_ack); + +/** + * Do a basic.reject + * + * Actively reject a message that has been delivered + * + * \param [in] state the connection object + * \param [in] channel the channel identifier + * \param [in] delivery_tag the delivery tag of the message to reject + * \param [in] requeue indicate to the broker whether it should requeue the + * message or just discard it. + * \return 0 on success, 0 > on failing to send the reject method to the broker. + * This will not indicate failure if something goes wrong on the + * broker. + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_basic_reject(amqp_connection_state_t state, + amqp_channel_t channel, uint64_t delivery_tag, + amqp_boolean_t requeue); + +/** + * Do a basic.nack + * + * Actively reject a message, this has the same effect as amqp_basic_reject() + * however, amqp_basic_nack() can negatively acknowledge multiple messages with + * one call much like amqp_basic_ack() can acknowledge mutliple messages with + * one call. + * + * \param [in] state the connection object + * \param [in] channel the channel identifier + * \param [in] delivery_tag the delivery tag of the message to reject + * \param [in] multiple if set to 1 negatively acknowledge all unacknowledged + * messages on this channel. + * \param [in] requeue indicate to the broker whether it should requeue the + * message or dead-letter it. + * \return AMQP_STATUS_OK on success, an amqp_status_enum value otherwise. + * + * \since v0.5.0 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_basic_nack(amqp_connection_state_t state, + amqp_channel_t channel, uint64_t delivery_tag, + amqp_boolean_t multiple, amqp_boolean_t requeue); +/** + * Check to see if there is data left in the receive buffer + * + * Can be used to see if there is data still in the buffer, if so + * calling amqp_simple_wait_frame will not immediately enter a + * blocking read. + * + * \param [in] state the connection object + * \return true if there is data in the recieve buffer, false otherwise + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +amqp_boolean_t AMQP_CALL amqp_data_in_buffer(amqp_connection_state_t state); + +/** + * Get the error string for the given error code. + * + * \deprecated This function has been deprecated in favor of + * \ref amqp_error_string2() which returns statically allocated + * string which do not need to be freed by the caller. + * + * The returned string resides on the heap; the caller is responsible + * for freeing it. + * + * \param [in] err return error code + * \return the error string + * + * \since v0.1 + */ +AMQP_DEPRECATED( + AMQP_PUBLIC_FUNCTION char *AMQP_CALL amqp_error_string(int err)); + +/** + * Get the error string for the given error code. + * + * Get an error string associated with an error code. The string is statically + * allocated and does not need to be freed + * + * \param [in] err the error code + * \return the error string + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +const char *AMQP_CALL amqp_error_string2(int err); + +/** + * Deserialize an amqp_table_t from AMQP wireformat + * + * This is an internal function and is not typically used by + * client applications + * + * \param [in] encoded the buffer containing the serialized data + * \param [in] pool memory pool used to allocate the table entries from + * \param [in] output the amqp_table_t structure to fill in. Any existing + * entries will be erased + * \param [in,out] offset The offset into the encoded buffer to start + * reading the serialized table. It will be updated + * by this function to end of the table + * \return AMQP_STATUS_OK on success, an amqp_status_enum value on failure + * Possible error codes: + * - AMQP_STATUS_NO_MEMORY out of memory + * - AMQP_STATUS_BAD_AMQP_DATA invalid wireformat + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_decode_table(amqp_bytes_t encoded, amqp_pool_t *pool, + amqp_table_t *output, size_t *offset); + +/** + * Serializes an amqp_table_t to the AMQP wireformat + * + * This is an internal function and is not typically used by + * client applications + * + * \param [in] encoded the buffer where to serialize the table to + * \param [in] input the amqp_table_t to serialize + * \param [in,out] offset The offset into the encoded buffer to start + * writing the serialized table. It will be updated + * by this function to where writing left off + * \return AMQP_STATUS_OK on success, an amqp_status_enum value on failure + * Possible error codes: + * - AMQP_STATUS_TABLE_TOO_BIG the serialized form is too large for the + * buffer + * - AMQP_STATUS_BAD_AMQP_DATA invalid table + * + * \since v0.1 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_encode_table(amqp_bytes_t encoded, amqp_table_t *input, + size_t *offset); + +/** + * Create a deep-copy of an amqp_table_t object + * + * Creates a deep-copy of an amqp_table_t object, using the provided pool + * object to allocate the necessary memory. This memory can be freed later by + * call recycle_amqp_pool(), or empty_amqp_pool() + * + * \param [in] original the table to copy + * \param [in,out] clone the table to copy to + * \param [in] pool the initialized memory pool to do allocations for the table + * from + * \return AMQP_STATUS_OK on success, amqp_status_enum value on failure. + * Possible error values: + * - AMQP_STATUS_NO_MEMORY - memory allocation failure. + * - AMQP_STATUS_INVALID_PARAMETER - invalid table (e.g., no key name) + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_table_clone(const amqp_table_t *original, + amqp_table_t *clone, amqp_pool_t *pool); + +/** + * A message object + * + * \since v0.4.0 + */ +typedef struct amqp_message_t_ { + amqp_basic_properties_t properties; /**< message properties */ + amqp_bytes_t body; /**< message body */ + amqp_pool_t pool; /**< pool used to allocate properties */ +} amqp_message_t; + +/** + * Reads the next message on a channel + * + * Reads a complete message (header + body) on a specified channel. This + * function is intended to be used with amqp_basic_get() or when an + * AMQP_BASIC_DELIVERY_METHOD method is received. + * + * \param [in,out] state the connection object + * \param [in] channel the channel on which to read the message from + * \param [in,out] message a pointer to a amqp_message_t object. Caller should + * call amqp_message_destroy() when it is done using the + * fields in the message object. The caller is responsible for + * allocating/destroying the amqp_message_t object itself. + * \param [in] flags pass in 0. Currently unused. + * \returns a amqp_rpc_reply_t object. ret.reply_type == AMQP_RESPONSE_NORMAL on + * success. + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +amqp_rpc_reply_t AMQP_CALL amqp_read_message(amqp_connection_state_t state, + amqp_channel_t channel, + amqp_message_t *message, + int flags); + +/** + * Frees memory associated with a amqp_message_t allocated in amqp_read_message + * + * \param [in] message + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +void AMQP_CALL amqp_destroy_message(amqp_message_t *message); + +/** + * Envelope object + * + * \since v0.4.0 + */ +typedef struct amqp_envelope_t_ { + amqp_channel_t channel; /**< channel message was delivered on */ + amqp_bytes_t + consumer_tag; /**< the consumer tag the message was delivered to */ + uint64_t delivery_tag; /**< the messages delivery tag */ + amqp_boolean_t redelivered; /**< flag indicating whether this message is being + redelivered */ + amqp_bytes_t exchange; /**< exchange this message was published to */ + amqp_bytes_t + routing_key; /**< the routing key this message was published with */ + amqp_message_t message; /**< the message */ +} amqp_envelope_t; + +/** + * Wait for and consume a message + * + * Waits for a basic.deliver method on any channel, upon receipt of + * basic.deliver it reads that message, and returns. If any other method is + * received before basic.deliver, this function will return an amqp_rpc_reply_t + * with ret.reply_type == AMQP_RESPONSE_LIBRARY_EXCEPTION, and + * ret.library_error == AMQP_STATUS_UNEXPECTED_STATE. The caller should then + * call amqp_simple_wait_frame() to read this frame and take appropriate action. + * + * This function should be used after starting a consumer with the + * amqp_basic_consume() function + * + * \param [in,out] state the connection object + * \param [in,out] envelope a pointer to a amqp_envelope_t object. Caller + * should call #amqp_destroy_envelope() when it is done using + * the fields in the envelope object. The caller is responsible + * for allocating/destroying the amqp_envelope_t object itself. + * \param [in] timeout a timeout to wait for a message delivery. Passing in + * NULL will result in blocking behavior. + * \param [in] flags pass in 0. Currently unused. + * \returns a amqp_rpc_reply_t object. ret.reply_type == AMQP_RESPONSE_NORMAL + * on success. If ret.reply_type == AMQP_RESPONSE_LIBRARY_EXCEPTION, + * and ret.library_error == AMQP_STATUS_UNEXPECTED_STATE, a frame other + * than AMQP_BASIC_DELIVER_METHOD was received, the caller should call + * amqp_simple_wait_frame() to read this frame and take appropriate + * action. + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +amqp_rpc_reply_t AMQP_CALL amqp_consume_message(amqp_connection_state_t state, + amqp_envelope_t *envelope, + struct timeval *timeout, + int flags); + +/** + * Frees memory associated with a amqp_envelope_t allocated in + * amqp_consume_message() + * + * \param [in] envelope + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +void AMQP_CALL amqp_destroy_envelope(amqp_envelope_t *envelope); + +/** + * Parameters used to connect to the RabbitMQ broker + * + * \since v0.2 + */ +struct amqp_connection_info { + char *user; /**< the username to authenticate with the broker, default on most + broker is 'guest' */ + char *password; /**< the password to authenticate with the broker, default on + most brokers is 'guest' */ + char *host; /**< the hostname of the broker */ + char *vhost; /**< the virtual host on the broker to connect to, a good default + is "/" */ + int port; /**< the port that the broker is listening on, default on most + brokers is 5672 */ + amqp_boolean_t ssl; +}; + +/** + * Initialze an amqp_connection_info to default values + * + * The default values are: + * - user: "guest" + * - password: "guest" + * - host: "localhost" + * - vhost: "/" + * - port: 5672 + * + * \param [out] parsed the connection info to set defaults on + * + * \since v0.2 + */ +AMQP_PUBLIC_FUNCTION +void AMQP_CALL + amqp_default_connection_info(struct amqp_connection_info *parsed); + +/** + * Parse a connection URL + * + * An amqp connection url takes the form: + * + * amqp://[$USERNAME[:$PASSWORD]\@]$HOST[:$PORT]/[$VHOST] + * + * Examples: + * amqp://guest:guest\@localhost:5672// + * amqp://guest:guest\@localhost/myvhost + * + * Any missing parts of the URL will be set to the defaults specified in + * amqp_default_connection_info. For amqps: URLs the default port will be set + * to 5671 instead of 5672 for non-SSL URLs. + * + * \note This function modifies url parameter. + * + * \param [in] url URI to parse, note that this parameter is modified by the + * function. + * \param [out] parsed the connection info gleaned from the URI. The char* + * members will point to parts of the url input parameter. + * Memory management will depend on how the url is allocated. + * \returns AMQP_STATUS_OK on success, AMQP_STATUS_BAD_URL on failure + * + * \since v0.2 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_parse_url(char *url, struct amqp_connection_info *parsed); + +/* socket API */ + +/** + * Open a socket connection. + * + * This function opens a socket connection returned from amqp_tcp_socket_new() + * or amqp_ssl_socket_new(). This function should be called after setting + * socket options and prior to assigning the socket to an AMQP connection with + * amqp_set_socket(). + * + * \param [in,out] self A socket object. + * \param [in] host Connect to this host. + * \param [in] port Connect on this remote port. + * + * \return AMQP_STATUS_OK on success, an amqp_status_enum on failure + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_socket_open(amqp_socket_t *self, const char *host, int port); + +/** + * Open a socket connection. + * + * This function opens a socket connection returned from amqp_tcp_socket_new() + * or amqp_ssl_socket_new(). This function should be called after setting + * socket options and prior to assigning the socket to an AMQP connection with + * amqp_set_socket(). + * + * \param [in,out] self A socket object. + * \param [in] host Connect to this host. + * \param [in] port Connect on this remote port. + * \param [in] timeout Max allowed time to spent on opening. If NULL - run in + * blocking mode + * + * \return AMQP_STATUS_OK on success, an amqp_status_enum on failure. + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_socket_open_noblock(amqp_socket_t *self, const char *host, + int port, struct timeval *timeout); + +/** + * Get the socket descriptor in use by a socket object. + * + * Retrieve the underlying socket descriptor. This function can be used to + * perform low-level socket operations that aren't supported by the socket + * interface. Use with caution! + * + * \param [in,out] self A socket object. + * + * \return The underlying socket descriptor, or -1 if there is no socket + * descriptor associated with + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_socket_get_sockfd(amqp_socket_t *self); + +/** + * Get the socket object associated with a amqp_connection_state_t + * + * \param [in] state the connection object to get the socket from + * \return a pointer to the socket object, or NULL if one has not been assigned + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +amqp_socket_t *AMQP_CALL amqp_get_socket(amqp_connection_state_t state); + +/** + * Get the broker properties table + * + * \param [in] state the connection object + * \return a pointer to an amqp_table_t containing the properties advertised + * by the broker on connection. The connection object owns the table, it + * should not be modified. + * + * \since v0.5.0 + */ +AMQP_PUBLIC_FUNCTION +amqp_table_t *AMQP_CALL + amqp_get_server_properties(amqp_connection_state_t state); + +/** + * Get the client properties table + * + * Get the properties that were passed to the broker on connection. + * + * \param [in] state the connection object + * \return a pointer to an amqp_table_t containing the properties advertised + * by the client on connection. The connection object owns the table, it + * should not be modified. + * + * \since v0.7.0 + */ +AMQP_PUBLIC_FUNCTION +amqp_table_t *AMQP_CALL + amqp_get_client_properties(amqp_connection_state_t state); + +/** + * Get the login handshake timeout. + * + * amqp_login and amqp_login_with_properties perform the login handshake with + * the broker. This function returns the timeout associated with completing + * this operation from the client side. This value can be set by using the + * amqp_set_handshake_timeout. + * + * Note that the RabbitMQ broker has configurable timeout for completing the + * login handshake, the default is 10 seconds. rabbitmq-c has a default of 12 + * seconds. + * + * \param [in] state the connection object + * \return a struct timeval representing the current login timeout for the state + * object. A NULL value represents an infinite timeout. The memory returned is + * owned by the connection object. + * + * \since v0.9.0 + */ +AMQP_PUBLIC_FUNCTION +struct timeval *AMQP_CALL + amqp_get_handshake_timeout(amqp_connection_state_t state); + +/** + * Set the login handshake timeout. + * + * amqp_login and amqp_login_with_properties perform the login handshake with + * the broker. This function sets the timeout associated with completing this + * operation from the client side. + * + * The timeout must be set before amqp_login or amqp_login_with_properties is + * called to change from the default timeout. + * + * Note that the RabbitMQ broker has a configurable timeout for completing the + * login handshake, the default is 10 seconds. rabbitmq-c has a default of 12 + * seconds. + * + * \param [in] state the connection object + * \param [in] timeout a struct timeval* representing new login timeout for the + * state object. NULL represents an infinite timeout. The value of timeout is + * copied internally, the caller is responsible for ownership of the passed in + * pointer, it does not need to remain valid after this function is called. + * \return AMQP_STATUS_OK on success. + * + * \since v0.9.0 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_set_handshake_timeout(amqp_connection_state_t state, + struct timeval *timeout); + +/** + * Get the RPC timeout + * + * Gets the timeout for any RPC-style AMQP command (e.g., amqp_queue_declare). + * This timeout may be changed at any time by calling \amqp_set_rpc_timeout + * function with a new timeout. The timeout applies individually to each RPC + * that is made. + * + * The default value is NULL, or an infinite timeout. + * + * When an RPC times out, the function will return an error AMQP_STATUS_TIMEOUT, + * and the connection will be closed. + * + *\warning RPC-timeouts are an advanced feature intended to be used to detect + * dead connections quickly when the rabbitmq-c implementation of heartbeats + * does not work. Do not use RPC timeouts unless you understand the implications + * of doing so. + * + * \param [in] state the connection object + * \return a struct timeval representing the current RPC timeout for the state + * object. A NULL value represents an infinite timeout. The memory returned is + * owned by the connection object. + * + * \since v0.9.0 + */ +AMQP_PUBLIC_FUNCTION +struct timeval *AMQP_CALL amqp_get_rpc_timeout(amqp_connection_state_t state); + +/** + * Set the RPC timeout + * + * Sets the timeout for any RPC-style AMQP command (e.g., amqp_queue_declare). + * This timeout may be changed at any time by calling this function with a new + * timeout. The timeout applies individually to each RPC that is made. + * + * The default value is NULL, or an infinite timeout. + * + * When an RPC times out, the function will return an error AMQP_STATUS_TIMEOUT, + * and the connection will be closed. + * + *\warning RPC-timeouts are an advanced feature intended to be used to detect + * dead connections quickly when the rabbitmq-c implementation of heartbeats + * does not work. Do not use RPC timeouts unless you understand the implications + * of doing so. + * + * \param [in] state the connection object + * \param [in] timeout a struct timeval* representing new RPC timeout for the + * state object. NULL represents an infinite timeout. The value of timeout is + * copied internally, the caller is responsible for ownership of the passed + * pointer, it does not need to remain valid after this function is called. + * \return AMQP_STATUS_SUCCESS on success. + * + * \since v0.9.0 + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_set_rpc_timeout(amqp_connection_state_t state, + struct timeval *timeout); + +AMQP_END_DECLS + +#endif /* AMQP_H */ diff --git a/ext/librabbitmq/macos/include/amqp_framing.h b/ext/librabbitmq/macos/include/amqp_framing.h new file mode 100644 index 00000000..fb20acc1 --- /dev/null +++ b/ext/librabbitmq/macos/include/amqp_framing.h @@ -0,0 +1,1144 @@ +/* Generated code. Do not edit. Edit and re-run codegen.py instead. + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MIT + * + * Portions created by Alan Antonuk are Copyright (c) 2012-2013 + * Alan Antonuk. All Rights Reserved. + * + * Portions created by VMware are Copyright (c) 2007-2012 VMware, Inc. + * All Rights Reserved. + * + * Portions created by Tony Garnock-Jones are Copyright (c) 2009-2010 + * VMware, Inc. and Tony Garnock-Jones. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * ***** END LICENSE BLOCK ***** + */ + +/** @file amqp_framing.h */ +#ifndef AMQP_FRAMING_H +#define AMQP_FRAMING_H + +#include + +AMQP_BEGIN_DECLS + +#define AMQP_PROTOCOL_VERSION_MAJOR 0 /**< AMQP protocol version major */ +#define AMQP_PROTOCOL_VERSION_MINOR 9 /**< AMQP protocol version minor */ +#define AMQP_PROTOCOL_VERSION_REVISION \ + 1 /**< AMQP protocol version revision \ + */ +#define AMQP_PROTOCOL_PORT 5672 /**< Default AMQP Port */ +#define AMQP_FRAME_METHOD 1 /**< Constant: FRAME-METHOD */ +#define AMQP_FRAME_HEADER 2 /**< Constant: FRAME-HEADER */ +#define AMQP_FRAME_BODY 3 /**< Constant: FRAME-BODY */ +#define AMQP_FRAME_HEARTBEAT 8 /**< Constant: FRAME-HEARTBEAT */ +#define AMQP_FRAME_MIN_SIZE 4096 /**< Constant: FRAME-MIN-SIZE */ +#define AMQP_FRAME_END 206 /**< Constant: FRAME-END */ +#define AMQP_REPLY_SUCCESS 200 /**< Constant: REPLY-SUCCESS */ +#define AMQP_CONTENT_TOO_LARGE 311 /**< Constant: CONTENT-TOO-LARGE */ +#define AMQP_NO_ROUTE 312 /**< Constant: NO-ROUTE */ +#define AMQP_NO_CONSUMERS 313 /**< Constant: NO-CONSUMERS */ +#define AMQP_ACCESS_REFUSED 403 /**< Constant: ACCESS-REFUSED */ +#define AMQP_NOT_FOUND 404 /**< Constant: NOT-FOUND */ +#define AMQP_RESOURCE_LOCKED 405 /**< Constant: RESOURCE-LOCKED */ +#define AMQP_PRECONDITION_FAILED 406 /**< Constant: PRECONDITION-FAILED */ +#define AMQP_CONNECTION_FORCED 320 /**< Constant: CONNECTION-FORCED */ +#define AMQP_INVALID_PATH 402 /**< Constant: INVALID-PATH */ +#define AMQP_FRAME_ERROR 501 /**< Constant: FRAME-ERROR */ +#define AMQP_SYNTAX_ERROR 502 /**< Constant: SYNTAX-ERROR */ +#define AMQP_COMMAND_INVALID 503 /**< Constant: COMMAND-INVALID */ +#define AMQP_CHANNEL_ERROR 504 /**< Constant: CHANNEL-ERROR */ +#define AMQP_UNEXPECTED_FRAME 505 /**< Constant: UNEXPECTED-FRAME */ +#define AMQP_RESOURCE_ERROR 506 /**< Constant: RESOURCE-ERROR */ +#define AMQP_NOT_ALLOWED 530 /**< Constant: NOT-ALLOWED */ +#define AMQP_NOT_IMPLEMENTED 540 /**< Constant: NOT-IMPLEMENTED */ +#define AMQP_INTERNAL_ERROR 541 /**< Constant: INTERNAL-ERROR */ + +/* Function prototypes. */ + +/** + * Get constant name string from constant + * + * @param [in] constantNumber constant to get the name of + * @returns string describing the constant. String is managed by + * the library and should not be free()'d by the program + */ +AMQP_PUBLIC_FUNCTION +char const *AMQP_CALL amqp_constant_name(int constantNumber); + +/** + * Checks to see if a constant is a hard error + * + * A hard error occurs when something severe enough + * happens that the connection must be closed. + * + * @param [in] constantNumber the error constant + * @returns true if its a hard error, false otherwise + */ +AMQP_PUBLIC_FUNCTION +amqp_boolean_t AMQP_CALL amqp_constant_is_hard_error(int constantNumber); + +/** + * Get method name string from method number + * + * @param [in] methodNumber the method number + * @returns method name string. String is managed by the library + * and should not be freed()'d by the program + */ +AMQP_PUBLIC_FUNCTION +char const *AMQP_CALL amqp_method_name(amqp_method_number_t methodNumber); + +/** + * Check whether a method has content + * + * A method that has content will receive the method frame + * a properties frame, then 1 to N body frames + * + * @param [in] methodNumber the method number + * @returns true if method has content, false otherwise + */ +AMQP_PUBLIC_FUNCTION +amqp_boolean_t AMQP_CALL + amqp_method_has_content(amqp_method_number_t methodNumber); + +/** + * Decodes a method from AMQP wireformat + * + * @param [in] methodNumber the method number for the decoded parameter + * @param [in] pool the memory pool to allocate the decoded method from + * @param [in] encoded the encoded byte string buffer + * @param [out] decoded pointer to the decoded method struct + * @returns 0 on success, an error code otherwise + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_decode_method(amqp_method_number_t methodNumber, + amqp_pool_t *pool, amqp_bytes_t encoded, + void **decoded); + +/** + * Decodes a header frame properties structure from AMQP wireformat + * + * @param [in] class_id the class id for the decoded parameter + * @param [in] pool the memory pool to allocate the decoded properties from + * @param [in] encoded the encoded byte string buffer + * @param [out] decoded pointer to the decoded properties struct + * @returns 0 on success, an error code otherwise + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_decode_properties(uint16_t class_id, amqp_pool_t *pool, + amqp_bytes_t encoded, void **decoded); + +/** + * Encodes a method structure in AMQP wireformat + * + * @param [in] methodNumber the method number for the decoded parameter + * @param [in] decoded the method structure (e.g., amqp_connection_start_t) + * @param [in] encoded an allocated byte buffer for the encoded method + * structure to be written to. If the buffer isn't large enough + * to hold the encoded method, an error code will be returned. + * @returns 0 on success, an error code otherwise. + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_encode_method(amqp_method_number_t methodNumber, + void *decoded, amqp_bytes_t encoded); + +/** + * Encodes a properties structure in AMQP wireformat + * + * @param [in] class_id the class id for the decoded parameter + * @param [in] decoded the properties structure (e.g., amqp_basic_properties_t) + * @param [in] encoded an allocated byte buffer for the encoded properties to + * written to. + * If the buffer isn't large enough to hold the encoded method, an + * an error code will be returned + * @returns 0 on success, an error code otherwise. + */ +AMQP_PUBLIC_FUNCTION +int AMQP_CALL amqp_encode_properties(uint16_t class_id, void *decoded, + amqp_bytes_t encoded); + +/* Method field records. */ + +#define AMQP_CONNECTION_START_METHOD \ + ((amqp_method_number_t)0x000A000A) /**< connection.start method id \ + @internal 10, 10; 655370 */ +/** connection.start method fields */ +typedef struct amqp_connection_start_t_ { + uint8_t version_major; /**< version-major */ + uint8_t version_minor; /**< version-minor */ + amqp_table_t server_properties; /**< server-properties */ + amqp_bytes_t mechanisms; /**< mechanisms */ + amqp_bytes_t locales; /**< locales */ +} amqp_connection_start_t; + +#define AMQP_CONNECTION_START_OK_METHOD \ + ((amqp_method_number_t)0x000A000B) /**< connection.start-ok method id \ + @internal 10, 11; 655371 */ +/** connection.start-ok method fields */ +typedef struct amqp_connection_start_ok_t_ { + amqp_table_t client_properties; /**< client-properties */ + amqp_bytes_t mechanism; /**< mechanism */ + amqp_bytes_t response; /**< response */ + amqp_bytes_t locale; /**< locale */ +} amqp_connection_start_ok_t; + +#define AMQP_CONNECTION_SECURE_METHOD \ + ((amqp_method_number_t)0x000A0014) /**< connection.secure method id \ + @internal 10, 20; 655380 */ +/** connection.secure method fields */ +typedef struct amqp_connection_secure_t_ { + amqp_bytes_t challenge; /**< challenge */ +} amqp_connection_secure_t; + +#define AMQP_CONNECTION_SECURE_OK_METHOD \ + ((amqp_method_number_t)0x000A0015) /**< connection.secure-ok method id \ + @internal 10, 21; 655381 */ +/** connection.secure-ok method fields */ +typedef struct amqp_connection_secure_ok_t_ { + amqp_bytes_t response; /**< response */ +} amqp_connection_secure_ok_t; + +#define AMQP_CONNECTION_TUNE_METHOD \ + ((amqp_method_number_t)0x000A001E) /**< connection.tune method id \ + @internal 10, 30; 655390 */ +/** connection.tune method fields */ +typedef struct amqp_connection_tune_t_ { + uint16_t channel_max; /**< channel-max */ + uint32_t frame_max; /**< frame-max */ + uint16_t heartbeat; /**< heartbeat */ +} amqp_connection_tune_t; + +#define AMQP_CONNECTION_TUNE_OK_METHOD \ + ((amqp_method_number_t)0x000A001F) /**< connection.tune-ok method id \ + @internal 10, 31; 655391 */ +/** connection.tune-ok method fields */ +typedef struct amqp_connection_tune_ok_t_ { + uint16_t channel_max; /**< channel-max */ + uint32_t frame_max; /**< frame-max */ + uint16_t heartbeat; /**< heartbeat */ +} amqp_connection_tune_ok_t; + +#define AMQP_CONNECTION_OPEN_METHOD \ + ((amqp_method_number_t)0x000A0028) /**< connection.open method id \ + @internal 10, 40; 655400 */ +/** connection.open method fields */ +typedef struct amqp_connection_open_t_ { + amqp_bytes_t virtual_host; /**< virtual-host */ + amqp_bytes_t capabilities; /**< capabilities */ + amqp_boolean_t insist; /**< insist */ +} amqp_connection_open_t; + +#define AMQP_CONNECTION_OPEN_OK_METHOD \ + ((amqp_method_number_t)0x000A0029) /**< connection.open-ok method id \ + @internal 10, 41; 655401 */ +/** connection.open-ok method fields */ +typedef struct amqp_connection_open_ok_t_ { + amqp_bytes_t known_hosts; /**< known-hosts */ +} amqp_connection_open_ok_t; + +#define AMQP_CONNECTION_CLOSE_METHOD \ + ((amqp_method_number_t)0x000A0032) /**< connection.close method id \ + @internal 10, 50; 655410 */ +/** connection.close method fields */ +typedef struct amqp_connection_close_t_ { + uint16_t reply_code; /**< reply-code */ + amqp_bytes_t reply_text; /**< reply-text */ + uint16_t class_id; /**< class-id */ + uint16_t method_id; /**< method-id */ +} amqp_connection_close_t; + +#define AMQP_CONNECTION_CLOSE_OK_METHOD \ + ((amqp_method_number_t)0x000A0033) /**< connection.close-ok method id \ + @internal 10, 51; 655411 */ +/** connection.close-ok method fields */ +typedef struct amqp_connection_close_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_connection_close_ok_t; + +#define AMQP_CONNECTION_BLOCKED_METHOD \ + ((amqp_method_number_t)0x000A003C) /**< connection.blocked method id \ + @internal 10, 60; 655420 */ +/** connection.blocked method fields */ +typedef struct amqp_connection_blocked_t_ { + amqp_bytes_t reason; /**< reason */ +} amqp_connection_blocked_t; + +#define AMQP_CONNECTION_UNBLOCKED_METHOD \ + ((amqp_method_number_t)0x000A003D) /**< connection.unblocked method id \ + @internal 10, 61; 655421 */ +/** connection.unblocked method fields */ +typedef struct amqp_connection_unblocked_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_connection_unblocked_t; + +#define AMQP_CHANNEL_OPEN_METHOD \ + ((amqp_method_number_t)0x0014000A) /**< channel.open method id @internal \ + 20, 10; 1310730 */ +/** channel.open method fields */ +typedef struct amqp_channel_open_t_ { + amqp_bytes_t out_of_band; /**< out-of-band */ +} amqp_channel_open_t; + +#define AMQP_CHANNEL_OPEN_OK_METHOD \ + ((amqp_method_number_t)0x0014000B) /**< channel.open-ok method id \ + @internal 20, 11; 1310731 */ +/** channel.open-ok method fields */ +typedef struct amqp_channel_open_ok_t_ { + amqp_bytes_t channel_id; /**< channel-id */ +} amqp_channel_open_ok_t; + +#define AMQP_CHANNEL_FLOW_METHOD \ + ((amqp_method_number_t)0x00140014) /**< channel.flow method id @internal \ + 20, 20; 1310740 */ +/** channel.flow method fields */ +typedef struct amqp_channel_flow_t_ { + amqp_boolean_t active; /**< active */ +} amqp_channel_flow_t; + +#define AMQP_CHANNEL_FLOW_OK_METHOD \ + ((amqp_method_number_t)0x00140015) /**< channel.flow-ok method id \ + @internal 20, 21; 1310741 */ +/** channel.flow-ok method fields */ +typedef struct amqp_channel_flow_ok_t_ { + amqp_boolean_t active; /**< active */ +} amqp_channel_flow_ok_t; + +#define AMQP_CHANNEL_CLOSE_METHOD \ + ((amqp_method_number_t)0x00140028) /**< channel.close method id @internal \ + 20, 40; 1310760 */ +/** channel.close method fields */ +typedef struct amqp_channel_close_t_ { + uint16_t reply_code; /**< reply-code */ + amqp_bytes_t reply_text; /**< reply-text */ + uint16_t class_id; /**< class-id */ + uint16_t method_id; /**< method-id */ +} amqp_channel_close_t; + +#define AMQP_CHANNEL_CLOSE_OK_METHOD \ + ((amqp_method_number_t)0x00140029) /**< channel.close-ok method id \ + @internal 20, 41; 1310761 */ +/** channel.close-ok method fields */ +typedef struct amqp_channel_close_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_channel_close_ok_t; + +#define AMQP_ACCESS_REQUEST_METHOD \ + ((amqp_method_number_t)0x001E000A) /**< access.request method id @internal \ + 30, 10; 1966090 */ +/** access.request method fields */ +typedef struct amqp_access_request_t_ { + amqp_bytes_t realm; /**< realm */ + amqp_boolean_t exclusive; /**< exclusive */ + amqp_boolean_t passive; /**< passive */ + amqp_boolean_t active; /**< active */ + amqp_boolean_t write; /**< write */ + amqp_boolean_t read; /**< read */ +} amqp_access_request_t; + +#define AMQP_ACCESS_REQUEST_OK_METHOD \ + ((amqp_method_number_t)0x001E000B) /**< access.request-ok method id \ + @internal 30, 11; 1966091 */ +/** access.request-ok method fields */ +typedef struct amqp_access_request_ok_t_ { + uint16_t ticket; /**< ticket */ +} amqp_access_request_ok_t; + +#define AMQP_EXCHANGE_DECLARE_METHOD \ + ((amqp_method_number_t)0x0028000A) /**< exchange.declare method id \ + @internal 40, 10; 2621450 */ +/** exchange.declare method fields */ +typedef struct amqp_exchange_declare_t_ { + uint16_t ticket; /**< ticket */ + amqp_bytes_t exchange; /**< exchange */ + amqp_bytes_t type; /**< type */ + amqp_boolean_t passive; /**< passive */ + amqp_boolean_t durable; /**< durable */ + amqp_boolean_t auto_delete; /**< auto-delete */ + amqp_boolean_t internal; /**< internal */ + amqp_boolean_t nowait; /**< nowait */ + amqp_table_t arguments; /**< arguments */ +} amqp_exchange_declare_t; + +#define AMQP_EXCHANGE_DECLARE_OK_METHOD \ + ((amqp_method_number_t)0x0028000B) /**< exchange.declare-ok method id \ + @internal 40, 11; 2621451 */ +/** exchange.declare-ok method fields */ +typedef struct amqp_exchange_declare_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_exchange_declare_ok_t; + +#define AMQP_EXCHANGE_DELETE_METHOD \ + ((amqp_method_number_t)0x00280014) /**< exchange.delete method id \ + @internal 40, 20; 2621460 */ +/** exchange.delete method fields */ +typedef struct amqp_exchange_delete_t_ { + uint16_t ticket; /**< ticket */ + amqp_bytes_t exchange; /**< exchange */ + amqp_boolean_t if_unused; /**< if-unused */ + amqp_boolean_t nowait; /**< nowait */ +} amqp_exchange_delete_t; + +#define AMQP_EXCHANGE_DELETE_OK_METHOD \ + ((amqp_method_number_t)0x00280015) /**< exchange.delete-ok method id \ + @internal 40, 21; 2621461 */ +/** exchange.delete-ok method fields */ +typedef struct amqp_exchange_delete_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_exchange_delete_ok_t; + +#define AMQP_EXCHANGE_BIND_METHOD \ + ((amqp_method_number_t)0x0028001E) /**< exchange.bind method id @internal \ + 40, 30; 2621470 */ +/** exchange.bind method fields */ +typedef struct amqp_exchange_bind_t_ { + uint16_t ticket; /**< ticket */ + amqp_bytes_t destination; /**< destination */ + amqp_bytes_t source; /**< source */ + amqp_bytes_t routing_key; /**< routing-key */ + amqp_boolean_t nowait; /**< nowait */ + amqp_table_t arguments; /**< arguments */ +} amqp_exchange_bind_t; + +#define AMQP_EXCHANGE_BIND_OK_METHOD \ + ((amqp_method_number_t)0x0028001F) /**< exchange.bind-ok method id \ + @internal 40, 31; 2621471 */ +/** exchange.bind-ok method fields */ +typedef struct amqp_exchange_bind_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_exchange_bind_ok_t; + +#define AMQP_EXCHANGE_UNBIND_METHOD \ + ((amqp_method_number_t)0x00280028) /**< exchange.unbind method id \ + @internal 40, 40; 2621480 */ +/** exchange.unbind method fields */ +typedef struct amqp_exchange_unbind_t_ { + uint16_t ticket; /**< ticket */ + amqp_bytes_t destination; /**< destination */ + amqp_bytes_t source; /**< source */ + amqp_bytes_t routing_key; /**< routing-key */ + amqp_boolean_t nowait; /**< nowait */ + amqp_table_t arguments; /**< arguments */ +} amqp_exchange_unbind_t; + +#define AMQP_EXCHANGE_UNBIND_OK_METHOD \ + ((amqp_method_number_t)0x00280033) /**< exchange.unbind-ok method id \ + @internal 40, 51; 2621491 */ +/** exchange.unbind-ok method fields */ +typedef struct amqp_exchange_unbind_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_exchange_unbind_ok_t; + +#define AMQP_QUEUE_DECLARE_METHOD \ + ((amqp_method_number_t)0x0032000A) /**< queue.declare method id @internal \ + 50, 10; 3276810 */ +/** queue.declare method fields */ +typedef struct amqp_queue_declare_t_ { + uint16_t ticket; /**< ticket */ + amqp_bytes_t queue; /**< queue */ + amqp_boolean_t passive; /**< passive */ + amqp_boolean_t durable; /**< durable */ + amqp_boolean_t exclusive; /**< exclusive */ + amqp_boolean_t auto_delete; /**< auto-delete */ + amqp_boolean_t nowait; /**< nowait */ + amqp_table_t arguments; /**< arguments */ +} amqp_queue_declare_t; + +#define AMQP_QUEUE_DECLARE_OK_METHOD \ + ((amqp_method_number_t)0x0032000B) /**< queue.declare-ok method id \ + @internal 50, 11; 3276811 */ +/** queue.declare-ok method fields */ +typedef struct amqp_queue_declare_ok_t_ { + amqp_bytes_t queue; /**< queue */ + uint32_t message_count; /**< message-count */ + uint32_t consumer_count; /**< consumer-count */ +} amqp_queue_declare_ok_t; + +#define AMQP_QUEUE_BIND_METHOD \ + ((amqp_method_number_t)0x00320014) /**< queue.bind method id @internal 50, \ + 20; 3276820 */ +/** queue.bind method fields */ +typedef struct amqp_queue_bind_t_ { + uint16_t ticket; /**< ticket */ + amqp_bytes_t queue; /**< queue */ + amqp_bytes_t exchange; /**< exchange */ + amqp_bytes_t routing_key; /**< routing-key */ + amqp_boolean_t nowait; /**< nowait */ + amqp_table_t arguments; /**< arguments */ +} amqp_queue_bind_t; + +#define AMQP_QUEUE_BIND_OK_METHOD \ + ((amqp_method_number_t)0x00320015) /**< queue.bind-ok method id @internal \ + 50, 21; 3276821 */ +/** queue.bind-ok method fields */ +typedef struct amqp_queue_bind_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_queue_bind_ok_t; + +#define AMQP_QUEUE_PURGE_METHOD \ + ((amqp_method_number_t)0x0032001E) /**< queue.purge method id @internal \ + 50, 30; 3276830 */ +/** queue.purge method fields */ +typedef struct amqp_queue_purge_t_ { + uint16_t ticket; /**< ticket */ + amqp_bytes_t queue; /**< queue */ + amqp_boolean_t nowait; /**< nowait */ +} amqp_queue_purge_t; + +#define AMQP_QUEUE_PURGE_OK_METHOD \ + ((amqp_method_number_t)0x0032001F) /**< queue.purge-ok method id @internal \ + 50, 31; 3276831 */ +/** queue.purge-ok method fields */ +typedef struct amqp_queue_purge_ok_t_ { + uint32_t message_count; /**< message-count */ +} amqp_queue_purge_ok_t; + +#define AMQP_QUEUE_DELETE_METHOD \ + ((amqp_method_number_t)0x00320028) /**< queue.delete method id @internal \ + 50, 40; 3276840 */ +/** queue.delete method fields */ +typedef struct amqp_queue_delete_t_ { + uint16_t ticket; /**< ticket */ + amqp_bytes_t queue; /**< queue */ + amqp_boolean_t if_unused; /**< if-unused */ + amqp_boolean_t if_empty; /**< if-empty */ + amqp_boolean_t nowait; /**< nowait */ +} amqp_queue_delete_t; + +#define AMQP_QUEUE_DELETE_OK_METHOD \ + ((amqp_method_number_t)0x00320029) /**< queue.delete-ok method id \ + @internal 50, 41; 3276841 */ +/** queue.delete-ok method fields */ +typedef struct amqp_queue_delete_ok_t_ { + uint32_t message_count; /**< message-count */ +} amqp_queue_delete_ok_t; + +#define AMQP_QUEUE_UNBIND_METHOD \ + ((amqp_method_number_t)0x00320032) /**< queue.unbind method id @internal \ + 50, 50; 3276850 */ +/** queue.unbind method fields */ +typedef struct amqp_queue_unbind_t_ { + uint16_t ticket; /**< ticket */ + amqp_bytes_t queue; /**< queue */ + amqp_bytes_t exchange; /**< exchange */ + amqp_bytes_t routing_key; /**< routing-key */ + amqp_table_t arguments; /**< arguments */ +} amqp_queue_unbind_t; + +#define AMQP_QUEUE_UNBIND_OK_METHOD \ + ((amqp_method_number_t)0x00320033) /**< queue.unbind-ok method id \ + @internal 50, 51; 3276851 */ +/** queue.unbind-ok method fields */ +typedef struct amqp_queue_unbind_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_queue_unbind_ok_t; + +#define AMQP_BASIC_QOS_METHOD \ + ((amqp_method_number_t)0x003C000A) /**< basic.qos method id @internal 60, \ + 10; 3932170 */ +/** basic.qos method fields */ +typedef struct amqp_basic_qos_t_ { + uint32_t prefetch_size; /**< prefetch-size */ + uint16_t prefetch_count; /**< prefetch-count */ + amqp_boolean_t global; /**< global */ +} amqp_basic_qos_t; + +#define AMQP_BASIC_QOS_OK_METHOD \ + ((amqp_method_number_t)0x003C000B) /**< basic.qos-ok method id @internal \ + 60, 11; 3932171 */ +/** basic.qos-ok method fields */ +typedef struct amqp_basic_qos_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_basic_qos_ok_t; + +#define AMQP_BASIC_CONSUME_METHOD \ + ((amqp_method_number_t)0x003C0014) /**< basic.consume method id @internal \ + 60, 20; 3932180 */ +/** basic.consume method fields */ +typedef struct amqp_basic_consume_t_ { + uint16_t ticket; /**< ticket */ + amqp_bytes_t queue; /**< queue */ + amqp_bytes_t consumer_tag; /**< consumer-tag */ + amqp_boolean_t no_local; /**< no-local */ + amqp_boolean_t no_ack; /**< no-ack */ + amqp_boolean_t exclusive; /**< exclusive */ + amqp_boolean_t nowait; /**< nowait */ + amqp_table_t arguments; /**< arguments */ +} amqp_basic_consume_t; + +#define AMQP_BASIC_CONSUME_OK_METHOD \ + ((amqp_method_number_t)0x003C0015) /**< basic.consume-ok method id \ + @internal 60, 21; 3932181 */ +/** basic.consume-ok method fields */ +typedef struct amqp_basic_consume_ok_t_ { + amqp_bytes_t consumer_tag; /**< consumer-tag */ +} amqp_basic_consume_ok_t; + +#define AMQP_BASIC_CANCEL_METHOD \ + ((amqp_method_number_t)0x003C001E) /**< basic.cancel method id @internal \ + 60, 30; 3932190 */ +/** basic.cancel method fields */ +typedef struct amqp_basic_cancel_t_ { + amqp_bytes_t consumer_tag; /**< consumer-tag */ + amqp_boolean_t nowait; /**< nowait */ +} amqp_basic_cancel_t; + +#define AMQP_BASIC_CANCEL_OK_METHOD \ + ((amqp_method_number_t)0x003C001F) /**< basic.cancel-ok method id \ + @internal 60, 31; 3932191 */ +/** basic.cancel-ok method fields */ +typedef struct amqp_basic_cancel_ok_t_ { + amqp_bytes_t consumer_tag; /**< consumer-tag */ +} amqp_basic_cancel_ok_t; + +#define AMQP_BASIC_PUBLISH_METHOD \ + ((amqp_method_number_t)0x003C0028) /**< basic.publish method id @internal \ + 60, 40; 3932200 */ +/** basic.publish method fields */ +typedef struct amqp_basic_publish_t_ { + uint16_t ticket; /**< ticket */ + amqp_bytes_t exchange; /**< exchange */ + amqp_bytes_t routing_key; /**< routing-key */ + amqp_boolean_t mandatory; /**< mandatory */ + amqp_boolean_t immediate; /**< immediate */ +} amqp_basic_publish_t; + +#define AMQP_BASIC_RETURN_METHOD \ + ((amqp_method_number_t)0x003C0032) /**< basic.return method id @internal \ + 60, 50; 3932210 */ +/** basic.return method fields */ +typedef struct amqp_basic_return_t_ { + uint16_t reply_code; /**< reply-code */ + amqp_bytes_t reply_text; /**< reply-text */ + amqp_bytes_t exchange; /**< exchange */ + amqp_bytes_t routing_key; /**< routing-key */ +} amqp_basic_return_t; + +#define AMQP_BASIC_DELIVER_METHOD \ + ((amqp_method_number_t)0x003C003C) /**< basic.deliver method id @internal \ + 60, 60; 3932220 */ +/** basic.deliver method fields */ +typedef struct amqp_basic_deliver_t_ { + amqp_bytes_t consumer_tag; /**< consumer-tag */ + uint64_t delivery_tag; /**< delivery-tag */ + amqp_boolean_t redelivered; /**< redelivered */ + amqp_bytes_t exchange; /**< exchange */ + amqp_bytes_t routing_key; /**< routing-key */ +} amqp_basic_deliver_t; + +#define AMQP_BASIC_GET_METHOD \ + ((amqp_method_number_t)0x003C0046) /**< basic.get method id @internal 60, \ + 70; 3932230 */ +/** basic.get method fields */ +typedef struct amqp_basic_get_t_ { + uint16_t ticket; /**< ticket */ + amqp_bytes_t queue; /**< queue */ + amqp_boolean_t no_ack; /**< no-ack */ +} amqp_basic_get_t; + +#define AMQP_BASIC_GET_OK_METHOD \ + ((amqp_method_number_t)0x003C0047) /**< basic.get-ok method id @internal \ + 60, 71; 3932231 */ +/** basic.get-ok method fields */ +typedef struct amqp_basic_get_ok_t_ { + uint64_t delivery_tag; /**< delivery-tag */ + amqp_boolean_t redelivered; /**< redelivered */ + amqp_bytes_t exchange; /**< exchange */ + amqp_bytes_t routing_key; /**< routing-key */ + uint32_t message_count; /**< message-count */ +} amqp_basic_get_ok_t; + +#define AMQP_BASIC_GET_EMPTY_METHOD \ + ((amqp_method_number_t)0x003C0048) /**< basic.get-empty method id \ + @internal 60, 72; 3932232 */ +/** basic.get-empty method fields */ +typedef struct amqp_basic_get_empty_t_ { + amqp_bytes_t cluster_id; /**< cluster-id */ +} amqp_basic_get_empty_t; + +#define AMQP_BASIC_ACK_METHOD \ + ((amqp_method_number_t)0x003C0050) /**< basic.ack method id @internal 60, \ + 80; 3932240 */ +/** basic.ack method fields */ +typedef struct amqp_basic_ack_t_ { + uint64_t delivery_tag; /**< delivery-tag */ + amqp_boolean_t multiple; /**< multiple */ +} amqp_basic_ack_t; + +#define AMQP_BASIC_REJECT_METHOD \ + ((amqp_method_number_t)0x003C005A) /**< basic.reject method id @internal \ + 60, 90; 3932250 */ +/** basic.reject method fields */ +typedef struct amqp_basic_reject_t_ { + uint64_t delivery_tag; /**< delivery-tag */ + amqp_boolean_t requeue; /**< requeue */ +} amqp_basic_reject_t; + +#define AMQP_BASIC_RECOVER_ASYNC_METHOD \ + ((amqp_method_number_t)0x003C0064) /**< basic.recover-async method id \ + @internal 60, 100; 3932260 */ +/** basic.recover-async method fields */ +typedef struct amqp_basic_recover_async_t_ { + amqp_boolean_t requeue; /**< requeue */ +} amqp_basic_recover_async_t; + +#define AMQP_BASIC_RECOVER_METHOD \ + ((amqp_method_number_t)0x003C006E) /**< basic.recover method id @internal \ + 60, 110; 3932270 */ +/** basic.recover method fields */ +typedef struct amqp_basic_recover_t_ { + amqp_boolean_t requeue; /**< requeue */ +} amqp_basic_recover_t; + +#define AMQP_BASIC_RECOVER_OK_METHOD \ + ((amqp_method_number_t)0x003C006F) /**< basic.recover-ok method id \ + @internal 60, 111; 3932271 */ +/** basic.recover-ok method fields */ +typedef struct amqp_basic_recover_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_basic_recover_ok_t; + +#define AMQP_BASIC_NACK_METHOD \ + ((amqp_method_number_t)0x003C0078) /**< basic.nack method id @internal 60, \ + 120; 3932280 */ +/** basic.nack method fields */ +typedef struct amqp_basic_nack_t_ { + uint64_t delivery_tag; /**< delivery-tag */ + amqp_boolean_t multiple; /**< multiple */ + amqp_boolean_t requeue; /**< requeue */ +} amqp_basic_nack_t; + +#define AMQP_TX_SELECT_METHOD \ + ((amqp_method_number_t)0x005A000A) /**< tx.select method id @internal 90, \ + 10; 5898250 */ +/** tx.select method fields */ +typedef struct amqp_tx_select_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_tx_select_t; + +#define AMQP_TX_SELECT_OK_METHOD \ + ((amqp_method_number_t)0x005A000B) /**< tx.select-ok method id @internal \ + 90, 11; 5898251 */ +/** tx.select-ok method fields */ +typedef struct amqp_tx_select_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_tx_select_ok_t; + +#define AMQP_TX_COMMIT_METHOD \ + ((amqp_method_number_t)0x005A0014) /**< tx.commit method id @internal 90, \ + 20; 5898260 */ +/** tx.commit method fields */ +typedef struct amqp_tx_commit_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_tx_commit_t; + +#define AMQP_TX_COMMIT_OK_METHOD \ + ((amqp_method_number_t)0x005A0015) /**< tx.commit-ok method id @internal \ + 90, 21; 5898261 */ +/** tx.commit-ok method fields */ +typedef struct amqp_tx_commit_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_tx_commit_ok_t; + +#define AMQP_TX_ROLLBACK_METHOD \ + ((amqp_method_number_t)0x005A001E) /**< tx.rollback method id @internal \ + 90, 30; 5898270 */ +/** tx.rollback method fields */ +typedef struct amqp_tx_rollback_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_tx_rollback_t; + +#define AMQP_TX_ROLLBACK_OK_METHOD \ + ((amqp_method_number_t)0x005A001F) /**< tx.rollback-ok method id @internal \ + 90, 31; 5898271 */ +/** tx.rollback-ok method fields */ +typedef struct amqp_tx_rollback_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_tx_rollback_ok_t; + +#define AMQP_CONFIRM_SELECT_METHOD \ + ((amqp_method_number_t)0x0055000A) /**< confirm.select method id @internal \ + 85, 10; 5570570 */ +/** confirm.select method fields */ +typedef struct amqp_confirm_select_t_ { + amqp_boolean_t nowait; /**< nowait */ +} amqp_confirm_select_t; + +#define AMQP_CONFIRM_SELECT_OK_METHOD \ + ((amqp_method_number_t)0x0055000B) /**< confirm.select-ok method id \ + @internal 85, 11; 5570571 */ +/** confirm.select-ok method fields */ +typedef struct amqp_confirm_select_ok_t_ { + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_confirm_select_ok_t; + +/* Class property records. */ +#define AMQP_CONNECTION_CLASS \ + (0x000A) /**< connection class id @internal 10 \ + */ +/** connection class properties */ +typedef struct amqp_connection_properties_t_ { + amqp_flags_t _flags; /**< bit-mask of set fields */ + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_connection_properties_t; + +#define AMQP_CHANNEL_CLASS (0x0014) /**< channel class id @internal 20 */ +/** channel class properties */ +typedef struct amqp_channel_properties_t_ { + amqp_flags_t _flags; /**< bit-mask of set fields */ + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_channel_properties_t; + +#define AMQP_ACCESS_CLASS (0x001E) /**< access class id @internal 30 */ +/** access class properties */ +typedef struct amqp_access_properties_t_ { + amqp_flags_t _flags; /**< bit-mask of set fields */ + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_access_properties_t; + +#define AMQP_EXCHANGE_CLASS (0x0028) /**< exchange class id @internal 40 */ +/** exchange class properties */ +typedef struct amqp_exchange_properties_t_ { + amqp_flags_t _flags; /**< bit-mask of set fields */ + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_exchange_properties_t; + +#define AMQP_QUEUE_CLASS (0x0032) /**< queue class id @internal 50 */ +/** queue class properties */ +typedef struct amqp_queue_properties_t_ { + amqp_flags_t _flags; /**< bit-mask of set fields */ + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_queue_properties_t; + +#define AMQP_BASIC_CLASS (0x003C) /**< basic class id @internal 60 */ +#define AMQP_BASIC_CONTENT_TYPE_FLAG (1 << 15) +#define AMQP_BASIC_CONTENT_ENCODING_FLAG (1 << 14) +#define AMQP_BASIC_HEADERS_FLAG (1 << 13) +#define AMQP_BASIC_DELIVERY_MODE_FLAG (1 << 12) +#define AMQP_BASIC_PRIORITY_FLAG (1 << 11) +#define AMQP_BASIC_CORRELATION_ID_FLAG (1 << 10) +#define AMQP_BASIC_REPLY_TO_FLAG (1 << 9) +#define AMQP_BASIC_EXPIRATION_FLAG (1 << 8) +#define AMQP_BASIC_MESSAGE_ID_FLAG (1 << 7) +#define AMQP_BASIC_TIMESTAMP_FLAG (1 << 6) +#define AMQP_BASIC_TYPE_FLAG (1 << 5) +#define AMQP_BASIC_USER_ID_FLAG (1 << 4) +#define AMQP_BASIC_APP_ID_FLAG (1 << 3) +#define AMQP_BASIC_CLUSTER_ID_FLAG (1 << 2) +/** basic class properties */ +typedef struct amqp_basic_properties_t_ { + amqp_flags_t _flags; /**< bit-mask of set fields */ + amqp_bytes_t content_type; /**< content-type */ + amqp_bytes_t content_encoding; /**< content-encoding */ + amqp_table_t headers; /**< headers */ + uint8_t delivery_mode; /**< delivery-mode */ + uint8_t priority; /**< priority */ + amqp_bytes_t correlation_id; /**< correlation-id */ + amqp_bytes_t reply_to; /**< reply-to */ + amqp_bytes_t expiration; /**< expiration */ + amqp_bytes_t message_id; /**< message-id */ + uint64_t timestamp; /**< timestamp */ + amqp_bytes_t type; /**< type */ + amqp_bytes_t user_id; /**< user-id */ + amqp_bytes_t app_id; /**< app-id */ + amqp_bytes_t cluster_id; /**< cluster-id */ +} amqp_basic_properties_t; + +#define AMQP_TX_CLASS (0x005A) /**< tx class id @internal 90 */ +/** tx class properties */ +typedef struct amqp_tx_properties_t_ { + amqp_flags_t _flags; /**< bit-mask of set fields */ + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_tx_properties_t; + +#define AMQP_CONFIRM_CLASS (0x0055) /**< confirm class id @internal 85 */ +/** confirm class properties */ +typedef struct amqp_confirm_properties_t_ { + amqp_flags_t _flags; /**< bit-mask of set fields */ + char dummy; /**< Dummy field to avoid empty struct */ +} amqp_confirm_properties_t; + +/* API functions for methods */ + +/** + * amqp_channel_open + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @returns amqp_channel_open_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_channel_open_ok_t *AMQP_CALL + amqp_channel_open(amqp_connection_state_t state, amqp_channel_t channel); +/** + * amqp_channel_flow + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] active active + * @returns amqp_channel_flow_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_channel_flow_ok_t *AMQP_CALL + amqp_channel_flow(amqp_connection_state_t state, amqp_channel_t channel, + amqp_boolean_t active); +/** + * amqp_exchange_declare + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] exchange exchange + * @param [in] type type + * @param [in] passive passive + * @param [in] durable durable + * @param [in] auto_delete auto_delete + * @param [in] internal internal + * @param [in] arguments arguments + * @returns amqp_exchange_declare_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_exchange_declare_ok_t *AMQP_CALL amqp_exchange_declare( + amqp_connection_state_t state, amqp_channel_t channel, + amqp_bytes_t exchange, amqp_bytes_t type, amqp_boolean_t passive, + amqp_boolean_t durable, amqp_boolean_t auto_delete, amqp_boolean_t internal, + amqp_table_t arguments); +/** + * amqp_exchange_delete + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] exchange exchange + * @param [in] if_unused if_unused + * @returns amqp_exchange_delete_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_exchange_delete_ok_t *AMQP_CALL + amqp_exchange_delete(amqp_connection_state_t state, amqp_channel_t channel, + amqp_bytes_t exchange, amqp_boolean_t if_unused); +/** + * amqp_exchange_bind + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] destination destination + * @param [in] source source + * @param [in] routing_key routing_key + * @param [in] arguments arguments + * @returns amqp_exchange_bind_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_exchange_bind_ok_t *AMQP_CALL + amqp_exchange_bind(amqp_connection_state_t state, amqp_channel_t channel, + amqp_bytes_t destination, amqp_bytes_t source, + amqp_bytes_t routing_key, amqp_table_t arguments); +/** + * amqp_exchange_unbind + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] destination destination + * @param [in] source source + * @param [in] routing_key routing_key + * @param [in] arguments arguments + * @returns amqp_exchange_unbind_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_exchange_unbind_ok_t *AMQP_CALL + amqp_exchange_unbind(amqp_connection_state_t state, amqp_channel_t channel, + amqp_bytes_t destination, amqp_bytes_t source, + amqp_bytes_t routing_key, amqp_table_t arguments); +/** + * amqp_queue_declare + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] queue queue + * @param [in] passive passive + * @param [in] durable durable + * @param [in] exclusive exclusive + * @param [in] auto_delete auto_delete + * @param [in] arguments arguments + * @returns amqp_queue_declare_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_queue_declare_ok_t *AMQP_CALL amqp_queue_declare( + amqp_connection_state_t state, amqp_channel_t channel, amqp_bytes_t queue, + amqp_boolean_t passive, amqp_boolean_t durable, amqp_boolean_t exclusive, + amqp_boolean_t auto_delete, amqp_table_t arguments); +/** + * amqp_queue_bind + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] queue queue + * @param [in] exchange exchange + * @param [in] routing_key routing_key + * @param [in] arguments arguments + * @returns amqp_queue_bind_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_queue_bind_ok_t *AMQP_CALL amqp_queue_bind( + amqp_connection_state_t state, amqp_channel_t channel, amqp_bytes_t queue, + amqp_bytes_t exchange, amqp_bytes_t routing_key, amqp_table_t arguments); +/** + * amqp_queue_purge + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] queue queue + * @returns amqp_queue_purge_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_queue_purge_ok_t *AMQP_CALL amqp_queue_purge(amqp_connection_state_t state, + amqp_channel_t channel, + amqp_bytes_t queue); +/** + * amqp_queue_delete + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] queue queue + * @param [in] if_unused if_unused + * @param [in] if_empty if_empty + * @returns amqp_queue_delete_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_queue_delete_ok_t *AMQP_CALL amqp_queue_delete( + amqp_connection_state_t state, amqp_channel_t channel, amqp_bytes_t queue, + amqp_boolean_t if_unused, amqp_boolean_t if_empty); +/** + * amqp_queue_unbind + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] queue queue + * @param [in] exchange exchange + * @param [in] routing_key routing_key + * @param [in] arguments arguments + * @returns amqp_queue_unbind_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_queue_unbind_ok_t *AMQP_CALL amqp_queue_unbind( + amqp_connection_state_t state, amqp_channel_t channel, amqp_bytes_t queue, + amqp_bytes_t exchange, amqp_bytes_t routing_key, amqp_table_t arguments); +/** + * amqp_basic_qos + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] prefetch_size prefetch_size + * @param [in] prefetch_count prefetch_count + * @param [in] global global + * @returns amqp_basic_qos_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_basic_qos_ok_t *AMQP_CALL amqp_basic_qos(amqp_connection_state_t state, + amqp_channel_t channel, + uint32_t prefetch_size, + uint16_t prefetch_count, + amqp_boolean_t global); +/** + * amqp_basic_consume + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] queue queue + * @param [in] consumer_tag consumer_tag + * @param [in] no_local no_local + * @param [in] no_ack no_ack + * @param [in] exclusive exclusive + * @param [in] arguments arguments + * @returns amqp_basic_consume_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_basic_consume_ok_t *AMQP_CALL amqp_basic_consume( + amqp_connection_state_t state, amqp_channel_t channel, amqp_bytes_t queue, + amqp_bytes_t consumer_tag, amqp_boolean_t no_local, amqp_boolean_t no_ack, + amqp_boolean_t exclusive, amqp_table_t arguments); +/** + * amqp_basic_cancel + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] consumer_tag consumer_tag + * @returns amqp_basic_cancel_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_basic_cancel_ok_t *AMQP_CALL + amqp_basic_cancel(amqp_connection_state_t state, amqp_channel_t channel, + amqp_bytes_t consumer_tag); +/** + * amqp_basic_recover + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @param [in] requeue requeue + * @returns amqp_basic_recover_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_basic_recover_ok_t *AMQP_CALL + amqp_basic_recover(amqp_connection_state_t state, amqp_channel_t channel, + amqp_boolean_t requeue); +/** + * amqp_tx_select + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @returns amqp_tx_select_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_tx_select_ok_t *AMQP_CALL amqp_tx_select(amqp_connection_state_t state, + amqp_channel_t channel); +/** + * amqp_tx_commit + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @returns amqp_tx_commit_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_tx_commit_ok_t *AMQP_CALL amqp_tx_commit(amqp_connection_state_t state, + amqp_channel_t channel); +/** + * amqp_tx_rollback + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @returns amqp_tx_rollback_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_tx_rollback_ok_t *AMQP_CALL amqp_tx_rollback(amqp_connection_state_t state, + amqp_channel_t channel); +/** + * amqp_confirm_select + * + * @param [in] state connection state + * @param [in] channel the channel to do the RPC on + * @returns amqp_confirm_select_ok_t + */ +AMQP_PUBLIC_FUNCTION +amqp_confirm_select_ok_t *AMQP_CALL + amqp_confirm_select(amqp_connection_state_t state, amqp_channel_t channel); + +AMQP_END_DECLS + +#endif /* AMQP_FRAMING_H */ diff --git a/ext/librabbitmq/macos/include/amqp_tcp_socket.h b/ext/librabbitmq/macos/include/amqp_tcp_socket.h new file mode 100644 index 00000000..3e9d82f5 --- /dev/null +++ b/ext/librabbitmq/macos/include/amqp_tcp_socket.h @@ -0,0 +1,68 @@ +/** \file */ +/* + * Portions created by Alan Antonuk are Copyright (c) 2013-2014 Alan Antonuk. + * All Rights Reserved. + * + * Portions created by Michael Steinert are Copyright (c) 2012-2013 Michael + * Steinert. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * A TCP socket connection. + */ + +#ifndef AMQP_TCP_SOCKET_H +#define AMQP_TCP_SOCKET_H + +#include + +AMQP_BEGIN_DECLS + +/** + * Create a new TCP socket. + * + * Call amqp_connection_close() to release socket resources. + * + * \return A new socket object or NULL if an error occurred. + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +amqp_socket_t *AMQP_CALL amqp_tcp_socket_new(amqp_connection_state_t state); + +/** + * Assign an open file descriptor to a socket object. + * + * This function must not be used in conjunction with amqp_socket_open(), i.e. + * the socket connection should already be open(2) when this function is + * called. + * + * \param [in,out] self A TCP socket object. + * \param [in] sockfd An open socket descriptor. + * + * \since v0.4.0 + */ +AMQP_PUBLIC_FUNCTION +void AMQP_CALL amqp_tcp_socket_set_sockfd(amqp_socket_t *self, int sockfd); + +AMQP_END_DECLS + +#endif /* AMQP_TCP_SOCKET_H */ diff --git a/ext/librabbitmq/macos/lib/librabbitmq.a b/ext/librabbitmq/macos/lib/librabbitmq.a new file mode 100644 index 0000000000000000000000000000000000000000..f3d27b31dcda47dde6601e85aa5901ff1b3a66d0 GIT binary patch literal 95704 zcmeEvdwf*Y_3sG;h=QD0L8GFKiZ!&N38IDynjslDqZ1N=C~9#M!bDQ@GMV8~#Rexa zIgF#URm-pKuSKgZwYH_#7E&J=1WB+yQniZO*7&N7X%$}xR+;-vS;EWh~ZGYZe0Uf@bTh38*5{rvOKpHXNc&UBY?ylYi_h8sBiR`&ml z;fF_ST3#SaTh4sW8?9*@UeUCz9R4SUpX6v-?wMKIj-!yj;w-IsB=Y!xri~dZgf!I-(Xn5&|vvYPX8vB`={)GgyA?q(*JYp zKOOlzaAlVEeWt&b`Q$U*TTB;cm`i1d{GGpoMWY%c~n31NHve`lgi*R8w=HQK6a|YwKDX{H=ld zKus`-YzNFo9os}u4pL(0nn{)RwsdDAjx!no!Zq}CFw z3n*Cwjj6PZOQl^!xwtOiUs~6w_y!aX3Dj4&D3w^y^?_gtHq>ZgA>~BYTKzRmjln>p z$~XsDa&|)~5V9pN5%#nd&XTZ1HHTWRQ=&+WO^)Cyq~Fj`r;>-irK!GtX?4x@tVCdJ zB~!h$sYOvsTS?MN|8)U-c%ze`IkdFCu5~#lAS1N|zGW$WHk_LJrdB09)YJ%yx~4|I z6&+}34zBiBx3pBRW_}X0bagOU-hw7ry|i926V~K!4Yt%ZUZV)4;zdTUg5?mUnwu;^wXhB6y&!e@e=K4e#5>rCdD(feO)Cc@^jm-&NG*qu% z8t}KE0#~=fR7173ffiNS(uVn|6lEcEz8V87Q&o_jqXX-2Ql{D(Xj~>0z)X_}h})QG zm#83Yc~po*9)qFAK&m*xru=~$Le+_uk*o|!29#k*l7{N~`lcEd!iw@Q3pF#kMp~cW zYN(`ZRpiZ0O)3>a!!~PLP=pYRD~E-EoPKMXNra6*O1u>nh$Ud3zcJLXlyt*Yi8=wv zyRNY=C_4q|N9(@221PIW35gQUW!1rID3}YLxeG&V^#>Y7tD}sEvO;yBCD2^2Dr|kz zb#+Q6;r6er3ocJJ&4vJ)GW1N%)l2K@>n!a#btd)#wP0)|Z^bt@Ekz+I+i7ZL4z|`M ziM94W&1fMxm#72iF>9{3nVoEBg#wsN7$U0SGK&quR&BkNpyB4kZKTlpkV7EmeDDI%UYx)&A=PD%E9y z+Uig}nvz79g8bGtv5K0jThK^{T9gR~YnqkmqY+kmOd?YnM@qG!sj(^8)QFKH^@kpd2rR2ZyQc&rLga?pCL6Ay)gNjM z)+KU9bksDbCKFs?qlA`dTnpo9ZLLm>l~lJJXj~DfhcR;U3T-Dw!%US~#@8~wcdn4D8{P7|iD+H;@(>ky_hS(plG80Kpj%4<~^=W8y!cuvH- zhXOJ@#W%=+Hj0Bs`N318m-x}+_Xh*3g3>Mhi#&@LCH>0PRV7`-57RNNr&ZHlB~-T7 zMnFA&RIy;7rMkZG0)g`T?flkPNlKRlT5gTx$6jr`axnD!xz9}a?ff=Z$$&>Nr=h0+ z{HzaWKY;?jriSKf)Z0+wN{sIPeqU)K5RT?L>8m2e9l#fzfO%{rqGL=i)r5xKb400&f53|u&|rI8trU66pzo2fXPa?5k00ISfeI; zt&!CiA26b$ep0PzOLj!d)Z`);R8pl zECa7x2d{?&&DwY$5(}QOHvTMN=zK(8B?92MKsjbBN4;>Yjg#U+M}eeBg*+)F1Lpe* z^AqK`PdUhfmh1pcOgTPOj?a~2wBnPi9H%HpzH$^O$1LSIBL9S@EJA92Ifnkse#!a-vO45E0==Zg|rA}X{q%1+eob2$l5Mivp2E)jeLOa8PGxgZl)9RC+TjkQVE`l1lNIx z5`?>>Q%0y%&BP@&M2YN`E5|pLqh2{~RF0@}T&|)oSB@K%j_JzbQI2brqe(e#RgNDk$1};nL-DYN%>b|2cwhK;JpM6cxCrSF^?m`GQHPU|hAJBC5`G-&>USB)S<|KGcZI@S=bKCTv9i)+i7%4c$8}2LJSGX(PixwK;f9Cnj9bWS}ulb_a+;8-H`ZYZ6$B?@? z4Gl1?__`Wa1klS{h84e{PCt6gC6g@ux*SdDx6^#ZGNLFRDM)iLSxyWAwpAb@pZVEd zO3>)&(c4#_00$%hUr2yA=F+#uPI^f;kYz-sqJ;ROA|FbB+<-m2H?I1pY(sJV8d8pc~O~$0wp>0qe^;1ZtOI z_99}Q5p`!7rbloLzj-_fu_aqKcNO=)Z$8oU-UxGhPi&;VWp}OKxLx1!6abt{`v7~2 z^)1f={u%x!YW4c+kK9^g}ehI#N~{X6sWx9`mk4`iA1iVSm2U+i6sSV(Ia zUmZA4@4OL8G|VM^Q1Z=4J*l}OK?K%ZS;yOY`#FR*cevM$=^AN7JpD%0 zK!#XF$5MvYWsm790qzweygkPkMPAK!edZyb`H?6VluFmXCxS_&43XVXA!%bk?|czR zcVvRDKLs5^!_4zBpnX{f46_6}Tu2H`M!82s8K>*Jjp&3N!>k0SH}%eSKzp-#eddh? zhIv_j?44t!4#dDw@1*G`@_%X`fEqk*!}QXTe=teSf5$hl9~_&Cu(fd-Wd?m}ggFto zZKN!l77tDU7jvYi@L#b{;G_{Hk38R@km#sBN=A)5x1q4?@&8CvTna+}BS8Y2(Zg?K znK^^^S%#>0ilnG$NBu|?Ee}&ugzA``gFN_29OQupt}#>(HE=Bhej8O6TRsX|4re`@ z47{Zt#d1-@wz-_KKR!<8!WsJw;4QK3wQ#2h+;Syq;ibu1_#0ro(Um|n!$vAl3!i{J zaKV39Mj5A@PleyiLUsFdjPztoimgJ`Pi-Bp0X-$^l*=plWN01EmWeo8hvR|G*g72i ziYPQk>+lw^iPnLdhRacFC?{{|;a(YI9NLo^M<-gD--#HXBi}G=PoH5L`DmiJ{{2G_ ze;47ge?a@GS#3s8x~yI+63UQOw+M7LgkJ|XV^+t@D2}WiKn={4)xRPP7VXIDE)gSh zR(~#IWnYN44oyj)=`KQhQ=GoNiGUc5RbT7|^g-M5o#wfSf>WEi5}5>wz)~>h0Ex^) z=de9=9HJFd;b?ot6EE|1ksj4>(8V8enQ{!0sxwJ(X4Mrv;GqN z2ue2VgFe};e+-B=y*PJ!EL#{dn!qu!-(q+q`?A|>MVQ$|GI*s~*4=7yr1yHJ|Uvd{c!V?IBP{Njy9m0da$_^n99YU_H zLs(BSQu~nAi75Gq;zAUWlt^TWOoYtO(uK?eR(2uiMlUOf-HSEYR7IZ*DpIslD@Or8 zcup$)AXdQB(Z2$`&>~DN*_!PD)*J54j@^p(Y1=rbVt>NSoQ>CQ#LPalp+#bp^Jx8+ zCIk*%mdfn%49qSWirMKD7%3lt(l@e|!3lf1WsHnhK3Wd2jGR~>`o`3%_sTI+BaTr< zAJ8ayd)0dg$f2s<_hqCRh&66{V*IcMSYH-3Brq5B8Hvh_%33XBjMHP^hI&)W>mr0x zzUU zCo6X5XJ}5*0@!Q(sPue4K^00V)7OCn-$5gl%{Bz3t1J%^A8K-JmE~??gv!Da#xUef zGZ6U}^K=%^V&ZA9Gs)t)NCY~I=S)g4F&%IePmbi5sd!@8|3Pxe;)(6~6yic}c1=D4 zx^yb|CB>JmE(Is6_j<{=Je$j1)JobC6t%zo1`)iae6;9Ha$-vp$Zq7u{`E0ZEO4esoi(NCR63m#&1jkTNY;*qBLZx4 zhz!dNZ%3!X()|Yh<14@iA(3V6m`9y7d$ge8OF;59kaFr7*r+;(lKj$4S~rDk{5e=Uplk;EvQHu zSXXicib3sv66^GX+FK;!@*LURQEaqF)D|AC-xA?vOk4Rg_y6SwF}AW#cTBNugN zY(o9hWfX_{Cjo0$f3mjGQ4Duv+zB*7Du{jj0Wy}-UA~0TW4es(1U^H?eu*GxtUQOS zWDZx!ak2H3M6t6ZTR915<5Ep{EavE2$JB1`!7ySZ36kvj+?);uCT{1AS2>s-qFjMm=CY7l;@bMlVDwc^Q@+)Uw}z9zIFN$R0!MjwNVP zsF;dli)hWo<;?rLP=C6-{{{Gr-2*K_LncS7Lf@`rY*jjB6z+EOVg`+M@}1IL1*&w? z%oDLQv~gdPtR2$OiI|Mie1?RDQq{_o`P84^6KhnHw#P=uxqa;ZPavY<6mbg>=|sGb z@Ix3&yG+t%EGt_w7|P14Af3%fR?f2-h?+6K(RwZ$M`E_T@)Sua4MP-uQS3^rw74I` zYGAz7+-rn)=3V3drhAF|TDO164!8N_U`(H^MPk_3Lxc4XP!09|79GOtc!#2)u(Q#P zt;Tyex(`8f2YUI#(QOA!?cm|*8ZZtbx=%qr3-03~%TTZTJ?IASP&7vpwjOC_fnV0U z*kFN9??%NN>g@#WaOfr@Ps5=*`kzCmXO)Hc`LWj&z~0sS*vlH~{QxwLpdX5c!f0RZ zo_`&lZZ&LjICPW1lhSQMc^2-C$LGR7)cX$T2BG_*Xeewi%4s-sSEC&`94`u=f+lS^ zbe|8C?qB=k@f$H8I-HC@M|lq?-Qm*RFbo}2dPFyz@>qoZ(GV&(z3X5bL%l~zr%x^x z=c8=Pv44_j)_5xs}jedu)j+4 zLd;p86XPGT)%hbJN=+Abn+khk--n0#?rz%hjCH_Q8;(~7cj5olq1A)ieAqtN)+bn$ z^;p;h7h|ImTxvZXZ~JI86{+l5wb=dHPOTV6Ry*1dgFG&H+J6fVHXYH|=X2F}&tVyYZQf{^n4F4;#>`h%J}?in>vJ!S&cG}x)Ng>*1~DElclpfnJSA?& z8=pBVLqT0VRTW@cH3xza-KHS>#;r{2{PnYWH{#Brwb$bOXfbEAsSQzLk~>4c(*;4a2;$SmmnyYgC45 zrJ-{_snU!~@PS=jSwVb|N4@<6;M4PY6}F$sXD6^yp5@?EMY=S9pOMGiX?e6Ic&q}C zW>F07s|6Fos5YnxCllyYMwWs4_<#RQUjQn>eVla{M1h zjw{ggpKZsEic9XJ(}~l?sAhZ~p#4hVV^?ARugd1k8W3 zr>L?1Bd`vfR*B=Z%2@D{6Le2st=k;!jg(HwF=ofXQSW?zGSzKi!e}9A9piJHw*|7x z)93EW9`B7T0&!$bztQo$-u`pir;Y@t!jca(uCk;9dW&Vp^{>>dtK=i+NY(8mXz{56%Hw*BxMu} zT_*a#{h|+{?ZMxkMDmhE=5}Ly4DIEiQxo~cG?()m15)opr{*?gj`I>ZUU9O_vCEd@ zZbY!=IA8H^zXtTN|3ENhnU9S83fV%IZ?qLwL}nRnzsxeq3Ol0yq$HzJo~2W=Iol%= z!p;JTr8u+4$IimGk>za2=~zR+F^*Y6!+eax9iBBs%mYcqdOJxZbi5UgU7o%y_pZ@d zktO}H*H4kG_~7!(!pugU=%T_>tkO$Ihie+jyBU(A(4FH+e@Xw%)`xL|f9mtg# z#72q@|MXR`3xw8;*(A9>og`OelB6FakW@*|vPfd9f`0&c>?nk0QqsR*uo*?`M_`JQ z9sx3~l75j^wA(=~l{BjW`b`1VKf^I1u`v46@vfc2RZzh_KAWlJ%xVbjT z9w&OI)jR;CMIpHf`I^{j@@(?m2y&}JFzA+zQ#&0ciG35nq!Gr7In6$kAhyd2Oh4(Lk zjrqVklaY0Sz-nY}C|0#>$!2&ds0Qa`;!!#*9;bpT(UgM~b#=15k}c@xSlqQplRciA zly`tkF~oi#ZHD+b5TdBt=9>NB1ESN4qzca!4js&@k3q@pS z8J`AhY^U5{Njnsv4+Jeaw+{v0!g9qi(OE zRIGKoUZub)902_M~fb*mo zCD}oTO`UDuZ-7iI$%3?!dB&8*u z2=drNZ1|KR2$Ps;VCVZ&j5WmSgs0DIj#h{9$&7Qb@Ke^Ww_l2b2)>yI_0Fe2Dkllq zqqD@ANOfdH68n`HOKYRqc_ZO? z8$!hT77!?dlCJD?Xt^ypf4qh>X`eq{1aegdUbYYyTgY?_1Y&L2h2uokQe5X~XQH2? z2ec%bT=5#giP~4Zc7a?aN}9=64aV7MFy2C4jtx+qm)e!B3A8rJrnOtZqhmKWgOpop z1{;8M3VRjdtQw;GDANl27j9_m!k!3nB`m2vU-efHlc4{m0i7(9gnHg3oHfOlfJmF- z-_xe}3mWoSmOv9J?w}M+3ZkUAt}~R*Mvd{wGNv!j9F<7gKn9%3gJ@O zK8>tD8=;hK`(U+wA+~qLVD)Wu6x93CU{$OIzCb+(+b(p29S%B3h+I630Pg!PGqcaJ zjvc6_qOrpy)u-OhT;02P?2r(ONMdwxD$=0!fLx@3wE#}z3IvEbRtZv|;0dgq3?Z$Y=|pXUGu1a&V!dWAmuN{Z}L{F7ocaM*=XLiQ4N zOBdOKF|vRf%ltI9$^s7NrvWc&LM)C=l(?FB`qsZ?gm(VwUq;e1{{N{*%}f_|A`n{lYSV8v`N!- z=486|q$9v)N}A5Qill4dAX^YiC9%Jt^-PGNw(d%ZyR{{s4uq{GhZ1;Nc`VUNNi6Hs zbZ1`dKAhiU-U)l#OEuP-McVkXWHD)L&k-dU+ih(Vuqul&x`dt+P&U`uNjPf)D}b;h zP>_)PN}@ypMZTy-@_E3<-aDLKj==a8^?ioT2FD?)u)!RaUU+9wY^B(z7h_>*{OW-Yg5*_)XDhr6vjNi ztWPqw*!bzds!~wH9A)FgN*LOgSO$rGPv+j1`rEX#VlAQuEgM8C_IJ)76FF^Wxpxna0$K#6u{YZbP_iJwqkM8%wq$_`O z==7|zkbJXncJ?*ATM=)l_aa!}X4Jc(XejI@(CvHu@N_{8hlfLV99kMm_jc$r2T(^E zL%rir=D)x@6b*&NLDPk@Ivm}=FldO!jW{!WI9?QfJkDPahi(Pv4&YsabJ#=C?>J1j ziaRh&x-X$;6=x_&bi*l+3vpi9c|V~zeTqL}#ZN;m=33_`K$` z;#loxg}Y15fg}g>iS2uH&6mReI23*=3x|YCU#i{y1ioIX?8o7#3FA9@f@fgpxd%s$ zXvcVuG4s_GPj|!4>G)|beTN{vLa?2(&6B5Wucc9|x^yt&*)#ZzI5zt!9h(h)F!(qf zi`Bbw(G$^8#$pU!I=;mo7Y>V_fUhg?X$+F4gRtrl)2c2a#_Dd+gXMxzr^Xejya61bg7}Mb_*oH4nt@ zM|5vwUJlQyJJ%CCXD)99l5^>eT$v-zIcyaXalRLf@U;>3#1LqY-Z>uuswY;OZl})( zkW6CcJQeu_l8u)H{km9lKOSnOCf`^cW~p(%J-M zGOc2fRIF0)wnMAWn;a)xu|#WJyOOJc8pC?#h*flTI1kWh3Sn!8@%~Sz+lD+?&lBU?J2YeHKB#%kF(Soi zT|Eb|sJ9OvM(lg|Xl;V_$FcagS5TlI5|{0^lTUn4Lh;SY10X)|@B|{B=pc67w@3Hv zEiR2z=9fm6xFVjs$dcUJUJr}`jrwLJ+l?loMq1KudR{Cwm!PSx{A;ggfKtR< z6?2WUBFMOxW!wZA^GU}1gp7-?S+YZY?}Fr9NC2^sfQVCy{PlXiAa;;?08%6RL`!s+ z^*&+5uRwfQC*pS_O$g`dgMj^z1)3|%6OF%FHqh&lI*NGEV3*|sy$|H1navNMN@+~C zq)~x1#C^yAXZYt6|MN2NFNV7FAS|-cBeKy4x%#07XtwOHre^>Oemk@DJy7s;QtL~zEPeoR39$WG@^+zUGg@{b#JfdpQJ4ahsBYy0*h64!}5{N zL`ym(Tta&Z`*f+AlhoK=STy2Jw#0?zS>K8Fppj^rEHubR8vZ!a?}@|6uBJ?1ZOwF& zIB~x>%2U!$Ao_{Jr$3eGCl8B0na=|dtCGa3w2DOvr3Yga+Z%`9`nt<5ukg=Z;4bs{ z%RGyW@>0!$F+A>4&jKrEPI>87RzD~fESlqSFR~)byz~7Fy;pmzIM00Myuef8yUM?? zvZTbbaG|6qDWAW{Gk=kPQF*!F=Uy<6BhD}PFDS2El=OjaVP%wnPx6fPZuW&CiY*|{cpq!Pn@T&QX+>8C5B&MXitjs;X)X$MQqlOzP_^fo5^F50z zkf^6rmVzW);93J5HfbTqyztmHLDr;A3N?_*5KF^|zaYb0BsB^riT-FvVk*EmC6b9c7MNgFLCF&QVFh%%(263w42UsinDG)g@wN>q}i)1VAXqX%1nBc(a+h29eX<>d=) zq9w6u$?~BTcLYo<)@l>`jJb2fcZ( z@GM9ZWuC`g6(l`j)22-Up0bKXSEXU)F0r?vlGOswrD*cgkWLhUF7{FQ@J>QT(Qc1V?@4`wSJ*AQ^H5@0y=$RrxN_Yi_pP#2`e_lK) zCA@g5jQAeXNf)l2E5j$AmOi{~kqoDE3CE7jPT^m1jSRm~f|T&}9G*%39uBWZ{46ai zC4Rv-CF4x`Yv%B4Go;^tnDBxnG9r_uq`#iSGx4WiL!sva2~y%0aKwuld~RFB=01=x!=daIUcTmSi&Bkd+UgjV{qg~JVaNDx9@IA$99yKj%;v% z>9{_orMnY!-9M51SZ^tGR9=tb?O{5qpW;#Sm4(OLHaa@$_Ut=E%_sVQ;%$3G@}>GJ zo+0QbK@YjxB|X*O!_m_X6;;@erHAUXjsCLm=-U#~Nd4XfdJTJr^l<%7$tUIiKG5Yc zT_$}H{%O#;n2vNU9+f{&Sm=T1J^|fwrW>lfCSjeujp?|Wq?NA}blt6S4*UApa{%fo&yJ=~6@P4_|2xtNaliziLGFM=+g=}sGh?hDWr41;b; zwx$&ggU$!KVy5HvCM6#?S83X0O`A54;Ry`iMLS6NhZ)|@@M?x1!4N3?F^0<+PGa~r z`UwiZh2a#2J7H*quVQ!_!w1kW5`GQCYXB!{+U)DEhK_;%{3;2f3|$O=vsmIUWB4`< zh3MBXJeJ`DS4ezarKX*Na96qX-#cHzNo5kw^hvnwG6~B8iGK5?(*JdaH+!Z3K|{jJ z82)9R^dFonA>GnT@|?o(SEbT_s6;}O;eB(Ye-y*(+|vJav4nFNK68omH(e~@nX@JQ z{VWMjWH|mJ>Gz;Pq4Xb_DdCw#5>CHRLhtz!zCJ_d^Ot}`U&Qb~&y)V+7>+BH{`*id zNG~S=5`ERz#BX>`n*ew!{Lf$X83OmNGSXxhB1cpT?XM_W=MAglmAJEk1~9S;R6is zVYq?e9SrFtGsR!SFv#$FhD#Y<#jt|mJcbuDJfGp&49{SA62oH|<}i$7JVEL1XBcBR z!0=^;&oX?H;iC*6V)y_8D6KUNs+D&3-k1`WE<7xSDUh!hSVB!gnenT+L_y#eOya ztz>^y6&!dT#Y_AKpl^DjDn04d;_O%R_xpe+dNp4kRP^V{2)A*#nva*E97KM;DZ}Y> zF8S4bx`_R1{`^&@SMyc8{KWm|m?%%wl>q|DCV+Es^wRD*v_8{|funeE2ve zABUe0GLlcLlJv)^`0V!pP2p<3xeIP0SI@WMu=*czh9f;|c(ub%Vb*XBKLOuR)4ZC0 zD!yiUbz@_o-d|gv_?7#HKyZ1}GVwe2_|^GfpfRX^)qWNI7I{OR#orpJ57a0>sB7z5 z8vHio((2Z_8vhMVt;{6Q&>URtU%EONNMIUknwACp%`Nx=`<7r`0>3Pf9*<;NgVl{e ze_bntY+2?Hw6rv}FngI?3!<(FD4fb8_&3_fYN{J+0`XtN=Rp;MZf#gen2yYXYprW&t`GQInromyDo4e$xv8n% zUtM3{RHJD}<2j@7-020b zG|CU28olWD#pCw}1FM4U0r2}5c@|S=Kk63jT6w{* z)V;`^@M^`(XF#Ejmi!Ei7css|c~be=<#Xl8D6=@`0Qhl}ox+O{;MW>#scXEBL!J5k zCiC0MdYgogU9FE(lNj}#EO~X)@9ve%) zKd{_i+d?%+JWl!caC=|Du{NNbt@%ZA%VkXYe+mGG*eG-;Mn764hADxz9_dq9KgRv* z!HdL1mn)uZ{HGU1tYP@Cu_?hd{D;m-eD*qiK<&BhAK>o5QA?0~aa(*u@I?I23Z7Qn z9uJ)zJ~(0JSqLPygC~U#j$C=7@{J20%vw2?eMTg^&w8u^-$M|8^WbN%=)ULhqcYoL zNMrUvbn;ukge%{^_{Hi{+qY5i1`qXH%0F`a})Ftcnsez69)P~La)KHH;bq$WqL>D92XLeKo z7-rNE;I3i;{y^u1jc7-K@Zt1S6bG#6pjS89T>)PB28;-1fpnndA|qNk;4@#^E4}AE z4lT-48Um9%J0i|mCGX8#`%eS*W`^)1uW>qn7Rohh9`7QS_}x*%ylc5gUgQIUu7VGz zecH@Wm+85!wpV16zAbuuy-E((!iNuhq_^J!w(jtkABQI4E=VCm_`t_{dw|g9lQ{3) zQ3a<6(6@$OG@?;b8EA3*XqM&{KUeFu{KDK>p!P)rIJbj?MIAk%I{iv$v4fNaKw1KD zNsudnCc!?OvPBsE{xv|q1U(XLmSCd<>j8{jQ5-^z(GJ4w@~j^bDSHuzlD>ztQyXS! zWswv!!C88M=v^~izwD!zIah>o6BEk@YWcYwZd$^m^3enS-3 zNhgb=77_OOrVgyA3@$`MBRL_QPU^WdI_@+avD#Sp8hm}m%s&15I}E*KJJ@XSX6+OS zAT>(Vn&Rr;(9Qg#-H+k>I&p3P+MQIymYe&NsjG8=WDj%}(J;(^8|wU{G_YPz-&7o8 zTzimumzK%BBdIy*Ey=?NX*g#pDx?w7jEg)2!Meea+r-_SxPx_nEzWOkGNNl3CaUbb^&GB?G}-0Y=0Q_jQBS*`v2aJktVTsGL~HgS?(WMwn5@*1+zgRIbRl%&r} zHVl4+sjM|KoI|DRXSi$llO6nUP{-WQjDP#5prm_R4)YF^LZm_B~vY z>DU;zZ!*7ChWRn>@V1l++Kb4j97rUZ3Rze<=}2ZwHN0#ij_+;4@juF5H>BPJsW<#_ zZXz}MjMEI~!+cQf&>Vza(%DV+X_%2b@|t1#l){JzI_1f`8nc} zBa7KU38(@1rlZQDgv7Bs&L5p~v+CpOgoN@8?hy2_!!LvmS2^NX+ixS%Nn1^Huuz`k z?bsi@pj()D_+o8UQTXN@ZPj!m+POjGbi5I{0=4-E8_8$hA&{ovFgVue6%H~3@eAAX zTq_QQ4~ze1!BG$!5!?nfAIaQ7Z6R*2rZB;uSSkJ(r%?IgX=C_9h7U5N+pp+(h2cJi zN7F9J*}zNBnaebqV^s(1ni^d+{Gyr7GFNM;rY6wZS{tgbU#-SHF-Wft23(jhHnptQ>Ka#6*Vip`(Rn}Dvg%;9#%J6l2D6;jR#)9JJ629H2)(?i zHAvGLSAA2{^`T~0ZFOBeW(9Sa)?geMti!ZMGQz~I6#_yM%uH*fto2Q;5H!>nSk(+v zV3|$O=IWMKj$66Fr&YUJn`*8P1YKfY=xVB|3AMC{l%)J1hZsRj55>gE6>Ms9Vd8dO zz*XDS;#wN2twm5WDP*7K!!FDz19dCFrzLXzWrK((X=<=N1>BU9FtFa-`a)il++Fu%o=le1CR>Z%d>SBUERmO%Bg)h;og z4PhqP+}zY63bMMjJ}It{67nYU>q7oR0T=jLB5CTRqEy#Zl}LTv(w6F$)vmh6x?mm3 z{oB%NxYVj$3m5vF3MN#dlu?RxwRJVNSVYhq2(-9rFwu8qqQC@uS?luZ>ro!kL~O>s zQ2MyeCxfckxi~|34~O3mnC`qqGjkk)4n5s@kv5(z^df$B*2t9fD`?=4hdT7rv=J%c zxuTKRv@--1L~uOC9R5Ov_%5D!W{OYi+4P(xK??si4j03AIW?A){C_=%&(9El;4ty` z9VR}eP2$OPo*@U9($K@@ivdvj^9;pI$K{-st{y3^Vmc~s@hE6-!~l;772UjW_U*7GqMLwH za^Y4idbnJZbQA{<(ai!~KGTtXh$judWuO}v2EW@tx0mVIUec!fd(iD;I<}j%bbkfi z9;RdaNlTYaIzAxtI}|_qWe+7^CVmaDH`>>l$xsKxlziH!s7KhMoBaboOa`Z24+wRi zQq6D?hff8h_(ua$ynWd+UJQ`pJpqV0{IuTzlJhqFBfixPO8_a}S?qTKQoPTQ7{#L> z4hL%DHb9E^eTJ6;o`mq3fY{2MMxO?gzZa1FlL4_tJ?#*5O8$2MU4VZAJQc7S5NlY| zXdmD-z;eJd0E+>!J~8|EQ1R*TKL7|;r~DWYL8sgfi070b{*hc>KnlMIkiw?{;yH!Z zJScpRgroZz_A%^X*v)V=!;K6#Fr*nU_>Asi*v4=b!)Aud8CEe|%&>x?!LXQN5yJw8 z`3zkQ^BCqb%wY&1Q9bG+7w^)Z;AaG6dpYY(samE%<@prM}D<__%(_Te*uR-%js27 zWIU^xzw~L^#c+u9P+#dGJ0QR6UruMg>W{8wzv^Gsffj#>XO+WG`#09`21oc$5z`ue zfg`-!5uf%$t@QLOlUDz&4t}(MWeq>h5$@cdp%ox2{TmLyT8bCjCe zG3g2>Xbl9h8^R+eKaEXkWa<}7Ukc|DG*4BC_3OoW%oXCWA;#lRHSQ z0jw*FHDP}phTUpENTB7YUg06pvQRS?xgpy!%p2H=y&!+h^6ULH5EX&VSOE{#63&*z z#^k1vl*Q?94lS*(YhBKf#KeTPp!rwSO0FCzlw60MGz`4e9!_%B;1^Q?CRH0-R-9B5 zZwXO$R35GiVXurMS~Q^fYnwyC8WoV(wqb--)ag{|Xuqb&m3$7jUsF_g;dDvO`!&hD zShsC7=e`ZPWi1zVO>^PJL;E&e)`}vq$$x!R(eM;d96ZWT%__azoS_tlw{P(m_7cs%J2j`C1Dg1}q7nuqwVo`(wB1nl-A8f#XF5xklxf2Yn`y@b%hvcOf zBuD(vKE}d|$H^kL_2B1{Zd^B$KhWijstu;vd;lR*7E1B-&SotHY5e;u7V1_pn z=nZcI$idqiZo_{P7|0#~Lc%!!Kze(e{_Q0<;u1t|utR|1GDNOGyltdhCfH+)661~u)r}WnBH_V6nD4Nub6cfdP#c83I!X81`O{0I|!oJf17)9ZJ zUj4Q%!M#xK!qd_+!)Qi0Jc=kiOsu>5Gn#zW4~~jU%MTjW$Q5pT$Q=Uv-4^%a4#A_t+ef z{HuX&p!w^5rX-0IR5QMtt?S7DFkvVg?*|A~Fv3Y?-cuxU|m zn17N#f{3dE!;iOtxfUAh?(HBK^;F)-W8DB{kw5g1Z|b44ng1x$=Y8TG`53j{_~BQd z`4P(&B}!k`hh9^-ypaxyW6a#%dXmTdY;dHf5c`VPE51@}hoB1Z1WAKC!IheqQ5 z9b_wfXhd*g_)wPK(FifteuLK3_4b<(f?H?$^{sQVBA1TTcZauQgDBdAnBJPZx&Yjd zV+S^F%zUcl&RX${yZe0R2SPsgE@K58-soMMD4NU|nnun2too4UR@uuh0Bk zB!ZtS^F~-%2U%J8&0E$NR0WmkxBM9yk-2HRX+->4T)qXwx)EOU^{$b)AdOT&ImG2> z^G4`f6WJ6Qq&cj6oqlL{+rcq<=NZtNzJ-2IxB#xiO=pJrO60~d`g3mcJ306{-?1nO zlG+GA@rgIwi{4^anR!46+|jf8tFb>KY}ZJ4ZEpz*WZj(Xu9BQ}b4GQQ9JOxF=&q8Z z*UcHzRWjDw+p!6BIe5L%j*SFNp`>maV%8dZV^6K#dLZXxxBi_DG8fhwTw3g9+`A-8 zDfS|qkWb&*I;M8}F3RLeT(7fmtf4>UHLuKtxW^^M{U=Z^uUVcCv2mr_A)Dm7Nk$vKQ~rNG`q%Vv5Uw?qO+gMrtLV9`B$L!)xbW37gzn+ z-f8e#_XP`kxDM%e_Slb=6kEDAHNMb0Xzd9HDLjSy2b+z^$<#!wa;s|izP`1@@J8;S z5s}fcJ9PZu*~#t={bA%NV1w8_y*#IO=A03s_Xi)fh6|gJCn;#uw^5n+;N2MVVEk}d zWYT9yFm#7LxsBBCjqmb?59Nm5O*SGspotI+I?WKIc0G$3%-Vt7P$^?i=qrPhls;&e zAL-&(RSd{?1IhOn>e}_Ka!855CBYq#N{mJ1KDO-kl@2?;msHOU$nXC={aE!ahAnEm zBrHd5=i_t-4VGj+6I;(}nB%T=iyIMf6;fG`S^2aP`9UA@?Th@jA7I^RaSxYA)3?qY zA?iCW&_Q+ZWUU+Rew3Eb5B1GL9dCw_$e|iqS$zwgJ7^M>J$tQ@)fXRdN9N|x-LU->FhDjqC%s6|GN=+XgxR#9&gomS=Kw=$QHum5;<8_F|navAUEGfOADo!Mm$do zDX96y(VFtIsqY4-qEw7XNJhZ0eTM2gVXF_iAEiSuICvDw8$8V&*+QdJ@7i4(02CS2 zgu^nA(&h=Sr$k-Jvz(Nn-{F1+@0kdt&*!Y~H{iF*Pvwsj0@NfY#>?;*3;&s|T189K zb=Ze(z==Y+kN6F2HCi^9lgk8hH}o4WwfE~fbJ^Lh>##w6<}z`)isr>3<(9_kdM6*T zHk9N;YazjaKRE4T;h^Z2hYTa#z940Qo_p}7+t(Z5aB=WVPVWSL;vWq&@LYm79sgnu zKNI2U_&0MnFGp}{#8EzN98Oa}JSpMp4->xeFyWgy{Bksu>GnNyc^$V1;pz5Gn^BkO z!LkB9sq%67P6VdoU&ZGhcpoSw{$>uReUEhUn`z+z&sXuL)9*$Oe-WJ1$-j{mpGp6l z4--B?q>hYd_>NnBze)Bd9<{GGC;444x-*S#|EK33CQIxmmL&HR>k-z+bZn1km{Rvq z?*v^B(~(_@N6}f*eG~zEn2zjIJc`be?%N0$U^-Su+H}Vuk4iqa*R*sqK)0Fs4Mj(L zU>k-(*ABWirXxER&!w!FxpLq3Y#<*5T{rI=lRb+^<@eIm{b1Vn+{^pCY~N|~L;Ics zOhHwt_9 zfO`SY0{kl=);Xv3Gkzz-%?$4cB)T^ChuB}ieh>Ry?4QVf+P9{3-T|ceJ?y9N{m8$b z{T=MDVt*z33)p`q`?0<)_n>~Cg&fc?enKcD@%>>tJc0VtLD z{RNQtR|1k=E&?RI7XspMBJC@l1OFL-SR`;h?7nIu+q+obWjNH!^(@)2n{)Hyqx~;q)slV*eI&^fcflzZw_B z*suEOYY~saRlnZL{3$LyFW{x{^&~i+yO~~%Bj_hkC|vdHKY*L|$5lW6pNK>LVwTU% z@=LwHi~JFoE>8Fm0<&Z z8II4kG_9sD-uQ$s=NT$bMFw#e*M^l_+#&(WvWAkV3(C_7(vM>it7}j~782pK8i%Az zpqpC!H8@p^`Ju8N3qe|?`pZXM0{#q? z&k5kvx%Gg6^Lzk?DWb#IT;w?X`G9=xPh4nE=u!SLaMLUJ0S@yghH^v>Mkd5+Nf!F$weDpe0U?s`umg`NU=-P|KdQ&$(F&4g3 z-cRn>->v1MtaQ&V!yMB~V|w^{=K+Te^m!yFd0hm1=V4eVyhRKP2x8qkx!*+Vq4>b) zJ1*Ly{<=GSbDnndRp zPoy!YbmrbQ6TOl7xjuZ&T4vr{P#Ueuiv1Gt#PJfr8XOCRAaYNmx2)!!OQSR1VL61( zu2M1tZ=`R%h_fde$iiYRB|mt%H>($4d=(8=8Rln-Ck&@2cpSEZjQDn=<^`WQ3oF?3 z^9E<(OGZJ13HV1FM*Sxk!>_Yldb|G2+3oEd* zW|-5Zpk@g+i0HIL;`b0J{NEh-Y9dUQzgo{|Q7- zbiDZfEwMks`$zB9&TKY9A5nbkj+)#rg1%0j4XM^}Hp##v7K|dk&geU+g ze?;MHi8D$C=M)y4Q!uR=w@|2ur+LJ}_K0i(!~IT5xQnSTl`ti|nZvIKOt-E&z~K*N z2;ayY*8rwlcXd&xg$HW`81HALq)+P%^iVOS3$NnvSqM+JF1(S$v38R-eh-Id(jTph z&_na(boay3x(husBuJ6JpTo~bcslv9rXik8>&CeU55N9a3JwQ&U60E-?fPUr=mwaM z%R4RIouJF%bgA6Mqt+cQ>%osApn~bB{Key-!`h4XHr~BVM|L0{MVDs1bpmLL@OwM- zkX_j5E$h~^Kv%$Yq8byS;%lK>2D*HvBRdg~qO+`{()TjOOh@)&qqFe)y+uB@n`F8i zjq*)v5H99N_9GsZ?!46dNa?pyH#0rkQwrZHU@`-AeN0DoB_73><@^YChc&Hf69CZ$ zOxq1RruEYY0LkA8h_&o#H?W_+SAi`~n+Aw+*|Y(qL3A$wQaoBuAb&gHae&tVVhlG; zWB*IYEBU_-Nc42xo#06fY5hZ_4`B)3#gN8;U?JA?K=R-Ay~cY;m)4I|{rrODfj`k6 zki2+R`$6k5yB24fDq=)ux$nWC#%h^w1^icUz zICL(ao7q1gz1kh@cd`Gc>~Cg2-QUJZ3CtLWKhNQ>0+p4X+*ZHKLBGNg?pUAUOJr;d z6g1P8R|474{2j2rG1Ra$adux^9Oai2Pro>_PuE#B;Jm(=adRAeSrBZgr`w+X+t&)D zfYwz2iLp%It$EN=CeO)L3w2G>f9am2!kN=~Le2AOxxSE?Qm30wSD?aaF1&cK7ozR4 z7PP=7{|#_Mq}G9zpXx2WJPjT8e7Z^uu&}NR8PGIo6&GsSUnsdFJa4b~T*tEaW3k`* zP!_EZe@K!*Iqwa^bsyqE8z`P4G~iAi93;Tu=H~;~|5$#{O{g z^R{y+il$ZZJbhome{Fv5xNvR^X)?TfA%phKF=!-w$0pwx&a54Q+QZ=prz}{W;PI!yqQv=r#8+o{ zAjwVVrp7!jI583P&)u|rJa|-L&)_Jr<87I(S=Kkyd>t2#{y{(e zxPqh`Z=cWy&hhR+{zQ?5HXD)3zDU{5c&^uc5|bbOj_pD*a^6dtYTpS24jXybet8JL zq#LY&BMyh&aT@|q{-tK19}32HG$xl)Ze*(|HCqdVm5FRUHF&XFuTb%`ZSfDImZzL* z@zv}t>-d-6eky6}6kk@uX5Z9?KD}c+{Juy-_uvWM-Y4m1?ZNS0y4@*MP@bn-`_C?@$!oskrn$ELlA?Zj z6;uVJ!Ua#w5>x>g-DH+jkqxtBF(IPIJUInFs9X3pigV+`RJ}>R0P1w85xtA};KrCP zImZ{0n%lc+l!=c;I!;1kg*~LXoNO5<+ZGtC0ew7< zYl=?Kr5qk~cN2jS2NQD-LP;s~rEF^GSt@Q$n$Y0vWc`yyI(Q79HhXsraoh*7so8` z5N!joItAWG@W!zoHQ^CDBO?z9(t^|5IHA}jnBkYC%{^}2vorkfxLYsXX+*>{h|cm} zRMsE*im`TQ7lg6Y3K31U$MW8$Tv;cO%e@BQ;D%DdItu+nCsh#<2ek`7dyRXdSl?Wq z5(`+-^N|otd;h~ZfQX1SAP*ai5k8Ou@ph%eSM43v!RYEJ`UTowB6j$59MpfF*hFXl z=V@F(Sec`{&e}Ht?=}D8&H6k2fb3!%#uV)#z8f&6;^wp0x4A$dL@vY94Hj%hVjYu? zLZ3qGbW`_uXYLGr1*iD2+=-L(f)GUI-l#vTZ02X7t+WC-kM2cF;Rj}34-sULbIT-UEmwV?0V$OMOuL z1A_L+Z3TepxH!(#Zp(#VeMW(Tk(H22>L%Rlge0w?0V7|Y{#?DL&ssKMTtW?nX704$)^?Q47CHtW#c^Y~>d|CUIR?HoPqaL9pDqds7`tB0BsBP6o zY4Wo^RUV(BJoK$AMhMB>Nh6Gay)rswglG`hC}k%?TNSlrfYn~{W5Gr~pvy1~7a$JO z8`w=M%LU8@L=jh_K&eo1n0#K2H@r<$+2B#$$gN~@gE$a>E1`U5k++xTW?GrKjY80L zODn@deIj4!>Mz#(Gvy~b%>3X3w4PuMB0D%MoUsf! za+VL;qda^U<`%Wakj)PoGh(dj4}E-cg%LT{h`6EIKi8JdtQrw|&oGZiD<8s#Kti>o zOMC!=t(S7N5hxzB9Bl-O$1F!1f#NaC(MI6Yo?=-vre65k;3*hF_X)Frkzw0Jt>v3L zki}z#ommgvix0vk(|wThMnH-Iy}bvi;`0}DC(24i&rBNH?lpIb_AF^yvb|H37=Q$S z49YSL;UjDMgX_H!h%QP5q6-Uy=)%Gvy09?a8@UoHU<30YH@N#ST%-l@nS;=R&&>Ds zdPo;AtlyAfrO6#Nz(rJ#cEnBuD10qO?Ow7HiT>N(U%VuCn!dy}r<(?kMgz?sapTJ< zsBdfZj-(qGdZBGq_X1Vh>3a86#TWctu_} zedv*#+F5%M^!T6WCC1LS{+`EQyeEtCSMsy@>rvKJJ;=x^3}w={OVsX^3L!g90~SS{ zrU8qhPSb!zQKu;?ghBg{=2*xthIS&)yy2^cc1i2t`H#4j6-;Pw<`^ITKNe7aPfqqL zzILken$MaqV9(NPeqpIZ=`(+myX^}iw%hqx{dL>L*u-??Ng|7(u1-Tas#sSqU_&iz7U)m zIn@a7%Em`{AH`-8O$0xZF75=D9X^b><22w0kzAG$@uH0s7ouW3X`MIhk^Q^SM$#e@ z?S;^H0rZWVcF8cl5QMuto3m=oCI71w_wC|xVoG;21{#IWV;Ud`puYm@^{#dM6X!+H zEfnDEEJO@FZ&vO>&Ib^$ztnufXYNkKO752@zBi`+1Q$W~mzlk8^J(0%fc{cU%eQQz zIul(Z+k4cVvGT@XvjksY$xCFjr=V%a-ZOU4-!C=az(=V*j5=j%DV;%@{PXv9tIEu0 zedZ3g`Hb7d?bT>N)}S=SDlBa^<1;p~EReWgSZYZWXBO5vqS8v}4){%>aO~pg+&!+p3F=WL8 zK`r&kv*}u4y*&sbed|Y%TI!IR%9$h+dd31Wef2H0`6Q40<*Jle!N>(6nmE0kwnZ?y z-{3VdV2PBi2Xp~;0n+Hd4G;~PxCq>c+(jDmnw2o%GMp6DWz?aHmRm zM>dZqXKoLUL%9NhZ+$-+93@s;jHoDe)Jd{Yv;e4bkHS`e?=~k)iFkV45NZOd3EHQ! zZm;Q^f)QZplx#0aL0Y!UtG7>rWU+bp*G;xz5k>E~0ocJilJ=KqKe+xFW#%qXd1zFa zvZRJ7E7#;itNfMTFj+4v6h}@n}$%+B%?Lq=EX1!h1gvi~r9cY*|{?n}s0M7Nu@IRM(&F5$t1pOVYiaaXf zee8?=f$D}hWTS?ld@H!OCVPreGuFu3Zft*JBo1|%iU0=CFDfD3_2x4hdN2g;c86z8 z(QdxHaChPJqCN0Ng1ACHa?^O1VcwL3x_Q%hj52P@feqg@9(~wNIjEnra5Z&sJcJMC z;NPqqBmRW9X2ukJU!QNx{OG1fuy`H5NYigWfFg50P9}v5>1F?AL`rfljRcGKUK&|c zv@g+w)A%Qdri6m$wB1znzkB-@@TjV5|B1v9kb0s5rCM~Vu?^OdfFOw=oq-9Sk%Xq= z^Hxei2twr%lNmsT8cpVs!#KU%wp6@oo7VOgZ*7~~Dn?r%_<(31rd}Udt%kO@WlXQ7 zS1b7B{(gI}J#*&dgwTHf@4vrH)>(V6z4zMh_gY8hC8{E=Un-fGn4P0GD_T3f9_+Lf zS3~+i+g^+i|7)ky%#VY+(9RK3Q$`)v^1b?H>1YK?gKLHbNDY$4H3RMqItxk$Y`%v_ zrZm)GVldWWn3ttC%to3v^aU?V&6>@R3A8%GuM&QN@%ZdRNO~WW-j|LPI90u|qfgom zBk=CHELQoXb;n1+3zLQ!M-O`RZdH#W&fbBKAqo1San|b8$SzQWe5XnQD|r-~&uvdE z_pM@VU(^GkdNJoc%(W+BH=3Kt&;!BUXlv3|jsQ>v0d)|KPzSLJ>L3zO2eGjy%E2Xt z12MMn&tN1&{_hMja%Uq(2C2&TF-i%a88Zg4z>VsM}iG z6Ub9nUwA0-5#B$$?Fq7n8*qwhQ2WS@@6Zc@hCZlU&}sl$PN{PCRpABpsEFtVxNvB_ z0DV@HDytARLv&>wIv?!fM4fag>IPIz^ixJeigK5B24G{#0fSTW6_qh*THAV`v)cJ? z1u!gs^>$}!r$%*e#rldZ&nheWR&`1fqKzi?L{WtfH4oGTF&Z5>Mx|C2@YYUnprXa3 z^bCy1#KBD%u3~Mq-wjq!VXBgECt{IZeCyX*8A!}-y{TYS0yiyhLfuOj!$U0nU}-th z9ZP?$v=-1wPBXz^7$pTl;lTSz5~Y4ts_KnvL8JQF5mBe1FzVb=?97L*fR>V|(=s9I z+<a*M6Ll_q1i|VVa{7?^RIL>w)1xY0W0}DKx(U^PA8uO@(6Rh^4C`T0C+>AZ|mXk_(tXd zxM5zwtVVe-EYqj3{8PXOzMi@gb^0cBFgFIX#nFpkKq>1sX|dpsCCA)di+n;uFKgQv zEU?=(0saY#qH_LWKh=1w_GeTMJ;Y2v@|gb2!?41n2RmC) zsy5MCCYg|qpev_!suIkRRTV4cHl%Vni8joPilyU)C)jxmX&zI$nk9RLjd=B5lv8>= zmQHR?5O=O{QmSx}!?fBP#WhMhy`kU)_)r<9izY94?ORor7^ZS|N@iKr1-bA!vICRw zmuoDa|2kTlbLi>U>G11^3cso|8#uNkOvqK37UgFP |g!EiVi5*iarI=?_M9XGjw znR+(B?m+=!W?r?u+IeU{idB!2JS^ro7Unpf-r1*$9h#z?trK(&U?-wtW0%_rYK(1D zdfI`UjiUt9lc!iGFc7NxA_JHssnLUSb|hvL5}+E1Rg~$St^wL==cQM~lS*@7MFTGe zP#x+Ij~qRE+fMekT%RRubhMG({OsmZE%QA%qt5<(=}V~f*7$1DzSb)`HR;)#WXcPmaO>NExR#&X4tSE9yyy&sR4&+H z=p>=^mmC+LRe|cM#$BpJw%|M|vjSn~O%*Ojw_x_bQd=t&2b%*-5r*eekzLAa-);H( zY5(u04Tlj`ZrYFmCcS?;9R)Lwp2=y$V|w!gXB2IF3b6z7My3aZQ=VN0MPmiaKK5*M z)aw!F`Do=kRnGfSYtDh>Q%d{ST8lu?dJ?12dvGlBm_4HHEAEVjx zXsd(wRIx?W4nk}d{h$>vrMxY3k{v*hCjo%Hs>5T^s3{MM<{)g((nUj0DC0u}x|7HF z$DEXML38PN3U#tN^$=~d>%o1hP$w~v)XsjCsHqzLDnLDVl%>Ie4#fi}Fv zYDtFjpf1^9E(4)wH=v?P<;#>oZv^HFtdIF=SDx5WyaT74hr#XmkC<3yE_@$bbg7*> z#~<1P2BJ7P0MPWAmq3(Cb6N!k&dnkVA|NrRv zts3jMXlfCrrbDmcux$5R!(kt^HnLC_ZV(aHP!B5PTD1i5c6w=|As%S1U$SIHeASJihJd-D?0Txxw6Z=9)kCWS z(fVen!VEO5X}YO-#r4bMfw|@@Sk^EJicrgEgr=5HnHIdN=4xn~4aQbCoFBYm&FY(i zm)1A0#w*>>WouS9wwxct1NC5JW&P@4WOaPa>ckBfK+O_kP}+C`3mY4Q%j5B;mWwA( zzJ5h~d1A>0kU2fM9v;@;JlVx-Lw!^Ik`*hV00>HX8&@yBav}P7NUFpw_X74n97McE z-aW9f<(U$}#K$1_ptuj^p9_5&z7K^N*;o|omsY`tDQKa8{D9TZxDaFt4y;WG;U%|-b=Re3<3rr<`e*Wu*aqkp& zZjAed--Y=W4c>szNNO~~|9#@ld*v{L+>QQ=g+qj2ixn!(Z9};COU2^&;me;C%+H5# zZym$XA#Y@e@Pkru)(zp_X=(po1Mth=aEW&3ri-6@zql_$_s z8brr_p%86*xzMqn&5PfYucV&_`fV@j_}TB~(R=tM{Zh~$*{|u@4=ZEJ*N2{ZA-27w z>Dez2NB;!qD}JNt*-z)u`|$r3=(oSD>Dg}|i=OqSv=IEiqUqT-l`;Ig%DWnLO~2K2 z?9ct^m>+S_9TYnD>v?qZ^WS-r{yU&AdrgPSeqI?9zlXjQj?aPK7JB+u#?T8&`}aXt zD|GDtl`(Wa`F1{5-pj)>`g=_;+R^JqU=b4mALVK)(PGWfz(OcoAR_ zumZ6A+(6(`zz$?2@e2V-cL5;7{oovp9|0u(3xU@HhCw$6a30_%0Fhl2#|k_dkn#NW zZ1wgl)CM>ccoX0W2xltbEa0CM{49abenQ*t1ti^Wfz4vSOz_15PZj$j!H)*DzaIlK z{C^kxn*uKeyqNI{{?b_*?*(Lh_W)iF_ZtOX0yrJ`nSfUT;;37}9cOC$y8vmQ5cu3g zjW+>KhW!@+k=3CnAi@tde_WSq9U#kbJRrt`&@*QQ0%5>zK<4LqKom{rp8#PdM#TL? z%vehwh{CfM)_m0gsN-_B`RE{i}eq zzZb9^@H{}K`z*jYfcF*a_`fPJ4#@cD05W~|jnw(}Z-C6VRevw*e0%K$$I zc(h34zXT**FCghU0NGxe0bwTI0Lb)L10pMwUQd?O1mKeZkD#+U59N9Qup0Q+02cr* z0sIu;)qqUj96+XzV;Jqv0*nFv9*xWfd=f84uufoDU{D}{^7k(IpdQX%R6d&b@jDp-ntg~?x&t@+0(%5E>uBnA zp}SeP&Okk8czqI{lAi&0voG=qxKpl!*+*H0_=uZzbq)LyH|ykg@vZ1l=ro)kDY+Hs z=V_Y6-Rv7(CGIRQnj28gq&NFQoFfuPH>u2Ip%*mpGx(!>r&xRz6^eKl`Xid9f}4F9 z$^j*RW?$(^xDz+~823x~X5S(%={NfnpBLQhJIoOOW}oGo;FsZ9@>7=Pbe!wbgu0woo{4e0gjo*dv+&KFMH~x$V-|4|OdHmn)37_(N-Qi`xnH&F> zC%gg=ze$h(-+Sm&9-KE*+~KpobmQlG-09|aKih*xJ@{=Ne7=WYmc2W?2R-x^9``?a z{O|VQFMIOy8=mm?dE94s@H0K>z1mg8@PLD~Eh%c)!1QZt2 zWP+k7Q!2To(pY1sgQJUz6ar}$-_V$Kq?F&mB7>FeUym5!e2Kv#+tsD6H(!P@9Tu;{ zQH)0ouaXlhVuf4kp)7Y*BgNCMXjuiBw~L`sHc$TW^7@v=gEjL)vMZxs(*#rpA(r%^im zH7!P1vse5u3wpUx`0GlgQTVG;uj3Te!0YNEM0f~g!9!SkbO>j4=jKJSv_4+X($aFA zC99NRUr2n0u3^Y3qMBljXrC7t7bDvU67jW*6F4)?vs=|-?A)q}wR&ac)3<&N z7PZ`>^V(Hr$CSp5$OdU{c2|nkYnH4;1`W#zFsv$bymGAjN;Eyg!xSbk0Sm@bS``Lb35*#|u9XR=PWbA=ehqo4 zz)NBc4O{k>+;yP{YMH(HwtYn<}P&u|&%Xsq%>YZIT)r9NI{ z{k*#1O}p|vYf}d-^b4A5hcAclcn^Y>c5{_^kSwSRx$oiw?_uzuabst!@>R&)>9N}W zhprG56WPt=N4oi+daLo^kMBxi>8l`n;>v)I+)g3j%6F|zobKAGMAtlP$C!&^4bRw> zKi?3+6UJUVgQ_YxN*j5VW8TXt4xS|kh!!#j5Gh`yAP9z8;~c`P#oo)(V@9htaFy>^ zn;rlyo?rIb1^)~Cz-7)Afg_M~u)wJf9O7e>8s~``=b%a*-cB?_PIgTy5r{!*QuWNl zHV8+FrZ$3|e(UxMWZS^WT8P3xy-pl1PvZf5XT&)R?>P4KkEl*hYXv9B8~s{a>A%EP zHwagTX3{?zHLiFeF);q{%T*uy1D_plgtX-+21bi`2B3-?++ZK_%9$5MqOp^Px*go~Mg?`dZ|s#MO~B5<~PBjSqZK_}Vi2wX>0S01!B ztwrudQe!L&DpJQH$kVDTU$-{#`Yj|<*Es9(;>c#OnHpH-(t(JrO&8Pe=E9MY4i$6e zye!EHI&y0h-w@&IU?DV_Ds`=zupmn)Tw0snK<(F@LS-W=Pq*T3KWy>p4+68QdUm&> zR_3a^dP&MV^0=!zv#Q%_n*rxXRsDWy3M6#=$!>rYX}p!L+`F;Zxe~8l-yisN0bcGt zM+ejiJSq#voL`_db*WIRoddjc&&zi6SpS`x?XmQjG3r4+rB}zC{Rck|ejta3R}oLw zZKT&eisxQmYZq^(j4}qCb}vRSK;1Rz7CI5o{F^28X2&*?ukfYwlV@Gb|jM^ z!P{gw;xrZG&6a8|v%gE&7Az6p&Tc`|ZBy#0LzDqIYCOrdP(4$zmU!)OA0{aMgF&zGQ9sC1`LlRbAm!O#_$E7j>)tJlv6ZG14&& zZ;Pw&25>C&o*}iu_UXoyTGWlw?^0gUS5)Ap`fJs= znd%%+&ggvWs2#VVDiEv0eO11;UDUmCQY)c2omUJ) zNSNk(QSZ75sM4iO(xl$Dp7*Ko^nr*|SWG!m?po~9-94y3EsHr%LrOieaP#O`>Qp=3 zj5w!uqXr>sK3r=dB)3$(j+(wm$C#4MCw0FKiq<{5Ti=|!bO*QkTKE~4W)q3ssvcc{j5S5`8- zuQl}1*dg-1G-`_7Fc(sWo}7T%0%-*tbZea7ZP+V$ zy0ORFbTtSgh%!~vo2?1RKGuZHOt=k^&LEs5ovHa_bZN01Q1I3!b|{%R{^1QdI!P$- z_zihuhnV>j8YD71mKtrRZ_LlTU%(0P6ShJ%u(ee&@F;ASZQ*FN6~As^8v zJtYuNd6Au3Ta3vgvM*-Mc|ql0bkdtB-ss~>9-jLZEas2i{;dqsS5RMi?S_#~ks3;0 zR~_05GT^piP|&@OgTZ-jaW{Cw+c~@tc?optwKaP{4(in@ibzOcZi@%w_relFC%Vzm z^`J^(z=3E{Jn7xo?Pe$p8cY}dOUHmG(Rk@xjz$KVk`4lxpNdb%{r}UH^ZfLN=_QD# z@3M5fyu@gy$6MBgP@kdt-G%}P-`hBcD#i^z^V5ajVZ@j!J;u<`@$D@GgNaS5gBkd! z?RjS~7c(jdvGH_ED%At8%R76>)xk`ULxO1jz|@Q)1$BV!{Lfmu##+(O54fexx~ zn@4sO{gj(v1KL(Yw87$@abiS`XwWqfpriIF%&k0 z^mTZa$@&LDv$}3+v30T3hEi&EvDzPm19f?uYL)pbEHL4P@^BsU0TQ%*sU%>v|2sb$ zBuX;_HIhj91eDV&tG%8fv~4IY#&qC5dZ8{I4#@8w`~Xdtg1{gL7Y@6)az!5H_H^`{}`-Ia~;gx zkTm4vGNA5DM`+kb$z#NHbFnFSVhJ zjWgcD=7mX08QQxRR-r7?8_G-rEraqMF5ccf_#Qenrk@=GT4@(G<6!D)H$Y(Io{j4$ z_W@$>z*D-=!R#L`wQw(jJ`XMRNw!ogc>^lTK&_IAHW2e|uLI@z)~aYIU!-_oyw{}) z)u{$6YE@_5QxAv+99Xuc2s!=$Sk55QEdsv;oo&Hx)5=16FQb-9-ZfYD#PWy^zBD#)Ri{znS;a%kkouhUK3}?@8AaxMzmHOa24@ zP-QOR{WM%9yW|`|T)7Js0-gf+AS|&35*jb?w;-nb}eNIwM-CiFc1ksf!M6nz->_$vwu zBtpC&?u0!8I|a51tP>a(7!(Mg{1u~r>PO19BYlL2kST;`BT(Mo>Bo;|l;Ebnnkl$x z-;`CvO;uxf-<-JV|9Ib?xaqI(sqTN6{^e}JO@9;>yaeS%a{xd3H~rx%;JiO#`k%wV z8KyBm#D^Q-?7{Ex;MB|GrsuTBjX&n0zt`i=d5oK$vwb)2y)W>6551hd$l2Eam-Bxe z7tfr0&idt0w7I$7oc{l#$J^!*SD%ck>kB%*oZ6bfN@GOD>#`M%E0-?DJJy6bs}t?J zgB@Hpe3+U&8DXt_oMJfd$@raeyUNcDFtMZ(8T=sXLmt9ysWol3vIWJ2z zugsm61qPj$p*zusIYE95ulF^G{)#3j{jb3}?ch&^2Y9^aWl?&9VR-Z#M*qk&J0PtD z#^AgRS6J{0SS-AHWlT7e#C<9HAGZ;9vsS~MzcmS8VezpA;c*I3towJ`<^?(2`CFHS z*CgTfNqB+|d;Z4AxO(AzWljN?1KNN9+4DAhDnnZS$nW24xL&l=Csu;pWwy1tXPMR1 z6MfUVbtLt;mSF^e_;kbfaw!oz(|)DMUf5dtrEpk z#t~8cM7~WF3$Rw1{vWW6>}IA?MvFe>z#44^obFUktfxj-!9nIiWEZC-Tnb$X0=xTD zNDO;aE>?ooPGfg{@Ao1yh#7sygv>}AH+WD)90YI!@eicR1w(+?WtmJd}!UC@C z$gS36W0{gpc+dq)N$tsh)$CE3eEBS0d!OEDSqcgAEf^6IdFPVXc#PF1}1@ zd<@@=LFd?$Sb}R72EJndw4j6&DpfB3)m%(vElnz&Rd{H#$V$G7))sTH%b_axn;A}a zu&AeuUZ)Rh`YvXK%7o;5SkJ1Be@J7+Nd=b4C{L7WBgzz9Z-fZv?0%E3Z|?L%voDKt zpHFdKuBzWGr1~CkgA+KMNx0I?12~=L5`5`2ul-?$IwP|24OO1pGhjXBJ_R-rAi`HC z=kr!Ow?{KP$&Ng9E_Uu59(XX-FJ>NrWv)W{FuX`Hd@1GYrl<3YvrkFg32V)D8egWQ zZez8{)oq-*4SdtXJKN4}svfq^rYx~;D_IF&1Jl4KcG*>dkki(S1Bo*R&UA6V5!}B^ zA8=v`T~S)1+uu$kNVh+h6-3RWtWL`{KI~6cbzHzLeck+`h5A;4DG~ND?#K~5Y zp;xD&aS7EC$&l)p)wA0%f(p2uqpFG`eI1m3sqE6X7ElU&u039%THi}?EVUtGe_)|5SQOrS zEIg%qWCCcFbaR|*JFh*;-3`?T@GJ$FG~%W9CES!*_wmi6+Mh~{=N4oTd&tb1B$ZoW zhZfpiRR5&KbGo;z5T82kJt`F}@k-`7?D1TmXv9rY+<>cJxqJ=2CI>jNgLDuDDJCRv z?$q_?t_CkzgRG=MM&+AYLEpl#Wgpab$e}{iQXy|s0&@mom z44r3P{Rg-gVjan05{)TzrH13$F@6wVr{TEGAR>N?hU1t0 zd%amExXJ&prpJG6;3u!JxNkzctf9)x)ww0f(#B==iIs74DR>3$SL*Ahdd^?p+|sxh zQ+0KjG`@zgrJ;WHGBy9N&=Y#~f4KW{Q!A%=?#nea$)#TRGQf8o@b~DeT#s_5G5RVE z&iv(1oR51Q@F)s}#^|d&h(I{p`m6)En5By{ix)>DS40ek^}B?_a;GT=Bd9ll<;7Ci z$~O0JxOK%L3Gb8QrOqTwaBk3n*q~)@TZRPJZa&C&Qm^)Sa zB<3Ik!3hpDGT@LUt#TGedHd$_fS%&YFppL=Pz8@0c;+ClRe8fnc^Z3j2%yqR6yhSz z<9g|G$?aehr#~|9G4oV&4h9|Y&U-kyZG)1;nd-jS;nducxAznzF4|rYUjY@AD$I1v zAG8uXW^be$nUh^&%yj0C83^0^dX%2Rb=wOP7w)U-XQD90?05U3U&TL?coKchZEYy| zaGBGH&Q*&dgy7!{u$2GopqegzZmx14sf%6d^HC7Fr zj&id1?cwgLZSnR^uVRIHK%vWu5n*lM4a|euZY@30Z=~! zMOOkcZDt zwA=IHP8wsj;lqtT?ZH_`-R@BjJ|B*5ckej`=P7RYk9g<@&r`j<((1-_=I|ibRk@zp z)h}7ojJI#@cW^2QSY)5RdBbd2S>Mtkq2}J@$Rjf^v3^vgY=?eS5A6zOsCO>`iW|0%byI+pUHN8nIJRP6;OT#x8EbgUUh(!p6pmeh&9*{ZbKR@>u`b1%89WTR z$ePoOX=@2s0~b)U3x$3RBs+ig&KEJCWg4>j%%&)HyzTUyz1O!8JIx;^-~Q5#P)>K8 zx&Jx;G(Bn(g!e-)+AE%An(*SH1e$er@xGpQ>96bpT&ym#=KKoDIMw9vvrzs-uh?bg z+*wb>^*wOv_rp5J;yzyTXyTM9J?buGH&dm)6vt3!Vrs?^_2n|nakcfMzw%n$A=Vd^ z!5)=;vC6lbOS_pTxNF~Xx;^RV_9HJ(+wtPrfcj=?G@vfrsux-uRw@9tg(DW-0TVF#hC*#^&4&b*gs1x@; z0Q#*fYNfwqp9dqDM)c z^4)jcz`H8tLMQp}OZNomCI}tNK^YUjtd~k*`DgsL2p!8q8AIo~m&SF?1X)+HT=M9A z(h~*!exYYM<ZhjqwYel-nS>*LA&^*e~!mfMc+Zd0z0R1yVi- z#_G^S!7YKK07*~TpfD5P(e-fRAwbgC2~PPzbgu;@{d~d00%rh{{)gb1bl(y94M5WK z#VhTq{Hfrkf8ucy=}mt^GUBHHxm|G6pLo|(tKlv|;|sWg-p<7Kn>kWY$N1=Ndz; zkETtXD&%sni85^xkYwUoBQb2hby61#C`i}ikO#m?I82`uYK7otour%f@!xOyi*&FI zuMpuDqjAk-1cTN|&>7HF4-q|y)lgcnbn)WqD9MaDB;mA*MGyEQFa7A~87_?OIrR6i z>l)rarRmim5JuxRX`>a;<>I73DgLXzz;kZEog3^E1xm2VL>Wc!mtEH=kN8La_{)w- z#^E?%c8k_dD-Es(>Bmm}lziK%pY#!^E#nLw^t?*%HK%t6!H=OY!8hn9XSsJF!13cfCxi%Tf;CZy(0h&c0tcIp=VTFML!ZeU%7_Zqk0*HU3D@yzzB zFkamh2jZjf{t54Do{FCiyiDWe#7E=VS>lU4uW8Kkn$=&+mnwQuhu1e{c;KTm6A0d@ ztSwRT3{13jvK5vW#vx3FFgHh@=d?)UQPB8UdV!6X={PFUexS9qATgR=k(q&kU*LIC z1zxX&Gq)gsymf@pLklSoeE$0OaTE|MhwVJ0V!}lf$V@ma2T+5{=QUL5%~jiGoe;lv z7EXXtRh>$Ia(tvxo18e?PFHo3O}445l0-aMQrCSl--7Q!=||=;N)>(PR#4#m-WF%k zFKW_1+K*5~>FZyVdo=__?COQBd2bX+6-Atp%kcQP=Keq!dyws{D#-c?vGmmwxL$9< zOL*lsmbx{lR#%iU2Z~@Ub@c@05=o7`KM;iHWD=e;ck2-FstXEh5kj>q1k@0$&vqku zEMA15>!1oD90(+m1G8;etE8rAEm%+!=uB1NCngQxm7wYlY>zAaTFELDrXq}=5lf>s zrPr0=`iNqY_sbR_RuvJNSz_`1JU2~Te?PmJ#G3or4O;D-27$3!uwKhYOzjWC!o~hI zihcHYpt=U^*XA++wZKYtf<8mL$mRtVk&e$+sA%GM0j&gDsiKSjD}09$N0`|&)fK+2 z!tVqxps*3X?r0R(WH7lHNgS9lL?$STOGq(p2nz5RuR+jth`f%Gf7%uKauxYGI`ZX+ zyv`)99fynq8-2rU?^(ZedpLe_EcNA9Bs=E(3&HlF)&6awsT~~z={pG+;mx@ScW+U4 zs1H8^UmztOODR$l^Y)TNeMYKe6PRvNrSd)qbK%^&UNQbf70BB4V7w{oJq$gs$dC*l zqxtf`y(GREQEy|^={pI?<&0eDyE~N~xa8XdkP-)%B+W)soH#o}(SrU_6kF}LDNj4L z6Qu7XU^LgdqUln0h(_{_IHDnGHk!gjH1h=M{2IY_q;)Ot)ZL1I{uG5!5T}CO(M^!P zlYopY0wd-Q{U zE*<@P6t5l2vY|1pC_bnOLx`sgvPRjcY|=?oDaue69Jtcv0sy~#mvV9EIhUXN7ID7^ z3H00dC`YeAvm1M9|Hyr^CT>N-kUwS2I^T7E8HK}op(CHlc<9cDfK(3_|qSXzX5i-!3X2c-LGK#+u9KsnK!vcAA#=%)g?PeHs65Lp)DIVItz1pW?% zg|$KGzW^EDZGfa-EwEnT6#^rGERXX9=Nf}}9Uy`%3JVMh1W@+WgTwRJEwq5yfgka5 zg#`j{2`*?LDDX Date: Thu, 31 Oct 2019 15:08:59 -0700 Subject: [PATCH 173/185] use std::string instead of const char* in rmq struct --- controller/RabbitMQ.cpp | 5 +++-- controller/RabbitMQ.hpp | 9 +++++---- service/OneService.cpp | 6 +++--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/controller/RabbitMQ.cpp b/controller/RabbitMQ.cpp index 41ebcc87..73af1ccd 100644 --- a/controller/RabbitMQ.cpp +++ b/controller/RabbitMQ.cpp @@ -51,13 +51,14 @@ void RabbitMQ::init() throw std::runtime_error("Can't create socket for RabbitMQ"); } - _status = amqp_socket_open_noblock(_socket, _mqc->host, _mqc->port, &tval); + fprintf(stderr, "RabbitMQ: amqp://%s:%s@%s:%d\n", _mqc->username.c_str(), _mqc->password.c_str(), _mqc->host.c_str(), _mqc->port); + _status = amqp_socket_open_noblock(_socket, _mqc->host.c_str(), _mqc->port, &tval); if (_status) { throw std::runtime_error("Can't connect to RabbitMQ"); } amqp_rpc_reply_t r = amqp_login(_conn, "/", 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, - _mqc->username, _mqc->password); + _mqc->username.c_str(), _mqc->password.c_str()); if (r.reply_type != AMQP_RESPONSE_NORMAL) { throw std::runtime_error("RabbitMQ Login Error"); } diff --git a/controller/RabbitMQ.hpp b/controller/RabbitMQ.hpp index c60af8ec..4c286288 100644 --- a/controller/RabbitMQ.hpp +++ b/controller/RabbitMQ.hpp @@ -15,14 +15,15 @@ #define ZT_CONTROLLER_RABBITMQ_HPP #include "DB.hpp" +#include namespace ZeroTier { struct MQConfig { - const char *host; + std::string host; int port; - const char *username; - const char *password; + std::string username; + std::string password; }; } @@ -32,7 +33,7 @@ struct MQConfig { #include #include -#include + namespace ZeroTier { diff --git a/service/OneService.cpp b/service/OneService.cpp index 69b439ae..18e9240a 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -990,9 +990,9 @@ public: fprintf(stderr, "Reading RabbitMQ Config\n"); _mqc = new MQConfig; _mqc->port = rmq["port"]; - _mqc->host = OSUtils::jsonString(rmq["host"], "").c_str(); - _mqc->username = OSUtils::jsonString(rmq["username"], "").c_str(); - _mqc->password = OSUtils::jsonString(rmq["password"], "").c_str(); + _mqc->host = OSUtils::jsonString(rmq["host"], ""); + _mqc->username = OSUtils::jsonString(rmq["username"], ""); + _mqc->password = OSUtils::jsonString(rmq["password"], ""); } // Bind to wildcard instead of to specific interfaces (disables full tunnel capability) From 088dab4f04d7ec662b83299a32d7183d5d48a5dc Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Thu, 31 Oct 2019 15:13:20 -0700 Subject: [PATCH 174/185] Let's not print this to the logs --- controller/RabbitMQ.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/controller/RabbitMQ.cpp b/controller/RabbitMQ.cpp index 73af1ccd..29a331ad 100644 --- a/controller/RabbitMQ.cpp +++ b/controller/RabbitMQ.cpp @@ -51,7 +51,6 @@ void RabbitMQ::init() throw std::runtime_error("Can't create socket for RabbitMQ"); } - fprintf(stderr, "RabbitMQ: amqp://%s:%s@%s:%d\n", _mqc->username.c_str(), _mqc->password.c_str(), _mqc->host.c_str(), _mqc->port); _status = amqp_socket_open_noblock(_socket, _mqc->host.c_str(), _mqc->port, &tval); if (_status) { throw std::runtime_error("Can't connect to RabbitMQ"); From e1e27eb19d2ff122333e1e9a192a9516335fd087 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Mon, 11 Nov 2019 12:03:49 -0800 Subject: [PATCH 175/185] Bugfix for incorrect port binding of secondary and tertiary ports --- service/OneService.cpp | 56 +++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/service/OneService.cpp b/service/OneService.cpp index 18e9240a..d2e4957e 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -678,44 +678,50 @@ public: // than one device behind the same NAT tries to use the same internal // private address port number. Buggy NATs are a running theme. if (_allowSecondaryPort) { - _ports[1] = (_secondaryPort == 0) ? 20000 + ((unsigned int)_node->address() % 45500) : _secondaryPort; - for(int i=0;;++i) { - if (i > 1000) { - _ports[1] = 0; - break; - } else if (++_ports[1] >= 65536) { - _ports[1] = 20000; + if (_secondaryPort) { + _ports[1] = _secondaryPort; + } else { + _ports[1] = 20000 + ((unsigned int)_node->address() % 45500); + for(int i=0;;++i) { + if (i > 1000) { + _ports[1] = 0; + break; + } else if (++_ports[1] >= 65536) { + _ports[1] = 20000; + } + if (_trialBind(_ports[1])) + break; } - if (_trialBind(_ports[1])) - break; } } - #ifdef ZT_USE_MINIUPNPC if (_portMappingEnabled) { // If we're running uPnP/NAT-PMP, bind a *third* port for that. We can't // use the other two ports for that because some NATs do really funky // stuff with ports that are explicitly mapped that breaks things. if (_ports[1]) { - _ports[2] = (_tertiaryPort == 0) ? _ports[1] : _tertiaryPort; - for(int i=0;;++i) { - if (i > 1000) { - _ports[2] = 0; - break; - } else if (++_ports[2] >= 65536) { - _ports[2] = 20000; + if (_tertiaryPort) { + _ports[2] = _tertiaryPort; + } else { + _ports[2] = _ports[1]; + for(int i=0;;++i) { + if (i > 1000) { + _ports[2] = 0; + break; + } else if (++_ports[2] >= 65536) { + _ports[2] = 20000; + } + if (_trialBind(_ports[2])) + break; + } + if (_ports[2]) { + char uniqueName[64]; + OSUtils::ztsnprintf(uniqueName,sizeof(uniqueName),"ZeroTier/%.10llx@%u",_node->address(),_ports[2]); + _portMapper = new PortMapper(_ports[2],uniqueName); } - if (_trialBind(_ports[2])) - break; - } - if (_ports[2]) { - char uniqueName[64]; - OSUtils::ztsnprintf(uniqueName,sizeof(uniqueName),"ZeroTier/%.10llx@%u",_node->address(),_ports[2]); - _portMapper = new PortMapper(_ports[2],uniqueName); } } } -#endif // Delete legacy iddb.d if present (cleanup) OSUtils::rmDashRf((_homePath + ZT_PATH_SEPARATOR_S "iddb.d").c_str()); From b8e70d866a16ef26d782e4a0b074a124c2cb4212 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Tue, 12 Nov 2019 09:46:39 -0800 Subject: [PATCH 176/185] Compile fix for unterminated conditional directive --- service/OneService.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/OneService.cpp b/service/OneService.cpp index d2e4957e..97ba1a36 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -722,7 +722,7 @@ public: } } } - +#endif // Delete legacy iddb.d if present (cleanup) OSUtils::rmDashRf((_homePath + ZT_PATH_SEPARATOR_S "iddb.d").c_str()); From 86abd31659d385b52d329cfcf8b6e203b8c85a46 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Wed, 13 Nov 2019 12:46:16 -0800 Subject: [PATCH 177/185] fix log line --- controller/PostgreSQL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/PostgreSQL.cpp b/controller/PostgreSQL.cpp index 08e06ee9..8f8c2785 100644 --- a/controller/PostgreSQL.cpp +++ b/controller/PostgreSQL.cpp @@ -760,7 +760,7 @@ void PostgreSQL::networksDbWatcher() fprintf(stderr, "ERROR: %s networksDbWatcher should still be running! Exiting Controller.\n", _myAddressStr.c_str()); exit(8); } - fprintf(stderr, "Exited membersDbWatcher\n"); + fprintf(stderr, "Exited networksDbWatcher\n"); } void PostgreSQL::_networksWatcher_Postgres(PGconn *conn) { From dc19deb6c3f23bb3dec7d4141a57b09369138313 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Wed, 13 Nov 2019 12:46:52 -0800 Subject: [PATCH 178/185] . --- .gitignore | 1 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 ++++++++ 2 files changed, 9 insertions(+) create mode 100644 macui/ZeroTier One.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/.gitignore b/.gitignore index 44b5eb56..62a6c6a1 100755 --- a/.gitignore +++ b/.gitignore @@ -120,3 +120,4 @@ __pycache__ *~ attic/world/*.c25519 attic/world/mkworld +workspace/ diff --git a/macui/ZeroTier One.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/macui/ZeroTier One.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/macui/ZeroTier One.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + From 8396f16dd2d26aece025e4a939d81340c4860ba9 Mon Sep 17 00:00:00 2001 From: Dave Cottlehuber Date: Tue, 19 Nov 2019 16:45:06 +0000 Subject: [PATCH 179/185] drop -Werror from DEBUG builds Appease compilers. Thanks @glimberg for the diff. Closes #1086 --- make-bsd.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make-bsd.mk b/make-bsd.mk index 8c7a6ad2..62a6d73e 100644 --- a/make-bsd.mk +++ b/make-bsd.mk @@ -13,7 +13,7 @@ ifeq ($(ZT_SANITIZE),1) endif # "make debug" is a shortcut for this ifeq ($(ZT_DEBUG),1) - CFLAGS+=-Wall -Werror -g -pthread $(INCLUDES) $(DEFS) + CFLAGS+=-Wall -g -pthread $(INCLUDES) $(DEFS) LDFLAGS+= STRIP=echo ZT_TRACE=1 From 381f15382c2ec06c77fe2d54a0208010248f935c Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Wed, 20 Nov 2019 13:56:26 -0800 Subject: [PATCH 180/185] Convert central-controller docker build to use a builder subcontainer --- ext/central-controller-docker/Dockerfile | 19 +++++++++++++------ make-linux.mk | 4 ++-- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/ext/central-controller-docker/Dockerfile b/ext/central-controller-docker/Dockerfile index 2fc92e6f..716390f8 100644 --- a/ext/central-controller-docker/Dockerfile +++ b/ext/central-controller-docker/Dockerfile @@ -1,19 +1,26 @@ # Dockerfile for ZeroTier Central Controllers -FROM centos:7 +FROM centos:7 as builder MAINTAINER Adam Ierymekno , Grant Limberg +ARG git_branch=master + RUN yum update -y RUN yum install -y https://download.postgresql.org/pub/repos/yum/10/redhat/rhel-7-x86_64/pgdg-centos10-10-2.noarch.rpm -RUN yum install -y bash postgresql10 libpqxx-devel - RUN yum -y install epel-release && yum -y update && yum clean all -RUN yum -y install clang jemalloc jemalloc-devel +RUN yum groupinstall -y "Development Tools" +RUN yum install -y bash postgresql10 postgresql10-devel libpqxx-devel glibc-static libstdc++-static clang jemalloc jemalloc-devel +RUN git clone http://git.int.zerotier.com/zerotier/ZeroTierOne.git +RUN if [ "$git_branch" != "master" ]; then cd ZeroTierOne && git checkout -b $git_branch origin/$git_branch; fi +RUN ldconfig +RUN cd ZeroTierOne && make central-controller + +FROM centos:7 -ADD zerotier-one /usr/local/bin/zerotier-one +COPY --from=builder /ZeroTierOne/zerotier-one /usr/local/bin/zerotier-one RUN chmod a+x /usr/local/bin/zerotier-one -ADD docker/main.sh / +ADD ext/central-controller-docker/main.sh / RUN chmod a+x /main.sh ENTRYPOINT /main.sh diff --git a/make-linux.mk b/make-linux.mk index 9fd4f7b9..b3181143 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -334,8 +334,8 @@ docker: FORCE central-controller: FORCE make -j4 LDLIBS="-L/usr/pgsql-10/lib/ -lpq -Lext/librabbitmq/centos_x64/lib/ -lrabbitmq" CXXFLAGS="-I/usr/pgsql-10/include -I./ext/librabbitmq/centos_x64/include -fPIC" DEFS="-DZT_CONTROLLER_USE_LIBPQ -DZT_CONTROLLER" ZT_OFFICIAL=1 ZT_USE_X64_ASM_ED25519=1 one -central-controller-docker: central-controller - docker build -t docker.zerotier.com/zerotier-central/ztcentral-controller:${TIMESTAMP} -f ext/central-controller-docker/Dockerfile . +central-controller-docker: FORCE + docker build -t docker.zerotier.com/zerotier-central/ztcentral-controller:${TIMESTAMP} -f ext/central-controller-docker/Dockerfile --build-arg git_branch=`git name-rev --name-only HEAD` . debug: FORCE make ZT_DEBUG=1 one From e58a0b3efbbd415fa135d16f613127cd4770adfc Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Thu, 21 Nov 2019 14:49:24 -0800 Subject: [PATCH 181/185] build central controller docker images on macOS --- make-mac.mk | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/make-mac.mk b/make-mac.mk index 545dabee..62df1f6f 100644 --- a/make-mac.mk +++ b/make-mac.mk @@ -16,6 +16,9 @@ ZT_VERSION_MINOR=$(shell cat version.h | grep -F VERSION_MINOR | cut -d ' ' -f 3 ZT_VERSION_REV=$(shell cat version.h | grep -F VERSION_REVISION | cut -d ' ' -f 3) ZT_VERSION_BUILD=$(shell cat version.h | grep -F VERSION_BUILD | cut -d ' ' -f 3) +# for central controller builds +TIMESTAMP=$(shell date +"%Y%m%d%H%M") + DEFS+=-DZT_BUILD_PLATFORM=$(ZT_BUILD_PLATFORM) -DZT_BUILD_ARCHITECTURE=$(ZT_BUILD_ARCHITECTURE) include objects.mk @@ -140,6 +143,9 @@ official: FORCE make ZT_OFFICIAL_RELEASE=1 macui make ZT_OFFICIAL_RELEASE=1 mac-dist-pkg +central-controller-docker: FORCE + docker build -t docker.zerotier.com/zerotier-central/ztcentral-controller:${TIMESTAMP} -f ext/central-controller-docker/Dockerfile --build-arg git_branch=$(shell git name-rev --name-only HEAD) . + clean: rm -rf MacEthernetTapAgent *.dSYM build-* *.a *.pkg *.dmg *.o node/*.o controller/*.o service/*.o osdep/*.o ext/http-parser/*.o $(CORE_OBJS) $(ONE_OBJS) zerotier-one zerotier-idtool zerotier-selftest zerotier-cli zerotier doc/node_modules macui/build zt1_update_$(ZT_BUILD_PLATFORM)_$(ZT_BUILD_ARCHITECTURE)_* From 54e25084feb1d5994650d3e104c56e8de48ce3f9 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Thu, 21 Nov 2019 14:51:33 -0800 Subject: [PATCH 182/185] re-enable CI on master --- Jenkinsfile | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 88989327..edb0c69e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -40,26 +40,26 @@ parallel 'centos7': { // throw err // } // } -// }, 'macOS': { -// node('macOS') { -// try { -// checkout scm +}, 'macOS': { + node('macOS') { + try { + checkout scm -// stage('Build macOS') { -// sh 'make -f make-mac.mk' -// } + stage('Build macOS') { + sh 'make -f make-mac.mk' + } -// stage('Build macOS UI') { -// sh 'cd macui && xcodebuild -target "ZeroTier One" -configuration Debug' -// } -// } -// catch (err) { -// currentBuild.result = "FAILURE" -// mattermostSend color: '#ff0000', message: "${env.JOB_NAME} broken on macOS (<${env.BUILD_URL}|Open>)" + stage('Build macOS UI') { + sh 'cd macui && xcodebuild -target "ZeroTier One" -configuration Debug' + } + } + catch (err) { + currentBuild.result = "FAILURE" + mattermostSend color: '#ff0000', message: "${env.JOB_NAME} broken on macOS (<${env.BUILD_URL}|Open>)" -// throw err -// } -// } + throw err + } + } // }, 'windows': { // node('windows') { // try { From d8597884f6a49bbe390eb56a4443a0c63cda4453 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Fri, 22 Nov 2019 11:25:31 -0800 Subject: [PATCH 183/185] jenkins windows --- Jenkinsfile | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index edb0c69e..2c4c97fb 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -60,25 +60,24 @@ parallel 'centos7': { throw err } } -// }, 'windows': { -// node('windows') { -// try { -// checkout scm +}, 'windows': { + node('windows') { + try { + checkout scm -// stage('Build Windows') { -// bat '''CALL "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\vcvarsall.bat" amd64 -// git clean -dfx -// msbuild windows\\ZeroTierOne.sln -// ''' -// } -// } -// catch (err) { -// currentBuild.result = "FAILURE" -// mattermostSend color: '#ff0000', message: "${env.JOB_NAME} broken on Windows (<${env.BUILD_URL}|Open>)" + stage('Build Windows') { + bat '''CALL "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\VC\\Auxiliary\\Build\\vcvars32.bat" x64 +msbuild windows\\ZeroTierOne.sln +''' + } + } + catch (err) { + currentBuild.result = "FAILURE" + mattermostSend color: '#ff0000', message: "${env.JOB_NAME} broken on Windows (<${env.BUILD_URL}|Open>)" -// throw err -// } -// } + throw err + } + } } mattermostSend color: "#00ff00", message: "${env.JOB_NAME} #${env.BUILD_NUMBER} Complete (<${env.BUILD_URL}|Show More...>)" From 2a7d4fcde52e60a97a50642ed5dc45867fed0943 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Tue, 17 Dec 2019 10:49:21 -0800 Subject: [PATCH 184/185] update vs project settings --- windows/ZeroTierOne/ZeroTierOne.vcxproj | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj b/windows/ZeroTierOne/ZeroTierOne.vcxproj index 1cfe8ae0..a91ed7d1 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj @@ -220,37 +220,37 @@ {B00A4957-5977-4AC1-9EF4-571DC27EADA2} ZeroTierOne - 10.0.17134.0 + 10.0 Application true - v141 + v142 MultiByte Application true - v141 + v142 MultiByte Application true - v141 + v142 MultiByte Application true - v141 + v142 MultiByte Application false - v141 + v142 true MultiByte Static @@ -258,7 +258,7 @@ Application false - v141 + v142 true MultiByte Static From 7696d450931b203049d722101028c7b3233585b0 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Tue, 17 Dec 2019 10:51:01 -0800 Subject: [PATCH 185/185] Fix handling of invalid conf file Fixes GitHub issue #1068 --- windows/WinUI/CentralAPI.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/windows/WinUI/CentralAPI.cs b/windows/WinUI/CentralAPI.cs index b0b4a267..22bdc697 100644 --- a/windows/WinUI/CentralAPI.cs +++ b/windows/WinUI/CentralAPI.cs @@ -75,7 +75,15 @@ namespace WinUI { byte[] tmp = File.ReadAllBytes(centralConfigPath); string json = Encoding.UTF8.GetString(tmp).Trim(); - Central = JsonConvert.DeserializeObject(json); + CentralServer ctmp = JsonConvert.DeserializeObject(json); + if (ctmp != null) + { + Central = ctmp; + } + else + { + Central = new CentralServer(); + } } else { @@ -105,7 +113,10 @@ namespace WinUI { string json = JsonConvert.SerializeObject(Central); byte[] tmp = Encoding.UTF8.GetBytes(json); - File.WriteAllBytes(CentralConfigFile(), tmp); + if (tmp != null) + { + File.WriteAllBytes(CentralConfigFile(), tmp); + } } private void UpdateRequestHeaders()