Bladeren bron

Cleanup, remove legacy accessors, formatting.

Adam Ierymenko 5 jaren geleden
bovenliggende
commit
a19bc1e826

+ 1 - 1
cmd/zerotier/cli/controller.go → 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) {
 }

+ 1 - 1
cmd/zerotier/cli/help.go

@@ -79,7 +79,7 @@ Commands:
     validate <identity>                  Locally validate an identity
     sign <identity> <file>               Sign a file with an identity's key
     verify <identity> <file> <sig>       Verify a signature
-  certificate <command> [args]         - Certificate commands
+  cert <command> [args]                - Certificate commands
     newid                                Create a new unique subject ID
     newcsr <subject json path>           Create a new CSR (signing request)
     sign <csr path> <identity path>      Sign a CSR to create a certificate

+ 3 - 2
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)
 }

+ 11 - 49
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<typename K,typename V>
-class Map : public std::map< K,V,std::less<K> >
-{
-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)[key] = value; }
-};
+template<typename K, typename V>
+class Map : public std::map< K, V >
+{};
 
-template<typename K,typename V>
-class MultiMap : public std::multimap< K,V,std::less<K>,Utils::Mallocator< std::pair<const K,V> > >
-{
-};
+template<typename K, typename V>
+class MultiMap : public std::multimap< K, V >
+{};
 
 #endif
 

+ 18 - 13
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<std::pair<int64_t, uint64_t> > messagesByLastUsedTime;
+				std::vector< std::pair< int64_t, uint64_t > > messagesByLastUsedTime;
 				messagesByLastUsedTime.reserve(m_messages.size());
 
-				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));
+				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 <uint64_t, Defragmenter<MF, MFP, GCS, GCT, P>::p_E> m_messages;
+	Map <uint64_t, Defragmenter< MF, MFP, GCS, GCT, P >::p_E> m_messages;
 	RWMutex m_messages_l;
 };
 

+ 9 - 10
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;

+ 5 - 6
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;
 	}

