From a425bbc67301bf486fe5b0aba8adb59ae791403e Mon Sep 17 00:00:00 2001 From: Kees Bos Date: Wed, 6 May 2015 12:05:20 +0200 Subject: [PATCH 01/37] Renamed supernode to rootserver --- README.md | 2 +- include/ZeroTierOne.h | 4 +- java/jni/ZT1_jniutils.cpp | 4 +- java/src/com/zerotier/sdk/Event.java | 2 +- java/src/com/zerotier/sdk/PeerRole.java | 4 +- node/Constants.hpp | 6 +- node/Dictionary.cpp | 9 +- node/Dictionary.hpp | 3 + node/IncomingPacket.cpp | 12 +-- node/Multicaster.cpp | 6 +- node/Network.cpp | 6 +- node/Node.cpp | 14 +-- node/Packet.hpp | 2 +- node/Peer.cpp | 6 +- node/SelfAwareness.cpp | 2 +- node/Switch.cpp | 26 ++--- node/Topology.cpp | 102 +++++++++--------- node/Topology.hpp | 64 +++++------ root-topology/README.md | 6 +- root-topology/ZT_DEFAULT_ROOT_TOPOLOGY.dict | 2 +- root-topology/mktopology.cpp | 18 ++-- .../{supernodes => rootservers}/7e19876aba | 0 .../{supernodes => rootservers}/8841408a2e | 0 .../{supernodes => rootservers}/8acf059fe3 | 0 .../{supernodes => rootservers}/9d219039f3 | 0 root-topology/test/README.md | 2 +- .../test/create-test-root-topology.sh | 12 +-- service/ControlPlane.cpp | 2 +- service/README.md | 4 +- tcp-proxy/tcp-proxy.cpp | 2 +- 30 files changed, 166 insertions(+), 156 deletions(-) rename root-topology/{supernodes => rootservers}/7e19876aba (100%) rename root-topology/{supernodes => rootservers}/8841408a2e (100%) rename root-topology/{supernodes => rootservers}/8acf059fe3 (100%) rename root-topology/{supernodes => rootservers}/9d219039f3 (100%) diff --git a/README.md b/README.md index f2ae10528..248065047 100644 --- a/README.md +++ b/README.md @@ -164,7 +164,7 @@ Users behind certain types of firewalls and "symmetric" NAT devices may not able If you're interested, there's a [technical deep dive about NAT traversal on our blog](https://www.zerotier.com/blog/?p=226). A troubleshooting tool to help you diagnose NAT issues is planned for the future as are uPnP/IGD/NAT-PMP and IPv6 transport. -If a firewall between you and the Internet blocks ZeroTier's UDP traffic, you will fall back to last-resort TCP tunneling to supernodes over port 443 (https impersonation). This will work almost anywhere but is *very slow* compared to UDP or direct peer to peer connectivity. +If a firewall between you and the Internet blocks ZeroTier's UDP traffic, you will fall back to last-resort TCP tunneling to rootservers over port 443 (https impersonation). This will work almost anywhere but is *very slow* compared to UDP or direct peer to peer connectivity. ### License diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 9b82c8d6f..b67d97edf 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -251,7 +251,7 @@ enum ZT1_Event /** * A more recent version was observed on the network * - * Right now this is only triggered if a hub or supernode reports a + * Right now this is only triggered if a hub or rootserver reports a * more recent version, and only once. It can be used to trigger a * software update check. * @@ -560,7 +560,7 @@ typedef struct enum ZT1_PeerRole { ZT1_PEER_ROLE_LEAF = 0, // ordinary node ZT1_PEER_ROLE_HUB = 1, // locally federated hub - ZT1_PEER_ROLE_SUPERNODE = 2 // planetary supernode + ZT1_PEER_ROLE_ROOTSERVER = 2 // planetary rootserver }; /** diff --git a/java/jni/ZT1_jniutils.cpp b/java/jni/ZT1_jniutils.cpp index e6404e87e..8779c3c35 100644 --- a/java/jni/ZT1_jniutils.cpp +++ b/java/jni/ZT1_jniutils.cpp @@ -174,8 +174,8 @@ jobject createPeerRole(JNIEnv *env, ZT1_PeerRole role) case ZT1_PEER_ROLE_HUB: fieldName = "PEER_ROLE_HUB"; break; - case ZT1_PEER_ROLE_SUPERNODE: - fieldName = "PEER_ROLE_SUPERNODE"; + case ZT1_PEER_ROLE_ROOTSERVER: + fieldName = "PEER_ROLE_ROOTSERVER"; break; } diff --git a/java/src/com/zerotier/sdk/Event.java b/java/src/com/zerotier/sdk/Event.java index d315990b1..436b1b226 100644 --- a/java/src/com/zerotier/sdk/Event.java +++ b/java/src/com/zerotier/sdk/Event.java @@ -90,7 +90,7 @@ public enum Event { /** * A more recent version was observed on the network * - *

Right now this is only triggered if a hub or supernode reports a + *

Right now this is only triggered if a hub or rootserver reports a * more recent version, and only once. It can be used to trigger a * software update check.

* diff --git a/java/src/com/zerotier/sdk/PeerRole.java b/java/src/com/zerotier/sdk/PeerRole.java index 56c3ac0c8..7a5156e1b 100644 --- a/java/src/com/zerotier/sdk/PeerRole.java +++ b/java/src/com/zerotier/sdk/PeerRole.java @@ -39,7 +39,7 @@ public enum PeerRole { PEER_ROLE_HUB, /** - * planetary supernode + * planetary rootserver */ - PEER_ROLE_SUPERNODE + PEER_ROLE_ROOTSERVER } \ No newline at end of file diff --git a/node/Constants.hpp b/node/Constants.hpp index ed227f9f7..aced6fe72 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -254,7 +254,7 @@ /** * Delay between scans of the topology active peer DB for peers that need ping * - * This is also how often pings will be retried to upstream peers (supernodes) + * This is also how often pings will be retried to upstream peers (rootservers) * constantly until something is heard. */ #define ZT_PING_CHECK_INVERVAL 6250 @@ -279,9 +279,9 @@ * * When we send something (including frames), we generally expect a response. * Switching relays if no response in a short period of time causes more - * rapid failover if a supernode goes down or becomes unreachable. In the + * rapid failover if a rootserver goes down or becomes unreachable. In the * mistaken case, little harm is done as it'll pick the next-fastest - * supernode and will switch back eventually. + * rootserver and will switch back eventually. */ #define ZT_PEER_RELAY_CONVERSATION_LATENCY_THRESHOLD 10000 diff --git a/node/Dictionary.cpp b/node/Dictionary.cpp index b3b015255..fb49002a5 100644 --- a/node/Dictionary.cpp +++ b/node/Dictionary.cpp @@ -32,9 +32,8 @@ namespace ZeroTier { -void Dictionary::fromString(const char *s,unsigned int maxlen) +void Dictionary::updateFromString(const char *s,unsigned int maxlen) { - clear(); bool escapeState = false; std::string keyBuf; std::string *element = &keyBuf; @@ -75,6 +74,12 @@ void Dictionary::fromString(const char *s,unsigned int maxlen) (*this)[keyBuf]; } +void Dictionary::fromString(const char *s,unsigned int maxlen) +{ + clear(); + updateFromString(s,maxlen); +} + bool Dictionary::sign(const Identity &id,uint64_t now) { try { diff --git a/node/Dictionary.hpp b/node/Dictionary.hpp index afdc2d74c..8628bc444 100644 --- a/node/Dictionary.hpp +++ b/node/Dictionary.hpp @@ -259,6 +259,9 @@ public: */ void fromString(const char *s,unsigned int maxlen); inline void fromString(const std::string &s) { fromString(s.c_str(),(unsigned int)s.length()); } + void updateFromString(const char *s,unsigned int maxlen); + inline void update(const char *s,unsigned int maxlen) { updateFromString(s, maxlen); } + inline void update(const std::string &s) { updateFromString(s.c_str(),(unsigned int)s.length()); } /** * @return True if this dictionary is cryptographically signed diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 8b228de52..5c83f24f4 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -110,7 +110,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr case Packet::ERROR_OBJ_NOT_FOUND: if (inReVerb == Packet::VERB_WHOIS) { - if (RR->topology->isSupernode(peer->address())) + if (RR->topology->isRootserver(peer->address())) RR->sw->cancelWhoisRequest(Address(field(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH)); } else if (inReVerb == Packet::VERB_NETWORK_CONFIG_REQUEST) { SharedPtr network(RR->node->network(at(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD))); @@ -128,7 +128,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr break; case Packet::ERROR_IDENTITY_COLLISION: - if (RR->topology->isSupernode(peer->address())) + if (RR->topology->isRootserver(peer->address())) RR->node->postEvent(ZT1_EVENT_FATAL_ERROR_IDENTITY_COLLISION); break; @@ -268,7 +268,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR) peer->setRemoteVersion(protoVersion,vMajor,vMinor,vRevision); bool trusted = false; - if (RR->topology->isSupernode(id.address())) { + if (RR->topology->isRootserver(id.address())) { RR->node->postNewerVersionIfNewer(vMajor,vMinor,vRevision); trusted = true; } @@ -353,7 +353,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr &p peer->setRemoteVersion(vProto,vMajor,vMinor,vRevision); bool trusted = false; - if (RR->topology->isSupernode(peer->address())) { + if (RR->topology->isRootserver(peer->address())) { RR->node->postNewerVersionIfNewer(vMajor,vMinor,vRevision); trusted = true; } @@ -362,10 +362,10 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr &p } break; case Packet::VERB_WHOIS: { - // Right now only supernodes are allowed to send OK(WHOIS) to prevent + // Right now only rootservers are allowed to send OK(WHOIS) to prevent // poisoning attacks. Further decentralization will require some other // kind of trust mechanism. - if (RR->topology->isSupernode(peer->address())) { + if (RR->topology->isRootserver(peer->address())) { const Identity id(*this,ZT_PROTO_VERB_WHOIS__OK__IDX_IDENTITY); if (id.locallyValidate()) RR->sw->doAnythingWaitingForPeer(RR->topology->addPeer(SharedPtr(new Peer(RR->identity,id)))); diff --git a/node/Multicaster.cpp b/node/Multicaster.cpp index 7da2b14c3..0cc4fb877 100644 --- a/node/Multicaster.cpp +++ b/node/Multicaster.cpp @@ -216,7 +216,7 @@ void Multicaster::send( if ((now - gs.lastExplicitGather) >= ZT_MULTICAST_EXPLICIT_GATHER_DELAY) { gs.lastExplicitGather = now; - SharedPtr sn(RR->topology->getBestSupernode()); + SharedPtr sn(RR->topology->getBestRootserver()); if (sn) { TRACE(">>MC upstream GATHER up to %u for group %.16llx/%s",gatherLimit,nwid,mg.toString().c_str()); @@ -271,12 +271,12 @@ void Multicaster::send( delete [] indexes; #ifdef ZT_SUPPORT_LEGACY_MULTICAST - // This sends a P5 multicast up to our supernode, who then + // This sends a P5 multicast up to our rootserver, who then // redistributes it manually down to all <1.0.0 peers for // legacy support. These peers don't support the new multicast // frame type, so even if they receive it they will ignore it. { - SharedPtr sn(RR->topology->getBestSupernode()); + SharedPtr sn(RR->topology->getBestRootserver()); if (sn) { uint32_t rn = RR->prng->next32(); Packet outp(sn->address(),RR->identity.address(),Packet::VERB_P5_MULTICAST_FRAME); diff --git a/node/Network.cpp b/node/Network.cpp index e513f43f9..60262cd59 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -518,13 +518,13 @@ public: RR(renv), _now(renv->node->now()), _network(nw), - _supernodeAddresses(renv->topology->supernodeAddresses()), + _rootserverAddresses(renv->topology->rootserverAddresses()), _allMulticastGroups(nw->_allMulticastGroups()) {} inline void operator()(Topology &t,const SharedPtr &p) { - if ( ( (p->hasActiveDirectPath(_now)) && (_network->_isAllowed(p->address())) ) || (std::find(_supernodeAddresses.begin(),_supernodeAddresses.end(),p->address()) != _supernodeAddresses.end()) ) { + if ( ( (p->hasActiveDirectPath(_now)) && (_network->_isAllowed(p->address())) ) || (std::find(_rootserverAddresses.begin(),_rootserverAddresses.end(),p->address()) != _rootserverAddresses.end()) ) { Packet outp(p->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); for(std::vector::iterator mg(_allMulticastGroups.begin());mg!=_allMulticastGroups.end();++mg) { @@ -551,7 +551,7 @@ private: const RuntimeEnvironment *RR; uint64_t _now; Network *_network; - std::vector
_supernodeAddresses; + std::vector
_rootserverAddresses; std::vector _allMulticastGroups; }; diff --git a/node/Node.cpp b/node/Node.cpp index 9f195a106..1f6d474ce 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -133,7 +133,9 @@ Node::Node( if (!rt.size()) rt.fromString(ZT_DEFAULTS.defaultRootTopology); } - RR->topology->setSupernodes(Dictionary(rt.get("supernodes",""))); + Dictionary rootservers(rt.get("rootservers","")); + rootservers.update(rt.get("supernodes","")); + RR->topology->setRootservers(rootservers); postEvent(ZT1_EVENT_UP); } @@ -189,7 +191,7 @@ public: RR(renv), _now(now), _relays(relays), - _supernodes(RR->topology->supernodeAddresses()) + _rootservers(RR->topology->rootserverAddresses()) { } @@ -205,7 +207,7 @@ public: } } - if ((isRelay)||(std::find(_supernodes.begin(),_supernodes.end(),p->address()) != _supernodes.end())) { + if ((isRelay)||(std::find(_rootservers.begin(),_rootservers.end(),p->address()) != _rootservers.end())) { p->doPingAndKeepalive(RR,_now); if (p->lastReceive() > lastReceiveFromUpstream) lastReceiveFromUpstream = p->lastReceive(); @@ -219,7 +221,7 @@ private: const RuntimeEnvironment *RR; uint64_t _now; const std::vector< std::pair > &_relays; - std::vector
_supernodes; + std::vector
_rootservers; }; ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline) @@ -260,7 +262,7 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *next } } - // Ping living or supernode/relay peers + // Ping living or rootserver/relay peers _PingPeersThatNeedPing pfunc(RR,now,networkRelays); RR->topology->eachPeer<_PingPeersThatNeedPing &>(pfunc); @@ -384,7 +386,7 @@ ZT1_PeerList *Node::peers() const p->versionRev = -1; } p->latency = pi->second->latency(); - p->role = RR->topology->isSupernode(pi->second->address()) ? ZT1_PEER_ROLE_SUPERNODE : ZT1_PEER_ROLE_LEAF; + p->role = RR->topology->isRootserver(pi->second->address()) ? ZT1_PEER_ROLE_ROOTSERVER : ZT1_PEER_ROLE_LEAF; std::vector paths(pi->second->paths()); Path *bestPath = pi->second->getBestPath(_now); diff --git a/node/Packet.hpp b/node/Packet.hpp index 1ec145d5c..21f8ca574 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -626,7 +626,7 @@ public: * [... additional tuples of network/address/adi ...] * * LIKEs are sent to peers with whom you have a direct peer to peer - * connection, and always including supernodes. + * connection, and always including rootservers. * * OK/ERROR are not generated. */ diff --git a/node/Peer.cpp b/node/Peer.cpp index d788d0063..3093ef41d 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -122,16 +122,16 @@ void Peer::received( /* Announce multicast groups of interest to direct peers if they are * considered authorized members of a given network. Also announce to - * supernodes and network controllers. */ + * rootservers and network controllers. */ if ((pathIsConfirmed)&&((now - _lastAnnouncedTo) >= ((ZT_MULTICAST_LIKE_EXPIRE / 2) - 1000))) { _lastAnnouncedTo = now; - const bool isSupernode = RR->topology->isSupernode(_id.address()); + const bool isRootserver = RR->topology->isRootserver(_id.address()); Packet outp(_id.address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); const std::vector< SharedPtr > networks(RR->node->allNetworks()); for(std::vector< SharedPtr >::const_iterator n(networks.begin());n!=networks.end();++n) { - if ( (isSupernode) || ((*n)->isAllowed(_id.address())) ) { + if ( (isRootserver) || ((*n)->isAllowed(_id.address())) ) { const std::vector mgs((*n)->allMulticastGroups()); for(std::vector::const_iterator mg(mgs.begin());mg!=mgs.end();++mg) { if ((outp.size() + 18) > ZT_UDP_DEFAULT_PAYLOAD_MTU) { diff --git a/node/SelfAwareness.cpp b/node/SelfAwareness.cpp index d7c0e5cc4..5fc8be2a6 100644 --- a/node/SelfAwareness.cpp +++ b/node/SelfAwareness.cpp @@ -118,7 +118,7 @@ void SelfAwareness::iam(const Address &reporter,const InetAddress &reporterPhysi // For all peers for whom we forgot an address, send a packet indirectly if // they are still considered alive so that we will re-establish direct links. - SharedPtr sn(RR->topology->getBestSupernode()); + SharedPtr sn(RR->topology->getBestRootserver()); if (sn) { Path *snp = sn->getBestPath(now); if (snp) { diff --git a/node/Switch.cpp b/node/Switch.cpp index 0aa0b664b..3ac0b9206 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -320,8 +320,8 @@ bool Switch::unite(const Address &p1,const Address &p2,bool force) * P2 in randomized order in terms of which gets sent first. This is done * since in a few cases NAT-t can be sensitive to slight timing differences * in terms of when the two peers initiate. Normally this is accounted for - * by the nearly-simultaneous RENDEZVOUS kickoff from the supernode, but - * given that supernodes are hosted on cloud providers this can in some + * by the nearly-simultaneous RENDEZVOUS kickoff from the rootserver, but + * given that rootservers are hosted on cloud providers this can in some * cases have a few ms of latency between packet departures. By randomizing * the order we make each attempted NAT-t favor one or the other going * first, meaning if it doesn't succeed the first time it might the second @@ -565,8 +565,8 @@ void Switch::_handleRemotePacketFragment(const InetAddress &fromAddr,const void // It wouldn't hurt anything, just redundant and unnecessary. SharedPtr relayTo = RR->topology->getPeer(destination); if ((!relayTo)||(!relayTo->send(RR,fragment.data(),fragment.size(),RR->node->now()))) { - // Don't know peer or no direct path -- so relay via supernode - relayTo = RR->topology->getBestSupernode(); + // Don't know peer or no direct path -- so relay via rootserver + relayTo = RR->topology->getBestRootserver(); if (relayTo) relayTo->send(RR,fragment.data(),fragment.size(),RR->node->now()); } @@ -641,8 +641,8 @@ void Switch::_handleRemotePacketHead(const InetAddress &fromAddr,const void *dat if ((relayTo)&&((relayTo->send(RR,packet->data(),packet->size(),RR->node->now())))) { unite(source,destination,false); } else { - // Don't know peer or no direct path -- so relay via supernode - relayTo = RR->topology->getBestSupernode(&source,1,true); + // Don't know peer or no direct path -- so relay via rootserver + relayTo = RR->topology->getBestRootserver(&source,1,true); if (relayTo) relayTo->send(RR,packet->data(),packet->size(),RR->node->now()); } @@ -712,13 +712,13 @@ void Switch::_handleBeacon(const InetAddress &fromAddr,const Buffer supernode(RR->topology->getBestSupernode(peersAlreadyConsulted,numPeersAlreadyConsulted,false)); - if (supernode) { - Packet outp(supernode->address(),RR->identity.address(),Packet::VERB_WHOIS); + SharedPtr rootserver(RR->topology->getBestRootserver(peersAlreadyConsulted,numPeersAlreadyConsulted,false)); + if (rootserver) { + Packet outp(rootserver->address(),RR->identity.address(),Packet::VERB_WHOIS); addr.appendTo(outp); - outp.armor(supernode->key(),true); - if (supernode->send(RR,outp.data(),outp.size(),RR->node->now())) - return supernode->address(); + outp.armor(rootserver->key(),true); + if (rootserver->send(RR,outp.data(),outp.size(),RR->node->now())) + return rootserver->address(); } return Address(); } @@ -752,7 +752,7 @@ bool Switch::_trySend(const Packet &packet,bool encrypt,uint64_t nwid) } if (!relay) - relay = RR->topology->getBestSupernode(); + relay = RR->topology->getBestRootserver(); if (!(relay)||(!(viaPath = relay->getBestPath(now)))) return false; diff --git a/node/Topology.cpp b/node/Topology.cpp index 5fcc2e612..cfa6749cd 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -36,7 +36,7 @@ namespace ZeroTier { Topology::Topology(const RuntimeEnvironment *renv) : RR(renv), - _amSupernode(false) + _amRootserver(false) { } @@ -44,16 +44,16 @@ Topology::~Topology() { } -void Topology::setSupernodes(const std::map< Identity,std::vector > &sn) +void Topology::setRootservers(const std::map< Identity,std::vector > &sn) { Mutex::Lock _l(_lock); - if (_supernodes == sn) + if (_rootservers == sn) return; // no change - _supernodes = sn; - _supernodeAddresses.clear(); - _supernodePeers.clear(); + _rootservers = sn; + _rootserverAddresses.clear(); + _rootserverPeers.clear(); const uint64_t now = RR->node->now(); for(std::map< Identity,std::vector >::const_iterator i(sn.begin());i!=sn.end();++i) { @@ -64,17 +64,17 @@ void Topology::setSupernodes(const std::map< Identity,std::vector > for(std::vector::const_iterator j(i->second.begin());j!=i->second.end();++j) p->addPath(Path(*j,true)); p->use(now); - _supernodePeers.push_back(p); + _rootserverPeers.push_back(p); } - _supernodeAddresses.push_back(i->first.address()); + _rootserverAddresses.push_back(i->first.address()); } - std::sort(_supernodeAddresses.begin(),_supernodeAddresses.end()); + std::sort(_rootserverAddresses.begin(),_rootserverAddresses.end()); - _amSupernode = (_supernodes.find(RR->identity) != _supernodes.end()); + _amRootserver = (_rootservers.find(RR->identity) != _rootservers.end()); } -void Topology::setSupernodes(const Dictionary &sn) +void Topology::setRootservers(const Dictionary &sn) { std::map< Identity,std::vector > m; for(Dictionary::const_iterator d(sn.begin());d!=sn.end();++d) { @@ -86,11 +86,11 @@ void Topology::setSupernodes(const Dictionary &sn) if (udp.length() > 0) a.push_back(InetAddress(udp)); } catch ( ... ) { - TRACE("supernode list contained invalid entry for: %s",d->first.c_str()); + TRACE("rootserver list contained invalid entry for: %s",d->first.c_str()); } } } - this->setSupernodes(m); + this->setRootservers(m); } SharedPtr Topology::addPeer(const SharedPtr &peer) @@ -141,28 +141,28 @@ SharedPtr Topology::getPeer(const Address &zta) return SharedPtr(); } -SharedPtr Topology::getBestSupernode(const Address *avoid,unsigned int avoidCount,bool strictAvoid) +SharedPtr Topology::getBestRootserver(const Address *avoid,unsigned int avoidCount,bool strictAvoid) { - SharedPtr bestSupernode; + SharedPtr bestRootserver; const uint64_t now = RR->node->now(); Mutex::Lock _l(_lock); - if (_amSupernode) { - /* If I am a supernode, the "best" supernode is the one whose address + if (_amRootserver) { + /* If I am a rootserver, the "best" rootserver 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. */ - if (_supernodeAddresses.size() > 1) { // gotta be one other than me for this to work - std::vector
::const_iterator sna(std::find(_supernodeAddresses.begin(),_supernodeAddresses.end(),RR->identity.address())); - if (sna != _supernodeAddresses.end()) { // sanity check -- _amSupernode should've been false in this case + if (_rootserverAddresses.size() > 1) { // gotta be one other than me for this to work + std::vector
::const_iterator sna(std::find(_rootserverAddresses.begin(),_rootserverAddresses.end(),RR->identity.address())); + if (sna != _rootserverAddresses.end()) { // sanity check -- _amRootserver should've been false in this case for(;;) { - if (++sna == _supernodeAddresses.end()) - sna = _supernodeAddresses.begin(); // wrap around at end + if (++sna == _rootserverAddresses.end()) + sna = _rootserverAddresses.begin(); // wrap around at end if (*sna != RR->identity.address()) { // pick one other than us -- starting from me+1 in sorted set order std::map< Address,SharedPtr >::const_iterator p(_activePeers.find(*sna)); if ((p != _activePeers.end())&&(p->second->hasActiveDirectPath(now))) { - bestSupernode = p->second; + bestRootserver = p->second; break; } } @@ -170,80 +170,80 @@ SharedPtr Topology::getBestSupernode(const Address *avoid,unsigned int avo } } } else { - /* If I am not a supernode, the best supernode is the active one with + /* If I am not a rootserver, the best rootserver is the active one with * the lowest latency. */ - unsigned int l,bestSupernodeLatency = 65536; + unsigned int l,bestRootserverLatency = 65536; uint64_t lds,ldr; - // First look for a best supernode by comparing latencies, but exclude - // supernodes that have not responded to direct messages in order to + // First look for a best rootserver by comparing latencies, but exclude + // rootservers that have not responded to direct messages in order to // try to exclude any that are dead or unreachable. - for(std::vector< SharedPtr >::const_iterator sn(_supernodePeers.begin());sn!=_supernodePeers.end();) { + for(std::vector< SharedPtr >::const_iterator sn(_rootserverPeers.begin());sn!=_rootserverPeers.end();) { // Skip explicitly avoided relays for(unsigned int i=0;iaddress()) - goto keep_searching_for_supernodes; + goto keep_searching_for_rootservers; } // Skip possibly comatose or unreachable relays lds = (*sn)->lastDirectSend(); ldr = (*sn)->lastDirectReceive(); if ((lds)&&(lds > ldr)&&((lds - ldr) > ZT_PEER_RELAY_CONVERSATION_LATENCY_THRESHOLD)) - goto keep_searching_for_supernodes; + goto keep_searching_for_rootservers; if ((*sn)->hasActiveDirectPath(now)) { l = (*sn)->latency(); - if (bestSupernode) { - if ((l)&&(l < bestSupernodeLatency)) { - bestSupernodeLatency = l; - bestSupernode = *sn; + if (bestRootserver) { + if ((l)&&(l < bestRootserverLatency)) { + bestRootserverLatency = l; + bestRootserver = *sn; } } else { if (l) - bestSupernodeLatency = l; - bestSupernode = *sn; + bestRootserverLatency = l; + bestRootserver = *sn; } } -keep_searching_for_supernodes: +keep_searching_for_rootservers: ++sn; } - if (bestSupernode) { - bestSupernode->use(now); - return bestSupernode; + if (bestRootserver) { + bestRootserver->use(now); + return bestRootserver; } else if (strictAvoid) return SharedPtr(); // If we have nothing from above, just pick one without avoidance criteria. - for(std::vector< SharedPtr >::const_iterator sn=_supernodePeers.begin();sn!=_supernodePeers.end();++sn) { + for(std::vector< SharedPtr >::const_iterator sn=_rootserverPeers.begin();sn!=_rootserverPeers.end();++sn) { if ((*sn)->hasActiveDirectPath(now)) { unsigned int l = (*sn)->latency(); - if (bestSupernode) { - if ((l)&&(l < bestSupernodeLatency)) { - bestSupernodeLatency = l; - bestSupernode = *sn; + if (bestRootserver) { + if ((l)&&(l < bestRootserverLatency)) { + bestRootserverLatency = l; + bestRootserver = *sn; } } else { if (l) - bestSupernodeLatency = l; - bestSupernode = *sn; + bestRootserverLatency = l; + bestRootserver = *sn; } } } } - if (bestSupernode) - bestSupernode->use(now); - return bestSupernode; + if (bestRootserver) + bestRootserver->use(now); + return bestRootserver; } void Topology::clean(uint64_t now) { Mutex::Lock _l(_lock); for(std::map< Address,SharedPtr >::iterator p(_activePeers.begin());p!=_activePeers.end();) { - if (((now - p->second->lastUsed()) >= ZT_PEER_IN_MEMORY_EXPIRATION)&&(std::find(_supernodeAddresses.begin(),_supernodeAddresses.end(),p->first) == _supernodeAddresses.end())) { + if (((now - p->second->lastUsed()) >= ZT_PEER_IN_MEMORY_EXPIRATION)&&(std::find(_rootserverAddresses.begin(),_rootserverAddresses.end(),p->first) == _rootserverAddresses.end())) { _activePeers.erase(p++); } else ++p; } diff --git a/node/Topology.hpp b/node/Topology.hpp index 56a9709fc..8aeae784e 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -59,21 +59,21 @@ public: ~Topology(); /** - * Set up supernodes for this network + * Set up rootservers for this network * - * @param sn Supernodes for this network + * @param sn Rootservers for this network */ - void setSupernodes(const std::map< Identity,std::vector > &sn); + void setRootservers(const std::map< Identity,std::vector > &sn); /** - * Set up supernodes for this network + * Set up rootservers for this network * * This performs no signature verification of any kind. The caller must * check the signature of the root topology dictionary first. * - * @param sn Supernodes dictionary from root-topology + * @param sn Rootservers dictionary from root-topology */ - void setSupernodes(const Dictionary &sn); + void setRootservers(const Dictionary &sn); /** * Add a peer to database @@ -95,65 +95,65 @@ public: SharedPtr getPeer(const Address &zta); /** - * @return Vector of peers that are supernodes + * @return Vector of peers that are rootservers */ - inline std::vector< SharedPtr > supernodePeers() const + inline std::vector< SharedPtr > rootserverPeers() const { Mutex::Lock _l(_lock); - return _supernodePeers; + return _rootserverPeers; } /** - * @return Number of supernodes + * @return Number of rootservers */ - inline unsigned int numSupernodes() const + inline unsigned int numRootservers() const { Mutex::Lock _l(_lock); - return (unsigned int)_supernodePeers.size(); + return (unsigned int)_rootserverPeers.size(); } /** - * Get the current favorite supernode + * Get the current favorite rootserver * - * @return Supernode with lowest latency or NULL if none + * @return Rootserver with lowest latency or NULL if none */ - inline SharedPtr getBestSupernode() + inline SharedPtr getBestRootserver() { - return getBestSupernode((const Address *)0,0,false); + return getBestRootserver((const Address *)0,0,false); } /** - * Get the best supernode, avoiding supernodes listed in an array + * Get the best rootserver, avoiding rootservers listed in an array * - * This will get the best supernode (lowest latency, etc.) but will - * try to avoid the listed supernodes, only using them if no others + * This will get the best rootserver (lowest latency, etc.) but will + * try to avoid the listed rootservers, only using them if no others * are available. * * @param avoid Nodes to avoid * @param avoidCount Number of nodes to avoid - * @param strictAvoid If false, consider avoided supernodes anyway if no non-avoid supernodes are available - * @return Supernode or NULL if none + * @param strictAvoid If false, consider avoided rootservers anyway if no non-avoid rootservers are available + * @return Rootserver or NULL if none */ - SharedPtr getBestSupernode(const Address *avoid,unsigned int avoidCount,bool strictAvoid); + SharedPtr getBestRootserver(const Address *avoid,unsigned int avoidCount,bool strictAvoid); /** * @param zta ZeroTier address - * @return True if this is a designated supernode + * @return True if this is a designated rootserver */ - inline bool isSupernode(const Address &zta) const + inline bool isRootserver(const Address &zta) const throw() { Mutex::Lock _l(_lock); - return (std::find(_supernodeAddresses.begin(),_supernodeAddresses.end(),zta) != _supernodeAddresses.end()); + return (std::find(_rootserverAddresses.begin(),_rootserverAddresses.end(),zta) != _rootserverAddresses.end()); } /** - * @return Vector of supernode addresses + * @return Vector of rootserver addresses */ - inline std::vector
supernodeAddresses() const + inline std::vector
rootserverAddresses() const { Mutex::Lock _l(_lock); - return _supernodeAddresses; + return _rootserverAddresses; } /** @@ -206,13 +206,13 @@ private: const RuntimeEnvironment *RR; std::map< Address,SharedPtr > _activePeers; - std::map< Identity,std::vector > _supernodes; - std::vector< Address > _supernodeAddresses; - std::vector< SharedPtr > _supernodePeers; + std::map< Identity,std::vector > _rootservers; + std::vector< Address > _rootserverAddresses; + std::vector< SharedPtr > _rootserverPeers; Mutex _lock; - bool _amSupernode; + bool _amRootserver; }; } // namespace ZeroTier diff --git a/root-topology/README.md b/root-topology/README.md index 2614d3d9d..c9c3a9083 100644 --- a/root-topology/README.md +++ b/root-topology/README.md @@ -2,9 +2,9 @@ This folder contains the source files to compile the signed network root topolog Keys in the root topology dictionary are: - * **supernodes**: contains another Dictionary mapping supernode address to supernode definition - * **##########**: supernode address, contains supernode definition - * **id**: supernode identity (public) in string-serialized format + * **rootservers**: contains another Dictionary mapping rootserver address to rootserver definition + * **##########**: rootserver address, contains rootserver definition + * **id**: rootserver identity (public) in string-serialized format * **udp**: comma-delimited list of ip/port UDP addresses of node * **tcp**: *DEPRECATED* comma-delimited list of ip/port TCP addresses of node * **desc**: human-readable description (optional) diff --git a/root-topology/ZT_DEFAULT_ROOT_TOPOLOGY.dict b/root-topology/ZT_DEFAULT_ROOT_TOPOLOGY.dict index 8aa828f0a..94cac7d0d 100644 --- a/root-topology/ZT_DEFAULT_ROOT_TOPOLOGY.dict +++ b/root-topology/ZT_DEFAULT_ROOT_TOPOLOGY.dict @@ -1,4 +1,4 @@ -supernodes=7e19876aba\=id\\\=7e19876aba:0:2a6e2b2318930f60eb097f70d0f4b028b2cd6d3d0c63c014b9039ff35390e41181f216fb2e6fa8d95c1ee9667156411905c3dccfea78d8c6dfafba688170b3fa\\nudp\\\=198.199.97.220/9993\\ntcp\\\=198.199.97.220/443\\ndesc\\\=San Francisco, California, USA\\ndns\\\=nyarlathotep.zerotier.com\\n\n8841408a2e\=id\\\=8841408a2e:0:bb1d31f2c323e264e9e64172c1a74f77899555ed10751cd56e86405cde118d02dffe555d462ccf6a85b5631c12350c8d5dc409ba10b9025d0f445cf449d92b1c\\nudp\\\=107.191.46.210/9993\\ntcp\\\=107.191.46.210/443\\ndesc\\\=Paris, France\\ndns\\\=shoggoth.zerotier.com\\n\n8acf059fe3\=id\\\=8acf059fe3:0:482f6ee5dfe902319b419de5bdc765209c0ecda38c4d6e4fcf0d33658398b4527dcd22f93112fb9befd02fd78bf7261b333fc105d192a623ca9e50fc60b374a5\\nudp\\\=162.243.77.111/9993\\ntcp\\\=162.243.77.111/443\\ndesc\\\=New York, New York, USA\\ndns\\\=cthulhu.zerotier.com\\n\n9d219039f3\=id\\\=9d219039f3:0:01f0922a98e3b34ebcbff333269dc265d7a020aab69d72be4d4acc9c8c9294785771256cd1d942a90d1bd1d2dca3ea84ef7d85afe6611fb43ff0b74126d90a6e\\nudp\\\=128.199.197.217/9993\\ntcp\\\=128.199.197.217/443\\ndesc\\\=Singapore\\ndns\\\=mi-go.zerotier.com\\n\n +rootservers=7e19876aba\=id\\\=7e19876aba:0:2a6e2b2318930f60eb097f70d0f4b028b2cd6d3d0c63c014b9039ff35390e41181f216fb2e6fa8d95c1ee9667156411905c3dccfea78d8c6dfafba688170b3fa\\nudp\\\=198.199.97.220/9993\\ntcp\\\=198.199.97.220/443\\ndesc\\\=San Francisco, California, USA\\ndns\\\=nyarlathotep.zerotier.com\\n\n8841408a2e\=id\\\=8841408a2e:0:bb1d31f2c323e264e9e64172c1a74f77899555ed10751cd56e86405cde118d02dffe555d462ccf6a85b5631c12350c8d5dc409ba10b9025d0f445cf449d92b1c\\nudp\\\=107.191.46.210/9993\\ntcp\\\=107.191.46.210/443\\ndesc\\\=Paris, France\\ndns\\\=shoggoth.zerotier.com\\n\n8acf059fe3\=id\\\=8acf059fe3:0:482f6ee5dfe902319b419de5bdc765209c0ecda38c4d6e4fcf0d33658398b4527dcd22f93112fb9befd02fd78bf7261b333fc105d192a623ca9e50fc60b374a5\\nudp\\\=162.243.77.111/9993\\ntcp\\\=162.243.77.111/443\\ndesc\\\=New York, New York, USA\\ndns\\\=cthulhu.zerotier.com\\n\n9d219039f3\=id\\\=9d219039f3:0:01f0922a98e3b34ebcbff333269dc265d7a020aab69d72be4d4acc9c8c9294785771256cd1d942a90d1bd1d2dca3ea84ef7d85afe6611fb43ff0b74126d90a6e\\nudp\\\=128.199.197.217/9993\\ntcp\\\=128.199.197.217/443\\ndesc\\\=Singapore\\ndns\\\=mi-go.zerotier.com\\n\n ~!ed25519=b7493f5a4b79a1dcc423fd25d2d8aa8d6293c490a12ceb6395417dd5868c17bfbcee685de58019d21f92576a78a45235d342efa2a00a544ded34766dd32d6f0e11809197f9baeedf4c6a0e8d2d657d280a579f2f2478b2f7c7a08089a5016b55 ~!sigid=77792b1c02:0:b5c361e8e9c2154e82c3e902fdfc337468b092a7c4d8dc685c37eb10ee4f3c17cc0bb1d024167e8cb0824d12263428373582da3d0a9a14b36e4546c317e811e6 ~!sigts=14ae42d0314 diff --git a/root-topology/mktopology.cpp b/root-topology/mktopology.cpp index 00ada7b76..f0ad5b556 100644 --- a/root-topology/mktopology.cpp +++ b/root-topology/mktopology.cpp @@ -30,21 +30,21 @@ int main(int argc,char **argv) if (OSUtils::readFile("template.dict",buf)) topology.fromString(buf); - // Read all entries in supernodes/ that correspond to supernode entry dictionaries - // and add them to topology under supernodes/ subkey. - Dictionary supernodes; - std::vector supernodeDictionaries(OSUtils::listDirectory("supernodes")); - for(std::vector::const_iterator sn(supernodeDictionaries.begin());sn!=supernodeDictionaries.end();++sn) { + // Read all entries in rootservers/ that correspond to rootserver entry dictionaries + // and add them to topology under rootservers/ subkey. + Dictionary rootservers; + std::vector rootserverDictionaries(OSUtils::listDirectory("rootservers")); + for(std::vector::const_iterator sn(rootserverDictionaries.begin());sn!=rootserverDictionaries.end();++sn) { if (sn->length() == 10) { buf.clear(); - if (!OSUtils::readFile((std::string("supernodes/")+(*sn)).c_str(),buf)) { - std::cerr << "Cannot read supernodes/" << *sn << std::endl; + if (!OSUtils::readFile((std::string("rootservers/")+(*sn)).c_str(),buf)) { + std::cerr << "Cannot read rootservers/" << *sn << std::endl; return 1; } - supernodes[*sn] = buf; + rootservers[*sn] = buf; } } - topology["supernodes"] = supernodes.toString(); + topology["rootservers"] = rootservers.toString(); if ((topologyAuthority)&&(topologyAuthority.hasPrivate())) { // Sign topology with root-topology-authority.secret diff --git a/root-topology/supernodes/7e19876aba b/root-topology/rootservers/7e19876aba similarity index 100% rename from root-topology/supernodes/7e19876aba rename to root-topology/rootservers/7e19876aba diff --git a/root-topology/supernodes/8841408a2e b/root-topology/rootservers/8841408a2e similarity index 100% rename from root-topology/supernodes/8841408a2e rename to root-topology/rootservers/8841408a2e diff --git a/root-topology/supernodes/8acf059fe3 b/root-topology/rootservers/8acf059fe3 similarity index 100% rename from root-topology/supernodes/8acf059fe3 rename to root-topology/rootservers/8acf059fe3 diff --git a/root-topology/supernodes/9d219039f3 b/root-topology/rootservers/9d219039f3 similarity index 100% rename from root-topology/supernodes/9d219039f3 rename to root-topology/rootservers/9d219039f3 diff --git a/root-topology/test/README.md b/root-topology/test/README.md index 332f8297f..ae7022437 100644 --- a/root-topology/test/README.md +++ b/root-topology/test/README.md @@ -1,6 +1,6 @@ Test Root Topology Script ====== -This builds a test-root-topology from any number of running test-supernode-# Docker containers. This can then be used with the (undocumented) -T (override root topology) option to run test networks under Docker. +This builds a test-root-topology from any number of running test-rootserver-# Docker containers. This can then be used with the (undocumented) -T (override root topology) option to run test networks under Docker. Once you have a local Docker test network running you can use iptables rules to simulate a variety of network pathologies, or you can just use it to test any new changes to the protocol or node behavior at some limited scale. diff --git a/root-topology/test/create-test-root-topology.sh b/root-topology/test/create-test-root-topology.sh index 86c0577cf..cb6287295 100755 --- a/root-topology/test/create-test-root-topology.sh +++ b/root-topology/test/create-test-root-topology.sh @@ -5,18 +5,18 @@ if [ ! -e ../mktopology ]; then exit 1 fi -echo 'Populating supernodes/* with all Docker test-supernode-* container IPs and identities...' +echo 'Populating rootservers/* with all Docker test-rootserver-* container IPs and identities...' -rm -rf supernodes -mkdir supernodes +rm -rf rootservers +mkdir rootservers -for cid in `docker ps -f 'name=test-supernode-*' -q`; do +for cid in `docker ps -f 'name=test-rootserver-*' -q`; do id=`docker exec $cid cat /var/lib/zerotier-one/identity.secret | cut -d : -f 1-3` ztaddr=`echo $id | cut -d : -f 1` ip=`docker exec $cid ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'` echo $cid $ztaddr $id $ip - echo "id=$id" >supernodes/$ztaddr - echo "udp=$ip/9993" >>supernodes/$ztaddr + echo "id=$id" >rootservers/$ztaddr + echo "udp=$ip/9993" >>rootservers/$ztaddr done echo 'Creating test-root-topology...' diff --git a/service/ControlPlane.cpp b/service/ControlPlane.cpp index 4158ed43d..e42c9ef85 100644 --- a/service/ControlPlane.cpp +++ b/service/ControlPlane.cpp @@ -213,7 +213,7 @@ static void _jsonAppend(unsigned int depth,std::string &buf,const ZT1_Peer *peer switch(peer->role) { case ZT1_PEER_ROLE_LEAF: prole = "LEAF"; break; case ZT1_PEER_ROLE_HUB: prole = "HUB"; break; - case ZT1_PEER_ROLE_SUPERNODE: prole = "SUPERNODE"; break; + case ZT1_PEER_ROLE_ROOTSERVER: prole = "ROOT"; break; } Utils::snprintf(json,sizeof(json), diff --git a/service/README.md b/service/README.md index 2a283cbd1..df62ff274 100644 --- a/service/README.md +++ b/service/README.md @@ -106,7 +106,7 @@ Getting /peer returns an array of peer objects for all current peers. See below versionRevintegerRevision of remote if knownno versionstringVersion in major.minor.rev formatno latencyintegerLatency in milliseconds if knownno -rolestringLEAF, HUB, or SUPERNODEno +rolestringLEAF, HUB, or ROOTSERVERno paths[object]Array of path objects (see below)no @@ -184,7 +184,7 @@ Relays, IP assignment pools, and rules are edited via direct POSTs to the networ **Relay object format:** -Relay objects define network-specific preferred relay nodes. Traffic to peers on this network will preferentially use these relays if they are available, and otherwise will fall back to the global supernode infrastructure. +Relay objects define network-specific preferred relay nodes. Traffic to peers on this network will preferentially use these relays if they are available, and otherwise will fall back to the global rootserver infrastructure. diff --git a/tcp-proxy/tcp-proxy.cpp b/tcp-proxy/tcp-proxy.cpp index f7ba2c2f6..6acf7b423 100644 --- a/tcp-proxy/tcp-proxy.cpp +++ b/tcp-proxy/tcp-proxy.cpp @@ -85,7 +85,7 @@ using namespace ZeroTier; * 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 supernodes and onto dedicated + * 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 From e5e11c1b24191bb0258e7aa29ecc02f1e2f78eca Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 4 Jun 2015 11:58:49 -0700 Subject: [PATCH 02/37] Update AUTHORS, change to MarkDown. --- AUTHORS.md | 38 ++++++++++++++++++++++++++++++++++++++ AUTHORS.txt | 27 --------------------------- 2 files changed, 38 insertions(+), 27 deletions(-) create mode 100644 AUTHORS.md delete mode 100644 AUTHORS.txt diff --git a/AUTHORS.md b/AUTHORS.md new file mode 100644 index 000000000..149362c31 --- /dev/null +++ b/AUTHORS.md @@ -0,0 +1,38 @@ +## Authors + + * ZeroTier protocol design and core network virtualization engine, ZeroTier One service, React web UI, packaging for most platforms, kitchen sink...
+ Adam Ierymenko / adam.ierymenko@zerotier.com + + * Java JNI Interface to enable Android application development, and Android app itself (code for that is elsewhere)
+ Grant Limberg / glimberg@gmail.com + +## Contributors + + * Debugging and testing, OpenWRT support fixes.
+ Moritz Warning / moritzwarning@web.de + + * Several others made smaller contributions, which GitHub tracks here:
+ https://github.com/zerotier/ZeroTierOne/graphs/contributors + +## Third Party Code + + * LZ4 compression algorithm by Yann Collet (BSD license)
+ http://code.google.com/p/lz4/ + + * http-parser by many authors (MIT license)
+ https://github.com/joyent/http-parser + + * json-parser by James McLaughlin (BSD license)
+ https://github.com/udp/json-parser + + * TunTapOSX by Mattias Nissler (BSD license)
+ http://tuntaposx.sourceforge.net + + * tap-windows and tap-windows6 by the OpenVPN project (GPL)
+ https://github.com/OpenVPN/tap-windows
+ https://github.com/OpenVPN/tap-windows6 + + * Salsa20 stream cipher, Curve25519 elliptic curve cipher, Ed25519 + digital signature algorithm, and Poly1305 MAC algorithm, all by + Daniel J. Bernstein (public domain)
+ http://cr.yp.to/ diff --git a/AUTHORS.txt b/AUTHORS.txt deleted file mode 100644 index 4ac870f1e..000000000 --- a/AUTHORS.txt +++ /dev/null @@ -1,27 +0,0 @@ -ZeroTier One is designed and written by Adam Ierymenko, with a few bug -fixes and other contributions from other users. Information about all -contributors can be found on the GitHub home page at: - -https://github.com/zerotier/ZeroTierOne - -ZeroTier One includes the following third party code: - - * LZ4 compression algorithm by Yann Collet (BSD license) - http://code.google.com/p/lz4/ - - * http-parser by many authors (MIT license) - https://github.com/joyent/http-parser - - * json-parser by James McLaughlin (BSD license) - https://github.com/udp/json-parser - - * TunTapOSX by Mattias Nissler (forked for ZT1) (BSD license) - http://tuntaposx.sourceforge.net - - * tap-windows by the OpenVPN project (forked for ZT1) (GPL) - https://github.com/OpenVPN/tap-windows - - * Salsa20 stream cipher, Curve25519 elliptic curve cipher, Ed25519 - digital signature algorithm, and Poly1305 MAC algorithm, all by - Daniel J. Bernstein (public domain) - http://cr.yp.to/ From ab720a6f1e375b9a79d32e8dec013c64deabff20 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 5 Jun 2015 13:48:33 -0700 Subject: [PATCH 03/37] Fix for poll() in Phy<> with no sockets open. Only affects tcp-proxy. --- osdep/Phy.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osdep/Phy.hpp b/osdep/Phy.hpp index 23fd2ee24..02ea56f90 100644 --- a/osdep/Phy.hpp +++ b/osdep/Phy.hpp @@ -620,7 +620,7 @@ public: #endif } - bool atEnd = false; + bool atEnd = _socks.empty(); for(typename std::list::iterator s(_socks.begin()),nexts;(!atEnd);s=nexts) { nexts = s; ++nexts; // we can delete the linked list item, so traverse now atEnd = (nexts == _socks.end()); // if we delete the last element, s!=_socks.end() will no longer terminate our loop From 17ca5be4c18f630313ed87e572b53dd07511e97c Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 9 Jun 2015 16:27:11 +0200 Subject: [PATCH 04/37] Rework Phy<> to clean up _socks entries only in poll() to fix instability in proxy. --- osdep/Phy.hpp | 43 ++++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/osdep/Phy.hpp b/osdep/Phy.hpp index 02ea56f90..8287a7800 100644 --- a/osdep/Phy.hpp +++ b/osdep/Phy.hpp @@ -123,12 +123,13 @@ private: enum PhySocketType { - ZT_PHY_SOCKET_TCP_OUT_PENDING = 0x00, - ZT_PHY_SOCKET_TCP_OUT_CONNECTED = 0x01, - ZT_PHY_SOCKET_TCP_IN = 0x02, - ZT_PHY_SOCKET_TCP_LISTEN = 0x03, - ZT_PHY_SOCKET_RAW = 0x04, - ZT_PHY_SOCKET_UDP = 0x05 + ZT_PHY_SOCKET_CLOSED = 0x00, // socket is closed, will be removed on next poll() + ZT_PHY_SOCKET_TCP_OUT_PENDING = 0x01, + ZT_PHY_SOCKET_TCP_OUT_CONNECTED = 0x02, + ZT_PHY_SOCKET_TCP_IN = 0x03, + ZT_PHY_SOCKET_TCP_LISTEN = 0x04, + ZT_PHY_SOCKET_RAW = 0x05, + ZT_PHY_SOCKET_UDP = 0x06 }; struct PhySocketImpl @@ -205,8 +206,10 @@ public: ~Phy() { - while (!_socks.empty()) - this->close((PhySocket *)&(_socks.front()),true); + for(typename std::list::const_iterator s(_socks.begin());s!=_socks.end();++s) { + if (s->type != ZT_PHY_SOCKET_CLOSED) + this->close((PhySocket *)&(*s),true); + } ZT_PHY_CLOSE_SOCKET(_whackReceiveSocket); ZT_PHY_CLOSE_SOCKET(_whackSendSocket); } @@ -620,11 +623,7 @@ public: #endif } - bool atEnd = _socks.empty(); - for(typename std::list::iterator s(_socks.begin()),nexts;(!atEnd);s=nexts) { - nexts = s; ++nexts; // we can delete the linked list item, so traverse now - atEnd = (nexts == _socks.end()); // if we delete the last element, s!=_socks.end() will no longer terminate our loop - + for(typename std::list::iterator s(_socks.begin());s!=_socks.end();) { switch (s->type) { case ZT_PHY_SOCKET_TCP_OUT_PENDING: @@ -724,6 +723,10 @@ public: break; } + + if (s->type == ZT_PHY_SOCKET_CLOSED) + _socks.erase(s++); + else ++s; } } @@ -765,21 +768,15 @@ public: break; } - long oldSock = (long)sws.sock; + // Causes entry to be deleted from list in poll(), ignored elsewhere + sws.type = ZT_PHY_SOCKET_CLOSED; - for(typename std::list::iterator s(_socks.begin());s!=_socks.end();++s) { - if (reinterpret_cast(&(*s)) == sock) { - _socks.erase(s); - break; - } - } - - if (oldSock >= _nfds) { + if (sws.sock >= _nfds) { long nfds = (long)_whackSendSocket; if ((long)_whackReceiveSocket > nfds) nfds = (long)_whackReceiveSocket; for(typename std::list::iterator s(_socks.begin());s!=_socks.end();++s) { - if ((long)s->sock > nfds) + if ((s->type != ZT_PHY_SOCKET_CLOSED)&&((long)s->sock > nfds)) nfds = (long)s->sock; } _nfds = nfds; From 00aa115898e88f1a979fa3074bbcb25ac8b3ab4c Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 9 Jun 2015 16:30:44 +0200 Subject: [PATCH 05/37] Allow double-close just in case in Phy<> --- osdep/Phy.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osdep/Phy.hpp b/osdep/Phy.hpp index 8287a7800..ec01625ba 100644 --- a/osdep/Phy.hpp +++ b/osdep/Phy.hpp @@ -739,6 +739,8 @@ public: if (!sock) return; PhySocketImpl &sws = *(reinterpret_cast(sock)); + if (sws.type == ZT_PHY_SOCKET_CLOSED) + return; FD_CLR(sws.sock,&_readfds); FD_CLR(sws.sock,&_writefds); From de697a1c45e8afbdd32687b9b5d203732ce5e62a Mon Sep 17 00:00:00 2001 From: Kees Bos Date: Thu, 11 Jun 2015 11:35:25 +0200 Subject: [PATCH 06/37] Change schema to enforce foreing keys The foreign keys have 'ON DELETE CASCADE' to simplify the removal of networks etc. (controller code) Some unique constraints are replaced with a multi column primary key. To update an existing database: * install updated binaries * stop service * sqlite3 controller.db .dump | \ egrep '((^PRAGMA)|(^BEGIN)|(^INSERT)|(^COMMIT))' | \ grep -v 'schemaVersion' > data.sql * mv controller.db controller.db.backup * start service * stop service * sqlite3 controller.db < data.sql * start service --- controller/schema.sql | 118 ++++++++++++++++++++-------------------- controller/schema.sql.c | 116 +++++++++++++++++++-------------------- 2 files changed, 115 insertions(+), 119 deletions(-) diff --git a/controller/schema.sql b/controller/schema.sql index b5646ee90..a3a7bb7a5 100644 --- a/controller/schema.sql +++ b/controller/schema.sql @@ -3,53 +3,6 @@ CREATE TABLE Config ( v varchar(1024) NOT NULL ); -CREATE TABLE IpAssignment ( - networkId char(16) NOT NULL, - nodeId char(10) NOT NULL, - ip blob(16) NOT NULL, - ipNetmaskBits integer NOT NULL DEFAULT(0), - ipVersion integer NOT NULL DEFAULT(4) -); - -CREATE INDEX IpAssignment_networkId_ip ON IpAssignment (networkId, ip); - -CREATE INDEX IpAssignment_networkId_nodeId ON IpAssignment (networkId, nodeId); - -CREATE INDEX IpAssignment_networkId ON IpAssignment (networkId); - -CREATE TABLE IpAssignmentPool ( - networkId char(16) NOT NULL, - ipNetwork blob(16) NOT NULL, - ipNetmaskBits integer NOT NULL, - ipVersion integer NOT NULL DEFAULT(4) -); - -CREATE INDEX IpAssignmentPool_networkId ON IpAssignmentPool (networkId); - -CREATE TABLE Member ( - networkId char(16) NOT NULL, - nodeId char(10) NOT NULL, - authorized integer NOT NULL DEFAULT(0), - activeBridge integer NOT NULL DEFAULT(0) -); - -CREATE INDEX Member_networkId ON Member (networkId); - -CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge); - -CREATE UNIQUE INDEX Member_networkId_nodeId ON Member (networkId, nodeId); - -CREATE TABLE MulticastRate ( - networkId char(16) NOT NULL, - mgMac char(12) NOT NULL, - mgAdi integer NOT NULL DEFAULT(0), - preload integer NOT NULL, - maxBalance integer NOT NULL, - accrual integer NOT NULL -); - -CREATE INDEX MulticastRate_networkId ON MulticastRate (networkId); - CREATE TABLE Network ( id char(16) PRIMARY KEY NOT NULL, name varchar(128) NOT NULL, @@ -63,16 +16,6 @@ CREATE TABLE Network ( revision integer NOT NULL DEFAULT(1) ); -CREATE TABLE Relay ( - networkId char(16) NOT NULL, - nodeId char(10) NOT NULL, - phyAddress varchar(64) NOT NULL -); - -CREATE INDEX Relay_networkId ON Relay (networkId); - -CREATE UNIQUE INDEX Relay_networkId_nodeId ON Relay (networkId, nodeId); - CREATE TABLE Node ( id char(10) PRIMARY KEY NOT NULL, identity varchar(4096) NOT NULL, @@ -81,10 +24,65 @@ CREATE TABLE Node ( firstSeen integer NOT NULL DEFAULT(0) ); +CREATE TABLE IpAssignment ( + networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, + nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE, + ip blob(16) NOT NULL, + ipNetmaskBits integer NOT NULL DEFAULT(0), + ipVersion integer NOT NULL DEFAULT(4) +); + +CREATE INDEX IpAssignment_networkId_ip ON IpAssignment (networkId, ip); + +CREATE INDEX IpAssignment_networkId_nodeId ON IpAssignment (networkId, nodeId); + +CREATE INDEX IpAssignment_networkId ON IpAssignment (networkId); + +CREATE TABLE IpAssignmentPool ( + networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, + ipNetwork blob(16) NOT NULL, + ipNetmaskBits integer NOT NULL, + ipVersion integer NOT NULL DEFAULT(4) +); + +CREATE INDEX IpAssignmentPool_networkId ON IpAssignmentPool (networkId); + +CREATE TABLE Member ( + networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, + nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE, + authorized integer NOT NULL DEFAULT(0), + activeBridge integer NOT NULL DEFAULT(0), + PRIMARY KEY (networkId, nodeId) +); + +CREATE INDEX Member_networkId ON Member (networkId); + +CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge); + +CREATE TABLE MulticastRate ( + networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, + mgMac char(12) NOT NULL, + mgAdi integer NOT NULL DEFAULT(0), + preload integer NOT NULL, + maxBalance integer NOT NULL, + accrual integer NOT NULL +); + +CREATE INDEX MulticastRate_networkId ON MulticastRate (networkId); + +CREATE TABLE Relay ( + networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, + nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE, + phyAddress varchar(64) NOT NULL, + PRIMARY KEY (networkId, nodeId) +); + +CREATE INDEX Relay_networkId ON Relay (networkId); + CREATE TABLE Rule ( - networkId char(16) NOT NULL, + networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, ruleId integer NOT NULL, - nodeId char(10), + nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE, vlanId integer, vlanPcp integer, etherType integer, @@ -101,4 +99,4 @@ CREATE TABLE Rule ( "action" varchar(4096) NOT NULL DEFAULT('accept') ); -CREATE INDEX Rule_networkId ON Rule (networkId); \ No newline at end of file +CREATE INDEX Rule_networkId ON Rule (networkId); diff --git a/controller/schema.sql.c b/controller/schema.sql.c index 1384b9008..0078eac3a 100644 --- a/controller/schema.sql.c +++ b/controller/schema.sql.c @@ -4,53 +4,6 @@ " v varchar(1024) NOT NULL\n"\ ");\n"\ "\n"\ -"CREATE TABLE IpAssignment (\n"\ -" networkId char(16) NOT NULL,\n"\ -" nodeId char(10) NOT NULL,\n"\ -" ip blob(16) NOT NULL,\n"\ -" ipNetmaskBits integer NOT NULL DEFAULT(0),\n"\ -" ipVersion integer NOT NULL DEFAULT(4)\n"\ -");\n"\ -"\n"\ -"CREATE INDEX IpAssignment_networkId_ip ON IpAssignment (networkId, ip);\n"\ -"\n"\ -"CREATE INDEX IpAssignment_networkId_nodeId ON IpAssignment (networkId, nodeId);\n"\ -"\n"\ -"CREATE INDEX IpAssignment_networkId ON IpAssignment (networkId);\n"\ -"\n"\ -"CREATE TABLE IpAssignmentPool (\n"\ -" networkId char(16) NOT NULL,\n"\ -" ipNetwork blob(16) NOT NULL,\n"\ -" ipNetmaskBits integer NOT NULL,\n"\ -" ipVersion integer NOT NULL DEFAULT(4)\n"\ -");\n"\ -"\n"\ -"CREATE INDEX IpAssignmentPool_networkId ON IpAssignmentPool (networkId);\n"\ -"\n"\ -"CREATE TABLE Member (\n"\ -" networkId char(16) NOT NULL,\n"\ -" nodeId char(10) NOT NULL,\n"\ -" authorized integer NOT NULL DEFAULT(0),\n"\ -" activeBridge integer NOT NULL DEFAULT(0)\n"\ -");\n"\ -"\n"\ -"CREATE INDEX Member_networkId ON Member (networkId);\n"\ -"\n"\ -"CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);\n"\ -"\n"\ -"CREATE UNIQUE INDEX Member_networkId_nodeId ON Member (networkId, nodeId);\n"\ -"\n"\ -"CREATE TABLE MulticastRate (\n"\ -" networkId char(16) NOT NULL,\n"\ -" mgMac char(12) NOT NULL,\n"\ -" mgAdi integer NOT NULL DEFAULT(0),\n"\ -" preload integer NOT NULL,\n"\ -" maxBalance integer NOT NULL,\n"\ -" accrual integer NOT NULL\n"\ -");\n"\ -"\n"\ -"CREATE INDEX MulticastRate_networkId ON MulticastRate (networkId);\n"\ -"\n"\ "CREATE TABLE Network (\n"\ " id char(16) PRIMARY KEY NOT NULL,\n"\ " name varchar(128) NOT NULL,\n"\ @@ -64,16 +17,6 @@ " revision integer NOT NULL DEFAULT(1)\n"\ ");\n"\ "\n"\ -"CREATE TABLE Relay (\n"\ -" networkId char(16) NOT NULL,\n"\ -" nodeId char(10) NOT NULL,\n"\ -" phyAddress varchar(64) NOT NULL\n"\ -");\n"\ -"\n"\ -"CREATE INDEX Relay_networkId ON Relay (networkId);\n"\ -"\n"\ -"CREATE UNIQUE INDEX Relay_networkId_nodeId ON Relay (networkId, nodeId);\n"\ -"\n"\ "CREATE TABLE Node (\n"\ " id char(10) PRIMARY KEY NOT NULL,\n"\ " identity varchar(4096) NOT NULL,\n"\ @@ -82,10 +25,65 @@ " firstSeen integer NOT NULL DEFAULT(0)\n"\ ");\n"\ "\n"\ +"CREATE TABLE IpAssignment (\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"\ +" ip blob(16) NOT NULL,\n"\ +" ipNetmaskBits integer NOT NULL DEFAULT(0),\n"\ +" ipVersion integer NOT NULL DEFAULT(4)\n"\ +");\n"\ +"\n"\ +"CREATE INDEX IpAssignment_networkId_ip ON IpAssignment (networkId, ip);\n"\ +"\n"\ +"CREATE INDEX IpAssignment_networkId_nodeId ON IpAssignment (networkId, nodeId);\n"\ +"\n"\ +"CREATE INDEX IpAssignment_networkId ON IpAssignment (networkId);\n"\ +"\n"\ +"CREATE TABLE IpAssignmentPool (\n"\ +" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\ +" ipNetwork blob(16) NOT NULL,\n"\ +" ipNetmaskBits integer NOT NULL,\n"\ +" ipVersion integer NOT NULL DEFAULT(4)\n"\ +");\n"\ +"\n"\ +"CREATE INDEX IpAssignmentPool_networkId ON IpAssignmentPool (networkId);\n"\ +"\n"\ +"CREATE TABLE Member (\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"\ +" authorized integer NOT NULL DEFAULT(0),\n"\ +" activeBridge integer NOT NULL DEFAULT(0),\n"\ +" PRIMARY KEY (networkId, nodeId)\n"\ +");\n"\ +"\n"\ +"CREATE INDEX Member_networkId ON Member (networkId);\n"\ +"\n"\ +"CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);\n"\ +"\n"\ +"CREATE TABLE MulticastRate (\n"\ +" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\ +" mgMac char(12) NOT NULL,\n"\ +" mgAdi integer NOT NULL DEFAULT(0),\n"\ +" preload integer NOT NULL,\n"\ +" maxBalance integer NOT NULL,\n"\ +" accrual integer NOT NULL\n"\ +");\n"\ +"\n"\ +"CREATE INDEX MulticastRate_networkId ON MulticastRate (networkId);\n"\ +"\n"\ +"CREATE TABLE Relay (\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"\ +" phyAddress varchar(64) NOT NULL,\n"\ +" PRIMARY KEY (networkId, nodeId)\n"\ +");\n"\ +"\n"\ +"CREATE INDEX Relay_networkId ON Relay (networkId);\n"\ +"\n"\ "CREATE TABLE Rule (\n"\ -" networkId char(16) NOT NULL,\n"\ +" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\ " ruleId integer NOT NULL,\n"\ -" nodeId char(10),\n"\ +" nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n"\ " vlanId integer,\n"\ " vlanPcp integer,\n"\ " etherType integer,\n"\ From 0d0af07ce969c9dd5a416c3b9f466ab0139a57e3 Mon Sep 17 00:00:00 2001 From: Kees Bos Date: Thu, 11 Jun 2015 11:49:13 +0200 Subject: [PATCH 07/37] Get deletion of networks in controller going Multiple statements in a sqlite3_prepare_v2 is not usable. Only the first statement will be executed. Since the schema now uses 'ON DELETE CASCADE', there's only one statement needed. If multiple statements are needed, there should be either multiple sqlite3_prepare_v2 calls be used or the sqlite3_exec function. --- controller/SqliteNetworkController.cpp | 5 ++--- service/ControlPlane.cpp | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/controller/SqliteNetworkController.cpp b/controller/SqliteNetworkController.cpp index a1905221f..6fec64534 100644 --- a/controller/SqliteNetworkController.cpp +++ b/controller/SqliteNetworkController.cpp @@ -179,7 +179,7 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) : ||(sqlite3_prepare_v2(_db,"DELETE FROM Rule WHERE networkId = ?",-1,&_sDeleteRulesForNetwork,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"INSERT INTO IpAssignmentPool (networkId,ipNetwork,ipNetmaskBits,ipVersion) VALUES (?,?,?,?)",-1,&_sCreateIpAssignmentPool,(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 IpAssignment WHERE networkId = ?; DELETE FROM IpAssignmentPool WHERE networkId = ?; DELETE FROM Member WHERE networkId = ?; DELETE FROM MulticastRate WHERE networkId = ?; DELETE FROM Relay WHERE networkId = ?; DELETE FROM Rule WHERE networkId = ?; DELETE FROM Network WHERE id = ?;",-1,&_sDeleteNetworkAndRelated,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"DELETE FROM Network WHERE id = ?;",-1,&_sDeleteNetworkAndRelated,(const char **)0) != SQLITE_OK) ) { //printf("!!! %s\n",sqlite3_errmsg(_db)); sqlite3_close(_db); @@ -1017,8 +1017,7 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpDELETE( } else { sqlite3_reset(_sDeleteNetworkAndRelated); - for(int i=1;i<=7;++i) - sqlite3_bind_text(_sDeleteNetworkAndRelated,i,nwids,16,SQLITE_STATIC); + sqlite3_bind_text(_sDeleteNetworkAndRelated,1,nwids,16,SQLITE_STATIC); return ((sqlite3_step(_sDeleteNetworkAndRelated) == SQLITE_DONE) ? 200 : 500); } diff --git a/service/ControlPlane.cpp b/service/ControlPlane.cpp index 71b3fd3fb..3ff9b7a21 100644 --- a/service/ControlPlane.cpp +++ b/service/ControlPlane.cpp @@ -525,7 +525,7 @@ unsigned int ControlPlane::handleRequest( } else { #ifdef ZT_ENABLE_NETWORK_CONTROLLER if (_controller) - _controller->handleControlPlaneHttpDELETE(std::vector(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType); + scode = _controller->handleControlPlaneHttpDELETE(std::vector(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType); else scode = 404; #else scode = 404; From c2ce018202c626ac25b821a1fe2c27edb7877411 Mon Sep 17 00:00:00 2001 From: Kees Bos Date: Thu, 11 Jun 2015 12:10:25 +0200 Subject: [PATCH 08/37] Return 404 on delete if network doesn't exist (controller) --- controller/SqliteNetworkController.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/controller/SqliteNetworkController.cpp b/controller/SqliteNetworkController.cpp index 6fec64534..f7604b158 100644 --- a/controller/SqliteNetworkController.cpp +++ b/controller/SqliteNetworkController.cpp @@ -993,6 +993,11 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpDELETE( char nwids[24]; Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid); + sqlite3_reset(_sGetNetworkById); + sqlite3_bind_text(_sGetNetworkById,1,nwids,16,SQLITE_STATIC); + if (sqlite3_step(_sGetNetworkById) != SQLITE_ROW) + return 404; + if (path.size() >= 3) { if ((path.size() == 4)&&(path[2] == "member")&&(path[3].length() == 10)) { From 7a55c6b388740f2dde67ae69011519147b06f3b6 Mon Sep 17 00:00:00 2001 From: Kees Bos Date: Thu, 11 Jun 2015 12:20:52 +0200 Subject: [PATCH 09/37] Return 404 on delete if network member is missing (controller) --- controller/SqliteNetworkController.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/controller/SqliteNetworkController.cpp b/controller/SqliteNetworkController.cpp index f7604b158..67fe1f9d1 100644 --- a/controller/SqliteNetworkController.cpp +++ b/controller/SqliteNetworkController.cpp @@ -1005,6 +1005,12 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpDELETE( char addrs[24]; Utils::snprintf(addrs,sizeof(addrs),"%.10llx",address); + sqlite3_reset(_sGetMember); + sqlite3_bind_text(_sGetMember,1,nwids,16,SQLITE_STATIC); + sqlite3_bind_text(_sGetMember,2,addrs,10,SQLITE_STATIC); + if (sqlite3_step(_sGetMember) != SQLITE_ROW) + return 404; + sqlite3_reset(_sDeleteIpAllocations); sqlite3_bind_text(_sDeleteIpAllocations,1,nwids,16,SQLITE_STATIC); sqlite3_bind_text(_sDeleteIpAllocations,2,addrs,10,SQLITE_STATIC); From dc50e8ae5b4b8ba194d46e5eba4f5ce4a12bf724 Mon Sep 17 00:00:00 2001 From: Kees Bos Date: Thu, 11 Jun 2015 17:56:54 +0200 Subject: [PATCH 10/37] Add ui to /var/lib/zerotier (linux installer) --- ext/installfiles/linux/buildinstaller.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ext/installfiles/linux/buildinstaller.sh b/ext/installfiles/linux/buildinstaller.sh index 496ba32ce..4f661b8d5 100755 --- a/ext/installfiles/linux/buildinstaller.sh +++ b/ext/installfiles/linux/buildinstaller.sh @@ -49,9 +49,12 @@ case "$system" in echo "Assembling Linux installer for $machine and version $vmajor.$vminor.$revision" - mkdir -p 'build-installer/var/lib/zerotier-one' + mkdir -p 'build-installer/var/lib/zerotier-one/ui' cp -fp 'ext/installfiles/linux/uninstall.sh' 'build-installer/var/lib/zerotier-one' cp -fp 'zerotier-one' 'build-installer/var/lib/zerotier-one' + for f in ui/*.html ui/*.js ui/*.css ui/*.jsx ; do + cp -fp "$f" 'build-installer/var/lib/zerotier-one/ui' + done mkdir -p 'build-installer/tmp' cp -fp 'ext/installfiles/linux/init.d/zerotier-one' 'build-installer/tmp/init.d_zerotier-one' cp -fp 'ext/installfiles/linux/systemd/zerotier-one.service' 'build-installer/tmp/systemd_zerotier-one.service' From 494681a48266f84c2f5518b1df357a89ae51c98a Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 12 Jun 2015 16:02:04 +0200 Subject: [PATCH 11/37] This might be a final fix for GitHub issue #173 and possibly others: ACTIVELY detect borked port status on Windows and if any "cable unplugged" or other wacky states are detected whack the adapter (close and reopen). Tested adding a whole bunch of windows networks, removing, adding more, etc. and it seems to work very well! --- osdep/WindowsEthernetTap.cpp | 348 +++++++++++++++++------------------ osdep/WindowsEthernetTap.hpp | 4 +- 2 files changed, 175 insertions(+), 177 deletions(-) diff --git a/osdep/WindowsEthernetTap.cpp b/osdep/WindowsEthernetTap.cpp index b373d9e27..d477f2e3d 100644 --- a/osdep/WindowsEthernetTap.cpp +++ b/osdep/WindowsEthernetTap.cpp @@ -92,9 +92,6 @@ static const WindowsEthernetTapEnv WINENV; // Only create or delete devices one at a time static Mutex _systemTapInitLock; -// Incrementing this causes everyone currently open to close and reopen -static volatile int _systemTapResetStatus = 0; - } // anonymous namespace WindowsEthernetTap::WindowsEthernetTap( @@ -268,12 +265,6 @@ WindowsEthernetTap::WindowsEthernetTap( } } else break; // no more keys or error occurred } - - // When we create a new tap device from scratch, existing taps for - // some reason go into 'unplugged' state. This can be fixed by - // closing and re-opening them. Incrementing this causes all - // existing tap threads to do this. - ++_systemTapResetStatus; } if (_netCfgInstanceId.length() > 0) { @@ -299,7 +290,6 @@ WindowsEthernetTap::WindowsEthernetTap( throw std::runtime_error("unable to find or create tap adapter"); } - // Convert device GUID junk... blech... is there an easier way to do this? { char nobraces[128]; const char *nbtmp1 = _netCfgInstanceId.c_str(); @@ -573,191 +563,199 @@ void WindowsEthernetTap::scanMulticastGroups(std::vector &added, void WindowsEthernetTap::threadMain() throw() { - char tapPath[256]; - OVERLAPPED tapOvlRead,tapOvlWrite; + char tapReadBuf[ZT_IF_MTU + 32]; + char tapPath[128]; HANDLE wait4[3]; - char *tapReadBuf = (char *)0; - - /* No idea why I did this. I did it a long time ago and there was only a - * a snarky comment. But I'd never do crap like this without a reason, so - * I am leaving it alone with a more descriptive snarky comment. */ - while (!tapReadBuf) { - tapReadBuf = (char *)::malloc(ZT_IF_MTU + 32); - if (!tapReadBuf) - Sleep(1000); - } + OVERLAPPED tapOvlRead,tapOvlWrite; Utils::snprintf(tapPath,sizeof(tapPath),"\\\\.\\Global\\%s.tap",_netCfgInstanceId.c_str()); - int prevTapResetStatus = _systemTapResetStatus; - bool throwOneAway = true; // Restart once on startup, because Windows. - bool powerCycle = true; // If true, "power cycle" the device, because Windows. - while (_run) { - if (powerCycle) { - _disableTapDevice(); - Sleep(500); + + try { + while (_run) { _enableTapDevice(); Sleep(500); - } - _tap = CreateFileA(tapPath,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_SYSTEM|FILE_FLAG_OVERLAPPED,NULL); - if (_tap == INVALID_HANDLE_VALUE) { - fprintf(stderr,"Error opening %s -- retrying.\r\n",tapPath); - powerCycle = true; - continue; - } - - { - uint32_t tmpi = 1; - DWORD bytesReturned = 0; - DeviceIoControl(_tap,TAP_WIN_IOCTL_SET_MEDIA_STATUS,&tmpi,sizeof(tmpi),&tmpi,sizeof(tmpi),&bytesReturned,NULL); - } - - { -#ifdef ZT_WINDOWS_CREATE_FAKE_DEFAULT_ROUTE - /* This inserts a fake default route and a fake ARP entry, forcing - * Windows to detect this as a "real" network and apply proper - * firewall rules. - * - * This hack is completely stupid, but Windows made me do it - * by being broken and insane. - * - * Background: Windows tries to detect its network location by - * matching it to the ARP address of the default route. Networks - * without default routes are "unidentified networks" and cannot - * have their firewall classification changed by the user (easily). - * - * Yes, you read that right. - * - * The common workaround is to set *NdisDeviceType to 1, which - * totally disables all Windows firewall functionality. This is - * the answer you'll find on most forums for things like OpenVPN. - * - * Yes, you read that right. - * - * The default route workaround is also known, but for this to - * work there must be a known default IP that resolves to a known - * ARP address. This works for an OpenVPN tunnel, but not here - * because this isn't a tunnel. It's a mesh. There is no "other - * end," or any other known always on IP. - * - * So let's make a fake one and shove it in there along with its - * fake static ARP entry. Also makes it instant-on and static. - * - * We'll have to see what DHCP does with this. In the future we - * probably will not want to do this on DHCP-enabled networks, so - * when we enable DHCP we will go in and yank this wacko hacko from - * the routing table before doing so. - * - * Like Jesse Pinkman would say: "YEEEEAAH BITCH!" */ - const uint32_t fakeIp = htonl(0x19fffffe); // 25.255.255.254 -- unrouted IPv4 block - for(int i=0;i<8;++i) { - MIB_IPNET_ROW2 ipnr; - memset(&ipnr,0,sizeof(ipnr)); - ipnr.Address.si_family = AF_INET; - ipnr.Address.Ipv4.sin_addr.s_addr = fakeIp; - ipnr.InterfaceLuid.Value = _deviceLuid.Value; - ipnr.PhysicalAddress[0] = _mac[0] ^ 0x10; // just make something up that's consistent and not part of this net - ipnr.PhysicalAddress[1] = 0x00; - ipnr.PhysicalAddress[2] = (UCHAR)((_deviceGuid.Data1 >> 24) & 0xff); - ipnr.PhysicalAddress[3] = (UCHAR)((_deviceGuid.Data1 >> 16) & 0xff); - ipnr.PhysicalAddress[4] = (UCHAR)((_deviceGuid.Data1 >> 8) & 0xff); - ipnr.PhysicalAddress[5] = (UCHAR)(_deviceGuid.Data1 & 0xff); - ipnr.PhysicalAddressLength = 6; - ipnr.State = NlnsPermanent; - ipnr.IsRouter = 1; - ipnr.IsUnreachable = 0; - ipnr.ReachabilityTime.LastReachable = 0x0fffffff; - ipnr.ReachabilityTime.LastUnreachable = 1; - DWORD result = CreateIpNetEntry2(&ipnr); - if (result != NO_ERROR) - Sleep(500); - else break; + _tap = CreateFileA(tapPath,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_SYSTEM|FILE_FLAG_OVERLAPPED,NULL); + if (_tap == INVALID_HANDLE_VALUE) { + _disableTapDevice(); + _enableTapDevice(); + Sleep(1000); + continue; } - for(int i=0;i<8;++i) { - MIB_IPFORWARD_ROW2 nr; - memset(&nr,0,sizeof(nr)); - InitializeIpForwardEntry(&nr); - nr.InterfaceLuid.Value = _deviceLuid.Value; - nr.DestinationPrefix.Prefix.si_family = AF_INET; // rest is left as 0.0.0.0/0 - nr.NextHop.si_family = AF_INET; - nr.NextHop.Ipv4.sin_addr.s_addr = fakeIp; - nr.Metric = 9999; // do not use as real default route - nr.Protocol = MIB_IPPROTO_NETMGMT; - DWORD result = CreateIpForwardEntry2(&nr); - if (result != NO_ERROR) - Sleep(500); - else break; + + { + uint32_t tmpi = 1; + DWORD bytesReturned = 0; + DeviceIoControl(_tap,TAP_WIN_IOCTL_SET_MEDIA_STATUS,&tmpi,sizeof(tmpi),&tmpi,sizeof(tmpi),&bytesReturned,NULL); + } + +#ifdef ZT_WINDOWS_CREATE_FAKE_DEFAULT_ROUTE + { + /* This inserts a fake default route and a fake ARP entry, forcing + * Windows to detect this as a "real" network and apply proper + * firewall rules. + * + * This hack is completely stupid, but Windows made me do it + * by being broken and insane. + * + * Background: Windows tries to detect its network location by + * matching it to the ARP address of the default route. Networks + * without default routes are "unidentified networks" and cannot + * have their firewall classification changed by the user (easily). + * + * Yes, you read that right. + * + * The common workaround is to set *NdisDeviceType to 1, which + * totally disables all Windows firewall functionality. This is + * the answer you'll find on most forums for things like OpenVPN. + * + * Yes, you read that right. + * + * The default route workaround is also known, but for this to + * work there must be a known default IP that resolves to a known + * ARP address. This works for an OpenVPN tunnel, but not here + * because this isn't a tunnel. It's a mesh. There is no "other + * end," or any other known always on IP. + * + * So let's make a fake one and shove it in there along with its + * fake static ARP entry. Also makes it instant-on and static. + * + * We'll have to see what DHCP does with this. In the future we + * probably will not want to do this on DHCP-enabled networks, so + * when we enable DHCP we will go in and yank this wacko hacko from + * the routing table before doing so. + * + * Like Jesse Pinkman would say: "YEEEEAAH BITCH!" */ + const uint32_t fakeIp = htonl(0x19fffffe); // 25.255.255.254 -- unrouted IPv4 block + for(int i=0;i<8;++i) { + MIB_IPNET_ROW2 ipnr; + memset(&ipnr,0,sizeof(ipnr)); + ipnr.Address.si_family = AF_INET; + ipnr.Address.Ipv4.sin_addr.s_addr = fakeIp; + ipnr.InterfaceLuid.Value = _deviceLuid.Value; + ipnr.PhysicalAddress[0] = _mac[0] ^ 0x10; // just make something up that's consistent and not part of this net + ipnr.PhysicalAddress[1] = 0x00; + ipnr.PhysicalAddress[2] = (UCHAR)((_deviceGuid.Data1 >> 24) & 0xff); + ipnr.PhysicalAddress[3] = (UCHAR)((_deviceGuid.Data1 >> 16) & 0xff); + ipnr.PhysicalAddress[4] = (UCHAR)((_deviceGuid.Data1 >> 8) & 0xff); + ipnr.PhysicalAddress[5] = (UCHAR)(_deviceGuid.Data1 & 0xff); + ipnr.PhysicalAddressLength = 6; + ipnr.State = NlnsPermanent; + ipnr.IsRouter = 1; + ipnr.IsUnreachable = 0; + ipnr.ReachabilityTime.LastReachable = 0x0fffffff; + ipnr.ReachabilityTime.LastUnreachable = 1; + DWORD result = CreateIpNetEntry2(&ipnr); + if (result != NO_ERROR) + Sleep(500); + else break; + } + for(int i=0;i<8;++i) { + MIB_IPFORWARD_ROW2 nr; + memset(&nr,0,sizeof(nr)); + InitializeIpForwardEntry(&nr); + nr.InterfaceLuid.Value = _deviceLuid.Value; + nr.DestinationPrefix.Prefix.si_family = AF_INET; // rest is left as 0.0.0.0/0 + nr.NextHop.si_family = AF_INET; + nr.NextHop.Ipv4.sin_addr.s_addr = fakeIp; + nr.Metric = 9999; // do not use as real default route + nr.Protocol = MIB_IPPROTO_NETMGMT; + DWORD result = CreateIpForwardEntry2(&nr); + if (result != NO_ERROR) + Sleep(500); + else break; + } } #endif - } - memset(&tapOvlRead,0,sizeof(tapOvlRead)); - tapOvlRead.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); - memset(&tapOvlWrite,0,sizeof(tapOvlWrite)); - tapOvlWrite.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); + memset(&tapOvlRead,0,sizeof(tapOvlRead)); + tapOvlRead.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); + memset(&tapOvlWrite,0,sizeof(tapOvlWrite)); + tapOvlWrite.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); - wait4[0] = _injectSemaphore; - wait4[1] = tapOvlRead.hEvent; - wait4[2] = tapOvlWrite.hEvent; // only included if writeInProgress is true + wait4[0] = _injectSemaphore; + wait4[1] = tapOvlRead.hEvent; + wait4[2] = tapOvlWrite.hEvent; // only included if writeInProgress is true - ReadFile(_tap,tapReadBuf,sizeof(tapReadBuf),NULL,&tapOvlRead); - bool writeInProgress = false; - while (_run) { - if ((prevTapResetStatus != _systemTapResetStatus)||(throwOneAway)) { - powerCycle = throwOneAway; - throwOneAway = false; - prevTapResetStatus = _systemTapResetStatus; - break; // this will cause us to close and reopen the tap - } - DWORD r = WaitForMultipleObjectsEx(writeInProgress ? 3 : 2,wait4,FALSE,2500,TRUE); - if (!_run) break; // will also break outer while(_run) + ReadFile(_tap,tapReadBuf,sizeof(tapReadBuf),NULL,&tapOvlRead); + bool writeInProgress = false; + ULONGLONG timeOfLastBorkCheck = GetTickCount64(); + while (_run) { + DWORD waitResult = WaitForMultipleObjectsEx(writeInProgress ? 3 : 2,wait4,FALSE,2500,TRUE); + if (!_run) break; // will also break outer while(_run) - if ((r == WAIT_TIMEOUT)||(r == WAIT_FAILED)) - continue; - - if (HasOverlappedIoCompleted(&tapOvlRead)) { - DWORD bytesRead = 0; - if (GetOverlappedResult(_tap,&tapOvlRead,&bytesRead,FALSE)) { - if ((bytesRead > 14)&&(_enabled)) { - MAC to(tapReadBuf,6); - 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); - } catch ( ... ) {} // handlers should not throw + // Check for issues with adapter and close/reopen if any are detected. This + // check fixes a while boatload of Windows adapter 'coma' issues after + // sleep/wake and when adapters are added/removed. Basically if the tap + // device is borked, whack it. + { + ULONGLONG tc = GetTickCount64(); + if ((tc - timeOfLastBorkCheck) >= 2500) { + timeOfLastBorkCheck = tc; + MIB_IF_TABLE2 *ift = NULL; + if ((GetIfTable2(&ift) == NO_ERROR)&&(ift)) { + bool isBorked = false; + for(ULONG r=0;rNumEntries;++r) { + if (ift->Table[r].InterfaceLuid.Value == _deviceLuid.Value) { + if ((ift->Table[r].InterfaceAndOperStatusFlags.NotMediaConnected)||(ift->Table[r].MediaConnectState == MediaConnectStateDisconnected)) + isBorked = true; + break; + } + } + FreeMibTable(ift); + if (isBorked) { + // Close and reopen tap device if there's an issue (outer loop) + break; + } + } } } - ReadFile(_tap,tapReadBuf,ZT_IF_MTU + 32,NULL,&tapOvlRead); + + if ((waitResult == WAIT_TIMEOUT)||(waitResult == WAIT_FAILED)) + continue; + + if (HasOverlappedIoCompleted(&tapOvlRead)) { + DWORD bytesRead = 0; + if (GetOverlappedResult(_tap,&tapOvlRead,&bytesRead,FALSE)) { + if ((bytesRead > 14)&&(_enabled)) { + MAC to(tapReadBuf,6); + 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); + } catch ( ... ) {} // handlers should not throw + } + } + ReadFile(_tap,tapReadBuf,ZT_IF_MTU + 32,NULL,&tapOvlRead); + } + + if (writeInProgress) { + if (HasOverlappedIoCompleted(&tapOvlWrite)) { + writeInProgress = false; + _injectPending_m.lock(); + _injectPending.pop(); + } else continue; // still writing, so skip code below and wait + } else _injectPending_m.lock(); + + if (!_injectPending.empty()) { + WriteFile(_tap,_injectPending.front().first.data,_injectPending.front().second,NULL,&tapOvlWrite); + writeInProgress = true; + } + + _injectPending_m.unlock(); } - if (writeInProgress) { - if (HasOverlappedIoCompleted(&tapOvlWrite)) { - writeInProgress = false; - _injectPending_m.lock(); - _injectPending.pop(); - } else continue; // still writing, so skip code below and wait - } else _injectPending_m.lock(); + CancelIo(_tap); - if (!_injectPending.empty()) { - WriteFile(_tap,_injectPending.front().first.data,_injectPending.front().second,NULL,&tapOvlWrite); - writeInProgress = true; - } + CloseHandle(tapOvlRead.hEvent); + CloseHandle(tapOvlWrite.hEvent); + CloseHandle(_tap); + _tap = INVALID_HANDLE_VALUE; - _injectPending_m.unlock(); + // We will restart and re-open the tap unless _run == false } - - CancelIo(_tap); - - CloseHandle(tapOvlRead.hEvent); - CloseHandle(tapOvlWrite.hEvent); - CloseHandle(_tap); - _tap = INVALID_HANDLE_VALUE; - - // We will restart and re-open the tap unless _run == false - } - - ::free(tapReadBuf); + } catch ( ... ) {} // catch unexpected exceptions -- this should not happen but would prevent program crash or other weird issues since threads should not throw } void WindowsEthernetTap::destroyAllPersistentTapDevices(const char *pathToHelpers) diff --git a/osdep/WindowsEthernetTap.hpp b/osdep/WindowsEthernetTap.hpp index 670467633..944b53f33 100644 --- a/osdep/WindowsEthernetTap.hpp +++ b/osdep/WindowsEthernetTap.hpp @@ -98,8 +98,8 @@ private: GUID _deviceGuid; NET_LUID _deviceLuid; - std::string _netCfgInstanceId; // NetCfgInstanceId, a GUID - std::string _deviceInstanceId; // DeviceInstanceID, another kind of "instance ID" + std::string _netCfgInstanceId; + std::string _deviceInstanceId; std::vector _multicastGroups; From 42390e662bb48813df03868949a45ae26c55790c Mon Sep 17 00:00:00 2001 From: Kees Bos Date: Sat, 13 Jun 2015 03:14:06 +0200 Subject: [PATCH 12/37] Pickup return code from handleControlPlaneHttpGET and handleControlPlaneHttpPOST --- service/ControlPlane.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/service/ControlPlane.cpp b/service/ControlPlane.cpp index 3ff9b7a21..4158ed43d 100644 --- a/service/ControlPlane.cpp +++ b/service/ControlPlane.cpp @@ -454,7 +454,7 @@ unsigned int ControlPlane::handleRequest( } else { #ifdef ZT_ENABLE_NETWORK_CONTROLLER if (_controller) - _controller->handleControlPlaneHttpGET(std::vector(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType); + scode = _controller->handleControlPlaneHttpGET(std::vector(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType); else scode = 404; #else scode = 404; @@ -490,7 +490,7 @@ unsigned int ControlPlane::handleRequest( } else { #ifdef ZT_ENABLE_NETWORK_CONTROLLER if (_controller) - _controller->handleControlPlaneHttpPOST(std::vector(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType); + scode = _controller->handleControlPlaneHttpPOST(std::vector(ps.begin()+1,ps.end()),urlArgs,headers,body,responseBody,responseContentType); else scode = 404; #else scode = 404; From 8a9715f183096e35e964a195b61f84bb263a9f85 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Sat, 13 Jun 2015 10:05:34 +0200 Subject: [PATCH 13/37] Rename ruleId to ruleNo and optimize some indexes in Sqlite3 schema. --- controller/SqliteNetworkController.cpp | 16 ++++++++-------- controller/schema.sql | 10 +++------- controller/schema.sql.c | 10 +++------- service/README.md | 4 ++-- 4 files changed, 16 insertions(+), 24 deletions(-) diff --git a/controller/SqliteNetworkController.cpp b/controller/SqliteNetworkController.cpp index 67fe1f9d1..5aad49ffd 100644 --- a/controller/SqliteNetworkController.cpp +++ b/controller/SqliteNetworkController.cpp @@ -167,8 +167,8 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) : ||(sqlite3_prepare_v2(_db,"SELECT n.id FROM Member AS m,Node AS n WHERE m.networkId = ? AND n.id = m.nodeId ORDER BY n.id ASC",-1,&_sListNetworkMembers,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT m.authorized,m.activeBridge,n.identity,n.lastAt,n.lastSeen,n.firstSeen FROM Member AS m,Node AS n WHERE m.networkId = ? AND m.nodeId = ?",-1,&_sGetMember2,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT ipNetwork,ipNetmaskBits,ipVersion FROM IpAssignmentPool WHERE networkId = ? ORDER BY ipNetwork ASC",-1,&_sGetIpAssignmentPools2,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"SELECT ruleId,nodeId,vlanId,vlanPcp,etherType,macSource,macDest,ipSource,ipDest,ipTos,ipProtocol,ipSourcePort,ipDestPort,\"flags\",invFlags,\"action\" FROM Rule WHERE networkId = ? ORDER BY ruleId ASC",-1,&_sListRules,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"INSERT INTO Rule (networkId,ruleId,nodeId,vlanId,vlanPcP,etherType,macSource,macDest,ipSource,ipDest,ipTos,ipProtocol,ipSourcePort,ipDestPort,\"action\") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",-1,&_sCreateRule,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"SELECT ruleNo,nodeId,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,"INSERT INTO Rule (networkId,ruleNo,nodeId,vlanId,vlanPcP,etherType,macSource,macDest,ipSource,ipDest,ipTos,ipProtocol,ipSourcePort,ipDestPort,\"action\") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",-1,&_sCreateRule,(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,"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) @@ -855,7 +855,7 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST( json_value *rj = j->u.object.values[k].value->u.array.values[kk]; if ((rj)&&(rj->type == json_object)) { struct { // NULL pointers indicate missing or NULL -- wildcards - const json_int_t *ruleId; + const json_int_t *ruleNo; const char *nodeId; const json_int_t *vlanId; const json_int_t *vlanPcp; @@ -875,8 +875,8 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST( memset(&rule,0,sizeof(rule)); for(unsigned int rk=0;rku.object.length;++rk) { - if ((!strcmp(rj->u.object.values[rk].name,"ruleId"))&&(rj->u.object.values[rk].value->type == json_integer)) - rule.ruleId = &(rj->u.object.values[rk].value->u.integer); + if ((!strcmp(rj->u.object.values[rk].name,"ruleNo"))&&(rj->u.object.values[rk].value->type == json_integer)) + rule.ruleNo = &(rj->u.object.values[rk].value->u.integer); else if ((!strcmp(rj->u.object.values[rk].name,"nodeId"))&&(rj->u.object.values[rk].value->type == json_string)) rule.nodeId = rj->u.object.values[rk].value->u.string.ptr; else if ((!strcmp(rj->u.object.values[rk].name,"vlanId"))&&(rj->u.object.values[rk].value->type == json_integer)) @@ -909,11 +909,11 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST( rule.action = rj->u.object.values[rk].value->u.string.ptr; } - if ((rule.ruleId)&&(rule.action)&&(rule.action[0])) { + if ((rule.ruleNo)&&(rule.action)&&(rule.action[0])) { char mactmp1[16],mactmp2[16]; sqlite3_reset(_sCreateRule); sqlite3_bind_text(_sCreateRule,1,nwids,16,SQLITE_STATIC); - sqlite3_bind_int64(_sCreateRule,2,*rule.ruleId); + sqlite3_bind_int64(_sCreateRule,2,*rule.ruleNo); // Optional values: null by default for(int i=3;i<=16;++i) @@ -1233,7 +1233,7 @@ unsigned int SqliteNetworkController::_doCPGet( bool firstRule = true; while (sqlite3_step(_sListRules) == SQLITE_ROW) { responseBody.append(firstRule ? "\n\t{\n" : ",{\n"); - Utils::snprintf(json,sizeof(json),"\t\t\"ruleId\": %lld,\n",sqlite3_column_int64(_sListRules,0)); + Utils::snprintf(json,sizeof(json),"\t\t\"ruleNo\": %lld,\n",sqlite3_column_int64(_sListRules,0)); responseBody.append(json); if (sqlite3_column_type(_sListRules,1) != SQLITE_NULL) { Utils::snprintf(json,sizeof(json),"\t\t\"nodeId\": \"%s\",\n",(const char *)sqlite3_column_text(_sListRules,1)); diff --git a/controller/schema.sql b/controller/schema.sql index a3a7bb7a5..25adce40d 100644 --- a/controller/schema.sql +++ b/controller/schema.sql @@ -32,12 +32,10 @@ CREATE TABLE IpAssignment ( ipVersion integer NOT NULL DEFAULT(4) ); -CREATE INDEX IpAssignment_networkId_ip ON IpAssignment (networkId, ip); +CREATE UNIQUE INDEX IpAssignment_networkId_ip ON IpAssignment (networkId, ip); CREATE INDEX IpAssignment_networkId_nodeId ON IpAssignment (networkId, nodeId); -CREATE INDEX IpAssignment_networkId ON IpAssignment (networkId); - CREATE TABLE IpAssignmentPool ( networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, ipNetwork blob(16) NOT NULL, @@ -55,8 +53,6 @@ CREATE TABLE Member ( PRIMARY KEY (networkId, nodeId) ); -CREATE INDEX Member_networkId ON Member (networkId); - CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge); CREATE TABLE MulticastRate ( @@ -81,7 +77,7 @@ CREATE INDEX Relay_networkId ON Relay (networkId); CREATE TABLE Rule ( networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, - ruleId integer NOT NULL, + ruleNo integer NOT NULL, nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE, vlanId integer, vlanPcp integer, @@ -99,4 +95,4 @@ CREATE TABLE Rule ( "action" varchar(4096) NOT NULL DEFAULT('accept') ); -CREATE INDEX Rule_networkId ON Rule (networkId); +CREATE UNIQUE INDEX Rule_networkId_ruleNo ON Rule (networkId, ruleNo); diff --git a/controller/schema.sql.c b/controller/schema.sql.c index 0078eac3a..243d37d5e 100644 --- a/controller/schema.sql.c +++ b/controller/schema.sql.c @@ -33,12 +33,10 @@ " ipVersion integer NOT NULL DEFAULT(4)\n"\ ");\n"\ "\n"\ -"CREATE INDEX IpAssignment_networkId_ip ON IpAssignment (networkId, ip);\n"\ +"CREATE UNIQUE INDEX IpAssignment_networkId_ip ON IpAssignment (networkId, ip);\n"\ "\n"\ "CREATE INDEX IpAssignment_networkId_nodeId ON IpAssignment (networkId, nodeId);\n"\ "\n"\ -"CREATE INDEX IpAssignment_networkId ON IpAssignment (networkId);\n"\ -"\n"\ "CREATE TABLE IpAssignmentPool (\n"\ " networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\ " ipNetwork blob(16) NOT NULL,\n"\ @@ -56,8 +54,6 @@ " PRIMARY KEY (networkId, nodeId)\n"\ ");\n"\ "\n"\ -"CREATE INDEX Member_networkId ON Member (networkId);\n"\ -"\n"\ "CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);\n"\ "\n"\ "CREATE TABLE MulticastRate (\n"\ @@ -82,7 +78,7 @@ "\n"\ "CREATE TABLE Rule (\n"\ " networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\ -" ruleId integer NOT NULL,\n"\ +" ruleNo integer NOT NULL,\n"\ " nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n"\ " vlanId integer,\n"\ " vlanPcp integer,\n"\ @@ -100,5 +96,5 @@ " \"action\" varchar(4096) NOT NULL DEFAULT('accept')\n"\ ");\n"\ "\n"\ -"CREATE INDEX Rule_networkId ON Rule (networkId);\n"\ +"CREATE UNIQUE INDEX Rule_networkId_ruleNo ON Rule (networkId, ruleNo);\n"\ "" diff --git a/service/README.md b/service/README.md index acad97a14..2a283cbd1 100644 --- a/service/README.md +++ b/service/README.md @@ -204,7 +204,7 @@ Relay objects define network-specific preferred relay nodes. Traffic to peers on * **Note**: at the moment, only rules specifying allowed Ethernet types are used. The database supports a richer rule set, but this is not implemented yet in the client. Other types of rules will have no effect (yet). -Rules are matched in order of ruleId. If no rules match, the default action is 'drop'. To allow all traffic, create a single rule with all *null* fields and an action of 'accept'. +Rules are matched in order of ruleNo. If no rules match, the default action is 'drop'. To allow all traffic, create a single rule with all *null* fields and an action of 'accept'. Rule object fields can be *null*, in which case they are omitted from the object. A null field indicates "no match on this criteria." @@ -212,7 +212,7 @@ IP related fields apply only to Ethernet frames of type IPv4 or IPV6. Otherwise
FieldTypeDescription
- + From 96a58becf8fe10efceab38c49553b009754d2632 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Sat, 13 Jun 2015 11:34:31 +0200 Subject: [PATCH 14/37] Gateways support in network controller schema and database (not implemented yet in client) toward GitHub issue #178 --- controller/SqliteNetworkController.cpp | 130 ++++++++++++++++++++++++- controller/SqliteNetworkController.hpp | 5 +- controller/schema.sql | 9 ++ controller/schema.sql.c | 9 ++ node/InetAddress.hpp | 10 ++ node/NetworkConfig.hpp | 37 +++++++ 6 files changed, 194 insertions(+), 6 deletions(-) diff --git a/controller/SqliteNetworkController.cpp b/controller/SqliteNetworkController.cpp index 5aad49ffd..35666fdba 100644 --- a/controller/SqliteNetworkController.cpp +++ b/controller/SqliteNetworkController.cpp @@ -179,7 +179,10 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) : ||(sqlite3_prepare_v2(_db,"DELETE FROM Rule WHERE networkId = ?",-1,&_sDeleteRulesForNetwork,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"INSERT INTO IpAssignmentPool (networkId,ipNetwork,ipNetmaskBits,ipVersion) VALUES (?,?,?,?)",-1,&_sCreateIpAssignmentPool,(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 Network WHERE id = ?;",-1,&_sDeleteNetworkAndRelated,(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 ip,ipVersion,metric FROM Gateway WHERE networkId = ? ORDER BY metric ASC",-1,&_sGetGateways,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"DELETE FROM Gateway WHERE networkId = ?",-1,&_sDeleteGateways,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"INSERT INTO Gateway (networkId,ip,ipVersion,metric) VALUES (?,?,?,?)",-1,&_sCreateGateway,(const char **)0) != SQLITE_OK) ) { //printf("!!! %s\n",sqlite3_errmsg(_db)); sqlite3_close(_db); @@ -222,7 +225,10 @@ SqliteNetworkController::~SqliteNetworkController() sqlite3_finalize(_sDeleteIpAssignmentPoolsForNetwork); sqlite3_finalize(_sDeleteRulesForNetwork); sqlite3_finalize(_sCreateIpAssignmentPool); - sqlite3_finalize(_sDeleteNetworkAndRelated); + sqlite3_finalize(_sDeleteNetwork); + sqlite3_finalize(_sGetGateways); + sqlite3_finalize(_sDeleteGateways); + sqlite3_finalize(_sCreateGateway); sqlite3_close(_db); } } @@ -455,6 +461,52 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co netconf[ZT_NETWORKCONFIG_DICT_KEY_RELAYS] = relays; } + { + char tmp[128]; + std::string gateways; + sqlite3_reset(_sGetGateways); + sqlite3_bind_text(_sGetGateways,1,network.id,16,SQLITE_STATIC); + while (sqlite3_step(_sGetGateways) == SQLITE_ROW) { + const unsigned char *ip = (const unsigned char *)sqlite3_column_blob(_sGetGateways,0); + switch(sqlite3_column_int(_sGetGateways,1)) { // ipVersion + case 4: + Utils::snprintf(tmp,sizeof(tmp),"%s%d.%d.%d.%d/%d", + (gateways.length() > 0) ? "," : "", + (int)ip[0], + (int)ip[1], + (int)ip[2], + (int)ip[3], + (int)sqlite3_column_int(_sGetGateways,2)); // metric + gateways.append(tmp); + break; + case 6: + Utils::snprintf(tmp,sizeof(tmp),"%s%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x/%d", + (gateways.length() > 0) ? "," : "", + (int)ip[0], + (int)ip[1], + (int)ip[2], + (int)ip[3], + (int)ip[4], + (int)ip[5], + (int)ip[6], + (int)ip[7], + (int)ip[8], + (int)ip[9], + (int)ip[10], + (int)ip[11], + (int)ip[12], + (int)ip[13], + (int)ip[14], + (int)ip[15], + (int)sqlite3_column_int(_sGetGateways,2)); // metric + gateways.append(tmp); + break; + } + } + if (gateways.length()) + netconf[ZT_NETWORKCONFIG_DICT_KEY_GATEWAYS] = gateways; + } + if ((network.v4AssignMode)&&(!strcmp(network.v4AssignMode,"zt"))) { std::string v4s; @@ -808,6 +860,31 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST( sqlite3_step(_sCreateRelay); } } + } else if (!strcmp(j->u.object.values[k].name,"gateways")) { + sqlite3_reset(_sDeleteGateways); + sqlite3_bind_text(_sDeleteGateways,1,nwids,16,SQLITE_STATIC); + sqlite3_step(_sDeleteGateways); + if (j->u.object.values[k].value->type == json_array) { + for(unsigned int kk=0;kku.object.values[k].value->u.array.length;++kk) { + json_value *gateway = j->u.object.values[k].value->u.array.values[kk]; + if ((gateway)&&(gateway->type == json_string)) { + InetAddress gwip(gateway->u.string.ptr); + int ipVersion = 0; + if (gwip.ss_family == AF_INET) + ipVersion = 4; + else if (gwip.ss_family == AF_INET6) + ipVersion = 6; + if (ipVersion) { + sqlite3_reset(_sCreateGateway); + sqlite3_bind_text(_sCreateGateway,1,nwids,16,SQLITE_STATIC); + sqlite3_bind_blob(_sCreateGateway,2,gwip.rawIpData(),(gwip.ss_family == AF_INET6) ? 16 : 4,SQLITE_STATIC); + sqlite3_bind_int(_sCreateGateway,3,ipVersion); + sqlite3_bind_int(_sCreateGateway,4,(int)gwip.metric()); + sqlite3_step(_sCreateGateway); + } + } + } + } } else if (!strcmp(j->u.object.values[k].name,"ipAssignmentPools")) { if (j->u.object.values[k].value->type == json_array) { std::set pools; @@ -1027,9 +1104,9 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpDELETE( } else { - sqlite3_reset(_sDeleteNetworkAndRelated); - sqlite3_bind_text(_sDeleteNetworkAndRelated,1,nwids,16,SQLITE_STATIC); - return ((sqlite3_step(_sDeleteNetworkAndRelated) == SQLITE_DONE) ? 200 : 500); + sqlite3_reset(_sDeleteNetwork); + sqlite3_bind_text(_sDeleteNetwork,1,nwids,16,SQLITE_STATIC); + return ((sqlite3_step(_sDeleteNetwork) == SQLITE_DONE) ? 200 : 500); } } // else 404 @@ -1212,6 +1289,49 @@ unsigned int SqliteNetworkController::_doCPGet( responseBody.append(_jsonEscape((const char *)sqlite3_column_text(_sGetRelays,1))); responseBody.append("\"}"); } + responseBody.append("],\n\t\"gateways\": ["); + + sqlite3_reset(_sGetGateways); + sqlite3_bind_text(_sGetGateways,1,nwids,16,SQLITE_STATIC); + bool firstGateway = true; + while (sqlite3_step(_sGetGateways) == SQLITE_ROW) { + char tmp[128]; + const unsigned char *ip = (const unsigned char *)sqlite3_column_blob(_sGetGateways,0); + switch(sqlite3_column_int(_sGetGateways,1)) { // ipVersion + case 4: + Utils::snprintf(tmp,sizeof(tmp),"%s%d.%d.%d.%d/%d\"", + (firstGateway) ? "\"" : ",\"", + (int)ip[0], + (int)ip[1], + (int)ip[2], + (int)ip[3], + (int)sqlite3_column_int(_sGetGateways,2)); // metric + break; + case 6: + Utils::snprintf(tmp,sizeof(tmp),"%s%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x/%d\"", + (firstGateway) ? "\"" : ",\"", + (int)ip[0], + (int)ip[1], + (int)ip[2], + (int)ip[3], + (int)ip[4], + (int)ip[5], + (int)ip[6], + (int)ip[7], + (int)ip[8], + (int)ip[9], + (int)ip[10], + (int)ip[11], + (int)ip[12], + (int)ip[13], + (int)ip[14], + (int)ip[15], + (int)sqlite3_column_int(_sGetGateways,2)); // metric + break; + } + responseBody.append(tmp); + firstGateway = false; + } responseBody.append("],\n\t\"ipAssignmentPools\": ["); sqlite3_reset(_sGetIpAssignmentPools2); diff --git a/controller/SqliteNetworkController.hpp b/controller/SqliteNetworkController.hpp index 5c92cc0b1..d258933d5 100644 --- a/controller/SqliteNetworkController.hpp +++ b/controller/SqliteNetworkController.hpp @@ -123,7 +123,10 @@ private: sqlite3_stmt *_sDeleteRulesForNetwork; sqlite3_stmt *_sCreateIpAssignmentPool; sqlite3_stmt *_sDeleteMember; - sqlite3_stmt *_sDeleteNetworkAndRelated; + sqlite3_stmt *_sDeleteNetwork; + sqlite3_stmt *_sGetGateways; + sqlite3_stmt *_sDeleteGateways; + sqlite3_stmt *_sCreateGateway; Mutex _lock; }; diff --git a/controller/schema.sql b/controller/schema.sql index 25adce40d..809c7161d 100644 --- a/controller/schema.sql +++ b/controller/schema.sql @@ -24,6 +24,15 @@ CREATE TABLE Node ( firstSeen integer NOT NULL DEFAULT(0) ); +CREATE TABLE Gateway ( + networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, + ip blob(16) NOT NULL, + ipVersion integer NOT NULL DEFAULT(4), + metric integer NOT NULL DEFAULT(0) +); + +CREATE UNIQUE INDEX Gateway_networkId_ip ON Gateway (networkId, ip); + CREATE TABLE IpAssignment ( networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE, diff --git a/controller/schema.sql.c b/controller/schema.sql.c index 243d37d5e..f1c663584 100644 --- a/controller/schema.sql.c +++ b/controller/schema.sql.c @@ -25,6 +25,15 @@ " firstSeen integer NOT NULL DEFAULT(0)\n"\ ");\n"\ "\n"\ +"CREATE TABLE Gateway (\n"\ +" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\ +" ip blob(16) NOT NULL,\n"\ +" ipVersion integer NOT NULL DEFAULT(4),\n"\ +" metric integer NOT NULL DEFAULT(0)\n"\ +");\n"\ +"\n"\ +"CREATE UNIQUE INDEX Gateway_networkId_ip ON Gateway (networkId, ip);\n"\ +"\n"\ "CREATE TABLE IpAssignment (\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"\ diff --git a/node/InetAddress.hpp b/node/InetAddress.hpp index 5b7251745..16e3f4d52 100644 --- a/node/InetAddress.hpp +++ b/node/InetAddress.hpp @@ -265,6 +265,16 @@ struct InetAddress : public sockaddr_storage */ inline unsigned int netmaskBits() const throw() { return port(); } + /** + * Alias for port() + * + * This just aliases port() because for gateways we use this field to + * store the gateway metric. + * + * @return Gateway metric + */ + inline unsigned int metric() const throw() { return port(); } + /** * Construct a full netmask as an InetAddress */ diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp index 89d1aec50..afbff3bfc 100644 --- a/node/NetworkConfig.hpp +++ b/node/NetworkConfig.hpp @@ -49,24 +49,61 @@ namespace ZeroTier { // These dictionary keys are short so they don't take up much room in // netconf response packets. + +// integer(hex)[,integer(hex),...] #define ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES "et" + +// network ID #define ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID "nwid" + +// integer(hex) #define ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP "ts" + +// integer(hex) #define ZT_NETWORKCONFIG_DICT_KEY_REVISION "r" + +// address of member #define ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO "id" + +// integer(hex) #define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT "ml" + +// dictionary of one or more of: MAC/ADI=preload,maxbalance,accrual #define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_RATES "mr" + +// 0/1 #define ZT_NETWORKCONFIG_DICT_KEY_PRIVATE "p" + +// text #define ZT_NETWORKCONFIG_DICT_KEY_NAME "n" + +// text #define ZT_NETWORKCONFIG_DICT_KEY_DESC "d" + +// IP/bits[,IP/bits,...] #define ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC "v4s" + +// IP/bits[,IP/bits,...] #define ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC "v6s" + +// serialized CertificateOfMembership #define ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP "com" + +// 0/1 #define ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST "eb" + +// 0/1 #define ZT_NETWORKCONFIG_DICT_KEY_ALLOW_PASSIVE_BRIDGING "pb" + +// node[,node,...] #define ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES "ab" + +// node;IP/port[,node;IP/port] #define ZT_NETWORKCONFIG_DICT_KEY_RELAYS "rl" +// IP/metric[,IP/metric,...] +#define ZT_NETWORKCONFIG_DICT_KEY_GATEWAYS "gw" + /** * Network configuration received from network controller nodes * From edbc5d3588eda9e596853024a42b304c77d5caff Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Sat, 13 Jun 2015 13:06:49 +0200 Subject: [PATCH 15/37] Gateways support in NetworkConfig object. --- node/NetworkConfig.cpp | 7 +++++++ node/NetworkConfig.hpp | 2 ++ 2 files changed, 9 insertions(+) diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp index 4b9620a6c..ecc4e8800 100644 --- a/node/NetworkConfig.cpp +++ b/node/NetworkConfig.cpp @@ -163,6 +163,13 @@ void NetworkConfig::_fromDictionary(const Dictionary &d) std::sort(_staticIps.begin(),_staticIps.end()); std::unique(_staticIps.begin(),_staticIps.end()); + std::vector gatewaysSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_GATEWAYS,"").c_str(),",","","")); + for(std::vector::const_iterator gwstr(gatewaysSplit.begin());gwstr!=gatewaysSplit.end();++gwstr) { + InetAddress gw(*gwstr); + if ((std::find(_gateways.begin(),_gateways.end(),gw) == _gateways.end())&&((gw.ss_family == AF_INET)||(gw.ss_family == AF_INET6))) + _gateways.push_back(gw); + } + std::vector activeBridgesSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES,"").c_str(),",","","")); for(std::vector::const_iterator a(activeBridgesSplit.begin());a!=activeBridgesSplit.end();++a) { if (a->length() == ZT_ADDRESS_LENGTH_HEX) { // ignore empty or garbage fields diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp index afbff3bfc..2fb56d6aa 100644 --- a/node/NetworkConfig.hpp +++ b/node/NetworkConfig.hpp @@ -183,6 +183,7 @@ public: inline const std::string &name() const throw() { return _name; } inline const std::string &description() const throw() { return _description; } inline const std::vector &staticIps() const throw() { return _staticIps; } + inline const std::vector &gateways() const throw() { return _gateways; } inline const std::vector
&activeBridges() const throw() { return _activeBridges; } inline const std::vector< std::pair > &relays() const throw() { return _relays; } inline const CertificateOfMembership &com() const throw() { return _com; } @@ -225,6 +226,7 @@ private: std::string _name; std::string _description; std::vector _staticIps; + std::vector _gateways; std::vector
_activeBridges; std::vector< std::pair > _relays; std::map _multicastRates; From 8aa68cd5f135f013a5f58e6bcf95f652d3ec625e Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Sat, 13 Jun 2015 13:13:19 +0200 Subject: [PATCH 16/37] Add new fields in operator== --- node/NetworkConfig.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp index ecc4e8800..5ed1dd3ff 100644 --- a/node/NetworkConfig.cpp +++ b/node/NetworkConfig.cpp @@ -218,7 +218,9 @@ bool NetworkConfig::operator==(const NetworkConfig &nc) const if (_name != nc._name) return false; if (_description != nc._description) return false; if (_staticIps != nc._staticIps) return false; + if (_gateways != nc._gateways) return false; if (_activeBridges != nc._activeBridges) return false; + if (_relays != nc._relays) return false; if (_multicastRates.size() == nc._multicastRates.size()) { // uclibc++ doesn't seem to implement map<> != map<> correctly, so do // it ourselves. Note that this depends on the maps being sorted. From 845955dea53035e8472059ff03feca9f47c0d5fa Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Sat, 13 Jun 2015 18:08:00 +0200 Subject: [PATCH 17/37] Add definition for VERB_CMA -- GitHub issue #180 --- node/Packet.cpp | 1 + node/Packet.hpp | 32 +++++++++++++++++++++++++++++--- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/node/Packet.cpp b/node/Packet.cpp index a81873ffd..f75d1df08 100644 --- a/node/Packet.cpp +++ b/node/Packet.cpp @@ -51,6 +51,7 @@ const char *Packet::verbString(Verb v) case VERB_MULTICAST_GATHER: return "MULTICAST_GATHER"; case VERB_MULTICAST_FRAME: return "MULTICAST_FRAME"; case VERB_SET_EPHEMERAL_KEY: return "SET_EPHEMERAL_KEY"; + case VERB_CMA: return "CMA"; } return "(unknown)"; } diff --git a/node/Packet.hpp b/node/Packet.hpp index 2dfb75e4b..1ec145d5c 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -513,8 +513,8 @@ public: * Destination address types and formats (not all of these are used now): * 0 - None -- no destination address data present * 1 - Ethernet address -- format: <[6] Ethernet MAC> - * 4 - 6-byte IPv4 address -- format: <[4] IP>, <[2] port> - * 6 - 18-byte IPv6 address -- format: <[16] IP>, <[2] port> + * 4 - 6-byte IPv4 UDP address/port -- format: <[4] IP>, <[2] port> + * 6 - 18-byte IPv6 UDP address/port -- format: <[16] IP>, <[2] port> * * OK payload: * <[8] timestamp (echoed from original HELLO)> @@ -770,6 +770,9 @@ public: VERB_MULTICAST_FRAME = 14, /* Ephemeral (PFS) key push: + * <[2] flags (unused and reserved, must be 0)> + * <[2] length of padding / extra field section> + * <[...] padding / extra field section> * <[8] 64-bit PFS key set ID sender holds for recipient (0==none)> * <[8] 64-bit PFS key set ID of this key set> * [... begin PFS key record ...] @@ -791,6 +794,12 @@ public: * the first record with common symmetric cipher, public key type, * and relevant flags must be used. * + * The padding section may be filled with an arbitrary amount of random + * or empty payload. This may be used as a countermeasure to prevent PFS + * key pushes from being recognized by packet size vs. other packets in + * the stream. This also provides potential space for additional fields + * that might be indicated in the future by flags. + * * Flags (all unspecified flags must be zero): * 0x01 - FIPS mode, only use record if FIPS compliant crypto in use * @@ -814,7 +823,24 @@ public: * <[8] PFS key set ID of received key set> * <[1] index in record list of chosen key record> */ - VERB_SET_EPHEMERAL_KEY = 15 + VERB_SET_EPHEMERAL_KEY = 15, + + /* "Call me at" -- push of potential endpoints for direct communication: + * <[1] flags> + * <[2] number of addresses> + * <[...] address types and addresses> + * + * Address types and addresses are of the same format as the destination + * address type and address in HELLO. + * + * The receiver may, upon receiving a CMA push, attempt to establish a + * direct link to one or more of the indicated addresses. Senders should + * only send CMA pushes to peers that they have some relationship + * with such as a shared network membership or a mutual trust. + * + * OK/ERROR are not generated. + */ + VERB_CMA = 16 }; /** From dcbae5f3138c3fcf1bfa1bce90dfa4a53062cecc Mon Sep 17 00:00:00 2001 From: Kees Bos Date: Sat, 13 Jun 2015 04:39:53 +0200 Subject: [PATCH 18/37] Bugfix controller get member info --- controller/SqliteNetworkController.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/SqliteNetworkController.cpp b/controller/SqliteNetworkController.cpp index 35666fdba..cb224c1de 100644 --- a/controller/SqliteNetworkController.cpp +++ b/controller/SqliteNetworkController.cpp @@ -1169,7 +1169,7 @@ unsigned int SqliteNetworkController::_doCPGet( sqlite3_bind_text(_sGetIpAssignmentsForNode2,1,nwids,16,SQLITE_STATIC); sqlite3_bind_text(_sGetIpAssignmentsForNode2,2,addrs,10,SQLITE_STATIC); bool firstIp = true; - while (sqlite3_step(_sGetIpAssignmentPools2) == SQLITE_ROW) { + while (sqlite3_step(_sGetIpAssignmentsForNode2) == SQLITE_ROW) { InetAddress ip((const void *)sqlite3_column_blob(_sGetIpAssignmentsForNode2,0),(sqlite3_column_int(_sGetIpAssignmentsForNode2,2) == 6) ? 16 : 4,(unsigned int)sqlite3_column_int(_sGetIpAssignmentPools2,1)); responseBody.append(firstIp ? "\"" : ",\""); firstIp = false; From 1cbdae65fec4e08c3e6f32860a739854183b5a45 Mon Sep 17 00:00:00 2001 From: Kees Bos Date: Sun, 14 Jun 2015 15:25:40 +0200 Subject: [PATCH 19/37] Fix controller/network/*/member/* Cross join works other than expected or something changed. The _sGetMember2 returned too many rows. Replaced it with an explicit join statement. --- controller/SqliteNetworkController.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/SqliteNetworkController.cpp b/controller/SqliteNetworkController.cpp index cb224c1de..352d214d5 100644 --- a/controller/SqliteNetworkController.cpp +++ b/controller/SqliteNetworkController.cpp @@ -165,7 +165,7 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) : ||(sqlite3_prepare_v2(_db,"SELECT nodeId,phyAddress FROM Relay WHERE networkId = ? ORDER BY nodeId ASC",-1,&_sGetRelays,(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,"SELECT n.id FROM Member AS m,Node AS n WHERE m.networkId = ? AND n.id = m.nodeId ORDER BY n.id ASC",-1,&_sListNetworkMembers,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"SELECT m.authorized,m.activeBridge,n.identity,n.lastAt,n.lastSeen,n.firstSeen FROM Member AS m,Node AS n WHERE m.networkId = ? AND m.nodeId = ?",-1,&_sGetMember2,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"SELECT m.authorized,m.activeBridge,n.identity,n.lastAt,n.lastSeen,n.firstSeen FROM Member AS m 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,"SELECT ipNetwork,ipNetmaskBits,ipVersion FROM IpAssignmentPool WHERE networkId = ? ORDER BY ipNetwork ASC",-1,&_sGetIpAssignmentPools2,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT ruleNo,nodeId,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,"INSERT INTO Rule (networkId,ruleNo,nodeId,vlanId,vlanPcP,etherType,macSource,macDest,ipSource,ipDest,ipTos,ipProtocol,ipSourcePort,ipDestPort,\"action\") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",-1,&_sCreateRule,(const char **)0) != SQLITE_OK) From 2e1d363a86f3c662b208cb10fe28880e2e373081 Mon Sep 17 00:00:00 2001 From: Kees Bos Date: Mon, 15 Jun 2015 02:05:11 +0200 Subject: [PATCH 20/37] Removed a superfluous cross join --- controller/SqliteNetworkController.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/SqliteNetworkController.cpp b/controller/SqliteNetworkController.cpp index 352d214d5..9f91564a3 100644 --- a/controller/SqliteNetworkController.cpp +++ b/controller/SqliteNetworkController.cpp @@ -164,7 +164,7 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) : ||(sqlite3_prepare_v2(_db,"DELETE FROM IpAssignment WHERE networkId = ? AND nodeId = ?",-1,&_sDeleteIpAllocations,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT nodeId,phyAddress FROM Relay WHERE networkId = ? ORDER BY nodeId ASC",-1,&_sGetRelays,(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,"SELECT n.id FROM Member AS m,Node AS n WHERE m.networkId = ? AND n.id = m.nodeId ORDER BY n.id ASC",-1,&_sListNetworkMembers,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"SELECT m.nodeId FROM Member AS m WHERE m.networkId = ? ORDER BY m.nodeId ASC",-1,&_sListNetworkMembers,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT m.authorized,m.activeBridge,n.identity,n.lastAt,n.lastSeen,n.firstSeen FROM Member AS m 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,"SELECT ipNetwork,ipNetmaskBits,ipVersion FROM IpAssignmentPool WHERE networkId = ? ORDER BY ipNetwork ASC",-1,&_sGetIpAssignmentPools2,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT ruleNo,nodeId,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) From 4affa10ca0bca91f9ec44d39860c8ede20daf9a2 Mon Sep 17 00:00:00 2001 From: Kees Bos Date: Mon, 15 Jun 2015 10:29:12 +0200 Subject: [PATCH 21/37] Fix 404 on creation of new network --- controller/SqliteNetworkController.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/controller/SqliteNetworkController.cpp b/controller/SqliteNetworkController.cpp index 9f91564a3..50927722c 100644 --- a/controller/SqliteNetworkController.cpp +++ b/controller/SqliteNetworkController.cpp @@ -747,6 +747,7 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST( } // else 404 } else { + std::vector path_copy(path); if (!networkExists) { if (path[1].substr(10) == "______") { @@ -786,6 +787,7 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST( sqlite3_bind_int64(_sCreateNetwork,3,(long long)OSUtils::now()); if (sqlite3_step(_sCreateNetwork) != SQLITE_DONE) return 500; + path_copy[1].assign(nwids); } json_value *j = json_parse(body.c_str(),body.length()); @@ -1041,7 +1043,7 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST( sqlite3_bind_text(_sSetNetworkRevision,2,nwids,16,SQLITE_STATIC); sqlite3_step(_sSetNetworkRevision); - return _doCPGet(path,urlArgs,headers,body,responseBody,responseContentType); + return _doCPGet(path_copy,urlArgs,headers,body,responseBody,responseContentType); } } // else 404 From 87bb0086deadf3663c3e0ec1308e0d71a6473362 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 17 Jun 2015 12:46:12 -0700 Subject: [PATCH 22/37] Almost certain fix for GitHub issue #184 on -dev --- node/IncomingPacket.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 5c83f24f4..8f95b9bad 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -689,6 +689,7 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons outp.append((uint16_t)netconfStr.length()); outp.append(netconfStr.data(),(unsigned int)netconfStr.length()); outp.compress(); + outp.armor(peer->key(),true); if (outp.size() > ZT_PROTO_MAX_PACKET_LENGTH) { TRACE("NETWORK_CONFIG_REQUEST failed: internal error: netconf size %u is too large",(unsigned int)netconfStr.length()); } else { From 6fc150bddb871ef0b6f3ba6a84a7faf01d8a57a3 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 18 Jun 2015 08:01:28 -0700 Subject: [PATCH 23/37] Move js/ to ZeroTierIntegrations project. --- js/zt1-api-client/constrain-types.js | 58 ------- js/zt1-api-client/index.js | 231 --------------------------- js/zt1-api-client/package.json | 15 -- 3 files changed, 304 deletions(-) delete mode 100644 js/zt1-api-client/constrain-types.js delete mode 100644 js/zt1-api-client/index.js delete mode 100644 js/zt1-api-client/package.json diff --git a/js/zt1-api-client/constrain-types.js b/js/zt1-api-client/constrain-types.js deleted file mode 100644 index 5b1137d59..000000000 --- a/js/zt1-api-client/constrain-types.js +++ /dev/null @@ -1,58 +0,0 @@ -'use strict' - -function convertType(v,t) -{ - if (Array.isArray(t)) { - var r = v; - if (t.length !== 0) { - if (Array.isArray(v)) { - r = []; - for(var i=0;i Date: Thu, 18 Jun 2015 19:14:52 +0200 Subject: [PATCH 24/37] Fix for ipv4 assignment --- controller/SqliteNetworkController.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/SqliteNetworkController.cpp b/controller/SqliteNetworkController.cpp index 50927722c..398b6991f 100644 --- a/controller/SqliteNetworkController.cpp +++ b/controller/SqliteNetworkController.cpp @@ -519,7 +519,7 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co int ipNetmaskBits = sqlite3_column_int(_sGetIpAssignmentsForNode,1); if ((ip)&&(sqlite3_column_bytes(_sGetIpAssignmentsForNode,0) >= 4)&&(ipNetmaskBits > 0)&&(ipNetmaskBits <= 32)) { char tmp[32]; - Utils::snprintf(tmp,sizeof(tmp),"%d.%d.%d.%d/%d",(int)ip[0],(int)ip[1],(int)ip[2],(int)ip[3],ipNetmaskBits); + Utils::snprintf(tmp,sizeof(tmp),"%d.%d.%d.%d/%d",(int)ip[12+0],(int)ip[12+1],(int)ip[12+2],(int)ip[12+3],ipNetmaskBits); if (v4s.length()) v4s.push_back(','); v4s.append(tmp); From 0073d0f694f925d925db96d25e2a504abda99722 Mon Sep 17 00:00:00 2001 From: Moritz Warning Date: Fri, 19 Jun 2015 00:24:17 +0200 Subject: [PATCH 25/37] replace txQueue list by vector for faster memory access and less allocations --- node/Multicaster.cpp | 20 ++++++++++++-------- node/Multicaster.hpp | 2 +- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/node/Multicaster.cpp b/node/Multicaster.cpp index 7da2b14c3..40be24419 100644 --- a/node/Multicaster.cpp +++ b/node/Multicaster.cpp @@ -320,10 +320,12 @@ void Multicaster::clean(uint64_t now) { Mutex::Lock _l(_groups_m); for(std::map< std::pair,MulticastGroupStatus >::iterator mm(_groups.begin());mm!=_groups.end();) { - for(std::list::iterator tx(mm->second.txQueue.begin());tx!=mm->second.txQueue.end();) { - if ((tx->expired(now))||(tx->atLimit())) - mm->second.txQueue.erase(tx++); - else ++tx; + for(std::vector::iterator tx(mm->second.txQueue.begin());tx!=mm->second.txQueue.end();) { + if ((tx->expired(now))||(tx->atLimit())) { + // erase element (replace by last) + *tx = mm->second.txQueue.back(); + mm->second.txQueue.pop_back(); + } else ++tx; } unsigned long count = 0; @@ -371,14 +373,16 @@ void Multicaster::_add(uint64_t now,uint64_t nwid,const MulticastGroup &mg,Multi //TRACE("..MC %s joined multicast group %.16llx/%s via %s",member.toString().c_str(),nwid,mg.toString().c_str(),((learnedFrom) ? learnedFrom.toString().c_str() : "(direct)")); - for(std::list::iterator tx(gs.txQueue.begin());tx!=gs.txQueue.end();) { + for(std::vector::iterator tx(gs.txQueue.begin());tx!=gs.txQueue.end();) { if (tx->atLimit()) { gs.txQueue.erase(tx++); } else { tx->sendIfNew(RR,member); - if (tx->atLimit()) - gs.txQueue.erase(tx++); - else ++tx; + if (tx->atLimit()) { + // erase element (replace by last) + *tx = gs.txQueue.back(); + gs.txQueue.pop_back(); + } else ++tx; } } } diff --git a/node/Multicaster.hpp b/node/Multicaster.hpp index c6c93b1ff..281222b84 100644 --- a/node/Multicaster.hpp +++ b/node/Multicaster.hpp @@ -70,7 +70,7 @@ private: MulticastGroupStatus() : lastExplicitGather(0) {} uint64_t lastExplicitGather; - std::list txQueue; // pending outbound multicasts + std::vector txQueue; // pending outbound multicasts std::vector members; // members of this group }; From 07f84a99b4458b3ddf5c14b9ce9b7c1dc5e2763e Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 19 Jun 2015 09:52:45 -0700 Subject: [PATCH 26/37] Rebuild properly signed root topology after supernode -> rootserver name change. --- root-topology/ZT_DEFAULT_ROOT_TOPOLOGY.c | 184 ++++++++++---------- root-topology/ZT_DEFAULT_ROOT_TOPOLOGY.dict | 6 +- root-topology/rootservers/7e19876aba | 1 - root-topology/rootservers/8841408a2e | 1 - root-topology/rootservers/8acf059fe3 | 1 - root-topology/rootservers/9d219039f3 | 1 - 6 files changed, 91 insertions(+), 103 deletions(-) diff --git a/root-topology/ZT_DEFAULT_ROOT_TOPOLOGY.c b/root-topology/ZT_DEFAULT_ROOT_TOPOLOGY.c index 1de95c717..96835e058 100644 --- a/root-topology/ZT_DEFAULT_ROOT_TOPOLOGY.c +++ b/root-topology/ZT_DEFAULT_ROOT_TOPOLOGY.c @@ -1,98 +1,90 @@ static unsigned char ZT_DEFAULT_ROOT_TOPOLOGY[] = { - 0x73, 0x75, 0x70, 0x65, 0x72, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x3d, 0x37, 0x65, 0x31, 0x39, 0x38, - 0x37, 0x36, 0x61, 0x62, 0x61, 0x5c, 0x3d, 0x69, 0x64, 0x5c, 0x5c, 0x5c, 0x3d, 0x37, 0x65, 0x31, - 0x39, 0x38, 0x37, 0x36, 0x61, 0x62, 0x61, 0x3a, 0x30, 0x3a, 0x32, 0x61, 0x36, 0x65, 0x32, 0x62, - 0x32, 0x33, 0x31, 0x38, 0x39, 0x33, 0x30, 0x66, 0x36, 0x30, 0x65, 0x62, 0x30, 0x39, 0x37, 0x66, - 0x37, 0x30, 0x64, 0x30, 0x66, 0x34, 0x62, 0x30, 0x32, 0x38, 0x62, 0x32, 0x63, 0x64, 0x36, 0x64, - 0x33, 0x64, 0x30, 0x63, 0x36, 0x33, 0x63, 0x30, 0x31, 0x34, 0x62, 0x39, 0x30, 0x33, 0x39, 0x66, - 0x66, 0x33, 0x35, 0x33, 0x39, 0x30, 0x65, 0x34, 0x31, 0x31, 0x38, 0x31, 0x66, 0x32, 0x31, 0x36, - 0x66, 0x62, 0x32, 0x65, 0x36, 0x66, 0x61, 0x38, 0x64, 0x39, 0x35, 0x63, 0x31, 0x65, 0x65, 0x39, - 0x36, 0x36, 0x37, 0x31, 0x35, 0x36, 0x34, 0x31, 0x31, 0x39, 0x30, 0x35, 0x63, 0x33, 0x64, 0x63, - 0x63, 0x66, 0x65, 0x61, 0x37, 0x38, 0x64, 0x38, 0x63, 0x36, 0x64, 0x66, 0x61, 0x66, 0x62, 0x61, - 0x36, 0x38, 0x38, 0x31, 0x37, 0x30, 0x62, 0x33, 0x66, 0x61, 0x5c, 0x5c, 0x6e, 0x75, 0x64, 0x70, - 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x39, 0x38, 0x2e, 0x31, 0x39, 0x39, 0x2e, 0x39, 0x37, 0x2e, 0x32, - 0x32, 0x30, 0x2f, 0x39, 0x39, 0x39, 0x33, 0x5c, 0x5c, 0x6e, 0x74, 0x63, 0x70, 0x5c, 0x5c, 0x5c, - 0x3d, 0x31, 0x39, 0x38, 0x2e, 0x31, 0x39, 0x39, 0x2e, 0x39, 0x37, 0x2e, 0x32, 0x32, 0x30, 0x2f, - 0x34, 0x34, 0x33, 0x5c, 0x5c, 0x6e, 0x64, 0x65, 0x73, 0x63, 0x5c, 0x5c, 0x5c, 0x3d, 0x53, 0x61, - 0x6e, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x69, 0x73, 0x63, 0x6f, 0x2c, 0x20, 0x43, 0x61, 0x6c, - 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x2c, 0x20, 0x55, 0x53, 0x41, 0x5c, 0x5c, 0x6e, 0x64, - 0x6e, 0x73, 0x5c, 0x5c, 0x5c, 0x3d, 0x6e, 0x79, 0x61, 0x72, 0x6c, 0x61, 0x74, 0x68, 0x6f, 0x74, - 0x65, 0x70, 0x2e, 0x7a, 0x65, 0x72, 0x6f, 0x74, 0x69, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x5c, - 0x5c, 0x6e, 0x5c, 0x6e, 0x38, 0x38, 0x34, 0x31, 0x34, 0x30, 0x38, 0x61, 0x32, 0x65, 0x5c, 0x3d, - 0x69, 0x64, 0x5c, 0x5c, 0x5c, 0x3d, 0x38, 0x38, 0x34, 0x31, 0x34, 0x30, 0x38, 0x61, 0x32, 0x65, - 0x3a, 0x30, 0x3a, 0x62, 0x62, 0x31, 0x64, 0x33, 0x31, 0x66, 0x32, 0x63, 0x33, 0x32, 0x33, 0x65, - 0x32, 0x36, 0x34, 0x65, 0x39, 0x65, 0x36, 0x34, 0x31, 0x37, 0x32, 0x63, 0x31, 0x61, 0x37, 0x34, - 0x66, 0x37, 0x37, 0x38, 0x39, 0x39, 0x35, 0x35, 0x35, 0x65, 0x64, 0x31, 0x30, 0x37, 0x35, 0x31, - 0x63, 0x64, 0x35, 0x36, 0x65, 0x38, 0x36, 0x34, 0x30, 0x35, 0x63, 0x64, 0x65, 0x31, 0x31, 0x38, - 0x64, 0x30, 0x32, 0x64, 0x66, 0x66, 0x65, 0x35, 0x35, 0x35, 0x64, 0x34, 0x36, 0x32, 0x63, 0x63, - 0x66, 0x36, 0x61, 0x38, 0x35, 0x62, 0x35, 0x36, 0x33, 0x31, 0x63, 0x31, 0x32, 0x33, 0x35, 0x30, - 0x63, 0x38, 0x64, 0x35, 0x64, 0x63, 0x34, 0x30, 0x39, 0x62, 0x61, 0x31, 0x30, 0x62, 0x39, 0x30, - 0x32, 0x35, 0x64, 0x30, 0x66, 0x34, 0x34, 0x35, 0x63, 0x66, 0x34, 0x34, 0x39, 0x64, 0x39, 0x32, - 0x62, 0x31, 0x63, 0x5c, 0x5c, 0x6e, 0x75, 0x64, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x30, 0x37, - 0x2e, 0x31, 0x39, 0x31, 0x2e, 0x34, 0x36, 0x2e, 0x32, 0x31, 0x30, 0x2f, 0x39, 0x39, 0x39, 0x33, - 0x5c, 0x5c, 0x6e, 0x74, 0x63, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x30, 0x37, 0x2e, 0x31, 0x39, - 0x31, 0x2e, 0x34, 0x36, 0x2e, 0x32, 0x31, 0x30, 0x2f, 0x34, 0x34, 0x33, 0x5c, 0x5c, 0x6e, 0x64, - 0x65, 0x73, 0x63, 0x5c, 0x5c, 0x5c, 0x3d, 0x50, 0x61, 0x72, 0x69, 0x73, 0x2c, 0x20, 0x46, 0x72, - 0x61, 0x6e, 0x63, 0x65, 0x5c, 0x5c, 0x6e, 0x64, 0x6e, 0x73, 0x5c, 0x5c, 0x5c, 0x3d, 0x73, 0x68, - 0x6f, 0x67, 0x67, 0x6f, 0x74, 0x68, 0x2e, 0x7a, 0x65, 0x72, 0x6f, 0x74, 0x69, 0x65, 0x72, 0x2e, - 0x63, 0x6f, 0x6d, 0x5c, 0x5c, 0x6e, 0x5c, 0x6e, 0x38, 0x61, 0x63, 0x66, 0x30, 0x35, 0x39, 0x66, - 0x65, 0x33, 0x5c, 0x3d, 0x69, 0x64, 0x5c, 0x5c, 0x5c, 0x3d, 0x38, 0x61, 0x63, 0x66, 0x30, 0x35, - 0x39, 0x66, 0x65, 0x33, 0x3a, 0x30, 0x3a, 0x34, 0x38, 0x32, 0x66, 0x36, 0x65, 0x65, 0x35, 0x64, - 0x66, 0x65, 0x39, 0x30, 0x32, 0x33, 0x31, 0x39, 0x62, 0x34, 0x31, 0x39, 0x64, 0x65, 0x35, 0x62, - 0x64, 0x63, 0x37, 0x36, 0x35, 0x32, 0x30, 0x39, 0x63, 0x30, 0x65, 0x63, 0x64, 0x61, 0x33, 0x38, - 0x63, 0x34, 0x64, 0x36, 0x65, 0x34, 0x66, 0x63, 0x66, 0x30, 0x64, 0x33, 0x33, 0x36, 0x35, 0x38, - 0x33, 0x39, 0x38, 0x62, 0x34, 0x35, 0x32, 0x37, 0x64, 0x63, 0x64, 0x32, 0x32, 0x66, 0x39, 0x33, - 0x31, 0x31, 0x32, 0x66, 0x62, 0x39, 0x62, 0x65, 0x66, 0x64, 0x30, 0x32, 0x66, 0x64, 0x37, 0x38, - 0x62, 0x66, 0x37, 0x32, 0x36, 0x31, 0x62, 0x33, 0x33, 0x33, 0x66, 0x63, 0x31, 0x30, 0x35, 0x64, - 0x31, 0x39, 0x32, 0x61, 0x36, 0x32, 0x33, 0x63, 0x61, 0x39, 0x65, 0x35, 0x30, 0x66, 0x63, 0x36, - 0x30, 0x62, 0x33, 0x37, 0x34, 0x61, 0x35, 0x5c, 0x5c, 0x6e, 0x75, 0x64, 0x70, 0x5c, 0x5c, 0x5c, - 0x3d, 0x31, 0x36, 0x32, 0x2e, 0x32, 0x34, 0x33, 0x2e, 0x37, 0x37, 0x2e, 0x31, 0x31, 0x31, 0x2f, - 0x39, 0x39, 0x39, 0x33, 0x5c, 0x5c, 0x6e, 0x74, 0x63, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x36, - 0x32, 0x2e, 0x32, 0x34, 0x33, 0x2e, 0x37, 0x37, 0x2e, 0x31, 0x31, 0x31, 0x2f, 0x34, 0x34, 0x33, - 0x5c, 0x5c, 0x6e, 0x64, 0x65, 0x73, 0x63, 0x5c, 0x5c, 0x5c, 0x3d, 0x4e, 0x65, 0x77, 0x20, 0x59, - 0x6f, 0x72, 0x6b, 0x2c, 0x20, 0x4e, 0x65, 0x77, 0x20, 0x59, 0x6f, 0x72, 0x6b, 0x2c, 0x20, 0x55, - 0x53, 0x41, 0x5c, 0x5c, 0x6e, 0x64, 0x6e, 0x73, 0x5c, 0x5c, 0x5c, 0x3d, 0x63, 0x74, 0x68, 0x75, - 0x6c, 0x68, 0x75, 0x2e, 0x7a, 0x65, 0x72, 0x6f, 0x74, 0x69, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, - 0x5c, 0x5c, 0x6e, 0x5c, 0x6e, 0x39, 0x64, 0x32, 0x31, 0x39, 0x30, 0x33, 0x39, 0x66, 0x33, 0x5c, - 0x3d, 0x69, 0x64, 0x5c, 0x5c, 0x5c, 0x3d, 0x39, 0x64, 0x32, 0x31, 0x39, 0x30, 0x33, 0x39, 0x66, - 0x33, 0x3a, 0x30, 0x3a, 0x30, 0x31, 0x66, 0x30, 0x39, 0x32, 0x32, 0x61, 0x39, 0x38, 0x65, 0x33, - 0x62, 0x33, 0x34, 0x65, 0x62, 0x63, 0x62, 0x66, 0x66, 0x33, 0x33, 0x33, 0x32, 0x36, 0x39, 0x64, - 0x63, 0x32, 0x36, 0x35, 0x64, 0x37, 0x61, 0x30, 0x32, 0x30, 0x61, 0x61, 0x62, 0x36, 0x39, 0x64, - 0x37, 0x32, 0x62, 0x65, 0x34, 0x64, 0x34, 0x61, 0x63, 0x63, 0x39, 0x63, 0x38, 0x63, 0x39, 0x32, - 0x39, 0x34, 0x37, 0x38, 0x35, 0x37, 0x37, 0x31, 0x32, 0x35, 0x36, 0x63, 0x64, 0x31, 0x64, 0x39, - 0x34, 0x32, 0x61, 0x39, 0x30, 0x64, 0x31, 0x62, 0x64, 0x31, 0x64, 0x32, 0x64, 0x63, 0x61, 0x33, - 0x65, 0x61, 0x38, 0x34, 0x65, 0x66, 0x37, 0x64, 0x38, 0x35, 0x61, 0x66, 0x65, 0x36, 0x36, 0x31, - 0x31, 0x66, 0x62, 0x34, 0x33, 0x66, 0x66, 0x30, 0x62, 0x37, 0x34, 0x31, 0x32, 0x36, 0x64, 0x39, - 0x30, 0x61, 0x36, 0x65, 0x5c, 0x5c, 0x6e, 0x75, 0x64, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x32, - 0x38, 0x2e, 0x31, 0x39, 0x39, 0x2e, 0x31, 0x39, 0x37, 0x2e, 0x32, 0x31, 0x37, 0x2f, 0x39, 0x39, - 0x39, 0x33, 0x5c, 0x5c, 0x6e, 0x74, 0x63, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x32, 0x38, 0x2e, - 0x31, 0x39, 0x39, 0x2e, 0x31, 0x39, 0x37, 0x2e, 0x32, 0x31, 0x37, 0x2f, 0x34, 0x34, 0x33, 0x5c, - 0x5c, 0x6e, 0x64, 0x65, 0x73, 0x63, 0x5c, 0x5c, 0x5c, 0x3d, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, - 0x6f, 0x72, 0x65, 0x5c, 0x5c, 0x6e, 0x64, 0x6e, 0x73, 0x5c, 0x5c, 0x5c, 0x3d, 0x6d, 0x69, 0x2d, - 0x67, 0x6f, 0x2e, 0x7a, 0x65, 0x72, 0x6f, 0x74, 0x69, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x5c, - 0x5c, 0x6e, 0x5c, 0x6e, 0x0a, 0x7e, 0x21, 0x65, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x3d, 0x62, - 0x37, 0x34, 0x39, 0x33, 0x66, 0x35, 0x61, 0x34, 0x62, 0x37, 0x39, 0x61, 0x31, 0x64, 0x63, 0x63, - 0x34, 0x32, 0x33, 0x66, 0x64, 0x32, 0x35, 0x64, 0x32, 0x64, 0x38, 0x61, 0x61, 0x38, 0x64, 0x36, - 0x32, 0x39, 0x33, 0x63, 0x34, 0x39, 0x30, 0x61, 0x31, 0x32, 0x63, 0x65, 0x62, 0x36, 0x33, 0x39, - 0x35, 0x34, 0x31, 0x37, 0x64, 0x64, 0x35, 0x38, 0x36, 0x38, 0x63, 0x31, 0x37, 0x62, 0x66, 0x62, - 0x63, 0x65, 0x65, 0x36, 0x38, 0x35, 0x64, 0x65, 0x35, 0x38, 0x30, 0x31, 0x39, 0x64, 0x32, 0x31, - 0x66, 0x39, 0x32, 0x35, 0x37, 0x36, 0x61, 0x37, 0x38, 0x61, 0x34, 0x35, 0x32, 0x33, 0x35, 0x64, - 0x33, 0x34, 0x32, 0x65, 0x66, 0x61, 0x32, 0x61, 0x30, 0x30, 0x61, 0x35, 0x34, 0x34, 0x64, 0x65, - 0x64, 0x33, 0x34, 0x37, 0x36, 0x36, 0x64, 0x64, 0x33, 0x32, 0x64, 0x36, 0x66, 0x30, 0x65, 0x31, - 0x31, 0x38, 0x30, 0x39, 0x31, 0x39, 0x37, 0x66, 0x39, 0x62, 0x61, 0x65, 0x65, 0x64, 0x66, 0x34, - 0x63, 0x36, 0x61, 0x30, 0x65, 0x38, 0x64, 0x32, 0x64, 0x36, 0x35, 0x37, 0x64, 0x32, 0x38, 0x30, - 0x61, 0x35, 0x37, 0x39, 0x66, 0x32, 0x66, 0x32, 0x34, 0x37, 0x38, 0x62, 0x32, 0x66, 0x37, 0x63, - 0x37, 0x61, 0x30, 0x38, 0x30, 0x38, 0x39, 0x61, 0x35, 0x30, 0x31, 0x36, 0x62, 0x35, 0x35, 0x0a, - 0x7e, 0x21, 0x73, 0x69, 0x67, 0x69, 0x64, 0x3d, 0x37, 0x37, 0x37, 0x39, 0x32, 0x62, 0x31, 0x63, - 0x30, 0x32, 0x3a, 0x30, 0x3a, 0x62, 0x35, 0x63, 0x33, 0x36, 0x31, 0x65, 0x38, 0x65, 0x39, 0x63, - 0x32, 0x31, 0x35, 0x34, 0x65, 0x38, 0x32, 0x63, 0x33, 0x65, 0x39, 0x30, 0x32, 0x66, 0x64, 0x66, - 0x63, 0x33, 0x33, 0x37, 0x34, 0x36, 0x38, 0x62, 0x30, 0x39, 0x32, 0x61, 0x37, 0x63, 0x34, 0x64, - 0x38, 0x64, 0x63, 0x36, 0x38, 0x35, 0x63, 0x33, 0x37, 0x65, 0x62, 0x31, 0x30, 0x65, 0x65, 0x34, - 0x66, 0x33, 0x63, 0x31, 0x37, 0x63, 0x63, 0x30, 0x62, 0x62, 0x31, 0x64, 0x30, 0x32, 0x34, 0x31, - 0x36, 0x37, 0x65, 0x38, 0x63, 0x62, 0x30, 0x38, 0x32, 0x34, 0x64, 0x31, 0x32, 0x32, 0x36, 0x33, - 0x34, 0x32, 0x38, 0x33, 0x37, 0x33, 0x35, 0x38, 0x32, 0x64, 0x61, 0x33, 0x64, 0x30, 0x61, 0x39, - 0x61, 0x31, 0x34, 0x62, 0x33, 0x36, 0x65, 0x34, 0x35, 0x34, 0x36, 0x63, 0x33, 0x31, 0x37, 0x65, - 0x38, 0x31, 0x31, 0x65, 0x36, 0x0a, 0x7e, 0x21, 0x73, 0x69, 0x67, 0x74, 0x73, 0x3d, 0x31, 0x34, - 0x61, 0x65, 0x34, 0x32, 0x64, 0x30, 0x33, 0x31, 0x34, 0x0a + 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x3d, 0x37, 0x65, 0x31, 0x39, + 0x38, 0x37, 0x36, 0x61, 0x62, 0x61, 0x5c, 0x3d, 0x69, 0x64, 0x5c, 0x5c, 0x5c, 0x3d, 0x37, 0x65, + 0x31, 0x39, 0x38, 0x37, 0x36, 0x61, 0x62, 0x61, 0x3a, 0x30, 0x3a, 0x32, 0x61, 0x36, 0x65, 0x32, + 0x62, 0x32, 0x33, 0x31, 0x38, 0x39, 0x33, 0x30, 0x66, 0x36, 0x30, 0x65, 0x62, 0x30, 0x39, 0x37, + 0x66, 0x37, 0x30, 0x64, 0x30, 0x66, 0x34, 0x62, 0x30, 0x32, 0x38, 0x62, 0x32, 0x63, 0x64, 0x36, + 0x64, 0x33, 0x64, 0x30, 0x63, 0x36, 0x33, 0x63, 0x30, 0x31, 0x34, 0x62, 0x39, 0x30, 0x33, 0x39, + 0x66, 0x66, 0x33, 0x35, 0x33, 0x39, 0x30, 0x65, 0x34, 0x31, 0x31, 0x38, 0x31, 0x66, 0x32, 0x31, + 0x36, 0x66, 0x62, 0x32, 0x65, 0x36, 0x66, 0x61, 0x38, 0x64, 0x39, 0x35, 0x63, 0x31, 0x65, 0x65, + 0x39, 0x36, 0x36, 0x37, 0x31, 0x35, 0x36, 0x34, 0x31, 0x31, 0x39, 0x30, 0x35, 0x63, 0x33, 0x64, + 0x63, 0x63, 0x66, 0x65, 0x61, 0x37, 0x38, 0x64, 0x38, 0x63, 0x36, 0x64, 0x66, 0x61, 0x66, 0x62, + 0x61, 0x36, 0x38, 0x38, 0x31, 0x37, 0x30, 0x62, 0x33, 0x66, 0x61, 0x5c, 0x5c, 0x6e, 0x75, 0x64, + 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x39, 0x38, 0x2e, 0x31, 0x39, 0x39, 0x2e, 0x39, 0x37, 0x2e, + 0x32, 0x32, 0x30, 0x2f, 0x39, 0x39, 0x39, 0x33, 0x5c, 0x5c, 0x6e, 0x74, 0x63, 0x70, 0x5c, 0x5c, + 0x5c, 0x3d, 0x31, 0x39, 0x38, 0x2e, 0x31, 0x39, 0x39, 0x2e, 0x39, 0x37, 0x2e, 0x32, 0x32, 0x30, + 0x2f, 0x34, 0x34, 0x33, 0x5c, 0x5c, 0x6e, 0x64, 0x65, 0x73, 0x63, 0x5c, 0x5c, 0x5c, 0x3d, 0x53, + 0x61, 0x6e, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x69, 0x73, 0x63, 0x6f, 0x2c, 0x20, 0x43, 0x61, + 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x2c, 0x20, 0x55, 0x53, 0x41, 0x5c, 0x5c, 0x6e, + 0x5c, 0x6e, 0x38, 0x38, 0x34, 0x31, 0x34, 0x30, 0x38, 0x61, 0x32, 0x65, 0x5c, 0x3d, 0x69, 0x64, + 0x5c, 0x5c, 0x5c, 0x3d, 0x38, 0x38, 0x34, 0x31, 0x34, 0x30, 0x38, 0x61, 0x32, 0x65, 0x3a, 0x30, + 0x3a, 0x62, 0x62, 0x31, 0x64, 0x33, 0x31, 0x66, 0x32, 0x63, 0x33, 0x32, 0x33, 0x65, 0x32, 0x36, + 0x34, 0x65, 0x39, 0x65, 0x36, 0x34, 0x31, 0x37, 0x32, 0x63, 0x31, 0x61, 0x37, 0x34, 0x66, 0x37, + 0x37, 0x38, 0x39, 0x39, 0x35, 0x35, 0x35, 0x65, 0x64, 0x31, 0x30, 0x37, 0x35, 0x31, 0x63, 0x64, + 0x35, 0x36, 0x65, 0x38, 0x36, 0x34, 0x30, 0x35, 0x63, 0x64, 0x65, 0x31, 0x31, 0x38, 0x64, 0x30, + 0x32, 0x64, 0x66, 0x66, 0x65, 0x35, 0x35, 0x35, 0x64, 0x34, 0x36, 0x32, 0x63, 0x63, 0x66, 0x36, + 0x61, 0x38, 0x35, 0x62, 0x35, 0x36, 0x33, 0x31, 0x63, 0x31, 0x32, 0x33, 0x35, 0x30, 0x63, 0x38, + 0x64, 0x35, 0x64, 0x63, 0x34, 0x30, 0x39, 0x62, 0x61, 0x31, 0x30, 0x62, 0x39, 0x30, 0x32, 0x35, + 0x64, 0x30, 0x66, 0x34, 0x34, 0x35, 0x63, 0x66, 0x34, 0x34, 0x39, 0x64, 0x39, 0x32, 0x62, 0x31, + 0x63, 0x5c, 0x5c, 0x6e, 0x75, 0x64, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x30, 0x37, 0x2e, 0x31, + 0x39, 0x31, 0x2e, 0x34, 0x36, 0x2e, 0x32, 0x31, 0x30, 0x2f, 0x39, 0x39, 0x39, 0x33, 0x5c, 0x5c, + 0x6e, 0x74, 0x63, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x30, 0x37, 0x2e, 0x31, 0x39, 0x31, 0x2e, + 0x34, 0x36, 0x2e, 0x32, 0x31, 0x30, 0x2f, 0x34, 0x34, 0x33, 0x5c, 0x5c, 0x6e, 0x64, 0x65, 0x73, + 0x63, 0x5c, 0x5c, 0x5c, 0x3d, 0x50, 0x61, 0x72, 0x69, 0x73, 0x2c, 0x20, 0x46, 0x72, 0x61, 0x6e, + 0x63, 0x65, 0x5c, 0x5c, 0x6e, 0x5c, 0x6e, 0x38, 0x61, 0x63, 0x66, 0x30, 0x35, 0x39, 0x66, 0x65, + 0x33, 0x5c, 0x3d, 0x69, 0x64, 0x5c, 0x5c, 0x5c, 0x3d, 0x38, 0x61, 0x63, 0x66, 0x30, 0x35, 0x39, + 0x66, 0x65, 0x33, 0x3a, 0x30, 0x3a, 0x34, 0x38, 0x32, 0x66, 0x36, 0x65, 0x65, 0x35, 0x64, 0x66, + 0x65, 0x39, 0x30, 0x32, 0x33, 0x31, 0x39, 0x62, 0x34, 0x31, 0x39, 0x64, 0x65, 0x35, 0x62, 0x64, + 0x63, 0x37, 0x36, 0x35, 0x32, 0x30, 0x39, 0x63, 0x30, 0x65, 0x63, 0x64, 0x61, 0x33, 0x38, 0x63, + 0x34, 0x64, 0x36, 0x65, 0x34, 0x66, 0x63, 0x66, 0x30, 0x64, 0x33, 0x33, 0x36, 0x35, 0x38, 0x33, + 0x39, 0x38, 0x62, 0x34, 0x35, 0x32, 0x37, 0x64, 0x63, 0x64, 0x32, 0x32, 0x66, 0x39, 0x33, 0x31, + 0x31, 0x32, 0x66, 0x62, 0x39, 0x62, 0x65, 0x66, 0x64, 0x30, 0x32, 0x66, 0x64, 0x37, 0x38, 0x62, + 0x66, 0x37, 0x32, 0x36, 0x31, 0x62, 0x33, 0x33, 0x33, 0x66, 0x63, 0x31, 0x30, 0x35, 0x64, 0x31, + 0x39, 0x32, 0x61, 0x36, 0x32, 0x33, 0x63, 0x61, 0x39, 0x65, 0x35, 0x30, 0x66, 0x63, 0x36, 0x30, + 0x62, 0x33, 0x37, 0x34, 0x61, 0x35, 0x5c, 0x5c, 0x6e, 0x75, 0x64, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, + 0x31, 0x36, 0x32, 0x2e, 0x32, 0x34, 0x33, 0x2e, 0x37, 0x37, 0x2e, 0x31, 0x31, 0x31, 0x2f, 0x39, + 0x39, 0x39, 0x33, 0x5c, 0x5c, 0x6e, 0x74, 0x63, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x36, 0x32, + 0x2e, 0x32, 0x34, 0x33, 0x2e, 0x37, 0x37, 0x2e, 0x31, 0x31, 0x31, 0x2f, 0x34, 0x34, 0x33, 0x5c, + 0x5c, 0x6e, 0x64, 0x65, 0x73, 0x63, 0x5c, 0x5c, 0x5c, 0x3d, 0x4e, 0x65, 0x77, 0x20, 0x59, 0x6f, + 0x72, 0x6b, 0x2c, 0x20, 0x4e, 0x65, 0x77, 0x20, 0x59, 0x6f, 0x72, 0x6b, 0x2c, 0x20, 0x55, 0x53, + 0x41, 0x5c, 0x5c, 0x6e, 0x5c, 0x6e, 0x39, 0x64, 0x32, 0x31, 0x39, 0x30, 0x33, 0x39, 0x66, 0x33, + 0x5c, 0x3d, 0x69, 0x64, 0x5c, 0x5c, 0x5c, 0x3d, 0x39, 0x64, 0x32, 0x31, 0x39, 0x30, 0x33, 0x39, + 0x66, 0x33, 0x3a, 0x30, 0x3a, 0x30, 0x31, 0x66, 0x30, 0x39, 0x32, 0x32, 0x61, 0x39, 0x38, 0x65, + 0x33, 0x62, 0x33, 0x34, 0x65, 0x62, 0x63, 0x62, 0x66, 0x66, 0x33, 0x33, 0x33, 0x32, 0x36, 0x39, + 0x64, 0x63, 0x32, 0x36, 0x35, 0x64, 0x37, 0x61, 0x30, 0x32, 0x30, 0x61, 0x61, 0x62, 0x36, 0x39, + 0x64, 0x37, 0x32, 0x62, 0x65, 0x34, 0x64, 0x34, 0x61, 0x63, 0x63, 0x39, 0x63, 0x38, 0x63, 0x39, + 0x32, 0x39, 0x34, 0x37, 0x38, 0x35, 0x37, 0x37, 0x31, 0x32, 0x35, 0x36, 0x63, 0x64, 0x31, 0x64, + 0x39, 0x34, 0x32, 0x61, 0x39, 0x30, 0x64, 0x31, 0x62, 0x64, 0x31, 0x64, 0x32, 0x64, 0x63, 0x61, + 0x33, 0x65, 0x61, 0x38, 0x34, 0x65, 0x66, 0x37, 0x64, 0x38, 0x35, 0x61, 0x66, 0x65, 0x36, 0x36, + 0x31, 0x31, 0x66, 0x62, 0x34, 0x33, 0x66, 0x66, 0x30, 0x62, 0x37, 0x34, 0x31, 0x32, 0x36, 0x64, + 0x39, 0x30, 0x61, 0x36, 0x65, 0x5c, 0x5c, 0x6e, 0x75, 0x64, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, + 0x32, 0x38, 0x2e, 0x31, 0x39, 0x39, 0x2e, 0x31, 0x39, 0x37, 0x2e, 0x32, 0x31, 0x37, 0x2f, 0x39, + 0x39, 0x39, 0x33, 0x5c, 0x5c, 0x6e, 0x74, 0x63, 0x70, 0x5c, 0x5c, 0x5c, 0x3d, 0x31, 0x32, 0x38, + 0x2e, 0x31, 0x39, 0x39, 0x2e, 0x31, 0x39, 0x37, 0x2e, 0x32, 0x31, 0x37, 0x2f, 0x34, 0x34, 0x33, + 0x5c, 0x5c, 0x6e, 0x64, 0x65, 0x73, 0x63, 0x5c, 0x5c, 0x5c, 0x3d, 0x53, 0x69, 0x6e, 0x67, 0x61, + 0x70, 0x6f, 0x72, 0x65, 0x5c, 0x5c, 0x6e, 0x5c, 0x6e, 0x0a, 0x7e, 0x21, 0x65, 0x64, 0x32, 0x35, + 0x35, 0x31, 0x39, 0x3d, 0x38, 0x33, 0x32, 0x62, 0x33, 0x35, 0x64, 0x61, 0x64, 0x64, 0x37, 0x66, + 0x35, 0x36, 0x66, 0x66, 0x33, 0x38, 0x31, 0x66, 0x61, 0x37, 0x32, 0x31, 0x64, 0x65, 0x37, 0x64, + 0x35, 0x62, 0x65, 0x34, 0x63, 0x65, 0x62, 0x66, 0x63, 0x63, 0x63, 0x32, 0x30, 0x30, 0x32, 0x30, + 0x38, 0x33, 0x38, 0x30, 0x64, 0x33, 0x30, 0x38, 0x34, 0x66, 0x36, 0x34, 0x38, 0x65, 0x32, 0x63, + 0x31, 0x61, 0x35, 0x63, 0x66, 0x34, 0x33, 0x65, 0x35, 0x39, 0x66, 0x39, 0x32, 0x61, 0x36, 0x36, + 0x35, 0x64, 0x66, 0x34, 0x64, 0x62, 0x63, 0x62, 0x38, 0x33, 0x37, 0x38, 0x38, 0x66, 0x36, 0x62, + 0x64, 0x36, 0x37, 0x37, 0x66, 0x30, 0x32, 0x62, 0x32, 0x31, 0x30, 0x65, 0x35, 0x30, 0x63, 0x61, + 0x66, 0x65, 0x66, 0x64, 0x32, 0x65, 0x66, 0x31, 0x38, 0x39, 0x62, 0x62, 0x66, 0x34, 0x38, 0x31, + 0x62, 0x64, 0x30, 0x32, 0x63, 0x64, 0x63, 0x39, 0x38, 0x34, 0x35, 0x33, 0x38, 0x37, 0x64, 0x38, + 0x34, 0x39, 0x62, 0x63, 0x35, 0x36, 0x66, 0x39, 0x63, 0x37, 0x32, 0x35, 0x31, 0x65, 0x35, 0x64, + 0x30, 0x65, 0x61, 0x34, 0x34, 0x34, 0x66, 0x66, 0x63, 0x66, 0x38, 0x66, 0x37, 0x32, 0x32, 0x63, + 0x32, 0x66, 0x65, 0x62, 0x38, 0x39, 0x36, 0x30, 0x33, 0x61, 0x30, 0x65, 0x35, 0x62, 0x61, 0x32, + 0x39, 0x35, 0x66, 0x63, 0x0a, 0x7e, 0x21, 0x73, 0x69, 0x67, 0x69, 0x64, 0x3d, 0x37, 0x37, 0x37, + 0x39, 0x32, 0x62, 0x31, 0x63, 0x30, 0x32, 0x3a, 0x30, 0x3a, 0x62, 0x35, 0x63, 0x33, 0x36, 0x31, + 0x65, 0x38, 0x65, 0x39, 0x63, 0x32, 0x31, 0x35, 0x34, 0x65, 0x38, 0x32, 0x63, 0x33, 0x65, 0x39, + 0x30, 0x32, 0x66, 0x64, 0x66, 0x63, 0x33, 0x33, 0x37, 0x34, 0x36, 0x38, 0x62, 0x30, 0x39, 0x32, + 0x61, 0x37, 0x63, 0x34, 0x64, 0x38, 0x64, 0x63, 0x36, 0x38, 0x35, 0x63, 0x33, 0x37, 0x65, 0x62, + 0x31, 0x30, 0x65, 0x65, 0x34, 0x66, 0x33, 0x63, 0x31, 0x37, 0x63, 0x63, 0x30, 0x62, 0x62, 0x31, + 0x64, 0x30, 0x32, 0x34, 0x31, 0x36, 0x37, 0x65, 0x38, 0x63, 0x62, 0x30, 0x38, 0x32, 0x34, 0x64, + 0x31, 0x32, 0x32, 0x36, 0x33, 0x34, 0x32, 0x38, 0x33, 0x37, 0x33, 0x35, 0x38, 0x32, 0x64, 0x61, + 0x33, 0x64, 0x30, 0x61, 0x39, 0x61, 0x31, 0x34, 0x62, 0x33, 0x36, 0x65, 0x34, 0x35, 0x34, 0x36, + 0x63, 0x33, 0x31, 0x37, 0x65, 0x38, 0x31, 0x31, 0x65, 0x36, 0x0a, 0x7e, 0x21, 0x73, 0x69, 0x67, + 0x74, 0x73, 0x3d, 0x31, 0x34, 0x65, 0x30, 0x63, 0x62, 0x62, 0x39, 0x38, 0x64, 0x36, 0x0a }; -#define ZT_DEFAULT_ROOT_TOPOLOGY_LEN 1514 +#define ZT_DEFAULT_ROOT_TOPOLOGY_LEN 1391 diff --git a/root-topology/ZT_DEFAULT_ROOT_TOPOLOGY.dict b/root-topology/ZT_DEFAULT_ROOT_TOPOLOGY.dict index 94cac7d0d..58144758e 100644 --- a/root-topology/ZT_DEFAULT_ROOT_TOPOLOGY.dict +++ b/root-topology/ZT_DEFAULT_ROOT_TOPOLOGY.dict @@ -1,4 +1,4 @@ -rootservers=7e19876aba\=id\\\=7e19876aba:0:2a6e2b2318930f60eb097f70d0f4b028b2cd6d3d0c63c014b9039ff35390e41181f216fb2e6fa8d95c1ee9667156411905c3dccfea78d8c6dfafba688170b3fa\\nudp\\\=198.199.97.220/9993\\ntcp\\\=198.199.97.220/443\\ndesc\\\=San Francisco, California, USA\\ndns\\\=nyarlathotep.zerotier.com\\n\n8841408a2e\=id\\\=8841408a2e:0:bb1d31f2c323e264e9e64172c1a74f77899555ed10751cd56e86405cde118d02dffe555d462ccf6a85b5631c12350c8d5dc409ba10b9025d0f445cf449d92b1c\\nudp\\\=107.191.46.210/9993\\ntcp\\\=107.191.46.210/443\\ndesc\\\=Paris, France\\ndns\\\=shoggoth.zerotier.com\\n\n8acf059fe3\=id\\\=8acf059fe3:0:482f6ee5dfe902319b419de5bdc765209c0ecda38c4d6e4fcf0d33658398b4527dcd22f93112fb9befd02fd78bf7261b333fc105d192a623ca9e50fc60b374a5\\nudp\\\=162.243.77.111/9993\\ntcp\\\=162.243.77.111/443\\ndesc\\\=New York, New York, USA\\ndns\\\=cthulhu.zerotier.com\\n\n9d219039f3\=id\\\=9d219039f3:0:01f0922a98e3b34ebcbff333269dc265d7a020aab69d72be4d4acc9c8c9294785771256cd1d942a90d1bd1d2dca3ea84ef7d85afe6611fb43ff0b74126d90a6e\\nudp\\\=128.199.197.217/9993\\ntcp\\\=128.199.197.217/443\\ndesc\\\=Singapore\\ndns\\\=mi-go.zerotier.com\\n\n -~!ed25519=b7493f5a4b79a1dcc423fd25d2d8aa8d6293c490a12ceb6395417dd5868c17bfbcee685de58019d21f92576a78a45235d342efa2a00a544ded34766dd32d6f0e11809197f9baeedf4c6a0e8d2d657d280a579f2f2478b2f7c7a08089a5016b55 +rootservers=7e19876aba\=id\\\=7e19876aba:0:2a6e2b2318930f60eb097f70d0f4b028b2cd6d3d0c63c014b9039ff35390e41181f216fb2e6fa8d95c1ee9667156411905c3dccfea78d8c6dfafba688170b3fa\\nudp\\\=198.199.97.220/9993\\ntcp\\\=198.199.97.220/443\\ndesc\\\=San Francisco, California, USA\\n\n8841408a2e\=id\\\=8841408a2e:0:bb1d31f2c323e264e9e64172c1a74f77899555ed10751cd56e86405cde118d02dffe555d462ccf6a85b5631c12350c8d5dc409ba10b9025d0f445cf449d92b1c\\nudp\\\=107.191.46.210/9993\\ntcp\\\=107.191.46.210/443\\ndesc\\\=Paris, France\\n\n8acf059fe3\=id\\\=8acf059fe3:0:482f6ee5dfe902319b419de5bdc765209c0ecda38c4d6e4fcf0d33658398b4527dcd22f93112fb9befd02fd78bf7261b333fc105d192a623ca9e50fc60b374a5\\nudp\\\=162.243.77.111/9993\\ntcp\\\=162.243.77.111/443\\ndesc\\\=New York, New York, USA\\n\n9d219039f3\=id\\\=9d219039f3:0:01f0922a98e3b34ebcbff333269dc265d7a020aab69d72be4d4acc9c8c9294785771256cd1d942a90d1bd1d2dca3ea84ef7d85afe6611fb43ff0b74126d90a6e\\nudp\\\=128.199.197.217/9993\\ntcp\\\=128.199.197.217/443\\ndesc\\\=Singapore\\n\n +~!ed25519=832b35dadd7f56ff381fa721de7d5be4cebfccc200208380d3084f648e2c1a5cf43e59f92a665df4dbcb83788f6bd677f02b210e50cafefd2ef189bbf481bd02cdc9845387d849bc56f9c7251e5d0ea444ffcf8f722c2feb89603a0e5ba295fc ~!sigid=77792b1c02:0:b5c361e8e9c2154e82c3e902fdfc337468b092a7c4d8dc685c37eb10ee4f3c17cc0bb1d024167e8cb0824d12263428373582da3d0a9a14b36e4546c317e811e6 -~!sigts=14ae42d0314 +~!sigts=14e0cbb98d6 diff --git a/root-topology/rootservers/7e19876aba b/root-topology/rootservers/7e19876aba index 23c2ad247..6bd8dc429 100644 --- a/root-topology/rootservers/7e19876aba +++ b/root-topology/rootservers/7e19876aba @@ -2,4 +2,3 @@ id=7e19876aba:0:2a6e2b2318930f60eb097f70d0f4b028b2cd6d3d0c63c014b9039ff35390e411 udp=198.199.97.220/9993 tcp=198.199.97.220/443 desc=San Francisco, California, USA -dns=nyarlathotep.zerotier.com diff --git a/root-topology/rootservers/8841408a2e b/root-topology/rootservers/8841408a2e index 09258f4e0..3be3333e4 100644 --- a/root-topology/rootservers/8841408a2e +++ b/root-topology/rootservers/8841408a2e @@ -2,4 +2,3 @@ id=8841408a2e:0:bb1d31f2c323e264e9e64172c1a74f77899555ed10751cd56e86405cde118d02 udp=107.191.46.210/9993 tcp=107.191.46.210/443 desc=Paris, France -dns=shoggoth.zerotier.com diff --git a/root-topology/rootservers/8acf059fe3 b/root-topology/rootservers/8acf059fe3 index 438e67a32..4a569d95b 100644 --- a/root-topology/rootservers/8acf059fe3 +++ b/root-topology/rootservers/8acf059fe3 @@ -2,4 +2,3 @@ id=8acf059fe3:0:482f6ee5dfe902319b419de5bdc765209c0ecda38c4d6e4fcf0d33658398b452 udp=162.243.77.111/9993 tcp=162.243.77.111/443 desc=New York, New York, USA -dns=cthulhu.zerotier.com diff --git a/root-topology/rootservers/9d219039f3 b/root-topology/rootservers/9d219039f3 index 1602f35e4..ec9224336 100644 --- a/root-topology/rootservers/9d219039f3 +++ b/root-topology/rootservers/9d219039f3 @@ -2,4 +2,3 @@ id=9d219039f3:0:01f0922a98e3b34ebcbff333269dc265d7a020aab69d72be4d4acc9c8c929478 udp=128.199.197.217/9993 tcp=128.199.197.217/443 desc=Singapore -dns=mi-go.zerotier.com From 7bae95836c8824a76e0299df776a708eb3e58576 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 19 Jun 2015 10:23:25 -0700 Subject: [PATCH 27/37] Root server terminology cleanup, and tighten up a security check by checking full identity of peers instead of just address. --- include/ZeroTierOne.h | 4 +- node/Constants.hpp | 6 +-- node/IncomingPacket.cpp | 16 +++--- node/Multicaster.cpp | 47 +---------------- node/Network.cpp | 6 +-- node/Node.cpp | 14 +++-- node/Packet.hpp | 2 +- node/Peer.cpp | 6 +-- node/SelfAwareness.cpp | 2 +- node/Switch.cpp | 26 +++++----- node/Topology.cpp | 109 +++++++++++++++++++++------------------ node/Topology.hpp | 73 +++++++++++--------------- service/ControlPlane.cpp | 6 +-- 13 files changed, 131 insertions(+), 186 deletions(-) diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index b67d97edf..b6ff69abe 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -559,8 +559,8 @@ typedef struct */ enum ZT1_PeerRole { ZT1_PEER_ROLE_LEAF = 0, // ordinary node - ZT1_PEER_ROLE_HUB = 1, // locally federated hub - ZT1_PEER_ROLE_ROOTSERVER = 2 // planetary rootserver + ZT1_PEER_ROLE_RELAY = 1, // relay node + ZT1_PEER_ROLE_ROOT = 2 // root server }; /** diff --git a/node/Constants.hpp b/node/Constants.hpp index aced6fe72..ac9dbc99c 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -254,7 +254,7 @@ /** * Delay between scans of the topology active peer DB for peers that need ping * - * This is also how often pings will be retried to upstream peers (rootservers) + * This is also how often pings will be retried to upstream peers (relays, roots) * constantly until something is heard. */ #define ZT_PING_CHECK_INVERVAL 6250 @@ -279,9 +279,9 @@ * * When we send something (including frames), we generally expect a response. * Switching relays if no response in a short period of time causes more - * rapid failover if a rootserver goes down or becomes unreachable. In the + * rapid failover if a root server goes down or becomes unreachable. In the * mistaken case, little harm is done as it'll pick the next-fastest - * rootserver and will switch back eventually. + * root server and will switch back eventually. */ #define ZT_PEER_RELAY_CONVERSATION_LATENCY_THRESHOLD 10000 diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 8f95b9bad..7e2bcdaa8 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -110,7 +110,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr case Packet::ERROR_OBJ_NOT_FOUND: if (inReVerb == Packet::VERB_WHOIS) { - if (RR->topology->isRootserver(peer->address())) + if (RR->topology->isRoot(peer->identity())) RR->sw->cancelWhoisRequest(Address(field(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH)); } else if (inReVerb == Packet::VERB_NETWORK_CONFIG_REQUEST) { SharedPtr network(RR->node->network(at(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD))); @@ -128,7 +128,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr break; case Packet::ERROR_IDENTITY_COLLISION: - if (RR->topology->isRootserver(peer->address())) + if (RR->topology->isRoot(peer->identity())) RR->node->postEvent(ZT1_EVENT_FATAL_ERROR_IDENTITY_COLLISION); break; @@ -268,7 +268,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR) peer->setRemoteVersion(protoVersion,vMajor,vMinor,vRevision); bool trusted = false; - if (RR->topology->isRootserver(id.address())) { + if (RR->topology->isRoot(id)) { RR->node->postNewerVersionIfNewer(vMajor,vMinor,vRevision); trusted = true; } @@ -353,7 +353,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr &p peer->setRemoteVersion(vProto,vMajor,vMinor,vRevision); bool trusted = false; - if (RR->topology->isRootserver(peer->address())) { + if (RR->topology->isRoot(peer->identity())) { RR->node->postNewerVersionIfNewer(vMajor,vMinor,vRevision); trusted = true; } @@ -362,10 +362,10 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr &p } break; case Packet::VERB_WHOIS: { - // Right now only rootservers are allowed to send OK(WHOIS) to prevent - // poisoning attacks. Further decentralization will require some other - // kind of trust mechanism. - if (RR->topology->isRootserver(peer->address())) { + /* Right now only root servers are allowed to send OK(WHOIS) to prevent + * poisoning attacks. Further decentralization will require some other + * kind of trust mechanism. */ + if (RR->topology->isRoot(peer->identity())) { const Identity id(*this,ZT_PROTO_VERB_WHOIS__OK__IDX_IDENTITY); if (id.locallyValidate()) RR->sw->doAnythingWaitingForPeer(RR->topology->addPeer(SharedPtr(new Peer(RR->identity,id)))); diff --git a/node/Multicaster.cpp b/node/Multicaster.cpp index 360233fe9..29e89189b 100644 --- a/node/Multicaster.cpp +++ b/node/Multicaster.cpp @@ -216,7 +216,7 @@ void Multicaster::send( if ((now - gs.lastExplicitGather) >= ZT_MULTICAST_EXPLICIT_GATHER_DELAY) { gs.lastExplicitGather = now; - SharedPtr sn(RR->topology->getBestRootserver()); + SharedPtr sn(RR->topology->getBestRoot()); if (sn) { TRACE(">>MC upstream GATHER up to %u for group %.16llx/%s",gatherLimit,nwid,mg.toString().c_str()); @@ -269,51 +269,6 @@ void Multicaster::send( // Free allocated memory buffer if any if (indexes != idxbuf) delete [] indexes; - -#ifdef ZT_SUPPORT_LEGACY_MULTICAST - // This sends a P5 multicast up to our rootserver, who then - // redistributes it manually down to all <1.0.0 peers for - // legacy support. These peers don't support the new multicast - // frame type, so even if they receive it they will ignore it. - { - SharedPtr sn(RR->topology->getBestRootserver()); - if (sn) { - uint32_t rn = RR->prng->next32(); - Packet outp(sn->address(),RR->identity.address(),Packet::VERB_P5_MULTICAST_FRAME); - - outp.append((uint16_t)0xffff); // do not forward - outp.append((unsigned char)0,320 + 1024); // empty queue and bloom filter - - outp.append((unsigned char)((com) ? ZT_PROTO_VERB_P5_MULTICAST_FRAME_FLAGS_HAS_MEMBERSHIP_CERTIFICATE : 0)); - outp.append((uint64_t)nwid); - outp.append((uint16_t)0); - outp.append((unsigned char)0); - outp.append((unsigned char)0); - RR->identity.address().appendTo(outp); - outp.append((const void *)&rn,3); // random multicast ID - if (src) - src.appendTo(outp); - else MAC(RR->identity.address(),nwid).appendTo(outp); - mg.mac().appendTo(outp); - outp.append((uint32_t)mg.adi()); - outp.append((uint16_t)etherType); - outp.append((uint16_t)len); - outp.append(data,len); - unsigned int signedPortionLen = outp.size() - ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION; - - C25519::Signature sig(RR->identity.sign(outp.field(ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION,signedPortionLen),signedPortionLen)); - - outp.append((uint16_t)sig.size()); - outp.append(sig.data,(unsigned int)sig.size()); - - if (com) com->serialize(outp); - - outp.compress(); - outp.armor(sn->key(),true); - sn->send(RR,outp.data(),outp.size(),now); - } - } -#endif // ZT_SUPPORT_LEGACY_MULTICAST } void Multicaster::clean(uint64_t now) diff --git a/node/Network.cpp b/node/Network.cpp index 60262cd59..a217595af 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -518,13 +518,13 @@ public: RR(renv), _now(renv->node->now()), _network(nw), - _rootserverAddresses(renv->topology->rootserverAddresses()), + _rootAddresses(renv->topology->rootAddresses()), _allMulticastGroups(nw->_allMulticastGroups()) {} inline void operator()(Topology &t,const SharedPtr &p) { - if ( ( (p->hasActiveDirectPath(_now)) && (_network->_isAllowed(p->address())) ) || (std::find(_rootserverAddresses.begin(),_rootserverAddresses.end(),p->address()) != _rootserverAddresses.end()) ) { + if ( ( (p->hasActiveDirectPath(_now)) && (_network->_isAllowed(p->address())) ) || (std::find(_rootAddresses.begin(),_rootAddresses.end(),p->address()) != _rootAddresses.end()) ) { Packet outp(p->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); for(std::vector::iterator mg(_allMulticastGroups.begin());mg!=_allMulticastGroups.end();++mg) { @@ -551,7 +551,7 @@ private: const RuntimeEnvironment *RR; uint64_t _now; Network *_network; - std::vector
_rootserverAddresses; + std::vector
_rootAddresses; std::vector _allMulticastGroups; }; diff --git a/node/Node.cpp b/node/Node.cpp index 1f6d474ce..45e2463ca 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -133,9 +133,7 @@ Node::Node( if (!rt.size()) rt.fromString(ZT_DEFAULTS.defaultRootTopology); } - Dictionary rootservers(rt.get("rootservers","")); - rootservers.update(rt.get("supernodes","")); - RR->topology->setRootservers(rootservers); + RR->topology->setRootServers(Dictionary(rt.get("rootservers",""))); postEvent(ZT1_EVENT_UP); } @@ -191,7 +189,7 @@ public: RR(renv), _now(now), _relays(relays), - _rootservers(RR->topology->rootserverAddresses()) + _rootAddresses(RR->topology->rootAddresses()) { } @@ -207,7 +205,7 @@ public: } } - if ((isRelay)||(std::find(_rootservers.begin(),_rootservers.end(),p->address()) != _rootservers.end())) { + if ((isRelay)||(std::find(_rootAddresses.begin(),_rootAddresses.end(),p->address()) != _rootAddresses.end())) { p->doPingAndKeepalive(RR,_now); if (p->lastReceive() > lastReceiveFromUpstream) lastReceiveFromUpstream = p->lastReceive(); @@ -221,7 +219,7 @@ private: const RuntimeEnvironment *RR; uint64_t _now; const std::vector< std::pair > &_relays; - std::vector
_rootservers; + std::vector
_rootAddresses; }; ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline) @@ -262,7 +260,7 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *next } } - // Ping living or rootserver/relay peers + // Ping living or root server/relay peers _PingPeersThatNeedPing pfunc(RR,now,networkRelays); RR->topology->eachPeer<_PingPeersThatNeedPing &>(pfunc); @@ -386,7 +384,7 @@ ZT1_PeerList *Node::peers() const p->versionRev = -1; } p->latency = pi->second->latency(); - p->role = RR->topology->isRootserver(pi->second->address()) ? ZT1_PEER_ROLE_ROOTSERVER : ZT1_PEER_ROLE_LEAF; + p->role = RR->topology->isRoot(pi->second->identity()) ? ZT1_PEER_ROLE_ROOT : ZT1_PEER_ROLE_LEAF; std::vector paths(pi->second->paths()); Path *bestPath = pi->second->getBestPath(_now); diff --git a/node/Packet.hpp b/node/Packet.hpp index 21f8ca574..49201b712 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -626,7 +626,7 @@ public: * [... additional tuples of network/address/adi ...] * * LIKEs are sent to peers with whom you have a direct peer to peer - * connection, and always including rootservers. + * connection, and always including root servers. * * OK/ERROR are not generated. */ diff --git a/node/Peer.cpp b/node/Peer.cpp index 3093ef41d..96caa72cf 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -122,16 +122,16 @@ void Peer::received( /* Announce multicast groups of interest to direct peers if they are * considered authorized members of a given network. Also announce to - * rootservers and network controllers. */ + * root servers and network controllers. */ if ((pathIsConfirmed)&&((now - _lastAnnouncedTo) >= ((ZT_MULTICAST_LIKE_EXPIRE / 2) - 1000))) { _lastAnnouncedTo = now; - const bool isRootserver = RR->topology->isRootserver(_id.address()); + const bool isRoot = RR->topology->isRoot(_id); Packet outp(_id.address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); const std::vector< SharedPtr > networks(RR->node->allNetworks()); for(std::vector< SharedPtr >::const_iterator n(networks.begin());n!=networks.end();++n) { - if ( (isRootserver) || ((*n)->isAllowed(_id.address())) ) { + if ( (isRoot) || ((*n)->isAllowed(_id.address())) ) { const std::vector mgs((*n)->allMulticastGroups()); for(std::vector::const_iterator mg(mgs.begin());mg!=mgs.end();++mg) { if ((outp.size() + 18) > ZT_UDP_DEFAULT_PAYLOAD_MTU) { diff --git a/node/SelfAwareness.cpp b/node/SelfAwareness.cpp index 5fc8be2a6..9f7c41d7d 100644 --- a/node/SelfAwareness.cpp +++ b/node/SelfAwareness.cpp @@ -118,7 +118,7 @@ void SelfAwareness::iam(const Address &reporter,const InetAddress &reporterPhysi // For all peers for whom we forgot an address, send a packet indirectly if // they are still considered alive so that we will re-establish direct links. - SharedPtr sn(RR->topology->getBestRootserver()); + SharedPtr sn(RR->topology->getBestRoot()); if (sn) { Path *snp = sn->getBestPath(now); if (snp) { diff --git a/node/Switch.cpp b/node/Switch.cpp index 3ac0b9206..af80f5e81 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -320,8 +320,8 @@ bool Switch::unite(const Address &p1,const Address &p2,bool force) * P2 in randomized order in terms of which gets sent first. This is done * since in a few cases NAT-t can be sensitive to slight timing differences * in terms of when the two peers initiate. Normally this is accounted for - * by the nearly-simultaneous RENDEZVOUS kickoff from the rootserver, but - * given that rootservers are hosted on cloud providers this can in some + * by the nearly-simultaneous RENDEZVOUS kickoff from the relay, but + * given that relay are hosted on cloud providers this can in some * cases have a few ms of latency between packet departures. By randomizing * the order we make each attempted NAT-t favor one or the other going * first, meaning if it doesn't succeed the first time it might the second @@ -565,8 +565,8 @@ void Switch::_handleRemotePacketFragment(const InetAddress &fromAddr,const void // It wouldn't hurt anything, just redundant and unnecessary. SharedPtr relayTo = RR->topology->getPeer(destination); if ((!relayTo)||(!relayTo->send(RR,fragment.data(),fragment.size(),RR->node->now()))) { - // Don't know peer or no direct path -- so relay via rootserver - relayTo = RR->topology->getBestRootserver(); + // Don't know peer or no direct path -- so relay via root server + relayTo = RR->topology->getBestRoot(); if (relayTo) relayTo->send(RR,fragment.data(),fragment.size(),RR->node->now()); } @@ -641,8 +641,8 @@ void Switch::_handleRemotePacketHead(const InetAddress &fromAddr,const void *dat if ((relayTo)&&((relayTo->send(RR,packet->data(),packet->size(),RR->node->now())))) { unite(source,destination,false); } else { - // Don't know peer or no direct path -- so relay via rootserver - relayTo = RR->topology->getBestRootserver(&source,1,true); + // Don't know peer or no direct path -- so relay via root server + relayTo = RR->topology->getBestRoot(&source,1,true); if (relayTo) relayTo->send(RR,packet->data(),packet->size(),RR->node->now()); } @@ -712,13 +712,13 @@ void Switch::_handleBeacon(const InetAddress &fromAddr,const Buffer rootserver(RR->topology->getBestRootserver(peersAlreadyConsulted,numPeersAlreadyConsulted,false)); - if (rootserver) { - Packet outp(rootserver->address(),RR->identity.address(),Packet::VERB_WHOIS); + SharedPtr root(RR->topology->getBestRoot(peersAlreadyConsulted,numPeersAlreadyConsulted,false)); + if (root) { + Packet outp(root->address(),RR->identity.address(),Packet::VERB_WHOIS); addr.appendTo(outp); - outp.armor(rootserver->key(),true); - if (rootserver->send(RR,outp.data(),outp.size(),RR->node->now())) - return rootserver->address(); + outp.armor(root->key(),true); + if (root->send(RR,outp.data(),outp.size(),RR->node->now())) + return root->address(); } return Address(); } @@ -752,7 +752,7 @@ bool Switch::_trySend(const Packet &packet,bool encrypt,uint64_t nwid) } if (!relay) - relay = RR->topology->getBestRootserver(); + relay = RR->topology->getBestRoot(); if (!(relay)||(!(viaPath = relay->getBestPath(now)))) return false; diff --git a/node/Topology.cpp b/node/Topology.cpp index cfa6749cd..2b1cc31fe 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -36,7 +36,7 @@ namespace ZeroTier { Topology::Topology(const RuntimeEnvironment *renv) : RR(renv), - _amRootserver(false) + _amRoot(false) { } @@ -44,16 +44,16 @@ Topology::~Topology() { } -void Topology::setRootservers(const std::map< Identity,std::vector > &sn) +void Topology::setRootServers(const std::map< Identity,std::vector > &sn) { Mutex::Lock _l(_lock); - if (_rootservers == sn) + if (_roots == sn) return; // no change - _rootservers = sn; - _rootserverAddresses.clear(); - _rootserverPeers.clear(); + _roots = sn; + _rootAddresses.clear(); + _rootPeers.clear(); const uint64_t now = RR->node->now(); for(std::map< Identity,std::vector >::const_iterator i(sn.begin());i!=sn.end();++i) { @@ -64,17 +64,17 @@ void Topology::setRootservers(const std::map< Identity,std::vector for(std::vector::const_iterator j(i->second.begin());j!=i->second.end();++j) p->addPath(Path(*j,true)); p->use(now); - _rootserverPeers.push_back(p); + _rootPeers.push_back(p); } - _rootserverAddresses.push_back(i->first.address()); + _rootAddresses.push_back(i->first.address()); } - std::sort(_rootserverAddresses.begin(),_rootserverAddresses.end()); + std::sort(_rootAddresses.begin(),_rootAddresses.end()); - _amRootserver = (_rootservers.find(RR->identity) != _rootservers.end()); + _amRoot = (_roots.find(RR->identity) != _roots.end()); } -void Topology::setRootservers(const Dictionary &sn) +void Topology::setRootServers(const Dictionary &sn) { std::map< Identity,std::vector > m; for(Dictionary::const_iterator d(sn.begin());d!=sn.end();++d) { @@ -86,11 +86,11 @@ void Topology::setRootservers(const Dictionary &sn) if (udp.length() > 0) a.push_back(InetAddress(udp)); } catch ( ... ) { - TRACE("rootserver list contained invalid entry for: %s",d->first.c_str()); + TRACE("root server list contained invalid entry for: %s",d->first.c_str()); } } } - this->setRootservers(m); + this->setRootServers(m); } SharedPtr Topology::addPeer(const SharedPtr &peer) @@ -141,28 +141,28 @@ SharedPtr Topology::getPeer(const Address &zta) return SharedPtr(); } -SharedPtr Topology::getBestRootserver(const Address *avoid,unsigned int avoidCount,bool strictAvoid) +SharedPtr Topology::getBestRoot(const Address *avoid,unsigned int avoidCount,bool strictAvoid) { - SharedPtr bestRootserver; + SharedPtr bestRoot; const uint64_t now = RR->node->now(); Mutex::Lock _l(_lock); - if (_amRootserver) { - /* If I am a rootserver, the "best" rootserver is the one whose address + 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. */ - if (_rootserverAddresses.size() > 1) { // gotta be one other than me for this to work - std::vector
::const_iterator sna(std::find(_rootserverAddresses.begin(),_rootserverAddresses.end(),RR->identity.address())); - if (sna != _rootserverAddresses.end()) { // sanity check -- _amRootserver should've been false in this case + if (_rootAddresses.size() > 1) { // gotta be one other than me for this to work + std::vector
::const_iterator sna(std::find(_rootAddresses.begin(),_rootAddresses.end(),RR->identity.address())); + if (sna != _rootAddresses.end()) { // sanity check -- _amRoot should've been false in this case for(;;) { - if (++sna == _rootserverAddresses.end()) - sna = _rootserverAddresses.begin(); // wrap around at end + if (++sna == _rootAddresses.end()) + sna = _rootAddresses.begin(); // wrap around at end if (*sna != RR->identity.address()) { // pick one other than us -- starting from me+1 in sorted set order std::map< Address,SharedPtr >::const_iterator p(_activePeers.find(*sna)); if ((p != _activePeers.end())&&(p->second->hasActiveDirectPath(now))) { - bestRootserver = p->second; + bestRoot = p->second; break; } } @@ -170,80 +170,87 @@ SharedPtr Topology::getBestRootserver(const Address *avoid,unsigned int av } } } else { - /* If I am not a rootserver, the best rootserver is the active one with + /* If I am not a root server, the best root server is the active one with * the lowest latency. */ - unsigned int l,bestRootserverLatency = 65536; + unsigned int l,bestLatency = 65536; uint64_t lds,ldr; - // First look for a best rootserver by comparing latencies, but exclude - // rootservers that have not responded to direct messages in order to + // First look for a best root by comparing latencies, but exclude + // root servers that have not responded to direct messages in order to // try to exclude any that are dead or unreachable. - for(std::vector< SharedPtr >::const_iterator sn(_rootserverPeers.begin());sn!=_rootserverPeers.end();) { + for(std::vector< SharedPtr >::const_iterator sn(_rootPeers.begin());sn!=_rootPeers.end();) { // Skip explicitly avoided relays for(unsigned int i=0;iaddress()) - goto keep_searching_for_rootservers; + goto keep_searching_for_roots; } // Skip possibly comatose or unreachable relays lds = (*sn)->lastDirectSend(); ldr = (*sn)->lastDirectReceive(); if ((lds)&&(lds > ldr)&&((lds - ldr) > ZT_PEER_RELAY_CONVERSATION_LATENCY_THRESHOLD)) - goto keep_searching_for_rootservers; + goto keep_searching_for_roots; if ((*sn)->hasActiveDirectPath(now)) { l = (*sn)->latency(); - if (bestRootserver) { - if ((l)&&(l < bestRootserverLatency)) { - bestRootserverLatency = l; - bestRootserver = *sn; + if (bestRoot) { + if ((l)&&(l < bestLatency)) { + bestLatency = l; + bestRoot = *sn; } } else { if (l) - bestRootserverLatency = l; - bestRootserver = *sn; + bestLatency = l; + bestRoot = *sn; } } -keep_searching_for_rootservers: +keep_searching_for_roots: ++sn; } - if (bestRootserver) { - bestRootserver->use(now); - return bestRootserver; + if (bestRoot) { + bestRoot->use(now); + return bestRoot; } else if (strictAvoid) return SharedPtr(); // If we have nothing from above, just pick one without avoidance criteria. - for(std::vector< SharedPtr >::const_iterator sn=_rootserverPeers.begin();sn!=_rootserverPeers.end();++sn) { + for(std::vector< SharedPtr >::const_iterator sn=_rootPeers.begin();sn!=_rootPeers.end();++sn) { if ((*sn)->hasActiveDirectPath(now)) { unsigned int l = (*sn)->latency(); - if (bestRootserver) { - if ((l)&&(l < bestRootserverLatency)) { - bestRootserverLatency = l; - bestRootserver = *sn; + if (bestRoot) { + if ((l)&&(l < bestLatency)) { + bestLatency = l; + bestRoot = *sn; } } else { if (l) - bestRootserverLatency = l; - bestRootserver = *sn; + bestLatency = l; + bestRoot = *sn; } } } } - if (bestRootserver) - bestRootserver->use(now); - return bestRootserver; + if (bestRoot) + bestRoot->use(now); + return bestRoot; +} + +bool Topology::isRoot(const Identity &id) const + throw() +{ + Mutex::Lock _l(_lock); + return (_roots.count(id) != 0); } void Topology::clean(uint64_t now) { Mutex::Lock _l(_lock); for(std::map< Address,SharedPtr >::iterator p(_activePeers.begin());p!=_activePeers.end();) { - if (((now - p->second->lastUsed()) >= ZT_PEER_IN_MEMORY_EXPIRATION)&&(std::find(_rootserverAddresses.begin(),_rootserverAddresses.end(),p->first) == _rootserverAddresses.end())) { + if (((now - p->second->lastUsed()) >= ZT_PEER_IN_MEMORY_EXPIRATION)&&(std::find(_rootAddresses.begin(),_rootAddresses.end(),p->first) == _rootAddresses.end())) { _activePeers.erase(p++); } else ++p; } diff --git a/node/Topology.hpp b/node/Topology.hpp index 8aeae784e..c878bcc6e 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -59,21 +59,19 @@ public: ~Topology(); /** - * Set up rootservers for this network - * - * @param sn Rootservers for this network + * @param sn Root server identities and addresses */ - void setRootservers(const std::map< Identity,std::vector > &sn); + void setRootServers(const std::map< Identity,std::vector > &sn); /** - * Set up rootservers for this network + * Set up root servers for this network * * This performs no signature verification of any kind. The caller must * check the signature of the root topology dictionary first. * - * @param sn Rootservers dictionary from root-topology + * @param sn 'rootservers' key from root-topology Dictionary (deserialized as Dictionary) */ - void setRootservers(const Dictionary &sn); + void setRootServers(const Dictionary &sn); /** * Add a peer to database @@ -95,65 +93,52 @@ public: SharedPtr getPeer(const Address &zta); /** - * @return Vector of peers that are rootservers + * @return Vector of peers that are root servers */ - inline std::vector< SharedPtr > rootserverPeers() const + inline std::vector< SharedPtr > rootPeers() const { Mutex::Lock _l(_lock); - return _rootserverPeers; + return _rootPeers; } /** - * @return Number of rootservers - */ - inline unsigned int numRootservers() const - { - Mutex::Lock _l(_lock); - return (unsigned int)_rootserverPeers.size(); - } - - /** - * Get the current favorite rootserver + * Get the current favorite root server * - * @return Rootserver with lowest latency or NULL if none + * @return Root server with lowest latency or NULL if none */ - inline SharedPtr getBestRootserver() + inline SharedPtr getBestRoot() { - return getBestRootserver((const Address *)0,0,false); + return getBestRoot((const Address *)0,0,false); } /** - * Get the best rootserver, avoiding rootservers listed in an array + * Get the best root server, avoiding root servers listed in an array * - * This will get the best rootserver (lowest latency, etc.) but will - * try to avoid the listed rootservers, only using them if no others + * This will get the best root server (lowest latency, etc.) but will + * try to avoid the listed root servers, only using them if no others * are available. * * @param avoid Nodes to avoid * @param avoidCount Number of nodes to avoid - * @param strictAvoid If false, consider avoided rootservers anyway if no non-avoid rootservers are available - * @return Rootserver or NULL if none + * @param strictAvoid If false, consider avoided root servers anyway if no non-avoid root servers are available + * @return Root server or NULL if none available */ - SharedPtr getBestRootserver(const Address *avoid,unsigned int avoidCount,bool strictAvoid); + SharedPtr getBestRoot(const Address *avoid,unsigned int avoidCount,bool strictAvoid); /** - * @param zta ZeroTier address - * @return True if this is a designated rootserver + * @param id Identity to check + * @return True if this is a designated root server */ - inline bool isRootserver(const Address &zta) const - throw() - { - Mutex::Lock _l(_lock); - return (std::find(_rootserverAddresses.begin(),_rootserverAddresses.end(),zta) != _rootserverAddresses.end()); - } + bool isRoot(const Identity &id) const + throw(); /** - * @return Vector of rootserver addresses + * @return Vector of root server addresses */ - inline std::vector
rootserverAddresses() const + inline std::vector
rootAddresses() const { Mutex::Lock _l(_lock); - return _rootserverAddresses; + return _rootAddresses; } /** @@ -206,13 +191,13 @@ private: const RuntimeEnvironment *RR; std::map< Address,SharedPtr > _activePeers; - std::map< Identity,std::vector > _rootservers; - std::vector< Address > _rootserverAddresses; - std::vector< SharedPtr > _rootserverPeers; + std::map< Identity,std::vector > _roots; + std::vector< Address > _rootAddresses; + std::vector< SharedPtr > _rootPeers; Mutex _lock; - bool _amRootserver; + bool _amRoot; }; } // namespace ZeroTier diff --git a/service/ControlPlane.cpp b/service/ControlPlane.cpp index e42c9ef85..015825867 100644 --- a/service/ControlPlane.cpp +++ b/service/ControlPlane.cpp @@ -211,9 +211,9 @@ static void _jsonAppend(unsigned int depth,std::string &buf,const ZT1_Peer *peer const char *prole = ""; switch(peer->role) { - case ZT1_PEER_ROLE_LEAF: prole = "LEAF"; break; - case ZT1_PEER_ROLE_HUB: prole = "HUB"; break; - case ZT1_PEER_ROLE_ROOTSERVER: prole = "ROOT"; break; + case ZT1_PEER_ROLE_LEAF: prole = "LEAF"; break; + case ZT1_PEER_ROLE_RELAY: prole = "RELAY"; break; + case ZT1_PEER_ROLE_ROOT: prole = "ROOT"; break; } Utils::snprintf(json,sizeof(json), From 50d4f66d733fb703208bb922ba08f06854d8dde5 Mon Sep 17 00:00:00 2001 From: Kees Bos Date: Fri, 19 Jun 2015 21:19:42 +0200 Subject: [PATCH 28/37] Fixed member authorization bug and minor cleanup --- controller/SqliteNetworkController.cpp | 36 ++++++++++++++------------ controller/SqliteNetworkController.hpp | 2 ++ 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/controller/SqliteNetworkController.cpp b/controller/SqliteNetworkController.cpp index 398b6991f..a1827a72e 100644 --- a/controller/SqliteNetworkController.cpp +++ b/controller/SqliteNetworkController.cpp @@ -178,6 +178,8 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) : ||(sqlite3_prepare_v2(_db,"DELETE FROM IpAssignmentPool WHERE networkId = ?",-1,&_sDeleteIpAssignmentPoolsForNetwork,(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,"INSERT INTO IpAssignmentPool (networkId,ipNetwork,ipNetmaskBits,ipVersion) VALUES (?,?,?,?)",-1,&_sCreateIpAssignmentPool,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"UPDATE Member SET authorized = ? WHERE rowid = ?",-1,&_sUpdateMemberAuthorized,(const char **)0) != SQLITE_OK) + ||(sqlite3_prepare_v2(_db,"UPDATE Member SET activeBridge = ? WHERE rowid = ?",-1,&_sUpdateMemberActiveBridge,(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 Network WHERE id = ?",-1,&_sDeleteNetwork,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT ip,ipVersion,metric FROM Gateway WHERE networkId = ? ORDER BY metric ASC",-1,&_sGetGateways,(const char **)0) != SQLITE_OK) @@ -225,6 +227,9 @@ SqliteNetworkController::~SqliteNetworkController() sqlite3_finalize(_sDeleteIpAssignmentPoolsForNetwork); sqlite3_finalize(_sDeleteRulesForNetwork); sqlite3_finalize(_sCreateIpAssignmentPool); + sqlite3_finalize(_sUpdateMemberAuthorized); + sqlite3_finalize(_sUpdateMemberActiveBridge); + sqlite3_finalize(_sDeleteMember); sqlite3_finalize(_sDeleteNetwork); sqlite3_finalize(_sGetGateways); sqlite3_finalize(_sDeleteGateways); @@ -342,7 +347,7 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co sqlite3_reset(_sCreateMember); sqlite3_bind_text(_sCreateMember,1,network.id,16,SQLITE_STATIC); sqlite3_bind_text(_sCreateMember,2,member.nodeId,10,SQLITE_STATIC); - sqlite3_bind_int(_sCreateMember,3,(member.authorized ? 0 : 1)); + sqlite3_bind_int(_sCreateMember,3,(member.authorized ? 1 : 0)); if (sqlite3_step(_sCreateMember) != SQLITE_DONE) { netconf["error"] = "unable to create new member record"; return NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR; @@ -680,29 +685,27 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST( if (!strcmp(j->u.object.values[k].name,"authorized")) { if (j->u.object.values[k].value->type == json_boolean) { - sqlite3_stmt *stmt = (sqlite3_stmt *)0; - if (sqlite3_prepare_v2(_db,"UPDATE Member SET authorized = ? WHERE rowid = ?",-1,&stmt,(const char **)0) == SQLITE_OK) - sqlite3_bind_int(stmt,1,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1); - sqlite3_bind_int64(stmt,2,memberRowId); - sqlite3_step(stmt); - sqlite3_finalize(stmt); + sqlite3_reset(_sUpdateMemberAuthorized); + sqlite3_bind_int(_sUpdateMemberAuthorized,1,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1); + sqlite3_bind_int64(_sUpdateMemberAuthorized,2,memberRowId); + if (sqlite3_step(_sUpdateMemberAuthorized) != SQLITE_DONE) + return 500; } } else if (!strcmp(j->u.object.values[k].name,"activeBridge")) { if (j->u.object.values[k].value->type == json_boolean) { - sqlite3_stmt *stmt = (sqlite3_stmt *)0; - if (sqlite3_prepare_v2(_db,"UPDATE Member SET activeBridge = ? WHERE rowid = ?",-1,&stmt,(const char **)0) == SQLITE_OK) { - sqlite3_bind_int(stmt,1,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1); - sqlite3_bind_int64(stmt,2,memberRowId); - sqlite3_step(stmt); - sqlite3_finalize(stmt); - } + sqlite3_reset(_sUpdateMemberActiveBridge); + sqlite3_bind_int(_sUpdateMemberActiveBridge,1,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1); + sqlite3_bind_int64(_sUpdateMemberActiveBridge,2,memberRowId); + if (sqlite3_step(_sUpdateMemberActiveBridge) != SQLITE_DONE) + return 500; } } else if (!strcmp(j->u.object.values[k].name,"ipAssignments")) { if (j->u.object.values[k].value->type == json_array) { sqlite3_reset(_sDeleteIpAllocations); sqlite3_bind_text(_sDeleteIpAllocations,1,nwids,16,SQLITE_STATIC); sqlite3_bind_text(_sDeleteIpAllocations,2,addrs,10,SQLITE_STATIC); - sqlite3_step(_sDeleteIpAllocations); + if (sqlite3_step(_sDeleteIpAllocations) != SQLITE_DONE) + return 500; for(unsigned int kk=0;kku.object.values[k].value->u.array.length;++kk) { json_value *ipalloc = j->u.object.values[k].value->u.array.values[kk]; if (ipalloc->type == json_string) { @@ -731,7 +734,8 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST( sqlite3_bind_blob(_sAllocateIp,3,(const void *)ipBlob,16,SQLITE_STATIC); sqlite3_bind_int(_sAllocateIp,4,(int)a.netmaskBits()); sqlite3_bind_int(_sAllocateIp,5,ipVersion); - sqlite3_step(_sAllocateIp); + if (sqlite3_step(_sAllocateIp) != SQLITE_DONE) + return 500; } } } diff --git a/controller/SqliteNetworkController.hpp b/controller/SqliteNetworkController.hpp index d258933d5..be2ca694f 100644 --- a/controller/SqliteNetworkController.hpp +++ b/controller/SqliteNetworkController.hpp @@ -122,6 +122,8 @@ private: sqlite3_stmt *_sDeleteIpAssignmentPoolsForNetwork; sqlite3_stmt *_sDeleteRulesForNetwork; sqlite3_stmt *_sCreateIpAssignmentPool; + sqlite3_stmt *_sUpdateMemberAuthorized; + sqlite3_stmt *_sUpdateMemberActiveBridge; sqlite3_stmt *_sDeleteMember; sqlite3_stmt *_sDeleteNetwork; sqlite3_stmt *_sGetGateways; From 2b04ac5e9b8be8bd1cc1263755a55a579f28009e Mon Sep 17 00:00:00 2001 From: Moritz Warning Date: Sat, 20 Jun 2015 09:36:51 +0200 Subject: [PATCH 29/37] replace _networks map by vector _networks is usually quite small, using binary search on a vector might be faster comapred to std::map. This is especially true when using uClibc++, which uses a list. --- node/Node.cpp | 38 ++++++++++++++++++++++---------------- node/Node.hpp | 23 ++++++++++++++++------- 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/node/Node.cpp b/node/Node.cpp index 9f195a106..8e00071fd 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -236,13 +236,14 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *next std::vector< SharedPtr > needConfig; { Mutex::Lock _l(_networks_m); - for(std::map< uint64_t,SharedPtr >::const_iterator n(_networks.begin());n!=_networks.end();++n) { - SharedPtr nc(n->second->config2()); - if (((now - n->second->lastConfigUpdate()) >= ZT_NETWORK_AUTOCONF_DELAY)||(!nc)) - needConfig.push_back(n->second); + for(std::vector< SharedPtr >::const_iterator n(_networks.begin());n!=_networks.end();++n) { + SharedPtr nc((*n)->config2()); + if (((now - (*n)->lastConfigUpdate()) >= ZT_NETWORK_AUTOCONF_DELAY)||(!nc)) + needConfig.push_back(*n); if (nc) networkRelays.insert(networkRelays.end(),nc->relays().begin(),nc->relays().end()); } + std::sort(_networks.begin(),_networks.end()); } // Request updated configuration for networks that need it @@ -310,19 +311,24 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *next ZT1_ResultCode Node::join(uint64_t nwid) { Mutex::Lock _l(_networks_m); - SharedPtr &nwe = _networks[nwid]; - if (!nwe) - nwe = SharedPtr(new Network(RR,nwid)); + std::vector< SharedPtr >::const_iterator nwi = std::lower_bound(_networks.begin(), _networks.end(), nwid, NetworkComparator()); + if(nwi == _networks.end() || (*nwi)->id() != nwid) { + _networks.push_back(SharedPtr(new Network(RR,nwid))); + std::sort(_networks.begin(),_networks.end()); + } return ZT1_RESULT_OK; } ZT1_ResultCode Node::leave(uint64_t nwid) { Mutex::Lock _l(_networks_m); - std::map< uint64_t,SharedPtr >::iterator nw(_networks.find(nwid)); - if (nw != _networks.end()) { - nw->second->destroy(); - _networks.erase(nw); + std::vector< SharedPtr >::iterator nwi = std::lower_bound(_networks.begin(), _networks.end(), nwid, NetworkComparator()); + if(nwi != _networks.end() && (*nwi)->id() == nwid) { + (*nwi)->destroy(); + // erase element (replace by last) + *nwi = _networks.back(); + _networks.pop_back(); + std::sort(_networks.begin(),_networks.end()); } return ZT1_RESULT_OK; } @@ -406,10 +412,10 @@ ZT1_PeerList *Node::peers() const ZT1_VirtualNetworkConfig *Node::networkConfig(uint64_t nwid) const { Mutex::Lock _l(_networks_m); - std::map< uint64_t,SharedPtr >::const_iterator nw(_networks.find(nwid)); - if (nw != _networks.end()) { + std::vector< SharedPtr >::const_iterator nwi = std::lower_bound(_networks.begin(), _networks.end(), nwid, NetworkComparator()); + if(nwi != _networks.end() && (*nwi)->id() == nwid) { ZT1_VirtualNetworkConfig *nc = (ZT1_VirtualNetworkConfig *)::malloc(sizeof(ZT1_VirtualNetworkConfig)); - nw->second->externalConfig(nc); + (*nwi)->externalConfig(nc); return nc; } return (ZT1_VirtualNetworkConfig *)0; @@ -426,8 +432,8 @@ ZT1_VirtualNetworkList *Node::networks() const nl->networks = (ZT1_VirtualNetworkConfig *)(buf + sizeof(ZT1_VirtualNetworkList)); nl->networkCount = 0; - for(std::map< uint64_t,SharedPtr >::const_iterator n(_networks.begin());n!=_networks.end();++n) - n->second->externalConfig(&(nl->networks[nl->networkCount++])); + for(std::vector< SharedPtr >::const_iterator n(_networks.begin());n!=_networks.end();++n) + (*n)->externalConfig(&(nl->networks[nl->networkCount++])); return nl; } diff --git a/node/Node.hpp b/node/Node.hpp index 1d9372e46..6ef306eb5 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -155,19 +155,21 @@ public: len); } - inline SharedPtr network(uint64_t nwid) + inline SharedPtr network(uint64_t nwid) const { Mutex::Lock _l(_networks_m); - std::map< uint64_t,SharedPtr >::iterator nw(_networks.find(nwid)); - return ((nw == _networks.end()) ? SharedPtr() : nw->second); + std::vector< SharedPtr >::const_iterator iter = std::lower_bound(_networks.begin(), _networks.end(), nwid, NetworkComparator()); + if(iter != _networks.end() && (*iter)->id() == nwid) { + return *iter; + } else { + return SharedPtr(); + } } inline std::vector< SharedPtr > allNetworks() const { Mutex::Lock _l(_networks_m); - std::vector< SharedPtr > nw; - for(std::map< uint64_t,SharedPtr >::const_iterator n(_networks.begin());n!=_networks.end();++n) - nw.push_back(n->second); + std::vector< SharedPtr > nw(_networks); return nw; } @@ -208,6 +210,13 @@ public: #endif private: + // for binary search on _networks + struct NetworkComparator { + bool operator()(const SharedPtr &n,uint64_t nwid) const { + return n->id() < nwid; + } + }; + RuntimeEnvironment _RR; RuntimeEnvironment *RR; @@ -223,7 +232,7 @@ private: //Dictionary _localConfig; // persisted as local.conf //Mutex _localConfig_m; - std::map< uint64_t,SharedPtr > _networks; + std::vector< SharedPtr > _networks; Mutex _networks_m; Mutex _backgroundTasksLock; From 787608b5683eb5df2a8ca0d365438234b5497c60 Mon Sep 17 00:00:00 2001 From: Moritz Warning Date: Sat, 20 Jun 2015 16:32:48 +0200 Subject: [PATCH 30/37] use _network function to reduce source code complexity --- node/Node.cpp | 10 +++++----- node/Node.hpp | 17 +++++++++++------ 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/node/Node.cpp b/node/Node.cpp index 8e00071fd..1dbb6d19d 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -311,8 +311,8 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *next ZT1_ResultCode Node::join(uint64_t nwid) { Mutex::Lock _l(_networks_m); - std::vector< SharedPtr >::const_iterator nwi = std::lower_bound(_networks.begin(), _networks.end(), nwid, NetworkComparator()); - if(nwi == _networks.end() || (*nwi)->id() != nwid) { + SharedPtr nw = _network(nwid); + if(!nw) { _networks.push_back(SharedPtr(new Network(RR,nwid))); std::sort(_networks.begin(),_networks.end()); } @@ -412,10 +412,10 @@ ZT1_PeerList *Node::peers() const ZT1_VirtualNetworkConfig *Node::networkConfig(uint64_t nwid) const { Mutex::Lock _l(_networks_m); - std::vector< SharedPtr >::const_iterator nwi = std::lower_bound(_networks.begin(), _networks.end(), nwid, NetworkComparator()); - if(nwi != _networks.end() && (*nwi)->id() == nwid) { + SharedPtr nw = _network(nwid); + if(nw) { ZT1_VirtualNetworkConfig *nc = (ZT1_VirtualNetworkConfig *)::malloc(sizeof(ZT1_VirtualNetworkConfig)); - (*nwi)->externalConfig(nc); + nw->externalConfig(nc); return nc; } return (ZT1_VirtualNetworkConfig *)0; diff --git a/node/Node.hpp b/node/Node.hpp index 6ef306eb5..b0f4ab222 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -158,12 +158,7 @@ public: inline SharedPtr network(uint64_t nwid) const { Mutex::Lock _l(_networks_m); - std::vector< SharedPtr >::const_iterator iter = std::lower_bound(_networks.begin(), _networks.end(), nwid, NetworkComparator()); - if(iter != _networks.end() && (*iter)->id() == nwid) { - return *iter; - } else { - return SharedPtr(); - } + return _network(nwid); } inline std::vector< SharedPtr > allNetworks() const @@ -217,6 +212,16 @@ private: } }; + inline SharedPtr _network(uint64_t nwid) const + { + std::vector< SharedPtr >::const_iterator iter = std::lower_bound(_networks.begin(), _networks.end(), nwid, NetworkComparator()); + if(iter != _networks.end() && (*iter)->id() == nwid) { + return *iter; + } else { + return SharedPtr(); + } + } + RuntimeEnvironment _RR; RuntimeEnvironment *RR; From def9cf2a6a6991bf19ceb74877152cdc6c149db7 Mon Sep 17 00:00:00 2001 From: Moritz Warning Date: Tue, 23 Jun 2015 00:08:59 +0200 Subject: [PATCH 31/37] replace vector::erase, was missed in a previous commit (ref #186) --- node/Multicaster.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/node/Multicaster.cpp b/node/Multicaster.cpp index 29e89189b..8a15bac13 100644 --- a/node/Multicaster.cpp +++ b/node/Multicaster.cpp @@ -330,7 +330,9 @@ void Multicaster::_add(uint64_t now,uint64_t nwid,const MulticastGroup &mg,Multi for(std::vector::iterator tx(gs.txQueue.begin());tx!=gs.txQueue.end();) { if (tx->atLimit()) { - gs.txQueue.erase(tx++); + // erase element (replace by last) + *tx = gs.txQueue.back(); + gs.txQueue.pop_back(); } else { tx->sendIfNew(RR,member); if (tx->atLimit()) { From 8a68624dae9e2bdb073e89f8e02e4bce85bfc7a8 Mon Sep 17 00:00:00 2001 From: Kees Bos Date: Fri, 26 Jun 2015 07:22:13 +0200 Subject: [PATCH 32/37] Fix cert verification check for self signed signatures --- node/Network.cpp | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/node/Network.cpp b/node/Network.cpp index d5dc7d58c..c072e9785 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -286,18 +286,28 @@ void Network::addMembershipCertificate(const CertificateOfMembership &cert,bool return; } - SharedPtr signer(RR->topology->getPeer(cert.signedBy())); + if (cert.signedBy() == RR->identity.address()) { + // We are the controller: RR->identity.address() == controller() == cert.signedBy() + // So, verify that we signed th cert ourself + if (!cert.verify(RR->identity)) { + TRACE("rejected network membership certificate for %.16llx self signed by %s: signature check failed",(unsigned long long)_id,cert.signedBy().toString().c_str()); + return; + } + } else { - if (!signer) { - // This would be rather odd, since this is our controller... could happen - // if we get packets before we've gotten config. - RR->sw->requestWhois(cert.signedBy()); - return; - } + SharedPtr signer(RR->topology->getPeer(cert.signedBy())); - if (!cert.verify(signer->identity())) { - TRACE("rejected network membership certificate for %.16llx signed by %s: signature check failed",(unsigned long long)_id,cert.signedBy().toString().c_str()); - return; + if (!signer) { + // This would be rather odd, since this is our controller... could happen + // if we get packets before we've gotten config. + RR->sw->requestWhois(cert.signedBy()); + return; + } + + if (!cert.verify(signer->identity())) { + TRACE("rejected network membership certificate for %.16llx signed by %s: signature check failed",(unsigned long long)_id,cert.signedBy().toString().c_str()); + return; + } } } From 3eca5d9c2933bc365de5b78e20976ccae360296e Mon Sep 17 00:00:00 2001 From: Kees Bos Date: Thu, 25 Jun 2015 18:35:13 +0200 Subject: [PATCH 33/37] Fix reporting of ipAssignments for ipv4 --- controller/SqliteNetworkController.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/controller/SqliteNetworkController.cpp b/controller/SqliteNetworkController.cpp index d77e06d86..eb8e399b2 100644 --- a/controller/SqliteNetworkController.cpp +++ b/controller/SqliteNetworkController.cpp @@ -1158,7 +1158,14 @@ unsigned int SqliteNetworkController::_doCPGet( sqlite3_bind_text(_sGetIpAssignmentsForNode2,2,addrs,10,SQLITE_STATIC); bool firstIp = true; while (sqlite3_step(_sGetIpAssignmentsForNode2) == SQLITE_ROW) { - InetAddress ip((const void *)sqlite3_column_blob(_sGetIpAssignmentsForNode2,0),(sqlite3_column_int(_sGetIpAssignmentsForNode2,2) == 6) ? 16 : 4,(unsigned int)sqlite3_column_int(_sGetIpAssignmentPools2,1)); + int ipversion = sqlite3_column_int(_sGetIpAssignmentsForNode2,2); + char ipBlob[16]; + memcpy(ipBlob,(const void *)sqlite3_column_blob(_sGetIpAssignmentsForNode2,0),16); + InetAddress ip( + (const void *)(ipversion == 6 ? ipBlob : &ipBlob[12]), + (ipversion == 6 ? 16 : 4), + (unsigned int)sqlite3_column_int(_sGetIpAssignmentsForNode2,1) + ); responseBody.append(firstIp ? "\"" : ",\""); firstIp = false; responseBody.append(_jsonEscape(ip.toString())); From c287ae4d1d0cb6448e556dda2c5c98eee4898cfe Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 26 Jun 2015 11:38:31 -0700 Subject: [PATCH 34/37] Redo conversion of _networks to a vector. Just use a simple linear search and put the nwid in a pair with the pointer so linear search can be done without pointer chasing. This should be the fastest option for anything less than dozens of networks, and should save memory over the old map. --- node/Node.cpp | 34 +++++++++++++++------------------- node/Node.hpp | 24 ++++++++++-------------- 2 files changed, 25 insertions(+), 33 deletions(-) diff --git a/node/Node.cpp b/node/Node.cpp index 60aeff1f0..850114341 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -141,7 +141,7 @@ Node::Node( Node::~Node() { Mutex::Lock _l(_networks_m); - _networks.clear(); + _networks.clear(); // ensure that networks are destroyed before shutdown delete RR->sa; delete RR->topology; delete RR->antiRec; @@ -236,14 +236,13 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *next std::vector< SharedPtr > needConfig; { Mutex::Lock _l(_networks_m); - for(std::vector< SharedPtr >::const_iterator n(_networks.begin());n!=_networks.end();++n) { - SharedPtr nc((*n)->config2()); - if (((now - (*n)->lastConfigUpdate()) >= ZT_NETWORK_AUTOCONF_DELAY)||(!nc)) - needConfig.push_back(*n); + for(std::vector< std::pair< uint64_t,SharedPtr > >::const_iterator n(_networks.begin());n!=_networks.end();++n) { + SharedPtr nc(n->second->config2()); + if (((now - n->second->lastConfigUpdate()) >= ZT_NETWORK_AUTOCONF_DELAY)||(!nc)) + needConfig.push_back(n->second); if (nc) networkRelays.insert(networkRelays.end(),nc->relays().begin(),nc->relays().end()); } - std::sort(_networks.begin(),_networks.end()); } // Request updated configuration for networks that need it @@ -312,24 +311,21 @@ ZT1_ResultCode Node::join(uint64_t nwid) { Mutex::Lock _l(_networks_m); SharedPtr nw = _network(nwid); - if(!nw) { - _networks.push_back(SharedPtr(new Network(RR,nwid))); - std::sort(_networks.begin(),_networks.end()); - } + if(!nw) + _networks.push_back(std::pair< uint64_t,SharedPtr >(nwid,SharedPtr(new Network(RR,nwid)))); + std::sort(_networks.begin(),_networks.end()); // will sort by nwid since it's the first in a pair<> return ZT1_RESULT_OK; } ZT1_ResultCode Node::leave(uint64_t nwid) { + std::vector< std::pair< uint64_t,SharedPtr > > newn; Mutex::Lock _l(_networks_m); - std::vector< SharedPtr >::iterator nwi = std::lower_bound(_networks.begin(), _networks.end(), nwid, NetworkComparator()); - if(nwi != _networks.end() && (*nwi)->id() == nwid) { - (*nwi)->destroy(); - // erase element (replace by last) - *nwi = _networks.back(); - _networks.pop_back(); - std::sort(_networks.begin(),_networks.end()); + for(std::vector< std::pair< uint64_t,SharedPtr > >::const_iterator n(_networks.begin());n!=_networks.end();++n) { + if (n->first != nwid) + newn.push_back(*n); } + _networks.swap(newn); return ZT1_RESULT_OK; } @@ -432,8 +428,8 @@ ZT1_VirtualNetworkList *Node::networks() const nl->networks = (ZT1_VirtualNetworkConfig *)(buf + sizeof(ZT1_VirtualNetworkList)); nl->networkCount = 0; - for(std::vector< SharedPtr >::const_iterator n(_networks.begin());n!=_networks.end();++n) - (*n)->externalConfig(&(nl->networks[nl->networkCount++])); + for(std::vector< std::pair< uint64_t,SharedPtr > >::const_iterator n(_networks.begin());n!=_networks.end();++n) + n->second->externalConfig(&(nl->networks[nl->networkCount++])); return nl; } diff --git a/node/Node.hpp b/node/Node.hpp index b0f4ab222..2d2898b57 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -163,8 +163,11 @@ public: inline std::vector< SharedPtr > allNetworks() const { + std::vector< SharedPtr > nw; Mutex::Lock _l(_networks_m); - std::vector< SharedPtr > nw(_networks); + nw.reserve(_networks.size()); + for(std::vector< std::pair< uint64_t, SharedPtr > >::const_iterator i=_networks.begin();i!=_networks.end();++i) + nw.push_back(i->second); return nw; } @@ -205,21 +208,14 @@ public: #endif private: - // for binary search on _networks - struct NetworkComparator { - bool operator()(const SharedPtr &n,uint64_t nwid) const { - return n->id() < nwid; - } - }; - inline SharedPtr _network(uint64_t nwid) const { - std::vector< SharedPtr >::const_iterator iter = std::lower_bound(_networks.begin(), _networks.end(), nwid, NetworkComparator()); - if(iter != _networks.end() && (*iter)->id() == nwid) { - return *iter; - } else { - return SharedPtr(); + // assumes _networks_m is locked + for(std::vector< std::pair< uint64_t, SharedPtr > >::const_iterator i=_networks.begin();i!=_networks.end();++i) { + if (i->first == nwid) + return i->second; } + return SharedPtr(); } RuntimeEnvironment _RR; @@ -237,7 +233,7 @@ private: //Dictionary _localConfig; // persisted as local.conf //Mutex _localConfig_m; - std::vector< SharedPtr > _networks; + std::vector< std::pair< uint64_t, SharedPtr > > _networks; Mutex _networks_m; Mutex _backgroundTasksLock; From 57c7992c785ab2f69fb2ddffd6f48bfebd96cab8 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 26 Jun 2015 12:36:45 -0700 Subject: [PATCH 35/37] GitHub issue #191 - kill intra-network multicast rate limits (which were not well supported or easily configurable anyway) -- this is really left over from the old collaborative multicast propagation algorithm. New algorithm (in for a while) has been sender-side replication in which sender "pays" all bandwidth, which intrinsically limits multicast. --- {node => attic}/BandwidthAccount.hpp | 0 controller/SqliteNetworkController.cpp | 26 ++++---------------- controller/SqliteNetworkController.hpp | 1 - controller/schema.sql | 11 --------- controller/schema.sql.c | 11 --------- node/Network.cpp | 14 ----------- node/Network.hpp | 11 --------- node/NetworkConfig.cpp | 31 ------------------------ node/NetworkConfig.hpp | 33 -------------------------- node/Switch.cpp | 6 ----- 10 files changed, 4 insertions(+), 140 deletions(-) rename {node => attic}/BandwidthAccount.hpp (100%) diff --git a/node/BandwidthAccount.hpp b/attic/BandwidthAccount.hpp similarity index 100% rename from node/BandwidthAccount.hpp rename to attic/BandwidthAccount.hpp diff --git a/controller/SqliteNetworkController.cpp b/controller/SqliteNetworkController.cpp index a1827a72e..d77e06d86 100644 --- a/controller/SqliteNetworkController.cpp +++ b/controller/SqliteNetworkController.cpp @@ -155,7 +155,6 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) : ||(sqlite3_prepare_v2(_db,"UPDATE Node SET lastAt = ?,lastSeen = ? WHERE id = ?",-1,&_sUpdateNode,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"UPDATE Node SET lastSeen = ? WHERE id = ?",-1,&_sUpdateNode2,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT etherType FROM Rule WHERE networkId = ? AND \"action\" = 'accept'",-1,&_sGetEtherTypesFromRuleTable,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"SELECT mgMac,mgAdi,preload,maxBalance,accrual FROM MulticastRate WHERE networkId = ?",-1,&_sGetMulticastRates,(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 ip,ipNetmaskBits FROM IpAssignment WHERE networkId = ? AND nodeId = ? AND ipVersion = ?",-1,&_sGetIpAssignmentsForNode,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT ipNetwork,ipNetmaskBits FROM IpAssignmentPool WHERE networkId = ? AND ipVersion = ?",-1,&_sGetIpAssignmentPools,(const char **)0) != SQLITE_OK) @@ -204,7 +203,6 @@ SqliteNetworkController::~SqliteNetworkController() sqlite3_finalize(_sUpdateNode); sqlite3_finalize(_sUpdateNode2); sqlite3_finalize(_sGetEtherTypesFromRuleTable); - sqlite3_finalize(_sGetMulticastRates); sqlite3_finalize(_sGetActiveBridges); sqlite3_finalize(_sGetIpAssignmentsForNode); sqlite3_finalize(_sGetIpAssignmentPools); @@ -403,26 +401,10 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co netconf[ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES] = allowedEtherTypesCsv; } - { - std::string multicastRates; - sqlite3_reset(_sGetMulticastRates); - sqlite3_bind_text(_sGetMulticastRates,1,network.id,16,SQLITE_STATIC); - while (sqlite3_step(_sGetMulticastRates) == SQLITE_ROW) { - const char *mac = (const char *)sqlite3_column_text(_sGetMulticastRates,0); - if ((mac)&&(strlen(mac) == 12)) { - unsigned long adi = ((unsigned long)sqlite3_column_int64(_sGetMulticastRates,1)) & 0xffffffff; - char tmp[256]; - Utils::snprintf(tmp,sizeof(tmp),"%s/%.4lx=%x,%x,%x\n",mac,adi,sqlite3_column_int(_sGetMulticastRates,2),sqlite3_column_int(_sGetMulticastRates,3),sqlite3_column_int(_sGetMulticastRates,4)); - multicastRates.append(tmp); - } - } - if (multicastRates.length() > 0) - netconf[ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_RATES] = multicastRates; - if (network.multicastLimit > 0) { - char ml[16]; - Utils::snprintf(ml,sizeof(ml),"%lx",(unsigned long)network.multicastLimit); - netconf[ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT] = ml; - } + if (network.multicastLimit > 0) { + char ml[16]; + Utils::snprintf(ml,sizeof(ml),"%lx",(unsigned long)network.multicastLimit); + netconf[ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT] = ml; } { diff --git a/controller/SqliteNetworkController.hpp b/controller/SqliteNetworkController.hpp index be2ca694f..9cdbc4040 100644 --- a/controller/SqliteNetworkController.hpp +++ b/controller/SqliteNetworkController.hpp @@ -99,7 +99,6 @@ private: sqlite3_stmt *_sUpdateNode; sqlite3_stmt *_sUpdateNode2; sqlite3_stmt *_sGetEtherTypesFromRuleTable; - sqlite3_stmt *_sGetMulticastRates; sqlite3_stmt *_sGetActiveBridges; sqlite3_stmt *_sGetIpAssignmentsForNode; sqlite3_stmt *_sGetIpAssignmentPools; diff --git a/controller/schema.sql b/controller/schema.sql index 809c7161d..d2261b2af 100644 --- a/controller/schema.sql +++ b/controller/schema.sql @@ -64,17 +64,6 @@ CREATE TABLE Member ( CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge); -CREATE TABLE MulticastRate ( - networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, - mgMac char(12) NOT NULL, - mgAdi integer NOT NULL DEFAULT(0), - preload integer NOT NULL, - maxBalance integer NOT NULL, - accrual integer NOT NULL -); - -CREATE INDEX MulticastRate_networkId ON MulticastRate (networkId); - CREATE TABLE Relay ( networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE, diff --git a/controller/schema.sql.c b/controller/schema.sql.c index f1c663584..1157facc5 100644 --- a/controller/schema.sql.c +++ b/controller/schema.sql.c @@ -65,17 +65,6 @@ "\n"\ "CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);\n"\ "\n"\ -"CREATE TABLE MulticastRate (\n"\ -" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\ -" mgMac char(12) NOT NULL,\n"\ -" mgAdi integer NOT NULL DEFAULT(0),\n"\ -" preload integer NOT NULL,\n"\ -" maxBalance integer NOT NULL,\n"\ -" accrual integer NOT NULL\n"\ -");\n"\ -"\n"\ -"CREATE INDEX MulticastRate_networkId ON MulticastRate (networkId);\n"\ -"\n"\ "CREATE TABLE Relay (\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"\ diff --git a/node/Network.cpp b/node/Network.cpp index a217595af..d5dc7d58c 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -357,20 +357,6 @@ void Network::clean() } } -bool Network::updateAndCheckMulticastBalance(const MulticastGroup &mg,unsigned int bytes) -{ - const uint64_t now = RR->node->now(); - Mutex::Lock _l(_lock); - if (!_config) - return false; - std::map< MulticastGroup,BandwidthAccount >::iterator bal(_multicastRateAccounts.find(mg)); - if (bal == _multicastRateAccounts.end()) { - NetworkConfig::MulticastRate r(_config->multicastRate(mg)); - bal = _multicastRateAccounts.insert(std::pair< MulticastGroup,BandwidthAccount >(mg,BandwidthAccount(r.preload,r.maxBalance,r.accrual,now))).first; - } - return bal->second.deduct(bytes,now); -} - void Network::learnBridgeRoute(const MAC &mac,const Address &addr) { Mutex::Lock _l(_lock); diff --git a/node/Network.hpp b/node/Network.hpp index 7976d9018..daa4554e6 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -47,7 +47,6 @@ #include "MulticastGroup.hpp" #include "MAC.hpp" #include "Dictionary.hpp" -#include "BandwidthAccount.hpp" #include "Multicaster.hpp" #include "NetworkConfig.hpp" #include "CertificateOfMembership.hpp" @@ -237,15 +236,6 @@ public: _externalConfig(ec); } - /** - * Update and check multicast rate balance for a multicast group - * - * @param mg Multicast group - * @param bytes Size of packet - * @return True if packet is within budget - */ - bool updateAndCheckMulticastBalance(const MulticastGroup &mg,unsigned int bytes); - /** * Get current network config or throw exception * @@ -370,7 +360,6 @@ private: std::vector< MulticastGroup > _myMulticastGroups; // multicast groups that we belong to including those behind us (updated periodically) std::map< MulticastGroup,uint64_t > _multicastGroupsBehindMe; // multicast groups bridged to us and when we last saw activity on each - std::map< MulticastGroup,BandwidthAccount > _multicastRateAccounts; std::map _remoteBridgeRoutes; // remote addresses where given MACs are reachable diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp index 5ed1dd3ff..8d682947f 100644 --- a/node/NetworkConfig.cpp +++ b/node/NetworkConfig.cpp @@ -32,10 +32,6 @@ namespace ZeroTier { -// This is fast enough for things like Apple's mDNS spam, so it should serve -// as a good default for your average network. -const NetworkConfig::MulticastRate NetworkConfig::DEFAULT_MULTICAST_RATE(40000,60000,80); - SharedPtr NetworkConfig::createTestNetworkConfig(const Address &self) { SharedPtr nc(new NetworkConfig()); @@ -85,18 +81,6 @@ std::vector NetworkConfig::allowedEtherTypes() const return ets; } -const NetworkConfig::MulticastRate &NetworkConfig::multicastRate(const MulticastGroup &mg) const - throw() -{ - std::map::const_iterator r(_multicastRates.find(mg)); - if (r == _multicastRates.end()) { - r = _multicastRates.find(MulticastGroup()); // zero MG signifies network's default rate - if (r == _multicastRates.end()) - return DEFAULT_MULTICAST_RATE; // neither specific nor default found in network config - } - return r->second; -} - void NetworkConfig::_fromDictionary(const Dictionary &d) { static const std::string zero("0"); @@ -181,13 +165,6 @@ void NetworkConfig::_fromDictionary(const Dictionary &d) std::sort(_activeBridges.begin(),_activeBridges.end()); std::unique(_activeBridges.begin(),_activeBridges.end()); - Dictionary multicastRateEntries(d.get(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_RATES,std::string())); - for(Dictionary::const_iterator i(multicastRateEntries.begin());i!=multicastRateEntries.end();++i) { - std::vector params(Utils::split(i->second.c_str(),",","","")); - if (params.size() >= 3) - _multicastRates[MulticastGroup(i->first)] = MulticastRate(Utils::hexStrToUInt(params[0].c_str()),Utils::hexStrToUInt(params[1].c_str()),Utils::hexStrToUInt(params[2].c_str())); - } - std::vector relaysSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_RELAYS,"").c_str(),",","","")); for(std::vector::const_iterator r(relaysSplit.begin());r!=relaysSplit.end();++r) { std::size_t semi(r->find(';')); // address;ip/port,... @@ -221,14 +198,6 @@ bool NetworkConfig::operator==(const NetworkConfig &nc) const if (_gateways != nc._gateways) return false; if (_activeBridges != nc._activeBridges) return false; if (_relays != nc._relays) return false; - if (_multicastRates.size() == nc._multicastRates.size()) { - // uclibc++ doesn't seem to implement map<> != map<> correctly, so do - // it ourselves. Note that this depends on the maps being sorted. - for(std::map::const_iterator a(_multicastRates.begin()),b(nc._multicastRates.begin());a!=_multicastRates.end();++a,++b) { - if ((a->first != b->first)||(a->second != b->second)) - return false; - } - } else return false; if (_com != nc._com) return false; return true; } diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp index 2fb56d6aa..75395fd53 100644 --- a/node/NetworkConfig.hpp +++ b/node/NetworkConfig.hpp @@ -68,9 +68,6 @@ namespace ZeroTier { // integer(hex) #define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT "ml" -// dictionary of one or more of: MAC/ADI=preload,maxbalance,accrual -#define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_RATES "mr" - // 0/1 #define ZT_NETWORKCONFIG_DICT_KEY_PRIVATE "p" @@ -114,27 +111,6 @@ class NetworkConfig friend class SharedPtr; public: - /** - * Tuple of multicast rate parameters - */ - struct MulticastRate - { - MulticastRate() throw() {} - MulticastRate(uint32_t pl,uint32_t maxb,uint32_t acc) throw() : preload(pl),maxBalance(maxb),accrual(acc) {} - - uint32_t preload; - uint32_t maxBalance; - uint32_t accrual; - - inline bool operator==(const MulticastRate &mr) const { return ((preload == mr.preload)&&(maxBalance == mr.maxBalance)&&(accrual == mr.accrual)); } - inline bool operator!=(const MulticastRate &mr) const { return (!(*this == mr)); } - }; - - /** - * A hard-coded default multicast rate for networks that don't specify - */ - static const MulticastRate DEFAULT_MULTICAST_RATE; - /** * Create an instance of a NetworkConfig for the test network ID * @@ -176,7 +152,6 @@ public: inline uint64_t revision() const throw() { return _revision; } inline const Address &issuedTo() const throw() { return _issuedTo; } inline unsigned int multicastLimit() const throw() { return _multicastLimit; } - inline const std::map &multicastRates() const throw() { return _multicastRates; } inline bool allowPassiveBridging() const throw() { return _allowPassiveBridging; } inline bool isPublic() const throw() { return (!_private); } inline bool isPrivate() const throw() { return _private; } @@ -198,13 +173,6 @@ public: return ( (_allowPassiveBridging) || (std::find(_activeBridges.begin(),_activeBridges.end(),fromPeer) != _activeBridges.end()) ); } - /** - * @param mg Multicast group - * @return Multicast rate or DEFAULT_MULTICAST_RATE if not set - */ - const MulticastRate &multicastRate(const MulticastGroup &mg) const - throw(); - bool operator==(const NetworkConfig &nc) const; inline bool operator!=(const NetworkConfig &nc) const { return (!(*this == nc)); } @@ -229,7 +197,6 @@ private: std::vector _gateways; std::vector
_activeBridges; std::vector< std::pair > _relays; - std::map _multicastRates; CertificateOfMembership _com; AtomicCounter __refCount; diff --git a/node/Switch.cpp b/node/Switch.cpp index af80f5e81..236c1e660 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -145,12 +145,6 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c if (fromBridged) network->learnBridgedMulticastGroup(mg,RR->node->now()); - // Check multicast/broadcast bandwidth quotas and reject if quota exceeded - if (!network->updateAndCheckMulticastBalance(mg,len)) { - TRACE("%.16llx: didn't multicast %u bytes, quota exceeded for multicast group %s",network->id(),len,mg.toString().c_str()); - return; - } - //TRACE("%.16llx: MULTICAST %s -> %s %s %u",network->id(),from.toString().c_str(),mg.toString().c_str(),etherTypeName(etherType),len); RR->mc->send( From 221df5187581ae5721159a9118e302ec376a744b Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 26 Jun 2015 13:04:52 -0700 Subject: [PATCH 36/37] Add Kees Bos to AUTHORS :) --- AUTHORS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/AUTHORS.md b/AUTHORS.md index 149362c31..4900aab54 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -8,6 +8,9 @@ ## Contributors + * A number of fixes and improvements to the new controller, other stuff.
+ Kees Bos / https://github.com/keesbos + * Debugging and testing, OpenWRT support fixes.
Moritz Warning / moritzwarning@web.de From 8fa924861541c4cdbe8fa466dd8df3e657ce50b6 Mon Sep 17 00:00:00 2001 From: Kees Bos Date: Wed, 24 Jun 2015 19:09:14 +0200 Subject: [PATCH 37/37] Set default accepted ethertypes if no rules are defined --- controller/SqliteNetworkController.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/controller/SqliteNetworkController.cpp b/controller/SqliteNetworkController.cpp index eb8e399b2..37466e19a 100644 --- a/controller/SqliteNetworkController.cpp +++ b/controller/SqliteNetworkController.cpp @@ -50,6 +50,7 @@ #include "../node/InetAddress.hpp" #include "../node/MAC.hpp" #include "../node/Address.hpp" +#include "../node/Switch.hpp" #include "../osdep/OSUtils.hpp" // Include ZT_NETCONF_SCHEMA_SQL constant to init database @@ -388,6 +389,14 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co if ((et >= 0)&&(et <= 0xffff)) allowedEtherTypes.push_back(et); } + if (!allowedEtherTypes.size()) { + // Nothing permitted is not usefull + // Just supply a default config allowing ARP, IPv4, IPv6 + // allowedEtherTypes.push_back(0); this would allow anything + allowedEtherTypes.push_back(ZT_ETHERTYPE_IPV4); + allowedEtherTypes.push_back(ZT_ETHERTYPE_ARP); + allowedEtherTypes.push_back(ZT_ETHERTYPE_IPV6); + } std::sort(allowedEtherTypes.begin(),allowedEtherTypes.end()); std::unique(allowedEtherTypes.begin(),allowedEtherTypes.end()); std::string allowedEtherTypesCsv;
FieldTypeDescription
ruleIdintegerUser-defined rule ID and sort order
ruleNointegerUser-defined rule ID and sort order
nodeIdstring10-digit hex ZeroTier address of node (a.k.a. "port on switch")
vlanIdintegerEthernet VLAN ID
vlanPcpintegerEthernet VLAN priority code point (PCP) ID