diff options
author | Adam Ierymenko <adam.ierymenko@gmail.com> | 2015-01-12 09:49:11 -0800 |
---|---|---|
committer | Adam Ierymenko <adam.ierymenko@gmail.com> | 2015-01-12 09:49:11 -0800 |
commit | fbc6ca28b7ee0b5d9917cdf6f7251e65dbb0d3ee (patch) | |
tree | 56787fd56d1fdafeabeb2e82e9bb3d8174f57468 | |
parent | 72f926dc41bed699f6510a273f5ebbe30d84f755 (diff) | |
parent | eab3ca1401b083b3d91d30d2c6f571dcb5c8a2a6 (diff) | |
download | infinitytier-fbc6ca28b7ee0b5d9917cdf6f7251e65dbb0d3ee.tar.gz infinitytier-fbc6ca28b7ee0b5d9917cdf6f7251e65dbb0d3ee.zip |
Merge branch 'adamierymenko-dev' of ssh://earth.zerotier.net:55522/git/ZeroTierOne into adamierymenko-dev
-rw-r--r-- | node/IncomingPacket.cpp | 39 | ||||
-rw-r--r-- | node/Network.cpp | 2 | ||||
-rw-r--r-- | node/NetworkConfigMaster.cpp | 15 | ||||
-rw-r--r-- | node/NetworkConfigMaster.hpp | 7 | ||||
-rw-r--r-- | node/Node.cpp | 15 | ||||
-rw-r--r-- | node/Peer.hpp | 26 | ||||
-rw-r--r-- | testnet/MTQ.hpp | 2 | ||||
-rw-r--r-- | version.h | 2 |
8 files changed, 98 insertions, 10 deletions
diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index f5379458..8e6de0e9 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -123,6 +123,14 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer> } break; + case Packet::ERROR_UNSUPPORTED_OPERATION: + if (inReVerb == Packet::VERB_NETWORK_CONFIG_REQUEST) { + SharedPtr<Network> network(RR->nc->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD))); + if ((network)&&(network->controller() == source())) + network->setNotFound(); + } + break; + case Packet::ERROR_IDENTITY_COLLISION: // TODO: if it comes from a supernode, regenerate a new identity // if (RR->topology->isSupernode(source())) {} @@ -286,9 +294,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p peer->setRemoteVersion(vProto,vMajor,vMinor,vRevision); // If a supernode has a version higher than ours, this causes a software - // update check to run now. This might bum-rush download.zerotier.com, but - // it's hosted on S3 so hopefully it can take it. This should cause updates - // to propagate out very quickly. + // update check to run now. if ((RR->updater)&&(RR->topology->isSupernode(peer->address()))) RR->updater->sawRemoteVersion(vMajor,vMinor,vRevision); } break; @@ -307,12 +313,33 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p case Packet::VERB_NETWORK_CONFIG_REQUEST: { SharedPtr<Network> nw(RR->nc->network(at<uint64_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_NETWORK_ID))); if ((nw)&&(nw->controller() == source())) { - // OK(NETWORK_CONFIG_REQUEST) is only accepted from a network's - // controller. unsigned int dictlen = at<uint16_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT_LEN); std::string dict((const char *)field(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT,dictlen),dictlen); if (dict.length()) { - nw->setConfiguration(Dictionary(dict)); + if (nw->setConfiguration(Dictionary(dict)) == 2) { // 2 == accepted and actually new + /* If this configuration was indeed new, we do another + * netconf request with its timestamp. We do this in + * order to (a) tell the netconf server we got it (it + * won't send a duplicate if ts == current), and (b) + * get another one if the netconf is changing rapidly + * until we finally have the final version. + * + * Note that we don't do this for netconf masters with + * versions <= 1.0.3, since those regenerate a new netconf + * with a new timestamp every time. In that case this double + * confirmation would create a race condition. */ + if (peer->atLeastVersion(1,0,3)) { + SharedPtr<NetworkConfig> nc(nw->config2()); + if ((nc)&&(nc->timestamp() > 0)) { // sanity check + Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NETWORK_CONFIG_REQUEST); + outp.append((uint64_t)nw->id()); + outp.append((uint16_t)0); // no meta-data + outp.append((uint64_t)nc->timestamp()); + outp.armor(peer->key(),true); + _fromSock->send(_remoteAddress,outp.data(),outp.size()); + } + } + } TRACE("got network configuration for network %.16llx from %s",(unsigned long long)nw->id(),source().toString().c_str()); } } diff --git a/node/Network.cpp b/node/Network.cpp index df741026..aac8d5d6 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -274,7 +274,7 @@ int Network::setConfiguration(const Dictionary &conf,bool saveToDisk) { Mutex::Lock _l(_lock); if ((_config)&&(*_config == *newConfig)) - return 1; // OK but duplicate + return 1; // OK config, but duplicate of what we already have } if (applyConfiguration(newConfig)) { if (saveToDisk) { diff --git a/node/NetworkConfigMaster.cpp b/node/NetworkConfigMaster.cpp index cbf7252c..3be2ad8c 100644 --- a/node/NetworkConfigMaster.cpp +++ b/node/NetworkConfigMaster.cpp @@ -94,8 +94,9 @@ void NetworkConfigMaster::doNetworkConfigRequest(const InetAddress &fromAddr,uin Utils::snprintf(nwKey,sizeof(nwKey),"zt1:network:%s:~",nwids); Utils::snprintf(revKey,sizeof(revKey),"zt1:network:%s:revision",nwids); - TRACE("netconf: request from %s for %s (if newer than %llu)",addrs,nwids,(unsigned long long)haveTimestamp); + TRACE("netconf: %s : %s if > %llu",nwids,addrs,(unsigned long long)haveTimestamp); + // Check to make sure network itself exists and is valid if (!_hget(nwKey,"id",tmps2)) { LOG("netconf: Redis error retrieving %s/id",nwKey); return; @@ -111,6 +112,7 @@ void NetworkConfigMaster::doNetworkConfigRequest(const InetAddress &fromAddr,uin return; } + // Get network revision if (!_get(revKey,revision)) { LOG("netconf: Redis error retrieving %s",revKey); return; @@ -118,20 +120,26 @@ void NetworkConfigMaster::doNetworkConfigRequest(const InetAddress &fromAddr,uin if (!revision.length()) revision = "0"; + // Get network member record for this peer if (!_hgetall(memberKey,memberRecord)) { LOG("netconf: Redis error retrieving %s",memberKey); return; } + // If there is no member record, init a new one -- for public networks this + // auto-authorizes, and for private nets it makes the peer show up in the UI + // so the admin can authorize or delete/hide it. if ((memberRecord.size() == 0)||(memberRecord.get("id","") != addrs)||(memberRecord.get("nwid","") != nwids)) { if (!_initNewMember(nwid,member,metaData,memberRecord)) return; } if (memberRecord.getBoolean("authorized")) { + // Get current netconf and netconf timestamp uint64_t ts = memberRecord.getHexUInt("netconfTimestamp",0); std::string netconf(memberRecord.get("netconf","")); + // Update statistics for this node Dictionary upd; upd.setHex("netconfClientTimestamp",haveTimestamp); if (fromAddr) @@ -139,11 +147,16 @@ void NetworkConfigMaster::doNetworkConfigRequest(const InetAddress &fromAddr,uin upd.setHex("lastSeen",Utils::now()); _hmset(memberKey,upd); + // Attempt to generate netconf for this node if there isn't + // one or it's not in step with the network's revision. if (((ts == 0)||(netconf.length() == 0))||(memberRecord.get("netconfRevision","") != revision)) { if (!_generateNetconf(nwid,member,metaData,netconf,ts)) return; } + // If the netconf we have (or just generated) is newer than what + // the client reports that it has, send it. Otherwise we just + // ignore the message since the client is up to date. if (ts > haveTimestamp) { TRACE("netconf: sending %u bytes of netconf data to %s",netconf.length(),addrs); Packet outp(member,RR->identity.address(),Packet::VERB_OK); diff --git a/node/NetworkConfigMaster.hpp b/node/NetworkConfigMaster.hpp index 25d5bb1c..c6993c56 100644 --- a/node/NetworkConfigMaster.hpp +++ b/node/NetworkConfigMaster.hpp @@ -30,6 +30,13 @@ #include "Constants.hpp" +#define ZT_LOCAL_CONFIG_NETCONF_REDIS_HOST "netconf.redisHost" +#define ZT_LOCAL_CONFIG_NETCONF_REDIS_PORT "netconf.redisPort" +#define ZT_LOCAL_CONFIG_NETCONF_REDIS_PORT_DEFAULT 6379 +#define ZT_LOCAL_CONFIG_NETCONF_REDIS_AUTH "netconf.redisAuth" +#define ZT_LOCAL_CONFIG_NETCONF_REDIS_DBNUM "netconf.redisDatabaseNumber" +#define ZT_LOCAL_CONFIG_NETCONF_REDIS_DBNUM_DEFAULT 0 + #ifdef ZT_ENABLE_NETCONF_MASTER #include <stdint.h> diff --git a/node/Node.cpp b/node/Node.cpp index d65e4e39..b9f027e3 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -310,6 +310,21 @@ Node::ReasonForTermination Node::run() } RR->node = this; +#ifdef ZT_ENABLE_NETCONF_MASTER + { + std::string redisHost(RR->nc->getLocalConfig(ZT_LOCAL_CONFIG_NETCONF_REDIS_HOST)); + if (redisHost.length() > 0) { + unsigned int redisPort = Utils::strToUInt(RR->nc->getLocalConfig(ZT_LOCAL_CONFIG_NETCONF_REDIS_PORT).c_str()); + if ((redisPort == 0)||(redisPort > 0xffff)) + redisPort = ZT_LOCAL_CONFIG_NETCONF_REDIS_PORT_DEFAULT; + std::string redisAuth(RR->nc->getLocalConfig(ZT_LOCAL_CONFIG_NETCONF_REDIS_AUTH)); + std::string redisDatabaseNumberStr(RR->nc->getLocalConfig(ZT_LOCAL_CONFIG_NETCONF_REDIS_DBNUM)); + unsigned int redisDatabaseNumber = (redisDatabaseNumberStr.length() > 0) ? Utils::strToUInt(redisDatabaseNumberStr.c_str()) : (unsigned int)ZT_LOCAL_CONFIG_NETCONF_REDIS_DBNUM_DEFAULT; + RR->netconfMaster = new NetworkConfigMaster(RR,redisHost.c_str(),redisPort,redisAuth.c_str(),redisDatabaseNumber); + } + } +#endif + #ifdef ZT_AUTO_UPDATE if (ZT_DEFAULTS.updateLatestNfoURL.length()) { RR->updater = new SoftwareUpdater(RR); diff --git a/node/Peer.hpp b/node/Peer.hpp index 142002a8..09bf0e04 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -341,6 +341,32 @@ public: inline unsigned int remoteVersionMinor() const throw() { return _vMinor; } inline unsigned int remoteVersionRevision() const throw() { return _vRevision; } + /** + * Check whether this peer's version is both known and is at least what is specified + * + * @param major Major version to check against + * @param minor Minor version + * @param rev Revision + * @return True if peer's version is at least supplied tuple + */ + inline bool atLeastVersion(unsigned int major,unsigned int minor,unsigned int rev) + throw() + { + if ((_vMajor > 0)||(_vMinor > 0)||(_vRevision > 0)) { + if (_vMajor > major) + return true; + else if (_vMajor == major) { + if (_vMinor > minor) + return true; + else if (_vMinor == minor) { + if (_vRevision >= rev) + return true; + } + } + } + return false; + } + inline bool remoteVersionKnown() const throw() { return ((_vMajor > 0)||(_vMinor > 0)||(_vRevision > 0)); } /** diff --git a/testnet/MTQ.hpp b/testnet/MTQ.hpp index 2a2fe1cd..c2f53e21 100644 --- a/testnet/MTQ.hpp +++ b/testnet/MTQ.hpp @@ -1,6 +1,6 @@ /* * ZeroTier One - Global Peer to Peer Ethernet - * Copyright (C) 2012-2014 ZeroTier Networks LLC + * Copyright (C) 2011-2015 ZeroTier Networks LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,6 +41,6 @@ /** * Revision */ -#define ZEROTIER_ONE_VERSION_REVISION 2 +#define ZEROTIER_ONE_VERSION_REVISION 3 #endif |