From a19bc1e826ebe500ce4359e93cc09e32f560ce55 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 14 Jul 2020 16:23:53 -0700 Subject: [PATCH] Cleanup, remove legacy accessors, formatting. --- cmd/zerotier/cli/{controller.go => cert.go} | 2 +- cmd/zerotier/cli/help.go | 2 +- cmd/zerotier/zerotier.go | 5 +- core/Containers.hpp | 60 +--- core/Defragmenter.hpp | 31 +- core/Member.cpp | 19 +- core/Member.hpp | 11 +- core/Network.cpp | 362 ++++++++++---------- core/Network.hpp | 105 +++--- core/Node.cpp | 7 +- core/Node.hpp | 28 +- core/Topology.cpp | 14 + core/Topology.hpp | 37 +- osdep/Arp.cpp | 58 ++-- osdep/LinuxNetLink.hpp | 97 +++--- osdep/NeighborDiscovery.cpp | 353 ++++++++++--------- osdep/NeighborDiscovery.hpp | 54 +-- 17 files changed, 630 insertions(+), 615 deletions(-) rename cmd/zerotier/cli/{controller.go => cert.go} (83%) diff --git a/cmd/zerotier/cli/controller.go b/cmd/zerotier/cli/cert.go similarity index 83% rename from cmd/zerotier/cli/controller.go rename to cmd/zerotier/cli/cert.go index 98766e088..64243312a 100644 --- a/cmd/zerotier/cli/controller.go +++ b/cmd/zerotier/cli/cert.go @@ -13,5 +13,5 @@ package cli -func Controller(basePath, authToken string, args []string, jsonOutput bool) { +func Cert(basePath, authToken string, args []string, jsonOutput bool) { } diff --git a/cmd/zerotier/cli/help.go b/cmd/zerotier/cli/help.go index 7c75802fe..f3d1d76ff 100644 --- a/cmd/zerotier/cli/help.go +++ b/cmd/zerotier/cli/help.go @@ -79,7 +79,7 @@ Commands: validate Locally validate an identity sign Sign a file with an identity's key verify Verify a signature - certificate [args] - Certificate commands + cert [args] - Certificate commands newid Create a new unique subject ID newcsr Create a new CSR (signing request) sign Sign a CSR to create a certificate diff --git a/cmd/zerotier/zerotier.go b/cmd/zerotier/zerotier.go index 5345361f5..6b03235db 100644 --- a/cmd/zerotier/zerotier.go +++ b/cmd/zerotier/zerotier.go @@ -139,12 +139,13 @@ func main() { cli.Peers(basePath, authTokenRequired(basePath, *tflag, *tTflag), cmdArgs, *jflag, true) case "root": cli.Root(basePath, authTokenRequired(basePath, *tflag, *tTflag), cmdArgs, *jflag) + case "controller": case "set": cli.Set(basePath, authTokenRequired(basePath, *tflag, *tTflag), cmdArgs) - case "controller": - cli.Controller(basePath, authTokenRequired(basePath, *tflag, *tTflag), cmdArgs, *jflag) case "identity": cli.Identity(cmdArgs) + case "cert": + cli.Cert(basePath, authTokenRequired(basePath, *tflag, *tTflag), cmdArgs, *jflag) } os.Exit(0) } diff --git a/core/Containers.hpp b/core/Containers.hpp index 64ec5f86b..ec4c024fd 100644 --- a/core/Containers.hpp +++ b/core/Containers.hpp @@ -41,35 +41,18 @@ struct intl_MapHasher std::size_t operator()(const O &obj) const noexcept { return (std::size_t)obj.hashCode(); } std::size_t operator()(const uint64_t i) const noexcept - { return (std::size_t)Utils::hash64(i + Utils::s_mapNonce); } + { return (std::size_t)Utils::hash64(i ^ Utils::s_mapNonce); } std::size_t operator()(const int64_t i) const noexcept - { return (std::size_t)Utils::hash64((uint64_t)i + Utils::s_mapNonce); } + { return (std::size_t)Utils::hash64((uint64_t)i ^ Utils::s_mapNonce); } std::size_t operator()(const uint32_t i) const noexcept - { return (std::size_t)Utils::hash32(i + (uint32_t)Utils::s_mapNonce); } + { 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); } + { return (std::size_t)Utils::hash32((uint32_t)i ^ (uint32_t)Utils::s_mapNonce); } }; template< typename K, typename V > class Map : public std::unordered_map< K, V, intl_MapHasher > -{ -public: - ZT_INLINE V *get(const K &key) noexcept - { - typename Map::iterator i(this->find(key)); - if (i == this->end()) - return nullptr; - return &(i->second); - } - ZT_INLINE const V *get(const K &key) const noexcept - { - typename Map::const_iterator i(this->find(key)); - if (i == this->end()) - return nullptr; - return &(i->second); - } - ZT_INLINE void set(const K &key, const V &value) { this->emplace(key, value); } -}; +{}; template< typename K, typename V > class MultiMap : public std::unordered_multimap< K, V, intl_MapHasher, std::equal_to< K > > @@ -77,34 +60,13 @@ class MultiMap : public std::unordered_multimap< K, V, intl_MapHasher, std::equa #else -template -class Map : public std::map< K,V,std::less > -{ -public: - ZT_INLINE V *get(const K &key) noexcept - { - typename Map::iterator i(this->find(key)); - if (i == this->end()) - return nullptr; - return &(i->second); - } +template +class Map : public std::map< K, V > +{}; - ZT_INLINE const V *get(const K &key) const noexcept - { - typename Map::const_iterator i(this->find(key)); - if (i == this->end()) - return nullptr; - return &(i->second); - } - - ZT_INLINE void set(const K &key,const V &value) - { (*this)[key] = value; } -}; - -template -class MultiMap : public std::multimap< K,V,std::less,Utils::Mallocator< std::pair > > -{ -}; +template +class MultiMap : public std::multimap< K, V > +{}; #endif diff --git a/core/Defragmenter.hpp b/core/Defragmenter.hpp index a34db85e5..2e79da4cd 100644 --- a/core/Defragmenter.hpp +++ b/core/Defragmenter.hpp @@ -167,15 +167,15 @@ public: // under the target size. This tries to minimize the amount of time the write // 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; + std::vector< std::pair< int64_t, uint64_t > > messagesByLastUsedTime; messagesByLastUsedTime.reserve(m_messages.size()); - for (typename Map::const_iterator i(m_messages.begin());i != m_messages.end();++i) - messagesByLastUsedTime.push_back(std::pair(i->second.lastUsed, i->first)); + for (typename Map< uint64_t, p_E >::const_iterator i(m_messages.begin()); i != m_messages.end(); ++i) + messagesByLastUsedTime.push_back(std::pair< int64_t, uint64_t >(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) + for (unsigned long x = 0, y = (messagesByLastUsedTime.size() - GCS); x <= y; ++x) m_messages.erase(messagesByLastUsedTime[x].second); } catch (...) { return ERR_OUT_OF_MEMORY; @@ -183,15 +183,20 @@ public: } // Get or create message fragment. - p_E *e = m_messages.get(messageId); - if (!e) { - ml.writing(); // acquire write lock on _messages if not already - try { - e = &(m_messages[messageId]); - } catch (...) { - return ERR_OUT_OF_MEMORY; + Defragmenter< MF, MFP, GCS, GCT, P >::p_E *e; + { + typename Map< uint64_t, Defragmenter< MF, MFP, GCS, GCT, P >::p_E >::iterator ee(m_messages.find(messageId)); + if (ee == m_messages.end()) { + ml.writing(); // acquire write lock on _messages if not already + try { + e = &(m_messages[messageId]); + } catch (...) { + return ERR_OUT_OF_MEMORY; + } + e->id = messageId; + } else { + e = &(ee->second); } - e->id = messageId; } // Switch back to holding only the read lock on _messages if we have locked for write @@ -343,7 +348,7 @@ private: Mutex lock; }; - Map ::p_E> m_messages; + Map ::p_E> m_messages; RWMutex m_messages_l; }; diff --git a/core/Member.cpp b/core/Member.cpp index cd18f326e..2a82ce542 100644 --- a/core/Member.cpp +++ b/core/Member.cpp @@ -115,7 +115,7 @@ void Member::pushCredentials(const RuntimeEnvironment *RR, void *tPtr, const int m_lastPushedCredentials = now; } -void Member::clean(const int64_t now, const NetworkConfig &nconf) +void Member::clean(const NetworkConfig &nconf) { m_cleanCredImpl< TagCredential >(nconf, m_remoteTags); m_cleanCredImpl< CapabilityCredential >(nconf, m_remoteCaps); @@ -164,18 +164,18 @@ static ZT_INLINE Member::AddCredentialResult _addCredImpl( const NetworkConfig &nconf, const C &cred) { - C *rc = remoteCreds.get(cred.id()); - if (rc) { - if (rc->timestamp() > cred.timestamp()) { + typename Map< uint32_t, C >::const_iterator rc(remoteCreds.find(cred.id())); + if (rc != remoteCreds.end()) { + if (rc->second.timestamp() > cred.timestamp()) { RR->t->credentialRejected(tPtr, 0x40000001, nconf.networkId, sourcePeerIdentity, cred.id(), cred.timestamp(), C::credentialType(), ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST); return Member::ADD_REJECTED; } - if (*rc == cred) + if (rc->second == cred) return Member::ADD_ACCEPTED_REDUNDANT; } - const int64_t *const rt = revocations.get(Member::credentialKey(C::credentialType(), cred.id())); - if ((rt) && (*rt >= cred.timestamp())) { + typename Map< uint64_t, int64_t >::const_iterator rt(revocations.find(Member::credentialKey(C::credentialType(), cred.id()))); + if ((rt != revocations.end()) && (rt->second >= cred.timestamp())) { RR->t->credentialRejected(tPtr, 0x24248124, nconf.networkId, sourcePeerIdentity, cred.id(), cred.timestamp(), C::credentialType(), ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED); return Member::ADD_REJECTED; } @@ -185,9 +185,8 @@ static ZT_INLINE Member::AddCredentialResult _addCredImpl( RR->t->credentialRejected(tPtr, 0x01feba012, nconf.networkId, sourcePeerIdentity, cred.id(), cred.timestamp(), C::credentialType(), ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID); return Member::ADD_REJECTED; case 0: - if (!rc) - rc = &(remoteCreds[cred.id()]); - *rc = cred; + if (rc == remoteCreds.end()) + remoteCreds[cred.id()] = cred; return Member::ADD_ACCEPTED_NEW; case 1: return Member::ADD_DEFERRED_FOR_WHOIS; diff --git a/core/Member.hpp b/core/Member.hpp index 57055dac6..3425efe24 100644 --- a/core/Member.hpp +++ b/core/Member.hpp @@ -73,17 +73,16 @@ public: */ ZT_INLINE const TagCredential *getTag(const NetworkConfig &nconf, const uint32_t id) const noexcept { - const TagCredential *const t = m_remoteTags.get(id); - return (((t)&&(m_isCredentialTimestampValid(nconf, *t))) ? t : (TagCredential *)0); + Map< uint32_t, TagCredential >::const_iterator t(m_remoteTags.find(id)); + return (((t != m_remoteTags.end())&&(m_isCredentialTimestampValid(nconf, t->second))) ? &(t->second) : (TagCredential *)0); } /** * Clean internal databases of stale entries * - * @param now Current time * @param nconf Current network configuration */ - void clean(int64_t now,const NetworkConfig &nconf); + void clean(const NetworkConfig &nconf); /** * Generates a key for internal use in indexing credentials by type and credential ID @@ -166,8 +165,8 @@ private: { const int64_t ts = remoteCredential.timestamp(); if (((ts >= nconf.timestamp) ? (ts - nconf.timestamp) : (nconf.timestamp - ts)) <= nconf.credentialTimeMaxDelta) { - const int64_t *threshold = m_revocations.get(credentialKey(C::credentialType(), remoteCredential.id())); - return ((!threshold)||(ts > *threshold)); + Map< uint64_t, int64_t >::const_iterator threshold(m_revocations.find(credentialKey(C::credentialType(), remoteCredential.id()))); + return ((threshold == m_revocations.end())||(ts > threshold->second)); } return false; } diff --git a/core/Network.cpp b/core/Network.cpp index 81ea00171..9a52ce1a3 100644 --- a/core/Network.cpp +++ b/core/Network.cpp @@ -33,14 +33,14 @@ namespace ZeroTier { namespace { // Returns true if packet appears valid; pos and proto will be set -bool _ipv6GetPayload(const uint8_t *frameData,unsigned int frameLen,unsigned int &pos,unsigned int &proto) noexcept +bool _ipv6GetPayload(const uint8_t *frameData, unsigned int frameLen, unsigned int &pos, unsigned int &proto) noexcept { if (frameLen < 40) return false; pos = 40; proto = frameData[6]; while (pos <= frameLen) { - switch(proto) { + switch (proto) { case 0: // hop-by-hop options case 43: // routing case 60: // destination options @@ -51,9 +51,9 @@ bool _ipv6GetPayload(const uint8_t *frameData,unsigned int frameLen,unsigned int pos += ((unsigned int)frameData[pos + 1] * 8) + 8; break; - //case 44: // fragment -- we currently can't parse these and they are deprecated in IPv6 anyway - //case 50: - //case 51: // IPSec ESP and AH -- we have to stop here since this is encrypted stuff + //case 44: // fragment -- we currently can't parse these and they are deprecated in IPv6 anyway + //case 50: + //case 51: // IPSec ESP and AH -- we have to stop here since this is encrypted stuff default: return true; } @@ -100,13 +100,13 @@ _doZtFilterResult _doZtFilter( rrl.clear(); - for(unsigned int rn=0;rn= 0 && rules[rn].v.qosBucket <= 8) ? rules[rn].v.qosBucket : 4; // 4 = default bucket (no priority) return DOZTFILTER_ACCEPT; @@ -117,10 +117,10 @@ _doZtFilterResult _doZtFilter( case ZT_NETWORK_RULE_ACTION_ACCEPT: return (superAccept ? DOZTFILTER_SUPER_ACCEPT : DOZTFILTER_ACCEPT); // match, accept packet - // These are initially handled together since preliminary logic is common + // These are initially handled together since preliminary logic is common case ZT_NETWORK_RULE_ACTION_TEE: case ZT_NETWORK_RULE_ACTION_WATCH: - case ZT_NETWORK_RULE_ACTION_REDIRECT: { + case ZT_NETWORK_RULE_ACTION_REDIRECT: { const Address fwdAddr(rules[rn].v.fwd.address); if (fwdAddr == ztSource) { // Skip as no-op since source is target @@ -140,12 +140,13 @@ _doZtFilterResult _doZtFilter( ccWatch = (rt == ZT_NETWORK_RULE_ACTION_WATCH); } } - } continue; + } + continue; case ZT_NETWORK_RULE_ACTION_BREAK: return DOZTFILTER_NO_MATCH; - // Unrecognized ACTIONs are ignored as no-ops + // Unrecognized ACTIONs are ignored as no-ops default: continue; } @@ -154,7 +155,7 @@ _doZtFilterResult _doZtFilter( // super-accept if we accept at all. This will cause us to accept redirected or // tee'd packets in spite of MAC and ZT addressing checks. if (inbound) { - switch(rt) { + switch (rt) { case ZT_NETWORK_RULE_ACTION_TEE: case ZT_NETWORK_RULE_ACTION_WATCH: case ZT_NETWORK_RULE_ACTION_REDIRECT: @@ -173,15 +174,15 @@ _doZtFilterResult _doZtFilter( // Circuit breaker: no need to evaluate an AND if the set's match state // is currently false since anything AND false is false. - if ((!thisSetMatches)&&(!(rules[rn].t & 0x40U))) { - rrl.logSkipped(rn,thisSetMatches); + if ((!thisSetMatches) && (!(rules[rn].t & 0x40U))) { + rrl.logSkipped(rn, thisSetMatches); continue; } // If this was not an ACTION evaluate next MATCH and update thisSetMatches with (AND [result]) uint8_t thisRuleMatches = 0; uint64_t ownershipVerificationMask = 1; // this magic value means it hasn't been computed yet -- this is done lazily the first time it's needed - switch(rt) { + switch (rt) { case ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS: thisRuleMatches = (uint8_t)(rules[rn].v.zt == ztSource.toInt()); break; @@ -206,50 +207,50 @@ _doZtFilterResult _doZtFilter( thisRuleMatches = (uint8_t)(MAC(rules[rn].v.mac) == macDest); break; case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE: - if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) { - thisRuleMatches = (uint8_t)(InetAddress((const void *)&(rules[rn].v.ipv4.ip),4,rules[rn].v.ipv4.mask).containsAddress(InetAddress((const void *)(frameData + 12),4,0))); + if ((etherType == ZT_ETHERTYPE_IPV4) && (frameLen >= 20)) { + thisRuleMatches = (uint8_t)(InetAddress((const void *)&(rules[rn].v.ipv4.ip), 4, rules[rn].v.ipv4.mask).containsAddress(InetAddress((const void *)(frameData + 12), 4, 0))); } else { thisRuleMatches = 0; } break; case ZT_NETWORK_RULE_MATCH_IPV4_DEST: - if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) { - thisRuleMatches = (uint8_t)(InetAddress((const void *)&(rules[rn].v.ipv4.ip),4,rules[rn].v.ipv4.mask).containsAddress(InetAddress((const void *)(frameData + 16),4,0))); + if ((etherType == ZT_ETHERTYPE_IPV4) && (frameLen >= 20)) { + thisRuleMatches = (uint8_t)(InetAddress((const void *)&(rules[rn].v.ipv4.ip), 4, rules[rn].v.ipv4.mask).containsAddress(InetAddress((const void *)(frameData + 16), 4, 0))); } else { thisRuleMatches = 0; } break; case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE: - if ((etherType == ZT_ETHERTYPE_IPV6)&&(frameLen >= 40)) { - thisRuleMatches = (uint8_t)(InetAddress((const void *)rules[rn].v.ipv6.ip,16,rules[rn].v.ipv6.mask).containsAddress(InetAddress((const void *)(frameData + 8),16,0))); + if ((etherType == ZT_ETHERTYPE_IPV6) && (frameLen >= 40)) { + thisRuleMatches = (uint8_t)(InetAddress((const void *)rules[rn].v.ipv6.ip, 16, rules[rn].v.ipv6.mask).containsAddress(InetAddress((const void *)(frameData + 8), 16, 0))); } else { thisRuleMatches = 0; } break; case ZT_NETWORK_RULE_MATCH_IPV6_DEST: - if ((etherType == ZT_ETHERTYPE_IPV6)&&(frameLen >= 40)) { - thisRuleMatches = (uint8_t)(InetAddress((const void *)rules[rn].v.ipv6.ip,16,rules[rn].v.ipv6.mask).containsAddress(InetAddress((const void *)(frameData + 24),16,0))); + if ((etherType == ZT_ETHERTYPE_IPV6) && (frameLen >= 40)) { + thisRuleMatches = (uint8_t)(InetAddress((const void *)rules[rn].v.ipv6.ip, 16, rules[rn].v.ipv6.mask).containsAddress(InetAddress((const void *)(frameData + 24), 16, 0))); } else { thisRuleMatches = 0; } break; case ZT_NETWORK_RULE_MATCH_IP_TOS: - if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) { + if ((etherType == ZT_ETHERTYPE_IPV4) && (frameLen >= 20)) { const uint8_t tosMasked = frameData[1] & rules[rn].v.ipTos.mask; - thisRuleMatches = (uint8_t)((tosMasked >= rules[rn].v.ipTos.value[0])&&(tosMasked <= rules[rn].v.ipTos.value[1])); - } else if ((etherType == ZT_ETHERTYPE_IPV6)&&(frameLen >= 40)) { + thisRuleMatches = (uint8_t)((tosMasked >= rules[rn].v.ipTos.value[0]) && (tosMasked <= rules[rn].v.ipTos.value[1])); + } else if ((etherType == ZT_ETHERTYPE_IPV6) && (frameLen >= 40)) { const uint8_t tosMasked = (((frameData[0] << 4U) & 0xf0U) | ((frameData[1] >> 4U) & 0x0fU)) & rules[rn].v.ipTos.mask; - thisRuleMatches = (uint8_t)((tosMasked >= rules[rn].v.ipTos.value[0])&&(tosMasked <= rules[rn].v.ipTos.value[1])); + thisRuleMatches = (uint8_t)((tosMasked >= rules[rn].v.ipTos.value[0]) && (tosMasked <= rules[rn].v.ipTos.value[1])); } else { thisRuleMatches = 0; } break; case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL: - if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) { + if ((etherType == ZT_ETHERTYPE_IPV4) && (frameLen >= 20)) { thisRuleMatches = (uint8_t)(rules[rn].v.ipProtocol == frameData[9]); } else if (etherType == ZT_ETHERTYPE_IPV6) { - unsigned int pos = 0,proto = 0; - if (_ipv6GetPayload(frameData,frameLen,pos,proto)) { + unsigned int pos = 0, proto = 0; + if (_ipv6GetPayload(frameData, frameLen, pos, proto)) { thisRuleMatches = (uint8_t)(rules[rn].v.ipProtocol == (uint8_t)proto); } else { thisRuleMatches = 0; @@ -262,13 +263,13 @@ _doZtFilterResult _doZtFilter( thisRuleMatches = (uint8_t)(rules[rn].v.etherType == (uint16_t)etherType); break; case ZT_NETWORK_RULE_MATCH_ICMP: - if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) { + if ((etherType == ZT_ETHERTYPE_IPV4) && (frameLen >= 20)) { if (frameData[9] == 0x01) { // IP protocol == ICMP const unsigned int ihl = (frameData[0] & 0xfU) * 4; if (frameLen >= (ihl + 2)) { if (rules[rn].v.icmp.type == frameData[ihl]) { if ((rules[rn].v.icmp.flags & 0x01) != 0) { - thisRuleMatches = (uint8_t)(frameData[ihl+1] == rules[rn].v.icmp.code); + thisRuleMatches = (uint8_t)(frameData[ihl + 1] == rules[rn].v.icmp.code); } else { thisRuleMatches = 1; } @@ -282,12 +283,12 @@ _doZtFilterResult _doZtFilter( thisRuleMatches = 0; } } else if (etherType == ZT_ETHERTYPE_IPV6) { - unsigned int pos = 0,proto = 0; - if (_ipv6GetPayload(frameData,frameLen,pos,proto)) { - if ((proto == 0x3a)&&(frameLen >= (pos+2))) { + unsigned int pos = 0, proto = 0; + if (_ipv6GetPayload(frameData, frameLen, pos, proto)) { + if ((proto == 0x3a) && (frameLen >= (pos + 2))) { if (rules[rn].v.icmp.type == frameData[pos]) { if ((rules[rn].v.icmp.flags & 0x01) != 0) { - thisRuleMatches = (uint8_t)(frameData[pos+1] == rules[rn].v.icmp.code); + thisRuleMatches = (uint8_t)(frameData[pos + 1] == rules[rn].v.icmp.code); } else { thisRuleMatches = 1; } @@ -306,10 +307,10 @@ _doZtFilterResult _doZtFilter( break; case ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE: case ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE: - if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) { + if ((etherType == ZT_ETHERTYPE_IPV4) && (frameLen >= 20)) { const unsigned int headerLen = 4 * (frameData[0] & 0xfU); int p = -1; - switch(frameData[9]) { // IP protocol number + switch (frameData[9]) { // IP protocol number // All these start with 16-bit source and destination port in that order case 0x06: // TCP case 0x11: // UDP @@ -323,12 +324,12 @@ _doZtFilterResult _doZtFilter( break; } - thisRuleMatches = (p >= 0) ? (uint8_t)((p >= (int)rules[rn].v.port[0])&&(p <= (int)rules[rn].v.port[1])) : (uint8_t)0; + thisRuleMatches = (p >= 0) ? (uint8_t)((p >= (int)rules[rn].v.port[0]) && (p <= (int)rules[rn].v.port[1])) : (uint8_t)0; } else if (etherType == ZT_ETHERTYPE_IPV6) { - unsigned int pos = 0,proto = 0; - if (_ipv6GetPayload(frameData,frameLen,pos,proto)) { + unsigned int pos = 0, proto = 0; + if (_ipv6GetPayload(frameData, frameLen, pos, proto)) { int p = -1; - switch(proto) { // IP protocol number + switch (proto) { // IP protocol number // All these start with 16-bit source and destination port in that order case 0x06: // TCP case 0x11: // UDP @@ -341,7 +342,7 @@ _doZtFilterResult _doZtFilter( } break; } - thisRuleMatches = (p > 0) ? (uint8_t)((p >= (int)rules[rn].v.port[0])&&(p <= (int)rules[rn].v.port[1])) : (uint8_t)0; + thisRuleMatches = (p > 0) ? (uint8_t)((p >= (int)rules[rn].v.port[0]) && (p <= (int)rules[rn].v.port[1])) : (uint8_t)0; } else { thisRuleMatches = 0; } @@ -356,11 +357,11 @@ _doZtFilterResult _doZtFilter( if (ownershipVerificationMask == 1) { ownershipVerificationMask = 0; InetAddress src; - if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)) { - src.set((const void *)(frameData + 12),4,0); - } else if ((etherType == ZT_ETHERTYPE_IPV6)&&(frameLen >= 40)) { + if ((etherType == ZT_ETHERTYPE_IPV4) && (frameLen >= 20)) { + src.set((const void *)(frameData + 12), 4, 0); + } else if ((etherType == ZT_ETHERTYPE_IPV6) && (frameLen >= 40)) { // IPv6 NDP requires special handling, since the src and dest IPs in the packet are empty or link-local. - if ( (frameLen >= (40 + 8 + 16)) && (frameData[6] == 0x3a) && ((frameData[40] == 0x87)||(frameData[40] == 0x88)) ) { + if ((frameLen >= (40 + 8 + 16)) && (frameData[6] == 0x3a) && ((frameData[40] == 0x87) || (frameData[40] == 0x88))) { if (frameData[40] == 0x87) { // Neighbor solicitations contain no reliable source address, so we implement a small // hack by considering them authenticated. Otherwise you would pretty much have to do @@ -368,25 +369,25 @@ _doZtFilterResult _doZtFilter( ownershipVerificationMask |= ZT_RULE_PACKET_CHARACTERISTICS_SENDER_IP_AUTHENTICATED; } else { // Neighbor advertisements on the other hand can absolutely be authenticated. - src.set((const void *)(frameData + 40 + 8),16,0); + src.set((const void *)(frameData + 40 + 8), 16, 0); } } else { // Other IPv6 packets can be handled normally - src.set((const void *)(frameData + 8),16,0); + src.set((const void *)(frameData + 8), 16, 0); } - } else if ((etherType == ZT_ETHERTYPE_ARP)&&(frameLen >= 28)) { - src.set((const void *)(frameData + 14),4,0); + } else if ((etherType == ZT_ETHERTYPE_ARP) && (frameLen >= 28)) { + src.set((const void *)(frameData + 14), 4, 0); } if (inbound) { if (membership) { - if ((src)&&(membership->peerOwnsAddress(nconf,src))) + if ((src) && (membership->peerOwnsAddress< InetAddress >(nconf, src))) ownershipVerificationMask |= ZT_RULE_PACKET_CHARACTERISTICS_SENDER_IP_AUTHENTICATED; - if (membership->peerOwnsAddress(nconf,macSource)) + if (membership->peerOwnsAddress< MAC >(nconf, macSource)) ownershipVerificationMask |= ZT_RULE_PACKET_CHARACTERISTICS_SENDER_MAC_AUTHENTICATED; } } else { - for(unsigned int i=0;i= 20)&&(frameData[9] == 0x06)) { + if ((etherType == ZT_ETHERTYPE_IPV4) && (frameLen >= 20) && (frameData[9] == 0x06)) { const unsigned int headerLen = 4 * (frameData[0] & 0xfU); cf |= (uint64_t)frameData[headerLen + 13]; cf |= (((uint64_t)(frameData[headerLen + 12] & 0x0fU)) << 8U); } else if (etherType == ZT_ETHERTYPE_IPV6) { - unsigned int pos = 0,proto = 0; - if (_ipv6GetPayload(frameData,frameLen,pos,proto)) { - if ((proto == 0x06)&&(frameLen > (pos + 14))) { + unsigned int pos = 0, proto = 0; + if (_ipv6GetPayload(frameData, frameLen, pos, proto)) { + if ((proto == 0x06) && (frameLen > (pos + 14))) { cf |= (uint64_t)frameData[pos + 13]; cf |= (((uint64_t)(frameData[pos + 12] & 0x0fU)) << 8U); } } } thisRuleMatches = (uint8_t)((cf & rules[rn].v.characteristics) != 0); - } break; + } + break; case ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE: - thisRuleMatches = (uint8_t)((frameLen >= (unsigned int)rules[rn].v.frameSize[0])&&(frameLen <= (unsigned int)rules[rn].v.frameSize[1])); + thisRuleMatches = (uint8_t)((frameLen >= (unsigned int)rules[rn].v.frameSize[0]) && (frameLen <= (unsigned int)rules[rn].v.frameSize[1])); break; case ZT_NETWORK_RULE_MATCH_RANDOM: thisRuleMatches = (uint8_t)((uint32_t)(Utils::random() & 0xffffffffULL) <= rules[rn].v.randomProbability); @@ -421,7 +423,7 @@ _doZtFilterResult _doZtFilter( case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR: case ZT_NETWORK_RULE_MATCH_TAGS_EQUAL: { const TagCredential *const localTag = std::lower_bound(&(nconf.tags[0]), &(nconf.tags[nconf.tagCount]), rules[rn].v.tag.id, TagCredential::IdComparePredicate()); - if ((localTag != &(nconf.tags[nconf.tagCount]))&&(localTag->id() == rules[rn].v.tag.id)) { + if ((localTag != &(nconf.tags[nconf.tagCount])) && (localTag->id() == rules[rn].v.tag.id)) { const TagCredential *const remoteTag = ((membership) ? membership->getTag(nconf, rules[rn].v.tag.id) : (const TagCredential *)0); if (remoteTag) { const uint32_t ltv = localTag->value(); @@ -436,12 +438,12 @@ _doZtFilterResult _doZtFilter( } else if (rt == ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR) { thisRuleMatches = (uint8_t)((ltv ^ rtv) == rules[rn].v.tag.value); } else if (rt == ZT_NETWORK_RULE_MATCH_TAGS_EQUAL) { - thisRuleMatches = (uint8_t)((ltv == rules[rn].v.tag.value)&&(rtv == rules[rn].v.tag.value)); + thisRuleMatches = (uint8_t)((ltv == rules[rn].v.tag.value) && (rtv == rules[rn].v.tag.value)); } else { // sanity check, can't really happen thisRuleMatches = 0; } } else { - if ((inbound)&&(!superAccept)) { + if ((inbound) && (!superAccept)) { thisRuleMatches = 0; } else { // Outbound side is not strict since if we have to match both tags and @@ -455,12 +457,13 @@ _doZtFilterResult _doZtFilter( } else { thisRuleMatches = 0; } - } break; + } + break; case ZT_NETWORK_RULE_MATCH_TAG_SENDER: case ZT_NETWORK_RULE_MATCH_TAG_RECEIVER: { if (superAccept) { thisRuleMatches = 1; - } else if ( ((rt == ZT_NETWORK_RULE_MATCH_TAG_SENDER)&&(inbound)) || ((rt == ZT_NETWORK_RULE_MATCH_TAG_RECEIVER)&&(!inbound)) ) { + } else if (((rt == ZT_NETWORK_RULE_MATCH_TAG_SENDER) && (inbound)) || ((rt == ZT_NETWORK_RULE_MATCH_TAG_RECEIVER) && (!inbound))) { const TagCredential *const remoteTag = ((membership) ? membership->getTag(nconf, rules[rn].v.tag.id) : (const TagCredential *)0); if (remoteTag) { thisRuleMatches = (uint8_t)(remoteTag->value() == rules[rn].v.tag.value); @@ -475,13 +478,14 @@ _doZtFilterResult _doZtFilter( } } else { // sender and outbound or receiver and inbound const TagCredential *const localTag = std::lower_bound(&(nconf.tags[0]), &(nconf.tags[nconf.tagCount]), rules[rn].v.tag.id, TagCredential::IdComparePredicate()); - if ((localTag != &(nconf.tags[nconf.tagCount]))&&(localTag->id() == rules[rn].v.tag.id)) { + if ((localTag != &(nconf.tags[nconf.tagCount])) && (localTag->id() == rules[rn].v.tag.id)) { thisRuleMatches = (uint8_t)(localTag->value() == rules[rn].v.tag.value); } else { thisRuleMatches = 0; } } - } break; + } + break; case ZT_NETWORK_RULE_MATCH_INTEGER_RANGE: { uint64_t integer = 0; const unsigned int bits = (rules[rn].v.intRange.format & 63U) + 1; @@ -509,17 +513,18 @@ _doZtFilterResult _doZtFilter( } integer >>= (64 - bits); } - thisRuleMatches = (uint8_t)((integer >= rules[rn].v.intRange.start)&&(integer <= (rules[rn].v.intRange.start + (uint64_t)rules[rn].v.intRange.end))); - } break; + thisRuleMatches = (uint8_t)((integer >= rules[rn].v.intRange.start) && (integer <= (rules[rn].v.intRange.start + (uint64_t)rules[rn].v.intRange.end))); + } + break; - // The result of an unsupported MATCH is configurable at the network - // level via a flag. + // The result of an unsupported MATCH is configurable at the network + // level via a flag. default: thisRuleMatches = (uint8_t)((nconf.flags & ZT_NETWORKCONFIG_FLAG_RULES_RESULT_OF_UNSUPPORTED_MATCH) != 0); break; } - rrl.log(rn,thisRuleMatches,thisSetMatches); + rrl.log(rn, thisRuleMatches, thisSetMatches); if ((rules[rn].t & 0x40U)) thisSetMatches |= (thisRuleMatches ^ ((rules[rn].t >> 7U) & 1U)); @@ -531,9 +536,9 @@ _doZtFilterResult _doZtFilter( } // anonymous namespace -const ZeroTier::MulticastGroup Network::BROADCAST(ZeroTier::MAC(0xffffffffffffULL),0); +const ZeroTier::MulticastGroup Network::BROADCAST(ZeroTier::MAC(0xffffffffffffULL), 0); -Network::Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,const Fingerprint &controllerFingerprint,void *uptr,const NetworkConfig *nconf) : +Network::Network(const RuntimeEnvironment *renv, void *tPtr, uint64_t nwid, const Fingerprint &controllerFingerprint, void *uptr, const NetworkConfig *nconf) : RR(renv), m_uPtr(uptr), m_id(nwid), @@ -547,33 +552,34 @@ Network::Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,const F m_controllerFingerprint = controllerFingerprint; if (nconf) { - this->setConfiguration(tPtr,*nconf,false); + this->setConfiguration(tPtr, *nconf, false); m_lastConfigUpdate = 0; // still want to re-request since it's likely outdated } else { uint64_t tmp[2]; - tmp[0] = nwid; tmp[1] = 0; + tmp[0] = nwid; + tmp[1] = 0; bool got = false; try { Dictionary dict; - Vector nconfData(RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,tmp)); + Vector< uint8_t > nconfData(RR->node->stateObjectGet(tPtr, ZT_STATE_OBJECT_NETWORK_CONFIG, tmp)); if (nconfData.size() > 2) { nconfData.push_back(0); - if (dict.decode(nconfData.data(),(unsigned int)nconfData.size())) { + if (dict.decode(nconfData.data(), (unsigned int)nconfData.size())) { try { - ScopedPtr nconf2(new NetworkConfig()); + ScopedPtr< NetworkConfig > nconf2(new NetworkConfig()); if (nconf2->fromDictionary(dict)) { - this->setConfiguration(tPtr,*nconf2,false); + this->setConfiguration(tPtr, *nconf2, false); m_lastConfigUpdate = 0; // still want to re-request an update since it's likely outdated got = true; } } catch (...) {} } } - } catch ( ... ) {} + } catch (...) {} if (!got) - RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,tmp,"\n",1); + RR->node->stateObjectPut(tPtr, ZT_STATE_OBJECT_NETWORK_CONFIG, tmp, "\n", 1); } if (!m_portInitialized) { @@ -615,7 +621,7 @@ bool Network::filterOutgoingPacket( const unsigned int vlanId, uint8_t &qosBucket) { - Trace::RuleResultLog rrl,crrl; + Trace::RuleResultLog rrl, crrl; Address ztFinalDest(ztDest); int localCapabilityIndex = -1; int accept = 0; @@ -626,12 +632,19 @@ bool Network::filterOutgoingPacket( Mutex::Lock l1(m_memberships_l); Mutex::Lock l2(m_config_l); - Member *const membership = (ztDest) ? m_memberships.get(ztDest) : nullptr; + Member *membership; + if (ztDest) { + Map::iterator mm(m_memberships.find(ztDest)); + if (mm != m_memberships.end()) + membership = &(mm->second); + } else { + membership = nullptr; + } - switch(_doZtFilter(RR, rrl, m_config, membership, false, ztSource, ztFinalDest, macSource, macDest, frameData, frameLen, etherType, vlanId, m_config.rules, m_config.ruleCount, cc, ccLength, ccWatch, qosBucket)) { + switch (_doZtFilter(RR, rrl, m_config, membership, false, ztSource, ztFinalDest, macSource, macDest, frameData, frameLen, etherType, vlanId, m_config.rules, m_config.ruleCount, cc, ccLength, ccWatch, qosBucket)) { case DOZTFILTER_NO_MATCH: { - for(unsigned int c=0;c < m_config.capabilityCount;++c) { + for (unsigned int c = 0; c < m_config.capabilityCount; ++c) { ztFinalDest = ztDest; // sanity check, shouldn't be possible if there was no match Address cc2; unsigned int ccLength2 = 0; @@ -647,7 +660,7 @@ bool Network::filterOutgoingPacket( localCapabilityIndex = (int)c; accept = 1; - if ((!noTee)&&(cc2)) { + if ((!noTee) && (cc2)) { // TODO /* Packet outp(cc2,RR->identity.address(),Packet::VERB_EXT_FRAME); @@ -667,7 +680,8 @@ bool Network::filterOutgoingPacket( if (accept) break; } - } break; + } + break; case DOZTFILTER_DROP: RR->t->networkFilter(tPtr, 0xadea5a2a, m_id, rrl.l, nullptr, 0, 0, ztSource, ztDest, macSource, macDest, (uint16_t)frameLen, frameData, (uint16_t)etherType, (uint16_t)vlanId, noTee, false, 0); @@ -684,7 +698,7 @@ bool Network::filterOutgoingPacket( } if (accept != 0) { - if ((!noTee)&&(cc)) { + if ((!noTee) && (cc)) { // TODO /* Packet outp(cc,RR->identity.address(),Packet::VERB_EXT_FRAME); @@ -699,7 +713,7 @@ bool Network::filterOutgoingPacket( */ } - if ((ztDest != ztFinalDest)&&(ztFinalDest)) { + if ((ztDest != ztFinalDest) && (ztFinalDest)) { // TODO /* Packet outp(ztFinalDest,RR->identity.address(),Packet::VERB_EXT_FRAME); @@ -730,7 +744,7 @@ bool Network::filterOutgoingPacket( int Network::filterIncomingPacket( void *tPtr, - const SharedPtr &sourcePeer, + const SharedPtr< Peer > &sourcePeer, const Address &ztDest, const MAC &macSource, const MAC &macDest, @@ -740,7 +754,7 @@ int Network::filterIncomingPacket( const unsigned int vlanId) { Address ztFinalDest(ztDest); - Trace::RuleResultLog rrl,crrl; + Trace::RuleResultLog rrl, crrl; int accept = 0; Address cc; unsigned int ccLength = 0; @@ -763,7 +777,7 @@ int Network::filterIncomingPacket( Address cc2; unsigned int ccLength2 = 0; bool ccWatch2 = false; - switch(_doZtFilter(RR, crrl, m_config, &membership, true, sourcePeer->address(), ztFinalDest, macSource, macDest, frameData, frameLen, etherType, vlanId, c->rules(), c->ruleCount(), cc2, ccLength2, ccWatch2, qosBucket)) { + switch (_doZtFilter(RR, crrl, m_config, &membership, true, sourcePeer->address(), ztFinalDest, macSource, macDest, frameData, frameLen, etherType, vlanId, c->rules(), c->ruleCount(), cc2, ccLength2, ccWatch2, qosBucket)) { case DOZTFILTER_NO_MATCH: case DOZTFILTER_DROP: // explicit DROP in a capability just terminates its evaluation and is an anti-pattern break; @@ -794,7 +808,8 @@ int Network::filterIncomingPacket( break; } } - } break; + } + break; case DOZTFILTER_DROP: //if (_config.remoteTraceTarget) @@ -826,7 +841,7 @@ int Network::filterIncomingPacket( */ } - if ((ztDest != ztFinalDest)&&(ztFinalDest)) { + if ((ztDest != ztFinalDest) && (ztFinalDest)) { // TODO /* Packet outp(ztFinalDest,RR->identity.address(),Packet::VERB_EXT_FRAME); @@ -851,7 +866,7 @@ int Network::filterIncomingPacket( return accept; } -void Network::multicastSubscribe(void *tPtr,const MulticastGroup &mg) +void Network::multicastSubscribe(void *tPtr, const MulticastGroup &mg) { Mutex::Lock l(m_myMulticastGroups_l); if (!std::binary_search(m_myMulticastGroups.begin(), m_myMulticastGroups.end(), mg)) { @@ -864,12 +879,12 @@ void Network::multicastSubscribe(void *tPtr,const MulticastGroup &mg) void Network::multicastUnsubscribe(const MulticastGroup &mg) { Mutex::Lock l(m_myMulticastGroups_l); - Vector::iterator i(std::lower_bound(m_myMulticastGroups.begin(), m_myMulticastGroups.end(), mg)); - if ((i != m_myMulticastGroups.end()) && (*i == mg) ) + Vector< MulticastGroup >::iterator i(std::lower_bound(m_myMulticastGroups.begin(), m_myMulticastGroups.end(), mg)); + if ((i != m_myMulticastGroups.end()) && (*i == mg)) m_myMulticastGroups.erase(i); } -uint64_t Network::handleConfigChunk(void *tPtr,uint64_t packetId,const SharedPtr &source,const Buf &chunk,int ptr,int size) +uint64_t Network::handleConfigChunk(void *tPtr, uint64_t packetId, const SharedPtr< Peer > &source, const Buf &chunk, int ptr, int size) { // If the controller's full fingerprint is known or was explicitly specified on join(), // require that the controller's identity match. Otherwise learn it. @@ -1013,16 +1028,16 @@ uint64_t Network::handleConfigChunk(void *tPtr,uint64_t packetId,const SharedPtr #endif } -int Network::setConfiguration(void *tPtr,const NetworkConfig &nconf,bool saveToDisk) +int Network::setConfiguration(void *tPtr, const NetworkConfig &nconf, bool saveToDisk) { if (m_destroyed) return 0; // _lock is NOT locked when this is called try { - if ((nconf.issuedTo != RR->identity.address())||(nconf.networkId != m_id)) + if ((nconf.issuedTo != RR->identity.address()) || (nconf.networkId != m_id)) return 0; // invalid config that is not for us or not for this network - if ((!Utils::allZero(nconf.issuedToFingerprintHash,ZT_FINGERPRINT_HASH_SIZE)) && (memcmp(nconf.issuedToFingerprintHash,RR->identity.fingerprint().hash,ZT_FINGERPRINT_HASH_SIZE) != 0)) + if ((!Utils::allZero(nconf.issuedToFingerprintHash, ZT_FINGERPRINT_HASH_SIZE)) && (memcmp(nconf.issuedToFingerprintHash, RR->identity.fingerprint().hash, ZT_FINGERPRINT_HASH_SIZE) != 0)) return 0; // full identity hash is present and does not match if (m_config == nconf) @@ -1030,7 +1045,7 @@ int Network::setConfiguration(void *tPtr,const NetworkConfig &nconf,bool saveToD ZT_VirtualNetworkConfig ctmp; bool oldPortInitialized; - { // do things that require lock here, but unlock before calling callbacks + { // do things that require lock here, but unlock before calling callbacks Mutex::Lock l1(m_config_l); m_config = nconf; @@ -1050,20 +1065,21 @@ int Network::setConfiguration(void *tPtr,const NetworkConfig &nconf,bool saveToD Dictionary d; if (nconf.toDictionary(d)) { uint64_t tmp[2]; - tmp[0] = m_id; tmp[1] = 0; - Vector d2; + tmp[0] = m_id; + tmp[1] = 0; + Vector< uint8_t > d2; d.encode(d2); - RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,tmp,d2.data(),(unsigned int)d2.size()); + RR->node->stateObjectPut(tPtr, ZT_STATE_OBJECT_NETWORK_CONFIG, tmp, d2.data(), (unsigned int)d2.size()); } - } catch ( ... ) {} + } catch (...) {} } return 2; // OK and configuration has changed - } catch ( ... ) {} // ignore invalid configs + } catch (...) {} // ignore invalid configs return 0; } -bool Network::gate(void *tPtr,const SharedPtr &peer) noexcept +bool Network::gate(void *tPtr, const SharedPtr< Peer > &peer) noexcept { Mutex::Lock lc(m_config_l); @@ -1074,21 +1090,13 @@ bool Network::gate(void *tPtr,const SharedPtr &peer) noexcept try { Mutex::Lock l(m_memberships_l); - Member *m = m_memberships.get(peer->address()); - if (m) { - // SECURITY: this method in CertificateOfMembership does a full fingerprint check as well as - // checking certificate agreement. See Membership.hpp. - return m->certificateOfMembershipAgress(m_config.com, peer->identity()); - } else { - m = &(m_memberships[peer->address()]); - return false; - } - } catch ( ... ) {} + return m_memberships[peer->address()].certificateOfMembershipAgress(m_config.com, peer->identity()); + } catch (...) {} return false; } -void Network::doPeriodicTasks(void *tPtr,const int64_t now) +void Network::doPeriodicTasks(void *tPtr, const int64_t now) { if (m_destroyed) return; @@ -1099,8 +1107,8 @@ void Network::doPeriodicTasks(void *tPtr,const int64_t now) { Mutex::Lock l1(m_memberships_l); - for(Map::iterator i(m_memberships.begin()); i != m_memberships.end(); ++i) - i->second.clean(now, m_config); + for (Map< Address, Member >::iterator i(m_memberships.begin()); i != m_memberships.end(); ++i) + i->second.clean(m_config); { Mutex::Lock l2(m_myMulticastGroups_l); @@ -1121,19 +1129,19 @@ void Network::doPeriodicTasks(void *tPtr,const int64_t now) } } -void Network::learnBridgeRoute(const MAC &mac,const Address &addr) +void Network::learnBridgeRoute(const MAC &mac, const Address &addr) { Mutex::Lock _l(m_remoteBridgeRoutes_l); m_remoteBridgeRoutes[mac] = addr; // Anti-DOS circuit breaker to prevent nodes from spamming us with absurd numbers of bridge routes while (m_remoteBridgeRoutes.size() > ZT_MAX_BRIDGE_ROUTES) { - Map< Address,unsigned long > counts; + Map< Address, unsigned long > counts; Address maxAddr; unsigned long maxCount = 0; // Find the address responsible for the most entries - for(Map::iterator i(m_remoteBridgeRoutes.begin());i != m_remoteBridgeRoutes.end();++i) { + for (Map< MAC, Address >::iterator i(m_remoteBridgeRoutes.begin()); i != m_remoteBridgeRoutes.end(); ++i) { const unsigned long c = ++counts[i->second]; if (c > maxCount) { maxCount = c; @@ -1142,7 +1150,7 @@ void Network::learnBridgeRoute(const MAC &mac,const Address &addr) } // Kill this address from our table, since it's most likely spamming us - for(Map::iterator i(m_remoteBridgeRoutes.begin());i != m_remoteBridgeRoutes.end();) { + for (Map< MAC, Address >::iterator i(m_remoteBridgeRoutes.begin()); i != m_remoteBridgeRoutes.end();) { if (i->second == maxAddr) m_remoteBridgeRoutes.erase(i++); else ++i; @@ -1216,7 +1224,7 @@ Member::AddCredentialResult Network::addCredential(void *tPtr, const Identity &s return m_memberships[coo.issuedTo()].addCredential(RR, tPtr, sourcePeerIdentity, m_config, coo); } -void Network::pushCredentials(void *tPtr,const SharedPtr &to,const int64_t now) +void Network::pushCredentials(void *tPtr, const SharedPtr< Peer > &to, const int64_t now) { const int64_t tout = std::min(m_config.credentialTimeMaxDelta, m_config.com.timestampMaxDelta()); Mutex::Lock _l(m_memberships_l); @@ -1251,7 +1259,7 @@ void Network::m_requestConfiguration(void *tPtr) const uint16_t startPortRange = (uint16_t)((m_id >> 40U) & 0xffff); const uint16_t endPortRange = (uint16_t)((m_id >> 24U) & 0xffff); if (endPortRange >= startPortRange) { - ScopedPtr nconf(new NetworkConfig()); + ScopedPtr< NetworkConfig > nconf(new NetworkConfig()); nconf->networkId = m_id; nconf->timestamp = RR->node->now(); @@ -1307,12 +1315,12 @@ void Network::m_requestConfiguration(void *tPtr) nconf->name[3] = 'o'; nconf->name[4] = 'c'; nconf->name[5] = '-'; - Utils::hex((uint16_t)startPortRange,nconf->name + 6); + Utils::hex((uint16_t)startPortRange, nconf->name + 6); nconf->name[10] = '-'; - Utils::hex((uint16_t)endPortRange,nconf->name + 11); + Utils::hex((uint16_t)endPortRange, nconf->name + 11); nconf->name[15] = (char)0; - this->setConfiguration(tPtr,*nconf,false); + this->setConfiguration(tPtr, *nconf, false); } else { this->setNotFound(); } @@ -1328,9 +1336,9 @@ void Network::m_requestConfiguration(void *tPtr) ipv4[3] = (uint8_t)myAddress; char v4ascii[24]; - Utils::decimal(ipv4[0],v4ascii); + Utils::decimal(ipv4[0], v4ascii); - ScopedPtr nconf(new NetworkConfig()); + ScopedPtr< NetworkConfig > nconf(new NetworkConfig()); nconf->networkId = m_id; nconf->timestamp = RR->node->now(); @@ -1348,7 +1356,7 @@ void Network::m_requestConfiguration(void *tPtr) nconf->specialists[0] = networkHub; nconf->staticIps[0] = InetAddress::makeIpv66plane(m_id, myAddress); - nconf->staticIps[1].set(ipv4,4,8); + nconf->staticIps[1].set(ipv4, 4, 8); nconf->rules[0].t = (uint8_t)ZT_NETWORK_RULE_ACTION_ACCEPT; @@ -1370,7 +1378,7 @@ void Network::m_requestConfiguration(void *tPtr) nconf->name[nn++] = '0'; nconf->name[nn] = (char)0; - this->setConfiguration(tPtr,*nconf,false); + this->setConfiguration(tPtr, *nconf, false); } return; } @@ -1378,17 +1386,17 @@ void Network::m_requestConfiguration(void *tPtr) const Address ctrl(controller()); Dictionary rmd; - rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_VENDOR,(uint64_t)1); // 1 == ZeroTier, no other vendors at the moment - rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_PROTOCOL_VERSION,(uint64_t)ZT_PROTO_VERSION); - rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION,(uint64_t)ZEROTIER_VERSION_MAJOR); - rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MINOR_VERSION,(uint64_t)ZEROTIER_VERSION_MINOR); - rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_REVISION,(uint64_t)ZEROTIER_VERSION_REVISION); - rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_MAX_NETWORK_RULES,(uint64_t)ZT_MAX_NETWORK_RULES); - rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_MAX_NETWORK_CAPABILITIES,(uint64_t)ZT_MAX_NETWORK_CAPABILITIES); - rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_MAX_CAPABILITY_RULES,(uint64_t)ZT_MAX_CAPABILITY_RULES); - rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_MAX_NETWORK_TAGS,(uint64_t)ZT_MAX_NETWORK_TAGS); - rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_FLAGS,(uint64_t)0); - rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_RULES_ENGINE_REV,(uint64_t)ZT_RULES_ENGINE_REVISION); + rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_VENDOR, (uint64_t)1); // 1 == ZeroTier, no other vendors at the moment + rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_PROTOCOL_VERSION, (uint64_t)ZT_PROTO_VERSION); + rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION, (uint64_t)ZEROTIER_VERSION_MAJOR); + rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MINOR_VERSION, (uint64_t)ZEROTIER_VERSION_MINOR); + rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_REVISION, (uint64_t)ZEROTIER_VERSION_REVISION); + rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_MAX_NETWORK_RULES, (uint64_t)ZT_MAX_NETWORK_RULES); + rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_MAX_NETWORK_CAPABILITIES, (uint64_t)ZT_MAX_NETWORK_CAPABILITIES); + rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_MAX_CAPABILITY_RULES, (uint64_t)ZT_MAX_CAPABILITY_RULES); + rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_MAX_NETWORK_TAGS, (uint64_t)ZT_MAX_NETWORK_TAGS); + rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_FLAGS, (uint64_t)0); + rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_RULES_ENGINE_REV, (uint64_t)ZT_RULES_ENGINE_REVISION); RR->t->networkConfigRequestSent(tPtr, 0x335bb1a2, m_id); @@ -1422,7 +1430,7 @@ void Network::m_requestConfiguration(void *tPtr) ZT_VirtualNetworkStatus Network::m_status() const { - switch(_netconfFailure) { + switch (_netconfFailure) { case NETCONF_FAILURE_ACCESS_DENIED: return ZT_NETWORK_STATUS_ACCESS_DENIED; case NETCONF_FAILURE_NOT_FOUND: @@ -1445,32 +1453,32 @@ void Network::m_externalConfig(ZT_VirtualNetworkConfig *ec) const ec->status = m_status(); ec->type = (m_config) ? (m_config.isPrivate() ? ZT_NETWORK_TYPE_PRIVATE : ZT_NETWORK_TYPE_PUBLIC) : ZT_NETWORK_TYPE_PRIVATE; ec->mtu = (m_config) ? m_config.mtu : ZT_DEFAULT_MTU; - Vector
ab; - for(unsigned int i=0;i < m_config.specialistCount;++i) { + Vector< Address > ab; + for (unsigned int i = 0; i < m_config.specialistCount; ++i) { if ((m_config.specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0) ab.push_back(Address(m_config.specialists[i])); } - ec->bridge = (std::find(ab.begin(),ab.end(),RR->identity.address()) != ab.end()) ? 1 : 0; + ec->bridge = (std::find(ab.begin(), ab.end(), RR->identity.address()) != ab.end()) ? 1 : 0; ec->broadcastEnabled = (m_config) ? (m_config.enableBroadcast() ? 1 : 0) : 0; ec->netconfRevision = (m_config) ? (unsigned long)m_config.revision : 0; ec->assignedAddressCount = 0; - for(unsigned int i=0;i(&(ec->assignedAddresses[i]),&(m_config.staticIps[i])); + Utils::copy< sizeof(struct sockaddr_storage) >(&(ec->assignedAddresses[i]), &(m_config.staticIps[i])); ++ec->assignedAddressCount; } else { - Utils::zero(&(ec->assignedAddresses[i])); + Utils::zero< sizeof(struct sockaddr_storage) >(&(ec->assignedAddresses[i])); } } ec->routeCount = 0; - for(unsigned int i=0;i(&(ec->routes[i]),&(m_config.routes[i])); + Utils::copy< sizeof(ZT_VirtualNetworkRoute) >(&(ec->routes[i]), &(m_config.routes[i])); ++ec->routeCount; } else { - Utils::zero(&(ec->routes[i])); + Utils::zero< sizeof(ZT_VirtualNetworkRoute) >(&(ec->routes[i])); } } } @@ -1478,26 +1486,26 @@ void Network::m_externalConfig(ZT_VirtualNetworkConfig *ec) const void Network::m_announceMulticastGroups(void *tPtr, bool force) { // Assumes _myMulticastGroups_l and _memberships_l are locked - const Vector groups(m_allMulticastGroups()); + const Vector< MulticastGroup > groups(m_allMulticastGroups()); m_announceMulticastGroupsTo(tPtr, controller(), groups); - // TODO - /* - Address *a = nullptr; - Membership *m = nullptr; - Hashtable::Iterator i(_memberships); - while (i.next(a,m)) { - bool announce = m->multicastLikeGate(now); // force this to be called even if 'force' is true since it updates last push time - if ((!announce)&&(force)) - announce = true; - if ((announce)&&(m->isAllowedOnNetwork(_config))) - _announceMulticastGroupsTo(tPtr,*a,groups); - } - */ + // TODO + /* +Address *a = nullptr; +Membership *m = nullptr; +Hashtable::Iterator i(_memberships); +while (i.next(a,m)) { + bool announce = m->multicastLikeGate(now); // force this to be called even if 'force' is true since it updates last push time + if ((!announce)&&(force)) + announce = true; + if ((announce)&&(m->isAllowedOnNetwork(_config))) + _announceMulticastGroupsTo(tPtr,*a,groups); + } + */ } -void Network::m_announceMulticastGroupsTo(void *tPtr, const Address &peer, const Vector &allMulticastGroups) +void Network::m_announceMulticastGroupsTo(void *tPtr, const Address &peer, const Vector< MulticastGroup > &allMulticastGroups) { #if 0 // Assumes _myMulticastGroups_l and _memberships_l are locked @@ -1523,18 +1531,18 @@ void Network::m_announceMulticastGroupsTo(void *tPtr, const Address &peer, const #endif } -Vector Network::m_allMulticastGroups() const +Vector< MulticastGroup > Network::m_allMulticastGroups() const { // Assumes _myMulticastGroups_l is locked - Vector mgs; + Vector< MulticastGroup > mgs; mgs.reserve(m_myMulticastGroups.size() + m_multicastGroupsBehindMe.size() + 1); mgs.insert(mgs.end(), m_myMulticastGroups.begin(), m_myMulticastGroups.end()); - for(Map::const_iterator i(m_multicastGroupsBehindMe.begin());i != m_multicastGroupsBehindMe.end();++i) + for (Map< MulticastGroup, int64_t >::const_iterator i(m_multicastGroupsBehindMe.begin()); i != m_multicastGroupsBehindMe.end(); ++i) mgs.push_back(i->first); if ((m_config) && (m_config.enableBroadcast())) mgs.push_back(Network::BROADCAST); - std::sort(mgs.begin(),mgs.end()); - mgs.erase(std::unique(mgs.begin(),mgs.end()),mgs.end()); + std::sort(mgs.begin(), mgs.end()); + mgs.erase(std::unique(mgs.begin(), mgs.end()), mgs.end()); return mgs; } diff --git a/core/Network.hpp b/core/Network.hpp index 019f96b47..8248c8e08 100644 --- a/core/Network.hpp +++ b/core/Network.hpp @@ -32,6 +32,7 @@ namespace ZeroTier { class RuntimeEnvironment; + class Peer; /** @@ -39,7 +40,7 @@ class Peer; */ class Network { - friend class SharedPtr; + friend class SharedPtr< Network >; public: /** @@ -50,7 +51,8 @@ public: /** * Compute primary controller device ID from network ID */ - static ZT_INLINE Address controllerFor(uint64_t nwid) noexcept { return Address(nwid >> 24U); } + static ZT_INLINE Address controllerFor(uint64_t nwid) noexcept + { return Address(nwid >> 24U); } /** * Construct a new network @@ -65,18 +67,33 @@ public: * @param uptr Arbitrary pointer used by externally-facing API (for user use) * @param nconf Network config, if known */ - Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,const Fingerprint &controllerFingerprint,void *uptr,const NetworkConfig *nconf); + Network(const RuntimeEnvironment *renv, void *tPtr, uint64_t nwid, const Fingerprint &controllerFingerprint, void *uptr, const NetworkConfig *nconf); ~Network(); - ZT_INLINE uint64_t id() const noexcept { return m_id; } - ZT_INLINE Address controller() const noexcept { return Address(m_id >> 24U); } - ZT_INLINE bool multicastEnabled() const noexcept { return (m_config.multicastLimit > 0); } - ZT_INLINE bool hasConfig() const noexcept { return (m_config); } - ZT_INLINE uint64_t lastConfigUpdate() const noexcept { return m_lastConfigUpdate; } - ZT_INLINE ZT_VirtualNetworkStatus status() const noexcept { return m_status(); } - ZT_INLINE const NetworkConfig &config() const noexcept { return m_config; } - ZT_INLINE const MAC &mac() const noexcept { return m_mac; } + ZT_INLINE uint64_t id() const noexcept + { return m_id; } + + ZT_INLINE Address controller() const noexcept + { return Address(m_id >> 24U); } + + ZT_INLINE bool multicastEnabled() const noexcept + { return (m_config.multicastLimit > 0); } + + ZT_INLINE bool hasConfig() const noexcept + { return (m_config); } + + ZT_INLINE uint64_t lastConfigUpdate() const noexcept + { return m_lastConfigUpdate; } + + ZT_INLINE ZT_VirtualNetworkStatus status() const noexcept + { return m_status(); } + + ZT_INLINE const NetworkConfig &config() const noexcept + { return m_config; } + + ZT_INLINE const MAC &mac() const noexcept + { return m_mac; } /** * Apply filters to an outgoing packet @@ -132,7 +149,7 @@ public: */ int filterIncomingPacket( void *tPtr, - const SharedPtr &sourcePeer, + const SharedPtr< Peer > &sourcePeer, const Address &ztDest, const MAC &macSource, const MAC &macDest, @@ -148,7 +165,7 @@ public: * @param includeBridgedGroups If true, also check groups we've learned via bridging * @return True if this network endpoint / peer is a member */ - ZT_INLINE bool subscribedToMulticastGroup(const MulticastGroup &mg,const bool includeBridgedGroups) const + ZT_INLINE bool subscribedToMulticastGroup(const MulticastGroup &mg, const bool includeBridgedGroups) const { Mutex::Lock l(m_myMulticastGroups_l); if (std::binary_search(m_myMulticastGroups.begin(), m_myMulticastGroups.end(), mg)) @@ -164,7 +181,7 @@ public: * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param mg New multicast group */ - void multicastSubscribe(void *tPtr,const MulticastGroup &mg); + void multicastSubscribe(void *tPtr, const MulticastGroup &mg); /** * Unsubscribe from a multicast group @@ -189,7 +206,7 @@ public: * @param size Size of data in chunk buffer (total, not relative to ptr) * @return Update ID if update was fully assembled and accepted or 0 otherwise */ - uint64_t handleConfigChunk(void *tPtr,uint64_t packetId,const SharedPtr &source,const Buf &chunk,int ptr,int size); + uint64_t handleConfigChunk(void *tPtr, uint64_t packetId, const SharedPtr< Peer > &source, const Buf &chunk, int ptr, int size); /** * Set network configuration @@ -203,17 +220,19 @@ public: * @param saveToDisk Save to disk? Used during loading, should usually be true otherwise. * @return 0 == bad, 1 == accepted but duplicate/unchanged, 2 == accepted and new */ - int setConfiguration(void *tPtr,const NetworkConfig &nconf,bool saveToDisk); + int setConfiguration(void *tPtr, const NetworkConfig &nconf, bool saveToDisk); /** * Set netconf failure to 'access denied' -- called in IncomingPacket when controller reports this */ - ZT_INLINE void setAccessDenied() noexcept { _netconfFailure = NETCONF_FAILURE_ACCESS_DENIED; } + ZT_INLINE void setAccessDenied() noexcept + { _netconfFailure = NETCONF_FAILURE_ACCESS_DENIED; } /** * Set netconf failure to 'not found' -- called by IncomingPacket when controller reports this */ - ZT_INLINE void setNotFound() noexcept { _netconfFailure = NETCONF_FAILURE_NOT_FOUND; } + ZT_INLINE void setNotFound() noexcept + { _netconfFailure = NETCONF_FAILURE_NOT_FOUND; } /** * Determine whether this peer is permitted to communicate on this network @@ -221,12 +240,12 @@ public: * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param peer Peer to check */ - bool gate(void *tPtr,const SharedPtr &peer) noexcept; + bool gate(void *tPtr, const SharedPtr< Peer > &peer) noexcept; /** * Do periodic cleanup and housekeeping tasks */ - void doPeriodicTasks(void *tPtr,int64_t now); + void doPeriodicTasks(void *tPtr, int64_t now); /** * Find the node on this network that has this MAC behind it (if any) @@ -237,8 +256,8 @@ public: ZT_INLINE Address findBridgeTo(const MAC &mac) const { Mutex::Lock _l(m_remoteBridgeRoutes_l); - const Address *const br = m_remoteBridgeRoutes.get(mac); - return ((br) ? *br : Address()); + Map< MAC, Address >::const_iterator br(m_remoteBridgeRoutes.find(mac)); + return ((br == m_remoteBridgeRoutes.end()) ? Address() : br->second); } /** @@ -247,7 +266,7 @@ public: * @param mac MAC address of destination * @param addr Bridge this MAC is reachable behind */ - void learnBridgeRoute(const MAC &mac,const Address &addr); + void learnBridgeRoute(const MAC &mac, const Address &addr); /** * Learn a multicast group that is bridged to our tap device @@ -256,10 +275,10 @@ public: * @param mg Multicast group * @param now Current time */ - ZT_INLINE void learnBridgedMulticastGroup(void *tPtr,const MulticastGroup &mg,int64_t now) + ZT_INLINE void learnBridgedMulticastGroup(void *tPtr, const MulticastGroup &mg, int64_t now) { Mutex::Lock l(m_myMulticastGroups_l); - m_multicastGroupsBehindMe.set(mg, now); + m_multicastGroupsBehindMe[mg] = now; } /** @@ -294,7 +313,7 @@ public: * @param to Destination peer * @param now Current time */ - void pushCredentials(void *tPtr,const SharedPtr &to,int64_t now); + void pushCredentials(void *tPtr, const SharedPtr< Peer > &to, int64_t now); /** * Destroy this network @@ -316,12 +335,12 @@ public: * * @param f Function of (const Address,const Membership) */ - template + template< typename F > ZT_INLINE void eachMember(F f) { Mutex::Lock ml(m_memberships_l); - for(Map::iterator i(m_memberships.begin()); i != m_memberships.end(); ++i) { // NOLINT(modernize-loop-convert,hicpp-use-auto,modernize-use-auto) - if (!f(i->first,i->second)) + for (Map< Address, Member >::iterator i(m_memberships.begin()); i != m_memberships.end(); ++i) { // NOLINT(modernize-loop-convert,hicpp-use-auto,modernize-use-auto) + if (!f(i->first, i->second)) break; } } @@ -329,15 +348,20 @@ public: /** * @return Externally usable pointer-to-pointer exported via the core API */ - ZT_INLINE void **userPtr() noexcept { return &m_uPtr; } + ZT_INLINE void **userPtr() noexcept + { return &m_uPtr; } private: void m_requestConfiguration(void *tPtr); + ZT_VirtualNetworkStatus m_status() const; + void m_externalConfig(ZT_VirtualNetworkConfig *ec) const; // assumes _lock is locked void m_announceMulticastGroups(void *tPtr, bool force); - void m_announceMulticastGroupsTo(void *tPtr, const Address &peer, const Vector &allMulticastGroups); - Vector m_allMulticastGroups() const; + + void m_announceMulticastGroupsTo(void *tPtr, const Address &peer, const Vector< MulticastGroup > &allMulticastGroups); + + Vector< MulticastGroup > m_allMulticastGroups() const; const RuntimeEnvironment *const RR; void *m_uPtr; @@ -345,30 +369,31 @@ private: Fingerprint m_controllerFingerprint; MAC m_mac; // local MAC address bool m_portInitialized; - std::atomic m_destroyed; + std::atomic< bool > m_destroyed; - Vector m_myMulticastGroups; // multicast groups that we belong to (according to tap) - Map m_multicastGroupsBehindMe; // multicast groups that seem to be behind us and when we last saw them (if we are a bridge) - Map m_remoteBridgeRoutes; // remote addresses where given MACs are reachable (for tracking devices behind remote bridges) + Vector< MulticastGroup > m_myMulticastGroups; // multicast groups that we belong to (according to tap) + Map< MulticastGroup, int64_t > m_multicastGroupsBehindMe; // multicast groups that seem to be behind us and when we last saw them (if we are a bridge) + Map< MAC, Address > m_remoteBridgeRoutes; // remote addresses where given MACs are reachable (for tracking devices behind remote bridges) NetworkConfig m_config; - std::atomic m_lastConfigUpdate; + std::atomic< int64_t > m_lastConfigUpdate; - volatile enum { + volatile enum + { NETCONF_FAILURE_NONE, NETCONF_FAILURE_ACCESS_DENIED, NETCONF_FAILURE_NOT_FOUND, NETCONF_FAILURE_INIT_FAILED } _netconfFailure; - Map m_memberships; + Map< Address, Member > m_memberships; Mutex m_myMulticastGroups_l; Mutex m_remoteBridgeRoutes_l; Mutex m_config_l; Mutex m_memberships_l; - std::atomic __refCount; + std::atomic< int > __refCount; }; } // namespace ZeroTier diff --git a/core/Node.cpp b/core/Node.cpp index 52171e69c..748eb62be 100644 --- a/core/Node.cpp +++ b/core/Node.cpp @@ -678,10 +678,11 @@ bool Node::externalPathLookup(void *tPtr, const Identity &id, int family, InetAd bool Node::localControllerHasAuthorized(const int64_t now, const uint64_t nwid, const Address &addr) const { m_localControllerAuthorizations_l.lock(); - const int64_t *const at = m_localControllerAuthorizations.get(p_LocalControllerAuth(nwid, addr)); + Map::const_iterator i(m_localControllerAuthorizations.find(p_LocalControllerAuth(nwid, addr))); + const int64_t at = (i == m_localControllerAuthorizations.end()) ? -1LL : i->second; m_localControllerAuthorizations_l.unlock(); - if (at) - return ((now - *at) < (ZT_NETWORK_AUTOCONF_DELAY * 3)); + if (at > 0) + return ((now - at) < (ZT_NETWORK_AUTOCONF_DELAY * 3)); return false; } diff --git a/core/Node.hpp b/core/Node.hpp index 31f64e777..dbe73d23d 100644 --- a/core/Node.hpp +++ b/core/Node.hpp @@ -55,7 +55,7 @@ public: int64_t now, int64_t localSocket, const struct sockaddr_storage *remoteAddress, - SharedPtr &packetData, + SharedPtr< Buf > &packetData, unsigned int packetLength, volatile int64_t *nextBackgroundTaskDeadline); @@ -67,7 +67,7 @@ public: uint64_t destMac, unsigned int etherType, unsigned int vlanId, - SharedPtr &frameData, + SharedPtr< Buf > &frameData, unsigned int frameLength, volatile int64_t *nextBackgroundTaskDeadline); @@ -222,19 +222,19 @@ public: * @param nwid Network ID * @return Network associated with ID */ - ZT_INLINE SharedPtr network(const uint64_t nwid) const noexcept + ZT_INLINE SharedPtr< Network > network(const uint64_t nwid) const noexcept { RWMutex::RLock l(m_networks_l); - const SharedPtr *const n = m_networks.get(nwid); - if (n) - return *n; - return SharedPtr(); + Map< uint64_t, SharedPtr< Network > >::const_iterator n(m_networks.find(nwid)); + if (likely(n != m_networks.end())) + return n->second; + return SharedPtr< Network >(); } /** * @return Known local interface addresses for this node */ - ZT_INLINE Vector localInterfaceAddresses() const + ZT_INLINE Vector< ZT_InterfaceAddress > localInterfaceAddresses() const { Mutex::Lock _l(m_localInterfaceAddresses_m); return m_localInterfaceAddresses; @@ -280,7 +280,7 @@ public: * @param id Object ID or NULL if this type does not use one * @return Vector containing data or empty vector if not found or empty */ - Vector stateObjectGet(void *tPtr, ZT_StateObjectType type, const uint64_t *id); + Vector< uint8_t > stateObjectGet(void *tPtr, ZT_StateObjectType type, const uint64_t *id); /** * Store a state object @@ -398,16 +398,16 @@ private: { return ((a.nwid < nwid) || ((a.nwid == nwid) && (a.address < address))); } }; - Map m_localControllerAuthorizations; + Map< p_LocalControllerAuth, int64_t > m_localControllerAuthorizations; Mutex m_localControllerAuthorizations_l; // Locally joined networks by network ID. - Map > m_networks; + Map< uint64_t, SharedPtr< Network > > 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 m_localInterfaceAddresses; + Vector< ZT_InterfaceAddress > m_localInterfaceAddresses; Mutex m_localInterfaceAddresses_m; // This is locked while running processBackgroundTasks(). @@ -419,10 +419,10 @@ private: int64_t m_lastNetworkHousekeepingRun; // This is the most recent value for time passed in via any of the core API methods. - std::atomic m_now; + std::atomic< int64_t > m_now; // True if at least one root appears reachable. - std::atomic m_online; + std::atomic< bool > m_online; }; } // namespace ZeroTier diff --git a/core/Topology.cpp b/core/Topology.cpp index 7cfaff07c..cf11c47e2 100644 --- a/core/Topology.cpp +++ b/core/Topology.cpp @@ -416,6 +416,20 @@ void Topology::m_loadCached(void *tPtr, const Address &zta, SharedPtr< Peer > &p } } +SharedPtr< Peer > Topology::m_peerFromCached(void *tPtr, const Address &zta) +{ + SharedPtr< Peer > p; + m_loadCached(tPtr, zta, p); + if (p) { + RWMutex::Lock l(m_peers_l); + SharedPtr< Peer > &hp = m_peers[zta]; + if (hp) + return hp; + hp = p; + } + return p; +} + void Topology::m_updateRootPeers_l_roots_certs(void *tPtr) { // assumes m_roots_l and m_certs_l are locked for write diff --git a/core/Topology.hpp b/core/Topology.hpp index 29793668c..9256d4d8e 100644 --- a/core/Topology.hpp +++ b/core/Topology.hpp @@ -65,24 +65,13 @@ public: { { RWMutex::RLock l(m_peers_l); - const SharedPtr< Peer > *const ap = m_peers.get(zta); - if (likely(ap != nullptr)) - return *ap; - } - { - SharedPtr< Peer > p; - if (loadFromCached) { - m_loadCached(tPtr, zta, p); - if (p) { - RWMutex::Lock l(m_peers_l); - SharedPtr< Peer > &hp = m_peers[zta]; - if (hp) - return hp; - hp = p; - } - } - return p; + Map< Address, SharedPtr< Peer > >::const_iterator ap(m_peers.find(zta)); + if (likely(ap != m_peers.end())) + return ap->second; } + if (loadFromCached) + return m_peerFromCached(tPtr, zta); + return SharedPtr< Peer >(); } /** @@ -97,9 +86,9 @@ public: const UniqueID k(r.key()); { RWMutex::RLock lck(m_paths_l); - SharedPtr< Path > *const p = m_paths.get(k); - if (likely(p != nullptr)) - return *p; + Map< UniqueID, SharedPtr< Path > >::const_iterator p(m_paths.find(k)); + if (likely(p != m_paths.end())) + return p->second; } { SharedPtr< Path > p(new Path(l, r)); @@ -231,11 +220,19 @@ public: private: void m_eraseCertificate_l_certs(const SharedPtr< const Certificate > &cert); + bool m_cleanCertificates_l_certs(int64_t now); + bool m_verifyCertificateChain_l_certs(const Certificate *current, const int64_t now) const; + ZT_CertificateError m_verifyCertificate_l_certs(const Certificate &cert, const int64_t now, unsigned int localTrust, bool skipSignatureCheck) const; + void m_loadCached(void *tPtr, const Address &zta, SharedPtr< Peer > &peer); + + SharedPtr< Peer > m_peerFromCached(void *tPtr, const Address &zta); + void m_updateRootPeers_l_roots_certs(void *tPtr); + void m_writeTrustStore_l_roots_certs(void *tPtr) const; const RuntimeEnvironment *const RR; diff --git a/osdep/Arp.cpp b/osdep/Arp.cpp index 743aa4bd2..448bc71ab 100644 --- a/osdep/Arp.cpp +++ b/osdep/Arp.cpp @@ -19,8 +19,8 @@ namespace ZeroTier { -static const uint8_t ARP_REQUEST_HEADER[8] = { 0x00,0x01,0x08,0x00,0x06,0x04,0x00,0x01 }; -static const uint8_t ARP_RESPONSE_HEADER[8] = { 0x00,0x01,0x08,0x00,0x06,0x04,0x00,0x02 }; +static const uint8_t ARP_REQUEST_HEADER[8] = {0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01}; +static const uint8_t ARP_RESPONSE_HEADER[8] = {0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x02}; Arp::Arp() : _cache(), @@ -28,7 +28,7 @@ Arp::Arp() : { } -void Arp::addLocal(uint32_t ip,const MAC &mac) +void Arp::addLocal(uint32_t ip, const MAC &mac) { _ArpEntry &e = _cache[ip]; e.lastQuerySent = 0; // local IP @@ -42,7 +42,7 @@ void Arp::remove(uint32_t ip) _cache.erase(ip); } -uint32_t Arp::processIncomingArp(const void *arp,unsigned int len,void *response,unsigned int &responseLen,MAC &responseDest) +uint32_t Arp::processIncomingArp(const void *arp, unsigned int len, void *response, unsigned int &responseLen, MAC &responseDest) { const uint64_t now = OSUtils::now(); uint32_t ip = 0; @@ -51,25 +51,25 @@ uint32_t Arp::processIncomingArp(const void *arp,unsigned int len,void *response responseDest.zero(); if (len >= 28) { - if (!memcmp(arp,ARP_REQUEST_HEADER,8)) { + if (!memcmp(arp, ARP_REQUEST_HEADER, 8)) { // Respond to ARP requests for locally-known IPs - _ArpEntry *targetEntry = _cache.get(reinterpret_cast(arp)[6]); - if ((targetEntry)&&(targetEntry->local)) { - memcpy(response,ARP_RESPONSE_HEADER,8); - targetEntry->mac.copyTo(reinterpret_cast(response) + 8); - memcpy(reinterpret_cast(response) + 14,reinterpret_cast(arp) + 24,4); - memcpy(reinterpret_cast(response) + 18,reinterpret_cast(arp) + 8,10); + Map< uint32_t, Arp::_ArpEntry >::const_iterator targetEntry(_cache.find(reinterpret_cast(arp)[6])); + if ((targetEntry != _cache.end()) && (targetEntry->second.local)) { + memcpy(response, ARP_RESPONSE_HEADER, 8); + targetEntry->second.mac.copyTo(reinterpret_cast(response) + 8); + memcpy(reinterpret_cast(response) + 14, reinterpret_cast(arp) + 24, 4); + memcpy(reinterpret_cast(response) + 18, reinterpret_cast(arp) + 8, 10); responseLen = 28; responseDest.setTo(reinterpret_cast(arp) + 8); } - } else if (!memcmp(arp,ARP_RESPONSE_HEADER,8)) { + } else if (!memcmp(arp, ARP_RESPONSE_HEADER, 8)) { // Learn cache entries for remote IPs from relevant ARP replies uint32_t responseIp = 0; - memcpy(&responseIp,reinterpret_cast(arp) + 14,4); - _ArpEntry *queryEntry = _cache.get(responseIp); - if ((queryEntry)&&(!queryEntry->local)&&((now - queryEntry->lastQuerySent) <= ZT_ARP_QUERY_MAX_TTL)) { - queryEntry->lastResponseReceived = now; - queryEntry->mac.setTo(reinterpret_cast(arp) + 8); + memcpy(&responseIp, reinterpret_cast(arp) + 14, 4); + Map< uint32_t, Arp::_ArpEntry >::iterator queryEntry(_cache.find(responseIp)); + if ((queryEntry != _cache.end()) && (!queryEntry->second.local) && ((now - queryEntry->second.lastQuerySent) <= ZT_ARP_QUERY_MAX_TTL)) { + queryEntry->second.lastResponseReceived = now; + queryEntry->second.mac.setTo(reinterpret_cast(arp) + 8); ip = responseIp; } } @@ -77,8 +77,8 @@ uint32_t Arp::processIncomingArp(const void *arp,unsigned int len,void *response if ((now - _lastCleaned) >= ZT_ARP_EXPIRE) { _lastCleaned = now; - for(Map< uint32_t,_ArpEntry >::iterator i(_cache.begin());i!=_cache.end();) { - if ((!i->second.local)&&((now - i->second.lastResponseReceived) >= ZT_ARP_EXPIRE)) + for (Map< uint32_t, _ArpEntry >::iterator i(_cache.begin()); i != _cache.end();) { + if ((!i->second.local) && ((now - i->second.lastResponseReceived) >= ZT_ARP_EXPIRE)) _cache.erase(i++); else ++i; } @@ -87,22 +87,26 @@ uint32_t Arp::processIncomingArp(const void *arp,unsigned int len,void *response return ip; } -MAC Arp::query(const MAC &localMac,uint32_t localIp,uint32_t targetIp,void *query,unsigned int &queryLen,MAC &queryDest) +MAC Arp::query(const MAC &localMac, uint32_t localIp, uint32_t targetIp, void *query, unsigned int &queryLen, MAC &queryDest) { const uint64_t now = OSUtils::now(); _ArpEntry &e = _cache[targetIp]; - if ( ((e.mac)&&((now - e.lastResponseReceived) >= (ZT_ARP_EXPIRE / 3))) || - ((!e.mac)&&((now - e.lastQuerySent) >= ZT_ARP_QUERY_INTERVAL)) ) { + if (((e.mac) && ((now - e.lastResponseReceived) >= (ZT_ARP_EXPIRE / 3))) || + ((!e.mac) && ((now - e.lastQuerySent) >= ZT_ARP_QUERY_INTERVAL))) { e.lastQuerySent = now; uint8_t *q = reinterpret_cast(query); - memcpy(q,ARP_REQUEST_HEADER,8); q += 8; // ARP request header information, always the same - localMac.copyTo(q); q += 6; // sending host MAC address - memcpy(q,&localIp,4); q += 4; // sending host IP (IP already in big-endian byte order) - memset(q,0,6); q += 6; // sending zeros for target MAC address as thats what we want to find - memcpy(q,&targetIp,4); // target IP address for resolution (IP already in big-endian byte order) + memcpy(q, ARP_REQUEST_HEADER, 8); + q += 8; // ARP request header information, always the same + localMac.copyTo(q); + q += 6; // sending host MAC address + memcpy(q, &localIp, 4); + q += 4; // sending host IP (IP already in big-endian byte order) + memset(q, 0, 6); + q += 6; // sending zeros for target MAC address as thats what we want to find + memcpy(q, &targetIp, 4); // target IP address for resolution (IP already in big-endian byte order) queryLen = 28; if (e.mac) queryDest = e.mac; // confirmation query, send directly to address holder diff --git a/osdep/LinuxNetLink.hpp b/osdep/LinuxNetLink.hpp index 4f4d2acb9..74427a873 100644 --- a/osdep/LinuxNetLink.hpp +++ b/osdep/LinuxNetLink.hpp @@ -47,70 +47,71 @@ typedef std::vector RouteList; class LinuxNetLink { private: - LinuxNetLink(); - ~LinuxNetLink(); + LinuxNetLink(); + ~LinuxNetLink(); public: - static LinuxNetLink& getInstance() - { - static LinuxNetLink instance; - return instance; - } + static LinuxNetLink& getInstance() + { + static LinuxNetLink instance; + return instance; + } - LinuxNetLink(LinuxNetLink const&) = delete; - void operator=(LinuxNetLink const&) = delete; + LinuxNetLink(LinuxNetLink const&) = delete; + void operator=(LinuxNetLink const&) = delete; - void addRoute(const InetAddress &target, const InetAddress &via, const InetAddress &src, const char *ifaceName); - void delRoute(const InetAddress &target, const InetAddress &via, const InetAddress &src, const char *ifaceName); - RouteList getIPV4Routes() const; - RouteList getIPV6Routes() const; + void addRoute(const InetAddress &target, const InetAddress &via, const InetAddress &src, const char *ifaceName); + void delRoute(const InetAddress &target, const InetAddress &via, const InetAddress &src, const char *ifaceName); + RouteList getIPV4Routes() const; + RouteList getIPV6Routes() const; - void addAddress(const InetAddress &addr, const char *iface); - void removeAddress(const InetAddress &addr, const char *iface); + void addAddress(const InetAddress &addr, const char *iface); + void removeAddress(const InetAddress &addr, const char *iface); + + void threadMain() throw(); - void threadMain() throw(); private: - int _doRecv(int fd); + int _doRecv(int fd); - void _processMessage(struct nlmsghdr *nlp, int nll); - void _routeAdded(struct nlmsghdr *nlp); - void _routeDeleted(struct nlmsghdr *nlp); - void _linkAdded(struct nlmsghdr *nlp); - void _linkDeleted(struct nlmsghdr *nlp); - void _ipAddressAdded(struct nlmsghdr *nlp); - void _ipAddressDeleted(struct nlmsghdr *nlp); + void _processMessage(struct nlmsghdr *nlp, int nll); + void _routeAdded(struct nlmsghdr *nlp); + void _routeDeleted(struct nlmsghdr *nlp); + void _linkAdded(struct nlmsghdr *nlp); + void _linkDeleted(struct nlmsghdr *nlp); + void _ipAddressAdded(struct nlmsghdr *nlp); + void _ipAddressDeleted(struct nlmsghdr *nlp); - void _requestInterfaceList(); - void _requestIPv4Routes(); - void _requestIPv6Routes(); + void _requestInterfaceList(); + void _requestIPv4Routes(); + void _requestIPv6Routes(); - int _indexForInterface(const char *iface); + int _indexForInterface(const char *iface); - void _setSocketTimeout(int fd, int seconds = 1); + void _setSocketTimeout(int fd, int seconds = 1); - Thread _t; - bool _running; + Thread _t; + bool _running; - RouteList _routes_ipv4; - Mutex _rv4_m; - RouteList _routes_ipv6; - Mutex _rv6_m; + RouteList _routes_ipv4; + Mutex _rv4_m; + RouteList _routes_ipv6; + Mutex _rv6_m; - uint32_t _seq; + uint32_t _seq; - struct iface_entry { - int index; - char ifacename[IFNAMSIZ]; - char mac[18]; - char mac_bin[6]; - unsigned int mtu; - }; - std::map _interfaces; - Mutex _if_m; + struct iface_entry { + int index; + char ifacename[IFNAMSIZ]; + char mac[18]; + char mac_bin[6]; + unsigned int mtu; + }; + std::map _interfaces; + Mutex _if_m; - // socket communication vars; - int _fd; - struct sockaddr_nl _la; + // socket communication vars; + int _fd; + struct sockaddr_nl _la; }; } diff --git a/osdep/NeighborDiscovery.cpp b/osdep/NeighborDiscovery.cpp index 604d203c4..5612376ad 100644 --- a/osdep/NeighborDiscovery.cpp +++ b/osdep/NeighborDiscovery.cpp @@ -20,239 +20,236 @@ namespace ZeroTier { -uint16_t calc_checksum (uint16_t *addr, int len) +uint16_t calc_checksum(uint16_t *addr, int len) { - int count = len; - uint32_t sum = 0; - uint16_t answer = 0; + int count = len; + uint32_t sum = 0; + uint16_t answer = 0; - // Sum up 2-byte values until none or only one byte left. - while (count > 1) { - sum += *(addr++); - count -= 2; - } + // Sum up 2-byte values until none or only one byte left. + while (count > 1) { + sum += *(addr++); + count -= 2; + } - // Add left-over byte, if any. - if (count > 0) { - sum += *(uint8_t *) addr; - } + // Add left-over byte, if any. + if (count > 0) { + sum += *(uint8_t *)addr; + } - // Fold 32-bit sum into 16 bits; we lose information by doing this, - // increasing the chances of a collision. - // sum = (lower 16 bits) + (upper 16 bits shifted right 16 bits) - while (sum >> 16) { - sum = (sum & 0xffff) + (sum >> 16); - } + // Fold 32-bit sum into 16 bits; we lose information by doing this, + // increasing the chances of a collision. + // sum = (lower 16 bits) + (upper 16 bits shifted right 16 bits) + while (sum >> 16) { + sum = (sum & 0xffff) + (sum >> 16); + } - // Checksum is one's compliment of sum. - answer = ~sum; + // Checksum is one's compliment of sum. + answer = ~sum; - return (answer); + return (answer); } -struct _pseudo_header { - uint8_t sourceAddr[16]; - uint8_t targetAddr[16]; - uint32_t length; - uint8_t zeros[3]; - uint8_t next; // 58 +struct _pseudo_header +{ + uint8_t sourceAddr[16]; + uint8_t targetAddr[16]; + uint32_t length; + uint8_t zeros[3]; + uint8_t next; // 58 }; -struct _option { - _option(int optionType) - : type(optionType) - , length(8) - { - memset(mac, 0, sizeof(mac)); - } +struct _option +{ + _option(int optionType) + : type(optionType), length(8) + { + memset(mac, 0, sizeof(mac)); + } - uint8_t type; - uint8_t length; - uint8_t mac[6]; + uint8_t type; + uint8_t length; + uint8_t mac[6]; }; -struct _neighbor_solicitation { - _neighbor_solicitation() - : type(135) - , code(0) - , checksum(0) - , option(1) - { - memset(&reserved, 0, sizeof(reserved)); - memset(target, 0, sizeof(target)); - } +struct _neighbor_solicitation +{ + _neighbor_solicitation() + : type(135), code(0), checksum(0), option(1) + { + memset(&reserved, 0, sizeof(reserved)); + memset(target, 0, sizeof(target)); + } - void calculateChecksum(const sockaddr_storage &sourceIp, const sockaddr_storage &destIp) { - _pseudo_header ph; - memset(&ph, 0, sizeof(_pseudo_header)); - const sockaddr_in6 *src = (const sockaddr_in6*)&sourceIp; - const sockaddr_in6 *dest = (const sockaddr_in6*)&destIp; + void calculateChecksum(const sockaddr_storage &sourceIp, const sockaddr_storage &destIp) + { + _pseudo_header ph; + memset(&ph, 0, sizeof(_pseudo_header)); + const sockaddr_in6 *src = (const sockaddr_in6 *)&sourceIp; + const sockaddr_in6 *dest = (const sockaddr_in6 *)&destIp; - memcpy(ph.sourceAddr, &src->sin6_addr, sizeof(struct in6_addr)); - memcpy(ph.targetAddr, &dest->sin6_addr, sizeof(struct in6_addr)); - ph.next = 58; - ph.length = htonl(sizeof(_neighbor_solicitation)); + memcpy(ph.sourceAddr, &src->sin6_addr, sizeof(struct in6_addr)); + memcpy(ph.targetAddr, &dest->sin6_addr, sizeof(struct in6_addr)); + ph.next = 58; + ph.length = htonl(sizeof(_neighbor_solicitation)); - size_t len = sizeof(_pseudo_header) + sizeof(_neighbor_solicitation); - uint8_t *tmp = (uint8_t*)malloc(len); - memcpy(tmp, &ph, sizeof(_pseudo_header)); - memcpy(tmp+sizeof(_pseudo_header), this, sizeof(_neighbor_solicitation)); + size_t len = sizeof(_pseudo_header) + sizeof(_neighbor_solicitation); + uint8_t *tmp = (uint8_t *)malloc(len); + memcpy(tmp, &ph, sizeof(_pseudo_header)); + memcpy(tmp + sizeof(_pseudo_header), this, sizeof(_neighbor_solicitation)); - checksum = calc_checksum((uint16_t*)tmp, (int)len); + checksum = calc_checksum((uint16_t *)tmp, (int)len); - free(tmp); - tmp = NULL; - } + free(tmp); + tmp = NULL; + } - uint8_t type; // 135 - uint8_t code; // 0 - uint16_t checksum; - uint32_t reserved; - uint8_t target[16]; - _option option; + uint8_t type; // 135 + uint8_t code; // 0 + uint16_t checksum; + uint32_t reserved; + uint8_t target[16]; + _option option; }; -struct _neighbor_advertisement { - _neighbor_advertisement() - : type(136) - , code(0) - , checksum(0) - , rso(0x40) - , option(2) - { - memset(padding, 0, sizeof(padding)); - memset(target, 0, sizeof(target)); - } +struct _neighbor_advertisement +{ + _neighbor_advertisement() + : type(136), code(0), checksum(0), rso(0x40), option(2) + { + memset(padding, 0, sizeof(padding)); + memset(target, 0, sizeof(target)); + } - void calculateChecksum(const sockaddr_storage &sourceIp, const InetAddress &destIp) { - _pseudo_header ph; - memset(&ph, 0, sizeof(_pseudo_header)); - const sockaddr_in6 *src = (const sockaddr_in6*)&sourceIp; - const sockaddr_in6 *dest = (const sockaddr_in6*)&destIp; + void calculateChecksum(const sockaddr_storage &sourceIp, const InetAddress &destIp) + { + _pseudo_header ph; + memset(&ph, 0, sizeof(_pseudo_header)); + const sockaddr_in6 *src = (const sockaddr_in6 *)&sourceIp; + const sockaddr_in6 *dest = (const sockaddr_in6 *)&destIp; - memcpy(ph.sourceAddr, &src->sin6_addr, sizeof(struct in6_addr)); - memcpy(ph.targetAddr, &dest->sin6_addr, sizeof(struct in6_addr)); - ph.next = 58; - ph.length = htonl(sizeof(_neighbor_advertisement)); + memcpy(ph.sourceAddr, &src->sin6_addr, sizeof(struct in6_addr)); + memcpy(ph.targetAddr, &dest->sin6_addr, sizeof(struct in6_addr)); + ph.next = 58; + ph.length = htonl(sizeof(_neighbor_advertisement)); - size_t len = sizeof(_pseudo_header) + sizeof(_neighbor_advertisement); - uint8_t *tmp = (uint8_t*)malloc(len); - memcpy(tmp, &ph, sizeof(_pseudo_header)); - memcpy(tmp+sizeof(_pseudo_header), this, sizeof(_neighbor_advertisement)); + size_t len = sizeof(_pseudo_header) + sizeof(_neighbor_advertisement); + uint8_t *tmp = (uint8_t *)malloc(len); + memcpy(tmp, &ph, sizeof(_pseudo_header)); + memcpy(tmp + sizeof(_pseudo_header), this, sizeof(_neighbor_advertisement)); - checksum = calc_checksum((uint16_t*)tmp, (int)len); + checksum = calc_checksum((uint16_t *)tmp, (int)len); - free(tmp); - tmp = NULL; - } + free(tmp); + tmp = NULL; + } - uint8_t type; // 136 - uint8_t code; // 0 - uint16_t checksum; - uint8_t rso; - uint8_t padding[3]; - uint8_t target[16]; - _option option; + uint8_t type; // 136 + uint8_t code; // 0 + uint16_t checksum; + uint8_t rso; + uint8_t padding[3]; + uint8_t target[16]; + _option option; }; NeighborDiscovery::NeighborDiscovery() - : _cache() - , _lastCleaned(OSUtils::now()) + : _cache(), _lastCleaned(OSUtils::now()) {} void NeighborDiscovery::addLocal(const sockaddr_storage &address, const MAC &mac) { - _NDEntry &e = _cache[InetAddress(address)]; - e.lastQuerySent = 0; - e.lastResponseReceived = 0; - e.mac = mac; - e.local = true; + _NDEntry &e = _cache[InetAddress(address)]; + e.lastQuerySent = 0; + e.lastResponseReceived = 0; + e.mac = mac; + e.local = true; } void NeighborDiscovery::remove(const sockaddr_storage &address) { - _cache.erase(InetAddress(address)); + _cache.erase(InetAddress(address)); } sockaddr_storage NeighborDiscovery::processIncomingND(const uint8_t *nd, unsigned int len, const sockaddr_storage &localIp, uint8_t *response, unsigned int &responseLen, MAC &responseDest) { - // assert(sizeof(_neighbor_solicitation) == 28); - // assert(sizeof(_neighbor_advertisement) == 32); + // assert(sizeof(_neighbor_solicitation) == 28); + // assert(sizeof(_neighbor_advertisement) == 32); - const uint64_t now = OSUtils::now(); - InetAddress ip; + const uint64_t now = OSUtils::now(); + InetAddress ip; - if (len >= sizeof(_neighbor_solicitation) && nd[0] == 0x87) { - // respond to Neighbor Solicitation request for local address - _neighbor_solicitation solicitation; - memcpy(&solicitation, nd, len); - InetAddress targetAddress(solicitation.target, 16, 0); - _NDEntry *targetEntry = _cache.get(targetAddress); - if (targetEntry && targetEntry->local) { - _neighbor_advertisement adv; - targetEntry->mac.copyTo(adv.option.mac); - memcpy(adv.target, solicitation.target, 16); - adv.calculateChecksum(localIp, targetAddress); - memcpy(response, &adv, sizeof(_neighbor_advertisement)); - responseLen = sizeof(_neighbor_advertisement); - responseDest.setTo(solicitation.option.mac); - } - } else if (len >= sizeof(_neighbor_advertisement) && nd[0] == 0x88) { - _neighbor_advertisement adv; - memcpy(&adv, nd, len); - InetAddress responseAddress(adv.target, 16, 0); - _NDEntry *queryEntry = _cache.get(responseAddress); - if(queryEntry && !queryEntry->local && (now - queryEntry->lastQuerySent <= ZT_ND_QUERY_MAX_TTL)) { - queryEntry->lastResponseReceived = now; - queryEntry->mac.setTo(adv.option.mac); - ip = responseAddress; - } - } + if (len >= sizeof(_neighbor_solicitation) && nd[0] == 0x87) { + // respond to Neighbor Solicitation request for local address + _neighbor_solicitation solicitation; + memcpy(&solicitation, nd, len); + InetAddress targetAddress(solicitation.target, 16, 0); + Map::const_iterator targetEntry(_cache.find(targetAddress)); + if ((targetEntry != _cache.end()) && targetEntry->second.local) { + _neighbor_advertisement adv; + targetEntry->second.mac.copyTo(adv.option.mac); + memcpy(adv.target, solicitation.target, 16); + adv.calculateChecksum(localIp, targetAddress); + memcpy(response, &adv, sizeof(_neighbor_advertisement)); + responseLen = sizeof(_neighbor_advertisement); + responseDest.setTo(solicitation.option.mac); + } + } else if (len >= sizeof(_neighbor_advertisement) && nd[0] == 0x88) { + _neighbor_advertisement adv; + memcpy(&adv, nd, len); + InetAddress responseAddress(adv.target, 16, 0); + Map::iterator queryEntry(_cache.find(responseAddress)); + if ((queryEntry != _cache.end()) && !queryEntry->second.local && (now - queryEntry->second.lastQuerySent <= ZT_ND_QUERY_MAX_TTL)) { + queryEntry->second.lastResponseReceived = now; + queryEntry->second.mac.setTo(adv.option.mac); + ip = responseAddress; + } + } - if ((now - _lastCleaned) >= ZT_ND_EXPIRE) { - _lastCleaned = now; - for(Map::iterator i(_cache.begin());i!=_cache.end();) { - if(!i->second.local && (now - i->second.lastResponseReceived) >= ZT_ND_EXPIRE) { - _cache.erase(i++); - } else { - ++i; - } - } - } + if ((now - _lastCleaned) >= ZT_ND_EXPIRE) { + _lastCleaned = now; + for (Map< InetAddress, _NDEntry >::iterator i(_cache.begin()); i != _cache.end();) { + if (!i->second.local && (now - i->second.lastResponseReceived) >= ZT_ND_EXPIRE) { + _cache.erase(i++); + } else { + ++i; + } + } + } - return *reinterpret_cast(&ip); + return *reinterpret_cast(&ip); } MAC NeighborDiscovery::query(const MAC &localMac, const sockaddr_storage &localIp, const sockaddr_storage &targetIp, uint8_t *query, unsigned int &queryLen, MAC &queryDest) { - const uint64_t now = OSUtils::now(); + const uint64_t now = OSUtils::now(); - InetAddress localAddress(localIp); - localAddress.setPort(0); - InetAddress targetAddress(targetIp); - targetAddress.setPort(0); + InetAddress localAddress(localIp); + localAddress.setPort(0); + InetAddress targetAddress(targetIp); + targetAddress.setPort(0); - _NDEntry &e = _cache[targetAddress]; + _NDEntry &e = _cache[targetAddress]; - if ( (e.mac && ((now - e.lastResponseReceived) >= (ZT_ND_EXPIRE / 3))) || - (!e.mac && ((now - e.lastQuerySent) >= ZT_ND_QUERY_INTERVAL))) { - e.lastQuerySent = now; + if ((e.mac && ((now - e.lastResponseReceived) >= (ZT_ND_EXPIRE / 3))) || + (!e.mac && ((now - e.lastQuerySent) >= ZT_ND_QUERY_INTERVAL))) { + e.lastQuerySent = now; - _neighbor_solicitation ns; - memcpy(ns.target, targetAddress.rawIpData(), 16); - localMac.copyTo(ns.option.mac); - ns.calculateChecksum(localIp, targetIp); - if (e.mac) { - queryDest = e.mac; - } else { - queryDest = (uint64_t)0xffffffffffffULL; - } - } else { - queryLen = 0; - queryDest.zero(); - } + _neighbor_solicitation ns; + memcpy(ns.target, targetAddress.rawIpData(), 16); + localMac.copyTo(ns.option.mac); + ns.calculateChecksum(localIp, targetIp); + if (e.mac) { + queryDest = e.mac; + } else { + queryDest = (uint64_t)0xffffffffffffULL; + } + } else { + queryLen = 0; + queryDest.zero(); + } - return e.mac; + return e.mac; } } diff --git a/osdep/NeighborDiscovery.hpp b/osdep/NeighborDiscovery.hpp index 66aafeddf..51b0b2f3a 100644 --- a/osdep/NeighborDiscovery.hpp +++ b/osdep/NeighborDiscovery.hpp @@ -27,39 +27,41 @@ namespace ZeroTier { class NeighborDiscovery { public: - NeighborDiscovery(); + NeighborDiscovery(); - /** - * Set a local IP entry that we should respond to Neighbor Requests withPrefix64k - * - * @param mac Our local MAC address - * @param ip Our IPv6 address - */ - void addLocal(const sockaddr_storage &address, const MAC &mac); + /** + * Set a local IP entry that we should respond to Neighbor Requests withPrefix64k + * + * @param mac Our local MAC address + * @param ip Our IPv6 address + */ + void addLocal(const sockaddr_storage &address, const MAC &mac); - /** - * Delete a local IP entry or cached Neighbor entry - * - * @param address IPv6 address to remove - */ - void remove(const sockaddr_storage &address); + /** + * Delete a local IP entry or cached Neighbor entry + * + * @param address IPv6 address to remove + */ + void remove(const sockaddr_storage &address); - sockaddr_storage processIncomingND(const uint8_t *nd, unsigned int len, const sockaddr_storage &localIp, uint8_t *response, unsigned int &responseLen, MAC &responseDest); + sockaddr_storage processIncomingND(const uint8_t *nd, unsigned int len, const sockaddr_storage &localIp, uint8_t *response, unsigned int &responseLen, MAC &responseDest); - MAC query(const MAC &localMac, const sockaddr_storage &localIp, const sockaddr_storage &targetIp, uint8_t *query, unsigned int &queryLen, MAC &queryDest); + MAC query(const MAC &localMac, const sockaddr_storage &localIp, const sockaddr_storage &targetIp, uint8_t *query, unsigned int &queryLen, MAC &queryDest); private: - struct _NDEntry - { - _NDEntry() : lastQuerySent(0), lastResponseReceived(0), mac(), local(false) {} - uint64_t lastQuerySent; - uint64_t lastResponseReceived; - MAC mac; - bool local; - }; + struct _NDEntry + { + _NDEntry() : lastQuerySent(0), lastResponseReceived(0), mac(), local(false) + {} - Map< InetAddress,_NDEntry > _cache; - uint64_t _lastCleaned; + uint64_t lastQuerySent; + uint64_t lastResponseReceived; + MAC mac; + bool local; + }; + + Map< InetAddress, _NDEntry > _cache; + uint64_t _lastCleaned; }; } // namespace ZeroTier