summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--node/IncomingPacket.cpp44
-rw-r--r--node/Node.cpp16
-rw-r--r--node/Peer.cpp8
-rw-r--r--node/Peer.hpp62
-rw-r--r--node/Topology.cpp165
-rw-r--r--node/Topology.hpp35
6 files changed, 72 insertions, 258 deletions
diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp
index 95091985..ad250d18 100644
--- a/node/IncomingPacket.cpp
+++ b/node/IncomingPacket.cpp
@@ -181,12 +181,8 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR)
return true;
}
- // Do we already have this peer?
SharedPtr<Peer> peer(RR->topology->getPeer(id.address()));
if (peer) {
- // Check to make sure this isn't a colliding identity (different key,
- // but same address). The odds are spectacularly low but it could happen.
- // Could also be a sign of someone doing something nasty.
if (peer->identity() != id) {
unsigned char key[ZT_PEER_SECRET_KEY_LENGTH];
if (RR->identity.agree(id,key,ZT_PEER_SECRET_KEY_LENGTH)) {
@@ -208,33 +204,8 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR)
} else if (!dearmor(peer->key())) {
LOG("rejected HELLO from %s(%s): packet failed authentication",source().toString().c_str(),_remoteAddress.toString().c_str());
return true;
- } // else continue and respond
+ }
} else {
- // If we don't have a peer record on file, check the identity cache (if
- // we have one) to see if we have a cached identity. Then check that for
- // collision before adding a new peer.
- Identity alreadyHaveCachedId(RR->topology->getIdentity(id.address()));
- if ((alreadyHaveCachedId)&&(id != alreadyHaveCachedId)) {
- unsigned char key[ZT_PEER_SECRET_KEY_LENGTH];
- if (RR->identity.agree(id,key,ZT_PEER_SECRET_KEY_LENGTH)) {
- if (dearmor(key)) { // ensure packet is authentic, otherwise drop
- LOG("rejected HELLO from %s(%s): address already claimed",source().toString().c_str(),_remoteAddress.toString().c_str());
- Packet outp(source(),RR->identity.address(),Packet::VERB_ERROR);
- outp.append((unsigned char)Packet::VERB_HELLO);
- outp.append(packetId());
- outp.append((unsigned char)Packet::ERROR_IDENTITY_COLLISION);
- outp.armor(key,true);
- _fromSock->send(_remoteAddress,outp.data(),outp.size());
- } else {
- LOG("rejected HELLO from %s(%s): packet failed authentication",source().toString().c_str(),_remoteAddress.toString().c_str());
- }
- } else {
- LOG("rejected HELLO from %s(%s): key agreement failed",source().toString().c_str(),_remoteAddress.toString().c_str());
- }
- return true;
- } // else continue since identity is already known and matches
-
- // If this is a new peer, learn it
SharedPtr<Peer> newPeer(new Peer(RR->identity,id));
if (!dearmor(newPeer->key())) {
LOG("rejected HELLO from %s(%s): packet failed authentication",source().toString().c_str(),_remoteAddress.toString().c_str());
@@ -376,29 +347,26 @@ bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,const SharedPtr<Peer>
{
try {
if (payloadLength() == ZT_ADDRESS_LENGTH) {
- Identity id(RR->topology->getIdentity(Address(payload(),ZT_ADDRESS_LENGTH)));
- if (id) {
- Packet outp(source(),RR->identity.address(),Packet::VERB_OK);
+ SharedPtr<Peer> queried(RR->topology->getPeer(Address(payload(),ZT_ADDRESS_LENGTH)));
+ if (queried) {
+ Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK);
outp.append((unsigned char)Packet::VERB_WHOIS);
outp.append(packetId());
- id.serialize(outp,false);
+ queried->identity().serialize(outp,false);
outp.armor(peer->key(),true);
_fromSock->send(_remoteAddress,outp.data(),outp.size());
- //TRACE("sent WHOIS response to %s for %s",source().toString().c_str(),Address(payload(),ZT_ADDRESS_LENGTH).toString().c_str());
} else {
- Packet outp(source(),RR->identity.address(),Packet::VERB_ERROR);
+ Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR);
outp.append((unsigned char)Packet::VERB_WHOIS);
outp.append(packetId());
outp.append((unsigned char)Packet::ERROR_OBJ_NOT_FOUND);
outp.append(payload(),ZT_ADDRESS_LENGTH);
outp.armor(peer->key(),true);
_fromSock->send(_remoteAddress,outp.data(),outp.size());
- //TRACE("sent WHOIS ERROR to %s for %s (not found)",source().toString().c_str(),Address(payload(),ZT_ADDRESS_LENGTH).toString().c_str());
}
} else {
TRACE("dropped WHOIS from %s(%s): missing or invalid address",source().toString().c_str(),_remoteAddress.toString().c_str());
}
-
peer->receive(RR,_fromSock,_remoteAddress,hops(),packetId(),Packet::VERB_WHOIS,0,Packet::VERB_NOP,Utils::now());
} catch ( ... ) {
TRACE("dropped WHOIS from %s(%s): unexpected exception",source().toString().c_str(),_remoteAddress.toString().c_str());
diff --git a/node/Node.cpp b/node/Node.cpp
index 2f97c999..4673312a 100644
--- a/node/Node.cpp
+++ b/node/Node.cpp
@@ -377,7 +377,7 @@ Node::ReasonForTermination Node::run()
Utils::lockDownFile(identitySecretPath.c_str(),false);
}
- // Make sure networks.d exists
+ // Make sure networks.d exists (used by NodeConfig to remember networks)
{
std::string networksDotD(RR->homePath + ZT_PATH_SEPARATOR_S + "networks.d");
#ifdef __WINDOWS__
@@ -386,13 +386,22 @@ Node::ReasonForTermination Node::run()
mkdir(networksDotD.c_str(),0700);
#endif
}
+ // Make sure iddb.d exists (used by Topology to remember identities)
+ {
+ std::string iddbDotD(RR->homePath + ZT_PATH_SEPARATOR_S + "iddb.d");
+#ifdef __WINDOWS__
+ CreateDirectoryA(iddbDotD.c_str(),NULL);
+#else
+ mkdir(iddbDotD.c_str(),0700);
+#endif
+ }
RR->http = new HttpClient();
RR->antiRec = new AntiRecursion();
RR->mc = new Multicaster(RR);
RR->sw = new Switch(RR);
RR->sm = new SocketManager(impl->udpPort,impl->tcpPort,&_CBztTraffic,RR);
- RR->topology = new Topology(RR,Utils::fileExists((RR->homePath + ZT_PATH_SEPARATOR_S + "iddb.d").c_str()));
+ RR->topology = new Topology(RR);
try {
RR->nc = new NodeConfig(RR);
} catch (std::exception &exc) {
@@ -443,6 +452,9 @@ Node::ReasonForTermination Node::run()
return impl->terminateBecause(Node::NODE_UNRECOVERABLE_ERROR,"invalid root-topology format");
}
}
+
+ // Delete peers.persist if it exists -- legacy file, just takes up space
+ Utils::rm(std::string(RR->homePath + ZT_PATH_SEPARATOR_S + "peers.persist").c_str());
} catch (std::bad_alloc &exc) {
return impl->terminateBecause(Node::NODE_UNRECOVERABLE_ERROR,"memory allocation failure");
} catch (std::runtime_error &exc) {
diff --git a/node/Peer.cpp b/node/Peer.cpp
index 94b8f29a..540a83a1 100644
--- a/node/Peer.cpp
+++ b/node/Peer.cpp
@@ -42,7 +42,7 @@ Peer::Peer() :
_lastReceive(0),
_lastUnicastFrame(0),
_lastMulticastFrame(0),
- __lastAnnouncedTo(0),
+ _lastAnnouncedTo(0),
_vMajor(0),
_vMinor(0),
_vRevision(0),
@@ -55,7 +55,7 @@ Peer::Peer(const Identity &myIdentity,const Identity &peerIdentity)
_lastReceive(0),
_lastUnicastFrame(0),
_lastMulticastFrame(0),
- __lastAnnouncedTo(0),
+ _lastAnnouncedTo(0),
_vMajor(0),
_vMinor(0),
_vRevision(0),
@@ -118,8 +118,8 @@ void Peer::receive(
* supernodes and network controllers. The other place this is done
* is in rescanMulticastGroups() in Network, but that only sends something
* if a network's multicast groups change. */
- if ((now - __lastAnnouncedTo) >= ((ZT_MULTICAST_LIKE_EXPIRE / 2) - 1000)) {
- __lastAnnouncedTo = now;
+ if ((now - _lastAnnouncedTo) >= ((ZT_MULTICAST_LIKE_EXPIRE / 2) - 1000)) {
+ _lastAnnouncedTo = now;
Packet outp(_id.address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE);
std::vector< SharedPtr<Network> > networks(RR->nc->networks());
diff --git a/node/Peer.hpp b/node/Peer.hpp
index ead14311..3bb2a56e 100644
--- a/node/Peer.hpp
+++ b/node/Peer.hpp
@@ -50,9 +50,6 @@
#include "NonCopyable.hpp"
#include "Mutex.hpp"
-// Comment out to disable peers.persist
-//#define ZT_PEER_SERIALIZATION_VERSION 13
-
namespace ZeroTier {
/**
@@ -248,7 +245,7 @@ public:
/**
* @return Time we last announced state TO this peer, such as multicast LIKEs
*/
- inline uint64_t lastAnnouncedTo() const throw() { return __lastAnnouncedTo; }
+ inline uint64_t lastAnnouncedTo() const throw() { return _lastAnnouncedTo; }
/**
* @param now Current time
@@ -405,61 +402,6 @@ public:
else return std::pair<InetAddress,InetAddress>();
}
-#ifdef ZT_PEER_SERIALIZATION_VERSION
- template<unsigned int C>
- inline void serialize(Buffer<C> &b) const
- {
- Mutex::Lock _l(_lock);
-
- b.append((unsigned char)ZT_PEER_SERIALIZATION_VERSION);
- _id.serialize(b,false);
- b.append(_key,sizeof(_key));
- b.append(_lastUsed);
- b.append(_lastReceive);
- b.append(_lastUnicastFrame);
- b.append(_lastMulticastFrame);
- b.append((uint16_t)_vProto);
- b.append((uint16_t)_vMajor);
- b.append((uint16_t)_vMinor);
- b.append((uint16_t)_vRevision);
- b.append((uint16_t)_latency);
- b.append((uint16_t)_paths.size());
- for(std::vector<Path>::const_iterator p(_paths.begin());p!=_paths.end();++p)
- p->serialize(b);
- }
- template<unsigned int C>
- inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
- {
- unsigned int p = startAt;
-
- if (b[p++] != ZT_PEER_SERIALIZATION_VERSION)
- throw std::invalid_argument("Peer: deserialize(): version mismatch");
-
- Mutex::Lock _l(_lock);
-
- p += _id.deserialize(b,p);
- memcpy(_key,b.field(p,sizeof(_key)),sizeof(_key)); p += sizeof(_key);
- _lastUsed = b.template at<uint64_t>(p); p += sizeof(uint64_t);
- _lastReceive = b.template at<uint64_t>(p); p += sizeof(uint64_t);
- _lastUnicastFrame = b.template at<uint64_t>(p); p += sizeof(uint64_t);
- _lastMulticastFrame = b.template at<uint64_t>(p); p += sizeof(uint64_t);
- __lastAnnouncedTo = 0;
- _vProto = b.template at<uint16_t>(p); p += sizeof(uint16_t);
- _vMajor = b.template at<uint16_t>(p); p += sizeof(uint16_t);
- _vMinor = b.template at<uint16_t>(p); p += sizeof(uint16_t);
- _vRevision = b.template at<uint16_t>(p); p += sizeof(uint16_t);
- _latency = b.template at<uint16_t>(p); p += sizeof(uint16_t);
- unsigned int npaths = (unsigned int)b.template at<uint16_t>(p); p += sizeof(uint16_t);
- _paths.clear();
- for(unsigned int i=0;i<npaths;++i) {
- _paths.push_back(Path());
- p += _paths.back().deserialize(b,p);
- }
-
- return (p - startAt);
- }
-#endif // ZT_PEER_SERIALIZATION_VERSION
-
private:
void _announceMulticastGroups(const RuntimeEnvironment *RR,uint64_t now);
@@ -472,7 +414,7 @@ private:
volatile uint64_t _lastReceive; // direct or indirect
volatile uint64_t _lastUnicastFrame;
volatile uint64_t _lastMulticastFrame;
- volatile uint64_t __lastAnnouncedTo; // not persisted -- shouldn't be unless Multicaster state is also persisted
+ volatile uint64_t _lastAnnouncedTo;
volatile uint16_t _vProto;
volatile uint16_t _vMajor;
volatile uint16_t _vMinor;
diff --git a/node/Topology.cpp b/node/Topology.cpp
index 10e5d9c7..c8f14a2c 100644
--- a/node/Topology.cpp
+++ b/node/Topology.cpp
@@ -38,19 +38,15 @@
namespace ZeroTier {
-Topology::Topology(const RuntimeEnvironment *renv,bool enablePermanentIdCaching) :
+Topology::Topology(const RuntimeEnvironment *renv) :
RR(renv),
+ _idCacheBase(renv->homePath + ZT_PATH_SEPARATOR_S + "iddb.d"),
_amSupernode(false)
{
- if (enablePermanentIdCaching)
- _idCacheBase = (RR->homePath + ZT_PATH_SEPARATOR_S + "iddb.d");
- _loadPeers();
}
Topology::~Topology()
{
- clean(Utils::now());
- _dumpPeers();
}
void Topology::setSupernodes(const std::map< Identity,std::vector< std::pair<InetAddress,bool> > > &sn)
@@ -108,57 +104,49 @@ SharedPtr<Peer> Topology::addPeer(const SharedPtr<Peer> &peer)
TRACE("BUG: addNewPeer() caught and ignored attempt to add peer for self");
throw std::logic_error("cannot add peer for self");
}
+
uint64_t now = Utils::now();
Mutex::Lock _l(_activePeers_m);
+
SharedPtr<Peer> p(_activePeers.insert(std::pair< Address,SharedPtr<Peer> >(peer->address(),peer)).first->second);
p->use(now);
- saveIdentity(p->identity());
+ _saveIdentity(p->identity());
+
return p;
}
-SharedPtr<Peer> Topology::getPeer(const Address &zta) const
+SharedPtr<Peer> Topology::getPeer(const Address &zta)
{
if (zta == RR->identity.address()) {
TRACE("BUG: ignored attempt to getPeer() for self, returned NULL");
return SharedPtr<Peer>();
}
+
uint64_t now = Utils::now();
Mutex::Lock _l(_activePeers_m);
- std::map< Address,SharedPtr<Peer> >::const_iterator ap(_activePeers.find(zta));
- if ((ap != _activePeers.end())&&(ap->second)) {
- ap->second->use(now);
- return ap->second;
- }
- return SharedPtr<Peer>();
-}
-Identity Topology::getIdentity(const Address &zta)
-{
- SharedPtr<Peer> p(getPeer(zta));
- if (p)
- return p->identity();
- if (_idCacheBase.length()) {
- std::string idcPath(_idCacheBase + ZT_PATH_SEPARATOR_S + zta.toString());
- std::string ids;
- if (Utils::readFile(idcPath.c_str(),ids)) {
- try {
- return Identity(ids);
- } catch ( ... ) {} // ignore invalid IDs
- }
+ SharedPtr<Peer> &ap = _activePeers[zta];
+
+ if (ap) {
+ ap->use(now);
+ return ap;
}
- return Identity();
-}
-void Topology::saveIdentity(const Identity &id)
-{
- if ((id)&&(_idCacheBase.length())) {
- std::string idcPath(_idCacheBase + ZT_PATH_SEPARATOR_S + id.address().toString());
- if (!Utils::fileExists(idcPath.c_str()))
- Utils::writeFile(idcPath.c_str(),id.toString(false));
+ Identity id(_getIdentity(zta));
+ if (id) {
+ try {
+ ap = SharedPtr<Peer>(new Peer(RR->identity,id));
+ ap->use(now);
+ return ap;
+ } catch ( ... ) {} // invalid identity?
}
+
+ _activePeers.erase(zta);
+
+ return SharedPtr<Peer>();
}
-SharedPtr<Peer> Topology::getBestSupernode(const Address *avoid,unsigned int avoidCount,bool strictAvoid) const
+SharedPtr<Peer> Topology::getBestSupernode(const Address *avoid,unsigned int avoidCount,bool strictAvoid)
{
SharedPtr<Peer> bestSupernode;
uint64_t now = Utils::now();
@@ -261,9 +249,9 @@ void Topology::clean(uint64_t now)
Mutex::Lock _l(_activePeers_m);
Mutex::Lock _l2(_supernodes_m);
for(std::map< Address,SharedPtr<Peer> >::iterator p(_activePeers.begin());p!=_activePeers.end();) {
- if (((now - p->second->lastUsed()) >= ZT_PEER_IN_MEMORY_EXPIRATION)&&(!_supernodeAddresses.count(p->second->address())))
+ if (((now - p->second->lastUsed()) >= ZT_PEER_IN_MEMORY_EXPIRATION)&&(!_supernodeAddresses.count(p->second->address()))) {
_activePeers.erase(p++);
- else {
+ } else {
p->second->clean(now);
++p;
}
@@ -288,101 +276,24 @@ bool Topology::authenticateRootTopology(const Dictionary &rt)
}
}
-void Topology::_dumpPeers()
+Identity Topology::_getIdentity(const Address &zta)
{
-#ifdef ZT_PEER_SERIALIZATION_VERSION
- Buffer<ZT_PEER_WRITE_BUF_SIZE> buf;
- std::string pdpath(RR->homePath + ZT_PATH_SEPARATOR_S + "peers.persist");
- Mutex::Lock _l(_activePeers_m);
-
- FILE *pd = fopen(pdpath.c_str(),"wb");
- if (!pd)
- return;
- if (fwrite("ZTPD0",5,1,pd) != 1) {
- fclose(pd);
- Utils::rm(pdpath);
- return;
- }
-
- for(std::map< Address,SharedPtr<Peer> >::iterator p(_activePeers.begin());p!=_activePeers.end();++p) {
+ std::string idcPath(_idCacheBase + ZT_PATH_SEPARATOR_S + zta.toString());
+ std::string ids;
+ if (Utils::readFile(idcPath.c_str(),ids)) {
try {
- p->second->serialize(buf);
- if (buf.size() >= (ZT_PEER_WRITE_BUF_SIZE / 2)) {
- if (fwrite(buf.data(),buf.size(),1,pd) != 1) {
- fclose(pd);
- Utils::rm(pdpath);
- buf.burn();
- return;
- }
- buf.clear();
- buf.burn();
- }
- } catch ( ... ) {
- fclose(pd);
- Utils::rm(pdpath);
- buf.burn();
- return;
- }
+ return Identity(ids);
+ } catch ( ... ) {} // ignore invalid IDs
}
-
- if (buf.size()) {
- if (fwrite(buf.data(),buf.size(),1,pd) != 1) {
- fclose(pd);
- Utils::rm(pdpath);
- buf.burn();
- return;
- }
- buf.burn();
- }
-
- fclose(pd);
- buf.burn();
-
- Utils::lockDownFile(pdpath.c_str(),false);
-#endif // ZT_PEER_SERIALIZATION_VERSION
+ return Identity();
}
-void Topology::_loadPeers()
+void Topology::_saveIdentity(const Identity &id)
{
- std::string pdpath(RR->homePath + ZT_PATH_SEPARATOR_S + "peers.persist");
-
-#ifdef ZT_PEER_SERIALIZATION_VERSION
- Buffer<ZT_PEER_WRITE_BUF_SIZE> buf;
- Mutex::Lock _l(_activePeers_m);
-
- _activePeers.clear();
-
- FILE *pd = fopen(pdpath.c_str(),"rb");
- if (!pd)
- return;
-
- try {
- char magic[5];
- if ((fread(magic,5,1,pd) == 1)&&(!memcmp("ZTPD0",magic,5))) {
- long rlen = 0;
- do {
- long rlen = (long)fread(const_cast<char *>(static_cast<const char *>(buf.data())) + buf.size(),1,ZT_PEER_WRITE_BUF_SIZE - buf.size(),pd);
- if (rlen < 0) rlen = 0;
- buf.setSize(buf.size() + (unsigned int)rlen);
- unsigned int ptr = 0;
- while ((ptr < (ZT_PEER_WRITE_BUF_SIZE / 2))&&(ptr < buf.size())) {
- SharedPtr<Peer> p(new Peer());
- ptr += p->deserialize(buf,ptr);
- _activePeers[p->address()] = p;
- saveIdentity(p->identity());
- }
- buf.behead(ptr);
- } while (rlen > 0);
- }
- } catch ( ... ) {
- _activePeers.clear();
+ if (id) {
+ std::string idcPath(_idCacheBase + ZT_PATH_SEPARATOR_S + id.address().toString());
+ Utils::writeFile(idcPath.c_str(),id.toString(false));
}
-
- fclose(pd);
- buf.burn();
-#endif // ZT_PEER_SERIALIZATION_VERSION
-
- Utils::rm(pdpath);
}
} // namespace ZeroTier
diff --git a/node/Topology.hpp b/node/Topology.hpp
index 8ab10074..f58d7486 100644
--- a/node/Topology.hpp
+++ b/node/Topology.hpp
@@ -58,7 +58,7 @@ class RuntimeEnvironment;
class Topology
{
public:
- Topology(const RuntimeEnvironment *renv,bool enablePermanentIdCaching);
+ Topology(const RuntimeEnvironment *renv);
~Topology();
/**
@@ -95,26 +95,7 @@ public:
* @param zta ZeroTier address of peer
* @return Peer or NULL if not found
*/
- SharedPtr<Peer> getPeer(const Address &zta) const;
-
- /**
- * Get an identity if cached or available in a peer record
- *
- * @param zta ZeroTier address
- * @return Identity or NULL-identity if not found
- */
- Identity getIdentity(const Address &zta);
-
- /**
- * Save identity in permanent store, or do nothing if disabled
- *
- * This is called automatically by addPeer(), so it should not need to be
- * called manually anywhere else. The private part of the identity, if
- * present, is NOT cached by this.
- *
- * @param id Identity to save
- */
- void saveIdentity(const Identity &id);
+ SharedPtr<Peer> getPeer(const Address &zta);
/**
* @return Vector of peers that are supernodes
@@ -139,7 +120,7 @@ public:
*
* @return Supernode with lowest latency or NULL if none
*/
- inline SharedPtr<Peer> getBestSupernode() const
+ inline SharedPtr<Peer> getBestSupernode()
{
return getBestSupernode((const Address *)0,0,false);
}
@@ -156,7 +137,7 @@ public:
* @param strictAvoid If false, consider avoided supernodes anyway if no non-avoid supernodes are available
* @return Supernode or NULL if none
*/
- SharedPtr<Peer> getBestSupernode(const Address *avoid,unsigned int avoidCount,bool strictAvoid) const;
+ SharedPtr<Peer> getBestSupernode(const Address *avoid,unsigned int avoidCount,bool strictAvoid);
/**
* @param zta ZeroTier address
@@ -373,12 +354,12 @@ public:
static bool authenticateRootTopology(const Dictionary &rt);
private:
- const RuntimeEnvironment *RR;
+ Identity _getIdentity(const Address &zta);
+ void _saveIdentity(const Identity &id);
- void _dumpPeers();
- void _loadPeers();
+ const RuntimeEnvironment *RR;
- std::string _idCacheBase; // empty if identity caching disabled
+ std::string _idCacheBase;
std::map< Address,SharedPtr<Peer> > _activePeers;
Mutex _activePeers_m;