From 7e6e56e2bce240a8d3a4f2825d3f110109a541b6 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 3 Aug 2016 18:04:08 -0700 Subject: Bunch of work on pushing and replication of tags and capabilities, and protocol cleanup. --- service/OneService.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 13820f5c..460eb1c9 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -705,6 +705,9 @@ public: } authToken = _trimString(authToken); + // Clean up any legacy files if present + OSUtils::rm((_homePath + ZT_PATH_SEPARATOR_S + "peers.save").c_str()); + _node = new Node( OSUtils::now(), this, -- cgit v1.2.3 From 98152d974ada42e659e65590dec9a53d0a28ef54 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 4 Aug 2016 11:40:38 -0700 Subject: More cleanup and removal of DeferredPackets, will do the latter in a more elegant way. --- include/ZeroTierOne.h | 21 ---------- node/Capability.cpp | 4 ++ node/Capability.hpp | 62 +++++++++++++-------------- node/DeferredPackets.cpp | 100 -------------------------------------------- node/DeferredPackets.hpp | 85 ------------------------------------- node/IncomingPacket.cpp | 20 +++------ node/IncomingPacket.hpp | 13 +----- node/Node.cpp | 24 ----------- node/Node.hpp | 9 ---- node/RuntimeEnvironment.hpp | 9 ---- node/Switch.cpp | 8 ++-- objects.mk | 1 - service/OneService.cpp | 4 -- 13 files changed, 45 insertions(+), 315 deletions(-) delete mode 100644 node/DeferredPackets.cpp delete mode 100644 node/DeferredPackets.hpp (limited to 'service/OneService.cpp') diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 9679cf64..88e83a6e 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -1902,27 +1902,6 @@ void ZT_Node_clusterStatus(ZT_Node *node,ZT_ClusterStatus *cs); */ void ZT_Node_setTrustedPaths(ZT_Node *node,const struct sockaddr_storage *networks,const uint64_t *ids,unsigned int count); -/** - * Do things in the background until Node dies - * - * This function can be called from one or more background threads to process - * certain tasks in the background to improve foreground performance. It will - * not return until the Node is shut down. If threading is not enabled in - * this build it will return immediately and will do nothing. - * - * This is completely optional. If this is never called, all processing is - * done in the foreground in the various processXXXX() methods. - * - * This does NOT replace or eliminate the need to call the normal - * processBackgroundTasks() function in your main loop. This mechanism is - * used to offload the processing of expensive mssages onto background - * handler threads to prevent foreground performance degradation under - * high load. - * - * @param node Node instance - */ -void ZT_Node_backgroundThreadMain(ZT_Node *node); - /** * Get ZeroTier One version * diff --git a/node/Capability.cpp b/node/Capability.cpp index ee798a6c..0a736ca8 100644 --- a/node/Capability.cpp +++ b/node/Capability.cpp @@ -28,9 +28,11 @@ namespace ZeroTier { int Capability::verify(const RuntimeEnvironment *RR) const { try { + // There must be at least one entry, and sanity check for bad chain max length if ((_maxCustodyChainLength < 1)||(_maxCustodyChainLength > ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH)) return -1; + // Validate all entries in chain of custody Buffer<(sizeof(Capability) * 2)> tmp; this->serialize(tmp,true); for(unsigned int c=0;c<_maxCustodyChainLength;++c) { @@ -53,6 +55,8 @@ int Capability::verify(const RuntimeEnvironment *RR) const return 1; } } + + // We reached max custody chain length and everything was valid return 0; } catch ( ... ) {} return -1; diff --git a/node/Capability.hpp b/node/Capability.hpp index 48282708..d9b49121 100644 --- a/node/Capability.hpp +++ b/node/Capability.hpp @@ -114,6 +114,23 @@ public: */ inline uint64_t expiration() const { return _expiration; } + /** + * Check to see if a given address is a 'to' address in the custody chain + * + * This does not actually do certificate checking. That must be done with verify(). + * + * @param a Address to check + * @return True if address is present + */ + inline bool wasIssuedTo(const Address &a) const + { + for(unsigned int i=0;i tmp; this->serialize(tmp,true); + _custody[i].to = to; + _custody[i].from = from.address(); _custody[i].signature = from.sign(tmp.data(),tmp.size()); return true; } @@ -255,22 +272,21 @@ public: b.append(_id); b.append(_nwid); b.append(_expiration); - serializeRules(b,_rules,_ruleCount); - b.append((uint8_t)_maxCustodyChainLength); - for(unsigned int i=0;;++i) { - if ((i < _maxCustodyChainLength)&&(i < ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH)&&(_custody[i].to)) { - _custody[i].to.appendTo(b); - _custody[i].from.appendTo(b); - if (!forSign) { + + if (!forSign) { + for(unsigned int i=0;;++i) { + if ((i < _maxCustodyChainLength)&&(i < ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH)&&(_custody[i].to)) { + _custody[i].to.appendTo(b); + _custody[i].from.appendTo(b); b.append((uint8_t)1); // 1 == Ed25519 signature b.append((uint16_t)ZT_C25519_SIGNATURE_LEN); // length of signature b.append(_custody[i].signature.data,ZT_C25519_SIGNATURE_LEN); + } else { + b.append((unsigned char)0,ZT_ADDRESS_LENGTH); // zero 'to' terminates chain + break; } - } else { - b.append((unsigned char)0,ZT_ADDRESS_LENGTH); // zero 'to' terminates chain - break; } } @@ -369,10 +385,9 @@ public: _id = b.template at(p); p += 4; _nwid = b.template at(p); p += 8; _expiration = b.template at(p); p += 8; - deserializeRules(b,p,_rules,_ruleCount,ZT_MAX_CAPABILITY_RULES); - _maxCustodyChainLength = (unsigned int)b[p++]; + if ((_maxCustodyChainLength < 1)||(_maxCustodyChainLength > ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH)) throw std::runtime_error("invalid max custody chain length"); for(unsigned int i;;++i) { @@ -393,25 +408,6 @@ public: return (p - startAt); } - /** - * Check to see if a given address is a 'to' address in the custody chain - * - * This does not actually do certificate checking. That must be done with verify(). - * - * @param a Address to check - * @return True if address is present - */ - inline bool wasIssuedTo(const Address &a) const - { - for(unsigned int i=0;i. - */ - -#include "Constants.hpp" -#include "DeferredPackets.hpp" -#include "IncomingPacket.hpp" -#include "RuntimeEnvironment.hpp" -#include "Node.hpp" - -namespace ZeroTier { - -DeferredPackets::DeferredPackets(const RuntimeEnvironment *renv) : - RR(renv), - _waiting(0), - _die(false) -{ -} - -DeferredPackets::~DeferredPackets() -{ - _q_m.lock(); - _die = true; - _q_m.unlock(); - - for(;;) { - _q_s.post(); - - _q_m.lock(); - if (_waiting <= 0) { - _q_m.unlock(); - break; - } else { - _q_m.unlock(); - } - } -} - -bool DeferredPackets::enqueue(IncomingPacket *pkt) -{ - { - Mutex::Lock _l(_q_m); - if (_q.size() >= ZT_DEFFEREDPACKETS_MAX) - return false; - _q.push_back(*pkt); - } - _q_s.post(); - return true; -} - -int DeferredPackets::process() -{ - std::list pkt; - - _q_m.lock(); - - if (_die) { - _q_m.unlock(); - return -1; - } - - while (_q.empty()) { - ++_waiting; - _q_m.unlock(); - _q_s.wait(); - _q_m.lock(); - --_waiting; - if (_die) { - _q_m.unlock(); - return -1; - } - } - - // Move item from _q list to a dummy list here to avoid copying packet - pkt.splice(pkt.end(),_q,_q.begin()); - - _q_m.unlock(); - - try { - pkt.front().tryDecode(RR,true); - } catch ( ... ) {} // drop invalids - - return 1; -} - -} // namespace ZeroTier diff --git a/node/DeferredPackets.hpp b/node/DeferredPackets.hpp deleted file mode 100644 index a9855396..00000000 --- a/node/DeferredPackets.hpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 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 . - */ - -#ifndef ZT_DEFERREDPACKETS_HPP -#define ZT_DEFERREDPACKETS_HPP - -#include - -#include "Constants.hpp" -#include "SharedPtr.hpp" -#include "Mutex.hpp" -#include "DeferredPackets.hpp" -#include "BinarySemaphore.hpp" - -/** - * Maximum number of deferred packets - */ -#define ZT_DEFFEREDPACKETS_MAX 256 - -namespace ZeroTier { - -class IncomingPacket; -class RuntimeEnvironment; - -/** - * Deferred packets - * - * IncomingPacket can defer its decoding this way by enqueueing itself here. - * When this is done, deferredDecode() is called later. This is done for - * operations that may be expensive to allow them to potentially be handled - * in the background or rate limited to maintain quality of service for more - * routine operations. - */ -class DeferredPackets -{ -public: - DeferredPackets(const RuntimeEnvironment *renv); - ~DeferredPackets(); - - /** - * Enqueue a packet - * - * @param pkt Packet to process later (possibly in the background) - * @return False if queue is full - */ - bool enqueue(IncomingPacket *pkt); - - /** - * Wait for and then process a deferred packet - * - * If we are shutting down (in destructor), this returns -1 and should - * not be called again. Otherwise it returns the number of packets - * processed. - * - * @return Number processed or -1 if shutting down - */ - int process(); - -private: - std::list _q; - const RuntimeEnvironment *const RR; - volatile int _waiting; - volatile bool _die; - Mutex _q_m; - BinarySemaphore _q_s; -}; - -} // namespace ZeroTier - -#endif diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 029570f1..ca609418 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -36,7 +36,6 @@ #include "World.hpp" #include "Cluster.hpp" #include "Node.hpp" -#include "DeferredPackets.hpp" #include "Filter.hpp" #include "CertificateOfMembership.hpp" #include "Capability.hpp" @@ -44,7 +43,7 @@ namespace ZeroTier { -bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,bool deferred) +bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR) { const Address sourceAddress(source()); @@ -64,18 +63,11 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,bool deferred) return true; } } else if ((c == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE)&&(verb() == Packet::VERB_HELLO)) { - // Unencrypted HELLOs require some potentially expensive verification, so - // do this in the background if background processing is enabled. - if ((RR->dpEnabled > 0)&&(!deferred)) { - RR->dp->enqueue(this); - return true; // 'handled' via deferring to background thread(s) - } else { - // A null pointer for peer to _doHELLO() tells it to run its own - // special internal authentication logic. This is done for unencrypted - // HELLOs to learn new identities, etc. - SharedPtr tmp; - return _doHELLO(RR,tmp); - } + // A null pointer for peer to _doHELLO() tells it to run its own + // special internal authentication logic. This is done for unencrypted + // HELLOs to learn new identities, etc. + SharedPtr tmp; + return _doHELLO(RR,tmp); } SharedPtr peer(RR->topology->getPeer(sourceAddress)); diff --git a/node/IncomingPacket.hpp b/node/IncomingPacket.hpp index bfb30a5e..558dfaa2 100644 --- a/node/IncomingPacket.hpp +++ b/node/IncomingPacket.hpp @@ -118,21 +118,12 @@ public: * about whether the packet was valid. A rejection is 'complete.' * * Once true is returned, this must not be called again. The packet's state - * may no longer be valid. The only exception is deferred decoding. In this - * case true is returned to indicate to the normal decode path that it is - * finished with the packet. The packet will have added itself to the - * deferred queue and will expect tryDecode() to be called one more time - * with deferred set to true. - * - * Deferred decoding is performed by DeferredPackets.cpp and should not be - * done elsewhere. Under deferred decoding packets only get one shot and - * so the return value of tryDecode() is ignored. + * may no longer be valid. * * @param RR Runtime environment - * @param deferred If true, this is a deferred decode and the return is ignored * @return True if decoding and processing is complete, false if caller should try again */ - bool tryDecode(const RuntimeEnvironment *RR,bool deferred); + bool tryDecode(const RuntimeEnvironment *RR); /** * @return Time of packet receipt / start of decode diff --git a/node/Node.cpp b/node/Node.cpp index e5d04e31..f04559db 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -37,7 +37,6 @@ #include "Identity.hpp" #include "SelfAwareness.hpp" #include "Cluster.hpp" -#include "DeferredPackets.hpp" const struct sockaddr_storage ZT_SOCKADDR_NULL = {0}; @@ -108,9 +107,7 @@ Node::Node( RR->mc = new Multicaster(RR); RR->topology = new Topology(RR); RR->sa = new SelfAwareness(RR); - RR->dp = new DeferredPackets(RR); } catch ( ... ) { - delete RR->dp; delete RR->sa; delete RR->topology; delete RR->mc; @@ -127,8 +124,6 @@ Node::~Node() _networks.clear(); // ensure that networks are destroyed before shutdow - RR->dpEnabled = 0; - delete RR->dp; delete RR->sa; delete RR->topology; delete RR->mc; @@ -621,18 +616,6 @@ void Node::clusterStatus(ZT_ClusterStatus *cs) memset(cs,0,sizeof(ZT_ClusterStatus)); } -void Node::backgroundThreadMain() -{ - ++RR->dpEnabled; - for(;;) { - try { - if (RR->dp->process() < 0) - break; - } catch ( ... ) {} // sanity check -- should not throw - } - --RR->dpEnabled; -} - /****************************************************************************/ /* Node methods used only within node/ */ /****************************************************************************/ @@ -1009,13 +992,6 @@ void ZT_Node_setTrustedPaths(ZT_Node *node,const struct sockaddr_storage *networ } catch ( ... ) {} } -void ZT_Node_backgroundThreadMain(ZT_Node *node) -{ - try { - reinterpret_cast(node)->backgroundThreadMain(); - } catch ( ... ) {} -} - void ZT_version(int *major,int *minor,int *revision) { if (major) *major = ZEROTIER_ONE_VERSION_MAJOR; diff --git a/node/Node.hpp b/node/Node.hpp index 0a39d1ee..98c4fd7c 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -117,18 +117,9 @@ public: void clusterRemoveMember(unsigned int memberId); void clusterHandleIncomingMessage(const void *msg,unsigned int len); void clusterStatus(ZT_ClusterStatus *cs); - void backgroundThreadMain(); // Internal functions ------------------------------------------------------ - /** - * Convenience threadMain() for easy background thread launch - * - * This allows background threads to be launched with Thread::start - * that will run against this node. - */ - inline void threadMain() throw() { this->backgroundThreadMain(); } - /** * @return Time as of last call to run() */ diff --git a/node/RuntimeEnvironment.hpp b/node/RuntimeEnvironment.hpp index 1f527733..7ba1c989 100644 --- a/node/RuntimeEnvironment.hpp +++ b/node/RuntimeEnvironment.hpp @@ -35,7 +35,6 @@ class Multicaster; class NetworkController; class SelfAwareness; class Cluster; -class DeferredPackets; /** * Holds global state for an instance of ZeroTier::Node @@ -51,11 +50,9 @@ public: ,mc((Multicaster *)0) ,topology((Topology *)0) ,sa((SelfAwareness *)0) - ,dp((DeferredPackets *)0) #ifdef ZT_ENABLE_CLUSTER ,cluster((Cluster *)0) #endif - ,dpEnabled(0) { } @@ -82,15 +79,9 @@ public: Multicaster *mc; Topology *topology; SelfAwareness *sa; - DeferredPackets *dp; - #ifdef ZT_ENABLE_CLUSTER Cluster *cluster; #endif - - // This is set to >0 if background threads are waiting on deferred - // packets, otherwise 'dp' should not be used. - volatile int dpEnabled; }; } // namespace ZeroTier diff --git a/node/Switch.cpp b/node/Switch.cpp index 41756aa9..33b08429 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -165,7 +165,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from for(unsigned int f=1;ffrag0.append(rq->frags[f - 1].payload(),rq->frags[f - 1].payloadLength()); - if (rq->frag0.tryDecode(RR,false)) { + if (rq->frag0.tryDecode(RR)) { rq->timestamp = 0; // packet decoded, free entry } else { rq->complete = true; // set complete flag but leave entry since it probably needs WHOIS or something @@ -264,7 +264,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from for(unsigned int f=1;ftotalFragments;++f) rq->frag0.append(rq->frags[f - 1].payload(),rq->frags[f - 1].payloadLength()); - if (rq->frag0.tryDecode(RR,false)) { + if (rq->frag0.tryDecode(RR)) { rq->timestamp = 0; // packet decoded, free entry } else { rq->complete = true; // set complete flag but leave entry since it probably needs WHOIS or something @@ -277,7 +277,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from } else { // Packet is unfragmented, so just process it IncomingPacket packet(data,len,localAddr,fromAddr,now); - if (!packet.tryDecode(RR,false)) { + if (!packet.tryDecode(RR)) { Mutex::Lock _l(_rxQueue_m); RXQueueEntry *rq = &(_rxQueue[ZT_RX_QUEUE_SIZE - 1]); unsigned long i = ZT_RX_QUEUE_SIZE - 1; @@ -705,7 +705,7 @@ void Switch::doAnythingWaitingForPeer(const SharedPtr &peer) while (i) { RXQueueEntry *rq = &(_rxQueue[--i]); if ((rq->timestamp)&&(rq->complete)) { - if (rq->frag0.tryDecode(RR,false)) + if (rq->frag0.tryDecode(RR)) rq->timestamp = 0; } } diff --git a/objects.mk b/objects.mk index 18e330b3..99cf1a72 100644 --- a/objects.mk +++ b/objects.mk @@ -3,7 +3,6 @@ OBJS=\ node/Capability.o \ node/CertificateOfMembership.o \ node/Cluster.o \ - node/DeferredPackets.o \ node/Filter.o \ node/Identity.o \ node/IncomingPacket.o \ diff --git a/service/OneService.cpp b/service/OneService.cpp index 460eb1c9..0c9b0b8e 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -864,10 +864,6 @@ public: } } - // Start two background threads to handle expensive ops out of line - Thread::start(_node); - Thread::start(_node); - _nextBackgroundTaskDeadline = 0; uint64_t clockShouldBe = OSUtils::now(); _lastRestart = clockShouldBe; -- cgit v1.2.3 From 402d99ea8d73d804294795cab12fceb6fe4234fe Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 16 Aug 2016 14:07:11 -0700 Subject: C++11 mode build fix. --- make-mac.mk | 2 +- service/OneService.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'service/OneService.cpp') diff --git a/make-mac.mk b/make-mac.mk index 09e04eab..63ffc3c8 100644 --- a/make-mac.mk +++ b/make-mac.mk @@ -65,7 +65,7 @@ else STRIP=strip endif -CXXFLAGS=$(CFLAGS) -fno-rtti -mmacosx-version-min=10.7 -std=c++11 -stdlib=libc++ +CXXFLAGS=$(CFLAGS) -mmacosx-version-min=10.7 -std=c++11 -stdlib=libc++ all: one diff --git a/service/OneService.cpp b/service/OneService.cpp index 0c9b0b8e..5c65dcc2 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1119,13 +1119,13 @@ public: for(std::vector::iterator ip(n.managedIps.begin());ip!=n.managedIps.end();++ip) { if (std::find(newManagedIps.begin(),newManagedIps.end(),*ip) == newManagedIps.end()) { if (!n.tap->removeIp(*ip)) - fprintf(stderr,"ERROR: unable to remove ip address %s"ZT_EOL_S, ip->toString().c_str()); + fprintf(stderr,"ERROR: unable to remove ip address %s" ZT_EOL_S, ip->toString().c_str()); } } for(std::vector::iterator ip(newManagedIps.begin());ip!=newManagedIps.end();++ip) { if (std::find(n.managedIps.begin(),n.managedIps.end(),*ip) == n.managedIps.end()) { if (!n.tap->addIp(*ip)) - fprintf(stderr,"ERROR: unable to add ip address %s"ZT_EOL_S, ip->toString().c_str()); + fprintf(stderr,"ERROR: unable to add ip address %s" ZT_EOL_S, ip->toString().c_str()); } } @@ -1468,11 +1468,11 @@ public: #ifdef __WINDOWS__ FILE *tapFailLog = fopen((_homePath + ZT_PATH_SEPARATOR_S"port_error_log.txt").c_str(),"a"); if (tapFailLog) { - fprintf(tapFailLog,"%.16llx: %s"ZT_EOL_S,(unsigned long long)nwid,exc.what()); + fprintf(tapFailLog,"%.16llx: %s" ZT_EOL_S,(unsigned long long)nwid,exc.what()); fclose(tapFailLog); } #else - fprintf(stderr,"ERROR: unable to configure virtual network port: %s"ZT_EOL_S,exc.what()); + fprintf(stderr,"ERROR: unable to configure virtual network port: %s" ZT_EOL_S,exc.what()); #endif _nets.erase(nwid); return -999; @@ -1531,7 +1531,7 @@ public: case ZT_EVENT_TRACE: { if (metaData) { - ::fprintf(stderr,"%s"ZT_EOL_S,(const char *)metaData); + ::fprintf(stderr,"%s" ZT_EOL_S,(const char *)metaData); ::fflush(stderr); } } break; -- cgit v1.2.3 From a13f4d8353cf6a7f612333f00282b27cfe2ce9b3 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 17 Aug 2016 10:42:32 -0700 Subject: We now always build the controller in ZeroTier One, at least for desktop and server targets. Also means that ZeroTier One now requires C++11. (Still keeping C++11 out of the core in node/ though.) --- controller/EmbeddedNetworkController.cpp | 1462 ++++++++++++++++++++++++++++++ controller/EmbeddedNetworkController.hpp | 173 ++++ controller/SqliteNetworkController.cpp | 1462 ------------------------------ controller/SqliteNetworkController.hpp | 173 ---- make-linux.mk | 6 - make-mac.mk | 6 - objects.mk | 1 + selftest.cpp | 4 - service/ControlPlane.cpp | 20 +- service/ControlPlane.hpp | 10 +- service/OneService.cpp | 25 +- service/OneService.hpp | 12 - 12 files changed, 1646 insertions(+), 1708 deletions(-) create mode 100644 controller/EmbeddedNetworkController.cpp create mode 100644 controller/EmbeddedNetworkController.hpp delete mode 100644 controller/SqliteNetworkController.cpp delete mode 100644 controller/SqliteNetworkController.hpp (limited to 'service/OneService.cpp') diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp new file mode 100644 index 00000000..479a65f5 --- /dev/null +++ b/controller/EmbeddedNetworkController.cpp @@ -0,0 +1,1462 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2015 ZeroTier, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "../include/ZeroTierOne.h" +#include "../node/Constants.hpp" + +#include "EmbeddedNetworkController.hpp" + +#include "../node/Node.hpp" +#include "../node/Utils.hpp" +#include "../node/CertificateOfMembership.hpp" +#include "../node/NetworkConfig.hpp" +#include "../node/Dictionary.hpp" +#include "../node/InetAddress.hpp" +#include "../node/MAC.hpp" +#include "../node/Address.hpp" + +using json = nlohmann::json; + +// API version reported via JSON control plane +#define ZT_NETCONF_CONTROLLER_API_VERSION 3 + +// Number of requests to remember in member history +#define ZT_NETCONF_DB_MEMBER_HISTORY_LENGTH 8 + +// Min duration between requests for an address/nwid combo to prevent floods +#define ZT_NETCONF_MIN_REQUEST_PERIOD 1000 + +// Nodes are considered active if they've queried in less than this long +#define ZT_NETCONF_NODE_ACTIVE_THRESHOLD ((ZT_NETWORK_AUTOCONF_DELAY * 2) + 5000) + +namespace ZeroTier { + +static json _renderRule(ZT_VirtualNetworkRule &rule) +{ + char tmp[128]; + json r = json::object(); + r["not"] = ((rule.t & 0x80) != 0); + switch((rule.t) & 0x7f) { + case ZT_NETWORK_RULE_ACTION_DROP: + r["type"] = "ACTION_DROP"; + break; + case ZT_NETWORK_RULE_ACTION_ACCEPT: + r["type"] = "ACTION_ACCEPT"; + break; + case ZT_NETWORK_RULE_ACTION_TEE: + r["type"] = "ACTION_TEE"; + r["zt"] = Address(rule.v.zt).toString(); + break; + case ZT_NETWORK_RULE_ACTION_REDIRECT: + r["type"] = "ACTION_REDIRECT"; + r["zt"] = Address(rule.v.zt).toString(); + break; + case ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS: + r["type"] = "MATCH_SOURCE_ZEROTIER_ADDRESS"; + r["zt"] = Address(rule.v.zt).toString(); + break; + case ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS: + r["type"] = "MATCH_DEST_ZEROTIER_ADDRESS"; + r["zt"] = Address(rule.v.zt).toString(); + break; + case ZT_NETWORK_RULE_MATCH_VLAN_ID: + r["type"] = "MATCH_VLAN_ID"; + r["vlanId"] = (uint64_t)rule.v.vlanId; + break; + case ZT_NETWORK_RULE_MATCH_VLAN_PCP: + r["type"] = "MATCH_VLAN_PCP"; + r["vlanPcp"] = (uint64_t)rule.v.vlanPcp; + break; + case ZT_NETWORK_RULE_MATCH_VLAN_DEI: + r["type"] = "MATCH_VLAN_DEI"; + r["vlanDei"] = (uint64_t)rule.v.vlanDei; + break; + case ZT_NETWORK_RULE_MATCH_ETHERTYPE: + r["type"] = "MATCH_ETHERTYPE"; + r["etherType"] = (uint64_t)rule.v.etherType; + break; + case ZT_NETWORK_RULE_MATCH_MAC_SOURCE: + r["type"] = "MATCH_MAC_SOURCE"; + Utils::snprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]); + r["mac"] = tmp; + break; + case ZT_NETWORK_RULE_MATCH_MAC_DEST: + r["type"] = "MATCH_MAC_DEST"; + Utils::snprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]); + r["mac"] = tmp; + break; + case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE: + r["type"] = "MATCH_IPV4_SOURCE"; + r["ip"] = InetAddress(&(rule.v.ipv4.ip),4,(unsigned int)rule.v.ipv4.mask).toString(); + break; + case ZT_NETWORK_RULE_MATCH_IPV4_DEST: + r["type"] = "MATCH_IPV4_DEST"; + r["ip"] = InetAddress(&(rule.v.ipv4.ip),4,(unsigned int)rule.v.ipv4.mask).toString(); + break; + case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE: + r["type"] = "MATCH_IPV6_SOURCE"; + r["ip"] = InetAddress(rule.v.ipv6.ip,16,(unsigned int)rule.v.ipv6.mask).toString(); + break; + case ZT_NETWORK_RULE_MATCH_IPV6_DEST: + r["type"] = "MATCH_IPV6_DEST"; + r["ip"] = InetAddress(rule.v.ipv6.ip,16,(unsigned int)rule.v.ipv6.mask).toString(); + break; + case ZT_NETWORK_RULE_MATCH_IP_TOS: + r["type"] = "MATCH_IP_TOS"; + r["ipTos"] = (uint64_t)rule.v.ipTos; + break; + case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL: + r["type"] = "MATCH_IP_PROTOCOL"; + r["ipProtocol"] = (uint64_t)rule.v.ipProtocol; + break; + case ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE: + r["type"] = "MATCH_IP_SOURCE_PORT_RANGE"; + r["start"] = (uint64_t)rule.v.port[0]; + r["end"] = (uint64_t)rule.v.port[1]; + break; + case ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE: + r["type"] = "MATCH_IP_DEST_PORT_RANGE"; + r["start"] = (uint64_t)rule.v.port[0]; + r["end"] = (uint64_t)rule.v.port[1]; + break; + case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS: + r["type"] = "MATCH_CHARACTERISTICS"; + Utils::snprintf(tmp,sizeof(tmp),"%.16llx",rule.v.characteristics[0]); + r["mask"] = tmp; + Utils::snprintf(tmp,sizeof(tmp),"%.16llx",rule.v.characteristics[1]); + r["value"] = tmp; + break; + case ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE: + r["type"] = "MATCH_FRAME_SIZE_RANGE"; + r["start"] = (uint64_t)rule.v.frameSize[0]; + r["end"] = (uint64_t)rule.v.frameSize[1]; + break; + case ZT_NETWORK_RULE_MATCH_TAGS_SAMENESS: + r["type"] = "MATCH_TAGS_SAMENESS"; + r["id"] = (uint64_t)rule.v.tag.id; + r["value"] = (uint64_t)rule.v.tag.value; + break; + case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND: + r["type"] = "MATCH_TAGS_BITWISE_AND"; + r["id"] = (uint64_t)rule.v.tag.id; + r["value"] = (uint64_t)rule.v.tag.value; + break; + case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR: + r["type"] = "MATCH_TAGS_BITWISE_OR"; + r["id"] = (uint64_t)rule.v.tag.id; + r["value"] = (uint64_t)rule.v.tag.value; + break; + case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR: + r["type"] = "MATCH_TAGS_BITWISE_XOR"; + r["id"] = (uint64_t)rule.v.tag.id; + r["value"] = (uint64_t)rule.v.tag.value; + break; + } + return r; +} + +static bool _parseRule(const json &r,ZT_VirtualNetworkRule &rule) +{ + if (r.is_object()) + return false; + std::string t = r["type"]; + memset(&rule,0,sizeof(ZT_VirtualNetworkRule)); + if (r.value("not",false)) + rule.t = 0x80; + else rule.t = 0x00; + if (t == "ACTION_DROP") { + rule.t |= ZT_NETWORK_RULE_ACTION_DROP; + return true; + } else if (t == "ACTION_ACCEPT") { + rule.t |= ZT_NETWORK_RULE_ACTION_ACCEPT; + return true; + } else if (t == "ACTION_TEE") { + rule.t |= ZT_NETWORK_RULE_ACTION_TEE; + rule.v.zt = Utils::hexStrToU64(r.value("zt","0").c_str()) & 0xffffffffffULL; + return true; + } else if (t == "ACTION_REDIRECT") { + rule.t |= ZT_NETWORK_RULE_ACTION_REDIRECT; + rule.v.zt = Utils::hexStrToU64(r.value("zt","0").c_str()) & 0xffffffffffULL; + return true; + } else if (t == "MATCH_SOURCE_ZEROTIER_ADDRESS") { + rule.t |= ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS; + rule.v.zt = Utils::hexStrToU64(r.value("zt","0").c_str()) & 0xffffffffffULL; + return true; + } else if (t == "MATCH_DEST_ZEROTIER_ADDRESS") { + rule.t |= ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS; + rule.v.zt = Utils::hexStrToU64(r.value("zt","0").c_str()) & 0xffffffffffULL; + return true; + } else if (t == "MATCH_VLAN_ID") { + rule.t |= ZT_NETWORK_RULE_MATCH_VLAN_ID; + rule.v.vlanId = (uint16_t)(r.value("vlanId",0ULL) & 0xffffULL); + return true; + } else if (t == "MATCH_VLAN_PCP") { + rule.t |= ZT_NETWORK_RULE_MATCH_VLAN_PCP; + rule.v.vlanPcp = (uint8_t)(r.value("vlanPcp",0ULL) & 0xffULL); + return true; + } else if (t == "MATCH_VLAN_DEI") { + rule.t |= ZT_NETWORK_RULE_MATCH_VLAN_DEI; + rule.v.vlanDei = (uint8_t)(r.value("vlanDei",0ULL) & 0xffULL); + return true; + } else if (t == "MATCH_ETHERTYPE") { + rule.t |= ZT_NETWORK_RULE_MATCH_ETHERTYPE; + rule.v.etherType = (uint16_t)(r.value("etherType",0ULL) & 0xffffULL); + return true; + } else if (t == "MATCH_MAC_SOURCE") { + rule.t |= ZT_NETWORK_RULE_MATCH_MAC_SOURCE; + const std::string mac(r.value("mac","0")); + Utils::unhex(mac.c_str(),(unsigned int)mac.length(),rule.v.mac,6); + return true; + } else if (t == "MATCH_MAC_DEST") { + rule.t |= ZT_NETWORK_RULE_MATCH_MAC_DEST; + const std::string mac(r.value("mac","0")); + Utils::unhex(mac.c_str(),(unsigned int)mac.length(),rule.v.mac,6); + return true; + } else if (t == "MATCH_IPV4_SOURCE") { + rule.t |= ZT_NETWORK_RULE_MATCH_IPV4_SOURCE; + InetAddress ip(r.value("ip","0.0.0.0")); + rule.v.ipv4.ip = reinterpret_cast(&ip)->sin_addr.s_addr; + rule.v.ipv4.mask = Utils::ntoh(reinterpret_cast(&ip)->sin_port) & 0xff; + if (rule.v.ipv4.mask > 32) rule.v.ipv4.mask = 32; + return true; + } else if (t == "MATCH_IPV4_DEST") { + rule.t |= ZT_NETWORK_RULE_MATCH_IPV4_DEST; + InetAddress ip(r.value("ip","0.0.0.0")); + rule.v.ipv4.ip = reinterpret_cast(&ip)->sin_addr.s_addr; + rule.v.ipv4.mask = Utils::ntoh(reinterpret_cast(&ip)->sin_port) & 0xff; + if (rule.v.ipv4.mask > 32) rule.v.ipv4.mask = 32; + return true; + } else if (t == "MATCH_IPV6_SOURCE") { + rule.t |= ZT_NETWORK_RULE_MATCH_IPV6_SOURCE; + InetAddress ip(r.value("ip","::0")); + memcpy(rule.v.ipv6.ip,reinterpret_cast(&ip)->sin6_addr.s6_addr,16); + rule.v.ipv6.mask = Utils::ntoh(reinterpret_cast(&ip)->sin6_port) & 0xff; + if (rule.v.ipv6.mask > 128) rule.v.ipv6.mask = 128; + return true; + } else if (t == "MATCH_IPV6_DEST") { + rule.t |= ZT_NETWORK_RULE_MATCH_IPV6_DEST; + InetAddress ip(r.value("ip","::0")); + memcpy(rule.v.ipv6.ip,reinterpret_cast(&ip)->sin6_addr.s6_addr,16); + rule.v.ipv6.mask = Utils::ntoh(reinterpret_cast(&ip)->sin6_port) & 0xff; + if (rule.v.ipv6.mask > 128) rule.v.ipv6.mask = 128; + return true; + } else if (t == "MATCH_IP_TOS") { + rule.t |= ZT_NETWORK_RULE_MATCH_IP_TOS; + rule.v.ipTos = (uint8_t)(r.value("ipTos",0ULL) & 0xffULL); + return true; + } else if (t == "MATCH_IP_PROTOCOL") { + rule.t |= ZT_NETWORK_RULE_MATCH_IP_PROTOCOL; + rule.v.ipProtocol = (uint8_t)(r.value("ipProtocol",0ULL) & 0xffULL); + return true; + } else if (t == "MATCH_IP_SOURCE_PORT_RANGE") { + rule.t |= ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE; + rule.v.port[0] = (uint16_t)(r.value("start",0ULL) & 0xffffULL); + rule.v.port[1] = (uint16_t)(r.value("end",0ULL) & 0xffffULL); + return true; + } else if (t == "MATCH_IP_DEST_PORT_RANGE") { + rule.t |= ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE; + rule.v.port[0] = (uint16_t)(r.value("start",0ULL) & 0xffffULL); + rule.v.port[1] = (uint16_t)(r.value("end",0ULL) & 0xffffULL); + return true; + } else if (t == "MATCH_CHARACTERISTICS") { + rule.t |= ZT_NETWORK_RULE_MATCH_CHARACTERISTICS; + if (r.count("mask")) { + auto v = r["mask"]; + if (v.is_number()) { + rule.v.characteristics[0] = v; + } else { + std::string tmp = v; + rule.v.characteristics[0] = Utils::hexStrToU64(tmp.c_str()); + } + } + if (r.count("value")) { + auto v = r["value"]; + if (v.is_number()) { + rule.v.characteristics[1] = v; + } else { + std::string tmp = v; + rule.v.characteristics[1] = Utils::hexStrToU64(tmp.c_str()); + } + } + return true; + } else if (t == "MATCH_FRAME_SIZE_RANGE") { + rule.t |= ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE; + rule.v.frameSize[0] = (uint16_t)(Utils::hexStrToU64(r.value("start","0").c_str()) & 0xffffULL); + rule.v.frameSize[1] = (uint16_t)(Utils::hexStrToU64(r.value("end","0").c_str()) & 0xffffULL); + return true; + } else if (t == "MATCH_TAGS_SAMENESS") { + rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_SAMENESS; + rule.v.tag.id = (uint32_t)(Utils::hexStrToU64(r.value("id","0").c_str()) & 0xffffffffULL); + rule.v.tag.value = (uint32_t)(Utils::hexStrToU64(r.value("value","0").c_str()) & 0xffffffffULL); + return true; + } else if (t == "MATCH_TAGS_BITWISE_AND") { + rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND; + rule.v.tag.id = (uint32_t)(Utils::hexStrToU64(r.value("id","0").c_str()) & 0xffffffffULL); + rule.v.tag.value = (uint32_t)(Utils::hexStrToU64(r.value("value","0").c_str()) & 0xffffffffULL); + return true; + } else if (t == "MATCH_TAGS_BITWISE_OR") { + rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR; + rule.v.tag.id = (uint32_t)(Utils::hexStrToU64(r.value("id","0").c_str()) & 0xffffffffULL); + rule.v.tag.value = (uint32_t)(Utils::hexStrToU64(r.value("value","0").c_str()) & 0xffffffffULL); + return true; + } else if (t == "MATCH_TAGS_BITWISE_XOR") { + rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR; + rule.v.tag.id = (uint32_t)(Utils::hexStrToU64(r.value("id","0").c_str()) & 0xffffffffULL); + rule.v.tag.value = (uint32_t)(Utils::hexStrToU64(r.value("value","0").c_str()) & 0xffffffffULL); + return true; + } + return false; +} + +EmbeddedNetworkController::EmbeddedNetworkController(Node *node,const char *dbPath) : + _node(node), + _path(dbPath) +{ + OSUtils::mkdir(dbPath); + /* + if (sqlite3_open_v2(dbPath,&_db,SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE,(const char *)0) != SQLITE_OK) + throw std::runtime_error("SqliteNetworkController cannot open database file"); + sqlite3_busy_timeout(_db,10000); + + sqlite3_exec(_db,"PRAGMA synchronous = OFF",0,0,0); + sqlite3_exec(_db,"PRAGMA journal_mode = MEMORY",0,0,0); + + sqlite3_stmt *s = (sqlite3_stmt *)0; + if ((sqlite3_prepare_v2(_db,"SELECT v FROM Config WHERE k = 'schemaVersion';",-1,&s,(const char **)0) == SQLITE_OK)&&(s)) { + int schemaVersion = -1234; + if (sqlite3_step(s) == SQLITE_ROW) { + schemaVersion = sqlite3_column_int(s,0); + } + + sqlite3_finalize(s); + + if (schemaVersion == -1234) { + sqlite3_close(_db); + throw std::runtime_error("SqliteNetworkController schemaVersion not found in Config table (init failure?)"); + } + + if (schemaVersion < 2) { + // Create NodeHistory table to upgrade from version 1 to version 2 + if (sqlite3_exec(_db, + "CREATE TABLE NodeHistory (\n" + " nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n" + " networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n" + " networkVisitCounter INTEGER NOT NULL DEFAULT(0),\n" + " networkRequestAuthorized INTEGER NOT NULL DEFAULT(0),\n" + " requestTime INTEGER NOT NULL DEFAULT(0),\n" + " clientMajorVersion INTEGER NOT NULL DEFAULT(0),\n" + " clientMinorVersion INTEGER NOT NULL DEFAULT(0),\n" + " clientRevision INTEGER NOT NULL DEFAULT(0),\n" + " networkRequestMetaData VARCHAR(1024),\n" + " fromAddress VARCHAR(128)\n" + ");\n" + "CREATE INDEX NodeHistory_nodeId ON NodeHistory (nodeId);\n" + "CREATE INDEX NodeHistory_networkId ON NodeHistory (networkId);\n" + "CREATE INDEX NodeHistory_requestTime ON NodeHistory (requestTime);\n" + "UPDATE \"Config\" SET \"v\" = 2 WHERE \"k\" = 'schemaVersion';\n" + ,0,0,0) != SQLITE_OK) { + char err[1024]; + Utils::snprintf(err,sizeof(err),"SqliteNetworkController cannot upgrade the database to version 2: %s",sqlite3_errmsg(_db)); + sqlite3_close(_db); + throw std::runtime_error(err); + } else { + schemaVersion = 2; + } + } + + if (schemaVersion < 3) { + // Create Route table to upgrade from version 2 to version 3 and migrate old + // data. Also delete obsolete Gateway table that was never actually used, and + // migrate Network flags to a bitwise flags field instead of ASCII cruft. + if (sqlite3_exec(_db, + "DROP TABLE Gateway;\n" + "CREATE TABLE Route (\n" + " networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n" + " target blob(16) NOT NULL,\n" + " via blob(16),\n" + " targetNetmaskBits integer NOT NULL,\n" + " ipVersion integer NOT NULL,\n" + " flags integer NOT NULL,\n" + " metric integer NOT NULL\n" + ");\n" + "CREATE INDEX Route_networkId ON Route (networkId);\n" + "INSERT INTO Route SELECT DISTINCT networkId,\"ip\" AS \"target\",NULL AS \"via\",ipNetmaskBits AS targetNetmaskBits,ipVersion,0 AS \"flags\",0 AS \"metric\" FROM IpAssignment WHERE nodeId IS NULL AND \"type\" = 1;\n" + "ALTER TABLE Network ADD COLUMN \"flags\" integer NOT NULL DEFAULT(0);\n" + "UPDATE Network SET \"flags\" = (\"flags\" | 1) WHERE v4AssignMode = 'zt';\n" + "UPDATE Network SET \"flags\" = (\"flags\" | 2) WHERE v6AssignMode = 'rfc4193';\n" + "UPDATE Network SET \"flags\" = (\"flags\" | 4) WHERE v6AssignMode = '6plane';\n" + "ALTER TABLE Member ADD COLUMN \"flags\" integer NOT NULL DEFAULT(0);\n" + "DELETE FROM IpAssignment WHERE nodeId IS NULL AND \"type\" = 1;\n" + "UPDATE \"Config\" SET \"v\" = 3 WHERE \"k\" = 'schemaVersion';\n" + ,0,0,0) != SQLITE_OK) { + char err[1024]; + Utils::snprintf(err,sizeof(err),"SqliteNetworkController cannot upgrade the database to version 3: %s",sqlite3_errmsg(_db)); + sqlite3_close(_db); + throw std::runtime_error(err); + } else { + schemaVersion = 3; + } + } + + if (schemaVersion < 4) { + // Turns out this was overkill and a huge performance drag. Will be revisiting this + // more later but for now a brief snapshot of recent history stored in Member is fine. + // Also prepare for implementation of proof of work requests. + if (sqlite3_exec(_db, + "DROP TABLE NodeHistory;\n" + "ALTER TABLE Member ADD COLUMN lastRequestTime integer NOT NULL DEFAULT(0);\n" + "ALTER TABLE Member ADD COLUMN lastPowDifficulty integer NOT NULL DEFAULT(0);\n" + "ALTER TABLE Member ADD COLUMN lastPowTime integer NOT NULL DEFAULT(0);\n" + "ALTER TABLE Member ADD COLUMN recentHistory blob;\n" + "CREATE INDEX Member_networkId_lastRequestTime ON Member(networkId, lastRequestTime);\n" + "UPDATE \"Config\" SET \"v\" = 4 WHERE \"k\" = 'schemaVersion';\n" + ,0,0,0) != SQLITE_OK) { + char err[1024]; + Utils::snprintf(err,sizeof(err),"SqliteNetworkController cannot upgrade the database to version 3: %s",sqlite3_errmsg(_db)); + sqlite3_close(_db); + throw std::runtime_error(err); + } else { + schemaVersion = 4; + } + } + + if (schemaVersion < 5) { + // Upgrade old rough draft Rule table to new release format + if (sqlite3_exec(_db, + "DROP TABLE Relay;\n" + "DROP INDEX Rule_networkId_ruleNo;\n" + "ALTER TABLE \"Rule\" RENAME TO RuleOld;\n" + "CREATE TABLE Rule (\n" + " networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n" + " capId integer,\n" + " ruleNo integer NOT NULL,\n" + " ruleType integer NOT NULL DEFAULT(0),\n" + " \"addr\" blob(16),\n" + " \"int1\" integer,\n" + " \"int2\" integer,\n" + " \"int3\" integer,\n" + " \"int4\" integer\n" + ");\n" + "INSERT INTO \"Rule\" SELECT networkId,(ruleNo*2) AS ruleNo,37 AS \"ruleType\",etherType AS \"int1\" FROM RuleOld WHERE RuleOld.etherType IS NOT NULL AND RuleOld.etherType > 0;\n" + "INSERT INTO \"Rule\" SELECT networkId,((ruleNo*2)+1) AS ruleNo,1 AS \"ruleType\" FROM RuleOld;\n" + "DROP TABLE RuleOld;\n" + "CREATE INDEX Rule_networkId_capId ON Rule (networkId,capId);\n" + "CREATE TABLE MemberTC (\n" + " networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n" + " nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n" + " tagId integer,\n" + " tagValue integer,\n" + " capId integer,\n" + " capMaxCustodyChainLength integer NOT NULL DEFAULT(1)\n" + ");\n" + "CREATE INDEX MemberTC_networkId_nodeId ON MemberTC (networkId,nodeId);\n" + "UPDATE \"Config\" SET \"v\" = 5 WHERE \"k\" = 'schemaVersion';\n" + ,0,0,0) != SQLITE_OK) { + char err[1024]; + Utils::snprintf(err,sizeof(err),"SqliteNetworkController cannot upgrade the database to version 3: %s",sqlite3_errmsg(_db)); + sqlite3_close(_db); + throw std::runtime_error(err); + } else { + schemaVersion = 5; + } + } + + if (schemaVersion != ZT_NETCONF_SQLITE_SCHEMA_VERSION) { + sqlite3_close(_db); + throw std::runtime_error("SqliteNetworkController database schema version mismatch"); + } + } else { + // Prepare statement will fail if Config table doesn't exist, which means our DB + // needs to be initialized. + if (sqlite3_exec(_db,ZT_NETCONF_SCHEMA_SQL"INSERT INTO Config (k,v) VALUES ('schemaVersion',"ZT_NETCONF_SQLITE_SCHEMA_VERSION_STR");",0,0,0) != SQLITE_OK) { + char err[1024]; + Utils::snprintf(err,sizeof(err),"SqliteNetworkController cannot initialize database and/or insert schemaVersion into Config table: %s",sqlite3_errmsg(_db)); + sqlite3_close(_db); + throw std::runtime_error(err); + } + } + + if ( + + (sqlite3_prepare_v2(_db,"SELECT name,private,enableBroadcast,allowPassiveBridging,\"flags\",multicastLimit,creationTime,revision,memberRevisionCounter,(SELECT COUNT(1) FROM Member WHERE Member.networkId = Network.id AND Member.authorized > 0) FROM Network WHERE id = ?",-1,&_sGetNetworkById,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"SELECT revision FROM Network WHERE id = ?",-1,&_sGetNetworkRevision,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"UPDATE Network SET revision = ? WHERE id = ?",-1,&_sSetNetworkRevision,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"INSERT INTO Network (id,name,creationTime,revision) VALUES (?,?,?,1)",-1,&_sCreateNetwork,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"DELETE FROM Network WHERE id = ?",-1,&_sDeleteNetwork,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"SELECT id FROM Network ORDER BY id ASC",-1,&_sListNetworks,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"UPDATE Network SET memberRevisionCounter = (memberRevisionCounter + 1) WHERE id = ?",-1,&_sIncrementMemberRevisionCounter,(const char **)0) != SQLITE_OK) + + ||(sqlite3_prepare_v2(_db,"SELECT identity FROM Node WHERE id = ?",-1,&_sGetNodeIdentity,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"INSERT OR REPLACE INTO Node (id,identity) VALUES (?,?)",-1,&_sCreateOrReplaceNode,(const char **)0) != SQLITE_OK) + + ||(sqlite3_prepare_v2(_db,"INSERT INTO Rule (networkId,ruleNo,nodeId,ztSource,ztDest,vlanId,vlanPcp,vlanDei,) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",-1,&_sCreateRule,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"SELECT ruleNo,nodeId,sourcePort,destPort,vlanId,vlanPcp,etherType,macSource,macDest,ipSource,ipDest,ipTos,ipProtocol,ipSourcePort,ipDestPort,\"flags\",invFlags,\"action\" FROM Rule WHERE networkId = ? ORDER BY ruleNo ASC",-1,&_sListRules,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"DELETE FROM Rule WHERE networkId = ?",-1,&_sDeleteRulesForNetwork,(const char **)0) != SQLITE_OK) + + ||(sqlite3_prepare_v2(_db,"SELECT ipRangeStart,ipRangeEnd FROM IpAssignmentPool WHERE networkId = ? AND ipVersion = ?",-1,&_sGetIpAssignmentPools,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"SELECT ipRangeStart,ipRangeEnd,ipVersion FROM IpAssignmentPool WHERE networkId = ? ORDER BY ipRangeStart ASC",-1,&_sGetIpAssignmentPools2,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"INSERT INTO IpAssignmentPool (networkId,ipRangeStart,ipRangeEnd,ipVersion) VALUES (?,?,?,?)",-1,&_sCreateIpAssignmentPool,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"DELETE FROM IpAssignmentPool WHERE networkId = ?",-1,&_sDeleteIpAssignmentPoolsForNetwork,(const char **)0) != SQLITE_OK) + + ||(sqlite3_prepare_v2(_db,"SELECT ip,ipNetmaskBits,ipVersion FROM IpAssignment WHERE networkId = ? AND nodeId = ? AND \"type\" = 0 ORDER BY ip ASC",-1,&_sGetIpAssignmentsForNode,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"SELECT 1 FROM IpAssignment WHERE networkId = ? AND ip = ? AND ipVersion = ? AND \"type\" = ?",-1,&_sCheckIfIpIsAllocated,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"INSERT INTO IpAssignment (networkId,nodeId,\"type\",ip,ipNetmaskBits,ipVersion) VALUES (?,?,?,?,?,?)",-1,&_sAllocateIp,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"DELETE FROM IpAssignment WHERE networkId = ? AND nodeId = ? AND \"type\" = ?",-1,&_sDeleteIpAllocations,(const char **)0) != SQLITE_OK) + + ||(sqlite3_prepare_v2(_db,"SELECT rowid,authorized,activeBridge,memberRevision,\"flags\",lastRequestTime,recentHistory FROM Member WHERE networkId = ? AND nodeId = ?",-1,&_sGetMember,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"SELECT m.authorized,m.activeBridge,m.memberRevision,n.identity,m.flags,m.lastRequestTime,m.recentHistory FROM Member AS m LEFT OUTER JOIN Node AS n ON n.id = m.nodeId WHERE m.networkId = ? AND m.nodeId = ?",-1,&_sGetMember2,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"INSERT INTO Member (networkId,nodeId,authorized,activeBridge,memberRevision) VALUES (?,?,?,0,(SELECT memberRevisionCounter FROM Network WHERE id = ?))",-1,&_sCreateMember,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"SELECT nodeId FROM Member WHERE networkId = ? AND activeBridge > 0 AND authorized > 0",-1,&_sGetActiveBridges,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"SELECT m.nodeId,m.memberRevision FROM Member AS m WHERE m.networkId = ? ORDER BY m.nodeId ASC",-1,&_sListNetworkMembers,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"UPDATE Member SET authorized = ?,memberRevision = (SELECT memberRevisionCounter FROM Network WHERE id = ?) WHERE rowid = ?",-1,&_sUpdateMemberAuthorized,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"UPDATE Member SET activeBridge = ?,memberRevision = (SELECT memberRevisionCounter FROM Network WHERE id = ?) WHERE rowid = ?",-1,&_sUpdateMemberActiveBridge,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"UPDATE Member SET \"lastRequestTime\" = ?, \"recentHistory\" = ? WHERE rowid = ?",-1,&_sUpdateMemberHistory,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"DELETE FROM Member WHERE networkId = ? AND nodeId = ?",-1,&_sDeleteMember,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"DELETE FROM Member WHERE networkId = ?",-1,&_sDeleteAllNetworkMembers,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"SELECT nodeId,recentHistory FROM Member WHERE networkId = ? AND lastRequestTime >= ?",-1,&_sGetActiveNodesOnNetwork,(const char **)0) != SQLITE_OK) + + ||(sqlite3_prepare_v2(_db,"INSERT INTO Route (networkId,target,via,targetNetmaskBits,ipVersion,flags,metric) VALUES (?,?,?,?,?,?,?)",-1,&_sCreateRoute,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"SELECT DISTINCT target,via,targetNetmaskBits,ipVersion,flags,metric FROM \"Route\" WHERE networkId = ? ORDER BY ipVersion,target,via",-1,&_sGetRoutes,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"DELETE FROM \"Route\" WHERE networkId = ?",-1,&_sDeleteRoutes,(const char **)0) != SQLITE_OK) + + ||(sqlite3_prepare_v2(_db,"SELECT \"v\" FROM \"Config\" WHERE \"k\" = ?",-1,&_sGetConfig,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"INSERT OR REPLACE INTO \"Config\" (\"k\",\"v\") VALUES (?,?)",-1,&_sSetConfig,(const char **)0) != SQLITE_OK) + + ) { + std::string err(std::string("SqliteNetworkController unable to initialize one or more prepared statements: ") + sqlite3_errmsg(_db)); + sqlite3_close(_db); + throw std::runtime_error(err); + } + + sqlite3_reset(_sGetConfig); + sqlite3_bind_text(_sGetConfig,1,"instanceId",10,SQLITE_STATIC); + if (sqlite3_step(_sGetConfig) != SQLITE_ROW) { + unsigned char sr[32]; + Utils::getSecureRandom(sr,32); + for(unsigned int i=0;i<32;++i) + _instanceId.push_back("0123456789abcdef"[(unsigned int)sr[i] & 0xf]); + + sqlite3_reset(_sSetConfig); + sqlite3_bind_text(_sSetConfig,1,"instanceId",10,SQLITE_STATIC); + sqlite3_bind_text(_sSetConfig,2,_instanceId.c_str(),-1,SQLITE_STATIC); + if (sqlite3_step(_sSetConfig) != SQLITE_DONE) + throw std::runtime_error("SqliteNetworkController unable to read or initialize instanceId"); + } else { + const char *iid = reinterpret_cast(sqlite3_column_text(_sGetConfig,0)); + if (!iid) + throw std::runtime_error("SqliteNetworkController unable to read instanceId (it's NULL)"); + _instanceId = iid; + } + +#ifdef ZT_NETCONF_SQLITE_TRACE + sqlite3_trace(_db,sqliteTraceFunc,(void *)0); +#endif + + _backupThread = Thread::start(this); + */ +} + +EmbeddedNetworkController::~EmbeddedNetworkController() +{ +} + +NetworkController::ResultCode EmbeddedNetworkController::doNetworkConfigRequest(const InetAddress &fromAddr,const Identity &signingId,const Identity &identity,uint64_t nwid,const Dictionary &metaData,NetworkConfig &nc) +{ + if (((!signingId)||(!signingId.hasPrivate()))||(signingId.address().toInt() != (nwid >> 24))) { + return NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR; + } + + const uint64_t now = OSUtils::now(); + + // Check rate limit circuit breaker to prevent flooding + { + Mutex::Lock _l(_lastRequestTime_m); + uint64_t &lrt = _lastRequestTime[std::pair(identity.address().toInt(),nwid)]; + if ((now - lrt) <= ZT_NETCONF_MIN_REQUEST_PERIOD) + return NetworkController::NETCONF_QUERY_IGNORE; + lrt = now; + } + + json network(_readJson(_networkJP(nwid,false))); + if (!network.size()) + return NetworkController::NETCONF_QUERY_OBJECT_NOT_FOUND; + const std::string memberJP(_memberJP(nwid,identity.address(),false)); + json member(_readJson(memberJP)); + + { + std::string haveIdStr = member.value("identity",""); + if (haveIdStr.length() > 0) { + try { + if (Identity(haveIdStr.c_str()) != identity) + return NetworkController::NETCONF_QUERY_ACCESS_DENIED; + } catch ( ... ) { + return NetworkController::NETCONF_QUERY_ACCESS_DENIED; + } + } else { + member["identity"] = identity.toString(false); + } + } + + // Make sure these are always present no matter what, and increment member revision since we will always at least log something + member["id"] = identity.address().toString(); + member["address"] = member["id"]; + member["nwid"] = network["id"]; + member["memberRevision"] = member.value("memberRevision",0ULL) + 1; + + // Update member log + { + json rlEntry = json::object(); + rlEntry["ts"] = now; + rlEntry["authorized"] = member["authorized"]; + rlEntry["clientMajorVersion"] = metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION,0); + rlEntry["clientMinorVersion"] = metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MINOR_VERSION,0); + rlEntry["clientRevision"] = metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_REVISION,0); + rlEntry["clientProtocolVersion"] = metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_PROTOCOL_VERSION,0); + if (fromAddr) + rlEntry["fromAddr"] = fromAddr.toString(); + json recentLog = json::array(); + recentLog.push_back(rlEntry); + auto oldLog = member["recentLog"]; + if (oldLog.is_array()) { + for(unsigned long i=0;i= ZT_NETCONF_DB_MEMBER_HISTORY_LENGTH) + break; + } + } + member["recentLog"] = recentLog; + } + + // Stop if network is private and member is not authorized + if ( (network.value("private",true)) && (!member.value("authorized",false)) ) { + _writeJson(memberJP,member); + return NetworkController::NETCONF_QUERY_ACCESS_DENIED; + } + // Else compose and send network config + + nc.networkId = nwid; + nc.type = network.value("private",true) ? ZT_NETWORK_TYPE_PRIVATE : ZT_NETWORK_TYPE_PUBLIC; + nc.timestamp = now; + nc.revision = network.value("revision",0ULL); + nc.issuedTo = identity.address(); + if (network.value("enableBroadcast",true)) nc.flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST; + if (network.value("allowPassiveBridging",false)) nc.flags |= ZT_NETWORKCONFIG_FLAG_ALLOW_PASSIVE_BRIDGING; + Utils::scopy(nc.name,sizeof(nc.name),network.value("name","").c_str()); + nc.multicastLimit = (unsigned int)network.value("multicastLimit",32ULL); + + bool amActiveBridge = false; + { + json ab = network["activeBridges"]; + if (ab.is_array()) { + for(unsigned long i=0;i= ZT_MAX_NETWORK_RULES) + break; + auto rule = rules[i]; + if (_parseRule(rule,nc.rules[nc.ruleCount])) + ++nc.ruleCount; + } + } + + if (routes.is_array()) { + for(unsigned long i=0;i= ZT_MAX_NETWORK_ROUTES) + break; + auto route = routes[i]; + InetAddress t(route.value("target","")); + InetAddress v(route.value("via","")); + if ((t)&&(v)&&(t.ss_family == v.ss_family)) { + ZT_VirtualNetworkRoute *r = &(nc.routes[nc.routeCount]); + *(reinterpret_cast(&(r->target))) = t; + *(reinterpret_cast(&(r->via))) = v; + ++nc.routeCount; + } + } + } + + bool haveManagedIpv4AutoAssignment = false; + bool haveManagedIpv6AutoAssignment = false; // "special" NDP-emulated address types do not count + json ipAssignments = member["ipAssignments"]; + if (ipAssignments.is_array()) { + for(unsigned long i=0;i(&(nc.routes[rk].target))->containsAddress(ip)) ) + routedNetmaskBits = reinterpret_cast(&(nc.routes[rk].target))->netmaskBits(); + } + + if (routedNetmaskBits > 0) { + if (nc.staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES) { + ip.setPort(routedNetmaskBits); + nc.staticIps[nc.staticIpCount++] = ip; + } + if (ip.ss_family == AF_INET) + haveManagedIpv4AutoAssignment = true; + else if (ip.ss_family == AF_INET6) + haveManagedIpv6AutoAssignment = true; + } + } + } else { + ipAssignments = json::array(); + } + + std::set allocatedIps; + bool allocatedIpsLoaded = false; + + if ( (ipAssignmentPools.is_array()) && ((v6AssignMode.is_object())&&(v6AssignMode.value("zt",false))) && (!haveManagedIpv6AutoAssignment) && (!amActiveBridge) ) { + if (!allocatedIpsLoaded) allocatedIps = _getAlreadyAllocatedIps(nwid); + for(unsigned long p=0;((p s[1])&&((e[1] - s[1]) >= 0xffffffffffULL)) { + // First see if we can just cram a ZeroTier ID into the higher 64 bits. If so do that. + xx[0] = Utils::hton(x[0]); + xx[1] = Utils::hton(x[1] + identity.address().toInt()); + } else { + // Otherwise pick random addresses -- this technically doesn't explore the whole range if the lower 64 bit range is >= 1 but that won't matter since that would be huge anyway + Utils::getSecureRandom((void *)xx,16); + if ((e[0] > s[0])) + xx[0] %= (e[0] - s[0]); + else xx[0] = 0; + if ((e[1] > s[1])) + xx[1] %= (e[1] - s[1]); + else xx[1] = 0; + xx[0] = Utils::hton(x[0] + xx[0]); + xx[1] = Utils::hton(x[1] + xx[1]); + } + + InetAddress ip6((const void *)xx,16,0); + + // Check if this IP is within a local-to-Ethernet routed network + int routedNetmaskBits = 0; + for(unsigned int rk=0;rk(&(nc.routes[rk].target))->containsAddress(ip6)) ) + routedNetmaskBits = reinterpret_cast(&(nc.routes[rk].target))->netmaskBits(); + } + + // If it's routed, then try to claim and assign it and if successful end loop + if ((routedNetmaskBits > 0)&&(!allocatedIps.count(ip6))) { + ipAssignments.push_back(ip6.toIpString()); + member["ipAssignments"] = ipAssignments; + ip6.setPort((unsigned int)routedNetmaskBits); + if (nc.staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES) + nc.staticIps[nc.staticIpCount++] = ip6; + haveManagedIpv4AutoAssignment = true; + break; + } + } + } + } + } + } + + if ( (ipAssignmentPools.is_array()) && ((v4AssignMode.is_object())&&(v4AssignMode.value("zt",false))) && (!haveManagedIpv4AutoAssignment) && (!amActiveBridge) ) { + if (!allocatedIpsLoaded) allocatedIps = _getAlreadyAllocatedIps(nwid); + for(unsigned long p=0;((p(&ipRangeStart)->sin_addr.s_addr)); + uint32_t ipRangeEnd = Utils::ntoh((uint32_t)(reinterpret_cast(&ipRangeEnd)->sin_addr.s_addr)); + if ((ipRangeEnd <= ipRangeStart)||(ipRangeStart == 0)) + continue; + uint32_t ipRangeLen = ipRangeEnd - ipRangeStart; + + // Start with the LSB of the member's address + uint32_t ipTrialCounter = (uint32_t)(identity.address().toInt() & 0xffffffff); + + for(uint32_t k=ipRangeStart,trialCount=0;(k<=ipRangeEnd)&&(trialCount < 1000);++k,++trialCount) { + uint32_t ip = (ipRangeLen > 0) ? (ipRangeStart + (ipTrialCounter % ipRangeLen)) : ipRangeStart; + ++ipTrialCounter; + if ((ip & 0x000000ff) == 0x000000ff) + continue; // don't allow addresses that end in .255 + + // Check if this IP is within a local-to-Ethernet routed network + int routedNetmaskBits = 0; + for(unsigned int rk=0;rk(&(nc.routes[rk].target))->sin_addr.s_addr)); + int targetBits = Utils::ntoh((uint16_t)(reinterpret_cast(&(nc.routes[rk].target))->sin_port)); + if ((ip & (0xffffffff << (32 - targetBits))) == targetIp) { + routedNetmaskBits = targetBits; + break; + } + } + } + + InetAddress ip4(Utils::hton(ip),0); + + // If it's routed, then try to claim and assign it and if successful end loop + if ((routedNetmaskBits > 0)&&(!allocatedIps.count(ip4))) { + ipAssignments.push_back(ip4.toIpString()); + member["ipAssignments"] = ipAssignments; + if (nc.staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES) { + struct sockaddr_in *const v4ip = reinterpret_cast(&(nc.staticIps[nc.staticIpCount++])); + v4ip->sin_family = AF_INET; + v4ip->sin_port = Utils::hton((uint16_t)routedNetmaskBits); + v4ip->sin_addr.s_addr = Utils::hton(ip); + } + haveManagedIpv4AutoAssignment = true; + break; + } + } + } + } + } + } + + if (network.value("private",true)) { + CertificateOfMembership com(now,ZT_NETWORK_COM_DEFAULT_REVISION_MAX_DELTA,nwid,identity.address()); + if (com.sign(signingId)) { + nc.com = com; + } else { + return NETCONF_QUERY_INTERNAL_SERVER_ERROR; + } + } + + _writeJson(memberJP,member); + return NetworkController::NETCONF_QUERY_OK; +} + +unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( + const std::vector &path, + const std::map &urlArgs, + const std::map &headers, + const std::string &body, + std::string &responseBody, + std::string &responseContentType) +{ + 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()); + char nwids[24]; + Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid); + + json network(_readJson(_networkJP(nwid,false))); + if (!network.size()) + return 404; + + if (path.size() >= 3) { + + if (path[2] == "member") { + + if (path.size() >= 4) { + const uint64_t address = Utils::hexStrToU64(path[3].c_str()); + + json member(_readJson(_memberJP(nwid,Address(address),false))); + if (!member.size()) + return 404; + + char addrs[24]; + Utils::snprintf(addrs,sizeof(addrs),"%.10llx",address); + + member["clock"] = OSUtils::now(); + responseBody = member.dump(2); + responseContentType = "application/json"; + + return 200; + } else { + + responseBody = "{"; + std::vector members(OSUtils::listSubdirectories((_networkBP(nwid,false) + ZT_PATH_SEPARATOR_S + "member").c_str())); + for(std::vector::iterator i(members.begin());i!=members.end();++i) { + if (i->length() == ZT_ADDRESS_LENGTH_HEX) { + json member(_readJson(_memberJP(nwid,Address(Utils::hexStrToU64(i->c_str())),false))); + if (member.size()) { + responseBody.append((responseBody.length() == 1) ? "\"" : ",\""); + responseBody.append(*i); + responseBody.append("\":"); + const std::string rc = member.value("memberRevision","0"); + responseBody.append(rc); + } + } + } + responseBody.push_back('}'); + responseContentType = "application/json"; + + return 200; + } + + } else if ((path[2] == "active")&&(path.size() == 3)) { + + responseBody = "{"; + std::vector members(OSUtils::listSubdirectories((_networkBP(nwid,false) + ZT_PATH_SEPARATOR_S + "member").c_str())); + const uint64_t threshold = OSUtils::now() - ZT_NETCONF_NODE_ACTIVE_THRESHOLD; + for(std::vector::iterator i(members.begin());i!=members.end();++i) { + if (i->length() == ZT_ADDRESS_LENGTH_HEX) { + json member(_readJson(_memberJP(nwid,Address(Utils::hexStrToU64(i->c_str())),false))); + if (member.size()) { + auto recentLog = member["recentLog"]; + if ((recentLog.is_array())&&(recentLog.size() > 0)) { + auto mostRecentLog = recentLog[0]; + if ((mostRecentLog.is_object())&&((uint64_t)mostRecentLog.value("ts",0ULL) >= threshold)) { + responseBody.append((responseBody.length() == 1) ? "\"" : ",\""); + responseBody.append(*i); + responseBody.append("\":"); + responseBody.append(mostRecentLog.dump()); + } + } + } + } + } + responseBody.push_back('}'); + responseContentType = "application/json"; + return 200; + + } else if ((path[2] == "test")&&(path.size() >= 4)) { + + Mutex::Lock _l(_circuitTests_m); + std::map< uint64_t,_CircuitTestEntry >::iterator cte(_circuitTests.find(Utils::hexStrToU64(path[3].c_str()))); + if ((cte != _circuitTests.end())&&(cte->second.test)) { + + responseBody = "["; + responseBody.append(cte->second.jsonResults); + responseBody.push_back(']'); + responseContentType = "application/json"; + + return 200; + + } // else 404 + + } // else 404 + + } else { + + nlohmann::json o(network); + o["clock"] = OSUtils::now(); + responseBody = o.dump(2); + responseContentType = "application/json"; + return 200; + + } + } else if (path.size() == 1) { + + responseBody = "["; + std::vector networks(OSUtils::listSubdirectories((_path + ZT_PATH_SEPARATOR_S + "network").c_str())); + for(auto i(networks.begin());i!=networks.end();++i) { + if (i->length() == 16) { + responseBody.append((responseBody.length() == 1) ? "\"" : ",\""); + responseBody.append(*i); + responseBody.append("\""); + } + } + responseBody.push_back(']'); + responseContentType = "application/json"; + return 200; + + } // else 404 + + } else { + + char tmp[4096]; + Utils::snprintf(tmp,sizeof(tmp),"{\n\t\"controller\": true,\n\t\"apiVersion\": %d,\n\t\"clock\": %llu\n}\n",ZT_NETCONF_CONTROLLER_API_VERSION,(unsigned long long)OSUtils::now()); + responseBody = tmp; + responseContentType = "application/json"; + return 200; + + } + + return 404; +} + +unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( + const std::vector &path, + const std::map &urlArgs, + const std::map &headers, + const std::string &body, + std::string &responseBody, + std::string &responseContentType) +{ + if (path.empty()) + return 404; + + json b; + try { + b = json::parse(body); + if (!b.is_object()) + return 400; + } catch ( ... ) { + return 400; + } + + if (path[0] == "network") { + + if ((path.size() >= 2)&&(path[1].length() == 16)) { + uint64_t nwid = Utils::hexStrToU64(path[1].c_str()); + char nwids[24]; + Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid); + + if (path.size() >= 3) { + json network(_readJson(_networkJP(nwid,false))); + if (!network.size()) + return 404; + + if ((path.size() == 4)&&(path[2] == "member")&&(path[3].length() == 10)) { + uint64_t address = Utils::hexStrToU64(path[3].c_str()); + char addrs[24]; + Utils::snprintf(addrs,sizeof(addrs),"%.10llx",(unsigned long long)address); + + json member(_readJson(_memberJP(nwid,Address(address),true))); + + try { + if (b.count("authorized")) member["authorized"] = b.value("authorized",false); + if ((b.count("identity"))&&(!member.count("identity"))) member["identity"] = b.value("identity",""); // allow identity to be populated only if not already known + + if (b.count("ipAssignments")) { + auto ipa = b["ipAssignments"]; + if (ipa.is_array()) { + json mipa(json::array()); + for(unsigned long i=0;itestId),sizeof(test->testId)); + test->credentialNetworkId = nwid; + test->ptr = (void *)this; + json hops = b["hops"]; + if (hops.is_array()) { + for(unsigned long i=0;ihops[test->hopCount].addresses[test->hops[test->hopCount].breadth++] = Utils::hexStrToU64(s.c_str()) & 0xffffffffffULL; + } + } else if (hops2.is_string()) { + std::string s = hops2; + test->hops[test->hopCount].addresses[test->hops[test->hopCount].breadth++] = Utils::hexStrToU64(s.c_str()) & 0xffffffffffULL; + } + } + } + test->reportAtEveryHop = (b.value("reportAtEveryHop",true) ? 1 : 0); + + if (!test->hopCount) { + ::free((void *)test); + return 400; + } + + test->timestamp = OSUtils::now(); + + _CircuitTestEntry &te = _circuitTests[test->testId]; + te.test = test; + te.jsonResults = ""; + + _node->circuitTestBegin(test,&(EmbeddedNetworkController::_circuitTestCallback)); + + char json[1024]; + Utils::snprintf(json,sizeof(json),"{\"testId\":\"%.16llx\"}",test->testId); + responseBody = json; + responseContentType = "application/json"; + return 200; + + } // else 404 + + } else { + // POST to network ID + + // Magic ID ending with ______ picks a random unused network ID + if (path[1].substr(10) == "______") { + nwid = 0; + uint64_t nwidPrefix = (Utils::hexStrToU64(path[1].substr(0,10).c_str()) << 24) & 0xffffffffff000000ULL; + uint64_t nwidPostfix = 0; + for(unsigned long k=0;k<100000;++k) { // sanity limit on trials + Utils::getSecureRandom(&nwidPostfix,sizeof(nwidPostfix)); + uint64_t tryNwid = nwidPrefix | (nwidPostfix & 0xffffffULL); + if ((tryNwid & 0xffffffULL) == 0ULL) tryNwid |= 1ULL; + Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)tryNwid); + if (!OSUtils::fileExists(_networkJP(tryNwid,false).c_str())) { + nwid = tryNwid; + break; + } + } + if (!nwid) + return 503; + } + + json network(_readJson(_networkJP(nwid,true))); + + try { + if (b.count("name")) network["name"] = b.value("name",""); + if (b.count("private")) network["private"] = b.value("private",true); + if (b.count("enableBroadcast")) network["enableBroadcast"] = b.value("enableBroadcast",false); + if (b.count("allowPassiveBridging")) network["allowPassiveBridging"] = b.value("allowPassiveBridging",false); + if (b.count("multicastLimit")) network["multicastLimit"] = b.value("multicastLimit",32ULL); + + if (b.count("activeBridges")) { + auto ab = b["activeBridges"]; + if (ab.is_array()) { + json ab2 = json::array(); + for(unsigned long i=0;i v6m(Utils::split(b.value("v6AssignMode","").c_str(),",","","")); + std::sort(v6m.begin(),v6m.end()); + v6m.erase(std::unique(v6m.begin(),v6m.end()),v6m.end()); + for(std::vector::iterator i(v6m.begin());i!=v6m.end();++i) { + if (*i == "rfc4193") + nv6m["rfc4193"] = true; + else if (*i == "zt") + nv6m["zt"] = true; + else if (*i == "6plane") + nv6m["6plane"] = true; + } + } else if (b["v6AssignMode"].is_object()) { + auto v6m = b["v6AssignMode"]; + if (v6m.count("rfc4193")) nv6m["rfc4193"] = v6m.value("rfc4193",false); + if (v6m.count("zt")) nv6m["rfc4193"] = v6m.value("zt",false); + if (v6m.count("6plane")) nv6m["rfc4193"] = v6m.value("6plane",false); + } + if (!nv6m.count("rfc4193")) nv6m["rfc4193"] = false; + if (!nv6m.count("zt")) nv6m["zt"] = false; + if (!nv6m.count("6plane")) nv6m["6plane"] = false; + } + + if (b.count("routes")) { + auto rts = b["routes"]; + if (rts.is_array()) { + for(unsigned long i=0;i &path, + const std::map &urlArgs, + const std::map &headers, + const std::string &body, + std::string &responseBody, + std::string &responseContentType) +{ + if (path.empty()) + return 404; + + if (path[0] == "network") { + if ((path.size() >= 2)&&(path[1].length() == 16)) { + const uint64_t nwid = Utils::hexStrToU64(path[1].c_str()); + + json network(_readJson(_networkJP(nwid,false))); + if (!network.size()) + return 404; + + if (path.size() >= 3) { + if ((path.size() == 4)&&(path[2] == "member")&&(path[3].length() == 10)) { + const uint64_t address = Utils::hexStrToU64(path[3].c_str()); + + json member(_readJson(_memberJP(nwid,Address(address),false))); + if (!member.size()) + return 404; + + OSUtils::rmDashRf(_memberBP(nwid,Address(address),false).c_str()); + + responseBody = member.dump(2); + responseContentType = "application/json"; + return 200; + } + } else { + OSUtils::rmDashRf(_networkBP(nwid,false).c_str()); + responseBody = network.dump(2); + responseContentType = "application/json"; + return 200; + } + } // else 404 + + } // else 404 + + return 404; +} + +void EmbeddedNetworkController::_circuitTestCallback(ZT_Node *node,ZT_CircuitTest *test,const ZT_CircuitTestReport *report) +{ + char tmp[65535]; + EmbeddedNetworkController *const self = reinterpret_cast(test->ptr); + + if (!test) + return; + if (!report) + return; + + Mutex::Lock _l(self->_circuitTests_m); + std::map< uint64_t,_CircuitTestEntry >::iterator cte(self->_circuitTests.find(test->testId)); + + if (cte == self->_circuitTests.end()) { // sanity check: a circuit test we didn't launch? + self->_node->circuitTestEnd(test); + ::free((void *)test); + return; + } + + Utils::snprintf(tmp,sizeof(tmp), + "%s{\n" + "\t\"timestamp\": %llu," ZT_EOL_S + "\t\"testId\": \"%.16llx\"," ZT_EOL_S + "\t\"upstream\": \"%.10llx\"," ZT_EOL_S + "\t\"current\": \"%.10llx\"," ZT_EOL_S + "\t\"receivedTimestamp\": %llu," ZT_EOL_S + "\t\"remoteTimestamp\": %llu," ZT_EOL_S + "\t\"sourcePacketId\": \"%.16llx\"," ZT_EOL_S + "\t\"flags\": %llu," ZT_EOL_S + "\t\"sourcePacketHopCount\": %u," ZT_EOL_S + "\t\"errorCode\": %u," ZT_EOL_S + "\t\"vendor\": %d," ZT_EOL_S + "\t\"protocolVersion\": %u," ZT_EOL_S + "\t\"majorVersion\": %u," ZT_EOL_S + "\t\"minorVersion\": %u," ZT_EOL_S + "\t\"revision\": %u," ZT_EOL_S + "\t\"platform\": %d," ZT_EOL_S + "\t\"architecture\": %d," ZT_EOL_S + "\t\"receivedOnLocalAddress\": \"%s\"," ZT_EOL_S + "\t\"receivedFromRemoteAddress\": \"%s\"" ZT_EOL_S + "}", + ((cte->second.jsonResults.length() > 0) ? ",\n" : ""), + (unsigned long long)report->timestamp, + (unsigned long long)test->testId, + (unsigned long long)report->upstream, + (unsigned long long)report->current, + (unsigned long long)OSUtils::now(), + (unsigned long long)report->remoteTimestamp, + (unsigned long long)report->sourcePacketId, + (unsigned long long)report->flags, + report->sourcePacketHopCount, + report->errorCode, + (int)report->vendor, + report->protocolVersion, + report->majorVersion, + report->minorVersion, + report->revision, + (int)report->platform, + (int)report->architecture, + reinterpret_cast(&(report->receivedOnLocalAddress))->toString().c_str(), + reinterpret_cast(&(report->receivedFromRemoteAddress))->toString().c_str()); + + cte->second.jsonResults.append(tmp); +} + +} // namespace ZeroTier diff --git a/controller/EmbeddedNetworkController.hpp b/controller/EmbeddedNetworkController.hpp new file mode 100644 index 00000000..f6e6b098 --- /dev/null +++ b/controller/EmbeddedNetworkController.hpp @@ -0,0 +1,173 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2015 ZeroTier, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef ZT_SQLITENETWORKCONTROLLER_HPP +#define ZT_SQLITENETWORKCONTROLLER_HPP + +#include + +#include +#include +#include +#include + +#include "../node/Constants.hpp" + +#include "../node/NetworkController.hpp" +#include "../node/Mutex.hpp" +#include "../node/Utils.hpp" +#include "../node/InetAddress.hpp" + +#include "../osdep/OSUtils.hpp" + +#include "../ext/json/json.hpp" + +namespace ZeroTier { + +class Node; + +class EmbeddedNetworkController : public NetworkController +{ +public: + EmbeddedNetworkController(Node *node,const char *dbPath); + virtual ~EmbeddedNetworkController(); + + virtual NetworkController::ResultCode doNetworkConfigRequest( + const InetAddress &fromAddr, + const Identity &signingId, + const Identity &identity, + uint64_t nwid, + const Dictionary &metaData, + NetworkConfig &nc); + + unsigned int handleControlPlaneHttpGET( + const std::vector &path, + const std::map &urlArgs, + const std::map &headers, + const std::string &body, + std::string &responseBody, + std::string &responseContentType); + unsigned int handleControlPlaneHttpPOST( + const std::vector &path, + const std::map &urlArgs, + const std::map &headers, + const std::string &body, + std::string &responseBody, + std::string &responseContentType); + unsigned int handleControlPlaneHttpDELETE( + const std::vector &path, + const std::map &urlArgs, + const std::map &headers, + const std::string &body, + std::string &responseBody, + std::string &responseContentType); + +private: + static void _circuitTestCallback(ZT_Node *node,ZT_CircuitTest *test,const ZT_CircuitTestReport *report); + + inline nlohmann::json _readJson(const std::string &path) + { + std::string buf; + if (OSUtils::readFile(path.c_str(),buf)) { + try { + return nlohmann::json::parse(buf); + } catch ( ... ) {} + } + return nlohmann::json::object(); + } + + inline bool _writeJson(const std::string &path,const nlohmann::json &obj) + { + std::string buf(obj.dump(2)); + return OSUtils::writeFile(path.c_str(),buf); + } + + inline std::string _networkBP(const uint64_t nwid,bool create) + { + char tmp[64]; + Utils::snprintf(tmp,sizeof(tmp),"%.16llx",nwid); + std::string p(_path + ZT_PATH_SEPARATOR_S + "network"); + if (create) OSUtils::mkdir(p.c_str()); + p.push_back(ZT_PATH_SEPARATOR); + p.append(tmp); + if (create) OSUtils::mkdir(p.c_str()); + return p; + } + inline std::string _networkJP(const uint64_t nwid,bool create) + { + return (_networkBP(nwid,create) + ZT_PATH_SEPARATOR + "config.json"); + } + inline std::string _memberBP(const uint64_t nwid,const Address &member,bool create) + { + std::string p(_networkBP(nwid,create)); + p.push_back(ZT_PATH_SEPARATOR); + p.append("member"); + if (create) OSUtils::mkdir(p.c_str()); + p.push_back(ZT_PATH_SEPARATOR); + p.append(member.toString()); + if (create) OSUtils::mkdir(p.c_str()); + return p; + } + inline std::string _memberJP(const uint64_t nwid,const Address &member,bool create) + { + return (_memberBP(nwid,member,create) + ZT_PATH_SEPARATOR + "config.json"); + } + + inline std::set _getAlreadyAllocatedIps(const uint64_t nwid) + { + std::set ips; + std::string bp(_networkBP(nwid,false) + ZT_PATH_SEPARATOR_S + "member"); + std::vector members(OSUtils::listSubdirectories(bp.c_str())); + for(std::vector::iterator m(members.begin());m!=members.end();++m) { + if (m->length() == ZT_ADDRESS_LENGTH_HEX) { + nlohmann::json mj = _readJson(bp + ZT_PATH_SEPARATOR_S + *m + ZT_PATH_SEPARATOR_S + "config.json"); + auto ipAssignments = mj["ipAssignments"]; + if (ipAssignments.is_array()) { + for(unsigned long i=0;i _circuitTests; + Mutex _circuitTests_m; + + // Last request time by address, for rate limitation + std::map< std::pair,uint64_t > _lastRequestTime; + Mutex _lastRequestTime_m; +}; + +} // namespace ZeroTier + +#endif diff --git a/controller/SqliteNetworkController.cpp b/controller/SqliteNetworkController.cpp deleted file mode 100644 index 863f93f3..00000000 --- a/controller/SqliteNetworkController.cpp +++ /dev/null @@ -1,1462 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2015 ZeroTier, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "../include/ZeroTierOne.h" -#include "../node/Constants.hpp" - -#include "SqliteNetworkController.hpp" - -#include "../node/Node.hpp" -#include "../node/Utils.hpp" -#include "../node/CertificateOfMembership.hpp" -#include "../node/NetworkConfig.hpp" -#include "../node/Dictionary.hpp" -#include "../node/InetAddress.hpp" -#include "../node/MAC.hpp" -#include "../node/Address.hpp" - -using json = nlohmann::json; - -// API version reported via JSON control plane -#define ZT_NETCONF_CONTROLLER_API_VERSION 3 - -// Number of requests to remember in member history -#define ZT_NETCONF_DB_MEMBER_HISTORY_LENGTH 8 - -// Min duration between requests for an address/nwid combo to prevent floods -#define ZT_NETCONF_MIN_REQUEST_PERIOD 1000 - -// Nodes are considered active if they've queried in less than this long -#define ZT_NETCONF_NODE_ACTIVE_THRESHOLD ((ZT_NETWORK_AUTOCONF_DELAY * 2) + 5000) - -namespace ZeroTier { - -static json _renderRule(ZT_VirtualNetworkRule &rule) -{ - char tmp[128]; - json r = json::object(); - r["not"] = ((rule.t & 0x80) != 0); - switch((rule.t) & 0x7f) { - case ZT_NETWORK_RULE_ACTION_DROP: - r["type"] = "ACTION_DROP"; - break; - case ZT_NETWORK_RULE_ACTION_ACCEPT: - r["type"] = "ACTION_ACCEPT"; - break; - case ZT_NETWORK_RULE_ACTION_TEE: - r["type"] = "ACTION_TEE"; - r["zt"] = Address(rule.v.zt).toString(); - break; - case ZT_NETWORK_RULE_ACTION_REDIRECT: - r["type"] = "ACTION_REDIRECT"; - r["zt"] = Address(rule.v.zt).toString(); - break; - case ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS: - r["type"] = "MATCH_SOURCE_ZEROTIER_ADDRESS"; - r["zt"] = Address(rule.v.zt).toString(); - break; - case ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS: - r["type"] = "MATCH_DEST_ZEROTIER_ADDRESS"; - r["zt"] = Address(rule.v.zt).toString(); - break; - case ZT_NETWORK_RULE_MATCH_VLAN_ID: - r["type"] = "MATCH_VLAN_ID"; - r["vlanId"] = (uint64_t)rule.v.vlanId; - break; - case ZT_NETWORK_RULE_MATCH_VLAN_PCP: - r["type"] = "MATCH_VLAN_PCP"; - r["vlanPcp"] = (uint64_t)rule.v.vlanPcp; - break; - case ZT_NETWORK_RULE_MATCH_VLAN_DEI: - r["type"] = "MATCH_VLAN_DEI"; - r["vlanDei"] = (uint64_t)rule.v.vlanDei; - break; - case ZT_NETWORK_RULE_MATCH_ETHERTYPE: - r["type"] = "MATCH_ETHERTYPE"; - r["etherType"] = (uint64_t)rule.v.etherType; - break; - case ZT_NETWORK_RULE_MATCH_MAC_SOURCE: - r["type"] = "MATCH_MAC_SOURCE"; - Utils::snprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]); - r["mac"] = tmp; - break; - case ZT_NETWORK_RULE_MATCH_MAC_DEST: - r["type"] = "MATCH_MAC_DEST"; - Utils::snprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]); - r["mac"] = tmp; - break; - case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE: - r["type"] = "MATCH_IPV4_SOURCE"; - r["ip"] = InetAddress(&(rule.v.ipv4.ip),4,(unsigned int)rule.v.ipv4.mask).toString(); - break; - case ZT_NETWORK_RULE_MATCH_IPV4_DEST: - r["type"] = "MATCH_IPV4_DEST"; - r["ip"] = InetAddress(&(rule.v.ipv4.ip),4,(unsigned int)rule.v.ipv4.mask).toString(); - break; - case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE: - r["type"] = "MATCH_IPV6_SOURCE"; - r["ip"] = InetAddress(rule.v.ipv6.ip,16,(unsigned int)rule.v.ipv6.mask).toString(); - break; - case ZT_NETWORK_RULE_MATCH_IPV6_DEST: - r["type"] = "MATCH_IPV6_DEST"; - r["ip"] = InetAddress(rule.v.ipv6.ip,16,(unsigned int)rule.v.ipv6.mask).toString(); - break; - case ZT_NETWORK_RULE_MATCH_IP_TOS: - r["type"] = "MATCH_IP_TOS"; - r["ipTos"] = (uint64_t)rule.v.ipTos; - break; - case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL: - r["type"] = "MATCH_IP_PROTOCOL"; - r["ipProtocol"] = (uint64_t)rule.v.ipProtocol; - break; - case ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE: - r["type"] = "MATCH_IP_SOURCE_PORT_RANGE"; - r["start"] = (uint64_t)rule.v.port[0]; - r["end"] = (uint64_t)rule.v.port[1]; - break; - case ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE: - r["type"] = "MATCH_IP_DEST_PORT_RANGE"; - r["start"] = (uint64_t)rule.v.port[0]; - r["end"] = (uint64_t)rule.v.port[1]; - break; - case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS: - r["type"] = "MATCH_CHARACTERISTICS"; - Utils::snprintf(tmp,sizeof(tmp),"%.16llx",rule.v.characteristics[0]); - r["mask"] = tmp; - Utils::snprintf(tmp,sizeof(tmp),"%.16llx",rule.v.characteristics[1]); - r["value"] = tmp; - break; - case ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE: - r["type"] = "MATCH_FRAME_SIZE_RANGE"; - r["start"] = (uint64_t)rule.v.frameSize[0]; - r["end"] = (uint64_t)rule.v.frameSize[1]; - break; - case ZT_NETWORK_RULE_MATCH_TAGS_SAMENESS: - r["type"] = "MATCH_TAGS_SAMENESS"; - r["id"] = (uint64_t)rule.v.tag.id; - r["value"] = (uint64_t)rule.v.tag.value; - break; - case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND: - r["type"] = "MATCH_TAGS_BITWISE_AND"; - r["id"] = (uint64_t)rule.v.tag.id; - r["value"] = (uint64_t)rule.v.tag.value; - break; - case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR: - r["type"] = "MATCH_TAGS_BITWISE_OR"; - r["id"] = (uint64_t)rule.v.tag.id; - r["value"] = (uint64_t)rule.v.tag.value; - break; - case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR: - r["type"] = "MATCH_TAGS_BITWISE_XOR"; - r["id"] = (uint64_t)rule.v.tag.id; - r["value"] = (uint64_t)rule.v.tag.value; - break; - } - return r; -} - -static bool _parseRule(const json &r,ZT_VirtualNetworkRule &rule) -{ - if (r.is_object()) - return false; - std::string t = r["type"]; - memset(&rule,0,sizeof(ZT_VirtualNetworkRule)); - if (r.value("not",false)) - rule.t = 0x80; - else rule.t = 0x00; - if (t == "ACTION_DROP") { - rule.t |= ZT_NETWORK_RULE_ACTION_DROP; - return true; - } else if (t == "ACTION_ACCEPT") { - rule.t |= ZT_NETWORK_RULE_ACTION_ACCEPT; - return true; - } else if (t == "ACTION_TEE") { - rule.t |= ZT_NETWORK_RULE_ACTION_TEE; - rule.v.zt = Utils::hexStrToU64(r.value("zt","0").c_str()) & 0xffffffffffULL; - return true; - } else if (t == "ACTION_REDIRECT") { - rule.t |= ZT_NETWORK_RULE_ACTION_REDIRECT; - rule.v.zt = Utils::hexStrToU64(r.value("zt","0").c_str()) & 0xffffffffffULL; - return true; - } else if (t == "MATCH_SOURCE_ZEROTIER_ADDRESS") { - rule.t |= ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS; - rule.v.zt = Utils::hexStrToU64(r.value("zt","0").c_str()) & 0xffffffffffULL; - return true; - } else if (t == "MATCH_DEST_ZEROTIER_ADDRESS") { - rule.t |= ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS; - rule.v.zt = Utils::hexStrToU64(r.value("zt","0").c_str()) & 0xffffffffffULL; - return true; - } else if (t == "MATCH_VLAN_ID") { - rule.t |= ZT_NETWORK_RULE_MATCH_VLAN_ID; - rule.v.vlanId = (uint16_t)(r.value("vlanId",0ULL) & 0xffffULL); - return true; - } else if (t == "MATCH_VLAN_PCP") { - rule.t |= ZT_NETWORK_RULE_MATCH_VLAN_PCP; - rule.v.vlanPcp = (uint8_t)(r.value("vlanPcp",0ULL) & 0xffULL); - return true; - } else if (t == "MATCH_VLAN_DEI") { - rule.t |= ZT_NETWORK_RULE_MATCH_VLAN_DEI; - rule.v.vlanDei = (uint8_t)(r.value("vlanDei",0ULL) & 0xffULL); - return true; - } else if (t == "MATCH_ETHERTYPE") { - rule.t |= ZT_NETWORK_RULE_MATCH_ETHERTYPE; - rule.v.etherType = (uint16_t)(r.value("etherType",0ULL) & 0xffffULL); - return true; - } else if (t == "MATCH_MAC_SOURCE") { - rule.t |= ZT_NETWORK_RULE_MATCH_MAC_SOURCE; - const std::string mac(r.value("mac","0")); - Utils::unhex(mac.c_str(),(unsigned int)mac.length(),rule.v.mac,6); - return true; - } else if (t == "MATCH_MAC_DEST") { - rule.t |= ZT_NETWORK_RULE_MATCH_MAC_DEST; - const std::string mac(r.value("mac","0")); - Utils::unhex(mac.c_str(),(unsigned int)mac.length(),rule.v.mac,6); - return true; - } else if (t == "MATCH_IPV4_SOURCE") { - rule.t |= ZT_NETWORK_RULE_MATCH_IPV4_SOURCE; - InetAddress ip(r.value("ip","0.0.0.0")); - rule.v.ipv4.ip = reinterpret_cast(&ip)->sin_addr.s_addr; - rule.v.ipv4.mask = Utils::ntoh(reinterpret_cast(&ip)->sin_port) & 0xff; - if (rule.v.ipv4.mask > 32) rule.v.ipv4.mask = 32; - return true; - } else if (t == "MATCH_IPV4_DEST") { - rule.t |= ZT_NETWORK_RULE_MATCH_IPV4_DEST; - InetAddress ip(r.value("ip","0.0.0.0")); - rule.v.ipv4.ip = reinterpret_cast(&ip)->sin_addr.s_addr; - rule.v.ipv4.mask = Utils::ntoh(reinterpret_cast(&ip)->sin_port) & 0xff; - if (rule.v.ipv4.mask > 32) rule.v.ipv4.mask = 32; - return true; - } else if (t == "MATCH_IPV6_SOURCE") { - rule.t |= ZT_NETWORK_RULE_MATCH_IPV6_SOURCE; - InetAddress ip(r.value("ip","::0")); - memcpy(rule.v.ipv6.ip,reinterpret_cast(&ip)->sin6_addr.s6_addr,16); - rule.v.ipv6.mask = Utils::ntoh(reinterpret_cast(&ip)->sin6_port) & 0xff; - if (rule.v.ipv6.mask > 128) rule.v.ipv6.mask = 128; - return true; - } else if (t == "MATCH_IPV6_DEST") { - rule.t |= ZT_NETWORK_RULE_MATCH_IPV6_DEST; - InetAddress ip(r.value("ip","::0")); - memcpy(rule.v.ipv6.ip,reinterpret_cast(&ip)->sin6_addr.s6_addr,16); - rule.v.ipv6.mask = Utils::ntoh(reinterpret_cast(&ip)->sin6_port) & 0xff; - if (rule.v.ipv6.mask > 128) rule.v.ipv6.mask = 128; - return true; - } else if (t == "MATCH_IP_TOS") { - rule.t |= ZT_NETWORK_RULE_MATCH_IP_TOS; - rule.v.ipTos = (uint8_t)(r.value("ipTos",0ULL) & 0xffULL); - return true; - } else if (t == "MATCH_IP_PROTOCOL") { - rule.t |= ZT_NETWORK_RULE_MATCH_IP_PROTOCOL; - rule.v.ipProtocol = (uint8_t)(r.value("ipProtocol",0ULL) & 0xffULL); - return true; - } else if (t == "MATCH_IP_SOURCE_PORT_RANGE") { - rule.t |= ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE; - rule.v.port[0] = (uint16_t)(r.value("start",0ULL) & 0xffffULL); - rule.v.port[1] = (uint16_t)(r.value("end",0ULL) & 0xffffULL); - return true; - } else if (t == "MATCH_IP_DEST_PORT_RANGE") { - rule.t |= ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE; - rule.v.port[0] = (uint16_t)(r.value("start",0ULL) & 0xffffULL); - rule.v.port[1] = (uint16_t)(r.value("end",0ULL) & 0xffffULL); - return true; - } else if (t == "MATCH_CHARACTERISTICS") { - rule.t |= ZT_NETWORK_RULE_MATCH_CHARACTERISTICS; - if (r.count("mask")) { - auto v = r["mask"]; - if (v.is_number()) { - rule.v.characteristics[0] = v; - } else { - std::string tmp = v; - rule.v.characteristics[0] = Utils::hexStrToU64(tmp.c_str()); - } - } - if (r.count("value")) { - auto v = r["value"]; - if (v.is_number()) { - rule.v.characteristics[1] = v; - } else { - std::string tmp = v; - rule.v.characteristics[1] = Utils::hexStrToU64(tmp.c_str()); - } - } - return true; - } else if (t == "MATCH_FRAME_SIZE_RANGE") { - rule.t |= ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE; - rule.v.frameSize[0] = (uint16_t)(Utils::hexStrToU64(r.value("start","0").c_str()) & 0xffffULL); - rule.v.frameSize[1] = (uint16_t)(Utils::hexStrToU64(r.value("end","0").c_str()) & 0xffffULL); - return true; - } else if (t == "MATCH_TAGS_SAMENESS") { - rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_SAMENESS; - rule.v.tag.id = (uint32_t)(Utils::hexStrToU64(r.value("id","0").c_str()) & 0xffffffffULL); - rule.v.tag.value = (uint32_t)(Utils::hexStrToU64(r.value("value","0").c_str()) & 0xffffffffULL); - return true; - } else if (t == "MATCH_TAGS_BITWISE_AND") { - rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND; - rule.v.tag.id = (uint32_t)(Utils::hexStrToU64(r.value("id","0").c_str()) & 0xffffffffULL); - rule.v.tag.value = (uint32_t)(Utils::hexStrToU64(r.value("value","0").c_str()) & 0xffffffffULL); - return true; - } else if (t == "MATCH_TAGS_BITWISE_OR") { - rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR; - rule.v.tag.id = (uint32_t)(Utils::hexStrToU64(r.value("id","0").c_str()) & 0xffffffffULL); - rule.v.tag.value = (uint32_t)(Utils::hexStrToU64(r.value("value","0").c_str()) & 0xffffffffULL); - return true; - } else if (t == "MATCH_TAGS_BITWISE_XOR") { - rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR; - rule.v.tag.id = (uint32_t)(Utils::hexStrToU64(r.value("id","0").c_str()) & 0xffffffffULL); - rule.v.tag.value = (uint32_t)(Utils::hexStrToU64(r.value("value","0").c_str()) & 0xffffffffULL); - return true; - } - return false; -} - -SqliteNetworkController::SqliteNetworkController(Node *node,const char *dbPath) : - _node(node), - _path(dbPath) -{ - OSUtils::mkdir(dbPath); - /* - if (sqlite3_open_v2(dbPath,&_db,SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE,(const char *)0) != SQLITE_OK) - throw std::runtime_error("SqliteNetworkController cannot open database file"); - sqlite3_busy_timeout(_db,10000); - - sqlite3_exec(_db,"PRAGMA synchronous = OFF",0,0,0); - sqlite3_exec(_db,"PRAGMA journal_mode = MEMORY",0,0,0); - - sqlite3_stmt *s = (sqlite3_stmt *)0; - if ((sqlite3_prepare_v2(_db,"SELECT v FROM Config WHERE k = 'schemaVersion';",-1,&s,(const char **)0) == SQLITE_OK)&&(s)) { - int schemaVersion = -1234; - if (sqlite3_step(s) == SQLITE_ROW) { - schemaVersion = sqlite3_column_int(s,0); - } - - sqlite3_finalize(s); - - if (schemaVersion == -1234) { - sqlite3_close(_db); - throw std::runtime_error("SqliteNetworkController schemaVersion not found in Config table (init failure?)"); - } - - if (schemaVersion < 2) { - // Create NodeHistory table to upgrade from version 1 to version 2 - if (sqlite3_exec(_db, - "CREATE TABLE NodeHistory (\n" - " nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n" - " networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n" - " networkVisitCounter INTEGER NOT NULL DEFAULT(0),\n" - " networkRequestAuthorized INTEGER NOT NULL DEFAULT(0),\n" - " requestTime INTEGER NOT NULL DEFAULT(0),\n" - " clientMajorVersion INTEGER NOT NULL DEFAULT(0),\n" - " clientMinorVersion INTEGER NOT NULL DEFAULT(0),\n" - " clientRevision INTEGER NOT NULL DEFAULT(0),\n" - " networkRequestMetaData VARCHAR(1024),\n" - " fromAddress VARCHAR(128)\n" - ");\n" - "CREATE INDEX NodeHistory_nodeId ON NodeHistory (nodeId);\n" - "CREATE INDEX NodeHistory_networkId ON NodeHistory (networkId);\n" - "CREATE INDEX NodeHistory_requestTime ON NodeHistory (requestTime);\n" - "UPDATE \"Config\" SET \"v\" = 2 WHERE \"k\" = 'schemaVersion';\n" - ,0,0,0) != SQLITE_OK) { - char err[1024]; - Utils::snprintf(err,sizeof(err),"SqliteNetworkController cannot upgrade the database to version 2: %s",sqlite3_errmsg(_db)); - sqlite3_close(_db); - throw std::runtime_error(err); - } else { - schemaVersion = 2; - } - } - - if (schemaVersion < 3) { - // Create Route table to upgrade from version 2 to version 3 and migrate old - // data. Also delete obsolete Gateway table that was never actually used, and - // migrate Network flags to a bitwise flags field instead of ASCII cruft. - if (sqlite3_exec(_db, - "DROP TABLE Gateway;\n" - "CREATE TABLE Route (\n" - " networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n" - " target blob(16) NOT NULL,\n" - " via blob(16),\n" - " targetNetmaskBits integer NOT NULL,\n" - " ipVersion integer NOT NULL,\n" - " flags integer NOT NULL,\n" - " metric integer NOT NULL\n" - ");\n" - "CREATE INDEX Route_networkId ON Route (networkId);\n" - "INSERT INTO Route SELECT DISTINCT networkId,\"ip\" AS \"target\",NULL AS \"via\",ipNetmaskBits AS targetNetmaskBits,ipVersion,0 AS \"flags\",0 AS \"metric\" FROM IpAssignment WHERE nodeId IS NULL AND \"type\" = 1;\n" - "ALTER TABLE Network ADD COLUMN \"flags\" integer NOT NULL DEFAULT(0);\n" - "UPDATE Network SET \"flags\" = (\"flags\" | 1) WHERE v4AssignMode = 'zt';\n" - "UPDATE Network SET \"flags\" = (\"flags\" | 2) WHERE v6AssignMode = 'rfc4193';\n" - "UPDATE Network SET \"flags\" = (\"flags\" | 4) WHERE v6AssignMode = '6plane';\n" - "ALTER TABLE Member ADD COLUMN \"flags\" integer NOT NULL DEFAULT(0);\n" - "DELETE FROM IpAssignment WHERE nodeId IS NULL AND \"type\" = 1;\n" - "UPDATE \"Config\" SET \"v\" = 3 WHERE \"k\" = 'schemaVersion';\n" - ,0,0,0) != SQLITE_OK) { - char err[1024]; - Utils::snprintf(err,sizeof(err),"SqliteNetworkController cannot upgrade the database to version 3: %s",sqlite3_errmsg(_db)); - sqlite3_close(_db); - throw std::runtime_error(err); - } else { - schemaVersion = 3; - } - } - - if (schemaVersion < 4) { - // Turns out this was overkill and a huge performance drag. Will be revisiting this - // more later but for now a brief snapshot of recent history stored in Member is fine. - // Also prepare for implementation of proof of work requests. - if (sqlite3_exec(_db, - "DROP TABLE NodeHistory;\n" - "ALTER TABLE Member ADD COLUMN lastRequestTime integer NOT NULL DEFAULT(0);\n" - "ALTER TABLE Member ADD COLUMN lastPowDifficulty integer NOT NULL DEFAULT(0);\n" - "ALTER TABLE Member ADD COLUMN lastPowTime integer NOT NULL DEFAULT(0);\n" - "ALTER TABLE Member ADD COLUMN recentHistory blob;\n" - "CREATE INDEX Member_networkId_lastRequestTime ON Member(networkId, lastRequestTime);\n" - "UPDATE \"Config\" SET \"v\" = 4 WHERE \"k\" = 'schemaVersion';\n" - ,0,0,0) != SQLITE_OK) { - char err[1024]; - Utils::snprintf(err,sizeof(err),"SqliteNetworkController cannot upgrade the database to version 3: %s",sqlite3_errmsg(_db)); - sqlite3_close(_db); - throw std::runtime_error(err); - } else { - schemaVersion = 4; - } - } - - if (schemaVersion < 5) { - // Upgrade old rough draft Rule table to new release format - if (sqlite3_exec(_db, - "DROP TABLE Relay;\n" - "DROP INDEX Rule_networkId_ruleNo;\n" - "ALTER TABLE \"Rule\" RENAME TO RuleOld;\n" - "CREATE TABLE Rule (\n" - " networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n" - " capId integer,\n" - " ruleNo integer NOT NULL,\n" - " ruleType integer NOT NULL DEFAULT(0),\n" - " \"addr\" blob(16),\n" - " \"int1\" integer,\n" - " \"int2\" integer,\n" - " \"int3\" integer,\n" - " \"int4\" integer\n" - ");\n" - "INSERT INTO \"Rule\" SELECT networkId,(ruleNo*2) AS ruleNo,37 AS \"ruleType\",etherType AS \"int1\" FROM RuleOld WHERE RuleOld.etherType IS NOT NULL AND RuleOld.etherType > 0;\n" - "INSERT INTO \"Rule\" SELECT networkId,((ruleNo*2)+1) AS ruleNo,1 AS \"ruleType\" FROM RuleOld;\n" - "DROP TABLE RuleOld;\n" - "CREATE INDEX Rule_networkId_capId ON Rule (networkId,capId);\n" - "CREATE TABLE MemberTC (\n" - " networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n" - " nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n" - " tagId integer,\n" - " tagValue integer,\n" - " capId integer,\n" - " capMaxCustodyChainLength integer NOT NULL DEFAULT(1)\n" - ");\n" - "CREATE INDEX MemberTC_networkId_nodeId ON MemberTC (networkId,nodeId);\n" - "UPDATE \"Config\" SET \"v\" = 5 WHERE \"k\" = 'schemaVersion';\n" - ,0,0,0) != SQLITE_OK) { - char err[1024]; - Utils::snprintf(err,sizeof(err),"SqliteNetworkController cannot upgrade the database to version 3: %s",sqlite3_errmsg(_db)); - sqlite3_close(_db); - throw std::runtime_error(err); - } else { - schemaVersion = 5; - } - } - - if (schemaVersion != ZT_NETCONF_SQLITE_SCHEMA_VERSION) { - sqlite3_close(_db); - throw std::runtime_error("SqliteNetworkController database schema version mismatch"); - } - } else { - // Prepare statement will fail if Config table doesn't exist, which means our DB - // needs to be initialized. - if (sqlite3_exec(_db,ZT_NETCONF_SCHEMA_SQL"INSERT INTO Config (k,v) VALUES ('schemaVersion',"ZT_NETCONF_SQLITE_SCHEMA_VERSION_STR");",0,0,0) != SQLITE_OK) { - char err[1024]; - Utils::snprintf(err,sizeof(err),"SqliteNetworkController cannot initialize database and/or insert schemaVersion into Config table: %s",sqlite3_errmsg(_db)); - sqlite3_close(_db); - throw std::runtime_error(err); - } - } - - if ( - - (sqlite3_prepare_v2(_db,"SELECT name,private,enableBroadcast,allowPassiveBridging,\"flags\",multicastLimit,creationTime,revision,memberRevisionCounter,(SELECT COUNT(1) FROM Member WHERE Member.networkId = Network.id AND Member.authorized > 0) FROM Network WHERE id = ?",-1,&_sGetNetworkById,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"SELECT revision FROM Network WHERE id = ?",-1,&_sGetNetworkRevision,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"UPDATE Network SET revision = ? WHERE id = ?",-1,&_sSetNetworkRevision,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"INSERT INTO Network (id,name,creationTime,revision) VALUES (?,?,?,1)",-1,&_sCreateNetwork,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"DELETE FROM Network WHERE id = ?",-1,&_sDeleteNetwork,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"SELECT id FROM Network ORDER BY id ASC",-1,&_sListNetworks,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"UPDATE Network SET memberRevisionCounter = (memberRevisionCounter + 1) WHERE id = ?",-1,&_sIncrementMemberRevisionCounter,(const char **)0) != SQLITE_OK) - - ||(sqlite3_prepare_v2(_db,"SELECT identity FROM Node WHERE id = ?",-1,&_sGetNodeIdentity,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"INSERT OR REPLACE INTO Node (id,identity) VALUES (?,?)",-1,&_sCreateOrReplaceNode,(const char **)0) != SQLITE_OK) - - ||(sqlite3_prepare_v2(_db,"INSERT INTO Rule (networkId,ruleNo,nodeId,ztSource,ztDest,vlanId,vlanPcp,vlanDei,) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",-1,&_sCreateRule,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"SELECT ruleNo,nodeId,sourcePort,destPort,vlanId,vlanPcp,etherType,macSource,macDest,ipSource,ipDest,ipTos,ipProtocol,ipSourcePort,ipDestPort,\"flags\",invFlags,\"action\" FROM Rule WHERE networkId = ? ORDER BY ruleNo ASC",-1,&_sListRules,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"DELETE FROM Rule WHERE networkId = ?",-1,&_sDeleteRulesForNetwork,(const char **)0) != SQLITE_OK) - - ||(sqlite3_prepare_v2(_db,"SELECT ipRangeStart,ipRangeEnd FROM IpAssignmentPool WHERE networkId = ? AND ipVersion = ?",-1,&_sGetIpAssignmentPools,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"SELECT ipRangeStart,ipRangeEnd,ipVersion FROM IpAssignmentPool WHERE networkId = ? ORDER BY ipRangeStart ASC",-1,&_sGetIpAssignmentPools2,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"INSERT INTO IpAssignmentPool (networkId,ipRangeStart,ipRangeEnd,ipVersion) VALUES (?,?,?,?)",-1,&_sCreateIpAssignmentPool,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"DELETE FROM IpAssignmentPool WHERE networkId = ?",-1,&_sDeleteIpAssignmentPoolsForNetwork,(const char **)0) != SQLITE_OK) - - ||(sqlite3_prepare_v2(_db,"SELECT ip,ipNetmaskBits,ipVersion FROM IpAssignment WHERE networkId = ? AND nodeId = ? AND \"type\" = 0 ORDER BY ip ASC",-1,&_sGetIpAssignmentsForNode,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"SELECT 1 FROM IpAssignment WHERE networkId = ? AND ip = ? AND ipVersion = ? AND \"type\" = ?",-1,&_sCheckIfIpIsAllocated,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"INSERT INTO IpAssignment (networkId,nodeId,\"type\",ip,ipNetmaskBits,ipVersion) VALUES (?,?,?,?,?,?)",-1,&_sAllocateIp,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"DELETE FROM IpAssignment WHERE networkId = ? AND nodeId = ? AND \"type\" = ?",-1,&_sDeleteIpAllocations,(const char **)0) != SQLITE_OK) - - ||(sqlite3_prepare_v2(_db,"SELECT rowid,authorized,activeBridge,memberRevision,\"flags\",lastRequestTime,recentHistory FROM Member WHERE networkId = ? AND nodeId = ?",-1,&_sGetMember,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"SELECT m.authorized,m.activeBridge,m.memberRevision,n.identity,m.flags,m.lastRequestTime,m.recentHistory FROM Member AS m LEFT OUTER JOIN Node AS n ON n.id = m.nodeId WHERE m.networkId = ? AND m.nodeId = ?",-1,&_sGetMember2,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"INSERT INTO Member (networkId,nodeId,authorized,activeBridge,memberRevision) VALUES (?,?,?,0,(SELECT memberRevisionCounter FROM Network WHERE id = ?))",-1,&_sCreateMember,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"SELECT nodeId FROM Member WHERE networkId = ? AND activeBridge > 0 AND authorized > 0",-1,&_sGetActiveBridges,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"SELECT m.nodeId,m.memberRevision FROM Member AS m WHERE m.networkId = ? ORDER BY m.nodeId ASC",-1,&_sListNetworkMembers,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"UPDATE Member SET authorized = ?,memberRevision = (SELECT memberRevisionCounter FROM Network WHERE id = ?) WHERE rowid = ?",-1,&_sUpdateMemberAuthorized,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"UPDATE Member SET activeBridge = ?,memberRevision = (SELECT memberRevisionCounter FROM Network WHERE id = ?) WHERE rowid = ?",-1,&_sUpdateMemberActiveBridge,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"UPDATE Member SET \"lastRequestTime\" = ?, \"recentHistory\" = ? WHERE rowid = ?",-1,&_sUpdateMemberHistory,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"DELETE FROM Member WHERE networkId = ? AND nodeId = ?",-1,&_sDeleteMember,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"DELETE FROM Member WHERE networkId = ?",-1,&_sDeleteAllNetworkMembers,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"SELECT nodeId,recentHistory FROM Member WHERE networkId = ? AND lastRequestTime >= ?",-1,&_sGetActiveNodesOnNetwork,(const char **)0) != SQLITE_OK) - - ||(sqlite3_prepare_v2(_db,"INSERT INTO Route (networkId,target,via,targetNetmaskBits,ipVersion,flags,metric) VALUES (?,?,?,?,?,?,?)",-1,&_sCreateRoute,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"SELECT DISTINCT target,via,targetNetmaskBits,ipVersion,flags,metric FROM \"Route\" WHERE networkId = ? ORDER BY ipVersion,target,via",-1,&_sGetRoutes,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"DELETE FROM \"Route\" WHERE networkId = ?",-1,&_sDeleteRoutes,(const char **)0) != SQLITE_OK) - - ||(sqlite3_prepare_v2(_db,"SELECT \"v\" FROM \"Config\" WHERE \"k\" = ?",-1,&_sGetConfig,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"INSERT OR REPLACE INTO \"Config\" (\"k\",\"v\") VALUES (?,?)",-1,&_sSetConfig,(const char **)0) != SQLITE_OK) - - ) { - std::string err(std::string("SqliteNetworkController unable to initialize one or more prepared statements: ") + sqlite3_errmsg(_db)); - sqlite3_close(_db); - throw std::runtime_error(err); - } - - sqlite3_reset(_sGetConfig); - sqlite3_bind_text(_sGetConfig,1,"instanceId",10,SQLITE_STATIC); - if (sqlite3_step(_sGetConfig) != SQLITE_ROW) { - unsigned char sr[32]; - Utils::getSecureRandom(sr,32); - for(unsigned int i=0;i<32;++i) - _instanceId.push_back("0123456789abcdef"[(unsigned int)sr[i] & 0xf]); - - sqlite3_reset(_sSetConfig); - sqlite3_bind_text(_sSetConfig,1,"instanceId",10,SQLITE_STATIC); - sqlite3_bind_text(_sSetConfig,2,_instanceId.c_str(),-1,SQLITE_STATIC); - if (sqlite3_step(_sSetConfig) != SQLITE_DONE) - throw std::runtime_error("SqliteNetworkController unable to read or initialize instanceId"); - } else { - const char *iid = reinterpret_cast(sqlite3_column_text(_sGetConfig,0)); - if (!iid) - throw std::runtime_error("SqliteNetworkController unable to read instanceId (it's NULL)"); - _instanceId = iid; - } - -#ifdef ZT_NETCONF_SQLITE_TRACE - sqlite3_trace(_db,sqliteTraceFunc,(void *)0); -#endif - - _backupThread = Thread::start(this); - */ -} - -SqliteNetworkController::~SqliteNetworkController() -{ -} - -NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(const InetAddress &fromAddr,const Identity &signingId,const Identity &identity,uint64_t nwid,const Dictionary &metaData,NetworkConfig &nc) -{ - if (((!signingId)||(!signingId.hasPrivate()))||(signingId.address().toInt() != (nwid >> 24))) { - return NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR; - } - - const uint64_t now = OSUtils::now(); - - // Check rate limit circuit breaker to prevent flooding - { - Mutex::Lock _l(_lastRequestTime_m); - uint64_t &lrt = _lastRequestTime[std::pair(identity.address().toInt(),nwid)]; - if ((now - lrt) <= ZT_NETCONF_MIN_REQUEST_PERIOD) - return NetworkController::NETCONF_QUERY_IGNORE; - lrt = now; - } - - json network(_readJson(_networkJP(nwid,false))); - if (!network.size()) - return NetworkController::NETCONF_QUERY_OBJECT_NOT_FOUND; - const std::string memberJP(_memberJP(nwid,identity.address(),false)); - json member(_readJson(memberJP)); - - { - std::string haveIdStr = member.value("identity",""); - if (haveIdStr.length() > 0) { - try { - if (Identity(haveIdStr.c_str()) != identity) - return NetworkController::NETCONF_QUERY_ACCESS_DENIED; - } catch ( ... ) { - return NetworkController::NETCONF_QUERY_ACCESS_DENIED; - } - } else { - member["identity"] = identity.toString(false); - } - } - - // Make sure these are always present no matter what, and increment member revision since we will always at least log something - member["id"] = identity.address().toString(); - member["address"] = member["id"]; - member["nwid"] = network["id"]; - member["memberRevision"] = member.value("memberRevision",0ULL) + 1; - - // Update member log - { - json rlEntry = json::object(); - rlEntry["ts"] = now; - rlEntry["authorized"] = member["authorized"]; - rlEntry["clientMajorVersion"] = metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION,0); - rlEntry["clientMinorVersion"] = metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MINOR_VERSION,0); - rlEntry["clientRevision"] = metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_REVISION,0); - rlEntry["clientProtocolVersion"] = metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_PROTOCOL_VERSION,0); - if (fromAddr) - rlEntry["fromAddr"] = fromAddr.toString(); - json recentLog = json::array(); - recentLog.push_back(rlEntry); - auto oldLog = member["recentLog"]; - if (oldLog.is_array()) { - for(unsigned long i=0;i= ZT_NETCONF_DB_MEMBER_HISTORY_LENGTH) - break; - } - } - member["recentLog"] = recentLog; - } - - // Stop if network is private and member is not authorized - if ( (network.value("private",true)) && (!member.value("authorized",false)) ) { - _writeJson(memberJP,member); - return NetworkController::NETCONF_QUERY_ACCESS_DENIED; - } - // Else compose and send network config - - nc.networkId = nwid; - nc.type = network.value("private",true) ? ZT_NETWORK_TYPE_PRIVATE : ZT_NETWORK_TYPE_PUBLIC; - nc.timestamp = now; - nc.revision = network.value("revision",0ULL); - nc.issuedTo = identity.address(); - if (network.value("enableBroadcast",true)) nc.flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST; - if (network.value("allowPassiveBridging",false)) nc.flags |= ZT_NETWORKCONFIG_FLAG_ALLOW_PASSIVE_BRIDGING; - Utils::scopy(nc.name,sizeof(nc.name),network.value("name","").c_str()); - nc.multicastLimit = (unsigned int)network.value("multicastLimit",32ULL); - - bool amActiveBridge = false; - { - json ab = network["activeBridges"]; - if (ab.is_array()) { - for(unsigned long i=0;i= ZT_MAX_NETWORK_RULES) - break; - auto rule = rules[i]; - if (_parseRule(rule,nc.rules[nc.ruleCount])) - ++nc.ruleCount; - } - } - - if (routes.is_array()) { - for(unsigned long i=0;i= ZT_MAX_NETWORK_ROUTES) - break; - auto route = routes[i]; - InetAddress t(route.value("target","")); - InetAddress v(route.value("via","")); - if ((t)&&(v)&&(t.ss_family == v.ss_family)) { - ZT_VirtualNetworkRoute *r = &(nc.routes[nc.routeCount]); - *(reinterpret_cast(&(r->target))) = t; - *(reinterpret_cast(&(r->via))) = v; - ++nc.routeCount; - } - } - } - - bool haveManagedIpv4AutoAssignment = false; - bool haveManagedIpv6AutoAssignment = false; // "special" NDP-emulated address types do not count - json ipAssignments = member["ipAssignments"]; - if (ipAssignments.is_array()) { - for(unsigned long i=0;i(&(nc.routes[rk].target))->containsAddress(ip)) ) - routedNetmaskBits = reinterpret_cast(&(nc.routes[rk].target))->netmaskBits(); - } - - if (routedNetmaskBits > 0) { - if (nc.staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES) { - ip.setPort(routedNetmaskBits); - nc.staticIps[nc.staticIpCount++] = ip; - } - if (ip.ss_family == AF_INET) - haveManagedIpv4AutoAssignment = true; - else if (ip.ss_family == AF_INET6) - haveManagedIpv6AutoAssignment = true; - } - } - } else { - ipAssignments = json::array(); - } - - std::set allocatedIps; - bool allocatedIpsLoaded = false; - - if ( (ipAssignmentPools.is_array()) && ((v6AssignMode.is_object())&&(v6AssignMode.value("zt",false))) && (!haveManagedIpv6AutoAssignment) && (!amActiveBridge) ) { - if (!allocatedIpsLoaded) allocatedIps = _getAlreadyAllocatedIps(nwid); - for(unsigned long p=0;((p s[1])&&((e[1] - s[1]) >= 0xffffffffffULL)) { - // First see if we can just cram a ZeroTier ID into the higher 64 bits. If so do that. - xx[0] = Utils::hton(x[0]); - xx[1] = Utils::hton(x[1] + identity.address().toInt()); - } else { - // Otherwise pick random addresses -- this technically doesn't explore the whole range if the lower 64 bit range is >= 1 but that won't matter since that would be huge anyway - Utils::getSecureRandom((void *)xx,16); - if ((e[0] > s[0])) - xx[0] %= (e[0] - s[0]); - else xx[0] = 0; - if ((e[1] > s[1])) - xx[1] %= (e[1] - s[1]); - else xx[1] = 0; - xx[0] = Utils::hton(x[0] + xx[0]); - xx[1] = Utils::hton(x[1] + xx[1]); - } - - InetAddress ip6((const void *)xx,16,0); - - // Check if this IP is within a local-to-Ethernet routed network - int routedNetmaskBits = 0; - for(unsigned int rk=0;rk(&(nc.routes[rk].target))->containsAddress(ip6)) ) - routedNetmaskBits = reinterpret_cast(&(nc.routes[rk].target))->netmaskBits(); - } - - // If it's routed, then try to claim and assign it and if successful end loop - if ((routedNetmaskBits > 0)&&(!allocatedIps.count(ip6))) { - ipAssignments.push_back(ip6.toIpString()); - member["ipAssignments"] = ipAssignments; - ip6.setPort((unsigned int)routedNetmaskBits); - if (nc.staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES) - nc.staticIps[nc.staticIpCount++] = ip6; - haveManagedIpv4AutoAssignment = true; - break; - } - } - } - } - } - } - - if ( (ipAssignmentPools.is_array()) && ((v4AssignMode.is_object())&&(v4AssignMode.value("zt",false))) && (!haveManagedIpv4AutoAssignment) && (!amActiveBridge) ) { - if (!allocatedIpsLoaded) allocatedIps = _getAlreadyAllocatedIps(nwid); - for(unsigned long p=0;((p(&ipRangeStart)->sin_addr.s_addr)); - uint32_t ipRangeEnd = Utils::ntoh((uint32_t)(reinterpret_cast(&ipRangeEnd)->sin_addr.s_addr)); - if ((ipRangeEnd <= ipRangeStart)||(ipRangeStart == 0)) - continue; - uint32_t ipRangeLen = ipRangeEnd - ipRangeStart; - - // Start with the LSB of the member's address - uint32_t ipTrialCounter = (uint32_t)(identity.address().toInt() & 0xffffffff); - - for(uint32_t k=ipRangeStart,trialCount=0;(k<=ipRangeEnd)&&(trialCount < 1000);++k,++trialCount) { - uint32_t ip = (ipRangeLen > 0) ? (ipRangeStart + (ipTrialCounter % ipRangeLen)) : ipRangeStart; - ++ipTrialCounter; - if ((ip & 0x000000ff) == 0x000000ff) - continue; // don't allow addresses that end in .255 - - // Check if this IP is within a local-to-Ethernet routed network - int routedNetmaskBits = 0; - for(unsigned int rk=0;rk(&(nc.routes[rk].target))->sin_addr.s_addr)); - int targetBits = Utils::ntoh((uint16_t)(reinterpret_cast(&(nc.routes[rk].target))->sin_port)); - if ((ip & (0xffffffff << (32 - targetBits))) == targetIp) { - routedNetmaskBits = targetBits; - break; - } - } - } - - InetAddress ip4(Utils::hton(ip),0); - - // If it's routed, then try to claim and assign it and if successful end loop - if ((routedNetmaskBits > 0)&&(!allocatedIps.count(ip4))) { - ipAssignments.push_back(ip4.toIpString()); - member["ipAssignments"] = ipAssignments; - if (nc.staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES) { - struct sockaddr_in *const v4ip = reinterpret_cast(&(nc.staticIps[nc.staticIpCount++])); - v4ip->sin_family = AF_INET; - v4ip->sin_port = Utils::hton((uint16_t)routedNetmaskBits); - v4ip->sin_addr.s_addr = Utils::hton(ip); - } - haveManagedIpv4AutoAssignment = true; - break; - } - } - } - } - } - } - - if (network.value("private",true)) { - CertificateOfMembership com(now,ZT_NETWORK_COM_DEFAULT_REVISION_MAX_DELTA,nwid,identity.address()); - if (com.sign(signingId)) { - nc.com = com; - } else { - return NETCONF_QUERY_INTERNAL_SERVER_ERROR; - } - } - - _writeJson(memberJP,member); - return NetworkController::NETCONF_QUERY_OK; -} - -unsigned int SqliteNetworkController::handleControlPlaneHttpGET( - const std::vector &path, - const std::map &urlArgs, - const std::map &headers, - const std::string &body, - std::string &responseBody, - std::string &responseContentType) -{ - 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()); - char nwids[24]; - Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid); - - json network(_readJson(_networkJP(nwid,false))); - if (!network.size()) - return 404; - - if (path.size() >= 3) { - - if (path[2] == "member") { - - if (path.size() >= 4) { - const uint64_t address = Utils::hexStrToU64(path[3].c_str()); - - json member(_readJson(_memberJP(nwid,Address(address),false))); - if (!member.size()) - return 404; - - char addrs[24]; - Utils::snprintf(addrs,sizeof(addrs),"%.10llx",address); - - member["clock"] = OSUtils::now(); - responseBody = member.dump(2); - responseContentType = "application/json"; - - return 200; - } else { - - responseBody = "{"; - std::vector members(OSUtils::listSubdirectories((_networkBP(nwid,false) + ZT_PATH_SEPARATOR_S + "member").c_str())); - for(std::vector::iterator i(members.begin());i!=members.end();++i) { - if (i->length() == ZT_ADDRESS_LENGTH_HEX) { - json member(_readJson(_memberJP(nwid,Address(Utils::hexStrToU64(i->c_str())),false))); - if (member.size()) { - responseBody.append((responseBody.length() == 1) ? "\"" : ",\""); - responseBody.append(*i); - responseBody.append("\":"); - const std::string rc = member.value("memberRevision","0"); - responseBody.append(rc); - } - } - } - responseBody.push_back('}'); - responseContentType = "application/json"; - - return 200; - } - - } else if ((path[2] == "active")&&(path.size() == 3)) { - - responseBody = "{"; - std::vector members(OSUtils::listSubdirectories((_networkBP(nwid,false) + ZT_PATH_SEPARATOR_S + "member").c_str())); - const uint64_t threshold = OSUtils::now() - ZT_NETCONF_NODE_ACTIVE_THRESHOLD; - for(std::vector::iterator i(members.begin());i!=members.end();++i) { - if (i->length() == ZT_ADDRESS_LENGTH_HEX) { - json member(_readJson(_memberJP(nwid,Address(Utils::hexStrToU64(i->c_str())),false))); - if (member.size()) { - auto recentLog = member["recentLog"]; - if ((recentLog.is_array())&&(recentLog.size() > 0)) { - auto mostRecentLog = recentLog[0]; - if ((mostRecentLog.is_object())&&((uint64_t)mostRecentLog.value("ts",0ULL) >= threshold)) { - responseBody.append((responseBody.length() == 1) ? "\"" : ",\""); - responseBody.append(*i); - responseBody.append("\":"); - responseBody.append(mostRecentLog.dump()); - } - } - } - } - } - responseBody.push_back('}'); - responseContentType = "application/json"; - return 200; - - } else if ((path[2] == "test")&&(path.size() >= 4)) { - - Mutex::Lock _l(_circuitTests_m); - std::map< uint64_t,_CircuitTestEntry >::iterator cte(_circuitTests.find(Utils::hexStrToU64(path[3].c_str()))); - if ((cte != _circuitTests.end())&&(cte->second.test)) { - - responseBody = "["; - responseBody.append(cte->second.jsonResults); - responseBody.push_back(']'); - responseContentType = "application/json"; - - return 200; - - } // else 404 - - } // else 404 - - } else { - - nlohmann::json o(network); - o["clock"] = OSUtils::now(); - responseBody = o.dump(2); - responseContentType = "application/json"; - return 200; - - } - } else if (path.size() == 1) { - - responseBody = "["; - std::vector networks(OSUtils::listSubdirectories((_path + ZT_PATH_SEPARATOR_S + "network").c_str())); - for(auto i(networks.begin());i!=networks.end();++i) { - if (i->length() == 16) { - responseBody.append((responseBody.length() == 1) ? "\"" : ",\""); - responseBody.append(*i); - responseBody.append("\""); - } - } - responseBody.push_back(']'); - responseContentType = "application/json"; - return 200; - - } // else 404 - - } else { - - char tmp[4096]; - Utils::snprintf(tmp,sizeof(tmp),"{\n\t\"controller\": true,\n\t\"apiVersion\": %d,\n\t\"clock\": %llu\n}\n",ZT_NETCONF_CONTROLLER_API_VERSION,(unsigned long long)OSUtils::now()); - responseBody = tmp; - responseContentType = "application/json"; - return 200; - - } - - return 404; -} - -unsigned int SqliteNetworkController::handleControlPlaneHttpPOST( - const std::vector &path, - const std::map &urlArgs, - const std::map &headers, - const std::string &body, - std::string &responseBody, - std::string &responseContentType) -{ - if (path.empty()) - return 404; - - json b; - try { - b = json::parse(body); - if (!b.is_object()) - return 400; - } catch ( ... ) { - return 400; - } - - if (path[0] == "network") { - - if ((path.size() >= 2)&&(path[1].length() == 16)) { - uint64_t nwid = Utils::hexStrToU64(path[1].c_str()); - char nwids[24]; - Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid); - - if (path.size() >= 3) { - json network(_readJson(_networkJP(nwid,false))); - if (!network.size()) - return 404; - - if ((path.size() == 4)&&(path[2] == "member")&&(path[3].length() == 10)) { - uint64_t address = Utils::hexStrToU64(path[3].c_str()); - char addrs[24]; - Utils::snprintf(addrs,sizeof(addrs),"%.10llx",(unsigned long long)address); - - json member(_readJson(_memberJP(nwid,Address(address),true))); - - try { - if (b.count("authorized")) member["authorized"] = b.value("authorized",false); - if ((b.count("identity"))&&(!member.count("identity"))) member["identity"] = b.value("identity",""); // allow identity to be populated only if not already known - - if (b.count("ipAssignments")) { - auto ipa = b["ipAssignments"]; - if (ipa.is_array()) { - json mipa(json::array()); - for(unsigned long i=0;itestId),sizeof(test->testId)); - test->credentialNetworkId = nwid; - test->ptr = (void *)this; - json hops = b["hops"]; - if (hops.is_array()) { - for(unsigned long i=0;ihops[test->hopCount].addresses[test->hops[test->hopCount].breadth++] = Utils::hexStrToU64(s.c_str()) & 0xffffffffffULL; - } - } else if (hops2.is_string()) { - std::string s = hops2; - test->hops[test->hopCount].addresses[test->hops[test->hopCount].breadth++] = Utils::hexStrToU64(s.c_str()) & 0xffffffffffULL; - } - } - } - test->reportAtEveryHop = (b.value("reportAtEveryHop",true) ? 1 : 0); - - if (!test->hopCount) { - ::free((void *)test); - return 400; - } - - test->timestamp = OSUtils::now(); - - _CircuitTestEntry &te = _circuitTests[test->testId]; - te.test = test; - te.jsonResults = ""; - - _node->circuitTestBegin(test,&(SqliteNetworkController::_circuitTestCallback)); - - char json[1024]; - Utils::snprintf(json,sizeof(json),"{\"testId\":\"%.16llx\"}",test->testId); - responseBody = json; - responseContentType = "application/json"; - return 200; - - } // else 404 - - } else { - // POST to network ID - - // Magic ID ending with ______ picks a random unused network ID - if (path[1].substr(10) == "______") { - nwid = 0; - uint64_t nwidPrefix = (Utils::hexStrToU64(path[1].substr(0,10).c_str()) << 24) & 0xffffffffff000000ULL; - uint64_t nwidPostfix = 0; - for(unsigned long k=0;k<100000;++k) { // sanity limit on trials - Utils::getSecureRandom(&nwidPostfix,sizeof(nwidPostfix)); - uint64_t tryNwid = nwidPrefix | (nwidPostfix & 0xffffffULL); - if ((tryNwid & 0xffffffULL) == 0ULL) tryNwid |= 1ULL; - Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)tryNwid); - if (!OSUtils::fileExists(_networkJP(tryNwid,false).c_str())) { - nwid = tryNwid; - break; - } - } - if (!nwid) - return 503; - } - - json network(_readJson(_networkJP(nwid,true))); - - try { - if (b.count("name")) network["name"] = b.value("name",""); - if (b.count("private")) network["private"] = b.value("private",true); - if (b.count("enableBroadcast")) network["enableBroadcast"] = b.value("enableBroadcast",false); - if (b.count("allowPassiveBridging")) network["allowPassiveBridging"] = b.value("allowPassiveBridging",false); - if (b.count("multicastLimit")) network["multicastLimit"] = b.value("multicastLimit",32ULL); - - if (b.count("activeBridges")) { - auto ab = b["activeBridges"]; - if (ab.is_array()) { - json ab2 = json::array(); - for(unsigned long i=0;i v6m(Utils::split(b.value("v6AssignMode","").c_str(),",","","")); - std::sort(v6m.begin(),v6m.end()); - v6m.erase(std::unique(v6m.begin(),v6m.end()),v6m.end()); - for(std::vector::iterator i(v6m.begin());i!=v6m.end();++i) { - if (*i == "rfc4193") - nv6m["rfc4193"] = true; - else if (*i == "zt") - nv6m["zt"] = true; - else if (*i == "6plane") - nv6m["6plane"] = true; - } - } else if (b["v6AssignMode"].is_object()) { - auto v6m = b["v6AssignMode"]; - if (v6m.count("rfc4193")) nv6m["rfc4193"] = v6m.value("rfc4193",false); - if (v6m.count("zt")) nv6m["rfc4193"] = v6m.value("zt",false); - if (v6m.count("6plane")) nv6m["rfc4193"] = v6m.value("6plane",false); - } - if (!nv6m.count("rfc4193")) nv6m["rfc4193"] = false; - if (!nv6m.count("zt")) nv6m["zt"] = false; - if (!nv6m.count("6plane")) nv6m["6plane"] = false; - } - - if (b.count("routes")) { - auto rts = b["routes"]; - if (rts.is_array()) { - for(unsigned long i=0;i &path, - const std::map &urlArgs, - const std::map &headers, - const std::string &body, - std::string &responseBody, - std::string &responseContentType) -{ - if (path.empty()) - return 404; - - if (path[0] == "network") { - if ((path.size() >= 2)&&(path[1].length() == 16)) { - const uint64_t nwid = Utils::hexStrToU64(path[1].c_str()); - - json network(_readJson(_networkJP(nwid,false))); - if (!network.size()) - return 404; - - if (path.size() >= 3) { - if ((path.size() == 4)&&(path[2] == "member")&&(path[3].length() == 10)) { - const uint64_t address = Utils::hexStrToU64(path[3].c_str()); - - json member(_readJson(_memberJP(nwid,Address(address),false))); - if (!member.size()) - return 404; - - OSUtils::rmDashRf(_memberBP(nwid,Address(address),false).c_str()); - - responseBody = member.dump(2); - responseContentType = "application/json"; - return 200; - } - } else { - OSUtils::rmDashRf(_networkBP(nwid,false).c_str()); - responseBody = network.dump(2); - responseContentType = "application/json"; - return 200; - } - } // else 404 - - } // else 404 - - return 404; -} - -void SqliteNetworkController::_circuitTestCallback(ZT_Node *node,ZT_CircuitTest *test,const ZT_CircuitTestReport *report) -{ - char tmp[65535]; - SqliteNetworkController *const self = reinterpret_cast(test->ptr); - - if (!test) - return; - if (!report) - return; - - Mutex::Lock _l(self->_circuitTests_m); - std::map< uint64_t,_CircuitTestEntry >::iterator cte(self->_circuitTests.find(test->testId)); - - if (cte == self->_circuitTests.end()) { // sanity check: a circuit test we didn't launch? - self->_node->circuitTestEnd(test); - ::free((void *)test); - return; - } - - Utils::snprintf(tmp,sizeof(tmp), - "%s{\n" - "\t\"timestamp\": %llu," ZT_EOL_S - "\t\"testId\": \"%.16llx\"," ZT_EOL_S - "\t\"upstream\": \"%.10llx\"," ZT_EOL_S - "\t\"current\": \"%.10llx\"," ZT_EOL_S - "\t\"receivedTimestamp\": %llu," ZT_EOL_S - "\t\"remoteTimestamp\": %llu," ZT_EOL_S - "\t\"sourcePacketId\": \"%.16llx\"," ZT_EOL_S - "\t\"flags\": %llu," ZT_EOL_S - "\t\"sourcePacketHopCount\": %u," ZT_EOL_S - "\t\"errorCode\": %u," ZT_EOL_S - "\t\"vendor\": %d," ZT_EOL_S - "\t\"protocolVersion\": %u," ZT_EOL_S - "\t\"majorVersion\": %u," ZT_EOL_S - "\t\"minorVersion\": %u," ZT_EOL_S - "\t\"revision\": %u," ZT_EOL_S - "\t\"platform\": %d," ZT_EOL_S - "\t\"architecture\": %d," ZT_EOL_S - "\t\"receivedOnLocalAddress\": \"%s\"," ZT_EOL_S - "\t\"receivedFromRemoteAddress\": \"%s\"" ZT_EOL_S - "}", - ((cte->second.jsonResults.length() > 0) ? ",\n" : ""), - (unsigned long long)report->timestamp, - (unsigned long long)test->testId, - (unsigned long long)report->upstream, - (unsigned long long)report->current, - (unsigned long long)OSUtils::now(), - (unsigned long long)report->remoteTimestamp, - (unsigned long long)report->sourcePacketId, - (unsigned long long)report->flags, - report->sourcePacketHopCount, - report->errorCode, - (int)report->vendor, - report->protocolVersion, - report->majorVersion, - report->minorVersion, - report->revision, - (int)report->platform, - (int)report->architecture, - reinterpret_cast(&(report->receivedOnLocalAddress))->toString().c_str(), - reinterpret_cast(&(report->receivedFromRemoteAddress))->toString().c_str()); - - cte->second.jsonResults.append(tmp); -} - -} // namespace ZeroTier diff --git a/controller/SqliteNetworkController.hpp b/controller/SqliteNetworkController.hpp deleted file mode 100644 index 288ea23a..00000000 --- a/controller/SqliteNetworkController.hpp +++ /dev/null @@ -1,173 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2015 ZeroTier, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef ZT_SQLITENETWORKCONTROLLER_HPP -#define ZT_SQLITENETWORKCONTROLLER_HPP - -#include - -#include -#include -#include -#include - -#include "../node/Constants.hpp" - -#include "../node/NetworkController.hpp" -#include "../node/Mutex.hpp" -#include "../node/Utils.hpp" -#include "../node/InetAddress.hpp" - -#include "../osdep/OSUtils.hpp" - -#include "../ext/json/json.hpp" - -namespace ZeroTier { - -class Node; - -class SqliteNetworkController : public NetworkController -{ -public: - SqliteNetworkController(Node *node,const char *dbPath); - virtual ~SqliteNetworkController(); - - virtual NetworkController::ResultCode doNetworkConfigRequest( - const InetAddress &fromAddr, - const Identity &signingId, - const Identity &identity, - uint64_t nwid, - const Dictionary &metaData, - NetworkConfig &nc); - - unsigned int handleControlPlaneHttpGET( - const std::vector &path, - const std::map &urlArgs, - const std::map &headers, - const std::string &body, - std::string &responseBody, - std::string &responseContentType); - unsigned int handleControlPlaneHttpPOST( - const std::vector &path, - const std::map &urlArgs, - const std::map &headers, - const std::string &body, - std::string &responseBody, - std::string &responseContentType); - unsigned int handleControlPlaneHttpDELETE( - const std::vector &path, - const std::map &urlArgs, - const std::map &headers, - const std::string &body, - std::string &responseBody, - std::string &responseContentType); - -private: - static void _circuitTestCallback(ZT_Node *node,ZT_CircuitTest *test,const ZT_CircuitTestReport *report); - - inline nlohmann::json _readJson(const std::string &path) - { - std::string buf; - if (OSUtils::readFile(path.c_str(),buf)) { - try { - return nlohmann::json::parse(buf); - } catch ( ... ) {} - } - return nlohmann::json::object(); - } - - inline bool _writeJson(const std::string &path,const nlohmann::json &obj) - { - std::string buf(obj.dump(2)); - return OSUtils::writeFile(path.c_str(),buf); - } - - inline std::string _networkBP(const uint64_t nwid,bool create) - { - char tmp[64]; - Utils::snprintf(tmp,sizeof(tmp),"%.16llx",nwid); - std::string p(_path + ZT_PATH_SEPARATOR_S + "network"); - if (create) OSUtils::mkdir(p.c_str()); - p.push_back(ZT_PATH_SEPARATOR); - p.append(tmp); - if (create) OSUtils::mkdir(p.c_str()); - return p; - } - inline std::string _networkJP(const uint64_t nwid,bool create) - { - return (_networkBP(nwid,create) + ZT_PATH_SEPARATOR + "config.json"); - } - inline std::string _memberBP(const uint64_t nwid,const Address &member,bool create) - { - std::string p(_networkBP(nwid,create)); - p.push_back(ZT_PATH_SEPARATOR); - p.append("member"); - if (create) OSUtils::mkdir(p.c_str()); - p.push_back(ZT_PATH_SEPARATOR); - p.append(member.toString()); - if (create) OSUtils::mkdir(p.c_str()); - return p; - } - inline std::string _memberJP(const uint64_t nwid,const Address &member,bool create) - { - return (_memberBP(nwid,member,create) + ZT_PATH_SEPARATOR + "config.json"); - } - - inline std::set _getAlreadyAllocatedIps(const uint64_t nwid) - { - std::set ips; - std::string bp(_networkBP(nwid,false) + ZT_PATH_SEPARATOR_S + "member"); - std::vector members(OSUtils::listSubdirectories(bp.c_str())); - for(std::vector::iterator m(members.begin());m!=members.end();++m) { - if (m->length() == ZT_ADDRESS_LENGTH_HEX) { - nlohmann::json mj = _readJson(bp + ZT_PATH_SEPARATOR_S + *m + ZT_PATH_SEPARATOR_S + "config.json"); - auto ipAssignments = mj["ipAssignments"]; - if (ipAssignments.is_array()) { - for(unsigned long i=0;i _circuitTests; - Mutex _circuitTests_m; - - // Last request time by address, for rate limitation - std::map< std::pair,uint64_t > _lastRequestTime; - Mutex _lastRequestTime_m; -}; - -} // namespace ZeroTier - -#endif diff --git a/make-linux.mk b/make-linux.mk index acc22a63..d0d206a1 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -82,12 +82,6 @@ ifeq ($(ZT_USE_MINIUPNPC),1) endif endif -ifeq ($(ZT_ENABLE_NETWORK_CONTROLLER),1) - DEFS+=-DZT_ENABLE_NETWORK_CONTROLLER - LDLIBS+=-L/usr/local/lib -lsqlite3 - OBJS+=controller/SqliteNetworkController.o -endif - ifeq ($(ZT_ENABLE_CLUSTER),1) DEFS+=-DZT_ENABLE_CLUSTER endif diff --git a/make-mac.mk b/make-mac.mk index 63ffc3c8..f00f8d6b 100644 --- a/make-mac.mk +++ b/make-mac.mk @@ -45,12 +45,6 @@ ifeq ($(ZT_USE_MINIUPNPC),1) OBJS+=ext/libnatpmp/natpmp.o ext/libnatpmp/getgateway.o ext/miniupnpc/connecthostport.o ext/miniupnpc/igd_desc_parse.o ext/miniupnpc/minisoap.o ext/miniupnpc/minissdpc.o ext/miniupnpc/miniupnpc.o ext/miniupnpc/miniwget.o ext/miniupnpc/minixml.o ext/miniupnpc/portlistingparse.o ext/miniupnpc/receivedata.o ext/miniupnpc/upnpcommands.o ext/miniupnpc/upnpdev.o ext/miniupnpc/upnperrors.o ext/miniupnpc/upnpreplyparse.o osdep/PortMapper.o endif -ifeq ($(ZT_ENABLE_NETWORK_CONTROLLER),1) - DEFS+=-DZT_ENABLE_NETWORK_CONTROLLER - LIBS+=-L/usr/local/lib -lsqlite3 - OBJS+=controller/SqliteNetworkController.o -endif - # Debug mode -- dump trace output, build binary with -g ifeq ($(ZT_DEBUG),1) DEFS+=-DZT_TRACE diff --git a/objects.mk b/objects.mk index 11b03c81..f92a907e 100644 --- a/objects.mk +++ b/objects.mk @@ -1,4 +1,5 @@ OBJS=\ + controller/EmbeddedNetworkController.o \ node/C25519.o \ node/Capability.o \ node/CertificateOfMembership.o \ diff --git a/selftest.cpp b/selftest.cpp index f4232851..ab05c9ef 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -53,10 +53,6 @@ #include "osdep/PortMapper.hpp" #include "osdep/Thread.hpp" -#ifdef ZT_ENABLE_NETWORK_CONTROLLER -#include "controller/SqliteNetworkController.hpp" -#endif // ZT_ENABLE_NETWORK_CONTROLLER - #ifdef __WINDOWS__ #include #endif diff --git a/service/ControlPlane.cpp b/service/ControlPlane.cpp index a10697a9..7aa757a9 100644 --- a/service/ControlPlane.cpp +++ b/service/ControlPlane.cpp @@ -34,9 +34,7 @@ #include "../ext/json-parser/json.h" #endif -#ifdef ZT_ENABLE_NETWORK_CONTROLLER -#include "../controller/SqliteNetworkController.hpp" -#endif +#include "../controller/EmbeddedNetworkController.hpp" #include "../node/InetAddress.hpp" #include "../node/Node.hpp" @@ -254,9 +252,7 @@ static void _jsonAppend(unsigned int depth,std::string &buf,const ZT_Peer *peer) ControlPlane::ControlPlane(OneService *svc,Node *n,const char *uiStaticPath) : _svc(svc), _node(n), -#ifdef ZT_ENABLE_NETWORK_CONTROLLER - _controller((SqliteNetworkController *)0), -#endif + _controller((EmbeddedNetworkController *)0), _uiStaticPath((uiStaticPath) ? uiStaticPath : "") { } @@ -499,13 +495,9 @@ unsigned int ControlPlane::handleRequest( responseContentType = "text/plain"; scode = 200; } else { -#ifdef ZT_ENABLE_NETWORK_CONTROLLER if (_controller) scode = _controller->handleControlPlaneHttpGET(std::vector(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType); else scode = 404; -#else - scode = 404; -#endif } } else scode = 401; // isAuth == false @@ -559,13 +551,9 @@ unsigned int ControlPlane::handleRequest( } else scode = 500; } } else { -#ifdef ZT_ENABLE_NETWORK_CONTROLLER if (_controller) scode = _controller->handleControlPlaneHttpPOST(std::vector(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType); else scode = 404; -#else - scode = 404; -#endif } } else scode = 401; // isAuth == false @@ -594,13 +582,9 @@ unsigned int ControlPlane::handleRequest( _node->freeQueryResult((void *)nws); } else scode = 500; } else { -#ifdef ZT_ENABLE_NETWORK_CONTROLLER if (_controller) scode = _controller->handleControlPlaneHttpDELETE(std::vector(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType); else scode = 404; -#else - scode = 404; -#endif } } else { diff --git a/service/ControlPlane.hpp b/service/ControlPlane.hpp index 08a9d6e0..ec9b94d7 100644 --- a/service/ControlPlane.hpp +++ b/service/ControlPlane.hpp @@ -31,7 +31,7 @@ namespace ZeroTier { class OneService; class Node; -class SqliteNetworkController; +class EmbeddedNetworkController; struct InetAddress; /** @@ -43,18 +43,16 @@ public: ControlPlane(OneService *svc,Node *n,const char *uiStaticPath); ~ControlPlane(); -#ifdef ZT_ENABLE_NETWORK_CONTROLLER /** * Set controller, which will be available under /controller * * @param c Network controller instance */ - inline void setController(SqliteNetworkController *c) + inline void setController(EmbeddedNetworkController *c) { Mutex::Lock _l(_lock); _controller = c; } -#endif /** * Add an authentication token for API access @@ -89,9 +87,7 @@ public: private: OneService *const _svc; Node *const _node; -#ifdef ZT_ENABLE_NETWORK_CONTROLLER - SqliteNetworkController *_controller; -#endif + EmbeddedNetworkController *_controller; std::string _uiStaticPath; std::set _authTokens; Mutex _lock; diff --git a/service/OneService.cpp b/service/OneService.cpp index 5c65dcc2..74628168 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -69,11 +69,7 @@ */ //#define ZT_BREAK_UDP -#ifdef ZT_ENABLE_NETWORK_CONTROLLER -#include "../controller/SqliteNetworkController.hpp" -#else -class SqliteNetworkController; -#endif // ZT_ENABLE_NETWORK_CONTROLLER +#include "../controller/EmbeddedNetworkController.hpp" #ifdef __WINDOWS__ #include @@ -129,7 +125,7 @@ namespace ZeroTier { typedef BSDEthernetTap EthernetTap; } #define ZT_TAP_CHECK_MULTICAST_INTERVAL 5000 // Path under ZT1 home for controller database if controller is enabled -#define ZT_CONTROLLER_DB_PATH "controller.db" +#define ZT_CONTROLLER_DB_PATH "controller.d" // TCP fallback relay host -- geo-distributed using Amazon Route53 geo-aware DNS #define ZT_TCP_FALLBACK_RELAY "tcp-fallback.zerotier.com" @@ -487,9 +483,7 @@ public: const std::string _homePath; BackgroundResolver _tcpFallbackResolver; -#ifdef ZT_ENABLE_NETWORK_CONTROLLER - SqliteNetworkController *_controller; -#endif + EmbeddedNetworkController *_controller; Phy _phy; Node *_node; @@ -579,9 +573,7 @@ public: OneServiceImpl(const char *hp,unsigned int port) : _homePath((hp) ? hp : ".") ,_tcpFallbackResolver(ZT_TCP_FALLBACK_RELAY) -#ifdef ZT_ENABLE_NETWORK_CONTROLLER - ,_controller((SqliteNetworkController *)0) -#endif + ,_controller((EmbeddedNetworkController *)0) ,_phy(this,false,true) ,_node((Node *)0) ,_controlPlane((ControlPlane *)0) @@ -673,9 +665,7 @@ public: #ifdef ZT_USE_MINIUPNPC delete _portMapper; #endif -#ifdef ZT_ENABLE_NETWORK_CONTROLLER delete _controller; -#endif #ifdef ZT_ENABLE_CLUSTER delete _clusterDefinition; #endif @@ -794,10 +784,8 @@ public: } } -#ifdef ZT_ENABLE_NETWORK_CONTROLLER - _controller = new SqliteNetworkController(_node,(_homePath + ZT_PATH_SEPARATOR_S + ZT_CONTROLLER_DB_PATH).c_str(),(_homePath + ZT_PATH_SEPARATOR_S + "circuitTestResults.d").c_str()); + _controller = new EmbeddedNetworkController(_node,(_homePath + ZT_PATH_SEPARATOR_S + ZT_CONTROLLER_DB_PATH).c_str()); _node->setNetconfMaster((void *)_controller); -#endif #ifdef ZT_ENABLE_CLUSTER if (OSUtils::fileExists((_homePath + ZT_PATH_SEPARATOR_S + "cluster").c_str())) { @@ -850,10 +838,7 @@ public: _controlPlane = new ControlPlane(this,_node,(_homePath + ZT_PATH_SEPARATOR_S + "ui").c_str()); _controlPlane->addAuthToken(authToken.c_str()); - -#ifdef ZT_ENABLE_NETWORK_CONTROLLER _controlPlane->setController(_controller); -#endif { // Remember networks from previous session std::vector networksDotD(OSUtils::listDirectory((_homePath + ZT_PATH_SEPARATOR_S + "networks.d").c_str())); diff --git a/service/OneService.hpp b/service/OneService.hpp index cead381d..72ff7d84 100644 --- a/service/OneService.hpp +++ b/service/OneService.hpp @@ -25,18 +25,6 @@ namespace ZeroTier { /** * Local service for ZeroTier One as system VPN/NFV provider - * - * If built with ZT_ENABLE_NETWORK_CONTROLLER defined, this includes and - * runs controller/SqliteNetworkController with a database called - * controller.db in the specified home directory. - * - * If built with ZT_AUTO_UPDATE, an official ZeroTier update URL is - * periodically checked and updates are automatically downloaded, verified - * against a built-in list of update signing keys, and installed. This is - * only supported for certain platforms. - * - * If built with ZT_ENABLE_CLUSTER, a 'cluster' file is checked and if - * present is read to determine the identity of other cluster members. */ class OneService { -- cgit v1.2.3 From faa9a06bf5302b246805ead12690b38c3036d802 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 17 Aug 2016 17:37:37 -0700 Subject: Controller fixes... --- controller/EmbeddedNetworkController.cpp | 219 +++++++++++++++++++------------ controller/README.md | 2 +- node/IncomingPacket.cpp | 6 +- service/OneService.cpp | 4 + 4 files changed, 148 insertions(+), 83 deletions(-) (limited to 'service/OneService.cpp') diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index 30072f95..649ff094 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -60,6 +60,50 @@ using json = nlohmann::json; namespace ZeroTier { +static uint64_t _jI(const json &jv,const uint64_t dfl) +{ + if (jv.is_number()) { + return (uint64_t)jv; + } else if (jv.is_string()) { + std::string s = jv; + return Utils::strToU64(s.c_str()); + } else if (jv.is_boolean()) { + return ((bool)jv ? 1ULL : 0ULL); + } + return dfl; +} +static bool _jB(const json &jv,const bool dfl) +{ + if (jv.is_boolean()) { + return (bool)jv; + } else if (jv.is_number()) { + return ((uint64_t)jv > 0ULL); + } else if (jv.is_string()) { + std::string s = jv; + if (s.length() > 0) { + switch(s[0]) { + case 't': + case 'T': + case '1': + return true; + } + } + return false; + } + return dfl; +} +static std::string _jS(const json &jv,const char *dfl) +{ + if (jv.is_string()) { + return jv; + } else if (jv.is_number()) { + return jv; + } else if (jv.is_boolean()) { + return ((bool)jv ? std::string("1") : std::string("0")); + } + return std::string((dfl) ? dfl : ""); +} + static json _renderRule(ZT_VirtualNetworkRule &rule) { char tmp[128]; @@ -190,7 +234,7 @@ static bool _parseRule(const json &r,ZT_VirtualNetworkRule &rule) return false; std::string t = r["type"]; memset(&rule,0,sizeof(ZT_VirtualNetworkRule)); - if (r.value("not",false)) + if (_jB(r["not"],false)) rule.t = 0x80; else rule.t = 0x00; if (t == "ACTION_DROP") { @@ -201,91 +245,91 @@ static bool _parseRule(const json &r,ZT_VirtualNetworkRule &rule) return true; } else if (t == "ACTION_TEE") { rule.t |= ZT_NETWORK_RULE_ACTION_TEE; - rule.v.zt = Utils::hexStrToU64(r.value("zt","0").c_str()) & 0xffffffffffULL; + rule.v.zt = Utils::hexStrToU64(_jS(r["zt"],"0").c_str()) & 0xffffffffffULL; return true; } else if (t == "ACTION_REDIRECT") { rule.t |= ZT_NETWORK_RULE_ACTION_REDIRECT; - rule.v.zt = Utils::hexStrToU64(r.value("zt","0").c_str()) & 0xffffffffffULL; + rule.v.zt = Utils::hexStrToU64(_jS(r["zt"],"0").c_str()) & 0xffffffffffULL; return true; } else if (t == "MATCH_SOURCE_ZEROTIER_ADDRESS") { rule.t |= ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS; - rule.v.zt = Utils::hexStrToU64(r.value("zt","0").c_str()) & 0xffffffffffULL; + rule.v.zt = Utils::hexStrToU64(_jS(r["zt"],"0").c_str()) & 0xffffffffffULL; return true; } else if (t == "MATCH_DEST_ZEROTIER_ADDRESS") { rule.t |= ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS; - rule.v.zt = Utils::hexStrToU64(r.value("zt","0").c_str()) & 0xffffffffffULL; + rule.v.zt = Utils::hexStrToU64(_jS(r["zt"],"0").c_str()) & 0xffffffffffULL; return true; } else if (t == "MATCH_VLAN_ID") { rule.t |= ZT_NETWORK_RULE_MATCH_VLAN_ID; - rule.v.vlanId = (uint16_t)(r.value("vlanId",0ULL) & 0xffffULL); + rule.v.vlanId = (uint16_t)(_jI(r["vlanId"],0ULL) & 0xffffULL); return true; } else if (t == "MATCH_VLAN_PCP") { rule.t |= ZT_NETWORK_RULE_MATCH_VLAN_PCP; - rule.v.vlanPcp = (uint8_t)(r.value("vlanPcp",0ULL) & 0xffULL); + rule.v.vlanPcp = (uint8_t)(_jI(r["vlanPcp"],0ULL) & 0xffULL); return true; } else if (t == "MATCH_VLAN_DEI") { rule.t |= ZT_NETWORK_RULE_MATCH_VLAN_DEI; - rule.v.vlanDei = (uint8_t)(r.value("vlanDei",0ULL) & 0xffULL); + rule.v.vlanDei = (uint8_t)(_jI(r["vlanDei"],0ULL) & 0xffULL); return true; } else if (t == "MATCH_ETHERTYPE") { rule.t |= ZT_NETWORK_RULE_MATCH_ETHERTYPE; - rule.v.etherType = (uint16_t)(r.value("etherType",0ULL) & 0xffffULL); + rule.v.etherType = (uint16_t)(_jI(r["etherType"],0ULL) & 0xffffULL); return true; } else if (t == "MATCH_MAC_SOURCE") { rule.t |= ZT_NETWORK_RULE_MATCH_MAC_SOURCE; - const std::string mac(r.value("mac","0")); + const std::string mac(_jS(r["mac"],"0")); Utils::unhex(mac.c_str(),(unsigned int)mac.length(),rule.v.mac,6); return true; } else if (t == "MATCH_MAC_DEST") { rule.t |= ZT_NETWORK_RULE_MATCH_MAC_DEST; - const std::string mac(r.value("mac","0")); + const std::string mac(_jS(r["mac"],"0")); Utils::unhex(mac.c_str(),(unsigned int)mac.length(),rule.v.mac,6); return true; } else if (t == "MATCH_IPV4_SOURCE") { rule.t |= ZT_NETWORK_RULE_MATCH_IPV4_SOURCE; - InetAddress ip(r.value("ip","0.0.0.0")); + InetAddress ip(_jS(r["ip"],"0.0.0.0")); rule.v.ipv4.ip = reinterpret_cast(&ip)->sin_addr.s_addr; rule.v.ipv4.mask = Utils::ntoh(reinterpret_cast(&ip)->sin_port) & 0xff; if (rule.v.ipv4.mask > 32) rule.v.ipv4.mask = 32; return true; } else if (t == "MATCH_IPV4_DEST") { rule.t |= ZT_NETWORK_RULE_MATCH_IPV4_DEST; - InetAddress ip(r.value("ip","0.0.0.0")); + InetAddress ip(_jS(r["ip"],"0.0.0.0")); rule.v.ipv4.ip = reinterpret_cast(&ip)->sin_addr.s_addr; rule.v.ipv4.mask = Utils::ntoh(reinterpret_cast(&ip)->sin_port) & 0xff; if (rule.v.ipv4.mask > 32) rule.v.ipv4.mask = 32; return true; } else if (t == "MATCH_IPV6_SOURCE") { rule.t |= ZT_NETWORK_RULE_MATCH_IPV6_SOURCE; - InetAddress ip(r.value("ip","::0")); + InetAddress ip(_jS(r["ip"],"::0")); memcpy(rule.v.ipv6.ip,reinterpret_cast(&ip)->sin6_addr.s6_addr,16); rule.v.ipv6.mask = Utils::ntoh(reinterpret_cast(&ip)->sin6_port) & 0xff; if (rule.v.ipv6.mask > 128) rule.v.ipv6.mask = 128; return true; } else if (t == "MATCH_IPV6_DEST") { rule.t |= ZT_NETWORK_RULE_MATCH_IPV6_DEST; - InetAddress ip(r.value("ip","::0")); + InetAddress ip(_jS(r["ip"],"::0")); memcpy(rule.v.ipv6.ip,reinterpret_cast(&ip)->sin6_addr.s6_addr,16); rule.v.ipv6.mask = Utils::ntoh(reinterpret_cast(&ip)->sin6_port) & 0xff; if (rule.v.ipv6.mask > 128) rule.v.ipv6.mask = 128; return true; } else if (t == "MATCH_IP_TOS") { rule.t |= ZT_NETWORK_RULE_MATCH_IP_TOS; - rule.v.ipTos = (uint8_t)(r.value("ipTos",0ULL) & 0xffULL); + rule.v.ipTos = (uint8_t)(_jI(r["ipTos"],0ULL) & 0xffULL); return true; } else if (t == "MATCH_IP_PROTOCOL") { rule.t |= ZT_NETWORK_RULE_MATCH_IP_PROTOCOL; - rule.v.ipProtocol = (uint8_t)(r.value("ipProtocol",0ULL) & 0xffULL); + rule.v.ipProtocol = (uint8_t)(_jI(r["ipProtocol"],0ULL) & 0xffULL); return true; } else if (t == "MATCH_IP_SOURCE_PORT_RANGE") { rule.t |= ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE; - rule.v.port[0] = (uint16_t)(r.value("start",0ULL) & 0xffffULL); - rule.v.port[1] = (uint16_t)(r.value("end",(uint64_t)rule.v.port[0]) & 0xffffULL); + rule.v.port[0] = (uint16_t)(_jI(r["start"],0ULL) & 0xffffULL); + rule.v.port[1] = (uint16_t)(_jI(r["end"],(uint64_t)rule.v.port[0]) & 0xffffULL); return true; } else if (t == "MATCH_IP_DEST_PORT_RANGE") { rule.t |= ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE; - rule.v.port[0] = (uint16_t)(r.value("start",0ULL) & 0xffffULL); - rule.v.port[1] = (uint16_t)(r.value("end",(uint64_t)rule.v.port[0]) & 0xffffULL); + rule.v.port[0] = (uint16_t)(_jI(r["start"],0ULL) & 0xffffULL); + rule.v.port[1] = (uint16_t)(_jI(r["end"],(uint64_t)rule.v.port[0]) & 0xffffULL); return true; } else if (t == "MATCH_CHARACTERISTICS") { rule.t |= ZT_NETWORK_RULE_MATCH_CHARACTERISTICS; @@ -310,28 +354,28 @@ static bool _parseRule(const json &r,ZT_VirtualNetworkRule &rule) return true; } else if (t == "MATCH_FRAME_SIZE_RANGE") { rule.t |= ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE; - rule.v.frameSize[0] = (uint16_t)(r.value("start",0ULL) & 0xffffULL); - rule.v.frameSize[1] = (uint16_t)(r.value("end",(uint64_t)rule.v.frameSize[0]) & 0xffffULL); + rule.v.frameSize[0] = (uint16_t)(_jI(r["start"],0ULL) & 0xffffULL); + rule.v.frameSize[1] = (uint16_t)(_jI(r["end"],(uint64_t)rule.v.frameSize[0]) & 0xffffULL); return true; } else if (t == "MATCH_TAGS_SAMENESS") { rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_SAMENESS; - rule.v.tag.id = (uint32_t)(r.value("id",0ULL) & 0xffffffffULL); - rule.v.tag.value = (uint32_t)(r.value("value",0ULL) & 0xffffffffULL); + rule.v.tag.id = (uint32_t)(_jI(r["id"],0ULL) & 0xffffffffULL); + rule.v.tag.value = (uint32_t)(_jI(r["value"],0ULL) & 0xffffffffULL); return true; } else if (t == "MATCH_TAGS_BITWISE_AND") { rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND; - rule.v.tag.id = (uint32_t)(r.value("id",0ULL) & 0xffffffffULL); - rule.v.tag.value = (uint32_t)(r.value("value",0ULL) & 0xffffffffULL); + rule.v.tag.id = (uint32_t)(_jI(r["id"],0ULL) & 0xffffffffULL); + rule.v.tag.value = (uint32_t)(_jI(r["value"],0ULL) & 0xffffffffULL); return true; } else if (t == "MATCH_TAGS_BITWISE_OR") { rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR; - rule.v.tag.id = (uint32_t)(r.value("id",0ULL) & 0xffffffffULL); - rule.v.tag.value = (uint32_t)(r.value("value",0ULL) & 0xffffffffULL); + rule.v.tag.id = (uint32_t)(_jI(r["id"],0ULL) & 0xffffffffULL); + rule.v.tag.value = (uint32_t)(_jI(r["value"],0ULL) & 0xffffffffULL); return true; } else if (t == "MATCH_TAGS_BITWISE_XOR") { rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR; - rule.v.tag.id = (uint32_t)(r.value("id",0ULL) & 0xffffffffULL); - rule.v.tag.value = (uint32_t)(r.value("value",0ULL) & 0xffffffffULL); + rule.v.tag.id = (uint32_t)(_jI(r["id"],0ULL) & 0xffffffffULL); + rule.v.tag.value = (uint32_t)(_jI(r["value"],0ULL) & 0xffffffffULL); return true; } return false; @@ -613,7 +657,7 @@ NetworkController::ResultCode EmbeddedNetworkController::doNetworkConfigRequest( json member(_readJson(memberJP)); { - std::string haveIdStr = member.value("identity",""); + std::string haveIdStr(_jS(member["identity"],"")); if (haveIdStr.length() > 0) { try { if (Identity(haveIdStr.c_str()) != identity) @@ -630,13 +674,18 @@ NetworkController::ResultCode EmbeddedNetworkController::doNetworkConfigRequest( member["id"] = identity.address().toString(); member["address"] = member["id"]; member["nwid"] = network["id"]; - member["memberRevision"] = member.value("memberRevision",0ULL) + 1; + member["lastModified"] = now; + { + auto revj = member["revision"]; + const uint64_t rev = (revj.is_number() ? ((uint64_t)revj + 1ULL) : 1ULL); + member["revision"] = rev; + } // Determine whether and how member is authorized const char *authorizedBy = (const char *)0; - if (!network.value("private",true)) { + if (!_jB(network["private"],true)) { authorizedBy = "networkIsPublic"; - } else if (member.value("authorized",false)) { + } else if (_jB(member["authorized"],false)) { authorizedBy = "memberIsAuthorized"; } else { char atok[256]; @@ -648,8 +697,8 @@ NetworkController::ResultCode EmbeddedNetworkController::doNetworkConfigRequest( for(unsigned long i=0;i now)) && (tok.length() > 0) && (tok == atok) ) { authorizedBy = "token"; break; @@ -700,14 +749,14 @@ NetworkController::ResultCode EmbeddedNetworkController::doNetworkConfigRequest( // If we made it this far, they are authorized. nc.networkId = nwid; - nc.type = network.value("private",true) ? ZT_NETWORK_TYPE_PRIVATE : ZT_NETWORK_TYPE_PUBLIC; + nc.type = _jB(network["private"],true) ? ZT_NETWORK_TYPE_PRIVATE : ZT_NETWORK_TYPE_PUBLIC; nc.timestamp = now; - nc.revision = network.value("revision",0ULL); + nc.revision = _jI(network["revision"],0ULL); nc.issuedTo = identity.address(); - if (network.value("enableBroadcast",true)) nc.flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST; - if (network.value("allowPassiveBridging",false)) nc.flags |= ZT_NETWORKCONFIG_FLAG_ALLOW_PASSIVE_BRIDGING; - Utils::scopy(nc.name,sizeof(nc.name),network.value("name","").c_str()); - nc.multicastLimit = (unsigned int)network.value("multicastLimit",32ULL); + if (_jB(network["enableBroadcast"],true)) nc.flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST; + if (_jB(network["allowPassiveBridging"],false)) nc.flags |= ZT_NETWORKCONFIG_FLAG_ALLOW_PASSIVE_BRIDGING; + Utils::scopy(nc.name,sizeof(nc.name),_jS(network["name"],"").c_str()); + nc.multicastLimit = (unsigned int)_jI(network["multicastLimit"],32ULL); bool amActiveBridge = false; { @@ -732,11 +781,11 @@ NetworkController::ResultCode EmbeddedNetworkController::doNetworkConfigRequest( auto rules = network["rules"]; if (v6AssignMode.is_object()) { - if ((v6AssignMode.value("rfc4193",false))&&(nc.staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES)) { + if ((_jB(v6AssignMode["rfc4193"],false))&&(nc.staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES)) { nc.staticIps[nc.staticIpCount++] = InetAddress::makeIpv6rfc4193(nwid,identity.address().toInt()); nc.flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION; } - if ((v6AssignMode.value("6plane",false))&&(nc.staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES)) { + if ((_jB(v6AssignMode["6plane"],false))&&(nc.staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES)) { nc.staticIps[nc.staticIpCount++] = InetAddress::makeIpv66plane(nwid,identity.address().toInt()); nc.flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION; } @@ -757,8 +806,8 @@ NetworkController::ResultCode EmbeddedNetworkController::doNetworkConfigRequest( if (nc.routeCount >= ZT_MAX_NETWORK_ROUTES) break; auto route = routes[i]; - InetAddress t(route.value("target","")); - InetAddress v(route.value("via","")); + InetAddress t(_jS(route["target"],"")); + InetAddress v(_jS(route["via"],"")); if ((t)&&(v)&&(t.ss_family == v.ss_family)) { ZT_VirtualNetworkRoute *r = &(nc.routes[nc.routeCount]); *(reinterpret_cast(&(r->target))) = t; @@ -803,13 +852,13 @@ NetworkController::ResultCode EmbeddedNetworkController::doNetworkConfigRequest( std::set allocatedIps; bool allocatedIpsLoaded = false; - if ( (ipAssignmentPools.is_array()) && ((v6AssignMode.is_object())&&(v6AssignMode.value("zt",false))) && (!haveManagedIpv6AutoAssignment) && (!amActiveBridge) ) { + if ( (ipAssignmentPools.is_array()) && ((v6AssignMode.is_object())&&(_jB(v6AssignMode["zt"],false))) && (!haveManagedIpv6AutoAssignment) && (!amActiveBridge) ) { if (!allocatedIpsLoaded) allocatedIps = _getAlreadyAllocatedIps(nwid); for(unsigned long p=0;((p(&ipRangeStart)->sin_addr.s_addr)); uint32_t ipRangeEnd = Utils::ntoh((uint32_t)(reinterpret_cast(&ipRangeEnd)->sin_addr.s_addr)); @@ -921,7 +970,7 @@ NetworkController::ResultCode EmbeddedNetworkController::doNetworkConfigRequest( } } - if (network.value("private",true)) { + if (_jB(network["private"],true)) { CertificateOfMembership com(now,ZT_NETWORK_COM_DEFAULT_REVISION_MAX_DELTA,nwid,identity.address()); if (com.sign(signingId)) { nc.com = com; @@ -983,8 +1032,10 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( responseBody.append((responseBody.length() == 1) ? "\"" : ",\""); responseBody.append(*i); responseBody.append("\":"); - const std::string rc = member.value("memberRevision","0"); - responseBody.append(rc); + auto rev = member["revision"]; + if (rev.is_number()) + responseBody.append(rev); + else responseBody.push_back('0'); } } } @@ -1006,7 +1057,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( auto recentLog = member["recentLog"]; if ((recentLog.is_array())&&(recentLog.size() > 0)) { auto mostRecentLog = recentLog[0]; - if ((mostRecentLog.is_object())&&((uint64_t)mostRecentLog.value("ts",0ULL) >= threshold)) { + if ((mostRecentLog.is_object())&&(_jI(mostRecentLog["ts"],0ULL) >= threshold)) { responseBody.append((responseBody.length() == 1) ? "\"" : ",\""); responseBody.append(*i); responseBody.append("\":"); @@ -1116,8 +1167,8 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( json member(_readJson(_memberJP(nwid,Address(address),true))); try { - if (b.count("authorized")) member["authorized"] = b.value("authorized",false); - if ((b.count("identity"))&&(!member.count("identity"))) member["identity"] = b.value("identity",""); // allow identity to be populated only if not already known + if (b.count("authorized")) member["authorized"] = _jB(b["authorized"],false); + if ((b.count("identity"))&&(!member.count("identity"))) member["identity"] = _jS(b["identity"],""); // allow identity to be populated only if not already known if (b.count("ipAssignments")) { auto ipa = b["ipAssignments"]; @@ -1144,12 +1195,17 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( member["id"] = addrs; member["address"] = addrs; // legacy member["nwid"] = nwids; - member["memberRevision"] = member.value("memberRevision",0ULL) + 1; member["objtype"] = "member"; + member["lastModified"] = OSUtils::now(); + { + auto revj = member["revision"]; + const uint64_t rev = (revj.is_number() ? ((uint64_t)revj + 1ULL) : 1ULL); + member["revision"] = rev; + } _writeJson(_memberJP(nwid,Address(address),true).c_str(),member); - member["clock"] = OSUtils::now(); + member["clock"] = member["lastModified"]; responseBody = member.dump(2); responseContentType = "application/json"; return 200; @@ -1178,7 +1234,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( } } } - test->reportAtEveryHop = (b.value("reportAtEveryHop",true) ? 1 : 0); + test->reportAtEveryHop = (_jB(b["reportAtEveryHop"],true) ? 1 : 0); if (!test->hopCount) { ::free((void *)test); @@ -1226,11 +1282,11 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( json network(_readJson(_networkJP(nwid,true))); try { - if (b.count("name")) network["name"] = b.value("name",""); - if (b.count("private")) network["private"] = b.value("private",true); - if (b.count("enableBroadcast")) network["enableBroadcast"] = b.value("enableBroadcast",false); - if (b.count("allowPassiveBridging")) network["allowPassiveBridging"] = b.value("allowPassiveBridging",false); - if (b.count("multicastLimit")) network["multicastLimit"] = b.value("multicastLimit",32ULL); + if (b.count("name")) network["name"] = _jS(b["name"],""); + if (b.count("private")) network["private"] = _jB(b["private"],true); + if (b.count("enableBroadcast")) network["enableBroadcast"] = _jB(b["enableBroadcast"],false); + if (b.count("allowPassiveBridging")) network["allowPassiveBridging"] = _jB(b["allowPassiveBridging"],false); + if (b.count("multicastLimit")) network["multicastLimit"] = _jI(b["multicastLimit"],32ULL); if (b.count("activeBridges")) { auto ab = b["activeBridges"]; @@ -1249,10 +1305,10 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( auto nv4m = network["v4AssignMode"]; if (!nv4m.is_object()) nv4m = json::object(); if (b["v4AssignMode"].is_string()) { // backward compatibility - nv4m["zt"] = (b.value("v4AssignMode","") == "zt"); + nv4m["zt"] = (_jS(b["v4AssignMode"],"") == "zt"); } else if (b["v4AssignMode"].is_object()) { auto v4m = b["v4AssignMode"]; - if (v4m.count("zt")) nv4m["zt"] = v4m.value("zt",false); + if (v4m.count("zt")) nv4m["zt"] = _jB(v4m["zt"],false); } if (!nv4m.count("zt")) nv4m["zt"] = false; } @@ -1261,7 +1317,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( auto nv6m = network["v6AssignMode"]; if (!nv6m.is_object()) nv6m = json::object(); if (b["v6AssignMode"].is_string()) { // backward compatibility - std::vector v6m(Utils::split(b.value("v6AssignMode","").c_str(),",","","")); + std::vector v6m(Utils::split(_jS(b["v6AssignMode"],"").c_str(),",","","")); std::sort(v6m.begin(),v6m.end()); v6m.erase(std::unique(v6m.begin(),v6m.end()),v6m.end()); for(std::vector::iterator i(v6m.begin());i!=v6m.end();++i) { @@ -1274,9 +1330,9 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( } } else if (b["v6AssignMode"].is_object()) { auto v6m = b["v6AssignMode"]; - if (v6m.count("rfc4193")) nv6m["rfc4193"] = v6m.value("rfc4193",false); - if (v6m.count("zt")) nv6m["rfc4193"] = v6m.value("zt",false); - if (v6m.count("6plane")) nv6m["rfc4193"] = v6m.value("6plane",false); + if (v6m.count("rfc4193")) nv6m["rfc4193"] = _jB(v6m["rfc4193"],false); + if (v6m.count("zt")) nv6m["rfc4193"] = _jB(v6m["zt"],false); + if (v6m.count("6plane")) nv6m["rfc4193"] = _jB(v6m["6plane"],false); } if (!nv6m.count("rfc4193")) nv6m["rfc4193"] = false; if (!nv6m.count("zt")) nv6m["zt"] = false; @@ -1289,8 +1345,8 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( for(unsigned long i=0;i 0) { json t = json::object(); t["token"] = tstr; - t["expires"] = token.value("expires",0ULL); + t["expires"] = _jI(token["expires"],0ULL); nat.push_back(t); } } @@ -1372,8 +1428,8 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( if (!network.count("creationTime")) network["creationTime"] = OSUtils::now(); if (!network.count("name")) network["name"] = ""; if (!network.count("multicastLimit")) network["multicastLimit"] = (uint64_t)32; - if (!network.count("v4AssignMode")) network["v4AssignMode"] = "{\"zt\":false}"_json; - if (!network.count("v6AssignMode")) network["v6AssignMode"] = "{\"rfc4193\":false,\"zt\":false,\"6plane\":false}"_json; + if (!network.count("v4AssignMode")) network["v4AssignMode"] = {{"zt",false}}; + if (!network.count("v6AssignMode")) network["v6AssignMode"] = {{"rfc4193",false},{"zt",false},{"6plane",false}}; if (!network.count("activeBridges")) network["activeBridges"] = json::array(); if (!network.count("authTokens")) network["authTokens"] = json::array(); @@ -1387,7 +1443,8 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( network["id"] = nwids; network["nwid"] = nwids; // legacy - network["revision"] = network.value("revision",0ULL) + 1ULL; + auto rev = network["revision"]; + network["revision"] = (rev.is_number() ? ((uint64_t)rev + 1ULL) : 1ULL); network["objtype"] = "network"; _writeJson(_networkJP(nwid,true),network); diff --git a/controller/README.md b/controller/README.md index 2c7541ae..0b57dd25 100644 --- a/controller/README.md +++ b/controller/README.md @@ -5,7 +5,7 @@ ZeroTier's 16-digit network IDs are really just a concatenation of the 10-digit This code implements the *node/NetworkController.hpp* interface to provide an embedded microservice configurable via the same local HTTP control plane as ZeroTier One iteself. It is built by default in ZeroTier One in desktop and server builds. This is the same code we use to run [my.zerotier.com](https://my.zerotier.com/), which is a web UI and API that runs in front of a pool of controllers. -Data is stored in JSON format under `controller.d` in the ZeroTier working directory. It can be copied, tar'd, placed in `git`, or edited in place, though we do not recommend doing the latter while the controller is running. Also take care if editing in place that you do not save corrupted JSON since the controller may then lose data when it attempts to load, modify, and save. +Data is stored in JSON format under `controller.d` in the ZeroTier working directory. It can be copied, tar'd, placed in `git`, etc. Technically the JSON files under `controller.d` can also be edited in place, but we do not recommend doing this under a running controller since data loss or corruption might result. Also take care to keep JSON values of the correct types or data loss may also result. ### Scalability and Reliability diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 5c9e80f8..e4f09106 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -804,8 +804,12 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons outp.armor(peer->key(),true); RR->node->putPacket(_localAddress,_remoteAddress,outp.data(),outp.size()); } + } catch (std::exception &exc) { + fprintf(stderr,"WARNING: network config request failed with exception: %s" ZT_EOL_S,exc.what()); + TRACE("dropped NETWORK_CONFIG_REQUEST from %s(%s): %s",source().toString().c_str(),_remoteAddress.toString().c_str(),exc.what()); } catch ( ... ) { - TRACE("dropped NETWORK_CONFIG_REQUEST from %s(%s): unexpected exception",source().toString().c_str(),_remoteAddress.toString().c_str()); + fprintf(stderr,"WARNING: network config request failed with exception: unknown exception" ZT_EOL_S); + TRACE("dropped NETWORK_CONFIG_REQUEST from %s(%s): unknown exception",source().toString().c_str(),_remoteAddress.toString().c_str()); } return true; } diff --git a/service/OneService.cpp b/service/OneService.cpp index 74628168..7ce45beb 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1705,7 +1705,11 @@ public: if (_controlPlane) scode = _controlPlane->handleRequest(tc->from,tc->parser.method,tc->url,tc->headers,tc->body,data,contentType); else scode = 500; + } catch (std::exception &exc) { + fprintf(stderr,"WARNING: unexpected exception processing control HTTP request: %s" ZT_EOL_S,exc.what()); + scode = 500; } catch ( ... ) { + fprintf(stderr,"WARNING: unexpected exception processing control HTTP request: unknown exceptino" ZT_EOL_S); scode = 500; } -- cgit v1.2.3 From 8d0b2b781e30f4a953b2ea5810249c7266f02b30 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 13 Sep 2016 16:25:48 -0700 Subject: Route management bug fixes. --- osdep/ManagedRoute.cpp | 3 ++- osdep/ManagedRoute.hpp | 65 ++++++++++++-------------------------------------- service/OneService.cpp | 18 +++++++------- 3 files changed, 26 insertions(+), 60 deletions(-) (limited to 'service/OneService.cpp') diff --git a/osdep/ManagedRoute.cpp b/osdep/ManagedRoute.cpp index ae20bb34..9763d271 100644 --- a/osdep/ManagedRoute.cpp +++ b/osdep/ManagedRoute.cpp @@ -240,6 +240,7 @@ static std::vector<_RTE> _getRTEs(const InetAddress &target,bool contains) static void _routeCmd(const char *op,const InetAddress &target,const InetAddress &via,const char *ifscope,const char *localInterface) { + //printf("route %s %s %s %s %s\n",op,target.toString().c_str(),(via) ? via.toString().c_str() : "(null)",(ifscope) ? ifscope : "(null)",(localInterface) ? localInterface : "(null)"); long p = (long)fork(); if (p > 0) { int exitcode = -1; @@ -436,7 +437,7 @@ bool ManagedRoute::sync() } if (!_applied.count(leftt)) { - _applied[rightt] = false; // not ifscoped + _applied[leftt] = false; // not ifscoped _routeCmd("add",leftt,_via,(const char *)0,(_via) ? (const char *)0 : _device); _routeCmd("change",leftt,_via,(const char *)0,(_via) ? (const char *)0 : _device); } diff --git a/osdep/ManagedRoute.hpp b/osdep/ManagedRoute.hpp index 4bf56503..fd77a79a 100644 --- a/osdep/ManagedRoute.hpp +++ b/osdep/ManagedRoute.hpp @@ -6,6 +6,9 @@ #include "../node/InetAddress.hpp" #include "../node/Utils.hpp" +#include "../node/SharedPtr.hpp" +#include "../node/AtomicCounter.hpp" +#include "../node/NonCopyable.hpp" #include #include @@ -16,58 +19,13 @@ namespace ZeroTier { /** * A ZT-managed route that used C++ RAII semantics to automatically clean itself up on deallocate */ -class ManagedRoute +class ManagedRoute : NonCopyable { -public: - ManagedRoute() - { - _device[0] = (char)0; - _systemDevice[0] = (char)0; - } - - ~ManagedRoute() - { - this->remove(); - } - - ManagedRoute(const ManagedRoute &r) - { - *this = r; - } - - inline ManagedRoute &operator=(const ManagedRoute &r) - { - if (_applied.size() == 0) { - _target = r._target; - _via = r._via; - _systemVia = r._systemVia; - _applied = r._applied; - Utils::scopy(_device,sizeof(_device),r._device); - Utils::scopy(_systemDevice,sizeof(_systemDevice),r._systemDevice); - } else { - // Sanity check -- this is an 'assert' to detect a bug - fprintf(stderr,"Applied ManagedRoute isn't copyable!\n"); - abort(); - } - return *this; - } + friend class SharedPtr; - /** - * Initialize object and set route - * - * Note: on Windows, use the interface NET_LUID in hexadecimal as the - * "device name." - * - * @param target Route target (e.g. 0.0.0.0/0 for default) - * @param via Route next L3 hop or NULL InetAddress if local in which case it will be routed via device - * @param device Name or hex LUID of ZeroTier device (e.g. zt#) - * @return True if route was successfully set - */ - inline bool set(const InetAddress &target,const InetAddress &via,const char *device) +public: + ManagedRoute(const InetAddress &target,const InetAddress &via,const char *device) { - if ((!via)&&(!device[0])) - return false; - this->remove(); _target = target; _via = via; if (via.ss_family == AF_INET) @@ -75,7 +33,12 @@ public: else if (via.ss_family == AF_INET6) _via.setPort(128); Utils::scopy(_device,sizeof(_device),device); - return this->sync(); + _systemDevice[0] = (char)0; + } + + ~ManagedRoute() + { + this->remove(); } /** @@ -108,6 +71,8 @@ private: std::map _applied; // routes currently applied char _device[128]; char _systemDevice[128]; // for route overrides + + AtomicCounter __refCount; }; } // namespace ZeroTier diff --git a/service/OneService.cpp b/service/OneService.cpp index 7ce45beb..30e6c938 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -537,7 +537,7 @@ public: EthernetTap *tap; ZT_VirtualNetworkConfig config; // memcpy() of raw config from core std::vector managedIps; - std::list managedRoutes; + std::list< SharedPtr > managedRoutes; NetworkSettings settings; }; std::map _nets; @@ -1128,13 +1128,13 @@ public: std::vector myIps(n.tap->ips()); // Nuke applied routes that are no longer in n.config.routes[] and/or are not allowed - for(std::list::iterator mr(n.managedRoutes.begin());mr!=n.managedRoutes.end();) { + for(std::list< SharedPtr >::iterator mr(n.managedRoutes.begin());mr!=n.managedRoutes.end();) { bool haveRoute = false; - if ( (checkIfManagedIsAllowed(n,mr->target())) && ((mr->via().ss_family != mr->target().ss_family)||(!matchIpOnly(myIps,mr->via()))) ) { + if ( (checkIfManagedIsAllowed(n,(*mr)->target())) && (((*mr)->via().ss_family != (*mr)->target().ss_family)||(!matchIpOnly(myIps,(*mr)->via()))) ) { for(unsigned int i=0;i(&(n.config.routes[i].target)); const InetAddress *const via = reinterpret_cast(&(n.config.routes[i].via)); - if ( (mr->target() == *target) && ( ((via->ss_family == target->ss_family)&&(mr->via() == *via)) || (tapdev == mr->device()) ) ) { + if ( ((*mr)->target() == *target) && ( ((via->ss_family == target->ss_family)&&((*mr)->via().ipsEqual(*via))) || (tapdev == (*mr)->device()) ) ) { haveRoute = true; break; } @@ -1168,10 +1168,10 @@ public: continue; // If we've already applied this route, just sync it and continue - for(std::list::iterator mr(n.managedRoutes.begin());mr!=n.managedRoutes.end();++mr) { - if ( (mr->target() == *target) && ( ((via->ss_family == target->ss_family)&&(mr->via() == *via)) || (tapdev == mr->device()) ) ) { + for(std::list< SharedPtr >::iterator mr(n.managedRoutes.begin());mr!=n.managedRoutes.end();++mr) { + if ( ((*mr)->target() == *target) && ( ((via->ss_family == target->ss_family)&&((*mr)->via().ipsEqual(*via))) || (tapdev == (*mr)->device()) ) ) { haveRoute = true; - mr->sync(); + (*mr)->sync(); break; } } @@ -1179,8 +1179,8 @@ public: continue; // Add and apply new routes - n.managedRoutes.push_back(ManagedRoute()); - if (!n.managedRoutes.back().set(*target,*via,tapdev)) + n.managedRoutes.push_back(SharedPtr(new ManagedRoute(*target,*via,tapdev))); + if (!n.managedRoutes.back()->sync()) n.managedRoutes.pop_back(); } } -- cgit v1.2.3 From ee5bd57d40f793baaf596a038f1446b29b1e86a4 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 14 Nov 2016 15:29:36 -0800 Subject: We don't bind to non-local IP for TCP yet, but eliminate double check. --- service/OneService.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 30e6c938..fcbccd63 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1259,12 +1259,10 @@ public: inline void phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,const struct sockaddr *from) { - if ((!from)||(reinterpret_cast(from)->ipScope() != InetAddress::IP_SCOPE_LOOPBACK)) { - // Non-Loopback: deny (for now) + if (!from) { _phy.close(sockN,false); return; } else { - // Loopback == HTTP JSON API request TcpConnection *tc = new TcpConnection(); _tcpConnections.insert(tc); tc->type = TcpConnection::TCP_HTTP_INCOMING; -- cgit v1.2.3 From b6c99ba3efeb51c7f08c1a4b1392f3942258195d Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 14 Nov 2016 15:47:06 -0800 Subject: Add (currently undocumented) option to allow management from certain networks. --- one.cpp | 11 ++++++++++- service/OneService.cpp | 37 +++++++++++++++++++++++-------------- service/OneService.hpp | 4 +++- 3 files changed, 36 insertions(+), 16 deletions(-) (limited to 'service/OneService.cpp') diff --git a/one.cpp b/one.cpp index 55cc2e19..51cda0c7 100644 --- a/one.cpp +++ b/one.cpp @@ -973,6 +973,7 @@ int main(int argc,char **argv) std::string homeDir; unsigned int port = ZT_DEFAULT_PORT; bool skipRootCheck = false; + const char *allowManagementFrom = (const char *)0; for(int i=1;irun()) { case OneService::ONE_STILL_RUNNING: // shouldn't happen, run() won't return until done case OneService::ONE_NORMAL_TERMINATION: diff --git a/service/OneService.cpp b/service/OneService.cpp index fcbccd63..91063bad 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -483,6 +483,7 @@ public: const std::string _homePath; BackgroundResolver _tcpFallbackResolver; + InetAddress _allowManagementFrom; EmbeddedNetworkController *_controller; Phy _phy; Node *_node; @@ -570,7 +571,7 @@ public: // end member variables ---------------------------------------------------- - OneServiceImpl(const char *hp,unsigned int port) : + OneServiceImpl(const char *hp,unsigned int port,const char *allowManagementFrom) : _homePath((hp) ? hp : ".") ,_tcpFallbackResolver(ZT_TCP_FALLBACK_RELAY) ,_controller((EmbeddedNetworkController *)0) @@ -595,6 +596,9 @@ public: #endif ,_run(true) { + if (allowManagementFrom) + _allowManagementFrom.fromString(allowManagementFrom); + _ports[0] = 0; _ports[1] = 0; _ports[2] = 0; @@ -614,7 +618,7 @@ public: struct sockaddr_in in4; memset(&in4,0,sizeof(in4)); in4.sin_family = AF_INET; - in4.sin_addr.s_addr = Utils::hton((uint32_t)0x7f000001); // right now we just listen for TCP @127.0.0.1 + in4.sin_addr.s_addr = Utils::hton((uint32_t)((allowManagementFrom) ? 0 : 0x7f000001)); // right now we just listen for TCP @127.0.0.1 in4.sin_port = Utils::hton((uint16_t)port); _v4TcpControlSocket = _phy.tcpListen((const struct sockaddr *)&in4,this); @@ -622,7 +626,8 @@ public: memset((void *)&in6,0,sizeof(in6)); in6.sin6_family = AF_INET6; in6.sin6_port = in4.sin_port; - in6.sin6_addr.s6_addr[15] = 1; // IPv6 localhost == ::1 + if (!allowManagementFrom) + in6.sin6_addr.s6_addr[15] = 1; // IPv6 localhost == ::1 _v6TcpControlSocket = _phy.tcpListen((const struct sockaddr *)&in6,this); // We must bind one of IPv4 or IPv6 -- support either failing to support hosts that @@ -1699,16 +1704,20 @@ public: std::string contentType("text/plain"); // default if not changed in handleRequest() unsigned int scode = 404; - try { - if (_controlPlane) - scode = _controlPlane->handleRequest(tc->from,tc->parser.method,tc->url,tc->headers,tc->body,data,contentType); - else scode = 500; - } catch (std::exception &exc) { - fprintf(stderr,"WARNING: unexpected exception processing control HTTP request: %s" ZT_EOL_S,exc.what()); - scode = 500; - } catch ( ... ) { - fprintf(stderr,"WARNING: unexpected exception processing control HTTP request: unknown exceptino" ZT_EOL_S); - scode = 500; + if ( ((!_allowManagementFrom)&&(tc->from.ipScope() == InetAddress::IP_SCOPE_LOOPBACK)) || (_allowManagementFrom.containsAddress(tc->from)) ) { + try { + if (_controlPlane) + scode = _controlPlane->handleRequest(tc->from,tc->parser.method,tc->url,tc->headers,tc->body,data,contentType); + else scode = 500; + } catch (std::exception &exc) { + fprintf(stderr,"WARNING: unexpected exception processing control HTTP request: %s" ZT_EOL_S,exc.what()); + scode = 500; + } catch ( ... ) { + fprintf(stderr,"WARNING: unexpected exception processing control HTTP request: unknown exceptino" ZT_EOL_S); + scode = 500; + } + } else { + scode = 401; } const char *scodestr; @@ -1973,7 +1982,7 @@ std::string OneService::autoUpdateUrl() return std::string(); } -OneService *OneService::newInstance(const char *hp,unsigned int port) { return new OneServiceImpl(hp,port); } +OneService *OneService::newInstance(const char *hp,unsigned int port,const char *allowManagementFrom) { return new OneServiceImpl(hp,port,allowManagementFrom); } OneService::~OneService() {} } // namespace ZeroTier diff --git a/service/OneService.hpp b/service/OneService.hpp index 72ff7d84..553bfd5e 100644 --- a/service/OneService.hpp +++ b/service/OneService.hpp @@ -98,10 +98,12 @@ public: * * @param hp Home path * @param port TCP and UDP port for packets and HTTP control (if 0, pick random port) + * @param allowManagementFrom If non-NULL, allow control from supplied IP/netmask */ static OneService *newInstance( const char *hp, - unsigned int port); + unsigned int port, + const char *allowManagementFrom = (const char *)0); virtual ~OneService(); -- cgit v1.2.3 From 2e5de46584e858b65e2f609a3d88b63e681e4e60 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 21 Nov 2016 13:20:56 -0800 Subject: local.conf and support for virtual role definition --- service/OneService.cpp | 144 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 127 insertions(+), 17 deletions(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 91063bad..425c8ef9 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -31,12 +31,6 @@ #include "../version.h" #include "../include/ZeroTierOne.h" -#ifdef ZT_USE_SYSTEM_HTTP_PARSER -#include -#else -#include "../ext/http-parser/http_parser.h" -#endif - #include "../node/Constants.hpp" #include "../node/Mutex.hpp" #include "../node/Node.hpp" @@ -59,6 +53,16 @@ #include "ClusterGeoIpService.hpp" #include "ClusterDefinition.hpp" +#ifdef ZT_USE_SYSTEM_HTTP_PARSER +#include +#else +#include "../ext/http-parser/http_parser.h" +#endif + +#include "../ext/json/json.hpp" + +using json = nlohmann::json; + /** * Uncomment to enable UDP breakage switch * @@ -144,6 +148,54 @@ namespace ZeroTier { namespace { +static uint64_t _jI(const json &jv,const uint64_t dfl) +{ + if (jv.is_number()) { + return (uint64_t)jv; + } else if (jv.is_string()) { + std::string s = jv; + return Utils::strToU64(s.c_str()); + } else if (jv.is_boolean()) { + return ((bool)jv ? 1ULL : 0ULL); + } + return dfl; +} +/* +static bool _jB(const json &jv,const bool dfl) +{ + if (jv.is_boolean()) { + return (bool)jv; + } else if (jv.is_number()) { + return ((uint64_t)jv > 0ULL); + } else if (jv.is_string()) { + std::string s = jv; + if (s.length() > 0) { + switch(s[0]) { + case 't': + case 'T': + case '1': + return true; + } + } + return false; + } + return dfl; +} +*/ +static std::string _jS(const json &jv,const char *dfl) +{ + if (jv.is_string()) { + return jv; + } else if (jv.is_number()) { + char tmp[64]; + Utils::snprintf(tmp,sizeof(tmp),"%llu",(uint64_t)jv); + return tmp; + } else if (jv.is_boolean()) { + return ((bool)jv ? std::string("1") : std::string("0")); + } + return std::string((dfl) ? dfl : ""); +} + #ifdef ZT_AUTO_UPDATE #define ZT_AUTO_UPDATE_MAX_HTTP_RESPONSE_SIZE (1024 * 1024 * 64) #define ZT_AUTO_UPDATE_CHECK_PERIOD 21600000 @@ -484,6 +536,7 @@ public: const std::string _homePath; BackgroundResolver _tcpFallbackResolver; InetAddress _allowManagementFrom; + json _localConfig; EmbeddedNetworkController *_controller; Phy _phy; Node *_node; @@ -758,13 +811,15 @@ public: _portsBE[i] = Utils::hton((uint16_t)_ports[i]); { + uint64_t trustedPathIds[ZT_MAX_TRUSTED_PATHS]; + InetAddress trustedPathNetworks[ZT_MAX_TRUSTED_PATHS]; + unsigned int trustedPathCount = 0; + + // Old style "trustedpaths" flat file -- will eventually go away FILE *trustpaths = fopen((_homePath + ZT_PATH_SEPARATOR_S + "trustedpaths").c_str(),"r"); - uint64_t ids[ZT_MAX_TRUSTED_PATHS]; - InetAddress addresses[ZT_MAX_TRUSTED_PATHS]; if (trustpaths) { char buf[1024]; - unsigned int count = 0; - while ((fgets(buf,sizeof(buf),trustpaths))&&(count < ZT_MAX_TRUSTED_PATHS)) { + while ((fgets(buf,sizeof(buf),trustpaths))&&(trustedPathCount < ZT_MAX_TRUSTED_PATHS)) { int fno = 0; char *saveptr = (char *)0; uint64_t trustedPathId = 0; @@ -778,14 +833,69 @@ public: ++fno; } if ( (trustedPathId != 0) && ((trustedPathNetwork.ss_family == AF_INET)||(trustedPathNetwork.ss_family == AF_INET6)) && (trustedPathNetwork.ipScope() != InetAddress::IP_SCOPE_GLOBAL) && (trustedPathNetwork.netmaskBits() > 0) ) { - ids[count] = trustedPathId; - addresses[count] = trustedPathNetwork; - ++count; + trustedPathIds[trustedPathCount] = trustedPathId; + trustedPathNetworks[trustedPathCount] = trustedPathNetwork; + ++trustedPathCount; } } fclose(trustpaths); - if (count) - _node->setTrustedPaths(reinterpret_cast(addresses),ids,count); + } + + // Read local config file + std::string lcbuf; + if (OSUtils::readFile((_homePath + ZT_PATH_SEPARATOR_S + "local.conf").c_str(),lcbuf)) { + try { + _localConfig = json::parse(lcbuf); + if (!_localConfig.is_object()) { + Mutex::Lock _l(_termReason_m); + _termReason = ONE_UNRECOVERABLE_ERROR; + _fatalErrorMessage = "invalid local.conf (content is not JSON object)"; + return _termReason; + } + } catch ( ... ) { + Mutex::Lock _l(_termReason_m); + _termReason = ONE_UNRECOVERABLE_ERROR; + _fatalErrorMessage = "invalid local.conf (JSON parse error)"; + return _termReason; + } + } + + // Get any trusted paths in local.conf + json &physical = _localConfig["physical"]; + if (physical.is_object()) { + for(json::iterator phy(physical.begin());phy!=physical.end();++phy) { + std::string nstr = phy.key(); + if (nstr.length()) { + if (phy.value().is_object()) { + uint64_t tpid = 0; + if ((tpid = _jI(phy.value()["trustedPathId"],0ULL))) { + InetAddress trustedPathNetwork(nstr); + if ( ((trustedPathNetwork.ss_family == AF_INET)||(trustedPathNetwork.ss_family == AF_INET6)) && (trustedPathCount < ZT_MAX_TRUSTED_PATHS) && (trustedPathNetwork.ipScope() != InetAddress::IP_SCOPE_GLOBAL) && (trustedPathNetwork.netmaskBits() > 0) ) { + trustedPathIds[trustedPathCount] = tpid; + trustedPathNetworks[trustedPathCount] = trustedPathNetwork; + ++trustedPathCount; + } + } + } + } + } + } + + // Set trusted paths if there are any + if (trustedPathCount) + _node->setTrustedPaths(reinterpret_cast(trustedPathNetworks),trustedPathIds,trustedPathCount); + + // Set any roles (upstream/federation) + json &virt = _localConfig["virtual"]; + if (virt.is_object()) { + for(json::iterator v(virt.begin());v!=virt.end();++v) { + std::string nstr = v.key(); + if ((nstr.length() == ZT_ADDRESS_LENGTH_HEX)&&(v.value().is_object())) { + const Address ztaddr(nstr.c_str()); + if (ztaddr) + _node->setRole(ztaddr.toInt(),(_jS(v.value()["role"],"") == "upstream") ? ZT_PEER_ROLE_UPSTREAM : ZT_PEER_ROLE_LEAF); + } + } } } @@ -806,7 +916,7 @@ public: Mutex::Lock _l(_termReason_m); _termReason = ONE_UNRECOVERABLE_ERROR; - _fatalErrorMessage = "Cluster: can't determine my cluster member ID: able to bind more than one cluster message socket IP/port!"; + _fatalErrorMessage = "cluster: can't determine my cluster member ID: able to bind more than one cluster message socket IP/port!"; return _termReason; } _clusterMessageSocket = cs; @@ -817,7 +927,7 @@ public: if (!_clusterMessageSocket) { Mutex::Lock _l(_termReason_m); _termReason = ONE_UNRECOVERABLE_ERROR; - _fatalErrorMessage = "Cluster: can't determine my cluster member ID: unable to bind to any cluster message socket IP/port."; + _fatalErrorMessage = "cluster: can't determine my cluster member ID: unable to bind to any cluster message socket IP/port."; return _termReason; } -- cgit v1.2.3 From 40078a99de423bb437acd2fcc1c42a9f920b0cfa Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 21 Nov 2016 14:14:43 -0800 Subject: Make parse failure of local.conf non-fatal in case people have ancient files sitting around. --- service/OneService.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 425c8ef9..289f0cbc 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -847,16 +847,10 @@ public: try { _localConfig = json::parse(lcbuf); if (!_localConfig.is_object()) { - Mutex::Lock _l(_termReason_m); - _termReason = ONE_UNRECOVERABLE_ERROR; - _fatalErrorMessage = "invalid local.conf (content is not JSON object)"; - return _termReason; + fprintf(stderr,"WARNING: unable to parse local.conf (root element is not a JSON object)" ZT_EOL_S); } } catch ( ... ) { - Mutex::Lock _l(_termReason_m); - _termReason = ONE_UNRECOVERABLE_ERROR; - _fatalErrorMessage = "invalid local.conf (JSON parse error)"; - return _termReason; + fprintf(stderr,"WARNING: unable to parse local.conf (invalid JSON)" ZT_EOL_S); } } -- cgit v1.2.3 From d159e5ca4400db6b6b1fc18d0e917fb0cca60627 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 21 Nov 2016 15:21:24 -0800 Subject: Allow relay policy setting in local.conf --- service/OneService.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 289f0cbc..efb6ff3c 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -883,7 +883,7 @@ public: json &virt = _localConfig["virtual"]; if (virt.is_object()) { for(json::iterator v(virt.begin());v!=virt.end();++v) { - std::string nstr = v.key(); + const std::string nstr = v.key(); if ((nstr.length() == ZT_ADDRESS_LENGTH_HEX)&&(v.value().is_object())) { const Address ztaddr(nstr.c_str()); if (ztaddr) @@ -891,6 +891,17 @@ public: } } } + + // Set any other local config stuff + json &settings = _localConfig["settings"]; + if (settings.is_object()) { + const std::string rp(_jS(settings["relayPolicy"],"")); + if (rp == "always") + _node->setRelayPolicy(ZT_RELAY_POLICY_ALWAYS); + else if (rp == "never") + _node->setRelayPolicy(ZT_RELAY_POLICY_NEVER); + else _node->setRelayPolicy(ZT_RELAY_POLICY_TRUSTED); + } } _controller = new EmbeddedNetworkController(_node,(_homePath + ZT_PATH_SEPARATOR_S + ZT_CONTROLLER_DB_PATH).c_str()); -- cgit v1.2.3 From 42ba70e79e3f1484f7bdde5832658cbd179649dc Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 22 Nov 2016 10:54:58 -0800 Subject: Replace long callback arg list with struct, and implement path whitelisting, path blacklisting, and local.conf support for roles. --- include/ZeroTierOne.h | 97 ++++++++++++++++---- node/IncomingPacket.cpp | 6 +- node/Node.cpp | 88 ++++++------------ node/Node.hpp | 86 +++-------------- node/Peer.cpp | 2 +- node/Switch.cpp | 2 +- service/OneService.cpp | 238 ++++++++++++++++++++++++++++++++++++------------ 7 files changed, 302 insertions(+), 217 deletions(-) (limited to 'service/OneService.cpp') diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 399f090c..72da53f2 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -1495,8 +1495,9 @@ typedef int (*ZT_WirePacketSendFunction)( * Paramters: * (1) Node * (2) User pointer - * (3) Local interface address - * (4) Remote address + * (3) ZeroTier address or 0 for none/any + * (4) Local interface address + * (5) Remote address * * This function must return nonzero (true) if the path should be used. * @@ -1515,13 +1516,87 @@ typedef int (*ZT_WirePacketSendFunction)( typedef int (*ZT_PathCheckFunction)( ZT_Node *, /* Node */ void *, /* User ptr */ + uint64_t, /* ZeroTier address */ const struct sockaddr_storage *, /* Local address */ const struct sockaddr_storage *); /* Remote address */ +/** + * Function to get physical addresses for ZeroTier peers + * + * Parameters: + * (1) Node + * (2) User pointer + * (3) ZeroTier address (least significant 40 bits) + * (4) Desried address family or -1 for any + * (5) Buffer to fill with result + * + * If provided this function will be occasionally called to get physical + * addresses that might be tried to reach a ZeroTier address. It must + * return a nonzero (true) value if the result buffer has been filled + * with an address. + */ +typedef int (*ZT_PathLookupFunction)( + ZT_Node *, /* Node */ + void *, /* User ptr */ + uint64_t, /* ZeroTier address (40 bits) */ + int, /* Desired ss_family or -1 for any */ + struct sockaddr_storage *); /* Result buffer */ + /****************************************************************************/ /* C Node API */ /****************************************************************************/ +/** + * Structure for configuring ZeroTier core callback functions + */ +struct ZT_Node_Callbacks +{ + /** + * Struct version -- must currently be 0 + */ + long version; + + /** + * REQUIRED: Function to get objects from persistent storage + */ + ZT_DataStoreGetFunction dataStoreGetFunction; + + /** + * REQUIRED: Function to store objects in persistent storage + */ + ZT_DataStorePutFunction dataStorePutFunction; + + /** + * REQUIRED: Function to send packets over the physical wire + */ + ZT_WirePacketSendFunction wirePacketSendFunction; + + /** + * REQUIRED: Function to inject frames into a virtual network's TAP + */ + ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction; + + /** + * REQUIRED: Function to be called when virtual networks are configured or changed + */ + ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction; + + /** + * REQUIRED: Function to be called to notify external code of important events + */ + ZT_EventCallback eventCallback; + + /** + * OPTIONAL: Function to check whether a given physical path should be used + */ + ZT_PathCheckFunction pathCheckFunction; + + /** + * OPTIONAL: Function to get hints to physical paths to ZeroTier addresses + */ + ZT_PathLookupFunction pathLookupFunction; +}; + /** * Create a new ZeroTier One node * @@ -1533,25 +1608,11 @@ typedef int (*ZT_PathCheckFunction)( * * @param node Result: pointer is set to new node instance on success * @param uptr User pointer to pass to functions/callbacks + * @param callbacks Callback function configuration * @param now Current clock in milliseconds - * @param dataStoreGetFunction Function called to get objects from persistent storage - * @param dataStorePutFunction Function called to put objects in persistent storage - * @param virtualNetworkConfigFunction Function to be called when virtual LANs are created, deleted, or their config parameters change - * @param pathCheckFunction A function to check whether a path should be used for ZeroTier traffic, or NULL to allow any path - * @param eventCallback Function to receive status updates and non-fatal error notices * @return OK (0) or error code if a fatal error condition has occurred */ -enum ZT_ResultCode ZT_Node_new( - ZT_Node **node, - void *uptr, - uint64_t now, - ZT_DataStoreGetFunction dataStoreGetFunction, - ZT_DataStorePutFunction dataStorePutFunction, - ZT_WirePacketSendFunction wirePacketSendFunction, - ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction, - ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction, - ZT_PathCheckFunction pathCheckFunction, - ZT_EventCallback eventCallback); +enum ZT_ResultCode ZT_Node_new(ZT_Node **node,void *uptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now); /** * Delete a node and free all resources it consumes diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 41f3e47d..7b828f8b 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -552,7 +552,7 @@ bool IncomingPacket::_doRENDEZVOUS(const RuntimeEnvironment *RR,const SharedPtr< const unsigned int addrlen = (*this)[ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRLEN]; if ((port > 0)&&((addrlen == 4)||(addrlen == 16))) { const InetAddress atAddr(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS,addrlen),addrlen,port); - if (RR->node->shouldUsePathForZeroTierTraffic(_path->localAddress(),atAddr)) { + if (RR->node->shouldUsePathForZeroTierTraffic(with,_path->localAddress(),atAddr)) { RR->node->putPacket(_path->localAddress(),atAddr,"ABRE",4,2); // send low-TTL junk packet to 'open' local NAT(s) and stateful firewalls rendezvousWith->attemptToContactAt(_path->localAddress(),atAddr,RR->node->now()); TRACE("RENDEZVOUS from %s says %s might be at %s, sent verification attempt",peer->address().toString().c_str(),with.toString().c_str(),atAddr.toString().c_str()); @@ -1120,7 +1120,7 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const Sha redundant = peer->hasActivePathTo(now,a); } - if ( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH) == 0) && (!redundant) && (RR->node->shouldUsePathForZeroTierTraffic(_path->localAddress(),a)) ) { + if ( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH) == 0) && (!redundant) && (RR->node->shouldUsePathForZeroTierTraffic(peer->address(),_path->localAddress(),a)) ) { if (++countPerScope[(int)a.ipScope()][0] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) { TRACE("attempting to contact %s at pushed direct path %s",peer->address().toString().c_str(),a.toString().c_str()); peer->attemptToContactAt(InetAddress(),a,now); @@ -1139,7 +1139,7 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const Sha redundant = peer->hasActivePathTo(now,a); } - if ( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH) == 0) && (!redundant) && (RR->node->shouldUsePathForZeroTierTraffic(_path->localAddress(),a)) ) { + if ( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH) == 0) && (!redundant) && (RR->node->shouldUsePathForZeroTierTraffic(peer->address(),_path->localAddress(),a)) ) { if (++countPerScope[(int)a.ipScope()][1] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) { TRACE("attempting to contact %s at pushed direct path %s",peer->address().toString().c_str(),a.toString().c_str()); peer->attemptToContactAt(InetAddress(),a,now); diff --git a/node/Node.cpp b/node/Node.cpp index 263cfc6e..a180766b 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -46,34 +46,20 @@ namespace ZeroTier { /* Public Node interface (C++, exposed via CAPI bindings) */ /****************************************************************************/ -Node::Node( - uint64_t now, - void *uptr, - ZT_DataStoreGetFunction dataStoreGetFunction, - ZT_DataStorePutFunction dataStorePutFunction, - ZT_WirePacketSendFunction wirePacketSendFunction, - ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction, - ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction, - ZT_PathCheckFunction pathCheckFunction, - ZT_EventCallback eventCallback) : +Node::Node(void *uptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now) : _RR(this), RR(&_RR), _uPtr(uptr), - _dataStoreGetFunction(dataStoreGetFunction), - _dataStorePutFunction(dataStorePutFunction), - _wirePacketSendFunction(wirePacketSendFunction), - _virtualNetworkFrameFunction(virtualNetworkFrameFunction), - _virtualNetworkConfigFunction(virtualNetworkConfigFunction), - _pathCheckFunction(pathCheckFunction), - _eventCallback(eventCallback), - _networks(), - _networks_m(), _prngStreamPtr(0), _now(now), _lastPingCheck(0), _lastHousekeepingRun(0), _relayPolicy(ZT_RELAY_POLICY_TRUSTED) { + if (callbacks->version != 0) + throw std::runtime_error("callbacks struct version mismatch"); + memcpy(&_cb,callbacks,sizeof(ZT_Node_Callbacks)); + _online = false; memset(_expectingRepliesToBucketPtr,0,sizeof(_expectingRepliesToBucketPtr)); @@ -81,30 +67,26 @@ Node::Node( memset(_lastIdentityVerification,0,sizeof(_lastIdentityVerification)); // Use Salsa20 alone as a high-quality non-crypto PRNG - { - char foo[32]; - Utils::getSecureRandom(foo,32); - _prng.init(foo,256,foo); - memset(_prngStream,0,sizeof(_prngStream)); - _prng.encrypt12(_prngStream,_prngStream,sizeof(_prngStream)); + char foo[32]; + Utils::getSecureRandom(foo,32); + _prng.init(foo,256,foo); + memset(_prngStream,0,sizeof(_prngStream)); + _prng.encrypt12(_prngStream,_prngStream,sizeof(_prngStream)); + + std::string idtmp(dataStoreGet("identity.secret")); + if ((!idtmp.length())||(!RR->identity.fromString(idtmp))||(!RR->identity.hasPrivate())) { + TRACE("identity.secret not found, generating..."); + RR->identity.generate(); + idtmp = RR->identity.toString(true); + if (!dataStorePut("identity.secret",idtmp,true)) + throw std::runtime_error("unable to write identity.secret"); } - - { - std::string idtmp(dataStoreGet("identity.secret")); - if ((!idtmp.length())||(!RR->identity.fromString(idtmp))||(!RR->identity.hasPrivate())) { - TRACE("identity.secret not found, generating..."); - RR->identity.generate(); - idtmp = RR->identity.toString(true); - if (!dataStorePut("identity.secret",idtmp,true)) - throw std::runtime_error("unable to write identity.secret"); - } - RR->publicIdentityStr = RR->identity.toString(false); - RR->secretIdentityStr = RR->identity.toString(true); - idtmp = dataStoreGet("identity.public"); - if (idtmp != RR->publicIdentityStr) { - if (!dataStorePut("identity.public",RR->publicIdentityStr,false)) - throw std::runtime_error("unable to write identity.public"); - } + RR->publicIdentityStr = RR->identity.toString(false); + RR->secretIdentityStr = RR->identity.toString(true); + idtmp = dataStoreGet("identity.public"); + if (idtmp != RR->publicIdentityStr) { + if (!dataStorePut("identity.public",RR->publicIdentityStr,false)) + throw std::runtime_error("unable to write identity.public"); } try { @@ -638,7 +620,7 @@ std::string Node::dataStoreGet(const char *name) std::string r; unsigned long olen = 0; do { - long n = _dataStoreGetFunction(reinterpret_cast(this),_uPtr,name,buf,sizeof(buf),(unsigned long)r.length(),&olen); + long n = _cb.dataStoreGetFunction(reinterpret_cast(this),_uPtr,name,buf,sizeof(buf),(unsigned long)r.length(),&olen); if (n <= 0) return std::string(); r.append(buf,n); @@ -646,7 +628,7 @@ std::string Node::dataStoreGet(const char *name) return r; } -bool Node::shouldUsePathForZeroTierTraffic(const InetAddress &localAddress,const InetAddress &remoteAddress) +bool Node::shouldUsePathForZeroTierTraffic(const Address &ztaddr,const InetAddress &localAddress,const InetAddress &remoteAddress) { if (!Path::isAddressValidForPath(remoteAddress)) return false; @@ -663,9 +645,7 @@ bool Node::shouldUsePathForZeroTierTraffic(const InetAddress &localAddress,const } } - if (_pathCheckFunction) - return (_pathCheckFunction(reinterpret_cast(this),_uPtr,reinterpret_cast(&localAddress),reinterpret_cast(&remoteAddress)) != 0); - else return true; + return ( (_cb.pathCheckFunction) ? (_cb.pathCheckFunction(reinterpret_cast(this),_uPtr,ztaddr.toInt(),reinterpret_cast(&localAddress),reinterpret_cast(&remoteAddress)) != 0) : true); } #ifdef ZT_TRACE @@ -822,21 +802,11 @@ void Node::ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &des extern "C" { -enum ZT_ResultCode ZT_Node_new( - ZT_Node **node, - void *uptr, - uint64_t now, - ZT_DataStoreGetFunction dataStoreGetFunction, - ZT_DataStorePutFunction dataStorePutFunction, - ZT_WirePacketSendFunction wirePacketSendFunction, - ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction, - ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction, - ZT_PathCheckFunction pathCheckFunction, - ZT_EventCallback eventCallback) +enum ZT_ResultCode ZT_Node_new(ZT_Node **node,void *uptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now) { *node = (ZT_Node *)0; try { - *node = reinterpret_cast(new ZeroTier::Node(now,uptr,dataStoreGetFunction,dataStorePutFunction,wirePacketSendFunction,virtualNetworkFrameFunction,virtualNetworkConfigFunction,pathCheckFunction,eventCallback)); + *node = reinterpret_cast(new ZeroTier::Node(uptr,callbacks,now)); return ZT_RESULT_OK; } catch (std::bad_alloc &exc) { return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; diff --git a/node/Node.hpp b/node/Node.hpp index 38303f8c..7d99ff09 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -59,17 +59,7 @@ namespace ZeroTier { class Node : public NetworkController::Sender { public: - Node( - uint64_t now, - void *uptr, - ZT_DataStoreGetFunction dataStoreGetFunction, - ZT_DataStorePutFunction dataStorePutFunction, - ZT_WirePacketSendFunction wirePacketSendFunction, - ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction, - ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction, - ZT_PathCheckFunction pathCheckFunction, - ZT_EventCallback eventCallback); - + Node(void *uptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now); virtual ~Node(); // Public API Functions ---------------------------------------------------- @@ -127,24 +117,11 @@ public: // Internal functions ------------------------------------------------------ - /** - * @return Time as of last call to run() - */ inline uint64_t now() const throw() { return _now; } - /** - * Enqueue a ZeroTier message to be sent - * - * @param localAddress Local address - * @param addr Destination address - * @param data Packet data - * @param len Packet length - * @param ttl Desired TTL (default: 0 for unchanged/default TTL) - * @return True if packet appears to have been sent - */ inline bool putPacket(const InetAddress &localAddress,const InetAddress &addr,const void *data,unsigned int len,unsigned int ttl = 0) { - return (_wirePacketSendFunction( + return (_cb.wirePacketSendFunction( reinterpret_cast(this), _uPtr, reinterpret_cast(&localAddress), @@ -154,21 +131,9 @@ public: ttl) == 0); } - /** - * Enqueue a frame to be injected into a tap device (port) - * - * @param nwid Network ID - * @param nuptr Network user ptr - * @param source Source MAC - * @param dest Destination MAC - * @param etherType 16-bit ethernet type - * @param vlanId VLAN ID or 0 if none - * @param data Frame data - * @param len Frame length - */ inline void putFrame(uint64_t nwid,void **nuptr,const MAC &source,const MAC &dest,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) { - _virtualNetworkFrameFunction( + _cb.virtualNetworkFrameFunction( reinterpret_cast(this), _uPtr, nwid, @@ -181,13 +146,6 @@ public: len); } - /** - * @param localAddress Local address - * @param remoteAddress Remote address - * @return True if path should be used - */ - bool shouldUsePathForZeroTierTraffic(const InetAddress &localAddress,const InetAddress &remoteAddress); - inline SharedPtr network(uint64_t nwid) const { Mutex::Lock _l(_networks_m); @@ -214,37 +172,20 @@ public: return nw; } - /** - * @return Potential direct paths to me a.k.a. local interface addresses - */ inline std::vector directPaths() const { Mutex::Lock _l(_directPaths_m); return _directPaths; } - inline bool dataStorePut(const char *name,const void *data,unsigned int len,bool secure) { return (_dataStorePutFunction(reinterpret_cast(this),_uPtr,name,data,len,(int)secure) == 0); } + inline bool dataStorePut(const char *name,const void *data,unsigned int len,bool secure) { return (_cb.dataStorePutFunction(reinterpret_cast(this),_uPtr,name,data,len,(int)secure) == 0); } inline bool dataStorePut(const char *name,const std::string &data,bool secure) { return dataStorePut(name,(const void *)data.data(),(unsigned int)data.length(),secure); } - inline void dataStoreDelete(const char *name) { _dataStorePutFunction(reinterpret_cast(this),_uPtr,name,(const void *)0,0,0); } + inline void dataStoreDelete(const char *name) { _cb.dataStorePutFunction(reinterpret_cast(this),_uPtr,name,(const void *)0,0,0); } std::string dataStoreGet(const char *name); - /** - * Post an event to the external user - * - * @param ev Event type - * @param md Meta-data (default: NULL/none) - */ - inline void postEvent(ZT_Event ev,const void *md = (const void *)0) { _eventCallback(reinterpret_cast(this),_uPtr,ev,md); } + inline void postEvent(ZT_Event ev,const void *md = (const void *)0) { _cb.eventCallback(reinterpret_cast(this),_uPtr,ev,md); } - /** - * Update virtual network port configuration - * - * @param nwid Network ID - * @param nuptr Network user ptr - * @param op Configuration operation - * @param nc Network configuration - */ - inline int configureVirtualNetworkPort(uint64_t nwid,void **nuptr,ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nc) { return _virtualNetworkConfigFunction(reinterpret_cast(this),_uPtr,nwid,nuptr,op,nc); } + inline int configureVirtualNetworkPort(uint64_t nwid,void **nuptr,ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nc) { return _cb.virtualNetworkConfigFunction(reinterpret_cast(this),_uPtr,nwid,nuptr,op,nc); } inline bool online() const throw() { return _online; } inline ZT_RelayPolicy relayPolicy() const { return _relayPolicy; } @@ -253,6 +194,9 @@ public: void postTrace(const char *module,unsigned int line,const char *fmt,...); #endif + bool shouldUsePathForZeroTierTraffic(const Address &ztaddr,const InetAddress &localAddress,const InetAddress &remoteAddress); + inline bool getPathHint(const Address &ztaddr,int family,InetAddress &addr) { return ( (_cb.pathLookupFunction) ? (_cb.pathLookupFunction(reinterpret_cast(this),_uPtr,ztaddr.toInt(),family,reinterpret_cast(&addr)) != 0) : false ); } + uint64_t prng(); void postCircuitTestReport(const ZT_CircuitTestReport *report); void setTrustedPaths(const struct sockaddr_storage *networks,const uint64_t *ids,unsigned int count); @@ -317,8 +261,8 @@ private: RuntimeEnvironment _RR; RuntimeEnvironment *RR; - void *_uPtr; // _uptr (lower case) is reserved in Visual Studio :P + ZT_Node_Callbacks _cb; // For tracking packet IDs to filter out OK/ERROR replies to packets we did not send uint8_t _expectingRepliesToBucketPtr[ZT_EXPECTING_REPLIES_BUCKET_MASK1 + 1]; @@ -327,14 +271,6 @@ private: // Time of last identity verification indexed by InetAddress.rateGateHash() uint64_t _lastIdentityVerification[16384]; - ZT_DataStoreGetFunction _dataStoreGetFunction; - ZT_DataStorePutFunction _dataStorePutFunction; - ZT_WirePacketSendFunction _wirePacketSendFunction; - ZT_VirtualNetworkFrameFunction _virtualNetworkFrameFunction; - ZT_VirtualNetworkConfigFunction _virtualNetworkConfigFunction; - ZT_PathCheckFunction _pathCheckFunction; - ZT_EventCallback _eventCallback; - std::vector< std::pair< uint64_t, SharedPtr > > _networks; Mutex _networks_m; diff --git a/node/Peer.cpp b/node/Peer.cpp index 94fb5298..e0bd0eac 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -160,7 +160,7 @@ void Peer::received( } } - if ( (!pathIsConfirmed) && (RR->node->shouldUsePathForZeroTierTraffic(path->localAddress(),path->address())) ) { + if ( (!pathIsConfirmed) && (RR->node->shouldUsePathForZeroTierTraffic(_id.address(),path->localAddress(),path->address())) ) { if (verb == Packet::VERB_OK) { Mutex::Lock _l(_paths_m); diff --git a/node/Switch.cpp b/node/Switch.cpp index a5dd57e4..881d7b92 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -85,7 +85,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from Address beaconAddr(reinterpret_cast(data) + 8,5); if (beaconAddr == RR->identity.address()) return; - if (!RR->node->shouldUsePathForZeroTierTraffic(localAddr,fromAddr)) + if (!RR->node->shouldUsePathForZeroTierTraffic(beaconAddr,localAddr,fromAddr)) return; SharedPtr peer(RR->topology->getPeer(beaconAddr)); if (peer) { // we'll only respond to beacons from known peers diff --git a/service/OneService.cpp b/service/OneService.cpp index efb6ff3c..7434ca67 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -160,7 +160,6 @@ static uint64_t _jI(const json &jv,const uint64_t dfl) } return dfl; } -/* static bool _jB(const json &jv,const bool dfl) { if (jv.is_boolean()) { @@ -181,7 +180,6 @@ static bool _jB(const json &jv,const bool dfl) } return dfl; } -*/ static std::string _jS(const json &jv,const char *dfl) { if (jv.is_string()) { @@ -452,7 +450,8 @@ static long SnodeDataStoreGetFunction(ZT_Node *node,void *uptr,const char *name, static int SnodeDataStorePutFunction(ZT_Node *node,void *uptr,const char *name,const void *data,unsigned long len,int secure); static int SnodeWirePacketSendFunction(ZT_Node *node,void *uptr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl); static void SnodeVirtualNetworkFrameFunction(ZT_Node *node,void *uptr,uint64_t nwid,void **nuptr,uint64_t sourceMac,uint64_t destMac,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len); -static int SnodePathCheckFunction(ZT_Node *node,void *uptr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *remoteAddr); +static int SnodePathCheckFunction(ZT_Node *node,void *uptr,uint64_t ztaddr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *remoteAddr); +static int SnodePathLookupFunction(ZT_Node *node,void *uptr,uint64_t ztaddr,int family,struct sockaddr_storage *result); #ifdef ZT_ENABLE_CLUSTER static void SclusterSendFunction(void *uptr,unsigned int toMemberId,const void *data,unsigned int len); @@ -536,11 +535,20 @@ public: const std::string _homePath; BackgroundResolver _tcpFallbackResolver; InetAddress _allowManagementFrom; - json _localConfig; EmbeddedNetworkController *_controller; Phy _phy; Node *_node; + // Local configuration and memo-ized static path definitions + json _localConfig; + Hashtable< uint64_t,std::vector > _v4Hints; + Hashtable< uint64_t,std::vector > _v6Hints; + Hashtable< uint64_t,std::vector > _v4Blacklists; + Hashtable< uint64_t,std::vector > _v6Blacklists; + std::vector< InetAddress > _globalV4Blacklist; + std::vector< InetAddress > _globalV6Blacklist; + Mutex _localConfig_m; + /* * To attempt to handle NAT/gateway craziness we use three local UDP ports: * @@ -552,7 +560,6 @@ public: * destructively with uPnP port mapping behavior in very weird buggy ways. * It's only used if uPnP/NAT-PMP is enabled in this build. */ - Binder _bindings[3]; unsigned int _ports[3]; uint16_t _portsBE[3]; // ports in big-endian network byte order as in sockaddr @@ -756,16 +763,19 @@ public: // Clean up any legacy files if present OSUtils::rm((_homePath + ZT_PATH_SEPARATOR_S + "peers.save").c_str()); - _node = new Node( - OSUtils::now(), - this, - SnodeDataStoreGetFunction, - SnodeDataStorePutFunction, - SnodeWirePacketSendFunction, - SnodeVirtualNetworkFrameFunction, - SnodeVirtualNetworkConfigFunction, - SnodePathCheckFunction, - SnodeEventCallback); + { + struct ZT_Node_Callbacks cb; + cb.version = 0; + cb.dataStoreGetFunction = SnodeDataStoreGetFunction; + cb.dataStorePutFunction = SnodeDataStorePutFunction; + cb.wirePacketSendFunction = SnodeWirePacketSendFunction; + cb.virtualNetworkFrameFunction = SnodeVirtualNetworkFrameFunction; + cb.virtualNetworkConfigFunction = SnodeVirtualNetworkConfigFunction; + cb.eventCallback = SnodeEventCallback; + cb.pathCheckFunction = SnodePathCheckFunction; + cb.pathLookupFunction = SnodePathLookupFunction; + _node = new Node(this,&cb,OSUtils::now()); + } // Attempt to bind to a secondary port chosen from our ZeroTier address. // This exists because there are buggy NATs out there that fail if more @@ -842,6 +852,7 @@ public: } // Read local config file + Mutex::Lock _l2(_localConfig_m); std::string lcbuf; if (OSUtils::readFile((_homePath + ZT_PATH_SEPARATOR_S + "local.conf").c_str(),lcbuf)) { try { @@ -854,19 +865,18 @@ public: } } - // Get any trusted paths in local.conf + // Get any trusted paths in local.conf (we'll parse the rest of physical[] elsewhere) json &physical = _localConfig["physical"]; if (physical.is_object()) { for(json::iterator phy(physical.begin());phy!=physical.end();++phy) { - std::string nstr = phy.key(); - if (nstr.length()) { + InetAddress net(_jS(phy.key(),"")); + if (net) { if (phy.value().is_object()) { - uint64_t tpid = 0; - if ((tpid = _jI(phy.value()["trustedPathId"],0ULL))) { - InetAddress trustedPathNetwork(nstr); - if ( ((trustedPathNetwork.ss_family == AF_INET)||(trustedPathNetwork.ss_family == AF_INET6)) && (trustedPathCount < ZT_MAX_TRUSTED_PATHS) && (trustedPathNetwork.ipScope() != InetAddress::IP_SCOPE_GLOBAL) && (trustedPathNetwork.netmaskBits() > 0) ) { + uint64_t tpid; + if ((tpid = _jI(phy.value()["trustedPathId"],0ULL)) != 0ULL) { + if ( ((net.ss_family == AF_INET)||(net.ss_family == AF_INET6)) && (trustedPathCount < ZT_MAX_TRUSTED_PATHS) && (net.ipScope() != InetAddress::IP_SCOPE_GLOBAL) && (net.netmaskBits() > 0) ) { trustedPathIds[trustedPathCount] = tpid; - trustedPathNetworks[trustedPathCount] = trustedPathNetwork; + trustedPathNetworks[trustedPathCount] = net; ++trustedPathCount; } } @@ -878,31 +888,8 @@ public: // Set trusted paths if there are any if (trustedPathCount) _node->setTrustedPaths(reinterpret_cast(trustedPathNetworks),trustedPathIds,trustedPathCount); - - // Set any roles (upstream/federation) - json &virt = _localConfig["virtual"]; - if (virt.is_object()) { - for(json::iterator v(virt.begin());v!=virt.end();++v) { - const std::string nstr = v.key(); - if ((nstr.length() == ZT_ADDRESS_LENGTH_HEX)&&(v.value().is_object())) { - const Address ztaddr(nstr.c_str()); - if (ztaddr) - _node->setRole(ztaddr.toInt(),(_jS(v.value()["role"],"") == "upstream") ? ZT_PEER_ROLE_UPSTREAM : ZT_PEER_ROLE_LEAF); - } - } - } - - // Set any other local config stuff - json &settings = _localConfig["settings"]; - if (settings.is_object()) { - const std::string rp(_jS(settings["relayPolicy"],"")); - if (rp == "always") - _node->setRelayPolicy(ZT_RELAY_POLICY_ALWAYS); - else if (rp == "never") - _node->setRelayPolicy(ZT_RELAY_POLICY_NEVER); - else _node->setRelayPolicy(ZT_RELAY_POLICY_TRUSTED); - } } + applyLocalConfig(); _controller = new EmbeddedNetworkController(_node,(_homePath + ZT_PATH_SEPARATOR_S + ZT_CONTROLLER_DB_PATH).c_str()); _node->setNetconfMaster((void *)_controller); @@ -1174,7 +1161,90 @@ public: return true; } - // Begin private implementation methods + // Internal implementation methods ----------------------------------------- + + void applyLocalConfig() + { + Mutex::Lock _l(_localConfig_m); + + _v4Hints.clear(); + _v6Hints.clear(); + _v4Blacklists.clear(); + _v6Blacklists.clear(); + json &virt = _localConfig["virtual"]; + if (virt.is_object()) { + for(json::iterator v(virt.begin());v!=virt.end();++v) { + const std::string nstr = v.key(); + if ((nstr.length() == ZT_ADDRESS_LENGTH_HEX)&&(v.value().is_object())) { + const Address ztaddr(nstr.c_str()); + if (ztaddr) { + _node->setRole(ztaddr.toInt(),(_jS(v.value()["role"],"") == "upstream") ? ZT_PEER_ROLE_UPSTREAM : ZT_PEER_ROLE_LEAF); + + const uint64_t ztaddr2 = ztaddr.toInt(); + std::vector &v4h = _v4Hints[ztaddr2]; + std::vector &v6h = _v6Hints[ztaddr2]; + std::vector &v4b = _v4Blacklists[ztaddr2]; + std::vector &v6b = _v6Blacklists[ztaddr2]; + + json &tryAddrs = v.value()["try"]; + if (tryAddrs.is_array()) { + for(unsigned long i=0;i 0)) { + if (phy.value().is_object()) { + if (_jB(phy.value()["blacklist"],false)) { + if (net.ss_family == AF_INET) + _globalV4Blacklist.push_back(net); + else if (net.ss_family == AF_INET6) + _globalV6Blacklist.push_back(net); + } + } + } + } + } + + json &settings = _localConfig["settings"]; + if (settings.is_object()) { + const std::string rp(_jS(settings["relayPolicy"],"")); + if (rp == "always") + _node->setRelayPolicy(ZT_RELAY_POLICY_ALWAYS); + else if (rp == "never") + _node->setRelayPolicy(ZT_RELAY_POLICY_NEVER); + else _node->setRelayPolicy(ZT_RELAY_POLICY_TRUSTED); + } + } // Checks if a managed IP or route target is allowed bool checkIfManagedIsAllowed(const NetworkState &n,const InetAddress &target) @@ -1306,6 +1376,8 @@ public: } } + // Handlers for Node and Phy<> callbacks ----------------------------------- + inline void phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *localAddr,const struct sockaddr *from,void *data,unsigned long len) { #ifdef ZT_ENABLE_CLUSTER @@ -1783,21 +1855,48 @@ public: n->tap->put(MAC(sourceMac),MAC(destMac),etherType,data,len); } - inline int nodePathCheckFunction(const struct sockaddr_storage *localAddr,const struct sockaddr_storage *remoteAddr) + inline int nodePathCheckFunction(uint64_t ztaddr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *remoteAddr) { - Mutex::Lock _l(_nets_m); - - for(std::map::const_iterator n(_nets.begin());n!=_nets.end();++n) { - if (n->second.tap) { - std::vector ips(n->second.tap->ips()); - for(std::vector::const_iterator i(ips.begin());i!=ips.end();++i) { - if (i->containsAddress(*(reinterpret_cast(remoteAddr)))) { - return 0; + // Make sure we're not trying to do ZeroTier-over-ZeroTier + { + Mutex::Lock _l(_nets_m); + for(std::map::const_iterator n(_nets.begin());n!=_nets.end();++n) { + if (n->second.tap) { + std::vector ips(n->second.tap->ips()); + for(std::vector::const_iterator i(ips.begin());i!=ips.end();++i) { + if (i->containsAddress(*(reinterpret_cast(remoteAddr)))) { + return 0; + } } } } } - + + // Check blacklists + const Hashtable< uint64_t,std::vector > *blh = (const Hashtable< uint64_t,std::vector > *)0; + const std::vector *gbl = (const std::vector *)0; + if (remoteAddr->ss_family == AF_INET) { + blh = &_v4Blacklists; + gbl = &_globalV4Blacklist; + } else if (remoteAddr->ss_family == AF_INET6) { + blh = &_v6Blacklists; + gbl = &_globalV6Blacklist; + } + if (blh) { + Mutex::Lock _l(_localConfig_m); + const std::vector *l = blh->get(ztaddr); + if (l) { + for(std::vector::const_iterator a(l->begin());a!=l->end();++a) { + if (a->containsAddress(*reinterpret_cast(remoteAddr))) + return 0; + } + } + for(std::vector::const_iterator a(gbl->begin());a!=gbl->end();++a) { + if (a->containsAddress(*reinterpret_cast(remoteAddr))) + return 0; + } + } + /* Note: I do not think we need to scan for overlap with managed routes * because of the "route forking" and interface binding that we do. This * ensures (we hope) that ZeroTier traffic will still take the physical @@ -1807,6 +1906,23 @@ public: return 1; } + inline int nodePathLookupFunction(uint64_t ztaddr,int family,struct sockaddr_storage *result) + { + const Hashtable< uint64_t,std::vector > *lh = (const Hashtable< uint64_t,std::vector > *)0; + if (family < 0) + lh = (_node->prng() & 1) ? &_v4Hints : &_v6Hints; + else if (family == AF_INET) + lh = &_v4Hints; + else if (family == AF_INET6) + lh = &_v6Hints; + else return 0; + const std::vector *l = lh->get(ztaddr); + if ((l)&&(l->size() > 0)) { + memcpy(result,&((*l)[(unsigned long)_node->prng() % l->size()]),sizeof(struct sockaddr_storage)); + return 1; + } else return 0; + } + inline void tapFrameHandler(uint64_t nwid,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) { _node->processVirtualNetworkFrame(OSUtils::now(),nwid,from.toInt(),to.toInt(),etherType,vlanId,data,len,&_nextBackgroundTaskDeadline); @@ -1956,8 +2072,10 @@ static int SnodeWirePacketSendFunction(ZT_Node *node,void *uptr,const struct soc { return reinterpret_cast(uptr)->nodeWirePacketSendFunction(localAddr,addr,data,len,ttl); } static void SnodeVirtualNetworkFrameFunction(ZT_Node *node,void *uptr,uint64_t nwid,void **nuptr,uint64_t sourceMac,uint64_t destMac,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) { reinterpret_cast(uptr)->nodeVirtualNetworkFrameFunction(nwid,nuptr,sourceMac,destMac,etherType,vlanId,data,len); } -static int SnodePathCheckFunction(ZT_Node *node,void *uptr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *remoteAddr) -{ return reinterpret_cast(uptr)->nodePathCheckFunction(localAddr,remoteAddr); } +static int SnodePathCheckFunction(ZT_Node *node,void *uptr,uint64_t ztaddr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *remoteAddr) +{ return reinterpret_cast(uptr)->nodePathCheckFunction(ztaddr,localAddr,remoteAddr); } +static int SnodePathLookupFunction(ZT_Node *node,void *uptr,uint64_t ztaddr,int family,struct sockaddr_storage *result) +{ return reinterpret_cast(uptr)->nodePathLookupFunction(ztaddr,family,result); } #ifdef ZT_ENABLE_CLUSTER static void SclusterSendFunction(void *uptr,unsigned int toMemberId,const void *data,unsigned int len) -- cgit v1.2.3 From 84732fcb12d66708e7887fba51413cbe629d86d3 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 22 Nov 2016 14:23:13 -0800 Subject: Wire through external path lookup. Static paths should now work. --- node/Constants.hpp | 5 +++++ node/Node.cpp | 2 +- node/Node.hpp | 7 +++++-- node/Peer.cpp | 11 +++++++++++ node/Peer.hpp | 8 ++++++++ node/Switch.cpp | 15 ++++++++------- service/OneService.cpp | 13 +++++++------ 7 files changed, 45 insertions(+), 16 deletions(-) (limited to 'service/OneService.cpp') diff --git a/node/Constants.hpp b/node/Constants.hpp index 8803ecee..ac1919b3 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -320,6 +320,11 @@ */ #define ZT_MIN_UNITE_INTERVAL 30000 +/** + * How often should peers try memorized or statically defined paths? + */ +#define ZT_TRY_MEMORIZED_PATH_INTERVAL 30000 + /** * Sanity limit on maximum bridge routes * diff --git a/node/Node.cpp b/node/Node.cpp index a180766b..11f76365 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -683,7 +683,7 @@ void Node::postTrace(const char *module,unsigned int line,const char *fmt,...) uint64_t Node::prng() { - unsigned int p = (++_prngStreamPtr % (sizeof(_prngStream) / sizeof(uint64_t))); + unsigned int p = (++_prngStreamPtr % ZT_NODE_PRNG_BUF_SIZE); if (!p) _prng.encrypt12(_prngStream,_prngStream,sizeof(_prngStream)); return _prngStream[p]; diff --git a/node/Node.hpp b/node/Node.hpp index 7d99ff09..eb46527d 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -49,6 +49,9 @@ #define ZT_EXPECTING_REPLIES_BUCKET_MASK1 255 #define ZT_EXPECTING_REPLIES_BUCKET_MASK2 31 +// Size of PRNG stream buffer +#define ZT_NODE_PRNG_BUF_SIZE 64 + namespace ZeroTier { /** @@ -195,7 +198,7 @@ public: #endif bool shouldUsePathForZeroTierTraffic(const Address &ztaddr,const InetAddress &localAddress,const InetAddress &remoteAddress); - inline bool getPathHint(const Address &ztaddr,int family,InetAddress &addr) { return ( (_cb.pathLookupFunction) ? (_cb.pathLookupFunction(reinterpret_cast(this),_uPtr,ztaddr.toInt(),family,reinterpret_cast(&addr)) != 0) : false ); } + inline bool externalPathLookup(const Address &ztaddr,int family,InetAddress &addr) { return ( (_cb.pathLookupFunction) ? (_cb.pathLookupFunction(reinterpret_cast(this),_uPtr,ztaddr.toInt(),family,reinterpret_cast(&addr)) != 0) : false ); } uint64_t prng(); void postCircuitTestReport(const ZT_CircuitTestReport *report); @@ -284,7 +287,7 @@ private: unsigned int _prngStreamPtr; Salsa20 _prng; - uint64_t _prngStream[16]; // repeatedly encrypted with _prng to yield a high-quality non-crypto PRNG stream + uint64_t _prngStream[ZT_NODE_PRNG_BUF_SIZE]; // repeatedly encrypted with _prng to yield a high-quality non-crypto PRNG stream uint64_t _now; uint64_t _lastPingCheck; diff --git a/node/Peer.cpp b/node/Peer.cpp index e0bd0eac..2ef139e1 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -43,6 +43,7 @@ static uint32_t _natKeepaliveBuf = 0; Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Identity &peerIdentity) : _lastReceive(0), _lastNontrivialReceive(0), + _lastTriedMemorizedPath(0), _lastDirectPathPushSent(0), _lastDirectPathPushReceive(0), _lastCredentialRequestSent(0), @@ -373,6 +374,16 @@ void Peer::attemptToContactAt(const InetAddress &localAddr,const InetAddress &at } } +void Peer::tryMemorizedPath(uint64_t now) +{ + if ((now - _lastTriedMemorizedPath) >= ZT_TRY_MEMORIZED_PATH_INTERVAL) { + _lastTriedMemorizedPath = now; + InetAddress mp; + if (RR->node->externalPathLookup(_id.address(),-1,mp)) + attemptToContactAt(InetAddress(),mp,now); + } +} + bool Peer::doPingAndKeepalive(uint64_t now,int inetAddressFamily) { Mutex::Lock _l(_paths_m); diff --git a/node/Peer.hpp b/node/Peer.hpp index a7240cb4..78b345b9 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -164,6 +164,13 @@ public: */ void attemptToContactAt(const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now); + /** + * Try a memorized or statically defined path if any are known + * + * Under the hood this is done periodically based on ZT_TRY_MEMORIZED_PATH_INTERVAL. + */ + void tryMemorizedPath(uint64_t now); + /** * Send pings or keepalives depending on configured timeouts * @@ -435,6 +442,7 @@ private: uint8_t _remoteClusterOptimal6[16]; uint64_t _lastReceive; // direct or indirect uint64_t _lastNontrivialReceive; // frames, things like netconf, etc. + uint64_t _lastTriedMemorizedPath; uint64_t _lastDirectPathPushSent; uint64_t _lastDirectPathPushReceive; uint64_t _lastCredentialRequestSent; diff --git a/node/Switch.cpp b/node/Switch.cpp index 881d7b92..7c94d438 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -710,12 +710,12 @@ bool Switch::_trySend(const Packet &packet,bool encrypt) if (peer) { const uint64_t now = RR->node->now(); - // First get the best path, and if it's dead (and this is not a root) - // we attempt to re-activate that path but this packet will flow - // upstream. If the path comes back alive, it will be used in the future. - // For roots we don't do the alive check since roots are not required - // to send heartbeats "down" and because we have to at least try to - // go somewhere. + /* First get the best path, and if it's dead (and this is not a root) + * we attempt to re-activate that path but this packet will flow + * upstream. If the path comes back alive, it will be used in the future. + * For roots we don't do the alive check since roots are not required + * to send heartbeats "down" and because we have to at least try to + * go somewhere. */ SharedPtr viaPath(peer->getBestPath(now,false)); if ( (viaPath) && (!viaPath->alive(now)) && (!RR->topology->isRoot(peer->identity())) ) { @@ -724,7 +724,8 @@ bool Switch::_trySend(const Packet &packet,bool encrypt) viaPath.zero(); } if (!viaPath) { - SharedPtr relay(RR->topology->getUpstreamPeer()); + peer->tryMemorizedPath(now); // periodically attempt memorized or statically defined paths, if any are known + const SharedPtr relay(RR->topology->getUpstreamPeer()); if ( (!relay) || (!(viaPath = relay->getBestPath(now,false))) ) { if (!(viaPath = peer->getBestPath(now,true))) return false; diff --git a/service/OneService.cpp b/service/OneService.cpp index 7434ca67..a2024e52 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1163,6 +1163,7 @@ public: // Internal implementation methods ----------------------------------------- + // Must be called after _localConfig is read or modified void applyLocalConfig() { Mutex::Lock _l(_localConfig_m); @@ -1872,6 +1873,12 @@ public: } } + /* Note: I do not think we need to scan for overlap with managed routes + * because of the "route forking" and interface binding that we do. This + * ensures (we hope) that ZeroTier traffic will still take the physical + * path even if its managed routes override this for other traffic. Will + * revisit if we see recursion problems. */ + // Check blacklists const Hashtable< uint64_t,std::vector > *blh = (const Hashtable< uint64_t,std::vector > *)0; const std::vector *gbl = (const std::vector *)0; @@ -1897,12 +1904,6 @@ public: } } - /* Note: I do not think we need to scan for overlap with managed routes - * because of the "route forking" and interface binding that we do. This - * ensures (we hope) that ZeroTier traffic will still take the physical - * path even if its managed routes override this for other traffic. Will - * revisit if we see problems with this. */ - return 1; } -- cgit v1.2.3 From 27f1155f1b2e7bbd61336837498d098b9e4f4a8d Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 23 Nov 2016 15:53:53 -0800 Subject: docs and API stuff --- service/ControlPlane.cpp | 6 +- service/OneService.cpp | 7 +- service/README.md | 171 +++++++++++++++++++++++++---------------------- 3 files changed, 98 insertions(+), 86 deletions(-) (limited to 'service/OneService.cpp') diff --git a/service/ControlPlane.cpp b/service/ControlPlane.cpp index 2f9e746e..21afee52 100644 --- a/service/ControlPlane.cpp +++ b/service/ControlPlane.cpp @@ -123,6 +123,7 @@ static void _jsonAppend(unsigned int depth,std::string &buf,const ZT_VirtualNetw Utils::snprintf(json,sizeof(json), "%s{\n" + "%s\t\"id\": \"%.16llx\",\n" "%s\t\"nwid\": \"%.16llx\",\n" "%s\t\"mac\": \"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\",\n" "%s\t\"name\": \"%s\",\n" @@ -143,6 +144,7 @@ static void _jsonAppend(unsigned int depth,std::string &buf,const ZT_VirtualNetw "%s}", prefix, prefix,nc->nwid, + prefix,nc->nwid, prefix,(unsigned int)((nc->mac >> 40) & 0xff),(unsigned int)((nc->mac >> 32) & 0xff),(unsigned int)((nc->mac >> 24) & 0xff),(unsigned int)((nc->mac >> 16) & 0xff),(unsigned int)((nc->mac >> 8) & 0xff),(unsigned int)(nc->mac & 0xff), prefix,_jsonEscape(nc->name).c_str(), prefix,nstatus, @@ -214,9 +216,9 @@ static void _jsonAppend(unsigned int depth,std::string &buf,const ZT_Peer *peer) const char *prole = ""; switch(peer->role) { - case ZT_PEER_ROLE_LEAF: prole = "LEAF"; break; + case ZT_PEER_ROLE_LEAF: prole = "LEAF"; break; case ZT_PEER_ROLE_UPSTREAM: prole = "UPSTREAM"; break; - case ZT_PEER_ROLE_ROOT: prole = "ROOT"; break; + case ZT_PEER_ROLE_ROOT: prole = "ROOT"; break; } Utils::snprintf(json,sizeof(json), diff --git a/service/OneService.cpp b/service/OneService.cpp index a2024e52..6cfaeb0e 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1179,7 +1179,8 @@ public: if ((nstr.length() == ZT_ADDRESS_LENGTH_HEX)&&(v.value().is_object())) { const Address ztaddr(nstr.c_str()); if (ztaddr) { - _node->setRole(ztaddr.toInt(),(_jS(v.value()["role"],"") == "upstream") ? ZT_PEER_ROLE_UPSTREAM : ZT_PEER_ROLE_LEAF); + const std::string rstr(_jS(v.value()["role"],"")); + _node->setRole(ztaddr.toInt(),((rstr == "upstream")||(rstr == "UPSTREAM")) ? ZT_PEER_ROLE_UPSTREAM : ZT_PEER_ROLE_LEAF); const uint64_t ztaddr2 = ztaddr.toInt(); std::vector &v4h = _v4Hints[ztaddr2]; @@ -1239,9 +1240,9 @@ public: json &settings = _localConfig["settings"]; if (settings.is_object()) { const std::string rp(_jS(settings["relayPolicy"],"")); - if (rp == "always") + if ((rp == "always")||(rp == "ALWAYS")) _node->setRelayPolicy(ZT_RELAY_POLICY_ALWAYS); - else if (rp == "never") + else if ((rp == "never")||(rp == "NEVER")) _node->setRelayPolicy(ZT_RELAY_POLICY_NEVER); else _node->setRelayPolicy(ZT_RELAY_POLICY_TRUSTED); } diff --git a/service/README.md b/service/README.md index f487f2bc..45f06fcf 100644 --- a/service/README.md +++ b/service/README.md @@ -3,7 +3,30 @@ ZeroTier One Network Virtualization Service This is the common background service implementation for ZeroTier One, the VPN-like OS-level network virtualization service. -It provides a ready-made core I/O loop and a local HTTP-based JSON control bus for controlling the service. This control bus HTTP server can also serve the files in ui/ if this folder's contents are installed in the ZeroTier home folder. The ui/ implements a React-based HTML5 user interface which is then wrappered for various platforms via MacGap, Windows .NET WebControl, etc. It can also be used locally from scripts or via *curl*. +### Local Configuration File + +Example `local.conf`: + +```javascript +{ + "physical": { + "network/bits": { + "trustedPathId": 0, + "blacklist": false + } + }, + "virtual": { + "##########": { + "role": "UPSTREAM", + "try": [ "IP/port" ], + "blacklist": [ "network/bits" ] + } + }, + "settings": { + "relayPolicy": "TRUSTED" + } +} +``` ### Network Virtualization Service API @@ -21,32 +44,19 @@ A *jsonp* URL argument may be supplied to request JSONP encapsulation. A JSONP r * Methods: GET * Returns: { object } - - - - - - - - - - - - - -
FieldTypeDescriptionWritable
addressstring10-digit hexadecimal ZeroTier address of this nodeno
publicIdentitystringFull public ZeroTier identity of this nodeno
worldIdintegerFixed value representing the virtual data center of Earth.no
worldTimestampintegerTimestamp of the last root server topology change.no
onlinebooleanDoes this node appear to have upstream network access?no
tcpFallbackActivebooleanIs TCP fallback mode active?no
versionMajorintegerZeroTier major versionno
versionMinorintegerZeroTier minor versionno
versionRevintegerZeroTier revisionno
versionstringVersion in major.minor.rev formatno
clockintegerNode system clock in ms since epochno
- -#### /config - - * Purpose: Get or set local configuration - * Methods: GET, POST - * Returns: { object } - -No local configuration options are exposed yet. - - - -
FieldTypeDescriptionWritable
+| Field | Type | Description | Writable | +| --------------------- | ------------- | ------------------------------------------------- | -------- | +| address | string | 10-digit hex ZeroTier address of this node | no | +| publicIdentity | string | This node's ZeroTier identity.public | no | +| worldId | integer | ZeroTier world ID (never changes except for test) | no | +| worldTimestamp | integer | Timestamp of most recent world definition | no | +| online | boolean | If true at least one upstream peer is reachable | no | +| tcpFallbackActive | boolean | If true we are using slow TCP fallback | no | +| versionMajor | integer | Software major version | no | +| versionMinor | integer | Software minor version | no | +| versionRev | integer | Software revision | no | +| version | string | major.minor.revision | no | +| clock | integer | Current system clock at node (ms since epoch) | no | #### /network @@ -66,36 +76,35 @@ To join a network, POST to it. Since networks have no mandatory writable paramet Most network settings are not writable, as they are defined by the network controller. - - - - - - - - - - - - - - - - - - - -
FieldTypeDescriptionWritable
nwidstring16-digit hex network IDno
macstringEthernet MAC address of virtual network portno
namestringNetwork short name as configured on network controllerno
statusstringNetwork status: OK, ACCESS_DENIED, PORT_ERROR, etc.no
typestringNetwork type, currently PUBLIC or PRIVATEno
mtuintegerEthernet MTUno
dhcpbooleanIf true, DHCP may be used to obtain an IP addressno
bridgebooleanIf true, this node may bridge in other Ethernet devicesno
broadcastEnabledbooleanIs Ethernet broadcast (ff:ff:ff:ff:ff:ff) allowed?no
portErrorintegerError code (if any) returned by underlying OS "tap" driverno
netconfRevisionintegerNetwork configuration revision IDno
assignedAddresses[string]ZeroTier-managed IP address assignments as array of IP/netmask bits tuplesno
routes[route]ZeroTier-managed route assignments for a network. See below for a description of the route object.no
portDeviceNamestringOS-specific network device name (if available)no
allowManagedbooleanWhether ZeroTier-managed IP addresses are allowed.yes
allowGlobalbooleanWhether globally-reachable IP addresses are allowed to be assigned.yes
allowDefaultbooleanWhether a default route is allowed to be assigned for the network (route all traffic via ZeroTier)yes
- -`route` objects - - - - - - - -
FieldTypeDescriptionWritable
targetstringTarget network / netmask bits, NULL, or 0.0.0.0/0 for default routeno
viastringGateway IP addressno
flagsintegerRoute flagsno
metricintegerRoute metric (not currently used)no
+| Field | Type | Description | Writable | +| --------------------- | ------------- | ------------------------------------------------- | -------- | +| id | string | 16-digit hex network ID | no | +| nwid | string | 16-digit hex network ID (legacy field) | no | +| mac | string | MAC address of network device for this network | no | +| name | string | Short name of this network (from controller) | no | +| status | string | Network status (OK, ACCESS_DENIED, etc.) | no | +| type | string | Network type (PUBLIC or PRIVATE) | no | +| mtu | integer | Ethernet MTU | no | +| dhcp | boolean | If true, DHCP should be used to get IP info | no | +| bridge | boolean | If true, this device can bridge others | no | +| broadcastEnabled | boolean | If true ff:ff:ff:ff:ff:ff broadcasts work | no | +| portError | integer | Error code returned by underlying tap driver | no | +| netconfRevision | integer | Network configuration revision ID | no | +| assignedAddresses | [string] | Array of ZeroTier-assigned IP addresses (/bits) | no | +| routes | [object] | Array of ZeroTier-assigned routes (see below) | no | +| portDeviceName | string | Name of virtual network device (if any) | no | +| allowManaged | boolean | Allow IP and route management | yes | +| allowGlobal | boolean | Allow IPs and routes that overlap with global IPs | yes | +| allowDefault | boolean | Allow overriding of system default route | yes | + +Route objects: + +| Field | Type | Description | Writable | +| --------------------- | ------------- | ------------------------------------------------- | -------- | +| target | string | Target network / netmask bits | no | +| via | string | Gateway IP address (next hop) or null for LAN | no | +| flags | integer | Flags, currently always 0 | no | +| metric | integer | Route metric (not currently used) | no | #### /peer @@ -107,29 +116,29 @@ Getting /peer returns an array of peer objects for all current peers. See below #### /peer/\ - * Purpose: Get information about a peer - * Methods: GET + * Purpose: Get or set information about a peer + * Methods: GET, POST * Returns: { object } - - - - - - - - - - -
FieldTypeDescriptionWritable
addressstring10-digit hex ZeroTier addressno
versionMajorintegerMajor version of remote if knownno
versionMinorintegerMinor version of remote if knownno
versionRevintegerRevision of remote if knownno
versionstringVersion in major.minor.rev formatno
latencyintegerLatency in milliseconds if knownno
rolestringLEAF, HUB, or ROOTSERVERno
paths[object]Array of path objects (see below)no
- -Path objects describe direct physical paths to peer. If no path objects are listed, peer is only reachable via indirect relay fallback. Path object format is: - - - - - - - - -
FieldTypeDescriptionWritable
addressstringPhysical socket address e.g. IP/port for UDPno
lastSendintegerLast send via this path in ms since epochno
lastReceiveintegerLast receive via this path in ms since epochno
fixedbooleanIf true, this is a statically-defined "fixed" pathno
preferredbooleanIf true, this is the current preferred pathno
+| Field | Type | Description | Writable | +| --------------------- | ------------- | ------------------------------------------------- | -------- | +| address | string | 10-digit hex ZeroTier address of peer | no | +| versionMajor | integer | Major version of remote (if known) | no | +| versionMinor | integer | Minor version of remote (if known) | no | +| versionRev | integer | Software revision of remote (if known) | no | +| version | string | major.minor.revision | no | +| latency | integer | Latency in milliseconds if known | no | +| role | string | LEAF, UPSTREAM, or ROOT | no | +| paths | [object] | Currently active physical paths (see below) | no | + +Path objects: + +| Field | Type | Description | Writable | +| --------------------- | ------------- | ------------------------------------------------- | -------- | +| address | string | Physical socket address e.g. IP/port | no | +| lastSend | integer | Time of last send through this path | no | +| lastReceive | integer | Time of last receive through this path | no | +| active | boolean | Is this path in use? | no | +| expired | boolean | Is this path expired? | no | +| preferred | boolean | Is this a current preferred path? | no | +| trustedPathId | integer | If nonzero this is a trusted path (unencrypted) | no | -- cgit v1.2.3 From 4702c5b4eea3e84f5ceed075277e69353537c94d Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 12 Dec 2016 14:43:09 -0800 Subject: Add local.conf option to blacklist interfaces by name. --- service/OneService.cpp | 73 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 29 deletions(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 6cfaeb0e..05e8997d 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -403,26 +403,6 @@ public: static BackgroundSoftwareUpdateChecker backgroundSoftwareUpdateChecker; #endif // ZT_AUTO_UPDATE -static bool isBlacklistedLocalInterfaceForZeroTierTraffic(const char *ifn) -{ -#if defined(__linux__) || defined(linux) || defined(__LINUX__) || defined(__linux) - if ((ifn[0] == 'l')&&(ifn[1] == 'o')) return true; // loopback - if ((ifn[0] == 'z')&&(ifn[1] == 't')) return true; // sanity check: zt# - if ((ifn[0] == 't')&&(ifn[1] == 'u')&&(ifn[2] == 'n')) return true; // tun# is probably an OpenVPN tunnel or similar - if ((ifn[0] == 't')&&(ifn[1] == 'a')&&(ifn[2] == 'p')) return true; // tap# is probably an OpenVPN tunnel or similar -#endif - -#ifdef __APPLE__ - if ((ifn[0] == 'l')&&(ifn[1] == 'o')) return true; // loopback - if ((ifn[0] == 'z')&&(ifn[1] == 't')) return true; // sanity check: zt# - if ((ifn[0] == 't')&&(ifn[1] == 'u')&&(ifn[2] == 'n')) return true; // tun# is probably an OpenVPN tunnel or similar - if ((ifn[0] == 't')&&(ifn[1] == 'a')&&(ifn[2] == 'p')) return true; // tap# is probably an OpenVPN tunnel or similar - if ((ifn[0] == 'u')&&(ifn[1] == 't')&&(ifn[2] == 'u')&&(ifn[3] == 'n')) return true; // ... as is utun# -#endif - - return false; -} - static std::string _trimString(const std::string &s) { unsigned long end = (unsigned long)s.length(); @@ -547,6 +527,7 @@ public: Hashtable< uint64_t,std::vector > _v6Blacklists; std::vector< InetAddress > _globalV4Blacklist; std::vector< InetAddress > _globalV6Blacklist; + std::vector< std::string > _interfacePrefixBlacklist; Mutex _localConfig_m; /* @@ -1237,6 +1218,7 @@ public: } } + _interfacePrefixBlacklist.clear(); json &settings = _localConfig["settings"]; if (settings.is_object()) { const std::string rp(_jS(settings["relayPolicy"],"")); @@ -1245,6 +1227,15 @@ public: else if ((rp == "never")||(rp == "NEVER")) _node->setRelayPolicy(ZT_RELAY_POLICY_NEVER); else _node->setRelayPolicy(ZT_RELAY_POLICY_TRUSTED); + + json &ignoreIfs = settings["interfacePrefixBlacklist"]; + if (ignoreIfs.is_array()) { + for(unsigned long i=0;i 0) + _interfacePrefixBlacklist.push_back(tmp); + } + } } } @@ -1992,16 +1983,40 @@ public: bool shouldBindInterface(const char *ifname,const InetAddress &ifaddr) { - if (isBlacklistedLocalInterfaceForZeroTierTraffic(ifname)) - return false; +#if defined(__linux__) || defined(linux) || defined(__LINUX__) || defined(__linux) + if ((ifname[0] == 'l')&&(ifname[1] == 'o')) return false; // loopback + if ((ifname[0] == 'z')&&(ifname[1] == 't')) return false; // sanity check: zt# + if ((ifname[0] == 't')&&(ifname[1] == 'u')&&(ifname[2] == 'n')) return false; // tun# is probably an OpenVPN tunnel or similar + if ((ifname[0] == 't')&&(ifname[1] == 'a')&&(ifname[2] == 'p')) return false; // tap# is probably an OpenVPN tunnel or similar +#endif - Mutex::Lock _l(_nets_m); - for(std::map::const_iterator n(_nets.begin());n!=_nets.end();++n) { - if (n->second.tap) { - std::vector ips(n->second.tap->ips()); - for(std::vector::const_iterator i(ips.begin());i!=ips.end();++i) { - if (i->ipsEqual(ifaddr)) - return false; +#ifdef __APPLE__ + if ((ifname[0] == 'l')&&(ifname[1] == 'o')) return false; // loopback + if ((ifname[0] == 'z')&&(ifname[1] == 't')) return false; // sanity check: zt# + if ((ifname[0] == 't')&&(ifname[1] == 'u')&&(ifname[2] == 'n')) return false; // tun# is probably an OpenVPN tunnel or similar + if ((ifname[0] == 't')&&(ifname[1] == 'a')&&(ifname[2] == 'p')) return false; // tap# is probably an OpenVPN tunnel or similar + if ((ifname[0] == 'u')&&(ifname[1] == 't')&&(ifname[2] == 'u')&&(ifname[3] == 'n')) return false; // ... as is utun# +#endif + + { + Mutex::Lock _l(_localConfig_m); + for(std::vector::const_iterator p(_interfacePrefixBlacklist.begin());p!=_interfacePrefixBlacklist.end();++p) { + if (!strncmp(p->c_str(),ifname,p->length())) { + printf("%s\n",ifname); + return false; + } + } + } + + { + Mutex::Lock _l(_nets_m); + for(std::map::const_iterator n(_nets.begin());n!=_nets.end();++n) { + if (n->second.tap) { + std::vector ips(n->second.tap->ips()); + for(std::vector::const_iterator i(ips.begin());i!=ips.end();++i) { + if (i->ipsEqual(ifaddr)) + return false; + } } } } -- cgit v1.2.3 From bad4b72f823642ee076c98a267ff425b59c47b2c Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 12 Dec 2016 14:44:21 -0800 Subject: Remove debug printf. --- service/OneService.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 05e8997d..b925fc1b 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -2001,10 +2001,8 @@ public: { Mutex::Lock _l(_localConfig_m); for(std::vector::const_iterator p(_interfacePrefixBlacklist.begin());p!=_interfacePrefixBlacklist.end();++p) { - if (!strncmp(p->c_str(),ifname,p->length())) { - printf("%s\n",ifname); + if (!strncmp(p->c_str(),ifname,p->length())) return false; - } } } -- cgit v1.2.3 From 890f6f0d35cc715f759cb3014c536a8801bd0c99 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 12 Dec 2016 16:25:41 -0800 Subject: Make allow management from a local.conf parameters. --- one.cpp | 11 +-- service/OneService.cpp | 231 ++++++++++++++++++++++++++++--------------------- service/OneService.hpp | 6 +- 3 files changed, 132 insertions(+), 116 deletions(-) (limited to 'service/OneService.cpp') diff --git a/one.cpp b/one.cpp index 3dad2ed9..c4fc30e2 100644 --- a/one.cpp +++ b/one.cpp @@ -973,7 +973,6 @@ int main(int argc,char **argv) std::string homeDir; unsigned int port = ZT_DEFAULT_PORT; bool skipRootCheck = false; - const char *allowManagementFrom = (const char *)0; for(int i=1;irun()) { case OneService::ONE_STILL_RUNNING: // shouldn't happen, run() won't return until done case OneService::ONE_NORMAL_TERMINATION: diff --git a/service/OneService.cpp b/service/OneService.cpp index b925fc1b..2e256307 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -514,10 +514,10 @@ public: const std::string _homePath; BackgroundResolver _tcpFallbackResolver; - InetAddress _allowManagementFrom; EmbeddedNetworkController *_controller; Phy _phy; Node *_node; + unsigned int _primaryPort; // Local configuration and memo-ized static path definitions json _localConfig; @@ -527,6 +527,7 @@ public: Hashtable< uint64_t,std::vector > _v6Blacklists; std::vector< InetAddress > _globalV4Blacklist; std::vector< InetAddress > _globalV6Blacklist; + std::vector< InetAddress > _allowManagementFrom; std::vector< std::string > _interfacePrefixBlacklist; Mutex _localConfig_m; @@ -612,12 +613,13 @@ public: // end member variables ---------------------------------------------------- - OneServiceImpl(const char *hp,unsigned int port,const char *allowManagementFrom) : + OneServiceImpl(const char *hp,unsigned int port) : _homePath((hp) ? hp : ".") ,_tcpFallbackResolver(ZT_TCP_FALLBACK_RELAY) ,_controller((EmbeddedNetworkController *)0) ,_phy(this,false,true) ,_node((Node *)0) + ,_primaryPort(port) ,_controlPlane((ControlPlane *)0) ,_lastDirectReceiveFromGlobal(0) #ifdef ZT_TCP_FALLBACK_RELAY @@ -637,63 +639,9 @@ public: #endif ,_run(true) { - if (allowManagementFrom) - _allowManagementFrom.fromString(allowManagementFrom); - _ports[0] = 0; _ports[1] = 0; _ports[2] = 0; - - // The control socket is bound to the default/static port on localhost. If we - // can do this, we have successfully allocated a port. The binders will take - // care of binding non-local addresses for ZeroTier traffic. - const int portTrials = (port == 0) ? 256 : 1; // if port is 0, pick random - for(int k=0;kaddress() % 45500); - for(int i=0;;++i) { - if (i > 1000) { - _ports[1] = 0; - break; - } else if (++_ports[1] >= 65536) { - _ports[1] = 20000; - } - if (_trialBind(_ports[1])) - break; - } - -#ifdef ZT_USE_MINIUPNPC - // If we're running uPnP/NAT-PMP, bind a *third* port for that. We can't - // use the other two ports for that because some NATs do really funky - // stuff with ports that are explicitly mapped that breaks things. - if (_ports[1]) { - _ports[2] = _ports[1]; - for(int i=0;;++i) { - if (i > 1000) { - _ports[2] = 0; - break; - } else if (++_ports[2] >= 65536) { - _ports[2] = 20000; - } - if (_trialBind(_ports[2])) - break; - } - if (_ports[2]) { - char uniqueName[64]; - Utils::snprintf(uniqueName,sizeof(uniqueName),"ZeroTier/%.10llx@%u",_node->address(),_ports[2]); - _portMapper = new PortMapper(_ports[2],uniqueName); - } - } -#endif - - for(int i=0;i<3;++i) - _portsBE[i] = Utils::hton((uint16_t)_ports[i]); - + // Read local configuration { uint64_t trustedPathIds[ZT_MAX_TRUSTED_PATHS]; InetAddress trustedPathNetworks[ZT_MAX_TRUSTED_PATHS]; @@ -872,6 +778,103 @@ public: } applyLocalConfig(); + // Bind TCP control socket + const int portTrials = (_primaryPort == 0) ? 256 : 1; // if port is 0, pick random + for(int k=0;k 0) ? 0 : 0x7f000001)); // right now we just listen for TCP @127.0.0.1 + in4.sin_port = Utils::hton((uint16_t)_primaryPort); + _v4TcpControlSocket = _phy.tcpListen((const struct sockaddr *)&in4,this); + + struct sockaddr_in6 in6; + memset((void *)&in6,0,sizeof(in6)); + in6.sin6_family = AF_INET6; + in6.sin6_port = in4.sin_port; + if (_allowManagementFrom.size() == 0) + in6.sin6_addr.s6_addr[15] = 1; // IPv6 localhost == ::1 + _v6TcpControlSocket = _phy.tcpListen((const struct sockaddr *)&in6,this); + + // We must bind one of IPv4 or IPv6 -- support either failing to support hosts that + // have only IPv4 or only IPv6 stacks. + if ((_v4TcpControlSocket)||(_v6TcpControlSocket)) { + _ports[0] = _primaryPort; + break; + } else { + if (_v4TcpControlSocket) + _phy.close(_v4TcpControlSocket,false); + if (_v6TcpControlSocket) + _phy.close(_v6TcpControlSocket,false); + _primaryPort = 0; + } + } else { + _primaryPort = 0; + } + } + if (_ports[0] == 0) { + Mutex::Lock _l(_termReason_m); + _termReason = ONE_UNRECOVERABLE_ERROR; + _fatalErrorMessage = "cannot bind to local control interface port"; + return _termReason; + } + + // Write file containing primary port to be read by CLIs, etc. + char portstr[64]; + Utils::snprintf(portstr,sizeof(portstr),"%u",_ports[0]); + OSUtils::writeFile((_homePath + ZT_PATH_SEPARATOR_S + "zerotier-one.port").c_str(),std::string(portstr)); + + // Attempt to bind to a secondary port chosen from our ZeroTier address. + // This exists because there are buggy NATs out there that fail if more + // than one device behind the same NAT tries to use the same internal + // private address port number. + _ports[1] = 20000 + ((unsigned int)_node->address() % 45500); + for(int i=0;;++i) { + if (i > 1000) { + _ports[1] = 0; + break; + } else if (++_ports[1] >= 65536) { + _ports[1] = 20000; + } + if (_trialBind(_ports[1])) + break; + } + +#ifdef ZT_USE_MINIUPNPC + // If we're running uPnP/NAT-PMP, bind a *third* port for that. We can't + // use the other two ports for that because some NATs do really funky + // stuff with ports that are explicitly mapped that breaks things. + if (_ports[1]) { + _ports[2] = _ports[1]; + for(int i=0;;++i) { + if (i > 1000) { + _ports[2] = 0; + break; + } else if (++_ports[2] >= 65536) { + _ports[2] = 20000; + } + if (_trialBind(_ports[2])) + break; + } + if (_ports[2]) { + char uniqueName[64]; + Utils::snprintf(uniqueName,sizeof(uniqueName),"ZeroTier/%.10llx@%u",_node->address(),_ports[2]); + _portMapper = new PortMapper(_ports[2],uniqueName); + } + } +#endif + + // Populate ports in big-endian format for quick compare + for(int i=0;i<3;++i) + _portsBE[i] = Utils::hton((uint16_t)_ports[i]); + _controller = new EmbeddedNetworkController(_node,(_homePath + ZT_PATH_SEPARATOR_S + ZT_CONTROLLER_DB_PATH).c_str()); _node->setNetconfMaster((void *)_controller); @@ -1218,6 +1221,7 @@ public: } } + _allowManagementFrom.clear(); _interfacePrefixBlacklist.clear(); json &settings = _localConfig["settings"]; if (settings.is_object()) { @@ -1236,6 +1240,15 @@ public: _interfacePrefixBlacklist.push_back(tmp); } } + + json &amf = settings["allowManagementFrom"]; + if (amf.is_array()) { + for(unsigned long i=0;ifrom.ipScope() == InetAddress::IP_SCOPE_LOOPBACK)) || (_allowManagementFrom.containsAddress(tc->from)) ) { + bool allow; + { + Mutex::Lock _l(_localConfig_m); + if (_allowManagementFrom.size() == 0) { + allow = (tc->from.ipScope() == InetAddress::IP_SCOPE_LOOPBACK); + } else { + allow = false; + for(std::vector::const_iterator i(_allowManagementFrom.begin());i!=_allowManagementFrom.end();++i) { + if (i->containsAddress(tc->from)) { + allow = true; + break; + } + } + } + } + + if (allow) { try { if (_controlPlane) scode = _controlPlane->handleRequest(tc->from,tc->parser.method,tc->url,tc->headers,tc->body,data,contentType); @@ -2230,7 +2259,7 @@ std::string OneService::autoUpdateUrl() return std::string(); } -OneService *OneService::newInstance(const char *hp,unsigned int port,const char *allowManagementFrom) { return new OneServiceImpl(hp,port,allowManagementFrom); } +OneService *OneService::newInstance(const char *hp,unsigned int port) { return new OneServiceImpl(hp,port); } OneService::~OneService() {} } // namespace ZeroTier diff --git a/service/OneService.hpp b/service/OneService.hpp index 553bfd5e..aebc051b 100644 --- a/service/OneService.hpp +++ b/service/OneService.hpp @@ -98,12 +98,8 @@ public: * * @param hp Home path * @param port TCP and UDP port for packets and HTTP control (if 0, pick random port) - * @param allowManagementFrom If non-NULL, allow control from supplied IP/netmask */ - static OneService *newInstance( - const char *hp, - unsigned int port, - const char *allowManagementFrom = (const char *)0); + static OneService *newInstance(const char *hp,unsigned int port); virtual ~OneService(); -- cgit v1.2.3 From a54c2b438c0abc574039055ecfc70dd829e2cade Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 15 Dec 2016 15:08:47 -0800 Subject: Basic support for streaming of changes via stdout from controller. --- controller/EmbeddedNetworkController.cpp | 4 ++-- controller/EmbeddedNetworkController.hpp | 7 ++++++- controller/JSONDB.cpp | 19 +++++++++++++++---- controller/JSONDB.hpp | 5 ++++- service/OneService.cpp | 2 +- 5 files changed, 28 insertions(+), 9 deletions(-) (limited to 'service/OneService.cpp') diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index 974936e4..df20d4ce 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -458,9 +458,9 @@ static bool _parseRule(json &r,ZT_VirtualNetworkRule &rule) return false; } -EmbeddedNetworkController::EmbeddedNetworkController(Node *node,const char *dbPath) : +EmbeddedNetworkController::EmbeddedNetworkController(Node *node,const char *dbPath,FILE *feed) : _threadsStarted(false), - _db(dbPath), + _db(dbPath,feed), _node(node) { OSUtils::mkdir(dbPath); diff --git a/controller/EmbeddedNetworkController.hpp b/controller/EmbeddedNetworkController.hpp index cde6522d..37c067ff 100644 --- a/controller/EmbeddedNetworkController.hpp +++ b/controller/EmbeddedNetworkController.hpp @@ -53,7 +53,12 @@ class Node; class EmbeddedNetworkController : public NetworkController { public: - EmbeddedNetworkController(Node *node,const char *dbPath); + /** + * @param node Parent node + * @param dbPath Path to store data + * @param feed FILE to send feed of all data and changes to (zero-delimited JSON objects) or NULL for none + */ + EmbeddedNetworkController(Node *node,const char *dbPath,FILE *feed); virtual ~EmbeddedNetworkController(); virtual void init(const Identity &signingId,Sender *sender); diff --git a/controller/JSONDB.cpp b/controller/JSONDB.cpp index a9e9d05b..dfea9dd1 100644 --- a/controller/JSONDB.cpp +++ b/controller/JSONDB.cpp @@ -27,14 +27,17 @@ bool JSONDB::put(const std::string &n,const nlohmann::json &obj) if (!_isValidObjectName(n)) return false; - std::string path(_genPath(n,true)); + const std::string path(_genPath(n,true)); if (!path.length()) return false; - std::string buf(obj.dump(2)); + const std::string buf(obj.dump(2)); if (!OSUtils::writeFile(path.c_str(),buf)) return false; + if (_feed) + fwrite(buf.c_str(),buf.length()+1,1,_feed); + _E &e = _db[n]; e.obj = obj; e.lastModifiedOnDisk = OSUtils::getLastModified(path.c_str()); @@ -55,7 +58,8 @@ const nlohmann::json &JSONDB::get(const std::string &n,unsigned long maxSinceChe if (e != _db.end()) { if ((now - e->second.lastCheck) <= (uint64_t)maxSinceCheck) return e->second.obj; - std::string path(_genPath(n,false)); + + const std::string path(_genPath(n,false)); if (!path.length()) // sanity check return _EMPTY_JSON; @@ -68,13 +72,16 @@ const nlohmann::json &JSONDB::get(const std::string &n,unsigned long maxSinceChe e->second.obj = nlohmann::json::parse(buf); e->second.lastModifiedOnDisk = lm; // don't update these if there is a parse error -- try again and again ASAP e->second.lastCheck = now; + + if (_feed) + fwrite(buf.c_str(),buf.length()+1,1,_feed); // it changed, so send to feed (also sends all objects on startup, which we want for Central) } catch ( ... ) {} // parse errors result in "holding pattern" behavior } } return e->second.obj; } else { - std::string path(_genPath(n,false)); + const std::string path(_genPath(n,false)); if (!path.length()) return _EMPTY_JSON; @@ -87,10 +94,14 @@ const nlohmann::json &JSONDB::get(const std::string &n,unsigned long maxSinceChe e2.obj = nlohmann::json::parse(buf); } catch ( ... ) { e2.obj = _EMPTY_JSON; + buf = "{}"; } e2.lastModifiedOnDisk = lm; e2.lastCheck = now; + if (_feed) + fwrite(buf.c_str(),buf.length()+1,1,_feed); + return e2.obj; } } diff --git a/controller/JSONDB.hpp b/controller/JSONDB.hpp index bd1ae5a5..40113655 100644 --- a/controller/JSONDB.hpp +++ b/controller/JSONDB.hpp @@ -19,6 +19,7 @@ #ifndef ZT_JSONDB_HPP #define ZT_JSONDB_HPP +#include #include #include @@ -41,7 +42,8 @@ namespace ZeroTier { class JSONDB { public: - JSONDB(const std::string &basePath) : + JSONDB(const std::string &basePath,FILE *feed) : + _feed(feed), _basePath(basePath) { _reload(_basePath); @@ -106,6 +108,7 @@ private: inline bool operator!=(const _E &e) const { return (obj != e.obj); } }; + FILE *_feed; std::string _basePath; std::map _db; }; diff --git a/service/OneService.cpp b/service/OneService.cpp index 2e256307..3a7edacb 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -875,7 +875,7 @@ public: for(int i=0;i<3;++i) _portsBE[i] = Utils::hton((uint16_t)_ports[i]); - _controller = new EmbeddedNetworkController(_node,(_homePath + ZT_PATH_SEPARATOR_S + ZT_CONTROLLER_DB_PATH).c_str()); + _controller = new EmbeddedNetworkController(_node,(_homePath + ZT_PATH_SEPARATOR_S + ZT_CONTROLLER_DB_PATH).c_str(),(FILE *)0); _node->setNetconfMaster((void *)_controller); #ifdef ZT_ENABLE_CLUSTER -- cgit v1.2.3 From e2b1a7157e3ba7b3cb342582acbdeb22033d7b84 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Thu, 5 Jan 2017 11:43:26 -0800 Subject: Potential fix for routing issue on Windows Move setting _initialized = true until after WindowsEthernetTap::threadMain() has actually created and brought up the adapter. Also in OneService::nodeVirtualNetworkConfigFunction(), wait up to 5 seconds for WindowsEthernatTap::isInitialized() to return true before attempting to configure the interface and managed routes. Without this, the adapter doesnt actually exist yet when trying to add routes --- osdep/WindowsEthernetTap.cpp | 6 +++++- osdep/WindowsEthernetTap.hpp | 5 +++++ service/OneService.cpp | 10 ++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) (limited to 'service/OneService.cpp') diff --git a/osdep/WindowsEthernetTap.cpp b/osdep/WindowsEthernetTap.cpp index a9ff31d3..8ee088bb 100644 --- a/osdep/WindowsEthernetTap.cpp +++ b/osdep/WindowsEthernetTap.cpp @@ -640,7 +640,7 @@ WindowsEthernetTap::WindowsEthernetTap( if (ConvertInterfaceGuidToLuid(&_deviceGuid,&_deviceLuid) != NO_ERROR) throw std::runtime_error("unable to convert device interface GUID to LUID"); - _initialized = true; + //_initialized = true; if (friendlyName) setFriendlyName(friendlyName); @@ -1007,6 +1007,10 @@ void WindowsEthernetTap::threadMain() ReadFile(_tap,tapReadBuf,sizeof(tapReadBuf),NULL,&tapOvlRead); bool writeInProgress = false; ULONGLONG timeOfLastBorkCheck = GetTickCount64(); + + + _initialized = true; + while (_run) { DWORD waitResult = WaitForMultipleObjectsEx(writeInProgress ? 3 : 2,wait4,FALSE,2500,TRUE); if (!_run) break; // will also break outer while(_run) diff --git a/osdep/WindowsEthernetTap.hpp b/osdep/WindowsEthernetTap.hpp index 0bbb17d8..74b37f8c 100644 --- a/osdep/WindowsEthernetTap.hpp +++ b/osdep/WindowsEthernetTap.hpp @@ -110,12 +110,17 @@ public: void threadMain() throw(); + bool isInitialized() const { return _initialized; }; + private: NET_IFINDEX _getDeviceIndex(); // throws on failure std::vector _getRegistryIPv4Value(const char *regKey); void _setRegistryIPv4Value(const char *regKey,const std::vector &value); void _syncIps(); + // clean up invalid values put into the windows registry + // void _cleanRegistry(); + void (*_handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int); void *_arg; MAC _mac; diff --git a/service/OneService.cpp b/service/OneService.cpp index 3a7edacb..96b3a960 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1666,6 +1666,16 @@ public: case ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE: memcpy(&(n.config),nwc,sizeof(ZT_VirtualNetworkConfig)); if (n.tap) { // sanity check +#ifdef __WINDOWS__ + // wait for up to 5 seconds for the WindowsEthernetTap to actually be initialized + // + // 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++) { + Sleep(10); + } +#endif syncManagedStuff(n,true,true); } else { _nets.erase(nwid); -- cgit v1.2.3 From 6fb49f68fc2ac3539732794f553f635610c92ef2 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 10 Jan 2017 12:20:29 -0800 Subject: Comment out and disable old auto-update code. --- make-mac.mk | 6 +----- service/OneService.cpp | 38 ++++---------------------------------- service/OneService.hpp | 5 ----- 3 files changed, 5 insertions(+), 44 deletions(-) (limited to 'service/OneService.cpp') diff --git a/make-mac.mk b/make-mac.mk index 0fbd3817..79f50ca1 100644 --- a/make-mac.mk +++ b/make-mac.mk @@ -24,7 +24,7 @@ ZT_USE_MINIUPNPC?=1 # For internal use only -- signs everything with ZeroTier's developer cert ifeq ($(ZT_OFFICIAL_RELEASE),1) - DEFS+=-DZT_OFFICIAL_RELEASE -DZT_AUTO_UPDATE + DEFS+=-DZT_OFFICIAL_RELEASE ZT_USE_MINIUPNPC=1 CODESIGN=codesign PRODUCTSIGN=productsign @@ -36,10 +36,6 @@ ifeq ($(ZT_ENABLE_CLUSTER),1) DEFS+=-DZT_ENABLE_CLUSTER endif -ifeq ($(ZT_AUTO_UPDATE),1) - DEFS+=-DZT_AUTO_UPDATE -endif - ifeq ($(ZT_USE_MINIUPNPC),1) DEFS+=-DMACOSX -DZT_USE_MINIUPNPC -DMINIUPNP_STATICLIB -D_DARWIN_C_SOURCE -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -D_BSD_SOURCE -D_DEFAULT_SOURCE -DOS_STRING=\"Darwin/15.0.0\" -DMINIUPNPC_VERSION_STRING=\"2.0\" -DUPNP_VERSION_STRING=\"UPnP/1.1\" -DENABLE_STRNATPMPERR OBJS+=ext/libnatpmp/natpmp.o ext/libnatpmp/getgateway.o ext/miniupnpc/connecthostport.o ext/miniupnpc/igd_desc_parse.o ext/miniupnpc/minisoap.o ext/miniupnpc/minissdpc.o ext/miniupnpc/miniupnpc.o ext/miniupnpc/miniwget.o ext/miniupnpc/minixml.o ext/miniupnpc/portlistingparse.o ext/miniupnpc/receivedata.o ext/miniupnpc/upnpcommands.o ext/miniupnpc/upnpdev.o ext/miniupnpc/upnperrors.o ext/miniupnpc/upnpreplyparse.o osdep/PortMapper.o diff --git a/service/OneService.cpp b/service/OneService.cpp index 96b3a960..cd267982 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -194,6 +194,8 @@ static std::string _jS(const json &jv,const char *dfl) return std::string((dfl) ? dfl : ""); } +#if 0 + #ifdef ZT_AUTO_UPDATE #define ZT_AUTO_UPDATE_MAX_HTTP_RESPONSE_SIZE (1024 * 1024 * 64) #define ZT_AUTO_UPDATE_CHECK_PERIOD 21600000 @@ -403,6 +405,8 @@ public: static BackgroundSoftwareUpdateChecker backgroundSoftwareUpdateChecker; #endif // ZT_AUTO_UPDATE +#endif + static std::string _trimString(const std::string &s) { unsigned long end = (unsigned long)s.length(); @@ -947,9 +951,6 @@ public: uint64_t lastTcpFallbackResolve = 0; uint64_t lastBindRefresh = 0; uint64_t lastLocalInterfaceAddressCheck = (OSUtils::now() - ZT_LOCAL_INTERFACE_CHECK_INTERVAL) + 15000; // do this in 15s to give portmapper time to configure and other things time to settle -#ifdef ZT_AUTO_UPDATE - uint64_t lastSoftwareUpdateCheck = 0; -#endif // ZT_AUTO_UPDATE for(;;) { _run_m.lock(); if (!_run) { @@ -994,13 +995,6 @@ public: dl = _nextBackgroundTaskDeadline; } -#ifdef ZT_AUTO_UPDATE - if ((now - lastSoftwareUpdateCheck) >= ZT_AUTO_UPDATE_CHECK_PERIOD) { - lastSoftwareUpdateCheck = now; - Thread::start(&backgroundSoftwareUpdateChecker); - } -#endif // ZT_AUTO_UPDATE - if ((now - lastTcpFallbackResolve) >= ZT_TCP_FALLBACK_RERESOLVE_DELAY) { lastTcpFallbackResolve = now; _tcpFallbackResolver.resolveNow(); @@ -2245,30 +2239,6 @@ std::string OneService::platformDefaultHomePath() return OSUtils::platformDefaultHomePath(); } -std::string OneService::autoUpdateUrl() -{ -#ifdef ZT_AUTO_UPDATE - -/* -#if defined(__LINUX__) && ( defined(__i386__) || defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(__i386) ) - if (sizeof(void *) == 8) - return "http://download.zerotier.com/ZeroTierOneInstaller-linux-x64-LATEST.nfo"; - else return "http://download.zerotier.com/ZeroTierOneInstaller-linux-x86-LATEST.nfo"; -#endif -*/ - -#if defined(__APPLE__) && ( defined(__i386__) || defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(__i386) ) - return "http://download.zerotier.com/update/mac_intel/"; -#endif - -#ifdef __WINDOWS__ - return "http://download.zerotier.com/update/win_intel/"; -#endif - -#endif // ZT_AUTO_UPDATE - return std::string(); -} - OneService *OneService::newInstance(const char *hp,unsigned int port) { return new OneServiceImpl(hp,port); } OneService::~OneService() {} diff --git a/service/OneService.hpp b/service/OneService.hpp index aebc051b..7aa3b361 100644 --- a/service/OneService.hpp +++ b/service/OneService.hpp @@ -81,11 +81,6 @@ public: */ static std::string platformDefaultHomePath(); - /** - * @return Auto-update URL or empty string if auto-updates unsupported or not enabled - */ - static std::string autoUpdateUrl(); - /** * Create a new instance of the service * -- cgit v1.2.3 From a064e19b8a78d3809e9f80fba010e0f53197c1a2 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 10 Jan 2017 13:51:10 -0800 Subject: Refactor some JSON stuff for performance, and fix a build error. --- controller/EmbeddedNetworkController.cpp | 261 +++++++++++++------------------ controller/JSONDB.cpp | 6 +- one.cpp | 3 - osdep/OSUtils.cpp | 58 +++++++ osdep/OSUtils.hpp | 8 + service/ControlPlane.cpp | 2 +- service/OneService.cpp | 68 ++------ 7 files changed, 188 insertions(+), 218 deletions(-) (limited to 'service/OneService.cpp') diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index bed76df7..3c13e7ce 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -63,53 +63,6 @@ using json = nlohmann::json; namespace ZeroTier { -// Get JSON values as unsigned integers, strings, or booleans, doing type conversion if possible -static uint64_t _jI(const json &jv,const uint64_t dfl) -{ - if (jv.is_number()) { - return (uint64_t)jv; - } else if (jv.is_string()) { - std::string s = jv; - return Utils::strToU64(s.c_str()); - } else if (jv.is_boolean()) { - return ((bool)jv ? 1ULL : 0ULL); - } - return dfl; -} -static bool _jB(const json &jv,const bool dfl) -{ - if (jv.is_boolean()) { - return (bool)jv; - } else if (jv.is_number()) { - return ((uint64_t)jv > 0ULL); - } else if (jv.is_string()) { - std::string s = jv; - if (s.length() > 0) { - switch(s[0]) { - case 't': - case 'T': - case '1': - return true; - } - } - return false; - } - return dfl; -} -static std::string _jS(const json &jv,const char *dfl) -{ - if (jv.is_string()) { - return jv; - } else if (jv.is_number()) { - char tmp[64]; - Utils::snprintf(tmp,sizeof(tmp),"%llu",(uint64_t)jv); - return tmp; - } else if (jv.is_boolean()) { - return ((bool)jv ? std::string("1") : std::string("0")); - } - return std::string((dfl) ? dfl : ""); -} - static json _renderRule(ZT_VirtualNetworkRule &rule) { char tmp[128]; @@ -281,13 +234,13 @@ static bool _parseRule(json &r,ZT_VirtualNetworkRule &rule) if (!r.is_object()) return false; - const std::string t(_jS(r["type"],"")); + const std::string t(OSUtils::jsonString(r["type"],"")); memset(&rule,0,sizeof(ZT_VirtualNetworkRule)); - if (_jB(r["not"],false)) + if (OSUtils::jsonBool(r["not"],false)) rule.t = 0x80; else rule.t = 0x00; - if (_jB(r["or"],false)) + if (OSUtils::jsonBool(r["or"],false)) rule.t |= 0x40; if (t == "ACTION_DROP") { @@ -298,115 +251,115 @@ static bool _parseRule(json &r,ZT_VirtualNetworkRule &rule) return true; } else if (t == "ACTION_TEE") { rule.t |= ZT_NETWORK_RULE_ACTION_TEE; - rule.v.fwd.address = Utils::hexStrToU64(_jS(r["address"],"0").c_str()) & 0xffffffffffULL; - rule.v.fwd.flags = (uint32_t)(_jI(r["flags"],0ULL) & 0xffffffffULL); - rule.v.fwd.length = (uint16_t)(_jI(r["length"],0ULL) & 0xffffULL); + rule.v.fwd.address = Utils::hexStrToU64(OSUtils::jsonString(r["address"],"0").c_str()) & 0xffffffffffULL; + rule.v.fwd.flags = (uint32_t)(OSUtils::jsonInt(r["flags"],0ULL) & 0xffffffffULL); + rule.v.fwd.length = (uint16_t)(OSUtils::jsonInt(r["length"],0ULL) & 0xffffULL); return true; } else if (t == "ACTION_WATCH") { rule.t |= ZT_NETWORK_RULE_ACTION_WATCH; - rule.v.fwd.address = Utils::hexStrToU64(_jS(r["address"],"0").c_str()) & 0xffffffffffULL; - rule.v.fwd.flags = (uint32_t)(_jI(r["flags"],0ULL) & 0xffffffffULL); - rule.v.fwd.length = (uint16_t)(_jI(r["length"],0ULL) & 0xffffULL); + rule.v.fwd.address = Utils::hexStrToU64(OSUtils::jsonString(r["address"],"0").c_str()) & 0xffffffffffULL; + rule.v.fwd.flags = (uint32_t)(OSUtils::jsonInt(r["flags"],0ULL) & 0xffffffffULL); + rule.v.fwd.length = (uint16_t)(OSUtils::jsonInt(r["length"],0ULL) & 0xffffULL); return true; } else if (t == "ACTION_REDIRECT") { rule.t |= ZT_NETWORK_RULE_ACTION_REDIRECT; - rule.v.fwd.address = Utils::hexStrToU64(_jS(r["address"],"0").c_str()) & 0xffffffffffULL; - rule.v.fwd.flags = (uint32_t)(_jI(r["flags"],0ULL) & 0xffffffffULL); + rule.v.fwd.address = Utils::hexStrToU64(OSUtils::jsonString(r["address"],"0").c_str()) & 0xffffffffffULL; + rule.v.fwd.flags = (uint32_t)(OSUtils::jsonInt(r["flags"],0ULL) & 0xffffffffULL); return true; } else if (t == "ACTION_DEBUG_LOG") { rule.t |= ZT_NETWORK_RULE_ACTION_DEBUG_LOG; return true; } else if (t == "MATCH_SOURCE_ZEROTIER_ADDRESS") { rule.t |= ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS; - rule.v.zt = Utils::hexStrToU64(_jS(r["zt"],"0").c_str()) & 0xffffffffffULL; + rule.v.zt = Utils::hexStrToU64(OSUtils::jsonString(r["zt"],"0").c_str()) & 0xffffffffffULL; return true; } else if (t == "MATCH_DEST_ZEROTIER_ADDRESS") { rule.t |= ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS; - rule.v.zt = Utils::hexStrToU64(_jS(r["zt"],"0").c_str()) & 0xffffffffffULL; + rule.v.zt = Utils::hexStrToU64(OSUtils::jsonString(r["zt"],"0").c_str()) & 0xffffffffffULL; return true; } else if (t == "MATCH_VLAN_ID") { rule.t |= ZT_NETWORK_RULE_MATCH_VLAN_ID; - rule.v.vlanId = (uint16_t)(_jI(r["vlanId"],0ULL) & 0xffffULL); + rule.v.vlanId = (uint16_t)(OSUtils::jsonInt(r["vlanId"],0ULL) & 0xffffULL); return true; } else if (t == "MATCH_VLAN_PCP") { rule.t |= ZT_NETWORK_RULE_MATCH_VLAN_PCP; - rule.v.vlanPcp = (uint8_t)(_jI(r["vlanPcp"],0ULL) & 0xffULL); + rule.v.vlanPcp = (uint8_t)(OSUtils::jsonInt(r["vlanPcp"],0ULL) & 0xffULL); return true; } else if (t == "MATCH_VLAN_DEI") { rule.t |= ZT_NETWORK_RULE_MATCH_VLAN_DEI; - rule.v.vlanDei = (uint8_t)(_jI(r["vlanDei"],0ULL) & 0xffULL); + rule.v.vlanDei = (uint8_t)(OSUtils::jsonInt(r["vlanDei"],0ULL) & 0xffULL); return true; } else if (t == "MATCH_MAC_SOURCE") { rule.t |= ZT_NETWORK_RULE_MATCH_MAC_SOURCE; - const std::string mac(_jS(r["mac"],"0")); + const std::string mac(OSUtils::jsonString(r["mac"],"0")); Utils::unhex(mac.c_str(),(unsigned int)mac.length(),rule.v.mac,6); return true; } else if (t == "MATCH_MAC_DEST") { rule.t |= ZT_NETWORK_RULE_MATCH_MAC_DEST; - const std::string mac(_jS(r["mac"],"0")); + const std::string mac(OSUtils::jsonString(r["mac"],"0")); Utils::unhex(mac.c_str(),(unsigned int)mac.length(),rule.v.mac,6); return true; } else if (t == "MATCH_IPV4_SOURCE") { rule.t |= ZT_NETWORK_RULE_MATCH_IPV4_SOURCE; - InetAddress ip(_jS(r["ip"],"0.0.0.0")); + InetAddress ip(OSUtils::jsonString(r["ip"],"0.0.0.0")); rule.v.ipv4.ip = reinterpret_cast(&ip)->sin_addr.s_addr; rule.v.ipv4.mask = Utils::ntoh(reinterpret_cast(&ip)->sin_port) & 0xff; if (rule.v.ipv4.mask > 32) rule.v.ipv4.mask = 32; return true; } else if (t == "MATCH_IPV4_DEST") { rule.t |= ZT_NETWORK_RULE_MATCH_IPV4_DEST; - InetAddress ip(_jS(r["ip"],"0.0.0.0")); + InetAddress ip(OSUtils::jsonString(r["ip"],"0.0.0.0")); rule.v.ipv4.ip = reinterpret_cast(&ip)->sin_addr.s_addr; rule.v.ipv4.mask = Utils::ntoh(reinterpret_cast(&ip)->sin_port) & 0xff; if (rule.v.ipv4.mask > 32) rule.v.ipv4.mask = 32; return true; } else if (t == "MATCH_IPV6_SOURCE") { rule.t |= ZT_NETWORK_RULE_MATCH_IPV6_SOURCE; - InetAddress ip(_jS(r["ip"],"::0")); + InetAddress ip(OSUtils::jsonString(r["ip"],"::0")); memcpy(rule.v.ipv6.ip,reinterpret_cast(&ip)->sin6_addr.s6_addr,16); rule.v.ipv6.mask = Utils::ntoh(reinterpret_cast(&ip)->sin6_port) & 0xff; if (rule.v.ipv6.mask > 128) rule.v.ipv6.mask = 128; return true; } else if (t == "MATCH_IPV6_DEST") { rule.t |= ZT_NETWORK_RULE_MATCH_IPV6_DEST; - InetAddress ip(_jS(r["ip"],"::0")); + InetAddress ip(OSUtils::jsonString(r["ip"],"::0")); memcpy(rule.v.ipv6.ip,reinterpret_cast(&ip)->sin6_addr.s6_addr,16); rule.v.ipv6.mask = Utils::ntoh(reinterpret_cast(&ip)->sin6_port) & 0xff; if (rule.v.ipv6.mask > 128) rule.v.ipv6.mask = 128; return true; } else if (t == "MATCH_IP_TOS") { rule.t |= ZT_NETWORK_RULE_MATCH_IP_TOS; - rule.v.ipTos = (uint8_t)(_jI(r["ipTos"],0ULL) & 0xffULL); + rule.v.ipTos = (uint8_t)(OSUtils::jsonInt(r["ipTos"],0ULL) & 0xffULL); return true; } else if (t == "MATCH_IP_PROTOCOL") { rule.t |= ZT_NETWORK_RULE_MATCH_IP_PROTOCOL; - rule.v.ipProtocol = (uint8_t)(_jI(r["ipProtocol"],0ULL) & 0xffULL); + rule.v.ipProtocol = (uint8_t)(OSUtils::jsonInt(r["ipProtocol"],0ULL) & 0xffULL); return true; } else if (t == "MATCH_ETHERTYPE") { rule.t |= ZT_NETWORK_RULE_MATCH_ETHERTYPE; - rule.v.etherType = (uint16_t)(_jI(r["etherType"],0ULL) & 0xffffULL); + rule.v.etherType = (uint16_t)(OSUtils::jsonInt(r["etherType"],0ULL) & 0xffffULL); return true; } else if (t == "MATCH_ICMP") { rule.t |= ZT_NETWORK_RULE_MATCH_ICMP; - rule.v.icmp.type = (uint8_t)(_jI(r["icmpType"],0ULL) & 0xffULL); + rule.v.icmp.type = (uint8_t)(OSUtils::jsonInt(r["icmpType"],0ULL) & 0xffULL); json &code = r["icmpCode"]; if (code.is_null()) { rule.v.icmp.code = 0; rule.v.icmp.flags = 0x00; } else { - rule.v.icmp.code = (uint8_t)(_jI(code,0ULL) & 0xffULL); + rule.v.icmp.code = (uint8_t)(OSUtils::jsonInt(code,0ULL) & 0xffULL); rule.v.icmp.flags = 0x01; } return true; } else if (t == "MATCH_IP_SOURCE_PORT_RANGE") { rule.t |= ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE; - rule.v.port[0] = (uint16_t)(_jI(r["start"],0ULL) & 0xffffULL); - rule.v.port[1] = (uint16_t)(_jI(r["end"],(uint64_t)rule.v.port[0]) & 0xffffULL); + rule.v.port[0] = (uint16_t)(OSUtils::jsonInt(r["start"],0ULL) & 0xffffULL); + rule.v.port[1] = (uint16_t)(OSUtils::jsonInt(r["end"],(uint64_t)rule.v.port[0]) & 0xffffULL); return true; } else if (t == "MATCH_IP_DEST_PORT_RANGE") { rule.t |= ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE; - rule.v.port[0] = (uint16_t)(_jI(r["start"],0ULL) & 0xffffULL); - rule.v.port[1] = (uint16_t)(_jI(r["end"],(uint64_t)rule.v.port[0]) & 0xffffULL); + rule.v.port[0] = (uint16_t)(OSUtils::jsonInt(r["start"],0ULL) & 0xffffULL); + rule.v.port[1] = (uint16_t)(OSUtils::jsonInt(r["end"],(uint64_t)rule.v.port[0]) & 0xffffULL); return true; } else if (t == "MATCH_CHARACTERISTICS") { rule.t |= ZT_NETWORK_RULE_MATCH_CHARACTERISTICS; @@ -422,37 +375,37 @@ static bool _parseRule(json &r,ZT_VirtualNetworkRule &rule) return true; } else if (t == "MATCH_FRAME_SIZE_RANGE") { rule.t |= ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE; - rule.v.frameSize[0] = (uint16_t)(_jI(r["start"],0ULL) & 0xffffULL); - rule.v.frameSize[1] = (uint16_t)(_jI(r["end"],(uint64_t)rule.v.frameSize[0]) & 0xffffULL); + rule.v.frameSize[0] = (uint16_t)(OSUtils::jsonInt(r["start"],0ULL) & 0xffffULL); + rule.v.frameSize[1] = (uint16_t)(OSUtils::jsonInt(r["end"],(uint64_t)rule.v.frameSize[0]) & 0xffffULL); return true; } else if (t == "MATCH_RANDOM") { rule.t |= ZT_NETWORK_RULE_MATCH_RANDOM; - rule.v.randomProbability = (uint32_t)(_jI(r["probability"],0ULL) & 0xffffffffULL); + rule.v.randomProbability = (uint32_t)(OSUtils::jsonInt(r["probability"],0ULL) & 0xffffffffULL); return true; } else if (t == "MATCH_TAGS_DIFFERENCE") { rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE; - rule.v.tag.id = (uint32_t)(_jI(r["id"],0ULL) & 0xffffffffULL); - rule.v.tag.value = (uint32_t)(_jI(r["value"],0ULL) & 0xffffffffULL); + rule.v.tag.id = (uint32_t)(OSUtils::jsonInt(r["id"],0ULL) & 0xffffffffULL); + rule.v.tag.value = (uint32_t)(OSUtils::jsonInt(r["value"],0ULL) & 0xffffffffULL); return true; } else if (t == "MATCH_TAGS_BITWISE_AND") { rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND; - rule.v.tag.id = (uint32_t)(_jI(r["id"],0ULL) & 0xffffffffULL); - rule.v.tag.value = (uint32_t)(_jI(r["value"],0ULL) & 0xffffffffULL); + rule.v.tag.id = (uint32_t)(OSUtils::jsonInt(r["id"],0ULL) & 0xffffffffULL); + rule.v.tag.value = (uint32_t)(OSUtils::jsonInt(r["value"],0ULL) & 0xffffffffULL); return true; } else if (t == "MATCH_TAGS_BITWISE_OR") { rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR; - rule.v.tag.id = (uint32_t)(_jI(r["id"],0ULL) & 0xffffffffULL); - rule.v.tag.value = (uint32_t)(_jI(r["value"],0ULL) & 0xffffffffULL); + rule.v.tag.id = (uint32_t)(OSUtils::jsonInt(r["id"],0ULL) & 0xffffffffULL); + rule.v.tag.value = (uint32_t)(OSUtils::jsonInt(r["value"],0ULL) & 0xffffffffULL); return true; } else if (t == "MATCH_TAGS_BITWISE_XOR") { rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR; - rule.v.tag.id = (uint32_t)(_jI(r["id"],0ULL) & 0xffffffffULL); - rule.v.tag.value = (uint32_t)(_jI(r["value"],0ULL) & 0xffffffffULL); + rule.v.tag.id = (uint32_t)(OSUtils::jsonInt(r["id"],0ULL) & 0xffffffffULL); + rule.v.tag.value = (uint32_t)(OSUtils::jsonInt(r["value"],0ULL) & 0xffffffffULL); return true; } else if (t == "MATCH_TAGS_EQUAL") { rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_EQUAL; - rule.v.tag.id = (uint32_t)(_jI(r["id"],0ULL) & 0xffffffffULL); - rule.v.tag.value = (uint32_t)(_jI(r["value"],0ULL) & 0xffffffffULL); + rule.v.tag.id = (uint32_t)(OSUtils::jsonInt(r["id"],0ULL) & 0xffffffffULL); + rule.v.tag.value = (uint32_t)(OSUtils::jsonInt(r["value"],0ULL) & 0xffffffffULL); return true; } @@ -552,7 +505,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( return 404; _addMemberNonPersistedFields(member,OSUtils::now()); - responseBody = member.dump(2); + responseBody = OSUtils::jsonDump(member); responseContentType = "application/json"; return 200; @@ -565,9 +518,9 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( _db.filter(pfx,120000,[&responseBody](const std::string &n,const json &member) { if (member.size() > 0) { responseBody.append((responseBody.length() == 1) ? "\"" : ",\""); - responseBody.append(_jS(member["id"],"")); + responseBody.append(OSUtils::jsonString(member["id"],"")); responseBody.append("\":"); - responseBody.append(_jS(member["revision"],"0")); + responseBody.append(OSUtils::jsonString(member["revision"],"0")); } return true; // never delete }); @@ -600,7 +553,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( _NetworkMemberInfo nmi; _getNetworkMemberInfo(now,nwid,nmi); _addNetworkNonPersistedFields(network,now,nmi); - responseBody = network.dump(2); + responseBody = OSUtils::jsonDump(network); responseContentType = "application/json"; return 200; @@ -655,7 +608,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( json b; try { - b = json::parse(body); + b = OSUtils::jsonParse(body); if (!b.is_object()) { responseBody = "{ \"message\": \"body is not a JSON object\" }"; responseContentType = "application/json"; @@ -691,12 +644,12 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( _initMember(member); try { - if (b.count("activeBridge")) member["activeBridge"] = _jB(b["activeBridge"],false); - if (b.count("noAutoAssignIps")) member["noAutoAssignIps"] = _jB(b["noAutoAssignIps"],false); + if (b.count("activeBridge")) member["activeBridge"] = OSUtils::jsonBool(b["activeBridge"],false); + if (b.count("noAutoAssignIps")) member["noAutoAssignIps"] = OSUtils::jsonBool(b["noAutoAssignIps"],false); if (b.count("authorized")) { - const bool newAuth = _jB(b["authorized"],false); - if (newAuth != _jB(member["authorized"],false)) { + const bool newAuth = OSUtils::jsonBool(b["authorized"],false); + if (newAuth != OSUtils::jsonBool(member["authorized"],false)) { member["authorized"] = newAuth; member[((newAuth) ? "lastAuthorizedTime" : "lastDeauthorizedTime")] = now; @@ -732,7 +685,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( for(unsigned long i=0;i::iterator t(mtags.begin());t!=mtags.end();++t) { @@ -750,7 +703,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( if (capabilities.is_array()) { json mcaps = json::array(); for(unsigned long i=0;ireportAtEveryHop = (_jB(b["reportAtEveryHop"],true) ? 1 : 0); + test->reportAtEveryHop = (OSUtils::jsonBool(b["reportAtEveryHop"],true) ? 1 : 0); if (!test->hopCount) { ::free((void *)test); @@ -868,19 +821,19 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( _initNetwork(network); try { - if (b.count("name")) network["name"] = _jS(b["name"],""); - if (b.count("private")) network["private"] = _jB(b["private"],true); - if (b.count("enableBroadcast")) network["enableBroadcast"] = _jB(b["enableBroadcast"],false); - if (b.count("allowPassiveBridging")) network["allowPassiveBridging"] = _jB(b["allowPassiveBridging"],false); - if (b.count("multicastLimit")) network["multicastLimit"] = _jI(b["multicastLimit"],32ULL); + if (b.count("name")) network["name"] = OSUtils::jsonString(b["name"],""); + if (b.count("private")) network["private"] = OSUtils::jsonBool(b["private"],true); + if (b.count("enableBroadcast")) network["enableBroadcast"] = OSUtils::jsonBool(b["enableBroadcast"],false); + if (b.count("allowPassiveBridging")) network["allowPassiveBridging"] = OSUtils::jsonBool(b["allowPassiveBridging"],false); + if (b.count("multicastLimit")) network["multicastLimit"] = OSUtils::jsonInt(b["multicastLimit"],32ULL); if (b.count("v4AssignMode")) { json nv4m; json &v4m = b["v4AssignMode"]; if (v4m.is_string()) { // backward compatibility - nv4m["zt"] = (_jS(v4m,"") == "zt"); + nv4m["zt"] = (OSUtils::jsonString(v4m,"") == "zt"); } else if (v4m.is_object()) { - nv4m["zt"] = _jB(v4m["zt"],false); + nv4m["zt"] = OSUtils::jsonBool(v4m["zt"],false); } else nv4m["zt"] = false; network["v4AssignMode"] = nv4m; } @@ -890,7 +843,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( json &v6m = b["v6AssignMode"]; if (!nv6m.is_object()) nv6m = json::object(); if (v6m.is_string()) { // backward compatibility - std::vector v6ms(OSUtils::split(_jS(v6m,"").c_str(),",","","")); + std::vector v6ms(OSUtils::split(OSUtils::jsonString(v6m,"").c_str(),",","","")); std::sort(v6ms.begin(),v6ms.end()); v6ms.erase(std::unique(v6ms.begin(),v6ms.end()),v6ms.end()); nv6m["rfc4193"] = false; @@ -905,9 +858,9 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( nv6m["6plane"] = true; } } else if (v6m.is_object()) { - if (v6m.count("rfc4193")) nv6m["rfc4193"] = _jB(v6m["rfc4193"],false); - if (v6m.count("zt")) nv6m["zt"] = _jB(v6m["zt"],false); - if (v6m.count("6plane")) nv6m["6plane"] = _jB(v6m["6plane"],false); + if (v6m.count("rfc4193")) nv6m["rfc4193"] = OSUtils::jsonBool(v6m["rfc4193"],false); + if (v6m.count("zt")) nv6m["zt"] = OSUtils::jsonBool(v6m["zt"],false); + if (v6m.count("6plane")) nv6m["6plane"] = OSUtils::jsonBool(v6m["6plane"],false); } else { nv6m["rfc4193"] = false; nv6m["zt"] = false; @@ -951,8 +904,8 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( for(unsigned long i=0;i 0) { json t = json::object(); t["token"] = tstr; - t["expires"] = _jI(token["expires"],0ULL); - t["maxUsesPerMember"] = _jI(token["maxUsesPerMember"],0ULL); + t["expires"] = OSUtils::jsonInt(token["expires"],0ULL); + t["maxUsesPerMember"] = OSUtils::jsonInt(token["maxUsesPerMember"],0ULL); nat.push_back(t); } } @@ -1010,7 +963,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( json &cap = capabilities[i]; if (cap.is_object()) { json ncap = json::object(); - const uint64_t capId = _jI(cap["id"],0ULL); + const uint64_t capId = OSUtils::jsonInt(cap["id"],0ULL); ncap["id"] = capId; json &rules = cap["rules"]; @@ -1065,7 +1018,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( _getNetworkMemberInfo(now,nwid,nmi); _addNetworkNonPersistedFields(network,now,nmi); - responseBody = network.dump(2); + responseBody = OSUtils::jsonDump(network); responseContentType = "application/json"; return 200; } // else 404 @@ -1113,7 +1066,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpDELETE( if (!member.size()) return 404; - responseBody = member.dump(2); + responseBody = OSUtils::jsonDump(member); responseContentType = "application/json"; return 200; } @@ -1128,7 +1081,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpDELETE( Mutex::Lock _l2(_nmiCache_m); _nmiCache.erase(nwid); - responseBody = network.dump(2); + responseBody = OSUtils::jsonDump(network); responseContentType = "application/json"; return 200; } @@ -1254,7 +1207,7 @@ void EmbeddedNetworkController::_request( _initMember(member); { - std::string haveIdStr(_jS(member["identity"],"")); + std::string haveIdStr(OSUtils::jsonString(member["identity"],"")); if (haveIdStr.length() > 0) { // If we already know this member's identity perform a full compare. This prevents // a "collision" from being able to auth onto our network in place of an already @@ -1283,9 +1236,9 @@ void EmbeddedNetworkController::_request( const char *authorizedBy = (const char *)0; bool autoAuthorized = false; json autoAuthCredentialType,autoAuthCredential; - if (_jB(member["authorized"],false)) { + if (OSUtils::jsonBool(member["authorized"],false)) { authorizedBy = "memberIsAuthorized"; - } else if (!_jB(network["private"],true)) { + } else if (!OSUtils::jsonBool(network["private"],true)) { authorizedBy = "networkIsPublic"; json &ahist = member["authHistory"]; if ((!ahist.is_array())||(ahist.size() == 0)) @@ -1304,9 +1257,9 @@ void EmbeddedNetworkController::_request( for(unsigned long i=0;i now))&&(tstr == presentedToken)) { bool usable = (maxUses == 0); @@ -1316,7 +1269,7 @@ void EmbeddedNetworkController::_request( if (ahist.is_array()) { for(unsigned long j=0;j::const_iterator ab(nmi.activeBridges.begin());ab!=nmi.activeBridges.end();++ab) { nc.addSpecialist(*ab,ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE); @@ -1459,11 +1412,11 @@ void EmbeddedNetworkController::_request( for(unsigned long i=0;iis_object())&&(cap->size() > 0)) { ZT_VirtualNetworkRule capr[ZT_MAX_CAPABILITY_RULES]; @@ -1491,7 +1444,7 @@ void EmbeddedNetworkController::_request( for(unsigned long i=0;i::const_iterator t(tagsById.begin());t!=tagsById.end();++t) { if (nc.tagCount >= ZT_MAX_NETWORK_TAGS) @@ -1525,14 +1478,14 @@ void EmbeddedNetworkController::_request( } } - const bool noAutoAssignIps = _jB(member["noAutoAssignIps"],false); + const bool noAutoAssignIps = OSUtils::jsonBool(member["noAutoAssignIps"],false); if ((v6AssignMode.is_object())&&(!noAutoAssignIps)) { - if ((_jB(v6AssignMode["rfc4193"],false))&&(nc.staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES)) { + if ((OSUtils::jsonBool(v6AssignMode["rfc4193"],false))&&(nc.staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES)) { nc.staticIps[nc.staticIpCount++] = InetAddress::makeIpv6rfc4193(nwid,identity.address().toInt()); nc.flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION; } - if ((_jB(v6AssignMode["6plane"],false))&&(nc.staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES)) { + if ((OSUtils::jsonBool(v6AssignMode["6plane"],false))&&(nc.staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES)) { nc.staticIps[nc.staticIpCount++] = InetAddress::makeIpv66plane(nwid,identity.address().toInt()); nc.flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION; } @@ -1572,12 +1525,12 @@ void EmbeddedNetworkController::_request( ipAssignments = json::array(); } - if ( (ipAssignmentPools.is_array()) && ((v6AssignMode.is_object())&&(_jB(v6AssignMode["zt"],false))) && (!haveManagedIpv6AutoAssignment) && (!noAutoAssignIps) ) { + if ( (ipAssignmentPools.is_array()) && ((v6AssignMode.is_object())&&(OSUtils::jsonBool(v6AssignMode["zt"],false))) && (!haveManagedIpv6AutoAssignment) && (!noAutoAssignIps) ) { for(unsigned long p=0;((p(&ipRangeStartIA)->sin_addr.s_addr)); uint32_t ipRangeEnd = Utils::ntoh((uint32_t)(reinterpret_cast(&ipRangeEndIA)->sin_addr.s_addr)); @@ -1722,7 +1675,7 @@ void EmbeddedNetworkController::_getNetworkMemberInfo(uint64_t now,uint64_t nwid Mutex::Lock _l(_db_m); _db.filter(pfx,120000,[&nmi,&now](const std::string &n,const json &member) { try { - if (_jB(member["authorized"],false)) { + if (OSUtils::jsonBool(member["authorized"],false)) { ++nmi.authorizedMemberCount; if (member.count("recentLog")) { @@ -1730,28 +1683,28 @@ void EmbeddedNetworkController::_getNetworkMemberInfo(uint64_t now,uint64_t nwid if ((mlog.is_array())&&(mlog.size() > 0)) { const json &mlog1 = mlog[0]; if (mlog1.is_object()) { - if ((now - _jI(mlog1["ts"],0ULL)) < ZT_NETCONF_NODE_ACTIVE_THRESHOLD) + if ((now - OSUtils::jsonInt(mlog1["ts"],0ULL)) < ZT_NETCONF_NODE_ACTIVE_THRESHOLD) ++nmi.activeMemberCount; } } } - if (_jB(member["activeBridge"],false)) { - nmi.activeBridges.insert(_jS(member["id"],"0000000000")); + if (OSUtils::jsonBool(member["activeBridge"],false)) { + nmi.activeBridges.insert(OSUtils::jsonString(member["id"],"0000000000")); } if (member.count("ipAssignments")) { const json &mips = member["ipAssignments"]; if (mips.is_array()) { for(unsigned long i=0;isecond.lastModifiedOnDisk != lm) { if (OSUtils::readFile(path.c_str(),buf)) { try { - e->second.obj = nlohmann::json::parse(buf); + e->second.obj = OSUtils::jsonParse(buf); e->second.lastModifiedOnDisk = lm; // don't update these if there is a parse error -- try again and again ASAP e->second.lastCheck = now; @@ -91,7 +91,7 @@ const nlohmann::json &JSONDB::get(const std::string &n,unsigned long maxSinceChe const uint64_t lm = OSUtils::getLastModified(path.c_str()); _E &e2 = _db[n]; try { - e2.obj = nlohmann::json::parse(buf); + e2.obj = OSUtils::jsonParse(buf); } catch ( ... ) { e2.obj = _EMPTY_JSON; buf = "{}"; diff --git a/one.cpp b/one.cpp index c4fc30e2..1cda3fb1 100644 --- a/one.cpp +++ b/one.cpp @@ -897,9 +897,6 @@ static void printHelp(const char *cn,FILE *out) fprintf(out, COPYRIGHT_NOTICE ZT_EOL_S LICENSE_GRANT ZT_EOL_S); - std::string updateUrl(OneService::autoUpdateUrl()); - if (updateUrl.length()) - fprintf(out,"Automatic updates enabled:" ZT_EOL_S" %s" ZT_EOL_S" (all updates are securely authenticated by 256-bit ECDSA signature)" ZT_EOL_S"" ZT_EOL_S,updateUrl.c_str()); fprintf(out,"Usage: %s [-switches] [home directory]" ZT_EOL_S"" ZT_EOL_S,cn); fprintf(out,"Available switches:" ZT_EOL_S); fprintf(out," -h - Display this help" ZT_EOL_S); diff --git a/osdep/OSUtils.cpp b/osdep/OSUtils.cpp index 65704fa3..a6757bcc 100644 --- a/osdep/OSUtils.cpp +++ b/osdep/OSUtils.cpp @@ -395,6 +395,64 @@ std::string OSUtils::platformDefaultHomePath() #endif // __UNIX_LIKE__ or not... } +// Inline these massive JSON operations in one place only to reduce binary footprint and compile time +nlohmann::json OSUtils::jsonParse(const std::string &buf) { return nlohmann::json::parse(buf); } +std::string OSUtils::jsonDump(const nlohmann::json &j) { return j.dump(2); } + +uint64_t OSUtils::jsonInt(const nlohmann::json &jv,const uint64_t dfl) +{ + try { + if (jv.is_number()) { + return (uint64_t)jv; + } else if (jv.is_string()) { + std::string s = jv; + return Utils::strToU64(s.c_str()); + } else if (jv.is_boolean()) { + return ((bool)jv ? 1ULL : 0ULL); + } + } catch ( ... ) {} + return dfl; +} + +bool OSUtils::jsonBool(const nlohmann::json &jv,const bool dfl) +{ + try { + if (jv.is_boolean()) { + return (bool)jv; + } else if (jv.is_number()) { + return ((uint64_t)jv > 0ULL); + } else if (jv.is_string()) { + std::string s = jv; + if (s.length() > 0) { + switch(s[0]) { + case 't': + case 'T': + case '1': + return true; + } + } + return false; + } + } catch ( ... ) {} + return dfl; +} + +std::string OSUtils::jsonString(const nlohmann::json &jv,const char *dfl) +{ + try { + if (jv.is_string()) { + return jv; + } else if (jv.is_number()) { + char tmp[64]; + Utils::snprintf(tmp,sizeof(tmp),"%llu",(uint64_t)jv); + return tmp; + } else if (jv.is_boolean()) { + return ((bool)jv ? std::string("1") : std::string("0")); + } + } catch ( ... ) {} + return std::string((dfl) ? dfl : ""); +} + // Used to convert HTTP header names to ASCII lower case const unsigned char OSUtils::TOLOWER_TABLE[256] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; diff --git a/osdep/OSUtils.hpp b/osdep/OSUtils.hpp index c73f0bd3..7aa83f17 100644 --- a/osdep/OSUtils.hpp +++ b/osdep/OSUtils.hpp @@ -45,6 +45,8 @@ #include #endif +#include "../ext/json/json.hpp" + namespace ZeroTier { /** @@ -267,6 +269,12 @@ public: */ static std::string platformDefaultHomePath(); + static nlohmann::json jsonParse(const std::string &buf); + static std::string jsonDump(const nlohmann::json &j); + static uint64_t jsonInt(const nlohmann::json &jv,const uint64_t dfl); + static bool jsonBool(const nlohmann::json &jv,const bool dfl); + static std::string jsonString(const nlohmann::json &jv,const char *dfl); + private: static const unsigned char TOLOWER_TABLE[256]; }; diff --git a/service/ControlPlane.cpp b/service/ControlPlane.cpp index 3bdfdf1b..86158a91 100644 --- a/service/ControlPlane.cpp +++ b/service/ControlPlane.cpp @@ -515,7 +515,7 @@ unsigned int ControlPlane::handleRequest( _svc->getNetworkSettings(nws->networks[i].nwid,localSettings); try { - nlohmann::json j(nlohmann::json::parse(body)); + nlohmann::json j(OSUtils::jsonParse(body)); if (j.is_object()) { nlohmann::json &allowManaged = j["allowManaged"]; if (allowManaged.is_boolean()) localSettings.allowManaged = (bool)allowManaged; diff --git a/service/OneService.cpp b/service/OneService.cpp index cd267982..9a1084d0 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -148,52 +148,6 @@ namespace ZeroTier { namespace { -static uint64_t _jI(const json &jv,const uint64_t dfl) -{ - if (jv.is_number()) { - return (uint64_t)jv; - } else if (jv.is_string()) { - std::string s = jv; - return Utils::strToU64(s.c_str()); - } else if (jv.is_boolean()) { - return ((bool)jv ? 1ULL : 0ULL); - } - return dfl; -} -static bool _jB(const json &jv,const bool dfl) -{ - if (jv.is_boolean()) { - return (bool)jv; - } else if (jv.is_number()) { - return ((uint64_t)jv > 0ULL); - } else if (jv.is_string()) { - std::string s = jv; - if (s.length() > 0) { - switch(s[0]) { - case 't': - case 'T': - case '1': - return true; - } - } - return false; - } - return dfl; -} -static std::string _jS(const json &jv,const char *dfl) -{ - if (jv.is_string()) { - return jv; - } else if (jv.is_number()) { - char tmp[64]; - Utils::snprintf(tmp,sizeof(tmp),"%llu",(uint64_t)jv); - return tmp; - } else if (jv.is_boolean()) { - return ((bool)jv ? std::string("1") : std::string("0")); - } - return std::string((dfl) ? dfl : ""); -} - #if 0 #ifdef ZT_AUTO_UPDATE @@ -747,7 +701,7 @@ public: std::string lcbuf; if (OSUtils::readFile((_homePath + ZT_PATH_SEPARATOR_S + "local.conf").c_str(),lcbuf)) { try { - _localConfig = json::parse(lcbuf); + _localConfig = OSUtils::jsonParse(lcbuf); if (!_localConfig.is_object()) { fprintf(stderr,"WARNING: unable to parse local.conf (root element is not a JSON object)" ZT_EOL_S); } @@ -760,11 +714,11 @@ public: json &physical = _localConfig["physical"]; if (physical.is_object()) { for(json::iterator phy(physical.begin());phy!=physical.end();++phy) { - InetAddress net(_jS(phy.key(),"")); + InetAddress net(OSUtils::jsonString(phy.key(),"")); if (net) { if (phy.value().is_object()) { uint64_t tpid; - if ((tpid = _jI(phy.value()["trustedPathId"],0ULL)) != 0ULL) { + if ((tpid = OSUtils::jsonInt(phy.value()["trustedPathId"],0ULL)) != 0ULL) { if ( ((net.ss_family == AF_INET)||(net.ss_family == AF_INET6)) && (trustedPathCount < ZT_MAX_TRUSTED_PATHS) && (net.ipScope() != InetAddress::IP_SCOPE_GLOBAL) && (net.netmaskBits() > 0) ) { trustedPathIds[trustedPathCount] = tpid; trustedPathNetworks[trustedPathCount] = net; @@ -1157,7 +1111,7 @@ public: if ((nstr.length() == ZT_ADDRESS_LENGTH_HEX)&&(v.value().is_object())) { const Address ztaddr(nstr.c_str()); if (ztaddr) { - const std::string rstr(_jS(v.value()["role"],"")); + const std::string rstr(OSUtils::jsonString(v.value()["role"],"")); _node->setRole(ztaddr.toInt(),((rstr == "upstream")||(rstr == "UPSTREAM")) ? ZT_PEER_ROLE_UPSTREAM : ZT_PEER_ROLE_LEAF); const uint64_t ztaddr2 = ztaddr.toInt(); @@ -1169,7 +1123,7 @@ public: json &tryAddrs = v.value()["try"]; if (tryAddrs.is_array()) { for(unsigned long i=0;i 0)) { if (phy.value().is_object()) { - if (_jB(phy.value()["blacklist"],false)) { + if (OSUtils::jsonBool(phy.value()["blacklist"],false)) { if (net.ss_family == AF_INET) _globalV4Blacklist.push_back(net); else if (net.ss_family == AF_INET6) @@ -1219,7 +1173,7 @@ public: _interfacePrefixBlacklist.clear(); json &settings = _localConfig["settings"]; if (settings.is_object()) { - const std::string rp(_jS(settings["relayPolicy"],"")); + const std::string rp(OSUtils::jsonString(settings["relayPolicy"],"")); if ((rp == "always")||(rp == "ALWAYS")) _node->setRelayPolicy(ZT_RELAY_POLICY_ALWAYS); else if ((rp == "never")||(rp == "NEVER")) @@ -1229,7 +1183,7 @@ public: json &ignoreIfs = settings["interfacePrefixBlacklist"]; if (ignoreIfs.is_array()) { for(unsigned long i=0;i 0) _interfacePrefixBlacklist.push_back(tmp); } @@ -1238,7 +1192,7 @@ public: json &amf = settings["allowManagementFrom"]; if (amf.is_array()) { for(unsigned long i=0;i Date: Wed, 11 Jan 2017 16:34:33 -0800 Subject: Software update integration. --- service/OneService.cpp | 227 +++---------------------------------- service/SoftwareUpdater.cpp | 267 +++++++++++++++++++++++++++++++++++++++----- service/SoftwareUpdater.hpp | 15 ++- 3 files changed, 263 insertions(+), 246 deletions(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 9a1084d0..0c1279ca 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -52,6 +52,7 @@ #include "ControlPlane.hpp" #include "ClusterGeoIpService.hpp" #include "ClusterDefinition.hpp" +#include "SoftwareUpdater.hpp" #ifdef ZT_USE_SYSTEM_HTTP_PARSER #include @@ -148,219 +149,6 @@ namespace ZeroTier { namespace { -#if 0 - -#ifdef ZT_AUTO_UPDATE -#define ZT_AUTO_UPDATE_MAX_HTTP_RESPONSE_SIZE (1024 * 1024 * 64) -#define ZT_AUTO_UPDATE_CHECK_PERIOD 21600000 -class BackgroundSoftwareUpdateChecker -{ -public: - bool isValidSigningIdentity(const Identity &id) - { - return ( - /* 0001 - 0004 : obsolete, used in old versions */ - /* 0005 */ (id == Identity("ba57ea350e:0:9d4be6d7f86c5660d5ee1951a3d759aa6e12a84fc0c0b74639500f1dbc1a8c566622e7d1c531967ebceb1e9d1761342f88324a8ba520c93c35f92f35080fa23f")) - /* 0006 */ ||(id == Identity("5067b21b83:0:8af477730f5055c48135b84bed6720a35bca4c0e34be4060a4c636288b1ec22217eb22709d610c66ed464c643130c51411bbb0294eef12fbe8ecc1a1e2c63a7a")) - /* 0007 */ ||(id == Identity("4f5e97a8f1:0:57880d056d7baeb04bbc057d6f16e6cb41388570e87f01492fce882485f65a798648595610a3ad49885604e7fb1db2dd3c2c534b75e42c3c0b110ad07b4bb138")) - /* 0008 */ ||(id == Identity("580bbb8e15:0:ad5ef31155bebc6bc413991992387e083fed26d699997ef76e7c947781edd47d1997161fa56ba337b1a2b44b129fd7c7197ce5185382f06011bc88d1363b4ddd")) - ); - } - - void doUpdateCheck() - { - std::string url(OneService::autoUpdateUrl()); - if ((url.length() <= 7)||(url.substr(0,7) != "http://")) - return; - - std::string httpHost; - std::string httpPath; - { - std::size_t slashIdx = url.substr(7).find_first_of('/'); - if (slashIdx == std::string::npos) { - httpHost = url.substr(7); - httpPath = "/"; - } else { - httpHost = url.substr(7,slashIdx); - httpPath = url.substr(slashIdx + 7); - } - } - if (httpHost.length() == 0) - return; - - std::vector ips(OSUtils::resolve(httpHost.c_str())); - for(std::vector::iterator ip(ips.begin());ip!=ips.end();++ip) { - if (!ip->port()) - ip->setPort(80); - std::string nfoPath = httpPath + "LATEST.nfo"; - std::map requestHeaders,responseHeaders; - std::string body; - requestHeaders["Host"] = httpHost; - unsigned int scode = Http::GET(ZT_AUTO_UPDATE_MAX_HTTP_RESPONSE_SIZE,60000,reinterpret_cast(&(*ip)),nfoPath.c_str(),requestHeaders,responseHeaders,body); - //fprintf(stderr,"UPDATE %s %s %u %lu\n",ip->toString().c_str(),nfoPath.c_str(),scode,body.length()); - if ((scode == 200)&&(body.length() > 0)) { - /* NFO fields: - * - * file= - * signedBy= - * ed25519= - * vMajor= - * vMinor= - * vRevision= */ - Dictionary<4096> nfo(body.c_str()); - char tmp[2048]; - - if (nfo.get("vMajor",tmp,sizeof(tmp)) <= 0) return; - const unsigned int vMajor = Utils::strToUInt(tmp); - if (nfo.get("vMinor",tmp,sizeof(tmp)) <= 0) return; - const unsigned int vMinor = Utils::strToUInt(tmp); - if (nfo.get("vRevision",tmp,sizeof(tmp)) <= 0) return; - const unsigned int vRevision = Utils::strToUInt(tmp); - if (Utils::compareVersion(vMajor,vMinor,vRevision,ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION) <= 0) { - //fprintf(stderr,"UPDATE %u.%u.%u is not newer than our version\n",vMajor,vMinor,vRevision); - return; - } - - if (nfo.get("signedBy",tmp,sizeof(tmp)) <= 0) return; - Identity signedBy; - if ((!signedBy.fromString(tmp))||(!isValidSigningIdentity(signedBy))) { - //fprintf(stderr,"UPDATE invalid signedBy or not authorized signing identity.\n"); - return; - } - - if (nfo.get("file",tmp,sizeof(tmp)) <= 0) return; - std::string filePath(tmp); - if ((!filePath.length())||(filePath.find("..") != std::string::npos)) - return; - filePath = httpPath + filePath; - - std::string fileData; - if (Http::GET(ZT_AUTO_UPDATE_MAX_HTTP_RESPONSE_SIZE,60000,reinterpret_cast(&(*ip)),filePath.c_str(),requestHeaders,responseHeaders,fileData) != 200) { - //fprintf(stderr,"UPDATE GET %s failed\n",filePath.c_str()); - return; - } - - if (nfo.get("ed25519",tmp,sizeof(tmp)) <= 0) return; - std::string ed25519(Utils::unhex(tmp)); - if ((ed25519.length() == 0)||(!signedBy.verify(fileData.data(),(unsigned int)fileData.length(),ed25519.data(),(unsigned int)ed25519.length()))) { - //fprintf(stderr,"UPDATE %s failed signature check!\n",filePath.c_str()); - return; - } - - /* --------------------------------------------------------------- */ - /* We made it! Begin OS-specific installation code. */ - -#ifdef __APPLE__ - /* OSX version is in the form of a MacOSX .pkg file, so we will - * launch installer (normally in /usr/sbin) to install it. It will - * then turn around and shut down the service, update files, and - * relaunch. */ - { - char bashp[128],pkgp[128]; - Utils::snprintf(bashp,sizeof(bashp),"/tmp/ZeroTierOne-update-%u.%u.%u.sh",vMajor,vMinor,vRevision); - Utils::snprintf(pkgp,sizeof(pkgp),"/tmp/ZeroTierOne-update-%u.%u.%u.pkg",vMajor,vMinor,vRevision); - FILE *pkg = fopen(pkgp,"w"); - if ((!pkg)||(fwrite(fileData.data(),fileData.length(),1,pkg) != 1)) { - fclose(pkg); - unlink(bashp); - unlink(pkgp); - fprintf(stderr,"UPDATE error writing %s\n",pkgp); - return; - } - fclose(pkg); - FILE *bash = fopen(bashp,"w"); - if (!bash) { - fclose(pkg); - unlink(bashp); - unlink(pkgp); - fprintf(stderr,"UPDATE error writing %s\n",bashp); - return; - } - fprintf(bash, - "#!/bin/bash\n" - "export PATH=/bin:/usr/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/sbin\n" - "sleep 1\n" - "installer -pkg \"%s\" -target /\n" - "sleep 1\n" - "rm -f \"%s\" \"%s\"\n" - "exit 0\n", - pkgp, - pkgp, - bashp); - fclose(bash); - long pid = (long)vfork(); - if (pid == 0) { - setsid(); // detach from parent so that shell isn't killed when parent is killed - signal(SIGHUP,SIG_IGN); - signal(SIGTERM,SIG_IGN); - signal(SIGQUIT,SIG_IGN); - execl("/bin/bash","/bin/bash",bashp,(char *)0); - exit(0); - } - } -#endif // __APPLE__ - -#ifdef __WINDOWS__ - /* Windows version comes in the form of .MSI package that - * takes care of everything. */ - { - char tempp[512],batp[512],msip[512],cmdline[512]; - if (GetTempPathA(sizeof(tempp),tempp) <= 0) - return; - CreateDirectoryA(tempp,(LPSECURITY_ATTRIBUTES)0); - Utils::snprintf(batp,sizeof(batp),"%s\\ZeroTierOne-update-%u.%u.%u.bat",tempp,vMajor,vMinor,vRevision); - Utils::snprintf(msip,sizeof(msip),"%s\\ZeroTierOne-update-%u.%u.%u.msi",tempp,vMajor,vMinor,vRevision); - FILE *msi = fopen(msip,"wb"); - if ((!msi)||(fwrite(fileData.data(),(size_t)fileData.length(),1,msi) != 1)) { - fclose(msi); - return; - } - fclose(msi); - FILE *bat = fopen(batp,"wb"); - if (!bat) - return; - fprintf(bat, - "TIMEOUT.EXE /T 1 /NOBREAK\r\n" - "NET.EXE STOP \"ZeroTierOneService\"\r\n" - "TIMEOUT.EXE /T 1 /NOBREAK\r\n" - "MSIEXEC.EXE /i \"%s\" /qn\r\n" - "TIMEOUT.EXE /T 1 /NOBREAK\r\n" - "NET.EXE START \"ZeroTierOneService\"\r\n" - "DEL \"%s\"\r\n" - "DEL \"%s\"\r\n", - msip, - msip, - batp); - fclose(bat); - STARTUPINFOA si; - PROCESS_INFORMATION pi; - memset(&si,0,sizeof(si)); - memset(&pi,0,sizeof(pi)); - Utils::snprintf(cmdline,sizeof(cmdline),"CMD.EXE /c \"%s\"",batp); - CreateProcessA(NULL,cmdline,NULL,NULL,FALSE,CREATE_NO_WINDOW|CREATE_NEW_PROCESS_GROUP,NULL,NULL,&si,&pi); - } -#endif // __WINDOWS__ - - /* --------------------------------------------------------------- */ - - return; - } // else try to fetch from next IP address - } - } - - void threadMain() - throw() - { - try { - this->doUpdateCheck(); - } catch ( ... ) {} - } -}; -static BackgroundSoftwareUpdateChecker backgroundSoftwareUpdateChecker; -#endif // ZT_AUTO_UPDATE - -#endif - static std::string _trimString(const std::string &s) { unsigned long end = (unsigned long)s.length(); @@ -475,6 +263,7 @@ public: EmbeddedNetworkController *_controller; Phy _phy; Node *_node; + SoftwareUpdater *_updater; unsigned int _primaryPort; // Local configuration and memo-ized static path definitions @@ -577,6 +366,7 @@ public: ,_controller((EmbeddedNetworkController *)0) ,_phy(this,false,true) ,_node((Node *)0) + ,_updater((SoftwareUpdater *)0) ,_primaryPort(port) ,_controlPlane((ControlPlane *)0) ,_lastDirectReceiveFromGlobal(0) @@ -664,6 +454,8 @@ public: _node = new Node(this,&cb,OSUtils::now()); } + _updater = new SoftwareUpdater(*_node,_homePath); + // Read local configuration { uint64_t trustedPathIds[ZT_MAX_TRUSTED_PATHS]; @@ -904,6 +696,7 @@ public: uint64_t lastTapMulticastGroupCheck = 0; uint64_t lastTcpFallbackResolve = 0; uint64_t lastBindRefresh = 0; + uint64_t lastUpdateCheck = clockShouldBe; uint64_t lastLocalInterfaceAddressCheck = (OSUtils::now() - ZT_LOCAL_INTERFACE_CHECK_INTERVAL) + 15000; // do this in 15s to give portmapper time to configure and other things time to settle for(;;) { _run_m.lock(); @@ -926,6 +719,12 @@ public: restarted = true; } + // Check for updates (if enabled) + if ((_updater)&&((now - lastUpdateCheck) > 10000)) { + lastUpdateCheck = now; + _updater->check(now); + } + // Refresh bindings in case device's interfaces have changed, and also sync routes to update any shadow routes (e.g. shadow default) if (((now - lastBindRefresh) >= ZT_BINDER_REFRESH_PERIOD)||(restarted)) { lastBindRefresh = now; @@ -1018,6 +817,8 @@ public: delete _controlPlane; _controlPlane = (ControlPlane *)0; + delete _updater; + _updater = (SoftwareUpdater *)0; delete _node; _node = (Node *)0; diff --git a/service/SoftwareUpdater.cpp b/service/SoftwareUpdater.cpp index 072e89fc..0fc1ac70 100644 --- a/service/SoftwareUpdater.cpp +++ b/service/SoftwareUpdater.cpp @@ -42,42 +42,254 @@ namespace ZeroTier { -SoftwareUpdater::SoftwareUpdater(Node &node,const char *homePath,bool updateDistributor) : - _node(node), - _lastCheckTime(OSUtils::now()), // check in the future in case we just started, in which case we're probably offline - _homePath(homePath) +#if 0 +#ifdef ZT_AUTO_UPDATE +#define ZT_AUTO_UPDATE_MAX_HTTP_RESPONSE_SIZE (1024 * 1024 * 64) +#define ZT_AUTO_UPDATE_CHECK_PERIOD 21600000 +class BackgroundSoftwareUpdateChecker { - // Load all updates we are distributing if we are an update distributor and have an update-dist.d folder - if (updateDistributor) { - std::string udd(_homePath + ZT_PATH_SEPARATOR_S + "update-dist.d"); - std::vector ud(OSUtils::listDirectory(udd.c_str())); - for(std::vector::iterator u(ud.begin());u!=ud.end();++u) { - // Each update has a companion .json file describing it. Other files are ignored. - if ((u->length() > 5)&&(u->substr(u->length() - 5,5) == ".json")) { - std::string buf; - if (OSUtils::readFile((udd + ZT_PATH_SEPARATOR_S + *u).c_str(),buf)) { - try { - _D d; - d.meta = OSUtils::jsonParse(buf); - std::string metaHash = OSUtils::jsonBinFromHex(d.meta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH]); - if ((metaHash.length() == ZT_SHA512_DIGEST_LEN)&&(OSUtils::readFile((udd + ZT_PATH_SEPARATOR_S + u->substr(0,u->length() - 5)).c_str(),d.bin))) { - uint8_t sha512[ZT_SHA512_DIGEST_LEN]; - SHA512::hash(sha512,d.bin.data(),(unsigned int)d.bin.length()); - if (!memcmp(sha512,metaHash.data(),ZT_SHA512_DIGEST_LEN)) { // double check that hash in JSON is correct - _dist[Array(sha512)] = d; - } - } - } catch ( ... ) {} // ignore bad meta JSON, etc. - } +public: + bool isValidSigningIdentity(const Identity &id) + { + return ( + /* 0001 - 0004 : obsolete, used in old versions */ + /* 0005 */ (id == Identity("ba57ea350e:0:9d4be6d7f86c5660d5ee1951a3d759aa6e12a84fc0c0b74639500f1dbc1a8c566622e7d1c531967ebceb1e9d1761342f88324a8ba520c93c35f92f35080fa23f")) + /* 0006 */ ||(id == Identity("5067b21b83:0:8af477730f5055c48135b84bed6720a35bca4c0e34be4060a4c636288b1ec22217eb22709d610c66ed464c643130c51411bbb0294eef12fbe8ecc1a1e2c63a7a")) + /* 0007 */ ||(id == Identity("4f5e97a8f1:0:57880d056d7baeb04bbc057d6f16e6cb41388570e87f01492fce882485f65a798648595610a3ad49885604e7fb1db2dd3c2c534b75e42c3c0b110ad07b4bb138")) + /* 0008 */ ||(id == Identity("580bbb8e15:0:ad5ef31155bebc6bc413991992387e083fed26d699997ef76e7c947781edd47d1997161fa56ba337b1a2b44b129fd7c7197ce5185382f06011bc88d1363b4ddd")) + ); + } + + void doUpdateCheck() + { + std::string url(OneService::autoUpdateUrl()); + if ((url.length() <= 7)||(url.substr(0,7) != "http://")) + return; + + std::string httpHost; + std::string httpPath; + { + std::size_t slashIdx = url.substr(7).find_first_of('/'); + if (slashIdx == std::string::npos) { + httpHost = url.substr(7); + httpPath = "/"; + } else { + httpHost = url.substr(7,slashIdx); + httpPath = url.substr(slashIdx + 7); } } + if (httpHost.length() == 0) + return; + + std::vector ips(OSUtils::resolve(httpHost.c_str())); + for(std::vector::iterator ip(ips.begin());ip!=ips.end();++ip) { + if (!ip->port()) + ip->setPort(80); + std::string nfoPath = httpPath + "LATEST.nfo"; + std::map requestHeaders,responseHeaders; + std::string body; + requestHeaders["Host"] = httpHost; + unsigned int scode = Http::GET(ZT_AUTO_UPDATE_MAX_HTTP_RESPONSE_SIZE,60000,reinterpret_cast(&(*ip)),nfoPath.c_str(),requestHeaders,responseHeaders,body); + //fprintf(stderr,"UPDATE %s %s %u %lu\n",ip->toString().c_str(),nfoPath.c_str(),scode,body.length()); + if ((scode == 200)&&(body.length() > 0)) { + /* NFO fields: + * + * file= + * signedBy= + * ed25519= + * vMajor= + * vMinor= + * vRevision= */ + Dictionary<4096> nfo(body.c_str()); + char tmp[2048]; + + if (nfo.get("vMajor",tmp,sizeof(tmp)) <= 0) return; + const unsigned int vMajor = Utils::strToUInt(tmp); + if (nfo.get("vMinor",tmp,sizeof(tmp)) <= 0) return; + const unsigned int vMinor = Utils::strToUInt(tmp); + if (nfo.get("vRevision",tmp,sizeof(tmp)) <= 0) return; + const unsigned int vRevision = Utils::strToUInt(tmp); + if (Utils::compareVersion(vMajor,vMinor,vRevision,ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION) <= 0) { + //fprintf(stderr,"UPDATE %u.%u.%u is not newer than our version\n",vMajor,vMinor,vRevision); + return; + } + + if (nfo.get("signedBy",tmp,sizeof(tmp)) <= 0) return; + Identity signedBy; + if ((!signedBy.fromString(tmp))||(!isValidSigningIdentity(signedBy))) { + //fprintf(stderr,"UPDATE invalid signedBy or not authorized signing identity.\n"); + return; + } + + if (nfo.get("file",tmp,sizeof(tmp)) <= 0) return; + std::string filePath(tmp); + if ((!filePath.length())||(filePath.find("..") != std::string::npos)) + return; + filePath = httpPath + filePath; + + std::string fileData; + if (Http::GET(ZT_AUTO_UPDATE_MAX_HTTP_RESPONSE_SIZE,60000,reinterpret_cast(&(*ip)),filePath.c_str(),requestHeaders,responseHeaders,fileData) != 200) { + //fprintf(stderr,"UPDATE GET %s failed\n",filePath.c_str()); + return; + } + + if (nfo.get("ed25519",tmp,sizeof(tmp)) <= 0) return; + std::string ed25519(Utils::unhex(tmp)); + if ((ed25519.length() == 0)||(!signedBy.verify(fileData.data(),(unsigned int)fileData.length(),ed25519.data(),(unsigned int)ed25519.length()))) { + //fprintf(stderr,"UPDATE %s failed signature check!\n",filePath.c_str()); + return; + } + + /* --------------------------------------------------------------- */ + /* We made it! Begin OS-specific installation code. */ + +#ifdef __APPLE__ + /* OSX version is in the form of a MacOSX .pkg file, so we will + * launch installer (normally in /usr/sbin) to install it. It will + * then turn around and shut down the service, update files, and + * relaunch. */ + { + char bashp[128],pkgp[128]; + Utils::snprintf(bashp,sizeof(bashp),"/tmp/ZeroTierOne-update-%u.%u.%u.sh",vMajor,vMinor,vRevision); + Utils::snprintf(pkgp,sizeof(pkgp),"/tmp/ZeroTierOne-update-%u.%u.%u.pkg",vMajor,vMinor,vRevision); + FILE *pkg = fopen(pkgp,"w"); + if ((!pkg)||(fwrite(fileData.data(),fileData.length(),1,pkg) != 1)) { + fclose(pkg); + unlink(bashp); + unlink(pkgp); + fprintf(stderr,"UPDATE error writing %s\n",pkgp); + return; + } + fclose(pkg); + FILE *bash = fopen(bashp,"w"); + if (!bash) { + fclose(pkg); + unlink(bashp); + unlink(pkgp); + fprintf(stderr,"UPDATE error writing %s\n",bashp); + return; + } + fprintf(bash, + "#!/bin/bash\n" + "export PATH=/bin:/usr/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/sbin\n" + "sleep 1\n" + "installer -pkg \"%s\" -target /\n" + "sleep 1\n" + "rm -f \"%s\" \"%s\"\n" + "exit 0\n", + pkgp, + pkgp, + bashp); + fclose(bash); + long pid = (long)vfork(); + if (pid == 0) { + setsid(); // detach from parent so that shell isn't killed when parent is killed + signal(SIGHUP,SIG_IGN); + signal(SIGTERM,SIG_IGN); + signal(SIGQUIT,SIG_IGN); + execl("/bin/bash","/bin/bash",bashp,(char *)0); + exit(0); + } + } +#endif // __APPLE__ + +#ifdef __WINDOWS__ + /* Windows version comes in the form of .MSI package that + * takes care of everything. */ + { + char tempp[512],batp[512],msip[512],cmdline[512]; + if (GetTempPathA(sizeof(tempp),tempp) <= 0) + return; + CreateDirectoryA(tempp,(LPSECURITY_ATTRIBUTES)0); + Utils::snprintf(batp,sizeof(batp),"%s\\ZeroTierOne-update-%u.%u.%u.bat",tempp,vMajor,vMinor,vRevision); + Utils::snprintf(msip,sizeof(msip),"%s\\ZeroTierOne-update-%u.%u.%u.msi",tempp,vMajor,vMinor,vRevision); + FILE *msi = fopen(msip,"wb"); + if ((!msi)||(fwrite(fileData.data(),(size_t)fileData.length(),1,msi) != 1)) { + fclose(msi); + return; + } + fclose(msi); + FILE *bat = fopen(batp,"wb"); + if (!bat) + return; + fprintf(bat, + "TIMEOUT.EXE /T 1 /NOBREAK\r\n" + "NET.EXE STOP \"ZeroTierOneService\"\r\n" + "TIMEOUT.EXE /T 1 /NOBREAK\r\n" + "MSIEXEC.EXE /i \"%s\" /qn\r\n" + "TIMEOUT.EXE /T 1 /NOBREAK\r\n" + "NET.EXE START \"ZeroTierOneService\"\r\n" + "DEL \"%s\"\r\n" + "DEL \"%s\"\r\n", + msip, + msip, + batp); + fclose(bat); + STARTUPINFOA si; + PROCESS_INFORMATION pi; + memset(&si,0,sizeof(si)); + memset(&pi,0,sizeof(pi)); + Utils::snprintf(cmdline,sizeof(cmdline),"CMD.EXE /c \"%s\"",batp); + CreateProcessA(NULL,cmdline,NULL,NULL,FALSE,CREATE_NO_WINDOW|CREATE_NEW_PROCESS_GROUP,NULL,NULL,&si,&pi); + } +#endif // __WINDOWS__ + + /* --------------------------------------------------------------- */ + + return; + } // else try to fetch from next IP address + } + } + + void threadMain() + throw() + { + try { + this->doUpdateCheck(); + } catch ( ... ) {} } +}; +static BackgroundSoftwareUpdateChecker backgroundSoftwareUpdateChecker; +#endif // ZT_AUTO_UPDATE +#endif + +SoftwareUpdater::SoftwareUpdater(Node &node,const std::string &homePath) : + _node(node), + _lastCheckTime(0), + _homePath(homePath) +{ } SoftwareUpdater::~SoftwareUpdater() { } +void SoftwareUpdater::loadUpdatesToDistribute() +{ + std::string udd(_homePath + ZT_PATH_SEPARATOR_S + "update-dist.d"); + std::vector ud(OSUtils::listDirectory(udd.c_str())); + for(std::vector::iterator u(ud.begin());u!=ud.end();++u) { + // Each update has a companion .json file describing it. Other files are ignored. + if ((u->length() > 5)&&(u->substr(u->length() - 5,5) == ".json")) { + std::string buf; + if (OSUtils::readFile((udd + ZT_PATH_SEPARATOR_S + *u).c_str(),buf)) { + try { + _D d; + d.meta = OSUtils::jsonParse(buf); + std::string metaHash = OSUtils::jsonBinFromHex(d.meta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH]); + if ((metaHash.length() == ZT_SHA512_DIGEST_LEN)&&(OSUtils::readFile((udd + ZT_PATH_SEPARATOR_S + u->substr(0,u->length() - 5)).c_str(),d.bin))) { + uint8_t sha512[ZT_SHA512_DIGEST_LEN]; + SHA512::hash(sha512,d.bin.data(),(unsigned int)d.bin.length()); + if (!memcmp(sha512,metaHash.data(),ZT_SHA512_DIGEST_LEN)) { // double check that hash in JSON is correct + _dist[Array(sha512)] = d; + } + } + } catch ( ... ) {} // ignore bad meta JSON, etc. + } + } + } +} + void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void *data,unsigned int len) { if (!len) return; @@ -197,7 +409,7 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void } } -nlohmann::json SoftwareUpdater::check() +nlohmann::json SoftwareUpdater::check(const uint64_t now) { if (_latestBinLength > 0) { if (_latestBin.length() >= _latestBinLength) { @@ -236,7 +448,6 @@ nlohmann::json SoftwareUpdater::check() } } - const uint64_t now = OSUtils::now(); if ((now - _lastCheckTime) >= ZT_SOFTWARE_UPDATE_CHECK_PERIOD) { _lastCheckTime = now; char tmp[512]; diff --git a/service/SoftwareUpdater.hpp b/service/SoftwareUpdater.hpp index 7ef08f6d..284d7f6a 100644 --- a/service/SoftwareUpdater.hpp +++ b/service/SoftwareUpdater.hpp @@ -34,17 +34,17 @@ /** * VERB_USER_MESSAGE type ID for software update messages */ -#define ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE 1000 +#define ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE 100 /** * ZeroTier address of node that provides software updates */ -#define ZT_SOFTWARE_UPDATE_SERVICE 0xc1243d3869ULL +#define ZT_SOFTWARE_UPDATE_SERVICE 0xb1d366e81fULL /** * ZeroTier identity that must be used to sign software updates */ -#define ZT_SOFTWARE_UPDATE_SIGNING_AUTHORITY "" +#define ZT_SOFTWARE_UPDATE_SIGNING_AUTHORITY "a60ed7a9eb:0:740fd482e02eabd28f69c83ad4353d44c9514627bc0656b5d194e2f34715745b62297120d47d7f0c728424c33297ea499dea4ce006ee3d7c0d802a6fb199d909" /** * Chunk size for in-band downloads (can be changed, designed to always fit in one UDP packet easily) @@ -117,9 +117,14 @@ public: VERB_DATA = 4 }; - SoftwareUpdater(Node &node,const char *homePath,bool updateDistributor); + SoftwareUpdater(Node &node,const std::string &homePath); ~SoftwareUpdater(); + /** + * Load update-dist.d if it exists + */ + void loadUpdatesToDistribute(); + /** * Handle a software update user message * @@ -136,7 +141,7 @@ public: * * @return Null JSON object or update information if there is an update downloaded and ready */ - nlohmann::json check(); + nlohmann::json check(const uint64_t now); /** * Apply any ready update now -- cgit v1.2.3 From 4aa52ffc771e43a8bce96b3f23e1f821ecd684ae Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 11 Jan 2017 16:47:42 -0800 Subject: Software update stuff. --- service/OneService.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 0c1279ca..64850d09 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -697,7 +697,7 @@ public: uint64_t lastTcpFallbackResolve = 0; uint64_t lastBindRefresh = 0; uint64_t lastUpdateCheck = clockShouldBe; - uint64_t lastLocalInterfaceAddressCheck = (OSUtils::now() - ZT_LOCAL_INTERFACE_CHECK_INTERVAL) + 15000; // do this in 15s to give portmapper time to configure and other things time to settle + uint64_t lastLocalInterfaceAddressCheck = (clockShouldBe - ZT_LOCAL_INTERFACE_CHECK_INTERVAL) + 15000; // do this in 15s to give portmapper time to configure and other things time to settle for(;;) { _run_m.lock(); if (!_run) { -- cgit v1.2.3 From d301540d92e924afc548599a559451c103e10e1c Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 11 Jan 2017 16:58:37 -0800 Subject: Software update stuff for test. --- service/OneService.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 64850d09..2ff02254 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -455,6 +455,7 @@ public: } _updater = new SoftwareUpdater(*_node,_homePath); + _updater->loadUpdatesToDistribute(); // Read local configuration { -- cgit v1.2.3 From d4321cdd41c74d3aa51e5224a0b3b7782da28ce6 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 11 Jan 2017 17:20:43 -0800 Subject: Wire up user message handling in OneService event handler. --- service/OneService.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 2ff02254..9ee05f96 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1477,6 +1477,13 @@ public: } } break; + case ZT_EVENT_USER_MESSAGE: { + const ZT_UserMessage *um = reinterpret_cast(metaData); + if ((um->typeId == ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE)&&(_updater)) { + _updater->handleSoftwareUpdateUserMessage(um->origin,um->data,um->length); + } + } break; + default: break; } -- cgit v1.2.3 From c6b0b076055f0b9b579c21bbbe83171a554a2600 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 12 Jan 2017 13:18:11 -0800 Subject: More software update work, and settings in local.conf. --- make-freebsd.mk | 40 +++++++++++++++--------- make-linux.mk | 64 +++++++++++---------------------------- make-mac.mk | 41 ++++++++++--------------- service/OneService.cpp | 19 ++++++++++-- service/SoftwareUpdater.cpp | 74 ++++++++++++++++++++++++--------------------- service/SoftwareUpdater.hpp | 33 ++++++++++++++++---- 6 files changed, 142 insertions(+), 129 deletions(-) (limited to 'service/OneService.cpp') diff --git a/make-freebsd.mk b/make-freebsd.mk index cb9a2e6d..7de85c8c 100644 --- a/make-freebsd.mk +++ b/make-freebsd.mk @@ -1,6 +1,5 @@ CC=cc CXX=c++ - INCLUDES= DEFS= LIBS= @@ -8,11 +7,6 @@ LIBS= include objects.mk OBJS+=osdep/BSDEthernetTap.o ext/lz4/lz4.o ext/http-parser/http_parser.o -# "make official" is a shortcut for this -ifeq ($(ZT_OFFICIAL_RELEASE),1) - DEFS+=-DZT_OFFICIAL_RELEASE -endif - # Build with ZT_ENABLE_CLUSTER=1 to build with cluster support ifeq ($(ZT_ENABLE_CLUSTER),1) DEFS+=-DZT_ENABLE_CLUSTER @@ -34,6 +28,32 @@ else STRIP=strip --strip-all endif +# Determine system build architecture from compiler target +CC_MACH=$(shell $(CC) -dumpmachine | cut -d '-' -f 1) +ZT_ARCHITECTURE=0 +ifeq ($(CC_MACH),x86_64) + ZT_ARCHITECTURE=2 +endif +ifeq ($(CC_MACH),amd64) + ZT_ARCHITECTURE=2 +endif +ifeq ($(CC_MACH),i386) + ZT_ARCHITECTURE=1 +endif +ifeq ($(CC_MACH),i686) + ZT_ARCHITECTURE=1 +endif +ifeq ($(CC_MACH),arm) + ZT_ARCHITECTURE=3 +endif +ifeq ($(CC_MACH),arm64) + ZT_ARCHITECTURE=4 +endif +ifeq ($(CC_MACH),aarch64) + ZT_ARCHITECTURE=4 +endif +DEFS+=-DZT_BUILD_PLATFORM=7 -DZT_BUILD_ARCHITECTURE=$(ZT_ARCHITECTURE) -DZT_SOFTWARE_UPDATE_DEFAULT="disable" + CXXFLAGS+=$(CFLAGS) -fno-rtti all: one @@ -48,18 +68,10 @@ selftest: $(OBJS) selftest.o $(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-selftest selftest.o $(OBJS) $(LIBS) $(STRIP) zerotier-selftest -# No installer on FreeBSD yet -#installer: one FORCE -# ./buildinstaller.sh - clean: rm -rf *.o node/*.o controller/*.o osdep/*.o service/*.o ext/http-parser/*.o ext/lz4/*.o ext/json-parser/*.o build-* zerotier-one zerotier-idtool zerotier-selftest zerotier-cli ZeroTierOneInstaller-* debug: FORCE make -j 4 ZT_DEBUG=1 -#official: FORCE -# make -j 4 ZT_OFFICIAL_RELEASE=1 -# ./buildinstaller.sh - FORCE: diff --git a/make-linux.mk b/make-linux.mk index 90644e3d..cb91ab88 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -1,24 +1,3 @@ -# -# Makefile for ZeroTier One on Linux -# -# This is confirmed to work on distributions newer than CentOS 6 (the -# one used for reference builds) and on 32 and 64 bit x86 and ARM -# machines. It should also work on other 'normal' machines and recent -# distributions. Editing might be required for tiny devices or weird -# distros. -# -# Targets -# one: zerotier-one and symlinks (cli and idtool) -# manpages: builds manpages, requires 'ronn' or nodeJS (will use either) -# all: builds 'one' and 'manpages' -# selftest: zerotier-selftest -# debug: builds 'one' and 'selftest' with tracing and debug flags -# clean: removes all built files, objects, other trash -# distclean: removes a few other things that might be present -# debian: build DEB packages; deb dev tools must be present -# redhat: build RPM packages; rpm dev tools must be present -# - # 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) @@ -28,8 +7,6 @@ ifeq ($(origin CXX),default) CXX=$(shell if [ -e /usr/bin/clang++ ]; then echo clang++; else echo g++; fi) endif -#UNAME_M=$(shell $(CC) -dumpmachine | cut -d '-' -f 1) - INCLUDES?= DEFS?=-D_FORTIFY_SOURCE=2 LDLIBS?= @@ -52,28 +29,23 @@ else DEFS+=-DZT_USE_SYSTEM_HTTP_PARSER endif -ifeq ($(ZT_USE_MINIUPNPC),1) - OBJS+=osdep/PortMapper.o - - DEFS+=-DZT_USE_MINIUPNPC - - # Auto-detect libminiupnpc at least v2.0 - MINIUPNPC_IS_NEW_ENOUGH=$(shell grep -sqr '.*define.*MINIUPNPC_VERSION.*"2.."' /usr/include/miniupnpc/miniupnpc.h && echo 1) - ifeq ($(MINIUPNPC_IS_NEW_ENOUGH),1) - DEFS+=-DZT_USE_SYSTEM_MINIUPNPC - LDLIBS+=-lminiupnpc - else - DEFS+=-DMINIUPNP_STATICLIB -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -DOS_STRING=\"Linux\" -DMINIUPNPC_VERSION_STRING=\"2.0\" -DUPNP_VERSION_STRING=\"UPnP/1.1\" -DENABLE_STRNATPMPERR - OBJS+=ext/miniupnpc/connecthostport.o ext/miniupnpc/igd_desc_parse.o ext/miniupnpc/minisoap.o ext/miniupnpc/minissdpc.o ext/miniupnpc/miniupnpc.o ext/miniupnpc/miniwget.o ext/miniupnpc/minixml.o ext/miniupnpc/portlistingparse.o ext/miniupnpc/receivedata.o ext/miniupnpc/upnpcommands.o ext/miniupnpc/upnpdev.o ext/miniupnpc/upnperrors.o ext/miniupnpc/upnpreplyparse.o - endif - - # Auto-detect libnatpmp - ifeq ($(wildcard /usr/include/natpmp.h),) - OBJS+=ext/libnatpmp/natpmp.o ext/libnatpmp/getgateway.o - else - LDLIBS+=-lnatpmp - DEFS+=-DZT_USE_SYSTEM_NATPMP - endif +# Auto-detect miniupnpc and nat-pmp as well and use system libs if present, +# otherwise build into binary as done on Mac and Windows. +OBJS+=osdep/PortMapper.o +DEFS+=-DZT_USE_MINIUPNPC +MINIUPNPC_IS_NEW_ENOUGH=$(shell grep -sqr '.*define.*MINIUPNPC_VERSION.*"2.."' /usr/include/miniupnpc/miniupnpc.h && echo 1) +ifeq ($(MINIUPNPC_IS_NEW_ENOUGH),1) + DEFS+=-DZT_USE_SYSTEM_MINIUPNPC + LDLIBS+=-lminiupnpc +else + DEFS+=-DMINIUPNP_STATICLIB -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -DOS_STRING=\"Linux\" -DMINIUPNPC_VERSION_STRING=\"2.0\" -DUPNP_VERSION_STRING=\"UPnP/1.1\" -DENABLE_STRNATPMPERR + OBJS+=ext/miniupnpc/connecthostport.o ext/miniupnpc/igd_desc_parse.o ext/miniupnpc/minisoap.o ext/miniupnpc/minissdpc.o ext/miniupnpc/miniupnpc.o ext/miniupnpc/miniwget.o ext/miniupnpc/minixml.o ext/miniupnpc/portlistingparse.o ext/miniupnpc/receivedata.o ext/miniupnpc/upnpcommands.o ext/miniupnpc/upnpdev.o ext/miniupnpc/upnperrors.o ext/miniupnpc/upnpreplyparse.o +endif +ifeq ($(wildcard /usr/include/natpmp.h),) + OBJS+=ext/libnatpmp/natpmp.o ext/libnatpmp/getgateway.o +else + LDLIBS+=-lnatpmp + DEFS+=-DZT_USE_SYSTEM_NATPMP endif ifeq ($(ZT_ENABLE_CLUSTER),1) @@ -137,7 +109,7 @@ endif ifeq ($(CC_MACH),aarch64) ZT_ARCHITECTURE=4 endif -DEFS+=-DZT_BUILD_PLATFORM=1 -DZT_BUILD_ARCHITECTURE=$(ZT_ARCHITECTURE) +DEFS+=-DZT_BUILD_PLATFORM=1 -DZT_BUILD_ARCHITECTURE=$(ZT_ARCHITECTURE) -DZT_SOFTWARE_UPDATE_DEFAULT="\"disable\"" all: one diff --git a/make-mac.mk b/make-mac.mk index e9de6f49..99a9d738 100644 --- a/make-mac.mk +++ b/make-mac.mk @@ -1,45 +1,39 @@ -ifeq ($(origin CC),default) - CC=$(shell if [ -e /usr/bin/clang ]; then echo clang; else echo gcc; fi) -endif -ifeq ($(origin CXX),default) - CXX=$(shell if [ -e /usr/bin/clang++ ]; then echo clang++; else echo g++; fi) -endif - +CC=clang +CXX=clang++ INCLUDES= DEFS= LIBS= -ARCH_FLAGS=-arch x86_64 - -include objects.mk -OBJS+=osdep/OSXEthernetTap.o ext/lz4/lz4.o ext/http-parser/http_parser.o - -# Disable codesign since open source users will not have ZeroTier's certs +ARCH_FLAGS= CODESIGN=echo PRODUCTSIGN=echo CODESIGN_APP_CERT= CODESIGN_INSTALLER_CERT= -# Build with libminiupnpc by default for Mac -- desktops/laptops almost always want this -ZT_USE_MINIUPNPC?=1 +# 3 == MacOS, 2 == X64 (the only arch for MacOS right now) +DEFS+=-DZT_BUILD_PLATFORM=3 -DZT_BUILD_ARCHITECTURE=2 -# For internal use only -- signs everything with ZeroTier's developer cert +include objects.mk +OBJS+=osdep/OSXEthernetTap.o ext/lz4/lz4.o ext/http-parser/http_parser.o + +# Official releases are signed with our Apple cert and apply software updates by default ifeq ($(ZT_OFFICIAL_RELEASE),1) - DEFS+=-DZT_OFFICIAL_RELEASE + DEFS+=-DZT_SOFTWARE_UPDATE_DEFAULT="apply" ZT_USE_MINIUPNPC=1 CODESIGN=codesign PRODUCTSIGN=productsign CODESIGN_APP_CERT="Developer ID Application: ZeroTier, Inc (8ZD9JUCZ4V)" CODESIGN_INSTALLER_CERT="Developer ID Installer: ZeroTier, Inc (8ZD9JUCZ4V)" +else + DEFS+=-DZT_SOFTWARE_UPDATE_DEFAULT="download" endif ifeq ($(ZT_ENABLE_CLUSTER),1) DEFS+=-DZT_ENABLE_CLUSTER endif -ifeq ($(ZT_USE_MINIUPNPC),1) - DEFS+=-DMACOSX -DZT_USE_MINIUPNPC -DMINIUPNP_STATICLIB -D_DARWIN_C_SOURCE -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -D_BSD_SOURCE -D_DEFAULT_SOURCE -DOS_STRING=\"Darwin/15.0.0\" -DMINIUPNPC_VERSION_STRING=\"2.0\" -DUPNP_VERSION_STRING=\"UPnP/1.1\" -DENABLE_STRNATPMPERR - OBJS+=ext/libnatpmp/natpmp.o ext/libnatpmp/getgateway.o ext/miniupnpc/connecthostport.o ext/miniupnpc/igd_desc_parse.o ext/miniupnpc/minisoap.o ext/miniupnpc/minissdpc.o ext/miniupnpc/miniupnpc.o ext/miniupnpc/miniwget.o ext/miniupnpc/minixml.o ext/miniupnpc/portlistingparse.o ext/miniupnpc/receivedata.o ext/miniupnpc/upnpcommands.o ext/miniupnpc/upnpdev.o ext/miniupnpc/upnperrors.o ext/miniupnpc/upnpreplyparse.o osdep/PortMapper.o -endif +# Build miniupnpc and nat-pmp as included libraries -- extra defs are required for these sources +DEFS+=-DMACOSX -DZT_USE_MINIUPNPC -DMINIUPNP_STATICLIB -D_DARWIN_C_SOURCE -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -D_BSD_SOURCE -D_DEFAULT_SOURCE -DOS_STRING=\"Darwin/15.0.0\" -DMINIUPNPC_VERSION_STRING=\"2.0\" -DUPNP_VERSION_STRING=\"UPnP/1.1\" -DENABLE_STRNATPMPERR +OBJS+=ext/libnatpmp/natpmp.o ext/libnatpmp/getgateway.o ext/miniupnpc/connecthostport.o ext/miniupnpc/igd_desc_parse.o ext/miniupnpc/minisoap.o ext/miniupnpc/minissdpc.o ext/miniupnpc/miniupnpc.o ext/miniupnpc/miniwget.o ext/miniupnpc/minixml.o ext/miniupnpc/portlistingparse.o ext/miniupnpc/receivedata.o ext/miniupnpc/upnpcommands.o ext/miniupnpc/upnpdev.o ext/miniupnpc/upnperrors.o ext/miniupnpc/upnpreplyparse.o osdep/PortMapper.o # Debug mode -- dump trace output, build binary with -g ifeq ($(ZT_DEBUG),1) @@ -55,10 +49,7 @@ else STRIP=strip endif -CXXFLAGS=$(CFLAGS) -mmacosx-version-min=10.7 -std=c++11 -stdlib=libc++ - -# 3 == MacOS, 2 == X64 -DEFS+=-DZT_BUILD_PLATFORM=3 -DZT_BUILD_ARCHITECTURE=2 +CXXFLAGS=$(CFLAGS) -std=c++11 -stdlib=libc++ all: one macui diff --git a/service/OneService.cpp b/service/OneService.cpp index 9ee05f96..697be24a 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -264,6 +264,7 @@ public: Phy _phy; Node *_node; SoftwareUpdater *_updater; + bool _updateAutoApply; unsigned int _primaryPort; // Local configuration and memo-ized static path definitions @@ -367,6 +368,7 @@ public: ,_phy(this,false,true) ,_node((Node *)0) ,_updater((SoftwareUpdater *)0) + ,_updateAutoApply(false) ,_primaryPort(port) ,_controlPlane((ControlPlane *)0) ,_lastDirectReceiveFromGlobal(0) @@ -454,9 +456,6 @@ public: _node = new Node(this,&cb,OSUtils::now()); } - _updater = new SoftwareUpdater(*_node,_homePath); - _updater->loadUpdatesToDistribute(); - // Read local configuration { uint64_t trustedPathIds[ZT_MAX_TRUSTED_PATHS]; @@ -982,6 +981,20 @@ public: _node->setRelayPolicy(ZT_RELAY_POLICY_NEVER); else _node->setRelayPolicy(ZT_RELAY_POLICY_TRUSTED); + const std::string up(OSUtils::jsonString(settings["softwareUpdate"],ZT_SOFTWARE_UPDATE_DEFAULT)); + const bool udist = OSUtils::jsonBool(settings["softwareUpdateDist"],false); + if (((up == "apply")||(up == "download"))||(udist)) { + if (!_updater) + _updater = new SoftwareUpdater(*_node,_homePath); + _updateAutoApply = (up == "apply"); + _updater->setUpdateDistribution(udist); + _updater->setChannel(OSUtils::jsonString(settings["softwareUpdateChannel"],ZT_SOFTWARE_UPDATE_DEFAULT_CHANNEL)); + } else { + delete _updater; + _updater = (SoftwareUpdater *)0; + _updateAutoApply = false; + } + json &ignoreIfs = settings["interfacePrefixBlacklist"]; if (ignoreIfs.is_array()) { for(unsigned long i=0;i ud(OSUtils::listDirectory(udd.c_str())); - for(std::vector::iterator u(ud.begin());u!=ud.end();++u) { - // Each update has a companion .json file describing it. Other files are ignored. - if ((u->length() > 5)&&(u->substr(u->length() - 5,5) == ".json")) { - std::string buf; - if (OSUtils::readFile((udd + ZT_PATH_SEPARATOR_S + *u).c_str(),buf)) { - try { - _D d; - d.meta = OSUtils::jsonParse(buf); - std::string metaHash = OSUtils::jsonBinFromHex(d.meta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH]); - if ((metaHash.length() == ZT_SHA512_DIGEST_LEN)&&(OSUtils::readFile((udd + ZT_PATH_SEPARATOR_S + u->substr(0,u->length() - 5)).c_str(),d.bin))) { - uint8_t sha512[ZT_SHA512_DIGEST_LEN]; - SHA512::hash(sha512,d.bin.data(),(unsigned int)d.bin.length()); - if (!memcmp(sha512,metaHash.data(),ZT_SHA512_DIGEST_LEN)) { // double check that hash in JSON is correct - _dist[Array(sha512)] = d; - printf("update-dist.d: %s\n",u->c_str()); + _dist.clear(); + if (distribute) { + std::string udd(_homePath + ZT_PATH_SEPARATOR_S + "update-dist.d"); + std::vector ud(OSUtils::listDirectory(udd.c_str())); + for(std::vector::iterator u(ud.begin());u!=ud.end();++u) { + // Each update has a companion .json file describing it. Other files are ignored. + if ((u->length() > 5)&&(u->substr(u->length() - 5,5) == ".json")) { + std::string buf; + if (OSUtils::readFile((udd + ZT_PATH_SEPARATOR_S + *u).c_str(),buf)) { + try { + _D d; + d.meta = OSUtils::jsonParse(buf); + std::string metaHash = OSUtils::jsonBinFromHex(d.meta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH]); + if ((metaHash.length() == ZT_SHA512_DIGEST_LEN)&&(OSUtils::readFile((udd + ZT_PATH_SEPARATOR_S + u->substr(0,u->length() - 5)).c_str(),d.bin))) { + uint8_t sha512[ZT_SHA512_DIGEST_LEN]; + SHA512::hash(sha512,d.bin.data(),(unsigned int)d.bin.length()); + if (!memcmp(sha512,metaHash.data(),ZT_SHA512_DIGEST_LEN)) { // double check that hash in JSON is correct + _dist[Array(sha512)] = d; + printf("update-dist.d: %s\n",u->c_str()); + } } - } - } catch ( ... ) {} // ignore bad meta JSON, etc. + } catch ( ... ) {} // ignore bad meta JSON, etc. + } } } } @@ -393,18 +397,17 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void idx |= (unsigned long)*(reinterpret_cast(data) + 18) << 16; idx |= (unsigned long)*(reinterpret_cast(data) + 19) << 8; idx |= (unsigned long)*(reinterpret_cast(data) + 20); + printf("<< DATA @%u / %u bytes (we now have %u bytes)\n",(unsigned int)idx,(unsigned int)(len - 21),(unsigned int)_latestBin.length()); if (idx == _latestBin.length()) { _latestBin.append(reinterpret_cast(data) + 21,len - 21); - } - printf("<< DATA @%u / %u bytes (we now have %u bytes)\n",(unsigned int)idx,(unsigned int)(len - 21),(unsigned int)_latestBin.length()); - - if (_latestBin.length() < _latestBinLength) { - Buffer<128> gd; - gd.append((uint8_t)VERB_GET_DATA); - gd.append(_latestBinHashPrefix.data,16); - gd.append((uint32_t)_latestBin.length()); - _node.sendUserMessage(ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,gd.data(),gd.size()); - printf(">> GET_DATA @%u\n",(unsigned int)_latestBin.length()); + if (_latestBin.length() < _latestBinLength) { + Buffer<128> gd; + gd.append((uint8_t)VERB_GET_DATA); + gd.append(_latestBinHashPrefix.data,16); + gd.append((uint32_t)_latestBin.length()); + _node.sendUserMessage(ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,gd.data(),gd.size()); + printf(">> GET_DATA @%u\n",(unsigned int)_latestBin.length()); + } } } break; @@ -417,7 +420,7 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void } } -nlohmann::json SoftwareUpdater::check(const uint64_t now) +bool SoftwareUpdater::check(const uint64_t now) { if ((now - _lastCheckTime) >= ZT_SOFTWARE_UPDATE_CHECK_PERIOD) { _lastCheckTime = now; @@ -439,7 +442,7 @@ nlohmann::json SoftwareUpdater::check(const uint64_t now) ZT_BUILD_PLATFORM, ZT_BUILD_ARCHITECTURE, (int)ZT_VENDOR_ZEROTIER, - "release"); + _channel.c_str()); _node.sendUserMessage(ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,tmp,len); printf(">> GET_LATEST\n"); } @@ -449,13 +452,14 @@ nlohmann::json SoftwareUpdater::check(const uint64_t now) if (_latestBinValid) { return _latestMeta; } else { - // This is the important security verification part! + // This is the very important security validation part that makes sure + // this software update doesn't have cooties. try { // (1) Check the hash itself to make sure the image is basically okay uint8_t sha512[ZT_SHA512_DIGEST_LEN]; SHA512::hash(sha512,_latestBin.data(),(unsigned int)_latestBin.length()); - if (Utils::hex(sha512,ZT_SHA512_DIGEST_LEN) == OSUtils::jsonString(_latestMeta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH],"")) { + if (Utils::hex(sha512,ZT_SHA512_DIGEST_LEN) == OSUtils::jsonString(_latestMeta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH],"~")) { // (2) Check signature by signing authority std::string sig(OSUtils::jsonBinFromHex(_latestMeta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIGNATURE])); if (Identity(ZT_SOFTWARE_UPDATE_SIGNING_AUTHORITY).verify(_latestBin.data(),(unsigned int)_latestBin.length(),sig.data(),(unsigned int)sig.length())) { @@ -489,7 +493,7 @@ nlohmann::json SoftwareUpdater::check(const uint64_t now) void SoftwareUpdater::apply() { - if ((_latestBin.length() == _latestBinLength)&&(_latestBinLength > 0)&&(_latestBinValid)) { + if ((_latestBin.length() > 0)&&(_latestBinValid)) { } } diff --git a/service/SoftwareUpdater.hpp b/service/SoftwareUpdater.hpp index 0501ff23..b9cabf23 100644 --- a/service/SoftwareUpdater.hpp +++ b/service/SoftwareUpdater.hpp @@ -64,19 +64,25 @@ //#define ZT_SOFTWARE_UPDATE_CHECK_PERIOD (60 * 60 * 1000) #define ZT_SOFTWARE_UPDATE_CHECK_PERIOD 5000 +/** + * Default update channel + */ +#define ZT_SOFTWARE_UPDATE_DEFAULT_CHANNEL "release" + #define ZT_SOFTWARE_UPDATE_JSON_VERSION_MAJOR "versionMajor" #define ZT_SOFTWARE_UPDATE_JSON_VERSION_MINOR "versionMinor" #define ZT_SOFTWARE_UPDATE_JSON_VERSION_REVISION "versionRev" -#define ZT_SOFTWARE_UPDATE_JSON_EXPECT_SIGNED_BY "expectedSigner" #define ZT_SOFTWARE_UPDATE_JSON_PLATFORM "platform" #define ZT_SOFTWARE_UPDATE_JSON_ARCHITECTURE "arch" #define ZT_SOFTWARE_UPDATE_JSON_VENDOR "vendor" #define ZT_SOFTWARE_UPDATE_JSON_CHANNEL "channel" +#define ZT_SOFTWARE_UPDATE_JSON_EXPECT_SIGNED_BY "expectedSigner" #define ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIGNED_BY "updateSigner" #define ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIGNATURE "updateSig" #define ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH "updateHash" #define ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIZE "updateSize" -#define ZT_SOFTWARE_UPDATE_JSON_EXEC_ARGS "updateExecArgs" +#define ZT_SOFTWARE_UPDATE_JSON_UPDATE_EXEC_ARGS "updateExecArgs" +#define ZT_SOFTWARE_UPDATE_JSON_UPDATE_URL "updateUrl" namespace ZeroTier { @@ -123,9 +129,11 @@ public: ~SoftwareUpdater(); /** - * Load update-dist.d if it exists + * Set whether or not we will distribute updates + * + * @param distribute If true, scan update-dist.d now and distribute updates found there -- if false, clear and stop distributing */ - void loadUpdatesToDistribute(); + void setUpdateDistribution(bool distribute); /** * Handle a software update user message @@ -141,9 +149,14 @@ public: * * It should be called about every 10 seconds. * - * @return Null JSON object or update information if there is an update downloaded and ready + * @return True if we've downloaded and verified an update */ - nlohmann::json check(const uint64_t now); + bool check(const uint64_t now); + + /** + * @return Meta-data for downloaded update or NULL if none + */ + inline const nlohmann::json &pending() const { return _latestMeta; } /** * Apply any ready update now @@ -153,10 +166,18 @@ public: */ void apply(); + /** + * Set software update channel + * + * @param channel 'release', 'beta', etc. + */ + inline void setChannel(const std::string &channel) { _channel = channel; } + private: Node &_node; uint64_t _lastCheckTime; std::string _homePath; + std::string _channel; // Offered software updates if we are an update host (we have update-dist.d and update hosting is enabled) struct _D -- cgit v1.2.3 From e7bab66d291acdd627e3bcfe434792ce360483b0 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 12 Jan 2017 13:54:08 -0800 Subject: Auto-apply updates if enabled. --- service/OneService.cpp | 3 ++- service/SoftwareUpdater.cpp | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 697be24a..b273aad4 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -722,7 +722,8 @@ public: // Check for updates (if enabled) if ((_updater)&&((now - lastUpdateCheck) > 10000)) { lastUpdateCheck = now; - _updater->check(now); + if (_updater->check(now) && _updateAutoApply) + _updater->apply(); } // Refresh bindings in case device's interfaces have changed, and also sync routes to update any shadow routes (e.g. shadow default) diff --git a/service/SoftwareUpdater.cpp b/service/SoftwareUpdater.cpp index f10eb204..0f5b4fca 100644 --- a/service/SoftwareUpdater.cpp +++ b/service/SoftwareUpdater.cpp @@ -450,7 +450,7 @@ bool SoftwareUpdater::check(const uint64_t now) if (_latestBinLength > 0) { if (_latestBin.length() >= _latestBinLength) { if (_latestBinValid) { - return _latestMeta; + return true; } else { // This is the very important security validation part that makes sure // this software update doesn't have cooties. @@ -466,7 +466,7 @@ bool SoftwareUpdater::check(const uint64_t now) // If we passed both of these, the update is good! _latestBinValid = true; printf("VALID UPDATE\n%s\n",OSUtils::jsonDump(_latestMeta).c_str()); - return _latestMeta; + return true; } } } catch ( ... ) {} // any exception equals verification failure @@ -488,7 +488,7 @@ bool SoftwareUpdater::check(const uint64_t now) } } - return nlohmann::json(); + return false; } void SoftwareUpdater::apply() -- cgit v1.2.3 From e9007b1f569ce15780ed34b837db987eec457d2f Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 19 Jan 2017 10:44:26 -0800 Subject: NodeJS migration script for old Sqlite controller.db to new controller data format. --- controller/EmbeddedNetworkController.hpp | 1 + controller/README.md | 10 +- controller/migrate-sqlite/migrate.js | 320 +++++++++++++++++++++++++++++++ controller/migrate-sqlite/package.json | 15 ++ osdep/OSUtils.cpp | 2 +- service/OneService.cpp | 10 +- 6 files changed, 348 insertions(+), 10 deletions(-) create mode 100644 controller/migrate-sqlite/migrate.js create mode 100644 controller/migrate-sqlite/package.json (limited to 'service/OneService.cpp') diff --git a/controller/EmbeddedNetworkController.hpp b/controller/EmbeddedNetworkController.hpp index 37c067ff..bd3a6666 100644 --- a/controller/EmbeddedNetworkController.hpp +++ b/controller/EmbeddedNetworkController.hpp @@ -165,6 +165,7 @@ private: if (!network.count("v6AssignMode")) network["v6AssignMode"] = {{"rfc4193",false},{"zt",false},{"6plane",false}}; if (!network.count("authTokens")) network["authTokens"] = nlohmann::json::array(); if (!network.count("capabilities")) network["capabilities"] = nlohmann::json::array(); + if (!network.count("routes")) network["routes"] = nlohmann::json::array(); if (!network.count("ipAssignmentPools")) network["ipAssignmentPools"] = nlohmann::json::array(); if (!network.count("rules")) { // If unspecified, rules are set to allow anything and behave like a flat L2 segment diff --git a/controller/README.md b/controller/README.md index 805641d9..edbdf804 100644 --- a/controller/README.md +++ b/controller/README.md @@ -15,15 +15,9 @@ The migration tool is written in nodeJS and can be used like this: cd migrate-sqlite npm install - node migrate-sqlite.js + node migrate.js
-You may need to `sudo node ...` if the ZeroTier working directory is owned by root. - -This code will dump the contents of any `controller.db` in the ZeroTier working directory and recreate its data in the form of JSON objects under `controller.d`. The old `controller.db` will then be renamed to `controller.db.migrated` and the controller will start normally. - -After migrating make sure that the contents of `controller.d` are owned and writable by the user that will be running the ZeroTier controller process! (Usually this is root but controllers that don't also join networks are sometimes run as unprivileged users.) - -If you don't have nodeJS on the machine running ZeroTier it is perfectly fine to just copy `controller.db` to a directory on another machine and run the migration tool there. After running your migration the contents of `controller.d` can be tar'd up and copied back over to the controller. Just remember to rename or remove `controller.db` on the controller machine afterwords so the controller will start. +Very old versions of nodeJS may have issues. We tested it with version 7. ### Scalability and Reliability diff --git a/controller/migrate-sqlite/migrate.js b/controller/migrate-sqlite/migrate.js new file mode 100644 index 00000000..ac9678a7 --- /dev/null +++ b/controller/migrate-sqlite/migrate.js @@ -0,0 +1,320 @@ +'use strict'; + +var sqlite3 = require('sqlite3').verbose(); +var fs = require('fs'); +var async = require('async'); + +function blobToIPv4(b) +{ + if (!b) + return null; + if (b.length !== 16) + return null; + return b.readUInt8(12).toString()+'.'+b.readUInt8(13).toString()+'.'+b.readUInt8(14).toString()+'.'+b.readUInt8(15).toString(); +} +function blobToIPv6(b) +{ + if (!b) + return null; + if (b.length !== 16) + return null; + var s = ''; + for(var i=0;i<16;++i) { + var x = b.readUInt8(i).toString(16); + if (x.length === 1) + s += '0'; + s += x; + if ((((i+1) & 1) === 0)&&(i !== 15)) + s += ':'; + } + return s; +} + +if (process.argv.length !== 4) { + console.log('ZeroTier Old Sqlite3 Controller DB Migration Utility'); + console.log('(c)2017 ZeroTier, Inc. [GPL3]'); + console.log(''); + console.log('Usage: node migrate.js '); + console.log(''); + console.log('The first argument must be the path to the old Sqlite3 controller.db'); + console.log('file. The second must be the path to the EMPTY controller.d database'); + console.log('directory for a new (1.1.17 or newer) controller. If this path does'); + console.log('not exist it will be created.'); + console.log(''); + console.log('WARNING: this will ONLY work correctly on a 1.1.14 controller database.'); + console.log('If your controller is old you should first upgrade to 1.1.14 and run the'); + console.log('controller so that it will brings its Sqlite3 database up to the latest'); + console.log('version before running this migration.'); + console.log(''); + process.exit(1); +} + +var oldDbPath = process.argv[2]; +var newDbPath = process.argv[3]; + +console.log('Starting migrate of "'+oldDbPath+'" to "'+newDbPath+'"...'); +console.log(''); + +var old = new sqlite3.Database(oldDbPath); + +var networks = {}; + +var nodeIdentities = {}; +var networkCount = 0; +var memberCount = 0; +var routeCount = 0; +var ipAssignmentPoolCount = 0; +var ipAssignmentCount = 0; +var ruleCount = 0; +var oldSchemaVersion = -1; + +async.series([function(nextStep) { + + old.each('SELECT v from Config WHERE k = \'schemaVersion\'',function(err,row) { + oldSchemaVersion = parseInt(row.v)||-1; + },nextStep); + +},function(nextStep) { + + if (oldSchemaVersion !== 4) { + console.log('FATAL: this MUST be run on a 1.1.14 controller.db! Upgrade your old'); + console.log('controller to 1.1.14 first and run it once to bring its DB up to date.'); + return process.exit(1); + } + + console.log('Reading networks...'); + old.each('SELECT * FROM Network',function(err,row) { + if ((typeof row.id === 'string')&&(row.id.length === 16)) { + var flags = parseInt(row.flags)||0; + networks[row.id] = { + id: row.id, + nwid: row.id, + objtype: 'network', + authTokens: [], + capabilities: [], + creationTime: parseInt(row.creationTime)||0, + enableBroadcast: !!row.enableBroadcast, + ipAssignmentPools: [], + lastModified: Date.now(), + multicastLimit: row.multicastLimit||32, + name: row.name||'', + private: !!row.private, + revision: parseInt(row.revision)||1, + rules: [{ 'type': 'ACTION_ACCEPT' }], // populated later if there are defined rules, otherwise default is allow all + routes: [], + v4AssignMode: { + 'zt': ((flags & 1) !== 0) + }, + v6AssignMode: { + '6plane': ((flags & 4) !== 0), + 'rfc4193': ((flags & 2) !== 0), + 'zt': ((flags & 8) !== 0) + }, + _members: {} // temporary + }; + ++networkCount; + //console.log(networks[row.id]); + } + },nextStep); + +},function(nextStep) { + + console.log(' '+networkCount+' networks.'); + console.log('Reading network route definitions...'); + old.each('SELECT * from Route WHERE ipVersion = 4 OR ipVersion = 6',function(err,row) { + var network = networks[row.networkId]; + if (network) { + var rt = { + target: (((row.ipVersion == 4) ? blobToIPv4(row.target) : blobToIPv6(row.target))+'/'+row.targetNetmaskBits), + via: ((row.via) ? ((row.ipVersion == 4) ? blobToIPv4(row.via) : blobToIPv6(row.via)) : null) + }; + network.routes.push(rt); + ++routeCount; + } + },nextStep); + +},function(nextStep) { + + console.log(' '+routeCount+' routes in '+networkCount+' networks.'); + console.log('Reading IP assignment pools...'); + old.each('SELECT * FROM IpAssignmentPool WHERE ipVersion = 4 OR ipVersion = 6',function(err,row) { + var network = networks[row.networkId]; + if (network) { + var p = { + ipRangeStart: ((row.ipVersion == 4) ? blobToIPv4(row.ipRangeStart) : blobToIPv6(row.ipRangeStart)), + ipRangeEnd: ((row.ipVersion == 4) ? blobToIPv4(row.ipRangeEnd) : blobToIPv6(row.ipRangeEnd)) + }; + network.ipAssignmentPools.push(p); + ++ipAssignmentPoolCount; + } + },nextStep); + +},function(nextStep) { + + console.log(' '+ipAssignmentPoolCount+' IP assignment pools in '+networkCount+' networks.'); + console.log('Reading known node identities...'); + old.each('SELECT * FROM Node',function(err,row) { + nodeIdentities[row.id] = row.identity; + },nextStep); + +},function(nextStep) { + + console.log(' '+Object.keys(nodeIdentities).length+' known identities.'); + console.log('Reading network members...'); + old.each('SELECT * FROM Member',function(err,row) { + var network = networks[row.networkId]; + if (network) { + network._members[row.nodeId] = { + id: row.nodeId, + address: row.nodeId, + objtype: 'member', + authorized: !!row.authorized, + activeBridge: !!row.activeBridge, + authHistory: [], + capabilities: [], + creationTime: 0, + identity: nodeIdentities[row.nodeId]||null, + ipAssignments: [], + lastAuthorizedTime: (row.authorized) ? Date.now() : 0, + lastDeauthorizedTime: (row.authorized) ? 0 : Date.now(), + lastModified: Date.now(), + lastRequestMetaData: '', + noAutoAssignIps: false, + nwid: row.networkId, + revision: parseInt(row.memberRevision)||1, + tags: [], + recentLog: [] + }; + ++memberCount; + //console.log(network._members[row.nodeId]); + } + },nextStep); + +},function(nextStep) { + + console.log(' '+memberCount+' members of '+networkCount+' networks.'); + console.log('Reading static IP assignments...'); + old.each('SELECT * FROM IpAssignment WHERE ipVersion = 4 OR ipVersion = 6',function(err,row) { + var network = networks[row.networkId]; + if (network) { + var member = network._members[row.nodeId]; + if ((member)&&((member.authorized)||(!network['private']))) { // don't mirror assignments to unauthorized members to avoid conflicts + if (row.ipVersion == 4) { + member.ipAssignments.push(blobToIPv4(row.ip)); + ++ipAssignmentCount; + } else if (row.ipVersion == 6) { + member.ipAssignments.push(blobToIPv6(row.ip)); + ++ipAssignmentCount; + } + } + } + },nextStep); + +},function(nextStep) { + + // Old versions only supported Ethertype whitelisting, so that's + // all we mirror forward. The other fields were always unused. + + console.log(' '+ipAssignmentCount+' IP assignments for '+memberCount+' authorized members of '+networkCount+' networks.'); + console.log('Reading allowed Ethernet types (old basic rules)...'); + var etherTypesByNetwork = {}; + old.each('SELECT DISTINCT networkId,ruleNo,etherType FROM Rule WHERE "action" = \'accept\'',function(err,row) { + if (row.networkId in networks) { + var et = parseInt(row.etherType)||0; + var ets = etherTypesByNetwork[row.networkId]; + if (!ets) + etherTypesByNetwork[row.networkId] = [ et ]; + else ets.push(et); + } + },function(err) { + if (err) return nextStep(err); + for(var nwid in etherTypesByNetwork) { + var ets = etherTypesByNetwork[nwid].sort(); + var network = networks[nwid]; + if (network) { + var rules = []; + if (ets.indexOf(0) >= 0) { + // If 0 is in the list, all Ethernet types are allowed so we accept all. + rules.push({ 'type': 'ACTION_ACCEPT' }); + } else { + // Otherwise we whitelist. + for(var i=0;i 0) { + try { + fs.mkdirSync(nwBase+network.id); + } catch (e) {} + var mbase = nwBase+network.id+'/member'; + try { + fs.mkdirSync(mbase,0o700); + } catch (e) {} + mbase = mbase + '/'; + + for(var mi=0;mi", + "license": "GPL-3.0", + "dependencies": { + "async": "^2.1.4", + "sqlite3": "^3.1.8" + } +} diff --git a/osdep/OSUtils.cpp b/osdep/OSUtils.cpp index 08d67bbe..170e1376 100644 --- a/osdep/OSUtils.cpp +++ b/osdep/OSUtils.cpp @@ -398,7 +398,7 @@ std::string OSUtils::platformDefaultHomePath() // Inline these massive JSON operations in one place only to reduce binary footprint and compile time nlohmann::json OSUtils::jsonParse(const std::string &buf) { return nlohmann::json::parse(buf); } -std::string OSUtils::jsonDump(const nlohmann::json &j) { return j.dump(2); } +std::string OSUtils::jsonDump(const nlohmann::json &j) { return j.dump(1); } uint64_t OSUtils::jsonInt(const nlohmann::json &jv,const uint64_t dfl) { diff --git a/service/OneService.cpp b/service/OneService.cpp index b273aad4..0fd8496d 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -625,7 +625,15 @@ public: for(int i=0;i<3;++i) _portsBE[i] = Utils::hton((uint16_t)_ports[i]); - _controller = new EmbeddedNetworkController(_node,(_homePath + ZT_PATH_SEPARATOR_S + ZT_CONTROLLER_DB_PATH).c_str(),(FILE *)0); + // Check for legacy controller.db and terminate if present to prevent nasty surprises for DIY controller folks + if (OSUtils::fileExists((_homePath + ZT_PATH_SEPARATOR_S "controller.db").c_str())) { + Mutex::Lock _l(_termReason_m); + _termReason = ONE_UNRECOVERABLE_ERROR; + _fatalErrorMessage = "controller.db is present in our home path! run migrate-sqlite to migrate to new controller.d format."; + return _termReason; + } + + _controller = new EmbeddedNetworkController(_node,(_homePath + ZT_PATH_SEPARATOR_S ZT_CONTROLLER_DB_PATH).c_str(),(FILE *)0); _node->setNetconfMaster((void *)_controller); #ifdef ZT_ENABLE_CLUSTER -- cgit v1.2.3 From 89d74cd293a374167547c3fc1f082ec4f2b27d65 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 19 Jan 2017 15:57:50 -0800 Subject: Add a portMappingEnabled flag to local.conf to allow uPnP/NAT-PMP to be disabled. --- service/OneService.cpp | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 0fd8496d..d9134a34 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -344,6 +344,7 @@ public: Mutex _termReason_m; // uPnP/NAT-PMP port mapper if enabled + bool _portMappingEnabled; // local.conf settings #ifdef ZT_USE_MINIUPNPC PortMapper *_portMapper; #endif @@ -379,6 +380,7 @@ public: ,_nextBackgroundTaskDeadline(0) ,_tcpFallbackTunnel((TcpConnection *)0) ,_termReason(ONE_STILL_RUNNING) + ,_portMappingEnabled(true) #ifdef ZT_USE_MINIUPNPC ,_portMapper((PortMapper *)0) #endif @@ -598,25 +600,27 @@ public: } #ifdef ZT_USE_MINIUPNPC - // If we're running uPnP/NAT-PMP, bind a *third* port for that. We can't - // use the other two ports for that because some NATs do really funky - // stuff with ports that are explicitly mapped that breaks things. - if (_ports[1]) { - _ports[2] = _ports[1]; - for(int i=0;;++i) { - if (i > 1000) { - _ports[2] = 0; - break; - } else if (++_ports[2] >= 65536) { - _ports[2] = 20000; + if (_portMappingEnabled) { + // If we're running uPnP/NAT-PMP, bind a *third* port for that. We can't + // use the other two ports for that because some NATs do really funky + // stuff with ports that are explicitly mapped that breaks things. + if (_ports[1]) { + _ports[2] = _ports[1]; + for(int i=0;;++i) { + if (i > 1000) { + _ports[2] = 0; + break; + } else if (++_ports[2] >= 65536) { + _ports[2] = 20000; + } + if (_trialBind(_ports[2])) + break; + } + if (_ports[2]) { + char uniqueName[64]; + Utils::snprintf(uniqueName,sizeof(uniqueName),"ZeroTier/%.10llx@%u",_node->address(),_ports[2]); + _portMapper = new PortMapper(_ports[2],uniqueName); } - if (_trialBind(_ports[2])) - break; - } - if (_ports[2]) { - char uniqueName[64]; - Utils::snprintf(uniqueName,sizeof(uniqueName),"ZeroTier/%.10llx@%u",_node->address(),_ports[2]); - _portMapper = new PortMapper(_ports[2],uniqueName); } } #endif @@ -983,6 +987,8 @@ public: _interfacePrefixBlacklist.clear(); json &settings = _localConfig["settings"]; if (settings.is_object()) { + _portMappingEnabled = OSUtils::jsonBool(settings["portMappingEnabled"],true); + const std::string rp(OSUtils::jsonString(settings["relayPolicy"],"")); if ((rp == "always")||(rp == "ALWAYS")) _node->setRelayPolicy(ZT_RELAY_POLICY_ALWAYS); -- cgit v1.2.3 From 7b231b38b02d74afff7ea9cde6ea5c4a8cee5103 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 19 Jan 2017 10:39:42 -0800 Subject: Now builds on OpenBSD, but segfaults. So not yet but close. GitHub issue #439 --- Makefile | 4 ++++ make-freebsd.mk | 2 -- osdep/BSDEthernetTap.cpp | 32 +++++++++++++++++++++++--------- service/OneService.cpp | 4 ++++ 4 files changed, 31 insertions(+), 11 deletions(-) (limited to 'service/OneService.cpp') diff --git a/Makefile b/Makefile index 5a5f6605..4bbd5ad2 100644 --- a/Makefile +++ b/Makefile @@ -11,8 +11,12 @@ ifeq ($(OSTYPE),Linux) endif ifeq ($(OSTYPE),FreeBSD) + CC=gcc + CXX=g++ include make-freebsd.mk endif ifeq ($(OSTYPE),OpenBSD) + CC=egcc + CXX=eg++ include make-freebsd.mk endif diff --git a/make-freebsd.mk b/make-freebsd.mk index 23ad278b..a90dfc77 100644 --- a/make-freebsd.mk +++ b/make-freebsd.mk @@ -1,5 +1,3 @@ -CC=cc -CXX=c++ INCLUDES= DEFS= LIBS= diff --git a/osdep/BSDEthernetTap.cpp b/osdep/BSDEthernetTap.cpp index e8d36c9c..463206f6 100644 --- a/osdep/BSDEthernetTap.cpp +++ b/osdep/BSDEthernetTap.cpp @@ -85,8 +85,14 @@ BSDEthernetTap::BSDEthernetTap( char devpath[64],ethaddr[64],mtustr[32],metstr[32],tmpdevname[32]; struct stat stattmp; - // On FreeBSD at least we can rename, so use nwid to generate a deterministic unique zt#### name using base32 - // As a result we don't use desiredDevice + Mutex::Lock _gl(globalTapCreateLock); + + if (mtu > 2800) + throw std::runtime_error("max tap MTU is 2800"); + +#ifdef __FreeBSD__ + /* FreeBSD allows long interface names and interface renaming */ + _dev = "zt"; _dev.push_back(ZT_BASE32_CHARS[(unsigned long)((nwid >> 60) & 0x1f)]); _dev.push_back(ZT_BASE32_CHARS[(unsigned long)((nwid >> 55) & 0x1f)]); @@ -102,13 +108,6 @@ BSDEthernetTap::BSDEthernetTap( _dev.push_back(ZT_BASE32_CHARS[(unsigned long)((nwid >> 5) & 0x1f)]); _dev.push_back(ZT_BASE32_CHARS[(unsigned long)(nwid & 0x1f)]); - Mutex::Lock _gl(globalTapCreateLock); - - if (mtu > 2800) - throw std::runtime_error("max tap MTU is 2800"); - - // On BSD we create taps and they can have high numbers, so use ones starting - // at 9993 to not conflict with other stuff. Then we rename it to zt std::vector devFiles(OSUtils::listDirectory("/dev")); for(int i=9993;i<(9993+128);++i) { Utils::snprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i); @@ -144,6 +143,19 @@ BSDEthernetTap::BSDEthernetTap( } } } +#else + /* Other BSDs like OpenBSD only have a limited number of tap devices that cannot be renamed */ + + for(int i=0;i<64;++i) { + Utils::snprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i); + Utils::snprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname); + _fd = ::open(devpath,O_RDWR); + if (_fd > 0) { + _dev = tmpdevname; + break; + } + } +#endif if (_fd <= 0) throw std::runtime_error("unable to open TAP device or no more devices available"); @@ -325,6 +337,7 @@ void BSDEthernetTap::scanMulticastGroups(std::vector &added,std: { std::vector newGroups; +#ifndef __OpenBSD__ struct ifmaddrs *ifmap = (struct ifmaddrs *)0; if (!getifmaddrs(&ifmap)) { struct ifmaddrs *p = ifmap; @@ -339,6 +352,7 @@ void BSDEthernetTap::scanMulticastGroups(std::vector &added,std: } freeifmaddrs(ifmap); } +#endif // __OpenBSD__ std::vector allIps(ips()); for(std::vector::iterator ip(allIps.begin());ip!=allIps.end();++ip) diff --git a/service/OneService.cpp b/service/OneService.cpp index d9134a34..93f5b5f0 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -115,6 +115,10 @@ namespace ZeroTier { typedef WindowsEthernetTap EthernetTap; } #include "../osdep/BSDEthernetTap.hpp" namespace ZeroTier { typedef BSDEthernetTap EthernetTap; } #endif // __FreeBSD__ +#ifdef __OpenBSD__ +#include "../osdep/BSDEthernetTap.hpp" +namespace ZeroTier { typedef BSDEthernetTap EthernetTap; } +#endif // __OpenBSD__ #endif // ZT_SERVICE_NETCON -- cgit v1.2.3 From 8f2a42d1ad84e5dba590e7f593d8a46cc81389b3 Mon Sep 17 00:00:00 2001 From: Michał Zieliński Date: Sun, 22 Jan 2017 23:02:34 +0100 Subject: allow user to specify arbitrary allowed IP networks in allowManaged --- node/Buffer.hpp | 10 +++++----- service/ControlPlane.cpp | 11 ++++++++++- service/OneService.cpp | 41 ++++++++++++++++++++++++++++++++++++++--- service/OneService.hpp | 7 +++++++ 4 files changed, 60 insertions(+), 9 deletions(-) (limited to 'service/OneService.cpp') diff --git a/node/Buffer.hpp b/node/Buffer.hpp index 0b171592..1a478894 100644 --- a/node/Buffer.hpp +++ b/node/Buffer.hpp @@ -61,11 +61,11 @@ public: // STL container idioms typedef unsigned char value_type; typedef unsigned char * pointer; - typedef const unsigned char * const_pointer; - typedef unsigned char & reference; - typedef const unsigned char & const_reference; - typedef unsigned char * iterator; - typedef const unsigned char * const_iterator; + typedef const char * const_pointer; + typedef char & reference; + typedef const char & const_reference; + typedef char * iterator; + typedef const char * const_iterator; typedef unsigned int size_type; typedef int difference_type; typedef std::reverse_iterator reverse_iterator; diff --git a/service/ControlPlane.cpp b/service/ControlPlane.cpp index 86158a91..27027d3b 100644 --- a/service/ControlPlane.cpp +++ b/service/ControlPlane.cpp @@ -121,6 +121,15 @@ static void _jsonAppend(unsigned int depth,std::string &buf,const ZT_VirtualNetw case ZT_NETWORK_TYPE_PUBLIC: ntype = "PUBLIC"; break; } + std::string allowManaged = (localSettings.allowManaged) ? "true" : "false"; + if (localSettings.allowManagedWhitelist.size() != 0) { + allowManaged = ""; + for (InetAddress address : localSettings.allowManagedWhitelist) { + if (allowManaged.size() != 0) allowManaged += ','; + allowManaged += address.toIpString() + "/" + std::to_string(address.netmaskBits()); + } + } + Utils::snprintf(json,sizeof(json), "%s{\n" "%s\t\"id\": \"%.16llx\",\n" @@ -158,7 +167,7 @@ static void _jsonAppend(unsigned int depth,std::string &buf,const ZT_VirtualNetw prefix,_jsonEnumerate(nc->assignedAddresses,nc->assignedAddressCount).c_str(), prefix,_jsonEnumerate(nc->routes,nc->routeCount).c_str(), prefix,_jsonEscape(portDeviceName).c_str(), - prefix,(localSettings.allowManaged) ? "true" : "false", + prefix,allowManaged.c_str(), prefix,(localSettings.allowGlobal) ? "true" : "false", prefix,(localSettings.allowDefault) ? "true" : "false", prefix); diff --git a/service/OneService.cpp b/service/OneService.cpp index 93f5b5f0..603234a2 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1039,6 +1039,18 @@ public: { if (!n.settings.allowManaged) return false; + + if (n.settings.allowManagedWhitelist.size() > 0) { + bool allowed = false; + for (InetAddress addr : n.settings.allowManagedWhitelist) { + if (addr.containsAddress(target) && addr.netmaskBits() <= target.netmaskBits()) { + allowed = true; + break; + } + } + if (!allowed) return false; + } + if (target.isDefaultRoute()) return n.settings.allowDefault; switch(target.ipScope()) { @@ -1423,9 +1435,32 @@ public: if (OSUtils::readFile(nlcpath,nlcbuf)) { Dictionary<4096> nc; nc.load(nlcbuf.c_str()); - n.settings.allowManaged = nc.getB("allowManaged",true); - n.settings.allowGlobal = nc.getB("allowGlobal",false); - n.settings.allowDefault = nc.getB("allowDefault",false); + Buffer<1024> allowManaged; + if (nc.get("allowManaged", allowManaged) && allowManaged.size() != 0) { + std::string addresses (allowManaged.begin(), allowManaged.size()); + if (allowManaged.size() <= 5) { // untidy parsing for backward compatibility + if (allowManaged[0] == '1' || allowManaged[0] == 't' || allowManaged[0] == 'T') { + n.settings.allowManaged = true; + } else { + n.settings.allowManaged = false; + } + } else { + // this should be a list of IP addresses + n.settings.allowManaged = true; + size_t pos = 0; + while (true) { + size_t nextPos = addresses.find(',', pos); + std::string address = addresses.substr(pos, (nextPos == std::string::npos ? addresses.size() : nextPos) - pos); + n.settings.allowManagedWhitelist.push_back(InetAddress(address)); + if (nextPos == std::string::npos) break; + pos = nextPos + 1; + } + } + } else { + n.settings.allowManaged = true; + } + n.settings.allowGlobal = nc.getB("allowGlobal", false); + n.settings.allowDefault = nc.getB("allowDefault", false); } } catch (std::exception &exc) { #ifdef __WINDOWS__ diff --git a/service/OneService.hpp b/service/OneService.hpp index 7aa3b361..88225da4 100644 --- a/service/OneService.hpp +++ b/service/OneService.hpp @@ -20,6 +20,7 @@ #define ZT_ONESERVICE_HPP #include +#include namespace ZeroTier { @@ -65,6 +66,12 @@ public: */ bool allowManaged; + /** + * Whitelist of addresses that can be configured by this network. + * If empty and allowManaged is true, allow all private/pseudoprivate addresses. + */ + std::vector allowManagedWhitelist; + /** * Allow configuration of IPs and routes within global (Internet) IP space? */ -- cgit v1.2.3 From ec0e8a9a4357df6316efc969edbb78347a574a5e Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 26 Jan 2017 13:59:20 -0800 Subject: Rip out resolver and use anycast address instead. In the long term existing TCP proxy dies anyway. Fixes static build problem for old Linux versions. --- objects.mk | 1 - osdep/BackgroundResolver.cpp | 121 ------------------------------------------- osdep/BackgroundResolver.hpp | 118 ----------------------------------------- osdep/OSUtils.cpp | 28 ---------- service/OneService.cpp | 27 ++-------- 5 files changed, 5 insertions(+), 290 deletions(-) delete mode 100644 osdep/BackgroundResolver.cpp delete mode 100644 osdep/BackgroundResolver.hpp (limited to 'service/OneService.cpp') diff --git a/objects.mk b/objects.mk index 38d6bef3..31498b72 100644 --- a/objects.mk +++ b/objects.mk @@ -26,7 +26,6 @@ OBJS=\ node/Tag.o \ node/Topology.o \ node/Utils.o \ - osdep/BackgroundResolver.o \ osdep/ManagedRoute.o \ osdep/Http.o \ osdep/OSUtils.o \ diff --git a/osdep/BackgroundResolver.cpp b/osdep/BackgroundResolver.cpp deleted file mode 100644 index ffcfdbae..00000000 --- a/osdep/BackgroundResolver.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 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 . - */ - -#include "OSUtils.hpp" -#include "Thread.hpp" -#include "BackgroundResolver.hpp" - -namespace ZeroTier { - -/* - * We can't actually abort a job. This is a legacy characteristic of the - * ancient synchronous resolver APIs. So to abort jobs, we just abandon - * them by setting their parent to null. - */ -class BackgroundResolverJob -{ -public: - std::string name; - BackgroundResolver *volatile parent; - Mutex lock; - - void threadMain() - throw() - { - std::vector ips; - try { - ips = OSUtils::resolve(name.c_str()); - } catch ( ... ) {} - { - Mutex::Lock _l(lock); - BackgroundResolver *p = parent; - if (p) - p->_postResult(ips); - } - delete this; - } -}; - -BackgroundResolver::BackgroundResolver(const char *name) : - _name(name), - _job((BackgroundResolverJob *)0), - _callback(0), - _arg((void *)0), - _ips(), - _lock() -{ -} - -BackgroundResolver::~BackgroundResolver() -{ - abort(); -} - -std::vector BackgroundResolver::get() const -{ - Mutex::Lock _l(_lock); - return _ips; -} - -void BackgroundResolver::resolveNow(void (*callback)(BackgroundResolver *,void *),void *arg) -{ - Mutex::Lock _l(_lock); - - if (_job) { - Mutex::Lock _l2(_job->lock); - _job->parent = (BackgroundResolver *)0; - _job = (BackgroundResolverJob *)0; - } - - BackgroundResolverJob *j = new BackgroundResolverJob(); - j->name = _name; - j->parent = this; - - _job = j; - _callback = callback; - _arg = arg; - - _jobThread = Thread::start(j); -} - -void BackgroundResolver::abort() -{ - Mutex::Lock _l(_lock); - if (_job) { - Mutex::Lock _l2(_job->lock); - _job->parent = (BackgroundResolver *)0; - _job = (BackgroundResolverJob *)0; - } -} - -void BackgroundResolver::_postResult(const std::vector &ips) -{ - void (*cb)(BackgroundResolver *,void *); - void *a; - { - Mutex::Lock _l(_lock); - _job = (BackgroundResolverJob *)0; - cb = _callback; - a = _arg; - _ips = ips; - } - if (cb) - cb(this,a); -} - -} // namespace ZeroTier diff --git a/osdep/BackgroundResolver.hpp b/osdep/BackgroundResolver.hpp deleted file mode 100644 index ba895487..00000000 --- a/osdep/BackgroundResolver.hpp +++ /dev/null @@ -1,118 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 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 . - */ - -#ifndef ZT_BACKGROUNDRESOLVER_HPP -#define ZT_BACKGROUNDRESOLVER_HPP - -#include -#include - -#include "../node/Constants.hpp" -#include "../node/Mutex.hpp" -#include "../node/InetAddress.hpp" -#include "../node/NonCopyable.hpp" -#include "Thread.hpp" - -namespace ZeroTier { - -class BackgroundResolverJob; - -/** - * A simple background resolver - */ -class BackgroundResolver : NonCopyable -{ - friend class BackgroundResolverJob; - -public: - /** - * Construct a new resolver - * - * resolveNow() must be called to actually initiate background resolution. - * - * @param name Name to resolve - */ - BackgroundResolver(const char *name); - - ~BackgroundResolver(); - - /** - * @return Most recent resolver results or empty vector if none - */ - std::vector get() const; - - /** - * Launch a background resolve job now - * - * If a resolve job is currently in progress, it is aborted and another - * job is started. - * - * Note that jobs can't actually be aborted due to the limitations of the - * ancient synchronous OS resolver APIs. As a result, in progress jobs - * that are aborted are simply abandoned. Don't call this too frequently - * or background threads might pile up. - * - * @param callback Callback function to receive notification or NULL if none - * @praam arg Second argument to callback function - */ - void resolveNow(void (*callback)(BackgroundResolver *,void *) = 0,void *arg = 0); - - /** - * Abort (abandon) any current resolve jobs - */ - void abort(); - - /** - * @return True if a background job is in progress - */ - inline bool running() const - { - Mutex::Lock _l(_lock); - return (_job != (BackgroundResolverJob *)0); - } - - /** - * Wait for pending job to complete (if any) - */ - inline void wait() const - { - Thread t; - { - Mutex::Lock _l(_lock); - if (!_job) - return; - t = _jobThread; - } - Thread::join(t); - } - -private: - void _postResult(const std::vector &ips); - - std::string _name; - BackgroundResolverJob *_job; - Thread _jobThread; - void (*_callback)(BackgroundResolver *,void *); - void *_arg; - std::vector _ips; - Mutex _lock; -}; - -} // namespace ZeroTier - -#endif diff --git a/osdep/OSUtils.cpp b/osdep/OSUtils.cpp index 170e1376..fc02109a 100644 --- a/osdep/OSUtils.cpp +++ b/osdep/OSUtils.cpp @@ -256,34 +256,6 @@ int64_t OSUtils::getFileSize(const char *path) return -1; } -std::vector OSUtils::resolve(const char *name) -{ - std::vector r; - std::vector::iterator i; - InetAddress tmp; - struct addrinfo *ai = (struct addrinfo *)0,*p; - if (!getaddrinfo(name,(const char *)0,(const struct addrinfo *)0,&ai)) { - try { - p = ai; - while (p) { - if ((p->ai_addr)&&((p->ai_addr->sa_family == AF_INET)||(p->ai_addr->sa_family == AF_INET6))) { - tmp = *(p->ai_addr); - for(i=r.begin();i!=r.end();++i) { - if (i->ipsEqual(tmp)) - goto skip_add_inetaddr; - } - r.push_back(tmp); - } -skip_add_inetaddr: - p = p->ai_next; - } - } catch ( ... ) {} - freeaddrinfo(ai); - } - std::sort(r.begin(),r.end()); - return r; -} - bool OSUtils::readFile(const char *path,std::string &buf) { char tmp[1024]; diff --git a/service/OneService.cpp b/service/OneService.cpp index 93f5b5f0..2932c605 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -43,7 +43,6 @@ #include "../osdep/Thread.hpp" #include "../osdep/OSUtils.hpp" #include "../osdep/Http.hpp" -#include "../osdep/BackgroundResolver.hpp" #include "../osdep/PortMapper.hpp" #include "../osdep/Binder.hpp" #include "../osdep/ManagedRoute.hpp" @@ -136,9 +135,8 @@ namespace ZeroTier { typedef BSDEthernetTap EthernetTap; } // Path under ZT1 home for controller database if controller is enabled #define ZT_CONTROLLER_DB_PATH "controller.d" -// TCP fallback relay host -- geo-distributed using Amazon Route53 geo-aware DNS -#define ZT_TCP_FALLBACK_RELAY "tcp-fallback.zerotier.com" -#define ZT_TCP_FALLBACK_RELAY_PORT 443 +// TCP fallback relay (run by ZeroTier, Inc. -- this will eventually go away) +#define ZT_TCP_FALLBACK_RELAY "204.80.128.1/443" // Frequency at which we re-resolve the TCP fallback relay #define ZT_TCP_FALLBACK_RERESOLVE_DELAY 86400000 @@ -263,7 +261,6 @@ public: // begin member variables -------------------------------------------------- const std::string _homePath; - BackgroundResolver _tcpFallbackResolver; EmbeddedNetworkController *_controller; Phy _phy; Node *_node; @@ -368,7 +365,6 @@ public: OneServiceImpl(const char *hp,unsigned int port) : _homePath((hp) ? hp : ".") - ,_tcpFallbackResolver(ZT_TCP_FALLBACK_RELAY) ,_controller((EmbeddedNetworkController *)0) ,_phy(this,false,true) ,_node((Node *)0) @@ -710,7 +706,6 @@ public: uint64_t clockShouldBe = OSUtils::now(); _lastRestart = clockShouldBe; uint64_t lastTapMulticastGroupCheck = 0; - uint64_t lastTcpFallbackResolve = 0; uint64_t lastBindRefresh = 0; uint64_t lastUpdateCheck = clockShouldBe; uint64_t lastLocalInterfaceAddressCheck = (clockShouldBe - ZT_LOCAL_INTERFACE_CHECK_INTERVAL) + 15000; // do this in 15s to give portmapper time to configure and other things time to settle @@ -765,11 +760,6 @@ public: dl = _nextBackgroundTaskDeadline; } - if ((now - lastTcpFallbackResolve) >= ZT_TCP_FALLBACK_RERESOLVE_DELAY) { - lastTcpFallbackResolve = now; - _tcpFallbackResolver.resolveNow(); - } - if ((_tcpFallbackTunnel)&&((now - _lastDirectReceiveFromGlobal) < (ZT_TCP_FALLBACK_AFTER / 2))) _phy.close(_tcpFallbackTunnel->sock); @@ -1617,16 +1607,9 @@ public: _tcpFallbackTunnel->writeBuf.append(reinterpret_cast(reinterpret_cast(&(reinterpret_cast(addr)->sin_port))),2); _tcpFallbackTunnel->writeBuf.append((const char *)data,len); } else if (((now - _lastSendToGlobalV4) < ZT_TCP_FALLBACK_AFTER)&&((now - _lastSendToGlobalV4) > (ZT_PING_CHECK_INVERVAL / 2))) { - std::vector tunnelIps(_tcpFallbackResolver.get()); - if (tunnelIps.empty()) { - if (!_tcpFallbackResolver.running()) - _tcpFallbackResolver.resolveNow(); - } else { - bool connected = false; - InetAddress addr(tunnelIps[(unsigned long)now % tunnelIps.size()]); - addr.setPort(ZT_TCP_FALLBACK_RELAY_PORT); - _phy.tcpConnect(reinterpret_cast(&addr),connected); - } + bool connected = false; + const InetAddress addr(ZT_TCP_FALLBACK_RELAY); + _phy.tcpConnect(reinterpret_cast(&addr),connected); } } _lastSendToGlobalV4 = now; -- cgit v1.2.3 From 64774d0d4f552b2864abd969c6bc69c0ced3b2e1 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 27 Jan 2017 13:27:52 -0800 Subject: Replace piecemeal designation of upstreams with the concept of moons, which is simpler and easier to use and inherits all the cool live update stuff of worlds (now called planets) and global roots. --- include/ZeroTierOne.h | 15 +--- node/IncomingPacket.cpp | 22 ++--- node/Node.cpp | 85 ++++++-------------- node/Node.hpp | 1 - node/Peer.cpp | 12 +-- node/Switch.cpp | 2 +- node/Topology.cpp | 207 +++++++++++++++++++++++------------------------- node/Topology.hpp | 79 ++++++++++-------- node/World.hpp | 87 ++++++++++---------- service/OneService.cpp | 22 +++-- service/README.md | 1 - world/mkworld.cpp | 5 +- 12 files changed, 242 insertions(+), 296 deletions(-) (limited to 'service/OneService.cpp') diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 8b1ee0ac..f0235b9d 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -848,8 +848,8 @@ enum ZT_VirtualNetworkConfigOperation enum ZT_PeerRole { ZT_PEER_ROLE_LEAF = 0, // ordinary node - ZT_PEER_ROLE_UPSTREAM = 1, // upstream node - ZT_PEER_ROLE_ROOT = 2 // global root + ZT_PEER_ROLE_UPSTREAM = 1, // moon root + ZT_PEER_ROLE_ROOT = 2 // planetary root }; /** @@ -1903,17 +1903,6 @@ void ZT_Node_clearLocalInterfaceAddresses(ZT_Node *node); */ int ZT_Node_sendUserMessage(ZT_Node *node,uint64_t dest,uint64_t typeId,const void *data,unsigned int len); -/** - * Set peer role - * - * Right now this can only be used to set a peer to either LEAF or - * UPSTREAM, since roots are fixed and defined by the World. - * - * @param ztAddress ZeroTier address (least significant 40 bits) - * @param role New peer role (LEAF or UPSTREAM) - */ -void ZT_Node_setRole(ZT_Node *node,uint64_t ztAddress,enum ZT_PeerRole role); - /** * Set a network configuration master instance for this node * diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 562aee91..2487a8aa 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -214,8 +214,8 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut Identity id; InetAddress externalSurfaceAddress; - uint64_t worldId = ZT_WORLD_ID_NULL; - uint64_t worldTimestamp = 0; + uint64_t planetWorldId = 0; + uint64_t planetWorldTimestamp = 0; { unsigned int ptr = ZT_PROTO_VERB_HELLO_IDX_IDENTITY + id.deserialize(*this,ZT_PROTO_VERB_HELLO_IDX_IDENTITY); @@ -223,10 +223,10 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut if (ptr < size()) ptr += externalSurfaceAddress.deserialize(*this,ptr); - // Get world ID and world timestamp if present (was not in old versions) + // Get primary planet world ID and world timestamp if present if ((ptr + 16) <= size()) { - worldId = at(ptr); ptr += 8; - worldTimestamp = at(ptr); + planetWorldId = at(ptr); ptr += 8; + planetWorldTimestamp = at(ptr); } } @@ -356,14 +356,14 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut tmpa.serialize(outp); } - if ((worldId != ZT_WORLD_ID_NULL)&&(RR->topology->worldTimestamp() > worldTimestamp)&&(worldId == RR->topology->worldId())) { - World w(RR->topology->world()); + if ((planetWorldId)&&(RR->topology->planetWorldTimestamp() > planetWorldTimestamp)&&(planetWorldId == RR->topology->planetWorldId())) { + World w(RR->topology->planet()); const unsigned int sizeAt = outp.size(); outp.addSize(2); // make room for 16-bit size field w.serialize(outp,false); outp.setAt(sizeAt,(uint16_t)(outp.size() - (sizeAt + 2))); } else { - outp.append((uint16_t)0); // no world update needed + outp.append((uint16_t)0); // no planet update needed } outp.armor(peer->key(),true); @@ -411,14 +411,14 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr &p if (ptr < size()) ptr += externalSurfaceAddress.deserialize(*this,ptr); - // Handle world updates from root servers if present (was not on old versions) - if (((ptr + 2) <= size())&&(RR->topology->isRoot(peer->identity()))) { + // Handle planet or moon updates + if ((ptr + 2) <= size()) { World worldUpdate; const unsigned int worldLen = at(ptr); ptr += 2; if (worldLen > 0) { World w; w.deserialize(*this,ptr); - RR->topology->worldUpdateIfValid(w); + RR->topology->addWorld(w,true); } } diff --git a/node/Node.cpp b/node/Node.cpp index 0d0750ca..df22e3f2 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -160,75 +160,48 @@ ZT_ResultCode Node::processVirtualNetworkFrame( class _PingPeersThatNeedPing { public: - _PingPeersThatNeedPing(const RuntimeEnvironment *renv,const std::vector
&upstreams,uint64_t now) : + _PingPeersThatNeedPing(const RuntimeEnvironment *renv,uint64_t now) : lastReceiveFromUpstream(0), RR(renv), - _upstreams(upstreams), - _now(now), - _world(RR->topology->world()) + _now(now) { + RR->topology->getUpstreamStableEndpoints(_upstreams); } uint64_t lastReceiveFromUpstream; // tracks last time we got a packet from an 'upstream' peer like a root or a relay inline void operator()(Topology &t,const SharedPtr &p) { - if (std::find(_upstreams.begin(),_upstreams.end(),p->address()) != _upstreams.end()) { - InetAddress stableEndpoint4,stableEndpoint6; - for(std::vector::const_iterator r(_world.roots().begin());r!=_world.roots().end();++r) { - if (r->identity == p->identity()) { - for(unsigned long k=0,ptr=(unsigned long)RR->node->prng();k<(unsigned long)r->stableEndpoints.size();++k) { - const InetAddress &addr = r->stableEndpoints[ptr++ % r->stableEndpoints.size()]; - if (!stableEndpoint4) { - if (addr.ss_family == AF_INET) - stableEndpoint4 = addr; - } - if (!stableEndpoint6) { - if (addr.ss_family == AF_INET6) - stableEndpoint6 = addr; - } + const std::vector *upstreamStableEndpoints = _upstreams.get(p->address()); + if ((upstreamStableEndpoints)&&(upstreamStableEndpoints->size() > 0)) { + if (!p->doPingAndKeepalive(_now,AF_INET)) { + for(unsigned long k=0,ptr=(unsigned long)RR->node->prng();k<(unsigned long)upstreamStableEndpoints->size();++k) { + const InetAddress &addr = (*upstreamStableEndpoints)[ptr++ % upstreamStableEndpoints->size()]; + if (addr.ss_family == AF_INET) { + p->sendHELLO(InetAddress(),addr,_now); + break; } - break; } } - - // We keep connections to upstream peers alive forever. - bool needToContactIndirect = true; - if (p->doPingAndKeepalive(_now,AF_INET)) { - needToContactIndirect = false; - } else { - if (stableEndpoint4) { - needToContactIndirect = false; - p->sendHELLO(InetAddress(),stableEndpoint4,_now); - } - } - if (p->doPingAndKeepalive(_now,AF_INET6)) { - needToContactIndirect = false; - } else { - if (stableEndpoint6) { - needToContactIndirect = false; - p->sendHELLO(InetAddress(),stableEndpoint6,_now); + if (!p->doPingAndKeepalive(_now,AF_INET6)) { + for(unsigned long k=0,ptr=(unsigned long)RR->node->prng();k<(unsigned long)upstreamStableEndpoints->size();++k) { + const InetAddress &addr = (*upstreamStableEndpoints)[ptr++ % upstreamStableEndpoints->size()]; + if (addr.ss_family == AF_INET6) { + p->sendHELLO(InetAddress(),addr,_now); + break; + } } } - - // If we don't have a direct path or a static endpoint, send something indirectly to find one. - if (needToContactIndirect) { - Packet outp(p->address(),RR->identity.address(),Packet::VERB_NOP); - RR->sw->send(outp,true); - } - lastReceiveFromUpstream = std::max(p->lastReceive(),lastReceiveFromUpstream); } else if (p->isActive(_now)) { - // Normal nodes get their preferred link kept alive if the node has generated frame traffic recently p->doPingAndKeepalive(_now,-1); } } private: const RuntimeEnvironment *RR; - const std::vector
&_upstreams; uint64_t _now; - World _world; + Hashtable< Address,std::vector > _upstreams; }; ZT_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline) @@ -263,7 +236,7 @@ ZT_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextB } // Do pings and keepalives - _PingPeersThatNeedPing pfunc(RR,upstreams,now); + _PingPeersThatNeedPing pfunc(RR,now); RR->topology->eachPeer<_PingPeersThatNeedPing &>(pfunc); // Update online status, post status change as event @@ -368,8 +341,8 @@ uint64_t Node::address() const void Node::status(ZT_NodeStatus *status) const { status->address = RR->identity.address().toInt(); - status->worldId = RR->topology->worldId(); - status->worldTimestamp = RR->topology->worldTimestamp(); + status->worldId = RR->topology->planetWorldId(); + status->worldTimestamp = RR->topology->planetWorldTimestamp(); status->publicIdentity = RR->publicIdentityStr.c_str(); status->secretIdentity = RR->secretIdentityStr.c_str(); status->relayPolicy = _relayPolicy; @@ -401,7 +374,7 @@ ZT_PeerList *Node::peers() const p->versionRev = -1; } p->latency = pi->second->latency(); - p->role = RR->topology->isRoot(pi->second->identity()) ? ZT_PEER_ROLE_ROOT : (RR->topology->isUpstream(pi->second->identity()) ? ZT_PEER_ROLE_UPSTREAM : ZT_PEER_ROLE_LEAF); + p->role = RR->topology->role(pi->second->identity().address()); std::vector< std::pair< SharedPtr,bool > > paths(pi->second->paths(_now)); SharedPtr bestp(pi->second->getBestPath(_now,false)); @@ -488,11 +461,6 @@ int Node::sendUserMessage(uint64_t dest,uint64_t typeId,const void *data,unsigne return 0; } -void Node::setRole(uint64_t ztAddress,ZT_PeerRole role) -{ - RR->topology->setUpstream(Address(ztAddress),(role == ZT_PEER_ROLE_UPSTREAM)); -} - void Node::setNetconfMaster(void *networkControllerInstance) { RR->localNetworkController = reinterpret_cast(networkControllerInstance); @@ -1016,13 +984,6 @@ int ZT_Node_sendUserMessage(ZT_Node *node,uint64_t dest,uint64_t typeId,const vo } } -void ZT_Node_setRole(ZT_Node *node,uint64_t ztAddress,ZT_PeerRole role) -{ - try { - reinterpret_cast(node)->setRole(ztAddress,role); - } catch ( ... ) {} -} - void ZT_Node_setNetconfMaster(ZT_Node *node,void *networkControllerInstance) { try { diff --git a/node/Node.hpp b/node/Node.hpp index d7b039b8..4c070014 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -105,7 +105,6 @@ public: int addLocalInterfaceAddress(const struct sockaddr_storage *addr); void clearLocalInterfaceAddresses(); int sendUserMessage(uint64_t dest,uint64_t typeId,const void *data,unsigned int len); - void setRole(uint64_t ztAddress,ZT_PeerRole role); void setNetconfMaster(void *networkControllerInstance); ZT_ResultCode circuitTestBegin(ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *)); void circuitTestEnd(ZT_CircuitTest *test); diff --git a/node/Peer.cpp b/node/Peer.cpp index 2ef139e1..40356034 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -37,9 +37,6 @@ namespace ZeroTier { -// Used to send varying values for NAT keepalive -static uint32_t _natKeepaliveBuf = 0; - Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Identity &peerIdentity) : _lastReceive(0), _lastNontrivialReceive(0), @@ -355,8 +352,8 @@ void Peer::sendHELLO(const InetAddress &localAddr,const InetAddress &atAddress,u outp.append(now); RR->identity.serialize(outp,false); atAddress.serialize(outp); - outp.append((uint64_t)RR->topology->worldId()); - outp.append((uint64_t)RR->topology->worldTimestamp()); + outp.append((uint64_t)RR->topology->planetWorldId()); + outp.append((uint64_t)RR->topology->planetWorldTimestamp()); RR->node->expectReplyTo(outp.packetId()); outp.armor(_key,false); // HELLO is sent in the clear RR->node->putPacket(localAddr,atAddress,outp.data(),outp.size()); @@ -401,12 +398,9 @@ bool Peer::doPingAndKeepalive(uint64_t now,int inetAddressFamily) } if (bestp >= 0) { - if ((now - _paths[bestp].lastReceive) >= ZT_PEER_PING_PERIOD) { + if ( ((now - _paths[bestp].lastReceive) >= ZT_PEER_PING_PERIOD) || (_paths[bestp].path->needsHeartbeat(now)) ) { attemptToContactAt(_paths[bestp].path->localAddress(),_paths[bestp].path->address(),now); _paths[bestp].path->sent(now); - } else if (_paths[bestp].path->needsHeartbeat(now)) { - _natKeepaliveBuf += (uint32_t)((now * 0x9e3779b1) >> 1); // tumble this around to send constantly varying (meaningless) payloads - _paths[bestp].path->send(RR,&_natKeepaliveBuf,sizeof(_natKeepaliveBuf),now); } return true; } else { diff --git a/node/Switch.cpp b/node/Switch.cpp index 7c94d438..04624f03 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -718,7 +718,7 @@ bool Switch::_trySend(const Packet &packet,bool encrypt) * go somewhere. */ SharedPtr viaPath(peer->getBestPath(now,false)); - if ( (viaPath) && (!viaPath->alive(now)) && (!RR->topology->isRoot(peer->identity())) ) { + if ( (viaPath) && (!viaPath->alive(now)) && (!RR->topology->isUpstream(peer->identity())) ) { if ((now - viaPath->lastOut()) > std::max((now - viaPath->lastIn()) * 4,(uint64_t)ZT_PATH_MIN_REACTIVATE_INTERVAL)) peer->attemptToContactAt(viaPath->localAddress(),viaPath->address(),now); viaPath.zero(); diff --git a/node/Topology.cpp b/node/Topology.cpp index bf51b585..be6807da 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -48,33 +48,22 @@ Topology::Topology(const RuntimeEnvironment *renv) : _trustedPathCount(0), _amRoot(false) { - // Get cached world if present - std::string dsWorld(RR->node->dataStoreGet("world")); - World cachedWorld; - if (dsWorld.length() > 0) { - try { - Buffer dswtmp(dsWorld.data(),(unsigned int)dsWorld.length()); - cachedWorld.deserialize(dswtmp,0); - } catch ( ... ) { - cachedWorld = World(); // clear if cached world is invalid - } - } - - // Use default or cached world depending on which is shinier - World defaultWorld; + World defaultPlanet; { Buffer wtmp(ZT_DEFAULT_WORLD,ZT_DEFAULT_WORLD_LENGTH); - defaultWorld.deserialize(wtmp,0); // throws on error, which would indicate a bad static variable up top + defaultPlanet.deserialize(wtmp,0); // throws on error, which would indicate a bad static variable up top } - if (cachedWorld.shouldBeReplacedBy(defaultWorld,false)) { - _setWorld(defaultWorld); - if (dsWorld.length() > 0) - RR->node->dataStoreDelete("world"); - } else _setWorld(cachedWorld); -} + addWorld(defaultPlanet,false); -Topology::~Topology() -{ + try { + World cachedPlanet; + std::string buf(RR->node->dataStoreGet("planet")); + if (buf.length() > 0) { + Buffer dswtmp(buf.data(),(unsigned int)buf.length()); + cachedPlanet.deserialize(dswtmp,0); + } + addWorld(cachedPlanet,false); + } catch ( ... ) {} } SharedPtr Topology::addPeer(const SharedPtr &peer) @@ -161,15 +150,14 @@ SharedPtr Topology::getUpstreamPeer(const Address *avoid,unsigned int avoi Mutex::Lock _l(_lock); if (_amRoot) { - /* If I am a root server, the "best" root server is the one whose address - * is numerically greater than mine (with wrap at top of list). This - * causes packets searching for a route to pretty much literally - * circumnavigate the globe rather than bouncing between just two. */ - - for(unsigned long p=0;p<_rootAddresses.size();++p) { - if (_rootAddresses[p] == RR->identity.address()) { - for(unsigned long q=1;q<_rootAddresses.size();++q) { - const SharedPtr *const nextsn = _peers.get(_rootAddresses[(p + q) % _rootAddresses.size()]); + /* If I am a root, pick another root that isn't mine and that + * has a numerically greater ID. This causes packets to roam + * around the top rather than bouncing between just two. */ + + for(unsigned long p=0;p<_upstreamAddresses.size();++p) { + if (_upstreamAddresses[p] == RR->identity.address()) { + for(unsigned long q=1;q<_upstreamAddresses.size();++q) { + const SharedPtr *const nextsn = _peers.get(_upstreamAddresses[(p + q) % _upstreamAddresses.size()]); if ((nextsn)&&((*nextsn)->hasActiveDirectPath(now))) return *nextsn; } @@ -178,8 +166,7 @@ SharedPtr Topology::getUpstreamPeer(const Address *avoid,unsigned int avoi } } else { - /* Otherwise pick the best upstream from among roots and any other - * designated upstreams that we trust. */ + /* Otherwise pick the bestest looking upstream */ unsigned int bestQualityOverall = ~((unsigned int)0); unsigned int bestQualityNotAvoid = ~((unsigned int)0); @@ -219,82 +206,112 @@ SharedPtr Topology::getUpstreamPeer(const Address *avoid,unsigned int avoi return SharedPtr(); } -bool Topology::isRoot(const Identity &id) const -{ - Mutex::Lock _l(_lock); - return (std::find(_rootAddresses.begin(),_rootAddresses.end(),id.address()) != _rootAddresses.end()); -} - bool Topology::isUpstream(const Identity &id) const { Mutex::Lock _l(_lock); return (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),id.address()) != _upstreamAddresses.end()); } -void Topology::setUpstream(const Address &a,bool upstream) +ZT_PeerRole Topology::role(const Address &ztaddr) const { - bool needWhois = false; - { - Mutex::Lock _l(_lock); - if (std::find(_rootAddresses.begin(),_rootAddresses.end(),a) == _rootAddresses.end()) { - if (upstream) { - if (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),a) == _upstreamAddresses.end()) { - _upstreamAddresses.push_back(a); - const SharedPtr *p = _peers.get(a); - if (!p) { - const Identity id(_getIdentity(a)); - if (id) { - _peers.set(a,SharedPtr(new Peer(RR,RR->identity,id))); - } else { - needWhois = true; // need to do this later due to _lock - } - } - } - } else { - std::vector
ua; - for(std::vector
::iterator i(_upstreamAddresses.begin());i!=_upstreamAddresses.end();++i) { - if (a != *i) - ua.push_back(*i); - } - _upstreamAddresses.swap(ua); - } + Mutex::Lock _l(_lock); + if (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),ztaddr) != _upstreamAddresses.end()) { + for(std::vector::const_iterator i(_planet.roots().begin());i!=_planet.roots().end();++i) { + if (i->identity.address() == ztaddr) + return ZT_PEER_ROLE_ROOT; } + return ZT_PEER_ROLE_UPSTREAM; } - if (needWhois) - RR->sw->requestWhois(a); + return ZT_PEER_ROLE_LEAF; } bool Topology::isProhibitedEndpoint(const Address &ztaddr,const InetAddress &ipaddr) const { Mutex::Lock _l(_lock); - if (std::find(_rootAddresses.begin(),_rootAddresses.end(),ztaddr) != _rootAddresses.end()) { - for(std::vector::const_iterator r(_world.roots().begin());r!=_world.roots().end();++r) { + // For roots the only permitted addresses are those defined. This adds just a little + // bit of extra security against spoofing, replaying, etc. + if (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),ztaddr) != _upstreamAddresses.end()) { + for(std::vector::const_iterator r(_planet.roots().begin());r!=_planet.roots().end();++r) { for(std::vector::const_iterator e(r->stableEndpoints.begin());e!=r->stableEndpoints.end();++e) { if (ipaddr.ipsEqual(*e)) return false; } } + for(std::vector::const_iterator m(_moons.begin());m!=_moons.end();++m) { + for(std::vector::const_iterator r(m->roots().begin());r!=m->roots().end();++r) { + for(std::vector::const_iterator e(r->stableEndpoints.begin());e!=r->stableEndpoints.end();++e) { + if (ipaddr.ipsEqual(*e)) + return false; + } + } + } return true; } return false; } -bool Topology::worldUpdateIfValid(const World &newWorld) +bool Topology::addWorld(const World &newWorld,bool updateOnly) { + if ((newWorld.type() != World::TYPE_PLANET)&&(newWorld.type() != World::TYPE_MOON)) + return false; + Mutex::Lock _l(_lock); - if (_world.shouldBeReplacedBy(newWorld,true)) { - _setWorld(newWorld); - try { - Buffer dswtmp; - newWorld.serialize(dswtmp,false); - RR->node->dataStorePut("world",dswtmp.data(),dswtmp.size(),false); - } catch ( ... ) { - RR->node->dataStoreDelete("world"); + + World *existing = (World *)0; + switch(newWorld.type()) { + case World::TYPE_PLANET: + existing = &_planet; + break; + case World::TYPE_MOON: + for(std::vector< World >::iterator m(_moons.begin());m!=_moons.end();++m) { + if (m->id() == newWorld.id()) { + existing = &(*m); + break; + } + } + break; + default: + return false; + } + + if (existing) { + if (existing->shouldBeReplacedBy(newWorld)) + *existing = newWorld; + else return false; + } else if ((newWorld.type() == World::TYPE_MOON)&&(!updateOnly)) { + _moons.push_back(newWorld); + existing = &(_moons.back()); + } else return false; + + char savePath[64]; + if (existing->type() == World::TYPE_MOON) + Utils::snprintf(savePath,sizeof(savePath),"moons.d/%.16llx",existing->id()); + else Utils::scopy(savePath,sizeof(savePath),"planet"); + try { + Buffer dswtmp; + existing->serialize(dswtmp,false); + RR->node->dataStorePut(savePath,dswtmp.data(),dswtmp.size(),false); + } catch ( ... ) { + RR->node->dataStoreDelete(savePath); + } + + _upstreamAddresses.clear(); + _amRoot = false; + for(std::vector::const_iterator i(_planet.roots().begin());i!=_planet.roots().end();++i) { + if (i->identity == RR->identity) + _amRoot = true; + else _upstreamAddresses.push_back(i->identity.address()); + } + for(std::vector::const_iterator m(_moons.begin());m!=_moons.end();++m) { + for(std::vector::const_iterator i(m->roots().begin());i!=m->roots().end();++i) { + if (i->identity == RR->identity) + _amRoot = true; + else _upstreamAddresses.push_back(i->identity.address()); } - return true; } + return false; } @@ -334,34 +351,4 @@ Identity Topology::_getIdentity(const Address &zta) return Identity(); } -void Topology::_setWorld(const World &newWorld) -{ - // assumed _lock is locked (or in constructor) - - std::vector
ua; - for(std::vector
::iterator a(_upstreamAddresses.begin());a!=_upstreamAddresses.end();++a) { - if (std::find(_rootAddresses.begin(),_rootAddresses.end(),*a) == _rootAddresses.end()) - ua.push_back(*a); - } - - _world = newWorld; - _rootAddresses.clear(); - _amRoot = false; - - for(std::vector::const_iterator r(_world.roots().begin());r!=_world.roots().end();++r) { - _rootAddresses.push_back(r->identity.address()); - if (std::find(ua.begin(),ua.end(),r->identity.address()) == ua.end()) - ua.push_back(r->identity.address()); - if (r->identity.address() == RR->identity.address()) { - _amRoot = true; - } else { - SharedPtr *rp = _peers.get(r->identity.address()); - if (!rp) - _peers.set(r->identity.address(),SharedPtr(new Peer(RR,RR->identity,r->identity))); - } - } - - _upstreamAddresses.swap(ua); -} - } // namespace ZeroTier diff --git a/node/Topology.hpp b/node/Topology.hpp index 90ad7083..47981248 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -50,7 +50,6 @@ class Topology { public: Topology(const RuntimeEnvironment *renv); - ~Topology(); /** * Add a peer to database @@ -141,12 +140,6 @@ public: */ SharedPtr getUpstreamPeer(const Address *avoid,unsigned int avoidCount,bool strictAvoid); - /** - * @param id Identity to check - * @return True if this is a designated root server in this world - */ - bool isRoot(const Identity &id) const; - /** * @param id Identity to check * @return True if this is a root server or a network preferred relay from one of our networks @@ -154,14 +147,10 @@ public: bool isUpstream(const Identity &id) const; /** - * Set whether or not an address is upstream - * - * If the address is a root this does nothing, since roots are fixed. - * - * @param a Target address - * @param upstream New upstream status + * @param ztaddr ZeroTier address + * @return Peer role for this device */ - void setUpstream(const Address &a,bool upstream); + ZT_PeerRole role(const Address &ztaddr) const; /** * Check for prohibited endpoints @@ -179,6 +168,30 @@ public: */ bool isProhibitedEndpoint(const Address &ztaddr,const InetAddress &ipaddr) const; + /** + * @param eps Hash table to fill with addresses and their stable endpoints + */ + inline void getUpstreamStableEndpoints(Hashtable< Address,std::vector > &eps) const + { + Mutex::Lock _l(_lock); + for(std::vector::const_iterator i(_planet.roots().begin());i!=_planet.roots().end();++i) { + std::vector &ips = eps[i->identity.address()]; + for(std::vector::const_iterator j(i->stableEndpoints.begin());j!=i->stableEndpoints.end();++j) { + if (std::find(ips.begin(),ips.end(),*j) == ips.end()) + ips.push_back(*j); + } + } + for(std::vector::const_iterator m(_moons.begin());m!=_moons.end();++m) { + for(std::vector::const_iterator i(m->roots().begin());i!=m->roots().end();++i) { + std::vector &ips = eps[i->identity.address()]; + for(std::vector::const_iterator j(i->stableEndpoints.begin());j!=i->stableEndpoints.end();++j) { + if (std::find(ips.begin(),ips.end(),*j) == ips.end()) + ips.push_back(*j); + } + } + } + } + /** * @return Vector of active upstream addresses (including roots) */ @@ -189,37 +202,38 @@ public: } /** - * @return Current World (copy) + * @return Current planet */ - inline World world() const + inline World planet() const { Mutex::Lock _l(_lock); - return _world; + return _planet; } /** - * @return Current world ID + * @return Current planet's world ID */ - inline uint64_t worldId() const + inline uint64_t planetWorldId() const { - return _world.id(); // safe to read without lock, and used from within eachPeer() so don't lock + return _planet.id(); // safe to read without lock, and used from within eachPeer() so don't lock } /** - * @return Current world timestamp + * @return Current planet's world timestamp */ - inline uint64_t worldTimestamp() const + inline uint64_t planetWorldTimestamp() const { - return _world.timestamp(); // safe to read without lock, and used from within eachPeer() so don't lock + return _planet.timestamp(); // safe to read without lock, and used from within eachPeer() so don't lock } /** * Validate new world and update if newer and signature is okay * - * @param newWorld Potential new world definition revision - * @return True if an update actually occurred + * @param newWorld A new or updated planet or moon to learn + * @param updateOnly If true only update currently known worlds + * @return True if it was valid and newer than current (or totally new for moons) */ - bool worldUpdateIfValid(const World &newWorld); + bool addWorld(const World &newWorld,bool updateOnly); /** * Clean and flush database @@ -284,9 +298,9 @@ public: } /** - * @return True if I am a root server in the current World + * @return True if I am a root server in a planet or moon */ - inline bool amRoot() const throw() { return _amRoot; } + inline bool amRoot() const { return _amRoot; } /** * Get the outbound trusted path ID for a physical address, or 0 if none @@ -339,7 +353,6 @@ public: private: Identity _getIdentity(const Address &zta); - void _setWorld(const World &newWorld); const RuntimeEnvironment *const RR; @@ -347,14 +360,14 @@ private: InetAddress _trustedPathNetworks[ZT_MAX_TRUSTED_PATHS]; unsigned int _trustedPathCount; - World _world; + World _planet; + std::vector< World > _moons; Hashtable< Address,SharedPtr > _peers; Hashtable< Path::HashKey,SharedPtr > _paths; - std::vector< Address > _upstreamAddresses; // includes roots - std::vector< Address > _rootAddresses; // only roots - bool _amRoot; // am I a root? + std::vector< Address > _upstreamAddresses; // includes root addresses of both planets and moons + bool _amRoot; // am I a root in a planet or moon? Mutex _lock; }; diff --git a/node/World.hpp b/node/World.hpp index 2f1edb00..c4682a69 100644 --- a/node/World.hpp +++ b/node/World.hpp @@ -48,16 +48,6 @@ */ #define ZT_WORLD_MAX_SERIALIZED_LENGTH (((1024 + (32 * ZT_WORLD_MAX_STABLE_ENDPOINTS_PER_ROOT)) * ZT_WORLD_MAX_ROOTS) + ZT_C25519_PUBLIC_KEY_LEN + ZT_C25519_SIGNATURE_LEN + 128) -/** - * World ID indicating null / empty World object - */ -#define ZT_WORLD_ID_NULL 0 - -/** - * World ID for a test network with ephemeral or temporary roots - */ -#define ZT_WORLD_ID_TESTNET 1 - /** * World ID for Earth * @@ -90,15 +80,23 @@ namespace ZeroTier { * orbits, the Moon (about 1.3 light seconds), and nearby Lagrange points. A * world ID for Mars and nearby space is defined but not yet used, and a test * world ID is provided for testing purposes. - * - * If you absolutely must run your own "unofficial" ZeroTier network, please - * define your world IDs above 0xffffffff (4294967295). Code to make a World - * is in mkworld.cpp in the parent directory and must be edited to change - * settings. */ class World { public: + /** + * World type -- do not change IDs + */ + enum Type + { + TYPE_NULL = 0, + TYPE_PLANET = 1, // Planets, of which there is currently one (Earth) + TYPE_MOON = 127 // Moons, which are user-created and many + }; + + /** + * Upstream server definition in world/moon + */ struct Root { Identity identity; @@ -113,45 +111,44 @@ public: * Construct an empty / null World */ World() : - _id(ZT_WORLD_ID_NULL), - _ts(0) {} + _id(0), + _ts(0), + _type(TYPE_NULL) {} /** * @return Root servers for this world and their stable endpoints */ - inline const std::vector &roots() const throw() { return _roots; } + inline const std::vector &roots() const { return _roots; } + + /** + * @return World type: planet or moon + */ + inline Type type() const { return _type; } /** * @return World unique identifier */ - inline uint64_t id() const throw() { return _id; } + inline uint64_t id() const { return _id; } /** * @return World definition timestamp */ - inline uint64_t timestamp() const throw() { return _ts; } + inline uint64_t timestamp() const { return _ts; } /** * Check whether a world update should replace this one * - * A new world update is valid if it is for the same world ID, is newer, - * and is signed by the current world's signing key. If this world object - * is null, it can always be updated. - * * @param update Candidate update - * @param fullSignatureCheck Perform full cryptographic signature check (true == yes, false == skip) - * @return True if update is newer than current and is properly signed + * @return True if update is newer than current, matches its ID and type, and is properly signed (or if current is NULL) */ - inline bool shouldBeReplacedBy(const World &update,bool fullSignatureCheck) + inline bool shouldBeReplacedBy(const World &update) { - if (_id == ZT_WORLD_ID_NULL) + if ((_id == 0)||(_type == TYPE_NULL)) return true; - if ((_id == update._id)&&(_ts < update._ts)) { - if (fullSignatureCheck) { - Buffer tmp; - update.serialize(tmp,true); - return C25519::verify(_updatesMustBeSignedBy,tmp.data(),tmp.size(),update._signature); - } else return true; + if ((_id == update._id)&&(_ts < update._ts)&&(_type == update._type)) { + Buffer tmp; + update.serialize(tmp,true); + return C25519::verify(_updatesMustBeSignedBy,tmp.data(),tmp.size(),update._signature); } return false; } @@ -159,14 +156,14 @@ public: /** * @return True if this World is non-empty */ - inline operator bool() const throw() { return (_id != ZT_WORLD_ID_NULL); } + inline operator bool() const { return (_type != TYPE_NULL); } template inline void serialize(Buffer &b,bool forSign = false) const { if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL); - b.append((uint8_t)0x01); + b.append((uint8_t)_type); b.append((uint64_t)_id); b.append((uint64_t)_ts); b.append(_updatesMustBeSignedBy.data,ZT_C25519_PUBLIC_KEY_LEN); @@ -190,14 +187,19 @@ public: _roots.clear(); - if (b[p++] != 0x01) - throw std::invalid_argument("invalid object type"); + switch((Type)b[p++]) { + case TYPE_NULL: _type = TYPE_NULL; break; // shouldn't ever really happen in serialized data but it's not invalid + case TYPE_PLANET: _type = TYPE_PLANET; break; + case TYPE_MOON: _type = TYPE_MOON; break; + default: + throw std::invalid_argument("invalid world type"); + } _id = b.template at(p); p += 8; _ts = b.template at(p); p += 8; memcpy(_updatesMustBeSignedBy.data,b.field(p,ZT_C25519_PUBLIC_KEY_LEN),ZT_C25519_PUBLIC_KEY_LEN); p += ZT_C25519_PUBLIC_KEY_LEN; memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); p += ZT_C25519_SIGNATURE_LEN; - unsigned int numRoots = b[p++]; + const unsigned int numRoots = (unsigned int)b[p++]; if (numRoots > ZT_WORLD_MAX_ROOTS) throw std::invalid_argument("too many roots in World"); for(unsigned int k=0;k _roots; diff --git a/service/OneService.cpp b/service/OneService.cpp index 2932c605..6d9effa1 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -422,7 +422,7 @@ public: try { std::string authToken; { - std::string authTokenPath(_homePath + ZT_PATH_SEPARATOR_S + "authtoken.secret"); + std::string authTokenPath(_homePath + ZT_PATH_SEPARATOR_S "authtoken.secret"); if (!OSUtils::readFile(authTokenPath.c_str(),authToken)) { unsigned char foo[24]; Utils::getSecureRandom(foo,sizeof(foo)); @@ -442,7 +442,8 @@ public: authToken = _trimString(authToken); // Clean up any legacy files if present - OSUtils::rm((_homePath + ZT_PATH_SEPARATOR_S + "peers.save").c_str()); + OSUtils::rm((_homePath + ZT_PATH_SEPARATOR_S "peers.save").c_str()); + OSUtils::rm((_homePath + ZT_PATH_SEPARATOR_S "world").c_str()); { struct ZT_Node_Callbacks cb; @@ -465,7 +466,7 @@ public: unsigned int trustedPathCount = 0; // Old style "trustedpaths" flat file -- will eventually go away - FILE *trustpaths = fopen((_homePath + ZT_PATH_SEPARATOR_S + "trustedpaths").c_str(),"r"); + FILE *trustpaths = fopen((_homePath + ZT_PATH_SEPARATOR_S "trustedpaths").c_str(),"r"); if (trustpaths) { char buf[1024]; while ((fgets(buf,sizeof(buf),trustpaths))&&(trustedPathCount < ZT_MAX_TRUSTED_PATHS)) { @@ -493,7 +494,7 @@ public: // Read local config file Mutex::Lock _l2(_localConfig_m); std::string lcbuf; - if (OSUtils::readFile((_homePath + ZT_PATH_SEPARATOR_S + "local.conf").c_str(),lcbuf)) { + if (OSUtils::readFile((_homePath + ZT_PATH_SEPARATOR_S "local.conf").c_str(),lcbuf)) { try { _localConfig = OSUtils::jsonParse(lcbuf); if (!_localConfig.is_object()) { @@ -581,7 +582,7 @@ public: // Write file containing primary port to be read by CLIs, etc. char portstr[64]; Utils::snprintf(portstr,sizeof(portstr),"%u",_ports[0]); - OSUtils::writeFile((_homePath + ZT_PATH_SEPARATOR_S + "zerotier-one.port").c_str(),std::string(portstr)); + OSUtils::writeFile((_homePath + ZT_PATH_SEPARATOR_S "zerotier-one.port").c_str(),std::string(portstr)); // Attempt to bind to a secondary port chosen from our ZeroTier address. // This exists because there are buggy NATs out there that fail if more @@ -641,8 +642,8 @@ public: _node->setNetconfMaster((void *)_controller); #ifdef ZT_ENABLE_CLUSTER - if (OSUtils::fileExists((_homePath + ZT_PATH_SEPARATOR_S + "cluster").c_str())) { - _clusterDefinition = new ClusterDefinition(_node->address(),(_homePath + ZT_PATH_SEPARATOR_S + "cluster").c_str()); + if (OSUtils::fileExists((_homePath + ZT_PATH_SEPARATOR_S "cluster").c_str())) { + _clusterDefinition = new ClusterDefinition(_node->address(),(_homePath + ZT_PATH_SEPARATOR_S "cluster").c_str()); if (_clusterDefinition->size() > 0) { std::vector members(_clusterDefinition->members()); for(std::vector::iterator m(members.begin());m!=members.end();++m) { @@ -689,12 +690,12 @@ public: } #endif - _controlPlane = new ControlPlane(this,_node,(_homePath + ZT_PATH_SEPARATOR_S + "ui").c_str()); + _controlPlane = new ControlPlane(this,_node,(_homePath + ZT_PATH_SEPARATOR_S "ui").c_str()); _controlPlane->addAuthToken(authToken.c_str()); _controlPlane->setController(_controller); { // Remember networks from previous session - std::vector networksDotD(OSUtils::listDirectory((_homePath + ZT_PATH_SEPARATOR_S + "networks.d").c_str())); + std::vector networksDotD(OSUtils::listDirectory((_homePath + ZT_PATH_SEPARATOR_S "networks.d").c_str())); for(std::vector::iterator f(networksDotD.begin());f!=networksDotD.end();++f) { std::size_t dot = f->find_last_of('.'); if ((dot == 16)&&(f->substr(16) == ".conf")) @@ -919,9 +920,6 @@ public: if ((nstr.length() == ZT_ADDRESS_LENGTH_HEX)&&(v.value().is_object())) { const Address ztaddr(nstr.c_str()); if (ztaddr) { - const std::string rstr(OSUtils::jsonString(v.value()["role"],"")); - _node->setRole(ztaddr.toInt(),((rstr == "upstream")||(rstr == "UPSTREAM")) ? ZT_PEER_ROLE_UPSTREAM : ZT_PEER_ROLE_LEAF); - const uint64_t ztaddr2 = ztaddr.toInt(); std::vector &v4h = _v4Hints[ztaddr2]; std::vector &v6h = _v6Hints[ztaddr2]; diff --git a/service/README.md b/service/README.md index d2398643..5d54b923 100644 --- a/service/README.md +++ b/service/README.md @@ -19,7 +19,6 @@ Settings available in `local.conf` (this is not valid JSON, and JSON does not al }, "virtual": { /* Settings applied to ZeroTier virtual network devices (VL1) */ "##########": { /* 10-digit ZeroTier address */ - "role": "upstream"|"leaf", /* If upstream, define this as a trusted "federated root" (default is leaf) */ "try": [ "IP/port"/*,...*/ ], /* Hints on where to reach this peer if no upstreams/roots are online */ "blacklist": [ "NETWORK/bits"/*,...*/ ] /* Blacklist a physical path for only this peer. */ } diff --git a/world/mkworld.cpp b/world/mkworld.cpp index 061d6341..2e9e621f 100644 --- a/world/mkworld.cpp +++ b/world/mkworld.cpp @@ -53,11 +53,12 @@ using namespace ZeroTier; class WorldMaker : public World { public: - static inline World make(uint64_t id,uint64_t ts,const C25519::Public &sk,const std::vector &roots,const C25519::Pair &signWith) + static inline World make(World::Type t,uint64_t id,uint64_t ts,const C25519::Public &sk,const std::vector &roots,const C25519::Pair &signWith) { WorldMaker w; w._id = id; w._ts = ts; + w._type = t; w._updateSigningKey = sk; w._roots = roots; @@ -139,7 +140,7 @@ int main(int argc,char **argv) fprintf(stderr,"INFO: generating and signing id==%llu ts==%llu"ZT_EOL_S,(unsigned long long)id,(unsigned long long)ts); - World nw = WorldMaker::make(id,ts,currentKP.pub,roots,previousKP); + World nw = WorldMaker::make(World::TYPE_PLANET,id,ts,currentKP.pub,roots,previousKP); Buffer outtmp; nw.serialize(outtmp,false); -- cgit v1.2.3 From 0b3b994241161c996c8432a2fb25e47b0f84c359 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 27 Jan 2017 14:05:09 -0800 Subject: Relay policy can now be computed. --- include/ZeroTierOne.h | 24 ------------------------ node/Network.cpp | 1 - node/NetworkConfig.hpp | 2 -- node/Node.cpp | 22 +--------------------- node/Node.hpp | 3 --- node/Switch.cpp | 27 +++++---------------------- service/ControlPlane.cpp | 2 -- service/OneService.cpp | 9 +-------- service/README.md | 1 - 9 files changed, 7 insertions(+), 84 deletions(-) (limited to 'service/OneService.cpp') diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index f0235b9d..f75638f8 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -406,16 +406,6 @@ enum ZT_Event ZT_EVENT_USER_MESSAGE = 6 }; -/** - * Node relay policy - */ -enum ZT_RelayPolicy -{ - ZT_RELAY_POLICY_NEVER = 0, - ZT_RELAY_POLICY_TRUSTED = 1, - ZT_RELAY_POLICY_ALWAYS = 2 -}; - /** * User message used with ZT_EVENT_USER_MESSAGE */ @@ -476,11 +466,6 @@ typedef struct */ const char *secretIdentity; - /** - * Node relay policy - */ - enum ZT_RelayPolicy relayPolicy; - /** * True if some kind of connectivity appears available */ @@ -1718,15 +1703,6 @@ enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame( */ enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline); -/** - * Set node's relay policy - * - * @param node Node instance - * @param rp New relay policy - * @return OK(0) or error code - */ -enum ZT_ResultCode ZT_Node_setRelayPolicy(ZT_Node *node,enum ZT_RelayPolicy rp); - /** * Join a network * diff --git a/node/Network.cpp b/node/Network.cpp index 8b0f2055..ec1bcb33 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -1102,7 +1102,6 @@ void Network::requestConfiguration() rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_MAX_NETWORK_TAGS,(uint64_t)ZT_MAX_NETWORK_TAGS); rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_FLAGS,(uint64_t)0); rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_RULES_ENGINE_REV,(uint64_t)ZT_RULES_ENGINE_REVISION); - rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_RELAY_POLICY,(uint64_t)RR->node->relayPolicy()); if (ctrl == RR->identity.address()) { if (RR->localNetworkController) { diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp index a548e866..39087395 100644 --- a/node/NetworkConfig.hpp +++ b/node/NetworkConfig.hpp @@ -135,8 +135,6 @@ namespace ZeroTier { #define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_AUTH "a" // Network configuration meta-data flags #define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_FLAGS "f" -// Relay policy for this node -#define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_RELAY_POLICY "rp" // These dictionary keys are short so they don't take up much room. // By convention we use upper case for binary blobs, but it doesn't really matter. diff --git a/node/Node.cpp b/node/Node.cpp index df22e3f2..23271cca 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -53,8 +53,7 @@ Node::Node(void *uptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now) : _prngStreamPtr(0), _now(now), _lastPingCheck(0), - _lastHousekeepingRun(0), - _relayPolicy(ZT_RELAY_POLICY_TRUSTED) + _lastHousekeepingRun(0) { if (callbacks->version != 0) throw std::runtime_error("callbacks struct version mismatch"); @@ -102,9 +101,6 @@ Node::Node(void *uptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now) : throw; } - if (RR->topology->amRoot()) - _relayPolicy = ZT_RELAY_POLICY_ALWAYS; - postEvent(ZT_EVENT_UP); } @@ -282,12 +278,6 @@ ZT_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextB return ZT_RESULT_OK; } -ZT_ResultCode Node::setRelayPolicy(enum ZT_RelayPolicy rp) -{ - _relayPolicy = rp; - return ZT_RESULT_OK; -} - ZT_ResultCode Node::join(uint64_t nwid,void *uptr) { Mutex::Lock _l(_networks_m); @@ -345,7 +335,6 @@ void Node::status(ZT_NodeStatus *status) const status->worldTimestamp = RR->topology->planetWorldTimestamp(); status->publicIdentity = RR->publicIdentityStr.c_str(); status->secretIdentity = RR->secretIdentityStr.c_str(); - status->relayPolicy = _relayPolicy; status->online = _online ? 1 : 0; } @@ -860,15 +849,6 @@ enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,uint64_t now,vol } } -enum ZT_ResultCode ZT_Node_setRelayPolicy(ZT_Node *node,enum ZT_RelayPolicy rp) -{ - try { - return reinterpret_cast(node)->setRelayPolicy(rp); - } catch ( ... ) { - return ZT_RESULT_FATAL_ERROR_INTERNAL; - } -} - enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,void *uptr) { try { diff --git a/node/Node.hpp b/node/Node.hpp index 4c070014..662abcb4 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -91,7 +91,6 @@ public: unsigned int frameLength, volatile uint64_t *nextBackgroundTaskDeadline); ZT_ResultCode processBackgroundTasks(uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline); - ZT_ResultCode setRelayPolicy(enum ZT_RelayPolicy rp); ZT_ResultCode join(uint64_t nwid,void *uptr); ZT_ResultCode leave(uint64_t nwid,void **uptr); ZT_ResultCode multicastSubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi); @@ -197,7 +196,6 @@ public: inline int configureVirtualNetworkPort(uint64_t nwid,void **nuptr,ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nc) { return _cb.virtualNetworkConfigFunction(reinterpret_cast(this),_uPtr,nwid,nuptr,op,nc); } inline bool online() const throw() { return _online; } - inline ZT_RelayPolicy relayPolicy() const { return _relayPolicy; } #ifdef ZT_TRACE void postTrace(const char *module,unsigned int line,const char *fmt,...); @@ -298,7 +296,6 @@ private: uint64_t _now; uint64_t _lastPingCheck; uint64_t _lastHousekeepingRun; - ZT_RelayPolicy _relayPolicy; bool _online; }; diff --git a/node/Switch.cpp b/node/Switch.cpp index 04624f03..f935b7aa 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -105,17 +105,8 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from const Address destination(fragment.destination()); if (destination != RR->identity.address()) { - switch(RR->node->relayPolicy()) { - case ZT_RELAY_POLICY_ALWAYS: - break; - case ZT_RELAY_POLICY_TRUSTED: - if (!path->trustEstablished(now)) - return; - break; - // case ZT_RELAY_POLICY_NEVER: - default: - return; - } + if ( (!RR->topology->amRoot()) && (!path->trustEstablished(now)) ) + return; if (fragment.hops() < ZT_RELAY_MAX_HOPS) { fragment.incrementHops(); @@ -213,18 +204,10 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from //TRACE("<< %.16llx %s -> %s (size: %u)",(unsigned long long)packet->packetId(),source.toString().c_str(),destination.toString().c_str(),packet->size()); + if (destination != RR->identity.address()) { - switch(RR->node->relayPolicy()) { - case ZT_RELAY_POLICY_ALWAYS: - break; - case ZT_RELAY_POLICY_TRUSTED: - if (!path->trustEstablished(now)) - return; - break; - // case ZT_RELAY_POLICY_NEVER: - default: - return; - } + if ( (!RR->topology->amRoot()) && (!path->trustEstablished(now)) ) + return; Packet packet(data,len); diff --git a/service/ControlPlane.cpp b/service/ControlPlane.cpp index 86158a91..e5142f3e 100644 --- a/service/ControlPlane.cpp +++ b/service/ControlPlane.cpp @@ -391,7 +391,6 @@ unsigned int ControlPlane::handleRequest( "\t\"worldId\": %llu,\n" "\t\"worldTimestamp\": %llu,\n" "\t\"online\": %s,\n" - "\t\"relayPolicy\": \"%s\",\n" "\t\"tcpFallbackActive\": %s,\n" "\t\"versionMajor\": %d,\n" "\t\"versionMinor\": %d,\n" @@ -405,7 +404,6 @@ unsigned int ControlPlane::handleRequest( status.worldId, status.worldTimestamp, (status.online) ? "true" : "false", - ((status.relayPolicy == ZT_RELAY_POLICY_ALWAYS) ? "always" : ((status.relayPolicy == ZT_RELAY_POLICY_NEVER) ? "never" : "trusted")), (_svc->tcpFallbackActive()) ? "true" : "false", ZEROTIER_ONE_VERSION_MAJOR, ZEROTIER_ONE_VERSION_MINOR, diff --git a/service/OneService.cpp b/service/OneService.cpp index 6d9effa1..f6174d42 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -694,7 +694,7 @@ public: _controlPlane->addAuthToken(authToken.c_str()); _controlPlane->setController(_controller); - { // Remember networks from previous session + { // Load existing networks std::vector networksDotD(OSUtils::listDirectory((_homePath + ZT_PATH_SEPARATOR_S "networks.d").c_str())); for(std::vector::iterator f(networksDotD.begin());f!=networksDotD.end();++f) { std::size_t dot = f->find_last_of('.'); @@ -981,13 +981,6 @@ public: if (settings.is_object()) { _portMappingEnabled = OSUtils::jsonBool(settings["portMappingEnabled"],true); - const std::string rp(OSUtils::jsonString(settings["relayPolicy"],"")); - if ((rp == "always")||(rp == "ALWAYS")) - _node->setRelayPolicy(ZT_RELAY_POLICY_ALWAYS); - else if ((rp == "never")||(rp == "NEVER")) - _node->setRelayPolicy(ZT_RELAY_POLICY_NEVER); - else _node->setRelayPolicy(ZT_RELAY_POLICY_TRUSTED); - const std::string up(OSUtils::jsonString(settings["softwareUpdate"],ZT_SOFTWARE_UPDATE_DEFAULT)); const bool udist = OSUtils::jsonBool(settings["softwareUpdateDist"],false); if (((up == "apply")||(up == "download"))||(udist)) { diff --git a/service/README.md b/service/README.md index 5d54b923..d3bc5338 100644 --- a/service/README.md +++ b/service/README.md @@ -24,7 +24,6 @@ Settings available in `local.conf` (this is not valid JSON, and JSON does not al } }, "settings": { /* Other global settings */ - "relayPolicy": "trusted"|"always"|"never", /* Policy for relaying others' traffic (see below) */ "portMappingEnabled": true|false, /* If true (the default), try to use uPnP or NAT-PMP to map ports */ "softwareUpdate": "apply"|"download"|"disable", /* Automatically apply updates, just download, or disable built-in software updates */ "softwareUpdateDist": true|false, /* If true, distribute software updates (only really useful to ZeroTier, Inc. itself, default is false) */ -- cgit v1.2.3 From 9f7919f71f6b4326e73759923d2cf747affc0244 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 27 Jan 2017 15:27:26 -0800 Subject: Add comments to join ("orbit") moons. --- include/ZeroTierOne.h | 22 +++++++++ node/IncomingPacket.cpp | 3 +- node/Node.cpp | 49 ++++++++++++++++++-- node/Node.hpp | 2 + node/Peer.cpp | 9 +++- node/Topology.cpp | 120 ++++++++++++++++++++++++++++++++++++++++-------- node/Topology.hpp | 39 ++++++++++++++-- service/OneService.cpp | 8 ++++ 8 files changed, 222 insertions(+), 30 deletions(-) (limited to 'service/OneService.cpp') diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index f75638f8..6c50a0a6 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -1779,6 +1779,28 @@ enum ZT_ResultCode ZT_Node_multicastSubscribe(ZT_Node *node,uint64_t nwid,uint64 */ enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi); +/** + * Add or update a moon + * + * Moons are persisted in the data store in moons.d/, so this can persist + * across invocations if the contents of moon.d are scanned and orbit is + * called for each on startup. + * + * @param moonWorldId Moon's world ID + * @param len Length of moonWorld in bytes + * @return Error if moon was invalid or failed to be added + */ +enum ZT_ResultCode ZT_Node_orbit(ZT_Node *node,uint64_t moonWorldId); + +/** + * Remove a moon (does nothing if not present) + * + * @param node Node instance + * @param moonWorldId World ID of moon to remove + * @return Error if anything bad happened + */ +ZT_ResultCode ZT_Node_deorbit(ZT_Node *node,uint64_t moonWorldId); + /** * Get this node's 40-bit ZeroTier address * diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 28b845b4..93bf4590 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -444,7 +444,8 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr &p TRACE("%s(%s): OK(HELLO), version %u.%u.%u, latency %u, reported external address %s",source().toString().c_str(),_path->address().toString().c_str(),vMajor,vMinor,vRevision,latency,((externalSurfaceAddress) ? externalSurfaceAddress.toString().c_str() : "(none)")); - peer->addDirectLatencyMeasurment(latency); + if (!hops()) + peer->addDirectLatencyMeasurment(latency); peer->setRemoteVersion(vProto,vMajor,vMinor,vRevision); if ((externalSurfaceAddress)&&(hops() == 0)) diff --git a/node/Node.cpp b/node/Node.cpp index 23271cca..f5ee1f9d 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -168,26 +168,35 @@ public: inline void operator()(Topology &t,const SharedPtr &p) { - const std::vector *upstreamStableEndpoints = _upstreams.get(p->address()); - if ((upstreamStableEndpoints)&&(upstreamStableEndpoints->size() > 0)) { + const std::vector *const upstreamStableEndpoints = _upstreams.get(p->address()); + if (upstreamStableEndpoints) { + bool contacted = false; + if (!p->doPingAndKeepalive(_now,AF_INET)) { for(unsigned long k=0,ptr=(unsigned long)RR->node->prng();k<(unsigned long)upstreamStableEndpoints->size();++k) { const InetAddress &addr = (*upstreamStableEndpoints)[ptr++ % upstreamStableEndpoints->size()]; if (addr.ss_family == AF_INET) { p->sendHELLO(InetAddress(),addr,_now); + contacted = true; break; } } - } + } else contacted = true; + if (!p->doPingAndKeepalive(_now,AF_INET6)) { for(unsigned long k=0,ptr=(unsigned long)RR->node->prng();k<(unsigned long)upstreamStableEndpoints->size();++k) { const InetAddress &addr = (*upstreamStableEndpoints)[ptr++ % upstreamStableEndpoints->size()]; if (addr.ss_family == AF_INET6) { p->sendHELLO(InetAddress(),addr,_now); + contacted = true; break; } } - } + } else contacted = true; + + if (!contacted) + p->sendHELLO(InetAddress(),InetAddress(),_now); + lastReceiveFromUpstream = std::max(p->lastReceive(),lastReceiveFromUpstream); } else if (p->isActive(_now)) { p->doPingAndKeepalive(_now,-1); @@ -224,7 +233,7 @@ ZT_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextB for(std::vector< SharedPtr >::const_iterator n(needConfig.begin());n!=needConfig.end();++n) (*n)->requestConfiguration(); - // Run WHOIS on upstreams we don't know about + // Attempt to get identity for any unknown upstreams const std::vector
upstreams(RR->topology->upstreamAddresses()); for(std::vector
::const_iterator a(upstreams.begin());a!=upstreams.end();++a) { if (!RR->topology->getPeer(*a)) @@ -323,6 +332,18 @@ ZT_ResultCode Node::multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,u } else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND; } +ZT_ResultCode Node::orbit(uint64_t moonWorldId) +{ + RR->topology->addMoon(moonWorldId); + return ZT_RESULT_OK; +} + +ZT_ResultCode Node::deorbit(uint64_t moonWorldId) +{ + RR->topology->removeMoon(moonWorldId); + return ZT_RESULT_OK; +} + uint64_t Node::address() const { return RR->identity.address().toInt(); @@ -893,6 +914,24 @@ enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node,uint64_t nwid,uint } } +enum ZT_ResultCode ZT_Node_orbit(ZT_Node *node,uint64_t moonWorldId) +{ + try { + return reinterpret_cast(node)->orbit(moonWorldId); + } catch ( ... ) { + return ZT_RESULT_FATAL_ERROR_INTERNAL; + } +} + +ZT_ResultCode ZT_Node_deorbit(ZT_Node *node,uint64_t moonWorldId) +{ + try { + return reinterpret_cast(node)->deorbit(moonWorldId); + } catch ( ... ) { + return ZT_RESULT_FATAL_ERROR_INTERNAL; + } +} + uint64_t ZT_Node_address(ZT_Node *node) { return reinterpret_cast(node)->address(); diff --git a/node/Node.hpp b/node/Node.hpp index 662abcb4..3e742092 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -95,6 +95,8 @@ public: ZT_ResultCode leave(uint64_t nwid,void **uptr); ZT_ResultCode multicastSubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi); ZT_ResultCode multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi); + ZT_ResultCode orbit(uint64_t moonWorldId); + ZT_ResultCode deorbit(uint64_t moonWorldId); uint64_t address() const; void status(ZT_NodeStatus *status) const; ZT_PeerList *peers() const; diff --git a/node/Peer.cpp b/node/Peer.cpp index 441a5b33..50135b9f 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -366,8 +366,13 @@ void Peer::sendHELLO(const InetAddress &localAddr,const InetAddress &atAddress,u } RR->node->expectReplyTo(outp.packetId()); - outp.armor(_key,false); // HELLO is sent in the clear - RR->node->putPacket(localAddr,atAddress,outp.data(),outp.size()); + + if (atAddress) { + outp.armor(_key,false); + RR->node->putPacket(localAddr,atAddress,outp.data(),outp.size()); + } else { + RR->sw->send(outp,false); + } } void Peer::attemptToContactAt(const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now) diff --git a/node/Topology.cpp b/node/Topology.cpp index be6807da..38afacb0 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -48,13 +48,6 @@ Topology::Topology(const RuntimeEnvironment *renv) : _trustedPathCount(0), _amRoot(false) { - World defaultPlanet; - { - Buffer wtmp(ZT_DEFAULT_WORLD,ZT_DEFAULT_WORLD_LENGTH); - defaultPlanet.deserialize(wtmp,0); // throws on error, which would indicate a bad static variable up top - } - addWorld(defaultPlanet,false); - try { World cachedPlanet; std::string buf(RR->node->dataStoreGet("planet")); @@ -64,6 +57,13 @@ Topology::Topology(const RuntimeEnvironment *renv) : } addWorld(cachedPlanet,false); } catch ( ... ) {} + + World defaultPlanet; + { + Buffer wtmp(ZT_DEFAULT_WORLD,ZT_DEFAULT_WORLD_LENGTH); + defaultPlanet.deserialize(wtmp,0); // throws on error, which would indicate a bad static variable up top + } + addWorld(defaultPlanet,false); } SharedPtr Topology::addPeer(const SharedPtr &peer) @@ -287,7 +287,7 @@ bool Topology::addWorld(const World &newWorld,bool updateOnly) char savePath[64]; if (existing->type() == World::TYPE_MOON) - Utils::snprintf(savePath,sizeof(savePath),"moons.d/%.16llx",existing->id()); + Utils::snprintf(savePath,sizeof(savePath),"moons.d/%.16llx.moon",existing->id()); else Utils::scopy(savePath,sizeof(savePath),"planet"); try { Buffer dswtmp; @@ -297,22 +297,71 @@ bool Topology::addWorld(const World &newWorld,bool updateOnly) RR->node->dataStoreDelete(savePath); } - _upstreamAddresses.clear(); - _amRoot = false; - for(std::vector::const_iterator i(_planet.roots().begin());i!=_planet.roots().end();++i) { - if (i->identity == RR->identity) - _amRoot = true; - else _upstreamAddresses.push_back(i->identity.address()); + if (existing->type() == World::TYPE_MOON) { + std::vector
cm; + for(std::vector
::const_iterator m(_contacingMoons.begin());m!=_contacingMoons.end();++m) { + if (m->toInt() != ((existing->id() >> 24) & 0xffffffffffULL)) + cm.push_back(*m); + } + _contacingMoons.swap(cm); } + + _memoizeUpstreams(); + + return true; +} + +void Topology::addMoon(const uint64_t id) +{ + char savePath[64]; + Utils::snprintf(savePath,sizeof(savePath),"moons.d/%.16llx.moon",id); + + try { + std::string moonBin(RR->node->dataStoreGet(savePath)); + if (moonBin.length() > 1) { + Buffer wtmp(moonBin.data(),(unsigned int)moonBin.length()); + World w; + w.deserialize(wtmp); + if (w.type() == World::TYPE_MOON) { + addWorld(w,false); + return; + } + } + } catch ( ... ) {} + + { + const Address a(id >> 24); + Mutex::Lock _l(_lock); + if (std::find(_contacingMoons.begin(),_contacingMoons.end(),a) == _contacingMoons.end()) + _contacingMoons.push_back(a); + } + RR->node->dataStorePut(savePath,"\0",1,false); // persist that we want to be a member +} + +void Topology::removeMoon(const uint64_t id) +{ + Mutex::Lock _l(_lock); + + std::vector nm; for(std::vector::const_iterator m(_moons.begin());m!=_moons.end();++m) { - for(std::vector::const_iterator i(m->roots().begin());i!=m->roots().end();++i) { - if (i->identity == RR->identity) - _amRoot = true; - else _upstreamAddresses.push_back(i->identity.address()); + if (m->id() != id) { + nm.push_back(*m); + } else { + char savePath[64]; + Utils::snprintf(savePath,sizeof(savePath),"moons.d/%.16llx.moon",id); + RR->node->dataStoreDelete(savePath); } } + _moons.swap(nm); - return false; + std::vector
cm; + for(std::vector
::const_iterator m(_contacingMoons.begin());m!=_contacingMoons.end();++m) { + if (m->toInt() != ((id >> 24) & 0xffffffffffULL)) + cm.push_back(*m); + } + _contacingMoons.swap(cm); + + _memoizeUpstreams(); } void Topology::clean(uint64_t now) @@ -351,4 +400,37 @@ Identity Topology::_getIdentity(const Address &zta) return Identity(); } +void Topology::_memoizeUpstreams() +{ + // assumes _lock is locked + _upstreamAddresses.clear(); + _amRoot = false; + for(std::vector::const_iterator i(_planet.roots().begin());i!=_planet.roots().end();++i) { + if (i->identity == RR->identity) { + _amRoot = true; + } else { + _upstreamAddresses.push_back(i->identity.address()); + SharedPtr &hp = _peers[i->identity.address()]; + if (!hp) { + hp = new Peer(RR,RR->identity,i->identity); + saveIdentity(i->identity); + } + } + } + for(std::vector::const_iterator m(_moons.begin());m!=_moons.end();++m) { + for(std::vector::const_iterator i(m->roots().begin());i!=m->roots().end();++i) { + if (i->identity == RR->identity) { + _amRoot = true; + } else { + _upstreamAddresses.push_back(i->identity.address()); + SharedPtr &hp = _peers[i->identity.address()]; + if (!hp) { + hp = new Peer(RR,RR->identity,i->identity); + saveIdentity(i->identity); + } + } + } + } +} + } // namespace ZeroTier diff --git a/node/Topology.hpp b/node/Topology.hpp index 6369c5cd..693ae12c 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -169,6 +169,11 @@ public: bool isProhibitedEndpoint(const Address &ztaddr,const InetAddress &ipaddr) const; /** + * This gets the known stable endpoints for any upstream + * + * It also adds empty entries for any upstreams we are attempting to + * contact. + * * @param eps Hash table to fill with addresses and their stable endpoints */ inline void getUpstreamStableEndpoints(Hashtable< Address,std::vector > &eps) const @@ -190,6 +195,8 @@ public: } } } + for(std::vector
::const_iterator m(_contacingMoons.begin());m!=_contacingMoons.end();++m) + eps[*m]; } /** @@ -198,7 +205,12 @@ public: inline std::vector
upstreamAddresses() const { Mutex::Lock _l(_lock); - return _upstreamAddresses; + std::vector
u(_upstreamAddresses); + for(std::vector
::const_iterator m(_contacingMoons.begin());m!=_contacingMoons.end();++m) { + if (std::find(u.begin(),u.end(),*m) == u.end()) + u.push_back(*m); + } + return u; } /** @@ -244,6 +256,25 @@ public: */ bool addWorld(const World &newWorld,bool updateOnly); + /** + * Add a moon + * + * This loads it from moons.d if present, and if not adds it to + * a list of moons that we want to contact. It does not actually + * send anything, though this will happen on the next background + * task loop where pings etc. are checked. + * + * @param id Moon ID + */ + void addMoon(const uint64_t id); + + /** + * Remove a moon + * + * @param id Moon's world ID + */ + void removeMoon(const uint64_t id); + /** * Clean and flush database */ @@ -362,6 +393,7 @@ public: private: Identity _getIdentity(const Address &zta); + void _memoizeUpstreams(); const RuntimeEnvironment *const RR; @@ -375,8 +407,9 @@ private: Hashtable< Address,SharedPtr > _peers; Hashtable< Path::HashKey,SharedPtr > _paths; - std::vector< Address > _upstreamAddresses; // includes root addresses of both planets and moons - bool _amRoot; // am I a root in a planet or moon? + std::vector
_contacingMoons; + std::vector
_upstreamAddresses; + bool _amRoot; Mutex _lock; }; diff --git a/service/OneService.cpp b/service/OneService.cpp index f6174d42..d2ebe6b7 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -702,6 +702,14 @@ public: _node->join(Utils::hexStrToU64(f->substr(0,dot).c_str()),(void *)0); } } + { // Load existing moons + std::vector moonsDotD(OSUtils::listDirectory((_homePath + ZT_PATH_SEPARATOR_S "moons.d").c_str())); + for(std::vector::iterator f(moonsDotD.begin());f!=moonsDotD.end();++f) { + std::size_t dot = f->find_last_of('.'); + if ((dot == 16)&&(f->substr(16) == ".moon")) + _node->orbit(Utils::hexStrToU64(f->substr(0,dot).c_str())); + } + } _nextBackgroundTaskDeadline = 0; uint64_t clockShouldBe = OSUtils::now(); -- cgit v1.2.3 From 31db768e4d4c2815d2be0493b2c76ea5f5edbffa Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Sat, 4 Feb 2017 00:23:31 -0800 Subject: A bit of code cleanup. --- controller/EmbeddedNetworkController.cpp | 2 +- doc/MANUAL.md | 2 - node/Address.hpp | 77 +++++++++----------------------- node/Identity.cpp | 2 +- node/NetworkConfig.cpp | 2 +- node/Switch.cpp | 3 +- service/OneService.cpp | 2 +- 7 files changed, 25 insertions(+), 65 deletions(-) (limited to 'service/OneService.cpp') diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index 3c13e7ce..e7bcdd07 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -1690,7 +1690,7 @@ void EmbeddedNetworkController::_getNetworkMemberInfo(uint64_t now,uint64_t nwid } if (OSUtils::jsonBool(member["activeBridge"],false)) { - nmi.activeBridges.insert(OSUtils::jsonString(member["id"],"0000000000")); + nmi.activeBridges.insert(Address(Utils::hexStrToU64(OSUtils::jsonString(member["id"],"0000000000").c_str()))); } if (member.count("ipAssignments")) { diff --git a/doc/MANUAL.md b/doc/MANUAL.md index abaeef26..8af8fc2d 100644 --- a/doc/MANUAL.md +++ b/doc/MANUAL.md @@ -109,8 +109,6 @@ In the simplest case using only global roots, an initial connection setup betwee 3. R also sends a message called *RENDEZVOUS* to A containing hints about how it might reach B, and to B informing it how it might reach A. We call this "transport triggered link provisioning." 4. A and B get *RENDEZVOUS* and attempt to send test messages to each other, possibly accomplishing [hole punching](https://en.wikipedia.org/wiki/UDP_hole_punching) of any NATs or stateful firewalls that happen to be in the way. If this works a direct link is established and packets no longer need to take the scenic route. -If R is a federated root the same process occurs, but possibly with additional steps. - VL1 provides instant always-on virtual L1 connectivity between all devices in the world. Indirect paths are automatically and transparently upgraded to direct paths whenever possible, and if a direct path is lost ZeroTier falls back to indirect communication and the process begins again. If a direct path can never be established, indirect communication can continue forever with direct connection attempts also continuing indefinitely on a periodic basis. The protocol also contains other facilities for direct connectivity establishment such as LAN peer discovery, port prediction to traverse IPv4 symmetric NATs, and explicit endpoint advertisement that can be coupled with port mapping using uPnP or NAT-PMP if available. VL1 is persistent and determined when it comes to finding the most efficient way to move data. diff --git a/node/Address.hpp b/node/Address.hpp index 9bf5605a..4a5883b0 100644 --- a/node/Address.hpp +++ b/node/Address.hpp @@ -38,57 +38,26 @@ namespace ZeroTier { class Address { public: - Address() - throw() : - _a(0) - { - } - - Address(const Address &a) - throw() : - _a(a._a) - { - } - - Address(uint64_t a) - throw() : - _a(a & 0xffffffffffULL) - { - } - - Address(const char *s) - throw() - { - unsigned char foo[ZT_ADDRESS_LENGTH]; - setTo(foo,Utils::unhex(s,foo,ZT_ADDRESS_LENGTH)); - } - - Address(const std::string &s) - throw() - { - unsigned char foo[ZT_ADDRESS_LENGTH]; - setTo(foo,Utils::unhex(s.c_str(),foo,ZT_ADDRESS_LENGTH)); - } + Address() : _a(0) {} + Address(const Address &a) : _a(a._a) {} + Address(uint64_t a) : _a(a & 0xffffffffffULL) {} /** * @param bits Raw address -- 5 bytes, big-endian byte order * @param len Length of array */ Address(const void *bits,unsigned int len) - throw() { setTo(bits,len); } inline Address &operator=(const Address &a) - throw() { _a = a._a; return *this; } inline Address &operator=(const uint64_t a) - throw() { _a = (a & 0xffffffffffULL); return *this; @@ -99,7 +68,6 @@ public: * @param len Length of array */ inline void setTo(const void *bits,unsigned int len) - throw() { if (len < ZT_ADDRESS_LENGTH) { _a = 0; @@ -119,7 +87,6 @@ public: * @param len Length of array */ inline void copyTo(void *bits,unsigned int len) const - throw() { if (len < ZT_ADDRESS_LENGTH) return; @@ -138,7 +105,6 @@ public: */ template inline void appendTo(Buffer &b) const - throw(std::out_of_range) { unsigned char *p = (unsigned char *)b.appendField(ZT_ADDRESS_LENGTH); *(p++) = (unsigned char)((_a >> 32) & 0xff); @@ -152,7 +118,6 @@ public: * @return Integer containing address (0 to 2^40) */ inline uint64_t toInt() const - throw() { return _a; } @@ -161,7 +126,6 @@ public: * @return Hash code for use with Hashtable */ inline unsigned long hashCode() const - throw() { return (unsigned long)_a; } @@ -188,12 +152,12 @@ public: /** * @return True if this address is not zero */ - inline operator bool() const throw() { return (_a != 0); } + inline operator bool() const { return (_a != 0); } /** * Set to null/zero */ - inline void zero() throw() { _a = 0; } + inline void zero() { _a = 0; } /** * Check if this address is reserved @@ -205,7 +169,6 @@ public: * @return True if address is reserved and may not be used */ inline bool isReserved() const - throw() { return ((!_a)||((_a >> 32) == ZT_ADDRESS_RESERVED_PREFIX)); } @@ -214,21 +177,21 @@ public: * @param i Value from 0 to 4 (inclusive) * @return Byte at said position (address interpreted in big-endian order) */ - inline unsigned char operator[](unsigned int i) const throw() { return (unsigned char)((_a >> (32 - (i * 8))) & 0xff); } - - inline bool operator==(const uint64_t &a) const throw() { return (_a == (a & 0xffffffffffULL)); } - inline bool operator!=(const uint64_t &a) const throw() { return (_a != (a & 0xffffffffffULL)); } - inline bool operator>(const uint64_t &a) const throw() { return (_a > (a & 0xffffffffffULL)); } - inline bool operator<(const uint64_t &a) const throw() { return (_a < (a & 0xffffffffffULL)); } - inline bool operator>=(const uint64_t &a) const throw() { return (_a >= (a & 0xffffffffffULL)); } - inline bool operator<=(const uint64_t &a) const throw() { return (_a <= (a & 0xffffffffffULL)); } - - inline bool operator==(const Address &a) const throw() { return (_a == a._a); } - inline bool operator!=(const Address &a) const throw() { return (_a != a._a); } - inline bool operator>(const Address &a) const throw() { return (_a > a._a); } - inline bool operator<(const Address &a) const throw() { return (_a < a._a); } - inline bool operator>=(const Address &a) const throw() { return (_a >= a._a); } - inline bool operator<=(const Address &a) const throw() { return (_a <= a._a); } + inline unsigned char operator[](unsigned int i) const { return (unsigned char)((_a >> (32 - (i * 8))) & 0xff); } + + inline bool operator==(const uint64_t &a) const { return (_a == (a & 0xffffffffffULL)); } + inline bool operator!=(const uint64_t &a) const { return (_a != (a & 0xffffffffffULL)); } + inline bool operator>(const uint64_t &a) const { return (_a > (a & 0xffffffffffULL)); } + inline bool operator<(const uint64_t &a) const { return (_a < (a & 0xffffffffffULL)); } + inline bool operator>=(const uint64_t &a) const { return (_a >= (a & 0xffffffffffULL)); } + inline bool operator<=(const uint64_t &a) const { return (_a <= (a & 0xffffffffffULL)); } + + inline bool operator==(const Address &a) const { return (_a == a._a); } + inline bool operator!=(const Address &a) const { return (_a != a._a); } + inline bool operator>(const Address &a) const { return (_a > a._a); } + inline bool operator<(const Address &a) const { return (_a < a._a); } + inline bool operator>=(const Address &a) const { return (_a >= a._a); } + inline bool operator<=(const Address &a) const { return (_a <= a._a); } private: uint64_t _a; diff --git a/node/Identity.cpp b/node/Identity.cpp index c47805d9..05b70873 100644 --- a/node/Identity.cpp +++ b/node/Identity.cpp @@ -160,7 +160,7 @@ bool Identity::fromString(const char *str) for(char *f=Utils::stok(tmp,":",&saveptr);(f);f=Utils::stok((char *)0,":",&saveptr)) { switch(fno++) { case 0: - _address = Address(f); + _address = Address(Utils::hexStrToU64(f)); if (_address.isReserved()) return false; break; diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp index 6acc48ea..2f356b15 100644 --- a/node/NetworkConfig.cpp +++ b/node/NetworkConfig.cpp @@ -258,7 +258,7 @@ bool NetworkConfig::fromDictionary(const Dictionary 0) { char *saveptr = (char *)0; for(char *f=Utils::stok(tmp2,",",&saveptr);(f);f=Utils::stok((char *)0,",",&saveptr)) { - this->addSpecialist(Address(f),ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE); + this->addSpecialist(Address(Utils::hexStrToU64(f)),ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE); } } #else diff --git a/node/Switch.cpp b/node/Switch.cpp index 9fcd379f..a769faea 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -224,7 +224,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from #endif SharedPtr relayTo = RR->topology->getPeer(destination); - if ((relayTo)&&((relayTo->sendDirect(packet.data(),packet.size(),now,false)))) { + if ((relayTo)&&(relayTo->sendDirect(packet.data(),packet.size(),now,false))) { if ((source != RR->identity.address())&&(_shouldUnite(now,source,destination))) { // don't send RENDEZVOUS for cluster frontplane relays const InetAddress *hintToSource = (InetAddress *)0; const InetAddress *hintToDest = (InetAddress *)0; @@ -245,7 +245,6 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from } if ((hintToSource)&&(hintToDest)) { - TRACE(">> RENDEZVOUS: %s(%s) <> %s(%s)",p1.toString().c_str(),p1a->toString().c_str(),p2.toString().c_str(),p2a->toString().c_str()); unsigned int alt = (unsigned int)RR->node->prng() & 1; // randomize which hint we send first for obscure NAT-t reasons const unsigned int completed = alt + 2; while (alt != completed) { diff --git a/service/OneService.cpp b/service/OneService.cpp index 49c5f4a0..9a1503e5 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -926,7 +926,7 @@ public: for(json::iterator v(virt.begin());v!=virt.end();++v) { const std::string nstr = v.key(); if ((nstr.length() == ZT_ADDRESS_LENGTH_HEX)&&(v.value().is_object())) { - const Address ztaddr(nstr.c_str()); + const Address ztaddr(Utils::hexStrToU64(nstr.c_str())); if (ztaddr) { const uint64_t ztaddr2 = ztaddr.toInt(); std::vector &v4h = _v4Hints[ztaddr2]; -- cgit v1.2.3 From 42f28bce52c3342e3aac68488260a02c71691177 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 13 Feb 2017 09:03:48 -0800 Subject: Cleanup and make moons (federated roots) a little easier to deal with. --- include/ZeroTierOne.h | 9 +++-- node/IncomingPacket.cpp | 1 + node/Node.cpp | 39 ++++++++++--------- node/Node.hpp | 2 +- node/Topology.cpp | 99 +++++++++++++++++++++++++++++------------------- node/Topology.hpp | 27 +++++-------- node/Utils.cpp | 19 +++------- node/Utils.hpp | 3 +- service/ControlPlane.cpp | 4 +- service/OneService.cpp | 2 +- 10 files changed, 107 insertions(+), 98 deletions(-) (limited to 'service/OneService.cpp') diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 583f9b6a..38ae7d8a 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -835,9 +835,9 @@ enum ZT_VirtualNetworkConfigOperation */ enum ZT_PeerRole { - ZT_PEER_ROLE_LEAF = 0, // ordinary node - ZT_PEER_ROLE_UPSTREAM = 1, // moon root - ZT_PEER_ROLE_ROOT = 2 // planetary root + ZT_PEER_ROLE_LEAF = 0, // ordinary node + ZT_PEER_ROLE_MOON = 1, // moon root + ZT_PEER_ROLE_PLANET = 2 // planetary root }; /** @@ -1790,10 +1790,11 @@ enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node,uint64_t nwid,uint * called for each on startup. * * @param moonWorldId Moon's world ID + * @param moonSeed If non-zero, the ZeroTier address of any member of the moon to query for moon definition * @param len Length of moonWorld in bytes * @return Error if moon was invalid or failed to be added */ -enum ZT_ResultCode ZT_Node_orbit(ZT_Node *node,uint64_t moonWorldId); +enum ZT_ResultCode ZT_Node_orbit(ZT_Node *node,uint64_t moonWorldId,uint64_t moonSeed); /** * Remove a moon (does nothing if not present) diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 02d6a140..8836df9f 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -568,6 +568,7 @@ bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,const SharedPtr id.serialize(outp,false); ++count; } else { + // Request unknown WHOIS from upstream from us (if we have one) RR->sw->requestWhois(addr); #ifdef ZT_ENABLE_CLUSTER // Distribute WHOIS queries across a cluster if we do not know the ID. diff --git a/node/Node.cpp b/node/Node.cpp index b8e74a52..388a4fb2 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -156,23 +156,26 @@ ZT_ResultCode Node::processVirtualNetworkFrame( class _PingPeersThatNeedPing { public: - _PingPeersThatNeedPing(const RuntimeEnvironment *renv,uint64_t now) : + _PingPeersThatNeedPing(const RuntimeEnvironment *renv,Hashtable< Address,std::vector > &upstreamsToContact,uint64_t now) : lastReceiveFromUpstream(0), RR(renv), + _upstreamsToContact(upstreamsToContact), _now(now), _bestCurrentUpstream(RR->topology->getUpstreamPeer()) { - RR->topology->getUpstreamStableEndpoints(_upstreams); } uint64_t lastReceiveFromUpstream; // tracks last time we got a packet from an 'upstream' peer like a root or a relay inline void operator()(Topology &t,const SharedPtr &p) { - const std::vector *const upstreamStableEndpoints = _upstreams.get(p->address()); + const std::vector *const upstreamStableEndpoints = _upstreamsToContact.get(p->address()); if (upstreamStableEndpoints) { bool contacted = false; + // Upstreams must be pinged constantly over both IPv4 and IPv6 to allow + // them to perform three way handshake introductions for both stacks. + if (!p->doPingAndKeepalive(_now,AF_INET)) { for(unsigned long k=0,ptr=(unsigned long)RR->node->prng();k<(unsigned long)upstreamStableEndpoints->size();++k) { const InetAddress &addr = (*upstreamStableEndpoints)[ptr++ % upstreamStableEndpoints->size()]; @@ -183,7 +186,6 @@ public: } } } else contacted = true; - if (!p->doPingAndKeepalive(_now,AF_INET6)) { for(unsigned long k=0,ptr=(unsigned long)RR->node->prng();k<(unsigned long)upstreamStableEndpoints->size();++k) { const InetAddress &addr = (*upstreamStableEndpoints)[ptr++ % upstreamStableEndpoints->size()]; @@ -202,6 +204,7 @@ public: } lastReceiveFromUpstream = std::max(p->lastReceive(),lastReceiveFromUpstream); + _upstreamsToContact.erase(p->address()); // erase from upstreams to contact so that we can WHOIS those that remain } else if (p->isActive(_now)) { p->doPingAndKeepalive(_now,-1); } @@ -209,9 +212,9 @@ public: private: const RuntimeEnvironment *RR; + Hashtable< Address,std::vector > &_upstreamsToContact; const uint64_t _now; const SharedPtr _bestCurrentUpstream; - Hashtable< Address,std::vector > _upstreams; }; ZT_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline) @@ -238,17 +241,19 @@ ZT_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextB for(std::vector< SharedPtr >::const_iterator n(needConfig.begin());n!=needConfig.end();++n) (*n)->requestConfiguration(); - // Attempt to get identity for any unknown upstreams - const std::vector
upstreams(RR->topology->upstreamAddresses()); - for(std::vector
::const_iterator a(upstreams.begin());a!=upstreams.end();++a) { - if (!RR->topology->getPeer(*a)) - RR->sw->requestWhois(*a); - } - // Do pings and keepalives - _PingPeersThatNeedPing pfunc(RR,now); + Hashtable< Address,std::vector > upstreamsToContact; + RR->topology->getUpstreamsToContact(upstreamsToContact); + _PingPeersThatNeedPing pfunc(RR,upstreamsToContact,now); RR->topology->eachPeer<_PingPeersThatNeedPing &>(pfunc); + // Run WHOIS to create Peer for any upstreams we could not contact (including pending moon seeds) + Hashtable< Address,std::vector >::Iterator i(upstreamsToContact); + Address *upstreamAddress = (Address *)0; + std::vector *upstreamStableEndpoints = (std::vector *)0; + while (i.next(upstreamAddress,upstreamStableEndpoints)) + RR->sw->requestWhois(*upstreamAddress); + // Update online status, post status change as event const bool oldOnline = _online; _online = (((now - pfunc.lastReceiveFromUpstream) < ZT_PEER_ACTIVITY_TIMEOUT)||(RR->topology->amRoot())); @@ -337,9 +342,9 @@ ZT_ResultCode Node::multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,u } else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND; } -ZT_ResultCode Node::orbit(uint64_t moonWorldId) +ZT_ResultCode Node::orbit(uint64_t moonWorldId,uint64_t moonSeed) { - RR->topology->addMoon(moonWorldId); + RR->topology->addMoon(moonWorldId,Address(moonSeed)); return ZT_RESULT_OK; } @@ -919,10 +924,10 @@ enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node,uint64_t nwid,uint } } -enum ZT_ResultCode ZT_Node_orbit(ZT_Node *node,uint64_t moonWorldId) +enum ZT_ResultCode ZT_Node_orbit(ZT_Node *node,uint64_t moonWorldId,uint64_t moonSeed) { try { - return reinterpret_cast(node)->orbit(moonWorldId); + return reinterpret_cast(node)->orbit(moonWorldId,moonSeed); } catch ( ... ) { return ZT_RESULT_FATAL_ERROR_INTERNAL; } diff --git a/node/Node.hpp b/node/Node.hpp index 3e742092..d83ce968 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -95,7 +95,7 @@ public: ZT_ResultCode leave(uint64_t nwid,void **uptr); ZT_ResultCode multicastSubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi); ZT_ResultCode multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi); - ZT_ResultCode orbit(uint64_t moonWorldId); + ZT_ResultCode orbit(uint64_t moonWorldId,uint64_t moonSeed); ZT_ResultCode deorbit(uint64_t moonWorldId); uint64_t address() const; void status(ZT_NodeStatus *status) const; diff --git a/node/Topology.cpp b/node/Topology.cpp index 0fde63dc..d85b6a7d 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -27,19 +27,31 @@ namespace ZeroTier { -// 2015-11-16 -- The Fabulous Four (should have named them after Beatles!) -//#define ZT_DEFAULT_WORLD_LENGTH 494 -//static const unsigned char ZT_DEFAULT_WORLD[ZT_DEFAULT_WORLD_LENGTH] = {0x01,0x00,0x00,0x00,0x00,0x08,0xea,0xc9,0x0a,0x00,0x00,0x01,0x51,0x11,0x70,0xb2,0xfb,0xb8,0xb3,0x88,0xa4,0x69,0x22,0x14,0x91,0xaa,0x9a,0xcd,0x66,0xcc,0x76,0x4c,0xde,0xfd,0x56,0x03,0x9f,0x10,0x67,0xae,0x15,0xe6,0x9c,0x6f,0xb4,0x2d,0x7b,0x55,0x33,0x0e,0x3f,0xda,0xac,0x52,0x9c,0x07,0x92,0xfd,0x73,0x40,0xa6,0xaa,0x21,0xab,0xa8,0xa4,0x89,0xfd,0xae,0xa4,0x4a,0x39,0xbf,0x2d,0x00,0x65,0x9a,0xc9,0xc8,0x18,0xeb,0x80,0x31,0xa4,0x65,0x95,0x45,0x06,0x1c,0xfb,0xc2,0x4e,0x5d,0xe7,0x0a,0x40,0x7a,0x97,0xce,0x36,0xa2,0x3d,0x05,0xca,0x87,0xc7,0x59,0x27,0x5c,0x8b,0x0d,0x4c,0xb4,0xbb,0x26,0x2f,0x77,0x17,0x5e,0xb7,0x4d,0xb8,0xd3,0xb4,0xe9,0x23,0x5d,0xcc,0xa2,0x71,0xa8,0xdf,0xf1,0x23,0xa3,0xb2,0x66,0x74,0xea,0xe5,0xdc,0x8d,0xef,0xd3,0x0a,0xa9,0xac,0xcb,0xda,0x93,0xbd,0x6c,0xcd,0x43,0x1d,0xa7,0x98,0x6a,0xde,0x70,0xc0,0xc6,0x1c,0xaf,0xf0,0xfd,0x7f,0x8a,0xb9,0x76,0x13,0xe1,0xde,0x4f,0xf3,0xd6,0x13,0x04,0x7e,0x19,0x87,0x6a,0xba,0x00,0x2a,0x6e,0x2b,0x23,0x18,0x93,0x0f,0x60,0xeb,0x09,0x7f,0x70,0xd0,0xf4,0xb0,0x28,0xb2,0xcd,0x6d,0x3d,0x0c,0x63,0xc0,0x14,0xb9,0x03,0x9f,0xf3,0x53,0x90,0xe4,0x11,0x81,0xf2,0x16,0xfb,0x2e,0x6f,0xa8,0xd9,0x5c,0x1e,0xe9,0x66,0x71,0x56,0x41,0x19,0x05,0xc3,0xdc,0xcf,0xea,0x78,0xd8,0xc6,0xdf,0xaf,0xba,0x68,0x81,0x70,0xb3,0xfa,0x00,0x01,0x04,0xc6,0xc7,0x61,0xdc,0x27,0x09,0x88,0x41,0x40,0x8a,0x2e,0x00,0xbb,0x1d,0x31,0xf2,0xc3,0x23,0xe2,0x64,0xe9,0xe6,0x41,0x72,0xc1,0xa7,0x4f,0x77,0x89,0x95,0x55,0xed,0x10,0x75,0x1c,0xd5,0x6e,0x86,0x40,0x5c,0xde,0x11,0x8d,0x02,0xdf,0xfe,0x55,0x5d,0x46,0x2c,0xcf,0x6a,0x85,0xb5,0x63,0x1c,0x12,0x35,0x0c,0x8d,0x5d,0xc4,0x09,0xba,0x10,0xb9,0x02,0x5d,0x0f,0x44,0x5c,0xf4,0x49,0xd9,0x2b,0x1c,0x00,0x01,0x04,0x6b,0xbf,0x2e,0xd2,0x27,0x09,0x8a,0xcf,0x05,0x9f,0xe3,0x00,0x48,0x2f,0x6e,0xe5,0xdf,0xe9,0x02,0x31,0x9b,0x41,0x9d,0xe5,0xbd,0xc7,0x65,0x20,0x9c,0x0e,0xcd,0xa3,0x8c,0x4d,0x6e,0x4f,0xcf,0x0d,0x33,0x65,0x83,0x98,0xb4,0x52,0x7d,0xcd,0x22,0xf9,0x31,0x12,0xfb,0x9b,0xef,0xd0,0x2f,0xd7,0x8b,0xf7,0x26,0x1b,0x33,0x3f,0xc1,0x05,0xd1,0x92,0xa6,0x23,0xca,0x9e,0x50,0xfc,0x60,0xb3,0x74,0xa5,0x00,0x01,0x04,0xa2,0xf3,0x4d,0x6f,0x27,0x09,0x9d,0x21,0x90,0x39,0xf3,0x00,0x01,0xf0,0x92,0x2a,0x98,0xe3,0xb3,0x4e,0xbc,0xbf,0xf3,0x33,0x26,0x9d,0xc2,0x65,0xd7,0xa0,0x20,0xaa,0xb6,0x9d,0x72,0xbe,0x4d,0x4a,0xcc,0x9c,0x8c,0x92,0x94,0x78,0x57,0x71,0x25,0x6c,0xd1,0xd9,0x42,0xa9,0x0d,0x1b,0xd1,0xd2,0xdc,0xa3,0xea,0x84,0xef,0x7d,0x85,0xaf,0xe6,0x61,0x1f,0xb4,0x3f,0xf0,0xb7,0x41,0x26,0xd9,0x0a,0x6e,0x00,0x01,0x04,0x80,0xc7,0xc5,0xd9,0x27,0x09}; - -// 2015-11-20 -- Alice and Bob are live, and we're now IPv6 dual-stack! -//#define ZT_DEFAULT_WORLD_LENGTH 792 -//static const unsigned char ZT_DEFAULT_WORLD[ZT_DEFAULT_WORLD_LENGTH] = {0x01,0x00,0x00,0x00,0x00,0x08,0xea,0xc9,0x0a,0x00,0x00,0x01,0x51,0x26,0x6f,0x7c,0x8a,0xb8,0xb3,0x88,0xa4,0x69,0x22,0x14,0x91,0xaa,0x9a,0xcd,0x66,0xcc,0x76,0x4c,0xde,0xfd,0x56,0x03,0x9f,0x10,0x67,0xae,0x15,0xe6,0x9c,0x6f,0xb4,0x2d,0x7b,0x55,0x33,0x0e,0x3f,0xda,0xac,0x52,0x9c,0x07,0x92,0xfd,0x73,0x40,0xa6,0xaa,0x21,0xab,0xa8,0xa4,0x89,0xfd,0xae,0xa4,0x4a,0x39,0xbf,0x2d,0x00,0x65,0x9a,0xc9,0xc8,0x18,0xeb,0xe8,0x0a,0xf5,0xbc,0xf8,0x3d,0x97,0xcd,0xc3,0xf8,0xe2,0x41,0x16,0x42,0x0f,0xc7,0x76,0x8e,0x07,0xf3,0x7e,0x9e,0x7d,0x1b,0xb3,0x23,0x21,0x79,0xce,0xb9,0xd0,0xcb,0xb5,0x94,0x7b,0x89,0x21,0x57,0x72,0xf6,0x70,0xa1,0xdd,0x67,0x38,0xcf,0x45,0x45,0xc2,0x8d,0x46,0xec,0x00,0x2c,0xe0,0x2a,0x63,0x3f,0x63,0x8d,0x33,0x08,0x51,0x07,0x77,0x81,0x5b,0x32,0x49,0xae,0x87,0x89,0xcf,0x31,0xaa,0x41,0xf1,0x52,0x97,0xdc,0xa2,0x55,0xe1,0x4a,0x6e,0x3c,0x04,0xf0,0x4f,0x8a,0x0e,0xe9,0xca,0xec,0x24,0x30,0x04,0x9d,0x21,0x90,0x39,0xf3,0x00,0x01,0xf0,0x92,0x2a,0x98,0xe3,0xb3,0x4e,0xbc,0xbf,0xf3,0x33,0x26,0x9d,0xc2,0x65,0xd7,0xa0,0x20,0xaa,0xb6,0x9d,0x72,0xbe,0x4d,0x4a,0xcc,0x9c,0x8c,0x92,0x94,0x78,0x57,0x71,0x25,0x6c,0xd1,0xd9,0x42,0xa9,0x0d,0x1b,0xd1,0xd2,0xdc,0xa3,0xea,0x84,0xef,0x7d,0x85,0xaf,0xe6,0x61,0x1f,0xb4,0x3f,0xf0,0xb7,0x41,0x26,0xd9,0x0a,0x6e,0x00,0x0c,0x04,0xbc,0xa6,0x5e,0xb1,0x27,0x09,0x06,0x2a,0x03,0xb0,0xc0,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x7d,0x00,0x01,0x27,0x09,0x04,0x9a,0x42,0xc5,0x21,0x27,0x09,0x06,0x2c,0x0f,0xf8,0x50,0x01,0x54,0x01,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x27,0x09,0x04,0x9f,0xcb,0x61,0xab,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x08,0x00,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,0x54,0x60,0x01,0x27,0x09,0x04,0xa9,0x39,0x8f,0x68,0x27,0x09,0x06,0x26,0x07,0xf0,0xd0,0x1d,0x01,0x00,0x57,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x27,0x09,0x04,0x6b,0xaa,0xc5,0x0e,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x00,0x01,0x00,0x20,0x00,0x00,0x00,0x00,0x02,0x00,0xe0,0x01,0x27,0x09,0x04,0x80,0xc7,0xc5,0xd9,0x27,0x09,0x06,0x24,0x00,0x61,0x80,0x00,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0xb7,0x40,0x01,0x27,0x09,0x88,0x41,0x40,0x8a,0x2e,0x00,0xbb,0x1d,0x31,0xf2,0xc3,0x23,0xe2,0x64,0xe9,0xe6,0x41,0x72,0xc1,0xa7,0x4f,0x77,0x89,0x95,0x55,0xed,0x10,0x75,0x1c,0xd5,0x6e,0x86,0x40,0x5c,0xde,0x11,0x8d,0x02,0xdf,0xfe,0x55,0x5d,0x46,0x2c,0xcf,0x6a,0x85,0xb5,0x63,0x1c,0x12,0x35,0x0c,0x8d,0x5d,0xc4,0x09,0xba,0x10,0xb9,0x02,0x5d,0x0f,0x44,0x5c,0xf4,0x49,0xd9,0x2b,0x1c,0x00,0x0c,0x04,0x2d,0x20,0xc6,0x82,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x64,0x00,0x81,0xc3,0x54,0x00,0x00,0xff,0xfe,0x18,0x1d,0x61,0x27,0x09,0x04,0x2e,0x65,0xa0,0xf9,0x27,0x09,0x06,0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x6a,0x30,0x01,0x27,0x09,0x04,0x6b,0xbf,0x2e,0xd2,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x68,0x00,0x83,0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0x27,0x09,0x04,0x2d,0x20,0xf6,0xb3,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x58,0x00,0x8b,0xf8,0x54,0x00,0x00,0xff,0xfe,0x15,0xb3,0x9a,0x27,0x09,0x04,0x2d,0x20,0xf8,0x57,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x70,0x00,0x9b,0xc9,0x54,0x00,0x00,0xff,0xfe,0x15,0xc4,0xf5,0x27,0x09,0x04,0x9f,0xcb,0x02,0x9a,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x0c,0xad,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x26,0x70,0x01,0x27,0x09,0x7e,0x19,0x87,0x6a,0xba,0x00,0x2a,0x6e,0x2b,0x23,0x18,0x93,0x0f,0x60,0xeb,0x09,0x7f,0x70,0xd0,0xf4,0xb0,0x28,0xb2,0xcd,0x6d,0x3d,0x0c,0x63,0xc0,0x14,0xb9,0x03,0x9f,0xf3,0x53,0x90,0xe4,0x11,0x81,0xf2,0x16,0xfb,0x2e,0x6f,0xa8,0xd9,0x5c,0x1e,0xe9,0x66,0x71,0x56,0x41,0x19,0x05,0xc3,0xdc,0xcf,0xea,0x78,0xd8,0xc6,0xdf,0xaf,0xba,0x68,0x81,0x70,0xb3,0xfa,0x00,0x01,0x04,0xc6,0xc7,0x61,0xdc,0x27,0x09,0x8a,0xcf,0x05,0x9f,0xe3,0x00,0x48,0x2f,0x6e,0xe5,0xdf,0xe9,0x02,0x31,0x9b,0x41,0x9d,0xe5,0xbd,0xc7,0x65,0x20,0x9c,0x0e,0xcd,0xa3,0x8c,0x4d,0x6e,0x4f,0xcf,0x0d,0x33,0x65,0x83,0x98,0xb4,0x52,0x7d,0xcd,0x22,0xf9,0x31,0x12,0xfb,0x9b,0xef,0xd0,0x2f,0xd7,0x8b,0xf7,0x26,0x1b,0x33,0x3f,0xc1,0x05,0xd1,0x92,0xa6,0x23,0xca,0x9e,0x50,0xfc,0x60,0xb3,0x74,0xa5,0x00,0x01,0x04,0xa2,0xf3,0x4d,0x6f,0x27,0x09}; - -// 2015-12-17 -- Old New York root is dead, old SF still alive -//#define ZT_DEFAULT_WORLD_LENGTH 732 -//static const unsigned char ZT_DEFAULT_WORLD[ZT_DEFAULT_WORLD_LENGTH] = {0x01,0x00,0x00,0x00,0x00,0x08,0xea,0xc9,0x0a,0x00,0x00,0x01,0x51,0xb1,0x7e,0x39,0x9d,0xb8,0xb3,0x88,0xa4,0x69,0x22,0x14,0x91,0xaa,0x9a,0xcd,0x66,0xcc,0x76,0x4c,0xde,0xfd,0x56,0x03,0x9f,0x10,0x67,0xae,0x15,0xe6,0x9c,0x6f,0xb4,0x2d,0x7b,0x55,0x33,0x0e,0x3f,0xda,0xac,0x52,0x9c,0x07,0x92,0xfd,0x73,0x40,0xa6,0xaa,0x21,0xab,0xa8,0xa4,0x89,0xfd,0xae,0xa4,0x4a,0x39,0xbf,0x2d,0x00,0x65,0x9a,0xc9,0xc8,0x18,0xeb,0x8a,0xca,0xf2,0x3d,0x71,0x2e,0xc2,0x39,0x45,0x66,0xb3,0xe9,0x39,0x79,0xb1,0x55,0xc4,0xa9,0xfc,0xbc,0xfc,0x55,0xaf,0x8a,0x2f,0x38,0xc8,0xcd,0xe9,0x02,0x5b,0x86,0xa9,0x72,0xf7,0x16,0x00,0x35,0xb7,0x84,0xc9,0xfc,0xe4,0xfa,0x96,0x8b,0xf4,0x1e,0xba,0x60,0x9f,0x85,0x14,0xc2,0x07,0x4b,0xfd,0xd1,0x6c,0x19,0x69,0xd3,0xf9,0x09,0x9c,0x9d,0xe3,0xb9,0x8f,0x11,0x78,0x71,0xa7,0x4a,0x05,0xd8,0xcc,0x60,0xa2,0x06,0x66,0x9f,0x47,0xc2,0x71,0xb8,0x54,0x80,0x9c,0x45,0x16,0x10,0xa9,0xd0,0xbd,0xf7,0x03,0x9d,0x21,0x90,0x39,0xf3,0x00,0x01,0xf0,0x92,0x2a,0x98,0xe3,0xb3,0x4e,0xbc,0xbf,0xf3,0x33,0x26,0x9d,0xc2,0x65,0xd7,0xa0,0x20,0xaa,0xb6,0x9d,0x72,0xbe,0x4d,0x4a,0xcc,0x9c,0x8c,0x92,0x94,0x78,0x57,0x71,0x25,0x6c,0xd1,0xd9,0x42,0xa9,0x0d,0x1b,0xd1,0xd2,0xdc,0xa3,0xea,0x84,0xef,0x7d,0x85,0xaf,0xe6,0x61,0x1f,0xb4,0x3f,0xf0,0xb7,0x41,0x26,0xd9,0x0a,0x6e,0x00,0x0c,0x04,0xbc,0xa6,0x5e,0xb1,0x27,0x09,0x06,0x2a,0x03,0xb0,0xc0,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x7d,0x00,0x01,0x27,0x09,0x04,0x9a,0x42,0xc5,0x21,0x27,0x09,0x06,0x2c,0x0f,0xf8,0x50,0x01,0x54,0x01,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x27,0x09,0x04,0x9f,0xcb,0x61,0xab,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x08,0x00,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,0x54,0x60,0x01,0x27,0x09,0x04,0xa9,0x39,0x8f,0x68,0x27,0x09,0x06,0x26,0x07,0xf0,0xd0,0x1d,0x01,0x00,0x57,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x27,0x09,0x04,0x6b,0xaa,0xc5,0x0e,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x00,0x01,0x00,0x20,0x00,0x00,0x00,0x00,0x02,0x00,0xe0,0x01,0x27,0x09,0x04,0x80,0xc7,0xc5,0xd9,0x27,0x09,0x06,0x24,0x00,0x61,0x80,0x00,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0xb7,0x40,0x01,0x27,0x09,0x88,0x41,0x40,0x8a,0x2e,0x00,0xbb,0x1d,0x31,0xf2,0xc3,0x23,0xe2,0x64,0xe9,0xe6,0x41,0x72,0xc1,0xa7,0x4f,0x77,0x89,0x95,0x55,0xed,0x10,0x75,0x1c,0xd5,0x6e,0x86,0x40,0x5c,0xde,0x11,0x8d,0x02,0xdf,0xfe,0x55,0x5d,0x46,0x2c,0xcf,0x6a,0x85,0xb5,0x63,0x1c,0x12,0x35,0x0c,0x8d,0x5d,0xc4,0x09,0xba,0x10,0xb9,0x02,0x5d,0x0f,0x44,0x5c,0xf4,0x49,0xd9,0x2b,0x1c,0x00,0x0c,0x04,0x2d,0x20,0xc6,0x82,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x64,0x00,0x81,0xc3,0x54,0x00,0x00,0xff,0xfe,0x18,0x1d,0x61,0x27,0x09,0x04,0x2e,0x65,0xa0,0xf9,0x27,0x09,0x06,0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x6a,0x30,0x01,0x27,0x09,0x04,0x6b,0xbf,0x2e,0xd2,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x68,0x00,0x83,0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0x27,0x09,0x04,0x2d,0x20,0xf6,0xb3,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x58,0x00,0x8b,0xf8,0x54,0x00,0x00,0xff,0xfe,0x15,0xb3,0x9a,0x27,0x09,0x04,0x2d,0x20,0xf8,0x57,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x70,0x00,0x9b,0xc9,0x54,0x00,0x00,0xff,0xfe,0x15,0xc4,0xf5,0x27,0x09,0x04,0x9f,0xcb,0x02,0x9a,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x0c,0xad,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x26,0x70,0x01,0x27,0x09,0x7e,0x19,0x87,0x6a,0xba,0x00,0x2a,0x6e,0x2b,0x23,0x18,0x93,0x0f,0x60,0xeb,0x09,0x7f,0x70,0xd0,0xf4,0xb0,0x28,0xb2,0xcd,0x6d,0x3d,0x0c,0x63,0xc0,0x14,0xb9,0x03,0x9f,0xf3,0x53,0x90,0xe4,0x11,0x81,0xf2,0x16,0xfb,0x2e,0x6f,0xa8,0xd9,0x5c,0x1e,0xe9,0x66,0x71,0x56,0x41,0x19,0x05,0xc3,0xdc,0xcf,0xea,0x78,0xd8,0xc6,0xdf,0xaf,0xba,0x68,0x81,0x70,0xb3,0xfa,0x00,0x02,0x04,0xc6,0xc7,0x61,0xdc,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x00,0x01,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0xc5,0xf0,0x01,0x27,0x09}; - -// 2016-01-13 -- Old San Francisco 1.0.1 root is dead, now we're just on Alice and Bob! +/* + * 2016-01-13 ZeroTier planet definition for the third planet of Sol: + * + * There are two roots, each of which is a cluster spread across multiple + * continents and providers. They are named Alice and Bob after the + * canonical example names used in cryptography. + * + * Alice: + * + * root-alice-ams-01: Amsterdam, Netherlands + * root-alice-joh-01: Johannesburg, South Africa + * root-alice-nyc-01: New York, New York, USA + * root-alice-sao-01: Sao Paolo, Brazil + * root-alice-sfo-01: San Francisco, California, USA + * root-alice-sgp-01: Singapore + * + * Bob: + * + * root-bob-dfw-01: Dallas, Texas, USA + * root-bob-fra-01: Frankfurt, Germany + * root-bob-par-01: Paris, France + * root-bob-syd-01: Sydney, Australia + * root-bob-tok-01: Tokyo, Japan + * root-bob-tor-01: Toronto, Canada + */ #define ZT_DEFAULT_WORLD_LENGTH 634 static const unsigned char ZT_DEFAULT_WORLD[ZT_DEFAULT_WORLD_LENGTH] = {0x01,0x00,0x00,0x00,0x00,0x08,0xea,0xc9,0x0a,0x00,0x00,0x01,0x52,0x3c,0x32,0x50,0x1a,0xb8,0xb3,0x88,0xa4,0x69,0x22,0x14,0x91,0xaa,0x9a,0xcd,0x66,0xcc,0x76,0x4c,0xde,0xfd,0x56,0x03,0x9f,0x10,0x67,0xae,0x15,0xe6,0x9c,0x6f,0xb4,0x2d,0x7b,0x55,0x33,0x0e,0x3f,0xda,0xac,0x52,0x9c,0x07,0x92,0xfd,0x73,0x40,0xa6,0xaa,0x21,0xab,0xa8,0xa4,0x89,0xfd,0xae,0xa4,0x4a,0x39,0xbf,0x2d,0x00,0x65,0x9a,0xc9,0xc8,0x18,0xeb,0x4a,0xf7,0x86,0xa8,0x40,0xd6,0x52,0xea,0xae,0x9e,0x7a,0xbf,0x4c,0x97,0x66,0xab,0x2d,0x6f,0xaf,0xc9,0x2b,0x3a,0xff,0xed,0xd6,0x30,0x3e,0xc4,0x6a,0x65,0xf2,0xbd,0x83,0x52,0xf5,0x40,0xe9,0xcc,0x0d,0x6e,0x89,0x3f,0x9a,0xa0,0xb8,0xdf,0x42,0xd2,0x2f,0x84,0xe6,0x03,0x26,0x0f,0xa8,0xe3,0xcc,0x05,0x05,0x03,0xef,0x12,0x80,0x0d,0xce,0x3e,0xb6,0x58,0x3b,0x1f,0xa8,0xad,0xc7,0x25,0xf9,0x43,0x71,0xa7,0x5c,0x9a,0xc7,0xe1,0xa3,0xb8,0x88,0xd0,0x71,0x6c,0x94,0x99,0x73,0x41,0x0b,0x1b,0x48,0x84,0x02,0x9d,0x21,0x90,0x39,0xf3,0x00,0x01,0xf0,0x92,0x2a,0x98,0xe3,0xb3,0x4e,0xbc,0xbf,0xf3,0x33,0x26,0x9d,0xc2,0x65,0xd7,0xa0,0x20,0xaa,0xb6,0x9d,0x72,0xbe,0x4d,0x4a,0xcc,0x9c,0x8c,0x92,0x94,0x78,0x57,0x71,0x25,0x6c,0xd1,0xd9,0x42,0xa9,0x0d,0x1b,0xd1,0xd2,0xdc,0xa3,0xea,0x84,0xef,0x7d,0x85,0xaf,0xe6,0x61,0x1f,0xb4,0x3f,0xf0,0xb7,0x41,0x26,0xd9,0x0a,0x6e,0x00,0x0c,0x04,0xbc,0xa6,0x5e,0xb1,0x27,0x09,0x06,0x2a,0x03,0xb0,0xc0,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x7d,0x00,0x01,0x27,0x09,0x04,0x9a,0x42,0xc5,0x21,0x27,0x09,0x06,0x2c,0x0f,0xf8,0x50,0x01,0x54,0x01,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x27,0x09,0x04,0x9f,0xcb,0x61,0xab,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x08,0x00,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,0x54,0x60,0x01,0x27,0x09,0x04,0xa9,0x39,0x8f,0x68,0x27,0x09,0x06,0x26,0x07,0xf0,0xd0,0x1d,0x01,0x00,0x57,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x27,0x09,0x04,0x6b,0xaa,0xc5,0x0e,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x00,0x01,0x00,0x20,0x00,0x00,0x00,0x00,0x02,0x00,0xe0,0x01,0x27,0x09,0x04,0x80,0xc7,0xc5,0xd9,0x27,0x09,0x06,0x24,0x00,0x61,0x80,0x00,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0xb7,0x40,0x01,0x27,0x09,0x88,0x41,0x40,0x8a,0x2e,0x00,0xbb,0x1d,0x31,0xf2,0xc3,0x23,0xe2,0x64,0xe9,0xe6,0x41,0x72,0xc1,0xa7,0x4f,0x77,0x89,0x95,0x55,0xed,0x10,0x75,0x1c,0xd5,0x6e,0x86,0x40,0x5c,0xde,0x11,0x8d,0x02,0xdf,0xfe,0x55,0x5d,0x46,0x2c,0xcf,0x6a,0x85,0xb5,0x63,0x1c,0x12,0x35,0x0c,0x8d,0x5d,0xc4,0x09,0xba,0x10,0xb9,0x02,0x5d,0x0f,0x44,0x5c,0xf4,0x49,0xd9,0x2b,0x1c,0x00,0x0c,0x04,0x2d,0x20,0xc6,0x82,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x64,0x00,0x81,0xc3,0x54,0x00,0x00,0xff,0xfe,0x18,0x1d,0x61,0x27,0x09,0x04,0x2e,0x65,0xa0,0xf9,0x27,0x09,0x06,0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x6a,0x30,0x01,0x27,0x09,0x04,0x6b,0xbf,0x2e,0xd2,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x68,0x00,0x83,0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0x27,0x09,0x04,0x2d,0x20,0xf6,0xb3,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x58,0x00,0x8b,0xf8,0x54,0x00,0x00,0xff,0xfe,0x15,0xb3,0x9a,0x27,0x09,0x04,0x2d,0x20,0xf8,0x57,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x70,0x00,0x9b,0xc9,0x54,0x00,0x00,0xff,0xfe,0x15,0xc4,0xf5,0x27,0x09,0x04,0x9f,0xcb,0x02,0x9a,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x0c,0xad,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x26,0x70,0x01,0x27,0x09}; @@ -219,9 +231,9 @@ ZT_PeerRole Topology::role(const Address &ztaddr) const if (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),ztaddr) != _upstreamAddresses.end()) { for(std::vector::const_iterator i(_planet.roots().begin());i!=_planet.roots().end();++i) { if (i->identity.address() == ztaddr) - return ZT_PEER_ROLE_ROOT; + return ZT_PEER_ROLE_PLANET; } - return ZT_PEER_ROLE_UPSTREAM; + return ZT_PEER_ROLE_MOON; } return ZT_PEER_ROLE_LEAF; } @@ -290,22 +302,32 @@ bool Topology::addWorld(const World &newWorld) if (existing->shouldBeReplacedBy(newWorld)) *existing = newWorld; else return false; - } else if ((newWorld.type() == World::TYPE_MOON)&&(std::find(_contactingMoons.begin(),_contactingMoons.end(),Address(newWorld.id() >> 24)) != _contactingMoons.end())) { - _moons.push_back(newWorld); - existing = &(_moons.back()); - - std::vector
cm; - for(std::vector
::const_iterator m(_contactingMoons.begin());m!=_contactingMoons.end();++m) { - if (m->toInt() != ((existing->id() >> 24) & 0xffffffffffULL)) - cm.push_back(*m); + } else if (newWorld.type() == World::TYPE_MOON) { + for(std::vector< std::pair >::const_iterator m(_moonSeeds.begin());m!=_moonSeeds.end();++m) { + if (m->first == newWorld.id()) { + for(std::vector::const_iterator r(newWorld.roots().begin());r!=newWorld.roots().end();++r) { + if (r->identity.address() == m->second) { + _moonSeeds.erase(m); + m = _moonSeeds.end(); // cause outer loop to terminate + _moons.push_back(newWorld); + existing = &(_moons.back()); + break; + } + } + } } - _contactingMoons.swap(cm); - } else return false; + if (!existing) + return false; + } else { + return false; + } char savePath[64]; - if (existing->type() == World::TYPE_MOON) + if (existing->type() == World::TYPE_MOON) { Utils::snprintf(savePath,sizeof(savePath),"moons.d/%.16llx.moon",existing->id()); - else Utils::scopy(savePath,sizeof(savePath),"planet"); + } else { + Utils::scopy(savePath,sizeof(savePath),"planet"); + } try { Buffer dswtmp; existing->serialize(dswtmp,false); @@ -319,15 +341,8 @@ bool Topology::addWorld(const World &newWorld) return true; } -void Topology::addMoon(const uint64_t id) +void Topology::addMoon(const uint64_t id,const Address &seed) { - { - const Address a(id >> 24); - Mutex::Lock _l(_upstreams_m); - if (std::find(_contactingMoons.begin(),_contactingMoons.end(),a) == _contactingMoons.end()) - _contactingMoons.push_back(a); - } - char savePath[64]; Utils::snprintf(savePath,sizeof(savePath),"moons.d/%.16llx.moon",id); @@ -344,7 +359,11 @@ void Topology::addMoon(const uint64_t id) } } catch ( ... ) {} - RR->node->dataStorePut(savePath,"\0",1,false); // persist that we want to be a member + if (seed) { + Mutex::Lock _l(_upstreams_m); + if (std::find(_moonSeeds.begin(),_moonSeeds.end(),std::pair(id,seed)) == _moonSeeds.end()) + _moonSeeds.push_back(std::pair(id,seed)); + } } void Topology::removeMoon(const uint64_t id) @@ -364,12 +383,12 @@ void Topology::removeMoon(const uint64_t id) } _moons.swap(nm); - std::vector
cm; - for(std::vector
::const_iterator m(_contactingMoons.begin());m!=_contactingMoons.end();++m) { - if (m->toInt() != ((id >> 24) & 0xffffffffffULL)) + std::vector< std::pair > cm; + for(std::vector< std::pair >::const_iterator m(_moonSeeds.begin());m!=_moonSeeds.end();++m) { + if (m->first != id) cm.push_back(*m); } - _contactingMoons.swap(cm); + _moonSeeds.swap(cm); _memoizeUpstreams(); } diff --git a/node/Topology.hpp b/node/Topology.hpp index dca35789..2465de64 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -170,14 +170,11 @@ public: bool isProhibitedEndpoint(const Address &ztaddr,const InetAddress &ipaddr) const; /** - * This gets the known stable endpoints for any upstream - * - * It also adds empty entries for any upstreams we are attempting to - * contact. + * Gets upstreams to contact and their stable endpoints (if known) * * @param eps Hash table to fill with addresses and their stable endpoints */ - inline void getUpstreamStableEndpoints(Hashtable< Address,std::vector > &eps) const + inline void getUpstreamsToContact(Hashtable< Address,std::vector > &eps) const { Mutex::Lock _l(_upstreams_m); for(std::vector::const_iterator i(_planet.roots().begin());i!=_planet.roots().end();++i) { @@ -196,8 +193,8 @@ public: } } } - for(std::vector
::const_iterator m(_contactingMoons.begin());m!=_contactingMoons.end();++m) - eps[*m]; + for(std::vector< std::pair >::const_iterator m(_moonSeeds.begin());m!=_moonSeeds.end();++m) + eps[m->second]; } /** @@ -206,12 +203,7 @@ public: inline std::vector
upstreamAddresses() const { Mutex::Lock _l(_upstreams_m); - std::vector
u(_upstreamAddresses); - for(std::vector
::const_iterator m(_contactingMoons.begin());m!=_contactingMoons.end();++m) { - if (std::find(u.begin(),u.end(),*m) == u.end()) - u.push_back(*m); - } - return u; + return _upstreamAddresses; } /** @@ -260,13 +252,12 @@ public: * Add a moon * * This loads it from moons.d if present, and if not adds it to - * a list of moons that we want to contact. It does not actually - * send anything, though this will happen on the next background - * task loop where pings etc. are checked. + * a list of moons that we want to contact. * * @param id Moon ID + * @param seed If non-NULL, an address of any member of the moon to contact */ - void addMoon(const uint64_t id); + void addMoon(const uint64_t id,const Address &seed); /** * Remove a moon @@ -422,7 +413,7 @@ private: World _planet; std::vector _moons; - std::vector
_contactingMoons; + std::vector< std::pair > _moonSeeds; std::vector
_upstreamAddresses; CertificateOfRepresentation _cor; bool _amRoot; diff --git a/node/Utils.cpp b/node/Utils.cpp index 00b0db06..fb448dd6 100644 --- a/node/Utils.cpp +++ b/node/Utils.cpp @@ -47,21 +47,14 @@ namespace ZeroTier { const char Utils::HEXCHARS[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' }; -static void _Utils_doBurn(char *ptr,unsigned int len) +// Crazy hack to force memory to be securely zeroed in spite of the best efforts of optimizing compilers. +static void _Utils_doBurn(volatile uint8_t *ptr,unsigned int len) { - for(unsigned int i=0;irole) { case ZT_PEER_ROLE_LEAF: prole = "LEAF"; break; - case ZT_PEER_ROLE_UPSTREAM: prole = "UPSTREAM"; break; - case ZT_PEER_ROLE_ROOT: prole = "ROOT"; break; + case ZT_PEER_ROLE_MOON: prole = "MOON"; break; + case ZT_PEER_ROLE_PLANET: prole = "PLANET"; break; } Utils::snprintf(json,sizeof(json), diff --git a/service/OneService.cpp b/service/OneService.cpp index 9a1503e5..6465463b 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -707,7 +707,7 @@ public: for(std::vector::iterator f(moonsDotD.begin());f!=moonsDotD.end();++f) { std::size_t dot = f->find_last_of('.'); if ((dot == 16)&&(f->substr(16) == ".moon")) - _node->orbit(Utils::hexStrToU64(f->substr(0,dot).c_str())); + _node->orbit(Utils::hexStrToU64(f->substr(0,dot).c_str()),0); } } -- cgit v1.2.3 From 4b115665057a334c08e427e0f34a4e3a48514ea1 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 13 Feb 2017 14:27:08 -0800 Subject: Integrate moon concept into http config bus, and clean up that code quite a bit. --- include/ZeroTierOne.h | 10 - node/Node.cpp | 12 +- node/Node.hpp | 6 + node/World.hpp | 10 + service/ControlPlane.cpp | 577 +++++++++++++++++++---------------------------- service/ControlPlane.hpp | 4 +- service/OneService.cpp | 2 +- 7 files changed, 263 insertions(+), 358 deletions(-) (limited to 'service/OneService.cpp') diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 38ae7d8a..9690489a 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -442,16 +442,6 @@ typedef struct */ uint64_t address; - /** - * Current world ID - */ - uint64_t worldId; - - /** - * Current world revision/timestamp - */ - uint64_t worldTimestamp; - /** * Public identity in string-serialized form (safe to send to others) * diff --git a/node/Node.cpp b/node/Node.cpp index 388a4fb2..6dc89387 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -362,8 +362,6 @@ uint64_t Node::address() const void Node::status(ZT_NodeStatus *status) const { status->address = RR->identity.address().toInt(); - status->worldId = RR->topology->planetWorldId(); - status->worldTimestamp = RR->topology->planetWorldTimestamp(); status->publicIdentity = RR->publicIdentityStr.c_str(); status->secretIdentity = RR->secretIdentityStr.c_str(); status->online = _online ? 1 : 0; @@ -714,6 +712,16 @@ void Node::setTrustedPaths(const struct sockaddr_storage *networks,const uint64_ RR->topology->setTrustedPaths(reinterpret_cast(networks),ids,count); } +World Node::planet() const +{ + return RR->topology->planet(); +} + +std::vector Node::moons() const +{ + return RR->topology->moons(); +} + void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &destination,const NetworkConfig &nc,bool sendLegacyFormatConfig) { if (destination == RR->identity.address()) { diff --git a/node/Node.hpp b/node/Node.hpp index d83ce968..a1d4b719 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -24,6 +24,7 @@ #include #include +#include #include "Constants.hpp" @@ -54,6 +55,8 @@ namespace ZeroTier { +class World; + /** * Implementation of Node object as defined in CAPI * @@ -210,6 +213,9 @@ public: void postCircuitTestReport(const ZT_CircuitTestReport *report); void setTrustedPaths(const struct sockaddr_storage *networks,const uint64_t *ids,unsigned int count); + World planet() const; + std::vector moons() const; + /** * Register that we are expecting a reply to a packet ID * diff --git a/node/World.hpp b/node/World.hpp index 8fe6dd2e..6e835bec 100644 --- a/node/World.hpp +++ b/node/World.hpp @@ -135,6 +135,16 @@ public: */ inline uint64_t timestamp() const { return _ts; } + /** + * @return C25519 signature + */ + inline const C25519::Signature &signature() const { return _signature; } + + /** + * @return Public key that must sign next update + */ + inline const C25519::Public &updatesMustBeSignedBy() const { return _updatesMustBeSignedBy; } + /** * Check whether a world update should replace this one * diff --git a/service/ControlPlane.cpp b/service/ControlPlane.cpp index 0b0fbc09..100deeda 100644 --- a/service/ControlPlane.cpp +++ b/service/ControlPlane.cpp @@ -35,77 +35,17 @@ #include "../node/InetAddress.hpp" #include "../node/Node.hpp" #include "../node/Utils.hpp" +#include "../node/World.hpp" + #include "../osdep/OSUtils.hpp" namespace ZeroTier { -static std::string _jsonEscape(const char *s) -{ - std::string buf; - for(const char *p=s;(*p);++p) { - switch(*p) { - case '\t': buf.append("\\t"); break; - case '\b': buf.append("\\b"); break; - case '\r': buf.append("\\r"); break; - case '\n': buf.append("\\n"); break; - case '\f': buf.append("\\f"); break; - case '"': buf.append("\\\""); break; - case '\\': buf.append("\\\\"); break; - case '/': buf.append("\\/"); break; - default: buf.push_back(*p); break; - } - } - return buf; -} -static std::string _jsonEscape(const std::string &s) { return _jsonEscape(s.c_str()); } +namespace { -static std::string _jsonEnumerate(const struct sockaddr_storage *ss,unsigned int count) +static void _networkToJson(nlohmann::json &nj,const ZT_VirtualNetworkConfig *nc,const std::string &portDeviceName,const OneService::NetworkSettings &localSettings) { - std::string buf; - buf.push_back('['); - for(unsigned int i=0;i 0) - buf.push_back(','); - buf.push_back('"'); - buf.append(_jsonEscape(reinterpret_cast(&(ss[i]))->toString())); - buf.push_back('"'); - } - buf.push_back(']'); - return buf; -} -static std::string _jsonEnumerate(const ZT_VirtualNetworkRoute *routes,unsigned int count) -{ - std::string buf; - buf.push_back('['); - for(unsigned int i=0;i 0) - buf.push_back(','); - buf.append("{\"target\":\""); - buf.append(_jsonEscape(reinterpret_cast(&(routes[i].target))->toString())); - buf.append("\",\"via\":"); - if (routes[i].via.ss_family == routes[i].target.ss_family) { - buf.push_back('"'); - buf.append(_jsonEscape(reinterpret_cast(&(routes[i].via))->toIpString())); - buf.append("\","); - } else buf.append("null,"); - char tmp[1024]; - Utils::snprintf(tmp,sizeof(tmp),"\"flags\":%u,\"metric\":%u}",(unsigned int)routes[i].flags,(unsigned int)routes[i].metric); - buf.append(tmp); - } - buf.push_back(']'); - return buf; -} - -static void _jsonAppend(unsigned int depth,std::string &buf,const ZT_VirtualNetworkConfig *nc,const std::string &portDeviceName,const OneService::NetworkSettings &localSettings) -{ - char json[4096]; - char prefix[32]; - - if (depth >= sizeof(prefix)) // sanity check -- shouldn't be possible - return; - for(unsigned int i=0;istatus) { @@ -121,107 +61,48 @@ static void _jsonAppend(unsigned int depth,std::string &buf,const ZT_VirtualNetw case ZT_NETWORK_TYPE_PUBLIC: ntype = "PUBLIC"; break; } - std::string allowManaged = (localSettings.allowManaged) ? "true" : "false"; - if (localSettings.allowManagedWhitelist.size() != 0) { - allowManaged = ""; - for (InetAddress address : localSettings.allowManagedWhitelist) { - if (allowManaged.size() != 0) allowManaged += ','; - allowManaged += address.toIpString() + "/" + std::to_string(address.netmaskBits()); - } + Utils::snprintf(tmp,sizeof(tmp),"%.16llx",nc->nwid); + nj["id"] = tmp; + nj["nwid"] = tmp; + Utils::snprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)((nc->mac >> 40) & 0xff),(unsigned int)((nc->mac >> 32) & 0xff),(unsigned int)((nc->mac >> 24) & 0xff),(unsigned int)((nc->mac >> 16) & 0xff),(unsigned int)((nc->mac >> 8) & 0xff),(unsigned int)(nc->mac & 0xff)); + nj["mac"] = tmp; + nj["name"] = nc->name; + nj["status"] = nstatus; + nj["type"] = ntype; + nj["mtu"] = nc->mtu; + nj["dhcp"] = (bool)(nc->dhcp == 0); + nj["bridge"] = (bool)(nc->bridge == 0); + nj["broadcastEnabled"] = (bool)(nc->broadcastEnabled == 0); + nj["portError"] = nc->portError; + nj["netconfRevision"] = nc->netconfRevision; + nj["portDeviceName"] = portDeviceName; + nj["allowManaged"] = localSettings.allowManaged; + nj["allowGlobal"] = localSettings.allowGlobal; + nj["allowDefault"] = localSettings.allowDefault; + + nlohmann::json aa = nlohmann::json::array(); + for(unsigned int i=0;iassignedAddressCount;++i) { + aa.push_back(reinterpret_cast(&(nc->assignedAddresses[i]))->toString()); } - - Utils::snprintf(json,sizeof(json), - "%s{\n" - "%s\t\"id\": \"%.16llx\",\n" - "%s\t\"nwid\": \"%.16llx\",\n" - "%s\t\"mac\": \"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\",\n" - "%s\t\"name\": \"%s\",\n" - "%s\t\"status\": \"%s\",\n" - "%s\t\"type\": \"%s\",\n" - "%s\t\"mtu\": %u,\n" - "%s\t\"dhcp\": %s,\n" - "%s\t\"bridge\": %s,\n" - "%s\t\"broadcastEnabled\": %s,\n" - "%s\t\"portError\": %d,\n" - "%s\t\"netconfRevision\": %lu,\n" - "%s\t\"assignedAddresses\": %s,\n" - "%s\t\"routes\": %s,\n" - "%s\t\"portDeviceName\": \"%s\",\n" - "%s\t\"allowManaged\": %s,\n" - "%s\t\"allowGlobal\": %s,\n" - "%s\t\"allowDefault\": %s\n" - "%s}", - prefix, - prefix,nc->nwid, - prefix,nc->nwid, - prefix,(unsigned int)((nc->mac >> 40) & 0xff),(unsigned int)((nc->mac >> 32) & 0xff),(unsigned int)((nc->mac >> 24) & 0xff),(unsigned int)((nc->mac >> 16) & 0xff),(unsigned int)((nc->mac >> 8) & 0xff),(unsigned int)(nc->mac & 0xff), - prefix,_jsonEscape(nc->name).c_str(), - prefix,nstatus, - prefix,ntype, - prefix,nc->mtu, - prefix,(nc->dhcp == 0) ? "false" : "true", - prefix,(nc->bridge == 0) ? "false" : "true", - prefix,(nc->broadcastEnabled == 0) ? "false" : "true", - prefix,nc->portError, - prefix,nc->netconfRevision, - prefix,_jsonEnumerate(nc->assignedAddresses,nc->assignedAddressCount).c_str(), - prefix,_jsonEnumerate(nc->routes,nc->routeCount).c_str(), - prefix,_jsonEscape(portDeviceName).c_str(), - prefix,allowManaged.c_str(), - prefix,(localSettings.allowGlobal) ? "true" : "false", - prefix,(localSettings.allowDefault) ? "true" : "false", - prefix); - buf.append(json); -} - -static std::string _jsonEnumerate(unsigned int depth,const ZT_PeerPhysicalPath *pp,unsigned int count) -{ - char json[2048]; - char prefix[32]; - - if (depth >= sizeof(prefix)) // sanity check -- shouldn't be possible - return std::string(); - for(unsigned int i=0;i 0) - buf.push_back(','); - Utils::snprintf(json,sizeof(json), - "{\n" - "%s\t\"address\": \"%s\",\n" - "%s\t\"lastSend\": %llu,\n" - "%s\t\"lastReceive\": %llu,\n" - "%s\t\"active\": %s,\n" - "%s\t\"expired\": %s,\n" - "%s\t\"preferred\": %s,\n" - "%s\t\"trustedPathId\": %llu\n" - "%s}", - prefix,_jsonEscape(reinterpret_cast(&(pp[i].address))->toString()).c_str(), - prefix,pp[i].lastSend, - prefix,pp[i].lastReceive, - prefix,(pp[i].expired != 0) ? "false" : "true", - prefix,(pp[i].expired == 0) ? "false" : "true", - prefix,(pp[i].preferred == 0) ? "false" : "true", - prefix,pp[i].trustedPathId, - prefix); - buf.append(json); + nj["assignedAddresses"] = aa; + + nlohmann::json ra = nlohmann::json::array(); + for(unsigned int i=0;irouteCount;++i) { + nlohmann::json rj; + rj["target"] = reinterpret_cast(&(nc->routes[i].target))->toString(); + if (nc->routes[i].via.ss_family == nc->routes[i].target.ss_family) + rj["via"] = reinterpret_cast(&(nc->routes[i].via))->toIpString(); + else rj["via"] = nlohmann::json(); + rj["flags"] = (int)nc->routes[i].flags; + rj["metric"] = (int)nc->routes[i].metric; + ra.push_back(rj); } - return buf; + nj["routes"] = ra; } -static void _jsonAppend(unsigned int depth,std::string &buf,const ZT_Peer *peer) +static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer) { - char json[2048]; - char prefix[32]; - - if (depth >= sizeof(prefix)) // sanity check -- shouldn't be possible - return; - for(unsigned int i=0;irole) { @@ -230,39 +111,57 @@ static void _jsonAppend(unsigned int depth,std::string &buf,const ZT_Peer *peer) case ZT_PEER_ROLE_PLANET: prole = "PLANET"; break; } - Utils::snprintf(json,sizeof(json), - "%s{\n" - "%s\t\"address\": \"%.10llx\",\n" - "%s\t\"versionMajor\": %d,\n" - "%s\t\"versionMinor\": %d,\n" - "%s\t\"versionRev\": %d,\n" - "%s\t\"version\": \"%d.%d.%d\",\n" - "%s\t\"latency\": %u,\n" - "%s\t\"role\": \"%s\",\n" - "%s\t\"paths\": [%s]\n" - "%s}", - prefix, - prefix,peer->address, - prefix,peer->versionMajor, - prefix,peer->versionMinor, - prefix,peer->versionRev, - prefix,peer->versionMajor,peer->versionMinor,peer->versionRev, - prefix,peer->latency, - prefix,prole, - prefix,_jsonEnumerate(depth+1,peer->paths,peer->pathCount).c_str(), - prefix); - buf.append(json); + Utils::snprintf(tmp,sizeof(tmp),"%.10llx",peer->address); + pj["address"] = tmp; + pj["versionMajor"] = peer->versionMajor; + pj["versionMinor"] = peer->versionMinor; + pj["versionRev"] = peer->versionRev; + Utils::snprintf(tmp,sizeof(tmp),"%d.%d.%d",peer->versionMajor,peer->versionMinor,peer->versionRev); + pj["version"] = tmp; + pj["latency"] = peer->latency; + pj["role"] = prole; + + nlohmann::json pa = nlohmann::json::array(); + for(unsigned int i=0;ipathCount;++i) { + nlohmann::json j; + j["address"] = reinterpret_cast(&(peer->paths[i].address))->toString(); + j["lastSend"] = peer->paths[i].lastSend; + j["lastReceive"] = peer->paths[i].lastReceive; + j["active"] = (bool)(peer->paths[i].expired != 0); + j["expired"] = (bool)(peer->paths[i].expired == 0); + j["preferred"] = (bool)(peer->paths[i].preferred == 0); + j["trustedPathId"] = peer->paths[i].trustedPathId; + pa.push_back(j); + } + pj["paths"] = pa; } -ControlPlane::ControlPlane(OneService *svc,Node *n,const char *uiStaticPath) : - _svc(svc), - _node(n), - _controller((EmbeddedNetworkController *)0), - _uiStaticPath((uiStaticPath) ? uiStaticPath : "") +static void _moonToJson(nlohmann::json &mj,const World &world) { + mj["id"] = world.id(); + mj["timestamp"] = world.timestamp(); + mj["signature"] = Utils::hex(world.signature().data,world.signature().size()); + mj["updatesMustBeSignedBy"] = Utils::hex(world.updatesMustBeSignedBy().data,world.updatesMustBeSignedBy().size()); + nlohmann::json ra = nlohmann::json::array(); + for(std::vector::const_iterator r(world.roots().begin());r!=world.roots().end();++r) { + nlohmann::json rj; + rj["identity"] = r->identity.toString(false); + nlohmann::json eps = nlohmann::json::array(); + for(std::vector::const_iterator a(r->stableEndpoints.begin());a!=r->stableEndpoints.end();++a) + eps.push_back(a->toString()); + rj["stableEndpoints"] = eps; + ra.push_back(rj); + } + mj["roots"] = ra; + mj["active"] = true; } -ControlPlane::~ControlPlane() +} // anonymous namespace + +ControlPlane::ControlPlane(OneService *svc,Node *n) : + _svc(svc), + _node(n), + _controller((EmbeddedNetworkController *)0) { } @@ -275,10 +174,12 @@ unsigned int ControlPlane::handleRequest( std::string &responseBody, std::string &responseContentType) { - char json[8194]; + char tmp[256]; unsigned int scode = 404; + nlohmann::json res; std::vector ps(OSUtils::split(path.c_str(),"/","","")); std::map urlArgs; + Mutex::Lock _l(_lock); /* Note: this is kind of restricted in what it'll take. It does not support @@ -298,8 +199,6 @@ unsigned int ControlPlane::handleRequest( else urlArgs[a->substr(0,eqpos)] = a->substr(eqpos + 1); } } - } else { - ps.push_back(std::string("index.html")); } bool isAuth = false; @@ -315,148 +214,113 @@ unsigned int ControlPlane::handleRequest( } if (httpMethod == HTTP_GET) { - - std::string ext; - std::size_t dotIdx = ps[0].find_last_of('.'); - if (dotIdx != std::string::npos) - ext = ps[0].substr(dotIdx); - - if ((ps.size() == 1)&&(ext.length() >= 2)&&(ext[0] == '.')) { - /* Static web pages can be served without authentication to enable a simple web - * UI. This is still only allowed from approved IP addresses. Anything with a - * dot in the first path element (e.g. foo.html) is considered a static page, - * as nothing in the API is so named. */ - - if (_uiStaticPath.length() > 0) { - if (ext == ".html") - responseContentType = "text/html"; - else if (ext == ".js") - responseContentType = "application/javascript"; - else if (ext == ".jsx") - responseContentType = "text/jsx"; - else if (ext == ".json") - responseContentType = "application/json"; - else if (ext == ".css") - responseContentType = "text/css"; - else if (ext == ".png") - responseContentType = "image/png"; - else if (ext == ".jpg") - responseContentType = "image/jpeg"; - else if (ext == ".gif") - responseContentType = "image/gif"; - else if (ext == ".txt") - responseContentType = "text/plain"; - else if (ext == ".xml") - responseContentType = "text/xml"; - else if (ext == ".svg") - responseContentType = "image/svg+xml"; - else responseContentType = "application/octet-stream"; - scode = OSUtils::readFile((_uiStaticPath + ZT_PATH_SEPARATOR_S + ps[0]).c_str(),responseBody) ? 200 : 404; - } else { - scode = 404; - } - - } else if (isAuth) { - /* Things that require authentication -- a.k.a. everything but static web app pages. */ - + if (isAuth) { if (ps[0] == "status") { - responseContentType = "application/json"; - ZT_NodeStatus status; _node->status(&status); - std::string clusterJson; + Utils::snprintf(tmp,sizeof(tmp),"%.10llx",status.address); + res["address"] = tmp; + res["publicIdentity"] = status.publicIdentity; + res["online"] = (bool)status.online; + res["tcpFallbackActive"] = _svc->tcpFallbackActive(); + res["versionMajor"] = ZEROTIER_ONE_VERSION_MAJOR; + res["versionMinor"] = ZEROTIER_ONE_VERSION_MINOR; + res["versionRev"] = ZEROTIER_ONE_VERSION_REVISION; + res["versionBuild"] = ZEROTIER_ONE_VERSION_BUILD; + Utils::snprintf(tmp,sizeof(tmp),"%d.%d.%d",ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION); + res["version"] = tmp; + res["clock"] = OSUtils::now(); + + World planet(_node->planet()); + res["planetWorldId"] = planet.id(); + res["planetWorldTimestamp"] = planet.timestamp(); + #ifdef ZT_ENABLE_CLUSTER - { - ZT_ClusterStatus cs; - _node->clusterStatus(&cs); - - if (cs.clusterSize >= 1) { - char t[1024]; - Utils::snprintf(t,sizeof(t),"{\n\t\t\"myId\": %u,\n\t\t\"clusterSize\": %u,\n\t\t\"members\": [",cs.myId,cs.clusterSize); - clusterJson.append(t); - for(unsigned int i=0;iclusterStatus(&cs); + if (cs.clusterSize >= 1) { + nlohmann::json cja = nlohmann::json::array(); + for(unsigned int i=0;itcpFallbackActive()) ? "true" : "false", - ZEROTIER_ONE_VERSION_MAJOR, - ZEROTIER_ONE_VERSION_MINOR, - ZEROTIER_ONE_VERSION_REVISION, - ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION, - (unsigned long long)OSUtils::now(), - ((clusterJson.length() > 0) ? clusterJson.c_str() : "null")); - responseBody = json; - scode = 200; - } else if (ps[0] == "settings") { - responseContentType = "application/json"; - responseBody = "{}"; // TODO scode = 200; + } else if (ps[0] == "moon") { + std::vector moons(_node->moons()); + if (ps.size() == 1) { + // Return [array] of all moons + + res = nlohmann::json::array(); + for(std::vector::const_iterator m(moons.begin());m!=moons.end();++m) { + nlohmann::json mj; + _moonToJson(mj,*m); + res.push_back(mj); + } + + scode = 2;; + } else { + // Return a single moon by ID + + const uint64_t id = Utils::hexStrToU64(ps[1].c_str()); + for(std::vector::const_iterator m(moons.begin());m!=moons.end();++m) { + if (m->id() == id) { + _moonToJson(res,*m); + scode = 200; + break; + } + } + + } } else if (ps[0] == "network") { ZT_VirtualNetworkList *nws = _node->networks(); if (nws) { if (ps.size() == 1) { // Return [array] of all networks - responseContentType = "application/json"; - responseBody = "[\n"; + + res = nlohmann::json::array(); for(unsigned long i=0;inetworkCount;++i) { - if (i > 0) - responseBody.append(","); OneService::NetworkSettings localSettings; _svc->getNetworkSettings(nws->networks[i].nwid,localSettings); - _jsonAppend(1,responseBody,&(nws->networks[i]),_svc->portDeviceName(nws->networks[i].nwid),localSettings); + nlohmann::json nj; + _networkToJson(nj,&(nws->networks[i]),_svc->portDeviceName(nws->networks[i].nwid),localSettings); + res.push_back(nj); } - responseBody.append("\n]\n"); + scode = 200; } else if (ps.size() == 2) { // Return a single network by ID or 404 if not found - uint64_t wantnw = Utils::hexStrToU64(ps[1].c_str()); + + const uint64_t wantnw = Utils::hexStrToU64(ps[1].c_str()); for(unsigned long i=0;inetworkCount;++i) { if (nws->networks[i].nwid == wantnw) { - responseContentType = "application/json"; OneService::NetworkSettings localSettings; _svc->getNetworkSettings(nws->networks[i].nwid,localSettings); - _jsonAppend(0,responseBody,&(nws->networks[i]),_svc->portDeviceName(nws->networks[i].nwid),localSettings); - responseBody.push_back('\n'); + _networkToJson(res,&(nws->networks[i]),_svc->portDeviceName(nws->networks[i].nwid),localSettings); scode = 200; break; } } - } // else 404 + + } else scode = 404; _node->freeQueryResult((void *)nws); } else scode = 500; } else if (ps[0] == "peer") { @@ -464,54 +328,78 @@ unsigned int ControlPlane::handleRequest( if (pl) { if (ps.size() == 1) { // Return [array] of all peers - responseContentType = "application/json"; - responseBody = "[\n"; + + res = nlohmann::json::array(); for(unsigned long i=0;ipeerCount;++i) { - if (i > 0) - responseBody.append(",\n"); - _jsonAppend(1,responseBody,&(pl->peers[i])); + nlohmann::json pj; + _peerToJson(pj,&(pl->peers[i])); + res.push_back(pj); } - responseBody.append("\n]\n"); + scode = 200; } else if (ps.size() == 2) { // Return a single peer by ID or 404 if not found + uint64_t wantp = Utils::hexStrToU64(ps[1].c_str()); for(unsigned long i=0;ipeerCount;++i) { if (pl->peers[i].address == wantp) { - responseContentType = "application/json"; - _jsonAppend(0,responseBody,&(pl->peers[i])); - responseBody.push_back('\n'); + _peerToJson(res,&(pl->peers[i])); scode = 200; break; } } - } // else 404 + + } else scode = 404; _node->freeQueryResult((void *)pl); } else scode = 500; - } else if (ps[0] == "newIdentity") { - // Return a newly generated ZeroTier identity -- this is primarily for debugging - // and testing to make it easy for automated test scripts to generate test IDs. - Identity newid; - newid.generate(); - responseBody = newid.toString(true); - responseContentType = "text/plain"; - scode = 200; } else { - if (_controller) + if (_controller) { scode = _controller->handleControlPlaneHttpGET(std::vector(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType); - else scode = 404; + } else scode = 404; } } else scode = 401; // isAuth == false - } else if ((httpMethod == HTTP_POST)||(httpMethod == HTTP_PUT)) { - if (isAuth) { - if (ps[0] == "settings") { - // TODO + if (ps[0] == "moon") { + if (ps.size() == 2) { + + uint64_t seed = 0; + try { + nlohmann::json j(OSUtils::jsonParse(body)); + if (j.is_object()) { + seed = OSUtils::jsonInt(j["seed"],0); + } + } catch ( ... ) { + // discard invalid JSON + } + + std::vector moons(_node->moons()); + const uint64_t id = Utils::hexStrToU64(ps[1].c_str()); + for(std::vector::const_iterator m(moons.begin());m!=moons.end();++m) { + if (m->id() == id) { + _moonToJson(res,*m); + scode = 200; + break; + } + } + + if ((scode != 200)&&(seed != 0)) { + res["seed"] = seed; + res["id"] = id; + res["roots"] = nlohmann::json::array(); + res["timestamp"] = 0; + res["signature"] = nlohmann::json(); + res["updatesMustBeSignedBy"] = nlohmann::json(); + res["active"] = false; + _node->orbit(id,seed); + } + + } else scode = 404; } else if (ps[0] == "network") { if (ps.size() == 2) { + uint64_t wantnw = Utils::hexStrToU64(ps[1].c_str()); _node->join(wantnw,(void *)0); // does nothing if we are a member ZT_VirtualNetworkList *nws = _node->networks(); @@ -536,17 +424,16 @@ unsigned int ControlPlane::handleRequest( } _svc->setNetworkSettings(nws->networks[i].nwid,localSettings); + _networkToJson(res,&(nws->networks[i]),_svc->portDeviceName(nws->networks[i].nwid),localSettings); - responseContentType = "application/json"; - _jsonAppend(0,responseBody,&(nws->networks[i]),_svc->portDeviceName(nws->networks[i].nwid),localSettings); - responseBody.push_back('\n'); scode = 200; break; } } _node->freeQueryResult((void *)nws); } else scode = 500; - } + + } else scode = 404; } else { if (_controller) scode = _controller->handleControlPlaneHttpPOST(std::vector(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType); @@ -554,12 +441,16 @@ unsigned int ControlPlane::handleRequest( } } else scode = 401; // isAuth == false - } else if (httpMethod == HTTP_DELETE) { - if (isAuth) { - if (ps[0] == "network") { + if (ps[0] == "moon") { + if (ps.size() == 2) { + _node->deorbit(Utils::hexStrToU64(ps[1].c_str())); + res["result"] = true; + scode = 200; + } // else 404 + } else if (ps[0] == "network") { ZT_VirtualNetworkList *nws = _node->networks(); if (nws) { if (ps.size() == 2) { @@ -567,8 +458,7 @@ unsigned int ControlPlane::handleRequest( for(unsigned long i=0;inetworkCount;++i) { if (nws->networks[i].nwid == wantnw) { _node->leave(wantnw,(void **)0); - responseBody = "true"; - responseContentType = "application/json"; + res["result"] = true; scode = 200; break; } @@ -582,13 +472,16 @@ unsigned int ControlPlane::handleRequest( else scode = 404; } - } else { - scode = 401; // isAuth = false - } - + } else scode = 401; // isAuth = false } else { scode = 400; - responseBody = "Method not supported."; + } + + if (responseBody.length() == 0) { + if ((res.is_object())||(res.is_array())) + responseBody = OSUtils::jsonDump(res); + else responseBody = "{}"; + responseContentType = "application/json"; } // Wrap result in jsonp function call if the user included a jsonp= url argument. diff --git a/service/ControlPlane.hpp b/service/ControlPlane.hpp index ec9b94d7..a1f743cb 100644 --- a/service/ControlPlane.hpp +++ b/service/ControlPlane.hpp @@ -40,8 +40,7 @@ struct InetAddress; class ControlPlane { public: - ControlPlane(OneService *svc,Node *n,const char *uiStaticPath); - ~ControlPlane(); + ControlPlane(OneService *svc,Node *n); /** * Set controller, which will be available under /controller @@ -88,7 +87,6 @@ private: OneService *const _svc; Node *const _node; EmbeddedNetworkController *_controller; - std::string _uiStaticPath; std::set _authTokens; Mutex _lock; }; diff --git a/service/OneService.cpp b/service/OneService.cpp index 6465463b..d56333c0 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -690,7 +690,7 @@ public: } #endif - _controlPlane = new ControlPlane(this,_node,(_homePath + ZT_PATH_SEPARATOR_S "ui").c_str()); + _controlPlane = new ControlPlane(this,_node); _controlPlane->addAuthToken(authToken.c_str()); _controlPlane->setController(_controller); -- cgit v1.2.3 From cd7b571da071a4af4afd978b920e1b8372c880a3 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 13 Feb 2017 15:55:38 -0800 Subject: Add a local.conf option to set the port. --- service/OneService.cpp | 1 + service/README.md | 1 + 2 files changed, 2 insertions(+) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index d56333c0..aa90798f 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -987,6 +987,7 @@ public: _interfacePrefixBlacklist.clear(); json &settings = _localConfig["settings"]; if (settings.is_object()) { + _primaryPort = (unsigned int)OSUtils::jsonInt(settings["primaryPort"],(uint64_t)_primaryPort) & 0xffff; _portMappingEnabled = OSUtils::jsonBool(settings["portMappingEnabled"],true); const std::string up(OSUtils::jsonString(settings["softwareUpdate"],ZT_SOFTWARE_UPDATE_DEFAULT)); diff --git a/service/README.md b/service/README.md index d3bc5338..bdf713c1 100644 --- a/service/README.md +++ b/service/README.md @@ -24,6 +24,7 @@ Settings available in `local.conf` (this is not valid JSON, and JSON does not al } }, "settings": { /* Other global settings */ + "primaryPort": 0-65535, /* If set, override default port of 9993 and any command line port */ "portMappingEnabled": true|false, /* If true (the default), try to use uPnP or NAT-PMP to map ports */ "softwareUpdate": "apply"|"download"|"disable", /* Automatically apply updates, just download, or disable built-in software updates */ "softwareUpdateDist": true|false, /* If true, distribute software updates (only really useful to ZeroTier, Inc. itself, default is false) */ -- cgit v1.2.3 From b5b335a6f844a21ac23e260b6deb8f69bdc61129 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Thu, 16 Feb 2017 16:41:26 -0800 Subject: Route re-add patch for linux build on Synology devices --- make-linux.mk | 4 ++++ osdep/LinuxEthernetTap.cpp | 2 ++ service/OneService.cpp | 7 ++++++- 3 files changed, 12 insertions(+), 1 deletion(-) (limited to 'service/OneService.cpp') diff --git a/make-linux.mk b/make-linux.mk index 29d19830..68f865bf 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -41,6 +41,10 @@ ifeq ($(ZT_ENABLE_CLUSTER),1) DEFS+=-DZT_ENABLE_CLUSTER endif +ifeq ($(ZT_SYNOLOGY), 1) + DEFS+=-D__SYNOLOGY__ +endif + ifeq ($(ZT_TRACE),1) DEFS+=-DZT_TRACE endif diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index e336bb67..55a6d9f6 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -221,8 +221,10 @@ bool LinuxEthernetTap::addIp(const InetAddress &ip) return false; std::vector allIps(ips()); +#ifndef __SYNOLOGY__ if (std::binary_search(allIps.begin(),allIps.end(),ip)) return true; +#endif // Remove and reconfigure if address is the same but netmask is different for(std::vector::iterator i(allIps.begin());i!=allIps.end();++i) { diff --git a/service/OneService.cpp b/service/OneService.cpp index aa90798f..dc3e0ed1 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1088,12 +1088,17 @@ public: } } for(std::vector::iterator ip(newManagedIps.begin());ip!=newManagedIps.end();++ip) { +#ifdef __SYNOLOGY__ + if (!n.tap->addIp(*ip)) + fprintf(stderr,"ERROR: unable to add ip address %s" ZT_EOL_S, ip->toString().c_str()); +#else if (std::find(n.managedIps.begin(),n.managedIps.end(),*ip) == n.managedIps.end()) { + if (!n.tap->addIp(*ip)) fprintf(stderr,"ERROR: unable to add ip address %s" ZT_EOL_S, ip->toString().c_str()); } +#endif } - n.managedIps.swap(newManagedIps); } -- cgit v1.2.3 From 946e413997560d1bb714e6f7099429b18f9fecee Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Tue, 21 Feb 2017 17:55:00 -0800 Subject: properly fill out ifcfg files. also removed route re-add code for synology --- osdep/Binder.hpp | 8 ++----- osdep/LinuxEthernetTap.cpp | 58 ++++++++++++++++++++++++++++++++++++++++++++-- osdep/LinuxEthernetTap.hpp | 1 + service/OneService.cpp | 11 ++++----- 4 files changed, 64 insertions(+), 14 deletions(-) (limited to 'service/OneService.cpp') diff --git a/osdep/Binder.hpp b/osdep/Binder.hpp index accff86f..9829f170 100644 --- a/osdep/Binder.hpp +++ b/osdep/Binder.hpp @@ -63,12 +63,8 @@ * * OneService also does this on detected restarts. */ -#ifdef __SYNOLOGY___ - // Synology devices like to kill routes, check more often and re-add - #define ZT_BINDER_REFRESH_PERIOD 10000 -#else - #define ZT_BINDER_REFRESH_PERIOD 30000 -#endif +#define ZT_BINDER_REFRESH_PERIOD 30000 + namespace ZeroTier { /** diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index 55a6d9f6..9d3773f0 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -109,7 +109,12 @@ LinuxEthernetTap::LinuxEthernetTap( if (!recalledDevice) { int devno = 0; do { +#ifdef __SYNOLOGY__ + devno+=50; // Arbitrary number to prevent interface name conflicts + Utils::snprintf(ifr.ifr_name,sizeof(ifr.ifr_name),"eth%d",devno++); +#else Utils::snprintf(ifr.ifr_name,sizeof(ifr.ifr_name),"zt%d",devno++); +#endif Utils::snprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); } while (stat(procpath,&sbuf) == 0); // try zt#++ until we find one that does not exist } @@ -215,16 +220,65 @@ static bool ___removeIp(const std::string &_dev,const InetAddress &ip) } } +bool LinuxEthernetTap::addIpSyn(std::vector ips) +{ + // Here we fill out interface config (ifcfg-dev) to prevent it from being killed + std::string filepath = "/etc/sysconfig/network-scripts/ifcfg-"+_dev; + std::string cfg_contents = "DEVICE="+_dev+"\nBOOTPROTO=static"; + int ip4=0,ip6=0,ip4_tot=0,ip6_tot=0; + + long cpid = (long)vfork(); + if (cpid == 0) { + OSUtils::redirectUnixOutputs("/dev/null",(const char *)0); + setenv("PATH", "/sbin:/bin:/usr/sbin:/usr/bin", 1); + // We must know if there is at least (one) of each protocol version so we + // can properly enumerate address/netmask combinations in the ifcfg-dev file + for(int i=0; i 1 ? std::to_string(ip4) : ""; + cfg_contents += "\nIPADDR"+numstr4+"="+ips[i].toIpString() + + "\nNETMASK"+numstr4+"="+ips[i].netmask().toIpString()+"\n"; + ip4++; + } + else { + std::string numstr6 = ip6_tot > 1 ? std::to_string(ip6) : ""; + cfg_contents += "\nIPV6ADDR"+numstr6+"="+ips[i].toIpString() + + "\nNETMASK"+numstr6+"="+ips[i].netmask().toIpString()+"\n"; + ip6++; + } + } + OSUtils::writeFile(filepath.c_str(), cfg_contents.c_str(), cfg_contents.length()); + // Finaly, add IPs + for(int i=0; i 0) { + int exitcode = -1; + ::waitpid(cpid,&exitcode,0); + return (exitcode == 0); + } + return true; +} + bool LinuxEthernetTap::addIp(const InetAddress &ip) { if (!ip) return false; std::vector allIps(ips()); -#ifndef __SYNOLOGY__ if (std::binary_search(allIps.begin(),allIps.end(),ip)) return true; -#endif // Remove and reconfigure if address is the same but netmask is different for(std::vector::iterator i(allIps.begin());i!=allIps.end();++i) { diff --git a/osdep/LinuxEthernetTap.hpp b/osdep/LinuxEthernetTap.hpp index cbb58efb..acdff9dd 100644 --- a/osdep/LinuxEthernetTap.hpp +++ b/osdep/LinuxEthernetTap.hpp @@ -52,6 +52,7 @@ public: void setEnabled(bool en); bool enabled() const; bool addIp(const InetAddress &ip); + bool addIpSyn(std::vector ips); 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); diff --git a/service/OneService.cpp b/service/OneService.cpp index dc3e0ed1..81950e26 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1087,18 +1087,17 @@ public: fprintf(stderr,"ERROR: unable to remove ip address %s" ZT_EOL_S, ip->toString().c_str()); } } - for(std::vector::iterator ip(newManagedIps.begin());ip!=newManagedIps.end();++ip) { #ifdef __SYNOLOGY__ - if (!n.tap->addIp(*ip)) - fprintf(stderr,"ERROR: unable to add ip address %s" ZT_EOL_S, ip->toString().c_str()); + if (!n.tap->addIpSyn(newManagedIps)) + fprintf(stderr,"ERROR: unable to add ip addresses to ifcfg" ZT_EOL_S); #else + for(std::vector::iterator ip(newManagedIps.begin());ip!=newManagedIps.end();++ip) { if (std::find(n.managedIps.begin(),n.managedIps.end(),*ip) == n.managedIps.end()) { - if (!n.tap->addIp(*ip)) fprintf(stderr,"ERROR: unable to add ip address %s" ZT_EOL_S, ip->toString().c_str()); - } -#endif + } } +#endif n.managedIps.swap(newManagedIps); } -- cgit v1.2.3 From a577b8d3816069a448a946302048a377b55cd74a Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 1 Mar 2017 16:33:34 -0800 Subject: Update how controller handles circuit tests -- save results to filesystem. --- controller/EmbeddedNetworkController.cpp | 137 +++++++++++++++---------------- controller/EmbeddedNetworkController.hpp | 15 ++-- controller/JSONDB.cpp | 25 ++++-- controller/JSONDB.hpp | 6 +- controller/README.md | 11 +-- node/Peer.cpp | 6 +- service/OneService.cpp | 2 +- 7 files changed, 100 insertions(+), 102 deletions(-) (limited to 'service/OneService.cpp') diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index 0e57fc14..7915765b 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -428,9 +428,9 @@ static bool _parseRule(json &r,ZT_VirtualNetworkRule &rule) return false; } -EmbeddedNetworkController::EmbeddedNetworkController(Node *node,const char *dbPath,FILE *feed) : +EmbeddedNetworkController::EmbeddedNetworkController(Node *node,const char *dbPath) : _threadsStarted(false), - _db(dbPath,feed), + _db(dbPath), _node(node) { OSUtils::mkdir(dbPath); @@ -546,21 +546,6 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( return 200; } - } else if ((path[2] == "test")&&(path.size() >= 4)) { - - Mutex::Lock _l(_circuitTests_m); - std::map< uint64_t,_CircuitTestEntry >::iterator cte(_circuitTests.find(Utils::hexStrToU64(path[3].c_str()))); - if ((cte != _circuitTests.end())&&(cte->second.test)) { - - responseBody = "["; - responseBody.append(cte->second.jsonResults); - responseBody.push_back(']'); - responseContentType = "application/json"; - - return 200; - - } // else 404 - } // else 404 } else { @@ -755,9 +740,10 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( return 200; } else if ((path.size() == 3)&&(path[2] == "test")) { - Mutex::Lock _l(_circuitTests_m); + Mutex::Lock _l(_tests_m); - ZT_CircuitTest *test = (ZT_CircuitTest *)malloc(sizeof(ZT_CircuitTest)); + _tests.push_back(ZT_CircuitTest()); + ZT_CircuitTest *const test = &(_tests.back()); memset(test,0,sizeof(ZT_CircuitTest)); Utils::getSecureRandom(&(test->testId),sizeof(test->testId)); @@ -781,7 +767,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( test->reportAtEveryHop = (OSUtils::jsonBool(b["reportAtEveryHop"],true) ? 1 : 0); if (!test->hopCount) { - ::free((void *)test); + _tests.pop_back(); responseBody = "{ \"message\": \"a test must contain at least one hop\" }"; responseContentType = "application/json"; return 400; @@ -789,18 +775,18 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( test->timestamp = OSUtils::now(); - _CircuitTestEntry &te = _circuitTests[test->testId]; - te.test = test; - te.jsonResults = ""; - - if (_node) + if (_node) { _node->circuitTestBegin(test,&(EmbeddedNetworkController::_circuitTestCallback)); - else return 500; + } else { + _tests.pop_back(); + return 500; + } char json[1024]; Utils::snprintf(json,sizeof(json),"{\"testId\":\"%.16llx\"}",test->testId); responseBody = json; responseContentType = "application/json"; + return 200; } // else 404 @@ -1137,62 +1123,67 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpDELETE( void EmbeddedNetworkController::threadMain() throw() { + uint64_t lastCircuitTestCheck = 0; for(;;) { - _RQEntry *const qe = _queue.get(); + _RQEntry *const qe = _queue.get(); // waits on next request if (!qe) break; // enqueue a NULL to terminate threads try { _request(qe->nwid,qe->fromAddr,qe->requestPacketId,qe->identity,qe->metaData); } catch ( ... ) {} delete qe; + + uint64_t now = OSUtils::now(); + if ((now - lastCircuitTestCheck) > ZT_EMBEDDEDNETWORKCONTROLLER_CIRCUIT_TEST_EXPIRATION) { + lastCircuitTestCheck = now; + Mutex::Lock _l(_tests_m); + for(std::list< ZT_CircuitTest >::iterator i(_tests.begin());i!=_tests.end();) { + if ((now - i->timestamp) > ZT_EMBEDDEDNETWORKCONTROLLER_CIRCUIT_TEST_EXPIRATION) { + _node->circuitTestEnd(&(*i)); + _tests.erase(i++); + } else ++i; + } + } } } void EmbeddedNetworkController::_circuitTestCallback(ZT_Node *node,ZT_CircuitTest *test,const ZT_CircuitTestReport *report) { - char tmp[65535]; + char tmp[1024],id[128]; EmbeddedNetworkController *const self = reinterpret_cast(test->ptr); - if (!test) - return; - if (!report) - return; - - Mutex::Lock _l(self->_circuitTests_m); - std::map< uint64_t,_CircuitTestEntry >::iterator cte(self->_circuitTests.find(test->testId)); - - if (cte == self->_circuitTests.end()) { // sanity check: a circuit test we didn't launch? - self->_node->circuitTestEnd(test); - ::free((void *)test); - return; - } + if ((!test)||(!report)||(!test->credentialNetworkId)) return; // sanity check + const uint64_t now = OSUtils::now(); + Utils::snprintf(id,sizeof(id),"network/%.16llx/test/%.16llx-%.16llx-%.10llx-%.10llx",test->credentialNetworkId,test->testId,now,report->upstream,report->current); Utils::snprintf(tmp,sizeof(tmp), - "%s{\n" - "\t\"timestamp\": %llu," ZT_EOL_S - "\t\"testId\": \"%.16llx\"," ZT_EOL_S - "\t\"upstream\": \"%.10llx\"," ZT_EOL_S - "\t\"current\": \"%.10llx\"," ZT_EOL_S - "\t\"receivedTimestamp\": %llu," ZT_EOL_S - "\t\"sourcePacketId\": \"%.16llx\"," ZT_EOL_S - "\t\"flags\": %llu," ZT_EOL_S - "\t\"sourcePacketHopCount\": %u," ZT_EOL_S - "\t\"errorCode\": %u," ZT_EOL_S - "\t\"vendor\": %d," ZT_EOL_S - "\t\"protocolVersion\": %u," ZT_EOL_S - "\t\"majorVersion\": %u," ZT_EOL_S - "\t\"minorVersion\": %u," ZT_EOL_S - "\t\"revision\": %u," ZT_EOL_S - "\t\"platform\": %d," ZT_EOL_S - "\t\"architecture\": %d," ZT_EOL_S - "\t\"receivedOnLocalAddress\": \"%s\"," ZT_EOL_S - "\t\"receivedFromRemoteAddress\": \"%s\"" ZT_EOL_S - "}", - ((cte->second.jsonResults.length() > 0) ? ",\n" : ""), - (unsigned long long)report->timestamp, + "{\"id\": \"%s\"," + "\"timestamp\": %llu," + "\"networkId\": \"%.16llx\"," + "\"testId\": \"%.16llx\"," + "\"upstream\": \"%.10llx\"," + "\"current\": \"%.10llx\"," + "\"receivedTimestamp\": %llu," + "\"sourcePacketId\": \"%.16llx\"," + "\"flags\": %llu," + "\"sourcePacketHopCount\": %u," + "\"errorCode\": %u," + "\"vendor\": %d," + "\"protocolVersion\": %u," + "\"majorVersion\": %u," + "\"minorVersion\": %u," + "\"revision\": %u," + "\"platform\": %d," + "\"architecture\": %d," + "\"receivedOnLocalAddress\": \"%s\"," + "\"receivedFromRemoteAddress\": \"%s\"," + "\"receivedFromLinkQuality\": %f}", + id + 30, // last bit only, not leading path + (unsigned long long)test->timestamp, + (unsigned long long)test->credentialNetworkId, (unsigned long long)test->testId, (unsigned long long)report->upstream, (unsigned long long)report->current, - (unsigned long long)OSUtils::now(), + (unsigned long long)now, (unsigned long long)report->sourcePacketId, (unsigned long long)report->flags, report->sourcePacketHopCount, @@ -1205,9 +1196,11 @@ void EmbeddedNetworkController::_circuitTestCallback(ZT_Node *node,ZT_CircuitTes (int)report->platform, (int)report->architecture, reinterpret_cast(&(report->receivedOnLocalAddress))->toString().c_str(), - reinterpret_cast(&(report->receivedFromRemoteAddress))->toString().c_str()); + reinterpret_cast(&(report->receivedFromRemoteAddress))->toString().c_str(), + ((double)report->receivedFromLinkQuality / (double)ZT_PATH_LINK_QUALITY_MAX)); - cte->second.jsonResults.append(tmp); + Mutex::Lock _l(self->_db_m); + self->_db.writeRaw(id,std::string(tmp)); } void EmbeddedNetworkController::_request( @@ -1354,12 +1347,12 @@ void EmbeddedNetworkController::_request( if (requestPacketId) { // only log if this is a request, not for generated pushes json rlEntry = json::object(); rlEntry["ts"] = now; - rlEntry["authorized"] = (authorizedBy) ? true : false; - rlEntry["authorizedBy"] = (authorizedBy) ? authorizedBy : ""; - rlEntry["clientMajorVersion"] = metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION,0); - rlEntry["clientMinorVersion"] = metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MINOR_VERSION,0); - rlEntry["clientRevision"] = metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_REVISION,0); - rlEntry["clientProtocolVersion"] = metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_PROTOCOL_VERSION,0); + rlEntry["auth"] = (authorizedBy) ? true : false; + rlEntry["authBy"] = (authorizedBy) ? authorizedBy : ""; + rlEntry["vMajor"] = metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION,0); + rlEntry["vMinor"] = metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MINOR_VERSION,0); + rlEntry["vRev"] = metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_REVISION,0); + rlEntry["vProto"] = metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_PROTOCOL_VERSION,0); if (fromAddr) rlEntry["fromAddr"] = fromAddr.toString(); diff --git a/controller/EmbeddedNetworkController.hpp b/controller/EmbeddedNetworkController.hpp index 3e39eaf5..ab7cdd53 100644 --- a/controller/EmbeddedNetworkController.hpp +++ b/controller/EmbeddedNetworkController.hpp @@ -46,6 +46,9 @@ // Number of background threads to start -- not actually started until needed #define ZT_EMBEDDEDNETWORKCONTROLLER_BACKGROUND_THREAD_COUNT 2 +// TTL for circuit tests +#define ZT_EMBEDDEDNETWORKCONTROLLER_CIRCUIT_TEST_EXPIRATION 120000 + namespace ZeroTier { class Node; @@ -56,9 +59,8 @@ public: /** * @param node Parent node * @param dbPath Path to store data - * @param feed FILE to send feed of all data and changes to (zero-delimited JSON objects) or NULL for none */ - EmbeddedNetworkController(Node *node,const char *dbPath,FILE *feed); + EmbeddedNetworkController(Node *node,const char *dbPath); virtual ~EmbeddedNetworkController(); virtual void init(const Identity &signingId,Sender *sender); @@ -199,13 +201,8 @@ private: NetworkController::Sender *_sender; Identity _signingId; - struct _CircuitTestEntry - { - ZT_CircuitTest *test; - std::string jsonResults; - }; - std::map< uint64_t,_CircuitTestEntry > _circuitTests; - Mutex _circuitTests_m; + std::list< ZT_CircuitTest > _tests; + Mutex _tests_m; std::map< std::pair,uint64_t > _lastRequestTime; Mutex _lastRequestTime_m; diff --git a/controller/JSONDB.cpp b/controller/JSONDB.cpp index 044f791c..1277aabb 100644 --- a/controller/JSONDB.cpp +++ b/controller/JSONDB.cpp @@ -22,6 +22,22 @@ namespace ZeroTier { static const nlohmann::json _EMPTY_JSON(nlohmann::json::object()); +bool JSONDB::writeRaw(const std::string &n,const std::string &obj) +{ + if (!_isValidObjectName(n)) + return false; + + const std::string path(_genPath(n,true)); + if (!path.length()) + return false; + + const std::string buf(obj); + if (!OSUtils::writeFile(path.c_str(),buf)) + return false; + + return true; +} + bool JSONDB::put(const std::string &n,const nlohmann::json &obj) { if (!_isValidObjectName(n)) @@ -35,9 +51,6 @@ bool JSONDB::put(const std::string &n,const nlohmann::json &obj) if (!OSUtils::writeFile(path.c_str(),buf)) return false; - if (_feed) - fwrite(buf.c_str(),buf.length()+1,1,_feed); - _E &e = _db[n]; e.obj = obj; e.lastModifiedOnDisk = OSUtils::getLastModified(path.c_str()); @@ -72,9 +85,6 @@ const nlohmann::json &JSONDB::get(const std::string &n,unsigned long maxSinceChe e->second.obj = OSUtils::jsonParse(buf); e->second.lastModifiedOnDisk = lm; // don't update these if there is a parse error -- try again and again ASAP e->second.lastCheck = now; - - if (_feed) - fwrite(buf.c_str(),buf.length()+1,1,_feed); // it changed, so send to feed (also sends all objects on startup, which we want for Central) } catch ( ... ) {} // parse errors result in "holding pattern" behavior } } @@ -99,9 +109,6 @@ const nlohmann::json &JSONDB::get(const std::string &n,unsigned long maxSinceChe e2.lastModifiedOnDisk = lm; e2.lastCheck = now; - if (_feed) - fwrite(buf.c_str(),buf.length()+1,1,_feed); - return e2.obj; } } diff --git a/controller/JSONDB.hpp b/controller/JSONDB.hpp index 40113655..5b7c5e50 100644 --- a/controller/JSONDB.hpp +++ b/controller/JSONDB.hpp @@ -42,8 +42,7 @@ namespace ZeroTier { class JSONDB { public: - JSONDB(const std::string &basePath,FILE *feed) : - _feed(feed), + JSONDB(const std::string &basePath) : _basePath(basePath) { _reload(_basePath); @@ -55,6 +54,8 @@ public: _reload(_basePath); } + bool writeRaw(const std::string &n,const std::string &obj); + bool put(const std::string &n,const nlohmann::json &obj); inline bool put(const std::string &n1,const std::string &n2,const nlohmann::json &obj) { return this->put((n1 + "/" + n2),obj); } @@ -108,7 +109,6 @@ private: inline bool operator!=(const _E &e) const { return (obj != e.obj); } }; - FILE *_feed; std::string _basePath; std::map _db; }; diff --git a/controller/README.md b/controller/README.md index 093300a6..db8d0153 100644 --- a/controller/README.md +++ b/controller/README.md @@ -237,11 +237,12 @@ Note that managed IP assignments are only used if they fall within a managed rou | Field | Type | Description | | --------------------- | ------------- | ------------------------------------------------- | | ts | integer | Time of request, ms since epoch | -| authorized | boolean | Was member authorized? | -| clientMajorVersion | integer | Client major version or -1 if unknown | -| clientMinorVersion | integer | Client minor version or -1 if unknown | -| clientRevision | integer | Client revision or -1 if unknown | -| clientProtocolVersion | integer | ZeroTier protocol version reported by client | +| auth | boolean | Was member authorized? | +| authBy | string | How was member authorized? | +| vMajor | integer | Client major version or -1 if unknown | +| vMinor | integer | Client minor version or -1 if unknown | +| vRev | integer | Client revision or -1 if unknown | +| vProto | integer | ZeroTier protocol version reported by client | | fromAddr | string | Physical address if known | The controller can only know a member's `fromAddr` if it's able to establish a direct path to it. Members behind very restrictive firewalls may not have this information since the controller will be receiving the member's requests by way of a relay. ZeroTier does not back-trace IP paths as packets are relayed since this would add a lot of protocol overhead. diff --git a/node/Peer.cpp b/node/Peer.cpp index 1dde8b65..fa3ce6c8 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -141,10 +141,10 @@ void Peer::received( path->trustedPacketReceived(now); } - if (hops == 0) { - if (_vProto >= 9) - path->updateLinkQuality((unsigned int)(packetId & 7)); + if (_vProto >= 9) + path->updateLinkQuality((unsigned int)(packetId & 7)); + if (hops == 0) { bool pathIsConfirmed = false; { Mutex::Lock _l(_paths_m); diff --git a/service/OneService.cpp b/service/OneService.cpp index 81950e26..8d8856a2 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -638,7 +638,7 @@ public: return _termReason; } - _controller = new EmbeddedNetworkController(_node,(_homePath + ZT_PATH_SEPARATOR_S ZT_CONTROLLER_DB_PATH).c_str(),(FILE *)0); + _controller = new EmbeddedNetworkController(_node,(_homePath + ZT_PATH_SEPARATOR_S ZT_CONTROLLER_DB_PATH).c_str()); _node->setNetconfMaster((void *)_controller); #ifdef ZT_ENABLE_CLUSTER -- cgit v1.2.3 From 22f86df6065ced3f0d7bbbb57ae2286cde06ce38 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 7 Mar 2017 13:53:11 -0800 Subject: Merge ControlPlane into OneService to make variable access simpler. --- objects.mk | 1 - service/ControlPlane.cpp | 553 ---------------------------------------------- service/ControlPlane.hpp | 96 -------- service/OneService.cpp | 562 +++++++++++++++++++++++++++++++++++++++++++---- service/OneService.hpp | 5 - 5 files changed, 521 insertions(+), 696 deletions(-) delete mode 100644 service/ControlPlane.cpp delete mode 100644 service/ControlPlane.hpp (limited to 'service/OneService.cpp') diff --git a/objects.mk b/objects.mk index 427024eb..74efc337 100644 --- a/objects.mk +++ b/objects.mk @@ -31,5 +31,4 @@ OBJS=\ osdep/Http.o \ osdep/OSUtils.o \ service/ClusterGeoIpService.o \ - service/ControlPlane.o \ service/SoftwareUpdater.o diff --git a/service/ControlPlane.cpp b/service/ControlPlane.cpp deleted file mode 100644 index e0be5f77..00000000 --- a/service/ControlPlane.cpp +++ /dev/null @@ -1,553 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 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 . - */ - -#include "ControlPlane.hpp" -#include "OneService.hpp" - -#include "../version.h" -#include "../include/ZeroTierOne.h" - -#ifdef ZT_USE_SYSTEM_HTTP_PARSER -#include -#else -#include "../ext/http-parser/http_parser.h" -#endif - -#include "../ext/json/json.hpp" - -#include "../controller/EmbeddedNetworkController.hpp" - -#include "../node/InetAddress.hpp" -#include "../node/Node.hpp" -#include "../node/Utils.hpp" -#include "../node/World.hpp" - -#include "../osdep/OSUtils.hpp" - -namespace ZeroTier { - -namespace { - -static void _networkToJson(nlohmann::json &nj,const ZT_VirtualNetworkConfig *nc,const std::string &portDeviceName,const OneService::NetworkSettings &localSettings) -{ - char tmp[256]; - - const char *nstatus = "",*ntype = ""; - switch(nc->status) { - case ZT_NETWORK_STATUS_REQUESTING_CONFIGURATION: nstatus = "REQUESTING_CONFIGURATION"; break; - case ZT_NETWORK_STATUS_OK: nstatus = "OK"; break; - case ZT_NETWORK_STATUS_ACCESS_DENIED: nstatus = "ACCESS_DENIED"; break; - case ZT_NETWORK_STATUS_NOT_FOUND: nstatus = "NOT_FOUND"; break; - case ZT_NETWORK_STATUS_PORT_ERROR: nstatus = "PORT_ERROR"; break; - case ZT_NETWORK_STATUS_CLIENT_TOO_OLD: nstatus = "CLIENT_TOO_OLD"; break; - } - switch(nc->type) { - case ZT_NETWORK_TYPE_PRIVATE: ntype = "PRIVATE"; break; - case ZT_NETWORK_TYPE_PUBLIC: ntype = "PUBLIC"; break; - } - - Utils::snprintf(tmp,sizeof(tmp),"%.16llx",nc->nwid); - nj["id"] = tmp; - nj["nwid"] = tmp; - Utils::snprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)((nc->mac >> 40) & 0xff),(unsigned int)((nc->mac >> 32) & 0xff),(unsigned int)((nc->mac >> 24) & 0xff),(unsigned int)((nc->mac >> 16) & 0xff),(unsigned int)((nc->mac >> 8) & 0xff),(unsigned int)(nc->mac & 0xff)); - nj["mac"] = tmp; - nj["name"] = nc->name; - nj["status"] = nstatus; - nj["type"] = ntype; - nj["mtu"] = nc->mtu; - nj["dhcp"] = (bool)(nc->dhcp != 0); - nj["bridge"] = (bool)(nc->bridge != 0); - nj["broadcastEnabled"] = (bool)(nc->broadcastEnabled != 0); - nj["portError"] = nc->portError; - nj["netconfRevision"] = nc->netconfRevision; - nj["portDeviceName"] = portDeviceName; - nj["allowManaged"] = localSettings.allowManaged; - nj["allowGlobal"] = localSettings.allowGlobal; - nj["allowDefault"] = localSettings.allowDefault; - - nlohmann::json aa = nlohmann::json::array(); - for(unsigned int i=0;iassignedAddressCount;++i) { - aa.push_back(reinterpret_cast(&(nc->assignedAddresses[i]))->toString()); - } - nj["assignedAddresses"] = aa; - - nlohmann::json ra = nlohmann::json::array(); - for(unsigned int i=0;irouteCount;++i) { - nlohmann::json rj; - rj["target"] = reinterpret_cast(&(nc->routes[i].target))->toString(); - if (nc->routes[i].via.ss_family == nc->routes[i].target.ss_family) - rj["via"] = reinterpret_cast(&(nc->routes[i].via))->toIpString(); - else rj["via"] = nlohmann::json(); - rj["flags"] = (int)nc->routes[i].flags; - rj["metric"] = (int)nc->routes[i].metric; - ra.push_back(rj); - } - nj["routes"] = ra; -} - -static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer) -{ - char tmp[256]; - - const char *prole = ""; - switch(peer->role) { - case ZT_PEER_ROLE_LEAF: prole = "LEAF"; break; - case ZT_PEER_ROLE_MOON: prole = "MOON"; break; - case ZT_PEER_ROLE_PLANET: prole = "PLANET"; break; - } - - Utils::snprintf(tmp,sizeof(tmp),"%.10llx",peer->address); - pj["address"] = tmp; - pj["versionMajor"] = peer->versionMajor; - pj["versionMinor"] = peer->versionMinor; - pj["versionRev"] = peer->versionRev; - Utils::snprintf(tmp,sizeof(tmp),"%d.%d.%d",peer->versionMajor,peer->versionMinor,peer->versionRev); - pj["version"] = tmp; - pj["latency"] = peer->latency; - pj["role"] = prole; - - nlohmann::json pa = nlohmann::json::array(); - for(unsigned int i=0;ipathCount;++i) { - nlohmann::json j; - j["address"] = reinterpret_cast(&(peer->paths[i].address))->toString(); - j["lastSend"] = peer->paths[i].lastSend; - j["lastReceive"] = peer->paths[i].lastReceive; - j["trustedPathId"] = peer->paths[i].trustedPathId; - j["linkQuality"] = (double)peer->paths[i].linkQuality / (double)ZT_PATH_LINK_QUALITY_MAX; - j["active"] = (bool)(peer->paths[i].expired == 0); - j["expired"] = (bool)(peer->paths[i].expired != 0); - j["preferred"] = (bool)(peer->paths[i].preferred != 0); - pa.push_back(j); - } - pj["paths"] = pa; -} - -static void _moonToJson(nlohmann::json &mj,const World &world) -{ - char tmp[64]; - Utils::snprintf(tmp,sizeof(tmp),"%.16llx",world.id()); - mj["id"] = tmp; - mj["timestamp"] = world.timestamp(); - mj["signature"] = Utils::hex(world.signature().data,(unsigned int)world.signature().size()); - mj["updatesMustBeSignedBy"] = Utils::hex(world.updatesMustBeSignedBy().data,(unsigned int)world.updatesMustBeSignedBy().size()); - nlohmann::json ra = nlohmann::json::array(); - for(std::vector::const_iterator r(world.roots().begin());r!=world.roots().end();++r) { - nlohmann::json rj; - rj["identity"] = r->identity.toString(false); - nlohmann::json eps = nlohmann::json::array(); - for(std::vector::const_iterator a(r->stableEndpoints.begin());a!=r->stableEndpoints.end();++a) - eps.push_back(a->toString()); - rj["stableEndpoints"] = eps; - ra.push_back(rj); - } - mj["roots"] = ra; - mj["waiting"] = false; -} - -} // anonymous namespace - -ControlPlane::ControlPlane(OneService *svc,Node *n) : - _svc(svc), - _node(n), - _controller((EmbeddedNetworkController *)0) -{ -} - -unsigned int ControlPlane::handleRequest( - const InetAddress &fromAddress, - unsigned int httpMethod, - const std::string &path, - const std::map &headers, - const std::string &body, - std::string &responseBody, - std::string &responseContentType) -{ - char tmp[256]; - unsigned int scode = 404; - nlohmann::json res; - std::vector ps(OSUtils::split(path.c_str(),"/","","")); - std::map urlArgs; - - Mutex::Lock _l(_lock); - - /* Note: this is kind of restricted in what it'll take. It does not support - * URL encoding, and /'s in URL args will screw it up. But the only URL args - * it really uses in ?jsonp=funcionName, and otherwise it just takes simple - * paths to simply-named resources. */ - if (ps.size() > 0) { - std::size_t qpos = ps[ps.size() - 1].find('?'); - if (qpos != std::string::npos) { - std::string args(ps[ps.size() - 1].substr(qpos + 1)); - ps[ps.size() - 1] = ps[ps.size() - 1].substr(0,qpos); - std::vector asplit(OSUtils::split(args.c_str(),"&","","")); - for(std::vector::iterator a(asplit.begin());a!=asplit.end();++a) { - std::size_t eqpos = a->find('='); - if (eqpos == std::string::npos) - urlArgs[*a] = ""; - else urlArgs[a->substr(0,eqpos)] = a->substr(eqpos + 1); - } - } - } - - bool isAuth = false; - { - std::map::const_iterator ah(headers.find("x-zt1-auth")); - if ((ah != headers.end())&&(_authTokens.count(ah->second) > 0)) { - isAuth = true; - } else { - ah = urlArgs.find("auth"); - if ((ah != urlArgs.end())&&(_authTokens.count(ah->second) > 0)) - isAuth = true; - } - } - -#ifdef __SYNOLOGY__ - #include - // Authenticate via Synology's built-in cgi script - if (!isAuth) { - /* - fprintf(stderr, "path = %s\n", path.c_str()); - fprintf(stderr, "headers.size=%d\n", headers.size()); - std::map::const_iterator it(headers.begin()); - while(it != headers.end()) { - fprintf(stderr,"header[%s] = %s\n", (it->first).c_str(), (it->second).c_str()); - it++; - } - */ - // parse out url args - int synotoken_pos = path.find("SynoToken"); - int argpos = path.find("?"); - if(synotoken_pos != std::string::npos && argpos != std::string::npos) { - std::string cookie = path.substr(argpos+1, synotoken_pos-(argpos+1)); - std::string synotoken = path.substr(synotoken_pos); - std::string cookie_val = cookie.substr(cookie.find("=")+1); - std::string synotoken_val = synotoken.substr(synotoken.find("=")+1); - // Set necessary env for auth script - std::map::const_iterator ah2(headers.find("x-forwarded-for")); - setenv("HTTP_COOKIE", cookie_val.c_str(), true); - setenv("HTTP_X_SYNO_TOKEN", synotoken_val.c_str(), true); - setenv("REMOTE_ADDR", ah2->second.c_str(),true); - //fprintf(stderr, "HTTP_COOKIE: %s\n",std::getenv ("HTTP_COOKIE")); - //fprintf(stderr, "HTTP_X_SYNO_TOKEN: %s\n",std::getenv ("HTTP_X_SYNO_TOKEN")); - //fprintf(stderr, "REMOTE_ADDR: %s\n",std::getenv ("REMOTE_ADDR")); - // check synology web auth - char user[256], buf[1024]; - FILE *fp = NULL; - bzero(user, 256); - fp = popen("/usr/syno/synoman/webman/modules/authenticate.cgi", "r"); - if(!fp) - isAuth = false; - else { - bzero(buf, sizeof(buf)); - fread(buf, 1024, 1, fp); - if(strlen(buf) > 0) { - snprintf(user, 256, "%s", buf); - isAuth = true; - } - } - pclose(fp); - } - } -#endif - - if (httpMethod == HTTP_GET) { - if (isAuth) { - if (ps[0] == "status") { - ZT_NodeStatus status; - _node->status(&status); - - Utils::snprintf(tmp,sizeof(tmp),"%.10llx",status.address); - res["address"] = tmp; - res["publicIdentity"] = status.publicIdentity; - res["online"] = (bool)(status.online != 0); - res["tcpFallbackActive"] = _svc->tcpFallbackActive(); - res["versionMajor"] = ZEROTIER_ONE_VERSION_MAJOR; - res["versionMinor"] = ZEROTIER_ONE_VERSION_MINOR; - res["versionRev"] = ZEROTIER_ONE_VERSION_REVISION; - res["versionBuild"] = ZEROTIER_ONE_VERSION_BUILD; - Utils::snprintf(tmp,sizeof(tmp),"%d.%d.%d",ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION); - res["version"] = tmp; - res["clock"] = OSUtils::now(); - - World planet(_node->planet()); - res["planetWorldId"] = planet.id(); - res["planetWorldTimestamp"] = planet.timestamp(); - -#ifdef ZT_ENABLE_CLUSTER - nlohmann::json cj; - ZT_ClusterStatus cs; - _node->clusterStatus(&cs); - if (cs.clusterSize >= 1) { - nlohmann::json cja = nlohmann::json::array(); - for(unsigned int i=0;i moons(_node->moons()); - if (ps.size() == 1) { - // Return [array] of all moons - - res = nlohmann::json::array(); - for(std::vector::const_iterator m(moons.begin());m!=moons.end();++m) { - nlohmann::json mj; - _moonToJson(mj,*m); - res.push_back(mj); - } - - scode = 200; - } else { - // Return a single moon by ID - - const uint64_t id = Utils::hexStrToU64(ps[1].c_str()); - for(std::vector::const_iterator m(moons.begin());m!=moons.end();++m) { - if (m->id() == id) { - _moonToJson(res,*m); - scode = 200; - break; - } - } - - } - } else if (ps[0] == "network") { - ZT_VirtualNetworkList *nws = _node->networks(); - if (nws) { - if (ps.size() == 1) { - // Return [array] of all networks - - res = nlohmann::json::array(); - for(unsigned long i=0;inetworkCount;++i) { - OneService::NetworkSettings localSettings; - _svc->getNetworkSettings(nws->networks[i].nwid,localSettings); - nlohmann::json nj; - _networkToJson(nj,&(nws->networks[i]),_svc->portDeviceName(nws->networks[i].nwid),localSettings); - res.push_back(nj); - } - - scode = 200; - } else if (ps.size() == 2) { - // Return a single network by ID or 404 if not found - - const uint64_t wantnw = Utils::hexStrToU64(ps[1].c_str()); - for(unsigned long i=0;inetworkCount;++i) { - if (nws->networks[i].nwid == wantnw) { - OneService::NetworkSettings localSettings; - _svc->getNetworkSettings(nws->networks[i].nwid,localSettings); - _networkToJson(res,&(nws->networks[i]),_svc->portDeviceName(nws->networks[i].nwid),localSettings); - scode = 200; - break; - } - } - - } else scode = 404; - _node->freeQueryResult((void *)nws); - } else scode = 500; - } else if (ps[0] == "peer") { - ZT_PeerList *pl = _node->peers(); - if (pl) { - if (ps.size() == 1) { - // Return [array] of all peers - - res = nlohmann::json::array(); - for(unsigned long i=0;ipeerCount;++i) { - nlohmann::json pj; - _peerToJson(pj,&(pl->peers[i])); - res.push_back(pj); - } - - scode = 200; - } else if (ps.size() == 2) { - // Return a single peer by ID or 404 if not found - - uint64_t wantp = Utils::hexStrToU64(ps[1].c_str()); - for(unsigned long i=0;ipeerCount;++i) { - if (pl->peers[i].address == wantp) { - _peerToJson(res,&(pl->peers[i])); - scode = 200; - break; - } - } - - } else scode = 404; - _node->freeQueryResult((void *)pl); - } else scode = 500; - } else { - if (_controller) { - scode = _controller->handleControlPlaneHttpGET(std::vector(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType); - } else scode = 404; - } - - } else scode = 401; // isAuth == false - } else if ((httpMethod == HTTP_POST)||(httpMethod == HTTP_PUT)) { - if (isAuth) { - - if (ps[0] == "moon") { - if (ps.size() == 2) { - - uint64_t seed = 0; - try { - nlohmann::json j(OSUtils::jsonParse(body)); - if (j.is_object()) { - seed = Utils::hexStrToU64(OSUtils::jsonString(j["seed"],"0").c_str()); - } - } catch ( ... ) { - // discard invalid JSON - } - - std::vector moons(_node->moons()); - const uint64_t id = Utils::hexStrToU64(ps[1].c_str()); - for(std::vector::const_iterator m(moons.begin());m!=moons.end();++m) { - if (m->id() == id) { - _moonToJson(res,*m); - scode = 200; - break; - } - } - - if ((scode != 200)&&(seed != 0)) { - char tmp[64]; - Utils::snprintf(tmp,sizeof(tmp),"%.16llx",id); - res["id"] = tmp; - res["roots"] = nlohmann::json::array(); - res["timestamp"] = 0; - res["signature"] = nlohmann::json(); - res["updatesMustBeSignedBy"] = nlohmann::json(); - res["waiting"] = true; - _node->orbit(id,seed); - } - - } else scode = 404; - } else if (ps[0] == "network") { - if (ps.size() == 2) { - - uint64_t wantnw = Utils::hexStrToU64(ps[1].c_str()); - _node->join(wantnw,(void *)0); // does nothing if we are a member - ZT_VirtualNetworkList *nws = _node->networks(); - if (nws) { - for(unsigned long i=0;inetworkCount;++i) { - if (nws->networks[i].nwid == wantnw) { - OneService::NetworkSettings localSettings; - _svc->getNetworkSettings(nws->networks[i].nwid,localSettings); - - try { - nlohmann::json j(OSUtils::jsonParse(body)); - if (j.is_object()) { - nlohmann::json &allowManaged = j["allowManaged"]; - if (allowManaged.is_boolean()) localSettings.allowManaged = (bool)allowManaged; - nlohmann::json &allowGlobal = j["allowGlobal"]; - if (allowGlobal.is_boolean()) localSettings.allowGlobal = (bool)allowGlobal; - nlohmann::json &allowDefault = j["allowDefault"]; - if (allowDefault.is_boolean()) localSettings.allowDefault = (bool)allowDefault; - } - } catch ( ... ) { - // discard invalid JSON - } - - _svc->setNetworkSettings(nws->networks[i].nwid,localSettings); - _networkToJson(res,&(nws->networks[i]),_svc->portDeviceName(nws->networks[i].nwid),localSettings); - - scode = 200; - break; - } - } - _node->freeQueryResult((void *)nws); - } else scode = 500; - - } else scode = 404; - } else { - if (_controller) - scode = _controller->handleControlPlaneHttpPOST(std::vector(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType); - else scode = 404; - } - - } else scode = 401; // isAuth == false - } else if (httpMethod == HTTP_DELETE) { - if (isAuth) { - - if (ps[0] == "moon") { - if (ps.size() == 2) { - _node->deorbit(Utils::hexStrToU64(ps[1].c_str())); - res["result"] = true; - scode = 200; - } // else 404 - } else if (ps[0] == "network") { - ZT_VirtualNetworkList *nws = _node->networks(); - if (nws) { - if (ps.size() == 2) { - uint64_t wantnw = Utils::hexStrToU64(ps[1].c_str()); - for(unsigned long i=0;inetworkCount;++i) { - if (nws->networks[i].nwid == wantnw) { - _node->leave(wantnw,(void **)0); - res["result"] = true; - scode = 200; - break; - } - } - } // else 404 - _node->freeQueryResult((void *)nws); - } else scode = 500; - } else { - if (_controller) - scode = _controller->handleControlPlaneHttpDELETE(std::vector(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType); - else scode = 404; - } - - } else scode = 401; // isAuth = false - } else { - scode = 400; - } - - if (responseBody.length() == 0) { - if ((res.is_object())||(res.is_array())) - responseBody = OSUtils::jsonDump(res); - else responseBody = "{}"; - responseContentType = "application/json"; - } - - // Wrap result in jsonp function call if the user included a jsonp= url argument. - // Also double-check isAuth since forbidding this without auth feels safer. - std::map::const_iterator jsonp(urlArgs.find("jsonp")); - if ((isAuth)&&(jsonp != urlArgs.end())&&(responseContentType == "application/json")) { - if (responseBody.length() > 0) - responseBody = jsonp->second + "(" + responseBody + ");"; - else responseBody = jsonp->second + "(null);"; - responseContentType = "application/javascript"; - } - - return scode; -} - -} // namespace ZeroTier diff --git a/service/ControlPlane.hpp b/service/ControlPlane.hpp deleted file mode 100644 index a1f743cb..00000000 --- a/service/ControlPlane.hpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 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 . - */ - -#ifndef ZT_ONE_CONTROLPLANE_HPP -#define ZT_ONE_CONTROLPLANE_HPP - -#include -#include -#include - -#include "../include/ZeroTierOne.h" - -#include "../node/Mutex.hpp" - -namespace ZeroTier { - -class OneService; -class Node; -class EmbeddedNetworkController; -struct InetAddress; - -/** - * HTTP control plane and static web server - */ -class ControlPlane -{ -public: - ControlPlane(OneService *svc,Node *n); - - /** - * Set controller, which will be available under /controller - * - * @param c Network controller instance - */ - inline void setController(EmbeddedNetworkController *c) - { - Mutex::Lock _l(_lock); - _controller = c; - } - - /** - * Add an authentication token for API access - */ - inline void addAuthToken(const char *tok) - { - Mutex::Lock _l(_lock); - _authTokens.insert(std::string(tok)); - } - - /** - * Handle HTTP request - * - * @param fromAddress Originating IP address of request - * @param httpMethod HTTP method (as defined in ext/http-parser/http_parser.h) - * @param path Request path - * @param headers Request headers - * @param body Request body - * @param responseBody Result parameter: fill with response data - * @param responseContentType Result parameter: fill with content type - * @return HTTP response code - */ - unsigned int handleRequest( - const InetAddress &fromAddress, - unsigned int httpMethod, - const std::string &path, - const std::map &headers, - const std::string &body, - std::string &responseBody, - std::string &responseContentType); - -private: - OneService *const _svc; - Node *const _node; - EmbeddedNetworkController *_controller; - std::set _authTokens; - Mutex _lock; -}; - -} // namespace ZeroTier - -#endif diff --git a/service/OneService.cpp b/service/OneService.cpp index 8d8856a2..eec9ac96 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -38,6 +38,7 @@ #include "../node/InetAddress.hpp" #include "../node/MAC.hpp" #include "../node/Identity.hpp" +#include "../node/World.hpp" #include "../osdep/Phy.hpp" #include "../osdep/Thread.hpp" @@ -48,11 +49,24 @@ #include "../osdep/ManagedRoute.hpp" #include "OneService.hpp" -#include "ControlPlane.hpp" #include "ClusterGeoIpService.hpp" #include "ClusterDefinition.hpp" #include "SoftwareUpdater.hpp" +#ifdef __WINDOWS__ +#include +#include +#include +#include +#include +#else +#include +#include +#include +#include +#include +#endif + #ifdef ZT_USE_SYSTEM_HTTP_PARSER #include #else @@ -75,20 +89,6 @@ using json = nlohmann::json; #include "../controller/EmbeddedNetworkController.hpp" -#ifdef __WINDOWS__ -#include -#include -#include -#include -#include -#else -#include -#include -#include -#include -#include -#endif - // Include the right tap device driver for this platform -- add new platforms here #ifdef ZT_SERVICE_NETCON @@ -170,6 +170,122 @@ static std::string _trimString(const std::string &s) return s.substr(start,end - start); } +static void _networkToJson(nlohmann::json &nj,const ZT_VirtualNetworkConfig *nc,const std::string &portDeviceName,const OneService::NetworkSettings &localSettings) +{ + char tmp[256]; + + const char *nstatus = "",*ntype = ""; + switch(nc->status) { + case ZT_NETWORK_STATUS_REQUESTING_CONFIGURATION: nstatus = "REQUESTING_CONFIGURATION"; break; + case ZT_NETWORK_STATUS_OK: nstatus = "OK"; break; + case ZT_NETWORK_STATUS_ACCESS_DENIED: nstatus = "ACCESS_DENIED"; break; + case ZT_NETWORK_STATUS_NOT_FOUND: nstatus = "NOT_FOUND"; break; + case ZT_NETWORK_STATUS_PORT_ERROR: nstatus = "PORT_ERROR"; break; + case ZT_NETWORK_STATUS_CLIENT_TOO_OLD: nstatus = "CLIENT_TOO_OLD"; break; + } + switch(nc->type) { + case ZT_NETWORK_TYPE_PRIVATE: ntype = "PRIVATE"; break; + case ZT_NETWORK_TYPE_PUBLIC: ntype = "PUBLIC"; break; + } + + Utils::snprintf(tmp,sizeof(tmp),"%.16llx",nc->nwid); + nj["id"] = tmp; + nj["nwid"] = tmp; + Utils::snprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)((nc->mac >> 40) & 0xff),(unsigned int)((nc->mac >> 32) & 0xff),(unsigned int)((nc->mac >> 24) & 0xff),(unsigned int)((nc->mac >> 16) & 0xff),(unsigned int)((nc->mac >> 8) & 0xff),(unsigned int)(nc->mac & 0xff)); + nj["mac"] = tmp; + nj["name"] = nc->name; + nj["status"] = nstatus; + nj["type"] = ntype; + nj["mtu"] = nc->mtu; + nj["dhcp"] = (bool)(nc->dhcp != 0); + nj["bridge"] = (bool)(nc->bridge != 0); + nj["broadcastEnabled"] = (bool)(nc->broadcastEnabled != 0); + nj["portError"] = nc->portError; + nj["netconfRevision"] = nc->netconfRevision; + nj["portDeviceName"] = portDeviceName; + nj["allowManaged"] = localSettings.allowManaged; + nj["allowGlobal"] = localSettings.allowGlobal; + nj["allowDefault"] = localSettings.allowDefault; + + nlohmann::json aa = nlohmann::json::array(); + for(unsigned int i=0;iassignedAddressCount;++i) { + aa.push_back(reinterpret_cast(&(nc->assignedAddresses[i]))->toString()); + } + nj["assignedAddresses"] = aa; + + nlohmann::json ra = nlohmann::json::array(); + for(unsigned int i=0;irouteCount;++i) { + nlohmann::json rj; + rj["target"] = reinterpret_cast(&(nc->routes[i].target))->toString(); + if (nc->routes[i].via.ss_family == nc->routes[i].target.ss_family) + rj["via"] = reinterpret_cast(&(nc->routes[i].via))->toIpString(); + else rj["via"] = nlohmann::json(); + rj["flags"] = (int)nc->routes[i].flags; + rj["metric"] = (int)nc->routes[i].metric; + ra.push_back(rj); + } + nj["routes"] = ra; +} + +static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer) +{ + char tmp[256]; + + const char *prole = ""; + switch(peer->role) { + case ZT_PEER_ROLE_LEAF: prole = "LEAF"; break; + case ZT_PEER_ROLE_MOON: prole = "MOON"; break; + case ZT_PEER_ROLE_PLANET: prole = "PLANET"; break; + } + + Utils::snprintf(tmp,sizeof(tmp),"%.10llx",peer->address); + pj["address"] = tmp; + pj["versionMajor"] = peer->versionMajor; + pj["versionMinor"] = peer->versionMinor; + pj["versionRev"] = peer->versionRev; + Utils::snprintf(tmp,sizeof(tmp),"%d.%d.%d",peer->versionMajor,peer->versionMinor,peer->versionRev); + pj["version"] = tmp; + pj["latency"] = peer->latency; + pj["role"] = prole; + + nlohmann::json pa = nlohmann::json::array(); + for(unsigned int i=0;ipathCount;++i) { + nlohmann::json j; + j["address"] = reinterpret_cast(&(peer->paths[i].address))->toString(); + j["lastSend"] = peer->paths[i].lastSend; + j["lastReceive"] = peer->paths[i].lastReceive; + j["trustedPathId"] = peer->paths[i].trustedPathId; + j["linkQuality"] = (double)peer->paths[i].linkQuality / (double)ZT_PATH_LINK_QUALITY_MAX; + j["active"] = (bool)(peer->paths[i].expired == 0); + j["expired"] = (bool)(peer->paths[i].expired != 0); + j["preferred"] = (bool)(peer->paths[i].preferred != 0); + pa.push_back(j); + } + pj["paths"] = pa; +} + +static void _moonToJson(nlohmann::json &mj,const World &world) +{ + char tmp[64]; + Utils::snprintf(tmp,sizeof(tmp),"%.16llx",world.id()); + mj["id"] = tmp; + mj["timestamp"] = world.timestamp(); + mj["signature"] = Utils::hex(world.signature().data,(unsigned int)world.signature().size()); + mj["updatesMustBeSignedBy"] = Utils::hex(world.updatesMustBeSignedBy().data,(unsigned int)world.updatesMustBeSignedBy().size()); + nlohmann::json ra = nlohmann::json::array(); + for(std::vector::const_iterator r(world.roots().begin());r!=world.roots().end();++r) { + nlohmann::json rj; + rj["identity"] = r->identity.toString(false); + nlohmann::json eps = nlohmann::json::array(); + for(std::vector::const_iterator a(r->stableEndpoints.begin());a!=r->stableEndpoints.end();++a) + eps.push_back(a->toString()); + rj["stableEndpoints"] = eps; + ra.push_back(rj); + } + mj["roots"] = ra; + mj["waiting"] = false; +} + class OneServiceImpl; static int SnodeVirtualNetworkConfigFunction(ZT_Node *node,void *uptr,uint64_t nwid,void **nuptr,enum ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nwconf); @@ -261,6 +377,7 @@ public: // begin member variables -------------------------------------------------- const std::string _homePath; + std::string _authToken; EmbeddedNetworkController *_controller; Phy _phy; Node *_node; @@ -299,9 +416,6 @@ public: PhySocket *_v4TcpControlSocket; PhySocket *_v6TcpControlSocket; - // JSON API handler - ControlPlane *_controlPlane; - // Time we last received a packet from a global address uint64_t _lastDirectReceiveFromGlobal; #ifdef ZT_TCP_FALLBACK_RELAY @@ -371,7 +485,6 @@ public: ,_updater((SoftwareUpdater *)0) ,_updateAutoApply(false) ,_primaryPort(port) - ,_controlPlane((ControlPlane *)0) ,_lastDirectReceiveFromGlobal(0) #ifdef ZT_TCP_FALLBACK_RELAY ,_lastSendToGlobalV4(0) @@ -420,16 +533,15 @@ public: virtual ReasonForTermination run() { try { - std::string authToken; { - std::string authTokenPath(_homePath + ZT_PATH_SEPARATOR_S "authtoken.secret"); - if (!OSUtils::readFile(authTokenPath.c_str(),authToken)) { + const std::string authTokenPath(_homePath + ZT_PATH_SEPARATOR_S "authtoken.secret"); + if (!OSUtils::readFile(authTokenPath.c_str(),_authToken)) { unsigned char foo[24]; Utils::getSecureRandom(foo,sizeof(foo)); - authToken = ""; + _authToken = ""; for(unsigned int i=0;iaddAuthToken(authToken.c_str()); - _controlPlane->setController(_controller); - { // Load existing networks std::vector networksDotD(OSUtils::listDirectory((_homePath + ZT_PATH_SEPARATOR_S "networks.d").c_str())); for(std::vector::iterator f(networksDotD.begin());f!=networksDotD.end();++f) { @@ -831,8 +939,6 @@ public: _nets.clear(); } - delete _controlPlane; - _controlPlane = (ControlPlane *)0; delete _updater; _updater = (SoftwareUpdater *)0; delete _node; @@ -862,11 +968,6 @@ public: else return std::string(); } - virtual bool tcpFallbackActive() const - { - return (_tcpFallbackTunnel != (TcpConnection *)0); - } - virtual void terminate() { _run_m.lock(); @@ -912,6 +1013,385 @@ public: // Internal implementation methods ----------------------------------------- + inline unsigned int handleControlPlaneHttpRequest( + const InetAddress &fromAddress, + unsigned int httpMethod, + const std::string &path, + const std::map &headers, + const std::string &body, + std::string &responseBody, + std::string &responseContentType) + { + char tmp[256]; + unsigned int scode = 404; + json res; + std::vector ps(OSUtils::split(path.c_str(),"/","","")); + std::map urlArgs; + + /* Note: this is kind of restricted in what it'll take. It does not support + * URL encoding, and /'s in URL args will screw it up. But the only URL args + * it really uses in ?jsonp=funcionName, and otherwise it just takes simple + * paths to simply-named resources. */ + if (ps.size() > 0) { + std::size_t qpos = ps[ps.size() - 1].find('?'); + if (qpos != std::string::npos) { + std::string args(ps[ps.size() - 1].substr(qpos + 1)); + ps[ps.size() - 1] = ps[ps.size() - 1].substr(0,qpos); + std::vector asplit(OSUtils::split(args.c_str(),"&","","")); + for(std::vector::iterator a(asplit.begin());a!=asplit.end();++a) { + std::size_t eqpos = a->find('='); + if (eqpos == std::string::npos) + urlArgs[*a] = ""; + else urlArgs[a->substr(0,eqpos)] = a->substr(eqpos + 1); + } + } + } + + bool isAuth = false; + { + std::map::const_iterator ah(headers.find("x-zt1-auth")); + if ((ah != headers.end())&&(_authToken == ah->second)) { + isAuth = true; + } else { + ah = urlArgs.find("auth"); + if ((ah != urlArgs.end())&&(_authToken == ah->second)) + isAuth = true; + } + } + +#ifdef __SYNOLOGY__ + // Authenticate via Synology's built-in cgi script + if (!isAuth) { + /* + fprintf(stderr, "path = %s\n", path.c_str()); + fprintf(stderr, "headers.size=%d\n", headers.size()); + std::map::const_iterator it(headers.begin()); + while(it != headers.end()) { + fprintf(stderr,"header[%s] = %s\n", (it->first).c_str(), (it->second).c_str()); + it++; + } + */ + // parse out url args + int synotoken_pos = path.find("SynoToken"); + int argpos = path.find("?"); + if(synotoken_pos != std::string::npos && argpos != std::string::npos) { + std::string cookie = path.substr(argpos+1, synotoken_pos-(argpos+1)); + std::string synotoken = path.substr(synotoken_pos); + std::string cookie_val = cookie.substr(cookie.find("=")+1); + std::string synotoken_val = synotoken.substr(synotoken.find("=")+1); + // Set necessary env for auth script + std::map::const_iterator ah2(headers.find("x-forwarded-for")); + setenv("HTTP_COOKIE", cookie_val.c_str(), true); + setenv("HTTP_X_SYNO_TOKEN", synotoken_val.c_str(), true); + setenv("REMOTE_ADDR", ah2->second.c_str(),true); + //fprintf(stderr, "HTTP_COOKIE: %s\n",std::getenv ("HTTP_COOKIE")); + //fprintf(stderr, "HTTP_X_SYNO_TOKEN: %s\n",std::getenv ("HTTP_X_SYNO_TOKEN")); + //fprintf(stderr, "REMOTE_ADDR: %s\n",std::getenv ("REMOTE_ADDR")); + // check synology web auth + char user[256], buf[1024]; + FILE *fp = NULL; + bzero(user, 256); + fp = popen("/usr/syno/synoman/webman/modules/authenticate.cgi", "r"); + if(!fp) + isAuth = false; + else { + bzero(buf, sizeof(buf)); + fread(buf, 1024, 1, fp); + if(strlen(buf) > 0) { + snprintf(user, 256, "%s", buf); + isAuth = true; + } + } + pclose(fp); + } + } +#endif + + if (httpMethod == HTTP_GET) { + if (isAuth) { + if (ps[0] == "status") { + ZT_NodeStatus status; + _node->status(&status); + + Utils::snprintf(tmp,sizeof(tmp),"%.10llx",status.address); + res["address"] = tmp; + res["publicIdentity"] = status.publicIdentity; + res["online"] = (bool)(status.online != 0); + res["tcpFallbackActive"] = (_tcpFallbackTunnel != (TcpConnection *)0); + res["versionMajor"] = ZEROTIER_ONE_VERSION_MAJOR; + res["versionMinor"] = ZEROTIER_ONE_VERSION_MINOR; + res["versionRev"] = ZEROTIER_ONE_VERSION_REVISION; + res["versionBuild"] = ZEROTIER_ONE_VERSION_BUILD; + Utils::snprintf(tmp,sizeof(tmp),"%d.%d.%d",ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION); + res["version"] = tmp; + res["clock"] = OSUtils::now(); + + World planet(_node->planet()); + res["planetWorldId"] = planet.id(); + res["planetWorldTimestamp"] = planet.timestamp(); + + #ifdef ZT_ENABLE_CLUSTER + json cj; + ZT_ClusterStatus cs; + _node->clusterStatus(&cs); + if (cs.clusterSize >= 1) { + json cja = json::array(); + for(unsigned int i=0;i moons(_node->moons()); + if (ps.size() == 1) { + // Return [array] of all moons + + res = json::array(); + for(std::vector::const_iterator m(moons.begin());m!=moons.end();++m) { + json mj; + _moonToJson(mj,*m); + res.push_back(mj); + } + + scode = 200; + } else { + // Return a single moon by ID + + const uint64_t id = Utils::hexStrToU64(ps[1].c_str()); + for(std::vector::const_iterator m(moons.begin());m!=moons.end();++m) { + if (m->id() == id) { + _moonToJson(res,*m); + scode = 200; + break; + } + } + + } + } else if (ps[0] == "network") { + ZT_VirtualNetworkList *nws = _node->networks(); + if (nws) { + if (ps.size() == 1) { + // Return [array] of all networks + + res = nlohmann::json::array(); + for(unsigned long i=0;inetworkCount;++i) { + OneService::NetworkSettings localSettings; + getNetworkSettings(nws->networks[i].nwid,localSettings); + nlohmann::json nj; + _networkToJson(nj,&(nws->networks[i]),portDeviceName(nws->networks[i].nwid),localSettings); + res.push_back(nj); + } + + scode = 200; + } else if (ps.size() == 2) { + // Return a single network by ID or 404 if not found + + const uint64_t wantnw = Utils::hexStrToU64(ps[1].c_str()); + for(unsigned long i=0;inetworkCount;++i) { + if (nws->networks[i].nwid == wantnw) { + OneService::NetworkSettings localSettings; + getNetworkSettings(nws->networks[i].nwid,localSettings); + _networkToJson(res,&(nws->networks[i]),portDeviceName(nws->networks[i].nwid),localSettings); + scode = 200; + break; + } + } + + } else scode = 404; + _node->freeQueryResult((void *)nws); + } else scode = 500; + } else if (ps[0] == "peer") { + ZT_PeerList *pl = _node->peers(); + if (pl) { + if (ps.size() == 1) { + // Return [array] of all peers + + res = nlohmann::json::array(); + for(unsigned long i=0;ipeerCount;++i) { + nlohmann::json pj; + _peerToJson(pj,&(pl->peers[i])); + res.push_back(pj); + } + + scode = 200; + } else if (ps.size() == 2) { + // Return a single peer by ID or 404 if not found + + uint64_t wantp = Utils::hexStrToU64(ps[1].c_str()); + for(unsigned long i=0;ipeerCount;++i) { + if (pl->peers[i].address == wantp) { + _peerToJson(res,&(pl->peers[i])); + scode = 200; + break; + } + } + + } else scode = 404; + _node->freeQueryResult((void *)pl); + } else scode = 500; + } else { + if (_controller) { + scode = _controller->handleControlPlaneHttpGET(std::vector(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType); + } else scode = 404; + } + + } else scode = 401; // isAuth == false + } else if ((httpMethod == HTTP_POST)||(httpMethod == HTTP_PUT)) { + if (isAuth) { + + if (ps[0] == "moon") { + if (ps.size() == 2) { + + uint64_t seed = 0; + try { + json j(OSUtils::jsonParse(body)); + if (j.is_object()) { + seed = Utils::hexStrToU64(OSUtils::jsonString(j["seed"],"0").c_str()); + } + } catch ( ... ) { + // discard invalid JSON + } + + std::vector moons(_node->moons()); + const uint64_t id = Utils::hexStrToU64(ps[1].c_str()); + for(std::vector::const_iterator m(moons.begin());m!=moons.end();++m) { + if (m->id() == id) { + _moonToJson(res,*m); + scode = 200; + break; + } + } + + if ((scode != 200)&&(seed != 0)) { + char tmp[64]; + Utils::snprintf(tmp,sizeof(tmp),"%.16llx",id); + res["id"] = tmp; + res["roots"] = json::array(); + res["timestamp"] = 0; + res["signature"] = json(); + res["updatesMustBeSignedBy"] = json(); + res["waiting"] = true; + _node->orbit(id,seed); + } + + } else scode = 404; + } else if (ps[0] == "network") { + if (ps.size() == 2) { + + uint64_t wantnw = Utils::hexStrToU64(ps[1].c_str()); + _node->join(wantnw,(void *)0); // does nothing if we are a member + ZT_VirtualNetworkList *nws = _node->networks(); + if (nws) { + for(unsigned long i=0;inetworkCount;++i) { + if (nws->networks[i].nwid == wantnw) { + OneService::NetworkSettings localSettings; + getNetworkSettings(nws->networks[i].nwid,localSettings); + + try { + json j(OSUtils::jsonParse(body)); + if (j.is_object()) { + json &allowManaged = j["allowManaged"]; + if (allowManaged.is_boolean()) localSettings.allowManaged = (bool)allowManaged; + json &allowGlobal = j["allowGlobal"]; + if (allowGlobal.is_boolean()) localSettings.allowGlobal = (bool)allowGlobal; + json &allowDefault = j["allowDefault"]; + if (allowDefault.is_boolean()) localSettings.allowDefault = (bool)allowDefault; + } + } catch ( ... ) { + // discard invalid JSON + } + + setNetworkSettings(nws->networks[i].nwid,localSettings); + _networkToJson(res,&(nws->networks[i]),portDeviceName(nws->networks[i].nwid),localSettings); + + scode = 200; + break; + } + } + _node->freeQueryResult((void *)nws); + } else scode = 500; + + } else scode = 404; + } else { + if (_controller) + scode = _controller->handleControlPlaneHttpPOST(std::vector(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType); + else scode = 404; + } + + } else scode = 401; // isAuth == false + } else if (httpMethod == HTTP_DELETE) { + if (isAuth) { + + if (ps[0] == "moon") { + if (ps.size() == 2) { + _node->deorbit(Utils::hexStrToU64(ps[1].c_str())); + res["result"] = true; + scode = 200; + } // else 404 + } else if (ps[0] == "network") { + ZT_VirtualNetworkList *nws = _node->networks(); + if (nws) { + if (ps.size() == 2) { + uint64_t wantnw = Utils::hexStrToU64(ps[1].c_str()); + for(unsigned long i=0;inetworkCount;++i) { + if (nws->networks[i].nwid == wantnw) { + _node->leave(wantnw,(void **)0); + res["result"] = true; + scode = 200; + break; + } + } + } // else 404 + _node->freeQueryResult((void *)nws); + } else scode = 500; + } else { + if (_controller) + scode = _controller->handleControlPlaneHttpDELETE(std::vector(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType); + else scode = 404; + } + + } else scode = 401; // isAuth = false + } else { + scode = 400; + } + + if (responseBody.length() == 0) { + if ((res.is_object())||(res.is_array())) + responseBody = OSUtils::jsonDump(res); + else responseBody = "{}"; + responseContentType = "application/json"; + } + + // Wrap result in jsonp function call if the user included a jsonp= url argument. + // Also double-check isAuth since forbidding this without auth feels safer. + std::map::const_iterator jsonp(urlArgs.find("jsonp")); + if ((isAuth)&&(jsonp != urlArgs.end())&&(responseContentType == "application/json")) { + if (responseBody.length() > 0) + responseBody = jsonp->second + "(" + responseBody + ");"; + else responseBody = jsonp->second + "(null);"; + responseContentType = "application/javascript"; + } + + return scode; + } + // Must be called after _localConfig is read or modified void applyLocalConfig() { @@ -1170,7 +1650,9 @@ public: } } - // Handlers for Node and Phy<> callbacks ----------------------------------- + // ========================================================================= + // Handlers for Node and Phy<> callbacks + // ========================================================================= inline void phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *localAddr,const struct sockaddr *from,void *data,unsigned long len) { @@ -1780,9 +2262,7 @@ public: if (allow) { try { - if (_controlPlane) - scode = _controlPlane->handleRequest(tc->from,tc->parser.method,tc->url,tc->headers,tc->body,data,contentType); - else scode = 500; + scode = handleControlPlaneHttpRequest(tc->from,tc->parser.method,tc->url,tc->headers,tc->body,data,contentType); } catch (std::exception &exc) { fprintf(stderr,"WARNING: unexpected exception processing control HTTP request: %s" ZT_EOL_S,exc.what()); scode = 500; diff --git a/service/OneService.hpp b/service/OneService.hpp index 442471ad..3390f2ac 100644 --- a/service/OneService.hpp +++ b/service/OneService.hpp @@ -131,11 +131,6 @@ public: */ virtual std::string portDeviceName(uint64_t nwid) const = 0; - /** - * @return True if TCP fallback is currently active - */ - virtual bool tcpFallbackActive() const = 0; - /** * Terminate background service (can be called from other threads) */ -- cgit v1.2.3 From 5dbafc2eebced7275d9d85c68abbbee4c0aca948 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 7 Mar 2017 14:17:51 -0800 Subject: Add config to status in JSON API. --- service/OneService.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index eec9ac96..28f6dfcf 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1126,7 +1126,16 @@ public: res["version"] = tmp; res["clock"] = OSUtils::now(); - World planet(_node->planet()); + { + Mutex::Lock _l(_localConfig_m); + res["config"] = _localConfig; + } + json &settings = res["config"]["settings"]; + settings["primaryPort"] = OSUtils::jsonInt(settings["primaryPort"],(uint64_t)_primaryPort) & 0xffff; + settings["portMappingEnabled"] = OSUtils::jsonBool(settings["portMappingEnabled"],true); + settings["softwareUpdate"] = OSUtils::jsonString(settings["softwareUpdate"],ZT_SOFTWARE_UPDATE_DEFAULT); + + const World planet(_node->planet()); res["planetWorldId"] = planet.id(); res["planetWorldTimestamp"] = planet.timestamp(); -- cgit v1.2.3 From 5249ce8fb459ed2d7fb37fdbd8a9faf2a0eb6365 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 8 Mar 2017 08:45:04 -0800 Subject: Small amount of cleanup. --- service/OneService.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 28f6dfcf..7e8a58e8 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1132,14 +1132,18 @@ public: } json &settings = res["config"]["settings"]; settings["primaryPort"] = OSUtils::jsonInt(settings["primaryPort"],(uint64_t)_primaryPort) & 0xffff; +#ifdef ZT_USE_MINIUPNPC settings["portMappingEnabled"] = OSUtils::jsonBool(settings["portMappingEnabled"],true); +#else + settings["portMappingEnabled"] = false; // not supported in build +#endif settings["softwareUpdate"] = OSUtils::jsonString(settings["softwareUpdate"],ZT_SOFTWARE_UPDATE_DEFAULT); const World planet(_node->planet()); res["planetWorldId"] = planet.id(); res["planetWorldTimestamp"] = planet.timestamp(); - #ifdef ZT_ENABLE_CLUSTER +#ifdef ZT_ENABLE_CLUSTER json cj; ZT_ClusterStatus cs; _node->clusterStatus(&cs); @@ -1162,9 +1166,9 @@ public: cj["clusterSize"] = cs.clusterSize; } res["cluster"] = cj; - #else +#else res["cluster"] = json(); - #endif +#endif scode = 200; } else if (ps[0] == "moon") { -- cgit v1.2.3 From 9c1a9f984b2bdffe94e147e3548080dfc7c2ef72 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 8 Mar 2017 10:18:12 -0800 Subject: Clean iddb.d periodically. --- osdep/OSUtils.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++++ osdep/OSUtils.hpp | 10 ++++++++++ service/OneService.cpp | 10 ++++++++++ 3 files changed, 66 insertions(+) (limited to 'service/OneService.cpp') diff --git a/osdep/OSUtils.cpp b/osdep/OSUtils.cpp index fc02109a..69d368ef 100644 --- a/osdep/OSUtils.cpp +++ b/osdep/OSUtils.cpp @@ -145,6 +145,52 @@ std::map OSUtils::listDirectoryFull(const char *path) return r; } +long OSUtils::cleanDirectory(const char *path,const uint64_t olderThan) +{ + long cleaned = 0; + +#ifdef __WINDOWS__ + HANDLE hFind; + WIN32_FIND_DATAA ffd; + if ((hFind = FindFirstFileA((std::string(path) + "\\*").c_str(),&ffd)) != INVALID_HANDLE_VALUE) { + do { + if ((strcmp(ffd.cFileName,"."))&&(strcmp(ffd.cFileName,".."))) { + } + } while (FindNextFileA(hFind,&ffd)); + FindClose(hFind); + } +#else + struct dirent de; + struct dirent *dptr; + struct stat st; + char tmp[4096]; + DIR *d = opendir(path); + if (!d) + return -1; + dptr = (struct dirent *)0; + for(;;) { + if (readdir_r(d,&de,&dptr)) + break; + if (dptr) { + if ((strcmp(dptr->d_name,"."))&&(strcmp(dptr->d_name,".."))&&(dptr->d_type == DT_REG)) { + Utils::snprintf(tmp,sizeof(tmp),"%s/%s",path,dptr->d_name); + if (stat(tmp,&st) == 0) { + uint64_t mt = (uint64_t)(st.st_mtime); + if ((mt > 0)&&((mt * 1000) < olderThan)) { + printf("%s\n",tmp); + if (unlink(tmp) == 0) + ++cleaned; + } + } + } + } else break; + } + closedir(d); +#endif + + return cleaned; +} + bool OSUtils::rmDashRf(const char *path) { #ifdef __WINDOWS__ diff --git a/osdep/OSUtils.hpp b/osdep/OSUtils.hpp index 2fe01979..adf1488e 100644 --- a/osdep/OSUtils.hpp +++ b/osdep/OSUtils.hpp @@ -119,6 +119,16 @@ public: */ static std::map listDirectoryFull(const char *path); + /** + * Clean a directory of files whose last modified time is older than this + * + * This ignores directories, symbolic links, and other special files. + * + * @param olderThan Last modified older than timestamp (ms since epoch) + * @return Number of cleaned files or negative on fatal error + */ + static long cleanDirectory(const char *path,const uint64_t olderThan); + /** * Delete a directory and all its files and subdirectories recursively * diff --git a/service/OneService.cpp b/service/OneService.cpp index 7e8a58e8..b9ea32af 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -147,6 +147,9 @@ namespace ZeroTier { typedef BSDEthernetTap EthernetTap; } // How often to check for local interface addresses #define ZT_LOCAL_INTERFACE_CHECK_INTERVAL 60000 +// Clean files from iddb.d that are older than this (60 days) +#define ZT_IDDB_CLEANUP_AGE 5184000000ULL + namespace ZeroTier { namespace { @@ -826,6 +829,7 @@ public: uint64_t lastBindRefresh = 0; uint64_t lastUpdateCheck = clockShouldBe; uint64_t lastLocalInterfaceAddressCheck = (clockShouldBe - ZT_LOCAL_INTERFACE_CHECK_INTERVAL) + 15000; // do this in 15s to give portmapper time to configure and other things time to settle + uint64_t lastCleanedIddb = 0; for(;;) { _run_m.lock(); if (!_run) { @@ -840,6 +844,12 @@ public: const uint64_t now = OSUtils::now(); + // Clean iddb.d on start and every 24 hours + if ((now - lastCleanedIddb) > 86400000) { + lastCleanedIddb = now; + OSUtils::cleanDirectory((_homePath + ZT_PATH_SEPARATOR_S "iddb.d").c_str(),now - ZT_IDDB_CLEANUP_AGE); + } + // Attempt to detect sleep/wake events by detecting delay overruns bool restarted = false; if ((now > clockShouldBe)&&((now - clockShouldBe) > 10000)) { -- cgit v1.2.3 From 6194d2af3d22c9208998fba490126a2f1416df67 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 10 Mar 2017 19:37:03 -0800 Subject: Return 200 from JSON API when moon is POSTed. --- service/OneService.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index b9ea32af..8bc06935 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1312,6 +1312,7 @@ public: res["updatesMustBeSignedBy"] = json(); res["waiting"] = true; _node->orbit(id,seed); + scode = 200; } } else scode = 404; -- cgit v1.2.3 From d0224b36236e969ad4f861986fc08ba97a7dc990 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 10 Mar 2017 22:02:08 -0800 Subject: Software update fix. --- service/OneService.cpp | 70 ++++++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 34 deletions(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 8bc06935..129c0499 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1148,6 +1148,7 @@ public: settings["portMappingEnabled"] = false; // not supported in build #endif settings["softwareUpdate"] = OSUtils::jsonString(settings["softwareUpdate"],ZT_SOFTWARE_UPDATE_DEFAULT); + settings["softwareUpdateChannel"] = OSUtils::jsonString(settings["softwareUpdateChannel"],ZT_SOFTWARE_UPDATE_DEFAULT_CHANNEL); const World planet(_node->planet()); res["planetWorldId"] = planet.id(); @@ -1420,12 +1421,13 @@ public: void applyLocalConfig() { Mutex::Lock _l(_localConfig_m); + json lc(_localConfig); _v4Hints.clear(); _v6Hints.clear(); _v4Blacklists.clear(); _v6Blacklists.clear(); - json &virt = _localConfig["virtual"]; + json &virt = lc["virtual"]; if (virt.is_object()) { for(json::iterator v(virt.begin());v!=virt.end();++v) { const std::string nstr = v.key(); @@ -1470,7 +1472,7 @@ public: _globalV4Blacklist.clear(); _globalV6Blacklist.clear(); - json &physical = _localConfig["physical"]; + json &physical = lc["physical"]; if (physical.is_object()) { for(json::iterator phy(physical.begin());phy!=physical.end();++phy) { const InetAddress net(OSUtils::jsonString(phy.key(),"")); @@ -1489,41 +1491,41 @@ public: _allowManagementFrom.clear(); _interfacePrefixBlacklist.clear(); - json &settings = _localConfig["settings"]; - if (settings.is_object()) { - _primaryPort = (unsigned int)OSUtils::jsonInt(settings["primaryPort"],(uint64_t)_primaryPort) & 0xffff; - _portMappingEnabled = OSUtils::jsonBool(settings["portMappingEnabled"],true); - - const std::string up(OSUtils::jsonString(settings["softwareUpdate"],ZT_SOFTWARE_UPDATE_DEFAULT)); - const bool udist = OSUtils::jsonBool(settings["softwareUpdateDist"],false); - if (((up == "apply")||(up == "download"))||(udist)) { - if (!_updater) - _updater = new SoftwareUpdater(*_node,_homePath); - _updateAutoApply = (up == "apply"); - _updater->setUpdateDistribution(udist); - _updater->setChannel(OSUtils::jsonString(settings["softwareUpdateChannel"],ZT_SOFTWARE_UPDATE_DEFAULT_CHANNEL)); - } else { - delete _updater; - _updater = (SoftwareUpdater *)0; - _updateAutoApply = false; - } - json &ignoreIfs = settings["interfacePrefixBlacklist"]; - if (ignoreIfs.is_array()) { - for(unsigned long i=0;i 0) - _interfacePrefixBlacklist.push_back(tmp); - } + json &settings = lc["settings"]; + + _primaryPort = (unsigned int)OSUtils::jsonInt(settings["primaryPort"],(uint64_t)_primaryPort) & 0xffff; + _portMappingEnabled = OSUtils::jsonBool(settings["portMappingEnabled"],true); + + const std::string up(OSUtils::jsonString(settings["softwareUpdate"],ZT_SOFTWARE_UPDATE_DEFAULT)); + const bool udist = OSUtils::jsonBool(settings["softwareUpdateDist"],false); + if (((up == "apply")||(up == "download"))||(udist)) { + if (!_updater) + _updater = new SoftwareUpdater(*_node,_homePath); + _updateAutoApply = (up == "apply"); + _updater->setUpdateDistribution(udist); + _updater->setChannel(OSUtils::jsonString(settings["softwareUpdateChannel"],ZT_SOFTWARE_UPDATE_DEFAULT_CHANNEL)); + } else { + delete _updater; + _updater = (SoftwareUpdater *)0; + _updateAutoApply = false; + } + + json &ignoreIfs = settings["interfacePrefixBlacklist"]; + if (ignoreIfs.is_array()) { + for(unsigned long i=0;i 0) + _interfacePrefixBlacklist.push_back(tmp); } + } - json &amf = settings["allowManagementFrom"]; - if (amf.is_array()) { - for(unsigned long i=0;i Date: Tue, 14 Mar 2017 13:17:10 -0700 Subject: Wait a minute (literally) before doing software update check on startup. --- service/OneService.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 129c0499..ea64b4aa 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -827,7 +827,7 @@ public: _lastRestart = clockShouldBe; uint64_t lastTapMulticastGroupCheck = 0; uint64_t lastBindRefresh = 0; - uint64_t lastUpdateCheck = clockShouldBe; + uint64_t lastUpdateCheck = clockShouldBe + 60000; uint64_t lastLocalInterfaceAddressCheck = (clockShouldBe - ZT_LOCAL_INTERFACE_CHECK_INTERVAL) + 15000; // do this in 15s to give portmapper time to configure and other things time to settle uint64_t lastCleanedIddb = 0; for(;;) { -- cgit v1.2.3 From f99b62c48d6cb9d1b79a67cb3cf5ae5e352a176b Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 14 Mar 2017 15:38:24 -0700 Subject: fix stupid thing. --- service/OneService.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index ea64b4aa..129c0499 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -827,7 +827,7 @@ public: _lastRestart = clockShouldBe; uint64_t lastTapMulticastGroupCheck = 0; uint64_t lastBindRefresh = 0; - uint64_t lastUpdateCheck = clockShouldBe + 60000; + uint64_t lastUpdateCheck = clockShouldBe; uint64_t lastLocalInterfaceAddressCheck = (clockShouldBe - ZT_LOCAL_INTERFACE_CHECK_INTERVAL) + 15000; // do this in 15s to give portmapper time to configure and other things time to settle uint64_t lastCleanedIddb = 0; for(;;) { -- cgit v1.2.3 From 1ef3069a7ef7692bb27d64b85dd2cfdf201e33b2 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 14 Mar 2017 21:21:12 -0700 Subject: 1.2.0 release notes and a few final tweaks and cleanup. --- RELEASE-NOTES.md | 84 +++++++++++++++++++++++++++++++--------------- rule-compiler/README.md | 3 ++ rule-compiler/cli.js | 35 ++++++++++++++----- rule-compiler/package.json | 2 +- service/OneService.cpp | 8 ----- service/README.md | 4 ++- 6 files changed, 90 insertions(+), 46 deletions(-) (limited to 'service/OneService.cpp') diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 42a2aaa4..d0ad47d8 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,32 +1,30 @@ ZeroTier Release Notes ====== -*As of 1.2.0 this will serve as a detailed changelog, which we've needed for a long time.* +# 2017-03-14 -- Version 1.2.0 -# 2017-03-13 -- Version 1.2.0 +Version 1.2.0 is a major milestone release representing almost nine months of work. It includes our rules engine for distributed network packet filtering and security monitoring, federated roots, and many other architectural and UI improvements and bug fixes. -Version 1.2.0 is a major milestone release and introduces a large number of new capabilities to the ZeroTier core network hypervisor. It also includes some security tightening, major UI improvements for Windows and Macintosh platforms, and a number of bug fixes and platform issue workarounds. - -## Features in 1.2.0 +## New Features in 1.2.0 ### The ZeroTier Rules Engine The largest new feature in 1.2.0, and the product of many months of work, is our advanced network rules engine. With this release we achieve traffic control, security monitoring, and micro-segmentation capability on par with many enterprise SDN solutions designed for use in advanced data centers and corporate networks. -Rules allow you to filter packets on your network and vector traffic to security observers (e.g. a node running Snort). Security observation can be performed in-band using REDIRECT or out of band using TEE, and for tha latter it can be done for headers only, for select traffic, or probabilistically to reduce overhead on large distributed networks. +Rules allow you to filter packets on your network and vector traffic to security observers. Security observation can be performed in-band using REDIRECT or out of band using TEE. Tags and capabilites provide advanced methods for implementing fine grained permission structures and micro-segmentation schemes without bloating the size and complexity of your rules table. -See our manual for more information. +See the [rules engine announcement blog post](https://www.zerotier.com/blog/?p=927) for an in-depth discussion of theory and implementation. The [manual](https://www.zerotier.com/manual.shtml) contains detailed information on rule, tag, and capability use, and the `rule-compiler/` subfolder of the ZeroTier source tree contains a JavaScript function to compile rules in our human-readable rule definition language into rules suitable for import into a network controller. (ZeroTier Central uses this same script to compile rules on [my.zerotier.com](https://my.zerotier.com/).) ### Root Server Federation -It's now possible to create your own root servers and add them to the root server pool on your nodes. This is done by creating what's called a "moon," which is a signed enumeration of root servers and their stable points on the network. Refer to the manual for more details on how to do this and how it works. +It's now possible to create your own root servers and add them to the root server pool on your nodes. This is done by creating what's called a "moon," which is a signed enumeration of root servers and their stable points on the network. Refer to the [manual](https://www.zerotier.com/manual.shtml) for instructions. Federated roots achieve a number of things: * You can deploy your own infrastructure to reduce dependency on ours. - * You can deploy them *inside your LAN* to ensure that network connectivity inside your facility still works if the Internet goes down. This is the first step toward making ZeroTier viable as an in-house SDN solution. + * You can deploy roots *inside your LAN* to ensure that network connectivity inside your facility still works if the Internet goes down. This is the first step toward making ZeroTier viable as an in-house SDN solution. * Roots can be deployed inside national boundaries for countries with data residency laws or "great firewalls." (As of 1.2.0 there is still no way to force all traffic to use these roots, but that will be easy to do in a later version.) * Last but not least this makes ZeroTier somewhat less centralized by eliminating any hard dependency on ZeroTier, Inc.'s infrastructure. @@ -50,23 +48,28 @@ A good software update system for Windows and Mac clients has been a missing fea We've greatly improved this mechanism in 1.2.0. Not only does it now do a better job of actually invoking the update, but it also transfers updates in-band using the ZeroTier protocol. This means it can work in environments that do not allows http/https traffic or that force it through proxies. There's also now an update channel setting: `beta` or `release` (the default). -As before software updates are authenticated in two ways: +Software updates are authenticated three ways: + + 1. ZeroTier's own signing key is used to sign all updates and this signature is checked prior to installation. ZeroTier, Inc.'s signatures are performed on an air-gapped machine. - 1. ZeroTier's own signing key is used to sign all updates and this signature is checked prior to installation. Our signatures are done on an air-gapped machine. + 2. Updates for Mac and Windows are signed using Apple and Microsoft (DigiCert EV) keys and will not install unless these signatures are also valid. - 2. Updates for Mac and Windows are signed using Apple and Microsoft (DigiCert) keys and will not install unless these signatures are also valid. + 3. The new in-band update mechanism also authenticates the source of the update via ZeroTier's built-in security features. This provides transport security, while 1 and 2 provide security of the update at rest. -Version 1.2.0's in-band mechanism effectively adds a third way: updates are fetched in-band from a designated ZeroTier node, thus authenticating the source using ZeroTier's built-in encryption and authentication mechanisms. +Updates are now configurable via `local.conf`. There are three options: `disable`, `download`, and `apply`. The third (apply) is the default for official builds on Windows and Mac, making updates happen silently and automatically as they do for popular browsers like Chrome and Firefox. Updates are disabled by default on Linux and other Unix-type systems as these are typically updated through package managers. -Updates are now configurable via `local.conf`. There are three options: `disable`, `download`, and `apply`. The third is the default for official builds on Windows and Mac, making updates happen silently and automatically as they do for popular browsers like Chrome and Firefox. For managed enterprise deployments IT people could ship a local.conf that disables updates and instead push updates via their management capabilities. Updates are disabled on Linux and other Unix-type platforms as these get updates through package repositories. +### Path Link Quality Awareness -### Path Quality Monitoring (QoS and SD-WAN phase one) +Version 1.2.0 is now aware of the link quality of direct paths with other 1.2.0 nodes. This information isn't used yet but is visible through the JSON API. (Quality always shows as 100% with pre-1.2.0 nodes.) Quality is measured passively with no additional overhead using a counter based packet loss detection algorithm. -Version 1.2.0 is now aware of the link quality of direct paths with other 1.2.0 nodes. This information isn't used yet but is visible through the JSON API. (Quality always shows as 100% with pre-1.2.0 nodes.) +This information is visible from the command line via `listpeers`: -Link quality monitoring is a precursor to intelligent multi-path and QoS support, which will in future versions bring us to feature parity with SD-WAN products like Cisco iWAN. + 200 listpeers XXXXXXXXXX 199.XXX.XXX.XXX/9993;10574;15250;1.00 48 1.2.0 LEAF + 200 listpeers XXXXXXXXXX 195.XXX.XXX.XXX/45584;467;7608;0.44 290 1.2.0 LEAF -"Connect all the things!" +The first peer's path is at 100% (1.00), while the second peer's path is suffering quite a bit of packet loss (0.44). + +Link quality awareness is a precursor to intelligent multi-path and QoS support, which will in future versions bring us to feature parity with SD-WAN products like Cisco iWAN. ### Security Improvements @@ -78,15 +81,42 @@ Revocations propagate using a "rumor mill" peer to peer algorithm. This means th ### Windows and Macintosh UI Improvements (ZeroTier One) -The Mac has a whole new UI built natively in Objective-C. It provides a pulldown similar in appearance and operation to the Mac WiFi task bar menu. The Windows UI has also been improved and now provides a task bar icon that can be right-clicked to manage networks. Both now expose managed route and IP permissions, allowing nodes to easily opt in to full tunnel operation if you have a router configured on your network. +The Mac has a whole new UI built natively in Objective-C. It provides a pulldown similar in appearance and operation to the Mac WiFi task bar menu. + +The Windows UI has also been improved and now provides a task bar icon that can be right-clicked to manage networks. Both now expose managed route and IP permissions, allowing nodes to easily opt in to full tunnel operation if you have a router configured on your network. + +### Ad-Hoc Networks + +A special kind of public network called an ad-hoc network may be accessed by joining a network ID with the format: + + ffSSSSEEEE000000 + | | | | + | | | Reserved for future use, must be 0 + | | End of port range (hex) + | Start of port range (hex) + Reserved ZeroTier address prefix indicating a controller-less network + +Ad-hoc networks are public (no access control) networks that have no network controller. Instead their configuration and other credentials are generated locally. Ad-hoc networks permit only IPv6 UDP and TCP unicast traffic (no multicast or broadcast) using 6plane format NDP-emulated IPv6 addresses. In addition an ad-hoc network ID encodes an IP port range. UDP packets and TCP SYN (connection open) packets are only allowed to desintation ports within the encoded range. + +For example `ff00160016000000` is an ad-hoc network allowing only SSH, while `ff0000ffff000000` is an ad-hoc network allowing any UDP or TCP port. + +Keep in mind that these networks are public and anyone in the entire world can join them. Care must be taken to avoid exposing vulnerable services or sharing unwanted files or other resources. + +### Network Controller (Partial) Rewrite + +The network controller has been largely rewritten to use a simple in-filesystem JSON data store in place of SQLite, and it is now included by default in all Windows, Mac, Linux, and BSD builds. This means any desktop or server node running ZeroTier One can now be a controller with no recompilation needed. + +If you have data in an old SQLite3 controller we've included a NodeJS script in `controller/migrate-sqlite` to migrate data to the new format. If you don't migrate, members will start getting `NOT_FOUND` when they attempt to query for updates. ## Major Bug Fixes in 1.2.0 - * **The Windows HyperV 100% CPU bug** - * This long-running problem turns out to have been an issue with Windows itself, but one we were triggering by placing invalid data into the Windows registry. Microsoft is aware of the issue but we've also fixed the triggering problem on our side. ZeroTier should now co-exist quite well with HyperV and should now be able to be bridged with a HyperV virtual switch. - * **Segmenation Faults on musl-libc based Linux Systems** - * Alpine Linux and some embedded Linux systems that use musl libc (a minimal libc) experienced segmentation faults. These were due to a smaller default stack size. A work-around that sets the stack size for new threads has been added. - * **Windows Firewall Blocks Local JSON API** - * On some Windows systems the firewall likes to block 127.0.0.1:9993 for mysterious reasons. This is now fixed in the installer via the addition of another firewall exemption rule. - * **UI Crash on Embedded Windows Due to Missing Fonts** - * The MSI installer now ships fonts and will install them if they are not present, so this should be fixed. + * **The Windows HyperV 100% CPU bug is FINALLY DEAD**: This long-running problem turns out to have been an issue with Windows itself, but one we were triggering by placing invalid data into the Windows registry. Microsoft is aware of the issue but we've also fixed the triggering problem on our side. ZeroTier should now co-exist quite well with HyperV and should now be able to be bridged with a HyperV virtual switch. + * **Segmenation faults on musl-libc based Linux systems**: Alpine Linux and some embedded Linux systems that use musl libc (a minimal libc) experienced segmentation faults. These were due to a smaller default stack size. A work-around that sets the stack size for new threads has been added. + * **Windows firewall blocks local JSON API**: On some Windows systems the firewall likes to block 127.0.0.1:9993 for mysterious reasons. This is now fixed in the installer via the addition of another firewall exemption rule. + * **UI crash on embedded Windows due to missing fonts**: The MSI installer now ships fonts and will install them if they are not present, so this should be fixed. + +## Other Improvements in 1.2.0 + + * **Improved dead path detection**: ZeroTier is now more aggressive about expiring paths that do not seem to be active. If a path seems marginal it is re-confirmed before re-use. + * **Minor performance improvements**: We've reduced unnecessary memcpy's and made a few other performance improvements in the core. + * **Linux static binaries**: For our official packages (the ones in the download.zerotier.com apt and yum repositories) we now build Linux binaries with static linking. Hopefully this will stop all the bug reports relating to library inconsistencies, as well as allowing our deb packages to run on a wider variety of Debian-based distributions. (There are far too many of these to support officially!) The overhead for this is very small, especially since we built our static versions against musl-libc. Distribution maintainers are of course free to build dynamically linked versions for inclusion into distributions; this only affects our official binaries. diff --git a/rule-compiler/README.md b/rule-compiler/README.md index e3aa2615..1ceeb713 100644 --- a/rule-compiler/README.md +++ b/rule-compiler/README.md @@ -3,3 +3,6 @@ ZeroTier Rules Compiler This script converts ZeroTier rules in human-readable format into rules suitable for import into a ZeroTier network controller. It's the script that is used in the rules editor on [ZeroTier Central](https://my.zerotier.com/). +A command line interface is included that may be invoked as: `node cli.js `. + +See the [manual](https://www.zerotier.com/manual.shtml) for information about the rules engine and rules script syntax. diff --git a/rule-compiler/cli.js b/rule-compiler/cli.js index c4a3b291..a0ff5197 100644 --- a/rule-compiler/cli.js +++ b/rule-compiler/cli.js @@ -1,7 +1,6 @@ 'use strict'; var fs = require('fs'); - var RuleCompiler = require('./rule-compiler.js'); if (process.argv.length < 3) { @@ -9,21 +8,39 @@ if (process.argv.length < 3) { process.exit(1); } -var src = fs.readFileSync(process.argv[2]).toString(); - var rules = []; var caps = {}; var tags = {}; -var err = RuleCompiler.compile(src,rules,caps,tags); +var err = RuleCompiler.compile(fs.readFileSync(process.argv[2]).toString(),rules,caps,tags); if (err) { - console.log('ERROR parsing '+process.argv[2]+' line '+err[0]+' column '+err[1]+': '+err[2]); + console.error('ERROR parsing '+process.argv[2]+' line '+err[0]+' column '+err[1]+': '+err[2]); process.exit(1); } else { + let capsArray = []; + let capabilitiesByName = {}; + for(let n in caps) { + capsArray.push(caps[n]); + capabilitiesByName[n] = caps[n].id; + } + let tagsArray = []; + for(let n in tags) { + let t = tags[n]; + tagsArray.push({ + 'id': t.id, + 'default': t['default']||null + }); + } + console.log(JSON.stringify({ - rules: rules, - caps: caps, - tags: tags - },null,2)); + config: { + rules: rules, + capabilities: capsArray, + tags: tagsArray + }, + capabilitiesByName: capabilitiesByName, + tagsByName: tags + },null,1)); + process.exit(0); } diff --git a/rule-compiler/package.json b/rule-compiler/package.json index 451295a4..e12d3759 100644 --- a/rule-compiler/package.json +++ b/rule-compiler/package.json @@ -1,6 +1,6 @@ { "name": "zerotier-rule-compiler", - "version": "1.1.17-3", + "version": "1.2.0-1", "description": "ZeroTier Rule Script Compiler", "main": "cli.js", "scripts": { diff --git a/service/OneService.cpp b/service/OneService.cpp index 129c0499..4a2102f1 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -745,14 +745,6 @@ public: for(int i=0;i<3;++i) _portsBE[i] = Utils::hton((uint16_t)_ports[i]); - // Check for legacy controller.db and terminate if present to prevent nasty surprises for DIY controller folks - if (OSUtils::fileExists((_homePath + ZT_PATH_SEPARATOR_S "controller.db").c_str())) { - Mutex::Lock _l(_termReason_m); - _termReason = ONE_UNRECOVERABLE_ERROR; - _fatalErrorMessage = "controller.db is present in our home path! run migrate-sqlite to migrate to new controller.d format."; - return _termReason; - } - _controller = new EmbeddedNetworkController(_node,(_homePath + ZT_PATH_SEPARATOR_S ZT_CONTROLLER_DB_PATH).c_str()); _node->setNetconfMaster((void *)_controller); diff --git a/service/README.md b/service/README.md index bdf713c1..f5223f2d 100644 --- a/service/README.md +++ b/service/README.md @@ -27,6 +27,7 @@ Settings available in `local.conf` (this is not valid JSON, and JSON does not al "primaryPort": 0-65535, /* If set, override default port of 9993 and any command line port */ "portMappingEnabled": true|false, /* If true (the default), try to use uPnP or NAT-PMP to map ports */ "softwareUpdate": "apply"|"download"|"disable", /* Automatically apply updates, just download, or disable built-in software updates */ + "softwareUpdateChannel": "release"|"beta", /* Software update channel */ "softwareUpdateDist": true|false, /* If true, distribute software updates (only really useful to ZeroTier, Inc. itself, default is false) */ "interfacePrefixBlacklist": [ "XXX",... ], /* Array of interface name prefixes (e.g. eth for eth#) to blacklist for ZT traffic */ "allowManagementFrom": "NETWORK/bits"|null /* If non-NULL, allow JSON/HTTP management from this IP network. Default is 127.0.0.1 only. */ @@ -57,7 +58,8 @@ An example `local.conf`: } }, "settings": { - "relayPolicy": "ALWAYS" + "softwareUpdate": "apply", + "softwraeUpdateChannel": "release" } } ``` -- cgit v1.2.3 From c6a39ed927161736e44aeaa67c6783024c1fb86a Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 17 Mar 2017 13:55:26 -0700 Subject: Fixes for possible ARM issues, cleanup, fix for spurious meaningless exceptions on NETWORK_CONFIG_REQUEST --- make-linux.mk | 14 +++++++- node/Dictionary.hpp | 25 +++++++++++---- node/IncomingPacket.cpp | 6 ++-- node/Network.cpp | 8 +++++ one.cpp | 85 +++++++++++++++++++++++++++++++------------------ service/OneService.cpp | 2 ++ 6 files changed, 99 insertions(+), 41 deletions(-) (limited to 'service/OneService.cpp') diff --git a/make-linux.mk b/make-linux.mk index 1bb62852..528c41c4 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -54,7 +54,7 @@ ifeq ($(ZT_RULES_ENGINE_DEBUGGING),1) endif ifeq ($(ZT_DEBUG),1) - DEFS+=-DZT_TRACE +# DEFS+=-DZT_TRACE override CFLAGS+=-Wall -g -O -pthread $(INCLUDES) $(DEFS) override CXXFLAGS+=-Wall -g -O -std=c++11 -pthread $(INCLUDES) $(DEFS) override LDFLAGS+= @@ -96,6 +96,12 @@ endif ifeq ($(CC_MACH),arm) ZT_ARCHITECTURE=3 endif +ifeq ($(CC_MACH),armv6) + ZT_ARCHITECTURE=3 +endif +ifeq ($(CC_MACH),armv7) + ZT_ARCHITECTURE=3 +endif ifeq ($(CC_MACH),arm64) ZT_ARCHITECTURE=4 endif @@ -104,6 +110,12 @@ ifeq ($(CC_MACH),aarch64) endif DEFS+=-DZT_BUILD_PLATFORM=1 -DZT_BUILD_ARCHITECTURE=$(ZT_ARCHITECTURE) -DZT_SOFTWARE_UPDATE_DEFAULT="\"disable\"" +# Define some conservative CPU instruction set flags for arm32 since there's a ton of variation out there +ifeq ($(ZT_ARCHITECTURE),3) + override CFLAGS+=-march=armv6zk -mcpu=arm1176jzf-s -mfloat-abi=hard -mfpu=vfp + override CXXFLAGS+=-march=armv6zk -mcpu=arm1176jzf-s -mfloat-abi=hard -mfpu=vfp +endif + # Define this to build a static binary, which is needed to make this runnable on a few ancient Linux distros ifeq ($(ZT_STATIC),1) override LDFLAGS+=-static diff --git a/node/Dictionary.hpp b/node/Dictionary.hpp index 15ab9ce3..fa9e2883 100644 --- a/node/Dictionary.hpp +++ b/node/Dictionary.hpp @@ -61,15 +61,23 @@ public: Dictionary(const char *s) { - Utils::scopy(_d,sizeof(_d),s); + if (s) { + Utils::scopy(_d,sizeof(_d),s); + } else { + _d[0] = (char)0; + } } Dictionary(const char *s,unsigned int len) { - if (len > (C-1)) - len = C-1; - memcpy(_d,s,len); - _d[len] = (char)0; + if (s) { + if (len > (C-1)) + len = C-1; + memcpy(_d,s,len); + _d[len] = (char)0; + } else { + _d[0] = (char)0; + } } Dictionary(const Dictionary &d) @@ -91,7 +99,12 @@ public: */ inline bool load(const char *s) { - return Utils::scopy(_d,sizeof(_d),s); + if (s) { + return Utils::scopy(_d,sizeof(_d),s); + } else { + _d[0] = (char)0; + return true; + } } /** diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 800985dc..ac4ae377 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -836,7 +836,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S bool trustEstablished = false; unsigned int p = ZT_PACKET_IDX_PAYLOAD; - while ((p < size())&&((*this)[p])) { + while ((p < size())&&((*this)[p] != 0)) { p += com.deserialize(*this,p); if (com) { const SharedPtr network(RR->node->network(com.networkId())); @@ -953,8 +953,8 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons const uint64_t requestPacketId = packetId(); if (RR->localNetworkController) { - const unsigned int metaDataLength = at(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN); - const char *metaDataBytes = (const char *)field(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT,metaDataLength); + const unsigned int metaDataLength = (ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN <= size()) ? at(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN) : 0; + const char *metaDataBytes = (metaDataLength != 0) ? (const char *)field(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT,metaDataLength) : (const char *)0; const Dictionary metaData(metaDataBytes,metaDataLength); RR->localNetworkController->request(nwid,(hopCount > 0) ? InetAddress() : _path->address(),requestPacketId,peer->identity(),metaData); } else { diff --git a/node/Network.cpp b/node/Network.cpp index dd812cab..92ca67ab 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -1517,6 +1517,10 @@ void Network::_sendUpdatesToMembers(const MulticastGroup *const newMulticastGrou Packet outp(*a,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS); _config.com.serialize(outp); outp.append((uint8_t)0x00); + outp.append((uint16_t)0); // no capabilities + outp.append((uint16_t)0); // no tags + outp.append((uint16_t)0); // no revocations + outp.append((uint16_t)0); // no certificates of ownership RR->sw->send(outp,true); } _announceMulticastGroupsTo(*a,groups); @@ -1529,6 +1533,10 @@ void Network::_sendUpdatesToMembers(const MulticastGroup *const newMulticastGrou Packet outp(c,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS); _config.com.serialize(outp); outp.append((uint8_t)0x00); + outp.append((uint16_t)0); // no capabilities + outp.append((uint16_t)0); // no tags + outp.append((uint16_t)0); // no revocations + outp.append((uint16_t)0); // no certificates of ownership RR->sw->send(outp,true); } _announceMulticastGroupsTo(c,groups); diff --git a/one.cpp b/one.cpp index 95230bf1..25a50dbb 100644 --- a/one.cpp +++ b/one.cpp @@ -72,6 +72,7 @@ #include "osdep/OSUtils.hpp" #include "osdep/Http.hpp" +#include "osdep/Thread.hpp" #include "service/OneService.hpp" @@ -1209,6 +1210,52 @@ static void printHelp(const char *cn,FILE *out) fprintf(out," -q - Query API (zerotier-cli)" ZT_EOL_S); } +class _OneServiceRunner +{ +public: + _OneServiceRunner(const char *pn,const std::string &hd,unsigned int p) : progname(pn),returnValue(0),port(p),homeDir(hd) {} + void threadMain() + throw() + { + try { + for(;;) { + zt1Service = OneService::newInstance(homeDir.c_str(),port); + switch(zt1Service->run()) { + case OneService::ONE_STILL_RUNNING: // shouldn't happen, run() won't return until done + case OneService::ONE_NORMAL_TERMINATION: + break; + case OneService::ONE_UNRECOVERABLE_ERROR: + fprintf(stderr,"%s: fatal error: %s" ZT_EOL_S,progname,zt1Service->fatalErrorMessage().c_str()); + returnValue = 1; + break; + case OneService::ONE_IDENTITY_COLLISION: { + delete zt1Service; + zt1Service = (OneService *)0; + std::string oldid; + OSUtils::readFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret").c_str(),oldid); + if (oldid.length()) { + OSUtils::writeFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret.saved_after_collision").c_str(),oldid); + OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret").c_str()); + OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S + "identity.public").c_str()); + } + } continue; // restart! + } + break; // terminate loop -- normally we don't keep restarting + } + + delete zt1Service; + zt1Service = (OneService *)0; + } catch ( ... ) { + fprintf(stderr,"%s: unexpected exception starting main OneService instance" ZT_EOL_S,progname); + returnValue = 1; + } + } + const char *progname; + unsigned int returnValue; + unsigned int port; + const std::string &homeDir; +}; + #ifdef __WINDOWS__ int _tmain(int argc, _TCHAR* argv[]) #else @@ -1421,8 +1468,8 @@ int main(int argc,char **argv) } else { // Running from service manager _winPokeAHole(); - ZeroTierOneService zt1Service; - if (CServiceBase::Run(zt1Service) == TRUE) { + ZeroTierOneService zt1WindowsService; + if (CServiceBase::Run(zt1WindowsService) == TRUE) { return 0; } else { fprintf(stderr,"%s: unable to start service (try -h for help)" ZT_EOL_S,argv[0]); @@ -1448,35 +1495,11 @@ int main(int argc,char **argv) } #endif // __UNIX_LIKE__ - unsigned int returnValue = 0; - - for(;;) { - zt1Service = OneService::newInstance(homeDir.c_str(),port); - switch(zt1Service->run()) { - case OneService::ONE_STILL_RUNNING: // shouldn't happen, run() won't return until done - case OneService::ONE_NORMAL_TERMINATION: - break; - case OneService::ONE_UNRECOVERABLE_ERROR: - fprintf(stderr,"%s: fatal error: %s" ZT_EOL_S,argv[0],zt1Service->fatalErrorMessage().c_str()); - returnValue = 1; - break; - case OneService::ONE_IDENTITY_COLLISION: { - delete zt1Service; - zt1Service = (OneService *)0; - std::string oldid; - OSUtils::readFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret").c_str(),oldid); - if (oldid.length()) { - OSUtils::writeFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret.saved_after_collision").c_str(),oldid); - OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret").c_str()); - OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S + "identity.public").c_str()); - } - } continue; // restart! - } - break; // terminate loop -- normally we don't keep restarting - } + _OneServiceRunner thr(argv[0],homeDir,port); + thr.threadMain(); + //Thread::join(Thread::start(&thr)); - delete zt1Service; - zt1Service = (OneService *)0; + OSUtils::rm(pidPath.c_str()); - return returnValue; + return thr.returnValue; } diff --git a/service/OneService.cpp b/service/OneService.cpp index 4a2102f1..1c2fa05d 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -488,6 +488,8 @@ public: ,_updater((SoftwareUpdater *)0) ,_updateAutoApply(false) ,_primaryPort(port) + ,_v4TcpControlSocket((PhySocket *)0) + ,_v6TcpControlSocket((PhySocket *)0) ,_lastDirectReceiveFromGlobal(0) #ifdef ZT_TCP_FALLBACK_RELAY ,_lastSendToGlobalV4(0) -- cgit v1.2.3 From 683ba79ff0ed4b80c6240fa84d43838027449acd Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Fri, 24 Mar 2017 17:00:14 -0700 Subject: Added ButtFlare stub code --- make-mac.mk | 4 + objects.mk | 3 +- service/ButtFlare.cpp | 194 +++++++++++++++++++++++++++++++++++++++++++++++++ service/ButtFlare.hpp | 94 ++++++++++++++++++++++++ service/OneService.cpp | 12 +++ 5 files changed, 306 insertions(+), 1 deletion(-) create mode 100644 service/ButtFlare.cpp create mode 100644 service/ButtFlare.hpp (limited to 'service/OneService.cpp') diff --git a/make-mac.mk b/make-mac.mk index 8ff1b772..e84f0746 100644 --- a/make-mac.mk +++ b/make-mac.mk @@ -37,6 +37,10 @@ ifeq ($(ZT_ENABLE_CLUSTER),1) DEFS+=-DZT_ENABLE_CLUSTER endif +ifeq ($(ZT_ENABLE_BUTTFLARE),1) + DEFS+=-DZT_ENABLE_BUTTFLARE +endif + # Build miniupnpc and nat-pmp as included libraries -- extra defs are required for these sources DEFS+=-DMACOSX -DZT_USE_MINIUPNPC -DMINIUPNP_STATICLIB -D_DARWIN_C_SOURCE -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -D_BSD_SOURCE -D_DEFAULT_SOURCE -DOS_STRING=\"Darwin/15.0.0\" -DMINIUPNPC_VERSION_STRING=\"2.0\" -DUPNP_VERSION_STRING=\"UPnP/1.1\" -DENABLE_STRNATPMPERR OBJS+=ext/libnatpmp/natpmp.o ext/libnatpmp/getgateway.o ext/miniupnpc/connecthostport.o ext/miniupnpc/igd_desc_parse.o ext/miniupnpc/minisoap.o ext/miniupnpc/minissdpc.o ext/miniupnpc/miniupnpc.o ext/miniupnpc/miniwget.o ext/miniupnpc/minixml.o ext/miniupnpc/portlistingparse.o ext/miniupnpc/receivedata.o ext/miniupnpc/upnpcommands.o ext/miniupnpc/upnpdev.o ext/miniupnpc/upnperrors.o ext/miniupnpc/upnpreplyparse.o osdep/PortMapper.o diff --git a/objects.mk b/objects.mk index 74efc337..47ce65e6 100644 --- a/objects.mk +++ b/objects.mk @@ -31,4 +31,5 @@ OBJS=\ osdep/Http.o \ osdep/OSUtils.o \ service/ClusterGeoIpService.o \ - service/SoftwareUpdater.o + service/SoftwareUpdater.o \ + service/ButtFlare.o diff --git a/service/ButtFlare.cpp b/service/ButtFlare.cpp new file mode 100644 index 00000000..cda92913 --- /dev/null +++ b/service/ButtFlare.cpp @@ -0,0 +1,194 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 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 . + */ + +#include "../osdep/Thread.hpp" +#include "ButtFlare.hpp" + +namespace ZeroTier { + + typedef void PhySocket; + + ButtFlare::ButtFlare( + void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), void *arg) + : + _handler(handler), + _phy(this,false,true), + _enabled(true), + _run(true) + { + // HTTP listen socket + struct sockaddr_in in4; + memset(&in4,0,sizeof(in4)); + in4.sin_family = AF_INET; + in4.sin_addr.s_addr = Utils::hton((uint32_t)(0x7f000001)); // right now we just listen for TCP @127.0.0.1 + in4.sin_port = Utils::hton((uint16_t)http_listen_port); + _tcpHttpListenSocket = _phy.tcpListen((const struct sockaddr *)&in4,this); + // SSL listen socket + in4.sin_port = Utils::hton((uint16_t)ssl_listen_port); + _tcpSSLListenSocket = _phy.tcpListen((const struct sockaddr *)&in4,this); + + /* + struct sockaddr_in6 in6; + memset((void *)&in6,0,sizeof(in6)); + in6.sin6_family = AF_INET6; + in6.sin6_port = in4.sin_port; + if (_allowManagementFrom.size() == 0) + in6.sin6_addr.s6_addr[15] = 1; // IPv6 localhost == ::1 + _v6TcpControlSocket = _phy.tcpListen((const struct sockaddr *)&in6,this); + + // We must bind one of IPv4 or IPv6 -- support either failing to support hosts that + // have only IPv4 or only IPv6 stacks. + if ((_v4TcpControlSocket)||(_v6TcpControlSocket)) { + _ports[0] = _primaryPort; + break; + } else { + if (_v4TcpControlSocket) + _phy.close(_v4TcpControlSocket,false); + if (_v6TcpControlSocket) + _phy.close(_v6TcpControlSocket,false); + _primaryPort = 0; + } + */ + + if(!_tcpHttpListenSocket) + printf("Error binding on port %d for HTTP listen socket\n", http_listen_port); + if(!_tcpSSLListenSocket) + printf("Error binding on port %d for SSL listen socket\n", ssl_listen_port); + _thread = Thread::start(this); + } + + ButtFlare::~ButtFlare() + { + _run = false; + _phy.whack(); + _phy.whack(); // TODO: Rationale? + Thread::join(_thread); + _phy.close(_tcpHttpListenSocket,false); + _phy.close(_tcpSSLListenSocket,false); + } + void ButtFlare::threadMain() + throw() + { + while(_run) { + _phy.poll(50); // in ms + } + } + + void ButtFlare::phyOnTcpData(PhySocket *sock,void **uptr,void *data,unsigned long len) + { + TcpConnection *conn = cmap[sock]; + unsigned char *buf = (unsigned char*)data; + std::string host = ""; + + for(int i=0; idestination_sock) { // no connection yet + + // Determine if HTTP or TLS/SSL + if(buf[0] == 22 && len > 100) // naive and incomplete way of checking for TLS, just for stub code + { + printf("TLS/SSL\n"); + host = "127.0.0.1"; + } + else + { + printf("HTTP\n"); + host = "127.0.0.1"; + } + + if(host != "") + { + bool connected; + struct sockaddr_in in4; + memset(&in4,0,sizeof(in4)); + in4.sin_family = AF_INET; + in4.sin_addr.s_addr = Utils::hton((uint32_t)(0x7f000001)); // right now we just listen for TCP @127.0.0.1 + in4.sin_port = Utils::hton((uint16_t)http_listen_port); + conn->destination_sock = _phy.tcpConnect((const struct sockaddr *)&in4, connected, this); + + if(!connected) { + printf("instant connect has occured\n"); + } + if(!conn->destination_sock) { + printf("there was an error connecting to the remote host\n"); + } + } + } + else // connection already established, just forward the data + { + int n = _phy.streamSend(conn->destination_sock, buf, len); + printf("wrote %d bytes (%p -> %p)\n", conn->origin_sock, conn->destination_sock); + } + } + + void ButtFlare::phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *localAddr,const struct sockaddr *from,void *data,unsigned long len) + { + } + void ButtFlare::phyOnTcpWritable(PhySocket *sock,void **uptr) + { + } + void ButtFlare::phyOnFileDescriptorActivity(PhySocket *sock,void **uptr,bool readable,bool writable) + { + } + + void ButtFlare::phyOnTcpConnect(PhySocket *sock,void **uptr,bool success) + { + printf("phyOnTcpConnect()\n"); + } + + void ButtFlare::phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,const struct sockaddr *from) + { + TcpConnection *conn = new TcpConnection(); + conn->origin_sock = sockN; + cmap[sockN]=conn; // add new connection + } + + void ButtFlare::phyOnUnixClose(PhySocket *sock,void **uptr) + { + } + void ButtFlare::phyOnUnixData(PhySocket *sock,void **uptr,void *data,ssize_t len) + { + } + void ButtFlare::phyOnUnixWritable(PhySocket *sock,void **uptr,bool lwip_invoked) + { + } + + + void ButtFlare::phyOnTcpClose(PhySocket *sock,void **uptr) + { + TcpConnection *conn = cmap[sock]; + if(conn == NULL) { + printf("No existing connection for this sock. Only closing origin sock\n"); + // _phy.close(sock); + return; + } + else + { + // Close both ends + // _phy.close(conn->destination_sock); + // _phy.close(conn->origin_sock); + } + } +} + +//#endif \ No newline at end of file diff --git a/service/ButtFlare.hpp b/service/ButtFlare.hpp new file mode 100644 index 00000000..6e8f0955 --- /dev/null +++ b/service/ButtFlare.hpp @@ -0,0 +1,94 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 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 . + */ + +#ifndef ZT_BUTTFLARE_HPP +#define ZT_BUTTFLARE_HPP + +#include "../node/InetAddress.hpp" +#include "../osdep/Phy.hpp" + +namespace ZeroTier { + + typedef void PhySocket; + class ButtFlare; + + struct TcpConnection + { + enum { + TCP_HTTP_INCOMING, + TCP_HTTP_OUTGOING, + TCP_TUNNEL_OUTGOING + } type; + + InetAddress from; + InetAddress realhost; + + PhySocket *origin_sock; + PhySocket *destination_sock; + }; + + class ButtFlare + { + friend class Phy; + + public: + ButtFlare( + void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), + void *arg); + + ~ButtFlare(); + + // Send incoming data to intended host + void phyOnTcpData(PhySocket *sock,void **uptr,void *data,unsigned long len); + + void phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *localAddr,const struct sockaddr *from,void *data,unsigned long len); + void phyOnTcpWritable(PhySocket *sock,void **uptr); + void phyOnFileDescriptorActivity(PhySocket *sock,void **uptr,bool readable,bool writable); + + // Establish outgoing connection to intended host + void phyOnTcpConnect(PhySocket *sock,void **uptr,bool success); + // Accept connection + void phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,const struct sockaddr *from); + // Handle the closure of a Unix Domain socket + void phyOnUnixClose(PhySocket *sock,void **uptr); + void phyOnUnixData(PhySocket *sock,void **uptr,void *data,ssize_t len); + void phyOnUnixWritable(PhySocket *sock,void **uptr,bool lwip_invoked); + + // Handle the closure of a TCP connection + void phyOnTcpClose(PhySocket *sock,void **uptr); + + void threadMain() + throw(); + + void (*_handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int); + + private: + int http_listen_port = 80; + int ssl_listen_port = 8899; + + volatile bool _enabled; + volatile bool _run; + + Thread _thread; + Phy _phy; + PhySocket *_tcpHttpListenSocket, *_tcpSSLListenSocket; + std::map cmap; + }; +} + +#endif \ No newline at end of file diff --git a/service/OneService.cpp b/service/OneService.cpp index 1c2fa05d..14f637b4 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -67,6 +67,10 @@ #include #endif +#ifdef ZT_ENABLE_BUTTFLARE +#include "ButtFlare.hpp" +#endif + #ifdef ZT_USE_SYSTEM_HTTP_PARSER #include #else @@ -474,6 +478,10 @@ public: unsigned int _clusterMemberId; #endif +#ifdef ZT_ENABLE_BUTTFLARE + ButtFlare *butt; +#endif + // Set to false to force service to stop volatile bool _run; Mutex _run_m; @@ -1914,6 +1922,10 @@ public: try { char friendlyName[128]; Utils::snprintf(friendlyName,sizeof(friendlyName),"ZeroTier One [%.16llx]",nwid); + +#ifdef ZT_ENABLE_BUTTFLARE + butt = new ButtFlare(StapFrameHandler, (void *)this); +#endif n.tap = new EthernetTap( _homePath.c_str(), MAC(nwc->mac), -- cgit v1.2.3 From 592cac58155fecf2e226b32c614e19064214cc1a Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 27 Mar 2017 12:09:37 -0700 Subject: Remove from a few other places. --- make-mac.mk | 4 ---- service/OneService.cpp | 11 ----------- 2 files changed, 15 deletions(-) (limited to 'service/OneService.cpp') diff --git a/make-mac.mk b/make-mac.mk index e84f0746..8ff1b772 100644 --- a/make-mac.mk +++ b/make-mac.mk @@ -37,10 +37,6 @@ ifeq ($(ZT_ENABLE_CLUSTER),1) DEFS+=-DZT_ENABLE_CLUSTER endif -ifeq ($(ZT_ENABLE_BUTTFLARE),1) - DEFS+=-DZT_ENABLE_BUTTFLARE -endif - # Build miniupnpc and nat-pmp as included libraries -- extra defs are required for these sources DEFS+=-DMACOSX -DZT_USE_MINIUPNPC -DMINIUPNP_STATICLIB -D_DARWIN_C_SOURCE -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -D_BSD_SOURCE -D_DEFAULT_SOURCE -DOS_STRING=\"Darwin/15.0.0\" -DMINIUPNPC_VERSION_STRING=\"2.0\" -DUPNP_VERSION_STRING=\"UPnP/1.1\" -DENABLE_STRNATPMPERR OBJS+=ext/libnatpmp/natpmp.o ext/libnatpmp/getgateway.o ext/miniupnpc/connecthostport.o ext/miniupnpc/igd_desc_parse.o ext/miniupnpc/minisoap.o ext/miniupnpc/minissdpc.o ext/miniupnpc/miniupnpc.o ext/miniupnpc/miniwget.o ext/miniupnpc/minixml.o ext/miniupnpc/portlistingparse.o ext/miniupnpc/receivedata.o ext/miniupnpc/upnpcommands.o ext/miniupnpc/upnpdev.o ext/miniupnpc/upnperrors.o ext/miniupnpc/upnpreplyparse.o osdep/PortMapper.o diff --git a/service/OneService.cpp b/service/OneService.cpp index 14f637b4..22eefbb9 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -67,10 +67,6 @@ #include #endif -#ifdef ZT_ENABLE_BUTTFLARE -#include "ButtFlare.hpp" -#endif - #ifdef ZT_USE_SYSTEM_HTTP_PARSER #include #else @@ -478,10 +474,6 @@ public: unsigned int _clusterMemberId; #endif -#ifdef ZT_ENABLE_BUTTFLARE - ButtFlare *butt; -#endif - // Set to false to force service to stop volatile bool _run; Mutex _run_m; @@ -1923,9 +1915,6 @@ public: char friendlyName[128]; Utils::snprintf(friendlyName,sizeof(friendlyName),"ZeroTier One [%.16llx]",nwid); -#ifdef ZT_ENABLE_BUTTFLARE - butt = new ButtFlare(StapFrameHandler, (void *)this); -#endif n.tap = new EthernetTap( _homePath.c_str(), MAC(nwc->mac), -- cgit v1.2.3 From e4896b257fde05a216500804d9bcef3b84b0980e Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 27 Mar 2017 17:03:17 -0700 Subject: Add thread PTR that gets passed through the entire ZT core call stack and then passed to handler functions resulting from a call. --- controller/EmbeddedNetworkController.cpp | 2 +- include/ZeroTierOne.h | 51 ++++-- node/Capability.cpp | 6 +- node/Capability.hpp | 2 +- node/CertificateOfMembership.cpp | 6 +- node/CertificateOfMembership.hpp | 3 +- node/CertificateOfOwnership.cpp | 6 +- node/CertificateOfOwnership.hpp | 3 +- node/IncomingPacket.cpp | 294 +++++++++++++++---------------- node/IncomingPacket.hpp | 43 ++--- node/Membership.cpp | 24 +-- node/Membership.hpp | 13 +- node/Multicaster.cpp | 23 +-- node/Multicaster.hpp | 13 +- node/Network.cpp | 112 ++++++------ node/Network.hpp | 59 ++++--- node/Node.cpp | 136 +++++++------- node/Node.hpp | 42 +++-- node/OutboundMulticast.cpp | 6 +- node/OutboundMulticast.hpp | 13 +- node/Path.cpp | 4 +- node/Path.hpp | 3 +- node/Peer.cpp | 37 ++-- node/Peer.hpp | 22 ++- node/Revocation.cpp | 6 +- node/Revocation.hpp | 3 +- node/SelfAwareness.cpp | 10 +- node/SelfAwareness.hpp | 2 +- node/Switch.cpp | 97 +++++----- node/Switch.hpp | 22 ++- node/Tag.cpp | 6 +- node/Tag.hpp | 3 +- node/Topology.cpp | 54 +++--- node/Topology.hpp | 26 +-- osdep/BSDEthernetTap.cpp | 5 +- osdep/BSDEthernetTap.hpp | 4 +- osdep/LinuxEthernetTap.cpp | 4 +- osdep/LinuxEthernetTap.hpp | 4 +- osdep/OSXEthernetTap.cpp | 4 +- osdep/OSXEthernetTap.hpp | 4 +- osdep/WindowsEthernetTap.cpp | 5 +- osdep/WindowsEthernetTap.hpp | 4 +- service/OneService.cpp | 58 +++--- service/SoftwareUpdater.cpp | 12 +- 44 files changed, 673 insertions(+), 583 deletions(-) (limited to 'service/OneService.cpp') diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index 51500ed7..ce56e906 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -790,7 +790,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( test->timestamp = OSUtils::now(); if (_node) { - _node->circuitTestBegin(test,&(EmbeddedNetworkController::_circuitTestCallback)); + _node->circuitTestBegin((void *)0,test,&(EmbeddedNetworkController::_circuitTestCallback)); } else { _tests.pop_back(); return 500; diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 98413a21..747e1855 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -1408,6 +1408,7 @@ typedef void ZT_Node; typedef int (*ZT_VirtualNetworkConfigFunction)( ZT_Node *, /* Node */ void *, /* User ptr */ + void *, /* Thread ptr */ uint64_t, /* Network ID */ void **, /* Modifiable network user PTR */ enum ZT_VirtualNetworkConfigOperation, /* Config operation */ @@ -1423,6 +1424,7 @@ typedef int (*ZT_VirtualNetworkConfigFunction)( typedef void (*ZT_VirtualNetworkFrameFunction)( ZT_Node *, /* Node */ void *, /* User ptr */ + void *, /* Thread ptr */ uint64_t, /* Network ID */ void **, /* Modifiable network user PTR */ uint64_t, /* Source MAC */ @@ -1442,10 +1444,11 @@ typedef void (*ZT_VirtualNetworkFrameFunction)( * in the definition of ZT_Event. */ typedef void (*ZT_EventCallback)( - ZT_Node *, - void *, - enum ZT_Event, - const void *); + ZT_Node *, /* Node */ + void *, /* User ptr */ + void *, /* Thread ptr */ + enum ZT_Event, /* Event type */ + const void *); /* Event payload (if applicable) */ /** * Function to get an object from the data store @@ -1468,8 +1471,9 @@ typedef void (*ZT_EventCallback)( * object. */ typedef long (*ZT_DataStoreGetFunction)( - ZT_Node *, - void *, + ZT_Node *, /* Node */ + void *, /* User ptr */ + void *, /* Thread ptr */ const char *, void *, unsigned long, @@ -1495,6 +1499,7 @@ typedef long (*ZT_DataStoreGetFunction)( typedef int (*ZT_DataStorePutFunction)( ZT_Node *, void *, + void *, /* Thread ptr */ const char *, const void *, unsigned long, @@ -1529,6 +1534,7 @@ typedef int (*ZT_DataStorePutFunction)( typedef int (*ZT_WirePacketSendFunction)( ZT_Node *, /* Node */ void *, /* User ptr */ + void *, /* Thread ptr */ const struct sockaddr_storage *, /* Local address */ const struct sockaddr_storage *, /* Remote address */ const void *, /* Packet data */ @@ -1562,6 +1568,7 @@ typedef int (*ZT_WirePacketSendFunction)( typedef int (*ZT_PathCheckFunction)( ZT_Node *, /* Node */ void *, /* User ptr */ + void *, /* Thread ptr */ uint64_t, /* ZeroTier address */ const struct sockaddr_storage *, /* Local address */ const struct sockaddr_storage *); /* Remote address */ @@ -1584,6 +1591,7 @@ typedef int (*ZT_PathCheckFunction)( typedef int (*ZT_PathLookupFunction)( ZT_Node *, /* Node */ void *, /* User ptr */ + void *, /* Thread ptr */ uint64_t, /* ZeroTier address (40 bits) */ int, /* Desired ss_family or -1 for any */ struct sockaddr_storage *); /* Result buffer */ @@ -1654,11 +1662,12 @@ struct ZT_Node_Callbacks * * @param node Result: pointer is set to new node instance on success * @param uptr User pointer to pass to functions/callbacks + * @param tptr Thread pointer to pass to functions/callbacks resulting from this call * @param callbacks Callback function configuration * @param now Current clock in milliseconds * @return OK (0) or error code if a fatal error condition has occurred */ -enum ZT_ResultCode ZT_Node_new(ZT_Node **node,void *uptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now); +enum ZT_ResultCode ZT_Node_new(ZT_Node **node,void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now); /** * Delete a node and free all resources it consumes @@ -1674,6 +1683,7 @@ void ZT_Node_delete(ZT_Node *node); * Process a packet received from the physical wire * * @param node Node instance + * @param tptr Thread pointer to pass to functions/callbacks resulting from this call * @param now Current clock in milliseconds * @param localAddress Local address, or point to ZT_SOCKADDR_NULL if unspecified * @param remoteAddress Origin of packet @@ -1684,6 +1694,7 @@ void ZT_Node_delete(ZT_Node *node); */ enum ZT_ResultCode ZT_Node_processWirePacket( ZT_Node *node, + void *tptr, uint64_t now, const struct sockaddr_storage *localAddress, const struct sockaddr_storage *remoteAddress, @@ -1695,6 +1706,7 @@ enum ZT_ResultCode ZT_Node_processWirePacket( * Process a frame from a virtual network port (tap) * * @param node Node instance + * @param tptr Thread pointer to pass to functions/callbacks resulting from this call * @param now Current clock in milliseconds * @param nwid ZeroTier 64-bit virtual network ID * @param sourceMac Source MAC address (least significant 48 bits) @@ -1708,6 +1720,7 @@ enum ZT_ResultCode ZT_Node_processWirePacket( */ enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame( ZT_Node *node, + void *tptr, uint64_t now, uint64_t nwid, uint64_t sourceMac, @@ -1722,11 +1735,12 @@ enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame( * Perform periodic background operations * * @param node Node instance + * @param tptr Thread pointer to pass to functions/callbacks resulting from this call * @param now Current clock in milliseconds * @param nextBackgroundTaskDeadline Value/result: set to deadline for next call to processBackgroundTasks() * @return OK (0) or error code if a fatal error condition has occurred */ -enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline); +enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,void *tptr,uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline); /** * Join a network @@ -1742,7 +1756,7 @@ enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,uint64_t now,vol * @param uptr An arbitrary pointer to associate with this network (default: NULL) * @return OK (0) or error code if a fatal error condition has occurred */ -enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,void *uptr); +enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,void *uptr,void *tptr); /** * Leave a network @@ -1759,7 +1773,7 @@ enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,void *uptr); * @param uptr Target pointer is set to uptr (if not NULL) * @return OK (0) or error code if a fatal error condition has occurred */ -enum ZT_ResultCode ZT_Node_leave(ZT_Node *node,uint64_t nwid,void **uptr); +enum ZT_ResultCode ZT_Node_leave(ZT_Node *node,uint64_t nwid,void **uptr,void *tptr); /** * Subscribe to an Ethernet multicast group @@ -1781,12 +1795,13 @@ enum ZT_ResultCode ZT_Node_leave(ZT_Node *node,uint64_t nwid,void **uptr); * This does not generate an update call to networkConfigCallback(). * * @param node Node instance + * @param tptr Thread pointer to pass to functions/callbacks resulting from this call * @param nwid 64-bit network ID * @param multicastGroup Ethernet multicast or broadcast MAC (least significant 48 bits) * @param multicastAdi Multicast ADI (least significant 32 bits only, use 0 if not needed) * @return OK (0) or error code if a fatal error condition has occurred */ -enum ZT_ResultCode ZT_Node_multicastSubscribe(ZT_Node *node,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi); +enum ZT_ResultCode ZT_Node_multicastSubscribe(ZT_Node *node,void *tptr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi); /** * Unsubscribe from an Ethernet multicast group (or all groups) @@ -1811,21 +1826,24 @@ enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node,uint64_t nwid,uint * across invocations if the contents of moon.d are scanned and orbit is * called for each on startup. * + * @param node Node instance + * @param tptr Thread pointer to pass to functions/callbacks resulting from this call * @param moonWorldId Moon's world ID * @param moonSeed If non-zero, the ZeroTier address of any member of the moon to query for moon definition * @param len Length of moonWorld in bytes * @return Error if moon was invalid or failed to be added */ -enum ZT_ResultCode ZT_Node_orbit(ZT_Node *node,uint64_t moonWorldId,uint64_t moonSeed); +enum ZT_ResultCode ZT_Node_orbit(ZT_Node *node,void *tptr,uint64_t moonWorldId,uint64_t moonSeed); /** * Remove a moon (does nothing if not present) * * @param node Node instance + * @param tptr Thread pointer to pass to functions/callbacks resulting from this call * @param moonWorldId World ID of moon to remove * @return Error if anything bad happened */ -enum ZT_ResultCode ZT_Node_deorbit(ZT_Node *node,uint64_t moonWorldId); +enum ZT_ResultCode ZT_Node_deorbit(ZT_Node *node,void *tptr,uint64_t moonWorldId); /** * Get this node's 40-bit ZeroTier address @@ -1919,13 +1937,15 @@ void ZT_Node_clearLocalInterfaceAddresses(ZT_Node *node); * There is no delivery guarantee here. Failure can occur if the message is * too large or if dest is not a valid ZeroTier address. * + * @param node Node instance + * @param tptr Thread pointer to pass to functions/callbacks resulting from this call * @param dest Destination ZeroTier address * @param typeId VERB_USER_MESSAGE type ID * @param data Payload data to attach to user message * @param len Length of data in bytes * @return Boolean: non-zero on success, zero on failure */ -int ZT_Node_sendUserMessage(ZT_Node *node,uint64_t dest,uint64_t typeId,const void *data,unsigned int len); +int ZT_Node_sendUserMessage(ZT_Node *node,void *tptr,uint64_t dest,uint64_t typeId,const void *data,unsigned int len); /** * Set a network configuration master instance for this node @@ -1957,11 +1977,12 @@ void ZT_Node_setNetconfMaster(ZT_Node *node,void *networkConfigMasterInstance); * for results forever. * * @param node Node instance + * @param tptr Thread pointer to pass to functions/callbacks resulting from this call * @param test Test configuration * @param reportCallback Function to call each time a report is received * @return OK or error if, for example, test is too big for a packet or support isn't compiled in */ -enum ZT_ResultCode ZT_Node_circuitTestBegin(ZT_Node *node,ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *, ZT_CircuitTest *,const ZT_CircuitTestReport *)); +enum ZT_ResultCode ZT_Node_circuitTestBegin(ZT_Node *node,void *tptr,ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *, ZT_CircuitTest *,const ZT_CircuitTestReport *)); /** * Stop listening for results to a given circuit test diff --git a/node/Capability.cpp b/node/Capability.cpp index 0a736ca8..c178e566 100644 --- a/node/Capability.cpp +++ b/node/Capability.cpp @@ -25,7 +25,7 @@ namespace ZeroTier { -int Capability::verify(const RuntimeEnvironment *RR) const +int Capability::verify(const RuntimeEnvironment *RR,void *tPtr) const { try { // There must be at least one entry, and sanity check for bad chain max length @@ -46,12 +46,12 @@ int Capability::verify(const RuntimeEnvironment *RR) const return -1; // otherwise if we have another entry it must be from the previous holder in the chain } - const Identity id(RR->topology->getIdentity(_custody[c].from)); + const Identity id(RR->topology->getIdentity(tPtr,_custody[c].from)); if (id) { if (!id.verify(tmp.data(),tmp.size(),_custody[c].signature)) return -1; } else { - RR->sw->requestWhois(_custody[c].from); + RR->sw->requestWhois(tPtr,_custody[c].from); return 1; } } diff --git a/node/Capability.hpp b/node/Capability.hpp index d070f2ad..5ef6c994 100644 --- a/node/Capability.hpp +++ b/node/Capability.hpp @@ -161,7 +161,7 @@ public: * @param RR Runtime environment to provide for peer lookup, etc. * @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or chain */ - int verify(const RuntimeEnvironment *RR) const; + int verify(const RuntimeEnvironment *RR,void *tPtr) const; template static inline void serializeRules(Buffer &b,const ZT_VirtualNetworkRule *rules,unsigned int ruleCount) diff --git a/node/CertificateOfMembership.cpp b/node/CertificateOfMembership.cpp index 43efcd20..9bf70216 100644 --- a/node/CertificateOfMembership.cpp +++ b/node/CertificateOfMembership.cpp @@ -207,14 +207,14 @@ bool CertificateOfMembership::sign(const Identity &with) } } -int CertificateOfMembership::verify(const RuntimeEnvironment *RR) const +int CertificateOfMembership::verify(const RuntimeEnvironment *RR,void *tPtr) const { if ((!_signedBy)||(_signedBy != Network::controllerFor(networkId()))||(_qualifierCount > ZT_NETWORK_COM_MAX_QUALIFIERS)) return -1; - const Identity id(RR->topology->getIdentity(_signedBy)); + const Identity id(RR->topology->getIdentity(tPtr,_signedBy)); if (!id) { - RR->sw->requestWhois(_signedBy); + RR->sw->requestWhois(tPtr,_signedBy); return 1; } diff --git a/node/CertificateOfMembership.hpp b/node/CertificateOfMembership.hpp index 2d7c2cb3..ae976b50 100644 --- a/node/CertificateOfMembership.hpp +++ b/node/CertificateOfMembership.hpp @@ -250,9 +250,10 @@ public: * Verify this COM and its signature * * @param RR Runtime environment for looking up peers + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or credential */ - int verify(const RuntimeEnvironment *RR) const; + int verify(const RuntimeEnvironment *RR,void *tPtr) const; /** * @return True if signed diff --git a/node/CertificateOfOwnership.cpp b/node/CertificateOfOwnership.cpp index 6fc59ad1..2bd181e0 100644 --- a/node/CertificateOfOwnership.cpp +++ b/node/CertificateOfOwnership.cpp @@ -25,13 +25,13 @@ namespace ZeroTier { -int CertificateOfOwnership::verify(const RuntimeEnvironment *RR) const +int CertificateOfOwnership::verify(const RuntimeEnvironment *RR,void *tPtr) const { if ((!_signedBy)||(_signedBy != Network::controllerFor(_networkId))) return -1; - const Identity id(RR->topology->getIdentity(_signedBy)); + const Identity id(RR->topology->getIdentity(tPtr,_signedBy)); if (!id) { - RR->sw->requestWhois(_signedBy); + RR->sw->requestWhois(tPtr,_signedBy); return 1; } try { diff --git a/node/CertificateOfOwnership.hpp b/node/CertificateOfOwnership.hpp index 57fd8259..8c47582d 100644 --- a/node/CertificateOfOwnership.hpp +++ b/node/CertificateOfOwnership.hpp @@ -137,9 +137,10 @@ public: /** * @param RR Runtime environment to allow identity lookup for signedBy + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature */ - int verify(const RuntimeEnvironment *RR) const; + int verify(const RuntimeEnvironment *RR,void *tPtr) const; template inline void serialize(Buffer &b,const bool forSign = false) const diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index e2275a04..52794fd7 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -44,7 +44,7 @@ namespace ZeroTier { -bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR) +bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr) { const Address sourceAddress(source()); @@ -65,10 +65,10 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR) } } else if ((c == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE)&&(verb() == Packet::VERB_HELLO)) { // Only HELLO is allowed in the clear, but will still have a MAC - return _doHELLO(RR,false); + return _doHELLO(RR,tPtr,false); } - const SharedPtr peer(RR->topology->getPeer(sourceAddress)); + const SharedPtr peer(RR->topology->getPeer(tPtr,sourceAddress)); if (peer) { if (!trusted) { if (!dearmor(peer->key())) { @@ -89,30 +89,30 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR) switch(v) { //case Packet::VERB_NOP: default: // ignore unknown verbs, but if they pass auth check they are "received" - peer->received(_path,hops(),packetId(),v,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),packetId(),v,0,Packet::VERB_NOP,false); return true; - case Packet::VERB_HELLO: return _doHELLO(RR,true); - case Packet::VERB_ERROR: return _doERROR(RR,peer); - case Packet::VERB_OK: return _doOK(RR,peer); - case Packet::VERB_WHOIS: return _doWHOIS(RR,peer); - case Packet::VERB_RENDEZVOUS: return _doRENDEZVOUS(RR,peer); - case Packet::VERB_FRAME: return _doFRAME(RR,peer); - case Packet::VERB_EXT_FRAME: return _doEXT_FRAME(RR,peer); - case Packet::VERB_ECHO: return _doECHO(RR,peer); - case Packet::VERB_MULTICAST_LIKE: return _doMULTICAST_LIKE(RR,peer); - case Packet::VERB_NETWORK_CREDENTIALS: return _doNETWORK_CREDENTIALS(RR,peer); - case Packet::VERB_NETWORK_CONFIG_REQUEST: return _doNETWORK_CONFIG_REQUEST(RR,peer); - case Packet::VERB_NETWORK_CONFIG: return _doNETWORK_CONFIG(RR,peer); - case Packet::VERB_MULTICAST_GATHER: return _doMULTICAST_GATHER(RR,peer); - case Packet::VERB_MULTICAST_FRAME: return _doMULTICAST_FRAME(RR,peer); - case Packet::VERB_PUSH_DIRECT_PATHS: return _doPUSH_DIRECT_PATHS(RR,peer); - case Packet::VERB_CIRCUIT_TEST: return _doCIRCUIT_TEST(RR,peer); - case Packet::VERB_CIRCUIT_TEST_REPORT: return _doCIRCUIT_TEST_REPORT(RR,peer); - case Packet::VERB_USER_MESSAGE: return _doUSER_MESSAGE(RR,peer); + case Packet::VERB_HELLO: return _doHELLO(RR,tPtr,true); + case Packet::VERB_ERROR: return _doERROR(RR,tPtr,peer); + case Packet::VERB_OK: return _doOK(RR,tPtr,peer); + case Packet::VERB_WHOIS: return _doWHOIS(RR,tPtr,peer); + case Packet::VERB_RENDEZVOUS: return _doRENDEZVOUS(RR,tPtr,peer); + case Packet::VERB_FRAME: return _doFRAME(RR,tPtr,peer); + case Packet::VERB_EXT_FRAME: return _doEXT_FRAME(RR,tPtr,peer); + case Packet::VERB_ECHO: return _doECHO(RR,tPtr,peer); + case Packet::VERB_MULTICAST_LIKE: return _doMULTICAST_LIKE(RR,tPtr,peer); + case Packet::VERB_NETWORK_CREDENTIALS: return _doNETWORK_CREDENTIALS(RR,tPtr,peer); + case Packet::VERB_NETWORK_CONFIG_REQUEST: return _doNETWORK_CONFIG_REQUEST(RR,tPtr,peer); + case Packet::VERB_NETWORK_CONFIG: return _doNETWORK_CONFIG(RR,tPtr,peer); + case Packet::VERB_MULTICAST_GATHER: return _doMULTICAST_GATHER(RR,tPtr,peer); + case Packet::VERB_MULTICAST_FRAME: return _doMULTICAST_FRAME(RR,tPtr,peer); + case Packet::VERB_PUSH_DIRECT_PATHS: return _doPUSH_DIRECT_PATHS(RR,tPtr,peer); + case Packet::VERB_CIRCUIT_TEST: return _doCIRCUIT_TEST(RR,tPtr,peer); + case Packet::VERB_CIRCUIT_TEST_REPORT: return _doCIRCUIT_TEST_REPORT(RR,tPtr,peer); + case Packet::VERB_USER_MESSAGE: return _doUSER_MESSAGE(RR,tPtr,peer); } } else { - RR->sw->requestWhois(sourceAddress); + RR->sw->requestWhois(tPtr,sourceAddress); return false; } } catch ( ... ) { @@ -123,7 +123,7 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR) } } -bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr &peer) +bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer) { try { const Packet::Verb inReVerb = (Packet::Verb)(*this)[ZT_PROTO_VERB_ERROR_IDX_IN_RE_VERB]; @@ -163,7 +163,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr case Packet::ERROR_IDENTITY_COLLISION: // FIXME: for federation this will need a payload with a signature or something. if (RR->topology->isUpstream(peer->identity())) - RR->node->postEvent(ZT_EVENT_FATAL_ERROR_IDENTITY_COLLISION); + RR->node->postEvent(tPtr,ZT_EVENT_FATAL_ERROR_IDENTITY_COLLISION); break; case Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE: { @@ -171,7 +171,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr const SharedPtr network(RR->node->network(at(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD))); const uint64_t now = RR->node->now(); if ( (network) && (network->config().com) && (peer->rateGateIncomingComRequest(now)) ) - network->pushCredentialsNow(peer->address(),now); + network->pushCredentialsNow(tPtr,peer->address(),now); } break; case Packet::ERROR_NETWORK_ACCESS_DENIED_: { @@ -185,7 +185,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr // Members of networks can use this error to indicate that they no longer // want to receive multicasts on a given channel. const SharedPtr network(RR->node->network(at(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD))); - if ((network)&&(network->gate(peer))) { + if ((network)&&(network->gate(tPtr,peer))) { const MulticastGroup mg(MAC(field(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD + 8,6),6),at(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD + 14)); TRACE("%.16llx: peer %s unsubscrubed from multicast group %s",network->id(),peer->address().toString().c_str(),mg.toString().c_str()); RR->mc->remove(network->id(),mg,peer->address()); @@ -195,14 +195,14 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr default: break; } - peer->received(_path,hops(),packetId(),Packet::VERB_ERROR,inRePacketId,inReVerb,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_ERROR,inRePacketId,inReVerb,false); } catch ( ... ) { TRACE("dropped ERROR from %s(%s): unexpected exception",peer->address().toString().c_str(),_path->address().toString().c_str()); } return true; } -bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAuthenticated) +bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool alreadyAuthenticated) { try { const uint64_t now = RR->node->now(); @@ -226,7 +226,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut return true; } - SharedPtr peer(RR->topology->getPeer(id.address())); + SharedPtr peer(RR->topology->getPeer(tPtr,id.address())); if (peer) { // We already have an identity with this address -- check for collisions if (!alreadyAuthenticated) { @@ -246,7 +246,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut outp.append((uint64_t)pid); outp.append((uint8_t)Packet::ERROR_IDENTITY_COLLISION); outp.armor(key,true,_path->nextOutgoingCounter()); - _path->send(RR,outp.data(),outp.size(),RR->node->now()); + _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); } else { TRACE("rejected HELLO from %s(%s): packet failed authentication",id.address().toString().c_str(),_path->address().toString().c_str()); } @@ -292,7 +292,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut return true; } - peer = RR->topology->addPeer(newPeer); + peer = RR->topology->addPeer(tPtr,newPeer); // Continue at // VALID } @@ -304,7 +304,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut if (ptr < size()) { ptr += externalSurfaceAddress.deserialize(*this,ptr); if ((externalSurfaceAddress)&&(hops() == 0)) - RR->sa->iam(id.address(),_path->localAddress(),_path->address(),externalSurfaceAddress,RR->topology->isUpstream(id),now); + RR->sa->iam(tPtr,id.address(),_path->localAddress(),_path->address(),externalSurfaceAddress,RR->topology->isUpstream(id),now); } // Get primary planet world ID and world timestamp if present @@ -408,17 +408,17 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut outp.setAt(corSizeAt,(uint16_t)(outp.size() - (corSizeAt + 2))); outp.armor(peer->key(),true,_path->nextOutgoingCounter()); - _path->send(RR,outp.data(),outp.size(),now); + _path->send(RR,tPtr,outp.data(),outp.size(),now); peer->setRemoteVersion(protoVersion,vMajor,vMinor,vRevision); // important for this to go first so received() knows the version - peer->received(_path,hops(),pid,Packet::VERB_HELLO,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),pid,Packet::VERB_HELLO,0,Packet::VERB_NOP,false); } catch ( ... ) { TRACE("dropped HELLO from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str()); } return true; } -bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr &peer) +bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer) { try { const Packet::Verb inReVerb = (Packet::Verb)(*this)[ZT_PROTO_VERB_OK_IDX_IN_RE_VERB]; @@ -463,7 +463,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr &p while (ptr < endOfWorlds) { World w; ptr += w.deserialize(*this,ptr); - RR->topology->addWorld(w,false); + RR->topology->addWorld(tPtr,w,false); } } else { ptr += worldsLen; @@ -490,20 +490,20 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr &p peer->setRemoteVersion(vProto,vMajor,vMinor,vRevision); if ((externalSurfaceAddress)&&(hops() == 0)) - RR->sa->iam(peer->address(),_path->localAddress(),_path->address(),externalSurfaceAddress,RR->topology->isUpstream(peer->identity()),RR->node->now()); + RR->sa->iam(tPtr,peer->address(),_path->localAddress(),_path->address(),externalSurfaceAddress,RR->topology->isUpstream(peer->identity()),RR->node->now()); } break; case Packet::VERB_WHOIS: if (RR->topology->isUpstream(peer->identity())) { const Identity id(*this,ZT_PROTO_VERB_WHOIS__OK__IDX_IDENTITY); - RR->sw->doAnythingWaitingForPeer(RR->topology->addPeer(SharedPtr(new Peer(RR,RR->identity,id)))); + RR->sw->doAnythingWaitingForPeer(tPtr,RR->topology->addPeer(tPtr,SharedPtr(new Peer(RR,RR->identity,id)))); } break; case Packet::VERB_NETWORK_CONFIG_REQUEST: { const SharedPtr network(RR->node->network(at(ZT_PROTO_VERB_OK_IDX_PAYLOAD))); if (network) - network->handleConfigChunk(packetId(),source(),*this,ZT_PROTO_VERB_OK_IDX_PAYLOAD); + network->handleConfigChunk(tPtr,packetId(),source(),*this,ZT_PROTO_VERB_OK_IDX_PAYLOAD); } break; case Packet::VERB_MULTICAST_GATHER: { @@ -513,7 +513,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr &p const MulticastGroup mg(MAC(field(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_MAC,6),6),at(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_ADI)); //TRACE("%s(%s): OK(MULTICAST_GATHER) %.16llx/%s length %u",source().toString().c_str(),_path->address().toString().c_str(),nwid,mg.toString().c_str(),size()); const unsigned int count = at(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS + 4); - RR->mc->addMultiple(RR->node->now(),nwid,mg,field(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS + 6,count * 5),count,at(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS)); + RR->mc->addMultiple(tPtr,RR->node->now(),nwid,mg,field(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS + 6,count * 5),count,at(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS)); } } break; @@ -532,7 +532,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr &p CertificateOfMembership com; offset += com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS); if (com) - network->addCredential(com); + network->addCredential(tPtr,com); } if ((flags & 0x02) != 0) { @@ -540,7 +540,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr &p offset += ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS; unsigned int totalKnown = at(offset); offset += 4; unsigned int count = at(offset); offset += 2; - RR->mc->addMultiple(RR->node->now(),nwid,mg,field(offset,count * 5),count,totalKnown); + RR->mc->addMultiple(tPtr,RR->node->now(),nwid,mg,field(offset,count * 5),count,totalKnown); } } } break; @@ -548,14 +548,14 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr &p default: break; } - peer->received(_path,hops(),packetId(),Packet::VERB_OK,inRePacketId,inReVerb,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_OK,inRePacketId,inReVerb,false); } catch ( ... ) { TRACE("dropped OK from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str()); } return true; } -bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,const SharedPtr &peer) +bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer) { try { if ((!RR->topology->amRoot())&&(!peer->rateGateInboundWhoisRequest(RR->node->now()))) { @@ -573,13 +573,13 @@ bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,const SharedPtr const Address addr(field(ptr,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); ptr += ZT_ADDRESS_LENGTH; - const Identity id(RR->topology->getIdentity(addr)); + const Identity id(RR->topology->getIdentity(tPtr,addr)); if (id) { id.serialize(outp,false); ++count; } else { // Request unknown WHOIS from upstream from us (if we have one) - RR->sw->requestWhois(addr); + RR->sw->requestWhois(tPtr,addr); #ifdef ZT_ENABLE_CLUSTER // Distribute WHOIS queries across a cluster if we do not know the ID. // This may result in duplicate OKs to the querying peer, which is fine. @@ -591,32 +591,32 @@ bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,const SharedPtr if (count > 0) { outp.armor(peer->key(),true,_path->nextOutgoingCounter()); - _path->send(RR,outp.data(),outp.size(),RR->node->now()); + _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); } - peer->received(_path,hops(),packetId(),Packet::VERB_WHOIS,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_WHOIS,0,Packet::VERB_NOP,false); } catch ( ... ) { TRACE("dropped WHOIS from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str()); } return true; } -bool IncomingPacket::_doRENDEZVOUS(const RuntimeEnvironment *RR,const SharedPtr &peer) +bool IncomingPacket::_doRENDEZVOUS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer) { try { if (!RR->topology->isUpstream(peer->identity())) { TRACE("RENDEZVOUS from %s ignored since source is not upstream",peer->address().toString().c_str()); } else { const Address with(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ZTADDRESS,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); - const SharedPtr rendezvousWith(RR->topology->getPeer(with)); + const SharedPtr rendezvousWith(RR->topology->getPeer(tPtr,with)); if (rendezvousWith) { const unsigned int port = at(ZT_PROTO_VERB_RENDEZVOUS_IDX_PORT); const unsigned int addrlen = (*this)[ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRLEN]; if ((port > 0)&&((addrlen == 4)||(addrlen == 16))) { const InetAddress atAddr(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS,addrlen),addrlen,port); - if (RR->node->shouldUsePathForZeroTierTraffic(with,_path->localAddress(),atAddr)) { - RR->node->putPacket(_path->localAddress(),atAddr,"ABRE",4,2); // send low-TTL junk packet to 'open' local NAT(s) and stateful firewalls - rendezvousWith->attemptToContactAt(_path->localAddress(),atAddr,RR->node->now(),false,0); + if (RR->node->shouldUsePathForZeroTierTraffic(tPtr,with,_path->localAddress(),atAddr)) { + RR->node->putPacket(tPtr,_path->localAddress(),atAddr,"ABRE",4,2); // send low-TTL junk packet to 'open' local NAT(s) and stateful firewalls + rendezvousWith->attemptToContactAt(tPtr,_path->localAddress(),atAddr,RR->node->now(),false,0); TRACE("RENDEZVOUS from %s says %s might be at %s, sent verification attempt",peer->address().toString().c_str(),with.toString().c_str(),atAddr.toString().c_str()); } else { TRACE("RENDEZVOUS from %s says %s might be at %s, ignoring since path is not suitable",peer->address().toString().c_str(),with.toString().c_str(),atAddr.toString().c_str()); @@ -628,46 +628,46 @@ bool IncomingPacket::_doRENDEZVOUS(const RuntimeEnvironment *RR,const SharedPtr< TRACE("ignored RENDEZVOUS from %s(%s) to meet unknown peer %s",peer->address().toString().c_str(),_path->address().toString().c_str(),with.toString().c_str()); } } - peer->received(_path,hops(),packetId(),Packet::VERB_RENDEZVOUS,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_RENDEZVOUS,0,Packet::VERB_NOP,false); } catch ( ... ) { TRACE("dropped RENDEZVOUS from %s(%s): unexpected exception",peer->address().toString().c_str(),_path->address().toString().c_str()); } return true; } -bool IncomingPacket::_doFRAME(const RuntimeEnvironment *RR,const SharedPtr &peer) +bool IncomingPacket::_doFRAME(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer) { try { const uint64_t nwid = at(ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID); const SharedPtr network(RR->node->network(nwid)); bool trustEstablished = false; if (network) { - if (network->gate(peer)) { + if (network->gate(tPtr,peer)) { trustEstablished = true; if (size() > ZT_PROTO_VERB_FRAME_IDX_PAYLOAD) { const unsigned int etherType = at(ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE); const MAC sourceMac(peer->address(),nwid); const unsigned int frameLen = size() - ZT_PROTO_VERB_FRAME_IDX_PAYLOAD; const uint8_t *const frameData = reinterpret_cast(data()) + ZT_PROTO_VERB_FRAME_IDX_PAYLOAD; - if (network->filterIncomingPacket(peer,RR->identity.address(),sourceMac,network->mac(),frameData,frameLen,etherType,0) > 0) - RR->node->putFrame(nwid,network->userPtr(),sourceMac,network->mac(),etherType,0,(const void *)frameData,frameLen); + if (network->filterIncomingPacket(tPtr,peer,RR->identity.address(),sourceMac,network->mac(),frameData,frameLen,etherType,0) > 0) + RR->node->putFrame(tPtr,nwid,network->userPtr(),sourceMac,network->mac(),etherType,0,(const void *)frameData,frameLen); } } else { TRACE("dropped FRAME from %s(%s): not a member of private network %.16llx",peer->address().toString().c_str(),_path->address().toString().c_str(),(unsigned long long)network->id()); - _sendErrorNeedCredentials(RR,peer,nwid); + _sendErrorNeedCredentials(RR,tPtr,peer,nwid); } } else { TRACE("dropped FRAME from %s(%s): we are not a member of network %.16llx",source().toString().c_str(),_path->address().toString().c_str(),at(ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID)); - _sendErrorNeedCredentials(RR,peer,nwid); + _sendErrorNeedCredentials(RR,tPtr,peer,nwid); } - peer->received(_path,hops(),packetId(),Packet::VERB_FRAME,0,Packet::VERB_NOP,trustEstablished); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_FRAME,0,Packet::VERB_NOP,trustEstablished); } catch ( ... ) { TRACE("dropped FRAME from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str()); } return true; } -bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr &peer) +bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer) { try { const uint64_t nwid = at(ZT_PROTO_VERB_EXT_FRAME_IDX_NETWORK_ID); @@ -680,13 +680,13 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr

addCredential(com); + network->addCredential(tPtr,com); } - if (!network->gate(peer)) { + if (!network->gate(tPtr,peer)) { TRACE("dropped EXT_FRAME from %s(%s): not a member of private network %.16llx",peer->address().toString().c_str(),_path->address().toString().c_str(),network->id()); - _sendErrorNeedCredentials(RR,peer,nwid); - peer->received(_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,false); + _sendErrorNeedCredentials(RR,tPtr,peer,nwid); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,false); return true; } @@ -699,36 +699,36 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr

mac())) { TRACE("dropped EXT_FRAME from %s@%s(%s) to %s: invalid source MAC %s",from.toString().c_str(),peer->address().toString().c_str(),_path->address().toString().c_str(),to.toString().c_str(),from.toString().c_str()); - peer->received(_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay return true; } - switch (network->filterIncomingPacket(peer,RR->identity.address(),from,to,frameData,frameLen,etherType,0)) { + switch (network->filterIncomingPacket(tPtr,peer,RR->identity.address(),from,to,frameData,frameLen,etherType,0)) { case 1: if (from != MAC(peer->address(),nwid)) { if (network->config().permitsBridging(peer->address())) { network->learnBridgeRoute(from,peer->address()); } else { TRACE("dropped EXT_FRAME from %s@%s(%s) to %s: sender not allowed to bridge into %.16llx",from.toString().c_str(),peer->address().toString().c_str(),_path->address().toString().c_str(),to.toString().c_str(),network->id()); - peer->received(_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay return true; } } else if (to != network->mac()) { if (to.isMulticast()) { if (network->config().multicastLimit == 0) { TRACE("dropped EXT_FRAME from %s@%s(%s) to %s: network %.16llx does not allow multicast",from.toString().c_str(),peer->address().toString().c_str(),_path->address().toString().c_str(),to.toString().c_str(),network->id()); - peer->received(_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay return true; } } else if (!network->config().permitsBridging(RR->identity.address())) { TRACE("dropped EXT_FRAME from %s@%s(%s) to %s: I cannot bridge to %.16llx or bridging disabled on network",from.toString().c_str(),peer->address().toString().c_str(),_path->address().toString().c_str(),to.toString().c_str(),network->id()); - peer->received(_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay return true; } } // fall through -- 2 means accept regardless of bridging checks or other restrictions case 2: - RR->node->putFrame(nwid,network->userPtr(),from,to,etherType,0,(const void *)frameData,frameLen); + RR->node->putFrame(tPtr,nwid,network->userPtr(),from,to,etherType,0,(const void *)frameData,frameLen); break; } } @@ -739,14 +739,14 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr

key(),true,_path->nextOutgoingCounter()); - _path->send(RR,outp.data(),outp.size(),RR->node->now()); + _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); } - peer->received(_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,true); } else { TRACE("dropped EXT_FRAME from %s(%s): we are not connected to network %.16llx",source().toString().c_str(),_path->address().toString().c_str(),at(ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID)); - _sendErrorNeedCredentials(RR,peer,nwid); - peer->received(_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,false); + _sendErrorNeedCredentials(RR,tPtr,peer,nwid); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,false); } } catch ( ... ) { TRACE("dropped EXT_FRAME from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str()); @@ -754,7 +754,7 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr

&peer) +bool IncomingPacket::_doECHO(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer) { try { if (!peer->rateGateEchoRequest(RR->node->now())) { @@ -769,16 +769,16 @@ bool IncomingPacket::_doECHO(const RuntimeEnvironment *RR,const SharedPtr if (size() > ZT_PACKET_IDX_PAYLOAD) outp.append(reinterpret_cast(data()) + ZT_PACKET_IDX_PAYLOAD,size() - ZT_PACKET_IDX_PAYLOAD); outp.armor(peer->key(),true,_path->nextOutgoingCounter()); - _path->send(RR,outp.data(),outp.size(),RR->node->now()); + _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); - peer->received(_path,hops(),pid,Packet::VERB_ECHO,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),pid,Packet::VERB_ECHO,0,Packet::VERB_NOP,false); } catch ( ... ) { TRACE("dropped ECHO from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str()); } return true; } -bool IncomingPacket::_doMULTICAST_LIKE(const RuntimeEnvironment *RR,const SharedPtr &peer) +bool IncomingPacket::_doMULTICAST_LIKE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer) { try { const uint64_t now = RR->node->now(); @@ -802,9 +802,9 @@ bool IncomingPacket::_doMULTICAST_LIKE(const RuntimeEnvironment *RR,const Shared if (!auth) { if ((!network)||(network->id() != nwid)) network = RR->node->network(nwid); - const bool authOnNet = ((network)&&(network->gate(peer))); + const bool authOnNet = ((network)&&(network->gate(tPtr,peer))); if (!authOnNet) - _sendErrorNeedCredentials(RR,peer,nwid); + _sendErrorNeedCredentials(RR,tPtr,peer,nwid); trustEstablished |= authOnNet; if (authOnNet||RR->mc->cacheAuthorized(peer->address(),nwid,now)) { auth = true; @@ -815,18 +815,18 @@ bool IncomingPacket::_doMULTICAST_LIKE(const RuntimeEnvironment *RR,const Shared if (auth) { const MulticastGroup group(MAC(field(ptr + 8,6),6),at(ptr + 14)); - RR->mc->add(now,nwid,group,peer->address()); + RR->mc->add(tPtr,now,nwid,group,peer->address()); } } - peer->received(_path,hops(),packetId(),Packet::VERB_MULTICAST_LIKE,0,Packet::VERB_NOP,trustEstablished); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_LIKE,0,Packet::VERB_NOP,trustEstablished); } catch ( ... ) { TRACE("dropped MULTICAST_LIKE from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str()); } return true; } -bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const SharedPtr &peer) +bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer) { try { if (!peer->rateGateCredentialsReceived(RR->node->now())) { @@ -847,7 +847,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S if (com) { const SharedPtr network(RR->node->network(com.networkId())); if (network) { - switch (network->addCredential(com)) { + switch (network->addCredential(tPtr,com)) { case Membership::ADD_REJECTED: break; case Membership::ADD_ACCEPTED_NEW: @@ -857,7 +857,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S case Membership::ADD_DEFERRED_FOR_WHOIS: return false; } - } else RR->mc->addCredential(com,false); + } else RR->mc->addCredential(tPtr,com,false); } } ++p; // skip trailing 0 after COMs if present @@ -868,7 +868,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S p += cap.deserialize(*this,p); const SharedPtr network(RR->node->network(cap.networkId())); if (network) { - switch (network->addCredential(cap)) { + switch (network->addCredential(tPtr,cap)) { case Membership::ADD_REJECTED: break; case Membership::ADD_ACCEPTED_NEW: @@ -888,7 +888,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S p += tag.deserialize(*this,p); const SharedPtr network(RR->node->network(tag.networkId())); if (network) { - switch (network->addCredential(tag)) { + switch (network->addCredential(tPtr,tag)) { case Membership::ADD_REJECTED: break; case Membership::ADD_ACCEPTED_NEW: @@ -908,7 +908,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S p += revocation.deserialize(*this,p); const SharedPtr network(RR->node->network(revocation.networkId())); if (network) { - switch(network->addCredential(peer->address(),revocation)) { + switch(network->addCredential(tPtr,peer->address(),revocation)) { case Membership::ADD_REJECTED: break; case Membership::ADD_ACCEPTED_NEW: @@ -928,7 +928,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S p += coo.deserialize(*this,p); const SharedPtr network(RR->node->network(coo.networkId())); if (network) { - switch(network->addCredential(coo)) { + switch(network->addCredential(tPtr,coo)) { case Membership::ADD_REJECTED: break; case Membership::ADD_ACCEPTED_NEW: @@ -942,7 +942,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S } } - peer->received(_path,hops(),packetId(),Packet::VERB_NETWORK_CREDENTIALS,0,Packet::VERB_NOP,trustEstablished); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_NETWORK_CREDENTIALS,0,Packet::VERB_NOP,trustEstablished); } catch (std::exception &exc) { //fprintf(stderr,"dropped NETWORK_CREDENTIALS from %s(%s): %s" ZT_EOL_S,source().toString().c_str(),_path->address().toString().c_str(),exc.what()); TRACE("dropped NETWORK_CREDENTIALS from %s(%s): %s",source().toString().c_str(),_path->address().toString().c_str(),exc.what()); @@ -953,7 +953,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S return true; } -bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,const SharedPtr &peer) +bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer) { try { const uint64_t nwid = at(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID); @@ -972,10 +972,10 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons outp.append((unsigned char)Packet::ERROR_UNSUPPORTED_OPERATION); outp.append(nwid); outp.armor(peer->key(),true,_path->nextOutgoingCounter()); - _path->send(RR,outp.data(),outp.size(),RR->node->now()); + _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); } - peer->received(_path,hopCount,requestPacketId,Packet::VERB_NETWORK_CONFIG_REQUEST,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hopCount,requestPacketId,Packet::VERB_NETWORK_CONFIG_REQUEST,0,Packet::VERB_NOP,false); } catch (std::exception &exc) { //fprintf(stderr,"dropped NETWORK_CONFIG_REQUEST from %s(%s): %s" ZT_EOL_S,source().toString().c_str(),_path->address().toString().c_str(),exc.what()); TRACE("dropped NETWORK_CONFIG_REQUEST from %s(%s): %s",source().toString().c_str(),_path->address().toString().c_str(),exc.what()); @@ -986,12 +986,12 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons return true; } -bool IncomingPacket::_doNETWORK_CONFIG(const RuntimeEnvironment *RR,const SharedPtr &peer) +bool IncomingPacket::_doNETWORK_CONFIG(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer) { try { const SharedPtr network(RR->node->network(at(ZT_PACKET_IDX_PAYLOAD))); if (network) { - const uint64_t configUpdateId = network->handleConfigChunk(packetId(),source(),*this,ZT_PACKET_IDX_PAYLOAD); + const uint64_t configUpdateId = network->handleConfigChunk(tPtr,packetId(),source(),*this,ZT_PACKET_IDX_PAYLOAD); if (configUpdateId) { Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK); outp.append((uint8_t)Packet::VERB_ECHO); @@ -999,17 +999,17 @@ bool IncomingPacket::_doNETWORK_CONFIG(const RuntimeEnvironment *RR,const Shared outp.append((uint64_t)network->id()); outp.append((uint64_t)configUpdateId); outp.armor(peer->key(),true,_path->nextOutgoingCounter()); - _path->send(RR,outp.data(),outp.size(),RR->node->now()); + _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); } } - peer->received(_path,hops(),packetId(),Packet::VERB_NETWORK_CONFIG,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_NETWORK_CONFIG,0,Packet::VERB_NOP,false); } catch ( ... ) { TRACE("dropped NETWORK_CONFIG_REFRESH from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str()); } return true; } -bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,const SharedPtr &peer) +bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer) { try { const uint64_t nwid = at(ZT_PROTO_VERB_MULTICAST_GATHER_IDX_NETWORK_ID); @@ -1027,17 +1027,17 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,const Shar com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_GATHER_IDX_COM); if (com) { if (network) - network->addCredential(com); - else RR->mc->addCredential(com,false); + network->addCredential(tPtr,com); + else RR->mc->addCredential(tPtr,com,false); } } catch ( ... ) { TRACE("MULTICAST_GATHER from %s(%s): discarded invalid COM",peer->address().toString().c_str(),_path->address().toString().c_str()); } } - const bool trustEstablished = ((network)&&(network->gate(peer))); + const bool trustEstablished = ((network)&&(network->gate(tPtr,peer))); if (!trustEstablished) - _sendErrorNeedCredentials(RR,peer,nwid); + _sendErrorNeedCredentials(RR,tPtr,peer,nwid); if ( ( trustEstablished || RR->mc->cacheAuthorized(peer->address(),nwid,RR->node->now()) ) && (gatherLimit > 0) ) { Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK); outp.append((unsigned char)Packet::VERB_MULTICAST_GATHER); @@ -1048,7 +1048,7 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,const Shar const unsigned int gatheredLocally = RR->mc->gather(peer->address(),nwid,mg,outp,gatherLimit); if (gatheredLocally > 0) { outp.armor(peer->key(),true,_path->nextOutgoingCounter()); - _path->send(RR,outp.data(),outp.size(),RR->node->now()); + _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); } // If we are a member of a cluster, distribute this GATHER across it @@ -1058,14 +1058,14 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,const Shar #endif } - peer->received(_path,hops(),packetId(),Packet::VERB_MULTICAST_GATHER,0,Packet::VERB_NOP,trustEstablished); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_GATHER,0,Packet::VERB_NOP,trustEstablished); } catch ( ... ) { TRACE("dropped MULTICAST_GATHER from %s(%s): unexpected exception",peer->address().toString().c_str(),_path->address().toString().c_str()); } return true; } -bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const SharedPtr &peer) +bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer) { try { const uint64_t nwid = at(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID); @@ -1081,19 +1081,19 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share CertificateOfMembership com; offset += com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME_IDX_COM); if (com) - network->addCredential(com); + network->addCredential(tPtr,com); } - if (!network->gate(peer)) { + if (!network->gate(tPtr,peer)) { TRACE("dropped MULTICAST_FRAME from %s(%s): not a member of private network %.16llx",peer->address().toString().c_str(),_path->address().toString().c_str(),(unsigned long long)network->id()); - _sendErrorNeedCredentials(RR,peer,nwid); - peer->received(_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,false); + _sendErrorNeedCredentials(RR,tPtr,peer,nwid); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,false); return true; } if (network->config().multicastLimit == 0) { TRACE("dropped MULTICAST_FRAME from %s(%s): network %.16llx does not allow multicast",peer->address().toString().c_str(),_path->address().toString().c_str(),(unsigned long long)network->id()); - peer->received(_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,false); return true; } @@ -1120,12 +1120,12 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share if ((frameLen > 0)&&(frameLen <= ZT_IF_MTU)) { if (!to.mac().isMulticast()) { TRACE("dropped MULTICAST_FRAME from %s@%s(%s) to %s: destination is unicast, must use FRAME or EXT_FRAME",from.toString().c_str(),peer->address().toString().c_str(),_path->address().toString().c_str(),to.toString().c_str()); - peer->received(_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay return true; } if ((!from)||(from.isMulticast())||(from == network->mac())) { TRACE("dropped MULTICAST_FRAME from %s@%s(%s) to %s: invalid source MAC",from.toString().c_str(),peer->address().toString().c_str(),_path->address().toString().c_str(),to.toString().c_str()); - peer->received(_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay return true; } @@ -1134,14 +1134,14 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share network->learnBridgeRoute(from,peer->address()); } else { TRACE("dropped MULTICAST_FRAME from %s@%s(%s) to %s: sender not allowed to bridge into %.16llx",from.toString().c_str(),peer->address().toString().c_str(),_path->address().toString().c_str(),to.toString().c_str(),network->id()); - peer->received(_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true); // trustEstablished because COM is okay return true; } } const uint8_t *const frameData = (const uint8_t *)field(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME,frameLen); - if (network->filterIncomingPacket(peer,RR->identity.address(),from,to.mac(),frameData,frameLen,etherType,0) > 0) { - RR->node->putFrame(nwid,network->userPtr(),from,to.mac(),etherType,0,(const void *)frameData,frameLen); + if (network->filterIncomingPacket(tPtr,peer,RR->identity.address(),from,to.mac(),frameData,frameLen,etherType,0) > 0) { + RR->node->putFrame(tPtr,nwid,network->userPtr(),from,to.mac(),etherType,0,(const void *)frameData,frameLen); } } @@ -1155,14 +1155,14 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share outp.append((unsigned char)0x02); // flag 0x02 = contains gather results if (RR->mc->gather(peer->address(),nwid,to,outp,gatherLimit)) { outp.armor(peer->key(),true,_path->nextOutgoingCounter()); - _path->send(RR,outp.data(),outp.size(),RR->node->now()); + _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); } } - peer->received(_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true); } else { - _sendErrorNeedCredentials(RR,peer,nwid); - peer->received(_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,false); + _sendErrorNeedCredentials(RR,tPtr,peer,nwid); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,false); } } catch ( ... ) { TRACE("dropped MULTICAST_FRAME from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str()); @@ -1170,7 +1170,7 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share return true; } -bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const SharedPtr &peer) +bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer) { try { const uint64_t now = RR->node->now(); @@ -1178,7 +1178,7 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const Sha // First, subject this to a rate limit if (!peer->rateGatePushDirectPaths(now)) { TRACE("dropped PUSH_DIRECT_PATHS from %s(%s): circuit breaker tripped",source().toString().c_str(),_path->address().toString().c_str()); - peer->received(_path,hops(),packetId(),Packet::VERB_PUSH_DIRECT_PATHS,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_PUSH_DIRECT_PATHS,0,Packet::VERB_NOP,false); return true; } @@ -1209,10 +1209,10 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const Sha redundant = peer->hasActivePathTo(now,a); } - if ( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH) == 0) && (!redundant) && (RR->node->shouldUsePathForZeroTierTraffic(peer->address(),_path->localAddress(),a)) ) { + if ( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH) == 0) && (!redundant) && (RR->node->shouldUsePathForZeroTierTraffic(tPtr,peer->address(),_path->localAddress(),a)) ) { if (++countPerScope[(int)a.ipScope()][0] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) { TRACE("attempting to contact %s at pushed direct path %s",peer->address().toString().c_str(),a.toString().c_str()); - peer->attemptToContactAt(InetAddress(),a,now,false,0); + peer->attemptToContactAt(tPtr,InetAddress(),a,now,false,0); } else { TRACE("ignoring contact for %s at %s -- too many per scope",peer->address().toString().c_str(),a.toString().c_str()); } @@ -1228,10 +1228,10 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const Sha redundant = peer->hasActivePathTo(now,a); } - if ( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH) == 0) && (!redundant) && (RR->node->shouldUsePathForZeroTierTraffic(peer->address(),_path->localAddress(),a)) ) { + if ( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH) == 0) && (!redundant) && (RR->node->shouldUsePathForZeroTierTraffic(tPtr,peer->address(),_path->localAddress(),a)) ) { if (++countPerScope[(int)a.ipScope()][1] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) { TRACE("attempting to contact %s at pushed direct path %s",peer->address().toString().c_str(),a.toString().c_str()); - peer->attemptToContactAt(InetAddress(),a,now,false,0); + peer->attemptToContactAt(tPtr,InetAddress(),a,now,false,0); } else { TRACE("ignoring contact for %s at %s -- too many per scope",peer->address().toString().c_str(),a.toString().c_str()); } @@ -1241,20 +1241,20 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const Sha ptr += addrLen; } - peer->received(_path,hops(),packetId(),Packet::VERB_PUSH_DIRECT_PATHS,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_PUSH_DIRECT_PATHS,0,Packet::VERB_NOP,false); } catch ( ... ) { TRACE("dropped PUSH_DIRECT_PATHS from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str()); } return true; } -bool IncomingPacket::_doCIRCUIT_TEST(const RuntimeEnvironment *RR,const SharedPtr &peer) +bool IncomingPacket::_doCIRCUIT_TEST(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer) { try { const Address originatorAddress(field(ZT_PACKET_IDX_PAYLOAD,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); - SharedPtr originator(RR->topology->getPeer(originatorAddress)); + SharedPtr originator(RR->topology->getPeer(tPtr,originatorAddress)); if (!originator) { - RR->sw->requestWhois(originatorAddress); + RR->sw->requestWhois(tPtr,originatorAddress); return false; } @@ -1285,7 +1285,7 @@ bool IncomingPacket::_doCIRCUIT_TEST(const RuntimeEnvironment *RR,const SharedPt const unsigned int signatureLength = at(ZT_PACKET_IDX_PAYLOAD + 27 + vlf); if (!originator->identity().verify(field(ZT_PACKET_IDX_PAYLOAD,27 + vlf),27 + vlf,field(ZT_PACKET_IDX_PAYLOAD + 29 + vlf,signatureLength),signatureLength)) { TRACE("dropped CIRCUIT_TEST from %s(%s): signature by originator %s invalid",source().toString().c_str(),_path->address().toString().c_str(),originatorAddress.toString().c_str()); - peer->received(_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST,0,Packet::VERB_NOP,false); return true; } vlf += signatureLength; @@ -1304,14 +1304,14 @@ bool IncomingPacket::_doCIRCUIT_TEST(const RuntimeEnvironment *RR,const SharedPt SharedPtr network(RR->node->network(originatorCredentialNetworkId)); if ((!network)||(!network->config().circuitTestingAllowed(originatorAddress))) { TRACE("dropped CIRCUIT_TEST from %s(%s): originator %s specified network ID %.16llx as credential, and we don't belong to that network or originator is not allowed'",source().toString().c_str(),_path->address().toString().c_str(),originatorAddress.toString().c_str(),originatorCredentialNetworkId); - peer->received(_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST,0,Packet::VERB_NOP,false); return true; } - if (network->gate(peer)) + if (network->gate(tPtr,peer)) reportFlags |= ZT_CIRCUIT_TEST_REPORT_FLAGS_UPSTREAM_AUTHORIZED_IN_PATH; } else { TRACE("dropped CIRCUIT_TEST from %s(%s): originator %s did not specify a credential or credential type",source().toString().c_str(),_path->address().toString().c_str(),originatorAddress.toString().c_str()); - peer->received(_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST,0,Packet::VERB_NOP,false); return true; } @@ -1327,7 +1327,7 @@ bool IncomingPacket::_doCIRCUIT_TEST(const RuntimeEnvironment *RR,const SharedPt for(unsigned int h=0;h nhp(RR->topology->getPeer(nextHop[h])); + SharedPtr nhp(RR->topology->getPeer(tPtr,nextHop[h])); if (nhp) { SharedPtr nhbp(nhp->getBestPath(now,false)); if ((nhbp)&&(nhbp->alive(now))) @@ -1362,7 +1362,7 @@ bool IncomingPacket::_doCIRCUIT_TEST(const RuntimeEnvironment *RR,const SharedPt nextHop[h].appendTo(outp); nextHopBestPathAddress[h].serialize(outp); // appends 0 if null InetAddress } - RR->sw->send(outp,true); + RR->sw->send(tPtr,outp,true); } // If there are next hops, forward the test along through the graph @@ -1377,19 +1377,19 @@ bool IncomingPacket::_doCIRCUIT_TEST(const RuntimeEnvironment *RR,const SharedPt if (RR->identity.address() != nextHop[h]) { // next hops that loop back to the current hop are not valid outp.newInitializationVector(); outp.setDestination(nextHop[h]); - RR->sw->send(outp,true); + RR->sw->send(tPtr,outp,true); } } } - peer->received(_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST,0,Packet::VERB_NOP,false); } catch ( ... ) { TRACE("dropped CIRCUIT_TEST from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str()); } return true; } -bool IncomingPacket::_doCIRCUIT_TEST_REPORT(const RuntimeEnvironment *RR,const SharedPtr &peer) +bool IncomingPacket::_doCIRCUIT_TEST_REPORT(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer) { try { ZT_CircuitTestReport report; @@ -1431,14 +1431,14 @@ bool IncomingPacket::_doCIRCUIT_TEST_REPORT(const RuntimeEnvironment *RR,const S RR->node->postCircuitTestReport(&report); - peer->received(_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST_REPORT,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST_REPORT,0,Packet::VERB_NOP,false); } catch ( ... ) { TRACE("dropped CIRCUIT_TEST_REPORT from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str()); } return true; } -bool IncomingPacket::_doUSER_MESSAGE(const RuntimeEnvironment *RR,const SharedPtr &peer) +bool IncomingPacket::_doUSER_MESSAGE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer) { try { if (size() >= (ZT_PACKET_IDX_PAYLOAD + 8)) { @@ -1447,16 +1447,16 @@ bool IncomingPacket::_doUSER_MESSAGE(const RuntimeEnvironment *RR,const SharedPt um.typeId = at(ZT_PACKET_IDX_PAYLOAD); um.data = reinterpret_cast(reinterpret_cast(data()) + ZT_PACKET_IDX_PAYLOAD + 8); um.length = size() - (ZT_PACKET_IDX_PAYLOAD + 8); - RR->node->postEvent(ZT_EVENT_USER_MESSAGE,reinterpret_cast(&um)); + RR->node->postEvent(tPtr,ZT_EVENT_USER_MESSAGE,reinterpret_cast(&um)); } - peer->received(_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST_REPORT,0,Packet::VERB_NOP,false); + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST_REPORT,0,Packet::VERB_NOP,false); } catch ( ... ) { TRACE("dropped CIRCUIT_TEST_REPORT from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str()); } return true; } -void IncomingPacket::_sendErrorNeedCredentials(const RuntimeEnvironment *RR,const SharedPtr &peer,const uint64_t nwid) +void IncomingPacket::_sendErrorNeedCredentials(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer,const uint64_t nwid) { const uint64_t now = RR->node->now(); if (peer->rateGateOutgoingComRequest(now)) { @@ -1466,7 +1466,7 @@ void IncomingPacket::_sendErrorNeedCredentials(const RuntimeEnvironment *RR,cons outp.append((uint8_t)Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE); outp.append(nwid); outp.armor(peer->key(),true,_path->nextOutgoingCounter()); - _path->send(RR,outp.data(),outp.size(),now); + _path->send(RR,tPtr,outp.data(),outp.size(),now); } } diff --git a/node/IncomingPacket.hpp b/node/IncomingPacket.hpp index febff28a..3d4a2e05 100644 --- a/node/IncomingPacket.hpp +++ b/node/IncomingPacket.hpp @@ -102,9 +102,10 @@ public: * may no longer be valid. * * @param RR Runtime environment + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @return True if decoding and processing is complete, false if caller should try again */ - bool tryDecode(const RuntimeEnvironment *RR); + bool tryDecode(const RuntimeEnvironment *RR,void *tPtr); /** * @return Time of packet receipt / start of decode @@ -114,26 +115,26 @@ public: private: // These are called internally to handle packet contents once it has // been authenticated, decrypted, decompressed, and classified. - bool _doERROR(const RuntimeEnvironment *RR,const SharedPtr &peer); - bool _doHELLO(const RuntimeEnvironment *RR,const bool alreadyAuthenticated); - bool _doOK(const RuntimeEnvironment *RR,const SharedPtr &peer); - bool _doWHOIS(const RuntimeEnvironment *RR,const SharedPtr &peer); - bool _doRENDEZVOUS(const RuntimeEnvironment *RR,const SharedPtr &peer); - bool _doFRAME(const RuntimeEnvironment *RR,const SharedPtr &peer); - bool _doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr &peer); - bool _doECHO(const RuntimeEnvironment *RR,const SharedPtr &peer); - bool _doMULTICAST_LIKE(const RuntimeEnvironment *RR,const SharedPtr &peer); - bool _doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const SharedPtr &peer); - bool _doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,const SharedPtr &peer); - bool _doNETWORK_CONFIG(const RuntimeEnvironment *RR,const SharedPtr &peer); - bool _doMULTICAST_GATHER(const RuntimeEnvironment *RR,const SharedPtr &peer); - bool _doMULTICAST_FRAME(const RuntimeEnvironment *RR,const SharedPtr &peer); - bool _doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const SharedPtr &peer); - bool _doCIRCUIT_TEST(const RuntimeEnvironment *RR,const SharedPtr &peer); - bool _doCIRCUIT_TEST_REPORT(const RuntimeEnvironment *RR,const SharedPtr &peer); - bool _doUSER_MESSAGE(const RuntimeEnvironment *RR,const SharedPtr &peer); - - void _sendErrorNeedCredentials(const RuntimeEnvironment *RR,const SharedPtr &peer,const uint64_t nwid); + bool _doERROR(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer); + bool _doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool alreadyAuthenticated); + bool _doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer); + bool _doWHOIS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer); + bool _doRENDEZVOUS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer); + bool _doFRAME(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer); + bool _doEXT_FRAME(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer); + bool _doECHO(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer); + bool _doMULTICAST_LIKE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer); + bool _doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer); + bool _doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer); + bool _doNETWORK_CONFIG(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer); + bool _doMULTICAST_GATHER(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer); + bool _doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer); + bool _doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer); + bool _doCIRCUIT_TEST(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer); + bool _doCIRCUIT_TEST_REPORT(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer); + bool _doUSER_MESSAGE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer); + + void _sendErrorNeedCredentials(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer,const uint64_t nwid); uint64_t _receiveTime; SharedPtr _path; diff --git a/node/Membership.cpp b/node/Membership.cpp index 3b2e3b1c..22c13c88 100644 --- a/node/Membership.cpp +++ b/node/Membership.cpp @@ -40,7 +40,7 @@ Membership::Membership() : for(unsigned int i=0;i= ZT_CREDENTIAL_PUSH_EVERY) || (force) ) ); @@ -113,7 +113,7 @@ void Membership::pushCredentials(const RuntimeEnvironment *RR,const uint64_t now outp.setAt(cooCountAt,(uint16_t)thisPacketCooCount); outp.compress(); - RR->sw->send(outp,true); + RR->sw->send(tPtr,outp,true); } } @@ -123,7 +123,7 @@ const Tag *Membership::getTag(const NetworkConfig &nconf,const uint32_t id) cons return ( ((t != &(_remoteTags[ZT_MAX_NETWORK_CAPABILITIES]))&&((*t)->id == (uint64_t)id)) ? ((((*t)->lastReceived)&&(_isCredentialTimestampValid(nconf,**t))) ? &((*t)->credential) : (const Tag *)0) : (const Tag *)0); } -Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const CertificateOfMembership &com) +Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const CertificateOfMembership &com) { const uint64_t newts = com.timestamp().first; if (newts <= _comRevocationThreshold) { @@ -141,7 +141,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme return ADD_ACCEPTED_REDUNDANT; } - switch(com.verify(RR)) { + switch(com.verify(RR,tPtr)) { default: TRACE("addCredential(CertificateOfMembership) for %s on %.16llx REJECTED (invalid signature or object)",com.issuedTo().toString().c_str(),com.networkId()); return ADD_REJECTED; @@ -154,7 +154,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme } } -Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const Tag &tag) +Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const Tag &tag) { _RemoteCredential *const *htmp = std::lower_bound(&(_remoteTags[0]),&(_remoteTags[ZT_MAX_NETWORK_TAGS]),(uint64_t)tag.id(),_RemoteCredentialComp()); _RemoteCredential *have = ((htmp != &(_remoteTags[ZT_MAX_NETWORK_TAGS]))&&((*htmp)->id == (uint64_t)tag.id())) ? *htmp : (_RemoteCredential *)0; @@ -169,7 +169,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme } } - switch(tag.verify(RR)) { + switch(tag.verify(RR,tPtr)) { default: TRACE("addCredential(Tag) for %s on %.16llx REJECTED (invalid)",tag.issuedTo().toString().c_str(),tag.networkId()); return ADD_REJECTED; @@ -184,7 +184,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme } } -Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const Capability &cap) +Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const Capability &cap) { _RemoteCredential *const *htmp = std::lower_bound(&(_remoteCaps[0]),&(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]),(uint64_t)cap.id(),_RemoteCredentialComp()); _RemoteCredential *have = ((htmp != &(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]))&&((*htmp)->id == (uint64_t)cap.id())) ? *htmp : (_RemoteCredential *)0; @@ -199,7 +199,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme } } - switch(cap.verify(RR)) { + switch(cap.verify(RR,tPtr)) { default: TRACE("addCredential(Capability) for %s on %.16llx REJECTED (invalid)",cap.issuedTo().toString().c_str(),cap.networkId()); return ADD_REJECTED; @@ -214,9 +214,9 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme } } -Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const Revocation &rev) +Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const Revocation &rev) { - switch(rev.verify(RR)) { + switch(rev.verify(RR,tPtr)) { default: return ADD_REJECTED; case 0: { @@ -239,7 +239,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme } } -Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const CertificateOfOwnership &coo) +Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const CertificateOfOwnership &coo) { _RemoteCredential *const *htmp = std::lower_bound(&(_remoteCoos[0]),&(_remoteCoos[ZT_MAX_CERTIFICATES_OF_OWNERSHIP]),(uint64_t)coo.id(),_RemoteCredentialComp()); _RemoteCredential *have = ((htmp != &(_remoteCoos[ZT_MAX_CERTIFICATES_OF_OWNERSHIP]))&&((*htmp)->id == (uint64_t)coo.id())) ? *htmp : (_RemoteCredential *)0; @@ -254,7 +254,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme } } - switch(coo.verify(RR)) { + switch(coo.verify(RR,tPtr)) { default: TRACE("addCredential(CertificateOfOwnership) for %s on %.16llx REJECTED (invalid)",coo.issuedTo().toString().c_str(),coo.networkId()); return ADD_REJECTED; diff --git a/node/Membership.hpp b/node/Membership.hpp index 97510b57..c28d598c 100644 --- a/node/Membership.hpp +++ b/node/Membership.hpp @@ -158,13 +158,14 @@ public: * sends VERB_NETWORK_CREDENTIALS if the recipient might need them. * * @param RR Runtime environment + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @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 * @param force If true, send objects regardless of last push time */ - void pushCredentials(const RuntimeEnvironment *RR,const uint64_t now,const Address &peerAddress,const NetworkConfig &nconf,int localCapabilityIndex,const bool force); + void pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const uint64_t now,const Address &peerAddress,const NetworkConfig &nconf,int localCapabilityIndex,const bool force); /** * Check whether we should push MULTICAST_LIKEs to this peer @@ -226,27 +227,27 @@ public: /** * Validate and add a credential if signature is okay and it's otherwise good */ - AddCredentialResult addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const CertificateOfMembership &com); + AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const CertificateOfMembership &com); /** * Validate and add a credential if signature is okay and it's otherwise good */ - AddCredentialResult addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const Tag &tag); + AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const Tag &tag); /** * Validate and add a credential if signature is okay and it's otherwise good */ - AddCredentialResult addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const Capability &cap); + AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const Capability &cap); /** * Validate and add a credential if signature is okay and it's otherwise good */ - AddCredentialResult addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const Revocation &rev); + AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const Revocation &rev); /** * Validate and add a credential if signature is okay and it's otherwise good */ - AddCredentialResult addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const CertificateOfOwnership &coo); + AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const CertificateOfOwnership &coo); private: _RemoteCredential *_newTag(const uint64_t id); diff --git a/node/Multicaster.cpp b/node/Multicaster.cpp index f8d58501..8e534b5e 100644 --- a/node/Multicaster.cpp +++ b/node/Multicaster.cpp @@ -43,14 +43,14 @@ Multicaster::~Multicaster() { } -void Multicaster::addMultiple(uint64_t now,uint64_t nwid,const MulticastGroup &mg,const void *addresses,unsigned int count,unsigned int totalKnown) +void Multicaster::addMultiple(void *tPtr,uint64_t now,uint64_t nwid,const MulticastGroup &mg,const void *addresses,unsigned int count,unsigned int totalKnown) { const unsigned char *p = (const unsigned char *)addresses; const unsigned char *e = p + (5 * count); Mutex::Lock _l(_groups_m); MulticastGroupStatus &gs = _groups[Multicaster::Key(nwid,mg)]; while (p != e) { - _add(now,nwid,mg,gs,Address(p,5)); + _add(tPtr,now,nwid,mg,gs,Address(p,5)); p += 5; } } @@ -152,6 +152,7 @@ std::vector

Multicaster::getMembers(uint64_t nwid,const MulticastGroup } void Multicaster::send( + void *tPtr, unsigned int limit, uint64_t now, uint64_t nwid, @@ -207,7 +208,7 @@ void Multicaster::send( for(std::vector
::const_iterator ast(alwaysSendTo.begin());ast!=alwaysSendTo.end();++ast) { if (*ast != RR->identity.address()) { - out.sendOnly(RR,*ast); // optimization: don't use dedup log if it's a one-pass send + out.sendOnly(RR,tPtr,*ast); // optimization: don't use dedup log if it's a one-pass send if (++count >= limit) break; } @@ -217,7 +218,7 @@ void Multicaster::send( while ((count < limit)&&(idx < gs.members.size())) { Address ma(gs.members[indexes[idx++]].address); if (std::find(alwaysSendTo.begin(),alwaysSendTo.end(),ma) == alwaysSendTo.end()) { - out.sendOnly(RR,ma); // optimization: don't use dedup log if it's a one-pass send + out.sendOnly(RR,tPtr,ma); // optimization: don't use dedup log if it's a one-pass send ++count; } } @@ -256,7 +257,7 @@ void Multicaster::send( if (com) com->serialize(outp); RR->node->expectReplyTo(outp.packetId()); - RR->sw->send(outp,true); + RR->sw->send(tPtr,outp,true); } } @@ -280,7 +281,7 @@ void Multicaster::send( for(std::vector
::const_iterator ast(alwaysSendTo.begin());ast!=alwaysSendTo.end();++ast) { if (*ast != RR->identity.address()) { - out.sendAndLog(RR,*ast); + out.sendAndLog(RR,tPtr,*ast); if (++count >= limit) break; } @@ -290,7 +291,7 @@ void Multicaster::send( while ((count < limit)&&(idx < gs.members.size())) { Address ma(gs.members[indexes[idx++]].address); if (std::find(alwaysSendTo.begin(),alwaysSendTo.end(),ma) == alwaysSendTo.end()) { - out.sendAndLog(RR,ma); + out.sendAndLog(RR,tPtr,ma); ++count; } } @@ -352,15 +353,15 @@ void Multicaster::clean(uint64_t now) } } -void Multicaster::addCredential(const CertificateOfMembership &com,bool alreadyValidated) +void Multicaster::addCredential(void *tPtr,const CertificateOfMembership &com,bool alreadyValidated) { - if ((alreadyValidated)||(com.verify(RR) == 0)) { + if ((alreadyValidated)||(com.verify(RR,tPtr) == 0)) { Mutex::Lock _l(_gatherAuth_m); _gatherAuth[_GatherAuthKey(com.networkId(),com.issuedTo())] = RR->node->now(); } } -void Multicaster::_add(uint64_t now,uint64_t nwid,const MulticastGroup &mg,MulticastGroupStatus &gs,const Address &member) +void Multicaster::_add(void *tPtr,uint64_t now,uint64_t nwid,const MulticastGroup &mg,MulticastGroupStatus &gs,const Address &member) { // assumes _groups_m is locked @@ -383,7 +384,7 @@ void Multicaster::_add(uint64_t now,uint64_t nwid,const MulticastGroup &mg,Multi if (tx->atLimit()) gs.txQueue.erase(tx++); else { - tx->sendIfNew(RR,member); + tx->sendIfNew(RR,tPtr,member); if (tx->atLimit()) gs.txQueue.erase(tx++); else ++tx; diff --git a/node/Multicaster.hpp b/node/Multicaster.hpp index 32dec9cf..f646a5be 100644 --- a/node/Multicaster.hpp +++ b/node/Multicaster.hpp @@ -90,10 +90,10 @@ public: * @param mg Multicast group * @param member New member address */ - inline void add(uint64_t now,uint64_t nwid,const MulticastGroup &mg,const Address &member) + inline void add(void *tPtr,uint64_t now,uint64_t nwid,const MulticastGroup &mg,const Address &member) { Mutex::Lock _l(_groups_m); - _add(now,nwid,mg,_groups[Multicaster::Key(nwid,mg)],member); + _add(tPtr,now,nwid,mg,_groups[Multicaster::Key(nwid,mg)],member); } /** @@ -101,6 +101,7 @@ public: * * It's up to the caller to check bounds on the array before calling this. * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param now Current time * @param nwid Network ID * @param mg Multicast group @@ -108,7 +109,7 @@ public: * @param count Number of addresses * @param totalKnown Total number of known addresses as reported by peer */ - void addMultiple(uint64_t now,uint64_t nwid,const MulticastGroup &mg,const void *addresses,unsigned int count,unsigned int totalKnown); + void addMultiple(void *tPtr,uint64_t now,uint64_t nwid,const MulticastGroup &mg,const void *addresses,unsigned int count,unsigned int totalKnown); /** * Remove a multicast group member (if present) @@ -150,6 +151,7 @@ public: /** * Send a multicast * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param limit Multicast limit * @param now Current time * @param nwid Network ID @@ -162,6 +164,7 @@ public: * @param len Length of packet data */ void send( + void *tPtr, unsigned int limit, uint64_t now, uint64_t nwid, @@ -191,7 +194,7 @@ public: * @param com Certificate of membership * @param alreadyValidated If true, COM has already been checked and found to be valid and signed */ - void addCredential(const CertificateOfMembership &com,bool alreadyValidated); + void addCredential(void *tPtr,const CertificateOfMembership &com,bool alreadyValidated); /** * Check authorization for GATHER and LIKE for non-network-members @@ -209,7 +212,7 @@ public: } private: - void _add(uint64_t now,uint64_t nwid,const MulticastGroup &mg,MulticastGroupStatus &gs,const Address &member); + void _add(void *tPtr,uint64_t now,uint64_t nwid,const MulticastGroup &mg,MulticastGroupStatus &gs,const Address &member); const RuntimeEnvironment *RR; diff --git a/node/Network.cpp b/node/Network.cpp index 38c1b0d9..0abfdf86 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -674,7 +674,7 @@ static _doZtFilterResult _doZtFilter( const ZeroTier::MulticastGroup Network::BROADCAST(ZeroTier::MAC(0xffffffffffffULL),0); -Network::Network(const RuntimeEnvironment *renv,uint64_t nwid,void *uptr) : +Network::Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,void *uptr) : RR(renv), _uPtr(uptr), _id(nwid), @@ -696,11 +696,11 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t nwid,void *uptr) : Dictionary *dconf = new Dictionary(); NetworkConfig *nconf = new NetworkConfig(); try { - std::string conf(RR->node->dataStoreGet(confn)); + std::string conf(RR->node->dataStoreGet(tPtr,confn)); if (conf.length()) { dconf->load(conf.c_str()); if (nconf->fromDictionary(*dconf)) { - this->setConfiguration(*nconf,false); + this->setConfiguration(tPtr,*nconf,false); _lastConfigUpdate = 0; // we still want to re-request a new config from the network gotConf = true; } @@ -711,13 +711,13 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t nwid,void *uptr) : if (!gotConf) { // Save a one-byte CR to persist membership while we request a real netconf - RR->node->dataStorePut(confn,"\n",1,false); + RR->node->dataStorePut(tPtr,confn,"\n",1,false); } if (!_portInitialized) { ZT_VirtualNetworkConfig ctmp; _externalConfig(&ctmp); - _portError = RR->node->configureVirtualNetworkPort(_id,&_uPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP,&ctmp); + _portError = RR->node->configureVirtualNetworkPort(tPtr,_id,&_uPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP,&ctmp); _portInitialized = true; } } @@ -729,15 +729,16 @@ Network::~Network() char n[128]; if (_destroyed) { - RR->node->configureVirtualNetworkPort(_id,&_uPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY,&ctmp); + RR->node->configureVirtualNetworkPort((void *)0,_id,&_uPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY,&ctmp); Utils::snprintf(n,sizeof(n),"networks.d/%.16llx.conf",_id); - RR->node->dataStoreDelete(n); + RR->node->dataStoreDelete((void *)0,n); } else { - RR->node->configureVirtualNetworkPort(_id,&_uPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN,&ctmp); + RR->node->configureVirtualNetworkPort((void *)0,_id,&_uPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN,&ctmp); } } bool Network::filterOutgoingPacket( + void *tPtr, const bool noTee, const Address &ztSource, const Address &ztDest, @@ -781,7 +782,7 @@ bool Network::filterOutgoingPacket( if ((!noTee)&&(cc2)) { Membership &m2 = _membership(cc2); - m2.pushCredentials(RR,now,cc2,_config,localCapabilityIndex,false); + m2.pushCredentials(RR,tPtr,now,cc2,_config,localCapabilityIndex,false); Packet outp(cc2,RR->identity.address(),Packet::VERB_EXT_FRAME); outp.append(_id); @@ -791,7 +792,7 @@ bool Network::filterOutgoingPacket( outp.append((uint16_t)etherType); outp.append(frameData,ccLength2); outp.compress(); - RR->sw->send(outp,true); + RR->sw->send(tPtr,outp,true); } break; @@ -813,11 +814,11 @@ bool Network::filterOutgoingPacket( if (accept) { if (membership) - membership->pushCredentials(RR,now,ztDest,_config,localCapabilityIndex,false); + membership->pushCredentials(RR,tPtr,now,ztDest,_config,localCapabilityIndex,false); if ((!noTee)&&(cc)) { Membership &m2 = _membership(cc); - m2.pushCredentials(RR,now,cc,_config,localCapabilityIndex,false); + m2.pushCredentials(RR,tPtr,now,cc,_config,localCapabilityIndex,false); Packet outp(cc,RR->identity.address(),Packet::VERB_EXT_FRAME); outp.append(_id); @@ -827,12 +828,12 @@ bool Network::filterOutgoingPacket( outp.append((uint16_t)etherType); outp.append(frameData,ccLength); outp.compress(); - RR->sw->send(outp,true); + RR->sw->send(tPtr,outp,true); } if ((ztDest != ztFinalDest)&&(ztFinalDest)) { Membership &m2 = _membership(ztFinalDest); - m2.pushCredentials(RR,now,ztFinalDest,_config,localCapabilityIndex,false); + m2.pushCredentials(RR,tPtr,now,ztFinalDest,_config,localCapabilityIndex,false); Packet outp(ztFinalDest,RR->identity.address(),Packet::VERB_EXT_FRAME); outp.append(_id); @@ -842,7 +843,7 @@ bool Network::filterOutgoingPacket( outp.append((uint16_t)etherType); outp.append(frameData,frameLen); outp.compress(); - RR->sw->send(outp,true); + RR->sw->send(tPtr,outp,true); return false; // DROP locally, since we redirected } else { @@ -854,6 +855,7 @@ bool Network::filterOutgoingPacket( } int Network::filterIncomingPacket( + void *tPtr, const SharedPtr &sourcePeer, const Address &ztDest, const MAC &macSource, @@ -898,7 +900,7 @@ int Network::filterIncomingPacket( if (accept) { if (cc2) { - _membership(cc2).pushCredentials(RR,RR->node->now(),cc2,_config,-1,false); + _membership(cc2).pushCredentials(RR,tPtr,RR->node->now(),cc2,_config,-1,false); Packet outp(cc2,RR->identity.address(),Packet::VERB_EXT_FRAME); outp.append(_id); @@ -908,7 +910,7 @@ int Network::filterIncomingPacket( outp.append((uint16_t)etherType); outp.append(frameData,ccLength2); outp.compress(); - RR->sw->send(outp,true); + RR->sw->send(tPtr,outp,true); } break; } @@ -929,7 +931,7 @@ int Network::filterIncomingPacket( if (accept) { if (cc) { - _membership(cc).pushCredentials(RR,RR->node->now(),cc,_config,-1,false); + _membership(cc).pushCredentials(RR,tPtr,RR->node->now(),cc,_config,-1,false); Packet outp(cc,RR->identity.address(),Packet::VERB_EXT_FRAME); outp.append(_id); @@ -939,11 +941,11 @@ int Network::filterIncomingPacket( outp.append((uint16_t)etherType); outp.append(frameData,ccLength); outp.compress(); - RR->sw->send(outp,true); + RR->sw->send(tPtr,outp,true); } if ((ztDest != ztFinalDest)&&(ztFinalDest)) { - _membership(ztFinalDest).pushCredentials(RR,RR->node->now(),ztFinalDest,_config,-1,false); + _membership(ztFinalDest).pushCredentials(RR,tPtr,RR->node->now(),ztFinalDest,_config,-1,false); Packet outp(ztFinalDest,RR->identity.address(),Packet::VERB_EXT_FRAME); outp.append(_id); @@ -953,7 +955,7 @@ int Network::filterIncomingPacket( outp.append((uint16_t)etherType); outp.append(frameData,frameLen); outp.compress(); - RR->sw->send(outp,true); + RR->sw->send(tPtr,outp,true); return 0; // DROP locally, since we redirected } @@ -972,12 +974,12 @@ bool Network::subscribedToMulticastGroup(const MulticastGroup &mg,bool includeBr return false; } -void Network::multicastSubscribe(const MulticastGroup &mg) +void Network::multicastSubscribe(void *tPtr,const MulticastGroup &mg) { Mutex::Lock _l(_lock); if (!std::binary_search(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg)) { _myMulticastGroups.insert(std::upper_bound(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg),mg); - _sendUpdatesToMembers(&mg); + _sendUpdatesToMembers(tPtr,&mg); } } @@ -989,7 +991,7 @@ void Network::multicastUnsubscribe(const MulticastGroup &mg) _myMulticastGroups.erase(i); } -uint64_t Network::handleConfigChunk(const uint64_t packetId,const Address &source,const Buffer &chunk,unsigned int ptr) +uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Address &source,const Buffer &chunk,unsigned int ptr) { const unsigned int start = ptr; @@ -1043,7 +1045,7 @@ uint64_t Network::handleConfigChunk(const uint64_t packetId,const Address &sourc } // If it's not a duplicate, check chunk signature - const Identity controllerId(RR->topology->getIdentity(controller())); + const Identity controllerId(RR->topology->getIdentity(tPtr,controller())); if (!controllerId) { // we should always have the controller identity by now, otherwise how would we have queried it the first time? TRACE("unable to verify chunk from %s: don't have controller identity",source.toString().c_str()); return 0; @@ -1067,7 +1069,7 @@ uint64_t Network::handleConfigChunk(const uint64_t packetId,const Address &sourc if ((*a != source)&&(*a != controller())) { Packet outp(*a,RR->identity.address(),Packet::VERB_NETWORK_CONFIG); outp.append(reinterpret_cast(chunk.data()) + start,chunk.size() - start); - RR->sw->send(outp,true); + RR->sw->send(tPtr,outp,true); } } } @@ -1126,7 +1128,7 @@ uint64_t Network::handleConfigChunk(const uint64_t packetId,const Address &sourc } if (nc) { - this->setConfiguration(*nc,true); + this->setConfiguration(tPtr,*nc,true); delete nc; return configUpdateId; } else { @@ -1136,7 +1138,7 @@ uint64_t Network::handleConfigChunk(const uint64_t packetId,const Address &sourc return 0; } -int Network::setConfiguration(const NetworkConfig &nconf,bool saveToDisk) +int Network::setConfiguration(void *tPtr,const NetworkConfig &nconf,bool saveToDisk) { // _lock is NOT locked when this is called try { @@ -1156,7 +1158,7 @@ int Network::setConfiguration(const NetworkConfig &nconf,bool saveToDisk) _portInitialized = true; _externalConfig(&ctmp); } - _portError = RR->node->configureVirtualNetworkPort(_id,&_uPtr,(oldPortInitialized) ? ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE : ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP,&ctmp); + _portError = RR->node->configureVirtualNetworkPort(tPtr,_id,&_uPtr,(oldPortInitialized) ? ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE : ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP,&ctmp); if (saveToDisk) { Dictionary *d = new Dictionary(); @@ -1164,7 +1166,7 @@ int Network::setConfiguration(const NetworkConfig &nconf,bool saveToDisk) char n[64]; Utils::snprintf(n,sizeof(n),"networks.d/%.16llx.conf",_id); if (nconf.toDictionary(*d,false)) - RR->node->dataStorePut(n,(const void *)d->data(),d->sizeBytes(),true); + RR->node->dataStorePut(tPtr,n,(const void *)d->data(),d->sizeBytes(),true); } catch ( ... ) {} delete d; } @@ -1176,7 +1178,7 @@ int Network::setConfiguration(const NetworkConfig &nconf,bool saveToDisk) return 0; } -void Network::requestConfiguration() +void Network::requestConfiguration(void *tPtr) { /* ZeroTier addresses can't begin with 0xff, so this is used to mark controllerless * network IDs. Controllerless network IDs only support unicast IPv6 using the 6plane @@ -1236,7 +1238,7 @@ void Network::requestConfiguration() nconf->type = ZT_NETWORK_TYPE_PUBLIC; Utils::snprintf(nconf->name,sizeof(nconf->name),"adhoc-%.04x-%.04x",(int)startPortRange,(int)endPortRange); - this->setConfiguration(*nconf,false); + this->setConfiguration(tPtr,*nconf,false); delete nconf; } else { this->setNotFound(); @@ -1284,10 +1286,10 @@ void Network::requestConfiguration() } outp.compress(); RR->node->expectReplyTo(outp.packetId()); - RR->sw->send(outp,true); + RR->sw->send(tPtr,outp,true); } -bool Network::gate(const SharedPtr &peer) +bool Network::gate(void *tPtr,const SharedPtr &peer) { const uint64_t now = RR->node->now(); Mutex::Lock _l(_lock); @@ -1298,8 +1300,8 @@ bool Network::gate(const SharedPtr &peer) if (!m) m = &(_membership(peer->address())); if (m->shouldLikeMulticasts(now)) { - m->pushCredentials(RR,now,peer->address(),_config,-1,false); - _announceMulticastGroupsTo(peer->address(),_allMulticastGroups()); + m->pushCredentials(RR,tPtr,now,peer->address(),_config,-1,false); + _announceMulticastGroupsTo(tPtr,peer->address(),_allMulticastGroups()); m->likingMulticasts(now); } return true; @@ -1377,31 +1379,31 @@ void Network::learnBridgeRoute(const MAC &mac,const Address &addr) } } -void Network::learnBridgedMulticastGroup(const MulticastGroup &mg,uint64_t now) +void Network::learnBridgedMulticastGroup(void *tPtr,const MulticastGroup &mg,uint64_t now) { Mutex::Lock _l(_lock); const unsigned long tmp = (unsigned long)_multicastGroupsBehindMe.size(); _multicastGroupsBehindMe.set(mg,now); if (tmp != _multicastGroupsBehindMe.size()) - _sendUpdatesToMembers(&mg); + _sendUpdatesToMembers(tPtr,&mg); } -Membership::AddCredentialResult Network::addCredential(const CertificateOfMembership &com) +Membership::AddCredentialResult Network::addCredential(void *tPtr,const CertificateOfMembership &com) { if (com.networkId() != _id) return Membership::ADD_REJECTED; const Address a(com.issuedTo()); Mutex::Lock _l(_lock); Membership &m = _membership(a); - const Membership::AddCredentialResult result = m.addCredential(RR,_config,com); + const Membership::AddCredentialResult result = m.addCredential(RR,tPtr,_config,com); if ((result == Membership::ADD_ACCEPTED_NEW)||(result == Membership::ADD_ACCEPTED_REDUNDANT)) { - m.pushCredentials(RR,RR->node->now(),a,_config,-1,false); - RR->mc->addCredential(com,true); + m.pushCredentials(RR,tPtr,RR->node->now(),a,_config,-1,false); + RR->mc->addCredential(tPtr,com,true); } return result; } -Membership::AddCredentialResult Network::addCredential(const Address &sentFrom,const Revocation &rev) +Membership::AddCredentialResult Network::addCredential(void *tPtr,const Address &sentFrom,const Revocation &rev) { if (rev.networkId() != _id) return Membership::ADD_REJECTED; @@ -1409,7 +1411,7 @@ Membership::AddCredentialResult Network::addCredential(const Address &sentFrom,c Mutex::Lock _l(_lock); Membership &m = _membership(rev.target()); - const Membership::AddCredentialResult result = m.addCredential(RR,_config,rev); + const Membership::AddCredentialResult result = m.addCredential(RR,tPtr,_config,rev); if ((result == Membership::ADD_ACCEPTED_NEW)&&(rev.fastPropagate())) { Address *a = (Address *)0; @@ -1424,7 +1426,7 @@ Membership::AddCredentialResult Network::addCredential(const Address &sentFrom,c outp.append((uint16_t)1); // one revocation! rev.serialize(outp); outp.append((uint16_t)0); // no certificates of ownership - RR->sw->send(outp,true); + RR->sw->send(tPtr,outp,true); } } } @@ -1495,7 +1497,7 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const } } -void Network::_sendUpdatesToMembers(const MulticastGroup *const newMulticastGroup) +void Network::_sendUpdatesToMembers(void *tPtr,const MulticastGroup *const newMulticastGroup) { // Assumes _lock is locked const uint64_t now = RR->node->now(); @@ -1521,9 +1523,9 @@ void Network::_sendUpdatesToMembers(const MulticastGroup *const newMulticastGrou outp.append((uint16_t)0); // no tags outp.append((uint16_t)0); // no revocations outp.append((uint16_t)0); // no certificates of ownership - RR->sw->send(outp,true); + RR->sw->send(tPtr,outp,true); } - _announceMulticastGroupsTo(*a,groups); + _announceMulticastGroupsTo(tPtr,*a,groups); } // Also announce to controller, and send COM to simplify and generalize behavior even though in theory it does not need it @@ -1537,9 +1539,9 @@ void Network::_sendUpdatesToMembers(const MulticastGroup *const newMulticastGrou outp.append((uint16_t)0); // no tags outp.append((uint16_t)0); // no revocations outp.append((uint16_t)0); // no certificates of ownership - RR->sw->send(outp,true); + RR->sw->send(tPtr,outp,true); } - _announceMulticastGroupsTo(c,groups); + _announceMulticastGroupsTo(tPtr,c,groups); } } @@ -1556,17 +1558,17 @@ void Network::_sendUpdatesToMembers(const MulticastGroup *const newMulticastGrou Membership *m = (Membership *)0; Hashtable::Iterator i(_memberships); while (i.next(a,m)) { - m->pushCredentials(RR,now,*a,_config,-1,false); + m->pushCredentials(RR,tPtr,now,*a,_config,-1,false); if ( ((newMulticastGroup)||(m->shouldLikeMulticasts(now))) && (m->isAllowedOnNetwork(_config)) ) { if (!newMulticastGroup) m->likingMulticasts(now); - _announceMulticastGroupsTo(*a,groups); + _announceMulticastGroupsTo(tPtr,*a,groups); } } } } -void Network::_announceMulticastGroupsTo(const Address &peer,const std::vector &allMulticastGroups) +void Network::_announceMulticastGroupsTo(void *tPtr,const Address &peer,const std::vector &allMulticastGroups) { // Assumes _lock is locked Packet outp(peer,RR->identity.address(),Packet::VERB_MULTICAST_LIKE); @@ -1574,7 +1576,7 @@ void Network::_announceMulticastGroupsTo(const Address &peer,const std::vector::const_iterator mg(allMulticastGroups.begin());mg!=allMulticastGroups.end();++mg) { if ((outp.size() + 24) >= ZT_PROTO_MAX_PACKET_LENGTH) { outp.compress(); - RR->sw->send(outp,true); + RR->sw->send(tPtr,outp,true); outp.reset(peer,RR->identity.address(),Packet::VERB_MULTICAST_LIKE); } @@ -1586,7 +1588,7 @@ void Network::_announceMulticastGroupsTo(const Address &peer,const std::vector ZT_PROTO_MIN_PACKET_LENGTH) { outp.compress(); - RR->sw->send(outp,true); + RR->sw->send(tPtr,outp,true); } } diff --git a/node/Network.hpp b/node/Network.hpp index 6cf6d974..fccc267a 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -77,10 +77,11 @@ public: * constructed to actually configure the port. * * @param renv Runtime environment + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param nwid Network ID * @param uptr Arbitrary pointer used by externally-facing API (for user use) */ - Network(const RuntimeEnvironment *renv,uint64_t nwid,void *uptr); + Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,void *uptr); ~Network(); @@ -101,6 +102,7 @@ public: * such as TEE may be taken, and credentials may be pushed, so this is not * side-effect-free. It's basically step one in sending something over VL2. * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param noTee If true, do not TEE anything anywhere (for two-pass filtering as done with multicast and bridging) * @param ztSource Source ZeroTier address * @param ztDest Destination ZeroTier address @@ -113,6 +115,7 @@ public: * @return True if packet should be sent, false if dropped or redirected */ bool filterOutgoingPacket( + void *tPtr, const bool noTee, const Address &ztSource, const Address &ztDest, @@ -131,6 +134,7 @@ public: * a match certain actions may be taken such as sending a copy of the packet * to a TEE or REDIRECT target. * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param sourcePeer Source Peer * @param ztDest Destination ZeroTier address * @param macSource Ethernet layer source address @@ -142,6 +146,7 @@ public: * @return 0 == drop, 1 == accept, 2 == accept even if bridged */ int filterIncomingPacket( + void *tPtr, const SharedPtr &sourcePeer, const Address &ztDest, const MAC &macSource, @@ -163,9 +168,10 @@ public: /** * Subscribe to a multicast group * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param mg New multicast group */ - void multicastSubscribe(const MulticastGroup &mg); + void multicastSubscribe(void *tPtr,const MulticastGroup &mg); /** * Unsubscribe from a multicast group @@ -181,22 +187,24 @@ public: * chunks via OK(NETWORK_CONFIG_REQUEST) or NETWORK_CONFIG. It verifies * each chunk and once assembled applies the configuration. * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param packetId Packet ID or 0 if none (e.g. via cluster path) * @param source Address of sender of chunk or NULL if none (e.g. via cluster path) * @param chunk Buffer containing chunk * @param ptr Index of chunk and related fields in packet * @return Update ID if update was fully assembled and accepted or 0 otherwise */ - uint64_t handleConfigChunk(const uint64_t packetId,const Address &source,const Buffer &chunk,unsigned int ptr); + uint64_t handleConfigChunk(void *tPtr,const uint64_t packetId,const Address &source,const Buffer &chunk,unsigned int ptr); /** * Set network configuration * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param nconf Network configuration * @param saveToDisk Save to disk? Used during loading, should usually be true otherwise. * @return 0 == bad, 1 == accepted but duplicate/unchanged, 2 == accepted and new */ - int setConfiguration(const NetworkConfig &nconf,bool saveToDisk); + int setConfiguration(void *tPtr,const NetworkConfig &nconf,bool saveToDisk); /** * Set netconf failure to 'access denied' -- called in IncomingPacket when controller reports this @@ -218,13 +226,18 @@ public: /** * Causes this network to request an updated configuration from its master node now + * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call */ - void requestConfiguration(); + void requestConfiguration(void *tPtr); /** * Determine whether this peer is permitted to communicate on this network + * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call + * @param peer Peer to check */ - bool gate(const SharedPtr &peer); + bool gate(void *tPtr,const SharedPtr &peer); /** * Do periodic cleanup and housekeeping tasks @@ -233,11 +246,13 @@ public: /** * Push state to members such as multicast group memberships and latest COM (if needed) + * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call */ - inline void sendUpdatesToMembers() + inline void sendUpdatesToMembers(void *tPtr) { Mutex::Lock _l(_lock); - _sendUpdatesToMembers((const MulticastGroup *)0); + _sendUpdatesToMembers(tPtr,(const MulticastGroup *)0); } /** @@ -264,64 +279,66 @@ public: /** * Learn a multicast group that is bridged to our tap device * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param mg Multicast group * @param now Current time */ - void learnBridgedMulticastGroup(const MulticastGroup &mg,uint64_t now); + void learnBridgedMulticastGroup(void *tPtr,const MulticastGroup &mg,uint64_t now); /** * Validate a credential and learn it if it passes certificate and other checks */ - Membership::AddCredentialResult addCredential(const CertificateOfMembership &com); + Membership::AddCredentialResult addCredential(void *tPtr,const CertificateOfMembership &com); /** * Validate a credential and learn it if it passes certificate and other checks */ - inline Membership::AddCredentialResult addCredential(const Capability &cap) + inline Membership::AddCredentialResult addCredential(void *tPtr,const Capability &cap) { if (cap.networkId() != _id) return Membership::ADD_REJECTED; Mutex::Lock _l(_lock); - return _membership(cap.issuedTo()).addCredential(RR,_config,cap); + return _membership(cap.issuedTo()).addCredential(RR,tPtr,_config,cap); } /** * Validate a credential and learn it if it passes certificate and other checks */ - inline Membership::AddCredentialResult addCredential(const Tag &tag) + inline Membership::AddCredentialResult addCredential(void *tPtr,const Tag &tag) { if (tag.networkId() != _id) return Membership::ADD_REJECTED; Mutex::Lock _l(_lock); - return _membership(tag.issuedTo()).addCredential(RR,_config,tag); + return _membership(tag.issuedTo()).addCredential(RR,tPtr,_config,tag); } /** * Validate a credential and learn it if it passes certificate and other checks */ - Membership::AddCredentialResult addCredential(const Address &sentFrom,const Revocation &rev); + Membership::AddCredentialResult addCredential(void *tPtr,const Address &sentFrom,const Revocation &rev); /** * Validate a credential and learn it if it passes certificate and other checks */ - inline Membership::AddCredentialResult addCredential(const CertificateOfOwnership &coo) + inline Membership::AddCredentialResult addCredential(void *tPtr,const CertificateOfOwnership &coo) { if (coo.networkId() != _id) return Membership::ADD_REJECTED; Mutex::Lock _l(_lock); - return _membership(coo.issuedTo()).addCredential(RR,_config,coo); + return _membership(coo.issuedTo()).addCredential(RR,tPtr,_config,coo); } /** * Force push credentials (COM, etc.) to a peer now * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param to Destination peer address * @param now Current time */ - inline void pushCredentialsNow(const Address &to,const uint64_t now) + inline void pushCredentialsNow(void *tPtr,const Address &to,const uint64_t now) { Mutex::Lock _l(_lock); - _membership(to).pushCredentials(RR,now,to,_config,-1,true); + _membership(to).pushCredentials(RR,tPtr,now,to,_config,-1,true); } /** @@ -353,8 +370,8 @@ private: ZT_VirtualNetworkStatus _status() const; void _externalConfig(ZT_VirtualNetworkConfig *ec) const; // assumes _lock is locked bool _gate(const SharedPtr &peer); - void _sendUpdatesToMembers(const MulticastGroup *const newMulticastGroup); - void _announceMulticastGroupsTo(const Address &peer,const std::vector &allMulticastGroups); + void _sendUpdatesToMembers(void *tPtr,const MulticastGroup *const newMulticastGroup); + void _announceMulticastGroupsTo(void *tPtr,const Address &peer,const std::vector &allMulticastGroups); std::vector _allMulticastGroups() const; Membership &_membership(const Address &a); diff --git a/node/Node.cpp b/node/Node.cpp index 1125ca7a..4e8d6655 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -46,7 +46,7 @@ namespace ZeroTier { /* Public Node interface (C++, exposed via CAPI bindings) */ /****************************************************************************/ -Node::Node(void *uptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now) : +Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now) : _RR(this), RR(&_RR), _uPtr(uptr), @@ -72,26 +72,26 @@ Node::Node(void *uptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now) : memset(_prngStream,0,sizeof(_prngStream)); _prng.crypt12(_prngStream,_prngStream,sizeof(_prngStream)); - std::string idtmp(dataStoreGet("identity.secret")); + std::string idtmp(dataStoreGet(tptr,"identity.secret")); if ((!idtmp.length())||(!RR->identity.fromString(idtmp))||(!RR->identity.hasPrivate())) { TRACE("identity.secret not found, generating..."); RR->identity.generate(); idtmp = RR->identity.toString(true); - if (!dataStorePut("identity.secret",idtmp,true)) + if (!dataStorePut(tptr,"identity.secret",idtmp,true)) throw std::runtime_error("unable to write identity.secret"); } RR->publicIdentityStr = RR->identity.toString(false); RR->secretIdentityStr = RR->identity.toString(true); - idtmp = dataStoreGet("identity.public"); + idtmp = dataStoreGet(tptr,"identity.public"); if (idtmp != RR->publicIdentityStr) { - if (!dataStorePut("identity.public",RR->publicIdentityStr,false)) + if (!dataStorePut(tptr,"identity.public",RR->publicIdentityStr,false)) throw std::runtime_error("unable to write identity.public"); } try { RR->sw = new Switch(RR); RR->mc = new Multicaster(RR); - RR->topology = new Topology(RR); + RR->topology = new Topology(RR,tptr); RR->sa = new SelfAwareness(RR); } catch ( ... ) { delete RR->sa; @@ -101,7 +101,7 @@ Node::Node(void *uptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now) : throw; } - postEvent(ZT_EVENT_UP); + postEvent(tptr,ZT_EVENT_UP); } Node::~Node() @@ -121,6 +121,7 @@ Node::~Node() } ZT_ResultCode Node::processWirePacket( + void *tptr, uint64_t now, const struct sockaddr_storage *localAddress, const struct sockaddr_storage *remoteAddress, @@ -129,11 +130,12 @@ ZT_ResultCode Node::processWirePacket( volatile uint64_t *nextBackgroundTaskDeadline) { _now = now; - RR->sw->onRemotePacket(*(reinterpret_cast(localAddress)),*(reinterpret_cast(remoteAddress)),packetData,packetLength); + RR->sw->onRemotePacket(tptr,*(reinterpret_cast(localAddress)),*(reinterpret_cast(remoteAddress)),packetData,packetLength); return ZT_RESULT_OK; } ZT_ResultCode Node::processVirtualNetworkFrame( + void *tptr, uint64_t now, uint64_t nwid, uint64_t sourceMac, @@ -147,7 +149,7 @@ ZT_ResultCode Node::processVirtualNetworkFrame( _now = now; SharedPtr nw(this->network(nwid)); if (nw) { - RR->sw->onLocalEthernet(nw,MAC(sourceMac),MAC(destMac),etherType,vlanId,frameData,frameLength); + RR->sw->onLocalEthernet(tptr,nw,MAC(sourceMac),MAC(destMac),etherType,vlanId,frameData,frameLength); return ZT_RESULT_OK; } else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND; } @@ -156,9 +158,10 @@ ZT_ResultCode Node::processVirtualNetworkFrame( class _PingPeersThatNeedPing { public: - _PingPeersThatNeedPing(const RuntimeEnvironment *renv,Hashtable< Address,std::vector > &upstreamsToContact,uint64_t now) : + _PingPeersThatNeedPing(const RuntimeEnvironment *renv,void *tPtr,Hashtable< Address,std::vector > &upstreamsToContact,uint64_t now) : lastReceiveFromUpstream(0), RR(renv), + _tPtr(tPtr), _upstreamsToContact(upstreamsToContact), _now(now), _bestCurrentUpstream(RR->topology->getUpstreamPeer()) @@ -176,21 +179,21 @@ public: // Upstreams must be pinged constantly over both IPv4 and IPv6 to allow // them to perform three way handshake introductions for both stacks. - if (!p->doPingAndKeepalive(_now,AF_INET)) { + if (!p->doPingAndKeepalive(_tPtr,_now,AF_INET)) { for(unsigned long k=0,ptr=(unsigned long)RR->node->prng();k<(unsigned long)upstreamStableEndpoints->size();++k) { const InetAddress &addr = (*upstreamStableEndpoints)[ptr++ % upstreamStableEndpoints->size()]; if (addr.ss_family == AF_INET) { - p->sendHELLO(InetAddress(),addr,_now,0); + p->sendHELLO(_tPtr,InetAddress(),addr,_now,0); contacted = true; break; } } } else contacted = true; - if (!p->doPingAndKeepalive(_now,AF_INET6)) { + if (!p->doPingAndKeepalive(_tPtr,_now,AF_INET6)) { for(unsigned long k=0,ptr=(unsigned long)RR->node->prng();k<(unsigned long)upstreamStableEndpoints->size();++k) { const InetAddress &addr = (*upstreamStableEndpoints)[ptr++ % upstreamStableEndpoints->size()]; if (addr.ss_family == AF_INET6) { - p->sendHELLO(InetAddress(),addr,_now,0); + p->sendHELLO(_tPtr,InetAddress(),addr,_now,0); contacted = true; break; } @@ -200,24 +203,25 @@ public: if ((!contacted)&&(_bestCurrentUpstream)) { const SharedPtr up(_bestCurrentUpstream->getBestPath(_now,true)); if (up) - p->sendHELLO(up->localAddress(),up->address(),_now,up->nextOutgoingCounter()); + p->sendHELLO(_tPtr,up->localAddress(),up->address(),_now,up->nextOutgoingCounter()); } lastReceiveFromUpstream = std::max(p->lastReceive(),lastReceiveFromUpstream); _upstreamsToContact.erase(p->address()); // erase from upstreams to contact so that we can WHOIS those that remain } else if (p->isActive(_now)) { - p->doPingAndKeepalive(_now,-1); + p->doPingAndKeepalive(_tPtr,_now,-1); } } private: const RuntimeEnvironment *RR; + void *_tPtr; Hashtable< Address,std::vector > &_upstreamsToContact; const uint64_t _now; const SharedPtr _bestCurrentUpstream; }; -ZT_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline) +ZT_ResultCode Node::processBackgroundTasks(void *tptr,uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline) { _now = now; Mutex::Lock bl(_backgroundTasksLock); @@ -235,16 +239,16 @@ ZT_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextB for(std::vector< std::pair< uint64_t,SharedPtr > >::const_iterator n(_networks.begin());n!=_networks.end();++n) { if (((now - n->second->lastConfigUpdate()) >= ZT_NETWORK_AUTOCONF_DELAY)||(!n->second->hasConfig())) needConfig.push_back(n->second); - n->second->sendUpdatesToMembers(); + n->second->sendUpdatesToMembers(tptr); } } for(std::vector< SharedPtr >::const_iterator n(needConfig.begin());n!=needConfig.end();++n) - (*n)->requestConfiguration(); + (*n)->requestConfiguration(tptr); // Do pings and keepalives Hashtable< Address,std::vector > upstreamsToContact; RR->topology->getUpstreamsToContact(upstreamsToContact); - _PingPeersThatNeedPing pfunc(RR,upstreamsToContact,now); + _PingPeersThatNeedPing pfunc(RR,tptr,upstreamsToContact,now); RR->topology->eachPeer<_PingPeersThatNeedPing &>(pfunc); // Run WHOIS to create Peer for any upstreams we could not contact (including pending moon seeds) @@ -252,13 +256,13 @@ ZT_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextB Address *upstreamAddress = (Address *)0; std::vector *upstreamStableEndpoints = (std::vector *)0; while (i.next(upstreamAddress,upstreamStableEndpoints)) - RR->sw->requestWhois(*upstreamAddress); + RR->sw->requestWhois(tptr,*upstreamAddress); // Update online status, post status change as event const bool oldOnline = _online; _online = (((now - pfunc.lastReceiveFromUpstream) < ZT_PEER_ACTIVITY_TIMEOUT)||(RR->topology->amRoot())); if (oldOnline != _online) - postEvent(_online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE); + postEvent(tptr,_online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE); } catch ( ... ) { return ZT_RESULT_FATAL_ERROR_INTERNAL; } @@ -286,7 +290,7 @@ ZT_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextB *nextBackgroundTaskDeadline = now + ZT_CLUSTER_PERIODIC_TASK_PERIOD; // this is really short so just tick at this rate } else { #endif - *nextBackgroundTaskDeadline = now + (uint64_t)std::max(std::min(timeUntilNextPingCheck,RR->sw->doTimerTasks(now)),(unsigned long)ZT_CORE_TIMER_TASK_GRANULARITY); + *nextBackgroundTaskDeadline = now + (uint64_t)std::max(std::min(timeUntilNextPingCheck,RR->sw->doTimerTasks(tptr,now)),(unsigned long)ZT_CORE_TIMER_TASK_GRANULARITY); #ifdef ZT_ENABLE_CLUSTER } #endif @@ -297,17 +301,17 @@ ZT_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextB return ZT_RESULT_OK; } -ZT_ResultCode Node::join(uint64_t nwid,void *uptr) +ZT_ResultCode Node::join(uint64_t nwid,void *uptr,void *tptr) { Mutex::Lock _l(_networks_m); SharedPtr nw = _network(nwid); if(!nw) - _networks.push_back(std::pair< uint64_t,SharedPtr >(nwid,SharedPtr(new Network(RR,nwid,uptr)))); + _networks.push_back(std::pair< uint64_t,SharedPtr >(nwid,SharedPtr(new Network(RR,tptr,nwid,uptr)))); std::sort(_networks.begin(),_networks.end()); // will sort by nwid since it's the first in a pair<> return ZT_RESULT_OK; } -ZT_ResultCode Node::leave(uint64_t nwid,void **uptr) +ZT_ResultCode Node::leave(uint64_t nwid,void **uptr,void *tptr) { std::vector< std::pair< uint64_t,SharedPtr > > newn; Mutex::Lock _l(_networks_m); @@ -324,11 +328,11 @@ ZT_ResultCode Node::leave(uint64_t nwid,void **uptr) return ZT_RESULT_OK; } -ZT_ResultCode Node::multicastSubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi) +ZT_ResultCode Node::multicastSubscribe(void *tptr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi) { SharedPtr nw(this->network(nwid)); if (nw) { - nw->multicastSubscribe(MulticastGroup(MAC(multicastGroup),(uint32_t)(multicastAdi & 0xffffffff))); + nw->multicastSubscribe(tptr,MulticastGroup(MAC(multicastGroup),(uint32_t)(multicastAdi & 0xffffffff))); return ZT_RESULT_OK; } else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND; } @@ -342,15 +346,15 @@ ZT_ResultCode Node::multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,u } else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND; } -ZT_ResultCode Node::orbit(uint64_t moonWorldId,uint64_t moonSeed) +ZT_ResultCode Node::orbit(void *tptr,uint64_t moonWorldId,uint64_t moonSeed) { - RR->topology->addMoon(moonWorldId,Address(moonSeed)); + RR->topology->addMoon(tptr,moonWorldId,Address(moonSeed)); return ZT_RESULT_OK; } -ZT_ResultCode Node::deorbit(uint64_t moonWorldId) +ZT_ResultCode Node::deorbit(void *tptr,uint64_t moonWorldId) { - RR->topology->removeMoon(moonWorldId); + RR->topology->removeMoon(tptr,moonWorldId); return ZT_RESULT_OK; } @@ -465,7 +469,7 @@ void Node::clearLocalInterfaceAddresses() _directPaths.clear(); } -int Node::sendUserMessage(uint64_t dest,uint64_t typeId,const void *data,unsigned int len) +int Node::sendUserMessage(void *tptr,uint64_t dest,uint64_t typeId,const void *data,unsigned int len) { try { if (RR->identity.address().toInt() != dest) { @@ -473,7 +477,7 @@ int Node::sendUserMessage(uint64_t dest,uint64_t typeId,const void *data,unsigne outp.append(typeId); outp.append(data,len); outp.compress(); - RR->sw->send(outp,true); + RR->sw->send(tptr,outp,true); return 1; } } catch ( ... ) {} @@ -486,7 +490,7 @@ void Node::setNetconfMaster(void *networkControllerInstance) RR->localNetworkController->init(RR->identity,this); } -ZT_ResultCode Node::circuitTestBegin(ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *)) +ZT_ResultCode Node::circuitTestBegin(void *tptr,ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *)) { if (test->hopCount > 0) { try { @@ -516,7 +520,7 @@ ZT_ResultCode Node::circuitTestBegin(ZT_CircuitTest *test,void (*reportCallback) for(unsigned int a=0;ahops[0].breadth;++a) { outp.newInitializationVector(); outp.setDestination(Address(test->hops[0].addresses[a])); - RR->sw->send(outp,true); + RR->sw->send(tptr,outp,true); } } catch ( ... ) { return ZT_RESULT_FATAL_ERROR_INTERNAL; // probably indicates FIFO too big for packet @@ -616,13 +620,13 @@ void Node::clusterStatus(ZT_ClusterStatus *cs) /* Node methods used only within node/ */ /****************************************************************************/ -std::string Node::dataStoreGet(const char *name) +std::string Node::dataStoreGet(void *tPtr,const char *name) { char buf[1024]; std::string r; unsigned long olen = 0; do { - long n = _cb.dataStoreGetFunction(reinterpret_cast(this),_uPtr,name,buf,sizeof(buf),(unsigned long)r.length(),&olen); + long n = _cb.dataStoreGetFunction(reinterpret_cast(this),_uPtr,tPtr,name,buf,sizeof(buf),(unsigned long)r.length(),&olen); if (n <= 0) return std::string(); r.append(buf,n); @@ -630,7 +634,7 @@ std::string Node::dataStoreGet(const char *name) return r; } -bool Node::shouldUsePathForZeroTierTraffic(const Address &ztaddr,const InetAddress &localAddress,const InetAddress &remoteAddress) +bool Node::shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,const InetAddress &localAddress,const InetAddress &remoteAddress) { if (!Path::isAddressValidForPath(remoteAddress)) return false; @@ -650,7 +654,7 @@ bool Node::shouldUsePathForZeroTierTraffic(const Address &ztaddr,const InetAddre } } - return ( (_cb.pathCheckFunction) ? (_cb.pathCheckFunction(reinterpret_cast(this),_uPtr,ztaddr.toInt(),reinterpret_cast(&localAddress),reinterpret_cast(&remoteAddress)) != 0) : true); + return ( (_cb.pathCheckFunction) ? (_cb.pathCheckFunction(reinterpret_cast(this),_uPtr,tPtr,ztaddr.toInt(),reinterpret_cast(&localAddress),reinterpret_cast(&remoteAddress)) != 0) : true); } #ifdef ZT_TRACE @@ -728,7 +732,7 @@ void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &de if (destination == RR->identity.address()) { SharedPtr n(network(nwid)); if (!n) return; - n->setConfiguration(nc,true); + n->setConfiguration((void *)0,nc,true); } else { Dictionary *dconf = new Dictionary(); try { @@ -762,7 +766,7 @@ void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &de outp.append(sig.data,ZT_C25519_SIGNATURE_LEN); outp.compress(); - RR->sw->send(outp,true); + RR->sw->send((void *)0,outp,true); chunkIndex += chunkLen; } } @@ -779,7 +783,7 @@ void Node::ncSendRevocation(const Address &destination,const Revocation &rev) if (destination == RR->identity.address()) { SharedPtr n(network(rev.networkId())); if (!n) return; - n->addCredential(RR->identity.address(),rev); + n->addCredential((void *)0,RR->identity.address(),rev); } else { Packet outp(destination,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS); outp.append((uint8_t)0x00); @@ -788,7 +792,7 @@ void Node::ncSendRevocation(const Address &destination,const Revocation &rev) outp.append((uint16_t)1); rev.serialize(outp); outp.append((uint16_t)0); - RR->sw->send(outp,true); + RR->sw->send((void *)0,outp,true); } } @@ -823,7 +827,7 @@ void Node::ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &des break; } outp.append(nwid); - RR->sw->send(outp,true); + RR->sw->send((void *)0,outp,true); } // else we can't send an ERROR() in response to nothing, so discard } @@ -835,11 +839,11 @@ void Node::ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &des extern "C" { -enum ZT_ResultCode ZT_Node_new(ZT_Node **node,void *uptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now) +enum ZT_ResultCode ZT_Node_new(ZT_Node **node,void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now) { *node = (ZT_Node *)0; try { - *node = reinterpret_cast(new ZeroTier::Node(uptr,callbacks,now)); + *node = reinterpret_cast(new ZeroTier::Node(uptr,tptr,callbacks,now)); return ZT_RESULT_OK; } catch (std::bad_alloc &exc) { return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; @@ -859,6 +863,7 @@ void ZT_Node_delete(ZT_Node *node) enum ZT_ResultCode ZT_Node_processWirePacket( ZT_Node *node, + void *tptr, uint64_t now, const struct sockaddr_storage *localAddress, const struct sockaddr_storage *remoteAddress, @@ -867,7 +872,7 @@ enum ZT_ResultCode ZT_Node_processWirePacket( volatile uint64_t *nextBackgroundTaskDeadline) { try { - return reinterpret_cast(node)->processWirePacket(now,localAddress,remoteAddress,packetData,packetLength,nextBackgroundTaskDeadline); + return reinterpret_cast(node)->processWirePacket(tptr,now,localAddress,remoteAddress,packetData,packetLength,nextBackgroundTaskDeadline); } catch (std::bad_alloc &exc) { return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; } catch ( ... ) { @@ -877,6 +882,7 @@ enum ZT_ResultCode ZT_Node_processWirePacket( enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame( ZT_Node *node, + void *tptr, uint64_t now, uint64_t nwid, uint64_t sourceMac, @@ -888,7 +894,7 @@ enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame( volatile uint64_t *nextBackgroundTaskDeadline) { try { - return reinterpret_cast(node)->processVirtualNetworkFrame(now,nwid,sourceMac,destMac,etherType,vlanId,frameData,frameLength,nextBackgroundTaskDeadline); + return reinterpret_cast(node)->processVirtualNetworkFrame(tptr,now,nwid,sourceMac,destMac,etherType,vlanId,frameData,frameLength,nextBackgroundTaskDeadline); } catch (std::bad_alloc &exc) { return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; } catch ( ... ) { @@ -896,10 +902,10 @@ enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame( } } -enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline) +enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,void *tptr,uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline) { try { - return reinterpret_cast(node)->processBackgroundTasks(now,nextBackgroundTaskDeadline); + return reinterpret_cast(node)->processBackgroundTasks(tptr,now,nextBackgroundTaskDeadline); } catch (std::bad_alloc &exc) { return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; } catch ( ... ) { @@ -907,10 +913,10 @@ enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,uint64_t now,vol } } -enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,void *uptr) +enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,void *uptr,void *tptr) { try { - return reinterpret_cast(node)->join(nwid,uptr); + return reinterpret_cast(node)->join(nwid,uptr,tptr); } catch (std::bad_alloc &exc) { return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; } catch ( ... ) { @@ -918,10 +924,10 @@ enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,void *uptr) } } -enum ZT_ResultCode ZT_Node_leave(ZT_Node *node,uint64_t nwid,void **uptr) +enum ZT_ResultCode ZT_Node_leave(ZT_Node *node,uint64_t nwid,void **uptr,void *tptr) { try { - return reinterpret_cast(node)->leave(nwid,uptr); + return reinterpret_cast(node)->leave(nwid,uptr,tptr); } catch (std::bad_alloc &exc) { return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; } catch ( ... ) { @@ -929,10 +935,10 @@ enum ZT_ResultCode ZT_Node_leave(ZT_Node *node,uint64_t nwid,void **uptr) } } -enum ZT_ResultCode ZT_Node_multicastSubscribe(ZT_Node *node,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi) +enum ZT_ResultCode ZT_Node_multicastSubscribe(ZT_Node *node,void *tptr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi) { try { - return reinterpret_cast(node)->multicastSubscribe(nwid,multicastGroup,multicastAdi); + return reinterpret_cast(node)->multicastSubscribe(tptr,nwid,multicastGroup,multicastAdi); } catch (std::bad_alloc &exc) { return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; } catch ( ... ) { @@ -951,19 +957,19 @@ enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node,uint64_t nwid,uint } } -enum ZT_ResultCode ZT_Node_orbit(ZT_Node *node,uint64_t moonWorldId,uint64_t moonSeed) +enum ZT_ResultCode ZT_Node_orbit(ZT_Node *node,void *tptr,uint64_t moonWorldId,uint64_t moonSeed) { try { - return reinterpret_cast(node)->orbit(moonWorldId,moonSeed); + return reinterpret_cast(node)->orbit(tptr,moonWorldId,moonSeed); } catch ( ... ) { return ZT_RESULT_FATAL_ERROR_INTERNAL; } } -ZT_ResultCode ZT_Node_deorbit(ZT_Node *node,uint64_t moonWorldId) +ZT_ResultCode ZT_Node_deorbit(ZT_Node *node,void *tptr,uint64_t moonWorldId) { try { - return reinterpret_cast(node)->deorbit(moonWorldId); + return reinterpret_cast(node)->deorbit(tptr,moonWorldId); } catch ( ... ) { return ZT_RESULT_FATAL_ERROR_INTERNAL; } @@ -1031,10 +1037,10 @@ void ZT_Node_clearLocalInterfaceAddresses(ZT_Node *node) } catch ( ... ) {} } -int ZT_Node_sendUserMessage(ZT_Node *node,uint64_t dest,uint64_t typeId,const void *data,unsigned int len) +int ZT_Node_sendUserMessage(ZT_Node *node,void *tptr,uint64_t dest,uint64_t typeId,const void *data,unsigned int len) { try { - return reinterpret_cast(node)->sendUserMessage(dest,typeId,data,len); + return reinterpret_cast(node)->sendUserMessage(tptr,dest,typeId,data,len); } catch ( ... ) { return 0; } @@ -1047,10 +1053,10 @@ void ZT_Node_setNetconfMaster(ZT_Node *node,void *networkControllerInstance) } catch ( ... ) {} } -enum ZT_ResultCode ZT_Node_circuitTestBegin(ZT_Node *node,ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *)) +enum ZT_ResultCode ZT_Node_circuitTestBegin(ZT_Node *node,void *tptr,ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *)) { try { - return reinterpret_cast(node)->circuitTestBegin(test,reportCallback); + return reinterpret_cast(node)->circuitTestBegin(tptr,test,reportCallback); } catch ( ... ) { return ZT_RESULT_FATAL_ERROR_INTERNAL; } diff --git a/node/Node.hpp b/node/Node.hpp index 21eac617..03bd7a8c 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -65,7 +65,7 @@ class World; class Node : public NetworkController::Sender { public: - Node(void *uptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now); + Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now); virtual ~Node(); // Get rid of alignment warnings on 32-bit Windows and possibly improve performance @@ -77,6 +77,7 @@ public: // Public API Functions ---------------------------------------------------- ZT_ResultCode processWirePacket( + void *tptr, uint64_t now, const struct sockaddr_storage *localAddress, const struct sockaddr_storage *remoteAddress, @@ -84,6 +85,7 @@ public: unsigned int packetLength, volatile uint64_t *nextBackgroundTaskDeadline); ZT_ResultCode processVirtualNetworkFrame( + void *tptr, uint64_t now, uint64_t nwid, uint64_t sourceMac, @@ -93,13 +95,13 @@ public: const void *frameData, unsigned int frameLength, volatile uint64_t *nextBackgroundTaskDeadline); - ZT_ResultCode processBackgroundTasks(uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline); - ZT_ResultCode join(uint64_t nwid,void *uptr); - ZT_ResultCode leave(uint64_t nwid,void **uptr); - ZT_ResultCode multicastSubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi); + ZT_ResultCode processBackgroundTasks(void *tptr,uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline); + ZT_ResultCode join(uint64_t nwid,void *uptr,void *tptr); + ZT_ResultCode leave(uint64_t nwid,void **uptr,void *tptr); + ZT_ResultCode multicastSubscribe(void *tptr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi); ZT_ResultCode multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi); - ZT_ResultCode orbit(uint64_t moonWorldId,uint64_t moonSeed); - ZT_ResultCode deorbit(uint64_t moonWorldId); + ZT_ResultCode orbit(void *tptr,uint64_t moonWorldId,uint64_t moonSeed); + ZT_ResultCode deorbit(void *tptr,uint64_t moonWorldId); uint64_t address() const; void status(ZT_NodeStatus *status) const; ZT_PeerList *peers() const; @@ -108,9 +110,9 @@ public: void freeQueryResult(void *qr); int addLocalInterfaceAddress(const struct sockaddr_storage *addr); void clearLocalInterfaceAddresses(); - int sendUserMessage(uint64_t dest,uint64_t typeId,const void *data,unsigned int len); + int sendUserMessage(void *tptr,uint64_t dest,uint64_t typeId,const void *data,unsigned int len); void setNetconfMaster(void *networkControllerInstance); - ZT_ResultCode circuitTestBegin(ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *)); + ZT_ResultCode circuitTestBegin(void *tptr,ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *)); void circuitTestEnd(ZT_CircuitTest *test); ZT_ResultCode clusterInit( unsigned int myId, @@ -132,11 +134,12 @@ public: inline uint64_t now() const throw() { return _now; } - inline bool putPacket(const InetAddress &localAddress,const InetAddress &addr,const void *data,unsigned int len,unsigned int ttl = 0) + inline bool putPacket(void *tPtr,const InetAddress &localAddress,const InetAddress &addr,const void *data,unsigned int len,unsigned int ttl = 0) { return (_cb.wirePacketSendFunction( reinterpret_cast(this), _uPtr, + tPtr, reinterpret_cast(&localAddress), reinterpret_cast(&addr), data, @@ -144,11 +147,12 @@ public: ttl) == 0); } - inline void putFrame(uint64_t nwid,void **nuptr,const MAC &source,const MAC &dest,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) + inline void putFrame(void *tPtr,uint64_t nwid,void **nuptr,const MAC &source,const MAC &dest,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) { _cb.virtualNetworkFrameFunction( reinterpret_cast(this), _uPtr, + tPtr, nwid, nuptr, source.toInt(), @@ -191,14 +195,14 @@ public: return _directPaths; } - inline bool dataStorePut(const char *name,const void *data,unsigned int len,bool secure) { return (_cb.dataStorePutFunction(reinterpret_cast(this),_uPtr,name,data,len,(int)secure) == 0); } - inline bool dataStorePut(const char *name,const std::string &data,bool secure) { return dataStorePut(name,(const void *)data.data(),(unsigned int)data.length(),secure); } - inline void dataStoreDelete(const char *name) { _cb.dataStorePutFunction(reinterpret_cast(this),_uPtr,name,(const void *)0,0,0); } - std::string dataStoreGet(const char *name); + inline bool dataStorePut(void *tPtr,const char *name,const void *data,unsigned int len,bool secure) { return (_cb.dataStorePutFunction(reinterpret_cast(this),_uPtr,tPtr,name,data,len,(int)secure) == 0); } + inline bool dataStorePut(void *tPtr,const char *name,const std::string &data,bool secure) { return dataStorePut(tPtr,name,(const void *)data.data(),(unsigned int)data.length(),secure); } + inline void dataStoreDelete(void *tPtr,const char *name) { _cb.dataStorePutFunction(reinterpret_cast(this),_uPtr,tPtr,name,(const void *)0,0,0); } + std::string dataStoreGet(void *tPtr,const char *name); - inline void postEvent(ZT_Event ev,const void *md = (const void *)0) { _cb.eventCallback(reinterpret_cast(this),_uPtr,ev,md); } + inline void postEvent(void *tPtr,ZT_Event ev,const void *md = (const void *)0) { _cb.eventCallback(reinterpret_cast(this),_uPtr,tPtr,ev,md); } - inline int configureVirtualNetworkPort(uint64_t nwid,void **nuptr,ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nc) { return _cb.virtualNetworkConfigFunction(reinterpret_cast(this),_uPtr,nwid,nuptr,op,nc); } + inline int configureVirtualNetworkPort(void *tPtr,uint64_t nwid,void **nuptr,ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nc) { return _cb.virtualNetworkConfigFunction(reinterpret_cast(this),_uPtr,tPtr,nwid,nuptr,op,nc); } inline bool online() const throw() { return _online; } @@ -206,8 +210,8 @@ public: void postTrace(const char *module,unsigned int line,const char *fmt,...); #endif - bool shouldUsePathForZeroTierTraffic(const Address &ztaddr,const InetAddress &localAddress,const InetAddress &remoteAddress); - inline bool externalPathLookup(const Address &ztaddr,int family,InetAddress &addr) { return ( (_cb.pathLookupFunction) ? (_cb.pathLookupFunction(reinterpret_cast(this),_uPtr,ztaddr.toInt(),family,reinterpret_cast(&addr)) != 0) : false ); } + bool shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,const InetAddress &localAddress,const InetAddress &remoteAddress); + inline bool externalPathLookup(void *tPtr,const Address &ztaddr,int family,InetAddress &addr) { return ( (_cb.pathLookupFunction) ? (_cb.pathLookupFunction(reinterpret_cast(this),_uPtr,tPtr,ztaddr.toInt(),family,reinterpret_cast(&addr)) != 0) : false ); } uint64_t prng(); void postCircuitTestReport(const ZT_CircuitTestReport *report); diff --git a/node/OutboundMulticast.cpp b/node/OutboundMulticast.cpp index d4cb87cb..285bfa5d 100644 --- a/node/OutboundMulticast.cpp +++ b/node/OutboundMulticast.cpp @@ -85,18 +85,18 @@ void OutboundMulticast::init( memcpy(_frameData,payload,_frameLen); } -void OutboundMulticast::sendOnly(const RuntimeEnvironment *RR,const Address &toAddr) +void OutboundMulticast::sendOnly(const RuntimeEnvironment *RR,void *tPtr,const Address &toAddr) { const SharedPtr nw(RR->node->network(_nwid)); const Address toAddr2(toAddr); - if ((nw)&&(nw->filterOutgoingPacket(true,RR->identity.address(),toAddr2,_macSrc,_macDest,_frameData,_frameLen,_etherType,0))) { + if ((nw)&&(nw->filterOutgoingPacket(tPtr,true,RR->identity.address(),toAddr2,_macSrc,_macDest,_frameData,_frameLen,_etherType,0))) { //TRACE(">>MC %.16llx -> %s",(unsigned long long)this,toAddr.toString().c_str()); _packet.newInitializationVector(); _packet.setDestination(toAddr2); RR->node->expectReplyTo(_packet.packetId()); Packet tmp(_packet); // make a copy of packet so as not to garble the original -- GitHub issue #461 - RR->sw->send(tmp,true); + RR->sw->send(tPtr,tmp,true); } } diff --git a/node/OutboundMulticast.hpp b/node/OutboundMulticast.hpp index 6370d0d7..0ecf113f 100644 --- a/node/OutboundMulticast.hpp +++ b/node/OutboundMulticast.hpp @@ -99,33 +99,36 @@ public: * Just send without checking log * * @param RR Runtime environment + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param toAddr Destination address */ - void sendOnly(const RuntimeEnvironment *RR,const Address &toAddr); + void sendOnly(const RuntimeEnvironment *RR,void *tPtr,const Address &toAddr); /** * Just send and log but do not check sent log * * @param RR Runtime environment + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param toAddr Destination address */ - inline void sendAndLog(const RuntimeEnvironment *RR,const Address &toAddr) + inline void sendAndLog(const RuntimeEnvironment *RR,void *tPtr,const Address &toAddr) { _alreadySentTo.push_back(toAddr); - sendOnly(RR,toAddr); + sendOnly(RR,tPtr,toAddr); } /** * Try to send this to a given peer if it hasn't been sent to them already * * @param RR Runtime environment + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param toAddr Destination address * @return True if address is new and packet was sent to switch, false if duplicate */ - inline bool sendIfNew(const RuntimeEnvironment *RR,const Address &toAddr) + inline bool sendIfNew(const RuntimeEnvironment *RR,void *tPtr,const Address &toAddr) { if (std::find(_alreadySentTo.begin(),_alreadySentTo.end(),toAddr) == _alreadySentTo.end()) { - sendAndLog(RR,toAddr); + sendAndLog(RR,tPtr,toAddr); return true; } else { return false; diff --git a/node/Path.cpp b/node/Path.cpp index 5592bacc..7366b56f 100644 --- a/node/Path.cpp +++ b/node/Path.cpp @@ -22,9 +22,9 @@ namespace ZeroTier { -bool Path::send(const RuntimeEnvironment *RR,const void *data,unsigned int len,uint64_t now) +bool Path::send(const RuntimeEnvironment *RR,void *tPtr,const void *data,unsigned int len,uint64_t now) { - if (RR->node->putPacket(_localAddress,address(),data,len)) { + if (RR->node->putPacket(tPtr,_localAddress,address(),data,len)) { _lastOut = now; return true; } diff --git a/node/Path.hpp b/node/Path.hpp index 62f29c22..aef628d4 100644 --- a/node/Path.hpp +++ b/node/Path.hpp @@ -186,12 +186,13 @@ public: * Send a packet via this path (last out time is also updated) * * @param RR Runtime environment + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param data Packet data * @param len Packet length * @param now Current time * @return True if transport reported success */ - bool send(const RuntimeEnvironment *RR,const void *data,unsigned int len,uint64_t now); + bool send(const RuntimeEnvironment *RR,void *tPtr,const void *data,unsigned int len,uint64_t now); /** * Manually update last sent time diff --git a/node/Peer.cpp b/node/Peer.cpp index fa3ce6c8..0cc23e33 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -68,6 +68,7 @@ Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Ident } void Peer::received( + void *tPtr, const SharedPtr &path, const unsigned int hops, const uint64_t packetId, @@ -161,7 +162,7 @@ void Peer::received( } } - if ( (!pathIsConfirmed) && (RR->node->shouldUsePathForZeroTierTraffic(_id.address(),path->localAddress(),path->address())) ) { + if ( (!pathIsConfirmed) && (RR->node->shouldUsePathForZeroTierTraffic(tPtr,_id.address(),path->localAddress(),path->address())) ) { if (verb == Packet::VERB_OK) { Mutex::Lock _l(_paths_m); @@ -206,7 +207,7 @@ void Peer::received( #endif } else { TRACE("got %s via unknown path %s(%s), confirming...",Packet::verbString(verb),_id.address().toString().c_str(),path->address().toString().c_str()); - attemptToContactAt(path->localAddress(),path->address(),now,true,path->nextOutgoingCounter()); + attemptToContactAt(tPtr,path->localAddress(),path->address(),now,true,path->nextOutgoingCounter()); path->sent(now); } } @@ -281,7 +282,7 @@ void Peer::received( if (count) { outp.setAt(ZT_PACKET_IDX_PAYLOAD,(uint16_t)count); outp.armor(_key,true,path->nextOutgoingCounter()); - path->send(RR,outp.data(),outp.size(),now); + path->send(RR,tPtr,outp.data(),outp.size(),now); } } } @@ -299,7 +300,7 @@ bool Peer::hasActivePathTo(uint64_t now,const InetAddress &addr) const return false; } -bool Peer::sendDirect(const void *data,unsigned int len,uint64_t now,bool forceEvenIfDead) +bool Peer::sendDirect(void *tPtr,const void *data,unsigned int len,uint64_t now,bool forceEvenIfDead) { Mutex::Lock _l(_paths_m); @@ -316,7 +317,7 @@ bool Peer::sendDirect(const void *data,unsigned int len,uint64_t now,bool forceE } if (bestp >= 0) { - return _paths[bestp].path->send(RR,data,len,now); + return _paths[bestp].path->send(RR,tPtr,data,len,now); } else { return false; } @@ -345,7 +346,7 @@ SharedPtr Peer::getBestPath(uint64_t now,bool includeExpired) } } -void Peer::sendHELLO(const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,unsigned int counter) +void Peer::sendHELLO(void *tPtr,const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,unsigned int counter) { Packet outp(_id.address(),RR->identity.address(),Packet::VERB_HELLO); @@ -387,35 +388,35 @@ void Peer::sendHELLO(const InetAddress &localAddr,const InetAddress &atAddress,u if (atAddress) { outp.armor(_key,false,counter); // false == don't encrypt full payload, but add MAC - RR->node->putPacket(localAddr,atAddress,outp.data(),outp.size()); + RR->node->putPacket(tPtr,localAddr,atAddress,outp.data(),outp.size()); } else { - RR->sw->send(outp,false); // false == don't encrypt full payload, but add MAC + RR->sw->send(tPtr,outp,false); // false == don't encrypt full payload, but add MAC } } -void Peer::attemptToContactAt(const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,bool sendFullHello,unsigned int counter) +void Peer::attemptToContactAt(void *tPtr,const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,bool sendFullHello,unsigned int counter) { if ( (!sendFullHello) && (_vProto >= 5) && (!((_vMajor == 1)&&(_vMinor == 1)&&(_vRevision == 0))) ) { Packet outp(_id.address(),RR->identity.address(),Packet::VERB_ECHO); RR->node->expectReplyTo(outp.packetId()); outp.armor(_key,true,counter); - RR->node->putPacket(localAddr,atAddress,outp.data(),outp.size()); + RR->node->putPacket(tPtr,localAddr,atAddress,outp.data(),outp.size()); } else { - sendHELLO(localAddr,atAddress,now,counter); + sendHELLO(tPtr,localAddr,atAddress,now,counter); } } -void Peer::tryMemorizedPath(uint64_t now) +void Peer::tryMemorizedPath(void *tPtr,uint64_t now) { if ((now - _lastTriedMemorizedPath) >= ZT_TRY_MEMORIZED_PATH_INTERVAL) { _lastTriedMemorizedPath = now; InetAddress mp; - if (RR->node->externalPathLookup(_id.address(),-1,mp)) - attemptToContactAt(InetAddress(),mp,now,true,0); + if (RR->node->externalPathLookup(tPtr,_id.address(),-1,mp)) + attemptToContactAt(tPtr,InetAddress(),mp,now,true,0); } } -bool Peer::doPingAndKeepalive(uint64_t now,int inetAddressFamily) +bool Peer::doPingAndKeepalive(void *tPtr,uint64_t now,int inetAddressFamily) { Mutex::Lock _l(_paths_m); @@ -433,7 +434,7 @@ bool Peer::doPingAndKeepalive(uint64_t now,int inetAddressFamily) if (bestp >= 0) { if ( ((now - _paths[bestp].lastReceive) >= ZT_PEER_PING_PERIOD) || (_paths[bestp].path->needsHeartbeat(now)) ) { - attemptToContactAt(_paths[bestp].path->localAddress(),_paths[bestp].path->address(),now,false,_paths[bestp].path->nextOutgoingCounter()); + attemptToContactAt(tPtr,_paths[bestp].path->localAddress(),_paths[bestp].path->address(),now,false,_paths[bestp].path->nextOutgoingCounter()); _paths[bestp].path->sent(now); } return true; @@ -452,12 +453,12 @@ bool Peer::hasActiveDirectPath(uint64_t now) const return false; } -void Peer::resetWithinScope(InetAddress::IpScope scope,int inetAddressFamily,uint64_t now) +void Peer::resetWithinScope(void *tPtr,InetAddress::IpScope scope,int inetAddressFamily,uint64_t now) { Mutex::Lock _l(_paths_m); for(unsigned int p=0;p<_numPaths;++p) { if ( (_paths[p].path->address().ss_family == inetAddressFamily) && (_paths[p].path->address().ipScope() == scope) ) { - attemptToContactAt(_paths[p].path->localAddress(),_paths[p].path->address(),now,false,_paths[p].path->nextOutgoingCounter()); + attemptToContactAt(tPtr,_paths[p].path->localAddress(),_paths[p].path->address(),now,false,_paths[p].path->nextOutgoingCounter()); _paths[p].path->sent(now); _paths[p].lastReceive = 0; // path will not be used unless it speaks again } diff --git a/node/Peer.hpp b/node/Peer.hpp index 72040b1d..41836410 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -84,6 +84,7 @@ public: * This is called by the decode pipe when a packet is proven to be authentic * and appears to be valid. * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param path Path over which packet was received * @param hops ZeroTier (not IP) hops * @param packetId Packet ID @@ -93,6 +94,7 @@ public: * @param trustEstablished If true, some form of non-trivial trust (like allowed in network) has been established */ void received( + void *tPtr, const SharedPtr &path, const unsigned int hops, const uint64_t packetId, @@ -125,13 +127,14 @@ public: /** * Send via best direct path * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param data Packet data * @param len Packet length * @param now Current time * @param forceEvenIfDead If true, send even if the path is not 'alive' * @return True if we actually sent something */ - bool sendDirect(const void *data,unsigned int len,uint64_t now,bool forceEvenIfDead); + bool sendDirect(void *tPtr,const void *data,unsigned int len,uint64_t now,bool forceEvenIfDead); /** * Get the best current direct path @@ -147,41 +150,47 @@ public: * * No statistics or sent times are updated here. * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param localAddr Local address * @param atAddress Destination address * @param now Current time * @param counter Outgoing packet counter */ - void sendHELLO(const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,unsigned int counter); + void sendHELLO(void *tPtr,const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,unsigned int counter); /** * Send ECHO (or HELLO for older peers) to this peer at the given address * * No statistics or sent times are updated here. * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param localAddr Local address * @param atAddress Destination address * @param now Current time * @param sendFullHello If true, always send a full HELLO instead of just an ECHO * @param counter Outgoing packet counter */ - void attemptToContactAt(const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,bool sendFullHello,unsigned int counter); + void attemptToContactAt(void *tPtr,const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,bool sendFullHello,unsigned int counter); /** * Try a memorized or statically defined path if any are known * * Under the hood this is done periodically based on ZT_TRY_MEMORIZED_PATH_INTERVAL. + * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call + * @param now Current time */ - void tryMemorizedPath(uint64_t now); + void tryMemorizedPath(void *tPtr,uint64_t now); /** * Send pings or keepalives depending on configured timeouts * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param now Current time * @param inetAddressFamily Keep this address family alive, or -1 for any * @return True if we have at least one direct path of the given family (or any if family is -1) */ - bool doPingAndKeepalive(uint64_t now,int inetAddressFamily); + bool doPingAndKeepalive(void *tPtr,uint64_t now,int inetAddressFamily); /** * @param now Current time @@ -195,11 +204,12 @@ public: * Resetting a path involves sending an ECHO to it and then deactivating * it until or unless it responds. * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param scope IP scope * @param inetAddressFamily Family e.g. AF_INET * @param now Current time */ - void resetWithinScope(InetAddress::IpScope scope,int inetAddressFamily,uint64_t now); + void resetWithinScope(void *tPtr,InetAddress::IpScope scope,int inetAddressFamily,uint64_t now); /** * Get most recently active path addresses for IPv4 and/or IPv6 diff --git a/node/Revocation.cpp b/node/Revocation.cpp index 420476a4..bab5653c 100644 --- a/node/Revocation.cpp +++ b/node/Revocation.cpp @@ -25,13 +25,13 @@ namespace ZeroTier { -int Revocation::verify(const RuntimeEnvironment *RR) const +int Revocation::verify(const RuntimeEnvironment *RR,void *tPtr) const { if ((!_signedBy)||(_signedBy != Network::controllerFor(_networkId))) return -1; - const Identity id(RR->topology->getIdentity(_signedBy)); + const Identity id(RR->topology->getIdentity(tPtr,_signedBy)); if (!id) { - RR->sw->requestWhois(_signedBy); + RR->sw->requestWhois(tPtr,_signedBy); return 1; } try { diff --git a/node/Revocation.hpp b/node/Revocation.hpp index 93c55112..8b9ce6dd 100644 --- a/node/Revocation.hpp +++ b/node/Revocation.hpp @@ -113,9 +113,10 @@ public: * Verify this revocation's signature * * @param RR Runtime environment to provide for peer lookup, etc. + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or chain */ - int verify(const RuntimeEnvironment *RR) const; + int verify(const RuntimeEnvironment *RR,void *tPtr) const; template inline void serialize(Buffer &b,const bool forSign = false) const diff --git a/node/SelfAwareness.cpp b/node/SelfAwareness.cpp index e84b7b65..cba84cdc 100644 --- a/node/SelfAwareness.cpp +++ b/node/SelfAwareness.cpp @@ -40,15 +40,17 @@ namespace ZeroTier { class _ResetWithinScope { public: - _ResetWithinScope(uint64_t now,int inetAddressFamily,InetAddress::IpScope scope) : + _ResetWithinScope(void *tPtr,uint64_t now,int inetAddressFamily,InetAddress::IpScope scope) : _now(now), + _tPtr(tPtr), _family(inetAddressFamily), _scope(scope) {} - inline void operator()(Topology &t,const SharedPtr &p) { p->resetWithinScope(_scope,_family,_now); } + inline void operator()(Topology &t,const SharedPtr &p) { p->resetWithinScope(_tPtr,_scope,_family,_now); } private: uint64_t _now; + void *_tPtr; int _family; InetAddress::IpScope _scope; }; @@ -59,7 +61,7 @@ SelfAwareness::SelfAwareness(const RuntimeEnvironment *renv) : { } -void SelfAwareness::iam(const Address &reporter,const InetAddress &receivedOnLocalAddress,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,uint64_t now) +void SelfAwareness::iam(void *tPtr,const Address &reporter,const InetAddress &receivedOnLocalAddress,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,uint64_t now) { const InetAddress::IpScope scope = myPhysicalAddress.ipScope(); @@ -91,7 +93,7 @@ void SelfAwareness::iam(const Address &reporter,const InetAddress &receivedOnLoc } // Reset all paths within this scope and address family - _ResetWithinScope rset(now,myPhysicalAddress.ss_family,(InetAddress::IpScope)scope); + _ResetWithinScope rset(tPtr,now,myPhysicalAddress.ss_family,(InetAddress::IpScope)scope); RR->topology->eachPeer<_ResetWithinScope &>(rset); } else { // Otherwise just update DB to use to determine external surface info diff --git a/node/SelfAwareness.hpp b/node/SelfAwareness.hpp index 4bdafeb2..c1db0c84 100644 --- a/node/SelfAwareness.hpp +++ b/node/SelfAwareness.hpp @@ -47,7 +47,7 @@ public: * @param trusted True if this peer is trusted as an authority to inform us of external address changes * @param now Current time */ - void iam(const Address &reporter,const InetAddress &receivedOnLocalAddress,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,uint64_t now); + void iam(void *tPtr,const Address &reporter,const InetAddress &receivedOnLocalAddress,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,uint64_t now); /** * Clean up database periodically diff --git a/node/Switch.cpp b/node/Switch.cpp index aab2e7ff..62674472 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -64,7 +64,7 @@ Switch::Switch(const RuntimeEnvironment *renv) : { } -void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &fromAddr,const void *data,unsigned int len) +void Switch::onRemotePacket(void *tPtr,const InetAddress &localAddr,const InetAddress &fromAddr,const void *data,unsigned int len) { try { const uint64_t now = RR->node->now(); @@ -81,15 +81,15 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from const Address beaconAddr(reinterpret_cast(data) + 8,5); if (beaconAddr == RR->identity.address()) return; - if (!RR->node->shouldUsePathForZeroTierTraffic(beaconAddr,localAddr,fromAddr)) + if (!RR->node->shouldUsePathForZeroTierTraffic(tPtr,beaconAddr,localAddr,fromAddr)) return; - const SharedPtr peer(RR->topology->getPeer(beaconAddr)); + const SharedPtr peer(RR->topology->getPeer(tPtr,beaconAddr)); if (peer) { // we'll only respond to beacons from known peers if ((now - _lastBeaconResponse) >= 2500) { // limit rate of responses _lastBeaconResponse = now; Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NOP); outp.armor(peer->key(),true,path->nextOutgoingCounter()); - path->send(RR,outp.data(),outp.size(),now); + path->send(RR,tPtr,outp.data(),outp.size(),now); } } @@ -115,8 +115,8 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from // Note: we don't bother initiating NAT-t for fragments, since heads will set that off. // It wouldn't hurt anything, just redundant and unnecessary. - SharedPtr relayTo = RR->topology->getPeer(destination); - if ((!relayTo)||(!relayTo->sendDirect(fragment.data(),fragment.size(),now,false))) { + SharedPtr relayTo = RR->topology->getPeer(tPtr,destination); + if ((!relayTo)||(!relayTo->sendDirect(tPtr,fragment.data(),fragment.size(),now,false))) { #ifdef ZT_ENABLE_CLUSTER if ((RR->cluster)&&(!isClusterFrontplane)) { RR->cluster->relayViaCluster(Address(),destination,fragment.data(),fragment.size(),false); @@ -127,7 +127,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from // Don't know peer or no direct path -- so relay via someone upstream relayTo = RR->topology->getUpstreamPeer(); if (relayTo) - relayTo->sendDirect(fragment.data(),fragment.size(),now,true); + relayTo->sendDirect(tPtr,fragment.data(),fragment.size(),now,true); } } else { TRACE("dropped relay [fragment](%s) -> %s, max hops exceeded",fromAddr.toString().c_str(),destination.toString().c_str()); @@ -171,7 +171,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from for(unsigned int f=1;ffrag0.append(rq->frags[f - 1].payload(),rq->frags[f - 1].payloadLength()); - if (rq->frag0.tryDecode(RR)) { + if (rq->frag0.tryDecode(RR,tPtr)) { rq->timestamp = 0; // packet decoded, free entry } else { rq->complete = true; // set complete flag but leave entry since it probably needs WHOIS or something @@ -212,8 +212,8 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from packet.incrementHops(); #endif - SharedPtr relayTo = RR->topology->getPeer(destination); - if ((relayTo)&&(relayTo->sendDirect(packet.data(),packet.size(),now,false))) { + SharedPtr relayTo = RR->topology->getPeer(tPtr,destination); + if ((relayTo)&&(relayTo->sendDirect(tPtr,packet.data(),packet.size(),now,false))) { if ((source != RR->identity.address())&&(_shouldUnite(now,source,destination))) { // don't send RENDEZVOUS for cluster frontplane relays const InetAddress *hintToSource = (InetAddress *)0; const InetAddress *hintToDest = (InetAddress *)0; @@ -222,7 +222,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from InetAddress sourceV4,sourceV6; relayTo->getRendezvousAddresses(now,destV4,destV6); - const SharedPtr sourcePeer(RR->topology->getPeer(source)); + const SharedPtr sourcePeer(RR->topology->getPeer(tPtr,source)); if (sourcePeer) { sourcePeer->getRendezvousAddresses(now,sourceV4,sourceV6); if ((destV6)&&(sourceV6)) { @@ -249,7 +249,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from outp.append((uint8_t)4); outp.append(hintToSource->rawIpData(),4); } - send(outp,true); + send(tPtr,outp,true); } else { Packet outp(destination,RR->identity.address(),Packet::VERB_RENDEZVOUS); outp.append((uint8_t)0); @@ -262,7 +262,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from outp.append((uint8_t)4); outp.append(hintToDest->rawIpData(),4); } - send(outp,true); + send(tPtr,outp,true); } ++alt; } @@ -278,7 +278,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from #endif relayTo = RR->topology->getUpstreamPeer(&source,1,true); if (relayTo) - relayTo->sendDirect(packet.data(),packet.size(),now,true); + relayTo->sendDirect(tPtr,packet.data(),packet.size(),now,true); } } else { TRACE("dropped relay %s(%s) -> %s, max hops exceeded",packet.source().toString().c_str(),fromAddr.toString().c_str(),destination.toString().c_str()); @@ -321,7 +321,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from for(unsigned int f=1;ftotalFragments;++f) rq->frag0.append(rq->frags[f - 1].payload(),rq->frags[f - 1].payloadLength()); - if (rq->frag0.tryDecode(RR)) { + if (rq->frag0.tryDecode(RR,tPtr)) { rq->timestamp = 0; // packet decoded, free entry } else { rq->complete = true; // set complete flag but leave entry since it probably needs WHOIS or something @@ -334,7 +334,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from } else { // Packet is unfragmented, so just process it IncomingPacket packet(data,len,path,now); - if (!packet.tryDecode(RR)) { + if (!packet.tryDecode(RR,tPtr)) { Mutex::Lock _l(_rxQueue_m); RXQueueEntry *rq = &(_rxQueue[ZT_RX_QUEUE_SIZE - 1]); unsigned long i = ZT_RX_QUEUE_SIZE - 1; @@ -362,7 +362,7 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from } } -void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) +void Switch::onLocalEthernet(void *tPtr,const SharedPtr &network,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) { if (!network->hasConfig()) return; @@ -474,7 +474,7 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c adv[42] = (checksum >> 8) & 0xff; adv[43] = checksum & 0xff; - RR->node->putFrame(network->id(),network->userPtr(),peerMac,from,ZT_ETHERTYPE_IPV6,0,adv,72); + RR->node->putFrame(tPtr,network->id(),network->userPtr(),peerMac,from,ZT_ETHERTYPE_IPV6,0,adv,72); return; // NDP emulation done. We have forged a "fake" reply, so no need to send actual NDP query. } // else no NDP emulation } // else no NDP emulation @@ -491,17 +491,18 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c * multicast addresses on bridge interfaces and subscribing each slave. * But in that case this does no harm, as the sets are just merged. */ if (fromBridged) - network->learnBridgedMulticastGroup(multicastGroup,RR->node->now()); + network->learnBridgedMulticastGroup(tPtr,multicastGroup,RR->node->now()); //TRACE("%.16llx: MULTICAST %s -> %s %s %u",network->id(),from.toString().c_str(),multicastGroup.toString().c_str(),etherTypeName(etherType),len); // First pass sets noTee to false, but noTee is set to true in OutboundMulticast to prevent duplicates. - if (!network->filterOutgoingPacket(false,RR->identity.address(),Address(),from,to,(const uint8_t *)data,len,etherType,vlanId)) { + if (!network->filterOutgoingPacket(tPtr,false,RR->identity.address(),Address(),from,to,(const uint8_t *)data,len,etherType,vlanId)) { TRACE("%.16llx: %s -> %s %s packet not sent: filterOutgoingPacket() returned false",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType)); return; } RR->mc->send( + tPtr, network->config().multicastLimit, RR->node->now(), network->id(), @@ -514,14 +515,14 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c len); } else if (to == network->mac()) { // Destination is this node, so just reinject it - RR->node->putFrame(network->id(),network->userPtr(),from,to,etherType,vlanId,data,len); + RR->node->putFrame(tPtr,network->id(),network->userPtr(),from,to,etherType,vlanId,data,len); } else if (to[0] == MAC::firstOctetForNetwork(network->id())) { // Destination is another ZeroTier peer on the same network Address toZT(to.toAddress(network->id())); // since in-network MACs are derived from addresses and network IDs, we can reverse this - SharedPtr toPeer(RR->topology->getPeer(toZT)); + SharedPtr toPeer(RR->topology->getPeer(tPtr,toZT)); - if (!network->filterOutgoingPacket(false,RR->identity.address(),toZT,from,to,(const uint8_t *)data,len,etherType,vlanId)) { + if (!network->filterOutgoingPacket(tPtr,false,RR->identity.address(),toZT,from,to,(const uint8_t *)data,len,etherType,vlanId)) { TRACE("%.16llx: %s -> %s %s packet not sent: filterOutgoingPacket() returned false",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType)); return; } @@ -536,7 +537,7 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c outp.append(data,len); if (!network->config().disableCompression()) outp.compress(); - send(outp,true); + send(tPtr,outp,true); } else { Packet outp(toZT,RR->identity.address(),Packet::VERB_FRAME); outp.append(network->id()); @@ -544,7 +545,7 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c outp.append(data,len); if (!network->config().disableCompression()) outp.compress(); - send(outp,true); + send(tPtr,outp,true); } //TRACE("%.16llx: UNICAST: %s -> %s etherType==%s(%.4x) vlanId==%u len==%u fromBridged==%d includeCom==%d",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType),etherType,vlanId,len,(int)fromBridged,(int)includeCom); @@ -554,7 +555,7 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c // We filter with a NULL destination ZeroTier address first. Filtrations // for each ZT destination are also done below. This is the same rationale // and design as for multicast. - if (!network->filterOutgoingPacket(false,RR->identity.address(),Address(),from,to,(const uint8_t *)data,len,etherType,vlanId)) { + if (!network->filterOutgoingPacket(tPtr,false,RR->identity.address(),Address(),from,to,(const uint8_t *)data,len,etherType,vlanId)) { TRACE("%.16llx: %s -> %s %s packet not sent: filterOutgoingPacket() returned false",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType)); return; } @@ -592,7 +593,7 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c } for(unsigned int b=0;bfilterOutgoingPacket(true,RR->identity.address(),bridges[b],from,to,(const uint8_t *)data,len,etherType,vlanId)) { + if (network->filterOutgoingPacket(tPtr,true,RR->identity.address(),bridges[b],from,to,(const uint8_t *)data,len,etherType,vlanId)) { Packet outp(bridges[b],RR->identity.address(),Packet::VERB_EXT_FRAME); outp.append(network->id()); outp.append((uint8_t)0x00); @@ -602,7 +603,7 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c outp.append(data,len); if (!network->config().disableCompression()) outp.compress(); - send(outp,true); + send(tPtr,outp,true); } else { TRACE("%.16llx: %s -> %s %s packet not sent: filterOutgoingPacket() returned false",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType)); } @@ -610,20 +611,20 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c } } -void Switch::send(Packet &packet,bool encrypt) +void Switch::send(void *tPtr,Packet &packet,bool encrypt) { if (packet.destination() == RR->identity.address()) { TRACE("BUG: caught attempt to send() to self, ignored"); return; } - if (!_trySend(packet,encrypt)) { + if (!_trySend(tPtr,packet,encrypt)) { Mutex::Lock _l(_txQueue_m); _txQueue.push_back(TXQueueEntry(packet.destination(),RR->node->now(),packet,encrypt)); } } -void Switch::requestWhois(const Address &addr) +void Switch::requestWhois(void *tPtr,const Address &addr) { #ifdef ZT_TRACE if (addr == RR->identity.address()) { @@ -644,10 +645,10 @@ void Switch::requestWhois(const Address &addr) } } if (inserted) - _sendWhoisRequest(addr,(const Address *)0,0); + _sendWhoisRequest(tPtr,addr,(const Address *)0,0); } -void Switch::doAnythingWaitingForPeer(const SharedPtr &peer) +void Switch::doAnythingWaitingForPeer(void *tPtr,const SharedPtr &peer) { { // cancel pending WHOIS since we now know this peer Mutex::Lock _l(_outstandingWhoisRequests_m); @@ -660,7 +661,7 @@ void Switch::doAnythingWaitingForPeer(const SharedPtr &peer) while (i) { RXQueueEntry *rq = &(_rxQueue[--i]); if ((rq->timestamp)&&(rq->complete)) { - if (rq->frag0.tryDecode(RR)) + if (rq->frag0.tryDecode(RR,tPtr)) rq->timestamp = 0; } } @@ -670,7 +671,7 @@ void Switch::doAnythingWaitingForPeer(const SharedPtr &peer) Mutex::Lock _l(_txQueue_m); for(std::list< TXQueueEntry >::iterator txi(_txQueue.begin());txi!=_txQueue.end();) { if (txi->dest == peer->address()) { - if (_trySend(txi->packet,txi->encrypt)) + if (_trySend(tPtr,txi->packet,txi->encrypt)) _txQueue.erase(txi++); else ++txi; } else ++txi; @@ -678,7 +679,7 @@ void Switch::doAnythingWaitingForPeer(const SharedPtr &peer) } } -unsigned long Switch::doTimerTasks(uint64_t now) +unsigned long Switch::doTimerTasks(void *tPtr,uint64_t now) { unsigned long nextDelay = 0xffffffff; // ceiling delay, caller will cap to minimum @@ -695,7 +696,7 @@ unsigned long Switch::doTimerTasks(uint64_t now) _outstandingWhoisRequests.erase(*a); } else { r->lastSent = now; - r->peersConsulted[r->retries] = _sendWhoisRequest(*a,r->peersConsulted,(r->retries > 1) ? r->retries : 0); + r->peersConsulted[r->retries] = _sendWhoisRequest(tPtr,*a,r->peersConsulted,(r->retries > 1) ? r->retries : 0); TRACE("WHOIS %s (retry %u)",a->toString().c_str(),r->retries); ++r->retries; nextDelay = std::min(nextDelay,(unsigned long)ZT_WHOIS_RETRY_DELAY); @@ -709,7 +710,7 @@ unsigned long Switch::doTimerTasks(uint64_t now) { // Time out TX queue packets that never got WHOIS lookups or other info. Mutex::Lock _l(_txQueue_m); for(std::list< TXQueueEntry >::iterator txi(_txQueue.begin());txi!=_txQueue.end();) { - if (_trySend(txi->packet,txi->encrypt)) + if (_trySend(tPtr,txi->packet,txi->encrypt)) _txQueue.erase(txi++); else if ((now - txi->creationTime) > ZT_TRANSMIT_QUEUE_TIMEOUT) { TRACE("TX %s -> %s timed out",txi->packet.source().toString().c_str(),txi->packet.destination().toString().c_str()); @@ -743,19 +744,19 @@ bool Switch::_shouldUnite(const uint64_t now,const Address &source,const Address return false; } -Address Switch::_sendWhoisRequest(const Address &addr,const Address *peersAlreadyConsulted,unsigned int numPeersAlreadyConsulted) +Address Switch::_sendWhoisRequest(void *tPtr,const Address &addr,const Address *peersAlreadyConsulted,unsigned int numPeersAlreadyConsulted) { SharedPtr upstream(RR->topology->getUpstreamPeer(peersAlreadyConsulted,numPeersAlreadyConsulted,false)); if (upstream) { Packet outp(upstream->address(),RR->identity.address(),Packet::VERB_WHOIS); addr.appendTo(outp); RR->node->expectReplyTo(outp.packetId()); - send(outp,true); + send(tPtr,outp,true); } return Address(); } -bool Switch::_trySend(Packet &packet,bool encrypt) +bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt) { SharedPtr viaPath; const uint64_t now = RR->node->now(); @@ -769,7 +770,7 @@ bool Switch::_trySend(Packet &packet,bool encrypt) clusterMostRecentMemberId = RR->cluster->checkSendViaCluster(destination,clusterMostRecentTs,clusterPeerSecret); #endif - const SharedPtr peer(RR->topology->getPeer(destination)); + const SharedPtr peer(RR->topology->getPeer(tPtr,destination)); if (peer) { /* First get the best path, and if it's dead (and this is not a root) * we attempt to re-activate that path but this packet will flow @@ -784,7 +785,7 @@ bool Switch::_trySend(Packet &packet,bool encrypt) if ((clusterMostRecentMemberId < 0)||(viaPath->lastIn() > clusterMostRecentTs)) { #endif if ((now - viaPath->lastOut()) > std::max((now - viaPath->lastIn()) * 4,(uint64_t)ZT_PATH_MIN_REACTIVATE_INTERVAL)) { - peer->attemptToContactAt(viaPath->localAddress(),viaPath->address(),now,false,viaPath->nextOutgoingCounter()); + peer->attemptToContactAt(tPtr,viaPath->localAddress(),viaPath->address(),now,false,viaPath->nextOutgoingCounter()); viaPath->sent(now); } #ifdef ZT_ENABLE_CLUSTER @@ -801,7 +802,7 @@ bool Switch::_trySend(Packet &packet,bool encrypt) #else if (!viaPath) { #endif - peer->tryMemorizedPath(now); // periodically attempt memorized or statically defined paths, if any are known + peer->tryMemorizedPath(tPtr,now); // periodically attempt memorized or statically defined paths, if any are known const SharedPtr relay(RR->topology->getUpstreamPeer()); if ( (!relay) || (!(viaPath = relay->getBestPath(now,false))) ) { if (!(viaPath = peer->getBestPath(now,true))) @@ -816,7 +817,7 @@ bool Switch::_trySend(Packet &packet,bool encrypt) #ifdef ZT_ENABLE_CLUSTER if (clusterMostRecentMemberId < 0) { #else - requestWhois(destination); + requestWhois(tPtr,destination); return false; // if we are not in cluster mode, there is no way we can send without knowing the peer directly #endif #ifdef ZT_ENABLE_CLUSTER @@ -844,9 +845,9 @@ bool Switch::_trySend(Packet &packet,bool encrypt) #endif #ifdef ZT_ENABLE_CLUSTER - if ( ((viaPath)&&(viaPath->send(RR,packet.data(),chunkSize,now))) || ((clusterMostRecentMemberId >= 0)&&(RR->cluster->sendViaCluster(clusterMostRecentMemberId,destination,packet.data(),chunkSize))) ) { + if ( ((viaPath)&&(viaPath->send(RR,tPtr,packet.data(),chunkSize,now))) || ((clusterMostRecentMemberId >= 0)&&(RR->cluster->sendViaCluster(clusterMostRecentMemberId,destination,packet.data(),chunkSize))) ) { #else - if (viaPath->send(RR,packet.data(),chunkSize,now)) { + if (viaPath->send(RR,tPtr,packet.data(),chunkSize,now)) { #endif if (chunkSize < packet.size()) { // Too big for one packet, fragment the rest @@ -866,7 +867,7 @@ bool Switch::_trySend(Packet &packet,bool encrypt) else if (clusterMostRecentMemberId >= 0) RR->cluster->sendViaCluster(clusterMostRecentMemberId,destination,frag.data(),frag.size()); #else - viaPath->send(RR,frag.data(),frag.size(),now); + viaPath->send(RR,tPtr,frag.data(),frag.size(),now); #endif fragStart += chunkSize; remaining -= chunkSize; diff --git a/node/Switch.hpp b/node/Switch.hpp index 9245c036..ff350934 100644 --- a/node/Switch.hpp +++ b/node/Switch.hpp @@ -59,16 +59,18 @@ public: /** * Called when a packet is received from the real network * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param localAddr Local interface address * @param fromAddr Internet IP address of origin * @param data Packet data * @param len Packet length */ - void onRemotePacket(const InetAddress &localAddr,const InetAddress &fromAddr,const void *data,unsigned int len); + void onRemotePacket(void *tPtr,const InetAddress &localAddr,const InetAddress &fromAddr,const void *data,unsigned int len); /** * Called when a packet comes from a local Ethernet tap * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param network Which network's TAP did this packet come from? * @param from Originating MAC address * @param to Destination MAC address @@ -77,7 +79,7 @@ public: * @param data Ethernet payload * @param len Frame length */ - void onLocalEthernet(const SharedPtr &network,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len); + void onLocalEthernet(void *tPtr,const SharedPtr &network,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len); /** * Send a packet to a ZeroTier address (destination in packet) @@ -91,26 +93,29 @@ public: * Needless to say, the packet's source must be this node. Otherwise it * won't be encrypted right. (This is not used for relaying.) * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param packet Packet to send (buffer may be modified) * @param encrypt Encrypt packet payload? (always true except for HELLO) */ - void send(Packet &packet,bool encrypt); + void send(void *tPtr,Packet &packet,bool encrypt); /** * Request WHOIS on a given address * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param addr Address to look up */ - void requestWhois(const Address &addr); + void requestWhois(void *tPtr,const Address &addr); /** * Run any processes that are waiting for this peer's identity * * Called when we learn of a peer's identity from HELLO, OK(WHOIS), etc. * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param peer New peer */ - void doAnythingWaitingForPeer(const SharedPtr &peer); + void doAnythingWaitingForPeer(void *tPtr,const SharedPtr &peer); /** * Perform retries and other periodic timer tasks @@ -118,15 +123,16 @@ public: * This can return a very long delay if there are no pending timer * tasks. The caller should cap this comparatively vs. other values. * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param now Current time * @return Number of milliseconds until doTimerTasks() should be run again */ - unsigned long doTimerTasks(uint64_t now); + unsigned long doTimerTasks(void *tPtr,uint64_t now); private: bool _shouldUnite(const uint64_t now,const Address &source,const Address &destination); - Address _sendWhoisRequest(const Address &addr,const Address *peersAlreadyConsulted,unsigned int numPeersAlreadyConsulted); - bool _trySend(Packet &packet,bool encrypt); // packet is modified if return is true + Address _sendWhoisRequest(void *tPtr,const Address &addr,const Address *peersAlreadyConsulted,unsigned int numPeersAlreadyConsulted); + bool _trySend(void *tPtr,Packet &packet,bool encrypt); // packet is modified if return is true const RuntimeEnvironment *const RR; uint64_t _lastBeaconResponse; diff --git a/node/Tag.cpp b/node/Tag.cpp index eb4026bc..3f924da1 100644 --- a/node/Tag.cpp +++ b/node/Tag.cpp @@ -25,13 +25,13 @@ namespace ZeroTier { -int Tag::verify(const RuntimeEnvironment *RR) const +int Tag::verify(const RuntimeEnvironment *RR,void *tPtr) const { if ((!_signedBy)||(_signedBy != Network::controllerFor(_networkId))) return -1; - const Identity id(RR->topology->getIdentity(_signedBy)); + const Identity id(RR->topology->getIdentity(tPtr,_signedBy)); if (!id) { - RR->sw->requestWhois(_signedBy); + RR->sw->requestWhois(tPtr,_signedBy); return 1; } try { diff --git a/node/Tag.hpp b/node/Tag.hpp index 146e8da9..38085906 100644 --- a/node/Tag.hpp +++ b/node/Tag.hpp @@ -105,9 +105,10 @@ public: * Check this tag's signature * * @param RR Runtime environment to allow identity lookup for signedBy + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or tag */ - int verify(const RuntimeEnvironment *RR) const; + int verify(const RuntimeEnvironment *RR,void *tPtr) const; template inline void serialize(Buffer &b,const bool forSign = false) const diff --git a/node/Topology.cpp b/node/Topology.cpp index 21547cd2..a1d37332 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -55,19 +55,19 @@ namespace ZeroTier { #define ZT_DEFAULT_WORLD_LENGTH 634 static const unsigned char ZT_DEFAULT_WORLD[ZT_DEFAULT_WORLD_LENGTH] = {0x01,0x00,0x00,0x00,0x00,0x08,0xea,0xc9,0x0a,0x00,0x00,0x01,0x52,0x3c,0x32,0x50,0x1a,0xb8,0xb3,0x88,0xa4,0x69,0x22,0x14,0x91,0xaa,0x9a,0xcd,0x66,0xcc,0x76,0x4c,0xde,0xfd,0x56,0x03,0x9f,0x10,0x67,0xae,0x15,0xe6,0x9c,0x6f,0xb4,0x2d,0x7b,0x55,0x33,0x0e,0x3f,0xda,0xac,0x52,0x9c,0x07,0x92,0xfd,0x73,0x40,0xa6,0xaa,0x21,0xab,0xa8,0xa4,0x89,0xfd,0xae,0xa4,0x4a,0x39,0xbf,0x2d,0x00,0x65,0x9a,0xc9,0xc8,0x18,0xeb,0x4a,0xf7,0x86,0xa8,0x40,0xd6,0x52,0xea,0xae,0x9e,0x7a,0xbf,0x4c,0x97,0x66,0xab,0x2d,0x6f,0xaf,0xc9,0x2b,0x3a,0xff,0xed,0xd6,0x30,0x3e,0xc4,0x6a,0x65,0xf2,0xbd,0x83,0x52,0xf5,0x40,0xe9,0xcc,0x0d,0x6e,0x89,0x3f,0x9a,0xa0,0xb8,0xdf,0x42,0xd2,0x2f,0x84,0xe6,0x03,0x26,0x0f,0xa8,0xe3,0xcc,0x05,0x05,0x03,0xef,0x12,0x80,0x0d,0xce,0x3e,0xb6,0x58,0x3b,0x1f,0xa8,0xad,0xc7,0x25,0xf9,0x43,0x71,0xa7,0x5c,0x9a,0xc7,0xe1,0xa3,0xb8,0x88,0xd0,0x71,0x6c,0x94,0x99,0x73,0x41,0x0b,0x1b,0x48,0x84,0x02,0x9d,0x21,0x90,0x39,0xf3,0x00,0x01,0xf0,0x92,0x2a,0x98,0xe3,0xb3,0x4e,0xbc,0xbf,0xf3,0x33,0x26,0x9d,0xc2,0x65,0xd7,0xa0,0x20,0xaa,0xb6,0x9d,0x72,0xbe,0x4d,0x4a,0xcc,0x9c,0x8c,0x92,0x94,0x78,0x57,0x71,0x25,0x6c,0xd1,0xd9,0x42,0xa9,0x0d,0x1b,0xd1,0xd2,0xdc,0xa3,0xea,0x84,0xef,0x7d,0x85,0xaf,0xe6,0x61,0x1f,0xb4,0x3f,0xf0,0xb7,0x41,0x26,0xd9,0x0a,0x6e,0x00,0x0c,0x04,0xbc,0xa6,0x5e,0xb1,0x27,0x09,0x06,0x2a,0x03,0xb0,0xc0,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x7d,0x00,0x01,0x27,0x09,0x04,0x9a,0x42,0xc5,0x21,0x27,0x09,0x06,0x2c,0x0f,0xf8,0x50,0x01,0x54,0x01,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x27,0x09,0x04,0x9f,0xcb,0x61,0xab,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x08,0x00,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,0x54,0x60,0x01,0x27,0x09,0x04,0xa9,0x39,0x8f,0x68,0x27,0x09,0x06,0x26,0x07,0xf0,0xd0,0x1d,0x01,0x00,0x57,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x27,0x09,0x04,0x6b,0xaa,0xc5,0x0e,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x00,0x01,0x00,0x20,0x00,0x00,0x00,0x00,0x02,0x00,0xe0,0x01,0x27,0x09,0x04,0x80,0xc7,0xc5,0xd9,0x27,0x09,0x06,0x24,0x00,0x61,0x80,0x00,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0xb7,0x40,0x01,0x27,0x09,0x88,0x41,0x40,0x8a,0x2e,0x00,0xbb,0x1d,0x31,0xf2,0xc3,0x23,0xe2,0x64,0xe9,0xe6,0x41,0x72,0xc1,0xa7,0x4f,0x77,0x89,0x95,0x55,0xed,0x10,0x75,0x1c,0xd5,0x6e,0x86,0x40,0x5c,0xde,0x11,0x8d,0x02,0xdf,0xfe,0x55,0x5d,0x46,0x2c,0xcf,0x6a,0x85,0xb5,0x63,0x1c,0x12,0x35,0x0c,0x8d,0x5d,0xc4,0x09,0xba,0x10,0xb9,0x02,0x5d,0x0f,0x44,0x5c,0xf4,0x49,0xd9,0x2b,0x1c,0x00,0x0c,0x04,0x2d,0x20,0xc6,0x82,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x64,0x00,0x81,0xc3,0x54,0x00,0x00,0xff,0xfe,0x18,0x1d,0x61,0x27,0x09,0x04,0x2e,0x65,0xa0,0xf9,0x27,0x09,0x06,0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x6a,0x30,0x01,0x27,0x09,0x04,0x6b,0xbf,0x2e,0xd2,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x68,0x00,0x83,0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0x27,0x09,0x04,0x2d,0x20,0xf6,0xb3,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x58,0x00,0x8b,0xf8,0x54,0x00,0x00,0xff,0xfe,0x15,0xb3,0x9a,0x27,0x09,0x04,0x2d,0x20,0xf8,0x57,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x70,0x00,0x9b,0xc9,0x54,0x00,0x00,0xff,0xfe,0x15,0xc4,0xf5,0x27,0x09,0x04,0x9f,0xcb,0x02,0x9a,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x0c,0xad,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x26,0x70,0x01,0x27,0x09}; -Topology::Topology(const RuntimeEnvironment *renv) : +Topology::Topology(const RuntimeEnvironment *renv,void *tPtr) : RR(renv), _trustedPathCount(0), _amRoot(false) { try { World cachedPlanet; - std::string buf(RR->node->dataStoreGet("planet")); + std::string buf(RR->node->dataStoreGet(tPtr,"planet")); if (buf.length() > 0) { Buffer dswtmp(buf.data(),(unsigned int)buf.length()); cachedPlanet.deserialize(dswtmp,0); } - addWorld(cachedPlanet,false); + addWorld(tPtr,cachedPlanet,false); } catch ( ... ) {} World defaultPlanet; @@ -75,10 +75,10 @@ Topology::Topology(const RuntimeEnvironment *renv) : Buffer wtmp(ZT_DEFAULT_WORLD,ZT_DEFAULT_WORLD_LENGTH); defaultPlanet.deserialize(wtmp,0); // throws on error, which would indicate a bad static variable up top } - addWorld(defaultPlanet,false); + addWorld(tPtr,defaultPlanet,false); } -SharedPtr Topology::addPeer(const SharedPtr &peer) +SharedPtr Topology::addPeer(void *tPtr,const SharedPtr &peer) { #ifdef ZT_TRACE if ((!peer)||(peer->address() == RR->identity.address())) { @@ -98,12 +98,12 @@ SharedPtr Topology::addPeer(const SharedPtr &peer) np = hp; } - saveIdentity(np->identity()); + saveIdentity(tPtr,np->identity()); return np; } -SharedPtr Topology::getPeer(const Address &zta) +SharedPtr Topology::getPeer(void *tPtr,const Address &zta) { if (zta == RR->identity.address()) { TRACE("BUG: ignored attempt to getPeer() for self, returned NULL"); @@ -118,7 +118,7 @@ SharedPtr Topology::getPeer(const Address &zta) } try { - Identity id(_getIdentity(zta)); + Identity id(_getIdentity(tPtr,zta)); if (id) { SharedPtr np(new Peer(RR,RR->identity,id)); { @@ -134,7 +134,7 @@ SharedPtr Topology::getPeer(const Address &zta) return SharedPtr(); } -Identity Topology::getIdentity(const Address &zta) +Identity Topology::getIdentity(void *tPtr,const Address &zta) { if (zta == RR->identity.address()) { return RR->identity; @@ -144,15 +144,15 @@ Identity Topology::getIdentity(const Address &zta) if (ap) return (*ap)->identity(); } - return _getIdentity(zta); + return _getIdentity(tPtr,zta); } -void Topology::saveIdentity(const Identity &id) +void Topology::saveIdentity(void *tPtr,const Identity &id) { if (id) { char p[128]; Utils::snprintf(p,sizeof(p),"iddb.d/%.10llx",(unsigned long long)id.address().toInt()); - RR->node->dataStorePut(p,id.toString(false),false); + RR->node->dataStorePut(tPtr,p,id.toString(false),false); } } @@ -264,7 +264,7 @@ bool Topology::isProhibitedEndpoint(const Address &ztaddr,const InetAddress &ipa return false; } -bool Topology::addWorld(const World &newWorld,bool alwaysAcceptNew) +bool Topology::addWorld(void *tPtr,const World &newWorld,bool alwaysAcceptNew) { if ((newWorld.type() != World::TYPE_PLANET)&&(newWorld.type() != World::TYPE_MOON)) return false; @@ -328,29 +328,29 @@ bool Topology::addWorld(const World &newWorld,bool alwaysAcceptNew) try { Buffer dswtmp; existing->serialize(dswtmp,false); - RR->node->dataStorePut(savePath,dswtmp.data(),dswtmp.size(),false); + RR->node->dataStorePut(tPtr,savePath,dswtmp.data(),dswtmp.size(),false); } catch ( ... ) { - RR->node->dataStoreDelete(savePath); + RR->node->dataStoreDelete(tPtr,savePath); } - _memoizeUpstreams(); + _memoizeUpstreams(tPtr); return true; } -void Topology::addMoon(const uint64_t id,const Address &seed) +void Topology::addMoon(void *tPtr,const uint64_t id,const Address &seed) { char savePath[64]; Utils::snprintf(savePath,sizeof(savePath),"moons.d/%.16llx.moon",id); try { - std::string moonBin(RR->node->dataStoreGet(savePath)); + std::string moonBin(RR->node->dataStoreGet(tPtr,savePath)); if (moonBin.length() > 1) { Buffer wtmp(moonBin.data(),(unsigned int)moonBin.length()); World w; w.deserialize(wtmp); if ((w.type() == World::TYPE_MOON)&&(w.id() == id)) { - addWorld(w,true); + addWorld(tPtr,w,true); return; } } @@ -363,7 +363,7 @@ void Topology::addMoon(const uint64_t id,const Address &seed) } } -void Topology::removeMoon(const uint64_t id) +void Topology::removeMoon(void *tPtr,const uint64_t id) { Mutex::Lock _l1(_upstreams_m); Mutex::Lock _l2(_peers_m); @@ -375,7 +375,7 @@ void Topology::removeMoon(const uint64_t id) } else { char savePath[64]; Utils::snprintf(savePath,sizeof(savePath),"moons.d/%.16llx.moon",id); - RR->node->dataStoreDelete(savePath); + RR->node->dataStoreDelete(tPtr,savePath); } } _moons.swap(nm); @@ -387,7 +387,7 @@ void Topology::removeMoon(const uint64_t id) } _moonSeeds.swap(cm); - _memoizeUpstreams(); + _memoizeUpstreams(tPtr); } void Topology::clean(uint64_t now) @@ -415,11 +415,11 @@ void Topology::clean(uint64_t now) } } -Identity Topology::_getIdentity(const Address &zta) +Identity Topology::_getIdentity(void *tPtr,const Address &zta) { char p[128]; Utils::snprintf(p,sizeof(p),"iddb.d/%.10llx",(unsigned long long)zta.toInt()); - std::string ids(RR->node->dataStoreGet(p)); + std::string ids(RR->node->dataStoreGet(tPtr,p)); if (ids.length() > 0) { try { return Identity(ids); @@ -428,7 +428,7 @@ Identity Topology::_getIdentity(const Address &zta) return Identity(); } -void Topology::_memoizeUpstreams() +void Topology::_memoizeUpstreams(void *tPtr) { // assumes _upstreams_m and _peers_m are locked _upstreamAddresses.clear(); @@ -442,7 +442,7 @@ void Topology::_memoizeUpstreams() SharedPtr &hp = _peers[i->identity.address()]; if (!hp) { hp = new Peer(RR,RR->identity,i->identity); - saveIdentity(i->identity); + saveIdentity(tPtr,i->identity); } } } @@ -456,7 +456,7 @@ void Topology::_memoizeUpstreams() SharedPtr &hp = _peers[i->identity.address()]; if (!hp) { hp = new Peer(RR,RR->identity,i->identity); - saveIdentity(i->identity); + saveIdentity(tPtr,i->identity); } } } diff --git a/node/Topology.hpp b/node/Topology.hpp index e21747c8..4870ab5e 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -50,7 +50,7 @@ class RuntimeEnvironment; class Topology { public: - Topology(const RuntimeEnvironment *renv); + Topology(const RuntimeEnvironment *renv,void *tPtr); /** * Add a peer to database @@ -58,18 +58,20 @@ public: * This will not replace existing peers. In that case the existing peer * record is returned. * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param peer Peer to add * @return New or existing peer (should replace 'peer') */ - SharedPtr addPeer(const SharedPtr &peer); + SharedPtr addPeer(void *tPtr,const SharedPtr &peer); /** * Get a peer from its address * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param zta ZeroTier address of peer * @return Peer or NULL if not found */ - SharedPtr getPeer(const Address &zta); + SharedPtr getPeer(void *tPtr,const Address &zta); /** * Get a peer only if it is presently in memory (no disk cache) @@ -109,10 +111,11 @@ public: /** * Get the identity of a peer * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param zta ZeroTier address of peer * @return Identity or NULL Identity if not found */ - Identity getIdentity(const Address &zta); + Identity getIdentity(void *tPtr,const Address &zta); /** * Cache an identity @@ -120,9 +123,10 @@ public: * This is done automatically on addPeer(), and so is only useful for * cluster identity replication. * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param id Identity to cache */ - void saveIdentity(const Identity &id); + void saveIdentity(void *tPtr,const Identity &id); /** * Get the current best upstream peer @@ -267,11 +271,12 @@ public: /** * Validate new world and update if newer and signature is okay * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param newWorld A new or updated planet or moon to learn * @param alwaysAcceptNew If true, always accept new moons even if we're not waiting for one * @return True if it was valid and newer than current (or totally new for moons) */ - bool addWorld(const World &newWorld,bool alwaysAcceptNew); + bool addWorld(void *tPtr,const World &newWorld,bool alwaysAcceptNew); /** * Add a moon @@ -282,14 +287,15 @@ public: * @param id Moon ID * @param seed If non-NULL, an address of any member of the moon to contact */ - void addMoon(const uint64_t id,const Address &seed); + void addMoon(void *tPtr,const uint64_t id,const Address &seed); /** * Remove a moon * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param id Moon's world ID */ - void removeMoon(const uint64_t id); + void removeMoon(void *tPtr,const uint64_t id); /** * Clean and flush database @@ -420,8 +426,8 @@ public: } private: - Identity _getIdentity(const Address &zta); - void _memoizeUpstreams(); + Identity _getIdentity(void *tPtr,const Address &zta); + void _memoizeUpstreams(void *tPtr); const RuntimeEnvironment *const RR; diff --git a/osdep/BSDEthernetTap.cpp b/osdep/BSDEthernetTap.cpp index 0e1ada6b..62fabc48 100644 --- a/osdep/BSDEthernetTap.cpp +++ b/osdep/BSDEthernetTap.cpp @@ -71,7 +71,7 @@ BSDEthernetTap::BSDEthernetTap( unsigned int metric, uint64_t nwid, const char *friendlyName, - void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), + void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), void *arg) : _handler(handler), _arg(arg), @@ -460,8 +460,7 @@ void BSDEthernetTap::threadMain() to.setTo(getBuf,6); from.setTo(getBuf + 6,6); unsigned int etherType = ntohs(((const uint16_t *)getBuf)[6]); - // TODO: VLAN support - _handler(_arg,_nwid,from,to,etherType,0,(const void *)(getBuf + 14),r - 14); + _handler(_arg,(void *)0,_nwid,from,to,etherType,0,(const void *)(getBuf + 14),r - 14); } r = 0; diff --git a/osdep/BSDEthernetTap.hpp b/osdep/BSDEthernetTap.hpp index 1bb48d31..8c6314db 100644 --- a/osdep/BSDEthernetTap.hpp +++ b/osdep/BSDEthernetTap.hpp @@ -43,7 +43,7 @@ public: unsigned int metric, uint64_t nwid, const char *friendlyName, - void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), + void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), void *arg); ~BSDEthernetTap(); @@ -62,7 +62,7 @@ public: throw(); private: - void (*_handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int); + 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; diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index e7fe657f..c4b978e7 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -62,7 +62,7 @@ LinuxEthernetTap::LinuxEthernetTap( unsigned int metric, uint64_t nwid, const char *friendlyName, - void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), + void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), void *arg) : _handler(handler), _arg(arg), @@ -470,7 +470,7 @@ void LinuxEthernetTap::threadMain() from.setTo(getBuf + 6,6); unsigned int etherType = ntohs(((const uint16_t *)getBuf)[6]); // TODO: VLAN support - _handler(_arg,_nwid,from,to,etherType,0,(const void *)(getBuf + 14),r - 14); + _handler(_arg,(void *)0,_nwid,from,to,etherType,0,(const void *)(getBuf + 14),r - 14); } r = 0; diff --git a/osdep/LinuxEthernetTap.hpp b/osdep/LinuxEthernetTap.hpp index 7dd7e01d..a2a00a79 100644 --- a/osdep/LinuxEthernetTap.hpp +++ b/osdep/LinuxEthernetTap.hpp @@ -44,7 +44,7 @@ public: unsigned int metric, uint64_t nwid, const char *friendlyName, - void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), + void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), void *arg); ~LinuxEthernetTap(); @@ -66,7 +66,7 @@ public: throw(); private: - void (*_handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int); + 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; diff --git a/osdep/OSXEthernetTap.cpp b/osdep/OSXEthernetTap.cpp index b3580929..35eac05a 100644 --- a/osdep/OSXEthernetTap.cpp +++ b/osdep/OSXEthernetTap.cpp @@ -314,7 +314,7 @@ OSXEthernetTap::OSXEthernetTap( unsigned int metric, uint64_t nwid, const char *friendlyName, - void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *data,unsigned int len), + void (*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), @@ -646,7 +646,7 @@ void OSXEthernetTap::threadMain() from.setTo(getBuf + 6,6); unsigned int etherType = ntohs(((const uint16_t *)getBuf)[6]); // TODO: VLAN support - _handler(_arg,_nwid,from,to,etherType,0,(const void *)(getBuf + 14),r - 14); + _handler(_arg,(void *)0,_nwid,from,to,etherType,0,(const void *)(getBuf + 14),r - 14); } r = 0; diff --git a/osdep/OSXEthernetTap.hpp b/osdep/OSXEthernetTap.hpp index de48f9a4..5a96c210 100644 --- a/osdep/OSXEthernetTap.hpp +++ b/osdep/OSXEthernetTap.hpp @@ -48,7 +48,7 @@ public: unsigned int metric, uint64_t nwid, const char *friendlyName, - void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), + void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), void *arg); ~OSXEthernetTap(); @@ -67,7 +67,7 @@ public: throw(); private: - void (*_handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int); + 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; diff --git a/osdep/WindowsEthernetTap.cpp b/osdep/WindowsEthernetTap.cpp index 8ee088bb..79b9d35e 100644 --- a/osdep/WindowsEthernetTap.cpp +++ b/osdep/WindowsEthernetTap.cpp @@ -456,7 +456,7 @@ WindowsEthernetTap::WindowsEthernetTap( unsigned int metric, uint64_t nwid, const char *friendlyName, - void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), + void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), void *arg) : _handler(handler), _arg(arg), @@ -1058,8 +1058,7 @@ void WindowsEthernetTap::threadMain() MAC from(tapReadBuf + 6,6); unsigned int etherType = ((((unsigned int)tapReadBuf[12]) & 0xff) << 8) | (((unsigned int)tapReadBuf[13]) & 0xff); try { - // TODO: decode vlans - _handler(_arg,_nwid,from,to,etherType,0,tapReadBuf + 14,bytesRead - 14); + _handler(_arg,(void *)0,_nwid,from,to,etherType,0,tapReadBuf + 14,bytesRead - 14); } catch ( ... ) {} // handlers should not throw } } diff --git a/osdep/WindowsEthernetTap.hpp b/osdep/WindowsEthernetTap.hpp index 53bba3e9..f2cf73f3 100644 --- a/osdep/WindowsEthernetTap.hpp +++ b/osdep/WindowsEthernetTap.hpp @@ -87,7 +87,7 @@ public: unsigned int metric, uint64_t nwid, const char *friendlyName, - void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), + void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), void *arg); ~WindowsEthernetTap(); @@ -118,7 +118,7 @@ private: void _setRegistryIPv4Value(const char *regKey,const std::vector &value); void _syncIps(); - void (*_handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int); + void (*_handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int); void *_arg; MAC _mac; uint64_t _nwid; diff --git a/service/OneService.cpp b/service/OneService.cpp index 22eefbb9..c07b3ba4 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -291,21 +291,21 @@ static void _moonToJson(nlohmann::json &mj,const World &world) class OneServiceImpl; -static int SnodeVirtualNetworkConfigFunction(ZT_Node *node,void *uptr,uint64_t nwid,void **nuptr,enum ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nwconf); -static void SnodeEventCallback(ZT_Node *node,void *uptr,enum ZT_Event event,const void *metaData); -static long SnodeDataStoreGetFunction(ZT_Node *node,void *uptr,const char *name,void *buf,unsigned long bufSize,unsigned long readIndex,unsigned long *totalSize); -static int SnodeDataStorePutFunction(ZT_Node *node,void *uptr,const char *name,const void *data,unsigned long len,int secure); -static int SnodeWirePacketSendFunction(ZT_Node *node,void *uptr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl); -static void SnodeVirtualNetworkFrameFunction(ZT_Node *node,void *uptr,uint64_t nwid,void **nuptr,uint64_t sourceMac,uint64_t destMac,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len); -static int SnodePathCheckFunction(ZT_Node *node,void *uptr,uint64_t ztaddr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *remoteAddr); -static int SnodePathLookupFunction(ZT_Node *node,void *uptr,uint64_t ztaddr,int family,struct sockaddr_storage *result); +static int SnodeVirtualNetworkConfigFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t nwid,void **nuptr,enum ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nwconf); +static void SnodeEventCallback(ZT_Node *node,void *uptr,void *tptr,enum ZT_Event event,const void *metaData); +static long SnodeDataStoreGetFunction(ZT_Node *node,void *uptr,void *tptr,const char *name,void *buf,unsigned long bufSize,unsigned long readIndex,unsigned long *totalSize); +static int SnodeDataStorePutFunction(ZT_Node *node,void *uptr,void *tptr,const char *name,const void *data,unsigned long len,int secure); +static int SnodeWirePacketSendFunction(ZT_Node *node,void *uptr,void *tptr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl); +static void SnodeVirtualNetworkFrameFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t nwid,void **nuptr,uint64_t sourceMac,uint64_t destMac,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len); +static int SnodePathCheckFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t ztaddr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *remoteAddr); +static int SnodePathLookupFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t ztaddr,int family,struct sockaddr_storage *result); #ifdef ZT_ENABLE_CLUSTER static void SclusterSendFunction(void *uptr,unsigned int toMemberId,const void *data,unsigned int len); static int SclusterGeoIpFunction(void *uptr,const struct sockaddr_storage *addr,int *x,int *y,int *z); #endif -static void StapFrameHandler(void *uptr,uint64_t nwid,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len); +static void StapFrameHandler(void *uptr,void *tptr,uint64_t nwid,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len); static int ShttpOnMessageBegin(http_parser *parser); static int ShttpOnUrl(http_parser *parser,const char *ptr,size_t length); @@ -573,7 +573,7 @@ public: cb.eventCallback = SnodeEventCallback; cb.pathCheckFunction = SnodePathCheckFunction; cb.pathLookupFunction = SnodePathLookupFunction; - _node = new Node(this,&cb,OSUtils::now()); + _node = new Node(this,(void *)0,&cb,OSUtils::now()); } // Read local configuration @@ -804,7 +804,7 @@ public: for(std::vector::iterator f(networksDotD.begin());f!=networksDotD.end();++f) { std::size_t dot = f->find_last_of('.'); if ((dot == 16)&&(f->substr(16) == ".conf")) - _node->join(Utils::hexStrToU64(f->substr(0,dot).c_str()),(void *)0); + _node->join(Utils::hexStrToU64(f->substr(0,dot).c_str()),(void *)0,(void *)0); } } { // Load existing moons @@ -812,7 +812,7 @@ public: for(std::vector::iterator f(moonsDotD.begin());f!=moonsDotD.end();++f) { std::size_t dot = f->find_last_of('.'); if ((dot == 16)&&(f->substr(16) == ".moon")) - _node->orbit(Utils::hexStrToU64(f->substr(0,dot).c_str()),0); + _node->orbit((void *)0,Utils::hexStrToU64(f->substr(0,dot).c_str()),0); } } @@ -877,7 +877,7 @@ public: uint64_t dl = _nextBackgroundTaskDeadline; if (dl <= now) { - _node->processBackgroundTasks(now,&_nextBackgroundTaskDeadline); + _node->processBackgroundTasks((void *)0,now,&_nextBackgroundTaskDeadline); dl = _nextBackgroundTaskDeadline; } @@ -892,7 +892,7 @@ public: std::vector added,removed; n->second.tap->scanMulticastGroups(added,removed); for(std::vector::iterator m(added.begin());m!=added.end();++m) - _node->multicastSubscribe(n->first,m->mac().toInt(),m->adi()); + _node->multicastSubscribe((void *)0,n->first,m->mac().toInt(),m->adi()); for(std::vector::iterator m(removed.begin());m!=removed.end();++m) _node->multicastUnsubscribe(n->first,m->mac().toInt(),m->adi()); } @@ -1306,7 +1306,7 @@ public: res["signature"] = json(); res["updatesMustBeSignedBy"] = json(); res["waiting"] = true; - _node->orbit(id,seed); + _node->orbit((void *)0,id,seed); scode = 200; } @@ -1315,7 +1315,7 @@ public: if (ps.size() == 2) { uint64_t wantnw = Utils::hexStrToU64(ps[1].c_str()); - _node->join(wantnw,(void *)0); // does nothing if we are a member + _node->join(wantnw,(void *)0,(void *)0); // does nothing if we are a member ZT_VirtualNetworkList *nws = _node->networks(); if (nws) { for(unsigned long i=0;inetworkCount;++i) { @@ -1360,7 +1360,7 @@ public: if (ps[0] == "moon") { if (ps.size() == 2) { - _node->deorbit(Utils::hexStrToU64(ps[1].c_str())); + _node->deorbit((void *)0,Utils::hexStrToU64(ps[1].c_str())); res["result"] = true; scode = 200; } // else 404 @@ -1371,7 +1371,7 @@ public: uint64_t wantnw = Utils::hexStrToU64(ps[1].c_str()); for(unsigned long i=0;inetworkCount;++i) { if (nws->networks[i].nwid == wantnw) { - _node->leave(wantnw,(void **)0); + _node->leave(wantnw,(void **)0,(void *)0); res["result"] = true; scode = 200; break; @@ -1693,6 +1693,7 @@ public: _lastDirectReceiveFromGlobal = OSUtils::now(); const ZT_ResultCode rc = _node->processWirePacket( + (void *)0, OSUtils::now(), reinterpret_cast(localAddr), (const struct sockaddr_storage *)from, // Phy<> uses sockaddr_storage, so it'll always be that big @@ -1845,6 +1846,7 @@ public: if (from) { InetAddress fakeTcpLocalInterfaceAddress((uint32_t)0xffffffff,0xffff); const ZT_ResultCode rc = _node->processWirePacket( + (void *)0, OSUtils::now(), reinterpret_cast(&fakeTcpLocalInterfaceAddress), reinterpret_cast(&from), @@ -2255,7 +2257,7 @@ public: inline void tapFrameHandler(uint64_t nwid,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) { - _node->processVirtualNetworkFrame(OSUtils::now(),nwid,from.toInt(),to.toInt(),etherType,vlanId,data,len,&_nextBackgroundTaskDeadline); + _node->processVirtualNetworkFrame((void *)0,OSUtils::now(),nwid,from.toInt(),to.toInt(),etherType,vlanId,data,len,&_nextBackgroundTaskDeadline); } inline void onHttpRequestToServer(TcpConnection *tc) @@ -2426,21 +2428,21 @@ public: } }; -static int SnodeVirtualNetworkConfigFunction(ZT_Node *node,void *uptr,uint64_t nwid,void **nuptr,enum ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nwconf) +static int SnodeVirtualNetworkConfigFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t nwid,void **nuptr,enum ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nwconf) { return reinterpret_cast(uptr)->nodeVirtualNetworkConfigFunction(nwid,nuptr,op,nwconf); } -static void SnodeEventCallback(ZT_Node *node,void *uptr,enum ZT_Event event,const void *metaData) +static void SnodeEventCallback(ZT_Node *node,void *uptr,void *tptr,enum ZT_Event event,const void *metaData) { reinterpret_cast(uptr)->nodeEventCallback(event,metaData); } -static long SnodeDataStoreGetFunction(ZT_Node *node,void *uptr,const char *name,void *buf,unsigned long bufSize,unsigned long readIndex,unsigned long *totalSize) +static long SnodeDataStoreGetFunction(ZT_Node *node,void *uptr,void *tptr,const char *name,void *buf,unsigned long bufSize,unsigned long readIndex,unsigned long *totalSize) { return reinterpret_cast(uptr)->nodeDataStoreGetFunction(name,buf,bufSize,readIndex,totalSize); } -static int SnodeDataStorePutFunction(ZT_Node *node,void *uptr,const char *name,const void *data,unsigned long len,int secure) +static int SnodeDataStorePutFunction(ZT_Node *node,void *uptr,void *tptr,const char *name,const void *data,unsigned long len,int secure) { return reinterpret_cast(uptr)->nodeDataStorePutFunction(name,data,len,secure); } -static int SnodeWirePacketSendFunction(ZT_Node *node,void *uptr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl) +static int SnodeWirePacketSendFunction(ZT_Node *node,void *uptr,void *tptr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl) { return reinterpret_cast(uptr)->nodeWirePacketSendFunction(localAddr,addr,data,len,ttl); } -static void SnodeVirtualNetworkFrameFunction(ZT_Node *node,void *uptr,uint64_t nwid,void **nuptr,uint64_t sourceMac,uint64_t destMac,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) +static void SnodeVirtualNetworkFrameFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t nwid,void **nuptr,uint64_t sourceMac,uint64_t destMac,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) { reinterpret_cast(uptr)->nodeVirtualNetworkFrameFunction(nwid,nuptr,sourceMac,destMac,etherType,vlanId,data,len); } -static int SnodePathCheckFunction(ZT_Node *node,void *uptr,uint64_t ztaddr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *remoteAddr) +static int SnodePathCheckFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t ztaddr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *remoteAddr) { return reinterpret_cast(uptr)->nodePathCheckFunction(ztaddr,localAddr,remoteAddr); } -static int SnodePathLookupFunction(ZT_Node *node,void *uptr,uint64_t ztaddr,int family,struct sockaddr_storage *result) +static int SnodePathLookupFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t ztaddr,int family,struct sockaddr_storage *result) { return reinterpret_cast(uptr)->nodePathLookupFunction(ztaddr,family,result); } #ifdef ZT_ENABLE_CLUSTER @@ -2458,7 +2460,7 @@ static int SclusterGeoIpFunction(void *uptr,const struct sockaddr_storage *addr, } #endif -static void StapFrameHandler(void *uptr,uint64_t nwid,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) +static void StapFrameHandler(void *uptr,void *tptr,uint64_t nwid,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) { reinterpret_cast(uptr)->tapFrameHandler(nwid,from,to,etherType,vlanId,data,len); } static int ShttpOnMessageBegin(http_parser *parser) diff --git a/service/SoftwareUpdater.cpp b/service/SoftwareUpdater.cpp index 7ecd42b1..7ec377cc 100644 --- a/service/SoftwareUpdater.cpp +++ b/service/SoftwareUpdater.cpp @@ -175,7 +175,7 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void std::string lj; lj.push_back((char)VERB_LATEST); lj.append(OSUtils::jsonDump(*latest)); - _node.sendUserMessage(origin,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,lj.data(),(unsigned int)lj.length()); + _node.sendUserMessage((void *)0,origin,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,lj.data(),(unsigned int)lj.length()); if (_distLog) { fprintf(_distLog,"%.10llx GET_LATEST %u.%u.%u_%u platform %u arch %u vendor %u channel %s -> LATEST %u.%u.%u_%u" ZT_EOL_S,(unsigned long long)origin,rvMaj,rvMin,rvRev,rvBld,rvPlatform,rvArch,rvVendor,rvChannel.c_str(),bestVMaj,bestVMin,bestVRev,bestVBld); fflush(_distLog); @@ -205,7 +205,7 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void gd.append((uint8_t)VERB_GET_DATA); gd.append(_downloadHashPrefix.data,16); gd.append((uint32_t)_download.length()); - _node.sendUserMessage(ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,gd.data(),gd.size()); + _node.sendUserMessage((void *)0,ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,gd.data(),gd.size()); //printf(">> GET_DATA @%u\n",(unsigned int)_download.length()); } } @@ -229,7 +229,7 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void buf.append(reinterpret_cast(data) + 1,16); buf.append((uint32_t)idx); buf.append(d->second.bin.data() + idx,std::min((unsigned long)ZT_SOFTWARE_UPDATE_CHUNK_SIZE,(unsigned long)(d->second.bin.length() - idx))); - _node.sendUserMessage(origin,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,buf.data(),buf.size()); + _node.sendUserMessage((void *)0,origin,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,buf.data(),buf.size()); //printf(">> DATA @%u\n",(unsigned int)idx); } } @@ -249,7 +249,7 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void gd.append((uint8_t)VERB_GET_DATA); gd.append(_downloadHashPrefix.data,16); gd.append((uint32_t)_download.length()); - _node.sendUserMessage(ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,gd.data(),gd.size()); + _node.sendUserMessage((void *)0,ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,gd.data(),gd.size()); //printf(">> GET_DATA @%u\n",(unsigned int)_download.length()); } } @@ -296,7 +296,7 @@ bool SoftwareUpdater::check(const uint64_t now) ZT_BUILD_ARCHITECTURE, (int)ZT_VENDOR_ZEROTIER, _channel.c_str()); - _node.sendUserMessage(ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,tmp,len); + _node.sendUserMessage((void *)0,ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,tmp,len); //printf(">> GET_LATEST\n"); } @@ -343,7 +343,7 @@ bool SoftwareUpdater::check(const uint64_t now) gd.append((uint8_t)VERB_GET_DATA); gd.append(_downloadHashPrefix.data,16); gd.append((uint32_t)_download.length()); - _node.sendUserMessage(ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,gd.data(),gd.size()); + _node.sendUserMessage((void *)0,ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,gd.data(),gd.size()); //printf(">> GET_DATA @%u\n",(unsigned int)_download.length()); } } -- cgit v1.2.3 From bc61357a44cf4906dda2b30c4474ae891982e620 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 18 Apr 2017 17:37:44 -0700 Subject: HTTP backend support for JSONDB --- controller/EmbeddedNetworkController.cpp | 2 - controller/JSONDB.cpp | 161 ++++++++++++++++++++++--------- controller/JSONDB.hpp | 12 +-- osdep/Http.hpp | 33 +++++++ service/OneService.cpp | 24 ++++- 5 files changed, 175 insertions(+), 57 deletions(-) (limited to 'service/OneService.cpp') diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index 0884deda..597bc9c9 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -434,8 +434,6 @@ EmbeddedNetworkController::EmbeddedNetworkController(Node *node,const char *dbPa _db(dbPath), _node(node) { - OSUtils::mkdir(dbPath); - OSUtils::lockDownFile(dbPath,true); // networks might contain auth tokens, etc., so restrict directory permissions } EmbeddedNetworkController::~EmbeddedNetworkController() diff --git a/controller/JSONDB.cpp b/controller/JSONDB.cpp index 756664eb..afc0631d 100644 --- a/controller/JSONDB.cpp +++ b/controller/JSONDB.cpp @@ -18,43 +18,67 @@ #include "JSONDB.hpp" +#define ZT_JSONDB_HTTP_TIMEOUT 60000 + namespace ZeroTier { static const nlohmann::json _EMPTY_JSON(nlohmann::json::object()); +static const std::map _ZT_JSONDB_GET_HEADERS; + +JSONDB::JSONDB(const std::string &basePath) : + _basePath(basePath) +{ + if ((_basePath.length() > 7)&&(_basePath.substr(0,7) == "http://")) { + // TODO: this doesn't yet support IPv6 since bracketed address notiation isn't supported. + // Typically it's used with 127.0.0.1 anyway. + std::string hn = _basePath.substr(7); + std::size_t hnend = hn.find_first_of('/'); + if (hnend != std::string::npos) + hn = hn.substr(0,hnend); + std::size_t hnsep = hn.find_last_of(':'); + if (hnsep != std::string::npos) + hn[hnsep] = '/'; + _httpAddr.fromString(hn); + if (hnend != std::string::npos) + _basePath = _basePath.substr(7 + hnend); + if (_basePath.length() == 0) + _basePath = "/"; + if (_basePath[0] != '/') + _basePath = std::string("/") + _basePath; + } else { + OSUtils::mkdir(_basePath.c_str()); + OSUtils::lockDownFile(_basePath.c_str(),true); // networks might contain auth tokens, etc., so restrict directory permissions + } + _reload(_basePath,std::string()); +} bool JSONDB::writeRaw(const std::string &n,const std::string &obj) { if (!_isValidObjectName(n)) return false; - - const std::string path(_genPath(n,true)); - if (!path.length()) - return false; - - const std::string buf(obj); - if (!OSUtils::writeFile(path.c_str(),buf)) - return false; - - return true; + if (_httpAddr) { + std::map headers; + std::string body; + std::map reqHeaders; + char tmp[64]; + Utils::snprintf(tmp,sizeof(tmp),"%lu",(unsigned long)obj.length()); + reqHeaders["Content-Length"] = tmp; + reqHeaders["Content-Type"] = "application/json"; + const unsigned int sc = Http::PUT(1048576,ZT_JSONDB_HTTP_TIMEOUT,reinterpret_cast(&_httpAddr),(_basePath+"/"+n).c_str(),reqHeaders,obj.data(),obj.length(),headers,body); + return (sc == 200); + } else { + const std::string path(_genPath(n,true)); + if (!path.length()) + return false; + return OSUtils::writeFile(path.c_str(),obj); + } } bool JSONDB::put(const std::string &n,const nlohmann::json &obj) { - if (!_isValidObjectName(n)) - return false; - - const std::string path(_genPath(n,true)); - if (!path.length()) - return false; - - const std::string buf(OSUtils::jsonDump(obj)); - if (!OSUtils::writeFile(path.c_str(),buf)) - return false; - - _E &e = _db[n]; - e.obj = obj; - - return true; + const bool r = writeRaw(n,OSUtils::jsonDump(obj)); + _db[n].obj = obj; + return r; } const nlohmann::json &JSONDB::get(const std::string &n) @@ -66,22 +90,28 @@ const nlohmann::json &JSONDB::get(const std::string &n) if (e != _db.end()) return e->second.obj; - const std::string path(_genPath(n,false)); - if (!path.length()) - return _EMPTY_JSON; std::string buf; - if (!OSUtils::readFile(path.c_str(),buf)) - return _EMPTY_JSON; + if (_httpAddr) { + std::map headers; + const unsigned int sc = Http::GET(1048576,ZT_JSONDB_HTTP_TIMEOUT,reinterpret_cast(&_httpAddr),(_basePath+"/"+n).c_str(),_ZT_JSONDB_GET_HEADERS,headers,buf); + if (sc != 200) + return _EMPTY_JSON; + } else { + const std::string path(_genPath(n,false)); + if (!path.length()) + return _EMPTY_JSON; + if (!OSUtils::readFile(path.c_str(),buf)) + return _EMPTY_JSON; + } - _E &e2 = _db[n]; try { + _E &e2 = _db[n]; e2.obj = OSUtils::jsonParse(buf); + return e2.obj; } catch ( ... ) { - e2.obj = _EMPTY_JSON; - buf = "{}"; + _db.erase(n); + return _EMPTY_JSON; } - - return e2.obj; } void JSONDB::erase(const std::string &n) @@ -89,23 +119,50 @@ void JSONDB::erase(const std::string &n) if (!_isValidObjectName(n)) return; - std::string path(_genPath(n,true)); - if (!path.length()) - return; + if (_httpAddr) { + std::string body; + std::map headers; + Http::DEL(1048576,ZT_JSONDB_HTTP_TIMEOUT,reinterpret_cast(&_httpAddr),(_basePath+"/"+n).c_str(),_ZT_JSONDB_GET_HEADERS,headers,body); + } else { + std::string path(_genPath(n,true)); + if (!path.length()) + return; + OSUtils::rm(path.c_str()); + } - OSUtils::rm(path.c_str()); _db.erase(n); } void JSONDB::_reload(const std::string &p,const std::string &b) { - std::vector dl(OSUtils::listDirectory(p.c_str(),true)); - for(std::vector::const_iterator di(dl.begin());di!=dl.end();++di) { - printf("%s\n",di->c_str()); - if ((di->length() > 5)&&(di->substr(di->length() - 5) == ".json")) { - this->get(b + di->substr(0,di->length() - 5)); - } else { - this->_reload((p + ZT_PATH_SEPARATOR + *di),(b + *di + ZT_PATH_SEPARATOR)); + if (_httpAddr) { + std::string body; + std::map headers; + const unsigned int sc = Http::GET(2147483647,ZT_JSONDB_HTTP_TIMEOUT,reinterpret_cast(&_httpAddr),_basePath.c_str(),_ZT_JSONDB_GET_HEADERS,headers,body); + if (sc == 200) { + try { + nlohmann::json dbImg(OSUtils::jsonParse(body)); + std::string tmp; + if (dbImg.is_object()) { + for(nlohmann::json::iterator i(dbImg.begin());i!=dbImg.end();++i) { + if (i.value().is_object()) { + tmp = i.key(); + _db[tmp].obj = i.value(); + } + } + } + } catch ( ... ) { + // TODO: report error? + } + } + } else { + std::vector dl(OSUtils::listDirectory(p.c_str(),true)); + for(std::vector::const_iterator di(dl.begin());di!=dl.end();++di) { + if ((di->length() > 5)&&(di->substr(di->length() - 5) == ".json")) { + this->get(b + di->substr(0,di->length() - 5)); + } else { + this->_reload((p + ZT_PATH_SEPARATOR + *di),(b + *di + ZT_PATH_SEPARATOR)); + } } } } @@ -130,15 +187,23 @@ std::string JSONDB::_genPath(const std::string &n,bool create) if (pt.size() == 0) return std::string(); + char sep; + if (_httpAddr) { + sep = '/'; + create = false; + } else { + sep = ZT_PATH_SEPARATOR; + } + std::string p(_basePath); if (create) OSUtils::mkdir(p.c_str()); for(unsigned long i=0,j=(unsigned long)(pt.size()-1);i _db; }; diff --git a/osdep/Http.hpp b/osdep/Http.hpp index 1ecf4eec..e7d4d03e 100644 --- a/osdep/Http.hpp +++ b/osdep/Http.hpp @@ -135,6 +135,39 @@ public: responseBody); } + /** + * Make HTTP PUT request + * + * It is the responsibility of the caller to set all headers. With PUT, the + * Content-Length and Content-Type headers must be set or the PUT will not + * work. + * + * @return HTTP status code or 0 on error (responseBody will contain error message) + */ + static inline unsigned int PUT( + unsigned long maxResponseSize, + unsigned long timeout, + const struct sockaddr *remoteAddress, + const char *path, + const std::map &requestHeaders, + const void *postData, + unsigned long postDataLength, + std::map &responseHeaders, + std::string &responseBody) + { + return _do( + "PUT", + maxResponseSize, + timeout, + remoteAddress, + path, + requestHeaders, + postData, + postDataLength, + responseHeaders, + responseBody); + } + private: static unsigned int _do( const char *method, diff --git a/service/OneService.cpp b/service/OneService.cpp index c07b3ba4..5f2adfe3 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -381,6 +381,7 @@ public: const std::string _homePath; std::string _authToken; + std::string _controllerDbPath; EmbeddedNetworkController *_controller; Phy _phy; Node *_node; @@ -482,6 +483,7 @@ public: OneServiceImpl(const char *hp,unsigned int port) : _homePath((hp) ? hp : ".") + ,_controllerDbPath(_homePath + ZT_PATH_SEPARATOR_S ZT_CONTROLLER_DB_PATH) ,_controller((EmbeddedNetworkController *)0) ,_phy(this,false,true) ,_node((Node *)0) @@ -747,7 +749,7 @@ public: for(int i=0;i<3;++i) _portsBE[i] = Utils::hton((uint16_t)_ports[i]); - _controller = new EmbeddedNetworkController(_node,(_homePath + ZT_PATH_SEPARATOR_S ZT_CONTROLLER_DB_PATH).c_str()); + _controller = new EmbeddedNetworkController(_node,_controllerDbPath.c_str()); _node->setNetconfMaster((void *)_controller); #ifdef ZT_ENABLE_CLUSTER @@ -1522,6 +1524,26 @@ public: _allowManagementFrom.push_back(nw); } } + + json &controllerDbHttpHost = settings["controllerDbHttpHost"]; + json &controllerDbHttpPort = settings["controllerDbHttpPort"]; + json &controllerDbHttpPath = settings["controllerDbHttpPath"]; + if ((controllerDbHttpHost.is_string())&&(controllerDbHttpPort.is_number())) { + _controllerDbPath = "http://"; + _controllerDbPath.append(controllerDbHttpHost); + char dbp[128]; + Utils::snprintf(dbp,sizeof(dbp),"%d",(int)controllerDbHttpPort); + _controllerDbPath.push_back(':'); + _controllerDbPath.append(dbp); + if (controllerDbHttpPath.is_string()) { + std::string p = controllerDbHttpPath; + if ((p.length() == 0)||(p[0] != '/')) + _controllerDbPath.push_back('/'); + _controllerDbPath.append(p); + } else { + _controllerDbPath.push_back('/'); + } + } } // Checks if a managed IP or route target is allowed -- cgit v1.2.3 From ba0d73d102e09b6d60f1d677b1e5472a25c08d42 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 20 Apr 2017 10:21:40 -0700 Subject: Windows build fixes. --- controller/JSONDB.cpp | 2 +- service/OneService.cpp | 3 ++- windows/ZeroTierOne/ZeroTierOne.vcxproj | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'service/OneService.cpp') diff --git a/controller/JSONDB.cpp b/controller/JSONDB.cpp index afc0631d..007e0fec 100644 --- a/controller/JSONDB.cpp +++ b/controller/JSONDB.cpp @@ -64,7 +64,7 @@ bool JSONDB::writeRaw(const std::string &n,const std::string &obj) Utils::snprintf(tmp,sizeof(tmp),"%lu",(unsigned long)obj.length()); reqHeaders["Content-Length"] = tmp; reqHeaders["Content-Type"] = "application/json"; - const unsigned int sc = Http::PUT(1048576,ZT_JSONDB_HTTP_TIMEOUT,reinterpret_cast(&_httpAddr),(_basePath+"/"+n).c_str(),reqHeaders,obj.data(),obj.length(),headers,body); + const unsigned int sc = Http::PUT(1048576,ZT_JSONDB_HTTP_TIMEOUT,reinterpret_cast(&_httpAddr),(_basePath+"/"+n).c_str(),reqHeaders,obj.data(),(unsigned long)obj.length(),headers,body); return (sc == 200); } else { const std::string path(_genPath(n,true)); diff --git a/service/OneService.cpp b/service/OneService.cpp index 5f2adfe3..a9185eea 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1530,7 +1530,8 @@ public: json &controllerDbHttpPath = settings["controllerDbHttpPath"]; if ((controllerDbHttpHost.is_string())&&(controllerDbHttpPort.is_number())) { _controllerDbPath = "http://"; - _controllerDbPath.append(controllerDbHttpHost); + std::string h = controllerDbHttpHost; + _controllerDbPath.append(h); char dbp[128]; Utils::snprintf(dbp,sizeof(dbp),"%d",(int)controllerDbHttpPort); _controllerDbPath.push_back(':'); diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj b/windows/ZeroTierOne/ZeroTierOne.vcxproj index 96de5d2b..9715f3d9 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj @@ -360,12 +360,13 @@ STATICLIB;ZT_SALSA20_SSE;ZT_USE_MINIUPNPC;MINIUPNP_STATICLIB;WIN32;NOMINMAX;ZT_SOFTWARE_UPDATE_DEFAULT="apply";ZT_BUILD_PLATFORM=2;ZT_BUILD_ARCHITECTURE=1;%(PreprocessorDefinitions) MultiThreaded - NoExtensions + StreamingSIMDExtensions2 true AnySuitable Speed true 4996 + Guard true -- cgit v1.2.3 From 8542ee59db85e4cb86c1b6fc9ac2330f24129de4 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 21 Apr 2017 12:42:51 -0700 Subject: Windows crash fix. --- service/OneService.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index a9185eea..b151d25d 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -988,7 +988,7 @@ public: std::map::const_iterator n(_nets.find(nwid)); if (n == _nets.end()) return false; - memcpy(&settings,&(n->second.settings),sizeof(NetworkSettings)); + settings = n->second.settings; return true; } @@ -999,7 +999,7 @@ public: std::map::iterator n(_nets.find(nwid)); if (n == _nets.end()) return false; - memcpy(&(n->second.settings),&settings,sizeof(NetworkSettings)); + n->second.settings = settings; char nlcpath[256]; Utils::snprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_homePath.c_str(),nwid); -- cgit v1.2.3 From 72def658d0ad8dda1e1735f6b28a7a0ec0235c22 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 26 Apr 2017 08:42:49 -0700 Subject: Add a dummy Ethernet tap and a build option to enable it. --- make-linux.mk | 6 +- osdep/TestEthernetTap.hpp | 148 ++++++++++++++++++++++++++++++++++++++++++++++ service/OneService.cpp | 15 +++-- 3 files changed, 164 insertions(+), 5 deletions(-) create mode 100644 osdep/TestEthernetTap.hpp (limited to 'service/OneService.cpp') diff --git a/make-linux.mk b/make-linux.mk index b7967238..811d4a6e 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -54,7 +54,7 @@ ifeq ($(ZT_RULES_ENGINE_DEBUGGING),1) endif ifeq ($(ZT_DEBUG),1) - DEFS+=-DZT_TRACE + override DEFS+=-DZT_TRACE override CFLAGS+=-Wall -g -O -pthread $(INCLUDES) $(DEFS) override CXXFLAGS+=-Wall -g -O -std=c++11 -pthread $(INCLUDES) $(DEFS) override LDFLAGS+= @@ -72,6 +72,10 @@ else STRIP+=--strip-all endif +ifeq ($(ZT_USE_TEST_TAP),1) + override DEFS+=-DZT_USE_TEST_TAP +endif + # Uncomment for gprof profile build #CFLAGS=-Wall -g -pg -pthread $(INCLUDES) $(DEFS) #CXXFLAGS=-Wall -g -pg -pthread $(INCLUDES) $(DEFS) diff --git a/osdep/TestEthernetTap.hpp b/osdep/TestEthernetTap.hpp new file mode 100644 index 00000000..6c044a94 --- /dev/null +++ b/osdep/TestEthernetTap.hpp @@ -0,0 +1,148 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 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 . + */ + +#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" + +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]; + Utils::snprintf(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) + { + } + +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/service/OneService.cpp b/service/OneService.cpp index b151d25d..988e723d 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -89,14 +89,19 @@ using json = nlohmann::json; #include "../controller/EmbeddedNetworkController.hpp" -// Include the right tap device driver for this platform -- add new platforms here +#ifdef ZT_USE_TEST_TAP + +#include "../osdep/TestEthernetTap.hpp" +namespace ZeroTier { typedef TestEthernetTap EthernetTap; } + +#else + #ifdef ZT_SERVICE_NETCON -// In network containers builds, use the virtual netcon endpoint instead of a tun/tap port driver #include "../netcon/NetconEthernetTap.hpp" namespace ZeroTier { typedef NetconEthernetTap EthernetTap; } -#else // not ZT_SERVICE_NETCON so pick a tap driver +#else #ifdef __APPLE__ #include "../osdep/OSXEthernetTap.hpp" @@ -121,9 +126,11 @@ namespace ZeroTier { typedef BSDEthernetTap EthernetTap; } #endif // ZT_SERVICE_NETCON +#endif // ZT_USE_TEST_TAP + // Sanity limits for HTTP #define ZT_MAX_HTTP_MESSAGE_SIZE (1024 * 1024 * 64) -#define ZT_MAX_HTTP_CONNECTIONS 64 +#define ZT_MAX_HTTP_CONNECTIONS 65536 // Interface metric for ZeroTier taps -- this ensures that if we are on WiFi and also // bridged via ZeroTier to the same LAN traffic will (if the OS is sane) prefer WiFi. -- cgit v1.2.3 From 1b68d6dbdc5540e1b26b4ea35d019dde746af79e Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 27 Apr 2017 20:47:25 -0700 Subject: License header update. --- include/ZeroTierOne.h | 10 +++++++++- node/Address.hpp | 10 +++++++++- node/Array.hpp | 10 +++++++++- node/AtomicCounter.hpp | 10 +++++++++- node/Buffer.hpp | 10 +++++++++- node/C25519.cpp | 4 +--- node/C25519.hpp | 10 +++++++++- node/Capability.cpp | 10 +++++++++- node/Capability.hpp | 10 +++++++++- node/CertificateOfMembership.cpp | 10 +++++++++- node/CertificateOfMembership.hpp | 10 +++++++++- node/CertificateOfOwnership.cpp | 10 +++++++++- node/CertificateOfOwnership.hpp | 10 +++++++++- node/CertificateOfRepresentation.hpp | 10 +++++++++- node/Cluster.cpp | 10 +++++++++- node/Cluster.hpp | 10 +++++++++- node/Constants.hpp | 10 +++++++++- node/Credential.hpp | 10 +++++++++- node/Dictionary.hpp | 10 +++++++++- node/Hashtable.hpp | 10 +++++++++- node/Identity.cpp | 10 +++++++++- node/Identity.hpp | 10 +++++++++- node/IncomingPacket.cpp | 10 +++++++++- node/IncomingPacket.hpp | 10 +++++++++- node/InetAddress.cpp | 10 +++++++++- node/InetAddress.hpp | 10 +++++++++- node/MAC.hpp | 10 +++++++++- node/Membership.cpp | 10 +++++++++- node/Membership.hpp | 10 +++++++++- node/MulticastGroup.hpp | 10 +++++++++- node/Multicaster.cpp | 10 +++++++++- node/Multicaster.hpp | 10 +++++++++- node/Mutex.hpp | 10 +++++++++- node/Network.cpp | 10 +++++++++- node/Network.hpp | 10 +++++++++- node/NetworkConfig.cpp | 10 +++++++++- node/NetworkConfig.hpp | 10 +++++++++- node/NetworkController.hpp | 10 +++++++++- node/Node.cpp | 10 +++++++++- node/Node.hpp | 10 +++++++++- node/NonCopyable.hpp | 10 +++++++++- node/OutboundMulticast.cpp | 10 +++++++++- node/OutboundMulticast.hpp | 10 +++++++++- node/Packet.cpp | 10 +++++++++- node/Packet.hpp | 10 +++++++++- node/Path.cpp | 10 +++++++++- node/Path.hpp | 10 +++++++++- node/Peer.cpp | 10 +++++++++- node/Peer.hpp | 10 +++++++++- node/Poly1305.hpp | 10 +++++++++- node/Revocation.cpp | 10 +++++++++- node/Revocation.hpp | 10 +++++++++- node/RuntimeEnvironment.hpp | 10 +++++++++- node/SHA512.cpp | 35 +++++++---------------------------- node/SHA512.hpp | 10 +++++++++- node/SelfAwareness.cpp | 10 +++++++++- node/SelfAwareness.hpp | 10 +++++++++- node/SharedPtr.hpp | 10 +++++++++- node/Switch.cpp | 10 +++++++++- node/Switch.hpp | 10 +++++++++- node/Tag.cpp | 10 +++++++++- node/Tag.hpp | 10 +++++++++- node/Topology.cpp | 10 +++++++++- node/Topology.hpp | 10 +++++++++- node/Utils.cpp | 10 +++++++++- node/Utils.hpp | 10 +++++++++- node/World.hpp | 10 +++++++++- one.cpp | 10 +++++++++- osdep/Arp.cpp | 10 +++++++++- osdep/Arp.hpp | 10 +++++++++- osdep/BSDEthernetTap.cpp | 10 +++++++++- osdep/BSDEthernetTap.hpp | 10 +++++++++- osdep/Binder.hpp | 10 +++++++++- osdep/BlockingQueue.hpp | 10 +++++++++- osdep/Http.cpp | 10 +++++++++- osdep/Http.hpp | 10 +++++++++- osdep/LinuxEthernetTap.cpp | 10 +++++++++- osdep/LinuxEthernetTap.hpp | 10 +++++++++- osdep/ManagedRoute.cpp | 10 +++++++++- osdep/ManagedRoute.hpp | 26 ++++++++++++++++++++++++++ osdep/NeighborDiscovery.cpp | 10 +++++++++- osdep/NeighborDiscovery.hpp | 10 +++++++++- osdep/OSUtils.cpp | 10 +++++++++- osdep/OSUtils.hpp | 10 +++++++++- osdep/OSXEthernetTap.cpp | 10 +++++++++- osdep/OSXEthernetTap.hpp | 10 +++++++++- osdep/Phy.hpp | 10 +++++++++- osdep/PortMapper.cpp | 10 +++++++++- osdep/PortMapper.hpp | 10 +++++++++- osdep/TestEthernetTap.hpp | 10 +++++++++- osdep/Thread.hpp | 10 +++++++++- osdep/WindowsEthernetTap.cpp | 10 +++++++++- osdep/WindowsEthernetTap.hpp | 10 +++++++++- selftest.cpp | 10 +++++++++- service/ClusterDefinition.hpp | 10 +++++++++- service/ClusterGeoIpService.cpp | 10 +++++++++- service/ClusterGeoIpService.hpp | 10 +++++++++- service/OneService.cpp | 10 +++++++++- service/OneService.hpp | 10 +++++++++- service/SoftwareUpdater.cpp | 10 +++++++++- service/SoftwareUpdater.hpp | 10 +++++++++- version.h | 10 +++++++++- 102 files changed, 925 insertions(+), 130 deletions(-) (limited to 'service/OneService.cpp') diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 747e1855..20707a1d 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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. */ /* diff --git a/node/Address.hpp b/node/Address.hpp index 4a5883b0..9d2d1734 100644 --- a/node/Address.hpp +++ b/node/Address.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_ADDRESS_HPP diff --git a/node/Array.hpp b/node/Array.hpp index 19b29eb3..5c616475 100644 --- a/node/Array.hpp +++ b/node/Array.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_ARRAY_HPP diff --git a/node/AtomicCounter.hpp b/node/AtomicCounter.hpp index a0f29baa..e1864db8 100644 --- a/node/AtomicCounter.hpp +++ b/node/AtomicCounter.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_ATOMICCOUNTER_HPP diff --git a/node/Buffer.hpp b/node/Buffer.hpp index 37f39e7b..ae242c73 100644 --- a/node/Buffer.hpp +++ b/node/Buffer.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_BUFFER_HPP diff --git a/node/C25519.cpp b/node/C25519.cpp index e9ffecc1..a78e0466 100644 --- a/node/C25519.cpp +++ b/node/C25519.cpp @@ -1,5 +1,3 @@ -// Code taken from NaCl by D. J. Bernstein and others - /* Matthew Dempsky Public domain. @@ -7,7 +5,7 @@ Derived from public domain code by D. J. Bernstein. */ // Modified very slightly for ZeroTier One by Adam Ierymenko -// (no functional changes) +// This code remains in the public domain. #include #include diff --git a/node/C25519.hpp b/node/C25519.hpp index b19d9693..da9ba665 100644 --- a/node/C25519.hpp +++ b/node/C25519.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_C25519_HPP diff --git a/node/Capability.cpp b/node/Capability.cpp index c178e566..0e02025a 100644 --- a/node/Capability.cpp +++ b/node/Capability.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 "Capability.hpp" diff --git a/node/Capability.hpp b/node/Capability.hpp index 454723ac..8d4b9085 100644 --- a/node/Capability.hpp +++ b/node/Capability.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_CAPABILITY_HPP diff --git a/node/CertificateOfMembership.cpp b/node/CertificateOfMembership.cpp index 9bf70216..a5445e42 100644 --- a/node/CertificateOfMembership.cpp +++ b/node/CertificateOfMembership.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 "CertificateOfMembership.hpp" diff --git a/node/CertificateOfMembership.hpp b/node/CertificateOfMembership.hpp index dfccb138..739d5390 100644 --- a/node/CertificateOfMembership.hpp +++ b/node/CertificateOfMembership.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_CERTIFICATEOFMEMBERSHIP_HPP diff --git a/node/CertificateOfOwnership.cpp b/node/CertificateOfOwnership.cpp index 2bd181e0..31d0ae18 100644 --- a/node/CertificateOfOwnership.cpp +++ b/node/CertificateOfOwnership.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 "CertificateOfOwnership.hpp" diff --git a/node/CertificateOfOwnership.hpp b/node/CertificateOfOwnership.hpp index f01da38e..95039a2d 100644 --- a/node/CertificateOfOwnership.hpp +++ b/node/CertificateOfOwnership.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_CERTIFICATEOFOWNERSHIP_HPP diff --git a/node/CertificateOfRepresentation.hpp b/node/CertificateOfRepresentation.hpp index 710ee577..92a71bc0 100644 --- a/node/CertificateOfRepresentation.hpp +++ b/node/CertificateOfRepresentation.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_CERTIFICATEOFREPRESENTATION_HPP diff --git a/node/Cluster.cpp b/node/Cluster.cpp index 54206f99..4d2dea76 100644 --- a/node/Cluster.cpp +++ b/node/Cluster.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifdef ZT_ENABLE_CLUSTER diff --git a/node/Cluster.hpp b/node/Cluster.hpp index 08e32a99..74b091f5 100644 --- a/node/Cluster.hpp +++ b/node/Cluster.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_CLUSTER_HPP diff --git a/node/Constants.hpp b/node/Constants.hpp index 93184efa..d3c87491 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_CONSTANTS_HPP diff --git a/node/Credential.hpp b/node/Credential.hpp index 0ae2a0a8..bc81919b 100644 --- a/node/Credential.hpp +++ b/node/Credential.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_CREDENTIAL_HPP diff --git a/node/Dictionary.hpp b/node/Dictionary.hpp index 0db13b63..e212e453 100644 --- a/node/Dictionary.hpp +++ b/node/Dictionary.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_DICTIONARY_HPP diff --git a/node/Hashtable.hpp b/node/Hashtable.hpp index 66f2990a..c46ed68f 100644 --- a/node/Hashtable.hpp +++ b/node/Hashtable.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_HASHTABLE_HPP diff --git a/node/Identity.cpp b/node/Identity.cpp index d1b21e9c..ba77aa47 100644 --- a/node/Identity.cpp +++ b/node/Identity.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 diff --git a/node/Identity.hpp b/node/Identity.hpp index e4522732..b1c7d6f4 100644 --- a/node/Identity.hpp +++ b/node/Identity.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_IDENTITY_HPP diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 303160ec..126da53c 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 diff --git a/node/IncomingPacket.hpp b/node/IncomingPacket.hpp index 3d4a2e05..43a1ea10 100644 --- a/node/IncomingPacket.hpp +++ b/node/IncomingPacket.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_INCOMINGPACKET_HPP diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp index 7d22eeae..62bb8145 100644 --- a/node/InetAddress.cpp +++ b/node/InetAddress.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 diff --git a/node/InetAddress.hpp b/node/InetAddress.hpp index c37fa621..0975a9cf 100644 --- a/node/InetAddress.hpp +++ b/node/InetAddress.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_INETADDRESS_HPP diff --git a/node/MAC.hpp b/node/MAC.hpp index 95623f12..e7717d99 100644 --- a/node/MAC.hpp +++ b/node/MAC.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_MAC_HPP diff --git a/node/Membership.cpp b/node/Membership.cpp index 2d0471f1..466f9021 100644 --- a/node/Membership.cpp +++ b/node/Membership.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 diff --git a/node/Membership.hpp b/node/Membership.hpp index 0bc8f335..5e4475da 100644 --- a/node/Membership.hpp +++ b/node/Membership.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_MEMBERSHIP_HPP diff --git a/node/MulticastGroup.hpp b/node/MulticastGroup.hpp index be4e8084..4240db67 100644 --- a/node/MulticastGroup.hpp +++ b/node/MulticastGroup.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_MULTICASTGROUP_HPP diff --git a/node/Multicaster.cpp b/node/Multicaster.cpp index 8e534b5e..52213364 100644 --- a/node/Multicaster.cpp +++ b/node/Multicaster.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 diff --git a/node/Multicaster.hpp b/node/Multicaster.hpp index f646a5be..2186e9c3 100644 --- a/node/Multicaster.hpp +++ b/node/Multicaster.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_MULTICASTER_HPP diff --git a/node/Mutex.hpp b/node/Mutex.hpp index d451ede0..6f1d3471 100644 --- a/node/Mutex.hpp +++ b/node/Mutex.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_MUTEX_HPP diff --git a/node/Network.cpp b/node/Network.cpp index b7f25f7f..ee0f8611 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 diff --git a/node/Network.hpp b/node/Network.hpp index faef0fed..cce6c41f 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_NETWORK_HPP diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp index fe7393e8..9effe529 100644 --- a/node/NetworkConfig.cpp +++ b/node/NetworkConfig.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp index 85c24090..7bae6a91 100644 --- a/node/NetworkConfig.hpp +++ b/node/NetworkConfig.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_NETWORKCONFIG_HPP diff --git a/node/NetworkController.hpp b/node/NetworkController.hpp index 0634f435..63d44a46 100644 --- a/node/NetworkController.hpp +++ b/node/NetworkController.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_NETWORKCONFIGMASTER_HPP diff --git a/node/Node.cpp b/node/Node.cpp index ccbe9411..5848d953 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 diff --git a/node/Node.hpp b/node/Node.hpp index d25a619b..95587161 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_NODE_HPP diff --git a/node/NonCopyable.hpp b/node/NonCopyable.hpp index 6d4daa86..25c71b1c 100644 --- a/node/NonCopyable.hpp +++ b/node/NonCopyable.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_NONCOPYABLE_HPP__ diff --git a/node/OutboundMulticast.cpp b/node/OutboundMulticast.cpp index 285bfa5d..a2341ffd 100644 --- a/node/OutboundMulticast.cpp +++ b/node/OutboundMulticast.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include "Constants.hpp" diff --git a/node/OutboundMulticast.hpp b/node/OutboundMulticast.hpp index 0ecf113f..0c988804 100644 --- a/node/OutboundMulticast.hpp +++ b/node/OutboundMulticast.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_OUTBOUNDMULTICAST_HPP diff --git a/node/Packet.cpp b/node/Packet.cpp index 8a57dd55..d60a3a34 100644 --- a/node/Packet.cpp +++ b/node/Packet.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 diff --git a/node/Packet.hpp b/node/Packet.hpp index 8ad2c0f9..1de679e7 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_N_PACKET_HPP diff --git a/node/Path.cpp b/node/Path.cpp index 7366b56f..a5fe1aa7 100644 --- a/node/Path.cpp +++ b/node/Path.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 "Path.hpp" diff --git a/node/Path.hpp b/node/Path.hpp index aef628d4..32bceae0 100644 --- a/node/Path.hpp +++ b/node/Path.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_PATH_HPP diff --git a/node/Peer.cpp b/node/Peer.cpp index 2e9f6a2b..01905833 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 "../version.h" diff --git a/node/Peer.hpp b/node/Peer.hpp index b9d85404..9b57f23e 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_PEER_HPP diff --git a/node/Poly1305.hpp b/node/Poly1305.hpp index 62d57546..ff709983 100644 --- a/node/Poly1305.hpp +++ b/node/Poly1305.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_POLY1305_HPP diff --git a/node/Revocation.cpp b/node/Revocation.cpp index bab5653c..026058da 100644 --- a/node/Revocation.cpp +++ b/node/Revocation.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 "Revocation.hpp" diff --git a/node/Revocation.hpp b/node/Revocation.hpp index e5e013bd..e8f5d00d 100644 --- a/node/Revocation.hpp +++ b/node/Revocation.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_REVOCATION_HPP diff --git a/node/RuntimeEnvironment.hpp b/node/RuntimeEnvironment.hpp index 7ba1c989..d8e1d699 100644 --- a/node/RuntimeEnvironment.hpp +++ b/node/RuntimeEnvironment.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_RUNTIMEENVIRONMENT_HPP diff --git a/node/SHA512.cpp b/node/SHA512.cpp index 76737d37..c8d81dd1 100644 --- a/node/SHA512.cpp +++ b/node/SHA512.cpp @@ -1,20 +1,11 @@ +// Code taken from NaCl by D. J. Bernstein and others +// Public domain + /* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 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 . - */ +20080913 +D. J. Bernstein +Public domain. +*/ #include #include @@ -25,18 +16,6 @@ namespace ZeroTier { -////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - -// Code taken from NaCl by D. J. Bernstein and others -// Public domain - -/* -20080913 -D. J. Bernstein -Public domain. -*/ - #define uint64 uint64_t #ifdef ZT_NO_TYPE_PUNNING diff --git a/node/SHA512.hpp b/node/SHA512.hpp index 639a7dfd..584f8e11 100644 --- a/node/SHA512.hpp +++ b/node/SHA512.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_SHA512_HPP diff --git a/node/SelfAwareness.cpp b/node/SelfAwareness.cpp index cba84cdc..c5daddc3 100644 --- a/node/SelfAwareness.cpp +++ b/node/SelfAwareness.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 diff --git a/node/SelfAwareness.hpp b/node/SelfAwareness.hpp index c1db0c84..63c416bf 100644 --- a/node/SelfAwareness.hpp +++ b/node/SelfAwareness.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_SELFAWARENESS_HPP diff --git a/node/SharedPtr.hpp b/node/SharedPtr.hpp index 1dd3b43d..09010f67 100644 --- a/node/SharedPtr.hpp +++ b/node/SharedPtr.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_SHAREDPTR_HPP diff --git a/node/Switch.cpp b/node/Switch.cpp index 56299a9a..211b706a 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 diff --git a/node/Switch.hpp b/node/Switch.hpp index ff350934..9793dd45 100644 --- a/node/Switch.hpp +++ b/node/Switch.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_N_SWITCH_HPP diff --git a/node/Tag.cpp b/node/Tag.cpp index 3f924da1..39b17f2a 100644 --- a/node/Tag.cpp +++ b/node/Tag.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 "Tag.hpp" diff --git a/node/Tag.hpp b/node/Tag.hpp index 1f7f6835..746ade26 100644 --- a/node/Tag.hpp +++ b/node/Tag.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_TAG_HPP diff --git a/node/Topology.cpp b/node/Topology.cpp index a1d37332..80f4ed4e 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #include "Constants.hpp" diff --git a/node/Topology.hpp b/node/Topology.hpp index d29c424e..d06ba94b 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_TOPOLOGY_HPP diff --git a/node/Utils.cpp b/node/Utils.cpp index 9ce1bf05..d69e5335 100644 --- a/node/Utils.cpp +++ b/node/Utils.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 diff --git a/node/Utils.hpp b/node/Utils.hpp index ceb29d7e..25a90055 100644 --- a/node/Utils.hpp +++ b/node/Utils.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_UTILS_HPP diff --git a/node/World.hpp b/node/World.hpp index 6e835bec..003d70e3 100644 --- a/node/World.hpp +++ b/node/World.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_WORLD_HPP diff --git a/one.cpp b/one.cpp index b40e28fc..1f38361f 100644 --- a/one.cpp +++ b/one.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 diff --git a/osdep/Arp.cpp b/osdep/Arp.cpp index fcc122f0..c06f459b 100644 --- a/osdep/Arp.cpp +++ b/osdep/Arp.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 diff --git a/osdep/Arp.hpp b/osdep/Arp.hpp index 5f0d199a..e26fcdb3 100644 --- a/osdep/Arp.hpp +++ b/osdep/Arp.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_ARP_HPP diff --git a/osdep/BSDEthernetTap.cpp b/osdep/BSDEthernetTap.cpp index 62fabc48..87a9aece 100644 --- a/osdep/BSDEthernetTap.cpp +++ b/osdep/BSDEthernetTap.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 diff --git a/osdep/BSDEthernetTap.hpp b/osdep/BSDEthernetTap.hpp index 8c6314db..3cb9c10e 100644 --- a/osdep/BSDEthernetTap.hpp +++ b/osdep/BSDEthernetTap.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_BSDETHERNETTAP_HPP diff --git a/osdep/Binder.hpp b/osdep/Binder.hpp index 9829f170..ee832825 100644 --- a/osdep/Binder.hpp +++ b/osdep/Binder.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_BINDER_HPP diff --git a/osdep/BlockingQueue.hpp b/osdep/BlockingQueue.hpp index 6172f4da..34abcb67 100644 --- a/osdep/BlockingQueue.hpp +++ b/osdep/BlockingQueue.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_BLOCKINGQUEUE_HPP diff --git a/osdep/Http.cpp b/osdep/Http.cpp index 064ccd0c..d2540071 100644 --- a/osdep/Http.cpp +++ b/osdep/Http.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 diff --git a/osdep/Http.hpp b/osdep/Http.hpp index e7d4d03e..3f98d760 100644 --- a/osdep/Http.hpp +++ b/osdep/Http.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_HTTP_HPP diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index f74efc0a..2d3891e3 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 diff --git a/osdep/LinuxEthernetTap.hpp b/osdep/LinuxEthernetTap.hpp index a2a00a79..ab9d2370 100644 --- a/osdep/LinuxEthernetTap.hpp +++ b/osdep/LinuxEthernetTap.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_LINUXETHERNETTAP_HPP diff --git a/osdep/ManagedRoute.cpp b/osdep/ManagedRoute.cpp index 3a020d61..fca1c290 100644 --- a/osdep/ManagedRoute.cpp +++ b/osdep/ManagedRoute.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 "../node/Constants.hpp" diff --git a/osdep/ManagedRoute.hpp b/osdep/ManagedRoute.hpp index fd77a79a..849bddf5 100644 --- a/osdep/ManagedRoute.hpp +++ b/osdep/ManagedRoute.hpp @@ -1,3 +1,29 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + #ifndef ZT_MANAGEDROUTE_HPP #define ZT_MANAGEDROUTE_HPP diff --git a/osdep/NeighborDiscovery.cpp b/osdep/NeighborDiscovery.cpp index 4f636310..cd8b9b91 100644 --- a/osdep/NeighborDiscovery.cpp +++ b/osdep/NeighborDiscovery.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 "NeighborDiscovery.hpp" diff --git a/osdep/NeighborDiscovery.hpp b/osdep/NeighborDiscovery.hpp index 47831bda..2e7a68ba 100644 --- a/osdep/NeighborDiscovery.hpp +++ b/osdep/NeighborDiscovery.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_NEIGHBORDISCOVERY_HPP diff --git a/osdep/OSUtils.cpp b/osdep/OSUtils.cpp index fd5efed0..b7fce982 100644 --- a/osdep/OSUtils.cpp +++ b/osdep/OSUtils.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 diff --git a/osdep/OSUtils.hpp b/osdep/OSUtils.hpp index b84d5d2d..4b9ee893 100644 --- a/osdep/OSUtils.hpp +++ b/osdep/OSUtils.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_OSUTILS_HPP diff --git a/osdep/OSXEthernetTap.cpp b/osdep/OSXEthernetTap.cpp index f70908b8..53c9ba98 100644 --- a/osdep/OSXEthernetTap.cpp +++ b/osdep/OSXEthernetTap.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 diff --git a/osdep/OSXEthernetTap.hpp b/osdep/OSXEthernetTap.hpp index 5a96c210..ed7f39c3 100644 --- a/osdep/OSXEthernetTap.hpp +++ b/osdep/OSXEthernetTap.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_OSXETHERNETTAP_HPP diff --git a/osdep/Phy.hpp b/osdep/Phy.hpp index eab8a317..01a339e9 100644 --- a/osdep/Phy.hpp +++ b/osdep/Phy.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_PHY_HPP diff --git a/osdep/PortMapper.cpp b/osdep/PortMapper.cpp index d3a19384..99286172 100644 --- a/osdep/PortMapper.cpp +++ b/osdep/PortMapper.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifdef ZT_USE_MINIUPNPC diff --git a/osdep/PortMapper.hpp b/osdep/PortMapper.hpp index 0b8d15fc..61015a09 100644 --- a/osdep/PortMapper.hpp +++ b/osdep/PortMapper.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifdef ZT_USE_MINIUPNPC diff --git a/osdep/TestEthernetTap.hpp b/osdep/TestEthernetTap.hpp index 6c044a94..afd89541 100644 --- a/osdep/TestEthernetTap.hpp +++ b/osdep/TestEthernetTap.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 diff --git a/osdep/Thread.hpp b/osdep/Thread.hpp index 5423a8ab..a2f0919f 100644 --- a/osdep/Thread.hpp +++ b/osdep/Thread.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_THREAD_HPP diff --git a/osdep/WindowsEthernetTap.cpp b/osdep/WindowsEthernetTap.cpp index 79b9d35e..c37c7410 100644 --- a/osdep/WindowsEthernetTap.cpp +++ b/osdep/WindowsEthernetTap.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 diff --git a/osdep/WindowsEthernetTap.hpp b/osdep/WindowsEthernetTap.hpp index f2cf73f3..a3c1c0c3 100644 --- a/osdep/WindowsEthernetTap.hpp +++ b/osdep/WindowsEthernetTap.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_WINDOWSETHERNETTAP_HPP diff --git a/selftest.cpp b/selftest.cpp index e23afd6e..209fe203 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 diff --git a/service/ClusterDefinition.hpp b/service/ClusterDefinition.hpp index dda1a8c8..9947e46b 100644 --- a/service/ClusterDefinition.hpp +++ b/service/ClusterDefinition.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_CLUSTERDEFINITION_HPP diff --git a/service/ClusterGeoIpService.cpp b/service/ClusterGeoIpService.cpp index 89015c51..2dcc9179 100644 --- a/service/ClusterGeoIpService.cpp +++ b/service/ClusterGeoIpService.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifdef ZT_ENABLE_CLUSTER diff --git a/service/ClusterGeoIpService.hpp b/service/ClusterGeoIpService.hpp index ff2fcdb8..380f944f 100644 --- a/service/ClusterGeoIpService.hpp +++ b/service/ClusterGeoIpService.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. */ #ifndef ZT_CLUSTERGEOIPSERVICE_HPP diff --git a/service/OneService.cpp b/service/OneService.cpp index 988e723d..9f9cec0a 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 diff --git a/service/OneService.hpp b/service/OneService.hpp index 3390f2ac..f52cd40e 100644 --- a/service/OneService.hpp +++ b/service/OneService.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_ONESERVICE_HPP diff --git a/service/SoftwareUpdater.cpp b/service/SoftwareUpdater.cpp index 7ec377cc..d94beab5 100644 --- a/service/SoftwareUpdater.cpp +++ b/service/SoftwareUpdater.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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 diff --git a/service/SoftwareUpdater.hpp b/service/SoftwareUpdater.hpp index 4bb0ef51..ff3e36df 100644 --- a/service/SoftwareUpdater.hpp +++ b/service/SoftwareUpdater.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_SOFTWAREUPDATER_HPP diff --git a/version.h b/version.h index c51bfee2..b3b2fc81 100644 --- a/version.h +++ b/version.h @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +14,14 @@ * * 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_VERSION_H -- cgit v1.2.3 From 1f26cb98de307cd7838fa14c61bcf958a5a7bb1c Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Thu, 4 May 2017 15:26:44 -0700 Subject: updated OneService convenience functions for SDK --- service/OneService.cpp | 73 +++++++++++++++++++++++++++++++++++++++++++++----- service/OneService.hpp | 44 ++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 6 deletions(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 9f9cec0a..9bfb310b 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -104,11 +104,12 @@ namespace ZeroTier { typedef TestEthernetTap EthernetTap; } #else -#ifdef ZT_SERVICE_NETCON - -#include "../netcon/NetconEthernetTap.hpp" -namespace ZeroTier { typedef NetconEthernetTap EthernetTap; } - +#ifdef ZT_SDK + #include "../controller/EmbeddedNetworkController.hpp" + #include "../node/Node.hpp" + // Use the virtual netcon endpoint instead of a tun/tap port driver + #include "../src/SocketTap.hpp" + namespace ZeroTier { typedef SocketTap EthernetTap; } #else #ifdef __APPLE__ @@ -989,6 +990,62 @@ public: else return std::string(); } +#ifdef ZT_SDK + virtual void leave(const char *hp) + { + _node->leave(Utils::hexStrToU64(hp),NULL,NULL); + } + + virtual void join(const char *hp) + { + _node->join(Utils::hexStrToU64(hp),NULL,NULL); + } + + virtual std::string givenHomePath() + { + return _homePath; + } + + virtual EthernetTap * getTap(uint64_t nwid) + { + Mutex::Lock _l(_nets_m); + std::map::const_iterator n(_nets.find(nwid)); + if (n == _nets.end()) + return NULL; + return n->second.tap; + } + + virtual EthernetTap *getTap(InetAddress &addr) + { + Mutex::Lock _l(_nets_m); + std::map::iterator it; + for(it = _nets.begin(); it != _nets.end(); it++) { + if(it->second.tap) { + for(int j=0; jsecond.tap->_ips.size(); j++) { + if(it->second.tap->_ips[j].isEqualPrefix(addr) || it->second.tap->_ips[j].ipsEqual(addr)) { + return it->second.tap; + } + } + } + } + return NULL; + } + + virtual Node * getNode() + { + return _node; + } + + virtual void removeNets() + { + Mutex::Lock _l(_nets_m); + std::map::iterator i; + for(i = _nets.begin(); i != _nets.end(); i++) { + delete i->second.tap; + } + } +#endif // ZT_SDK + virtual void terminate() { _run_m.lock(); @@ -1158,9 +1215,11 @@ public: #else settings["portMappingEnabled"] = false; // not supported in build #endif +#ifndef ZT_SDK + settings["softwareUpdate"] = OSUtils::jsonString(settings["softwareUpdate"],ZT_SOFTWARE_UPDATE_DEFAULT); settings["softwareUpdateChannel"] = OSUtils::jsonString(settings["softwareUpdateChannel"],ZT_SOFTWARE_UPDATE_DEFAULT_CHANNEL); - +#endif const World planet(_node->planet()); res["planetWorldId"] = planet.id(); res["planetWorldTimestamp"] = planet.timestamp(); @@ -1508,6 +1567,7 @@ public: _primaryPort = (unsigned int)OSUtils::jsonInt(settings["primaryPort"],(uint64_t)_primaryPort) & 0xffff; _portMappingEnabled = OSUtils::jsonBool(settings["portMappingEnabled"],true); +#ifndef ZT_SDK const std::string up(OSUtils::jsonString(settings["softwareUpdate"],ZT_SOFTWARE_UPDATE_DEFAULT)); const bool udist = OSUtils::jsonBool(settings["softwareUpdateDist"],false); if (((up == "apply")||(up == "download"))||(udist)) { @@ -1521,6 +1581,7 @@ public: _updater = (SoftwareUpdater *)0; _updateAutoApply = false; } +#endif json &ignoreIfs = settings["interfacePrefixBlacklist"]; if (ignoreIfs.is_array()) { diff --git a/service/OneService.hpp b/service/OneService.hpp index f52cd40e..b770a3c0 100644 --- a/service/OneService.hpp +++ b/service/OneService.hpp @@ -32,6 +32,13 @@ #include "../node/InetAddress.hpp" +#ifdef ZT_SDK + #include "../node/Node.hpp" + // Use the virtual netcon endpoint instead of a tun/tap port driver + #include "../src/SocketTap.hpp" + namespace ZeroTier { typedef SocketTap EthernetTap; } +#endif + namespace ZeroTier { /** @@ -139,6 +146,43 @@ public: */ virtual std::string portDeviceName(uint64_t nwid) const = 0; +#ifdef ZT_SDK + /** + * Leaves a network + */ + virtual void leave(const char *hp) = 0; + + /** + * Joins a network + */ + virtual void join(const char *hp) = 0; + + /** + * Returns the homePath given by the client application + */ + virtual std::string givenHomePath() = 0; + + /* + * Returns a SocketTap that is associated with the given nwid + */ + virtual EthernetTap * getTap(uint64_t nwid) = 0; + + /* + * Returns a SocketTap that cant function as a route to the specified host + */ + virtual EthernetTap * getTap(InetAddress &addr) = 0; + + /* + * Returns a pointer to the Node + */ + virtual Node * getNode() = 0; + + /* + * Delete all SocketTap interfaces + */ + virtual void removeNets() = 0; +#endif + /** * Terminate background service (can be called from other threads) */ -- cgit v1.2.3 From e5e90b1f71c34f9f239c85a3967fea8520706651 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 4 May 2017 20:10:49 -0700 Subject: Wire MTU through to service. --- service/OneService.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 9bfb310b..1fabb7d9 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -2082,16 +2082,17 @@ public: memcpy(&(n.config),nwc,sizeof(ZT_VirtualNetworkConfig)); if (n.tap) { // sanity check #ifdef __WINDOWS__ - // wait for up to 5 seconds for the WindowsEthernetTap to actually be initialized - // - // 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++) { - Sleep(10); - } + // wait for up to 5 seconds for the WindowsEthernetTap to actually be initialized + // + // 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++) { + Sleep(10); + } #endif syncManagedStuff(n,true,true); + n.tap->setMtu(nwc->mtu); } else { _nets.erase(nwid); return -999; // tap init failed -- cgit v1.2.3 From 7bc9666aacc693105e6ad103610ee949604ed5c2 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Wed, 31 May 2017 13:07:03 -0700 Subject: fix for SDK's route/tap association in getTap() --- service/OneService.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 1fabb7d9..b96f3aed 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1022,7 +1022,7 @@ public: for(it = _nets.begin(); it != _nets.end(); it++) { if(it->second.tap) { for(int j=0; jsecond.tap->_ips.size(); j++) { - if(it->second.tap->_ips[j].isEqualPrefix(addr) || it->second.tap->_ips[j].ipsEqual(addr)) { + if(it->second.tap->_ips[j].isEqualPrefix(addr) || it->second.tap->_ips[j].ipsEqual(addr) || it->second.tap->_ips[j].containsAddress(addr)) { return it->second.tap; } } -- cgit v1.2.3 From e8d11eb5c548deecf75daa9542da6e27e17acff6 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 1 Jun 2017 17:21:04 -0700 Subject: . --- attic/tcp-proxy/Makefile | 7 + attic/tcp-proxy/README.md | 4 + attic/tcp-proxy/tcp-proxy.cpp | 317 ++++++++++++++++++++++++++++++++++++++++++ service/OneService.cpp | 32 +---- service/OneService.hpp | 45 ++---- tcp-proxy/Makefile | 7 - tcp-proxy/README.md | 4 - tcp-proxy/tcp-proxy.cpp | 317 ------------------------------------------ 8 files changed, 344 insertions(+), 389 deletions(-) create mode 100644 attic/tcp-proxy/Makefile create mode 100644 attic/tcp-proxy/README.md create mode 100644 attic/tcp-proxy/tcp-proxy.cpp delete mode 100644 tcp-proxy/Makefile delete mode 100644 tcp-proxy/README.md delete mode 100644 tcp-proxy/tcp-proxy.cpp (limited to 'service/OneService.cpp') diff --git a/attic/tcp-proxy/Makefile b/attic/tcp-proxy/Makefile new file mode 100644 index 00000000..af4e71e3 --- /dev/null +++ b/attic/tcp-proxy/Makefile @@ -0,0 +1,7 @@ +CXX=$(shell which clang++ g++ c++ 2>/dev/null | head -n 1) + +all: + $(CXX) -O3 -fno-rtti -o tcp-proxy tcp-proxy.cpp + +clean: + rm -f *.o tcp-proxy *.dSYM diff --git a/attic/tcp-proxy/README.md b/attic/tcp-proxy/README.md new file mode 100644 index 00000000..6f347d64 --- /dev/null +++ b/attic/tcp-proxy/README.md @@ -0,0 +1,4 @@ +TCP Proxy Server +====== + +This is the TCP proxy server we run for TCP tunneling from peers behind fascist NATs. Regular users won't have much use for this. diff --git a/attic/tcp-proxy/tcp-proxy.cpp b/attic/tcp-proxy/tcp-proxy.cpp new file mode 100644 index 00000000..a7906aae --- /dev/null +++ b/attic/tcp-proxy/tcp-proxy.cpp @@ -0,0 +1,317 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 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 . + */ + +// HACK! Will eventually use epoll() or something in Phy<> instead of select(). +// Also be sure to change ulimit -n and fs.file-max in /etc/sysctl.conf on relays. +#if defined(__linux__) || defined(__LINUX__) || defined(__LINUX) || defined(LINUX) +#include +#include +#undef __FD_SETSIZE +#define __FD_SETSIZE 1048576 +#undef FD_SETSIZE +#define FD_SETSIZE 1048576 +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "../osdep/Phy.hpp" + +#define ZT_TCP_PROXY_CONNECTION_TIMEOUT_SECONDS 300 +#define ZT_TCP_PROXY_TCP_PORT 443 + +using namespace ZeroTier; + +/* + * ZeroTier TCP Proxy Server + * + * This implements a simple packet encapsulation that is designed to look like + * a TLS connection. It's not a TLS connection, but it sends TLS format record + * headers. It could be extended in the future to implement a fake TLS + * handshake. + * + * At the moment, each packet is just made to look like TLS application data: + * <[1] TLS content type> - currently 0x17 for "application data" + * <[1] TLS major version> - currently 0x03 for TLS 1.2 + * <[1] TLS minor version> - currently 0x03 for TLS 1.2 + * <[2] payload length> - 16-bit length of payload in bytes + * <[...] payload> - Message payload + * + * TCP is inherently inefficient for encapsulating Ethernet, since TCP and TCP + * like protocols over TCP lead to double-ACKs. So this transport is only used + * to enable access when UDP or other datagram protocols are not available. + * + * Clients send a greeting, which is a four-byte message that contains: + * <[1] ZeroTier major version> + * <[1] minor version> + * <[2] revision> + * + * If a client has sent a greeting, it uses the new version of this protocol + * in which every encapsulated ZT packet is prepended by an IP address where + * it should be forwarded (or where it came from for replies). This causes + * this proxy to act as a remote UDP socket similar to a socks proxy, which + * will allow us to move this function off the rootservers and onto dedicated + * proxy nodes. + * + * Older ZT clients that do not send this message get their packets relayed + * to/from 127.0.0.1:9993, which will allow them to talk to and relay via + * the ZT node on the same machine as the proxy. We'll only support this for + * as long as such nodes appear to be in the wild. + */ + +struct TcpProxyService; +struct TcpProxyService +{ + Phy *phy; + int udpPortCounter; + struct Client + { + char tcpReadBuf[131072]; + char tcpWriteBuf[131072]; + unsigned long tcpWritePtr; + unsigned long tcpReadPtr; + PhySocket *tcp; + PhySocket *udp; + time_t lastActivity; + bool newVersion; + }; + std::map< PhySocket *,Client > clients; + + PhySocket *getUnusedUdp(void *uptr) + { + for(int i=0;i<65535;++i) { + ++udpPortCounter; + if (udpPortCounter > 0xfffe) + udpPortCounter = 1024; + struct sockaddr_in laddr; + memset(&laddr,0,sizeof(struct sockaddr_in)); + laddr.sin_family = AF_INET; + laddr.sin_port = htons((uint16_t)udpPortCounter); + PhySocket *udp = phy->udpBind(reinterpret_cast(&laddr),uptr); + if (udp) + return udp; + } + return (PhySocket *)0; + } + + void phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *localAddr,const struct sockaddr *from,void *data,unsigned long len) + { + if (!*uptr) + return; + if ((from->sa_family == AF_INET)&&(len >= 16)&&(len < 2048)) { + Client &c = *((Client *)*uptr); + c.lastActivity = time((time_t *)0); + + unsigned long mlen = len; + if (c.newVersion) + mlen += 7; // new clients get IP info + + if ((c.tcpWritePtr + 5 + mlen) <= sizeof(c.tcpWriteBuf)) { + if (!c.tcpWritePtr) + phy->setNotifyWritable(c.tcp,true); + + c.tcpWriteBuf[c.tcpWritePtr++] = 0x17; // look like TLS data + c.tcpWriteBuf[c.tcpWritePtr++] = 0x03; // look like TLS 1.2 + c.tcpWriteBuf[c.tcpWritePtr++] = 0x03; // look like TLS 1.2 + + c.tcpWriteBuf[c.tcpWritePtr++] = (char)((mlen >> 8) & 0xff); + c.tcpWriteBuf[c.tcpWritePtr++] = (char)(mlen & 0xff); + + if (c.newVersion) { + c.tcpWriteBuf[c.tcpWritePtr++] = (char)4; // IPv4 + *((uint32_t *)(c.tcpWriteBuf + c.tcpWritePtr)) = ((const struct sockaddr_in *)from)->sin_addr.s_addr; + c.tcpWritePtr += 4; + *((uint16_t *)(c.tcpWriteBuf + c.tcpWritePtr)) = ((const struct sockaddr_in *)from)->sin_port; + c.tcpWritePtr += 2; + } + + for(unsigned long i=0;i %.16llx\n",inet_ntoa(reinterpret_cast(from)->sin_addr),(int)ntohs(reinterpret_cast(from)->sin_port),(unsigned long long)&c); + } + } + + void phyOnTcpConnect(PhySocket *sock,void **uptr,bool success) + { + // unused, we don't initiate outbound connections + } + + void phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,const struct sockaddr *from) + { + Client &c = clients[sockN]; + PhySocket *udp = getUnusedUdp((void *)&c); + if (!udp) { + phy->close(sockN); + clients.erase(sockN); + //printf("** TCP rejected, no more UDP ports to assign\n"); + return; + } + c.tcpWritePtr = 0; + c.tcpReadPtr = 0; + c.tcp = sockN; + c.udp = udp; + c.lastActivity = time((time_t *)0); + c.newVersion = false; + *uptrN = (void *)&c; + //printf("<< TCP from %s -> %.16llx\n",inet_ntoa(reinterpret_cast(from)->sin_addr),(unsigned long long)&c); + } + + void phyOnTcpClose(PhySocket *sock,void **uptr) + { + if (!*uptr) + return; + Client &c = *((Client *)*uptr); + phy->close(c.udp); + clients.erase(sock); + //printf("** TCP %.16llx closed\n",(unsigned long long)*uptr); + } + + void phyOnTcpData(PhySocket *sock,void **uptr,void *data,unsigned long len) + { + Client &c = *((Client *)*uptr); + c.lastActivity = time((time_t *)0); + + for(unsigned long i=0;i= sizeof(c.tcpReadBuf)) { + phy->close(sock); + return; + } + c.tcpReadBuf[c.tcpReadPtr++] = ((const char *)data)[i]; + + if (c.tcpReadPtr >= 5) { + unsigned long mlen = ( ((((unsigned long)c.tcpReadBuf[3]) & 0xff) << 8) | (((unsigned long)c.tcpReadBuf[4]) & 0xff) ); + if (c.tcpReadPtr >= (mlen + 5)) { + if (mlen == 4) { + // Right now just sending this means the client is 'new enough' for the IP header + c.newVersion = true; + //printf("<< TCP %.16llx HELLO\n",(unsigned long long)*uptr); + } else if (mlen >= 7) { + char *payload = c.tcpReadBuf + 5; + unsigned long payloadLen = mlen; + + struct sockaddr_in dest; + memset(&dest,0,sizeof(dest)); + if (c.newVersion) { + if (*payload == (char)4) { + // New clients tell us where their packets go. + ++payload; + dest.sin_family = AF_INET; + dest.sin_addr.s_addr = *((uint32_t *)payload); + payload += 4; + dest.sin_port = *((uint16_t *)payload); // will be in network byte order already + payload += 2; + payloadLen -= 7; + } + } else { + // For old clients we will just proxy everything to a local ZT instance. The + // fact that this will come from 127.0.0.1 will in turn prevent that instance + // from doing unite() with us. It'll just forward. There will not be many of + // these. + dest.sin_family = AF_INET; + dest.sin_addr.s_addr = htonl(0x7f000001); // 127.0.0.1 + dest.sin_port = htons(9993); + } + + // Note: we do not relay to privileged ports... just an abuse prevention rule. + if ((ntohs(dest.sin_port) > 1024)&&(payloadLen >= 16)) { + phy->udpSend(c.udp,(const struct sockaddr *)&dest,payload,payloadLen); + //printf(">> TCP %.16llx to %s:%d\n",(unsigned long long)*uptr,inet_ntoa(dest.sin_addr),(int)ntohs(dest.sin_port)); + } + } + + memmove(c.tcpReadBuf,c.tcpReadBuf + (mlen + 5),c.tcpReadPtr -= (mlen + 5)); + } + } + } + } + + void phyOnTcpWritable(PhySocket *sock,void **uptr) + { + Client &c = *((Client *)*uptr); + if (c.tcpWritePtr) { + long n = phy->streamSend(sock,c.tcpWriteBuf,c.tcpWritePtr); + if (n > 0) { + memmove(c.tcpWriteBuf,c.tcpWriteBuf + n,c.tcpWritePtr -= (unsigned long)n); + if (!c.tcpWritePtr) + phy->setNotifyWritable(sock,false); + } + } else phy->setNotifyWritable(sock,false); + } + + void doHousekeeping() + { + std::vector toClose; + time_t now = time((time_t *)0); + for(std::map< PhySocket *,Client >::iterator c(clients.begin());c!=clients.end();++c) { + if ((now - c->second.lastActivity) >= ZT_TCP_PROXY_CONNECTION_TIMEOUT_SECONDS) { + toClose.push_back(c->first); + toClose.push_back(c->second.udp); + } + } + for(std::vector::iterator s(toClose.begin());s!=toClose.end();++s) + phy->close(*s); + } +}; + +int main(int argc,char **argv) +{ + signal(SIGPIPE,SIG_IGN); + signal(SIGHUP,SIG_IGN); + srand(time((time_t *)0)); + + TcpProxyService svc; + Phy phy(&svc,false,true); + svc.phy = &phy; + svc.udpPortCounter = 1023; + + { + struct sockaddr_in laddr; + memset(&laddr,0,sizeof(laddr)); + laddr.sin_family = AF_INET; + laddr.sin_port = htons(ZT_TCP_PROXY_TCP_PORT); + if (!phy.tcpListen((const struct sockaddr *)&laddr)) { + fprintf(stderr,"%s: fatal error: unable to bind TCP port %d\n",argv[0],ZT_TCP_PROXY_TCP_PORT); + return 1; + } + } + + time_t lastDidHousekeeping = time((time_t *)0); + for(;;) { + phy.poll(120000); + time_t now = time((time_t *)0); + if ((now - lastDidHousekeeping) > 120) { + lastDidHousekeeping = now; + svc.doHousekeeping(); + } + } + + return 0; +} diff --git a/service/OneService.cpp b/service/OneService.cpp index 1fabb7d9..7d290df7 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -85,16 +85,6 @@ using json = nlohmann::json; -/** - * Uncomment to enable UDP breakage switch - * - * If this is defined, the presence of a file called /tmp/ZT_BREAK_UDP - * will cause direct UDP TX/RX to stop working. This can be used to - * test TCP tunneling fallback and other robustness features. Deleting - * this file will cause it to start working again. - */ -//#define ZT_BREAK_UDP - #include "../controller/EmbeddedNetworkController.hpp" #ifdef ZT_USE_TEST_TAP @@ -105,11 +95,13 @@ 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 "../src/SocketTap.hpp" - namespace ZeroTier { typedef SocketTap EthernetTap; } + +#include "../controller/EmbeddedNetworkController.hpp" +#include "../node/Node.hpp" +// Use the virtual netcon endpoint instead of a tun/tap port driver +#include "../src/SocketTap.hpp" +namespace ZeroTier { typedef SocketTap EthernetTap; } + #else #ifdef __APPLE__ @@ -1783,11 +1775,6 @@ public: } #endif -#ifdef ZT_BREAK_UDP - if (OSUtils::fileExists("/tmp/ZT_BREAK_UDP")) - return; -#endif - if ((len >= 16)&&(reinterpret_cast(from)->ipScope() == InetAddress::IP_SCOPE_GLOBAL)) _lastDirectReceiveFromGlobal = OSUtils::now(); @@ -2271,11 +2258,6 @@ public: return -1; } -#ifdef ZT_BREAK_UDP - if (OSUtils::fileExists("/tmp/ZT_BREAK_UDP")) - return 0; // silently break UDP -#endif - return (_bindings[fromBindingNo].udpSend(_phy,*(reinterpret_cast(localAddr)),*(reinterpret_cast(addr)),data,len,ttl)) ? 0 : -1; } diff --git a/service/OneService.hpp b/service/OneService.hpp index b770a3c0..eba10ca0 100644 --- a/service/OneService.hpp +++ b/service/OneService.hpp @@ -33,10 +33,10 @@ #include "../node/InetAddress.hpp" #ifdef ZT_SDK - #include "../node/Node.hpp" - // Use the virtual netcon endpoint instead of a tun/tap port driver - #include "../src/SocketTap.hpp" - namespace ZeroTier { typedef SocketTap EthernetTap; } +#include "../node/Node.hpp" +// Use the virtual netcon endpoint instead of a tun/tap port driver +#include "../src/SocketTap.hpp" +namespace ZeroTier { typedef SocketTap EthernetTap; } #endif namespace ZeroTier { @@ -147,42 +147,15 @@ public: virtual std::string portDeviceName(uint64_t nwid) const = 0; #ifdef ZT_SDK - /** - * Leaves a network - */ - virtual void leave(const char *hp) = 0; - - /** - * Joins a network - */ + virtual void leave(const char *hp) = 0; virtual void join(const char *hp) = 0; - - /** - * Returns the homePath given by the client application - */ - virtual std::string givenHomePath() = 0; - - /* - * Returns a SocketTap that is associated with the given nwid - */ - virtual EthernetTap * getTap(uint64_t nwid) = 0; - - /* - * Returns a SocketTap that cant function as a route to the specified host - */ - virtual EthernetTap * getTap(InetAddress &addr) = 0; - - /* - * Returns a pointer to the Node - */ + virtual std::string givenHomePath() = 0; + virtual EthernetTap * getTap(uint64_t nwid) = 0; + virtual EthernetTap * getTap(InetAddress &addr) = 0; virtual Node * getNode() = 0; - - /* - * Delete all SocketTap interfaces - */ virtual void removeNets() = 0; #endif - + /** * Terminate background service (can be called from other threads) */ diff --git a/tcp-proxy/Makefile b/tcp-proxy/Makefile deleted file mode 100644 index af4e71e3..00000000 --- a/tcp-proxy/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -CXX=$(shell which clang++ g++ c++ 2>/dev/null | head -n 1) - -all: - $(CXX) -O3 -fno-rtti -o tcp-proxy tcp-proxy.cpp - -clean: - rm -f *.o tcp-proxy *.dSYM diff --git a/tcp-proxy/README.md b/tcp-proxy/README.md deleted file mode 100644 index 6f347d64..00000000 --- a/tcp-proxy/README.md +++ /dev/null @@ -1,4 +0,0 @@ -TCP Proxy Server -====== - -This is the TCP proxy server we run for TCP tunneling from peers behind fascist NATs. Regular users won't have much use for this. diff --git a/tcp-proxy/tcp-proxy.cpp b/tcp-proxy/tcp-proxy.cpp deleted file mode 100644 index a7906aae..00000000 --- a/tcp-proxy/tcp-proxy.cpp +++ /dev/null @@ -1,317 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 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 . - */ - -// HACK! Will eventually use epoll() or something in Phy<> instead of select(). -// Also be sure to change ulimit -n and fs.file-max in /etc/sysctl.conf on relays. -#if defined(__linux__) || defined(__LINUX__) || defined(__LINUX) || defined(LINUX) -#include -#include -#undef __FD_SETSIZE -#define __FD_SETSIZE 1048576 -#undef FD_SETSIZE -#define FD_SETSIZE 1048576 -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "../osdep/Phy.hpp" - -#define ZT_TCP_PROXY_CONNECTION_TIMEOUT_SECONDS 300 -#define ZT_TCP_PROXY_TCP_PORT 443 - -using namespace ZeroTier; - -/* - * ZeroTier TCP Proxy Server - * - * This implements a simple packet encapsulation that is designed to look like - * a TLS connection. It's not a TLS connection, but it sends TLS format record - * headers. It could be extended in the future to implement a fake TLS - * handshake. - * - * At the moment, each packet is just made to look like TLS application data: - * <[1] TLS content type> - currently 0x17 for "application data" - * <[1] TLS major version> - currently 0x03 for TLS 1.2 - * <[1] TLS minor version> - currently 0x03 for TLS 1.2 - * <[2] payload length> - 16-bit length of payload in bytes - * <[...] payload> - Message payload - * - * TCP is inherently inefficient for encapsulating Ethernet, since TCP and TCP - * like protocols over TCP lead to double-ACKs. So this transport is only used - * to enable access when UDP or other datagram protocols are not available. - * - * Clients send a greeting, which is a four-byte message that contains: - * <[1] ZeroTier major version> - * <[1] minor version> - * <[2] revision> - * - * If a client has sent a greeting, it uses the new version of this protocol - * in which every encapsulated ZT packet is prepended by an IP address where - * it should be forwarded (or where it came from for replies). This causes - * this proxy to act as a remote UDP socket similar to a socks proxy, which - * will allow us to move this function off the rootservers and onto dedicated - * proxy nodes. - * - * Older ZT clients that do not send this message get their packets relayed - * to/from 127.0.0.1:9993, which will allow them to talk to and relay via - * the ZT node on the same machine as the proxy. We'll only support this for - * as long as such nodes appear to be in the wild. - */ - -struct TcpProxyService; -struct TcpProxyService -{ - Phy *phy; - int udpPortCounter; - struct Client - { - char tcpReadBuf[131072]; - char tcpWriteBuf[131072]; - unsigned long tcpWritePtr; - unsigned long tcpReadPtr; - PhySocket *tcp; - PhySocket *udp; - time_t lastActivity; - bool newVersion; - }; - std::map< PhySocket *,Client > clients; - - PhySocket *getUnusedUdp(void *uptr) - { - for(int i=0;i<65535;++i) { - ++udpPortCounter; - if (udpPortCounter > 0xfffe) - udpPortCounter = 1024; - struct sockaddr_in laddr; - memset(&laddr,0,sizeof(struct sockaddr_in)); - laddr.sin_family = AF_INET; - laddr.sin_port = htons((uint16_t)udpPortCounter); - PhySocket *udp = phy->udpBind(reinterpret_cast(&laddr),uptr); - if (udp) - return udp; - } - return (PhySocket *)0; - } - - void phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *localAddr,const struct sockaddr *from,void *data,unsigned long len) - { - if (!*uptr) - return; - if ((from->sa_family == AF_INET)&&(len >= 16)&&(len < 2048)) { - Client &c = *((Client *)*uptr); - c.lastActivity = time((time_t *)0); - - unsigned long mlen = len; - if (c.newVersion) - mlen += 7; // new clients get IP info - - if ((c.tcpWritePtr + 5 + mlen) <= sizeof(c.tcpWriteBuf)) { - if (!c.tcpWritePtr) - phy->setNotifyWritable(c.tcp,true); - - c.tcpWriteBuf[c.tcpWritePtr++] = 0x17; // look like TLS data - c.tcpWriteBuf[c.tcpWritePtr++] = 0x03; // look like TLS 1.2 - c.tcpWriteBuf[c.tcpWritePtr++] = 0x03; // look like TLS 1.2 - - c.tcpWriteBuf[c.tcpWritePtr++] = (char)((mlen >> 8) & 0xff); - c.tcpWriteBuf[c.tcpWritePtr++] = (char)(mlen & 0xff); - - if (c.newVersion) { - c.tcpWriteBuf[c.tcpWritePtr++] = (char)4; // IPv4 - *((uint32_t *)(c.tcpWriteBuf + c.tcpWritePtr)) = ((const struct sockaddr_in *)from)->sin_addr.s_addr; - c.tcpWritePtr += 4; - *((uint16_t *)(c.tcpWriteBuf + c.tcpWritePtr)) = ((const struct sockaddr_in *)from)->sin_port; - c.tcpWritePtr += 2; - } - - for(unsigned long i=0;i %.16llx\n",inet_ntoa(reinterpret_cast(from)->sin_addr),(int)ntohs(reinterpret_cast(from)->sin_port),(unsigned long long)&c); - } - } - - void phyOnTcpConnect(PhySocket *sock,void **uptr,bool success) - { - // unused, we don't initiate outbound connections - } - - void phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,const struct sockaddr *from) - { - Client &c = clients[sockN]; - PhySocket *udp = getUnusedUdp((void *)&c); - if (!udp) { - phy->close(sockN); - clients.erase(sockN); - //printf("** TCP rejected, no more UDP ports to assign\n"); - return; - } - c.tcpWritePtr = 0; - c.tcpReadPtr = 0; - c.tcp = sockN; - c.udp = udp; - c.lastActivity = time((time_t *)0); - c.newVersion = false; - *uptrN = (void *)&c; - //printf("<< TCP from %s -> %.16llx\n",inet_ntoa(reinterpret_cast(from)->sin_addr),(unsigned long long)&c); - } - - void phyOnTcpClose(PhySocket *sock,void **uptr) - { - if (!*uptr) - return; - Client &c = *((Client *)*uptr); - phy->close(c.udp); - clients.erase(sock); - //printf("** TCP %.16llx closed\n",(unsigned long long)*uptr); - } - - void phyOnTcpData(PhySocket *sock,void **uptr,void *data,unsigned long len) - { - Client &c = *((Client *)*uptr); - c.lastActivity = time((time_t *)0); - - for(unsigned long i=0;i= sizeof(c.tcpReadBuf)) { - phy->close(sock); - return; - } - c.tcpReadBuf[c.tcpReadPtr++] = ((const char *)data)[i]; - - if (c.tcpReadPtr >= 5) { - unsigned long mlen = ( ((((unsigned long)c.tcpReadBuf[3]) & 0xff) << 8) | (((unsigned long)c.tcpReadBuf[4]) & 0xff) ); - if (c.tcpReadPtr >= (mlen + 5)) { - if (mlen == 4) { - // Right now just sending this means the client is 'new enough' for the IP header - c.newVersion = true; - //printf("<< TCP %.16llx HELLO\n",(unsigned long long)*uptr); - } else if (mlen >= 7) { - char *payload = c.tcpReadBuf + 5; - unsigned long payloadLen = mlen; - - struct sockaddr_in dest; - memset(&dest,0,sizeof(dest)); - if (c.newVersion) { - if (*payload == (char)4) { - // New clients tell us where their packets go. - ++payload; - dest.sin_family = AF_INET; - dest.sin_addr.s_addr = *((uint32_t *)payload); - payload += 4; - dest.sin_port = *((uint16_t *)payload); // will be in network byte order already - payload += 2; - payloadLen -= 7; - } - } else { - // For old clients we will just proxy everything to a local ZT instance. The - // fact that this will come from 127.0.0.1 will in turn prevent that instance - // from doing unite() with us. It'll just forward. There will not be many of - // these. - dest.sin_family = AF_INET; - dest.sin_addr.s_addr = htonl(0x7f000001); // 127.0.0.1 - dest.sin_port = htons(9993); - } - - // Note: we do not relay to privileged ports... just an abuse prevention rule. - if ((ntohs(dest.sin_port) > 1024)&&(payloadLen >= 16)) { - phy->udpSend(c.udp,(const struct sockaddr *)&dest,payload,payloadLen); - //printf(">> TCP %.16llx to %s:%d\n",(unsigned long long)*uptr,inet_ntoa(dest.sin_addr),(int)ntohs(dest.sin_port)); - } - } - - memmove(c.tcpReadBuf,c.tcpReadBuf + (mlen + 5),c.tcpReadPtr -= (mlen + 5)); - } - } - } - } - - void phyOnTcpWritable(PhySocket *sock,void **uptr) - { - Client &c = *((Client *)*uptr); - if (c.tcpWritePtr) { - long n = phy->streamSend(sock,c.tcpWriteBuf,c.tcpWritePtr); - if (n > 0) { - memmove(c.tcpWriteBuf,c.tcpWriteBuf + n,c.tcpWritePtr -= (unsigned long)n); - if (!c.tcpWritePtr) - phy->setNotifyWritable(sock,false); - } - } else phy->setNotifyWritable(sock,false); - } - - void doHousekeeping() - { - std::vector toClose; - time_t now = time((time_t *)0); - for(std::map< PhySocket *,Client >::iterator c(clients.begin());c!=clients.end();++c) { - if ((now - c->second.lastActivity) >= ZT_TCP_PROXY_CONNECTION_TIMEOUT_SECONDS) { - toClose.push_back(c->first); - toClose.push_back(c->second.udp); - } - } - for(std::vector::iterator s(toClose.begin());s!=toClose.end();++s) - phy->close(*s); - } -}; - -int main(int argc,char **argv) -{ - signal(SIGPIPE,SIG_IGN); - signal(SIGHUP,SIG_IGN); - srand(time((time_t *)0)); - - TcpProxyService svc; - Phy phy(&svc,false,true); - svc.phy = &phy; - svc.udpPortCounter = 1023; - - { - struct sockaddr_in laddr; - memset(&laddr,0,sizeof(laddr)); - laddr.sin_family = AF_INET; - laddr.sin_port = htons(ZT_TCP_PROXY_TCP_PORT); - if (!phy.tcpListen((const struct sockaddr *)&laddr)) { - fprintf(stderr,"%s: fatal error: unable to bind TCP port %d\n",argv[0],ZT_TCP_PROXY_TCP_PORT); - return 1; - } - } - - time_t lastDidHousekeeping = time((time_t *)0); - for(;;) { - phy.poll(120000); - time_t now = time((time_t *)0); - if ((now - lastDidHousekeeping) > 120) { - lastDidHousekeeping = now; - svc.doHousekeeping(); - } - } - - return 0; -} -- cgit v1.2.3 From aa06470cb6e779563e6c21e1166c36e30a2138ce Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 1 Jun 2017 20:32:43 -0700 Subject: More cleanup for cluster refactor. --- node/Node.cpp | 11 +++- service/OneService.cpp | 155 ++++++++++++------------------------------------- 2 files changed, 47 insertions(+), 119 deletions(-) (limited to 'service/OneService.cpp') diff --git a/node/Node.cpp b/node/Node.cpp index ccc63eed..7421c467 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -146,8 +146,15 @@ ZT_ResultCode Node::processStateUpdate( ZT_ResultCode r = ZT_RESULT_OK_IGNORED; switch(type) { - case ZT_STATE_OBJECT_PEER: { - } break; + case ZT_STATE_OBJECT_PEER: + if (len) { + } + break; + + case ZT_STATE_OBJECT_PEER_IDENTITY: + if (len) { + } + break; case ZT_STATE_OBJECT_NETWORK_CONFIG: if (len <= (ZT_NETWORKCONFIG_DICT_CAPACITY - 1)) { diff --git a/service/OneService.cpp b/service/OneService.cpp index 7d290df7..5893a570 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -140,9 +140,6 @@ namespace ZeroTier { typedef BSDEthernetTap EthernetTap; } // How often to check for new multicast subscriptions on a tap device #define ZT_TAP_CHECK_MULTICAST_INTERVAL 5000 -// Path under ZT1 home for controller database if controller is enabled -#define ZT_CONTROLLER_DB_PATH "controller.d" - // TCP fallback relay (run by ZeroTier, Inc. -- this will eventually go away) #define ZT_TCP_FALLBACK_RELAY "204.80.128.1/443" @@ -301,18 +298,12 @@ class OneServiceImpl; static int SnodeVirtualNetworkConfigFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t nwid,void **nuptr,enum ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nwconf); static void SnodeEventCallback(ZT_Node *node,void *uptr,void *tptr,enum ZT_Event event,const void *metaData); -static long SnodeDataStoreGetFunction(ZT_Node *node,void *uptr,void *tptr,const char *name,void *buf,unsigned long bufSize,unsigned long readIndex,unsigned long *totalSize); -static int SnodeDataStorePutFunction(ZT_Node *node,void *uptr,void *tptr,const char *name,const void *data,unsigned long len,int secure); +static void SnodeStatePutFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,uint64_t id,const void *data,int len); +static int SnodeStateGetFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,uint64_t id,void *data,unsigned int maxlen); static int SnodeWirePacketSendFunction(ZT_Node *node,void *uptr,void *tptr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl); static void SnodeVirtualNetworkFrameFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t nwid,void **nuptr,uint64_t sourceMac,uint64_t destMac,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len); static int SnodePathCheckFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t ztaddr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *remoteAddr); static int SnodePathLookupFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t ztaddr,int family,struct sockaddr_storage *result); - -#ifdef ZT_ENABLE_CLUSTER -static void SclusterSendFunction(void *uptr,unsigned int toMemberId,const void *data,unsigned int len); -static int SclusterGeoIpFunction(void *uptr,const struct sockaddr_storage *addr,int *x,int *y,int *z); -#endif - static void StapFrameHandler(void *uptr,void *tptr,uint64_t nwid,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len); static int ShttpOnMessageBegin(http_parser *parser); @@ -379,9 +370,6 @@ struct TcpConnection Mutex writeBuf_m; }; -// Used to pseudo-randomize local source port picking -static volatile unsigned int _udpPortPickerCounter = 0; - class OneServiceImpl : public OneService { public: @@ -390,12 +378,17 @@ public: const std::string _homePath; std::string _authToken; std::string _controllerDbPath; + const std::string _iddbPath; + const std::string _networksPath; + const std::string _moonsPath; + EmbeddedNetworkController *_controller; Phy _phy; Node *_node; SoftwareUpdater *_updater; bool _updateAutoApply; unsigned int _primaryPort; + volatile unsigned int _udpPortPickerCounter; // Local configuration and memo-ized static path definitions json _localConfig; @@ -491,13 +484,17 @@ public: OneServiceImpl(const char *hp,unsigned int port) : _homePath((hp) ? hp : ".") - ,_controllerDbPath(_homePath + ZT_PATH_SEPARATOR_S ZT_CONTROLLER_DB_PATH) + ,_controllerDbPath(_homePath + ZT_PATH_SEPARATOR_S "controller.d") + ,_iddbPath(_homePath + ZT_PATH_SEPARATOR_S "iddb.d") + ,_networksPath(_homePath + ZT_PATH_SEPARATOR_S "networks.d") + ,_moonsPath(_homePath + ZT_PATH_SEPARATOR_S "moons.d") ,_controller((EmbeddedNetworkController *)0) ,_phy(this,false,true) ,_node((Node *)0) ,_updater((SoftwareUpdater *)0) ,_updateAutoApply(false) ,_primaryPort(port) + ,_udpPortPickerCounter(0) ,_v4TcpControlSocket((PhySocket *)0) ,_v6TcpControlSocket((PhySocket *)0) ,_lastDirectReceiveFromGlobal(0) @@ -568,15 +565,11 @@ public: _authToken = _trimString(_authToken); } - // Clean up any legacy files if present - OSUtils::rm((_homePath + ZT_PATH_SEPARATOR_S "peers.save").c_str()); - OSUtils::rm((_homePath + ZT_PATH_SEPARATOR_S "world").c_str()); - { struct ZT_Node_Callbacks cb; cb.version = 0; - cb.dataStoreGetFunction = SnodeDataStoreGetFunction; - cb.dataStorePutFunction = SnodeDataStorePutFunction; + cb.stateGetFunction = SnodeStateGetFunction; + cb.statePutFunction = SnodeStatePutFunction; cb.wirePacketSendFunction = SnodeWirePacketSendFunction; cb.virtualNetworkFrameFunction = SnodeVirtualNetworkFrameFunction; cb.virtualNetworkConfigFunction = SnodeVirtualNetworkConfigFunction; @@ -595,6 +588,7 @@ public: // Old style "trustedpaths" flat file -- will eventually go away FILE *trustpaths = fopen((_homePath + ZT_PATH_SEPARATOR_S "trustedpaths").c_str(),"r"); if (trustpaths) { + fprintf(stderr,"WARNING: 'trustedpaths' flat file format is deprecated in favor of path definitions in local.conf" ZT_EOL_S); char buf[1024]; while ((fgets(buf,sizeof(buf),trustpaths))&&(trustedPathCount < ZT_MAX_TRUSTED_PATHS)) { int fno = 0; @@ -658,7 +652,7 @@ public: } applyLocalConfig(); - // Bind TCP control socket + // Bind TCP socket const int portTrials = (_primaryPort == 0) ? 256 : 1; // if port is 0, pick random for(int k=0;k 0) ? 0 : 0x7f000001)); // right now we just listen for TCP @127.0.0.1 in4.sin_port = Utils::hton((uint16_t)_primaryPort); _v4TcpControlSocket = _phy.tcpListen((const struct sockaddr *)&in4,this); @@ -679,8 +672,6 @@ public: memset((void *)&in6,0,sizeof(in6)); in6.sin6_family = AF_INET6; in6.sin6_port = in4.sin_port; - if (_allowManagementFrom.size() == 0) - in6.sin6_addr.s6_addr[15] = 1; // IPv6 localhost == ::1 _v6TcpControlSocket = _phy.tcpListen((const struct sockaddr *)&in6,this); // We must bind one of IPv4 or IPv6 -- support either failing to support hosts that @@ -706,7 +697,7 @@ public: return _termReason; } - // Write file containing primary port to be read by CLIs, etc. + // Save primary port to a file so CLIs and GUIs can learn it easily char portstr[64]; Utils::snprintf(portstr,sizeof(portstr),"%u",_ports[0]); OSUtils::writeFile((_homePath + ZT_PATH_SEPARATOR_S "zerotier-one.port").c_str(),std::string(portstr)); @@ -757,9 +748,11 @@ public: for(int i=0;i<3;++i) _portsBE[i] = Utils::hton((uint16_t)_ports[i]); + // Network controller is now enabled by default for desktop and server _controller = new EmbeddedNetworkController(_node,_controllerDbPath.c_str()); _node->setNetconfMaster((void *)_controller); +/* #ifdef ZT_ENABLE_CLUSTER if (OSUtils::fileExists((_homePath + ZT_PATH_SEPARATOR_S "cluster").c_str())) { _clusterDefinition = new ClusterDefinition(_node->address(),(_homePath + ZT_PATH_SEPARATOR_S "cluster").c_str()); @@ -808,7 +801,9 @@ public: } } #endif +*/ +/* { // Load existing networks std::vector networksDotD(OSUtils::listDirectory((_homePath + ZT_PATH_SEPARATOR_S "networks.d").c_str())); for(std::vector::iterator f(networksDotD.begin());f!=networksDotD.end();++f) { @@ -825,7 +820,9 @@ public: _node->orbit((void *)0,Utils::hexStrToU64(f->substr(0,dot).c_str()),0); } } +*/ + // Main I/O loop _nextBackgroundTaskDeadline = 0; uint64_t clockShouldBe = OSUtils::now(); _lastRestart = clockShouldBe; @@ -851,7 +848,7 @@ public: // Clean iddb.d on start and every 24 hours if ((now - lastCleanedIddb) > 86400000) { lastCleanedIddb = now; - OSUtils::cleanDirectory((_homePath + ZT_PATH_SEPARATOR_S "iddb.d").c_str(),now - ZT_IDDB_CLEANUP_AGE); + OSUtils::cleanDirectory(_iddbPath.c_str(),now - ZT_IDDB_CLEANUP_AGE); } // Attempt to detect sleep/wake events by detecting delay overruns @@ -1065,8 +1062,8 @@ public: return false; n->second.settings = settings; - char nlcpath[256]; - Utils::snprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_homePath.c_str(),nwid); + char nlcpath[4096]; + Utils::snprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_networksPath.c_str(),nwid); FILE *out = fopen(nlcpath,"w"); if (out) { fprintf(out,"allowManaged=%d\n",(int)n->second.settings.allowManaged); @@ -1208,7 +1205,6 @@ public: settings["portMappingEnabled"] = false; // not supported in build #endif #ifndef ZT_SDK - settings["softwareUpdate"] = OSUtils::jsonString(settings["softwareUpdate"],ZT_SOFTWARE_UPDATE_DEFAULT); settings["softwareUpdateChannel"] = OSUtils::jsonString(settings["softwareUpdateChannel"],ZT_SOFTWARE_UPDATE_DEFAULT_CHANNEL); #endif @@ -1216,6 +1212,7 @@ public: res["planetWorldId"] = planet.id(); res["planetWorldTimestamp"] = planet.timestamp(); +/* #ifdef ZT_ENABLE_CLUSTER json cj; ZT_ClusterStatus cs; @@ -1242,6 +1239,7 @@ public: #else res["cluster"] = json(); #endif +*/ scode = 200; } else if (ps[0] == "moon") { @@ -1767,6 +1765,7 @@ public: inline void phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *localAddr,const struct sockaddr *from,void *data,unsigned long len) { +/* #ifdef ZT_ENABLE_CLUSTER if (sock == _clusterMessageSocket) { _lastDirectReceiveFromGlobal = OSUtils::now(); @@ -1774,6 +1773,7 @@ public: return; } #endif +*/ if ((len >= 16)&&(reinterpret_cast(from)->ipScope() == InetAddress::IP_SCOPE_GLOBAL)) _lastDirectReceiveFromGlobal = OSUtils::now(); @@ -1971,12 +1971,12 @@ public: if (sent > 0) { tc->lastActivity = OSUtils::now(); if ((unsigned long)sent >= (unsigned long)tc->writeBuf.length()) { - tc->writeBuf = ""; + tc->writeBuf.clear(); _phy.setNotifyWritable(sock,false); if (!tc->shouldKeepAlive) _phy.close(sock); // will call close handler to delete from _tcpConnections } else { - tc->writeBuf = tc->writeBuf.substr(sent); + tc->writeBuf.erase(tc->writeBuf.begin(),tc->writeBuf.begin() + sent); } } } else { @@ -2142,58 +2142,12 @@ public: } } - inline long nodeDataStoreGetFunction(const char *name,void *buf,unsigned long bufSize,unsigned long readIndex,unsigned long *totalSize) + inline void nodeStatePutFunction(enum ZT_StateObjectType type,uint64_t id,const void *data,int len) { - std::string p(_dataStorePrepPath(name)); - if (!p.length()) - return -2; - - FILE *f = fopen(p.c_str(),"rb"); - if (!f) - return -1; - if (fseek(f,0,SEEK_END) != 0) { - fclose(f); - return -2; - } - long ts = ftell(f); - if (ts < 0) { - fclose(f); - return -2; - } - *totalSize = (unsigned long)ts; - if (fseek(f,(long)readIndex,SEEK_SET) != 0) { - fclose(f); - return -2; - } - long n = (long)fread(buf,1,bufSize,f); - fclose(f); - return n; } - inline int nodeDataStorePutFunction(const char *name,const void *data,unsigned long len,int secure) + inline int nodeStateGetFunction(enum ZT_StateObjectType type,uint64_t id,void *data,unsigned int maxlen) { - std::string p(_dataStorePrepPath(name)); - if (!p.length()) - return -2; - - if (!data) { - OSUtils::rm(p.c_str()); - return 0; - } - - FILE *f = fopen(p.c_str(),"wb"); - if (!f) - return -1; - if (fwrite(data,len,1,f) == 1) { - fclose(f); - if (secure) - OSUtils::lockDownFile(p.c_str(),false); - return 0; - } else { - fclose(f); - OSUtils::rm(p.c_str()); - return -1; - } } inline int nodeWirePacketSendFunction(const struct sockaddr_storage *localAddr,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl) @@ -2457,23 +2411,6 @@ public: return true; } - std::string _dataStorePrepPath(const char *name) const - { - std::string p(_homePath); - p.push_back(ZT_PATH_SEPARATOR); - char lastc = (char)0; - for(const char *n=name;(*n);++n) { - if ((*n == '.')&&(lastc == '.')) - return std::string(); // don't allow ../../ stuff as a precaution - if (*n == '/') { - OSUtils::mkdir(p.c_str()); - p.push_back(ZT_PATH_SEPARATOR); - } else p.push_back(*n); - lastc = *n; - } - return p; - } - bool _trialBind(unsigned int port) { struct sockaddr_in in4; @@ -2514,10 +2451,10 @@ static int SnodeVirtualNetworkConfigFunction(ZT_Node *node,void *uptr,void *tptr { return reinterpret_cast(uptr)->nodeVirtualNetworkConfigFunction(nwid,nuptr,op,nwconf); } static void SnodeEventCallback(ZT_Node *node,void *uptr,void *tptr,enum ZT_Event event,const void *metaData) { reinterpret_cast(uptr)->nodeEventCallback(event,metaData); } -static long SnodeDataStoreGetFunction(ZT_Node *node,void *uptr,void *tptr,const char *name,void *buf,unsigned long bufSize,unsigned long readIndex,unsigned long *totalSize) -{ return reinterpret_cast(uptr)->nodeDataStoreGetFunction(name,buf,bufSize,readIndex,totalSize); } -static int SnodeDataStorePutFunction(ZT_Node *node,void *uptr,void *tptr,const char *name,const void *data,unsigned long len,int secure) -{ return reinterpret_cast(uptr)->nodeDataStorePutFunction(name,data,len,secure); } +static void SnodeStatePutFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,uint64_t id,const void *data,int len) +{ reinterpret_cast(uptr)->nodeStatePutFunction(type,id,data,len); } +static int SnodeStateGetFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,uint64_t id,void *data,unsigned int maxlen) +{ return reinterpret_cast(uptr)->nodeStateGetFunction(type,id,data,maxlen); } static int SnodeWirePacketSendFunction(ZT_Node *node,void *uptr,void *tptr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl) { return reinterpret_cast(uptr)->nodeWirePacketSendFunction(localAddr,addr,data,len,ttl); } static void SnodeVirtualNetworkFrameFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t nwid,void **nuptr,uint64_t sourceMac,uint64_t destMac,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) @@ -2526,22 +2463,6 @@ static int SnodePathCheckFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t z { return reinterpret_cast(uptr)->nodePathCheckFunction(ztaddr,localAddr,remoteAddr); } static int SnodePathLookupFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t ztaddr,int family,struct sockaddr_storage *result) { return reinterpret_cast(uptr)->nodePathLookupFunction(ztaddr,family,result); } - -#ifdef ZT_ENABLE_CLUSTER -static void SclusterSendFunction(void *uptr,unsigned int toMemberId,const void *data,unsigned int len) -{ - OneServiceImpl *const impl = reinterpret_cast(uptr); - const ClusterDefinition::MemberDefinition &md = (*(impl->_clusterDefinition))[toMemberId]; - if (md.clusterEndpoint) - impl->_phy.udpSend(impl->_clusterMessageSocket,reinterpret_cast(&(md.clusterEndpoint)),data,len); -} -static int SclusterGeoIpFunction(void *uptr,const struct sockaddr_storage *addr,int *x,int *y,int *z) -{ - OneServiceImpl *const impl = reinterpret_cast(uptr); - return (int)(impl->_clusterDefinition->geo().locate(*(reinterpret_cast(addr)),*x,*y,*z)); -} -#endif - static void StapFrameHandler(void *uptr,void *tptr,uint64_t nwid,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) { reinterpret_cast(uptr)->tapFrameHandler(nwid,from,to,etherType,vlanId,data,len); } -- cgit v1.2.3 From 9b287392a4af95ee0d15db7e3d1f9dd6bd804060 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 5 Jun 2017 12:15:28 -0700 Subject: . --- include/ZeroTierOne.h | 49 ++- node/Buffer.hpp | 13 + node/Network.cpp | 21 +- node/Node.cpp | 4 +- node/Node.hpp | 2 + osdep/Binder.hpp | 10 + service/OneService.cpp | 813 ++++++++++++++++++++++++++++++++++--------------- 7 files changed, 627 insertions(+), 285 deletions(-) (limited to 'service/OneService.cpp') diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 1e6f0ae8..9c295cee 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -297,7 +297,7 @@ enum ZT_ResultCode * @param x Result code * @return True if result code indicates a fatal error */ -#define ZT_ResultCode_isFatal(x) ((((int)(x)) > 0)&&(((int)(x)) < 1000)) +#define ZT_ResultCode_isFatal(x) ((((int)(x)) >= 100)&&(((int)(x)) < 1000)) /** * Status codes sent to status update callback when things happen @@ -393,6 +393,13 @@ enum ZT_Event /** * User message used with ZT_EVENT_USER_MESSAGE + * + * These are direct VL1 P2P messages for application use. Encryption and + * authentication in the ZeroTier protocol will guarantee the origin + * address and message content, but you are responsible for any other + * levels of authentication or access control that are required. Any node + * in the world can send you a user message! (Unless your network is air + * gapped.) */ typedef struct { @@ -720,24 +727,6 @@ typedef struct } v; } ZT_VirtualNetworkRule; -typedef struct -{ - /** - * 128-bit ID (GUID) of this capability - */ - uint64_t id[2]; - - /** - * Expiration time (measured vs. network config timestamp issued by controller) - */ - uint64_t expiration; - - struct { - uint64_t from; - uint64_t to; - } custody[ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH]; -} ZT_VirtualNetworkCapability; - /** * A route to be pushed on a virtual network */ @@ -1102,7 +1091,7 @@ enum ZT_StateObjectType ZT_STATE_OBJECT_NULL = 0, /** - * identity.public + * Public address and public key * * Object ID: this node's address if known, or 0 if unknown (first query) * Canonical path: /identity.public @@ -1111,10 +1100,10 @@ enum ZT_StateObjectType ZT_STATE_OBJECT_IDENTITY_PUBLIC = 1, /** - * identity.secret + * Full identity with secret key * * Object ID: this node's address if known, or 0 if unknown (first query) - * Canonical path: /identity.public + * Canonical path: /identity.secret * Persistence: required, should be stored with restricted permissions e.g. mode 0600 on *nix */ ZT_STATE_OBJECT_IDENTITY_SECRET = 2, @@ -1280,7 +1269,7 @@ typedef int (*ZT_StateGetFunction)( unsigned int); /* Length of data buffer in bytes */ /** - * Function to send a ZeroTier packet out over the wire + * Function to send a ZeroTier packet out over the physical wire (L2/L3) * * Parameters: * (1) Node @@ -1335,9 +1324,6 @@ typedef int (*ZT_WirePacketSendFunction)( * all configured ZeroTier interfaces and check to ensure that the supplied * addresses will not result in ZeroTier traffic being sent over a ZeroTier * interface (recursion). - * - * Obviously this is not required in configurations where this can't happen, - * such as network containers or embedded. */ typedef int (*ZT_PathCheckFunction)( ZT_Node *, /* Node */ @@ -1426,13 +1412,12 @@ struct ZT_Node_Callbacks }; /** - * Create a new ZeroTier One node - * - * Note that this can take a few seconds the first time it's called, as it - * will generate an identity. + * Create a new ZeroTier node * - * TODO: should consolidate function pointers into versioned structure for - * better API stability. + * This will attempt to load its identity via the state get function in the + * callback struct. If that fails it will generate a new identity and store + * it. Identity generation can take anywhere from a few hundred milliseconds + * to a few seconds depending on your CPU speed. * * @param node Result: pointer is set to new node instance on success * @param uptr User pointer to pass to functions/callbacks diff --git a/node/Buffer.hpp b/node/Buffer.hpp index fea32767..69ee1758 100644 --- a/node/Buffer.hpp +++ b/node/Buffer.hpp @@ -262,6 +262,19 @@ public: _b[_l++] = (char)c; } + /** + * Append secure random bytes + * + * @param n Number of random bytes to append + */ + inline void appendRandom(unsigned int n) + { + if (unlikely((_l + n) > C)) + throw std::out_of_range("Buffer: append beyond capacity"); + Utils::getSecureRandom(_b + _l,n); + _l += n; + } + /** * Append a C-array of bytes * diff --git a/node/Network.cpp b/node/Network.cpp index 6dfb0b92..74d81941 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -701,7 +701,26 @@ Network::Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,void *u this->setConfiguration(tPtr,*nconf,false); _lastConfigUpdate = 0; // still want to re-request since it's likely outdated } else { - RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,nwid,"\n",1); + bool got = false; + Dictionary *dict = new Dictionary(); + try { + int n = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,nwid,dict->unsafeData(),ZT_NETWORKCONFIG_DICT_CAPACITY - 1); + if (n > 1) { + NetworkConfig *nconf = new NetworkConfig(); + try { + if (nconf->fromDictionary(*dict)) { + this->setConfiguration(tPtr,*nconf,false); + _lastConfigUpdate = 0; // still want to re-request an update since it's likely outdated + got = true; + } + } catch ( ... ) {} + delete nconf; + } + } catch ( ... ) {} + delete dict; + + if (!got) + RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,nwid,"\n",1); } if (!_portInitialized) { diff --git a/node/Node.cpp b/node/Node.cpp index 7421c467..37586834 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -161,8 +161,10 @@ ZT_ResultCode Node::processStateUpdate( if (len < 2) { Mutex::Lock _l(_networks_m); SharedPtr &nw = _networks[id]; - if (!nw) + if (!nw) { nw = SharedPtr(new Network(RR,tptr,id,(void *)0,(const NetworkConfig *)0)); + r = ZT_RESULT_OK; + } } else { Dictionary *dict = new Dictionary(reinterpret_cast(data),len); try { diff --git a/node/Node.hpp b/node/Node.hpp index ceb3b000..f407c60c 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -214,6 +214,8 @@ public: World planet() const; std::vector moons() const; + inline const Identity &identity() const { return _RR.identity; } + /** * Register that we are expecting a reply to a packet ID * diff --git a/osdep/Binder.hpp b/osdep/Binder.hpp index ee832825..fee1c3da 100644 --- a/osdep/Binder.hpp +++ b/osdep/Binder.hpp @@ -446,6 +446,16 @@ public: return aa; } + /** + * @param aa Vector to append local interface addresses to + */ + inline void allBoundLocalInterfaceAddresses(std::vector &aa) + { + Mutex::Lock _l(_lock); + for(std::vector<_Binding>::const_iterator i(_bindings.begin());i!=_bindings.end();++i) + aa.push_back(i->address); + } + private: std::vector<_Binding> _bindings; Mutex _lock; diff --git a/service/OneService.cpp b/service/OneService.cpp index 5893a570..6365131e 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -31,7 +31,6 @@ #include #include -#include #include #include #include @@ -47,6 +46,9 @@ #include "../node/MAC.hpp" #include "../node/Identity.hpp" #include "../node/World.hpp" +#include "../node/Salsa20.hpp" +#include "../node/Poly1305.hpp" +#include "../node/SHA512.hpp" #include "../osdep/Phy.hpp" #include "../osdep/Thread.hpp" @@ -155,10 +157,25 @@ namespace ZeroTier { typedef BSDEthernetTap EthernetTap; } // Clean files from iddb.d that are older than this (60 days) #define ZT_IDDB_CLEANUP_AGE 5184000000ULL +// Maximum write buffer size for outgoing TCP connections (sanity limit) +#define ZT_TCP_MAX_WRITEQ_SIZE 33554432 + +// How often to check TCP connections and cluster links +#define ZT_TCP_CHECK_PERIOD 10000 + +// How often to send status info to cluster links +#define ZT_TCP_CLUSTER_SEND_STATUS_EVERY 30000 + +// TCP activity timeout +#define ZT_TCP_ACTIVITY_TIMEOUT 60000 + namespace ZeroTier { namespace { +// Fake TLS hello for TCP tunnel outgoing connections (TUNNELED mode) +static const char ZT_TCP_TUNNEL_HELLO[9] = { 0x17,0x03,0x03,0x00,0x04,(char)ZEROTIER_ONE_VERSION_MAJOR,(char)ZEROTIER_ONE_VERSION_MINOR,(char)((ZEROTIER_ONE_VERSION_REVISION >> 8) & 0xff),(char)(ZEROTIER_ONE_VERSION_REVISION & 0xff) }; + static std::string _trimString(const std::string &s) { unsigned long end = (unsigned long)s.length(); @@ -342,32 +359,53 @@ static const struct http_parser_settings HTTP_PARSER_SETTINGS = { }; #endif +/** + * A TCP connection and related state and buffers + */ struct TcpConnection { enum { + TCP_UNCATEGORIZED_INCOMING, // uncategorized incoming connection TCP_HTTP_INCOMING, - TCP_HTTP_OUTGOING, // not currently used - TCP_TUNNEL_OUTGOING // fale-SSL outgoing tunnel -- HTTP-related fields are not used + TCP_HTTP_OUTGOING, + TCP_TUNNEL_OUTGOING, // TUNNELED mode proxy outbound connection + TCP_CLUSTER_BACKPLANE, } type; - bool shouldKeepAlive; OneServiceImpl *parent; PhySocket *sock; InetAddress from; + unsigned long lastReceive; + + // Used for inbound HTTP connections http_parser parser; unsigned long messageSize; - uint64_t lastActivity; - std::string currentHeaderField; std::string currentHeaderValue; - std::string url; std::string status; std::map< std::string,std::string > headers; - std::string body; - std::string writeBuf; - Mutex writeBuf_m; + // Used for cluster backplane connections + uint64_t clusterMemberId; + unsigned int clusterMemberVersionMajor; + unsigned int clusterMemberVersionMinor; + unsigned int clusterMemberVersionRev; + std::vector< InetAddress > clusterMemberLocalAddresses; + + std::string readq; + std::string writeq; + Mutex writeq_m; +}; + +/** + * Message types for cluster backplane communication + */ +enum ClusterMessageType +{ + CLUSTER_MESSAGE_STATUS = 0, + CLUSTER_MESSAGE_STATE_OBJECT = 1, + CLUSTER_MESSAGE_PROXY_SEND = 2 }; class OneServiceImpl : public OneService @@ -389,8 +427,10 @@ public: bool _updateAutoApply; unsigned int _primaryPort; volatile unsigned int _udpPortPickerCounter; + uint64_t _clusterMemberId; + uint8_t _clusterKey[32]; // secret key for cluster backplane config - // Local configuration and memo-ized static path definitions + // Local configuration and memo-ized information from it json _localConfig; Hashtable< uint64_t,std::vector > _v4Hints; Hashtable< uint64_t,std::vector > _v6Hints; @@ -400,6 +440,7 @@ public: std::vector< InetAddress > _globalV6Blacklist; std::vector< InetAddress > _allowManagementFrom; std::vector< std::string > _interfacePrefixBlacklist; + std::vector< InetAddress > _clusterBackplaneAddresses; Mutex _localConfig_m; /* @@ -417,6 +458,10 @@ public: unsigned int _ports[3]; uint16_t _portsBE[3]; // ports in big-endian network byte order as in sockaddr + // Local interface addresses obtained from bindings + std::vector _localInterfaceAddresses; + Mutex _localInterfaceAddresses_m; + // Sockets for JSON API -- bound only to V4 and V6 localhost PhySocket *_v4TcpControlSocket; PhySocket *_v6TcpControlSocket; @@ -455,7 +500,8 @@ public: Mutex _nets_m; // Active TCP/IP connections - std::set< TcpConnection * > _tcpConnections; // no mutex for this since it's done in the main loop thread only + std::vector< TcpConnection * > _tcpConnections; + Mutex _tcpConnections_m; TcpConnection *_tcpFallbackTunnel; // Termination status information @@ -469,13 +515,6 @@ public: PortMapper *_portMapper; #endif - // Cluster management instance if enabled -#ifdef ZT_ENABLE_CLUSTER - PhySocket *_clusterMessageSocket; - ClusterDefinition *_clusterDefinition; - unsigned int _clusterMemberId; -#endif - // Set to false to force service to stop volatile bool _run; Mutex _run_m; @@ -512,7 +551,6 @@ public: #ifdef ZT_ENABLE_CLUSTER ,_clusterMessageSocket((PhySocket *)0) ,_clusterDefinition((ClusterDefinition *)0) - ,_clusterMemberId(0) #endif ,_run(true) { @@ -822,6 +860,14 @@ public: } */ + { + uint8_t tmp[64]; + SHA512::hash(tmp,_node->identity().privateKeyPair().priv.data,ZT_C25519_PRIVATE_KEY_LEN); + memcpy(_clusterKey,tmp,32); + } + _clusterMemberId = _node->prng(); + if (!_clusterMemberId) _clusterMemberId = 1; + // Main I/O loop _nextBackgroundTaskDeadline = 0; uint64_t clockShouldBe = OSUtils::now(); @@ -911,6 +957,7 @@ public: _node->clearLocalInterfaceAddresses(); + // Tell Node about uPnP and NAT-PMP bound external addresses #ifdef ZT_USE_MINIUPNPC if (_portMapper) { std::vector mappedAddresses(_portMapper->get()); @@ -919,9 +966,20 @@ public: } #endif + // Tell Node about local interface addresses bound to the primary port std::vector boundAddrs(_bindings[0].allBoundLocalInterfaceAddresses()); for(std::vector::const_iterator i(boundAddrs.begin());i!=boundAddrs.end();++i) _node->addLocalInterfaceAddress(reinterpret_cast(&(*i))); + + // Memoize all local interface addresses for use in clustering -- we tell other cluster members about these + { + Mutex::Lock _l(_localInterfaceAddresses_m); + _localInterfaceAddresses.clear(); + for(int i=0;i<3;++i) { + if (_ports[i] > 0) + _bindings[i].allBoundLocalInterfaceAddresses(_localInterfaceAddresses); + } + } } const unsigned long delay = (dl > now) ? (unsigned long)(dl - now) : 100; @@ -939,6 +997,7 @@ public: } try { + Mutex::Lock _l(_tcpConnections_m); while (!_tcpConnections.empty()) _phy.close((*_tcpConnections.begin())->sock); } catch ( ... ) {} @@ -980,35 +1039,35 @@ public: } #ifdef ZT_SDK - virtual void leave(const char *hp) - { - _node->leave(Utils::hexStrToU64(hp),NULL,NULL); - } + virtual void leave(const char *hp) + { + _node->leave(Utils::hexStrToU64(hp),NULL,NULL); + } virtual void join(const char *hp) { _node->join(Utils::hexStrToU64(hp),NULL,NULL); } - virtual std::string givenHomePath() - { - return _homePath; - } + virtual std::string givenHomePath() + { + return _homePath; + } - virtual EthernetTap * getTap(uint64_t nwid) - { + virtual EthernetTap * getTap(uint64_t nwid) + { Mutex::Lock _l(_nets_m); std::map::const_iterator n(_nets.find(nwid)); if (n == _nets.end()) - return NULL; + return NULL; return n->second.tap; - } + } - virtual EthernetTap *getTap(InetAddress &addr) - { - Mutex::Lock _l(_nets_m); + virtual EthernetTap *getTap(InetAddress &addr) + { + Mutex::Lock _l(_nets_m); std::map::iterator it; - for(it = _nets.begin(); it != _nets.end(); it++) { + for(it = _nets.begin(); it != _nets.end(); it++) { if(it->second.tap) { for(int j=0; jsecond.tap->_ips.size(); j++) { if(it->second.tap->_ips[j].isEqualPrefix(addr) || it->second.tap->_ips[j].ipsEqual(addr)) { @@ -1016,9 +1075,9 @@ public: } } } - } - return NULL; - } + } + return NULL; + } virtual Node * getNode() { @@ -1029,9 +1088,8 @@ public: { Mutex::Lock _l(_nets_m); std::map::iterator i; - for(i = _nets.begin(); i != _nets.end(); i++) { - delete i->second.tap; - } + for(i = _nets.begin(); i != _nets.end(); i++) + delete i->second.tap; } #endif // ZT_SDK @@ -1078,7 +1136,9 @@ public: return true; } - // Internal implementation methods ----------------------------------------- + // ========================================================================= + // Internal implementation methods for control plane, route setup, etc. + // ========================================================================= inline unsigned int handleControlPlaneHttpRequest( const InetAddress &fromAddress, @@ -1759,22 +1819,118 @@ public: } } + void announceStatusToClusterMember(TcpConnection *tc) + { + Buffer<4096> buf; + + buf.appendRandom(16); + buf.addSize(8); // space for MAC + buf.append((uint8_t)CLUSTER_MESSAGE_STATUS); + buf.append(_clusterMemberId); + buf.append((uint16_t)ZEROTIER_ONE_VERSION_MAJOR); + buf.append((uint16_t)ZEROTIER_ONE_VERSION_MINOR); + buf.append((uint16_t)ZEROTIER_ONE_VERSION_REVISION); + + { + Mutex::Lock _l(_localInterfaceAddresses_m); + buf.append((uint16_t)_localInterfaceAddresses.size()); + for(std::vector::const_iterator i(_localInterfaceAddresses.begin());i!=_localInterfaceAddresses.end();++i) { + i->serialize(buf); + if ((buf.size() + 32) > buf.capacity()) + break; + } + } + + Mutex::Lock _l(tc->writeq_m); + + if (tc->writeq.length() == 0) + _phy.setNotifyWritable(tc->sock,true); + + const unsigned int mlen = buf.size(); + tc->writeq.push_back((char)((mlen >> 16) & 0xff)); + tc->writeq.push_back((char)((mlen >> 8) & 0xff)); + tc->writeq.push_back((char)(mlen & 0xff)); + + char *data = reinterpret_cast(buf.unsafeData()); + + uint8_t key[32]; + memcpy(key,_clusterKey,32); + for(int i=0;i<8;++i) key[i] ^= data[i]; + Salsa20 s20(key,data + 8); + + uint8_t macKey[32]; + uint8_t mac[16]; + memset(macKey,0,32); + s20.crypt12(macKey,macKey,32); + s20.crypt12(data + 24,data + 24,mlen - 24); + Poly1305::compute(mac,data + 24,mlen - 24,macKey); + memcpy(data + 16,mac,8); + + tc->writeq.append(data,mlen); + } + + void replicateStateObjectToCluster(const ZT_StateObjectType type,const uint64_t id,const void *const data,const unsigned int len,const uint64_t everyoneBut) + { + uint8_t *buf = new uint8_t[len + 34]; + try { + std::vector sentTo; + if (everyoneBut) + sentTo.push_back(everyoneBut); + Mutex::Lock _l(_tcpConnections_m); + for(std::vector::const_iterator ci(_tcpConnections.begin());ci!=_tcpConnections.end();++ci) { + TcpConnection *const c = *ci; + if ((c->type == TcpConnection::TCP_CLUSTER_BACKPLANE)&&(c->clusterMemberId != 0)&&(std::find(sentTo.begin(),sentTo.end(),c->clusterMemberId) == sentTo.end())) { + sentTo.push_back(c->clusterMemberId); + Mutex::Lock _l2(c->writeq_m); + + if (c->writeq.length() == 0) + _phy.setNotifyWritable(c->sock,true); + + const unsigned int mlen = len + 34; + c->writeq.push_back((char)((mlen >> 16) & 0xff)); + c->writeq.push_back((char)((mlen >> 8) & 0xff)); + c->writeq.push_back((char)(mlen & 0xff)); + + Utils::getSecureRandom(buf,16); + + buf[24] = (uint8_t)CLUSTER_MESSAGE_STATE_OBJECT; + buf[25] = (uint8_t)type; + buf[26] = (uint8_t)((id >> 56) & 0xff); + buf[27] = (uint8_t)((id >> 48) & 0xff); + buf[28] = (uint8_t)((id >> 40) & 0xff); + buf[29] = (uint8_t)((id >> 32) & 0xff); + buf[30] = (uint8_t)((id >> 24) & 0xff); + buf[31] = (uint8_t)((id >> 16) & 0xff); + buf[32] = (uint8_t)((id >> 8) & 0xff); + buf[33] = (uint8_t)(id & 0xff); + memcpy(buf + 34,data,len); + + uint8_t key[32]; + memcpy(key,_clusterKey,32); + for(int i=0;i<8;++i) key[i] ^= buf[i]; + Salsa20 s20(key,buf + 8); + + uint8_t macKey[32]; + uint8_t mac[16]; + memset(macKey,0,32); + s20.crypt12(macKey,macKey,32); + s20.crypt12(buf + 24,buf + 24,mlen - 24); + Poly1305::compute(mac,buf + 24,mlen - 24,macKey); + memcpy(buf + 16,mac,8); + + c->writeq.append(reinterpret_cast(buf),len + 34); + } + } + } catch ( ... ) {} // sanity check + delete [] buf; + } + // ========================================================================= // Handlers for Node and Phy<> callbacks // ========================================================================= inline void phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *localAddr,const struct sockaddr *from,void *data,unsigned long len) { -/* -#ifdef ZT_ENABLE_CLUSTER - if (sock == _clusterMessageSocket) { - _lastDirectReceiveFromGlobal = OSUtils::now(); - _node->clusterHandleIncomingMessage(data,len); - return; - } -#endif -*/ - if ((len >= 16)&&(reinterpret_cast(from)->ipScope() == InetAddress::IP_SCOPE_GLOBAL)) _lastDirectReceiveFromGlobal = OSUtils::now(); @@ -1798,38 +1954,27 @@ public: inline void phyOnTcpConnect(PhySocket *sock,void **uptr,bool success) { - if (!success) + if (!success) { + phyOnTcpClose(sock,uptr); return; + } - // Outgoing TCP connections are always TCP fallback tunnel connections. - - TcpConnection *tc = new TcpConnection(); - _tcpConnections.insert(tc); - - tc->type = TcpConnection::TCP_TUNNEL_OUTGOING; - tc->shouldKeepAlive = true; - tc->parent = this; + TcpConnection *const tc = reinterpret_cast(*uptr); + if (!tc) { // sanity check + _phy.close(sock,true); + return; + } tc->sock = sock; - // from and parser are not used - tc->messageSize = 0; // unused - tc->lastActivity = OSUtils::now(); - // HTTP stuff is not used - tc->writeBuf = ""; - *uptr = (void *)tc; - - // Send "hello" message - tc->writeBuf.push_back((char)0x17); - tc->writeBuf.push_back((char)0x03); - tc->writeBuf.push_back((char)0x03); // fake TLS 1.2 header - tc->writeBuf.push_back((char)0x00); - tc->writeBuf.push_back((char)0x04); // mlen == 4 - tc->writeBuf.push_back((char)ZEROTIER_ONE_VERSION_MAJOR); - tc->writeBuf.push_back((char)ZEROTIER_ONE_VERSION_MINOR); - tc->writeBuf.push_back((char)((ZEROTIER_ONE_VERSION_REVISION >> 8) & 0xff)); - tc->writeBuf.push_back((char)(ZEROTIER_ONE_VERSION_REVISION & 0xff)); - _phy.setNotifyWritable(sock,true); - - _tcpFallbackTunnel = tc; + + if (tc->type == TcpConnection::TCP_TUNNEL_OUTGOING) { + if (_tcpFallbackTunnel) + _phy.close(_tcpFallbackTunnel->sock); + _tcpFallbackTunnel = tc; + _phy.streamSend(sock,ZT_TCP_TUNNEL_HELLO,sizeof(ZT_TCP_TUNNEL_HELLO)); + } else if (tc->type == TcpConnection::TCP_CLUSTER_BACKPLANE) { + } else { + _phy.close(sock,true); + } } inline void phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,const struct sockaddr *from) @@ -1839,149 +1984,313 @@ public: return; } else { TcpConnection *tc = new TcpConnection(); - _tcpConnections.insert(tc); - tc->type = TcpConnection::TCP_HTTP_INCOMING; - tc->shouldKeepAlive = true; + { + Mutex::Lock _l(_tcpConnections_m); + _tcpConnections.push_back(tc); + } + + tc->type = TcpConnection::TCP_UNCATEGORIZED_INCOMING; tc->parent = this; tc->sock = sockN; tc->from = from; + tc->lastReceive = OSUtils::now(); http_parser_init(&(tc->parser),HTTP_REQUEST); tc->parser.data = (void *)tc; tc->messageSize = 0; - tc->lastActivity = OSUtils::now(); - tc->currentHeaderField = ""; - tc->currentHeaderValue = ""; - tc->url = ""; - tc->status = ""; - tc->headers.clear(); - tc->body = ""; - tc->writeBuf = ""; + *uptrN = (void *)tc; } } - inline void phyOnTcpClose(PhySocket *sock,void **uptr) + void phyOnTcpClose(PhySocket *sock,void **uptr) { TcpConnection *tc = (TcpConnection *)*uptr; if (tc) { - if (tc == _tcpFallbackTunnel) + if (tc == _tcpFallbackTunnel) { _tcpFallbackTunnel = (TcpConnection *)0; - _tcpConnections.erase(tc); + } + { + Mutex::Lock _l(_tcpConnections_m); + _tcpConnections.erase(std::remove(_tcpConnections.begin(),_tcpConnections.end(),tc),_tcpConnections.end()); + } delete tc; } } - inline void phyOnTcpData(PhySocket *sock,void **uptr,void *data,unsigned long len) + void phyOnTcpData(PhySocket *sock,void **uptr,void *data,unsigned long len) { - TcpConnection *tc = reinterpret_cast(*uptr); - switch(tc->type) { + try { + if (!len) return; // sanity check, should never happen + TcpConnection *tc = reinterpret_cast(*uptr); + tc->lastReceive = OSUtils::now(); + switch(tc->type) { + + case TcpConnection::TCP_UNCATEGORIZED_INCOMING: + switch(reinterpret_cast(data)[0]) { + // 0x93 is first byte of cluster backplane connections + case 0x93: { + bool allow = false; + { + Mutex::Lock _l(_localConfig_m); + for(std::vector< InetAddress >::const_iterator i(_clusterBackplaneAddresses.begin());i!=_clusterBackplaneAddresses.end();++i) { + if (tc->from.ipsEqual(*i)) { + allow = true; + break; + } + } + } + if (allow) { // note that we also auth each packet cryptographically -- this is just a first line sanity check + tc->type = TcpConnection::TCP_CLUSTER_BACKPLANE; + tc->clusterMemberId = 0; // unknown, waiting for first status message + announceStatusToClusterMember(tc); + if (len > 1) + phyOnTcpData(sock,uptr,reinterpret_cast(data) + 1,len - 1); + } else { + _phy.close(sock); + } + } break; + + // HTTP: GET, PUT, POST, HEAD + case 'G': + case 'P': + case 'H': { + bool allow; + { + Mutex::Lock _l(_localConfig_m); + if (_allowManagementFrom.size() == 0) { + allow = (tc->from.ipScope() == InetAddress::IP_SCOPE_LOOPBACK); + } else { + allow = false; + for(std::vector::const_iterator i(_allowManagementFrom.begin());i!=_allowManagementFrom.end();++i) { + if (i->containsAddress(tc->from)) { + allow = true; + break; + } + } + } + } + if (allow) { + tc->type = TcpConnection::TCP_HTTP_INCOMING; + phyOnTcpData(sock,uptr,data,len); + } else { + _phy.close(sock); + } + } break; + + // Drop unknown protocols + default: + _phy.close(sock); + break; + } + return; - case TcpConnection::TCP_HTTP_INCOMING: - case TcpConnection::TCP_HTTP_OUTGOING: - http_parser_execute(&(tc->parser),&HTTP_PARSER_SETTINGS,(const char *)data,len); - if ((tc->parser.upgrade)||(tc->parser.http_errno != HPE_OK)) { - _phy.close(sock); + case TcpConnection::TCP_HTTP_INCOMING: + case TcpConnection::TCP_HTTP_OUTGOING: + http_parser_execute(&(tc->parser),&HTTP_PARSER_SETTINGS,(const char *)data,len); + if ((tc->parser.upgrade)||(tc->parser.http_errno != HPE_OK)) + _phy.close(sock); return; - } - break; - case TcpConnection::TCP_TUNNEL_OUTGOING: - tc->body.append((const char *)data,len); - while (tc->body.length() >= 5) { - const char *data = tc->body.data(); - const unsigned long mlen = ( ((((unsigned long)data[3]) & 0xff) << 8) | (((unsigned long)data[4]) & 0xff) ); - if (tc->body.length() >= (mlen + 5)) { - InetAddress from; + case TcpConnection::TCP_TUNNEL_OUTGOING: + tc->readq.append((const char *)data,len); + while (tc->readq.length() >= 5) { + const char *data = tc->readq.data(); + const unsigned long mlen = ( ((((unsigned long)data[3]) & 0xff) << 8) | (((unsigned long)data[4]) & 0xff) ); + if (tc->readq.length() >= (mlen + 5)) { + InetAddress from; unsigned long plen = mlen; // payload length, modified if there's an IP header - data += 5; // skip forward past pseudo-TLS junk and mlen - if (plen == 4) { - // Hello message, which isn't sent by proxy and would be ignored by client - } else if (plen) { - // Messages should contain IPv4 or IPv6 source IP address data - switch(data[0]) { - case 4: // IPv4 - if (plen >= 7) { - from.set((const void *)(data + 1),4,((((unsigned int)data[5]) & 0xff) << 8) | (((unsigned int)data[6]) & 0xff)); - data += 7; // type + 4 byte IP + 2 byte port - plen -= 7; - } else { + data += 5; // skip forward past pseudo-TLS junk and mlen + if (plen == 4) { + // Hello message, which isn't sent by proxy and would be ignored by client + } else if (plen) { + // Messages should contain IPv4 or IPv6 source IP address data + switch(data[0]) { + case 4: // IPv4 + if (plen >= 7) { + from.set((const void *)(data + 1),4,((((unsigned int)data[5]) & 0xff) << 8) | (((unsigned int)data[6]) & 0xff)); + data += 7; // type + 4 byte IP + 2 byte port + plen -= 7; + } else { + _phy.close(sock); + return; + } + break; + case 6: // IPv6 + if (plen >= 19) { + from.set((const void *)(data + 1),16,((((unsigned int)data[17]) & 0xff) << 8) | (((unsigned int)data[18]) & 0xff)); + data += 19; // type + 16 byte IP + 2 byte port + plen -= 19; + } else { + _phy.close(sock); + return; + } + break; + case 0: // none/omitted + ++data; + --plen; + break; + default: // invalid address type _phy.close(sock); return; - } - break; - case 6: // IPv6 - if (plen >= 19) { - from.set((const void *)(data + 1),16,((((unsigned int)data[17]) & 0xff) << 8) | (((unsigned int)data[18]) & 0xff)); - data += 19; // type + 16 byte IP + 2 byte port - plen -= 19; - } else { + } + + if (from) { + InetAddress fakeTcpLocalInterfaceAddress((uint32_t)0xffffffff,0xffff); + const ZT_ResultCode rc = _node->processWirePacket( + (void *)0, + OSUtils::now(), + reinterpret_cast(&fakeTcpLocalInterfaceAddress), + reinterpret_cast(&from), + data, + plen, + &_nextBackgroundTaskDeadline); + if (ZT_ResultCode_isFatal(rc)) { + char tmp[256]; + Utils::snprintf(tmp,sizeof(tmp),"fatal error code from processWirePacket: %d",(int)rc); + Mutex::Lock _l(_termReason_m); + _termReason = ONE_UNRECOVERABLE_ERROR; + _fatalErrorMessage = tmp; + this->terminate(); _phy.close(sock); return; } + } + } + + if (tc->readq.length() > (mlen + 5)) + tc->readq.erase(tc->readq.begin(),tc->readq.begin() + (mlen + 5)); + else tc->readq.clear(); + } else break; + } + return; + + case TcpConnection::TCP_CLUSTER_BACKPLANE: + tc->readq.append((const char *)data,len); + if (tc->readq.length() >= 28) { // got 3-byte message size + 16-byte IV + 8-byte MAC + 1-byte type (encrypted) + uint8_t *data = reinterpret_cast(const_cast(tc->readq.data())); + unsigned long mlen = ( ((unsigned long)data[0] << 16) | ((unsigned long)data[1] << 8) | (unsigned long)data[2] ); + if ((mlen < 25)||(mlen > ZT_TCP_MAX_WRITEQ_SIZE)) { + _phy.close(sock); + return; + } else if (tc->readq.length() >= (mlen + 3)) { // got entire message + data += 3; + + uint8_t key[32]; + memcpy(key,_clusterKey,32); + for(int i=0;i<8;++i) key[i] ^= data[i]; // first 8 bytes of IV get XORed with key + Salsa20 s20(key,data + 8); // last 8 bytes of IV are fed into Salsa20 directly as its 64-bit IV + + uint8_t macKey[32]; + uint8_t mac[16]; + memset(macKey,0,32); + s20.crypt12(macKey,macKey,32); + Poly1305::compute(mac,data + 24,mlen - 24,macKey); + if (!Utils::secureEq(mac,data + 16,8)) { + _phy.close(sock); + return; + } + s20.crypt12(data + 24,data + 24,mlen - 24); + + switch((ClusterMessageType)data[24]) { + case CLUSTER_MESSAGE_STATUS: + if (mlen > (25 + 16)) { + Buffer<4096> tmp(data + 25,mlen - 25); + try { + tc->clusterMemberId = tmp.at(0); + if (tc->clusterMemberId == _clusterMemberId) { // shouldn't happen, but don't allow self-to-self + _phy.close(sock); + return; + } + tc->clusterMemberVersionMajor = tmp.at(8); + tc->clusterMemberVersionMinor = tmp.at(10); + tc->clusterMemberVersionRev = tmp.at(12); + const unsigned int clusterMemberLocalAddressCount = tmp.at(14); + std::vector la; + unsigned int ptr = 16; + for(unsigned int k=0;kclusterMemberLocalAddresses.swap(la); + } catch ( ... ) {} + } + break; + + case CLUSTER_MESSAGE_STATE_OBJECT: + if (mlen >= (25 + 9)) { // type + object ID + [data] + const uint64_t objId = ( + ((uint64_t)data[26] << 56) | + ((uint64_t)data[27] << 48) | + ((uint64_t)data[28] << 40) | + ((uint64_t)data[29] << 32) | + ((uint64_t)data[30] << 24) | + ((uint64_t)data[31] << 16) | + ((uint64_t)data[32] << 8) | + (uint64_t)data[33] + ); + if (_node->processStateUpdate((void *)0,(ZT_StateObjectType)data[25],objId,data + 34,(unsigned int)(mlen - 34)) == ZT_RESULT_OK) + replicateStateObjectToCluster((ZT_StateObjectType)data[25],objId,data + 34,(unsigned int)(mlen - 34),tc->clusterMemberId); + } break; - case 0: // none/omitted - ++data; - --plen; + + case CLUSTER_MESSAGE_PROXY_SEND: + if (mlen > 25) { + Buffer<4096> tmp(data + 25,mlen - 25); + try { + InetAddress dest,src; + unsigned int ptr = dest.deserialize(tmp); + ptr += src.deserialize(tmp,ptr); + if (ptr < tmp.size()) { + bool local; + { + Mutex::Lock _l(_localInterfaceAddresses_m); + local = (std::find(_localInterfaceAddresses.begin(),_localInterfaceAddresses.end(),src) != _localInterfaceAddresses.end()); + } + if (local) + nodeWirePacketSendFunction(&src,&dest,reinterpret_cast(tmp.data()) + ptr,tmp.size() - ptr,0); + } + } catch ( ... ) {} + } break; - default: // invalid address type - _phy.close(sock); - return; } - if (from) { - InetAddress fakeTcpLocalInterfaceAddress((uint32_t)0xffffffff,0xffff); - const ZT_ResultCode rc = _node->processWirePacket( - (void *)0, - OSUtils::now(), - reinterpret_cast(&fakeTcpLocalInterfaceAddress), - reinterpret_cast(&from), - data, - plen, - &_nextBackgroundTaskDeadline); - if (ZT_ResultCode_isFatal(rc)) { - char tmp[256]; - Utils::snprintf(tmp,sizeof(tmp),"fatal error code from processWirePacket: %d",(int)rc); - Mutex::Lock _l(_termReason_m); - _termReason = ONE_UNRECOVERABLE_ERROR; - _fatalErrorMessage = tmp; - this->terminate(); - _phy.close(sock); - return; - } - } + tc->readq.erase(tc->readq.begin(),tc->readq.begin() + mlen); } + } + return; - if (tc->body.length() > (mlen + 5)) - tc->body = tc->body.substr(mlen + 5); - else tc->body = ""; - } else break; - } - break; - + } + } catch ( ... ) { + _phy.close(sock); } } inline void phyOnTcpWritable(PhySocket *sock,void **uptr) { TcpConnection *tc = reinterpret_cast(*uptr); - Mutex::Lock _l(tc->writeBuf_m); - if (tc->writeBuf.length() > 0) { - long sent = (long)_phy.streamSend(sock,tc->writeBuf.data(),(unsigned long)tc->writeBuf.length(),true); - if (sent > 0) { - tc->lastActivity = OSUtils::now(); - if ((unsigned long)sent >= (unsigned long)tc->writeBuf.length()) { - tc->writeBuf.clear(); - _phy.setNotifyWritable(sock,false); - if (!tc->shouldKeepAlive) - _phy.close(sock); // will call close handler to delete from _tcpConnections - } else { - tc->writeBuf.erase(tc->writeBuf.begin(),tc->writeBuf.begin() + sent); + bool closeit = false; + { + Mutex::Lock _l(tc->writeq_m); + if (tc->writeq.length() > 0) { + long sent = (long)_phy.streamSend(sock,tc->writeq.data(),(unsigned long)tc->writeq.length(),true); + if (sent > 0) { + if ((unsigned long)sent >= (unsigned long)tc->writeq.length()) { + tc->writeq.clear(); + _phy.setNotifyWritable(sock,false); + + if (tc->type == TcpConnection::TCP_HTTP_INCOMING) + closeit = true; // HTTP keep alive not supported + } else { + tc->writeq.erase(tc->writeq.begin(),tc->writeq.begin() + sent); + } } + } else { + _phy.setNotifyWritable(sock,false); } - } else { - _phy.setNotifyWritable(sock,false); } + if (closeit) + _phy.close(sock); } inline void phyOnFileDescriptorActivity(PhySocket *sock,void **uptr,bool readable,bool writable) {} @@ -2148,6 +2457,27 @@ public: inline int nodeStateGetFunction(enum ZT_StateObjectType type,uint64_t id,void *data,unsigned int maxlen) { + char p[4096]; + FILE *f = (FILE *)0; + switch(type) { + case ZT_STATE_OBJECT_IDENTITY_PUBLIC: + break; + case ZT_STATE_OBJECT_IDENTITY_SECRET: + break; + case ZT_STATE_OBJECT_PEER_IDENTITY: + break; + case ZT_STATE_OBJECT_NETWORK_CONFIG: + break; + case ZT_STATE_OBJECT_PLANET: + break; + case ZT_STATE_OBJECT_MOON: + break; + default: + return -1; + } + if (f) { + } + return -1; } inline int nodeWirePacketSendFunction(const struct sockaddr_storage *localAddr,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl) @@ -2178,28 +2508,41 @@ public: const uint64_t now = OSUtils::now(); if (((now - _lastDirectReceiveFromGlobal) > ZT_TCP_FALLBACK_AFTER)&&((now - _lastRestart) > ZT_TCP_FALLBACK_AFTER)) { if (_tcpFallbackTunnel) { - Mutex::Lock _l(_tcpFallbackTunnel->writeBuf_m); - if (!_tcpFallbackTunnel->writeBuf.length()) + Mutex::Lock _l(_tcpFallbackTunnel->writeq_m); + if (_tcpFallbackTunnel->writeq.length() == 0) _phy.setNotifyWritable(_tcpFallbackTunnel->sock,true); - unsigned long mlen = len + 7; - _tcpFallbackTunnel->writeBuf.push_back((char)0x17); - _tcpFallbackTunnel->writeBuf.push_back((char)0x03); - _tcpFallbackTunnel->writeBuf.push_back((char)0x03); // fake TLS 1.2 header - _tcpFallbackTunnel->writeBuf.push_back((char)((mlen >> 8) & 0xff)); - _tcpFallbackTunnel->writeBuf.push_back((char)(mlen & 0xff)); - _tcpFallbackTunnel->writeBuf.push_back((char)4); // IPv4 - _tcpFallbackTunnel->writeBuf.append(reinterpret_cast(reinterpret_cast(&(reinterpret_cast(addr)->sin_addr.s_addr))),4); - _tcpFallbackTunnel->writeBuf.append(reinterpret_cast(reinterpret_cast(&(reinterpret_cast(addr)->sin_port))),2); - _tcpFallbackTunnel->writeBuf.append((const char *)data,len); + const unsigned long mlen = len + 7; + _tcpFallbackTunnel->writeq.push_back((char)0x17); + _tcpFallbackTunnel->writeq.push_back((char)0x03); + _tcpFallbackTunnel->writeq.push_back((char)0x03); // fake TLS 1.2 header + _tcpFallbackTunnel->writeq.push_back((char)((mlen >> 8) & 0xff)); + _tcpFallbackTunnel->writeq.push_back((char)(mlen & 0xff)); + _tcpFallbackTunnel->writeq.push_back((char)4); // IPv4 + _tcpFallbackTunnel->writeq.append(reinterpret_cast(reinterpret_cast(&(reinterpret_cast(addr)->sin_addr.s_addr))),4); + _tcpFallbackTunnel->writeq.append(reinterpret_cast(reinterpret_cast(&(reinterpret_cast(addr)->sin_port))),2); + _tcpFallbackTunnel->writeq.append((const char *)data,len); } else if (((now - _lastSendToGlobalV4) < ZT_TCP_FALLBACK_AFTER)&&((now - _lastSendToGlobalV4) > (ZT_PING_CHECK_INVERVAL / 2))) { bool connected = false; const InetAddress addr(ZT_TCP_FALLBACK_RELAY); - _phy.tcpConnect(reinterpret_cast(&addr),connected); + + TcpConnection *tc = new TcpConnection(); + { + Mutex::Lock _l(_tcpConnections_m); + _tcpConnections.push_back(tc); + } + + tc->type = TcpConnection::TCP_TUNNEL_OUTGOING; + tc->parent = this; + tc->sock = (PhySocket *)0; // set in connect handler + tc->messageSize = 0; + + _phy.tcpConnect(reinterpret_cast(&addr),connected,(void *)tc,true); } } _lastSendToGlobalV4 = now; } #endif // ZT_TCP_FALLBACK_RELAY + } else if (addr->ss_family == AF_INET6) { if (reinterpret_cast(localAddr)->sin6_port != 0) { const uint16_t lp = reinterpret_cast(localAddr)->sin6_port; @@ -2298,39 +2641,22 @@ public: inline void onHttpRequestToServer(TcpConnection *tc) { - char tmpn[256]; + char tmpn[4096]; std::string data; std::string contentType("text/plain"); // default if not changed in handleRequest() unsigned int scode = 404; - bool allow; - { - Mutex::Lock _l(_localConfig_m); - if (_allowManagementFrom.size() == 0) { - allow = (tc->from.ipScope() == InetAddress::IP_SCOPE_LOOPBACK); - } else { - allow = false; - for(std::vector::const_iterator i(_allowManagementFrom.begin());i!=_allowManagementFrom.end();++i) { - if (i->containsAddress(tc->from)) { - allow = true; - break; - } - } - } - } + // Note that we check allowed IP ranges when HTTP connections are first detected in + // phyOnTcpData(). If we made it here the source IP is okay. - if (allow) { - try { - scode = handleControlPlaneHttpRequest(tc->from,tc->parser.method,tc->url,tc->headers,tc->body,data,contentType); - } catch (std::exception &exc) { - fprintf(stderr,"WARNING: unexpected exception processing control HTTP request: %s" ZT_EOL_S,exc.what()); - scode = 500; - } catch ( ... ) { - fprintf(stderr,"WARNING: unexpected exception processing control HTTP request: unknown exceptino" ZT_EOL_S); - scode = 500; - } - } else { - scode = 401; + try { + scode = handleControlPlaneHttpRequest(tc->from,tc->parser.method,tc->url,tc->headers,tc->readq,data,contentType); + } catch (std::exception &exc) { + fprintf(stderr,"WARNING: unexpected exception processing control HTTP request: %s" ZT_EOL_S,exc.what()); + scode = 500; + } catch ( ... ) { + fprintf(stderr,"WARNING: unexpected exception processing control HTTP request: unknown exceptino" ZT_EOL_S); + scode = 500; } const char *scodestr; @@ -2346,19 +2672,16 @@ public: default: scodestr = "Error"; break; } - Utils::snprintf(tmpn,sizeof(tmpn),"HTTP/1.1 %.3u %s\r\nCache-Control: no-cache\r\nPragma: no-cache\r\n",scode,scodestr); + Utils::snprintf(tmpn,sizeof(tmpn),"HTTP/1.1 %.3u %s\r\nCache-Control: no-cache\r\nPragma: no-cache\r\nContent-Type: %s\r\nContent-Length: %lu\r\nConnection: close\r\n\r\n", + scode, + scodestr, + contentType.c_str(), + (unsigned long)data.length()); { - Mutex::Lock _l(tc->writeBuf_m); - tc->writeBuf.assign(tmpn); - tc->writeBuf.append("Content-Type: "); - tc->writeBuf.append(contentType); - Utils::snprintf(tmpn,sizeof(tmpn),"\r\nContent-Length: %lu\r\n",(unsigned long)data.length()); - tc->writeBuf.append(tmpn); - if (!tc->shouldKeepAlive) - tc->writeBuf.append("Connection: close\r\n"); - tc->writeBuf.append("\r\n"); + Mutex::Lock _l(tc->writeq_m); + tc->writeq = tmpn; if (tc->parser.method != HTTP_HEAD) - tc->writeBuf.append(data); + tc->writeq.append(data); } _phy.setNotifyWritable(tc->sock,true); @@ -2366,8 +2689,7 @@ public: inline void onHttpResponseFromClient(TcpConnection *tc) { - if (!tc->shouldKeepAlive) - _phy.close(tc->sock); // will call close handler, which deletes from _tcpConnections + _phy.close(tc->sock); } bool shouldBindInterface(const char *ifname,const InetAddress &ifaddr) @@ -2472,10 +2794,10 @@ static int ShttpOnMessageBegin(http_parser *parser) tc->currentHeaderField = ""; tc->currentHeaderValue = ""; tc->messageSize = 0; - tc->url = ""; - tc->status = ""; + tc->url.clear(); + tc->status.clear(); tc->headers.clear(); - tc->body = ""; + tc->readq.clear(); return 0; } static int ShttpOnUrl(http_parser *parser,const char *ptr,size_t length) @@ -2492,16 +2814,7 @@ static int ShttpOnStatus(http_parser *parser,const char *ptr,size_t length) #else static int ShttpOnStatus(http_parser *parser) #endif -{ - /* - TcpConnection *tc = reinterpret_cast(parser->data); - tc->messageSize += (unsigned long)length; - if (tc->messageSize > ZT_MAX_HTTP_MESSAGE_SIZE) - return -1; - tc->status.append(ptr,length); - */ - return 0; -} +{ return 0; } static int ShttpOnHeaderField(http_parser *parser,const char *ptr,size_t length) { TcpConnection *tc = reinterpret_cast(parser->data); @@ -2539,14 +2852,12 @@ static int ShttpOnBody(http_parser *parser,const char *ptr,size_t length) tc->messageSize += (unsigned long)length; if (tc->messageSize > ZT_MAX_HTTP_MESSAGE_SIZE) return -1; - tc->body.append(ptr,length); + tc->readq.append(ptr,length); return 0; } static int ShttpOnMessageComplete(http_parser *parser) { TcpConnection *tc = reinterpret_cast(parser->data); - tc->shouldKeepAlive = (http_should_keep_alive(parser) != 0); - tc->lastActivity = OSUtils::now(); if (tc->type == TcpConnection::TCP_HTTP_INCOMING) { tc->parent->onHttpRequestToServer(tc); } else { -- cgit v1.2.3 From 4f2179b0dfb06e7f1b802af89ed57b07c84e4195 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 5 Jun 2017 13:42:43 -0700 Subject: . --- service/OneService.cpp | 61 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 2 deletions(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 6365131e..472115da 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1925,6 +1925,49 @@ public: delete [] buf; } + void writeStateObject(enum ZT_StateObjectType type,uint64_t id,const void *data,int len) + { + char p[4096]; + bool secure = false; + switch(type) { + case ZT_STATE_OBJECT_IDENTITY_PUBLIC: + Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str()); + break; + case ZT_STATE_OBJECT_IDENTITY_SECRET: + Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str()); + secure = true; + break; + case ZT_STATE_OBJECT_PEER_IDENTITY: + Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "iddb.d/%.10llx",_homePath.c_str(),(unsigned long long)id); + break; + case ZT_STATE_OBJECT_NETWORK_CONFIG: + Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id); + secure = true; + break; + case ZT_STATE_OBJECT_PLANET: + Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); + break; + case ZT_STATE_OBJECT_MOON: + Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id); + break; + default: + p[0] = (char)0; + break; + } + if (p[0]) { + FILE *f = fopen(p,"w"); + if (f) { + if (fwrite(data,len,1,f) != 1) + fprintf(stderr,"WARNING: unable to write to file: %s (I/O error)" ZT_EOL_S,p); + fclose(f); + if (secure) + OSUtils::lockDownFile(p,false); + } else { + fprintf(stderr,"WARNING: unable to write to file: %s (unable to open)" ZT_EOL_S,p); + } + } + } + // ========================================================================= // Handlers for Node and Phy<> callbacks // ========================================================================= @@ -2229,8 +2272,10 @@ public: ((uint64_t)data[32] << 8) | (uint64_t)data[33] ); - if (_node->processStateUpdate((void *)0,(ZT_StateObjectType)data[25],objId,data + 34,(unsigned int)(mlen - 34)) == ZT_RESULT_OK) + if (_node->processStateUpdate((void *)0,(ZT_StateObjectType)data[25],objId,data + 34,(unsigned int)(mlen - 34)) == ZT_RESULT_OK) { + writeStateObject((ZT_StateObjectType)data[25],objId,data + 34,(unsigned int)(mlen - 34)); replicateStateObjectToCluster((ZT_StateObjectType)data[25],objId,data + 34,(unsigned int)(mlen - 34),tc->clusterMemberId); + } } break; @@ -2453,29 +2498,41 @@ public: inline void nodeStatePutFunction(enum ZT_StateObjectType type,uint64_t id,const void *data,int len) { + writeStateObject(type,id,data,len); + replicateStateObjectToCluster(type,id,data,len,0); } inline int nodeStateGetFunction(enum ZT_StateObjectType type,uint64_t id,void *data,unsigned int maxlen) { char p[4096]; - FILE *f = (FILE *)0; switch(type) { case ZT_STATE_OBJECT_IDENTITY_PUBLIC: + Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str()); break; case ZT_STATE_OBJECT_IDENTITY_SECRET: + Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str()); break; case ZT_STATE_OBJECT_PEER_IDENTITY: + Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "iddb.d/%.10llx",_homePath.c_str(),(unsigned long long)id); break; case ZT_STATE_OBJECT_NETWORK_CONFIG: + Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id); break; case ZT_STATE_OBJECT_PLANET: + Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); break; case ZT_STATE_OBJECT_MOON: + Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id); break; default: return -1; } + FILE *f = fopen(p,"r"); if (f) { + int n = (int)fread(data,1,maxlen,f); + fclose(f); + if (n >= 0) + return n; } return -1; } -- cgit v1.2.3 From 951d911531ec1eaa246e234a7b31b6bf5bc6bb79 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 6 Jun 2017 16:11:19 -0700 Subject: Last bit of new cluster code, ready to test. --- osdep/Binder.hpp | 215 ++++++++++---------- service/OneService.cpp | 531 ++++++++++++++++++++++++++++--------------------- 2 files changed, 414 insertions(+), 332 deletions(-) (limited to 'service/OneService.cpp') diff --git a/osdep/Binder.hpp b/osdep/Binder.hpp index fee1c3da..1839ecc2 100644 --- a/osdep/Binder.hpp +++ b/osdep/Binder.hpp @@ -66,11 +66,7 @@ #include "Phy.hpp" #include "OSUtils.hpp" -/** - * Period between binder rescans/refreshes - * - * OneService also does this on detected restarts. - */ +// Period between refreshes of bindings #define ZT_BINDER_REFRESH_PERIOD 30000 namespace ZeroTier { @@ -105,10 +101,7 @@ public: Binder() {} /** - * Close all bound ports - * - * This should be called on shutdown. It closes listen sockets and UDP ports - * but not TCP connections from any TCP listen sockets. + * Close all bound ports, should be called on shutdown * * @param phy Physical interface */ @@ -116,9 +109,9 @@ public: void closeAll(Phy &phy) { Mutex::Lock _l(_lock); - for(typename std::vector<_Binding>::const_iterator i(_bindings.begin());i!=_bindings.end();++i) { - phy.close(i->udpSock,false); - phy.close(i->tcpListenSock,false); + for(std::vector<_Binding>::iterator b(_bindings.begin());b!=_bindings.end();++b) { + phy.close(b->udpSock,false); + phy.close(b->tcpListenSock,false); } } @@ -129,7 +122,7 @@ public: * changes, on startup, or periodically (e.g. every 30-60s). * * @param phy Physical interface - * @param port Port to bind to on all interfaces (TCP and UDP) + * @param ports Ports to bind on all interfaces * @param ignoreInterfacesByName Ignore these interfaces by name * @param ignoreInterfacesByNamePrefix Ignore these interfaces by name-prefix (starts-with, e.g. zt ignores zt*) * @param ignoreInterfacesByAddress Ignore these interfaces by address @@ -137,11 +130,10 @@ public: * @tparam INTERFACE_CHECKER Type for class containing shouldBindInterface() method */ template - void refresh(Phy &phy,unsigned int port,INTERFACE_CHECKER &ifChecker) + void refresh(Phy &phy,unsigned int *ports,unsigned int portCount,INTERFACE_CHECKER &ifChecker) { std::map localIfAddrs; - PhySocket *udps; - //PhySocket *tcps; + PhySocket *udps,*tcps; Mutex::Lock _l(_lock); #ifdef __WINDOWS__ @@ -161,8 +153,10 @@ public: case InetAddress::IP_SCOPE_GLOBAL: case InetAddress::IP_SCOPE_SHARED: case InetAddress::IP_SCOPE_PRIVATE: - ip.setPort(port); - localIfAddrs.insert(std::pair(ip,std::string())); + for(int x=0;x(ip,std::string())); + } break; } } @@ -231,8 +225,10 @@ public: case InetAddress::IP_SCOPE_GLOBAL: case InetAddress::IP_SCOPE_SHARED: case InetAddress::IP_SCOPE_PRIVATE: - ip.setPort(port); - localIfAddrs.insert(std::pair(ip,std::string(devname))); + for(int x=0;x(ip,std::string(devname))); + } break; } } @@ -249,11 +245,8 @@ public: configuration.ifc_buf = nullptr; if (controlfd < 0) goto ip4_address_error; - if (ioctl(controlfd, SIOCGIFCONF, &configuration) < 0) goto ip4_address_error; - configuration.ifc_buf = (char*)malloc(configuration.ifc_len); - if (ioctl(controlfd, SIOCGIFCONF, &configuration) < 0) goto ip4_address_error; for (int i=0; i < (int)(configuration.ifc_len / sizeof(ifreq)); i ++) { @@ -262,9 +255,8 @@ public: if (addr->sa_family != AF_INET) continue; std::string ifname = request.ifr_ifrn.ifrn_name; // name can either be just interface name or interface name followed by ':' and arbitrary label - if (ifname.find(':') != std::string::npos) { + if (ifname.find(':') != std::string::npos) ifname = ifname.substr(0, ifname.find(':')); - } InetAddress ip(&(((struct sockaddr_in *)addr)->sin_addr),4,0); if (ifChecker.shouldBindInterface(ifname.c_str(), ip)) { @@ -274,8 +266,10 @@ public: case InetAddress::IP_SCOPE_GLOBAL: case InetAddress::IP_SCOPE_SHARED: case InetAddress::IP_SCOPE_PRIVATE: - ip.setPort(port); - localIfAddrs.insert(std::pair(ip, ifname)); + for(int x=0;x(ip,ifname)); + } break; } } @@ -306,8 +300,10 @@ public: case InetAddress::IP_SCOPE_GLOBAL: case InetAddress::IP_SCOPE_SHARED: case InetAddress::IP_SCOPE_PRIVATE: - ip.setPort(port); - localIfAddrs.insert(std::pair(ip,std::string(ifa->ifa_name))); + for(int x=0;x(ip,std::string(ifa->ifa_name))); + } break; } } @@ -322,59 +318,57 @@ public: // Default to binding to wildcard if we can't enumerate addresses if (localIfAddrs.empty()) { - localIfAddrs.insert(std::pair(InetAddress((uint32_t)0,port),std::string())); - localIfAddrs.insert(std::pair(InetAddress((const void *)"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",16,port),std::string())); + for(int x=0;x(InetAddress((uint32_t)0,ports[x]),std::string())); + localIfAddrs.insert(std::pair(InetAddress((const void *)"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",16,ports[x]),std::string())); + } } - // Close any old bindings to anything that doesn't exist anymore - for(typename std::vector<_Binding>::const_iterator bi(_bindings.begin());bi!=_bindings.end();++bi) { - if (localIfAddrs.find(bi->address) == localIfAddrs.end()) { - phy.close(bi->udpSock,false); - phy.close(bi->tcpListenSock,false); + std::vector<_Binding> newBindings; + + // Save bindings that are still valid, close those that are not + for(std::vector<_Binding>::iterator b(_bindings.begin());b!=_bindings.end();++b) { + if (localIfAddrs.find(b->address) != localIfAddrs.end()) { + newBindings.push_back(*b); + } else { + phy.close(b->udpSock,false); + phy.close(b->tcpListenSock,false); } } - std::vector<_Binding> newBindings; + // Create new bindings for those not already bound for(std::map::const_iterator ii(localIfAddrs.begin());ii!=localIfAddrs.end();++ii) { - typename std::vector<_Binding>::const_iterator bi(_bindings.begin()); - while (bi != _bindings.end()) { - if (bi->address == ii->first) { - newBindings.push_back(*bi); + typename std::vector<_Binding>::const_iterator bi(newBindings.begin()); + while (bi != newBindings.end()) { + if (bi->address == ii->first) break; - } ++bi; } - - if (bi == _bindings.end()) { + if (bi == newBindings.end()) { udps = phy.udpBind(reinterpret_cast(&(ii->first)),(void *)0,ZT_UDP_DESIRED_BUF_SIZE); - if (udps) { - //tcps = phy.tcpListen(reinterpret_cast(&ii),(void *)0); - //if (tcps) { + tcps = phy.tcpListen(reinterpret_cast(&(ii->first)),(void *)0); + if ((udps)&&(tcps)) { #ifdef __LINUX__ - // Bind Linux sockets to their device so routes tha we manage do not override physical routes (wish all platforms had this!) - if (ii->second.length() > 0) { - int fd = (int)Phy::getDescriptor(udps); - char tmp[256]; - Utils::scopy(tmp,sizeof(tmp),ii->second.c_str()); - if (fd >= 0) { - if (setsockopt(fd,SOL_SOCKET,SO_BINDTODEVICE,tmp,strlen(tmp)) != 0) { - fprintf(stderr,"WARNING: unable to set SO_BINDTODEVICE to bind %s to %s\n",ii->first.toIpString().c_str(),ii->second.c_str()); - } - } - } + // Bind Linux sockets to their device so routes tha we manage do not override physical routes (wish all platforms had this!) + if (ii->second.length() > 0) { + char tmp[256]; + Utils::scopy(tmp,sizeof(tmp),ii->second.c_str()); + int fd = (int)Phy::getDescriptor(udps); + if (fd >= 0) + setsockopt(fd,SOL_SOCKET,SO_BINDTODEVICE,tmp,strlen(tmp)); + fd = (int)Phy::getDescriptor(tcps); + if (fd >= 0) + setsockopt(fd,SOL_SOCKET,SO_BINDTODEVICE,tmp,strlen(tmp)); + } #endif // __LINUX__ - newBindings.push_back(_Binding()); - newBindings.back().udpSock = udps; - //newBindings.back().tcpListenSock = tcps; - newBindings.back().address = ii->first; - //} else { - // phy.close(udps,false); - //} + newBindings.push_back(_Binding()); + newBindings.back().udpSock = udps; + newBindings.back().tcpListenSock = tcps; + newBindings.back().address = ii->first; } } } - // Swapping pointers and then letting the old one fall out of scope is faster than copying again _bindings.swap(newBindings); } @@ -402,58 +396,79 @@ public: * @param data Data to send * @param len Length of data * @param v4ttl If non-zero, send this packet with the specified IP TTL (IPv4 only) + * @return -1 == local doesn't match any bound address, 0 == send failure, 1 == send successful */ template - inline bool udpSend(Phy &phy,const InetAddress &local,const InetAddress &remote,const void *data,unsigned int len,unsigned int v4ttl = 0) const + inline int udpSend(Phy &phy,const InetAddress &local,const InetAddress &remote,const void *data,unsigned int len,unsigned int v4ttl = 0) const { + PhySocket *s; + typename std::vector<_Binding>::const_iterator i; + int result; Mutex::Lock _l(_lock); - if (local) { - for(typename std::vector<_Binding>::const_iterator i(_bindings.begin());i!=_bindings.end();++i) { - if (i->address == local) { - if ((v4ttl)&&(local.ss_family == AF_INET)) - phy.setIp4UdpTtl(i->udpSock,v4ttl); - const bool result = phy.udpSend(i->udpSock,reinterpret_cast(&remote),data,len); - if ((v4ttl)&&(local.ss_family == AF_INET)) - phy.setIp4UdpTtl(i->udpSock,255); - return result; + + if (remote.ss_family == AF_INET) { + if (local) { + for(i=_bindings.begin();i!=_bindings.end();++i) { + if ( + (i->address.ss_family == AF_INET) && + (reinterpret_cast(&(i->address))->sin_port == reinterpret_cast(&local)->sin_port) && + (reinterpret_cast(&(i->address))->sin_addr.s_addr == reinterpret_cast(&local)->sin_addr.s_addr) + ) + { + s = i->udpSock; + goto Binder_send_packet; + } + } + } else { + for(i=_bindings.begin();i!=_bindings.end();++i) { + if (i->address.ss_family == AF_INET) { + s = i->udpSock; + goto Binder_send_packet; + } } } - return false; } else { - bool result = false; - for(typename std::vector<_Binding>::const_iterator i(_bindings.begin());i!=_bindings.end();++i) { - if (i->address.ss_family == remote.ss_family) { - if ((v4ttl)&&(remote.ss_family == AF_INET)) - phy.setIp4UdpTtl(i->udpSock,v4ttl); - result |= phy.udpSend(i->udpSock,reinterpret_cast(&remote),data,len); - if ((v4ttl)&&(remote.ss_family == AF_INET)) - phy.setIp4UdpTtl(i->udpSock,255); + if (local) { + for(i=_bindings.begin();i!=_bindings.end();++i) { + if ( + (i->address.ss_family == AF_INET6) && + (reinterpret_cast(&(i->address))->sin6_port == reinterpret_cast(&local)->sin6_port) && + (!memcmp(reinterpret_cast(&(i->address))->sin6_addr.s6_addr,reinterpret_cast(&local)->sin6_addr.s6_addr,16)) + ) + { + s = i->udpSock; + goto Binder_send_packet; + } + } + } else { + for(i=_bindings.begin();i!=_bindings.end();++i) { + if (i->address.ss_family == AF_INET6) { + s = i->udpSock; + goto Binder_send_packet; + } } } - return result; } + + return -1; + +Binder_send_packet: + if (v4ttl) phy.setIp4UdpTtl(s,v4ttl); + result = (int)phy.udpSend(s,reinterpret_cast(&remote),data,len); + if (v4ttl) phy.setIp4UdpTtl(s,255); + return result; } /** * @return All currently bound local interface addresses */ - inline std::vector allBoundLocalInterfaceAddresses() + inline std::vector allBoundLocalInterfaceAddresses() const { - Mutex::Lock _l(_lock); std::vector aa; - for(std::vector<_Binding>::const_iterator i(_bindings.begin());i!=_bindings.end();++i) - aa.push_back(i->address); - return aa; - } - - /** - * @param aa Vector to append local interface addresses to - */ - inline void allBoundLocalInterfaceAddresses(std::vector &aa) - { Mutex::Lock _l(_lock); - for(std::vector<_Binding>::const_iterator i(_bindings.begin());i!=_bindings.end();++i) - aa.push_back(i->address); + for(std::vector<_Binding>::const_iterator b(_bindings.begin());b!=_bindings.end();++b) + aa.push_back(b->address); + return aa; } private: diff --git a/service/OneService.cpp b/service/OneService.cpp index 472115da..8fc76e31 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -160,11 +160,8 @@ namespace ZeroTier { typedef BSDEthernetTap EthernetTap; } // Maximum write buffer size for outgoing TCP connections (sanity limit) #define ZT_TCP_MAX_WRITEQ_SIZE 33554432 -// How often to check TCP connections and cluster links -#define ZT_TCP_CHECK_PERIOD 10000 - -// How often to send status info to cluster links -#define ZT_TCP_CLUSTER_SEND_STATUS_EVERY 30000 +// How often to check TCP connections and cluster links and send status to cluster peers +#define ZT_TCP_CHECK_PERIOD 15000 // TCP activity timeout #define ZT_TCP_ACTIVITY_TIMEOUT 60000 @@ -369,12 +366,12 @@ struct TcpConnection TCP_HTTP_INCOMING, TCP_HTTP_OUTGOING, TCP_TUNNEL_OUTGOING, // TUNNELED mode proxy outbound connection - TCP_CLUSTER_BACKPLANE, + TCP_CLUSTER_BACKPLANE } type; OneServiceImpl *parent; PhySocket *sock; - InetAddress from; + InetAddress remoteAddr; unsigned long lastReceive; // Used for inbound HTTP connections @@ -392,6 +389,7 @@ struct TcpConnection unsigned int clusterMemberVersionMinor; unsigned int clusterMemberVersionRev; std::vector< InetAddress > clusterMemberLocalAddresses; + Mutex clusterMemberLocalAddresses_m; std::string readq; std::string writeq; @@ -454,17 +452,8 @@ public: * destructively with uPnP port mapping behavior in very weird buggy ways. * It's only used if uPnP/NAT-PMP is enabled in this build. */ - Binder _bindings[3]; unsigned int _ports[3]; - uint16_t _portsBE[3]; // ports in big-endian network byte order as in sockaddr - - // Local interface addresses obtained from bindings - std::vector _localInterfaceAddresses; - Mutex _localInterfaceAddresses_m; - - // Sockets for JSON API -- bound only to V4 and V6 localhost - PhySocket *_v4TcpControlSocket; - PhySocket *_v6TcpControlSocket; + Binder _binder; // Time we last received a packet from a global address uint64_t _lastDirectReceiveFromGlobal; @@ -534,8 +523,7 @@ public: ,_updateAutoApply(false) ,_primaryPort(port) ,_udpPortPickerCounter(0) - ,_v4TcpControlSocket((PhySocket *)0) - ,_v6TcpControlSocket((PhySocket *)0) + ,_clusterMemberId(0) ,_lastDirectReceiveFromGlobal(0) #ifdef ZT_TCP_FALLBACK_RELAY ,_lastSendToGlobalV4(0) @@ -547,10 +535,6 @@ public: ,_portMappingEnabled(true) #ifdef ZT_USE_MINIUPNPC ,_portMapper((PortMapper *)0) -#endif -#ifdef ZT_ENABLE_CLUSTER - ,_clusterMessageSocket((PhySocket *)0) - ,_clusterDefinition((ClusterDefinition *)0) #endif ,_run(true) { @@ -561,23 +545,11 @@ public: virtual ~OneServiceImpl() { - for(int i=0;i<3;++i) - _bindings[i].closeAll(_phy); - - _phy.close(_v4TcpControlSocket); - _phy.close(_v6TcpControlSocket); - -#ifdef ZT_ENABLE_CLUSTER - _phy.close(_clusterMessageSocket); -#endif - + _binder.closeAll(_phy); #ifdef ZT_USE_MINIUPNPC delete _portMapper; #endif delete _controller; -#ifdef ZT_ENABLE_CLUSTER - delete _clusterDefinition; -#endif } virtual ReasonForTermination run() @@ -623,7 +595,7 @@ public: InetAddress trustedPathNetworks[ZT_MAX_TRUSTED_PATHS]; unsigned int trustedPathCount = 0; - // Old style "trustedpaths" flat file -- will eventually go away + // LEGACY: support old "trustedpaths" flat file FILE *trustpaths = fopen((_homePath + ZT_PATH_SEPARATOR_S "trustedpaths").c_str(),"r"); if (trustpaths) { fprintf(stderr,"WARNING: 'trustedpaths' flat file format is deprecated in favor of path definitions in local.conf" ZT_EOL_S); @@ -688,9 +660,11 @@ public: if (trustedPathCount) _node->setTrustedPaths(reinterpret_cast(trustedPathNetworks),trustedPathIds,trustedPathCount); } + + // Apply other runtime configuration from local.conf applyLocalConfig(); - // Bind TCP socket + // Make sure we can use the primary port, and hunt for one if configured to do so const int portTrials = (_primaryPort == 0) ? 256 : 1; // if port is 0, pick random for(int k=0;kaddress() % 45500); for(int i=0;;++i) { if (i > 1000) { @@ -782,10 +732,6 @@ public: } #endif - // Populate ports in big-endian format for quick compare - for(int i=0;i<3;++i) - _portsBE[i] = Utils::hton((uint16_t)_ports[i]); - // Network controller is now enabled by default for desktop and server _controller = new EmbeddedNetworkController(_node,_controllerDbPath.c_str()); _node->setNetconfMaster((void *)_controller); @@ -841,8 +787,8 @@ public: #endif */ -/* - { // Load existing networks + // Join existing networks in networks.d + { std::vector networksDotD(OSUtils::listDirectory((_homePath + ZT_PATH_SEPARATOR_S "networks.d").c_str())); for(std::vector::iterator f(networksDotD.begin());f!=networksDotD.end();++f) { std::size_t dot = f->find_last_of('.'); @@ -850,7 +796,9 @@ public: _node->join(Utils::hexStrToU64(f->substr(0,dot).c_str()),(void *)0,(void *)0); } } - { // Load existing moons + + // Orbit existing moons in moons.d + { std::vector moonsDotD(OSUtils::listDirectory((_homePath + ZT_PATH_SEPARATOR_S "moons.d").c_str())); for(std::vector::iterator f(moonsDotD.begin());f!=moonsDotD.end();++f) { std::size_t dot = f->find_last_of('.'); @@ -858,8 +806,8 @@ public: _node->orbit((void *)0,Utils::hexStrToU64(f->substr(0,dot).c_str()),0); } } -*/ + // Derive the cluster's shared secret backplane encryption key by hashing its shared secret identity { uint8_t tmp[64]; SHA512::hash(tmp,_node->identity().privateKeyPair().priv.data,ZT_C25519_PRIVATE_KEY_LEN); @@ -877,6 +825,7 @@ public: uint64_t lastUpdateCheck = clockShouldBe; uint64_t lastLocalInterfaceAddressCheck = (clockShouldBe - ZT_LOCAL_INTERFACE_CHECK_INTERVAL) + 15000; // do this in 15s to give portmapper time to configure and other things time to settle uint64_t lastCleanedIddb = 0; + uint64_t lastTcpCheck = 0; for(;;) { _run_m.lock(); if (!_run) { @@ -914,11 +863,13 @@ public: // Refresh bindings in case device's interfaces have changed, and also sync routes to update any shadow routes (e.g. shadow default) if (((now - lastBindRefresh) >= ZT_BINDER_REFRESH_PERIOD)||(restarted)) { lastBindRefresh = now; + unsigned int p[3]; + unsigned int pc = 0; for(int i=0;i<3;++i) { - if (_ports[i]) { - _bindings[i].refresh(_phy,_ports[i],*this); - } + if (_ports[i]) + p[pc++] = _ports[i]; } + _binder.refresh(_phy,p,pc,*this); { Mutex::Lock _l(_nets_m); for(std::map::iterator n(_nets.begin());n!=_nets.end();++n) { @@ -928,15 +879,18 @@ public: } } + // Run background task processor in core if it's time to do so uint64_t dl = _nextBackgroundTaskDeadline; if (dl <= now) { _node->processBackgroundTasks((void *)0,now,&_nextBackgroundTaskDeadline); dl = _nextBackgroundTaskDeadline; } + // Close TCP fallback tunnel if we have direct UDP if ((_tcpFallbackTunnel)&&((now - _lastDirectReceiveFromGlobal) < (ZT_TCP_FALLBACK_AFTER / 2))) _phy.close(_tcpFallbackTunnel->sock); + // Sync multicast group memberships if ((now - lastTapMulticastGroupCheck) >= ZT_TAP_CHECK_MULTICAST_INTERVAL) { lastTapMulticastGroupCheck = now; Mutex::Lock _l(_nets_m); @@ -952,12 +906,12 @@ public: } } + // Sync information about physical network interfaces if ((now - lastLocalInterfaceAddressCheck) >= ZT_LOCAL_INTERFACE_CHECK_INTERVAL) { lastLocalInterfaceAddressCheck = now; _node->clearLocalInterfaceAddresses(); - // Tell Node about uPnP and NAT-PMP bound external addresses #ifdef ZT_USE_MINIUPNPC if (_portMapper) { std::vector mappedAddresses(_portMapper->get()); @@ -966,18 +920,57 @@ public: } #endif - // Tell Node about local interface addresses bound to the primary port - std::vector boundAddrs(_bindings[0].allBoundLocalInterfaceAddresses()); + std::vector boundAddrs(_binder.allBoundLocalInterfaceAddresses()); for(std::vector::const_iterator i(boundAddrs.begin());i!=boundAddrs.end();++i) _node->addLocalInterfaceAddress(reinterpret_cast(&(*i))); + } + + // Check TCP connections and cluster links + if ((now - lastTcpCheck) >= ZT_TCP_CHECK_PERIOD) { + lastTcpCheck = now; - // Memoize all local interface addresses for use in clustering -- we tell other cluster members about these + std::vector toClose; + std::vector clusterLinksUp; { - Mutex::Lock _l(_localInterfaceAddresses_m); - _localInterfaceAddresses.clear(); - for(int i=0;i<3;++i) { - if (_ports[i] > 0) - _bindings[i].allBoundLocalInterfaceAddresses(_localInterfaceAddresses); + Mutex::Lock _l(_tcpConnections_m); + for(std::vector::const_iterator c(_tcpConnections.begin());c!=_tcpConnections.end();++c) { + TcpConnection *const tc = *c; + tc->writeq_m.lock(); + const unsigned long wql = (unsigned long)tc->writeq.length(); + tc->writeq_m.unlock(); + if ((tc->sock)&&((wql > ZT_TCP_MAX_WRITEQ_SIZE)||((now - tc->lastReceive) > ZT_TCP_ACTIVITY_TIMEOUT))) { + toClose.push_back(tc->sock); + } else if ((tc->type == TcpConnection::TCP_CLUSTER_BACKPLANE)&&(tc->clusterMemberId)) { + clusterLinksUp.push_back(tc->remoteAddr); + sendMyCurrentClusterState(tc); + } + } + } + for(std::vector::iterator s(toClose.begin());s!=toClose.end();++s) + _phy.close(*s,true); + + { + Mutex::Lock _l(_localConfig_m); + for(std::vector::const_iterator ca(_clusterBackplaneAddresses.begin());ca!=_clusterBackplaneAddresses.end();++ca) { + if (std::find(clusterLinksUp.begin(),clusterLinksUp.end(),*ca) == clusterLinksUp.end()) { + TcpConnection *tc = new TcpConnection(); + { + Mutex::Lock _l(_tcpConnections_m); + _tcpConnections.push_back(tc); + } + + tc->type = TcpConnection::TCP_CLUSTER_BACKPLANE; + tc->remoteAddr = *ca; + tc->lastReceive = OSUtils::now(); + tc->parent = this; + tc->sock = (PhySocket *)0; // set in connect handler + tc->messageSize = 0; + + tc->clusterMemberId = 0; // not known yet + + bool connected = false; + _phy.tcpConnect(reinterpret_cast(&(*ca)),connected,(void *)tc,true); + } } } } @@ -986,10 +979,6 @@ public: clockShouldBe = now + (uint64_t)delay; _phy.poll(delay); } - } catch (std::exception &exc) { - Mutex::Lock _l(_termReason_m); - _termReason = ONE_UNRECOVERABLE_ERROR; - _fatalErrorMessage = exc.what(); } catch ( ... ) { Mutex::Lock _l(_termReason_m); _termReason = ONE_UNRECOVERABLE_ERROR; @@ -1819,110 +1808,154 @@ public: } } - void announceStatusToClusterMember(TcpConnection *tc) + // ========================================================================= + // Cluster messaging functions + // ========================================================================= + + // mlen must be at least 24 + void encryptClusterMessage(char *data,unsigned int mlen) { - Buffer<4096> buf; + uint8_t key[32]; + memcpy(key,_clusterKey,32); + for(int i=0;i<8;++i) key[i] ^= data[i]; + Salsa20 s20(key,data + 8); - buf.appendRandom(16); - buf.addSize(8); // space for MAC - buf.append((uint8_t)CLUSTER_MESSAGE_STATUS); - buf.append(_clusterMemberId); - buf.append((uint16_t)ZEROTIER_ONE_VERSION_MAJOR); - buf.append((uint16_t)ZEROTIER_ONE_VERSION_MINOR); - buf.append((uint16_t)ZEROTIER_ONE_VERSION_REVISION); + uint8_t macKey[32]; + uint8_t mac[16]; + memset(macKey,0,32); + s20.crypt12(macKey,macKey,32); + s20.crypt12(data + 24,data + 24,mlen - 24); + Poly1305::compute(mac,data + 24,mlen - 24,macKey); + memcpy(data + 16,mac,8); + } - { - Mutex::Lock _l(_localInterfaceAddresses_m); - buf.append((uint16_t)_localInterfaceAddresses.size()); - for(std::vector::const_iterator i(_localInterfaceAddresses.begin());i!=_localInterfaceAddresses.end();++i) { + void announceStatusToClusterMember(TcpConnection *tc) + { + try { + Buffer<8194> buf; + + buf.appendRandom(16); + buf.addSize(8); // space for MAC + buf.append((uint8_t)CLUSTER_MESSAGE_STATUS); + buf.append(_clusterMemberId); + buf.append((uint16_t)ZEROTIER_ONE_VERSION_MAJOR); + buf.append((uint16_t)ZEROTIER_ONE_VERSION_MINOR); + buf.append((uint16_t)ZEROTIER_ONE_VERSION_REVISION); + + std::vector lif(_binder.allBoundLocalInterfaceAddresses()); + buf.append((uint16_t)lif.size()); + for(std::vector::const_iterator i(lif.begin());i!=lif.end();++i) i->serialize(buf); - if ((buf.size() + 32) > buf.capacity()) - break; + + Mutex::Lock _l(tc->writeq_m); + + if (tc->writeq.length() == 0) + _phy.setNotifyWritable(tc->sock,true); + + const unsigned int mlen = buf.size(); + tc->writeq.push_back((char)((mlen >> 16) & 0xff)); + tc->writeq.push_back((char)((mlen >> 8) & 0xff)); + tc->writeq.push_back((char)(mlen & 0xff)); + + char *const data = reinterpret_cast(buf.unsafeData()); + encryptClusterMessage(data,mlen); + tc->writeq.append(data,mlen); + } catch ( ... ) { + fprintf(stderr,"WARNING: unexpected exception announcing status to cluster members" ZT_EOL_S); + } + } + + bool proxySendViaCluster(const InetAddress &fromAddress,const InetAddress &dest,const void *data,unsigned int len,unsigned int ttl) + { + Mutex::Lock _l(_tcpConnections_m); + for(std::vector::const_iterator c(_tcpConnections.begin());c!=_tcpConnections.end();++c) { + TcpConnection *const tc = *c; + if ((tc->type == TcpConnection::TCP_CLUSTER_BACKPLANE)&&(tc->clusterMemberId)) { + Mutex::Lock _l2(tc->clusterMemberLocalAddresses_m); + for(std::vector::const_iterator i(tc->clusterMemberLocalAddresses.begin());i!=tc->clusterMemberLocalAddresses.end();++i) { + if (*i == fromAddress) { + Buffer<1024> buf; + + buf.appendRandom(16); + buf.addSize(8); // space for MAC + buf.append((uint8_t)CLUSTER_MESSAGE_PROXY_SEND); + buf.append((uint8_t)ttl); + dest.serialize(buf); + fromAddress.serialize(buf); + + Mutex::Lock _l3(tc->writeq_m); + + if (tc->writeq.length() == 0) + _phy.setNotifyWritable(tc->sock,true); + + const unsigned int mlen = buf.size() + len; + tc->writeq.push_back((char)((mlen >> 16) & 0xff)); + tc->writeq.push_back((char)((mlen >> 8) & 0xff)); + tc->writeq.push_back((char)(mlen & 0xff)); + + const unsigned long startpos = (unsigned long)tc->writeq.length(); + tc->writeq.append(reinterpret_cast(buf.data()),buf.size()); + tc->writeq.append(reinterpret_cast(data),len); + + char *const outdata = const_cast(tc->writeq.data()) + startpos; + encryptClusterMessage(outdata,mlen); + + return true; + } + } } } + return false; + } - Mutex::Lock _l(tc->writeq_m); + void replicateStateObject(const ZT_StateObjectType type,const uint64_t id,const void *const data,const unsigned int len,TcpConnection *tc) + { + char buf[34]; + + Mutex::Lock _l2(tc->writeq_m); if (tc->writeq.length() == 0) _phy.setNotifyWritable(tc->sock,true); - const unsigned int mlen = buf.size(); + const unsigned int mlen = len + 34; + tc->writeq.push_back((char)((mlen >> 16) & 0xff)); tc->writeq.push_back((char)((mlen >> 8) & 0xff)); tc->writeq.push_back((char)(mlen & 0xff)); - char *data = reinterpret_cast(buf.unsafeData()); - - uint8_t key[32]; - memcpy(key,_clusterKey,32); - for(int i=0;i<8;++i) key[i] ^= data[i]; - Salsa20 s20(key,data + 8); - - uint8_t macKey[32]; - uint8_t mac[16]; - memset(macKey,0,32); - s20.crypt12(macKey,macKey,32); - s20.crypt12(data + 24,data + 24,mlen - 24); - Poly1305::compute(mac,data + 24,mlen - 24,macKey); - memcpy(data + 16,mac,8); - - tc->writeq.append(data,mlen); + Utils::getSecureRandom(buf,16); + buf[24] = (char)CLUSTER_MESSAGE_STATE_OBJECT; + buf[25] = (char)type; + buf[26] = (char)((id >> 56) & 0xff); + buf[27] = (char)((id >> 48) & 0xff); + buf[28] = (char)((id >> 40) & 0xff); + buf[29] = (char)((id >> 32) & 0xff); + buf[30] = (char)((id >> 24) & 0xff); + buf[31] = (char)((id >> 16) & 0xff); + buf[32] = (char)((id >> 8) & 0xff); + buf[33] = (char)(id & 0xff); + + const unsigned long startpos = (unsigned long)tc->writeq.length(); + tc->writeq.append(buf,34); + tc->writeq.append(reinterpret_cast(data),len); + + char *const outdata = const_cast(tc->writeq.data()) + startpos; + encryptClusterMessage(outdata,mlen); } void replicateStateObjectToCluster(const ZT_StateObjectType type,const uint64_t id,const void *const data,const unsigned int len,const uint64_t everyoneBut) { - uint8_t *buf = new uint8_t[len + 34]; - try { - std::vector sentTo; - if (everyoneBut) - sentTo.push_back(everyoneBut); - Mutex::Lock _l(_tcpConnections_m); - for(std::vector::const_iterator ci(_tcpConnections.begin());ci!=_tcpConnections.end();++ci) { - TcpConnection *const c = *ci; - if ((c->type == TcpConnection::TCP_CLUSTER_BACKPLANE)&&(c->clusterMemberId != 0)&&(std::find(sentTo.begin(),sentTo.end(),c->clusterMemberId) == sentTo.end())) { - sentTo.push_back(c->clusterMemberId); - Mutex::Lock _l2(c->writeq_m); - - if (c->writeq.length() == 0) - _phy.setNotifyWritable(c->sock,true); - - const unsigned int mlen = len + 34; - c->writeq.push_back((char)((mlen >> 16) & 0xff)); - c->writeq.push_back((char)((mlen >> 8) & 0xff)); - c->writeq.push_back((char)(mlen & 0xff)); - - Utils::getSecureRandom(buf,16); - - buf[24] = (uint8_t)CLUSTER_MESSAGE_STATE_OBJECT; - buf[25] = (uint8_t)type; - buf[26] = (uint8_t)((id >> 56) & 0xff); - buf[27] = (uint8_t)((id >> 48) & 0xff); - buf[28] = (uint8_t)((id >> 40) & 0xff); - buf[29] = (uint8_t)((id >> 32) & 0xff); - buf[30] = (uint8_t)((id >> 24) & 0xff); - buf[31] = (uint8_t)((id >> 16) & 0xff); - buf[32] = (uint8_t)((id >> 8) & 0xff); - buf[33] = (uint8_t)(id & 0xff); - memcpy(buf + 34,data,len); - - uint8_t key[32]; - memcpy(key,_clusterKey,32); - for(int i=0;i<8;++i) key[i] ^= buf[i]; - Salsa20 s20(key,buf + 8); - - uint8_t macKey[32]; - uint8_t mac[16]; - memset(macKey,0,32); - s20.crypt12(macKey,macKey,32); - s20.crypt12(buf + 24,buf + 24,mlen - 24); - Poly1305::compute(mac,buf + 24,mlen - 24,macKey); - memcpy(buf + 16,mac,8); - - c->writeq.append(reinterpret_cast(buf),len + 34); - } + std::vector sentTo; + if (everyoneBut) + sentTo.push_back(everyoneBut); + Mutex::Lock _l(_tcpConnections_m); + for(std::vector::const_iterator ci(_tcpConnections.begin());ci!=_tcpConnections.end();++ci) { + TcpConnection *const c = *ci; + if ((c->type == TcpConnection::TCP_CLUSTER_BACKPLANE)&&(c->clusterMemberId != 0)&&(std::find(sentTo.begin(),sentTo.end(),c->clusterMemberId) == sentTo.end())) { + sentTo.push_back(c->clusterMemberId); + replicateStateObject(type,id,data,len,c); } - } catch ( ... ) {} // sanity check - delete [] buf; + } } void writeStateObject(enum ZT_StateObjectType type,uint64_t id,const void *data,int len) @@ -1955,15 +1988,48 @@ public: break; } if (p[0]) { - FILE *f = fopen(p,"w"); - if (f) { - if (fwrite(data,len,1,f) != 1) - fprintf(stderr,"WARNING: unable to write to file: %s (I/O error)" ZT_EOL_S,p); - fclose(f); - if (secure) - OSUtils::lockDownFile(p,false); + if (len >= 0) { + FILE *f = fopen(p,"w"); + if (f) { + if (fwrite(data,len,1,f) != 1) + fprintf(stderr,"WARNING: unable to write to file: %s (I/O error)" ZT_EOL_S,p); + fclose(f); + if (secure) + OSUtils::lockDownFile(p,false); + } else { + fprintf(stderr,"WARNING: unable to write to file: %s (unable to open)" ZT_EOL_S,p); + } } else { - fprintf(stderr,"WARNING: unable to write to file: %s (unable to open)" ZT_EOL_S,p); + OSUtils::rm(p); + } + } + } + + void sendMyCurrentClusterState(TcpConnection *tc) + { + // We currently don't need to dump everything. Networks and moons are most important. + // The rest will get caught up rapidly due to constant peer updates, etc. + std::string buf; + std::vector l(OSUtils::listDirectory((_homePath + ZT_PATH_SEPARATOR_S + "networks.d").c_str(),false)); + for(std::vector::const_iterator f(l.begin());f!=l.end();++f) { + buf.clear(); + if (OSUtils::readFile((_homePath + ZT_PATH_SEPARATOR_S + *f).c_str(),buf)) { + if (f->length() == 21) { + const uint64_t nwid = Utils::hexStrToU64(f->substr(0,16).c_str()); + if (nwid) + replicateStateObject(ZT_STATE_OBJECT_NETWORK_CONFIG,nwid,buf.data(),(int)buf.length(),tc); + } + } + } + l = OSUtils::listDirectory((_homePath + ZT_PATH_SEPARATOR_S + "moons.d").c_str(),false); + for(std::vector::const_iterator f(l.begin());f!=l.end();++f) { + buf.clear(); + if (OSUtils::readFile((_homePath + ZT_PATH_SEPARATOR_S + *f).c_str(),buf)) { + if (f->length() == 21) { + const uint64_t moonId = Utils::hexStrToU64(f->substr(0,16).c_str()); + if (moonId) + replicateStateObject(ZT_STATE_OBJECT_MOON,moonId,buf.data(),(int)buf.length(),tc); + } } } } @@ -2015,6 +2081,12 @@ public: _tcpFallbackTunnel = tc; _phy.streamSend(sock,ZT_TCP_TUNNEL_HELLO,sizeof(ZT_TCP_TUNNEL_HELLO)); } else if (tc->type == TcpConnection::TCP_CLUSTER_BACKPLANE) { + { + Mutex::Lock _l(tc->writeq_m); + tc->writeq.push_back((char)0x93); // identifies type of connection as cluster backplane + } + announceStatusToClusterMember(tc); + _phy.setNotifyWritable(sock,true); } else { _phy.close(sock,true); } @@ -2035,7 +2107,7 @@ public: tc->type = TcpConnection::TCP_UNCATEGORIZED_INCOMING; tc->parent = this; tc->sock = sockN; - tc->from = from; + tc->remoteAddr = from; tc->lastReceive = OSUtils::now(); http_parser_init(&(tc->parser),HTTP_REQUEST); tc->parser.data = (void *)tc; @@ -2072,17 +2144,19 @@ public: switch(reinterpret_cast(data)[0]) { // 0x93 is first byte of cluster backplane connections case 0x93: { + // We only allow this from cluster backplane IPs. We also authenticate + // each packet cryptographically, so this is just a first line of defense. bool allow = false; { Mutex::Lock _l(_localConfig_m); for(std::vector< InetAddress >::const_iterator i(_clusterBackplaneAddresses.begin());i!=_clusterBackplaneAddresses.end();++i) { - if (tc->from.ipsEqual(*i)) { + if (tc->remoteAddr.ipsEqual(*i)) { allow = true; break; } } } - if (allow) { // note that we also auth each packet cryptographically -- this is just a first line sanity check + if (allow) { tc->type = TcpConnection::TCP_CLUSTER_BACKPLANE; tc->clusterMemberId = 0; // unknown, waiting for first status message announceStatusToClusterMember(tc); @@ -2097,15 +2171,17 @@ public: case 'G': case 'P': case 'H': { + // This is only allowed from IPs permitted to access the management + // backplane, which is just 127.0.0.1/::1 unless otherwise configured. bool allow; { Mutex::Lock _l(_localConfig_m); if (_allowManagementFrom.size() == 0) { - allow = (tc->from.ipScope() == InetAddress::IP_SCOPE_LOOPBACK); + allow = (tc->remoteAddr.ipScope() == InetAddress::IP_SCOPE_LOOPBACK); } else { allow = false; for(std::vector::const_iterator i(_allowManagementFrom.begin());i!=_allowManagementFrom.end();++i) { - if (i->containsAddress(tc->from)) { + if (i->containsAddress(tc->remoteAddr)) { allow = true; break; } @@ -2240,11 +2316,15 @@ public: if (mlen > (25 + 16)) { Buffer<4096> tmp(data + 25,mlen - 25); try { - tc->clusterMemberId = tmp.at(0); - if (tc->clusterMemberId == _clusterMemberId) { // shouldn't happen, but don't allow self-to-self + const uint64_t cmid = tmp.at(0); + if (cmid == _clusterMemberId) { // shouldn't happen, but don't allow self-to-self _phy.close(sock); return; } + if (!tc->clusterMemberId) { + tc->clusterMemberId = cmid; + sendMyCurrentClusterState(tc); + } tc->clusterMemberVersionMajor = tmp.at(8); tc->clusterMemberVersionMinor = tmp.at(10); tc->clusterMemberVersionRev = tmp.at(12); @@ -2255,7 +2335,10 @@ public: la.push_back(InetAddress()); ptr += la.back().deserialize(tmp,ptr); } - tc->clusterMemberLocalAddresses.swap(la); + { + Mutex::Lock _l2(tc->clusterMemberLocalAddresses_m); + tc->clusterMemberLocalAddresses.swap(la); + } } catch ( ... ) {} } break; @@ -2284,17 +2367,12 @@ public: Buffer<4096> tmp(data + 25,mlen - 25); try { InetAddress dest,src; - unsigned int ptr = dest.deserialize(tmp); + const unsigned int ttl = (unsigned int)tmp[0]; + unsigned int ptr = 1; + ptr += dest.deserialize(tmp); ptr += src.deserialize(tmp,ptr); - if (ptr < tmp.size()) { - bool local; - { - Mutex::Lock _l(_localInterfaceAddresses_m); - local = (std::find(_localInterfaceAddresses.begin(),_localInterfaceAddresses.end(),src) != _localInterfaceAddresses.end()); - } - if (local) - nodeWirePacketSendFunction(&src,&dest,reinterpret_cast(tmp.data()) + ptr,tmp.size() - ptr,0); - } + if (ptr < tmp.size()) + _binder.udpSend(_phy,src,dest,reinterpret_cast(tmp.data()) + ptr,tmp.size() - ptr,ttl); } catch ( ... ) {} } break; @@ -2539,24 +2617,8 @@ public: inline int nodeWirePacketSendFunction(const struct sockaddr_storage *localAddr,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl) { - unsigned int fromBindingNo = 0; - - if (addr->ss_family == AF_INET) { - if (reinterpret_cast(localAddr)->sin_port == 0) { - // If sender is sending from wildcard (null address), choose the secondary backup - // port 1/4 of the time. (but only for IPv4) - fromBindingNo = (++_udpPortPickerCounter & 0x4) >> 2; - if (!_ports[fromBindingNo]) - fromBindingNo = 0; - } else { - const uint16_t lp = reinterpret_cast(localAddr)->sin_port; - if (lp == _portsBE[1]) - fromBindingNo = 1; - else if (lp == _portsBE[2]) - fromBindingNo = 2; - } - #ifdef ZT_TCP_FALLBACK_RELAY + if (addr->ss_family == AF_INET) { // TCP fallback tunnel support, currently IPv4 only if ((len >= 16)&&(reinterpret_cast(addr)->ipScope() == InetAddress::IP_SCOPE_GLOBAL)) { // Engage TCP tunnel fallback if we haven't received anything valid from a global @@ -2579,40 +2641,45 @@ public: _tcpFallbackTunnel->writeq.append(reinterpret_cast(reinterpret_cast(&(reinterpret_cast(addr)->sin_port))),2); _tcpFallbackTunnel->writeq.append((const char *)data,len); } else if (((now - _lastSendToGlobalV4) < ZT_TCP_FALLBACK_AFTER)&&((now - _lastSendToGlobalV4) > (ZT_PING_CHECK_INVERVAL / 2))) { - bool connected = false; const InetAddress addr(ZT_TCP_FALLBACK_RELAY); - TcpConnection *tc = new TcpConnection(); { Mutex::Lock _l(_tcpConnections_m); _tcpConnections.push_back(tc); } - tc->type = TcpConnection::TCP_TUNNEL_OUTGOING; + tc->remoteAddr = addr; + tc->lastReceive = OSUtils::now(); tc->parent = this; tc->sock = (PhySocket *)0; // set in connect handler tc->messageSize = 0; - + bool connected = false; _phy.tcpConnect(reinterpret_cast(&addr),connected,(void *)tc,true); } } _lastSendToGlobalV4 = now; } + } + // Even when relaying we still send via UDP. This way if UDP starts + // working we can instantly "fail forward" to it and stop using TCP + // proxy fallback, which is slow. #endif // ZT_TCP_FALLBACK_RELAY - } else if (addr->ss_family == AF_INET6) { - if (reinterpret_cast(localAddr)->sin6_port != 0) { - const uint16_t lp = reinterpret_cast(localAddr)->sin6_port; - if (lp == _portsBE[1]) - fromBindingNo = 1; - else if (lp == _portsBE[2]) - fromBindingNo = 2; - } - } else { - return -1; - } + switch (_binder.udpSend(_phy,*(reinterpret_cast(localAddr)),*(reinterpret_cast(addr)),data,len,ttl)) { + case -1: // local bound address not found, so see if a cluster peer owns it + if (localAddr->ss_family != 0) { + return (proxySendViaCluster(*(reinterpret_cast(localAddr)),*(reinterpret_cast(addr)),data,len,ttl)) ? 0 : -1; + } else { + return -1; // failure + } + break; + + case 0: // failure + return -1; - return (_bindings[fromBindingNo].udpSend(_phy,*(reinterpret_cast(localAddr)),*(reinterpret_cast(addr)),data,len,ttl)) ? 0 : -1; + default: // success + return 0; + } } inline void nodeVirtualNetworkFrameFunction(uint64_t nwid,void **nuptr,uint64_t sourceMac,uint64_t destMac,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) @@ -2707,7 +2774,7 @@ public: // phyOnTcpData(). If we made it here the source IP is okay. try { - scode = handleControlPlaneHttpRequest(tc->from,tc->parser.method,tc->url,tc->headers,tc->readq,data,contentType); + scode = handleControlPlaneHttpRequest(tc->remoteAddr,tc->parser.method,tc->url,tc->headers,tc->readq,data,contentType); } catch (std::exception &exc) { fprintf(stderr,"WARNING: unexpected exception processing control HTTP request: %s" ZT_EOL_S,exc.what()); scode = 500; -- cgit v1.2.3 From 9a3c34b5b3040711f1018e313046df4fac13b403 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 7 Jun 2017 17:19:33 -0700 Subject: Build fix, use -Os on Linux too. --- make-linux.mk | 4 +-- osdep/Binder.hpp | 15 ++++++++++ service/OneService.cpp | 77 +++++++++++++++----------------------------------- 3 files changed, 40 insertions(+), 56 deletions(-) (limited to 'service/OneService.cpp') diff --git a/make-linux.mk b/make-linux.mk index eb77326e..5af8a92d 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -65,9 +65,9 @@ ifeq ($(ZT_DEBUG),1) node/Salsa20.o node/SHA512.o node/C25519.o node/Poly1305.o: CXXFLAGS=-Wall -O2 -g -pthread $(INCLUDES) $(DEFS) else override DEFS+=-D_FORTIFY_SOURCE=2 - CFLAGS?=-O3 -fstack-protector + CFLAGS?=-Os -fstack-protector override CFLAGS+=-Wall -Wno-deprecated -fPIE -pthread $(INCLUDES) -DNDEBUG $(DEFS) - CXXFLAGS?=-O3 -fstack-protector + CXXFLAGS?=-Os -fstack-protector override CXXFLAGS+=-Wall -Wno-deprecated -Wno-unused-result -Wreorder -fPIE -std=c++11 -pthread $(INCLUDES) -DNDEBUG $(DEFS) override LDFLAGS+=-pie -Wl,-z,relro,-z,now STRIP?=strip diff --git a/osdep/Binder.hpp b/osdep/Binder.hpp index 1839ecc2..a0b47367 100644 --- a/osdep/Binder.hpp +++ b/osdep/Binder.hpp @@ -57,6 +57,7 @@ #include #include #include +#include #include "../node/NonCopyable.hpp" #include "../node/InetAddress.hpp" @@ -471,6 +472,20 @@ Binder_send_packet: return aa; } + /** + * @param addr Address to check + * @return True if this is a bound local interface address + */ + inline bool isBoundLocalInterfaceAddress(const InetAddress &addr) const + { + Mutex::Lock _l(_lock); + for(std::vector<_Binding>::const_iterator b(_bindings.begin());b!=_bindings.end();++b) { + if (b->address == addr) + return true; + } + return false; + } + private: std::vector<_Binding> _bindings; Mutex _lock; diff --git a/service/OneService.cpp b/service/OneService.cpp index 8fc76e31..798a34b9 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -736,57 +736,6 @@ public: _controller = new EmbeddedNetworkController(_node,_controllerDbPath.c_str()); _node->setNetconfMaster((void *)_controller); -/* -#ifdef ZT_ENABLE_CLUSTER - if (OSUtils::fileExists((_homePath + ZT_PATH_SEPARATOR_S "cluster").c_str())) { - _clusterDefinition = new ClusterDefinition(_node->address(),(_homePath + ZT_PATH_SEPARATOR_S "cluster").c_str()); - if (_clusterDefinition->size() > 0) { - std::vector members(_clusterDefinition->members()); - for(std::vector::iterator m(members.begin());m!=members.end();++m) { - PhySocket *cs = _phy.udpBind(reinterpret_cast(&(m->clusterEndpoint))); - if (cs) { - if (_clusterMessageSocket) { - _phy.close(_clusterMessageSocket,false); - _phy.close(cs,false); - - Mutex::Lock _l(_termReason_m); - _termReason = ONE_UNRECOVERABLE_ERROR; - _fatalErrorMessage = "cluster: can't determine my cluster member ID: able to bind more than one cluster message socket IP/port!"; - return _termReason; - } - _clusterMessageSocket = cs; - _clusterMemberId = m->id; - } - } - - if (!_clusterMessageSocket) { - Mutex::Lock _l(_termReason_m); - _termReason = ONE_UNRECOVERABLE_ERROR; - _fatalErrorMessage = "cluster: can't determine my cluster member ID: unable to bind to any cluster message socket IP/port."; - return _termReason; - } - - const ClusterDefinition::MemberDefinition &me = (*_clusterDefinition)[_clusterMemberId]; - InetAddress endpoints[255]; - unsigned int numEndpoints = 0; - for(std::vector::const_iterator i(me.zeroTierEndpoints.begin());i!=me.zeroTierEndpoints.end();++i) - endpoints[numEndpoints++] = *i; - - if (_node->clusterInit(_clusterMemberId,reinterpret_cast(endpoints),numEndpoints,me.x,me.y,me.z,&SclusterSendFunction,this,_clusterDefinition->geo().available() ? &SclusterGeoIpFunction : 0,this) == ZT_RESULT_OK) { - std::vector members(_clusterDefinition->members()); - for(std::vector::iterator m(members.begin());m!=members.end();++m) { - if (m->id != _clusterMemberId) - _node->clusterAddMember(m->id); - } - } - } else { - delete _clusterDefinition; - _clusterDefinition = (ClusterDefinition *)0; - } - } -#endif -*/ - // Join existing networks in networks.d { std::vector networksDotD(OSUtils::listDirectory((_homePath + ZT_PATH_SEPARATOR_S "networks.d").c_str())); @@ -810,10 +759,18 @@ public: // Derive the cluster's shared secret backplane encryption key by hashing its shared secret identity { uint8_t tmp[64]; - SHA512::hash(tmp,_node->identity().privateKeyPair().priv.data,ZT_C25519_PRIVATE_KEY_LEN); + uint8_t sk[ZT_C25519_PRIVATE_KEY_LEN + 4]; + memcpy(sk,_node->identity().privateKeyPair().priv.data,ZT_C25519_PRIVATE_KEY_LEN); + sk[ZT_C25519_PRIVATE_KEY_LEN] = 0xab; + sk[ZT_C25519_PRIVATE_KEY_LEN + 1] = 0xcd; + sk[ZT_C25519_PRIVATE_KEY_LEN + 2] = 0xef; + sk[ZT_C25519_PRIVATE_KEY_LEN + 3] = 0xab; // add an arbitrary nonce, just because + SHA512::hash(tmp,sk,ZT_C25519_PRIVATE_KEY_LEN + 4); memcpy(_clusterKey,tmp,32); } - _clusterMemberId = _node->prng(); + + // Assign a random non-zero cluster member ID to identify vs. other cluster members + Utils::getSecureRandom(&_clusterMemberId,sizeof(_clusterMemberId)); if (!_clusterMemberId) _clusterMemberId = 1; // Main I/O loop @@ -929,6 +886,7 @@ public: if ((now - lastTcpCheck) >= ZT_TCP_CHECK_PERIOD) { lastTcpCheck = now; + // Send status to active cluster links and close overflowed and dead ones std::vector toClose; std::vector clusterLinksUp; { @@ -949,10 +907,11 @@ public: for(std::vector::iterator s(toClose.begin());s!=toClose.end();++s) _phy.close(*s,true); + // Attempt to connect to cluster links we don't have an active connection to { Mutex::Lock _l(_localConfig_m); for(std::vector::const_iterator ca(_clusterBackplaneAddresses.begin());ca!=_clusterBackplaneAddresses.end();++ca) { - if (std::find(clusterLinksUp.begin(),clusterLinksUp.end(),*ca) == clusterLinksUp.end()) { + if ( (std::find(clusterLinksUp.begin(),clusterLinksUp.end(),*ca) == clusterLinksUp.end()) && (!_binder.isBoundLocalInterfaceAddress(*ca)) ) { TcpConnection *tc = new TcpConnection(); { Mutex::Lock _l(_tcpConnections_m); @@ -1640,6 +1599,16 @@ public: } } + json &cl = settings["cluster"]; + _clusterBackplaneAddresses.clear(); + if (cl.is_array()) { + for(unsigned long i=0;i Date: Tue, 27 Jun 2017 11:31:29 -0700 Subject: Rename Utils::snprintf due to it being a #define on one platform. --- attic/DBM.cpp | 243 ------------------------------- attic/DBM.hpp | 168 --------------------- controller/EmbeddedNetworkController.cpp | 26 ++-- controller/JSONDB.cpp | 10 +- node/Address.hpp | 4 +- node/Dictionary.hpp | 4 +- node/InetAddress.cpp | 8 +- node/MAC.hpp | 2 +- node/MulticastGroup.hpp | 2 +- node/Network.cpp | 4 +- node/NetworkConfig.cpp | 2 +- node/Node.cpp | 2 +- node/Utils.cpp | 5 +- node/Utils.hpp | 3 +- one.cpp | 20 +-- osdep/BSDEthernetTap.cpp | 16 +- osdep/Http.cpp | 4 +- osdep/LinuxEthernetTap.cpp | 10 +- osdep/OSUtils.cpp | 6 +- osdep/OSXEthernetTap.cpp | 14 +- osdep/PortMapper.cpp | 4 +- osdep/WindowsEthernetTap.cpp | 10 +- selftest.cpp | 2 +- service/ClusterDefinition.hpp | 2 +- service/OneService.cpp | 62 ++++---- service/SoftwareUpdater.cpp | 2 +- 26 files changed, 111 insertions(+), 524 deletions(-) delete mode 100644 attic/DBM.cpp delete mode 100644 attic/DBM.hpp (limited to 'service/OneService.cpp') diff --git a/attic/DBM.cpp b/attic/DBM.cpp deleted file mode 100644 index 54f017e0..00000000 --- a/attic/DBM.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -#include "DBM.hpp" - -#include "../version.h" - -#include "../node/Salsa20.hpp" -#include "../node/Poly1305.hpp" -#include "../node/SHA512.hpp" - -#include "../osdep/OSUtils.hpp" - -#define ZT_STORED_OBJECT_TYPE__CLUSTER_NODE_STATUS (ZT_STORED_OBJECT__MAX_TYPE_ID + 1) -#define ZT_STORED_OBJECT_TYPE__CLUSTER_DEFINITION (ZT_STORED_OBJECT__MAX_TYPE_ID + 2) - -namespace ZeroTier { - -// We generate the cluster ID from our address and version info since this is -// not at all designed to allow interoperation between versions (or endians) -// in the same cluster. -static inline uint64_t _mkClusterId(const Address &myAddress) -{ - uint64_t x = ZEROTIER_ONE_VERSION_MAJOR; - x <<= 8; - x += ZEROTIER_ONE_VERSION_MINOR; - x <<= 8; - x += ZEROTIER_ONE_VERSION_REVISION; - x <<= 40; - x ^= myAddress.toInt(); -#if __BYTE_ORDER == __BIG_ENDIAN - ++x; -#endif; - return x; -} - -void DBM::onUpdate(uint64_t from,const _MapKey &k,const _MapValue &v,uint64_t rev) -{ - char p[4096]; - char tmp[ZT_DBM_MAX_VALUE_SIZE]; - if (_persistentPath((ZT_StoredObjectType)k.type,k.key,p,sizeof(p))) { - // Reduce unnecessary disk writes - FILE *f = fopen(p,"r"); - if (f) { - long n = (long)fread(tmp,1,sizeof(tmp),f); - fclose(f); - if ((n == (long)v.len)&&(!memcmp(v.data,tmp,n))) - return; - } - - // Write to disk if file has changed or was not already present - f = fopen(p,"w"); - if (f) { - if (fwrite(data,len,1,f) != 1) - fprintf(stderr,"WARNING: error writing to %s (I/O error)" ZT_EOL_S,p); - fclose(f); - if (type == ZT_STORED_OBJECT_IDENTITY_SECRET) - OSUtils::lockDownFile(p,false); - } else { - fprintf(stderr,"WARNING: error writing to %s (cannot open)" ZT_EOL_S,p); - } - } -} - -void DBM::onDelete(uint64_t from,const _MapKey &k) -{ - char p[4096]; - if (_persistentPath((ZT_StoredObjectType)k.type,k.key,p,sizeof(p))) - OSUtils::rm(p); -} - -DBM::_vsdm_cryptor::_vsdm_cryptor(const Identity &secretIdentity) -{ - uint8_t s512[64]; - SHA512::hash(h512,secretIdentity.privateKeyPair().priv.data,ZT_C25519_PRIVATE_KEY_LEN); - memcpy(_key,s512,sizeof(_key)); -} - -void DBM::_vsdm_cryptor::encrypt(void *d,unsigned long l) -{ - if (l >= 24) { // sanity check - uint8_t key[32]; - uint8_t authKey[32]; - uint8_t auth[16]; - - uint8_t *const iv = reinterpret_cast(d) + (l - 16); - Utils::getSecureRandom(iv,16); - memcpy(key,_key,32); - for(unsigned long i=0;i<8;++i) - _key[i] ^= iv[i]; - - Salsa20 s20(key,iv + 8); - memset(authKey,0,32); - s20.crypt12(authKey,authKey,32); - s20.crypt12(d,d,l - 24); - - Poly1305::compute(auth,d,l - 24,authKey); - memcpy(reinterpret_cast(d) + (l - 24),auth,8); - } -} - -bool DBM::_vsdm_cryptor::decrypt(void *d,unsigned long l) -{ - if (l >= 24) { // sanity check - uint8_t key[32]; - uint8_t authKey[32]; - uint8_t auth[16]; - - uint8_t *const iv = reinterpret_cast(d) + (l - 16); - memcpy(key,_key,32); - for(unsigned long i=0;i<8;++i) - _key[i] ^= iv[i]; - - Salsa20 s20(key,iv + 8); - memset(authKey,0,32); - s20.crypt12(authKey,authKey,32); - - Poly1305::compute(auth,d,l - 24,authKey); - if (!Utils::secureEq(reinterpret_cast(d) + (l - 24),auth,8)) - return false; - - s20.crypt12(d,d,l - 24); - - return true; - } - return false; -} - -DBM::DBM(const Identity &secretIdentity,uint64_t clusterMemberId,const std::string &basePath,Node *node) : - _basePath(basePath), - _node(node), - _startTime(OSUtils::now()), - _m(_mkClusterId(secretIdentity.address()),clusterMemberId,false,_vsdm_cryptor(secretIdentity),_vsdm_watcher(this)) -{ -} - -DBM::~DBM() -{ -} - -void DBM::put(const ZT_StoredObjectType type,const uint64_t key,const void *data,unsigned int len) -{ - char p[4096]; - if (_m.put(_MapKey(key,(uint16_t)type),Value(OSUtils::now(),(uint16_t)len,data))) { - if (_persistentPath(type,key,p,sizeof(p))) { - FILE *f = fopen(p,"w"); - if (f) { - if (fwrite(data,len,1,f) != 1) - fprintf(stderr,"WARNING: error writing to %s (I/O error)" ZT_EOL_S,p); - fclose(f); - if (type == ZT_STORED_OBJECT_IDENTITY_SECRET) - OSUtils::lockDownFile(p,false); - } else { - fprintf(stderr,"WARNING: error writing to %s (cannot open)" ZT_EOL_S,p); - } - } - } -} - -bool DBM::get(const ZT_StoredObjectType type,const uint64_t key,Value &value) -{ - char p[4096]; - if (_m.get(_MapKey(key,(uint16_t)type),value)) - return true; - if (_persistentPath(type,key,p,sizeof(p))) { - FILE *f = fopen(p,"r"); - if (f) { - long n = (long)fread(value.data,1,sizeof(value.data),f); - value.len = (n > 0) ? (uint16_t)n : (uint16_t)0; - fclose(f); - value.ts = OSUtils::getLastModified(p); - _m.put(_MapKey(key,(uint16_t)type),value); - return true; - } - } - return false; -} - -void DBM::del(const ZT_StoredObjectType type,const uint64_t key) -{ - char p[4096]; - _m.del(_MapKey(key,(uint16_t)type)); - if (_persistentPath(type,key,p,sizeof(p))) - OSUtils::rm(p); -} - -void DBM::clean() -{ -} - -bool DBM::_persistentPath(const ZT_StoredObjectType type,const uint64_t key,char *p,unsigned int maxlen) -{ - switch(type) { - case ZT_STORED_OBJECT_IDENTITY_PUBLIC: - Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "identity.public",_basePath.c_str()); - return true; - case ZT_STORED_OBJECT_IDENTITY_SECRET: - Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "identity.secret",_basePath.c_str()); - return true; - case ZT_STORED_OBJECT_IDENTITY: - Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "iddb.d" ZT_PATH_SEPARATOR_S "%.10llx",_basePath.c_str(),key); - return true; - case ZT_STORED_OBJECT_NETWORK_CONFIG: - Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.conf",_basePath.c_str(),key); - return true; - case ZT_STORED_OBJECT_PLANET: - Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "planet",_basePath.c_str()); - return true; - case ZT_STORED_OBJECT_MOON: - Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "moons.d" ZT_PATH_SEPARATOR_S "%.16llx.moon",_basePath.c_str(),key); - return true; - case (ZT_StoredObjectType)ZT_STORED_OBJECT_TYPE__CLUSTER_DEFINITION: - Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "cluster",_basePath.c_str()); - return true; - default: - return false; - } -} - -} // namespace ZeroTier diff --git a/attic/DBM.hpp b/attic/DBM.hpp deleted file mode 100644 index c6d5b8c0..00000000 --- a/attic/DBM.hpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -#ifndef ZT_DBM_HPP___ -#define ZT_DBM_HPP___ - -#include -#include -#include -#include - -#include - -#include "../node/Constants.hpp" -#include "../node/Mutex.hpp" -#include "../node/Utils.hpp" -#include "../node/Identity.hpp" -#include "../node/Peer.hpp" - -#include "../ext/vsdm/vsdm.hpp" - -// The Peer is the largest structure we persist here -#define ZT_DBM_MAX_VALUE_SIZE sizeof(Peer) - -namespace ZeroTier { - -class Node; -class DBM; - -class DBM -{ -public: - ZT_PACKED_STRUCT(struct Value - { - Value(const uint64_t t,const uint16_t l,const void *d) : - ts(t), - l(l) - { - memcpy(data,d,l); - } - uint64_t ts; - uint16_t len; - uint8_t data[ZT_DBM_MAX_VALUE_SIZE]; - }); - -private: - ZT_PACKED_STRUCT(struct _MapKey - { - _MapKey() : obj(0),type(0) {} - _MapKey(const uint16_t t,const uint64_t o) : obj(o),type(t) {} - uint64_t obj; - uint16_t type; - inline bool operator==(const _MapKey &k) const { return ((obj == k.obj)&&(type == k.type)); } - }); - struct _MapHasher - { - inline std::size_t operator()(const _MapKey &k) const { return (std::size_t)((k.obj ^ (k.obj >> 32)) + (uint64_t)k.type); } - }; - - void onUpdate(uint64_t from,const _MapKey &k,const Value &v,uint64_t rev); - void onDelete(uint64_t from,const _MapKey &k); - - class _vsdm_watcher - { - public: - _vsdm_watcher(DBM *p) : _parent(p) {} - inline void add(uint64_t from,const _MapKey &k,const Value &v,uint64_t rev) { _parent->onUpdate(from,k,v,rev); } - inline void update(uint64_t from,const _MapKey &k,const Value &v,uint64_t rev) { _parent->onUpdate(from,k,v,rev); } - inline void del(uint64_t from,const _MapKey &k) { _parent->onDelete(from,k); } - private: - DBM *_parent; - }; - class _vsdm_serializer - { - public: - static inline unsigned long objectSize(const _MapKey &k) { return 10; } - static inline unsigned long objectSize(const Value &v) { return (10 + v.len); } - static inline const char *objectData(const _MapKey &k) { return reinterpret_cast(&k); } - static inline const char *objectData(const Value &v) { return reinterpret_cast(&v); } - static inline bool objectDeserialize(const char *d,unsigned long l,_MapKey &k) - { - if (l == 10) { - memcpy(&k,d,10); - return true; - } - return false; - } - static inline bool objectDeserialize(const char *d,unsigned long l,Value &v) - { - if ((l >= 10)&&(l <= (10 + ZT_DBM_MAX_VALUE_SIZE))) { - memcpy(&v,d,l); - return true; - } - return false; - } - }; - class _vsdm_cryptor - { - public: - _vsdm_cryptor(const Identity &secretIdentity); - static inline unsigned long overhead() { return 24; } - void encrypt(void *d,unsigned long l); - bool decrypt(void *d,unsigned long l); - uint8_t _key[32]; - }; - - typedef vsdm< _MapKey,Value,16384,_vsdm_watcher,_vsdm_serializer,_vsdm_cryptor,_MapHasher > _Map; - - friend class _Map; - -public: - ZT_PACKED_STRUCT(struct ClusterPeerStatus - { - uint64_t startTime; - uint64_t currentTime; - uint64_t clusterPeersConnected; - uint64_t ztPeersConnected; - uint16_t platform; - uint16_t arch; - }); - - DBM(const Identity &secretIdentity,uint64_t clusterMemberId,const std::string &basePath,Node *node); - - ~DBM(); - - void put(const ZT_StoredObjectType type,const uint64_t key,const void *data,unsigned int len); - - bool get(const ZT_StoredObjectType type,const uint64_t key,Value &value); - - void del(const ZT_StoredObjectType type,const uint64_t key); - - void clean(); - -private: - bool DBM::_persistentPath(const ZT_StoredObjectType type,const uint64_t key,char *p,unsigned int maxlen); - - const std::string _basePath; - Node *const _node; - uint64_t _startTime; - _Map _m; -}; - -} // namespace ZeroTier - -#endif diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index e2eaa788..85c759e7 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -122,12 +122,12 @@ static json _renderRule(ZT_VirtualNetworkRule &rule) break; case ZT_NETWORK_RULE_MATCH_MAC_SOURCE: r["type"] = "MATCH_MAC_SOURCE"; - Utils::snprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]); + Utils::ztsnprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]); r["mac"] = tmp; break; case ZT_NETWORK_RULE_MATCH_MAC_DEST: r["type"] = "MATCH_MAC_DEST"; - Utils::snprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]); + Utils::ztsnprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]); r["mac"] = tmp; break; case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE: @@ -179,7 +179,7 @@ static json _renderRule(ZT_VirtualNetworkRule &rule) break; case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS: r["type"] = "MATCH_CHARACTERISTICS"; - Utils::snprintf(tmp,sizeof(tmp),"%.16llx",rule.v.characteristics); + Utils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",rule.v.characteristics); r["mask"] = tmp; break; case ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE: @@ -514,7 +514,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( _db.eachMember(nwid,[&responseBody](uint64_t networkId,uint64_t nodeId,const json &member) { if ((member.is_object())&&(member.size() > 0)) { char tmp[128]; - Utils::snprintf(tmp,sizeof(tmp),"%s%.10llx\":%llu",(responseBody.length() > 1) ? ",\"" : "\"",(unsigned long long)nodeId,(unsigned long long)OSUtils::jsonInt(member["revision"],0)); + Utils::ztsnprintf(tmp,sizeof(tmp),"%s%.10llx\":%llu",(responseBody.length() > 1) ? ",\"" : "\"",(unsigned long long)nodeId,(unsigned long long)OSUtils::jsonInt(member["revision"],0)); responseBody.append(tmp); } }); @@ -548,7 +548,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( for(std::vector::const_iterator i(networkIds.begin());i!=networkIds.end();++i) { if (responseBody.length() > 1) responseBody.push_back(','); - Utils::snprintf(tmp,sizeof(tmp),"\"%.16llx\"",(unsigned long long)*i); + Utils::ztsnprintf(tmp,sizeof(tmp),"\"%.16llx\"",(unsigned long long)*i); responseBody.append(tmp); } responseBody.push_back(']'); @@ -562,7 +562,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( // Controller status char tmp[4096]; - Utils::snprintf(tmp,sizeof(tmp),"{\n\t\"controller\": true,\n\t\"apiVersion\": %d,\n\t\"clock\": %llu\n}\n",ZT_NETCONF_CONTROLLER_API_VERSION,(unsigned long long)OSUtils::now()); + Utils::ztsnprintf(tmp,sizeof(tmp),"{\n\t\"controller\": true,\n\t\"apiVersion\": %d,\n\t\"clock\": %llu\n}\n",ZT_NETCONF_CONTROLLER_API_VERSION,(unsigned long long)OSUtils::now()); responseBody = tmp; responseContentType = "application/json"; return 200; @@ -603,14 +603,14 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( if ((path.size() >= 2)&&(path[1].length() == 16)) { uint64_t nwid = Utils::hexStrToU64(path[1].c_str()); char nwids[24]; - Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid); + Utils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid); if (path.size() >= 3) { if ((path.size() == 4)&&(path[2] == "member")&&(path[3].length() == 10)) { uint64_t address = Utils::hexStrToU64(path[3].c_str()); char addrs[24]; - Utils::snprintf(addrs,sizeof(addrs),"%.10llx",(unsigned long long)address); + Utils::ztsnprintf(addrs,sizeof(addrs),"%.10llx",(unsigned long long)address); json member; _db.getNetworkMember(nwid,address,member); @@ -748,7 +748,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( if (!nwid) return 503; } - Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid); + Utils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid); json network; _db.getNetwork(nwid,network); @@ -995,7 +995,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( _queue.post(qe); char tmp[64]; - Utils::snprintf(tmp,sizeof(tmp),"{\"clock\":%llu,\"ping\":%s}",(unsigned long long)now,OSUtils::jsonDump(b).c_str()); + Utils::ztsnprintf(tmp,sizeof(tmp),"{\"clock\":%llu,\"ping\":%s}",(unsigned long long)now,OSUtils::jsonDump(b).c_str()); responseBody = tmp; responseContentType = "application/json"; @@ -1083,7 +1083,7 @@ void EmbeddedNetworkController::threadMain() auto ms = this->_memberStatus.find(_MemberStatusKey(networkId,nodeId)); if (ms != _memberStatus.end()) lrt = ms->second.lastRequestTime; - Utils::snprintf(tmp,sizeof(tmp),"%s\"%.16llx-%.10llx\":%llu", + Utils::ztsnprintf(tmp,sizeof(tmp),"%s\"%.16llx-%.10llx\":%llu", (first) ? "" : ",", (unsigned long long)networkId, (unsigned long long)nodeId, @@ -1093,7 +1093,7 @@ void EmbeddedNetworkController::threadMain() }); } char tmp2[256]; - Utils::snprintf(tmp2,sizeof(tmp2),"},\"clock\":%llu,\"startTime\":%llu}",(unsigned long long)now,(unsigned long long)_startTime); + Utils::ztsnprintf(tmp2,sizeof(tmp2),"},\"clock\":%llu,\"startTime\":%llu}",(unsigned long long)now,(unsigned long long)_startTime); pong.append(tmp2); _db.writeRaw("pong",pong); } @@ -1126,7 +1126,7 @@ void EmbeddedNetworkController::_request( ms.lastRequestTime = now; } - Utils::snprintf(nwids,sizeof(nwids),"%.16llx",nwid); + Utils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid); if (!_db.getNetworkAndMember(nwid,identity.address().toInt(),network,member,ns)) { _sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_OBJECT_NOT_FOUND); return; diff --git a/controller/JSONDB.cpp b/controller/JSONDB.cpp index e0dd1742..acf23700 100644 --- a/controller/JSONDB.cpp +++ b/controller/JSONDB.cpp @@ -94,7 +94,7 @@ bool JSONDB::writeRaw(const std::string &n,const std::string &obj) std::string body; std::map reqHeaders; char tmp[64]; - Utils::snprintf(tmp,sizeof(tmp),"%lu",(unsigned long)obj.length()); + Utils::ztsnprintf(tmp,sizeof(tmp),"%lu",(unsigned long)obj.length()); reqHeaders["Content-Length"] = tmp; reqHeaders["Content-Type"] = "application/json"; const unsigned int sc = Http::PUT(0,ZT_JSONDB_HTTP_TIMEOUT,reinterpret_cast(&_httpAddr),(_basePath+"/"+n).c_str(),reqHeaders,obj.data(),(unsigned long)obj.length(),headers,body); @@ -164,7 +164,7 @@ bool JSONDB::getNetworkMember(const uint64_t networkId,const uint64_t nodeId,nlo void JSONDB::saveNetwork(const uint64_t networkId,const nlohmann::json &networkConfig) { char n[64]; - Utils::snprintf(n,sizeof(n),"network/%.16llx",(unsigned long long)networkId); + Utils::ztsnprintf(n,sizeof(n),"network/%.16llx",(unsigned long long)networkId); writeRaw(n,OSUtils::jsonDump(networkConfig)); { Mutex::Lock _l(_networks_m); @@ -176,7 +176,7 @@ void JSONDB::saveNetwork(const uint64_t networkId,const nlohmann::json &networkC void JSONDB::saveNetworkMember(const uint64_t networkId,const uint64_t nodeId,const nlohmann::json &memberConfig) { char n[256]; - Utils::snprintf(n,sizeof(n),"network/%.16llx/member/%.10llx",(unsigned long long)networkId,(unsigned long long)nodeId); + Utils::ztsnprintf(n,sizeof(n),"network/%.16llx/member/%.10llx",(unsigned long long)networkId,(unsigned long long)nodeId); writeRaw(n,OSUtils::jsonDump(memberConfig)); { Mutex::Lock _l(_networks_m); @@ -202,7 +202,7 @@ nlohmann::json JSONDB::eraseNetwork(const uint64_t networkId) } char n[256]; - Utils::snprintf(n,sizeof(n),"network/%.16llx",(unsigned long long)networkId); + Utils::ztsnprintf(n,sizeof(n),"network/%.16llx",(unsigned long long)networkId); if (_httpAddr) { // Deletion is currently done by Central in harnessed mode @@ -229,7 +229,7 @@ nlohmann::json JSONDB::eraseNetwork(const uint64_t networkId) nlohmann::json JSONDB::eraseNetworkMember(const uint64_t networkId,const uint64_t nodeId,bool recomputeSummaryInfo) { char n[256]; - Utils::snprintf(n,sizeof(n),"network/%.16llx/member/%.10llx",(unsigned long long)networkId,(unsigned long long)nodeId); + Utils::ztsnprintf(n,sizeof(n),"network/%.16llx/member/%.10llx",(unsigned long long)networkId,(unsigned long long)nodeId); if (_httpAddr) { // Deletion is currently done by the caller in Central harnessed mode diff --git a/node/Address.hpp b/node/Address.hpp index 9d2d1734..98e32858 100644 --- a/node/Address.hpp +++ b/node/Address.hpp @@ -144,7 +144,7 @@ public: inline std::string toString() const { char buf[16]; - Utils::snprintf(buf,sizeof(buf),"%.10llx",(unsigned long long)_a); + Utils::ztsnprintf(buf,sizeof(buf),"%.10llx",(unsigned long long)_a); return std::string(buf); }; @@ -154,7 +154,7 @@ public: */ inline void toString(char *buf,unsigned int len) const { - Utils::snprintf(buf,len,"%.10llx",(unsigned long long)_a); + Utils::ztsnprintf(buf,len,"%.10llx",(unsigned long long)_a); } /** diff --git a/node/Dictionary.hpp b/node/Dictionary.hpp index 4413d628..0b000f13 100644 --- a/node/Dictionary.hpp +++ b/node/Dictionary.hpp @@ -391,7 +391,7 @@ public: inline bool add(const char *key,uint64_t value) { char tmp[32]; - Utils::snprintf(tmp,sizeof(tmp),"%llx",(unsigned long long)value); + Utils::ztsnprintf(tmp,sizeof(tmp),"%llx",(unsigned long long)value); return this->add(key,tmp,-1); } @@ -401,7 +401,7 @@ public: inline bool add(const char *key,const Address &a) { char tmp[32]; - Utils::snprintf(tmp,sizeof(tmp),"%.10llx",(unsigned long long)a.toInt()); + Utils::ztsnprintf(tmp,sizeof(tmp),"%.10llx",(unsigned long long)a.toInt()); return this->add(key,tmp,-1); } diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp index 0fbb2d68..17d7c72e 100644 --- a/node/InetAddress.cpp +++ b/node/InetAddress.cpp @@ -152,7 +152,7 @@ std::string InetAddress::toString() const char buf[128]; switch(ss_family) { case AF_INET: - Utils::snprintf(buf,sizeof(buf),"%d.%d.%d.%d/%d", + Utils::ztsnprintf(buf,sizeof(buf),"%d.%d.%d.%d/%d", (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[0], (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[1], (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[2], @@ -161,7 +161,7 @@ std::string InetAddress::toString() const ); return std::string(buf); case AF_INET6: - Utils::snprintf(buf,sizeof(buf),"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x/%d", + Utils::ztsnprintf(buf,sizeof(buf),"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x/%d", (int)(reinterpret_cast(this)->sin6_addr.s6_addr[0]), (int)(reinterpret_cast(this)->sin6_addr.s6_addr[1]), (int)(reinterpret_cast(this)->sin6_addr.s6_addr[2]), @@ -190,7 +190,7 @@ std::string InetAddress::toIpString() const char buf[128]; switch(ss_family) { case AF_INET: - Utils::snprintf(buf,sizeof(buf),"%d.%d.%d.%d", + Utils::ztsnprintf(buf,sizeof(buf),"%d.%d.%d.%d", (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[0], (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[1], (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[2], @@ -198,7 +198,7 @@ std::string InetAddress::toIpString() const ); return std::string(buf); case AF_INET6: - Utils::snprintf(buf,sizeof(buf),"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", + Utils::ztsnprintf(buf,sizeof(buf),"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", (int)(reinterpret_cast(this)->sin6_addr.s6_addr[0]), (int)(reinterpret_cast(this)->sin6_addr.s6_addr[1]), (int)(reinterpret_cast(this)->sin6_addr.s6_addr[2]), diff --git a/node/MAC.hpp b/node/MAC.hpp index e7717d99..db50aeb1 100644 --- a/node/MAC.hpp +++ b/node/MAC.hpp @@ -178,7 +178,7 @@ public: */ inline void toString(char *buf,unsigned int len) const { - Utils::snprintf(buf,len,"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)(*this)[0],(int)(*this)[1],(int)(*this)[2],(int)(*this)[3],(int)(*this)[4],(int)(*this)[5]); + Utils::ztsnprintf(buf,len,"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)(*this)[0],(int)(*this)[1],(int)(*this)[2],(int)(*this)[3],(int)(*this)[4],(int)(*this)[5]); } /** diff --git a/node/MulticastGroup.hpp b/node/MulticastGroup.hpp index 4240db67..7cbec2e0 100644 --- a/node/MulticastGroup.hpp +++ b/node/MulticastGroup.hpp @@ -100,7 +100,7 @@ public: inline std::string toString() const { char buf[64]; - Utils::snprintf(buf,sizeof(buf),"%.2x%.2x%.2x%.2x%.2x%.2x/%.8lx",(unsigned int)_mac[0],(unsigned int)_mac[1],(unsigned int)_mac[2],(unsigned int)_mac[3],(unsigned int)_mac[4],(unsigned int)_mac[5],(unsigned long)_adi); + Utils::ztsnprintf(buf,sizeof(buf),"%.2x%.2x%.2x%.2x%.2x%.2x/%.8lx",(unsigned int)_mac[0],(unsigned int)_mac[1],(unsigned int)_mac[2],(unsigned int)_mac[3],(unsigned int)_mac[4],(unsigned int)_mac[5],(unsigned long)_adi); return std::string(buf); } diff --git a/node/Network.cpp b/node/Network.cpp index 12deeeb7..8c6f2ce8 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -51,7 +51,7 @@ namespace ZeroTier { namespace { #ifdef ZT_RULES_ENGINE_DEBUGGING -#define FILTER_TRACE(f,...) { Utils::snprintf(dpbuf,sizeof(dpbuf),f,##__VA_ARGS__); dlog.push_back(std::string(dpbuf)); } +#define FILTER_TRACE(f,...) { Utils::ztsnprintf(dpbuf,sizeof(dpbuf),f,##__VA_ARGS__); dlog.push_back(std::string(dpbuf)); } static const char *_rtn(const ZT_VirtualNetworkRuleType rt) { switch(rt) { @@ -1261,7 +1261,7 @@ void Network::requestConfiguration(void *tPtr) nconf->rules[13].t = (uint8_t)ZT_NETWORK_RULE_ACTION_DROP; nconf->type = ZT_NETWORK_TYPE_PUBLIC; - Utils::snprintf(nconf->name,sizeof(nconf->name),"adhoc-%.04x-%.04x",(int)startPortRange,(int)endPortRange); + Utils::ztsnprintf(nconf->name,sizeof(nconf->name),"adhoc-%.04x-%.04x",(int)startPortRange,(int)endPortRange); this->setConfiguration(tPtr,*nconf,false); delete nconf; diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp index c39f6cab..65101c3a 100644 --- a/node/NetworkConfig.cpp +++ b/node/NetworkConfig.cpp @@ -94,7 +94,7 @@ bool NetworkConfig::toDictionary(Dictionary &d,b if (ets.length() > 0) ets.push_back(','); char tmp2[16]; - Utils::snprintf(tmp2,sizeof(tmp2),"%x",et); + Utils::ztsnprintf(tmp2,sizeof(tmp2),"%x",et); ets.append(tmp2); } et = 0; diff --git a/node/Node.cpp b/node/Node.cpp index 39325b65..ab49e63b 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -742,7 +742,7 @@ void Node::postTrace(const char *module,unsigned int line,const char *fmt,...) va_end(ap); tmp2[sizeof(tmp2)-1] = (char)0; - Utils::snprintf(tmp1,sizeof(tmp1),"[%s] %s:%u %s",nowstr,module,line,tmp2); + Utils::ztsnprintf(tmp1,sizeof(tmp1),"[%s] %s:%u %s",nowstr,module,line,tmp2); postEvent((void *)0,ZT_EVENT_TRACE,tmp1); } #endif // ZT_TRACE diff --git a/node/Utils.cpp b/node/Utils.cpp index d69e5335..d2321e16 100644 --- a/node/Utils.cpp +++ b/node/Utils.cpp @@ -244,8 +244,7 @@ bool Utils::scopy(char *dest,unsigned int len,const char *src) return true; } -unsigned int Utils::snprintf(char *buf,unsigned int len,const char *fmt,...) - throw(std::length_error) +unsigned int Utils::ztsnprintf(char *buf,unsigned int len,const char *fmt,...) { va_list ap; @@ -256,7 +255,7 @@ unsigned int Utils::snprintf(char *buf,unsigned int len,const char *fmt,...) if ((n >= (int)len)||(n < 0)) { if (len) buf[len - 1] = (char)0; - throw std::length_error("buf[] overflow in Utils::snprintf"); + throw std::length_error("buf[] overflow"); } return (unsigned int)n; diff --git a/node/Utils.hpp b/node/Utils.hpp index 25a90055..212ef247 100644 --- a/node/Utils.hpp +++ b/node/Utils.hpp @@ -244,8 +244,7 @@ public: * @param ... Format arguments * @throws std::length_error buf[] too short (buf[] will still be left null-terminated) */ - static unsigned int snprintf(char *buf,unsigned int len,const char *fmt,...) - throw(std::length_error); + static unsigned int ztsnprintf(char *buf,unsigned int len,const char *fmt,...); /** * Count the number of bits set in an integer diff --git a/one.cpp b/one.cpp index 93504cfb..cbf09121 100644 --- a/one.cpp +++ b/one.cpp @@ -260,9 +260,9 @@ static int cli(int argc,char **argv) if (hd) { char p[4096]; #ifdef __APPLE__ - Utils::snprintf(p,sizeof(p),"%s/Library/Application Support/ZeroTier/One/authtoken.secret",hd); + Utils::ztsnprintf(p,sizeof(p),"%s/Library/Application Support/ZeroTier/One/authtoken.secret",hd); #else - Utils::snprintf(p,sizeof(p),"%s/.zeroTierOneAuthToken",hd); + Utils::ztsnprintf(p,sizeof(p),"%s/.zeroTierOneAuthToken",hd); #endif OSUtils::readFile(p,authToken); } @@ -278,7 +278,7 @@ static int cli(int argc,char **argv) InetAddress addr; { char addrtmp[256]; - Utils::snprintf(addrtmp,sizeof(addrtmp),"%s/%u",ip.c_str(),port); + Utils::ztsnprintf(addrtmp,sizeof(addrtmp),"%s/%u",ip.c_str(),port); addr = InetAddress(addrtmp); } @@ -366,7 +366,7 @@ static int cli(int argc,char **argv) std::string addr = path["address"]; const uint64_t now = OSUtils::now(); const double lq = (path.count("linkQuality")) ? (double)path["linkQuality"] : -1.0; - Utils::snprintf(tmp,sizeof(tmp),"%s;%llu;%llu;%1.2f",addr.c_str(),now - (uint64_t)path["lastSend"],now - (uint64_t)path["lastReceive"],lq); + Utils::ztsnprintf(tmp,sizeof(tmp),"%s;%llu;%llu;%1.2f",addr.c_str(),now - (uint64_t)path["lastSend"],now - (uint64_t)path["lastReceive"],lq); bestPath = tmp; break; } @@ -378,7 +378,7 @@ static int cli(int argc,char **argv) int64_t vmin = p["versionMinor"]; int64_t vrev = p["versionRev"]; if (vmaj >= 0) { - Utils::snprintf(ver,sizeof(ver),"%lld.%lld.%lld",vmaj,vmin,vrev); + Utils::ztsnprintf(ver,sizeof(ver),"%lld.%lld.%lld",vmaj,vmin,vrev); } else { ver[0] = '-'; ver[1] = (char)0; @@ -527,9 +527,9 @@ static int cli(int argc,char **argv) const uint64_t seed = Utils::hexStrToU64(arg2.c_str()); if ((worldId)&&(seed)) { char jsons[1024]; - Utils::snprintf(jsons,sizeof(jsons),"{\"seed\":\"%s\"}",arg2.c_str()); + Utils::ztsnprintf(jsons,sizeof(jsons),"{\"seed\":\"%s\"}",arg2.c_str()); char cl[128]; - Utils::snprintf(cl,sizeof(cl),"%u",(unsigned int)strlen(jsons)); + Utils::ztsnprintf(cl,sizeof(cl),"%u",(unsigned int)strlen(jsons)); requestHeaders["Content-Type"] = "application/json"; requestHeaders["Content-Length"] = cl; unsigned int scode = Http::POST( @@ -579,11 +579,11 @@ static int cli(int argc,char **argv) if (eqidx != std::string::npos) { if ((arg2.substr(0,eqidx) == "allowManaged")||(arg2.substr(0,eqidx) == "allowGlobal")||(arg2.substr(0,eqidx) == "allowDefault")) { char jsons[1024]; - Utils::snprintf(jsons,sizeof(jsons),"{\"%s\":%s}", + Utils::ztsnprintf(jsons,sizeof(jsons),"{\"%s\":%s}", arg2.substr(0,eqidx).c_str(), (((arg2.substr(eqidx,2) == "=t")||(arg2.substr(eqidx,2) == "=1")) ? "true" : "false")); char cl[128]; - Utils::snprintf(cl,sizeof(cl),"%u",(unsigned int)strlen(jsons)); + Utils::ztsnprintf(cl,sizeof(cl),"%u",(unsigned int)strlen(jsons)); requestHeaders["Content-Type"] = "application/json"; requestHeaders["Content-Length"] = cl; unsigned int scode = Http::POST( @@ -864,7 +864,7 @@ static int idtool(int argc,char **argv) Buffer wbuf; w.serialize(wbuf); char fn[128]; - Utils::snprintf(fn,sizeof(fn),"%.16llx.moon",w.id()); + Utils::ztsnprintf(fn,sizeof(fn),"%.16llx.moon",w.id()); OSUtils::writeFile(fn,wbuf.data(),wbuf.size()); printf("wrote %s (signed world with timestamp %llu)" ZT_EOL_S,fn,(unsigned long long)now); } diff --git a/osdep/BSDEthernetTap.cpp b/osdep/BSDEthernetTap.cpp index 5bb5fbd1..f07f9e5a 100644 --- a/osdep/BSDEthernetTap.cpp +++ b/osdep/BSDEthernetTap.cpp @@ -114,8 +114,8 @@ BSDEthernetTap::BSDEthernetTap( std::vector devFiles(OSUtils::listDirectory("/dev")); for(int i=9993;i<(9993+128);++i) { - Utils::snprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i); - Utils::snprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname); + Utils::ztsnprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i); + Utils::ztsnprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname); if (std::find(devFiles.begin(),devFiles.end(),std::string(tmpdevname)) == devFiles.end()) { long cpid = (long)vfork(); if (cpid == 0) { @@ -152,8 +152,8 @@ BSDEthernetTap::BSDEthernetTap( /* Other BSDs like OpenBSD only have a limited number of tap devices that cannot be renamed */ for(int i=0;i<64;++i) { - Utils::snprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i); - Utils::snprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname); + Utils::ztsnprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i); + Utils::ztsnprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname); _fd = ::open(devpath,O_RDWR); if (_fd > 0) { _dev = tmpdevname; @@ -171,9 +171,9 @@ BSDEthernetTap::BSDEthernetTap( } // Configure MAC address and MTU, bring interface up - Utils::snprintf(ethaddr,sizeof(ethaddr),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)mac[0],(int)mac[1],(int)mac[2],(int)mac[3],(int)mac[4],(int)mac[5]); - Utils::snprintf(mtustr,sizeof(mtustr),"%u",_mtu); - Utils::snprintf(metstr,sizeof(metstr),"%u",_metric); + Utils::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]); + Utils::ztsnprintf(mtustr,sizeof(mtustr),"%u",_mtu); + Utils::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); @@ -385,7 +385,7 @@ void BSDEthernetTap::setMtu(unsigned int mtu) long cpid = (long)vfork(); if (cpid == 0) { char tmp[64]; - Utils::snprintf(tmp,sizeof(tmp),"%u",mtu); + Utils::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) { diff --git a/osdep/Http.cpp b/osdep/Http.cpp index f1d3bfe2..3c556f44 100644 --- a/osdep/Http.cpp +++ b/osdep/Http.cpp @@ -244,10 +244,10 @@ unsigned int Http::_do( try { char tmp[1024]; - Utils::snprintf(tmp,sizeof(tmp),"%s %s HTTP/1.1\r\n",method,path); + Utils::ztsnprintf(tmp,sizeof(tmp),"%s %s HTTP/1.1\r\n",method,path); handler.writeBuf.append(tmp); for(std::map::const_iterator h(requestHeaders.begin());h!=requestHeaders.end();++h) { - Utils::snprintf(tmp,sizeof(tmp),"%s: %s\r\n",h->first.c_str(),h->second.c_str()); + Utils::ztsnprintf(tmp,sizeof(tmp),"%s: %s\r\n",h->first.c_str(),h->second.c_str()); handler.writeBuf.append(tmp); } handler.writeBuf.append("\r\n"); diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index ccaa92ef..fc5199f1 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -97,7 +97,7 @@ LinuxEthernetTap::LinuxEthernetTap( char procpath[128],nwids[32]; struct stat sbuf; - Utils::snprintf(nwids,sizeof(nwids),"%.16llx",nwid); + Utils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid); Mutex::Lock _l(__tapCreateLock); // create only one tap at a time, globally @@ -134,7 +134,7 @@ LinuxEthernetTap::LinuxEthernetTap( std::map::const_iterator gdmEntry = globalDeviceMap.find(nwids); if (gdmEntry != globalDeviceMap.end()) { Utils::scopy(ifr.ifr_name,sizeof(ifr.ifr_name),gdmEntry->second.c_str()); - Utils::snprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); + Utils::ztsnprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); recalledDevice = (stat(procpath,&sbuf) != 0); } @@ -142,8 +142,8 @@ LinuxEthernetTap::LinuxEthernetTap( #ifdef __SYNOLOGY__ int devno = 50; do { - Utils::snprintf(ifr.ifr_name,sizeof(ifr.ifr_name),"eth%d",devno++); - Utils::snprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); + Utils::ztsnprintf(ifr.ifr_name,sizeof(ifr.ifr_name),"eth%d",devno++); + Utils::ztsnprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); } while (stat(procpath,&sbuf) == 0); // try zt#++ until we find one that does not exist #else char devno = 0; @@ -158,7 +158,7 @@ LinuxEthernetTap::LinuxEthernetTap( _base32_5_to_8(reinterpret_cast(tmp2) + 5,tmp3 + 10); tmp3[15] = (char)0; memcpy(ifr.ifr_name,tmp3,16); - Utils::snprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); + Utils::ztsnprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); } while (stat(procpath,&sbuf) == 0); #endif } diff --git a/osdep/OSUtils.cpp b/osdep/OSUtils.cpp index 53e8bb97..bf0dc04d 100644 --- a/osdep/OSUtils.cpp +++ b/osdep/OSUtils.cpp @@ -134,7 +134,7 @@ long OSUtils::cleanDirectory(const char *path,const uint64_t olderThan) if (date.QuadPart > 0) { date.QuadPart -= adjust.QuadPart; if ((uint64_t)((date.QuadPart / 10000000) * 1000) < olderThan) { - Utils::snprintf(tmp, sizeof(tmp), "%s\\%s", path, ffd.cFileName); + Utils::ztsnprintf(tmp, sizeof(tmp), "%s\\%s", path, ffd.cFileName); if (DeleteFileA(tmp)) ++cleaned; } @@ -157,7 +157,7 @@ long OSUtils::cleanDirectory(const char *path,const uint64_t olderThan) break; if (dptr) { if ((strcmp(dptr->d_name,"."))&&(strcmp(dptr->d_name,".."))&&(dptr->d_type == DT_REG)) { - Utils::snprintf(tmp,sizeof(tmp),"%s/%s",path,dptr->d_name); + Utils::ztsnprintf(tmp,sizeof(tmp),"%s/%s",path,dptr->d_name); if (stat(tmp,&st) == 0) { uint64_t mt = (uint64_t)(st.st_mtime); if ((mt > 0)&&((mt * 1000) < olderThan)) { @@ -446,7 +446,7 @@ std::string OSUtils::jsonString(const nlohmann::json &jv,const char *dfl) return jv; } else if (jv.is_number()) { char tmp[64]; - Utils::snprintf(tmp,sizeof(tmp),"%llu",(uint64_t)jv); + Utils::ztsnprintf(tmp,sizeof(tmp),"%llu",(uint64_t)jv); return tmp; } else if (jv.is_boolean()) { return ((bool)jv ? std::string("1") : std::string("0")); diff --git a/osdep/OSXEthernetTap.cpp b/osdep/OSXEthernetTap.cpp index f5e1c43f..e082408e 100644 --- a/osdep/OSXEthernetTap.cpp +++ b/osdep/OSXEthernetTap.cpp @@ -336,7 +336,7 @@ OSXEthernetTap::OSXEthernetTap( char devpath[64],ethaddr[64],mtustr[32],metstr[32],nwids[32]; struct stat stattmp; - Utils::snprintf(nwids,sizeof(nwids),"%.16llx",nwid); + Utils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid); Mutex::Lock _gl(globalTapCreateLock); @@ -391,13 +391,13 @@ OSXEthernetTap::OSXEthernetTap( // Open the first unused tap device if we didn't recall a previous one. if (!recalledDevice) { for(int i=0;i<64;++i) { - Utils::snprintf(devpath,sizeof(devpath),"/dev/zt%d",i); + Utils::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]; - Utils::snprintf(foo,sizeof(foo),"zt%d",i); + Utils::ztsnprintf(foo,sizeof(foo),"zt%d",i); _dev = foo; break; } @@ -413,9 +413,9 @@ OSXEthernetTap::OSXEthernetTap( } // Configure MAC address and MTU, bring interface up - Utils::snprintf(ethaddr,sizeof(ethaddr),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)mac[0],(int)mac[1],(int)mac[2],(int)mac[3],(int)mac[4],(int)mac[5]); - Utils::snprintf(mtustr,sizeof(mtustr),"%u",_mtu); - Utils::snprintf(metstr,sizeof(metstr),"%u",_metric); + Utils::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]); + Utils::ztsnprintf(mtustr,sizeof(mtustr),"%u",_mtu); + Utils::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); @@ -636,7 +636,7 @@ void OSXEthernetTap::setMtu(unsigned int mtu) long cpid = (long)vfork(); if (cpid == 0) { char tmp[64]; - Utils::snprintf(tmp,sizeof(tmp),"%u",mtu); + Utils::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) { diff --git a/osdep/PortMapper.cpp b/osdep/PortMapper.cpp index 99286172..df868e7a 100644 --- a/osdep/PortMapper.cpp +++ b/osdep/PortMapper.cpp @@ -205,7 +205,7 @@ public: memset(externalip,0,sizeof(externalip)); memset(&urls,0,sizeof(urls)); memset(&data,0,sizeof(data)); - Utils::snprintf(inport,sizeof(inport),"%d",localPort); + Utils::ztsnprintf(inport,sizeof(inport),"%d",localPort); if ((UPNP_GetValidIGD(devlist,&urls,&data,lanaddr,sizeof(lanaddr)))&&(lanaddr[0])) { #ifdef ZT_PORTMAPPER_TRACE @@ -220,7 +220,7 @@ public: int tryPort = (int)localPort + tries; if (tryPort >= 65535) tryPort = (tryPort - 65535) + 1025; - Utils::snprintf(outport,sizeof(outport),"%u",tryPort); + Utils::ztsnprintf(outport,sizeof(outport),"%u",tryPort); // First check and see if this port is already mapped to the // same unique name. If so, keep this mapping and don't try diff --git a/osdep/WindowsEthernetTap.cpp b/osdep/WindowsEthernetTap.cpp index c5d82d8e..b96ad791 100644 --- a/osdep/WindowsEthernetTap.cpp +++ b/osdep/WindowsEthernetTap.cpp @@ -484,7 +484,7 @@ WindowsEthernetTap::WindowsEthernetTap( char tag[24]; // We "tag" registry entries with the network ID to identify persistent devices - Utils::snprintf(tag,sizeof(tag),"%.16llx",(unsigned long long)nwid); + Utils::ztsnprintf(tag,sizeof(tag),"%.16llx",(unsigned long long)nwid); Mutex::Lock _l(_systemTapInitLock); @@ -601,10 +601,10 @@ WindowsEthernetTap::WindowsEthernetTap( if (_netCfgInstanceId.length() > 0) { char tmps[64]; - unsigned int tmpsl = Utils::snprintf(tmps,sizeof(tmps),"%.2X-%.2X-%.2X-%.2X-%.2X-%.2X",(unsigned int)mac[0],(unsigned int)mac[1],(unsigned int)mac[2],(unsigned int)mac[3],(unsigned int)mac[4],(unsigned int)mac[5]) + 1; + unsigned int tmpsl = Utils::ztsnprintf(tmps,sizeof(tmps),"%.2X-%.2X-%.2X-%.2X-%.2X-%.2X",(unsigned int)mac[0],(unsigned int)mac[1],(unsigned int)mac[2],(unsigned int)mac[3],(unsigned int)mac[4],(unsigned int)mac[5]) + 1; RegSetKeyValueA(nwAdapters,_mySubkeyName.c_str(),"NetworkAddress",REG_SZ,tmps,tmpsl); RegSetKeyValueA(nwAdapters,_mySubkeyName.c_str(),"MAC",REG_SZ,tmps,tmpsl); - tmpsl = Utils::snprintf(tmps, sizeof(tmps), "%d", mtu); + tmpsl = Utils::ztsnprintf(tmps, sizeof(tmps), "%d", mtu); RegSetKeyValueA(nwAdapters,_mySubkeyName.c_str(),"MTU",REG_SZ,tmps,tmpsl); DWORD tmp = 0; @@ -879,7 +879,7 @@ void WindowsEthernetTap::setMtu(unsigned int mtu) HKEY nwAdapters; if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}", 0, KEY_READ | KEY_WRITE, &nwAdapters) == ERROR_SUCCESS) { char tmps[64]; - unsigned int tmpsl = Utils::snprintf(tmps, sizeof(tmps), "%d", mtu); + unsigned int tmpsl = Utils::ztsnprintf(tmps, sizeof(tmps), "%d", mtu); RegSetKeyValueA(nwAdapters, _mySubkeyName.c_str(), "MTU", REG_SZ, tmps, tmpsl); RegCloseKey(nwAdapters); } @@ -902,7 +902,7 @@ void WindowsEthernetTap::threadMain() HANDLE wait4[3]; OVERLAPPED tapOvlRead,tapOvlWrite; - Utils::snprintf(tapPath,sizeof(tapPath),"\\\\.\\Global\\%s.tap",_netCfgInstanceId.c_str()); + Utils::ztsnprintf(tapPath,sizeof(tapPath),"\\\\.\\Global\\%s.tap",_netCfgInstanceId.c_str()); try { while (_run) { diff --git a/selftest.cpp b/selftest.cpp index 8175d708..ff171aa3 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -831,7 +831,7 @@ static int testOther() memset(key, 0, sizeof(key)); memset(value, 0, sizeof(value)); for(unsigned int q=0;q<32;++q) { - Utils::snprintf(key[q],16,"%.8lx",(unsigned long)(rand() % 1000) + (q * 1000)); + Utils::ztsnprintf(key[q],16,"%.8lx",(unsigned long)(rand() % 1000) + (q * 1000)); int r = rand() % 128; for(int x=0;x lines(OSUtils::split(cf.c_str(),"\r\n","","")); for(std::vector::iterator l(lines.begin());l!=lines.end();++l) { diff --git a/service/OneService.cpp b/service/OneService.cpp index 644454bc..993fb116 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -210,10 +210,10 @@ static void _networkToJson(nlohmann::json &nj,const ZT_VirtualNetworkConfig *nc, case ZT_NETWORK_TYPE_PUBLIC: ntype = "PUBLIC"; break; } - Utils::snprintf(tmp,sizeof(tmp),"%.16llx",nc->nwid); + Utils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",nc->nwid); nj["id"] = tmp; nj["nwid"] = tmp; - Utils::snprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)((nc->mac >> 40) & 0xff),(unsigned int)((nc->mac >> 32) & 0xff),(unsigned int)((nc->mac >> 24) & 0xff),(unsigned int)((nc->mac >> 16) & 0xff),(unsigned int)((nc->mac >> 8) & 0xff),(unsigned int)(nc->mac & 0xff)); + Utils::ztsnprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)((nc->mac >> 40) & 0xff),(unsigned int)((nc->mac >> 32) & 0xff),(unsigned int)((nc->mac >> 24) & 0xff),(unsigned int)((nc->mac >> 16) & 0xff),(unsigned int)((nc->mac >> 8) & 0xff),(unsigned int)(nc->mac & 0xff)); nj["mac"] = tmp; nj["name"] = nc->name; nj["status"] = nstatus; @@ -260,12 +260,12 @@ static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer) case ZT_PEER_ROLE_PLANET: prole = "PLANET"; break; } - Utils::snprintf(tmp,sizeof(tmp),"%.10llx",peer->address); + Utils::ztsnprintf(tmp,sizeof(tmp),"%.10llx",peer->address); pj["address"] = tmp; pj["versionMajor"] = peer->versionMajor; pj["versionMinor"] = peer->versionMinor; pj["versionRev"] = peer->versionRev; - Utils::snprintf(tmp,sizeof(tmp),"%d.%d.%d",peer->versionMajor,peer->versionMinor,peer->versionRev); + Utils::ztsnprintf(tmp,sizeof(tmp),"%d.%d.%d",peer->versionMajor,peer->versionMinor,peer->versionRev); pj["version"] = tmp; pj["latency"] = peer->latency; pj["role"] = prole; @@ -289,7 +289,7 @@ static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer) static void _moonToJson(nlohmann::json &mj,const World &world) { char tmp[64]; - Utils::snprintf(tmp,sizeof(tmp),"%.16llx",world.id()); + Utils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",world.id()); mj["id"] = tmp; mj["timestamp"] = world.timestamp(); mj["signature"] = Utils::hex(world.signature().data,(unsigned int)world.signature().size()); @@ -687,7 +687,7 @@ public: // Save primary port to a file so CLIs and GUIs can learn it easily char portstr[64]; - Utils::snprintf(portstr,sizeof(portstr),"%u",_ports[0]); + Utils::ztsnprintf(portstr,sizeof(portstr),"%u",_ports[0]); OSUtils::writeFile((_homePath + ZT_PATH_SEPARATOR_S "zerotier-one.port").c_str(),std::string(portstr)); // Attempt to bind to a secondary port chosen from our ZeroTier address. @@ -725,7 +725,7 @@ public: } if (_ports[2]) { char uniqueName[64]; - Utils::snprintf(uniqueName,sizeof(uniqueName),"ZeroTier/%.10llx@%u",_node->address(),_ports[2]); + Utils::ztsnprintf(uniqueName,sizeof(uniqueName),"ZeroTier/%.10llx@%u",_node->address(),_ports[2]); _portMapper = new PortMapper(_ports[2],uniqueName); } } @@ -1069,7 +1069,7 @@ public: n->second.settings = settings; char nlcpath[4096]; - Utils::snprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_networksPath.c_str(),nwid); + Utils::ztsnprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_networksPath.c_str(),nwid); FILE *out = fopen(nlcpath,"w"); if (out) { fprintf(out,"allowManaged=%d\n",(int)n->second.settings.allowManaged); @@ -1188,7 +1188,7 @@ public: ZT_NodeStatus status; _node->status(&status); - Utils::snprintf(tmp,sizeof(tmp),"%.10llx",status.address); + Utils::ztsnprintf(tmp,sizeof(tmp),"%.10llx",status.address); res["address"] = tmp; res["publicIdentity"] = status.publicIdentity; res["online"] = (bool)(status.online != 0); @@ -1197,7 +1197,7 @@ public: res["versionMinor"] = ZEROTIER_ONE_VERSION_MINOR; res["versionRev"] = ZEROTIER_ONE_VERSION_REVISION; res["versionBuild"] = ZEROTIER_ONE_VERSION_BUILD; - Utils::snprintf(tmp,sizeof(tmp),"%d.%d.%d",ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION); + Utils::ztsnprintf(tmp,sizeof(tmp),"%d.%d.%d",ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION); res["version"] = tmp; res["clock"] = OSUtils::now(); @@ -1373,7 +1373,7 @@ public: if ((scode != 200)&&(seed != 0)) { char tmp[64]; - Utils::snprintf(tmp,sizeof(tmp),"%.16llx",id); + Utils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",id); res["id"] = tmp; res["roots"] = json::array(); res["timestamp"] = 0; @@ -1617,7 +1617,7 @@ public: std::string h = controllerDbHttpHost; _controllerDbPath.append(h); char dbp[128]; - Utils::snprintf(dbp,sizeof(dbp),"%d",(int)controllerDbHttpPort); + Utils::ztsnprintf(dbp,sizeof(dbp),"%d",(int)controllerDbHttpPort); _controllerDbPath.push_back(':'); _controllerDbPath.append(dbp); if (controllerDbHttpPath.is_string()) { @@ -1711,7 +1711,7 @@ public: if (syncRoutes) { char tapdev[64]; #ifdef __WINDOWS__ - Utils::snprintf(tapdev,sizeof(tapdev),"%.16llx",(unsigned long long)n.tap->luid().Value); + Utils::ztsnprintf(tapdev,sizeof(tapdev),"%.16llx",(unsigned long long)n.tap->luid().Value); #else Utils::scopy(tapdev,sizeof(tapdev),n.tap->deviceName().c_str()); #endif @@ -1933,24 +1933,24 @@ public: bool secure = false; switch(type) { case ZT_STATE_OBJECT_IDENTITY_PUBLIC: - Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str()); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str()); break; case ZT_STATE_OBJECT_IDENTITY_SECRET: - Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str()); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str()); secure = true; break; case ZT_STATE_OBJECT_PEER_IDENTITY: - Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "iddb.d/%.10llx",_homePath.c_str(),(unsigned long long)id); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "iddb.d/%.10llx",_homePath.c_str(),(unsigned long long)id); break; case ZT_STATE_OBJECT_NETWORK_CONFIG: - Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id); secure = true; break; case ZT_STATE_OBJECT_PLANET: - Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); break; case ZT_STATE_OBJECT_MOON: - Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id); break; default: p[0] = (char)0; @@ -2022,7 +2022,7 @@ public: &_nextBackgroundTaskDeadline); if (ZT_ResultCode_isFatal(rc)) { char tmp[256]; - Utils::snprintf(tmp,sizeof(tmp),"fatal error code from processWirePacket: %d",(int)rc); + Utils::ztsnprintf(tmp,sizeof(tmp),"fatal error code from processWirePacket: %d",(int)rc); Mutex::Lock _l(_termReason_m); _termReason = ONE_UNRECOVERABLE_ERROR; _fatalErrorMessage = tmp; @@ -2235,7 +2235,7 @@ public: &_nextBackgroundTaskDeadline); if (ZT_ResultCode_isFatal(rc)) { char tmp[256]; - Utils::snprintf(tmp,sizeof(tmp),"fatal error code from processWirePacket: %d",(int)rc); + Utils::ztsnprintf(tmp,sizeof(tmp),"fatal error code from processWirePacket: %d",(int)rc); Mutex::Lock _l(_termReason_m); _termReason = ONE_UNRECOVERABLE_ERROR; _fatalErrorMessage = tmp; @@ -2402,7 +2402,7 @@ public: if (!n.tap) { try { char friendlyName[128]; - Utils::snprintf(friendlyName,sizeof(friendlyName),"ZeroTier One [%.16llx]",nwid); + Utils::ztsnprintf(friendlyName,sizeof(friendlyName),"ZeroTier One [%.16llx]",nwid); n.tap = new EthernetTap( _homePath.c_str(), @@ -2416,7 +2416,7 @@ public: *nuptr = (void *)&n; char nlcpath[256]; - Utils::snprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_homePath.c_str(),nwid); + Utils::ztsnprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_homePath.c_str(),nwid); std::string nlcbuf; if (OSUtils::readFile(nlcpath,nlcbuf)) { Dictionary<4096> nc; @@ -2502,7 +2502,7 @@ public: #endif if (op == ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY) { char nlcpath[256]; - Utils::snprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_homePath.c_str(),nwid); + Utils::ztsnprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_homePath.c_str(),nwid); OSUtils::rm(nlcpath); } } else { @@ -2554,22 +2554,22 @@ public: char p[4096]; switch(type) { case ZT_STATE_OBJECT_IDENTITY_PUBLIC: - Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str()); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str()); break; case ZT_STATE_OBJECT_IDENTITY_SECRET: - Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str()); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str()); break; case ZT_STATE_OBJECT_PEER_IDENTITY: - Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "iddb.d/%.10llx",_homePath.c_str(),(unsigned long long)id); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "iddb.d/%.10llx",_homePath.c_str(),(unsigned long long)id); break; case ZT_STATE_OBJECT_NETWORK_CONFIG: - Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id); break; case ZT_STATE_OBJECT_PLANET: - Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); break; case ZT_STATE_OBJECT_MOON: - Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id); break; default: return -1; @@ -2765,7 +2765,7 @@ public: default: scodestr = "Error"; break; } - Utils::snprintf(tmpn,sizeof(tmpn),"HTTP/1.1 %.3u %s\r\nCache-Control: no-cache\r\nPragma: no-cache\r\nContent-Type: %s\r\nContent-Length: %lu\r\nConnection: close\r\n\r\n", + Utils::ztsnprintf(tmpn,sizeof(tmpn),"HTTP/1.1 %.3u %s\r\nCache-Control: no-cache\r\nPragma: no-cache\r\nContent-Type: %s\r\nContent-Length: %lu\r\nConnection: close\r\n\r\n", scode, scodestr, contentType.c_str(), diff --git a/service/SoftwareUpdater.cpp b/service/SoftwareUpdater.cpp index d94beab5..e0519827 100644 --- a/service/SoftwareUpdater.cpp +++ b/service/SoftwareUpdater.cpp @@ -284,7 +284,7 @@ bool SoftwareUpdater::check(const uint64_t now) if ((now - _lastCheckTime) >= ZT_SOFTWARE_UPDATE_CHECK_PERIOD) { _lastCheckTime = now; char tmp[512]; - const unsigned int len = Utils::snprintf(tmp,sizeof(tmp), + const unsigned int len = Utils::ztsnprintf(tmp,sizeof(tmp), "%c{\"" ZT_SOFTWARE_UPDATE_JSON_VERSION_MAJOR "\":%d," "\"" ZT_SOFTWARE_UPDATE_JSON_VERSION_MINOR "\":%d," "\"" ZT_SOFTWARE_UPDATE_JSON_VERSION_REVISION "\":%d," -- cgit v1.2.3 From baa10c2995b7e0e49b49fe63a264a20982b817cf Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 30 Jun 2017 17:32:07 -0700 Subject: . --- include/ZeroTierOne.h | 8 +-- node/Constants.hpp | 2 +- node/IncomingPacket.cpp | 8 +-- node/Network.cpp | 14 +++-- node/Node.cpp | 24 ++++--- node/Node.hpp | 6 +- node/Path.hpp | 30 +++++++++ node/Peer.cpp | 164 ++++++++++++++++++++++++++++++++++++++++++------ node/Peer.hpp | 54 ++++++---------- node/Topology.cpp | 32 +++++++--- node/Topology.hpp | 2 +- service/OneService.cpp | 130 +++++++++++++++++++++----------------- 12 files changed, 326 insertions(+), 148 deletions(-) (limited to 'service/OneService.cpp') diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 9c295cee..40cae3b4 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -1115,14 +1115,14 @@ enum ZT_StateObjectType * Canonical path: /peers.d/
(10-digit hex address) * Persistence: optional, can be purged at any time */ - ZT_STATE_OBJECT_PEER = 3, + ZT_STATE_OBJECT_PEER_STATE = 3, /** * The identity of a known peer * * Object ID: peer address * Canonical path: /iddb.d/
(10-digit hex address) - * Persistence: optional, can be purged at any time, recommended ttl 30-60 days + * Persistence: recommended, can be purged at any time, recommended ttl 30-60 days */ ZT_STATE_OBJECT_PEER_IDENTITY = 4, @@ -1248,7 +1248,7 @@ typedef void (*ZT_StatePutFunction)( void *, /* User ptr */ void *, /* Thread ptr */ enum ZT_StateObjectType, /* State object type */ - uint64_t, /* State object ID (if applicable) */ + const uint64_t [2], /* State object ID (if applicable) */ const void *, /* State object data */ int); /* Length of data or -1 to delete */ @@ -1264,7 +1264,7 @@ typedef int (*ZT_StateGetFunction)( void *, /* User ptr */ void *, /* Thread ptr */ enum ZT_StateObjectType, /* State object type */ - uint64_t, /* State object ID (if applicable) */ + const uint64_t [2], /* State object ID (if applicable) */ void *, /* Buffer to store state object data */ unsigned int); /* Length of data buffer in bytes */ diff --git a/node/Constants.hpp b/node/Constants.hpp index fbbba76e..88549937 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -216,7 +216,7 @@ /** * How often Topology::clean() and Network::clean() and similar are called, in ms */ -#define ZT_HOUSEKEEPING_PERIOD 120000 +#define ZT_HOUSEKEEPING_PERIOD 10000 /** * How long to remember peer records in RAM if they haven't been used diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 1d55c9f3..4d99e87d 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -1211,8 +1211,8 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPt (!( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) == 0) && (peer->hasActivePathTo(now,a)) )) && // not already known (RR->node->shouldUsePathForZeroTierTraffic(tPtr,peer->address(),_path->localAddress(),a)) ) // should use path { - if ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) != 0) - peer->setClusterPreferred(a); + //if ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) != 0) + // peer->setClusterPreferred(a); if (++countPerScope[(int)a.ipScope()][0] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) { TRACE("attempting to contact %s at pushed direct path %s",peer->address().toString().c_str(),a.toString().c_str()); peer->attemptToContactAt(tPtr,InetAddress(),a,now,false,0); @@ -1228,8 +1228,8 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPt (!( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) == 0) && (peer->hasActivePathTo(now,a)) )) && // not already known (RR->node->shouldUsePathForZeroTierTraffic(tPtr,peer->address(),_path->localAddress(),a)) ) // should use path { - if ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) != 0) - peer->setClusterPreferred(a); + //if ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) != 0) + // peer->setClusterPreferred(a); if (++countPerScope[(int)a.ipScope()][1] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) { TRACE("attempting to contact %s at pushed direct path %s",peer->address().toString().c_str(),a.toString().c_str()); peer->attemptToContactAt(tPtr,InetAddress(),a,now,false,0); diff --git a/node/Network.cpp b/node/Network.cpp index 8c6f2ce8..0a16ded8 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -700,10 +700,13 @@ Network::Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,void *u this->setConfiguration(tPtr,*nconf,false); _lastConfigUpdate = 0; // still want to re-request since it's likely outdated } else { + uint64_t tmp[2]; + tmp[0] = nwid; tmp[1] = 0; + bool got = false; Dictionary *dict = new Dictionary(); try { - int n = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,nwid,dict->unsafeData(),ZT_NETWORKCONFIG_DICT_CAPACITY - 1); + int n = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,tmp,dict->unsafeData(),ZT_NETWORKCONFIG_DICT_CAPACITY - 1); if (n > 1) { NetworkConfig *nconf = new NetworkConfig(); try { @@ -719,7 +722,7 @@ Network::Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,void *u delete dict; if (!got) - RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,nwid,"\n",1); + RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,tmp,"\n",1); } if (!_portInitialized) { @@ -1185,8 +1188,11 @@ int Network::setConfiguration(void *tPtr,const NetworkConfig &nconf,bool saveToD if (saveToDisk) { Dictionary *d = new Dictionary(); try { - if (nconf.toDictionary(*d,false)) - RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,_id,d->data(),d->sizeBytes()); + if (nconf.toDictionary(*d,false)) { + uint64_t tmp[2]; + tmp[0] = _id; tmp[1] = 0; + RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,tmp,d->data(),d->sizeBytes()); + } } catch ( ... ) {} delete d; } diff --git a/node/Node.cpp b/node/Node.cpp index ab49e63b..1112c0f2 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -76,22 +76,26 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint6 memset(_expectingRepliesTo,0,sizeof(_expectingRepliesTo)); memset(_lastIdentityVerification,0,sizeof(_lastIdentityVerification)); + uint64_t idtmp[2]; + idtmp[0] = 0; idtmp[1] = 0; char tmp[512]; std::string tmp2; - int n = stateObjectGet(tptr,ZT_STATE_OBJECT_IDENTITY_SECRET,0,tmp,sizeof(tmp) - 1); + int n = stateObjectGet(tptr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp,tmp,sizeof(tmp) - 1); if (n > 0) { tmp[n] = (char)0; if (!RR->identity.fromString(tmp)) n = -1; } + + idtmp[0] = RR->identity.address().toInt(); idtmp[1] = 0; if (n <= 0) { RR->identity.generate(); tmp2 = RR->identity.toString(true); - stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_SECRET,RR->identity.address().toInt(),tmp2.data(),(unsigned int)tmp2.length()); + stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp,tmp2.data(),(unsigned int)tmp2.length()); tmp2 = RR->identity.toString(false); - stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,RR->identity.address().toInt(),tmp2.data(),(unsigned int)tmp2.length()); + stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,tmp2.data(),(unsigned int)tmp2.length()); } else { - n = stateObjectGet(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,RR->identity.address().toInt(),tmp,sizeof(tmp) - 1); + n = stateObjectGet(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,tmp,sizeof(tmp) - 1); if (n > 0) { tmp[n] = (char)0; if (RR->identity.toString(false) != tmp) @@ -99,7 +103,7 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint6 } if (n <= 0) { tmp2 = RR->identity.toString(false); - stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,RR->identity.address().toInt(),tmp2.data(),(unsigned int)tmp2.length()); + stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,tmp2.data(),(unsigned int)tmp2.length()); } } @@ -145,7 +149,7 @@ ZT_ResultCode Node::processStateUpdate( ZT_ResultCode r = ZT_RESULT_OK_IGNORED; switch(type) { - case ZT_STATE_OBJECT_PEER: + case ZT_STATE_OBJECT_PEER_STATE: if (len) { } break; @@ -380,9 +384,9 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,uint64_t now,volatile uint } if ((now - _lastHousekeepingRun) >= ZT_HOUSEKEEPING_PERIOD) { + _lastHousekeepingRun = now; try { - _lastHousekeepingRun = now; - RR->topology->clean(now); + RR->topology->doPeriodicTasks(tptr,now); RR->sa->clean(now); RR->mc->clean(now); } catch ( ... ) { @@ -443,7 +447,9 @@ ZT_ResultCode Node::leave(uint64_t nwid,void **uptr,void *tptr) _networks.erase(nwid); } - RR->node->stateObjectDelete(tptr,ZT_STATE_OBJECT_NETWORK_CONFIG,nwid); + uint64_t tmp[2]; + tmp[0] = nwid; tmp[1] = 0; + RR->node->stateObjectDelete(tptr,ZT_STATE_OBJECT_NETWORK_CONFIG,tmp); return ZT_RESULT_OK; } diff --git a/node/Node.hpp b/node/Node.hpp index f407c60c..f1209d00 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -197,9 +197,9 @@ public: inline bool online() const throw() { return _online; } - inline int stateObjectGet(void *const tPtr,ZT_StateObjectType type,const uint64_t id,void *const data,const unsigned int maxlen) { return _cb.stateGetFunction(reinterpret_cast(this),_uPtr,tPtr,type,id,data,maxlen); } - inline void stateObjectPut(void *const tPtr,ZT_StateObjectType type,const uint64_t id,const void *const data,const unsigned int len) { _cb.statePutFunction(reinterpret_cast(this),_uPtr,tPtr,type,id,data,(int)len); } - inline void stateObjectDelete(void *const tPtr,ZT_StateObjectType type,const uint64_t id) { _cb.statePutFunction(reinterpret_cast(this),_uPtr,tPtr,type,id,(const void *)0,-1); } + inline int stateObjectGet(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2],void *const data,const unsigned int maxlen) { return _cb.stateGetFunction(reinterpret_cast(this),_uPtr,tPtr,type,id,data,maxlen); } + inline void stateObjectPut(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2],const void *const data,const unsigned int len) { _cb.statePutFunction(reinterpret_cast(this),_uPtr,tPtr,type,id,data,(int)len); } + inline void stateObjectDelete(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2]) { _cb.statePutFunction(reinterpret_cast(this),_uPtr,tPtr,type,id,(const void *)0,-1); } #ifdef ZT_TRACE void postTrace(const char *module,unsigned int line,const char *fmt,...); diff --git a/node/Path.hpp b/node/Path.hpp index 32bceae0..74b31d8d 100644 --- a/node/Path.hpp +++ b/node/Path.hpp @@ -46,6 +46,11 @@ */ #define ZT_PATH_MAX_PREFERENCE_RANK ((ZT_INETADDRESS_MAX_SCOPE << 1) | 1) +/** + * Maximum distance for a path + */ +#define ZT_PATH_DISTANCE_MAX 0xffff + namespace ZeroTier { class RuntimeEnvironment; @@ -120,6 +125,7 @@ public: _incomingLinkQualitySlowLogCounter(-64), // discard first fast log _incomingLinkQualityPreviousPacketCounter(0), _outgoingPacketCounter(0), + _distance(ZT_PATH_DISTANCE_MAX), _addr(), _localAddress(), _ipScope(InetAddress::IP_SCOPE_NONE) @@ -137,6 +143,7 @@ public: _incomingLinkQualitySlowLogCounter(-64), // discard first fast log _incomingLinkQualityPreviousPacketCounter(0), _outgoingPacketCounter(0), + _distance(ZT_PATH_DISTANCE_MAX), _addr(addr), _localAddress(localAddress), _ipScope(addr.ipScope()) @@ -299,6 +306,28 @@ public: */ inline uint64_t lastIn() const { return _lastIn; } + /** + * @return Time last trust-established packet was received + */ + inline uint64_t lastTrustEstablishedPacketReceived() const { return _lastTrustEstablishedPacketReceived; } + + /** + * @return Distance (higher is further) + */ + inline unsigned int distance() const { return _distance; } + + /** + * @param lo Last out send + * @param li Last in send + * @param lt Last trust established packet received + */ + inline void updateFromRemoteState(const uint64_t lo,const uint64_t li,const uint64_t lt) + { + _lastOut = lo; + _lastIn = li; + _lastTrustEstablishedPacketReceived = lt; + } + /** * Return and increment outgoing packet counter (used with Packet::armor()) * @@ -315,6 +344,7 @@ private: volatile signed int _incomingLinkQualitySlowLogCounter; volatile unsigned int _incomingLinkQualityPreviousPacketCounter; volatile unsigned int _outgoingPacketCounter; + volatile unsigned int _distance; InetAddress _addr; InetAddress _localAddress; InetAddress::IpScope _ipScope; // memoize this since it's a computed value checked often diff --git a/node/Peer.cpp b/node/Peer.cpp index 84086048..a7466296 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -38,6 +38,8 @@ namespace ZeroTier { Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Identity &peerIdentity) : RR(renv), + _lastWroteState(0), + _lastReceivedStateTimestamp(0), _lastReceive(0), _lastNontrivialReceive(0), _lastTriedMemorizedPath(0), @@ -75,6 +77,7 @@ void Peer::received( { const uint64_t now = RR->node->now(); +/* #ifdef ZT_ENABLE_CLUSTER bool isClusterSuboptimalPath = false; if ((RR->cluster)&&(hops == 0)) { @@ -120,6 +123,7 @@ void Peer::received( } } #endif +*/ _lastReceive = now; switch (verb) { @@ -143,6 +147,8 @@ void Peer::received( if (hops == 0) { bool pathAlreadyKnown = false; + bool newPathLearned = false; + { Mutex::Lock _l(_paths_m); if ((path->address().ss_family == AF_INET)&&(_v4Path.p)) { @@ -152,9 +158,6 @@ void Peer::received( const struct sockaddr_in *const ll = reinterpret_cast(&(_v4Path.p->localAddress())); if ((r->sin_addr.s_addr == l->sin_addr.s_addr)&&(r->sin_port == l->sin_port)&&(rl->sin_addr.s_addr == ll->sin_addr.s_addr)&&(rl->sin_port == ll->sin_port)) { _v4Path.lr = now; -#ifdef ZT_ENABLE_CLUSTER - _v4Path.localClusterSuboptimal = isClusterSuboptimalPath; -#endif pathAlreadyKnown = true; } } else if ((path->address().ss_family == AF_INET6)&&(_v6Path.p)) { @@ -164,9 +167,6 @@ void Peer::received( const struct sockaddr_in6 *const ll = reinterpret_cast(&(_v6Path.p->localAddress())); if ((!memcmp(r->sin6_addr.s6_addr,l->sin6_addr.s6_addr,16))&&(r->sin6_port == l->sin6_port)&&(!memcmp(rl->sin6_addr.s6_addr,ll->sin6_addr.s6_addr,16))&&(rl->sin6_port == ll->sin6_port)) { _v6Path.lr = now; -#ifdef ZT_ENABLE_CLUSTER - _v6Path.localClusterSuboptimal = isClusterSuboptimalPath; -#endif pathAlreadyKnown = true; } } @@ -176,11 +176,11 @@ void Peer::received( Mutex::Lock _l(_paths_m); _PeerPath *potentialNewPeerPath = (_PeerPath *)0; if (path->address().ss_family == AF_INET) { - if ( (!_v4Path.p) || (!_v4Path.p->alive(now)) || ((_v4Path.p->address() != _v4ClusterPreferred)&&(path->preferenceRank() >= _v4Path.p->preferenceRank())) ) { + if ( (!_v4Path.p) || (!_v4Path.p->alive(now)) || (path->preferenceRank() >= _v4Path.p->preferenceRank()) ) { potentialNewPeerPath = &_v4Path; } } else if (path->address().ss_family == AF_INET6) { - if ( (!_v6Path.p) || (!_v6Path.p->alive(now)) || ((_v6Path.p->address() != _v6ClusterPreferred)&&(path->preferenceRank() >= _v6Path.p->preferenceRank())) ) { + if ( (!_v6Path.p) || (!_v6Path.p->alive(now)) || (path->preferenceRank() >= _v6Path.p->preferenceRank()) ) { potentialNewPeerPath = &_v6Path; } } @@ -188,11 +188,7 @@ void Peer::received( if (verb == Packet::VERB_OK) { potentialNewPeerPath->lr = now; potentialNewPeerPath->p = path; -#ifdef ZT_ENABLE_CLUSTER - potentialNewPeerPath->localClusterSuboptimal = isClusterSuboptimalPath; - if (RR->cluster) - RR->cluster->broadcastHavePeer(_id); -#endif + newPathLearned = true; } else { TRACE("got %s via unknown path %s(%s), confirming...",Packet::verbString(verb),_id.address().toString().c_str(),path->address().toString().c_str()); attemptToContactAt(tPtr,path->localAddress(),path->address(),now,true,path->nextOutgoingCounter()); @@ -200,15 +196,12 @@ void Peer::received( } } } + + if (newPathLearned) + writeState(tPtr,now); } else if (this->trustEstablished(now)) { // Send PUSH_DIRECT_PATHS if hops>0 (relayed) and we have a trust relationship (common network membership) -#ifdef ZT_ENABLE_CLUSTER - // Cluster mode disables normal PUSH_DIRECT_PATHS in favor of cluster-based peer redirection - const bool haveCluster = (RR->cluster); -#else - const bool haveCluster = false; -#endif - if ( ((now - _lastDirectPathPushSent) >= ZT_DIRECT_PATH_PUSH_INTERVAL) && (!haveCluster) ) { + if ((now - _lastDirectPathPushSent) >= ZT_DIRECT_PATH_PUSH_INTERVAL) { _lastDirectPathPushSent = now; std::vector pathsToPush; @@ -439,4 +432,135 @@ bool Peer::doPingAndKeepalive(void *tPtr,uint64_t now,int inetAddressFamily) return false; } +void Peer::writeState(void *tPtr,const uint64_t now) +{ + try { + Buffer b; + + b.append((uint8_t)1); // version + b.append(now); + + _id.serialize(b); + + { + Mutex::Lock _l(_paths_m); + unsigned int count = 0; + if (_v4Path.lr) + ++count; + if (_v6Path.lr) + ++count; + b.append((uint8_t)count); + if (_v4Path.lr) { + b.append(_v4Path.lr); + b.append(_v4Path.p->lastOut()); + b.append(_v4Path.p->lastIn()); + b.append(_v4Path.p->lastTrustEstablishedPacketReceived()); + b.append((uint16_t)_v4Path.p->distance()); + _v4Path.p->address().serialize(b); + _v4Path.p->localAddress().serialize(b); + } + if (_v6Path.lr) { + b.append(_v6Path.lr); + b.append(_v6Path.p->lastOut()); + b.append(_v6Path.p->lastIn()); + b.append(_v6Path.p->lastTrustEstablishedPacketReceived()); + b.append((uint16_t)_v6Path.p->distance()); + _v6Path.p->address().serialize(b); + _v6Path.p->localAddress().serialize(b); + } + } + + b.append(_lastReceive); + b.append(_lastNontrivialReceive); + b.append(_lastTriedMemorizedPath); + b.append(_lastDirectPathPushSent); + b.append(_lastDirectPathPushReceive); + b.append(_lastCredentialRequestSent); + b.append(_lastWhoisRequestReceived); + b.append(_lastEchoRequestReceived); + b.append(_lastComRequestReceived); + b.append(_lastComRequestSent); + b.append(_lastCredentialsReceived); + b.append(_lastTrustEstablishedPacketReceived); + + b.append(_vProto); + b.append(_vMajor); + b.append(_vMinor); + b.append(_vRevision); + + b.append((uint16_t)0); // length of additional fields + + uint64_t tmp[2]; + tmp[0] = _id.address().toInt(); tmp[1] = 0; + RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_PEER_STATE,tmp,b.data(),b.size()); + + _lastWroteState = now; + } catch ( ... ) {} // sanity check, should not be possible +} + +bool Peer::applyStateUpdate(const void *data,unsigned int len) +{ + try { + Buffer b(data,len); + unsigned int ptr = 0; + + if (b[ptr++] != 1) + return false; + const uint64_t ts = b.at(ptr); ptr += 8; + if (ts <= _lastReceivedStateTimestamp) + return false; + + const unsigned int pathCount = (unsigned int)b[ptr++]; + { + Mutex::Lock _l(_paths_m); + for(unsigned int i=0;i(ptr); ptr += 8; + const uint64_t lastOut = b.at(ptr); ptr += 8; + const uint64_t lastIn = b.at(ptr); ptr += 8; + const uint64_t lastTrustEstablishedPacketReceived = b.at(ptr); ptr += 8; + const unsigned int distance = b.at(ptr); ptr += 2; + InetAddress addr,localAddr; + ptr += addr.deserialize(b,ptr); + ptr += localAddr.deserialize(b,ptr); + if (addr.ss_family == localAddr.ss_family) { + _PeerPath *p = (_PeerPath *)0; + switch(addr.ss_family) { + case AF_INET: p = &_v4Path; break; + case AF_INET6: p = &_v6Path; break; + } + if (p) { + if ( ((p->p->address() != addr)||(p->p->localAddress() != localAddr)) && (p->p->distance() > distance) ) + p->p = RR->topology->getPath(localAddr,addr); + p->lr = lr; + p->p->updateFromRemoteState(lastOut,lastIn,lastTrustEstablishedPacketReceived); + } + } + } + } + + _lastReceive = std::max(_lastReceive,b.at(ptr)); ptr += 8; + _lastNontrivialReceive = std::max(_lastNontrivialReceive,b.at(ptr)); ptr += 8; + _lastTriedMemorizedPath = std::max(_lastTriedMemorizedPath,b.at(ptr)); ptr += 8; + _lastDirectPathPushSent = std::max(_lastDirectPathPushSent,b.at(ptr)); ptr += 8; + _lastDirectPathPushReceive = std::max(_lastDirectPathPushReceive,b.at(ptr)); ptr += 8; + _lastCredentialRequestSent = std::max(_lastCredentialRequestSent,b.at(ptr)); ptr += 8; + _lastWhoisRequestReceived = std::max(_lastWhoisRequestReceived,b.at(ptr)); ptr += 8; + _lastEchoRequestReceived = std::max(_lastEchoRequestReceived,b.at(ptr)); ptr += 8; + _lastComRequestReceived = std::max(_lastComRequestReceived,b.at(ptr)); ptr += 8; + _lastComRequestSent = std::max(_lastComRequestSent,b.at(ptr)); ptr += 8; + _lastCredentialsReceived = std::max(_lastCredentialsReceived,b.at(ptr)); ptr += 8; + _lastTrustEstablishedPacketReceived = std::max(_lastTrustEstablishedPacketReceived,b.at(ptr)); ptr += 8; + + _vProto = b.at(ptr); ptr += 2; + _vMajor = b.at(ptr); ptr += 2; + _vMinor = b.at(ptr); ptr += 2; + _vRevision = b.at(ptr); ptr += 2; + + _lastReceivedStateTimestamp = ts; + + return true; + } catch ( ... ) {} // ignore invalid state updates + return false; +} + } // namespace ZeroTier diff --git a/node/Peer.hpp b/node/Peer.hpp index 9b57f23e..d6b7dad9 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -193,6 +193,22 @@ public: */ bool doPingAndKeepalive(void *tPtr,uint64_t now,int inetAddressFamily); + /** + * Write current peer state to external storage / cluster network + * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call + */ + void writeState(void *tPtr,const uint64_t now); + + /** + * Apply a state update received from e.g. a remote cluster member + * + * @param data State update data + * @param len Length of state update + * @return True if state update was applied, false if ignored or invalid + */ + bool applyStateUpdate(const void *data,unsigned int len); + /** * Reset paths within a given IP scope and address family * @@ -218,19 +234,6 @@ public: } } - /** - * Indicate that the given address was provided by a cluster as a preferred destination - * - * @param addr Address cluster prefers that we use - */ - inline void setClusterPreferred(const InetAddress &addr) - { - if (addr.ss_family == AF_INET) - _v4ClusterPreferred = addr; - else if (addr.ss_family == AF_INET6) - _v6ClusterPreferred = addr; - } - /** * Fill parameters with V4 and V6 addresses if known and alive * @@ -317,18 +320,6 @@ public: else _latency = std::min(l,(unsigned int)65535); } -#ifdef ZT_ENABLE_CLUSTER - /** - * @param now Current time - * @return True if this peer has at least one active direct path that is not cluster-suboptimal - */ - inline bool hasLocalClusterOptimalPath(uint64_t now) const - { - Mutex::Lock _l(_paths_m); - return ( ((_v4Path.p)&&(_v4Path.p->alive(now))&&(!_v4Path.localClusterSuboptimal)) || ((_v6Path.p)&&(_v6Path.p->alive(now))&&(!_v6Path.localClusterSuboptimal)) ); - } -#endif - /** * @return 256-bit secret symmetric encryption key */ @@ -449,22 +440,18 @@ public: private: struct _PeerPath { -#ifdef ZT_ENABLE_CLUSTER - _PeerPath() : lr(0),p(),localClusterSuboptimal(false) {} -#else _PeerPath() : lr(0),p() {} -#endif uint64_t lr; // time of last valid ZeroTier packet SharedPtr p; -#ifdef ZT_ENABLE_CLUSTER - bool localClusterSuboptimal; // true if our cluster has determined that we should not be serving this peer -#endif }; uint8_t _key[ZT_PEER_SECRET_KEY_LENGTH]; const RuntimeEnvironment *RR; + uint64_t _lastWroteState; + uint64_t _lastReceivedStateTimestamp; + uint64_t _lastReceive; // direct or indirect uint64_t _lastNontrivialReceive; // frames, things like netconf, etc. uint64_t _lastTriedMemorizedPath; @@ -483,9 +470,6 @@ private: uint16_t _vMinor; uint16_t _vRevision; - InetAddress _v4ClusterPreferred; - InetAddress _v6ClusterPreferred; - _PeerPath _v4Path; // IPv4 direct path _PeerPath _v6Path; // IPv6 direct path Mutex _paths_m; diff --git a/node/Topology.cpp b/node/Topology.cpp index d4b424ff..be116b28 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -69,7 +69,9 @@ Topology::Topology(const RuntimeEnvironment *renv,void *tPtr) : _amRoot(false) { uint8_t tmp[ZT_WORLD_MAX_SERIALIZED_LENGTH]; - int n = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_PLANET,0,tmp,sizeof(tmp)); + uint64_t idtmp[2]; + idtmp[0] = 0; idtmp[1] = 0; + int n = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_PLANET,idtmp,tmp,sizeof(tmp)); if (n > 0) { try { World cachedPlanet; @@ -159,7 +161,9 @@ void Topology::saveIdentity(void *tPtr,const Identity &id) { if (id) { const std::string tmp(id.toString(false)); - RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_PEER_IDENTITY,id.address().toInt(),tmp.data(),(unsigned int)tmp.length()); + uint64_t idtmp[2]; + idtmp[0] = id.address().toInt(); idtmp[1] = 0; + RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_PEER_IDENTITY,idtmp,tmp.data(),(unsigned int)tmp.length()); } } @@ -329,7 +333,9 @@ bool Topology::addWorld(void *tPtr,const World &newWorld,bool alwaysAcceptNew) try { Buffer sbuf; existing->serialize(sbuf,false); - RR->node->stateObjectPut(tPtr,(existing->type() == World::TYPE_PLANET) ? ZT_STATE_OBJECT_PLANET : ZT_STATE_OBJECT_MOON,existing->id(),sbuf.data(),sbuf.size()); + uint64_t idtmp[2]; + idtmp[0] = existing->id(); idtmp[1] = 0; + RR->node->stateObjectPut(tPtr,(existing->type() == World::TYPE_PLANET) ? ZT_STATE_OBJECT_PLANET : ZT_STATE_OBJECT_MOON,idtmp,sbuf.data(),sbuf.size()); } catch ( ... ) {} _memoizeUpstreams(tPtr); @@ -340,7 +346,9 @@ bool Topology::addWorld(void *tPtr,const World &newWorld,bool alwaysAcceptNew) void Topology::addMoon(void *tPtr,const uint64_t id,const Address &seed) { char tmp[ZT_WORLD_MAX_SERIALIZED_LENGTH]; - int n = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_MOON,id,tmp,sizeof(tmp)); + uint64_t idtmp[2]; + idtmp[0] = id; idtmp[1] = 0; + int n = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_MOON,idtmp,tmp,sizeof(tmp)); if (n > 0) { try { World w; @@ -369,7 +377,9 @@ void Topology::removeMoon(void *tPtr,const uint64_t id) if (m->id() != id) { nm.push_back(*m); } else { - RR->node->stateObjectDelete(tPtr,ZT_STATE_OBJECT_MOON,id); + uint64_t idtmp[2]; + idtmp[0] = id; idtmp[1] = 0; + RR->node->stateObjectDelete(tPtr,ZT_STATE_OBJECT_MOON,idtmp); } } _moons.swap(nm); @@ -384,7 +394,7 @@ void Topology::removeMoon(void *tPtr,const uint64_t id) _memoizeUpstreams(tPtr); } -void Topology::clean(uint64_t now) +void Topology::doPeriodicTasks(void *tPtr,uint64_t now) { { Mutex::Lock _l1(_peers_m); @@ -393,10 +403,14 @@ void Topology::clean(uint64_t now) Address *a = (Address *)0; SharedPtr *p = (SharedPtr *)0; while (i.next(a,p)) { - if ( (!(*p)->isAlive(now)) && (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),*a) == _upstreamAddresses.end()) ) + if ( (!(*p)->isAlive(now)) && (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),*a) == _upstreamAddresses.end()) ) { _peers.erase(*a); + } else { + (*p)->writeState(tPtr,now); + } } } + { Mutex::Lock _l(_paths_m); Hashtable< Path::HashKey,SharedPtr >::Iterator i(_paths); @@ -412,7 +426,9 @@ void Topology::clean(uint64_t now) Identity Topology::_getIdentity(void *tPtr,const Address &zta) { char tmp[512]; - int n = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_PEER_IDENTITY,zta.toInt(),tmp,sizeof(tmp) - 1); + uint64_t idtmp[2]; + idtmp[0] = zta.toInt(); idtmp[1] = 0; + int n = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_PEER_IDENTITY,idtmp,tmp,sizeof(tmp) - 1); if (n > 0) { tmp[n] = (char)0; try { diff --git a/node/Topology.hpp b/node/Topology.hpp index d06ba94b..9bc7c0d8 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -308,7 +308,7 @@ public: /** * Clean and flush database */ - void clean(uint64_t now); + void doPeriodicTasks(void *tPtr,uint64_t now); /** * @param now Current time diff --git a/service/OneService.cpp b/service/OneService.cpp index 993fb116..f949f348 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -312,8 +312,8 @@ class OneServiceImpl; static int SnodeVirtualNetworkConfigFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t nwid,void **nuptr,enum ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nwconf); static void SnodeEventCallback(ZT_Node *node,void *uptr,void *tptr,enum ZT_Event event,const void *metaData); -static void SnodeStatePutFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,uint64_t id,const void *data,int len); -static int SnodeStateGetFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,uint64_t id,void *data,unsigned int maxlen); +static void SnodeStatePutFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,const uint64_t id[2],const void *data,int len); +static int SnodeStateGetFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,const uint64_t id[2],void *data,unsigned int maxlen); static int SnodeWirePacketSendFunction(ZT_Node *node,void *uptr,void *tptr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl); static void SnodeVirtualNetworkFrameFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t nwid,void **nuptr,uint64_t sourceMac,uint64_t destMac,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len); static int SnodePathCheckFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t ztaddr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *remoteAddr); @@ -1220,34 +1220,20 @@ public: res["planetWorldId"] = planet.id(); res["planetWorldTimestamp"] = planet.timestamp(); -/* -#ifdef ZT_ENABLE_CLUSTER - json cj; - ZT_ClusterStatus cs; - _node->clusterStatus(&cs); - if (cs.clusterSize >= 1) { - json cja = json::array(); - for(unsigned int i=0;i::const_iterator ca(_clusterBackplaneAddresses.begin());ca!=_clusterBackplaneAddresses.end();++ca) { + uint64_t up = 0; + for(std::vector::const_iterator c(_tcpConnections.begin());c!=_tcpConnections.end();++c) { + if (((*c)->remoteAddr == *ca)&&((*c)->clusterMemberId)&&((*c)->lastReceive > up)) + up = (*c)->lastReceive; + } + cj[ca->toString()] = up; } - cj["members"] = cja; - cj["myId"] = (int)cs.myId; - cj["clusterSize"] = cs.clusterSize; + res["cluster"] = cj; } - res["cluster"] = cj; -#else - res["cluster"] = json(); -#endif -*/ scode = 200; } else if (ps[0] == "moon") { @@ -1877,16 +1863,15 @@ public: return false; } - void replicateStateObject(const ZT_StateObjectType type,const uint64_t id,const void *const data,const unsigned int len,TcpConnection *tc) + void replicateStateObject(const ZT_StateObjectType type,const uint64_t id[2],const void *const data,const unsigned int len,TcpConnection *tc) { - char buf[34]; - + char buf[42]; Mutex::Lock _l2(tc->writeq_m); if (tc->writeq.length() == 0) _phy.setNotifyWritable(tc->sock,true); - const unsigned int mlen = len + 34; + const unsigned int mlen = len + 42; tc->writeq.push_back((char)((mlen >> 16) & 0xff)); tc->writeq.push_back((char)((mlen >> 8) & 0xff)); @@ -1895,24 +1880,32 @@ public: Utils::getSecureRandom(buf,16); buf[24] = (char)CLUSTER_MESSAGE_STATE_OBJECT; buf[25] = (char)type; - buf[26] = (char)((id >> 56) & 0xff); - buf[27] = (char)((id >> 48) & 0xff); - buf[28] = (char)((id >> 40) & 0xff); - buf[29] = (char)((id >> 32) & 0xff); - buf[30] = (char)((id >> 24) & 0xff); - buf[31] = (char)((id >> 16) & 0xff); - buf[32] = (char)((id >> 8) & 0xff); - buf[33] = (char)(id & 0xff); + buf[26] = (char)((id[0] >> 56) & 0xff); + buf[27] = (char)((id[0] >> 48) & 0xff); + buf[28] = (char)((id[0] >> 40) & 0xff); + buf[29] = (char)((id[0] >> 32) & 0xff); + buf[30] = (char)((id[0] >> 24) & 0xff); + buf[31] = (char)((id[0] >> 16) & 0xff); + buf[32] = (char)((id[0] >> 8) & 0xff); + buf[33] = (char)(id[0] & 0xff); + buf[34] = (char)((id[1] >> 56) & 0xff); + buf[35] = (char)((id[1] >> 48) & 0xff); + buf[36] = (char)((id[1] >> 40) & 0xff); + buf[37] = (char)((id[1] >> 32) & 0xff); + buf[38] = (char)((id[1] >> 24) & 0xff); + buf[39] = (char)((id[1] >> 16) & 0xff); + buf[40] = (char)((id[1] >> 8) & 0xff); + buf[41] = (char)(id[1] & 0xff); const unsigned long startpos = (unsigned long)tc->writeq.length(); - tc->writeq.append(buf,34); + tc->writeq.append(buf,42); tc->writeq.append(reinterpret_cast(data),len); char *const outdata = const_cast(tc->writeq.data()) + startpos; encryptClusterMessage(outdata,mlen); } - void replicateStateObjectToCluster(const ZT_StateObjectType type,const uint64_t id,const void *const data,const unsigned int len,const uint64_t everyoneBut) + void replicateStateObjectToCluster(const ZT_StateObjectType type,const uint64_t id[2],const void *const data,const unsigned int len,const uint64_t everyoneBut) { std::vector sentTo; if (everyoneBut) @@ -1927,7 +1920,7 @@ public: } } - void writeStateObject(enum ZT_StateObjectType type,uint64_t id,const void *data,int len) + void writeStateObject(enum ZT_StateObjectType type,const uint64_t id[2],const void *data,int len) { char p[4096]; bool secure = false; @@ -1940,17 +1933,17 @@ public: secure = true; break; case ZT_STATE_OBJECT_PEER_IDENTITY: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "iddb.d/%.10llx",_homePath.c_str(),(unsigned long long)id); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "iddb.d/%.10llx",_homePath.c_str(),(unsigned long long)id[0]); break; case ZT_STATE_OBJECT_NETWORK_CONFIG: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id[0]); secure = true; break; case ZT_STATE_OBJECT_PLANET: Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); break; case ZT_STATE_OBJECT_MOON: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id); + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id[0]); break; default: p[0] = (char)0; @@ -1985,8 +1978,12 @@ public: if (OSUtils::readFile((_homePath + ZT_PATH_SEPARATOR_S + *f).c_str(),buf)) { if (f->length() == 21) { const uint64_t nwid = Utils::hexStrToU64(f->substr(0,16).c_str()); - if (nwid) - replicateStateObject(ZT_STATE_OBJECT_NETWORK_CONFIG,nwid,buf.data(),(int)buf.length(),tc); + if (nwid) { + uint64_t tmp[2]; + tmp[0] = nwid; + tmp[1] = 0; + replicateStateObject(ZT_STATE_OBJECT_NETWORK_CONFIG,tmp,buf.data(),(int)buf.length(),tc); + } } } } @@ -1996,8 +1993,12 @@ public: if (OSUtils::readFile((_homePath + ZT_PATH_SEPARATOR_S + *f).c_str(),buf)) { if (f->length() == 21) { const uint64_t moonId = Utils::hexStrToU64(f->substr(0,16).c_str()); - if (moonId) - replicateStateObject(ZT_STATE_OBJECT_MOON,moonId,buf.data(),(int)buf.length(),tc); + if (moonId) { + uint64_t tmp[2]; + tmp[0] = moonId; + tmp[1] = 0; + replicateStateObject(ZT_STATE_OBJECT_MOON,tmp,buf.data(),(int)buf.length(),tc); + } } } } @@ -2313,8 +2314,9 @@ public: break; case CLUSTER_MESSAGE_STATE_OBJECT: - if (mlen >= (25 + 9)) { // type + object ID + [data] - const uint64_t objId = ( + if (mlen >= 42) { // type + object ID + [data] + uint64_t objId[2]; + objId[0] = ( ((uint64_t)data[26] << 56) | ((uint64_t)data[27] << 48) | ((uint64_t)data[28] << 40) | @@ -2324,9 +2326,19 @@ public: ((uint64_t)data[32] << 8) | (uint64_t)data[33] ); - if (_node->processStateUpdate((void *)0,(ZT_StateObjectType)data[25],objId,data + 34,(unsigned int)(mlen - 34)) == ZT_RESULT_OK) { - writeStateObject((ZT_StateObjectType)data[25],objId,data + 34,(unsigned int)(mlen - 34)); - replicateStateObjectToCluster((ZT_StateObjectType)data[25],objId,data + 34,(unsigned int)(mlen - 34),tc->clusterMemberId); + objId[1] = ( + ((uint64_t)data[34] << 56) | + ((uint64_t)data[35] << 48) | + ((uint64_t)data[36] << 40) | + ((uint64_t)data[37] << 32) | + ((uint64_t)data[38] << 24) | + ((uint64_t)data[39] << 16) | + ((uint64_t)data[40] << 8) | + (uint64_t)data[41] + ); + if (_node->processStateUpdate((void *)0,(ZT_StateObjectType)data[25],objId[0],data + 42,(unsigned int)(mlen - 42)) == ZT_RESULT_OK) { + writeStateObject((ZT_StateObjectType)data[25],objId,data + 42,(unsigned int)(mlen - 42)); + replicateStateObjectToCluster((ZT_StateObjectType)data[25],objId,data + 42,(unsigned int)(mlen - 42),tc->clusterMemberId); } } break; @@ -2543,13 +2555,13 @@ public: } } - inline void nodeStatePutFunction(enum ZT_StateObjectType type,uint64_t id,const void *data,int len) + inline void nodeStatePutFunction(enum ZT_StateObjectType type,const uint64_t id[2],const void *data,int len) { writeStateObject(type,id,data,len); replicateStateObjectToCluster(type,id,data,len,0); } - inline int nodeStateGetFunction(enum ZT_StateObjectType type,uint64_t id,void *data,unsigned int maxlen) + inline int nodeStateGetFunction(enum ZT_StateObjectType type,const uint64_t id[2],void *data,unsigned int maxlen) { char p[4096]; switch(type) { @@ -2866,9 +2878,9 @@ static int SnodeVirtualNetworkConfigFunction(ZT_Node *node,void *uptr,void *tptr { return reinterpret_cast(uptr)->nodeVirtualNetworkConfigFunction(nwid,nuptr,op,nwconf); } static void SnodeEventCallback(ZT_Node *node,void *uptr,void *tptr,enum ZT_Event event,const void *metaData) { reinterpret_cast(uptr)->nodeEventCallback(event,metaData); } -static void SnodeStatePutFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,uint64_t id,const void *data,int len) +static void SnodeStatePutFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,const uint64_t id[2],const void *data,int len) { reinterpret_cast(uptr)->nodeStatePutFunction(type,id,data,len); } -static int SnodeStateGetFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,uint64_t id,void *data,unsigned int maxlen) +static int SnodeStateGetFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,const uint64_t id[2],void *data,unsigned int maxlen) { return reinterpret_cast(uptr)->nodeStateGetFunction(type,id,data,maxlen); } static int SnodeWirePacketSendFunction(ZT_Node *node,void *uptr,void *tptr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl) { return reinterpret_cast(uptr)->nodeWirePacketSendFunction(localAddr,addr,data,len,ttl); } -- cgit v1.2.3 From 2f20258807f8665bc3f9c527106e61761e01ecc3 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 6 Jul 2017 10:25:36 -0700 Subject: . --- include/ZeroTierOne.h | 34 +++++----- node/Constants.hpp | 12 ++-- node/Identity.hpp | 5 +- node/IncomingPacket.cpp | 12 ---- node/Network.cpp | 10 --- node/Node.cpp | 151 +++++++++++--------------------------------- node/Node.hpp | 2 +- node/Path.hpp | 13 ---- node/Peer.cpp | 113 ++++++++++++++++++++------------- node/Peer.hpp | 16 ++++- node/RuntimeEnvironment.hpp | 19 ++++-- node/Switch.cpp | 93 ++------------------------- node/Topology.cpp | 59 +++++------------ node/Topology.hpp | 27 ++------ osdep/Binder.hpp | 4 +- service/OneService.cpp | 94 +++++++++++++-------------- 16 files changed, 240 insertions(+), 424 deletions(-) (limited to 'service/OneService.cpp') diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 40cae3b4..133ae340 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -1072,9 +1072,9 @@ typedef struct * identity of a node and its address, the identity (public and secret) * must be saved at a minimum. * - * The reference service implementation currently persists identity, - * peer identities (for a period of time), planet, moons, and network - * configurations. Other state is treated as ephemeral. + * State objects actually have two IDs (uint64_t[2]). If only one is + * listed the second ([1]) should be zero and is ignored in storage + * and replication. * * All state objects should be replicated in cluster mode. The reference * clustering implementation uses a rumor mill algorithm in which state @@ -1118,22 +1118,25 @@ enum ZT_StateObjectType ZT_STATE_OBJECT_PEER_STATE = 3, /** - * The identity of a known peer + * Network configuration * * Object ID: peer address - * Canonical path: /iddb.d/
(10-digit hex address) - * Persistence: recommended, can be purged at any time, recommended ttl 30-60 days + * Canonical path: /networks.d/.conf (16-digit hex ID) + * Persistence: required if network memberships should persist */ - ZT_STATE_OBJECT_PEER_IDENTITY = 4, + ZT_STATE_OBJECT_NETWORK_CONFIG = 4, /** - * Network configuration + * Network membership (network X peer intersection) * - * Object ID: peer address - * Canonical path: /networks.d/.conf (16-digit hex ID) - * Persistence: required if network memberships should persist + * If these are persisted they must be restored after peer states and + * network configs. Otherwise they are ignored. + * + * Object ID: [0] network ID, [1] peer address + * Canonical path: /networks.d//members.d/
+ * Persistence: optional (not usually needed) */ - ZT_STATE_OBJECT_NETWORK_CONFIG = 5, + ZT_STATE_OBJECT_NETWORK_MEMBERSHIP = 5, /** * The planet (there is only one per... well... planet!) @@ -1450,7 +1453,8 @@ void ZT_Node_delete(ZT_Node *node); * * Unless clustering is being implemented this function doesn't need to be * used after startup. It could be called in response to filesystem changes - * to allow some degree of live configurability by filesystem observation. + * to allow some degree of live configurability by filesystem observation + * but this kind of thing is entirely optional. * * The return value of this function indicates whether the update was accepted * as new. A return value of ZT_RESULT_OK indicates that the node gleaned new @@ -1468,7 +1472,7 @@ void ZT_Node_delete(ZT_Node *node); * @param node Node instance * @param tptr Thread pointer to pass to functions/callbacks resulting from this call * @param type State object type - * @param id State object ID + * @param id State object ID (if object type has only one ID, second should be zero) * @param data State object data * @param len Length of state object data in bytes * @return ZT_RESULT_OK if object was accepted or ZT_RESULT_OK_IGNORED if non-informative, error if object was invalid @@ -1477,7 +1481,7 @@ enum ZT_ResultCode ZT_Node_processStateUpdate( ZT_Node *node, void *tptr, ZT_StateObjectType type, - uint64_t id, + const uint64_t id[2], const void *data, unsigned int len); diff --git a/node/Constants.hpp b/node/Constants.hpp index 88549937..274b9564 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -216,7 +216,12 @@ /** * How often Topology::clean() and Network::clean() and similar are called, in ms */ -#define ZT_HOUSEKEEPING_PERIOD 10000 +#define ZT_HOUSEKEEPING_PERIOD 60000 + +/** + * How often in ms to write peer state to storage and/or cluster (approximate) + */ +#define ZT_PEER_STATE_WRITE_PERIOD 10000 /** * How long to remember peer records in RAM if they haven't been used @@ -322,11 +327,6 @@ */ #define ZT_PEER_PATH_EXPIRATION ((ZT_PEER_PING_PERIOD * 4) + 3000) -/** - * Send a full HELLO every this often (ms) - */ -#define ZT_PEER_SEND_FULL_HELLO_EVERY (ZT_PEER_PING_PERIOD * 2) - /** * How often to retry expired paths that we're still remembering */ diff --git a/node/Identity.hpp b/node/Identity.hpp index b1c7d6f4..79e17f4d 100644 --- a/node/Identity.hpp +++ b/node/Identity.hpp @@ -91,7 +91,10 @@ public: ~Identity() { - delete _privateKey; + if (_privateKey) { + Utils::burn(_privateKey,sizeof(C25519::Private)); + delete _privateKey; + } } inline Identity &operator=(const Identity &id) diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 4d99e87d..0548387b 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -585,12 +585,6 @@ bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,void *tPtr,const Shar } else { // Request unknown WHOIS from upstream from us (if we have one) RR->sw->requestWhois(tPtr,addr); -#ifdef ZT_ENABLE_CLUSTER - // Distribute WHOIS queries across a cluster if we do not know the ID. - // This may result in duplicate OKs to the querying peer, which is fine. - if (RR->cluster) - RR->cluster->sendDistributedQuery(*this); -#endif } } @@ -1055,12 +1049,6 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,void *tPtr outp.armor(peer->key(),true,_path->nextOutgoingCounter()); _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); } - - // If we are a member of a cluster, distribute this GATHER across it -#ifdef ZT_ENABLE_CLUSTER - if ((RR->cluster)&&(gatheredLocally < gatherLimit)) - RR->cluster->sendDistributedQuery(*this); -#endif } peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_GATHER,0,Packet::VERB_NOP,trustEstablished); diff --git a/node/Network.cpp b/node/Network.cpp index 0a16ded8..bccc0397 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -1067,11 +1067,6 @@ uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Add return 0; } -#ifdef ZT_ENABLE_CLUSTER - if ((source)&&(RR->cluster)) - RR->cluster->broadcastNetworkConfigChunk(chunk.field(start,chunk.size() - start),chunk.size() - start); -#endif - // New properly verified chunks can be flooded "virally" through the network if (fastPropagate) { Address *a = (Address *)0; @@ -1099,11 +1094,6 @@ uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Add if ((!c)||(_incomingConfigChunks[i].ts < c->ts)) c = &(_incomingConfigChunks[i]); } - -#ifdef ZT_ENABLE_CLUSTER - if ((source)&&(RR->cluster)) - RR->cluster->broadcastNetworkConfigChunk(chunk.field(start,chunk.size() - start),chunk.size() - start); -#endif } else { TRACE("discarded single-chunk unsigned legacy config: this is only allowed if the sender is the controller itself"); return 0; diff --git a/node/Node.cpp b/node/Node.cpp index 1112c0f2..4ffe496c 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -68,6 +68,7 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint6 throw std::runtime_error("callbacks struct version mismatch"); memcpy(&_cb,callbacks,sizeof(ZT_Node_Callbacks)); + // Initialize non-cryptographic PRNG from a good random source Utils::getSecureRandom((void *)_prngState,sizeof(_prngState)); _online = false; @@ -78,33 +79,34 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint6 uint64_t idtmp[2]; idtmp[0] = 0; idtmp[1] = 0; - char tmp[512]; - std::string tmp2; + char tmp[1024]; int n = stateObjectGet(tptr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp,tmp,sizeof(tmp) - 1); if (n > 0) { tmp[n] = (char)0; - if (!RR->identity.fromString(tmp)) + if (RR->identity.fromString(tmp)) { + RR->publicIdentityStr = RR->identity.toString(false); + RR->secretIdentityStr = RR->identity.toString(true); + } else { n = -1; + } } idtmp[0] = RR->identity.address().toInt(); idtmp[1] = 0; if (n <= 0) { RR->identity.generate(); - tmp2 = RR->identity.toString(true); - stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp,tmp2.data(),(unsigned int)tmp2.length()); - tmp2 = RR->identity.toString(false); - stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,tmp2.data(),(unsigned int)tmp2.length()); + RR->publicIdentityStr = RR->identity.toString(false); + RR->secretIdentityStr = RR->identity.toString(true); + stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp,RR->secretIdentityStr.data(),(unsigned int)RR->secretIdentityStr.length()); + stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr.data(),(unsigned int)RR->publicIdentityStr.length()); } else { n = stateObjectGet(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,tmp,sizeof(tmp) - 1); if (n > 0) { tmp[n] = (char)0; - if (RR->identity.toString(false) != tmp) + if (RR->publicIdentityStr != tmp) n = -1; } - if (n <= 0) { - tmp2 = RR->identity.toString(false); - stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,tmp2.data(),(unsigned int)tmp2.length()); - } + if (n <= 0) + stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr.data(),(unsigned int)RR->publicIdentityStr.length()); } try { @@ -125,24 +127,20 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint6 Node::~Node() { - Mutex::Lock _l(_networks_m); - - _networks.clear(); // destroy all networks before shutdown - + { + Mutex::Lock _l(_networks_m); + _networks.clear(); // destroy all networks before shutdown + } delete RR->sa; delete RR->topology; delete RR->mc; delete RR->sw; - -#ifdef ZT_ENABLE_CLUSTER - delete RR->cluster; -#endif } ZT_ResultCode Node::processStateUpdate( void *tptr, ZT_StateObjectType type, - uint64_t id, + const uint64_t id[2], const void *data, unsigned int len) { @@ -151,11 +149,12 @@ ZT_ResultCode Node::processStateUpdate( case ZT_STATE_OBJECT_PEER_STATE: if (len) { - } - break; - - case ZT_STATE_OBJECT_PEER_IDENTITY: - if (len) { + const SharedPtr p(RR->topology->getPeer(tptr,Address(id[0]))); + if (p) { + r = (p->applyStateUpdate(data,len)) ? ZT_RESULT_OK : ZT_RESULT_OK_IGNORED; + } else { + r = (Peer::createFromStateUpdate(RR,tptr,data,len)) ? ZT_RESULT_OK : ZT_RESULT_OK_IGNORED; + } } break; @@ -163,9 +162,9 @@ ZT_ResultCode Node::processStateUpdate( if (len <= (ZT_NETWORKCONFIG_DICT_CAPACITY - 1)) { if (len < 2) { Mutex::Lock _l(_networks_m); - SharedPtr &nw = _networks[id]; + SharedPtr &nw = _networks[id[0]]; if (!nw) { - nw = SharedPtr(new Network(RR,tptr,id,(void *)0,(const NetworkConfig *)0)); + nw = SharedPtr(new Network(RR,tptr,id[0],(void *)0,(const NetworkConfig *)0)); r = ZT_RESULT_OK; } } else { @@ -175,7 +174,7 @@ ZT_ResultCode Node::processStateUpdate( try { if (nconf->fromDictionary(*dict)) { Mutex::Lock _l(_networks_m); - SharedPtr &nw = _networks[id]; + SharedPtr &nw = _networks[id[0]]; if (nw) { switch (nw->setConfiguration(tptr,*nconf,false)) { default: @@ -189,7 +188,7 @@ ZT_ResultCode Node::processStateUpdate( break; } } else { - nw = SharedPtr(new Network(RR,tptr,id,(void *)0,nconf)); + nw = SharedPtr(new Network(RR,tptr,id[0],(void *)0,nconf)); } } else { r = ZT_RESULT_ERROR_BAD_PARAMETER; @@ -208,9 +207,14 @@ ZT_ResultCode Node::processStateUpdate( } break; + case ZT_STATE_OBJECT_NETWORK_MEMBERSHIP: + if (len) { + } + break; + case ZT_STATE_OBJECT_PLANET: case ZT_STATE_OBJECT_MOON: - if (len <= ZT_WORLD_MAX_SERIALIZED_LENGTH) { + if ((len)&&(len <= ZT_WORLD_MAX_SERIALIZED_LENGTH)) { World w; try { w.deserialize(Buffer(data,len)); @@ -395,18 +399,7 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,uint64_t now,volatile uint } try { -#ifdef ZT_ENABLE_CLUSTER - // If clustering is enabled we have to call cluster->doPeriodicTasks() very often, so we override normal timer deadline behavior - if (RR->cluster) { - RR->sw->doTimerTasks(tptr,now); - RR->cluster->doPeriodicTasks(); - *nextBackgroundTaskDeadline = now + ZT_CLUSTER_PERIODIC_TASK_PERIOD; // this is really short so just tick at this rate - } else { -#endif - *nextBackgroundTaskDeadline = now + (uint64_t)std::max(std::min(timeUntilNextPingCheck,RR->sw->doTimerTasks(tptr,now)),(unsigned long)ZT_CORE_TIMER_TASK_GRANULARITY); -#ifdef ZT_ENABLE_CLUSTER - } -#endif + *nextBackgroundTaskDeadline = now + (uint64_t)std::max(std::min(timeUntilNextPingCheck,RR->sw->doTimerTasks(tptr,now)),(unsigned long)ZT_CORE_TIMER_TASK_GRANULARITY); } catch ( ... ) { return ZT_RESULT_FATAL_ERROR_INTERNAL; } @@ -620,76 +613,6 @@ void Node::setNetconfMaster(void *networkControllerInstance) RR->localNetworkController->init(RR->identity,this); } -/* -ZT_ResultCode Node::clusterInit( - unsigned int myId, - const struct sockaddr_storage *zeroTierPhysicalEndpoints, - unsigned int numZeroTierPhysicalEndpoints, - int x, - int y, - int z, - void (*sendFunction)(void *,unsigned int,const void *,unsigned int), - void *sendFunctionArg, - int (*addressToLocationFunction)(void *,const struct sockaddr_storage *,int *,int *,int *), - void *addressToLocationFunctionArg) -{ -#ifdef ZT_ENABLE_CLUSTER - if (RR->cluster) - return ZT_RESULT_ERROR_BAD_PARAMETER; - - std::vector eps; - for(unsigned int i=0;icluster = new Cluster(RR,myId,eps,x,y,z,sendFunction,sendFunctionArg,addressToLocationFunction,addressToLocationFunctionArg); - - return ZT_RESULT_OK; -#else - return ZT_RESULT_ERROR_UNSUPPORTED_OPERATION; -#endif -} - -ZT_ResultCode Node::clusterAddMember(unsigned int memberId) -{ -#ifdef ZT_ENABLE_CLUSTER - if (!RR->cluster) - return ZT_RESULT_ERROR_BAD_PARAMETER; - RR->cluster->addMember((uint16_t)memberId); - return ZT_RESULT_OK; -#else - return ZT_RESULT_ERROR_UNSUPPORTED_OPERATION; -#endif -} - -void Node::clusterRemoveMember(unsigned int memberId) -{ -#ifdef ZT_ENABLE_CLUSTER - if (RR->cluster) - RR->cluster->removeMember((uint16_t)memberId); -#endif -} - -void Node::clusterHandleIncomingMessage(const void *msg,unsigned int len) -{ -#ifdef ZT_ENABLE_CLUSTER - if (RR->cluster) - RR->cluster->handleIncomingStateMessage(msg,len); -#endif -} - -void Node::clusterStatus(ZT_ClusterStatus *cs) -{ - if (!cs) - return; -#ifdef ZT_ENABLE_CLUSTER - if (RR->cluster) - RR->cluster->status(*cs); - else -#endif - memset(cs,0,sizeof(ZT_ClusterStatus)); -} -*/ - /****************************************************************************/ /* Node methods used only within node/ */ /****************************************************************************/ @@ -918,7 +841,7 @@ enum ZT_ResultCode ZT_Node_processStateUpdate( ZT_Node *node, void *tptr, ZT_StateObjectType type, - uint64_t id, + const uint64_t id[2], const void *data, unsigned int len) { diff --git a/node/Node.hpp b/node/Node.hpp index f1209d00..17050d24 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -85,7 +85,7 @@ public: ZT_ResultCode processStateUpdate( void *tptr, ZT_StateObjectType type, - uint64_t id, + const uint64_t id[2], const void *data, unsigned int len); ZT_ResultCode processWirePacket( diff --git a/node/Path.hpp b/node/Path.hpp index 74b31d8d..a6f56d31 100644 --- a/node/Path.hpp +++ b/node/Path.hpp @@ -46,11 +46,6 @@ */ #define ZT_PATH_MAX_PREFERENCE_RANK ((ZT_INETADDRESS_MAX_SCOPE << 1) | 1) -/** - * Maximum distance for a path - */ -#define ZT_PATH_DISTANCE_MAX 0xffff - namespace ZeroTier { class RuntimeEnvironment; @@ -125,7 +120,6 @@ public: _incomingLinkQualitySlowLogCounter(-64), // discard first fast log _incomingLinkQualityPreviousPacketCounter(0), _outgoingPacketCounter(0), - _distance(ZT_PATH_DISTANCE_MAX), _addr(), _localAddress(), _ipScope(InetAddress::IP_SCOPE_NONE) @@ -143,7 +137,6 @@ public: _incomingLinkQualitySlowLogCounter(-64), // discard first fast log _incomingLinkQualityPreviousPacketCounter(0), _outgoingPacketCounter(0), - _distance(ZT_PATH_DISTANCE_MAX), _addr(addr), _localAddress(localAddress), _ipScope(addr.ipScope()) @@ -311,11 +304,6 @@ public: */ inline uint64_t lastTrustEstablishedPacketReceived() const { return _lastTrustEstablishedPacketReceived; } - /** - * @return Distance (higher is further) - */ - inline unsigned int distance() const { return _distance; } - /** * @param lo Last out send * @param li Last in send @@ -344,7 +332,6 @@ private: volatile signed int _incomingLinkQualitySlowLogCounter; volatile unsigned int _incomingLinkQualityPreviousPacketCounter; volatile unsigned int _outgoingPacketCounter; - volatile unsigned int _distance; InetAddress _addr; InetAddress _localAddress; InetAddress::IpScope _ipScope; // memoize this since it's a computed value checked often diff --git a/node/Peer.cpp b/node/Peer.cpp index a7466296..18d05875 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -146,8 +146,8 @@ void Peer::received( path->updateLinkQuality((unsigned int)(packetId & 7)); if (hops == 0) { + // If this is a direct packet (no hops), update existing paths or learn new ones bool pathAlreadyKnown = false; - bool newPathLearned = false; { Mutex::Lock _l(_paths_m); @@ -188,7 +188,7 @@ void Peer::received( if (verb == Packet::VERB_OK) { potentialNewPeerPath->lr = now; potentialNewPeerPath->p = path; - newPathLearned = true; + _lastWroteState = 0; // force state write now } else { TRACE("got %s via unknown path %s(%s), confirming...",Packet::verbString(verb),_id.address().toString().c_str(),path->address().toString().c_str()); attemptToContactAt(tPtr,path->localAddress(),path->address(),now,true,path->nextOutgoingCounter()); @@ -196,9 +196,6 @@ void Peer::received( } } } - - if (newPathLearned) - writeState(tPtr,now); } else if (this->trustEstablished(now)) { // Send PUSH_DIRECT_PATHS if hops>0 (relayed) and we have a trust relationship (common network membership) if ((now - _lastDirectPathPushSent) >= ZT_DIRECT_PATH_PUSH_INTERVAL) { @@ -270,6 +267,9 @@ void Peer::received( } } } + + if ((now - _lastWroteState) > ZT_PEER_STATE_WRITE_PERIOD) + writeState(tPtr,now); } bool Peer::sendDirect(void *tPtr,const void *data,unsigned int len,uint64_t now,bool force) @@ -435,7 +435,7 @@ bool Peer::doPingAndKeepalive(void *tPtr,uint64_t now,int inetAddressFamily) void Peer::writeState(void *tPtr,const uint64_t now) { try { - Buffer b; + Buffer b; b.append((uint8_t)1); // version b.append(now); @@ -455,7 +455,6 @@ void Peer::writeState(void *tPtr,const uint64_t now) b.append(_v4Path.p->lastOut()); b.append(_v4Path.p->lastIn()); b.append(_v4Path.p->lastTrustEstablishedPacketReceived()); - b.append((uint16_t)_v4Path.p->distance()); _v4Path.p->address().serialize(b); _v4Path.p->localAddress().serialize(b); } @@ -464,29 +463,29 @@ void Peer::writeState(void *tPtr,const uint64_t now) b.append(_v6Path.p->lastOut()); b.append(_v6Path.p->lastIn()); b.append(_v6Path.p->lastTrustEstablishedPacketReceived()); - b.append((uint16_t)_v6Path.p->distance()); _v6Path.p->address().serialize(b); _v6Path.p->localAddress().serialize(b); } } - b.append(_lastReceive); - b.append(_lastNontrivialReceive); - b.append(_lastTriedMemorizedPath); - b.append(_lastDirectPathPushSent); - b.append(_lastDirectPathPushReceive); - b.append(_lastCredentialRequestSent); - b.append(_lastWhoisRequestReceived); - b.append(_lastEchoRequestReceived); - b.append(_lastComRequestReceived); - b.append(_lastComRequestSent); - b.append(_lastCredentialsReceived); - b.append(_lastTrustEstablishedPacketReceived); - - b.append(_vProto); - b.append(_vMajor); - b.append(_vMinor); - b.append(_vRevision); + // Save space by sending these as time since now at 100ms resolution + b.append((uint16_t)(std::max(now - _lastReceive,(uint64_t)6553500) / 100)); + b.append((uint16_t)(std::max(now - _lastNontrivialReceive,(uint64_t)6553500) / 100)); + b.append((uint16_t)(std::max(now - _lastTriedMemorizedPath,(uint64_t)6553500) / 100)); + b.append((uint16_t)(std::max(now - _lastDirectPathPushSent,(uint64_t)6553500) / 100)); + b.append((uint16_t)(std::max(now - _lastDirectPathPushReceive,(uint64_t)6553500) / 100)); + b.append((uint16_t)(std::max(now - _lastCredentialRequestSent,(uint64_t)6553500) / 100)); + b.append((uint16_t)(std::max(now - _lastWhoisRequestReceived,(uint64_t)6553500) / 100)); + b.append((uint16_t)(std::max(now - _lastEchoRequestReceived,(uint64_t)6553500) / 100)); + b.append((uint16_t)(std::max(now - _lastComRequestReceived,(uint64_t)6553500) / 100)); + b.append((uint16_t)(std::max(now - _lastComRequestSent,(uint64_t)6553500) / 100)); + b.append((uint16_t)(std::max(now - _lastCredentialsReceived,(uint64_t)6553500) / 100)); + b.append((uint16_t)(std::max(now - _lastTrustEstablishedPacketReceived,(uint64_t)6553500) / 100)); + + b.append((uint8_t)_vProto); + b.append((uint8_t)_vMajor); + b.append((uint8_t)_vMinor); + b.append((uint16_t)_vRevision); b.append((uint16_t)0); // length of additional fields @@ -501,7 +500,7 @@ void Peer::writeState(void *tPtr,const uint64_t now) bool Peer::applyStateUpdate(const void *data,unsigned int len) { try { - Buffer b(data,len); + Buffer b(data,len); unsigned int ptr = 0; if (b[ptr++] != 1) @@ -510,6 +509,11 @@ bool Peer::applyStateUpdate(const void *data,unsigned int len) if (ts <= _lastReceivedStateTimestamp) return false; + Identity id; + ptr += id.deserialize(b,ptr); + if (id != _id) // sanity check + return false; + const unsigned int pathCount = (unsigned int)b[ptr++]; { Mutex::Lock _l(_paths_m); @@ -518,7 +522,6 @@ bool Peer::applyStateUpdate(const void *data,unsigned int len) const uint64_t lastOut = b.at(ptr); ptr += 8; const uint64_t lastIn = b.at(ptr); ptr += 8; const uint64_t lastTrustEstablishedPacketReceived = b.at(ptr); ptr += 8; - const unsigned int distance = b.at(ptr); ptr += 2; InetAddress addr,localAddr; ptr += addr.deserialize(b,ptr); ptr += localAddr.deserialize(b,ptr); @@ -529,8 +532,9 @@ bool Peer::applyStateUpdate(const void *data,unsigned int len) case AF_INET6: p = &_v6Path; break; } if (p) { - if ( ((p->p->address() != addr)||(p->p->localAddress() != localAddr)) && (p->p->distance() > distance) ) + if ( (!p->p) || ((p->p->address() != addr)||(p->p->localAddress() != localAddr)) ) { p->p = RR->topology->getPath(localAddr,addr); + } p->lr = lr; p->p->updateFromRemoteState(lastOut,lastIn,lastTrustEstablishedPacketReceived); } @@ -538,22 +542,22 @@ bool Peer::applyStateUpdate(const void *data,unsigned int len) } } - _lastReceive = std::max(_lastReceive,b.at(ptr)); ptr += 8; - _lastNontrivialReceive = std::max(_lastNontrivialReceive,b.at(ptr)); ptr += 8; - _lastTriedMemorizedPath = std::max(_lastTriedMemorizedPath,b.at(ptr)); ptr += 8; - _lastDirectPathPushSent = std::max(_lastDirectPathPushSent,b.at(ptr)); ptr += 8; - _lastDirectPathPushReceive = std::max(_lastDirectPathPushReceive,b.at(ptr)); ptr += 8; - _lastCredentialRequestSent = std::max(_lastCredentialRequestSent,b.at(ptr)); ptr += 8; - _lastWhoisRequestReceived = std::max(_lastWhoisRequestReceived,b.at(ptr)); ptr += 8; - _lastEchoRequestReceived = std::max(_lastEchoRequestReceived,b.at(ptr)); ptr += 8; - _lastComRequestReceived = std::max(_lastComRequestReceived,b.at(ptr)); ptr += 8; - _lastComRequestSent = std::max(_lastComRequestSent,b.at(ptr)); ptr += 8; - _lastCredentialsReceived = std::max(_lastCredentialsReceived,b.at(ptr)); ptr += 8; - _lastTrustEstablishedPacketReceived = std::max(_lastTrustEstablishedPacketReceived,b.at(ptr)); ptr += 8; - - _vProto = b.at(ptr); ptr += 2; - _vMajor = b.at(ptr); ptr += 2; - _vMinor = b.at(ptr); ptr += 2; + _lastReceive = std::max(_lastReceive,ts - ((uint64_t)b.at(ptr) * 100ULL)); ptr += 2; + _lastNontrivialReceive = std::max(_lastNontrivialReceive,ts - ((uint64_t)b.at(ptr) * 100ULL)); ptr += 2; + _lastTriedMemorizedPath = std::max(_lastTriedMemorizedPath,ts - ((uint64_t)b.at(ptr) * 100ULL)); ptr += 2; + _lastDirectPathPushSent = std::max(_lastDirectPathPushSent,ts - ((uint64_t)b.at(ptr) * 100ULL)); ptr += 2; + _lastDirectPathPushReceive = std::max(_lastDirectPathPushReceive,ts - ((uint64_t)b.at(ptr) * 100ULL)); ptr += 2; + _lastCredentialRequestSent = std::max(_lastCredentialRequestSent,ts - ((uint64_t)b.at(ptr) * 100ULL)); ptr += 2; + _lastWhoisRequestReceived = std::max(_lastWhoisRequestReceived,ts - ((uint64_t)b.at(ptr) * 100ULL)); ptr += 2; + _lastEchoRequestReceived = std::max(_lastEchoRequestReceived,ts - ((uint64_t)b.at(ptr) * 100ULL)); ptr += 2; + _lastComRequestReceived = std::max(_lastComRequestReceived,ts - ((uint64_t)b.at(ptr) * 100ULL)); ptr += 2; + _lastComRequestSent = std::max(_lastComRequestSent,ts - ((uint64_t)b.at(ptr) * 100ULL)); ptr += 2; + _lastCredentialsReceived = std::max(_lastCredentialsReceived,ts - ((uint64_t)b.at(ptr) * 100ULL)); ptr += 2; + _lastTrustEstablishedPacketReceived = std::max(_lastTrustEstablishedPacketReceived,ts - ((uint64_t)b.at(ptr) * 100ULL)); ptr += 2; + + _vProto = (uint16_t)b[ptr++]; + _vMajor = (uint16_t)b[ptr++]; + _vMinor = (uint16_t)b[ptr++]; _vRevision = b.at(ptr); ptr += 2; _lastReceivedStateTimestamp = ts; @@ -563,4 +567,25 @@ bool Peer::applyStateUpdate(const void *data,unsigned int len) return false; } +SharedPtr Peer::createFromStateUpdate(const RuntimeEnvironment *renv,void *tPtr,const void *data,unsigned int len) +{ + try { + Identity id; + { + Buffer b(data,len); + unsigned int ptr = 0; + if (b[ptr++] != 1) + return SharedPtr(); + ptr += 8; // skip TS, don't care + id.deserialize(b,ptr); + } + if (id) { + const SharedPtr p(new Peer(renv,renv->identity,id)); + if (p->applyStateUpdate(data,len)) + return renv->topology->addPeer(tPtr,p); + } + } catch ( ... ) {} + return SharedPtr(); +} + } // namespace ZeroTier diff --git a/node/Peer.hpp b/node/Peer.hpp index d6b7dad9..f0eb3ee8 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -51,6 +51,8 @@ #include "Mutex.hpp" #include "NonCopyable.hpp" +#define ZT_PEER_MAX_SERIALIZED_STATE_SIZE (sizeof(Peer) + 32 + (sizeof(Path) * 2)) + namespace ZeroTier { /** @@ -194,9 +196,10 @@ public: bool doPingAndKeepalive(void *tPtr,uint64_t now,int inetAddressFamily); /** - * Write current peer state to external storage / cluster network + * Write object state to external storage and/or cluster network * * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call + * @param now Current time */ void writeState(void *tPtr,const uint64_t now); @@ -437,6 +440,17 @@ public: return false; } + /** + * Create a peer from a remote state update + * + * @param renv Runtime environment + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call + * @param data State update data + * @param len State update length + * @return Peer or NULL if data was invalid + */ + static SharedPtr createFromStateUpdate(const RuntimeEnvironment *renv,void *tPtr,const void *data,unsigned int len); + private: struct _PeerPath { diff --git a/node/RuntimeEnvironment.hpp b/node/RuntimeEnvironment.hpp index d8e1d699..ee0c8c24 100644 --- a/node/RuntimeEnvironment.hpp +++ b/node/RuntimeEnvironment.hpp @@ -30,8 +30,8 @@ #include #include "Constants.hpp" +#include "Utils.hpp" #include "Identity.hpp" -#include "Mutex.hpp" namespace ZeroTier { @@ -58,10 +58,13 @@ public: ,mc((Multicaster *)0) ,topology((Topology *)0) ,sa((SelfAwareness *)0) -#ifdef ZT_ENABLE_CLUSTER - ,cluster((Cluster *)0) -#endif { + Utils::getSecureRandom(&instanceId,sizeof(instanceId)); + } + + ~RuntimeEnvironment() + { + Utils::burn(reinterpret_cast(const_cast(secretIdentityStr.data())),(unsigned int)secretIdentityStr.length()); } // Node instance that owns this RuntimeEnvironment @@ -87,9 +90,11 @@ public: Multicaster *mc; Topology *topology; SelfAwareness *sa; -#ifdef ZT_ENABLE_CLUSTER - Cluster *cluster; -#endif + + /** + * A random integer identifying this run of ZeroTier + */ + uint32_t instanceId; }; } // namespace ZeroTier diff --git a/node/Switch.cpp b/node/Switch.cpp index 2be54b37..cbd73a83 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -108,13 +108,7 @@ void Switch::onRemotePacket(void *tPtr,const InetAddress &localAddr,const InetAd const Address destination(fragment.destination()); if (destination != RR->identity.address()) { -#ifdef ZT_ENABLE_CLUSTER - const bool isClusterFrontplane = ((RR->cluster)&&(RR->cluster->isClusterPeerFrontplane(fromAddr))); -#else - const bool isClusterFrontplane = false; -#endif - - if ( (!RR->topology->amRoot()) && (!path->trustEstablished(now)) && (!isClusterFrontplane) ) + if ( (!RR->topology->amRoot()) && (!path->trustEstablished(now)) ) return; if (fragment.hops() < ZT_RELAY_MAX_HOPS) { @@ -124,13 +118,6 @@ void Switch::onRemotePacket(void *tPtr,const InetAddress &localAddr,const InetAd // It wouldn't hurt anything, just redundant and unnecessary. SharedPtr relayTo = RR->topology->getPeer(tPtr,destination); if ((!relayTo)||(!relayTo->sendDirect(tPtr,fragment.data(),fragment.size(),now,false))) { -#ifdef ZT_ENABLE_CLUSTER - if ((RR->cluster)&&(!isClusterFrontplane)) { - RR->cluster->relayViaCluster(Address(),destination,fragment.data(),fragment.size(),false); - return; - } -#endif - // Don't know peer or no direct path -- so relay via someone upstream relayTo = RR->topology->getUpstreamPeer(); if (relayTo) @@ -197,13 +184,8 @@ void Switch::onRemotePacket(void *tPtr,const InetAddress &localAddr,const InetAd //TRACE("<< %.16llx %s -> %s (size: %u)",(unsigned long long)packet->packetId(),source.toString().c_str(),destination.toString().c_str(),packet->size()); -#ifdef ZT_ENABLE_CLUSTER - if ( (source == RR->identity.address()) && ((!RR->cluster)||(!RR->cluster->isClusterPeerFrontplane(fromAddr))) ) - return; -#else if (source == RR->identity.address()) return; -#endif if (destination != RR->identity.address()) { if ( (!RR->topology->amRoot()) && (!path->trustEstablished(now)) && (source != RR->identity.address()) ) @@ -212,12 +194,7 @@ void Switch::onRemotePacket(void *tPtr,const InetAddress &localAddr,const InetAd Packet packet(data,len); if (packet.hops() < ZT_RELAY_MAX_HOPS) { -#ifdef ZT_ENABLE_CLUSTER - if (source != RR->identity.address()) // don't increment hops for cluster frontplane relays - packet.incrementHops(); -#else packet.incrementHops(); -#endif SharedPtr relayTo = RR->topology->getPeer(tPtr,destination); if ((relayTo)&&(relayTo->sendDirect(tPtr,packet.data(),packet.size(),now,false))) { @@ -277,12 +254,6 @@ void Switch::onRemotePacket(void *tPtr,const InetAddress &localAddr,const InetAd } } } else { -#ifdef ZT_ENABLE_CLUSTER - if ((RR->cluster)&&(source != RR->identity.address())) { - RR->cluster->relayViaCluster(source,destination,packet.data(),packet.size(),_shouldUnite(now,source,destination)); - return; - } -#endif relayTo = RR->topology->getUpstreamPeer(&source,1,true); if (relayTo) relayTo->sendDirect(tPtr,packet.data(),packet.size(),now,true); @@ -769,14 +740,6 @@ bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt) const uint64_t now = RR->node->now(); const Address destination(packet.destination()); -#ifdef ZT_ENABLE_CLUSTER - uint64_t clusterMostRecentTs = 0; - int clusterMostRecentMemberId = -1; - uint8_t clusterPeerSecret[ZT_PEER_SECRET_KEY_LENGTH]; - if (RR->cluster) - clusterMostRecentMemberId = RR->cluster->checkSendViaCluster(destination,clusterMostRecentTs,clusterPeerSecret); -#endif - const SharedPtr peer(RR->topology->getPeer(tPtr,destination)); if (peer) { /* First get the best path, and if it's dead (and this is not a root) @@ -788,74 +751,37 @@ bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt) viaPath = peer->getBestPath(now,false); if ( (viaPath) && (!viaPath->alive(now)) && (!RR->topology->isUpstream(peer->identity())) ) { -#ifdef ZT_ENABLE_CLUSTER - if ((clusterMostRecentMemberId < 0)||(viaPath->lastIn() > clusterMostRecentTs)) { -#endif - if ((now - viaPath->lastOut()) > std::max((now - viaPath->lastIn()) * 4,(uint64_t)ZT_PATH_MIN_REACTIVATE_INTERVAL)) { - peer->attemptToContactAt(tPtr,viaPath->localAddress(),viaPath->address(),now,false,viaPath->nextOutgoingCounter()); - viaPath->sent(now); - } -#ifdef ZT_ENABLE_CLUSTER + if ((now - viaPath->lastOut()) > std::max((now - viaPath->lastIn()) * 4,(uint64_t)ZT_PATH_MIN_REACTIVATE_INTERVAL)) { + peer->attemptToContactAt(tPtr,viaPath->localAddress(),viaPath->address(),now,false,viaPath->nextOutgoingCounter()); + viaPath->sent(now); } -#endif viaPath.zero(); } -#ifdef ZT_ENABLE_CLUSTER - if (clusterMostRecentMemberId >= 0) { - if ((viaPath)&&(viaPath->lastIn() < clusterMostRecentTs)) - viaPath.zero(); - } else if (!viaPath) { -#else if (!viaPath) { -#endif peer->tryMemorizedPath(tPtr,now); // periodically attempt memorized or statically defined paths, if any are known const SharedPtr relay(RR->topology->getUpstreamPeer()); if ( (!relay) || (!(viaPath = relay->getBestPath(now,false))) ) { if (!(viaPath = peer->getBestPath(now,true))) return false; } -#ifdef ZT_ENABLE_CLUSTER } -#else - } -#endif } else { -#ifdef ZT_ENABLE_CLUSTER - if (clusterMostRecentMemberId < 0) { -#else - requestWhois(tPtr,destination); - return false; // if we are not in cluster mode, there is no way we can send without knowing the peer directly -#endif -#ifdef ZT_ENABLE_CLUSTER - } -#endif + requestWhois(tPtr,destination); + return false; // if we are not in cluster mode, there is no way we can send without knowing the peer directly } unsigned int chunkSize = std::min(packet.size(),(unsigned int)ZT_UDP_DEFAULT_PAYLOAD_MTU); packet.setFragmented(chunkSize < packet.size()); -#ifdef ZT_ENABLE_CLUSTER - const uint64_t trustedPathId = (viaPath) ? RR->topology->getOutboundPathTrust(viaPath->address()) : 0; - if (trustedPathId) { - packet.setTrusted(trustedPathId); - } else { - packet.armor((clusterMostRecentMemberId >= 0) ? clusterPeerSecret : peer->key(),encrypt,(viaPath) ? viaPath->nextOutgoingCounter() : 0); - } -#else const uint64_t trustedPathId = RR->topology->getOutboundPathTrust(viaPath->address()); if (trustedPathId) { packet.setTrusted(trustedPathId); } else { packet.armor(peer->key(),encrypt,viaPath->nextOutgoingCounter()); } -#endif -#ifdef ZT_ENABLE_CLUSTER - if ( ((viaPath)&&(viaPath->send(RR,tPtr,packet.data(),chunkSize,now))) || ((clusterMostRecentMemberId >= 0)&&(RR->cluster->sendViaCluster(clusterMostRecentMemberId,destination,packet.data(),chunkSize))) ) { -#else if (viaPath->send(RR,tPtr,packet.data(),chunkSize,now)) { -#endif if (chunkSize < packet.size()) { // Too big for one packet, fragment the rest unsigned int fragStart = chunkSize; @@ -868,14 +794,7 @@ bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt) for(unsigned int fno=1;fnosend(RR,tPtr,frag.data(),frag.size(),now); - else if (clusterMostRecentMemberId >= 0) - RR->cluster->sendViaCluster(clusterMostRecentMemberId,destination,frag.data(),frag.size()); -#else viaPath->send(RR,tPtr,frag.data(),frag.size(),now); -#endif fragStart += chunkSize; remaining -= chunkSize; } diff --git a/node/Topology.cpp b/node/Topology.cpp index be116b28..09a1a895 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -108,8 +108,6 @@ SharedPtr Topology::addPeer(void *tPtr,const SharedPtr &peer) np = hp; } - saveIdentity(tPtr,np->identity()); - return np; } @@ -128,18 +126,20 @@ SharedPtr Topology::getPeer(void *tPtr,const Address &zta) } try { - Identity id(_getIdentity(tPtr,zta)); - if (id) { - SharedPtr np(new Peer(RR,RR->identity,id)); - { - Mutex::Lock _l(_peers_m); - SharedPtr &ap = _peers[zta]; - if (!ap) - ap.swap(np); + char buf[ZT_PEER_MAX_SERIALIZED_STATE_SIZE]; + uint64_t idbuf[2]; idbuf[0] = zta.toInt(); idbuf[1] = 0; + int len = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_PEER_STATE,idbuf,buf,(unsigned int)sizeof(buf)); + if (len > 0) { + Mutex::Lock _l(_peers_m); + SharedPtr &ap = _peers[zta]; + if (ap) return ap; - } + ap = Peer::createFromStateUpdate(RR,tPtr,buf,len); + if (!ap) + _peers.erase(zta); + return ap; } - } catch ( ... ) {} // invalid identity on disk? + } catch ( ... ) {} // ignore invalid identities or other strage failures return SharedPtr(); } @@ -154,17 +154,7 @@ Identity Topology::getIdentity(void *tPtr,const Address &zta) if (ap) return (*ap)->identity(); } - return _getIdentity(tPtr,zta); -} - -void Topology::saveIdentity(void *tPtr,const Identity &id) -{ - if (id) { - const std::string tmp(id.toString(false)); - uint64_t idtmp[2]; - idtmp[0] = id.address().toInt(); idtmp[1] = 0; - RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_PEER_IDENTITY,idtmp,tmp.data(),(unsigned int)tmp.length()); - } + return Identity(); } SharedPtr Topology::getUpstreamPeer(const Address *avoid,unsigned int avoidCount,bool strictAvoid) @@ -423,21 +413,6 @@ void Topology::doPeriodicTasks(void *tPtr,uint64_t now) } } -Identity Topology::_getIdentity(void *tPtr,const Address &zta) -{ - char tmp[512]; - uint64_t idtmp[2]; - idtmp[0] = zta.toInt(); idtmp[1] = 0; - int n = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_PEER_IDENTITY,idtmp,tmp,sizeof(tmp) - 1); - if (n > 0) { - tmp[n] = (char)0; - try { - return Identity(tmp); - } catch ( ... ) {} // ignore invalid IDs - } - return Identity(); -} - void Topology::_memoizeUpstreams(void *tPtr) { // assumes _upstreams_m and _peers_m are locked @@ -450,10 +425,8 @@ void Topology::_memoizeUpstreams(void *tPtr) } else if (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),i->identity.address()) == _upstreamAddresses.end()) { _upstreamAddresses.push_back(i->identity.address()); SharedPtr &hp = _peers[i->identity.address()]; - if (!hp) { + if (!hp) hp = new Peer(RR,RR->identity,i->identity); - saveIdentity(tPtr,i->identity); - } } } @@ -464,10 +437,8 @@ void Topology::_memoizeUpstreams(void *tPtr) } else if (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),i->identity.address()) == _upstreamAddresses.end()) { _upstreamAddresses.push_back(i->identity.address()); SharedPtr &hp = _peers[i->identity.address()]; - if (!hp) { + if (!hp) hp = new Peer(RR,RR->identity,i->identity); - saveIdentity(tPtr,i->identity); - } } } } diff --git a/node/Topology.hpp b/node/Topology.hpp index 9bc7c0d8..32e38dd3 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -81,6 +81,13 @@ public: */ SharedPtr getPeer(void *tPtr,const Address &zta); + /** + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call + * @param zta ZeroTier address of peer + * @return Identity or NULL identity if not found + */ + Identity getIdentity(void *tPtr,const Address &zta); + /** * Get a peer only if it is presently in memory (no disk cache) * @@ -116,26 +123,6 @@ public: return p; } - /** - * Get the identity of a peer - * - * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call - * @param zta ZeroTier address of peer - * @return Identity or NULL Identity if not found - */ - Identity getIdentity(void *tPtr,const Address &zta); - - /** - * Cache an identity - * - * This is done automatically on addPeer(), and so is only useful for - * cluster identity replication. - * - * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call - * @param id Identity to cache - */ - void saveIdentity(void *tPtr,const Identity &id); - /** * Get the current best upstream peer * diff --git a/osdep/Binder.hpp b/osdep/Binder.hpp index a0b47367..b1fe5921 100644 --- a/osdep/Binder.hpp +++ b/osdep/Binder.hpp @@ -180,7 +180,7 @@ public: const unsigned long pid = (unsigned long)getpid(); // Get all device names - Utils::snprintf(fn,sizeof(fn),"/proc/%lu/net/dev",pid); + Utils::ztsnprintf(fn,sizeof(fn),"/proc/%lu/net/dev",pid); FILE *procf = fopen(fn,"r"); if (procf) { while (fgets(tmp,sizeof(tmp),procf)) { @@ -196,7 +196,7 @@ public: } // Get IPv6 addresses (and any device names we don't already know) - Utils::snprintf(fn,sizeof(fn),"/proc/%lu/net/if_inet6",pid); + Utils::ztsnprintf(fn,sizeof(fn),"/proc/%lu/net/if_inet6",pid); procf = fopen(fn,"r"); if (procf) { while (fgets(tmp,sizeof(tmp),procf)) { diff --git a/service/OneService.cpp b/service/OneService.cpp index f949f348..b5b11111 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -154,9 +154,6 @@ namespace ZeroTier { typedef BSDEthernetTap EthernetTap; } // How often to check for local interface addresses #define ZT_LOCAL_INTERFACE_CHECK_INTERVAL 60000 -// Clean files from iddb.d that are older than this (60 days) -#define ZT_IDDB_CLEANUP_AGE 5184000000ULL - // Maximum write buffer size for outgoing TCP connections (sanity limit) #define ZT_TCP_MAX_WRITEQ_SIZE 33554432 @@ -414,7 +411,6 @@ public: const std::string _homePath; std::string _authToken; std::string _controllerDbPath; - const std::string _iddbPath; const std::string _networksPath; const std::string _moonsPath; @@ -513,7 +509,6 @@ public: OneServiceImpl(const char *hp,unsigned int port) : _homePath((hp) ? hp : ".") ,_controllerDbPath(_homePath + ZT_PATH_SEPARATOR_S "controller.d") - ,_iddbPath(_homePath + ZT_PATH_SEPARATOR_S "iddb.d") ,_networksPath(_homePath + ZT_PATH_SEPARATOR_S "networks.d") ,_moonsPath(_homePath + ZT_PATH_SEPARATOR_S "moons.d") ,_controller((EmbeddedNetworkController *)0) @@ -732,6 +727,9 @@ public: } #endif + // Delete legacy iddb.d if present (cleanup) + 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()); _node->setNetconfMaster((void *)_controller); @@ -781,7 +779,6 @@ public: uint64_t lastBindRefresh = 0; uint64_t lastUpdateCheck = clockShouldBe; uint64_t lastLocalInterfaceAddressCheck = (clockShouldBe - ZT_LOCAL_INTERFACE_CHECK_INTERVAL) + 15000; // do this in 15s to give portmapper time to configure and other things time to settle - uint64_t lastCleanedIddb = 0; uint64_t lastTcpCheck = 0; for(;;) { _run_m.lock(); @@ -797,12 +794,6 @@ public: const uint64_t now = OSUtils::now(); - // Clean iddb.d on start and every 24 hours - if ((now - lastCleanedIddb) > 86400000) { - lastCleanedIddb = now; - OSUtils::cleanDirectory(_iddbPath.c_str(),now - ZT_IDDB_CLEANUP_AGE); - } - // Attempt to detect sleep/wake events by detecting delay overruns bool restarted = false; if ((now > clockShouldBe)&&((now - clockShouldBe) > 10000)) { @@ -1027,7 +1018,7 @@ public: return NULL; } - virtual Node * getNode() + virtual Node *getNode() { return _node; } @@ -1903,27 +1894,16 @@ public: char *const outdata = const_cast(tc->writeq.data()) + startpos; encryptClusterMessage(outdata,mlen); - } - - void replicateStateObjectToCluster(const ZT_StateObjectType type,const uint64_t id[2],const void *const data,const unsigned int len,const uint64_t everyoneBut) - { - std::vector sentTo; - if (everyoneBut) - sentTo.push_back(everyoneBut); - Mutex::Lock _l(_tcpConnections_m); - for(std::vector::const_iterator ci(_tcpConnections.begin());ci!=_tcpConnections.end();++ci) { - TcpConnection *const c = *ci; - if ((c->type == TcpConnection::TCP_CLUSTER_BACKPLANE)&&(c->clusterMemberId != 0)&&(std::find(sentTo.begin(),sentTo.end(),c->clusterMemberId) == sentTo.end())) { - sentTo.push_back(c->clusterMemberId); - replicateStateObject(type,id,data,len,c); - } - } + tc->writeq.append(outdata,mlen); } void writeStateObject(enum ZT_StateObjectType type,const uint64_t id[2],const void *data,int len) { - char p[4096]; + char buf[65535]; + char p[1024]; + FILE *f; bool secure = false; + switch(type) { case ZT_STATE_OBJECT_IDENTITY_PUBLIC: Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str()); @@ -1932,13 +1912,14 @@ public: Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str()); secure = true; break; - case ZT_STATE_OBJECT_PEER_IDENTITY: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "iddb.d/%.10llx",_homePath.c_str(),(unsigned long long)id[0]); - break; + //case ZT_STATE_OBJECT_PEER_STATE: + // break; case ZT_STATE_OBJECT_NETWORK_CONFIG: Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id[0]); secure = true; break; + //case ZT_STATE_OBJECT_NETWORK_MEMBERSHIP: + // break; case ZT_STATE_OBJECT_PLANET: Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); break; @@ -1949,17 +1930,30 @@ public: p[0] = (char)0; break; } + if (p[0]) { if (len >= 0) { - FILE *f = fopen(p,"w"); + // Check to see if we've already written this first. This reduces + // redundant writes and I/O overhead on most platforms and has + // little effect on others. + f = fopen(p,"r"); + bool redundant = false; if (f) { - if (fwrite(data,len,1,f) != 1) - fprintf(stderr,"WARNING: unable to write to file: %s (I/O error)" ZT_EOL_S,p); + long l = (long)fread(buf,1,sizeof(buf),f); fclose(f); - if (secure) - OSUtils::lockDownFile(p,false); - } else { - fprintf(stderr,"WARNING: unable to write to file: %s (unable to open)" ZT_EOL_S,p); + redundant = ((l == (long)len)&&(memcmp(data,buf,l) == 0)); + } + if (!redundant) { + f = fopen(p,"w"); + if (f) { + if (fwrite(data,len,1,f) != 1) + fprintf(stderr,"WARNING: unable to write to file: %s (I/O error)" ZT_EOL_S,p); + fclose(f); + if (secure) + OSUtils::lockDownFile(p,false); + } else { + fprintf(stderr,"WARNING: unable to write to file: %s (unable to open)" ZT_EOL_S,p); + } } } else { OSUtils::rm(p); @@ -2314,7 +2308,7 @@ public: break; case CLUSTER_MESSAGE_STATE_OBJECT: - if (mlen >= 42) { // type + object ID + [data] + if (mlen > 42) { // type + object ID + [data] uint64_t objId[2]; objId[0] = ( ((uint64_t)data[26] << 56) | @@ -2336,10 +2330,8 @@ public: ((uint64_t)data[40] << 8) | (uint64_t)data[41] ); - if (_node->processStateUpdate((void *)0,(ZT_StateObjectType)data[25],objId[0],data + 42,(unsigned int)(mlen - 42)) == ZT_RESULT_OK) { + if (_node->processStateUpdate((void *)0,(ZT_StateObjectType)data[25],objId,data + 42,(unsigned int)(mlen - 42)) == ZT_RESULT_OK) writeStateObject((ZT_StateObjectType)data[25],objId,data + 42,(unsigned int)(mlen - 42)); - replicateStateObjectToCluster((ZT_StateObjectType)data[25],objId,data + 42,(unsigned int)(mlen - 42),tc->clusterMemberId); - } } break; @@ -2558,7 +2550,18 @@ public: inline void nodeStatePutFunction(enum ZT_StateObjectType type,const uint64_t id[2],const void *data,int len) { writeStateObject(type,id,data,len); - replicateStateObjectToCluster(type,id,data,len,0); + + std::vector sentTo; + { + Mutex::Lock _l(_tcpConnections_m); + for(std::vector::const_iterator ci(_tcpConnections.begin());ci!=_tcpConnections.end();++ci) { + TcpConnection *const c = *ci; + if ((c->type == TcpConnection::TCP_CLUSTER_BACKPLANE)&&(c->clusterMemberId != 0)&&(std::find(sentTo.begin(),sentTo.end(),c->clusterMemberId) == sentTo.end())) { + sentTo.push_back(c->clusterMemberId); + replicateStateObject(type,id,data,len,c); + } + } + } } inline int nodeStateGetFunction(enum ZT_StateObjectType type,const uint64_t id[2],void *data,unsigned int maxlen) @@ -2571,9 +2574,6 @@ public: case ZT_STATE_OBJECT_IDENTITY_SECRET: Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str()); break; - case ZT_STATE_OBJECT_PEER_IDENTITY: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "iddb.d/%.10llx",_homePath.c_str(),(unsigned long long)id); - break; case ZT_STATE_OBJECT_NETWORK_CONFIG: Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id); break; -- cgit v1.2.3 From f18158a52d28c14352018a68d328f41fcdb7966f Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 6 Jul 2017 11:45:22 -0700 Subject: . --- include/ZeroTierOne.h | 135 ++-------- node/IncomingPacket.cpp | 14 +- node/Node.cpp | 130 +--------- node/Node.hpp | 14 +- node/Path.cpp | 2 +- node/Path.hpp | 51 ++-- node/Peer.cpp | 59 ++--- node/Peer.hpp | 12 +- node/RuntimeEnvironment.hpp | 10 +- node/SelfAwareness.cpp | 4 +- node/SelfAwareness.hpp | 10 +- node/Switch.cpp | 8 +- node/Switch.hpp | 4 +- node/Topology.cpp | 4 +- node/Topology.hpp | 4 +- osdep/Binder.hpp | 109 ++------ service/OneService.cpp | 609 +++++--------------------------------------- 17 files changed, 198 insertions(+), 981 deletions(-) (limited to 'service/OneService.cpp') diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 133ae340..180e5cd2 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -229,11 +229,6 @@ extern "C" { */ #define ZT_RULE_PACKET_CHARACTERISTICS_TCP_FIN 0x0000000000000001ULL -/** - * A null/empty sockaddr (all zero) to signify an unspecified socket address - */ -extern const struct sockaddr_storage ZT_SOCKADDR_NULL; - /****************************************************************************/ /* Structures and other types */ /****************************************************************************/ @@ -1067,21 +1062,6 @@ typedef struct /** * ZeroTier core state objects - * - * All of these objects can be persisted if desired. To preserve the - * identity of a node and its address, the identity (public and secret) - * must be saved at a minimum. - * - * State objects actually have two IDs (uint64_t[2]). If only one is - * listed the second ([1]) should be zero and is ignored in storage - * and replication. - * - * All state objects should be replicated in cluster mode. The reference - * clustering implementation uses a rumor mill algorithm in which state - * updates that are accepted with RESULT_OK (but not RESULT_OK_IGNORED) - * are flooded to all connected cluster peers. This results in updates - * being flooded across the cluster until all cluster members have the - * latest. */ enum ZT_StateObjectType { @@ -1108,36 +1088,6 @@ enum ZT_StateObjectType */ ZT_STATE_OBJECT_IDENTITY_SECRET = 2, - /** - * A peer to which this node is communicating - * - * Object ID: peer address - * Canonical path: /peers.d/
(10-digit hex address) - * Persistence: optional, can be purged at any time - */ - ZT_STATE_OBJECT_PEER_STATE = 3, - - /** - * Network configuration - * - * Object ID: peer address - * Canonical path: /networks.d/.conf (16-digit hex ID) - * Persistence: required if network memberships should persist - */ - ZT_STATE_OBJECT_NETWORK_CONFIG = 4, - - /** - * Network membership (network X peer intersection) - * - * If these are persisted they must be restored after peer states and - * network configs. Otherwise they are ignored. - * - * Object ID: [0] network ID, [1] peer address - * Canonical path: /networks.d//members.d/
- * Persistence: optional (not usually needed) - */ - ZT_STATE_OBJECT_NETWORK_MEMBERSHIP = 5, - /** * The planet (there is only one per... well... planet!) * @@ -1145,7 +1095,7 @@ enum ZT_StateObjectType * Canonical path: /planet * Persistence: recommended */ - ZT_STATE_OBJECT_PLANET = 6, + ZT_STATE_OBJECT_PLANET = 3, /** * A moon (federated root set) @@ -1154,12 +1104,25 @@ enum ZT_StateObjectType * Canonical path: /moons.d/.moon (16-digit hex ID) * Persistence: required if moon memberships should persist */ - ZT_STATE_OBJECT_MOON = 7, + ZT_STATE_OBJECT_MOON = 4, /** - * IDs above this value will not be used by the core (and could be used as implementation-specific IDs) + * Peer and related state + * + * Object ID: peer address + * Canonical path: /peers.d/ (10-digit address + * Persistence: optional, can be cleared at any time + */ + ZT_STATE_OBJECT_PEER = 5, + + /** + * Network configuration + * + * Object ID: peer address + * Canonical path: /networks.d/.conf (16-digit hex ID) + * Persistence: required if network memberships should persist */ - ZT_STATE_OBJECT__MAX_ID = 255 + ZT_STATE_OBJECT_NETWORK_CONFIG = 6 }; /** @@ -1277,17 +1240,15 @@ typedef int (*ZT_StateGetFunction)( * Parameters: * (1) Node * (2) User pointer - * (3) Local interface address + * (3) Local socket or -1 for "all" or "any" * (4) Remote address * (5) Packet data * (6) Packet length * (7) Desired IP TTL or 0 to use default * - * If there is only one local interface it is safe to ignore the local - * interface address. Otherwise if running with multiple interfaces, the - * correct local interface should be chosen by address unless NULL. If - * the ss_family field is zero (NULL address), a random or preferred - * default interface should be used. + * If there is only one local socket, the local socket can be ignored. + * If the local socket is -1, the packet should be sent out from all + * bound local sockets or a random bound local socket. * * If TTL is nonzero, packets should have their IP TTL value set to this * value if possible. If this is not possible it is acceptable to ignore @@ -1301,7 +1262,7 @@ typedef int (*ZT_WirePacketSendFunction)( ZT_Node *, /* Node */ void *, /* User ptr */ void *, /* Thread ptr */ - const struct sockaddr_storage *, /* Local address */ + int64_t, /* Local socket */ const struct sockaddr_storage *, /* Remote address */ const void *, /* Packet data */ unsigned int, /* Packet length */ @@ -1314,7 +1275,7 @@ typedef int (*ZT_WirePacketSendFunction)( * (1) Node * (2) User pointer * (3) ZeroTier address or 0 for none/any - * (4) Local interface address + * (4) Local socket or -1 if unknown * (5) Remote address * * This function must return nonzero (true) if the path should be used. @@ -1333,7 +1294,7 @@ typedef int (*ZT_PathCheckFunction)( void *, /* User ptr */ void *, /* Thread ptr */ uint64_t, /* ZeroTier address */ - const struct sockaddr_storage *, /* Local address */ + int64_t, /* Local socket or -1 if unknown */ const struct sockaddr_storage *); /* Remote address */ /** @@ -1441,57 +1402,13 @@ enum ZT_ResultCode ZT_Node_new(ZT_Node **node,void *uptr,void *tptr,const struct */ void ZT_Node_delete(ZT_Node *node); -/** - * Notify node of an update to a state object - * - * This can be called after node startup to restore cached state objects such - * as network configurations for joined networks, planet, moons, etc. See - * the documentation of ZT_StateObjectType for more information. It's okay - * to call this for everything in the object store, but note that the node - * will automatically query for some core objects like identities so supplying - * these via this function is not necessary. - * - * Unless clustering is being implemented this function doesn't need to be - * used after startup. It could be called in response to filesystem changes - * to allow some degree of live configurability by filesystem observation - * but this kind of thing is entirely optional. - * - * The return value of this function indicates whether the update was accepted - * as new. A return value of ZT_RESULT_OK indicates that the node gleaned new - * information from this update and that therefore (in cluster rumor mill mode) - * this update should be distributed to other members of a cluster. A return - * value of ZT_RESULT_OK_IGNORED indicates that the object did not provide any - * new information and therefore should not be propagated in a cluster. - * - * If clustering isn't being implemented the return value of this function can - * generally be ignored. - * - * ZT_RESULT_ERROR_BAD_PARAMETER can be returned if the parameter was invalid - * or not applicable. Object stores may delete the object in this case. - * - * @param node Node instance - * @param tptr Thread pointer to pass to functions/callbacks resulting from this call - * @param type State object type - * @param id State object ID (if object type has only one ID, second should be zero) - * @param data State object data - * @param len Length of state object data in bytes - * @return ZT_RESULT_OK if object was accepted or ZT_RESULT_OK_IGNORED if non-informative, error if object was invalid - */ -enum ZT_ResultCode ZT_Node_processStateUpdate( - ZT_Node *node, - void *tptr, - ZT_StateObjectType type, - const uint64_t id[2], - const void *data, - unsigned int len); - /** * Process a packet received from the physical wire * * @param node Node instance * @param tptr Thread pointer to pass to functions/callbacks resulting from this call * @param now Current clock in milliseconds - * @param localAddress Local address, or point to ZT_SOCKADDR_NULL if unspecified + * @param localSocket Local socket (you can use 0 if only one local socket is bound and ignore this) * @param remoteAddress Origin of packet * @param packetData Packet data * @param packetLength Packet length @@ -1502,7 +1419,7 @@ enum ZT_ResultCode ZT_Node_processWirePacket( ZT_Node *node, void *tptr, uint64_t now, - const struct sockaddr_storage *localAddress, + int64_t localSocket, const struct sockaddr_storage *remoteAddress, const void *packetData, unsigned int packetLength, diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 0548387b..f0be96f9 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -309,7 +309,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool if (ptr < size()) { ptr += externalSurfaceAddress.deserialize(*this,ptr); if ((externalSurfaceAddress)&&(hops() == 0)) - RR->sa->iam(tPtr,id.address(),_path->localAddress(),_path->address(),externalSurfaceAddress,RR->topology->isUpstream(id),now); + RR->sa->iam(tPtr,id.address(),_path->localSocket(),_path->address(),externalSurfaceAddress,RR->topology->isUpstream(id),now); } // Get primary planet world ID and world timestamp if present @@ -495,7 +495,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedP peer->setRemoteVersion(vProto,vMajor,vMinor,vRevision); if ((externalSurfaceAddress)&&(hops() == 0)) - RR->sa->iam(tPtr,peer->address(),_path->localAddress(),_path->address(),externalSurfaceAddress,RR->topology->isUpstream(peer->identity()),RR->node->now()); + RR->sa->iam(tPtr,peer->address(),_path->localSocket(),_path->address(),externalSurfaceAddress,RR->topology->isUpstream(peer->identity()),RR->node->now()); } break; case Packet::VERB_WHOIS: @@ -613,9 +613,9 @@ bool IncomingPacket::_doRENDEZVOUS(const RuntimeEnvironment *RR,void *tPtr,const const unsigned int addrlen = (*this)[ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRLEN]; if ((port > 0)&&((addrlen == 4)||(addrlen == 16))) { const InetAddress atAddr(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS,addrlen),addrlen,port); - if (RR->node->shouldUsePathForZeroTierTraffic(tPtr,with,_path->localAddress(),atAddr)) { - RR->node->putPacket(tPtr,_path->localAddress(),atAddr,"ABRE",4,2); // send low-TTL junk packet to 'open' local NAT(s) and stateful firewalls - rendezvousWith->attemptToContactAt(tPtr,_path->localAddress(),atAddr,RR->node->now(),false,0); + if (RR->node->shouldUsePathForZeroTierTraffic(tPtr,with,_path->localSocket(),atAddr)) { + RR->node->putPacket(tPtr,_path->localSocket(),atAddr,"ABRE",4,2); // send low-TTL junk packet to 'open' local NAT(s) and stateful firewalls + rendezvousWith->attemptToContactAt(tPtr,_path->localSocket(),atAddr,RR->node->now(),false,0); TRACE("RENDEZVOUS from %s says %s might be at %s, sent verification attempt",peer->address().toString().c_str(),with.toString().c_str(),atAddr.toString().c_str()); } else { TRACE("RENDEZVOUS from %s says %s might be at %s, ignoring since path is not suitable",peer->address().toString().c_str(),with.toString().c_str(),atAddr.toString().c_str()); @@ -1197,7 +1197,7 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPt if ( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH) == 0) && // not being told to forget (!( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) == 0) && (peer->hasActivePathTo(now,a)) )) && // not already known - (RR->node->shouldUsePathForZeroTierTraffic(tPtr,peer->address(),_path->localAddress(),a)) ) // should use path + (RR->node->shouldUsePathForZeroTierTraffic(tPtr,peer->address(),_path->localSocket(),a)) ) // should use path { //if ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) != 0) // peer->setClusterPreferred(a); @@ -1214,7 +1214,7 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPt if ( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH) == 0) && // not being told to forget (!( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) == 0) && (peer->hasActivePathTo(now,a)) )) && // not already known - (RR->node->shouldUsePathForZeroTierTraffic(tPtr,peer->address(),_path->localAddress(),a)) ) // should use path + (RR->node->shouldUsePathForZeroTierTraffic(tPtr,peer->address(),_path->localSocket(),a)) ) // should use path { //if ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) != 0) // peer->setClusterPreferred(a); diff --git a/node/Node.cpp b/node/Node.cpp index 4ffe496c..4b598f61 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -47,8 +47,6 @@ #include "SelfAwareness.hpp" #include "Network.hpp" -const struct sockaddr_storage ZT_SOCKADDR_NULL = {0}; - namespace ZeroTier { /****************************************************************************/ @@ -137,114 +135,17 @@ Node::~Node() delete RR->sw; } -ZT_ResultCode Node::processStateUpdate( - void *tptr, - ZT_StateObjectType type, - const uint64_t id[2], - const void *data, - unsigned int len) -{ - ZT_ResultCode r = ZT_RESULT_OK_IGNORED; - switch(type) { - - case ZT_STATE_OBJECT_PEER_STATE: - if (len) { - const SharedPtr p(RR->topology->getPeer(tptr,Address(id[0]))); - if (p) { - r = (p->applyStateUpdate(data,len)) ? ZT_RESULT_OK : ZT_RESULT_OK_IGNORED; - } else { - r = (Peer::createFromStateUpdate(RR,tptr,data,len)) ? ZT_RESULT_OK : ZT_RESULT_OK_IGNORED; - } - } - break; - - case ZT_STATE_OBJECT_NETWORK_CONFIG: - if (len <= (ZT_NETWORKCONFIG_DICT_CAPACITY - 1)) { - if (len < 2) { - Mutex::Lock _l(_networks_m); - SharedPtr &nw = _networks[id[0]]; - if (!nw) { - nw = SharedPtr(new Network(RR,tptr,id[0],(void *)0,(const NetworkConfig *)0)); - r = ZT_RESULT_OK; - } - } else { - Dictionary *dict = new Dictionary(reinterpret_cast(data),len); - try { - NetworkConfig *nconf = new NetworkConfig(); - try { - if (nconf->fromDictionary(*dict)) { - Mutex::Lock _l(_networks_m); - SharedPtr &nw = _networks[id[0]]; - if (nw) { - switch (nw->setConfiguration(tptr,*nconf,false)) { - default: - r = ZT_RESULT_ERROR_BAD_PARAMETER; - break; - case 1: - r = ZT_RESULT_OK_IGNORED; - break; - case 2: - r = ZT_RESULT_OK; - break; - } - } else { - nw = SharedPtr(new Network(RR,tptr,id[0],(void *)0,nconf)); - } - } else { - r = ZT_RESULT_ERROR_BAD_PARAMETER; - } - } catch ( ... ) { - r = ZT_RESULT_ERROR_BAD_PARAMETER; - } - delete nconf; - } catch ( ... ) { - r = ZT_RESULT_ERROR_BAD_PARAMETER; - } - delete dict; - } - } else { - r = ZT_RESULT_ERROR_BAD_PARAMETER; - } - break; - - case ZT_STATE_OBJECT_NETWORK_MEMBERSHIP: - if (len) { - } - break; - - case ZT_STATE_OBJECT_PLANET: - case ZT_STATE_OBJECT_MOON: - if ((len)&&(len <= ZT_WORLD_MAX_SERIALIZED_LENGTH)) { - World w; - try { - w.deserialize(Buffer(data,len)); - if (( (w.type() == World::TYPE_MOON)&&(type == ZT_STATE_OBJECT_MOON) )||( (w.type() == World::TYPE_PLANET)&&(type == ZT_STATE_OBJECT_PLANET) )) { - r = (RR->topology->addWorld(tptr,w,false)) ? ZT_RESULT_OK : ZT_RESULT_OK_IGNORED; - } - } catch ( ... ) { - r = ZT_RESULT_ERROR_BAD_PARAMETER; - } - } else { - r = ZT_RESULT_ERROR_BAD_PARAMETER; - } - break; - - default: break; - } - return r; -} - ZT_ResultCode Node::processWirePacket( void *tptr, uint64_t now, - const struct sockaddr_storage *localAddress, + int64_t localSocket, const struct sockaddr_storage *remoteAddress, const void *packetData, unsigned int packetLength, volatile uint64_t *nextBackgroundTaskDeadline) { _now = now; - RR->sw->onRemotePacket(tptr,*(reinterpret_cast(localAddress)),*(reinterpret_cast(remoteAddress)),packetData,packetLength); + RR->sw->onRemotePacket(tptr,localSocket,*(reinterpret_cast(remoteAddress)),packetData,packetLength); return ZT_RESULT_OK; } @@ -317,7 +218,7 @@ public: if ((!contacted)&&(_bestCurrentUpstream)) { const SharedPtr up(_bestCurrentUpstream->getBestPath(_now,true)); if (up) - p->sendHELLO(_tPtr,up->localAddress(),up->address(),_now,up->nextOutgoingCounter()); + p->sendHELLO(_tPtr,up->localSocket(),up->address(),_now,up->nextOutgoingCounter()); } lastReceiveFromUpstream = std::max(p->lastReceive(),lastReceiveFromUpstream); @@ -617,7 +518,7 @@ void Node::setNetconfMaster(void *networkControllerInstance) /* Node methods used only within node/ */ /****************************************************************************/ -bool Node::shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,const InetAddress &localAddress,const InetAddress &remoteAddress) +bool Node::shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,const int64_t localSocket,const InetAddress &remoteAddress) { if (!Path::isAddressValidForPath(remoteAddress)) return false; @@ -640,7 +541,7 @@ bool Node::shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,cons } } - return ( (_cb.pathCheckFunction) ? (_cb.pathCheckFunction(reinterpret_cast(this),_uPtr,tPtr,ztaddr.toInt(),reinterpret_cast(&localAddress),reinterpret_cast(&remoteAddress)) != 0) : true); + return ( (_cb.pathCheckFunction) ? (_cb.pathCheckFunction(reinterpret_cast(this),_uPtr,tPtr,ztaddr.toInt(),localSocket,reinterpret_cast(&remoteAddress)) != 0) : true); } #ifdef ZT_TRACE @@ -837,35 +738,18 @@ void ZT_Node_delete(ZT_Node *node) } catch ( ... ) {} } -enum ZT_ResultCode ZT_Node_processStateUpdate( - ZT_Node *node, - void *tptr, - ZT_StateObjectType type, - const uint64_t id[2], - const void *data, - unsigned int len) -{ - try { - return reinterpret_cast(node)->processStateUpdate(tptr,type,id,data,len); - } catch (std::bad_alloc &exc) { - return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; - } catch ( ... ) { - return ZT_RESULT_FATAL_ERROR_INTERNAL; - } -} - enum ZT_ResultCode ZT_Node_processWirePacket( ZT_Node *node, void *tptr, uint64_t now, - const struct sockaddr_storage *localAddress, + int64_t localSocket, const struct sockaddr_storage *remoteAddress, const void *packetData, unsigned int packetLength, volatile uint64_t *nextBackgroundTaskDeadline) { try { - return reinterpret_cast(node)->processWirePacket(tptr,now,localAddress,remoteAddress,packetData,packetLength,nextBackgroundTaskDeadline); + return reinterpret_cast(node)->processWirePacket(tptr,now,localSocket,remoteAddress,packetData,packetLength,nextBackgroundTaskDeadline); } catch (std::bad_alloc &exc) { return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; } catch ( ... ) { diff --git a/node/Node.hpp b/node/Node.hpp index 17050d24..55491b06 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -82,16 +82,10 @@ public: // Public API Functions ---------------------------------------------------- - ZT_ResultCode processStateUpdate( - void *tptr, - ZT_StateObjectType type, - const uint64_t id[2], - const void *data, - unsigned int len); ZT_ResultCode processWirePacket( void *tptr, uint64_t now, - const struct sockaddr_storage *localAddress, + int64_t localSocket, const struct sockaddr_storage *remoteAddress, const void *packetData, unsigned int packetLength, @@ -129,13 +123,13 @@ public: inline uint64_t now() const throw() { return _now; } - inline bool putPacket(void *tPtr,const InetAddress &localAddress,const InetAddress &addr,const void *data,unsigned int len,unsigned int ttl = 0) + inline bool putPacket(void *tPtr,const int64_t localSocket,const InetAddress &addr,const void *data,unsigned int len,unsigned int ttl = 0) { return (_cb.wirePacketSendFunction( reinterpret_cast(this), _uPtr, tPtr, - reinterpret_cast(&localAddress), + localSocket, reinterpret_cast(&addr), data, len, @@ -205,7 +199,7 @@ public: void postTrace(const char *module,unsigned int line,const char *fmt,...); #endif - bool shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,const InetAddress &localAddress,const InetAddress &remoteAddress); + bool shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,const int64_t localSocket,const InetAddress &remoteAddress); inline bool externalPathLookup(void *tPtr,const Address &ztaddr,int family,InetAddress &addr) { return ( (_cb.pathLookupFunction) ? (_cb.pathLookupFunction(reinterpret_cast(this),_uPtr,tPtr,ztaddr.toInt(),family,reinterpret_cast(&addr)) != 0) : false ); } uint64_t prng(); diff --git a/node/Path.cpp b/node/Path.cpp index a5fe1aa7..9dc9aba5 100644 --- a/node/Path.cpp +++ b/node/Path.cpp @@ -32,7 +32,7 @@ namespace ZeroTier { bool Path::send(const RuntimeEnvironment *RR,void *tPtr,const void *data,unsigned int len,uint64_t now) { - if (RR->node->putPacket(tPtr,_localAddress,address(),data,len)) { + if (RR->node->putPacket(tPtr,_localSocket,_addr,data,len)) { _lastOut = now; return true; } diff --git a/node/Path.hpp b/node/Path.hpp index a6f56d31..854b28e2 100644 --- a/node/Path.hpp +++ b/node/Path.hpp @@ -66,49 +66,28 @@ public: public: HashKey() {} - HashKey(const InetAddress &l,const InetAddress &r) + HashKey(const int64_t l,const InetAddress &r) { - // This is an ad-hoc bit packing algorithm to yield unique keys for - // remote addresses and their local-side counterparts if defined. - // Portability across runtimes is not needed. if (r.ss_family == AF_INET) { _k[0] = (uint64_t)reinterpret_cast(&r)->sin_addr.s_addr; _k[1] = (uint64_t)reinterpret_cast(&r)->sin_port; - if (l.ss_family == AF_INET) { - _k[2] = (uint64_t)reinterpret_cast(&l)->sin_addr.s_addr; - _k[3] = (uint64_t)reinterpret_cast(&r)->sin_port; - } else { - _k[2] = 0; - _k[3] = 0; - } + _k[2] = (uint64_t)l; } else if (r.ss_family == AF_INET6) { - const uint8_t *a = reinterpret_cast(reinterpret_cast(&r)->sin6_addr.s6_addr); - uint8_t *b = reinterpret_cast(_k); - for(unsigned int i=0;i<16;++i) b[i] = a[i]; - _k[2] = ~((uint64_t)reinterpret_cast(&r)->sin6_port); - if (l.ss_family == AF_INET6) { - _k[2] ^= ((uint64_t)reinterpret_cast(&r)->sin6_port) << 32; - a = reinterpret_cast(reinterpret_cast(&l)->sin6_addr.s6_addr); - b += 24; - for(unsigned int i=0;i<8;++i) b[i] = a[i]; - a += 8; - for(unsigned int i=0;i<8;++i) b[i] ^= a[i]; - } + memcpy(_k,reinterpret_cast(&r)->sin6_addr.s6_addr,16); + _k[2] = ((uint64_t)reinterpret_cast(&r)->sin6_port << 32) ^ (uint64_t)l; } else { - _k[0] = 0; - _k[1] = 0; - _k[2] = 0; - _k[3] = 0; + memcpy(_k,&r,std::min(sizeof(_k),sizeof(InetAddress))); + _k[2] += (uint64_t)l; } } - inline unsigned long hashCode() const { return (unsigned long)(_k[0] + _k[1] + _k[2] + _k[3]); } + inline unsigned long hashCode() const { return (unsigned long)(_k[0] + _k[1] + _k[2]); } - inline bool operator==(const HashKey &k) const { return ( (_k[0] == k._k[0]) && (_k[1] == k._k[1]) && (_k[2] == k._k[2]) && (_k[3] == k._k[3]) ); } + inline bool operator==(const HashKey &k) const { return ( (_k[0] == k._k[0]) && (_k[1] == k._k[1]) && (_k[2] == k._k[2]) ); } inline bool operator!=(const HashKey &k) const { return (!(*this == k)); } private: - uint64_t _k[4]; + uint64_t _k[3]; }; Path() : @@ -116,29 +95,29 @@ public: _lastIn(0), _lastTrustEstablishedPacketReceived(0), _incomingLinkQualityFastLog(0xffffffffffffffffULL), + _localSocket(-1), _incomingLinkQualitySlowLogPtr(0), _incomingLinkQualitySlowLogCounter(-64), // discard first fast log _incomingLinkQualityPreviousPacketCounter(0), _outgoingPacketCounter(0), _addr(), - _localAddress(), _ipScope(InetAddress::IP_SCOPE_NONE) { for(int i=0;i<(int)sizeof(_incomingLinkQualitySlowLog);++i) _incomingLinkQualitySlowLog[i] = ZT_PATH_LINK_QUALITY_MAX; } - Path(const InetAddress &localAddress,const InetAddress &addr) : + Path(const int64_t localSocket,const InetAddress &addr) : _lastOut(0), _lastIn(0), _lastTrustEstablishedPacketReceived(0), _incomingLinkQualityFastLog(0xffffffffffffffffULL), + _localSocket(localSocket), _incomingLinkQualitySlowLogPtr(0), _incomingLinkQualitySlowLogCounter(-64), // discard first fast log _incomingLinkQualityPreviousPacketCounter(0), _outgoingPacketCounter(0), _addr(addr), - _localAddress(localAddress), _ipScope(addr.ipScope()) { for(int i=0;i<(int)sizeof(_incomingLinkQualitySlowLog);++i) @@ -210,9 +189,9 @@ public: inline void sent(const uint64_t t) { _lastOut = t; } /** - * @return Address of local side of this path or NULL if unspecified + * @return Local socket as specified by external code */ - inline const InetAddress &localAddress() const { return _localAddress; } + inline const int64_t localSocket() const { return _localSocket; } /** * @return Physical address @@ -328,12 +307,12 @@ private: volatile uint64_t _lastIn; volatile uint64_t _lastTrustEstablishedPacketReceived; volatile uint64_t _incomingLinkQualityFastLog; + int64_t _localSocket; volatile unsigned long _incomingLinkQualitySlowLogPtr; volatile signed int _incomingLinkQualitySlowLogCounter; volatile unsigned int _incomingLinkQualityPreviousPacketCounter; volatile unsigned int _outgoingPacketCounter; InetAddress _addr; - InetAddress _localAddress; InetAddress::IpScope _ipScope; // memoize this since it's a computed value checked often volatile uint8_t _incomingLinkQualitySlowLog[32]; AtomicCounter __refCount; diff --git a/node/Peer.cpp b/node/Peer.cpp index 18d05875..875d651e 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -154,25 +154,21 @@ void Peer::received( if ((path->address().ss_family == AF_INET)&&(_v4Path.p)) { const struct sockaddr_in *const r = reinterpret_cast(&(path->address())); const struct sockaddr_in *const l = reinterpret_cast(&(_v4Path.p->address())); - const struct sockaddr_in *const rl = reinterpret_cast(&(path->localAddress())); - const struct sockaddr_in *const ll = reinterpret_cast(&(_v4Path.p->localAddress())); - if ((r->sin_addr.s_addr == l->sin_addr.s_addr)&&(r->sin_port == l->sin_port)&&(rl->sin_addr.s_addr == ll->sin_addr.s_addr)&&(rl->sin_port == ll->sin_port)) { + if ((r->sin_addr.s_addr == l->sin_addr.s_addr)&&(r->sin_port == l->sin_port)&&(path->localSocket() == _v4Path.p->localSocket())) { _v4Path.lr = now; pathAlreadyKnown = true; } } else if ((path->address().ss_family == AF_INET6)&&(_v6Path.p)) { const struct sockaddr_in6 *const r = reinterpret_cast(&(path->address())); const struct sockaddr_in6 *const l = reinterpret_cast(&(_v6Path.p->address())); - const struct sockaddr_in6 *const rl = reinterpret_cast(&(path->localAddress())); - const struct sockaddr_in6 *const ll = reinterpret_cast(&(_v6Path.p->localAddress())); - if ((!memcmp(r->sin6_addr.s6_addr,l->sin6_addr.s6_addr,16))&&(r->sin6_port == l->sin6_port)&&(!memcmp(rl->sin6_addr.s6_addr,ll->sin6_addr.s6_addr,16))&&(rl->sin6_port == ll->sin6_port)) { + if ((!memcmp(r->sin6_addr.s6_addr,l->sin6_addr.s6_addr,16))&&(r->sin6_port == l->sin6_port)&&(path->localSocket() == _v6Path.p->localSocket())) { _v6Path.lr = now; pathAlreadyKnown = true; } } } - if ( (!pathAlreadyKnown) && (RR->node->shouldUsePathForZeroTierTraffic(tPtr,_id.address(),path->localAddress(),path->address())) ) { + if ( (!pathAlreadyKnown) && (RR->node->shouldUsePathForZeroTierTraffic(tPtr,_id.address(),path->localSocket(),path->address())) ) { Mutex::Lock _l(_paths_m); _PeerPath *potentialNewPeerPath = (_PeerPath *)0; if (path->address().ss_family == AF_INET) { @@ -191,7 +187,7 @@ void Peer::received( _lastWroteState = 0; // force state write now } else { TRACE("got %s via unknown path %s(%s), confirming...",Packet::verbString(verb),_id.address().toString().c_str(),path->address().toString().c_str()); - attemptToContactAt(tPtr,path->localAddress(),path->address(),now,true,path->nextOutgoingCounter()); + attemptToContactAt(tPtr,path->localSocket(),path->address(),now,true,path->nextOutgoingCounter()); path->sent(now); } } @@ -318,7 +314,7 @@ SharedPtr Peer::getBestPath(uint64_t now,bool includeExpired) return SharedPtr(); } -void Peer::sendHELLO(void *tPtr,const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,unsigned int counter) +void Peer::sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,uint64_t now,unsigned int counter) { Packet outp(_id.address(),RR->identity.address(),Packet::VERB_HELLO); @@ -360,21 +356,21 @@ void Peer::sendHELLO(void *tPtr,const InetAddress &localAddr,const InetAddress & if (atAddress) { outp.armor(_key,false,counter); // false == don't encrypt full payload, but add MAC - RR->node->putPacket(tPtr,localAddr,atAddress,outp.data(),outp.size()); + RR->node->putPacket(tPtr,localSocket,atAddress,outp.data(),outp.size()); } else { RR->sw->send(tPtr,outp,false); // false == don't encrypt full payload, but add MAC } } -void Peer::attemptToContactAt(void *tPtr,const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,bool sendFullHello,unsigned int counter) +void Peer::attemptToContactAt(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,uint64_t now,bool sendFullHello,unsigned int counter) { if ( (!sendFullHello) && (_vProto >= 5) && (!((_vMajor == 1)&&(_vMinor == 1)&&(_vRevision == 0))) ) { Packet outp(_id.address(),RR->identity.address(),Packet::VERB_ECHO); RR->node->expectReplyTo(outp.packetId()); outp.armor(_key,true,counter); - RR->node->putPacket(tPtr,localAddr,atAddress,outp.data(),outp.size()); + RR->node->putPacket(tPtr,localSocket,atAddress,outp.data(),outp.size()); } else { - sendHELLO(tPtr,localAddr,atAddress,now,counter); + sendHELLO(tPtr,localSocket,atAddress,now,counter); } } @@ -402,13 +398,13 @@ bool Peer::doPingAndKeepalive(void *tPtr,uint64_t now,int inetAddressFamily) if (v6lr > v4lr) { if ( ((now - _v6Path.lr) >= ZT_PEER_PING_PERIOD) || (_v6Path.p->needsHeartbeat(now)) ) { - attemptToContactAt(tPtr,_v6Path.p->localAddress(),_v6Path.p->address(),now,false,_v6Path.p->nextOutgoingCounter()); + attemptToContactAt(tPtr,_v6Path.p->localSocket(),_v6Path.p->address(),now,false,_v6Path.p->nextOutgoingCounter()); _v6Path.p->sent(now); return true; } } else if (v4lr) { if ( ((now - _v4Path.lr) >= ZT_PEER_PING_PERIOD) || (_v4Path.p->needsHeartbeat(now)) ) { - attemptToContactAt(tPtr,_v4Path.p->localAddress(),_v4Path.p->address(),now,false,_v4Path.p->nextOutgoingCounter()); + attemptToContactAt(tPtr,_v4Path.p->localSocket(),_v4Path.p->address(),now,false,_v4Path.p->nextOutgoingCounter()); _v4Path.p->sent(now); return true; } @@ -416,13 +412,13 @@ bool Peer::doPingAndKeepalive(void *tPtr,uint64_t now,int inetAddressFamily) } else { if ( (inetAddressFamily == AF_INET) && ((now - _v4Path.lr) < ZT_PEER_PATH_EXPIRATION) ) { if ( ((now - _v4Path.lr) >= ZT_PEER_PING_PERIOD) || (_v4Path.p->needsHeartbeat(now)) ) { - attemptToContactAt(tPtr,_v4Path.p->localAddress(),_v4Path.p->address(),now,false,_v4Path.p->nextOutgoingCounter()); + attemptToContactAt(tPtr,_v4Path.p->localSocket(),_v4Path.p->address(),now,false,_v4Path.p->nextOutgoingCounter()); _v4Path.p->sent(now); return true; } } else if ( (inetAddressFamily == AF_INET6) && ((now - _v6Path.lr) < ZT_PEER_PATH_EXPIRATION) ) { if ( ((now - _v6Path.lr) >= ZT_PEER_PING_PERIOD) || (_v6Path.p->needsHeartbeat(now)) ) { - attemptToContactAt(tPtr,_v6Path.p->localAddress(),_v6Path.p->address(),now,false,_v6Path.p->nextOutgoingCounter()); + attemptToContactAt(tPtr,_v6Path.p->localSocket(),_v6Path.p->address(),now,false,_v6Path.p->nextOutgoingCounter()); _v6Path.p->sent(now); return true; } @@ -456,7 +452,6 @@ void Peer::writeState(void *tPtr,const uint64_t now) b.append(_v4Path.p->lastIn()); b.append(_v4Path.p->lastTrustEstablishedPacketReceived()); _v4Path.p->address().serialize(b); - _v4Path.p->localAddress().serialize(b); } if (_v6Path.lr) { b.append(_v6Path.lr); @@ -464,7 +459,6 @@ void Peer::writeState(void *tPtr,const uint64_t now) b.append(_v6Path.p->lastIn()); b.append(_v6Path.p->lastTrustEstablishedPacketReceived()); _v6Path.p->address().serialize(b); - _v6Path.p->localAddress().serialize(b); } } @@ -491,7 +485,7 @@ void Peer::writeState(void *tPtr,const uint64_t now) uint64_t tmp[2]; tmp[0] = _id.address().toInt(); tmp[1] = 0; - RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_PEER_STATE,tmp,b.data(),b.size()); + //RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_PEER_STATE,tmp,b.data(),b.size()); _lastWroteState = now; } catch ( ... ) {} // sanity check, should not be possible @@ -522,22 +516,19 @@ bool Peer::applyStateUpdate(const void *data,unsigned int len) const uint64_t lastOut = b.at(ptr); ptr += 8; const uint64_t lastIn = b.at(ptr); ptr += 8; const uint64_t lastTrustEstablishedPacketReceived = b.at(ptr); ptr += 8; - InetAddress addr,localAddr; + InetAddress addr; ptr += addr.deserialize(b,ptr); - ptr += localAddr.deserialize(b,ptr); - if (addr.ss_family == localAddr.ss_family) { - _PeerPath *p = (_PeerPath *)0; - switch(addr.ss_family) { - case AF_INET: p = &_v4Path; break; - case AF_INET6: p = &_v6Path; break; - } - if (p) { - if ( (!p->p) || ((p->p->address() != addr)||(p->p->localAddress() != localAddr)) ) { - p->p = RR->topology->getPath(localAddr,addr); - } - p->lr = lr; - p->p->updateFromRemoteState(lastOut,lastIn,lastTrustEstablishedPacketReceived); + _PeerPath *p = (_PeerPath *)0; + switch(addr.ss_family) { + case AF_INET: p = &_v4Path; break; + case AF_INET6: p = &_v6Path; break; + } + if (p) { + if ( (!p->p) || (p->p->address() != addr) ) { + p->p = RR->topology->getPath(-1,addr); } + p->lr = lr; + p->p->updateFromRemoteState(lastOut,lastIn,lastTrustEstablishedPacketReceived); } } } diff --git a/node/Peer.hpp b/node/Peer.hpp index f0eb3ee8..478c7232 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -154,12 +154,12 @@ public: * No statistics or sent times are updated here. * * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call - * @param localAddr Local address + * @param localSocket Local source socket * @param atAddress Destination address * @param now Current time * @param counter Outgoing packet counter */ - void sendHELLO(void *tPtr,const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,unsigned int counter); + void sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,uint64_t now,unsigned int counter); /** * Send ECHO (or HELLO for older peers) to this peer at the given address @@ -167,13 +167,13 @@ public: * No statistics or sent times are updated here. * * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call - * @param localAddr Local address + * @param localSocket Local source socket * @param atAddress Destination address * @param now Current time * @param sendFullHello If true, always send a full HELLO instead of just an ECHO * @param counter Outgoing packet counter */ - void attemptToContactAt(void *tPtr,const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,bool sendFullHello,unsigned int counter); + void attemptToContactAt(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,uint64_t now,bool sendFullHello,unsigned int counter); /** * Try a memorized or statically defined path if any are known @@ -227,11 +227,11 @@ public: { Mutex::Lock _l(_paths_m); if ((inetAddressFamily == AF_INET)&&(_v4Path.lr)&&(_v4Path.p->address().ipScope() == scope)) { - attemptToContactAt(tPtr,_v4Path.p->localAddress(),_v4Path.p->address(),now,false,_v4Path.p->nextOutgoingCounter()); + attemptToContactAt(tPtr,_v4Path.p->localSocket(),_v4Path.p->address(),now,false,_v4Path.p->nextOutgoingCounter()); _v4Path.p->sent(now); _v4Path.lr = 0; // path will not be used unless it speaks again } else if ((inetAddressFamily == AF_INET6)&&(_v6Path.lr)&&(_v6Path.p->address().ipScope() == scope)) { - attemptToContactAt(tPtr,_v6Path.p->localAddress(),_v6Path.p->address(),now,false,_v6Path.p->nextOutgoingCounter()); + attemptToContactAt(tPtr,_v6Path.p->localSocket(),_v6Path.p->address(),now,false,_v6Path.p->nextOutgoingCounter()); _v6Path.p->sent(now); _v6Path.lr = 0; // path will not be used unless it speaks again } diff --git a/node/RuntimeEnvironment.hpp b/node/RuntimeEnvironment.hpp index ee0c8c24..99afe25d 100644 --- a/node/RuntimeEnvironment.hpp +++ b/node/RuntimeEnvironment.hpp @@ -67,6 +67,11 @@ public: Utils::burn(reinterpret_cast(const_cast(secretIdentityStr.data())),(unsigned int)secretIdentityStr.length()); } + /** + * A random integer identifying this running instance in a cluster + */ + uint64_t instanceId; + // Node instance that owns this RuntimeEnvironment Node *const node; @@ -90,11 +95,6 @@ public: Multicaster *mc; Topology *topology; SelfAwareness *sa; - - /** - * A random integer identifying this run of ZeroTier - */ - uint32_t instanceId; }; } // namespace ZeroTier diff --git a/node/SelfAwareness.cpp b/node/SelfAwareness.cpp index c5daddc3..3e3397f5 100644 --- a/node/SelfAwareness.cpp +++ b/node/SelfAwareness.cpp @@ -69,7 +69,7 @@ SelfAwareness::SelfAwareness(const RuntimeEnvironment *renv) : { } -void SelfAwareness::iam(void *tPtr,const Address &reporter,const InetAddress &receivedOnLocalAddress,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,uint64_t now) +void SelfAwareness::iam(void *tPtr,const Address &reporter,const int64_t receivedOnLocalSocket,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,uint64_t now) { const InetAddress::IpScope scope = myPhysicalAddress.ipScope(); @@ -77,7 +77,7 @@ void SelfAwareness::iam(void *tPtr,const Address &reporter,const InetAddress &re return; Mutex::Lock _l(_phy_m); - PhySurfaceEntry &entry = _phy[PhySurfaceKey(reporter,receivedOnLocalAddress,reporterPhysicalAddress,scope)]; + PhySurfaceEntry &entry = _phy[PhySurfaceKey(reporter,receivedOnLocalSocket,reporterPhysicalAddress,scope)]; if ( (trusted) && ((now - entry.ts) < ZT_SELFAWARENESS_ENTRY_TIMEOUT) && (!entry.mySurface.ipsEqual(myPhysicalAddress)) ) { // Changes to external surface reported by trusted peers causes path reset in this scope diff --git a/node/SelfAwareness.hpp b/node/SelfAwareness.hpp index 63c416bf..35e0ad39 100644 --- a/node/SelfAwareness.hpp +++ b/node/SelfAwareness.hpp @@ -55,7 +55,7 @@ public: * @param trusted True if this peer is trusted as an authority to inform us of external address changes * @param now Current time */ - void iam(void *tPtr,const Address &reporter,const InetAddress &receivedOnLocalAddress,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,uint64_t now); + void iam(void *tPtr,const Address &reporter,const int64_t receivedOnLocalSocket,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,uint64_t now); /** * Clean up database periodically @@ -75,15 +75,15 @@ private: struct PhySurfaceKey { Address reporter; - InetAddress receivedOnLocalAddress; + int64_t receivedOnLocalSocket; InetAddress reporterPhysicalAddress; InetAddress::IpScope scope; PhySurfaceKey() : reporter(),scope(InetAddress::IP_SCOPE_NONE) {} - PhySurfaceKey(const Address &r,const InetAddress &rol,const InetAddress &ra,InetAddress::IpScope s) : reporter(r),receivedOnLocalAddress(rol),reporterPhysicalAddress(ra),scope(s) {} + PhySurfaceKey(const Address &r,const int64_t rol,const InetAddress &ra,InetAddress::IpScope s) : reporter(r),receivedOnLocalSocket(rol),reporterPhysicalAddress(ra),scope(s) {} - inline unsigned long hashCode() const throw() { return ((unsigned long)reporter.toInt() + (unsigned long)scope); } - inline bool operator==(const PhySurfaceKey &k) const throw() { return ((reporter == k.reporter)&&(receivedOnLocalAddress == k.receivedOnLocalAddress)&&(reporterPhysicalAddress == k.reporterPhysicalAddress)&&(scope == k.scope)); } + inline unsigned long hashCode() const { return ((unsigned long)reporter.toInt() + (unsigned long)scope); } + inline bool operator==(const PhySurfaceKey &k) const { return ((reporter == k.reporter)&&(receivedOnLocalSocket == k.receivedOnLocalSocket)&&(reporterPhysicalAddress == k.reporterPhysicalAddress)&&(scope == k.scope)); } }; struct PhySurfaceEntry { diff --git a/node/Switch.cpp b/node/Switch.cpp index cbd73a83..a77ca89e 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -71,12 +71,12 @@ Switch::Switch(const RuntimeEnvironment *renv) : { } -void Switch::onRemotePacket(void *tPtr,const InetAddress &localAddr,const InetAddress &fromAddr,const void *data,unsigned int len) +void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddress &fromAddr,const void *data,unsigned int len) { try { const uint64_t now = RR->node->now(); - SharedPtr path(RR->topology->getPath(localAddr,fromAddr)); + SharedPtr path(RR->topology->getPath(localSocket,fromAddr)); path->received(now); if (len == 13) { @@ -88,7 +88,7 @@ void Switch::onRemotePacket(void *tPtr,const InetAddress &localAddr,const InetAd const Address beaconAddr(reinterpret_cast(data) + 8,5); if (beaconAddr == RR->identity.address()) return; - if (!RR->node->shouldUsePathForZeroTierTraffic(tPtr,beaconAddr,localAddr,fromAddr)) + if (!RR->node->shouldUsePathForZeroTierTraffic(tPtr,beaconAddr,localSocket,fromAddr)) return; const SharedPtr peer(RR->topology->getPeer(tPtr,beaconAddr)); if (peer) { // we'll only respond to beacons from known peers @@ -752,7 +752,7 @@ bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt) viaPath = peer->getBestPath(now,false); if ( (viaPath) && (!viaPath->alive(now)) && (!RR->topology->isUpstream(peer->identity())) ) { if ((now - viaPath->lastOut()) > std::max((now - viaPath->lastIn()) * 4,(uint64_t)ZT_PATH_MIN_REACTIVATE_INTERVAL)) { - peer->attemptToContactAt(tPtr,viaPath->localAddress(),viaPath->address(),now,false,viaPath->nextOutgoingCounter()); + peer->attemptToContactAt(tPtr,viaPath->localSocket(),viaPath->address(),now,false,viaPath->nextOutgoingCounter()); viaPath->sent(now); } viaPath.zero(); diff --git a/node/Switch.hpp b/node/Switch.hpp index 9793dd45..cebe9e67 100644 --- a/node/Switch.hpp +++ b/node/Switch.hpp @@ -68,12 +68,12 @@ public: * Called when a packet is received from the real network * * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call - * @param localAddr Local interface address + * @param localSocket Local I/O socket as supplied by external code * @param fromAddr Internet IP address of origin * @param data Packet data * @param len Packet length */ - void onRemotePacket(void *tPtr,const InetAddress &localAddr,const InetAddress &fromAddr,const void *data,unsigned int len); + void onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddress &fromAddr,const void *data,unsigned int len); /** * Called when a packet comes from a local Ethernet tap diff --git a/node/Topology.cpp b/node/Topology.cpp index 09a1a895..d4632f43 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -125,10 +125,11 @@ SharedPtr Topology::getPeer(void *tPtr,const Address &zta) return *ap; } + /* try { char buf[ZT_PEER_MAX_SERIALIZED_STATE_SIZE]; uint64_t idbuf[2]; idbuf[0] = zta.toInt(); idbuf[1] = 0; - int len = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_PEER_STATE,idbuf,buf,(unsigned int)sizeof(buf)); + int len = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_PEER,idbuf,buf,(unsigned int)sizeof(buf)); if (len > 0) { Mutex::Lock _l(_peers_m); SharedPtr &ap = _peers[zta]; @@ -140,6 +141,7 @@ SharedPtr Topology::getPeer(void *tPtr,const Address &zta) return ap; } } catch ( ... ) {} // ignore invalid identities or other strage failures + */ return SharedPtr(); } diff --git a/node/Topology.hpp b/node/Topology.hpp index 32e38dd3..5f3e2da1 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -110,11 +110,11 @@ public: /** * Get a Path object for a given local and remote physical address, creating if needed * - * @param l Local address or NULL for 'any' or 'wildcard' + * @param l Local socket * @param r Remote address * @return Pointer to canonicalized Path object */ - inline SharedPtr getPath(const InetAddress &l,const InetAddress &r) + inline SharedPtr getPath(const int64_t l,const InetAddress &r) { Mutex::Lock _l(_paths_m); SharedPtr &p = _paths[Path::HashKey(l,r)]; diff --git a/osdep/Binder.hpp b/osdep/Binder.hpp index b1fe5921..040f3e46 100644 --- a/osdep/Binder.hpp +++ b/osdep/Binder.hpp @@ -88,11 +88,7 @@ class Binder : NonCopyable private: struct _Binding { - _Binding() : - udpSock((PhySocket *)0), - tcpListenSock((PhySocket *)0), - address() {} - + _Binding() : udpSock((PhySocket *)0),tcpListenSock((PhySocket *)0) {} PhySocket *udpSock; PhySocket *tcpListenSock; InetAddress address; @@ -373,93 +369,6 @@ public: _bindings.swap(newBindings); } - /** - * Send a UDP packet from the specified local interface, or all - * - * Unfortunately even by examining the routing table there is no ultimately - * robust way to tell where we might reach another host that works in all - * environments. As a result, we send packets with null (wildcard) local - * addresses from *every* bound interface. - * - * These are typically initial HELLOs, path probes, etc., since normal - * conversations will have a local endpoint address. So the cost is low and - * if the peer is not reachable via that route then the packet will go - * nowhere and nothing will happen. - * - * It will of course only send via interface bindings of the same socket - * family. No point in sending V4 via V6 or vice versa. - * - * In any case on most hosts there's only one or two interfaces that we - * will use, so none of this is particularly costly. - * - * @param local Local interface address or null address for 'all' - * @param remote Remote address - * @param data Data to send - * @param len Length of data - * @param v4ttl If non-zero, send this packet with the specified IP TTL (IPv4 only) - * @return -1 == local doesn't match any bound address, 0 == send failure, 1 == send successful - */ - template - inline int udpSend(Phy &phy,const InetAddress &local,const InetAddress &remote,const void *data,unsigned int len,unsigned int v4ttl = 0) const - { - PhySocket *s; - typename std::vector<_Binding>::const_iterator i; - int result; - Mutex::Lock _l(_lock); - - if (remote.ss_family == AF_INET) { - if (local) { - for(i=_bindings.begin();i!=_bindings.end();++i) { - if ( - (i->address.ss_family == AF_INET) && - (reinterpret_cast(&(i->address))->sin_port == reinterpret_cast(&local)->sin_port) && - (reinterpret_cast(&(i->address))->sin_addr.s_addr == reinterpret_cast(&local)->sin_addr.s_addr) - ) - { - s = i->udpSock; - goto Binder_send_packet; - } - } - } else { - for(i=_bindings.begin();i!=_bindings.end();++i) { - if (i->address.ss_family == AF_INET) { - s = i->udpSock; - goto Binder_send_packet; - } - } - } - } else { - if (local) { - for(i=_bindings.begin();i!=_bindings.end();++i) { - if ( - (i->address.ss_family == AF_INET6) && - (reinterpret_cast(&(i->address))->sin6_port == reinterpret_cast(&local)->sin6_port) && - (!memcmp(reinterpret_cast(&(i->address))->sin6_addr.s6_addr,reinterpret_cast(&local)->sin6_addr.s6_addr,16)) - ) - { - s = i->udpSock; - goto Binder_send_packet; - } - } - } else { - for(i=_bindings.begin();i!=_bindings.end();++i) { - if (i->address.ss_family == AF_INET6) { - s = i->udpSock; - goto Binder_send_packet; - } - } - } - } - - return -1; - -Binder_send_packet: - if (v4ttl) phy.setIp4UdpTtl(s,v4ttl); - result = (int)phy.udpSend(s,reinterpret_cast(&remote),data,len); - if (v4ttl) phy.setIp4UdpTtl(s,255); - return result; - } - /** * @return All currently bound local interface addresses */ @@ -472,6 +381,22 @@ Binder_send_packet: return aa; } + /** + * Send from all bound UDP sockets + */ + template + inline bool udpSendAll(Phy &phy,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl) + { + bool r = false; + Mutex::Lock _l(_lock); + for(std::vector<_Binding>::const_iterator b(_bindings.begin());b!=_bindings.end();++b) { + if (ttl) phy.setIp4UdpTtl(b->udpSock,ttl); + if (phy.udpSend(b->udpSock,(const struct sockaddr *)addr,data,len)) r = true; + if (ttl) phy.setIp4UdpTtl(b->udpSock,255); + } + return r; + } + /** * @param addr Address to check * @return True if this is a bound local interface address diff --git a/service/OneService.cpp b/service/OneService.cpp index b5b11111..6497ae20 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -59,8 +59,6 @@ #include "../osdep/ManagedRoute.hpp" #include "OneService.hpp" -#include "ClusterGeoIpService.hpp" -#include "ClusterDefinition.hpp" #include "SoftwareUpdater.hpp" #ifdef __WINDOWS__ @@ -157,9 +155,6 @@ namespace ZeroTier { typedef BSDEthernetTap EthernetTap; } // Maximum write buffer size for outgoing TCP connections (sanity limit) #define ZT_TCP_MAX_WRITEQ_SIZE 33554432 -// How often to check TCP connections and cluster links and send status to cluster peers -#define ZT_TCP_CHECK_PERIOD 15000 - // TCP activity timeout #define ZT_TCP_ACTIVITY_TIMEOUT 60000 @@ -311,9 +306,9 @@ static int SnodeVirtualNetworkConfigFunction(ZT_Node *node,void *uptr,void *tptr static void SnodeEventCallback(ZT_Node *node,void *uptr,void *tptr,enum ZT_Event event,const void *metaData); static void SnodeStatePutFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,const uint64_t id[2],const void *data,int len); static int SnodeStateGetFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,const uint64_t id[2],void *data,unsigned int maxlen); -static int SnodeWirePacketSendFunction(ZT_Node *node,void *uptr,void *tptr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl); +static int SnodeWirePacketSendFunction(ZT_Node *node,void *uptr,void *tptr,int64_t localSocket,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl); static void SnodeVirtualNetworkFrameFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t nwid,void **nuptr,uint64_t sourceMac,uint64_t destMac,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len); -static int SnodePathCheckFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t ztaddr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *remoteAddr); +static int SnodePathCheckFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t ztaddr,int64_t localSocket,const struct sockaddr_storage *remoteAddr); static int SnodePathLookupFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t ztaddr,int family,struct sockaddr_storage *result); static void StapFrameHandler(void *uptr,void *tptr,uint64_t nwid,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len); @@ -362,8 +357,7 @@ struct TcpConnection TCP_UNCATEGORIZED_INCOMING, // uncategorized incoming connection TCP_HTTP_INCOMING, TCP_HTTP_OUTGOING, - TCP_TUNNEL_OUTGOING, // TUNNELED mode proxy outbound connection - TCP_CLUSTER_BACKPLANE + TCP_TUNNEL_OUTGOING // TUNNELED mode proxy outbound connection } type; OneServiceImpl *parent; @@ -380,29 +374,11 @@ struct TcpConnection std::string status; std::map< std::string,std::string > headers; - // Used for cluster backplane connections - uint64_t clusterMemberId; - unsigned int clusterMemberVersionMajor; - unsigned int clusterMemberVersionMinor; - unsigned int clusterMemberVersionRev; - std::vector< InetAddress > clusterMemberLocalAddresses; - Mutex clusterMemberLocalAddresses_m; - std::string readq; std::string writeq; Mutex writeq_m; }; -/** - * Message types for cluster backplane communication - */ -enum ClusterMessageType -{ - CLUSTER_MESSAGE_STATUS = 0, - CLUSTER_MESSAGE_STATE_OBJECT = 1, - CLUSTER_MESSAGE_PROXY_SEND = 2 -}; - class OneServiceImpl : public OneService { public: @@ -421,8 +397,6 @@ public: bool _updateAutoApply; unsigned int _primaryPort; volatile unsigned int _udpPortPickerCounter; - uint64_t _clusterMemberId; - uint8_t _clusterKey[32]; // secret key for cluster backplane config // Local configuration and memo-ized information from it json _localConfig; @@ -434,7 +408,6 @@ public: std::vector< InetAddress > _globalV6Blacklist; std::vector< InetAddress > _allowManagementFrom; std::vector< std::string > _interfacePrefixBlacklist; - std::vector< InetAddress > _clusterBackplaneAddresses; Mutex _localConfig_m; /* @@ -518,7 +491,6 @@ public: ,_updateAutoApply(false) ,_primaryPort(port) ,_udpPortPickerCounter(0) - ,_clusterMemberId(0) ,_lastDirectReceiveFromGlobal(0) #ifdef ZT_TCP_FALLBACK_RELAY ,_lastSendToGlobalV4(0) @@ -754,23 +726,6 @@ public: } } - // Derive the cluster's shared secret backplane encryption key by hashing its shared secret identity - { - uint8_t tmp[64]; - uint8_t sk[ZT_C25519_PRIVATE_KEY_LEN + 4]; - memcpy(sk,_node->identity().privateKeyPair().priv.data,ZT_C25519_PRIVATE_KEY_LEN); - sk[ZT_C25519_PRIVATE_KEY_LEN] = 0xab; - sk[ZT_C25519_PRIVATE_KEY_LEN + 1] = 0xcd; - sk[ZT_C25519_PRIVATE_KEY_LEN + 2] = 0xef; - sk[ZT_C25519_PRIVATE_KEY_LEN + 3] = 0xab; // add an arbitrary nonce, just because - SHA512::hash(tmp,sk,ZT_C25519_PRIVATE_KEY_LEN + 4); - memcpy(_clusterKey,tmp,32); - } - - // Assign a random non-zero cluster member ID to identify vs. other cluster members - Utils::getSecureRandom(&_clusterMemberId,sizeof(_clusterMemberId)); - if (!_clusterMemberId) _clusterMemberId = 1; - // Main I/O loop _nextBackgroundTaskDeadline = 0; uint64_t clockShouldBe = OSUtils::now(); @@ -779,7 +734,6 @@ public: uint64_t lastBindRefresh = 0; uint64_t lastUpdateCheck = clockShouldBe; uint64_t lastLocalInterfaceAddressCheck = (clockShouldBe - ZT_LOCAL_INTERFACE_CHECK_INTERVAL) + 15000; // do this in 15s to give portmapper time to configure and other things time to settle - uint64_t lastTcpCheck = 0; for(;;) { _run_m.lock(); if (!_run) { @@ -873,58 +827,6 @@ public: _node->addLocalInterfaceAddress(reinterpret_cast(&(*i))); } - // Check TCP connections and cluster links - if ((now - lastTcpCheck) >= ZT_TCP_CHECK_PERIOD) { - lastTcpCheck = now; - - // Send status to active cluster links and close overflowed and dead ones - std::vector toClose; - std::vector clusterLinksUp; - { - Mutex::Lock _l(_tcpConnections_m); - for(std::vector::const_iterator c(_tcpConnections.begin());c!=_tcpConnections.end();++c) { - TcpConnection *const tc = *c; - tc->writeq_m.lock(); - const unsigned long wql = (unsigned long)tc->writeq.length(); - tc->writeq_m.unlock(); - if ((tc->sock)&&((wql > ZT_TCP_MAX_WRITEQ_SIZE)||((now - tc->lastReceive) > ZT_TCP_ACTIVITY_TIMEOUT))) { - toClose.push_back(tc->sock); - } else if ((tc->type == TcpConnection::TCP_CLUSTER_BACKPLANE)&&(tc->clusterMemberId)) { - clusterLinksUp.push_back(tc->remoteAddr); - sendMyCurrentClusterState(tc); - } - } - } - for(std::vector::iterator s(toClose.begin());s!=toClose.end();++s) - _phy.close(*s,true); - - // Attempt to connect to cluster links we don't have an active connection to - { - Mutex::Lock _l(_localConfig_m); - for(std::vector::const_iterator ca(_clusterBackplaneAddresses.begin());ca!=_clusterBackplaneAddresses.end();++ca) { - if ( (std::find(clusterLinksUp.begin(),clusterLinksUp.end(),*ca) == clusterLinksUp.end()) && (!_binder.isBoundLocalInterfaceAddress(*ca)) ) { - TcpConnection *tc = new TcpConnection(); - { - Mutex::Lock _l(_tcpConnections_m); - _tcpConnections.push_back(tc); - } - - tc->type = TcpConnection::TCP_CLUSTER_BACKPLANE; - tc->remoteAddr = *ca; - tc->lastReceive = OSUtils::now(); - tc->parent = this; - tc->sock = (PhySocket *)0; // set in connect handler - tc->messageSize = 0; - - tc->clusterMemberId = 0; // not known yet - - bool connected = false; - _phy.tcpConnect(reinterpret_cast(&(*ca)),connected,(void *)tc,true); - } - } - } - } - const unsigned long delay = (dl > now) ? (unsigned long)(dl - now) : 100; clockShouldBe = now + (uint64_t)delay; _phy.poll(delay); @@ -1211,21 +1113,6 @@ public: res["planetWorldId"] = planet.id(); res["planetWorldTimestamp"] = planet.timestamp(); - { - json cj(json::object()); - Mutex::Lock _l(_tcpConnections_m); - Mutex::Lock _l2(_localConfig_m); - for(std::vector::const_iterator ca(_clusterBackplaneAddresses.begin());ca!=_clusterBackplaneAddresses.end();++ca) { - uint64_t up = 0; - for(std::vector::const_iterator c(_tcpConnections.begin());c!=_tcpConnections.end();++c) { - if (((*c)->remoteAddr == *ca)&&((*c)->clusterMemberId)&&((*c)->lastReceive > up)) - up = (*c)->lastReceive; - } - cj[ca->toString()] = up; - } - res["cluster"] = cj; - } - scode = 200; } else if (ps[0] == "moon") { std::vector moons(_node->moons()); @@ -1576,16 +1463,6 @@ public: } } - json &cl = settings["cluster"]; - _clusterBackplaneAddresses.clear(); - if (cl.is_array()) { - for(unsigned long i=0;i buf; - - buf.appendRandom(16); - buf.addSize(8); // space for MAC - buf.append((uint8_t)CLUSTER_MESSAGE_STATUS); - buf.append(_clusterMemberId); - buf.append((uint16_t)ZEROTIER_ONE_VERSION_MAJOR); - buf.append((uint16_t)ZEROTIER_ONE_VERSION_MINOR); - buf.append((uint16_t)ZEROTIER_ONE_VERSION_REVISION); - - std::vector lif(_binder.allBoundLocalInterfaceAddresses()); - buf.append((uint16_t)lif.size()); - for(std::vector::const_iterator i(lif.begin());i!=lif.end();++i) - i->serialize(buf); - - Mutex::Lock _l(tc->writeq_m); - - if (tc->writeq.length() == 0) - _phy.setNotifyWritable(tc->sock,true); - - const unsigned int mlen = buf.size(); - tc->writeq.push_back((char)((mlen >> 16) & 0xff)); - tc->writeq.push_back((char)((mlen >> 8) & 0xff)); - tc->writeq.push_back((char)(mlen & 0xff)); - - char *const data = reinterpret_cast(buf.unsafeData()); - encryptClusterMessage(data,mlen); - tc->writeq.append(data,mlen); - } catch ( ... ) { - fprintf(stderr,"WARNING: unexpected exception announcing status to cluster members" ZT_EOL_S); - } - } - - bool proxySendViaCluster(const InetAddress &fromAddress,const InetAddress &dest,const void *data,unsigned int len,unsigned int ttl) - { - Mutex::Lock _l(_tcpConnections_m); - for(std::vector::const_iterator c(_tcpConnections.begin());c!=_tcpConnections.end();++c) { - TcpConnection *const tc = *c; - if ((tc->type == TcpConnection::TCP_CLUSTER_BACKPLANE)&&(tc->clusterMemberId)) { - Mutex::Lock _l2(tc->clusterMemberLocalAddresses_m); - for(std::vector::const_iterator i(tc->clusterMemberLocalAddresses.begin());i!=tc->clusterMemberLocalAddresses.end();++i) { - if (*i == fromAddress) { - Buffer<1024> buf; - - buf.appendRandom(16); - buf.addSize(8); // space for MAC - buf.append((uint8_t)CLUSTER_MESSAGE_PROXY_SEND); - buf.append((uint8_t)ttl); - dest.serialize(buf); - fromAddress.serialize(buf); - - Mutex::Lock _l3(tc->writeq_m); - - if (tc->writeq.length() == 0) - _phy.setNotifyWritable(tc->sock,true); - - const unsigned int mlen = buf.size() + len; - tc->writeq.push_back((char)((mlen >> 16) & 0xff)); - tc->writeq.push_back((char)((mlen >> 8) & 0xff)); - tc->writeq.push_back((char)(mlen & 0xff)); - - const unsigned long startpos = (unsigned long)tc->writeq.length(); - tc->writeq.append(reinterpret_cast(buf.data()),buf.size()); - tc->writeq.append(reinterpret_cast(data),len); - - char *const outdata = const_cast(tc->writeq.data()) + startpos; - encryptClusterMessage(outdata,mlen); - - return true; - } - } - } - } - return false; - } - - void replicateStateObject(const ZT_StateObjectType type,const uint64_t id[2],const void *const data,const unsigned int len,TcpConnection *tc) - { - char buf[42]; - Mutex::Lock _l2(tc->writeq_m); - - if (tc->writeq.length() == 0) - _phy.setNotifyWritable(tc->sock,true); - - const unsigned int mlen = len + 42; - - tc->writeq.push_back((char)((mlen >> 16) & 0xff)); - tc->writeq.push_back((char)((mlen >> 8) & 0xff)); - tc->writeq.push_back((char)(mlen & 0xff)); - - Utils::getSecureRandom(buf,16); - buf[24] = (char)CLUSTER_MESSAGE_STATE_OBJECT; - buf[25] = (char)type; - buf[26] = (char)((id[0] >> 56) & 0xff); - buf[27] = (char)((id[0] >> 48) & 0xff); - buf[28] = (char)((id[0] >> 40) & 0xff); - buf[29] = (char)((id[0] >> 32) & 0xff); - buf[30] = (char)((id[0] >> 24) & 0xff); - buf[31] = (char)((id[0] >> 16) & 0xff); - buf[32] = (char)((id[0] >> 8) & 0xff); - buf[33] = (char)(id[0] & 0xff); - buf[34] = (char)((id[1] >> 56) & 0xff); - buf[35] = (char)((id[1] >> 48) & 0xff); - buf[36] = (char)((id[1] >> 40) & 0xff); - buf[37] = (char)((id[1] >> 32) & 0xff); - buf[38] = (char)((id[1] >> 24) & 0xff); - buf[39] = (char)((id[1] >> 16) & 0xff); - buf[40] = (char)((id[1] >> 8) & 0xff); - buf[41] = (char)(id[1] & 0xff); - - const unsigned long startpos = (unsigned long)tc->writeq.length(); - tc->writeq.append(buf,42); - tc->writeq.append(reinterpret_cast(data),len); - - char *const outdata = const_cast(tc->writeq.data()) + startpos; - encryptClusterMessage(outdata,mlen); - tc->writeq.append(outdata,mlen); - } - - void writeStateObject(enum ZT_StateObjectType type,const uint64_t id[2],const void *data,int len) - { - char buf[65535]; - char p[1024]; - FILE *f; - bool secure = false; - - switch(type) { - case ZT_STATE_OBJECT_IDENTITY_PUBLIC: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str()); - break; - case ZT_STATE_OBJECT_IDENTITY_SECRET: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str()); - secure = true; - break; - //case ZT_STATE_OBJECT_PEER_STATE: - // break; - case ZT_STATE_OBJECT_NETWORK_CONFIG: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id[0]); - secure = true; - break; - //case ZT_STATE_OBJECT_NETWORK_MEMBERSHIP: - // break; - case ZT_STATE_OBJECT_PLANET: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); - break; - case ZT_STATE_OBJECT_MOON: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id[0]); - break; - default: - p[0] = (char)0; - break; - } - - if (p[0]) { - if (len >= 0) { - // Check to see if we've already written this first. This reduces - // redundant writes and I/O overhead on most platforms and has - // little effect on others. - f = fopen(p,"r"); - bool redundant = false; - if (f) { - long l = (long)fread(buf,1,sizeof(buf),f); - fclose(f); - redundant = ((l == (long)len)&&(memcmp(data,buf,l) == 0)); - } - if (!redundant) { - f = fopen(p,"w"); - if (f) { - if (fwrite(data,len,1,f) != 1) - fprintf(stderr,"WARNING: unable to write to file: %s (I/O error)" ZT_EOL_S,p); - fclose(f); - if (secure) - OSUtils::lockDownFile(p,false); - } else { - fprintf(stderr,"WARNING: unable to write to file: %s (unable to open)" ZT_EOL_S,p); - } - } - } else { - OSUtils::rm(p); - } - } - } - - void sendMyCurrentClusterState(TcpConnection *tc) - { - // We currently don't need to dump everything. Networks and moons are most important. - // The rest will get caught up rapidly due to constant peer updates, etc. - std::string buf; - std::vector l(OSUtils::listDirectory((_homePath + ZT_PATH_SEPARATOR_S + "networks.d").c_str(),false)); - for(std::vector::const_iterator f(l.begin());f!=l.end();++f) { - buf.clear(); - if (OSUtils::readFile((_homePath + ZT_PATH_SEPARATOR_S + *f).c_str(),buf)) { - if (f->length() == 21) { - const uint64_t nwid = Utils::hexStrToU64(f->substr(0,16).c_str()); - if (nwid) { - uint64_t tmp[2]; - tmp[0] = nwid; - tmp[1] = 0; - replicateStateObject(ZT_STATE_OBJECT_NETWORK_CONFIG,tmp,buf.data(),(int)buf.length(),tc); - } - } - } - } - l = OSUtils::listDirectory((_homePath + ZT_PATH_SEPARATOR_S + "moons.d").c_str(),false); - for(std::vector::const_iterator f(l.begin());f!=l.end();++f) { - buf.clear(); - if (OSUtils::readFile((_homePath + ZT_PATH_SEPARATOR_S + *f).c_str(),buf)) { - if (f->length() == 21) { - const uint64_t moonId = Utils::hexStrToU64(f->substr(0,16).c_str()); - if (moonId) { - uint64_t tmp[2]; - tmp[0] = moonId; - tmp[1] = 0; - replicateStateObject(ZT_STATE_OBJECT_MOON,tmp,buf.data(),(int)buf.length(),tc); - } - } - } - } - } - // ========================================================================= // Handlers for Node and Phy<> callbacks // ========================================================================= @@ -2010,7 +1643,7 @@ public: const ZT_ResultCode rc = _node->processWirePacket( (void *)0, OSUtils::now(), - reinterpret_cast(localAddr), + (int64_t)((uintptr_t)sock), (const struct sockaddr_storage *)from, // Phy<> uses sockaddr_storage, so it'll always be that big data, len, @@ -2044,13 +1677,6 @@ public: _phy.close(_tcpFallbackTunnel->sock); _tcpFallbackTunnel = tc; _phy.streamSend(sock,ZT_TCP_TUNNEL_HELLO,sizeof(ZT_TCP_TUNNEL_HELLO)); - } else if (tc->type == TcpConnection::TCP_CLUSTER_BACKPLANE) { - { - Mutex::Lock _l(tc->writeq_m); - tc->writeq.push_back((char)0x93); // identifies type of connection as cluster backplane - } - announceStatusToClusterMember(tc); - _phy.setNotifyWritable(sock,true); } else { _phy.close(sock,true); } @@ -2106,31 +1732,6 @@ public: case TcpConnection::TCP_UNCATEGORIZED_INCOMING: switch(reinterpret_cast(data)[0]) { - // 0x93 is first byte of cluster backplane connections - case 0x93: { - // We only allow this from cluster backplane IPs. We also authenticate - // each packet cryptographically, so this is just a first line of defense. - bool allow = false; - { - Mutex::Lock _l(_localConfig_m); - for(std::vector< InetAddress >::const_iterator i(_clusterBackplaneAddresses.begin());i!=_clusterBackplaneAddresses.end();++i) { - if (tc->remoteAddr.ipsEqual(*i)) { - allow = true; - break; - } - } - } - if (allow) { - tc->type = TcpConnection::TCP_CLUSTER_BACKPLANE; - tc->clusterMemberId = 0; // unknown, waiting for first status message - announceStatusToClusterMember(tc); - if (len > 1) - phyOnTcpData(sock,uptr,reinterpret_cast(data) + 1,len - 1); - } else { - _phy.close(sock); - } - } break; - // HTTP: GET, PUT, POST, HEAD case 'G': case 'P': @@ -2223,7 +1824,7 @@ public: const ZT_ResultCode rc = _node->processWirePacket( (void *)0, OSUtils::now(), - reinterpret_cast(&fakeTcpLocalInterfaceAddress), + -1, reinterpret_cast(&from), data, plen, @@ -2248,114 +1849,6 @@ public: } return; - case TcpConnection::TCP_CLUSTER_BACKPLANE: - tc->readq.append((const char *)data,len); - if (tc->readq.length() >= 28) { // got 3-byte message size + 16-byte IV + 8-byte MAC + 1-byte type (encrypted) - uint8_t *data = reinterpret_cast(const_cast(tc->readq.data())); - unsigned long mlen = ( ((unsigned long)data[0] << 16) | ((unsigned long)data[1] << 8) | (unsigned long)data[2] ); - if ((mlen < 25)||(mlen > ZT_TCP_MAX_WRITEQ_SIZE)) { - _phy.close(sock); - return; - } else if (tc->readq.length() >= (mlen + 3)) { // got entire message - data += 3; - - uint8_t key[32]; - memcpy(key,_clusterKey,32); - for(int i=0;i<8;++i) key[i] ^= data[i]; // first 8 bytes of IV get XORed with key - Salsa20 s20(key,data + 8); // last 8 bytes of IV are fed into Salsa20 directly as its 64-bit IV - - uint8_t macKey[32]; - uint8_t mac[16]; - memset(macKey,0,32); - s20.crypt12(macKey,macKey,32); - Poly1305::compute(mac,data + 24,mlen - 24,macKey); - if (!Utils::secureEq(mac,data + 16,8)) { - _phy.close(sock); - return; - } - s20.crypt12(data + 24,data + 24,mlen - 24); - - switch((ClusterMessageType)data[24]) { - case CLUSTER_MESSAGE_STATUS: - if (mlen > (25 + 16)) { - Buffer<4096> tmp(data + 25,mlen - 25); - try { - const uint64_t cmid = tmp.at(0); - if (cmid == _clusterMemberId) { // shouldn't happen, but don't allow self-to-self - _phy.close(sock); - return; - } - if (!tc->clusterMemberId) { - tc->clusterMemberId = cmid; - sendMyCurrentClusterState(tc); - } - tc->clusterMemberVersionMajor = tmp.at(8); - tc->clusterMemberVersionMinor = tmp.at(10); - tc->clusterMemberVersionRev = tmp.at(12); - const unsigned int clusterMemberLocalAddressCount = tmp.at(14); - std::vector la; - unsigned int ptr = 16; - for(unsigned int k=0;kclusterMemberLocalAddresses_m); - tc->clusterMemberLocalAddresses.swap(la); - } - } catch ( ... ) {} - } - break; - - case CLUSTER_MESSAGE_STATE_OBJECT: - if (mlen > 42) { // type + object ID + [data] - uint64_t objId[2]; - objId[0] = ( - ((uint64_t)data[26] << 56) | - ((uint64_t)data[27] << 48) | - ((uint64_t)data[28] << 40) | - ((uint64_t)data[29] << 32) | - ((uint64_t)data[30] << 24) | - ((uint64_t)data[31] << 16) | - ((uint64_t)data[32] << 8) | - (uint64_t)data[33] - ); - objId[1] = ( - ((uint64_t)data[34] << 56) | - ((uint64_t)data[35] << 48) | - ((uint64_t)data[36] << 40) | - ((uint64_t)data[37] << 32) | - ((uint64_t)data[38] << 24) | - ((uint64_t)data[39] << 16) | - ((uint64_t)data[40] << 8) | - (uint64_t)data[41] - ); - if (_node->processStateUpdate((void *)0,(ZT_StateObjectType)data[25],objId,data + 42,(unsigned int)(mlen - 42)) == ZT_RESULT_OK) - writeStateObject((ZT_StateObjectType)data[25],objId,data + 42,(unsigned int)(mlen - 42)); - } - break; - - case CLUSTER_MESSAGE_PROXY_SEND: - if (mlen > 25) { - Buffer<4096> tmp(data + 25,mlen - 25); - try { - InetAddress dest,src; - const unsigned int ttl = (unsigned int)tmp[0]; - unsigned int ptr = 1; - ptr += dest.deserialize(tmp); - ptr += src.deserialize(tmp,ptr); - if (ptr < tmp.size()) - _binder.udpSend(_phy,src,dest,reinterpret_cast(tmp.data()) + ptr,tmp.size() - ptr,ttl); - } catch ( ... ) {} - } - break; - } - - tc->readq.erase(tc->readq.begin(),tc->readq.begin() + mlen); - } - } - return; - } } catch ( ... ) { _phy.close(sock); @@ -2549,18 +2042,57 @@ public: inline void nodeStatePutFunction(enum ZT_StateObjectType type,const uint64_t id[2],const void *data,int len) { - writeStateObject(type,id,data,len); + char p[1024]; + FILE *f; + bool secure = false; - std::vector sentTo; - { - Mutex::Lock _l(_tcpConnections_m); - for(std::vector::const_iterator ci(_tcpConnections.begin());ci!=_tcpConnections.end();++ci) { - TcpConnection *const c = *ci; - if ((c->type == TcpConnection::TCP_CLUSTER_BACKPLANE)&&(c->clusterMemberId != 0)&&(std::find(sentTo.begin(),sentTo.end(),c->clusterMemberId) == sentTo.end())) { - sentTo.push_back(c->clusterMemberId); - replicateStateObject(type,id,data,len,c); - } + switch(type) { + case ZT_STATE_OBJECT_IDENTITY_PUBLIC: + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str()); + break; + case ZT_STATE_OBJECT_IDENTITY_SECRET: + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str()); + secure = true; + break; + case ZT_STATE_OBJECT_PLANET: + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); + break; + case ZT_STATE_OBJECT_MOON: + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id[0]); + break; + case ZT_STATE_OBJECT_NETWORK_CONFIG: + Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id[0]); + secure = true; + break; + default: + return; + } + + if (len >= 0) { + // Check to see if we've already written this first. This reduces + // redundant writes and I/O overhead on most platforms and has + // little effect on others. + f = fopen(p,"r"); + if (f) { + char buf[65535]; + long l = (long)fread(buf,1,sizeof(buf),f); + fclose(f); + if ((l == (long)len)&&(memcmp(data,buf,l) == 0)) + return; } + + f = fopen(p,"w"); + if (f) { + if (fwrite(data,len,1,f) != 1) + fprintf(stderr,"WARNING: unable to write to file: %s (I/O error)" ZT_EOL_S,p); + fclose(f); + if (secure) + OSUtils::lockDownFile(p,false); + } else { + fprintf(stderr,"WARNING: unable to write to file: %s (unable to open)" ZT_EOL_S,p); + } + } else { + OSUtils::rm(p); } } @@ -2596,7 +2128,7 @@ public: return -1; } - inline int nodeWirePacketSendFunction(const struct sockaddr_storage *localAddr,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl) + inline int nodeWirePacketSendFunction(const int64_t localSocket,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl) { #ifdef ZT_TCP_FALLBACK_RELAY if (addr->ss_family == AF_INET) { @@ -2646,20 +2178,13 @@ public: // proxy fallback, which is slow. #endif // ZT_TCP_FALLBACK_RELAY - switch (_binder.udpSend(_phy,*(reinterpret_cast(localAddr)),*(reinterpret_cast(addr)),data,len,ttl)) { - case -1: // local bound address not found, so see if a cluster peer owns it - if (localAddr->ss_family != 0) { - return (proxySendViaCluster(*(reinterpret_cast(localAddr)),*(reinterpret_cast(addr)),data,len,ttl)) ? 0 : -1; - } else { - return -1; // failure - } - break; - - case 0: // failure - return -1; - - default: // success - return 0; + if ((localSocket != 0)&&(localSocket != -1)) { + if ((ttl)&&(addr->ss_family == AF_INET)) _phy.setIp4UdpTtl((PhySocket *)((uintptr_t)localSocket),ttl); + const bool r = _phy.udpSend((PhySocket *)((uintptr_t)localSocket),(const struct sockaddr *)addr,data,len); + if ((ttl)&&(addr->ss_family == AF_INET)) _phy.setIp4UdpTtl((PhySocket *)((uintptr_t)localSocket),255); + return ((r) ? 0 : -1); + } else { + return ((_binder.udpSendAll(_phy,addr,data,len,ttl)) ? 0 : -1); } } @@ -2671,7 +2196,7 @@ public: n->tap->put(MAC(sourceMac),MAC(destMac),etherType,data,len); } - inline int nodePathCheckFunction(uint64_t ztaddr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *remoteAddr) + inline int nodePathCheckFunction(uint64_t ztaddr,const int64_t localSocket,const struct sockaddr_storage *remoteAddr) { // Make sure we're not trying to do ZeroTier-over-ZeroTier { @@ -2882,12 +2407,12 @@ static void SnodeStatePutFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_St { reinterpret_cast(uptr)->nodeStatePutFunction(type,id,data,len); } static int SnodeStateGetFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,const uint64_t id[2],void *data,unsigned int maxlen) { return reinterpret_cast(uptr)->nodeStateGetFunction(type,id,data,maxlen); } -static int SnodeWirePacketSendFunction(ZT_Node *node,void *uptr,void *tptr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl) -{ return reinterpret_cast(uptr)->nodeWirePacketSendFunction(localAddr,addr,data,len,ttl); } +static int SnodeWirePacketSendFunction(ZT_Node *node,void *uptr,void *tptr,int64_t localSocket,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl) +{ return reinterpret_cast(uptr)->nodeWirePacketSendFunction(localSocket,addr,data,len,ttl); } static void SnodeVirtualNetworkFrameFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t nwid,void **nuptr,uint64_t sourceMac,uint64_t destMac,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) { reinterpret_cast(uptr)->nodeVirtualNetworkFrameFunction(nwid,nuptr,sourceMac,destMac,etherType,vlanId,data,len); } -static int SnodePathCheckFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t ztaddr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *remoteAddr) -{ return reinterpret_cast(uptr)->nodePathCheckFunction(ztaddr,localAddr,remoteAddr); } +static int SnodePathCheckFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t ztaddr,int64_t localSocket,const struct sockaddr_storage *remoteAddr) +{ return reinterpret_cast(uptr)->nodePathCheckFunction(ztaddr,localSocket,remoteAddr); } static int SnodePathLookupFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t ztaddr,int family,struct sockaddr_storage *result) { return reinterpret_cast(uptr)->nodePathLookupFunction(ztaddr,family,result); } static void StapFrameHandler(void *uptr,void *tptr,uint64_t nwid,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) -- cgit v1.2.3 From dff8c02cfee9eaafae0974f3b070ff849a94c4ac Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 6 Jul 2017 12:33:00 -0700 Subject: Pull out and deprecate old cluster code. New cluster code will not be merged yet. --- node/IncomingPacket.cpp | 12 ++++++------ node/Peer.cpp | 18 ++++++++++++++++-- node/Peer.hpp | 17 ++++++++++++++++- service/OneService.cpp | 20 ++++++++++++++++++++ 4 files changed, 58 insertions(+), 9 deletions(-) (limited to 'service/OneService.cpp') diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index f0be96f9..ac8514c6 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -1199,9 +1199,9 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPt (!( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) == 0) && (peer->hasActivePathTo(now,a)) )) && // not already known (RR->node->shouldUsePathForZeroTierTraffic(tPtr,peer->address(),_path->localSocket(),a)) ) // should use path { - //if ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) != 0) - // peer->setClusterPreferred(a); - if (++countPerScope[(int)a.ipScope()][0] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) { + if ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) != 0) { + peer->redirect(tPtr,_path->localSocket(),a,now); + } else if (++countPerScope[(int)a.ipScope()][0] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) { TRACE("attempting to contact %s at pushed direct path %s",peer->address().toString().c_str(),a.toString().c_str()); peer->attemptToContactAt(tPtr,InetAddress(),a,now,false,0); } else { @@ -1216,9 +1216,9 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPt (!( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) == 0) && (peer->hasActivePathTo(now,a)) )) && // not already known (RR->node->shouldUsePathForZeroTierTraffic(tPtr,peer->address(),_path->localSocket(),a)) ) // should use path { - //if ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) != 0) - // peer->setClusterPreferred(a); - if (++countPerScope[(int)a.ipScope()][1] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) { + if ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) != 0) { + peer->redirect(tPtr,_path->localSocket(),a,now); + } else if (++countPerScope[(int)a.ipScope()][1] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) { TRACE("attempting to contact %s at pushed direct path %s",peer->address().toString().c_str(),a.toString().c_str()); peer->attemptToContactAt(tPtr,InetAddress(),a,now,false,0); } else { diff --git a/node/Peer.cpp b/node/Peer.cpp index fb9a72b1..e16540b3 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -170,11 +170,11 @@ void Peer::received( Mutex::Lock _l(_paths_m); _PeerPath *potentialNewPeerPath = (_PeerPath *)0; if (path->address().ss_family == AF_INET) { - if ( (!_v4Path.p) || (!_v4Path.p->alive(now)) || (path->preferenceRank() >= _v4Path.p->preferenceRank()) ) { + if ( ( (!_v4Path.p) || (!_v4Path.p->alive(now)) || (path->preferenceRank() >= _v4Path.p->preferenceRank()) ) && ( (now - _v4Path.sticky) > ZT_PEER_PATH_EXPIRATION ) ) { potentialNewPeerPath = &_v4Path; } } else if (path->address().ss_family == AF_INET6) { - if ( (!_v6Path.p) || (!_v6Path.p->alive(now)) || (path->preferenceRank() >= _v6Path.p->preferenceRank()) ) { + if ( ( (!_v6Path.p) || (!_v6Path.p->alive(now)) || (path->preferenceRank() >= _v6Path.p->preferenceRank()) ) && ( (now - _v6Path.sticky) > ZT_PEER_PATH_EXPIRATION ) ) { potentialNewPeerPath = &_v6Path; } } @@ -422,4 +422,18 @@ bool Peer::doPingAndKeepalive(void *tPtr,uint64_t now,int inetAddressFamily) return false; } +void Peer::redirect(void *tPtr,const int64_t localSocket,const InetAddress &remoteAddress,const uint64_t now) +{ + Mutex::Lock _l(_paths_m); + SharedPtr p(RR->topology->getPath(localSocket,remoteAddress)); + attemptToContactAt(tPtr,localSocket,remoteAddress,now,true,p->nextOutgoingCounter()); + if (remoteAddress.ss_family == AF_INET) { + _v4Path.p = p; + _v4Path.sticky = now; + } else if (remoteAddress.ss_family == AF_INET6) { + _v6Path.p = p; + _v6Path.sticky = now; + } +} + } // namespace ZeroTier diff --git a/node/Peer.hpp b/node/Peer.hpp index ad2d0ddc..b24318ec 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -195,6 +195,20 @@ public: */ bool doPingAndKeepalive(void *tPtr,uint64_t now,int inetAddressFamily); + /** + * Specify remote path for this peer and forget others + * + * This overrides normal path learning and tells this peer to be found + * at this address, at least within the address's family. Other address + * families are not modified. + * + * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call + * @param localSocket Local socket as supplied by external code + * @param remoteAddress Remote address + * @param now Current time + */ + void redirect(void *tPtr,const int64_t localSocket,const InetAddress &remoteAddress,const uint64_t now); + /** * Reset paths within a given IP scope and address family * @@ -426,8 +440,9 @@ public: private: struct _PeerPath { - _PeerPath() : lr(0),p() {} + _PeerPath() : lr(0),sticky(0),p() {} uint64_t lr; // time of last valid ZeroTier packet + uint64_t sticky; // time last set as sticky SharedPtr p; }; diff --git a/service/OneService.cpp b/service/OneService.cpp index 6497ae20..6c2c9a8b 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -394,6 +394,8 @@ public: Phy _phy; Node *_node; SoftwareUpdater *_updater; + PhySocket *_localControlSocket4; + PhySocket *_localControlSocket6; bool _updateAutoApply; unsigned int _primaryPort; volatile unsigned int _udpPortPickerCounter; @@ -488,6 +490,8 @@ public: ,_phy(this,false,true) ,_node((Node *)0) ,_updater((SoftwareUpdater *)0) + ,_localControlSocket4((PhySocket *)0) + ,_localControlSocket6((PhySocket *)0) ,_updateAutoApply(false) ,_primaryPort(port) ,_udpPortPickerCounter(0) @@ -513,6 +517,8 @@ public: virtual ~OneServiceImpl() { _binder.closeAll(_phy); + _phy.close(_localControlSocket4); + _phy.close(_localControlSocket6); #ifdef ZT_USE_MINIUPNPC delete _portMapper; #endif @@ -652,6 +658,20 @@ public: return _termReason; } + // Bind local control socket + { + struct sockaddr_in lo4; + memset(&lo4,0,sizeof(lo4)); + lo4.sin_family = AF_INET; + lo4.sin_port = Utils::hton((uint16_t)_ports[0]); + _localControlSocket4 = _phy.tcpListen((const struct sockaddr *)&lo4); + struct sockaddr_in6 lo6; + memset(&lo6,0,sizeof(lo6)); + lo6.sin6_family = AF_INET6; + lo6.sin6_port = lo4.sin_port; + _localControlSocket6 = _phy.tcpListen((const struct sockaddr *)&lo6); + } + // Save primary port to a file so CLIs and GUIs can learn it easily char portstr[64]; Utils::ztsnprintf(portstr,sizeof(portstr),"%u",_ports[0]); -- cgit v1.2.3 From d2415dee00914ab3fd7016758f4184d46bb407a5 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 6 Jul 2017 16:11:11 -0700 Subject: Cleanup. --- controller/EmbeddedNetworkController.cpp | 104 +++++++++-------- controller/JSONDB.cpp | 14 +-- node/Address.hpp | 15 +-- node/CertificateOfMembership.cpp | 7 +- node/Dictionary.hpp | 6 +- node/Identity.cpp | 26 +++-- node/Identity.hpp | 18 +-- node/InetAddress.cpp | 195 ++++++++++++++----------------- node/InetAddress.hpp | 94 ++++++--------- node/MAC.hpp | 83 +++---------- node/MulticastGroup.hpp | 12 -- node/Network.cpp | 14 ++- node/NetworkConfig.cpp | 12 +- node/Node.cpp | 51 ++------ node/Node.hpp | 4 - node/RuntimeEnvironment.hpp | 10 +- node/Topology.cpp | 8 +- node/Utils.cpp | 114 ++++-------------- node/Utils.hpp | 182 +++++++++++++++++++++-------- one.cpp | 55 +++++---- osdep/BSDEthernetTap.cpp | 19 +-- osdep/Http.cpp | 4 +- osdep/LinuxEthernetTap.cpp | 33 +++--- osdep/ManagedRoute.cpp | 11 +- osdep/OSUtils.cpp | 28 ++++- osdep/OSUtils.hpp | 15 ++- osdep/OSXEthernetTap.cpp | 20 ++-- osdep/PortMapper.cpp | 4 +- osdep/WindowsEthernetTap.cpp | 10 +- selftest.cpp | 31 +++-- service/OneService.cpp | 94 +++++++-------- service/SoftwareUpdater.cpp | 5 +- 32 files changed, 620 insertions(+), 678 deletions(-) (limited to 'service/OneService.cpp') diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index 85c759e7..b57a37e8 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -76,19 +76,19 @@ static json _renderRule(ZT_VirtualNetworkRule &rule) break; case ZT_NETWORK_RULE_ACTION_TEE: r["type"] = "ACTION_TEE"; - r["address"] = Address(rule.v.fwd.address).toString(); + r["address"] = Address(rule.v.fwd.address).toString(tmp); r["flags"] = (unsigned int)rule.v.fwd.flags; r["length"] = (unsigned int)rule.v.fwd.length; break; case ZT_NETWORK_RULE_ACTION_WATCH: r["type"] = "ACTION_WATCH"; - r["address"] = Address(rule.v.fwd.address).toString(); + r["address"] = Address(rule.v.fwd.address).toString(tmp); r["flags"] = (unsigned int)rule.v.fwd.flags; r["length"] = (unsigned int)rule.v.fwd.length; break; case ZT_NETWORK_RULE_ACTION_REDIRECT: r["type"] = "ACTION_REDIRECT"; - r["address"] = Address(rule.v.fwd.address).toString(); + r["address"] = Address(rule.v.fwd.address).toString(tmp); r["flags"] = (unsigned int)rule.v.fwd.flags; break; case ZT_NETWORK_RULE_ACTION_BREAK: @@ -102,11 +102,11 @@ static json _renderRule(ZT_VirtualNetworkRule &rule) switch(rt) { case ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS: r["type"] = "MATCH_SOURCE_ZEROTIER_ADDRESS"; - r["zt"] = Address(rule.v.zt).toString(); + r["zt"] = Address(rule.v.zt).toString(tmp); break; case ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS: r["type"] = "MATCH_DEST_ZEROTIER_ADDRESS"; - r["zt"] = Address(rule.v.zt).toString(); + r["zt"] = Address(rule.v.zt).toString(tmp); break; case ZT_NETWORK_RULE_MATCH_VLAN_ID: r["type"] = "MATCH_VLAN_ID"; @@ -122,29 +122,29 @@ static json _renderRule(ZT_VirtualNetworkRule &rule) break; case ZT_NETWORK_RULE_MATCH_MAC_SOURCE: r["type"] = "MATCH_MAC_SOURCE"; - Utils::ztsnprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]); r["mac"] = tmp; break; case ZT_NETWORK_RULE_MATCH_MAC_DEST: r["type"] = "MATCH_MAC_DEST"; - Utils::ztsnprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]); r["mac"] = tmp; break; case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE: r["type"] = "MATCH_IPV4_SOURCE"; - r["ip"] = InetAddress(&(rule.v.ipv4.ip),4,(unsigned int)rule.v.ipv4.mask).toString(); + r["ip"] = InetAddress(&(rule.v.ipv4.ip),4,(unsigned int)rule.v.ipv4.mask).toString(tmp); break; case ZT_NETWORK_RULE_MATCH_IPV4_DEST: r["type"] = "MATCH_IPV4_DEST"; - r["ip"] = InetAddress(&(rule.v.ipv4.ip),4,(unsigned int)rule.v.ipv4.mask).toString(); + r["ip"] = InetAddress(&(rule.v.ipv4.ip),4,(unsigned int)rule.v.ipv4.mask).toString(tmp); break; case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE: r["type"] = "MATCH_IPV6_SOURCE"; - r["ip"] = InetAddress(rule.v.ipv6.ip,16,(unsigned int)rule.v.ipv6.mask).toString(); + r["ip"] = InetAddress(rule.v.ipv6.ip,16,(unsigned int)rule.v.ipv6.mask).toString(tmp); break; case ZT_NETWORK_RULE_MATCH_IPV6_DEST: r["type"] = "MATCH_IPV6_DEST"; - r["ip"] = InetAddress(rule.v.ipv6.ip,16,(unsigned int)rule.v.ipv6.mask).toString(); + r["ip"] = InetAddress(rule.v.ipv6.ip,16,(unsigned int)rule.v.ipv6.mask).toString(tmp); break; case ZT_NETWORK_RULE_MATCH_IP_TOS: r["type"] = "MATCH_IP_TOS"; @@ -179,7 +179,7 @@ static json _renderRule(ZT_VirtualNetworkRule &rule) break; case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS: r["type"] = "MATCH_CHARACTERISTICS"; - Utils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",rule.v.characteristics); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",rule.v.characteristics); r["mask"] = tmp; break; case ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE: @@ -312,28 +312,28 @@ static bool _parseRule(json &r,ZT_VirtualNetworkRule &rule) return true; } else if (t == "MATCH_IPV4_SOURCE") { rule.t |= ZT_NETWORK_RULE_MATCH_IPV4_SOURCE; - InetAddress ip(OSUtils::jsonString(r["ip"],"0.0.0.0")); + InetAddress ip(OSUtils::jsonString(r["ip"],"0.0.0.0").c_str()); rule.v.ipv4.ip = reinterpret_cast(&ip)->sin_addr.s_addr; rule.v.ipv4.mask = Utils::ntoh(reinterpret_cast(&ip)->sin_port) & 0xff; if (rule.v.ipv4.mask > 32) rule.v.ipv4.mask = 32; return true; } else if (t == "MATCH_IPV4_DEST") { rule.t |= ZT_NETWORK_RULE_MATCH_IPV4_DEST; - InetAddress ip(OSUtils::jsonString(r["ip"],"0.0.0.0")); + InetAddress ip(OSUtils::jsonString(r["ip"],"0.0.0.0").c_str()); rule.v.ipv4.ip = reinterpret_cast(&ip)->sin_addr.s_addr; rule.v.ipv4.mask = Utils::ntoh(reinterpret_cast(&ip)->sin_port) & 0xff; if (rule.v.ipv4.mask > 32) rule.v.ipv4.mask = 32; return true; } else if (t == "MATCH_IPV6_SOURCE") { rule.t |= ZT_NETWORK_RULE_MATCH_IPV6_SOURCE; - InetAddress ip(OSUtils::jsonString(r["ip"],"::0")); + InetAddress ip(OSUtils::jsonString(r["ip"],"::0").c_str()); memcpy(rule.v.ipv6.ip,reinterpret_cast(&ip)->sin6_addr.s6_addr,16); rule.v.ipv6.mask = Utils::ntoh(reinterpret_cast(&ip)->sin6_port) & 0xff; if (rule.v.ipv6.mask > 128) rule.v.ipv6.mask = 128; return true; } else if (t == "MATCH_IPV6_DEST") { rule.t |= ZT_NETWORK_RULE_MATCH_IPV6_DEST; - InetAddress ip(OSUtils::jsonString(r["ip"],"::0")); + InetAddress ip(OSUtils::jsonString(r["ip"],"::0").c_str()); memcpy(rule.v.ipv6.ip,reinterpret_cast(&ip)->sin6_addr.s6_addr,16); rule.v.ipv6.mask = Utils::ntoh(reinterpret_cast(&ip)->sin6_port) & 0xff; if (rule.v.ipv6.mask > 128) rule.v.ipv6.mask = 128; @@ -514,7 +514,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( _db.eachMember(nwid,[&responseBody](uint64_t networkId,uint64_t nodeId,const json &member) { if ((member.is_object())&&(member.size() > 0)) { char tmp[128]; - Utils::ztsnprintf(tmp,sizeof(tmp),"%s%.10llx\":%llu",(responseBody.length() > 1) ? ",\"" : "\"",(unsigned long long)nodeId,(unsigned long long)OSUtils::jsonInt(member["revision"],0)); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%s%.10llx\":%llu",(responseBody.length() > 1) ? ",\"" : "\"",(unsigned long long)nodeId,(unsigned long long)OSUtils::jsonInt(member["revision"],0)); responseBody.append(tmp); } }); @@ -548,7 +548,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( for(std::vector::const_iterator i(networkIds.begin());i!=networkIds.end();++i) { if (responseBody.length() > 1) responseBody.push_back(','); - Utils::ztsnprintf(tmp,sizeof(tmp),"\"%.16llx\"",(unsigned long long)*i); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"\"%.16llx\"",(unsigned long long)*i); responseBody.append(tmp); } responseBody.push_back(']'); @@ -562,7 +562,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( // Controller status char tmp[4096]; - Utils::ztsnprintf(tmp,sizeof(tmp),"{\n\t\"controller\": true,\n\t\"apiVersion\": %d,\n\t\"clock\": %llu\n}\n",ZT_NETCONF_CONTROLLER_API_VERSION,(unsigned long long)OSUtils::now()); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"{\n\t\"controller\": true,\n\t\"apiVersion\": %d,\n\t\"clock\": %llu\n}\n",ZT_NETCONF_CONTROLLER_API_VERSION,(unsigned long long)OSUtils::now()); responseBody = tmp; responseContentType = "application/json"; return 200; @@ -603,14 +603,14 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( if ((path.size() >= 2)&&(path[1].length() == 16)) { uint64_t nwid = Utils::hexStrToU64(path[1].c_str()); char nwids[24]; - Utils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid); + OSUtils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid); if (path.size() >= 3) { if ((path.size() == 4)&&(path[2] == "member")&&(path[3].length() == 10)) { uint64_t address = Utils::hexStrToU64(path[3].c_str()); char addrs[24]; - Utils::ztsnprintf(addrs,sizeof(addrs),"%.10llx",(unsigned long long)address); + OSUtils::ztsnprintf(addrs,sizeof(addrs),"%.10llx",(unsigned long long)address); json member; _db.getNetworkMember(nwid,address,member); @@ -655,9 +655,10 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( json mipa(json::array()); for(unsigned long i=0;i()); + InetAddress t(target.get().c_str()); InetAddress v; - if (via.is_string()) v.fromString(via.get()); + if (via.is_string()) v.fromString(via.get().c_str()); if ( ((t.ss_family == AF_INET)||(t.ss_family == AF_INET6)) && (t.netmaskBitsValid()) ) { json tmp; - tmp["target"] = t.toString(); + char tmp2[64]; + tmp["target"] = t.toString(tmp2); if (v.ss_family == t.ss_family) - tmp["via"] = v.toIpString(); + tmp["via"] = v.toIpString(tmp2); else tmp["via"] = json(); nrts.push_back(tmp); } @@ -840,12 +842,13 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( for(unsigned long i=0;i_memberStatus.find(_MemberStatusKey(networkId,nodeId)); if (ms != _memberStatus.end()) lrt = ms->second.lastRequestTime; - Utils::ztsnprintf(tmp,sizeof(tmp),"%s\"%.16llx-%.10llx\":%llu", + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%s\"%.16llx-%.10llx\":%llu", (first) ? "" : ",", (unsigned long long)networkId, (unsigned long long)nodeId, @@ -1093,7 +1096,7 @@ void EmbeddedNetworkController::threadMain() }); } char tmp2[256]; - Utils::ztsnprintf(tmp2,sizeof(tmp2),"},\"clock\":%llu,\"startTime\":%llu}",(unsigned long long)now,(unsigned long long)_startTime); + OSUtils::ztsnprintf(tmp2,sizeof(tmp2),"},\"clock\":%llu,\"startTime\":%llu}",(unsigned long long)now,(unsigned long long)_startTime); pong.append(tmp2); _db.writeRaw("pong",pong); } @@ -1126,7 +1129,7 @@ void EmbeddedNetworkController::_request( ms.lastRequestTime = now; } - Utils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid); + OSUtils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid); if (!_db.getNetworkAndMember(nwid,identity.address().toInt(),network,member,ns)) { _sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_OBJECT_NOT_FOUND); return; @@ -1152,13 +1155,15 @@ void EmbeddedNetworkController::_request( } } else { // If we do not yet know this member's identity, learn it. - member["identity"] = identity.toString(false); + char idtmp[1024]; + member["identity"] = identity.toString(false,idtmp); } } // These are always the same, but make sure they are set { - const std::string addrs(identity.address().toString()); + char tmpid[128]; + const std::string addrs(identity.address().toString(tmpid)); member["id"] = addrs; member["address"] = addrs; member["nwid"] = nwids; @@ -1264,8 +1269,9 @@ void EmbeddedNetworkController::_request( if (fromAddr) ms.physicalAddr = fromAddr; + char tmpip[64]; if (ms.physicalAddr) - member["physicalAddr"] = ms.physicalAddr.toString(); + member["physicalAddr"] = ms.physicalAddr.toString(tmpip); } } } else { @@ -1427,9 +1433,9 @@ void EmbeddedNetworkController::_request( json &target = route["target"]; json &via = route["via"]; if (target.is_string()) { - const InetAddress t(target.get()); + const InetAddress t(target.get().c_str()); InetAddress v; - if (via.is_string()) v.fromString(via.get()); + if (via.is_string()) v.fromString(via.get().c_str()); if ((t.ss_family == AF_INET)||(t.ss_family == AF_INET6)) { ZT_VirtualNetworkRoute *r = &(nc->routes[nc->routeCount]); *(reinterpret_cast(&(r->target))) = t; @@ -1462,7 +1468,7 @@ void EmbeddedNetworkController::_request( if (!ipAssignments[i].is_string()) continue; std::string ips = ipAssignments[i]; - InetAddress ip(ips); + InetAddress ip(ips.c_str()); // IP assignments are only pushed if there is a corresponding local route. We also now get the netmask bits from // this route, ignoring the netmask bits field of the assigned IP itself. Using that was worthless and a source @@ -1492,8 +1498,8 @@ void EmbeddedNetworkController::_request( for(unsigned long p=0;((p 0) && (!std::binary_search(ns.allocatedIps.begin(),ns.allocatedIps.end(),ip6)) ) { - ipAssignments.push_back(ip6.toIpString()); + char tmpip[64]; + ipAssignments.push_back(ip6.toIpString(tmpip)); member["ipAssignments"] = ipAssignments; ip6.setPort((unsigned int)routedNetmaskBits); if (nc->staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES) @@ -1552,8 +1559,8 @@ void EmbeddedNetworkController::_request( for(unsigned long p=0;((p(&ipRangeStartIA)->sin_addr.s_addr)); uint32_t ipRangeEnd = Utils::ntoh((uint32_t)(reinterpret_cast(&ipRangeEndIA)->sin_addr.s_addr)); @@ -1586,7 +1593,8 @@ void EmbeddedNetworkController::_request( // If it's routed, then try to claim and assign it and if successful end loop const InetAddress ip4(Utils::hton(ip),0); if ( (routedNetmaskBits > 0) && (!std::binary_search(ns.allocatedIps.begin(),ns.allocatedIps.end(),ip4)) ) { - ipAssignments.push_back(ip4.toIpString()); + char tmpip[64]; + ipAssignments.push_back(ip4.toIpString(tmpip)); member["ipAssignments"] = ipAssignments; if (nc->staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES) { struct sockaddr_in *const v4ip = reinterpret_cast(&(nc->staticIps[nc->staticIpCount++])); diff --git a/controller/JSONDB.cpp b/controller/JSONDB.cpp index acf23700..97a217a1 100644 --- a/controller/JSONDB.cpp +++ b/controller/JSONDB.cpp @@ -39,7 +39,7 @@ JSONDB::JSONDB(const std::string &basePath) : std::size_t hnsep = hn.find_last_of(':'); if (hnsep != std::string::npos) hn[hnsep] = '/'; - _httpAddr.fromString(hn); + _httpAddr.fromString(hn.c_str()); if (hnend != std::string::npos) _basePath = _basePath.substr(7 + hnend); if (_basePath.length() == 0) @@ -94,7 +94,7 @@ bool JSONDB::writeRaw(const std::string &n,const std::string &obj) std::string body; std::map reqHeaders; char tmp[64]; - Utils::ztsnprintf(tmp,sizeof(tmp),"%lu",(unsigned long)obj.length()); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%lu",(unsigned long)obj.length()); reqHeaders["Content-Length"] = tmp; reqHeaders["Content-Type"] = "application/json"; const unsigned int sc = Http::PUT(0,ZT_JSONDB_HTTP_TIMEOUT,reinterpret_cast(&_httpAddr),(_basePath+"/"+n).c_str(),reqHeaders,obj.data(),(unsigned long)obj.length(),headers,body); @@ -164,7 +164,7 @@ bool JSONDB::getNetworkMember(const uint64_t networkId,const uint64_t nodeId,nlo void JSONDB::saveNetwork(const uint64_t networkId,const nlohmann::json &networkConfig) { char n[64]; - Utils::ztsnprintf(n,sizeof(n),"network/%.16llx",(unsigned long long)networkId); + OSUtils::ztsnprintf(n,sizeof(n),"network/%.16llx",(unsigned long long)networkId); writeRaw(n,OSUtils::jsonDump(networkConfig)); { Mutex::Lock _l(_networks_m); @@ -176,7 +176,7 @@ void JSONDB::saveNetwork(const uint64_t networkId,const nlohmann::json &networkC void JSONDB::saveNetworkMember(const uint64_t networkId,const uint64_t nodeId,const nlohmann::json &memberConfig) { char n[256]; - Utils::ztsnprintf(n,sizeof(n),"network/%.16llx/member/%.10llx",(unsigned long long)networkId,(unsigned long long)nodeId); + OSUtils::ztsnprintf(n,sizeof(n),"network/%.16llx/member/%.10llx",(unsigned long long)networkId,(unsigned long long)nodeId); writeRaw(n,OSUtils::jsonDump(memberConfig)); { Mutex::Lock _l(_networks_m); @@ -202,7 +202,7 @@ nlohmann::json JSONDB::eraseNetwork(const uint64_t networkId) } char n[256]; - Utils::ztsnprintf(n,sizeof(n),"network/%.16llx",(unsigned long long)networkId); + OSUtils::ztsnprintf(n,sizeof(n),"network/%.16llx",(unsigned long long)networkId); if (_httpAddr) { // Deletion is currently done by Central in harnessed mode @@ -229,7 +229,7 @@ nlohmann::json JSONDB::eraseNetwork(const uint64_t networkId) nlohmann::json JSONDB::eraseNetworkMember(const uint64_t networkId,const uint64_t nodeId,bool recomputeSummaryInfo) { char n[256]; - Utils::ztsnprintf(n,sizeof(n),"network/%.16llx/member/%.10llx",(unsigned long long)networkId,(unsigned long long)nodeId); + OSUtils::ztsnprintf(n,sizeof(n),"network/%.16llx/member/%.10llx",(unsigned long long)networkId,(unsigned long long)nodeId); if (_httpAddr) { // Deletion is currently done by the caller in Central harnessed mode @@ -314,7 +314,7 @@ void JSONDB::threadMain() const nlohmann::json &mips = member["ipAssignments"]; if (mips.is_array()) { for(unsigned long i=0;iadd(key,tmp,-1); + return this->add(key,Utils::hex(value,tmp),-1); } /** @@ -401,8 +400,7 @@ public: inline bool add(const char *key,const Address &a) { char tmp[32]; - Utils::ztsnprintf(tmp,sizeof(tmp),"%.10llx",(unsigned long long)a.toInt()); - return this->add(key,tmp,-1); + return this->add(key,Utils::hex(a.toInt(),tmp),-1); } /** diff --git a/node/Identity.cpp b/node/Identity.cpp index ba77aa47..3b00b4c0 100644 --- a/node/Identity.cpp +++ b/node/Identity.cpp @@ -136,19 +136,23 @@ bool Identity::locallyValidate() const (digest[63] == addrb[4])); } -std::string Identity::toString(bool includePrivate) const +char *Identity::toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const { - std::string r; - - r.append(_address.toString()); - r.append(":0:"); // 0 == ZT_OBJECT_TYPE_IDENTITY - r.append(Utils::hex(_publicKey.data,(unsigned int)_publicKey.size())); + char *p = buf; + Utils::hex10(_address.toInt(),p); + p += 10; + *(p++) = ':'; + *(p++) = '0'; + *(p++) = ':'; + Utils::hex(_publicKey.data,ZT_C25519_PUBLIC_KEY_LEN,p); + p += ZT_C25519_PUBLIC_KEY_LEN * 2; if ((_privateKey)&&(includePrivate)) { - r.push_back(':'); - r.append(Utils::hex(_privateKey->data,(unsigned int)_privateKey->size())); + *(p++) = ':'; + Utils::hex(_privateKey->data,ZT_C25519_PRIVATE_KEY_LEN,p); + p += ZT_C25519_PRIVATE_KEY_LEN * 2; } - - return r; + *(p++) = (char)0; + return buf; } bool Identity::fromString(const char *str) @@ -157,7 +161,7 @@ bool Identity::fromString(const char *str) return false; char *saveptr = (char *)0; - char tmp[1024]; + char tmp[ZT_IDENTITY_STRING_BUFFER_LENGTH]; if (!Utils::scopy(tmp,sizeof(tmp),str)) return false; diff --git a/node/Identity.hpp b/node/Identity.hpp index 79e17f4d..5804b9f8 100644 --- a/node/Identity.hpp +++ b/node/Identity.hpp @@ -29,7 +29,6 @@ #include #include -#include #include "Constants.hpp" #include "Array.hpp" @@ -39,6 +38,8 @@ #include "Buffer.hpp" #include "SHA512.hpp" +#define ZT_IDENTITY_STRING_BUFFER_LENGTH 384 + namespace ZeroTier { /** @@ -66,16 +67,7 @@ public: { } - Identity(const char *str) - throw(std::invalid_argument) : - _privateKey((C25519::Private *)0) - { - if (!fromString(str)) - throw std::invalid_argument(std::string("invalid string-serialized identity: ") + str); - } - - Identity(const std::string &str) - throw(std::invalid_argument) : + Identity(const char *str) : _privateKey((C25519::Private *)0) { if (!fromString(str)) @@ -277,9 +269,10 @@ public: * Serialize to a more human-friendly string * * @param includePrivate If true, include private key (if it exists) + * @param buf Buffer to store string * @return ASCII string representation of identity */ - std::string toString(bool includePrivate) const; + char *toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const; /** * Deserialize a human-friendly string @@ -291,7 +284,6 @@ public: * @return True if deserialization appears successful */ bool fromString(const char *str); - inline bool fromString(const std::string &str) { return fromString(str.c_str()); } /** * @return C25519 public key diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp index 17d7c72e..f7585bdb 100644 --- a/node/InetAddress.cpp +++ b/node/InetAddress.cpp @@ -5,7 +5,7 @@ * 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. + * (at your oion) 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 @@ -40,7 +40,6 @@ const InetAddress InetAddress::LO4((const void *)("\x7f\x00\x00\x01"),4,0); const InetAddress InetAddress::LO6((const void *)("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"),16,0); InetAddress::IpScope InetAddress::ipScope() const - throw() { switch(ss_family) { @@ -111,27 +110,7 @@ InetAddress::IpScope InetAddress::ipScope() const return IP_SCOPE_NONE; } -void InetAddress::set(const std::string &ip,unsigned int port) - throw() -{ - memset(this,0,sizeof(InetAddress)); - if (ip.find(':') != std::string::npos) { - struct sockaddr_in6 *sin6 = reinterpret_cast(this); - ss_family = AF_INET6; - sin6->sin6_port = Utils::hton((uint16_t)port); - if (inet_pton(AF_INET6,ip.c_str(),(void *)&(sin6->sin6_addr.s6_addr)) <= 0) - memset(this,0,sizeof(InetAddress)); - } else if (ip.find('.') != std::string::npos) { - struct sockaddr_in *sin = reinterpret_cast(this); - ss_family = AF_INET; - sin->sin_port = Utils::hton((uint16_t)port); - if (inet_pton(AF_INET,ip.c_str(),(void *)&(sin->sin_addr.s_addr)) <= 0) - memset(this,0,sizeof(InetAddress)); - } -} - void InetAddress::set(const void *ipBytes,unsigned int ipLen,unsigned int port) - throw() { memset(this,0,sizeof(InetAddress)); if (ipLen == 4) { @@ -147,90 +126,98 @@ void InetAddress::set(const void *ipBytes,unsigned int ipLen,unsigned int port) } } -std::string InetAddress::toString() const +char *InetAddress::toString(char buf[64]) const { - char buf[128]; - switch(ss_family) { - case AF_INET: - Utils::ztsnprintf(buf,sizeof(buf),"%d.%d.%d.%d/%d", - (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[0], - (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[1], - (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[2], - (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[3], - (int)Utils::ntoh((uint16_t)(reinterpret_cast(this)->sin_port)) - ); - return std::string(buf); - case AF_INET6: - Utils::ztsnprintf(buf,sizeof(buf),"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x/%d", - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[0]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[1]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[2]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[3]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[4]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[5]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[6]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[7]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[8]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[9]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[10]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[11]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[12]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[13]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[14]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[15]), - (int)Utils::ntoh((uint16_t)(reinterpret_cast(this)->sin6_port)) - ); - return std::string(buf); + char *p = toIpString(buf); + if (*p) { + while (*p) ++p; + *(p++) = '/'; + Utils::decimal(port(),p); } - return std::string(); + return buf; } -std::string InetAddress::toIpString() const +char *InetAddress::toIpString(char buf[64]) const { - char buf[128]; switch(ss_family) { - case AF_INET: - Utils::ztsnprintf(buf,sizeof(buf),"%d.%d.%d.%d", - (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[0], - (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[1], - (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[2], - (int)(reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)))[3] - ); - return std::string(buf); - case AF_INET6: - Utils::ztsnprintf(buf,sizeof(buf),"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[0]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[1]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[2]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[3]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[4]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[5]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[6]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[7]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[8]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[9]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[10]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[11]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[12]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[13]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[14]), - (int)(reinterpret_cast(this)->sin6_addr.s6_addr[15]) - ); - return std::string(buf); + case AF_INET: { + const uint8_t *a = reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr)); + char *p = buf; + for(int i=0;;++i) { + Utils::decimal((unsigned long)a[i],p); + if (i != 3) { + while (*p) ++p; + *(p++) = '.'; + } else break; + } + } break; + + case AF_INET6: { + uint16_t a[8]; + memcpy(a,reinterpret_cast(this)->sin6_addr.s6_addr,16); + char *p = buf; + for(int i=0;i<8;++i) { + Utils::hex(Utils::ntoh(a[i]),p); + p[4] = (i == 7) ? (char)0 : ':'; + p += 5; + } + } break; + + default: + buf[0] = (char)0; + break; } - return std::string(); + return buf; } -void InetAddress::fromString(const std::string &ipSlashPort) +bool InetAddress::fromString(const char *ipSlashPort) { - const std::size_t slashAt = ipSlashPort.find('/'); - if (slashAt == std::string::npos) { - set(ipSlashPort,0); + char buf[64]; + + memset(this,0,sizeof(InetAddress)); + + if (!*ipSlashPort) + return true; + if (!Utils::scopy(buf,sizeof(buf),ipSlashPort)) + return false; + + char *portAt = buf; + while ((*portAt)&&(*portAt != '/')) + ++portAt; + unsigned int port = 0; + if (*portAt) { + *(portAt++) = (char)0; + port = Utils::strToUInt(portAt) & 0xffff; + } + + if (strchr(buf,':')) { + uint16_t a[8]; + unsigned int b = 0; + char *saveptr = (char *)0; + for(char *s=Utils::stok(buf,":",&saveptr);((s)&&(b<8));s=Utils::stok((char *)0,":",&saveptr)) + a[b++] = Utils::hton((uint16_t)(Utils::hexStrToUInt(s) & 0xffff)); + + struct sockaddr_in6 *const in6 = reinterpret_cast(this); + in6->sin6_family = AF_INET6; + memcpy(in6->sin6_addr.s6_addr,a,16); + in6->sin6_port = Utils::hton((uint16_t)port); + + return true; + } else if (strchr(buf,'.')) { + uint8_t a[4]; + unsigned int b = 0; + char *saveptr = (char *)0; + for(char *s=Utils::stok(buf,".",&saveptr);((s)&&(b<4));s=Utils::stok((char *)0,".",&saveptr)) + a[b++] = (uint8_t)(Utils::strToUInt(s) & 0xff); + + struct sockaddr_in *const in = reinterpret_cast(this); + in->sin_family = AF_INET; + memcpy(&(in->sin_addr.s_addr),a,4); + in->sin_port = Utils::hton((uint16_t)port); + + return true; } else { - long p = strtol(ipSlashPort.substr(slashAt+1).c_str(),(char **)0,10); - if ((p > 0)&&(p <= 0xffff)) - set(ipSlashPort.substr(0,slashAt),(unsigned int)p); - else set(ipSlashPort.substr(0,slashAt),0); + return false; } } @@ -244,14 +231,13 @@ InetAddress InetAddress::netmask() const case AF_INET6: { uint64_t nm[2]; const unsigned int bits = netmaskBits(); - if(bits) { - nm[0] = Utils::hton((uint64_t)((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits)))); - nm[1] = Utils::hton((uint64_t)((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits)))); - } - else { - nm[0] = 0; - nm[1] = 0; - } + if(bits) { + nm[0] = Utils::hton((uint64_t)((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits)))); + nm[1] = Utils::hton((uint64_t)((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits)))); + } else { + nm[0] = 0; + nm[1] = 0; + } memcpy(reinterpret_cast(&r)->sin6_addr.s6_addr,nm,16); } break; } @@ -338,7 +324,6 @@ bool InetAddress::containsAddress(const InetAddress &addr) const } bool InetAddress::isNetwork() const - throw() { switch(ss_family) { case AF_INET: { @@ -371,7 +356,6 @@ bool InetAddress::isNetwork() const } bool InetAddress::operator==(const InetAddress &a) const - throw() { if (ss_family == a.ss_family) { switch(ss_family) { @@ -395,7 +379,6 @@ bool InetAddress::operator==(const InetAddress &a) const } bool InetAddress::operator<(const InetAddress &a) const - throw() { if (ss_family < a.ss_family) return true; diff --git a/node/InetAddress.hpp b/node/InetAddress.hpp index 4cb9a4dc..dd055084 100644 --- a/node/InetAddress.hpp +++ b/node/InetAddress.hpp @@ -31,8 +31,6 @@ #include #include -#include - #include "Constants.hpp" #include "../include/ZeroTierOne.h" #include "Utils.hpp" @@ -85,25 +83,22 @@ struct InetAddress : public sockaddr_storage IP_SCOPE_PRIVATE = 7 // 10.x.x.x, 192.168.x.x, etc. }; - InetAddress() throw() { memset(this,0,sizeof(InetAddress)); } - InetAddress(const InetAddress &a) throw() { memcpy(this,&a,sizeof(InetAddress)); } - InetAddress(const InetAddress *a) throw() { memcpy(this,a,sizeof(InetAddress)); } - InetAddress(const struct sockaddr_storage &ss) throw() { *this = ss; } - InetAddress(const struct sockaddr_storage *ss) throw() { *this = ss; } - InetAddress(const struct sockaddr &sa) throw() { *this = sa; } - InetAddress(const struct sockaddr *sa) throw() { *this = sa; } - InetAddress(const struct sockaddr_in &sa) throw() { *this = sa; } - InetAddress(const struct sockaddr_in *sa) throw() { *this = sa; } - InetAddress(const struct sockaddr_in6 &sa) throw() { *this = sa; } - InetAddress(const struct sockaddr_in6 *sa) throw() { *this = sa; } - InetAddress(const void *ipBytes,unsigned int ipLen,unsigned int port) throw() { this->set(ipBytes,ipLen,port); } - InetAddress(const uint32_t ipv4,unsigned int port) throw() { this->set(&ipv4,4,port); } - InetAddress(const std::string &ip,unsigned int port) throw() { this->set(ip,port); } - InetAddress(const std::string &ipSlashPort) throw() { this->fromString(ipSlashPort); } - InetAddress(const char *ipSlashPort) throw() { this->fromString(std::string(ipSlashPort)); } + InetAddress() { memset(this,0,sizeof(InetAddress)); } + InetAddress(const InetAddress &a) { memcpy(this,&a,sizeof(InetAddress)); } + InetAddress(const InetAddress *a) { memcpy(this,a,sizeof(InetAddress)); } + InetAddress(const struct sockaddr_storage &ss) { *this = ss; } + InetAddress(const struct sockaddr_storage *ss) { *this = ss; } + InetAddress(const struct sockaddr &sa) { *this = sa; } + InetAddress(const struct sockaddr *sa) { *this = sa; } + InetAddress(const struct sockaddr_in &sa) { *this = sa; } + InetAddress(const struct sockaddr_in *sa) { *this = sa; } + InetAddress(const struct sockaddr_in6 &sa) { *this = sa; } + InetAddress(const struct sockaddr_in6 *sa) { *this = sa; } + InetAddress(const void *ipBytes,unsigned int ipLen,unsigned int port) { this->set(ipBytes,ipLen,port); } + InetAddress(const uint32_t ipv4,unsigned int port) { this->set(&ipv4,4,port); } + InetAddress(const char *ipSlashPort) { this->fromString(ipSlashPort); } inline InetAddress &operator=(const InetAddress &a) - throw() { if (&a != this) memcpy(this,&a,sizeof(InetAddress)); @@ -111,7 +106,6 @@ struct InetAddress : public sockaddr_storage } inline InetAddress &operator=(const InetAddress *a) - throw() { if (a != this) memcpy(this,a,sizeof(InetAddress)); @@ -119,7 +113,6 @@ struct InetAddress : public sockaddr_storage } inline InetAddress &operator=(const struct sockaddr_storage &ss) - throw() { if (reinterpret_cast(&ss) != this) memcpy(this,&ss,sizeof(InetAddress)); @@ -127,7 +120,6 @@ struct InetAddress : public sockaddr_storage } inline InetAddress &operator=(const struct sockaddr_storage *ss) - throw() { if (reinterpret_cast(ss) != this) memcpy(this,ss,sizeof(InetAddress)); @@ -135,7 +127,6 @@ struct InetAddress : public sockaddr_storage } inline InetAddress &operator=(const struct sockaddr_in &sa) - throw() { if (reinterpret_cast(&sa) != this) { memset(this,0,sizeof(InetAddress)); @@ -145,7 +136,6 @@ struct InetAddress : public sockaddr_storage } inline InetAddress &operator=(const struct sockaddr_in *sa) - throw() { if (reinterpret_cast(sa) != this) { memset(this,0,sizeof(InetAddress)); @@ -155,7 +145,6 @@ struct InetAddress : public sockaddr_storage } inline InetAddress &operator=(const struct sockaddr_in6 &sa) - throw() { if (reinterpret_cast(&sa) != this) { memset(this,0,sizeof(InetAddress)); @@ -165,7 +154,6 @@ struct InetAddress : public sockaddr_storage } inline InetAddress &operator=(const struct sockaddr_in6 *sa) - throw() { if (reinterpret_cast(sa) != this) { memset(this,0,sizeof(InetAddress)); @@ -175,7 +163,6 @@ struct InetAddress : public sockaddr_storage } inline InetAddress &operator=(const struct sockaddr &sa) - throw() { if (reinterpret_cast(&sa) != this) { memset(this,0,sizeof(InetAddress)); @@ -192,7 +179,6 @@ struct InetAddress : public sockaddr_storage } inline InetAddress &operator=(const struct sockaddr *sa) - throw() { if (reinterpret_cast(sa) != this) { memset(this,0,sizeof(InetAddress)); @@ -211,17 +197,7 @@ struct InetAddress : public sockaddr_storage /** * @return IP scope classification (e.g. loopback, link-local, private, global) */ - IpScope ipScope() const - throw(); - - /** - * Set from a string-format IP and a port - * - * @param ip IP address in V4 or V6 ASCII notation - * @param port Port or 0 for none - */ - void set(const std::string &ip,unsigned int port) - throw(); + IpScope ipScope() const; /** * Set from a raw IP and port number @@ -230,8 +206,7 @@ struct InetAddress : public sockaddr_storage * @param ipLen Length of IP address: 4 or 16 * @param port Port number or 0 for none */ - void set(const void *ipBytes,unsigned int ipLen,unsigned int port) - throw(); + void set(const void *ipBytes,unsigned int ipLen,unsigned int port); /** * Set the port component @@ -272,23 +247,23 @@ struct InetAddress : public sockaddr_storage /** * @return ASCII IP/port format representation */ - std::string toString() const; + char *toString(char buf[64]) const; /** * @return IP portion only, in ASCII string format */ - std::string toIpString() const; + char *toIpString(char buf[64]) const; /** - * @param ipSlashPort ASCII IP/port format notation + * @param ipSlashPort IP/port (port is optional, will be 0 if not included) + * @return True if address appeared to be valid */ - void fromString(const std::string &ipSlashPort); + bool fromString(const char *ipSlashPort); /** * @return Port or 0 if no port component defined */ inline unsigned int port() const - throw() { switch(ss_family) { case AF_INET: return Utils::ntoh((uint16_t)(reinterpret_cast(this)->sin_port)); @@ -306,7 +281,7 @@ struct InetAddress : public sockaddr_storage * * @return Netmask bits */ - inline unsigned int netmaskBits() const throw() { return port(); } + inline unsigned int netmaskBits() const { return port(); } /** * @return True if netmask bits is valid for the address type @@ -329,7 +304,7 @@ struct InetAddress : public sockaddr_storage * * @return Gateway metric */ - inline unsigned int metric() const throw() { return port(); } + inline unsigned int metric() const { return port(); } /** * Construct a full netmask as an InetAddress @@ -376,12 +351,12 @@ struct InetAddress : public sockaddr_storage /** * @return True if this is an IPv4 address */ - inline bool isV4() const throw() { return (ss_family == AF_INET); } + inline bool isV4() const { return (ss_family == AF_INET); } /** * @return True if this is an IPv6 address */ - inline bool isV6() const throw() { return (ss_family == AF_INET6); } + inline bool isV6() const { return (ss_family == AF_INET6); } /** * @return pointer to raw address bytes or NULL if not available @@ -454,7 +429,7 @@ struct InetAddress : public sockaddr_storage /** * Set to null/zero */ - inline void zero() throw() { memset(this,0,sizeof(InetAddress)); } + inline void zero() { memset(this,0,sizeof(InetAddress)); } /** * Check whether this is a network/route rather than an IP assignment @@ -464,8 +439,7 @@ struct InetAddress : public sockaddr_storage * * @return True if everything after netmask bits is zero */ - bool isNetwork() const - throw(); + bool isNetwork() const; /** * @return 14-bit (0-16383) hash of this IP's first 24 or 48 bits (for V4 or V6) for rate limiting code, or 0 if non-IP @@ -494,7 +468,7 @@ struct InetAddress : public sockaddr_storage /** * @return True if address family is non-zero */ - inline operator bool() const throw() { return (ss_family != 0); } + inline operator bool() const { return (ss_family != 0); } template inline void serialize(Buffer &b) const @@ -552,12 +526,12 @@ struct InetAddress : public sockaddr_storage return (p - startAt); } - bool operator==(const InetAddress &a) const throw(); - bool operator<(const InetAddress &a) const throw(); - inline bool operator!=(const InetAddress &a) const throw() { return !(*this == a); } - inline bool operator>(const InetAddress &a) const throw() { return (a < *this); } - inline bool operator<=(const InetAddress &a) const throw() { return !(a < *this); } - inline bool operator>=(const InetAddress &a) const throw() { return !(*this < a); } + bool operator==(const InetAddress &a) const; + bool operator<(const InetAddress &a) const; + inline bool operator!=(const InetAddress &a) const { return !(*this == a); } + inline bool operator>(const InetAddress &a) const { return (a < *this); } + inline bool operator<=(const InetAddress &a) const { return !(a < *this); } + inline bool operator>=(const InetAddress &a) const { return !(*this < a); } /** * @param mac MAC address seed diff --git a/node/MAC.hpp b/node/MAC.hpp index db50aeb1..52388d59 100644 --- a/node/MAC.hpp +++ b/node/MAC.hpp @@ -44,30 +44,24 @@ namespace ZeroTier { class MAC { public: - MAC() throw() : _m(0ULL) {} - MAC(const MAC &m) throw() : _m(m._m) {} + MAC() : _m(0ULL) {} + MAC(const MAC &m) : _m(m._m) {} - MAC(const unsigned char a,const unsigned char b,const unsigned char c,const unsigned char d,const unsigned char e,const unsigned char f) throw() : + MAC(const unsigned char a,const unsigned char b,const unsigned char c,const unsigned char d,const unsigned char e,const unsigned char f) : _m( ((((uint64_t)a) & 0xffULL) << 40) | ((((uint64_t)b) & 0xffULL) << 32) | ((((uint64_t)c) & 0xffULL) << 24) | ((((uint64_t)d) & 0xffULL) << 16) | ((((uint64_t)e) & 0xffULL) << 8) | (((uint64_t)f) & 0xffULL) ) {} - - MAC(const char *s) throw() { fromString(s); } - MAC(const std::string &s) throw() { fromString(s.c_str()); } - - MAC(const void *bits,unsigned int len) throw() { setTo(bits,len); } - - MAC(const Address &ztaddr,uint64_t nwid) throw() { fromAddress(ztaddr,nwid); } - - MAC(const uint64_t m) throw() : _m(m & 0xffffffffffffULL) {} + MAC(const void *bits,unsigned int len) { setTo(bits,len); } + MAC(const Address &ztaddr,uint64_t nwid) { fromAddress(ztaddr,nwid); } + MAC(const uint64_t m) : _m(m & 0xffffffffffffULL) {} /** * @return MAC in 64-bit integer */ - inline uint64_t toInt() const throw() { return _m; } + inline uint64_t toInt() const { return _m; } /** * Set MAC to zero @@ -77,14 +71,13 @@ public: /** * @return True if MAC is non-zero */ - inline operator bool() const throw() { return (_m != 0ULL); } + inline operator bool() const { return (_m != 0ULL); } /** * @param bits Raw MAC in big-endian byte order * @param len Length, must be >= 6 or result is zero */ inline void setTo(const void *bits,unsigned int len) - throw() { if (len < 6) { _m = 0ULL; @@ -104,7 +97,6 @@ public: * @param len Length of buffer, must be >= 6 or nothing is copied */ inline void copyTo(void *buf,unsigned int len) const - throw() { if (len < 6) return; @@ -124,7 +116,6 @@ public: */ template inline void appendTo(Buffer &b) const - throw(std::out_of_range) { unsigned char *p = (unsigned char *)b.appendField(6); *(p++) = (unsigned char)((_m >> 40) & 0xff); @@ -138,48 +129,17 @@ public: /** * @return True if this is broadcast (all 0xff) */ - inline bool isBroadcast() const throw() { return (_m == 0xffffffffffffULL); } + inline bool isBroadcast() const { return (_m == 0xffffffffffffULL); } /** * @return True if this is a multicast MAC */ - inline bool isMulticast() const throw() { return ((_m & 0x010000000000ULL) != 0ULL); } + inline bool isMulticast() const { return ((_m & 0x010000000000ULL) != 0ULL); } /** * @param True if this is a locally-administered MAC */ - inline bool isLocallyAdministered() const throw() { return ((_m & 0x020000000000ULL) != 0ULL); } - - /** - * @param s Hex MAC, with or without : delimiters - */ - inline void fromString(const char *s) - { - char tmp[8]; - for(int i=0;i<6;++i) - tmp[i] = (char)0; - Utils::unhex(s,tmp,6); - setTo(tmp,6); - } - - /** - * @return MAC address in standard :-delimited hex format - */ - inline std::string toString() const - { - char tmp[24]; - toString(tmp,sizeof(tmp)); - return std::string(tmp); - } - - /** - * @param buf Buffer to contain human-readable MAC - * @param len Length of buffer - */ - inline void toString(char *buf,unsigned int len) const - { - Utils::ztsnprintf(buf,len,"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)(*this)[0],(int)(*this)[1],(int)(*this)[2],(int)(*this)[3],(int)(*this)[4],(int)(*this)[5]); - } + inline bool isLocallyAdministered() const { return ((_m & 0x020000000000ULL) != 0ULL); } /** * Set this MAC to a MAC derived from an address and a network ID @@ -188,7 +148,6 @@ public: * @param nwid 64-bit network ID */ inline void fromAddress(const Address &ztaddr,uint64_t nwid) - throw() { uint64_t m = ((uint64_t)firstOctetForNetwork(nwid)) << 40; m |= ztaddr.toInt(); // a is 40 bits @@ -208,7 +167,6 @@ public: * @param nwid Network ID */ inline Address toAddress(uint64_t nwid) const - throw() { uint64_t a = _m & 0xffffffffffULL; // least significant 40 bits of MAC are formed from address a ^= ((nwid >> 8) & 0xff) << 32; // ... XORed with bits 8-48 of the nwid in little-endian byte order, so unmask it @@ -224,7 +182,6 @@ public: * @return First octet of MAC for this network */ static inline unsigned char firstOctetForNetwork(uint64_t nwid) - throw() { unsigned char a = ((unsigned char)(nwid & 0xfe) | 0x02); // locally administered, not multicast, from LSB of network ID return ((a == 0x52) ? 0x32 : a); // blacklist 0x52 since it's used by KVM, libvirt, and other popular virtualization engines... seems de-facto standard on Linux @@ -239,29 +196,27 @@ public: /** * @return 6, which is the number of bytes in a MAC, for container compliance */ - inline unsigned int size() const throw() { return 6; } + inline unsigned int size() const { return 6; } - inline unsigned long hashCode() const throw() { return (unsigned long)_m; } + inline unsigned long hashCode() const { return (unsigned long)_m; } inline MAC &operator=(const MAC &m) - throw() { _m = m._m; return *this; } inline MAC &operator=(const uint64_t m) - throw() { _m = m; return *this; } - inline bool operator==(const MAC &m) const throw() { return (_m == m._m); } - inline bool operator!=(const MAC &m) const throw() { return (_m != m._m); } - inline bool operator<(const MAC &m) const throw() { return (_m < m._m); } - inline bool operator<=(const MAC &m) const throw() { return (_m <= m._m); } - inline bool operator>(const MAC &m) const throw() { return (_m > m._m); } - inline bool operator>=(const MAC &m) const throw() { return (_m >= m._m); } + inline bool operator==(const MAC &m) const { return (_m == m._m); } + inline bool operator!=(const MAC &m) const { return (_m != m._m); } + inline bool operator<(const MAC &m) const { return (_m < m._m); } + inline bool operator<=(const MAC &m) const { return (_m <= m._m); } + inline bool operator>(const MAC &m) const { return (_m > m._m); } + inline bool operator>=(const MAC &m) const { return (_m >= m._m); } private: uint64_t _m; diff --git a/node/MulticastGroup.hpp b/node/MulticastGroup.hpp index 7cbec2e0..f56c675b 100644 --- a/node/MulticastGroup.hpp +++ b/node/MulticastGroup.hpp @@ -29,8 +29,6 @@ #include -#include - #include "MAC.hpp" #include "InetAddress.hpp" @@ -94,16 +92,6 @@ public: return MulticastGroup(); } - /** - * @return Human readable string representing this group (MAC/ADI in hex) - */ - inline std::string toString() const - { - char buf[64]; - Utils::ztsnprintf(buf,sizeof(buf),"%.2x%.2x%.2x%.2x%.2x%.2x/%.8lx",(unsigned int)_mac[0],(unsigned int)_mac[1],(unsigned int)_mac[2],(unsigned int)_mac[3],(unsigned int)_mac[4],(unsigned int)_mac[5],(unsigned long)_adi); - return std::string(buf); - } - /** * @return Multicast address */ diff --git a/node/Network.cpp b/node/Network.cpp index bccc0397..f2b6771b 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -51,7 +51,7 @@ namespace ZeroTier { namespace { #ifdef ZT_RULES_ENGINE_DEBUGGING -#define FILTER_TRACE(f,...) { Utils::ztsnprintf(dpbuf,sizeof(dpbuf),f,##__VA_ARGS__); dlog.push_back(std::string(dpbuf)); } +#define FILTER_TRACE(f,...) { snprintf(dpbuf,sizeof(dpbuf),f,##__VA_ARGS__); dlog.push_back(std::string(dpbuf)); } static const char *_rtn(const ZT_VirtualNetworkRuleType rt) { switch(rt) { @@ -1257,7 +1257,17 @@ void Network::requestConfiguration(void *tPtr) nconf->rules[13].t = (uint8_t)ZT_NETWORK_RULE_ACTION_DROP; nconf->type = ZT_NETWORK_TYPE_PUBLIC; - Utils::ztsnprintf(nconf->name,sizeof(nconf->name),"adhoc-%.04x-%.04x",(int)startPortRange,(int)endPortRange); + + nconf->name[0] = 'a'; + nconf->name[1] = 'd'; + nconf->name[2] = 'h'; + nconf->name[3] = 'o'; + nconf->name[4] = 'c'; + nconf->name[5] = '-'; + Utils::hex((uint16_t)startPortRange,nconf->name + 6); + nconf->name[10] = '-'; + Utils::hex((uint16_t)endPortRange,nconf->name + 11); + nconf->name[15] = (char)0; this->setConfiguration(tPtr,*nconf,false); delete nconf; diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp index 65101c3a..e5929923 100644 --- a/node/NetworkConfig.cpp +++ b/node/NetworkConfig.cpp @@ -64,7 +64,8 @@ bool NetworkConfig::toDictionary(Dictionary &d,b if (this->staticIps[i].ss_family == AF_INET) { if (v4s.length() > 0) v4s.push_back(','); - v4s.append(this->staticIps[i].toString()); + char buf[64]; + v4s.append(this->staticIps[i].toString(buf)); } } if (v4s.length() > 0) { @@ -75,7 +76,8 @@ bool NetworkConfig::toDictionary(Dictionary &d,b if (this->staticIps[i].ss_family == AF_INET6) { if (v6s.length() > 0) v6s.push_back(','); - v6s.append(this->staticIps[i].toString()); + char buf[64]; + v6s.append(this->staticIps[i].toString(buf)); } } if (v6s.length() > 0) { @@ -94,8 +96,7 @@ bool NetworkConfig::toDictionary(Dictionary &d,b if (ets.length() > 0) ets.push_back(','); char tmp2[16]; - Utils::ztsnprintf(tmp2,sizeof(tmp2),"%x",et); - ets.append(tmp2); + ets.append(Utils::hex((uint16_t)et,tmp2)); } et = 0; } @@ -114,7 +115,8 @@ bool NetworkConfig::toDictionary(Dictionary &d,b if ((this->specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0) { if (ab.length() > 0) ab.push_back(','); - ab.append(Address(this->specialists[i]).toString().c_str()); + char tmp2[16]; + ab.append(Address(this->specialists[i]).toString(tmp2)); } } if (ab.length() > 0) { diff --git a/node/Node.cpp b/node/Node.cpp index 4b598f61..e28accee 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -82,8 +82,8 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint6 if (n > 0) { tmp[n] = (char)0; if (RR->identity.fromString(tmp)) { - RR->publicIdentityStr = RR->identity.toString(false); - RR->secretIdentityStr = RR->identity.toString(true); + RR->identity.toString(false,RR->publicIdentityStr); + RR->identity.toString(true,RR->secretIdentityStr); } else { n = -1; } @@ -92,10 +92,10 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint6 idtmp[0] = RR->identity.address().toInt(); idtmp[1] = 0; if (n <= 0) { RR->identity.generate(); - RR->publicIdentityStr = RR->identity.toString(false); - RR->secretIdentityStr = RR->identity.toString(true); - stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp,RR->secretIdentityStr.data(),(unsigned int)RR->secretIdentityStr.length()); - stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr.data(),(unsigned int)RR->publicIdentityStr.length()); + RR->identity.toString(false,RR->publicIdentityStr); + RR->identity.toString(true,RR->secretIdentityStr); + stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp,RR->secretIdentityStr,(unsigned int)strlen(RR->secretIdentityStr)); + stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr)); } else { n = stateObjectGet(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,tmp,sizeof(tmp) - 1); if (n > 0) { @@ -104,7 +104,7 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint6 n = -1; } if (n <= 0) - stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr.data(),(unsigned int)RR->publicIdentityStr.length()); + stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr)); } try { @@ -386,8 +386,8 @@ uint64_t Node::address() const void Node::status(ZT_NodeStatus *status) const { status->address = RR->identity.address().toInt(); - status->publicIdentity = RR->publicIdentityStr.c_str(); - status->secretIdentity = RR->secretIdentityStr.c_str(); + status->publicIdentity = RR->publicIdentityStr; + status->secretIdentity = RR->secretIdentityStr; status->online = _online ? 1 : 0; } @@ -544,39 +544,6 @@ bool Node::shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,cons return ( (_cb.pathCheckFunction) ? (_cb.pathCheckFunction(reinterpret_cast(this),_uPtr,tPtr,ztaddr.toInt(),localSocket,reinterpret_cast(&remoteAddress)) != 0) : true); } -#ifdef ZT_TRACE -void Node::postTrace(const char *module,unsigned int line,const char *fmt,...) -{ - static Mutex traceLock; - - va_list ap; - char tmp1[1024],tmp2[1024],tmp3[256]; - - Mutex::Lock _l(traceLock); - - time_t now = (time_t)(_now / 1000ULL); -#ifdef __WINDOWS__ - ctime_s(tmp3,sizeof(tmp3),&now); - char *nowstr = tmp3; -#else - char *nowstr = ctime_r(&now,tmp3); -#endif - unsigned long nowstrlen = (unsigned long)strlen(nowstr); - if (nowstr[nowstrlen-1] == '\n') - nowstr[--nowstrlen] = (char)0; - if (nowstr[nowstrlen-1] == '\r') - nowstr[--nowstrlen] = (char)0; - - va_start(ap,fmt); - vsnprintf(tmp2,sizeof(tmp2),fmt,ap); - va_end(ap); - tmp2[sizeof(tmp2)-1] = (char)0; - - Utils::ztsnprintf(tmp1,sizeof(tmp1),"[%s] %s:%u %s",nowstr,module,line,tmp2); - postEvent((void *)0,ZT_EVENT_TRACE,tmp1); -} -#endif // ZT_TRACE - uint64_t Node::prng() { // https://en.wikipedia.org/wiki/Xorshift#xorshift.2B diff --git a/node/Node.hpp b/node/Node.hpp index 55491b06..40903f7c 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -195,10 +195,6 @@ public: inline void stateObjectPut(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2],const void *const data,const unsigned int len) { _cb.statePutFunction(reinterpret_cast(this),_uPtr,tPtr,type,id,data,(int)len); } inline void stateObjectDelete(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2]) { _cb.statePutFunction(reinterpret_cast(this),_uPtr,tPtr,type,id,(const void *)0,-1); } -#ifdef ZT_TRACE - void postTrace(const char *module,unsigned int line,const char *fmt,...); -#endif - bool shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,const int64_t localSocket,const InetAddress &remoteAddress); inline bool externalPathLookup(void *tPtr,const Address &ztaddr,int family,InetAddress &addr) { return ( (_cb.pathLookupFunction) ? (_cb.pathLookupFunction(reinterpret_cast(this),_uPtr,tPtr,ztaddr.toInt(),family,reinterpret_cast(&addr)) != 0) : false ); } diff --git a/node/RuntimeEnvironment.hpp b/node/RuntimeEnvironment.hpp index 99afe25d..94b96d34 100644 --- a/node/RuntimeEnvironment.hpp +++ b/node/RuntimeEnvironment.hpp @@ -27,7 +27,7 @@ #ifndef ZT_RUNTIMEENVIRONMENT_HPP #define ZT_RUNTIMEENVIRONMENT_HPP -#include +#include #include "Constants.hpp" #include "Utils.hpp" @@ -60,11 +60,13 @@ public: ,sa((SelfAwareness *)0) { Utils::getSecureRandom(&instanceId,sizeof(instanceId)); + memset(publicIdentityStr,0,sizeof(publicIdentityStr)); + memset(secretIdentityStr,0,sizeof(secretIdentityStr)); } ~RuntimeEnvironment() { - Utils::burn(reinterpret_cast(const_cast(secretIdentityStr.data())),(unsigned int)secretIdentityStr.length()); + Utils::burn(secretIdentityStr,sizeof(secretIdentityStr)); } /** @@ -77,8 +79,8 @@ public: // This node's identity Identity identity; - std::string publicIdentityStr; - std::string secretIdentityStr; + char publicIdentityStr[ZT_IDENTITY_STRING_BUFFER_LENGTH]; + char secretIdentityStr[ZT_IDENTITY_STRING_BUFFER_LENGTH]; // This is set externally to an instance of this base class NetworkController *localNetworkController; diff --git a/node/Topology.cpp b/node/Topology.cpp index 809bc7e7..e7bbdfae 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -91,12 +91,8 @@ Topology::Topology(const RuntimeEnvironment *renv,void *tPtr) : SharedPtr Topology::addPeer(void *tPtr,const SharedPtr &peer) { #ifdef ZT_TRACE - if ((!peer)||(peer->address() == RR->identity.address())) { - if (!peer) - fprintf(stderr,"FATAL BUG: addPeer() caught attempt to add NULL peer" ZT_EOL_S); - else fprintf(stderr,"FATAL BUG: addPeer() caught attempt to add peer for self" ZT_EOL_S); - abort(); - } + if ((!peer)||(peer->address() == RR->identity.address())) + return SharedPtr(); #endif SharedPtr np; diff --git a/node/Utils.cpp b/node/Utils.cpp index d2321e16..a3a4c3c3 100644 --- a/node/Utils.cpp +++ b/node/Utils.cpp @@ -55,90 +55,35 @@ namespace ZeroTier { const char Utils::HEXCHARS[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' }; -// Crazy hack to force memory to be securely zeroed in spite of the best efforts of optimizing compilers. -static void _Utils_doBurn(volatile uint8_t *ptr,unsigned int len) -{ - volatile uint8_t *const end = ptr + len; - while (ptr != end) *(ptr++) = (uint8_t)0; -} -static void (*volatile _Utils_doBurn_ptr)(volatile uint8_t *,unsigned int) = _Utils_doBurn; -void Utils::burn(void *ptr,unsigned int len) { (_Utils_doBurn_ptr)((volatile uint8_t *)ptr,len); } - -std::string Utils::hex(const void *data,unsigned int len) +static unsigned long _Utils_itoa(unsigned long n,char *s) { - std::string r; - r.reserve(len * 2); - for(unsigned int i=0;i> 4]); - r.push_back(HEXCHARS[((const unsigned char *)data)[i] & 0x0f]); - } - return r; + if (n == 0) + return 0; + unsigned long pos = _Utils_itoa(n / 10,s); + if (pos >= 22) // sanity check, should be impossible + pos = 22; + s[pos] = '0' + (char)(n % 10); + return pos + 1; } - -std::string Utils::unhex(const char *hex,unsigned int maxlen) +char *Utils::decimal(unsigned long n,char s[24]) { - int n = 1; - unsigned char c,b = 0; - const char *eof = hex + maxlen; - std::string r; - - if (!maxlen) - return r; - - while ((c = (unsigned char)*(hex++))) { - if ((c >= 48)&&(c <= 57)) { // 0..9 - if ((n ^= 1)) - r.push_back((char)(b | (c - 48))); - else b = (c - 48) << 4; - } else if ((c >= 65)&&(c <= 70)) { // A..F - if ((n ^= 1)) - r.push_back((char)(b | (c - (65 - 10)))); - else b = (c - (65 - 10)) << 4; - } else if ((c >= 97)&&(c <= 102)) { // a..f - if ((n ^= 1)) - r.push_back((char)(b | (c - (97 - 10)))); - else b = (c - (97 - 10)) << 4; - } - if (hex == eof) - break; + if (n == 0) { + s[0] = '0'; + s[1] = (char)0; + return s; } - - return r; + s[_Utils_itoa(n,s)] = (char)0; + return s; } -unsigned int Utils::unhex(const char *hex,unsigned int maxlen,void *buf,unsigned int len) +// Crazy hack to force memory to be securely zeroed in spite of the best efforts of optimizing compilers. +static void _Utils_doBurn(volatile uint8_t *ptr,unsigned int len) { - int n = 1; - unsigned char c,b = 0; - unsigned int l = 0; - const char *eof = hex + maxlen; - - if (!maxlen) - return 0; - - while ((c = (unsigned char)*(hex++))) { - if ((c >= 48)&&(c <= 57)) { // 0..9 - if ((n ^= 1)) { - if (l >= len) break; - ((unsigned char *)buf)[l++] = (b | (c - 48)); - } else b = (c - 48) << 4; - } else if ((c >= 65)&&(c <= 70)) { // A..F - if ((n ^= 1)) { - if (l >= len) break; - ((unsigned char *)buf)[l++] = (b | (c - (65 - 10))); - } else b = (c - (65 - 10)) << 4; - } else if ((c >= 97)&&(c <= 102)) { // a..f - if ((n ^= 1)) { - if (l >= len) break; - ((unsigned char *)buf)[l++] = (b | (c - (97 - 10))); - } else b = (c - (97 - 10)) << 4; - } - if (hex == eof) - break; - } - - return l; + volatile uint8_t *const end = ptr + len; + while (ptr != end) *(ptr++) = (uint8_t)0; } +static void (*volatile _Utils_doBurn_ptr)(volatile uint8_t *,unsigned int) = _Utils_doBurn; +void Utils::burn(void *ptr,unsigned int len) { (_Utils_doBurn_ptr)((volatile uint8_t *)ptr,len); } void Utils::getSecureRandom(void *buf,unsigned int bytes) { @@ -244,21 +189,4 @@ bool Utils::scopy(char *dest,unsigned int len,const char *src) return true; } -unsigned int Utils::ztsnprintf(char *buf,unsigned int len,const char *fmt,...) -{ - va_list ap; - - va_start(ap,fmt); - int n = (int)vsnprintf(buf,len,fmt,ap); - va_end(ap); - - if ((n >= (int)len)||(n < 0)) { - if (len) - buf[len - 1] = (char)0; - throw std::length_error("buf[] overflow"); - } - - return (unsigned int)n; -} - } // namespace ZeroTier diff --git a/node/Utils.hpp b/node/Utils.hpp index 212ef247..5a5e9f39 100644 --- a/node/Utils.hpp +++ b/node/Utils.hpp @@ -70,42 +70,144 @@ public: static void burn(void *ptr,unsigned int len); /** - * Convert binary data to hexadecimal - * - * @param data Data to convert to hex - * @param len Length of data - * @return Hexadecimal string + * @param n Number to convert + * @param s Buffer, at least 24 bytes in size + * @return String containing 'n' in base 10 form */ - static std::string hex(const void *data,unsigned int len); - static inline std::string hex(const std::string &data) { return hex(data.data(),(unsigned int)data.length()); } + static char *decimal(unsigned long n,char s[24]); - /** - * Convert hexadecimal to binary data - * - * This ignores all non-hex characters, just stepping over them and - * continuing. Upper and lower case are supported for letters a-f. - * - * @param hex Hexadecimal ASCII code (non-hex chars are ignored, stops at zero or maxlen) - * @param maxlen Maximum length of hex string buffer - * @return Binary data - */ - static std::string unhex(const char *hex,unsigned int maxlen); - static inline std::string unhex(const std::string &hex) { return unhex(hex.c_str(),(unsigned int)hex.length()); } + static inline char *hex(uint64_t i,char *const s) + { + s[0] = HEXCHARS[(i >> 60) & 0xf]; + s[1] = HEXCHARS[(i >> 56) & 0xf]; + s[2] = HEXCHARS[(i >> 52) & 0xf]; + s[3] = HEXCHARS[(i >> 48) & 0xf]; + s[4] = HEXCHARS[(i >> 44) & 0xf]; + s[5] = HEXCHARS[(i >> 40) & 0xf]; + s[6] = HEXCHARS[(i >> 36) & 0xf]; + s[7] = HEXCHARS[(i >> 32) & 0xf]; + s[8] = HEXCHARS[(i >> 28) & 0xf]; + s[9] = HEXCHARS[(i >> 24) & 0xf]; + s[10] = HEXCHARS[(i >> 20) & 0xf]; + s[11] = HEXCHARS[(i >> 16) & 0xf]; + s[12] = HEXCHARS[(i >> 12) & 0xf]; + s[13] = HEXCHARS[(i >> 8) & 0xf]; + s[14] = HEXCHARS[(i >> 4) & 0xf]; + s[15] = HEXCHARS[i & 0xf]; + s[16] = (char)0; + return s; + } - /** - * Convert hexadecimal to binary data - * - * This ignores all non-hex characters, just stepping over them and - * continuing. Upper and lower case are supported for letters a-f. - * - * @param hex Hexadecimal ASCII - * @param maxlen Maximum length of hex string buffer - * @param buf Buffer to fill - * @param len Length of buffer - * @return Number of characters actually written - */ - static unsigned int unhex(const char *hex,unsigned int maxlen,void *buf,unsigned int len); - static inline unsigned int unhex(const std::string &hex,void *buf,unsigned int len) { return unhex(hex.c_str(),(unsigned int)hex.length(),buf,len); } + static inline char *hex10(uint64_t i,char *const s) + { + s[0] = HEXCHARS[(i >> 36) & 0xf]; + s[1] = HEXCHARS[(i >> 32) & 0xf]; + s[2] = HEXCHARS[(i >> 28) & 0xf]; + s[3] = HEXCHARS[(i >> 24) & 0xf]; + s[4] = HEXCHARS[(i >> 20) & 0xf]; + s[5] = HEXCHARS[(i >> 16) & 0xf]; + s[6] = HEXCHARS[(i >> 12) & 0xf]; + s[7] = HEXCHARS[(i >> 8) & 0xf]; + s[8] = HEXCHARS[(i >> 4) & 0xf]; + s[9] = HEXCHARS[i & 0xf]; + s[10] = (char)0; + return s; + } + + static inline char *hex(uint16_t i,char *const s) + { + s[0] = HEXCHARS[(i >> 12) & 0xf]; + s[1] = HEXCHARS[(i >> 8) & 0xf]; + s[2] = HEXCHARS[(i >> 4) & 0xf]; + s[3] = HEXCHARS[i & 0xf]; + s[4] = (char)0; + return s; + } + + static inline char *hex(uint8_t i,char *const s) + { + s[0] = HEXCHARS[(i >> 4) & 0xf]; + s[1] = HEXCHARS[i & 0xf]; + s[2] = (char)0; + return s; + } + + static inline char *hex(const void *d,unsigned int l,char *s) + { + char *save = s; + for(unsigned int i=0;i(d)[i]; + *(s++) = HEXCHARS[(b >> 4) & 0xf]; + *(s++) = HEXCHARS[b & 0xf]; + } + *s = (char)0; + return save; + } + + static inline unsigned int unhex(const char *h,void *buf,unsigned int buflen) + { + unsigned int l = 0; + while (l < buflen) { + uint8_t hc = (uint8_t)*(h++); + if (!hc) break; + + uint8_t c = 0; + if ((hc >= 48)&&(hc <= 57)) + c = hc - 48; + else if ((hc >= 97)&&(hc <= 102)) + c = hc - 87; + else if ((hc >= 65)&&(hc <= 70)) + c = hc - 55; + + hc = (uint8_t)*(h++); + if (!hc) break; + + c <<= 4; + if ((hc >= 48)&&(hc <= 57)) + c |= hc - 48; + else if ((hc >= 97)&&(hc <= 102)) + c |= hc - 87; + else if ((hc >= 65)&&(hc <= 70)) + c |= hc - 55; + + reinterpret_cast(buf)[l++] = c; + } + return l; + } + + static inline unsigned int unhex(const char *h,unsigned int hlen,void *buf,unsigned int buflen) + { + unsigned int l = 0; + const char *hend = h + hlen; + while (l < buflen) { + if (h == hend) break; + uint8_t hc = (uint8_t)*(h++); + if (!hc) break; + + uint8_t c = 0; + if ((hc >= 48)&&(hc <= 57)) + c = hc - 48; + else if ((hc >= 97)&&(hc <= 102)) + c = hc - 87; + else if ((hc >= 65)&&(hc <= 70)) + c = hc - 55; + + if (h == hend) break; + hc = (uint8_t)*(h++); + if (!hc) break; + + c <<= 4; + if ((hc >= 48)&&(hc <= 57)) + c |= hc - 48; + else if ((hc >= 97)&&(hc <= 102)) + c |= hc - 87; + else if ((hc >= 65)&&(hc <= 70)) + c |= hc - 55; + + reinterpret_cast(buf)[l++] = c; + } + return l; + } /** * Generate secure random bytes @@ -232,20 +334,6 @@ public: */ static bool scopy(char *dest,unsigned int len,const char *src); - /** - * Variant of snprintf that is portable and throws an exception - * - * This just wraps the local implementation whatever it's called, while - * performing a few other checks and adding exceptions for overflow. - * - * @param buf Buffer to write to - * @param len Length of buffer in bytes - * @param fmt Format string - * @param ... Format arguments - * @throws std::length_error buf[] too short (buf[] will still be left null-terminated) - */ - static unsigned int ztsnprintf(char *buf,unsigned int len,const char *fmt,...); - /** * Count the number of bits set in an integer * diff --git a/one.cpp b/one.cpp index cbf09121..b1a19e8c 100644 --- a/one.cpp +++ b/one.cpp @@ -260,9 +260,9 @@ static int cli(int argc,char **argv) if (hd) { char p[4096]; #ifdef __APPLE__ - Utils::ztsnprintf(p,sizeof(p),"%s/Library/Application Support/ZeroTier/One/authtoken.secret",hd); + OSUtils::ztsnprintf(p,sizeof(p),"%s/Library/Application Support/ZeroTier/One/authtoken.secret",hd); #else - Utils::ztsnprintf(p,sizeof(p),"%s/.zeroTierOneAuthToken",hd); + OSUtils::ztsnprintf(p,sizeof(p),"%s/.zeroTierOneAuthToken",hd); #endif OSUtils::readFile(p,authToken); } @@ -278,7 +278,7 @@ static int cli(int argc,char **argv) InetAddress addr; { char addrtmp[256]; - Utils::ztsnprintf(addrtmp,sizeof(addrtmp),"%s/%u",ip.c_str(),port); + OSUtils::ztsnprintf(addrtmp,sizeof(addrtmp),"%s/%u",ip.c_str(),port); addr = InetAddress(addrtmp); } @@ -366,7 +366,7 @@ static int cli(int argc,char **argv) std::string addr = path["address"]; const uint64_t now = OSUtils::now(); const double lq = (path.count("linkQuality")) ? (double)path["linkQuality"] : -1.0; - Utils::ztsnprintf(tmp,sizeof(tmp),"%s;%llu;%llu;%1.2f",addr.c_str(),now - (uint64_t)path["lastSend"],now - (uint64_t)path["lastReceive"],lq); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%s;%llu;%llu;%1.2f",addr.c_str(),now - (uint64_t)path["lastSend"],now - (uint64_t)path["lastReceive"],lq); bestPath = tmp; break; } @@ -378,7 +378,7 @@ static int cli(int argc,char **argv) int64_t vmin = p["versionMinor"]; int64_t vrev = p["versionRev"]; if (vmaj >= 0) { - Utils::ztsnprintf(ver,sizeof(ver),"%lld.%lld.%lld",vmaj,vmin,vrev); + OSUtils::ztsnprintf(ver,sizeof(ver),"%lld.%lld.%lld",vmaj,vmin,vrev); } else { ver[0] = '-'; ver[1] = (char)0; @@ -527,9 +527,9 @@ static int cli(int argc,char **argv) const uint64_t seed = Utils::hexStrToU64(arg2.c_str()); if ((worldId)&&(seed)) { char jsons[1024]; - Utils::ztsnprintf(jsons,sizeof(jsons),"{\"seed\":\"%s\"}",arg2.c_str()); + OSUtils::ztsnprintf(jsons,sizeof(jsons),"{\"seed\":\"%s\"}",arg2.c_str()); char cl[128]; - Utils::ztsnprintf(cl,sizeof(cl),"%u",(unsigned int)strlen(jsons)); + OSUtils::ztsnprintf(cl,sizeof(cl),"%u",(unsigned int)strlen(jsons)); requestHeaders["Content-Type"] = "application/json"; requestHeaders["Content-Length"] = cl; unsigned int scode = Http::POST( @@ -579,11 +579,11 @@ static int cli(int argc,char **argv) if (eqidx != std::string::npos) { if ((arg2.substr(0,eqidx) == "allowManaged")||(arg2.substr(0,eqidx) == "allowGlobal")||(arg2.substr(0,eqidx) == "allowDefault")) { char jsons[1024]; - Utils::ztsnprintf(jsons,sizeof(jsons),"{\"%s\":%s}", + OSUtils::ztsnprintf(jsons,sizeof(jsons),"{\"%s\":%s}", arg2.substr(0,eqidx).c_str(), (((arg2.substr(eqidx,2) == "=t")||(arg2.substr(eqidx,2) == "=1")) ? "true" : "false")); char cl[128]; - Utils::ztsnprintf(cl,sizeof(cl),"%u",(unsigned int)strlen(jsons)); + OSUtils::ztsnprintf(cl,sizeof(cl),"%u",(unsigned int)strlen(jsons)); requestHeaders["Content-Type"] = "application/json"; requestHeaders["Content-Length"] = cl; unsigned int scode = Http::POST( @@ -648,7 +648,7 @@ static Identity getIdFromArg(char *arg) } else { // identity is to be read from a file std::string idser; if (OSUtils::readFile(arg,idser)) { - if (id.fromString(idser)) + if (id.fromString(idser.c_str())) return id; } } @@ -689,14 +689,15 @@ static int idtool(int argc,char **argv) } } - std::string idser = id.toString(true); + char idtmp[1024]; + std::string idser = id.toString(true,idtmp); if (argc >= 3) { if (!OSUtils::writeFile(argv[2],idser)) { fprintf(stderr,"Error writing to %s" ZT_EOL_S,argv[2]); return 1; } else printf("%s written" ZT_EOL_S,argv[2]); if (argc >= 4) { - idser = id.toString(false); + idser = id.toString(false,idtmp); if (!OSUtils::writeFile(argv[3],idser)) { fprintf(stderr,"Error writing to %s" ZT_EOL_S,argv[3]); return 1; @@ -731,7 +732,8 @@ static int idtool(int argc,char **argv) return 1; } - printf("%s",id.toString(false).c_str()); + char idtmp[1024]; + printf("%s",id.toString(false,idtmp)); } else if (!strcmp(argv[1],"sign")) { if (argc < 4) { idtoolPrintHelp(stdout,argv[0]); @@ -755,7 +757,8 @@ static int idtool(int argc,char **argv) return 1; } C25519::Signature signature = id.sign(inf.data(),(unsigned int)inf.length()); - printf("%s",Utils::hex(signature.data,(unsigned int)signature.size()).c_str()); + char hexbuf[1024]; + printf("%s",Utils::hex(signature.data,(unsigned int)signature.size(),hexbuf)); } else if (!strcmp(argv[1],"verify")) { if (argc < 4) { idtoolPrintHelp(stdout,argv[0]); @@ -774,7 +777,8 @@ static int idtool(int argc,char **argv) return 1; } - std::string signature(Utils::unhex(argv[4])); + char buf[4096]; + std::string signature(buf,Utils::unhex(argv[4],buf,(unsigned int)sizeof(buf))); if ((signature.length() > ZT_ADDRESS_LENGTH)&&(id.verify(inf.data(),(unsigned int)inf.length(),signature.data(),(unsigned int)signature.length()))) { printf("%s signature valid" ZT_EOL_S,argv[3]); } else { @@ -793,14 +797,15 @@ static int idtool(int argc,char **argv) C25519::Pair kp(C25519::generate()); + char idtmp[4096]; nlohmann::json mj; mj["objtype"] = "world"; mj["worldType"] = "moon"; - mj["updatesMustBeSignedBy"] = mj["signingKey"] = Utils::hex(kp.pub.data,(unsigned int)kp.pub.size()); - mj["signingKey_SECRET"] = Utils::hex(kp.priv.data,(unsigned int)kp.priv.size()); - mj["id"] = id.address().toString(); + mj["updatesMustBeSignedBy"] = mj["signingKey"] = Utils::hex(kp.pub.data,(unsigned int)kp.pub.size(),idtmp); + mj["signingKey_SECRET"] = Utils::hex(kp.priv.data,(unsigned int)kp.priv.size(),idtmp); + mj["id"] = id.address().toString(idtmp); nlohmann::json seedj; - seedj["identity"] = id.toString(false); + seedj["identity"] = id.toString(false,idtmp); seedj["stableEndpoints"] = nlohmann::json::array(); (mj["roots"] = nlohmann::json::array()).push_back(seedj); std::string mjd(OSUtils::jsonDump(mj)); @@ -836,9 +841,9 @@ static int idtool(int argc,char **argv) C25519::Pair signingKey; C25519::Public updatesMustBeSignedBy; - Utils::unhex(OSUtils::jsonString(mj["signingKey"],""),signingKey.pub.data,(unsigned int)signingKey.pub.size()); - Utils::unhex(OSUtils::jsonString(mj["signingKey_SECRET"],""),signingKey.priv.data,(unsigned int)signingKey.priv.size()); - Utils::unhex(OSUtils::jsonString(mj["updatesMustBeSignedBy"],""),updatesMustBeSignedBy.data,(unsigned int)updatesMustBeSignedBy.size()); + Utils::unhex(OSUtils::jsonString(mj["signingKey"],"").c_str(),signingKey.pub.data,(unsigned int)signingKey.pub.size()); + Utils::unhex(OSUtils::jsonString(mj["signingKey_SECRET"],"").c_str(),signingKey.priv.data,(unsigned int)signingKey.priv.size()); + Utils::unhex(OSUtils::jsonString(mj["updatesMustBeSignedBy"],"").c_str(),updatesMustBeSignedBy.data,(unsigned int)updatesMustBeSignedBy.size()); std::vector roots; nlohmann::json &rootsj = mj["roots"]; @@ -847,11 +852,11 @@ static int idtool(int argc,char **argv) nlohmann::json &r = rootsj[i]; if (r.is_object()) { roots.push_back(World::Root()); - roots.back().identity = Identity(OSUtils::jsonString(r["identity"],"")); + roots.back().identity = Identity(OSUtils::jsonString(r["identity"],"").c_str()); nlohmann::json &stableEndpointsj = r["stableEndpoints"]; if (stableEndpointsj.is_array()) { for(unsigned long k=0;k<(unsigned long)stableEndpointsj.size();++k) - roots.back().stableEndpoints.push_back(InetAddress(OSUtils::jsonString(stableEndpointsj[k],""))); + roots.back().stableEndpoints.push_back(InetAddress(OSUtils::jsonString(stableEndpointsj[k],"").c_str())); std::sort(roots.back().stableEndpoints.begin(),roots.back().stableEndpoints.end()); } } @@ -864,7 +869,7 @@ static int idtool(int argc,char **argv) Buffer wbuf; w.serialize(wbuf); char fn[128]; - Utils::ztsnprintf(fn,sizeof(fn),"%.16llx.moon",w.id()); + OSUtils::ztsnprintf(fn,sizeof(fn),"%.16llx.moon",w.id()); OSUtils::writeFile(fn,wbuf.data(),wbuf.size()); printf("wrote %s (signed world with timestamp %llu)" ZT_EOL_S,fn,(unsigned long long)now); } diff --git a/osdep/BSDEthernetTap.cpp b/osdep/BSDEthernetTap.cpp index f07f9e5a..8e57d605 100644 --- a/osdep/BSDEthernetTap.cpp +++ b/osdep/BSDEthernetTap.cpp @@ -114,8 +114,8 @@ BSDEthernetTap::BSDEthernetTap( std::vector devFiles(OSUtils::listDirectory("/dev")); for(int i=9993;i<(9993+128);++i) { - Utils::ztsnprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i); - Utils::ztsnprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname); + OSUtils::ztsnprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i); + OSUtils::ztsnprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname); if (std::find(devFiles.begin(),devFiles.end(),std::string(tmpdevname)) == devFiles.end()) { long cpid = (long)vfork(); if (cpid == 0) { @@ -152,8 +152,8 @@ BSDEthernetTap::BSDEthernetTap( /* Other BSDs like OpenBSD only have a limited number of tap devices that cannot be renamed */ for(int i=0;i<64;++i) { - Utils::ztsnprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i); - Utils::ztsnprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname); + OSUtils::ztsnprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i); + OSUtils::ztsnprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname); _fd = ::open(devpath,O_RDWR); if (_fd > 0) { _dev = tmpdevname; @@ -171,9 +171,9 @@ BSDEthernetTap::BSDEthernetTap( } // Configure MAC address and MTU, bring interface up - Utils::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]); - Utils::ztsnprintf(mtustr,sizeof(mtustr),"%u",_mtu); - Utils::ztsnprintf(metstr,sizeof(metstr),"%u",_metric); + 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); @@ -256,7 +256,8 @@ bool BSDEthernetTap::addIp(const InetAddress &ip) long cpid = (long)vfork(); if (cpid == 0) { - ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),ip.isV4() ? "inet" : "inet6",ip.toString().c_str(),"alias",(const char *)0); + char tmp[128]; + ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),ip.isV4() ? "inet" : "inet6",ip.toString(tmp),"alias",(const char *)0); ::_exit(-1); } else if (cpid > 0) { int exitcode = -1; @@ -385,7 +386,7 @@ void BSDEthernetTap::setMtu(unsigned int mtu) long cpid = (long)vfork(); if (cpid == 0) { char tmp[64]; - Utils::ztsnprintf(tmp,sizeof(tmp),"%u",mtu); + 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) { diff --git a/osdep/Http.cpp b/osdep/Http.cpp index 3c556f44..d6d0238c 100644 --- a/osdep/Http.cpp +++ b/osdep/Http.cpp @@ -244,10 +244,10 @@ unsigned int Http::_do( try { char tmp[1024]; - Utils::ztsnprintf(tmp,sizeof(tmp),"%s %s HTTP/1.1\r\n",method,path); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%s %s HTTP/1.1\r\n",method,path); handler.writeBuf.append(tmp); for(std::map::const_iterator h(requestHeaders.begin());h!=requestHeaders.end();++h) { - Utils::ztsnprintf(tmp,sizeof(tmp),"%s: %s\r\n",h->first.c_str(),h->second.c_str()); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%s: %s\r\n",h->first.c_str(),h->second.c_str()); handler.writeBuf.append(tmp); } handler.writeBuf.append("\r\n"); diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index fc5199f1..c8f9ef9d 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -97,7 +97,7 @@ LinuxEthernetTap::LinuxEthernetTap( char procpath[128],nwids[32]; struct stat sbuf; - Utils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid); + OSUtils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid); Mutex::Lock _l(__tapCreateLock); // create only one tap at a time, globally @@ -134,7 +134,7 @@ LinuxEthernetTap::LinuxEthernetTap( std::map::const_iterator gdmEntry = globalDeviceMap.find(nwids); if (gdmEntry != globalDeviceMap.end()) { Utils::scopy(ifr.ifr_name,sizeof(ifr.ifr_name),gdmEntry->second.c_str()); - Utils::ztsnprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); + OSUtils::ztsnprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); recalledDevice = (stat(procpath,&sbuf) != 0); } @@ -142,8 +142,8 @@ LinuxEthernetTap::LinuxEthernetTap( #ifdef __SYNOLOGY__ int devno = 50; do { - Utils::ztsnprintf(ifr.ifr_name,sizeof(ifr.ifr_name),"eth%d",devno++); - Utils::ztsnprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); + OSUtils::ztsnprintf(ifr.ifr_name,sizeof(ifr.ifr_name),"eth%d",devno++); + OSUtils::ztsnprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); } while (stat(procpath,&sbuf) == 0); // try zt#++ until we find one that does not exist #else char devno = 0; @@ -158,7 +158,7 @@ LinuxEthernetTap::LinuxEthernetTap( _base32_5_to_8(reinterpret_cast(tmp2) + 5,tmp3 + 10); tmp3[15] = (char)0; memcpy(ifr.ifr_name,tmp3,16); - Utils::ztsnprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); + OSUtils::ztsnprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); } while (stat(procpath,&sbuf) == 0); #endif } @@ -264,7 +264,8 @@ static bool ___removeIp(const std::string &_dev,const InetAddress &ip) if (cpid == 0) { OSUtils::redirectUnixOutputs("/dev/null",(const char *)0); setenv("PATH", "/sbin:/bin:/usr/sbin:/usr/bin", 1); - ::execlp("ip","ip","addr","del",ip.toString().c_str(),"dev",_dev.c_str(),(const char *)0); + char iptmp[128]; + ::execlp("ip","ip","addr","del",ip.toString(iptmp),"dev",_dev.c_str(),(const char *)0); ::_exit(-1); } else { int exitcode = -1; @@ -296,25 +297,28 @@ bool LinuxEthernetTap::addIpSyn(std::vector ips) // Assemble and write contents of ifcfg-dev file for(int i=0; i<(int)ips.size(); i++) { if (ips[i].isV4()) { + char iptmp[64],iptmp2[64]; std::string numstr4 = ip4_tot > 1 ? std::to_string(ip4) : ""; - cfg_contents += "\nIPADDR"+numstr4+"="+ips[i].toIpString() - + "\nNETMASK"+numstr4+"="+ips[i].netmask().toIpString()+"\n"; + cfg_contents += "\nIPADDR"+numstr4+"="+ips[i].toIpString(iptmp) + + "\nNETMASK"+numstr4+"="+ips[i].netmask().toIpString(iptmp2)+"\n"; ip4++; } else { + char iptmp[64],iptmp2[64]; std::string numstr6 = ip6_tot > 1 ? std::to_string(ip6) : ""; - cfg_contents += "\nIPV6ADDR"+numstr6+"="+ips[i].toIpString() - + "\nNETMASK"+numstr6+"="+ips[i].netmask().toIpString()+"\n"; + cfg_contents += "\nIPV6ADDR"+numstr6+"="+ips[i].toIpString(iptmp) + + "\nNETMASK"+numstr6+"="+ips[i].netmask().toIpString(iptmp2)+"\n"; ip6++; } } OSUtils::writeFile(filepath.c_str(), cfg_contents.c_str(), cfg_contents.length()); // Finaly, add IPs for(int i=0; i<(int)ips.size(); i++){ + char iptmp[128],iptmp2[128[; if (ips[i].isV4()) - ::execlp("ip","ip","addr","add",ips[i].toString().c_str(),"broadcast",ips[i].broadcast().toIpString().c_str(),"dev",_dev.c_str(),(const char *)0); + ::execlp("ip","ip","addr","add",ips[i].toString(iptmp),"broadcast",ips[i].broadcast().toIpString(iptmp2),"dev",_dev.c_str(),(const char *)0); else - ::execlp("ip","ip","addr","add",ips[i].toString().c_str(),"dev",_dev.c_str(),(const char *)0); + ::execlp("ip","ip","addr","add",ips[i].toString(iptmp),"dev",_dev.c_str(),(const char *)0); } ::_exit(-1); } else if (cpid > 0) { @@ -345,10 +349,11 @@ bool LinuxEthernetTap::addIp(const InetAddress &ip) if (cpid == 0) { OSUtils::redirectUnixOutputs("/dev/null",(const char *)0); setenv("PATH", "/sbin:/bin:/usr/sbin:/usr/bin", 1); + char iptmp[128],iptmp2[128]; if (ip.isV4()) { - ::execlp("ip","ip","addr","add",ip.toString().c_str(),"broadcast",ip.broadcast().toIpString().c_str(),"dev",_dev.c_str(),(const char *)0); + ::execlp("ip","ip","addr","add",ip.toString(iptmp),"broadcast",ip.broadcast().toIpString(iptmp2),"dev",_dev.c_str(),(const char *)0); } else { - ::execlp("ip","ip","addr","add",ip.toString().c_str(),"dev",_dev.c_str(),(const char *)0); + ::execlp("ip","ip","addr","add",ip.toString(iptmp),"dev",_dev.c_str(),(const char *)0); } ::_exit(-1); } else if (cpid > 0) { diff --git a/osdep/ManagedRoute.cpp b/osdep/ManagedRoute.cpp index fca1c290..3a0b8a7e 100644 --- a/osdep/ManagedRoute.cpp +++ b/osdep/ManagedRoute.cpp @@ -246,7 +246,6 @@ static std::vector<_RTE> _getRTEs(const InetAddress &target,bool contains) static void _routeCmd(const char *op,const InetAddress &target,const InetAddress &via,const char *ifscope,const char *localInterface) { - //printf("route %s %s %s %s %s\n",op,target.toString().c_str(),(via) ? via.toString().c_str() : "(null)",(ifscope) ? ifscope : "(null)",(localInterface) ? localInterface : "(null)"); long p = (long)fork(); if (p > 0) { int exitcode = -1; @@ -254,17 +253,19 @@ static void _routeCmd(const char *op,const InetAddress &target,const InetAddress } else if (p == 0) { ::close(STDOUT_FILENO); ::close(STDERR_FILENO); + char ttmp[64]; + char iptmp[64]; if (via) { if ((ifscope)&&(ifscope[0])) { - ::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,op,"-ifscope",ifscope,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString().c_str(),via.toIpString().c_str(),(const char *)0); + ::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,op,"-ifscope",ifscope,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString(ttmp),via.toIpString(iptmp),(const char *)0); } else { - ::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,op,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString().c_str(),via.toIpString().c_str(),(const char *)0); + ::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,op,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString(ttmp),via.toIpString(iptmp),(const char *)0); } } else if ((localInterface)&&(localInterface[0])) { if ((ifscope)&&(ifscope[0])) { - ::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,op,"-ifscope",ifscope,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString().c_str(),"-interface",localInterface,(const char *)0); + ::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,op,"-ifscope",ifscope,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString(ttmp),"-interface",localInterface,(const char *)0); } else { - ::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,op,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString().c_str(),"-interface",localInterface,(const char *)0); + ::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,op,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString(ttmp),"-interface",localInterface,(const char *)0); } } ::_exit(-1); diff --git a/osdep/OSUtils.cpp b/osdep/OSUtils.cpp index 06508e77..882b8255 100644 --- a/osdep/OSUtils.cpp +++ b/osdep/OSUtils.cpp @@ -57,6 +57,23 @@ namespace ZeroTier { +unsigned int OSUtils::ztsnprintf(char *buf,unsigned int len,const char *fmt,...) +{ + va_list ap; + + va_start(ap,fmt); + int n = (int)vsnprintf(buf,len,fmt,ap); + va_end(ap); + + if ((n >= (int)len)||(n < 0)) { + if (len) + buf[len - 1] = (char)0; + throw std::length_error("buf[] overflow"); + } + + return (unsigned int)n; +} + #ifdef __UNIX_LIKE__ bool OSUtils::redirectUnixOutputs(const char *stdoutPath,const char *stderrPath) throw() @@ -134,7 +151,7 @@ long OSUtils::cleanDirectory(const char *path,const uint64_t olderThan) if (date.QuadPart > 0) { date.QuadPart -= adjust.QuadPart; if ((uint64_t)((date.QuadPart / 10000000) * 1000) < olderThan) { - Utils::ztsnprintf(tmp, sizeof(tmp), "%s\\%s", path, ffd.cFileName); + ztsnprintf(tmp, sizeof(tmp), "%s\\%s", path, ffd.cFileName); if (DeleteFileA(tmp)) ++cleaned; } @@ -157,7 +174,7 @@ long OSUtils::cleanDirectory(const char *path,const uint64_t olderThan) break; if (dptr) { if ((strcmp(dptr->d_name,"."))&&(strcmp(dptr->d_name,".."))&&(dptr->d_type == DT_REG)) { - Utils::ztsnprintf(tmp,sizeof(tmp),"%s/%s",path,dptr->d_name); + ztsnprintf(tmp,sizeof(tmp),"%s/%s",path,dptr->d_name); if (stat(tmp,&st) == 0) { uint64_t mt = (uint64_t)(st.st_mtime); if ((mt > 0)&&((mt * 1000) < olderThan)) { @@ -464,7 +481,7 @@ std::string OSUtils::jsonString(const nlohmann::json &jv,const char *dfl) return jv; } else if (jv.is_number()) { char tmp[64]; - Utils::ztsnprintf(tmp,sizeof(tmp),"%llu",(uint64_t)jv); + ztsnprintf(tmp,sizeof(tmp),"%llu",(uint64_t)jv); return tmp; } else if (jv.is_boolean()) { return ((bool)jv ? std::string("1") : std::string("0")); @@ -477,9 +494,10 @@ std::string OSUtils::jsonBinFromHex(const nlohmann::json &jv) { std::string s(jsonString(jv,"")); if (s.length() > 0) { - char *buf = new char[(s.length() / 2) + 1]; + unsigned int buflen = (s.length() / 2) + 1; + char *buf = new char[buflen]; try { - unsigned int l = Utils::unhex(s,buf,(unsigned int)s.length()); + unsigned int l = Utils::unhex(s.c_str(),buf,buflen); std::string b(buf,l); delete [] buf; return b; diff --git a/osdep/OSUtils.hpp b/osdep/OSUtils.hpp index dff7df86..d6f32822 100644 --- a/osdep/OSUtils.hpp +++ b/osdep/OSUtils.hpp @@ -33,7 +33,6 @@ #include #include -#include #include #include #include @@ -66,6 +65,20 @@ namespace ZeroTier { class OSUtils { public: + /** + * Variant of snprintf that is portable and throws an exception + * + * This just wraps the local implementation whatever it's called, while + * performing a few other checks and adding exceptions for overflow. + * + * @param buf Buffer to write to + * @param len Length of buffer in bytes + * @param fmt Format string + * @param ... Format arguments + * @throws std::length_error buf[] too short (buf[] will still be left null-terminated) + */ + static unsigned int ztsnprintf(char *buf,unsigned int len,const char *fmt,...); + #ifdef __UNIX_LIKE__ /** * Close STDOUT_FILENO and STDERR_FILENO and replace them with output to given path diff --git a/osdep/OSXEthernetTap.cpp b/osdep/OSXEthernetTap.cpp index e082408e..b43d34c0 100644 --- a/osdep/OSXEthernetTap.cpp +++ b/osdep/OSXEthernetTap.cpp @@ -336,7 +336,7 @@ OSXEthernetTap::OSXEthernetTap( char devpath[64],ethaddr[64],mtustr[32],metstr[32],nwids[32]; struct stat stattmp; - Utils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid); + OSUtils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid); Mutex::Lock _gl(globalTapCreateLock); @@ -391,13 +391,13 @@ OSXEthernetTap::OSXEthernetTap( // Open the first unused tap device if we didn't recall a previous one. if (!recalledDevice) { for(int i=0;i<64;++i) { - Utils::ztsnprintf(devpath,sizeof(devpath),"/dev/zt%d",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]; - Utils::ztsnprintf(foo,sizeof(foo),"zt%d",i); + OSUtils::ztsnprintf(foo,sizeof(foo),"zt%d",i); _dev = foo; break; } @@ -413,9 +413,9 @@ OSXEthernetTap::OSXEthernetTap( } // Configure MAC address and MTU, bring interface up - Utils::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]); - Utils::ztsnprintf(mtustr,sizeof(mtustr),"%u",_mtu); - Utils::ztsnprintf(metstr,sizeof(metstr),"%u",_metric); + 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); @@ -499,7 +499,8 @@ bool OSXEthernetTap::addIp(const InetAddress &ip) long cpid = (long)vfork(); if (cpid == 0) { - ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),(ip.ss_family == AF_INET6) ? "inet6" : "inet",ip.toString().c_str(),"alias",(const char *)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; @@ -519,7 +520,8 @@ bool OSXEthernetTap::removeIp(const InetAddress &ip) if (*i == ip) { long cpid = (long)vfork(); if (cpid == 0) { - execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),(ip.ss_family == AF_INET6) ? "inet6" : "inet",ip.toIpString().c_str(),"-alias",(const char *)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; @@ -636,7 +638,7 @@ void OSXEthernetTap::setMtu(unsigned int mtu) long cpid = (long)vfork(); if (cpid == 0) { char tmp[64]; - Utils::ztsnprintf(tmp,sizeof(tmp),"%u",mtu); + 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) { diff --git a/osdep/PortMapper.cpp b/osdep/PortMapper.cpp index df868e7a..b1990486 100644 --- a/osdep/PortMapper.cpp +++ b/osdep/PortMapper.cpp @@ -205,7 +205,7 @@ public: memset(externalip,0,sizeof(externalip)); memset(&urls,0,sizeof(urls)); memset(&data,0,sizeof(data)); - Utils::ztsnprintf(inport,sizeof(inport),"%d",localPort); + OSUtils::ztsnprintf(inport,sizeof(inport),"%d",localPort); if ((UPNP_GetValidIGD(devlist,&urls,&data,lanaddr,sizeof(lanaddr)))&&(lanaddr[0])) { #ifdef ZT_PORTMAPPER_TRACE @@ -220,7 +220,7 @@ public: int tryPort = (int)localPort + tries; if (tryPort >= 65535) tryPort = (tryPort - 65535) + 1025; - Utils::ztsnprintf(outport,sizeof(outport),"%u",tryPort); + OSUtils::ztsnprintf(outport,sizeof(outport),"%u",tryPort); // First check and see if this port is already mapped to the // same unique name. If so, keep this mapping and don't try diff --git a/osdep/WindowsEthernetTap.cpp b/osdep/WindowsEthernetTap.cpp index b96ad791..5344268f 100644 --- a/osdep/WindowsEthernetTap.cpp +++ b/osdep/WindowsEthernetTap.cpp @@ -484,7 +484,7 @@ WindowsEthernetTap::WindowsEthernetTap( char tag[24]; // We "tag" registry entries with the network ID to identify persistent devices - Utils::ztsnprintf(tag,sizeof(tag),"%.16llx",(unsigned long long)nwid); + OSUtils::ztsnprintf(tag,sizeof(tag),"%.16llx",(unsigned long long)nwid); Mutex::Lock _l(_systemTapInitLock); @@ -601,10 +601,10 @@ WindowsEthernetTap::WindowsEthernetTap( if (_netCfgInstanceId.length() > 0) { char tmps[64]; - unsigned int tmpsl = Utils::ztsnprintf(tmps,sizeof(tmps),"%.2X-%.2X-%.2X-%.2X-%.2X-%.2X",(unsigned int)mac[0],(unsigned int)mac[1],(unsigned int)mac[2],(unsigned int)mac[3],(unsigned int)mac[4],(unsigned int)mac[5]) + 1; + unsigned int tmpsl = OSUtils::ztsnprintf(tmps,sizeof(tmps),"%.2X-%.2X-%.2X-%.2X-%.2X-%.2X",(unsigned int)mac[0],(unsigned int)mac[1],(unsigned int)mac[2],(unsigned int)mac[3],(unsigned int)mac[4],(unsigned int)mac[5]) + 1; RegSetKeyValueA(nwAdapters,_mySubkeyName.c_str(),"NetworkAddress",REG_SZ,tmps,tmpsl); RegSetKeyValueA(nwAdapters,_mySubkeyName.c_str(),"MAC",REG_SZ,tmps,tmpsl); - tmpsl = Utils::ztsnprintf(tmps, sizeof(tmps), "%d", mtu); + tmpsl = OSUtils::ztsnprintf(tmps, sizeof(tmps), "%d", mtu); RegSetKeyValueA(nwAdapters,_mySubkeyName.c_str(),"MTU",REG_SZ,tmps,tmpsl); DWORD tmp = 0; @@ -879,7 +879,7 @@ void WindowsEthernetTap::setMtu(unsigned int mtu) HKEY nwAdapters; if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}", 0, KEY_READ | KEY_WRITE, &nwAdapters) == ERROR_SUCCESS) { char tmps[64]; - unsigned int tmpsl = Utils::ztsnprintf(tmps, sizeof(tmps), "%d", mtu); + unsigned int tmpsl = OSUtils::ztsnprintf(tmps, sizeof(tmps), "%d", mtu); RegSetKeyValueA(nwAdapters, _mySubkeyName.c_str(), "MTU", REG_SZ, tmps, tmpsl); RegCloseKey(nwAdapters); } @@ -902,7 +902,7 @@ void WindowsEthernetTap::threadMain() HANDLE wait4[3]; OVERLAPPED tapOvlRead,tapOvlWrite; - Utils::ztsnprintf(tapPath,sizeof(tapPath),"\\\\.\\Global\\%s.tap",_netCfgInstanceId.c_str()); + OSUtils::ztsnprintf(tapPath,sizeof(tapPath),"\\\\.\\Global\\%s.tap",_netCfgInstanceId.c_str()); try { while (_run) { diff --git a/selftest.cpp b/selftest.cpp index ff171aa3..e6705700 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -153,10 +153,11 @@ static int testCrypto() { static unsigned char buf1[16384]; static unsigned char buf2[sizeof(buf1)],buf3[sizeof(buf1)]; + static char hexbuf[1024]; for(int i=0;i<3;++i) { Utils::getSecureRandom(buf1,64); - std::cout << "[crypto] getSecureRandom: " << Utils::hex(buf1,64) << std::endl; + std::cout << "[crypto] getSecureRandom: " << Utils::hex(buf1,64,hexbuf) << std::endl; } std::cout << "[crypto] Testing Salsa20... "; std::cout.flush(); @@ -213,7 +214,7 @@ static int testCrypto() } uint64_t end = OSUtils::now(); SHA512::hash(buf1,bb,1234567); - std::cout << ((bytes / 1048576.0) / ((long double)(end - start) / 1024.0)) << " MiB/second (" << Utils::hex(buf1,16) << ')' << std::endl; + std::cout << ((bytes / 1048576.0) / ((long double)(end - start) / 1024.0)) << " MiB/second (" << Utils::hex(buf1,16,hexbuf) << ')' << std::endl; ::free((void *)bb); } @@ -265,7 +266,7 @@ static int testCrypto() } uint64_t end = OSUtils::now(); SHA512::hash(buf1,bb,1234567); - std::cout << ((bytes / 1048576.0) / ((long double)(end - start) / 1024.0)) << " MiB/second (" << Utils::hex(buf1,16) << ')' << std::endl; + std::cout << ((bytes / 1048576.0) / ((long double)(end - start) / 1024.0)) << " MiB/second (" << Utils::hex(buf1,16,hexbuf) << ')' << std::endl; ::free((void *)bb); } @@ -427,6 +428,7 @@ static int testIdentity() { Identity id; Buffer<512> buf; + char buf2[1024]; std::cout << "[identity] Validate known-good identity... "; std::cout.flush(); if (!id.fromString(KNOWN_GOOD_IDENTITY)) { @@ -459,7 +461,7 @@ static int testIdentity() uint64_t genstart = OSUtils::now(); id.generate(); uint64_t genend = OSUtils::now(); - std::cout << "(took " << (genend - genstart) << "ms): " << id.toString(true) << std::endl; + std::cout << "(took " << (genend - genstart) << "ms): " << id.toString(true,buf2) << std::endl; std::cout << "[identity] Locally validate identity: "; if (id.locallyValidate()) { std::cout << "PASS" << std::endl; @@ -499,7 +501,7 @@ static int testIdentity() { Identity id2; - id2.fromString(id.toString(true).c_str()); + id2.fromString(id.toString(true,buf2)); std::cout << "[identity] Serialize and deserialize (ASCII w/private): "; if ((id == id2)&&(id2.locallyValidate())) { std::cout << "PASS" << std::endl; @@ -511,7 +513,7 @@ static int testIdentity() { Identity id2; - id2.fromString(id.toString(false).c_str()); + id2.fromString(id.toString(false,buf2)); std::cout << "[identity] Serialize and deserialize (ASCII no private): "; if ((id == id2)&&(id2.locallyValidate())) { std::cout << "PASS" << std::endl; @@ -526,16 +528,18 @@ static int testIdentity() static int testCertificate() { + char buf[4096]; + Identity authority; std::cout << "[certificate] Generating identity to act as authority... "; std::cout.flush(); authority.generate(); - std::cout << authority.address().toString() << std::endl; + std::cout << authority.address().toString(buf) << std::endl; Identity idA,idB; std::cout << "[certificate] Generating identities A and B... "; std::cout.flush(); idA.generate(); idB.generate(); - std::cout << idA.address().toString() << ", " << idB.address().toString() << std::endl; + std::cout << idA.address().toString(buf) << ", " << idB.address().toString(buf) << std::endl; std::cout << "[certificate] Generating certificates A and B..."; CertificateOfMembership cA(10000,100,1,idA.address()); @@ -641,6 +645,8 @@ static void _testExcept(int &depth) static int testOther() { + char buf[1024]; + std::cout << "[other] Testing C++ exceptions... "; std::cout.flush(); int depth = 0; try { @@ -657,6 +663,13 @@ static int testOther() return -1; } + std::cout << "[other] Testing InetAddress encode/decode..."; std::cout.flush(); + std::cout << " " << InetAddress("127.0.0.1/9993").toString(buf); + std::cout << " " << InetAddress("feed:dead:babe:dead:beef:f00d:1234:5678/12345").toString(buf); + std::cout << " " << InetAddress("0/9993").toString(buf); + std::cout << " " << InetAddress("").toString(buf); + std::cout << std::endl; + #if 0 std::cout << "[other] Testing Hashtable... "; std::cout.flush(); { @@ -831,7 +844,7 @@ static int testOther() memset(key, 0, sizeof(key)); memset(value, 0, sizeof(value)); for(unsigned int q=0;q<32;++q) { - Utils::ztsnprintf(key[q],16,"%.8lx",(unsigned long)(rand() % 1000) + (q * 1000)); + OSUtils::ztsnprintf(key[q],16,"%.8lx",(unsigned long)(rand() % 1000) + (q * 1000)); int r = rand() % 128; for(int x=0;xnwid); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",nc->nwid); nj["id"] = tmp; nj["nwid"] = tmp; - Utils::ztsnprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)((nc->mac >> 40) & 0xff),(unsigned int)((nc->mac >> 32) & 0xff),(unsigned int)((nc->mac >> 24) & 0xff),(unsigned int)((nc->mac >> 16) & 0xff),(unsigned int)((nc->mac >> 8) & 0xff),(unsigned int)(nc->mac & 0xff)); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)((nc->mac >> 40) & 0xff),(unsigned int)((nc->mac >> 32) & 0xff),(unsigned int)((nc->mac >> 24) & 0xff),(unsigned int)((nc->mac >> 16) & 0xff),(unsigned int)((nc->mac >> 8) & 0xff),(unsigned int)(nc->mac & 0xff)); nj["mac"] = tmp; nj["name"] = nc->name; nj["status"] = nstatus; @@ -223,16 +223,16 @@ static void _networkToJson(nlohmann::json &nj,const ZT_VirtualNetworkConfig *nc, nlohmann::json aa = nlohmann::json::array(); for(unsigned int i=0;iassignedAddressCount;++i) { - aa.push_back(reinterpret_cast(&(nc->assignedAddresses[i]))->toString()); + aa.push_back(reinterpret_cast(&(nc->assignedAddresses[i]))->toString(tmp)); } nj["assignedAddresses"] = aa; nlohmann::json ra = nlohmann::json::array(); for(unsigned int i=0;irouteCount;++i) { nlohmann::json rj; - rj["target"] = reinterpret_cast(&(nc->routes[i].target))->toString(); + rj["target"] = reinterpret_cast(&(nc->routes[i].target))->toString(tmp); if (nc->routes[i].via.ss_family == nc->routes[i].target.ss_family) - rj["via"] = reinterpret_cast(&(nc->routes[i].via))->toIpString(); + rj["via"] = reinterpret_cast(&(nc->routes[i].via))->toIpString(tmp); else rj["via"] = nlohmann::json(); rj["flags"] = (int)nc->routes[i].flags; rj["metric"] = (int)nc->routes[i].metric; @@ -252,12 +252,12 @@ static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer) case ZT_PEER_ROLE_PLANET: prole = "PLANET"; break; } - Utils::ztsnprintf(tmp,sizeof(tmp),"%.10llx",peer->address); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.10llx",peer->address); pj["address"] = tmp; pj["versionMajor"] = peer->versionMajor; pj["versionMinor"] = peer->versionMinor; pj["versionRev"] = peer->versionRev; - Utils::ztsnprintf(tmp,sizeof(tmp),"%d.%d.%d",peer->versionMajor,peer->versionMinor,peer->versionRev); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%d.%d.%d",peer->versionMajor,peer->versionMinor,peer->versionRev); pj["version"] = tmp; pj["latency"] = peer->latency; pj["role"] = prole; @@ -265,7 +265,7 @@ static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer) nlohmann::json pa = nlohmann::json::array(); for(unsigned int i=0;ipathCount;++i) { nlohmann::json j; - j["address"] = reinterpret_cast(&(peer->paths[i].address))->toString(); + j["address"] = reinterpret_cast(&(peer->paths[i].address))->toString(tmp); j["lastSend"] = peer->paths[i].lastSend; j["lastReceive"] = peer->paths[i].lastReceive; j["trustedPathId"] = peer->paths[i].trustedPathId; @@ -280,19 +280,19 @@ static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer) static void _moonToJson(nlohmann::json &mj,const World &world) { - char tmp[64]; - Utils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",world.id()); + char tmp[4096]; + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",world.id()); mj["id"] = tmp; mj["timestamp"] = world.timestamp(); - mj["signature"] = Utils::hex(world.signature().data,(unsigned int)world.signature().size()); - mj["updatesMustBeSignedBy"] = Utils::hex(world.updatesMustBeSignedBy().data,(unsigned int)world.updatesMustBeSignedBy().size()); + mj["signature"] = Utils::hex(world.signature().data,(unsigned int)world.signature().size(),tmp); + mj["updatesMustBeSignedBy"] = Utils::hex(world.updatesMustBeSignedBy().data,(unsigned int)world.updatesMustBeSignedBy().size(),tmp); nlohmann::json ra = nlohmann::json::array(); for(std::vector::const_iterator r(world.roots().begin());r!=world.roots().end();++r) { nlohmann::json rj; - rj["identity"] = r->identity.toString(false); + rj["identity"] = r->identity.toString(false,tmp); nlohmann::json eps = nlohmann::json::array(); for(std::vector::const_iterator a(r->stableEndpoints.begin());a!=r->stableEndpoints.end();++a) - eps.push_back(a->toString()); + eps.push_back(a->toString(tmp)); rj["stableEndpoints"] = eps; ra.push_back(rj); } @@ -613,7 +613,7 @@ public: json &physical = _localConfig["physical"]; if (physical.is_object()) { for(json::iterator phy(physical.begin());phy!=physical.end();++phy) { - InetAddress net(OSUtils::jsonString(phy.key(),"")); + InetAddress net(OSUtils::jsonString(phy.key(),"").c_str()); if (net) { if (phy.value().is_object()) { uint64_t tpid; @@ -674,7 +674,7 @@ public: // Save primary port to a file so CLIs and GUIs can learn it easily char portstr[64]; - Utils::ztsnprintf(portstr,sizeof(portstr),"%u",_ports[0]); + OSUtils::ztsnprintf(portstr,sizeof(portstr),"%u",_ports[0]); OSUtils::writeFile((_homePath + ZT_PATH_SEPARATOR_S "zerotier-one.port").c_str(),std::string(portstr)); // Attempt to bind to a secondary port chosen from our ZeroTier address. @@ -712,7 +712,7 @@ public: } if (_ports[2]) { char uniqueName[64]; - Utils::ztsnprintf(uniqueName,sizeof(uniqueName),"ZeroTier/%.10llx@%u",_node->address(),_ports[2]); + OSUtils::ztsnprintf(uniqueName,sizeof(uniqueName),"ZeroTier/%.10llx@%u",_node->address(),_ports[2]); _portMapper = new PortMapper(_ports[2],uniqueName); } } @@ -982,7 +982,7 @@ public: n->second.settings = settings; char nlcpath[4096]; - Utils::ztsnprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_networksPath.c_str(),nwid); + OSUtils::ztsnprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_networksPath.c_str(),nwid); FILE *out = fopen(nlcpath,"w"); if (out) { fprintf(out,"allowManaged=%d\n",(int)n->second.settings.allowManaged); @@ -1101,7 +1101,7 @@ public: ZT_NodeStatus status; _node->status(&status); - Utils::ztsnprintf(tmp,sizeof(tmp),"%.10llx",status.address); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.10llx",status.address); res["address"] = tmp; res["publicIdentity"] = status.publicIdentity; res["online"] = (bool)(status.online != 0); @@ -1110,7 +1110,7 @@ public: res["versionMinor"] = ZEROTIER_ONE_VERSION_MINOR; res["versionRev"] = ZEROTIER_ONE_VERSION_REVISION; res["versionBuild"] = ZEROTIER_ONE_VERSION_BUILD; - Utils::ztsnprintf(tmp,sizeof(tmp),"%d.%d.%d",ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%d.%d.%d",ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION); res["version"] = tmp; res["clock"] = OSUtils::now(); @@ -1257,7 +1257,7 @@ public: if ((scode != 200)&&(seed != 0)) { char tmp[64]; - Utils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",id); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",id); res["id"] = tmp; res["roots"] = json::array(); res["timestamp"] = 0; @@ -1395,7 +1395,7 @@ public: json &tryAddrs = v.value()["try"]; if (tryAddrs.is_array()) { for(unsigned long i=0;i 0)) { if (phy.value().is_object()) { if (OSUtils::jsonBool(phy.value()["blacklist"],false)) { @@ -1477,7 +1477,7 @@ public: json &amf = settings["allowManagementFrom"]; if (amf.is_array()) { for(unsigned long i=0;i newManagedIps; @@ -1565,7 +1567,7 @@ public: for(std::vector::iterator ip(n.managedIps.begin());ip!=n.managedIps.end();++ip) { if (std::find(newManagedIps.begin(),newManagedIps.end(),*ip) == newManagedIps.end()) { if (!n.tap->removeIp(*ip)) - fprintf(stderr,"ERROR: unable to remove ip address %s" ZT_EOL_S, ip->toString().c_str()); + fprintf(stderr,"ERROR: unable to remove ip address %s" ZT_EOL_S, ip->toString(ipbuf)); } } #ifdef __SYNOLOGY__ @@ -1575,7 +1577,7 @@ public: for(std::vector::iterator ip(newManagedIps.begin());ip!=newManagedIps.end();++ip) { if (std::find(n.managedIps.begin(),n.managedIps.end(),*ip) == n.managedIps.end()) { if (!n.tap->addIp(*ip)) - fprintf(stderr,"ERROR: unable to add ip address %s" ZT_EOL_S, ip->toString().c_str()); + fprintf(stderr,"ERROR: unable to add ip address %s" ZT_EOL_S, ip->toString(ipbuf)); } } #endif @@ -1585,7 +1587,7 @@ public: if (syncRoutes) { char tapdev[64]; #ifdef __WINDOWS__ - Utils::ztsnprintf(tapdev,sizeof(tapdev),"%.16llx",(unsigned long long)n.tap->luid().Value); + OSUtils::ztsnprintf(tapdev,sizeof(tapdev),"%.16llx",(unsigned long long)n.tap->luid().Value); #else Utils::scopy(tapdev,sizeof(tapdev),n.tap->deviceName().c_str()); #endif @@ -1670,7 +1672,7 @@ public: &_nextBackgroundTaskDeadline); if (ZT_ResultCode_isFatal(rc)) { char tmp[256]; - Utils::ztsnprintf(tmp,sizeof(tmp),"fatal error code from processWirePacket: %d",(int)rc); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"fatal error code from processWirePacket: %d",(int)rc); Mutex::Lock _l(_termReason_m); _termReason = ONE_UNRECOVERABLE_ERROR; _fatalErrorMessage = tmp; @@ -1851,7 +1853,7 @@ public: &_nextBackgroundTaskDeadline); if (ZT_ResultCode_isFatal(rc)) { char tmp[256]; - Utils::ztsnprintf(tmp,sizeof(tmp),"fatal error code from processWirePacket: %d",(int)rc); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"fatal error code from processWirePacket: %d",(int)rc); Mutex::Lock _l(_termReason_m); _termReason = ONE_UNRECOVERABLE_ERROR; _fatalErrorMessage = tmp; @@ -1919,7 +1921,7 @@ public: if (!n.tap) { try { char friendlyName[128]; - Utils::ztsnprintf(friendlyName,sizeof(friendlyName),"ZeroTier One [%.16llx]",nwid); + OSUtils::ztsnprintf(friendlyName,sizeof(friendlyName),"ZeroTier One [%.16llx]",nwid); n.tap = new EthernetTap( _homePath.c_str(), @@ -1933,7 +1935,7 @@ public: *nuptr = (void *)&n; char nlcpath[256]; - Utils::ztsnprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_homePath.c_str(),nwid); + OSUtils::ztsnprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_homePath.c_str(),nwid); std::string nlcbuf; if (OSUtils::readFile(nlcpath,nlcbuf)) { Dictionary<4096> nc; @@ -1954,7 +1956,7 @@ public: while (true) { size_t nextPos = addresses.find(',', pos); std::string address = addresses.substr(pos, (nextPos == std::string::npos ? addresses.size() : nextPos) - pos); - n.settings.allowManagedWhitelist.push_back(InetAddress(address)); + n.settings.allowManagedWhitelist.push_back(InetAddress(address.c_str())); if (nextPos == std::string::npos) break; pos = nextPos + 1; } @@ -2019,7 +2021,7 @@ public: #endif if (op == ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY) { char nlcpath[256]; - Utils::ztsnprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_homePath.c_str(),nwid); + OSUtils::ztsnprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_homePath.c_str(),nwid); OSUtils::rm(nlcpath); } } else { @@ -2068,20 +2070,20 @@ public: switch(type) { case ZT_STATE_OBJECT_IDENTITY_PUBLIC: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str()); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str()); break; case ZT_STATE_OBJECT_IDENTITY_SECRET: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str()); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str()); secure = true; break; case ZT_STATE_OBJECT_PLANET: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); break; case ZT_STATE_OBJECT_MOON: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id[0]); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id[0]); break; case ZT_STATE_OBJECT_NETWORK_CONFIG: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id[0]); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id[0]); secure = true; break; default: @@ -2121,19 +2123,19 @@ public: char p[4096]; switch(type) { case ZT_STATE_OBJECT_IDENTITY_PUBLIC: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str()); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str()); break; case ZT_STATE_OBJECT_IDENTITY_SECRET: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str()); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str()); break; case ZT_STATE_OBJECT_NETWORK_CONFIG: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id); break; case ZT_STATE_OBJECT_PLANET: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); break; case ZT_STATE_OBJECT_MOON: - Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id); break; default: return -1; @@ -2322,7 +2324,7 @@ public: default: scodestr = "Error"; break; } - Utils::ztsnprintf(tmpn,sizeof(tmpn),"HTTP/1.1 %.3u %s\r\nCache-Control: no-cache\r\nPragma: no-cache\r\nContent-Type: %s\r\nContent-Length: %lu\r\nConnection: close\r\n\r\n", + OSUtils::ztsnprintf(tmpn,sizeof(tmpn),"HTTP/1.1 %.3u %s\r\nCache-Control: no-cache\r\nPragma: no-cache\r\nContent-Type: %s\r\nContent-Length: %lu\r\nConnection: close\r\n\r\n", scode, scodestr, contentType.c_str(), diff --git a/service/SoftwareUpdater.cpp b/service/SoftwareUpdater.cpp index e0519827..b4bf03ec 100644 --- a/service/SoftwareUpdater.cpp +++ b/service/SoftwareUpdater.cpp @@ -284,7 +284,7 @@ bool SoftwareUpdater::check(const uint64_t now) if ((now - _lastCheckTime) >= ZT_SOFTWARE_UPDATE_CHECK_PERIOD) { _lastCheckTime = now; char tmp[512]; - const unsigned int len = Utils::ztsnprintf(tmp,sizeof(tmp), + const unsigned int len = OSUtils::ztsnprintf(tmp,sizeof(tmp), "%c{\"" ZT_SOFTWARE_UPDATE_JSON_VERSION_MAJOR "\":%d," "\"" ZT_SOFTWARE_UPDATE_JSON_VERSION_MINOR "\":%d," "\"" ZT_SOFTWARE_UPDATE_JSON_VERSION_REVISION "\":%d," @@ -321,7 +321,8 @@ bool SoftwareUpdater::check(const uint64_t now) // (1) Check the hash itself to make sure the image is basically okay uint8_t sha512[ZT_SHA512_DIGEST_LEN]; SHA512::hash(sha512,_download.data(),(unsigned int)_download.length()); - if (Utils::hex(sha512,ZT_SHA512_DIGEST_LEN) == OSUtils::jsonString(_latestMeta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH],"")) { + char hexbuf[(ZT_SHA512_DIGEST_LEN * 2) + 2]; + if (OSUtils::jsonString(_latestMeta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH],"") == Utils::hex(sha512,ZT_SHA512_DIGEST_LEN,hexbuf)) { // (2) Check signature by signing authority const std::string sig(OSUtils::jsonBinFromHex(_latestMeta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIGNATURE])); if (Identity(ZT_SOFTWARE_UPDATE_SIGNING_AUTHORITY).verify(_download.data(),(unsigned int)_download.length(),sig.data(),(unsigned int)sig.length())) { -- cgit v1.2.3 From 88997a03145c36845df6939d56e518343a12e630 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 6 Jul 2017 16:29:11 -0700 Subject: Windows build fixes. --- .../zerotier-one/tools/chocolateyinstall.ps1 | 4 +- osdep/Binder.hpp | 4 +- osdep/WindowsEthernetTap.cpp | 55 +++++++++++----------- service/OneService.cpp | 2 +- 4 files changed, 33 insertions(+), 32 deletions(-) (limited to 'service/OneService.cpp') diff --git a/ext/installfiles/windows/chocolatey/zerotier-one/tools/chocolateyinstall.ps1 b/ext/installfiles/windows/chocolatey/zerotier-one/tools/chocolateyinstall.ps1 index f8a7457e..9a0f6bac 100644 --- a/ext/installfiles/windows/chocolatey/zerotier-one/tools/chocolateyinstall.ps1 +++ b/ext/installfiles/windows/chocolatey/zerotier-one/tools/chocolateyinstall.ps1 @@ -1,7 +1,7 @@ $packageName = 'zerotier-one' $installerType = 'msi' -$url = 'https://download.zerotier.com/RELEASES/1.1.14/dist/ZeroTier%20One.msi' -$url64 = 'https://download.zerotier.com/RELEASES/1.1.14/dist/ZeroTier%20One.msi' +$url = 'https://download.zerotier.com/RELEASES/1.2.4/dist/ZeroTier%20One.msi' +$url64 = 'https://download.zerotier.com/RELEASES/1.2.4/dist/ZeroTier%20One.msi' $silentArgs = '/quiet' $validExitCodes = @(0,3010) diff --git a/osdep/Binder.hpp b/osdep/Binder.hpp index 040f3e46..f956a67e 100644 --- a/osdep/Binder.hpp +++ b/osdep/Binder.hpp @@ -150,7 +150,7 @@ public: case InetAddress::IP_SCOPE_GLOBAL: case InetAddress::IP_SCOPE_SHARED: case InetAddress::IP_SCOPE_PRIVATE: - for(int x=0;x(ip,std::string())); } @@ -315,7 +315,7 @@ public: // Default to binding to wildcard if we can't enumerate addresses if (localIfAddrs.empty()) { - for(int x=0;x(InetAddress((uint32_t)0,ports[x]),std::string())); localIfAddrs.insert(std::pair(InetAddress((const void *)"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",16,ports[x]),std::string())); } diff --git a/osdep/WindowsEthernetTap.cpp b/osdep/WindowsEthernetTap.cpp index 5344268f..22179cb6 100644 --- a/osdep/WindowsEthernetTap.cpp +++ b/osdep/WindowsEthernetTap.cpp @@ -722,20 +722,21 @@ bool WindowsEthernetTap::removeIp(const InetAddress &ip) DeleteUnicastIpAddressEntry(&(ipt->Table[i])); FreeMibTable(ipt); - if (ip.isV4()) { - std::vector regIps(_getRegistryIPv4Value("IPAddress")); - std::vector regSubnetMasks(_getRegistryIPv4Value("SubnetMask")); - std::string ipstr(ip.toIpString()); - for (std::vector::iterator rip(regIps.begin()), rm(regSubnetMasks.begin()); ((rip != regIps.end()) && (rm != regSubnetMasks.end())); ++rip, ++rm) { - if (*rip == ipstr) { - regIps.erase(rip); - regSubnetMasks.erase(rm); - _setRegistryIPv4Value("IPAddress", regIps); - _setRegistryIPv4Value("SubnetMask", regSubnetMasks); - break; - } - } - } + if (ip.isV4()) { + std::vector regIps(_getRegistryIPv4Value("IPAddress")); + std::vector regSubnetMasks(_getRegistryIPv4Value("SubnetMask")); + char ipbuf[64]; + std::string ipstr(ip.toIpString(ipbuf)); + for (std::vector::iterator rip(regIps.begin()), rm(regSubnetMasks.begin()); ((rip != regIps.end()) && (rm != regSubnetMasks.end())); ++rip, ++rm) { + if (*rip == ipstr) { + regIps.erase(rip); + regSubnetMasks.erase(rm); + _setRegistryIPv4Value("IPAddress", regIps); + _setRegistryIPv4Value("SubnetMask", regSubnetMasks); + break; + } + } + } return true; } @@ -750,7 +751,7 @@ bool WindowsEthernetTap::removeIp(const InetAddress &ip) std::vector WindowsEthernetTap::ips() const { - static const InetAddress linkLocalLoopback("fe80::1",64); // what is this and why does Windows assign it? + static const InetAddress linkLocalLoopback("fe80::1/64"); // what is this and why does Windows assign it? std::vector addrs; if (!_initialized) @@ -1226,18 +1227,18 @@ void WindowsEthernetTap::_syncIps() CreateUnicastIpAddressEntry(&ipr); } - if (aip->isV4()) - { - std::string ipStr(aip->toIpString()); - std::vector regIps(_getRegistryIPv4Value("IPAddress")); - if (std::find(regIps.begin(), regIps.end(), ipStr) == regIps.end()) { - std::vector regSubnetMasks(_getRegistryIPv4Value("SubnetMask")); - regIps.push_back(ipStr); - regSubnetMasks.push_back(aip->netmask().toIpString()); - _setRegistryIPv4Value("IPAddress", regIps); - _setRegistryIPv4Value("SubnetMask", regSubnetMasks); - } - } + if (aip->isV4()) { + char ipbuf[64]; + std::string ipStr(aip->toIpString(ipbuf)); + std::vector regIps(_getRegistryIPv4Value("IPAddress")); + if (std::find(regIps.begin(), regIps.end(), ipStr) == regIps.end()) { + std::vector regSubnetMasks(_getRegistryIPv4Value("SubnetMask")); + regIps.push_back(ipStr); + regSubnetMasks.push_back(aip->netmask().toIpString(ipbuf)); + _setRegistryIPv4Value("IPAddress", regIps); + _setRegistryIPv4Value("SubnetMask", regSubnetMasks); + } + } } } diff --git a/service/OneService.cpp b/service/OneService.cpp index d6e3e4df..352985c8 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -363,7 +363,7 @@ struct TcpConnection OneServiceImpl *parent; PhySocket *sock; InetAddress remoteAddr; - unsigned long lastReceive; + uint64_t lastReceive; // Used for inbound HTTP connections http_parser parser; -- cgit v1.2.3 From ba6fd168235fac1c2ec029a49616510da56efe0f Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 13 Jul 2017 15:08:57 -0700 Subject: More tracing stuff. --- include/ZeroTierOne.h | 59 ++++++++++++++++++++++ node/Identity.cpp | 32 ++++++++---- node/Node.cpp | 13 ++--- node/Trace.cpp | 129 +++++++++++++------------------------------------ node/Trace.hpp | 4 ++ node/Utils.hpp | 18 +++---- osdep/Binder.hpp | 89 +++++++++++++++++++++++----------- selftest.cpp | 40 ++++++--------- service/OneService.cpp | 11 +++-- 9 files changed, 216 insertions(+), 179 deletions(-) (limited to 'service/OneService.cpp') diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index f7681768..e4c39fbc 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -257,6 +257,65 @@ extern "C" { */ #define ZT_RULE_PACKET_CHARACTERISTICS_TCP_FIN 0x0000000000000001ULL +// Fields in remote trace dictionaries +#define ZT_REMOTE_TRACE_FIELD__EVENT "E" +#define ZT_REMOTE_TRACE_FIELD__PACKET_ID "pid" +#define ZT_REMOTE_TRACE_FIELD__PACKET_VERB "pv" +#define ZT_REMOTE_TRACE_FIELD__PACKET_TRUSTED_PATH_ID "ptpid" +#define ZT_REMOTE_TRACE_FIELD__PACKET_TRUSTED_PATH_APPROVED "ptpok" +#define ZT_REMOTE_TRACE_FIELD__PACKET_HOPS "phops" +#define ZT_REMOTE_TRACE_FIELD__OLD_REMOTE_PHYADDR "oldrphy" +#define ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR "rzt" +#define ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR "rphy" +#define ZT_REMOTE_TRACE_FIELD__LOCAL_ZTADDR "lzt" +#define ZT_REMOTE_TRACE_FIELD__LOCAL_PHYADDR "lphy" +#define ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET "ls" +#define ZT_REMOTE_TRACE_FIELD__IP_SCOPE "ipsc" +#define ZT_REMOTE_TRACE_FIELD__NETWORK_ID "nwid" +#define ZT_REMOTE_TRACE_FIELD__SOURCE_MAC "seth" +#define ZT_REMOTE_TRACE_FIELD__DEST_MAC "deth" +#define ZT_REMOTE_TRACE_FIELD__ETHERTYPE "et" +#define ZT_REMOTE_TRACE_FIELD__VLAN_ID "vlan" +#define ZT_REMOTE_TRACE_FIELD__FRAME_LENGTH "fl" +#define ZT_REMOTE_TRACE_FIELD__FRAME_DATA "fd" +#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE "crtype" +#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID "crid" +#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP "crts" +#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_INFO "crinfo" +#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO "criss" +#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_REVOCATION_TARGET "crrevt" +#define ZT_REMOTE_TRACE_FIELD__REASON "reason" + +// Event types in remote traces +#define ZT_REMOTE_TRACE_EVENT__RESETTING_PATHS_IN_SCOPE 0x1000 +#define ZT_REMOTE_TRACE_EVENT__TX_TIMED_OUT 0x1001 +#define ZT_REMOTE_TRACE_EVENT__PEER_CONFIRMING_UNKNOWN_PATH 0x1002 +#define ZT_REMOTE_TRACE_EVENT__PEER_LEARNED_NEW_PATH 0x1003 +#define ZT_REMOTE_TRACE_EVENT__PEER_REDIRECTED 0x1004 +#define ZT_REMOTE_TRACE_EVENT__PACKET_MAC_FAILURE 0x1005 +#define ZT_REMOTE_TRACE_EVENT__PACKET_INVALID 0x1006 +#define ZT_REMOTE_TRACE_EVENT__DROPPED_HELLO 0x1006 +#define ZT_REMOTE_TRACE_EVENT__OUTGOING_NETWORK_FRAME_DROPPED 0x2000 +#define ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_ACCESS_DENIED 0x2001 +#define ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_FRAME_DROPPED 0x2002 +#define ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED 0x2003 +#define ZT_REMOTE_TRACE_EVENT__CREDENTIAL_ACCEPTED 0x2004 + +// Event types in remote traces in hex string form +#define ZT_REMOTE_TRACE_EVENT__RESETTING_PATHS_IN_SCOPE_S "1000" +#define ZT_REMOTE_TRACE_EVENT__TX_TIMED_OUT_S "1001" +#define ZT_REMOTE_TRACE_EVENT__PEER_CONFIRMING_UNKNOWN_PATH_S "1002" +#define ZT_REMOTE_TRACE_EVENT__PEER_LEARNED_NEW_PATH_S "1003" +#define ZT_REMOTE_TRACE_EVENT__PEER_REDIRECTED_S "1004" +#define ZT_REMOTE_TRACE_EVENT__PACKET_MAC_FAILURE_S "1005" +#define ZT_REMOTE_TRACE_EVENT__PACKET_INVALID_S "1006" +#define ZT_REMOTE_TRACE_EVENT__DROPPED_HELLO_S "1006" +#define ZT_REMOTE_TRACE_EVENT__OUTGOING_NETWORK_FRAME_DROPPED_S "2000" +#define ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_ACCESS_DENIED_S "2001" +#define ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_FRAME_DROPPED_S "2002" +#define ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED_S "2003" +#define ZT_REMOTE_TRACE_EVENT__CREDENTIAL_ACCEPTED_S "2004" + /****************************************************************************/ /* Structures and other types */ /****************************************************************************/ diff --git a/node/Identity.cpp b/node/Identity.cpp index dba27d1c..a972d60d 100644 --- a/node/Identity.cpp +++ b/node/Identity.cpp @@ -157,44 +157,58 @@ char *Identity::toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_ bool Identity::fromString(const char *str) { - if (!str) + if (!str) { + _address.zero(); return false; - - char *saveptr = (char *)0; + } char tmp[ZT_IDENTITY_STRING_BUFFER_LENGTH]; - if (!Utils::scopy(tmp,sizeof(tmp),str)) + if (!Utils::scopy(tmp,sizeof(tmp),str)) { + _address.zero(); return false; + } delete _privateKey; _privateKey = (C25519::Private *)0; int fno = 0; + char *saveptr = (char *)0; for(char *f=Utils::stok(tmp,":",&saveptr);(f);f=Utils::stok((char *)0,":",&saveptr)) { switch(fno++) { case 0: _address = Address(Utils::hexStrToU64(f)); - if (_address.isReserved()) + if (_address.isReserved()) { + _address.zero(); return false; + } break; case 1: - if ((f[0] != '0')||(f[1])) + if ((f[0] != '0')||(f[1])) { + _address.zero(); return false; + } break; case 2: - if (Utils::unhex(f,_publicKey.data,(unsigned int)_publicKey.size()) != _publicKey.size()) + if (Utils::unhex(f,_publicKey.data,(unsigned int)_publicKey.size()) != _publicKey.size()) { + _address.zero(); return false; + } break; case 3: _privateKey = new C25519::Private(); - if (Utils::unhex(f,_privateKey->data,(unsigned int)_privateKey->size()) != _privateKey->size()) + if (Utils::unhex(f,_privateKey->data,(unsigned int)_privateKey->size()) != _privateKey->size()) { + _address.zero(); return false; + } break; default: + _address.zero(); return false; } } - if (fno < 3) + if (fno < 3) { + _address.zero(); return false; + } return true; } diff --git a/node/Node.cpp b/node/Node.cpp index 073af4bd..ff3acfc2 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -78,7 +78,7 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint6 uint64_t idtmp[2]; idtmp[0] = 0; idtmp[1] = 0; - char tmp[1024]; + char tmp[2048]; int n = stateObjectGet(tptr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp,tmp,sizeof(tmp) - 1); if (n > 0) { tmp[n] = (char)0; @@ -92,21 +92,18 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint6 if (n <= 0) { RR->identity.generate(); - idtmp[0] = RR->identity.address().toInt(); idtmp[1] = 0; RR->identity.toString(false,RR->publicIdentityStr); RR->identity.toString(true,RR->secretIdentityStr); + idtmp[0] = RR->identity.address().toInt(); idtmp[1] = 0; stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp,RR->secretIdentityStr,(unsigned int)strlen(RR->secretIdentityStr)); stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr)); } else { idtmp[0] = RR->identity.address().toInt(); idtmp[1] = 0; n = stateObjectGet(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,tmp,sizeof(tmp) - 1); - if (n > 0) { - tmp[n] = (char)0; - if (RR->publicIdentityStr != tmp) - n = -1; + if ((n > 0)&&(n < sizeof(RR->publicIdentityStr))&&(n < sizeof(tmp))) { + if (memcmp(tmp,RR->publicIdentityStr,n)) + stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr)); } - if (n <= 0) - stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr)); } try { diff --git a/node/Trace.cpp b/node/Trace.cpp index dc5ecf19..21d06228 100644 --- a/node/Trace.cpp +++ b/node/Trace.cpp @@ -39,101 +39,6 @@ namespace ZeroTier { -// Defining ZT_TRACE causes debug tracing messages to be dumped to stderr -#ifdef ZT_TRACE - -static const char *packetVerbString(Packet::Verb v) -{ - switch(v) { - case Packet::VERB_NOP: return "NOP"; - case Packet::VERB_HELLO: return "HELLO"; - case Packet::VERB_ERROR: return "ERROR"; - case Packet::VERB_OK: return "OK"; - case Packet::VERB_WHOIS: return "WHOIS"; - case Packet::VERB_RENDEZVOUS: return "RENDEZVOUS"; - case Packet::VERB_FRAME: return "FRAME"; - case Packet::VERB_EXT_FRAME: return "EXT_FRAME"; - case Packet::VERB_ECHO: return "ECHO"; - case Packet::VERB_MULTICAST_LIKE: return "MULTICAST_LIKE"; - case Packet::VERB_NETWORK_CREDENTIALS: return "NETWORK_CREDENTIALS"; - case Packet::VERB_NETWORK_CONFIG_REQUEST: return "NETWORK_CONFIG_REQUEST"; - case Packet::VERB_NETWORK_CONFIG: return "NETWORK_CONFIG"; - case Packet::VERB_MULTICAST_GATHER: return "MULTICAST_GATHER"; - case Packet::VERB_MULTICAST_FRAME: return "MULTICAST_FRAME"; - case Packet::VERB_PUSH_DIRECT_PATHS: return "PUSH_DIRECT_PATHS"; - case Packet::VERB_USER_MESSAGE: return "USER_MESSAGE"; - case Packet::VERB_REMOTE_TRACE: return "REMOTE_TRACE"; - } - return "(unknown)"; -} - -static const char *packetErrorString(Packet::ErrorCode e) -{ - switch(e) { - case Packet::ERROR_NONE: return "NONE"; - case Packet::ERROR_INVALID_REQUEST: return "INVALID_REQUEST"; - case Packet::ERROR_BAD_PROTOCOL_VERSION: return "BAD_PROTOCOL_VERSION"; - case Packet::ERROR_OBJ_NOT_FOUND: return "OBJECT_NOT_FOUND"; - case Packet::ERROR_IDENTITY_COLLISION: return "IDENTITY_COLLISION"; - case Packet::ERROR_UNSUPPORTED_OPERATION: return "UNSUPPORTED_OPERATION"; - case Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE: return "NEED_MEMBERSHIP_CERTIFICATE"; - case Packet::ERROR_NETWORK_ACCESS_DENIED_: return "NETWORK_ACCESS_DENIED"; - case Packet::ERROR_UNWANTED_MULTICAST: return "UNWANTED_MULTICAST"; - } - return "(unknown)"; -} - -#define TRprintf(f,...) { fprintf(stderr,(f),__VA_ARGS__); fflush(stderr); } - -#else - -#define TRprintf(f,...) - -#endif // ZT_TRACE - -#define ZT_REMOTE_TRACE_FIELD__EVENT "E" -#define ZT_REMOTE_TRACE_FIELD__PACKET_ID "pid" -#define ZT_REMOTE_TRACE_FIELD__PACKET_VERB "pv" -#define ZT_REMOTE_TRACE_FIELD__PACKET_TRUSTED_PATH_ID "ptpid" -#define ZT_REMOTE_TRACE_FIELD__PACKET_TRUSTED_PATH_APPROVED "ptpok" -#define ZT_REMOTE_TRACE_FIELD__PACKET_HOPS "phops" -#define ZT_REMOTE_TRACE_FIELD__OLD_REMOTE_PHYADDR "oldrphy" -#define ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR "rzt" -#define ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR "rphy" -#define ZT_REMOTE_TRACE_FIELD__LOCAL_ZTADDR "lzt" -#define ZT_REMOTE_TRACE_FIELD__LOCAL_PHYADDR "lphy" -#define ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET "ls" -#define ZT_REMOTE_TRACE_FIELD__IP_SCOPE "ipsc" -#define ZT_REMOTE_TRACE_FIELD__NETWORK_ID "nwid" -#define ZT_REMOTE_TRACE_FIELD__SOURCE_MAC "seth" -#define ZT_REMOTE_TRACE_FIELD__DEST_MAC "deth" -#define ZT_REMOTE_TRACE_FIELD__ETHERTYPE "et" -#define ZT_REMOTE_TRACE_FIELD__VLAN_ID "vlan" -#define ZT_REMOTE_TRACE_FIELD__FRAME_LENGTH "fl" -#define ZT_REMOTE_TRACE_FIELD__FRAME_DATA "fd" -#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE "credtype" -#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID "credid" -#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP "credts" -#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_INFO "credinfo" -#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO "crediss" -#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_REVOCATION_TARGET "credRt" -#define ZT_REMOTE_TRACE_FIELD__REASON "reason" - -#define ZT_REMOTE_TRACE_EVENT__RESETTING_PATHS_IN_SCOPE_S "1000" -#define ZT_REMOTE_TRACE_EVENT__TX_TIMED_OUT_S "1001" -#define ZT_REMOTE_TRACE_EVENT__PEER_CONFIRMING_UNKNOWN_PATH_S "1002" -#define ZT_REMOTE_TRACE_EVENT__PEER_LEARNED_NEW_PATH_S "1003" -#define ZT_REMOTE_TRACE_EVENT__PEER_REDIRECTED_S "1004" -#define ZT_REMOTE_TRACE_EVENT__PACKET_MAC_FAILURE_S "1005" -#define ZT_REMOTE_TRACE_EVENT__PACKET_INVALID_S "1006" -#define ZT_REMOTE_TRACE_EVENT__DROPPED_HELLO_S "1006" - -#define ZT_REMOTE_TRACE_EVENT__OUTGOING_NETWORK_FRAME_DROPPED_S "2000" -#define ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_ACCESS_DENIED_S "2001" -#define ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_FRAME_DROPPED_S "2002" -#define ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED_S "2003" -#define ZT_REMOTE_TRACE_EVENT__CREDENTIAL_ACCEPTED_S "2004" - void Trace::resettingPathsInScope(void *const tPtr,const Address &reporter,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,const InetAddress::IpScope scope) { char tmp[128]; @@ -328,6 +233,7 @@ void Trace::credentialRejected(void *const tPtr,const CertificateOfMembership &c d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo()); if (reason) d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); + _send(tPtr,d,0); } void Trace::credentialRejected(void *const tPtr,const CertificateOfOwnership &c,const char *reason) @@ -341,6 +247,7 @@ void Trace::credentialRejected(void *const tPtr,const CertificateOfOwnership &c, d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo()); if (reason) d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); + _send(tPtr,d,0); } void Trace::credentialRejected(void *const tPtr,const CertificateOfRepresentation &c,const char *reason) @@ -352,6 +259,7 @@ void Trace::credentialRejected(void *const tPtr,const CertificateOfRepresentatio d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp()); if (reason) d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); + _send(tPtr,d,0); } void Trace::credentialRejected(void *const tPtr,const Capability &c,const char *reason) @@ -365,6 +273,7 @@ void Trace::credentialRejected(void *const tPtr,const Capability &c,const char * d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo()); if (reason) d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); + _send(tPtr,d,0); } void Trace::credentialRejected(void *const tPtr,const Tag &c,const char *reason) @@ -379,6 +288,7 @@ void Trace::credentialRejected(void *const tPtr,const Tag &c,const char *reason) d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_INFO,(uint64_t)c.value()); if (reason) d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); + _send(tPtr,d,0); } void Trace::credentialRejected(void *const tPtr,const Revocation &c,const char *reason) @@ -391,6 +301,7 @@ void Trace::credentialRejected(void *const tPtr,const Revocation &c,const char * d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_REVOCATION_TARGET,c.target()); if (reason) d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); + _send(tPtr,d,0); } void Trace::credentialAccepted(void *const tPtr,const CertificateOfMembership &c) @@ -402,6 +313,7 @@ void Trace::credentialAccepted(void *const tPtr,const CertificateOfMembership &c d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo()); + _send(tPtr,d,0); } void Trace::credentialAccepted(void *const tPtr,const CertificateOfOwnership &c) @@ -413,6 +325,7 @@ void Trace::credentialAccepted(void *const tPtr,const CertificateOfOwnership &c) d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo()); + _send(tPtr,d,0); } void Trace::credentialAccepted(void *const tPtr,const CertificateOfRepresentation &c) @@ -422,6 +335,7 @@ void Trace::credentialAccepted(void *const tPtr,const CertificateOfRepresentatio d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp()); + _send(tPtr,d,0); } void Trace::credentialAccepted(void *const tPtr,const Capability &c) @@ -433,6 +347,7 @@ void Trace::credentialAccepted(void *const tPtr,const Capability &c) d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo()); + _send(tPtr,d,0); } void Trace::credentialAccepted(void *const tPtr,const Tag &c) @@ -445,6 +360,7 @@ void Trace::credentialAccepted(void *const tPtr,const Tag &c) d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_INFO,(uint64_t)c.value()); + _send(tPtr,d,0); } void Trace::credentialAccepted(void *const tPtr,const Revocation &c) @@ -455,10 +371,33 @@ void Trace::credentialAccepted(void *const tPtr,const Revocation &c) d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_REVOCATION_TARGET,c.target()); + _send(tPtr,d,0); } void Trace::_send(void *const tPtr,const Dictionary &d) { +#ifdef ZT_TRACE + unsigned int i = 0; + while (i < (unsigned int)(sizeof(_traceMsgBuf) - 1)) { + const char c = d.data()[i]; + if (c == 0) { + break; + } else if (c == '\n') { + _traceMsgBuf[i++] = ' '; + } else if ((c >= 32)&&(c <= 126)) { + _traceMsgBuf[i++] = c; + } else { + if ((i + 3) < (unsigned int)(sizeof(_traceMsgBuf) - 1)) { + _traceMsgBuf[i++] = '\\'; + Utils::hex((uint8_t)c,_traceMsgBuf + i); + } + } + } + _traceMsgBuf[i] = (char)0; + //printf("%s\n",_traceMsgBuf); + RR->node->postEvent(tPtr,ZT_EVENT_TRACE,_traceMsgBuf); +#endif + const Address rtt(RR->node->remoteTraceTarget()); if (rtt) { Packet outp(rtt,RR->identity.address(),Packet::VERB_REMOTE_TRACE); diff --git a/node/Trace.hpp b/node/Trace.hpp index eefd5359..dae67e28 100644 --- a/node/Trace.hpp +++ b/node/Trace.hpp @@ -155,6 +155,10 @@ private: void _send(void *const tPtr,const Dictionary &d); void _send(void *const tPtr,const Dictionary &d,const uint64_t networkId); void _send(void *const tPtr,const Dictionary &d,const SharedPtr &network); + +#ifdef ZT_TRACE + char _traceMsgBuf[4096]; +#endif }; } // namespace ZeroTier diff --git a/node/Utils.hpp b/node/Utils.hpp index 1139c9f1..8f61d396 100644 --- a/node/Utils.hpp +++ b/node/Utils.hpp @@ -150,8 +150,8 @@ public: { char *save = s; for(unsigned int i=0;i(d)[i]; - *(s++) = HEXCHARS[(b >> 4) & 0xf]; + const unsigned int b = reinterpret_cast(d)[i]; + *(s++) = HEXCHARS[b >> 4]; *(s++) = HEXCHARS[b & 0xf]; } *s = (char)0; @@ -162,18 +162,18 @@ public: { unsigned int l = 0; while (l < buflen) { - uint8_t hc = (uint8_t)*(h++); + uint8_t hc = *(reinterpret_cast(h++)); if (!hc) break; uint8_t c = 0; - if ((hc >= 48)&&(hc <= 57)) + if ((hc >= 48)&&(hc <= 57)) // 0..9 c = hc - 48; - else if ((hc >= 97)&&(hc <= 102)) + else if ((hc >= 97)&&(hc <= 102)) // a..f c = hc - 87; - else if ((hc >= 65)&&(hc <= 70)) + else if ((hc >= 65)&&(hc <= 70)) // A..F c = hc - 55; - hc = (uint8_t)*(h++); + hc = *(reinterpret_cast(h++)); if (!hc) break; c <<= 4; @@ -195,7 +195,7 @@ public: const char *hend = h + hlen; while (l < buflen) { if (h == hend) break; - uint8_t hc = (uint8_t)*(h++); + uint8_t hc = *(reinterpret_cast(h++)); if (!hc) break; uint8_t c = 0; @@ -207,7 +207,7 @@ public: c = hc - 55; if (h == hend) break; - hc = (uint8_t)*(h++); + hc = *(reinterpret_cast(h++)); if (!hc) break; c <<= 4; diff --git a/osdep/Binder.hpp b/osdep/Binder.hpp index 126dba28..17a0fbf6 100644 --- a/osdep/Binder.hpp +++ b/osdep/Binder.hpp @@ -58,6 +58,7 @@ #include #include #include +#include #include "../node/NonCopyable.hpp" #include "../node/InetAddress.hpp" @@ -70,6 +71,9 @@ // Period between refreshes of bindings #define ZT_BINDER_REFRESH_PERIOD 30000 +// Max number of bindings +#define ZT_BINDER_MAX_BINDINGS 128 + namespace ZeroTier { /** @@ -95,7 +99,7 @@ private: }; public: - Binder() {} + Binder() : _bindingCount(0) {} /** * Close all bound ports, should be called on shutdown @@ -106,10 +110,11 @@ public: void closeAll(Phy &phy) { Mutex::Lock _l(_lock); - for(std::vector<_Binding>::iterator b(_bindings.begin());b!=_bindings.end();++b) { - phy.close(b->udpSock,false); - phy.close(b->tcpListenSock,false); + for(unsigned int b=0,c=_bindingCount;b newBindings; + const unsigned int oldBindingCount = _bindingCount; + _bindingCount = 0; // Save bindings that are still valid, close those that are not - for(std::vector<_Binding>::iterator b(_bindings.begin());b!=_bindings.end();++b) { - if (localIfAddrs.find(b->address) != localIfAddrs.end()) { - newBindings.push_back(*b); + for(unsigned int b=0;budpSock,false); - phy.close(b->tcpListenSock,false); + PhySocket *const udps = _bindings[b].udpSock; + PhySocket *const tcps = _bindings[b].tcpListenSock; + _bindings[b].udpSock = (PhySocket *)0; + _bindings[b].tcpListenSock = (PhySocket *)0; + phy.close(udps,false); + phy.close(tcps,false); } } // Create new bindings for those not already bound for(std::map::const_iterator ii(localIfAddrs.begin());ii!=localIfAddrs.end();++ii) { - typename std::vector<_Binding>::const_iterator bi(newBindings.begin()); - while (bi != newBindings.end()) { - if (bi->address == ii->first) + unsigned int bi = 0; + while (bi != _bindingCount) { + if (_bindings[bi].address == ii->first) break; ++bi; } - if (bi == newBindings.end()) { + if (bi == _bindingCount) { udps = phy.udpBind(reinterpret_cast(&(ii->first)),(void *)0,ZT_UDP_DESIRED_BUF_SIZE); tcps = phy.tcpListen(reinterpret_cast(&(ii->first)),(void *)0); if ((udps)&&(tcps)) { @@ -358,15 +370,18 @@ public: setsockopt(fd,SOL_SOCKET,SO_BINDTODEVICE,tmp,strlen(tmp)); } #endif // __LINUX__ - newBindings.push_back(_Binding()); - newBindings.back().udpSock = udps; - newBindings.back().tcpListenSock = tcps; - newBindings.back().address = ii->first; + if (_bindingCount < ZT_BINDER_MAX_BINDINGS) { + _bindings[_bindingCount].udpSock = udps; + _bindings[_bindingCount].tcpListenSock = tcps; + _bindings[_bindingCount].address = ii->first; + ++_bindingCount; + } + } else { + phy.close(udps,false); + phy.close(tcps,false); } } } - - _bindings.swap(newBindings); } /** @@ -376,8 +391,8 @@ public: { std::vector aa; Mutex::Lock _l(_lock); - for(std::vector<_Binding>::const_iterator b(_bindings.begin());b!=_bindings.end();++b) - aa.push_back(b->address); + for(unsigned int b=0,c=_bindingCount;b::const_iterator b(_bindings.begin());b!=_bindings.end();++b) { - if (ttl) phy.setIp4UdpTtl(b->udpSock,ttl); - if (phy.udpSend(b->udpSock,(const struct sockaddr *)addr,data,len)) r = true; - if (ttl) phy.setIp4UdpTtl(b->udpSock,255); + for(unsigned int b=0,c=_bindingCount;b::const_iterator b(_bindings.begin());b!=_bindings.end();++b) { - if (b->address == addr) + for(unsigned int b=0;b<_bindingCount;++b) { + if (_bindings[b].address == addr) return true; } return false; } + /** + * Quickly check that a UDP socket is valid + * + * @param udpSock UDP socket to check + * @return True if socket is currently bound/allocated + */ + inline bool isUdpSocketValid(PhySocket *const udpSock) + { + for(unsigned int b=0,c=_bindingCount;b _bindings; + _Binding _bindings[ZT_BINDER_MAX_BINDINGS]; + std::atomic _bindingCount; Mutex _lock; }; diff --git a/selftest.cpp b/selftest.cpp index 882422bc..f4de36a9 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -633,33 +633,25 @@ static int testPacket() return 0; } -static void _testExcept(int &depth) -{ - if (depth >= 16) { - throw std::runtime_error("LOL!"); - } else { - ++depth; - _testExcept(depth); - } -} - static int testOther() { char buf[1024]; - - std::cout << "[other] Testing C++ exceptions... "; std::cout.flush(); - int depth = 0; - try { - _testExcept(depth); - } catch (std::runtime_error &e) { - if (depth == 16) { - std::cout << "OK" << std::endl; - } else { - std::cout << "ERROR (depth not 16)" << std::endl; - return -1; - } - } catch ( ... ) { - std::cout << "ERROR (exception not std::runtime_error)" << std::endl; + char buf2[4096]; + char buf3[1024]; + + std::cout << "[other] Testing hex/unhex... "; std::cout.flush(); + Utils::getSecureRandom(buf,(unsigned int)sizeof(buf)); + Utils::hex(buf,(unsigned int)sizeof(buf),buf2); + Utils::unhex(buf2,buf3,(unsigned int)sizeof(buf3)); + if (memcmp(buf,buf3,sizeof(buf)) == 0) { + std::cout << "PASS" << std::endl; + } else { + std::cout << "FAIL!" << std::endl; + buf2[78] = 0; + std::cout << buf2 << std::endl; + Utils::hex(buf3,(unsigned int)sizeof(buf3),buf2); + buf2[78] = 0; + std::cout << buf2 << std::endl; return -1; } diff --git a/service/OneService.cpp b/service/OneService.cpp index 352985c8..1b07eb79 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -658,16 +658,18 @@ public: return _termReason; } - // Bind local control socket + // Bind TCP control socket to 127.0.0.1 and ::1 as well for loopback TCP control socket queries { struct sockaddr_in lo4; memset(&lo4,0,sizeof(lo4)); lo4.sin_family = AF_INET; + lo4.sin_addr.s_addr = Utils::hton((uint32_t)0x7f000001); lo4.sin_port = Utils::hton((uint16_t)_ports[0]); _localControlSocket4 = _phy.tcpListen((const struct sockaddr *)&lo4); struct sockaddr_in6 lo6; memset(&lo6,0,sizeof(lo6)); lo6.sin6_family = AF_INET6; + lo6.sin6_addr.s6_addr[15] = 1; lo6.sin6_port = lo4.sin_port; _localControlSocket6 = _phy.tcpListen((const struct sockaddr *)&lo6); } @@ -1661,12 +1663,11 @@ public: { if ((len >= 16)&&(reinterpret_cast(from)->ipScope() == InetAddress::IP_SCOPE_GLOBAL)) _lastDirectReceiveFromGlobal = OSUtils::now(); - const ZT_ResultCode rc = _node->processWirePacket( (void *)0, OSUtils::now(), - (int64_t)((uintptr_t)sock), - (const struct sockaddr_storage *)from, // Phy<> uses sockaddr_storage, so it'll always be that big + reinterpret_cast(sock), + reinterpret_cast(from), // Phy<> uses sockaddr_storage, so it'll always be that big data, len, &_nextBackgroundTaskDeadline); @@ -2200,7 +2201,7 @@ public: // proxy fallback, which is slow. #endif // ZT_TCP_FALLBACK_RELAY - if ((localSocket != 0)&&(localSocket != -1)) { + if ((localSocket != -1)&&(localSocket != 0)&&(_binder.isUdpSocketValid((PhySocket *)((uintptr_t)localSocket)))) { if ((ttl)&&(addr->ss_family == AF_INET)) _phy.setIp4UdpTtl((PhySocket *)((uintptr_t)localSocket),ttl); const bool r = _phy.udpSend((PhySocket *)((uintptr_t)localSocket),(const struct sockaddr *)addr,data,len); if ((ttl)&&(addr->ss_family == AF_INET)) _phy.setIp4UdpTtl((PhySocket *)((uintptr_t)localSocket),255); -- cgit v1.2.3 From 4ecc0c59cafac54ff2d32e97b130f83b7481da2e Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 14 Jul 2017 13:03:16 -0700 Subject: Plumbing through of remote trace into controller code. --- controller/EmbeddedNetworkController.cpp | 67 ++++++++++++++++++++++++++++++++ controller/EmbeddedNetworkController.hpp | 4 ++ include/ZeroTierOne.h | 45 ++++++++++++++++++++- node/IncomingPacket.cpp | 27 ++++++++++++- node/IncomingPacket.hpp | 1 + node/Packet.hpp | 3 -- service/OneService.cpp | 6 +++ 7 files changed, 148 insertions(+), 5 deletions(-) (limited to 'service/OneService.cpp') diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index b57a37e8..8b8a93bd 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -621,6 +621,15 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( if (b.count("activeBridge")) member["activeBridge"] = OSUtils::jsonBool(b["activeBridge"],false); if (b.count("noAutoAssignIps")) member["noAutoAssignIps"] = OSUtils::jsonBool(b["noAutoAssignIps"],false); + if (b.count("remoteTraceTarget")) { + const std::string rtt(OSUtils::jsonString(b["remoteTraceTarget"],"")); + if (rtt.length() == 10) { + member["remoteTraceTarget"] = rtt; + } else { + member["remoteTraceTarget"] = json(); + } + } + if (b.count("authorized")) { const bool newAuth = OSUtils::jsonBool(b["authorized"],false); if (newAuth != OSUtils::jsonBool(member["authorized"],false)) { @@ -764,6 +773,15 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( if (b.count("multicastLimit")) network["multicastLimit"] = OSUtils::jsonInt(b["multicastLimit"],32ULL); if (b.count("mtu")) network["mtu"] = std::max(std::min((unsigned int)OSUtils::jsonInt(b["mtu"],ZT_DEFAULT_MTU),(unsigned int)ZT_MAX_MTU),(unsigned int)ZT_MIN_MTU); + if (b.count("remoteTraceTarget")) { + const std::string rtt(OSUtils::jsonString(b["remoteTraceTarget"],"")); + if (rtt.length() == 10) { + network["remoteTraceTarget"] = rtt; + } else { + network["remoteTraceTarget"] = json(); + } + } + if (b.count("v4AssignMode")) { json nv4m; json &v4m = b["v4AssignMode"]; @@ -1065,6 +1083,55 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpDELETE( return 404; } +void EmbeddedNetworkController::handleRemoteTrace(const ZT_RemoteTrace &rt) +{ + // Convert Dictionary into JSON object + json d; + char *saveptr = (char *)0; + for(char *l=Utils::stok(rt.data,"\n",&saveptr);(l);l=Utils::stok((char *)0,"\n",&saveptr)) { + char *eq = strchr(l,'='); + if (eq > l) { + std::string k(l,(unsigned long)(eq - l)); + std::string v; + ++eq; + while (*eq) { + if (*eq == '\\') { + ++eq; + if (*eq) { + switch(*eq) { + case 'r': + v.push_back('\r'); + break; + case 'n': + v.push_back('\n'); + break; + case '0': + v.push_back((char)0); + break; + case 'e': + v.push_back('='); + break; + default: + v.push_back(*eq); + break; + } + ++eq; + } + } else { + v.push_back(*(eq++)); + } + } + if (v.length() > 0) + d[k] = v; + } + } + + char p[128]; + OSUtils::ztsnprintf(p,sizeof(p),"trace/%.10llx_%.16llx.json",rt.origin,OSUtils::now()); + _db.writeRaw(p,OSUtils::jsonDump(d)); + //fprintf(stdout,"%s\n",OSUtils::jsonDump(d).c_str()); fflush(stdout); +} + void EmbeddedNetworkController::threadMain() throw() { diff --git a/controller/EmbeddedNetworkController.hpp b/controller/EmbeddedNetworkController.hpp index 1589ea71..03ba0b95 100644 --- a/controller/EmbeddedNetworkController.hpp +++ b/controller/EmbeddedNetworkController.hpp @@ -90,6 +90,8 @@ public: std::string &responseBody, std::string &responseContentType); + void handleRemoteTrace(const ZT_RemoteTrace &rt); + void threadMain() throw(); @@ -142,6 +144,7 @@ private: if (!member.count("vRev")) member["vRev"] = -1; if (!member.count("vProto")) member["vProto"] = -1; if (!member.count("physicalAddr")) member["physicalAddr"] = nlohmann::json(); + if (!member.count("remoteTraceTarget")) member["remoteTraceTarget"] = nlohmann::json(); member["objtype"] = "member"; } inline void _initNetwork(nlohmann::json &network) @@ -159,6 +162,7 @@ private: if (!network.count("routes")) network["routes"] = nlohmann::json::array(); if (!network.count("ipAssignmentPools")) network["ipAssignmentPools"] = nlohmann::json::array(); if (!network.count("mtu")) network["mtu"] = ZT_DEFAULT_MTU; + if (!network.count("remoteTraceTarget")) network["remoteTraceTarget"] = nlohmann::json(); if (!network.count("rules")) { // If unspecified, rules are set to allow anything and behave like a flat L2 segment network["rules"] = {{ diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index e4c39fbc..14ddc7fe 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -470,9 +470,52 @@ enum ZT_Event * * Meta-data: ZT_UserMessage structure */ - ZT_EVENT_USER_MESSAGE = 6 + ZT_EVENT_USER_MESSAGE = 6, + + /** + * Remote trace received + * + * These are generated when a VERB_REMOTE_TRACE is received. Note + * that any node can fling one of these at us. It is your responsibility + * to filter and determine if it's worth paying attention to. If it's + * not just drop it. Most nodes that are not active controllers ignore + * these, and controllers only save them if they pertain to networks + * with remote tracing enabled. + * + * Meta-data: ZT_RemoteTrace structure + */ + ZT_EVENT_REMOTE_TRACE = 7 }; +/** + * Payload of REMOTE_TRACE event + */ +typedef struct +{ + /** + * ZeroTier address of sender + */ + uint64_t origin; + + /** + * Null-terminated Dictionary containing key/value pairs sent by origin + * + * This *should* be a dictionary, but the implementation only checks + * that it is a valid non-empty C-style null-terminated string. Be very + * careful to use a well-tested parser to parse this as it represents + * data received from a potentially un-trusted peer on the network. + * Invalid payloads should be dropped. + * + * The contents of data[] may be modified. + */ + char *data; + + /** + * Length of dict[] in bytes, including terminating null + */ + unsigned int len; +} ZT_RemoteTrace; + /** * User message used with ZT_EVENT_USER_MESSAGE * diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index a5875d1e..5e5d1d72 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -1192,7 +1192,7 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPt bool IncomingPacket::_doUSER_MESSAGE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer) { try { - if (size() >= (ZT_PACKET_IDX_PAYLOAD + 8)) { + if (likely(size() >= (ZT_PACKET_IDX_PAYLOAD + 8))) { ZT_UserMessage um; um.origin = peer->address().toInt(); um.typeId = at(ZT_PACKET_IDX_PAYLOAD); @@ -1207,6 +1207,31 @@ bool IncomingPacket::_doUSER_MESSAGE(const RuntimeEnvironment *RR,void *tPtr,con return true; } +bool IncomingPacket::_doREMOTE_TRACE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer) +{ + ZT_RemoteTrace rt; + try { + const char *ptr = reinterpret_cast(data()) + ZT_PACKET_IDX_PAYLOAD; + const char *const eof = reinterpret_cast(data()) + size(); + rt.origin = peer->address().toInt(); + rt.data = const_cast(ptr); // start of first string + while (ptr < eof) { + if (!*ptr) { // end of string + rt.len = (unsigned int)(ptr - rt.data); + if ((rt.len > 0)&&(rt.len <= ZT_MAX_REMOTE_TRACE_SIZE)) + RR->node->postEvent(tPtr,ZT_EVENT_REMOTE_TRACE,&rt); + rt.data = const_cast(++ptr); // start of next string, if any + } else { + ++ptr; + } + } + peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_REMOTE_TRACE,0,Packet::VERB_NOP,false,0); + } catch ( ... ) { + RR->t->incomingPacketInvalid(tPtr,_path,packetId(),source(),hops(),Packet::VERB_REMOTE_TRACE,"unexpected exception"); + } + return true; +} + void IncomingPacket::_sendErrorNeedCredentials(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer,const uint64_t nwid) { const uint64_t now = RR->node->now(); diff --git a/node/IncomingPacket.hpp b/node/IncomingPacket.hpp index 11b60712..692c63df 100644 --- a/node/IncomingPacket.hpp +++ b/node/IncomingPacket.hpp @@ -139,6 +139,7 @@ private: bool _doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer); bool _doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer); bool _doUSER_MESSAGE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer); + bool _doREMOTE_TRACE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer); void _sendErrorNeedCredentials(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer,const uint64_t nwid); diff --git a/node/Packet.hpp b/node/Packet.hpp index a1ea73e1..b8e69fa9 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -978,9 +978,6 @@ public: * The instance ID is a random 64-bit value generated by each ZeroTier * node on startup. This is helpful in identifying traces from different * members of a cluster. - * - * The Dictionary serialization format is the same as used for network - * configurations. The maximum size of a trace is 10000 bytes. */ VERB_REMOTE_TRACE = 0x15 }; diff --git a/service/OneService.cpp b/service/OneService.cpp index 1b07eb79..115830e5 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -2058,6 +2058,12 @@ public: } } break; + case ZT_EVENT_REMOTE_TRACE: { + const ZT_RemoteTrace *rt = reinterpret_cast(metaData); + if ((rt)&&(rt->len > 0)&&(rt->len <= ZT_MAX_REMOTE_TRACE_SIZE)&&(rt->data)) + _controller->handleRemoteTrace(*rt); + } + default: break; } -- cgit v1.2.3 From b62296a40bd4ed2d01404679cdc9512a1f18bcca Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 19 Jul 2017 14:13:17 -0700 Subject: Bug fixes in new harness mode. --- controller/EmbeddedNetworkController.cpp | 20 ++-- controller/JSONDB.cpp | 194 ++++++++++++++++++------------- controller/JSONDB.hpp | 12 ++ osdep/OSUtils.cpp | 2 +- osdep/OSUtils.hpp | 2 +- service/OneService.cpp | 29 ++--- 6 files changed, 147 insertions(+), 112 deletions(-) (limited to 'service/OneService.cpp') diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index cb0c05af..70691fe0 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -1145,7 +1145,7 @@ void EmbeddedNetworkController::handleRemoteTrace(const ZT_RemoteTrace &rt) if (accept) { char p[128]; OSUtils::ztsnprintf(p,sizeof(p),"trace/%s",id); - _db.writeRaw(p,OSUtils::jsonDump(d)); + _db.writeRaw(p,OSUtils::jsonDump(d,-1)); } } catch ( ... ) { // drop invalid trace messages if an error occurs @@ -1157,17 +1157,24 @@ void EmbeddedNetworkController::threadMain() { char tmp[256]; _RQEntry *qe = (_RQEntry *)0; - while ((_running)&&(_queue.get(qe,1000) != BlockingQueue<_RQEntry *>::STOP)) { + while (_running) { + const BlockingQueue<_RQEntry *>::TimedWaitResult wr = _queue.get(qe,1000); + if ((wr == BlockingQueue<_RQEntry *>::STOP)||(!_running)) + break; + try { - if (qe->type == _RQEntry::RQENTRY_TYPE_REQUEST) + if ((wr == BlockingQueue<_RQEntry *>::OK)&&(qe->type == _RQEntry::RQENTRY_TYPE_REQUEST)) { _request(qe->nwid,qe->fromAddr,qe->requestPacketId,qe->identity,qe->metaData); + delete qe; + } // Every 10s we update a 'status' containing member online state, etc. const uint64_t now = OSUtils::now(); if ((now - _lastDumpedStatus) >= 10000) { _lastDumpedStatus = now; bool first = true; - std::string st("{\"id\":\"status\",\"objtype\":\"status\",\"memberStatus\":{"); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"{\"id\":\"%.10llx-status\",\"objtype\":\"status\",\"memberStatus\":[",_signingId.address().toInt()); + std::string st(tmp); { Mutex::Lock _l(_memberStatus_m); st.reserve(48 * (_memberStatus.size() + 1)); @@ -1176,7 +1183,7 @@ void EmbeddedNetworkController::threadMain() auto ms = this->_memberStatus.find(_MemberStatusKey(networkId,nodeId)); if (ms != _memberStatus.end()) lrt = ms->second.lastRequestTime; - OSUtils::ztsnprintf(tmp,sizeof(tmp),"%s\"%.16llx-%.10llx\":%llu", + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%s\"%.16llx\",%llu,%llu", (first) ? "" : ",", (unsigned long long)networkId, (unsigned long long)nodeId, @@ -1185,12 +1192,11 @@ void EmbeddedNetworkController::threadMain() first = false; }); } - OSUtils::ztsnprintf(tmp,sizeof(tmp),"},\"clock\":%llu,\"startTime\":%llu}",(unsigned long long)now,(unsigned long long)_startTime); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"],\"clock\":%llu,\"startTime\":%llu,\"uptime\":%llu}",(unsigned long long)now,(unsigned long long)_startTime,(unsigned long long)(now - _startTime)); st.append(tmp); _db.writeRaw("status",st); } } catch ( ... ) {} - delete qe; } } diff --git a/controller/JSONDB.cpp b/controller/JSONDB.cpp index ad9ba248..216470b4 100644 --- a/controller/JSONDB.cpp +++ b/controller/JSONDB.cpp @@ -41,7 +41,8 @@ JSONDB::JSONDB(const std::string &basePath) : _basePath(basePath), _rawInput(-1), _rawOutput(-1), - _summaryThreadRun(true) + _summaryThreadRun(true), + _dataReady(false) { if ((_basePath.length() > 7)&&(_basePath.substr(0,7) == "http://")) { // If base path is http:// we run in HTTP mode @@ -75,6 +76,8 @@ JSONDB::JSONDB(const std::string &basePath) : OSUtils::lockDownFile(_basePath.c_str(),true); // networks might contain auth tokens, etc., so restrict directory permissions } + _networks_m.lock(); // locked until data is loaded, etc. + if (_rawInput < 0) { unsigned int cnt = 0; while (!_load(_basePath)) { @@ -82,27 +85,25 @@ JSONDB::JSONDB(const std::string &basePath) : fprintf(stderr,"WARNING: controller still waiting to read '%s'..." ZT_EOL_S,_basePath.c_str()); Thread::sleep(250); } - } - for(std::unordered_map::iterator n(_networks.begin());n!=_networks.end();++n) - _recomputeSummaryInfo(n->first); - for(;;) { - _summaryThread_m.lock(); - if (_summaryThreadToDo.empty()) { - _summaryThread_m.unlock(); - break; + for(std::unordered_map::iterator n(_networks.begin());n!=_networks.end();++n) + _summaryThreadToDo.push_back(n->first); + + if (_summaryThreadToDo.size() > 0) { + _summaryThread = Thread::start(this); + } else { + _dataReady = true; + _networks_m.unlock(); } - _summaryThread_m.unlock(); - Thread::sleep(50); + } else { + // In IPC mode we wait for the first message to start, and we start + // this thread since this thread is responsible for reading from stdin. + _summaryThread = Thread::start(this); } } JSONDB::~JSONDB() { - { - Mutex::Lock _l(_networks_m); - _networks.clear(); - } Thread t; { Mutex::Lock _l(_summaryThread_m); @@ -119,11 +120,11 @@ bool JSONDB::writeRaw(const std::string &n,const std::string &obj) #ifndef __WINDOWS__ if (obj.length() > 0) { Mutex::Lock _l(_rawLock); - if (write(_rawOutput,obj.c_str(),obj.length() + 1) > 0) - return true; - } else { - return true; - } + if ((long)write(_rawOutput,obj.data(),obj.length()) == (long)obj.length()) { + if (write(_rawOutput,"\n",1) == 1) + return true; + } + } else return true; #endif return false; } else if (_httpAddr) { @@ -202,7 +203,7 @@ void JSONDB::saveNetwork(const uint64_t networkId,const nlohmann::json &networkC { char n[64]; OSUtils::ztsnprintf(n,sizeof(n),"network/%.16llx",(unsigned long long)networkId); - writeRaw(n,OSUtils::jsonDump(networkConfig)); + writeRaw(n,OSUtils::jsonDump(networkConfig,-1)); { Mutex::Lock _l(_networks_m); _networks[networkId].config = nlohmann::json::to_msgpack(networkConfig); @@ -214,7 +215,7 @@ void JSONDB::saveNetworkMember(const uint64_t networkId,const uint64_t nodeId,co { char n[256]; OSUtils::ztsnprintf(n,sizeof(n),"network/%.16llx/member/%.10llx",(unsigned long long)networkId,(unsigned long long)nodeId); - writeRaw(n,OSUtils::jsonDump(memberConfig)); + writeRaw(n,OSUtils::jsonDump(memberConfig,-1)); { Mutex::Lock _l(_networks_m); _networks[networkId].members[nodeId] = nlohmann::json::to_msgpack(memberConfig); @@ -310,6 +311,7 @@ void JSONDB::threadMain() std::string rawInputBuf; FD_ZERO(&readfds); FD_ZERO(&nullfds); + struct timeval tv; #endif std::vector todo; @@ -317,24 +319,42 @@ void JSONDB::threadMain() while (_summaryThreadRun) { #ifndef __WINDOWS__ if (_rawInput < 0) { + // In HTTP and filesystem mode we just wait for summary to-do items Thread::sleep(25); } else { + // In IPC mode we wait but also select() on STDIN to read database updates FD_SET(_rawInput,&readfds); - struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 25000; select(_rawInput+1,&readfds,&nullfds,&nullfds,&tv); if (FD_ISSET(_rawInput,&readfds)) { const long rn = (long)read(_rawInput,readbuf,1048576); + bool gotMessage = false; for(long i=0;i 0) { - _add(OSUtils::jsonParse(rawInputBuf)); + try { + const nlohmann::json obj(OSUtils::jsonParse(rawInputBuf)); + + gotMessage = true; + if (!_dataReady) { + _dataReady = true; + _networks_m.unlock(); + } + + if (obj.is_array()) { + for(unsigned long i=0;i::iterator ii(todo.begin());ii!=todo.end();++ii) { - const uint64_t networkId = *ii; + if (!_dataReady) { + _dataReady = true; + _networks_m.unlock(); + } + + const uint64_t now = OSUtils::now(); + try { Mutex::Lock _l(_networks_m); - std::unordered_map::iterator n(_networks.find(networkId)); - if (n != _networks.end()) { - NetworkSummaryInfo &ns = n->second.summaryInfo; - ns.activeBridges.clear(); - ns.allocatedIps.clear(); - ns.authorizedMemberCount = 0; - ns.activeMemberCount = 0; - ns.totalMemberCount = 0; - ns.mostRecentDeauthTime = 0; - - for(std::unordered_map< uint64_t,std::vector >::const_iterator m(n->second.members.begin());m!=n->second.members.end();++m) { - try { - nlohmann::json member(nlohmann::json::from_msgpack(m->second)); - - if (OSUtils::jsonBool(member["authorized"],false)) { - ++ns.authorizedMemberCount; - - try { - const nlohmann::json &mlog = member["recentLog"]; - if ((mlog.is_array())&&(mlog.size() > 0)) { - const nlohmann::json &mlog1 = mlog[0]; - if (mlog1.is_object()) { - if ((now - OSUtils::jsonInt(mlog1["ts"],0ULL)) < (ZT_NETWORK_AUTOCONF_DELAY * 2)) - ++ns.activeMemberCount; + for(std::vector::iterator ii(todo.begin());ii!=todo.end();++ii) { + const uint64_t networkId = *ii; + std::unordered_map::iterator n(_networks.find(networkId)); + if (n != _networks.end()) { + NetworkSummaryInfo &ns = n->second.summaryInfo; + ns.activeBridges.clear(); + ns.allocatedIps.clear(); + ns.authorizedMemberCount = 0; + ns.activeMemberCount = 0; + ns.totalMemberCount = 0; + ns.mostRecentDeauthTime = 0; + + for(std::unordered_map< uint64_t,std::vector >::const_iterator m(n->second.members.begin());m!=n->second.members.end();++m) { + try { + nlohmann::json member(nlohmann::json::from_msgpack(m->second)); + + if (OSUtils::jsonBool(member["authorized"],false)) { + ++ns.authorizedMemberCount; + + try { + const nlohmann::json &mlog = member["recentLog"]; + if ((mlog.is_array())&&(mlog.size() > 0)) { + const nlohmann::json &mlog1 = mlog[0]; + if (mlog1.is_object()) { + if ((now - OSUtils::jsonInt(mlog1["ts"],0ULL)) < (ZT_NETWORK_AUTOCONF_DELAY * 2)) + ++ns.activeMemberCount; + } } - } - } catch ( ... ) {} - - try { - if (OSUtils::jsonBool(member["activeBridge"],false)) - ns.activeBridges.push_back(Address(m->first)); - } catch ( ... ) {} - - try { - const nlohmann::json &mips = member["ipAssignments"]; - if (mips.is_array()) { - for(unsigned long i=0;ifirst)); + } catch ( ... ) {} + + try { + const nlohmann::json &mips = member["ipAssignments"]; + if (mips.is_array()) { + for(unsigned long i=0;isecond.summaryInfoLastComputed = now; + n->second.summaryInfoLastComputed = now; + } } - } + } catch ( ... ) {} todo.clear(); } + if (!_dataReady) // sanity check + _networks_m.unlock(); + #ifndef __WINDOWS__ delete [] readbuf; #endif diff --git a/controller/JSONDB.hpp b/controller/JSONDB.hpp index 23d00a51..7131b0c1 100644 --- a/controller/JSONDB.hpp +++ b/controller/JSONDB.hpp @@ -62,6 +62,17 @@ public: JSONDB(const std::string &basePath); ~JSONDB(); + /** + * Write a JSON object to the data store + * + * It's important that obj contain a valid JSON object with no newlines (jsonDump with -1 + * for indentation), since newline-delimited JSON is what nodeJS's IPC speaks and this + * is important in Central-harnessed mode. + * + * @param n Path name of object + * @param obj Object in single-line no-CRs JSON object format (OSUtils::jsonDump(obj,-1)) + * @return True if write appears successful + */ bool writeRaw(const std::string &n,const std::string &obj); bool hasNetwork(const uint64_t networkId) const; @@ -171,6 +182,7 @@ private: std::unordered_map< uint64_t,_NW > _networks; std::unordered_map< uint64_t,std::unordered_set< uint64_t > > _members; + bool _dataReady; Mutex _networks_m; }; diff --git a/osdep/OSUtils.cpp b/osdep/OSUtils.cpp index 882b8255..c1edc353 100644 --- a/osdep/OSUtils.cpp +++ b/osdep/OSUtils.cpp @@ -434,7 +434,7 @@ std::string OSUtils::platformDefaultHomePath() // Inline these massive JSON operations in one place only to reduce binary footprint and compile time nlohmann::json OSUtils::jsonParse(const std::string &buf) { return nlohmann::json::parse(buf.c_str()); } -std::string OSUtils::jsonDump(const nlohmann::json &j) { return j.dump(1); } +std::string OSUtils::jsonDump(const nlohmann::json &j,int indentation) { return j.dump(indentation); } uint64_t OSUtils::jsonInt(const nlohmann::json &jv,const uint64_t dfl) { diff --git a/osdep/OSUtils.hpp b/osdep/OSUtils.hpp index d6f32822..8683ba25 100644 --- a/osdep/OSUtils.hpp +++ b/osdep/OSUtils.hpp @@ -276,7 +276,7 @@ public: static std::string platformDefaultHomePath(); static nlohmann::json jsonParse(const std::string &buf); - static std::string jsonDump(const nlohmann::json &j); + static std::string jsonDump(const nlohmann::json &j,int indentation = 1); static uint64_t jsonInt(const nlohmann::json &jv,const uint64_t dfl); static bool jsonBool(const nlohmann::json &jv,const bool dfl); static std::string jsonString(const nlohmann::json &jv,const char *dfl); diff --git a/service/OneService.cpp b/service/OneService.cpp index 115830e5..27f2ef3c 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -629,6 +629,14 @@ public: } } + // Allow controller DB path to be put somewhere else + json &settings = _localConfig["settings"]; + if (settings.is_object()) { + const std::string cdbp(OSUtils::jsonString(settings["controllerDbPath"],"")); + if (cdbp.length() > 0) + _controllerDbPath = cdbp; + } + // Set trusted paths if there are any if (trustedPathCount) _node->setTrustedPaths(reinterpret_cast(trustedPathNetworks),trustedPathIds,trustedPathCount); @@ -1484,27 +1492,6 @@ public: _allowManagementFrom.push_back(nw); } } - - json &controllerDbHttpHost = settings["controllerDbHttpHost"]; - json &controllerDbHttpPort = settings["controllerDbHttpPort"]; - json &controllerDbHttpPath = settings["controllerDbHttpPath"]; - if ((controllerDbHttpHost.is_string())&&(controllerDbHttpPort.is_number())) { - _controllerDbPath = "http://"; - std::string h = controllerDbHttpHost; - _controllerDbPath.append(h); - char dbp[128]; - OSUtils::ztsnprintf(dbp,sizeof(dbp),"%d",(int)controllerDbHttpPort); - _controllerDbPath.push_back(':'); - _controllerDbPath.append(dbp); - if (controllerDbHttpPath.is_string()) { - std::string p = controllerDbHttpPath; - if ((p.length() == 0)||(p[0] != '/')) - _controllerDbPath.push_back('/'); - _controllerDbPath.append(p); - } else { - _controllerDbPath.push_back('/'); - } - } } // Checks if a managed IP or route target is allowed -- cgit v1.2.3 From ee1dc16e8ffc5c5cc8f3b5da97cf2d01c7604ab7 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Thu, 10 Aug 2017 00:59:15 -0700 Subject: Added getRoutes() for libzt --- service/OneService.cpp | 26 ++++++-------------------- service/OneService.hpp | 3 +-- 2 files changed, 7 insertions(+), 22 deletions(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 27f2ef3c..ab3b8d73 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -925,29 +925,15 @@ public: return _homePath; } - virtual EthernetTap * getTap(uint64_t nwid) + std::vector *getRoutes(uint64_t nwid) { Mutex::Lock _l(_nets_m); - std::map::const_iterator n(_nets.find(nwid)); - if (n == _nets.end()) - return NULL; - return n->second.tap; - } - - virtual EthernetTap *getTap(InetAddress &addr) - { - Mutex::Lock _l(_nets_m); - std::map::iterator it; - for(it = _nets.begin(); it != _nets.end(); it++) { - if(it->second.tap) { - for(int j=0; jsecond.tap->_ips.size(); j++) { - if(it->second.tap->_ips[j].isEqualPrefix(addr) || it->second.tap->_ips[j].ipsEqual(addr) || it->second.tap->_ips[j].containsAddress(addr)) { - return it->second.tap; - } - } - } + NetworkState &n = _nets[nwid]; + std::vector *routes = new std::vector(); + for(int i=0; ipush_back(n.config.routes[i]); } - return NULL; + return routes; } virtual Node *getNode() diff --git a/service/OneService.hpp b/service/OneService.hpp index eba10ca0..0d37ec63 100644 --- a/service/OneService.hpp +++ b/service/OneService.hpp @@ -150,10 +150,9 @@ public: virtual void leave(const char *hp) = 0; virtual void join(const char *hp) = 0; virtual std::string givenHomePath() = 0; - virtual EthernetTap * getTap(uint64_t nwid) = 0; - virtual EthernetTap * getTap(InetAddress &addr) = 0; virtual Node * getNode() = 0; virtual void removeNets() = 0; + virtual std::vector *getRoutes(uint64_t nwid) = 0; #endif /** -- cgit v1.2.3 From 59b7cbb591b8f9ed4abfc25773619d6b1bebc4d2 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Tue, 15 Aug 2017 16:22:28 -0700 Subject: Rename SocketTap to VirtualTap to prevent confusion on role --- service/OneService.cpp | 4 ++-- service/OneService.hpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index ab3b8d73..c3bf9fee 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -99,8 +99,8 @@ namespace ZeroTier { typedef TestEthernetTap EthernetTap; } #include "../controller/EmbeddedNetworkController.hpp" #include "../node/Node.hpp" // Use the virtual netcon endpoint instead of a tun/tap port driver -#include "../src/SocketTap.hpp" -namespace ZeroTier { typedef SocketTap EthernetTap; } +#include "../src/VirtualTap.hpp" +namespace ZeroTier { typedef VirtualTap EthernetTap; } #else diff --git a/service/OneService.hpp b/service/OneService.hpp index 0d37ec63..b0467419 100644 --- a/service/OneService.hpp +++ b/service/OneService.hpp @@ -35,8 +35,8 @@ #ifdef ZT_SDK #include "../node/Node.hpp" // Use the virtual netcon endpoint instead of a tun/tap port driver -#include "../src/SocketTap.hpp" -namespace ZeroTier { typedef SocketTap EthernetTap; } +#include "../src/VirtualTap.hpp" +namespace ZeroTier { typedef VirtualTap EthernetTap; } #endif namespace ZeroTier { -- cgit v1.2.3 From 4352202349a9059d4cd1fbad7e148ed047d8e47d Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 18 Aug 2017 14:54:10 -0700 Subject: Reduce TCP relay latency -- see GitHub issue #564 --- service/OneService.cpp | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index c3bf9fee..f5f8700a 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -2142,19 +2142,30 @@ public: const uint64_t now = OSUtils::now(); if (((now - _lastDirectReceiveFromGlobal) > ZT_TCP_FALLBACK_AFTER)&&((now - _lastRestart) > ZT_TCP_FALLBACK_AFTER)) { if (_tcpFallbackTunnel) { - Mutex::Lock _l(_tcpFallbackTunnel->writeq_m); - if (_tcpFallbackTunnel->writeq.length() == 0) - _phy.setNotifyWritable(_tcpFallbackTunnel->sock,true); - const unsigned long mlen = len + 7; - _tcpFallbackTunnel->writeq.push_back((char)0x17); - _tcpFallbackTunnel->writeq.push_back((char)0x03); - _tcpFallbackTunnel->writeq.push_back((char)0x03); // fake TLS 1.2 header - _tcpFallbackTunnel->writeq.push_back((char)((mlen >> 8) & 0xff)); - _tcpFallbackTunnel->writeq.push_back((char)(mlen & 0xff)); - _tcpFallbackTunnel->writeq.push_back((char)4); // IPv4 - _tcpFallbackTunnel->writeq.append(reinterpret_cast(reinterpret_cast(&(reinterpret_cast(addr)->sin_addr.s_addr))),4); - _tcpFallbackTunnel->writeq.append(reinterpret_cast(reinterpret_cast(&(reinterpret_cast(addr)->sin_port))),2); - _tcpFallbackTunnel->writeq.append((const char *)data,len); + bool flushNow = false; + { + Mutex::Lock _l(_tcpFallbackTunnel->writeq_m); + if (_tcpFallbackTunnel->writeq.size() < (1024 * 64)) { + if (_tcpFallbackTunnel->writeq.length() == 0) { + _phy.setNotifyWritable(_tcpFallbackTunnel->sock,true); + flushNow = true; + } + const unsigned long mlen = len + 7; + _tcpFallbackTunnel->writeq.push_back((char)0x17); + _tcpFallbackTunnel->writeq.push_back((char)0x03); + _tcpFallbackTunnel->writeq.push_back((char)0x03); // fake TLS 1.2 header + _tcpFallbackTunnel->writeq.push_back((char)((mlen >> 8) & 0xff)); + _tcpFallbackTunnel->writeq.push_back((char)(mlen & 0xff)); + _tcpFallbackTunnel->writeq.push_back((char)4); // IPv4 + _tcpFallbackTunnel->writeq.append(reinterpret_cast(reinterpret_cast(&(reinterpret_cast(addr)->sin_addr.s_addr))),4); + _tcpFallbackTunnel->writeq.append(reinterpret_cast(reinterpret_cast(&(reinterpret_cast(addr)->sin_port))),2); + _tcpFallbackTunnel->writeq.append((const char *)data,len); + } + } + if (flushNow) { + void *tmpptr = (void *)_tcpFallbackTunnel; + phyOnTcpWritable(_tcpFallbackTunnel->sock,&tmpptr); + } } else if (((now - _lastSendToGlobalV4) < ZT_TCP_FALLBACK_AFTER)&&((now - _lastSendToGlobalV4) > (ZT_PING_CHECK_INVERVAL / 2))) { const InetAddress addr(ZT_TCP_FALLBACK_RELAY); TcpConnection *tc = new TcpConnection(); -- cgit v1.2.3 From 64758c46b672f8b3182c370aed6b81a07780c093 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 23 Aug 2017 13:40:51 -0700 Subject: Implement peer serialization and deserialization. --- node/Peer.cpp | 2 +- node/Peer.hpp | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++ node/Topology.cpp | 31 +++++++++++++++---- node/Topology.hpp | 2 ++ service/OneService.cpp | 25 ++++++++++++--- 5 files changed, 132 insertions(+), 12 deletions(-) (limited to 'service/OneService.cpp') diff --git a/node/Peer.cpp b/node/Peer.cpp index 986e52ef..127f222c 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -369,7 +369,7 @@ void Peer::tryMemorizedPath(void *tPtr,uint64_t now) _lastTriedMemorizedPath = now; InetAddress mp; if (RR->node->externalPathLookup(tPtr,_id.address(),-1,mp)) - attemptToContactAt(tPtr,InetAddress(),mp,now,true,0); + attemptToContactAt(tPtr,-1,mp,now,true,0); } } diff --git a/node/Peer.hpp b/node/Peer.hpp index c6423a59..af9163a5 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -439,6 +439,90 @@ public: return false; } + /** + * Serialize a peer for storage in local cache + * + * This does not serialize everything, just identity and addresses where the peer + * may be reached. + */ + template + inline void serialize(Buffer &b) const + { + b.append((uint8_t)0); + + _id.serialize(b); + + b.append(_lastReceive); + b.append(_lastNontrivialReceive); + b.append(_lastTriedMemorizedPath); + b.append(_lastDirectPathPushSent); + b.append(_lastDirectPathPushReceive); + b.append(_lastCredentialRequestSent); + b.append(_lastWhoisRequestReceived); + b.append(_lastEchoRequestReceived); + b.append(_lastComRequestReceived); + b.append(_lastComRequestSent); + b.append(_lastCredentialsReceived); + b.append(_lastTrustEstablishedPacketReceived); + + b.append((uint16_t)_vProto); + b.append((uint16_t)_vMajor); + b.append((uint16_t)_vMinor); + b.append((uint16_t)_vRevision); + + { + Mutex::Lock _l(_paths_m); + unsigned int pcount = 0; + if (_v4Path.p) ++pcount; + if (_v6Path.p) ++pcount; + b.append((uint8_t)pcount); + if (_v4Path.p) _v4Path.p->address().serialize(b); + if (_v6Path.p) _v6Path.p->address().serialize(b); + } + + b.append((uint16_t)0); + } + + template + inline static SharedPtr deserializeFromCache(uint64_t now,void *tPtr,Buffer &b,const RuntimeEnvironment *renv) + { + try { + unsigned int ptr = 0; + if (b[ptr++] != 0) + return SharedPtr(); + + Identity id; + ptr += id.deserialize(b,ptr); + if (!id) + return SharedPtr(); + + SharedPtr p(new Peer(renv,renv->identity,id)); + + ptr += 12 * 8; // skip deserializing ephemeral state in this case + + p->_vProto = b.template at(ptr); ptr += 2; + p->_vMajor = b.template at(ptr); ptr += 2; + p->_vMinor = b.template at(ptr); ptr += 2; + p->_vRevision = b.template at(ptr); ptr += 2; + + const unsigned int pcount = (unsigned int)b[ptr++]; + for(unsigned int i=0;iattemptToContactAt(tPtr,-1,inaddr,now,true,0); + } catch ( ... ) { + break; + } + } + + return p; + } catch ( ... ) { + return SharedPtr(); + } + } + private: struct _PeerPath { diff --git a/node/Topology.cpp b/node/Topology.cpp index edca0180..aeca59a7 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -88,6 +88,15 @@ Topology::Topology(const RuntimeEnvironment *renv,void *tPtr) : addWorld(tPtr,defaultPlanet,false); } +Topology::~Topology() +{ + Hashtable< Address,SharedPtr >::Iterator i(_peers); + Address *a = (Address *)0; + SharedPtr *p = (SharedPtr *)0; + while (i.next(a,p)) + _savePeer((void *)0,*p); +} + SharedPtr Topology::addPeer(void *tPtr,const SharedPtr &peer) { SharedPtr np; @@ -113,23 +122,21 @@ SharedPtr Topology::getPeer(void *tPtr,const Address &zta) return *ap; } - /* try { - char buf[ZT_PEER_MAX_SERIALIZED_STATE_SIZE]; + Buffer buf; uint64_t idbuf[2]; idbuf[0] = zta.toInt(); idbuf[1] = 0; - int len = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_PEER,idbuf,buf,(unsigned int)sizeof(buf)); + int len = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_PEER,idbuf,buf.unsafeData(),ZT_PEER_MAX_SERIALIZED_STATE_SIZE); if (len > 0) { Mutex::Lock _l(_peers_m); SharedPtr &ap = _peers[zta]; if (ap) return ap; - ap = Peer::createFromStateUpdate(RR,tPtr,buf,len); + ap = Peer::deserializeFromCache(RR->node->now(),tPtr,buf,RR); if (!ap) _peers.erase(zta); return ap; } } catch ( ... ) {} // ignore invalid identities or other strage failures - */ return SharedPtr(); } @@ -383,8 +390,10 @@ void Topology::doPeriodicTasks(void *tPtr,uint64_t now) Address *a = (Address *)0; SharedPtr *p = (SharedPtr *)0; while (i.next(a,p)) { - if ( (!(*p)->isAlive(now)) && (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),*a) == _upstreamAddresses.end()) ) + if ( (!(*p)->isAlive(now)) && (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),*a) == _upstreamAddresses.end()) ) { + _savePeer(tPtr,*p); _peers.erase(*a); + } } } @@ -440,4 +449,14 @@ void Topology::_memoizeUpstreams(void *tPtr) _cor.sign(RR->identity,RR->node->now()); } +void Topology::_savePeer(void *tPtr,const SharedPtr &peer) +{ + try { + Buffer buf; + peer->serialize(buf); + uint64_t tmpid[2]; tmpid[0] = peer->address().toInt(); tmpid[1] = 0; + RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_PEER,tmpid,buf.data(),buf.size()); + } catch ( ... ) {} // sanity check, discard invalid entries +} + } // namespace ZeroTier diff --git a/node/Topology.hpp b/node/Topology.hpp index 30e58abc..04dfb1cc 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -59,6 +59,7 @@ class Topology { public: Topology(const RuntimeEnvironment *renv,void *tPtr); + ~Topology(); /** * Add a peer to database @@ -419,6 +420,7 @@ public: private: Identity _getIdentity(void *tPtr,const Address &zta); void _memoizeUpstreams(void *tPtr); + void _savePeer(void *tPtr,const SharedPtr &peer); const RuntimeEnvironment *const RR; diff --git a/service/OneService.cpp b/service/OneService.cpp index f5f8700a..cd33e399 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -2047,6 +2047,8 @@ public: char p[1024]; FILE *f; bool secure = false; + char dirname[1024]; + dirname[0] = 0; switch(type) { case ZT_STATE_OBJECT_IDENTITY_PUBLIC: @@ -2060,12 +2062,18 @@ public: OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); break; case ZT_STATE_OBJECT_MOON: - OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id[0]); + OSUtils::ztsnprintf(dirname,sizeof(dirname),"%s" ZT_PATH_SEPARATOR_S "moons.d",_homePath.c_str()); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx.moon",dirname,(unsigned long long)id[0]); break; case ZT_STATE_OBJECT_NETWORK_CONFIG: - OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id[0]); + OSUtils::ztsnprintf(dirname,sizeof(dirname),"%s" ZT_PATH_SEPARATOR_S "networks.d",_homePath.c_str()); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx.conf",dirname,(unsigned long long)id[0]); secure = true; break; + case ZT_STATE_OBJECT_PEER: + OSUtils::ztsnprintf(dirname,sizeof(dirname),"%s" ZT_PATH_SEPARATOR_S "peers.d",_homePath.c_str()); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.10llx.peer",dirname,(unsigned long long)id[0]); + break; default: return; } @@ -2084,6 +2092,10 @@ public: } f = fopen(p,"w"); + if ((!f)&&(dirname[0])) { // create subdirectory if it does not exist + OSUtils::mkdir(dirname); + f = fopen(p,"w"); + } if (f) { if (fwrite(data,len,1,f) != 1) fprintf(stderr,"WARNING: unable to write to file: %s (I/O error)" ZT_EOL_S,p); @@ -2108,15 +2120,18 @@ public: case ZT_STATE_OBJECT_IDENTITY_SECRET: OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str()); break; - case ZT_STATE_OBJECT_NETWORK_CONFIG: - OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id); - break; case ZT_STATE_OBJECT_PLANET: OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); break; case ZT_STATE_OBJECT_MOON: OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id); break; + case ZT_STATE_OBJECT_NETWORK_CONFIG: + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id); + break; + case ZT_STATE_OBJECT_PEER: + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "peers.d/%.10llx.conf",_homePath.c_str(),(unsigned long long)id[0]); + break; default: return -1; } -- cgit v1.2.3 From 2cebe7a5e0069880e197590a03c4afa8a9492595 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 23 Aug 2017 14:09:29 -0700 Subject: Fix name difference. --- service/OneService.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index cd33e399..2da72461 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -2124,13 +2124,13 @@ public: OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); break; case ZT_STATE_OBJECT_MOON: - OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d" ZT_PATH_SEPARATOR_S "%.16llx.moon",_homePath.c_str(),(unsigned long long)id); break; case ZT_STATE_OBJECT_NETWORK_CONFIG: - OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.conf",_homePath.c_str(),(unsigned long long)id); break; case ZT_STATE_OBJECT_PEER: - OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "peers.d/%.10llx.conf",_homePath.c_str(),(unsigned long long)id[0]); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "peers.d" ZT_PATH_SEPARATOR_S "%.10llx.peer",_homePath.c_str(),(unsigned long long)id[0]); break; default: return -1; -- cgit v1.2.3 From 6418d02572d91b0e53b030642d997573181d8c6b Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 24 Aug 2017 15:33:24 -0700 Subject: Fix HTTP DELETE stupid bug. --- service/OneService.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 2da72461..093d9ee8 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1728,9 +1728,10 @@ public: case TcpConnection::TCP_UNCATEGORIZED_INCOMING: switch(reinterpret_cast(data)[0]) { - // HTTP: GET, PUT, POST, HEAD + // HTTP: GET, PUT, POST, HEAD, DELETE case 'G': case 'P': + case 'D': case 'H': { // This is only allowed from IPs permitted to access the management // backplane, which is just 127.0.0.1/::1 unless otherwise configured. @@ -2313,7 +2314,7 @@ public: fprintf(stderr,"WARNING: unexpected exception processing control HTTP request: %s" ZT_EOL_S,exc.what()); scode = 500; } catch ( ... ) { - fprintf(stderr,"WARNING: unexpected exception processing control HTTP request: unknown exceptino" ZT_EOL_S); + fprintf(stderr,"WARNING: unexpected exception processing control HTTP request: unknown exception" ZT_EOL_S); scode = 500; } -- cgit v1.2.3 From f8014413a376551b7853baae81072f969a755e46 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 1 Sep 2017 16:25:34 -0700 Subject: Add UDP MTU configurability. --- include/ZeroTierOne.h | 55 +++++++++++++++-------------- node/Multicaster.cpp | 2 +- node/Network.cpp | 1 - node/Node.cpp | 14 ++++---- node/Node.hpp | 2 +- node/Packet.hpp | 6 +--- node/Switch.cpp | 13 ++++--- node/Topology.cpp | 2 +- node/Topology.hpp | 95 ++++++++++++++++++++++++++++++++++++++------------ service/OneService.cpp | 25 ++++++------- service/README.md | 3 +- 11 files changed, 134 insertions(+), 84 deletions(-) (limited to 'service/OneService.cpp') diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index b889ade0..7cbebb32 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -93,13 +93,17 @@ extern "C" { #define ZT_MAX_MTU 10000 /** - * Default payload MTU for UDP packets + * Minimum UDP payload size allowed + */ +#define ZT_MIN_PHYSMTU 1400 + +/** + * Default UDP payload size (physical path MTU) not including UDP and IP overhead * * This is 1500 - IPv6 UDP overhead - PPPoE overhead and is safe for 99.9% of * all Internet links. */ #define ZT_DEFAULT_PHYSMTU 1444 -#define ZT_UDP_DEFAULT_PAYLOAD_MTU 1444 /** * Maximum physical UDP payload @@ -172,9 +176,9 @@ extern "C" { #define ZT_MAX_PEER_NETWORK_PATHS 4 /** - * Maximum number of trusted physical network paths + * Maximum number of path configurations that can be set */ -#define ZT_MAX_TRUSTED_PATHS 16 +#define ZT_MAX_CONFIGURABLE_PATHS 32 /** * Maximum number of rules per capability @@ -1058,11 +1062,6 @@ typedef struct */ unsigned int mtu; - /** - * Recommended MTU to avoid fragmentation at the physical layer (hint) - */ - unsigned int physicalMtu; - /** * If nonzero, the network this port belongs to indicates DHCP availability * @@ -1132,6 +1131,21 @@ typedef struct unsigned long networkCount; } ZT_VirtualNetworkList; +/** + * Physical path configuration + */ +typedef struct { + /** + * If non-zero set this physical network path to be trusted to disable encryption and authentication + */ + uint64_t trustedPathId; + + /** + * Physical path MTU from ZT_MIN_PHYSMTU and ZT_MAX_PHYSMTU or <= 0 to use default + */ + int mtu; +} ZT_PhysicalPathConfiguration; + /** * Physical network path to a peer */ @@ -1856,27 +1870,14 @@ ZT_SDK_API int ZT_Node_sendUserMessage(ZT_Node *node,void *tptr,uint64_t dest,ui ZT_SDK_API void ZT_Node_setNetconfMaster(ZT_Node *node,void *networkConfigMasterInstance); /** - * Set trusted paths - * - * A trusted path is a physical network (network/bits) over which both - * encryption and authentication can be skipped to improve performance. - * Each trusted path must have a non-zero unique ID that is the same across - * all participating nodes. - * - * We don't recommend using trusted paths at all unless you really *need* - * near-bare-metal performance. Even on a LAN authentication and encryption - * are never a bad thing, and anything that introduces an "escape hatch" - * for encryption should be treated with the utmost care. - * - * Calling with NULL pointers for networks and ids and a count of zero clears - * all trusted paths. + * Set configuration for a given physical path * * @param node Node instance - * @param networks Array of [count] networks - * @param ids Array of [count] corresponding non-zero path IDs (zero path IDs are ignored) - * @param count Number of trusted paths-- values greater than ZT_MAX_TRUSTED_PATHS are clipped + * @param pathNetwork Network/CIDR of path or NULL to clear the cache and reset all paths to default + * @param pathConfig Path configuration or NULL to erase this entry and therefore reset it to NULL + * @return OK or error code */ -ZT_SDK_API void ZT_Node_setTrustedPaths(ZT_Node *node,const struct sockaddr_storage *networks,const uint64_t *ids,unsigned int count); +ZT_SDK_API enum ZT_ResultCode ZT_Node_setPhysicalPathConfiguration(ZT_Node *node,const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig); /** * Get ZeroTier One version diff --git a/node/Multicaster.cpp b/node/Multicaster.cpp index fb7b068f..e8c8613a 100644 --- a/node/Multicaster.cpp +++ b/node/Multicaster.cpp @@ -111,7 +111,7 @@ unsigned int Multicaster::gather(const Address &queryingPeer,uint64_t nwid,const // Members are returned in random order so that repeated gather queries // will return different subsets of a large multicast group. k = 0; - while ((added < limit)&&(k < s->members.size())&&((appendTo.size() + ZT_ADDRESS_LENGTH) <= ZT_UDP_DEFAULT_PAYLOAD_MTU)) { + while ((added < limit)&&(k < s->members.size())&&((appendTo.size() + ZT_ADDRESS_LENGTH) <= ZT_PROTO_MAX_PACKET_LENGTH)) { rptr = (unsigned int)RR->node->prng(); restart_member_scan: diff --git a/node/Network.cpp b/node/Network.cpp index f7b144e3..16155c33 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -1346,7 +1346,6 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const ec->status = _status(); ec->type = (_config) ? (_config.isPrivate() ? ZT_NETWORK_TYPE_PRIVATE : ZT_NETWORK_TYPE_PUBLIC) : ZT_NETWORK_TYPE_PRIVATE; ec->mtu = (_config) ? _config.mtu : ZT_DEFAULT_MTU; - ec->physicalMtu = ZT_UDP_DEFAULT_PAYLOAD_MTU - (ZT_PACKET_IDX_PAYLOAD + 16); ec->dhcp = 0; std::vector
ab(_config.activeBridges()); ec->bridge = ((_config.allowPassiveBridging())||(std::find(ab.begin(),ab.end(),RR->identity.address()) != ab.end())) ? 1 : 0; diff --git a/node/Node.cpp b/node/Node.cpp index 34609fd4..871fb21b 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -561,9 +561,9 @@ uint64_t Node::prng() return z + y; } -void Node::setTrustedPaths(const struct sockaddr_storage *networks,const uint64_t *ids,unsigned int count) +ZT_ResultCode Node::setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork, const ZT_PhysicalPathConfiguration *pathConfig) { - RR->topology->setTrustedPaths(reinterpret_cast(networks),ids,count); + return ZT_RESULT_OK; } World Node::planet() const @@ -815,7 +815,7 @@ enum ZT_ResultCode ZT_Node_orbit(ZT_Node *node,void *tptr,uint64_t moonWorldId,u } } -ZT_ResultCode ZT_Node_deorbit(ZT_Node *node,void *tptr,uint64_t moonWorldId) +enum ZT_ResultCode ZT_Node_deorbit(ZT_Node *node,void *tptr,uint64_t moonWorldId) { try { return reinterpret_cast(node)->deorbit(tptr,moonWorldId); @@ -902,11 +902,13 @@ void ZT_Node_setNetconfMaster(ZT_Node *node,void *networkControllerInstance) } catch ( ... ) {} } -void ZT_Node_setTrustedPaths(ZT_Node *node,const struct sockaddr_storage *networks,const uint64_t *ids,unsigned int count) +enum ZT_ResultCode ZT_Node_setPhysicalPathConfiguration(ZT_Node *node,const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig) { try { - reinterpret_cast(node)->setTrustedPaths(networks,ids,count); - } catch ( ... ) {} + return reinterpret_cast(node)->setPhysicalPathConfiguration(pathNetwork,pathConfig); + } catch ( ... ) { + return ZT_RESULT_FATAL_ERROR_INTERNAL; + } } void ZT_version(int *major,int *minor,int *revision) diff --git a/node/Node.hpp b/node/Node.hpp index 9658174f..1aa01c9a 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -192,7 +192,7 @@ public: inline bool externalPathLookup(void *tPtr,const Address &ztaddr,int family,InetAddress &addr) { return ( (_cb.pathLookupFunction) ? (_cb.pathLookupFunction(reinterpret_cast(this),_uPtr,tPtr,ztaddr.toInt(),family,reinterpret_cast(&addr)) != 0) : false ); } uint64_t prng(); - void setTrustedPaths(const struct sockaddr_storage *networks,const uint64_t *ids,unsigned int count); + ZT_ResultCode setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig); World planet() const; std::vector moons() const; diff --git a/node/Packet.hpp b/node/Packet.hpp index 5fc631b1..db70e06f 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -225,12 +225,8 @@ /** * Packet buffer size (can be changed) - * - * The current value is big enough for ZT_MAX_PACKET_FRAGMENTS, the pragmatic - * packet fragment limit, times the default UDP MTU. Most packets won't be - * this big. */ -#define ZT_PROTO_MAX_PACKET_LENGTH (ZT_MAX_PACKET_FRAGMENTS * ZT_UDP_DEFAULT_PAYLOAD_MTU) +#define ZT_PROTO_MAX_PACKET_LENGTH (ZT_MAX_PACKET_FRAGMENTS * ZT_DEFAULT_PHYSMTU) /** * Minimum viable packet length (a.k.a. header length) diff --git a/node/Switch.cpp b/node/Switch.cpp index 952bdef8..f46b3e73 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -722,10 +722,13 @@ bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt) return false; } - unsigned int chunkSize = std::min(packet.size(),(unsigned int)ZT_UDP_DEFAULT_PAYLOAD_MTU); + unsigned int mtu = ZT_DEFAULT_PHYSMTU; + uint64_t trustedPathId = 0; + RR->topology->getOutboundPathInfo(viaPath->address(),mtu,trustedPathId); + + unsigned int chunkSize = std::min(packet.size(),mtu); packet.setFragmented(chunkSize < packet.size()); - const uint64_t trustedPathId = RR->topology->getOutboundPathTrust(viaPath->address()); if (trustedPathId) { packet.setTrusted(trustedPathId); } else { @@ -737,13 +740,13 @@ bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt) // Too big for one packet, fragment the rest unsigned int fragStart = chunkSize; unsigned int remaining = packet.size() - chunkSize; - unsigned int fragsRemaining = (remaining / (ZT_UDP_DEFAULT_PAYLOAD_MTU - ZT_PROTO_MIN_FRAGMENT_LENGTH)); - if ((fragsRemaining * (ZT_UDP_DEFAULT_PAYLOAD_MTU - ZT_PROTO_MIN_FRAGMENT_LENGTH)) < remaining) + unsigned int fragsRemaining = (remaining / (mtu - ZT_PROTO_MIN_FRAGMENT_LENGTH)); + if ((fragsRemaining * (mtu - ZT_PROTO_MIN_FRAGMENT_LENGTH)) < remaining) ++fragsRemaining; const unsigned int totalFragments = fragsRemaining + 1; for(unsigned int fno=1;fnosend(RR,tPtr,frag.data(),frag.size(),now); fragStart += chunkSize; diff --git a/node/Topology.cpp b/node/Topology.cpp index ee5d969d..905b6a91 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -65,7 +65,7 @@ static const unsigned char ZT_DEFAULT_WORLD[ZT_DEFAULT_WORLD_LENGTH] = {0x01,0x0 Topology::Topology(const RuntimeEnvironment *renv,void *tPtr) : RR(renv), - _trustedPathCount(0), + _numConfiguredPhysicalPaths(0), _amRoot(false) { uint8_t tmp[ZT_WORLD_MAX_SERIALIZED_LENGTH]; diff --git a/node/Topology.hpp b/node/Topology.hpp index 43921896..34df28a1 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -339,6 +339,41 @@ public: */ inline bool amRoot() const { return _amRoot; } + /** + * Get info about a path + * + * The supplied result variables are not modified if no special config info is found. + * + * @param physicalAddress Physical endpoint address + * @param mtu Variable set to MTU + * @param trustedPathId Variable set to trusted path ID + */ + inline void getOutboundPathInfo(const InetAddress &physicalAddress,unsigned int &mtu,uint64_t &trustedPathId) + { + for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i ZT_MAX_TRUSTED_PATHS) - count = ZT_MAX_TRUSTED_PATHS; - Mutex::Lock _l(_trustedPaths_m); - for(unsigned int i=0;i cpaths; + for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i ZT_MAX_PHYSMTU) + pc.mtu = ZT_MAX_PHYSMTU; + + cpaths[*(reinterpret_cast(pathNetwork))] = pc; + } else { + cpaths.erase(*(reinterpret_cast(pathNetwork))); + } + + unsigned int cnt = 0; + for(std::map::const_iterator i(cpaths.begin());((i!=cpaths.end())&&(cntfirst; + _physicalPathConfig[cnt].second = i->second; + ++cnt; + } + _numConfiguredPhysicalPaths = cnt; } - _trustedPathCount = count; } /** @@ -414,10 +467,8 @@ private: const RuntimeEnvironment *const RR; - uint64_t _trustedPathIds[ZT_MAX_TRUSTED_PATHS]; - InetAddress _trustedPathNetworks[ZT_MAX_TRUSTED_PATHS]; - unsigned int _trustedPathCount; - Mutex _trustedPaths_m; + std::pair _physicalPathConfig[ZT_MAX_CONFIGURABLE_PATHS]; + volatile unsigned int _numConfiguredPhysicalPaths; Hashtable< Address,SharedPtr > _peers; Mutex _peers_m; diff --git a/service/OneService.cpp b/service/OneService.cpp index 093d9ee8..66e9a9c8 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -564,16 +564,14 @@ public: // Read local configuration { - uint64_t trustedPathIds[ZT_MAX_TRUSTED_PATHS]; - InetAddress trustedPathNetworks[ZT_MAX_TRUSTED_PATHS]; - unsigned int trustedPathCount = 0; + std::map ppc; // LEGACY: support old "trustedpaths" flat file FILE *trustpaths = fopen((_homePath + ZT_PATH_SEPARATOR_S "trustedpaths").c_str(),"r"); if (trustpaths) { fprintf(stderr,"WARNING: 'trustedpaths' flat file format is deprecated in favor of path definitions in local.conf" ZT_EOL_S); char buf[1024]; - while ((fgets(buf,sizeof(buf),trustpaths))&&(trustedPathCount < ZT_MAX_TRUSTED_PATHS)) { + while (fgets(buf,sizeof(buf),trustpaths)) { int fno = 0; char *saveptr = (char *)0; uint64_t trustedPathId = 0; @@ -587,9 +585,8 @@ public: ++fno; } if ( (trustedPathId != 0) && ((trustedPathNetwork.ss_family == AF_INET)||(trustedPathNetwork.ss_family == AF_INET6)) && (trustedPathNetwork.ipScope() != InetAddress::IP_SCOPE_GLOBAL) && (trustedPathNetwork.netmaskBits() > 0) ) { - trustedPathIds[trustedPathCount] = trustedPathId; - trustedPathNetworks[trustedPathCount] = trustedPathNetwork; - ++trustedPathCount; + ppc[trustedPathNetwork].trustedPathId = trustedPathId; + ppc[trustedPathNetwork].mtu = 0; // use default } } fclose(trustpaths); @@ -618,12 +615,10 @@ public: if (phy.value().is_object()) { uint64_t tpid; if ((tpid = OSUtils::jsonInt(phy.value()["trustedPathId"],0ULL)) != 0ULL) { - if ( ((net.ss_family == AF_INET)||(net.ss_family == AF_INET6)) && (trustedPathCount < ZT_MAX_TRUSTED_PATHS) && (net.ipScope() != InetAddress::IP_SCOPE_GLOBAL) && (net.netmaskBits() > 0) ) { - trustedPathIds[trustedPathCount] = tpid; - trustedPathNetworks[trustedPathCount] = net; - ++trustedPathCount; - } + if ((net.ss_family == AF_INET)||(net.ss_family == AF_INET6)) + ppc[net].trustedPathId = tpid; } + ppc[net].mtu = (int)OSUtils::jsonInt(phy.value()["mtu"],0ULL); // 0 means use default } } } @@ -638,8 +633,10 @@ public: } // Set trusted paths if there are any - if (trustedPathCount) - _node->setTrustedPaths(reinterpret_cast(trustedPathNetworks),trustedPathIds,trustedPathCount); + if (ppc.size() > 0) { + for(std::map::iterator i(ppc.begin());i!=ppc.end();++i) + _node->setPhysicalPathConfiguration(reinterpret_cast(&(i->first)),&(i->second)); + } } // Apply other runtime configuration from local.conf diff --git a/service/README.md b/service/README.md index f5223f2d..77085a6f 100644 --- a/service/README.md +++ b/service/README.md @@ -14,7 +14,8 @@ Settings available in `local.conf` (this is not valid JSON, and JSON does not al "physical": { /* Settings that apply to physical L2/L3 network paths. */ "NETWORK/bits": { /* Network e.g. 10.0.0.0/24 or fd00::/32 */ "blacklist": true|false, /* If true, blacklist this path for all ZeroTier traffic */ - "trustedPathId": 0|!0 /* If present and nonzero, define this as a trusted path (see below) */ + "trustedPathId": 0|!0, /* If present and nonzero, define this as a trusted path (see below) */ + "mtu": 0|!0 /* if present and non-zero, set UDP maximum payload MTU for this path */ } /* ,... additional networks */ }, "virtual": { /* Settings applied to ZeroTier virtual network devices (VL1) */ -- cgit v1.2.3 From b1d60df44cb24589bc5718da932ef4bb54168fa3 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Mon, 2 Oct 2017 15:52:57 -0700 Subject: timestamps changed from uint64_t to int64_t There were cases in the code where time calculations and comparisons were overflowing and causing connection instability. This will keep time calculations within expected ranges. --- controller/EmbeddedNetworkController.cpp | 14 +++--- controller/EmbeddedNetworkController.hpp | 8 ++-- controller/JSONDB.cpp | 4 +- controller/JSONDB.hpp | 2 +- include/ZeroTierOne.h | 12 ++--- node/CertificateOfMembership.hpp | 2 +- node/IncomingPacket.cpp | 12 ++--- node/IncomingPacket.hpp | 4 +- node/Membership.cpp | 8 ++-- node/Membership.hpp | 14 +++--- node/Multicaster.cpp | 8 ++-- node/Multicaster.hpp | 12 ++--- node/Network.cpp | 10 ++--- node/Network.hpp | 4 +- node/Node.cpp | 34 +++++++------- node/Node.hpp | 26 +++++------ node/OutboundMulticast.hpp | 2 +- node/Path.cpp | 2 +- node/Path.hpp | 22 ++++----- node/Peer.cpp | 35 ++++++++------- node/Peer.hpp | 76 ++++++++++++++++---------------- node/Revocation.hpp | 4 +- node/SelfAwareness.cpp | 6 +-- node/SelfAwareness.hpp | 4 +- node/Switch.cpp | 20 ++++----- node/Switch.hpp | 14 +++--- node/Topology.cpp | 7 +-- node/Topology.hpp | 4 +- one.cpp | 6 +-- osdep/OSUtils.hpp | 6 +-- osdep/PortMapper.cpp | 2 +- service/OneService.cpp | 22 +++++---- service/SoftwareUpdater.cpp | 2 +- service/SoftwareUpdater.hpp | 2 +- 34 files changed, 209 insertions(+), 201 deletions(-) (limited to 'service/OneService.cpp') diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index 1d46d5e6..20f81966 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -535,7 +535,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( } else { // Get network - const uint64_t now = OSUtils::now(); + const int64_t now = OSUtils::now(); JSONDB::NetworkSummaryInfo ns; _db.getNetworkSummaryInfo(nwid,ns); _addNetworkNonPersistedFields(network,now,ns); @@ -602,7 +602,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( responseContentType = "application/json"; return 400; } - const uint64_t now = OSUtils::now(); + const int64_t now = OSUtils::now(); if (path[0] == "network") { @@ -1087,7 +1087,7 @@ void EmbeddedNetworkController::handleRemoteTrace(const ZT_RemoteTrace &rt) } } - const uint64_t now = OSUtils::now(); + const int64_t now = OSUtils::now(); OSUtils::ztsnprintf(id,sizeof(id),"%.10llx-%.10llx-%.16llx-%.8lx",_signingId.address().toInt(),rt.origin,now,++idCounter); d["id"] = id; d["objtype"] = "trace"; @@ -1129,7 +1129,7 @@ void EmbeddedNetworkController::handleRemoteTrace(const ZT_RemoteTrace &rt) void EmbeddedNetworkController::onNetworkUpdate(const uint64_t networkId) { // Send an update to all members of the network that are online - const uint64_t now = OSUtils::now(); + const int64_t now = OSUtils::now(); Mutex::Lock _l(_memberStatus_m); for(auto i=_memberStatus.begin();i!=_memberStatus.end();++i) { if ((i->first.networkId == networkId)&&(i->second.online(now))&&(i->second.lastRequestMetaData)) @@ -1150,7 +1150,7 @@ void EmbeddedNetworkController::onNetworkMemberUpdate(const uint64_t networkId,c void EmbeddedNetworkController::onNetworkMemberDeauthorize(const uint64_t networkId,const uint64_t memberId) { - const uint64_t now = OSUtils::now(); + 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); rev.sign(_signingId); { @@ -1224,7 +1224,7 @@ void EmbeddedNetworkController::_request( if (((!_signingId)||(!_signingId.hasPrivate()))||(_signingId.address().toInt() != (nwid >> 24))||(!_sender)) return; - const uint64_t now = OSUtils::now(); + const int64_t now = OSUtils::now(); if (requestPacketId) { Mutex::Lock _l(_memberStatus_m); @@ -1360,7 +1360,7 @@ void EmbeddedNetworkController::_request( // If we made it this far, they are authorized. // ------------------------------------------------------------------------- - uint64_t credentialtmd = ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MAX_MAX_DELTA; + int64_t credentialtmd = ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MAX_MAX_DELTA; if (now > ns.mostRecentDeauthTime) { // If we recently de-authorized a member, shrink credential TTL/max delta to // be below the threshold required to exclude it. Cap this to a min/max to diff --git a/controller/EmbeddedNetworkController.hpp b/controller/EmbeddedNetworkController.hpp index 19469164..fce56065 100644 --- a/controller/EmbeddedNetworkController.hpp +++ b/controller/EmbeddedNetworkController.hpp @@ -166,7 +166,7 @@ private: } network["objtype"] = "network"; } - inline void _addNetworkNonPersistedFields(nlohmann::json &network,uint64_t now,const JSONDB::NetworkSummaryInfo &ns) + inline void _addNetworkNonPersistedFields(nlohmann::json &network,int64_t now,const JSONDB::NetworkSummaryInfo &ns) { network["clock"] = now; network["authorizedMemberCount"] = ns.authorizedMemberCount; @@ -182,7 +182,7 @@ private: // legacy fields network.erase("lastModified"); } - inline void _addMemberNonPersistedFields(uint64_t nwid,uint64_t nodeId,nlohmann::json &member,uint64_t now) + inline void _addMemberNonPersistedFields(uint64_t nwid,uint64_t nodeId,nlohmann::json &member,int64_t now) { member["clock"] = now; Mutex::Lock _l(_memberStatus_m); @@ -197,7 +197,7 @@ private: member.erase("lastRequestMetaData"); } - const uint64_t _startTime; + const int64_t _startTime; volatile bool _running; BlockingQueue<_RQEntry *> _queue; @@ -230,7 +230,7 @@ private: Dictionary lastRequestMetaData; Identity identity; InetAddress physicalAddr; // last known physical address - inline bool online(const uint64_t now) const { return ((now - lastRequestTime) < (ZT_NETWORK_AUTOCONF_DELAY * 2)); } + inline bool online(const int64_t now) const { return ((now - lastRequestTime) < (ZT_NETWORK_AUTOCONF_DELAY * 2)); } }; struct _MemberStatusHash { diff --git a/controller/JSONDB.cpp b/controller/JSONDB.cpp index f362acf3..67b13393 100644 --- a/controller/JSONDB.cpp +++ b/controller/JSONDB.cpp @@ -323,7 +323,7 @@ void JSONDB::threadMain() _networks_m.unlock(); } - const uint64_t now = OSUtils::now(); + const int64_t now = OSUtils::now(); try { Mutex::Lock _l(_networks_m); for(std::vector::iterator ii(todo.begin());ii!=todo.end();++ii) { @@ -373,7 +373,7 @@ void JSONDB::threadMain() } catch ( ... ) {} } else { try { - ns.mostRecentDeauthTime = std::max(ns.mostRecentDeauthTime,OSUtils::jsonInt(member["lastDeauthorizedTime"],0ULL)); + ns.mostRecentDeauthTime = std::max(ns.mostRecentDeauthTime,(int64_t)OSUtils::jsonInt(member["lastDeauthorizedTime"],0LL)); } catch ( ... ) {} } ++ns.totalMemberCount; diff --git a/controller/JSONDB.hpp b/controller/JSONDB.hpp index 44f4d7f5..db909cb0 100644 --- a/controller/JSONDB.hpp +++ b/controller/JSONDB.hpp @@ -57,7 +57,7 @@ public: unsigned long authorizedMemberCount; unsigned long activeMemberCount; unsigned long totalMemberCount; - uint64_t mostRecentDeauthTime; + int64_t mostRecentDeauthTime; }; JSONDB(const std::string &basePath,EmbeddedNetworkController *parent); diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index cf6b21fd..8adbc4d1 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -1587,7 +1587,7 @@ struct ZT_Node_Callbacks * @param now Current clock in milliseconds * @return OK (0) or error code if a fatal error condition has occurred */ -ZT_SDK_API enum ZT_ResultCode ZT_Node_new(ZT_Node **node,void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now); +ZT_SDK_API enum ZT_ResultCode ZT_Node_new(ZT_Node **node,void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64_t now); /** * Delete a node and free all resources it consumes @@ -1615,12 +1615,12 @@ ZT_SDK_API void ZT_Node_delete(ZT_Node *node); ZT_SDK_API enum ZT_ResultCode ZT_Node_processWirePacket( ZT_Node *node, void *tptr, - uint64_t now, + int64_t now, int64_t localSocket, const struct sockaddr_storage *remoteAddress, const void *packetData, unsigned int packetLength, - volatile uint64_t *nextBackgroundTaskDeadline); + volatile int64_t *nextBackgroundTaskDeadline); /** * Process a frame from a virtual network port (tap) @@ -1641,7 +1641,7 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_processWirePacket( ZT_SDK_API enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame( ZT_Node *node, void *tptr, - uint64_t now, + int64_t now, uint64_t nwid, uint64_t sourceMac, uint64_t destMac, @@ -1649,7 +1649,7 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame( unsigned int vlanId, const void *frameData, unsigned int frameLength, - volatile uint64_t *nextBackgroundTaskDeadline); + volatile int64_t *nextBackgroundTaskDeadline); /** * Perform periodic background operations @@ -1660,7 +1660,7 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame( * @param nextBackgroundTaskDeadline Value/result: set to deadline for next call to processBackgroundTasks() * @return OK (0) or error code if a fatal error condition has occurred */ -ZT_SDK_API enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,void *tptr,uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline); +ZT_SDK_API enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,void *tptr,int64_t now,volatile int64_t *nextBackgroundTaskDeadline); /** * Join a network diff --git a/node/CertificateOfMembership.hpp b/node/CertificateOfMembership.hpp index 3ffa814f..0105fade 100644 --- a/node/CertificateOfMembership.hpp +++ b/node/CertificateOfMembership.hpp @@ -176,7 +176,7 @@ public: /** * @return Timestamp for this cert and maximum delta for timestamp */ - inline uint64_t timestamp() const + inline int64_t timestamp() const { for(unsigned int i=0;i<_qualifierCount;++i) { if (_qualifiers[i].id == COM_RESERVED_ID_TIMESTAMP) diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 685f2f09..c0409c91 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -169,7 +169,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const Shar // Peers can send this in response to frames if they do not have a recent enough COM from us networkId = at(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD); const SharedPtr network(RR->node->network(networkId)); - const uint64_t now = RR->node->now(); + const int64_t now = RR->node->now(); if ( (network) && (network->config().com) && (peer->rateGateIncomingComRequest(now)) ) network->pushCredentialsNow(tPtr,peer->address(),now); } break; @@ -202,7 +202,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const Shar bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool alreadyAuthenticated) { - const uint64_t now = RR->node->now(); + const int64_t now = RR->node->now(); const uint64_t pid = packetId(); const Address fromAddress(source()); @@ -210,7 +210,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool const unsigned int vMajor = (*this)[ZT_PROTO_VERB_HELLO_IDX_MAJOR_VERSION]; const unsigned int vMinor = (*this)[ZT_PROTO_VERB_HELLO_IDX_MINOR_VERSION]; const unsigned int vRevision = at(ZT_PROTO_VERB_HELLO_IDX_REVISION); - const uint64_t timestamp = at(ZT_PROTO_VERB_HELLO_IDX_TIMESTAMP); + const int64_t timestamp = at(ZT_PROTO_VERB_HELLO_IDX_TIMESTAMP); Identity id; unsigned int ptr = ZT_PROTO_VERB_HELLO_IDX_IDENTITY + id.deserialize(*this,ZT_PROTO_VERB_HELLO_IDX_IDENTITY); @@ -725,7 +725,7 @@ bool IncomingPacket::_doECHO(const RuntimeEnvironment *RR,void *tPtr,const Share bool IncomingPacket::_doMULTICAST_LIKE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer) { - const uint64_t now = RR->node->now(); + const int64_t now = RR->node->now(); uint64_t authOnNetwork[256]; // cache for approved network IDs unsigned int authOnNetworkCount = 0; @@ -1082,7 +1082,7 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr, bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer) { - const uint64_t now = RR->node->now(); + const int64_t now = RR->node->now(); // First, subject this to a rate limit if (!peer->rateGatePushDirectPaths(now)) { @@ -1186,7 +1186,7 @@ bool IncomingPacket::_doREMOTE_TRACE(const RuntimeEnvironment *RR,void *tPtr,con void IncomingPacket::_sendErrorNeedCredentials(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer,const uint64_t nwid) { - const uint64_t now = RR->node->now(); + const int64_t now = RR->node->now(); if (peer->rateGateOutgoingComRequest(now)) { Packet outp(source(),RR->identity.address(),Packet::VERB_ERROR); outp.append((uint8_t)verb()); diff --git a/node/IncomingPacket.hpp b/node/IncomingPacket.hpp index 45a0166d..c8f52721 100644 --- a/node/IncomingPacket.hpp +++ b/node/IncomingPacket.hpp @@ -77,7 +77,7 @@ public: * @param now Current time * @throws std::out_of_range Range error processing packet */ - IncomingPacket(const void *data,unsigned int len,const SharedPtr &path,uint64_t now) : + IncomingPacket(const void *data,unsigned int len,const SharedPtr &path,int64_t now) : Packet(data,len), _receiveTime(now), _path(path) @@ -93,7 +93,7 @@ public: * @param now Current time * @throws std::out_of_range Range error processing packet */ - inline void init(const void *data,unsigned int len,const SharedPtr &path,uint64_t now) + inline void init(const void *data,unsigned int len,const SharedPtr &path,int64_t now) { copyFrom(data,len); _receiveTime = now; diff --git a/node/Membership.cpp b/node/Membership.cpp index 17de6554..740f4e68 100644 --- a/node/Membership.cpp +++ b/node/Membership.cpp @@ -51,7 +51,7 @@ Membership::Membership() : resetPushState(); } -void Membership::pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const uint64_t now,const Address &peerAddress,const NetworkConfig &nconf,int localCapabilityIndex,const bool force) +void Membership::pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const int64_t now,const Address &peerAddress,const NetworkConfig &nconf,int localCapabilityIndex,const bool force) { bool sendCom = ( (nconf.com) && ( ((now - _lastPushedCom) >= ZT_CREDENTIAL_PUSH_EVERY) || (force) ) ); @@ -127,13 +127,13 @@ void Membership::pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const u Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const CertificateOfMembership &com) { - const uint64_t newts = com.timestamp(); + const int64_t newts = com.timestamp(); if (newts <= _comRevocationThreshold) { RR->t->credentialRejected(tPtr,com,"revoked"); return ADD_REJECTED; } - const uint64_t oldts = _com.timestamp(); + const int64_t oldts = _com.timestamp(); if (newts < oldts) { RR->t->credentialRejected(tPtr,com,"old"); return ADD_REJECTED; @@ -227,7 +227,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme } } -void Membership::clean(const uint64_t now,const NetworkConfig &nconf) +void Membership::clean(const int64_t now,const NetworkConfig &nconf) { _cleanCredImpl(nconf,_remoteTags); _cleanCredImpl(nconf,_remoteCaps); diff --git a/node/Membership.hpp b/node/Membership.hpp index c6e2b803..5612858a 100644 --- a/node/Membership.hpp +++ b/node/Membership.hpp @@ -80,7 +80,7 @@ public: * @param localCapabilityIndex Index of local capability to include (in nconf.capabilities[]) or -1 if none * @param force If true, send objects regardless of last push time */ - void pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const uint64_t now,const Address &peerAddress,const NetworkConfig &nconf,int localCapabilityIndex,const bool force); + void pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const int64_t now,const Address &peerAddress,const NetworkConfig &nconf,int localCapabilityIndex,const bool force); /** * Check whether we should push MULTICAST_LIKEs to this peer, and update last sent time if true @@ -88,7 +88,7 @@ public: * @param now Current time * @return True if we should update multicasts */ - inline bool multicastLikeGate(const uint64_t now) + inline bool multicastLikeGate(const int64_t now) { if ((now - _lastUpdatedMulticast) >= ZT_MULTICAST_ANNOUNCE_PERIOD) { _lastUpdatedMulticast = now; @@ -110,7 +110,7 @@ public: return nconf.com.agreesWith(_com); } - inline bool recentlyAssociated(const uint64_t now) const + inline bool recentlyAssociated(const int64_t now) const { return ((_com)&&((now - _com.timestamp()) < ZT_PEER_ACTIVITY_TIMEOUT)); } @@ -180,7 +180,7 @@ public: * @param now Current time * @param nconf Current network configuration */ - void clean(const uint64_t now,const NetworkConfig &nconf); + void clean(const int64_t now,const NetworkConfig &nconf); /** * Reset last pushed time for local credentials @@ -223,13 +223,13 @@ private: } // Last time we pushed MULTICAST_LIKE(s) - uint64_t _lastUpdatedMulticast; + int64_t _lastUpdatedMulticast; // Last time we pushed our COM to this peer - uint64_t _lastPushedCom; + int64_t _lastPushedCom; // Revocation threshold for COM or 0 if none - uint64_t _comRevocationThreshold; + int64_t _comRevocationThreshold; // Remote member's latest network COM CertificateOfMembership _com; diff --git a/node/Multicaster.cpp b/node/Multicaster.cpp index e8c8613a..fa6f7bd1 100644 --- a/node/Multicaster.cpp +++ b/node/Multicaster.cpp @@ -51,7 +51,7 @@ Multicaster::~Multicaster() { } -void Multicaster::addMultiple(void *tPtr,uint64_t now,uint64_t nwid,const MulticastGroup &mg,const void *addresses,unsigned int count,unsigned int totalKnown) +void Multicaster::addMultiple(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup &mg,const void *addresses,unsigned int count,unsigned int totalKnown) { const unsigned char *p = (const unsigned char *)addresses; const unsigned char *e = p + (5 * count); @@ -160,7 +160,7 @@ std::vector
Multicaster::getMembers(uint64_t nwid,const MulticastGroup void Multicaster::send( void *tPtr, unsigned int limit, - uint64_t now, + int64_t now, uint64_t nwid, bool disableCompression, const std::vector
&alwaysSendTo, @@ -309,7 +309,7 @@ void Multicaster::send( delete [] indexes; } -void Multicaster::clean(uint64_t now) +void Multicaster::clean(int64_t now) { { Mutex::Lock _l(_groups_m); @@ -367,7 +367,7 @@ void Multicaster::addCredential(void *tPtr,const CertificateOfMembership &com,bo } } -void Multicaster::_add(void *tPtr,uint64_t now,uint64_t nwid,const MulticastGroup &mg,MulticastGroupStatus &gs,const Address &member) +void Multicaster::_add(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup &mg,MulticastGroupStatus &gs,const Address &member) { // assumes _groups_m is locked diff --git a/node/Multicaster.hpp b/node/Multicaster.hpp index 69a6645d..08c96485 100644 --- a/node/Multicaster.hpp +++ b/node/Multicaster.hpp @@ -98,7 +98,7 @@ public: * @param mg Multicast group * @param member New member address */ - inline void add(void *tPtr,uint64_t now,uint64_t nwid,const MulticastGroup &mg,const Address &member) + inline void add(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup &mg,const Address &member) { Mutex::Lock _l(_groups_m); _add(tPtr,now,nwid,mg,_groups[Multicaster::Key(nwid,mg)],member); @@ -117,7 +117,7 @@ public: * @param count Number of addresses * @param totalKnown Total number of known addresses as reported by peer */ - void addMultiple(void *tPtr,uint64_t now,uint64_t nwid,const MulticastGroup &mg,const void *addresses,unsigned int count,unsigned int totalKnown); + void addMultiple(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup &mg,const void *addresses,unsigned int count,unsigned int totalKnown); /** * Remove a multicast group member (if present) @@ -174,7 +174,7 @@ public: void send( void *tPtr, unsigned int limit, - uint64_t now, + int64_t now, uint64_t nwid, bool disableCompression, const std::vector
&alwaysSendTo, @@ -190,7 +190,7 @@ public: * @param RR Runtime environment * @param now Current time */ - void clean(uint64_t now); + void clean(int64_t now); /** * Add an authorization credential @@ -212,7 +212,7 @@ public: * @param now Current time * @return True if GATHER and LIKE should be allowed */ - bool cacheAuthorized(const Address &a,const uint64_t nwid,const uint64_t now) const + bool cacheAuthorized(const Address &a,const uint64_t nwid,const int64_t now) const { Mutex::Lock _l(_gatherAuth_m); const uint64_t *p = _gatherAuth.get(_GatherAuthKey(nwid,a)); @@ -220,7 +220,7 @@ public: } private: - void _add(void *tPtr,uint64_t now,uint64_t nwid,const MulticastGroup &mg,MulticastGroupStatus &gs,const Address &member); + void _add(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup &mg,MulticastGroupStatus &gs,const Address &member); const RuntimeEnvironment *RR; diff --git a/node/Network.cpp b/node/Network.cpp index 16155c33..111e4736 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -592,7 +592,7 @@ bool Network::filterOutgoingPacket( const unsigned int etherType, const unsigned int vlanId) { - const uint64_t now = RR->node->now(); + const int64_t now = RR->node->now(); Address ztFinalDest(ztDest); int localCapabilityIndex = -1; int accept = 0; @@ -1164,7 +1164,7 @@ void Network::requestConfiguration(void *tPtr) bool Network::gate(void *tPtr,const SharedPtr &peer) { - const uint64_t now = RR->node->now(); + const int64_t now = RR->node->now(); Mutex::Lock _l(_lock); try { if (_config) { @@ -1192,7 +1192,7 @@ bool Network::recentlyAssociatedWith(const Address &addr) void Network::clean() { - const uint64_t now = RR->node->now(); + const int64_t now = RR->node->now(); Mutex::Lock _l(_lock); if (_destroyed) @@ -1257,7 +1257,7 @@ void Network::learnBridgeRoute(const MAC &mac,const Address &addr) } } -void Network::learnBridgedMulticastGroup(void *tPtr,const MulticastGroup &mg,uint64_t now) +void Network::learnBridgedMulticastGroup(void *tPtr,const MulticastGroup &mg,int64_t now) { Mutex::Lock _l(_lock); const unsigned long tmp = (unsigned long)_multicastGroupsBehindMe.size(); @@ -1377,7 +1377,7 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const void Network::_sendUpdatesToMembers(void *tPtr,const MulticastGroup *const newMulticastGroup) { // Assumes _lock is locked - const uint64_t now = RR->node->now(); + const int64_t now = RR->node->now(); std::vector groups; if (newMulticastGroup) diff --git a/node/Network.hpp b/node/Network.hpp index d4d217f2..1b4da7d2 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -305,7 +305,7 @@ public: * @param mg Multicast group * @param now Current time */ - void learnBridgedMulticastGroup(void *tPtr,const MulticastGroup &mg,uint64_t now); + void learnBridgedMulticastGroup(void *tPtr,const MulticastGroup &mg,int64_t now); /** * Validate a credential and learn it if it passes certificate and other checks @@ -357,7 +357,7 @@ public: * @param to Destination peer address * @param now Current time */ - inline void pushCredentialsNow(void *tPtr,const Address &to,const uint64_t now) + 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,true); diff --git a/node/Node.cpp b/node/Node.cpp index cc076e4d..31ee8f19 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -54,7 +54,7 @@ namespace ZeroTier { /* Public Node interface (C++, exposed via CAPI bindings) */ /****************************************************************************/ -Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now) : +Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64_t now) : _RR(this), RR(&_RR), _uPtr(uptr), @@ -139,12 +139,12 @@ Node::~Node() ZT_ResultCode Node::processWirePacket( void *tptr, - uint64_t now, + int64_t now, int64_t localSocket, const struct sockaddr_storage *remoteAddress, const void *packetData, unsigned int packetLength, - volatile uint64_t *nextBackgroundTaskDeadline) + volatile int64_t *nextBackgroundTaskDeadline) { _now = now; RR->sw->onRemotePacket(tptr,localSocket,*(reinterpret_cast(remoteAddress)),packetData,packetLength); @@ -153,7 +153,7 @@ ZT_ResultCode Node::processWirePacket( ZT_ResultCode Node::processVirtualNetworkFrame( void *tptr, - uint64_t now, + int64_t now, uint64_t nwid, uint64_t sourceMac, uint64_t destMac, @@ -161,7 +161,7 @@ ZT_ResultCode Node::processVirtualNetworkFrame( unsigned int vlanId, const void *frameData, unsigned int frameLength, - volatile uint64_t *nextBackgroundTaskDeadline) + volatile int64_t *nextBackgroundTaskDeadline) { _now = now; SharedPtr nw(this->network(nwid)); @@ -175,7 +175,7 @@ ZT_ResultCode Node::processVirtualNetworkFrame( class _PingPeersThatNeedPing { public: - _PingPeersThatNeedPing(const RuntimeEnvironment *renv,void *tPtr,Hashtable< Address,std::vector > &upstreamsToContact,uint64_t now) : + _PingPeersThatNeedPing(const RuntimeEnvironment *renv,void *tPtr,Hashtable< Address,std::vector > &upstreamsToContact,int64_t now) : lastReceiveFromUpstream(0), RR(renv), _tPtr(tPtr), @@ -185,7 +185,7 @@ public: { } - uint64_t lastReceiveFromUpstream; // tracks last time we got a packet from an 'upstream' peer like a root or a relay + int64_t lastReceiveFromUpstream; // tracks last time we got a packet from an 'upstream' peer like a root or a relay inline void operator()(Topology &t,const SharedPtr &p) { @@ -234,17 +234,17 @@ private: const RuntimeEnvironment *RR; void *_tPtr; Hashtable< Address,std::vector > &_upstreamsToContact; - const uint64_t _now; + const int64_t _now; const SharedPtr _bestCurrentUpstream; }; -ZT_ResultCode Node::processBackgroundTasks(void *tptr,uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline) +ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64_t *nextBackgroundTaskDeadline) { _now = now; Mutex::Lock bl(_backgroundTasksLock); unsigned long timeUntilNextPingCheck = ZT_PING_CHECK_INVERVAL; - const uint64_t timeSinceLastPingCheck = now - _lastPingCheck; + const int64_t timeSinceLastPingCheck = now - _lastPingCheck; if (timeSinceLastPingCheck >= ZT_PING_CHECK_INVERVAL) { try { _lastPingCheck = now; @@ -305,7 +305,7 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,uint64_t now,volatile uint } try { - *nextBackgroundTaskDeadline = now + (uint64_t)std::max(std::min(timeUntilNextPingCheck,RR->sw->doTimerTasks(tptr,now)),(unsigned long)ZT_CORE_TIMER_TASK_GRANULARITY); + *nextBackgroundTaskDeadline = now + (int64_t)std::max(std::min(timeUntilNextPingCheck,RR->sw->doTimerTasks(tptr,now)),(unsigned long)ZT_CORE_TIMER_TASK_GRANULARITY); } catch ( ... ) { return ZT_RESULT_FATAL_ERROR_INTERNAL; } @@ -689,7 +689,7 @@ void Node::ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &des extern "C" { -enum ZT_ResultCode ZT_Node_new(ZT_Node **node,void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now) +enum ZT_ResultCode ZT_Node_new(ZT_Node **node,void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64_t now) { *node = (ZT_Node *)0; try { @@ -714,12 +714,12 @@ void ZT_Node_delete(ZT_Node *node) enum ZT_ResultCode ZT_Node_processWirePacket( ZT_Node *node, void *tptr, - uint64_t now, + int64_t now, int64_t localSocket, const struct sockaddr_storage *remoteAddress, const void *packetData, unsigned int packetLength, - volatile uint64_t *nextBackgroundTaskDeadline) + volatile int64_t *nextBackgroundTaskDeadline) { try { return reinterpret_cast(node)->processWirePacket(tptr,now,localSocket,remoteAddress,packetData,packetLength,nextBackgroundTaskDeadline); @@ -733,7 +733,7 @@ enum ZT_ResultCode ZT_Node_processWirePacket( enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame( ZT_Node *node, void *tptr, - uint64_t now, + int64_t now, uint64_t nwid, uint64_t sourceMac, uint64_t destMac, @@ -741,7 +741,7 @@ enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame( unsigned int vlanId, const void *frameData, unsigned int frameLength, - volatile uint64_t *nextBackgroundTaskDeadline) + volatile int64_t *nextBackgroundTaskDeadline) { try { return reinterpret_cast(node)->processVirtualNetworkFrame(tptr,now,nwid,sourceMac,destMac,etherType,vlanId,frameData,frameLength,nextBackgroundTaskDeadline); @@ -752,7 +752,7 @@ enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame( } } -enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,void *tptr,uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline) +enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,void *tptr,int64_t now,volatile int64_t *nextBackgroundTaskDeadline) { try { return reinterpret_cast(node)->processBackgroundTasks(tptr,now,nextBackgroundTaskDeadline); diff --git a/node/Node.hpp b/node/Node.hpp index 1aa01c9a..ae7976d4 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -64,7 +64,7 @@ class World; class Node : public NetworkController::Sender { public: - Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now); + Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64_t now); virtual ~Node(); // Get rid of alignment warnings on 32-bit Windows and possibly improve performance @@ -77,15 +77,15 @@ public: ZT_ResultCode processWirePacket( void *tptr, - uint64_t now, + int64_t now, int64_t localSocket, const struct sockaddr_storage *remoteAddress, const void *packetData, unsigned int packetLength, - volatile uint64_t *nextBackgroundTaskDeadline); + volatile int64_t *nextBackgroundTaskDeadline); ZT_ResultCode processVirtualNetworkFrame( void *tptr, - uint64_t now, + int64_t now, uint64_t nwid, uint64_t sourceMac, uint64_t destMac, @@ -93,8 +93,8 @@ public: unsigned int vlanId, const void *frameData, unsigned int frameLength, - volatile uint64_t *nextBackgroundTaskDeadline); - ZT_ResultCode processBackgroundTasks(void *tptr,uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline); + volatile int64_t *nextBackgroundTaskDeadline); + ZT_ResultCode processBackgroundTasks(void *tptr,int64_t now,volatile int64_t *nextBackgroundTaskDeadline); ZT_ResultCode join(uint64_t nwid,void *uptr,void *tptr); ZT_ResultCode leave(uint64_t nwid,void **uptr,void *tptr); ZT_ResultCode multicastSubscribe(void *tptr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi); @@ -114,7 +114,7 @@ public: // Internal functions ------------------------------------------------------ - inline uint64_t now() const { return _now; } + inline int64_t now() const { return _now; } inline bool putPacket(void *tPtr,const int64_t localSocket,const InetAddress &addr,const void *data,unsigned int len,unsigned int ttl = 0) { @@ -243,7 +243,7 @@ public: * @param from Source address of packet * @return True if within rate limits */ - inline bool rateGateIdentityVerification(const uint64_t now,const InetAddress &from) + inline bool rateGateIdentityVerification(const int64_t now,const InetAddress &from) { unsigned long iph = from.rateGateHash(); if ((now - _lastIdentityVerification[iph]) >= ZT_IDENTITY_VALIDATION_SOURCE_RATE_LIMIT) { @@ -270,7 +270,7 @@ private: uint32_t _expectingRepliesTo[ZT_EXPECTING_REPLIES_BUCKET_MASK1 + 1][ZT_EXPECTING_REPLIES_BUCKET_MASK2 + 1]; // Time of last identity verification indexed by InetAddress.rateGateHash() -- used in IncomingPacket::_doHELLO() via rateGateIdentityVerification() - uint64_t _lastIdentityVerification[16384]; + int64_t _lastIdentityVerification[16384]; Hashtable< uint64_t,SharedPtr > _networks; Mutex _networks_m; @@ -281,10 +281,10 @@ private: Mutex _backgroundTasksLock; Address _remoteTraceTarget; - uint64_t _now; - uint64_t _lastPingCheck; - uint64_t _lastHousekeepingRun; - volatile uint64_t _prngState[2]; + int64_t _now; + int64_t _lastPingCheck; + int64_t _lastHousekeepingRun; + volatile int64_t _prngState[2]; bool _online; }; diff --git a/node/OutboundMulticast.hpp b/node/OutboundMulticast.hpp index 486b66ff..2f6d8338 100644 --- a/node/OutboundMulticast.hpp +++ b/node/OutboundMulticast.hpp @@ -96,7 +96,7 @@ public: * @param now Current time * @return True if this multicast is expired (has exceeded transmit timeout) */ - inline bool expired(uint64_t now) const { return ((now - _timestamp) >= ZT_MULTICAST_TRANSMIT_TIMEOUT); } + inline bool expired(int64_t now) const { return ((now - _timestamp) >= ZT_MULTICAST_TRANSMIT_TIMEOUT); } /** * @return True if this outbound multicast has been sent to enough peers diff --git a/node/Path.cpp b/node/Path.cpp index 9dc9aba5..ca366e39 100644 --- a/node/Path.cpp +++ b/node/Path.cpp @@ -30,7 +30,7 @@ namespace ZeroTier { -bool Path::send(const RuntimeEnvironment *RR,void *tPtr,const void *data,unsigned int len,uint64_t now) +bool Path::send(const RuntimeEnvironment *RR,void *tPtr,const void *data,unsigned int len,int64_t now) { if (RR->node->putPacket(tPtr,_localSocket,_addr,data,len)) { _lastOut = now; diff --git a/node/Path.hpp b/node/Path.hpp index ac8e4c0e..050fb6e2 100644 --- a/node/Path.hpp +++ b/node/Path.hpp @@ -179,14 +179,14 @@ public: * @param now Current time * @return True if transport reported success */ - bool send(const RuntimeEnvironment *RR,void *tPtr,const void *data,unsigned int len,uint64_t now); + bool send(const RuntimeEnvironment *RR,void *tPtr,const void *data,unsigned int len,int64_t now); /** * Manually update last sent time * * @param t Time of send */ - inline void sent(const uint64_t t) { _lastOut = t; } + inline void sent(const int64_t t) { _lastOut = t; } /** * @return Local socket as specified by external code @@ -206,7 +206,7 @@ public: /** * @return True if path has received a trust established packet (e.g. common network membership) in the past ZT_TRUST_EXPIRATION ms */ - inline bool trustEstablished(const uint64_t now) const { return ((now - _lastTrustEstablishedPacketReceived) < ZT_TRUST_EXPIRATION); } + inline bool trustEstablished(const int64_t now) const { return ((now - _lastTrustEstablishedPacketReceived) < ZT_TRUST_EXPIRATION); } /** * @return Preference rank, higher == better @@ -261,27 +261,27 @@ public: /** * @return True if path appears alive */ - inline bool alive(const uint64_t now) const { return ((now - _lastIn) <= ZT_PATH_ALIVE_TIMEOUT); } + inline bool alive(const int64_t now) const { return ((now - _lastIn) <= ZT_PATH_ALIVE_TIMEOUT); } /** * @return True if this path needs a heartbeat */ - inline bool needsHeartbeat(const uint64_t now) const { return ((now - _lastOut) >= ZT_PATH_HEARTBEAT_PERIOD); } + inline bool needsHeartbeat(const int64_t now) const { return ((now - _lastOut) >= ZT_PATH_HEARTBEAT_PERIOD); } /** * @return Last time we sent something */ - inline uint64_t lastOut() const { return _lastOut; } + inline int64_t lastOut() const { return _lastOut; } /** * @return Last time we received anything */ - inline uint64_t lastIn() const { return _lastIn; } + inline int64_t lastIn() const { return _lastIn; } /** * @return Time last trust-established packet was received */ - inline uint64_t lastTrustEstablishedPacketReceived() const { return _lastTrustEstablishedPacketReceived; } + inline int64_t lastTrustEstablishedPacketReceived() const { return _lastTrustEstablishedPacketReceived; } /** * Return and increment outgoing packet counter (used with Packet::armor()) @@ -291,9 +291,9 @@ public: inline unsigned int nextOutgoingCounter() { return _outgoingPacketCounter++; } private: - volatile uint64_t _lastOut; - volatile uint64_t _lastIn; - volatile uint64_t _lastTrustEstablishedPacketReceived; + volatile int64_t _lastOut; + volatile int64_t _lastIn; + volatile int64_t _lastTrustEstablishedPacketReceived; volatile uint64_t _incomingLinkQualityFastLog; int64_t _localSocket; volatile unsigned long _incomingLinkQualitySlowLogPtr; diff --git a/node/Peer.cpp b/node/Peer.cpp index a954b716..60661592 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -34,6 +34,7 @@ #include "SelfAwareness.hpp" #include "Packet.hpp" #include "Trace.hpp" +#include "InetAddress.hpp" namespace ZeroTier { @@ -75,7 +76,7 @@ void Peer::received( const bool trustEstablished, const uint64_t networkId) { - const uint64_t now = RR->node->now(); + const int64_t now = RR->node->now(); /* #ifdef ZT_ENABLE_CLUSTER @@ -263,14 +264,14 @@ void Peer::received( } } -bool Peer::sendDirect(void *tPtr,const void *data,unsigned int len,uint64_t now,bool force) +bool Peer::sendDirect(void *tPtr,const void *data,unsigned int len,int64_t now,bool force) { Mutex::Lock _l(_paths_m); - uint64_t v6lr = 0; + int64_t v6lr = 0; if ( ((now - _v6Path.lr) < ZT_PEER_PATH_EXPIRATION) && (_v6Path.p) ) v6lr = _v6Path.p->lastIn(); - uint64_t v4lr = 0; + int64_t v4lr = 0; if ( ((now - _v4Path.lr) < ZT_PEER_PATH_EXPIRATION) && (_v4Path.p) ) v4lr = _v4Path.p->lastIn(); @@ -289,16 +290,18 @@ bool Peer::sendDirect(void *tPtr,const void *data,unsigned int len,uint64_t now, return false; } -SharedPtr Peer::getBestPath(uint64_t now,bool includeExpired) +SharedPtr Peer::getBestPath(int64_t now,bool includeExpired) { Mutex::Lock _l(_paths_m); - uint64_t v6lr = 0; - if ( ( includeExpired || ((now - _v6Path.lr) < ZT_PEER_PATH_EXPIRATION) ) && (_v6Path.p) ) + int64_t v6lr = 0; + if ((includeExpired || ((now - _v6Path.lr) < ZT_PEER_PATH_EXPIRATION)) && (_v6Path.p)) { v6lr = _v6Path.p->lastIn(); - uint64_t v4lr = 0; - if ( ( includeExpired || ((now - _v4Path.lr) < ZT_PEER_PATH_EXPIRATION) ) && (_v4Path.p) ) + } + int64_t v4lr = 0; + if ((includeExpired || ((now - _v4Path.lr) < ZT_PEER_PATH_EXPIRATION)) && (_v4Path.p)) { v4lr = _v4Path.p->lastIn(); + } if (v6lr > v4lr) { return _v6Path.p; @@ -309,7 +312,7 @@ SharedPtr Peer::getBestPath(uint64_t now,bool includeExpired) return SharedPtr(); } -void Peer::sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,uint64_t now,unsigned int counter) +void Peer::sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,int64_t now,unsigned int counter) { Packet outp(_id.address(),RR->identity.address(),Packet::VERB_HELLO); @@ -357,7 +360,7 @@ void Peer::sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atA } } -void Peer::attemptToContactAt(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,uint64_t now,bool sendFullHello,unsigned int counter) +void Peer::attemptToContactAt(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,int64_t now,bool sendFullHello,unsigned int counter) { if ( (!sendFullHello) && (_vProto >= 5) && (!((_vMajor == 1)&&(_vMinor == 1)&&(_vRevision == 0))) ) { Packet outp(_id.address(),RR->identity.address(),Packet::VERB_ECHO); @@ -369,7 +372,7 @@ void Peer::attemptToContactAt(void *tPtr,const int64_t localSocket,const InetAdd } } -void Peer::tryMemorizedPath(void *tPtr,uint64_t now) +void Peer::tryMemorizedPath(void *tPtr,int64_t now) { if ((now - _lastTriedMemorizedPath) >= ZT_TRY_MEMORIZED_PATH_INTERVAL) { _lastTriedMemorizedPath = now; @@ -379,15 +382,15 @@ void Peer::tryMemorizedPath(void *tPtr,uint64_t now) } } -bool Peer::doPingAndKeepalive(void *tPtr,uint64_t now,int inetAddressFamily) +bool Peer::doPingAndKeepalive(void *tPtr,int64_t now,int inetAddressFamily) { Mutex::Lock _l(_paths_m); if (inetAddressFamily < 0) { - uint64_t v6lr = 0; + int64_t v6lr = 0; if ( ((now - _v6Path.lr) < ZT_PEER_PATH_EXPIRATION) && (_v6Path.p) ) v6lr = _v6Path.p->lastIn(); - uint64_t v4lr = 0; + int64_t v4lr = 0; if ( ((now - _v4Path.lr) < ZT_PEER_PATH_EXPIRATION) && (_v4Path.p) ) v4lr = _v4Path.p->lastIn(); @@ -423,7 +426,7 @@ bool Peer::doPingAndKeepalive(void *tPtr,uint64_t now,int inetAddressFamily) return false; } -void Peer::redirect(void *tPtr,const int64_t localSocket,const InetAddress &remoteAddress,const uint64_t now) +void Peer::redirect(void *tPtr,const int64_t localSocket,const InetAddress &remoteAddress,const int64_t now) { if ((remoteAddress.ss_family != AF_INET)&&(remoteAddress.ss_family != AF_INET6)) // sanity check return; diff --git a/node/Peer.hpp b/node/Peer.hpp index af9163a5..e08f7d36 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -120,7 +120,7 @@ public: * @param addr Remote address * @return True if we have an active path to this destination */ - inline bool hasActivePathTo(uint64_t now,const InetAddress &addr) const + inline bool hasActivePathTo(int64_t now,const InetAddress &addr) const { Mutex::Lock _l(_paths_m); return ( ((addr.ss_family == AF_INET)&&(_v4Path.p)&&(_v4Path.p->address() == addr)&&(_v4Path.p->alive(now))) || ((addr.ss_family == AF_INET6)&&(_v6Path.p)&&(_v6Path.p->address() == addr)&&(_v6Path.p->alive(now))) ); @@ -136,7 +136,7 @@ public: * @param force If true, send even if path is not alive * @return True if we actually sent something */ - bool sendDirect(void *tPtr,const void *data,unsigned int len,uint64_t now,bool force); + bool sendDirect(void *tPtr,const void *data,unsigned int len,int64_t now,bool force); /** * Get the best current direct path @@ -148,7 +148,7 @@ public: * @param includeExpired If true, include even expired paths * @return Best current path or NULL if none */ - SharedPtr getBestPath(uint64_t now,bool includeExpired); + SharedPtr getBestPath(int64_t now,bool includeExpired); /** * Send a HELLO to this peer at a specified physical address @@ -161,7 +161,7 @@ public: * @param now Current time * @param counter Outgoing packet counter */ - void sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,uint64_t now,unsigned int counter); + void sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,int64_t now,unsigned int counter); /** * Send ECHO (or HELLO for older peers) to this peer at the given address @@ -175,7 +175,7 @@ public: * @param sendFullHello If true, always send a full HELLO instead of just an ECHO * @param counter Outgoing packet counter */ - void attemptToContactAt(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,uint64_t now,bool sendFullHello,unsigned int counter); + void attemptToContactAt(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,int64_t now,bool sendFullHello,unsigned int counter); /** * Try a memorized or statically defined path if any are known @@ -185,7 +185,7 @@ public: * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param now Current time */ - void tryMemorizedPath(void *tPtr,uint64_t now); + void tryMemorizedPath(void *tPtr,int64_t now); /** * Send pings or keepalives depending on configured timeouts @@ -195,7 +195,7 @@ public: * @param inetAddressFamily Keep this address family alive, or -1 for any * @return True if we have at least one direct path of the given family (or any if family is -1) */ - bool doPingAndKeepalive(void *tPtr,uint64_t now,int inetAddressFamily); + bool doPingAndKeepalive(void *tPtr,int64_t now,int inetAddressFamily); /** * Specify remote path for this peer and forget others @@ -209,7 +209,7 @@ public: * @param remoteAddress Remote address * @param now Current time */ - void redirect(void *tPtr,const int64_t localSocket,const InetAddress &remoteAddress,const uint64_t now); + void redirect(void *tPtr,const int64_t localSocket,const InetAddress &remoteAddress,const int64_t now); /** * Reset paths within a given IP scope and address family @@ -222,7 +222,7 @@ public: * @param inetAddressFamily Family e.g. AF_INET * @param now Current time */ - inline void resetWithinScope(void *tPtr,InetAddress::IpScope scope,int inetAddressFamily,uint64_t now) + inline void resetWithinScope(void *tPtr,InetAddress::IpScope scope,int inetAddressFamily,int64_t now) { Mutex::Lock _l(_paths_m); if ((inetAddressFamily == AF_INET)&&(_v4Path.lr)&&(_v4Path.p->address().ipScope() == scope)) { @@ -243,7 +243,7 @@ public: * @param v4 Result parameter to receive active IPv4 address, if any * @param v6 Result parameter to receive active IPv6 address, if any */ - inline void getRendezvousAddresses(uint64_t now,InetAddress &v4,InetAddress &v6) const + inline void getRendezvousAddresses(int64_t now,InetAddress &v4,InetAddress &v6) const { Mutex::Lock _l(_paths_m); if (((now - _v4Path.lr) < ZT_PEER_PATH_EXPIRATION)&&(_v4Path.p->alive(now))) @@ -256,7 +256,7 @@ public: * @param now Current time * @return All known paths to this peer */ - inline std::vector< SharedPtr > paths(const uint64_t now) const + inline std::vector< SharedPtr > paths(const int64_t now) const { std::vector< SharedPtr > pp; Mutex::Lock _l(_paths_m); @@ -270,17 +270,17 @@ public: /** * @return Time of last receive of anything, whether direct or relayed */ - inline uint64_t lastReceive() const { return _lastReceive; } + inline int64_t lastReceive() const { return _lastReceive; } /** * @return True if we've heard from this peer in less than ZT_PEER_ACTIVITY_TIMEOUT */ - inline bool isAlive(const uint64_t now) const { return ((now - _lastReceive) < ZT_PEER_ACTIVITY_TIMEOUT); } + inline bool isAlive(const int64_t now) const { return ((now - _lastReceive) < ZT_PEER_ACTIVITY_TIMEOUT); } /** * @return True if this peer has sent us real network traffic recently */ - inline uint64_t isActive(uint64_t now) const { return ((now - _lastNontrivialReceive) < ZT_PEER_ACTIVITY_TIMEOUT); } + inline int64_t isActive(int64_t now) const { return ((now - _lastNontrivialReceive) < ZT_PEER_ACTIVITY_TIMEOUT); } /** * @return Latency in milliseconds or 0 if unknown @@ -298,7 +298,7 @@ public: * * @return Relay quality score computed from latency and other factors, lower is better */ - inline unsigned int relayQuality(const uint64_t now) const + inline unsigned int relayQuality(const int64_t now) const { const uint64_t tsr = now - _lastReceive; if (tsr >= ZT_PEER_ACTIVITY_TIMEOUT) @@ -353,12 +353,12 @@ public: /** * @return True if peer has received a trust established packet (e.g. common network membership) in the past ZT_TRUST_EXPIRATION ms */ - inline bool trustEstablished(const uint64_t now) const { return ((now - _lastTrustEstablishedPacketReceived) < ZT_TRUST_EXPIRATION); } + inline bool trustEstablished(const int64_t now) const { return ((now - _lastTrustEstablishedPacketReceived) < ZT_TRUST_EXPIRATION); } /** * Rate limit gate for VERB_PUSH_DIRECT_PATHS */ - inline bool rateGatePushDirectPaths(const uint64_t now) + inline bool rateGatePushDirectPaths(const int64_t now) { if ((now - _lastDirectPathPushReceive) <= ZT_PUSH_DIRECT_PATHS_CUTOFF_TIME) ++_directPathPushCutoffCount; @@ -370,7 +370,7 @@ public: /** * Rate limit gate for VERB_NETWORK_CREDENTIALS */ - inline bool rateGateCredentialsReceived(const uint64_t now) + inline bool rateGateCredentialsReceived(const int64_t now) { if ((now - _lastCredentialsReceived) <= ZT_PEER_CREDENTIALS_CUTOFF_TIME) ++_credentialsCutoffCount; @@ -382,7 +382,7 @@ public: /** * Rate limit gate for sending of ERROR_NEED_MEMBERSHIP_CERTIFICATE */ - inline bool rateGateRequestCredentials(const uint64_t now) + inline bool rateGateRequestCredentials(const int64_t now) { if ((now - _lastCredentialRequestSent) >= ZT_PEER_GENERAL_RATE_LIMIT) { _lastCredentialRequestSent = now; @@ -394,7 +394,7 @@ public: /** * Rate limit gate for inbound WHOIS requests */ - inline bool rateGateInboundWhoisRequest(const uint64_t now) + inline bool rateGateInboundWhoisRequest(const int64_t now) { if ((now - _lastWhoisRequestReceived) >= ZT_PEER_WHOIS_RATE_LIMIT) { _lastWhoisRequestReceived = now; @@ -406,7 +406,7 @@ public: /** * Rate limit gate for inbound ECHO requests */ - inline bool rateGateEchoRequest(const uint64_t now) + inline bool rateGateEchoRequest(const int64_t now) { if ((now - _lastEchoRequestReceived) >= ZT_PEER_GENERAL_RATE_LIMIT) { _lastEchoRequestReceived = now; @@ -418,7 +418,7 @@ public: /** * Rate gate incoming requests for network COM */ - inline bool rateGateIncomingComRequest(const uint64_t now) + inline bool rateGateIncomingComRequest(const int64_t now) { if ((now - _lastComRequestReceived) >= ZT_PEER_GENERAL_RATE_LIMIT) { _lastComRequestReceived = now; @@ -430,7 +430,7 @@ public: /** * Rate gate outgoing requests for network COM */ - inline bool rateGateOutgoingComRequest(const uint64_t now) + inline bool rateGateOutgoingComRequest(const int64_t now) { if ((now - _lastComRequestSent) >= ZT_PEER_GENERAL_RATE_LIMIT) { _lastComRequestSent = now; @@ -484,7 +484,7 @@ public: } template - inline static SharedPtr deserializeFromCache(uint64_t now,void *tPtr,Buffer &b,const RuntimeEnvironment *renv) + inline static SharedPtr deserializeFromCache(int64_t now,void *tPtr,Buffer &b,const RuntimeEnvironment *renv) { try { unsigned int ptr = 0; @@ -527,8 +527,8 @@ private: struct _PeerPath { _PeerPath() : lr(0),sticky(0),p() {} - uint64_t lr; // time of last valid ZeroTier packet - uint64_t sticky; // time last set as sticky + int64_t lr; // time of last valid ZeroTier packet + int64_t sticky; // time last set as sticky SharedPtr p; }; @@ -536,18 +536,18 @@ private: const RuntimeEnvironment *RR; - uint64_t _lastReceive; // direct or indirect - uint64_t _lastNontrivialReceive; // frames, things like netconf, etc. - uint64_t _lastTriedMemorizedPath; - uint64_t _lastDirectPathPushSent; - uint64_t _lastDirectPathPushReceive; - uint64_t _lastCredentialRequestSent; - uint64_t _lastWhoisRequestReceived; - uint64_t _lastEchoRequestReceived; - uint64_t _lastComRequestReceived; - uint64_t _lastComRequestSent; - uint64_t _lastCredentialsReceived; - uint64_t _lastTrustEstablishedPacketReceived; + int64_t _lastReceive; // direct or indirect + int64_t _lastNontrivialReceive; // frames, things like netconf, etc. + int64_t _lastTriedMemorizedPath; + int64_t _lastDirectPathPushSent; + int64_t _lastDirectPathPushReceive; + int64_t _lastCredentialRequestSent; + int64_t _lastWhoisRequestReceived; + int64_t _lastEchoRequestReceived; + int64_t _lastComRequestReceived; + int64_t _lastComRequestSent; + int64_t _lastCredentialsReceived; + int64_t _lastTrustEstablishedPacketReceived; uint16_t _vProto; uint16_t _vMajor; diff --git a/node/Revocation.hpp b/node/Revocation.hpp index a28da0ab..7f7498bb 100644 --- a/node/Revocation.hpp +++ b/node/Revocation.hpp @@ -85,7 +85,7 @@ public: inline uint32_t id() const { return _id; } inline uint32_t credentialId() const { return _credentialId; } inline uint64_t networkId() const { return _networkId; } - inline uint64_t threshold() const { return _threshold; } + inline int64_t threshold() const { return _threshold; } inline const Address &target() const { return _target; } inline const Address &signer() const { return _signedBy; } inline Credential::Type type() const { return _type; } @@ -184,7 +184,7 @@ private: uint32_t _id; uint32_t _credentialId; uint64_t _networkId; - uint64_t _threshold; + int64_t _threshold; uint64_t _flags; Address _target; Address _signedBy; diff --git a/node/SelfAwareness.cpp b/node/SelfAwareness.cpp index 0af0d691..83cd89c9 100644 --- a/node/SelfAwareness.cpp +++ b/node/SelfAwareness.cpp @@ -49,7 +49,7 @@ namespace ZeroTier { class _ResetWithinScope { public: - _ResetWithinScope(void *tPtr,uint64_t now,int inetAddressFamily,InetAddress::IpScope scope) : + _ResetWithinScope(void *tPtr,int64_t now,int inetAddressFamily,InetAddress::IpScope scope) : _now(now), _tPtr(tPtr), _family(inetAddressFamily), @@ -70,7 +70,7 @@ SelfAwareness::SelfAwareness(const RuntimeEnvironment *renv) : { } -void SelfAwareness::iam(void *tPtr,const Address &reporter,const int64_t receivedOnLocalSocket,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,uint64_t now) +void SelfAwareness::iam(void *tPtr,const Address &reporter,const int64_t receivedOnLocalSocket,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,int64_t now) { const InetAddress::IpScope scope = myPhysicalAddress.ipScope(); @@ -112,7 +112,7 @@ void SelfAwareness::iam(void *tPtr,const Address &reporter,const int64_t receive } } -void SelfAwareness::clean(uint64_t now) +void SelfAwareness::clean(int64_t now) { Mutex::Lock _l(_phy_m); Hashtable< PhySurfaceKey,PhySurfaceEntry >::Iterator i(_phy); diff --git a/node/SelfAwareness.hpp b/node/SelfAwareness.hpp index 35e0ad39..7ddba465 100644 --- a/node/SelfAwareness.hpp +++ b/node/SelfAwareness.hpp @@ -55,14 +55,14 @@ public: * @param trusted True if this peer is trusted as an authority to inform us of external address changes * @param now Current time */ - void iam(void *tPtr,const Address &reporter,const int64_t receivedOnLocalSocket,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,uint64_t now); + void iam(void *tPtr,const Address &reporter,const int64_t receivedOnLocalSocket,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,int64_t now); /** * Clean up database periodically * * @param now Current time */ - void clean(uint64_t now); + void clean(int64_t now); /** * If we appear to be behind a symmetric NAT, get predictions for possible external endpoints diff --git a/node/Switch.cpp b/node/Switch.cpp index f46b3e73..cc022b6b 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -57,7 +57,7 @@ Switch::Switch(const RuntimeEnvironment *renv) : void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddress &fromAddr,const void *data,unsigned int len) { try { - const uint64_t now = RR->node->now(); + const int64_t now = RR->node->now(); const SharedPtr path(RR->topology->getPath(localSocket,fromAddr)); path->received(now); @@ -557,14 +557,14 @@ void Switch::send(void *tPtr,Packet &packet,bool encrypt) } } -void Switch::requestWhois(void *tPtr,const uint64_t now,const Address &addr) +void Switch::requestWhois(void *tPtr,const int64_t now,const Address &addr) { if (addr == RR->identity.address()) return; { Mutex::Lock _l(_lastSentWhoisRequest_m); - uint64_t &last = _lastSentWhoisRequest[addr]; + int64_t &last = _lastSentWhoisRequest[addr]; if ((now - last) < ZT_WHOIS_RETRY_DELAY) return; else last = now; @@ -586,7 +586,7 @@ void Switch::doAnythingWaitingForPeer(void *tPtr,const SharedPtr &peer) _lastSentWhoisRequest.erase(peer->address()); } - const uint64_t now = RR->node->now(); + const int64_t now = RR->node->now(); for(unsigned int ptr=0;ptrtimestamp)&&(rq->complete)) { @@ -611,7 +611,7 @@ void Switch::doAnythingWaitingForPeer(void *tPtr,const SharedPtr &peer) } } -unsigned long Switch::doTimerTasks(void *tPtr,uint64_t now) +unsigned long Switch::doTimerTasks(void *tPtr,int64_t now) { const uint64_t timeSinceLastCheck = now - _lastCheckedQueues; if (timeSinceLastCheck < ZT_WHOIS_RETRY_DELAY) @@ -663,9 +663,9 @@ unsigned long Switch::doTimerTasks(void *tPtr,uint64_t now) { Mutex::Lock _l(_lastSentWhoisRequest_m); - Hashtable< Address,uint64_t >::Iterator i(_lastSentWhoisRequest); + Hashtable< Address,int64_t >::Iterator i(_lastSentWhoisRequest); Address *a = (Address *)0; - uint64_t *ts = (uint64_t *)0; + int64_t *ts = (int64_t *)0; while (i.next(a,ts)) { if ((now - *ts) > (ZT_WHOIS_RETRY_DELAY * 2)) _lastSentWhoisRequest.erase(*a); @@ -675,7 +675,7 @@ unsigned long Switch::doTimerTasks(void *tPtr,uint64_t now) return ZT_WHOIS_RETRY_DELAY; } -bool Switch::_shouldUnite(const uint64_t now,const Address &source,const Address &destination) +bool Switch::_shouldUnite(const int64_t now,const Address &source,const Address &destination) { Mutex::Lock _l(_lastUniteAttempt_m); uint64_t &ts = _lastUniteAttempt[_LastUniteKey(source,destination)]; @@ -689,7 +689,7 @@ bool Switch::_shouldUnite(const uint64_t now,const Address &source,const Address bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt) { SharedPtr viaPath; - const uint64_t now = RR->node->now(); + const int64_t now = RR->node->now(); const Address destination(packet.destination()); const SharedPtr peer(RR->topology->getPeer(tPtr,destination)); @@ -703,7 +703,7 @@ bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt) viaPath = peer->getBestPath(now,false); if ( (viaPath) && (!viaPath->alive(now)) && (!RR->topology->isUpstream(peer->identity())) ) { - if ((now - viaPath->lastOut()) > std::max((now - viaPath->lastIn()) * 4,(uint64_t)ZT_PATH_MIN_REACTIVATE_INTERVAL)) { + if ((now - viaPath->lastOut()) > std::max((now - viaPath->lastIn()) * 4,(int64_t)ZT_PATH_MIN_REACTIVATE_INTERVAL)) { peer->attemptToContactAt(tPtr,viaPath->localSocket(),viaPath->address(),now,false,viaPath->nextOutgoingCounter()); viaPath->sent(now); } diff --git a/node/Switch.hpp b/node/Switch.hpp index c258a255..b42389fc 100644 --- a/node/Switch.hpp +++ b/node/Switch.hpp @@ -114,7 +114,7 @@ public: * @param now Current time * @param addr Address to look up */ - void requestWhois(void *tPtr,const uint64_t now,const Address &addr); + void requestWhois(void *tPtr,const int64_t now,const Address &addr); /** * Run any processes that are waiting for this peer's identity @@ -136,25 +136,25 @@ public: * @param now Current time * @return Number of milliseconds until doTimerTasks() should be run again */ - unsigned long doTimerTasks(void *tPtr,uint64_t now); + unsigned long doTimerTasks(void *tPtr,int64_t now); private: - bool _shouldUnite(const uint64_t now,const Address &source,const Address &destination); + bool _shouldUnite(const int64_t now,const Address &source,const Address &destination); bool _trySend(void *tPtr,Packet &packet,bool encrypt); // packet is modified if return is true const RuntimeEnvironment *const RR; - uint64_t _lastBeaconResponse; - volatile uint64_t _lastCheckedQueues; + int64_t _lastBeaconResponse; + volatile int64_t _lastCheckedQueues; // Time we last sent a WHOIS request for each address - Hashtable< Address,uint64_t > _lastSentWhoisRequest; + Hashtable< Address,int64_t > _lastSentWhoisRequest; Mutex _lastSentWhoisRequest_m; // Packets waiting for WHOIS replies or other decode info or missing fragments struct RXQueueEntry { RXQueueEntry() : timestamp(0) {} - volatile uint64_t timestamp; // 0 if entry is not in use + volatile int64_t timestamp; // 0 if entry is not in use volatile uint64_t packetId; IncomingPacket frag0; // head of packet Packet::Fragment frags[ZT_MAX_PACKET_FRAGMENTS - 1]; // later fragments (if any) diff --git a/node/Topology.cpp b/node/Topology.cpp index 8a830b93..f884e9c3 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -133,8 +133,9 @@ SharedPtr Topology::getPeer(void *tPtr,const Address &zta) if (ap) return ap; ap = Peer::deserializeFromCache(RR->node->now(),tPtr,buf,RR); - if (!ap) + if (!ap) { _peers.erase(zta); + } return SharedPtr(); } } catch ( ... ) {} // ignore invalid identities or other strage failures @@ -157,7 +158,7 @@ Identity Topology::getIdentity(void *tPtr,const Address &zta) SharedPtr Topology::getUpstreamPeer() { - const uint64_t now = RR->node->now(); + const int64_t now = RR->node->now(); unsigned int bestq = ~((unsigned int)0); const SharedPtr *best = (const SharedPtr *)0; @@ -365,7 +366,7 @@ void Topology::removeMoon(void *tPtr,const uint64_t id) _memoizeUpstreams(tPtr); } -void Topology::doPeriodicTasks(void *tPtr,uint64_t now) +void Topology::doPeriodicTasks(void *tPtr,int64_t now) { { Mutex::Lock _l1(_peers_m); diff --git a/node/Topology.hpp b/node/Topology.hpp index 34df28a1..c3a218e3 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -286,13 +286,13 @@ public: /** * Clean and flush database */ - void doPeriodicTasks(void *tPtr,uint64_t now); + void doPeriodicTasks(void *tPtr,int64_t now); /** * @param now Current time * @return Number of peers with active direct paths */ - inline unsigned long countActive(uint64_t now) const + inline unsigned long countActive(int64_t now) const { unsigned long cnt = 0; Mutex::Lock _l(_peers_m); diff --git a/one.cpp b/one.cpp index b1a19e8c..de16cc2d 100644 --- a/one.cpp +++ b/one.cpp @@ -364,9 +364,9 @@ static int cli(int argc,char **argv) if (path["preferred"]) { char tmp[256]; std::string addr = path["address"]; - const uint64_t now = OSUtils::now(); + const int64_t now = OSUtils::now(); const double lq = (path.count("linkQuality")) ? (double)path["linkQuality"] : -1.0; - OSUtils::ztsnprintf(tmp,sizeof(tmp),"%s;%llu;%llu;%1.2f",addr.c_str(),now - (uint64_t)path["lastSend"],now - (uint64_t)path["lastReceive"],lq); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%s;%lld;%lld;%1.2f",addr.c_str(),now - (int64_t)path["lastSend"],now - (int64_t)path["lastReceive"],lq); bestPath = tmp; break; } @@ -864,7 +864,7 @@ static int idtool(int argc,char **argv) } std::sort(roots.begin(),roots.end()); - const uint64_t now = OSUtils::now(); + const int64_t now = OSUtils::now(); World w(World::make(t,id,now,updatesMustBeSignedBy,roots,signingKey)); Buffer wbuf; w.serialize(wbuf); diff --git a/osdep/OSUtils.hpp b/osdep/OSUtils.hpp index 8683ba25..8f66f850 100644 --- a/osdep/OSUtils.hpp +++ b/osdep/OSUtils.hpp @@ -200,7 +200,7 @@ public: /** * @return Current time in milliseconds since epoch */ - static inline uint64_t now() + static inline int64_t now() { #ifdef __WINDOWS__ FILETIME ft; @@ -210,7 +210,7 @@ public: SystemTimeToFileTime(&st,&ft); tmp.LowPart = ft.dwLowDateTime; tmp.HighPart = ft.dwHighDateTime; - return ( ((tmp.QuadPart - 116444736000000000ULL) / 10000L) + st.wMilliseconds ); + return (int64_t)( ((tmp.QuadPart - 116444736000000000LL) / 10000L) + st.wMilliseconds ); #else struct timeval tv; #ifdef __LINUX__ @@ -218,7 +218,7 @@ public: #else gettimeofday(&tv,(struct timezone *)0); #endif - return ( (1000ULL * (uint64_t)tv.tv_sec) + (uint64_t)(tv.tv_usec / 1000) ); + return ( (1000LL * (int64_t)tv.tv_sec) + (int64_t)(tv.tv_usec / 1000) ); #endif }; diff --git a/osdep/PortMapper.cpp b/osdep/PortMapper.cpp index 0da00653..825972b0 100644 --- a/osdep/PortMapper.cpp +++ b/osdep/PortMapper.cpp @@ -131,7 +131,7 @@ public: InetAddress publicAddress; sendpublicaddressrequest(&natpmp); - uint64_t myTimeout = OSUtils::now() + 5000; + int64_t myTimeout = OSUtils::now() + 5000; do { fd_set fds; struct timeval timeout; diff --git a/service/OneService.cpp b/service/OneService.cpp index 66e9a9c8..fb185ee7 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -276,6 +276,10 @@ static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer) pa.push_back(j); } pj["paths"] = pa; + + if (peer->address == 0xda6c71a1ad) { + fprintf(stdout, "%s\n", pj.dump(2).c_str()); + } } static void _moonToJson(nlohmann::json &mj,const World &world) @@ -436,7 +440,7 @@ public: uint64_t _lastRestart; // Deadline for the next background task service function - volatile uint64_t _nextBackgroundTaskDeadline; + volatile int64_t _nextBackgroundTaskDeadline; // Configured networks struct NetworkState @@ -755,12 +759,12 @@ public: // Main I/O loop _nextBackgroundTaskDeadline = 0; - uint64_t clockShouldBe = OSUtils::now(); + int64_t clockShouldBe = OSUtils::now(); _lastRestart = clockShouldBe; - uint64_t lastTapMulticastGroupCheck = 0; - uint64_t lastBindRefresh = 0; - uint64_t lastUpdateCheck = clockShouldBe; - uint64_t lastLocalInterfaceAddressCheck = (clockShouldBe - ZT_LOCAL_INTERFACE_CHECK_INTERVAL) + 15000; // do this in 15s to give portmapper time to configure and other things time to settle + int64_t lastTapMulticastGroupCheck = 0; + int64_t lastBindRefresh = 0; + int64_t lastUpdateCheck = clockShouldBe; + int64_t lastLocalInterfaceAddressCheck = (clockShouldBe - ZT_LOCAL_INTERFACE_CHECK_INTERVAL) + 15000; // do this in 15s to give portmapper time to configure and other things time to settle for(;;) { _run_m.lock(); if (!_run) { @@ -773,7 +777,7 @@ public: _run_m.unlock(); } - const uint64_t now = OSUtils::now(); + const int64_t now = OSUtils::now(); // Attempt to detect sleep/wake events by detecting delay overruns bool restarted = false; @@ -809,7 +813,7 @@ public: } // Run background task processor in core if it's time to do so - uint64_t dl = _nextBackgroundTaskDeadline; + int64_t dl = _nextBackgroundTaskDeadline; if (dl <= now) { _node->processBackgroundTasks((void *)0,now,&_nextBackgroundTaskDeadline); dl = _nextBackgroundTaskDeadline; @@ -2152,7 +2156,7 @@ public: // Engage TCP tunnel fallback if we haven't received anything valid from a global // IP address in ZT_TCP_FALLBACK_AFTER milliseconds. If we do start getting // valid direct traffic we'll stop using it and close the socket after a while. - const uint64_t now = OSUtils::now(); + const int64_t now = OSUtils::now(); if (((now - _lastDirectReceiveFromGlobal) > ZT_TCP_FALLBACK_AFTER)&&((now - _lastRestart) > ZT_TCP_FALLBACK_AFTER)) { if (_tcpFallbackTunnel) { bool flushNow = false; diff --git a/service/SoftwareUpdater.cpp b/service/SoftwareUpdater.cpp index 11005945..39833c90 100644 --- a/service/SoftwareUpdater.cpp +++ b/service/SoftwareUpdater.cpp @@ -303,7 +303,7 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void } } -bool SoftwareUpdater::check(const uint64_t now) +bool SoftwareUpdater::check(const int64_t now) { if ((now - _lastCheckTime) >= ZT_SOFTWARE_UPDATE_CHECK_PERIOD) { _lastCheckTime = now; diff --git a/service/SoftwareUpdater.hpp b/service/SoftwareUpdater.hpp index ff3e36df..f16c99a0 100644 --- a/service/SoftwareUpdater.hpp +++ b/service/SoftwareUpdater.hpp @@ -167,7 +167,7 @@ public: * * @return True if we've downloaded and verified an update */ - bool check(const uint64_t now); + bool check(const int64_t now); /** * @return Meta-data for downloaded update or NULL if none -- cgit v1.2.3 From 4177a115229fe9c3548f9df38d75a5dfdcaa754c Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Wed, 4 Oct 2017 09:18:13 -0700 Subject: remove some leftover debug code --- service/OneService.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index fb185ee7..9ab78385 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -276,10 +276,6 @@ static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer) pa.push_back(j); } pj["paths"] = pa; - - if (peer->address == 0xda6c71a1ad) { - fprintf(stdout, "%s\n", pj.dump(2).c_str()); - } } static void _moonToJson(nlohmann::json &mj,const World &world) -- cgit v1.2.3 From ceeb35eaac083c1557691f7b814a0bf1af587883 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Thu, 5 Oct 2017 13:19:25 -0700 Subject: If lastSend/lastReceive is < 0, just put 0. --- service/OneService.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 9ab78385..f366efd4 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -264,10 +264,12 @@ static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer) nlohmann::json pa = nlohmann::json::array(); for(unsigned int i=0;ipathCount;++i) { + int64_t lastSend = peer->paths[i].lastSend; + int64_t lastReceive = peer->paths[i].lastReceive; nlohmann::json j; j["address"] = reinterpret_cast(&(peer->paths[i].address))->toString(tmp); - j["lastSend"] = peer->paths[i].lastSend; - j["lastReceive"] = peer->paths[i].lastReceive; + j["lastSend"] = (lastSend < 0) ? 0 : lastSend; + j["lastReceive"] = (lastReceive < 0) ? 0 : lastReceive; j["trustedPathId"] = peer->paths[i].trustedPathId; j["linkQuality"] = (double)peer->paths[i].linkQuality / (double)ZT_PATH_LINK_QUALITY_MAX; j["active"] = (bool)(peer->paths[i].expired == 0); -- cgit v1.2.3 From ee4783e3fb975d73aabeaa433c346aea043908a9 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Tue, 10 Oct 2017 15:01:15 -0700 Subject: ifdef omit of deletePersistentTapDevice() in OneService for libzt builds on Windows --- service/OneService.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index f366efd4..743f5a9a 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1989,7 +1989,7 @@ public: *nuptr = (void *)0; delete n.tap; _nets.erase(nwid); -#ifdef __WINDOWS__ +#if defined(__WINDOWS__) && !defined(ZT_SDK) if ((op == ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY)&&(winInstanceId.length() > 0)) WindowsEthernetTap::deletePersistentTapDevice(winInstanceId.c_str()); #endif -- cgit v1.2.3 From 2cc4dc5a6fb815f97614c71429d5c4674576ebef Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 25 Oct 2017 16:08:14 -0700 Subject: Clean peers.d periodically and delete peers older than 30 days. --- osdep/OSUtils.cpp | 6 +++--- osdep/OSUtils.hpp | 2 +- service/OneService.cpp | 7 +++++++ 3 files changed, 11 insertions(+), 4 deletions(-) (limited to 'service/OneService.cpp') diff --git a/osdep/OSUtils.cpp b/osdep/OSUtils.cpp index 30349285..0257458a 100644 --- a/osdep/OSUtils.cpp +++ b/osdep/OSUtils.cpp @@ -133,7 +133,7 @@ std::vector OSUtils::listDirectory(const char *path,bool includeDir return r; } -long OSUtils::cleanDirectory(const char *path,const uint64_t olderThan) +long OSUtils::cleanDirectory(const char *path,const int64_t olderThan) { long cleaned = 0; @@ -150,7 +150,7 @@ long OSUtils::cleanDirectory(const char *path,const uint64_t olderThan) date.LowPart = ffd.ftLastWriteTime.dwLowDateTime; if (date.QuadPart > 0) { date.QuadPart -= adjust.QuadPart; - if ((uint64_t)((date.QuadPart / 10000000) * 1000) < olderThan) { + if ((int64_t)((date.QuadPart / 10000000) * 1000) < olderThan) { ztsnprintf(tmp, sizeof(tmp), "%s\\%s", path, ffd.cFileName); if (DeleteFileA(tmp)) ++cleaned; @@ -176,7 +176,7 @@ long OSUtils::cleanDirectory(const char *path,const uint64_t olderThan) if ((strcmp(dptr->d_name,"."))&&(strcmp(dptr->d_name,".."))&&(dptr->d_type == DT_REG)) { ztsnprintf(tmp,sizeof(tmp),"%s/%s",path,dptr->d_name); if (stat(tmp,&st) == 0) { - uint64_t mt = (uint64_t)(st.st_mtime); + int64_t mt = (int64_t)(st.st_mtime); if ((mt > 0)&&((mt * 1000) < olderThan)) { if (unlink(tmp) == 0) ++cleaned; diff --git a/osdep/OSUtils.hpp b/osdep/OSUtils.hpp index 8f66f850..45770b7f 100644 --- a/osdep/OSUtils.hpp +++ b/osdep/OSUtils.hpp @@ -142,7 +142,7 @@ public: * @param olderThan Last modified older than timestamp (ms since epoch) * @return Number of cleaned files or negative on fatal error */ - static long cleanDirectory(const char *path,const uint64_t olderThan); + static long cleanDirectory(const char *path,const int64_t olderThan); /** * Delete a directory and all its files and subdirectories recursively diff --git a/service/OneService.cpp b/service/OneService.cpp index 743f5a9a..e962fb5b 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -762,6 +762,7 @@ public: int64_t lastTapMulticastGroupCheck = 0; int64_t lastBindRefresh = 0; int64_t lastUpdateCheck = clockShouldBe; + int64_t lastCleanedPeersDb = 0; int64_t lastLocalInterfaceAddressCheck = (clockShouldBe - ZT_LOCAL_INTERFACE_CHECK_INTERVAL) + 15000; // do this in 15s to give portmapper time to configure and other things time to settle for(;;) { _run_m.lock(); @@ -856,6 +857,12 @@ public: _node->addLocalInterfaceAddress(reinterpret_cast(&(*i))); } + // Clean peers.d periodically + if ((now - lastCleanedPeersDb) >= 3600000) { + lastCleanedPeersDb = now; + OSUtils::cleanDirectory((_homePath + ZT_PATH_SEPARATOR_S "peers.d").c_str(),now - 2592000000LL); // delete older than 30 days + } + const unsigned long delay = (dl > now) ? (unsigned long)(dl - now) : 100; clockShouldBe = now + (uint64_t)delay; _phy.poll(delay); -- cgit v1.2.3 From 92c7070aa85425041f856d7e4203bdd1ae713c33 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 3 Nov 2017 20:55:16 -0400 Subject: RethinkDB fixes. --- controller/EmbeddedNetworkController.cpp | 105 ++++------- controller/EmbeddedNetworkController.hpp | 2 +- controller/RethinkDB.cpp | 288 +++++++++++++++++-------------- controller/RethinkDB.hpp | 2 + make-linux.mk | 2 +- service/OneService.cpp | 6 +- 6 files changed, 200 insertions(+), 205 deletions(-) (limited to 'service/OneService.cpp') diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index 7cb931c6..1ca2ee08 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -457,8 +457,7 @@ EmbeddedNetworkController::EmbeddedNetworkController(Node *node,const char *dbPa _startTime(OSUtils::now()), _node(node), _path(dbPath), - _sender((NetworkController::Sender *)0), - _db(this,_signingId.address(),dbPath) + _sender((NetworkController::Sender *)0) { } @@ -476,7 +475,8 @@ void EmbeddedNetworkController::init(const Identity &signingId,Sender *sender) _signingId = signingId; _sender = sender; _signingIdAddressString = signingId.address().toString(tmp); - _db.waitForReady(); + _db.reset(new ControllerDB(this,_signingId.address(),_path.c_str())); + _db->waitForReady(); } void EmbeddedNetworkController::request( @@ -507,12 +507,15 @@ 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) { @@ -524,7 +527,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; _addMemberNonPersistedFields(nwid,address,member,OSUtils::now()); responseBody = OSUtils::jsonDump(member); @@ -535,7 +538,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) { @@ -558,7 +561,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( const int64_t now = OSUtils::now(); ControllerDB::NetworkSummaryInfo ns; - _db.summary(nwid,ns); + _db->summary(nwid,ns); _addNetworkNonPersistedFields(nwid,network,now,ns); responseBody = OSUtils::jsonDump(network); responseContentType = "application/json"; @@ -569,7 +572,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( // List networks std::vector networkIds; - _db.networks(networkIds); + _db->networks(networkIds); char tmp[64]; responseBody = "["; responseBody.reserve((networkIds.size() + 1) * 24); @@ -608,6 +611,8 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( std::string &responseBody, std::string &responseContentType) { + if (!_db) + return 500; if (path.empty()) return 404; @@ -641,7 +646,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); json origMember(member); // for detecting changes _initMember(member); @@ -732,7 +737,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( if (member != origMember) { json &revj = member["revision"]; member["revision"] = (revj.is_number() ? ((uint64_t)revj + 1ULL) : 1ULL); - _db.save(member); + _db->save(member); } _addMemberNonPersistedFields(nwid,address,member,now); @@ -754,7 +759,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; } @@ -765,7 +770,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); json origNetwork(network); // for detecting changes _initNetwork(network); @@ -984,11 +989,11 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST( if (network != origNetwork) { json &revj = network["revision"]; network["revision"] = (revj.is_number() ? ((uint64_t)revj + 1ULL) : 1ULL); - _db.save(network); + _db->save(network); } ControllerDB::NetworkSummaryInfo ns; - _db.summary(nwid,ns); + _db->summary(nwid,ns); _addNetworkNonPersistedFields(nwid,network,now,ns); responseBody = OSUtils::jsonDump(network); @@ -1011,6 +1016,8 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpDELETE( std::string &responseBody, std::string &responseContentType) { + if (!_db) + return 500; if (path.empty()) return 404; @@ -1022,7 +1029,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpDELETE( const uint64_t address = Utils::hexStrToU64(path[3].c_str()); json network,member; - _db.get(nwid,network,address,member); + _db->get(nwid,network,address,member); { std::lock_guard l(_memberStatus_l); @@ -1037,8 +1044,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); @@ -1068,6 +1075,9 @@ 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; @@ -1106,7 +1116,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); } catch ( ... ) { // drop invalid trace messages if an error occurs } @@ -1159,6 +1169,9 @@ void EmbeddedNetworkController::_request( ControllerDB::NetworkSummaryInfo ns; json network,member,origMember; + if (!_db) + return; + if (((!_signingId)||(!_signingId.hasPrivate()))||(_signingId.address().toInt() != (nwid >> 24))||(!_sender)) return; @@ -1173,7 +1186,7 @@ void EmbeddedNetworkController::_request( } OSUtils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid); - if (!_db.get(nwid,network,identity.address().toInt(),member,ns)) { + if (!_db->get(nwid,network,identity.address().toInt(),member,ns)) { _sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_OBJECT_NOT_FOUND); return; } @@ -1288,7 +1301,7 @@ void EmbeddedNetworkController::_request( if (origMember != member) { json &revj = member["revision"]; member["revision"] = (revj.is_number() ? ((uint64_t)revj + 1ULL) : 1ULL); - _db.save(member); + _db->save(member); } _sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_ACCESS_DENIED); return; @@ -1655,62 +1668,12 @@ void EmbeddedNetworkController::_request( if (member != origMember) { json &revj = member["revision"]; member["revision"] = (revj.is_number() ? ((uint64_t)revj + 1ULL) : 1ULL); - _db.save(member); + _db->save(member); } _sender->ncSendConfig(nwid,requestPacketId,identity.address(),*(nc.get()),metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_VERSION,0) < 6); } -/* -void EmbeddedNetworkController::threadMain() - throw() -{ - char tmp[256]; - _RQEntry *qe = (_RQEntry *)0; - while (_running) { - const BlockingQueue<_RQEntry *>::TimedWaitResult wr = _queue.get(qe,1000); - if ((wr == BlockingQueue<_RQEntry *>::STOP)||(!_running)) - break; - - try { - if ((wr == BlockingQueue<_RQEntry *>::OK)&&(qe->type == _RQEntry::RQENTRY_TYPE_REQUEST)) { - _request(qe->nwid,qe->fromAddr,qe->requestPacketId,qe->identity,qe->metaData); - delete qe; - } - - // Every 10s we update a 'status' containing member online state, etc. - const uint64_t now = OSUtils::now(); - if ((now - _lastDumpedStatus) >= 10000) { - _lastDumpedStatus = now; - bool first = true; - OSUtils::ztsnprintf(tmp,sizeof(tmp),"{\"id\":\"%.10llx-status\",\"objtype\":\"status\",\"memberStatus\":[",_signingId.address().toInt()); - std::string st(tmp); - { - Mutex::Lock _l(_memberStatus_m); - st.reserve(48 * (_memberStatus.size() + 1)); - _db.eachId([this,&st,&now,&first,&tmp](uint64_t networkId,uint64_t nodeId) { - uint64_t lrt = 0ULL; - auto ms = this->_memberStatus.find(_MemberStatusKey(networkId,nodeId)); - if (ms != _memberStatus.end()) - lrt = ms->second.lastRequestTime; - OSUtils::ztsnprintf(tmp,sizeof(tmp),"%s\"%.16llx\",\"%.10llx\",%llu", - (first) ? "" : ",", - (unsigned long long)networkId, - (unsigned long long)nodeId, - (unsigned long long)lrt); - st.append(tmp); - first = false; - }); - } - OSUtils::ztsnprintf(tmp,sizeof(tmp),"],\"clock\":%llu,\"startTime\":%llu,\"uptime\":%llu,\"vMajor\":%d,\"vMinor\":%d,\"vRev\":%d}",(unsigned long long)now,(unsigned long long)_startTime,(unsigned long long)(now - _startTime),ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION); - st.append(tmp); - _db.writeRaw("status",st); - } - } catch ( ... ) {} - } -} -*/ - void EmbeddedNetworkController::_startThreads() { std::lock_guard l(_threads_l); diff --git a/controller/EmbeddedNetworkController.hpp b/controller/EmbeddedNetworkController.hpp index 7149df10..f9b6fb5a 100644 --- a/controller/EmbeddedNetworkController.hpp +++ b/controller/EmbeddedNetworkController.hpp @@ -239,7 +239,7 @@ private: Identity _signingId; std::string _signingIdAddressString; NetworkController::Sender *_sender; - ControllerDB _db; + std::unique_ptr _db; BlockingQueue< _RQEntry * > _queue; std::vector _threads; std::mutex _threads_l; diff --git a/controller/RethinkDB.cpp b/controller/RethinkDB.cpp index 6e656d23..1f8d29df 100644 --- a/controller/RethinkDB.cpp +++ b/controller/RethinkDB.cpp @@ -40,12 +40,13 @@ RethinkDB::RethinkDB(EmbeddedNetworkController *const nc,const Address &myAddres _waitNoticePrinted(false) { std::vector ps(OSUtils::split(path,":","","")); - if ((ps.size() != 5)||(ps[0] != "rethinkdb")) + if ((ps.size() < 4)||(ps[0] != "rethinkdb")) throw std::runtime_error("invalid rethinkdb database url"); _host = ps[1]; - _db = ps[2]; - _auth = ps[3]; - _port = Utils::strToInt(ps[4].c_str()); + _port = Utils::strToInt(ps[2].c_str()); + _db = ps[3]; + if (ps.size() > 4) + _auth = ps[4]; _readyLock.lock(); @@ -56,167 +57,192 @@ RethinkDB::RethinkDB(EmbeddedNetworkController *const nc,const Address &myAddres } _membersDbWatcher = std::thread([this]() { - while (_run == 1) { - try { - std::unique_ptr rdb(R::connect(this->_host,this->_port,this->_auth)); - if (rdb) { - _membersDbWatcherConnection = (void *)rdb.get(); - auto cur = R::db(this->_db).table("Member",R::optargs("read_mode","outdated")).get_all(this->_myAddressStr,R::optargs("index","controllerId")).changes(R::optargs("squash",0.05,"include_initial",true,"include_types",true,"include_states",true)).run(*rdb); - while (cur.has_next()) { - if (_run != 1) break; - json tmp(json::parse(cur.next().as_json())); - if ((tmp["type"] == "state")&&(tmp["state"] == "ready")) { - if (--this->_ready == 0) { - if (_waitNoticePrinted) - fprintf(stderr,"NOTICE: controller RethinkDB data download complete." ZT_EOL_S); - this->_readyLock.unlock(); + try { + while (_run == 1) { + try { + std::unique_ptr rdb(R::connect(this->_host,this->_port,this->_auth)); + if (rdb) { + _membersDbWatcherConnection = (void *)rdb.get(); + auto cur = R::db(this->_db).table("Member",R::optargs("read_mode","outdated")).get_all(this->_myAddressStr,R::optargs("index","controllerId")).changes(R::optargs("squash",0.05,"include_initial",true,"include_types",true,"include_states",true)).run(*rdb); + while (cur.has_next()) { + if (_run != 1) break; + json tmp(json::parse(cur.next().as_json())); + if ((tmp["type"] == "state")&&(tmp["state"] == "ready")) { + if (--this->_ready == 0) { + if (_waitNoticePrinted) + fprintf(stderr,"NOTICE: controller RethinkDB data download complete." ZT_EOL_S); + this->_readyLock.unlock(); + } + } else { + try { + json &ov = tmp["old_val"]; + json &nv = tmp["new_val"]; + if (ov.is_object()||nv.is_object()) { + this->_memberChanged(ov,nv); + } + } catch ( ... ) {} // ignore bad records } - } else { - try { - json &ov = tmp["old_val"]; - json &nv = tmp["new_val"]; - if (ov.is_object()||nv.is_object()) - this->_memberChanged(ov,nv); - } catch ( ... ) {} // ignore bad records } } + } catch (std::exception &e) { + fprintf(stderr,"ERROR: controller RethinkDB (member change stream): %s" ZT_EOL_S,e.what()); + } catch (R::Error &e) { + fprintf(stderr,"ERROR: controller RethinkDB (member change stream): %s" ZT_EOL_S,e.message.c_str()); + } catch ( ... ) { + fprintf(stderr,"ERROR: controller RethinkDB (member change stream): unknown exception" ZT_EOL_S); } - } catch (std::exception &e) { - fprintf(stderr,"ERROR: controller RethinkDB (member change stream): %s" ZT_EOL_S,e.what()); - } catch (R::Error &e) { - fprintf(stderr,"ERROR: controller RethinkDB (member change stream): %s" ZT_EOL_S,e.message.c_str()); - } catch ( ... ) { - fprintf(stderr,"ERROR: controller RethinkDB (member change stream): unknown exception" ZT_EOL_S); + std::this_thread::sleep_for(std::chrono::milliseconds(250)); } - std::this_thread::sleep_for(std::chrono::milliseconds(250)); - } + } catch ( ... ) {} }); _networksDbWatcher = std::thread([this]() { - while (_run == 1) { - try { - std::unique_ptr rdb(R::connect(this->_host,this->_port,this->_auth)); - if (rdb) { - _membersDbWatcherConnection = (void *)rdb.get(); - auto cur = R::db(this->_db).table("Network",R::optargs("read_mode","outdated")).get_all(this->_myAddressStr,R::optargs("index","controllerId")).changes(R::optargs("squash",0.05,"include_initial",true,"include_types",true,"include_states",true)).run(*rdb); - while (cur.has_next()) { - if (_run != 1) break; - json tmp(json::parse(cur.next().as_json())); - if ((tmp["type"] == "state")&&(tmp["state"] == "ready")) { - if (--this->_ready == 0) { - if (_waitNoticePrinted) - fprintf(stderr,"NOTICE: controller RethinkDB data download complete." ZT_EOL_S); - this->_readyLock.unlock(); + try { + while (_run == 1) { + try { + std::unique_ptr rdb(R::connect(this->_host,this->_port,this->_auth)); + if (rdb) { + _networksDbWatcherConnection = (void *)rdb.get(); + auto cur = R::db(this->_db).table("Network",R::optargs("read_mode","outdated")).get_all(this->_myAddressStr,R::optargs("index","controllerId")).changes(R::optargs("squash",0.05,"include_initial",true,"include_types",true,"include_states",true)).run(*rdb); + while (cur.has_next()) { + if (_run != 1) break; + json tmp(json::parse(cur.next().as_json())); + if ((tmp["type"] == "state")&&(tmp["state"] == "ready")) { + if (--this->_ready == 0) { + if (_waitNoticePrinted) + fprintf(stderr,"NOTICE: controller RethinkDB data download complete." ZT_EOL_S); + this->_readyLock.unlock(); + } + } else { + try { + json &ov = tmp["old_val"]; + json &nv = tmp["new_val"]; + if (ov.is_object()||nv.is_object()) { + this->_networkChanged(ov,nv); + } + } catch ( ... ) {} // ignore bad records } - } else { - try { - json &ov = tmp["old_val"]; - json &nv = tmp["new_val"]; - if (ov.is_object()||nv.is_object()) - this->_networkChanged(ov,nv); - } catch ( ... ) {} // ignore bad records } } + } catch (std::exception &e) { + fprintf(stderr,"ERROR: controller RethinkDB (network change stream): %s" ZT_EOL_S,e.what()); + } catch (R::Error &e) { + fprintf(stderr,"ERROR: controller RethinkDB (network change stream): %s" ZT_EOL_S,e.message.c_str()); + } catch ( ... ) { + fprintf(stderr,"ERROR: controller RethinkDB (network change stream): unknown exception" ZT_EOL_S); } - } catch (std::exception &e) { - fprintf(stderr,"ERROR: controller RethinkDB (network change stream): %s" ZT_EOL_S,e.what()); - } catch (R::Error &e) { - fprintf(stderr,"ERROR: controller RethinkDB (network change stream): %s" ZT_EOL_S,e.message.c_str()); - } catch ( ... ) { - fprintf(stderr,"ERROR: controller RethinkDB (network change stream): unknown exception" ZT_EOL_S); + std::this_thread::sleep_for(std::chrono::milliseconds(250)); } - std::this_thread::sleep_for(std::chrono::milliseconds(250)); - } + } catch ( ... ) {} }); for(int t=0;t rdb; - nlohmann::json *config = (nlohmann::json *)0; - while ((this->_commitQueue.get(config))&&(_run == 1)) { - if (!config) - continue; - json record; - const std::string objtype = (*config)["objtype"]; - const char *table; - std::string deleteId; - if (objtype == "member") { - const std::string nwid = (*config)["nwid"]; - const std::string id = (*config)["id"]; - record["id"] = nwid + "-" + id; - record["controllerId"] = this->_myAddressStr; - record["networkId"] = nwid; - record["nodeId"] = id; - record["config"] = *config; - table = "Member"; - } else if (objtype == "network") { - const std::string id = (*config)["id"]; - record["id"] = id; - record["controllerId"] = this->_myAddressStr; - record["config"] = *config; - table = "Network"; - } else if (objtype == "delete_network") { - deleteId = (*config)["id"]; - table = "Network"; - } else if (objtype == "delete_member") { - deleteId = (*config)["nwid"]; - deleteId.push_back('-'); - const std::string tmp = (*config)["id"]; - deleteId.append(tmp); - table = "Member"; - } else if (objtype == "trace") { - record = *config; - table = "RemoteTrace"; - } else { - continue; - } + try { + std::unique_ptr rdb; + nlohmann::json *config = (nlohmann::json *)0; + while ((this->_commitQueue.get(config))&&(_run == 1)) { + if (!config) + continue; + json record; + const std::string objtype = (*config)["objtype"]; + const char *table; + std::string deleteId; + if (objtype == "member") { + const std::string nwid = (*config)["nwid"]; + const std::string id = (*config)["id"]; + record["id"] = nwid + "-" + id; + record["controllerId"] = this->_myAddressStr; + record["networkId"] = nwid; + record["nodeId"] = id; + record["config"] = *config; + table = "Member"; + } else if (objtype == "network") { + const std::string id = (*config)["id"]; + record["id"] = id; + record["controllerId"] = this->_myAddressStr; + record["config"] = *config; + table = "Network"; + } else if (objtype == "delete_network") { + deleteId = (*config)["id"]; + table = "Network"; + } else if (objtype == "delete_member") { + deleteId = (*config)["nwid"]; + deleteId.push_back('-'); + const std::string tmp = (*config)["id"]; + deleteId.append(tmp); + table = "Member"; + } else if (objtype == "trace") { + record = *config; + table = "RemoteTrace"; + } else { + continue; + } - while (_run == 1) { - try { - if (!rdb) - rdb = R::connect(this->_host,this->_port,this->_auth); - if (rdb) { - if (deleteId.length() > 0) { - R::db(this->_db).table(table).get(deleteId).delete_().run(*rdb); + while (_run == 1) { + try { + if (!rdb) + rdb = R::connect(this->_host,this->_port,this->_auth); + if (rdb) { + if (deleteId.length() > 0) { + printf("DELETE: %s" ZT_EOL_S,deleteId.c_str()); + R::db(this->_db).table(table).get(deleteId).delete_().run(*rdb); + } else { + printf("UPSERT: %s" ZT_EOL_S,record.dump().c_str()); + R::db(this->_db).table(table).insert(R::Datum::from_json(record.dump()),R::optargs("conflict","update","return_changes",false)).run(*rdb); + } + break; } else { - R::db(this->_db).table(table).insert(record.dump(),R::optargs("conflict","update","return_changes",false)).run(*rdb); + fprintf(stderr,"ERROR: controller RethinkDB (insert/update): connect failed (will retry)" ZT_EOL_S); } - break; - } else { - fprintf(stderr,"ERROR: controller RethinkDB (insert/update): connect failed (will retry)" ZT_EOL_S); + } catch (std::exception &e) { + fprintf(stderr,"ERROR: controller RethinkDB (insert/update): %s" ZT_EOL_S,e.what()); + rdb.reset(); + } catch (R::Error &e) { + fprintf(stderr,"ERROR: controller RethinkDB (insert/update): %s" ZT_EOL_S,e.message.c_str()); + rdb.reset(); + } catch ( ... ) { + fprintf(stderr,"ERROR: controller RethinkDB (insert/update): unknown exception" ZT_EOL_S); + rdb.reset(); } - } catch (std::exception &e) { - fprintf(stderr,"ERROR: controller RethinkDB (insert/update): %s" ZT_EOL_S,e.what()); - rdb.reset(); - } catch (R::Error &e) { - fprintf(stderr,"ERROR: controller RethinkDB (insert/update): %s" ZT_EOL_S,e.message.c_str()); - rdb.reset(); - } catch ( ... ) { - fprintf(stderr,"ERROR: controller RethinkDB (insert/update): unknown exception" ZT_EOL_S); - rdb.reset(); + std::this_thread::sleep_for(std::chrono::milliseconds(250)); } - std::this_thread::sleep_for(std::chrono::milliseconds(250)); } - } + } catch ( ... ) {} }); } + + _heartbeatThread = std::thread([this]() { + try { + char tmp[1024]; + std::unique_ptr rdb; + while (_run == 1) { + try { + if (!rdb) + rdb = R::connect(this->_host,this->_port,this->_auth); + if (rdb) { + OSUtils::ztsnprintf(tmp,sizeof(tmp),"{\"id\":\"%s\",\"lastAlive\":%lld}",this->_myAddressStr.c_str(),(long long)OSUtils::now()); + R::db(this->_db).table("Controller").update(R::Datum::from_json(tmp)).run(*rdb); + } + } catch ( ... ) { + rdb.reset(); + } + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + } + } catch ( ... ) {} + }); } RethinkDB::~RethinkDB() { - // FIXME: not totally safe but will generally work, and only happens on shutdown anyway. - // Would need to add some kind of 'whack it' support to librethinkdbxx to do better. _run = 0; std::this_thread::sleep_for(std::chrono::milliseconds(100)); - if (_membersDbWatcherConnection) - ((R::Connection *)_membersDbWatcherConnection)->close(); - if (_networksDbWatcherConnection) - ((R::Connection *)_networksDbWatcherConnection)->close(); _commitQueue.stop(); for(int t=0;t _commitQueue; std::thread _commitThread[ZT_CONTROLLER_RETHINKDB_COMMIT_THREADS]; + std::thread _heartbeatThread; + mutable std::mutex _readyLock; // locked until ready std::atomic _ready; std::atomic _run; diff --git a/make-linux.mk b/make-linux.mk index 4d944776..877d6dc9 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -268,7 +268,7 @@ official-static: FORCE central-controller: FORCE cd ext/librethinkdbxx ; make - make LDLIBS="-ljemalloc ext/librethinkdbxx/build/librethinkdb++.a" DEFS="-DZT_CONTROLLER_USE_RETHINKDB" one + make -j4 LDLIBS="ext/librethinkdbxx/build/librethinkdb++.a" DEFS="-DZT_CONTROLLER_USE_RETHINKDB" one debug: FORCE make ZT_DEBUG=1 one diff --git a/service/OneService.cpp b/service/OneService.cpp index e962fb5b..66cb708d 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -867,10 +867,14 @@ public: clockShouldBe = now + (uint64_t)delay; _phy.poll(delay); } + } catch (std::exception &e) { + Mutex::Lock _l(_termReason_m); + _termReason = ONE_UNRECOVERABLE_ERROR; + _fatalErrorMessage = std::string("unexpected exception in main thread: ")+e.what(); } catch ( ... ) { Mutex::Lock _l(_termReason_m); _termReason = ONE_UNRECOVERABLE_ERROR; - _fatalErrorMessage = "unexpected exception in main thread"; + _fatalErrorMessage = "unexpected exception in main thread: unknown exception"; } try { -- cgit v1.2.3 From e5d1243dd225526b044d36b15dd28a74c49a8816 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Mon, 6 Nov 2017 13:43:56 -0800 Subject: Minor changes to SDK-related portions of OneService --- service/OneService.cpp | 10 +++++----- service/OneService.hpp | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index e962fb5b..8081d00a 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -99,7 +99,7 @@ namespace ZeroTier { typedef TestEthernetTap EthernetTap; } #include "../controller/EmbeddedNetworkController.hpp" #include "../node/Node.hpp" // Use the virtual netcon endpoint instead of a tun/tap port driver -#include "../src/VirtualTap.hpp" +#include "../include/VirtualTap.h" namespace ZeroTier { typedef VirtualTap EthernetTap; } #else @@ -916,14 +916,14 @@ public: } #ifdef ZT_SDK - virtual void leave(const char *hp) + virtual void leave(const uint64_t hp) { - _node->leave(Utils::hexStrToU64(hp),NULL,NULL); + _node->leave(hp, NULL, NULL); } - virtual void join(const char *hp) + virtual void join(const uint64_t hp) { - _node->join(Utils::hexStrToU64(hp),NULL,NULL); + _node->join(hp, NULL, NULL); } virtual std::string givenHomePath() diff --git a/service/OneService.hpp b/service/OneService.hpp index b0467419..23e572d0 100644 --- a/service/OneService.hpp +++ b/service/OneService.hpp @@ -35,7 +35,7 @@ #ifdef ZT_SDK #include "../node/Node.hpp" // Use the virtual netcon endpoint instead of a tun/tap port driver -#include "../src/VirtualTap.hpp" +#include "../include/VirtualTap.h" namespace ZeroTier { typedef VirtualTap EthernetTap; } #endif @@ -147,8 +147,8 @@ public: virtual std::string portDeviceName(uint64_t nwid) const = 0; #ifdef ZT_SDK - virtual void leave(const char *hp) = 0; - virtual void join(const char *hp) = 0; + virtual void leave(const uint64_t hp) = 0; + virtual void join(const uint64_t hp) = 0; virtual std::string givenHomePath() = 0; virtual Node * getNode() = 0; virtual void removeNets() = 0; -- cgit v1.2.3 From 382dd82eb62ba41b6051af92ce749809a3b61ed7 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Mon, 27 Nov 2017 15:31:25 -0800 Subject: Fix for local.conf virtual path blacklist (ticket #594) --- service/OneService.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index b767dea8..b30dc390 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1411,7 +1411,7 @@ public: json &blAddrs = v.value()["blacklist"]; if (blAddrs.is_array()) { for(unsigned long i=0;i Date: Fri, 15 Dec 2017 11:03:20 -0800 Subject: Some micro-optimizations, including a memcpy that is faster than Linux for most distro/compiler versions. --- controller/EmbeddedNetworkController.cpp | 8 +++--- make-linux.mk | 6 ++--- node/Buffer.hpp | 8 +++--- node/Capability.hpp | 10 ++++---- node/CertificateOfMembership.hpp | 6 ++--- node/CertificateOfOwnership.hpp | 8 +++--- node/Dictionary.hpp | 2 +- node/Identity.hpp | 4 +-- node/InetAddress.cpp | 16 ++++++------ node/InetAddress.hpp | 34 ++++++++++++------------ node/Network.cpp | 6 ++--- node/NetworkConfig.hpp | 4 +-- node/Node.cpp | 4 +-- node/OutboundMulticast.cpp | 2 +- node/Packet.cpp | 28 ++++++++++---------- node/Path.hpp | 4 +-- node/Revocation.hpp | 2 +- node/Tag.hpp | 2 +- node/Utils.hpp | 38 +++++++++++++++++++++++++++ node/World.hpp | 4 +-- selftest.cpp | 44 ++++++++++++++++++++++++++++++++ service/OneService.cpp | 4 +-- 22 files changed, 163 insertions(+), 81 deletions(-) (limited to 'service/OneService.cpp') diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index d8ac1878..2032f097 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -333,14 +333,14 @@ static bool _parseRule(json &r,ZT_VirtualNetworkRule &rule) } else if (t == "MATCH_IPV6_SOURCE") { rule.t |= ZT_NETWORK_RULE_MATCH_IPV6_SOURCE; InetAddress ip(OSUtils::jsonString(r["ip"],"::0").c_str()); - memcpy(rule.v.ipv6.ip,reinterpret_cast(&ip)->sin6_addr.s6_addr,16); + ZT_FAST_MEMCPY(rule.v.ipv6.ip,reinterpret_cast(&ip)->sin6_addr.s6_addr,16); rule.v.ipv6.mask = Utils::ntoh(reinterpret_cast(&ip)->sin6_port) & 0xff; if (rule.v.ipv6.mask > 128) rule.v.ipv6.mask = 128; return true; } else if (t == "MATCH_IPV6_DEST") { rule.t |= ZT_NETWORK_RULE_MATCH_IPV6_DEST; InetAddress ip(OSUtils::jsonString(r["ip"],"::0").c_str()); - memcpy(rule.v.ipv6.ip,reinterpret_cast(&ip)->sin6_addr.s6_addr,16); + ZT_FAST_MEMCPY(rule.v.ipv6.ip,reinterpret_cast(&ip)->sin6_addr.s6_addr,16); rule.v.ipv6.mask = Utils::ntoh(reinterpret_cast(&ip)->sin6_port) & 0xff; if (rule.v.ipv6.mask > 128) rule.v.ipv6.mask = 128; return true; @@ -1520,8 +1520,8 @@ void EmbeddedNetworkController::_request( InetAddress ipRangeEnd(OSUtils::jsonString(pool["ipRangeEnd"],"").c_str()); if ( (ipRangeStart.ss_family == AF_INET6) && (ipRangeEnd.ss_family == AF_INET6) ) { uint64_t s[2],e[2],x[2],xx[2]; - memcpy(s,ipRangeStart.rawIpData(),16); - memcpy(e,ipRangeEnd.rawIpData(),16); + ZT_FAST_MEMCPY(s,ipRangeStart.rawIpData(),16); + ZT_FAST_MEMCPY(e,ipRangeEnd.rawIpData(),16); s[0] = Utils::ntoh(s[0]); s[1] = Utils::ntoh(s[1]); e[0] = Utils::ntoh(e[0]); diff --git a/make-linux.mk b/make-linux.mk index 5b623247..99268990 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -66,9 +66,9 @@ ifeq ($(ZT_DEBUG),1) node/Salsa20.o node/SHA512.o node/C25519.o node/Poly1305.o: CXXFLAGS=-Wall -O2 -g -pthread $(INCLUDES) $(DEFS) else override DEFS+=-D_FORTIFY_SOURCE=2 - CFLAGS?=-Os -fstack-protector + CFLAGS?=-O3 -fstack-protector override CFLAGS+=-Wall -Wno-deprecated -fPIE -pthread $(INCLUDES) -DNDEBUG $(DEFS) - CXXFLAGS?=-Os -fstack-protector + CXXFLAGS?=-O3 -fstack-protector override CXXFLAGS+=-Wall -Wno-deprecated -Wno-unused-result -Wreorder -fPIE -std=c++11 -pthread $(INCLUDES) -DNDEBUG $(DEFS) override LDFLAGS+=-pie -Wl,-z,relro,-z,now STRIP?=strip @@ -241,7 +241,7 @@ zerotier-idtool: one zerotier-cli: one libzerotiercore.a: FORCE - make CFLAGS="-Os -fstack-protector -fPIC" CXXFLAGS="-Os -std=c++11 -fstack-protector -fPIC" $(CORE_OBJS) + make CFLAGS="-O3 -fstack-protector -fPIC" CXXFLAGS="-O3 -std=c++11 -fstack-protector -fPIC" $(CORE_OBJS) ar rcs libzerotiercore.a $(CORE_OBJS) ranlib libzerotiercore.a diff --git a/node/Buffer.hpp b/node/Buffer.hpp index 7b91e72f..f84b3774 100644 --- a/node/Buffer.hpp +++ b/node/Buffer.hpp @@ -116,9 +116,9 @@ public: if (unlikely(b._l > C)) throw ZT_EXCEPTION_OUT_OF_BOUNDS; if (C2 == C) { - memcpy(this,&b,sizeof(Buffer)); + ZT_FAST_MEMCPY(this,&b,sizeof(Buffer)); } else { - memcpy(_b,b._b,_l = b._l); + ZT_FAST_MEMCPY(_b,b._b,_l = b._l); } return *this; } @@ -127,7 +127,7 @@ public: { if (unlikely(l > C)) throw ZT_EXCEPTION_OUT_OF_BOUNDS; - memcpy(_b,b,l); + ZT_FAST_MEMCPY(_b,b,l); _l = l; } @@ -281,7 +281,7 @@ public: { if (unlikely((_l + l) > C)) throw ZT_EXCEPTION_OUT_OF_BOUNDS; - memcpy(_b + _l,b,l); + ZT_FAST_MEMCPY(_b + _l,b,l); _l += l; } diff --git a/node/Capability.hpp b/node/Capability.hpp index 407884ad..bec1f47f 100644 --- a/node/Capability.hpp +++ b/node/Capability.hpp @@ -94,7 +94,7 @@ public: _maxCustodyChainLength = (mccl > 0) ? ((mccl < ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH) ? mccl : (unsigned int)ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH) : 1; _ruleCount = (ruleCount < ZT_MAX_CAPABILITY_RULES) ? ruleCount : ZT_MAX_CAPABILITY_RULES; if (_ruleCount) - memcpy(_rules,rules,sizeof(ZT_VirtualNetworkRule) * _ruleCount); + ZT_FAST_MEMCPY(_rules,rules,sizeof(ZT_VirtualNetworkRule) * _ruleCount); } /** @@ -320,16 +320,16 @@ public: break; case ZT_NETWORK_RULE_MATCH_MAC_SOURCE: case ZT_NETWORK_RULE_MATCH_MAC_DEST: - memcpy(rules[ruleCount].v.mac,b.field(p,6),6); + ZT_FAST_MEMCPY(rules[ruleCount].v.mac,b.field(p,6),6); break; case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE: case ZT_NETWORK_RULE_MATCH_IPV4_DEST: - memcpy(&(rules[ruleCount].v.ipv4.ip),b.field(p,4),4); + ZT_FAST_MEMCPY(&(rules[ruleCount].v.ipv4.ip),b.field(p,4),4); rules[ruleCount].v.ipv4.mask = (uint8_t)b[p + 4]; break; case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE: case ZT_NETWORK_RULE_MATCH_IPV6_DEST: - memcpy(rules[ruleCount].v.ipv6.ip,b.field(p,16),16); + ZT_FAST_MEMCPY(rules[ruleCount].v.ipv6.ip,b.field(p,16),16); rules[ruleCount].v.ipv6.mask = (uint8_t)b[p + 16]; break; case ZT_NETWORK_RULE_MATCH_IP_TOS: @@ -452,7 +452,7 @@ public: if (b.template at(p) != ZT_C25519_SIGNATURE_LEN) throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN; p += 2; - memcpy(_custody[i].signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); p += ZT_C25519_SIGNATURE_LEN; + ZT_FAST_MEMCPY(_custody[i].signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); p += ZT_C25519_SIGNATURE_LEN; } else { p += 2 + b.template at(p); } diff --git a/node/CertificateOfMembership.hpp b/node/CertificateOfMembership.hpp index 0105fade..2eff1083 100644 --- a/node/CertificateOfMembership.hpp +++ b/node/CertificateOfMembership.hpp @@ -119,7 +119,7 @@ public: CertificateOfMembership(const CertificateOfMembership &c) { - memcpy(this,&c,sizeof(CertificateOfMembership)); + ZT_FAST_MEMCPY(this,&c,sizeof(CertificateOfMembership)); } /** @@ -147,7 +147,7 @@ public: inline CertificateOfMembership &operator=(const CertificateOfMembership &c) { - memcpy(this,&c,sizeof(CertificateOfMembership)); + ZT_FAST_MEMCPY(this,&c,sizeof(CertificateOfMembership)); return *this; } @@ -329,7 +329,7 @@ public: p += ZT_ADDRESS_LENGTH; if (_signedBy) { - memcpy(_signature.data,b.field(p,(unsigned int)_signature.size()),_signature.size()); + ZT_FAST_MEMCPY(_signature.data,b.field(p,(unsigned int)_signature.size()),_signature.size()); p += (unsigned int)_signature.size(); } diff --git a/node/CertificateOfOwnership.hpp b/node/CertificateOfOwnership.hpp index 431bcc03..e397fd63 100644 --- a/node/CertificateOfOwnership.hpp +++ b/node/CertificateOfOwnership.hpp @@ -115,11 +115,11 @@ public: if (_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) return; if (ip.ss_family == AF_INET) { _thingTypes[_thingCount] = THING_IPV4_ADDRESS; - memcpy(_thingValues[_thingCount],&(reinterpret_cast(&ip)->sin_addr.s_addr),4); + ZT_FAST_MEMCPY(_thingValues[_thingCount],&(reinterpret_cast(&ip)->sin_addr.s_addr),4); ++_thingCount; } else if (ip.ss_family == AF_INET6) { _thingTypes[_thingCount] = THING_IPV6_ADDRESS; - memcpy(_thingValues[_thingCount],reinterpret_cast(&ip)->sin6_addr.s6_addr,16); + ZT_FAST_MEMCPY(_thingValues[_thingCount],reinterpret_cast(&ip)->sin6_addr.s6_addr,16); ++_thingCount; } } @@ -198,7 +198,7 @@ public: for(unsigned int i=0,j=_thingCount;i(p) != ZT_C25519_SIGNATURE_LEN) throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN; p += 2; - memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); p += ZT_C25519_SIGNATURE_LEN; + ZT_FAST_MEMCPY(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); p += ZT_C25519_SIGNATURE_LEN; } else { p += 2 + b.template at(p); } diff --git a/node/Dictionary.hpp b/node/Dictionary.hpp index 061dcac1..a1b0f9cb 100644 --- a/node/Dictionary.hpp +++ b/node/Dictionary.hpp @@ -81,7 +81,7 @@ public: if (s) { if (len > (C-1)) len = C-1; - memcpy(_d,s,len); + ZT_FAST_MEMCPY(_d,s,len); _d[len] = (char)0; } else { _d[0] = (char)0; diff --git a/node/Identity.hpp b/node/Identity.hpp index 3d4d9385..ab2886ad 100644 --- a/node/Identity.hpp +++ b/node/Identity.hpp @@ -249,7 +249,7 @@ public: if (b[p++] != 0) throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE; - memcpy(_publicKey.data,b.field(p,(unsigned int)_publicKey.size()),(unsigned int)_publicKey.size()); + ZT_FAST_MEMCPY(_publicKey.data,b.field(p,(unsigned int)_publicKey.size()),(unsigned int)_publicKey.size()); p += (unsigned int)_publicKey.size(); unsigned int privateKeyLength = (unsigned int)b[p++]; @@ -257,7 +257,7 @@ public: if (privateKeyLength != ZT_C25519_PRIVATE_KEY_LEN) throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN; _privateKey = new C25519::Private(); - memcpy(_privateKey->data,b.field(p,ZT_C25519_PRIVATE_KEY_LEN),ZT_C25519_PRIVATE_KEY_LEN); + ZT_FAST_MEMCPY(_privateKey->data,b.field(p,ZT_C25519_PRIVATE_KEY_LEN),ZT_C25519_PRIVATE_KEY_LEN); p += ZT_C25519_PRIVATE_KEY_LEN; } diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp index d3efc089..ee32ce72 100644 --- a/node/InetAddress.cpp +++ b/node/InetAddress.cpp @@ -115,13 +115,13 @@ void InetAddress::set(const void *ipBytes,unsigned int ipLen,unsigned int port) memset(this,0,sizeof(InetAddress)); if (ipLen == 4) { uint32_t ipb[1]; - memcpy(ipb,ipBytes,4); + ZT_FAST_MEMCPY(ipb,ipBytes,4); ss_family = AF_INET; reinterpret_cast(this)->sin_addr.s_addr = ipb[0]; reinterpret_cast(this)->sin_port = Utils::hton((uint16_t)port); } else if (ipLen == 16) { ss_family = AF_INET6; - memcpy(reinterpret_cast(this)->sin6_addr.s6_addr,ipBytes,16); + ZT_FAST_MEMCPY(reinterpret_cast(this)->sin6_addr.s6_addr,ipBytes,16); reinterpret_cast(this)->sin6_port = Utils::hton((uint16_t)port); } } @@ -154,7 +154,7 @@ char *InetAddress::toIpString(char buf[64]) const case AF_INET6: { uint16_t a[8]; - memcpy(a,reinterpret_cast(this)->sin6_addr.s6_addr,16); + ZT_FAST_MEMCPY(a,reinterpret_cast(this)->sin6_addr.s6_addr,16); char *p = buf; for(int i=0;i<8;++i) { Utils::hex(Utils::ntoh(a[i]),p); @@ -199,7 +199,7 @@ bool InetAddress::fromString(const char *ipSlashPort) struct sockaddr_in6 *const in6 = reinterpret_cast(this); in6->sin6_family = AF_INET6; - memcpy(in6->sin6_addr.s6_addr,a,16); + ZT_FAST_MEMCPY(in6->sin6_addr.s6_addr,a,16); in6->sin6_port = Utils::hton((uint16_t)port); return true; @@ -212,7 +212,7 @@ bool InetAddress::fromString(const char *ipSlashPort) struct sockaddr_in *const in = reinterpret_cast(this); in->sin_family = AF_INET; - memcpy(&(in->sin_addr.s_addr),a,4); + ZT_FAST_MEMCPY(&(in->sin_addr.s_addr),a,4); in->sin_port = Utils::hton((uint16_t)port); return true; @@ -238,7 +238,7 @@ InetAddress InetAddress::netmask() const nm[0] = 0; nm[1] = 0; } - memcpy(reinterpret_cast(&r)->sin6_addr.s6_addr,nm,16); + ZT_FAST_MEMCPY(reinterpret_cast(&r)->sin6_addr.s6_addr,nm,16); } break; } return r; @@ -264,10 +264,10 @@ InetAddress InetAddress::network() const case AF_INET6: { uint64_t nm[2]; const unsigned int bits = netmaskBits(); - memcpy(nm,reinterpret_cast(&r)->sin6_addr.s6_addr,16); + ZT_FAST_MEMCPY(nm,reinterpret_cast(&r)->sin6_addr.s6_addr,16); nm[0] &= Utils::hton((uint64_t)((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits)))); nm[1] &= Utils::hton((uint64_t)((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits)))); - memcpy(reinterpret_cast(&r)->sin6_addr.s6_addr,nm,16); + ZT_FAST_MEMCPY(reinterpret_cast(&r)->sin6_addr.s6_addr,nm,16); } break; } return r; diff --git a/node/InetAddress.hpp b/node/InetAddress.hpp index 76810b93..fd430099 100644 --- a/node/InetAddress.hpp +++ b/node/InetAddress.hpp @@ -91,8 +91,8 @@ struct InetAddress : public sockaddr_storage }; InetAddress() { memset(this,0,sizeof(InetAddress)); } - InetAddress(const InetAddress &a) { memcpy(this,&a,sizeof(InetAddress)); } - InetAddress(const InetAddress *a) { memcpy(this,a,sizeof(InetAddress)); } + InetAddress(const InetAddress &a) { ZT_FAST_MEMCPY(this,&a,sizeof(InetAddress)); } + InetAddress(const InetAddress *a) { ZT_FAST_MEMCPY(this,a,sizeof(InetAddress)); } InetAddress(const struct sockaddr_storage &ss) { *this = ss; } InetAddress(const struct sockaddr_storage *ss) { *this = ss; } InetAddress(const struct sockaddr &sa) { *this = sa; } @@ -108,28 +108,28 @@ struct InetAddress : public sockaddr_storage inline InetAddress &operator=(const InetAddress &a) { if (&a != this) - memcpy(this,&a,sizeof(InetAddress)); + ZT_FAST_MEMCPY(this,&a,sizeof(InetAddress)); return *this; } inline InetAddress &operator=(const InetAddress *a) { if (a != this) - memcpy(this,a,sizeof(InetAddress)); + ZT_FAST_MEMCPY(this,a,sizeof(InetAddress)); return *this; } inline InetAddress &operator=(const struct sockaddr_storage &ss) { if (reinterpret_cast(&ss) != this) - memcpy(this,&ss,sizeof(InetAddress)); + ZT_FAST_MEMCPY(this,&ss,sizeof(InetAddress)); return *this; } inline InetAddress &operator=(const struct sockaddr_storage *ss) { if (reinterpret_cast(ss) != this) - memcpy(this,ss,sizeof(InetAddress)); + ZT_FAST_MEMCPY(this,ss,sizeof(InetAddress)); return *this; } @@ -137,7 +137,7 @@ struct InetAddress : public sockaddr_storage { if (reinterpret_cast(&sa) != this) { memset(this,0,sizeof(InetAddress)); - memcpy(this,&sa,sizeof(struct sockaddr_in)); + ZT_FAST_MEMCPY(this,&sa,sizeof(struct sockaddr_in)); } return *this; } @@ -146,7 +146,7 @@ struct InetAddress : public sockaddr_storage { if (reinterpret_cast(sa) != this) { memset(this,0,sizeof(InetAddress)); - memcpy(this,sa,sizeof(struct sockaddr_in)); + ZT_FAST_MEMCPY(this,sa,sizeof(struct sockaddr_in)); } return *this; } @@ -155,7 +155,7 @@ struct InetAddress : public sockaddr_storage { if (reinterpret_cast(&sa) != this) { memset(this,0,sizeof(InetAddress)); - memcpy(this,&sa,sizeof(struct sockaddr_in6)); + ZT_FAST_MEMCPY(this,&sa,sizeof(struct sockaddr_in6)); } return *this; } @@ -164,7 +164,7 @@ struct InetAddress : public sockaddr_storage { if (reinterpret_cast(sa) != this) { memset(this,0,sizeof(InetAddress)); - memcpy(this,sa,sizeof(struct sockaddr_in6)); + ZT_FAST_MEMCPY(this,sa,sizeof(struct sockaddr_in6)); } return *this; } @@ -175,10 +175,10 @@ struct InetAddress : public sockaddr_storage memset(this,0,sizeof(InetAddress)); switch(sa.sa_family) { case AF_INET: - memcpy(this,&sa,sizeof(struct sockaddr_in)); + ZT_FAST_MEMCPY(this,&sa,sizeof(struct sockaddr_in)); break; case AF_INET6: - memcpy(this,&sa,sizeof(struct sockaddr_in6)); + ZT_FAST_MEMCPY(this,&sa,sizeof(struct sockaddr_in6)); break; } } @@ -191,10 +191,10 @@ struct InetAddress : public sockaddr_storage memset(this,0,sizeof(InetAddress)); switch(sa->sa_family) { case AF_INET: - memcpy(this,sa,sizeof(struct sockaddr_in)); + ZT_FAST_MEMCPY(this,sa,sizeof(struct sockaddr_in)); break; case AF_INET6: - memcpy(this,sa,sizeof(struct sockaddr_in6)); + ZT_FAST_MEMCPY(this,sa,sizeof(struct sockaddr_in6)); break; } } @@ -388,7 +388,7 @@ struct InetAddress : public sockaddr_storage break; case AF_INET6: r.ss_family = AF_INET6; - memcpy(reinterpret_cast(&r)->sin6_addr.s6_addr,reinterpret_cast(this)->sin6_addr.s6_addr,16); + ZT_FAST_MEMCPY(reinterpret_cast(&r)->sin6_addr.s6_addr,reinterpret_cast(this)->sin6_addr.s6_addr,16); break; } return r; @@ -537,12 +537,12 @@ struct InetAddress : public sockaddr_storage return (unsigned int)(b.template at(p) + 3); // other addresses begin with 16-bit non-inclusive length case 0x04: ss_family = AF_INET; - memcpy(&(reinterpret_cast(this)->sin_addr.s_addr),b.field(p,4),4); p += 4; + ZT_FAST_MEMCPY(&(reinterpret_cast(this)->sin_addr.s_addr),b.field(p,4),4); p += 4; reinterpret_cast(this)->sin_port = Utils::hton(b.template at(p)); p += 2; break; case 0x06: ss_family = AF_INET6; - memcpy(reinterpret_cast(this)->sin6_addr.s6_addr,b.field(p,16),16); p += 16; + ZT_FAST_MEMCPY(reinterpret_cast(this)->sin6_addr.s6_addr,b.field(p,16),16); p += 16; reinterpret_cast(this)->sin_port = Utils::hton(b.template at(p)); p += 2; break; default: diff --git a/node/Network.cpp b/node/Network.cpp index a9e8539e..e8e91174 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -983,7 +983,7 @@ uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Add return false; c->haveChunkIds[c->haveChunks++] = chunkId; - memcpy(c->data.unsafeData() + chunkIndex,chunkData,chunkLen); + ZT_FAST_MEMCPY(c->data.unsafeData() + chunkIndex,chunkData,chunkLen); c->haveBytes += chunkLen; if (c->haveBytes == totalLength) { @@ -1385,7 +1385,7 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const ec->assignedAddressCount = 0; for(unsigned int i=0;iassignedAddresses[i]),&(_config.staticIps[i]),sizeof(struct sockaddr_storage)); + ZT_FAST_MEMCPY(&(ec->assignedAddresses[i]),&(_config.staticIps[i]),sizeof(struct sockaddr_storage)); ++ec->assignedAddressCount; } else { memset(&(ec->assignedAddresses[i]),0,sizeof(struct sockaddr_storage)); @@ -1395,7 +1395,7 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const ec->routeCount = 0; for(unsigned int i=0;iroutes[i]),&(_config.routes[i]),sizeof(ZT_VirtualNetworkRoute)); + ZT_FAST_MEMCPY(&(ec->routes[i]),&(_config.routes[i]),sizeof(ZT_VirtualNetworkRoute)); ++ec->routeCount; } else { memset(&(ec->routes[i]),0,sizeof(ZT_VirtualNetworkRoute)); diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp index bb48e6aa..19823e24 100644 --- a/node/NetworkConfig.hpp +++ b/node/NetworkConfig.hpp @@ -234,12 +234,12 @@ public: NetworkConfig(const NetworkConfig &nc) { - memcpy(this,&nc,sizeof(NetworkConfig)); + ZT_FAST_MEMCPY(this,&nc,sizeof(NetworkConfig)); } inline NetworkConfig &operator=(const NetworkConfig &nc) { - memcpy(this,&nc,sizeof(NetworkConfig)); + ZT_FAST_MEMCPY(this,&nc,sizeof(NetworkConfig)); return *this; } diff --git a/node/Node.cpp b/node/Node.cpp index ef8925d5..8d8f5ca0 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -66,7 +66,7 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64 { if (callbacks->version != 0) throw ZT_EXCEPTION_INVALID_ARGUMENT; - memcpy(&_cb,callbacks,sizeof(ZT_Node_Callbacks)); + ZT_FAST_MEMCPY(&_cb,callbacks,sizeof(ZT_Node_Callbacks)); // Initialize non-cryptographic PRNG from a good random source Utils::getSecureRandom((void *)_prngState,sizeof(_prngState)); @@ -441,7 +441,7 @@ ZT_PeerList *Node::peers() const SharedPtr bestp(pi->second->getBestPath(_now,false)); p->pathCount = 0; for(std::vector< SharedPtr >::iterator path(paths.begin());path!=paths.end();++path) { - memcpy(&(p->paths[p->pathCount].address),&((*path)->address()),sizeof(struct sockaddr_storage)); + ZT_FAST_MEMCPY(&(p->paths[p->pathCount].address),&((*path)->address()),sizeof(struct sockaddr_storage)); p->paths[p->pathCount].lastSend = (*path)->lastOut(); p->paths[p->pathCount].lastReceive = (*path)->lastIn(); p->paths[p->pathCount].trustedPathId = RR->topology->getOutboundPathTrust((*path)->address()); diff --git a/node/OutboundMulticast.cpp b/node/OutboundMulticast.cpp index 04ba2c2a..9aa44736 100644 --- a/node/OutboundMulticast.cpp +++ b/node/OutboundMulticast.cpp @@ -78,7 +78,7 @@ void OutboundMulticast::init( if (!disableCompression) _packet.compress(); - memcpy(_frameData,payload,_frameLen); + ZT_FAST_MEMCPY(_frameData,payload,_frameLen); } void OutboundMulticast::sendOnly(const RuntimeEnvironment *RR,void *tPtr,const Address &toAddr) diff --git a/node/Packet.cpp b/node/Packet.cpp index d3f7dfd6..af42cda5 100644 --- a/node/Packet.cpp +++ b/node/Packet.cpp @@ -387,27 +387,27 @@ static void LZ4_write32(void* memPtr, U32 value) { ((unalign*)memPtr)->u32 = val static inline U16 LZ4_read16(const void* memPtr) { - U16 val; memcpy(&val, memPtr, sizeof(val)); return val; + U16 val; ZT_FAST_MEMCPY(&val, memPtr, sizeof(val)); return val; } static inline U32 LZ4_read32(const void* memPtr) { - U32 val; memcpy(&val, memPtr, sizeof(val)); return val; + U32 val; ZT_FAST_MEMCPY(&val, memPtr, sizeof(val)); return val; } static inline reg_t LZ4_read_ARCH(const void* memPtr) { - reg_t val; memcpy(&val, memPtr, sizeof(val)); return val; + reg_t val; ZT_FAST_MEMCPY(&val, memPtr, sizeof(val)); return val; } static inline void LZ4_write16(void* memPtr, U16 value) { - memcpy(memPtr, &value, sizeof(value)); + ZT_FAST_MEMCPY(memPtr, &value, sizeof(value)); } static inline void LZ4_write32(void* memPtr, U32 value) { - memcpy(memPtr, &value, sizeof(value)); + ZT_FAST_MEMCPY(memPtr, &value, sizeof(value)); } #endif /* LZ4_FORCE_MEMORY_ACCESS */ @@ -435,7 +435,7 @@ static inline void LZ4_writeLE16(void* memPtr, U16 value) static inline void LZ4_copy8(void* dst, const void* src) { - memcpy(dst,src,8); + ZT_FAST_MEMCPY(dst,src,8); } /* customized variant of memcpy, which can overwrite up to 8 bytes beyond dstEnd */ @@ -830,7 +830,7 @@ _last_literals: } else { *op++ = (BYTE)(lastRun< oend))) goto _output_error; /* Error : input must be consumed */ } - memcpy(op, ip, length); + ZT_FAST_MEMCPY(op, ip, length); ip += length; op += length; break; /* Necessarily EOF, due to parsing restrictions */ @@ -995,14 +995,14 @@ FORCE_INLINE int LZ4_decompress_generic( /* match encompass external dictionary and current block */ size_t const copySize = (size_t)(lowPrefix-match); size_t const restSize = length - copySize; - memcpy(op, dictEnd - copySize, copySize); + ZT_FAST_MEMCPY(op, dictEnd - copySize, copySize); op += copySize; if (restSize > (size_t)(op-lowPrefix)) { /* overlap copy */ BYTE* const endOfMatch = op + restSize; const BYTE* copyFrom = lowPrefix; while (op < endOfMatch) *op++ = *copyFrom++; } else { - memcpy(op, lowPrefix, restSize); + ZT_FAST_MEMCPY(op, lowPrefix, restSize); op += restSize; } } continue; @@ -1017,7 +1017,7 @@ FORCE_INLINE int LZ4_decompress_generic( op[2] = match[2]; op[3] = match[3]; match += dec32table[offset]; - memcpy(op+4, match, 4); + ZT_FAST_MEMCPY(op+4, match, 4); match -= dec64; } else { LZ4_copy8(op, match); match+=8; } op += 8; @@ -1095,7 +1095,7 @@ void Packet::armor(const void *key,bool encryptPayload,unsigned int counter) s20.crypt12(payload,payload,payloadLen); uint64_t mac[2]; Poly1305::compute(mac,payload,payloadLen,macKey); - memcpy(data + ZT_PACKET_IDX_MAC,mac,8); + ZT_FAST_MEMCPY(data + ZT_PACKET_IDX_MAC,mac,8); } } @@ -1167,7 +1167,7 @@ bool Packet::compress() if ((cl > 0)&&(cl < pl)) { data[ZT_PACKET_IDX_VERB] |= (char)ZT_PROTO_VERB_FLAG_COMPRESSED; setSize((unsigned int)cl + ZT_PACKET_IDX_PAYLOAD); - memcpy(data + ZT_PACKET_IDX_PAYLOAD,buf,cl); + ZT_FAST_MEMCPY(data + ZT_PACKET_IDX_PAYLOAD,buf,cl); return true; } } @@ -1187,7 +1187,7 @@ bool Packet::uncompress() int ucl = LZ4_decompress_safe((const char *)data + ZT_PACKET_IDX_PAYLOAD,buf,compLen,sizeof(buf)); if ((ucl > 0)&&(ucl <= (int)(capacity() - ZT_PACKET_IDX_PAYLOAD))) { setSize((unsigned int)ucl + ZT_PACKET_IDX_PAYLOAD); - memcpy(data + ZT_PACKET_IDX_PAYLOAD,buf,ucl); + ZT_FAST_MEMCPY(data + ZT_PACKET_IDX_PAYLOAD,buf,ucl); } else { return false; } diff --git a/node/Path.hpp b/node/Path.hpp index ab52ced6..008b05c5 100644 --- a/node/Path.hpp +++ b/node/Path.hpp @@ -73,10 +73,10 @@ public: _k[1] = (uint64_t)reinterpret_cast(&r)->sin_port; _k[2] = (uint64_t)l; } else if (r.ss_family == AF_INET6) { - memcpy(_k,reinterpret_cast(&r)->sin6_addr.s6_addr,16); + ZT_FAST_MEMCPY(_k,reinterpret_cast(&r)->sin6_addr.s6_addr,16); _k[2] = ((uint64_t)reinterpret_cast(&r)->sin6_port << 32) ^ (uint64_t)l; } else { - memcpy(_k,&r,std::min(sizeof(_k),sizeof(InetAddress))); + ZT_FAST_MEMCPY(_k,&r,std::min(sizeof(_k),sizeof(InetAddress))); _k[2] += (uint64_t)l; } } diff --git a/node/Revocation.hpp b/node/Revocation.hpp index 7f7498bb..4a18914f 100644 --- a/node/Revocation.hpp +++ b/node/Revocation.hpp @@ -166,7 +166,7 @@ public: if (b[p++] == 1) { if (b.template at(p) == ZT_C25519_SIGNATURE_LEN) { p += 2; - memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); + ZT_FAST_MEMCPY(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); p += ZT_C25519_SIGNATURE_LEN; } else throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN; } else { diff --git a/node/Tag.hpp b/node/Tag.hpp index fc1377de..394c7be6 100644 --- a/node/Tag.hpp +++ b/node/Tag.hpp @@ -163,7 +163,7 @@ public: if (b.template at(p) != ZT_C25519_SIGNATURE_LEN) throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN; p += 2; - memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); p += ZT_C25519_SIGNATURE_LEN; + ZT_FAST_MEMCPY(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); p += ZT_C25519_SIGNATURE_LEN; } else { p += 2 + b.template at(p); } diff --git a/node/Utils.hpp b/node/Utils.hpp index 87584fcf..20108e27 100644 --- a/node/Utils.hpp +++ b/node/Utils.hpp @@ -40,6 +40,44 @@ #include "Constants.hpp" +// So it's 2017 and this still helps on most Linux versions. It shouldn't but it does. Go figure. +#if defined(__LINUX__) && ((defined(_MSC_VER) || defined(__GNUC__)) && (defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) || defined(__AMD64__) || defined(_M_X64))) +#include +static inline void ZT_FAST_MEMCPY(void *a,const void *b,unsigned long k) +{ + char *aa = reinterpret_cast(a); + const char *bb = reinterpret_cast(b); + while (likely(k >= 128)) { + __m128i t1 = _mm_loadu_si128(reinterpret_cast(bb)); bb += 16; + __m128i t2 = _mm_loadu_si128(reinterpret_cast(bb)); bb += 16; + __m128i t3 = _mm_loadu_si128(reinterpret_cast(bb)); bb += 16; + __m128i t4 = _mm_loadu_si128(reinterpret_cast(bb)); bb += 16; + _mm_storeu_si128(reinterpret_cast<__m128i *>(aa),t1); aa += 16; + _mm_storeu_si128(reinterpret_cast<__m128i *>(aa),t2); aa += 16; + _mm_storeu_si128(reinterpret_cast<__m128i *>(aa),t3); aa += 16; + _mm_storeu_si128(reinterpret_cast<__m128i *>(aa),t4); aa += 16; + __m128i t5 = _mm_loadu_si128(reinterpret_cast(bb)); bb += 16; + __m128i t6 = _mm_loadu_si128(reinterpret_cast(bb)); bb += 16; + __m128i t7 = _mm_loadu_si128(reinterpret_cast(bb)); bb += 16; + __m128i t8 = _mm_loadu_si128(reinterpret_cast(bb)); bb += 16; + _mm_storeu_si128(reinterpret_cast<__m128i *>(aa),t5); aa += 16; + _mm_storeu_si128(reinterpret_cast<__m128i *>(aa),t6); aa += 16; + _mm_storeu_si128(reinterpret_cast<__m128i *>(aa),t7); aa += 16; + _mm_storeu_si128(reinterpret_cast<__m128i *>(aa),t8); aa += 16; + k -= 128; + } + while (likely(k >= 16)) { + __m128i t1 = _mm_loadu_si128(reinterpret_cast(bb)); bb += 16; + _mm_storeu_si128(reinterpret_cast<__m128i *>(aa),t1); aa += 16; + k -= 16; + } + for(unsigned long i=0;i(p); p += 8; _ts = b.template at(p); p += 8; - memcpy(_updatesMustBeSignedBy.data,b.field(p,ZT_C25519_PUBLIC_KEY_LEN),ZT_C25519_PUBLIC_KEY_LEN); p += ZT_C25519_PUBLIC_KEY_LEN; - memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); p += ZT_C25519_SIGNATURE_LEN; + ZT_FAST_MEMCPY(_updatesMustBeSignedBy.data,b.field(p,ZT_C25519_PUBLIC_KEY_LEN),ZT_C25519_PUBLIC_KEY_LEN); p += ZT_C25519_PUBLIC_KEY_LEN; + ZT_FAST_MEMCPY(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); p += ZT_C25519_SIGNATURE_LEN; const unsigned int numRoots = (unsigned int)b[p++]; if (numRoots > ZT_WORLD_MAX_ROOTS) throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW; diff --git a/selftest.cpp b/selftest.cpp index c3b8ce2f..86894564 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -660,6 +660,50 @@ static int testOther() std::cout << " " << InetAddress("").toString(buf); std::cout << std::endl; + std::cout << "[other] Benchmarking memcpy... "; std::cout.flush(); + { + unsigned char *bb = (unsigned char *)::malloc(1234567); + unsigned char *cc = (unsigned char *)::malloc(1234567); + for(unsigned int i=0;i<1234567;++i) + bb[i] = (unsigned char)i; + double bytes = 0.0; + uint64_t start = OSUtils::now(); + for(unsigned int i=0;i<20000;++i) { + ++bb[i]; + ++bb[i+1]; + memcpy(cc,bb,1234567); + bytes += 1234567.0; + } + if (cc[0] != bb[0]) + abort(); + uint64_t end = OSUtils::now(); + std::cout << ((bytes / 1048576.0) / ((long double)(end - start) / 1024.0)) << " MiB/second" << std::endl; + ::free((void *)bb); + ::free((void *)cc); + } + + std::cout << "[other] Benchmarking ZT_FAST_MEMCPY... "; std::cout.flush(); + { + unsigned char *bb = (unsigned char *)::malloc(1234567); + unsigned char *cc = (unsigned char *)::malloc(1234567); + for(unsigned int i=0;i<1234567;++i) + bb[i] = (unsigned char)i; + double bytes = 0.0; + uint64_t start = OSUtils::now(); + for(unsigned int i=0;i<20000;++i) { + ++bb[0]; + ++bb[1234566]; + ZT_FAST_MEMCPY(cc,bb,1234567); + bytes += 1234567.0; + } + if (cc[0] != bb[0]) + abort(); + uint64_t end = OSUtils::now(); + std::cout << ((bytes / 1048576.0) / ((long double)(end - start) / 1024.0)) << " MiB/second" << std::endl; + ::free((void *)bb); + ::free((void *)cc); + } + #if 0 std::cout << "[other] Testing Hashtable... "; std::cout.flush(); { diff --git a/service/OneService.cpp b/service/OneService.cpp index b30dc390..3ca75362 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1971,7 +1971,7 @@ public: // After setting up tap, fall through to CONFIG_UPDATE since we also want to do this... case ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE: - memcpy(&(n.config),nwc,sizeof(ZT_VirtualNetworkConfig)); + ZT_FAST_MEMCPY(&(n.config),nwc,sizeof(ZT_VirtualNetworkConfig)); if (n.tap) { // sanity check #ifdef __WINDOWS__ // wait for up to 5 seconds for the WindowsEthernetTap to actually be initialized @@ -2298,7 +2298,7 @@ public: else return 0; const std::vector *l = lh->get(ztaddr); if ((l)&&(l->size() > 0)) { - memcpy(result,&((*l)[(unsigned long)_node->prng() % l->size()]),sizeof(struct sockaddr_storage)); + ZT_FAST_MEMCPY(result,&((*l)[(unsigned long)_node->prng() % l->size()]),sizeof(struct sockaddr_storage)); return 1; } else return 0; } -- cgit v1.2.3 From f7b3ffe8a0ddab78a547560d164223747c93c4db Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Fri, 5 Jan 2018 17:10:59 -0800 Subject: Commented out block which ignores added routes if there already exists an IP in the route's range. Attempted fix for #600 --- osdep/ManagedRoute.cpp | 5 +++++ service/OneService.cpp | 2 ++ 2 files changed, 7 insertions(+) (limited to 'service/OneService.cpp') diff --git a/osdep/ManagedRoute.cpp b/osdep/ManagedRoute.cpp index a3746572..2289b23a 100644 --- a/osdep/ManagedRoute.cpp +++ b/osdep/ManagedRoute.cpp @@ -480,6 +480,10 @@ bool ManagedRoute::sync() // Detect routes previously applied by ZT that don't exist in the system's route list. Re-apply these. // NOTE: The following block was added in reaction to the macOS High Sierra 10.13.2 disappearing // route issue. This comment should be removed once we're sure this block doesn't have any side-effects. + /* + + // Commented out temporarily to test more generalized fix + bool found = false; std::vector<_RTE> currRoutes(_getRTEs(_target,false)); for(std::vector<_RTE>::iterator r(currRoutes.begin());r!=currRoutes.end();++r) { @@ -496,6 +500,7 @@ bool ManagedRoute::sync() rt = _applied.find(rightt); _applied.erase(rt, _applied.end()); } + */ if (!_applied.count(leftt)) { _applied[leftt] = false; // not ifscoped diff --git a/service/OneService.cpp b/service/OneService.cpp index 3ca75362..a21c1c08 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1610,12 +1610,14 @@ public: bool haveRoute = false; // Ignore routes implied by local managed IPs since adding the IP adds the route + /* for(std::vector::iterator ip(n.managedIps.begin());ip!=n.managedIps.end();++ip) { if ((target->netmaskBits() == ip->netmaskBits())&&(target->containsAddress(*ip))) { haveRoute = true; break; } } + */ if (haveRoute) continue; -- cgit v1.2.3 From 9c7ee5a21e2875baf3b1643101f660f41c903124 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 8 Jan 2018 13:06:24 -0800 Subject: Tear out old "link quality" stuff since it is not currently used and will be done differently. --- include/ZeroTierOne.h | 5 ----- node/IncomingPacket.cpp | 26 ++++++++++----------- node/Node.cpp | 7 +++--- node/Packet.cpp | 6 ++--- node/Packet.hpp | 9 +------- node/Path.hpp | 60 ------------------------------------------------- node/Peer.cpp | 29 +++++++++++------------- node/Peer.hpp | 8 +++---- node/Switch.cpp | 4 ++-- one.cpp | 3 +-- service/OneService.cpp | 1 - 11 files changed, 38 insertions(+), 120 deletions(-) (limited to 'service/OneService.cpp') diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 04c4b83b..93a91933 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -1183,11 +1183,6 @@ typedef struct */ uint64_t trustedPathId; - /** - * Path link quality from 0 to 255 (always 255 if peer does not support) - */ - int linkQuality; - /** * Is path expired? */ diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index d44e3b54..38fd3aa0 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -241,7 +241,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool outp.append((uint8_t)Packet::VERB_HELLO); outp.append((uint64_t)pid); outp.append((uint8_t)Packet::ERROR_IDENTITY_COLLISION); - outp.armor(key,true,_path->nextOutgoingCounter()); + outp.armor(key,true); _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); } else { RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,pid,fromAddress,hops(),"invalid MAC"); @@ -391,7 +391,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool } outp.setAt(worldUpdateSizeAt,(uint16_t)(outp.size() - (worldUpdateSizeAt + 2))); - outp.armor(peer->key(),true,_path->nextOutgoingCounter()); + outp.armor(peer->key(),true); _path->send(RR,tPtr,outp.data(),outp.size(),now); peer->setRemoteVersion(protoVersion,vMajor,vMinor,vRevision); // important for this to go first so received() knows the version @@ -538,7 +538,7 @@ bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,void *tPtr,const Shar } if (count > 0) { - outp.armor(peer->key(),true,_path->nextOutgoingCounter()); + outp.armor(peer->key(),true); _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); } @@ -560,7 +560,7 @@ bool IncomingPacket::_doRENDEZVOUS(const RuntimeEnvironment *RR,void *tPtr,const if (RR->node->shouldUsePathForZeroTierTraffic(tPtr,with,_path->localSocket(),atAddr)) { const uint64_t junk = RR->node->prng(); RR->node->putPacket(tPtr,_path->localSocket(),atAddr,&junk,4,2); // send low-TTL junk packet to 'open' local NAT(s) and stateful firewalls - rendezvousWith->attemptToContactAt(tPtr,_path->localSocket(),atAddr,RR->node->now(),false,0); + rendezvousWith->attemptToContactAt(tPtr,_path->localSocket(),atAddr,RR->node->now(),false); } } } @@ -669,7 +669,7 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,void *tPtr,const outp.append((uint8_t)Packet::VERB_EXT_FRAME); outp.append((uint64_t)packetId()); outp.append((uint64_t)nwid); - outp.armor(peer->key(),true,_path->nextOutgoingCounter()); + outp.armor(peer->key(),true); _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); } @@ -692,7 +692,7 @@ bool IncomingPacket::_doECHO(const RuntimeEnvironment *RR,void *tPtr,const Share outp.append((uint64_t)pid); if (size() > ZT_PACKET_IDX_PAYLOAD) outp.append(reinterpret_cast(data()) + ZT_PACKET_IDX_PAYLOAD,size() - ZT_PACKET_IDX_PAYLOAD); - outp.armor(peer->key(),true,_path->nextOutgoingCounter()); + outp.armor(peer->key(),true); _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); peer->received(tPtr,_path,hops(),pid,Packet::VERB_ECHO,0,Packet::VERB_NOP,false,0); @@ -885,7 +885,7 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,void outp.append(requestPacketId); outp.append((unsigned char)Packet::ERROR_UNSUPPORTED_OPERATION); outp.append(nwid); - outp.armor(peer->key(),true,_path->nextOutgoingCounter()); + outp.armor(peer->key(),true); _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); } @@ -905,7 +905,7 @@ bool IncomingPacket::_doNETWORK_CONFIG(const RuntimeEnvironment *RR,void *tPtr,c outp.append((uint64_t)packetId()); outp.append((uint64_t)network->id()); outp.append((uint64_t)configUpdateId); - outp.armor(peer->key(),true,_path->nextOutgoingCounter()); + outp.armor(peer->key(),true); _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); } } @@ -948,7 +948,7 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,void *tPtr outp.append((uint32_t)mg.adi()); const unsigned int gatheredLocally = RR->mc->gather(peer->address(),nwid,mg,outp,gatherLimit); if (gatheredLocally > 0) { - outp.armor(peer->key(),true,_path->nextOutgoingCounter()); + outp.armor(peer->key(),true); _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); } } @@ -1043,7 +1043,7 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr, outp.append((uint32_t)to.adi()); outp.append((unsigned char)0x02); // flag 0x02 = contains gather results if (RR->mc->gather(peer->address(),nwid,to,outp,gatherLimit)) { - outp.armor(peer->key(),true,_path->nextOutgoingCounter()); + outp.armor(peer->key(),true); _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); } } @@ -1094,7 +1094,7 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPt if ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) != 0) { peer->clusterRedirect(tPtr,_path,a,now); } else if (++countPerScope[(int)a.ipScope()][0] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) { - peer->attemptToContactAt(tPtr,InetAddress(),a,now,false,0); + peer->attemptToContactAt(tPtr,InetAddress(),a,now,false); } } } break; @@ -1108,7 +1108,7 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPt if ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) != 0) { peer->clusterRedirect(tPtr,_path,a,now); } else if (++countPerScope[(int)a.ipScope()][1] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) { - peer->attemptToContactAt(tPtr,InetAddress(),a,now,false,0); + peer->attemptToContactAt(tPtr,InetAddress(),a,now,false); } } } break; @@ -1170,7 +1170,7 @@ void IncomingPacket::_sendErrorNeedCredentials(const RuntimeEnvironment *RR,void outp.append(packetId()); outp.append((uint8_t)Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE); outp.append(nwid); - outp.armor(peer->key(),true,_path->nextOutgoingCounter()); + outp.armor(peer->key(),true); _path->send(RR,tPtr,outp.data(),outp.size(),now); } } diff --git a/node/Node.cpp b/node/Node.cpp index 8d8f5ca0..d4b69689 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -202,7 +202,7 @@ public: for(unsigned long k=0,ptr=(unsigned long)RR->node->prng();k<(unsigned long)upstreamStableEndpoints->size();++k) { const InetAddress &addr = (*upstreamStableEndpoints)[ptr++ % upstreamStableEndpoints->size()]; if (addr.ss_family == AF_INET) { - p->sendHELLO(_tPtr,-1,addr,_now,0); + p->sendHELLO(_tPtr,-1,addr,_now); contacted = true; break; } @@ -213,7 +213,7 @@ public: for(unsigned long k=0,ptr=(unsigned long)RR->node->prng();k<(unsigned long)upstreamStableEndpoints->size();++k) { const InetAddress &addr = (*upstreamStableEndpoints)[ptr++ % upstreamStableEndpoints->size()]; if (addr.ss_family == AF_INET6) { - p->sendHELLO(_tPtr,-1,addr,_now,0); + p->sendHELLO(_tPtr,-1,addr,_now); contacted = true; break; } @@ -225,7 +225,7 @@ public: if ((!contacted)&&(_bestCurrentUpstream)) { const SharedPtr up(_bestCurrentUpstream->getBestPath(_now,true)); if (up) - p->sendHELLO(_tPtr,up->localSocket(),up->address(),_now,up->nextOutgoingCounter()); + p->sendHELLO(_tPtr,up->localSocket(),up->address(),_now); } lastReceiveFromUpstream = std::max(p->lastReceive(),lastReceiveFromUpstream); @@ -445,7 +445,6 @@ ZT_PeerList *Node::peers() const p->paths[p->pathCount].lastSend = (*path)->lastOut(); p->paths[p->pathCount].lastReceive = (*path)->lastIn(); p->paths[p->pathCount].trustedPathId = RR->topology->getOutboundPathTrust((*path)->address()); - p->paths[p->pathCount].linkQuality = (int)(*path)->linkQuality(); p->paths[p->pathCount].expired = 0; p->paths[p->pathCount].preferred = ((*path) == bestp) ? 1 : 0; ++p->pathCount; diff --git a/node/Packet.cpp b/node/Packet.cpp index af42cda5..cb9e1e0f 100644 --- a/node/Packet.cpp +++ b/node/Packet.cpp @@ -1061,18 +1061,16 @@ static inline int LZ4_decompress_safe(const char* source, char* dest, int compre const unsigned char Packet::ZERO_KEY[32] = { 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,0,0 }; -void Packet::armor(const void *key,bool encryptPayload,unsigned int counter) +void Packet::armor(const void *key,bool encryptPayload) { uint8_t mangledKey[32]; uint8_t *const data = reinterpret_cast(unsafeData()); - // Mask least significant 3 bits of packet ID with counter to embed packet send counter for QoS use - data[7] = (data[7] & 0xf8) | (uint8_t)(counter & 0x07); - // Set flag now, since it affects key mangle function setCipher(encryptPayload ? ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012 : ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE); _salsa20MangleKey((const unsigned char *)key,mangledKey); + if (ZT_HAS_FAST_CRYPTO()) { const unsigned int encryptLen = (encryptPayload) ? (size() - ZT_PACKET_IDX_VERB) : 0; uint64_t keyStream[(ZT_PROTO_MAX_PACKET_LENGTH + 64 + 8) / 8]; diff --git a/node/Packet.hpp b/node/Packet.hpp index cc055347..8cfb5492 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -68,7 +68,6 @@ * + Tags and Capabilities * + Inline push of CertificateOfMembership deprecated * 9 - 1.2.0 ... CURRENT - * + In-band encoding of packet counter for link quality measurement */ #define ZT_PROTO_VERSION 9 @@ -1202,11 +1201,6 @@ public: */ inline uint64_t packetId() const { return at(ZT_PACKET_IDX_IV); } - /** - * @return Value of link quality counter extracted from this packet's ID, range 0 to 7 (3 bits) - */ - inline unsigned int linkQualityCounter() const { return (unsigned int)(reinterpret_cast(data())[7] & 0x07); } - /** * Set packet verb * @@ -1237,9 +1231,8 @@ public: * * @param key 32-byte key * @param encryptPayload If true, encrypt packet payload, else just MAC - * @param counter Packet send counter for destination peer -- only least significant 3 bits are used */ - void armor(const void *key,bool encryptPayload,unsigned int counter); + void armor(const void *key,bool encryptPayload); /** * Verify and (if encrypted) decrypt packet diff --git a/node/Path.hpp b/node/Path.hpp index 008b05c5..6b4b9915 100644 --- a/node/Path.hpp +++ b/node/Path.hpp @@ -94,36 +94,22 @@ public: _lastOut(0), _lastIn(0), _lastTrustEstablishedPacketReceived(0), - _incomingLinkQualityFastLog(0xffffffffffffffffULL), _localSocket(-1), - _incomingLinkQualitySlowLogPtr(0), - _incomingLinkQualitySlowLogCounter(-64), // discard first fast log - _incomingLinkQualityPreviousPacketCounter(0), - _outgoingPacketCounter(0), _latency(0xffff), _addr(), _ipScope(InetAddress::IP_SCOPE_NONE) { - for(int i=0;i<(int)sizeof(_incomingLinkQualitySlowLog);++i) - _incomingLinkQualitySlowLog[i] = ZT_PATH_LINK_QUALITY_MAX; } Path(const int64_t localSocket,const InetAddress &addr) : _lastOut(0), _lastIn(0), _lastTrustEstablishedPacketReceived(0), - _incomingLinkQualityFastLog(0xffffffffffffffffULL), _localSocket(localSocket), - _incomingLinkQualitySlowLogPtr(0), - _incomingLinkQualitySlowLogCounter(-64), // discard first fast log - _incomingLinkQualityPreviousPacketCounter(0), - _outgoingPacketCounter(0), _latency(0xffff), _addr(addr), _ipScope(addr.ipScope()) { - for(int i=0;i<(int)sizeof(_incomingLinkQualitySlowLog);++i) - _incomingLinkQualitySlowLog[i] = ZT_PATH_LINK_QUALITY_MAX; } /** @@ -133,39 +119,6 @@ public: */ inline void received(const uint64_t t) { _lastIn = t; } - /** - * Update link quality using a counter from an incoming packet (or packet head in fragmented case) - * - * @param counter Packet link quality counter (range 0 to 7, must not have other bits set) - */ - inline void updateLinkQuality(const unsigned int counter) - { - const unsigned int prev = _incomingLinkQualityPreviousPacketCounter; - _incomingLinkQualityPreviousPacketCounter = counter; - const uint64_t fl = (_incomingLinkQualityFastLog = ((_incomingLinkQualityFastLog << 1) | (uint64_t)(prev == ((counter - 1) & 0x7)))); - if (++_incomingLinkQualitySlowLogCounter >= 64) { - _incomingLinkQualitySlowLogCounter = 0; - _incomingLinkQualitySlowLog[_incomingLinkQualitySlowLogPtr++ % sizeof(_incomingLinkQualitySlowLog)] = (uint8_t)Utils::countBits(fl); - } - } - - /** - * @return Link quality from 0 (min) to 255 (max) - */ - inline unsigned int linkQuality() const - { - unsigned long slsize = _incomingLinkQualitySlowLogPtr; - if (slsize > (unsigned long)sizeof(_incomingLinkQualitySlowLog)) - slsize = (unsigned long)sizeof(_incomingLinkQualitySlowLog); - else if (!slsize) - return 255; // ZT_PATH_LINK_QUALITY_MAX - unsigned long lq = 0; - for(unsigned long i=0;i= 255) ? 255 : lq); - } - /** * Set time last trusted packet was received (done in Peer::received()) */ @@ -313,27 +266,14 @@ public: */ inline int64_t lastTrustEstablishedPacketReceived() const { return _lastTrustEstablishedPacketReceived; } - /** - * Return and increment outgoing packet counter (used with Packet::armor()) - * - * @return Next value that should be used for outgoing packet counter (only least significant 3 bits are used) - */ - inline unsigned int nextOutgoingCounter() { return _outgoingPacketCounter++; } - private: volatile int64_t _lastOut; volatile int64_t _lastIn; volatile int64_t _lastTrustEstablishedPacketReceived; - volatile uint64_t _incomingLinkQualityFastLog; int64_t _localSocket; - volatile unsigned long _incomingLinkQualitySlowLogPtr; - volatile signed int _incomingLinkQualitySlowLogCounter; - volatile unsigned int _incomingLinkQualityPreviousPacketCounter; - volatile unsigned int _outgoingPacketCounter; volatile unsigned int _latency; InetAddress _addr; InetAddress::IpScope _ipScope; // memoize this since it's a computed value checked often - volatile uint8_t _incomingLinkQualitySlowLog[32]; AtomicCounter __refCount; }; diff --git a/node/Peer.cpp b/node/Peer.cpp index fceef94f..6e46089f 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -95,9 +95,6 @@ void Peer::received( path->trustedPacketReceived(now); } - if (_vProto >= 9) - path->updateLinkQuality((unsigned int)(packetId & 7)); - if (hops == 0) { // If this is a direct packet (no hops), update existing paths or learn new ones @@ -161,7 +158,7 @@ void Peer::received( } if (attemptToContact) { - attemptToContactAt(tPtr,path->localSocket(),path->address(),now,true,path->nextOutgoingCounter()); + attemptToContactAt(tPtr,path->localSocket(),path->address(),now,true); path->sent(now); RR->t->peerConfirmingUnknownPath(tPtr,networkId,*this,path,packetId,verb); } @@ -226,7 +223,7 @@ void Peer::received( if (count) { outp.setAt(ZT_PACKET_IDX_PAYLOAD,(uint16_t)count); - outp.armor(_key,true,path->nextOutgoingCounter()); + outp.armor(_key,true); path->send(RR,tPtr,outp.data(),outp.size(),now); } } @@ -357,7 +354,7 @@ void Peer::introduce(void *const tPtr,const int64_t now,const SharedPtr &o outp.append((uint8_t)4); outp.append(other->_paths[theirs].p->address().rawIpData(),4); } - outp.armor(_key,true,_paths[mine].p->nextOutgoingCounter()); + outp.armor(_key,true); _paths[mine].p->send(RR,tPtr,outp.data(),outp.size(),now); } else { Packet outp(other->_id.address(),RR->identity.address(),Packet::VERB_RENDEZVOUS); @@ -371,7 +368,7 @@ void Peer::introduce(void *const tPtr,const int64_t now,const SharedPtr &o outp.append((uint8_t)4); outp.append(_paths[mine].p->address().rawIpData(),4); } - outp.armor(other->_key,true,other->_paths[theirs].p->nextOutgoingCounter()); + outp.armor(other->_key,true); other->_paths[theirs].p->send(RR,tPtr,outp.data(),outp.size(),now); } ++alt; @@ -379,7 +376,7 @@ void Peer::introduce(void *const tPtr,const int64_t now,const SharedPtr &o } } -void Peer::sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,int64_t now,unsigned int counter) +void Peer::sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,int64_t now) { Packet outp(_id.address(),RR->identity.address(),Packet::VERB_HELLO); @@ -415,22 +412,22 @@ void Peer::sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atA RR->node->expectReplyTo(outp.packetId()); if (atAddress) { - outp.armor(_key,false,counter); // false == don't encrypt full payload, but add MAC + outp.armor(_key,false); // false == don't encrypt full payload, but add MAC RR->node->putPacket(tPtr,localSocket,atAddress,outp.data(),outp.size()); } else { RR->sw->send(tPtr,outp,false); // false == don't encrypt full payload, but add MAC } } -void Peer::attemptToContactAt(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,int64_t now,bool sendFullHello,unsigned int counter) +void Peer::attemptToContactAt(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,int64_t now,bool sendFullHello) { if ( (!sendFullHello) && (_vProto >= 5) && (!((_vMajor == 1)&&(_vMinor == 1)&&(_vRevision == 0))) ) { Packet outp(_id.address(),RR->identity.address(),Packet::VERB_ECHO); RR->node->expectReplyTo(outp.packetId()); - outp.armor(_key,true,counter); + outp.armor(_key,true); RR->node->putPacket(tPtr,localSocket,atAddress,outp.data(),outp.size()); } else { - sendHELLO(tPtr,localSocket,atAddress,now,counter); + sendHELLO(tPtr,localSocket,atAddress,now); } } @@ -440,7 +437,7 @@ void Peer::tryMemorizedPath(void *tPtr,int64_t now) _lastTriedMemorizedPath = now; InetAddress mp; if (RR->node->externalPathLookup(tPtr,_id.address(),-1,mp)) - attemptToContactAt(tPtr,-1,mp,now,true,0); + attemptToContactAt(tPtr,-1,mp,now,true); } } @@ -470,7 +467,7 @@ unsigned int Peer::doPingAndKeepalive(void *tPtr,int64_t now) // Clean expired and reduced priority paths if ( ((now - _paths[i].lr) < ZT_PEER_PATH_EXPIRATION) && (_paths[i].priority == maxPriority) ) { if ((sendFullHello)||(_paths[i].p->needsHeartbeat(now))) { - attemptToContactAt(tPtr,_paths[i].p->localSocket(),_paths[i].p->address(),now,sendFullHello,_paths[i].p->nextOutgoingCounter()); + attemptToContactAt(tPtr,_paths[i].p->localSocket(),_paths[i].p->address(),now,sendFullHello); _paths[i].p->sent(now); sent |= (_paths[i].p->address().ss_family == AF_INET) ? 0x1 : 0x2; } @@ -495,7 +492,7 @@ void Peer::clusterRedirect(void *tPtr,const SharedPtr &originatingPath,con SharedPtr np(RR->topology->getPath(originatingPath->localSocket(),remoteAddress)); RR->t->peerRedirected(tPtr,0,*this,np); - attemptToContactAt(tPtr,originatingPath->localSocket(),remoteAddress,now,true,np->nextOutgoingCounter()); + attemptToContactAt(tPtr,originatingPath->localSocket(),remoteAddress,now,true); { Mutex::Lock _l(_paths_m); @@ -545,7 +542,7 @@ void Peer::resetWithinScope(void *tPtr,InetAddress::IpScope scope,int inetAddres for(unsigned int i=0;iaddress().ss_family == inetAddressFamily)&&(_paths[i].p->ipScope() == scope)) { - attemptToContactAt(tPtr,_paths[i].p->localSocket(),_paths[i].p->address(),now,false,_paths[i].p->nextOutgoingCounter()); + attemptToContactAt(tPtr,_paths[i].p->localSocket(),_paths[i].p->address(),now,false); _paths[i].p->sent(now); _paths[i].lr = 0; // path will not be used unless it speaks again } diff --git a/node/Peer.hpp b/node/Peer.hpp index 53b916ab..99728736 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -175,9 +175,8 @@ public: * @param localSocket Local source socket * @param atAddress Destination address * @param now Current time - * @param counter Outgoing packet counter */ - void sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,int64_t now,unsigned int counter); + void sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,int64_t now); /** * Send ECHO (or HELLO for older peers) to this peer at the given address @@ -189,9 +188,8 @@ public: * @param atAddress Destination address * @param now Current time * @param sendFullHello If true, always send a full HELLO instead of just an ECHO - * @param counter Outgoing packet counter */ - void attemptToContactAt(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,int64_t now,bool sendFullHello,unsigned int counter); + void attemptToContactAt(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,int64_t now,bool sendFullHello); /** * Try a memorized or statically defined path if any are known @@ -480,7 +478,7 @@ public: try { ptr += inaddr.deserialize(b,ptr); if (inaddr) - p->attemptToContactAt(tPtr,-1,inaddr,now,true,0); + p->attemptToContactAt(tPtr,-1,inaddr,now,true); } catch ( ... ) { break; } diff --git a/node/Switch.cpp b/node/Switch.cpp index 1958c43e..b2cab1d0 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -78,7 +78,7 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre if ((now - _lastBeaconResponse) >= 2500) { // limit rate of responses _lastBeaconResponse = now; Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NOP); - outp.armor(peer->key(),true,path->nextOutgoingCounter()); + outp.armor(peer->key(),true); path->send(RR,tPtr,outp.data(),outp.size(),now); } } @@ -670,7 +670,7 @@ bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt) if (trustedPathId) { packet.setTrusted(trustedPathId); } else { - packet.armor(peer->key(),encrypt,viaPath->nextOutgoingCounter()); + packet.armor(peer->key(),encrypt); } if (viaPath->send(RR,tPtr,packet.data(),chunkSize,now)) { diff --git a/one.cpp b/one.cpp index 48b5d9a2..a1238bb8 100644 --- a/one.cpp +++ b/one.cpp @@ -365,8 +365,7 @@ static int cli(int argc,char **argv) char tmp[256]; std::string addr = path["address"]; const int64_t now = OSUtils::now(); - const double lq = (path.count("linkQuality")) ? (double)path["linkQuality"] : -1.0; - OSUtils::ztsnprintf(tmp,sizeof(tmp),"%s;%lld;%lld;%1.2f",addr.c_str(),now - (int64_t)path["lastSend"],now - (int64_t)path["lastReceive"],lq); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"%s;%lld;%lld",addr.c_str(),now - (int64_t)path["lastSend"],now - (int64_t)path["lastReceive"]); bestPath = tmp; break; } diff --git a/service/OneService.cpp b/service/OneService.cpp index 3ca75362..686806b3 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -271,7 +271,6 @@ static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer) j["lastSend"] = (lastSend < 0) ? 0 : lastSend; j["lastReceive"] = (lastReceive < 0) ? 0 : lastReceive; j["trustedPathId"] = peer->paths[i].trustedPathId; - j["linkQuality"] = (double)peer->paths[i].linkQuality / (double)ZT_PATH_LINK_QUALITY_MAX; j["active"] = (bool)(peer->paths[i].expired == 0); j["expired"] = (bool)(peer->paths[i].expired != 0); j["preferred"] = (bool)(peer->paths[i].preferred != 0); -- cgit v1.2.3 From 65c07afe055e6d33a07ea6adf87aedcf564806a2 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 8 Jan 2018 14:33:28 -0800 Subject: Copyright updates for 2018. --- COPYING | 2 +- include/ZeroTierOne.h | 2 +- node/Address.hpp | 2 +- node/Array.hpp | 2 +- node/AtomicCounter.hpp | 2 +- node/Buffer.hpp | 2 +- node/C25519.hpp | 2 +- node/Capability.cpp | 2 +- node/Capability.hpp | 2 +- node/CertificateOfMembership.cpp | 2 +- node/CertificateOfMembership.hpp | 2 +- node/CertificateOfOwnership.cpp | 2 +- node/CertificateOfOwnership.hpp | 2 +- node/Constants.hpp | 2 +- node/Credential.hpp | 2 +- node/Dictionary.hpp | 2 +- node/Hashtable.hpp | 2 +- node/Identity.cpp | 2 +- node/Identity.hpp | 2 +- node/IncomingPacket.cpp | 2 +- node/IncomingPacket.hpp | 2 +- node/InetAddress.cpp | 2 +- node/InetAddress.hpp | 2 +- node/MAC.hpp | 2 +- node/Membership.cpp | 2 +- node/Membership.hpp | 2 +- node/MulticastGroup.hpp | 2 +- node/Multicaster.cpp | 2 +- node/Multicaster.hpp | 2 +- node/Mutex.hpp | 2 +- node/Network.cpp | 2 +- node/Network.hpp | 2 +- node/NetworkConfig.cpp | 2 +- node/NetworkConfig.hpp | 2 +- node/NetworkController.hpp | 2 +- node/Node.cpp | 2 +- node/Node.hpp | 2 +- node/NonCopyable.hpp | 2 +- node/OutboundMulticast.cpp | 2 +- node/OutboundMulticast.hpp | 2 +- node/Packet.cpp | 2 +- node/Packet.hpp | 2 +- node/Path.cpp | 2 +- node/Path.hpp | 2 +- node/Peer.cpp | 2 +- node/Peer.hpp | 2 +- node/Poly1305.hpp | 2 +- node/Revocation.cpp | 2 +- node/Revocation.hpp | 2 +- node/RuntimeEnvironment.hpp | 2 +- node/SHA512.hpp | 2 +- node/SelfAwareness.cpp | 2 +- node/SelfAwareness.hpp | 2 +- node/SharedPtr.hpp | 2 +- node/Switch.cpp | 2 +- node/Switch.hpp | 2 +- node/Tag.cpp | 2 +- node/Tag.hpp | 2 +- node/Topology.cpp | 2 +- node/Topology.hpp | 2 +- node/Trace.cpp | 2 +- node/Trace.hpp | 2 +- node/Utils.cpp | 2 +- node/Utils.hpp | 2 +- node/World.hpp | 2 +- one.cpp | 4 ++-- osdep/Arp.cpp | 2 +- osdep/Arp.hpp | 2 +- osdep/BSDEthernetTap.cpp | 2 +- osdep/BSDEthernetTap.hpp | 2 +- osdep/Binder.hpp | 2 +- osdep/BlockingQueue.hpp | 2 +- osdep/Http.cpp | 2 +- osdep/Http.hpp | 2 +- osdep/LinuxEthernetTap.cpp | 2 +- osdep/LinuxEthernetTap.hpp | 2 +- osdep/ManagedRoute.cpp | 2 +- osdep/ManagedRoute.hpp | 2 +- osdep/NeighborDiscovery.cpp | 2 +- osdep/NeighborDiscovery.hpp | 2 +- osdep/OSUtils.cpp | 2 +- osdep/OSUtils.hpp | 2 +- osdep/OSXEthernetTap.cpp | 2 +- osdep/OSXEthernetTap.hpp | 2 +- osdep/Phy.hpp | 2 +- osdep/PortMapper.cpp | 2 +- osdep/PortMapper.hpp | 2 +- osdep/TestEthernetTap.hpp | 2 +- osdep/Thread.hpp | 2 +- osdep/WindowsEthernetTap.cpp | 2 +- osdep/WindowsEthernetTap.hpp | 2 +- selftest.cpp | 2 +- service/OneService.cpp | 2 +- service/OneService.hpp | 2 +- service/SoftwareUpdater.cpp | 2 +- service/SoftwareUpdater.hpp | 2 +- version.h | 2 +- 97 files changed, 98 insertions(+), 98 deletions(-) (limited to 'service/OneService.cpp') diff --git a/COPYING b/COPYING index 23d42dfa..8008d3e0 100644 --- a/COPYING +++ b/COPYING @@ -1,5 +1,5 @@ ZeroTier One, an endpoint server for the ZeroTier virtual network layer. -Copyright © 2011–2016 ZeroTier, Inc. +Copyright © 2011–2018 ZeroTier, Inc. ZeroTier One is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 93a91933..f07650b5 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Address.hpp b/node/Address.hpp index 12c52a3f..41977af2 100644 --- a/node/Address.hpp +++ b/node/Address.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Array.hpp b/node/Array.hpp index ef2611e4..de827c08 100644 --- a/node/Array.hpp +++ b/node/Array.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/AtomicCounter.hpp b/node/AtomicCounter.hpp index 34b58e91..d58c4b56 100644 --- a/node/AtomicCounter.hpp +++ b/node/AtomicCounter.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Buffer.hpp b/node/Buffer.hpp index f84b3774..bbf4ee37 100644 --- a/node/Buffer.hpp +++ b/node/Buffer.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/C25519.hpp b/node/C25519.hpp index 950c7fed..3f22b445 100644 --- a/node/C25519.hpp +++ b/node/C25519.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Capability.cpp b/node/Capability.cpp index 47dca1fc..fb52be8a 100644 --- a/node/Capability.cpp +++ b/node/Capability.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Capability.hpp b/node/Capability.hpp index bec1f47f..91a46566 100644 --- a/node/Capability.hpp +++ b/node/Capability.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/CertificateOfMembership.cpp b/node/CertificateOfMembership.cpp index dedcccff..a849a44c 100644 --- a/node/CertificateOfMembership.cpp +++ b/node/CertificateOfMembership.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/CertificateOfMembership.hpp b/node/CertificateOfMembership.hpp index 2eff1083..19fe5367 100644 --- a/node/CertificateOfMembership.hpp +++ b/node/CertificateOfMembership.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/CertificateOfOwnership.cpp b/node/CertificateOfOwnership.cpp index eeb0d99c..8ee67865 100644 --- a/node/CertificateOfOwnership.cpp +++ b/node/CertificateOfOwnership.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/CertificateOfOwnership.hpp b/node/CertificateOfOwnership.hpp index e397fd63..278ae863 100644 --- a/node/CertificateOfOwnership.hpp +++ b/node/CertificateOfOwnership.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Constants.hpp b/node/Constants.hpp index 6360a693..23bebafd 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Credential.hpp b/node/Credential.hpp index e8767e22..34e94162 100644 --- a/node/Credential.hpp +++ b/node/Credential.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Dictionary.hpp b/node/Dictionary.hpp index a1b0f9cb..59afb7c6 100644 --- a/node/Dictionary.hpp +++ b/node/Dictionary.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Hashtable.hpp b/node/Hashtable.hpp index 5aa045b9..58dc8fca 100644 --- a/node/Hashtable.hpp +++ b/node/Hashtable.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Identity.cpp b/node/Identity.cpp index 72bea75d..9cc507f7 100644 --- a/node/Identity.cpp +++ b/node/Identity.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Identity.hpp b/node/Identity.hpp index ab2886ad..cd24757e 100644 --- a/node/Identity.hpp +++ b/node/Identity.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 38fd3aa0..341f3281 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/IncomingPacket.hpp b/node/IncomingPacket.hpp index c8f52721..88f4f066 100644 --- a/node/IncomingPacket.hpp +++ b/node/IncomingPacket.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp index ee32ce72..ecfc81ab 100644 --- a/node/InetAddress.cpp +++ b/node/InetAddress.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/InetAddress.hpp b/node/InetAddress.hpp index fd430099..e6dfabf9 100644 --- a/node/InetAddress.hpp +++ b/node/InetAddress.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/MAC.hpp b/node/MAC.hpp index 18fe2032..c08323a4 100644 --- a/node/MAC.hpp +++ b/node/MAC.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Membership.cpp b/node/Membership.cpp index de5fb99d..affe7a71 100644 --- a/node/Membership.cpp +++ b/node/Membership.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Membership.hpp b/node/Membership.hpp index 95ec2180..ad0bb73e 100644 --- a/node/Membership.hpp +++ b/node/Membership.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/MulticastGroup.hpp b/node/MulticastGroup.hpp index 6039d3c4..0f4a621e 100644 --- a/node/MulticastGroup.hpp +++ b/node/MulticastGroup.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Multicaster.cpp b/node/Multicaster.cpp index fa6f7bd1..d5bdfdf6 100644 --- a/node/Multicaster.cpp +++ b/node/Multicaster.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Multicaster.hpp b/node/Multicaster.hpp index 08c96485..59959328 100644 --- a/node/Multicaster.hpp +++ b/node/Multicaster.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Mutex.hpp b/node/Mutex.hpp index 53ae05c4..cbd80524 100644 --- a/node/Mutex.hpp +++ b/node/Mutex.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Network.cpp b/node/Network.cpp index e8e91174..e8a52e33 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Network.hpp b/node/Network.hpp index 1b4da7d2..db285108 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp index 2e07ac82..f9b16cc5 100644 --- a/node/NetworkConfig.cpp +++ b/node/NetworkConfig.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp index 19823e24..4121a241 100644 --- a/node/NetworkConfig.hpp +++ b/node/NetworkConfig.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/NetworkController.hpp b/node/NetworkController.hpp index 63d44a46..393bcc91 100644 --- a/node/NetworkController.hpp +++ b/node/NetworkController.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Node.cpp b/node/Node.cpp index d4b69689..af03669c 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Node.hpp b/node/Node.hpp index f8236db8..82f35c56 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/NonCopyable.hpp b/node/NonCopyable.hpp index 5e8c753d..31107a50 100644 --- a/node/NonCopyable.hpp +++ b/node/NonCopyable.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/OutboundMulticast.cpp b/node/OutboundMulticast.cpp index 9aa44736..d7a7b4d8 100644 --- a/node/OutboundMulticast.cpp +++ b/node/OutboundMulticast.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/OutboundMulticast.hpp b/node/OutboundMulticast.hpp index 2f6d8338..836b840b 100644 --- a/node/OutboundMulticast.hpp +++ b/node/OutboundMulticast.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Packet.cpp b/node/Packet.cpp index cb9e1e0f..de059054 100644 --- a/node/Packet.cpp +++ b/node/Packet.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Packet.hpp b/node/Packet.hpp index 8cfb5492..b96ab375 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Path.cpp b/node/Path.cpp index ca366e39..b1b3dd06 100644 --- a/node/Path.cpp +++ b/node/Path.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Path.hpp b/node/Path.hpp index 6b4b9915..62d750b7 100644 --- a/node/Path.hpp +++ b/node/Path.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Peer.cpp b/node/Peer.cpp index 6e46089f..71afd852 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Peer.hpp b/node/Peer.hpp index 99728736..99216bab 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Poly1305.hpp b/node/Poly1305.hpp index 0bdfa74f..adcc2410 100644 --- a/node/Poly1305.hpp +++ b/node/Poly1305.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Revocation.cpp b/node/Revocation.cpp index 89a2db95..78098f8c 100644 --- a/node/Revocation.cpp +++ b/node/Revocation.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Revocation.hpp b/node/Revocation.hpp index 4a18914f..eaf01915 100644 --- a/node/Revocation.hpp +++ b/node/Revocation.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/RuntimeEnvironment.hpp b/node/RuntimeEnvironment.hpp index 0bb78599..9ecdc400 100644 --- a/node/RuntimeEnvironment.hpp +++ b/node/RuntimeEnvironment.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/SHA512.hpp b/node/SHA512.hpp index 584f8e11..eedc284a 100644 --- a/node/SHA512.hpp +++ b/node/SHA512.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/SelfAwareness.cpp b/node/SelfAwareness.cpp index 83cd89c9..c4f107fb 100644 --- a/node/SelfAwareness.cpp +++ b/node/SelfAwareness.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/SelfAwareness.hpp b/node/SelfAwareness.hpp index 7ddba465..ce6e8c76 100644 --- a/node/SelfAwareness.hpp +++ b/node/SelfAwareness.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/SharedPtr.hpp b/node/SharedPtr.hpp index af66545f..aa03cf0b 100644 --- a/node/SharedPtr.hpp +++ b/node/SharedPtr.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Switch.cpp b/node/Switch.cpp index b2cab1d0..c3626f9f 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Switch.hpp b/node/Switch.hpp index b42389fc..4fc5453d 100644 --- a/node/Switch.hpp +++ b/node/Switch.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Tag.cpp b/node/Tag.cpp index bde41a70..62d9cb2e 100644 --- a/node/Tag.cpp +++ b/node/Tag.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Tag.hpp b/node/Tag.hpp index 394c7be6..d2e932c2 100644 --- a/node/Tag.hpp +++ b/node/Tag.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Topology.cpp b/node/Topology.cpp index d1b389df..fa9868e9 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Topology.hpp b/node/Topology.hpp index b09f95cf..0bcdfb0a 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Trace.cpp b/node/Trace.cpp index 4303946b..a60a0194 100644 --- a/node/Trace.cpp +++ b/node/Trace.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Trace.hpp b/node/Trace.hpp index 08241d37..05d5b66a 100644 --- a/node/Trace.hpp +++ b/node/Trace.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Utils.cpp b/node/Utils.cpp index 4ac18366..a69a575e 100644 --- a/node/Utils.cpp +++ b/node/Utils.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/Utils.hpp b/node/Utils.hpp index 54af3aec..5565fad6 100644 --- a/node/Utils.hpp +++ b/node/Utils.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/node/World.hpp b/node/World.hpp index 26d94fcd..459470ca 100644 --- a/node/World.hpp +++ b/node/World.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/one.cpp b/one.cpp index a1238bb8..8d4b8fc5 100644 --- a/one.cpp +++ b/one.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 @@ -93,7 +93,7 @@ using namespace ZeroTier; static OneService *volatile zt1Service = (OneService *)0; #define PROGRAM_NAME "ZeroTier One" -#define COPYRIGHT_NOTICE "Copyright (c) 2011-2017 ZeroTier, Inc." +#define COPYRIGHT_NOTICE "Copyright (c) 2011-2018 ZeroTier, Inc." #define LICENSE_GRANT \ "This is free software: you may copy, modify, and/or distribute this" ZT_EOL_S \ "work under the terms of the GNU General Public License, version 3 or" ZT_EOL_S \ diff --git a/osdep/Arp.cpp b/osdep/Arp.cpp index c06f459b..cc4e920a 100644 --- a/osdep/Arp.cpp +++ b/osdep/Arp.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/osdep/Arp.hpp b/osdep/Arp.hpp index e26fcdb3..27e92fdb 100644 --- a/osdep/Arp.hpp +++ b/osdep/Arp.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/osdep/BSDEthernetTap.cpp b/osdep/BSDEthernetTap.cpp index c0fdad9c..053df21d 100644 --- a/osdep/BSDEthernetTap.cpp +++ b/osdep/BSDEthernetTap.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/osdep/BSDEthernetTap.hpp b/osdep/BSDEthernetTap.hpp index fd2685f3..3d91dbbb 100644 --- a/osdep/BSDEthernetTap.hpp +++ b/osdep/BSDEthernetTap.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/osdep/Binder.hpp b/osdep/Binder.hpp index e3c2dc02..399ce04a 100644 --- a/osdep/Binder.hpp +++ b/osdep/Binder.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/osdep/BlockingQueue.hpp b/osdep/BlockingQueue.hpp index 5e1a24ef..351a095a 100644 --- a/osdep/BlockingQueue.hpp +++ b/osdep/BlockingQueue.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/osdep/Http.cpp b/osdep/Http.cpp index d6d0238c..16785c96 100644 --- a/osdep/Http.cpp +++ b/osdep/Http.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/osdep/Http.hpp b/osdep/Http.hpp index 3f98d760..b717c5c9 100644 --- a/osdep/Http.hpp +++ b/osdep/Http.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index 848f3638..6ef42744 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/osdep/LinuxEthernetTap.hpp b/osdep/LinuxEthernetTap.hpp index e05dee8c..5142eec1 100644 --- a/osdep/LinuxEthernetTap.hpp +++ b/osdep/LinuxEthernetTap.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/osdep/ManagedRoute.cpp b/osdep/ManagedRoute.cpp index 2289b23a..8ffbed2a 100644 --- a/osdep/ManagedRoute.cpp +++ b/osdep/ManagedRoute.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/osdep/ManagedRoute.hpp b/osdep/ManagedRoute.hpp index 849bddf5..873d0cfb 100644 --- a/osdep/ManagedRoute.hpp +++ b/osdep/ManagedRoute.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/osdep/NeighborDiscovery.cpp b/osdep/NeighborDiscovery.cpp index ac95748b..d9862f3d 100644 --- a/osdep/NeighborDiscovery.cpp +++ b/osdep/NeighborDiscovery.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/osdep/NeighborDiscovery.hpp b/osdep/NeighborDiscovery.hpp index 2e7a68ba..59186289 100644 --- a/osdep/NeighborDiscovery.hpp +++ b/osdep/NeighborDiscovery.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/osdep/OSUtils.cpp b/osdep/OSUtils.cpp index 3325c621..aa531243 100644 --- a/osdep/OSUtils.cpp +++ b/osdep/OSUtils.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/osdep/OSUtils.hpp b/osdep/OSUtils.hpp index 274b48df..324b7923 100644 --- a/osdep/OSUtils.hpp +++ b/osdep/OSUtils.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/osdep/OSXEthernetTap.cpp b/osdep/OSXEthernetTap.cpp index b43d34c0..dbff6200 100644 --- a/osdep/OSXEthernetTap.cpp +++ b/osdep/OSXEthernetTap.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/osdep/OSXEthernetTap.hpp b/osdep/OSXEthernetTap.hpp index d0a8a99d..fe402901 100644 --- a/osdep/OSXEthernetTap.hpp +++ b/osdep/OSXEthernetTap.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/osdep/Phy.hpp b/osdep/Phy.hpp index f71bd56c..8e683f10 100644 --- a/osdep/Phy.hpp +++ b/osdep/Phy.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/osdep/PortMapper.cpp b/osdep/PortMapper.cpp index 9aeeb8d6..a7dd3046 100644 --- a/osdep/PortMapper.cpp +++ b/osdep/PortMapper.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/osdep/PortMapper.hpp b/osdep/PortMapper.hpp index 61015a09..fa3cdc31 100644 --- a/osdep/PortMapper.hpp +++ b/osdep/PortMapper.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/osdep/TestEthernetTap.hpp b/osdep/TestEthernetTap.hpp index 047a19b1..2f73258a 100644 --- a/osdep/TestEthernetTap.hpp +++ b/osdep/TestEthernetTap.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/osdep/Thread.hpp b/osdep/Thread.hpp index b3011f32..35ea5035 100644 --- a/osdep/Thread.hpp +++ b/osdep/Thread.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/osdep/WindowsEthernetTap.cpp b/osdep/WindowsEthernetTap.cpp index 93da8ad6..22b81454 100644 --- a/osdep/WindowsEthernetTap.cpp +++ b/osdep/WindowsEthernetTap.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/osdep/WindowsEthernetTap.hpp b/osdep/WindowsEthernetTap.hpp index 70789e75..856c3be7 100644 --- a/osdep/WindowsEthernetTap.hpp +++ b/osdep/WindowsEthernetTap.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/selftest.cpp b/selftest.cpp index 86894564..9edb4928 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/service/OneService.cpp b/service/OneService.cpp index 71bb6983..e65ad0e2 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/service/OneService.hpp b/service/OneService.hpp index 23e572d0..3b670e4a 100644 --- a/service/OneService.hpp +++ b/service/OneService.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/service/SoftwareUpdater.cpp b/service/SoftwareUpdater.cpp index 39833c90..6a25dbec 100644 --- a/service/SoftwareUpdater.cpp +++ b/service/SoftwareUpdater.cpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/service/SoftwareUpdater.hpp b/service/SoftwareUpdater.hpp index f16c99a0..ed329b1f 100644 --- a/service/SoftwareUpdater.hpp +++ b/service/SoftwareUpdater.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 diff --git a/version.h b/version.h index b3b2fc81..d80bec80 100644 --- a/version.h +++ b/version.h @@ -1,6 +1,6 @@ /* * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * 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 -- cgit v1.2.3 From 30694f0b20413f3f08f6bb51b151e69f29a9a75a Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 9 Jan 2018 08:59:26 -0800 Subject: Allow trusted paths over global IPs for legacy config format too. --- service/OneService.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index e65ad0e2..c4d29c52 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -585,7 +585,7 @@ public: } else break; ++fno; } - if ( (trustedPathId != 0) && ((trustedPathNetwork.ss_family == AF_INET)||(trustedPathNetwork.ss_family == AF_INET6)) && (trustedPathNetwork.ipScope() != InetAddress::IP_SCOPE_GLOBAL) && (trustedPathNetwork.netmaskBits() > 0) ) { + if ( (trustedPathId != 0) && ((trustedPathNetwork.ss_family == AF_INET)||(trustedPathNetwork.ss_family == AF_INET6)) && (trustedPathNetwork.netmaskBits() > 0) ) { ppc[trustedPathNetwork].trustedPathId = trustedPathId; ppc[trustedPathNetwork].mtu = 0; // use default } -- cgit v1.2.3 From 2e1bc6e500be4b7bdec3304245c8d19ab186a97c Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Tue, 9 Jan 2018 09:59:55 -0800 Subject: Cleaned up old code for attempted fix for ticket #600 --- osdep/ManagedRoute.cpp | 25 ------------------------- service/OneService.cpp | 1 + 2 files changed, 1 insertion(+), 25 deletions(-) (limited to 'service/OneService.cpp') diff --git a/osdep/ManagedRoute.cpp b/osdep/ManagedRoute.cpp index 8ffbed2a..d7c80704 100644 --- a/osdep/ManagedRoute.cpp +++ b/osdep/ManagedRoute.cpp @@ -477,31 +477,6 @@ bool ManagedRoute::sync() } } - // Detect routes previously applied by ZT that don't exist in the system's route list. Re-apply these. - // NOTE: The following block was added in reaction to the macOS High Sierra 10.13.2 disappearing - // route issue. This comment should be removed once we're sure this block doesn't have any side-effects. - /* - - // Commented out temporarily to test more generalized fix - - bool found = false; - std::vector<_RTE> currRoutes(_getRTEs(_target,false)); - for(std::vector<_RTE>::iterator r(currRoutes.begin());r!=currRoutes.end();++r) { - if(_target == r->target) { - found = true; - break; - } - } - if (!found) { - // erase _applied enteries - std::map::iterator rt; - rt = _applied.find(leftt); - _applied.erase(rt, _applied.end()); - rt = _applied.find(rightt); - _applied.erase(rt, _applied.end()); - } - */ - if (!_applied.count(leftt)) { _applied[leftt] = false; // not ifscoped _routeCmd("add",leftt,_via,(const char *)0,(_via) ? (const char *)0 : _device); diff --git a/service/OneService.cpp b/service/OneService.cpp index e65ad0e2..92b78a8c 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1609,6 +1609,7 @@ public: bool haveRoute = false; // Ignore routes implied by local managed IPs since adding the IP adds the route + // Commented out to fix ticket #600 (disappearing routes on macOS). Remove this block when we're sure there's no side effects /* for(std::vector::iterator ip(n.managedIps.begin());ip!=n.managedIps.end();++ip) { if ((target->netmaskBits() == ip->netmaskBits())&&(target->containsAddress(*ip))) { -- cgit v1.2.3 From 7e2d6149759e84ab4dc4a4f2e025d143b2882900 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Tue, 9 Jan 2018 10:16:49 -0800 Subject: Attempted fix for ticket #656 (failes to acknowledge physical blacklists) --- service/OneService.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 8aeecd5e..2e9c530d 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -2279,6 +2279,8 @@ public: return 0; } } + } + if (gbl) { for(std::vector::const_iterator a(gbl->begin());a!=gbl->end();++a) { if (a->containsAddress(*reinterpret_cast(remoteAddr))) return 0; -- cgit v1.2.3 From 640cc22749276e7c7f6e7cfa4eee8c0590064ac0 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Wed, 10 Jan 2018 12:41:52 -0800 Subject: Added allowTcpFallbackRelay to local.conf, fixed logic in Binder's route enumeration --- osdep/Binder.hpp | 12 +++++- service/OneService.cpp | 101 ++++++++++++++++++++++++++----------------------- 2 files changed, 64 insertions(+), 49 deletions(-) (limited to 'service/OneService.cpp') diff --git a/osdep/Binder.hpp b/osdep/Binder.hpp index 2c42daee..e10c0080 100644 --- a/osdep/Binder.hpp +++ b/osdep/Binder.hpp @@ -137,6 +137,7 @@ public: std::map localIfAddrs; PhySocket *udps,*tcps; Mutex::Lock _l(_lock); + bool interfacesEnumerated = true; #ifdef __WINDOWS__ @@ -167,6 +168,9 @@ public: a = a->Next; } } + else { + interfacesEnumerated = false; + } #else // not __WINDOWS__ @@ -195,6 +199,9 @@ public: } fclose(procf); } + else { + interfacesEnumerated = false; + } // Get IPv6 addresses (and any device names we don't already know) OSUtils::ztsnprintf(fn,sizeof(fn),"/proc/%lu/net/if_inet6",pid); @@ -314,12 +321,15 @@ public: } freeifaddrs(ifatbl); } + else { + interfacesEnumerated = false; + } } #endif // Default to binding to wildcard if we can't enumerate addresses - if (localIfAddrs.empty()) { + if (!interfacesEnumerated && localIfAddrs.empty()) { for(int x=0;x<(int)portCount;++x) { localIfAddrs.insert(std::pair(InetAddress((uint32_t)0,ports[x]),std::string())); localIfAddrs.insert(std::pair(InetAddress((const void *)"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",16,ports[x]),std::string())); diff --git a/service/OneService.cpp b/service/OneService.cpp index 2e9c530d..487ff4d0 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -398,6 +398,7 @@ public: PhySocket *_localControlSocket4; PhySocket *_localControlSocket6; bool _updateAutoApply; + bool _allowTcpFallbackRelay; unsigned int _primaryPort; volatile unsigned int _udpPortPickerCounter; @@ -1125,6 +1126,7 @@ public: } json &settings = res["config"]["settings"]; settings["primaryPort"] = OSUtils::jsonInt(settings["primaryPort"],(uint64_t)_primaryPort) & 0xffff; + settings["allowTcpFallbackRelay"] = OSUtils::jsonBool(settings["allowTcpFallbackRelay"],_allowTcpFallbackRelay); #ifdef ZT_USE_MINIUPNPC settings["portMappingEnabled"] = OSUtils::jsonBool(settings["portMappingEnabled"],true); #else @@ -1452,6 +1454,7 @@ public: json &settings = lc["settings"]; _primaryPort = (unsigned int)OSUtils::jsonInt(settings["primaryPort"],(uint64_t)_primaryPort) & 0xffff; + _allowTcpFallbackRelay = OSUtils::jsonBool(settings["allowTcpFallbackRelay"],true); _portMappingEnabled = OSUtils::jsonBool(settings["portMappingEnabled"],true); #ifndef ZT_SDK @@ -2161,63 +2164,66 @@ public: inline int nodeWirePacketSendFunction(const int64_t localSocket,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl) { #ifdef ZT_TCP_FALLBACK_RELAY - if (addr->ss_family == AF_INET) { - // TCP fallback tunnel support, currently IPv4 only - if ((len >= 16)&&(reinterpret_cast(addr)->ipScope() == InetAddress::IP_SCOPE_GLOBAL)) { - // Engage TCP tunnel fallback if we haven't received anything valid from a global - // IP address in ZT_TCP_FALLBACK_AFTER milliseconds. If we do start getting - // valid direct traffic we'll stop using it and close the socket after a while. - const int64_t now = OSUtils::now(); - if (((now - _lastDirectReceiveFromGlobal) > ZT_TCP_FALLBACK_AFTER)&&((now - _lastRestart) > ZT_TCP_FALLBACK_AFTER)) { - if (_tcpFallbackTunnel) { - bool flushNow = false; - { - Mutex::Lock _l(_tcpFallbackTunnel->writeq_m); - if (_tcpFallbackTunnel->writeq.size() < (1024 * 64)) { - if (_tcpFallbackTunnel->writeq.length() == 0) { - _phy.setNotifyWritable(_tcpFallbackTunnel->sock,true); - flushNow = true; + if(_allowTcpFallbackRelay) { + if (addr->ss_family == AF_INET) { + // TCP fallback tunnel support, currently IPv4 only + if ((len >= 16)&&(reinterpret_cast(addr)->ipScope() == InetAddress::IP_SCOPE_GLOBAL)) { + // Engage TCP tunnel fallback if we haven't received anything valid from a global + // IP address in ZT_TCP_FALLBACK_AFTER milliseconds. If we do start getting + // valid direct traffic we'll stop using it and close the socket after a while. + const int64_t now = OSUtils::now(); + if (((now - _lastDirectReceiveFromGlobal) > ZT_TCP_FALLBACK_AFTER)&&((now - _lastRestart) > ZT_TCP_FALLBACK_AFTER)) { + if (_tcpFallbackTunnel) { + bool flushNow = false; + { + Mutex::Lock _l(_tcpFallbackTunnel->writeq_m); + if (_tcpFallbackTunnel->writeq.size() < (1024 * 64)) { + if (_tcpFallbackTunnel->writeq.length() == 0) { + _phy.setNotifyWritable(_tcpFallbackTunnel->sock,true); + flushNow = true; + } + const unsigned long mlen = len + 7; + _tcpFallbackTunnel->writeq.push_back((char)0x17); + _tcpFallbackTunnel->writeq.push_back((char)0x03); + _tcpFallbackTunnel->writeq.push_back((char)0x03); // fake TLS 1.2 header + _tcpFallbackTunnel->writeq.push_back((char)((mlen >> 8) & 0xff)); + _tcpFallbackTunnel->writeq.push_back((char)(mlen & 0xff)); + _tcpFallbackTunnel->writeq.push_back((char)4); // IPv4 + _tcpFallbackTunnel->writeq.append(reinterpret_cast(reinterpret_cast(&(reinterpret_cast(addr)->sin_addr.s_addr))),4); + _tcpFallbackTunnel->writeq.append(reinterpret_cast(reinterpret_cast(&(reinterpret_cast(addr)->sin_port))),2); + _tcpFallbackTunnel->writeq.append((const char *)data,len); } - const unsigned long mlen = len + 7; - _tcpFallbackTunnel->writeq.push_back((char)0x17); - _tcpFallbackTunnel->writeq.push_back((char)0x03); - _tcpFallbackTunnel->writeq.push_back((char)0x03); // fake TLS 1.2 header - _tcpFallbackTunnel->writeq.push_back((char)((mlen >> 8) & 0xff)); - _tcpFallbackTunnel->writeq.push_back((char)(mlen & 0xff)); - _tcpFallbackTunnel->writeq.push_back((char)4); // IPv4 - _tcpFallbackTunnel->writeq.append(reinterpret_cast(reinterpret_cast(&(reinterpret_cast(addr)->sin_addr.s_addr))),4); - _tcpFallbackTunnel->writeq.append(reinterpret_cast(reinterpret_cast(&(reinterpret_cast(addr)->sin_port))),2); - _tcpFallbackTunnel->writeq.append((const char *)data,len); } + if (flushNow) { + void *tmpptr = (void *)_tcpFallbackTunnel; + phyOnTcpWritable(_tcpFallbackTunnel->sock,&tmpptr); + } + } else if (((now - _lastSendToGlobalV4) < ZT_TCP_FALLBACK_AFTER)&&((now - _lastSendToGlobalV4) > (ZT_PING_CHECK_INVERVAL / 2))) { + const InetAddress addr(ZT_TCP_FALLBACK_RELAY); + TcpConnection *tc = new TcpConnection(); + { + Mutex::Lock _l(_tcpConnections_m); + _tcpConnections.push_back(tc); + } + tc->type = TcpConnection::TCP_TUNNEL_OUTGOING; + tc->remoteAddr = addr; + tc->lastReceive = OSUtils::now(); + tc->parent = this; + tc->sock = (PhySocket *)0; // set in connect handler + tc->messageSize = 0; + bool connected = false; + _phy.tcpConnect(reinterpret_cast(&addr),connected,(void *)tc,true); } - if (flushNow) { - void *tmpptr = (void *)_tcpFallbackTunnel; - phyOnTcpWritable(_tcpFallbackTunnel->sock,&tmpptr); - } - } else if (((now - _lastSendToGlobalV4) < ZT_TCP_FALLBACK_AFTER)&&((now - _lastSendToGlobalV4) > (ZT_PING_CHECK_INVERVAL / 2))) { - const InetAddress addr(ZT_TCP_FALLBACK_RELAY); - TcpConnection *tc = new TcpConnection(); - { - Mutex::Lock _l(_tcpConnections_m); - _tcpConnections.push_back(tc); - } - tc->type = TcpConnection::TCP_TUNNEL_OUTGOING; - tc->remoteAddr = addr; - tc->lastReceive = OSUtils::now(); - tc->parent = this; - tc->sock = (PhySocket *)0; // set in connect handler - tc->messageSize = 0; - bool connected = false; - _phy.tcpConnect(reinterpret_cast(&addr),connected,(void *)tc,true); } + _lastSendToGlobalV4 = now; } - _lastSendToGlobalV4 = now; } } +#endif // ZT_TCP_FALLBACK_RELAY + // Even when relaying we still send via UDP. This way if UDP starts // working we can instantly "fail forward" to it and stop using TCP // proxy fallback, which is slow. -#endif // ZT_TCP_FALLBACK_RELAY if ((localSocket != -1)&&(localSocket != 0)&&(_binder.isUdpSocketValid((PhySocket *)((uintptr_t)localSocket)))) { if ((ttl)&&(addr->ss_family == AF_INET)) _phy.setIp4UdpTtl((PhySocket *)((uintptr_t)localSocket),ttl); @@ -2286,7 +2292,6 @@ public: return 0; } } - return 1; } -- cgit v1.2.3 From f87326fc21fb6db0944730ba1fe961d8bb249450 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 11 Jan 2018 14:29:57 -0800 Subject: Fixes for lock ordering -- GitHub issue #573 --- node/Mutex.hpp | 3 ++- node/Node.hpp | 2 +- node/Topology.cpp | 8 ++++---- service/OneService.cpp | 20 +++++++++++++++++++- 4 files changed, 26 insertions(+), 7 deletions(-) (limited to 'service/OneService.cpp') diff --git a/node/Mutex.hpp b/node/Mutex.hpp index cbd80524..e0917f01 100644 --- a/node/Mutex.hpp +++ b/node/Mutex.hpp @@ -38,7 +38,8 @@ namespace ZeroTier { -#if defined(__GNUC__) && (defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) || defined(__AMD64__) || defined(_M_X64)) +//#if defined(__GNUC__) && (defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) || defined(__AMD64__) || defined(_M_X64)) +#if 0 // Inline ticket lock on x64 systems with GCC and CLANG (Mac, Linux) -- this is really fast as long as locking durations are very short class Mutex : NonCopyable diff --git a/node/Node.hpp b/node/Node.hpp index 82f35c56..79284b63 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -284,7 +284,7 @@ private: Address _remoteTraceTarget; enum Trace::Level _remoteTraceLevel; - int64_t _now; + volatile int64_t _now; int64_t _lastPingCheck; int64_t _lastHousekeepingRun; int64_t _lastMemoizedTraceSettings; diff --git a/node/Topology.cpp b/node/Topology.cpp index fa9868e9..17a0eee4 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -162,8 +162,8 @@ SharedPtr Topology::getUpstreamPeer() unsigned int bestq = ~((unsigned int)0); const SharedPtr *best = (const SharedPtr *)0; - Mutex::Lock _l1(_peers_m); - Mutex::Lock _l2(_upstreams_m); + Mutex::Lock _l2(_peers_m); + Mutex::Lock _l1(_upstreams_m); for(std::vector
::const_iterator a(_upstreamAddresses.begin());a!=_upstreamAddresses.end();++a) { const SharedPtr *p = _peers.get(*a); @@ -252,8 +252,8 @@ bool Topology::addWorld(void *tPtr,const World &newWorld,bool alwaysAcceptNew) if ((newWorld.type() != World::TYPE_PLANET)&&(newWorld.type() != World::TYPE_MOON)) return false; - Mutex::Lock _l1(_upstreams_m); Mutex::Lock _l2(_peers_m); + Mutex::Lock _l1(_upstreams_m); World *existing = (World *)0; switch(newWorld.type()) { @@ -341,8 +341,8 @@ void Topology::addMoon(void *tPtr,const uint64_t id,const Address &seed) void Topology::removeMoon(void *tPtr,const uint64_t id) { - Mutex::Lock _l1(_upstreams_m); Mutex::Lock _l2(_peers_m); + Mutex::Lock _l1(_upstreams_m); std::vector nm; for(std::vector::const_iterator m(_moons.begin());m!=_moons.end();++m) { diff --git a/service/OneService.cpp b/service/OneService.cpp index 487ff4d0..7d254124 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -825,7 +825,24 @@ public: // Sync multicast group memberships if ((now - lastTapMulticastGroupCheck) >= ZT_TAP_CHECK_MULTICAST_INTERVAL) { lastTapMulticastGroupCheck = now; - Mutex::Lock _l(_nets_m); + std::vector< std::pair< uint64_t,std::pair< std::vector,std::vector > > > mgChanges; + { + Mutex::Lock _l(_nets_m); + mgChanges.reserve(_nets.size() + 1); + for(std::map::const_iterator n(_nets.begin());n!=_nets.end();++n) { + if (n->second.tap) { + mgChanges.push_back(std::pair< uint64_t,std::pair< std::vector,std::vector > >(n->first,std::pair< std::vector,std::vector >())); + n->second.tap->scanMulticastGroups(mgChanges.back().second.first,mgChanges.back().second.second); + } + } + } + for(std::vector< std::pair< uint64_t,std::pair< std::vector,std::vector > > >::iterator c(mgChanges.begin());c!=mgChanges.end();++c) { + for(std::vector::iterator m(c->second.first.begin());m!=c->second.first.end();++m) + _node->multicastSubscribe((void *)0,c->first,m->mac().toInt(),m->adi()); + for(std::vector::iterator m(c->second.second.begin());m!=c->second.second.end();++m) + _node->multicastUnsubscribe(c->first,m->mac().toInt(),m->adi()); + } + /* for(std::map::const_iterator n(_nets.begin());n!=_nets.end();++n) { if (n->second.tap) { std::vector added,removed; @@ -836,6 +853,7 @@ public: _node->multicastUnsubscribe(n->first,m->mac().toInt(),m->adi()); } } + */ } // Sync information about physical network interfaces -- cgit v1.2.3 From c594351bccda348c5605d5dfb77939cf8fa4f5f4 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 11 Jan 2018 14:32:55 -0800 Subject: Remove old code. --- service/OneService.cpp | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 7d254124..b6b6f5fe 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -842,18 +842,6 @@ public: for(std::vector::iterator m(c->second.second.begin());m!=c->second.second.end();++m) _node->multicastUnsubscribe(c->first,m->mac().toInt(),m->adi()); } - /* - for(std::map::const_iterator n(_nets.begin());n!=_nets.end();++n) { - if (n->second.tap) { - std::vector added,removed; - n->second.tap->scanMulticastGroups(added,removed); - for(std::vector::iterator m(added.begin());m!=added.end();++m) - _node->multicastSubscribe((void *)0,n->first,m->mac().toInt(),m->adi()); - for(std::vector::iterator m(removed.begin());m!=removed.end();++m) - _node->multicastUnsubscribe(n->first,m->mac().toInt(),m->adi()); - } - } - */ } // Sync information about physical network interfaces -- cgit v1.2.3 From 125ec622ca446021ad3d2a707752b11fcb5dd195 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 25 Jan 2018 14:59:11 -0500 Subject: Add bindToWildcard local.conf option. --- osdep/Binder.hpp | 316 +++++++++++++++++++++++++------------------------ service/OneService.cpp | 8 +- service/README.md | 3 +- 3 files changed, 167 insertions(+), 160 deletions(-) (limited to 'service/OneService.cpp') diff --git a/osdep/Binder.hpp b/osdep/Binder.hpp index e10c0080..f5fc32e3 100644 --- a/osdep/Binder.hpp +++ b/osdep/Binder.hpp @@ -125,184 +125,110 @@ public: * * @param phy Physical interface * @param ports Ports to bind on all interfaces - * @param ignoreInterfacesByName Ignore these interfaces by name - * @param ignoreInterfacesByNamePrefix Ignore these interfaces by name-prefix (starts-with, e.g. zt ignores zt*) - * @param ignoreInterfacesByAddress Ignore these interfaces by address + * @param portCount Number of ports + * @param bindtoWildcard If true, bind wildcard instead of per-interface IPs + * @param ifChecker Interface checker function to see if an interface should be used * @tparam PHY_HANDLER_TYPE Type for Phy<> template * @tparam INTERFACE_CHECKER Type for class containing shouldBindInterface() method */ template - void refresh(Phy &phy,unsigned int *ports,unsigned int portCount,INTERFACE_CHECKER &ifChecker) + void refresh(Phy &phy,unsigned int *ports,unsigned int portCount,bool bindToWildcard,INTERFACE_CHECKER &ifChecker) { std::map localIfAddrs; PhySocket *udps,*tcps; Mutex::Lock _l(_lock); bool interfacesEnumerated = true; + if (!bindToWildcard) { #ifdef __WINDOWS__ - char aabuf[32768]; - ULONG aalen = sizeof(aabuf); - if (GetAdaptersAddresses(AF_UNSPEC,GAA_FLAG_SKIP_ANYCAST|GAA_FLAG_SKIP_MULTICAST|GAA_FLAG_SKIP_DNS_SERVER,(void *)0,reinterpret_cast(aabuf),&aalen) == NO_ERROR) { - PIP_ADAPTER_ADDRESSES a = reinterpret_cast(aabuf); - while (a) { - PIP_ADAPTER_UNICAST_ADDRESS ua = a->FirstUnicastAddress; - while (ua) { - InetAddress ip(ua->Address.lpSockaddr); - if (ifChecker.shouldBindInterface("",ip)) { - switch(ip.ipScope()) { - default: break; - case InetAddress::IP_SCOPE_PSEUDOPRIVATE: - case InetAddress::IP_SCOPE_GLOBAL: - case InetAddress::IP_SCOPE_SHARED: - case InetAddress::IP_SCOPE_PRIVATE: - for(int x=0;x<(int)portCount;++x) { - ip.setPort(ports[x]); - localIfAddrs.insert(std::pair(ip,std::string())); - } - break; + char aabuf[32768]; + ULONG aalen = sizeof(aabuf); + if (GetAdaptersAddresses(AF_UNSPEC,GAA_FLAG_SKIP_ANYCAST|GAA_FLAG_SKIP_MULTICAST|GAA_FLAG_SKIP_DNS_SERVER,(void *)0,reinterpret_cast(aabuf),&aalen) == NO_ERROR) { + PIP_ADAPTER_ADDRESSES a = reinterpret_cast(aabuf); + while (a) { + PIP_ADAPTER_UNICAST_ADDRESS ua = a->FirstUnicastAddress; + while (ua) { + InetAddress ip(ua->Address.lpSockaddr); + if (ifChecker.shouldBindInterface("",ip)) { + switch(ip.ipScope()) { + default: break; + case InetAddress::IP_SCOPE_PSEUDOPRIVATE: + case InetAddress::IP_SCOPE_GLOBAL: + case InetAddress::IP_SCOPE_SHARED: + case InetAddress::IP_SCOPE_PRIVATE: + for(int x=0;x<(int)portCount;++x) { + ip.setPort(ports[x]); + localIfAddrs.insert(std::pair(ip,std::string())); + } + break; + } } + ua = ua->Next; } - ua = ua->Next; + a = a->Next; } - a = a->Next; } - } - else { - interfacesEnumerated = false; - } + else { + interfacesEnumerated = false; + } #else // not __WINDOWS__ - /* On Linux we use an alternative method if available since getifaddrs() - * gets very slow when there are lots of network namespaces. This won't - * work unless /proc/PID/net/if_inet6 exists and it may not on some - * embedded systems, so revert to getifaddrs() there. */ + /* On Linux we use an alternative method if available since getifaddrs() + * gets very slow when there are lots of network namespaces. This won't + * work unless /proc/PID/net/if_inet6 exists and it may not on some + * embedded systems, so revert to getifaddrs() there. */ #ifdef __LINUX__ - char fn[256],tmp[256]; - std::set ifnames; - const unsigned long pid = (unsigned long)getpid(); - - // Get all device names - OSUtils::ztsnprintf(fn,sizeof(fn),"/proc/%lu/net/dev",pid); - FILE *procf = fopen(fn,"r"); - if (procf) { - while (fgets(tmp,sizeof(tmp),procf)) { - tmp[255] = 0; - char *saveptr = (char *)0; - for(char *f=Utils::stok(tmp," \t\r\n:|",&saveptr);(f);f=Utils::stok((char *)0," \t\r\n:|",&saveptr)) { - if ((strcmp(f,"Inter-") != 0)&&(strcmp(f,"face") != 0)&&(f[0] != 0)) - ifnames.insert(f); - break; // we only want the first field - } - } - fclose(procf); - } - else { - interfacesEnumerated = false; - } - - // Get IPv6 addresses (and any device names we don't already know) - OSUtils::ztsnprintf(fn,sizeof(fn),"/proc/%lu/net/if_inet6",pid); - procf = fopen(fn,"r"); - if (procf) { - while (fgets(tmp,sizeof(tmp),procf)) { - tmp[255] = 0; - char *saveptr = (char *)0; - unsigned char ipbits[16]; - memset(ipbits,0,sizeof(ipbits)); - char *devname = (char *)0; - int n = 0; - for(char *f=Utils::stok(tmp," \t\r\n",&saveptr);(f);f=Utils::stok((char *)0," \t\r\n",&saveptr)) { - switch(n++) { - case 0: // IP in hex - Utils::unhex(f,32,ipbits,16); - break; - case 5: // device name - devname = f; - break; - } - } - if (devname) { - ifnames.insert(devname); - InetAddress ip(ipbits,16,0); - if (ifChecker.shouldBindInterface(devname,ip)) { - switch(ip.ipScope()) { - default: break; - case InetAddress::IP_SCOPE_PSEUDOPRIVATE: - case InetAddress::IP_SCOPE_GLOBAL: - case InetAddress::IP_SCOPE_SHARED: - case InetAddress::IP_SCOPE_PRIVATE: - for(int x=0;x<(int)portCount;++x) { - ip.setPort(ports[x]); - localIfAddrs.insert(std::pair(ip,std::string(devname))); - } - break; - } + char fn[256],tmp[256]; + std::set ifnames; + const unsigned long pid = (unsigned long)getpid(); + + // Get all device names + OSUtils::ztsnprintf(fn,sizeof(fn),"/proc/%lu/net/dev",pid); + FILE *procf = fopen(fn,"r"); + if (procf) { + while (fgets(tmp,sizeof(tmp),procf)) { + tmp[255] = 0; + char *saveptr = (char *)0; + for(char *f=Utils::stok(tmp," \t\r\n:|",&saveptr);(f);f=Utils::stok((char *)0," \t\r\n:|",&saveptr)) { + if ((strcmp(f,"Inter-") != 0)&&(strcmp(f,"face") != 0)&&(f[0] != 0)) + ifnames.insert(f); + break; // we only want the first field } } + fclose(procf); + } + else { + interfacesEnumerated = false; } - fclose(procf); - } - // Get IPv4 addresses for each device - if (ifnames.size() > 0) { - const int controlfd = (int)socket(AF_INET,SOCK_DGRAM,0); - struct ifconf configuration; - configuration.ifc_len = 0; - configuration.ifc_buf = nullptr; - - if (controlfd < 0) goto ip4_address_error; - if (ioctl(controlfd, SIOCGIFCONF, &configuration) < 0) goto ip4_address_error; - configuration.ifc_buf = (char*)malloc(configuration.ifc_len); - if (ioctl(controlfd, SIOCGIFCONF, &configuration) < 0) goto ip4_address_error; - - for (int i=0; i < (int)(configuration.ifc_len / sizeof(ifreq)); i ++) { - struct ifreq& request = configuration.ifc_req[i]; - struct sockaddr* addr = &request.ifr_ifru.ifru_addr; - if (addr->sa_family != AF_INET) continue; - std::string ifname = request.ifr_ifrn.ifrn_name; - // name can either be just interface name or interface name followed by ':' and arbitrary label - if (ifname.find(':') != std::string::npos) - ifname = ifname.substr(0, ifname.find(':')); - - InetAddress ip(&(((struct sockaddr_in *)addr)->sin_addr),4,0); - if (ifChecker.shouldBindInterface(ifname.c_str(), ip)) { - switch(ip.ipScope()) { - default: break; - case InetAddress::IP_SCOPE_PSEUDOPRIVATE: - case InetAddress::IP_SCOPE_GLOBAL: - case InetAddress::IP_SCOPE_SHARED: - case InetAddress::IP_SCOPE_PRIVATE: - for(int x=0;x<(int)portCount;++x) { - ip.setPort(ports[x]); - localIfAddrs.insert(std::pair(ip,ifname)); + // Get IPv6 addresses (and any device names we don't already know) + OSUtils::ztsnprintf(fn,sizeof(fn),"/proc/%lu/net/if_inet6",pid); + procf = fopen(fn,"r"); + if (procf) { + while (fgets(tmp,sizeof(tmp),procf)) { + tmp[255] = 0; + char *saveptr = (char *)0; + unsigned char ipbits[16]; + memset(ipbits,0,sizeof(ipbits)); + char *devname = (char *)0; + int n = 0; + for(char *f=Utils::stok(tmp," \t\r\n",&saveptr);(f);f=Utils::stok((char *)0," \t\r\n",&saveptr)) { + switch(n++) { + case 0: // IP in hex + Utils::unhex(f,32,ipbits,16); + break; + case 5: // device name + devname = f; + break; } - break; } - } - } - - ip4_address_error: - free(configuration.ifc_buf); - if (controlfd > 0) close(controlfd); - } - - const bool gotViaProc = (localIfAddrs.size() > 0); -#else - const bool gotViaProc = false; -#endif - - if (!gotViaProc) { - struct ifaddrs *ifatbl = (struct ifaddrs *)0; - struct ifaddrs *ifa; - if ((getifaddrs(&ifatbl) == 0)&&(ifatbl)) { - ifa = ifatbl; - while (ifa) { - if ((ifa->ifa_name)&&(ifa->ifa_addr)) { - InetAddress ip = *(ifa->ifa_addr); - if (ifChecker.shouldBindInterface(ifa->ifa_name,ip)) { + if (devname) { + ifnames.insert(devname); + InetAddress ip(ipbits,16,0); + if (ifChecker.shouldBindInterface(devname,ip)) { switch(ip.ipScope()) { default: break; case InetAddress::IP_SCOPE_PSEUDOPRIVATE: @@ -311,23 +237,99 @@ public: case InetAddress::IP_SCOPE_PRIVATE: for(int x=0;x<(int)portCount;++x) { ip.setPort(ports[x]); - localIfAddrs.insert(std::pair(ip,std::string(ifa->ifa_name))); + localIfAddrs.insert(std::pair(ip,std::string(devname))); } break; } } } - ifa = ifa->ifa_next; } - freeifaddrs(ifatbl); + fclose(procf); } - else { - interfacesEnumerated = false; + + // Get IPv4 addresses for each device + if (ifnames.size() > 0) { + const int controlfd = (int)socket(AF_INET,SOCK_DGRAM,0); + struct ifconf configuration; + configuration.ifc_len = 0; + configuration.ifc_buf = nullptr; + + if (controlfd < 0) goto ip4_address_error; + if (ioctl(controlfd, SIOCGIFCONF, &configuration) < 0) goto ip4_address_error; + configuration.ifc_buf = (char*)malloc(configuration.ifc_len); + if (ioctl(controlfd, SIOCGIFCONF, &configuration) < 0) goto ip4_address_error; + + for (int i=0; i < (int)(configuration.ifc_len / sizeof(ifreq)); i ++) { + struct ifreq& request = configuration.ifc_req[i]; + struct sockaddr* addr = &request.ifr_ifru.ifru_addr; + if (addr->sa_family != AF_INET) continue; + std::string ifname = request.ifr_ifrn.ifrn_name; + // name can either be just interface name or interface name followed by ':' and arbitrary label + if (ifname.find(':') != std::string::npos) + ifname = ifname.substr(0, ifname.find(':')); + + InetAddress ip(&(((struct sockaddr_in *)addr)->sin_addr),4,0); + if (ifChecker.shouldBindInterface(ifname.c_str(), ip)) { + switch(ip.ipScope()) { + default: break; + case InetAddress::IP_SCOPE_PSEUDOPRIVATE: + case InetAddress::IP_SCOPE_GLOBAL: + case InetAddress::IP_SCOPE_SHARED: + case InetAddress::IP_SCOPE_PRIVATE: + for(int x=0;x<(int)portCount;++x) { + ip.setPort(ports[x]); + localIfAddrs.insert(std::pair(ip,ifname)); + } + break; + } + } + } + + ip4_address_error: + free(configuration.ifc_buf); + if (controlfd > 0) close(controlfd); } - } + const bool gotViaProc = (localIfAddrs.size() > 0); +#else + const bool gotViaProc = false; #endif + if (!gotViaProc) { + struct ifaddrs *ifatbl = (struct ifaddrs *)0; + struct ifaddrs *ifa; + if ((getifaddrs(&ifatbl) == 0)&&(ifatbl)) { + ifa = ifatbl; + while (ifa) { + if ((ifa->ifa_name)&&(ifa->ifa_addr)) { + InetAddress ip = *(ifa->ifa_addr); + if (ifChecker.shouldBindInterface(ifa->ifa_name,ip)) { + switch(ip.ipScope()) { + default: break; + case InetAddress::IP_SCOPE_PSEUDOPRIVATE: + case InetAddress::IP_SCOPE_GLOBAL: + case InetAddress::IP_SCOPE_SHARED: + case InetAddress::IP_SCOPE_PRIVATE: + for(int x=0;x<(int)portCount;++x) { + ip.setPort(ports[x]); + localIfAddrs.insert(std::pair(ip,std::string(ifa->ifa_name))); + } + break; + } + } + } + ifa = ifa->ifa_next; + } + freeifaddrs(ifatbl); + } + else { + interfacesEnumerated = false; + } + } + +#endif + } + // Default to binding to wildcard if we can't enumerate addresses if (!interfacesEnumerated && localIfAddrs.empty()) { for(int x=0;x<(int)portCount;++x) { diff --git a/service/OneService.cpp b/service/OneService.cpp index b6b6f5fe..a9a8171c 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -565,6 +565,7 @@ public: } // Read local configuration + bool bindToWildcard = false; { std::map ppc; @@ -626,12 +627,15 @@ public: } } - // Allow controller DB path to be put somewhere else json &settings = _localConfig["settings"]; if (settings.is_object()) { + // Allow controller DB path to be put somewhere else const std::string cdbp(OSUtils::jsonString(settings["controllerDbPath"],"")); if (cdbp.length() > 0) _controllerDbPath = cdbp; + + // Bind to wildcard instead of to specific interfaces (disables full tunnel capability) + bindToWildcard = OSUtils::jsonBool(settings["bindToWildcard"],false); } // Set trusted paths if there are any @@ -801,7 +805,7 @@ public: if (_ports[i]) p[pc++] = _ports[i]; } - _binder.refresh(_phy,p,pc,*this); + _binder.refresh(_phy,p,pc,bindToWildcard,*this); { Mutex::Lock _l(_nets_m); for(std::map::iterator n(_nets.begin());n!=_nets.end();++n) { diff --git a/service/README.md b/service/README.md index ad6bcb49..2a6cb154 100644 --- a/service/README.md +++ b/service/README.md @@ -31,7 +31,8 @@ Settings available in `local.conf` (this is not valid JSON, and JSON does not al "softwareUpdateChannel": "release"|"beta", /* Software update channel */ "softwareUpdateDist": true|false, /* If true, distribute software updates (only really useful to ZeroTier, Inc. itself, default is false) */ "interfacePrefixBlacklist": [ "XXX",... ], /* Array of interface name prefixes (e.g. eth for eth#) to blacklist for ZT traffic */ - "allowManagementFrom": "NETWORK/bits"|null /* If non-NULL, allow JSON/HTTP management from this IP network. Default is 127.0.0.1 only. */ + "allowManagementFrom": "NETWORK/bits"|null, /* If non-NULL, allow JSON/HTTP management from this IP network. Default is 127.0.0.1 only. */ + "bindToWildcard": true|false /* If true, bind to wildcard e.g. 0.0.0.0 instead of per interface */ } } ``` -- cgit v1.2.3 From 5f5302e59535c988188e3857469c5414014d62c4 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 25 Jan 2018 17:27:08 -0500 Subject: More useful to allow arrays of IPs to bind to. --- osdep/Binder.hpp | 9 ++++++--- service/OneService.cpp | 16 +++++++++++++--- service/README.md | 3 +-- 3 files changed, 20 insertions(+), 8 deletions(-) (limited to 'service/OneService.cpp') diff --git a/osdep/Binder.hpp b/osdep/Binder.hpp index f5fc32e3..d7c3f03c 100644 --- a/osdep/Binder.hpp +++ b/osdep/Binder.hpp @@ -126,20 +126,20 @@ public: * @param phy Physical interface * @param ports Ports to bind on all interfaces * @param portCount Number of ports - * @param bindtoWildcard If true, bind wildcard instead of per-interface IPs + * @param explicitBind If present, override interface IP detection and bind to these (if possible) * @param ifChecker Interface checker function to see if an interface should be used * @tparam PHY_HANDLER_TYPE Type for Phy<> template * @tparam INTERFACE_CHECKER Type for class containing shouldBindInterface() method */ template - void refresh(Phy &phy,unsigned int *ports,unsigned int portCount,bool bindToWildcard,INTERFACE_CHECKER &ifChecker) + void refresh(Phy &phy,unsigned int *ports,unsigned int portCount,const std::vector explicitBind,INTERFACE_CHECKER &ifChecker) { std::map localIfAddrs; PhySocket *udps,*tcps; Mutex::Lock _l(_lock); bool interfacesEnumerated = true; - if (!bindToWildcard) { + if (explicitBind.empty()) { #ifdef __WINDOWS__ char aabuf[32768]; @@ -328,6 +328,9 @@ public: } #endif + } else { + for(std::vector::const_iterator i(explicitBind.begin());i!=explicitBind.end();++i) + localIfAddrs.insert(std::pair(*i,std::string())); } // Default to binding to wildcard if we can't enumerate addresses diff --git a/service/OneService.cpp b/service/OneService.cpp index a9a8171c..bcdef04f 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -565,7 +565,7 @@ public: } // Read local configuration - bool bindToWildcard = false; + std::vector explicitBind; { std::map ppc; @@ -635,7 +635,17 @@ public: _controllerDbPath = cdbp; // Bind to wildcard instead of to specific interfaces (disables full tunnel capability) - bindToWildcard = OSUtils::jsonBool(settings["bindToWildcard"],false); + json &bind = settings["bind"]; + if (bind.is_array()) { + for(unsigned long i=0;i 0) { + InetAddress ip(ips.c_str()); + if ((ip.ss_family == AF_INET)||(ip.ss_family == AF_INET6)) + explicitBind.push_back(ip); + } + } + } } // Set trusted paths if there are any @@ -805,7 +815,7 @@ public: if (_ports[i]) p[pc++] = _ports[i]; } - _binder.refresh(_phy,p,pc,bindToWildcard,*this); + _binder.refresh(_phy,p,pc,explicitBind,*this); { Mutex::Lock _l(_nets_m); for(std::map::iterator n(_nets.begin());n!=_nets.end();++n) { diff --git a/service/README.md b/service/README.md index 2a6cb154..9ac097ab 100644 --- a/service/README.md +++ b/service/README.md @@ -32,13 +32,12 @@ Settings available in `local.conf` (this is not valid JSON, and JSON does not al "softwareUpdateDist": true|false, /* If true, distribute software updates (only really useful to ZeroTier, Inc. itself, default is false) */ "interfacePrefixBlacklist": [ "XXX",... ], /* Array of interface name prefixes (e.g. eth for eth#) to blacklist for ZT traffic */ "allowManagementFrom": "NETWORK/bits"|null, /* If non-NULL, allow JSON/HTTP management from this IP network. Default is 127.0.0.1 only. */ - "bindToWildcard": true|false /* If true, bind to wildcard e.g. 0.0.0.0 instead of per interface */ + "bind": [ "ip",... ] /* If present and non-null, bind to these IPs instead of to each interface (wildcard IP allowed) */ } } ``` * **trustedPathId**: A trusted path is a physical network over which encryption and authentication are not required. This provides a performance boost but sacrifices all ZeroTier's security features when communicating over this path. Only use this if you know what you are doing and really need the performance! To set up a trusted path, all devices using it *MUST* have the *same trusted path ID* for the same network. Trusted path IDs are arbitrary positive non-zero integers. For example a group of devices on a LAN with IPs in 10.0.0.0/24 could use it as a fast trusted path if they all had the same trusted path ID of "25" defined for that network. - * **relayPolicy**: Under what circumstances should this device relay traffic for other devices? The default is TRUSTED, meaning that we'll only relay for devices we know to be members of a network we have joined. NEVER is the default on mobile devices (iOS/Android) and tells us to never relay traffic. ALWAYS is usually only set for upstreams and roots, allowing them to act as promiscuous relays for anyone who desires it. An example `local.conf`: -- cgit v1.2.3 From f3dfd636343904a01681c80e91b44aa00ce33f2e Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 26 Jan 2018 20:00:37 -0500 Subject: Clean up some old stuff. --- node/Array.hpp | 117 --------------------------------------- node/C25519.hpp | 31 ++--------- node/CertificateOfMembership.cpp | 6 +- node/CertificateOfMembership.hpp | 10 ++-- node/Identity.cpp | 8 +-- node/Identity.hpp | 14 ++--- node/Multicaster.hpp | 66 +++++++++++----------- node/World.hpp | 4 +- one.cpp | 12 ++-- osdep/Phy.hpp | 23 ++++---- selftest.cpp | 10 ++-- service/OneService.cpp | 4 +- service/SoftwareUpdater.cpp | 26 +++++---- service/SoftwareUpdater.hpp | 6 +- 14 files changed, 101 insertions(+), 236 deletions(-) delete mode 100644 node/Array.hpp (limited to 'service/OneService.cpp') diff --git a/node/Array.hpp b/node/Array.hpp deleted file mode 100644 index de827c08..00000000 --- a/node/Array.hpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -#ifndef ZT_ARRAY_HPP -#define ZT_ARRAY_HPP - -#include - -namespace ZeroTier { - -/** - * Static array -- a simple thing that's belonged in STL since the time of the dinosaurs - */ -template -class Array -{ -public: - Array() {} - - Array(const Array &a) - { - for(unsigned long i=0;i reverse_iterator; - typedef std::reverse_iterator const_reverse_iterator; - - inline iterator begin() { return data; } - inline iterator end() { return &(data[S]); } - inline const_iterator begin() const { return data; } - inline const_iterator end() const { return &(data[S]); } - - inline reverse_iterator rbegin() { return reverse_iterator(begin()); } - inline reverse_iterator rend() { return reverse_iterator(end()); } - inline const_reverse_iterator rbegin() const { return const_reverse_iterator(begin()); } - inline const_reverse_iterator rend() const { return const_reverse_iterator(end()); } - */ - - inline unsigned long size() const { return S; } - inline unsigned long max_size() const { return S; } - - inline reference operator[](const std::size_t n) { return data[n]; } - inline const_reference operator[](const std::size_t n) const { return data[n]; } - - inline reference front() { return data[0]; } - inline const_reference front() const { return data[0]; } - inline reference back() { return data[S-1]; } - inline const_reference back() const { return data[S-1]; } - - inline bool operator==(const Array &k) const - { - for(unsigned long i=0;i(const Array &k) const { return (k < *this); } - inline bool operator<=(const Array &k) const { return !(k < *this); } - inline bool operator>=(const Array &k) const { return !(*this < k); } - - T data[S]; -}; - -} // namespace ZeroTier - -#endif diff --git a/node/C25519.hpp b/node/C25519.hpp index 3f22b445..2e9184a0 100644 --- a/node/C25519.hpp +++ b/node/C25519.hpp @@ -27,7 +27,6 @@ #ifndef ZT_C25519_HPP #define ZT_C25519_HPP -#include "Array.hpp" #include "Utils.hpp" namespace ZeroTier { @@ -42,28 +41,10 @@ namespace ZeroTier { class C25519 { public: - /** - * Public key (both crypto and signing) - */ - typedef Array Public; // crypto key, signing key (both 32 bytes) - - /** - * Private key (both crypto and signing) - */ - typedef Array Private; // crypto key, signing key (both 32 bytes) - - /** - * Message signature - */ - typedef Array Signature; - - /** - * Public/private key pair - */ - typedef struct { - Public pub; - Private priv; - } Pair; + struct Public { uint8_t data[ZT_C25519_PUBLIC_KEY_LEN]; }; + struct Private { uint8_t data[ZT_C25519_PRIVATE_KEY_LEN]; }; + struct Signature { uint8_t data[ZT_C25519_SIGNATURE_LEN]; }; + struct Pair { Public pub; Private priv; }; /** * Generate a C25519 elliptic curve key pair @@ -71,7 +52,7 @@ public: static inline Pair generate() { Pair kp; - Utils::getSecureRandom(kp.priv.data,(unsigned int)kp.priv.size()); + Utils::getSecureRandom(kp.priv.data,ZT_C25519_PRIVATE_KEY_LEN); _calcPubDH(kp); _calcPubED(kp); return kp; @@ -95,7 +76,7 @@ public: { Pair kp; void *const priv = (void *)kp.priv.data; - Utils::getSecureRandom(priv,(unsigned int)kp.priv.size()); + Utils::getSecureRandom(priv,ZT_C25519_PRIVATE_KEY_LEN); _calcPubED(kp); // do Ed25519 key -- bytes 32-63 of pub and priv do { ++(((uint64_t *)priv)[1]); diff --git a/node/CertificateOfMembership.cpp b/node/CertificateOfMembership.cpp index a849a44c..8184ce99 100644 --- a/node/CertificateOfMembership.cpp +++ b/node/CertificateOfMembership.cpp @@ -84,7 +84,7 @@ std::string CertificateOfMembership::toString() const if (_signedBy) { s.push_back(':'); - s.append(Utils::hex(_signature.data,(unsigned int)_signature.size(),tmp)); + s.append(Utils::hex(_signature.data,ZT_C25519_SIGNATURE_LEN,tmp)); } return s; @@ -94,7 +94,7 @@ void CertificateOfMembership::fromString(const char *s) { _qualifierCount = 0; _signedBy.zero(); - memset(_signature.data,0,_signature.size()); + memset(_signature.data,0,ZT_C25519_SIGNATURE_LEN); if (!*s) return; @@ -145,7 +145,7 @@ void CertificateOfMembership::fromString(const char *s) colonAt = 0; while ((s[colonAt])&&(s[colonAt] != ':')) ++colonAt; if (colonAt) { - if (Utils::unhex(s,colonAt,_signature.data,(unsigned int)_signature.size()) != _signature.size()) + if (Utils::unhex(s,colonAt,_signature.data,ZT_C25519_SIGNATURE_LEN) != ZT_C25519_SIGNATURE_LEN) _signedBy.zero(); } else { _signedBy.zero(); diff --git a/node/CertificateOfMembership.hpp b/node/CertificateOfMembership.hpp index 19fe5367..b5a90007 100644 --- a/node/CertificateOfMembership.hpp +++ b/node/CertificateOfMembership.hpp @@ -142,7 +142,7 @@ public: _qualifiers[2].value = issuedTo.toInt(); _qualifiers[2].maxDelta = 0xffffffffffffffffULL; _qualifierCount = 3; - memset(_signature.data,0,_signature.size()); + memset(_signature.data,0,ZT_C25519_SIGNATURE_LEN); } inline CertificateOfMembership &operator=(const CertificateOfMembership &c) @@ -293,7 +293,7 @@ public: } _signedBy.appendTo(b); if (_signedBy) - b.append(_signature.data,(unsigned int)_signature.size()); + b.append(_signature.data,ZT_C25519_SIGNATURE_LEN); } template @@ -329,8 +329,8 @@ public: p += ZT_ADDRESS_LENGTH; if (_signedBy) { - ZT_FAST_MEMCPY(_signature.data,b.field(p,(unsigned int)_signature.size()),_signature.size()); - p += (unsigned int)_signature.size(); + ZT_FAST_MEMCPY(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); + p += ZT_C25519_SIGNATURE_LEN; } return (p - startAt); @@ -348,7 +348,7 @@ public: if ((a.id != b.id)||(a.value != b.value)||(a.maxDelta != b.maxDelta)) return false; } - return (_signature == c._signature); + return (memcmp(_signature.data,c._signature.data,ZT_C25519_SIGNATURE_LEN) == 0); } inline bool operator!=(const CertificateOfMembership &c) const { return (!(*this == c)); } diff --git a/node/Identity.cpp b/node/Identity.cpp index 9cc507f7..03f27083 100644 --- a/node/Identity.cpp +++ b/node/Identity.cpp @@ -87,7 +87,7 @@ struct _Identity_generate_cond _Identity_generate_cond(unsigned char *sb,char *gm) : digest(sb),genmem(gm) {} inline bool operator()(const C25519::Pair &kp) const { - _computeMemoryHardHash(kp.pub.data,(unsigned int)kp.pub.size(),digest,genmem); + _computeMemoryHardHash(kp.pub.data,ZT_C25519_PUBLIC_KEY_LEN,digest,genmem); return (digest[0] < ZT_IDENTITY_GEN_HASHCASH_FIRST_BYTE_LESS_THAN); } unsigned char *digest; @@ -120,7 +120,7 @@ bool Identity::locallyValidate() const unsigned char digest[64]; char *genmem = new char[ZT_IDENTITY_GEN_MEMORY]; - _computeMemoryHardHash(_publicKey.data,(unsigned int)_publicKey.size(),digest,genmem); + _computeMemoryHardHash(_publicKey.data,ZT_C25519_PUBLIC_KEY_LEN,digest,genmem); delete [] genmem; unsigned char addrb[5]; @@ -187,14 +187,14 @@ bool Identity::fromString(const char *str) } break; case 2: - if (Utils::unhex(f,_publicKey.data,(unsigned int)_publicKey.size()) != _publicKey.size()) { + if (Utils::unhex(f,_publicKey.data,ZT_C25519_PUBLIC_KEY_LEN) != ZT_C25519_PUBLIC_KEY_LEN) { _address.zero(); return false; } break; case 3: _privateKey = new C25519::Private(); - if (Utils::unhex(f,_privateKey->data,(unsigned int)_privateKey->size()) != _privateKey->size()) { + if (Utils::unhex(f,_privateKey->data,ZT_C25519_PRIVATE_KEY_LEN) != ZT_C25519_PRIVATE_KEY_LEN) { _address.zero(); return false; } diff --git a/node/Identity.hpp b/node/Identity.hpp index 74514436..74716aa0 100644 --- a/node/Identity.hpp +++ b/node/Identity.hpp @@ -215,10 +215,10 @@ public: { _address.appendTo(b); b.append((uint8_t)0); // C25519/Ed25519 identity type - b.append(_publicKey.data,(unsigned int)_publicKey.size()); + b.append(_publicKey.data,ZT_C25519_PUBLIC_KEY_LEN); if ((_privateKey)&&(includePrivate)) { - b.append((unsigned char)_privateKey->size()); - b.append(_privateKey->data,(unsigned int)_privateKey->size()); + b.append((unsigned char)ZT_C25519_PRIVATE_KEY_LEN); + b.append(_privateKey->data,ZT_C25519_PRIVATE_KEY_LEN); } else b.append((unsigned char)0); } @@ -248,8 +248,8 @@ public: if (b[p++] != 0) throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE; - ZT_FAST_MEMCPY(_publicKey.data,b.field(p,(unsigned int)_publicKey.size()),(unsigned int)_publicKey.size()); - p += (unsigned int)_publicKey.size(); + ZT_FAST_MEMCPY(_publicKey.data,b.field(p,ZT_C25519_PUBLIC_KEY_LEN),ZT_C25519_PUBLIC_KEY_LEN); + p += ZT_C25519_PUBLIC_KEY_LEN; unsigned int privateKeyLength = (unsigned int)b[p++]; if (privateKeyLength) { @@ -306,8 +306,8 @@ public: */ inline operator bool() const { return (_address); } - inline bool operator==(const Identity &id) const { return ((_address == id._address)&&(_publicKey == id._publicKey)); } - inline bool operator<(const Identity &id) const { return ((_address < id._address)||((_address == id._address)&&(_publicKey < id._publicKey))); } + inline bool operator==(const Identity &id) const { return ((_address == id._address)&&(memcmp(_publicKey.data,id._publicKey.data,ZT_C25519_PUBLIC_KEY_LEN) == 0)); } + inline bool operator<(const Identity &id) const { return ((_address < id._address)||((_address == id._address)&&(memcmp(_publicKey.data,id._publicKey.data,ZT_C25519_PUBLIC_KEY_LEN) < 0))); } inline bool operator!=(const Identity &id) const { return !(*this == id); } inline bool operator>(const Identity &id) const { return (id < *this); } inline bool operator<=(const Identity &id) const { return !(id < *this); } diff --git a/node/Multicaster.hpp b/node/Multicaster.hpp index 59959328..999efb61 100644 --- a/node/Multicaster.hpp +++ b/node/Multicaster.hpp @@ -42,7 +42,6 @@ #include "OutboundMulticast.hpp" #include "Utils.hpp" #include "Mutex.hpp" -#include "NonCopyable.hpp" namespace ZeroTier { @@ -53,39 +52,8 @@ class Packet; /** * Database of known multicast peers within a network */ -class Multicaster : NonCopyable +class Multicaster { -private: - struct Key - { - Key() : nwid(0),mg() {} - Key(uint64_t n,const MulticastGroup &g) : nwid(n),mg(g) {} - - uint64_t nwid; - MulticastGroup 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))); } - }; - - struct MulticastGroupMember - { - MulticastGroupMember() {} - MulticastGroupMember(const Address &a,uint64_t ts) : address(a),timestamp(ts) {} - - Address address; - uint64_t timestamp; // time of last notification - }; - - struct MulticastGroupStatus - { - MulticastGroupStatus() : lastExplicitGather(0) {} - - uint64_t lastExplicitGather; - std::list txQueue; // pending outbound multicasts - std::vector members; // members of this group - }; - public: Multicaster(const RuntimeEnvironment *renv); ~Multicaster(); @@ -220,9 +188,39 @@ public: } private: + struct Key + { + Key() : nwid(0),mg() {} + Key(uint64_t n,const MulticastGroup &g) : nwid(n),mg(g) {} + + uint64_t nwid; + MulticastGroup 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))); } + }; + + struct MulticastGroupMember + { + MulticastGroupMember() {} + MulticastGroupMember(const Address &a,uint64_t ts) : address(a),timestamp(ts) {} + + Address address; + uint64_t timestamp; // time of last notification + }; + + struct MulticastGroupStatus + { + MulticastGroupStatus() : lastExplicitGather(0) {} + + uint64_t lastExplicitGather; + std::list txQueue; // pending outbound multicasts + std::vector members; // members of this group + }; + void _add(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup &mg,MulticastGroupStatus &gs,const Address &member); - const RuntimeEnvironment *RR; + const RuntimeEnvironment *const RR; Hashtable _groups; Mutex _groups_m; diff --git a/node/World.hpp b/node/World.hpp index 459470ca..9edf2a6a 100644 --- a/node/World.hpp +++ b/node/World.hpp @@ -240,11 +240,9 @@ public: return (p - startAt); } - inline bool operator==(const World &w) const { return ((_id == w._id)&&(_ts == w._ts)&&(_updatesMustBeSignedBy == w._updatesMustBeSignedBy)&&(_signature == w._signature)&&(_roots == w._roots)&&(_type == w._type)); } + inline bool operator==(const World &w) const { return ((_id == w._id)&&(_ts == w._ts)&&(memcmp(_updatesMustBeSignedBy.data,w._updatesMustBeSignedBy.data,ZT_C25519_PUBLIC_KEY_LEN) == 0)&&(memcmp(_signature.data,w._signature.data,ZT_C25519_SIGNATURE_LEN) == 0)&&(_roots == w._roots)&&(_type == w._type)); } inline bool operator!=(const World &w) const { return (!(*this == w)); } - inline bool operator<(const World &w) const { return (((int)_type < (int)w._type) ? true : ((_type == w._type) ? (_id < w._id) : false)); } - /** * Create a World object signed with a key pair * diff --git a/one.cpp b/one.cpp index a8f51b45..4bf35e82 100644 --- a/one.cpp +++ b/one.cpp @@ -795,7 +795,7 @@ static int idtool(int argc,char **argv) } C25519::Signature signature = id.sign(inf.data(),(unsigned int)inf.length()); char hexbuf[1024]; - printf("%s",Utils::hex(signature.data,(unsigned int)signature.size(),hexbuf)); + printf("%s",Utils::hex(signature.data,ZT_C25519_SIGNATURE_LEN,hexbuf)); } else if (!strcmp(argv[1],"verify")) { if (argc < 4) { idtoolPrintHelp(stdout,argv[0]); @@ -838,8 +838,8 @@ static int idtool(int argc,char **argv) nlohmann::json mj; mj["objtype"] = "world"; mj["worldType"] = "moon"; - mj["updatesMustBeSignedBy"] = mj["signingKey"] = Utils::hex(kp.pub.data,(unsigned int)kp.pub.size(),idtmp); - mj["signingKey_SECRET"] = Utils::hex(kp.priv.data,(unsigned int)kp.priv.size(),idtmp); + mj["updatesMustBeSignedBy"] = mj["signingKey"] = Utils::hex(kp.pub.data,ZT_C25519_PUBLIC_KEY_LEN,idtmp); + mj["signingKey_SECRET"] = Utils::hex(kp.priv.data,ZT_C25519_PRIVATE_KEY_LEN,idtmp); mj["id"] = id.address().toString(idtmp); nlohmann::json seedj; seedj["identity"] = id.toString(false,idtmp); @@ -878,9 +878,9 @@ static int idtool(int argc,char **argv) C25519::Pair signingKey; C25519::Public updatesMustBeSignedBy; - Utils::unhex(OSUtils::jsonString(mj["signingKey"],"").c_str(),signingKey.pub.data,(unsigned int)signingKey.pub.size()); - Utils::unhex(OSUtils::jsonString(mj["signingKey_SECRET"],"").c_str(),signingKey.priv.data,(unsigned int)signingKey.priv.size()); - Utils::unhex(OSUtils::jsonString(mj["updatesMustBeSignedBy"],"").c_str(),updatesMustBeSignedBy.data,(unsigned int)updatesMustBeSignedBy.size()); + Utils::unhex(OSUtils::jsonString(mj["signingKey"],"").c_str(),signingKey.pub.data,ZT_C25519_PUBLIC_KEY_LEN); + Utils::unhex(OSUtils::jsonString(mj["signingKey_SECRET"],"").c_str(),signingKey.priv.data,ZT_C25519_PRIVATE_KEY_LEN); + Utils::unhex(OSUtils::jsonString(mj["updatesMustBeSignedBy"],"").c_str(),updatesMustBeSignedBy.data,ZT_C25519_PUBLIC_KEY_LEN); std::vector roots; nlohmann::json &rootsj = mj["roots"]; diff --git a/osdep/Phy.hpp b/osdep/Phy.hpp index 8e683f10..243db0a8 100644 --- a/osdep/Phy.hpp +++ b/osdep/Phy.hpp @@ -688,25 +688,26 @@ public: * until one works. * * @param sock Socket - * @param bufferSize Desired buffer sizes + * @param receiveBufferSize Desired size of receive buffer + * @param sendBufferSize Desired size of send buffer */ - inline void setBufferSizes(const PhySocket *sock,int bufferSize) + inline void setBufferSizes(const PhySocket *sock,int receiveBufferSize,int sendBufferSize) { PhySocketImpl &sws = *(reinterpret_cast(sock)); - if (bufferSize > 0) { - int bs = bufferSize; - while (bs >= 65536) { - int tmpbs = bs; + if (receiveBufferSize > 0) { + while (receiveBufferSize > 0) { + int tmpbs = receiveBufferSize; if (::setsockopt(sws.sock,SOL_SOCKET,SO_RCVBUF,(const char *)&tmpbs,sizeof(tmpbs)) == 0) break; - bs -= 16384; + receiveBufferSize -= 16384; } - bs = bufferSize; - while (bs >= 65536) { - int tmpbs = bs; + } + if (sendBufferSize > 0) { + while (sendBufferSize > 0) { + int tmpbs = sendBufferSize; if (::setsockopt(sws.sock,SOL_SOCKET,SO_SNDBUF,(const char *)&tmpbs,sizeof(tmpbs)) == 0) break; - bs -= 16384; + sendBufferSize -= 16384; } } } diff --git a/selftest.cpp b/selftest.cpp index c3fd397c..cf3bbdeb 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -321,10 +321,10 @@ static int testCrypto() std::cout << "[crypto] Testing C25519 and Ed25519 against test vectors... "; std::cout.flush(); for(int k=0;k::const_iterator r(world.roots().begin());r!=world.roots().end();++r) { nlohmann::json rj; diff --git a/service/SoftwareUpdater.cpp b/service/SoftwareUpdater.cpp index 6a25dbec..d12861d4 100644 --- a/service/SoftwareUpdater.cpp +++ b/service/SoftwareUpdater.cpp @@ -126,11 +126,13 @@ void SoftwareUpdater::setUpdateDistribution(bool distribute) const std::string binPath(udd + ZT_PATH_SEPARATOR_S + u->substr(0,u->length() - 5)); const std::string metaHash(OSUtils::jsonBinFromHex(d.meta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH])); if ((metaHash.length() == ZT_SHA512_DIGEST_LEN)&&(OSUtils::readFile(binPath.c_str(),d.bin))) { - uint8_t sha512[ZT_SHA512_DIGEST_LEN]; - SHA512::hash(sha512,d.bin.data(),(unsigned int)d.bin.length()); - if (!memcmp(sha512,metaHash.data(),ZT_SHA512_DIGEST_LEN)) { // double check that hash in JSON is correct + std::array sha512; + SHA512::hash(sha512.data(),d.bin.data(),(unsigned int)d.bin.length()); + if (!memcmp(sha512.data(),metaHash.data(),ZT_SHA512_DIGEST_LEN)) { // double check that hash in JSON is correct d.meta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIZE] = d.bin.length(); // override with correct value -- setting this in meta json is optional - _dist[Array(sha512)] = d; + std::array shakey; + memcpy(shakey.data(),sha512.data(),16); + _dist[shakey] = d; if (_distLog) { fprintf(_distLog,".......... INIT: DISTRIBUTING %s (%u bytes)" ZT_EOL_S,binPath.c_str(),(unsigned int)d.bin.length()); fflush(_distLog); @@ -179,7 +181,7 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void unsigned int bestVMin = rvMin; unsigned int bestVRev = rvRev; unsigned int bestVBld = rvBld; - for(std::map< Array,_D >::const_iterator d(_dist.begin());d!=_dist.end();++d) { + for(std::map< std::array,_D >::const_iterator d(_dist.begin());d!=_dist.end();++d) { // The arch field in update description .json files can be an array for e.g. multi-arch update files const nlohmann::json &dvArch2 = d->second.meta[ZT_SOFTWARE_UPDATE_JSON_ARCHITECTURE]; std::vector dvArch; @@ -233,14 +235,14 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void _latestValid = false; OSUtils::rm((_homePath + ZT_PATH_SEPARATOR_S ZT_SOFTWARE_UPDATE_BIN_FILENAME).c_str()); _download = std::string(); - memcpy(_downloadHashPrefix.data,hash.data(),16); + memcpy(_downloadHashPrefix.data(),hash.data(),16); _downloadLength = len; } if ((_downloadLength > 0)&&(_download.length() < _downloadLength)) { Buffer<128> gd; gd.append((uint8_t)VERB_GET_DATA); - gd.append(_downloadHashPrefix.data,16); + gd.append(_downloadHashPrefix.data(),16); gd.append((uint32_t)_download.length()); _node.sendUserMessage((void *)0,ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,gd.data(),gd.size()); } @@ -257,7 +259,9 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void idx |= (unsigned long)*(reinterpret_cast(data) + 18) << 16; idx |= (unsigned long)*(reinterpret_cast(data) + 19) << 8; idx |= (unsigned long)*(reinterpret_cast(data) + 20); - std::map< Array,_D >::iterator d(_dist.find(Array(reinterpret_cast(data) + 1))); + std::array shakey; + memcpy(shakey.data(),reinterpret_cast(data) + 1,16); + std::map< std::array,_D >::iterator d(_dist.find(shakey)); if ((d != _dist.end())&&(idx < (unsigned long)d->second.bin.length())) { Buffer buf; buf.append((uint8_t)VERB_DATA); @@ -270,7 +274,7 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void break; case VERB_DATA: - if ((len >= 21)&&(_downloadLength > 0)&&(!memcmp(_downloadHashPrefix.data,reinterpret_cast(data) + 1,16))) { + if ((len >= 21)&&(_downloadLength > 0)&&(!memcmp(_downloadHashPrefix.data(),reinterpret_cast(data) + 1,16))) { unsigned long idx = (unsigned long)*(reinterpret_cast(data) + 17) << 24; idx |= (unsigned long)*(reinterpret_cast(data) + 18) << 16; idx |= (unsigned long)*(reinterpret_cast(data) + 19) << 8; @@ -280,7 +284,7 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void if (_download.length() < _downloadLength) { Buffer<128> gd; gd.append((uint8_t)VERB_GET_DATA); - gd.append(_downloadHashPrefix.data,16); + gd.append(_downloadHashPrefix.data(),16); gd.append((uint32_t)_download.length()); _node.sendUserMessage((void *)0,ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,gd.data(),gd.size()); } @@ -371,7 +375,7 @@ bool SoftwareUpdater::check(const int64_t now) } else { Buffer<128> gd; gd.append((uint8_t)VERB_GET_DATA); - gd.append(_downloadHashPrefix.data,16); + gd.append(_downloadHashPrefix.data(),16); gd.append((uint32_t)_download.length()); _node.sendUserMessage((void *)0,ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,gd.data(),gd.size()); } diff --git a/service/SoftwareUpdater.hpp b/service/SoftwareUpdater.hpp index ed329b1f..7f73eba2 100644 --- a/service/SoftwareUpdater.hpp +++ b/service/SoftwareUpdater.hpp @@ -33,11 +33,11 @@ #include #include #include +#include #include "../include/ZeroTierOne.h" #include "../node/Identity.hpp" -#include "../node/Array.hpp" #include "../node/Packet.hpp" #include "../ext/json/json.hpp" @@ -202,13 +202,13 @@ private: nlohmann::json meta; std::string bin; }; - std::map< Array,_D > _dist; // key is first 16 bytes of hash + std::map< std::array,_D > _dist; // key is first 16 bytes of hash nlohmann::json _latestMeta; bool _latestValid; std::string _download; - Array _downloadHashPrefix; + std::array _downloadHashPrefix; unsigned long _downloadLength; }; -- cgit v1.2.3 From 73ca9b6373a758bcba7d589064dd2cfb27208d3a Mon Sep 17 00:00:00 2001 From: neutronscott Date: Sat, 3 Feb 2018 14:53:46 -0500 Subject: check physical blacklist for interface binding as well --- service/OneService.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 27b71141..250e4b38 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -2414,7 +2414,22 @@ public: return false; } } - + { + // Check global blacklists + const std::vector *gbl = (const std::vector *)0; + if (ifaddr.ss_family == AF_INET) { + gbl = &_globalV4Blacklist; + } else if (ifaddr.ss_family == AF_INET6) { + gbl = &_globalV6Blacklist; + } + if (gbl) { + Mutex::Lock _l(_localConfig_m); + for(std::vector::const_iterator a(gbl->begin());a!=gbl->end();++a) { + if (a->containsAddress(ifaddr)) + return false; + } + } + } { Mutex::Lock _l(_nets_m); for(std::map::const_iterator n(_nets.begin());n!=_nets.end();++n) { -- cgit v1.2.3 From db952a050a727717a5cd836c79a50d7504a9b9ef Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Thu, 8 Feb 2018 14:15:32 -0800 Subject: Added platform checks for Windows in OneService --- service/OneService.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 27b71141..4854d68d 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1593,7 +1593,7 @@ public: if (syncRoutes) { char tapdev[64]; -#ifdef __WINDOWS__ +#if defined(__WINDOWS__) && !defined(ZT_SDK) OSUtils::ztsnprintf(tapdev,sizeof(tapdev),"%.16llx",(unsigned long long)n.tap->luid().Value); #else Utils::scopy(tapdev,sizeof(tapdev),n.tap->deviceName().c_str()); @@ -1998,7 +1998,7 @@ public: case ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE: ZT_FAST_MEMCPY(&(n.config),nwc,sizeof(ZT_VirtualNetworkConfig)); if (n.tap) { // sanity check -#ifdef __WINDOWS__ +#if defined(__WINDOWS__) && !defined(ZT_SDK) // wait for up to 5 seconds for the WindowsEthernetTap to actually be initialized // // without WindowsEthernetTap::isInitialized() returning true, the won't actually @@ -2019,7 +2019,7 @@ public: case ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN: case ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY: if (n.tap) { // sanity check -#ifdef __WINDOWS__ +#if defined(__WINDOWS__) && !defined(ZT_SDK) std::string winInstanceId(n.tap->instanceId()); #endif *nuptr = (void *)0; -- cgit v1.2.3 From 916077012ed4810492d6e45ed07222cdbb750fc0 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 16 Mar 2018 11:27:11 -0700 Subject: Make sure fopen is in binary mode on Windows. --- service/OneService.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 4854d68d..abbd6e75 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -2118,7 +2118,7 @@ public: // Check to see if we've already written this first. This reduces // redundant writes and I/O overhead on most platforms and has // little effect on others. - f = fopen(p,"r"); + f = fopen(p,"rb"); if (f) { char buf[65535]; long l = (long)fread(buf,1,sizeof(buf),f); @@ -2127,10 +2127,10 @@ public: return; } - f = fopen(p,"w"); + f = fopen(p,"wb"); if ((!f)&&(dirname[0])) { // create subdirectory if it does not exist OSUtils::mkdir(dirname); - f = fopen(p,"w"); + f = fopen(p,"wb"); } if (f) { if (fwrite(data,len,1,f) != 1) @@ -2171,7 +2171,7 @@ public: default: return -1; } - FILE *f = fopen(p,"r"); + FILE *f = fopen(p,"rb"); if (f) { int n = (int)fread(data,1,maxlen,f); fclose(f); -- cgit v1.2.3