From 16a3c14c535a0a6e5dda87e8a2206f23bdcee000 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 13 Apr 2020 12:22:08 -0700 Subject: [PATCH] A bunch of cleanup and refactoring, implementation of prep for forward secrecy still in progress. --- node/AES.hpp | 2 +- node/Address.hpp | 2 + node/C25519.cpp | 10 +- node/C25519.hpp | 8 +- node/Capability.cpp | 44 +-- node/Capability.hpp | 52 ++-- node/CertificateOfMembership.cpp | 122 ++++---- node/CertificateOfMembership.hpp | 36 +-- node/CertificateOfOwnership.cpp | 72 ++--- node/CertificateOfOwnership.hpp | 58 ++-- node/Constants.hpp | 49 ++- node/Containers.hpp | 8 + node/Credential.cpp | 8 +- node/Defragmenter.hpp | 52 ++-- node/Dictionary.cpp | 12 +- node/Dictionary.hpp | 8 +- node/Endpoint.hpp | 22 +- node/Expect.hpp | 45 +-- node/InetAddress.cpp | 104 +++---- node/InetAddress.hpp | 59 ++-- node/MAC.hpp | 2 +- node/Node.cpp | 172 +++++----- node/Node.hpp | 89 +++--- node/Path.cpp | 6 +- node/Path.hpp | 54 ++-- node/Peer.cpp | 518 ++++++++++++++----------------- node/Peer.hpp | 203 +++++------- node/Protocol.hpp | 217 ++++++------- node/Revocation.cpp | 50 +-- node/Revocation.hpp | 58 ++-- node/ScopedPtr.hpp | 30 +- node/SelfAwareness.cpp | 18 +- node/SelfAwareness.hpp | 26 +- node/SharedPtr.hpp | 82 ++--- node/Speck128.hpp | 18 +- node/SymmetricKey.hpp | 100 +++--- node/Tag.cpp | 42 +-- node/Tag.hpp | 48 +-- node/Tests.cpp | 12 - node/Tests.h | 8 +- node/Topology.cpp | 104 +++---- node/Topology.hpp | 97 +++--- node/Trace.cpp | 33 +- node/Trace.hpp | 61 ++-- node/VL1.cpp | 82 +++-- node/VL1.hpp | 33 +- node/VL2.cpp | 22 +- node/VL2.hpp | 19 +- 48 files changed, 1377 insertions(+), 1600 deletions(-) diff --git a/node/AES.hpp b/node/AES.hpp index 2d50ae3fa..2c1f02d15 100644 --- a/node/AES.hpp +++ b/node/AES.hpp @@ -23,10 +23,10 @@ #ifndef ZT_AES_NO_ACCEL #ifdef ZT_ARCH_X64 -#include #include #include #include +#include #define ZT_AES_AESNI 1 #endif #endif diff --git a/node/Address.hpp b/node/Address.hpp index c97d004e4..0524f4303 100644 --- a/node/Address.hpp +++ b/node/Address.hpp @@ -17,6 +17,7 @@ #include "Constants.hpp" #include "Utils.hpp" #include "TriviallyCopyable.hpp" +#include "Containers.hpp" #define ZT_ADDRESS_STRING_SIZE_MAX 11 @@ -91,6 +92,7 @@ public: s[10] = 0; return s; } + ZT_INLINE String toString() const { char s[ZT_ADDRESS_STRING_SIZE_MAX]; toString(s); return String(s); } /** * Check if this address is reserved diff --git a/node/C25519.cpp b/node/C25519.cpp index 434ce74a5..0d3919f1f 100644 --- a/node/C25519.cpp +++ b/node/C25519.cpp @@ -2371,14 +2371,14 @@ namespace ZeroTier { void C25519::generateCombined(uint8_t *pub,uint8_t *priv) { Utils::getSecureRandom(priv,ZT_C25519_COMBINED_PRIVATE_KEY_SIZE); - _calcPubDH(pub,priv); - _calcPubED(pub,priv); + s_calcPubDH(pub, priv); + s_calcPubED(pub, priv); } void C25519::generateC25519(uint8_t pub[ZT_C25519_ECDH_PUBLIC_KEY_SIZE],uint8_t priv[ZT_C25519_ECDH_PRIVATE_KEY_SIZE]) { Utils::getSecureRandom(priv,ZT_C25519_ECDH_PRIVATE_KEY_SIZE); - _calcPubDH(pub,priv); + s_calcPubDH(pub, priv); } void C25519::agree(const uint8_t mine[ZT_C25519_COMBINED_PRIVATE_KEY_SIZE],const uint8_t their[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE],uint8_t rawkey[ZT_C25519_ECDH_SHARED_SECRET_SIZE]) @@ -2472,14 +2472,14 @@ bool C25519::verify(const uint8_t their[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE],cons return Utils::secureEq(sig,t2,32); } -void C25519::_calcPubDH(uint8_t *const pub,const uint8_t *const priv) +void C25519::s_calcPubDH(uint8_t *pub, const uint8_t *priv) { // First 32 bytes of pub and priv are the keys for ECDH key // agreement. This generates the public portion from the private. crypto_scalarmult_base(pub,priv); } -void C25519::_calcPubED(uint8_t pub[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE],const uint8_t priv[ZT_C25519_COMBINED_PRIVATE_KEY_SIZE]) +void C25519::s_calcPubED(uint8_t *pub, const uint8_t *priv) { struct { uint8_t extsk[64]; diff --git a/node/C25519.hpp b/node/C25519.hpp index f9db3f002..77611ef1b 100644 --- a/node/C25519.hpp +++ b/node/C25519.hpp @@ -62,11 +62,11 @@ public: static ZT_INLINE void generateSatisfying(F cond,uint8_t pub[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE],uint8_t priv[ZT_C25519_COMBINED_PRIVATE_KEY_SIZE]) { Utils::getSecureRandom(priv,ZT_C25519_COMBINED_PRIVATE_KEY_SIZE); - _calcPubED(pub,priv); // do Ed25519 key -- bytes 32-63 of pub and priv + s_calcPubED(pub, priv); // do Ed25519 key -- bytes 32-63 of pub and priv do { ++(((uint64_t *)priv)[1]); --(((uint64_t *)priv)[2]); - _calcPubDH(pub,priv); // keep regenerating bytes 0-31 until satisfied + s_calcPubDH(pub, priv); // keep regenerating bytes 0-31 until satisfied } while (!cond(pub)); } @@ -116,11 +116,11 @@ public: private: // derive first 32 bytes of kp.pub from first 32 bytes of kp.priv // this is the ECDH key - static void _calcPubDH(uint8_t *pub,const uint8_t *priv); + static void s_calcPubDH(uint8_t *pub, const uint8_t *priv); // derive 2nd 32 bytes of kp.pub from 2nd 32 bytes of kp.priv // this is the Ed25519 sign/verify key - static void _calcPubED(uint8_t pub[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE],const uint8_t priv[ZT_C25519_COMBINED_PRIVATE_KEY_SIZE]); + static void s_calcPubED(uint8_t *pub, const uint8_t *priv); }; } // namespace ZeroTier diff --git a/node/Capability.cpp b/node/Capability.cpp index 661a8ea33..4b3bb35bf 100644 --- a/node/Capability.cpp +++ b/node/Capability.cpp @@ -21,10 +21,10 @@ namespace ZeroTier { bool Capability::sign(const Identity &from,const Address &to) noexcept { uint8_t buf[ZT_CAPABILITY_MARSHAL_SIZE_MAX + 16]; - _issuedTo = to; - _signedBy = from.address(); - _signatureLength = from.sign(buf,(unsigned int)marshal(buf,true),_signature,sizeof(_signature)); - return _signatureLength > 0; + m_issuedTo = to; + m_signedBy = from.address(); + m_signatureLength = from.sign(buf, (unsigned int)marshal(buf, true), m_signature, sizeof(m_signature)); + return m_signatureLength > 0; } int Capability::marshal(uint8_t data[ZT_CAPABILITY_MARSHAL_SIZE_MAX],const bool forSign) const noexcept @@ -36,23 +36,23 @@ int Capability::marshal(uint8_t data[ZT_CAPABILITY_MARSHAL_SIZE_MAX],const bool data[p++] = 0x7f; } - Utils::storeBigEndian(data + p,_nwid); p += 8; - Utils::storeBigEndian(data + p,(uint64_t)_ts); p += 8; - Utils::storeBigEndian(data + p,_id); p += 4; + Utils::storeBigEndian(data + p, m_nwid); p += 8; + Utils::storeBigEndian(data + p,(uint64_t)m_ts); p += 8; + Utils::storeBigEndian(data + p, m_id); p += 4; - Utils::storeBigEndian(data + p,(uint16_t)_ruleCount); p += 2; - p += Capability::marshalVirtualNetworkRules(data + p,_rules,_ruleCount); + Utils::storeBigEndian(data + p,(uint16_t)m_ruleCount); p += 2; + p += Capability::marshalVirtualNetworkRules(data + p, m_rules, m_ruleCount); // LEGACY: older versions supported multiple records with this being a maximum custody // chain length. This is deprecated so set the max chain length to one. data[p++] = (uint8_t)1; if (!forSign) { - _issuedTo.copyTo(data + p); p += ZT_ADDRESS_LENGTH; - _signedBy.copyTo(data + 0); p += ZT_ADDRESS_LENGTH; + m_issuedTo.copyTo(data + p); p += ZT_ADDRESS_LENGTH; + m_signedBy.copyTo(data + 0); p += ZT_ADDRESS_LENGTH; data[p++] = 1; // LEGACY: old versions require a reserved byte here - Utils::storeBigEndian(data + p,(uint16_t)_signatureLength); p += 2; - Utils::copy(data + p,_signature,_signatureLength); p += (int)_signatureLength; + Utils::storeBigEndian(data + p,(uint16_t)m_signatureLength); p += 2; + Utils::copy(data + p, m_signature, m_signatureLength); p += (int)m_signatureLength; // LEGACY: older versions supported more than one record terminated by a zero address. for(int k=0;k(data); - _ts = (int64_t)Utils::loadBigEndian(data + 8); - _id = Utils::loadBigEndian(data + 16); + m_nwid = Utils::loadBigEndian(data); + m_ts = (int64_t)Utils::loadBigEndian(data + 8); + m_id = Utils::loadBigEndian(data + 16); const unsigned int rc = Utils::loadBigEndian(data + 20); if (rc > ZT_MAX_CAPABILITY_RULES) return -1; - const int rulesLen = unmarshalVirtualNetworkRules(data + 22,len - 22,_rules,_ruleCount,rc); + const int rulesLen = unmarshalVirtualNetworkRules(data + 22,len - 22, m_rules, m_ruleCount, rc); if (rulesLen < 0) return rulesLen; int p = 22 + rulesLen; @@ -103,17 +103,17 @@ int Capability::unmarshal(const uint8_t *data,int len) noexcept if (!to) break; - _issuedTo = to; + m_issuedTo = to; if ((p + ZT_ADDRESS_LENGTH) > len) return -1; - _signedBy.setTo(data + p); p += ZT_ADDRESS_LENGTH + 1; // LEGACY: +1 to skip reserved field + m_signedBy.setTo(data + p); p += ZT_ADDRESS_LENGTH + 1; // LEGACY: +1 to skip reserved field if ((p + 2) > len) return -1; - _signatureLength = Utils::loadBigEndian(data + p); p += 2; - if ((_signatureLength > sizeof(_signature))||((p + (int)_signatureLength) > len)) + m_signatureLength = Utils::loadBigEndian(data + p); p += 2; + if ((m_signatureLength > sizeof(m_signature)) || ((p + (int)m_signatureLength) > len)) return -1; - Utils::copy(_signature,data + p,_signatureLength); p += (int)_signatureLength; + Utils::copy(m_signature, data + p, m_signatureLength); p += (int)m_signatureLength; } if ((p + 2) > len) diff --git a/node/Capability.hpp b/node/Capability.hpp index 21886b187..0b75a4e51 100644 --- a/node/Capability.hpp +++ b/node/Capability.hpp @@ -68,33 +68,33 @@ public: * @param ruleCount Number of flow rules */ ZT_INLINE Capability(const uint32_t id,const uint64_t nwid,const int64_t ts,const ZT_VirtualNetworkRule *const rules,const unsigned int ruleCount) noexcept : // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init) - _nwid(nwid), - _ts(ts), - _id(id), - _ruleCount((ruleCount < ZT_MAX_CAPABILITY_RULES) ? ruleCount : ZT_MAX_CAPABILITY_RULES), - _signatureLength(0) + m_nwid(nwid), + m_ts(ts), + m_id(id), + m_ruleCount((ruleCount < ZT_MAX_CAPABILITY_RULES) ? ruleCount : ZT_MAX_CAPABILITY_RULES), + m_signatureLength(0) { - if (_ruleCount > 0) - Utils::copy(_rules,rules,sizeof(ZT_VirtualNetworkRule) * _ruleCount); + if (m_ruleCount > 0) + Utils::copy(m_rules, rules, sizeof(ZT_VirtualNetworkRule) * m_ruleCount); } /** * @return Rules -- see ruleCount() for size of array */ - ZT_INLINE const ZT_VirtualNetworkRule *rules() const noexcept { return _rules; } + ZT_INLINE const ZT_VirtualNetworkRule *rules() const noexcept { return m_rules; } /** * @return Number of rules in rules() */ - ZT_INLINE unsigned int ruleCount() const noexcept { return _ruleCount; } + ZT_INLINE unsigned int ruleCount() const noexcept { return m_ruleCount; } - ZT_INLINE uint32_t id() const noexcept { return _id; } - ZT_INLINE uint64_t networkId() const noexcept { return _nwid; } - ZT_INLINE int64_t timestamp() const noexcept { return _ts; } - ZT_INLINE const Address &issuedTo() const noexcept { return _issuedTo; } - ZT_INLINE const Address &signer() const noexcept { return _signedBy; } - ZT_INLINE const uint8_t *signature() const noexcept { return _signature; } - ZT_INLINE unsigned int signatureLength() const noexcept { return _signatureLength; } + ZT_INLINE uint32_t id() const noexcept { return m_id; } + ZT_INLINE uint64_t networkId() const noexcept { return m_nwid; } + ZT_INLINE int64_t timestamp() const noexcept { return m_ts; } + ZT_INLINE const Address &issuedTo() const noexcept { return m_issuedTo; } + ZT_INLINE const Address &signer() const noexcept { return m_signedBy; } + ZT_INLINE const uint8_t *signature() const noexcept { return m_signature; } + ZT_INLINE unsigned int signatureLength() const noexcept { return m_signatureLength; } /** * Sign this capability and add signature to its chain of custody @@ -145,21 +145,21 @@ public: static int unmarshalVirtualNetworkRules(const uint8_t *data,int len,ZT_VirtualNetworkRule *rules,unsigned int &ruleCount,unsigned int maxRuleCount) noexcept; // Provides natural sort order by ID - ZT_INLINE bool operator<(const Capability &c) const noexcept { return (_id < c._id); } + ZT_INLINE bool operator<(const Capability &c) const noexcept { return (m_id < c.m_id); } ZT_INLINE bool operator==(const Capability &c) const noexcept { return (memcmp(this,&c,sizeof(Capability)) == 0); } ZT_INLINE bool operator!=(const Capability &c) const noexcept { return (memcmp(this,&c,sizeof(Capability)) != 0); } private: - uint64_t _nwid; - int64_t _ts; - uint32_t _id; - unsigned int _ruleCount; - ZT_VirtualNetworkRule _rules[ZT_MAX_CAPABILITY_RULES]; - Address _issuedTo; - Address _signedBy; - unsigned int _signatureLength; - uint8_t _signature[ZT_SIGNATURE_BUFFER_SIZE]; + uint64_t m_nwid; + int64_t m_ts; + uint32_t m_id; + unsigned int m_ruleCount; + ZT_VirtualNetworkRule m_rules[ZT_MAX_CAPABILITY_RULES]; + Address m_issuedTo; + Address m_signedBy; + unsigned int m_signatureLength; + uint8_t m_signature[ZT_SIGNATURE_BUFFER_SIZE]; }; } // namespace ZeroTier diff --git a/node/CertificateOfMembership.cpp b/node/CertificateOfMembership.cpp index 2518212e0..ff1acbe9e 100644 --- a/node/CertificateOfMembership.cpp +++ b/node/CertificateOfMembership.cpp @@ -16,30 +16,30 @@ namespace ZeroTier { CertificateOfMembership::CertificateOfMembership(const int64_t timestamp,const int64_t timestampMaxDelta,const uint64_t nwid,const Identity &issuedTo) noexcept : // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init) - _timestamp(timestamp), - _timestampMaxDelta(timestampMaxDelta), - _networkId(nwid), - _issuedTo(issuedTo.fingerprint()), - _signatureLength(0) {} + m_timestamp(timestamp), + m_timestampMaxDelta(timestampMaxDelta), + m_networkId(nwid), + m_issuedTo(issuedTo.fingerprint()), + m_signatureLength(0) {} bool CertificateOfMembership::agreesWith(const CertificateOfMembership &other) const noexcept { // NOTE: we always do explicit absolute value with an if() since llabs() can have overflow // conditions that could introduce a vulnerability. - if (other._timestamp > _timestamp) { - if ((other._timestamp - _timestamp) > std::min(_timestampMaxDelta,other._timestampMaxDelta)) + if (other.m_timestamp > m_timestamp) { + if ((other.m_timestamp - m_timestamp) > std::min(m_timestampMaxDelta, other.m_timestampMaxDelta)) return false; } else { - if ((_timestamp - other._timestamp) > std::min(_timestampMaxDelta,other._timestampMaxDelta)) + if ((m_timestamp - other.m_timestamp) > std::min(m_timestampMaxDelta, other.m_timestampMaxDelta)) return false; } // us <> them - for(FCV<_Qualifier,ZT_CERTIFICATEOFMEMBERSHIP_MAX_ADDITIONAL_QUALIFIERS>::const_iterator i(_additionalQualifiers.begin());i != _additionalQualifiers.end();++i) { + for(FCV::const_iterator i(m_additionalQualifiers.begin());i != m_additionalQualifiers.end();++i) { if (i->delta != 0xffffffffffffffffULL) { const uint64_t *v2 = nullptr; - for(FCV<_Qualifier,ZT_CERTIFICATEOFMEMBERSHIP_MAX_ADDITIONAL_QUALIFIERS>::const_iterator j(other._additionalQualifiers.begin());j != other._additionalQualifiers.end();++i) { + for(FCV::const_iterator j(other.m_additionalQualifiers.begin());j != other.m_additionalQualifiers.end();++i) { if (j->id == i->id) { v2 = &(j->value); break; @@ -58,10 +58,10 @@ bool CertificateOfMembership::agreesWith(const CertificateOfMembership &other) c } // them <> us (we need a second pass in case they have qualifiers we don't or vice versa) - for(FCV<_Qualifier,ZT_CERTIFICATEOFMEMBERSHIP_MAX_ADDITIONAL_QUALIFIERS>::const_iterator i(other._additionalQualifiers.begin());i != other._additionalQualifiers.end();++i) { + for(FCV::const_iterator i(other.m_additionalQualifiers.begin());i != other.m_additionalQualifiers.end();++i) { if (i->delta != 0xffffffffffffffffULL) { const uint64_t *v2 = nullptr; - for(FCV<_Qualifier,ZT_CERTIFICATEOFMEMBERSHIP_MAX_ADDITIONAL_QUALIFIERS>::const_iterator j(_additionalQualifiers.begin());j != _additionalQualifiers.end();++i) { + for(FCV::const_iterator j(m_additionalQualifiers.begin());j != m_additionalQualifiers.end();++i) { if (j->id == i->id) { v2 = &(j->value); break; @@ -81,16 +81,16 @@ bool CertificateOfMembership::agreesWith(const CertificateOfMembership &other) c // SECURITY: check for issued-to inequality is a sanity check. This should be impossible since elsewhere // in the code COMs are checked to ensure that they do in fact belong to their issued-to identities. - return (other._networkId == _networkId) && (_networkId != 0) && (other._issuedTo.address() != _issuedTo.address()); + return (other.m_networkId == m_networkId) && (m_networkId != 0) && (other.m_issuedTo.address() != m_issuedTo.address()); } bool CertificateOfMembership::sign(const Identity &with) noexcept { - _signedBy = with.address(); + m_signedBy = with.address(); uint64_t buf[ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX / 8]; - const unsigned int bufSize = _fillSigningBuf(buf); - _signatureLength = with.sign(buf,bufSize,_signature,sizeof(_signature)); - return _signatureLength > 0; + const unsigned int bufSize = m_fillSigningBuf(buf); + m_signatureLength = with.sign(buf, bufSize, m_signature, sizeof(m_signature)); + return m_signatureLength > 0; } int CertificateOfMembership::marshal(uint8_t data[ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX],const bool v2) const noexcept @@ -101,40 +101,40 @@ int CertificateOfMembership::marshal(uint8_t data[ZT_CERTIFICATEOFMEMBERSHIP_MAR // equality compare, and the address of the issued-to node as an informational tuple. int p = 3; Utils::storeBigEndian(data + p,0); p += 8; - Utils::storeBigEndian(data + p,(uint64_t)_timestamp); p += 8; - Utils::storeBigEndian(data + p,(uint64_t)_timestampMaxDelta); p += 8; + Utils::storeBigEndian(data + p,(uint64_t)m_timestamp); p += 8; + Utils::storeBigEndian(data + p,(uint64_t)m_timestampMaxDelta); p += 8; Utils::storeBigEndian(data + p,1); p += 8; - Utils::storeBigEndian(data + p,_networkId); p += 8; + Utils::storeBigEndian(data + p, m_networkId); p += 8; Utils::storeBigEndian(data + p,0); p += 8; Utils::storeBigEndian(data + p,2); p += 8; - Utils::storeBigEndian(data + p,_issuedTo.address().toInt()); p += 8; + Utils::storeBigEndian(data + p, m_issuedTo.address().toInt()); p += 8; Utils::storeAsIsEndian(data + p,0xffffffffffffffffULL); p += 8; if (v2) { // V2 marshal format will have three tuples followed by the fingerprint hash. Utils::storeBigEndian(data + 1,3); - Utils::copy<48>(data + p,_issuedTo.hash()); + Utils::copy<48>(data + p, m_issuedTo.hash()); p += 48; } else { // V1 marshal format must shove everything into tuples, resulting in nine. Utils::storeBigEndian(data + 1,9); for(int k=0;k<6;++k) { Utils::storeBigEndian(data + p,(uint64_t)k + 3); p += 8; - Utils::storeAsIsEndian(data + p,Utils::loadAsIsEndian(_issuedTo.hash() + (k * 8))); p += 8; + Utils::storeAsIsEndian(data + p,Utils::loadAsIsEndian(m_issuedTo.hash() + (k * 8))); p += 8; Utils::storeAsIsEndian(data + p,0xffffffffffffffffULL); p += 8; } } - _signedBy.copyTo(data + p); p += 5; + m_signedBy.copyTo(data + p); p += 5; if (v2) { // V2 marshal format prefixes signatures with a 16-bit length to support future signature types. - Utils::storeBigEndian(data + p,(uint16_t)_signatureLength); p += 2; - Utils::copy(data + p,_signature,_signatureLength); - p += (int)_signatureLength; + Utils::storeBigEndian(data + p,(uint16_t)m_signatureLength); p += 2; + Utils::copy(data + p, m_signature, m_signatureLength); + p += (int)m_signatureLength; } else { // V1 only supports 96-byte signature fields. - Utils::copy<96>(data + p,_signature); + Utils::copy<96>(data + p, m_signature); p += 96; } @@ -160,70 +160,70 @@ int CertificateOfMembership::unmarshal(const uint8_t *data,int len) noexcept const uint64_t delta = Utils::loadBigEndian(data + p); p += 8; // NOLINT(hicpp-use-auto,modernize-use-auto) switch(id) { case 0: - _timestamp = (int64_t)value; - _timestampMaxDelta = (int64_t)delta; + m_timestamp = (int64_t)value; + m_timestampMaxDelta = (int64_t)delta; break; case 1: - _networkId = value; + m_networkId = value; break; case 2: - _issuedTo.apiFingerprint()->address = value; + m_issuedTo.apiFingerprint()->address = value; break; // V1 nodes will pack the hash into qualifier tuples. case 3: - Utils::storeBigEndian(_issuedTo.apiFingerprint()->hash,value); + Utils::storeBigEndian(m_issuedTo.apiFingerprint()->hash, value); break; case 4: - Utils::storeBigEndian(_issuedTo.apiFingerprint()->hash + 8,value); + Utils::storeBigEndian(m_issuedTo.apiFingerprint()->hash + 8, value); break; case 5: - Utils::storeBigEndian(_issuedTo.apiFingerprint()->hash + 16,value); + Utils::storeBigEndian(m_issuedTo.apiFingerprint()->hash + 16, value); break; case 6: - Utils::storeBigEndian(_issuedTo.apiFingerprint()->hash + 24,value); + Utils::storeBigEndian(m_issuedTo.apiFingerprint()->hash + 24, value); break; case 7: - Utils::storeBigEndian(_issuedTo.apiFingerprint()->hash + 32,value); + Utils::storeBigEndian(m_issuedTo.apiFingerprint()->hash + 32, value); break; case 8: - Utils::storeBigEndian(_issuedTo.apiFingerprint()->hash + 40,value); + Utils::storeBigEndian(m_issuedTo.apiFingerprint()->hash + 40, value); break; default: - if (_additionalQualifiers.size() >= ZT_CERTIFICATEOFMEMBERSHIP_MAX_ADDITIONAL_QUALIFIERS) + if (m_additionalQualifiers.size() >= ZT_CERTIFICATEOFMEMBERSHIP_MAX_ADDITIONAL_QUALIFIERS) return -1; - _additionalQualifiers.push_back(_Qualifier(id,value,delta)); + m_additionalQualifiers.push_back(p_Qualifier(id, value, delta)); break; } } - std::sort(_additionalQualifiers.begin(),_additionalQualifiers.end()); + std::sort(m_additionalQualifiers.begin(), m_additionalQualifiers.end()); if (data[0] == 1) { if ((p + 96) > len) return -1; - _signatureLength = 96; - Utils::copy<96>(_signature,data + p); + m_signatureLength = 96; + Utils::copy<96>(m_signature, data + p); return p + 96; } else if (data[0] == 2) { if ((p + 48) > len) return -1; - Utils::copy<48>(_issuedTo.apiFingerprint()->hash,data + p); + Utils::copy<48>(m_issuedTo.apiFingerprint()->hash, data + p); p += 48; if ((p + 2) > len) return -1; - _signatureLength = Utils::loadBigEndian(data + p); - if ((_signatureLength > (unsigned int)sizeof(_signature))||((p + (int)_signatureLength) > len)) + m_signatureLength = Utils::loadBigEndian(data + p); + if ((m_signatureLength > (unsigned int)sizeof(m_signature)) || ((p + (int)m_signatureLength) > len)) return -1; - Utils::copy(_signature,data + p,_signatureLength); - return p + (int)_signatureLength; + Utils::copy(m_signature, data + p, m_signatureLength); + return p + (int)m_signatureLength; } return -1; } -unsigned int CertificateOfMembership::_fillSigningBuf(uint64_t buf[ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX / 8]) const noexcept +unsigned int CertificateOfMembership::m_fillSigningBuf(uint64_t *buf) const noexcept { const uint64_t informational = 0xffffffffffffffffULL; @@ -235,41 +235,41 @@ unsigned int CertificateOfMembership::_fillSigningBuf(uint64_t buf[ZT_CERTIFICAT // The standard three tuples that must begin every COM. buf[0] = 0; - buf[1] = Utils::hton((uint64_t)_timestamp); - buf[2] = Utils::hton((uint64_t)_timestampMaxDelta); + buf[1] = Utils::hton((uint64_t)m_timestamp); + buf[2] = Utils::hton((uint64_t)m_timestampMaxDelta); buf[3] = ZT_CONST_TO_BE_UINT64(1); - buf[4] = Utils::hton(_networkId); + buf[4] = Utils::hton(m_networkId); buf[5] = 0; buf[6] = ZT_CONST_TO_BE_UINT64(2); - buf[7] = Utils::hton(_issuedTo.address().toInt()); + buf[7] = Utils::hton(m_issuedTo.address().toInt()); buf[8] = informational; unsigned int p = 9; // The full identity fingerprint of the peer to whom the COM was issued, // embeded as a series of informational tuples. - if (_issuedTo.haveHash()) { + if (m_issuedTo.haveHash()) { buf[p++] = ZT_CONST_TO_BE_UINT64(3); - buf[p++] = Utils::loadAsIsEndian(_issuedTo.hash()); + buf[p++] = Utils::loadAsIsEndian(m_issuedTo.hash()); buf[p++] = informational; buf[p++] = ZT_CONST_TO_BE_UINT64(4); - buf[p++] = Utils::loadAsIsEndian(_issuedTo.hash() + 8); + buf[p++] = Utils::loadAsIsEndian(m_issuedTo.hash() + 8); buf[p++] = informational; buf[p++] = ZT_CONST_TO_BE_UINT64(5); - buf[p++] = Utils::loadAsIsEndian(_issuedTo.hash() + 16); + buf[p++] = Utils::loadAsIsEndian(m_issuedTo.hash() + 16); buf[p++] = informational; buf[p++] = ZT_CONST_TO_BE_UINT64(6); - buf[p++] = Utils::loadAsIsEndian(_issuedTo.hash() + 24); + buf[p++] = Utils::loadAsIsEndian(m_issuedTo.hash() + 24); buf[p++] = informational; buf[p++] = ZT_CONST_TO_BE_UINT64(7); - buf[p++] = Utils::loadAsIsEndian(_issuedTo.hash() + 32); + buf[p++] = Utils::loadAsIsEndian(m_issuedTo.hash() + 32); buf[p++] = informational; buf[p++] = ZT_CONST_TO_BE_UINT64(8); - buf[p++] = Utils::loadAsIsEndian(_issuedTo.hash() + 40); + buf[p++] = Utils::loadAsIsEndian(m_issuedTo.hash() + 40); buf[p++] = informational; } - for(FCV<_Qualifier,ZT_CERTIFICATEOFMEMBERSHIP_MAX_ADDITIONAL_QUALIFIERS>::const_iterator i(_additionalQualifiers.begin());i != _additionalQualifiers.end();++i) { // NOLINT(modernize-loop-convert) + for(FCV::const_iterator i(m_additionalQualifiers.begin());i != m_additionalQualifiers.end();++i) { // NOLINT(modernize-loop-convert) buf[p++] = Utils::hton(i->id); buf[p++] = Utils::hton(i->value); buf[p++] = Utils::hton(i->delta); diff --git a/node/CertificateOfMembership.hpp b/node/CertificateOfMembership.hpp index 856ed8655..cf728271b 100644 --- a/node/CertificateOfMembership.hpp +++ b/node/CertificateOfMembership.hpp @@ -126,7 +126,7 @@ public: /** * @return True if there's something here */ - ZT_INLINE operator bool() const noexcept { return (_networkId != 0); } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) + ZT_INLINE operator bool() const noexcept { return (m_networkId != 0); } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) /** * @return Credential ID, always 0 for COMs @@ -136,22 +136,22 @@ public: /** * @return Timestamp for this cert and maximum delta for timestamp */ - ZT_INLINE int64_t timestamp() const noexcept { return _timestamp; } + ZT_INLINE int64_t timestamp() const noexcept { return m_timestamp; } /** * @return Maximum allowed difference between timestamps */ - ZT_INLINE int64_t timestampMaxDelta() const noexcept { return _timestampMaxDelta; } + ZT_INLINE int64_t timestampMaxDelta() const noexcept { return m_timestampMaxDelta; } /** * @return Fingerprint of identity to which this cert was issued */ - ZT_INLINE const Fingerprint &issuedTo() const noexcept { return _issuedTo; } + ZT_INLINE const Fingerprint &issuedTo() const noexcept { return m_issuedTo; } /** * @return Network ID for which this cert was issued */ - ZT_INLINE uint64_t networkId() const noexcept { return _networkId; } + ZT_INLINE uint64_t networkId() const noexcept { return m_networkId; } /** * Compare two certificates for parameter agreement @@ -191,26 +191,26 @@ public: int unmarshal(const uint8_t *data,int len) noexcept; private: - unsigned int _fillSigningBuf(uint64_t buf[ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX / 8]) const noexcept; + unsigned int m_fillSigningBuf(uint64_t *buf) const noexcept; - struct _Qualifier + struct p_Qualifier { - ZT_INLINE _Qualifier() noexcept : id(0),value(0),delta(0) {} - ZT_INLINE _Qualifier(const uint64_t id_,const uint64_t value_,const uint64_t delta_) noexcept : id(id_),value(value_),delta(delta_) {} + ZT_INLINE p_Qualifier() noexcept : id(0), value(0), delta(0) {} + ZT_INLINE p_Qualifier(const uint64_t id_, const uint64_t value_, const uint64_t delta_) noexcept : id(id_), value(value_), delta(delta_) {} uint64_t id; uint64_t value; uint64_t delta; - ZT_INLINE bool operator<(const _Qualifier &q) const noexcept { return (id < q.id); } // sort order + ZT_INLINE bool operator<(const p_Qualifier &q) const noexcept { return (id < q.id); } // sort order }; - FCV<_Qualifier,ZT_CERTIFICATEOFMEMBERSHIP_MAX_ADDITIONAL_QUALIFIERS> _additionalQualifiers; - int64_t _timestamp; - int64_t _timestampMaxDelta; - uint64_t _networkId; - Fingerprint _issuedTo; - Address _signedBy; - unsigned int _signatureLength; - uint8_t _signature[ZT_SIGNATURE_BUFFER_SIZE]; + FCV m_additionalQualifiers; + int64_t m_timestamp; + int64_t m_timestampMaxDelta; + uint64_t m_networkId; + Fingerprint m_issuedTo; + Address m_signedBy; + unsigned int m_signatureLength; + uint8_t m_signature[ZT_SIGNATURE_BUFFER_SIZE]; }; } // namespace ZeroTier diff --git a/node/CertificateOfOwnership.cpp b/node/CertificateOfOwnership.cpp index 690ffa99b..4dacdc74f 100644 --- a/node/CertificateOfOwnership.cpp +++ b/node/CertificateOfOwnership.cpp @@ -17,34 +17,34 @@ namespace ZeroTier { void CertificateOfOwnership::addThing(const InetAddress &ip) { - if (_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) + if (m_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) return; if (ip.family() == AF_INET) { - _thingTypes[_thingCount] = THING_IPV4_ADDRESS; - Utils::copy<4>(_thingValues[_thingCount],&(reinterpret_cast(&ip)->sin_addr.s_addr)); - ++_thingCount; + m_thingTypes[m_thingCount] = THING_IPV4_ADDRESS; + Utils::copy<4>(m_thingValues[m_thingCount], &(reinterpret_cast(&ip)->sin_addr.s_addr)); + ++m_thingCount; } else if (ip.family() == AF_INET6) { - _thingTypes[_thingCount] = THING_IPV6_ADDRESS; - Utils::copy<16>(_thingValues[_thingCount],reinterpret_cast(&ip)->sin6_addr.s6_addr); - ++_thingCount; + m_thingTypes[m_thingCount] = THING_IPV6_ADDRESS; + Utils::copy<16>(m_thingValues[m_thingCount], reinterpret_cast(&ip)->sin6_addr.s6_addr); + ++m_thingCount; } } void CertificateOfOwnership::addThing(const MAC &mac) { - if (_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) + if (m_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) return; - _thingTypes[_thingCount] = THING_MAC_ADDRESS; - mac.copyTo(_thingValues[_thingCount]); - ++_thingCount; + m_thingTypes[m_thingCount] = THING_MAC_ADDRESS; + mac.copyTo(m_thingValues[m_thingCount]); + ++m_thingCount; } bool CertificateOfOwnership::sign(const Identity &signer) { uint8_t buf[ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX + 16]; if (signer.hasPrivate()) { - _signedBy = signer.address(); - _signatureLength = signer.sign(buf,(unsigned int)marshal(buf,true),_signature,sizeof(_signature)); + m_signedBy = signer.address(); + m_signatureLength = signer.sign(buf, (unsigned int)marshal(buf, true), m_signature, sizeof(m_signature)); return true; } return false; @@ -57,23 +57,23 @@ int CertificateOfOwnership::marshal(uint8_t data[ZT_CERTIFICATEOFOWNERSHIP_MARSH for(int k=0;k<16;++k) data[p++] = 0x7f; } - Utils::storeBigEndian(data + p,_networkId); - Utils::storeBigEndian(data + p + 8,(uint64_t)_ts); - Utils::storeBigEndian(data + p + 16,_flags); - Utils::storeBigEndian(data + p + 24,_id); - Utils::storeBigEndian(data + p + 28,(uint16_t)_thingCount); + Utils::storeBigEndian(data + p, m_networkId); + Utils::storeBigEndian(data + p + 8,(uint64_t)m_ts); + Utils::storeBigEndian(data + p + 16, m_flags); + Utils::storeBigEndian(data + p + 24, m_id); + Utils::storeBigEndian(data + p + 28,(uint16_t)m_thingCount); p += 30; - for(unsigned int i=0,j=_thingCount;i(data + p,_thingValues[i]); + for(unsigned int i=0,j=m_thingCount;i < j;++i) { + data[p++] = m_thingTypes[i]; + Utils::copy(data + p, m_thingValues[i]); p += ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE; } - _issuedTo.copyTo(data + p); p += ZT_ADDRESS_LENGTH; - _signedBy.copyTo(data + p); p += ZT_ADDRESS_LENGTH; + m_issuedTo.copyTo(data + p); p += ZT_ADDRESS_LENGTH; + m_signedBy.copyTo(data + p); p += ZT_ADDRESS_LENGTH; if (!forSign) { data[p++] = 1; - Utils::storeBigEndian(data + p,(uint16_t)_signatureLength); p += 2; - Utils::copy(data + p,_signature,_signatureLength); p += (int)_signatureLength; + Utils::storeBigEndian(data + p,(uint16_t)m_signatureLength); p += 2; + Utils::copy(data + p, m_signature, m_signatureLength); p += (int)m_signatureLength; } data[p++] = 0; data[p++] = 0; @@ -89,27 +89,27 @@ int CertificateOfOwnership::unmarshal(const uint8_t *data,int len) noexcept if (len < 30) return -1; - _networkId = Utils::loadBigEndian(data); - _ts = (int64_t)Utils::loadBigEndian(data + 8); - _flags = Utils::loadBigEndian(data + 16); - _id = Utils::loadBigEndian(data + 24); - _thingCount = Utils::loadBigEndian(data + 28); - if (_thingCount > ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) + m_networkId = Utils::loadBigEndian(data); + m_ts = (int64_t)Utils::loadBigEndian(data + 8); + m_flags = Utils::loadBigEndian(data + 16); + m_id = Utils::loadBigEndian(data + 24); + m_thingCount = Utils::loadBigEndian(data + 28); + if (m_thingCount > ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) return -1; int p = 30; - for(unsigned int i=0,j=_thingCount;i len) return -1; - _thingTypes[i] = data[p++]; - Utils::copy(_thingValues[i],data + p); + m_thingTypes[i] = data[p++]; + Utils::copy(m_thingValues[i], data + p); p += ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE; } if ((p + ZT_ADDRESS_LENGTH + ZT_ADDRESS_LENGTH + 1 + 2) > len) return -1; - _issuedTo.setTo(data + p); p += ZT_ADDRESS_LENGTH; - _signedBy.setTo(data + p); p += ZT_ADDRESS_LENGTH + 1; + m_issuedTo.setTo(data + p); p += ZT_ADDRESS_LENGTH; + m_signedBy.setTo(data + p); p += ZT_ADDRESS_LENGTH + 1; p += 2 + Utils::loadBigEndian(data + p); if (p > len) diff --git a/node/CertificateOfOwnership.hpp b/node/CertificateOfOwnership.hpp index 40d8be646..06c4bed6f 100644 --- a/node/CertificateOfOwnership.hpp +++ b/node/CertificateOfOwnership.hpp @@ -65,23 +65,23 @@ public: ZT_INLINE CertificateOfOwnership(const uint64_t nwid,const int64_t ts,const Address &issuedTo,const uint32_t id) noexcept // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init) { memoryZero(this); - _networkId = nwid; - _ts = ts; - _id = id; - _issuedTo = issuedTo; + m_networkId = nwid; + m_ts = ts; + m_id = id; + m_issuedTo = issuedTo; } - ZT_INLINE uint64_t networkId() const noexcept { return _networkId; } - ZT_INLINE int64_t timestamp() const noexcept { return _ts; } - ZT_INLINE uint32_t id() const noexcept { return _id; } - ZT_INLINE const Address &issuedTo() const noexcept { return _issuedTo; } - ZT_INLINE const Address &signer() const noexcept { return _signedBy; } - ZT_INLINE const uint8_t *signature() const noexcept { return _signature; } - ZT_INLINE unsigned int signatureLength() const noexcept { return _signatureLength; } + ZT_INLINE uint64_t networkId() const noexcept { return m_networkId; } + ZT_INLINE int64_t timestamp() const noexcept { return m_ts; } + ZT_INLINE uint32_t id() const noexcept { return m_id; } + ZT_INLINE const Address &issuedTo() const noexcept { return m_issuedTo; } + ZT_INLINE const Address &signer() const noexcept { return m_signedBy; } + ZT_INLINE const uint8_t *signature() const noexcept { return m_signature; } + ZT_INLINE unsigned int signatureLength() const noexcept { return m_signatureLength; } - ZT_INLINE unsigned int thingCount() const noexcept { return (unsigned int)_thingCount; } - ZT_INLINE Thing thingType(const unsigned int i) const noexcept { return (Thing)_thingTypes[i]; } - ZT_INLINE const uint8_t *thingValue(const unsigned int i) const noexcept { return _thingValues[i]; } + ZT_INLINE unsigned int thingCount() const noexcept { return (unsigned int)m_thingCount; } + ZT_INLINE Thing thingType(const unsigned int i) const noexcept { return (Thing)m_thingTypes[i]; } + ZT_INLINE const uint8_t *thingValue(const unsigned int i) const noexcept { return m_thingValues[i]; } ZT_INLINE bool owns(const InetAddress &ip) const noexcept { @@ -139,7 +139,7 @@ public: int unmarshal(const uint8_t *data,int len) noexcept; // Provides natural sort order by ID - ZT_INLINE bool operator<(const CertificateOfOwnership &coo) const noexcept { return (_id < coo._id); } + ZT_INLINE bool operator<(const CertificateOfOwnership &coo) const noexcept { return (m_id < coo.m_id); } ZT_INLINE bool operator==(const CertificateOfOwnership &coo) const noexcept { return (memcmp(this,&coo,sizeof(CertificateOfOwnership)) == 0); } ZT_INLINE bool operator!=(const CertificateOfOwnership &coo) const noexcept { return (memcmp(this,&coo,sizeof(CertificateOfOwnership)) != 0); } @@ -147,11 +147,11 @@ public: private: ZT_INLINE bool _owns(const Thing &t,const void *v,unsigned int l) const noexcept { - for(unsigned int i=0,j=_thingCount;i(v)[k] != _thingValues[i][k]) + if (reinterpret_cast(v)[k] != m_thingValues[i][k]) break; ++k; } @@ -162,17 +162,17 @@ private: return false; } - uint64_t _networkId; - int64_t _ts; - uint64_t _flags; - uint32_t _id; - uint16_t _thingCount; - uint8_t _thingTypes[ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS]; - uint8_t _thingValues[ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS][ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE]; - Address _issuedTo; - Address _signedBy; - unsigned int _signatureLength; - uint8_t _signature[ZT_SIGNATURE_BUFFER_SIZE]; + uint64_t m_networkId; + int64_t m_ts; + uint64_t m_flags; + uint32_t m_id; + uint16_t m_thingCount; + uint8_t m_thingTypes[ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS]; + uint8_t m_thingValues[ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS][ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE]; + Address m_issuedTo; + Address m_signedBy; + unsigned int m_signatureLength; + uint8_t m_signature[ZT_SIGNATURE_BUFFER_SIZE]; }; } // namespace ZeroTier diff --git a/node/Constants.hpp b/node/Constants.hpp index 8f8bcabc2..a01139a2e 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -87,22 +87,14 @@ #define ZT_SYMMETRIC_KEY_TTL_MESSAGES 2147483648 /** - * Maximum delay between timer task checks + * Normal delay between processBackgroundTasks calls. */ -#define ZT_MAX_TIMER_TASK_INTERVAL 1000 - -/** - * Interval between steps or stages in multi-stage NAT traversal operations. - * - * This is for example the interval between initial firewall openers and real packets - * for two-phase IPv4 hole punch. - */ -#define ZT_NAT_TRAVERSAL_INTERVAL 200 +#define ZT_TIMER_TASK_INTERVAL 2000 /** * How often most internal cleanup and housekeeping tasks are performed */ -#define ZT_HOUSEKEEPING_PERIOD 120000 +#define ZT_HOUSEKEEPING_PERIOD 300000 /** * How often network housekeeping is performed @@ -125,9 +117,12 @@ #define ZT_RELAY_MAX_HOPS 4 /** - * Period between keepalives sent to paths if no other traffic has been sent + * Period between keepalives sent to paths if no other traffic has been sent. + * + * The average NAT timeout is 60-120s, but there exist NATs in the wild with timeouts + * as short as 30s. Come in just under 30s and we should be fine. */ -#define ZT_PATH_KEEPALIVE_PERIOD 20000 +#define ZT_PATH_KEEPALIVE_PERIOD 28000 /** * Timeout for path alive-ness (measured from last receive) @@ -135,12 +130,22 @@ #define ZT_PATH_ALIVE_TIMEOUT ((ZT_PATH_KEEPALIVE_PERIOD * 2) + 5000) /** - * Delay between calls to the pulse() method in Peer for each peer + * Number of ports to try for each BFG1024 scan attempt (if enabled). */ -#define ZT_PEER_PULSE_INTERVAL ZT_PATH_KEEPALIVE_PERIOD +#define ZT_NAT_T_BFG1024_PORTS_PER_ATTEMPT 256 /** - * Minimum interval between HELLOs to peers. + * Maximum number of queued endpoints to try per "pulse." + */ +#define ZT_NAT_T_MAX_QUEUED_ATTEMPTS_PER_PULSE 4 + +/** + * Delay between calls to the pulse() method in Peer for each peer + */ +#define ZT_PEER_PULSE_INTERVAL (ZT_PATH_KEEPALIVE_PERIOD / 2) + +/** + * Interval between HELLOs to peers. */ #define ZT_PEER_HELLO_INTERVAL 120000LL @@ -154,7 +159,7 @@ #define ZT_PEER_GLOBAL_TIMEOUT 2592000000LL /** - * Maximum interval between sort/prioritize of paths for a peer + * Interval between sort/prioritize of paths for a peer */ #define ZT_PEER_PRIORITIZE_PATHS_INTERVAL 5000 @@ -182,16 +187,6 @@ */ #define ZT_MAX_BRIDGE_SPAM 32 -/** - * Interval between attempts to make a direct connection if one does not exist - */ -#define ZT_DIRECT_CONNECT_ATTEMPT_INTERVAL 30000 - -/** - * Maximum number of paths per IP scope (e.g. global, link-local) and family (e.g. v4/v6) - */ -#define ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY 4 - /** * WHOIS rate limit (we allow these to be pretty fast) */ diff --git a/node/Containers.hpp b/node/Containers.hpp index 3c0bb50a1..c01c1f913 100644 --- a/node/Containers.hpp +++ b/node/Containers.hpp @@ -26,6 +26,7 @@ #include #include #include +#include namespace ZeroTier { @@ -39,6 +40,7 @@ struct _MapHasher 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 > > { @@ -133,6 +135,12 @@ class Set : public std::set< V,std::less,Utils::Mallocator > { }; +class String : public std::basic_string< char,std::char_traits,Utils::Mallocator > +{ +public: + explicit ZT_INLINE String(const char *const s) { assign(s); } +}; + } // ZeroTier #endif diff --git a/node/Credential.cpp b/node/Credential.cpp index 82fabb296..ab34e3f79 100644 --- a/node/Credential.cpp +++ b/node/Credential.cpp @@ -74,18 +74,18 @@ Credential::VerifyResult Credential::_verify(const RuntimeEnvironment *const RR, Credential::VerifyResult Credential::_verify(const RuntimeEnvironment *const RR,void *tPtr,const CertificateOfMembership &credential) const { // Sanity check network ID. - if ((!credential._signedBy)||(credential._signedBy != Network::controllerFor(credential._networkId))) + if ((!credential.m_signedBy) || (credential.m_signedBy != Network::controllerFor(credential.m_networkId))) return Credential::VERIFY_BAD_SIGNATURE; // If we don't know the peer, get its identity. This shouldn't happen here but should be handled. - const SharedPtr peer(RR->topology->peer(tPtr,credential._signedBy)); + const SharedPtr peer(RR->topology->peer(tPtr,credential.m_signedBy)); if (!peer) return Credential::VERIFY_NEED_IDENTITY; // Now verify the controller's signature. uint64_t buf[ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX / 8]; - const unsigned int bufSize = credential._fillSigningBuf(buf); - return peer->identity().verify(buf,bufSize,credential._signature,credential._signatureLength) ? Credential::VERIFY_OK : Credential::VERIFY_BAD_SIGNATURE; + const unsigned int bufSize = credential.m_fillSigningBuf(buf); + return peer->identity().verify(buf, bufSize, credential.m_signature, credential.m_signatureLength) ? Credential::VERIFY_OK : Credential::VERIFY_BAD_SIGNATURE; } } // namespace ZeroTier diff --git a/node/Defragmenter.hpp b/node/Defragmenter.hpp index 145c5c6e8..0840a6105 100644 --- a/node/Defragmenter.hpp +++ b/node/Defragmenter.hpp @@ -39,16 +39,22 @@ namespace ZeroTier { * * This class is thread-safe and handles locking internally. * + * Templating is so that this class can be placed in a test harness and tested + * without dependencies on external code. The default template parameters are + * the ones used throughout the ZeroTier core. + * * @tparam MF Maximum number of fragments that each message can possess (default: ZT_MAX_PACKET_FRAGMENTS) * @tparam MFP Maximum number of incoming fragments per path (if paths are specified) (default: ZT_MAX_INCOMING_FRAGMENTS_PER_PATH) * @tparam GCS Garbage collection target size for the incoming message queue (default: ZT_MAX_PACKET_FRAGMENTS * 2) * @tparam GCT Garbage collection trigger threshold, usually 2X GCS (default: ZT_MAX_PACKET_FRAGMENTS * 4) + * @tparam P Type for pointer to a path object (default: SharedPtr) */ template< unsigned int MF = ZT_MAX_PACKET_FRAGMENTS, unsigned int MFP = ZT_MAX_INCOMING_FRAGMENTS_PER_PATH, unsigned int GCS = (ZT_MAX_PACKET_FRAGMENTS * 2), - unsigned int GCT = (ZT_MAX_PACKET_FRAGMENTS * 4)> + unsigned int GCT = (ZT_MAX_PACKET_FRAGMENTS * 4), + typename P = SharedPtr > class Defragmenter { public: @@ -146,17 +152,17 @@ public: const unsigned int fragmentNo, const unsigned int totalFragmentsExpected, const int64_t now, - const SharedPtr &via) + const P &via) { // Sanity checks for malformed fragments or invalid input parameters. if ((fragmentNo >= totalFragmentsExpected)||(totalFragmentsExpected > MF)||(totalFragmentsExpected == 0)) return ERR_INVALID_FRAGMENT; // We hold the read lock on _messages unless we need to add a new entry or do GC. - RWMutex::RMaybeWLock ml(_messages_l); + RWMutex::RMaybeWLock ml(m_messages_l); // Check message hash table size and perform GC if necessary. - if (_messages.size() >= GCT) { + if (m_messages.size() >= GCT) { try { // Scan messages with read lock still locked first and make a sorted list of // message entries by last modified time. Then lock for writing and delete @@ -165,27 +171,27 @@ public: // lock is held since many threads can hold the read lock but all threads must // wait if someone holds the write lock. std::vector > messagesByLastUsedTime; - messagesByLastUsedTime.reserve(_messages.size()); + messagesByLastUsedTime.reserve(m_messages.size()); - for(typename Map< uint64_t,_E >::const_iterator i(_messages.begin());i!=_messages.end();++i) + for(typename Map< uint64_t,p_E >::const_iterator i(m_messages.begin());i != m_messages.end();++i) messagesByLastUsedTime.push_back(std::pair(i->second.lastUsed,i->first)); std::sort(messagesByLastUsedTime.begin(),messagesByLastUsedTime.end()); ml.writing(); // acquire write lock on _messages for (unsigned long x = 0,y = (messagesByLastUsedTime.size() - GCS); x <= y; ++x) - _messages.erase(messagesByLastUsedTime[x].second); + m_messages.erase(messagesByLastUsedTime[x].second); } catch (...) { return ERR_OUT_OF_MEMORY; } } // Get or create message fragment. - _E *e = _messages.get(messageId); + p_E *e = m_messages.get(messageId); if (!e) { ml.writing(); // acquire write lock on _messages if not already try { - e = &(_messages[messageId]); - } catch (...) { + e = &(m_messages[messageId]); + } catch ( ... ) { return ERR_OUT_OF_MEMORY; } e->id = messageId; @@ -275,8 +281,8 @@ public: */ ZT_INLINE void clear() { - RWMutex::Lock ml(_messages_l); - _messages.clear(); + RWMutex::Lock ml(m_messages_l); + m_messages.clear(); } /** @@ -284,21 +290,21 @@ public: */ ZT_INLINE unsigned int cacheSize() noexcept { - RWMutex::RLock ml(_messages_l); - return _messages.size(); + RWMutex::RLock ml(m_messages_l); + return m_messages.size(); } private: - // _E is an entry in the message queue. - struct _E + // p_E is an entry in the message queue. + struct p_E { - ZT_INLINE _E() noexcept : + ZT_INLINE p_E() noexcept : id(0), lastUsed(0), totalFragmentsExpected(0), fragmentsReceived(0) {} - ZT_INLINE _E(const _E &e) noexcept : + ZT_INLINE p_E(const p_E &e) noexcept : id(e.id), lastUsed(e.lastUsed), totalFragmentsExpected(e.totalFragmentsExpected), @@ -307,7 +313,7 @@ private: message(e.message), lock() {} - ZT_INLINE ~_E() + ZT_INLINE ~p_E() { if (via) { via->_inboundFragmentedMessages_l.lock(); @@ -316,7 +322,7 @@ private: } } - ZT_INLINE _E &operator=(const _E &e) + ZT_INLINE p_E &operator=(const p_E &e) { if (this != &e) { id = e.id; @@ -333,13 +339,13 @@ private: int64_t lastUsed; unsigned int totalFragmentsExpected; unsigned int fragmentsReceived; - SharedPtr via; + P via; FCV< Buf::Slice,MF > message; Mutex lock; }; - Map< uint64_t,Defragmenter::_E > _messages; - RWMutex _messages_l; + Map< uint64_t,Defragmenter::p_E > m_messages; + RWMutex m_messages_l; }; } // namespace ZeroTier diff --git a/node/Dictionary.cpp b/node/Dictionary.cpp index 117dab2ab..1f87e731b 100644 --- a/node/Dictionary.cpp +++ b/node/Dictionary.cpp @@ -25,14 +25,14 @@ Dictionary::~Dictionary() std::vector &Dictionary::operator[](const char *k) { - return _t[_toKey(k)]; + return m_entries[s_toKey(k)]; } const std::vector &Dictionary::operator[](const char *k) const { static const std::vector emptyEntry; - Map< uint64_t,std::vector >::const_iterator e(_t.find(_toKey(k))); - return (e == _t.end()) ? emptyEntry : e->second; + Map< uint64_t,std::vector >::const_iterator e(m_entries.find(s_toKey(k))); + return (e == m_entries.end()) ? emptyEntry : e->second; } void Dictionary::add(const char *k,bool v) @@ -147,7 +147,7 @@ void Dictionary::getS(const char *k,char *v,unsigned int cap) const void Dictionary::clear() { - _t.clear(); + m_entries.clear(); } void Dictionary::encode(std::vector &out) const @@ -156,7 +156,7 @@ void Dictionary::encode(std::vector &out) const out.clear(); - for(Map< uint64_t,std::vector >::const_iterator ti(_t.begin());ti!=_t.end();++ti) { + for(Map< uint64_t,std::vector >::const_iterator ti(m_entries.begin());ti != m_entries.end();++ti) { str[0] = ti->first; const char *k = (const char *)str; for(;;) { @@ -247,7 +247,7 @@ bool Dictionary::decode(const void *data,unsigned int len) if ((c < 33)||(c > 126)||(c == 92)) { return false; } else if (c == 61) { - v = &_t[k]; + v = &m_entries[k]; } else { reinterpret_cast(&k)[ki & 7U] ^= c; } diff --git a/node/Dictionary.hpp b/node/Dictionary.hpp index 6aa761663..12715d3a1 100644 --- a/node/Dictionary.hpp +++ b/node/Dictionary.hpp @@ -137,12 +137,12 @@ public: /** * @return Number of entries */ - ZT_INLINE unsigned int size() const noexcept { return _t.size(); } + ZT_INLINE unsigned int size() const noexcept { return m_entries.size(); } /** * @return True if dictionary is not empty */ - ZT_INLINE bool empty() const noexcept { return _t.empty(); } + ZT_INLINE bool empty() const noexcept { return m_entries.empty(); } /** * Encode to a string in the supplied vector @@ -169,7 +169,7 @@ public: private: // This just packs up to 8 character bytes into a 64-bit word. There is no need // for this to be portable in terms of endian-ness. It's just for fast key lookup. - static ZT_INLINE uint64_t _toKey(const char *k) + static ZT_INLINE uint64_t s_toKey(const char *k) { uint64_t key = 0; for(int i=0;i<8;++i) { @@ -179,7 +179,7 @@ private: return key; } - Map< uint64_t,Vector > _t; + Map< uint64_t,Vector > m_entries; }; } // namespace ZeroTier diff --git a/node/Endpoint.hpp b/node/Endpoint.hpp index 101b82187..0708ed10e 100644 --- a/node/Endpoint.hpp +++ b/node/Endpoint.hpp @@ -57,21 +57,29 @@ public: * Protocol identifier bits. * * Endpoint types can support more than one of these, though it depends on the type. + * + * Most of these are reserved for possible future use. */ enum Protocol { - PROTO_DGRAM = 0x0001, - PROTO_TCP = 0x0002, - PROTO_HTTP = 0x0004, - PROTO_HTTPS = 0x0008, - PROTO_WS = 0x0010, - PROTO_WEBRTC = 0x0020 + PROTO_DGRAM = 0x0001, // UDP for IP or naked Ethernet frames + PROTO_STREAM = 0x0002, // TCP + PROTO_HTTP2 = 0x0004, // HTTP2 bidirectional protocol + PROTO_HTTPS2 = 0x0008, // HTTP2 over SSL/TLS + PROTO_WS = 0x0010, // Web sockets + PROTO_WEBRTC = 0x0020, // WebRTC data channels + PROTO_WIREGUARD = 0x0040 // Wireguard as low-level transport }; ZT_INLINE Endpoint() noexcept { memoryZero(this); } // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init) explicit Endpoint(const InetAddress &sa,Protocol proto = PROTO_DGRAM) noexcept; + /** + * @return True if this is an IPv4 or IPv6 IP address + */ + ZT_INLINE bool isInetAddr() const noexcept { return ((_t == TYPE_INETADDR_V4)||(_t == TYPE_INETADDR_V6)); } + /** * @return InetAddress or NIL if not of this type */ @@ -113,7 +121,7 @@ public: private: Type _t; Protocol _proto; - int _l[3]; // X,Y,Z location in kilometers from the nearest gravitational center of mass + int _l[3]; // X,Y,Z location in kilometers from the nearest gravitational center of mass (e.g. Earth) union { sockaddr_storage sa; ZT_Fingerprint zt; diff --git a/node/Expect.hpp b/node/Expect.hpp index 2435fe54d..6a8d00403 100644 --- a/node/Expect.hpp +++ b/node/Expect.hpp @@ -20,22 +20,14 @@ /** * Number of buckets to use to maintain a list of expected replies. * - * More buckets means less chance of two packets tagging the same - * bucket. This doesn't actually hurt anything since this class - * behaves like a bloom filter: you can have false positives but - * not false negatives. - * - * OKs are also cryptographically authenticated, so this is not a - * huge problem, but this helps harden the system against replay - * attacks for e.g. denial of service. + * Making this a power of two improves efficiency a little by allowing bit shift division. */ -#define ZT_EXPECT_BUCKETS 131072 +#define ZT_EXPECT_BUCKETS 32768 /** * 1/2 the TTL for expected replies in milliseconds * - * Making this a power of two improves efficiency a little by allowing bit - * shift division. + * Making this a power of two improves efficiency a little by allowing bit shift division. */ #define ZT_EXPECT_TTL 4096LL @@ -47,40 +39,37 @@ namespace ZeroTier { class Expect { public: - ZT_INLINE Expect() : _salt(Utils::getSecureRandomU64()) {} // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init) + ZT_INLINE Expect() {} // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init,hicpp-use-equals-default,modernize-use-equals-default) /** - * Called by other code when something is sending a packet that may receive an OK response + * Called by other code when something is sending a packet that could potentially receive an OK response * * @param packetId Packet ID of packet being sent (be sure it's post-armor()) * @param now Current time */ ZT_INLINE void sending(const uint64_t packetId,const int64_t now) noexcept { - _packetIdSent[Utils::hash64(packetId ^ _salt) % ZT_EXPECT_BUCKETS].store((int32_t)(now / ZT_EXPECT_TTL)); + _packetIdSent[Utils::hash64(packetId ^ Utils::s_mapNonce) % ZT_EXPECT_BUCKETS].store((uint32_t)(now / ZT_EXPECT_TTL)); } /** - * Check whether an OK is expected for this packet + * Check if an OK is expected and if so reset the corresponding bucket. * - * @param inRePacketId - * @param now - * @return + * This means this call mutates the state. If it returns true, it will + * subsequently return false. This is for replay protection for OKs. + * + * @param inRePacketId In-re packet ID we're expecting + * @param now Current time + * @return True if we're expecting a reply (and a reset occurred) */ - ZT_INLINE bool expecting(const uint64_t inRePacketId,const int64_t now) const noexcept + ZT_INLINE bool expecting(const uint64_t inRePacketId,const int64_t now) noexcept { - return (((now / ZT_EXPECT_TTL) - (int64_t)_packetIdSent[Utils::hash64(inRePacketId ^ _salt) % ZT_EXPECT_BUCKETS].load()) <= 1); + return (((now / ZT_EXPECT_TTL) - (int64_t)_packetIdSent[(unsigned long)Utils::hash64(inRePacketId ^ Utils::s_mapNonce) % ZT_EXPECT_BUCKETS].exchange(0)) <= 1); } private: - // This is a static per-runtime salt that's XORed and mixed with the packet ID - // to make it difficult for a third party to predict expected-reply buckets. - // Such prediction would not be catastrophic but it's easy and good to harden - // against it. - const uint64_t _salt; - - // Each bucket contains a timestamp in units of the expect duration. - std::atomic _packetIdSent[ZT_EXPECT_BUCKETS]; + // Each bucket contains a timestamp in units of the max expect duration. + std::atomic _packetIdSent[ZT_EXPECT_BUCKETS]; }; } // namespace ZeroTier diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp index 6c6701232..80cc7a6f9 100644 --- a/node/InetAddress.cpp +++ b/node/InetAddress.cpp @@ -29,7 +29,7 @@ InetAddress::IpScope InetAddress::ipScope() const noexcept switch(_data.ss_family) { case AF_INET: { - const uint32_t ip = Utils::ntoh((uint32_t)reinterpret_cast(this)->sin_addr.s_addr); + const uint32_t ip = Utils::ntoh((uint32_t)reinterpret_cast(this)->sin_addr.s_addr); switch(ip >> 24U) { case 0x00: return IP_SCOPE_NONE; // 0.0.0.0/8 (reserved, never used) case 0x06: return IP_SCOPE_PSEUDOPRIVATE; // 6.0.0.0/8 (US Army) @@ -68,7 +68,7 @@ InetAddress::IpScope InetAddress::ipScope() const noexcept } case AF_INET6: { - const unsigned char *ip = reinterpret_cast(reinterpret_cast(this)->sin6_addr.s6_addr); // NOLINT(hicpp-use-auto,modernize-use-auto) + const unsigned char *ip = reinterpret_cast(reinterpret_cast(this)->sin6_addr.s6_addr); // NOLINT(hicpp-use-auto,modernize-use-auto) if ((ip[0] & 0xf0U) == 0xf0) { if (ip[0] == 0xff) return IP_SCOPE_MULTICAST; // ff00::/8 if ((ip[0] == 0xfe)&&((ip[1] & 0xc0U) == 0x80)) { @@ -100,12 +100,12 @@ void InetAddress::set(const void *ipBytes,unsigned int ipLen,unsigned int port) uint32_t ipb[1]; Utils::copy<4>(ipb,ipBytes); _data.ss_family = AF_INET; - reinterpret_cast(this)->sin_addr.s_addr = ipb[0]; - reinterpret_cast(this)->sin_port = Utils::hton((uint16_t)port); + 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; - Utils::copy<16>(reinterpret_cast(this)->sin6_addr.s6_addr,ipBytes); - reinterpret_cast(this)->sin6_port = Utils::hton((uint16_t)port); + Utils::copy<16>(reinterpret_cast(this)->sin6_addr.s6_addr,ipBytes); + reinterpret_cast(this)->sin6_port = Utils::hton((uint16_t)port); } } @@ -113,14 +113,14 @@ bool InetAddress::isDefaultRoute() const noexcept { switch(_data.ss_family) { case AF_INET: - return ( (reinterpret_cast(this)->sin_addr.s_addr == 0) && (reinterpret_cast(this)->sin_port == 0) ); + return ( (reinterpret_cast(this)->sin_addr.s_addr == 0) && (reinterpret_cast(this)->sin_port == 0) ); case AF_INET6: - const uint8_t *ipb = reinterpret_cast(reinterpret_cast(this)->sin6_addr.s6_addr); // NOLINT(hicpp-use-auto,modernize-use-auto) + const uint8_t *ipb = reinterpret_cast(reinterpret_cast(this)->sin6_addr.s6_addr); // NOLINT(hicpp-use-auto,modernize-use-auto) for(int i=0;i<16;++i) { if (ipb[i]) return false; } - return (reinterpret_cast(this)->sin6_port == 0); + return (reinterpret_cast(this)->sin6_port == 0); } return false; } @@ -142,17 +142,17 @@ char *InetAddress::toIpString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const no switch(_data.ss_family) { case AF_INET: { #ifdef _WIN32 - inet_ntop(AF_INET, (void*)&reinterpret_cast(this)->sin_addr.s_addr, buf, INET_ADDRSTRLEN); + inet_ntop(AF_INET, (void*)&reinterpret_cast(this)->sin_addr.s_addr, buf, INET_ADDRSTRLEN); #else - inet_ntop(AF_INET, &reinterpret_cast(this)->sin_addr.s_addr, buf, INET_ADDRSTRLEN); + inet_ntop(AF_INET, &reinterpret_cast(this)->sin_addr.s_addr, buf, INET_ADDRSTRLEN); #endif } break; case AF_INET6: { #ifdef _WIN32 - inet_ntop(AF_INET6, (void*)reinterpret_cast(this)->sin6_addr.s6_addr, buf, INET6_ADDRSTRLEN); + inet_ntop(AF_INET6, (void*)reinterpret_cast(this)->sin6_addr.s6_addr, buf, INET6_ADDRSTRLEN); #else - inet_ntop(AF_INET6, reinterpret_cast(this)->sin6_addr.s6_addr, buf, INET6_ADDRSTRLEN); + inet_ntop(AF_INET6, reinterpret_cast(this)->sin6_addr.s6_addr, buf, INET6_ADDRSTRLEN); #endif } break; } @@ -180,13 +180,13 @@ bool InetAddress::fromString(const char *ipSlashPort) noexcept } if (strchr(buf,':')) { - struct sockaddr_in6 *const in6 = reinterpret_cast(this); // NOLINT(hicpp-use-auto,modernize-use-auto) + sockaddr_in6 *const in6 = reinterpret_cast(this); // NOLINT(hicpp-use-auto,modernize-use-auto) inet_pton(AF_INET6, buf, &in6->sin6_addr.s6_addr); in6->sin6_family = AF_INET6; in6->sin6_port = Utils::hton((uint16_t)port); return true; } else if (strchr(buf,'.')) { - struct sockaddr_in *const in = reinterpret_cast(this); // NOLINT(hicpp-use-auto,modernize-use-auto) + sockaddr_in *const in = reinterpret_cast(this); // NOLINT(hicpp-use-auto,modernize-use-auto) inet_pton(AF_INET, buf, &in->sin_addr.s_addr); in->sin_family = AF_INET; in->sin_port = Utils::hton((uint16_t)port); @@ -201,7 +201,7 @@ InetAddress InetAddress::netmask() const noexcept InetAddress r(*this); switch(r._data.ss_family) { case AF_INET: - reinterpret_cast(&r)->sin_addr.s_addr = Utils::hton((uint32_t)(0xffffffffU << (32 - netmaskBits()))); + reinterpret_cast(&r)->sin_addr.s_addr = Utils::hton((uint32_t)(0xffffffffU << (32 - netmaskBits()))); break; case AF_INET6: { uint64_t nm[2]; @@ -213,7 +213,7 @@ InetAddress InetAddress::netmask() const noexcept nm[0] = 0; nm[1] = 0; } - Utils::copy<16>(reinterpret_cast(&r)->sin6_addr.s6_addr,nm); + Utils::copy<16>(reinterpret_cast(&r)->sin6_addr.s6_addr,nm); } break; } return r; @@ -223,7 +223,7 @@ InetAddress InetAddress::broadcast() const noexcept { if (_data.ss_family == AF_INET) { InetAddress r(*this); - reinterpret_cast(&r)->sin_addr.s_addr |= Utils::hton((uint32_t)(0xffffffffU >> netmaskBits())); + reinterpret_cast(&r)->sin_addr.s_addr |= Utils::hton((uint32_t)(0xffffffffU >> netmaskBits())); return r; } return InetAddress(); @@ -234,15 +234,15 @@ InetAddress InetAddress::network() const noexcept InetAddress r(*this); switch(r._data.ss_family) { case AF_INET: - reinterpret_cast(&r)->sin_addr.s_addr &= Utils::hton((uint32_t)(0xffffffffU << (32 - netmaskBits()))); + reinterpret_cast(&r)->sin_addr.s_addr &= Utils::hton((uint32_t)(0xffffffffU << (32 - netmaskBits()))); break; case AF_INET6: { uint64_t nm[2]; const unsigned int bits = netmaskBits(); - Utils::copy<16>(nm,reinterpret_cast(&r)->sin6_addr.s6_addr); + Utils::copy<16>(nm,reinterpret_cast(&r)->sin6_addr.s6_addr); nm[0] &= Utils::hton((uint64_t)((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits)))); nm[1] &= Utils::hton((uint64_t)((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits)))); - Utils::copy<16>(reinterpret_cast(&r)->sin6_addr.s6_addr,nm); + Utils::copy<16>(reinterpret_cast(&r)->sin6_addr.s6_addr,nm); } break; } return r; @@ -255,10 +255,10 @@ bool InetAddress::isEqualPrefix(const InetAddress &addr) const noexcept case AF_INET6: { const InetAddress mask(netmask()); InetAddress addr_mask(addr.netmask()); - const uint8_t *n = reinterpret_cast(reinterpret_cast(&addr_mask)->sin6_addr.s6_addr); // NOLINT(hicpp-use-auto,modernize-use-auto) - const uint8_t *m = reinterpret_cast(reinterpret_cast(&mask)->sin6_addr.s6_addr); // NOLINT(hicpp-use-auto,modernize-use-auto) - const uint8_t *a = reinterpret_cast(reinterpret_cast(&addr)->sin6_addr.s6_addr); // NOLINT(hicpp-use-auto,modernize-use-auto) - const uint8_t *b = reinterpret_cast(reinterpret_cast(this)->sin6_addr.s6_addr); // NOLINT(hicpp-use-auto,modernize-use-auto) + const uint8_t *n = reinterpret_cast(reinterpret_cast(&addr_mask)->sin6_addr.s6_addr); // NOLINT(hicpp-use-auto,modernize-use-auto) + const uint8_t *m = reinterpret_cast(reinterpret_cast(&mask)->sin6_addr.s6_addr); // NOLINT(hicpp-use-auto,modernize-use-auto) + const uint8_t *a = reinterpret_cast(reinterpret_cast(&addr)->sin6_addr.s6_addr); // NOLINT(hicpp-use-auto,modernize-use-auto) + const uint8_t *b = reinterpret_cast(reinterpret_cast(this)->sin6_addr.s6_addr); // NOLINT(hicpp-use-auto,modernize-use-auto) for(unsigned int i=0;i<16;++i) { if ((a[i] & m[i]) != (b[i] & n[i])) return false; @@ -279,15 +279,15 @@ bool InetAddress::containsAddress(const InetAddress &addr) const noexcept if (bits == 0) return true; return ( - (Utils::ntoh((uint32_t)reinterpret_cast(&addr)->sin_addr.s_addr) >> (32 - bits)) == - (Utils::ntoh((uint32_t)reinterpret_cast(this)->sin_addr.s_addr) >> (32 - bits)) + (Utils::ntoh((uint32_t)reinterpret_cast(&addr)->sin_addr.s_addr) >> (32 - bits)) == + (Utils::ntoh((uint32_t)reinterpret_cast(this)->sin_addr.s_addr) >> (32 - bits)) ); } case AF_INET6: { const InetAddress mask(netmask()); - const uint8_t *m = reinterpret_cast(reinterpret_cast(&mask)->sin6_addr.s6_addr); // NOLINT(hicpp-use-auto,modernize-use-auto) - const uint8_t *a = reinterpret_cast(reinterpret_cast(&addr)->sin6_addr.s6_addr); // NOLINT(hicpp-use-auto,modernize-use-auto) - const uint8_t *b = reinterpret_cast(reinterpret_cast(this)->sin6_addr.s6_addr); // NOLINT(hicpp-use-auto,modernize-use-auto) + const uint8_t *m = reinterpret_cast(reinterpret_cast(&mask)->sin6_addr.s6_addr); // NOLINT(hicpp-use-auto,modernize-use-auto) + const uint8_t *a = reinterpret_cast(reinterpret_cast(&addr)->sin6_addr.s6_addr); // NOLINT(hicpp-use-auto,modernize-use-auto) + const uint8_t *b = reinterpret_cast(reinterpret_cast(this)->sin6_addr.s6_addr); // NOLINT(hicpp-use-auto,modernize-use-auto) for(unsigned int i=0;i<16;++i) { if ((a[i] & m[i]) != b[i]) return false; @@ -308,19 +308,19 @@ void InetAddress::forTrace(ZT_TraceEventPathAddress &ta) const noexcept break; case AF_INET: ta.type = ZT_TRACE_EVENT_PATH_TYPE_INETADDR_V4; - tmp = (uint32_t)(reinterpret_cast(this)->sin_addr.s_addr); + tmp = (uint32_t)(reinterpret_cast(this)->sin_addr.s_addr); ta.address[0] = reinterpret_cast(&tmp)[0]; ta.address[1] = reinterpret_cast(&tmp)[1]; ta.address[2] = reinterpret_cast(&tmp)[2]; ta.address[3] = reinterpret_cast(&tmp)[3]; Utils::zero(ta.address + 4); - ta.port = reinterpret_cast(this)->sin_port; + ta.port = reinterpret_cast(this)->sin_port; break; case AF_INET6: ta.type = ZT_TRACE_EVENT_PATH_TYPE_INETADDR_V6; - Utils::copy<16>(ta.address,reinterpret_cast(this)->sin6_addr.s6_addr); + Utils::copy<16>(ta.address,reinterpret_cast(this)->sin6_addr.s6_addr); Utils::zero(ta.address + 16); - ta.port = reinterpret_cast(this)->sin6_port; + ta.port = reinterpret_cast(this)->sin6_port; break; } } @@ -334,7 +334,7 @@ bool InetAddress::isNetwork() const noexcept return false; if (bits >= 32) return false; - uint32_t ip = Utils::ntoh((uint32_t)reinterpret_cast(this)->sin_addr.s_addr); + uint32_t ip = Utils::ntoh((uint32_t)reinterpret_cast(this)->sin_addr.s_addr); return ((ip & (0xffffffffU >> bits)) == 0); } case AF_INET6: { @@ -343,7 +343,7 @@ bool InetAddress::isNetwork() const noexcept return false; if (bits >= 128) return false; - const unsigned char *ip = reinterpret_cast(reinterpret_cast(this)->sin6_addr.s6_addr); // NOLINT(hicpp-use-auto,modernize-use-auto) + const unsigned char *ip = reinterpret_cast(reinterpret_cast(this)->sin6_addr.s6_addr); // NOLINT(hicpp-use-auto,modernize-use-auto) unsigned int p = bits / 8; if ((ip[p++] & (0xffU >> (bits % 8))) != 0) return false; @@ -425,14 +425,14 @@ bool InetAddress::operator==(const InetAddress &a) const noexcept switch(_data.ss_family) { case AF_INET: return ( - (reinterpret_cast(this)->sin_port == reinterpret_cast(&a)->sin_port)&& - (reinterpret_cast(this)->sin_addr.s_addr == reinterpret_cast(&a)->sin_addr.s_addr)); + (reinterpret_cast(this)->sin_port == reinterpret_cast(&a)->sin_port)&& + (reinterpret_cast(this)->sin_addr.s_addr == reinterpret_cast(&a)->sin_addr.s_addr)); case AF_INET6: return ( - (reinterpret_cast(this)->sin6_port == reinterpret_cast(&a)->sin6_port)&& - (reinterpret_cast(this)->sin6_flowinfo == reinterpret_cast(&a)->sin6_flowinfo)&& - (memcmp(reinterpret_cast(this)->sin6_addr.s6_addr,reinterpret_cast(&a)->sin6_addr.s6_addr,16) == 0)&& - (reinterpret_cast(this)->sin6_scope_id == reinterpret_cast(&a)->sin6_scope_id)); + (reinterpret_cast(this)->sin6_port == reinterpret_cast(&a)->sin6_port)&& + (reinterpret_cast(this)->sin6_flowinfo == reinterpret_cast(&a)->sin6_flowinfo)&& + (memcmp(reinterpret_cast(this)->sin6_addr.s6_addr,reinterpret_cast(&a)->sin6_addr.s6_addr,16) == 0)&& + (reinterpret_cast(this)->sin6_scope_id == reinterpret_cast(&a)->sin6_scope_id)); default: return (memcmp(this,&a,sizeof(InetAddress)) == 0); } @@ -447,24 +447,24 @@ bool InetAddress::operator<(const InetAddress &a) const noexcept else if (_data.ss_family == a._data.ss_family) { switch(_data.ss_family) { case AF_INET: - if (reinterpret_cast(this)->sin_port < reinterpret_cast(&a)->sin_port) + if (reinterpret_cast(this)->sin_port < reinterpret_cast(&a)->sin_port) return true; - else if (reinterpret_cast(this)->sin_port == reinterpret_cast(&a)->sin_port) { - if (reinterpret_cast(this)->sin_addr.s_addr < reinterpret_cast(&a)->sin_addr.s_addr) + else if (reinterpret_cast(this)->sin_port == reinterpret_cast(&a)->sin_port) { + if (reinterpret_cast(this)->sin_addr.s_addr < reinterpret_cast(&a)->sin_addr.s_addr) return true; } break; case AF_INET6: - if (reinterpret_cast(this)->sin6_port < reinterpret_cast(&a)->sin6_port) + if (reinterpret_cast(this)->sin6_port < reinterpret_cast(&a)->sin6_port) return true; - else if (reinterpret_cast(this)->sin6_port == reinterpret_cast(&a)->sin6_port) { - if (reinterpret_cast(this)->sin6_flowinfo < reinterpret_cast(&a)->sin6_flowinfo) + else if (reinterpret_cast(this)->sin6_port == reinterpret_cast(&a)->sin6_port) { + if (reinterpret_cast(this)->sin6_flowinfo < reinterpret_cast(&a)->sin6_flowinfo) return true; - else if (reinterpret_cast(this)->sin6_flowinfo == reinterpret_cast(&a)->sin6_flowinfo) { - if (memcmp(reinterpret_cast(this)->sin6_addr.s6_addr,reinterpret_cast(&a)->sin6_addr.s6_addr,16) < 0) + else if (reinterpret_cast(this)->sin6_flowinfo == reinterpret_cast(&a)->sin6_flowinfo) { + if (memcmp(reinterpret_cast(this)->sin6_addr.s6_addr,reinterpret_cast(&a)->sin6_addr.s6_addr,16) < 0) return true; - else if (memcmp(reinterpret_cast(this)->sin6_addr.s6_addr,reinterpret_cast(&a)->sin6_addr.s6_addr,16) == 0) { - if (reinterpret_cast(this)->sin6_scope_id < reinterpret_cast(&a)->sin6_scope_id) + else if (memcmp(reinterpret_cast(this)->sin6_addr.s6_addr,reinterpret_cast(&a)->sin6_addr.s6_addr,16) == 0) { + if (reinterpret_cast(this)->sin6_scope_id < reinterpret_cast(&a)->sin6_scope_id) return true; } } diff --git a/node/InetAddress.hpp b/node/InetAddress.hpp index cf25f62e9..0ae821029 100644 --- a/node/InetAddress.hpp +++ b/node/InetAddress.hpp @@ -14,13 +14,10 @@ #ifndef ZT_INETADDRESS_HPP #define ZT_INETADDRESS_HPP -#include -#include -#include - #include "Constants.hpp" #include "Utils.hpp" #include "MAC.hpp" +#include "Containers.hpp" #include "TriviallyCopyable.hpp" namespace ZeroTier { @@ -194,10 +191,10 @@ public: { switch(_data.ss_family) { case AF_INET: - reinterpret_cast(this)->sin_port = Utils::hton((uint16_t)port); + reinterpret_cast(this)->sin_port = Utils::hton((uint16_t)port); break; case AF_INET6: - reinterpret_cast(this)->sin6_port = Utils::hton((uint16_t)port); + reinterpret_cast(this)->sin6_port = Utils::hton((uint16_t)port); break; } } @@ -211,11 +208,13 @@ public: * @return ASCII IP/port format representation */ char *toString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept; + ZT_INLINE String toString() const { char buf[ZT_INETADDRESS_STRING_SIZE_MAX]; toString(buf); return String(buf); } /** * @return IP portion only, in ASCII string format */ char *toIpString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept; + ZT_INLINE String toIpString() const { char buf[ZT_INETADDRESS_STRING_SIZE_MAX]; toIpString(buf); return String(buf); } /** * @param ipSlashPort IP/port (port is optional, will be 0 if not included) @@ -229,8 +228,8 @@ public: ZT_INLINE unsigned int port() const noexcept { switch(_data.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)); + 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; } } @@ -325,8 +324,8 @@ public: ZT_INLINE const void *rawIpData() const noexcept { switch(_data.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); + 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; } } @@ -339,12 +338,12 @@ public: InetAddress r; switch(_data.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; + reinterpret_cast(&r)->sin_family = AF_INET; + reinterpret_cast(&r)->sin_addr.s_addr = reinterpret_cast(this)->sin_addr.s_addr; break; case AF_INET6: - reinterpret_cast(&r)->sin6_family = AF_INET; - Utils::copy<16>(reinterpret_cast(&r)->sin6_addr.s6_addr,reinterpret_cast(this)->sin6_addr.s6_addr); + reinterpret_cast(&r)->sin6_family = AF_INET; + Utils::copy<16>(reinterpret_cast(&r)->sin6_addr.s6_addr,reinterpret_cast(this)->sin6_addr.s6_addr); break; } return r; @@ -361,9 +360,9 @@ public: const uint8_t f = _data.ss_family; if (f == a._data.ss_family) { if (f == AF_INET) - return (reinterpret_cast(this)->sin_addr.s_addr == reinterpret_cast(&a)->sin_addr.s_addr); + return (reinterpret_cast(this)->sin_addr.s_addr == reinterpret_cast(&a)->sin_addr.s_addr); if (f == AF_INET6) - return (memcmp(reinterpret_cast(this)->sin6_addr.s6_addr,reinterpret_cast(&a)->sin6_addr.s6_addr,16) == 0); + return (memcmp(reinterpret_cast(this)->sin6_addr.s6_addr,reinterpret_cast(&a)->sin6_addr.s6_addr,16) == 0); return (memcmp(this,&a,sizeof(InetAddress)) == 0); } return false; @@ -382,9 +381,9 @@ public: const uint8_t f = _data.ss_family; if (f == a._data.ss_family) { if (f == AF_INET) - return (reinterpret_cast(this)->sin_addr.s_addr == reinterpret_cast(&a)->sin_addr.s_addr); + return (reinterpret_cast(this)->sin_addr.s_addr == reinterpret_cast(&a)->sin_addr.s_addr); if (f == AF_INET6) - return (memcmp(reinterpret_cast(this)->sin6_addr.s6_addr,reinterpret_cast(&a)->sin6_addr.s6_addr,8) == 0); + return (memcmp(reinterpret_cast(this)->sin6_addr.s6_addr,reinterpret_cast(&a)->sin6_addr.s6_addr,8) == 0); return (memcmp(this,&a,sizeof(InetAddress)) == 0); } return false; @@ -393,12 +392,12 @@ 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); + 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) { 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(&_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 ); } return Utils::fnv1a32(&_data,sizeof(_data)); @@ -502,14 +501,14 @@ static_assert(sizeof(sockaddr_in) <= sizeof(InetAddress),"InetAddress sizing inc static_assert(sizeof(sockaddr_in6) <= sizeof(InetAddress),"InetAddress sizing incorrect"); static_assert(sizeof(sockaddr) <= sizeof(InetAddress),"InetAddress sizing incorrect"); -static ZT_INLINE InetAddress *asInetAddress(sockaddr_in *p) noexcept { return reinterpret_cast(p); } -static ZT_INLINE InetAddress *asInetAddress(sockaddr_in6 *p) noexcept { return reinterpret_cast(p); } -static ZT_INLINE InetAddress *asInetAddress(sockaddr *p) noexcept { return reinterpret_cast(p); } -static ZT_INLINE InetAddress *asInetAddress(sockaddr_storage *p) noexcept { return reinterpret_cast(p); } -static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_in *p) noexcept { return reinterpret_cast(p); } -static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_in6 *p) noexcept { return reinterpret_cast(p); } -static ZT_INLINE const InetAddress *asInetAddress(const sockaddr *p) noexcept { return reinterpret_cast(p); } -static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_storage *p) noexcept { return reinterpret_cast(p); } +static ZT_INLINE InetAddress *asInetAddress(sockaddr_in *const p) noexcept { return reinterpret_cast(p); } +static ZT_INLINE InetAddress *asInetAddress(sockaddr_in6 *const p) noexcept { return reinterpret_cast(p); } +static ZT_INLINE InetAddress *asInetAddress(sockaddr *const p) noexcept { return reinterpret_cast(p); } +static ZT_INLINE InetAddress *asInetAddress(sockaddr_storage *const p) noexcept { return reinterpret_cast(p); } +static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_in *const p) noexcept { return reinterpret_cast(p); } +static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_in6 *const p) noexcept { return reinterpret_cast(p); } +static ZT_INLINE const InetAddress *asInetAddress(const sockaddr *const p) noexcept { return reinterpret_cast(p); } +static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_storage *const p) noexcept { return reinterpret_cast(p); } static ZT_INLINE InetAddress &asInetAddress(sockaddr_in &p) noexcept { return *reinterpret_cast(&p); } static ZT_INLINE InetAddress &asInetAddress(sockaddr_in6 &p) noexcept { return *reinterpret_cast(&p); } static ZT_INLINE InetAddress &asInetAddress(sockaddr &p) noexcept { return *reinterpret_cast(&p); } diff --git a/node/MAC.hpp b/node/MAC.hpp index 3f411fcc3..0536ec352 100644 --- a/node/MAC.hpp +++ b/node/MAC.hpp @@ -142,7 +142,7 @@ public: */ ZT_INLINE unsigned int size() const noexcept { return 6; } - ZT_INLINE unsigned long hashCode() const noexcept { return (unsigned long)_m; } + ZT_INLINE unsigned long hashCode() const noexcept { return (unsigned long)Utils::hash64(_m); } ZT_INLINE char *toString(char buf[18]) const noexcept { diff --git a/node/Node.cpp b/node/Node.cpp index 04eb320cc..8da94f3ce 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -75,18 +75,18 @@ struct _sortPeerPtrsByAddress } // anonymous namespace Node::Node(void *uPtr,void *tPtr,const struct ZT_Node_Callbacks *callbacks,int64_t now) : - _RR(this), - RR(&_RR), - _objects(nullptr), - _cb(*callbacks), - _uPtr(uPtr), - _networks(), - _lastPeerPulse(0), - _lastHousekeepingRun(0), - _lastNetworkHousekeepingRun(0), - _now(now), - _natMustDie(true), - _online(false) + m_RR(this), + RR(&m_RR), + m_objects(nullptr), + m_cb(*callbacks), + m_uPtr(uPtr), + m_networks(), + m_lastPeerPulse(0), + m_lastHousekeepingRun(0), + m_lastNetworkHousekeepingRun(0), + m_now(now), + m_natMustDie(true), + m_online(false) { // Load this node's identity. uint64_t idtmp[2]; idtmp[0] = 0; idtmp[1] = 0; @@ -116,28 +116,27 @@ Node::Node(void *uPtr,void *tPtr,const struct ZT_Node_Callbacks *callbacks,int64 stateObjectPut(tPtr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr)); } - uint8_t tmph[ZT_FINGERPRINT_HASH_SIZE]; + uint8_t tmph[ZT_SHA384_DIGEST_SIZE]; RR->identity.hashWithPrivate(tmph); RR->localCacheSymmetric.init(tmph); - Utils::burn(tmph,sizeof(tmph)); // This constructs all the components of the ZeroTier core within a single contiguous memory container, // which reduces memory fragmentation and may improve cache locality. - _objects = new _NodeObjects(RR,tPtr); + m_objects = new _NodeObjects(RR, tPtr); postEvent(tPtr, ZT_EVENT_UP); } Node::~Node() { - _networks_m.lock(); - _networks_m.unlock(); - _networks.clear(); - _networks_m.lock(); - _networks_m.unlock(); + m_networks_l.lock(); + m_networks_l.unlock(); + m_networks.clear(); + m_networks_l.lock(); + m_networks_l.unlock(); - if (_objects) - delete (_NodeObjects *)_objects; + if (m_objects) + delete (_NodeObjects *)m_objects; // Let go of cached Buf objects. If other nodes happen to be running in this // same process space new Bufs will be allocated as needed, but this is almost @@ -161,7 +160,7 @@ ZT_ResultCode Node::processWirePacket( unsigned int packetLength, volatile int64_t *nextBackgroundTaskDeadline) { - _now = now; + m_now = now; RR->vl1->onRemotePacket(tPtr,localSocket,(remoteAddress) ? InetAddress::NIL : *asInetAddress(remoteAddress),packetData,packetLength); return ZT_RESULT_OK; } @@ -178,7 +177,7 @@ ZT_ResultCode Node::processVirtualNetworkFrame( unsigned int frameLength, volatile int64_t *nextBackgroundTaskDeadline) { - _now = now; + m_now = now; SharedPtr nw(this->network(nwid)); if (nw) { RR->vl2->onLocalEthernet(tPtr,nw,MAC(sourceMac),MAC(destMac),etherType,vlanId,frameData,frameLength); @@ -215,20 +214,20 @@ struct _processBackgroundTasks_eachPeer }; ZT_ResultCode Node::processBackgroundTasks(void *tPtr,int64_t now,volatile int64_t *nextBackgroundTaskDeadline) { - _now = now; - Mutex::Lock bl(_backgroundTasksLock); + m_now = now; + Mutex::Lock bl(m_backgroundTasksLock); try { // Call peer pulse() method of all peers every ZT_PEER_PULSE_INTERVAL. - if ((now - _lastPeerPulse) >= ZT_PEER_PULSE_INTERVAL) { - _lastPeerPulse = now; + if ((now - m_lastPeerPulse) >= ZT_PEER_PULSE_INTERVAL) { + m_lastPeerPulse = now; try { _processBackgroundTasks_eachPeer pf(now,this,tPtr); RR->topology->eachPeerWithRoot<_processBackgroundTasks_eachPeer &>(pf); - if (pf.online != _online) { - _online = pf.online; - postEvent(tPtr, _online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE); + if (pf.online != m_online) { + m_online = pf.online; + postEvent(tPtr, m_online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE); } RR->topology->rankRoots(now); @@ -248,29 +247,29 @@ ZT_ResultCode Node::processBackgroundTasks(void *tPtr,int64_t now,volatile int64 } // Perform network housekeeping and possibly request new certs and configs every ZT_NETWORK_HOUSEKEEPING_PERIOD. - if ((now - _lastNetworkHousekeepingRun) >= ZT_NETWORK_HOUSEKEEPING_PERIOD) { - _lastHousekeepingRun = now; + if ((now - m_lastNetworkHousekeepingRun) >= ZT_NETWORK_HOUSEKEEPING_PERIOD) { + m_lastHousekeepingRun = now; { - RWMutex::RLock l(_networks_m); - for(Map< uint64_t,SharedPtr >::const_iterator i(_networks.begin());i!=_networks.end();++i) + RWMutex::RLock l(m_networks_l); + for(Map< uint64_t,SharedPtr >::const_iterator i(m_networks.begin());i != m_networks.end();++i) i->second->doPeriodicTasks(tPtr,now); } } // Clean up other stuff every ZT_HOUSEKEEPING_PERIOD. - if ((now - _lastHousekeepingRun) >= ZT_HOUSEKEEPING_PERIOD) { - _lastHousekeepingRun = now; + if ((now - m_lastHousekeepingRun) >= ZT_HOUSEKEEPING_PERIOD) { + m_lastHousekeepingRun = now; try { // Clean up any old local controller auth memoizations. This is an // optimization for network controllers to know whether to accept // or trust nodes without doing an extra cert check. - _localControllerAuthorizations_m.lock(); - for(Map<_LocalControllerAuth,int64_t>::iterator i(_localControllerAuthorizations.begin());i!=_localControllerAuthorizations.end();) { // NOLINT(hicpp-use-auto,modernize-use-auto) + m_localControllerAuthorizations_l.lock(); + for(Map::iterator i(m_localControllerAuthorizations.begin());i != m_localControllerAuthorizations.end();) { // NOLINT(hicpp-use-auto,modernize-use-auto) if ((i->second - now) > (ZT_NETWORK_AUTOCONF_DELAY * 3)) - _localControllerAuthorizations.erase(i++); + m_localControllerAuthorizations.erase(i++); else ++i; } - _localControllerAuthorizations_m.unlock(); + m_localControllerAuthorizations_l.unlock(); RR->topology->doPeriodicTasks(tPtr, now); RR->sa->clean(now); @@ -279,30 +278,7 @@ ZT_ResultCode Node::processBackgroundTasks(void *tPtr,int64_t now,volatile int64 } } - // Set off any due or overdue peer alarms. - int64_t earliestAlarmAt = now + ZT_MAX_TIMER_TASK_INTERVAL; - std::vector bzzt; - { - Mutex::Lock l(_peerAlarms_l); - for(std::map< Fingerprint,int64_t,std::less,Utils::Mallocator< std::pair > >::iterator a(_peerAlarms.begin());a!=_peerAlarms.end();) { // NOLINT(hicpp-use-auto,modernize-use-auto) - if (now >= a->second) { - bzzt.push_back(a->first); - _peerAlarms.erase(a++); - } else { - if (a->second < earliestAlarmAt) - earliestAlarmAt = a->second; - ++a; - } - } - } - for(std::vector::iterator a(bzzt.begin());a!=bzzt.end();++a) { // NOLINT(hicpp-use-auto,modernize-use-auto,modernize-loop-convert) - const SharedPtr p(RR->topology->peer(tPtr,a->address(),false)); - if ((p)&&(p->identity().fingerprint() == *a)) - p->alarm(tPtr,now); - } - - // Tell caller when to call this method next. - *nextBackgroundTaskDeadline = earliestAlarmAt; + *nextBackgroundTaskDeadline = now + ZT_TIMER_TASK_INTERVAL; } catch ( ... ) { return ZT_RESULT_FATAL_ERROR_INTERNAL; } @@ -316,8 +292,8 @@ ZT_ResultCode Node::join(uint64_t nwid,const ZT_Fingerprint *controllerFingerpri if (controllerFingerprint) Utils::copy(fp.apiFingerprint(),controllerFingerprint); - RWMutex::Lock l(_networks_m); - SharedPtr &nw = _networks[nwid]; + RWMutex::Lock l(m_networks_l); + SharedPtr &nw = m_networks[nwid]; if (nw) return ZT_RESULT_OK; nw.set(new Network(RR,tptr,nwid,fp,uptr,nullptr)); @@ -329,15 +305,15 @@ ZT_ResultCode Node::leave(uint64_t nwid,void **uptr,void *tptr) { ZT_VirtualNetworkConfig ctmp; - _networks_m.lock(); - Map< uint64_t,SharedPtr >::iterator nwi(_networks.find(nwid)); // NOLINT(hicpp-use-auto,modernize-use-auto) - if (nwi == _networks.end()) { - _networks_m.unlock(); + m_networks_l.lock(); + Map< uint64_t,SharedPtr >::iterator nwi(m_networks.find(nwid)); // NOLINT(hicpp-use-auto,modernize-use-auto) + if (nwi == m_networks.end()) { + m_networks_l.unlock(); return ZT_RESULT_OK; } SharedPtr nw(nwi->second); - _networks.erase(nwi); - _networks_m.unlock(); + m_networks.erase(nwi); + m_networks_l.unlock(); if (uptr) *uptr = *nw->userPtr(); @@ -403,7 +379,7 @@ void Node::status(ZT_NodeStatus *status) const status->identity = reinterpret_cast(&RR->identity); status->publicIdentity = RR->publicIdentityStr; status->secretIdentity = RR->secretIdentityStr; - status->online = _online ? 1 : 0; + status->online = m_online ? 1 : 0; } ZT_PeerList *Node::peers() const @@ -419,7 +395,7 @@ ZT_PeerList *Node::peers() const pl->peers = (ZT_Peer *)(buf + sizeof(ZT_PeerList)); Identity *identities = (Identity *)(buf + sizeof(ZT_PeerList) + (sizeof(ZT_Peer) * peers.size())); // NOLINT(modernize-use-auto,hicpp-use-auto) - const int64_t now = _now; + const int64_t now = m_now; pl->peerCount = 0; for(std::vector< SharedPtr >::iterator pi(peers.begin());pi!=peers.end();++pi) { // NOLINT(modernize-use-auto,modernize-loop-convert,hicpp-use-auto) ZT_Peer *const p = &(pl->peers[pl->peerCount]); @@ -480,16 +456,16 @@ ZT_VirtualNetworkConfig *Node::networkConfig(uint64_t nwid) const ZT_VirtualNetworkList *Node::networks() const { - RWMutex::RLock l(_networks_m); + RWMutex::RLock l(m_networks_l); - char *const buf = (char *)::malloc(sizeof(ZT_VirtualNetworkList) + (sizeof(ZT_VirtualNetworkConfig) * _networks.size())); + char *const buf = (char *)::malloc(sizeof(ZT_VirtualNetworkList) + (sizeof(ZT_VirtualNetworkConfig) * m_networks.size())); if (!buf) return nullptr; ZT_VirtualNetworkList *nl = (ZT_VirtualNetworkList *)buf; // NOLINT(modernize-use-auto,hicpp-use-auto) nl->networks = (ZT_VirtualNetworkConfig *)(buf + sizeof(ZT_VirtualNetworkList)); nl->networkCount = 0; - for(Map< uint64_t,SharedPtr >::const_iterator i(_networks.begin());i!=_networks.end();++i) // NOLINT(modernize-use-auto,modernize-loop-convert,hicpp-use-auto) + for(Map< uint64_t,SharedPtr >::const_iterator i(m_networks.begin());i != m_networks.end();++i) // NOLINT(modernize-use-auto,modernize-loop-convert,hicpp-use-auto) i->second->externalConfig(&(nl->networks[nl->networkCount++])); return nl; @@ -510,8 +486,8 @@ void Node::freeQueryResult(void *qr) void Node::setInterfaceAddresses(const ZT_InterfaceAddress *addrs,unsigned int addrCount) { - Mutex::Lock _l(_localInterfaceAddresses_m); - _localInterfaceAddresses.clear(); + Mutex::Lock _l(m_localInterfaceAddresses_m); + m_localInterfaceAddresses.clear(); for(unsigned int i=0;i Node::stateObjectGet(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2]) { std::vector r; - if (_cb.stateGetFunction) { + if (m_cb.stateGetFunction) { void *data = 0; void (*freeFunc)(void *) = 0; - int l = _cb.stateGetFunction( + int l = m_cb.stateGetFunction( reinterpret_cast(this), - _uPtr, + m_uPtr, tPtr, type, id, @@ -577,8 +553,8 @@ std::vector Node::stateObjectGet(void *const tPtr,ZT_StateObjectType ty bool Node::shouldUsePathForZeroTierTraffic(void *tPtr,const Identity &id,const int64_t localSocket,const InetAddress &remoteAddress) { { - RWMutex::RLock l(_networks_m); - for(Map< uint64_t,SharedPtr >::iterator i(_networks.begin());i!=_networks.end();++i) { // NOLINT(hicpp-use-auto,modernize-use-auto,modernize-loop-convert) + RWMutex::RLock l(m_networks_l); + for(Map< uint64_t,SharedPtr >::iterator i(m_networks.begin());i != m_networks.end();++i) { // NOLINT(hicpp-use-auto,modernize-use-auto,modernize-loop-convert) for (unsigned int k = 0,j = i->second->config().staticIpCount; k < j; ++k) { if (i->second->config().staticIps[k].containsAddress(remoteAddress)) return false; @@ -586,10 +562,10 @@ bool Node::shouldUsePathForZeroTierTraffic(void *tPtr,const Identity &id,const i } } - if (_cb.pathCheckFunction) { - return (_cb.pathCheckFunction( + if (m_cb.pathCheckFunction) { + return (m_cb.pathCheckFunction( reinterpret_cast(this), - _uPtr, + m_uPtr, tPtr, id.address().toInt(), (const ZT_Identity *)&id, @@ -602,10 +578,10 @@ bool Node::shouldUsePathForZeroTierTraffic(void *tPtr,const Identity &id,const i bool Node::externalPathLookup(void *tPtr,const Identity &id,int family,InetAddress &addr) { - if (_cb.pathLookupFunction) { - return (_cb.pathLookupFunction( + if (m_cb.pathLookupFunction) { + return (m_cb.pathLookupFunction( reinterpret_cast(this), - _uPtr, + m_uPtr, tPtr, id.address().toInt(), reinterpret_cast(&id), @@ -623,9 +599,9 @@ ZT_ResultCode Node::setPhysicalPathConfiguration(const struct sockaddr_storage * bool Node::localControllerHasAuthorized(const int64_t now,const uint64_t nwid,const Address &addr) const { - _localControllerAuthorizations_m.lock(); - const int64_t *const at = _localControllerAuthorizations.get(_LocalControllerAuth(nwid,addr)); - _localControllerAuthorizations_m.unlock(); + m_localControllerAuthorizations_l.lock(); + const int64_t *const at = m_localControllerAuthorizations.get(p_LocalControllerAuth(nwid, addr)); + m_localControllerAuthorizations_l.unlock(); if (at) return ((now - *at) < (ZT_NETWORK_AUTOCONF_DELAY * 3)); return false; @@ -635,9 +611,9 @@ bool Node::localControllerHasAuthorized(const int64_t now,const uint64_t nwid,co void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &destination,const NetworkConfig &nc,bool sendLegacyFormatConfig) { - _localControllerAuthorizations_m.lock(); - _localControllerAuthorizations[_LocalControllerAuth(nwid,destination)] = now(); - _localControllerAuthorizations_m.unlock(); + m_localControllerAuthorizations_l.lock(); + m_localControllerAuthorizations[p_LocalControllerAuth(nwid, destination)] = now(); + m_localControllerAuthorizations_l.unlock(); if (destination == RR->identity.address()) { SharedPtr n(network(nwid)); diff --git a/node/Node.hpp b/node/Node.hpp index dec30cf34..cb3ef087b 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -110,7 +110,7 @@ public: /** * @return Most recent time value supplied to core via API */ - ZT_INLINE int64_t now() const noexcept { return _now; } + ZT_INLINE int64_t now() const noexcept { return m_now; } /** * Send packet to to the physical wire via callback @@ -125,9 +125,9 @@ public: */ ZT_INLINE bool putPacket(void *tPtr,const int64_t localSocket,const InetAddress &addr,const void *data,unsigned int len,unsigned int ttl = 0) noexcept { - return (_cb.wirePacketSendFunction( + return (m_cb.wirePacketSendFunction( reinterpret_cast(this), - _uPtr, + m_uPtr, tPtr, localSocket, reinterpret_cast(&addr), @@ -151,9 +151,9 @@ public: */ ZT_INLINE void putFrame(void *tPtr,uint64_t nwid,void **nuptr,const MAC &source,const MAC &dest,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) noexcept { - _cb.virtualNetworkFrameFunction( + m_cb.virtualNetworkFrameFunction( reinterpret_cast(this), - _uPtr, + m_uPtr, tPtr, nwid, nuptr, @@ -171,8 +171,8 @@ public: */ ZT_INLINE SharedPtr network(uint64_t nwid) const noexcept { - RWMutex::RLock l(_networks_m); - const SharedPtr *const n = _networks.get(nwid); + RWMutex::RLock l(m_networks_l); + const SharedPtr *const n = m_networks.get(nwid); if (n) return *n; return SharedPtr(); @@ -183,8 +183,8 @@ public: */ ZT_INLINE Vector localInterfaceAddresses() const { - Mutex::Lock _l(_localInterfaceAddresses_m); - return _localInterfaceAddresses; + Mutex::Lock _l(m_localInterfaceAddresses_m); + return m_localInterfaceAddresses; } /** @@ -196,7 +196,7 @@ public: */ ZT_INLINE void postEvent(void *tPtr,ZT_Event ev,const void *md = nullptr) noexcept { - _cb.eventCallback(reinterpret_cast(this),_uPtr,tPtr,ev,md); + m_cb.eventCallback(reinterpret_cast(this), m_uPtr, tPtr, ev, md); } /** @@ -210,13 +210,13 @@ public: */ ZT_INLINE void configureVirtualNetworkPort(void *tPtr,uint64_t nwid,void **nuptr,ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nc) noexcept { - _cb.virtualNetworkConfigFunction(reinterpret_cast(this),_uPtr,tPtr,nwid,nuptr,op,nc); + m_cb.virtualNetworkConfigFunction(reinterpret_cast(this), m_uPtr, tPtr, nwid, nuptr, op, nc); } /** * @return True if node appears online */ - ZT_INLINE bool online() const noexcept { return _online; } + ZT_INLINE bool online() const noexcept { return m_online; } /** * Get a state object @@ -239,8 +239,8 @@ public: */ ZT_INLINE void stateObjectPut(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2],const void *const data,const unsigned int len) noexcept { - if (_cb.statePutFunction) - _cb.statePutFunction(reinterpret_cast(this),_uPtr,tPtr,type,id,data,(int)len); + if (m_cb.statePutFunction) + m_cb.statePutFunction(reinterpret_cast(this), m_uPtr, tPtr, type, id, data, (int)len); } /** @@ -252,8 +252,8 @@ public: */ ZT_INLINE void stateObjectDelete(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2]) noexcept { - if (_cb.statePutFunction) - _cb.statePutFunction(reinterpret_cast(this),_uPtr,tPtr,type,id,nullptr,-1); + if (m_cb.statePutFunction) + m_cb.statePutFunction(reinterpret_cast(this), m_uPtr, tPtr, type, id, nullptr, -1); } /** @@ -292,12 +292,12 @@ public: /** * @return This node's identity */ - ZT_INLINE const Identity &identity() const noexcept { return _RR.identity; } + ZT_INLINE const Identity &identity() const noexcept { return m_RR.identity; } /** * @return True if aggressive NAT-traversal mechanisms like scanning of <1024 ports are enabled */ - ZT_INLINE bool natMustDie() const noexcept { return _natMustDie; } + ZT_INLINE bool natMustDie() const noexcept { return m_natMustDie; } /** * Wake peer by calling its alarm() method at or after a given time. @@ -332,68 +332,59 @@ public: virtual void ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &destination,NetworkController::ErrorCode errorCode); // NOLINT(cppcoreguidelines-explicit-virtual-functions,hicpp-use-override,modernize-use-override) private: - RuntimeEnvironment _RR; + RuntimeEnvironment m_RR; RuntimeEnvironment *const RR; // Pointer to a struct defined in Node that holds instances of core objects. - void *_objects; + void *m_objects; // Function pointers to C callbacks supplied via the API. - ZT_Node_Callbacks _cb; + ZT_Node_Callbacks m_cb; // A user-specified opaque pointer passed back via API callbacks. - void *_uPtr; - - // Fingerprints of peers that want to have their alarm() function called at some point in the future. - // These behave like weak references in that the node looks them up in Topology and calls alarm() - // in each peer if that peer object is still held in memory. Calling alarm() unnecessarily on a peer - // is harmless. This just exists as an optimization to prevent having to iterate through all peers - // on every processBackgroundTasks call. A simple map<> is used here because there are usually only - // a few of these, if any. - std::map< Fingerprint,int64_t,std::less,Utils::Mallocator< std::pair > > _peerAlarms; - Mutex _peerAlarms_l; + void *m_uPtr; // Cache that remembers whether or not the locally running network controller (if any) has authorized // someone on their most recent query. This is used by the network controller as a memoization optimization // to elide unnecessary signature verifications. It might get moved in the future since this is sort of a // weird place to put it. - struct _LocalControllerAuth + struct p_LocalControllerAuth { uint64_t nwid,address; - ZT_INLINE _LocalControllerAuth(const uint64_t nwid_,const Address &address_) noexcept: nwid(nwid_),address(address_.toInt()) {} + ZT_INLINE p_LocalControllerAuth(const uint64_t nwid_, const Address &address_) noexcept: nwid(nwid_), address(address_.toInt()) {} ZT_INLINE unsigned long hashCode() const noexcept { return (unsigned long)(nwid + address); } - ZT_INLINE bool operator==(const _LocalControllerAuth &a) const noexcept { return ((a.nwid == nwid) && (a.address == address)); } - ZT_INLINE bool operator!=(const _LocalControllerAuth &a) const noexcept { return ((a.nwid != nwid) || (a.address != address)); } - ZT_INLINE bool operator<(const _LocalControllerAuth &a) const noexcept { return ((a.nwid < nwid) || ((a.nwid == nwid)&&(a.address < address))); } + ZT_INLINE bool operator==(const p_LocalControllerAuth &a) const noexcept { return ((a.nwid == nwid) && (a.address == address)); } + ZT_INLINE bool operator!=(const p_LocalControllerAuth &a) const noexcept { return ((a.nwid != nwid) || (a.address != address)); } + ZT_INLINE bool operator<(const p_LocalControllerAuth &a) const noexcept { return ((a.nwid < nwid) || ((a.nwid == nwid) && (a.address < address))); } }; - Map<_LocalControllerAuth,int64_t> _localControllerAuthorizations; - Mutex _localControllerAuthorizations_m; + Map m_localControllerAuthorizations; + Mutex m_localControllerAuthorizations_l; // Locally joined networks by network ID. - Map< uint64_t,SharedPtr > _networks; - RWMutex _networks_m; + Map< uint64_t,SharedPtr > m_networks; + RWMutex m_networks_l; // These are local interface addresses that have been configured via the API // and can be pushed to other nodes. - Vector< ZT_InterfaceAddress > _localInterfaceAddresses; - Mutex _localInterfaceAddresses_m; + Vector< ZT_InterfaceAddress > m_localInterfaceAddresses; + Mutex m_localInterfaceAddresses_m; // This is locked while running processBackgroundTasks(). - Mutex _backgroundTasksLock; + Mutex m_backgroundTasksLock; // These are locked via _backgroundTasksLock as they're only checked and modified in processBackgroundTasks(). - int64_t _lastPeerPulse; - int64_t _lastHousekeepingRun; - int64_t _lastNetworkHousekeepingRun; + int64_t m_lastPeerPulse; + int64_t m_lastHousekeepingRun; + int64_t m_lastNetworkHousekeepingRun; // This is the most recent value for time passed in via any of the core API methods. - std::atomic _now; + std::atomic m_now; // True if we are to use really intensive NAT-busting measures. - std::atomic _natMustDie; + std::atomic m_natMustDie; // True if at least one root appears reachable. - std::atomic _online; + std::atomic m_online; }; } // namespace ZeroTier diff --git a/node/Path.cpp b/node/Path.cpp index 565e0faff..86a03c136 100644 --- a/node/Path.cpp +++ b/node/Path.cpp @@ -19,9 +19,9 @@ namespace ZeroTier { bool Path::send(const RuntimeEnvironment *const RR,void *const tPtr,const void *const data,const unsigned int len,const int64_t now) noexcept { - if (RR->node->putPacket(tPtr,_localSocket,_addr,data,len)) { - _lastOut = now; - _outMeter.log(now,len); + if (RR->node->putPacket(tPtr, m_localSocket, m_addr, data, len)) { + m_lastOut = now; + m_outMeter.log(now, len); return true; } return false; diff --git a/node/Path.hpp b/node/Path.hpp index 67e966362..74e0b96a7 100644 --- a/node/Path.hpp +++ b/node/Path.hpp @@ -32,7 +32,7 @@ namespace ZeroTier { class RuntimeEnvironment; -template +template class Defragmenter; /** @@ -43,16 +43,16 @@ class Path friend class SharedPtr; // Allow defragmenter to access fragment-in-flight info stored in Path for performance reasons. - template + template friend class Defragmenter; public: ZT_INLINE Path(const int64_t l,const InetAddress &r) noexcept : // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init) - _localSocket(l), - _lastIn(0), - _lastOut(0), - _latency(-1), - _addr(r) + m_localSocket(l), + m_lastIn(0), + m_lastOut(0), + m_latency(-1), + m_addr(r) { } @@ -76,8 +76,8 @@ public: */ ZT_INLINE void sent(const int64_t now,const unsigned int bytes) noexcept { - _lastOut.store(now); - _outMeter.log(now,bytes); + m_lastOut.store(now); + m_outMeter.log(now, bytes); } /** @@ -88,8 +88,8 @@ public: */ ZT_INLINE void received(const int64_t now,const unsigned int bytes) noexcept { - _lastIn.store(now); - _inMeter.log(now,bytes); + m_lastIn.store(now); + m_inMeter.log(now, bytes); } /** @@ -99,54 +99,54 @@ public: */ ZT_INLINE void updateLatency(const unsigned int newMeasurement) noexcept { - int lat = _latency; + int lat = m_latency; if (lat > 0) { - _latency = (lat + newMeasurement) / 2; + m_latency = (lat + newMeasurement) / 2; } else { - _latency = newMeasurement; + m_latency = newMeasurement; } } /** * @return Latency in milliseconds or -1 if unknown */ - ZT_INLINE int latency() const noexcept { return _latency; } + ZT_INLINE int latency() const noexcept { return m_latency; } /** * Check path aliveness * * @param now Current time */ - ZT_INLINE bool alive(const int64_t now) const noexcept { return ((now - _lastIn.load()) < ZT_PATH_ALIVE_TIMEOUT); } + ZT_INLINE bool alive(const int64_t now) const noexcept { return ((now - m_lastIn.load()) < ZT_PATH_ALIVE_TIMEOUT); } /** * @return Physical address */ - ZT_INLINE const InetAddress &address() const noexcept { return _addr; } + ZT_INLINE const InetAddress &address() const noexcept { return m_addr; } /** * @return Local socket as specified by external code */ - ZT_INLINE int64_t localSocket() const noexcept { return _localSocket; } + ZT_INLINE int64_t localSocket() const noexcept { return m_localSocket; } /** * @return Last time we received anything */ - ZT_INLINE int64_t lastIn() const noexcept { return _lastIn.load(); } + ZT_INLINE int64_t lastIn() const noexcept { return m_lastIn.load(); } /** * @return Last time we sent something */ - ZT_INLINE int64_t lastOut() const noexcept { return _lastOut.load(); } + ZT_INLINE int64_t lastOut() const noexcept { return m_lastOut.load(); } private: - const int64_t _localSocket; - std::atomic _lastIn; - std::atomic _lastOut; - std::atomic _latency; - const InetAddress _addr; - Meter<> _inMeter; - Meter<> _outMeter; + const int64_t m_localSocket; + std::atomic m_lastIn; + std::atomic m_lastOut; + std::atomic m_latency; + const InetAddress m_addr; + Meter<> m_inMeter; + Meter<> m_outMeter; // These fields belong to Defragmenter but are kept in Path for performance // as it's much faster this way than having Defragmenter maintain another diff --git a/node/Peer.cpp b/node/Peer.cpp index da23f33b5..6778d26e3 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -26,21 +26,20 @@ namespace ZeroTier { Peer::Peer(const RuntimeEnvironment *renv) : // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init) RR(renv), - _lastReceive(0), - _lastSend(0), - _lastSentHello(), - _lastWhoisRequestReceived(0), - _lastEchoRequestReceived(0), - _lastProbeReceived(0), - _lastAttemptedP2PInit(0), - _lastPrioritizedPaths(0), - _lastAttemptedAggressiveNATTraversal(0), - _alivePathCount(0), - _probe(0), - _vProto(0), - _vMajor(0), - _vMinor(0), - _vRevision(0) + m_lastReceive(0), + m_lastSend(0), + m_lastSentHello(), + m_lastWhoisRequestReceived(0), + m_lastEchoRequestReceived(0), + m_lastPrioritizedPaths(0), + m_alivePathCount(0), + m_tryQueue(), + m_tryQueuePtr(m_tryQueue.end()), + m_probe(0), + m_vProto(0), + m_vMajor(0), + m_vMinor(0), + m_vRevision(0) { } @@ -50,16 +49,16 @@ Peer::~Peer() // NOLINT(hicpp-use-equals-default,modernize-use-equals-default) bool Peer::init(const Identity &peerIdentity) { - RWMutex::Lock l(_lock); + RWMutex::Lock l(m_lock); - if (_id == peerIdentity) - return true; - _id = peerIdentity; + if (m_id) // already initialized sanity check + return false; + m_id = peerIdentity; uint8_t ktmp[ZT_SYMMETRIC_KEY_SIZE]; if (!RR->identity.agree(peerIdentity,ktmp)) return false; - _identityKey.init(RR->node->now(),ktmp); + m_identityKey.init(RR->node->now(), ktmp); Utils::burn(ktmp,sizeof(ktmp)); return true; @@ -76,67 +75,64 @@ void Peer::received( { const int64_t now = RR->node->now(); - _lastReceive = now; - _inMeter.log(now,payloadLength); + m_lastReceive = now; + m_inMeter.log(now, payloadLength); if (hops == 0) { - RWMutex::RMaybeWLock l(_lock); + RWMutex::RMaybeWLock l(m_lock); - // If this matches an existing path, skip path learning stuff. - for (unsigned int i=0;i<_alivePathCount;++i) { - if (_paths[i] == path) { - _lock.runlock(); + // If this matches an existing path, skip path learning stuff. For the small number + // of paths a peer will have linear scan is the fastest way to do lookup. + for (unsigned int i=0;i < m_alivePathCount;++i) { + if (m_paths[i] == path) return; - } } // If we made it here, we don't already know this path. - if (RR->node->shouldUsePathForZeroTierTraffic(tPtr,_id,path->localSocket(),path->address())) { + if (RR->node->shouldUsePathForZeroTierTraffic(tPtr, m_id, path->localSocket(), path->address())) { + // SECURITY: note that if we've made it here we expected this OK, see Expect.hpp. + // There is replay protection in effect for OK responses. if (verb == Protocol::VERB_OK) { + // If we're learning a new path convert the lock to an exclusive write lock. l.writing(); - // SECURITY: in the future we may not accept anything but OK(HELLO) to learn paths, - // but right now we accept any OK for backward compatibility. Note that OK will - // have been checked against expected packet IDs (see Expect.hpp) before we get here, - // and this guards against replay attacks. - // If the path list is full, replace the least recently active path. Otherwise append new path. unsigned int newPathIdx = 0; - if (_alivePathCount >= ZT_MAX_PEER_NETWORK_PATHS) { + if (m_alivePathCount >= ZT_MAX_PEER_NETWORK_PATHS) { int64_t lastReceiveTimeMax = 0; - for (unsigned int i=0;i<_alivePathCount;++i) { - if ((_paths[i]->address().family() == path->address().family()) && - (_paths[i]->localSocket() == path->localSocket()) && // TODO: should be localInterface when multipath is integrated - (_paths[i]->address().ipsEqual2(path->address()))) { + for (unsigned int i=0;i < m_alivePathCount;++i) { + if ((m_paths[i]->address().family() == path->address().family()) && + (m_paths[i]->localSocket() == path->localSocket()) && // TODO: should be localInterface when multipath is integrated + (m_paths[i]->address().ipsEqual2(path->address()))) { // Replace older path if everything is the same except the port number, since NAT/firewall reboots // and other wacky stuff can change port number assignments. - _paths[i] = path; + m_paths[i] = path; return; - } else if (_paths[i]->lastIn() > lastReceiveTimeMax) { - lastReceiveTimeMax = _paths[i]->lastIn(); + } else if (m_paths[i]->lastIn() > lastReceiveTimeMax) { + lastReceiveTimeMax = m_paths[i]->lastIn(); newPathIdx = i; } } } else { - newPathIdx = _alivePathCount++; + newPathIdx = m_alivePathCount++; } InetAddress old; - if (_paths[newPathIdx]) - old = _paths[newPathIdx]->address(); - _paths[newPathIdx] = path; + if (m_paths[newPathIdx]) + old = m_paths[newPathIdx]->address(); + m_paths[newPathIdx] = path; // Re-prioritize paths to include the new one. - _prioritizePaths(now); + m_prioritizePaths(now); // Remember most recently learned paths for future bootstrap attempts on restart. Endpoint pathEndpoint(path->address()); - _bootstrap[pathEndpoint.type()] = pathEndpoint; + m_bootstrap[pathEndpoint.type()] = pathEndpoint; - RR->t->learnedNewPath(tPtr,0x582fabdd,packetId,_id,path->address(),old); + RR->t->learnedNewPath(tPtr, 0x582fabdd, packetId, m_id, path->address(), old); } else { path->sent(now,hello(tPtr,path->localSocket(),path->address(),now)); - RR->t->tryingNewPath(tPtr,0xb7747ddd,_id,path->address(),path->address(),packetId,(uint8_t)verb,_id,ZT_TRACE_TRYING_NEW_PATH_REASON_PACKET_RECEIVED_FROM_UNKNOWN_PATH); + RR->t->tryingNewPath(tPtr, 0xb7747ddd, m_id, path->address(), path->address(), packetId, (uint8_t)verb, m_id, ZT_TRACE_TRYING_NEW_PATH_REASON_PACKET_RECEIVED_FROM_UNKNOWN_PATH); } } } @@ -194,112 +190,181 @@ unsigned int Peer::hello(void *tPtr,int64_t localSocket,const InetAddress &atAdd #endif } -unsigned int Peer::sendNOP(void *const tPtr,const int64_t localSocket,const InetAddress &atAddress,const int64_t now) +unsigned int Peer::probe(void *tPtr,int64_t localSocket,const InetAddress &atAddress,int64_t now) { - Buf outp; - Protocol::Header &ph = outp.as(); // NOLINT(hicpp-use-auto,modernize-use-auto) - ph.packetId = Protocol::getPacketId(); - _id.address().copyTo(ph.destination); - RR->identity.address().copyTo(ph.source); - ph.flags = 0; - ph.verb = Protocol::VERB_NOP; - Protocol::armor(outp,sizeof(Protocol::Header),_identityKey.key(),this->cipher()); - RR->node->putPacket(tPtr,localSocket,atAddress,outp.unsafeData,sizeof(Protocol::Header)); - return sizeof(Protocol::Header); + if (m_vProto < 11) { + Buf outp; + Protocol::Header &ph = outp.as(); // NOLINT(hicpp-use-auto,modernize-use-auto) + //ph.packetId = Protocol::getPacketId(); + m_id.address().copyTo(ph.destination); + RR->identity.address().copyTo(ph.source); + ph.flags = 0; + ph.verb = Protocol::VERB_NOP; + Protocol::armor(outp, sizeof(Protocol::Header), m_identityKey.key(), this->cipher()); + RR->node->putPacket(tPtr,localSocket,atAddress,outp.unsafeData,sizeof(Protocol::Header)); + return sizeof(Protocol::Header); + } else { + RR->node->putPacket(tPtr, -1, atAddress, &m_probe, 4); + return 4; + } } void Peer::pulse(void *const tPtr,const int64_t now,const bool isRoot) { - RWMutex::Lock l(_lock); + RWMutex::Lock l(m_lock); bool needHello = false; - if ((now - _lastSentHello) >= ZT_PEER_HELLO_INTERVAL) { - _lastSentHello = now; + if ((now - m_lastSentHello) >= ZT_PEER_HELLO_INTERVAL) { + m_lastSentHello = now; needHello = true; } - _prioritizePaths(now); + m_prioritizePaths(now); - for(unsigned int i=0;i<_alivePathCount;++i) { - if (needHello) { - needHello = false; - const unsigned int bytes = hello(tPtr,_paths[i]->localSocket(),_paths[i]->address(),now); - _paths[i]->sent(now,bytes); - sent(now,bytes); - } else if ((now - _paths[i]->lastOut()) >= ZT_PATH_KEEPALIVE_PERIOD) { - _paths[i]->send(RR,tPtr,&now,1,now); - sent(now,1); - } - - // TODO: when we merge multipath we'll keep one open per interface to non-roots. - // For roots we try to keep every path open. - if (!isRoot) - return; - } - - if (needHello) { - // Try any statically configured addresses. - InetAddress addr; - if (RR->node->externalPathLookup(tPtr,_id,-1,addr)) { - if (RR->node->shouldUsePathForZeroTierTraffic(tPtr,_id,-1,addr)) { - RR->t->tryingNewPath(tPtr,0x84a10000,_id,addr,InetAddress::NIL,0,0,Identity::NIL,ZT_TRACE_TRYING_NEW_PATH_REASON_EXPLICITLY_SUGGESTED_ADDRESS); - hello(tPtr,-1,addr,now); - } - } - - if (!_bootstrap.empty()) { - if (isRoot) { - // Try all bootstrap addresses if this is a root. - for(std::map< Endpoint::Type,Endpoint >::const_iterator i(_bootstrap.begin());i!=_bootstrap.end();++i) { - if ( ((i->first == Endpoint::TYPE_INETADDR_V4)||(i->first == Endpoint::TYPE_INETADDR_V6)) && (!i->second.inetAddr().ipsEqual(addr)) ) { - RR->t->tryingNewPath(tPtr,0x0a009444,_id,i->second.inetAddr(),InetAddress::NIL,0,0,Identity::NIL,ZT_TRACE_TRYING_NEW_PATH_REASON_BOOTSTRAP_ADDRESS); - hello(tPtr,-1,i->second.inetAddr(),now); - } + if (m_alivePathCount == 0) { + // If there are no direct paths, attempt to make one. If there are queued addresses + // to try, attempt one of those. Otherwise try a path we can fetch via API callbacks + // and/or a remembered bootstrap path. + if (m_tryQueue.empty()) { + InetAddress addr; + if (RR->node->externalPathLookup(tPtr, m_id, -1, addr)) { + if ((addr)&&(RR->node->shouldUsePathForZeroTierTraffic(tPtr, m_id, -1, addr))) { + RR->t->tryingNewPath(tPtr, 0x84a10000, m_id, addr, InetAddress::NIL, 0, 0, Identity::NIL, ZT_TRACE_TRYING_NEW_PATH_REASON_EXPLICITLY_SUGGESTED_ADDRESS); + sent(now,probe(tPtr,-1,addr,now)); } - } else { - // Otherwise try a random bootstrap address. - unsigned int tryAtIndex = (unsigned int)Utils::random() % (unsigned int)_bootstrap.size(); - for(std::map< Endpoint::Type,Endpoint >::const_iterator i(_bootstrap.begin());i!=_bootstrap.end();++i) { + } + if (!m_bootstrap.empty()) { + unsigned int tryAtIndex = (unsigned int)Utils::random() % (unsigned int)m_bootstrap.size(); + for(SortedMap< Endpoint::Type,Endpoint >::const_iterator i(m_bootstrap.begin());i != m_bootstrap.end();++i) { if (tryAtIndex > 0) { --tryAtIndex; } else { - if ( ((i->first == Endpoint::TYPE_INETADDR_V4)||(i->first == Endpoint::TYPE_INETADDR_V6)) && (!i->second.inetAddr().ipsEqual(addr)) ) { - RR->t->tryingNewPath(tPtr,0x0a009444,_id,i->second.inetAddr(),InetAddress::NIL,0,0,Identity::NIL,ZT_TRACE_TRYING_NEW_PATH_REASON_BOOTSTRAP_ADDRESS); - hello(tPtr,-1,i->second.inetAddr(),now); + if ((i->second.isInetAddr())&&(!i->second.inetAddr().ipsEqual(addr))) { + RR->t->tryingNewPath(tPtr, 0x0a009444, m_id, i->second.inetAddr(), InetAddress::NIL, 0, 0, Identity::NIL, ZT_TRACE_TRYING_NEW_PATH_REASON_BOOTSTRAP_ADDRESS); + sent(now,probe(tPtr,-1,i->second.inetAddr(),now)); + break; } } } } + } else { + for(int k=0;(kts) > ZT_PATH_ALIVE_TIMEOUT) { + m_tryQueue.erase(m_tryQueuePtr++); + continue; + } + + if (m_tryQueuePtr->target.isInetAddr()) { + if ((m_tryQueuePtr->breakSymmetricBFG1024) && (RR->node->natMustDie())) { + // Attempt aggressive NAT traversal if both requested and enabled. + uint16_t ports[1023]; + for (unsigned int i=0;i<1023;++i) + ports[i] = (uint64_t)(i + 1); + for (unsigned int i=0;i<512;++i) { + const uint64_t rn = Utils::random(); + const unsigned int a = (unsigned int)rn % 1023; + const unsigned int b = (unsigned int)(rn >> 32U) % 1023; + if (a != b) { + uint16_t tmp = ports[a]; + ports[a] = ports[b]; + ports[b] = tmp; + } + } + InetAddress addr(m_tryQueuePtr->target.inetAddr()); + for (unsigned int i = 0;i < ZT_NAT_T_BFG1024_PORTS_PER_ATTEMPT;++i) { + addr.setPort(ports[i]); + sent(now,probe(tPtr,-1,addr,now)); + } + } else { + // Otherwise send a normal probe. + sent(now,probe(tPtr, -1, m_tryQueuePtr->target.inetAddr(), now)); + } + } + + ++m_tryQueuePtr; + } + } + } else { + // Keep direct paths alive, sending a HELLO if we need one or else just a simple byte. + for(unsigned int i=0;i < m_alivePathCount;++i) { + if (needHello) { + needHello = false; + const unsigned int bytes = hello(tPtr, m_paths[i]->localSocket(), m_paths[i]->address(), now); + m_paths[i]->sent(now, bytes); + sent(now,bytes); + } else if ((now - m_paths[i]->lastOut()) >= ZT_PATH_KEEPALIVE_PERIOD) { + m_paths[i]->send(RR, tPtr, &now, 1, now); + sent(now,1); + } + } + } + + // If we could not reliably send a HELLO via a direct path, send it by way of a root. + if (needHello) { + const SharedPtr root(RR->topology->root()); + if (root) { + const SharedPtr via(root->path(now)); + if (via) { + const unsigned int bytes = hello(tPtr,via->localSocket(),via->address(),now); + via->sent(now,bytes); + root->relayed(now,bytes); + sent(now,bytes); + } } } } +void Peer::tryDirectPath(const int64_t now,const Endpoint &ep,const bool breakSymmetricBFG1024) +{ + RWMutex::Lock l(m_lock); + + for(List::iterator i(m_tryQueue.begin());i != m_tryQueue.end();++i) { // NOLINT(modernize-loop-convert,hicpp-use-auto,modernize-use-auto) + if (i->target == ep) { + i->ts = now; + i->breakSymmetricBFG1024 = breakSymmetricBFG1024; + return; + } + } + +#ifdef __CPP11__ + m_tryQueue.emplace_back(now, ep, breakSymmetricBFG1024); +#else + _tryQueue.push_back(_TryQueueItem(now,ep,breakSymmetricBFG1024)); +#endif +} + void Peer::resetWithinScope(void *tPtr,InetAddress::IpScope scope,int inetAddressFamily,int64_t now) { - RWMutex::RLock l(_lock); - for(unsigned int i=0;i<_alivePathCount;++i) { - if ((_paths[i])&&((_paths[i]->address().family() == inetAddressFamily)&&(_paths[i]->address().ipScope() == scope))) - _paths[i]->sent(now,sendNOP(tPtr,_paths[i]->localSocket(),_paths[i]->address(),now)); + RWMutex::RLock l(m_lock); + for(unsigned int i=0;i < m_alivePathCount;++i) { + if ((m_paths[i]) && ((m_paths[i]->address().family() == inetAddressFamily) && (m_paths[i]->address().ipScope() == scope))) { + const unsigned int bytes = probe(tPtr, m_paths[i]->localSocket(), m_paths[i]->address(), now); + m_paths[i]->sent(now, bytes); + sent(now,bytes); + } } } bool Peer::directlyConnected(int64_t now) { - if ((now - _lastPrioritizedPaths) > ZT_PEER_PRIORITIZE_PATHS_INTERVAL) { - RWMutex::Lock l(_lock); - _prioritizePaths(now); - return _alivePathCount > 0; + if ((now - m_lastPrioritizedPaths) > ZT_PEER_PRIORITIZE_PATHS_INTERVAL) { + RWMutex::Lock l(m_lock); + m_prioritizePaths(now); + return m_alivePathCount > 0; } else { - RWMutex::RLock l(_lock); - return _alivePathCount > 0; + RWMutex::RLock l(m_lock); + return m_alivePathCount > 0; } } void Peer::getAllPaths(std::vector< SharedPtr > &paths) { - RWMutex::RLock l(_lock); + RWMutex::RLock l(m_lock); paths.clear(); - paths.assign(_paths,_paths + _alivePathCount); + paths.assign(m_paths, m_paths + m_alivePathCount); } void Peer::save(void *tPtr) const @@ -312,179 +377,48 @@ void Peer::save(void *tPtr) const const int len = marshal(buf + 8); if (len > 0) { uint64_t id[2]; - id[0] = _id.address().toInt(); + id[0] = m_id.address().toInt(); id[1] = 0; RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_PEER,id,buf,(unsigned int)len + 8); } } -void Peer::tryToContactAt(void *const tPtr,const Endpoint &ep,const int64_t now,const bool bfg1024) -{ - static uint8_t junk = 0; - - if (ep.inetAddr()) { // only this endpoint type is currently implemented - if (!RR->node->shouldUsePathForZeroTierTraffic(tPtr,_id,-1,ep.inetAddr())) - return; - - // Sending a packet with a low TTL before the real message assists traversal with some - // stateful firewalls and is harmless otherwise AFAIK. - ++junk; - RR->node->putPacket(tPtr,-1,ep.inetAddr(),&junk,1,2); - - // In a few hundred milliseconds we'll send the real packet. - { - RWMutex::Lock l(_lock); - _contactQueue.push_back(_ContactQueueItem(ep.inetAddr(),ZT_MAX_PEER_NETWORK_PATHS)); // NOLINT(hicpp-use-emplace,modernize-use-emplace) - } - - // If the peer indicates that they may be behind a symmetric NAT and there are no - // living direct paths, try a few more aggressive things. - if ((ep.inetAddr().family() == AF_INET) && (!directlyConnected(now))) { - unsigned int port = ep.inetAddr().port(); - if ((bfg1024)&&(port < 1024)&&(RR->node->natMustDie())) { - // If the other side is using a low-numbered port and has elected to - // have this done, we can try scanning every port below 1024. The search - // space here is small enough that we have a very good chance of punching. - - // Generate a random order list of all <1024 ports except 0 and the original sending port. - uint16_t ports[1022]; - uint16_t ctr = 1; - for (int i=0;i<1022;++i) { // NOLINT(modernize-loop-convert) - if (ctr == port) ++ctr; - ports[i] = ctr++; - } - for (int i=0;i<512;++i) { - uint64_t rn = Utils::random(); - unsigned int a = ((unsigned int)rn) % 1022; - unsigned int b = ((unsigned int)(rn >> 24U)) % 1022; - if (a != b) { - uint16_t tmp = ports[a]; - ports[a] = ports[b]; - ports[b] = tmp; - } - } - - // Chunk ports into chunks of 128 to try in few hundred millisecond intervals, - // abandoning attempts once there is at least one direct path. - { - static_assert((896 % ZT_PEER_BFG1024_PORT_SCAN_CHUNK_SIZE) == 0,"port scan chunk size doesn't evenly divide port list"); - static_assert((1022 - 896) <= ZT_PEER_BFG1024_PORT_SCAN_CHUNK_SIZE,"port scan chunk size needs to be adjusted"); - RWMutex::Lock l(_lock); - for (int i=0;i<896;i+=ZT_PEER_BFG1024_PORT_SCAN_CHUNK_SIZE) - _contactQueue.push_back(_ContactQueueItem(ep.inetAddr(),ports + i,ports + i + ZT_PEER_BFG1024_PORT_SCAN_CHUNK_SIZE,1)); // NOLINT(hicpp-use-emplace,modernize-use-emplace) - _contactQueue.push_back(_ContactQueueItem(ep.inetAddr(),ports + 896,ports + 1022,1)); // NOLINT(hicpp-use-emplace,modernize-use-emplace) - } - } else { - // Otherwise use the simpler sequential port attempt method in intervals. - RWMutex::Lock l(_lock); - for (int k=0;k<3;++k) { - if (++port > 65535) break; - InetAddress tryNext(ep.inetAddr()); - tryNext.setPort(port); - _contactQueue.push_back(_ContactQueueItem(tryNext,1)); // NOLINT(hicpp-use-emplace,modernize-use-emplace) - } - } - } - - // Start alarms going off to actually send these... - RR->node->setPeerAlarm(_id.fingerprint(),now + ZT_NAT_TRAVERSAL_INTERVAL); - } -} - -void Peer::alarm(void *tPtr,const int64_t now) -{ - // Right now alarms are only used for multi-phase or multi-step NAT traversal operations. - - // Pop one contact queue item and also clean the queue of any that are no - // longer applicable because the alive path count has exceeded their threshold. - bool stillHaveContactQueueItems; - _ContactQueueItem qi; - { - RWMutex::Lock l(_lock); - - if (_contactQueue.empty()) - return; - while (_alivePathCount >= _contactQueue.front().alivePathThreshold) { - _contactQueue.pop_front(); - if (_contactQueue.empty()) - return; - } - - _ContactQueueItem &qi2 = _contactQueue.front(); - qi.address = qi2.address; - qi.ports = qi2.ports; - qi.alivePathThreshold = qi2.alivePathThreshold; - _contactQueue.pop_front(); - - for(std::list< _ContactQueueItem,Utils::Mallocator<_ContactQueueItem> >::iterator q(_contactQueue.begin());q!=_contactQueue.end();) { // NOLINT(hicpp-use-auto,modernize-use-auto) - if (_alivePathCount >= q->alivePathThreshold) - _contactQueue.erase(q++); - else ++q; - } - - stillHaveContactQueueItems = !_contactQueue.empty(); - } - - if ((_vProto >= 11) && (_probe != 0)) { - if (qi.ports.empty()) { - RR->node->putPacket(tPtr,-1,qi.address,&_probe,ZT_PROTO_PROBE_LENGTH); - } else { - for (FCV::iterator p(qi.ports.begin()); p != qi.ports.end(); ++p) { // NOLINT(hicpp-use-auto,modernize-use-auto) - qi.address.setPort(*p); - RR->node->putPacket(tPtr,-1,qi.address,&_probe,ZT_PROTO_PROBE_LENGTH); - } - } - } else { - if (qi.ports.empty()) { - this->sendNOP(tPtr,-1,qi.address,now); - } else { - for (FCV::iterator p(qi.ports.begin()); p != qi.ports.end(); ++p) { // NOLINT(hicpp-use-auto,modernize-use-auto) - qi.address.setPort(*p); - this->sendNOP(tPtr,-1,qi.address,now); - } - } - } - - if (stillHaveContactQueueItems) - RR->node->setPeerAlarm(_id.fingerprint(),now + ZT_NAT_TRAVERSAL_INTERVAL); -} - int Peer::marshal(uint8_t data[ZT_PEER_MARSHAL_SIZE_MAX]) const noexcept { data[0] = 0; // serialized peer version - RWMutex::RLock l(_lock); + RWMutex::RLock l(m_lock); - int s = _identityKey.marshal(RR->localCacheSymmetric,data + 1); + int s = m_identityKey.marshal(RR->localCacheSymmetric, data + 1); if (s < 0) return -1; int p = 1 + s; - s = _id.marshal(data + p,false); + s = m_id.marshal(data + p, false); if (s < 0) return -1; p += s; - s = _locator.marshal(data + p); + s = m_locator.marshal(data + p); if (s <= 0) return s; p += s; - data[p++] = (uint8_t)_bootstrap.size(); - for(std::map< Endpoint::Type,Endpoint >::const_iterator i(_bootstrap.begin());i!=_bootstrap.end();++i) { // NOLINT(modernize-loop-convert,hicpp-use-auto,modernize-use-auto) + data[p++] = (uint8_t)m_bootstrap.size(); + for(std::map< Endpoint::Type,Endpoint >::const_iterator i(m_bootstrap.begin());i != m_bootstrap.end();++i) { // NOLINT(modernize-loop-convert,hicpp-use-auto,modernize-use-auto) s = i->second.marshal(data + p); if (s <= 0) return -1; p += s; } - Utils::storeBigEndian(data + p,(uint16_t)_vProto); + Utils::storeBigEndian(data + p,(uint16_t)m_vProto); p += 2; - Utils::storeBigEndian(data + p,(uint16_t)_vMajor); + Utils::storeBigEndian(data + p,(uint16_t)m_vMajor); p += 2; - Utils::storeBigEndian(data + p,(uint16_t)_vMinor); + Utils::storeBigEndian(data + p,(uint16_t)m_vMinor); p += 2; - Utils::storeBigEndian(data + p,(uint16_t)_vRevision); + Utils::storeBigEndian(data + p,(uint16_t)m_vRevision); p += 2; data[p++] = 0; @@ -495,12 +429,12 @@ int Peer::marshal(uint8_t data[ZT_PEER_MARSHAL_SIZE_MAX]) const noexcept int Peer::unmarshal(const uint8_t *restrict data,const int len) noexcept { - RWMutex::Lock l(_lock); + RWMutex::Lock l(m_lock); if ((len <= 1) || (data[0] != 0)) return -1; - int s = _identityKey.unmarshal(RR->localCacheSymmetric,data + 1,len); + int s = m_identityKey.unmarshal(RR->localCacheSymmetric, data + 1, len); if (s < 0) return -1; int p = 1 + s; @@ -509,24 +443,24 @@ int Peer::unmarshal(const uint8_t *restrict data,const int len) noexcept // identity has changed. In this case we do not have to forget everything about // the peer but we must generate a new identity key by key agreement with our // new identity. - if (!_identityKey) { + if (!m_identityKey) { uint8_t tmp[ZT_SYMMETRIC_KEY_SIZE]; - if (!RR->identity.agree(_id,tmp)) + if (!RR->identity.agree(m_id, tmp)) return -1; - _identityKey.init(RR->node->now(),tmp); + m_identityKey.init(RR->node->now(), tmp); Utils::burn(tmp,sizeof(tmp)); } // These are ephemeral and start out as NIL after unmarshal. - _ephemeralKeys[0].clear(); - _ephemeralKeys[1].clear(); + m_ephemeralKeys[0].clear(); + m_ephemeralKeys[1].clear(); - s = _id.unmarshal(data + 38,len - 38); + s = m_id.unmarshal(data + 38, len - 38); if (s < 0) return s; p += s; - s = _locator.unmarshal(data + p,len - p); + s = m_locator.unmarshal(data + p, len - p); if (s < 0) return s; p += s; @@ -536,24 +470,24 @@ int Peer::unmarshal(const uint8_t *restrict data,const int len) noexcept const unsigned int bootstrapCount = data[p++]; if (bootstrapCount > ZT_MAX_PEER_NETWORK_PATHS) return -1; - _bootstrap.clear(); + m_bootstrap.clear(); for(unsigned int i=0;i len) return -1; - _vProto = Utils::loadBigEndian(data + p); p += 2; - _vMajor = Utils::loadBigEndian(data + p); p += 2; - _vMinor = Utils::loadBigEndian(data + p); p += 2; - _vRevision = Utils::loadBigEndian(data + p); p += 2; + m_vProto = Utils::loadBigEndian(data + p); p += 2; + m_vMajor = Utils::loadBigEndian(data + p); p += 2; + m_vMinor = Utils::loadBigEndian(data + p); p += 2; + m_vRevision = Utils::loadBigEndian(data + p); p += 2; p += 2 + (int)Utils::loadBigEndian(data + p); return (p > len) ? -1 : p; @@ -563,28 +497,28 @@ struct _PathPriorityComparisonOperator { ZT_INLINE bool operator()(const SharedPtr &a,const SharedPtr &b) const noexcept { - // Sort in order of last received time for receipt of anything over path, which prioritizes - // paths by aliveness. This will go away when we merge in multipath in favor of something - // much smarter. - return ( ((a)&&(a->lastIn() > 0)) && ((!b)||(b->lastIn() <= 0)||(a->lastIn() < b->lastIn())) ); + // Sort in descending order of most recent receive time. + return (a->lastIn() > b->lastIn()); } }; -void Peer::_prioritizePaths(const int64_t now) +void Peer::m_prioritizePaths(int64_t now) { // assumes _lock is locked for writing - _lastPrioritizedPaths = now; + m_lastPrioritizedPaths = now; - std::sort(_paths,_paths + ZT_MAX_PEER_NETWORK_PATHS,_PathPriorityComparisonOperator()); + if (m_alivePathCount > 0) { + // Sort paths in descending order of priority. + std::sort(m_paths, m_paths + m_alivePathCount, _PathPriorityComparisonOperator()); - for(unsigned int i=0;ialive(now))) { - _alivePathCount = i; - - for(;ialive(now))) { + m_alivePathCount = i; + for (;i < ZT_MAX_PEER_NETWORK_PATHS;++i) + m_paths[i].zero(); + break; + } } } } diff --git a/node/Peer.hpp b/node/Peer.hpp index 6585594e3..0c306e887 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -34,8 +34,6 @@ // version, identity, locator, bootstrap, version info, length of any additional fields #define ZT_PEER_MARSHAL_SIZE_MAX (1 + ZT_SYMMETRICKEY_MARSHAL_SIZE_MAX + ZT_IDENTITY_MARSHAL_SIZE_MAX + ZT_LOCATOR_MARSHAL_SIZE_MAX + 1 + (ZT_MAX_PEER_NETWORK_PATHS * ZT_ENDPOINT_MARSHAL_SIZE_MAX) + (2*4) + 2) -#define ZT_PEER_BFG1024_PORT_SCAN_CHUNK_SIZE 128 - namespace ZeroTier { class Topology; @@ -72,20 +70,20 @@ public: /** * @return This peer's ZT address (short for identity().address()) */ - ZT_INLINE Address address() const noexcept { return _id.address(); } + ZT_INLINE Address address() const noexcept { return m_id.address(); } /** * @return This peer's identity */ - ZT_INLINE const Identity &identity() const noexcept { return _id; } + ZT_INLINE const Identity &identity() const noexcept { return m_id; } /** * @return Copy of current locator */ ZT_INLINE Locator locator() const noexcept { - RWMutex::RLock l(_lock); - return _locator; + RWMutex::RLock l(m_lock); + return m_locator; } /** @@ -118,8 +116,8 @@ public: */ ZT_INLINE void sent(const int64_t now,const unsigned int bytes) noexcept { - _lastSend = now; - _outMeter.log(now,bytes); + m_lastSend = now; + m_outMeter.log(now, bytes); } /** @@ -130,7 +128,7 @@ public: */ ZT_INLINE void relayed(const int64_t now,const unsigned int bytes) noexcept { - _relayedMeter.log(now,bytes); + m_relayedMeter.log(now, bytes); } /** @@ -140,15 +138,15 @@ public: */ ZT_INLINE SharedPtr path(const int64_t now) noexcept { - if ((now - _lastPrioritizedPaths) > ZT_PEER_PRIORITIZE_PATHS_INTERVAL) { - RWMutex::Lock l(_lock); - _prioritizePaths(now); - if (_alivePathCount > 0) - return _paths[0]; + if ((now - m_lastPrioritizedPaths) > ZT_PEER_PRIORITIZE_PATHS_INTERVAL) { + RWMutex::Lock l(m_lock); + m_prioritizePaths(now); + if (m_alivePathCount > 0) + return m_paths[0]; } else { - RWMutex::RLock l(_lock); - if (_alivePathCount > 0) - return _paths[0]; + RWMutex::RLock l(m_lock); + if (m_alivePathCount > 0) + return m_paths[0]; } return SharedPtr(); } @@ -197,7 +195,7 @@ public: * @param now Current time * @return Number of bytes sent */ - unsigned int sendNOP(void *tPtr,int64_t localSocket,const InetAddress &atAddress,int64_t now); + unsigned int probe(void *tPtr,int64_t localSocket,const InetAddress &atAddress,int64_t now); /** * Ping this peer if needed and/or perform other periodic tasks. @@ -208,6 +206,15 @@ public: */ void pulse(void *tPtr,int64_t now,bool isRoot); + /** + * Add a potential candidate direct path to the P2P "try" queue. + * + * @param now Current time + * @param ep Endpoint to attempt to contact + * @param bfg1024 Use BFG1024 brute force symmetric NAT busting algorithm if applicable + */ + void tryDirectPath(int64_t now,const Endpoint &ep,bool breakSymmetricBFG1024); + /** * Reset paths within a given IP scope and address family * @@ -228,8 +235,9 @@ public: */ ZT_INLINE FCV bootstrap() const noexcept { + RWMutex::RLock l(m_lock); FCV r; - for(std::map< Endpoint::Type,Endpoint,std::less,Utils::Mallocator< std::pair > >::const_iterator i(_bootstrap.begin());i!=_bootstrap.end();++i) // NOLINT(hicpp-use-auto,modernize-use-auto,modernize-loop-convert) + for(SortedMap::const_iterator i(m_bootstrap.begin());i != m_bootstrap.end();++i) // NOLINT(hicpp-use-auto,modernize-use-auto,modernize-loop-convert) r.push_back(i->second); return r; } @@ -241,14 +249,14 @@ public: */ ZT_INLINE void setBootstrap(const Endpoint &ep) noexcept { - RWMutex::Lock l(_lock); - _bootstrap[ep.type()] = ep; + RWMutex::Lock l(m_lock); + m_bootstrap[ep.type()] = ep; } /** * @return Time of last receive of anything, whether direct or relayed */ - ZT_INLINE int64_t lastReceive() const noexcept { return _lastReceive; } + ZT_INLINE int64_t lastReceive() const noexcept { return m_lastReceive; } /** * @return Average latency of all direct paths or -1 if no direct paths or unknown @@ -257,9 +265,9 @@ public: { int ltot = 0; int lcnt = 0; - RWMutex::RLock l(_lock); - for(unsigned int i=0;i<_alivePathCount;++i) { - int lat = _paths[i]->latency(); + RWMutex::RLock l(m_lock); + for(unsigned int i=0;i < m_alivePathCount;++i) { + int lat = m_paths[i]->latency(); if (lat > 0) { ltot += lat; ++lcnt; @@ -286,17 +294,17 @@ public: */ ZT_INLINE void setRemoteVersion(unsigned int vproto,unsigned int vmaj,unsigned int vmin,unsigned int vrev) noexcept { - _vProto = (uint16_t)vproto; - _vMajor = (uint16_t)vmaj; - _vMinor = (uint16_t)vmin; - _vRevision = (uint16_t)vrev; + m_vProto = (uint16_t)vproto; + m_vMajor = (uint16_t)vmaj; + m_vMinor = (uint16_t)vmin; + m_vRevision = (uint16_t)vrev; } - ZT_INLINE unsigned int remoteVersionProtocol() const noexcept { return _vProto; } - ZT_INLINE unsigned int remoteVersionMajor() const noexcept { return _vMajor; } - ZT_INLINE unsigned int remoteVersionMinor() const noexcept { return _vMinor; } - ZT_INLINE unsigned int remoteVersionRevision() const noexcept { return _vRevision; } - ZT_INLINE bool remoteVersionKnown() const noexcept { return ((_vMajor > 0) || (_vMinor > 0) || (_vRevision > 0)); } + ZT_INLINE unsigned int remoteVersionProtocol() const noexcept { return m_vProto; } + ZT_INLINE unsigned int remoteVersionMajor() const noexcept { return m_vMajor; } + ZT_INLINE unsigned int remoteVersionMinor() const noexcept { return m_vMinor; } + ZT_INLINE unsigned int remoteVersionRevision() const noexcept { return m_vRevision; } + ZT_INLINE bool remoteVersionKnown() const noexcept { return ((m_vMajor > 0) || (m_vMinor > 0) || (m_vRevision > 0)); } /** * @return True if there is at least one alive direct path @@ -315,24 +323,6 @@ public: */ void save(void *tPtr) const; - /** - * Attempt to contact this peer at a physical address, subject to internal checks - * - * @param tPtr External user pointer we pass around - * @param ep Endpoint to attempt to contact - * @param now Current time - * @param bfg1024 Use BFG1024 brute force symmetric NAT busting algorithm if applicable - */ - void tryToContactAt(void *tPtr,const Endpoint &ep,int64_t now,bool bfg1024); - - /** - * Called by Node when an alarm set by this peer goes off - * - * @param tPtr External user pointer we pass around - * @param now Current time - */ - void alarm(void *tPtr,int64_t now); - // NOTE: peer marshal/unmarshal only saves/restores the identity, locator, most // recent bootstrap address, and version information. static constexpr int marshalSizeMax() noexcept { return ZT_PEER_MARSHAL_SIZE_MAX; } @@ -344,20 +334,8 @@ public: */ ZT_INLINE bool rateGateInboundWhoisRequest(const int64_t now) noexcept { - if ((now - _lastWhoisRequestReceived) >= ZT_PEER_WHOIS_RATE_LIMIT) { - _lastWhoisRequestReceived = now; - return true; - } - return false; - } - - /** - * Rate limit attempts in response to incoming short probe packets - */ - ZT_INLINE bool rateGateInboundProbe(const int64_t now) noexcept - { - if ((now - _lastProbeReceived) >= ZT_DIRECT_CONNECT_ATTEMPT_INTERVAL) { - _lastProbeReceived = now; + if ((now - m_lastWhoisRequestReceived) >= ZT_PEER_WHOIS_RATE_LIMIT) { + m_lastWhoisRequestReceived = now; return true; } return false; @@ -368,97 +346,82 @@ public: */ ZT_INLINE bool rateGateEchoRequest(const int64_t now) noexcept { - if ((now - _lastEchoRequestReceived) >= ZT_PEER_GENERAL_RATE_LIMIT) { - _lastEchoRequestReceived = now; + if ((now - m_lastEchoRequestReceived) >= ZT_PEER_GENERAL_RATE_LIMIT) { + m_lastEchoRequestReceived = now; return true; } return false; } private: - void _prioritizePaths(int64_t now); + void m_prioritizePaths(int64_t now); const RuntimeEnvironment *RR; // Read/write mutex for non-atomic non-const fields. - RWMutex _lock; + RWMutex m_lock; // The permanent identity key resulting from agreement between our identity and this peer's identity. - SymmetricKey< AES,0,0 > _identityKey; + SymmetricKey< AES,0,0 > m_identityKey; // Most recently successful (for decrypt) ephemeral key and one previous key. - SymmetricKey< AES,ZT_SYMMETRIC_KEY_TTL,ZT_SYMMETRIC_KEY_TTL_MESSAGES > _ephemeralKeys[2]; + SymmetricKey< AES,ZT_SYMMETRIC_KEY_TTL,ZT_SYMMETRIC_KEY_TTL_MESSAGES > m_ephemeralKeys[2]; - Identity _id; - Locator _locator; + Identity m_id; + Locator m_locator; // the last time something was sent or received from this peer (direct or indirect). - std::atomic _lastReceive; - std::atomic _lastSend; + std::atomic m_lastReceive; + std::atomic m_lastSend; // The last time we sent a full HELLO to this peer. - int64_t _lastSentHello; // only checked while locked + int64_t m_lastSentHello; // only checked while locked // The last time a WHOIS request was received from this peer (anti-DOS / anti-flood). - std::atomic _lastWhoisRequestReceived; + std::atomic m_lastWhoisRequestReceived; // The last time an ECHO request was received from this peer (anti-DOS / anti-flood). - std::atomic _lastEchoRequestReceived; - - // The last time a probe was received from this peer (for anti-DOS / anti-flood use). - std::atomic _lastProbeReceived; - - // The last time we tried to init P2P connectivity with this peer. - std::atomic _lastAttemptedP2PInit; + std::atomic m_lastEchoRequestReceived; // The last time we sorted paths in order of preference. (This happens pretty often.) - std::atomic _lastPrioritizedPaths; - - // The last time we opened a can of whupass against this peer's NAT (if enabled). - std::atomic _lastAttemptedAggressiveNATTraversal; + std::atomic m_lastPrioritizedPaths; // Meters measuring actual bandwidth in, out, and relayed via this peer (mostly if this is a root). - Meter<> _inMeter; - Meter<> _outMeter; - Meter<> _relayedMeter; + Meter<> m_inMeter; + Meter<> m_outMeter; + Meter<> m_relayedMeter; + + // Direct paths sorted in descending order of preference. + SharedPtr m_paths[ZT_MAX_PEER_NETWORK_PATHS]; // For SharedPtr<> std::atomic __refCount; - // Direct paths sorted in descending order of preference. - SharedPtr _paths[ZT_MAX_PEER_NETWORK_PATHS]; - // Number of paths current alive (number of non-NULL entries in _paths). - unsigned int _alivePathCount; - - // Queue of batches of one or more physical addresses to try at some point in the future (for NAT traversal logic). - struct _ContactQueueItem - { - ZT_INLINE _ContactQueueItem() {} // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init,hicpp-use-equals-default,modernize-use-equals-default) - ZT_INLINE _ContactQueueItem(const InetAddress &a,const uint16_t *pstart,const uint16_t *pend,const unsigned int apt) : - address(a), - ports(pstart,pend), - alivePathThreshold(apt) {} - ZT_INLINE _ContactQueueItem(const InetAddress &a,const unsigned int apt) : - address(a), - ports(), - alivePathThreshold(apt) {} - InetAddress address; - FCV ports; // if non-empty try these ports, otherwise use the one in address - unsigned int alivePathThreshold; // skip and forget if alive path count is >= this - }; - List<_ContactQueueItem> _contactQueue; + unsigned int m_alivePathCount; // Remembered addresses by endpoint type (std::map is smaller for only a few keys). - std::map< Endpoint::Type,Endpoint,std::less,Utils::Mallocator< std::pair > > _bootstrap; + SortedMap m_bootstrap; + + // Addresses recieved via PUSH_DIRECT_PATHS etc. that we are scheduled to try. + struct p_TryQueueItem + { + ZT_INLINE p_TryQueueItem() : target(), ts(0), breakSymmetricBFG1024(false) {} + ZT_INLINE p_TryQueueItem(const int64_t now, const Endpoint &t, const bool bfg) : target(t), ts(now), breakSymmetricBFG1024(bfg) {} + Endpoint target; + int64_t ts; + bool breakSymmetricBFG1024; + }; + List m_tryQueue; + List::iterator m_tryQueuePtr; // loops over _tryQueue like a circular buffer // 32-bit probe or 0 if unknown. - uint32_t _probe; + uint32_t m_probe; - uint16_t _vProto; - uint16_t _vMajor; - uint16_t _vMinor; - uint16_t _vRevision; + uint16_t m_vProto; + uint16_t m_vMajor; + uint16_t m_vMinor; + uint16_t m_vRevision; }; } // namespace ZeroTier diff --git a/node/Protocol.hpp b/node/Protocol.hpp index 968e81567..2ff4cdc21 100644 --- a/node/Protocol.hpp +++ b/node/Protocol.hpp @@ -24,8 +24,6 @@ #include "Identity.hpp" /* - * Core ZeroTier protocol packet formats ------------------------------------------------------------------------------ - * * Packet format: * <[8] 64-bit packet ID / crypto IV> * <[5] destination ZT address> @@ -77,8 +75,6 @@ * Fragments do not carry their own packet MAC. The entire packet is * authenticated once it is assembled by the receiver. Incomplete packets * are discarded after a receiver configured period of time. - * - * -------------------------------------------------------------------------------------------------------------------- */ /* @@ -112,14 +108,13 @@ * 11 - 2.0.0 ... CURRENT * + New more WAN-efficient P2P-assisted multicast algorithm * + HELLO and OK(HELLO) include an extra HMAC to harden authentication - * + HELLO and OK(HELLO) can carry structured meta-data - * + Ephemeral keys for forward secrecy and limited key lifetime + * + HELLO and OK(HELLO) carry meta-data in a dictionary that's encrypted + * + Forward secrecy, key lifetime management * + Old planet/moon stuff is DEAD! Independent roots are easier. - * + AES encryption is now the default + * + AES encryption with the SIV construction AES-GMAC-SIV * + New combined Curve25519/NIST P-384 identity type (type 1) * + Short probe packets to reduce probe bandwidth - * + Aggressive NAT traversal techniques for IPv4 symmetric NATs - * + Remote diagnostics including rewrite of remote tracing + * + More aggressive NAT traversal techniques for IPv4 symmetric NATs */ #define ZT_PROTO_VERSION 11 @@ -158,12 +153,12 @@ #define ZT_PROTO_MAX_HOPS 7 /** - * NONE/Poly1305 (using Salsa20/12 to generate poly1305 key) + * NONE/Poly1305 (legacy) */ #define ZT_PROTO_CIPHER_SUITE__POLY1305_NONE 0 /** - * Salsa2012/Poly1305 + * Salsa2012/Poly1305 (legacy) */ #define ZT_PROTO_CIPHER_SUITE__POLY1305_SALSA2012 1 @@ -179,7 +174,7 @@ #define ZT_PROTO_CIPHER_SUITE__NONE 2 /** - * AES-GMAC-SIV (AES-256) + * AES-GMAC-SIV */ #define ZT_PROTO_CIPHER_SUITE__AES_GMAC_SIV 3 @@ -229,62 +224,41 @@ #define ZT_PROTO_VERB_FLAG_COMPRESSED 0x80U /** - * Mask to extract just the verb from the verb field, which also includes flags + * Mask to extract just the verb from the verb / verb flags field */ #define ZT_PROTO_VERB_MASK 0x1fU /** - * Key derivation function label for the keys used with HMAC-384 in HELLO - * - * With the KDF the 'iter' parameter is 0 for the key used for - * HMAC in HELLO and 1 for the one used in OK(HELLO). + * AES-GMAC-SIV first of two keys */ -#define ZT_PROTO_KDF_KEY_LABEL_HELLO_HMAC 'H' +#define ZT_KBKDF_LABEL_AES_GMAC_SIV_K0 '0' /** - * HELLO exchange meta-data: random 128-bit identifier for each running instance + * AES-GMAC-SIV second of two keys */ -#define ZT_PROTO_HELLO_NODE_META_INSTANCE_ID "i" +#define ZT_KBKDF_LABEL_AES_GMAC_SIV_K1 '1' /** - * HELLO exchange meta-data: signed locator for this node + * Key used to encrypt dictionary in HELLO with AES-CTR. */ -#define ZT_PROTO_HELLO_NODE_META_LOCATOR "l" +#define ZT_KBKDF_LABEL_HELLO_DICTIONARY_ENCRYPT 'H' /** - * HELLO exchange meta-data: ephemeral C25519 public key + * Key used for extra HMAC-SHA384 authentication on some packets. */ -#define ZT_PROTO_HELLO_NODE_META_EPHEMERAL_C25519 "e0" +#define ZT_KBKDF_LABEL_PACKET_HMAC 'M' -/** - * HELLO exchange meta-data: ephemeral NIST P-384 public key - */ -#define ZT_PROTO_HELLO_NODE_META_EPHEMERAL_P384 "e1" - -/** - * HELLO exchange meta-data: address(es) of nodes to whom this node will relay - */ -#define ZT_PROTO_HELLO_NODE_META_NEIGHBORS "wr" - -/** - * HELLO exchange meta-data: X coordinate of your node (sent in OK(HELLO)) - */ -#define ZT_PROTO_HELLO_NODE_META_LOCATION_X "gX" - -/** - * HELLO exchange meta-data: Y coordinate of your node (sent in OK(HELLO)) - */ -#define ZT_PROTO_HELLO_NODE_META_LOCATION_Y "gY" - -/** - * HELLO exchange meta-data: Z coordinate of your node (sent in OK(HELLO)) - */ -#define ZT_PROTO_HELLO_NODE_META_LOCATION_Z "gZ" - -/** - * HELLO exchange meta-data: preferred cipher suite (may be ignored) - */ -#define ZT_PROTO_HELLO_NODE_META_PREFERRED_CIPHER_SUITE "c" +#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" namespace ZeroTier { namespace Protocol { @@ -309,42 +283,48 @@ enum Verb * <[1] software major version (LEGACY)> * <[1] software minor version (LEGACY)> * <[2] software revision (LEGACY)> - * <[8] timestamp for determining latency (LEGACY)> - * <[...] binary serialized identity> + * <[8] timestamp> + * <[...] binary serialized full sender identity> * <[...] physical destination address of packet (LEGACY)> * <[2] 16-bit reserved "encrypted zero" field (LEGACY)> + * <[4] 32 additional random nonce bits> + * [... start of encrypted section ...] + * <[2] 16-bit length of encrypted dictionary> * <[...] encrypted dictionary> - * <[2] 16-bit length of preceding encrypted dictionary> - * <[48] HMAC-SHA384 of plaintext packet (with hops masked to 0)> + * [... end of encrypted section ...] + * <[48] HMAC-SHA384 of plaintext packet> * - * HELLO is sent to initiate a new pairing between two nodes. + * HELLO is sent to initiate a new pairing between two nodes and + * periodically to refresh information. * - * HELLO is the only packet ever sent without normal payload encryption, + * HELLO is the only packet ever sent without whole payload encryption, * though an inner encrypted envelope exists to obscure all fields that - * do not need to be sent in the clear. HELLO's MAC field contains a - * Poly1305 MAC for backward compatibility, and v2.x adds an additional - * HMAC-SHA384 at the end for stronger authentication of sessions. HELLO - * authentication is performed using the long-lived identity key only, - * and the encryption of the inner dictionary field is done using a key - * derived from this identity key explicitly for this purpose. + * do not need to be sent in the clear. There is nothing in this + * encrypted section that would be catastrophic if it leaked, but it's + * good to proactively limit exposed information. * - * The main payload of HELLO is the protocol version and the full identity - * of the sender, which includes the sender's public key(s). An encrypted - * dictionary (key/value store) is also included for additional information. - * This is encrypted using AES-CTR with a derived key and using the final - * 96 bits of the packet's HMAC-SHA384 as the CTR IV. (The HMAC authenticates - * the packet prior to this field being encrypted, making this a SIV - * construction much like AES-GMAC-SIV.) + * Inner encryption is AES-CTR with a key derived using KBKDF and a + * label indicating this specific usage. The 96-bit CTR nonce is the + * packet ID followed by the additional 32 random bits provided before + * the encrypted section. * - * The length of the dictionary field is included immediately after it so - * that it can be decrypted and the HMAC validated without performing any - * parsing of anything else, since it's a good idea to authenticate any - * message as early as possible in any secure protocol. + * Authentication and encryption in HELLO and OK(HELLO) are always done + * with the long-lived identity key, not ephemeral shared keys. This + * is so ephemeral key negotiation can always occur on the first try + * even if things get out of sync e.g. by one side restarting. Nothing + * in HELLO is likely to be dangerous if decrypted later. * - * V1.x will ignore the HMAC and dictionary fields as it doesn't understand - * them, but the packet is constructed so that 1.x nodes will parse what - * they need to communicate with 2.x nodes (without forward secrecy) as long - * as we wish to support this. + * HELLO and OK(HELLO) include an extra HMAC at the end of the packet. + * This authenticates them to a level of certainty beyond that afforded + * by regular AEAD. HMAC is computed over the whole packet prior to + * encryption/MAC and with the 3-bit hop count field masked as it is + * with regular packet AEAD, and it is then included in the regular + * packet MAC. + * + * LEGACY: for legacy reasons the MAC field of HELLO is a poly1305 + * MAC initialized in the same manner as 1.x. Since HMAC provides + * additional full 256-bit strength authentication this should not be + * a problem for FIPS. * * Several legacy fields are present as well for the benefit of 1.x nodes. * These will go away and become simple reserved space once 1.x is no longer @@ -354,49 +334,52 @@ enum Verb * old encrypted field is no longer there and that it should stop parsing * the packet at that point. * - * The following fields are nearly always present and must exist to support - * forward secrecy (in the case of the instance ID, keys, and key revision) - * or federated root membership (in the case of the locator). + * 1.x does not understand the dictionary and HMAC fields, but it will + * ignore them due to the "encrypted zero" field indicating that the + * packet contains no more information. + * + * Dictionary fields: + * + * The following fields are always present in HELLO: * - * TIMESTAMP - node's timestamp in milliseconds (supersedes legacy field) * INSTANCE_ID - a 64-bit unique value generated on each node start - * EPHEMERAL_C25519 - an ephemeral Curve25519 public key - * EPHEMERAL_P384 - an ephemeral NIST P-384 public key * LOCATOR - signed record enumerating this node's trusted contact points - * PROBE_TOKEN - 32-bit token that can be used to try to contact this peer + * PROBE_TOKEN - 32-bit probe token + * + * The following fields are used to establish forward secrecy: + * + * EPHEMERAL_C25519 - C25519 ephemeral public key (32 bytes) + * EPHEMERAL_P384 - NIST P-384 ephemneral public key (49 bytes) + * EPHEMERAL_REMOTE - SHA-384 of keys we have for peer (absent if none) * * The following optional fields may also be present: * * 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) - * LOC_X, LOC_Y, LOC_Z - location relative to the nearest large center of mass - * PEER_LOC_X, PEER_LOC_Y, PEER_LOC_Z - where sender thinks peer is located * 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 * COMPLIANCE - bit mask containing bits for e.g. a FIPS-compliant node * - * A valid and successfully authenticated HELLO will generate the following - * OK response. It contains an echo of the timestamp supplied by the - * initiating peer, the protocol version, and a dictionary containing - * the same information about the responding peer as the originating peer - * sent. + * The actual keys for these fields are in corresponding #defines by these + * names. * - * Note that OK(HELLO) as well as HELLO itself is always sent using the long - * lived identity key, not ephemeral keys. This allows ephemeral re-keying to - * always succeed if one side's ephemeral keys are out of date. + * The timestamp field in OK is echoed but the others represent the sender + * of the OK and are not echoes from HELLO. The dictionary in OK typically + * only contains the EPHEMERAL fields, allowing the receiver of the OK to + * confirm that both sides know the correct keys and thus begin using the + * ephemeral shared secret to send packets. * * OK payload: * <[8] timestamp echoed from original HELLO> - * <[1] protocol version> - * <[1] software major version (LEGACY)> - * <[1] software minor version (LEGACY)> - * <[2] software revision (LEGACY)> - * <[...] physical destination address of packet (LEGACY)> - * <[2] 16-bit reserved zero field (LEGACY)> + * <[1] protocol version of responding node> + * <[2] 16-bit length of dictionary> * <[...] dictionary> - * <[48] HMAC-SHA384 of plaintext packet (with hops masked to 0)> + * <[48] HMAC-SHA384 of plaintext packet> + * + * LEGACY: a legacy format OK will be sent to nodes with older protocol + * versions. */ VERB_HELLO = 0x01, @@ -416,7 +399,7 @@ enum Verb * Success response: * <[1] in-re verb> * <[8] in-re packet ID> - * <[...] request-specific payload> + * <[...] response-specific payload> */ VERB_OK = 0x03, @@ -693,26 +676,14 @@ enum Verb * * Path record format: * <[1] 8-bit path flags> - * <[2] length of extended path characteristics or 0 for none> - * <[...] extended path characteristics> + * <[2] length of extended path data or 0 for none> + * <[...] extended path data> * <[1] address type> * <[1] address record length in bytes> * <[...] address> * * Path flags: - * 0x01 - Sender is likely behind a symmetric NAT - * 0x02 - Use BFG1024 algorithm for symmetric NAT-t if conditions met - * - * The receiver may, upon receiving a push, attempt to establish a - * direct link to one or more of the indicated addresses. It is the - * responsibility of the sender to limit which peers it pushes direct - * paths to to those with whom it has a trust relationship. The receiver - * must obey any restrictions provided such as exclusivity or blacklists. - * OK responses to this message are optional. - * - * Note that a direct path push does not imply that learned paths can't - * be used unless they are blacklisted explicitly or unless flag 0x01 - * is set. + * 0x01 - BFG1024 symmetric NAT-t requested * * OK and ERROR are not generated. */ @@ -754,11 +725,9 @@ enum Verb * * Encapsulation exists to enable secure relaying as opposed to the usual * "dumb" relaying. The latter is faster but secure relaying has roles - * where endpoint privacy is desired. Multiply nested ENCAP packets - * could allow ZeroTier to act as an onion router. + * where endpoint privacy is desired. * - * When encapsulated packets are forwarded they do have their hop count - * field incremented. + * Packet hop count is incremented as normal. */ VERB_ENCAP = 0x17 diff --git a/node/Revocation.cpp b/node/Revocation.cpp index 4e6bb009b..a21111cc0 100644 --- a/node/Revocation.cpp +++ b/node/Revocation.cpp @@ -19,8 +19,8 @@ bool Revocation::sign(const Identity &signer) noexcept { uint8_t buf[ZT_REVOCATION_MARSHAL_SIZE_MAX+32]; if (signer.hasPrivate()) { - _signedBy = signer.address(); - _signatureLength = signer.sign(buf,(unsigned int)marshal(buf,true),_signature,sizeof(_signature)); + m_signedBy = signer.address(); + m_signatureLength = signer.sign(buf, (unsigned int)marshal(buf, true), m_signature, sizeof(m_signature)); return true; } return false; @@ -34,20 +34,20 @@ int Revocation::marshal(uint8_t data[ZT_REVOCATION_MARSHAL_SIZE_MAX],bool forSig data[p++] = 0x7f; } Utils::storeBigEndian(data + p,0); p += 4; - Utils::storeBigEndian(data + p,_id); p += 4; - Utils::storeBigEndian(data + p,_networkId); p += 8; + Utils::storeBigEndian(data + p, m_id); p += 4; + Utils::storeBigEndian(data + p, m_networkId); p += 8; Utils::storeBigEndian(data + p,0); p += 4; - Utils::storeBigEndian(data + p,_credentialId); p += 4; - Utils::storeBigEndian(data + p,(uint64_t)_threshold); p += 8; - Utils::storeBigEndian(data + p,_flags); p += 8; - _target.copyTo(data + p); p += ZT_ADDRESS_LENGTH; - _signedBy.copyTo(data + p); p += ZT_ADDRESS_LENGTH; - data[p++] = (uint8_t)_type; + Utils::storeBigEndian(data + p, m_credentialId); p += 4; + Utils::storeBigEndian(data + p,(uint64_t)m_threshold); p += 8; + Utils::storeBigEndian(data + p, m_flags); p += 8; + m_target.copyTo(data + p); p += ZT_ADDRESS_LENGTH; + m_signedBy.copyTo(data + p); p += ZT_ADDRESS_LENGTH; + data[p++] = (uint8_t)m_type; if (!forSign) { data[p++] = 1; - Utils::storeBigEndian(data + p,(uint16_t)_signatureLength); - Utils::copy(data + p,_signature,_signatureLength); - p += (int)_signatureLength; + Utils::storeBigEndian(data + p,(uint16_t)m_signatureLength); + Utils::copy(data + p, m_signature, m_signatureLength); + p += (int)m_signatureLength; } data[p++] = 0; data[p++] = 0; @@ -63,21 +63,21 @@ int Revocation::unmarshal(const uint8_t *restrict data,const int len) noexcept if (len < 54) return -1; // 4 bytes reserved - _id = Utils::loadBigEndian(data + 4); - _networkId = Utils::loadBigEndian(data + 8); + m_id = Utils::loadBigEndian(data + 4); + m_networkId = Utils::loadBigEndian(data + 8); // 4 bytes reserved - _credentialId = Utils::loadBigEndian(data + 20); - _threshold = (int64_t)Utils::loadBigEndian(data + 24); - _flags = Utils::loadBigEndian(data + 32); - _target.setTo(data + 40); - _signedBy.setTo(data + 45); - _type = (ZT_CredentialType)data[50]; + m_credentialId = Utils::loadBigEndian(data + 20); + m_threshold = (int64_t)Utils::loadBigEndian(data + 24); + m_flags = Utils::loadBigEndian(data + 32); + m_target.setTo(data + 40); + m_signedBy.setTo(data + 45); + m_type = (ZT_CredentialType)data[50]; // 1 byte reserved - _signatureLength = Utils::loadBigEndian(data + 52); - int p = 54 + (int)_signatureLength; - if ((_signatureLength > ZT_SIGNATURE_BUFFER_SIZE)||(p > len)) + m_signatureLength = Utils::loadBigEndian(data + 52); + int p = 54 + (int)m_signatureLength; + if ((m_signatureLength > ZT_SIGNATURE_BUFFER_SIZE) || (p > len)) return -1; - Utils::copy(_signature,data + 54,_signatureLength); + Utils::copy(m_signature, data + 54, m_signatureLength); if ((p + 2) > len) return -1; p += 2 + Utils::loadBigEndian(data + p); diff --git a/node/Revocation.hpp b/node/Revocation.hpp index 91ba14e77..f7749280f 100644 --- a/node/Revocation.hpp +++ b/node/Revocation.hpp @@ -59,28 +59,28 @@ public: * @param ct Credential type being revoked */ ZT_INLINE Revocation(const uint32_t i,const uint64_t nwid,const uint32_t cid,const uint64_t thr,const uint64_t fl,const Address &tgt,const ZT_CredentialType ct) noexcept : // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init) - _id(i), - _credentialId(cid), - _networkId(nwid), - _threshold(thr), - _flags(fl), - _target(tgt), - _signedBy(), - _type(ct), - _signatureLength(0) + m_id(i), + m_credentialId(cid), + m_networkId(nwid), + m_threshold(thr), + m_flags(fl), + m_target(tgt), + m_signedBy(), + m_type(ct), + m_signatureLength(0) { } - ZT_INLINE uint32_t id() const noexcept { return _id; } - ZT_INLINE uint32_t credentialId() const noexcept { return _credentialId; } - ZT_INLINE uint64_t networkId() const noexcept { return _networkId; } - ZT_INLINE int64_t threshold() const noexcept { return _threshold; } - ZT_INLINE const Address &target() const noexcept { return _target; } - ZT_INLINE const Address &signer() const noexcept { return _signedBy; } - ZT_INLINE ZT_CredentialType typeBeingRevoked() const noexcept { return _type; } - ZT_INLINE const uint8_t *signature() const noexcept { return _signature; } - ZT_INLINE unsigned int signatureLength() const noexcept { return _signatureLength; } - ZT_INLINE bool fastPropagate() const noexcept { return ((_flags & ZT_REVOCATION_FLAG_FAST_PROPAGATE) != 0); } + ZT_INLINE uint32_t id() const noexcept { return m_id; } + ZT_INLINE uint32_t credentialId() const noexcept { return m_credentialId; } + ZT_INLINE uint64_t networkId() const noexcept { return m_networkId; } + ZT_INLINE int64_t threshold() const noexcept { return m_threshold; } + ZT_INLINE const Address &target() const noexcept { return m_target; } + ZT_INLINE const Address &signer() const noexcept { return m_signedBy; } + ZT_INLINE ZT_CredentialType typeBeingRevoked() const noexcept { return m_type; } + ZT_INLINE const uint8_t *signature() const noexcept { return m_signature; } + ZT_INLINE unsigned int signatureLength() const noexcept { return m_signatureLength; } + ZT_INLINE bool fastPropagate() const noexcept { return ((m_flags & ZT_REVOCATION_FLAG_FAST_PROPAGATE) != 0); } /** * @param signer Signing identity, must have private key @@ -101,16 +101,16 @@ public: int unmarshal(const uint8_t *restrict data,int len) noexcept; private: - uint32_t _id; - uint32_t _credentialId; - uint64_t _networkId; - int64_t _threshold; - uint64_t _flags; - Address _target; - Address _signedBy; - ZT_CredentialType _type; - unsigned int _signatureLength; - uint8_t _signature[ZT_SIGNATURE_BUFFER_SIZE]; + uint32_t m_id; + uint32_t m_credentialId; + uint64_t m_networkId; + int64_t m_threshold; + uint64_t m_flags; + Address m_target; + Address m_signedBy; + ZT_CredentialType m_type; + unsigned int m_signatureLength; + uint8_t m_signature[ZT_SIGNATURE_BUFFER_SIZE]; }; } // namespace ZeroTier diff --git a/node/ScopedPtr.hpp b/node/ScopedPtr.hpp index fecbd5fd4..c1f40f3ae 100644 --- a/node/ScopedPtr.hpp +++ b/node/ScopedPtr.hpp @@ -28,32 +28,32 @@ template class ScopedPtr : public TriviallyCopyable { public: - explicit ZT_INLINE ScopedPtr(T *const p) noexcept : _p(p) {} - ZT_INLINE ~ScopedPtr() { delete _p; } + explicit ZT_INLINE ScopedPtr(T *const p) noexcept : m_ptr(p) {} + ZT_INLINE ~ScopedPtr() { delete m_ptr; } - ZT_INLINE T *operator->() const noexcept { return _p; } - ZT_INLINE T &operator*() const noexcept { return *_p; } - explicit ZT_INLINE operator bool() const noexcept { return (_p != (T *)0); } - ZT_INLINE T *ptr() const noexcept { return _p; } + ZT_INLINE T *operator->() const noexcept { return m_ptr; } + ZT_INLINE T &operator*() const noexcept { return *m_ptr; } + explicit ZT_INLINE operator bool() const noexcept { return (m_ptr != (T *)0); } + ZT_INLINE T *ptr() const noexcept { return m_ptr; } ZT_INLINE void swap(const ScopedPtr &p) noexcept { - T *const tmp = _p; - _p = p._p; - p._p = tmp; + T *const tmp = m_ptr; + m_ptr = p.m_ptr; + p.m_ptr = tmp; } - ZT_INLINE bool operator==(const ScopedPtr &p) const noexcept { return (_p == p._p); } - ZT_INLINE bool operator!=(const ScopedPtr &p) const noexcept { return (_p != p._p); } - ZT_INLINE bool operator==(T *const p) const noexcept { return (_p == p); } - ZT_INLINE bool operator!=(T *const p) const noexcept { return (_p != p); } + ZT_INLINE bool operator==(const ScopedPtr &p) const noexcept { return (m_ptr == p.m_ptr); } + ZT_INLINE bool operator!=(const ScopedPtr &p) const noexcept { return (m_ptr != p.m_ptr); } + ZT_INLINE bool operator==(T *const p) const noexcept { return (m_ptr == p); } + ZT_INLINE bool operator!=(T *const p) const noexcept { return (m_ptr != p); } private: ZT_INLINE ScopedPtr() noexcept {} // NOLINT(hicpp-use-equals-default,hicpp-use-equals-delete,modernize-use-equals-default) - ZT_INLINE ScopedPtr(const ScopedPtr &p) noexcept : _p(nullptr) {} + ZT_INLINE ScopedPtr(const ScopedPtr &p) noexcept : m_ptr(nullptr) {} ZT_INLINE ScopedPtr &operator=(const ScopedPtr &p) noexcept { return *this; } - T *const _p; + T *const m_ptr; }; } // namespace ZeroTier diff --git a/node/SelfAwareness.cpp b/node/SelfAwareness.cpp index 59849fa70..8f70d1113 100644 --- a/node/SelfAwareness.cpp +++ b/node/SelfAwareness.cpp @@ -55,8 +55,8 @@ void SelfAwareness::iam(void *tPtr,const Identity &reporter,const int64_t receiv if ((scope != reporterPhysicalAddress.ipScope())||(scope == InetAddress::IP_SCOPE_NONE)||(scope == InetAddress::IP_SCOPE_LOOPBACK)||(scope == InetAddress::IP_SCOPE_MULTICAST)) return; - Mutex::Lock l(_phy_l); - PhySurfaceEntry &entry = _phy[PhySurfaceKey(reporter.address(),receivedOnLocalSocket,reporterPhysicalAddress,scope)]; + Mutex::Lock l(m_phy_l); + p_PhySurfaceEntry &entry = m_phy[p_PhySurfaceKey(reporter.address(), receivedOnLocalSocket, reporterPhysicalAddress, scope)]; if ( (trusted) && ((now - entry.ts) < ZT_SELFAWARENESS_ENTRY_TIMEOUT) && (!entry.mySurface.ipsEqual(myPhysicalAddress)) ) { // Changes to external surface reported by trusted peers causes path reset in this scope @@ -67,9 +67,9 @@ 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(_phy.begin());i!=_phy.end();) { // NOLINT(modernize-loop-convert,modernize-use-auto,hicpp-use-auto) + for(Map::iterator i(m_phy.begin());i != m_phy.end();) { // NOLINT(modernize-loop-convert,modernize-use-auto,hicpp-use-auto) if ((i->first.scope == scope)&&(i->first.reporterPhysicalAddress != reporterPhysicalAddress)) - _phy.erase(i++); + m_phy.erase(i++); else ++i; } @@ -88,10 +88,10 @@ void SelfAwareness::iam(void *tPtr,const Identity &reporter,const int64_t receiv void SelfAwareness::clean(int64_t now) { - Mutex::Lock l(_phy_l); - for(Map::iterator i(_phy.begin());i!=_phy.end();) { // NOLINT(modernize-loop-convert,modernize-use-auto,hicpp-use-auto) + 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) if ((now - i->second.ts) >= ZT_SELFAWARENESS_ENTRY_TIMEOUT) - _phy.erase(i++); + m_phy.erase(i++); else ++i; } } @@ -102,8 +102,8 @@ SelfAwareness::ExternalAddressList SelfAwareness::externalAddresses(const int64_ Map counts; { - Mutex::Lock l(_phy_l); - for(Map::const_iterator i(_phy.begin());i!=_phy.end();++i) { // NOLINT(modernize-loop-convert,modernize-use-auto,hicpp-use-auto) + 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) if ((now - i->second.ts) < ZT_SELFAWARENESS_ENTRY_TIMEOUT) ++counts[i->second.mySurface]; } diff --git a/node/SelfAwareness.hpp b/node/SelfAwareness.hpp index b0f4f308d..11625ff4f 100644 --- a/node/SelfAwareness.hpp +++ b/node/SelfAwareness.hpp @@ -20,8 +20,6 @@ #include "Address.hpp" #include "Mutex.hpp" -#include - namespace ZeroTier { class Identity; @@ -30,7 +28,7 @@ class RuntimeEnvironment; /** * SelfAwareness manages awareness of this peer's external address(es) and NAT situation. * - * This code should not be capable of achieving sentience and triggering the Terminator wars. + * Name aside, it shouldn't be capable of achieving sentience. */ class SelfAwareness { @@ -67,21 +65,21 @@ public: ExternalAddressList externalAddresses(int64_t now) const; private: - struct PhySurfaceKey + struct p_PhySurfaceKey { Address reporter; int64_t receivedOnLocalSocket; InetAddress reporterPhysicalAddress; InetAddress::IpScope scope; - ZT_INLINE PhySurfaceKey() noexcept {} // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init,hicpp-use-equals-default,modernize-use-equals-default) - ZT_INLINE PhySurfaceKey(const Address &r,const int64_t rol,const InetAddress &ra,InetAddress::IpScope s) noexcept : reporter(r),receivedOnLocalSocket(rol),reporterPhysicalAddress(ra),scope(s) {} + ZT_INLINE p_PhySurfaceKey() noexcept {} // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init,hicpp-use-equals-default,modernize-use-equals-default) + ZT_INLINE p_PhySurfaceKey(const Address &r, const int64_t rol, const InetAddress &ra, InetAddress::IpScope s) noexcept : reporter(r), receivedOnLocalSocket(rol), reporterPhysicalAddress(ra), scope(s) {} ZT_INLINE unsigned long hashCode() const noexcept { return ((unsigned long)reporter.toInt() + (unsigned long)receivedOnLocalSocket + (unsigned long)scope); } - ZT_INLINE bool operator==(const PhySurfaceKey &k) const noexcept { return ((reporter == k.reporter) && (receivedOnLocalSocket == k.receivedOnLocalSocket) && (reporterPhysicalAddress == k.reporterPhysicalAddress) && (scope == k.scope)); } - ZT_INLINE bool operator!=(const PhySurfaceKey &k) const noexcept { return (!(*this == k)); } - ZT_INLINE bool operator<(const PhySurfaceKey &k) const noexcept + ZT_INLINE bool operator==(const p_PhySurfaceKey &k) const noexcept { return ((reporter == k.reporter) && (receivedOnLocalSocket == k.receivedOnLocalSocket) && (reporterPhysicalAddress == k.reporterPhysicalAddress) && (scope == k.scope)); } + ZT_INLINE bool operator!=(const p_PhySurfaceKey &k) const noexcept { return (!(*this == k)); } + ZT_INLINE bool operator<(const p_PhySurfaceKey &k) const noexcept { if (reporter < k.reporter) { return true; @@ -100,19 +98,19 @@ private: } }; - struct PhySurfaceEntry + struct p_PhySurfaceEntry { InetAddress mySurface; uint64_t ts; bool trusted; - ZT_INLINE PhySurfaceEntry() noexcept : mySurface(),ts(0),trusted(false) {} - ZT_INLINE PhySurfaceEntry(const InetAddress &a,const uint64_t t) noexcept : mySurface(a),ts(t),trusted(false) {} + ZT_INLINE p_PhySurfaceEntry() noexcept : mySurface(), ts(0), trusted(false) {} + ZT_INLINE p_PhySurfaceEntry(const InetAddress &a, const uint64_t t) noexcept : mySurface(a), ts(t), trusted(false) {} }; const RuntimeEnvironment *RR; - Map< PhySurfaceKey,PhySurfaceEntry > _phy; - Mutex _phy_l; + Map< p_PhySurfaceKey,p_PhySurfaceEntry > m_phy; + Mutex m_phy_l; }; } // namespace ZeroTier diff --git a/node/SharedPtr.hpp b/node/SharedPtr.hpp index aa4bb9a53..c2ef5678f 100644 --- a/node/SharedPtr.hpp +++ b/node/SharedPtr.hpp @@ -30,27 +30,27 @@ template class SharedPtr : public TriviallyCopyable { public: - ZT_INLINE SharedPtr() noexcept : _ptr((T *)0) {} - explicit ZT_INLINE SharedPtr(T *obj) noexcept : _ptr(obj) { ++obj->__refCount; } - ZT_INLINE SharedPtr(const SharedPtr &sp) noexcept : _ptr(sp._getAndInc()) {} + ZT_INLINE SharedPtr() noexcept : m_ptr((T *)0) {} + explicit ZT_INLINE SharedPtr(T *obj) noexcept : m_ptr(obj) { ++obj->__refCount; } + ZT_INLINE SharedPtr(const SharedPtr &sp) noexcept : m_ptr(sp._getAndInc()) {} ZT_INLINE ~SharedPtr() { - if (_ptr) { - if (--_ptr->__refCount <= 0) - delete _ptr; + if (m_ptr) { + if (--m_ptr->__refCount <= 0) + delete m_ptr; } } ZT_INLINE SharedPtr &operator=(const SharedPtr &sp) { - if (_ptr != sp._ptr) { + if (m_ptr != sp.m_ptr) { T *p = sp._getAndInc(); - if (_ptr) { - if (--_ptr->__refCount <= 0) - delete _ptr; + if (m_ptr) { + if (--m_ptr->__refCount <= 0) + delete m_ptr; } - _ptr = p; + m_ptr = p; } return *this; } @@ -67,7 +67,7 @@ public: { zero(); ++ptr->__refCount; - _ptr = ptr; + m_ptr = ptr; } /** @@ -77,7 +77,7 @@ public: * * @param ptr Pointer to set */ - ZT_INLINE void unsafeSet(T *ptr) noexcept { _ptr = ptr; } + ZT_INLINE void unsafeSet(T *ptr) noexcept { m_ptr = ptr; } /** * Swap with another pointer 'for free' without ref count overhead @@ -86,9 +86,9 @@ public: */ ZT_INLINE void swap(SharedPtr &with) noexcept { - T *tmp = _ptr; - _ptr = with._ptr; - with._ptr = tmp; + T *tmp = m_ptr; + m_ptr = with.m_ptr; + with.m_ptr = tmp; } /** @@ -101,33 +101,33 @@ public: */ ZT_INLINE void move(SharedPtr &from) { - if (_ptr) { - if (--_ptr->__refCount <= 0) - delete _ptr; + if (m_ptr) { + if (--m_ptr->__refCount <= 0) + delete m_ptr; } - _ptr = from._ptr; - from._ptr = nullptr; + m_ptr = from.m_ptr; + from.m_ptr = nullptr; } - ZT_INLINE operator bool() const noexcept { return (_ptr != nullptr); } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) + ZT_INLINE operator bool() const noexcept { return (m_ptr != nullptr); } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) - ZT_INLINE T &operator*() const noexcept { return *_ptr; } - ZT_INLINE T *operator->() const noexcept { return _ptr; } + ZT_INLINE T &operator*() const noexcept { return *m_ptr; } + ZT_INLINE T *operator->() const noexcept { return m_ptr; } /** * @return Raw pointer to held object */ - ZT_INLINE T *ptr() const noexcept { return _ptr; } + ZT_INLINE T *ptr() const noexcept { return m_ptr; } /** * Set this pointer to NULL */ ZT_INLINE void zero() { - if (_ptr) { - if (--_ptr->__refCount <= 0) - delete _ptr; - _ptr = (T *)0; + if (m_ptr) { + if (--m_ptr->__refCount <= 0) + delete m_ptr; + m_ptr = (T *)0; } } @@ -136,26 +136,26 @@ public: */ ZT_INLINE int references() noexcept { - if (_ptr) - return _ptr->__refCount; + if (m_ptr) + return m_ptr->__refCount; return 0; } - ZT_INLINE bool operator==(const SharedPtr &sp) const noexcept { return (_ptr == sp._ptr); } - ZT_INLINE bool operator!=(const SharedPtr &sp) const noexcept { return (_ptr != sp._ptr); } - ZT_INLINE bool operator>(const SharedPtr &sp) const noexcept { return (_ptr > sp._ptr); } - ZT_INLINE bool operator<(const SharedPtr &sp) const noexcept { return (_ptr < sp._ptr); } - ZT_INLINE bool operator>=(const SharedPtr &sp) const noexcept { return (_ptr >= sp._ptr); } - ZT_INLINE bool operator<=(const SharedPtr &sp) const noexcept { return (_ptr <= sp._ptr); } + ZT_INLINE bool operator==(const SharedPtr &sp) const noexcept { return (m_ptr == sp.m_ptr); } + ZT_INLINE bool operator!=(const SharedPtr &sp) const noexcept { return (m_ptr != sp.m_ptr); } + ZT_INLINE bool operator>(const SharedPtr &sp) const noexcept { return (m_ptr > sp.m_ptr); } + ZT_INLINE bool operator<(const SharedPtr &sp) const noexcept { return (m_ptr < sp.m_ptr); } + ZT_INLINE bool operator>=(const SharedPtr &sp) const noexcept { return (m_ptr >= sp.m_ptr); } + ZT_INLINE bool operator<=(const SharedPtr &sp) const noexcept { return (m_ptr <= sp.m_ptr); } private: ZT_INLINE T *_getAndInc() const noexcept { - if (_ptr) - ++_ptr->__refCount; - return _ptr; + if (m_ptr) + ++m_ptr->__refCount; + return m_ptr; } - T *_ptr; + T *m_ptr; }; } // namespace ZeroTier diff --git a/node/Speck128.hpp b/node/Speck128.hpp index 541d674a2..124625944 100644 --- a/node/Speck128.hpp +++ b/node/Speck128.hpp @@ -26,7 +26,9 @@ namespace ZeroTier { * little-endian for higher performance on the majority of platforms. * * Right now this is only used as part of the PoW function for V1 identity - * generation. + * generation. It's used because it's faster than SHA for filling a buffer + * with randomness and unlike AES its relative performance advantage + * across CPU architectures is pretty much identical. * * @tparam R Number of rounds (default: 32) */ @@ -46,7 +48,7 @@ public: */ ZT_INLINE Speck128(const void *k) noexcept { this->init(k); } // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init,google-explicit-constructor,hicpp-explicit-conversions) - ZT_INLINE ~Speck128() { Utils::burn(_k,sizeof(_k)); } + ZT_INLINE ~Speck128() { Utils::burn(m_expandedKey, sizeof(m_expandedKey)); } /** * Initialize Speck from a 128-bit key @@ -66,14 +68,14 @@ public: */ ZT_INLINE void initXY(uint64_t x,uint64_t y) noexcept { - _k[0] = x; + m_expandedKey[0] = x; for(uint64_t i=0;i<(R-1);++i) { x = x >> 8U | x << 56U; x += y; x ^= i; y = y << 3U | y >> 61U; y ^= x; - _k[i + 1] = y; + m_expandedKey[i + 1] = y; } } @@ -89,7 +91,7 @@ public: ZT_INLINE void encryptXY(uint64_t &x,uint64_t &y) const noexcept { for (int i=0;i> 8U | x << 56U; x += y; x ^= kk; @@ -107,7 +109,7 @@ public: ZT_INLINE void encryptXYXYXYXY(uint64_t &x0,uint64_t &y0,uint64_t &x1,uint64_t &y1,uint64_t &x2,uint64_t &y2,uint64_t &x3,uint64_t &y3) const noexcept { for (int i=0;i> 8U | x0 << 56U; x1 = x1 >> 8U | x1 << 56U; x2 = x2 >> 8U | x2 << 56U; @@ -143,7 +145,7 @@ public: ZT_INLINE void decryptXY(uint64_t &x,uint64_t &y) const noexcept { for (int i=(R-1);i>=0;--i) { - const uint64_t kk = _k[i]; + const uint64_t kk = m_expandedKey[i]; y ^= x; y = y >> 3U | y << 61U; x ^= kk; @@ -183,7 +185,7 @@ public: } private: - uint64_t _k[R]; + uint64_t m_expandedKey[R]; }; } // namespace ZeroTier diff --git a/node/SymmetricKey.hpp b/node/SymmetricKey.hpp index 4e626abee..0a70e8999 100644 --- a/node/SymmetricKey.hpp +++ b/node/SymmetricKey.hpp @@ -49,11 +49,11 @@ public: */ ZT_INLINE SymmetricKey() noexcept : // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init,hicpp-use-equals-default,modernize-use-equals-default) cipher(), - _ts(0), - _nonceBase(0), - _odometer(0) + m_ts(0), + m_nonceBase(0), + m_odometer(0) { - Utils::memoryLock(_k,sizeof(_k)); + Utils::memoryLock(m_secret, sizeof(m_secret)); } /** @@ -64,38 +64,38 @@ public: */ explicit ZT_INLINE SymmetricKey(const int64_t ts,const void *const key) noexcept : // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init) cipher(key), - _ts(ts), - _nonceBase((uint64_t)ts << 22U), // << 22 to shift approximately the seconds since epoch into the most significant 32 bits - _odometer(0) + m_ts(ts), + m_nonceBase((uint64_t)ts << 22U), // << 22 to shift approximately the seconds since epoch into the most significant 32 bits + m_odometer(0) { - Utils::memoryLock(_k,sizeof(_k)); - Utils::copy(_k,key); + Utils::memoryLock(m_secret, sizeof(m_secret)); + Utils::copy(m_secret, key); } ZT_INLINE SymmetricKey(const SymmetricKey &k) noexcept : // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init) - cipher(k._k), - _ts(k.ts), - _nonceBase(k._nonceBase), - _odometer(k._odometer) + cipher(k.m_secret), + m_ts(k.ts), + m_nonceBase(k.m_nonceBase), + m_odometer(k.m_odometer) { - Utils::memoryLock(_k,sizeof(_k)); - Utils::copy(_k,k._k); + Utils::memoryLock(m_secret, sizeof(m_secret)); + Utils::copy(m_secret, k.m_secret); } ZT_INLINE ~SymmetricKey() noexcept { - Utils::burn(_k,sizeof(_k)); - Utils::memoryUnlock(_k,sizeof(_k)); + Utils::burn(m_secret, sizeof(m_secret)); + Utils::memoryUnlock(m_secret, sizeof(m_secret)); } ZT_INLINE SymmetricKey &operator=(const SymmetricKey &k) noexcept { if (&k != this) { - cipher.init(k._k); - _ts = k._ts; - _nonceBase = k._nonceBase; - _odometer = k._odometer; - Utils::copy(_k,k._k); + cipher.init(k.m_secret); + m_ts = k.m_ts; + m_nonceBase = k.m_nonceBase; + m_odometer = k.m_odometer; + Utils::copy(m_secret, k.m_secret); } return *this; } @@ -111,13 +111,13 @@ public: */ ZT_INLINE bool init(const int64_t ts,const void *const key) noexcept { - if ((_ts > 0)&&(memcmp(_k,key,ZT_SYMMETRIC_KEY_SIZE) == 0)) + if ((m_ts > 0) && (memcmp(m_secret, key, ZT_SYMMETRIC_KEY_SIZE) == 0)) return false; cipher.init(key); - _ts = ts; - _nonceBase = (uint64_t)ts << 22U; // << 22 to shift approximately the seconds since epoch into the most significant 32 bits; - _odometer = 0; - Utils::copy(_k,key); + m_ts = ts; + m_nonceBase = (uint64_t)ts << 22U; // << 22 to shift approximately the seconds since epoch into the most significant 32 bits; + m_odometer = 0; + Utils::copy(m_secret, key); return true; } @@ -126,10 +126,10 @@ public: */ ZT_INLINE void clear() noexcept { - _ts = 0; - _nonceBase = 0; - _odometer = 0; - Utils::zero(_k); + m_ts = 0; + m_nonceBase = 0; + m_odometer = 0; + Utils::zero(m_secret); } /** @@ -140,7 +140,7 @@ public: */ ZT_INLINE bool expiringSoon(const int64_t now) const noexcept { - return (TTL > 0) && ( ((now - _ts) >= (TTL / 2)) || (_odometer >= (TTLM / 2)) ); + return (TTL > 0) && (((now - m_ts) >= (TTL / 2)) || (m_odometer >= (TTLM / 2)) ); } /** @@ -151,7 +151,7 @@ public: */ ZT_INLINE bool expired(const int64_t now) const noexcept { - return (TTL > 0) && ( ((now - _ts) >= TTL) || (_odometer >= TTLM) ); + return (TTL > 0) && (((now - m_ts) >= TTL) || (m_odometer >= TTLM) ); } /** @@ -169,7 +169,7 @@ public: */ ZT_INLINE const uint8_t *key() const noexcept { - return _k; + return m_secret; } /** @@ -179,13 +179,13 @@ public: */ ZT_INLINE uint64_t nextMessageIv() noexcept { - return _nonceBase + _odometer++; + return m_nonceBase + m_odometer++; } /** * @return True if this object is not NIL */ - ZT_INLINE operator bool() const noexcept { return (_ts > 0); } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) + ZT_INLINE operator bool() const noexcept { return (m_ts > 0); } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) static constexpr int marshalSizeMax() noexcept { return ZT_SYMMETRICKEY_MARSHAL_SIZE_MAX; } @@ -200,9 +200,9 @@ public: template ZT_INLINE int marshal(const MC &keyEncCipher,uint8_t data[ZT_SYMMETRICKEY_MARSHAL_SIZE_MAX]) const noexcept { - Utils::storeBigEndian(data,(uint64_t)_ts); - Utils::storeBigEndian(data + 8,_odometer.load()); - Utils::storeBigEndian(data + 16,Utils::fnv1a32(_k,sizeof(_k))); + Utils::storeBigEndian(data,(uint64_t)m_ts); + Utils::storeBigEndian(data + 8, m_odometer.load()); + Utils::storeBigEndian(data + 16,Utils::fnv1a32(m_secret, sizeof(m_secret))); // Key encryption at rest is CBC using the last 32 bits of the timestamp, the odometer, // and the FNV1a checksum as a 128-bit IV. A duplicate IV wouldn't matter much anyway since @@ -210,10 +210,10 @@ public: // looks better. uint8_t tmp[16]; for(int i=0;i<16;++i) - tmp[i] = data[i + 4] ^ _k[i]; + tmp[i] = data[i + 4] ^ m_secret[i]; keyEncCipher.encrypt(tmp,data + 20); for(int i=0;i<16;++i) - tmp[i] = data[i + 20] ^ _k[i + 16]; + tmp[i] = data[i + 20] ^ m_secret[i + 16]; keyEncCipher.encrypt(tmp,data + 36); return ZT_SYMMETRICKEY_MARSHAL_SIZE_MAX; @@ -238,29 +238,29 @@ public: if (len < ZT_SYMMETRICKEY_MARSHAL_SIZE_MAX) return -1; - _ts = (int64_t)Utils::loadBigEndian(data); - _odometer = (uint64_t)Utils::loadBigEndian(data + 8); + m_ts = (int64_t)Utils::loadBigEndian(data); + m_odometer = (uint64_t)Utils::loadBigEndian(data + 8); const uint32_t fnv = Utils::loadBigEndian(data + 16); // NOLINT(hicpp-use-auto,modernize-use-auto) uint8_t tmp[16]; keyDecCipher.decrypt(data + 20,tmp); for(int i=0;i<16;++i) - _k[i] = data[i + 4] ^ tmp[i]; + m_secret[i] = data[i + 4] ^ tmp[i]; keyDecCipher.decrypt(data + 36,tmp); for(int i=0;i<16;++i) - _k[i + 16] = data[i + 20] ^ tmp[i]; + m_secret[i + 16] = data[i + 20] ^ tmp[i]; - if (Utils::fnv1a32(_k,sizeof(_k)) != fnv) + if (Utils::fnv1a32(m_secret, sizeof(m_secret)) != fnv) clear(); return ZT_SYMMETRICKEY_MARSHAL_SIZE_MAX; } private: - int64_t _ts; - uint64_t _nonceBase; - std::atomic _odometer; - uint8_t _k[ZT_SYMMETRIC_KEY_SIZE]; + int64_t m_ts; + uint64_t m_nonceBase; + std::atomic m_odometer; + uint8_t m_secret[ZT_SYMMETRIC_KEY_SIZE]; }; } // namespace ZeroTier diff --git a/node/Tag.cpp b/node/Tag.cpp index 69c038d7b..5e1efe9ec 100644 --- a/node/Tag.cpp +++ b/node/Tag.cpp @@ -19,8 +19,8 @@ bool Tag::sign(const Identity &signer) noexcept { uint8_t buf[ZT_TAG_MARSHAL_SIZE_MAX]; if (signer.hasPrivate()) { - _signedBy = signer.address(); - _signatureLength = signer.sign(buf,(unsigned int)marshal(buf,true),_signature,sizeof(_signature)); + m_signedBy = signer.address(); + m_signatureLength = signer.sign(buf, (unsigned int)marshal(buf, true), m_signature, sizeof(m_signature)); return true; } return false; @@ -33,17 +33,17 @@ int Tag::marshal(uint8_t data[ZT_TAG_MARSHAL_SIZE_MAX],bool forSign) const noexc for(int k=0;k<8;++k) data[p++] = 0x7f; } - Utils::storeBigEndian(data + p,_networkId); p += 8; - Utils::storeBigEndian(data + p,(uint64_t)_ts); p += 8; - Utils::storeBigEndian(data + p,_id); p += 4; - Utils::storeBigEndian(data + p,_value); p += 4; - _issuedTo.copyTo(data + p); p += ZT_ADDRESS_LENGTH; - _signedBy.copyTo(data + p); p += ZT_ADDRESS_LENGTH; + Utils::storeBigEndian(data + p, m_networkId); p += 8; + Utils::storeBigEndian(data + p,(uint64_t)m_ts); p += 8; + Utils::storeBigEndian(data + p, m_id); p += 4; + Utils::storeBigEndian(data + p, m_value); p += 4; + m_issuedTo.copyTo(data + p); p += ZT_ADDRESS_LENGTH; + m_signedBy.copyTo(data + p); p += ZT_ADDRESS_LENGTH; if (!forSign) { data[p++] = 1; - Utils::storeBigEndian(data + p,(uint16_t)_signatureLength); p += 2; - Utils::copy(data + p,_signature,_signatureLength); - p += (int)_signatureLength; + Utils::storeBigEndian(data + p,(uint16_t)m_signatureLength); p += 2; + Utils::copy(data + p, m_signature, m_signatureLength); + p += (int)m_signatureLength; } data[p++] = 0; data[p++] = 0; @@ -58,18 +58,18 @@ int Tag::unmarshal(const uint8_t *data,int len) noexcept { if (len < 37) return -1; - _networkId = Utils::loadBigEndian(data); - _ts = (int64_t)Utils::loadBigEndian(data + 8); - _id = Utils::loadBigEndian(data + 16); - _value = Utils::loadBigEndian(data + 20); - _issuedTo.setTo(data + 24); - _signedBy.setTo(data + 29); + m_networkId = Utils::loadBigEndian(data); + m_ts = (int64_t)Utils::loadBigEndian(data + 8); + m_id = Utils::loadBigEndian(data + 16); + m_value = Utils::loadBigEndian(data + 20); + m_issuedTo.setTo(data + 24); + m_signedBy.setTo(data + 29); // 1 byte reserved - _signatureLength = Utils::loadBigEndian(data + 35); - int p = 37 + (int)_signatureLength; - if ((_signatureLength > ZT_SIGNATURE_BUFFER_SIZE)||(p > len)) + m_signatureLength = Utils::loadBigEndian(data + 35); + int p = 37 + (int)m_signatureLength; + if ((m_signatureLength > ZT_SIGNATURE_BUFFER_SIZE) || (p > len)) return -1; - Utils::copy(_signature,data + p,_signatureLength); + Utils::copy(m_signature, data + p, m_signatureLength); if ((p + 2) > len) return -1; p += 2 + Utils::loadBigEndian(data + p); diff --git a/node/Tag.hpp b/node/Tag.hpp index 7291ac708..b0b0225fc 100644 --- a/node/Tag.hpp +++ b/node/Tag.hpp @@ -65,24 +65,24 @@ public: * @param value Tag value */ ZT_INLINE Tag(const uint64_t nwid,const int64_t ts,const Address &issuedTo,const uint32_t id,const uint32_t value) noexcept : // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init) - _id(id), - _value(value), - _networkId(nwid), - _ts(ts), - _issuedTo(issuedTo), - _signedBy(), - _signatureLength(0) + m_id(id), + m_value(value), + m_networkId(nwid), + m_ts(ts), + m_issuedTo(issuedTo), + m_signedBy(), + m_signatureLength(0) { } - ZT_INLINE uint32_t id() const noexcept { return _id; } - ZT_INLINE const uint32_t &value() const noexcept { return _value; } - ZT_INLINE uint64_t networkId() const noexcept { return _networkId; } - ZT_INLINE int64_t timestamp() const noexcept { return _ts; } - ZT_INLINE const Address &issuedTo() const noexcept { return _issuedTo; } - ZT_INLINE const Address &signer() const noexcept { return _signedBy; } - ZT_INLINE const uint8_t *signature() const noexcept { return _signature; } - ZT_INLINE unsigned int signatureLength() const noexcept { return _signatureLength; } + ZT_INLINE uint32_t id() const noexcept { return m_id; } + ZT_INLINE const uint32_t &value() const noexcept { return m_value; } + ZT_INLINE uint64_t networkId() const noexcept { return m_networkId; } + ZT_INLINE int64_t timestamp() const noexcept { return m_ts; } + ZT_INLINE const Address &issuedTo() const noexcept { return m_issuedTo; } + ZT_INLINE const Address &signer() const noexcept { return m_signedBy; } + ZT_INLINE const uint8_t *signature() const noexcept { return m_signature; } + ZT_INLINE unsigned int signatureLength() const noexcept { return m_signatureLength; } /** * Sign this tag @@ -105,7 +105,7 @@ public: int unmarshal(const uint8_t *data,int len) noexcept; // Provides natural sort order by ID - ZT_INLINE bool operator<(const Tag &t) const noexcept { return (_id < t._id); } + ZT_INLINE bool operator<(const Tag &t) const noexcept { return (m_id < t.m_id); } ZT_INLINE bool operator==(const Tag &t) const noexcept { return (memcmp(this,&t,sizeof(Tag)) == 0); } ZT_INLINE bool operator!=(const Tag &t) const noexcept { return (memcmp(this,&t,sizeof(Tag)) != 0); } @@ -125,14 +125,14 @@ public: }; private: - uint32_t _id; - uint32_t _value; - uint64_t _networkId; - int64_t _ts; - Address _issuedTo; - Address _signedBy; - unsigned int _signatureLength; - uint8_t _signature[ZT_SIGNATURE_BUFFER_SIZE]; + uint32_t m_id; + uint32_t m_value; + uint64_t m_networkId; + int64_t m_ts; + Address m_issuedTo; + Address m_signedBy; + unsigned int m_signatureLength; + uint8_t m_signature[ZT_SIGNATURE_BUFFER_SIZE]; }; } // namespace ZeroTier diff --git a/node/Tests.cpp b/node/Tests.cpp index 991c9d990..8f18f9360 100644 --- a/node/Tests.cpp +++ b/node/Tests.cpp @@ -407,18 +407,6 @@ extern "C" const char *ZTT_general() ZT_T_PRINTF("[general] Utils::getSecureRandom() sample: %s" ZT_EOL_S,secrands); } - { - ZT_T_PRINTF("[general] Sanity checking Protocol::getPacketId()... "); - std::set pids; - for(unsigned long i=0;i<1048576;++i) - pids.insert(Protocol::getPacketId()); - if (pids.size() != 1048576) { - ZT_T_PRINTF("FAILED (collision after only 1048576 generations!)"); - return "getPacketId() produced collisions"; - } - ZT_T_PRINTF("OK" ZT_EOL_S); - } - { ZT_T_PRINTF("[general] Testing FCV (fixed capacity vector)... "); long cnt = 0; diff --git a/node/Tests.h b/node/Tests.h index 004e9b796..94f415d58 100644 --- a/node/Tests.h +++ b/node/Tests.h @@ -38,8 +38,8 @@ * in "valgrind" or a similar tool to detect marginal bad behvaior. */ -#ifndef ZT_TESTS_HPP -#define ZT_TESTS_HPP +#ifndef ZT_TESTS_H +#define ZT_TESTS_H #ifdef ZT_ENABLE_TESTS @@ -50,6 +50,10 @@ #define ZT_T_PRINTF(fmt,...) printf((fmt),##__VA_ARGS__),fflush(stdout) #endif +#ifdef __cplusplus +extern "C" { +#endif + /** * Test platform, compiler behavior, utility functions, and core classes */ diff --git a/node/Topology.cpp b/node/Topology.cpp index 60872135e..9b898c954 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -36,7 +36,7 @@ struct _RootSortComparisonOperator Topology::Topology(const RuntimeEnvironment *renv,void *tPtr) : RR(renv), - _numConfiguredPhysicalPaths(0) + 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)); @@ -47,24 +47,24 @@ Topology::Topology(const RuntimeEnvironment *renv,void *tPtr) : Identity id; int l = id.unmarshal(dptr,drem); if (l > 0) { - _roots.insert(id); + m_roots.insert(id); dptr += l; drem -= l; } } } - for(std::set::const_iterator r(_roots.begin());r!=_roots.end();++r) { + for(std::set::const_iterator r(m_roots.begin());r != m_roots.end();++r) { SharedPtr p; - _loadCached(tPtr,r->address(),p); + m_loadCached(tPtr, r->address(), p); if ((!p)||(p->identity() != *r)) { p.set(new Peer(RR)); p->init(*r); } - _rootPeers.push_back(p); - _peers[p->address()] = p; - _peersByIncomingProbe[p->incomingProbe()] = p; - _peersByIdentityHash[p->identity().fingerprint()] = p; + m_rootPeers.push_back(p); + m_peers[p->address()] = p; + m_peersByIncomingProbe[p->incomingProbe()] = p; + m_peersByIdentityHash[p->identity().fingerprint()] = p; } } @@ -74,43 +74,43 @@ Topology::~Topology() SharedPtr Topology::add(void *tPtr,const SharedPtr &peer) { - RWMutex::Lock _l(_peers_l); + RWMutex::Lock _l(m_peers_l); - SharedPtr &hp = _peers[peer->address()]; + SharedPtr &hp = m_peers[peer->address()]; if (hp) return hp; - _loadCached(tPtr,peer->address(),hp); + m_loadCached(tPtr, peer->address(), hp); if (hp) { - _peersByIncomingProbe[peer->incomingProbe()] = hp; - _peersByIdentityHash[peer->identity().fingerprint()] = hp; + m_peersByIncomingProbe[peer->incomingProbe()] = hp; + m_peersByIdentityHash[peer->identity().fingerprint()] = hp; return hp; } hp = peer; - _peersByIncomingProbe[peer->incomingProbe()] = peer; - _peersByIdentityHash[peer->identity().fingerprint()] = peer; + m_peersByIncomingProbe[peer->incomingProbe()] = peer; + m_peersByIdentityHash[peer->identity().fingerprint()] = peer; return peer; } void Topology::getAllPeers(std::vector< SharedPtr > &allPeers) const { - RWMutex::RLock l(_peers_l); + RWMutex::RLock l(m_peers_l); allPeers.clear(); - allPeers.reserve(_peers.size()); - for(Map< Address,SharedPtr >::const_iterator i(_peers.begin());i!=_peers.end();++i) + 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); } void Topology::setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig) { if (!pathNetwork) { - _numConfiguredPhysicalPaths = 0; + m_numConfiguredPhysicalPaths = 0; } else { std::map cpaths; - for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i::const_iterator i(cpaths.begin());((i!=cpaths.end())&&(cntfirst; - _physicalPathConfig[cnt].second = i->second; + m_physicalPathConfig[cnt].first = i->first; + m_physicalPathConfig[cnt].second = i->second; ++cnt; } - _numConfiguredPhysicalPaths = cnt; + m_numConfiguredPhysicalPaths = cnt; } } void Topology::addRoot(void *tPtr,const Identity &id,const InetAddress &bootstrap) { if (id == RR->identity) return; // sanity check - RWMutex::Lock l1(_peers_l); - std::pair< std::set::iterator,bool > ir(_roots.insert(id)); + RWMutex::Lock l1(m_peers_l); + std::pair< std::set::iterator,bool > ir(m_roots.insert(id)); if (ir.second) { - SharedPtr &p = _peers[id.address()]; + SharedPtr &p = m_peers[id.address()]; if (!p) { p.set(new Peer(RR)); p->init(id); if (bootstrap) p->setBootstrap(Endpoint(bootstrap)); - _peersByIncomingProbe[p->incomingProbe()] = p; - _peersByIdentityHash[p->identity().fingerprint()] = p; + m_peersByIncomingProbe[p->incomingProbe()] = p; + m_peersByIdentityHash[p->identity().fingerprint()] = p; } - _rootPeers.push_back(p); + m_rootPeers.push_back(p); - uint8_t *const roots = (uint8_t *)malloc(ZT_IDENTITY_MARSHAL_SIZE_MAX * _roots.size()); + 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(_roots.begin());i!=_roots.end();++i) { + 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; @@ -173,16 +173,16 @@ void Topology::addRoot(void *tPtr,const Identity &id,const InetAddress &bootstra bool Topology::removeRoot(const Identity &id) { - RWMutex::Lock l1(_peers_l); - std::set::iterator r(_roots.find(id)); - if (r != _roots.end()) { - for(std::vector< SharedPtr >::iterator p(_rootPeers.begin());p!=_rootPeers.end();++p) { + RWMutex::Lock l1(m_peers_l); + std::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) { if ((*p)->identity() == id) { - _rootPeers.erase(p); + m_rootPeers.erase(p); break; } } - _roots.erase(r); + m_roots.erase(r); return true; } return false; @@ -190,28 +190,28 @@ bool Topology::removeRoot(const Identity &id) void Topology::rankRoots(const int64_t now) { - RWMutex::Lock l1(_peers_l); - std::sort(_rootPeers.begin(),_rootPeers.end(),_RootSortComparisonOperator(now)); + RWMutex::Lock l1(m_peers_l); + std::sort(m_rootPeers.begin(), m_rootPeers.end(), _RootSortComparisonOperator(now)); } void Topology::doPeriodicTasks(void *tPtr,const int64_t now) { { - RWMutex::Lock l1(_peers_l); - for(Map< Address,SharedPtr >::iterator i(_peers.begin());i!=_peers.end();) { - if ( (!i->second->alive(now)) && (_roots.count(i->second->identity()) == 0) ) { + 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) ) { i->second->save(tPtr); - _peersByIncomingProbe.erase(i->second->incomingProbe()); - _peersByIdentityHash.erase(i->second->identity().fingerprint()); - _peers.erase(i++); + m_peersByIncomingProbe.erase(i->second->incomingProbe()); + m_peersByIdentityHash.erase(i->second->identity().fingerprint()); + m_peers.erase(i++); } else ++i; } } { - RWMutex::Lock l1(_paths_l); - for(Map< uint64_t,SharedPtr >::iterator i(_paths.begin());i!=_paths.end();) { + 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))) - _paths.erase(i++); + m_paths.erase(i++); else ++i; } } @@ -219,12 +219,12 @@ void Topology::doPeriodicTasks(void *tPtr,const int64_t now) void Topology::saveAll(void *tPtr) { - RWMutex::RLock l(_peers_l); - for(Map< Address,SharedPtr >::iterator i(_peers.begin());i!=_peers.end();++i) + RWMutex::RLock l(m_peers_l); + for(Map< Address,SharedPtr >::iterator i(m_peers.begin());i != m_peers.end();++i) i->second->save(tPtr); } -void Topology::_loadCached(void *tPtr,const Address &zta,SharedPtr &peer) +void Topology::m_loadCached(void *tPtr, const Address &zta, SharedPtr &peer) { try { uint64_t id[2]; diff --git a/node/Topology.hpp b/node/Topology.hpp index fe586695d..e904c979a 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -67,18 +67,18 @@ public: ZT_INLINE SharedPtr peer(void *tPtr,const Address &zta,const bool loadFromCached = true) { { - RWMutex::RLock l(_peers_l); - const SharedPtr *const ap = _peers.get(zta); + RWMutex::RLock l(m_peers_l); + const SharedPtr *const ap = m_peers.get(zta); if (ap) return *ap; } { SharedPtr p; if (loadFromCached) { - _loadCached(tPtr,zta,p); + m_loadCached(tPtr, zta, p); if (p) { - RWMutex::Lock l(_peers_l); - SharedPtr &hp = _peers[zta]; + RWMutex::Lock l(m_peers_l); + SharedPtr &hp = m_peers[zta]; if (hp) return hp; hp = p; @@ -96,8 +96,8 @@ public: */ ZT_INLINE SharedPtr peerByHash(const Fingerprint &hash) { - RWMutex::RLock _l(_peers_l); - const SharedPtr *const ap = _peersByIdentityHash.get(hash); + RWMutex::RLock _l(m_peers_l); + const SharedPtr *const ap = m_peersByIdentityHash.get(hash); if (ap) return *ap; return SharedPtr(); @@ -111,8 +111,8 @@ public: */ ZT_INLINE SharedPtr peerByProbe(const uint64_t probe) { - RWMutex::RLock _l(_peers_l); - const SharedPtr *const ap = _peersByIncomingProbe.get(probe); + RWMutex::RLock _l(m_peers_l); + const SharedPtr *const ap = m_peersByIncomingProbe.get(probe); if (ap) return *ap; return SharedPtr(); @@ -127,17 +127,17 @@ public: */ ZT_INLINE SharedPtr path(const int64_t l,const InetAddress &r) { - const uint64_t k = _getPathKey(l,r); + const uint64_t k = s_getPathKey(l, r); { - RWMutex::RLock lck(_paths_l); - SharedPtr *const p = _paths.get(k); + RWMutex::RLock lck(m_paths_l); + SharedPtr *const p = m_paths.get(k); if (p) return *p; } { SharedPtr p(new Path(l,r)); - RWMutex::Lock lck(_paths_l); - SharedPtr &p2 = _paths[k]; + RWMutex::Lock lck(m_paths_l); + SharedPtr &p2 = m_paths[k]; if (p2) return p2; p2 = p; @@ -150,10 +150,10 @@ public: */ ZT_INLINE SharedPtr root() const { - RWMutex::RLock l(_peers_l); - if (_rootPeers.empty()) + RWMutex::RLock l(m_peers_l); + if (m_rootPeers.empty()) return SharedPtr(); - return _rootPeers.front(); + return m_rootPeers.front(); } /** @@ -162,8 +162,8 @@ public: */ ZT_INLINE bool isRoot(const Identity &id) const { - RWMutex::RLock l(_peers_l); - return (_roots.count(id) > 0); + RWMutex::RLock l(m_peers_l); + return (m_roots.count(id) > 0); } /** @@ -178,8 +178,8 @@ public: template ZT_INLINE void eachPeer(F f) const { - RWMutex::RLock l(_peers_l); - for(Map< Address,SharedPtr >::const_iterator i(_peers.begin());i!=_peers.end();++i) // NOLINT(modernize-loop-convert,hicpp-use-auto,modernize-use-auto) + RWMutex::RLock l(m_peers_l); + for(Map< Address,SharedPtr >::const_iterator i(m_peers.begin());i != m_peers.end();++i) // NOLINT(modernize-loop-convert,hicpp-use-auto,modernize-use-auto) f(i->second); } @@ -195,16 +195,16 @@ public: template ZT_INLINE void eachPeerWithRoot(F f) const { - RWMutex::RLock l(_peers_l); + RWMutex::RLock l(m_peers_l); std::vector rootPeerPtrs; - rootPeerPtrs.reserve(_rootPeers.size()); - for(std::vector< SharedPtr >::const_iterator rp(_rootPeers.begin());rp!=_rootPeers.end();++rp) // NOLINT(modernize-loop-convert,hicpp-use-auto,modernize-use-auto) + rootPeerPtrs.reserve(m_rootPeers.size()); + for(std::vector< SharedPtr >::const_iterator rp(m_rootPeers.begin());rp != m_rootPeers.end();++rp) // NOLINT(modernize-loop-convert,hicpp-use-auto,modernize-use-auto) rootPeerPtrs.push_back((uintptr_t)rp->ptr()); std::sort(rootPeerPtrs.begin(),rootPeerPtrs.end()); try { - for(Map< Address,SharedPtr >::const_iterator i(_peers.begin());i!=_peers.end();++i) // NOLINT(modernize-loop-convert,hicpp-use-auto,modernize-use-auto) + for(Map< Address,SharedPtr >::const_iterator i(m_peers.begin());i != m_peers.end();++i) // NOLINT(modernize-loop-convert,hicpp-use-auto,modernize-use-auto) f(i->second,std::binary_search(rootPeerPtrs.begin(),rootPeerPtrs.end(),(uintptr_t)i->second.ptr())); } catch ( ... ) {} // should not throw } @@ -218,8 +218,8 @@ public: template ZT_INLINE void eachPath(F f) const { - RWMutex::RLock l(_paths_l); - for(Map< uint64_t,SharedPtr >::const_iterator i(_paths.begin());i!=_paths.end();++i) // NOLINT(modernize-loop-convert,hicpp-use-auto,modernize-use-auto) + 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); } @@ -239,10 +239,10 @@ public: */ ZT_INLINE void getOutboundPathInfo(const InetAddress &physicalAddress,unsigned int &mtu,uint64_t &trustedPathId) { - for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i &peer); + 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; // This gets an integer key from an InetAddress for looking up paths. - ZT_INLINE uint64_t _getPathKey(int64_t l,const InetAddress &r) const + static ZT_INLINE uint64_t s_getPathKey(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; @@ -348,18 +348,19 @@ private: const RuntimeEnvironment *const RR; - RWMutex _peers_l; - RWMutex _paths_l; + RWMutex m_peers_l; + RWMutex m_paths_l; - std::pair< InetAddress,ZT_PhysicalPathConfiguration > _physicalPathConfig[ZT_MAX_CONFIGURABLE_PATHS]; - unsigned int _numConfiguredPhysicalPaths; + std::pair< InetAddress,ZT_PhysicalPathConfiguration > m_physicalPathConfig[ZT_MAX_CONFIGURABLE_PATHS]; + unsigned int m_numConfiguredPhysicalPaths; - Map< Address,SharedPtr > _peers; - Map< uint64_t,SharedPtr > _peersByIncomingProbe; - Map< Fingerprint,SharedPtr > _peersByIdentityHash; - Map< uint64_t,SharedPtr > _paths; - std::set< Identity > _roots; // locked by _peers_l - std::vector< SharedPtr > _rootPeers; // locked by _peers_l + Map< uint64_t,SharedPtr > m_paths; + + Map< Address,SharedPtr > m_peers; + Map< uint64_t,SharedPtr > m_peersByIncomingProbe; + Map< Fingerprint,SharedPtr > m_peersByIdentityHash; + Set< Identity > m_roots; + Vector< SharedPtr > m_rootPeers; }; } // namespace ZeroTier diff --git a/node/Trace.cpp b/node/Trace.cpp index 608132239..7e35b78c4 100644 --- a/node/Trace.cpp +++ b/node/Trace.cpp @@ -28,41 +28,10 @@ namespace ZeroTier { Trace::Trace(const RuntimeEnvironment *renv) : RR(renv), - _vl1(false), - _vl2(false), - _vl2Filter(false), - _vl2Multicast(false) + _f(0) { } -Trace::Str Trace::str(const InetAddress &a,const bool ipOnly) -{ - Str s; - if (ipOnly) - a.toIpString(s.s); - else a.toString(s.s); - return s; -} - -Trace::Str Trace::str(const Address &a) -{ - Str s; - a.toString(s.s); - return s; -} - -Trace::Str Trace::str(const Address &peerAddress,const SharedPtr &path) -{ - Str s; - peerAddress.toString(s.s); - s.s[11] = '('; - path->address().toString(s.s + 12); - int x = strlen(s.s); - s.s[x] = ')'; - s.s[x+1] = 0; - return s; -} - void Trace::unexpectedError( void *tPtr, uint32_t codeLocation, diff --git a/node/Trace.hpp b/node/Trace.hpp index 676a89293..ea5d236fa 100644 --- a/node/Trace.hpp +++ b/node/Trace.hpp @@ -26,6 +26,11 @@ #include #include +#define ZT_TRACE_F_VL1 0x01U +#define ZT_TRACE_F_VL2 0x02U +#define ZT_TRACE_F_VL2_FILTER 0x04U +#define ZT_TRACE_F_VL2_MULTICAST 0x08U + namespace ZeroTier { class RuntimeEnvironment; @@ -74,25 +79,8 @@ public: } }; - /** - * Simple container for a C string - * - * @tparam C Capacity of string - */ - template - struct Str - { - ZT_INLINE Str() { Utils::zero(s); } // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init) - constexpr static unsigned int capacity() { return C; } - char s[C]; - }; - explicit Trace(const RuntimeEnvironment *renv); - static Str str(const InetAddress &a,bool ipOnly = false); - static Str str(const Address &a); - static Str str(const Address &peerAddress,const SharedPtr &path); - void unexpectedError( void *tPtr, uint32_t codeLocation, @@ -108,7 +96,8 @@ public: const InetAddress &newExternal, const InetAddress::IpScope scope) { - if (_vl1) _resettingPathsInScope(tPtr,codeLocation,reporter,from,oldExternal,newExternal,scope); + if ((_f & ZT_TRACE_F_VL1) != 0) + _resettingPathsInScope(tPtr,codeLocation,reporter,from,oldExternal,newExternal,scope); } ZT_INLINE void tryingNewPath( @@ -122,7 +111,8 @@ public: const Identity &triggeringPeer, ZT_TraceTryingNewPathReason reason) { - if (_vl1) _tryingNewPath(tPtr,codeLocation,trying,physicalAddress,triggerAddress,triggeringPacketId,triggeringPacketVerb,triggeringPeer,reason); + if ((_f & ZT_TRACE_F_VL1) != 0) + _tryingNewPath(tPtr,codeLocation,trying,physicalAddress,triggerAddress,triggeringPacketId,triggeringPacketVerb,triggeringPeer,reason); } ZT_INLINE void learnedNewPath( @@ -133,7 +123,8 @@ public: const InetAddress &physicalAddress, const InetAddress &replaced) { - if (_vl1) _learnedNewPath(tPtr,codeLocation,packetId,peerIdentity,physicalAddress,replaced); + if ((_f & ZT_TRACE_F_VL1) != 0) + _learnedNewPath(tPtr,codeLocation,packetId,peerIdentity,physicalAddress,replaced); } ZT_INLINE void incomingPacketDropped( @@ -147,7 +138,8 @@ public: uint8_t verb, const ZT_TracePacketDropReason reason) { - if (_vl1) _incomingPacketDropped(tPtr,codeLocation,packetId,networkId,peerIdentity,physicalAddress,hops,verb,reason); + if ((_f & ZT_TRACE_F_VL1) != 0) + _incomingPacketDropped(tPtr,codeLocation,packetId,networkId,peerIdentity,physicalAddress,hops,verb,reason); } ZT_INLINE void outgoingNetworkFrameDropped( @@ -161,7 +153,8 @@ public: const uint8_t *frameData, ZT_TraceFrameDropReason reason) { - if (_vl2) _outgoingNetworkFrameDropped(tPtr,codeLocation,networkId,sourceMac,destMac,etherType,frameLength,frameData,reason); + if ((_f & ZT_TRACE_F_VL2) != 0) + _outgoingNetworkFrameDropped(tPtr,codeLocation,networkId,sourceMac,destMac,etherType,frameLength,frameData,reason); } ZT_INLINE void incomingNetworkFrameDropped( @@ -179,7 +172,8 @@ public: bool credentialRequestSent, ZT_TraceFrameDropReason reason) { - if (_vl2) _incomingNetworkFrameDropped(tPtr,codeLocation,networkId,sourceMac,destMac,peerIdentity,physicalAddress,hops,frameLength,frameData,verb,credentialRequestSent,reason); + if ((_f & ZT_TRACE_F_VL2) != 0) + _incomingNetworkFrameDropped(tPtr,codeLocation,networkId,sourceMac,destMac,peerIdentity,physicalAddress,hops,frameLength,frameData,verb,credentialRequestSent,reason); } ZT_INLINE void networkConfigRequestSent( @@ -187,7 +181,8 @@ public: const uint32_t codeLocation, uint64_t networkId) { - if (_vl2) _networkConfigRequestSent(tPtr,codeLocation,networkId); + if ((_f & ZT_TRACE_F_VL2) != 0) + _networkConfigRequestSent(tPtr,codeLocation,networkId); } ZT_INLINE void networkFilter( @@ -210,7 +205,7 @@ public: bool inbound, int accept) { - if (_vl2Filter) { + if ((_f & ZT_TRACE_F_VL2_FILTER) != 0) { _networkFilter( tPtr, codeLocation, @@ -244,7 +239,8 @@ public: uint8_t credentialType, ZT_TraceCredentialRejectionReason reason) { - if (_vl2) _credentialRejected(tPtr,codeLocation,networkId,address,identity,credentialId,credentialTimestamp,credentialType,reason); + if ((_f & ZT_TRACE_F_VL2) != 0) + _credentialRejected(tPtr,codeLocation,networkId,address,identity,credentialId,credentialTimestamp,credentialType,reason); } private: @@ -342,18 +338,7 @@ private: ZT_TraceCredentialRejectionReason reason); const RuntimeEnvironment *const RR; - volatile bool _vl1,_vl2,_vl2Filter,_vl2Multicast; - - struct _MonitoringPeer - { - int64_t _timeSet; - unsigned int _traceTypes; - SharedPtr peer; - Mutex lock; - }; - - std::vector<_MonitoringPeer> _monitoringPeers; - RWMutex _monitoringPeers_l; + volatile unsigned int _f; // faster than atomic, but may not "instantly" change... will after next memory fence }; } // namespace ZeroTier diff --git a/node/VL1.cpp b/node/VL1.cpp index f037697bf..34e2a749b 100644 --- a/node/VL1.cpp +++ b/node/VL1.cpp @@ -44,10 +44,6 @@ VL1::VL1(const RuntimeEnvironment *renv) : { } -VL1::~VL1() -{ -} - void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAddress &fromAddr,SharedPtr &data,const unsigned int len) { // Get canonical Path object for this originating address and local socket pair. @@ -63,7 +59,7 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd if (len == ZT_PROTO_PROBE_LENGTH) { const SharedPtr peer(RR->topology->peerByProbe(data->lI64(0))); if ((peer)&&(peer->rateGateInboundProbe(now))) - path->sent(now,peer->sendNOP(tPtr,path->localSocket(),path->address(),now)); + path->sent(now,peer->nop(tPtr,path->localSocket(),path->address(),now)); return; } @@ -88,11 +84,11 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd destination.setTo(fragmentHeader.destination); if (destination != RR->identity.address()) { - _relay(tPtr,path,destination,data,len); + m_relay(tPtr, path, destination, data, len); return; } - switch (_inputPacketAssembler.assemble( + switch (m_inputPacketAssembler.assemble( fragmentHeader.packetId, pktv, data, @@ -122,12 +118,12 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd destination.setTo(packetHeader.destination); if (destination != RR->identity.address()) { - _relay(tPtr,path,destination,data,len); + m_relay(tPtr, path, destination, data, len); return; } if ((packetHeader.flags & ZT_PROTO_FLAG_FRAGMENTED) != 0) { - switch (_inputPacketAssembler.assemble( + switch (m_inputPacketAssembler.assemble( packetHeader.packetId, pktv, data, @@ -199,11 +195,11 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd return; } { - Mutex::Lock wl(_whoisQueue_l); - _WhoisQueueItem &wq = _whoisQueue[source]; + Mutex::Lock wl(m_whoisQueue_l); + p_WhoisQueueItem &wq = m_whoisQueue[source]; wq.inboundPackets.push_back(pkt); } - _sendPendingWhois(tPtr,now); + m_sendPendingWhois(tPtr, now); return; } @@ -374,24 +370,24 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd Protocol::Verb inReVerb = Protocol::VERB_NOP; // set via result parameter to _ERROR and _OK switch(verb) { case Protocol::VERB_NOP: break; - case Protocol::VERB_HELLO: ok = _HELLO(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break; - case Protocol::VERB_ERROR: ok = _ERROR(tPtr,path,peer,*pkt.b,(int)packetSize,inReVerb); break; - case Protocol::VERB_OK: ok = _OK(tPtr,path,peer,*pkt.b,(int)packetSize,inReVerb); break; - case Protocol::VERB_WHOIS: ok = _WHOIS(tPtr,path,peer,*pkt.b,(int)packetSize); break; - case Protocol::VERB_RENDEZVOUS: ok = _RENDEZVOUS(tPtr,path,peer,*pkt.b,(int)packetSize); break; - case Protocol::VERB_FRAME: ok = RR->vl2->_FRAME(tPtr,path,peer,*pkt.b,(int)packetSize); break; - case Protocol::VERB_EXT_FRAME: ok = RR->vl2->_EXT_FRAME(tPtr,path,peer,*pkt.b,(int)packetSize); break; - case Protocol::VERB_ECHO: ok = _ECHO(tPtr,path,peer,*pkt.b,(int)packetSize); break; - case Protocol::VERB_MULTICAST_LIKE: ok = RR->vl2->_MULTICAST_LIKE(tPtr,path,peer,*pkt.b,(int)packetSize); break; - case Protocol::VERB_NETWORK_CREDENTIALS: ok = RR->vl2->_NETWORK_CREDENTIALS(tPtr,path,peer,*pkt.b,(int)packetSize); break; - case Protocol::VERB_NETWORK_CONFIG_REQUEST: ok = RR->vl2->_NETWORK_CONFIG_REQUEST(tPtr,path,peer,*pkt.b,(int)packetSize); break; - case Protocol::VERB_NETWORK_CONFIG: ok = RR->vl2->_NETWORK_CONFIG(tPtr,path,peer,*pkt.b,(int)packetSize); break; - case Protocol::VERB_MULTICAST_GATHER: ok = RR->vl2->_MULTICAST_GATHER(tPtr,path,peer,*pkt.b,(int)packetSize); break; - case Protocol::VERB_MULTICAST_FRAME_deprecated: ok = RR->vl2->_MULTICAST_FRAME_deprecated(tPtr,path,peer,*pkt.b,(int)packetSize); break; - case Protocol::VERB_PUSH_DIRECT_PATHS: ok = _PUSH_DIRECT_PATHS(tPtr,path,peer,*pkt.b,(int)packetSize); break; - case Protocol::VERB_USER_MESSAGE: ok = _USER_MESSAGE(tPtr,path,peer,*pkt.b,(int)packetSize); break; - case Protocol::VERB_MULTICAST: ok = RR->vl2->_MULTICAST(tPtr,path,peer,*pkt.b,(int)packetSize); break; - case Protocol::VERB_ENCAP: ok = _ENCAP(tPtr,path,peer,*pkt.b,(int)packetSize); break; + case Protocol::VERB_HELLO: ok = m_HELLO(tPtr, path, peer, *pkt.b, (int) packetSize, authenticated); break; + case Protocol::VERB_ERROR: ok = m_ERROR(tPtr, path, peer, *pkt.b, (int) packetSize, inReVerb); break; + case Protocol::VERB_OK: ok = m_OK(tPtr, path, peer, *pkt.b, (int) packetSize, inReVerb); break; + case Protocol::VERB_WHOIS: ok = m_WHOIS(tPtr, path, peer, *pkt.b, (int) packetSize); break; + case Protocol::VERB_RENDEZVOUS: ok = m_RENDEZVOUS(tPtr, path, peer, *pkt.b, (int) packetSize); break; + case Protocol::VERB_FRAME: ok = RR->vl2->m_FRAME(tPtr, path, peer, *pkt.b, (int) packetSize); break; + case Protocol::VERB_EXT_FRAME: ok = RR->vl2->m_EXT_FRAME(tPtr, path, peer, *pkt.b, (int) packetSize); break; + case Protocol::VERB_ECHO: ok = m_ECHO(tPtr, path, peer, *pkt.b, (int) packetSize); break; + case Protocol::VERB_MULTICAST_LIKE: ok = RR->vl2->m_MULTICAST_LIKE(tPtr, path, peer, *pkt.b, (int) packetSize); break; + case Protocol::VERB_NETWORK_CREDENTIALS: ok = RR->vl2->m_NETWORK_CREDENTIALS(tPtr, path, peer, *pkt.b, (int) packetSize); break; + case Protocol::VERB_NETWORK_CONFIG_REQUEST: ok = RR->vl2->m_NETWORK_CONFIG_REQUEST(tPtr, path, peer, *pkt.b, (int) packetSize); break; + case Protocol::VERB_NETWORK_CONFIG: ok = RR->vl2->m_NETWORK_CONFIG(tPtr, path, peer, *pkt.b, (int) packetSize); break; + case Protocol::VERB_MULTICAST_GATHER: ok = RR->vl2->m_MULTICAST_GATHER(tPtr, path, peer, *pkt.b, (int) packetSize); break; + case Protocol::VERB_MULTICAST_FRAME_deprecated: ok = RR->vl2->m_MULTICAST_FRAME_deprecated(tPtr, path, peer, *pkt.b, (int) packetSize); break; + case Protocol::VERB_PUSH_DIRECT_PATHS: ok = m_PUSH_DIRECT_PATHS(tPtr, path, peer, *pkt.b, (int) packetSize); break; + case Protocol::VERB_USER_MESSAGE: ok = m_USER_MESSAGE(tPtr, path, peer, *pkt.b, (int) packetSize); break; + case Protocol::VERB_MULTICAST: ok = RR->vl2->m_MULTICAST(tPtr, path, peer, *pkt.b, (int) packetSize); break; + case Protocol::VERB_ENCAP: ok = m_ENCAP(tPtr, path, peer, *pkt.b, (int) packetSize); break; default: RR->t->incomingPacketDropped(tPtr,0xeeeeeff0,ph->packetId,0,identityFromPeerPtr(peer),path->address(),hops,verb,ZT_TRACE_PACKET_DROP_REASON_UNRECOGNIZED_VERB); break; @@ -403,7 +399,7 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd } } -void VL1::_relay(void *tPtr,const SharedPtr &path,const Address &destination,SharedPtr &data,unsigned int len) +void VL1::m_relay(void *tPtr, const SharedPtr &path, const Address &destination, SharedPtr &data, unsigned int len) { const uint8_t newHopCount = (data->lI8(ZT_PROTO_PACKET_FLAGS_INDEX) & 7U) + 1; if (newHopCount >= ZT_RELAY_MAX_HOPS) @@ -421,7 +417,7 @@ void VL1::_relay(void *tPtr,const SharedPtr &path,const Address &destinati toPath->send(RR,tPtr,data->unsafeData,len,now); } -void VL1::_sendPendingWhois(void *const tPtr,const int64_t now) +void VL1::m_sendPendingWhois(void *tPtr, int64_t now) { SharedPtr root(RR->topology->root()); if (!root) @@ -432,8 +428,8 @@ void VL1::_sendPendingWhois(void *const tPtr,const int64_t now) std::vector
toSend; { - Mutex::Lock wl(_whoisQueue_l); - for(Map::iterator wi(_whoisQueue.begin());wi!=_whoisQueue.end();++wi) { + Mutex::Lock wl(m_whoisQueue_l); + for(Map::iterator wi(m_whoisQueue.begin());wi != m_whoisQueue.end();++wi) { if ((now - wi->second.lastRetry) >= ZT_WHOIS_RETRY_DELAY) { wi->second.lastRetry = now; ++wi->second.retries; @@ -468,7 +464,7 @@ void VL1::_sendPendingWhois(void *const tPtr,const int64_t now) } } -bool VL1::_HELLO(void *tPtr,const SharedPtr &path,SharedPtr &peer,Buf &pkt,int packetSize,const bool authenticated) +bool VL1::m_HELLO(void *tPtr, const SharedPtr &path, SharedPtr &peer, Buf &pkt, int packetSize, bool authenticated) { if (packetSize < (int)sizeof(Protocol::HELLO)) { RR->t->incomingPacketDropped(tPtr,0x2bdb0001,0,0,identityFromPeerPtr(peer),path->address(),0,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET); @@ -663,7 +659,7 @@ bool VL1::_HELLO(void *tPtr,const SharedPtr &path,SharedPtr &peer,Bu return true; } -bool VL1::_ERROR(void *tPtr,const SharedPtr &path,const SharedPtr &peer,Buf &pkt,int packetSize,Protocol::Verb &inReVerb) +bool VL1::m_ERROR(void *tPtr, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb) { if (packetSize < (int)sizeof(Protocol::ERROR::Header)) { RR->t->incomingPacketDropped(tPtr,0x3beb1947,0,0,identityFromPeerPtr(peer),path->address(),0,Protocol::VERB_ERROR,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET); @@ -708,7 +704,7 @@ bool VL1::_ERROR(void *tPtr,const SharedPtr &path,const SharedPtr &p return true; } -bool VL1::_OK(void *tPtr,const SharedPtr &path,const SharedPtr &peer,Buf &pkt,int packetSize,Protocol::Verb &inReVerb) +bool VL1::m_OK(void *tPtr, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb) { if (packetSize < (int)sizeof(Protocol::OK::Header)) { RR->t->incomingPacketDropped(tPtr,0x4c1f1ff7,0,0,identityFromPeerPtr(peer),path->address(),0,Protocol::VERB_OK,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET); @@ -741,7 +737,7 @@ bool VL1::_OK(void *tPtr,const SharedPtr &path,const SharedPtr &peer return true; } -bool VL1::_WHOIS(void *tPtr,const SharedPtr &path,const SharedPtr &peer,Buf &pkt,int packetSize) +bool VL1::m_WHOIS(void *tPtr, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize) { if (packetSize < (int)sizeof(Protocol::OK::Header)) { RR->t->incomingPacketDropped(tPtr,0x4c1f1ff7,0,0,identityFromPeerPtr(peer),path->address(),0,Protocol::VERB_OK,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET); @@ -793,7 +789,7 @@ bool VL1::_WHOIS(void *tPtr,const SharedPtr &path,const SharedPtr &p return true; } -bool VL1::_RENDEZVOUS(void *tPtr,const SharedPtr &path,const SharedPtr &peer,Buf &pkt,int packetSize) +bool VL1::m_RENDEZVOUS(void *tPtr, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize) { if (RR->topology->isRoot(peer->identity())) { if (packetSize < (int)sizeof(Protocol::RENDEZVOUS)) { @@ -839,7 +835,7 @@ bool VL1::_RENDEZVOUS(void *tPtr,const SharedPtr &path,const SharedPtr &path,const SharedPtr &peer,Buf &pkt,int packetSize) +bool VL1::m_ECHO(void *tPtr, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize) { const uint64_t packetId = Protocol::packetId(pkt,packetSize); const uint64_t now = RR->node->now(); @@ -875,7 +871,7 @@ bool VL1::_ECHO(void *tPtr,const SharedPtr &path,const SharedPtr &pe return true; } -bool VL1::_PUSH_DIRECT_PATHS(void *tPtr,const SharedPtr &path,const SharedPtr &peer,Buf &pkt,int packetSize) +bool VL1::m_PUSH_DIRECT_PATHS(void *tPtr, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize) { if (packetSize < (int)sizeof(Protocol::PUSH_DIRECT_PATHS)) { RR->t->incomingPacketDropped(tPtr,0x1bb1bbb1,Protocol::packetId(pkt,packetSize),0,peer->identity(),path->address(),Protocol::packetHops(pkt,packetSize),Protocol::VERB_PUSH_DIRECT_PATHS,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET); @@ -964,13 +960,13 @@ bool VL1::_PUSH_DIRECT_PATHS(void *tPtr,const SharedPtr &path,const Shared return true; } -bool VL1::_USER_MESSAGE(void *tPtr,const SharedPtr &path,const SharedPtr &peer,Buf &pkt,int packetSize) +bool VL1::m_USER_MESSAGE(void *tPtr, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize) { // TODO return true; } -bool VL1::_ENCAP(void *tPtr,const SharedPtr &path,const SharedPtr &peer,Buf &pkt,int packetSize) +bool VL1::m_ENCAP(void *tPtr, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize) { // TODO: not implemented yet return true; diff --git a/node/VL1.hpp b/node/VL1.hpp index cdf09afbc..a5ff6f4b8 100644 --- a/node/VL1.hpp +++ b/node/VL1.hpp @@ -40,7 +40,6 @@ class VL1 { public: explicit VL1(const RuntimeEnvironment *renv); - ~VL1(); /** * Called when a packet is received from the real network @@ -63,34 +62,34 @@ private: const RuntimeEnvironment *RR; // Code to handle relaying of packets to other nodes. - void _relay(void *tPtr,const SharedPtr &path,const Address &destination,SharedPtr &data,unsigned int len); + void m_relay(void *tPtr, const SharedPtr &path, const Address &destination, SharedPtr &data, unsigned int len); // Send any pending WHOIS requests. - void _sendPendingWhois(void *tPtr,int64_t now); + void m_sendPendingWhois(void *tPtr, int64_t now); // Handlers for VL1 verbs -- for clarity's sake VL2 verbs are in the VL2 class. - bool _HELLO(void *tPtr,const SharedPtr &path,SharedPtr &peer,Buf &pkt,int packetSize,bool authenticated); - bool _ERROR(void *tPtr,const SharedPtr &path,const SharedPtr &peer,Buf &pkt,int packetSize,Protocol::Verb &inReVerb); - bool _OK(void *tPtr,const SharedPtr &path,const SharedPtr &peer,Buf &pkt,int packetSize,Protocol::Verb &inReVerb); - bool _WHOIS(void *tPtr,const SharedPtr &path,const SharedPtr &peer,Buf &pkt,int packetSize); - bool _RENDEZVOUS(void *tPtr,const SharedPtr &path,const SharedPtr &peer,Buf &pkt,int packetSize); - bool _ECHO(void *tPtr,const SharedPtr &path,const SharedPtr &peer,Buf &pkt,int packetSize); - bool _PUSH_DIRECT_PATHS(void *tPtr,const SharedPtr &path,const SharedPtr &peer,Buf &pkt,int packetSize); - bool _USER_MESSAGE(void *tPtr,const SharedPtr &path,const SharedPtr &peer,Buf &pkt,int packetSize); - bool _ENCAP(void *tPtr,const SharedPtr &path,const SharedPtr &peer,Buf &pkt,int packetSize); + bool m_HELLO(void *tPtr, const SharedPtr &path, SharedPtr &peer, Buf &pkt, int packetSize, bool authenticated); + bool m_ERROR(void *tPtr, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb); + bool m_OK(void *tPtr, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb); + bool m_WHOIS(void *tPtr, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize); + bool m_RENDEZVOUS(void *tPtr, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize); + bool m_ECHO(void *tPtr, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize); + bool m_PUSH_DIRECT_PATHS(void *tPtr, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize); + bool m_USER_MESSAGE(void *tPtr, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize); + bool m_ENCAP(void *tPtr, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize); - struct _WhoisQueueItem + struct p_WhoisQueueItem { - ZT_INLINE _WhoisQueueItem() : lastRetry(0),inboundPackets(),retries(0) {} + ZT_INLINE p_WhoisQueueItem() : lastRetry(0), inboundPackets(), retries(0) {} int64_t lastRetry; FCV inboundPackets; // capacity can be changed but this should be plenty unsigned int retries; }; - Defragmenter _inputPacketAssembler; + Defragmenter m_inputPacketAssembler; - Map _whoisQueue; - Mutex _whoisQueue_l; + Map m_whoisQueue; + Mutex m_whoisQueue_l; }; } // namespace ZeroTier diff --git a/node/VL2.cpp b/node/VL2.cpp index 63e8a4c0c..2be45db63 100644 --- a/node/VL2.cpp +++ b/node/VL2.cpp @@ -27,47 +27,43 @@ VL2::VL2(const RuntimeEnvironment *renv) { } -VL2::~VL2() -{ -} - void VL2::onLocalEthernet(void *const tPtr,const SharedPtr &network,const MAC &from,const MAC &to,const unsigned int etherType,unsigned int vlanId,SharedPtr &data,unsigned int len) { } -bool VL2::_FRAME(void *const tPtr,const SharedPtr &path,SharedPtr &peer,Buf &pkt,int packetSize) +bool VL2::m_FRAME(void *tPtr, const SharedPtr &path, SharedPtr &peer, Buf &pkt, int packetSize) { } -bool VL2::_EXT_FRAME(void *const tPtr,const SharedPtr &path,SharedPtr &peer,Buf &pkt,int packetSize) +bool VL2::m_EXT_FRAME(void *tPtr, const SharedPtr &path, SharedPtr &peer, Buf &pkt, int packetSize) { } -bool VL2::_MULTICAST_LIKE(void *const tPtr,const SharedPtr &path,SharedPtr &peer,Buf &pkt,int packetSize) +bool VL2::m_MULTICAST_LIKE(void *tPtr, const SharedPtr &path, SharedPtr &peer, Buf &pkt, int packetSize) { } -bool VL2::_NETWORK_CREDENTIALS(void *const tPtr,const SharedPtr &path,SharedPtr &peer,Buf &pkt,int packetSize) +bool VL2::m_NETWORK_CREDENTIALS(void *tPtr, const SharedPtr &path, SharedPtr &peer, Buf &pkt, int packetSize) { } -bool VL2::_NETWORK_CONFIG_REQUEST(void *const tPtr,const SharedPtr &path,SharedPtr &peer,Buf &pkt,int packetSize) +bool VL2::m_NETWORK_CONFIG_REQUEST(void *tPtr, const SharedPtr &path, SharedPtr &peer, Buf &pkt, int packetSize) { } -bool VL2::_NETWORK_CONFIG(void *const tPtr,const SharedPtr &path,SharedPtr &peer,Buf &pkt,int packetSize) +bool VL2::m_NETWORK_CONFIG(void *tPtr, const SharedPtr &path, SharedPtr &peer, Buf &pkt, int packetSize) { } -bool VL2::_MULTICAST_GATHER(void *const tPtr,const SharedPtr &path,SharedPtr &peer,Buf &pkt,int packetSize) +bool VL2::m_MULTICAST_GATHER(void *tPtr, const SharedPtr &path, SharedPtr &peer, Buf &pkt, int packetSize) { } -bool VL2::_MULTICAST_FRAME_deprecated(void *const tPtr,const SharedPtr &path,SharedPtr &peer,Buf &pkt,int packetSize) +bool VL2::m_MULTICAST_FRAME_deprecated(void *tPtr, const SharedPtr &path, SharedPtr &peer, Buf &pkt, int packetSize) { } -bool VL2::_MULTICAST(void *const tPtr,const SharedPtr &path,SharedPtr &peer,Buf &pkt,int packetSize) +bool VL2::m_MULTICAST(void *tPtr, const SharedPtr &path, SharedPtr &peer, Buf &pkt, int packetSize) { } diff --git a/node/VL2.hpp b/node/VL2.hpp index 015a4b925..f11afbbc0 100644 --- a/node/VL2.hpp +++ b/node/VL2.hpp @@ -36,7 +36,6 @@ class VL2 public: explicit VL2(const RuntimeEnvironment *renv); - ~VL2(); /** * Called when a packet comes from a local Ethernet tap @@ -53,15 +52,15 @@ public: void onLocalEthernet(void *tPtr,const SharedPtr &network,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,SharedPtr &data,unsigned int len); protected: - bool _FRAME(void *tPtr,const SharedPtr &path,SharedPtr &peer,Buf &pkt,int packetSize); - bool _EXT_FRAME(void *tPtr,const SharedPtr &path,SharedPtr &peer,Buf &pkt,int packetSize); - bool _MULTICAST_LIKE(void *tPtr,const SharedPtr &path,SharedPtr &peer,Buf &pkt,int packetSize); - bool _NETWORK_CREDENTIALS(void *tPtr,const SharedPtr &path,SharedPtr &peer,Buf &pkt,int packetSize); - bool _NETWORK_CONFIG_REQUEST(void *tPtr,const SharedPtr &path,SharedPtr &peer,Buf &pkt,int packetSize); - bool _NETWORK_CONFIG(void *tPtr,const SharedPtr &path,SharedPtr &peer,Buf &pkt,int packetSize); - bool _MULTICAST_GATHER(void *tPtr,const SharedPtr &path,SharedPtr &peer,Buf &pkt,int packetSize); - bool _MULTICAST_FRAME_deprecated(void *tPtr,const SharedPtr &path,SharedPtr &peer,Buf &pkt,int packetSize); - bool _MULTICAST(void *tPtr,const SharedPtr &path,SharedPtr &peer,Buf &pkt,int packetSize); + bool m_FRAME(void *tPtr, const SharedPtr &path, SharedPtr &peer, Buf &pkt, int packetSize); + bool m_EXT_FRAME(void *tPtr, const SharedPtr &path, SharedPtr &peer, Buf &pkt, int packetSize); + bool m_MULTICAST_LIKE(void *tPtr, const SharedPtr &path, SharedPtr &peer, Buf &pkt, int packetSize); + bool m_NETWORK_CREDENTIALS(void *tPtr, const SharedPtr &path, SharedPtr &peer, Buf &pkt, int packetSize); + bool m_NETWORK_CONFIG_REQUEST(void *tPtr, const SharedPtr &path, SharedPtr &peer, Buf &pkt, int packetSize); + bool m_NETWORK_CONFIG(void *tPtr, const SharedPtr &path, SharedPtr &peer, Buf &pkt, int packetSize); + bool m_MULTICAST_GATHER(void *tPtr, const SharedPtr &path, SharedPtr &peer, Buf &pkt, int packetSize); + bool m_MULTICAST_FRAME_deprecated(void *tPtr, const SharedPtr &path, SharedPtr &peer, Buf &pkt, int packetSize); + bool m_MULTICAST(void *tPtr, const SharedPtr &path, SharedPtr &peer, Buf &pkt, int packetSize); private: };