From 692733fffbf97b561f7fa62349f14b2399335bf4 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Mon, 15 Jul 2019 13:00:16 -0700 Subject: [PATCH 01/50] 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 de6b4f460..4d3da958d 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 bb99ef1351b72260836db29d5863ca1ee6dc0478 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 31 Jul 2019 16:41:12 -0700 Subject: [PATCH 02/50] 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 7b997c49a..cda978b87 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 03/50] Bump version --- version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.h b/version.h index 8e380a1dc..808cf8ddc 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 04/50] 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 000000000..09e5e28b3 --- /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 05/50] 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 40ffce2f9..43f5d9c94 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 06/50] 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 92dd30cbc..031eb0b76 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 6f2d0339c..506573ed2 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 969e1f140..5e5738123 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 07/50] 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 506573ed2..73e11c6c1 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 08/50] GitHub issue #993 (???) --- node/Multicaster.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/node/Multicaster.hpp b/node/Multicaster.hpp index 2cdcfb82c..c55c6f3c8 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 09/50] GitHub issue #993 (???) --- node/Multicaster.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/node/Multicaster.hpp b/node/Multicaster.hpp index c55c6f3c8..971f84af4 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 10/50] 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 f499d3874..85920eecd 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 cda978b87..484aefa57 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 5d55d0a4a..33efb7257 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 f0c8ebfb9..999eca72a 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 e2bcfe587..709712b5f 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 11/50] 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 d290ba949..d5c049ad3 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 ea67928b3..afda65546 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 808cf8ddc..106787935 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 d8525f2af..43dca4c0b 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 72217215e..6123eb708 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 12/50] 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 26b529d7d..1694f87f6 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 13/50] LFDB fix --- controller/LFDB.cpp | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/controller/LFDB.cpp b/controller/LFDB.cpp index 999eca72a..a7bbf81d5 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 14/50] 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 | 85 +++++++------- controller/RabbitMQ.cpp | 134 +++++++++++------------ controller/RabbitMQ.hpp | 32 +++--- 10 files changed, 161 insertions(+), 152 deletions(-) diff --git a/controller/DB.cpp b/controller/DB.cpp index bb734dc85..75adf53e5 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 85920eecd..461f385e6 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 bf5685271..80331578c 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 7bc37be21..c0f14f8b6 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 484aefa57..acc8680e6 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 a7bbf81d5..9203a5a18 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 709712b5f..45be3e518 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 f35f89fc9..fe69635d1 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 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(); + void commitThread(); + void onlineNotificationThread(); - enum OverrideMode { - ALLOW_PGBOUNCER_OVERRIDE = 0, - NO_OVERRIDE = 1 - }; + 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 eec9745dc..cf5c567d7 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 d341681be..6bac68daa 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 15/50] 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 461f385e6..732a6e25c 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 000000000..bccdefddd --- /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 000000000..1af0018ee --- /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 80331578c..d9c6364b6 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 acc8680e6..66b3d2c2e 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 33efb7257..deef88546 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 9203a5a18..5bf0aaf79 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 731874626..646da65df 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 45be3e518..121d00df8 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 fe69635d1..ce6fb2428 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 cf5c567d7..e14fbf3f2 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 6bac68daa..c8ef31ca5 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 16/50] 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 75adf53e5..a4440f388 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 732a6e25c..e391538ea 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 bccdefddd..63c0f58ba 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::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::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) +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 1af0018ee..aee598af2 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 d9c6364b6..64acda0f1 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 c0f14f8b6..85223dc43 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 66b3d2c2e..1dc2498ab 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 deef88546..8aa2c18ec 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 5bf0aaf79..5dd6d0821 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 646da65df..bcd6cdd08 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 121d00df8..13b7b8d85 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 ce6fb2428..6b0ea9961 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 17/50] 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 64acda0f1..893c0239c 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 85223dc43..904f09599 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 13b7b8d85..012946b4e 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 fcda13fdf..e25ed36c2 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 18/50] 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 e391538ea..efb08d63b 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 19/50] . --- controller/DBMirrorSet.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/controller/DBMirrorSet.cpp b/controller/DBMirrorSet.cpp index 63c0f58ba..f435698e2 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 20/50] 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 f435698e2..5d9ea0507 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 5dd6d0821..812b2f381 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 21/50] 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 812b2f381..3672dfa97 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 746009898..b0be01056 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 1e151b616..4458c9b09 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 43f5d9c94..7c9671e5b 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 22/50] 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 b81c7aeb4..db3863060 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 23/50] 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 012946b4e..8a34ec1d4 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 24/50] 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 893c0239c..08d31bee6 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 904f09599..adc2a2eca 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 7c9671e5b..13dca4b06 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 25/50] 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 | 1525 ++++++++++------- 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, 2094 insertions(+), 915 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 000000000..c20eefa58 --- /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 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 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 000000000..0710b4008 --- /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 afda65546..d962e96dd 100755 --- a/ext/installfiles/mac/ZeroTier One.pkgproj +++ b/ext/installfiles/mac/ZeroTier One.pkgproj @@ -2,670 +2,731 @@ + PACKAGES + + + MUST-CLOSE-APPLICATION-ITEMS + + MUST-CLOSE-APPLICATIONS + + PACKAGE_FILES + + DEFAULT_INSTALL_LOCATION + / + 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 + + PACKAGE_SCRIPTS + + POSTINSTALL_PATH + + PATH + postinst.sh + PATH_TYPE + 1 + + PREINSTALL_PATH + + PATH + preinst.sh + PATH_TYPE + 1 + + RESOURCES + + + PACKAGE_SETTINGS + + 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 + + TYPE + 0 + UUID + 1B6AFC3A-9EA5-4401-83D4-37F06CD13CD6 + + PROJECT - PACKAGE_FILES - - DEFAULT_INSTALL_LOCATION - / - 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 - - - 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 - / - PATH_TYPE - 0 - PERMISSIONS - 493 - TYPE - 1 - UID - 0 - - PAYLOAD_TYPE - 0 - SHOW_INVISIBLE - - SPLIT_FORKS - - TREAT_MISSING_FILES_AS_WARNING - - VERSION - 3 - - PACKAGE_SCRIPTS - - POSTINSTALL_PATH - - PATH - postinst.sh - PATH_TYPE - 1 - - PREINSTALL_PATH - - PATH - preinst.sh - PATH_TYPE - 1 - - RESOURCES - - - PACKAGE_SETTINGS - - AUTHENTICATION - 1 - CONCLUSION_ACTION - 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 - 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 b4ea2ee23..95301a4e9 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 deefd5c74..5b1fe2dc8 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 000000000..a10db55fe --- /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 000000000..fc8fc8482 --- /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 2ea93dd1d..5ed49eef8 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 050bec343..1acecb4b6 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 a11a75e24..237df4704 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 fb5bc6dbb..2eef59be6 100644 --- a/osdep/MacEthernetTap.hpp +++ b/osdep/MacEthernetTap.hpp @@ -27,6 +27,14 @@ #ifndef ZT_OSXETHERNETTAP_HPP #define ZT_OSXETHERNETTAP_HPP +#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 @@ -34,17 +42,9 @@ #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" - 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 000000000..4f0520a65 --- /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 000000000..fbf2694b2 --- /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 32b6dfa61..a174816e7 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 6b44d48e8..000000000 --- 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 78a956728..7a8638759 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 26/50] 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 0735a47fb..c71b3f778 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 e25ed36c2..32f625884 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 13dca4b06..a434f4846 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 27/50] 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 d962e96dd..2bd19123c 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 28/50] 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 a10db55fe..21618a582 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 a434f4846..b38e8f427 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 29/50] Remove debug line --- osdep/EthernetTap.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/osdep/EthernetTap.cpp b/osdep/EthernetTap.cpp index 21618a582..c3bb4ca17 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 30/50] cleanup --- controller/LFDB.cpp | 49 ++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/controller/LFDB.cpp b/controller/LFDB.cpp index 3672dfa97..3b800ec2a 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 31/50] cleanup --- osdep/EthernetTap.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/osdep/EthernetTap.cpp b/osdep/EthernetTap.cpp index c3bb4ca17..82290fc28 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 32/50] 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 db3863060..53537de8d 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 33/50] warning cleanup --- node/C25519.cpp | 361 +++++++----------------------------------------- 1 file changed, 50 insertions(+), 311 deletions(-) diff --git a/node/C25519.cpp b/node/C25519.cpp index 4384f8fd8..38cfd6141 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 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 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 34/50] more warning cleanup --- node/C25519.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/node/C25519.cpp b/node/C25519.cpp index 38cfd6141..d7c7011fd 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 35/50] warning removal --- controller/PostgreSQL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/PostgreSQL.cpp b/controller/PostgreSQL.cpp index 8a34ec1d4..a43e2118b 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 36/50] Windows fixes. --- service/OneService.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/service/OneService.cpp b/service/OneService.cpp index b38e8f427..93e97bdef 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 37/50] 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 2346dabcc..2bcc86030 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 f761d9207..78e088c73 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 38/50] 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 efb08d63b..aebe4e112 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 5d9ea0507..5b491216d 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 1dc2498ab..cf5847d6a 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 3b800ec2a..35068321d 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 a43e2118b..66b49394e 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 39/50] 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 35068321d..d00d8631c 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 40/50] Add periodic sync check when syncing LF<>another DB --- controller/DB.hpp | 15 ++++++++++++- controller/DBMirrorSet.cpp | 46 +++++++++++++++++++++++++++++++++++++- controller/DBMirrorSet.hpp | 3 +++ controller/LFDB.cpp | 2 +- 4 files changed, 63 insertions(+), 3 deletions(-) diff --git a/controller/DB.hpp b/controller/DB.hpp index aebe4e112..6c518426c 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 5b491216d..852e70f30 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 aee598af2..23cb25e71 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 d00d8631c..b6dc66578 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 41/50] Shutdown fix --- controller/DBMirrorSet.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/controller/DBMirrorSet.cpp b/controller/DBMirrorSet.cpp index 852e70f30..c1be6b9ce 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 42/50] One more sync fix. --- controller/DBMirrorSet.cpp | 40 +++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/controller/DBMirrorSet.cpp b/controller/DBMirrorSet.cpp index c1be6b9ce..c3cd7841f 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 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); + } + } } } } - } 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); - } - } - } - } + } 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 43/50] 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 a4440f388..0c6274b9c 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 44/50] 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 66b49394e..cd913f87a 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 45/50] 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 cd913f87a..07bb5825a 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 46/50] 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 07bb5825a..30b3f70d9 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 47/50] 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 30b3f70d9..476ee708b 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 48/50] Comment ugly query --- controller/PostgreSQL.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/controller/PostgreSQL.cpp b/controller/PostgreSQL.cpp index 476ee708b..0c345c901 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 49/50] * 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 1dd56b9fd..a781392d6 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 50/50] 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 d5c049ad3..0bf2307a6 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 6123eb708..46e166fd9 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