diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 80091f623..f69ab54cd 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 6daa6aa0b..9fb613d88 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 000000000..2b41d735f --- /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 . + * + * -- + * + * 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 +#include +#include +#include + +#include +#include +#include + +#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 &roots,const C25519::Pair &signWith) + { + WorldMaker w; + w._id = id; + w._ts = ts; + w._updateSigningKey = sk; + w._roots = roots; + + Buffer 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 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 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 9fcc2e494..39abe720b 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 1eb219145..7496b045b 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(new ZeroTier::Node(now,uptr,dataStoreGetFunction,dataStorePutFunction,wirePacketSendFunction,virtualNetworkFrameFunction,virtualNetworkConfigFunction,eventCallback,overrideRootTopology)); + *node = reinterpret_cast(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 0ae176c0d..c7038ed40 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 958d0f3e7..939d84a51 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 5aedae868..0cf4cfe84 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 dswtmp(dsWorld.data(),dsWorld.length()); - _world.deserialize(dswtmp,0); - } catch ( ... ) { - _world = World(); // set to null if cached world is invalid - } - { - World defaultWorld; - Buffer 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(alls.data()); RR->node->dataStoreDelete("peers.save"); @@ -97,19 +80,24 @@ Topology::Topology(const RuntimeEnvironment *renv) : clean(RR->node->now()); - for(std::vector::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 *rp = _peers.get(r->identity.address()); - if (rp) { - _rootPeers.push_back(*rp); - } else if (r->identity.address() != RR->identity.address()) { - SharedPtr 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 dswtmp(dsWorld.data(),dsWorld.length()); + cachedWorld.deserialize(dswtmp,0); + } catch ( ... ) { + cachedWorld = World(); // clear if cached world is invalid } + World defaultWorld; + { + Buffer 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::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 *rp = _peers.get(r->identity.address()); + if (rp) { + _rootPeers.push_back(*rp); + } else if (r->identity.address() != RR->identity.address()) { + SharedPtr 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 ed8f3d865..3abc27e4a 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -31,10 +31,10 @@ #include #include -#include #include #include #include +#include #include "Constants.hpp" @@ -146,6 +146,23 @@ public: return _world; } + /** + * @return Pair containing world ID and world timestamp (faster than world().id() etc.) + */ + inline std::pair worldIdentification() const + { + Mutex::Lock _l(_lock); + return std::pair(_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 */ @@ -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 > > 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 0d26021f2..7ccd2c536 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 tmp; - update.serialize(tmp); - return C25519::verify(_updateSigningKey,tmp.data(),tmp.size(),update._signature); + if ((_id == update._id)&&(_ts < update._ts)) { + if (fullSignatureCheck) { + Buffer 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 - inline void serialize(Buffer &b) const + inline void serialize(Buffer &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::const_iterator r(_roots.begin());r!=_roots.end();++r) { r->identity.serialize(b); @@ -170,6 +188,8 @@ public: for(std::vector::const_iterator ep(r->stableEndpoints.begin());ep!=r->stableEndpoints.end();++ep) ep->serialize(b); } + if (forSign) + b.append((uint64_t)0xf7f7f7f7f7f7f7f7ULL); } template diff --git a/one.cpp b/one.cpp index a4d5190c9..c8661fda4 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 for UDP and TCP/HTTP (default: 9993, 0 for random)"ZT_EOL_S); - //fprintf(out," -T - 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 071a2cbce..6b28c41e6 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 _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 70d024bc1..2f76ebaa2 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();