mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-05 20:13:44 +02:00
Work in progress on crypto stuff, refactoring to back out of use of structs for encode/decode as it is questionably portable.
This commit is contained in:
parent
16a3c14c53
commit
2b0127c26d
45 changed files with 909 additions and 1067 deletions
|
@ -93,11 +93,7 @@ endif(WIN32)
|
|||
|
||||
if (
|
||||
CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64" OR
|
||||
CMAKE_SYSTEM_PROCESSOR MATCHES "amd64" OR
|
||||
CMAKE_SYSTEM_PROCESSOR MATCHES "i386" OR
|
||||
CMAKE_SYSTEM_PROCESSOR MATCHES "i486" OR
|
||||
CMAKE_SYSTEM_PROCESSOR MATCHES "i586" OR
|
||||
CMAKE_SYSTEM_PROCESSOR MATCHES "i686"
|
||||
CMAKE_SYSTEM_PROCESSOR MATCHES "amd64"
|
||||
)
|
||||
message("++ Adding SSE and AES-NI flags for processor ${CMAKE_SYSTEM_PROCESSOR}")
|
||||
add_compile_options(-maes -mrdrnd -mpclmul -msse -msse2 -mssse3)
|
||||
|
|
|
@ -29,25 +29,6 @@
|
|||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
/* ZT_PACKED_STRUCT encloses structs whose contents should be bit-packed.
|
||||
* Nearly all compilers support this. These macros detect the compiler and
|
||||
* define it correctly for gcc/icc/clang or MSC. */
|
||||
#ifndef ZT_PACKED_STRUCT
|
||||
#if defined(__GCC__) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || defined(__INTEL_COMPILER) || defined(__clang__)
|
||||
#define ZT_PACKED_STRUCT(D) D __attribute__((packed))
|
||||
#define ZT_PACKED_STRUCT_START
|
||||
#define ZT_PACKED_STRUCT_END __attribute__((packed))
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
#define ZT_PACKED_STRUCT(D) __pragma(pack(push,1)) D __pragma(pack(pop))
|
||||
#define ZT_PACKED_STRUCT_START __pragma(pack(push,1))
|
||||
#define ZT_PACKED_STRUCT_END __pragma(pack(pop))
|
||||
#endif
|
||||
#endif
|
||||
#ifndef ZT_PACKED_STRUCT
|
||||
#error Missing a macro to define ZT_PACKED_STRUCT for your compiler.
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
extern "C" {
|
||||
|
@ -278,7 +259,6 @@ extern "C" {
|
|||
|
||||
/* ----------------------------------------------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
/**
|
||||
* Identity type codes
|
||||
*/
|
||||
|
@ -297,7 +277,7 @@ typedef void ZT_Identity;
|
|||
/**
|
||||
* Full identity fingerprint with address and 384-bit hash of public key(s)
|
||||
*/
|
||||
ZT_PACKED_STRUCT(struct _ZT_Fingerprint
|
||||
typedef struct
|
||||
{
|
||||
/**
|
||||
* Short address (only least significant 40 bits are used)
|
||||
|
@ -308,8 +288,7 @@ ZT_PACKED_STRUCT(struct _ZT_Fingerprint
|
|||
* 384-bit hash of identity public key(s)
|
||||
*/
|
||||
uint8_t hash[48];
|
||||
});
|
||||
typedef struct _ZT_Fingerprint ZT_Fingerprint;
|
||||
} ZT_Fingerprint;
|
||||
|
||||
/**
|
||||
* Credential type IDs
|
||||
|
@ -449,6 +428,8 @@ enum ZT_TraceCredentialRejectionReason
|
|||
ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID = 4
|
||||
};
|
||||
|
||||
#if 0
|
||||
|
||||
/**
|
||||
* Physical path address from a trace event
|
||||
*
|
||||
|
@ -623,6 +604,8 @@ _ZT_TRACE_EVENT_STRUCT_END()
|
|||
#undef _ZT_TRACE_EVENT_STRUCT_START
|
||||
#undef _ZT_TRACE_EVENT_STRUCT_END
|
||||
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/**
|
||||
|
|
11
node/AES.hpp
11
node/AES.hpp
|
@ -23,10 +23,9 @@
|
|||
|
||||
#ifndef ZT_AES_NO_ACCEL
|
||||
#ifdef ZT_ARCH_X64
|
||||
#include <xmmintrin.h>
|
||||
#include <emmintrin.h>
|
||||
#include <smmintrin.h>
|
||||
#include <immintrin.h>
|
||||
#include <wmmintrin.h>
|
||||
#define ZT_AES_AESNI 1
|
||||
#endif
|
||||
#endif
|
||||
|
@ -57,7 +56,7 @@ public:
|
|||
/**
|
||||
* Create an un-initialized AES instance (must call init() before use)
|
||||
*/
|
||||
ZT_INLINE AES() noexcept // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
|
||||
ZT_INLINE AES() noexcept
|
||||
{
|
||||
Utils::memoryLock(this,sizeof(AES));
|
||||
}
|
||||
|
@ -67,7 +66,7 @@ public:
|
|||
*
|
||||
* @param key 256-bit key
|
||||
*/
|
||||
explicit ZT_INLINE AES(const void *const key) noexcept // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
|
||||
explicit ZT_INLINE AES(const void *const key) noexcept
|
||||
{
|
||||
Utils::memoryLock(this,sizeof(AES));
|
||||
this->init(key);
|
||||
|
@ -264,7 +263,7 @@ public:
|
|||
* @param k0 First of two AES instances keyed with K0
|
||||
* @param k1 Second of two AES instances keyed with K1
|
||||
*/
|
||||
ZT_INLINE GMACSIVEncryptor(const AES &k0,const AES &k1) noexcept : // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
|
||||
ZT_INLINE GMACSIVEncryptor(const AES &k0,const AES &k1) noexcept :
|
||||
_gmac(k0),
|
||||
_ctr(k1) {}
|
||||
|
||||
|
@ -383,7 +382,7 @@ public:
|
|||
class GMACSIVDecryptor
|
||||
{
|
||||
public:
|
||||
ZT_INLINE GMACSIVDecryptor(const AES &k0,const AES &k1) noexcept : // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
|
||||
ZT_INLINE GMACSIVDecryptor(const AES &k0,const AES &k1) noexcept :
|
||||
_ctr(k1),
|
||||
_gmac(k0) {}
|
||||
|
||||
|
|
|
@ -107,7 +107,7 @@ public:
|
|||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept { return (unsigned long)_a; }
|
||||
|
||||
ZT_INLINE operator bool() const noexcept { return (_a != 0); } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
|
||||
ZT_INLINE operator bool() const noexcept { return (_a != 0); }
|
||||
|
||||
ZT_INLINE bool operator==(const Address &a) const noexcept { return _a == a._a; }
|
||||
ZT_INLINE bool operator!=(const Address &a) const noexcept { return _a != a._a; }
|
||||
|
|
|
@ -32,6 +32,7 @@ set(core_headers
|
|||
OS.hpp
|
||||
Path.hpp
|
||||
Peer.hpp
|
||||
PeerList.hpp
|
||||
Poly1305.hpp
|
||||
Protocol.hpp
|
||||
RuntimeEnvironment.hpp
|
||||
|
|
|
@ -57,7 +57,7 @@ class Capability : public Credential
|
|||
public:
|
||||
static constexpr ZT_CredentialType credentialType() noexcept { return ZT_CREDENTIAL_TYPE_CAPABILITY; }
|
||||
|
||||
ZT_INLINE Capability() noexcept { memoryZero(this); } // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
|
||||
ZT_INLINE Capability() noexcept { memoryZero(this); }
|
||||
|
||||
/**
|
||||
* @param id Capability ID
|
||||
|
|
|
@ -149,6 +149,11 @@
|
|||
*/
|
||||
#define ZT_PEER_HELLO_INTERVAL 120000LL
|
||||
|
||||
/**
|
||||
* Timeout for peers being alive
|
||||
*/
|
||||
#define ZT_PEER_ALIVE_TIMEOUT ((ZT_PEER_HELLO_INTERVAL * 2) + 5000)
|
||||
|
||||
/**
|
||||
* Global timeout for peers in milliseconds
|
||||
*
|
||||
|
|
|
@ -31,18 +31,19 @@
|
|||
namespace ZeroTier {
|
||||
|
||||
#ifdef __CPP11__
|
||||
struct _MapHasher
|
||||
|
||||
struct intl_MapHasher
|
||||
{
|
||||
template<typename O>
|
||||
std::size_t operator()(const O &obj) const noexcept { return (std::size_t)obj.hashCode(); }
|
||||
std::size_t operator()(const uint64_t i) const noexcept { return (std::size_t)Utils::hash64(i ^ Utils::s_mapNonce); }
|
||||
std::size_t operator()(const int64_t i) const noexcept { return (std::size_t)Utils::hash64((uint64_t)i ^ Utils::s_mapNonce); }
|
||||
std::size_t operator()(const uint32_t i) const noexcept { return (std::size_t)Utils::hash32(i ^ (uint32_t)Utils::s_mapNonce); }
|
||||
std::size_t operator()(const int32_t i) const noexcept { return (std::size_t)Utils::hash32((uint32_t)i ^ (uint32_t)Utils::s_mapNonce); }
|
||||
std::size_t operator()(const uint64_t i) const noexcept { return (std::size_t)Utils::hash64(i + Utils::s_mapNonce); }
|
||||
std::size_t operator()(const int64_t i) const noexcept { return (std::size_t)Utils::hash64((uint64_t)i + Utils::s_mapNonce); }
|
||||
std::size_t operator()(const uint32_t i) const noexcept { return (std::size_t)Utils::hash32(i + (uint32_t)Utils::s_mapNonce); }
|
||||
std::size_t operator()(const int32_t i) const noexcept { return (std::size_t)Utils::hash32((uint32_t)i + (uint32_t)Utils::s_mapNonce); }
|
||||
};
|
||||
|
||||
template<typename K,typename V>
|
||||
class Map : public std::unordered_map< K,V,_MapHasher,std::equal_to<K>,Utils::Mallocator< std::pair<const K,V> > >
|
||||
class Map : public std::unordered_map< K,V,intl_MapHasher,std::equal_to<K>,Utils::Mallocator< std::pair<const K,V> > >
|
||||
{
|
||||
public:
|
||||
ZT_INLINE V *get(const K &key) noexcept
|
||||
|
@ -66,7 +67,14 @@ public:
|
|||
this->emplace(key,value);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename K,typename V>
|
||||
class MultiMap : public std::unordered_multimap< K,V,intl_MapHasher,std::equal_to<K>,Utils::Mallocator< std::pair<const K,V> > >
|
||||
{
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template<typename K,typename V>
|
||||
class Map : public std::map< K,V,std::less<K>,Utils::Mallocator< std::pair<const K,V> > >
|
||||
{
|
||||
|
@ -92,6 +100,12 @@ public:
|
|||
(*this)[key] = value;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename K,typename V>
|
||||
class MultiMap : public std::multimap< K,V,std::less<K>,Utils::Mallocator< std::pair<const K,V> > >
|
||||
{
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template<typename K,typename V>
|
||||
|
|
|
@ -22,10 +22,6 @@
|
|||
#include "FCV.hpp"
|
||||
#include "Containers.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,10 +19,6 @@ Dictionary::Dictionary()
|
|||
{
|
||||
}
|
||||
|
||||
Dictionary::~Dictionary()
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<uint8_t> &Dictionary::operator[](const char *k)
|
||||
{
|
||||
return m_entries[s_toKey(k)];
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
#include "Buf.hpp"
|
||||
#include "Containers.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
|
@ -42,7 +40,6 @@ class Dictionary
|
|||
{
|
||||
public:
|
||||
Dictionary();
|
||||
~Dictionary();
|
||||
|
||||
/**
|
||||
* Get a reference to a value
|
||||
|
|
|
@ -49,7 +49,7 @@ public:
|
|||
*/
|
||||
ZT_INLINE void sending(const uint64_t packetId,const int64_t now) noexcept
|
||||
{
|
||||
_packetIdSent[Utils::hash64(packetId ^ Utils::s_mapNonce) % ZT_EXPECT_BUCKETS].store((uint32_t)(now / ZT_EXPECT_TTL));
|
||||
m_packetIdSent[Utils::hash64(packetId ^ Utils::s_mapNonce) % ZT_EXPECT_BUCKETS].store((uint32_t)(now / ZT_EXPECT_TTL));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -64,12 +64,12 @@ public:
|
|||
*/
|
||||
ZT_INLINE bool expecting(const uint64_t inRePacketId,const int64_t now) noexcept
|
||||
{
|
||||
return (((now / ZT_EXPECT_TTL) - (int64_t)_packetIdSent[(unsigned long)Utils::hash64(inRePacketId ^ Utils::s_mapNonce) % ZT_EXPECT_BUCKETS].exchange(0)) <= 1);
|
||||
return (((now / ZT_EXPECT_TTL) - (int64_t)m_packetIdSent[(unsigned long)Utils::hash64(inRePacketId ^ Utils::s_mapNonce) % ZT_EXPECT_BUCKETS].exchange(0)) <= 1);
|
||||
}
|
||||
|
||||
private:
|
||||
// Each bucket contains a timestamp in units of the max expect duration.
|
||||
std::atomic<uint32_t> _packetIdSent[ZT_EXPECT_BUCKETS];
|
||||
std::atomic<uint32_t> m_packetIdSent[ZT_EXPECT_BUCKETS];
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -49,7 +49,7 @@ public:
|
|||
/**
|
||||
* @return True if this FCV is trivially copyable, which means its type is also.
|
||||
*/
|
||||
static constexpr bool isTriviallyCopyable() noexcept { return isTriviallyCopyable(reinterpret_cast<const T *>(0)); }
|
||||
static constexpr bool isTriviallyCopyable() noexcept { return ZeroTier::isTriviallyCopyable(reinterpret_cast<const T *>(nullptr)); }
|
||||
|
||||
ZT_INLINE FCV() noexcept : _s(0) {} // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
|
||||
ZT_INLINE FCV(const FCV &v) : _s(0) { *this = v; } // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
|
||||
|
|
|
@ -43,15 +43,15 @@ public:
|
|||
*/
|
||||
ZT_INLINE Fingerprint() noexcept { memoryZero(this); } // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
|
||||
|
||||
ZT_INLINE Address address() const noexcept { return Address(_fp.address); }
|
||||
ZT_INLINE const uint8_t *hash() const noexcept { return _fp.hash; }
|
||||
ZT_INLINE ZT_Fingerprint *apiFingerprint() noexcept { return &_fp; }
|
||||
ZT_INLINE const ZT_Fingerprint *apiFingerprint() const noexcept { return &_fp; }
|
||||
ZT_INLINE Address address() const noexcept { return Address(m_cfp.address); }
|
||||
ZT_INLINE const uint8_t *hash() const noexcept { return m_cfp.hash; }
|
||||
ZT_INLINE ZT_Fingerprint *apiFingerprint() noexcept { return &m_cfp; }
|
||||
ZT_INLINE const ZT_Fingerprint *apiFingerprint() const noexcept { return &m_cfp; }
|
||||
|
||||
/**
|
||||
* @return True if hash is not all zero (missing/unspecified)
|
||||
*/
|
||||
ZT_INLINE bool haveHash() const noexcept { return (!Utils::allZero(_fp.hash,sizeof(_fp.hash))); }
|
||||
ZT_INLINE bool haveHash() const noexcept { return (!Utils::allZero(m_cfp.hash, sizeof(m_cfp.hash))); }
|
||||
|
||||
/**
|
||||
* Get a base32-encoded representation of this fingerprint
|
||||
|
@ -62,7 +62,7 @@ public:
|
|||
{
|
||||
uint8_t tmp[48 + 5];
|
||||
address().copyTo(tmp);
|
||||
Utils::copy<48>(tmp + 5,_fp.hash);
|
||||
Utils::copy<48>(tmp + 5, m_cfp.hash);
|
||||
Utils::b32e(tmp,sizeof(tmp),s,ZT_FINGERPRINT_STRING_BUFFER_LENGTH);
|
||||
s[ZT_FINGERPRINT_STRING_BUFFER_LENGTH-1] = 0; // sanity check, ensure always zero terminated
|
||||
}
|
||||
|
@ -78,25 +78,25 @@ public:
|
|||
uint8_t tmp[48 + 5];
|
||||
if (Utils::b32d(s,tmp,sizeof(tmp)) != sizeof(tmp))
|
||||
return false;
|
||||
_fp.address = Address(tmp).toInt();
|
||||
Utils::copy<48>(_fp.hash,tmp + 5);
|
||||
m_cfp.address = Address(tmp).toInt();
|
||||
Utils::copy<48>(m_cfp.hash, tmp + 5);
|
||||
return true;
|
||||
}
|
||||
|
||||
ZT_INLINE void zero() noexcept { memoryZero(this); }
|
||||
ZT_INLINE unsigned long hashCode() const noexcept { return _fp.address; }
|
||||
ZT_INLINE unsigned long hashCode() const noexcept { return m_cfp.address; }
|
||||
|
||||
ZT_INLINE operator bool() const noexcept { return (_fp.address != 0); } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
|
||||
ZT_INLINE operator bool() const noexcept { return (m_cfp.address != 0); } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
|
||||
|
||||
ZT_INLINE bool operator==(const Fingerprint &h) const noexcept { return ((_fp.address == h._fp.address) && (memcmp(_fp.hash,h._fp.hash,ZT_FINGERPRINT_HASH_SIZE) == 0)); }
|
||||
ZT_INLINE bool operator==(const Fingerprint &h) const noexcept { return ((m_cfp.address == h.m_cfp.address) && (memcmp(m_cfp.hash, h.m_cfp.hash, ZT_FINGERPRINT_HASH_SIZE) == 0)); }
|
||||
ZT_INLINE bool operator!=(const Fingerprint &h) const noexcept { return !(*this == h); }
|
||||
ZT_INLINE bool operator<(const Fingerprint &h) const noexcept { return ((_fp.address < h._fp.address) || ((_fp.address == h._fp.address) && (memcmp(_fp.hash,h._fp.hash,ZT_FINGERPRINT_HASH_SIZE) < 0))); }
|
||||
ZT_INLINE bool operator<(const Fingerprint &h) const noexcept { return ((m_cfp.address < h.m_cfp.address) || ((m_cfp.address == h.m_cfp.address) && (memcmp(m_cfp.hash, h.m_cfp.hash, ZT_FINGERPRINT_HASH_SIZE) < 0))); }
|
||||
ZT_INLINE bool operator>(const Fingerprint &h) const noexcept { return (h < *this); }
|
||||
ZT_INLINE bool operator<=(const Fingerprint &h) const noexcept { return !(h < *this); }
|
||||
ZT_INLINE bool operator>=(const Fingerprint &h) const noexcept { return !(*this < h); }
|
||||
|
||||
private:
|
||||
ZT_Fingerprint _fp;
|
||||
ZT_Fingerprint m_cfp;
|
||||
};
|
||||
|
||||
static_assert(sizeof(Fingerprint) == sizeof(ZT_Fingerprint),"Fingerprint should be the same size as the underlying C ZT_Fingerprint");
|
||||
|
|
|
@ -176,8 +176,8 @@ const Identity Identity::NIL;
|
|||
|
||||
bool Identity::generate(const Type t)
|
||||
{
|
||||
_type = t;
|
||||
_hasPrivate = true;
|
||||
m_type = t;
|
||||
m_hasPrivate = true;
|
||||
|
||||
switch(t) {
|
||||
case C25519: {
|
||||
|
@ -186,9 +186,9 @@ bool Identity::generate(const Type t)
|
|||
uint8_t digest[64];
|
||||
char *const genmem = new char[ZT_V0_IDENTITY_GEN_MEMORY];
|
||||
do {
|
||||
C25519::generateSatisfying(identityV0ProofOfWorkCriteria(digest,genmem),_pub.c25519,_priv.c25519);
|
||||
_address.setTo(digest + 59);
|
||||
} while (_address.isReserved());
|
||||
C25519::generateSatisfying(identityV0ProofOfWorkCriteria(digest,genmem), m_pub.c25519, m_priv.c25519);
|
||||
m_address.setTo(digest + 59);
|
||||
} while (m_address.isReserved());
|
||||
delete[] genmem;
|
||||
_computeHash();
|
||||
} break;
|
||||
|
@ -201,21 +201,21 @@ bool Identity::generate(const Type t)
|
|||
// Loop until we pass the PoW criteria. The nonce is only 8 bits, so generate
|
||||
// some new key material every time it wraps. The ECC384 generator is slightly
|
||||
// faster so use that one.
|
||||
_pub.nonce = 0;
|
||||
C25519::generateCombined(_pub.c25519,_priv.c25519);
|
||||
ECC384GenerateKey(_pub.p384,_priv.p384);
|
||||
m_pub.nonce = 0;
|
||||
C25519::generateCombined(m_pub.c25519, m_priv.c25519);
|
||||
ECC384GenerateKey(m_pub.p384, m_priv.p384);
|
||||
for(;;) {
|
||||
if (identityV1ProofOfWorkCriteria(&_pub,sizeof(_pub),b))
|
||||
if (identityV1ProofOfWorkCriteria(&m_pub, sizeof(m_pub), b))
|
||||
break;
|
||||
if (++_pub.nonce == 0)
|
||||
ECC384GenerateKey(_pub.p384,_priv.p384);
|
||||
if (++m_pub.nonce == 0)
|
||||
ECC384GenerateKey(m_pub.p384, m_priv.p384);
|
||||
}
|
||||
|
||||
// If we passed PoW then check that the address is valid, otherwise loop
|
||||
// back around and run the whole process again.
|
||||
_computeHash();
|
||||
_address.setTo(_fp.hash());
|
||||
if (!_address.isReserved())
|
||||
m_address.setTo(m_fp.hash());
|
||||
if (!m_address.isReserved())
|
||||
break;
|
||||
}
|
||||
free(b);
|
||||
|
@ -231,24 +231,24 @@ bool Identity::generate(const Type t)
|
|||
bool Identity::locallyValidate() const noexcept
|
||||
{
|
||||
try {
|
||||
if ((!_address.isReserved()) && (_address)) {
|
||||
switch (_type) {
|
||||
if ((!m_address.isReserved()) && (m_address)) {
|
||||
switch (m_type) {
|
||||
|
||||
case C25519: {
|
||||
uint8_t digest[64];
|
||||
char *genmem = new char[ZT_V0_IDENTITY_GEN_MEMORY];
|
||||
identityV0ProofOfWorkFrankenhash(_pub.c25519,ZT_C25519_COMBINED_PUBLIC_KEY_SIZE,digest,genmem);
|
||||
identityV0ProofOfWorkFrankenhash(m_pub.c25519, ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, digest, genmem);
|
||||
delete[] genmem;
|
||||
return ((_address == Address(digest + 59)) && (digest[0] < 17));
|
||||
return ((m_address == Address(digest + 59)) && (digest[0] < 17));
|
||||
}
|
||||
|
||||
case P384: {
|
||||
if (_address != Address(_fp.hash()))
|
||||
if (m_address != Address(m_fp.hash()))
|
||||
return false;
|
||||
uint64_t *const b = (uint64_t *)malloc(ZT_IDENTITY_V1_POW_MEMORY_SIZE * 8); // NOLINT(hicpp-use-auto,modernize-use-auto)
|
||||
if (!b)
|
||||
return false;
|
||||
const bool ok = identityV1ProofOfWorkCriteria(&_pub,sizeof(_pub),b);
|
||||
const bool ok = identityV1ProofOfWorkCriteria(&m_pub, sizeof(m_pub), b);
|
||||
free(b);
|
||||
return ok;
|
||||
}
|
||||
|
@ -261,15 +261,15 @@ bool Identity::locallyValidate() const noexcept
|
|||
|
||||
void Identity::hashWithPrivate(uint8_t h[ZT_FINGERPRINT_HASH_SIZE]) const
|
||||
{
|
||||
if (_hasPrivate) {
|
||||
switch (_type) {
|
||||
if (m_hasPrivate) {
|
||||
switch (m_type) {
|
||||
|
||||
case C25519:
|
||||
SHA384(h,_pub.c25519,ZT_C25519_COMBINED_PUBLIC_KEY_SIZE,_priv.c25519,ZT_C25519_COMBINED_PRIVATE_KEY_SIZE);
|
||||
SHA384(h, m_pub.c25519, ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, m_priv.c25519, ZT_C25519_COMBINED_PRIVATE_KEY_SIZE);
|
||||
break;
|
||||
|
||||
case P384:
|
||||
SHA384(h,&_pub,sizeof(_pub),&_priv,sizeof(_priv));
|
||||
SHA384(h, &m_pub, sizeof(m_pub), &m_priv, sizeof(m_priv));
|
||||
break;
|
||||
|
||||
}
|
||||
|
@ -280,20 +280,20 @@ void Identity::hashWithPrivate(uint8_t h[ZT_FINGERPRINT_HASH_SIZE]) const
|
|||
|
||||
unsigned int Identity::sign(const void *data,unsigned int len,void *sig,unsigned int siglen) const
|
||||
{
|
||||
if (_hasPrivate) {
|
||||
switch(_type) {
|
||||
if (m_hasPrivate) {
|
||||
switch(m_type) {
|
||||
|
||||
case C25519:
|
||||
if (siglen >= ZT_C25519_SIGNATURE_LEN) {
|
||||
C25519::sign(_priv.c25519,_pub.c25519,data,len,sig);
|
||||
C25519::sign(m_priv.c25519, m_pub.c25519, data, len, sig);
|
||||
return ZT_C25519_SIGNATURE_LEN;
|
||||
}
|
||||
|
||||
case P384:
|
||||
if (siglen >= ZT_ECC384_SIGNATURE_SIZE) {
|
||||
uint8_t h[48];
|
||||
SHA384(h,data,len,&_pub,ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE); // include C25519 public key in hash
|
||||
ECC384ECDSASign(_priv.p384,h,(uint8_t *)sig);
|
||||
SHA384(h, data, len, &m_pub, ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE); // include C25519 public key in hash
|
||||
ECC384ECDSASign(m_priv.p384, h, (uint8_t *)sig);
|
||||
return ZT_ECC384_SIGNATURE_SIZE;
|
||||
}
|
||||
|
||||
|
@ -304,16 +304,16 @@ unsigned int Identity::sign(const void *data,unsigned int len,void *sig,unsigned
|
|||
|
||||
bool Identity::verify(const void *data,unsigned int len,const void *sig,unsigned int siglen) const
|
||||
{
|
||||
switch(_type) {
|
||||
switch(m_type) {
|
||||
|
||||
case C25519:
|
||||
return C25519::verify(_pub.c25519,data,len,sig,siglen);
|
||||
return C25519::verify(m_pub.c25519, data, len, sig, siglen);
|
||||
|
||||
case P384:
|
||||
if (siglen == ZT_ECC384_SIGNATURE_SIZE) {
|
||||
uint8_t h[48];
|
||||
SHA384(h,data,len,&_pub,ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE);
|
||||
return ECC384ECDSAVerify(_pub.p384,h,(const uint8_t *)sig);
|
||||
SHA384(h, data, len, &m_pub, ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE);
|
||||
return ECC384ECDSAVerify(m_pub.p384, h, (const uint8_t *)sig);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -325,34 +325,34 @@ bool Identity::agree(const Identity &id,uint8_t key[ZT_SYMMETRIC_KEY_SIZE]) cons
|
|||
{
|
||||
uint8_t rawkey[128];
|
||||
uint8_t h[64];
|
||||
if (_hasPrivate) {
|
||||
if (_type == C25519) {
|
||||
if (m_hasPrivate) {
|
||||
if (m_type == C25519) {
|
||||
|
||||
if ((id._type == C25519)||(id._type == P384)) {
|
||||
if ((id.m_type == C25519) || (id.m_type == P384)) {
|
||||
// If we are a C25519 key we can agree with another C25519 key or with only the
|
||||
// C25519 portion of a type 1 P-384 key.
|
||||
C25519::agree(_priv.c25519,id._pub.c25519,rawkey);
|
||||
C25519::agree(m_priv.c25519, id.m_pub.c25519, rawkey);
|
||||
SHA512(h,rawkey,ZT_C25519_ECDH_SHARED_SECRET_SIZE);
|
||||
Utils::copy<ZT_SYMMETRIC_KEY_SIZE>(key,h);
|
||||
return true;
|
||||
}
|
||||
|
||||
} else if (_type == P384) {
|
||||
} else if (m_type == P384) {
|
||||
|
||||
if (id._type == P384) {
|
||||
if (id.m_type == P384) {
|
||||
// For another P384 identity we execute DH agreement with BOTH keys and then
|
||||
// hash the results together. For those (cough FIPS cough) who only consider
|
||||
// P384 to be kosher, the C25519 secret can be considered a "salt"
|
||||
// or something. For those who don't trust P384 this means the privacy of
|
||||
// your traffic is also protected by C25519.
|
||||
C25519::agree(_priv.c25519,id._pub.c25519,rawkey);
|
||||
ECC384ECDH(id._pub.p384,_priv.p384,rawkey + ZT_C25519_ECDH_SHARED_SECRET_SIZE);
|
||||
C25519::agree(m_priv.c25519, id.m_pub.c25519, rawkey);
|
||||
ECC384ECDH(id.m_pub.p384, m_priv.p384, rawkey + ZT_C25519_ECDH_SHARED_SECRET_SIZE);
|
||||
SHA384(h,rawkey,ZT_C25519_ECDH_SHARED_SECRET_SIZE + ZT_ECC384_SHARED_SECRET_SIZE);
|
||||
Utils::copy<ZT_SYMMETRIC_KEY_SIZE>(key,h);
|
||||
return true;
|
||||
} else if (id._type == C25519) {
|
||||
} else if (id.m_type == C25519) {
|
||||
// If the other identity is a C25519 identity we can agree using only that type.
|
||||
C25519::agree(_priv.c25519,id._pub.c25519,rawkey);
|
||||
C25519::agree(m_priv.c25519, id.m_pub.c25519, rawkey);
|
||||
SHA512(h,rawkey,ZT_C25519_ECDH_SHARED_SECRET_SIZE);
|
||||
Utils::copy<ZT_SYMMETRIC_KEY_SIZE>(key,h);
|
||||
return true;
|
||||
|
@ -366,20 +366,20 @@ bool Identity::agree(const Identity &id,uint8_t key[ZT_SYMMETRIC_KEY_SIZE]) cons
|
|||
char *Identity::toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const
|
||||
{
|
||||
char *p = buf;
|
||||
_address.toString(p);
|
||||
m_address.toString(p);
|
||||
p += 10;
|
||||
*(p++) = ':';
|
||||
|
||||
switch(_type) {
|
||||
switch(m_type) {
|
||||
|
||||
case C25519: {
|
||||
*(p++) = '0';
|
||||
*(p++) = ':';
|
||||
Utils::hex(_pub.c25519,ZT_C25519_COMBINED_PUBLIC_KEY_SIZE,p);
|
||||
Utils::hex(m_pub.c25519, ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, p);
|
||||
p += ZT_C25519_COMBINED_PUBLIC_KEY_SIZE * 2;
|
||||
if ((_hasPrivate)&&(includePrivate)) {
|
||||
if ((m_hasPrivate) && (includePrivate)) {
|
||||
*(p++) = ':';
|
||||
Utils::hex(_priv.c25519,ZT_C25519_COMBINED_PRIVATE_KEY_SIZE,p);
|
||||
Utils::hex(m_priv.c25519, ZT_C25519_COMBINED_PRIVATE_KEY_SIZE, p);
|
||||
p += ZT_C25519_COMBINED_PRIVATE_KEY_SIZE * 2;
|
||||
}
|
||||
*p = (char)0;
|
||||
|
@ -389,12 +389,12 @@ char *Identity::toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_
|
|||
case P384: {
|
||||
*(p++) = '1';
|
||||
*(p++) = ':';
|
||||
int el = Utils::b32e((const uint8_t *)(&_pub),sizeof(_pub),p,(int)(ZT_IDENTITY_STRING_BUFFER_LENGTH - (uintptr_t)(p - buf)));
|
||||
int el = Utils::b32e((const uint8_t *)(&m_pub), sizeof(m_pub), p, (int)(ZT_IDENTITY_STRING_BUFFER_LENGTH - (uintptr_t)(p - buf)));
|
||||
if (el <= 0) return nullptr;
|
||||
p += el;
|
||||
if ((_hasPrivate)&&(includePrivate)) {
|
||||
if ((m_hasPrivate) && (includePrivate)) {
|
||||
*(p++) = ':';
|
||||
el = Utils::b32e((const uint8_t *)(&_priv),sizeof(_priv),p,(int)(ZT_IDENTITY_STRING_BUFFER_LENGTH - (uintptr_t)(p - buf)));
|
||||
el = Utils::b32e((const uint8_t *)(&m_priv), sizeof(m_priv), p, (int)(ZT_IDENTITY_STRING_BUFFER_LENGTH - (uintptr_t)(p - buf)));
|
||||
if (el <= 0) return nullptr;
|
||||
p += el;
|
||||
}
|
||||
|
@ -409,17 +409,17 @@ char *Identity::toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_
|
|||
|
||||
bool Identity::fromString(const char *str)
|
||||
{
|
||||
_fp.zero();
|
||||
_hasPrivate = false;
|
||||
m_fp.zero();
|
||||
m_hasPrivate = false;
|
||||
|
||||
if (!str) {
|
||||
_address.zero();
|
||||
m_address.zero();
|
||||
return false;
|
||||
}
|
||||
|
||||
char tmp[ZT_IDENTITY_STRING_BUFFER_LENGTH];
|
||||
if (!Utils::scopy(tmp,sizeof(tmp),str)) {
|
||||
_address.zero();
|
||||
m_address.zero();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -429,37 +429,37 @@ bool Identity::fromString(const char *str)
|
|||
switch(fno++) {
|
||||
|
||||
case 0:
|
||||
_address = Address(Utils::hexStrToU64(f));
|
||||
if (_address.isReserved()) {
|
||||
_address.zero();
|
||||
m_address = Address(Utils::hexStrToU64(f));
|
||||
if (m_address.isReserved()) {
|
||||
m_address.zero();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if ((f[0] == '0')&&(!f[1])) {
|
||||
_type = C25519;
|
||||
m_type = C25519;
|
||||
} else if ((f[0] == '1')&&(!f[1])) {
|
||||
_type = P384;
|
||||
m_type = P384;
|
||||
} else {
|
||||
_address.zero();
|
||||
m_address.zero();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
switch(_type) {
|
||||
switch(m_type) {
|
||||
|
||||
case C25519:
|
||||
if (Utils::unhex(f,strlen(f),_pub.c25519,ZT_C25519_COMBINED_PUBLIC_KEY_SIZE) != ZT_C25519_COMBINED_PUBLIC_KEY_SIZE) {
|
||||
_address.zero();
|
||||
if (Utils::unhex(f, strlen(f), m_pub.c25519, ZT_C25519_COMBINED_PUBLIC_KEY_SIZE) != ZT_C25519_COMBINED_PUBLIC_KEY_SIZE) {
|
||||
m_address.zero();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case P384:
|
||||
if (Utils::b32d(f,(uint8_t *)(&_pub),sizeof(_pub)) != sizeof(_pub)) {
|
||||
_address.zero();
|
||||
if (Utils::b32d(f, (uint8_t *)(&m_pub), sizeof(m_pub)) != sizeof(m_pub)) {
|
||||
m_address.zero();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
@ -469,23 +469,23 @@ bool Identity::fromString(const char *str)
|
|||
|
||||
case 3:
|
||||
if (strlen(f) > 1) {
|
||||
switch(_type) {
|
||||
switch(m_type) {
|
||||
|
||||
case C25519:
|
||||
if (Utils::unhex(f,strlen(f),_priv.c25519,ZT_C25519_COMBINED_PRIVATE_KEY_SIZE) != ZT_C25519_COMBINED_PRIVATE_KEY_SIZE) {
|
||||
_address.zero();
|
||||
if (Utils::unhex(f, strlen(f), m_priv.c25519, ZT_C25519_COMBINED_PRIVATE_KEY_SIZE) != ZT_C25519_COMBINED_PRIVATE_KEY_SIZE) {
|
||||
m_address.zero();
|
||||
return false;
|
||||
} else {
|
||||
_hasPrivate = true;
|
||||
m_hasPrivate = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case P384:
|
||||
if (Utils::b32d(f,(uint8_t *)(&_priv),sizeof(_priv)) != sizeof(_priv)) {
|
||||
_address.zero();
|
||||
if (Utils::b32d(f, (uint8_t *)(&m_priv), sizeof(m_priv)) != sizeof(m_priv)) {
|
||||
m_address.zero();
|
||||
return false;
|
||||
} else {
|
||||
_hasPrivate = true;
|
||||
m_hasPrivate = true;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -497,13 +497,13 @@ bool Identity::fromString(const char *str)
|
|||
}
|
||||
|
||||
if (fno < 3) {
|
||||
_address.zero();
|
||||
m_address.zero();
|
||||
return false;
|
||||
}
|
||||
|
||||
_computeHash();
|
||||
if ((_type == P384)&&(_address != Address(_fp.hash()))) {
|
||||
_address.zero();
|
||||
if ((m_type == P384) && (m_address != Address(m_fp.hash()))) {
|
||||
m_address.zero();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -512,14 +512,14 @@ bool Identity::fromString(const char *str)
|
|||
|
||||
int Identity::marshal(uint8_t data[ZT_IDENTITY_MARSHAL_SIZE_MAX],const bool includePrivate) const noexcept
|
||||
{
|
||||
_address.copyTo(data);
|
||||
switch(_type) {
|
||||
m_address.copyTo(data);
|
||||
switch(m_type) {
|
||||
case C25519:
|
||||
data[ZT_ADDRESS_LENGTH] = (uint8_t)C25519;
|
||||
Utils::copy<ZT_C25519_COMBINED_PUBLIC_KEY_SIZE>(data + ZT_ADDRESS_LENGTH + 1,_pub.c25519);
|
||||
if ((includePrivate)&&(_hasPrivate)) {
|
||||
Utils::copy<ZT_C25519_COMBINED_PUBLIC_KEY_SIZE>(data + ZT_ADDRESS_LENGTH + 1, m_pub.c25519);
|
||||
if ((includePrivate)&&(m_hasPrivate)) {
|
||||
data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE] = ZT_C25519_COMBINED_PRIVATE_KEY_SIZE;
|
||||
Utils::copy<ZT_C25519_COMBINED_PRIVATE_KEY_SIZE>(data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1,_priv.c25519);
|
||||
Utils::copy<ZT_C25519_COMBINED_PRIVATE_KEY_SIZE>(data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1, m_priv.c25519);
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1 + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE;
|
||||
} else {
|
||||
data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE] = 0;
|
||||
|
@ -528,10 +528,10 @@ int Identity::marshal(uint8_t data[ZT_IDENTITY_MARSHAL_SIZE_MAX],const bool incl
|
|||
|
||||
case P384:
|
||||
data[ZT_ADDRESS_LENGTH] = (uint8_t)P384;
|
||||
Utils::copy<ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE>(data + ZT_ADDRESS_LENGTH + 1,&_pub);
|
||||
if ((includePrivate)&&(_hasPrivate)) {
|
||||
Utils::copy<ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE>(data + ZT_ADDRESS_LENGTH + 1,&m_pub);
|
||||
if ((includePrivate)&&(m_hasPrivate)) {
|
||||
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE] = ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE;
|
||||
Utils::copy<ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE>(data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1,&_priv);
|
||||
Utils::copy<ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE>(data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1,&m_priv);
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE;
|
||||
} else {
|
||||
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE] = 0;
|
||||
|
@ -544,32 +544,32 @@ int Identity::marshal(uint8_t data[ZT_IDENTITY_MARSHAL_SIZE_MAX],const bool incl
|
|||
|
||||
int Identity::unmarshal(const uint8_t *data,const int len) noexcept
|
||||
{
|
||||
_fp.zero();
|
||||
_hasPrivate = false;
|
||||
m_fp.zero();
|
||||
m_hasPrivate = false;
|
||||
|
||||
if (len < (1 + ZT_ADDRESS_LENGTH))
|
||||
return -1;
|
||||
_address.setTo(data);
|
||||
m_address.setTo(data);
|
||||
|
||||
unsigned int privlen;
|
||||
switch((_type = (Type)data[ZT_ADDRESS_LENGTH])) {
|
||||
switch((m_type = (Type)data[ZT_ADDRESS_LENGTH])) {
|
||||
|
||||
case C25519:
|
||||
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1))
|
||||
return -1;
|
||||
|
||||
Utils::copy<ZT_C25519_COMBINED_PUBLIC_KEY_SIZE>(_pub.c25519,data + ZT_ADDRESS_LENGTH + 1);
|
||||
Utils::copy<ZT_C25519_COMBINED_PUBLIC_KEY_SIZE>(m_pub.c25519, data + ZT_ADDRESS_LENGTH + 1);
|
||||
_computeHash();
|
||||
|
||||
privlen = data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE];
|
||||
if (privlen == ZT_C25519_COMBINED_PRIVATE_KEY_SIZE) {
|
||||
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1 + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE))
|
||||
return -1;
|
||||
_hasPrivate = true;
|
||||
Utils::copy<ZT_C25519_COMBINED_PRIVATE_KEY_SIZE>(_priv.c25519,data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1);
|
||||
m_hasPrivate = true;
|
||||
Utils::copy<ZT_C25519_COMBINED_PRIVATE_KEY_SIZE>(m_priv.c25519, data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1);
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1 + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE;
|
||||
} else if (privlen == 0) {
|
||||
_hasPrivate = false;
|
||||
m_hasPrivate = false;
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1;
|
||||
}
|
||||
break;
|
||||
|
@ -578,20 +578,20 @@ int Identity::unmarshal(const uint8_t *data,const int len) noexcept
|
|||
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1))
|
||||
return -1;
|
||||
|
||||
Utils::copy<ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE>(&_pub,data + ZT_ADDRESS_LENGTH + 1);
|
||||
Utils::copy<ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE>(&m_pub, data + ZT_ADDRESS_LENGTH + 1);
|
||||
_computeHash(); // this sets the address for P384
|
||||
if (_address != Address(_fp.hash())) // this sanity check is possible with V1 identities
|
||||
if (m_address != Address(m_fp.hash())) // this sanity check is possible with V1 identities
|
||||
return -1;
|
||||
|
||||
privlen = data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE];
|
||||
if (privlen == ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE) {
|
||||
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE))
|
||||
return -1;
|
||||
_hasPrivate = true;
|
||||
Utils::copy<ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE>(&_priv,data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1);
|
||||
m_hasPrivate = true;
|
||||
Utils::copy<ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE>(&m_priv, data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1);
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE;
|
||||
} else if (privlen == 0) {
|
||||
_hasPrivate = false;
|
||||
m_hasPrivate = false;
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1;
|
||||
}
|
||||
break;
|
||||
|
@ -603,19 +603,19 @@ int Identity::unmarshal(const uint8_t *data,const int len) noexcept
|
|||
|
||||
void Identity::_computeHash()
|
||||
{
|
||||
switch(_type) {
|
||||
switch(m_type) {
|
||||
default:
|
||||
_fp.zero();
|
||||
m_fp.zero();
|
||||
break;
|
||||
|
||||
case C25519:
|
||||
_fp._fp.address = _address.toInt();
|
||||
SHA384(_fp._fp.hash,_pub.c25519,ZT_C25519_COMBINED_PUBLIC_KEY_SIZE);
|
||||
m_fp.m_cfp.address = m_address.toInt();
|
||||
SHA384(m_fp.m_cfp.hash, m_pub.c25519, ZT_C25519_COMBINED_PUBLIC_KEY_SIZE);
|
||||
break;
|
||||
|
||||
case P384:
|
||||
SHA384(_fp._fp.hash,&_pub,sizeof(_pub));
|
||||
_fp._fp.address = _address.toInt();
|
||||
SHA384(m_fp.m_cfp.hash, &m_pub, sizeof(m_pub));
|
||||
m_fp.m_cfp.address = m_address.toInt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "ECC384.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Fingerprint.hpp"
|
||||
#include "Containers.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
@ -86,7 +87,7 @@ public:
|
|||
ZT_INLINE ~Identity()
|
||||
{
|
||||
Utils::memoryUnlock(this,sizeof(Identity));
|
||||
Utils::burn(reinterpret_cast<void *>(&this->_priv),sizeof(this->_priv));
|
||||
Utils::burn(reinterpret_cast<void *>(&this->m_priv), sizeof(this->m_priv));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -97,7 +98,7 @@ public:
|
|||
/**
|
||||
* @return Identity type (undefined if identity is null or invalid)
|
||||
*/
|
||||
ZT_INLINE Type type() const noexcept { return _type; }
|
||||
ZT_INLINE Type type() const noexcept { return m_type; }
|
||||
|
||||
/**
|
||||
* Generate a new identity (address, key pair)
|
||||
|
@ -123,7 +124,7 @@ public:
|
|||
/**
|
||||
* @return True if this identity contains a private key
|
||||
*/
|
||||
ZT_INLINE bool hasPrivate() const noexcept { return _hasPrivate; }
|
||||
ZT_INLINE bool hasPrivate() const noexcept { return m_hasPrivate; }
|
||||
|
||||
/**
|
||||
* Get a 384-bit hash of this identity's public key(s)
|
||||
|
@ -137,7 +138,7 @@ public:
|
|||
*
|
||||
* @return Hash of public key(s)
|
||||
*/
|
||||
ZT_INLINE const Fingerprint &fingerprint() const noexcept { return _fp; }
|
||||
ZT_INLINE const Fingerprint &fingerprint() const noexcept { return m_fp; }
|
||||
|
||||
/**
|
||||
* Compute a hash of this identity's public and private keys.
|
||||
|
@ -187,7 +188,7 @@ public:
|
|||
/**
|
||||
* @return This identity's address
|
||||
*/
|
||||
ZT_INLINE Address address() const noexcept { return _address; }
|
||||
ZT_INLINE Address address() const noexcept { return m_address; }
|
||||
|
||||
/**
|
||||
* Serialize to a more human-friendly string
|
||||
|
@ -197,6 +198,7 @@ public:
|
|||
* @return ASCII string representation of identity (pointer to buf)
|
||||
*/
|
||||
char *toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const;
|
||||
ZT_INLINE String toString(const bool includePrivate = false) const { char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]; toString(includePrivate); return String(buf); }
|
||||
|
||||
/**
|
||||
* Deserialize a human-friendly string
|
||||
|
@ -212,13 +214,13 @@ public:
|
|||
/**
|
||||
* @return True if this identity contains something
|
||||
*/
|
||||
explicit ZT_INLINE operator bool() const noexcept { return (_address); }
|
||||
explicit ZT_INLINE operator bool() const noexcept { return (m_address); }
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept { return _fp.hashCode(); }
|
||||
ZT_INLINE unsigned long hashCode() const noexcept { return m_fp.hashCode(); }
|
||||
|
||||
ZT_INLINE bool operator==(const Identity &id) const noexcept { return (_fp == id._fp); }
|
||||
ZT_INLINE bool operator==(const Identity &id) const noexcept { return (m_fp == id.m_fp); }
|
||||
ZT_INLINE bool operator!=(const Identity &id) const noexcept { return !(*this == id); }
|
||||
ZT_INLINE bool operator<(const Identity &id) const noexcept { return (_fp < id._fp); }
|
||||
ZT_INLINE bool operator<(const Identity &id) const noexcept { return (m_fp < id.m_fp); }
|
||||
ZT_INLINE bool operator>(const Identity &id) const noexcept { return (id < *this); }
|
||||
ZT_INLINE bool operator<=(const Identity &id) const noexcept { return !(id < *this); }
|
||||
ZT_INLINE bool operator>=(const Identity &id) const noexcept { return !(*this < id); }
|
||||
|
@ -230,19 +232,19 @@ public:
|
|||
private:
|
||||
void _computeHash();
|
||||
|
||||
Address _address;
|
||||
Fingerprint _fp;
|
||||
Address m_address;
|
||||
Fingerprint m_fp;
|
||||
ZT_PACKED_STRUCT(struct { // do not re-order these fields
|
||||
uint8_t c25519[ZT_C25519_COMBINED_PRIVATE_KEY_SIZE];
|
||||
uint8_t p384[ZT_ECC384_PRIVATE_KEY_SIZE];
|
||||
}) _priv;
|
||||
}) m_priv;
|
||||
ZT_PACKED_STRUCT(struct { // do not re-order these fields
|
||||
uint8_t nonce; // nonce for PoW generate/verify
|
||||
uint8_t c25519[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE]; // Curve25519 and Ed25519 public keys
|
||||
uint8_t p384[ZT_ECC384_PUBLIC_KEY_SIZE]; // NIST P-384 public key
|
||||
}) _pub;
|
||||
Type _type; // _type determines which fields in _priv and _pub are used
|
||||
bool _hasPrivate;
|
||||
}) m_pub;
|
||||
Type m_type; // _type determines which fields in _priv and _pub are used
|
||||
bool m_hasPrivate;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -26,7 +26,7 @@ const InetAddress InetAddress::NIL;
|
|||
|
||||
InetAddress::IpScope InetAddress::ipScope() const noexcept
|
||||
{
|
||||
switch(_data.ss_family) {
|
||||
switch(m_sockaddr.ss_family) {
|
||||
|
||||
case AF_INET: {
|
||||
const uint32_t ip = Utils::ntoh((uint32_t)reinterpret_cast<const sockaddr_in *>(this)->sin_addr.s_addr);
|
||||
|
@ -99,11 +99,11 @@ void InetAddress::set(const void *ipBytes,unsigned int ipLen,unsigned int port)
|
|||
if (ipLen == 4) {
|
||||
uint32_t ipb[1];
|
||||
Utils::copy<4>(ipb,ipBytes);
|
||||
_data.ss_family = AF_INET;
|
||||
m_sockaddr.ss_family = AF_INET;
|
||||
reinterpret_cast<sockaddr_in *>(this)->sin_addr.s_addr = ipb[0];
|
||||
reinterpret_cast<sockaddr_in *>(this)->sin_port = Utils::hton((uint16_t)port);
|
||||
} else if (ipLen == 16) {
|
||||
_data.ss_family = AF_INET6;
|
||||
m_sockaddr.ss_family = AF_INET6;
|
||||
Utils::copy<16>(reinterpret_cast<sockaddr_in6 *>(this)->sin6_addr.s6_addr,ipBytes);
|
||||
reinterpret_cast<sockaddr_in6 *>(this)->sin6_port = Utils::hton((uint16_t)port);
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ void InetAddress::set(const void *ipBytes,unsigned int ipLen,unsigned int port)
|
|||
|
||||
bool InetAddress::isDefaultRoute() const noexcept
|
||||
{
|
||||
switch(_data.ss_family) {
|
||||
switch(m_sockaddr.ss_family) {
|
||||
case AF_INET:
|
||||
return ( (reinterpret_cast<const sockaddr_in *>(this)->sin_addr.s_addr == 0) && (reinterpret_cast<const sockaddr_in *>(this)->sin_port == 0) );
|
||||
case AF_INET6:
|
||||
|
@ -139,7 +139,7 @@ char *InetAddress::toString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noex
|
|||
char *InetAddress::toIpString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept
|
||||
{
|
||||
buf[0] = (char)0;
|
||||
switch(_data.ss_family) {
|
||||
switch(m_sockaddr.ss_family) {
|
||||
case AF_INET: {
|
||||
#ifdef _WIN32
|
||||
inet_ntop(AF_INET, (void*)&reinterpret_cast<const sockaddr_in *>(this)->sin_addr.s_addr, buf, INET_ADDRSTRLEN);
|
||||
|
@ -199,7 +199,7 @@ bool InetAddress::fromString(const char *ipSlashPort) noexcept
|
|||
InetAddress InetAddress::netmask() const noexcept
|
||||
{
|
||||
InetAddress r(*this);
|
||||
switch(r._data.ss_family) {
|
||||
switch(r.m_sockaddr.ss_family) {
|
||||
case AF_INET:
|
||||
reinterpret_cast<sockaddr_in *>(&r)->sin_addr.s_addr = Utils::hton((uint32_t)(0xffffffffU << (32 - netmaskBits())));
|
||||
break;
|
||||
|
@ -221,7 +221,7 @@ InetAddress InetAddress::netmask() const noexcept
|
|||
|
||||
InetAddress InetAddress::broadcast() const noexcept
|
||||
{
|
||||
if (_data.ss_family == AF_INET) {
|
||||
if (m_sockaddr.ss_family == AF_INET) {
|
||||
InetAddress r(*this);
|
||||
reinterpret_cast<sockaddr_in *>(&r)->sin_addr.s_addr |= Utils::hton((uint32_t)(0xffffffffU >> netmaskBits()));
|
||||
return r;
|
||||
|
@ -232,7 +232,7 @@ InetAddress InetAddress::broadcast() const noexcept
|
|||
InetAddress InetAddress::network() const noexcept
|
||||
{
|
||||
InetAddress r(*this);
|
||||
switch(r._data.ss_family) {
|
||||
switch(r.m_sockaddr.ss_family) {
|
||||
case AF_INET:
|
||||
reinterpret_cast<sockaddr_in *>(&r)->sin_addr.s_addr &= Utils::hton((uint32_t)(0xffffffffU << (32 - netmaskBits())));
|
||||
break;
|
||||
|
@ -250,8 +250,8 @@ InetAddress InetAddress::network() const noexcept
|
|||
|
||||
bool InetAddress::isEqualPrefix(const InetAddress &addr) const noexcept
|
||||
{
|
||||
if (addr._data.ss_family == _data.ss_family) {
|
||||
switch(_data.ss_family) {
|
||||
if (addr.m_sockaddr.ss_family == m_sockaddr.ss_family) {
|
||||
switch(m_sockaddr.ss_family) {
|
||||
case AF_INET6: {
|
||||
const InetAddress mask(netmask());
|
||||
InetAddress addr_mask(addr.netmask());
|
||||
|
@ -272,8 +272,8 @@ bool InetAddress::isEqualPrefix(const InetAddress &addr) const noexcept
|
|||
|
||||
bool InetAddress::containsAddress(const InetAddress &addr) const noexcept
|
||||
{
|
||||
if (addr._data.ss_family == _data.ss_family) {
|
||||
switch(_data.ss_family) {
|
||||
if (addr.m_sockaddr.ss_family == m_sockaddr.ss_family) {
|
||||
switch(m_sockaddr.ss_family) {
|
||||
case AF_INET: {
|
||||
const unsigned int bits = netmaskBits();
|
||||
if (bits == 0)
|
||||
|
@ -302,7 +302,7 @@ bool InetAddress::containsAddress(const InetAddress &addr) const noexcept
|
|||
void InetAddress::forTrace(ZT_TraceEventPathAddress &ta) const noexcept
|
||||
{
|
||||
uint32_t tmp;
|
||||
switch(_data.ss_family) {
|
||||
switch(m_sockaddr.ss_family) {
|
||||
default:
|
||||
Utils::zero<sizeof(ZT_TraceEventPathAddress)>(&ta);
|
||||
break;
|
||||
|
@ -327,7 +327,7 @@ void InetAddress::forTrace(ZT_TraceEventPathAddress &ta) const noexcept
|
|||
|
||||
bool InetAddress::isNetwork() const noexcept
|
||||
{
|
||||
switch(_data.ss_family) {
|
||||
switch(m_sockaddr.ss_family) {
|
||||
case AF_INET: {
|
||||
unsigned int bits = netmaskBits();
|
||||
if (bits <= 0)
|
||||
|
@ -360,7 +360,7 @@ bool InetAddress::isNetwork() const noexcept
|
|||
int InetAddress::marshal(uint8_t data[ZT_INETADDRESS_MARSHAL_SIZE_MAX]) const noexcept
|
||||
{
|
||||
unsigned int port;
|
||||
switch(_data.ss_family) {
|
||||
switch(m_sockaddr.ss_family) {
|
||||
case AF_INET:
|
||||
port = Utils::ntoh((uint16_t)reinterpret_cast<const sockaddr_in *>(this)->sin_port);
|
||||
data[0] = 4;
|
||||
|
@ -421,8 +421,8 @@ int InetAddress::unmarshal(const uint8_t *restrict data,const int len) noexcept
|
|||
|
||||
bool InetAddress::operator==(const InetAddress &a) const noexcept
|
||||
{
|
||||
if (_data.ss_family == a._data.ss_family) {
|
||||
switch(_data.ss_family) {
|
||||
if (m_sockaddr.ss_family == a.m_sockaddr.ss_family) {
|
||||
switch(m_sockaddr.ss_family) {
|
||||
case AF_INET:
|
||||
return (
|
||||
(reinterpret_cast<const sockaddr_in *>(this)->sin_port == reinterpret_cast<const sockaddr_in *>(&a)->sin_port)&&
|
||||
|
@ -442,10 +442,10 @@ bool InetAddress::operator==(const InetAddress &a) const noexcept
|
|||
|
||||
bool InetAddress::operator<(const InetAddress &a) const noexcept
|
||||
{
|
||||
if (_data.ss_family < a._data.ss_family)
|
||||
if (m_sockaddr.ss_family < a.m_sockaddr.ss_family)
|
||||
return true;
|
||||
else if (_data.ss_family == a._data.ss_family) {
|
||||
switch(_data.ss_family) {
|
||||
else if (m_sockaddr.ss_family == a.m_sockaddr.ss_family) {
|
||||
switch(m_sockaddr.ss_family) {
|
||||
case AF_INET:
|
||||
if (reinterpret_cast<const sockaddr_in *>(this)->sin_port < reinterpret_cast<const sockaddr_in *>(&a)->sin_port)
|
||||
return true;
|
||||
|
|
|
@ -166,7 +166,7 @@ public:
|
|||
/**
|
||||
* @return Address family (ss_family in sockaddr_storage)
|
||||
*/
|
||||
ZT_INLINE uint8_t family() const noexcept { return _data.ss_family; }
|
||||
ZT_INLINE uint8_t family() const noexcept { return m_sockaddr.ss_family; }
|
||||
|
||||
/**
|
||||
* @return IP scope classification (e.g. loopback, link-local, private, global)
|
||||
|
@ -189,7 +189,7 @@ public:
|
|||
*/
|
||||
ZT_INLINE void setPort(unsigned int port) noexcept
|
||||
{
|
||||
switch(_data.ss_family) {
|
||||
switch(m_sockaddr.ss_family) {
|
||||
case AF_INET:
|
||||
reinterpret_cast<sockaddr_in *>(this)->sin_port = Utils::hton((uint16_t)port);
|
||||
break;
|
||||
|
@ -227,7 +227,7 @@ public:
|
|||
*/
|
||||
ZT_INLINE unsigned int port() const noexcept
|
||||
{
|
||||
switch(_data.ss_family) {
|
||||
switch(m_sockaddr.ss_family) {
|
||||
case AF_INET: return Utils::ntoh((uint16_t)(reinterpret_cast<const sockaddr_in *>(this)->sin_port));
|
||||
case AF_INET6: return Utils::ntoh((uint16_t)(reinterpret_cast<const sockaddr_in6 *>(this)->sin6_port));
|
||||
default: return 0;
|
||||
|
@ -251,7 +251,7 @@ public:
|
|||
ZT_INLINE bool netmaskBitsValid() const noexcept
|
||||
{
|
||||
const unsigned int n = port();
|
||||
switch(_data.ss_family) {
|
||||
switch(m_sockaddr.ss_family) {
|
||||
case AF_INET: return (n <= 32);
|
||||
case AF_INET6: return (n <= 128);
|
||||
}
|
||||
|
@ -323,7 +323,7 @@ public:
|
|||
*/
|
||||
ZT_INLINE const void *rawIpData() const noexcept
|
||||
{
|
||||
switch(_data.ss_family) {
|
||||
switch(m_sockaddr.ss_family) {
|
||||
case AF_INET: return (const void *)&(reinterpret_cast<const sockaddr_in *>(this)->sin_addr.s_addr);
|
||||
case AF_INET6: return (const void *)(reinterpret_cast<const sockaddr_in6 *>(this)->sin6_addr.s6_addr);
|
||||
default: return nullptr;
|
||||
|
@ -336,7 +336,7 @@ public:
|
|||
ZT_INLINE InetAddress ipOnly() const noexcept
|
||||
{
|
||||
InetAddress r;
|
||||
switch(_data.ss_family) {
|
||||
switch(m_sockaddr.ss_family) {
|
||||
case AF_INET:
|
||||
reinterpret_cast<sockaddr_in *>(&r)->sin_family = AF_INET;
|
||||
reinterpret_cast<sockaddr_in *>(&r)->sin_addr.s_addr = reinterpret_cast<const sockaddr_in *>(this)->sin_addr.s_addr;
|
||||
|
@ -357,8 +357,8 @@ public:
|
|||
*/
|
||||
ZT_INLINE bool ipsEqual(const InetAddress &a) const noexcept
|
||||
{
|
||||
const uint8_t f = _data.ss_family;
|
||||
if (f == a._data.ss_family) {
|
||||
const uint8_t f = m_sockaddr.ss_family;
|
||||
if (f == a.m_sockaddr.ss_family) {
|
||||
if (f == AF_INET)
|
||||
return (reinterpret_cast<const sockaddr_in *>(this)->sin_addr.s_addr == reinterpret_cast<const sockaddr_in *>(&a)->sin_addr.s_addr);
|
||||
if (f == AF_INET6)
|
||||
|
@ -378,8 +378,8 @@ public:
|
|||
*/
|
||||
ZT_INLINE bool ipsEqual2(const InetAddress &a) const noexcept
|
||||
{
|
||||
const uint8_t f = _data.ss_family;
|
||||
if (f == a._data.ss_family) {
|
||||
const uint8_t f = m_sockaddr.ss_family;
|
||||
if (f == a.m_sockaddr.ss_family) {
|
||||
if (f == AF_INET)
|
||||
return (reinterpret_cast<const sockaddr_in *>(this)->sin_addr.s_addr == reinterpret_cast<const sockaddr_in *>(&a)->sin_addr.s_addr);
|
||||
if (f == AF_INET6)
|
||||
|
@ -391,16 +391,16 @@ public:
|
|||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{
|
||||
if (_data.ss_family == AF_INET) {
|
||||
return (unsigned long)Utils::hash32(((uint32_t)reinterpret_cast<const sockaddr_in *>(&_data)->sin_addr.s_addr + (uint32_t)reinterpret_cast<const sockaddr_in *>(&_data)->sin_port) ^ (uint32_t)Utils::s_mapNonce);
|
||||
} else if (_data.ss_family == AF_INET6) {
|
||||
if (m_sockaddr.ss_family == AF_INET) {
|
||||
return (unsigned long)Utils::hash32(((uint32_t)reinterpret_cast<const sockaddr_in *>(&m_sockaddr)->sin_addr.s_addr + (uint32_t)reinterpret_cast<const sockaddr_in *>(&m_sockaddr)->sin_port) ^ (uint32_t)Utils::s_mapNonce);
|
||||
} else if (m_sockaddr.ss_family == AF_INET6) {
|
||||
return (unsigned long)Utils::hash64(
|
||||
(Utils::loadAsIsEndian<uint64_t>(reinterpret_cast<const sockaddr_in6 *>(&_data)->sin6_addr.s6_addr) +
|
||||
Utils::loadAsIsEndian<uint64_t>(reinterpret_cast<const sockaddr_in6 *>(&_data)->sin6_addr.s6_addr + 8) +
|
||||
(uint64_t)reinterpret_cast<const sockaddr_in6 *>(&_data)->sin6_port) ^ Utils::s_mapNonce
|
||||
(Utils::loadAsIsEndian<uint64_t>(reinterpret_cast<const sockaddr_in6 *>(&m_sockaddr)->sin6_addr.s6_addr) +
|
||||
Utils::loadAsIsEndian<uint64_t>(reinterpret_cast<const sockaddr_in6 *>(&m_sockaddr)->sin6_addr.s6_addr + 8) +
|
||||
(uint64_t)reinterpret_cast<const sockaddr_in6 *>(&m_sockaddr)->sin6_port) ^ Utils::s_mapNonce
|
||||
);
|
||||
}
|
||||
return Utils::fnv1a32(&_data,sizeof(_data));
|
||||
return Utils::fnv1a32(&m_sockaddr, sizeof(m_sockaddr));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -493,7 +493,7 @@ public:
|
|||
static InetAddress makeIpv66plane(uint64_t nwid,uint64_t zeroTierAddress) noexcept;
|
||||
|
||||
private:
|
||||
sockaddr_storage _data;
|
||||
sockaddr_storage m_sockaddr;
|
||||
};
|
||||
|
||||
static_assert(sizeof(sockaddr_storage) == sizeof(InetAddress),"InetAddress sizing incorrect");
|
||||
|
|
|
@ -20,50 +20,50 @@ bool Locator::sign(const int64_t ts,const Identity &id) noexcept
|
|||
uint8_t signData[ZT_LOCATOR_MARSHAL_SIZE_MAX];
|
||||
if (!id.hasPrivate())
|
||||
return false;
|
||||
_ts = ts;
|
||||
if (_endpointCount > 0)
|
||||
std::sort(_at,_at + _endpointCount);
|
||||
m_ts = ts;
|
||||
if (m_endpointCount > 0)
|
||||
std::sort(m_at, m_at + m_endpointCount);
|
||||
const unsigned int signLen = marshal(signData,true);
|
||||
_signatureLength = id.sign(signData, signLen, _signature, sizeof(_signature));
|
||||
return (_signatureLength > 0);
|
||||
m_signatureLength = id.sign(signData, signLen, m_signature, sizeof(m_signature));
|
||||
return (m_signatureLength > 0);
|
||||
}
|
||||
|
||||
bool Locator::verify(const Identity &id) const noexcept
|
||||
{
|
||||
if ((_ts == 0)||(_endpointCount > ZT_LOCATOR_MAX_ENDPOINTS)||(_signatureLength > ZT_SIGNATURE_BUFFER_SIZE))
|
||||
if ((m_ts == 0) || (m_endpointCount > ZT_LOCATOR_MAX_ENDPOINTS) || (m_signatureLength > ZT_SIGNATURE_BUFFER_SIZE))
|
||||
return false;
|
||||
uint8_t signData[ZT_LOCATOR_MARSHAL_SIZE_MAX];
|
||||
const unsigned int signLen = marshal(signData,true);
|
||||
return id.verify(signData,signLen,_signature,_signatureLength);
|
||||
return id.verify(signData, signLen, m_signature, m_signatureLength);
|
||||
}
|
||||
|
||||
int Locator::marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX],const bool excludeSignature) const noexcept
|
||||
{
|
||||
if ((_endpointCount > ZT_LOCATOR_MAX_ENDPOINTS)||(_signatureLength > ZT_SIGNATURE_BUFFER_SIZE))
|
||||
if ((m_endpointCount > ZT_LOCATOR_MAX_ENDPOINTS) || (m_signatureLength > ZT_SIGNATURE_BUFFER_SIZE))
|
||||
return -1;
|
||||
|
||||
data[0] = 0xff; // version byte, currently 0xff to never be the same as byte 0 of an identity for legacy compatibility reasons
|
||||
Utils::storeBigEndian<int64_t>(data + 1,_ts);
|
||||
Utils::storeBigEndian<int64_t>(data + 1, m_ts);
|
||||
int p = 9;
|
||||
|
||||
if (_ts > 0) {
|
||||
Utils::storeBigEndian(data + p,(uint16_t)_endpointCount);
|
||||
if (m_ts > 0) {
|
||||
Utils::storeBigEndian(data + p,(uint16_t)m_endpointCount);
|
||||
p += 2;
|
||||
for (unsigned int i = 0; i < _endpointCount; ++i) {
|
||||
int tmp = _at[i].marshal(data + p);
|
||||
for (unsigned int i = 0;i < m_endpointCount;++i) {
|
||||
int tmp = m_at[i].marshal(data + p);
|
||||
if (tmp < 0)
|
||||
return -1;
|
||||
p += tmp;
|
||||
}
|
||||
|
||||
if (!excludeSignature) {
|
||||
Utils::storeBigEndian(data + p,(uint16_t)_signatureLength);
|
||||
Utils::storeBigEndian(data + p,(uint16_t)m_signatureLength);
|
||||
p += 2;
|
||||
Utils::copy(data + p,_signature,_signatureLength);
|
||||
p += (int)_signatureLength;
|
||||
Utils::copy(data + p, m_signature, m_signatureLength);
|
||||
p += (int)m_signatureLength;
|
||||
}
|
||||
|
||||
Utils::storeBigEndian(data + p,_flags);
|
||||
Utils::storeBigEndian(data + p, m_flags);
|
||||
p += 2;
|
||||
}
|
||||
|
||||
|
@ -77,17 +77,17 @@ int Locator::unmarshal(const uint8_t *restrict data,const int len) noexcept
|
|||
|
||||
if (data[0] != 0xff)
|
||||
return -1;
|
||||
_ts = Utils::loadBigEndian<int64_t>(data + 1);
|
||||
m_ts = Utils::loadBigEndian<int64_t>(data + 1);
|
||||
int p = 9;
|
||||
|
||||
if (_ts > 0) {
|
||||
if (m_ts > 0) {
|
||||
const unsigned int ec = Utils::loadBigEndian<uint16_t>(data + p);
|
||||
p += 2;
|
||||
if (ec > ZT_LOCATOR_MAX_ENDPOINTS)
|
||||
return -1;
|
||||
_endpointCount = ec;
|
||||
m_endpointCount = ec;
|
||||
for (unsigned int i = 0; i < ec; ++i) {
|
||||
int tmp = _at[i].unmarshal(data + p,len - p);
|
||||
int tmp = m_at[i].unmarshal(data + p, len - p);
|
||||
if (tmp < 0)
|
||||
return -1;
|
||||
p += tmp;
|
||||
|
@ -99,18 +99,18 @@ int Locator::unmarshal(const uint8_t *restrict data,const int len) noexcept
|
|||
p += 2;
|
||||
if (sl > ZT_SIGNATURE_BUFFER_SIZE)
|
||||
return -1;
|
||||
_signatureLength = sl;
|
||||
m_signatureLength = sl;
|
||||
if ((p + (int)sl) > len)
|
||||
return -1;
|
||||
Utils::copy(_signature,data + p,sl);
|
||||
Utils::copy(m_signature, data + p, sl);
|
||||
p += (int)sl;
|
||||
|
||||
if ((p + 2) > len)
|
||||
return -1;
|
||||
_flags = Utils::loadBigEndian<uint16_t>(data + p);
|
||||
m_flags = Utils::loadBigEndian<uint16_t>(data + p);
|
||||
p += 2;
|
||||
} else {
|
||||
_ts = 0;
|
||||
m_ts = 0;
|
||||
}
|
||||
|
||||
return p;
|
||||
|
|
|
@ -47,32 +47,32 @@ public:
|
|||
/**
|
||||
* @return Timestamp (a.k.a. revision number) set by Location signer
|
||||
*/
|
||||
ZT_INLINE int64_t timestamp() const noexcept { return _ts; }
|
||||
ZT_INLINE int64_t timestamp() const noexcept { return m_ts; }
|
||||
|
||||
/**
|
||||
* @return True if locator is signed
|
||||
*/
|
||||
ZT_INLINE bool isSigned() const noexcept { return (_signatureLength > 0); }
|
||||
ZT_INLINE bool isSigned() const noexcept { return (m_signatureLength > 0); }
|
||||
|
||||
/**
|
||||
* @return Length of signature in bytes or 0 if none
|
||||
*/
|
||||
ZT_INLINE unsigned int signatureLength() const noexcept { return _signatureLength; }
|
||||
ZT_INLINE unsigned int signatureLength() const noexcept { return m_signatureLength; }
|
||||
|
||||
/**
|
||||
* @return Pointer to signature bytes
|
||||
*/
|
||||
ZT_INLINE const uint8_t *signature() const noexcept { return _signature; }
|
||||
ZT_INLINE const uint8_t *signature() const noexcept { return m_signature; }
|
||||
|
||||
/**
|
||||
* @return Number of endpoints in this locator
|
||||
*/
|
||||
ZT_INLINE unsigned int endpointCount() const noexcept { return _endpointCount; }
|
||||
ZT_INLINE unsigned int endpointCount() const noexcept { return m_endpointCount; }
|
||||
|
||||
/**
|
||||
* @return Pointer to array of endpoints
|
||||
*/
|
||||
ZT_INLINE const Endpoint *endpoints() const noexcept { return _at; }
|
||||
ZT_INLINE const Endpoint *endpoints() const noexcept { return m_at; }
|
||||
|
||||
/**
|
||||
* Add an endpoint to this locator
|
||||
|
@ -85,9 +85,9 @@ public:
|
|||
*/
|
||||
ZT_INLINE bool add(const Endpoint &ep) noexcept
|
||||
{
|
||||
if (_endpointCount >= ZT_LOCATOR_MAX_ENDPOINTS)
|
||||
if (m_endpointCount >= ZT_LOCATOR_MAX_ENDPOINTS)
|
||||
return false;
|
||||
_at[_endpointCount++] = ep;
|
||||
m_at[m_endpointCount++] = ep;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -110,19 +110,19 @@ public:
|
|||
*/
|
||||
bool verify(const Identity &id) const noexcept;
|
||||
|
||||
explicit ZT_INLINE operator bool() const noexcept { return (_ts != 0); }
|
||||
explicit ZT_INLINE operator bool() const noexcept { return (m_ts != 0); }
|
||||
|
||||
static constexpr int marshalSizeMax() noexcept { return ZT_LOCATOR_MARSHAL_SIZE_MAX; }
|
||||
int marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX],bool excludeSignature = false) const noexcept;
|
||||
int unmarshal(const uint8_t *restrict data,int len) noexcept;
|
||||
|
||||
private:
|
||||
int64_t _ts;
|
||||
unsigned int _endpointCount;
|
||||
unsigned int _signatureLength;
|
||||
Endpoint _at[ZT_LOCATOR_MAX_ENDPOINTS];
|
||||
uint16_t _flags;
|
||||
uint8_t _signature[ZT_SIGNATURE_BUFFER_SIZE];
|
||||
int64_t m_ts;
|
||||
unsigned int m_endpointCount;
|
||||
unsigned int m_signatureLength;
|
||||
Endpoint m_at[ZT_LOCATOR_MAX_ENDPOINTS];
|
||||
uint16_t m_flags;
|
||||
uint8_t m_signature[ZT_SIGNATURE_BUFFER_SIZE];
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
78
node/MAC.hpp
78
node/MAC.hpp
|
@ -31,26 +31,26 @@ namespace ZeroTier {
|
|||
class MAC : public TriviallyCopyable
|
||||
{
|
||||
public:
|
||||
ZT_INLINE MAC() noexcept : _m(0ULL) {}
|
||||
ZT_INLINE MAC(const uint8_t a,const uint8_t b,const uint8_t c,const uint8_t d,const uint8_t e,const uint8_t f) noexcept : _m((((uint64_t)a) << 40U) | (((uint64_t)b) << 32U) | (((uint64_t)c) << 24U) | (((uint64_t)d) << 16U) | (((uint64_t)e) << 8U) | ((uint64_t)f) ) {}
|
||||
explicit ZT_INLINE MAC(const uint64_t m) noexcept : _m(m) {}
|
||||
ZT_INLINE MAC() noexcept : m_mac(0ULL) {}
|
||||
ZT_INLINE MAC(const uint8_t a,const uint8_t b,const uint8_t c,const uint8_t d,const uint8_t e,const uint8_t f) noexcept : m_mac((((uint64_t)a) << 40U) | (((uint64_t)b) << 32U) | (((uint64_t)c) << 24U) | (((uint64_t)d) << 16U) | (((uint64_t)e) << 8U) | ((uint64_t)f) ) {}
|
||||
explicit ZT_INLINE MAC(const uint64_t m) noexcept : m_mac(m) {}
|
||||
explicit ZT_INLINE MAC(const uint8_t b[6]) noexcept { setTo(b); } // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
|
||||
ZT_INLINE MAC(const Address &ztaddr,const uint64_t nwid) noexcept { fromAddress(ztaddr,nwid); } // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
|
||||
|
||||
/**
|
||||
* @return MAC in 64-bit integer
|
||||
*/
|
||||
ZT_INLINE uint64_t toInt() const noexcept { return _m; }
|
||||
ZT_INLINE uint64_t toInt() const noexcept { return m_mac; }
|
||||
|
||||
/**
|
||||
* Set MAC to zero
|
||||
*/
|
||||
ZT_INLINE void zero() noexcept { _m = 0ULL; }
|
||||
ZT_INLINE void zero() noexcept { m_mac = 0ULL; }
|
||||
|
||||
/**
|
||||
* @return True if MAC is non-zero
|
||||
*/
|
||||
ZT_INLINE operator bool() const noexcept { return (_m != 0ULL); } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
|
||||
ZT_INLINE operator bool() const noexcept { return (m_mac != 0ULL); } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
|
||||
|
||||
/**
|
||||
* @param bits Raw MAC in big-endian byte order
|
||||
|
@ -58,7 +58,7 @@ public:
|
|||
*/
|
||||
ZT_INLINE void setTo(const uint8_t b[6]) noexcept
|
||||
{
|
||||
_m = ((uint64_t)b[0] << 40U) | ((uint64_t)b[1] << 32U) | ((uint64_t)b[2] << 24U) | ((uint64_t)b[3] << 16U) | ((uint64_t)b[4] << 8U) | (uint64_t)b[5];
|
||||
m_mac = ((uint64_t)b[0] << 40U) | ((uint64_t)b[1] << 32U) | ((uint64_t)b[2] << 24U) | ((uint64_t)b[3] << 16U) | ((uint64_t)b[4] << 8U) | (uint64_t)b[5];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -67,23 +67,23 @@ public:
|
|||
*/
|
||||
ZT_INLINE void copyTo(uint8_t b[6]) const noexcept
|
||||
{
|
||||
b[0] = (uint8_t)(_m >> 40U);
|
||||
b[1] = (uint8_t)(_m >> 32U);
|
||||
b[2] = (uint8_t)(_m >> 24U);
|
||||
b[3] = (uint8_t)(_m >> 16U);
|
||||
b[4] = (uint8_t)(_m >> 8U);
|
||||
b[5] = (uint8_t)_m;
|
||||
b[0] = (uint8_t)(m_mac >> 40U);
|
||||
b[1] = (uint8_t)(m_mac >> 32U);
|
||||
b[2] = (uint8_t)(m_mac >> 24U);
|
||||
b[3] = (uint8_t)(m_mac >> 16U);
|
||||
b[4] = (uint8_t)(m_mac >> 8U);
|
||||
b[5] = (uint8_t)m_mac;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if this is broadcast (all 0xff)
|
||||
*/
|
||||
ZT_INLINE bool isBroadcast() const noexcept { return _m; }
|
||||
ZT_INLINE bool isBroadcast() const noexcept { return m_mac; }
|
||||
|
||||
/**
|
||||
* @return True if this is a multicast MAC
|
||||
*/
|
||||
ZT_INLINE bool isMulticast() const noexcept { return ((_m & 0x010000000000ULL) != 0ULL); }
|
||||
ZT_INLINE bool isMulticast() const noexcept { return ((m_mac & 0x010000000000ULL) != 0ULL); }
|
||||
|
||||
/**
|
||||
* Set this MAC to a MAC derived from an address and a network ID
|
||||
|
@ -100,7 +100,7 @@ public:
|
|||
m ^= ((nwid >> 24U) & 0xffU) << 16U;
|
||||
m ^= ((nwid >> 32U) & 0xffU) << 8U;
|
||||
m ^= (nwid >> 40U) & 0xffU;
|
||||
_m = m;
|
||||
m_mac = m;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -112,7 +112,7 @@ public:
|
|||
*/
|
||||
ZT_INLINE Address toAddress(uint64_t nwid) const noexcept
|
||||
{
|
||||
uint64_t a = _m & 0xffffffffffULL; // least significant 40 bits of MAC are formed from address
|
||||
uint64_t a = m_mac & 0xffffffffffULL; // least significant 40 bits of MAC are formed from address
|
||||
a ^= ((nwid >> 8U) & 0xffU) << 32U; // ... XORed with bits 8-48 of the nwid in little-endian byte order, so unmask it
|
||||
a ^= ((nwid >> 16U) & 0xffU) << 24U;
|
||||
a ^= ((nwid >> 24U) & 0xffU) << 16U;
|
||||
|
@ -135,49 +135,49 @@ public:
|
|||
* @param i Value from 0 to 5 (inclusive)
|
||||
* @return Byte at said position (address interpreted in big-endian order)
|
||||
*/
|
||||
ZT_INLINE uint8_t operator[](unsigned int i) const noexcept { return (uint8_t)(_m >> (40 - (i * 8))); }
|
||||
ZT_INLINE uint8_t operator[](unsigned int i) const noexcept { return (uint8_t)(m_mac >> (40 - (i * 8))); }
|
||||
|
||||
/**
|
||||
* @return 6, which is the number of bytes in a MAC, for container compliance
|
||||
*/
|
||||
ZT_INLINE unsigned int size() const noexcept { return 6; }
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept { return (unsigned long)Utils::hash64(_m); }
|
||||
ZT_INLINE unsigned long hashCode() const noexcept { return (unsigned long)Utils::hash64(m_mac); }
|
||||
|
||||
ZT_INLINE char *toString(char buf[18]) const noexcept
|
||||
{
|
||||
buf[0] = Utils::HEXCHARS[(_m >> 44U) & 0xfU];
|
||||
buf[1] = Utils::HEXCHARS[(_m >> 40U) & 0xfU];
|
||||
buf[0] = Utils::HEXCHARS[(m_mac >> 44U) & 0xfU];
|
||||
buf[1] = Utils::HEXCHARS[(m_mac >> 40U) & 0xfU];
|
||||
buf[2] = ':';
|
||||
buf[3] = Utils::HEXCHARS[(_m >> 36U) & 0xfU];
|
||||
buf[4] = Utils::HEXCHARS[(_m >> 32U) & 0xfU];
|
||||
buf[3] = Utils::HEXCHARS[(m_mac >> 36U) & 0xfU];
|
||||
buf[4] = Utils::HEXCHARS[(m_mac >> 32U) & 0xfU];
|
||||
buf[5] = ':';
|
||||
buf[6] = Utils::HEXCHARS[(_m >> 28U) & 0xfU];
|
||||
buf[7] = Utils::HEXCHARS[(_m >> 24U) & 0xfU];
|
||||
buf[6] = Utils::HEXCHARS[(m_mac >> 28U) & 0xfU];
|
||||
buf[7] = Utils::HEXCHARS[(m_mac >> 24U) & 0xfU];
|
||||
buf[8] = ':';
|
||||
buf[9] = Utils::HEXCHARS[(_m >> 20U) & 0xfU];
|
||||
buf[10] = Utils::HEXCHARS[(_m >> 16U) & 0xfU];
|
||||
buf[9] = Utils::HEXCHARS[(m_mac >> 20U) & 0xfU];
|
||||
buf[10] = Utils::HEXCHARS[(m_mac >> 16U) & 0xfU];
|
||||
buf[11] = ':';
|
||||
buf[12] = Utils::HEXCHARS[(_m >> 12U) & 0xfU];
|
||||
buf[13] = Utils::HEXCHARS[(_m >> 8U) & 0xfU];
|
||||
buf[12] = Utils::HEXCHARS[(m_mac >> 12U) & 0xfU];
|
||||
buf[13] = Utils::HEXCHARS[(m_mac >> 8U) & 0xfU];
|
||||
buf[14] = ':';
|
||||
buf[15] = Utils::HEXCHARS[(_m >> 4U) & 0xfU];
|
||||
buf[16] = Utils::HEXCHARS[_m & 0xfU];
|
||||
buf[15] = Utils::HEXCHARS[(m_mac >> 4U) & 0xfU];
|
||||
buf[16] = Utils::HEXCHARS[m_mac & 0xfU];
|
||||
buf[17] = (char)0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
ZT_INLINE MAC &operator=(const uint64_t m) noexcept { _m = m; return *this; }
|
||||
ZT_INLINE MAC &operator=(const uint64_t m) noexcept { m_mac = m; return *this; }
|
||||
|
||||
ZT_INLINE bool operator==(const MAC &m) const noexcept { return (_m == m._m); }
|
||||
ZT_INLINE bool operator!=(const MAC &m) const noexcept { return (_m != m._m); }
|
||||
ZT_INLINE bool operator<(const MAC &m) const noexcept { return (_m < m._m); }
|
||||
ZT_INLINE bool operator<=(const MAC &m) const noexcept { return (_m <= m._m); }
|
||||
ZT_INLINE bool operator>(const MAC &m) const noexcept { return (_m > m._m); }
|
||||
ZT_INLINE bool operator>=(const MAC &m) const noexcept { return (_m >= m._m); }
|
||||
ZT_INLINE bool operator==(const MAC &m) const noexcept { return (m_mac == m.m_mac); }
|
||||
ZT_INLINE bool operator!=(const MAC &m) const noexcept { return (m_mac != m.m_mac); }
|
||||
ZT_INLINE bool operator<(const MAC &m) const noexcept { return (m_mac < m.m_mac); }
|
||||
ZT_INLINE bool operator<=(const MAC &m) const noexcept { return (m_mac <= m.m_mac); }
|
||||
ZT_INLINE bool operator>(const MAC &m) const noexcept { return (m_mac > m.m_mac); }
|
||||
ZT_INLINE bool operator>=(const MAC &m) const noexcept { return (m_mac >= m.m_mac); }
|
||||
|
||||
private:
|
||||
uint64_t _m;
|
||||
uint64_t m_mac;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -21,10 +21,10 @@
|
|||
namespace ZeroTier {
|
||||
|
||||
Membership::Membership() :
|
||||
_comRevocationThreshold(0),
|
||||
_lastPushedCredentials(0),
|
||||
_comAgreementLocalTimestamp(0),
|
||||
_comAgreementRemoteTimestamp(0)
|
||||
m_comRevocationThreshold(0),
|
||||
m_lastPushedCredentials(0),
|
||||
m_comAgreementLocalTimestamp(0),
|
||||
m_comAgreementRemoteTimestamp(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -110,30 +110,30 @@ void Membership::pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const i
|
|||
}
|
||||
}
|
||||
|
||||
_lastPushedCredentials = now;
|
||||
m_lastPushedCredentials = now;
|
||||
}
|
||||
|
||||
void Membership::clean(const int64_t now,const NetworkConfig &nconf)
|
||||
{
|
||||
_cleanCredImpl<Tag>(nconf,_remoteTags);
|
||||
_cleanCredImpl<Capability>(nconf,_remoteCaps);
|
||||
_cleanCredImpl<CertificateOfOwnership>(nconf,_remoteCoos);
|
||||
m_cleanCredImpl<Tag>(nconf, m_remoteTags);
|
||||
m_cleanCredImpl<Capability>(nconf, m_remoteCaps);
|
||||
m_cleanCredImpl<CertificateOfOwnership>(nconf, m_remoteCoos);
|
||||
}
|
||||
|
||||
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const CertificateOfMembership &com)
|
||||
{
|
||||
const int64_t newts = com.timestamp();
|
||||
if (newts <= _comRevocationThreshold) {
|
||||
if (newts <= m_comRevocationThreshold) {
|
||||
RR->t->credentialRejected(tPtr,0xd9992121,com.networkId(),sourcePeerIdentity.address(),sourcePeerIdentity,com.id(),com.timestamp(),ZT_CREDENTIAL_TYPE_COM,ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED);
|
||||
return ADD_REJECTED;
|
||||
}
|
||||
|
||||
const int64_t oldts = _com.timestamp();
|
||||
const int64_t oldts = m_com.timestamp();
|
||||
if (newts < oldts) {
|
||||
RR->t->credentialRejected(tPtr,0xd9928192,com.networkId(),sourcePeerIdentity.address(),sourcePeerIdentity,com.id(),com.timestamp(),ZT_CREDENTIAL_TYPE_COM,ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST);
|
||||
return ADD_REJECTED;
|
||||
}
|
||||
if ((newts == oldts)&&(_com == com))
|
||||
if ((newts == oldts)&&(m_com == com))
|
||||
return ADD_ACCEPTED_REDUNDANT;
|
||||
|
||||
switch(com.verify(RR,tPtr)) {
|
||||
|
@ -141,7 +141,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
|
|||
RR->t->credentialRejected(tPtr,0x0f198241,com.networkId(),sourcePeerIdentity.address(),sourcePeerIdentity,com.id(),com.timestamp(),ZT_CREDENTIAL_TYPE_COM,ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
|
||||
return Membership::ADD_REJECTED;
|
||||
case Credential::VERIFY_OK:
|
||||
_com = com;
|
||||
m_com = com;
|
||||
return ADD_ACCEPTED_NEW;
|
||||
case Credential::VERIFY_BAD_SIGNATURE:
|
||||
RR->t->credentialRejected(tPtr,0xbaf0aaaa,com.networkId(),sourcePeerIdentity.address(),sourcePeerIdentity,com.id(),com.timestamp(),ZT_CREDENTIAL_TYPE_COM,ZT_TRACE_CREDENTIAL_REJECTION_REASON_SIGNATURE_VERIFICATION_FAILED);
|
||||
|
@ -191,9 +191,9 @@ static ZT_INLINE Membership::AddCredentialResult _addCredImpl(
|
|||
return Membership::ADD_DEFERRED_FOR_WHOIS;
|
||||
}
|
||||
}
|
||||
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const Tag &tag) { return _addCredImpl<Tag>(_remoteTags,_revocations,RR,tPtr,sourcePeerIdentity,nconf,tag); }
|
||||
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const Capability &cap) { return _addCredImpl<Capability>(_remoteCaps,_revocations,RR,tPtr,sourcePeerIdentity,nconf,cap); }
|
||||
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const CertificateOfOwnership &coo) { return _addCredImpl<CertificateOfOwnership>(_remoteCoos,_revocations,RR,tPtr,sourcePeerIdentity,nconf,coo); }
|
||||
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const Tag &tag) { return _addCredImpl<Tag>(m_remoteTags, m_revocations, RR, tPtr, sourcePeerIdentity, nconf, tag); }
|
||||
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const Capability &cap) { return _addCredImpl<Capability>(m_remoteCaps, m_revocations, RR, tPtr, sourcePeerIdentity, nconf, cap); }
|
||||
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const CertificateOfOwnership &coo) { return _addCredImpl<CertificateOfOwnership>(m_remoteCoos, m_revocations, RR, tPtr, sourcePeerIdentity, nconf, coo); }
|
||||
|
||||
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const Revocation &rev)
|
||||
{
|
||||
|
@ -206,18 +206,18 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
|
|||
const ZT_CredentialType ct = rev.typeBeingRevoked();
|
||||
switch(ct) {
|
||||
case ZT_CREDENTIAL_TYPE_COM:
|
||||
if (rev.threshold() > _comRevocationThreshold) {
|
||||
_comRevocationThreshold = rev.threshold();
|
||||
if (rev.threshold() > m_comRevocationThreshold) {
|
||||
m_comRevocationThreshold = rev.threshold();
|
||||
return ADD_ACCEPTED_NEW;
|
||||
}
|
||||
return ADD_ACCEPTED_REDUNDANT;
|
||||
case ZT_CREDENTIAL_TYPE_CAPABILITY:
|
||||
case ZT_CREDENTIAL_TYPE_TAG:
|
||||
case ZT_CREDENTIAL_TYPE_COO:
|
||||
rt = &(_revocations[credentialKey(ct,rev.credentialId())]);
|
||||
rt = &(m_revocations[credentialKey(ct, rev.credentialId())]);
|
||||
if (*rt < rev.threshold()) {
|
||||
*rt = rev.threshold();
|
||||
_comRevocationThreshold = rev.threshold();
|
||||
m_comRevocationThreshold = rev.threshold();
|
||||
return ADD_ACCEPTED_NEW;
|
||||
}
|
||||
return ADD_ACCEPTED_REDUNDANT;
|
||||
|
@ -231,7 +231,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
|
|||
}
|
||||
}
|
||||
|
||||
bool Membership::_isUnspoofableAddress(const NetworkConfig &nconf,const InetAddress &ip) const noexcept
|
||||
bool Membership::m_isUnspoofableAddress(const NetworkConfig &nconf, const InetAddress &ip) const noexcept
|
||||
{
|
||||
if ((ip.isV6())&&(nconf.ndpEmulation())) {
|
||||
const InetAddress sixpl(InetAddress::makeIpv66plane(nconf.networkId,nconf.issuedTo.toInt()));
|
||||
|
|
|
@ -64,7 +64,7 @@ public:
|
|||
/**
|
||||
* @return Time we last pushed credentials to this member
|
||||
*/
|
||||
ZT_INLINE int64_t lastPushedCredentials() const noexcept { return _lastPushedCredentials; }
|
||||
ZT_INLINE int64_t lastPushedCredentials() const noexcept { return m_lastPushedCredentials; }
|
||||
|
||||
/**
|
||||
* Get a remote member's tag (if we have it)
|
||||
|
@ -75,8 +75,8 @@ public:
|
|||
*/
|
||||
ZT_INLINE const Tag *getTag(const NetworkConfig &nconf,const uint32_t id) const noexcept
|
||||
{
|
||||
const Tag *const t = _remoteTags.get(id);
|
||||
return (((t)&&(_isCredentialTimestampValid(nconf,*t))) ? t : (Tag *)0);
|
||||
const Tag *const t = m_remoteTags.get(id);
|
||||
return (((t)&&(m_isCredentialTimestampValid(nconf, *t))) ? t : (Tag *)0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -103,10 +103,10 @@ public:
|
|||
template<typename T>
|
||||
ZT_INLINE bool peerOwnsAddress(const NetworkConfig &nconf,const T &r) const noexcept
|
||||
{
|
||||
if (_isUnspoofableAddress(nconf,r))
|
||||
if (s_isUnspoofableAddress(nconf, r))
|
||||
return true;
|
||||
for(Map< uint32_t,CertificateOfOwnership >::const_iterator i(_remoteCoos.begin());i!=_remoteCoos.end();++i) {
|
||||
if (_isCredentialTimestampValid(nconf,i->second)&&(i->second.owns(r)))
|
||||
for(Map< uint32_t,CertificateOfOwnership >::const_iterator i(m_remoteCoos.begin());i != m_remoteCoos.end();++i) {
|
||||
if (m_isCredentialTimestampValid(nconf, i->second) && (i->second.owns(r)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -119,9 +119,9 @@ public:
|
|||
*/
|
||||
ZT_INLINE bool certificateOfMembershipAgress(const CertificateOfMembership &localCom,const Identity &remoteIdentity)
|
||||
{
|
||||
if ((_comAgreementLocalTimestamp == localCom.timestamp())&&(_comAgreementRemoteTimestamp == _com.timestamp()))
|
||||
if ((m_comAgreementLocalTimestamp == localCom.timestamp()) && (m_comAgreementRemoteTimestamp == m_com.timestamp()))
|
||||
return true;
|
||||
if (_com.agreesWith(localCom)) {
|
||||
if (m_com.agreesWith(localCom)) {
|
||||
// SECURITY: newer network controllers embed the full fingerprint into the COM. If we are
|
||||
// joined to a network managed by one of these, our COM will contain one. If it's present
|
||||
// we compare vs the other and require them to match. If our COM does not contain a full
|
||||
|
@ -130,18 +130,18 @@ public:
|
|||
// and in so doing indicates if it's new or old. However this will go away after a while
|
||||
// once we can be pretty sure there are no ancient controllers around.
|
||||
if (localCom.issuedTo().haveHash()) {
|
||||
if (localCom.issuedTo() != _com.issuedTo())
|
||||
if (localCom.issuedTo() != m_com.issuedTo())
|
||||
return false;
|
||||
} else {
|
||||
// LEGACY: support networks run by old controllers.
|
||||
if (localCom.issuedTo().address() != _com.issuedTo().address())
|
||||
if (localCom.issuedTo().address() != m_com.issuedTo().address())
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remember that these two COMs agreed. If any are updated this is invalidated and a full
|
||||
// agreement check will be done again.
|
||||
_comAgreementLocalTimestamp = localCom.timestamp();
|
||||
_comAgreementRemoteTimestamp = _com.timestamp();
|
||||
m_comAgreementLocalTimestamp = localCom.timestamp();
|
||||
m_comAgreementRemoteTimestamp = m_com.timestamp();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -158,77 +158,77 @@ private:
|
|||
// This returns true if a resource is an IPv6 NDP-emulated address. These embed the ZT
|
||||
// address of the peer and therefore cannot be spoofed, causing peerOwnsAddress() to
|
||||
// always return true for them. A certificate is not required for these.
|
||||
ZT_INLINE bool _isUnspoofableAddress(const NetworkConfig &nconf,const MAC &m) const noexcept { return false; }
|
||||
bool _isUnspoofableAddress(const NetworkConfig &nconf,const InetAddress &ip) const noexcept;
|
||||
ZT_INLINE static bool s_isUnspoofableAddress(const NetworkConfig &nconf, const MAC &m) noexcept { return false; }
|
||||
bool m_isUnspoofableAddress(const NetworkConfig &nconf, const InetAddress &ip) const noexcept;
|
||||
|
||||
// This compares the remote credential's timestamp to the timestamp in our network config
|
||||
// plus or minus the permitted maximum timestamp delta.
|
||||
template<typename C>
|
||||
ZT_INLINE bool _isCredentialTimestampValid(const NetworkConfig &nconf,const C &remoteCredential) const noexcept
|
||||
ZT_INLINE bool m_isCredentialTimestampValid(const NetworkConfig &nconf, const C &remoteCredential) const noexcept
|
||||
{
|
||||
const int64_t ts = remoteCredential.timestamp();
|
||||
if (((ts >= nconf.timestamp) ? (ts - nconf.timestamp) : (nconf.timestamp - ts)) <= nconf.credentialTimeMaxDelta) {
|
||||
const int64_t *threshold = _revocations.get(credentialKey(C::credentialType(),remoteCredential.id()));
|
||||
const int64_t *threshold = m_revocations.get(credentialKey(C::credentialType(), remoteCredential.id()));
|
||||
return ((!threshold)||(ts > *threshold));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename C>
|
||||
ZT_INLINE void _cleanCredImpl(const NetworkConfig &nconf,Map<uint32_t,C> &remoteCreds)
|
||||
ZT_INLINE void m_cleanCredImpl(const NetworkConfig &nconf, Map<uint32_t,C> &remoteCreds)
|
||||
{
|
||||
for(typename Map<uint32_t,C>::iterator i(remoteCreds.begin());i!=remoteCreds.end();) {
|
||||
if (!_isCredentialTimestampValid(nconf,i->second))
|
||||
if (!m_isCredentialTimestampValid(nconf, i->second))
|
||||
remoteCreds.erase(i++);
|
||||
else ++i;
|
||||
}
|
||||
}
|
||||
|
||||
// Revocation threshold for COM or 0 if none
|
||||
int64_t _comRevocationThreshold;
|
||||
int64_t m_comRevocationThreshold;
|
||||
|
||||
// Time we last pushed credentials
|
||||
int64_t _lastPushedCredentials;
|
||||
int64_t m_lastPushedCredentials;
|
||||
|
||||
// COM timestamps at which we last agreed-- used to memo-ize agreement and avoid having to recompute constantly.
|
||||
int64_t _comAgreementLocalTimestamp,_comAgreementRemoteTimestamp;
|
||||
int64_t m_comAgreementLocalTimestamp,m_comAgreementRemoteTimestamp;
|
||||
|
||||
// Remote member's latest network COM
|
||||
CertificateOfMembership _com;
|
||||
CertificateOfMembership m_com;
|
||||
|
||||
// Revocations by credentialKey()
|
||||
Map< uint64_t,int64_t > _revocations;
|
||||
Map<uint64_t,int64_t> m_revocations;
|
||||
|
||||
// Remote credentials that we have received from this member (and that are valid)
|
||||
Map< uint32_t,Tag > _remoteTags;
|
||||
Map< uint32_t,Capability > _remoteCaps;
|
||||
Map< uint32_t,CertificateOfOwnership > _remoteCoos;
|
||||
Map<uint32_t,Tag> m_remoteTags;
|
||||
Map<uint32_t,Capability> m_remoteCaps;
|
||||
Map<uint32_t,CertificateOfOwnership> m_remoteCoos;
|
||||
|
||||
public:
|
||||
class CapabilityIterator
|
||||
{
|
||||
public:
|
||||
ZT_INLINE CapabilityIterator(Membership &m,const NetworkConfig &nconf) noexcept :
|
||||
_hti(m._remoteCaps.begin()),
|
||||
_m(m),
|
||||
_nconf(nconf)
|
||||
m_hti(m.m_remoteCaps.begin()),
|
||||
m_parent(m),
|
||||
m_nconf(nconf)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE Capability *next() noexcept
|
||||
{
|
||||
while (_hti != _m._remoteCaps.end()) {
|
||||
Map< uint32_t,Capability >::iterator i(_hti++); // NOLINT(hicpp-use-auto,modernize-use-auto)
|
||||
if (_m._isCredentialTimestampValid(_nconf,i->second))
|
||||
while (m_hti != m_parent.m_remoteCaps.end()) {
|
||||
Map< uint32_t,Capability >::iterator i(m_hti++); // NOLINT(hicpp-use-auto,modernize-use-auto)
|
||||
if (m_parent.m_isCredentialTimestampValid(m_nconf, i->second))
|
||||
return &(i->second);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
Map< uint32_t,Capability >::iterator _hti;
|
||||
Membership &_m;
|
||||
const NetworkConfig &_nconf;
|
||||
Map< uint32_t,Capability >::iterator m_hti;
|
||||
Membership &m_parent;
|
||||
const NetworkConfig &m_nconf;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -57,10 +57,10 @@ public:
|
|||
// the log size and then if it's a new bucket setting it or otherwise adding
|
||||
// to it.
|
||||
const unsigned long bucket = ((unsigned long)(now / TUNIT)) % LSIZE;
|
||||
if (_bucket.exchange(bucket) != bucket) {
|
||||
_totalExclCounts.fetch_add(_counts[bucket].exchange(count));
|
||||
if (m_bucket.exchange(bucket) != bucket) {
|
||||
m_totalExclCounts.fetch_add(m_counts[bucket].exchange(count));
|
||||
} else {
|
||||
_counts[bucket].fetch_add(count);
|
||||
m_counts[bucket].fetch_add(count);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,15 +75,15 @@ public:
|
|||
{
|
||||
total = 0;
|
||||
for(unsigned long i=0;i<LSIZE;++i)
|
||||
total += _counts[i].load();
|
||||
total += m_counts[i].load();
|
||||
rate = (double)total / (double)LSIZE;
|
||||
total += _totalExclCounts.load();
|
||||
total += m_totalExclCounts.load();
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic<uint64_t> _counts[LSIZE];
|
||||
std::atomic<uint64_t> _totalExclCounts;
|
||||
std::atomic<unsigned long> _bucket;
|
||||
std::atomic<uint64_t> m_counts[LSIZE];
|
||||
std::atomic<uint64_t> m_totalExclCounts;
|
||||
std::atomic<unsigned long> m_bucket;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -42,8 +42,8 @@ namespace ZeroTier {
|
|||
class MulticastGroup : public TriviallyCopyable
|
||||
{
|
||||
public:
|
||||
ZT_INLINE MulticastGroup() noexcept : _mac(),_adi(0) {}
|
||||
ZT_INLINE MulticastGroup(const MAC &m,uint32_t a) noexcept : _mac(m),_adi(a) {}
|
||||
ZT_INLINE MulticastGroup() noexcept : m_mac(), m_adi(0) {}
|
||||
ZT_INLINE MulticastGroup(const MAC &m,uint32_t a) noexcept : m_mac(m), m_adi(a) {}
|
||||
|
||||
/**
|
||||
* Derive the multicast group used for address resolution (ARP/NDP) for an IP
|
||||
|
@ -73,32 +73,32 @@ public:
|
|||
/**
|
||||
* @return Ethernet MAC portion of multicast group
|
||||
*/
|
||||
ZT_INLINE const MAC &mac() const noexcept { return _mac; }
|
||||
ZT_INLINE const MAC &mac() const noexcept { return m_mac; }
|
||||
|
||||
/**
|
||||
* @return Additional distinguishing information, which is normally zero except for IPv4 ARP where it's the IPv4 address
|
||||
*/
|
||||
ZT_INLINE uint32_t adi() const { return _adi; }
|
||||
ZT_INLINE uint32_t adi() const { return m_adi; }
|
||||
|
||||
ZT_INLINE bool operator==(const MulticastGroup &g) const noexcept { return ((_mac == g._mac) && (_adi == g._adi)); }
|
||||
ZT_INLINE bool operator!=(const MulticastGroup &g) const noexcept { return ((_mac != g._mac) || (_adi != g._adi)); }
|
||||
ZT_INLINE bool operator==(const MulticastGroup &g) const noexcept { return ((m_mac == g.m_mac) && (m_adi == g.m_adi)); }
|
||||
ZT_INLINE bool operator!=(const MulticastGroup &g) const noexcept { return ((m_mac != g.m_mac) || (m_adi != g.m_adi)); }
|
||||
ZT_INLINE bool operator<(const MulticastGroup &g) const noexcept
|
||||
{
|
||||
if (_mac < g._mac)
|
||||
if (m_mac < g.m_mac)
|
||||
return true;
|
||||
else if (_mac == g._mac)
|
||||
return (_adi < g._adi);
|
||||
else if (m_mac == g.m_mac)
|
||||
return (m_adi < g.m_adi);
|
||||
return false;
|
||||
}
|
||||
ZT_INLINE bool operator>(const MulticastGroup &g) const noexcept { return (g < *this); }
|
||||
ZT_INLINE bool operator<=(const MulticastGroup &g) const noexcept { return !(g < *this); }
|
||||
ZT_INLINE bool operator>=(const MulticastGroup &g) const noexcept { return !(*this < g); }
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept { return (_mac.hashCode() + (unsigned long)_adi); }
|
||||
ZT_INLINE unsigned long hashCode() const noexcept { return (m_mac.hashCode() + (unsigned long)m_adi); }
|
||||
|
||||
private:
|
||||
MAC _mac;
|
||||
uint32_t _adi;
|
||||
MAC m_mac;
|
||||
uint32_t m_adi;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
300
node/Network.cpp
300
node/Network.cpp
|
@ -535,20 +535,20 @@ const ZeroTier::MulticastGroup Network::BROADCAST(ZeroTier::MAC(0xffffffffffffUL
|
|||
|
||||
Network::Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,const Fingerprint &controllerFingerprint,void *uptr,const NetworkConfig *nconf) :
|
||||
RR(renv),
|
||||
_uPtr(uptr),
|
||||
_id(nwid),
|
||||
_mac(renv->identity.address(),nwid),
|
||||
_portInitialized(false),
|
||||
_lastConfigUpdate(0),
|
||||
_destroyed(false),
|
||||
m_uPtr(uptr),
|
||||
m_id(nwid),
|
||||
m_mac(renv->identity.address(), nwid),
|
||||
m_portInitialized(false),
|
||||
m_lastConfigUpdate(0),
|
||||
m_destroyed(false),
|
||||
_netconfFailure(NETCONF_FAILURE_NONE)
|
||||
{
|
||||
if (controllerFingerprint)
|
||||
_controllerFingerprint = controllerFingerprint;
|
||||
m_controllerFingerprint = controllerFingerprint;
|
||||
|
||||
if (nconf) {
|
||||
this->setConfiguration(tPtr,*nconf,false);
|
||||
_lastConfigUpdate = 0; // still want to re-request since it's likely outdated
|
||||
m_lastConfigUpdate = 0; // still want to re-request since it's likely outdated
|
||||
} else {
|
||||
uint64_t tmp[2];
|
||||
tmp[0] = nwid; tmp[1] = 0;
|
||||
|
@ -564,7 +564,7 @@ Network::Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,const F
|
|||
ScopedPtr<NetworkConfig> nconf2(new NetworkConfig());
|
||||
if (nconf2->fromDictionary(dict)) {
|
||||
this->setConfiguration(tPtr,*nconf2,false);
|
||||
_lastConfigUpdate = 0; // still want to re-request an update since it's likely outdated
|
||||
m_lastConfigUpdate = 0; // still want to re-request an update since it's likely outdated
|
||||
got = true;
|
||||
}
|
||||
} catch (...) {}
|
||||
|
@ -576,29 +576,29 @@ Network::Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,const F
|
|||
RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,tmp,"\n",1);
|
||||
}
|
||||
|
||||
if (!_portInitialized) {
|
||||
if (!m_portInitialized) {
|
||||
ZT_VirtualNetworkConfig ctmp;
|
||||
_externalConfig(&ctmp);
|
||||
RR->node->configureVirtualNetworkPort(tPtr,_id,&_uPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP,&ctmp);
|
||||
_portInitialized = true;
|
||||
m_externalConfig(&ctmp);
|
||||
RR->node->configureVirtualNetworkPort(tPtr, m_id, &m_uPtr, ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP, &ctmp);
|
||||
m_portInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
Network::~Network()
|
||||
{
|
||||
_memberships_l.lock();
|
||||
_config_l.lock();
|
||||
_config_l.unlock();
|
||||
_memberships_l.unlock();
|
||||
m_memberships_l.lock();
|
||||
m_config_l.lock();
|
||||
m_config_l.unlock();
|
||||
m_memberships_l.unlock();
|
||||
|
||||
ZT_VirtualNetworkConfig ctmp;
|
||||
_externalConfig(&ctmp);
|
||||
m_externalConfig(&ctmp);
|
||||
|
||||
if (_destroyed) {
|
||||
if (m_destroyed) {
|
||||
// This is done in Node::leave() so we can pass tPtr properly
|
||||
//RR->node->configureVirtualNetworkPort((void *)0,_id,&_uPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY,&ctmp);
|
||||
} else {
|
||||
RR->node->configureVirtualNetworkPort(nullptr,_id,&_uPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN,&ctmp);
|
||||
RR->node->configureVirtualNetworkPort(nullptr, m_id, &m_uPtr, ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN, &ctmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -623,20 +623,20 @@ bool Network::filterOutgoingPacket(
|
|||
unsigned int ccLength = 0;
|
||||
bool ccWatch = false;
|
||||
|
||||
Mutex::Lock l1(_memberships_l);
|
||||
Mutex::Lock l2(_config_l);
|
||||
Mutex::Lock l1(m_memberships_l);
|
||||
Mutex::Lock l2(m_config_l);
|
||||
|
||||
Membership *const membership = (ztDest) ? _memberships.get(ztDest) : nullptr;
|
||||
Membership *const membership = (ztDest) ? m_memberships.get(ztDest) : nullptr;
|
||||
|
||||
switch(_doZtFilter(RR,rrl,_config,membership,false,ztSource,ztFinalDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.rules,_config.ruleCount,cc,ccLength,ccWatch,qosBucket)) {
|
||||
switch(_doZtFilter(RR, rrl, m_config, membership, false, ztSource, ztFinalDest, macSource, macDest, frameData, frameLen, etherType, vlanId, m_config.rules, m_config.ruleCount, cc, ccLength, ccWatch, qosBucket)) {
|
||||
|
||||
case DOZTFILTER_NO_MATCH: {
|
||||
for(unsigned int c=0;c<_config.capabilityCount;++c) {
|
||||
for(unsigned int c=0;c < m_config.capabilityCount;++c) {
|
||||
ztFinalDest = ztDest; // sanity check, shouldn't be possible if there was no match
|
||||
Address cc2;
|
||||
unsigned int ccLength2 = 0;
|
||||
bool ccWatch2 = false;
|
||||
switch (_doZtFilter(RR,crrl,_config,membership,false,ztSource,ztFinalDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.capabilities[c].rules(),_config.capabilities[c].ruleCount(),cc2,ccLength2,ccWatch2,qosBucket)) {
|
||||
switch (_doZtFilter(RR, crrl, m_config, membership, false, ztSource, ztFinalDest, macSource, macDest, frameData, frameLen, etherType, vlanId, m_config.capabilities[c].rules(), m_config.capabilities[c].ruleCount(), cc2, ccLength2, ccWatch2, qosBucket)) {
|
||||
case DOZTFILTER_NO_MATCH:
|
||||
case DOZTFILTER_DROP: // explicit DROP in a capability just terminates its evaluation and is an anti-pattern
|
||||
break;
|
||||
|
@ -670,7 +670,7 @@ bool Network::filterOutgoingPacket(
|
|||
} break;
|
||||
|
||||
case DOZTFILTER_DROP:
|
||||
RR->t->networkFilter(tPtr,0xadea5a2a,_id,rrl.l,nullptr,0,0,ztSource,ztDest,macSource,macDest,(uint16_t)frameLen,frameData,(uint16_t)etherType,(uint16_t)vlanId,noTee,false,0);
|
||||
RR->t->networkFilter(tPtr, 0xadea5a2a, m_id, rrl.l, nullptr, 0, 0, ztSource, ztDest, macSource, macDest, (uint16_t)frameLen, frameData, (uint16_t)etherType, (uint16_t)vlanId, noTee, false, 0);
|
||||
return false;
|
||||
|
||||
case DOZTFILTER_REDIRECT: // interpreted as ACCEPT but ztFinalDest will have been changed in _doZtFilter()
|
||||
|
@ -719,10 +719,10 @@ bool Network::filterOutgoingPacket(
|
|||
}
|
||||
|
||||
if (localCapabilityIndex >= 0) {
|
||||
const Capability &cap = _config.capabilities[localCapabilityIndex];
|
||||
RR->t->networkFilter(tPtr,0x56ff1a93,_id,rrl.l,crrl.l,cap.id(),cap.timestamp(),ztSource,ztDest,macSource,macDest,(uint16_t)frameLen,frameData,(uint16_t)etherType,(uint16_t)vlanId,noTee,false,accept);
|
||||
const Capability &cap = m_config.capabilities[localCapabilityIndex];
|
||||
RR->t->networkFilter(tPtr, 0x56ff1a93, m_id, rrl.l, crrl.l, cap.id(), cap.timestamp(), ztSource, ztDest, macSource, macDest, (uint16_t)frameLen, frameData, (uint16_t)etherType, (uint16_t)vlanId, noTee, false, accept);
|
||||
} else {
|
||||
RR->t->networkFilter(tPtr,0x112fbbab,_id,rrl.l,nullptr,0,0,ztSource,ztDest,macSource,macDest,(uint16_t)frameLen,frameData,(uint16_t)etherType,(uint16_t)vlanId,noTee,false,accept);
|
||||
RR->t->networkFilter(tPtr, 0x112fbbab, m_id, rrl.l, nullptr, 0, 0, ztSource, ztDest, macSource, macDest, (uint16_t)frameLen, frameData, (uint16_t)etherType, (uint16_t)vlanId, noTee, false, accept);
|
||||
}
|
||||
|
||||
return (accept != 0);
|
||||
|
@ -749,21 +749,21 @@ int Network::filterIncomingPacket(
|
|||
|
||||
uint8_t qosBucket = 255; // For incoming packets this is a dummy value
|
||||
|
||||
Mutex::Lock l1(_memberships_l);
|
||||
Mutex::Lock l2(_config_l);
|
||||
Mutex::Lock l1(m_memberships_l);
|
||||
Mutex::Lock l2(m_config_l);
|
||||
|
||||
Membership &membership = _memberships[sourcePeer->address()];
|
||||
Membership &membership = m_memberships[sourcePeer->address()];
|
||||
|
||||
switch (_doZtFilter(RR,rrl,_config,&membership,true,sourcePeer->address(),ztFinalDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.rules,_config.ruleCount,cc,ccLength,ccWatch,qosBucket)) {
|
||||
switch (_doZtFilter(RR, rrl, m_config, &membership, true, sourcePeer->address(), ztFinalDest, macSource, macDest, frameData, frameLen, etherType, vlanId, m_config.rules, m_config.ruleCount, cc, ccLength, ccWatch, qosBucket)) {
|
||||
|
||||
case DOZTFILTER_NO_MATCH: {
|
||||
Membership::CapabilityIterator mci(membership,_config);
|
||||
Membership::CapabilityIterator mci(membership, m_config);
|
||||
while ((c = mci.next())) {
|
||||
ztFinalDest = ztDest; // sanity check, should be unmodified if there was no match
|
||||
Address cc2;
|
||||
unsigned int ccLength2 = 0;
|
||||
bool ccWatch2 = false;
|
||||
switch(_doZtFilter(RR,crrl,_config,&membership,true,sourcePeer->address(),ztFinalDest,macSource,macDest,frameData,frameLen,etherType,vlanId,c->rules(),c->ruleCount(),cc2,ccLength2,ccWatch2,qosBucket)) {
|
||||
switch(_doZtFilter(RR, crrl, m_config, &membership, true, sourcePeer->address(), ztFinalDest, macSource, macDest, frameData, frameLen, etherType, vlanId, c->rules(), c->ruleCount(), cc2, ccLength2, ccWatch2, qosBucket)) {
|
||||
case DOZTFILTER_NO_MATCH:
|
||||
case DOZTFILTER_DROP: // explicit DROP in a capability just terminates its evaluation and is an anti-pattern
|
||||
break;
|
||||
|
@ -853,31 +853,31 @@ int Network::filterIncomingPacket(
|
|||
|
||||
void Network::multicastSubscribe(void *tPtr,const MulticastGroup &mg)
|
||||
{
|
||||
Mutex::Lock l(_myMulticastGroups_l);
|
||||
if (!std::binary_search(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg)) {
|
||||
_myMulticastGroups.insert(std::upper_bound(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg),mg);
|
||||
Mutex::Lock l2(_memberships_l);
|
||||
_announceMulticastGroups(tPtr,true);
|
||||
Mutex::Lock l(m_myMulticastGroups_l);
|
||||
if (!std::binary_search(m_myMulticastGroups.begin(), m_myMulticastGroups.end(), mg)) {
|
||||
m_myMulticastGroups.insert(std::upper_bound(m_myMulticastGroups.begin(), m_myMulticastGroups.end(), mg), mg);
|
||||
Mutex::Lock l2(m_memberships_l);
|
||||
m_announceMulticastGroups(tPtr, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Network::multicastUnsubscribe(const MulticastGroup &mg)
|
||||
{
|
||||
Mutex::Lock l(_myMulticastGroups_l);
|
||||
std::vector<MulticastGroup>::iterator i(std::lower_bound(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg));
|
||||
if ( (i != _myMulticastGroups.end()) && (*i == mg) )
|
||||
_myMulticastGroups.erase(i);
|
||||
Mutex::Lock l(m_myMulticastGroups_l);
|
||||
std::vector<MulticastGroup>::iterator i(std::lower_bound(m_myMulticastGroups.begin(), m_myMulticastGroups.end(), mg));
|
||||
if ((i != m_myMulticastGroups.end()) && (*i == mg) )
|
||||
m_myMulticastGroups.erase(i);
|
||||
}
|
||||
|
||||
uint64_t Network::handleConfigChunk(void *tPtr,uint64_t packetId,const SharedPtr<Peer> &source,const Buf &chunk,int ptr,int size)
|
||||
{
|
||||
// If the controller's full fingerprint is known or was explicitly specified on join(),
|
||||
// require that the controller's identity match. Otherwise learn it.
|
||||
if (_controllerFingerprint) {
|
||||
if (source->identity().fingerprint() != _controllerFingerprint)
|
||||
if (m_controllerFingerprint) {
|
||||
if (source->identity().fingerprint() != m_controllerFingerprint)
|
||||
return 0;
|
||||
} else {
|
||||
_controllerFingerprint = source->identity().fingerprint();
|
||||
m_controllerFingerprint = source->identity().fingerprint();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1015,42 +1015,42 @@ uint64_t Network::handleConfigChunk(void *tPtr,uint64_t packetId,const SharedPtr
|
|||
|
||||
int Network::setConfiguration(void *tPtr,const NetworkConfig &nconf,bool saveToDisk)
|
||||
{
|
||||
if (_destroyed)
|
||||
if (m_destroyed)
|
||||
return 0;
|
||||
|
||||
// _lock is NOT locked when this is called
|
||||
try {
|
||||
if ((nconf.issuedTo != RR->identity.address())||(nconf.networkId != _id))
|
||||
if ((nconf.issuedTo != RR->identity.address())||(nconf.networkId != m_id))
|
||||
return 0; // invalid config that is not for us or not for this network
|
||||
if ((!Utils::allZero(nconf.issuedToFingerprintHash,ZT_FINGERPRINT_HASH_SIZE)) && (memcmp(nconf.issuedToFingerprintHash,RR->identity.fingerprint().hash(),ZT_FINGERPRINT_HASH_SIZE) != 0))
|
||||
return 0; // full identity hash is present and does not match
|
||||
|
||||
if (_config == nconf)
|
||||
if (m_config == nconf)
|
||||
return 1; // OK config, but duplicate of what we already have
|
||||
|
||||
ZT_VirtualNetworkConfig ctmp;
|
||||
bool oldPortInitialized;
|
||||
{ // do things that require lock here, but unlock before calling callbacks
|
||||
Mutex::Lock l1(_config_l);
|
||||
Mutex::Lock l1(m_config_l);
|
||||
|
||||
_config = nconf;
|
||||
_lastConfigUpdate = RR->node->now();
|
||||
m_config = nconf;
|
||||
m_lastConfigUpdate = RR->node->now();
|
||||
_netconfFailure = NETCONF_FAILURE_NONE;
|
||||
|
||||
oldPortInitialized = _portInitialized;
|
||||
_portInitialized = true;
|
||||
oldPortInitialized = m_portInitialized;
|
||||
m_portInitialized = true;
|
||||
|
||||
_externalConfig(&ctmp);
|
||||
m_externalConfig(&ctmp);
|
||||
}
|
||||
|
||||
RR->node->configureVirtualNetworkPort(tPtr,_id,&_uPtr,(oldPortInitialized) ? ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE : ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP,&ctmp);
|
||||
RR->node->configureVirtualNetworkPort(tPtr, m_id, &m_uPtr, (oldPortInitialized) ? ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE : ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP, &ctmp);
|
||||
|
||||
if (saveToDisk) {
|
||||
try {
|
||||
Dictionary d;
|
||||
if (nconf.toDictionary(d,false)) {
|
||||
uint64_t tmp[2];
|
||||
tmp[0] = _id; tmp[1] = 0;
|
||||
tmp[0] = m_id; tmp[1] = 0;
|
||||
std::vector<uint8_t> d2;
|
||||
d.encode(d2);
|
||||
RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,tmp,d2.data(),(unsigned int)d2.size());
|
||||
|
@ -1065,22 +1065,22 @@ int Network::setConfiguration(void *tPtr,const NetworkConfig &nconf,bool saveToD
|
|||
|
||||
bool Network::gate(void *tPtr,const SharedPtr<Peer> &peer) noexcept
|
||||
{
|
||||
Mutex::Lock lc(_config_l);
|
||||
Mutex::Lock lc(m_config_l);
|
||||
|
||||
if (!_config)
|
||||
if (!m_config)
|
||||
return false;
|
||||
if (_config.isPublic())
|
||||
if (m_config.isPublic())
|
||||
return true;
|
||||
|
||||
try {
|
||||
Mutex::Lock l(_memberships_l);
|
||||
Membership *m = _memberships.get(peer->address());
|
||||
Mutex::Lock l(m_memberships_l);
|
||||
Membership *m = m_memberships.get(peer->address());
|
||||
if (m) {
|
||||
// SECURITY: this method in CertificateOfMembership does a full fingerprint check as well as
|
||||
// checking certificate agreement. See Membership.hpp.
|
||||
return m->certificateOfMembershipAgress(_config.com,peer->identity());
|
||||
return m->certificateOfMembershipAgress(m_config.com, peer->identity());
|
||||
} else {
|
||||
m = &(_memberships[peer->address()]);
|
||||
m = &(m_memberships[peer->address()]);
|
||||
return false;
|
||||
}
|
||||
} catch ( ... ) {}
|
||||
|
@ -1090,20 +1090,20 @@ bool Network::gate(void *tPtr,const SharedPtr<Peer> &peer) noexcept
|
|||
|
||||
void Network::doPeriodicTasks(void *tPtr,const int64_t now)
|
||||
{
|
||||
if (_destroyed)
|
||||
if (m_destroyed)
|
||||
return;
|
||||
|
||||
if ((now - _lastConfigUpdate) >= ZT_NETWORK_AUTOCONF_DELAY)
|
||||
_requestConfiguration(tPtr);
|
||||
if ((now - m_lastConfigUpdate) >= ZT_NETWORK_AUTOCONF_DELAY)
|
||||
m_requestConfiguration(tPtr);
|
||||
|
||||
{
|
||||
Mutex::Lock l1(_memberships_l);
|
||||
Mutex::Lock l1(m_memberships_l);
|
||||
|
||||
for(Map<Address,Membership>::iterator i(_memberships.begin());i!=_memberships.end();++i)
|
||||
i->second.clean(now,_config);
|
||||
for(Map<Address,Membership>::iterator i(m_memberships.begin());i != m_memberships.end();++i)
|
||||
i->second.clean(now, m_config);
|
||||
|
||||
{
|
||||
Mutex::Lock l2(_myMulticastGroups_l);
|
||||
Mutex::Lock l2(m_myMulticastGroups_l);
|
||||
|
||||
// TODO
|
||||
/*
|
||||
|
@ -1123,17 +1123,17 @@ void Network::doPeriodicTasks(void *tPtr,const int64_t now)
|
|||
|
||||
void Network::learnBridgeRoute(const MAC &mac,const Address &addr)
|
||||
{
|
||||
Mutex::Lock _l(_remoteBridgeRoutes_l);
|
||||
_remoteBridgeRoutes[mac] = addr;
|
||||
Mutex::Lock _l(m_remoteBridgeRoutes_l);
|
||||
m_remoteBridgeRoutes[mac] = addr;
|
||||
|
||||
// Anti-DOS circuit breaker to prevent nodes from spamming us with absurd numbers of bridge routes
|
||||
while (_remoteBridgeRoutes.size() > ZT_MAX_BRIDGE_ROUTES) {
|
||||
while (m_remoteBridgeRoutes.size() > ZT_MAX_BRIDGE_ROUTES) {
|
||||
Map< Address,unsigned long > counts;
|
||||
Address maxAddr;
|
||||
unsigned long maxCount = 0;
|
||||
|
||||
// Find the address responsible for the most entries
|
||||
for(Map<MAC,Address>::iterator i(_remoteBridgeRoutes.begin());i!=_remoteBridgeRoutes.end();++i) {
|
||||
for(Map<MAC,Address>::iterator i(m_remoteBridgeRoutes.begin());i != m_remoteBridgeRoutes.end();++i) {
|
||||
const unsigned long c = ++counts[i->second];
|
||||
if (c > maxCount) {
|
||||
maxCount = c;
|
||||
|
@ -1142,9 +1142,9 @@ void Network::learnBridgeRoute(const MAC &mac,const Address &addr)
|
|||
}
|
||||
|
||||
// Kill this address from our table, since it's most likely spamming us
|
||||
for(Map<MAC,Address>::iterator i(_remoteBridgeRoutes.begin());i!=_remoteBridgeRoutes.end();) {
|
||||
for(Map<MAC,Address>::iterator i(m_remoteBridgeRoutes.begin());i != m_remoteBridgeRoutes.end();) {
|
||||
if (i->second == maxAddr)
|
||||
_remoteBridgeRoutes.erase(i++);
|
||||
m_remoteBridgeRoutes.erase(i++);
|
||||
else ++i;
|
||||
}
|
||||
}
|
||||
|
@ -1152,37 +1152,37 @@ void Network::learnBridgeRoute(const MAC &mac,const Address &addr)
|
|||
|
||||
Membership::AddCredentialResult Network::addCredential(void *tPtr,const Identity &sourcePeerIdentity,const CertificateOfMembership &com)
|
||||
{
|
||||
if (com.networkId() != _id)
|
||||
if (com.networkId() != m_id)
|
||||
return Membership::ADD_REJECTED;
|
||||
Mutex::Lock _l(_memberships_l);
|
||||
return _memberships[com.issuedTo().address()].addCredential(RR,tPtr,sourcePeerIdentity,_config,com);
|
||||
Mutex::Lock _l(m_memberships_l);
|
||||
return m_memberships[com.issuedTo().address()].addCredential(RR, tPtr, sourcePeerIdentity, m_config, com);
|
||||
}
|
||||
|
||||
Membership::AddCredentialResult Network::addCredential(void *tPtr,const Identity &sourcePeerIdentity,const Capability &cap)
|
||||
{
|
||||
if (cap.networkId() != _id)
|
||||
if (cap.networkId() != m_id)
|
||||
return Membership::ADD_REJECTED;
|
||||
Mutex::Lock _l(_memberships_l);
|
||||
return _memberships[cap.issuedTo()].addCredential(RR,tPtr,sourcePeerIdentity,_config,cap);
|
||||
Mutex::Lock _l(m_memberships_l);
|
||||
return m_memberships[cap.issuedTo()].addCredential(RR, tPtr, sourcePeerIdentity, m_config, cap);
|
||||
}
|
||||
|
||||
Membership::AddCredentialResult Network::addCredential(void *tPtr,const Identity &sourcePeerIdentity,const Tag &tag)
|
||||
{
|
||||
if (tag.networkId() != _id)
|
||||
if (tag.networkId() != m_id)
|
||||
return Membership::ADD_REJECTED;
|
||||
Mutex::Lock _l(_memberships_l);
|
||||
return _memberships[tag.issuedTo()].addCredential(RR,tPtr,sourcePeerIdentity,_config,tag);
|
||||
Mutex::Lock _l(m_memberships_l);
|
||||
return m_memberships[tag.issuedTo()].addCredential(RR, tPtr, sourcePeerIdentity, m_config, tag);
|
||||
}
|
||||
|
||||
Membership::AddCredentialResult Network::addCredential(void *tPtr,const Identity &sourcePeerIdentity,const Revocation &rev)
|
||||
{
|
||||
if (rev.networkId() != _id)
|
||||
if (rev.networkId() != m_id)
|
||||
return Membership::ADD_REJECTED;
|
||||
|
||||
Mutex::Lock l1(_memberships_l);
|
||||
Membership &m = _memberships[rev.target()];
|
||||
Mutex::Lock l1(m_memberships_l);
|
||||
Membership &m = m_memberships[rev.target()];
|
||||
|
||||
const Membership::AddCredentialResult result = m.addCredential(RR,tPtr,sourcePeerIdentity,_config,rev);
|
||||
const Membership::AddCredentialResult result = m.addCredential(RR, tPtr, sourcePeerIdentity, m_config, rev);
|
||||
|
||||
if ((result == Membership::ADD_ACCEPTED_NEW)&&(rev.fastPropagate())) {
|
||||
// TODO
|
||||
|
@ -1210,50 +1210,50 @@ Membership::AddCredentialResult Network::addCredential(void *tPtr,const Identity
|
|||
|
||||
Membership::AddCredentialResult Network::addCredential(void *tPtr,const Identity &sourcePeerIdentity,const CertificateOfOwnership &coo)
|
||||
{
|
||||
if (coo.networkId() != _id)
|
||||
if (coo.networkId() != m_id)
|
||||
return Membership::ADD_REJECTED;
|
||||
Mutex::Lock _l(_memberships_l);
|
||||
return _memberships[coo.issuedTo()].addCredential(RR,tPtr,sourcePeerIdentity,_config,coo);
|
||||
Mutex::Lock _l(m_memberships_l);
|
||||
return m_memberships[coo.issuedTo()].addCredential(RR, tPtr, sourcePeerIdentity, m_config, coo);
|
||||
}
|
||||
|
||||
void Network::pushCredentials(void *tPtr,const SharedPtr<Peer> &to,const int64_t now)
|
||||
{
|
||||
const int64_t tout = std::min(_config.credentialTimeMaxDelta,_config.com.timestampMaxDelta());
|
||||
Mutex::Lock _l(_memberships_l);
|
||||
Membership &m = _memberships[to->address()];
|
||||
const int64_t tout = std::min(m_config.credentialTimeMaxDelta, m_config.com.timestampMaxDelta());
|
||||
Mutex::Lock _l(m_memberships_l);
|
||||
Membership &m = m_memberships[to->address()];
|
||||
if (((now - m.lastPushedCredentials()) + 5000) >= tout) {
|
||||
m.pushCredentials(RR,tPtr,now,to,_config);
|
||||
m.pushCredentials(RR, tPtr, now, to, m_config);
|
||||
}
|
||||
}
|
||||
|
||||
void Network::destroy()
|
||||
{
|
||||
_memberships_l.lock();
|
||||
_config_l.lock();
|
||||
_destroyed = true;
|
||||
_config_l.unlock();
|
||||
_memberships_l.unlock();
|
||||
m_memberships_l.lock();
|
||||
m_config_l.lock();
|
||||
m_destroyed = true;
|
||||
m_config_l.unlock();
|
||||
m_memberships_l.unlock();
|
||||
}
|
||||
|
||||
void Network::externalConfig(ZT_VirtualNetworkConfig *ec) const
|
||||
{
|
||||
Mutex::Lock _l(_config_l);
|
||||
_externalConfig(ec);
|
||||
Mutex::Lock _l(m_config_l);
|
||||
m_externalConfig(ec);
|
||||
}
|
||||
|
||||
void Network::_requestConfiguration(void *tPtr)
|
||||
void Network::m_requestConfiguration(void *tPtr)
|
||||
{
|
||||
if (_destroyed)
|
||||
if (m_destroyed)
|
||||
return;
|
||||
|
||||
if ((_id >> 56U) == 0xff) {
|
||||
if ((_id & 0xffffffU) == 0) {
|
||||
const uint16_t startPortRange = (uint16_t)((_id >> 40U) & 0xffff);
|
||||
const uint16_t endPortRange = (uint16_t)((_id >> 24U) & 0xffff);
|
||||
if ((m_id >> 56U) == 0xff) {
|
||||
if ((m_id & 0xffffffU) == 0) {
|
||||
const uint16_t startPortRange = (uint16_t)((m_id >> 40U) & 0xffff);
|
||||
const uint16_t endPortRange = (uint16_t)((m_id >> 24U) & 0xffff);
|
||||
if (endPortRange >= startPortRange) {
|
||||
ScopedPtr<NetworkConfig> nconf(new NetworkConfig());
|
||||
|
||||
nconf->networkId = _id;
|
||||
nconf->networkId = m_id;
|
||||
nconf->timestamp = RR->node->now();
|
||||
nconf->credentialTimeMaxDelta = ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MAX_MAX_DELTA;
|
||||
nconf->revision = 1;
|
||||
|
@ -1263,7 +1263,7 @@ void Network::_requestConfiguration(void *tPtr)
|
|||
nconf->multicastLimit = 0;
|
||||
nconf->staticIpCount = 1;
|
||||
nconf->ruleCount = 14;
|
||||
nconf->staticIps[0] = InetAddress::makeIpv66plane(_id,RR->identity.address().toInt());
|
||||
nconf->staticIps[0] = InetAddress::makeIpv66plane(m_id, RR->identity.address().toInt());
|
||||
|
||||
// Drop everything but IPv6
|
||||
nconf->rules[0].t = (uint8_t)ZT_NETWORK_RULE_MATCH_ETHERTYPE | 0x80U; // NOT
|
||||
|
@ -1316,13 +1316,13 @@ void Network::_requestConfiguration(void *tPtr)
|
|||
} else {
|
||||
this->setNotFound();
|
||||
}
|
||||
} else if ((_id & 0xffU) == 0x01) {
|
||||
} else if ((m_id & 0xffU) == 0x01) {
|
||||
// ffAAaaaaaaaaaa01 -- where AA is the IPv4 /8 to use and aaaaaaaaaa is the anchor node for multicast gather and replication
|
||||
const uint64_t myAddress = RR->identity.address().toInt();
|
||||
const uint64_t networkHub = (_id >> 8U) & 0xffffffffffULL;
|
||||
const uint64_t networkHub = (m_id >> 8U) & 0xffffffffffULL;
|
||||
|
||||
uint8_t ipv4[4];
|
||||
ipv4[0] = (uint8_t)(_id >> 48U);
|
||||
ipv4[0] = (uint8_t)(m_id >> 48U);
|
||||
ipv4[1] = (uint8_t)(myAddress >> 16U);
|
||||
ipv4[2] = (uint8_t)(myAddress >> 8U);
|
||||
ipv4[3] = (uint8_t)myAddress;
|
||||
|
@ -1332,7 +1332,7 @@ void Network::_requestConfiguration(void *tPtr)
|
|||
|
||||
ScopedPtr<NetworkConfig> nconf(new NetworkConfig());
|
||||
|
||||
nconf->networkId = _id;
|
||||
nconf->networkId = m_id;
|
||||
nconf->timestamp = RR->node->now();
|
||||
nconf->credentialTimeMaxDelta = ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MAX_MAX_DELTA;
|
||||
nconf->revision = 1;
|
||||
|
@ -1347,7 +1347,7 @@ void Network::_requestConfiguration(void *tPtr)
|
|||
if (networkHub != 0)
|
||||
nconf->specialists[0] = networkHub;
|
||||
|
||||
nconf->staticIps[0] = InetAddress::makeIpv66plane(_id,myAddress);
|
||||
nconf->staticIps[0] = InetAddress::makeIpv66plane(m_id, myAddress);
|
||||
nconf->staticIps[1].set(ipv4,4,8);
|
||||
|
||||
nconf->rules[0].t = (uint8_t)ZT_NETWORK_RULE_ACTION_ACCEPT;
|
||||
|
@ -1390,11 +1390,11 @@ void Network::_requestConfiguration(void *tPtr)
|
|||
rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_FLAGS,(uint64_t)0);
|
||||
rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_RULES_ENGINE_REV,(uint64_t)ZT_RULES_ENGINE_REVISION);
|
||||
|
||||
RR->t->networkConfigRequestSent(tPtr,0x335bb1a2,_id);
|
||||
RR->t->networkConfigRequestSent(tPtr, 0x335bb1a2, m_id);
|
||||
|
||||
if (ctrl == RR->identity.address()) {
|
||||
if (RR->localNetworkController) {
|
||||
RR->localNetworkController->request(_id,InetAddress(),0xffffffffffffffffULL,RR->identity,rmd);
|
||||
RR->localNetworkController->request(m_id, InetAddress(), 0xffffffffffffffffULL, RR->identity, rmd);
|
||||
} else {
|
||||
this->setNotFound();
|
||||
}
|
||||
|
@ -1420,7 +1420,7 @@ void Network::_requestConfiguration(void *tPtr)
|
|||
*/
|
||||
}
|
||||
|
||||
ZT_VirtualNetworkStatus Network::_status() const
|
||||
ZT_VirtualNetworkStatus Network::m_status() const
|
||||
{
|
||||
switch(_netconfFailure) {
|
||||
case NETCONF_FAILURE_ACCESS_DENIED:
|
||||
|
@ -1428,36 +1428,36 @@ ZT_VirtualNetworkStatus Network::_status() const
|
|||
case NETCONF_FAILURE_NOT_FOUND:
|
||||
return ZT_NETWORK_STATUS_NOT_FOUND;
|
||||
case NETCONF_FAILURE_NONE:
|
||||
return ((_config) ? ZT_NETWORK_STATUS_OK : ZT_NETWORK_STATUS_REQUESTING_CONFIGURATION);
|
||||
return ((m_config) ? ZT_NETWORK_STATUS_OK : ZT_NETWORK_STATUS_REQUESTING_CONFIGURATION);
|
||||
default:
|
||||
return ZT_NETWORK_STATUS_REQUESTING_CONFIGURATION;
|
||||
}
|
||||
}
|
||||
|
||||
void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const
|
||||
void Network::m_externalConfig(ZT_VirtualNetworkConfig *ec) const
|
||||
{
|
||||
// assumes _config_l is locked
|
||||
ec->nwid = _id;
|
||||
ec->mac = _mac.toInt();
|
||||
if (_config)
|
||||
Utils::scopy(ec->name,sizeof(ec->name),_config.name);
|
||||
ec->nwid = m_id;
|
||||
ec->mac = m_mac.toInt();
|
||||
if (m_config)
|
||||
Utils::scopy(ec->name, sizeof(ec->name), m_config.name);
|
||||
else ec->name[0] = (char)0;
|
||||
ec->status = _status();
|
||||
ec->type = (_config) ? (_config.isPrivate() ? ZT_NETWORK_TYPE_PRIVATE : ZT_NETWORK_TYPE_PUBLIC) : ZT_NETWORK_TYPE_PRIVATE;
|
||||
ec->mtu = (_config) ? _config.mtu : ZT_DEFAULT_MTU;
|
||||
ec->status = m_status();
|
||||
ec->type = (m_config) ? (m_config.isPrivate() ? ZT_NETWORK_TYPE_PRIVATE : ZT_NETWORK_TYPE_PUBLIC) : ZT_NETWORK_TYPE_PRIVATE;
|
||||
ec->mtu = (m_config) ? m_config.mtu : ZT_DEFAULT_MTU;
|
||||
std::vector<Address> ab;
|
||||
for(unsigned int i=0;i<_config.specialistCount;++i) {
|
||||
if ((_config.specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0)
|
||||
ab.push_back(Address(_config.specialists[i]));
|
||||
for(unsigned int i=0;i < m_config.specialistCount;++i) {
|
||||
if ((m_config.specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0)
|
||||
ab.push_back(Address(m_config.specialists[i]));
|
||||
}
|
||||
ec->bridge = (std::find(ab.begin(),ab.end(),RR->identity.address()) != ab.end()) ? 1 : 0;
|
||||
ec->broadcastEnabled = (_config) ? (_config.enableBroadcast() ? 1 : 0) : 0;
|
||||
ec->netconfRevision = (_config) ? (unsigned long)_config.revision : 0;
|
||||
ec->broadcastEnabled = (m_config) ? (m_config.enableBroadcast() ? 1 : 0) : 0;
|
||||
ec->netconfRevision = (m_config) ? (unsigned long)m_config.revision : 0;
|
||||
|
||||
ec->assignedAddressCount = 0;
|
||||
for(unsigned int i=0;i<ZT_MAX_ZT_ASSIGNED_ADDRESSES;++i) {
|
||||
if (i < _config.staticIpCount) {
|
||||
Utils::copy<sizeof(struct sockaddr_storage)>(&(ec->assignedAddresses[i]),&(_config.staticIps[i]));
|
||||
if (i < m_config.staticIpCount) {
|
||||
Utils::copy<sizeof(struct sockaddr_storage)>(&(ec->assignedAddresses[i]),&(m_config.staticIps[i]));
|
||||
++ec->assignedAddressCount;
|
||||
} else {
|
||||
Utils::zero<sizeof(struct sockaddr_storage)>(&(ec->assignedAddresses[i]));
|
||||
|
@ -1466,8 +1466,8 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const
|
|||
|
||||
ec->routeCount = 0;
|
||||
for(unsigned int i=0;i<ZT_MAX_NETWORK_ROUTES;++i) {
|
||||
if (i < _config.routeCount) {
|
||||
Utils::copy<sizeof(ZT_VirtualNetworkRoute)>(&(ec->routes[i]),&(_config.routes[i]));
|
||||
if (i < m_config.routeCount) {
|
||||
Utils::copy<sizeof(ZT_VirtualNetworkRoute)>(&(ec->routes[i]),&(m_config.routes[i]));
|
||||
++ec->routeCount;
|
||||
} else {
|
||||
Utils::zero<sizeof(ZT_VirtualNetworkRoute)>(&(ec->routes[i]));
|
||||
|
@ -1475,11 +1475,11 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const
|
|||
}
|
||||
}
|
||||
|
||||
void Network::_announceMulticastGroups(void *tPtr,bool force)
|
||||
void Network::m_announceMulticastGroups(void *tPtr, bool force)
|
||||
{
|
||||
// Assumes _myMulticastGroups_l and _memberships_l are locked
|
||||
const std::vector<MulticastGroup> groups(_allMulticastGroups());
|
||||
_announceMulticastGroupsTo(tPtr,controller(),groups);
|
||||
const Vector<MulticastGroup> groups(m_allMulticastGroups());
|
||||
m_announceMulticastGroupsTo(tPtr, controller(), groups);
|
||||
|
||||
// TODO
|
||||
/*
|
||||
|
@ -1497,7 +1497,7 @@ void Network::_announceMulticastGroups(void *tPtr,bool force)
|
|||
|
||||
}
|
||||
|
||||
void Network::_announceMulticastGroupsTo(void *tPtr,const Address &peer,const std::vector<MulticastGroup> &allMulticastGroups)
|
||||
void Network::m_announceMulticastGroupsTo(void *tPtr, const Address &peer, const Vector<MulticastGroup> &allMulticastGroups)
|
||||
{
|
||||
#if 0
|
||||
// Assumes _myMulticastGroups_l and _memberships_l are locked
|
||||
|
@ -1523,15 +1523,15 @@ void Network::_announceMulticastGroupsTo(void *tPtr,const Address &peer,const st
|
|||
#endif
|
||||
}
|
||||
|
||||
std::vector<MulticastGroup> Network::_allMulticastGroups() const
|
||||
Vector<MulticastGroup> Network::m_allMulticastGroups() const
|
||||
{
|
||||
// Assumes _myMulticastGroups_l is locked
|
||||
std::vector<MulticastGroup> mgs;
|
||||
mgs.reserve(_myMulticastGroups.size() + _multicastGroupsBehindMe.size() + 1);
|
||||
mgs.insert(mgs.end(),_myMulticastGroups.begin(),_myMulticastGroups.end());
|
||||
for(Map< MulticastGroup,uint64_t >::const_iterator i(_multicastGroupsBehindMe.begin());i!=_multicastGroupsBehindMe.end();++i)
|
||||
Vector<MulticastGroup> mgs;
|
||||
mgs.reserve(m_myMulticastGroups.size() + m_multicastGroupsBehindMe.size() + 1);
|
||||
mgs.insert(mgs.end(), m_myMulticastGroups.begin(), m_myMulticastGroups.end());
|
||||
for(Map<MulticastGroup,uint64_t>::const_iterator i(m_multicastGroupsBehindMe.begin());i != m_multicastGroupsBehindMe.end();++i)
|
||||
mgs.push_back(i->first);
|
||||
if ((_config)&&(_config.enableBroadcast()))
|
||||
if ((m_config) && (m_config.enableBroadcast()))
|
||||
mgs.push_back(Network::BROADCAST);
|
||||
std::sort(mgs.begin(),mgs.end());
|
||||
mgs.erase(std::unique(mgs.begin(),mgs.end()),mgs.end());
|
||||
|
|
|
@ -75,14 +75,14 @@ public:
|
|||
|
||||
~Network();
|
||||
|
||||
ZT_INLINE uint64_t id() const noexcept { return _id; }
|
||||
ZT_INLINE Address controller() const noexcept { return Address(_id >> 24U); }
|
||||
ZT_INLINE bool multicastEnabled() const noexcept { return (_config.multicastLimit > 0); }
|
||||
ZT_INLINE bool hasConfig() const noexcept { return (_config); }
|
||||
ZT_INLINE uint64_t lastConfigUpdate() const noexcept { return _lastConfigUpdate; }
|
||||
ZT_INLINE ZT_VirtualNetworkStatus status() const noexcept { return _status(); }
|
||||
ZT_INLINE const NetworkConfig &config() const noexcept { return _config; }
|
||||
ZT_INLINE const MAC &mac() const noexcept { return _mac; }
|
||||
ZT_INLINE uint64_t id() const noexcept { return m_id; }
|
||||
ZT_INLINE Address controller() const noexcept { return Address(m_id >> 24U); }
|
||||
ZT_INLINE bool multicastEnabled() const noexcept { return (m_config.multicastLimit > 0); }
|
||||
ZT_INLINE bool hasConfig() const noexcept { return (m_config); }
|
||||
ZT_INLINE uint64_t lastConfigUpdate() const noexcept { return m_lastConfigUpdate; }
|
||||
ZT_INLINE ZT_VirtualNetworkStatus status() const noexcept { return m_status(); }
|
||||
ZT_INLINE const NetworkConfig &config() const noexcept { return m_config; }
|
||||
ZT_INLINE const MAC &mac() const noexcept { return m_mac; }
|
||||
|
||||
/**
|
||||
* Apply filters to an outgoing packet
|
||||
|
@ -156,11 +156,11 @@ public:
|
|||
*/
|
||||
ZT_INLINE bool subscribedToMulticastGroup(const MulticastGroup &mg,const bool includeBridgedGroups) const
|
||||
{
|
||||
Mutex::Lock l(_myMulticastGroups_l);
|
||||
if (std::binary_search(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg))
|
||||
Mutex::Lock l(m_myMulticastGroups_l);
|
||||
if (std::binary_search(m_myMulticastGroups.begin(), m_myMulticastGroups.end(), mg))
|
||||
return true;
|
||||
else if (includeBridgedGroups)
|
||||
return (_multicastGroupsBehindMe.find(mg) != _multicastGroupsBehindMe.end());
|
||||
return (m_multicastGroupsBehindMe.find(mg) != m_multicastGroupsBehindMe.end());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -242,8 +242,8 @@ public:
|
|||
*/
|
||||
ZT_INLINE Address findBridgeTo(const MAC &mac) const
|
||||
{
|
||||
Mutex::Lock _l(_remoteBridgeRoutes_l);
|
||||
const Address *const br = _remoteBridgeRoutes.get(mac);
|
||||
Mutex::Lock _l(m_remoteBridgeRoutes_l);
|
||||
const Address *const br = m_remoteBridgeRoutes.get(mac);
|
||||
return ((br) ? *br : Address());
|
||||
}
|
||||
|
||||
|
@ -264,8 +264,8 @@ public:
|
|||
*/
|
||||
ZT_INLINE void learnBridgedMulticastGroup(void *tPtr,const MulticastGroup &mg,int64_t now)
|
||||
{
|
||||
Mutex::Lock l(_myMulticastGroups_l);
|
||||
_multicastGroupsBehindMe.set(mg,now);
|
||||
Mutex::Lock l(m_myMulticastGroups_l);
|
||||
m_multicastGroupsBehindMe.set(mg, now);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -325,8 +325,8 @@ public:
|
|||
template<typename F>
|
||||
ZT_INLINE void eachMember(F f)
|
||||
{
|
||||
Mutex::Lock ml(_memberships_l);
|
||||
for(Map<Address,Membership>::iterator i(_memberships.begin());i!=_memberships.end();++i) { // NOLINT(modernize-loop-convert,hicpp-use-auto,modernize-use-auto)
|
||||
Mutex::Lock ml(m_memberships_l);
|
||||
for(Map<Address,Membership>::iterator i(m_memberships.begin());i != m_memberships.end();++i) { // NOLINT(modernize-loop-convert,hicpp-use-auto,modernize-use-auto)
|
||||
if (!f(i->first,i->second))
|
||||
break;
|
||||
}
|
||||
|
@ -335,40 +335,30 @@ public:
|
|||
/**
|
||||
* @return Externally usable pointer-to-pointer exported via the core API
|
||||
*/
|
||||
ZT_INLINE void **userPtr() noexcept { return &_uPtr; }
|
||||
ZT_INLINE void **userPtr() noexcept { return &m_uPtr; }
|
||||
|
||||
private:
|
||||
void _requestConfiguration(void *tPtr);
|
||||
ZT_VirtualNetworkStatus _status() const;
|
||||
void _externalConfig(ZT_VirtualNetworkConfig *ec) const; // assumes _lock is locked
|
||||
void _announceMulticastGroups(void *tPtr,bool force);
|
||||
void _announceMulticastGroupsTo(void *tPtr,const Address &peer,const std::vector<MulticastGroup> &allMulticastGroups);
|
||||
std::vector<MulticastGroup> _allMulticastGroups() const;
|
||||
void m_requestConfiguration(void *tPtr);
|
||||
ZT_VirtualNetworkStatus m_status() const;
|
||||
void m_externalConfig(ZT_VirtualNetworkConfig *ec) const; // assumes _lock is locked
|
||||
void m_announceMulticastGroups(void *tPtr, bool force);
|
||||
void m_announceMulticastGroupsTo(void *tPtr, const Address &peer, const Vector<MulticastGroup> &allMulticastGroups);
|
||||
Vector<MulticastGroup> m_allMulticastGroups() const;
|
||||
|
||||
const RuntimeEnvironment *const RR;
|
||||
void *_uPtr;
|
||||
const uint64_t _id;
|
||||
Fingerprint _controllerFingerprint;
|
||||
MAC _mac; // local MAC address
|
||||
bool _portInitialized;
|
||||
void *m_uPtr;
|
||||
const uint64_t m_id;
|
||||
Fingerprint m_controllerFingerprint;
|
||||
MAC m_mac; // local MAC address
|
||||
bool m_portInitialized;
|
||||
std::atomic<bool> m_destroyed;
|
||||
|
||||
std::vector< MulticastGroup > _myMulticastGroups; // multicast groups that we belong to (according to tap)
|
||||
Map< MulticastGroup,uint64_t > _multicastGroupsBehindMe; // multicast groups that seem to be behind us and when we last saw them (if we are a bridge)
|
||||
Map< MAC,Address > _remoteBridgeRoutes; // remote addresses where given MACs are reachable (for tracking devices behind remote bridges)
|
||||
Vector<MulticastGroup> m_myMulticastGroups; // multicast groups that we belong to (according to tap)
|
||||
Map<MulticastGroup,int64_t> m_multicastGroupsBehindMe; // multicast groups that seem to be behind us and when we last saw them (if we are a bridge)
|
||||
Map<MAC,Address> m_remoteBridgeRoutes; // remote addresses where given MACs are reachable (for tracking devices behind remote bridges)
|
||||
|
||||
NetworkConfig _config;
|
||||
std::atomic<int64_t> _lastConfigUpdate;
|
||||
|
||||
struct _IncomingConfigChunk
|
||||
{
|
||||
ZT_INLINE _IncomingConfigChunk() : touchCtr(0),updateId(0) {}
|
||||
uint64_t touchCtr;
|
||||
uint64_t updateId;
|
||||
std::map< int,std::vector<uint8_t> > chunks;
|
||||
};
|
||||
_IncomingConfigChunk _incomingConfigChunks[ZT_NETWORK_MAX_INCOMING_UPDATES];
|
||||
|
||||
volatile bool _destroyed;
|
||||
NetworkConfig m_config;
|
||||
std::atomic<int64_t> m_lastConfigUpdate;
|
||||
|
||||
volatile enum {
|
||||
NETCONF_FAILURE_NONE,
|
||||
|
@ -377,12 +367,12 @@ private:
|
|||
NETCONF_FAILURE_INIT_FAILED
|
||||
} _netconfFailure;
|
||||
|
||||
Map<Address,Membership> _memberships;
|
||||
Map<Address,Membership> m_memberships;
|
||||
|
||||
Mutex _myMulticastGroups_l;
|
||||
Mutex _remoteBridgeRoutes_l;
|
||||
Mutex _config_l;
|
||||
Mutex _memberships_l;
|
||||
Mutex m_myMulticastGroups_l;
|
||||
Mutex m_remoteBridgeRoutes_l;
|
||||
Mutex m_config_l;
|
||||
Mutex m_memberships_l;
|
||||
|
||||
std::atomic<int> __refCount;
|
||||
};
|
||||
|
|
|
@ -11,10 +11,6 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Node.hpp"
|
||||
|
@ -90,7 +86,7 @@ Node::Node(void *uPtr,void *tPtr,const struct ZT_Node_Callbacks *callbacks,int64
|
|||
{
|
||||
// Load this node's identity.
|
||||
uint64_t idtmp[2]; idtmp[0] = 0; idtmp[1] = 0;
|
||||
std::vector<uint8_t> data(stateObjectGet(tPtr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp));
|
||||
Vector<uint8_t> data(stateObjectGet(tPtr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp));
|
||||
bool haveIdentity = false;
|
||||
if (!data.empty()) {
|
||||
data.push_back(0); // zero-terminate string
|
||||
|
@ -528,12 +524,12 @@ void Node::setController(void *networkControllerInstance)
|
|||
|
||||
// Methods used only within the core ----------------------------------------------------------------------------------
|
||||
|
||||
std::vector<uint8_t> Node::stateObjectGet(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2])
|
||||
Vector<uint8_t> Node::stateObjectGet(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2])
|
||||
{
|
||||
std::vector<uint8_t> r;
|
||||
Vector<uint8_t> r;
|
||||
if (m_cb.stateGetFunction) {
|
||||
void *data = 0;
|
||||
void (*freeFunc)(void *) = 0;
|
||||
void *data = nullptr;
|
||||
void (*freeFunc)(void *) = nullptr;
|
||||
int l = m_cb.stateGetFunction(
|
||||
reinterpret_cast<ZT_Node *>(this),
|
||||
m_uPtr,
|
||||
|
|
|
@ -226,7 +226,7 @@ public:
|
|||
* @param id Object ID
|
||||
* @return Vector containing data or empty vector if not found or empty
|
||||
*/
|
||||
std::vector<uint8_t> stateObjectGet(void *tPtr,ZT_StateObjectType type,const uint64_t id[2]);
|
||||
Vector<uint8_t> stateObjectGet(void *tPtr,ZT_StateObjectType type,const uint64_t id[2]);
|
||||
|
||||
/**
|
||||
* Store a state object
|
||||
|
@ -299,18 +299,6 @@ public:
|
|||
*/
|
||||
ZT_INLINE bool natMustDie() const noexcept { return m_natMustDie; }
|
||||
|
||||
/**
|
||||
* Wake peer by calling its alarm() method at or after a given time.
|
||||
*
|
||||
* @param peer Identity fingerprint of peer to wake
|
||||
* @param triggerTime Time alarm should go off
|
||||
*/
|
||||
ZT_INLINE void setPeerAlarm(const Fingerprint &peer,const int64_t triggerTime)
|
||||
{
|
||||
Mutex::Lock l(_peerAlarms_l);
|
||||
_peerAlarms[peer] = triggerTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a local controller has authorized a member on a network
|
||||
*
|
||||
|
|
|
@ -194,4 +194,7 @@ typedef unsigned uint128_t __attribute__((mode(TI)));
|
|||
#endif
|
||||
#endif
|
||||
|
||||
// Macro to print very verbose tracing information to standard error.
|
||||
#define ZT_SPEW(f,...) fprintf(stderr,"%s(%d): " f ZT_EOL_S,__FILE__,__LINE__,__VA_ARGS__)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -20,13 +20,7 @@
|
|||
#include "Utils.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "Meter.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
#include "Containers.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -151,7 +145,7 @@ private:
|
|||
// These fields belong to Defragmenter but are kept in Path for performance
|
||||
// as it's much faster this way than having Defragmenter maintain another
|
||||
// mapping from paths to inbound message IDs.
|
||||
std::set<uint64_t> _inboundFragmentedMessages;
|
||||
Set<uint64_t> _inboundFragmentedMessages;
|
||||
Mutex _inboundFragmentedMessages_l;
|
||||
|
||||
std::atomic<int> __refCount;
|
||||
|
|
|
@ -86,6 +86,32 @@ public:
|
|||
return m_locator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this peer's probe token
|
||||
*
|
||||
* This doesn't update the mapping in Topology. The caller must do
|
||||
* this, which is the HELLO handler in VL1.
|
||||
*
|
||||
* @param t New probe token
|
||||
* @return Old probe token
|
||||
*/
|
||||
ZT_INLINE uint32_t setProbeToken(const uint32_t t) const noexcept
|
||||
{
|
||||
RWMutex::Lock l(m_lock);
|
||||
const uint32_t pt = m_probe;
|
||||
m_probe = t;
|
||||
return pt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return This peer's probe token or 0 if unknown
|
||||
*/
|
||||
ZT_INLINE uint32_t probeToken() const noexcept
|
||||
{
|
||||
RWMutex::RLock l(m_lock);
|
||||
return m_probe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log receipt of an authenticated packet
|
||||
*
|
||||
|
@ -415,7 +441,7 @@ private:
|
|||
List<p_TryQueueItem> m_tryQueue;
|
||||
List<p_TryQueueItem>::iterator m_tryQueuePtr; // loops over _tryQueue like a circular buffer
|
||||
|
||||
// 32-bit probe or 0 if unknown.
|
||||
// 32-bit probe token or 0 if unknown.
|
||||
uint32_t m_probe;
|
||||
|
||||
uint16_t m_vProto;
|
||||
|
|
114
node/PeerList.hpp
Normal file
114
node/PeerList.hpp
Normal file
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Copyright (c)2013-2020 ZeroTier, Inc.
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file in the project's root directory.
|
||||
*
|
||||
* Change Date: 2024-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
#ifndef ZT_PEERLIST_HPP
|
||||
#define ZT_PEERLIST_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Peer.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
* A list of peers
|
||||
*
|
||||
* This is a simple vector optimized for the case where there will almost always
|
||||
* be zero or one element. In that case it doesn't allocate. If there's more than
|
||||
* one element, it will grow to include all elements.
|
||||
*
|
||||
* It's used to return lookups in Topology where there will almost always be zero
|
||||
* or one peers returned but where there technically (but very rarely) can be more.
|
||||
*/
|
||||
class PeerList
|
||||
{
|
||||
public:
|
||||
ZT_INLINE PeerList() noexcept :
|
||||
m_onePeer(),
|
||||
m_peers(&m_onePeer),
|
||||
m_peerCount(0)
|
||||
{}
|
||||
|
||||
ZT_INLINE PeerList(const PeerList &pl)
|
||||
{
|
||||
const unsigned int pc = pl.m_peerCount;
|
||||
if (likely(pc <= 1)) {
|
||||
m_onePeer = pl.m_onePeer;
|
||||
m_peers = &m_onePeer;
|
||||
} else {
|
||||
m_peers = new SharedPtr<Peer>[pc];
|
||||
for (unsigned int i=0;i<pc;++i)
|
||||
m_peers[i] = pl.m_peers[i];
|
||||
}
|
||||
m_peerCount = pc;
|
||||
}
|
||||
|
||||
ZT_INLINE ~PeerList()
|
||||
{
|
||||
if (unlikely(m_peers != &m_onePeer))
|
||||
delete [] m_peers;
|
||||
}
|
||||
|
||||
ZT_INLINE PeerList &operator=(const PeerList &pl)
|
||||
{
|
||||
if (&pl != this) {
|
||||
if (unlikely(m_peers != &m_onePeer))
|
||||
delete [] m_peers;
|
||||
if (likely(pl.m_peerCount <= 1)) {
|
||||
m_onePeer = pl.m_onePeer;
|
||||
m_peers = &m_onePeer;
|
||||
} else {
|
||||
m_onePeer.zero();
|
||||
m_peers = new SharedPtr<Peer>[pl.m_peerCount];
|
||||
for (unsigned int i = 0;i < pl.m_peerCount;++i)
|
||||
m_peers[i] = pl.m_peers[i];
|
||||
}
|
||||
m_peerCount = pl.m_peerCount;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize the peer list to store a given number of members
|
||||
*
|
||||
* To populate the list, this must be called first followed by each member
|
||||
* being set with the [] operator. List content after this call is undefined
|
||||
* and may contain old data if the object is being re-used.
|
||||
*
|
||||
* @param s New size of list
|
||||
*/
|
||||
ZT_INLINE void resize(const unsigned int s)
|
||||
{
|
||||
if (unlikely(m_peers != &m_onePeer))
|
||||
delete [] m_peers;
|
||||
m_peerCount = s;
|
||||
if (likely(s <= 1)) {
|
||||
m_peers = &m_onePeer;
|
||||
} else {
|
||||
m_peers = new SharedPtr<Peer>[s];
|
||||
}
|
||||
}
|
||||
|
||||
ZT_INLINE SharedPtr<Peer> &operator[](const unsigned int i) noexcept { return m_peers[i]; }
|
||||
ZT_INLINE const SharedPtr<Peer> &operator[](const unsigned int i) const noexcept { return m_peers[i]; }
|
||||
ZT_INLINE unsigned int size() const noexcept { return m_peerCount; }
|
||||
|
||||
private:
|
||||
SharedPtr<Peer> m_onePeer;
|
||||
SharedPtr<Peer> *m_peers;
|
||||
unsigned int m_peerCount;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
|
@ -251,14 +251,16 @@
|
|||
#define ZT_PROTO_HELLO_NODE_META_INSTANCE_ID "i"
|
||||
#define ZT_PROTO_HELLO_NODE_META_LOCATOR "l"
|
||||
#define ZT_PROTO_HELLO_NODE_META_PROBE_TOKEN "p"
|
||||
#define ZT_PROTO_HELLO_NODE_META_NEIGHBORS "n"
|
||||
#define ZT_PROTO_HELLO_NODE_META_SOFTWARE_VENDOR "s"
|
||||
#define ZT_PROTO_HELLO_NODE_META_SOFTWARE_VERSION "v"
|
||||
#define ZT_PROTO_HELLO_NODE_META_PHYSICAL_DEST "d"
|
||||
#define ZT_PROTO_HELLO_NODE_META_COMPLIANCE "c"
|
||||
#define ZT_PROTO_HELOO_NODE_META_EPHEMERAL_C25519 "0"
|
||||
#define ZT_PROTO_HELOO_NODE_META_EPHEMERAL_P384 "1"
|
||||
#define ZT_PROTO_HELOO_NODE_META_EPHEMERAL_REMOTE "R"
|
||||
#define ZT_PROTO_HELLO_NODE_META_EPHEMERAL_C25519 "0"
|
||||
#define ZT_PROTO_HELLO_NODE_META_EPHEMERAL_P384 "1"
|
||||
#define ZT_PROTO_HELLO_NODE_META_EPHEMERAL_REMOTE "R"
|
||||
|
||||
static_assert(ZT_PROTO_MAX_PACKET_LENGTH < ZT_BUF_MEM_SIZE,"maximum packet length won't fit in Buf");
|
||||
static_assert(ZT_PROTO_PACKET_ENCRYPTED_SECTION_START == (ZT_PROTO_MIN_PACKET_LENGTH-1),"encrypted packet section must start right before protocol verb at one less than minimum packet size");
|
||||
|
||||
namespace ZeroTier {
|
||||
namespace Protocol {
|
||||
|
@ -356,7 +358,6 @@ enum Verb
|
|||
*
|
||||
* NAME - arbitrary short user-defined name for this node
|
||||
* CONTACT - arbitrary short contact information string for this node
|
||||
* NEIGHBORS - addresses of node(s) to whom we'll relay (mesh-like routing)
|
||||
* SOFTWARE_VENDOR - short name or description of vendor, such as a URL
|
||||
* SOFTWARE_VERSION - major, minor, revision, and build (packed 64-bit int)
|
||||
* PHYSICAL_DEST - serialized Endpoint to which this message was sent
|
||||
|
@ -425,21 +426,28 @@ enum Verb
|
|||
/**
|
||||
* Relay-mediated NAT traversal or firewall punching initiation:
|
||||
* <[1] flags (unused, currently 0)>
|
||||
* <[5] ZeroTier address of peer that might be found at this address>
|
||||
* <[5] ZeroTier address of other peer>
|
||||
* <[2] 16-bit number of endpoints where peer might be reached>
|
||||
* <[...] endpoints to attempt>
|
||||
*
|
||||
* Legacy packet format for pre-2.x peers:
|
||||
* <[1] flags (unused, currently 0)>
|
||||
* <[5] ZeroTier address of other peer>
|
||||
* <[2] 16-bit protocol address port>
|
||||
* <[1] protocol address length / type>
|
||||
* <[...] protocol address (network byte order)>
|
||||
*
|
||||
* This is sent by a third party node to inform a node of where another
|
||||
* may be located. These are currently only allowed from roots.
|
||||
* When a root or other peer is relaying messages, it can periodically send
|
||||
* RENDEZVOUS to assist peers in establishing direct communication.
|
||||
*
|
||||
* The protocol address format differs from the standard InetAddress
|
||||
* encoding for legacy reasons, but it's not hard to decode. The following
|
||||
* values are valid for the protocol address length (type) field:
|
||||
* Peers also directly exchange information via HELLO, so this serves as
|
||||
* a second way for peers to learn about their possible locations.
|
||||
*
|
||||
* 4 - IPv4 IP address
|
||||
* 16 - IPv6 IP address
|
||||
* 255 - Endpoint object, unmarshaled in place (port ignored)
|
||||
* It also serves another function: temporal coordination of NAT traversal
|
||||
* attempts. Some NATs traverse better if both sides first send "firewall
|
||||
* opener" packets and then send real packets and if this exchange is
|
||||
* coordinated in time so that the packets effectively pass each other in
|
||||
* flight.
|
||||
*
|
||||
* No OK or ERROR is generated.
|
||||
*/
|
||||
|
@ -627,46 +635,7 @@ enum Verb
|
|||
*/
|
||||
VERB_MULTICAST_GATHER = 0x0d,
|
||||
|
||||
/** *** DEPRECATED ***
|
||||
* Multicast frame:
|
||||
* <[8] 64-bit network ID>
|
||||
* <[1] flags>
|
||||
* [<[4] 32-bit implicit gather limit>]
|
||||
* [<[6] source MAC>]
|
||||
* <[6] destination MAC (multicast address)>
|
||||
* <[4] 32-bit multicast ADI (multicast address extension)>
|
||||
* <[2] 16-bit ethertype>
|
||||
* <[...] ethernet payload>
|
||||
*
|
||||
* Flags:
|
||||
* 0x01 - Network certificate of membership attached (DEPRECATED)
|
||||
* 0x02 - Implicit gather limit field is present
|
||||
* 0x04 - Source MAC is specified -- otherwise it's computed from sender
|
||||
* 0x08 - Please replicate (sent to multicast replicators)
|
||||
*
|
||||
* OK and ERROR responses are optional. OK may be generated if there are
|
||||
* implicit gather results or if the recipient wants to send its own
|
||||
* updated certificate of network membership to the sender. ERROR may be
|
||||
* generated if a certificate is needed or if multicasts to this group
|
||||
* are no longer wanted (multicast unsubscribe).
|
||||
*
|
||||
* OK response payload:
|
||||
* <[8] 64-bit network ID>
|
||||
* <[6] MAC address of multicast group>
|
||||
* <[4] 32-bit ADI for multicast group>
|
||||
* <[1] flags>
|
||||
* [<[...] network certificate of membership (DEPRECATED)>]
|
||||
* [<[...] implicit gather results if flag 0x01 is set>]
|
||||
*
|
||||
* OK flags (same bits as request flags):
|
||||
* 0x01 - OK includes certificate of network membership (DEPRECATED)
|
||||
* 0x02 - OK includes implicit gather results
|
||||
*
|
||||
* ERROR response payload:
|
||||
* <[8] 64-bit network ID>
|
||||
* <[6] multicast group MAC>
|
||||
* <[4] 32-bit multicast group ADI>
|
||||
*/
|
||||
// Deprecated multicast frame message type.
|
||||
VERB_MULTICAST_FRAME_deprecated = 0x0e,
|
||||
|
||||
/**
|
||||
|
@ -676,14 +645,19 @@ enum Verb
|
|||
*
|
||||
* Path record format:
|
||||
* <[1] 8-bit path flags>
|
||||
* <[2] length of extended path data or 0 for none>
|
||||
* <[...] extended path data>
|
||||
* <[1] address type>
|
||||
* <[1] address record length in bytes>
|
||||
* <[...] address>
|
||||
* <[2] length of endpoint record>
|
||||
* <[...] endpoint>
|
||||
*
|
||||
* The following fields are also included if the node is pre-2.x:
|
||||
* <[1] address type (LEGACY)>
|
||||
* <[1] address length in bytes (LEGACY)>
|
||||
* <[...] address (LEGACY)>
|
||||
*
|
||||
* Path flags:
|
||||
* 0x01 - BFG1024 symmetric NAT-t requested
|
||||
* Path record flags:
|
||||
* 0x01 - reserved (legacy)
|
||||
* 0x02 - reserved (legacy)
|
||||
* 0x04 - Symmetric NAT detected at sender side
|
||||
* 0x08 - Request aggressive symmetric NAT traversal
|
||||
*
|
||||
* OK and ERROR are not generated.
|
||||
*/
|
||||
|
@ -704,19 +678,6 @@ enum Verb
|
|||
*/
|
||||
VERB_USER_MESSAGE = 0x14,
|
||||
|
||||
/**
|
||||
* Encapsulate a ZeroTier packet for multicast distribution:
|
||||
* [... begin signed portion ...]
|
||||
* <[1] 8-bit flags>
|
||||
* <[5] 40-bit ZeroTier address of sender>
|
||||
* <[2] 16-bit length of inner payload>
|
||||
* <[1] inner payload verb>
|
||||
* <[...] inner payload data>
|
||||
* [... end signed portion ...]
|
||||
* <[2] 16-bit length of signature or 0 if un-signed>
|
||||
* [<[...] optional signature of multicast>]
|
||||
* <[...] address (min prefix) list>
|
||||
*/
|
||||
VERB_MULTICAST = 0x16,
|
||||
|
||||
/**
|
||||
|
@ -807,220 +768,6 @@ enum NetworkConfigFlag
|
|||
NETWORK_CONFIG_FLAG_FAST_PROPAGATE = 0x01
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* These are bit-packed structures for rapid parsing of packets or at least
|
||||
* the fixed size headers thereof. Not all packet types have these as some
|
||||
* are full of variable length fields are are more easily parsed through
|
||||
* incremental decoding.
|
||||
*
|
||||
* All fields larger than one byte are in big-endian byte order on the wire.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Normal packet header
|
||||
*
|
||||
* @tparam PT Packet payload type (default: uint8_t[])
|
||||
*/
|
||||
ZT_PACKED_STRUCT(struct Header
|
||||
{
|
||||
uint64_t packetId;
|
||||
uint8_t destination[5];
|
||||
uint8_t source[5];
|
||||
uint8_t flags;
|
||||
uint64_t mac;
|
||||
// --- begin encrypted envelope ---
|
||||
uint8_t verb;
|
||||
});
|
||||
|
||||
/**
|
||||
* Packet fragment header
|
||||
*/
|
||||
ZT_PACKED_STRUCT(struct FragmentHeader
|
||||
{
|
||||
uint64_t packetId;
|
||||
uint8_t destination[5];
|
||||
uint8_t fragmentIndicator; // always 0xff for fragments
|
||||
uint8_t counts; // total: most significant four bits, number: least significant four bits
|
||||
uint8_t hops; // top 5 bits unused and must be zero
|
||||
});
|
||||
|
||||
ZT_PACKED_STRUCT(struct HELLO
|
||||
{
|
||||
Header h;
|
||||
uint8_t versionProtocol;
|
||||
uint8_t versionMajor;
|
||||
uint8_t versionMinor;
|
||||
uint16_t versionRev;
|
||||
uint64_t timestamp;
|
||||
});
|
||||
|
||||
ZT_PACKED_STRUCT(struct RENDEZVOUS
|
||||
{
|
||||
Header h;
|
||||
uint8_t flags;
|
||||
uint8_t peerAddress[5];
|
||||
uint16_t port;
|
||||
uint8_t addressLength;
|
||||
});
|
||||
|
||||
ZT_PACKED_STRUCT(struct FRAME
|
||||
{
|
||||
Header h;
|
||||
uint64_t networkId;
|
||||
uint16_t etherType;
|
||||
});
|
||||
|
||||
ZT_PACKED_STRUCT(struct EXT_FRAME
|
||||
{
|
||||
Header h;
|
||||
uint64_t networkId;
|
||||
uint8_t flags;
|
||||
});
|
||||
|
||||
ZT_PACKED_STRUCT(struct PUSH_DIRECT_PATHS
|
||||
{
|
||||
Header h;
|
||||
uint16_t numPaths;
|
||||
});
|
||||
|
||||
ZT_PACKED_STRUCT(struct MULTICAST_LIKE
|
||||
{
|
||||
ZT_PACKED_STRUCT(struct Entry
|
||||
{
|
||||
uint64_t networkId;
|
||||
uint8_t mac[6];
|
||||
uint32_t adi;
|
||||
});
|
||||
|
||||
Header h;
|
||||
});
|
||||
|
||||
namespace OK {
|
||||
|
||||
/**
|
||||
* OK response header
|
||||
*
|
||||
* @tparam PT OK payload type (default: uint8_t[])
|
||||
*/
|
||||
ZT_PACKED_STRUCT(struct Header
|
||||
{
|
||||
Protocol::Header h;
|
||||
uint8_t inReVerb;
|
||||
uint64_t inRePacketId;
|
||||
});
|
||||
|
||||
ZT_PACKED_STRUCT(struct WHOIS
|
||||
{
|
||||
OK::Header h;
|
||||
});
|
||||
|
||||
ZT_PACKED_STRUCT(struct ECHO
|
||||
{
|
||||
OK::Header h;
|
||||
});
|
||||
|
||||
ZT_PACKED_STRUCT(struct HELLO
|
||||
{
|
||||
OK::Header h;
|
||||
uint64_t timestampEcho;
|
||||
uint8_t versionProtocol;
|
||||
uint8_t versionMajor;
|
||||
uint8_t versionMinor;
|
||||
uint16_t versionRev;
|
||||
});
|
||||
|
||||
ZT_PACKED_STRUCT(struct EXT_FRAME
|
||||
{
|
||||
OK::Header h;
|
||||
uint64_t networkId;
|
||||
uint8_t flags;
|
||||
uint8_t destMac[6];
|
||||
uint8_t sourceMac[6];
|
||||
uint16_t etherType;
|
||||
});
|
||||
|
||||
ZT_PACKED_STRUCT(struct NETWORK_CONFIG
|
||||
{
|
||||
OK::Header h;
|
||||
uint64_t networkId;
|
||||
uint64_t configUpdateId;
|
||||
});
|
||||
|
||||
} // namespace OK
|
||||
|
||||
namespace ERROR {
|
||||
|
||||
/**
|
||||
* Error header
|
||||
*
|
||||
* The error header comes after the packet header but before type-specific payloads.
|
||||
*
|
||||
* @tparam PT Error payload type (default: uint8_t[])
|
||||
*/
|
||||
ZT_PACKED_STRUCT(struct Header
|
||||
{
|
||||
Protocol::Header h;
|
||||
int8_t inReVerb;
|
||||
uint64_t inRePacketId;
|
||||
uint8_t error;
|
||||
});
|
||||
|
||||
ZT_PACKED_STRUCT(struct NEED_MEMBERSHIP_CERTIFICATE
|
||||
{
|
||||
ERROR::Header h;
|
||||
uint64_t networkId;
|
||||
});
|
||||
|
||||
ZT_PACKED_STRUCT(struct UNSUPPORTED_OPERATION__NETWORK_CONFIG_REQUEST
|
||||
{
|
||||
ERROR::Header h;
|
||||
uint64_t networkId;
|
||||
});
|
||||
|
||||
} // namespace ERROR
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static_assert(sizeof(Protocol::Header) == ZT_PROTO_MIN_PACKET_LENGTH,"Protocol::Header struct packing error");
|
||||
static_assert(sizeof(Protocol::FragmentHeader) == ZT_PROTO_MIN_FRAGMENT_LENGTH,"Protocol::FragmentHeader struct packing error");
|
||||
static_assert(ZT_PROTO_MAX_PACKET_LENGTH < ZT_BUF_MEM_SIZE,"maximum packet length won't fit in Buf");
|
||||
static_assert(ZT_PROTO_PACKET_ENCRYPTED_SECTION_START == (ZT_PROTO_MIN_PACKET_LENGTH-1),"encrypted packet section must start right before protocol verb at one less than minimum packet size");
|
||||
|
||||
/**
|
||||
* Convenience function to pull packet ID from a raw buffer
|
||||
*
|
||||
* @param pkt Packet to read first 8 bytes from
|
||||
* @param packetSize Packet's actual size in bytes
|
||||
* @return Packet ID or 0 if packet size is less than 8
|
||||
*/
|
||||
static ZT_INLINE uint64_t packetId(const Buf &pkt,const unsigned int packetSize) noexcept { return (packetSize >= 8) ? Utils::loadBigEndian<uint64_t>(pkt.unsafeData) : 0ULL; }
|
||||
|
||||
/**
|
||||
* @param Packet to extract hops from
|
||||
* @param packetSize Packet's actual size in bytes
|
||||
* @return 3-bit hops field embedded in packet flags field
|
||||
*/
|
||||
static ZT_INLINE uint8_t packetHops(const Buf &pkt,const unsigned int packetSize) noexcept { return (packetSize >= ZT_PROTO_PACKET_FLAGS_INDEX) ? (pkt.unsafeData[ZT_PROTO_PACKET_FLAGS_INDEX] & ZT_PROTO_FLAG_FIELD_HOPS_MASK) : 0; }
|
||||
|
||||
/**
|
||||
* @param Packet to extract cipher ID from
|
||||
* @param packetSize Packet's actual size in bytes
|
||||
* @return 3-bit cipher field embedded in packet flags field
|
||||
*/
|
||||
static ZT_INLINE uint8_t packetCipher(const Buf &pkt,const unsigned int packetSize) noexcept { return (packetSize >= ZT_PROTO_PACKET_FLAGS_INDEX) ? ((pkt.unsafeData[ZT_PROTO_PACKET_FLAGS_INDEX] >> 3U) & 0x07U) : 0; }
|
||||
|
||||
/**
|
||||
* @return 3-bit hops field embedded in packet flags field
|
||||
*/
|
||||
static ZT_INLINE uint8_t packetHops(const Header &ph) noexcept { return (ph.flags & 0x07U); }
|
||||
|
||||
/**
|
||||
* @return 3-bit cipher field embedded in packet flags field
|
||||
*/
|
||||
static ZT_INLINE uint8_t packetCipher(const Header &ph) noexcept { return ((ph.flags >> 3U) & 0x07U); }
|
||||
|
||||
/**
|
||||
* Deterministically mangle a 256-bit crypto key based on packet characteristics
|
||||
*
|
||||
|
|
|
@ -55,7 +55,7 @@ public:
|
|||
secretIdentityStr[0] = (char)0;
|
||||
}
|
||||
|
||||
ZT_INLINE ~RuntimeEnvironment()
|
||||
ZT_INLINE ~RuntimeEnvironment() noexcept
|
||||
{
|
||||
Utils::burn(secretIdentityStr,sizeof(secretIdentityStr));
|
||||
}
|
||||
|
|
|
@ -17,8 +17,7 @@
|
|||
#include "Topology.hpp"
|
||||
#include "Peer.hpp"
|
||||
#include "Trace.hpp"
|
||||
|
||||
#include <set>
|
||||
#include "Containers.hpp"
|
||||
|
||||
// Entry timeout -- make it fairly long since this is just to prevent stale buildup
|
||||
#define ZT_SELFAWARENESS_ENTRY_TIMEOUT 300000
|
||||
|
@ -67,7 +66,7 @@ void SelfAwareness::iam(void *tPtr,const Identity &reporter,const int64_t receiv
|
|||
// Erase all entries in this scope that were not reported from this remote address to prevent 'thrashing'
|
||||
// due to multiple reports of endpoint change.
|
||||
// Don't use 'entry' after this since hash table gets modified.
|
||||
for(Map<p_PhySurfaceKey,p_PhySurfaceEntry>::iterator i(m_phy.begin());i != m_phy.end();) { // NOLINT(modernize-loop-convert,modernize-use-auto,hicpp-use-auto)
|
||||
for(Map<p_PhySurfaceKey,p_PhySurfaceEntry>::iterator i(m_phy.begin());i != m_phy.end();) {
|
||||
if ((i->first.scope == scope)&&(i->first.reporterPhysicalAddress != reporterPhysicalAddress))
|
||||
m_phy.erase(i++);
|
||||
else ++i;
|
||||
|
@ -89,27 +88,29 @@ void SelfAwareness::iam(void *tPtr,const Identity &reporter,const int64_t receiv
|
|||
void SelfAwareness::clean(int64_t now)
|
||||
{
|
||||
Mutex::Lock l(m_phy_l);
|
||||
for(Map<p_PhySurfaceKey,p_PhySurfaceEntry>::iterator i(m_phy.begin());i != m_phy.end();) { // NOLINT(modernize-loop-convert,modernize-use-auto,hicpp-use-auto)
|
||||
for(Map<p_PhySurfaceKey,p_PhySurfaceEntry>::iterator i(m_phy.begin());i != m_phy.end();) {
|
||||
if ((now - i->second.ts) >= ZT_SELFAWARENESS_ENTRY_TIMEOUT)
|
||||
m_phy.erase(i++);
|
||||
else ++i;
|
||||
}
|
||||
}
|
||||
|
||||
SelfAwareness::ExternalAddressList SelfAwareness::externalAddresses(const int64_t now) const
|
||||
MultiMap<unsigned int,InetAddress> SelfAwareness::externalAddresses(const int64_t now) const
|
||||
{
|
||||
SelfAwareness::ExternalAddressList r;
|
||||
Map<InetAddress,unsigned long> counts;
|
||||
MultiMap<unsigned int,InetAddress> r;
|
||||
|
||||
// Count endpoints reporting each IP/port combo
|
||||
Map<InetAddress,unsigned long> counts;
|
||||
{
|
||||
Mutex::Lock l(m_phy_l);
|
||||
for(Map<p_PhySurfaceKey,p_PhySurfaceEntry>::const_iterator i(m_phy.begin());i != m_phy.end();++i) { // NOLINT(modernize-loop-convert,modernize-use-auto,hicpp-use-auto)
|
||||
for(Map<p_PhySurfaceKey,p_PhySurfaceEntry>::const_iterator i(m_phy.begin());i != m_phy.end();++i) {
|
||||
if ((now - i->second.ts) < ZT_SELFAWARENESS_ENTRY_TIMEOUT)
|
||||
++counts[i->second.mySurface];
|
||||
}
|
||||
}
|
||||
|
||||
for(Map<InetAddress,unsigned long>::iterator i(counts.begin());i!=counts.end();++i) // NOLINT(modernize-loop-convert,modernize-use-auto,hicpp-use-auto)
|
||||
// Invert to create a map from count to address
|
||||
for(Map<InetAddress,unsigned long>::iterator i(counts.begin());i!=counts.end();++i)
|
||||
r.insert(std::pair<unsigned long,InetAddress>(i->second,i->first));
|
||||
|
||||
return r;
|
||||
|
|
|
@ -33,8 +33,6 @@ class RuntimeEnvironment;
|
|||
class SelfAwareness
|
||||
{
|
||||
public:
|
||||
typedef std::multimap< unsigned long,InetAddress,std::less<unsigned long>,Utils::Mallocator< std::pair<const unsigned long,InetAddress> > > ExternalAddressList;
|
||||
|
||||
explicit SelfAwareness(const RuntimeEnvironment *renv);
|
||||
|
||||
/**
|
||||
|
@ -62,7 +60,7 @@ public:
|
|||
* @param now Current time
|
||||
* @return Map of count to IP/port representing how many endpoints reported each address
|
||||
*/
|
||||
ExternalAddressList externalAddresses(int64_t now) const;
|
||||
MultiMap<unsigned int,InetAddress> externalAddresses(int64_t now) const;
|
||||
|
||||
private:
|
||||
struct p_PhySurfaceKey
|
||||
|
|
|
@ -127,7 +127,31 @@ public:
|
|||
if (m_ptr) {
|
||||
if (--m_ptr->__refCount <= 0)
|
||||
delete m_ptr;
|
||||
m_ptr = (T *)0;
|
||||
m_ptr = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set pointer to NULL and delete object if reference count is only 1
|
||||
*
|
||||
* This can be called periodically to implement something like a weak
|
||||
* reference as it exists in other more managed languages like Java,
|
||||
* but with the caveat that it only works if there is only one remaining
|
||||
* SharedPtr to be treated as weak.
|
||||
*
|
||||
* @return True if object was in fact deleted or was already zero/NULL
|
||||
*/
|
||||
ZT_INLINE bool weakGC()
|
||||
{
|
||||
if (m_ptr) {
|
||||
if (m_ptr->__refCount.compare_exchange_strong(1,0)) {
|
||||
delete m_ptr;
|
||||
m_ptr = nullptr;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,31 +15,12 @@
|
|||
|
||||
namespace ZeroTier {
|
||||
|
||||
const uint64_t Topology::s_pathHashSalt = Utils::getSecureRandomU64();
|
||||
|
||||
// Sorts roots so as to put the lowest latency alive root first.
|
||||
struct _RootSortComparisonOperator
|
||||
{
|
||||
ZT_INLINE _RootSortComparisonOperator(const int64_t now) : _now(now) {}
|
||||
ZT_INLINE bool operator()(const SharedPtr<Peer> &a,const SharedPtr<Peer> &b)
|
||||
{
|
||||
const int64_t now = _now;
|
||||
if (a->active(now)) {
|
||||
if (b->active(now))
|
||||
return (a->latency() < b->latency());
|
||||
return true;
|
||||
}
|
||||
return a->lastReceive() < b->lastReceive();
|
||||
}
|
||||
const int64_t _now;
|
||||
};
|
||||
|
||||
Topology::Topology(const RuntimeEnvironment *renv,void *tPtr) :
|
||||
RR(renv),
|
||||
m_numConfiguredPhysicalPaths(0)
|
||||
{
|
||||
uint64_t idtmp[2]; idtmp[0] = 0; idtmp[1] = 0;
|
||||
std::vector<uint8_t> data(RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_ROOTS,idtmp));
|
||||
Vector<uint8_t> data(RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_ROOTS,idtmp));
|
||||
if (!data.empty()) {
|
||||
uint8_t *dptr = data.data();
|
||||
int drem = (int)data.size();
|
||||
|
@ -50,57 +31,66 @@ Topology::Topology(const RuntimeEnvironment *renv,void *tPtr) :
|
|||
m_roots.insert(id);
|
||||
dptr += l;
|
||||
drem -= l;
|
||||
ZT_SPEW("recalled root %s",id.address().toString().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(std::set<Identity>::const_iterator r(m_roots.begin());r != m_roots.end();++r) {
|
||||
for(Set<Identity>::const_iterator r(m_roots.begin());r != m_roots.end();++r) {
|
||||
SharedPtr<Peer> p;
|
||||
m_loadCached(tPtr, r->address(), p);
|
||||
m_loadCached(tPtr,r->address(),p);
|
||||
if ((!p)||(p->identity() != *r)) {
|
||||
p.set(new Peer(RR));
|
||||
p->init(*r);
|
||||
}
|
||||
m_rootPeers.push_back(p);
|
||||
m_peers[p->address()] = p;
|
||||
m_peersByIncomingProbe[p->incomingProbe()] = p;
|
||||
m_peersByIdentityHash[p->identity().fingerprint()] = p;
|
||||
}
|
||||
}
|
||||
|
||||
Topology::~Topology()
|
||||
{
|
||||
}
|
||||
|
||||
SharedPtr<Peer> Topology::add(void *tPtr,const SharedPtr<Peer> &peer)
|
||||
{
|
||||
RWMutex::Lock _l(m_peers_l);
|
||||
|
||||
SharedPtr<Peer> &hp = m_peers[peer->address()];
|
||||
if (hp)
|
||||
return hp;
|
||||
|
||||
m_loadCached(tPtr, peer->address(), hp);
|
||||
if (hp) {
|
||||
m_peersByIncomingProbe[peer->incomingProbe()] = hp;
|
||||
m_peersByIdentityHash[peer->identity().fingerprint()] = hp;
|
||||
m_loadCached(tPtr,peer->address(),hp);
|
||||
if (hp)
|
||||
return hp;
|
||||
}
|
||||
|
||||
hp = peer;
|
||||
m_peersByIncomingProbe[peer->incomingProbe()] = peer;
|
||||
m_peersByIdentityHash[peer->identity().fingerprint()] = peer;
|
||||
|
||||
return peer;
|
||||
}
|
||||
|
||||
void Topology::getAllPeers(std::vector< SharedPtr<Peer> > &allPeers) const
|
||||
PeerList Topology::peersByProbeToken(const uint32_t probeToken) const
|
||||
{
|
||||
RWMutex::RLock l(m_peers_l);
|
||||
allPeers.clear();
|
||||
allPeers.reserve(m_peers.size());
|
||||
for(Map< Address,SharedPtr<Peer> >::const_iterator i(m_peers.begin());i != m_peers.end();++i)
|
||||
allPeers.push_back(i->second);
|
||||
Mutex::Lock l(m_peersByProbeToken_l);
|
||||
std::pair< MultiMap< uint32_t,SharedPtr<Peer> >::const_iterator,MultiMap< uint32_t,SharedPtr<Peer> >::const_iterator > r(m_peersByProbeToken.equal_range(probeToken));
|
||||
PeerList pl;
|
||||
if (r.first == r.second)
|
||||
return pl;
|
||||
const unsigned int cnt = (unsigned int)std::distance(r.first,r.second);
|
||||
pl.resize(cnt);
|
||||
MultiMap< uint32_t,SharedPtr<Peer> >::const_iterator pi(r.first);
|
||||
for(unsigned int i=0;i<cnt;++i) {
|
||||
pl[i] = pi->second;
|
||||
++pi;
|
||||
}
|
||||
return pl;
|
||||
}
|
||||
|
||||
void Topology::updateProbeToken(const SharedPtr<Peer> &peer,const uint32_t oldToken,const uint32_t newToken)
|
||||
{
|
||||
Mutex::Lock l(m_peersByProbeToken_l);
|
||||
if (oldToken != 0) {
|
||||
std::pair< MultiMap< uint32_t,SharedPtr<Peer> >::iterator,MultiMap< uint32_t,SharedPtr<Peer> >::iterator > r(m_peersByProbeToken.equal_range(oldToken));
|
||||
for(MultiMap< uint32_t,SharedPtr<Peer> >::iterator i(r.first);i!=r.second;) {
|
||||
if (i->second == peer)
|
||||
m_peersByProbeToken.erase(i++);
|
||||
else ++i;
|
||||
}
|
||||
}
|
||||
if (newToken != 0)
|
||||
m_peersByProbeToken.insert(std::pair< uint32_t,SharedPtr<Peer> >(newToken,peer));
|
||||
}
|
||||
|
||||
void Topology::setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig)
|
||||
|
@ -137,11 +127,25 @@ void Topology::setPhysicalPathConfiguration(const struct sockaddr_storage *pathN
|
|||
}
|
||||
}
|
||||
|
||||
void Topology::addRoot(void *tPtr,const Identity &id,const InetAddress &bootstrap)
|
||||
struct p_RootSortComparisonOperator
|
||||
{
|
||||
if (id == RR->identity) return; // sanity check
|
||||
ZT_INLINE bool operator()(const SharedPtr<Peer> &a,const SharedPtr<Peer> &b) const noexcept
|
||||
{
|
||||
// Sort in inverse order of latency with lowest latency first (and -1 last).
|
||||
const int bb = b->latency();
|
||||
if (bb < 0)
|
||||
return true;
|
||||
return bb < a->latency();
|
||||
}
|
||||
};
|
||||
|
||||
void Topology::addRoot(void *const tPtr,const Identity &id,const InetAddress &bootstrap)
|
||||
{
|
||||
if (id == RR->identity)
|
||||
return;
|
||||
|
||||
RWMutex::Lock l1(m_peers_l);
|
||||
std::pair< std::set<Identity>::iterator,bool > ir(m_roots.insert(id));
|
||||
std::pair< Set<Identity>::iterator,bool > ir(m_roots.insert(id));
|
||||
if (ir.second) {
|
||||
SharedPtr<Peer> &p = m_peers[id.address()];
|
||||
if (!p) {
|
||||
|
@ -149,68 +153,56 @@ void Topology::addRoot(void *tPtr,const Identity &id,const InetAddress &bootstra
|
|||
p->init(id);
|
||||
if (bootstrap)
|
||||
p->setBootstrap(Endpoint(bootstrap));
|
||||
m_peersByIncomingProbe[p->incomingProbe()] = p;
|
||||
m_peersByIdentityHash[p->identity().fingerprint()] = p;
|
||||
}
|
||||
m_rootPeers.push_back(p);
|
||||
|
||||
uint8_t *const roots = (uint8_t *)malloc(ZT_IDENTITY_MARSHAL_SIZE_MAX * m_roots.size());
|
||||
if (roots) {
|
||||
int p = 0;
|
||||
for(std::set<Identity>::const_iterator i(m_roots.begin());i != m_roots.end();++i) {
|
||||
int pp = i->marshal(roots + p,false);
|
||||
if (pp > 0)
|
||||
p += pp;
|
||||
}
|
||||
uint64_t id[2];
|
||||
id[0] = 0;
|
||||
id[1] = 0;
|
||||
RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_ROOTS,id,roots,(unsigned int)p);
|
||||
free(roots);
|
||||
}
|
||||
std::sort(m_rootPeers.begin(),m_rootPeers.end(),p_RootSortComparisonOperator());
|
||||
m_writeRootList(tPtr);
|
||||
}
|
||||
}
|
||||
|
||||
bool Topology::removeRoot(const Identity &id)
|
||||
bool Topology::removeRoot(void *const tPtr,const Identity &id)
|
||||
{
|
||||
RWMutex::Lock l1(m_peers_l);
|
||||
std::set<Identity>::iterator r(m_roots.find(id));
|
||||
Set<Identity>::iterator r(m_roots.find(id));
|
||||
if (r != m_roots.end()) {
|
||||
for(std::vector< SharedPtr<Peer> >::iterator p(m_rootPeers.begin());p != m_rootPeers.end();++p) {
|
||||
for(Vector< SharedPtr<Peer> >::iterator p(m_rootPeers.begin());p != m_rootPeers.end();++p) {
|
||||
if ((*p)->identity() == id) {
|
||||
m_rootPeers.erase(p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_roots.erase(r);
|
||||
m_writeRootList(tPtr);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Topology::rankRoots(const int64_t now)
|
||||
void Topology::rankRoots()
|
||||
{
|
||||
RWMutex::Lock l1(m_peers_l);
|
||||
std::sort(m_rootPeers.begin(), m_rootPeers.end(), _RootSortComparisonOperator(now));
|
||||
std::sort(m_rootPeers.begin(),m_rootPeers.end(),p_RootSortComparisonOperator());
|
||||
}
|
||||
|
||||
void Topology::doPeriodicTasks(void *tPtr,const int64_t now)
|
||||
{
|
||||
// Delete peers that haven't said anything in ZT_PEER_ALIVE_TIMEOUT.
|
||||
{
|
||||
RWMutex::Lock l1(m_peers_l);
|
||||
for(Map< Address,SharedPtr<Peer> >::iterator i(m_peers.begin());i != m_peers.end();) {
|
||||
if ( (!i->second->alive(now)) && (m_roots.count(i->second->identity()) == 0) ) {
|
||||
if ( ((now - i->second->lastReceive()) > ZT_PEER_ALIVE_TIMEOUT) && (m_roots.count(i->second->identity()) == 0) ) {
|
||||
updateProbeToken(i->second,i->second->probeToken(),0);
|
||||
i->second->save(tPtr);
|
||||
m_peersByIncomingProbe.erase(i->second->incomingProbe());
|
||||
m_peersByIdentityHash.erase(i->second->identity().fingerprint());
|
||||
m_peers.erase(i++);
|
||||
} else ++i;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete paths that are no longer held by anyone else ("weak reference" type behavior).
|
||||
{
|
||||
RWMutex::Lock l1(m_paths_l);
|
||||
for(Map< uint64_t,SharedPtr<Path> >::iterator i(m_paths.begin());i != m_paths.end();) {
|
||||
if ((i->second.references() <= 1)&&(!i->second->alive(now)))
|
||||
if (i->second.weakGC())
|
||||
m_paths.erase(i++);
|
||||
else ++i;
|
||||
}
|
||||
|
@ -220,7 +212,7 @@ void Topology::doPeriodicTasks(void *tPtr,const int64_t now)
|
|||
void Topology::saveAll(void *tPtr)
|
||||
{
|
||||
RWMutex::RLock l(m_peers_l);
|
||||
for(Map< Address,SharedPtr<Peer> >::iterator i(m_peers.begin());i != m_peers.end();++i)
|
||||
for(Map< Address,SharedPtr<Peer> >::iterator i(m_peers.begin());i!=m_peers.end();++i)
|
||||
i->second->save(tPtr);
|
||||
}
|
||||
|
||||
|
@ -230,7 +222,7 @@ void Topology::m_loadCached(void *tPtr, const Address &zta, SharedPtr<Peer> &pee
|
|||
uint64_t id[2];
|
||||
id[0] = zta.toInt();
|
||||
id[1] = 0;
|
||||
std::vector<uint8_t> data(RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_PEER,id));
|
||||
Vector<uint8_t> data(RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_PEER,id));
|
||||
if (data.size() > 8) {
|
||||
const uint8_t *d = data.data();
|
||||
int dl = (int)data.size();
|
||||
|
@ -253,4 +245,23 @@ void Topology::m_loadCached(void *tPtr, const Address &zta, SharedPtr<Peer> &pee
|
|||
}
|
||||
}
|
||||
|
||||
void Topology::m_writeRootList(void *tPtr)
|
||||
{
|
||||
// assumes m_peers_l is locked
|
||||
uint8_t *const roots = (uint8_t *)malloc(ZT_IDENTITY_MARSHAL_SIZE_MAX * m_roots.size());
|
||||
if (roots) { // sanity check
|
||||
int p = 0;
|
||||
for(Set<Identity>::const_iterator i(m_roots.begin());i != m_roots.end();++i) {
|
||||
const int pp = i->marshal(roots + p,false);
|
||||
if (pp > 0)
|
||||
p += pp;
|
||||
}
|
||||
uint64_t id[2];
|
||||
id[0] = 0;
|
||||
id[1] = 0;
|
||||
RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_ROOTS,id,roots,(unsigned int)p);
|
||||
free(roots);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -14,12 +14,6 @@
|
|||
#ifndef ZT_TOPOLOGY_HPP
|
||||
#define ZT_TOPOLOGY_HPP
|
||||
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <set>
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Identity.hpp"
|
||||
|
@ -31,6 +25,7 @@
|
|||
#include "ScopedPtr.hpp"
|
||||
#include "Fingerprint.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "PeerList.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -43,7 +38,6 @@ class Topology
|
|||
{
|
||||
public:
|
||||
Topology(const RuntimeEnvironment *renv,void *tPtr);
|
||||
~Topology();
|
||||
|
||||
/**
|
||||
* Add peer to database
|
||||
|
@ -89,34 +83,21 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* Get a peer by its 384-bit identity public key hash
|
||||
* Get peer(s) by 32-bit probe token
|
||||
*
|
||||
* @param hash Identity hash
|
||||
* @return Peer or NULL if no peer is currently in memory for this hash (cache is not checked in this case)
|
||||
* @param probeToken Probe token
|
||||
* @return List of peers
|
||||
*/
|
||||
ZT_INLINE SharedPtr<Peer> peerByHash(const Fingerprint &hash)
|
||||
{
|
||||
RWMutex::RLock _l(m_peers_l);
|
||||
const SharedPtr<Peer> *const ap = m_peersByIdentityHash.get(hash);
|
||||
if (ap)
|
||||
return *ap;
|
||||
return SharedPtr<Peer>();
|
||||
}
|
||||
PeerList peersByProbeToken(uint32_t probeToken) const;
|
||||
|
||||
/**
|
||||
* Get a peer by its incoming short probe packet payload
|
||||
* Set or update the probe token associated with a peer
|
||||
*
|
||||
* @param probe Short probe payload (in big-endian byte order)
|
||||
* @return Peer or NULL if no peer is currently in memory matching this probe (cache is not checked in this case)
|
||||
* @param peer Peer to update
|
||||
* @param oldToken Old probe token or 0 if none
|
||||
* @param newToken New probe token or 0 to erase old mapping but not set a new token
|
||||
*/
|
||||
ZT_INLINE SharedPtr<Peer> peerByProbe(const uint64_t probe)
|
||||
{
|
||||
RWMutex::RLock _l(m_peers_l);
|
||||
const SharedPtr<Peer> *const ap = m_peersByIncomingProbe.get(probe);
|
||||
if (ap)
|
||||
return *ap;
|
||||
return SharedPtr<Peer>();
|
||||
}
|
||||
void updateProbeToken(const SharedPtr<Peer> &peer,uint32_t oldToken,uint32_t newToken);
|
||||
|
||||
/**
|
||||
* Get a Path object for a given local and remote physical address, creating if needed
|
||||
|
@ -163,7 +144,7 @@ public:
|
|||
ZT_INLINE bool isRoot(const Identity &id) const
|
||||
{
|
||||
RWMutex::RLock l(m_peers_l);
|
||||
return (m_roots.count(id) > 0);
|
||||
return (m_roots.find(id) != m_roots.end());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -209,24 +190,17 @@ public:
|
|||
} catch ( ... ) {} // should not throw
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate through all paths in the system
|
||||
*
|
||||
* @tparam F Function to call for each path
|
||||
* @param f
|
||||
*/
|
||||
template<typename F>
|
||||
ZT_INLINE void eachPath(F f) const
|
||||
{
|
||||
RWMutex::RLock l(m_paths_l);
|
||||
for(Map< uint64_t,SharedPtr<Path> >::const_iterator i(m_paths.begin());i != m_paths.end();++i) // NOLINT(modernize-loop-convert,hicpp-use-auto,modernize-use-auto)
|
||||
f(i->second);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param allPeers vector to fill with all current peers
|
||||
*/
|
||||
void getAllPeers(std::vector< SharedPtr<Peer> > &allPeers) const;
|
||||
ZT_INLINE void getAllPeers(Vector< SharedPtr<Peer> > &allPeers) const
|
||||
{
|
||||
RWMutex::RLock l(m_peers_l);
|
||||
allPeers.clear();
|
||||
allPeers.reserve(m_peers.size());
|
||||
for(Map< Address,SharedPtr<Peer> >::const_iterator i(m_peers.begin());i != m_peers.end();++i)
|
||||
allPeers.push_back(i->second);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get info about a path
|
||||
|
@ -295,17 +269,18 @@ public:
|
|||
/**
|
||||
* Remove a root server's identity from the root server set
|
||||
*
|
||||
* @param tPtr Thread pointer
|
||||
* @param id Root server identity
|
||||
* @return True if root found and removed, false if not found
|
||||
*/
|
||||
bool removeRoot(const Identity &id);
|
||||
bool removeRoot(void *tPtr,const Identity &id);
|
||||
|
||||
/**
|
||||
* Sort roots in asecnding order of apparent latency
|
||||
*
|
||||
* @param now Current time
|
||||
*/
|
||||
void rankRoots(int64_t now);
|
||||
void rankRoots();
|
||||
|
||||
/**
|
||||
* Do periodic tasks such as database cleanup
|
||||
|
@ -318,47 +293,45 @@ public:
|
|||
void saveAll(void *tPtr);
|
||||
|
||||
private:
|
||||
// Load cached peer and set 'peer' to it, if one is found.
|
||||
void m_loadCached(void *tPtr, const Address &zta, SharedPtr<Peer> &peer);
|
||||
|
||||
// This is a secure random integer created at startup to salt the calculation of path hash map keys
|
||||
static const uint64_t s_pathHashSalt;
|
||||
void m_writeRootList(void *tPtr);
|
||||
|
||||
// This gets an integer key from an InetAddress for looking up paths.
|
||||
static ZT_INLINE uint64_t s_getPathKey(int64_t l, const InetAddress &r)
|
||||
static ZT_INLINE uint64_t s_getPathKey(const int64_t l,const InetAddress &r)
|
||||
{
|
||||
if (r.family() == AF_INET) {
|
||||
return s_pathHashSalt + (uint64_t)(reinterpret_cast<const struct sockaddr_in *>(&r)->sin_addr.s_addr) + (uint64_t)Utils::ntoh(reinterpret_cast<const struct sockaddr_in *>(&r)->sin_port) + (uint64_t)l;
|
||||
return ((uint64_t)(reinterpret_cast<const sockaddr_in *>(&r)->sin_addr.s_addr) << 24U) +
|
||||
((uint64_t)reinterpret_cast<const sockaddr_in *>(&r)->sin_port << 8U) +
|
||||
(uint64_t)l;
|
||||
} else if (r.family() == AF_INET6) {
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
uint64_t h = s_pathHashSalt;
|
||||
for(int i=0;i<16;++i) {
|
||||
h += (uint64_t)((reinterpret_cast<const struct sockaddr_in6 *>(&r)->sin6_addr.s6_addr)[i]);
|
||||
h += (h << 10U);
|
||||
h ^= (h >> 6U);
|
||||
}
|
||||
uint64_t htmp[2];
|
||||
Utils::copy<16>(htmp,reinterpret_cast<const sockaddr_in6 *>(&r)->sin6_addr.s6_addr);
|
||||
const uint64_t h = htmp[0] ^ htmp[1];
|
||||
#else
|
||||
uint64_t h = s_pathHashSalt + (reinterpret_cast<const uint64_t *>(reinterpret_cast<const struct sockaddr_in6 *>(&r)->sin6_addr.s6_addr)[0] + reinterpret_cast<const uint64_t *>(reinterpret_cast<const struct sockaddr_in6 *>(&r)->sin6_addr.s6_addr)[1]);
|
||||
const uint64_t h = reinterpret_cast<const uint64_t *>(reinterpret_cast<const sockaddr_in6 *>(&r)->sin6_addr.s6_addr)[0] ^
|
||||
reinterpret_cast<const uint64_t *>(reinterpret_cast<const sockaddr_in6 *>(&r)->sin6_addr.s6_addr)[1];
|
||||
#endif
|
||||
return h + (uint64_t)Utils::ntoh(reinterpret_cast<const struct sockaddr_in6 *>(&r)->sin6_port) + (uint64_t)l;
|
||||
return h + (uint64_t)Utils::ntoh(reinterpret_cast<const struct sockaddr_in6 *>(&r)->sin6_port) ^ (uint64_t)l;
|
||||
} else {
|
||||
return Utils::fnv1a32(reinterpret_cast<const void *>(&r),sizeof(InetAddress)) + (uint64_t)l;
|
||||
return (uint64_t)Utils::fnv1a32(reinterpret_cast<const void *>(&r),sizeof(InetAddress)) + (uint64_t)l;
|
||||
}
|
||||
}
|
||||
|
||||
const RuntimeEnvironment *const RR;
|
||||
|
||||
RWMutex m_peers_l;
|
||||
RWMutex m_paths_l;
|
||||
Mutex m_peersByProbeToken_l;
|
||||
RWMutex m_peers_l;
|
||||
|
||||
std::pair< InetAddress,ZT_PhysicalPathConfiguration > m_physicalPathConfig[ZT_MAX_CONFIGURABLE_PATHS];
|
||||
unsigned int m_numConfiguredPhysicalPaths;
|
||||
|
||||
Map< uint64_t,SharedPtr<Path> > m_paths;
|
||||
|
||||
MultiMap< uint32_t,SharedPtr<Peer> > m_peersByProbeToken;
|
||||
|
||||
Map< Address,SharedPtr<Peer> > m_peers;
|
||||
Map< uint64_t,SharedPtr<Peer> > m_peersByIncomingProbe;
|
||||
Map< Fingerprint,SharedPtr<Peer> > m_peersByIdentityHash;
|
||||
Set< Identity > m_roots;
|
||||
Vector< SharedPtr<Peer> > m_rootPeers;
|
||||
};
|
||||
|
|
|
@ -18,10 +18,6 @@
|
|||
#include "Path.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstdarg>
|
||||
|
||||
// NOTE: packet IDs are always handled in network byte order, so no need to convert them.
|
||||
|
||||
namespace ZeroTier {
|
||||
|
|
|
@ -20,11 +20,7 @@
|
|||
#include "InetAddress.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "MAC.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
#include "Containers.hpp"
|
||||
|
||||
#define ZT_TRACE_F_VL1 0x01U
|
||||
#define ZT_TRACE_F_VL2 0x02U
|
||||
|
|
|
@ -17,9 +17,6 @@
|
|||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
#include "FCV.hpp"
|
||||
#include "Containers.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
class RuntimeEnvironment;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "Protocol.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "Containers.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue