More World stuff, and mkworld.

This commit is contained in:
Adam Ierymenko 2015-10-13 08:49:36 -07:00
parent 1b1945c63e
commit cae58f43f1
13 changed files with 281 additions and 105 deletions

View File

@ -1023,7 +1023,6 @@ typedef int (*ZT_WirePacketSendFunction)(
* @param dataStorePutFunction Function called to put objects in persistent storage * @param dataStorePutFunction Function called to put objects in persistent storage
* @param virtualNetworkConfigFunction Function to be called when virtual LANs are created, deleted, or their config parameters change * @param virtualNetworkConfigFunction Function to be called when virtual LANs are created, deleted, or their config parameters change
* @param eventCallback Function to receive status updates and non-fatal error notices * @param eventCallback Function to receive status updates and non-fatal error notices
* @param overrideRootTopology Alternative root server topology or NULL for default (mostly for test/debug use)
* @return OK (0) or error code if a fatal error condition has occurred * @return OK (0) or error code if a fatal error condition has occurred
*/ */
enum ZT_ResultCode ZT_Node_new( enum ZT_ResultCode ZT_Node_new(
@ -1035,8 +1034,7 @@ enum ZT_ResultCode ZT_Node_new(
ZT_WirePacketSendFunction wirePacketSendFunction, ZT_WirePacketSendFunction wirePacketSendFunction,
ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction, ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction, ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction,
ZT_EventCallback eventCallback, ZT_EventCallback eventCallback);
const char *overrideRootTopology);
/** /**
* Delete a node and free all resources it consumes * Delete a node and free all resources it consumes

View File

@ -79,6 +79,10 @@ selftest: $(OBJS) selftest.o
$(CXX) $(CXXFLAGS) -o zerotier-selftest selftest.o $(OBJS) $(LIBS) $(CXX) $(CXXFLAGS) -o zerotier-selftest selftest.o $(OBJS) $(LIBS)
$(STRIP) zerotier-selftest $(STRIP) zerotier-selftest
mkworld: $(OBJS)
rm -f mkworld
$(CXX) $(CXXFLAGS) -o mkworld mkworld.cpp $(OBJS) $(LIBS)
# Requires Packages: http://s.sudre.free.fr/Software/Packages/about.html # Requires Packages: http://s.sudre.free.fr/Software/Packages/about.html
mac-dist-pkg: FORCE mac-dist-pkg: FORCE
packagesbuild "ext/installfiles/mac/ZeroTier One.pkgproj" packagesbuild "ext/installfiles/mac/ZeroTier One.pkgproj"
@ -93,7 +97,7 @@ official: FORCE
make ZT_OFFICIAL_RELEASE=1 mac-dist-pkg make ZT_OFFICIAL_RELEASE=1 mac-dist-pkg
clean: clean:
rm -rf *.dSYM build-* *.pkg *.dmg *.o node/*.o controller/*.o service/*.o osdep/*.o ext/http-parser/*.o ext/lz4/*.o ext/json-parser/*.o zerotier-one zerotier-idtool zerotier-selftest zerotier-cli ZeroTierOneInstaller-* rm -rf *.dSYM build-* *.pkg *.dmg *.o node/*.o controller/*.o service/*.o osdep/*.o ext/http-parser/*.o ext/lz4/*.o ext/json-parser/*.o zerotier-one zerotier-idtool zerotier-selftest zerotier-cli ZeroTierOneInstaller-* mkworld
# For those building from source -- installs signed binary tap driver in system ZT home # For those building from source -- installs signed binary tap driver in system ZT home
install-mac-tap: FORCE install-mac-tap: FORCE

153
mkworld.cpp Normal file
View File

@ -0,0 +1,153 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2015 ZeroTier, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* --
*
* ZeroTier may be used and distributed under the terms of the GPLv3, which
* are available at: http://www.gnu.org/licenses/gpl-3.0.html
*
* If you would like to embed ZeroTier into a commercial application or
* redistribute it in a modified binary form, please contact ZeroTier Networks
* LLC. Start here: http://www.zerotier.com/
*/
/*
* This utility makes the World from the configuration specified below.
* It probably won't be much use to anyone outside ZeroTier, Inc. except
* for testing and experimentation purposes.
*
* If you want to make your own World you must edit this file.
*
* When run, it expects two files in the current directory:
*
* previous.c25519 - key pair to sign this world (key from previous world)
* current.c25519 - key pair whose public key should be embedded in this world
*
* If these files do not exist, they are both created with the same key pair
* and a self-signed initial World is born.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <string>
#include <vector>
#include <algorithm>
#include "node/Constants.hpp"
#include "node/World.hpp"
#include "node/C25519.hpp"
#include "node/Identity.hpp"
#include "node/InetAddress.hpp"
#include "osdep/OSUtils.hpp"
using namespace ZeroTier;
class WorldMaker : public World
{
public:
static inline World make(uint64_t id,uint64_t ts,const C25519::Public &sk,const std::vector<World::Root> &roots,const C25519::Pair &signWith)
{
WorldMaker w;
w._id = id;
w._ts = ts;
w._updateSigningKey = sk;
w._roots = roots;
Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> tmp;
w.serialize(tmp,true);
w._signature = C25519::sign(signWith,tmp.data(),tmp.size());
return w;
}
};
int main(int argc,char **argv)
{
std::string previous,current;
if ((!OSUtils::readFile("previous.c25519",previous))||(!OSUtils::readFile("current.c25519",current))) {
C25519::Pair np(C25519::generate());
previous = std::string();
previous.append((const char *)np.pub.data,ZT_C25519_PUBLIC_KEY_LEN);
previous.append((const char *)np.priv.data,ZT_C25519_PRIVATE_KEY_LEN);
current = previous;
OSUtils::writeFile("previous.c25519",previous);
OSUtils::writeFile("current.c25519",current);
fprintf(stderr,"INFO: created initial world keys: previous.c25519, current.c25519"ZT_EOL_S);
}
if ((previous.length() != (ZT_C25519_PUBLIC_KEY_LEN + ZT_C25519_PRIVATE_KEY_LEN))||(current.length() != (ZT_C25519_PUBLIC_KEY_LEN + ZT_C25519_PRIVATE_KEY_LEN))) {
fprintf(stderr,"FATAL: previous.c25519 or current.c25519 empty or invalid"ZT_EOL_S);
return 1;
}
C25519::Pair previousKP;
memcpy(previousKP.pub.data,previous.data(),ZT_C25519_PUBLIC_KEY_LEN);
memcpy(previousKP.priv.data,previous.data() + ZT_C25519_PUBLIC_KEY_LEN,ZT_C25519_PRIVATE_KEY_LEN);
C25519::Pair currentKP;
memcpy(currentKP.pub.data,current.data(),ZT_C25519_PUBLIC_KEY_LEN);
memcpy(currentKP.priv.data,current.data() + ZT_C25519_PUBLIC_KEY_LEN,ZT_C25519_PRIVATE_KEY_LEN);
// EDIT BELOW HERE ---------------------------------------------------------
std::vector<World::Root> roots;
// old US-SFO
roots.push_back(World::Root());
roots.back().identity = Identity("7e19876aba:0:2a6e2b2318930f60eb097f70d0f4b028b2cd6d3d0c63c014b9039ff35390e41181f216fb2e6fa8d95c1ee9667156411905c3dccfea78d8c6dfafba688170b3fa");
roots.back().stableEndpoints.push_back(InetAddress("198.199.97.220/9993"));
std::sort(roots.back().stableEndpoints.begin(),roots.back().stableEndpoints.end());
// old EU-PARIS
roots.push_back(World::Root());
roots.back().identity = Identity("8841408a2e:0:bb1d31f2c323e264e9e64172c1a74f77899555ed10751cd56e86405cde118d02dffe555d462ccf6a85b5631c12350c8d5dc409ba10b9025d0f445cf449d92b1c");
roots.back().stableEndpoints.push_back(InetAddress("107.191.46.210/9993"));
std::sort(roots.back().stableEndpoints.begin(),roots.back().stableEndpoints.end());
// old US-NYC
roots.push_back(World::Root());
roots.back().identity = Identity("8acf059fe3:0:482f6ee5dfe902319b419de5bdc765209c0ecda38c4d6e4fcf0d33658398b4527dcd22f93112fb9befd02fd78bf7261b333fc105d192a623ca9e50fc60b374a5");
roots.back().stableEndpoints.push_back(InetAddress("162.243.77.111/9993"));
std::sort(roots.back().stableEndpoints.begin(),roots.back().stableEndpoints.end());
// old AP-SNG
roots.push_back(World::Root());
roots.back().identity = Identity("9d219039f3:0:01f0922a98e3b34ebcbff333269dc265d7a020aab69d72be4d4acc9c8c9294785771256cd1d942a90d1bd1d2dca3ea84ef7d85afe6611fb43ff0b74126d90a6e");
roots.back().stableEndpoints.push_back(InetAddress("128.199.197.217/9993"));
std::sort(roots.back().stableEndpoints.begin(),roots.back().stableEndpoints.end());
std::sort(roots.begin(),roots.end());
const uint64_t id = ZT_WORLD_ID_EARTH;
const uint64_t ts = OSUtils::now();
// END WORLD SETUP ---------------------------------------------------------
fprintf(stderr,"INFO: generating and signing id==%llu ts==%llu"ZT_EOL_S,(unsigned long long)id,(unsigned long long)ts);
World nw = WorldMaker::make(id,ts,currentKP.pub,roots,previousKP);
Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> outtmp;
nw.serialize(outtmp,false);
fwrite(outtmp.data(),outtmp.size(),1,stdout);
fflush(stdout);
fprintf(stderr,"INFO: wrote %u bytes to stdout"ZT_EOL_S,outtmp.size());
return 0;
}

View File

@ -33,7 +33,6 @@
#include "../include/ZeroTierOne.h" #include "../include/ZeroTierOne.h"
#include "Constants.hpp" #include "Constants.hpp"
#include "Defaults.hpp"
#include "RuntimeEnvironment.hpp" #include "RuntimeEnvironment.hpp"
#include "IncomingPacket.hpp" #include "IncomingPacket.hpp"
#include "Topology.hpp" #include "Topology.hpp"

View File

@ -46,7 +46,6 @@
#include "Address.hpp" #include "Address.hpp"
#include "Identity.hpp" #include "Identity.hpp"
#include "SelfAwareness.hpp" #include "SelfAwareness.hpp"
#include "Defaults.hpp"
const struct sockaddr_storage ZT_SOCKADDR_NULL = {0}; const struct sockaddr_storage ZT_SOCKADDR_NULL = {0};
@ -64,8 +63,7 @@ Node::Node(
ZT_WirePacketSendFunction wirePacketSendFunction, ZT_WirePacketSendFunction wirePacketSendFunction,
ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction, ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction, ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction,
ZT_EventCallback eventCallback, ZT_EventCallback eventCallback) :
const char *overrideRootTopology) :
_RR(this), _RR(this),
RR(&_RR), RR(&_RR),
_uPtr(uptr), _uPtr(uptr),
@ -125,21 +123,6 @@ Node::Node(
throw; throw;
} }
Dictionary rt;
if (overrideRootTopology) {
rt.fromString(std::string(overrideRootTopology));
} else {
std::string rttmp(dataStoreGet("root-topology"));
if (rttmp.length() > 0) {
rt.fromString(rttmp);
if (!Topology::authenticateRootTopology(rt))
rt.clear();
}
if ((!rt.size())||(!rt.contains("rootservers")))
rt.fromString(ZT_DEFAULTS.defaultRootTopology);
}
RR->topology->setRootServers(Dictionary(rt.get("rootservers","")));
postEvent(ZT_EVENT_UP); postEvent(ZT_EVENT_UP);
} }
@ -609,12 +592,11 @@ enum ZT_ResultCode ZT_Node_new(
ZT_WirePacketSendFunction wirePacketSendFunction, ZT_WirePacketSendFunction wirePacketSendFunction,
ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction, ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction, ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction,
ZT_EventCallback eventCallback, ZT_EventCallback eventCallback)
const char *overrideRootTopology)
{ {
*node = (ZT_Node *)0; *node = (ZT_Node *)0;
try { try {
*node = reinterpret_cast<ZT_Node *>(new ZeroTier::Node(now,uptr,dataStoreGetFunction,dataStorePutFunction,wirePacketSendFunction,virtualNetworkFrameFunction,virtualNetworkConfigFunction,eventCallback,overrideRootTopology)); *node = reinterpret_cast<ZT_Node *>(new ZeroTier::Node(now,uptr,dataStoreGetFunction,dataStorePutFunction,wirePacketSendFunction,virtualNetworkFrameFunction,virtualNetworkConfigFunction,eventCallback));
return ZT_RESULT_OK; return ZT_RESULT_OK;
} catch (std::bad_alloc &exc) { } catch (std::bad_alloc &exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;

View File

@ -71,8 +71,7 @@ public:
ZT_WirePacketSendFunction wirePacketSendFunction, ZT_WirePacketSendFunction wirePacketSendFunction,
ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction, ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction, ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction,
ZT_EventCallback eventCallback, ZT_EventCallback eventCallback);
const char *overrideRootTopology);
~Node(); ~Node();

View File

@ -540,6 +540,8 @@ public:
* <[...] binary serialized identity (see Identity)> * <[...] binary serialized identity (see Identity)>
* <[1] destination address type> * <[1] destination address type>
* [<[...] destination address>] * [<[...] destination address>]
* <[8] 64-bit world ID of current world>
* <[8] 64-bit timestamp of current world>
* *
* This is the only message that ever must be sent in the clear, since it * This is the only message that ever must be sent in the clear, since it
* is used to push an identity to a new peer. * is used to push an identity to a new peer.
@ -564,8 +566,8 @@ public:
* <[2] software revision (of responder)> * <[2] software revision (of responder)>
* <[1] destination address type (for this OK, not copied from HELLO)> * <[1] destination address type (for this OK, not copied from HELLO)>
* [<[...] destination address>] * [<[...] destination address>]
* <[8] 64-bit world ID of current world> * <[8] 64-bit world ID of current world (of responder)>
* <[8] 64-bit timestamp of current world> * <[8] 64-bit timestamp of current world (of responder)>
* *
* ERROR has no payload. * ERROR has no payload.
*/ */

View File

@ -42,23 +42,6 @@ Topology::Topology(const RuntimeEnvironment *renv) :
RR(renv), RR(renv),
_amRoot(false) _amRoot(false)
{ {
try {
std::string dsWorld(RR->node->dataStoreGet("world"));
Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> dswtmp(dsWorld.data(),dsWorld.length());
_world.deserialize(dswtmp,0);
} catch ( ... ) {
_world = World(); // set to null if cached world is invalid
}
{
World defaultWorld;
Buffer<ZT_DEFAULT_WORLD_LENGTH> wtmp(ZT_DEFAULT_WORLD,ZT_DEFAULT_WORLD_LENGTH);
defaultWorld.deserialize(wtmp,0); // throws on error, which would indicate a bad static variable up top
if (_world.verifyUpdate(defaultWorld)) {
_world = defaultWorld;
RR->node->dataStorePut("world",ZT_DEFAULT_WORLD,ZT_DEFAULT_WORLD_LENGTH,false);
}
}
std::string alls(RR->node->dataStoreGet("peers.save")); std::string alls(RR->node->dataStoreGet("peers.save"));
const uint8_t *all = reinterpret_cast<const uint8_t *>(alls.data()); const uint8_t *all = reinterpret_cast<const uint8_t *>(alls.data());
RR->node->dataStoreDelete("peers.save"); RR->node->dataStoreDelete("peers.save");
@ -97,19 +80,24 @@ Topology::Topology(const RuntimeEnvironment *renv) :
clean(RR->node->now()); clean(RR->node->now());
for(std::vector<World::Root>::const_iterator r(_world.roots().begin());r!=_world.roots().end();++r) { std::string dsWorld(RR->node->dataStoreGet("world"));
if (r->identity == RR->identity) World cachedWorld;
_amRoot = true; try {
_rootAddresses.push_back(r->identity.address()); Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> dswtmp(dsWorld.data(),dsWorld.length());
SharedPtr<Peer> *rp = _peers.get(r->identity.address()); cachedWorld.deserialize(dswtmp,0);
if (rp) { } catch ( ... ) {
_rootPeers.push_back(*rp); cachedWorld = World(); // clear if cached world is invalid
} else if (r->identity.address() != RR->identity.address()) {
SharedPtr<Peer> newrp(new Peer(RR->identity,r->identity));
_peers.set(r->identity.address(),newrp);
_rootPeers.push_back(newrp);
}
} }
World defaultWorld;
{
Buffer<ZT_DEFAULT_WORLD_LENGTH> wtmp(ZT_DEFAULT_WORLD,ZT_DEFAULT_WORLD_LENGTH);
defaultWorld.deserialize(wtmp,0); // throws on error, which would indicate a bad static variable up top
}
if (cachedWorld.shouldBeReplacedBy(defaultWorld,false)) {
_setWorld(defaultWorld);
if (dsWorld.length() > 0)
RR->node->dataStoreDelete("world");
} else _setWorld(cachedWorld);
} }
Topology::~Topology() Topology::~Topology()
@ -283,6 +271,16 @@ keep_searching_for_roots:
return bestRoot; return bestRoot;
} }
bool Topology::worldUpdateIfValid(const World &newWorld)
{
Mutex::Lock _l(_lock);
if (_world.shouldBeReplacedBy(newWorld,true)) {
_setWorld(newWorld);
return true;
}
return false;
}
void Topology::clean(uint64_t now) void Topology::clean(uint64_t now)
{ {
Mutex::Lock _l(_lock); Mutex::Lock _l(_lock);
@ -320,4 +318,26 @@ void Topology::_saveIdentity(const Identity &id)
} }
} }
void Topology::_setWorld(const World &newWorld)
{
// assumed _lock is locked (or in constructor)
_world = newWorld;
_amRoot = false;
_rootAddresses.clear();
_rootPeers.clear();
for(std::vector<World::Root>::const_iterator r(_world.roots().begin());r!=_world.roots().end();++r) {
if (r->identity == RR->identity)
_amRoot = true;
_rootAddresses.push_back(r->identity.address());
SharedPtr<Peer> *rp = _peers.get(r->identity.address());
if (rp) {
_rootPeers.push_back(*rp);
} else if (r->identity.address() != RR->identity.address()) {
SharedPtr<Peer> newrp(new Peer(RR->identity,r->identity));
_peers.set(r->identity.address(),newrp);
_rootPeers.push_back(newrp);
}
}
}
} // namespace ZeroTier } // namespace ZeroTier

