mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-05 03:53:44 +02:00
Merge branch 'adamierymenko-dev' of ssh://earth.zerotier.net:55522/git/ZeroTierOne into adamierymenko-dev
This commit is contained in:
commit
fbc6ca28b7
8 changed files with 98 additions and 10 deletions
|
@ -123,6 +123,14 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer>
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case Packet::ERROR_IDENTITY_COLLISION:
|
||||||
// TODO: if it comes from a supernode, regenerate a new identity
|
// TODO: if it comes from a supernode, regenerate a new identity
|
||||||
// if (RR->topology->isSupernode(source())) {}
|
// 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);
|
peer->setRemoteVersion(vProto,vMajor,vMinor,vRevision);
|
||||||
|
|
||||||
// If a supernode has a version higher than ours, this causes a software
|
// 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
|
// update check to run now.
|
||||||
// it's hosted on S3 so hopefully it can take it. This should cause updates
|
|
||||||
// to propagate out very quickly.
|
|
||||||
if ((RR->updater)&&(RR->topology->isSupernode(peer->address())))
|
if ((RR->updater)&&(RR->topology->isSupernode(peer->address())))
|
||||||
RR->updater->sawRemoteVersion(vMajor,vMinor,vRevision);
|
RR->updater->sawRemoteVersion(vMajor,vMinor,vRevision);
|
||||||
} break;
|
} break;
|
||||||
|
@ -307,12 +313,33 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p
|
||||||
case Packet::VERB_NETWORK_CONFIG_REQUEST: {
|
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)));
|
SharedPtr<Network> nw(RR->nc->network(at<uint64_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_NETWORK_ID)));
|
||||||
if ((nw)&&(nw->controller() == source())) {
|
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);
|
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);
|
std::string dict((const char *)field(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT,dictlen),dictlen);
|
||||||
if (dict.length()) {
|
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());
|
TRACE("got network configuration for network %.16llx from %s",(unsigned long long)nw->id(),source().toString().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -274,7 +274,7 @@ int Network::setConfiguration(const Dictionary &conf,bool saveToDisk)
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_lock);
|
Mutex::Lock _l(_lock);
|
||||||
if ((_config)&&(*_config == *newConfig))
|
if ((_config)&&(*_config == *newConfig))
|
||||||
return 1; // OK but duplicate
|
return 1; // OK config, but duplicate of what we already have
|
||||||
}
|
}
|
||||||
if (applyConfiguration(newConfig)) {
|
if (applyConfiguration(newConfig)) {
|
||||||
if (saveToDisk) {
|
if (saveToDisk) {
|
||||||
|
|
|
@ -94,8 +94,9 @@ void NetworkConfigMaster::doNetworkConfigRequest(const InetAddress &fromAddr,uin
|
||||||
Utils::snprintf(nwKey,sizeof(nwKey),"zt1:network:%s:~",nwids);
|
Utils::snprintf(nwKey,sizeof(nwKey),"zt1:network:%s:~",nwids);
|
||||||
Utils::snprintf(revKey,sizeof(revKey),"zt1:network:%s:revision",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)) {
|
if (!_hget(nwKey,"id",tmps2)) {
|
||||||
LOG("netconf: Redis error retrieving %s/id",nwKey);
|
LOG("netconf: Redis error retrieving %s/id",nwKey);
|
||||||
return;
|
return;
|
||||||
|
@ -111,6 +112,7 @@ void NetworkConfigMaster::doNetworkConfigRequest(const InetAddress &fromAddr,uin
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get network revision
|
||||||
if (!_get(revKey,revision)) {
|
if (!_get(revKey,revision)) {
|
||||||
LOG("netconf: Redis error retrieving %s",revKey);
|
LOG("netconf: Redis error retrieving %s",revKey);
|
||||||
return;
|
return;
|
||||||
|
@ -118,20 +120,26 @@ void NetworkConfigMaster::doNetworkConfigRequest(const InetAddress &fromAddr,uin
|
||||||
if (!revision.length())
|
if (!revision.length())
|
||||||
revision = "0";
|
revision = "0";
|
||||||
|
|
||||||
|
// Get network member record for this peer
|
||||||
if (!_hgetall(memberKey,memberRecord)) {
|
if (!_hgetall(memberKey,memberRecord)) {
|
||||||
LOG("netconf: Redis error retrieving %s",memberKey);
|
LOG("netconf: Redis error retrieving %s",memberKey);
|
||||||
return;
|
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 ((memberRecord.size() == 0)||(memberRecord.get("id","") != addrs)||(memberRecord.get("nwid","") != nwids)) {
|
||||||
if (!_initNewMember(nwid,member,metaData,memberRecord))
|
if (!_initNewMember(nwid,member,metaData,memberRecord))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memberRecord.getBoolean("authorized")) {
|
if (memberRecord.getBoolean("authorized")) {
|
||||||
|
// Get current netconf and netconf timestamp
|
||||||
uint64_t ts = memberRecord.getHexUInt("netconfTimestamp",0);
|
uint64_t ts = memberRecord.getHexUInt("netconfTimestamp",0);
|
||||||
std::string netconf(memberRecord.get("netconf",""));
|
std::string netconf(memberRecord.get("netconf",""));
|
||||||
|
|
||||||
|
// Update statistics for this node
|
||||||
Dictionary upd;
|
Dictionary upd;
|
||||||
upd.setHex("netconfClientTimestamp",haveTimestamp);
|
upd.setHex("netconfClientTimestamp",haveTimestamp);
|
||||||
if (fromAddr)
|
if (fromAddr)
|
||||||
|
@ -139,11 +147,16 @@ void NetworkConfigMaster::doNetworkConfigRequest(const InetAddress &fromAddr,uin
|
||||||
upd.setHex("lastSeen",Utils::now());
|
upd.setHex("lastSeen",Utils::now());
|
||||||
_hmset(memberKey,upd);
|
_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 (((ts == 0)||(netconf.length() == 0))||(memberRecord.get("netconfRevision","") != revision)) {
|
||||||
if (!_generateNetconf(nwid,member,metaData,netconf,ts))
|
if (!_generateNetconf(nwid,member,metaData,netconf,ts))
|
||||||
return;
|
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) {
|
if (ts > haveTimestamp) {
|
||||||
TRACE("netconf: sending %u bytes of netconf data to %s",netconf.length(),addrs);
|
TRACE("netconf: sending %u bytes of netconf data to %s",netconf.length(),addrs);
|
||||||
Packet outp(member,RR->identity.address(),Packet::VERB_OK);
|
Packet outp(member,RR->identity.address(),Packet::VERB_OK);
|
||||||
|
|
|
@ -30,6 +30,13 @@
|
||||||
|
|
||||||
#include "Constants.hpp"
|
#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
|
#ifdef ZT_ENABLE_NETCONF_MASTER
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
|
@ -310,6 +310,21 @@ Node::ReasonForTermination Node::run()
|
||||||
}
|
}
|
||||||
RR->node = this;
|
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
|
#ifdef ZT_AUTO_UPDATE
|
||||||
if (ZT_DEFAULTS.updateLatestNfoURL.length()) {
|
if (ZT_DEFAULTS.updateLatestNfoURL.length()) {
|
||||||
RR->updater = new SoftwareUpdater(RR);
|
RR->updater = new SoftwareUpdater(RR);
|
||||||
|
|
|
@ -341,6 +341,32 @@ public:
|
||||||
inline unsigned int remoteVersionMinor() const throw() { return _vMinor; }
|
inline unsigned int remoteVersionMinor() const throw() { return _vMinor; }
|
||||||
inline unsigned int remoteVersionRevision() const throw() { return _vRevision; }
|
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)); }
|
inline bool remoteVersionKnown() const throw() { return ((_vMajor > 0)||(_vMinor > 0)||(_vRevision > 0)); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* ZeroTier One - Global Peer to Peer Ethernet
|
* 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
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|
|
@ -41,6 +41,6 @@
|
||||||
/**
|
/**
|
||||||
* Revision
|
* Revision
|
||||||
*/
|
*/
|
||||||
#define ZEROTIER_ONE_VERSION_REVISION 2
|
#define ZEROTIER_ONE_VERSION_REVISION 3
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue