diff --git a/CMakeLists.txt b/CMakeLists.txt index 18f8b1bf3..8d93b2ac8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/include/ZeroTierCore.h b/include/ZeroTierCore.h index be765db92..eea4d233b 100644 --- a/include/ZeroTierCore.h +++ b/include/ZeroTierCore.h @@ -29,25 +29,6 @@ #include #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 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 + /****************************************************************************/ /** diff --git a/node/AES.hpp b/node/AES.hpp index 2c1f02d15..1f3cc556f 100644 --- a/node/AES.hpp +++ b/node/AES.hpp @@ -23,10 +23,9 @@ #ifndef ZT_AES_NO_ACCEL #ifdef ZT_ARCH_X64 +#include #include -#include #include -#include #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) {} diff --git a/node/Address.hpp b/node/Address.hpp index 0524f4303..1f1698b33 100644 --- a/node/Address.hpp +++ b/node/Address.hpp @@ -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; } diff --git a/node/CMakeLists.txt b/node/CMakeLists.txt index fe4409028..24479dc58 100644 --- a/node/CMakeLists.txt +++ b/node/CMakeLists.txt @@ -32,6 +32,7 @@ set(core_headers OS.hpp Path.hpp Peer.hpp + PeerList.hpp Poly1305.hpp Protocol.hpp RuntimeEnvironment.hpp diff --git a/node/Capability.hpp b/node/Capability.hpp index 0b75a4e51..bf2501b9a 100644 --- a/node/Capability.hpp +++ b/node/Capability.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 diff --git a/node/Constants.hpp b/node/Constants.hpp index a01139a2e..25f8fcadb 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -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 * diff --git a/node/Containers.hpp b/node/Containers.hpp index c01c1f913..f74ce9922 100644 --- a/node/Containers.hpp +++ b/node/Containers.hpp @@ -31,18 +31,19 @@ namespace ZeroTier { #ifdef __CPP11__ -struct _MapHasher + +struct intl_MapHasher { template 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 -class Map : public std::unordered_map< K,V,_MapHasher,std::equal_to,Utils::Mallocator< std::pair > > +class Map : public std::unordered_map< K,V,intl_MapHasher,std::equal_to,Utils::Mallocator< std::pair > > { public: ZT_INLINE V *get(const K &key) noexcept @@ -66,7 +67,14 @@ public: this->emplace(key,value); } }; + +template +class MultiMap : public std::unordered_multimap< K,V,intl_MapHasher,std::equal_to,Utils::Mallocator< std::pair > > +{ +}; + #else + template class Map : public std::map< K,V,std::less,Utils::Mallocator< std::pair > > { @@ -92,6 +100,12 @@ public: (*this)[key] = value; } }; + +template +class MultiMap : public std::multimap< K,V,std::less,Utils::Mallocator< std::pair > > +{ +}; + #endif template diff --git a/node/Defragmenter.hpp b/node/Defragmenter.hpp index 0840a6105..fdd24e93a 100644 --- a/node/Defragmenter.hpp +++ b/node/Defragmenter.hpp @@ -22,10 +22,6 @@ #include "FCV.hpp" #include "Containers.hpp" -#include -#include -#include - namespace ZeroTier { /** diff --git a/node/Dictionary.cpp b/node/Dictionary.cpp index 1f87e731b..24fbbe431 100644 --- a/node/Dictionary.cpp +++ b/node/Dictionary.cpp @@ -19,10 +19,6 @@ Dictionary::Dictionary() { } -Dictionary::~Dictionary() -{ -} - std::vector &Dictionary::operator[](const char *k) { return m_entries[s_toKey(k)]; diff --git a/node/Dictionary.hpp b/node/Dictionary.hpp index 12715d3a1..7b83cf19c 100644 --- a/node/Dictionary.hpp +++ b/node/Dictionary.hpp @@ -20,8 +20,6 @@ #include "Buf.hpp" #include "Containers.hpp" -#include - namespace ZeroTier { /** @@ -42,7 +40,6 @@ class Dictionary { public: Dictionary(); - ~Dictionary(); /** * Get a reference to a value diff --git a/node/Expect.hpp b/node/Expect.hpp index 6a8d00403..390a97cd0 100644 --- a/node/Expect.hpp +++ b/node/Expect.hpp @@ -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 _packetIdSent[ZT_EXPECT_BUCKETS]; + std::atomic m_packetIdSent[ZT_EXPECT_BUCKETS]; }; } // namespace ZeroTier diff --git a/node/FCV.hpp b/node/FCV.hpp index a5c135640..5c87a28c3 100644 --- a/node/FCV.hpp +++ b/node/FCV.hpp @@ -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(0)); } + static constexpr bool isTriviallyCopyable() noexcept { return ZeroTier::isTriviallyCopyable(reinterpret_cast(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) diff --git a/node/Fingerprint.hpp b/node/Fingerprint.hpp index 1f8a16cb5..f87734ee3 100644 --- a/node/Fingerprint.hpp +++ b/node/Fingerprint.hpp @@ -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"); diff --git a/node/Identity.cpp b/node/Identity.cpp index fb8173c79..6b800e295 100644 --- a/node/Identity.cpp +++ b/node/Identity.cpp @@ -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(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(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(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(data + ZT_ADDRESS_LENGTH + 1,_pub.c25519); - if ((includePrivate)&&(_hasPrivate)) { + Utils::copy(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(data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1,_priv.c25519); + Utils::copy(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(data + ZT_ADDRESS_LENGTH + 1,&_pub); - if ((includePrivate)&&(_hasPrivate)) { + Utils::copy(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(data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1,&_priv); + Utils::copy(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(_pub.c25519,data + ZT_ADDRESS_LENGTH + 1); + Utils::copy(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(_priv.c25519,data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1); + m_hasPrivate = true; + Utils::copy(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(&_pub,data + ZT_ADDRESS_LENGTH + 1); + Utils::copy(&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(&_priv,data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1); + m_hasPrivate = true; + Utils::copy(&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; } } diff --git a/node/Identity.hpp b/node/Identity.hpp index eeffb6075..6db0e640a 100644 --- a/node/Identity.hpp +++ b/node/Identity.hpp @@ -22,6 +22,7 @@ #include "ECC384.hpp" #include "TriviallyCopyable.hpp" #include "Fingerprint.hpp" +#include "Containers.hpp" #include #include @@ -86,7 +87,7 @@ public: ZT_INLINE ~Identity() { Utils::memoryUnlock(this,sizeof(Identity)); - Utils::burn(reinterpret_cast(&this->_priv),sizeof(this->_priv)); + Utils::burn(reinterpret_cast(&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 diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp index 80cc7a6f9..6cb55ec40 100644 --- a/node/InetAddress.cpp +++ b/node/InetAddress.cpp @@ -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(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(this)->sin_addr.s_addr = ipb[0]; reinterpret_cast(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(this)->sin6_addr.s6_addr,ipBytes); reinterpret_cast(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(this)->sin_addr.s_addr == 0) && (reinterpret_cast(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(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(&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(&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(&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(&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(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(this)->sin_port == reinterpret_cast(&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(this)->sin_port < reinterpret_cast(&a)->sin_port) return true; diff --git a/node/InetAddress.hpp b/node/InetAddress.hpp index 0ae821029..a530105fd 100644 --- a/node/InetAddress.hpp +++ b/node/InetAddress.hpp @@ -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(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(this)->sin_port)); case AF_INET6: return Utils::ntoh((uint16_t)(reinterpret_cast(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(this)->sin_addr.s_addr); case AF_INET6: return (const void *)(reinterpret_cast(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(&r)->sin_family = AF_INET; reinterpret_cast(&r)->sin_addr.s_addr = reinterpret_cast(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(this)->sin_addr.s_addr == reinterpret_cast(&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(this)->sin_addr.s_addr == reinterpret_cast(&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(&_data)->sin_addr.s_addr + (uint32_t)reinterpret_cast(&_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(&m_sockaddr)->sin_addr.s_addr + (uint32_t)reinterpret_cast(&m_sockaddr)->sin_port) ^ (uint32_t)Utils::s_mapNonce); + } else if (m_sockaddr.ss_family == AF_INET6) { return (unsigned long)Utils::hash64( - (Utils::loadAsIsEndian(reinterpret_cast(&_data)->sin6_addr.s6_addr) + - Utils::loadAsIsEndian(reinterpret_cast(&_data)->sin6_addr.s6_addr + 8) + - (uint64_t)reinterpret_cast(&_data)->sin6_port) ^ Utils::s_mapNonce + (Utils::loadAsIsEndian(reinterpret_cast(&m_sockaddr)->sin6_addr.s6_addr) + + Utils::loadAsIsEndian(reinterpret_cast(&m_sockaddr)->sin6_addr.s6_addr + 8) + + (uint64_t)reinterpret_cast(&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"); diff --git a/node/Locator.cpp b/node/Locator.cpp index 329592eec..2a0b8ff55 100644 --- a/node/Locator.cpp +++ b/node/Locator.cpp @@ -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(data + 1,_ts); + Utils::storeBigEndian(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(data + 1); + m_ts = Utils::loadBigEndian(data + 1); int p = 9; - if (_ts > 0) { + if (m_ts > 0) { const unsigned int ec = Utils::loadBigEndian(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(data + p); + m_flags = Utils::loadBigEndian(data + p); p += 2; } else { - _ts = 0; + m_ts = 0; } return p; diff --git a/node/Locator.hpp b/node/Locator.hpp index ce561aaf1..0d03eae7b 100644 --- a/node/Locator.hpp +++ b/node/Locator.hpp @@ -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 diff --git a/node/MAC.hpp b/node/MAC.hpp index 0536ec352..0651461f9 100644 --- a/node/MAC.hpp +++ b/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 diff --git a/node/Membership.cpp b/node/Membership.cpp index faf7407a3..edb374267 100644 --- a/node/Membership.cpp +++ b/node/Membership.cpp @@ -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(nconf,_remoteTags); - _cleanCredImpl(nconf,_remoteCaps); - _cleanCredImpl(nconf,_remoteCoos); + m_cleanCredImpl(nconf, m_remoteTags); + m_cleanCredImpl(nconf, m_remoteCaps); + m_cleanCredImpl(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(_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(_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(_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(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(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(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())); diff --git a/node/Membership.hpp b/node/Membership.hpp index 50f888111..9ce017ff2 100644 --- a/node/Membership.hpp +++ b/node/Membership.hpp @@ -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 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 - 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 - ZT_INLINE void _cleanCredImpl(const NetworkConfig &nconf,Map &remoteCreds) + ZT_INLINE void m_cleanCredImpl(const NetworkConfig &nconf, Map &remoteCreds) { for(typename Map::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 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 m_remoteTags; + Map m_remoteCaps; + Map 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; }; }; diff --git a/node/Meter.hpp b/node/Meter.hpp index ccef127d3..666525e10 100644 --- a/node/Meter.hpp +++ b/node/Meter.hpp @@ -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 _counts[LSIZE]; - std::atomic _totalExclCounts; - std::atomic _bucket; + std::atomic m_counts[LSIZE]; + std::atomic m_totalExclCounts; + std::atomic m_bucket; }; } // namespace ZeroTier diff --git a/node/MulticastGroup.hpp b/node/MulticastGroup.hpp index 61e5c482a..d27ca2d13 100644 --- a/node/MulticastGroup.hpp +++ b/node/MulticastGroup.hpp @@ -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 diff --git a/node/Network.cpp b/node/Network.cpp index ac19822ac..052379ea7 100644 --- a/node/Network.cpp +++ b/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 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::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::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 &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 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) 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) 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::iterator i(_memberships.begin());i!=_memberships.end();++i) - i->second.clean(now,_config); + for(Map::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::iterator i(_remoteBridgeRoutes.begin());i!=_remoteBridgeRoutes.end();++i) { + for(Map::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::iterator i(_remoteBridgeRoutes.begin());i!=_remoteBridgeRoutes.end();) { + for(Map::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 &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 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 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
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(&(ec->assignedAddresses[i]),&(_config.staticIps[i])); + if (i < m_config.staticIpCount) { + Utils::copy(&(ec->assignedAddresses[i]),&(m_config.staticIps[i])); ++ec->assignedAddressCount; } else { Utils::zero(&(ec->assignedAddresses[i])); @@ -1466,8 +1466,8 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const ec->routeCount = 0; for(unsigned int i=0;i(&(ec->routes[i]),&(_config.routes[i])); + if (i < m_config.routeCount) { + Utils::copy(&(ec->routes[i]),&(m_config.routes[i])); ++ec->routeCount; } else { Utils::zero(&(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 groups(_allMulticastGroups()); - _announceMulticastGroupsTo(tPtr,controller(),groups); + const Vector 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 &allMulticastGroups) +void Network::m_announceMulticastGroupsTo(void *tPtr, const Address &peer, const Vector &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 Network::_allMulticastGroups() const +Vector Network::m_allMulticastGroups() const { // Assumes _myMulticastGroups_l is locked - std::vector 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 mgs; + mgs.reserve(m_myMulticastGroups.size() + m_multicastGroupsBehindMe.size() + 1); + mgs.insert(mgs.end(), m_myMulticastGroups.begin(), m_myMulticastGroups.end()); + for(Map::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()); diff --git a/node/Network.hpp b/node/Network.hpp index e2427df96..6c1a015ef 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -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 ZT_INLINE void eachMember(F f) { - Mutex::Lock ml(_memberships_l); - for(Map::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::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 &allMulticastGroups); - std::vector _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 &allMulticastGroups); + Vector 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 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 m_myMulticastGroups; // multicast groups that we belong to (according to tap) + Map m_multicastGroupsBehindMe; // multicast groups that seem to be behind us and when we last saw them (if we are a bridge) + Map m_remoteBridgeRoutes; // remote addresses where given MACs are reachable (for tracking devices behind remote bridges) - NetworkConfig _config; - std::atomic _lastConfigUpdate; - - struct _IncomingConfigChunk - { - ZT_INLINE _IncomingConfigChunk() : touchCtr(0),updateId(0) {} - uint64_t touchCtr; - uint64_t updateId; - std::map< int,std::vector > chunks; - }; - _IncomingConfigChunk _incomingConfigChunks[ZT_NETWORK_MAX_INCOMING_UPDATES]; - - volatile bool _destroyed; + NetworkConfig m_config; + std::atomic m_lastConfigUpdate; volatile enum { NETCONF_FAILURE_NONE, @@ -377,12 +367,12 @@ private: NETCONF_FAILURE_INIT_FAILED } _netconfFailure; - Map _memberships; + Map 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 __refCount; }; diff --git a/node/Node.cpp b/node/Node.cpp index 8da94f3ce..aa3ef0ac6 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -11,10 +11,6 @@ */ /****/ -#include -#include -#include - #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 data(stateObjectGet(tPtr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp)); + Vector 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 Node::stateObjectGet(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2]) +Vector Node::stateObjectGet(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2]) { - std::vector r; + Vector 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(this), m_uPtr, diff --git a/node/Node.hpp b/node/Node.hpp index cb3ef087b..19886890a 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -226,7 +226,7 @@ public: * @param id Object ID * @return Vector containing data or empty vector if not found or empty */ - std::vector stateObjectGet(void *tPtr,ZT_StateObjectType type,const uint64_t id[2]); + Vector 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 * diff --git a/node/OS.hpp b/node/OS.hpp index 63a12f068..42adc1286 100644 --- a/node/OS.hpp +++ b/node/OS.hpp @@ -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 diff --git a/node/Path.hpp b/node/Path.hpp index 74e0b96a7..5380b3cb6 100644 --- a/node/Path.hpp +++ b/node/Path.hpp @@ -20,13 +20,7 @@ #include "Utils.hpp" #include "Mutex.hpp" #include "Meter.hpp" - -#include -#include -#include -#include -#include -#include +#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 _inboundFragmentedMessages; + Set _inboundFragmentedMessages; Mutex _inboundFragmentedMessages_l; std::atomic __refCount; diff --git a/node/Peer.hpp b/node/Peer.hpp index 0c306e887..4881b9e6f 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -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 m_tryQueue; List::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; diff --git a/node/PeerList.hpp b/node/PeerList.hpp new file mode 100644 index 000000000..ed60eb9ba --- /dev/null +++ b/node/PeerList.hpp @@ -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[pc]; + for (unsigned int i=0;i[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[s]; + } + } + + ZT_INLINE SharedPtr &operator[](const unsigned int i) noexcept { return m_peers[i]; } + ZT_INLINE const SharedPtr &operator[](const unsigned int i) const noexcept { return m_peers[i]; } + ZT_INLINE unsigned int size() const noexcept { return m_peerCount; } + +private: + SharedPtr m_onePeer; + SharedPtr *m_peers; + unsigned int m_peerCount; +}; + +} // namespace ZeroTier + +#endif diff --git a/node/Protocol.hpp b/node/Protocol.hpp index 2ff4cdc21..b38879124 100644 --- a/node/Protocol.hpp +++ b/node/Protocol.hpp @@ -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(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 * diff --git a/node/RuntimeEnvironment.hpp b/node/RuntimeEnvironment.hpp index bd72280b3..1a361aadd 100644 --- a/node/RuntimeEnvironment.hpp +++ b/node/RuntimeEnvironment.hpp @@ -55,7 +55,7 @@ public: secretIdentityStr[0] = (char)0; } - ZT_INLINE ~RuntimeEnvironment() + ZT_INLINE ~RuntimeEnvironment() noexcept { Utils::burn(secretIdentityStr,sizeof(secretIdentityStr)); } diff --git a/node/SelfAwareness.cpp b/node/SelfAwareness.cpp index 8f70d1113..5f18e8fe4 100644 --- a/node/SelfAwareness.cpp +++ b/node/SelfAwareness.cpp @@ -17,8 +17,7 @@ #include "Topology.hpp" #include "Peer.hpp" #include "Trace.hpp" - -#include +#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::iterator i(m_phy.begin());i != m_phy.end();) { // NOLINT(modernize-loop-convert,modernize-use-auto,hicpp-use-auto) + for(Map::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::iterator i(m_phy.begin());i != m_phy.end();) { // NOLINT(modernize-loop-convert,modernize-use-auto,hicpp-use-auto) + for(Map::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 SelfAwareness::externalAddresses(const int64_t now) const { - SelfAwareness::ExternalAddressList r; - Map counts; + MultiMap r; + // Count endpoints reporting each IP/port combo + Map counts; { Mutex::Lock l(m_phy_l); - for(Map::const_iterator i(m_phy.begin());i != m_phy.end();++i) { // NOLINT(modernize-loop-convert,modernize-use-auto,hicpp-use-auto) + for(Map::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::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::iterator i(counts.begin());i!=counts.end();++i) r.insert(std::pair(i->second,i->first)); return r; diff --git a/node/SelfAwareness.hpp b/node/SelfAwareness.hpp index 11625ff4f..774034edb 100644 --- a/node/SelfAwareness.hpp +++ b/node/SelfAwareness.hpp @@ -33,8 +33,6 @@ class RuntimeEnvironment; class SelfAwareness { public: - typedef std::multimap< unsigned long,InetAddress,std::less,Utils::Mallocator< std::pair > > 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 externalAddresses(int64_t now) const; private: struct p_PhySurfaceKey diff --git a/node/SharedPtr.hpp b/node/SharedPtr.hpp index c2ef5678f..ebf6ad86c 100644 --- a/node/SharedPtr.hpp +++ b/node/SharedPtr.hpp @@ -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; } } diff --git a/node/Topology.cpp b/node/Topology.cpp index 9b898c954..7e1c582e6 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -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 &a,const SharedPtr &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 data(RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_ROOTS,idtmp)); + Vector 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::const_iterator r(m_roots.begin());r != m_roots.end();++r) { + for(Set::const_iterator r(m_roots.begin());r != m_roots.end();++r) { SharedPtr 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 Topology::add(void *tPtr,const SharedPtr &peer) { RWMutex::Lock _l(m_peers_l); - SharedPtr &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 > &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 >::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 >::const_iterator,MultiMap< uint32_t,SharedPtr >::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 >::const_iterator pi(r.first); + for(unsigned int i=0;isecond; + ++pi; + } + return pl; +} + +void Topology::updateProbeToken(const SharedPtr &peer,const uint32_t oldToken,const uint32_t newToken) +{ + Mutex::Lock l(m_peersByProbeToken_l); + if (oldToken != 0) { + std::pair< MultiMap< uint32_t,SharedPtr >::iterator,MultiMap< uint32_t,SharedPtr >::iterator > r(m_peersByProbeToken.equal_range(oldToken)); + for(MultiMap< uint32_t,SharedPtr >::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 >(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 &a,const SharedPtr &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::iterator,bool > ir(m_roots.insert(id)); + std::pair< Set::iterator,bool > ir(m_roots.insert(id)); if (ir.second) { SharedPtr &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::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::iterator r(m_roots.find(id)); + Set::iterator r(m_roots.find(id)); if (r != m_roots.end()) { - for(std::vector< SharedPtr >::iterator p(m_rootPeers.begin());p != m_rootPeers.end();++p) { + for(Vector< SharedPtr >::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 >::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 >::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 >::iterator i(m_peers.begin());i != m_peers.end();++i) + for(Map< Address,SharedPtr >::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 &pee uint64_t id[2]; id[0] = zta.toInt(); id[1] = 0; - std::vector data(RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_PEER,id)); + Vector 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 &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::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 diff --git a/node/Topology.hpp b/node/Topology.hpp index e904c979a..5df07304d 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -14,12 +14,6 @@ #ifndef ZT_TOPOLOGY_HPP #define ZT_TOPOLOGY_HPP -#include -#include -#include -#include -#include - #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 peerByHash(const Fingerprint &hash) - { - RWMutex::RLock _l(m_peers_l); - const SharedPtr *const ap = m_peersByIdentityHash.get(hash); - if (ap) - return *ap; - return SharedPtr(); - } + 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 peerByProbe(const uint64_t probe) - { - RWMutex::RLock _l(m_peers_l); - const SharedPtr *const ap = m_peersByIncomingProbe.get(probe); - if (ap) - return *ap; - return SharedPtr(); - } + void updateProbeToken(const SharedPtr &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 - ZT_INLINE void eachPath(F f) const - { - RWMutex::RLock l(m_paths_l); - for(Map< uint64_t,SharedPtr >::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 > &allPeers) const; + ZT_INLINE void getAllPeers(Vector< SharedPtr > &allPeers) const + { + RWMutex::RLock l(m_peers_l); + allPeers.clear(); + allPeers.reserve(m_peers.size()); + for(Map< Address,SharedPtr >::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); - - // 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(&r)->sin_addr.s_addr) + (uint64_t)Utils::ntoh(reinterpret_cast(&r)->sin_port) + (uint64_t)l; + return ((uint64_t)(reinterpret_cast(&r)->sin_addr.s_addr) << 24U) + + ((uint64_t)reinterpret_cast(&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(&r)->sin6_addr.s6_addr)[i]); - h += (h << 10U); - h ^= (h >> 6U); - } + uint64_t htmp[2]; + Utils::copy<16>(htmp,reinterpret_cast(&r)->sin6_addr.s6_addr); + const uint64_t h = htmp[0] ^ htmp[1]; #else - uint64_t h = s_pathHashSalt + (reinterpret_cast(reinterpret_cast(&r)->sin6_addr.s6_addr)[0] + reinterpret_cast(reinterpret_cast(&r)->sin6_addr.s6_addr)[1]); + const uint64_t h = reinterpret_cast(reinterpret_cast(&r)->sin6_addr.s6_addr)[0] ^ + reinterpret_cast(reinterpret_cast(&r)->sin6_addr.s6_addr)[1]; #endif - return h + (uint64_t)Utils::ntoh(reinterpret_cast(&r)->sin6_port) + (uint64_t)l; + return h + (uint64_t)Utils::ntoh(reinterpret_cast(&r)->sin6_port) ^ (uint64_t)l; } else { - return Utils::fnv1a32(reinterpret_cast(&r),sizeof(InetAddress)) + (uint64_t)l; + return (uint64_t)Utils::fnv1a32(reinterpret_cast(&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 > m_paths; + MultiMap< uint32_t,SharedPtr > m_peersByProbeToken; + Map< Address,SharedPtr > m_peers; - Map< uint64_t,SharedPtr > m_peersByIncomingProbe; - Map< Fingerprint,SharedPtr > m_peersByIdentityHash; Set< Identity > m_roots; Vector< SharedPtr > m_rootPeers; }; diff --git a/node/Trace.cpp b/node/Trace.cpp index 7e35b78c4..c801d03c8 100644 --- a/node/Trace.cpp +++ b/node/Trace.cpp @@ -18,10 +18,6 @@ #include "Path.hpp" #include "InetAddress.hpp" -#include -#include -#include - // NOTE: packet IDs are always handled in network byte order, so no need to convert them. namespace ZeroTier { diff --git a/node/Trace.hpp b/node/Trace.hpp index ea5d236fa..1a460b7db 100644 --- a/node/Trace.hpp +++ b/node/Trace.hpp @@ -20,11 +20,7 @@ #include "InetAddress.hpp" #include "Address.hpp" #include "MAC.hpp" - -#include -#include -#include -#include +#include "Containers.hpp" #define ZT_TRACE_F_VL1 0x01U #define ZT_TRACE_F_VL2 0x02U diff --git a/node/TriviallyCopyable.hpp b/node/TriviallyCopyable.hpp index 8e98fc185..f13c84bb0 100644 --- a/node/TriviallyCopyable.hpp +++ b/node/TriviallyCopyable.hpp @@ -17,9 +17,6 @@ #include "Constants.hpp" #include "Utils.hpp" -#include -#include - namespace ZeroTier { /** diff --git a/node/VL1.hpp b/node/VL1.hpp index a5ff6f4b8..300235eff 100644 --- a/node/VL1.hpp +++ b/node/VL1.hpp @@ -23,8 +23,6 @@ #include "FCV.hpp" #include "Containers.hpp" -#include - namespace ZeroTier { class RuntimeEnvironment; diff --git a/node/VL2.hpp b/node/VL2.hpp index f11afbbc0..381304a6a 100644 --- a/node/VL2.hpp +++ b/node/VL2.hpp @@ -20,6 +20,7 @@ #include "Protocol.hpp" #include "Mutex.hpp" #include "FCV.hpp" +#include "Containers.hpp" namespace ZeroTier {