summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/ZeroTierOne.h4
-rw-r--r--make-mac.mk6
-rw-r--r--mkworld.cpp153
-rw-r--r--node/IncomingPacket.cpp1
-rw-r--r--node/Node.cpp24
-rw-r--r--node/Node.hpp3
-rw-r--r--node/Packet.hpp6
-rw-r--r--node/Topology.cpp78
-rw-r--r--node/Topology.hpp22
-rw-r--r--node/World.hpp60
-rw-r--r--one.cpp16
-rw-r--r--service/OneService.cpp9
-rw-r--r--service/OneService.hpp4
13 files changed, 281 insertions, 105 deletions
diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h
index 80091f62..f69ab54c 100644
--- a/include/ZeroTierOne.h
+++ b/include/ZeroTierOne.h
@@ -1023,7 +1023,6 @@ typedef int (*ZT_WirePacketSendFunction)(
* @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 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
*/
enum ZT_ResultCode ZT_Node_new(
@@ -1035,8 +1034,7 @@ enum ZT_ResultCode ZT_Node_new(
ZT_WirePacketSendFunction wirePacketSendFunction,
ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction,
- ZT_EventCallback eventCallback,
- const char *overrideRootTopology);
+ ZT_EventCallback eventCallback);
/**
* Delete a node and free all resources it consumes
diff --git a/make-mac.mk b/make-mac.mk
index 6daa6aa0..9fb613d8 100644
--- a/make-mac.mk
+++ b/make-mac.mk
@@ -79,6 +79,10 @@ selftest: $(OBJS) selftest.o
$(CXX) $(CXXFLAGS) -o zerotier-selftest selftest.o $(OBJS) $(LIBS)
$(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
mac-dist-pkg: FORCE
packagesbuild "ext/installfiles/mac/ZeroTier One.pkgproj"
@@ -93,7 +97,7 @@ official: FORCE
make ZT_OFFICIAL_RELEASE=1 mac-dist-pkg
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
install-mac-tap: FORCE
diff --git a/mkworld.cpp b/mkworld.cpp
new file mode 100644
index 00000000..2b41d735
--- /dev/null
+++ b/mkworld.cpp
@@ -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;
+}
diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp
index 9fcc2e49..39abe720 100644
--- a/node/IncomingPacket.cpp
+++ b/node/IncomingPacket.cpp
@@ -33,7 +33,6 @@
#include "../include/ZeroTierOne.h"
#include "Constants.hpp"
-#include "Defaults.hpp"
#include "RuntimeEnvironment.hpp"
#include "IncomingPacket.hpp"
#include "Topology.hpp"
diff --git a/node/Node.cpp b/node/Node.cpp
index 1eb21914..7496b045 100644
--- a/node/Node.cpp
+++ b/node/Node.cpp
@@ -46,7 +46,6 @@
#include "Address.hpp"
#include "Identity.hpp"
#include "SelfAwareness.hpp"
-#include "Defaults.hpp"
const struct sockaddr_storage ZT_SOCKADDR_NULL = {0};
@@ -64,8 +63,7 @@ Node::Node(
ZT_WirePacketSendFunction wirePacketSendFunction,
ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction,
- ZT_EventCallback eventCallback,
- const char *overrideRootTopology) :
+ ZT_EventCallback eventCallback) :
_RR(this),
RR(&_RR),
_uPtr(uptr),
@@ -125,21 +123,6 @@ Node::Node(
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);
}
@@ -609,12 +592,11 @@ enum ZT_ResultCode ZT_Node_new(
ZT_WirePacketSendFunction wirePacketSendFunction,
ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction,
- ZT_EventCallback eventCallback,
- const char *overrideRootTopology)
+ ZT_EventCallback eventCallback)
{
*node = (ZT_Node *)0;
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;
} catch (std::bad_alloc &exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
diff --git a/node/Node.hpp b/node/Node.hpp
index 0ae176c0..c7038ed4 100644
--- a/node/Node.hpp
+++ b/node/Node.hpp
@@ -71,8 +71,7 @@ public:
ZT_WirePacketSendFunction wirePacketSendFunction,
ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction,
- ZT_EventCallback eventCallback,
- const char *overrideRootTopology);
+ ZT_EventCallback eventCallback);
~Node();
diff --git a/node/Packet.hpp b/node/Packet.hpp
index 958d0f3e..939d84a5 100644
--- a/node/Packet.hpp
+++ b/node/Packet.hpp
@@ -540,6 +540,8 @@ public:
* <[...] binary serialized identity (see Identity)>
* <[1] destination address type>
* [<[...] 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
* is used to push an identity to a new peer.
@@ -564,8 +566,8 @@ public:
* <[2] software revision (of responder)>
* <[1] destination address type (for this OK, not copied from HELLO)>
* [<[...] destination address>]
- * <[8] 64-bit world ID of current world>
- * <[8] 64-bit timestamp of current world>
+ * <[8] 64-bit world ID of current world (of responder)>
+ * <[8] 64-bit timestamp of current world (of responder)>
*
* ERROR has no payload.
*/
diff --git a/node/Topology.cpp b/node/Topology.cpp
index 5aedae86..0cf4cfe8 100644
--- a/node/Topology.cpp
+++ b/node/Topology.cpp
@@ -42,23 +42,6 @@ Topology::Topology(const RuntimeEnvironment *renv) :
RR(renv),
_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"));
const uint8_t *all = reinterpret_cast<const uint8_t *>(alls.data());
RR->node->dataStoreDelete("peers.save");
@@ -97,19 +80,24 @@ Topology::Topology(const RuntimeEnvironment *renv) :
clean(RR->node->now());
- 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);
- }
+ std::string dsWorld(RR->node->dataStoreGet("world"));
+ World cachedWorld;
+ try {
+ Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> dswtmp(dsWorld.data(),dsWorld.length());
+ cachedWorld.deserialize(dswtmp,0);
+ } catch ( ... ) {
+ cachedWorld = World(); // clear 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 (cachedWorld.shouldBeReplacedBy(defaultWorld,false)) {
+ _setWorld(defaultWorld);
+ if (dsWorld.length() > 0)
+ RR->node->dataStoreDelete("world");
+ } else _setWorld(cachedWorld);
}
Topology::~Topology()
@@ -283,6 +271,16 @@ keep_searching_for_roots:
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)
{
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
diff --git a/node/Topology.hpp b/node/Topology.hpp
index ed8f3d86..3abc27e4 100644
--- a/node/Topology.hpp
+++ b/node/Topology.hpp
@@ -31,10 +31,10 @@
#include <stdio.h>
#include <string.h>
-#include <map>
#include <vector>
#include <stdexcept>
#include <algorithm>
+#include <utility>
#include "Constants.hpp"
@@ -147,6 +147,23 @@ public:
}
/**
+ * @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
*/
void clean(uint64_t now);
@@ -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
{
@@ -187,6 +204,7 @@ public:
private:
Identity _getIdentity(const Address &zta);
void _saveIdentity(const Identity &id);
+ void _setWorld(const World &newWorld);
const RuntimeEnvironment *RR;
diff --git a/node/World.hpp b/node/World.hpp
index 0d26021f..7ccd2c53 100644
--- a/node/World.hpp
+++ b/node/World.hpp
@@ -55,7 +55,7 @@
/**
* 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
@@ -68,15 +68,11 @@
#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
- * to the public network 8056c2e21c000001 of the same name.
- *
- * 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.
+ * to the public network 8056c2e21c000001 of the same name. It was chosen
+ * from Earth's approximate distance from the sun in kilometers.
*/
#define ZT_WORLD_ID_EARTH 149604618
@@ -90,9 +86,24 @@ namespace ZeroTier {
/**
* A world definition (formerly known as a root topology)
*
- * A world consists of a set of root servers and a signature scheme enabling
- * it to be updated going forward. It defines a single ZeroTier VL1 network
- * area within which any device can reach any other.
+ * Think of a World as a single data center. Within this data center a set
+ * of distributed fault tolerant root servers provide stable anchor points
+ * 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
{
@@ -130,24 +141,28 @@ public:
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,
* and is signed by the current world's signing key. If this world object
* is null, it can always be updated.
*
* @param update Candidate update
+ * @param fullSignatureCheck Perform full cryptographic signature check (true == yes, false == skip)
* @return True if update is newer than current and is properly signed
*/
- inline bool verifyUpdate(const World &update)
+ inline bool shouldBeReplacedBy(const World &update,bool fullSignatureCheck)
{
if (_id == ZT_WORLD_ID_NULL)
return true;
- if ((update._id != _id)||(update._ts <= _ts))
- return false;
- Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> tmp;
- update.serialize(tmp);
- return C25519::verify(_updateSigningKey,tmp.data(),tmp.size(),update._signature);
+ if ((_id == update._id)&&(_ts < update._ts)) {
+ if (fullSignatureCheck) {
+ Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> tmp;
+ update.serialize(tmp,true);
+ 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); }
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((uint64_t)_id);
b.append((uint64_t)_ts);
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());
for(std::vector<Root>::const_iterator r(_roots.begin());r!=_roots.end();++r) {
r->identity.serialize(b);
@@ -170,6 +188,8 @@ public:
for(std::vector<InetAddress>::const_iterator ep(r->stableEndpoints.begin());ep!=r->stableEndpoints.end();++ep)
ep->serialize(b);
}
+ if (forSign)
+ b.append((uint64_t)0xf7f7f7f7f7f7f7f7ULL);
}
template<unsigned int C>
diff --git a/one.cpp b/one.cpp
index a4d5190c..c8661fda 100644
--- a/one.cpp
+++ b/one.cpp
@@ -911,7 +911,6 @@ static void printHelp(const char *cn,FILE *out)
fprintf(out," -v - Show version"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," -T<path> - Override root topology, do not authenticate or update"ZT_EOL_S);
#ifdef __UNIX_LIKE__
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")))
return cli(argc,argv);
- std::string overrideRootTopology;
std::string homeDir;
unsigned int port = ZT_DEFAULT_PORT;
bool skipRootCheck = false;
@@ -1001,18 +999,6 @@ int main(int argc,char **argv)
skipRootCheck = true;
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
printf("%d.%d.%d"ZT_EOL_S,ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION);
return 0;
@@ -1169,7 +1155,7 @@ int main(int argc,char **argv)
try {
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()) {
case OneService::ONE_STILL_RUNNING: // shouldn't happen, run() won't return until done
case OneService::ONE_NORMAL_TERMINATION:
diff --git a/service/OneService.cpp b/service/OneService.cpp
index 071a2cbc..6b28c41e 100644
--- a/service/OneService.cpp
+++ b/service/OneService.cpp
@@ -418,14 +418,13 @@ struct TcpConnection
class OneServiceImpl : public OneService
{
public:
- OneServiceImpl(const char *hp,unsigned int port,const char *overrideRootTopology) :
+ OneServiceImpl(const char *hp,unsigned int port) :
_homePath((hp) ? hp : "."),
_tcpFallbackResolver(ZT_TCP_FALLBACK_RELAY),
#ifdef ZT_ENABLE_NETWORK_CONTROLLER
_controller((SqliteNetworkController *)0),
#endif
_phy(this,false,true),
- _overrideRootTopology((overrideRootTopology) ? overrideRootTopology : ""),
_node((Node *)0),
_controlPlane((ControlPlane *)0),
_lastDirectReceiveFromGlobal(0),
@@ -550,8 +549,7 @@ public:
SnodeWirePacketSendFunction,
SnodeVirtualNetworkFrameFunction,
SnodeVirtualNetworkConfigFunction,
- SnodeEventCallback,
- ((_overrideRootTopology.length() > 0) ? _overrideRootTopology.c_str() : (const char *)0));
+ SnodeEventCallback);
#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());
@@ -1329,7 +1327,6 @@ private:
SqliteNetworkController *_controller;
#endif
Phy<OneServiceImpl *> _phy;
- std::string _overrideRootTopology;
Node *_node;
InetAddress _v4LocalAddress,_v6LocalAddress;
PhySocket *_v4UdpSocket;
@@ -1526,7 +1523,7 @@ std::string OneService::autoUpdateUrl()
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() {}
} // namespace ZeroTier
diff --git a/service/OneService.hpp b/service/OneService.hpp
index 70d024bc..2f76ebaa 100644
--- a/service/OneService.hpp
+++ b/service/OneService.hpp
@@ -95,12 +95,10 @@ public:
*
* @param hp Home path
* @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(
const char *hp,
- unsigned int port,
- const char *overrideRootTopology = (const char *)0);
+ unsigned int port);
virtual ~OneService();