More threading improvements in root, more DNS TXT and multicast work (in progress)

This commit is contained in:
Adam Ierymenko 2019-09-16 10:33:59 -07:00
parent 9f9032ae36
commit e08fc81397
No known key found for this signature in database
GPG Key ID: C8877CF2D7A5D7F3
10 changed files with 317 additions and 95 deletions

View File

@ -129,6 +129,67 @@ public:
} }
} }
/**
* Make a DNS name contiaining a public key that can sign DNS entries
*
* This generates the initial fields of a DNS name that contains an
* encoded public key. Users may append any domain suffix to this name.
*
* @return First field(s) of DNS name
*/
static inline Str makeSecureDnsName(const uint8_t p384SigningKeyPublic[ZT_ECC384_PUBLIC_KEY_SIZE])
{
uint8_t tmp[ZT_ECC384_PUBLIC_KEY_SIZE+2];
memcpy(tmp,p384SigningKeyPublic,ZT_ECC384_PUBLIC_KEY_SIZE);
const uint16_t crc = Utils::crc16(tmp,ZT_ECC384_PUBLIC_KEY_SIZE);
tmp[ZT_ECC384_PUBLIC_KEY_SIZE-2] = (uint8_t)(crc >> 8);
tmp[ZT_ECC384_PUBLIC_KEY_SIZE-1] = (uint8_t)(crc);
Str name;
char b32[128];
Utils::b32e(tmp,35,b32,sizeof(b32));
name << b32;
Utils::b32e(tmp + 35,(ZT_ECC384_PUBLIC_KEY_SIZE+2) - 35,b32,sizeof(b32));
name << '.';
name << b32;
return name;
}
/**
* @return True if a key was found and successfully decoded
*/
static inline bool decodeSecureDnsName(const char *name,uint8_t p384SigningKeyPublic[ZT_ECC384_PUBLIC_KEY_SIZE])
{
uint8_t b32[128];
unsigned int b32ptr = 0;
char tmp[1024];
Utils::scopy(tmp,sizeof(tmp),name);
bool ok = false;
for(char *saveptr=(char *)0,*p=Utils::stok(tmp,".",&saveptr);p;p=Utils::stok((char *)0,".",&saveptr)) {
if (b32ptr >= sizeof(b32))
break;
int s = Utils::b32d(p,b32 + b32ptr,sizeof(b32) - b32ptr);
if (s > 0) {
b32ptr += (unsigned int)s;
if (b32ptr > 2) {
const uint16_t crc = Utils::crc16(b32,b32ptr);
if ((b32[b32ptr-2] == (uint8_t)(crc >> 8))&&(b32[b32ptr-1] == (uint8_t)(crc & 0xff))) {
ok = true;
break;
}
}
} else break;
}
if (ok) {
if (b32ptr == (ZT_ECC384_PUBLIC_KEY_SIZE + 2)) {
memcpy(p384SigningKeyPublic,b32,ZT_ECC384_PUBLIC_KEY_SIZE);
return true;
}
}
return false;
}
/** /**
* Make DNS TXT records for this locator * Make DNS TXT records for this locator
* *
@ -184,7 +245,7 @@ public:
* now contains the contents of the supplied TXT records. * now contains the contents of the supplied TXT records.
*/ */
template<typename I> template<typename I>
inline bool decodeTxtRecords(I start,I end,const uint8_t p384SigningKeyPublic[ZT_ECC384_PUBLIC_KEY_SIZE]) inline bool decodeTxtRecords(const Str &dnsName,I start,I end)
{ {
uint8_t dec[256],s384[48]; uint8_t dec[256],s384[48];
try { try {
@ -204,12 +265,13 @@ public:
for(std::vector<Str>::const_iterator i(txtRecords.begin());i!=txtRecords.end();++i) for(std::vector<Str>::const_iterator i(txtRecords.begin());i!=txtRecords.end();++i)
tmp->append(dec,Utils::b64d(i->c_str() + 2,dec,sizeof(dec))); tmp->append(dec,Utils::b64d(i->c_str() + 2,dec,sizeof(dec)));
if (tmp->size() <= ZT_ECC384_SIGNATURE_SIZE) { uint8_t p384SigningKeyPublic[ZT_ECC384_PUBLIC_KEY_SIZE];
return false; if (decodeSecureDnsName(dnsName.c_str(),p384SigningKeyPublic)) {
} if (tmp->size() <= ZT_ECC384_SIGNATURE_SIZE)
SHA384(s384,tmp->data(),tmp->size() - ZT_ECC384_SIGNATURE_SIZE); return false;
if (!ECC384ECDSAVerify(p384SigningKeyPublic,s384,((const uint8_t *)tmp->data()) + (tmp->size() - ZT_ECC384_SIGNATURE_SIZE))) { SHA384(s384,tmp->data(),tmp->size() - ZT_ECC384_SIGNATURE_SIZE);
return false; if (!ECC384ECDSAVerify(p384SigningKeyPublic,s384,((const uint8_t *)tmp->data()) + (tmp->size() - ZT_ECC384_SIGNATURE_SIZE)))
return false;
} }
deserialize(*tmp,0); deserialize(*tmp,0);

View File

@ -33,6 +33,7 @@
#include "Network.hpp" #include "Network.hpp"
#include "Trace.hpp" #include "Trace.hpp"
#include "ScopedPtr.hpp" #include "ScopedPtr.hpp"
#include "Locator.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -172,6 +173,7 @@ ZT_ResultCode Node::processVirtualNetworkFrame(
} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND; } else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
} }
#if 0
struct _processBackgroundTasks_ping_eachRoot struct _processBackgroundTasks_ping_eachRoot
{ {
Hashtable< void *,bool > roots; Hashtable< void *,bool > roots;
@ -179,7 +181,7 @@ struct _processBackgroundTasks_ping_eachRoot
void *tPtr; void *tPtr;
bool online; bool online;
inline void operator()(const Root &root,const SharedPtr<Peer> &peer) ZT_ALWAYS_INLINE void operator()(const Root &root,const SharedPtr<Peer> &peer)
{ {
unsigned int v4SendCount = 0,v6SendCount = 0; unsigned int v4SendCount = 0,v6SendCount = 0;
peer->ping(tPtr,now,v4SendCount,v6SendCount); peer->ping(tPtr,now,v4SendCount,v6SendCount);
@ -204,6 +206,7 @@ struct _processBackgroundTasks_ping_eachRoot
roots.set((void *)peer.ptr(),true); roots.set((void *)peer.ptr(),true);
} }
}; };
#endif
struct _processBackgroundTasks_ping_eachPeer struct _processBackgroundTasks_ping_eachPeer
{ {
@ -211,7 +214,7 @@ struct _processBackgroundTasks_ping_eachPeer
void *tPtr; void *tPtr;
Hashtable< void *,bool > *roots; Hashtable< void *,bool > *roots;
inline void operator()(const SharedPtr<Peer> &peer) ZT_ALWAYS_INLINE void operator()(const SharedPtr<Peer> &peer)
{ {
if (!roots->contains((void *)peer.ptr())) { if (!roots->contains((void *)peer.ptr())) {
unsigned int v4SendCount = 0,v6SendCount = 0; unsigned int v4SendCount = 0,v6SendCount = 0;
@ -234,22 +237,24 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64
if ((now - _lastPing) >= ZT_PEER_PING_PERIOD) { if ((now - _lastPing) >= ZT_PEER_PING_PERIOD) {
_lastPing = now; _lastPing = now;
try { try {
#if 0
_processBackgroundTasks_ping_eachRoot rf; _processBackgroundTasks_ping_eachRoot rf;
rf.now = now; rf.now = now;
rf.tPtr = tptr; rf.tPtr = tptr;
rf.online = false; rf.online = false;
RR->topology->eachRoot(rf); RR->topology->eachRoot(rf);
#endif
_processBackgroundTasks_ping_eachPeer pf; _processBackgroundTasks_ping_eachPeer pf;
pf.now = now; pf.now = now;
pf.tPtr = tptr; pf.tPtr = tptr;
pf.roots = &rf.roots; //pf.roots = &rf.roots;
RR->topology->eachPeer(pf); RR->topology->eachPeer(pf);
if (rf.online != _online) { //if (rf.online != _online) {
_online = rf.online; // _online = rf.online;
postEvent(tptr,_online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE); // postEvent(tptr,_online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE);
} //}
} catch ( ... ) { } catch ( ... ) {
return ZT_RESULT_FATAL_ERROR_INTERNAL; return ZT_RESULT_FATAL_ERROR_INTERNAL;
} }

View File

@ -151,14 +151,35 @@ public:
return ((*this) << a.toString(tmp)); return ((*this) << a.toString(tmp));
} }
ZT_ALWAYS_INLINE Str &append(const char *s,const unsigned int max)
{
if (likely(s != (const char *)0)) {
unsigned long l = _l;
unsigned int c = 0;
while (*s) {
if (c++ >= max) break;
if (unlikely(l >= ZT_STR_CAPACITY)) {
_s[ZT_STR_CAPACITY] = 0;
_l = ZT_STR_CAPACITY;
throw ZT_EXCEPTION_OUT_OF_BOUNDS;
}
_s[l++] = *s;
++s;
}
_s[l] = 0;
_l = (uint8_t)l;
}
return *this;
}
ZT_ALWAYS_INLINE operator bool() const { return (_l != 0); } ZT_ALWAYS_INLINE operator bool() const { return (_l != 0); }
ZT_ALWAYS_INLINE bool operator==(const Str &s) const { return ((_l == s._l)&&(strcmp(_s,s._s) == 0)); } ZT_ALWAYS_INLINE bool operator==(const Str &s) const { return ((_l == s._l)&&(memcmp(_s,s._s,_l) == 0)); }
ZT_ALWAYS_INLINE bool operator!=(const Str &s) const { return ((_l != s._l)||(strcmp(_s,s._s) != 0)); } ZT_ALWAYS_INLINE bool operator!=(const Str &s) const { return ((_l != s._l)||(memcmp(_s,s._s,_l) != 0)); }
ZT_ALWAYS_INLINE bool operator<(const Str &s) const { return ((_l < s._l)&&(strcmp(_s,s._s) < 0)); } ZT_ALWAYS_INLINE bool operator<(const Str &s) const { return ( (_l < s._l) ? true : ((_l == s._l) ? (memcmp(_s,s._s,_l) < 0) : false) ); }
ZT_ALWAYS_INLINE bool operator>(const Str &s) const { return ((_l > s._l)&&(strcmp(_s,s._s) > 0)); } ZT_ALWAYS_INLINE bool operator>(const Str &s) const { return (s < *this); }
ZT_ALWAYS_INLINE bool operator<=(const Str &s) const { return ((_l <= s._l)&&(strcmp(_s,s._s) <= 0)); } ZT_ALWAYS_INLINE bool operator<=(const Str &s) const { return !(s < *this); }
ZT_ALWAYS_INLINE bool operator>=(const Str &s) const { return ((_l >= s._l)&&(strcmp(_s,s._s) >= 0)); } ZT_ALWAYS_INLINE bool operator>=(const Str &s) const { return !(*this < s); }
ZT_ALWAYS_INLINE bool operator==(const char *s) const { return (strcmp(_s,s) == 0); } ZT_ALWAYS_INLINE bool operator==(const char *s) const { return (strcmp(_s,s) == 0); }
ZT_ALWAYS_INLINE bool operator!=(const char *s) const { return (strcmp(_s,s) != 0); } ZT_ALWAYS_INLINE bool operator!=(const char *s) const { return (strcmp(_s,s) != 0); }
@ -167,6 +188,16 @@ public:
ZT_ALWAYS_INLINE bool operator<=(const char *s) const { return (strcmp(_s,s) <= 0); } ZT_ALWAYS_INLINE bool operator<=(const char *s) const { return (strcmp(_s,s) <= 0); }
ZT_ALWAYS_INLINE bool operator>=(const char *s) const { return (strcmp(_s,s) >= 0); } ZT_ALWAYS_INLINE bool operator>=(const char *s) const { return (strcmp(_s,s) >= 0); }
ZT_ALWAYS_INLINE unsigned long hashCode() const
{
const char *p = _s;
unsigned long h = 0;
char c;
while ((c = *(p++)))
h = (31 * h) + (unsigned long)c;
return h;
}
private: private:
uint8_t _l; uint8_t _l;
char _s[ZT_STR_CAPACITY+1]; char _s[ZT_STR_CAPACITY+1];

View File

@ -21,6 +21,7 @@
#include <stdexcept> #include <stdexcept>
#include <algorithm> #include <algorithm>
#include <utility> #include <utility>
#include <set>
#include "Constants.hpp" #include "Constants.hpp"
#include "../include/ZeroTierOne.h" #include "../include/ZeroTierOne.h"
@ -32,8 +33,9 @@
#include "Mutex.hpp" #include "Mutex.hpp"
#include "InetAddress.hpp" #include "InetAddress.hpp"
#include "Hashtable.hpp" #include "Hashtable.hpp"
#include "Root.hpp" #include "Locator.hpp"
#include "SharedPtr.hpp" #include "SharedPtr.hpp"
#include "ScopedPtr.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -65,7 +67,7 @@ public:
{ {
SharedPtr<Peer> np; SharedPtr<Peer> np;
{ {
Mutex::Lock _l(_peers_m); Mutex::Lock _l(_peers_l);
SharedPtr<Peer> &hp = _peers[peer->address()]; SharedPtr<Peer> &hp = _peers[peer->address()];
if (!hp) if (!hp)
hp = peer; hp = peer;
@ -86,11 +88,12 @@ public:
if (zta == _myIdentity.address()) if (zta == _myIdentity.address())
return SharedPtr<Peer>(); return SharedPtr<Peer>();
Mutex::Lock l1(_peers_m); Mutex::Lock l1(_peers_l);
const SharedPtr<Peer> *const ap = _peers.get(zta); const SharedPtr<Peer> *const ap = _peers.get(zta);
if (ap) if (ap)
return *ap; return *ap;
#if 0
Mutex::Lock l2(_roots_m); Mutex::Lock l2(_roots_m);
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) {
if (r->address() == zta) { if (r->address() == zta) {
@ -101,6 +104,7 @@ public:
} catch ( ... ) {} } catch ( ... ) {}
} }
} }
#endif
return SharedPtr<Peer>(); return SharedPtr<Peer>();
} }
@ -115,7 +119,7 @@ public:
if (zta == _myIdentity.address()) { if (zta == _myIdentity.address()) {
return _myIdentity; return _myIdentity;
} else { } else {
Mutex::Lock _l(_peers_m); Mutex::Lock _l(_peers_l);
const SharedPtr<Peer> *const ap = _peers.get(zta); const SharedPtr<Peer> *const ap = _peers.get(zta);
if (ap) if (ap)
return (*ap)->identity(); return (*ap)->identity();
@ -132,7 +136,7 @@ public:
*/ */
ZT_ALWAYS_INLINE SharedPtr<Path> getPath(const int64_t l,const InetAddress &r) ZT_ALWAYS_INLINE SharedPtr<Path> getPath(const int64_t l,const InetAddress &r)
{ {
Mutex::Lock _l(_paths_m); Mutex::Lock _l(_paths_l);
SharedPtr<Path> &p = _paths[Path::HashKey(l,r)]; SharedPtr<Path> &p = _paths[Path::HashKey(l,r)];
if (!p) if (!p)
p.set(new Path(l,r)); p.set(new Path(l,r));
@ -145,11 +149,13 @@ public:
*/ */
ZT_ALWAYS_INLINE bool isRoot(const Identity &id) const ZT_ALWAYS_INLINE bool isRoot(const Identity &id) const
{ {
#if 0
Mutex::Lock l(_roots_m); Mutex::Lock l(_roots_m);
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) {
if (r->is(id)) if (r->is(id))
return true; return true;
} }
#endif
return false; return false;
} }
@ -159,7 +165,7 @@ public:
ZT_ALWAYS_INLINE void doPeriodicTasks(int64_t now) ZT_ALWAYS_INLINE void doPeriodicTasks(int64_t now)
{ {
{ {
Mutex::Lock _l1(_peers_m); Mutex::Lock _l1(_peers_l);
Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers); Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers);
Address *a = (Address *)0; Address *a = (Address *)0;
SharedPtr<Peer> *p = (SharedPtr<Peer> *)0; SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
@ -170,7 +176,7 @@ public:
} }
} }
{ {
Mutex::Lock _l(_paths_m); Mutex::Lock _l(_paths_l);
Hashtable< Path::HashKey,SharedPtr<Path> >::Iterator i(_paths); Hashtable< Path::HashKey,SharedPtr<Path> >::Iterator i(_paths);
Path::HashKey *k = (Path::HashKey *)0; Path::HashKey *k = (Path::HashKey *)0;
SharedPtr<Path> *p = (SharedPtr<Path> *)0; SharedPtr<Path> *p = (SharedPtr<Path> *)0;
@ -188,7 +194,7 @@ public:
ZT_ALWAYS_INLINE unsigned long countActive(int64_t now) const ZT_ALWAYS_INLINE unsigned long countActive(int64_t now) const
{ {
unsigned long cnt = 0; unsigned long cnt = 0;
Mutex::Lock _l(_peers_m); Mutex::Lock _l(_peers_l);
Hashtable< Address,SharedPtr<Peer> >::Iterator i(const_cast<Topology *>(this)->_peers); Hashtable< Address,SharedPtr<Peer> >::Iterator i(const_cast<Topology *>(this)->_peers);
Address *a = (Address *)0; Address *a = (Address *)0;
SharedPtr<Peer> *p = (SharedPtr<Peer> *)0; SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
@ -212,7 +218,7 @@ public:
template<typename F> template<typename F>
ZT_ALWAYS_INLINE void eachPeer(F f) ZT_ALWAYS_INLINE void eachPeer(F f)
{ {
Mutex::Lock l(_peers_m); Mutex::Lock l(_peers_l);
Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers); Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers);
Address *a = (Address *)0; Address *a = (Address *)0;
SharedPtr<Peer> *p = (SharedPtr<Peer> *)0; SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
@ -221,6 +227,7 @@ public:
} }
} }
#if 0
/** /**
* Apply a function or function object to all roots * Apply a function or function object to all roots
* *
@ -237,7 +244,7 @@ public:
SharedPtr<Peer> rp; SharedPtr<Peer> rp;
for(std::vector<Root>::const_iterator i(_roots.begin());i!=_roots.end();++i) { for(std::vector<Root>::const_iterator i(_roots.begin());i!=_roots.end();++i) {
{ {
Mutex::Lock l2(_peers_m); Mutex::Lock l2(_peers_l);
const SharedPtr<Peer> *const ap = _peers.get(i->address()); const SharedPtr<Peer> *const ap = _peers.get(i->address());
if (ap) { if (ap) {
rp = *ap; rp = *ap;
@ -256,7 +263,7 @@ public:
* @param now Current time * @param now Current time
* @return Best/fastest currently connected root or NULL if none * @return Best/fastest currently connected root or NULL if none
*/ */
ZT_ALWAYS_INLINE SharedPtr<Peer> root(const int64_t now) inline SharedPtr<Peer> root(const int64_t now)
{ {
Mutex::Lock l(_bestRoot_m); Mutex::Lock l(_bestRoot_m);
if ((!_bestRoot)||((now - _lastRankedBestRoot) >= ZT_FIND_BEST_ROOT_PERIOD)) { if ((!_bestRoot)||((now - _lastRankedBestRoot) >= ZT_FIND_BEST_ROOT_PERIOD)) {
@ -266,7 +273,7 @@ public:
long bestQuality = 2147483647; long bestQuality = 2147483647;
for(std::vector<Root>::const_iterator i(_roots.begin());i!=_roots.end();++i) { for(std::vector<Root>::const_iterator i(_roots.begin());i!=_roots.end();++i) {
{ {
Mutex::Lock l2(_peers_m); Mutex::Lock l2(_peers_l);
const SharedPtr<Peer> *const ap = _peers.get(i->address()); const SharedPtr<Peer> *const ap = _peers.get(i->address());
if (ap) { if (ap) {
rp = *ap; rp = *ap;
@ -287,6 +294,54 @@ public:
} }
return _bestRoot; return _bestRoot;
} }
#endif
ZT_ALWAYS_INLINE SharedPtr<Peer> root(const int64_t now)
{
return SharedPtr<Peer>();
}
/**
* @return Names of dynamic roots currently known by the system
*/
ZT_ALWAYS_INLINE std::vector<Str> dynamicRootNames() const
{
Mutex::Lock l(_dynamicRoots_l);
return _dynamicRoots.keys();
}
/**
* Set or update a static root entry
*
* @param id Static root's identity
* @param addrs Static root's IP address(es)
*/
ZT_ALWAYS_INLINE void setStaticRoot(const Identity &id,const std::vector<InetAddress> &addrs)
{
Mutex::Lock l(_staticRoots_l);
_staticRoots[id] = addrs;
}
/**
* Set or update dynamic root if new locator is newer and valid
*
* This checks internal validity of the new locator including its internal self-signature.
* It does not check any DNS signatures.
*
* @param dnsName DNS name used to retrive root
* @param latestLocator Latest locator
* @return True if latest locator is internally valid and newer
*/
ZT_ALWAYS_INLINE bool setDynamicRoot(const Str &dnsName,const Locator &latestLocator)
{
Mutex::Lock l(_dynamicRoots_l);
Locator &ll = _dynamicRoots[dnsName];
if (ll.timestamp() < latestLocator.timestamp()) {
ll = latestLocator;
return true;
}
return false;
}
/** /**
* Get the best relay to a given address, which may or may not be a root * Get the best relay to a given address, which may or may not be a root
@ -298,15 +353,15 @@ public:
ZT_ALWAYS_INLINE SharedPtr<Peer> findRelayTo(const int64_t now,const Address &toAddr) ZT_ALWAYS_INLINE SharedPtr<Peer> findRelayTo(const int64_t now,const Address &toAddr)
{ {
// TODO: in the future this will check 'mesh-like' relays and if enabled consult LF for other roots (for if this is a root) // TODO: in the future this will check 'mesh-like' relays and if enabled consult LF for other roots (for if this is a root)
return root(now); //return root(now);
} }
/** /**
* @param allPeers vector to fill with all current peers * @param allPeers vector to fill with all current peers
*/ */
ZT_ALWAYS_INLINE void getAllPeers(std::vector< SharedPtr<Peer> > &allPeers) const inline void getAllPeers(std::vector< SharedPtr<Peer> > &allPeers) const
{ {
Mutex::Lock l(_peers_m); Mutex::Lock l(_peers_l);
allPeers.clear(); allPeers.clear();
allPeers.reserve(_peers.size()); allPeers.reserve(_peers.size());
Hashtable< Address,SharedPtr<Peer> >::Iterator i(*(const_cast<Hashtable< Address,SharedPtr<Peer> > *>(&_peers))); Hashtable< Address,SharedPtr<Peer> >::Iterator i(*(const_cast<Hashtable< Address,SharedPtr<Peer> > *>(&_peers)));
@ -385,7 +440,7 @@ public:
/** /**
* Set or clear physical path configuration (called via Node::setPhysicalPathConfiguration) * Set or clear physical path configuration (called via Node::setPhysicalPathConfiguration)
*/ */
ZT_ALWAYS_INLINE void setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig) inline void setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig)
{ {
if (!pathNetwork) { if (!pathNetwork) {
_numConfiguredPhysicalPaths = 0; _numConfiguredPhysicalPaths = 0;
@ -422,17 +477,26 @@ public:
private: private:
const RuntimeEnvironment *const RR; const RuntimeEnvironment *const RR;
const Identity _myIdentity; const Identity _myIdentity;
std::pair<InetAddress,ZT_PhysicalPathConfiguration> _physicalPathConfig[ZT_MAX_CONFIGURABLE_PATHS]; std::pair<InetAddress,ZT_PhysicalPathConfiguration> _physicalPathConfig[ZT_MAX_CONFIGURABLE_PATHS];
unsigned int _numConfiguredPhysicalPaths; unsigned int _numConfiguredPhysicalPaths;
std::vector<Root> _roots;
SharedPtr<Peer> _bestRoot;
int64_t _lastRankedBestRoot;
Hashtable< Address,SharedPtr<Peer> > _peers; Hashtable< Address,SharedPtr<Peer> > _peers;
Hashtable< Path::HashKey,SharedPtr<Path> > _paths; Hashtable< Path::HashKey,SharedPtr<Path> > _paths;
Mutex _roots_m;
Mutex _bestRoot_m; Hashtable< Identity,std::vector<InetAddress> > _staticRoots;
Mutex _peers_m; Hashtable< Str,Locator > _dynamicRoots;
Mutex _paths_m;
//std::vector<Root> _roots;
//SharedPtr<Peer> _bestRoot;
//int64_t _lastRankedBestRoot;
//Mutex _roots_m;
//Mutex _bestRoot_m;
Mutex _peers_l;
Mutex _paths_l;
Mutex _staticRoots_l;
Mutex _dynamicRoots_l;
}; };
} // namespace ZeroTier } // namespace ZeroTier

View File

@ -95,6 +95,49 @@ char *Utils::decimal(unsigned long n,char s[24])
return s; return s;
} }
unsigned short Utils::crc16(const void *buf,unsigned int len)
{
static const uint16_t crc16tab[256]= {
0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,
0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,
0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6,
0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,
0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,
0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d,
0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4,
0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,
0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823,
0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b,
0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12,
0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,
0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41,
0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49,
0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,
0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,
0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f,
0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067,
0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,
0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,
0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d,
0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405,
0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,
0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634,
0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab,
0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,
0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,
0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92,
0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9,
0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,
0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,
0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0
};
uint16_t crc = 0;
const uint8_t *p = (const uint8_t *)buf;
for(unsigned int i=0;i<len;++i)
crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ *(p++)) & 0x00ff];
return crc;
}
unsigned int Utils::unhex(const char *h,void *buf,unsigned int buflen) unsigned int Utils::unhex(const char *h,void *buf,unsigned int buflen)
{ {
unsigned int l = 0; unsigned int l = 0;

View File

@ -68,6 +68,11 @@ public:
*/ */
static char *decimal(unsigned long n,char s[24]); static char *decimal(unsigned long n,char s[24]);
/**
* Compute CRC16-CCITT
*/
static uint16_t crc16(const void *buf,unsigned int len);
/** /**
* Convert an unsigned integer into hex * Convert an unsigned integer into hex
* *

View File

@ -94,10 +94,9 @@ static OneService *volatile zt1Service = (OneService *)0;
static void cliPrintHelp(const char *pn,FILE *out) static void cliPrintHelp(const char *pn,FILE *out)
{ {
fprintf(out, fprintf(out,
"%s version %d.%d.%d build %d (platform %d arch %d)" ZT_EOL_S, "%s version %d.%d.%d build %d" ZT_EOL_S,
PROGRAM_NAME, PROGRAM_NAME,
ZEROTIER_ONE_VERSION_MAJOR, ZEROTIER_ONE_VERSION_MINOR, ZEROTIER_ONE_VERSION_REVISION, ZEROTIER_ONE_VERSION_BUILD, ZEROTIER_ONE_VERSION_MAJOR, ZEROTIER_ONE_VERSION_MINOR, ZEROTIER_ONE_VERSION_REVISION, ZEROTIER_ONE_VERSION_BUILD);
ZT_BUILD_PLATFORM, ZT_BUILD_ARCHITECTURE);
fprintf(out, fprintf(out,
COPYRIGHT_NOTICE ZT_EOL_S COPYRIGHT_NOTICE ZT_EOL_S
LICENSE_GRANT ZT_EOL_S); LICENSE_GRANT ZT_EOL_S);

View File

@ -107,8 +107,10 @@ using json = nlohmann::json;
#ifdef MSG_DONTWAIT #ifdef MSG_DONTWAIT
#define SENDTO_FLAGS MSG_DONTWAIT #define SENDTO_FLAGS MSG_DONTWAIT
#define RECVFROM_FLAGS 0
#else #else
#define SENDTO_FLAGS 0 #define SENDTO_FLAGS 0
#define RECVFROM_FLAGS 0
#endif #endif
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -911,7 +913,7 @@ int main(int argc,char **argv)
memset(&in6,0,sizeof(in6)); memset(&in6,0,sizeof(in6));
for(;;) { for(;;) {
socklen_t sl = sizeof(in6); socklen_t sl = sizeof(in6);
const int pl = (int)recvfrom(s6,pkt.unsafeData(),pkt.capacity(),0,(struct sockaddr *)&in6,&sl); const int pl = (int)recvfrom(s6,pkt.unsafeData(),pkt.capacity(),RECVFROM_FLAGS,(struct sockaddr *)&in6,&sl);
if (pl > 0) { if (pl > 0) {
if (pl >= ZT_PROTO_MIN_FRAGMENT_LENGTH) { if (pl >= ZT_PROTO_MIN_FRAGMENT_LENGTH) {
try { try {
@ -940,7 +942,7 @@ int main(int argc,char **argv)
memset(&in4,0,sizeof(in4)); memset(&in4,0,sizeof(in4));
for(;;) { for(;;) {
socklen_t sl = sizeof(in4); socklen_t sl = sizeof(in4);
const int pl = (int)recvfrom(s4,pkt.unsafeData(),pkt.capacity(),0,(struct sockaddr *)&in4,&sl); const int pl = (int)recvfrom(s4,pkt.unsafeData(),pkt.capacity(),RECVFROM_FLAGS,(struct sockaddr *)&in4,&sl);
if (pl > 0) { if (pl > 0) {
if (pl >= ZT_PROTO_MIN_FRAGMENT_LENGTH) { if (pl >= ZT_PROTO_MIN_FRAGMENT_LENGTH) {
try { try {
@ -986,43 +988,43 @@ int main(int argc,char **argv)
o << '['; o << '[';
try { try {
bool first = true; bool first = true;
std::lock_guard<std::mutex> l(s_peersByIdentity_l); std::lock_guard<std::mutex> l(s_peers_l);
for(auto p=s_peersByIdentity.begin();p!=s_peersByIdentity.end();++p) { for(auto p=s_peers.begin();p!=s_peers.end();++p) {
if (first) if (first)
first = false; first = false;
else o << ','; else o << ',';
o << o <<
"{\"address\":\"" << p->first.address().toString(tmp) << "\"" "{\"address\":\"" << (*p)->id.address().toString(tmp) << "\""
",\"latency\":-1" ",\"latency\":-1"
",\"paths\":["; ",\"paths\":[";
if (p->second->ip4) { if ((*p)->ip4) {
o << o <<
"{\"active\":true" "{\"active\":true"
",\"address\":\"" << p->second->ip4.toIpString(tmp) << "\\/" << p->second->ip4.port() << "\"" ",\"address\":\"" << (*p)->ip4.toIpString(tmp) << "\\/" << (*p)->ip4.port() << "\""
",\"expired\":false" ",\"expired\":false"
",\"lastReceive\":" << p->second->lastReceive << ",\"lastReceive\":" << (*p)->lastReceive <<
",\"lastSend\":" << p->second->lastSend << ",\"lastSend\":" << (*p)->lastSend <<
",\"preferred\":true" ",\"preferred\":true"
",\"trustedPathId\":0}"; ",\"trustedPathId\":0}";
} }
if (p->second->ip6) { if ((*p)->ip6) {
if (p->second->ip4) if ((*p)->ip4)
o << ','; o << ',';
o << o <<
"{\"active\":true" "{\"active\":true"
",\"address\":\"" << p->second->ip6.toIpString(tmp) << "\\/" << p->second->ip6.port() << "\"" ",\"address\":\"" << (*p)->ip6.toIpString(tmp) << "\\/" << (*p)->ip6.port() << "\""
",\"expired\":false" ",\"expired\":false"
",\"lastReceive\":" << p->second->lastReceive << ",\"lastReceive\":" << (*p)->lastReceive <<
",\"lastSend\":" << p->second->lastSend << ",\"lastSend\":" << (*p)->lastSend <<
",\"preferred\":" << ((p->second->ip4) ? "false" : "true") << ",\"preferred\":" << (((*p)->ip4) ? "false" : "true") <<
",\"trustedPathId\":0}"; ",\"trustedPathId\":0}";
} }
o << "]" o << "]"
",\"role\":\"LEAF\"" ",\"role\":\"LEAF\""
",\"version\":\"" << p->second->vMajor << '.' << p->second->vMinor << '.' << p->second->vRev << "\"" ",\"version\":\"" << (*p)->vMajor << '.' << (*p)->vMinor << '.' << (*p)->vRev << "\""
",\"versionMajor\":" << p->second->vMajor << ",\"versionMajor\":" << (*p)->vMajor <<
",\"versionMinor\":" << p->second->vMinor << ",\"versionMinor\":" << (*p)->vMinor <<
",\"versionRev\":" << p->second->vRev << "}"; ",\"versionRev\":" << (*p)->vRev << "}";
} }
} catch ( ... ) {} } catch ( ... ) {}
o << ']'; o << ']';
@ -1146,27 +1148,34 @@ int main(int argc,char **argv)
} }
// Remove expired peers // Remove expired peers
{ try {
std::lock_guard<std::mutex> pbi_l(s_peers_l); std::vector< SharedPtr<RootPeer> > toRemove;
for(auto p=s_peers.begin();p!=s_peers.end();) { toRemove.reserve(1024);
if ((now - (*p)->lastReceive) > ZT_PEER_ACTIVITY_TIMEOUT) { {
{ std::lock_guard<std::mutex> pbi_l(s_peers_l);
std::lock_guard<std::mutex> pbi_l(s_peersByIdentity_l); for(auto p=s_peers.begin();p!=s_peers.end();) {
s_peersByIdentity.erase((*p)->id); if ((now - (*p)->lastReceive) > ZT_PEER_ACTIVITY_TIMEOUT) {
} toRemove.emplace_back(*p);
{ s_peers.erase(p++);
std::lock_guard<std::mutex> pbv_l(s_peersByVirtAddr_l); } else ++p;
auto pbv = s_peersByVirtAddr.find((*p)->id.address()); }
if (pbv != s_peersByVirtAddr.end()) {
pbv->second.erase(*p);
if (pbv->second.empty())
s_peersByVirtAddr.erase(pbv);
}
}
s_peers.erase(p++);
} else ++p;
} }
} for(auto p=toRemove.begin();p!=toRemove.end();++p) {
{
std::lock_guard<std::mutex> pbi_l(s_peersByIdentity_l);
s_peersByIdentity.erase((*p)->id);
}
{
std::lock_guard<std::mutex> pbv_l(s_peersByVirtAddr_l);
auto pbv = s_peersByVirtAddr.find((*p)->id.address());
if (pbv != s_peersByVirtAddr.end()) {
pbv->second.erase(*p);
if (pbv->second.empty())
s_peersByVirtAddr.erase(pbv);
}
}
}
} catch ( ... ) {}
// Remove old rendezvous entries // Remove old rendezvous entries
{ {
@ -1212,17 +1221,16 @@ int main(int argc,char **argv)
if (pf) { if (pf) {
std::vector< SharedPtr<RootPeer> > sp; std::vector< SharedPtr<RootPeer> > sp;
{ {
std::lock_guard<std::mutex> pbi_l(s_peersByIdentity_l); std::lock_guard<std::mutex> pbi_l(s_peers_l);
sp.reserve(s_peersByIdentity.size()); sp.reserve(s_peers.size());
for(auto p=s_peersByIdentity.begin();p!=s_peersByIdentity.end();++p) { for(auto p=s_peers.begin();p!=s_peers.end();++p) {
sp.push_back(p->second); sp.emplace_back(*p);
} }
} }
std::sort(sp.begin(),sp.end(),[](const SharedPtr<RootPeer> &a,const SharedPtr<RootPeer> &b) { return (a->id < b->id); }); std::sort(sp.begin(),sp.end(),[](const SharedPtr<RootPeer> &a,const SharedPtr<RootPeer> &b) { return (a->id < b->id); });
fprintf(pf,"Address %21s %45s %10s %6s %10s" ZT_EOL_S,"IPv4","IPv6","Age(sec)","Vers","Fwd(KiB/s)"); fprintf(pf,"Address %21s %45s %10s %6s %10s" ZT_EOL_S,"IPv4","IPv6","Age(sec)","Vers","Fwd(KiB/s)");
{ {
std::lock_guard<std::mutex> lf_l(s_lastForwardedTo_l);
char ip4[128],ip6[128],ver[128]; char ip4[128],ip6[128],ver[128];
for(auto p=sp.begin();p!=sp.end();++p) { for(auto p=sp.begin();p!=sp.end();++p) {
if ((*p)->ip4) { if ((*p)->ip4) {
@ -1239,9 +1247,11 @@ int main(int argc,char **argv)
} }
OSUtils::ztsnprintf(ver,sizeof(ver),"%d.%d.%d",(*p)->vMajor,(*p)->vMinor,(*p)->vRev); OSUtils::ztsnprintf(ver,sizeof(ver),"%d.%d.%d",(*p)->vMajor,(*p)->vMinor,(*p)->vRev);
double forwardingSpeed = 0.0; double forwardingSpeed = 0.0;
s_lastForwardedTo_l.lock();
auto lft = s_lastForwardedTo.find((*p)->id.address()); auto lft = s_lastForwardedTo.find((*p)->id.address());
if (lft != s_lastForwardedTo.end()) if (lft != s_lastForwardedTo.end())
forwardingSpeed = lft->second.bps.perSecond(now) / 1024.0; forwardingSpeed = lft->second.bps.perSecond(now) / 1024.0;
s_lastForwardedTo_l.unlock();
fprintf(pf,"%.10llx %21s %45s %10.4f %6s %10.4f" ZT_EOL_S, fprintf(pf,"%.10llx %21s %45s %10.4f %6s %10.4f" ZT_EOL_S,
(unsigned long long)(*p)->id.address().toInt(), (unsigned long long)(*p)->id.address().toInt(),
ip4, ip4,
@ -1265,11 +1275,12 @@ int main(int argc,char **argv)
if (sf) { if (sf) {
fprintf(sf,"Uptime (seconds) : %ld" ZT_EOL_S,(long)((now - s_startTime) / 1000)); fprintf(sf,"Uptime (seconds) : %ld" ZT_EOL_S,(long)((now - s_startTime) / 1000));
s_peersByIdentity_l.lock(); s_peersByIdentity_l.lock();
fprintf(sf,"Peers : %llu" ZT_EOL_S,(unsigned long long)s_peersByIdentity.size()); auto peersByIdentitySize = s_peersByIdentity.size();
s_peersByVirtAddr_l.lock();
fprintf(sf,"Virtual Address Collisions : %llu" ZT_EOL_S,(unsigned long long)(s_peersByIdentity.size() - s_peersByVirtAddr.size()));
s_peersByVirtAddr_l.unlock();
s_peersByIdentity_l.unlock(); s_peersByIdentity_l.unlock();
fprintf(sf,"Peers : %llu" ZT_EOL_S,(unsigned long long)peersByIdentitySize);
s_peersByVirtAddr_l.lock();
fprintf(sf,"Virtual Address Collisions : %llu" ZT_EOL_S,(unsigned long long)(peersByIdentitySize - s_peersByVirtAddr.size()));
s_peersByVirtAddr_l.unlock();
s_rendezvousTracking_l.lock(); s_rendezvousTracking_l.lock();
uint64_t unsuccessfulp2p = 0; uint64_t unsuccessfulp2p = 0;
for(auto lr=s_rendezvousTracking.begin();lr!=s_rendezvousTracking.end();++lr) { for(auto lr=s_rendezvousTracking.begin();lr!=s_rendezvousTracking.end();++lr) {

View File

@ -620,6 +620,7 @@ static int testIdentity()
} }
} }
/*
try { try {
std::cout << "[identity] Testing Locator and DNS TXT encoding... "; std::cout.flush(); std::cout << "[identity] Testing Locator and DNS TXT encoding... "; std::cout.flush();
uint8_t dnsPub[ZT_ECC384_PUBLIC_KEY_SIZE],dnsPriv[ZT_ECC384_PRIVATE_KEY_SIZE]; uint8_t dnsPub[ZT_ECC384_PUBLIC_KEY_SIZE],dnsPriv[ZT_ECC384_PRIVATE_KEY_SIZE];
@ -633,7 +634,7 @@ static int testIdentity()
l->sign(*ti); l->sign(*ti);
auto tr = l->makeTxtRecords(dnsPub,dnsPriv); auto tr = l->makeTxtRecords(dnsPub,dnsPriv);
std::unique_ptr<Locator> l2(new Locator()); std::unique_ptr<Locator> l2(new Locator());
if (!l2->decodeTxtRecords(tr.begin(),tr.end(),dnsPub)) { if (!l2->decodeTxtRecords(tr.begin(),tr.end())) {
std::cout << "FAILED (decode TXT records returned false)" ZT_EOL_S; std::cout << "FAILED (decode TXT records returned false)" ZT_EOL_S;
return -1; return -1;
} }
@ -642,6 +643,7 @@ static int testIdentity()
std::cout << "FAILED (threw integer exception " << e << ")" ZT_EOL_S; std::cout << "FAILED (threw integer exception " << e << ")" ZT_EOL_S;
return -1; return -1;
} }
*/
return 0; return 0;
} }