Parcourir la source

Some symbol renaming, performance improvements, a bug fix for compiling on some platforms, and some Topology work.

Adam Ierymenko il y a 5 ans
Parent
commit
92d2bbc63c

+ 8 - 8
core/AES.cpp

@@ -349,8 +349,8 @@ void AES::GMAC::update(const void *const data, unsigned int len) noexcept
 			--len;
 			_r[_rp++] = *(in++);
 			if (_rp == 16) {
-				y0 ^= Utils::loadAsIsEndian< uint64_t >(_r);
-				y1 ^= Utils::loadAsIsEndian< uint64_t >(_r + 8);
+				y0 ^= Utils::loadMachineEndian< uint64_t >(_r);
+				y1 ^= Utils::loadMachineEndian< uint64_t >(_r + 8);
 				s_gfmul(h0, h1, y0, y1);
 				break;
 			}
@@ -358,8 +358,8 @@ void AES::GMAC::update(const void *const data, unsigned int len) noexcept
 	}
 
 	while (len >= 16) {
-		y0 ^= Utils::loadAsIsEndian< uint64_t >(in);
-		y1 ^= Utils::loadAsIsEndian< uint64_t >(in + 8);
+		y0 ^= Utils::loadMachineEndian< uint64_t >(in);
+		y1 ^= Utils::loadMachineEndian< uint64_t >(in + 8);
 		s_gfmul(h0, h1, y0, y1);
 		in += 16;
 		len -= 16;
@@ -488,8 +488,8 @@ void AES::GMAC::finish(uint8_t tag[16]) noexcept
 	if (_rp) {
 		while (_rp < 16)
 			_r[_rp++] = 0;
-		y0 ^= Utils::loadAsIsEndian< uint64_t >(_r);
-		y1 ^= Utils::loadAsIsEndian< uint64_t >(_r + 8);
+		y0 ^= Utils::loadMachineEndian< uint64_t >(_r);
+		y1 ^= Utils::loadMachineEndian< uint64_t >(_r + 8);
 		s_gfmul(h0, h1, y0, y1);
 	}
 
@@ -504,8 +504,8 @@ void AES::GMAC::finish(uint8_t tag[16]) noexcept
 	((uint8_t *)iv2)[15] = 1;
 	_aes._encryptSW((const uint8_t *)iv2, (uint8_t *)iv2);
 
-	Utils::storeAsIsEndian< uint64_t >(tag, iv2[0] ^ y0);
-	Utils::storeAsIsEndian< uint64_t >(tag + 8, iv2[1] ^ y1);
+	Utils::storeMachineEndian< uint64_t >(tag, iv2[0] ^ y0);
+	Utils::storeMachineEndian< uint64_t >(tag + 8, iv2[1] ^ y1);
 }
 
 // AES-CTR ------------------------------------------------------------------------------------------------------------

+ 82 - 18
core/Blob.hpp

@@ -16,37 +16,101 @@
 
 #include "Constants.hpp"
 #include "Utils.hpp"
+#include "TriviallyCopyable.hpp"
+
+#include <algorithm>
+
+// This header contains simple statically sized binary object types.
 
 namespace ZeroTier {
 
 /**
- * Container for arbitrary bytes for use in collections
- *
- * @tparam S Size of container in bytes
+ * Blob type for SHA384 hashes
  */
-template<unsigned int S>
-struct Blob
+struct SHA384Hash
 {
-	uint8_t data[S];
+	uint64_t data[6];
+
+	ZT_INLINE SHA384Hash() noexcept
+	{ Utils::zero< 48 >(data); }
 
-	ZT_INLINE Blob() noexcept { Utils::zero<S>(data); }
-	explicit ZT_INLINE Blob(const void *const d) noexcept { Utils::copy<S>(data,d); }
+	explicit ZT_INLINE SHA384Hash(const void *const d) noexcept
+	{ Utils::copy< 48 >(data, d); }
+
+	ZT_INLINE const uint8_t *bytes() const noexcept
+	{ return reinterpret_cast<const uint8_t *>(data); }
 
 	ZT_INLINE unsigned long hashCode() const noexcept
-	{ return (unsigned long)Utils::fnv1a32(data, S); }
+	{ return (unsigned long)data[0]; }
+
+	ZT_INLINE operator bool() const noexcept
+	{ return ((data[0] != 0) && (data[1] != 0) && (data[2] != 0) && (data[3] != 0) && (data[4] != 0) && (data[5] != 0)); }
+
+	ZT_INLINE bool operator==(const SHA384Hash &b) const noexcept
+	{ return ((data[0] == b.data[0]) && (data[1] == b.data[1]) && (data[2] == b.data[2]) && (data[3] == b.data[3]) && (data[4] == b.data[4]) && (data[5] == b.data[5])); }
 
-	ZT_INLINE operator bool() const noexcept { return !Utils::allZero(data); }
+	ZT_INLINE bool operator!=(const SHA384Hash &b) const noexcept
+	{ return !(*this == b); }
 
-	ZT_INLINE bool operator==(const Blob &b) const noexcept { return (memcmp(data,b.data,S) == 0); }
-	ZT_INLINE bool operator!=(const Blob &b) const noexcept { return (memcmp(data,b.data,S) != 0); }
-	ZT_INLINE bool operator<(const Blob &b) const noexcept { return (memcmp(data,b.data,S) < 0); }
-	ZT_INLINE bool operator>(const Blob &b) const noexcept { return (memcmp(data,b.data,S) > 0); }
-	ZT_INLINE bool operator<=(const Blob &b) const noexcept { return (memcmp(data,b.data,S) <= 0); }
-	ZT_INLINE bool operator>=(const Blob &b) const noexcept { return (memcmp(data,b.data,S) >= 0); }
+	ZT_INLINE bool operator<(const SHA384Hash &b) const noexcept
+	{ return (memcmp(data, b.data, 48) < 0); }
+
+	ZT_INLINE bool operator>(const SHA384Hash &b) const noexcept
+	{ return (memcmp(data, b.data, 48) > 0); }
+
+	ZT_INLINE bool operator<=(const SHA384Hash &b) const noexcept
+	{ return (memcmp(data, b.data, 48) <= 0); }
+
+	ZT_INLINE bool operator>=(const SHA384Hash &b) const noexcept
+	{ return (memcmp(data, b.data, 48) >= 0); }
 };
 
-typedef Blob<48> SHA384Hash;
-typedef Blob<16> GUID;
+/**
+ * Blob type for 128-bit GUIDs, UUIDs, etc.
+ */
+struct UniqueID
+{
+	uint64_t data[2];
+
+	ZT_INLINE UniqueID() noexcept
+	{}
+
+	ZT_INLINE UniqueID(const uint64_t a, const uint64_t b) noexcept
+	{
+		data[0] = a;
+		data[1] = b;
+	}
+
+	explicit ZT_INLINE UniqueID(const void *const d) noexcept
+	{ Utils::copy< 16 >(data, d); }
+
+	ZT_INLINE const uint8_t *bytes() const noexcept
+	{ return reinterpret_cast<const uint8_t *>(data); }
+
+	ZT_INLINE unsigned long hashCode() const noexcept
+	{ return (unsigned long)data[1]; }
+
+	ZT_INLINE operator bool() const noexcept
+	{ return ((data[0] != 0) && (data[1] != 0)); }
+
+	ZT_INLINE bool operator==(const SHA384Hash &b) const noexcept
+	{ return ((data[0] == b.data[0]) && (data[1] == b.data[1])); }
+
+	ZT_INLINE bool operator!=(const SHA384Hash &b) const noexcept
+	{ return !(*this == b); }
+
+	ZT_INLINE bool operator<(const SHA384Hash &b) const noexcept
+	{ return (memcmp(data, b.data, 16) < 0); }
+
+	ZT_INLINE bool operator>(const SHA384Hash &b) const noexcept
+	{ return (memcmp(data, b.data, 16) > 0); }
+
+	ZT_INLINE bool operator<=(const SHA384Hash &b) const noexcept
+	{ return (memcmp(data, b.data, 16) <= 0); }
+
+	ZT_INLINE bool operator>=(const SHA384Hash &b) const noexcept
+	{ return (memcmp(data, b.data, 16) >= 0); }
+};
 
 } // namespace ZeroTier
 