+ 185 - 177
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<ruleCount;++rn) {
+	for (unsigned int rn = 0; rn < ruleCount; ++rn) {
 		const ZT_VirtualNetworkRuleType rt = (ZT_VirtualNetworkRuleType)(rules[rn].t & 0x3fU);
 
 		// First check if this is an ACTION
 		if ((unsigned int)rt <= (unsigned int)ZT_NETWORK_RULE_ACTION__MAX_ID) {
 			if (thisSetMatches) {
-				switch(rt) {
+				switch (rt) {
 					case ZT_NETWORK_RULE_ACTION_PRIORITY:
 						qosBucket = (rules[rn].v.qosBucket >= 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<InetAddress>(nconf,src)))
+							if ((src) && (membership->peerOwnsAddress< InetAddress >(nconf, src)))
 								ownershipVerificationMask |= ZT_RULE_PACKET_CHARACTERISTICS_SENDER_IP_AUTHENTICATED;
-							if (membership->peerOwnsAddress<MAC>(nconf,macSource))
+							if (membership->peerOwnsAddress< MAC >(nconf, macSource))
 								ownershipVerificationMask |= ZT_RULE_PACKET_CHARACTERISTICS_SENDER_MAC_AUTHENTICATED;
 						}
 					} else {
-						for(unsigned int i=0;i<nconf.certificateOfOwnershipCount;++i) {
-							if ((src)&&(nconf.certificatesOfOwnership[i].owns(src)))
+						for (unsigned int i = 0; i < nconf.certificateOfOwnershipCount; ++i) {
+							if ((src) && (nconf.certificatesOfOwnership[i].owns(src)))
 								ownershipVerificationMask |= ZT_RULE_PACKET_CHARACTERISTICS_SENDER_IP_AUTHENTICATED;
 							if (nconf.certificatesOfOwnership[i].owns(macSource))
 								ownershipVerificationMask |= ZT_RULE_PACKET_CHARACTERISTICS_SENDER_MAC_AUTHENTICATED;
@@ -394,23 +395,24 @@ _doZtFilterResult _doZtFilter(
 					}
 				}
 				cf |= ownershipVerificationMask;
-				if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 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<uint8_t> 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<NetworkConfig> 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<Address, Member>::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<Peer> &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<MulticastGroup>::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<Peer> &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<uint8_t> 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> &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> &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<Address,Member>::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<MAC,Address>::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<MAC,Address>::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<Peer> &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<NetworkConfig> 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<NetworkConfig> 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<Address> 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<ZT_MAX_ZT_ASSIGNED_ADDRESSES;++i) {
+	for (unsigned int i = 0; i < ZT_MAX_ZT_ASSIGNED_ADDRESSES; ++i) {
 		if (i < m_config.staticIpCount) {
-			Utils::copy<sizeof(struct sockaddr_storage)>(&(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<sizeof(struct sockaddr_storage)>(&(ec->assignedAddresses[i]));
+			Utils::zero< sizeof(struct sockaddr_storage) >(&(ec->assignedAddresses[i]));
 		}
 	}
 
 	ec->routeCount = 0;
-	for(unsigned int i=0;i<ZT_MAX_NETWORK_ROUTES;++i) {
+	for (unsigned int i = 0; i < ZT_MAX_NETWORK_ROUTES; ++i) {
 		if (i < m_config.routeCount) {
-			Utils::copy<sizeof(ZT_VirtualNetworkRoute)>(&(ec->routes[i]),&(m_config.routes[i]));
+			Utils::copy< sizeof(ZT_VirtualNetworkRoute) >(&(ec->routes[i]), &(m_config.routes[i]));
 			++ec->routeCount;
 		} else {
-			Utils::zero<sizeof(ZT_VirtualNetworkRoute)>(&(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<MulticastGroup> groups(m_allMulticastGroups());
+	const Vector< MulticastGroup > groups(m_allMulticastGroups());
 	m_announceMulticastGroupsTo(tPtr, controller(), groups);
 
-		// TODO
-		/*
-	Address *a = nullptr;
-	Membership *m = nullptr;
-	Hashtable<Address,Membership>::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<Address,Membership>::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<MulticastGroup> &allMulticastGroups)
+void Network::m_announceMulticastGroupsTo(void *tPtr, const Address &peer, const Vector< MulticastGroup > &allMulticastGroups)
 {
 #if 0
 	// Assumes _myMulticastGroups_l and _memberships_l are locked
@@ -1523,18 +1531,18 @@ void Network::m_announceMulticastGroupsTo(void *tPtr, const Address &peer, const
 #endif
 }
 
-Vector<MulticastGroup> Network::m_allMulticastGroups() const
+Vector< MulticastGroup > Network::m_allMulticastGroups() const
 {
 	// Assumes _myMulticastGroups_l is locked
-	Vector<MulticastGroup> 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<MulticastGroup,int64_t>::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;
 }
 

+ 65 - 40
core/Network.hpp

@@ -32,6 +32,7 @@
 namespace ZeroTier {
 
 class RuntimeEnvironment;
+
 class Peer;
 
 /**
@@ -39,7 +40,7 @@ class Peer;
  */
 class Network
 {
-	friend class SharedPtr<Network>;
+	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<Peer> &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<Peer> &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> &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<Peer> &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<typename F>
+	template< typename F >
 	ZT_INLINE void eachMember(F f)
 	{
 		Mutex::Lock ml(m_memberships_l);
-		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))
+		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<MulticastGroup> &allMulticastGroups);
-	Vector<MulticastGroup> 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<bool> m_destroyed;
+	std::atomic< bool > m_destroyed;
 
-	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)
+	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<int64_t> 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<Address,Member> 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<int> __refCount;
+	std::atomic< int > __refCount;
 };
 
 } // namespace ZeroTier

+ 4 - 3
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<Node::p_LocalControllerAuth, int64_t>::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;
 }
 

+ 14 - 14
core/Node.hpp

@@ -55,7 +55,7 @@ public:
 		int64_t now,
 		int64_t localSocket,
 		const struct sockaddr_storage *remoteAddress,
-		SharedPtr<Buf> &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<Buf> &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> 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<Network> *const n = m_networks.get(nwid);
-		if (n)
-			return *n;
-		return SharedPtr<Network>();
+		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<ZT_InterfaceAddress> 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<uint8_t> 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<p_LocalControllerAuth, int64_t> m_localControllerAuthorizations;
+	Map< p_LocalControllerAuth, int64_t > m_localControllerAuthorizations;
 	Mutex m_localControllerAuthorizations_l;
 
 	// Locally joined networks by network ID.
-	Map<uint64_t, SharedPtr<Network> > 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<ZT_InterfaceAddress> 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<int64_t> m_now;
+	std::atomic< int64_t > m_now;
 
 	// True if at least one root appears reachable.
-	std::atomic<bool> m_online;
+	std::atomic< bool > m_online;
 };
 
 } // namespace ZeroTier

+ 14 - 0
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

+ 17 - 20
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;

+ 31 - 27
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<const uint32_t *>(arp)[6]);
-			if ((targetEntry)&&(targetEntry->local)) {
-				memcpy(response,ARP_RESPONSE_HEADER,8);
-				targetEntry->mac.copyTo(reinterpret_cast<uint8_t *>(response) + 8);
-				memcpy(reinterpret_cast<uint8_t *>(response) + 14,reinterpret_cast<const uint8_t *>(arp) + 24,4);
-				memcpy(reinterpret_cast<uint8_t *>(response) + 18,reinterpret_cast<const uint8_t *>(arp) + 8,10);
+			Map< uint32_t, Arp::_ArpEntry >::const_iterator targetEntry(_cache.find(reinterpret_cast<const uint32_t *>(arp)[6]));
+			if ((targetEntry != _cache.end()) && (targetEntry->second.local)) {
+				memcpy(response, ARP_RESPONSE_HEADER, 8);
+				targetEntry->second.mac.copyTo(reinterpret_cast<uint8_t *>(response) + 8);
+				memcpy(reinterpret_cast<uint8_t *>(response) + 14, reinterpret_cast<const uint8_t *>(arp) + 24, 4);
+				memcpy(reinterpret_cast<uint8_t *>(response) + 18, reinterpret_cast<const uint8_t *>(arp) + 8, 10);
 				responseLen = 28;
 				responseDest.setTo(reinterpret_cast<const uint8_t *>(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<const uint8_t *>(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<const uint8_t *>(arp) + 8);
+			memcpy(&responseIp, reinterpret_cast<const uint8_t *>(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<const uint8_t *>(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<uint8_t *>(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

+ 58 - 57
osdep/LinuxNetLink.hpp

@@ -47,70 +47,71 @@ typedef std::vector<route_entry> 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);
-
-    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();
-
-    int _indexForInterface(const char *iface);
-
-    void _setSocketTimeout(int fd, int seconds = 1);
-
-    Thread _t;
-    bool _running;
-
-    RouteList _routes_ipv4;
-    Mutex _rv4_m;
-    RouteList _routes_ipv6;
-    Mutex _rv6_m;
-
-    uint32_t _seq;
-
-    struct iface_entry {
-        int index;
-        char ifacename[IFNAMSIZ];
-        char mac[18];
-        char mac_bin[6];
-        unsigned int mtu;
-    };
-    std::map<int, iface_entry> _interfaces;
-    Mutex _if_m;
-
-    // socket communication vars;
-    int _fd;
-    struct sockaddr_nl _la;
+	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 _requestInterfaceList();
+	void _requestIPv4Routes();
+	void _requestIPv6Routes();
+
+	int _indexForInterface(const char *iface);
+
+	void _setSocketTimeout(int fd, int seconds = 1);
+
+	Thread _t;
+	bool _running;
+
+	RouteList _routes_ipv4;
+	Mutex _rv4_m;
+	RouteList _routes_ipv6;
+	Mutex _rv6_m;
+
+	uint32_t _seq;
+
+	struct iface_entry {
+		int index;
+		char ifacename[IFNAMSIZ];
+		char mac[18];
+		char mac_bin[6];
+		unsigned int mtu;
+	};
+	std::map<int, iface_entry> _interfaces;
+	Mutex _if_m;
+
+	// socket communication vars;
+	int _fd;
+	struct sockaddr_nl _la;
 };
 
 }

+ 202 - 205
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;
-
-    // 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;
-    }
-
-    // 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;
-
-    return (answer);
+	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;
+	}
+
+	// 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);
+	}
+
+	// Checksum is one's compliment of sum.
+	answer = ~sum;
+
+	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));
-    }
-
-    uint8_t type;
-    uint8_t length;
-    uint8_t mac[6];
+struct _option
+{
+	_option(int optionType)
+		: type(optionType), length(8)
+	{
+		memset(mac, 0, sizeof(mac));
+	}
+
+	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));
-    }
-
-    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));
-
-        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);
-
-        free(tmp);
-        tmp = NULL;
-    }
-
-    uint8_t type; // 135
-    uint8_t code; // 0
-    uint16_t checksum;
-    uint32_t reserved;
-    uint8_t target[16];
-    _option option;
+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;
+
+		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));
+
+		checksum = calc_checksum((uint16_t *)tmp, (int)len);
+
+		free(tmp);
+		tmp = NULL;
+	}
+
+	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));
-    }
-
-    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));
-
-        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);
-
-        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;
+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;
+
+		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));
+
+		checksum = calc_checksum((uint16_t *)tmp, (int)len);
+
+		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;
 };
 
 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);
-
-    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 ((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<sockaddr_storage *>(&ip);
+	// assert(sizeof(_neighbor_solicitation) == 28);
+	// assert(sizeof(_neighbor_advertisement) == 32);
+
+	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);
+		Map<InetAddress, NeighborDiscovery::_NDEntry>::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<InetAddress, NeighborDiscovery::_NDEntry>::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< 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<sockaddr_storage *>(&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();
-
-    InetAddress localAddress(localIp);
-    localAddress.setPort(0);
-    InetAddress targetAddress(targetIp);
-    targetAddress.setPort(0);
-
-    _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;
-
-        _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;
+	const uint64_t now = OSUtils::now();
+
+	InetAddress localAddress(localIp);
+	localAddress.setPort(0);
+	InetAddress targetAddress(targetIp);
+	targetAddress.setPort(0);
+
+	_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;
+
+		_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;
 }
 
 }

+ 28 - 26
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