View File

@ -31,10 +31,10 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <map>
#include <vector> #include <vector>
#include <stdexcept> #include <stdexcept>
#include <algorithm> #include <algorithm>
#include <utility>
#include "Constants.hpp" #include "Constants.hpp"
@ -146,6 +146,23 @@ public:
return _world; return _world;
} }
/**
* @return Pair containing world ID and world timestamp (faster than world().id() etc.)
*/
inline std::pair<uint64_t,uint64_t> worldIdentification() const
{
Mutex::Lock _l(_lock);
return std::pair<uint64_t,uint64_t>(_world.id(),_world.timestamp());
}
/**
* Validate new world and update if newer and signature is okay
*
* @param newWorld Potential new world definition revision
* @return True if an update actually occurred
*/
bool worldUpdateIfValid(const World &newWorld);
/** /**
* Clean and flush database * Clean and flush database
*/ */
@ -176,7 +193,7 @@ public:
} }
/** /**
* @return All currently active peers by address * @return All currently active peers by address (unsorted)
*/ */
inline std::vector< std::pair< Address,SharedPtr<Peer> > > allPeers() const inline std::vector< std::pair< Address,SharedPtr<Peer> > > allPeers() const
{ {
@ -187,6 +204,7 @@ public:
private: private:
Identity _getIdentity(const Address &zta); Identity _getIdentity(const Address &zta);
void _saveIdentity(const Identity &id); void _saveIdentity(const Identity &id);
void _setWorld(const World &newWorld);
const RuntimeEnvironment *RR; const RuntimeEnvironment *RR;

View File

@ -55,7 +55,7 @@
/** /**
* The (more than) maximum length of a serialized World * The (more than) maximum length of a serialized World
*/ */
#define ZT_WORLD_MAX_SERIALIZED_LENGTH (((1024 + (32 * ZT_WORLD_MAX_STABLE_ENDPOINTS_PER_ROOT)) * ZT_WORLD_MAX_ROOTS) + ZT_C25519_PUBLIC_KEY_LEN + ZT_C25519_SIGNATURE_LEN + 64) #define ZT_WORLD_MAX_SERIALIZED_LENGTH (((1024 + (32 * ZT_WORLD_MAX_STABLE_ENDPOINTS_PER_ROOT)) * ZT_WORLD_MAX_ROOTS) + ZT_C25519_PUBLIC_KEY_LEN + ZT_C25519_SIGNATURE_LEN + 128)
/** /**
* World ID indicating null / empty World object * World ID indicating null / empty World object
@ -68,15 +68,11 @@
#define ZT_WORLD_ID_TESTNET 1 #define ZT_WORLD_ID_TESTNET 1
/** /**
* World ID for Earth -- its approximate distance from the sun in kilometers * World ID for Earth
* *
* This is the ID for the ZeroTier World used on planet Earth. It is unrelated * This is the ID for the ZeroTier World used on planet Earth. It is unrelated
* to the public network 8056c2e21c000001 of the same name. * to the public network 8056c2e21c000001 of the same name. It was chosen
* * from Earth's approximate distance from the sun in kilometers.
* It's advisable to create a new World for network regions spaced more than
* 2-3 light seconds, since RTT times in excess of 5s are problematic for some
* protocols. Earth could therefore include its low and high orbits, the Moon,
* and nearby Lagrange points.
*/ */
#define ZT_WORLD_ID_EARTH 149604618 #define ZT_WORLD_ID_EARTH 149604618
@ -90,9 +86,24 @@ namespace ZeroTier {
/** /**
* A world definition (formerly known as a root topology) * A world definition (formerly known as a root topology)
* *
* A world consists of a set of root servers and a signature scheme enabling * Think of a World as a single data center. Within this data center a set
* it to be updated going forward. It defines a single ZeroTier VL1 network * of distributed fault tolerant root servers provide stable anchor points
* area within which any device can reach any other. * for a peer to peer network that provides VLAN service. Updates to a world
* definition can be published by signing them with the previous revision's
* signing key, and should be very infrequent.
*
* The maximum data center size is approximately 2.5 cubic light seconds,
* since many protocols have issues with >5s RTT latencies.
*
* ZeroTier operates a World for Earth capable of encompassing the planet, its
* orbits, the Moon (about 1.3 light seconds), and nearby Lagrange points. A
* world ID for Mars and nearby space is defined but not yet used, and a test
* world ID is provided for testing purposes.
*
* If you absolutely must run your own "unofficial" ZeroTier network, please
* define your world IDs above 0xffffffff (4294967295). Code to make a World
* is in mkworld.cpp in the parent directory and must be edited to change
* settings.
*/ */
class World class World
{ {
@ -130,24 +141,28 @@ public:
inline uint64_t timestamp() const throw() { return _ts; } inline uint64_t timestamp() const throw() { return _ts; }
/** /**
* Verify a world update * Check whether a world update should replace this one
* *
* A new world update is valid if it is for the same world ID, is newer, * A new world update is valid if it is for the same world ID, is newer,
* and is signed by the current world's signing key. If this world object * and is signed by the current world's signing key. If this world object
* is null, it can always be updated. * is null, it can always be updated.
* *
* @param update Candidate update * @param update Candidate update
* @param fullSignatureCheck Perform full cryptographic signature check (true == yes, false == skip)
* @return True if update is newer than current and is properly signed * @return True if update is newer than current and is properly signed
*/ */
inline bool verifyUpdate(const World &update) inline bool shouldBeReplacedBy(const World &update,bool fullSignatureCheck)
{ {
if (_id == ZT_WORLD_ID_NULL) if (_id == ZT_WORLD_ID_NULL)
return true; return true;
if ((update._id != _id)||(update._ts <= _ts)) if ((_id == update._id)&&(_ts < update._ts)) {
return false; if (fullSignatureCheck) {
Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> tmp; Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> tmp;
update.serialize(tmp); update.serialize(tmp,true);
return C25519::verify(_updateSigningKey,tmp.data(),tmp.size(),update._signature); return C25519::verify(_updateSigningKey,tmp.data(),tmp.size(),update._signature);
} else return true;
}
return false;
} }
/** /**
@ -156,13 +171,16 @@ public:
inline operator bool() const throw() { return (_id != ZT_WORLD_ID_NULL); } inline operator bool() const throw() { return (_id != ZT_WORLD_ID_NULL); }
template<unsigned int C> template<unsigned int C>
inline void serialize(Buffer<C> &b) const inline void serialize(Buffer<C> &b,bool forSign = false) const
{ {
if (forSign)
b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
b.append((uint8_t)0x01); // version -- only one valid value for now b.append((uint8_t)0x01); // version -- only one valid value for now
b.append((uint64_t)_id); b.append((uint64_t)_id);
b.append((uint64_t)_ts); b.append((uint64_t)_ts);
b.append(_updateSigningKey.data,ZT_C25519_PUBLIC_KEY_LEN); b.append(_updateSigningKey.data,ZT_C25519_PUBLIC_KEY_LEN);
b.append(_signature.data,ZT_C25519_SIGNATURE_LEN); if (!forSign)
b.append(_signature.data,ZT_C25519_SIGNATURE_LEN);
b.append((uint8_t)_roots.size()); b.append((uint8_t)_roots.size());
for(std::vector<Root>::const_iterator r(_roots.begin());r!=_roots.end();++r) { for(std::vector<Root>::const_iterator r(_roots.begin());r!=_roots.end();++r) {
r->identity.serialize(b); r->identity.serialize(b);
@ -170,6 +188,8 @@ public:
for(std::vector<InetAddress>::const_iterator ep(r->stableEndpoints.begin());ep!=r->stableEndpoints.end();++ep) for(std::vector<InetAddress>::const_iterator ep(r->stableEndpoints.begin());ep!=r->stableEndpoints.end();++ep)
ep->serialize(b); ep->serialize(b);
} }
if (forSign)
b.append((uint64_t)0xf7f7f7f7f7f7f7f7ULL);
} }
template<unsigned int C> template<unsigned int C>

16
one.cpp
View File

@ -911,7 +911,6 @@ static void printHelp(const char *cn,FILE *out)
fprintf(out," -v - Show version"ZT_EOL_S); fprintf(out," -v - Show version"ZT_EOL_S);
fprintf(out," -U - Run as unprivileged user (skip privilege check)"ZT_EOL_S); fprintf(out," -U - Run as unprivileged user (skip privilege check)"ZT_EOL_S);
fprintf(out," -p<port> - Port for UDP and TCP/HTTP (default: 9993, 0 for random)"ZT_EOL_S); fprintf(out," -p<port> - Port for UDP and TCP/HTTP (default: 9993, 0 for random)"ZT_EOL_S);
//fprintf(out," -T<path> - Override root topology, do not authenticate or update"ZT_EOL_S);
#ifdef __UNIX_LIKE__ #ifdef __UNIX_LIKE__
fprintf(out," -d - Fork and run as daemon (Unix-ish OSes)"ZT_EOL_S); fprintf(out," -d - Fork and run as daemon (Unix-ish OSes)"ZT_EOL_S);
@ -974,7 +973,6 @@ int main(int argc,char **argv)
if ((strstr(argv[0],"zerotier-cli"))||(strstr(argv[0],"ZEROTIER-CLI"))) if ((strstr(argv[0],"zerotier-cli"))||(strstr(argv[0],"ZEROTIER-CLI")))
return cli(argc,argv); return cli(argc,argv);
std::string overrideRootTopology;
std::string homeDir; std::string homeDir;
unsigned int port = ZT_DEFAULT_PORT; unsigned int port = ZT_DEFAULT_PORT;
bool skipRootCheck = false; bool skipRootCheck = false;
@ -1001,18 +999,6 @@ int main(int argc,char **argv)
skipRootCheck = true; skipRootCheck = true;
break; break;
case 'T': // Override root topology
if (argv[i][2]) {
if (!OSUtils::readFile(argv[i] + 2,overrideRootTopology)) {
fprintf(stderr,"%s: cannot read root topology from %s"ZT_EOL_S,argv[0],argv[i] + 2);
return 1;
}
} else {
printHelp(argv[0],stdout);
return 1;
}
break;
case 'v': // Display version case 'v': // Display version
printf("%d.%d.%d"ZT_EOL_S,ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION); printf("%d.%d.%d"ZT_EOL_S,ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION);
return 0; return 0;
@ -1169,7 +1155,7 @@ int main(int argc,char **argv)
try { try {
for(;;) { for(;;) {
zt1Service = OneService::newInstance(homeDir.c_str(),port,(overrideRootTopology.length() > 0) ? overrideRootTopology.c_str() : (const char *)0); zt1Service = OneService::newInstance(homeDir.c_str(),port);
switch(zt1Service->run()) { switch(zt1Service->run()) {
case OneService::ONE_STILL_RUNNING: // shouldn't happen, run() won't return until done case OneService::ONE_STILL_RUNNING: // shouldn't happen, run() won't return until done
case OneService::ONE_NORMAL_TERMINATION: case OneService::ONE_NORMAL_TERMINATION:

View File

@ -418,14 +418,13 @@ struct TcpConnection
class OneServiceImpl : public OneService class OneServiceImpl : public OneService
{ {
public: public:
OneServiceImpl(const char *hp,unsigned int port,const char *overrideRootTopology) : OneServiceImpl(const char *hp,unsigned int port) :
_homePath((hp) ? hp : "."), _homePath((hp) ? hp : "."),
_tcpFallbackResolver(ZT_TCP_FALLBACK_RELAY), _tcpFallbackResolver(ZT_TCP_FALLBACK_RELAY),
#ifdef ZT_ENABLE_NETWORK_CONTROLLER #ifdef ZT_ENABLE_NETWORK_CONTROLLER
_controller((SqliteNetworkController *)0), _controller((SqliteNetworkController *)0),
#endif #endif
_phy(this,false,true), _phy(this,false,true),
_overrideRootTopology((overrideRootTopology) ? overrideRootTopology : ""),
_node((Node *)0), _node((Node *)0),
_controlPlane((ControlPlane *)0), _controlPlane((ControlPlane *)0),
_lastDirectReceiveFromGlobal(0), _lastDirectReceiveFromGlobal(0),
@ -550,8 +549,7 @@ public:
SnodeWirePacketSendFunction, SnodeWirePacketSendFunction,
SnodeVirtualNetworkFrameFunction, SnodeVirtualNetworkFrameFunction,
SnodeVirtualNetworkConfigFunction, SnodeVirtualNetworkConfigFunction,
SnodeEventCallback, SnodeEventCallback);
((_overrideRootTopology.length() > 0) ? _overrideRootTopology.c_str() : (const char *)0));
#ifdef ZT_ENABLE_NETWORK_CONTROLLER #ifdef ZT_ENABLE_NETWORK_CONTROLLER
_controller = new SqliteNetworkController(_node,(_homePath + ZT_PATH_SEPARATOR_S + ZT_CONTROLLER_DB_PATH).c_str(),(_homePath + ZT_PATH_SEPARATOR_S + "circuitTestResults.d").c_str()); _controller = new SqliteNetworkController(_node,(_homePath + ZT_PATH_SEPARATOR_S + ZT_CONTROLLER_DB_PATH).c_str(),(_homePath + ZT_PATH_SEPARATOR_S + "circuitTestResults.d").c_str());
@ -1329,7 +1327,6 @@ private:
SqliteNetworkController *_controller; SqliteNetworkController *_controller;
#endif #endif
Phy<OneServiceImpl *> _phy; Phy<OneServiceImpl *> _phy;
std::string _overrideRootTopology;
Node *_node; Node *_node;
InetAddress _v4LocalAddress,_v6LocalAddress; InetAddress _v4LocalAddress,_v6LocalAddress;
PhySocket *_v4UdpSocket; PhySocket *_v4UdpSocket;
@ -1526,7 +1523,7 @@ std::string OneService::autoUpdateUrl()
return std::string(); return std::string();
} }
OneService *OneService::newInstance(const char *hp,unsigned int port,const char *overrideRootTopology) { return new OneServiceImpl(hp,port,overrideRootTopology); } OneService *OneService::newInstance(const char *hp,unsigned int port) { return new OneServiceImpl(hp,port); }
OneService::~OneService() {} OneService::~OneService() {}
} // namespace ZeroTier } // namespace ZeroTier

View File

@ -95,12 +95,10 @@ public:
* *
* @param hp Home path * @param hp Home path
* @param port TCP and UDP port for packets and HTTP control (if 0, pick random port) * @param port TCP and UDP port for packets and HTTP control (if 0, pick random port)
* @param overrideRootTopology String-serialized root topology (for testing, default: NULL)
*/ */
static OneService *newInstance( static OneService *newInstance(
const char *hp, const char *hp,
unsigned int port, unsigned int port);
const char *overrideRootTopology = (const char *)0);
virtual ~OneService(); virtual ~OneService();