+ 1 - 1
core/Certificate.cpp

@@ -151,7 +151,7 @@ void Certificate::addSubjectCertificate(const uint8_t serialNo[ZT_SHA384_DIGEST_
 	// Enlarge array of uint8_t pointers, set new pointer to local copy of serial, and set
 	// certificates to point to potentially reallocated array.
 	m_subjectCertificates.resize(++this->subject.certificateCount);
-	m_subjectCertificates.back() = m_serials.back().data;
+	m_subjectCertificates.back() = m_serials.back().bytes();
 	this->subject.certificates = m_subjectCertificates.data();
 }
 

+ 1 - 1
core/Certificate.hpp

@@ -182,7 +182,7 @@ public:
 	}
 
 	ZT_INLINE unsigned long hashCode() const noexcept
-	{ return (unsigned long)Utils::loadAsIsEndian< uint32_t >(this->serialNo); }
+	{ return (unsigned long)Utils::loadMachineEndian< uint32_t >(this->serialNo); }
 
 	ZT_INLINE bool operator==(const ZT_Certificate &c) const noexcept
 	{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) == 0; }

+ 4 - 4
core/InetAddress.cpp

@@ -106,7 +106,7 @@ void InetAddress::set(const void *ipBytes, unsigned int ipLen, unsigned int port
 	if (ipLen == 4) {
 		as.sa_in.sin_family = AF_INET;
 		as.sa_in.sin_port = Utils::hton((uint16_t) port);
-		as.sa_in.sin_addr.s_addr = Utils::loadAsIsEndian<uint32_t>(ipBytes);
+		as.sa_in.sin_addr.s_addr = Utils::loadMachineEndian< uint32_t >(ipBytes);
 	} else if (ipLen == 16) {
 		as.sa_in6.sin6_family = AF_INET6;
 		as.sa_in6.sin6_port = Utils::hton((uint16_t) port);
@@ -369,14 +369,14 @@ int InetAddress::unmarshal(const uint8_t *restrict data, const int len) noexcept
 			if (unlikely(len < 7))
 				return -1;
 			as.sa_in.sin_family = AF_INET;
-			as.sa_in.sin_port = Utils::loadAsIsEndian<uint16_t>(data + 5);
-			as.sa_in.sin_addr.s_addr = Utils::loadAsIsEndian<uint32_t>(data + 1);
+			as.sa_in.sin_port = Utils::loadMachineEndian< uint16_t >(data + 5);
+			as.sa_in.sin_addr.s_addr = Utils::loadMachineEndian< uint32_t >(data + 1);
 			return 7;
 		case 6:
 			if (unlikely(len < 19))
 				return -1;
 			as.sa_in6.sin6_family = AF_INET6;
-			as.sa_in6.sin6_port = Utils::loadAsIsEndian<uint16_t>(data + 17);
+			as.sa_in6.sin6_port = Utils::loadMachineEndian< uint16_t >(data + 17);
 			Utils::copy<16>(as.sa_in6.sin6_addr.s6_addr, data + 1);
 			return 19;
 		default:

+ 43 - 14
core/InetAddress.hpp

@@ -19,6 +19,7 @@
 #include "MAC.hpp"
 #include "Containers.hpp"
 #include "TriviallyCopyable.hpp"
+#include "Blob.hpp"
 
 namespace ZeroTier {
 
@@ -74,7 +75,7 @@ public:
 	struct Hasher
 	{
 		ZT_INLINE std::size_t operator()(const InetAddress &a) const noexcept
-		{ return (std::size_t) a.hashCode(); }
+		{ return (std::size_t)a.hashCode(); }
 	};
 
 	ZT_INLINE InetAddress() noexcept
@@ -211,10 +212,10 @@ public:
 	{
 		switch (as.ss.ss_family) {
 			case AF_INET:
-				as.sa_in.sin_port = Utils::hton((uint16_t) port);
+				as.sa_in.sin_port = Utils::hton((uint16_t)port);
 				break;
 			case AF_INET6:
-				as.sa_in6.sin6_port = Utils::hton((uint16_t) port);
+				as.sa_in6.sin6_port = Utils::hton((uint16_t)port);
 				break;
 		}
 	}
@@ -387,7 +388,7 @@ public:
 				break;
 			case AF_INET6:
 				r.as.sa_in6.sin6_family = AF_INET6;
-				Utils::copy<16>(r.as.sa_in6.sin6_addr.s6_addr, as.sa_in6.sin6_addr.s6_addr);
+				Utils::copy< 16 >(r.as.sa_in6.sin6_addr.s6_addr, as.sa_in6.sin6_addr.s6_addr);
 				break;
 		}
 		return r;
@@ -436,12 +437,12 @@ public:
 	ZT_INLINE unsigned long hashCode() const noexcept
 	{
 		if (as.ss.ss_family == AF_INET) {
-			return (unsigned long) Utils::hash32(((uint32_t) as.sa_in.sin_addr.s_addr + (uint32_t) as.sa_in.sin_port) ^ (uint32_t) Utils::s_mapNonce);
+			return (unsigned long)Utils::hash32(((uint32_t)as.sa_in.sin_addr.s_addr + (uint32_t)as.sa_in.sin_port) ^ (uint32_t)Utils::s_mapNonce);
 		} else if (as.ss.ss_family == AF_INET6) {
-			return (unsigned long) Utils::hash64(
-				(Utils::loadAsIsEndian<uint64_t>(as.sa_in6.sin6_addr.s6_addr) +
-				 Utils::loadAsIsEndian<uint64_t>(as.sa_in6.sin6_addr.s6_addr + 8) +
-				 (uint64_t) as.sa_in6.sin6_port) ^
+			return (unsigned long)Utils::hash64(
+				(Utils::loadMachineEndian< uint64_t >(as.sa_in6.sin6_addr.s6_addr) +
+				 Utils::loadMachineEndian< uint64_t >(as.sa_in6.sin6_addr.s6_addr + 8) +
+				 (uint64_t)as.sa_in6.sin6_port) ^
 				Utils::s_mapNonce);
 		}
 		return Utils::fnv1a32(this, sizeof(InetAddress));
@@ -486,15 +487,15 @@ public:
 	{
 		if (as.ss.ss_family == a.as.ss.ss_family) {
 			if (as.ss.ss_family == AF_INET) {
-				const uint16_t p0 = Utils::ntoh((uint16_t) as.sa_in.sin_port);
-				const uint16_t p1 = Utils::ntoh((uint16_t) a.as.sa_in.sin_port);
+				const uint16_t p0 = Utils::ntoh((uint16_t)as.sa_in.sin_port);
+				const uint16_t p1 = Utils::ntoh((uint16_t)a.as.sa_in.sin_port);
 				if (p0 == p1)
-					return Utils::ntoh((uint32_t) as.sa_in.sin_addr.s_addr) < Utils::ntoh((uint32_t) a.as.sa_in.sin_addr.s_addr);
+					return Utils::ntoh((uint32_t)as.sa_in.sin_addr.s_addr) < Utils::ntoh((uint32_t)a.as.sa_in.sin_addr.s_addr);
 				return p0 < p1;
 			}
 			if (as.ss.ss_family == AF_INET6) {
-				const uint16_t p0 = Utils::ntoh((uint16_t) as.sa_in6.sin6_port);
-				const uint16_t p1 = Utils::ntoh((uint16_t) a.as.sa_in6.sin6_port);
+				const uint16_t p0 = Utils::ntoh((uint16_t)as.sa_in6.sin6_port);
+				const uint16_t p1 = Utils::ntoh((uint16_t)a.as.sa_in6.sin6_port);
 				if (p0 == p1)
 					return memcmp(as.sa_in6.sin6_addr.s6_addr, a.as.sa_in6.sin6_addr.s6_addr, 16) < 0;
 				return p0 < p1;
@@ -516,6 +517,34 @@ public:
 	ZT_INLINE bool operator>=(const InetAddress &a) const noexcept
 	{ return !(*this < a); }
 
+	/**
+	 * Generate a local unique key for this address
+	 *
+	 * This key is not comparable across instances or architectures.
+	 *
+	 * @return Local unique key
+	 */
+	ZT_INLINE UniqueID key() const noexcept
+	{
+		if (as.ss.ss_family == AF_INET) {
+			// For IPv4 we can just pack the IP and port into the first element.
+			return UniqueID(((uint64_t)as.sa_in.sin_addr.s_addr << 16U) ^ (uint64_t)as.sa_in.sin_port, 0);
+		} else if (likely(as.ss.ss_family == AF_INET6)) {
+			// The OR with (a2 == 0) is to make sure the second part of the UniqueID
+			// can never be zero, otherwise it could be made to collide with an IPv4
+			// IP address. We also construct this to make it so someone in a /64
+			// can't collide another address in the same /64.
+			const uint64_t a1 = Utils::loadMachineEndian< uint64_t >(as.sa_in6.sin6_addr.s6_addr);
+			const uint64_t a2 = Utils::hash64(Utils::s_mapNonce ^ Utils::loadMachineEndian< uint64_t >(as.sa_in6.sin6_addr.s6_addr + 8)) + (uint64_t)as.sa_in6.sin6_port;
+			return UniqueID(a1, a2 | (uint64_t)(a2 == 0));
+		} else if (likely(as.ss.ss_family == 0)) {
+			return UniqueID(0, 0);
+		} else {
+			// This should never be reached, but handle it somehow.
+			return UniqueID(Utils::fnv1a32(&as, sizeof(as)), 0);
+		}
+	}
+
 	/**
 	 * Compute an IPv6 link-local address
 	 *

+ 1 - 1
core/Locator.cpp

@@ -109,7 +109,7 @@ int Locator::marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX], const bool exclu
 		p += l;
 	}
 
-	Utils::storeAsIsEndian<uint16_t>(data + p, 0); // length of meta-data, currently always 0
+	Utils::storeMachineEndian< uint16_t >(data + p, 0); // length of meta-data, currently always 0
 	p += 2;
 
 	if (!excludeSignature) {

+ 39 - 59
core/Member.cpp

@@ -28,7 +28,7 @@ Member::Member() :
 {
 }
 
-void Member::pushCredentials(const RuntimeEnvironment *RR, void *tPtr, const int64_t now, const SharedPtr<Peer> &to, const NetworkConfig &nconf)
+void Member::pushCredentials(const RuntimeEnvironment *RR, void *tPtr, const int64_t now, const SharedPtr< Peer > &to, const NetworkConfig &nconf)
 {
 	if (!nconf.com) // sanity check
 		return;
@@ -117,36 +117,36 @@ void Member::pushCredentials(const RuntimeEnvironment *RR, void *tPtr, const int
 
 void Member::clean(const int64_t now, const NetworkConfig &nconf)
 {
-	m_cleanCredImpl<TagCredential>(nconf, m_remoteTags);
-	m_cleanCredImpl<CapabilityCredential>(nconf, m_remoteCaps);
-	m_cleanCredImpl<OwnershipCredential>(nconf, m_remoteCoos);
+	m_cleanCredImpl< TagCredential >(nconf, m_remoteTags);
+	m_cleanCredImpl< CapabilityCredential >(nconf, m_remoteCaps);
+	m_cleanCredImpl< OwnershipCredential >(nconf, m_remoteCoos);
 }
 
 Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, void *tPtr, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const MembershipCredential &com)
 {
 	const int64_t newts = com.timestamp();
 	if (newts <= m_comRevocationThreshold) {
-		RR->t->credentialRejected(tPtr,0xd9992121,com.networkId(),sourcePeerIdentity,com.id(),com.timestamp(),ZT_CREDENTIAL_TYPE_COM,ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED);
+		RR->t->credentialRejected(tPtr, 0xd9992121, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED);
 		return ADD_REJECTED;
 	}
 
 	const int64_t oldts = m_com.timestamp();
 	if (newts < oldts) {
-		RR->t->credentialRejected(tPtr,0xd9928192,com.networkId(),sourcePeerIdentity,com.id(),com.timestamp(),ZT_CREDENTIAL_TYPE_COM,ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST);
+		RR->t->credentialRejected(tPtr, 0xd9928192, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST);
 		return ADD_REJECTED;
 	}
-	if ((newts == oldts)&&(m_com == com))
+	if ((newts == oldts) && (m_com == com))
 		return ADD_ACCEPTED_REDUNDANT;
 
-	switch(com.verify(RR,tPtr)) {
+	switch (com.verify(RR, tPtr)) {
 		default:
-			RR->t->credentialRejected(tPtr,0x0f198241,com.networkId(),sourcePeerIdentity,com.id(),com.timestamp(),ZT_CREDENTIAL_TYPE_COM,ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
+			RR->t->credentialRejected(tPtr, 0x0f198241, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
 			return Member::ADD_REJECTED;
 		case Credential::VERIFY_OK:
 			m_com = com;
 			return ADD_ACCEPTED_NEW;
 		case Credential::VERIFY_BAD_SIGNATURE:
-			RR->t->credentialRejected(tPtr,0xbaf0aaaa,com.networkId(),sourcePeerIdentity,com.id(),com.timestamp(),ZT_CREDENTIAL_TYPE_COM,ZT_TRACE_CREDENTIAL_REJECTION_REASON_SIGNATURE_VERIFICATION_FAILED);
+			RR->t->credentialRejected(tPtr, 0xbaf0aaaa, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_SIGNATURE_VERIFICATION_FAILED);
 			return ADD_REJECTED;
 		case Credential::VERIFY_NEED_IDENTITY:
 			return ADD_DEFERRED_FOR_WHOIS;
@@ -154,10 +154,10 @@ Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR,
 }
 
 // 3/5 of the credential types have identical addCredential() code
-template<typename C>
+template< typename C >
 static ZT_INLINE Member::AddCredentialResult _addCredImpl(
-	Map<uint32_t,C> &remoteCreds,
-	const Map<uint64_t,int64_t> &revocations,
+	Map< uint32_t, C > &remoteCreds,
+	const Map< uint64_t, int64_t > &revocations,
 	const RuntimeEnvironment *const RR,
 	void *const tPtr,
 	const Identity &sourcePeerIdentity,
@@ -167,7 +167,7 @@ static ZT_INLINE Member::AddCredentialResult _addCredImpl(
 	C *rc = remoteCreds.get(cred.id());
 	if (rc) {
 		if (rc->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);
+			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)
@@ -175,14 +175,14 @@ static ZT_INLINE Member::AddCredentialResult _addCredImpl(
 	}
 
 	const int64_t *const rt = revocations.get(Member::credentialKey(C::credentialType(), cred.id()));
-	if ((rt)&&(*rt >= cred.timestamp())) {
-		RR->t->credentialRejected(tPtr,0x24248124,nconf.networkId,sourcePeerIdentity,cred.id(),cred.timestamp(),C::credentialType(),ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED);
+	if ((rt) && (*rt >= 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;
 	}
 
-	switch(cred.verify(RR,tPtr)) {
+	switch (cred.verify(RR, tPtr)) {
 		default:
-			RR->t->credentialRejected(tPtr,0x01feba012,nconf.networkId,sourcePeerIdentity,cred.id(),cred.timestamp(),C::credentialType(),ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
+			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)
@@ -193,20 +193,26 @@ static ZT_INLINE Member::AddCredentialResult _addCredImpl(
 			return Member::ADD_DEFERRED_FOR_WHOIS;
 	}
 }
-Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, void *tPtr, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const TagCredential &tag) { return _addCredImpl<TagCredential>(m_remoteTags, m_revocations, RR, tPtr, sourcePeerIdentity, nconf, tag); }
-Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, void *tPtr, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const CapabilityCredential &cap) { return _addCredImpl<CapabilityCredential>(m_remoteCaps, m_revocations, RR, tPtr, sourcePeerIdentity, nconf, cap); }
-Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, void *tPtr, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const OwnershipCredential &coo) { return _addCredImpl<OwnershipCredential>(m_remoteCoos, m_revocations, RR, tPtr, sourcePeerIdentity, nconf, coo); }
+
+Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, void *tPtr, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const TagCredential &tag)
+{ return _addCredImpl< TagCredential >(m_remoteTags, m_revocations, RR, tPtr, sourcePeerIdentity, nconf, tag); }
+
+Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, void *tPtr, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const CapabilityCredential &cap)
+{ return _addCredImpl< CapabilityCredential >(m_remoteCaps, m_revocations, RR, tPtr, sourcePeerIdentity, nconf, cap); }
+
+Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, void *tPtr, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const OwnershipCredential &coo)
+{ return _addCredImpl< OwnershipCredential >(m_remoteCoos, m_revocations, RR, tPtr, sourcePeerIdentity, nconf, coo); }
 
 Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, void *tPtr, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const RevocationCredential &rev)
 {
 	int64_t *rt;
-	switch(rev.verify(RR,tPtr)) {
+	switch (rev.verify(RR, tPtr)) {
 		default:
-			RR->t->credentialRejected(tPtr,0x938fffff,nconf.networkId,sourcePeerIdentity,rev.id(),0,ZT_CREDENTIAL_TYPE_REVOCATION,ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
+			RR->t->credentialRejected(tPtr, 0x938fffff, nconf.networkId, sourcePeerIdentity, rev.id(), 0, ZT_CREDENTIAL_TYPE_REVOCATION, ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
 			return ADD_REJECTED;
 		case 0: {
 			const ZT_CredentialType ct = rev.typeBeingRevoked();
-			switch(ct) {
+			switch (ct) {
 				case ZT_CREDENTIAL_TYPE_COM:
 					if (rev.threshold() > m_comRevocationThreshold) {
 						m_comRevocationThreshold = rev.threshold();
@@ -224,7 +230,7 @@ Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR,
 					}
 					return ADD_ACCEPTED_REDUNDANT;
 				default:
-					RR->t->credentialRejected(tPtr,0x0bbbb1a4,nconf.networkId,sourcePeerIdentity,rev.id(),0,ZT_CREDENTIAL_TYPE_REVOCATION,ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
+					RR->t->credentialRejected(tPtr, 0x0bbbb1a4, nconf.networkId, sourcePeerIdentity, rev.id(), 0, ZT_CREDENTIAL_TYPE_REVOCATION, ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
 					return ADD_REJECTED;
 			}
 		}
@@ -235,40 +241,14 @@ Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR,
 
 bool Member::m_isUnspoofableAddress(const NetworkConfig &nconf, const InetAddress &ip) const noexcept
 {
-	if ((ip.isV6())&&(nconf.ndpEmulation())) {
-		const InetAddress sixpl(InetAddress::makeIpv66plane(nconf.networkId,nconf.issuedTo.toInt()));
-		for(unsigned int i=0;i<nconf.staticIpCount;++i) {
-			if (nconf.staticIps[i].ipsEqual(sixpl)) {
-				bool prefixMatches = true;
-				for(unsigned int j=0;j<5;++j) { // check for match on /40
-					if ((((const struct sockaddr_in6 *)&ip)->sin6_addr.s6_addr)[j] != (((const struct sockaddr_in6 *)&sixpl)->sin6_addr.s6_addr)[j]) {
-						prefixMatches = false;
-						break;
-					}
-				}
-				if (prefixMatches)
-					return true;
-				break;
-			}
-		}
-
-		const InetAddress rfc4193(InetAddress::makeIpv6rfc4193(nconf.networkId,nconf.issuedTo.toInt()));
-		for(unsigned int i=0;i<nconf.staticIpCount;++i) {
-			if (nconf.staticIps[i].ipsEqual(rfc4193)) {
-				bool prefixMatches = true;
-				for(unsigned int j=0;j<11;++j) { // check for match on /88
-					if ((((const struct sockaddr_in6 *)&ip)->sin6_addr.s6_addr)[j] != (((const struct sockaddr_in6 *)&rfc4193)->sin6_addr.s6_addr)[j]) {
-						prefixMatches = false;
-						break;
-					}
-				}
-				if (prefixMatches)
-					return true;
-				break;
-			}
-		}
-	}
-	return false;
+	return (
+		ip.isV6() &&
+		nconf.ndpEmulation() &&
+		(
+			(ip == InetAddress::makeIpv66plane(nconf.networkId, m_com.issuedTo().address)) ||
+			(ip == InetAddress::makeIpv6rfc4193(nconf.networkId, m_com.issuedTo().address))
+		)
+	);
 }
 
 } // namespace ZeroTier

+ 2 - 2
core/Member.hpp

@@ -99,7 +99,7 @@ public:
 	 * @return True if this peer has a certificate of ownership for the given resource
 	 */
 	template<typename T>
-	ZT_INLINE bool peerOwnsAddress(const NetworkConfig &nconf,const T &r) const noexcept
+	ZT_INLINE bool peerOwnsAddress(const NetworkConfig &nconf, const T &r) const noexcept
 	{
 		if (m_isUnspoofableAddress(nconf, r))
 			return true;
@@ -156,7 +156,7 @@ private:
 	// This returns true if a resource is an IPv6 NDP-emulated address. These embed the ZT
 	// address of the peer and therefore cannot be spoofed, causing peerOwnsAddress() to
 	// always return true for them. A certificate is not required for these.
-	constexpr bool m_isUnspoofableAddress(const NetworkConfig &nconf, const MAC &m) const noexcept { return false; }
+	ZT_INLINE bool m_isUnspoofableAddress(const NetworkConfig &nconf, const MAC &m) const noexcept { return false; }
 	bool m_isUnspoofableAddress(const NetworkConfig &nconf, const InetAddress &ip) const noexcept;
 
 	// This compares the remote credential's timestamp to the timestamp in our network config

+ 9 - 9
core/MembershipCredential.cpp

@@ -117,7 +117,7 @@ int MembershipCredential::marshal(uint8_t data[ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_
 	p += 8;
 	Utils::storeBigEndian<uint64_t>(data + p, m_issuedTo.address);
 	p += 8;
-	Utils::storeAsIsEndian<uint64_t>(data + p, 0xffffffffffffffffULL);
+	Utils::storeMachineEndian< uint64_t >(data + p, 0xffffffffffffffffULL);
 	p += 8;
 
 	if (v2) {
@@ -131,9 +131,9 @@ int MembershipCredential::marshal(uint8_t data[ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_
 		for (int k = 0;k < 6;++k) {
 			Utils::storeBigEndian<uint64_t>(data + p, (uint64_t) k + 3);
 			p += 8;
-			Utils::storeAsIsEndian<uint64_t>(data + p, Utils::loadAsIsEndian<uint64_t>(m_issuedTo.hash + (k * 8)));
+			Utils::storeMachineEndian< uint64_t >(data + p, Utils::loadMachineEndian< uint64_t >(m_issuedTo.hash + (k * 8)));
 			p += 8;
-			Utils::storeAsIsEndian<uint64_t>(data + p, 0xffffffffffffffffULL);
+			Utils::storeMachineEndian< uint64_t >(data + p, 0xffffffffffffffffULL);
 			p += 8;
 		}
 	}
@@ -268,22 +268,22 @@ unsigned int MembershipCredential::m_fillSigningBuf(uint64_t *buf) const noexcep
 	// embeded as a series of informational tuples.
 	if (m_issuedTo.haveHash()) {
 		buf[p++] = ZT_CONST_TO_BE_UINT64(3);
-		buf[p++] = Utils::loadAsIsEndian<uint64_t>(m_issuedTo.hash);
+		buf[p++] = Utils::loadMachineEndian< uint64_t >(m_issuedTo.hash);
 		buf[p++] = informational;
 		buf[p++] = ZT_CONST_TO_BE_UINT64(4);
-		buf[p++] = Utils::loadAsIsEndian<uint64_t>(m_issuedTo.hash + 8);
+		buf[p++] = Utils::loadMachineEndian< uint64_t >(m_issuedTo.hash + 8);
 		buf[p++] = informational;
 		buf[p++] = ZT_CONST_TO_BE_UINT64(5);
-		buf[p++] = Utils::loadAsIsEndian<uint64_t>(m_issuedTo.hash + 16);
+		buf[p++] = Utils::loadMachineEndian< uint64_t >(m_issuedTo.hash + 16);
 		buf[p++] = informational;
 		buf[p++] = ZT_CONST_TO_BE_UINT64(6);
-		buf[p++] = Utils::loadAsIsEndian<uint64_t>(m_issuedTo.hash + 24);
+		buf[p++] = Utils::loadMachineEndian< uint64_t >(m_issuedTo.hash + 24);
 		buf[p++] = informational;
 		buf[p++] = ZT_CONST_TO_BE_UINT64(7);
-		buf[p++] = Utils::loadAsIsEndian<uint64_t>(m_issuedTo.hash + 32);
+		buf[p++] = Utils::loadMachineEndian< uint64_t >(m_issuedTo.hash + 32);
 		buf[p++] = informational;
 		buf[p++] = ZT_CONST_TO_BE_UINT64(8);
-		buf[p++] = Utils::loadAsIsEndian<uint64_t>(m_issuedTo.hash + 40);
+		buf[p++] = Utils::loadMachineEndian< uint64_t >(m_issuedTo.hash + 40);
 		buf[p++] = informational;
 	}
 

+ 2 - 2
core/Peer.cpp

@@ -227,7 +227,7 @@ unsigned int Peer::hello(void *tPtr, int64_t localSocket, const InetAddress &atA
 	p1305.update(outp.unsafeData + ZT_PROTO_PACKET_ENCRYPTED_SECTION_START, ii - ZT_PROTO_PACKET_ENCRYPTED_SECTION_START);
 	uint64_t polyMac[2];
 	p1305.finish(polyMac);
-	Utils::storeAsIsEndian< uint64_t >(outp.unsafeData + ZT_PROTO_PACKET_MAC_INDEX, polyMac[0]);
+	Utils::storeMachineEndian< uint64_t >(outp.unsafeData + ZT_PROTO_PACKET_MAC_INDEX, polyMac[0]);
 
 	return (likely(RR->node->putPacket(tPtr, localSocket, atAddress, outp.unsafeData, ii))) ? ii : 0;
 }
@@ -704,7 +704,7 @@ unsigned int Peer::m_sendProbe(void *tPtr, int64_t localSocket, const InetAddres
 	const uint64_t packetId = k->nextMessage(RR->identity.address(), m_id.address());
 
 	uint8_t p[ZT_PROTO_MIN_PACKET_LENGTH];
-	Utils::storeAsIsEndian< uint64_t >(p + ZT_PROTO_PACKET_ID_INDEX, packetId);
+	Utils::storeMachineEndian< uint64_t >(p + ZT_PROTO_PACKET_ID_INDEX, packetId);
 	m_id.address().copyTo(p + ZT_PROTO_PACKET_DESTINATION_INDEX);
 	RR->identity.address().copyTo(p + ZT_PROTO_PACKET_SOURCE_INDEX);
 	p[ZT_PROTO_PACKET_FLAGS_INDEX] = 0;

+ 2 - 2
core/Protocol.hpp

@@ -834,11 +834,11 @@ static ZT_INLINE void salsa2012DeriveKey(const uint8_t *const in,uint8_t *const
  */
 static ZT_INLINE int newPacket(uint8_t pkt[28],const uint64_t packetId,const Address destination,const Address source,const Verb verb) noexcept
 {
-	Utils::storeAsIsEndian<uint64_t>(pkt + ZT_PROTO_PACKET_ID_INDEX,packetId);
+	Utils::storeMachineEndian< uint64_t >(pkt + ZT_PROTO_PACKET_ID_INDEX, packetId);
 	destination.copyTo(pkt + ZT_PROTO_PACKET_DESTINATION_INDEX);
 	source.copyTo(pkt + ZT_PROTO_PACKET_SOURCE_INDEX);
 	pkt[ZT_PROTO_PACKET_FLAGS_INDEX] = 0;
-	Utils::storeAsIsEndian<uint64_t>(pkt + ZT_PROTO_PACKET_MAC_INDEX,0);
+	Utils::storeMachineEndian< uint64_t >(pkt + ZT_PROTO_PACKET_MAC_INDEX, 0);
 	pkt[ZT_PROTO_PACKET_VERB_INDEX] = (uint8_t)verb;
 	return ZT_PROTO_PACKET_VERB_INDEX + 1;
 }

+ 6 - 6
core/SHA512.cpp

@@ -200,12 +200,12 @@ void HMACSHA384(const uint8_t key[ZT_SYMMETRIC_KEY_SIZE],const void *msg,const u
 	uint64_t kInPadded[16]; // input padded key
 	uint64_t outer[22]; // output padded key | H(input padded key | msg)
 
-	const uint64_t k0 = Utils::loadAsIsEndian<uint64_t>(key);
-	const uint64_t k1 = Utils::loadAsIsEndian<uint64_t>(key + 8);
-	const uint64_t k2 = Utils::loadAsIsEndian<uint64_t>(key + 16);
-	const uint64_t k3 = Utils::loadAsIsEndian<uint64_t>(key + 24);
-	const uint64_t k4 = Utils::loadAsIsEndian<uint64_t>(key + 32);
-	const uint64_t k5 = Utils::loadAsIsEndian<uint64_t>(key + 40);
+	const uint64_t k0 = Utils::loadMachineEndian< uint64_t >(key);
+	const uint64_t k1 = Utils::loadMachineEndian< uint64_t >(key + 8);
+	const uint64_t k2 = Utils::loadMachineEndian< uint64_t >(key + 16);
+	const uint64_t k3 = Utils::loadMachineEndian< uint64_t >(key + 24);
+	const uint64_t k4 = Utils::loadMachineEndian< uint64_t >(key + 32);
+	const uint64_t k5 = Utils::loadMachineEndian< uint64_t >(key + 40);
 
 	const uint64_t ipad = 0x3636363636363636ULL;
 	kInPadded[0] = k0 ^ ipad;

+ 18 - 18
core/Tests.cpp

@@ -427,35 +427,35 @@ extern "C" const char *ZTT_general()
 				return "ZT_CONST_TO_BE_UINT16 macro is not working";
 			}
 #if __BYTE_ORDER == __LITTLE_ENDIAN
-			if (Utils::loadAsIsEndian< uint64_t >(&a) != 0x0102030405060708ULL) {
-				ZT_T_PRINTF("FAILED (loadAsIsEndian)" ZT_EOL_S);
-				return "Utils::loadAsIsEndian() broken";
+			if (Utils::loadMachineEndian< uint64_t >(&a) != 0x0102030405060708ULL) {
+				ZT_T_PRINTF("FAILED (loadMachineEndian)" ZT_EOL_S);
+				return "Utils::loadMachineEndian() broken";
 			}
-			if (Utils::loadAsIsEndian< uint32_t >(&b) != 0x01020304) {
-				ZT_T_PRINTF("FAILED (loadAsIsEndian)" ZT_EOL_S);
-				return "Utils::loadAsIsEndian() broken";
+			if (Utils::loadMachineEndian< uint32_t >(&b) != 0x01020304) {
+				ZT_T_PRINTF("FAILED (loadMachineEndian)" ZT_EOL_S);
+				return "Utils::loadMachineEndian() broken";
 			}
-			if (Utils::loadAsIsEndian< uint16_t >(&c) != 0x0102) {
-				ZT_T_PRINTF("FAILED (loadAsIsEndian)" ZT_EOL_S);
-				return "Utils::loadAsIsEndian() broken";
+			if (Utils::loadMachineEndian< uint16_t >(&c) != 0x0102) {
+				ZT_T_PRINTF("FAILED (loadMachineEndian)" ZT_EOL_S);
+				return "Utils::loadMachineEndian() broken";
 			}
 			Utils::zero< sizeof(t) >(t);
-			Utils::storeAsIsEndian< uint64_t >(t, 0x0807060504030201ULL);
+			Utils::storeMachineEndian< uint64_t >(t, 0x0807060504030201ULL);
 			if (t[0] != 1) {
-				ZT_T_PRINTF("FAILED (storeAsIsEndian)" ZT_EOL_S);
-				return "Utils::storeAsIsEndian() broken";
+				ZT_T_PRINTF("FAILED (storeMachineEndian)" ZT_EOL_S);
+				return "Utils::storeMachineEndian() broken";
 			}
 			Utils::zero< sizeof(t) >(t);
-			Utils::storeAsIsEndian< uint32_t >(t, 0x04030201);
+			Utils::storeMachineEndian< uint32_t >(t, 0x04030201);
 			if (t[0] != 1) {
-				ZT_T_PRINTF("FAILED (storeAsIsEndian)" ZT_EOL_S);
-				return "Utils::storeAsIsEndian() broken";
+				ZT_T_PRINTF("FAILED (storeMachineEndian)" ZT_EOL_S);
+				return "Utils::storeMachineEndian() broken";
 			}
 			Utils::zero< sizeof(t) >(t);
-			Utils::storeAsIsEndian< uint16_t >(t, 0x0201);
+			Utils::storeMachineEndian< uint16_t >(t, 0x0201);
 			if (t[0] != 1) {
-				ZT_T_PRINTF("FAILED (storeAsIsEndian)" ZT_EOL_S);
-				return "Utils::storeAsIsEndian() broken";
+				ZT_T_PRINTF("FAILED (storeMachineEndian)" ZT_EOL_S);
+				return "Utils::storeMachineEndian() broken";
 			}
 #else
 			if (Utils::loadAsIsEndian<uint64_t>(&a) != 0x0807060504030201ULL) {

+ 4 - 4
core/Topology.cpp

@@ -182,18 +182,18 @@ void Topology::doPeriodicTasks(void *tPtr, const int64_t now)
 
 	// Delete paths that are no longer held by anyone else ("weak reference" type behavior).
 	{
-		Vector< uint64_t > toDelete;
+		Vector< UniqueID > toDelete;
 		{
 			RWMutex::RLock l1(m_paths_l);
-			for (Map< uint64_t, SharedPtr< Path > >::iterator i(m_paths.begin()); i != m_paths.end();
+			for (Map< UniqueID, SharedPtr< Path > >::iterator i(m_paths.begin()); i != m_paths.end();
 			     ++i) {
 				if (i->second.weakGC())
 					toDelete.push_back(i->first);
 			}
 		}
-		for (Vector< uint64_t >::iterator i(toDelete.begin()); i != toDelete.end(); ++i) {
+		for (Vector< UniqueID >::iterator i(toDelete.begin()); i != toDelete.end(); ++i) {
 			RWMutex::Lock l1(m_paths_l);
-			const Map< uint64_t, SharedPtr< Path > >::iterator p(m_paths.find(*i));
+			const Map< UniqueID, SharedPtr< Path > >::iterator p(m_paths.find(*i));
 			if (likely(p != m_paths.end()))
 				m_paths.erase(p);
 		}

+ 2 - 21
core/Topology.hpp

@@ -94,7 +94,7 @@ public:
 	 */
 	ZT_INLINE SharedPtr< Path > path(const int64_t l, const InetAddress &r)
 	{
-		const uint64_t k = s_getPathKey(l, r);
+		const UniqueID k(r.key());
 		{
 			RWMutex::RLock lck(m_paths_l);
 			SharedPtr< Path > *const p = m_paths.get(k);
@@ -238,25 +238,6 @@ private:
 	void m_updateRootPeers_l_roots_certs(void *tPtr);
 	void m_writeTrustStore_l_roots_certs(void *tPtr) const;
 
-	// This gets an integer key from an InetAddress for looking up paths.
-	static ZT_INLINE uint64_t s_getPathKey(const int64_t l, const InetAddress &r) noexcept
-	{
-		// SECURITY: these will be used as keys in a Map<> which uses its own hasher that
-		// mixes in a per-invocation secret to work against hash collision attacks. See the
-		// map hasher in Containers.hpp. Otherwise the point here is really really fast
-		// path lookup by address. The number of paths is never likely to be high enough
-		// for a collision to be something we worry about. That would require a minimum of
-		// millions and millions of paths on a single node.
-		if (r.family() == AF_INET) {
-			return ((uint64_t)(r.as.sa_in.sin_addr.s_addr) << 32U) ^ ((uint64_t)r.as.sa_in.sin_port << 16U) ^ (uint64_t)l;
-		} else if (r.family() == AF_INET6) {
-			return Utils::loadAsIsEndian< uint64_t >(r.as.sa_in6.sin6_addr.s6_addr) + Utils::loadAsIsEndian< uint64_t >(r.as.sa_in6.sin6_addr.s6_addr + 8) + (uint64_t)r.as.sa_in6.sin6_port + (uint64_t)l;
-		} else {
-			// This should never really be used but it's here just in case.
-			return (uint64_t)Utils::fnv1a32(reinterpret_cast<const void *>(&r), sizeof(InetAddress)) + (uint64_t)l;
-		}
-	}
-
 	const RuntimeEnvironment *const RR;
 
 	RWMutex m_paths_l; // m_paths
@@ -264,7 +245,7 @@ private:
 	RWMutex m_roots_l; // m_roots, m_rootPeers
 	Mutex m_certs_l;   // m_certs, m_certsBySubjectIdentity
 
-	Map< uint64_t, SharedPtr< Path > > m_paths;
+	Map< UniqueID, SharedPtr< Path > > m_paths;
 
 	Map< Address, SharedPtr< Peer > > m_peers;
 

+ 2 - 2
core/Utils.hpp

@@ -593,7 +593,7 @@ static ZT_INLINE I ntoh(const I n) noexcept
  * @return Loaded raw integer
  */
 template< typename I >
-static ZT_INLINE I loadAsIsEndian(const void *const p) noexcept
+static ZT_INLINE I loadMachineEndian(const void *const p) noexcept
 {
 #ifdef ZT_NO_UNALIGNED_ACCESS
 	I tmp;
@@ -613,7 +613,7 @@ static ZT_INLINE I loadAsIsEndian(const void *const p) noexcept
  * @param i Integer to store
  */
 template< typename I >
-static ZT_INLINE void storeAsIsEndian(void *const p, const I i) noexcept
+static ZT_INLINE void storeMachineEndian(void *const p, const I i) noexcept
 {
 #ifdef ZT_NO_UNALIGNED_ACCESS
 	for(unsigned int k=0;k<sizeof(I);++k)

+ 6 - 6
core/VL1.cpp

@@ -117,7 +117,7 @@ void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const Inet
 			return;
 
 		static_assert((ZT_PROTO_PACKET_ID_INDEX + sizeof(uint64_t)) < ZT_PROTO_MIN_FRAGMENT_LENGTH, "overflow");
-		const uint64_t packetId = Utils::loadAsIsEndian< uint64_t >(data->unsafeData + ZT_PROTO_PACKET_ID_INDEX);
+		const uint64_t packetId = Utils::loadMachineEndian< uint64_t >(data->unsafeData + ZT_PROTO_PACKET_ID_INDEX);
 
 		static_assert((ZT_PROTO_PACKET_DESTINATION_INDEX + ZT_ADDRESS_LENGTH) < ZT_PROTO_MIN_FRAGMENT_LENGTH, "overflow");
 		const Address destination(data->unsafeData + ZT_PROTO_PACKET_DESTINATION_INDEX);
@@ -244,7 +244,7 @@ void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const Inet
 					uint64_t mac[2];
 					s20cf.poly1305.finish(mac);
 					static_assert((ZT_PROTO_PACKET_MAC_INDEX + 8) < ZT_PROTO_MIN_PACKET_LENGTH, "overflow");
-					if (unlikely(Utils::loadAsIsEndian< uint64_t >(hdr + ZT_PROTO_PACKET_MAC_INDEX) != mac[0])) {
+					if (unlikely(Utils::loadMachineEndian< uint64_t >(hdr + ZT_PROTO_PACKET_MAC_INDEX) != mac[0])) {
 						ZT_SPEW("discarding packet %.16llx from %s(%s): packet MAC failed (none/poly1305)", packetId, source.toString().c_str(), fromAddr.toString().c_str());
 						RR->t->incomingPacketDropped(tPtr, 0xcc89c812, packetId, 0, peer->identity(), path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
 						return;
@@ -268,7 +268,7 @@ void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const Inet
 					uint64_t mac[2];
 					s20cf.poly1305.finish(mac);
 					static_assert((ZT_PROTO_PACKET_MAC_INDEX + 8) < ZT_PROTO_MIN_PACKET_LENGTH, "overflow");
-					if (unlikely(Utils::loadAsIsEndian< uint64_t >(hdr + ZT_PROTO_PACKET_MAC_INDEX) != mac[0])) {
+					if (unlikely(Utils::loadMachineEndian< uint64_t >(hdr + ZT_PROTO_PACKET_MAC_INDEX) != mac[0])) {
 						ZT_SPEW("discarding packet %.16llx from %s(%s): packet MAC failed (salsa/poly1305)", packetId, source.toString().c_str(), fromAddr.toString().c_str());
 						RR->t->incomingPacketDropped(tPtr, 0xcc89c812, packetId, 0, peer->identity(), path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
 						return;
@@ -477,8 +477,8 @@ void VL1::m_sendPendingWhois(void *tPtr, int64_t now)
 
 SharedPtr< Peer > VL1::m_HELLO(void *tPtr, const SharedPtr< Path > &path, Buf &pkt, int packetSize)
 {
-	const uint64_t packetId = Utils::loadAsIsEndian< uint64_t >(pkt.unsafeData + ZT_PROTO_PACKET_ID_INDEX);
-	const uint64_t mac = Utils::loadAsIsEndian< uint64_t >(pkt.unsafeData + ZT_PROTO_PACKET_MAC_INDEX);
+	const uint64_t packetId = Utils::loadMachineEndian< uint64_t >(pkt.unsafeData + ZT_PROTO_PACKET_ID_INDEX);
+	const uint64_t mac = Utils::loadMachineEndian< uint64_t >(pkt.unsafeData + ZT_PROTO_PACKET_MAC_INDEX);
 	const uint8_t hops = pkt.unsafeData[ZT_PROTO_PACKET_FLAGS_INDEX] & ZT_PROTO_FLAG_FIELD_HOPS_MASK;
 
 	const uint8_t protoVersion = pkt.lI8< ZT_PROTO_PACKET_PAYLOAD_START >();
@@ -543,7 +543,7 @@ SharedPtr< Peer > VL1::m_HELLO(void *tPtr, const SharedPtr< Path > &path, Buf &p
 		}
 		packetSize -= ZT_HMACSHA384_LEN;
 		pkt.unsafeData[ZT_PROTO_PACKET_FLAGS_INDEX] &= ~ZT_PROTO_FLAG_FIELD_HOPS_MASK; // mask hops to 0
-		Utils::storeAsIsEndian< uint64_t >(pkt.unsafeData + ZT_PROTO_PACKET_MAC_INDEX, 0); // set MAC field to 0
+		Utils::storeMachineEndian< uint64_t >(pkt.unsafeData + ZT_PROTO_PACKET_MAC_INDEX, 0); // set MAC field to 0
 		HMACSHA384(peer->identityHelloHmacKey(), pkt.unsafeData, packetSize, hmac);
 		if (unlikely(!Utils::secureEq(hmac, pkt.unsafeData + packetSize, ZT_HMACSHA384_LEN))) {
 			RR->t->incomingPacketDropped(tPtr, 0x707a9891, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);