Browse Source

clang-format this branch to match dev

Adam Ierymenko 1 month ago
parent
commit
5eb3cd2699
100 changed files with 11248 additions and 9965 deletions
  1. 132 132
      controller/ConnectionPool.hpp
  2. 165 116
      controller/DB.cpp
  3. 78 79
      controller/DB.hpp
  4. 66 67
      controller/DBMirrorSet.cpp
  5. 22 23
      controller/DBMirrorSet.hpp
  6. 328 252
      controller/EmbeddedNetworkController.cpp
  7. 77 80
      controller/EmbeddedNetworkController.hpp
  8. 71 66
      controller/FileDB.cpp
  9. 10 12
      controller/FileDB.hpp
  10. 192 160
      controller/LFDB.cpp
  11. 20 25
      controller/LFDB.hpp
  12. 335 258
      controller/PostgreSQL.cpp
  13. 58 55
      controller/PostgreSQL.hpp
  14. 5 5
      controller/Redis.hpp
  15. 164 134
      node/AES.cpp
  16. 113 109
      node/AES.hpp
  17. 67 69
      node/AES_aesni.cpp
  18. 55 49
      node/AES_armcrypto.cpp
  19. 114 43
      node/Address.hpp
  20. 18 11
      node/AtomicCounter.hpp
  21. 2 2
      node/Bond.cpp
  22. 2 2
      node/Bond.hpp
  23. 137 104
      node/Buffer.hpp
  24. 620 691
      node/C25519.cpp
  25. 47 34
      node/C25519.hpp
  26. 26 20
      node/Capability.cpp
  27. 114 92
      node/Capability.hpp
  28. 29 27
      node/CertificateOfMembership.cpp
  29. 75 56
      node/CertificateOfMembership.hpp
  30. 17 15
      node/CertificateOfOwnership.cpp
  31. 94 68
      node/CertificateOfOwnership.hpp
  32. 49 49
      node/Constants.hpp
  33. 10 13
      node/Credential.hpp
  34. 26 28
      node/DNS.hpp
  35. 113 86
      node/Dictionary.hpp
  36. 101 96
      node/Hashtable.hpp
  37. 68 70
      node/Identity.cpp
  38. 92 69
      node/Identity.hpp
  39. 275 258
      node/IncomingPacket.cpp
  40. 39 45
      node/IncomingPacket.hpp
  41. 154 145
      node/InetAddress.cpp
  42. 239 166
      node/InetAddress.hpp
  43. 108 56
      node/MAC.hpp
  44. 64 61
      node/Membership.cpp
  45. 89 90
      node/Membership.hpp
  46. 137 245
      node/Metrics.cpp
  47. 135 138
      node/Metrics.hpp
  48. 50 29
      node/MulticastGroup.hpp
  49. 116 127
      node/Multicaster.cpp
  50. 82 59
      node/Multicaster.hpp
  51. 41 39
      node/Mutex.hpp
  52. 323 256
      node/Network.cpp
  53. 134 107
      node/Network.hpp
  54. 161 145
      node/NetworkConfig.cpp
  55. 112 92
      node/NetworkConfig.hpp
  56. 21 31
      node/NetworkController.hpp
  57. 372 335
      node/Node.cpp
  58. 138 114
      node/Node.hpp
  59. 20 18
      node/OutboundMulticast.cpp
  60. 38 28
      node/OutboundMulticast.hpp
  61. 349 276
      node/Packet.cpp
  62. 216 163
      node/Packet.hpp
  63. 4 4
      node/PacketMultiplexer.cpp
  64. 5 4
      node/Path.cpp
  65. 200 114
      node/Path.hpp
  66. 157 141
      node/Peer.cpp
  67. 164 114
      node/Peer.hpp
  68. 504 428
      node/Poly1305.cpp
  69. 4 5
      node/Poly1305.hpp
  70. 14 12
      node/Revocation.cpp
  71. 82 64
      node/Revocation.hpp
  72. 40 31
      node/RingBuffer.hpp
  73. 18 26
      node/RuntimeEnvironment.hpp
  74. 95 104
      node/SHA512.cpp
  75. 18 18
      node/SHA512.hpp
  76. 671 659
      node/Salsa20.cpp
  77. 59 55
      node/Salsa20.hpp
  78. 44 45
      node/SelfAwareness.cpp
  79. 33 22
      node/SelfAwareness.hpp
  80. 63 28
      node/SharedPtr.hpp
  81. 263 260
      node/Switch.cpp
  82. 90 89
      node/Switch.hpp
  83. 14 12
      node/Tag.cpp
  84. 109 65
      node/Tag.hpp
  85. 5 4
      node/Topology.cpp
  86. 98 95
      node/Topology.hpp
  87. 323 283
      node/Trace.cpp
  88. 88 74
      node/Trace.hpp
  89. 69 72
      node/Utils.cpp
  90. 291 286
      node/Utils.hpp
  91. 92 60
      node/World.hpp
  92. 51 46
      osdep/Arp.cpp
  93. 21 22
      osdep/Arp.hpp
  94. 175 167
      osdep/BSDEthernetTap.cpp
  95. 28 29
      osdep/BSDEthernetTap.hpp
  96. 32 31
      osdep/Binder.hpp
  97. 27 31
      osdep/BlockingQueue.hpp
  98. 50 54
      osdep/EthernetTap.cpp
  99. 18 19
      osdep/EthernetTap.hpp
  100. 104 102
      osdep/Http.cpp

+ 132 - 132
controller/ConnectionPool.hpp

@@ -14,162 +14,162 @@
 #ifndef ZT_CONNECTION_POOL_H_
 #define ZT_CONNECTION_POOL_H_
 
-
 #ifndef _DEBUG
-	#define _DEBUG(x)
+#define _DEBUG(x)
 #endif
 
 #include "../node/Metrics.hpp"
 
 #include <deque>
-#include <set>
+#include <exception>
 #include <memory>
 #include <mutex>
-#include <exception>
+#include <set>
 #include <string>
 
 namespace ZeroTier {
 
-struct ConnectionUnavailable : std::exception { 
-    char const* what() const throw() {
-        return "Unable to allocate connection";
-    }; 
+struct ConnectionUnavailable : std::exception {
+	char const* what() const throw()
+	{
+		return "Unable to allocate connection";
+	};
 };
 
-
 class Connection {
-public:
-    virtual ~Connection() {};
+  public:
+	virtual ~Connection() {};
 };
 
 class ConnectionFactory {
-public:
-    virtual ~ConnectionFactory() {};
-    virtual std::shared_ptr<Connection> create()=0;
+  public:
+	virtual ~ConnectionFactory() {};
+	virtual std::shared_ptr<Connection> create() = 0;
 };
 
 struct ConnectionPoolStats {
-    size_t pool_size;
-    size_t borrowed_size;
+	size_t pool_size;
+	size_t borrowed_size;
 };
 
-template<class T>
-class ConnectionPool {
-public:
-    ConnectionPool(size_t max_pool_size, size_t min_pool_size, std::shared_ptr<ConnectionFactory> factory)
-        : m_maxPoolSize(max_pool_size)
-        , m_minPoolSize(min_pool_size)
-        , m_factory(factory)
-    {
-        Metrics::max_pool_size += max_pool_size;
-        Metrics::min_pool_size += min_pool_size;
-        while(m_pool.size() < m_minPoolSize){
-            m_pool.push_back(m_factory->create());
-            Metrics::pool_avail++;
-        }
-    };
-
-    ConnectionPoolStats get_stats() {
-        std::unique_lock<std::mutex> lock(m_poolMutex);
-
-        ConnectionPoolStats stats;
-        stats.pool_size = m_pool.size();
-        stats.borrowed_size = m_borrowed.size();			
-
-        return stats;
-    };
-
-    ~ConnectionPool() {
-    };
-
-    /**
-     * Borrow
-     *
-     * Borrow a connection for temporary use
-     *
-     * When done, either (a) call unborrow() to return it, or (b) (if it's bad) just let it go out of scope.  This will cause it to automatically be replaced.
-     * @retval a shared_ptr to the connection object
-     */
-    std::shared_ptr<T> borrow() {
-        std::unique_lock<std::mutex> l(m_poolMutex);
-        
-        while((m_pool.size() + m_borrowed.size()) < m_minPoolSize) {
-            std::shared_ptr<Connection> conn = m_factory->create();
-            m_pool.push_back(conn);
-            Metrics::pool_avail++;
-        }
-
-        if(m_pool.size()==0){
-            
-            if ((m_pool.size() + m_borrowed.size()) < m_maxPoolSize) {
-                try {
-                    std::shared_ptr<Connection> conn = m_factory->create();
-                    m_borrowed.insert(conn);
-                    Metrics::pool_in_use++;
-                    return std::static_pointer_cast<T>(conn);
-                } catch (std::exception &e) {
-                    Metrics::pool_errors++;
-                    throw ConnectionUnavailable();
-                }
-            } else {
-                for(auto it = m_borrowed.begin(); it != m_borrowed.end(); ++it){
-                    if((*it).unique()) {
-                        // This connection has been abandoned! Destroy it and create a new connection
-                        try {
-                            // If we are able to create a new connection, return it
-                            _DEBUG("Creating new connection to replace discarded connection");
-                            std::shared_ptr<Connection> conn = m_factory->create();
-                            m_borrowed.erase(it);
-                            m_borrowed.insert(conn);
-                            return std::static_pointer_cast<T>(conn);
-                        } catch(std::exception& e) {
-                            // Error creating a replacement connection
-                            Metrics::pool_errors++;
-                            throw ConnectionUnavailable();
-                        }
-                    }
-                }
-                // Nothing available
-                Metrics::pool_errors++;
-                throw ConnectionUnavailable();
-            }
-        }
-
-        // Take one off the front
-        std::shared_ptr<Connection> conn = m_pool.front();
-        m_pool.pop_front();
-        Metrics::pool_avail--;
-        // Add it to the borrowed list
-        m_borrowed.insert(conn);
-        Metrics::pool_in_use++;
-        return std::static_pointer_cast<T>(conn);
-    };
-
-    /**
-     * Unborrow a connection
-     *
-     * Only call this if you are returning a working connection.  If the connection was bad, just let it go out of scope (so the connection manager can replace it).
-     * @param the connection
-     */
-    void unborrow(std::shared_ptr<T> conn) {
-        // Lock
-        std::unique_lock<std::mutex> lock(m_poolMutex);
-        m_borrowed.erase(conn);
-        Metrics::pool_in_use--;
-        if ((m_pool.size() + m_borrowed.size()) < m_maxPoolSize) {
-            Metrics::pool_avail++;
-            m_pool.push_back(conn);
-        }
-    };
-protected:
-    size_t m_maxPoolSize;
-    size_t m_minPoolSize;
-    std::shared_ptr<ConnectionFactory> m_factory;
-    std::deque<std::shared_ptr<Connection> > m_pool;
-    std::set<std::shared_ptr<Connection> > m_borrowed;
-    std::mutex m_poolMutex;
+template <class T> class ConnectionPool {
+  public:
+	ConnectionPool(size_t max_pool_size, size_t min_pool_size, std::shared_ptr<ConnectionFactory> factory) : m_maxPoolSize(max_pool_size), m_minPoolSize(min_pool_size), m_factory(factory)
+	{
+		Metrics::max_pool_size += max_pool_size;
+		Metrics::min_pool_size += min_pool_size;
+		while (m_pool.size() < m_minPoolSize) {
+			m_pool.push_back(m_factory->create());
+			Metrics::pool_avail++;
+		}
+	};
+
+	ConnectionPoolStats get_stats()
+	{
+		std::unique_lock<std::mutex> lock(m_poolMutex);
+
+		ConnectionPoolStats stats;
+		stats.pool_size = m_pool.size();
+		stats.borrowed_size = m_borrowed.size();
+
+		return stats;
+	};
+
+	~ConnectionPool() {};
+
+	/**
+	 * Borrow
+	 *
+	 * Borrow a connection for temporary use
+	 *
+	 * When done, either (a) call unborrow() to return it, or (b) (if it's bad) just let it go out of scope.  This will cause it to automatically be replaced.
+	 * @retval a shared_ptr to the connection object
+	 */
+	std::shared_ptr<T> borrow()
+	{
+		std::unique_lock<std::mutex> l(m_poolMutex);
+
+		while ((m_pool.size() + m_borrowed.size()) < m_minPoolSize) {
+			std::shared_ptr<Connection> conn = m_factory->create();
+			m_pool.push_back(conn);
+			Metrics::pool_avail++;
+		}
+
+		if (m_pool.size() == 0) {
+			if ((m_pool.size() + m_borrowed.size()) < m_maxPoolSize) {
+				try {
+					std::shared_ptr<Connection> conn = m_factory->create();
+					m_borrowed.insert(conn);
+					Metrics::pool_in_use++;
+					return std::static_pointer_cast<T>(conn);
+				}
+				catch (std::exception& e) {
+					Metrics::pool_errors++;
+					throw ConnectionUnavailable();
+				}
+			}
+			else {
+				for (auto it = m_borrowed.begin(); it != m_borrowed.end(); ++it) {
+					if ((*it).unique()) {
+						// This connection has been abandoned! Destroy it and create a new connection
+						try {
+							// If we are able to create a new connection, return it
+							_DEBUG("Creating new connection to replace discarded connection");
+							std::shared_ptr<Connection> conn = m_factory->create();
+							m_borrowed.erase(it);
+							m_borrowed.insert(conn);
+							return std::static_pointer_cast<T>(conn);
+						}
+						catch (std::exception& e) {
+							// Error creating a replacement connection
+							Metrics::pool_errors++;
+							throw ConnectionUnavailable();
+						}
+					}
+				}
+				// Nothing available
+				Metrics::pool_errors++;
+				throw ConnectionUnavailable();
+			}
+		}
+
+		// Take one off the front
+		std::shared_ptr<Connection> conn = m_pool.front();
+		m_pool.pop_front();
+		Metrics::pool_avail--;
+		// Add it to the borrowed list
+		m_borrowed.insert(conn);
+		Metrics::pool_in_use++;
+		return std::static_pointer_cast<T>(conn);
+	};
+
+	/**
+	 * Unborrow a connection
+	 *
+	 * Only call this if you are returning a working connection.  If the connection was bad, just let it go out of scope (so the connection manager can replace it).
+	 * @param the connection
+	 */
+	void unborrow(std::shared_ptr<T> conn)
+	{
+		// Lock
+		std::unique_lock<std::mutex> lock(m_poolMutex);
+		m_borrowed.erase(conn);
+		Metrics::pool_in_use--;
+		if ((m_pool.size() + m_borrowed.size()) < m_maxPoolSize) {
+			Metrics::pool_avail++;
+			m_pool.push_back(conn);
+		}
+	};
+
+  protected:
+	size_t m_maxPoolSize;
+	size_t m_minPoolSize;
+	std::shared_ptr<ConnectionFactory> m_factory;
+	std::deque<std::shared_ptr<Connection> > m_pool;
+	std::set<std::shared_ptr<Connection> > m_borrowed;
+	std::mutex m_poolMutex;
 };
 
-}
+}	// namespace ZeroTier
 
 #endif

+ 165 - 116
controller/DB.cpp

@@ -12,77 +12,114 @@
 /****/
 
 #include "DB.hpp"
-#include "EmbeddedNetworkController.hpp"
+
 #include "../node/Metrics.hpp"
+#include "EmbeddedNetworkController.hpp"
 
-#include <chrono>
 #include <algorithm>
+#include <chrono>
 #include <stdexcept>
 
 using json = nlohmann::json;
 
 namespace ZeroTier {
 
-void DB::initNetwork(nlohmann::json &network)
+void DB::initNetwork(nlohmann::json& network)
 {
-	if (!network.count("private")) network["private"] = true;
-	if (!network.count("creationTime")) network["creationTime"] = OSUtils::now();
-	if (!network.count("name")) network["name"] = "";
-	if (!network.count("multicastLimit")) network["multicastLimit"] = (uint64_t)32;
-	if (!network.count("enableBroadcast")) network["enableBroadcast"] = true;
-	if (!network.count("v4AssignMode")) network["v4AssignMode"] = {{"zt",false}};
-	if (!network.count("v6AssignMode")) network["v6AssignMode"] = {{"rfc4193",false},{"zt",false},{"6plane",false}};
-	if (!network.count("authTokens")) network["authTokens"] = {{}};
-	if (!network.count("capabilities")) network["capabilities"] = nlohmann::json::array();
-	if (!network.count("tags")) network["tags"] = nlohmann::json::array();
-	if (!network.count("routes")) network["routes"] = nlohmann::json::array();
-	if (!network.count("ipAssignmentPools")) network["ipAssignmentPools"] = nlohmann::json::array();
-	if (!network.count("mtu")) network["mtu"] = ZT_DEFAULT_MTU;
-	if (!network.count("remoteTraceTarget")) network["remoteTraceTarget"] = nlohmann::json();
-	if (!network.count("removeTraceLevel")) network["remoteTraceLevel"] = 0;
-	if (!network.count("rulesSource")) network["rulesSource"] = "";
-	if (!network.count("rules")) {
+	if (! network.count("private"))
+		network["private"] = true;
+	if (! network.count("creationTime"))
+		network["creationTime"] = OSUtils::now();
+	if (! network.count("name"))
+		network["name"] = "";
+	if (! network.count("multicastLimit"))
+		network["multicastLimit"] = (uint64_t)32;
+	if (! network.count("enableBroadcast"))
+		network["enableBroadcast"] = true;
+	if (! network.count("v4AssignMode"))
+		network["v4AssignMode"] = { { "zt", false } };
+	if (! network.count("v6AssignMode"))
+		network["v6AssignMode"] = { { "rfc4193", false }, { "zt", false }, { "6plane", false } };
+	if (! network.count("authTokens"))
+		network["authTokens"] = { {} };
+	if (! network.count("capabilities"))
+		network["capabilities"] = nlohmann::json::array();
+	if (! network.count("tags"))
+		network["tags"] = nlohmann::json::array();
+	if (! network.count("routes"))
+		network["routes"] = nlohmann::json::array();
+	if (! network.count("ipAssignmentPools"))
+		network["ipAssignmentPools"] = nlohmann::json::array();
+	if (! network.count("mtu"))
+		network["mtu"] = ZT_DEFAULT_MTU;
+	if (! network.count("remoteTraceTarget"))
+		network["remoteTraceTarget"] = nlohmann::json();
+	if (! network.count("removeTraceLevel"))
+		network["remoteTraceLevel"] = 0;
+	if (! network.count("rulesSource"))
+		network["rulesSource"] = "";
+	if (! network.count("rules")) {
 		// If unspecified, rules are set to allow anything and behave like a flat L2 segment
-		network["rules"] = {{
-			{ "not",false },
-			{ "or", false },
-			{ "type","ACTION_ACCEPT" }
-		}};
+		network["rules"] = { { { "not", false }, { "or", false }, { "type", "ACTION_ACCEPT" } } };
 	}
-	if (!network.count("dns")) network["dns"] = nlohmann::json::array();
-	if (!network.count("ssoEnabled")) network["ssoEnabled"] = false;
-	if (!network.count("clientId")) network["clientId"] = "";
-	if (!network.count("authorizationEndpoint")) network["authorizationEndpoint"] = "";
+	if (! network.count("dns"))
+		network["dns"] = nlohmann::json::array();
+	if (! network.count("ssoEnabled"))
+		network["ssoEnabled"] = false;
+	if (! network.count("clientId"))
+		network["clientId"] = "";
+	if (! network.count("authorizationEndpoint"))
+		network["authorizationEndpoint"] = "";
 
 	network["objtype"] = "network";
 }
 
-void DB::initMember(nlohmann::json &member)
+void DB::initMember(nlohmann::json& member)
 {
-	if (!member.count("authorized")) member["authorized"] = false;
-	if (!member.count("ssoExempt")) member["ssoExempt"] = false;
-	if (!member.count("ipAssignments")) member["ipAssignments"] = nlohmann::json::array();
-	if (!member.count("activeBridge")) member["activeBridge"] = false;
-	if (!member.count("tags")) member["tags"] = nlohmann::json::array();
-	if (!member.count("capabilities")) member["capabilities"] = nlohmann::json::array();
-	if (!member.count("creationTime")) member["creationTime"] = OSUtils::now();
-	if (!member.count("noAutoAssignIps")) member["noAutoAssignIps"] = false;
-	if (!member.count("revision")) member["revision"] = 0ULL;
-	if (!member.count("lastDeauthorizedTime")) member["lastDeauthorizedTime"] = 0ULL;
-	if (!member.count("lastAuthorizedTime")) member["lastAuthorizedTime"] = 0ULL;
-	if (!member.count("lastAuthorizedCredentialType")) member["lastAuthorizedCredentialType"] = nlohmann::json();
-	if (!member.count("lastAuthorizedCredential")) member["lastAuthorizedCredential"] = nlohmann::json();
-	if (!member.count("authenticationExpiryTime")) member["authenticationExpiryTime"] = 0LL;
-	if (!member.count("vMajor")) member["vMajor"] = -1;
-	if (!member.count("vMinor")) member["vMinor"] = -1;
-	if (!member.count("vRev")) member["vRev"] = -1;
-	if (!member.count("vProto")) member["vProto"] = -1;
-	if (!member.count("remoteTraceTarget")) member["remoteTraceTarget"] = nlohmann::json();
-	if (!member.count("removeTraceLevel")) member["remoteTraceLevel"] = 0;
+	if (! member.count("authorized"))
+		member["authorized"] = false;
+	if (! member.count("ssoExempt"))
+		member["ssoExempt"] = false;
+	if (! member.count("ipAssignments"))
+		member["ipAssignments"] = nlohmann::json::array();
+	if (! member.count("activeBridge"))
+		member["activeBridge"] = false;
+	if (! member.count("tags"))
+		member["tags"] = nlohmann::json::array();
+	if (! member.count("capabilities"))
+		member["capabilities"] = nlohmann::json::array();
+	if (! member.count("creationTime"))
+		member["creationTime"] = OSUtils::now();
+	if (! member.count("noAutoAssignIps"))
+		member["noAutoAssignIps"] = false;
+	if (! member.count("revision"))
+		member["revision"] = 0ULL;
+	if (! member.count("lastDeauthorizedTime"))
+		member["lastDeauthorizedTime"] = 0ULL;
+	if (! member.count("lastAuthorizedTime"))
+		member["lastAuthorizedTime"] = 0ULL;
+	if (! member.count("lastAuthorizedCredentialType"))
+		member["lastAuthorizedCredentialType"] = nlohmann::json();
+	if (! member.count("lastAuthorizedCredential"))
+		member["lastAuthorizedCredential"] = nlohmann::json();
+	if (! member.count("authenticationExpiryTime"))
+		member["authenticationExpiryTime"] = 0LL;
+	if (! member.count("vMajor"))
+		member["vMajor"] = -1;
+	if (! member.count("vMinor"))
+		member["vMinor"] = -1;
+	if (! member.count("vRev"))
+		member["vRev"] = -1;
+	if (! member.count("vProto"))
+		member["vProto"] = -1;
+	if (! member.count("remoteTraceTarget"))
+		member["remoteTraceTarget"] = nlohmann::json();
+	if (! member.count("removeTraceLevel"))
+		member["remoteTraceLevel"] = 0;
 	member["objtype"] = "member";
 }
 
-void DB::cleanNetwork(nlohmann::json &network)
+void DB::cleanNetwork(nlohmann::json& network)
 {
 	network.erase("clock");
 	network.erase("authorizedMemberCount");
@@ -91,21 +128,25 @@ void DB::cleanNetwork(nlohmann::json &network)
 	network.erase("lastModified");
 }
 
-void DB::cleanMember(nlohmann::json &member)
+void DB::cleanMember(nlohmann::json& member)
 {
 	member.erase("clock");
 	member.erase("physicalAddr");
 	member.erase("recentLog");
 	member.erase("lastModified");
 	member.erase("lastRequestMetaData");
-	member.erase("authenticationURL"); // computed
-	member.erase("authenticationClientID"); // computed
+	member.erase("authenticationURL");		  // computed
+	member.erase("authenticationClientID");	  // computed
 }
 
-DB::DB() {}
-DB::~DB() {}
+DB::DB()
+{
+}
+DB::~DB()
+{
+}
 
-bool DB::get(const uint64_t networkId,nlohmann::json &network)
+bool DB::get(const uint64_t networkId, nlohmann::json& network)
 {
 	waitForReady();
 	Metrics::db_get_network++;
@@ -124,7 +165,7 @@ bool DB::get(const uint64_t networkId,nlohmann::json &network)
 	return true;
 }
 
-bool DB::get(const uint64_t networkId,nlohmann::json &network,const uint64_t memberId,nlohmann::json &member)
+bool DB::get(const uint64_t networkId, nlohmann::json& network, const uint64_t memberId, nlohmann::json& member)
 {
 	waitForReady();
 	Metrics::db_get_network_and_member++;
@@ -147,7 +188,7 @@ bool DB::get(const uint64_t networkId,nlohmann::json &network,const uint64_t mem
 	return true;
 }
 
-bool DB::get(const uint64_t networkId,nlohmann::json &network,const uint64_t memberId,nlohmann::json &member,NetworkSummaryInfo &info)
+bool DB::get(const uint64_t networkId, nlohmann::json& network, const uint64_t memberId, nlohmann::json& member, NetworkSummaryInfo& info)
 {
 	waitForReady();
 	Metrics::db_get_network_and_member_and_summary++;
@@ -162,7 +203,7 @@ bool DB::get(const uint64_t networkId,nlohmann::json &network,const uint64_t mem
 	{
 		std::shared_lock<std::shared_mutex> l2(nw->lock);
 		network = nw->config;
-		_fillSummaryInfo(nw,info);
+		_fillSummaryInfo(nw, info);
 		auto m = nw->members.find(memberId);
 		if (m == nw->members.end())
 			return false;
@@ -171,7 +212,7 @@ bool DB::get(const uint64_t networkId,nlohmann::json &network,const uint64_t mem
 	return true;
 }
 
-bool DB::get(const uint64_t networkId,nlohmann::json &network,std::vector<nlohmann::json> &members)
+bool DB::get(const uint64_t networkId, nlohmann::json& network, std::vector<nlohmann::json>& members)
 {
 	waitForReady();
 	Metrics::db_get_member_list++;
@@ -186,23 +227,23 @@ bool DB::get(const uint64_t networkId,nlohmann::json &network,std::vector<nlohma
 	{
 		std::shared_lock<std::shared_mutex> l2(nw->lock);
 		network = nw->config;
-		for(auto m=nw->members.begin();m!=nw->members.end();++m) {
+		for (auto m = nw->members.begin(); m != nw->members.end(); ++m) {
 			members.push_back(m->second);
 		}
 	}
 	return true;
 }
 
-void DB::networks(std::set<uint64_t> &networks)
+void DB::networks(std::set<uint64_t>& networks)
 {
 	waitForReady();
 	Metrics::db_get_network_list++;
 	std::shared_lock<std::shared_mutex> l(_networks_l);
-	for(auto n=_networks.begin();n!=_networks.end();++n)
+	for (auto n = _networks.begin(); n != _networks.end(); ++n)
 		networks.insert(n->first);
 }
 
-void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool notifyListeners)
+void DB::_memberChanged(nlohmann::json& old, nlohmann::json& memberConfig, bool notifyListeners)
 {
 	Metrics::db_member_change++;
 	uint64_t memberId = 0;
@@ -212,9 +253,9 @@ void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool no
 	std::shared_ptr<_Network> nw;
 
 	if (old.is_object()) {
-		memberId = OSUtils::jsonIntHex(old["id"],0ULL);
-		networkId = OSUtils::jsonIntHex(old["nwid"],0ULL);
-		if ((memberId)&&(networkId)) {
+		memberId = OSUtils::jsonIntHex(old["id"], 0ULL);
+		networkId = OSUtils::jsonIntHex(old["nwid"], 0ULL);
+		if ((memberId) && (networkId)) {
 			{
 				std::unique_lock<std::shared_mutex> l(_networks_l);
 				auto nw2 = _networks.find(networkId);
@@ -224,17 +265,17 @@ void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool no
 			}
 			if (nw) {
 				std::unique_lock<std::shared_mutex> l(nw->lock);
-				if (OSUtils::jsonBool(old["activeBridge"],false)) {
+				if (OSUtils::jsonBool(old["activeBridge"], false)) {
 					nw->activeBridgeMembers.erase(memberId);
 				}
-				wasAuth = OSUtils::jsonBool(old["authorized"],false);
+				wasAuth = OSUtils::jsonBool(old["authorized"], false);
 				if (wasAuth) {
 					nw->authorizedMembers.erase(memberId);
 				}
-				json &ips = old["ipAssignments"];
+				json& ips = old["ipAssignments"];
 				if (ips.is_array()) {
-					for(unsigned long i=0;i<ips.size();++i) {
-						json &ipj = ips[i];
+					for (unsigned long i = 0; i < ips.size(); ++i) {
+						json& ipj = ips[i];
 						if (ipj.is_string()) {
 							const std::string ips = ipj;
 							InetAddress ipa(ips.c_str());
@@ -248,14 +289,14 @@ void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool no
 	}
 
 	if (memberConfig.is_object()) {
-		if (!nw) {
-			memberId = OSUtils::jsonIntHex(memberConfig["id"],0ULL);
-			networkId = OSUtils::jsonIntHex(memberConfig["nwid"],0ULL);
-			if ((!memberId)||(!networkId))
+		if (! nw) {
+			memberId = OSUtils::jsonIntHex(memberConfig["id"], 0ULL);
+			networkId = OSUtils::jsonIntHex(memberConfig["nwid"], 0ULL);
+			if ((! memberId) || (! networkId))
 				return;
 			std::unique_lock<std::shared_mutex> l(_networks_l);
-			std::shared_ptr<_Network> &nw2 = _networks[networkId];
-			if (!nw2)
+			std::shared_ptr<_Network>& nw2 = _networks[networkId];
+			if (! nw2)
 				nw2.reset(new _Network);
 			nw = nw2;
 		}
@@ -265,18 +306,18 @@ void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool no
 
 			nw->members[memberId] = memberConfig;
 
-			if (OSUtils::jsonBool(memberConfig["activeBridge"],false)) {
+			if (OSUtils::jsonBool(memberConfig["activeBridge"], false)) {
 				nw->activeBridgeMembers.insert(memberId);
 			}
-			isAuth = OSUtils::jsonBool(memberConfig["authorized"],false);
+			isAuth = OSUtils::jsonBool(memberConfig["authorized"], false);
 			if (isAuth) {
 				Metrics::member_auths++;
 				nw->authorizedMembers.insert(memberId);
 			}
-			json &ips = memberConfig["ipAssignments"];
+			json& ips = memberConfig["ipAssignments"];
 			if (ips.is_array()) {
-				for(unsigned long i=0;i<ips.size();++i) {
-					json &ipj = ips[i];
+				for (unsigned long i = 0; i < ips.size(); ++i) {
+					json& ipj = ips[i];
 					if (ipj.is_string()) {
 						const std::string ips = ipj;
 						InetAddress ipa(ips.c_str());
@@ -286,8 +327,8 @@ void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool no
 				}
 			}
 
-			if (!isAuth) {
-				const int64_t ldt = (int64_t)OSUtils::jsonInt(memberConfig["lastDeauthorizedTime"],0ULL);
+			if (! isAuth) {
+				const int64_t ldt = (int64_t)OSUtils::jsonInt(memberConfig["lastDeauthorizedTime"], 0ULL);
 				if (ldt > nw->mostRecentDeauthTime)
 					nw->mostRecentDeauthTime = ldt;
 			}
@@ -295,11 +336,12 @@ void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool no
 
 		if (notifyListeners) {
 			std::unique_lock<std::shared_mutex> ll(_changeListeners_l);
-			for(auto i=_changeListeners.begin();i!=_changeListeners.end();++i) {
-				(*i)->onNetworkMemberUpdate(this,networkId,memberId,memberConfig);
+			for (auto i = _changeListeners.begin(); i != _changeListeners.end(); ++i) {
+				(*i)->onNetworkMemberUpdate(this, networkId, memberId, memberConfig);
 			}
 		}
-	} else if (memberId) {
+	}
+	else if (memberId) {
 		if (nw) {
 			std::unique_lock<std::shared_mutex> l(nw->lock);
 			nw->members.erase(memberId);
@@ -307,7 +349,7 @@ void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool no
 		if (networkId) {
 			std::unique_lock<std::shared_mutex> l(_networks_l);
 			auto er = _networkByMember.equal_range(memberId);
-			for(auto i=er.first;i!=er.second;++i) {
+			for (auto i = er.first; i != er.second; ++i) {
 				if (i->second == networkId) {
 					_networkByMember.erase(i);
 					break;
@@ -317,40 +359,45 @@ void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool no
 	}
 
 	if (notifyListeners) {
-		if(networkId != 0 && memberId != 0 && old.is_object() && !memberConfig.is_object()) {
+		if (networkId != 0 && memberId != 0 && old.is_object() && ! memberConfig.is_object()) {
 			// member delete
 			Metrics::member_count--;
-		} else if (networkId != 0 && memberId != 0 && !old.is_object() && memberConfig.is_object()) {
+		}
+		else if (networkId != 0 && memberId != 0 && ! old.is_object() && memberConfig.is_object()) {
 			// new member
 			Metrics::member_count++;
 		}
 
-		if (!wasAuth && isAuth) {
+		if (! wasAuth && isAuth) {
 			Metrics::member_auths++;
-		} else if (wasAuth && !isAuth) {
+		}
+		else if (wasAuth && ! isAuth) {
 			Metrics::member_deauths++;
-		} else {
+		}
+		else {
 			Metrics::member_changes++;
 		}
 	}
 
-	if ((notifyListeners)&&((wasAuth)&&(!isAuth)&&(networkId)&&(memberId))) {
+	if ((notifyListeners) && ((wasAuth) && (! isAuth) && (networkId) && (memberId))) {
 		std::unique_lock<std::shared_mutex> ll(_changeListeners_l);
-		for(auto i=_changeListeners.begin();i!=_changeListeners.end();++i) {
-			(*i)->onNetworkMemberDeauthorize(this,networkId,memberId);
+		for (auto i = _changeListeners.begin(); i != _changeListeners.end(); ++i) {
+			(*i)->onNetworkMemberDeauthorize(this, networkId, memberId);
 		}
 	}
 }
 
-void DB::_networkChanged(nlohmann::json &old,nlohmann::json &networkConfig,bool notifyListeners)
+void DB::_networkChanged(nlohmann::json& old, nlohmann::json& networkConfig, bool notifyListeners)
 {
 	Metrics::db_network_change++;
 	if (notifyListeners) {
 		if (old.is_object() && old.contains("id") && networkConfig.is_object() && networkConfig.contains("id")) {
 			Metrics::network_changes++;
-		} else if (!old.is_object() && networkConfig.is_object() && networkConfig.contains("id")) {
+		}
+		else if (! old.is_object() && networkConfig.is_object() && networkConfig.contains("id")) {
 			Metrics::network_count++;
-		} else if (old.is_object() && old.contains("id") && !networkConfig.is_object()) {
+		}
+		else if (old.is_object() && old.contains("id") && ! networkConfig.is_object()) {
 			Metrics::network_count--;
 		}
 	}
@@ -362,8 +409,8 @@ void DB::_networkChanged(nlohmann::json &old,nlohmann::json &networkConfig,bool
 			std::shared_ptr<_Network> nw;
 			{
 				std::unique_lock<std::shared_mutex> l(_networks_l);
-				std::shared_ptr<_Network> &nw2 = _networks[networkId];
-				if (!nw2)
+				std::shared_ptr<_Network>& nw2 = _networks[networkId];
+				if (! nw2)
 					nw2.reset(new _Network);
 				nw = nw2;
 			}
@@ -373,12 +420,13 @@ void DB::_networkChanged(nlohmann::json &old,nlohmann::json &networkConfig,bool
 			}
 			if (notifyListeners) {
 				std::unique_lock<std::shared_mutex> ll(_changeListeners_l);
-				for(auto i=_changeListeners.begin();i!=_changeListeners.end();++i) {
-					(*i)->onNetworkUpdate(this,networkId,networkConfig);
+				for (auto i = _changeListeners.begin(); i != _changeListeners.end(); ++i) {
+					(*i)->onNetworkUpdate(this, networkId, networkConfig);
 				}
 			}
 		}
-	} else if (old.is_object()) {
+	}
+	else if (old.is_object()) {
 		const std::string ids = old["id"];
 		const uint64_t networkId = Utils::hexStrToU64(ids.c_str());
 		if (networkId) {
@@ -387,15 +435,16 @@ void DB::_networkChanged(nlohmann::json &old,nlohmann::json &networkConfig,bool
 				nlohmann::json network;
 				std::vector<nlohmann::json> members;
 				this->get(networkId, network, members);
-				for(auto i=members.begin();i!=members.end();++i) {
+				for (auto i = members.begin(); i != members.end(); ++i) {
 					const std::string nodeID = (*i)["id"];
 					const uint64_t memberId = Utils::hexStrToU64(nodeID.c_str());
 					std::unique_lock<std::shared_mutex> ll(_changeListeners_l);
-					for(auto j=_changeListeners.begin();j!=_changeListeners.end();++j) {
-						(*j)->onNetworkMemberDeauthorize(this,networkId,memberId);
+					for (auto j = _changeListeners.begin(); j != _changeListeners.end(); ++j) {
+						(*j)->onNetworkMemberDeauthorize(this, networkId, memberId);
 					}
 				}
-			} catch (std::exception &e) {
+			}
+			catch (std::exception& e) {
 				std::cerr << "Error deauthorizing members on network delete: " << e.what() << std::endl;
 			}
 
@@ -406,17 +455,17 @@ void DB::_networkChanged(nlohmann::json &old,nlohmann::json &networkConfig,bool
 	}
 }
 
-void DB::_fillSummaryInfo(const std::shared_ptr<_Network> &nw,NetworkSummaryInfo &info)
+void DB::_fillSummaryInfo(const std::shared_ptr<_Network>& nw, NetworkSummaryInfo& info)
 {
-	for(auto ab=nw->activeBridgeMembers.begin();ab!=nw->activeBridgeMembers.end();++ab)
+	for (auto ab = nw->activeBridgeMembers.begin(); ab != nw->activeBridgeMembers.end(); ++ab)
 		info.activeBridges.push_back(Address(*ab));
-	std::sort(info.activeBridges.begin(),info.activeBridges.end());
-	for(auto ip=nw->allocatedIps.begin();ip!=nw->allocatedIps.end();++ip)
+	std::sort(info.activeBridges.begin(), info.activeBridges.end());
+	for (auto ip = nw->allocatedIps.begin(); ip != nw->allocatedIps.end(); ++ip)
 		info.allocatedIps.push_back(*ip);
-	std::sort(info.allocatedIps.begin(),info.allocatedIps.end());
+	std::sort(info.allocatedIps.begin(), info.allocatedIps.end());
 	info.authorizedMemberCount = (unsigned long)nw->authorizedMembers.size();
 	info.totalMemberCount = (unsigned long)nw->members.size();
 	info.mostRecentDeauthTime = nw->mostRecentDeauthTime;
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier

+ 78 - 79
controller/DB.hpp

@@ -14,49 +14,36 @@
 #ifndef ZT_CONTROLLER_DB_HPP
 #define ZT_CONTROLLER_DB_HPP
 
-//#define ZT_CONTROLLER_USE_LIBPQ
+// #define ZT_CONTROLLER_USE_LIBPQ
 
 #include "../node/Constants.hpp"
 #include "../node/Identity.hpp"
 #include "../node/InetAddress.hpp"
-#include "../osdep/OSUtils.hpp"
 #include "../osdep/BlockingQueue.hpp"
+#include "../osdep/OSUtils.hpp"
 
+#include <atomic>
+#include <map>
 #include <memory>
+#include <nlohmann/json.hpp>
+#include <prometheus/simpleapi.h>
+#include <set>
+#include <shared_mutex>
 #include <string>
 #include <thread>
 #include <unordered_map>
 #include <unordered_set>
 #include <vector>
-#include <atomic>
-#include <shared_mutex>
-#include <set>
-#include <map>
-
-#include <nlohmann/json.hpp>
-
-#include <prometheus/simpleapi.h>
 
 #define ZT_MEMBER_AUTH_TIMEOUT_NOTIFY_BEFORE 25000
 
-namespace ZeroTier
-{
-
-struct AuthInfo
-{
-public:
-	AuthInfo() 
-	: enabled(false)
-	, version(0)
-	, authenticationURL()
-	, authenticationExpiryTime(0)
-	, issuerURL()
-	, centralAuthURL()
-	, ssoNonce()
-	, ssoState()
-	, ssoClientID()
-	, ssoProvider("default")
-	{}
+namespace ZeroTier {
+
+struct AuthInfo {
+  public:
+	AuthInfo() : enabled(false), version(0), authenticationURL(), authenticationExpiryTime(0), issuerURL(), centralAuthURL(), ssoNonce(), ssoState(), ssoClientID(), ssoProvider("default")
+	{
+	}
 
 	bool enabled;
 	uint64_t version;
@@ -73,22 +60,31 @@ public:
 /**
  * Base class with common infrastructure for all controller DB implementations
  */
-class DB
-{
-public:
-	class ChangeListener
-	{
-	public:
-		ChangeListener() {}
-		virtual ~ChangeListener() {}
-		virtual void onNetworkUpdate(const void *db,uint64_t networkId,const nlohmann::json &network) {}
-		virtual void onNetworkMemberUpdate(const void *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member) {}
-		virtual void onNetworkMemberDeauthorize(const void *db,uint64_t networkId,uint64_t memberId) {}
+class DB {
+  public:
+	class ChangeListener {
+	  public:
+		ChangeListener()
+		{
+		}
+		virtual ~ChangeListener()
+		{
+		}
+		virtual void onNetworkUpdate(const void* db, uint64_t networkId, const nlohmann::json& network)
+		{
+		}
+		virtual void onNetworkMemberUpdate(const void* db, uint64_t networkId, uint64_t memberId, const nlohmann::json& member)
+		{
+		}
+		virtual void onNetworkMemberDeauthorize(const void* db, uint64_t networkId, uint64_t memberId)
+		{
+		}
 	};
 
-	struct NetworkSummaryInfo
-	{
-		NetworkSummaryInfo() : authorizedMemberCount(0),totalMemberCount(0),mostRecentDeauthTime(0) {}
+	struct NetworkSummaryInfo {
+		NetworkSummaryInfo() : authorizedMemberCount(0), totalMemberCount(0), mostRecentDeauthTime(0)
+		{
+		}
 		std::vector<Address> activeBridges;
 		std::vector<InetAddress> allocatedIps;
 		unsigned long authorizedMemberCount;
@@ -96,10 +92,10 @@ public:
 		int64_t mostRecentDeauthTime;
 	};
 
-	static void initNetwork(nlohmann::json &network);
-	static void initMember(nlohmann::json &member);
-	static void cleanNetwork(nlohmann::json &network);
-	static void cleanMember(nlohmann::json &member);
+	static void initNetwork(nlohmann::json& network);
+	static void initMember(nlohmann::json& member);
+	static void cleanNetwork(nlohmann::json& network);
+	static void cleanMember(nlohmann::json& member);
 
 	DB();
 	virtual ~DB();
@@ -113,41 +109,43 @@ public:
 		return (_networks.find(networkId) != _networks.end());
 	}
 
-	bool get(const uint64_t networkId,nlohmann::json &network);
-	bool get(const uint64_t networkId,nlohmann::json &network,const uint64_t memberId,nlohmann::json &member);
-	bool get(const uint64_t networkId,nlohmann::json &network,const uint64_t memberId,nlohmann::json &member,NetworkSummaryInfo &info);
-	bool get(const uint64_t networkId,nlohmann::json &network,std::vector<nlohmann::json> &members);
+	bool get(const uint64_t networkId, nlohmann::json& network);
+	bool get(const uint64_t networkId, nlohmann::json& network, const uint64_t memberId, nlohmann::json& member);
+	bool get(const uint64_t networkId, nlohmann::json& network, const uint64_t memberId, nlohmann::json& member, NetworkSummaryInfo& info);
+	bool get(const uint64_t networkId, nlohmann::json& network, std::vector<nlohmann::json>& members);
 
-	void networks(std::set<uint64_t> &networks);
+	void networks(std::set<uint64_t>& networks);
 
-	template<typename F>
-	inline void each(F f)
+	template <typename F> inline void each(F f)
 	{
 		nlohmann::json nullJson;
 		std::unique_lock<std::shared_mutex> lck(_networks_l);
-		for(auto nw=_networks.begin();nw!=_networks.end();++nw) {
-			f(nw->first,nw->second->config,0,nullJson); // first provide network with 0 for member ID
-			for(auto m=nw->second->members.begin();m!=nw->second->members.end();++m) {
-				f(nw->first,nw->second->config,m->first,m->second);
+		for (auto nw = _networks.begin(); nw != _networks.end(); ++nw) {
+			f(nw->first, nw->second->config, 0, nullJson);	 // first provide network with 0 for member ID
+			for (auto m = nw->second->members.begin(); m != nw->second->members.end(); ++m) {
+				f(nw->first, nw->second->config, m->first, m->second);
 			}
 		}
 	}
 
-	virtual bool save(nlohmann::json &record,bool notifyListeners) = 0;
+	virtual bool save(nlohmann::json& record, bool notifyListeners) = 0;
 	virtual void eraseNetwork(const uint64_t networkId) = 0;
-	virtual void eraseMember(const uint64_t networkId,const uint64_t memberId) = 0;
-	virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress) = 0;
+	virtual void eraseMember(const uint64_t networkId, const uint64_t memberId) = 0;
+	virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress) = 0;
 
-	virtual AuthInfo getSSOAuthInfo(const nlohmann::json &member, const std::string &redirectURL) { return AuthInfo(); }
+	virtual AuthInfo getSSOAuthInfo(const nlohmann::json& member, const std::string& redirectURL)
+	{
+		return AuthInfo();
+	}
 
-	inline void addListener(DB::ChangeListener *const listener)
+	inline void addListener(DB::ChangeListener* const listener)
 	{
 		std::unique_lock<std::shared_mutex> l(_changeListeners_l);
 		_changeListeners.push_back(listener);
 	}
 
-protected:
-	static inline bool _compareRecords(const nlohmann::json &a,const nlohmann::json &b)
+  protected:
+	static inline bool _compareRecords(const nlohmann::json& a, const nlohmann::json& b)
 	{
 		if (a.is_object() == b.is_object()) {
 			if (a.is_object()) {
@@ -155,10 +153,10 @@ protected:
 					return false;
 				auto amap = a.get<nlohmann::json::object_t>();
 				auto bmap = b.get<nlohmann::json::object_t>();
-				for(auto ai=amap.begin();ai!=amap.end();++ai) {
-					if (ai->first != "revision") { // ignore revision, compare only non-revision-counter fields
+				for (auto ai = amap.begin(); ai != amap.end(); ++ai) {
+					if (ai->first != "revision") {	 // ignore revision, compare only non-revision-counter fields
 						auto bi = bmap.find(ai->first);
-						if ((bi == bmap.end())||(bi->second != ai->second))
+						if ((bi == bmap.end()) || (bi->second != ai->second))
 							return false;
 					}
 				}
@@ -169,29 +167,30 @@ protected:
 		return false;
 	}
 
-	struct _Network
-	{
-		_Network() : mostRecentDeauthTime(0) {}
+	struct _Network {
+		_Network() : mostRecentDeauthTime(0)
+		{
+		}
 		nlohmann::json config;
-		std::unordered_map<uint64_t,nlohmann::json> members;
+		std::unordered_map<uint64_t, nlohmann::json> members;
 		std::unordered_set<uint64_t> activeBridgeMembers;
 		std::unordered_set<uint64_t> authorizedMembers;
-		std::unordered_set<InetAddress,InetAddress::Hasher> allocatedIps;
+		std::unordered_set<InetAddress, InetAddress::Hasher> allocatedIps;
 		int64_t mostRecentDeauthTime;
 		std::shared_mutex lock;
 	};
 
-	virtual void _memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool notifyListeners);
-	virtual void _networkChanged(nlohmann::json &old,nlohmann::json &networkConfig,bool notifyListeners);
-	void _fillSummaryInfo(const std::shared_ptr<_Network> &nw,NetworkSummaryInfo &info);
+	virtual void _memberChanged(nlohmann::json& old, nlohmann::json& memberConfig, bool notifyListeners);
+	virtual void _networkChanged(nlohmann::json& old, nlohmann::json& networkConfig, bool notifyListeners);
+	void _fillSummaryInfo(const std::shared_ptr<_Network>& nw, NetworkSummaryInfo& info);
 
-	std::vector<DB::ChangeListener *> _changeListeners;
-	std::unordered_map< uint64_t,std::shared_ptr<_Network> > _networks;
-	std::unordered_multimap< uint64_t,uint64_t > _networkByMember;
+	std::vector<DB::ChangeListener*> _changeListeners;
+	std::unordered_map<uint64_t, std::shared_ptr<_Network> > _networks;
+	std::unordered_multimap<uint64_t, uint64_t> _networkByMember;
 	mutable std::shared_mutex _changeListeners_l;
 	mutable std::shared_mutex _networks_l;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 66 - 67
controller/DBMirrorSet.cpp

@@ -15,56 +15,54 @@
 
 namespace ZeroTier {
 
-DBMirrorSet::DBMirrorSet(DB::ChangeListener *listener)
-	: _listener(listener)
-	, _running(true)
-	, _syncCheckerThread()
-	, _dbs()
-	, _dbs_l()
+DBMirrorSet::DBMirrorSet(DB::ChangeListener* listener) : _listener(listener), _running(true), _syncCheckerThread(), _dbs(), _dbs_l()
 {
 	_syncCheckerThread = std::thread([this]() {
-		for(;;) {
-			for(int i=0;i<120;++i) { // 1 minute delay between checks
-				if (!_running)
+		for (;;) {
+			for (int i = 0; i < 120; ++i) {	  // 1 minute delay between checks
+				if (! _running)
 					return;
 				std::this_thread::sleep_for(std::chrono::milliseconds(500));
 			}
 
-			std::vector< std::shared_ptr<DB> > dbs;
+			std::vector<std::shared_ptr<DB> > dbs;
 			{
 				std::unique_lock<std::shared_mutex> l(_dbs_l);
 				if (_dbs.size() <= 1)
-					continue; // no need to do this if there's only one DB, so skip the iteration
+					continue;	// no need to do this if there's only one DB, so skip the iteration
 				dbs = _dbs;
 			}
 
-			for(auto db=dbs.begin();db!=dbs.end();++db) {
-				(*db)->each([&dbs,&db](uint64_t networkId,const nlohmann::json &network,uint64_t memberId,const nlohmann::json &member) {
+			for (auto db = dbs.begin(); db != dbs.end(); ++db) {
+				(*db)->each([&dbs, &db](uint64_t networkId, const nlohmann::json& network, uint64_t memberId, const nlohmann::json& member) {
 					try {
 						if (network.is_object()) {
 							if (memberId == 0) {
-								for(auto db2=dbs.begin();db2!=dbs.end();++db2) {
+								for (auto db2 = dbs.begin(); db2 != dbs.end(); ++db2) {
 									if (db->get() != db2->get()) {
 										nlohmann::json nw2;
-										if ((!(*db2)->get(networkId,nw2))||((nw2.is_object())&&(OSUtils::jsonInt(nw2["revision"],0) < OSUtils::jsonInt(network["revision"],0)))) {
+										if ((! (*db2)->get(networkId, nw2)) || ((nw2.is_object()) && (OSUtils::jsonInt(nw2["revision"], 0) < OSUtils::jsonInt(network["revision"], 0)))) {
 											nw2 = network;
-											(*db2)->save(nw2,false);
+											(*db2)->save(nw2, false);
 										}
 									}
 								}
-							} else if (member.is_object()) {
-								for(auto db2=dbs.begin();db2!=dbs.end();++db2) {
+							}
+							else if (member.is_object()) {
+								for (auto db2 = dbs.begin(); db2 != dbs.end(); ++db2) {
 									if (db->get() != db2->get()) {
-										nlohmann::json nw2,m2;
-										if ((!(*db2)->get(networkId,nw2,memberId,m2))||((m2.is_object())&&(OSUtils::jsonInt(m2["revision"],0) < OSUtils::jsonInt(member["revision"],0)))) {
+										nlohmann::json nw2, m2;
+										if ((! (*db2)->get(networkId, nw2, memberId, m2)) || ((m2.is_object()) && (OSUtils::jsonInt(m2["revision"], 0) < OSUtils::jsonInt(member["revision"], 0)))) {
 											m2 = member;
-											(*db2)->save(m2,false);
+											(*db2)->save(m2, false);
 										}
 									}
 								}
 							}
 						}
-					} catch ( ... ) {} // skip entries that generate JSON errors
+					}
+					catch (...) {
+					}	// skip entries that generate JSON errors
 				});
 			}
 		}
@@ -80,58 +78,58 @@ DBMirrorSet::~DBMirrorSet()
 bool DBMirrorSet::hasNetwork(const uint64_t networkId) const
 {
 	std::shared_lock<std::shared_mutex> l(_dbs_l);
-	for(auto d=_dbs.begin();d!=_dbs.end();++d) {
+	for (auto d = _dbs.begin(); d != _dbs.end(); ++d) {
 		if ((*d)->hasNetwork(networkId))
 			return true;
 	}
 	return false;
 }
 
-bool DBMirrorSet::get(const uint64_t networkId,nlohmann::json &network)
+bool DBMirrorSet::get(const uint64_t networkId, nlohmann::json& network)
 {
 	std::shared_lock<std::shared_mutex> l(_dbs_l);
-	for(auto d=_dbs.begin();d!=_dbs.end();++d) {
-		if ((*d)->get(networkId,network)) {
+	for (auto d = _dbs.begin(); d != _dbs.end(); ++d) {
+		if ((*d)->get(networkId, network)) {
 			return true;
 		}
 	}
 	return false;
 }
 
-bool DBMirrorSet::get(const uint64_t networkId,nlohmann::json &network,const uint64_t memberId,nlohmann::json &member)
+bool DBMirrorSet::get(const uint64_t networkId, nlohmann::json& network, const uint64_t memberId, nlohmann::json& member)
 {
 	std::shared_lock<std::shared_mutex> l(_dbs_l);
-	for(auto d=_dbs.begin();d!=_dbs.end();++d) {
-		if ((*d)->get(networkId,network,memberId,member))
+	for (auto d = _dbs.begin(); d != _dbs.end(); ++d) {
+		if ((*d)->get(networkId, network, memberId, member))
 			return true;
 	}
 	return false;
 }
 
-bool DBMirrorSet::get(const uint64_t networkId,nlohmann::json &network,const uint64_t memberId,nlohmann::json &member,DB::NetworkSummaryInfo &info)
+bool DBMirrorSet::get(const uint64_t networkId, nlohmann::json& network, const uint64_t memberId, nlohmann::json& member, DB::NetworkSummaryInfo& info)
 {
 	std::shared_lock<std::shared_mutex> l(_dbs_l);
-	for(auto d=_dbs.begin();d!=_dbs.end();++d) {
-		if ((*d)->get(networkId,network,memberId,member,info))
+	for (auto d = _dbs.begin(); d != _dbs.end(); ++d) {
+		if ((*d)->get(networkId, network, memberId, member, info))
 			return true;
 	}
 	return false;
 }
 
-bool DBMirrorSet::get(const uint64_t networkId,nlohmann::json &network,std::vector<nlohmann::json> &members)
+bool DBMirrorSet::get(const uint64_t networkId, nlohmann::json& network, std::vector<nlohmann::json>& members)
 {
 	std::shared_lock<std::shared_mutex> l(_dbs_l);
-	for(auto d=_dbs.begin();d!=_dbs.end();++d) {
-		if ((*d)->get(networkId,network,members))
+	for (auto d = _dbs.begin(); d != _dbs.end(); ++d) {
+		if ((*d)->get(networkId, network, members))
 			return true;
 	}
 	return false;
 }
 
-AuthInfo DBMirrorSet::getSSOAuthInfo(const nlohmann::json &member, const std::string &redirectURL) 
+AuthInfo DBMirrorSet::getSSOAuthInfo(const nlohmann::json& member, const std::string& redirectURL)
 {
 	std::shared_lock<std::shared_mutex> l(_dbs_l);
-	for(auto d=_dbs.begin();d!=_dbs.end();++d) { 
+	for (auto d = _dbs.begin(); d != _dbs.end(); ++d) {
 		AuthInfo info = (*d)->getSSOAuthInfo(member, redirectURL);
 		if (info.enabled) {
 			return info;
@@ -140,10 +138,10 @@ AuthInfo DBMirrorSet::getSSOAuthInfo(const nlohmann::json &member, const std::st
 	return AuthInfo();
 }
 
-void DBMirrorSet::networks(std::set<uint64_t> &networks)
+void DBMirrorSet::networks(std::set<uint64_t>& networks)
 {
 	std::shared_lock<std::shared_mutex> l(_dbs_l);
-	for(auto d=_dbs.begin();d!=_dbs.end();++d) {
+	for (auto d = _dbs.begin(); d != _dbs.end(); ++d) {
 		(*d)->networks(networks);
 	}
 }
@@ -152,7 +150,7 @@ bool DBMirrorSet::waitForReady()
 {
 	bool r = false;
 	std::shared_lock<std::shared_mutex> l(_dbs_l);
-	for(auto d=_dbs.begin();d!=_dbs.end();++d) {
+	for (auto d = _dbs.begin(); d != _dbs.end(); ++d) {
 		r |= (*d)->waitForReady();
 	}
 	return r;
@@ -161,30 +159,31 @@ bool DBMirrorSet::waitForReady()
 bool DBMirrorSet::isReady()
 {
 	std::shared_lock<std::shared_mutex> l(_dbs_l);
-	for(auto d=_dbs.begin();d!=_dbs.end();++d) {
-		if (!(*d)->isReady())
+	for (auto d = _dbs.begin(); d != _dbs.end(); ++d) {
+		if (! (*d)->isReady())
 			return false;
 	}
 	return true;
 }
 
-bool DBMirrorSet::save(nlohmann::json &record,bool notifyListeners)
+bool DBMirrorSet::save(nlohmann::json& record, bool notifyListeners)
 {
-	std::vector< std::shared_ptr<DB> > dbs;
+	std::vector<std::shared_ptr<DB> > dbs;
 	{
 		std::unique_lock<std::shared_mutex> l(_dbs_l);
 		dbs = _dbs;
 	}
 	if (notifyListeners) {
-		for(auto d=dbs.begin();d!=dbs.end();++d) {
-			if ((*d)->save(record,true))
+		for (auto d = dbs.begin(); d != dbs.end(); ++d) {
+			if ((*d)->save(record, true))
 				return true;
 		}
 		return false;
-	} else {
+	}
+	else {
 		bool modified = false;
-		for(auto d=dbs.begin();d!=dbs.end();++d) {
-			modified |= (*d)->save(record,false);
+		for (auto d = dbs.begin(); d != dbs.end(); ++d) {
+			modified |= (*d)->save(record, false);
 		}
 		return modified;
 	}
@@ -193,54 +192,54 @@ bool DBMirrorSet::save(nlohmann::json &record,bool notifyListeners)
 void DBMirrorSet::eraseNetwork(const uint64_t networkId)
 {
 	std::unique_lock<std::shared_mutex> l(_dbs_l);
-	for(auto d=_dbs.begin();d!=_dbs.end();++d) {
+	for (auto d = _dbs.begin(); d != _dbs.end(); ++d) {
 		(*d)->eraseNetwork(networkId);
 	}
 }
 
-void DBMirrorSet::eraseMember(const uint64_t networkId,const uint64_t memberId)
+void DBMirrorSet::eraseMember(const uint64_t networkId, const uint64_t memberId)
 {
 	std::unique_lock<std::shared_mutex> l(_dbs_l);
-	for(auto d=_dbs.begin();d!=_dbs.end();++d) {
-		(*d)->eraseMember(networkId,memberId);
+	for (auto d = _dbs.begin(); d != _dbs.end(); ++d) {
+		(*d)->eraseMember(networkId, memberId);
 	}
 }
 
-void DBMirrorSet::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress)
+void DBMirrorSet::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress)
 {
 	std::shared_lock<std::shared_mutex> l(_dbs_l);
-	for(auto d=_dbs.begin();d!=_dbs.end();++d) {
-		(*d)->nodeIsOnline(networkId,memberId,physicalAddress);
+	for (auto d = _dbs.begin(); d != _dbs.end(); ++d) {
+		(*d)->nodeIsOnline(networkId, memberId, physicalAddress);
 	}
 }
 
-void DBMirrorSet::onNetworkUpdate(const void *db,uint64_t networkId,const nlohmann::json &network)
+void DBMirrorSet::onNetworkUpdate(const void* db, uint64_t networkId, const nlohmann::json& network)
 {
 	nlohmann::json record(network);
 	std::unique_lock<std::shared_mutex> l(_dbs_l);
-	for(auto d=_dbs.begin();d!=_dbs.end();++d) {
+	for (auto d = _dbs.begin(); d != _dbs.end(); ++d) {
 		if (d->get() != db) {
-			(*d)->save(record,false);
+			(*d)->save(record, false);
 		}
 	}
-	_listener->onNetworkUpdate(this,networkId,network);
+	_listener->onNetworkUpdate(this, networkId, network);
 }
 
-void DBMirrorSet::onNetworkMemberUpdate(const void *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member)
+void DBMirrorSet::onNetworkMemberUpdate(const void* db, uint64_t networkId, uint64_t memberId, const nlohmann::json& member)
 {
 	nlohmann::json record(member);
 	std::unique_lock<std::shared_mutex> l(_dbs_l);
-	for(auto d=_dbs.begin();d!=_dbs.end();++d) {
+	for (auto d = _dbs.begin(); d != _dbs.end(); ++d) {
 		if (d->get() != db) {
-			(*d)->save(record,false);
+			(*d)->save(record, false);
 		}
 	}
-	_listener->onNetworkMemberUpdate(this,networkId,memberId,member);
+	_listener->onNetworkMemberUpdate(this, networkId, memberId, member);
 }
 
-void DBMirrorSet::onNetworkMemberDeauthorize(const void *db,uint64_t networkId,uint64_t memberId)
+void DBMirrorSet::onNetworkMemberDeauthorize(const void* db, uint64_t networkId, uint64_t memberId)
 {
-	_listener->onNetworkMemberDeauthorize(this,networkId,memberId);
+	_listener->onNetworkMemberDeauthorize(this, networkId, memberId);
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier

+ 22 - 23
controller/DBMirrorSet.hpp

@@ -16,58 +16,57 @@
 
 #include "DB.hpp"
 
-#include <vector>
 #include <memory>
-#include <shared_mutex>
 #include <set>
+#include <shared_mutex>
 #include <thread>
+#include <vector>
 
 namespace ZeroTier {
 
-class DBMirrorSet : public DB::ChangeListener
-{
-public:
-	DBMirrorSet(DB::ChangeListener *listener);
+class DBMirrorSet : public DB::ChangeListener {
+  public:
+	DBMirrorSet(DB::ChangeListener* listener);
 	virtual ~DBMirrorSet();
 
 	bool hasNetwork(const uint64_t networkId) const;
 
-	bool get(const uint64_t networkId,nlohmann::json &network);
-	bool get(const uint64_t networkId,nlohmann::json &network,const uint64_t memberId,nlohmann::json &member);
-	bool get(const uint64_t networkId,nlohmann::json &network,const uint64_t memberId,nlohmann::json &member,DB::NetworkSummaryInfo &info);
-	bool get(const uint64_t networkId,nlohmann::json &network,std::vector<nlohmann::json> &members);
+	bool get(const uint64_t networkId, nlohmann::json& network);
+	bool get(const uint64_t networkId, nlohmann::json& network, const uint64_t memberId, nlohmann::json& member);
+	bool get(const uint64_t networkId, nlohmann::json& network, const uint64_t memberId, nlohmann::json& member, DB::NetworkSummaryInfo& info);
+	bool get(const uint64_t networkId, nlohmann::json& network, std::vector<nlohmann::json>& members);
 
-	void networks(std::set<uint64_t> &networks);
+	void networks(std::set<uint64_t>& networks);
 
 	bool waitForReady();
 	bool isReady();
-	bool save(nlohmann::json &record,bool notifyListeners);
+	bool save(nlohmann::json& record, bool notifyListeners);
 	void eraseNetwork(const uint64_t networkId);
-	void eraseMember(const uint64_t networkId,const uint64_t memberId);
-	void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress);
+	void eraseMember(const uint64_t networkId, const uint64_t memberId);
+	void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress);
 
 	// These are called by various DB instances when changes occur.
-	virtual void onNetworkUpdate(const void *db,uint64_t networkId,const nlohmann::json &network);
-	virtual void onNetworkMemberUpdate(const void *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member);
-	virtual void onNetworkMemberDeauthorize(const void *db,uint64_t networkId,uint64_t memberId);
+	virtual void onNetworkUpdate(const void* db, uint64_t networkId, const nlohmann::json& network);
+	virtual void onNetworkMemberUpdate(const void* db, uint64_t networkId, uint64_t memberId, const nlohmann::json& member);
+	virtual void onNetworkMemberDeauthorize(const void* db, uint64_t networkId, uint64_t memberId);
 
-	AuthInfo getSSOAuthInfo(const nlohmann::json &member, const std::string &redirectURL);
+	AuthInfo getSSOAuthInfo(const nlohmann::json& member, const std::string& redirectURL);
 
-	inline void addDB(const std::shared_ptr<DB> &db)
+	inline void addDB(const std::shared_ptr<DB>& db)
 	{
 		db->addListener(this);
 		std::unique_lock<std::shared_mutex> l(_dbs_l);
 		_dbs.push_back(db);
 	}
 
-private:
-	DB::ChangeListener *const _listener;
+  private:
+	DB::ChangeListener* const _listener;
 	std::atomic_bool _running;
 	std::thread _syncCheckerThread;
-	std::vector< std::shared_ptr< DB > > _dbs;
+	std::vector<std::shared_ptr<DB> > _dbs;
 	mutable std::shared_mutex _dbs_l;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

File diff suppressed because it is too large
+ 328 - 252
controller/EmbeddedNetworkController.cpp


+ 77 - 80
controller/EmbeddedNetworkController.hpp

@@ -14,112 +14,109 @@
 #ifndef ZT_SQLITENETWORKCONTROLLER_HPP
 #define ZT_SQLITENETWORKCONTROLLER_HPP
 
-#include <stdint.h>
-
-#include <string>
-#include <map>
-#include <vector>
-#include <set>
-#include <list>
-#include <thread>
-#include <unordered_map>
-#include <atomic>
-
+#include "../node/Address.hpp"
 #include "../node/Constants.hpp"
+#include "../node/InetAddress.hpp"
 #include "../node/NetworkController.hpp"
 #include "../node/Utils.hpp"
-#include "../node/Address.hpp"
-#include "../node/InetAddress.hpp"
-
+#include "../osdep/BlockingQueue.hpp"
 #include "../osdep/OSUtils.hpp"
 #include "../osdep/Thread.hpp"
-#include "../osdep/BlockingQueue.hpp"
-
-#include <nlohmann/json.hpp>
-
-#include <cpp-httplib/httplib.h>
-
 #include "DB.hpp"
 #include "DBMirrorSet.hpp"
 
+#include <atomic>
+#include <cpp-httplib/httplib.h>
+#include <list>
+#include <map>
+#include <nlohmann/json.hpp>
+#include <set>
+#include <stdint.h>
+#include <string>
+#include <thread>
+#include <unordered_map>
+#include <vector>
+
 namespace ZeroTier {
 
 class Node;
 struct RedisConfig;
 
-class EmbeddedNetworkController : public NetworkController,public DB::ChangeListener
-{
-public:
+class EmbeddedNetworkController
+	: public NetworkController
+	, public DB::ChangeListener {
+  public:
 	/**
 	 * @param node Parent node
 	 * @param dbPath Database path (file path or database credentials)
 	 */
-	EmbeddedNetworkController(Node *node,const char *ztPath,const char *dbPath, int listenPort, RedisConfig *rc);
+	EmbeddedNetworkController(Node* node, const char* ztPath, const char* dbPath, int listenPort, RedisConfig* rc);
 	virtual ~EmbeddedNetworkController();
 
-	virtual void init(const Identity &signingId,Sender *sender);
+	virtual void init(const Identity& signingId, Sender* sender);
 
-	void setSSORedirectURL(const std::string &url);
+	void setSSORedirectURL(const std::string& url);
 
-	virtual void request(
-		uint64_t nwid,
-		const InetAddress &fromAddr,
-		uint64_t requestPacketId,
-		const Identity &identity,
-		const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> &metaData);
+	virtual void request(uint64_t nwid, const InetAddress& fromAddr, uint64_t requestPacketId, const Identity& identity, const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY>& metaData);
 
-	void configureHTTPControlPlane(
-		httplib::Server &s,
-		httplib::Server &sV6,
-		const std::function<void(const httplib::Request&, httplib::Response&, std::string)>);
+	void configureHTTPControlPlane(httplib::Server& s, httplib::Server& sV6, const std::function<void(const httplib::Request&, httplib::Response&, std::string)>);
 
-	void handleRemoteTrace(const ZT_RemoteTrace &rt);
+	void handleRemoteTrace(const ZT_RemoteTrace& rt);
 
-	virtual void onNetworkUpdate(const void *db,uint64_t networkId,const nlohmann::json &network);
-	virtual void onNetworkMemberUpdate(const void *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member);
-	virtual void onNetworkMemberDeauthorize(const void *db,uint64_t networkId,uint64_t memberId);
+	virtual void onNetworkUpdate(const void* db, uint64_t networkId, const nlohmann::json& network);
+	virtual void onNetworkMemberUpdate(const void* db, uint64_t networkId, uint64_t memberId, const nlohmann::json& member);
+	virtual void onNetworkMemberDeauthorize(const void* db, uint64_t networkId, uint64_t memberId);
 
-private:
-	void _request(uint64_t nwid,const InetAddress &fromAddr,uint64_t requestPacketId,const Identity &identity,const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> &metaData);
+  private:
+	void _request(uint64_t nwid, const InetAddress& fromAddr, uint64_t requestPacketId, const Identity& identity, const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY>& metaData);
 	void _startThreads();
 	void _ssoExpiryThread();
 
-	std::string networkUpdateFromPostData(uint64_t networkID, const std::string &body);
+	std::string networkUpdateFromPostData(uint64_t networkID, const std::string& body);
 
-	struct _RQEntry
-	{
+	struct _RQEntry {
 		uint64_t nwid;
 		uint64_t requestPacketId;
 		InetAddress fromAddr;
 		Identity identity;
 		Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> metaData;
-		enum {
-			RQENTRY_TYPE_REQUEST = 0
-		} type;
+		enum { RQENTRY_TYPE_REQUEST = 0 } type;
 	};
 
-	struct _MemberStatusKey
-	{
-		_MemberStatusKey() : networkId(0),nodeId(0) {}
-		_MemberStatusKey(const uint64_t nwid,const uint64_t nid) : networkId(nwid),nodeId(nid) {}
+	struct _MemberStatusKey {
+		_MemberStatusKey() : networkId(0), nodeId(0)
+		{
+		}
+		_MemberStatusKey(const uint64_t nwid, const uint64_t nid) : networkId(nwid), nodeId(nid)
+		{
+		}
 		uint64_t networkId;
 		uint64_t nodeId;
-		inline bool operator==(const _MemberStatusKey &k) const { return ((k.networkId == networkId)&&(k.nodeId == nodeId)); }
-		inline bool operator<(const _MemberStatusKey &k) const { return (k.networkId < networkId) || ((k.networkId == networkId)&&(k.nodeId < nodeId)); }
+		inline bool operator==(const _MemberStatusKey& k) const
+		{
+			return ((k.networkId == networkId) && (k.nodeId == nodeId));
+		}
+		inline bool operator<(const _MemberStatusKey& k) const
+		{
+			return (k.networkId < networkId) || ((k.networkId == networkId) && (k.nodeId < nodeId));
+		}
 	};
-	struct _MemberStatus
-	{
-		_MemberStatus() : lastRequestTime(0),authenticationExpiryTime(-1),vMajor(-1),vMinor(-1),vRev(-1),vProto(-1) {}
+	struct _MemberStatus {
+		_MemberStatus() : lastRequestTime(0), authenticationExpiryTime(-1), vMajor(-1), vMinor(-1), vRev(-1), vProto(-1)
+		{
+		}
 		int64_t lastRequestTime;
 		int64_t authenticationExpiryTime;
-		int vMajor,vMinor,vRev,vProto;
+		int vMajor, vMinor, vRev, vProto;
 		Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> lastRequestMetaData;
 		Identity identity;
-		inline bool online(const int64_t now) const { return ((now - lastRequestTime) < (ZT_NETWORK_AUTOCONF_DELAY * 2)); }
+		inline bool online(const int64_t now) const
+		{
+			return ((now - lastRequestTime) < (ZT_NETWORK_AUTOCONF_DELAY * 2));
+		}
 	};
-	struct _MemberStatusHash
-	{
-		inline std::size_t operator()(const _MemberStatusKey &networkIdNodeId) const
+	struct _MemberStatusHash {
+		inline std::size_t operator()(const _MemberStatusKey& networkIdNodeId) const
 		{
 			return (std::size_t)(networkIdNodeId.networkId + networkIdNodeId.nodeId);
 		}
@@ -127,26 +124,26 @@ private:
 
 	const int64_t _startTime;
 	int _listenPort;
-	Node *const _node;
+	Node* const _node;
 	std::string _ztPath;
 	std::string _path;
 	Identity _signingId;
 	std::string _signingIdAddressString;
-	NetworkController::Sender *_sender;
+	NetworkController::Sender* _sender;
 
 	DBMirrorSet _db;
-	BlockingQueue< _RQEntry * > _queue;
+	BlockingQueue<_RQEntry*> _queue;
 
 	std::vector<std::thread> _threads;
 	std::mutex _threads_l;
 
-	std::unordered_map< _MemberStatusKey,_MemberStatus,_MemberStatusHash > _memberStatus;
+	std::unordered_map<_MemberStatusKey, _MemberStatus, _MemberStatusHash> _memberStatus;
 	std::mutex _memberStatus_l;
 
-	std::set< std::pair<int64_t, _MemberStatusKey> > _expiringSoon;
+	std::set<std::pair<int64_t, _MemberStatusKey> > _expiringSoon;
 	std::mutex _expiringSoon_l;
 
-	RedisConfig *_rc;
+	RedisConfig* _rc;
 	std::string _ssoRedirectURL;
 
 	bool _ssoExpiryRunning;
@@ -154,30 +151,30 @@ private:
 
 #ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK
 	prometheus::simpleapi::benchmark_family_t _member_status_lookup;
-	prometheus::simpleapi::counter_family_t   _member_status_lookup_count;
+	prometheus::simpleapi::counter_family_t _member_status_lookup_count;
 	prometheus::simpleapi::benchmark_family_t _node_is_online;
-	prometheus::simpleapi::counter_family_t   _node_is_online_count;
+	prometheus::simpleapi::counter_family_t _node_is_online_count;
 	prometheus::simpleapi::benchmark_family_t _get_and_init_member;
-	prometheus::simpleapi::counter_family_t   _get_and_init_member_count;
+	prometheus::simpleapi::counter_family_t _get_and_init_member_count;
 	prometheus::simpleapi::benchmark_family_t _have_identity;
-	prometheus::simpleapi::counter_family_t   _have_identity_count;
+	prometheus::simpleapi::counter_family_t _have_identity_count;
 	prometheus::simpleapi::benchmark_family_t _determine_auth;
-	prometheus::simpleapi::counter_family_t   _determine_auth_count;
+	prometheus::simpleapi::counter_family_t _determine_auth_count;
 	prometheus::simpleapi::benchmark_family_t _sso_check;
-	prometheus::simpleapi::counter_family_t   _sso_check_count;
+	prometheus::simpleapi::counter_family_t _sso_check_count;
 	prometheus::simpleapi::benchmark_family_t _auth_check;
-	prometheus::simpleapi::counter_family_t   _auth_check_count;
+	prometheus::simpleapi::counter_family_t _auth_check_count;
 	prometheus::simpleapi::benchmark_family_t _json_schlep;
-	prometheus::simpleapi::counter_family_t   _json_schlep_count;
+	prometheus::simpleapi::counter_family_t _json_schlep_count;
 	prometheus::simpleapi::benchmark_family_t _issue_certificate;
-	prometheus::simpleapi::counter_family_t   _issue_certificate_count;
+	prometheus::simpleapi::counter_family_t _issue_certificate_count;
 	prometheus::simpleapi::benchmark_family_t _save_member;
-	prometheus::simpleapi::counter_family_t   _save_member_count;
+	prometheus::simpleapi::counter_family_t _save_member_count;
 	prometheus::simpleapi::benchmark_family_t _send_netconf;
-	prometheus::simpleapi::counter_family_t   _send_netconf_count;
+	prometheus::simpleapi::counter_family_t _send_netconf_count;
 #endif
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 71 - 66
controller/FileDB.cpp

@@ -15,51 +15,49 @@
 
 #include "../node/Metrics.hpp"
 
-namespace ZeroTier
-{
+namespace ZeroTier {
 
-FileDB::FileDB(const char *path) :
-	DB(),
-	_path(path),
-	_networksPath(_path + ZT_PATH_SEPARATOR_S + "network"),
-	_tracePath(_path + ZT_PATH_SEPARATOR_S + "trace"),
-	_running(true)
+FileDB::FileDB(const char* path) : DB(), _path(path), _networksPath(_path + ZT_PATH_SEPARATOR_S + "network"), _tracePath(_path + ZT_PATH_SEPARATOR_S + "trace"), _running(true)
 {
 	OSUtils::mkdir(_path.c_str());
-	OSUtils::lockDownFile(_path.c_str(),true);
+	OSUtils::lockDownFile(_path.c_str(), true);
 	OSUtils::mkdir(_networksPath.c_str());
 	OSUtils::mkdir(_tracePath.c_str());
 
-	std::vector<std::string> networks(OSUtils::listDirectory(_networksPath.c_str(),false));
+	std::vector<std::string> networks(OSUtils::listDirectory(_networksPath.c_str(), false));
 	std::string buf;
-	for(auto n=networks.begin();n!=networks.end();++n) {
+	for (auto n = networks.begin(); n != networks.end(); ++n) {
 		buf.clear();
-		if ((n->length() == 21)&&(OSUtils::readFile((_networksPath + ZT_PATH_SEPARATOR_S + *n).c_str(),buf))) {
+		if ((n->length() == 21) && (OSUtils::readFile((_networksPath + ZT_PATH_SEPARATOR_S + *n).c_str(), buf))) {
 			try {
 				nlohmann::json network(OSUtils::jsonParse(buf));
 				const std::string nwids = network["id"];
 				if (nwids.length() == 16) {
 					nlohmann::json nullJson;
-					_networkChanged(nullJson,network,false);
+					_networkChanged(nullJson, network, false);
 					Metrics::network_count++;
 					std::string membersPath(_networksPath + ZT_PATH_SEPARATOR_S + nwids + ZT_PATH_SEPARATOR_S "member");
-					std::vector<std::string> members(OSUtils::listDirectory(membersPath.c_str(),false));
-					for(auto m=members.begin();m!=members.end();++m) {
+					std::vector<std::string> members(OSUtils::listDirectory(membersPath.c_str(), false));
+					for (auto m = members.begin(); m != members.end(); ++m) {
 						buf.clear();
-						if ((m->length() == 15)&&(OSUtils::readFile((membersPath + ZT_PATH_SEPARATOR_S + *m).c_str(),buf))) {
+						if ((m->length() == 15) && (OSUtils::readFile((membersPath + ZT_PATH_SEPARATOR_S + *m).c_str(), buf))) {
 							try {
 								nlohmann::json member(OSUtils::jsonParse(buf));
 								const std::string addrs = member["id"];
 								if (addrs.length() == 10) {
 									nlohmann::json nullJson2;
-									_memberChanged(nullJson2,member,false);
+									_memberChanged(nullJson2, member, false);
 									Metrics::member_count++;
 								}
-							} catch ( ... ) {}
+							}
+							catch (...) {
+							}
 						}
 					}
 				}
-			} catch ( ... ) {}
+			}
+			catch (...) {
+			}
 		}
 	}
 }
@@ -71,97 +69,104 @@ FileDB::~FileDB()
 		_running = false;
 		_online_l.unlock();
 		_onlineUpdateThread.join();
-	} catch ( ... ) {}
+	}
+	catch (...) {
+	}
 }
 
-bool FileDB::waitForReady() { return true; }
-bool FileDB::isReady() { return true; }
+bool FileDB::waitForReady()
+{
+	return true;
+}
+bool FileDB::isReady()
+{
+	return true;
+}
 
-bool FileDB::save(nlohmann::json &record,bool notifyListeners)
+bool FileDB::save(nlohmann::json& record, bool notifyListeners)
 {
-	char p1[4096],p2[4096],pb[4096];
+	char p1[4096], p2[4096], pb[4096];
 	bool modified = false;
 	try {
 		const std::string objtype = record["objtype"];
 		if (objtype == "network") {
-
-			const uint64_t nwid = OSUtils::jsonIntHex(record["id"],0ULL);
+			const uint64_t nwid = OSUtils::jsonIntHex(record["id"], 0ULL);
 			if (nwid) {
 				nlohmann::json old;
-				get(nwid,old);
-				if ((!old.is_object())||(!_compareRecords(old,record))) {
-					record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL;
-					OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%.16llx.json",_networksPath.c_str(),nwid);
-					if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) {
-						fprintf(stderr,"WARNING: controller unable to write to path: %s" ZT_EOL_S,p1);
+				get(nwid, old);
+				if ((! old.is_object()) || (! _compareRecords(old, record))) {
+					record["revision"] = OSUtils::jsonInt(record["revision"], 0ULL) + 1ULL;
+					OSUtils::ztsnprintf(p1, sizeof(p1), "%s" ZT_PATH_SEPARATOR_S "%.16llx.json", _networksPath.c_str(), nwid);
+					if (! OSUtils::writeFile(p1, OSUtils::jsonDump(record, -1))) {
+						fprintf(stderr, "WARNING: controller unable to write to path: %s" ZT_EOL_S, p1);
 					}
-					_networkChanged(old,record,notifyListeners);
+					_networkChanged(old, record, notifyListeners);
 					modified = true;
 				}
 			}
-
-		} else if (objtype == "member") {
-
-			const uint64_t id = OSUtils::jsonIntHex(record["id"],0ULL);
-			const uint64_t nwid = OSUtils::jsonIntHex(record["nwid"],0ULL);
-			if ((id)&&(nwid)) {
-				nlohmann::json network,old;
-				get(nwid,network,id,old);
-				if ((!old.is_object())||(!_compareRecords(old,record))) {
-					record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL;
-					OSUtils::ztsnprintf(pb,sizeof(pb),"%s" ZT_PATH_SEPARATOR_S "%.16llx" ZT_PATH_SEPARATOR_S "member",_networksPath.c_str(),(unsigned long long)nwid);
-					OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%.10llx.json",pb,(unsigned long long)id);
-					if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) {
-						OSUtils::ztsnprintf(p2,sizeof(p2),"%s" ZT_PATH_SEPARATOR_S "%.16llx",_networksPath.c_str(),(unsigned long long)nwid);
+		}
+		else if (objtype == "member") {
+			const uint64_t id = OSUtils::jsonIntHex(record["id"], 0ULL);
+			const uint64_t nwid = OSUtils::jsonIntHex(record["nwid"], 0ULL);
+			if ((id) && (nwid)) {
+				nlohmann::json network, old;
+				get(nwid, network, id, old);
+				if ((! old.is_object()) || (! _compareRecords(old, record))) {
+					record["revision"] = OSUtils::jsonInt(record["revision"], 0ULL) + 1ULL;
+					OSUtils::ztsnprintf(pb, sizeof(pb), "%s" ZT_PATH_SEPARATOR_S "%.16llx" ZT_PATH_SEPARATOR_S "member", _networksPath.c_str(), (unsigned long long)nwid);
+					OSUtils::ztsnprintf(p1, sizeof(p1), "%s" ZT_PATH_SEPARATOR_S "%.10llx.json", pb, (unsigned long long)id);
+					if (! OSUtils::writeFile(p1, OSUtils::jsonDump(record, -1))) {
+						OSUtils::ztsnprintf(p2, sizeof(p2), "%s" ZT_PATH_SEPARATOR_S "%.16llx", _networksPath.c_str(), (unsigned long long)nwid);
 						OSUtils::mkdir(p2);
 						OSUtils::mkdir(pb);
-						if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) {
-							fprintf(stderr,"WARNING: controller unable to write to path: %s" ZT_EOL_S,p1);
+						if (! OSUtils::writeFile(p1, OSUtils::jsonDump(record, -1))) {
+							fprintf(stderr, "WARNING: controller unable to write to path: %s" ZT_EOL_S, p1);
 						}
 					}
-					_memberChanged(old,record,notifyListeners);
+					_memberChanged(old, record, notifyListeners);
 					modified = true;
 				}
 			}
-
 		}
-	} catch ( ... ) {} // drop invalid records missing fields
+	}
+	catch (...) {
+	}	// drop invalid records missing fields
 	return modified;
 }
 
 void FileDB::eraseNetwork(const uint64_t networkId)
 {
-	nlohmann::json network,nullJson;
-	get(networkId,network);
+	nlohmann::json network, nullJson;
+	get(networkId, network);
 	char p[16384];
-	OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx.json",_networksPath.c_str(),networkId);
+	OSUtils::ztsnprintf(p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "%.16llx.json", _networksPath.c_str(), networkId);
 	OSUtils::rm(p);
-	OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx",_networksPath.c_str(),(unsigned long long)networkId);
+	OSUtils::ztsnprintf(p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "%.16llx", _networksPath.c_str(), (unsigned long long)networkId);
 	OSUtils::rmDashRf(p);
-	_networkChanged(network,nullJson,true);
+	_networkChanged(network, nullJson, true);
 	std::lock_guard<std::mutex> l(this->_online_l);
 	this->_online.erase(networkId);
 }
 
-void FileDB::eraseMember(const uint64_t networkId,const uint64_t memberId)
+void FileDB::eraseMember(const uint64_t networkId, const uint64_t memberId)
 {
-	nlohmann::json network,member,nullJson;
-	get(networkId,network,memberId,member);
+	nlohmann::json network, member, nullJson;
+	get(networkId, network, memberId, member);
 	char p[4096];
-	OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx" ZT_PATH_SEPARATOR_S "member" ZT_PATH_SEPARATOR_S "%.10llx.json",_networksPath.c_str(),networkId,memberId);
+	OSUtils::ztsnprintf(p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "%.16llx" ZT_PATH_SEPARATOR_S "member" ZT_PATH_SEPARATOR_S "%.10llx.json", _networksPath.c_str(), networkId, memberId);
 	OSUtils::rm(p);
-	_memberChanged(member,nullJson,true);
+	_memberChanged(member, nullJson, true);
 	std::lock_guard<std::mutex> l(this->_online_l);
 	this->_online[networkId].erase(memberId);
 }
 
-void FileDB::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress)
+void FileDB::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress)
 {
-	char mid[32],atmp[64];
-	OSUtils::ztsnprintf(mid,sizeof(mid),"%.10llx",(unsigned long long)memberId);
+	char mid[32], atmp[64];
+	OSUtils::ztsnprintf(mid, sizeof(mid), "%.10llx", (unsigned long long)memberId);
 	physicalAddress.toString(atmp);
 	std::lock_guard<std::mutex> l(this->_online_l);
 	this->_online[networkId][memberId][OSUtils::now()] = physicalAddress;
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier

+ 10 - 12
controller/FileDB.hpp

@@ -16,32 +16,30 @@
 
 #include "DB.hpp"
 
-namespace ZeroTier
-{
+namespace ZeroTier {
 
-class FileDB : public DB
-{
-public:
-	FileDB(const char *path);
+class FileDB : public DB {
+  public:
+	FileDB(const char* path);
 	virtual ~FileDB();
 
 	virtual bool waitForReady();
 	virtual bool isReady();
-	virtual bool save(nlohmann::json &record,bool notifyListeners);
+	virtual bool save(nlohmann::json& record, bool notifyListeners);
 	virtual void eraseNetwork(const uint64_t networkId);
-	virtual void eraseMember(const uint64_t networkId,const uint64_t memberId);
-	virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress);
+	virtual void eraseMember(const uint64_t networkId, const uint64_t memberId);
+	virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress);
 
-protected:
+  protected:
 	std::string _path;
 	std::string _networksPath;
 	std::string _tracePath;
 	std::thread _onlineUpdateThread;
-	std::map< uint64_t,std::map<uint64_t,std::map<int64_t,InetAddress> > > _online;
+	std::map<uint64_t, std::map<uint64_t, std::map<int64_t, InetAddress> > > _online;
 	std::mutex _online_l;
 	bool _running;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 192 - 160
controller/LFDB.cpp

@@ -13,51 +13,52 @@
 
 #include "LFDB.hpp"
 
-#include <thread>
+#include "../ext/cpp-httplib/httplib.h"
+#include "../osdep/OSUtils.hpp"
+
 #include <chrono>
 #include <iostream>
 #include <sstream>
+#include <thread>
 
-#include "../osdep/OSUtils.hpp"
-#include "../ext/cpp-httplib/httplib.h"
-
-namespace ZeroTier
-{
+namespace ZeroTier {
 
-LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,const char *lfOwnerPublic,const char *lfNodeHost,int lfNodePort,bool storeOnlineState) :
-	DB(),
-	_myId(myId),
-	_lfOwnerPrivate((lfOwnerPrivate) ? lfOwnerPrivate : ""),
-	_lfOwnerPublic((lfOwnerPublic) ? lfOwnerPublic : ""),
-	_lfNodeHost((lfNodeHost) ? lfNodeHost : "127.0.0.1"),
-	_lfNodePort(((lfNodePort > 0)&&(lfNodePort < 65536)) ? lfNodePort : 9980),
-	_running(true),
-	_ready(false),
-	_storeOnlineState(storeOnlineState)
+LFDB::LFDB(const Identity& myId, const char* path, const char* lfOwnerPrivate, const char* lfOwnerPublic, const char* lfNodeHost, int lfNodePort, bool storeOnlineState)
+	: DB()
+	, _myId(myId)
+	, _lfOwnerPrivate((lfOwnerPrivate) ? lfOwnerPrivate : "")
+	, _lfOwnerPublic((lfOwnerPublic) ? lfOwnerPublic : "")
+	, _lfNodeHost((lfNodeHost) ? lfNodeHost : "127.0.0.1")
+	, _lfNodePort(((lfNodePort > 0) && (lfNodePort < 65536)) ? lfNodePort : 9980)
+	, _running(true)
+	, _ready(false)
+	, _storeOnlineState(storeOnlineState)
 {
 	_syncThread = std::thread([this]() {
 		char controllerAddress[24];
 		const uint64_t controllerAddressInt = _myId.address().toInt();
 		_myId.address().toString(controllerAddress);
-		std::string networksSelectorName("com.zerotier.controller.lfdb:"); networksSelectorName.append(controllerAddress); networksSelectorName.append("/network");
+		std::string networksSelectorName("com.zerotier.controller.lfdb:");
+		networksSelectorName.append(controllerAddress);
+		networksSelectorName.append("/network");
 
 		// LF record masking key is the first 32 bytes of SHA512(controller private key) in hex,
 		// hiding record values from anything but the controller or someone who has its key.
 		uint8_t sha512pk[64];
 		_myId.sha512PrivateKey(sha512pk);
-		char maskingKey [128];
-		Utils::hex(sha512pk,32,maskingKey);
+		char maskingKey[128];
+		Utils::hex(sha512pk, 32, maskingKey);
 
-		httplib::Client htcli(_lfNodeHost.c_str(),_lfNodePort);
+		httplib::Client htcli(_lfNodeHost.c_str(), _lfNodePort);
 		int64_t timeRangeStart = 0;
 		while (_running.load()) {
 			{
 				std::lock_guard<std::mutex> sl(_state_l);
-				for(auto ns=_state.begin();ns!=_state.end();++ns) {
+				for (auto ns = _state.begin(); ns != _state.end(); ++ns) {
 					if (ns->second.dirty) {
 						nlohmann::json network;
-						if (get(ns->first,network)) {
-							nlohmann::json newrec,selector0;
+						if (get(ns->first, network)) {
+							nlohmann::json newrec, selector0;
 							selector0["Name"] = networksSelectorName;
 							selector0["Ordinal"] = ns->first;
 							newrec["Selectors"].push_back(selector0);
@@ -66,30 +67,34 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons
 							newrec["MaskingKey"] = maskingKey;
 							newrec["PulseIfUnchanged"] = true;
 							try {
-								auto resp = htcli.Post("/makerecord",newrec.dump(),"application/json");
+								auto resp = htcli.Post("/makerecord", newrec.dump(), "application/json");
 								if (resp) {
 									if (resp->status == 200) {
 										ns->second.dirty = false;
-										//printf("SET network %.16llx %s\n",ns->first,resp->body.c_str());
-									} else {
-										fprintf(stderr,"ERROR: LFDB: %d from node (create/update network): %s" ZT_EOL_S,resp->status,resp->body.c_str());
+										// printf("SET network %.16llx %s\n",ns->first,resp->body.c_str());
+									}
+									else {
+										fprintf(stderr, "ERROR: LFDB: %d from node (create/update network): %s" ZT_EOL_S, resp->status, resp->body.c_str());
 									}
-								} else {
-									fprintf(stderr,"ERROR: LFDB: node is offline" ZT_EOL_S);
 								}
-							} catch (std::exception &e) {
-								fprintf(stderr,"ERROR: LFDB: unexpected exception querying node (create/update network): %s" ZT_EOL_S,e.what());
-							} catch ( ... ) {
-								fprintf(stderr,"ERROR: LFDB: unexpected exception querying node (create/update network): unknown exception" ZT_EOL_S);
+								else {
+									fprintf(stderr, "ERROR: LFDB: node is offline" ZT_EOL_S);
+								}
+							}
+							catch (std::exception& e) {
+								fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (create/update network): %s" ZT_EOL_S, e.what());
+							}
+							catch (...) {
+								fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (create/update network): unknown exception" ZT_EOL_S);
 							}
 						}
 					}
 
-					for(auto ms=ns->second.members.begin();ms!=ns->second.members.end();++ms) {
-						if ((_storeOnlineState)&&(ms->second.lastOnlineDirty)&&(ms->second.lastOnlineAddress)) {
-							nlohmann::json newrec,selector0,selector1,selectors,ip;
-							char tmp[1024],tmp2[128];
-							OSUtils::ztsnprintf(tmp,sizeof(tmp),"com.zerotier.controller.lfdb:%s/network/%.16llx/online",controllerAddress,(unsigned long long)ns->first);
+					for (auto ms = ns->second.members.begin(); ms != ns->second.members.end(); ++ms) {
+						if ((_storeOnlineState) && (ms->second.lastOnlineDirty) && (ms->second.lastOnlineAddress)) {
+							nlohmann::json newrec, selector0, selector1, selectors, ip;
+							char tmp[1024], tmp2[128];
+							OSUtils::ztsnprintf(tmp, sizeof(tmp), "com.zerotier.controller.lfdb:%s/network/%.16llx/online", controllerAddress, (unsigned long long)ns->first);
 							ms->second.lastOnlineAddress.toIpString(tmp2);
 							selector0["Name"] = tmp;
 							selector0["Ordinal"] = ms->first;
@@ -98,18 +103,18 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons
 							selectors.push_back(selector0);
 							selectors.push_back(selector1);
 							newrec["Selectors"] = selectors;
-							const uint8_t *const rawip = (const uint8_t *)ms->second.lastOnlineAddress.rawIpData();
-							switch(ms->second.lastOnlineAddress.ss_family) {
+							const uint8_t* const rawip = (const uint8_t*)ms->second.lastOnlineAddress.rawIpData();
+							switch (ms->second.lastOnlineAddress.ss_family) {
 								case AF_INET:
-									for(int j=0;j<4;++j)
+									for (int j = 0; j < 4; ++j)
 										ip.push_back((unsigned int)rawip[j]);
 									break;
 								case AF_INET6:
-									for(int j=0;j<16;++j)
+									for (int j = 0; j < 16; ++j)
 										ip.push_back((unsigned int)rawip[j]);
 									break;
 								default:
-									ip = tmp2; // should never happen since only IP transport is currently supported
+									ip = tmp2;	 // should never happen since only IP transport is currently supported
 									break;
 							}
 							newrec["Value"] = ip;
@@ -118,28 +123,32 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons
 							newrec["Timestamp"] = ms->second.lastOnlineTime;
 							newrec["PulseIfUnchanged"] = true;
 							try {
-								auto resp = htcli.Post("/makerecord",newrec.dump(),"application/json");
+								auto resp = htcli.Post("/makerecord", newrec.dump(), "application/json");
 								if (resp) {
 									if (resp->status == 200) {
 										ms->second.lastOnlineDirty = false;
-										//printf("SET member online %.16llx %.10llx %s\n",ns->first,ms->first,resp->body.c_str());
-									} else {
-										fprintf(stderr,"ERROR: LFDB: %d from node (create/update member online status): %s" ZT_EOL_S,resp->status,resp->body.c_str());
+										// printf("SET member online %.16llx %.10llx %s\n",ns->first,ms->first,resp->body.c_str());
 									}
-								} else {
-									fprintf(stderr,"ERROR: LFDB: node is offline" ZT_EOL_S);
+									else {
+										fprintf(stderr, "ERROR: LFDB: %d from node (create/update member online status): %s" ZT_EOL_S, resp->status, resp->body.c_str());
+									}
+								}
+								else {
+									fprintf(stderr, "ERROR: LFDB: node is offline" ZT_EOL_S);
 								}
-							} catch (std::exception &e) {
-								fprintf(stderr,"ERROR: LFDB: unexpected exception querying node (create/update member online status): %s" ZT_EOL_S,e.what());
-							} catch ( ... ) {
-								fprintf(stderr,"ERROR: LFDB: unexpected exception querying node (create/update member online status): unknown exception" ZT_EOL_S);
+							}
+							catch (std::exception& e) {
+								fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (create/update member online status): %s" ZT_EOL_S, e.what());
+							}
+							catch (...) {
+								fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (create/update member online status): unknown exception" ZT_EOL_S);
 							}
 						}
 
 						if (ms->second.dirty) {
-							nlohmann::json network,member;
-							if (get(ns->first,network,ms->first,member)) {
-								nlohmann::json newrec,selector0,selector1,selectors;
+							nlohmann::json network, member;
+							if (get(ns->first, network, ms->first, member)) {
+								nlohmann::json newrec, selector0, selector1, selectors;
 								selector0["Name"] = networksSelectorName;
 								selector0["Ordinal"] = ns->first;
 								selector1["Name"] = "member";
@@ -152,21 +161,25 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons
 								newrec["MaskingKey"] = maskingKey;
 								newrec["PulseIfUnchanged"] = true;
 								try {
-									auto resp = htcli.Post("/makerecord",newrec.dump(),"application/json");
+									auto resp = htcli.Post("/makerecord", newrec.dump(), "application/json");
 									if (resp) {
 										if (resp->status == 200) {
 											ms->second.dirty = false;
-											//printf("SET member %.16llx %.10llx %s\n",ns->first,ms->first,resp->body.c_str());
-										} else {
-											fprintf(stderr,"ERROR: LFDB: %d from node (create/update member): %s" ZT_EOL_S,resp->status,resp->body.c_str());
+											// printf("SET member %.16llx %.10llx %s\n",ns->first,ms->first,resp->body.c_str());
 										}
-									} else {
-										fprintf(stderr,"ERROR: LFDB: node is offline" ZT_EOL_S);
+										else {
+											fprintf(stderr, "ERROR: LFDB: %d from node (create/update member): %s" ZT_EOL_S, resp->status, resp->body.c_str());
+										}
+									}
+									else {
+										fprintf(stderr, "ERROR: LFDB: node is offline" ZT_EOL_S);
 									}
-								} catch (std::exception &e) {
-									fprintf(stderr,"ERROR: LFDB: unexpected exception querying node (create/update member): %s" ZT_EOL_S,e.what());
-								} catch ( ... ) {
-									fprintf(stderr,"ERROR: LFDB: unexpected exception querying node (create/update member): unknown exception" ZT_EOL_S);
+								}
+								catch (std::exception& e) {
+									fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (create/update member): %s" ZT_EOL_S, e.what());
+								}
+								catch (...) {
+									fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (create/update member): unknown exception" ZT_EOL_S);
 								}
 							}
 						}
@@ -176,143 +189,161 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons
 
 			try {
 				std::ostringstream query;
-				query <<
-					"{"
-						"\"Ranges\":[{"
-							"\"Name\":\"" << networksSelectorName << "\","
-							"\"Range\":[0,18446744073709551615]"
-						"}],"
-						"\"TimeRange\":[" << timeRangeStart << ",9223372036854775807],"
-						"\"MaskingKey\":\"" << maskingKey << "\","
-						"\"Owners\":[\"" << _lfOwnerPublic << "\"]"
-					"}";
-				auto resp = htcli.Post("/query",query.str(),"application/json");
+				query << "{"
+						 "\"Ranges\":[{"
+						 "\"Name\":\""
+					  << networksSelectorName
+					  << "\","
+						 "\"Range\":[0,18446744073709551615]"
+						 "}],"
+						 "\"TimeRange\":["
+					  << timeRangeStart
+					  << ",9223372036854775807],"
+						 "\"MaskingKey\":\""
+					  << maskingKey
+					  << "\","
+						 "\"Owners\":[\""
+					  << _lfOwnerPublic
+					  << "\"]"
+						 "}";
+				auto resp = htcli.Post("/query", query.str(), "application/json");
 				if (resp) {
 					if (resp->status == 200) {
 						nlohmann::json results(OSUtils::jsonParse(resp->body));
-						if ((results.is_array())&&(!results.empty())) {
-							for(std::size_t ri=0;ri<results.size();++ri) {
-								nlohmann::json &rset = results[ri];
-								if ((rset.is_array())&&(!rset.empty())) {
-
-									nlohmann::json &result = rset[0];
+						if ((results.is_array()) && (! results.empty())) {
+							for (std::size_t ri = 0; ri < results.size(); ++ri) {
+								nlohmann::json& rset = results[ri];
+								if ((rset.is_array()) && (! rset.empty())) {
+									nlohmann::json& result = rset[0];
 									if (result.is_object()) {
-										nlohmann::json &record = result["Record"];
+										nlohmann::json& record = result["Record"];
 										if (record.is_object()) {
 											const std::string recordValue = result["Value"];
-											//printf("GET network %s\n",recordValue.c_str());
+											// printf("GET network %s\n",recordValue.c_str());
 											nlohmann::json network(OSUtils::jsonParse(recordValue));
 											if (network.is_object()) {
 												const std::string idstr = network["id"];
 												const uint64_t id = Utils::hexStrToU64(idstr.c_str());
-												if ((id >> 24) == controllerAddressInt) { // sanity check
+												if ((id >> 24) == controllerAddressInt) {	// sanity check
 
 													nlohmann::json oldNetwork;
-													if ((timeRangeStart > 0)&&(get(id,oldNetwork))) {
+													if ((timeRangeStart > 0) && (get(id, oldNetwork))) {
 														const uint64_t revision = network["revision"];
 														const uint64_t prevRevision = oldNetwork["revision"];
 														if (prevRevision < revision) {
-															_networkChanged(oldNetwork,network,timeRangeStart > 0);
+															_networkChanged(oldNetwork, network, timeRangeStart > 0);
 														}
-													} else {
+													}
+													else {
 														nlohmann::json nullJson;
-														_networkChanged(nullJson,network,timeRangeStart > 0);
+														_networkChanged(nullJson, network, timeRangeStart > 0);
 													}
-
 												}
 											}
 										}
 									}
-
 								}
 							}
 						}
-					} else {
-						fprintf(stderr,"ERROR: LFDB: %d from node (check for network updates): %s" ZT_EOL_S,resp->status,resp->body.c_str());
 					}
-				} else {
-					fprintf(stderr,"ERROR: LFDB: node is offline" ZT_EOL_S);
+					else {
+						fprintf(stderr, "ERROR: LFDB: %d from node (check for network updates): %s" ZT_EOL_S, resp->status, resp->body.c_str());
+					}
+				}
+				else {
+					fprintf(stderr, "ERROR: LFDB: node is offline" ZT_EOL_S);
 				}
-			} catch (std::exception &e) {
-				fprintf(stderr,"ERROR: LFDB: unexpected exception querying node (check for network updates): %s" ZT_EOL_S,e.what());
-			} catch ( ... ) {
-				fprintf(stderr,"ERROR: LFDB: unexpected exception querying node (check for network updates): unknown exception" ZT_EOL_S);
+			}
+			catch (std::exception& e) {
+				fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (check for network updates): %s" ZT_EOL_S, e.what());
+			}
+			catch (...) {
+				fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (check for network updates): unknown exception" ZT_EOL_S);
 			}
 
 			try {
 				std::ostringstream query;
-				query <<
-					"{"
-						"\"Ranges\":[{"
-							"\"Name\":\"" << networksSelectorName << "\","
-							"\"Range\":[0,18446744073709551615]"
-						"},{"
-							"\"Name\":\"member\","
-							"\"Range\":[0,18446744073709551615]"
-						"}],"
-						"\"TimeRange\":[" << timeRangeStart << ",9223372036854775807],"
-						"\"MaskingKey\":\"" << maskingKey << "\","
-						"\"Owners\":[\"" << _lfOwnerPublic << "\"]"
-					"}";
-				auto resp = htcli.Post("/query",query.str(),"application/json");
+				query << "{"
+						 "\"Ranges\":[{"
+						 "\"Name\":\""
+					  << networksSelectorName
+					  << "\","
+						 "\"Range\":[0,18446744073709551615]"
+						 "},{"
+						 "\"Name\":\"member\","
+						 "\"Range\":[0,18446744073709551615]"
+						 "}],"
+						 "\"TimeRange\":["
+					  << timeRangeStart
+					  << ",9223372036854775807],"
+						 "\"MaskingKey\":\""
+					  << maskingKey
+					  << "\","
+						 "\"Owners\":[\""
+					  << _lfOwnerPublic
+					  << "\"]"
+						 "}";
+				auto resp = htcli.Post("/query", query.str(), "application/json");
 				if (resp) {
 					if (resp->status == 200) {
 						nlohmann::json results(OSUtils::jsonParse(resp->body));
-						if ((results.is_array())&&(!results.empty())) {
-							for(std::size_t ri=0;ri<results.size();++ri) {
-								nlohmann::json &rset = results[ri];
-								if ((rset.is_array())&&(!rset.empty())) {
-
-									nlohmann::json &result = rset[0];
+						if ((results.is_array()) && (! results.empty())) {
+							for (std::size_t ri = 0; ri < results.size(); ++ri) {
+								nlohmann::json& rset = results[ri];
+								if ((rset.is_array()) && (! rset.empty())) {
+									nlohmann::json& result = rset[0];
 									if (result.is_object()) {
-										nlohmann::json &record = result["Record"];
+										nlohmann::json& record = result["Record"];
 										if (record.is_object()) {
 											const std::string recordValue = result["Value"];
-											//printf("GET member %s\n",recordValue.c_str());
+											// printf("GET member %s\n",recordValue.c_str());
 											nlohmann::json member(OSUtils::jsonParse(recordValue));
 											if (member.is_object()) {
 												const std::string nwidstr = member["nwid"];
 												const std::string idstr = member["id"];
 												const uint64_t nwid = Utils::hexStrToU64(nwidstr.c_str());
 												const uint64_t id = Utils::hexStrToU64(idstr.c_str());
-												if ((id)&&((nwid >> 24) == controllerAddressInt)) { // sanity check
+												if ((id) && ((nwid >> 24) == controllerAddressInt)) {	// sanity check
 
-													nlohmann::json network,oldMember;
-													if ((timeRangeStart > 0)&&(get(nwid,network,id,oldMember))) {
+													nlohmann::json network, oldMember;
+													if ((timeRangeStart > 0) && (get(nwid, network, id, oldMember))) {
 														const uint64_t revision = member["revision"];
 														const uint64_t prevRevision = oldMember["revision"];
 														if (prevRevision < revision)
-															_memberChanged(oldMember,member,timeRangeStart > 0);
-													} else if (hasNetwork(nwid)) {
+															_memberChanged(oldMember, member, timeRangeStart > 0);
+													}
+													else if (hasNetwork(nwid)) {
 														nlohmann::json nullJson;
-														_memberChanged(nullJson,member,timeRangeStart > 0);
+														_memberChanged(nullJson, member, timeRangeStart > 0);
 													}
-
 												}
 											}
 										}
 									}
-
 								}
 							}
 						}
-					} else {
-						fprintf(stderr,"ERROR: LFDB: %d from node (check for member updates): %s" ZT_EOL_S,resp->status,resp->body.c_str());
 					}
-				} else {
-					fprintf(stderr,"ERROR: LFDB: node is offline" ZT_EOL_S);
+					else {
+						fprintf(stderr, "ERROR: LFDB: %d from node (check for member updates): %s" ZT_EOL_S, resp->status, resp->body.c_str());
+					}
 				}
-			} catch (std::exception &e) {
-				fprintf(stderr,"ERROR: LFDB: unexpected exception querying node (check for member updates): %s" ZT_EOL_S,e.what());
-			} catch ( ... ) {
-				fprintf(stderr,"ERROR: LFDB: unexpected exception querying node (check for member updates): unknown exception" ZT_EOL_S);
+				else {
+					fprintf(stderr, "ERROR: LFDB: node is offline" ZT_EOL_S);
+				}
+			}
+			catch (std::exception& e) {
+				fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (check for member updates): %s" ZT_EOL_S, e.what());
+			}
+			catch (...) {
+				fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (check for member updates): unknown exception" ZT_EOL_S);
 			}
 
-			timeRangeStart = time(nullptr) - 120; // start next query 2m before now to avoid losing updates
+			timeRangeStart = time(nullptr) - 120;	// start next query 2m before now to avoid losing updates
 			_ready.store(true);
 
-			for(int k=0;k<4;++k) { // 2s delay between queries for remotely modified networks or members
-				if (!_running.load())
+			for (int k = 0; k < 4; ++k) {	// 2s delay between queries for remotely modified networks or members
+				if (! _running.load())
 					return;
 				std::this_thread::sleep_for(std::chrono::milliseconds(500));
 			}
@@ -328,7 +359,7 @@ LFDB::~LFDB()
 
 bool LFDB::waitForReady()
 {
-	while (!_ready.load()) {
+	while (! _ready.load()) {
 		std::this_thread::sleep_for(std::chrono::milliseconds(500));
 	}
 	return true;
@@ -339,18 +370,18 @@ bool LFDB::isReady()
 	return (_ready.load());
 }
 
-bool LFDB::save(nlohmann::json &record,bool notifyListeners)
+bool LFDB::save(nlohmann::json& record, bool notifyListeners)
 {
 	bool modified = false;
 	const std::string objtype = record["objtype"];
 	if (objtype == "network") {
-		const uint64_t nwid = OSUtils::jsonIntHex(record["id"],0ULL);
+		const uint64_t nwid = OSUtils::jsonIntHex(record["id"], 0ULL);
 		if (nwid) {
 			nlohmann::json old;
-			get(nwid,old);
-			if ((!old.is_object())||(!_compareRecords(old,record))) {
-				record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL;
-				_networkChanged(old,record,notifyListeners);
+			get(nwid, old);
+			if ((! old.is_object()) || (! _compareRecords(old, record))) {
+				record["revision"] = OSUtils::jsonInt(record["revision"], 0ULL) + 1ULL;
+				_networkChanged(old, record, notifyListeners);
 				{
 					std::lock_guard<std::mutex> l(_state_l);
 					_state[nwid].dirty = true;
@@ -358,15 +389,16 @@ bool LFDB::save(nlohmann::json &record,bool notifyListeners)
 				modified = true;
 			}
 		}
-	} else if (objtype == "member") {
-		const uint64_t nwid = OSUtils::jsonIntHex(record["nwid"],0ULL);
-		const uint64_t id = OSUtils::jsonIntHex(record["id"],0ULL);
-		if ((id)&&(nwid)) {
-			nlohmann::json network,old;
-			get(nwid,network,id,old);
-			if ((!old.is_object())||(!_compareRecords(old,record))) {
-				record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL;
-				_memberChanged(old,record,notifyListeners);
+	}
+	else if (objtype == "member") {
+		const uint64_t nwid = OSUtils::jsonIntHex(record["nwid"], 0ULL);
+		const uint64_t id = OSUtils::jsonIntHex(record["id"], 0ULL);
+		if ((id) && (nwid)) {
+			nlohmann::json network, old;
+			get(nwid, network, id, old);
+			if ((! old.is_object()) || (! _compareRecords(old, record))) {
+				record["revision"] = OSUtils::jsonInt(record["revision"], 0ULL) + 1ULL;
+				_memberChanged(old, record, notifyListeners);
 				{
 					std::lock_guard<std::mutex> l(_state_l);
 					_state[nwid].members[id].dirty = true;
@@ -383,12 +415,12 @@ void LFDB::eraseNetwork(const uint64_t networkId)
 	// TODO
 }
 
-void LFDB::eraseMember(const uint64_t networkId,const uint64_t memberId)
+void LFDB::eraseMember(const uint64_t networkId, const uint64_t memberId)
 {
 	// TODO
 }
 
-void LFDB::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress)
+void LFDB::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress)
 {
 	std::lock_guard<std::mutex> l(_state_l);
 	auto nw = _state.find(networkId);
@@ -403,4 +435,4 @@ void LFDB::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const I
 	}
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier

+ 20 - 25
controller/LFDB.hpp

@@ -16,19 +16,18 @@
 
 #include "DB.hpp"
 
+#include <atomic>
 #include <mutex>
 #include <string>
 #include <unordered_map>
-#include <atomic>
 
 namespace ZeroTier {
 
 /**
  * DB implementation for controller that stores data in LF
  */
-class LFDB : public DB
-{
-public:
+class LFDB : public DB {
+  public:
 	/**
 	 * @param myId This controller's identity
 	 * @param path Base path for ZeroTier node itself
@@ -38,44 +37,40 @@ public:
 	 * @param lfNodePort LF node http (not https) port
 	 * @param storeOnlineState If true, store online/offline state and IP info in LF (a lot of data, only for private networks!)
 	 */
-	LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,const char *lfOwnerPublic,const char *lfNodeHost,int lfNodePort,bool storeOnlineState);
+	LFDB(const Identity& myId, const char* path, const char* lfOwnerPrivate, const char* lfOwnerPublic, const char* lfNodeHost, int lfNodePort, bool storeOnlineState);
 	virtual ~LFDB();
 
 	virtual bool waitForReady();
 	virtual bool isReady();
-	virtual bool save(nlohmann::json &record,bool notifyListeners);
+	virtual bool save(nlohmann::json& record, bool notifyListeners);
 	virtual void eraseNetwork(const uint64_t networkId);
-	virtual void eraseMember(const uint64_t networkId,const uint64_t memberId);
-	virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress);
+	virtual void eraseMember(const uint64_t networkId, const uint64_t memberId);
+	virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress);
 
-protected:
+  protected:
 	const Identity _myId;
 
-	std::string _lfOwnerPrivate,_lfOwnerPublic;
+	std::string _lfOwnerPrivate, _lfOwnerPublic;
 	std::string _lfNodeHost;
 	int _lfNodePort;
 
-	struct _MemberState
-	{
-		_MemberState() :
-			lastOnlineAddress(),
-			lastOnlineTime(0),
-			dirty(false),
-			lastOnlineDirty(false) {}
+	struct _MemberState {
+		_MemberState() : lastOnlineAddress(), lastOnlineTime(0), dirty(false), lastOnlineDirty(false)
+		{
+		}
 		InetAddress lastOnlineAddress;
 		int64_t lastOnlineTime;
 		bool dirty;
 		bool lastOnlineDirty;
 	};
-	struct _NetworkState
-	{
-		_NetworkState() :
-			members(),
-			dirty(false) {}
-		std::unordered_map<uint64_t,_MemberState> members;
+	struct _NetworkState {
+		_NetworkState() : members(), dirty(false)
+		{
+		}
+		std::unordered_map<uint64_t, _MemberState> members;
 		bool dirty;
 	};
-	std::unordered_map<uint64_t,_NetworkState> _state;
+	std::unordered_map<uint64_t, _NetworkState> _state;
 	std::mutex _state_l;
 
 	std::atomic_bool _running;
@@ -84,6 +79,6 @@ protected:
 	bool _storeOnlineState;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

File diff suppressed because it is too large
+ 335 - 258
controller/PostgreSQL.cpp


+ 58 - 55
controller/PostgreSQL.hpp

@@ -20,78 +20,81 @@
 
 #define ZT_CENTRAL_CONTROLLER_COMMIT_THREADS 4
 
+#include "../node/Metrics.hpp"
 #include "ConnectionPool.hpp"
-#include <pqxx/pqxx>
 
 #include <memory>
+#include <pqxx/pqxx>
 #include <redis++/redis++.h>
 
-#include "../node/Metrics.hpp"
-
 extern "C" {
 typedef struct pg_conn PGconn;
 }
 
 namespace smeeclient {
-	struct SmeeClient;
+struct SmeeClient;
 }
 
 namespace ZeroTier {
 
 struct RedisConfig;
 
-
 class PostgresConnection : public Connection {
-public:
-	virtual ~PostgresConnection() {
+  public:
+	virtual ~PostgresConnection()
+	{
 	}
 
 	std::shared_ptr<pqxx::connection> c;
 	int a;
 };
 
-
 class PostgresConnFactory : public ConnectionFactory {
-public:
-	PostgresConnFactory(std::string &connString) 
-		: m_connString(connString)
+  public:
+	PostgresConnFactory(std::string& connString) : m_connString(connString)
 	{
 	}
 
-	virtual std::shared_ptr<Connection> create() {
+	virtual std::shared_ptr<Connection> create()
+	{
 		Metrics::conn_counter++;
 		auto c = std::shared_ptr<PostgresConnection>(new PostgresConnection());
 		c->c = std::make_shared<pqxx::connection>(m_connString);
 		return std::static_pointer_cast<Connection>(c);
 	}
-private:
+
+  private:
 	std::string m_connString;
 };
 
 class PostgreSQL;
 
 class MemberNotificationReceiver : public pqxx::notification_receiver {
-public: 
-	MemberNotificationReceiver(PostgreSQL *p, pqxx::connection &c, const std::string &channel);
-	virtual ~MemberNotificationReceiver() {
+  public:
+	MemberNotificationReceiver(PostgreSQL* p, pqxx::connection& c, const std::string& channel);
+	virtual ~MemberNotificationReceiver()
+	{
 		fprintf(stderr, "MemberNotificationReceiver destroyed\n");
 	}
 
-	virtual void operator() (const std::string &payload, int backendPid);
-private:
-	PostgreSQL *_psql;
+	virtual void operator()(const std::string& payload, int backendPid);
+
+  private:
+	PostgreSQL* _psql;
 };
 
 class NetworkNotificationReceiver : public pqxx::notification_receiver {
-public:
-	NetworkNotificationReceiver(PostgreSQL *p, pqxx::connection &c, const std::string &channel);
-	virtual ~NetworkNotificationReceiver() {
+  public:
+	NetworkNotificationReceiver(PostgreSQL* p, pqxx::connection& c, const std::string& channel);
+	virtual ~NetworkNotificationReceiver()
+	{
 		fprintf(stderr, "NetworkNotificationReceiver destroyed\n");
 	};
 
-	virtual void operator() (const std::string &payload, int packend_pid);
-private:
-	PostgreSQL *_psql;
+	virtual void operator()(const std::string& payload, int packend_pid);
+
+  private:
+	PostgreSQL* _psql;
 };
 
 /**
@@ -100,36 +103,40 @@ private:
  * This is for use with ZeroTier Central.  Others are free to build and use it
  * but be aware that we might change it at any time.
  */
-class PostgreSQL : public DB
-{
+class PostgreSQL : public DB {
 	friend class MemberNotificationReceiver;
 	friend class NetworkNotificationReceiver;
-public:
-	PostgreSQL(const Identity &myId, const char *path, int listenPort, RedisConfig *rc);
+
+  public:
+	PostgreSQL(const Identity& myId, const char* path, int listenPort, RedisConfig* rc);
 	virtual ~PostgreSQL();
 
 	virtual bool waitForReady();
 	virtual bool isReady();
-	virtual bool save(nlohmann::json &record,bool notifyListeners);
+	virtual bool save(nlohmann::json& record, bool notifyListeners);
 	virtual void eraseNetwork(const uint64_t networkId);
 	virtual void eraseMember(const uint64_t networkId, const uint64_t memberId);
-	virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress &physicalAddress);
-	virtual AuthInfo getSSOAuthInfo(const nlohmann::json &member, const std::string &redirectURL);
-
-protected:
-	struct _PairHasher
-	{
-		inline std::size_t operator()(const std::pair<uint64_t,uint64_t> &p) const { return (std::size_t)(p.first ^ p.second); }
+	virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress);
+	virtual AuthInfo getSSOAuthInfo(const nlohmann::json& member, const std::string& redirectURL);
+
+  protected:
+	struct _PairHasher {
+		inline std::size_t operator()(const std::pair<uint64_t, uint64_t>& p) const
+		{
+			return (std::size_t)(p.first ^ p.second);
+		}
 	};
-	virtual void _memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool notifyListeners) {
+	virtual void _memberChanged(nlohmann::json& old, nlohmann::json& memberConfig, bool notifyListeners)
+	{
 		DB::_memberChanged(old, memberConfig, notifyListeners);
 	}
 
-	virtual void _networkChanged(nlohmann::json &old,nlohmann::json &networkConfig,bool notifyListeners) {
+	virtual void _networkChanged(nlohmann::json& old, nlohmann::json& networkConfig, bool notifyListeners)
+	{
 		DB::_networkChanged(old, networkConfig, notifyListeners);
 	}
 
-private:
+  private:
 	void initializeNetworks();
 	void initializeMembers();
 	void heartbeat();
@@ -145,16 +152,12 @@ private:
 	void onlineNotificationThread();
 	void onlineNotification_Postgres();
 	void onlineNotification_Redis();
-	uint64_t _doRedisUpdate(sw::redis::Transaction &tx, std::string &controllerId,
-		std::unordered_map< std::pair<uint64_t,uint64_t>,std::pair<int64_t,InetAddress>,_PairHasher > &lastOnline);
+	uint64_t _doRedisUpdate(sw::redis::Transaction& tx, std::string& controllerId, std::unordered_map<std::pair<uint64_t, uint64_t>, std::pair<int64_t, InetAddress>, _PairHasher>& lastOnline);
 
 	void configureSmee();
-	void notifyNewMember(const std::string &networkID, const std::string &memberID);
+	void notifyNewMember(const std::string& networkID, const std::string& memberID);
 
-	enum OverrideMode {
-		ALLOW_PGBOUNCER_OVERRIDE = 0,
-		NO_OVERRIDE = 1
-	};
+	enum OverrideMode { ALLOW_PGBOUNCER_OVERRIDE = 0, NO_OVERRIDE = 1 };
 
 	std::shared_ptr<ConnectionPool<PostgresConnection> > _pool;
 
@@ -163,7 +166,7 @@ private:
 	std::string _myAddressStr;
 	std::string _connString;
 
-	BlockingQueue< std::pair<nlohmann::json,bool> > _commitQueue;
+	BlockingQueue<std::pair<nlohmann::json, bool> > _commitQueue;
 
 	std::thread _heartbeatThread;
 	std::thread _membersDbWatcher;
@@ -171,7 +174,7 @@ private:
 	std::thread _commitThread[ZT_CENTRAL_CONTROLLER_COMMIT_THREADS];
 	std::thread _onlineNotificationThread;
 
-	std::unordered_map< std::pair<uint64_t,uint64_t>,std::pair<int64_t,InetAddress>,_PairHasher > _lastOnline;
+	std::unordered_map<std::pair<uint64_t, uint64_t>, std::pair<int64_t, InetAddress>, _PairHasher> _lastOnline;
 
 	mutable std::mutex _lastOnline_l;
 	mutable std::mutex _readyLock;
@@ -181,16 +184,16 @@ private:
 	int _listenPort;
 	uint8_t _ssoPsk[48];
 
-	RedisConfig *_rc;
+	RedisConfig* _rc;
 	std::shared_ptr<sw::redis::Redis> _redis;
 	std::shared_ptr<sw::redis::RedisCluster> _cluster;
-    bool _redisMemberStatus;
+	bool _redisMemberStatus;
 
-	smeeclient::SmeeClient *_smee;
+	smeeclient::SmeeClient* _smee;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
-#endif // ZT_CONTROLLER_LIBPQ_HPP
+#endif	 // ZT_CONTROLLER_LIBPQ_HPP
 
-#endif // ZT_CONTROLLER_USE_LIBPQ
+#endif	 // ZT_CONTROLLER_USE_LIBPQ

+ 5 - 5
controller/Redis.hpp

@@ -5,11 +5,11 @@
 
 namespace ZeroTier {
 struct RedisConfig {
-    std::string hostname;
-    int port;
-    std::string password;
-    bool clusterMode;
+	std::string hostname;
+	int port;
+	std::string password;
+	bool clusterMode;
 };
-}
+}	// namespace ZeroTier
 
 #endif

+ 164 - 134
node/AES.cpp

@@ -11,9 +11,10 @@
  */
 /****/
 
-#include "Constants.hpp"
 #include "AES.hpp"
 
+#include "Constants.hpp"
+
 #ifdef __GNUC__
 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
 #endif
@@ -31,40 +32,40 @@ namespace ZeroTier {
 
 namespace {
 
-#define s_bmul32(N, x, y, rh, rl) \
-	uint32_t x0t_##N = (x) & 0x11111111U; \
-	uint32_t x1t_##N = (x) & 0x22222222U; \
-	uint32_t x2t_##N = (x) & 0x44444444U; \
-	uint32_t x3t_##N = (x) & 0x88888888U; \
-	uint32_t y0t_##N = (y) & 0x11111111U; \
-	uint32_t y1t_##N = (y) & 0x22222222U; \
-	uint32_t y2t_##N = (y) & 0x44444444U; \
-	uint32_t y3t_##N = (y) & 0x88888888U; \
-	uint64_t z0t_##N = (((uint64_t)x0t_##N * y0t_##N) ^ ((uint64_t)x1t_##N * y3t_##N) ^ ((uint64_t)x2t_##N * y2t_##N) ^ ((uint64_t)x3t_##N * y1t_##N)) & 0x1111111111111111ULL; \
-	uint64_t z1t_##N = (((uint64_t)x0t_##N * y1t_##N) ^ ((uint64_t)x1t_##N * y0t_##N) ^ ((uint64_t)x2t_##N * y3t_##N) ^ ((uint64_t)x3t_##N * y2t_##N)) & 0x2222222222222222ULL; \
-	uint64_t z2t_##N = (((uint64_t)x0t_##N * y2t_##N) ^ ((uint64_t)x1t_##N * y1t_##N) ^ ((uint64_t)x2t_##N * y0t_##N) ^ ((uint64_t)x3t_##N * y3t_##N)) & 0x4444444444444444ULL; \
-	z0t_##N |= z1t_##N; \
-	z2t_##N |= z0t_##N; \
-	uint64_t zt_##N = z2t_##N | ((((uint64_t)x0t_##N * y3t_##N) ^ ((uint64_t)x1t_##N * y2t_##N) ^ ((uint64_t)x2t_##N * y1t_##N) ^ ((uint64_t)x3t_##N * y0t_##N)) & 0x8888888888888888ULL); \
-	(rh) = (uint32_t)(zt_##N >> 32U); \
+#define s_bmul32(N, x, y, rh, rl)                                                                                                                                                                                                              \
+	uint32_t x0t_##N = (x) & 0x11111111U;                                                                                                                                                                                                      \
+	uint32_t x1t_##N = (x) & 0x22222222U;                                                                                                                                                                                                      \
+	uint32_t x2t_##N = (x) & 0x44444444U;                                                                                                                                                                                                      \
+	uint32_t x3t_##N = (x) & 0x88888888U;                                                                                                                                                                                                      \
+	uint32_t y0t_##N = (y) & 0x11111111U;                                                                                                                                                                                                      \
+	uint32_t y1t_##N = (y) & 0x22222222U;                                                                                                                                                                                                      \
+	uint32_t y2t_##N = (y) & 0x44444444U;                                                                                                                                                                                                      \
+	uint32_t y3t_##N = (y) & 0x88888888U;                                                                                                                                                                                                      \
+	uint64_t z0t_##N = (((uint64_t)x0t_##N * y0t_##N) ^ ((uint64_t)x1t_##N * y3t_##N) ^ ((uint64_t)x2t_##N * y2t_##N) ^ ((uint64_t)x3t_##N * y1t_##N)) & 0x1111111111111111ULL;                                                                \
+	uint64_t z1t_##N = (((uint64_t)x0t_##N * y1t_##N) ^ ((uint64_t)x1t_##N * y0t_##N) ^ ((uint64_t)x2t_##N * y3t_##N) ^ ((uint64_t)x3t_##N * y2t_##N)) & 0x2222222222222222ULL;                                                                \
+	uint64_t z2t_##N = (((uint64_t)x0t_##N * y2t_##N) ^ ((uint64_t)x1t_##N * y1t_##N) ^ ((uint64_t)x2t_##N * y0t_##N) ^ ((uint64_t)x3t_##N * y3t_##N)) & 0x4444444444444444ULL;                                                                \
+	z0t_##N |= z1t_##N;                                                                                                                                                                                                                        \
+	z2t_##N |= z0t_##N;                                                                                                                                                                                                                        \
+	uint64_t zt_##N = z2t_##N | ((((uint64_t)x0t_##N * y3t_##N) ^ ((uint64_t)x1t_##N * y2t_##N) ^ ((uint64_t)x2t_##N * y1t_##N) ^ ((uint64_t)x3t_##N * y0t_##N)) & 0x8888888888888888ULL);                                                     \
+	(rh) = (uint32_t)(zt_##N >> 32U);                                                                                                                                                                                                          \
 	(rl) = (uint32_t)zt_##N;
 
-void s_gfmul(const uint64_t hh, const uint64_t hl, uint64_t &y0, uint64_t &y1) noexcept
+void s_gfmul(const uint64_t hh, const uint64_t hl, uint64_t& y0, uint64_t& y1) noexcept
 {
 	uint32_t hhh = (uint32_t)(hh >> 32U);
 	uint32_t hhl = (uint32_t)hh;
 	uint32_t hlh = (uint32_t)(hl >> 32U);
 	uint32_t hll = (uint32_t)hl;
-	uint32_t hhXlh = hhh ^hlh;
-	uint32_t hhXll = hhl ^hll;
+	uint32_t hhXlh = hhh ^ hlh;
+	uint32_t hhXll = hhl ^ hll;
 	uint64_t yl = Utils::ntoh(y0);
 	uint64_t yh = Utils::ntoh(y1);
 	uint32_t cilh = (uint32_t)(yh >> 32U);
 	uint32_t cill = (uint32_t)yh;
 	uint32_t cihh = (uint32_t)(yl >> 32U);
 	uint32_t cihl = (uint32_t)yl;
-	uint32_t cihXlh = cihh ^cilh;
-	uint32_t cihXll = cihl ^cill;
+	uint32_t cihXlh = cihh ^ cilh;
+	uint32_t cihXll = cihl ^ cill;
 	uint32_t aah, aal, abh, abl, ach, acl;
 	s_bmul32(M0, cihh, hhh, aah, aal);
 	s_bmul32(M1, cihl, hhl, abh, abl);
@@ -94,8 +95,8 @@ void s_gfmul(const uint64_t hh, const uint64_t hl, uint64_t &y0, uint64_t &y1) n
 	cbh ^= bbh ^ abh;
 	cbl ^= bbl ^ abl;
 	uint64_t zhh = ((uint64_t)aah << 32U) | aal;
-	uint64_t zhl = (((uint64_t)abh << 32U) | abl) ^(((uint64_t)cah << 32U) | cal);
-	uint64_t zlh = (((uint64_t)bah << 32U) | bal) ^(((uint64_t)cbh << 32U) | cbl);
+	uint64_t zhl = (((uint64_t)abh << 32U) | abl) ^ (((uint64_t)cah << 32U) | cal);
+	uint64_t zlh = (((uint64_t)bah << 32U) | bal) ^ (((uint64_t)cbh << 32U) | cbl);
 	uint64_t zll = ((uint64_t)bbh << 32U) | bbl;
 	zhh = zhh << 1U | zhl >> 63U;
 	zhl = zhl << 1U | zlh >> 63U;
@@ -108,11 +109,11 @@ void s_gfmul(const uint64_t hh, const uint64_t hl, uint64_t &y0, uint64_t &y1) n
 	y1 = Utils::hton(zhl);
 }
 
-} // anonymous namespace
+}	// anonymous namespace
 
-void AES::GMAC::update(const void *const data, unsigned int len) noexcept
+void AES::GMAC::update(const void* const data, unsigned int len) noexcept
 {
-	const uint8_t *in = reinterpret_cast<const uint8_t *>(data);
+	const uint8_t* in = reinterpret_cast<const uint8_t*>(data);
 	_len += len;
 
 #ifdef ZT_AES_AESNI
@@ -120,14 +121,14 @@ void AES::GMAC::update(const void *const data, unsigned int len) noexcept
 		p_aesNIUpdate(in, len);
 		return;
 	}
-#endif // ZT_AES_AESNI
+#endif	 // ZT_AES_AESNI
 
 #ifdef ZT_AES_NEON
 	if (Utils::ARMCAP.pmull) {
 		p_armUpdate(in, len);
 		return;
 	}
-#endif // ZT_AES_NEON
+#endif	 // ZT_AES_NEON
 
 	const uint64_t h0 = _aes.p_k.sw.h[0];
 	const uint64_t h1 = _aes.p_k.sw.h[1];
@@ -136,14 +137,14 @@ void AES::GMAC::update(const void *const data, unsigned int len) noexcept
 
 	if (_rp) {
 		for (;;) {
-			if (!len) {
+			if (! len) {
 				return;
 			}
 			--len;
 			_r[_rp++] = *(in++);
 			if (_rp == 16) {
-				y0 ^= Utils::loadMachineEndian< uint64_t >(_r);
-				y1 ^= Utils::loadMachineEndian< uint64_t >(_r + 8);
+				y0 ^= Utils::loadMachineEndian<uint64_t>(_r);
+				y1 ^= Utils::loadMachineEndian<uint64_t>(_r + 8);
 				s_gfmul(h0, h1, y0, y1);
 				break;
 			}
@@ -151,8 +152,8 @@ void AES::GMAC::update(const void *const data, unsigned int len) noexcept
 	}
 
 	while (len >= 16) {
-		y0 ^= Utils::loadMachineEndian< uint64_t >(in);
-		y1 ^= Utils::loadMachineEndian< uint64_t >(in + 8);
+		y0 ^= Utils::loadMachineEndian<uint64_t>(in);
+		y1 ^= Utils::loadMachineEndian<uint64_t>(in + 8);
 		in += 16;
 		s_gfmul(h0, h1, y0, y1);
 		len -= 16;
@@ -164,7 +165,7 @@ void AES::GMAC::update(const void *const data, unsigned int len) noexcept
 	for (unsigned int i = 0; i < len; ++i) {
 		_r[i] = in[i];
 	}
-	_rp = len; // len is always less than 16 here
+	_rp = len;	 // len is always less than 16 here
 }
 
 void AES::GMAC::finish(uint8_t tag[16]) noexcept
@@ -174,14 +175,14 @@ void AES::GMAC::finish(uint8_t tag[16]) noexcept
 		p_aesNIFinish(tag);
 		return;
 	}
-#endif // ZT_AES_AESNI
+#endif	 // ZT_AES_AESNI
 
 #ifdef ZT_AES_NEON
 	if (Utils::ARMCAP.pmull) {
 		p_armFinish(tag);
 		return;
 	}
-#endif // ZT_AES_NEON
+#endif	 // ZT_AES_NEON
 
 	const uint64_t h0 = _aes.p_k.sw.h[0];
 	const uint64_t h1 = _aes.p_k.sw.h[1];
@@ -192,8 +193,8 @@ void AES::GMAC::finish(uint8_t tag[16]) noexcept
 		while (_rp < 16) {
 			_r[_rp++] = 0;
 		}
-		y0 ^= Utils::loadMachineEndian< uint64_t >(_r);
-		y1 ^= Utils::loadMachineEndian< uint64_t >(_r + 8);
+		y0 ^= Utils::loadMachineEndian<uint64_t>(_r);
+		y1 ^= Utils::loadMachineEndian<uint64_t>(_r + 8);
 		s_gfmul(h0, h1, y0, y1);
 	}
 
@@ -201,57 +202,57 @@ void AES::GMAC::finish(uint8_t tag[16]) noexcept
 	s_gfmul(h0, h1, y0, y1);
 
 	uint64_t iv2[2];
-	Utils::copy< 12 >(iv2, _iv);
+	Utils::copy<12>(iv2, _iv);
 #if __BYTE_ORDER == __BIG_ENDIAN
-	reinterpret_cast<uint32_t *>(iv2)[3] = 0x00000001;
+	reinterpret_cast<uint32_t*>(iv2)[3] = 0x00000001;
 #else
-	reinterpret_cast<uint32_t *>(iv2)[3] = 0x01000000;
+	reinterpret_cast<uint32_t*>(iv2)[3] = 0x01000000;
 #endif
 	_aes.encrypt(iv2, iv2);
 
-	Utils::storeMachineEndian< uint64_t >(tag, iv2[0] ^ y0);
-	Utils::storeMachineEndian< 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 ------------------------------------------------------------------------------------------------------------
 
-void AES::CTR::crypt(const void *const input, unsigned int len) noexcept
+void AES::CTR::crypt(const void* const input, unsigned int len) noexcept
 {
-	const uint8_t *in = reinterpret_cast<const uint8_t *>(input);
-	uint8_t *out = _out;
+	const uint8_t* in = reinterpret_cast<const uint8_t*>(input);
+	uint8_t* out = _out;
 
 #ifdef ZT_AES_AESNI
 	if (likely(Utils::CPUID.aes)) {
 		p_aesNICrypt(in, out, len);
 		return;
 	}
-#endif // ZT_AES_AESNI
+#endif	 // ZT_AES_AESNI
 
 #ifdef ZT_AES_NEON
 	if (Utils::ARMCAP.aes) {
 		p_armCrypt(in, out, len);
 		return;
 	}
-#endif // ZT_AES_NEON
+#endif	 // ZT_AES_NEON
 
 	uint64_t keyStream[2];
-	uint32_t ctr = Utils::ntoh(reinterpret_cast<uint32_t *>(_ctr)[3]);
+	uint32_t ctr = Utils::ntoh(reinterpret_cast<uint32_t*>(_ctr)[3]);
 
 	unsigned int totalLen = _len;
 	if ((totalLen & 15U)) {
 		for (;;) {
-			if (!len) {
+			if (! len) {
 				_len = (totalLen + len);
 				return;
 			}
 			--len;
 			out[totalLen++] = *(in++);
-			if (!(totalLen & 15U)) {
-				_aes.p_encryptSW(reinterpret_cast<const uint8_t *>(_ctr), reinterpret_cast<uint8_t *>(keyStream));
-				reinterpret_cast<uint32_t *>(_ctr)[3] = Utils::hton(++ctr);
-				uint8_t *outblk = out + (totalLen - 16);
+			if (! (totalLen & 15U)) {
+				_aes.p_encryptSW(reinterpret_cast<const uint8_t*>(_ctr), reinterpret_cast<uint8_t*>(keyStream));
+				reinterpret_cast<uint32_t*>(_ctr)[3] = Utils::hton(++ctr);
+				uint8_t* outblk = out + (totalLen - 16);
 				for (int i = 0; i < 16; ++i) {
-					outblk[i] ^= reinterpret_cast<uint8_t *>(keyStream)[i];
+					outblk[i] ^= reinterpret_cast<uint8_t*>(keyStream)[i];
 				}
 				break;
 			}
@@ -262,10 +263,10 @@ void AES::CTR::crypt(const void *const input, unsigned int len) noexcept
 	_len = (totalLen + len);
 
 	if (likely(len >= 16)) {
-		const uint32_t *const restrict rk = _aes.p_k.sw.ek;
-		const uint32_t ctr0rk0 = Utils::ntoh(reinterpret_cast<const uint32_t *>(_ctr)[0]) ^rk[0];
-		const uint32_t ctr1rk1 = Utils::ntoh(reinterpret_cast<const uint32_t *>(_ctr)[1]) ^rk[1];
-		const uint32_t ctr2rk2 = Utils::ntoh(reinterpret_cast<const uint32_t *>(_ctr)[2]) ^rk[2];
+		const uint32_t* const restrict rk = _aes.p_k.sw.ek;
+		const uint32_t ctr0rk0 = Utils::ntoh(reinterpret_cast<const uint32_t*>(_ctr)[0]) ^ rk[0];
+		const uint32_t ctr1rk1 = Utils::ntoh(reinterpret_cast<const uint32_t*>(_ctr)[1]) ^ rk[1];
+		const uint32_t ctr2rk2 = Utils::ntoh(reinterpret_cast<const uint32_t*>(_ctr)[2]) ^ rk[2];
 		const uint32_t m8 = 0x000000ff;
 		const uint32_t m8_8 = 0x0000ff00;
 		const uint32_t m8_16 = 0x00ff0000;
@@ -278,8 +279,8 @@ void AES::CTR::crypt(const void *const input, unsigned int len) noexcept
 				s2 = ctr2rk2;
 				s3 = ctr++ ^ rk[3];
 
-				const uint64_t in0 = *reinterpret_cast<const uint64_t *>(in);
-				const uint64_t in1 = *reinterpret_cast<const uint64_t *>(in + 8);
+				const uint64_t in0 = *reinterpret_cast<const uint64_t*>(in);
+				const uint64_t in1 = *reinterpret_cast<const uint64_t*>(in + 8);
 				in += 16;
 
 				t0 = Te0[s0 >> 24U] ^ Te1_r((s1 >> 16U) & m8) ^ Te2_r((s2 >> 8U) & m8) ^ Te3_r(s3 & m8) ^ rk[4];
@@ -339,11 +340,12 @@ void AES::CTR::crypt(const void *const input, unsigned int len) noexcept
 				s2 = (Te2_r(t2 >> 24U) & m8_24) ^ (Te3_r((t3 >> 16U) & m8) & m8_16) ^ (Te0[(t0 >> 8U) & m8] & m8_8) ^ (Te1_r(t1 & m8) & m8) ^ rk[58];
 				s3 = (Te2_r(t3 >> 24U) & m8_24) ^ (Te3_r((t0 >> 16U) & m8) & m8_16) ^ (Te0[(t1 >> 8U) & m8] & m8_8) ^ (Te1_r(t2 & m8) & m8) ^ rk[59];
 
-				*reinterpret_cast<uint64_t *>(out) = in0 ^ Utils::hton(((uint64_t)s0 << 32U) | (uint64_t)s1);
-				*reinterpret_cast<uint64_t *>(out + 8) = in1 ^ Utils::hton(((uint64_t)s2 << 32U) | (uint64_t)s3);
+				*reinterpret_cast<uint64_t*>(out) = in0 ^ Utils::hton(((uint64_t)s0 << 32U) | (uint64_t)s1);
+				*reinterpret_cast<uint64_t*>(out + 8) = in1 ^ Utils::hton(((uint64_t)s2 << 32U) | (uint64_t)s3);
 				out += 16;
 			} while ((len -= 16) >= 16);
-		} else {
+		}
+		else {
 			do {
 				uint32_t s0, s1, s2, s3, t0, t1, t2, t3;
 				s0 = ctr0rk0;
@@ -428,7 +430,7 @@ void AES::CTR::crypt(const void *const input, unsigned int len) noexcept
 				in += 16;
 			} while ((len -= 16) >= 16);
 		}
-		reinterpret_cast<uint32_t *>(_ctr)[3] = Utils::hton(ctr);
+		reinterpret_cast<uint32_t*>(_ctr)[3] = Utils::hton(ctr);
 	}
 
 	// Any remaining input is placed in _out. This will be picked up and crypted
@@ -454,48 +456,76 @@ void AES::CTR::finish() noexcept
 
 // Software AES and AES key expansion ---------------------------------------------------------------------------------
 
-const uint32_t AES::Te0[256] = {0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153,
-                                0x2a15153f, 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f,
-                                0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba,
-                                0x4ba8a8e3, 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d,
-                                0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437,
-                                0xf279798b, 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818,
-                                0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878,
-                                0xa5dfdf7a, 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a};
-const uint32_t AES::Te4[256] = {0x63636363, 0x7c7c7c7c, 0x77777777, 0x7b7b7b7b, 0xf2f2f2f2, 0x6b6b6b6b, 0x6f6f6f6f, 0xc5c5c5c5, 0x30303030, 0x01010101, 0x67676767, 0x2b2b2b2b, 0xfefefefe, 0xd7d7d7d7, 0xabababab, 0x76767676, 0xcacacaca, 0x82828282, 0xc9c9c9c9, 0x7d7d7d7d, 0xfafafafa, 0x59595959, 0x47474747, 0xf0f0f0f0, 0xadadadad, 0xd4d4d4d4, 0xa2a2a2a2, 0xafafafaf, 0x9c9c9c9c, 0xa4a4a4a4, 0x72727272, 0xc0c0c0c0, 0xb7b7b7b7, 0xfdfdfdfd, 0x93939393, 0x26262626, 0x36363636, 0x3f3f3f3f, 0xf7f7f7f7, 0xcccccccc, 0x34343434, 0xa5a5a5a5, 0xe5e5e5e5, 0xf1f1f1f1, 0x71717171, 0xd8d8d8d8, 0x31313131,
-                                0x15151515, 0x04040404, 0xc7c7c7c7, 0x23232323, 0xc3c3c3c3, 0x18181818, 0x96969696, 0x05050505, 0x9a9a9a9a, 0x07070707, 0x12121212, 0x80808080, 0xe2e2e2e2, 0xebebebeb, 0x27272727, 0xb2b2b2b2, 0x75757575,
-                                0x09090909, 0x83838383, 0x2c2c2c2c, 0x1a1a1a1a, 0x1b1b1b1b, 0x6e6e6e6e, 0x5a5a5a5a, 0xa0a0a0a0, 0x52525252, 0x3b3b3b3b, 0xd6d6d6d6, 0xb3b3b3b3, 0x29292929, 0xe3e3e3e3, 0x2f2f2f2f, 0x84848484, 0x53535353, 0xd1d1d1d1, 0x00000000, 0xedededed, 0x20202020, 0xfcfcfcfc, 0xb1b1b1b1, 0x5b5b5b5b, 0x6a6a6a6a, 0xcbcbcbcb, 0xbebebebe, 0x39393939, 0x4a4a4a4a, 0x4c4c4c4c, 0x58585858, 0xcfcfcfcf, 0xd0d0d0d0, 0xefefefef, 0xaaaaaaaa, 0xfbfbfbfb, 0x43434343, 0x4d4d4d4d, 0x33333333, 0x85858585, 0x45454545, 0xf9f9f9f9, 0x02020202, 0x7f7f7f7f, 0x50505050, 0x3c3c3c3c, 0x9f9f9f9f,
-                                0xa8a8a8a8, 0x51515151, 0xa3a3a3a3, 0x40404040, 0x8f8f8f8f, 0x92929292, 0x9d9d9d9d, 0x38383838, 0xf5f5f5f5, 0xbcbcbcbc, 0xb6b6b6b6, 0xdadadada, 0x21212121, 0x10101010, 0xffffffff, 0xf3f3f3f3, 0xd2d2d2d2,
-                                0xcdcdcdcd, 0x0c0c0c0c, 0x13131313, 0xecececec, 0x5f5f5f5f, 0x97979797, 0x44444444, 0x17171717, 0xc4c4c4c4, 0xa7a7a7a7, 0x7e7e7e7e, 0x3d3d3d3d, 0x64646464, 0x5d5d5d5d, 0x19191919, 0x73737373, 0x60606060, 0x81818181, 0x4f4f4f4f, 0xdcdcdcdc, 0x22222222, 0x2a2a2a2a, 0x90909090, 0x88888888, 0x46464646, 0xeeeeeeee, 0xb8b8b8b8, 0x14141414, 0xdededede, 0x5e5e5e5e, 0x0b0b0b0b, 0xdbdbdbdb, 0xe0e0e0e0, 0x32323232, 0x3a3a3a3a, 0x0a0a0a0a, 0x49494949, 0x06060606, 0x24242424, 0x5c5c5c5c, 0xc2c2c2c2, 0xd3d3d3d3, 0xacacacac, 0x62626262, 0x91919191, 0x95959595, 0xe4e4e4e4,
-                                0x79797979, 0xe7e7e7e7, 0xc8c8c8c8, 0x37373737, 0x6d6d6d6d, 0x8d8d8d8d, 0xd5d5d5d5, 0x4e4e4e4e, 0xa9a9a9a9, 0x6c6c6c6c, 0x56565656, 0xf4f4f4f4, 0xeaeaeaea, 0x65656565, 0x7a7a7a7a, 0xaeaeaeae, 0x08080808,
-                                0xbabababa, 0x78787878, 0x25252525, 0x2e2e2e2e, 0x1c1c1c1c, 0xa6a6a6a6, 0xb4b4b4b4, 0xc6c6c6c6, 0xe8e8e8e8, 0xdddddddd, 0x74747474, 0x1f1f1f1f, 0x4b4b4b4b, 0xbdbdbdbd, 0x8b8b8b8b, 0x8a8a8a8a, 0x70707070, 0x3e3e3e3e, 0xb5b5b5b5, 0x66666666, 0x48484848, 0x03030303, 0xf6f6f6f6, 0x0e0e0e0e, 0x61616161, 0x35353535, 0x57575757, 0xb9b9b9b9, 0x86868686, 0xc1c1c1c1, 0x1d1d1d1d, 0x9e9e9e9e, 0xe1e1e1e1, 0xf8f8f8f8, 0x98989898, 0x11111111, 0x69696969, 0xd9d9d9d9, 0x8e8e8e8e, 0x94949494, 0x9b9b9b9b, 0x1e1e1e1e, 0x87878787, 0xe9e9e9e9, 0xcececece, 0x55555555, 0x28282828,
-                                0xdfdfdfdf, 0x8c8c8c8c, 0xa1a1a1a1, 0x89898989, 0x0d0d0d0d, 0xbfbfbfbf, 0xe6e6e6e6, 0x42424242, 0x68686868, 0x41414141, 0x99999999, 0x2d2d2d2d, 0x0f0f0f0f, 0xb0b0b0b0, 0x54545454, 0xbbbbbbbb, 0x16161616};
-const uint32_t AES::Td0[256] = {0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c,
-                                0xf9082b94, 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c,
-                                0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1,
-                                0x24362e3a, 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8,
-                                0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e,
-                                0x82c3aff5, 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6,
-                                0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14,
-                                0x7844db86, 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742};
-const uint8_t AES::Td4[256] = {0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d,
-                               0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
-                               0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c,
-                               0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d};
-const uint32_t AES::rcon[15] = {0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000, 0x6c000000, 0xd8000000, 0xab000000, 0x4d000000, 0x9a000000};
-
-void AES::p_initSW(const uint8_t *key) noexcept
+const uint32_t AES::Te0[256] = { 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a,
+								 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b,
+								 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f,
+								 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f,
+								 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497,
+								 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a,
+								 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3,
+								 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d,
+								 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395,
+								 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76,
+								 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b,
+								 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818,
+								 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85,
+								 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9,
+								 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a,
+								 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a };
+const uint32_t AES::Te4[256] = { 0x63636363, 0x7c7c7c7c, 0x77777777, 0x7b7b7b7b, 0xf2f2f2f2, 0x6b6b6b6b, 0x6f6f6f6f, 0xc5c5c5c5, 0x30303030, 0x01010101, 0x67676767, 0x2b2b2b2b, 0xfefefefe, 0xd7d7d7d7, 0xabababab, 0x76767676,
+								 0xcacacaca, 0x82828282, 0xc9c9c9c9, 0x7d7d7d7d, 0xfafafafa, 0x59595959, 0x47474747, 0xf0f0f0f0, 0xadadadad, 0xd4d4d4d4, 0xa2a2a2a2, 0xafafafaf, 0x9c9c9c9c, 0xa4a4a4a4, 0x72727272, 0xc0c0c0c0,
+								 0xb7b7b7b7, 0xfdfdfdfd, 0x93939393, 0x26262626, 0x36363636, 0x3f3f3f3f, 0xf7f7f7f7, 0xcccccccc, 0x34343434, 0xa5a5a5a5, 0xe5e5e5e5, 0xf1f1f1f1, 0x71717171, 0xd8d8d8d8, 0x31313131, 0x15151515,
+								 0x04040404, 0xc7c7c7c7, 0x23232323, 0xc3c3c3c3, 0x18181818, 0x96969696, 0x05050505, 0x9a9a9a9a, 0x07070707, 0x12121212, 0x80808080, 0xe2e2e2e2, 0xebebebeb, 0x27272727, 0xb2b2b2b2, 0x75757575,
+								 0x09090909, 0x83838383, 0x2c2c2c2c, 0x1a1a1a1a, 0x1b1b1b1b, 0x6e6e6e6e, 0x5a5a5a5a, 0xa0a0a0a0, 0x52525252, 0x3b3b3b3b, 0xd6d6d6d6, 0xb3b3b3b3, 0x29292929, 0xe3e3e3e3, 0x2f2f2f2f, 0x84848484,
+								 0x53535353, 0xd1d1d1d1, 0x00000000, 0xedededed, 0x20202020, 0xfcfcfcfc, 0xb1b1b1b1, 0x5b5b5b5b, 0x6a6a6a6a, 0xcbcbcbcb, 0xbebebebe, 0x39393939, 0x4a4a4a4a, 0x4c4c4c4c, 0x58585858, 0xcfcfcfcf,
+								 0xd0d0d0d0, 0xefefefef, 0xaaaaaaaa, 0xfbfbfbfb, 0x43434343, 0x4d4d4d4d, 0x33333333, 0x85858585, 0x45454545, 0xf9f9f9f9, 0x02020202, 0x7f7f7f7f, 0x50505050, 0x3c3c3c3c, 0x9f9f9f9f, 0xa8a8a8a8,
+								 0x51515151, 0xa3a3a3a3, 0x40404040, 0x8f8f8f8f, 0x92929292, 0x9d9d9d9d, 0x38383838, 0xf5f5f5f5, 0xbcbcbcbc, 0xb6b6b6b6, 0xdadadada, 0x21212121, 0x10101010, 0xffffffff, 0xf3f3f3f3, 0xd2d2d2d2,
+								 0xcdcdcdcd, 0x0c0c0c0c, 0x13131313, 0xecececec, 0x5f5f5f5f, 0x97979797, 0x44444444, 0x17171717, 0xc4c4c4c4, 0xa7a7a7a7, 0x7e7e7e7e, 0x3d3d3d3d, 0x64646464, 0x5d5d5d5d, 0x19191919, 0x73737373,
+								 0x60606060, 0x81818181, 0x4f4f4f4f, 0xdcdcdcdc, 0x22222222, 0x2a2a2a2a, 0x90909090, 0x88888888, 0x46464646, 0xeeeeeeee, 0xb8b8b8b8, 0x14141414, 0xdededede, 0x5e5e5e5e, 0x0b0b0b0b, 0xdbdbdbdb,
+								 0xe0e0e0e0, 0x32323232, 0x3a3a3a3a, 0x0a0a0a0a, 0x49494949, 0x06060606, 0x24242424, 0x5c5c5c5c, 0xc2c2c2c2, 0xd3d3d3d3, 0xacacacac, 0x62626262, 0x91919191, 0x95959595, 0xe4e4e4e4, 0x79797979,
+								 0xe7e7e7e7, 0xc8c8c8c8, 0x37373737, 0x6d6d6d6d, 0x8d8d8d8d, 0xd5d5d5d5, 0x4e4e4e4e, 0xa9a9a9a9, 0x6c6c6c6c, 0x56565656, 0xf4f4f4f4, 0xeaeaeaea, 0x65656565, 0x7a7a7a7a, 0xaeaeaeae, 0x08080808,
+								 0xbabababa, 0x78787878, 0x25252525, 0x2e2e2e2e, 0x1c1c1c1c, 0xa6a6a6a6, 0xb4b4b4b4, 0xc6c6c6c6, 0xe8e8e8e8, 0xdddddddd, 0x74747474, 0x1f1f1f1f, 0x4b4b4b4b, 0xbdbdbdbd, 0x8b8b8b8b, 0x8a8a8a8a,
+								 0x70707070, 0x3e3e3e3e, 0xb5b5b5b5, 0x66666666, 0x48484848, 0x03030303, 0xf6f6f6f6, 0x0e0e0e0e, 0x61616161, 0x35353535, 0x57575757, 0xb9b9b9b9, 0x86868686, 0xc1c1c1c1, 0x1d1d1d1d, 0x9e9e9e9e,
+								 0xe1e1e1e1, 0xf8f8f8f8, 0x98989898, 0x11111111, 0x69696969, 0xd9d9d9d9, 0x8e8e8e8e, 0x94949494, 0x9b9b9b9b, 0x1e1e1e1e, 0x87878787, 0xe9e9e9e9, 0xcececece, 0x55555555, 0x28282828, 0xdfdfdfdf,
+								 0x8c8c8c8c, 0xa1a1a1a1, 0x89898989, 0x0d0d0d0d, 0xbfbfbfbf, 0xe6e6e6e6, 0x42424242, 0x68686868, 0x41414141, 0x99999999, 0x2d2d2d2d, 0x0f0f0f0f, 0xb0b0b0b0, 0x54545454, 0xbbbbbbbb, 0x16161616 };
+const uint32_t AES::Td0[256] = { 0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f,
+								 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844,
+								 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94,
+								 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c,
+								 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051,
+								 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb,
+								 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a,
+								 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8,
+								 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120,
+								 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef,
+								 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5,
+								 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6,
+								 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f,
+								 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713,
+								 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86,
+								 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742 };
+const uint8_t AES::Td4[256] = { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
+								0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
+								0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
+								0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
+								0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
+								0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
+								0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
+								0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d };
+const uint32_t AES::rcon[15] = { 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000, 0x6c000000, 0xd8000000, 0xab000000, 0x4d000000, 0x9a000000 };
+
+void AES::p_initSW(const uint8_t* key) noexcept
 {
-	uint32_t *rk = p_k.sw.ek;
-
-	rk[0] = Utils::loadBigEndian< uint32_t >(key);
-	rk[1] = Utils::loadBigEndian< uint32_t >(key + 4);
-	rk[2] = Utils::loadBigEndian< uint32_t >(key + 8);
-	rk[3] = Utils::loadBigEndian< uint32_t >(key + 12);
-	rk[4] = Utils::loadBigEndian< uint32_t >(key + 16);
-	rk[5] = Utils::loadBigEndian< uint32_t >(key + 20);
-	rk[6] = Utils::loadBigEndian< uint32_t >(key + 24);
-	rk[7] = Utils::loadBigEndian< uint32_t >(key + 28);
+	uint32_t* rk = p_k.sw.ek;
+
+	rk[0] = Utils::loadBigEndian<uint32_t>(key);
+	rk[1] = Utils::loadBigEndian<uint32_t>(key + 4);
+	rk[2] = Utils::loadBigEndian<uint32_t>(key + 8);
+	rk[3] = Utils::loadBigEndian<uint32_t>(key + 12);
+	rk[4] = Utils::loadBigEndian<uint32_t>(key + 16);
+	rk[5] = Utils::loadBigEndian<uint32_t>(key + 20);
+	rk[6] = Utils::loadBigEndian<uint32_t>(key + 24);
+	rk[7] = Utils::loadBigEndian<uint32_t>(key + 28);
 	for (int i = 0;;) {
 		uint32_t temp = rk[7];
 		rk[8] = rk[0] ^ (Te2_r((temp >> 16U) & 0xffU) & 0xff000000U) ^ (Te3_r((temp >> 8U) & 0xffU) & 0x00ff0000U) ^ (Te0[(temp) & 0xffU] & 0x0000ff00U) ^ (Te1_r(temp >> 24U) & 0x000000ffU) ^ rcon[i];
@@ -513,7 +543,7 @@ void AES::p_initSW(const uint8_t *key) noexcept
 		rk += 8;
 	}
 
-	p_encryptSW((const uint8_t *)Utils::ZERO256, (uint8_t *)p_k.sw.h);
+	p_encryptSW((const uint8_t*)Utils::ZERO256, (uint8_t*)p_k.sw.h);
 	p_k.sw.h[0] = Utils::ntoh(p_k.sw.h[0]);
 	p_k.sw.h[1] = Utils::ntoh(p_k.sw.h[1]);
 
@@ -545,17 +575,17 @@ void AES::p_initSW(const uint8_t *key) noexcept
 	}
 }
 
-void AES::p_encryptSW(const uint8_t *in, uint8_t *out) const noexcept
+void AES::p_encryptSW(const uint8_t* in, uint8_t* out) const noexcept
 {
-	const uint32_t *const restrict rk = p_k.sw.ek;
+	const uint32_t* const restrict rk = p_k.sw.ek;
 	const uint32_t m8 = 0x000000ff;
 	const uint32_t m8_8 = 0x0000ff00;
 	const uint32_t m8_16 = 0x00ff0000;
 	const uint32_t m8_24 = 0xff000000;
-	uint32_t s0 = Utils::loadBigEndian< uint32_t >(in) ^rk[0];
-	uint32_t s1 = Utils::loadBigEndian< uint32_t >(in + 4) ^rk[1];
-	uint32_t s2 = Utils::loadBigEndian< uint32_t >(in + 8) ^rk[2];
-	uint32_t s3 = Utils::loadBigEndian< uint32_t >(in + 12) ^rk[3];
+	uint32_t s0 = Utils::loadBigEndian<uint32_t>(in) ^ rk[0];
+	uint32_t s1 = Utils::loadBigEndian<uint32_t>(in + 4) ^ rk[1];
+	uint32_t s2 = Utils::loadBigEndian<uint32_t>(in + 8) ^ rk[2];
+	uint32_t s3 = Utils::loadBigEndian<uint32_t>(in + 12) ^ rk[3];
 
 	uint32_t t0, t1, t2, t3;
 	t0 = Te0[s0 >> 24U] ^ Te1_r((s1 >> 16U) & m8) ^ Te2_r((s2 >> 8U) & m8) ^ Te3_r(s3 & m8) ^ rk[4];
@@ -615,20 +645,20 @@ void AES::p_encryptSW(const uint8_t *in, uint8_t *out) const noexcept
 	s2 = (Te2_r(t2 >> 24U) & m8_24) ^ (Te3_r((t3 >> 16U) & m8) & m8_16) ^ (Te0[(t0 >> 8U) & m8] & m8_8) ^ (Te1_r(t1 & m8) & m8) ^ rk[58];
 	s3 = (Te2_r(t3 >> 24U) & m8_24) ^ (Te3_r((t0 >> 16U) & m8) & m8_16) ^ (Te0[(t1 >> 8U) & m8] & m8_8) ^ (Te1_r(t2 & m8) & m8) ^ rk[59];
 
-	Utils::storeBigEndian< uint32_t >(out, s0);
-	Utils::storeBigEndian< uint32_t >(out + 4, s1);
-	Utils::storeBigEndian< uint32_t >(out + 8, s2);
-	Utils::storeBigEndian< uint32_t >(out + 12, s3);
+	Utils::storeBigEndian<uint32_t>(out, s0);
+	Utils::storeBigEndian<uint32_t>(out + 4, s1);
+	Utils::storeBigEndian<uint32_t>(out + 8, s2);
+	Utils::storeBigEndian<uint32_t>(out + 12, s3);
 }
 
-void AES::p_decryptSW(const uint8_t *in, uint8_t *out) const noexcept
+void AES::p_decryptSW(const uint8_t* in, uint8_t* out) const noexcept
 {
-	const uint32_t *restrict rk = p_k.sw.dk;
+	const uint32_t* restrict rk = p_k.sw.dk;
 	const uint32_t m8 = 0x000000ff;
-	uint32_t s0 = Utils::loadBigEndian< uint32_t >(in) ^rk[0];
-	uint32_t s1 = Utils::loadBigEndian< uint32_t >(in + 4) ^rk[1];
-	uint32_t s2 = Utils::loadBigEndian< uint32_t >(in + 8) ^rk[2];
-	uint32_t s3 = Utils::loadBigEndian< uint32_t >(in + 12) ^rk[3];
+	uint32_t s0 = Utils::loadBigEndian<uint32_t>(in) ^ rk[0];
+	uint32_t s1 = Utils::loadBigEndian<uint32_t>(in + 4) ^ rk[1];
+	uint32_t s2 = Utils::loadBigEndian<uint32_t>(in + 8) ^ rk[2];
+	uint32_t s3 = Utils::loadBigEndian<uint32_t>(in + 12) ^ rk[3];
 
 	uint32_t t0, t1, t2, t3;
 	t0 = Td0[s0 >> 24U] ^ Td1_r((s3 >> 16U) & m8) ^ Td2_r((s2 >> 8U) & m8) ^ Td3_r(s1 & m8) ^ rk[4];
@@ -683,15 +713,15 @@ void AES::p_decryptSW(const uint8_t *in, uint8_t *out) const noexcept
 	t1 = Td0[s1 >> 24U] ^ Td1_r((s0 >> 16U) & m8) ^ Td2_r((s3 >> 8U) & m8) ^ Td3_r(s2 & m8) ^ rk[53];
 	t2 = Td0[s2 >> 24U] ^ Td1_r((s1 >> 16U) & m8) ^ Td2_r((s0 >> 8U) & m8) ^ Td3_r(s3 & m8) ^ rk[54];
 	t3 = Td0[s3 >> 24U] ^ Td1_r((s2 >> 16U) & m8) ^ Td2_r((s1 >> 8U) & m8) ^ Td3_r(s0 & m8) ^ rk[55];
-	s0 = (Td4[t0 >> 24U] << 24U) ^ (Td4[(t3 >> 16U) & m8] << 16U) ^ (Td4[(t2 >> 8U) & m8] << 8U) ^ (Td4[(t1) & m8]) ^ rk[56];
-	s1 = (Td4[t1 >> 24U] << 24U) ^ (Td4[(t0 >> 16U) & m8] << 16U) ^ (Td4[(t3 >> 8U) & m8] << 8U) ^ (Td4[(t2) & m8]) ^ rk[57];
-	s2 = (Td4[t2 >> 24U] << 24U) ^ (Td4[(t1 >> 16U) & m8] << 16U) ^ (Td4[(t0 >> 8U) & m8] << 8U) ^ (Td4[(t3) & m8]) ^ rk[58];
-	s3 = (Td4[t3 >> 24U] << 24U) ^ (Td4[(t2 >> 16U) & m8] << 16U) ^ (Td4[(t1 >> 8U) & m8] << 8U) ^ (Td4[(t0) & m8]) ^ rk[59];
-
-	Utils::storeBigEndian< uint32_t >(out, s0);
-	Utils::storeBigEndian< uint32_t >(out + 4, s1);
-	Utils::storeBigEndian< uint32_t >(out + 8, s2);
-	Utils::storeBigEndian< uint32_t >(out + 12, s3);
+	s0 = (Td4[t0 >> 24U] << 24U) ^ (Td4[(t3 >> 16U) & m8] << 16U) ^ (Td4[(t2 >> 8U) & m8] << 8U) ^ (Td4[(t1)&m8]) ^ rk[56];
+	s1 = (Td4[t1 >> 24U] << 24U) ^ (Td4[(t0 >> 16U) & m8] << 16U) ^ (Td4[(t3 >> 8U) & m8] << 8U) ^ (Td4[(t2)&m8]) ^ rk[57];
+	s2 = (Td4[t2 >> 24U] << 24U) ^ (Td4[(t1 >> 16U) & m8] << 16U) ^ (Td4[(t0 >> 8U) & m8] << 8U) ^ (Td4[(t3)&m8]) ^ rk[58];
+	s3 = (Td4[t3 >> 24U] << 24U) ^ (Td4[(t2 >> 16U) & m8] << 16U) ^ (Td4[(t1 >> 8U) & m8] << 8U) ^ (Td4[(t0)&m8]) ^ rk[59];
+
+	Utils::storeBigEndian<uint32_t>(out, s0);
+	Utils::storeBigEndian<uint32_t>(out + 4, s1);
+	Utils::storeBigEndian<uint32_t>(out + 8, s2);
+	Utils::storeBigEndian<uint32_t>(out + 12, s3);
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier

+ 113 - 109
node/AES.hpp

@@ -15,16 +15,16 @@
 #define ZT_AES_HPP
 
 #include "Constants.hpp"
-#include "Utils.hpp"
 #include "SHA512.hpp"
+#include "Utils.hpp"
 
 // Uncomment to disable all hardware acceleration (usually for testing)
-//#define ZT_AES_NO_ACCEL
+// #define ZT_AES_NO_ACCEL
 
-#if !defined(ZT_AES_NO_ACCEL) && defined(ZT_ARCH_X64)
+#if ! defined(ZT_AES_NO_ACCEL) && defined(ZT_ARCH_X64)
 #define ZT_AES_AESNI 1
 #endif
-#if !defined(ZT_AES_NO_ACCEL) && defined(ZT_ARCH_ARM_HAS_NEON) && defined(ZT_ARCH_ARM_HAS_CRYPTO)
+#if ! defined(ZT_AES_NO_ACCEL) && defined(ZT_ARCH_ARM_HAS_NEON) && defined(ZT_ARCH_ARM_HAS_CRYPTO)
 #define ZT_AES_NEON 1
 #endif
 
@@ -40,9 +40,8 @@ namespace ZeroTier {
  * This includes hardware acceleration for certain processors. The software
  * mode is fallback and is significantly slower.
  */
-class AES
-{
-public:
+class AES {
+  public:
 	/**
 	 * @return True if this system has hardware AES acceleration
 	 */
@@ -63,39 +62,44 @@ public:
 	 * Create an un-initialized AES instance (must call init() before use)
 	 */
 	ZT_INLINE AES() noexcept
-	{}
+	{
+	}
 
 	/**
 	 * Create an AES instance with the given key
 	 *
 	 * @param key 256-bit key
 	 */
-	explicit ZT_INLINE AES(const void *const key) noexcept
-	{ this->init(key); }
+	explicit ZT_INLINE AES(const void* const key) noexcept
+	{
+		this->init(key);
+	}
 
 	ZT_INLINE ~AES()
-	{ Utils::burn(&p_k, sizeof(p_k)); }
+	{
+		Utils::burn(&p_k, sizeof(p_k));
+	}
 
 	/**
 	 * Set (or re-set) this AES256 cipher's key
 	 *
 	 * @param key 256-bit / 32-byte key
 	 */
-	ZT_INLINE void init(const void *const key) noexcept
+	ZT_INLINE void init(const void* const key) noexcept
 	{
 #ifdef ZT_AES_AESNI
 		if (likely(Utils::CPUID.aes)) {
-			p_init_aesni(reinterpret_cast<const uint8_t *>(key));
+			p_init_aesni(reinterpret_cast<const uint8_t*>(key));
 			return;
 		}
 #endif
 #ifdef ZT_AES_NEON
 		if (Utils::ARMCAP.aes) {
-			p_init_armneon_crypto(reinterpret_cast<const uint8_t *>(key));
+			p_init_armneon_crypto(reinterpret_cast<const uint8_t*>(key));
 			return;
 		}
 #endif
-		p_initSW(reinterpret_cast<const uint8_t *>(key));
+		p_initSW(reinterpret_cast<const uint8_t*>(key));
 	}
 
 	/**
@@ -104,7 +108,7 @@ public:
 	 * @param in Input block
 	 * @param out Output block (can be same as input)
 	 */
-	ZT_INLINE void encrypt(const void *const in, void *const out) const noexcept
+	ZT_INLINE void encrypt(const void* const in, void* const out) const noexcept
 	{
 #ifdef ZT_AES_AESNI
 		if (likely(Utils::CPUID.aes)) {
@@ -118,7 +122,7 @@ public:
 			return;
 		}
 #endif
-		p_encryptSW(reinterpret_cast<const uint8_t *>(in), reinterpret_cast<uint8_t *>(out));
+		p_encryptSW(reinterpret_cast<const uint8_t*>(in), reinterpret_cast<uint8_t*>(out));
 	}
 
 	/**
@@ -127,7 +131,7 @@ public:
 	 * @param in Input block
 	 * @param out Output block (can be same as input)
 	 */
-	ZT_INLINE void decrypt(const void *const in, void *const out) const noexcept
+	ZT_INLINE void decrypt(const void* const in, void* const out) const noexcept
 	{
 #ifdef ZT_AES_AESNI
 		if (likely(Utils::CPUID.aes)) {
@@ -141,7 +145,7 @@ public:
 			return;
 		}
 #endif
-		p_decryptSW(reinterpret_cast<const uint8_t *>(in), reinterpret_cast<uint8_t *>(out));
+		p_decryptSW(reinterpret_cast<const uint8_t*>(in), reinterpret_cast<uint8_t*>(out));
 	}
 
 	class GMACSIVEncryptor;
@@ -150,12 +154,11 @@ public:
 	/**
 	 * Streaming GMAC calculator
 	 */
-	class GMAC
-	{
+	class GMAC {
 		friend class GMACSIVEncryptor;
 		friend class GMACSIVDecryptor;
 
-	public:
+	  public:
 		/**
 		 * @return True if this system has hardware GMAC acceleration
 		 */
@@ -177,8 +180,9 @@ public:
 		 *
 		 * @param aes Keyed AES instance to use
 		 */
-		ZT_INLINE GMAC(const AES &aes) : _aes(aes)
-		{}
+		ZT_INLINE GMAC(const AES& aes) : _aes(aes)
+		{
+		}
 
 		/**
 		 * Reset and initialize for a new GMAC calculation
@@ -192,12 +196,12 @@ public:
 			// We fill the least significant 32 bits in the _iv field with 1 since in GCM mode
 			// this would hold the counter, but we're not doing GCM. The counter is therefore
 			// always 1.
-#ifdef ZT_AES_AESNI // also implies an x64 processor
-			*reinterpret_cast<uint64_t *>(_iv) = *reinterpret_cast<const uint64_t *>(iv);
-			*reinterpret_cast<uint32_t *>(_iv + 8) = *reinterpret_cast<const uint64_t *>(iv + 8);
-			*reinterpret_cast<uint32_t *>(_iv + 12) = 0x01000000; // 0x00000001 in big-endian byte order
+#ifdef ZT_AES_AESNI	  // also implies an x64 processor
+			*reinterpret_cast<uint64_t*>(_iv) = *reinterpret_cast<const uint64_t*>(iv);
+			*reinterpret_cast<uint32_t*>(_iv + 8) = *reinterpret_cast<const uint64_t*>(iv + 8);
+			*reinterpret_cast<uint32_t*>(_iv + 12) = 0x01000000;   // 0x00000001 in big-endian byte order
 #else
-			for(int i=0;i<12;++i) {
+			for (int i = 0; i < 12; ++i) {
 				_iv[i] = iv[i];
 			}
 			_iv[12] = 0;
@@ -215,7 +219,7 @@ public:
 		 * @param data Bytes to process
 		 * @param len Length of input
 		 */
-		void update(const void *data, unsigned int len) noexcept;
+		void update(const void* data, unsigned int len) noexcept;
 
 		/**
 		 * Process any remaining cached bytes and generate tag
@@ -226,19 +230,19 @@ public:
 		 */
 		void finish(uint8_t tag[16]) noexcept;
 
-	private:
+	  private:
 #ifdef ZT_AES_AESNI
-		void p_aesNIUpdate(const uint8_t *in, unsigned int len) noexcept;
+		void p_aesNIUpdate(const uint8_t* in, unsigned int len) noexcept;
 		void p_aesNIFinish(uint8_t tag[16]) noexcept;
 #endif
 #ifdef ZT_AES_NEON
-		void p_armUpdate(const uint8_t *in, unsigned int len) noexcept;
+		void p_armUpdate(const uint8_t* in, unsigned int len) noexcept;
 		void p_armFinish(uint8_t tag[16]) noexcept;
 #endif
-		const AES &_aes;
+		const AES& _aes;
 		unsigned int _rp;
 		unsigned int _len;
-		uint8_t _r[16]; // remainder
+		uint8_t _r[16];	  // remainder
 		uint8_t _iv[16];
 		uint64_t _y[2];
 	};
@@ -249,14 +253,14 @@ public:
 	 * NOTE: this doesn't support overflow of the counter in the least significant 32 bits.
 	 * AES-GMAC-CTR doesn't need this, so we don't support it as an optimization.
 	 */
-	class CTR
-	{
+	class CTR {
 		friend class GMACSIVEncryptor;
 		friend class GMACSIVDecryptor;
 
-	public:
-		ZT_INLINE CTR(const AES &aes) noexcept: _aes(aes)
-		{}
+	  public:
+		ZT_INLINE CTR(const AES& aes) noexcept : _aes(aes)
+		{
+		}
 
 		/**
 		 * Initialize this CTR instance to encrypt a new stream
@@ -264,10 +268,10 @@ public:
 		 * @param iv Unique initialization vector and initial 32-bit counter (least significant 32 bits, big-endian)
 		 * @param output Buffer to which to store output (MUST be large enough for total bytes processed!)
 		 */
-		ZT_INLINE void init(const uint8_t iv[16], void *const output) noexcept
+		ZT_INLINE void init(const uint8_t iv[16], void* const output) noexcept
 		{
-			Utils::copy< 16 >(_ctr, iv);
-			_out = reinterpret_cast<uint8_t *>(output);
+			Utils::copy<16>(_ctr, iv);
+			_out = reinterpret_cast<uint8_t*>(output);
 			_len = 0;
 		}
 
@@ -278,11 +282,11 @@ public:
 		 * @param ic Initial counter (must be in big-endian byte order!)
 		 * @param output Buffer to which to store output (MUST be large enough for total bytes processed!)
 		 */
-		ZT_INLINE void init(const uint8_t iv[12], const uint32_t ic, void *const output) noexcept
+		ZT_INLINE void init(const uint8_t iv[12], const uint32_t ic, void* const output) noexcept
 		{
-			Utils::copy< 12 >(_ctr, iv);
-			reinterpret_cast<uint32_t *>(_ctr)[3] = ic;
-			_out = reinterpret_cast<uint8_t *>(output);
+			Utils::copy<12>(_ctr, iv);
+			reinterpret_cast<uint32_t*>(_ctr)[3] = ic;
+			_out = reinterpret_cast<uint8_t*>(output);
 			_len = 0;
 		}
 
@@ -292,7 +296,7 @@ public:
 		 * @param input Input data
 		 * @param len Length of input
 		 */
-		void crypt(const void *input, unsigned int len) noexcept;
+		void crypt(const void* input, unsigned int len) noexcept;
 
 		/**
 		 * Finish any remaining bytes if total bytes processed wasn't a multiple of 16
@@ -301,16 +305,16 @@ public:
 		 */
 		void finish() noexcept;
 
-	private:
+	  private:
 #ifdef ZT_AES_AESNI
-		void p_aesNICrypt(const uint8_t *in, uint8_t *out, unsigned int len) noexcept;
+		void p_aesNICrypt(const uint8_t* in, uint8_t* out, unsigned int len) noexcept;
 #endif
 #ifdef ZT_AES_NEON
-		void p_armCrypt(const uint8_t *in, uint8_t *out, unsigned int len) noexcept;
+		void p_armCrypt(const uint8_t* in, uint8_t* out, unsigned int len) noexcept;
 #endif
-		const AES &_aes;
+		const AES& _aes;
 		uint64_t _ctr[2];
-		uint8_t *_out;
+		uint8_t* _out;
 		unsigned int _len;
 	};
 
@@ -325,19 +329,19 @@ public:
 	 * This supports encryption of a maximum of 2^31 bytes of data per
 	 * call to init().
 	 */
-	class GMACSIVEncryptor
-	{
-	public:
+	class GMACSIVEncryptor {
+	  public:
 		/**
 		 * Create a new AES-GMAC-SIV encryptor keyed with the provided AES instances
 		 *
 		 * @param k0 First of two AES instances keyed with K0
 		 * @param k1 Second of two AES instances keyed with K1
 		 */
-		ZT_INLINE GMACSIVEncryptor(const AES &k0, const AES &k1) noexcept :
-			_gmac(k0),
-			_ctr(k1)
-		{}
+		ZT_INLINE GMACSIVEncryptor(const AES& k0, const AES& k1) noexcept
+			: _gmac(k0)
+			, _ctr(k1)
+		{
+		}
 
 		/**
 		 * Initialize AES-GMAC-SIV
@@ -345,7 +349,7 @@ public:
 		 * @param iv IV in network byte order (byte order in which it will appear on the wire)
 		 * @param output Pointer to buffer to receive ciphertext, must be large enough for all to-be-processed data!
 		 */
-		ZT_INLINE void init(const uint64_t iv, void *const output) noexcept
+		ZT_INLINE void init(const uint64_t iv, void* const output) noexcept
 		{
 			// Output buffer to receive the result of AES-CTR encryption.
 			_output = output;
@@ -353,7 +357,7 @@ public:
 			// Initialize GMAC with 64-bit IV (and remaining 32 bits padded to zero).
 			_tag[0] = iv;
 			_tag[1] = 0;
-			_gmac.init(reinterpret_cast<const uint8_t *>(_tag));
+			_gmac.init(reinterpret_cast<const uint8_t*>(_tag));
 		}
 
 		/**
@@ -367,7 +371,7 @@ public:
 		 * @param aad Additional authenticated data
 		 * @param len Length of AAD in bytes
 		 */
-		ZT_INLINE void aad(const void *const aad, unsigned int len) noexcept
+		ZT_INLINE void aad(const void* const aad, unsigned int len) noexcept
 		{
 			// Feed ADD into GMAC first
 			_gmac.update(aad, len);
@@ -385,8 +389,10 @@ public:
 		 * @param input Plaintext chunk
 		 * @param len Length of plaintext chunk
 		 */
-		ZT_INLINE void update1(const void *const input, const unsigned int len) noexcept
-		{ _gmac.update(input, len); }
+		ZT_INLINE void update1(const void* const input, const unsigned int len) noexcept
+		{
+			_gmac.update(input, len);
+		}
 
 		/**
 		 * Finish first pass, compute CTR IV, initialize second pass.
@@ -395,7 +401,7 @@ public:
 		{
 			// Compute 128-bit GMAC tag.
 			uint64_t tmp[2];
-			_gmac.finish(reinterpret_cast<uint8_t *>(tmp));
+			_gmac.finish(reinterpret_cast<uint8_t*>(tmp));
 
 			// Shorten to 64 bits, concatenate with message IV, and encrypt with AES to
 			// yield the CTR IV and opaque IV/MAC blob. In ZeroTier's use of GMAC-SIV
@@ -415,7 +421,7 @@ public:
 			// and so 2^31 should be considered the input limit.
 			tmp[0] = _tag[0];
 			tmp[1] = _tag[1] & ZT_CONST_TO_BE_UINT64(0xffffffff7fffffffULL);
-			_ctr.init(reinterpret_cast<const uint8_t *>(tmp), _output);
+			_ctr.init(reinterpret_cast<const uint8_t*>(tmp), _output);
 		}
 
 		/**
@@ -427,8 +433,10 @@ public:
 		 * @param input Plaintext chunk
 		 * @param len Length of plaintext chunk
 		 */
-		ZT_INLINE void update2(const void *const input, const unsigned int len) noexcept
-		{ _ctr.crypt(input, len); }
+		ZT_INLINE void update2(const void* const input, const unsigned int len) noexcept
+		{
+			_ctr.crypt(input, len);
+		}
 
 		/**
 		 * Finish second pass and return a pointer to the opaque 128-bit IV+MAC block
@@ -438,14 +446,14 @@ public:
 		 *
 		 * @return Pointer to 128-bit opaque IV+MAC (packed into two 64-bit integers)
 		 */
-		ZT_INLINE const uint64_t *finish2()
+		ZT_INLINE const uint64_t* finish2()
 		{
 			_ctr.finish();
 			return _tag;
 		}
 
-	private:
-		void *_output;
+	  private:
+		void* _output;
 		uint64_t _tag[2];
 		AES::GMAC _gmac;
 		AES::CTR _ctr;
@@ -456,13 +464,13 @@ public:
 	 *
 	 * GMAC-SIV decryption is single-pass. AAD (if any) must be processed first.
 	 */
-	class GMACSIVDecryptor
-	{
-	public:
-		ZT_INLINE GMACSIVDecryptor(const AES &k0, const AES &k1) noexcept:
-			_ctr(k1),
-			_gmac(k0)
-		{}
+	class GMACSIVDecryptor {
+	  public:
+		ZT_INLINE GMACSIVDecryptor(const AES& k0, const AES& k1) noexcept
+			: _ctr(k1)
+			, _gmac(k0)
+		{
+		}
 
 		/**
 		 * Initialize decryptor for a new message
@@ -470,18 +478,18 @@ public:
 		 * @param tag 128-bit combined IV/MAC originally created by GMAC-SIV encryption
 		 * @param output Buffer in which to write output plaintext (must be large enough!)
 		 */
-		ZT_INLINE void init(const uint64_t tag[2], void *const output) noexcept
+		ZT_INLINE void init(const uint64_t tag[2], void* const output) noexcept
 		{
 			uint64_t tmp[2];
 			tmp[0] = tag[0];
 			tmp[1] = tag[1] & ZT_CONST_TO_BE_UINT64(0xffffffff7fffffffULL);
-			_ctr.init(reinterpret_cast<const uint8_t *>(tmp), output);
+			_ctr.init(reinterpret_cast<const uint8_t*>(tmp), output);
 
 			_ctr._aes.decrypt(tag, _ivMac);
 
 			tmp[0] = _ivMac[0];
 			tmp[1] = 0;
-			_gmac.init(reinterpret_cast<const uint8_t *>(tmp));
+			_gmac.init(reinterpret_cast<const uint8_t*>(tmp));
 
 			_output = output;
 			_decryptedLen = 0;
@@ -493,7 +501,7 @@ public:
 		 * @param aad Additional authenticated data
 		 * @param len Length of AAD in bytes
 		 */
-		ZT_INLINE void aad(const void *const aad, unsigned int len) noexcept
+		ZT_INLINE void aad(const void* const aad, unsigned int len) noexcept
 		{
 			_gmac.update(aad, len);
 			len &= 0xfU;
@@ -510,7 +518,7 @@ public:
 		 * @param input Input ciphertext
 		 * @param len Length of ciphertext
 		 */
-		ZT_INLINE void update(const void *const input, const unsigned int len) noexcept
+		ZT_INLINE void update(const void* const input, const unsigned int len) noexcept
 		{
 			_ctr.crypt(input, len);
 			_decryptedLen += len;
@@ -527,52 +535,48 @@ public:
 
 			uint64_t gmacTag[2];
 			_gmac.update(_output, _decryptedLen);
-			_gmac.finish(reinterpret_cast<uint8_t *>(gmacTag));
+			_gmac.finish(reinterpret_cast<uint8_t*>(gmacTag));
 			return (gmacTag[0] ^ gmacTag[1]) == _ivMac[1];
 		}
 
-	private:
+	  private:
 		uint64_t _ivMac[2];
 		AES::CTR _ctr;
 		AES::GMAC _gmac;
-		void *_output;
+		void* _output;
 		unsigned int _decryptedLen;
 	};
 
-private:
+  private:
 	static const uint32_t Te0[256];
 	static const uint32_t Te4[256];
 	static const uint32_t Td0[256];
 	static const uint8_t Td4[256];
 	static const uint32_t rcon[15];
 
-	void p_initSW(const uint8_t *key) noexcept;
-	void p_encryptSW(const uint8_t *in, uint8_t *out) const noexcept;
-	void p_decryptSW(const uint8_t *in, uint8_t *out) const noexcept;
+	void p_initSW(const uint8_t* key) noexcept;
+	void p_encryptSW(const uint8_t* in, uint8_t* out) const noexcept;
+	void p_decryptSW(const uint8_t* in, uint8_t* out) const noexcept;
 
-	union
-	{
+	union {
 #ifdef ZT_AES_AESNI
-		struct
-		{
+		struct {
 			__m128i k[28];
-			__m128i h[4]; // h, hh, hhh, hhhh
-			__m128i h2[4]; // _mm_xor_si128(_mm_shuffle_epi32(h, 78), h), etc.
+			__m128i h[4];	 // h, hh, hhh, hhhh
+			__m128i h2[4];	 // _mm_xor_si128(_mm_shuffle_epi32(h, 78), h), etc.
 		} ni;
 #endif
 
 #ifdef ZT_AES_NEON
-		struct
-		{
-			uint64_t hsw[2]; // in case it has AES but not PMULL, not sure if that ever happens
+		struct {
+			uint64_t hsw[2];   // in case it has AES but not PMULL, not sure if that ever happens
 			uint8x16_t ek[15];
 			uint8x16_t dk[15];
 			uint8x16_t h;
 		} neon;
 #endif
 
-		struct
-		{
+		struct {
 			uint64_t h[2];
 			uint32_t ek[60];
 			uint32_t dk[60];
@@ -580,18 +584,18 @@ private:
 	} p_k;
 
 #ifdef ZT_AES_AESNI
-	void p_init_aesni(const uint8_t *key) noexcept;
-	void p_encrypt_aesni(const void *in, void *out) const noexcept;
-	void p_decrypt_aesni(const void *in, void *out) const noexcept;
+	void p_init_aesni(const uint8_t* key) noexcept;
+	void p_encrypt_aesni(const void* in, void* out) const noexcept;
+	void p_decrypt_aesni(const void* in, void* out) const noexcept;
 #endif
 
 #ifdef ZT_AES_NEON
-	void p_init_armneon_crypto(const uint8_t *key) noexcept;
-	void p_encrypt_armneon_crypto(const void *in, void *out) const noexcept;
-	void p_decrypt_armneon_crypto(const void *in, void *out) const noexcept;
+	void p_init_armneon_crypto(const uint8_t* key) noexcept;
+	void p_encrypt_armneon_crypto(const void* in, void* out) const noexcept;
+	void p_decrypt_armneon_crypto(const void* in, void* out) const noexcept;
 #endif
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 67 - 69
node/AES_aesni.cpp

@@ -11,8 +11,8 @@
  */
 /****/
 
-#include "Constants.hpp"
 #include "AES.hpp"
+#include "Constants.hpp"
 
 #ifdef ZT_AES_AESNI
 
@@ -29,7 +29,8 @@ const __m128i s_sseSwapBytes = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
 #ifdef __GNUC__
 __attribute__((__target__("ssse3,sse4,sse4.1,sse4.2,pclmul")))
 #endif
-__m128i p_gmacPCLMUL128(const __m128i h, __m128i y) noexcept
+__m128i
+p_gmacPCLMUL128(const __m128i h, __m128i y) noexcept
 {
 	y = _mm_shuffle_epi8(y, s_sseSwapBytes);
 	__m128i t1 = _mm_clmulepi64_si128(h, y, 0x00);
@@ -55,7 +56,7 @@ __m128i p_gmacPCLMUL128(const __m128i h, __m128i y) noexcept
  * The performance gain can be significant but regular SSE is already so
  * fast it's highly unlikely to be a rate limiting factor except on massive
  * servers and network infrastructure stuff. */
-#if !defined(__WINDOWS__) && ((__GNUC__ >= 8) || (__clang_major__ >= 7))
+#if ! defined(__WINDOWS__) && ((__GNUC__ >= 8) || (__clang_major__ >= 7))
 
 #define ZT_AES_VAES512 1
 
@@ -80,12 +81,8 @@ void p_aesCtrInnerVAES512(unsigned int &len, const uint64_t c0, uint64_t &c1, co
 	const __m512i kk13 = _mm512_broadcast_i32x4(k[13]);
 	const __m512i kk14 = _mm512_broadcast_i32x4(k[14]);
 	do {
-		__m512i p0 = _mm512_loadu_si512(reinterpret_cast<const __m512i *>(in));
-		__m512i d0 = _mm512_set_epi64(
-			(long long)Utils::hton(c1 + 3ULL), (long long)c0,
-			(long long)Utils::hton(c1 + 2ULL), (long long)c0,
-			(long long)Utils::hton(c1 + 1ULL), (long long)c0,
-			(long long)Utils::hton(c1), (long long)c0);
+		__m512i p0 = _mm512_loadu_si512(reinterpret_cast<const __m512i*>(in));
+		__m512i d0 = _mm512_set_epi64((long long)Utils::hton(c1 + 3ULL), (long long)c0, (long long)Utils::hton(c1 + 2ULL), (long long)c0, (long long)Utils::hton(c1 + 1ULL), (long long)c0, (long long)Utils::hton(c1), (long long)c0);
 		c1 += 4;
 		in += 64;
 		len -= 64;
@@ -104,7 +101,7 @@ void p_aesCtrInnerVAES512(unsigned int &len, const uint64_t c0, uint64_t &c1, co
 		d0 = _mm512_aesenc_epi128(d0, kk12);
 		d0 = _mm512_aesenc_epi128(d0, kk13);
 		d0 = _mm512_aesenclast_epi128(d0, kk14);
-		_mm512_storeu_si512(reinterpret_cast<__m512i *>(out), _mm512_xor_si512(p0, d0));
+		_mm512_storeu_si512(reinterpret_cast<__m512i*>(out), _mm512_xor_si512(p0, d0));
 		out += 64;
 	} while (likely(len >= 64));
 }
@@ -132,14 +129,10 @@ void p_aesCtrInnerVAES256(unsigned int &len, const uint64_t c0, uint64_t &c1, co
 	const __m256i kk13 = _mm256_broadcastsi128_si256(k[13]);
 	const __m256i kk14 = _mm256_broadcastsi128_si256(k[14]);
 	do {
-		__m256i p0 = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(in));
-		__m256i p1 = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(in + 32));
-		__m256i d0 = _mm256_set_epi64x(
-			(long long)Utils::hton(c1 + 1ULL), (long long)c0,
-			(long long)Utils::hton(c1), (long long)c0);
-		__m256i d1 = _mm256_set_epi64x(
-			(long long)Utils::hton(c1 + 3ULL), (long long)c0,
-			(long long)Utils::hton(c1 + 2ULL), (long long)c0);
+		__m256i p0 = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(in));
+		__m256i p1 = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(in + 32));
+		__m256i d0 = _mm256_set_epi64x((long long)Utils::hton(c1 + 1ULL), (long long)c0, (long long)Utils::hton(c1), (long long)c0);
+		__m256i d1 = _mm256_set_epi64x((long long)Utils::hton(c1 + 3ULL), (long long)c0, (long long)Utils::hton(c1 + 2ULL), (long long)c0);
 		c1 += 4;
 		in += 64;
 		len -= 64;
@@ -173,18 +166,19 @@ void p_aesCtrInnerVAES256(unsigned int &len, const uint64_t c0, uint64_t &c1, co
 		d1 = _mm256_aesenc_epi128(d1, kk13);
 		d0 = _mm256_aesenclast_epi128(d0, kk14);
 		d1 = _mm256_aesenclast_epi128(d1, kk14);
-		_mm256_storeu_si256(reinterpret_cast<__m256i *>(out), _mm256_xor_si256(d0, p0));
-		_mm256_storeu_si256(reinterpret_cast<__m256i *>(out + 32), _mm256_xor_si256(d1, p1));
+		_mm256_storeu_si256(reinterpret_cast<__m256i*>(out), _mm256_xor_si256(d0, p0));
+		_mm256_storeu_si256(reinterpret_cast<__m256i*>(out + 32), _mm256_xor_si256(d1, p1));
 		out += 64;
 	} while (likely(len >= 64));
 }
 
-#endif // does compiler support AVX2 and AVX512 AES intrinsics?
+#endif	 // does compiler support AVX2 and AVX512 AES intrinsics?
 
 #ifdef __GNUC__
 __attribute__((__target__("ssse3,sse4,sse4.1,sse4.2,aes,pclmul")))
 #endif
-__m128i p_init256_1_aesni(__m128i a, __m128i b) noexcept
+__m128i
+p_init256_1_aesni(__m128i a, __m128i b) noexcept
 {
 	__m128i x, y;
 	b = _mm_shuffle_epi32(b, 0xff);
@@ -201,7 +195,8 @@ __m128i p_init256_1_aesni(__m128i a, __m128i b) noexcept
 #ifdef __GNUC__
 __attribute__((__target__("ssse3,sse4,sse4.1,sse4.2,aes,pclmul")))
 #endif
-__m128i p_init256_2_aesni(__m128i a, __m128i b) noexcept
+__m128i
+p_init256_2_aesni(__m128i a, __m128i b) noexcept
 {
 	__m128i x, y, z;
 	y = _mm_aeskeygenassist_si128(a, 0x00);
@@ -216,25 +211,25 @@ __m128i p_init256_2_aesni(__m128i a, __m128i b) noexcept
 	return x;
 }
 
-} // anonymous namespace
+}	// anonymous namespace
 
 #ifdef __GNUC__
 __attribute__((__target__("ssse3,sse4,sse4.1,sse4.2,pclmul")))
 #endif
 void AES::GMAC::p_aesNIUpdate(const uint8_t *in, unsigned int len) noexcept
 {
-	__m128i y = _mm_loadu_si128(reinterpret_cast<const __m128i *>(_y));
+	__m128i y = _mm_loadu_si128(reinterpret_cast<const __m128i*>(_y));
 
 	// Handle anything left over from a previous run that wasn't a multiple of 16 bytes.
 	if (_rp) {
 		for (;;) {
-			if (!len) {
+			if (! len) {
 				return;
 			}
 			--len;
 			_r[_rp++] = *(in++);
 			if (_rp == 16) {
-				y = p_gmacPCLMUL128(_aes.p_k.ni.h[0], _mm_xor_si128(y, _mm_loadu_si128(reinterpret_cast<__m128i *>(_r))));
+				y = p_gmacPCLMUL128(_aes.p_k.ni.h[0], _mm_xor_si128(y, _mm_loadu_si128(reinterpret_cast<__m128i*>(_r))));
 				break;
 			}
 		}
@@ -250,17 +245,21 @@ void AES::GMAC::p_aesNIUpdate(const uint8_t *in, unsigned int len) noexcept
 		const __m128i hh2 = _aes.p_k.ni.h2[1];
 		const __m128i hhh2 = _aes.p_k.ni.h2[2];
 		const __m128i hhhh2 = _aes.p_k.ni.h2[3];
-		const uint8_t *const end64 = in + (len & ~((unsigned int)63));
+		const uint8_t* const end64 = in + (len & ~((unsigned int)63));
 		len &= 63U;
 		do {
-			__m128i d1 = _mm_shuffle_epi8(_mm_xor_si128(y, _mm_loadu_si128(reinterpret_cast<const __m128i *>(in))), sb);
-			__m128i d2 = _mm_shuffle_epi8(_mm_loadu_si128(reinterpret_cast<const __m128i *>(in + 16)), sb);
-			__m128i d3 = _mm_shuffle_epi8(_mm_loadu_si128(reinterpret_cast<const __m128i *>(in + 32)), sb);
-			__m128i d4 = _mm_shuffle_epi8(_mm_loadu_si128(reinterpret_cast<const __m128i *>(in + 48)), sb);
+			__m128i d1 = _mm_shuffle_epi8(_mm_xor_si128(y, _mm_loadu_si128(reinterpret_cast<const __m128i*>(in))), sb);
+			__m128i d2 = _mm_shuffle_epi8(_mm_loadu_si128(reinterpret_cast<const __m128i*>(in + 16)), sb);
+			__m128i d3 = _mm_shuffle_epi8(_mm_loadu_si128(reinterpret_cast<const __m128i*>(in + 32)), sb);
+			__m128i d4 = _mm_shuffle_epi8(_mm_loadu_si128(reinterpret_cast<const __m128i*>(in + 48)), sb);
 			in += 64;
 			__m128i a = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(hhhh, d1, 0x00), _mm_clmulepi64_si128(hhh, d2, 0x00)), _mm_xor_si128(_mm_clmulepi64_si128(hh, d3, 0x00), _mm_clmulepi64_si128(h, d4, 0x00)));
 			__m128i b = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(hhhh, d1, 0x11), _mm_clmulepi64_si128(hhh, d2, 0x11)), _mm_xor_si128(_mm_clmulepi64_si128(hh, d3, 0x11), _mm_clmulepi64_si128(h, d4, 0x11)));
-			__m128i c = _mm_xor_si128(_mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(hhhh2, _mm_xor_si128(_mm_shuffle_epi32(d1, 78), d1), 0x00), _mm_clmulepi64_si128(hhh2, _mm_xor_si128(_mm_shuffle_epi32(d2, 78), d2), 0x00)), _mm_xor_si128(_mm_clmulepi64_si128(hh2, _mm_xor_si128(_mm_shuffle_epi32(d3, 78), d3), 0x00), _mm_clmulepi64_si128(h2, _mm_xor_si128(_mm_shuffle_epi32(d4, 78), d4), 0x00))), _mm_xor_si128(a, b));
+			__m128i c = _mm_xor_si128(
+				_mm_xor_si128(
+					_mm_xor_si128(_mm_clmulepi64_si128(hhhh2, _mm_xor_si128(_mm_shuffle_epi32(d1, 78), d1), 0x00), _mm_clmulepi64_si128(hhh2, _mm_xor_si128(_mm_shuffle_epi32(d2, 78), d2), 0x00)),
+					_mm_xor_si128(_mm_clmulepi64_si128(hh2, _mm_xor_si128(_mm_shuffle_epi32(d3, 78), d3), 0x00), _mm_clmulepi64_si128(h2, _mm_xor_si128(_mm_shuffle_epi32(d4, 78), d4), 0x00))),
+				_mm_xor_si128(a, b));
 			a = _mm_xor_si128(_mm_slli_si128(c, 8), a);
 			b = _mm_xor_si128(_mm_srli_si128(c, 8), b);
 			c = _mm_srli_epi32(a, 31);
@@ -274,18 +273,18 @@ void AES::GMAC::p_aesNIUpdate(const uint8_t *in, unsigned int len) noexcept
 	}
 
 	while (len >= 16) {
-		y = p_gmacPCLMUL128(_aes.p_k.ni.h[0], _mm_xor_si128(y, _mm_loadu_si128(reinterpret_cast<const __m128i *>(in))));
+		y = p_gmacPCLMUL128(_aes.p_k.ni.h[0], _mm_xor_si128(y, _mm_loadu_si128(reinterpret_cast<const __m128i*>(in))));
 		in += 16;
 		len -= 16;
 	}
 
-	_mm_storeu_si128(reinterpret_cast<__m128i *>(_y), y);
+	_mm_storeu_si128(reinterpret_cast<__m128i*>(_y), y);
 
 	// Any overflow is cached for a later run or finish().
 	for (unsigned int i = 0; i < len; ++i) {
 		_r[i] = in[i];
 	}
-	_rp = len; // len is always less than 16 here
+	_rp = len;	 // len is always less than 16 here
 }
 
 #ifdef __GNUC__
@@ -293,23 +292,23 @@ __attribute__((__target__("ssse3,sse4,sse4.1,sse4.2,pclmul,aes")))
 #endif
 void AES::GMAC::p_aesNIFinish(uint8_t tag[16]) noexcept
 {
-	__m128i y = _mm_loadu_si128(reinterpret_cast<const __m128i *>(_y));
+	__m128i y = _mm_loadu_si128(reinterpret_cast<const __m128i*>(_y));
 
 	// Handle any remaining bytes, padding the last block with zeroes.
 	if (_rp) {
 		while (_rp < 16) {
 			_r[_rp++] = 0;
 		}
-		y = p_gmacPCLMUL128(_aes.p_k.ni.h[0], _mm_xor_si128(y, _mm_loadu_si128(reinterpret_cast<__m128i *>(_r))));
+		y = p_gmacPCLMUL128(_aes.p_k.ni.h[0], _mm_xor_si128(y, _mm_loadu_si128(reinterpret_cast<__m128i*>(_r))));
 	}
 
 	// Interleave encryption of IV with the final GHASH of y XOR (length * 8).
 	// Then XOR these together to get the final tag.
-	const __m128i *const k = _aes.p_k.ni.k;
+	const __m128i* const k = _aes.p_k.ni.k;
 	const __m128i h = _aes.p_k.ni.h[0];
 	y = _mm_xor_si128(y, _mm_set_epi64x(0LL, (long long)Utils::hton((uint64_t)_len << 3U)));
 	y = _mm_shuffle_epi8(y, s_sseSwapBytes);
-	__m128i encIV = _mm_xor_si128(_mm_loadu_si128(reinterpret_cast<const __m128i *>(_iv)), k[0]);
+	__m128i encIV = _mm_xor_si128(_mm_loadu_si128(reinterpret_cast<const __m128i*>(_iv)), k[0]);
 	__m128i t1 = _mm_clmulepi64_si128(h, y, 0x00);
 	__m128i t2 = _mm_clmulepi64_si128(h, y, 0x01);
 	__m128i t3 = _mm_clmulepi64_si128(h, y, 0x10);
@@ -359,7 +358,7 @@ void AES::GMAC::p_aesNIFinish(uint8_t tag[16]) noexcept
 	t4 = _mm_xor_si128(t4, t3);
 	encIV = _mm_aesenclast_si128(encIV, k[14]);
 	t4 = _mm_xor_si128(t4, t5);
-	_mm_storeu_si128(reinterpret_cast<__m128i *>(tag), _mm_xor_si128(_mm_shuffle_epi8(t4, s_sseSwapBytes), encIV));
+	_mm_storeu_si128(reinterpret_cast<__m128i*>(tag), _mm_xor_si128(_mm_shuffle_epi8(t4, s_sseSwapBytes), encIV));
 }
 
 #ifdef __GNUC__
@@ -370,7 +369,7 @@ void AES::CTR::p_aesNICrypt(const uint8_t *in, uint8_t *out, unsigned int len) n
 	const __m128i dd = _mm_set_epi64x(0, (long long)_ctr[0]);
 	uint64_t c1 = Utils::ntoh(_ctr[1]);
 
-	const __m128i *const k = _aes.p_k.ni.k;
+	const __m128i* const k = _aes.p_k.ni.k;
 	const __m128i k0 = k[0];
 	const __m128i k1 = k[1];
 	const __m128i k2 = k[2];
@@ -391,14 +390,14 @@ void AES::CTR::p_aesNICrypt(const uint8_t *in, uint8_t *out, unsigned int len) n
 	unsigned int totalLen = _len;
 	if ((totalLen & 15U)) {
 		for (;;) {
-			if (unlikely(!len)) {
+			if (unlikely(! len)) {
 				_ctr[1] = Utils::hton(c1);
 				_len = totalLen;
 				return;
 			}
 			--len;
 			out[totalLen++] = *(in++);
-			if (!(totalLen & 15U)) {
+			if (! (totalLen & 15U)) {
 				__m128i d0 = _mm_insert_epi64(dd, (long long)Utils::hton(c1++), 1);
 				d0 = _mm_xor_si128(d0, k0);
 				d0 = _mm_aesenc_si128(d0, k1);
@@ -411,7 +410,7 @@ void AES::CTR::p_aesNICrypt(const uint8_t *in, uint8_t *out, unsigned int len) n
 				d0 = _mm_aesenc_si128(d0, k8);
 				d0 = _mm_aesenc_si128(d0, k9);
 				d0 = _mm_aesenc_si128(d0, k10);
-				__m128i *const outblk = reinterpret_cast<__m128i *>(out + (totalLen - 16));
+				__m128i* const outblk = reinterpret_cast<__m128i*>(out + (totalLen - 16));
 				d0 = _mm_aesenc_si128(d0, k11);
 				const __m128i p0 = _mm_loadu_si128(outblk);
 				d0 = _mm_aesenc_si128(d0, k12);
@@ -427,26 +426,26 @@ void AES::CTR::p_aesNICrypt(const uint8_t *in, uint8_t *out, unsigned int len) n
 	_len = totalLen + len;
 
 	if (likely(len >= 64)) {
-
 #if defined(ZT_AES_VAES512) && defined(ZT_AES_VAES256)
 		if (Utils::CPUID.vaes && (len >= 256)) {
 			if (Utils::CPUID.avx512f) {
 				p_aesCtrInnerVAES512(len, _ctr[0], c1, in, out, k);
-			} else {
+			}
+			else {
 				p_aesCtrInnerVAES256(len, _ctr[0], c1, in, out, k);
 			}
 			goto skip_conventional_aesni_64;
 		}
 #endif
 
-#if !defined(ZT_AES_VAES512) && defined(ZT_AES_VAES256)
+#if ! defined(ZT_AES_VAES512) && defined(ZT_AES_VAES256)
 		if (Utils::CPUID.vaes && (len >= 256)) {
 			p_aesCtrInnerVAES256(len, _ctr[0], c1, in, out, k);
 			goto skip_conventional_aesni_64;
 		}
 #endif
 
-		const uint8_t *const eof64 = in + (len & ~((unsigned int)63));
+		const uint8_t* const eof64 = in + (len & ~((unsigned int)63));
 		len &= 63;
 		__m128i d0, d1, d2, d3;
 		do {
@@ -515,21 +514,20 @@ void AES::CTR::p_aesNICrypt(const uint8_t *in, uint8_t *out, unsigned int len) n
 			d1 = _mm_aesenc_si128(d1, k13);
 			d2 = _mm_aesenc_si128(d2, k13);
 			d3 = _mm_aesenc_si128(d3, k13);
-			d0 = _mm_xor_si128(_mm_aesenclast_si128(d0, k14), _mm_loadu_si128(reinterpret_cast<const __m128i *>(in)));
-			d1 = _mm_xor_si128(_mm_aesenclast_si128(d1, k14), _mm_loadu_si128(reinterpret_cast<const __m128i *>(in + 16)));
-			d2 = _mm_xor_si128(_mm_aesenclast_si128(d2, k14), _mm_loadu_si128(reinterpret_cast<const __m128i *>(in + 32)));
-			d3 = _mm_xor_si128(_mm_aesenclast_si128(d3, k14), _mm_loadu_si128(reinterpret_cast<const __m128i *>(in + 48)));
+			d0 = _mm_xor_si128(_mm_aesenclast_si128(d0, k14), _mm_loadu_si128(reinterpret_cast<const __m128i*>(in)));
+			d1 = _mm_xor_si128(_mm_aesenclast_si128(d1, k14), _mm_loadu_si128(reinterpret_cast<const __m128i*>(in + 16)));
+			d2 = _mm_xor_si128(_mm_aesenclast_si128(d2, k14), _mm_loadu_si128(reinterpret_cast<const __m128i*>(in + 32)));
+			d3 = _mm_xor_si128(_mm_aesenclast_si128(d3, k14), _mm_loadu_si128(reinterpret_cast<const __m128i*>(in + 48)));
 			in += 64;
-			_mm_storeu_si128(reinterpret_cast<__m128i *>(out), d0);
-			_mm_storeu_si128(reinterpret_cast<__m128i *>(out + 16), d1);
-			_mm_storeu_si128(reinterpret_cast<__m128i *>(out + 32), d2);
-			_mm_storeu_si128(reinterpret_cast<__m128i *>(out + 48), d3);
+			_mm_storeu_si128(reinterpret_cast<__m128i*>(out), d0);
+			_mm_storeu_si128(reinterpret_cast<__m128i*>(out + 16), d1);
+			_mm_storeu_si128(reinterpret_cast<__m128i*>(out + 32), d2);
+			_mm_storeu_si128(reinterpret_cast<__m128i*>(out + 48), d3);
 			out += 64;
 		} while (likely(in != eof64));
-
 	}
 
-	skip_conventional_aesni_64:
+skip_conventional_aesni_64:
 	while (len >= 16) {
 		__m128i d0 = _mm_insert_epi64(dd, (long long)Utils::hton(c1++), 1);
 		d0 = _mm_xor_si128(d0, k0);
@@ -546,7 +544,7 @@ void AES::CTR::p_aesNICrypt(const uint8_t *in, uint8_t *out, unsigned int len) n
 		d0 = _mm_aesenc_si128(d0, k11);
 		d0 = _mm_aesenc_si128(d0, k12);
 		d0 = _mm_aesenc_si128(d0, k13);
-		_mm_storeu_si128(reinterpret_cast<__m128i *>(out), _mm_xor_si128(_mm_aesenclast_si128(d0, k14), _mm_loadu_si128(reinterpret_cast<const __m128i *>(in))));
+		_mm_storeu_si128(reinterpret_cast<__m128i*>(out), _mm_xor_si128(_mm_aesenclast_si128(d0, k14), _mm_loadu_si128(reinterpret_cast<const __m128i*>(in))));
 		in += 16;
 		len -= 16;
 		out += 16;
@@ -568,8 +566,8 @@ __attribute__((__target__("ssse3,sse4,sse4.1,sse4.2,aes,pclmul")))
 void AES::p_init_aesni(const uint8_t *key) noexcept
 {
 	__m128i t1, t2, k1, k2, k3, k4, k5, k6, k7, k8, k9, k10, k11, k12, k13;
-	p_k.ni.k[0] = t1 = _mm_loadu_si128((const __m128i *)key);
-	p_k.ni.k[1] = k1 = t2 = _mm_loadu_si128((const __m128i *)(key + 16));
+	p_k.ni.k[0] = t1 = _mm_loadu_si128((const __m128i*)key);
+	p_k.ni.k[1] = k1 = t2 = _mm_loadu_si128((const __m128i*)(key + 16));
 	p_k.ni.k[2] = k2 = t1 = p_init256_1_aesni(t1, _mm_aeskeygenassist_si128(t2, 0x01));
 	p_k.ni.k[3] = k3 = t2 = p_init256_2_aesni(t1, t2);
 	p_k.ni.k[4] = k4 = t1 = p_init256_1_aesni(t1, _mm_aeskeygenassist_si128(t2, 0x02));
@@ -597,7 +595,7 @@ void AES::p_init_aesni(const uint8_t *key) noexcept
 	p_k.ni.k[26] = _mm_aesimc_si128(k2);
 	p_k.ni.k[27] = _mm_aesimc_si128(k1);
 
-	__m128i h = p_k.ni.k[0]; // _mm_xor_si128(_mm_setzero_si128(),_k.ni.k[0]);
+	__m128i h = p_k.ni.k[0];   // _mm_xor_si128(_mm_setzero_si128(),_k.ni.k[0]);
 	h = _mm_aesenc_si128(h, k1);
 	h = _mm_aesenc_si128(h, k2);
 	h = _mm_aesenc_si128(h, k3);
@@ -631,7 +629,7 @@ __attribute__((__target__("ssse3,sse4,sse4.1,sse4.2,aes,pclmul")))
 #endif
 void AES::p_encrypt_aesni(const void *const in, void *const out) const noexcept
 {
-	__m128i tmp = _mm_loadu_si128((const __m128i *)in);
+	__m128i tmp = _mm_loadu_si128((const __m128i*)in);
 	tmp = _mm_xor_si128(tmp, p_k.ni.k[0]);
 	tmp = _mm_aesenc_si128(tmp, p_k.ni.k[1]);
 	tmp = _mm_aesenc_si128(tmp, p_k.ni.k[2]);
@@ -646,7 +644,7 @@ void AES::p_encrypt_aesni(const void *const in, void *const out) const noexcept
 	tmp = _mm_aesenc_si128(tmp, p_k.ni.k[11]);
 	tmp = _mm_aesenc_si128(tmp, p_k.ni.k[12]);
 	tmp = _mm_aesenc_si128(tmp, p_k.ni.k[13]);
-	_mm_storeu_si128((__m128i *)out, _mm_aesenclast_si128(tmp, p_k.ni.k[14]));
+	_mm_storeu_si128((__m128i*)out, _mm_aesenclast_si128(tmp, p_k.ni.k[14]));
 }
 
 #ifdef __GNUC__
@@ -654,7 +652,7 @@ __attribute__((__target__("ssse3,sse4,sse4.1,sse4.2,aes,pclmul")))
 #endif
 void AES::p_decrypt_aesni(const void *in, void *out) const noexcept
 {
-	__m128i tmp = _mm_loadu_si128((const __m128i *)in);
+	__m128i tmp = _mm_loadu_si128((const __m128i*)in);
 	tmp = _mm_xor_si128(tmp, p_k.ni.k[14]);
 	tmp = _mm_aesdec_si128(tmp, p_k.ni.k[15]);
 	tmp = _mm_aesdec_si128(tmp, p_k.ni.k[16]);
@@ -669,9 +667,9 @@ void AES::p_decrypt_aesni(const void *in, void *out) const noexcept
 	tmp = _mm_aesdec_si128(tmp, p_k.ni.k[25]);
 	tmp = _mm_aesdec_si128(tmp, p_k.ni.k[26]);
 	tmp = _mm_aesdec_si128(tmp, p_k.ni.k[27]);
-	_mm_storeu_si128((__m128i *)out, _mm_aesdeclast_si128(tmp, p_k.ni.k[0]));
+	_mm_storeu_si128((__m128i*)out, _mm_aesdeclast_si128(tmp, p_k.ni.k[0]));
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
-#endif // ZT_AES_AESNI
+#endif	 // ZT_AES_AESNI

+ 55 - 49
node/AES_armcrypto.cpp

@@ -11,8 +11,8 @@
  */
 /****/
 
-#include "Constants.hpp"
 #include "AES.hpp"
+#include "Constants.hpp"
 
 #ifdef ZT_AES_NEON
 
@@ -29,34 +29,34 @@ ZT_INLINE uint8x16_t s_clmul_armneon_crypto(uint8x16_t h, uint8x16_t y, const ui
 	y = vrbitq_u8(y);
 	const uint8x16_t p = vreinterpretq_u8_u64(vdupq_n_u64(0x0000000000000087));
 	t0 = vextq_u8(y, y, 8);
-	__asm__ __volatile__("pmull     %0.1q, %1.1d, %2.1d \n\t" : "=w" (r0) : "w" (h), "w" (y));
-	__asm__ __volatile__("pmull2   %0.1q, %1.2d, %2.2d \n\t" :"=w" (r1) : "w" (h), "w" (y));
-	__asm__ __volatile__("pmull     %0.1q, %1.1d, %2.1d \n\t" : "=w" (t1) : "w" (h), "w" (t0));
-	__asm__ __volatile__("pmull2   %0.1q, %1.2d, %2.2d \n\t" :"=w" (t0) : "w" (h), "w" (t0));
+	__asm__ __volatile__("pmull     %0.1q, %1.1d, %2.1d \n\t" : "=w"(r0) : "w"(h), "w"(y));
+	__asm__ __volatile__("pmull2   %0.1q, %1.2d, %2.2d \n\t" : "=w"(r1) : "w"(h), "w"(y));
+	__asm__ __volatile__("pmull     %0.1q, %1.1d, %2.1d \n\t" : "=w"(t1) : "w"(h), "w"(t0));
+	__asm__ __volatile__("pmull2   %0.1q, %1.2d, %2.2d \n\t" : "=w"(t0) : "w"(h), "w"(t0));
 	t0 = veorq_u8(t0, t1);
 	t1 = vextq_u8(z, t0, 8);
 	r0 = veorq_u8(r0, t1);
 	t1 = vextq_u8(t0, z, 8);
 	r1 = veorq_u8(r1, t1);
-	__asm__ __volatile__("pmull2   %0.1q, %1.2d, %2.2d \n\t" :"=w" (t0) : "w" (r1), "w" (p));
+	__asm__ __volatile__("pmull2   %0.1q, %1.2d, %2.2d \n\t" : "=w"(t0) : "w"(r1), "w"(p));
 	t1 = vextq_u8(t0, z, 8);
 	r1 = veorq_u8(r1, t1);
 	t1 = vextq_u8(z, t0, 8);
 	r0 = veorq_u8(r0, t1);
-	__asm__ __volatile__("pmull     %0.1q, %1.1d, %2.1d \n\t" : "=w" (t0) : "w" (r1), "w" (p));
+	__asm__ __volatile__("pmull     %0.1q, %1.1d, %2.1d \n\t" : "=w"(t0) : "w"(r1), "w"(p));
 	return vrbitq_u8(veorq_u8(r0, t0));
 }
 
-} // anonymous namespace
+}	// anonymous namespace
 
-void AES::GMAC::p_armUpdate(const uint8_t *in, unsigned int len) noexcept
+void AES::GMAC::p_armUpdate(const uint8_t* in, unsigned int len) noexcept
 {
-	uint8x16_t y = vld1q_u8(reinterpret_cast<const uint8_t *>(_y));
+	uint8x16_t y = vld1q_u8(reinterpret_cast<const uint8_t*>(_y));
 	const uint8x16_t h = _aes.p_k.neon.h;
 
 	if (_rp) {
-		for(;;) {
-			if (!len) {
+		for (;;) {
+			if (! len) {
 				return;
 			}
 			--len;
@@ -74,18 +74,18 @@ void AES::GMAC::p_armUpdate(const uint8_t *in, unsigned int len) noexcept
 		len -= 16;
 	}
 
-	vst1q_u8(reinterpret_cast<uint8_t *>(_y), y);
+	vst1q_u8(reinterpret_cast<uint8_t*>(_y), y);
 
 	for (unsigned int i = 0; i < len; ++i) {
 		_r[i] = in[i];
 	}
-	_rp = len; // len is always less than 16 here
+	_rp = len;	 // len is always less than 16 here
 }
 
 void AES::GMAC::p_armFinish(uint8_t tag[16]) noexcept
 {
 	uint64_t tmp[2];
-	uint8x16_t y = vld1q_u8(reinterpret_cast<const uint8_t *>(_y));
+	uint8x16_t y = vld1q_u8(reinterpret_cast<const uint8_t*>(_y));
 	const uint8x16_t h = _aes.p_k.neon.h;
 
 	if (_rp) {
@@ -97,25 +97,25 @@ void AES::GMAC::p_armFinish(uint8_t tag[16]) noexcept
 
 	tmp[0] = Utils::hton((uint64_t)_len << 3U);
 	tmp[1] = 0;
-	y = s_clmul_armneon_crypto(h, y, reinterpret_cast<const uint8_t *>(tmp));
+	y = s_clmul_armneon_crypto(h, y, reinterpret_cast<const uint8_t*>(tmp));
 
-	Utils::copy< 12 >(tmp, _iv);
+	Utils::copy<12>(tmp, _iv);
 #if __BYTE_ORDER == __BIG_ENDIAN
-	reinterpret_cast<uint32_t *>(tmp)[3] = 0x00000001;
+	reinterpret_cast<uint32_t*>(tmp)[3] = 0x00000001;
 #else
-	reinterpret_cast<uint32_t *>(tmp)[3] = 0x01000000;
+	reinterpret_cast<uint32_t*>(tmp)[3] = 0x01000000;
 #endif
 	_aes.encrypt(tmp, tmp);
 
 	uint8x16_t yy = y;
-	Utils::storeMachineEndian< uint64_t >(tag, tmp[0] ^ reinterpret_cast<const uint64_t *>(&yy)[0]);
-	Utils::storeMachineEndian< uint64_t >(tag + 8, tmp[1] ^ reinterpret_cast<const uint64_t *>(&yy)[1]);
+	Utils::storeMachineEndian<uint64_t>(tag, tmp[0] ^ reinterpret_cast<const uint64_t*>(&yy)[0]);
+	Utils::storeMachineEndian<uint64_t>(tag + 8, tmp[1] ^ reinterpret_cast<const uint64_t*>(&yy)[1]);
 }
 
-void AES::CTR::p_armCrypt(const uint8_t *in, uint8_t *out, unsigned int len) noexcept
+void AES::CTR::p_armCrypt(const uint8_t* in, uint8_t* out, unsigned int len) noexcept
 {
-	uint8x16_t dd = vrev32q_u8(vld1q_u8(reinterpret_cast<uint8_t *>(_ctr)));
-	const uint32x4_t one = {0,0,0,1};
+	uint8x16_t dd = vrev32q_u8(vld1q_u8(reinterpret_cast<uint8_t*>(_ctr)));
+	const uint32x4_t one = { 0, 0, 0, 1 };
 
 	uint8x16_t k0 = _aes.p_k.neon.ek[0];
 	uint8x16_t k1 = _aes.p_k.neon.ek[1];
@@ -136,15 +136,15 @@ void AES::CTR::p_armCrypt(const uint8_t *in, uint8_t *out, unsigned int len) noe
 	unsigned int totalLen = _len;
 	if ((totalLen & 15U) != 0) {
 		for (;;) {
-			if (unlikely(!len)) {
-				vst1q_u8(reinterpret_cast<uint8_t *>(_ctr), vrev32q_u8(dd));
+			if (unlikely(! len)) {
+				vst1q_u8(reinterpret_cast<uint8_t*>(_ctr), vrev32q_u8(dd));
 				_len = totalLen;
 				return;
 			}
 			--len;
 			out[totalLen++] = *(in++);
 			if ((totalLen & 15U) == 0) {
-				uint8_t *const otmp = out + (totalLen - 16);
+				uint8_t* const otmp = out + (totalLen - 16);
 				uint8x16_t d0 = vrev32q_u8(dd);
 				uint8x16_t pt = vld1q_u8(otmp);
 				d0 = vaesmcq_u8(vaeseq_u8(d0, k0));
@@ -298,46 +298,52 @@ void AES::CTR::p_armCrypt(const uint8_t *in, uint8_t *out, unsigned int len) noe
 		out[i] = in[i];
 	}
 
-	vst1q_u8(reinterpret_cast<uint8_t *>(_ctr), vrev32q_u8(dd));
+	vst1q_u8(reinterpret_cast<uint8_t*>(_ctr), vrev32q_u8(dd));
 }
 
 #define ZT_INIT_ARMNEON_CRYPTO_SUBWORD(w) ((uint32_t)s_sbox[w & 0xffU] + ((uint32_t)s_sbox[(w >> 8U) & 0xffU] << 8U) + ((uint32_t)s_sbox[(w >> 16U) & 0xffU] << 16U) + ((uint32_t)s_sbox[(w >> 24U) & 0xffU] << 24U))
 #define ZT_INIT_ARMNEON_CRYPTO_ROTWORD(w) (((w) << 8U) | ((w) >> 24U))
-#define ZT_INIT_ARMNEON_CRYPTO_NK 8
-#define ZT_INIT_ARMNEON_CRYPTO_NB 4
-#define ZT_INIT_ARMNEON_CRYPTO_NR 14
+#define ZT_INIT_ARMNEON_CRYPTO_NK		  8
+#define ZT_INIT_ARMNEON_CRYPTO_NB		  4
+#define ZT_INIT_ARMNEON_CRYPTO_NR		  14
 
-void AES::p_init_armneon_crypto(const uint8_t *key) noexcept
+void AES::p_init_armneon_crypto(const uint8_t* key) noexcept
 {
-	static const uint8_t s_sbox[256] = {0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c,
-	                                    0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea,
-	                                    0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16};
+	static const uint8_t s_sbox[256] = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
+										 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
+										 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+										 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
+										 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
+										 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+										 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
+										 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 };
 
 	uint64_t h[2];
-	uint32_t *const w = reinterpret_cast<uint32_t *>(p_k.neon.ek);
+	uint32_t* const w = reinterpret_cast<uint32_t*>(p_k.neon.ek);
 
-	for (unsigned int i=0;i<ZT_INIT_ARMNEON_CRYPTO_NK;++i) {
+	for (unsigned int i = 0; i < ZT_INIT_ARMNEON_CRYPTO_NK; ++i) {
 		const unsigned int j = i * 4;
 		w[i] = ((uint32_t)key[j] << 24U) | ((uint32_t)key[j + 1] << 16U) | ((uint32_t)key[j + 2] << 8U) | (uint32_t)key[j + 3];
 	}
 
-	for (unsigned int i=ZT_INIT_ARMNEON_CRYPTO_NK;i<(ZT_INIT_ARMNEON_CRYPTO_NB * (ZT_INIT_ARMNEON_CRYPTO_NR + 1));++i) {
+	for (unsigned int i = ZT_INIT_ARMNEON_CRYPTO_NK; i < (ZT_INIT_ARMNEON_CRYPTO_NB * (ZT_INIT_ARMNEON_CRYPTO_NR + 1)); ++i) {
 		uint32_t t = w[i - 1];
 		const unsigned int imod = i & (ZT_INIT_ARMNEON_CRYPTO_NK - 1);
 		if (imod == 0) {
 			t = ZT_INIT_ARMNEON_CRYPTO_SUBWORD(ZT_INIT_ARMNEON_CRYPTO_ROTWORD(t)) ^ rcon[(i - 1) / ZT_INIT_ARMNEON_CRYPTO_NK];
-		} else if (imod == 4) {
+		}
+		else if (imod == 4) {
 			t = ZT_INIT_ARMNEON_CRYPTO_SUBWORD(t);
 		}
 		w[i] = w[i - ZT_INIT_ARMNEON_CRYPTO_NK] ^ t;
 	}
 
-	for (unsigned int i=0;i<(ZT_INIT_ARMNEON_CRYPTO_NB * (ZT_INIT_ARMNEON_CRYPTO_NR + 1));++i) {
+	for (unsigned int i = 0; i < (ZT_INIT_ARMNEON_CRYPTO_NB * (ZT_INIT_ARMNEON_CRYPTO_NR + 1)); ++i) {
 		w[i] = Utils::hton(w[i]);
 	}
 
 	p_k.neon.dk[0] = p_k.neon.ek[14];
-	for (int i=1;i<14;++i) {
+	for (int i = 1; i < 14; ++i) {
 		p_k.neon.dk[i] = vaesimcq_u8(p_k.neon.ek[14 - i]);
 	}
 	p_k.neon.dk[14] = p_k.neon.ek[0];
@@ -349,9 +355,9 @@ void AES::p_init_armneon_crypto(const uint8_t *key) noexcept
 	p_k.sw.h[1] = Utils::ntoh(h[1]);
 }
 
-void AES::p_encrypt_armneon_crypto(const void *const in, void *const out) const noexcept
+void AES::p_encrypt_armneon_crypto(const void* const in, void* const out) const noexcept
 {
-	uint8x16_t tmp = vld1q_u8(reinterpret_cast<const uint8_t *>(in));
+	uint8x16_t tmp = vld1q_u8(reinterpret_cast<const uint8_t*>(in));
 	tmp = vaesmcq_u8(vaeseq_u8(tmp, p_k.neon.ek[0]));
 	tmp = vaesmcq_u8(vaeseq_u8(tmp, p_k.neon.ek[1]));
 	tmp = vaesmcq_u8(vaeseq_u8(tmp, p_k.neon.ek[2]));
@@ -366,12 +372,12 @@ void AES::p_encrypt_armneon_crypto(const void *const in, void *const out) const
 	tmp = vaesmcq_u8(vaeseq_u8(tmp, p_k.neon.ek[11]));
 	tmp = vaesmcq_u8(vaeseq_u8(tmp, p_k.neon.ek[12]));
 	tmp = veorq_u8(vaeseq_u8(tmp, p_k.neon.ek[13]), p_k.neon.ek[14]);
-	vst1q_u8(reinterpret_cast<uint8_t *>(out), tmp);
+	vst1q_u8(reinterpret_cast<uint8_t*>(out), tmp);
 }
 
-void AES::p_decrypt_armneon_crypto(const void *const in, void *const out) const noexcept
+void AES::p_decrypt_armneon_crypto(const void* const in, void* const out) const noexcept
 {
-	uint8x16_t tmp = vld1q_u8(reinterpret_cast<const uint8_t *>(in));
+	uint8x16_t tmp = vld1q_u8(reinterpret_cast<const uint8_t*>(in));
 	tmp = vaesimcq_u8(vaesdq_u8(tmp, p_k.neon.dk[0]));
 	tmp = vaesimcq_u8(vaesdq_u8(tmp, p_k.neon.dk[1]));
 	tmp = vaesimcq_u8(vaesdq_u8(tmp, p_k.neon.dk[2]));
@@ -386,9 +392,9 @@ void AES::p_decrypt_armneon_crypto(const void *const in, void *const out) const
 	tmp = vaesimcq_u8(vaesdq_u8(tmp, p_k.neon.dk[11]));
 	tmp = vaesimcq_u8(vaesdq_u8(tmp, p_k.neon.dk[12]));
 	tmp = veorq_u8(vaesdq_u8(tmp, p_k.neon.dk[13]), p_k.neon.dk[14]);
-	vst1q_u8(reinterpret_cast<uint8_t *>(out), tmp);
+	vst1q_u8(reinterpret_cast<uint8_t*>(out), tmp);
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
-#endif // ZT_AES_NEON
+#endif	 // ZT_AES_NEON

+ 114 - 43
node/Address.hpp

@@ -14,49 +14,64 @@
 #ifndef ZT_ADDRESS_HPP
 #define ZT_ADDRESS_HPP
 
+#include "Buffer.hpp"
+#include "Constants.hpp"
+#include "Utils.hpp"
+
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <stdint.h>
 #include <string.h>
-
 #include <string>
 
-#include "Constants.hpp"
-#include "Utils.hpp"
-#include "Buffer.hpp"
-
 namespace ZeroTier {
 
 /**
  * A ZeroTier address
  */
-class Address
-{
-public:
-	Address() : _a(0) {}
-	Address(const Address &a) : _a(a._a) {}
-	Address(uint64_t a) : _a(a & 0xffffffffffULL) {}
+class Address {
+  public:
+	Address() : _a(0)
+	{
+	}
+	Address(const Address& a) : _a(a._a)
+	{
+	}
+	Address(uint64_t a) : _a(a & 0xffffffffffULL)
+	{
+	}
 
 	/**
 	 * @param bits Raw address -- 5 bytes, big-endian byte order
 	 * @param len Length of array
 	 */
-	Address(const void *bits,unsigned int len) { setTo(bits,len); }
+	Address(const void* bits, unsigned int len)
+	{
+		setTo(bits, len);
+	}
 
-	inline Address &operator=(const Address &a) { _a = a._a; return *this; }
-	inline Address &operator=(const uint64_t a) { _a = (a & 0xffffffffffULL); return *this; }
+	inline Address& operator=(const Address& a)
+	{
+		_a = a._a;
+		return *this;
+	}
+	inline Address& operator=(const uint64_t a)
+	{
+		_a = (a & 0xffffffffffULL);
+		return *this;
+	}
 
 	/**
 	 * @param bits Raw address -- 5 bytes, big-endian byte order
 	 * @param len Length of array
 	 */
-	inline void setTo(const void *bits,const unsigned int len)
+	inline void setTo(const void* bits, const unsigned int len)
 	{
 		if (len < ZT_ADDRESS_LENGTH) {
 			_a = 0;
 			return;
 		}
-		const unsigned char *b = (const unsigned char *)bits;
+		const unsigned char* b = (const unsigned char*)bits;
 		uint64_t a = ((uint64_t)*b++) << 32;
 		a |= ((uint64_t)*b++) << 24;
 		a |= ((uint64_t)*b++) << 16;
@@ -69,12 +84,12 @@ public:
 	 * @param bits Buffer to hold 5-byte address in big-endian byte order
 	 * @param len Length of array
 	 */
-	inline void copyTo(void *const bits,const unsigned int len) const
+	inline void copyTo(void* const bits, const unsigned int len) const
 	{
 		if (len < ZT_ADDRESS_LENGTH) {
 			return;
 		}
-		unsigned char *b = (unsigned char *)bits;
+		unsigned char* b = (unsigned char*)bits;
 		*(b++) = (unsigned char)((_a >> 32) & 0xff);
 		*(b++) = (unsigned char)((_a >> 24) & 0xff);
 		*(b++) = (unsigned char)((_a >> 16) & 0xff);
@@ -87,10 +102,9 @@ public:
 	 *
 	 * @param b Buffer to append to
 	 */
-	template<unsigned int C>
-	inline void appendTo(Buffer<C> &b) const
+	template <unsigned int C> inline void appendTo(Buffer<C>& b) const
 	{
-		unsigned char *p = (unsigned char *)b.appendField(ZT_ADDRESS_LENGTH);
+		unsigned char* p = (unsigned char*)b.appendField(ZT_ADDRESS_LENGTH);
 		*(p++) = (unsigned char)((_a >> 32) & 0xff);
 		*(p++) = (unsigned char)((_a >> 24) & 0xff);
 		*(p++) = (unsigned char)((_a >> 16) & 0xff);
@@ -101,22 +115,34 @@ public:
 	/**
 	 * @return Integer containing address (0 to 2^40)
 	 */
-	inline uint64_t toInt() const { return _a; }
+	inline uint64_t toInt() const
+	{
+		return _a;
+	}
 
 	/**
 	 * @return Hash code for use with Hashtable
 	 */
-	inline unsigned long hashCode() const { return (unsigned long)_a; }
+	inline unsigned long hashCode() const
+	{
+		return (unsigned long)_a;
+	}
 
 	/**
 	 * @return Hexadecimal string
 	 */
-	inline char *toString(char buf[11]) const { return Utils::hex10(_a,buf); }
+	inline char* toString(char buf[11]) const
+	{
+		return Utils::hex10(_a, buf);
+	}
 
 	/**
 	 * @return True if this address is not zero
 	 */
-	inline operator bool() const { return (_a != 0); }
+	inline operator bool() const
+	{
+		return (_a != 0);
+	}
 
 	/**
 	 * Check if this address is reserved
@@ -127,34 +153,79 @@ public:
 	 *
 	 * @return True if address is reserved and may not be used
 	 */
-	inline bool isReserved() const { return ((!_a)||((_a >> 32) == ZT_ADDRESS_RESERVED_PREFIX)); }
+	inline bool isReserved() const
+	{
+		return ((! _a) || ((_a >> 32) == ZT_ADDRESS_RESERVED_PREFIX));
+	}
 
 	/**
 	 * @param i Value from 0 to 4 (inclusive)
 	 * @return Byte at said position (address interpreted in big-endian order)
 	 */
-	inline uint8_t operator[](unsigned int i) const { return (uint8_t)(_a >> (32 - (i * 8))); }
+	inline uint8_t operator[](unsigned int i) const
+	{
+		return (uint8_t)(_a >> (32 - (i * 8)));
+	}
 
-	inline void zero() { _a = 0; }
+	inline void zero()
+	{
+		_a = 0;
+	}
 
-	inline bool operator==(const uint64_t &a) const { return (_a == (a & 0xffffffffffULL)); }
-	inline bool operator!=(const uint64_t &a) const { return (_a != (a & 0xffffffffffULL)); }
-	inline bool operator>(const uint64_t &a) const { return (_a > (a & 0xffffffffffULL)); }
-	inline bool operator<(const uint64_t &a) const { return (_a < (a & 0xffffffffffULL)); }
-	inline bool operator>=(const uint64_t &a) const { return (_a >= (a & 0xffffffffffULL)); }
-	inline bool operator<=(const uint64_t &a) const { return (_a <= (a & 0xffffffffffULL)); }
+	inline bool operator==(const uint64_t& a) const
+	{
+		return (_a == (a & 0xffffffffffULL));
+	}
+	inline bool operator!=(const uint64_t& a) const
+	{
+		return (_a != (a & 0xffffffffffULL));
+	}
+	inline bool operator>(const uint64_t& a) const
+	{
+		return (_a > (a & 0xffffffffffULL));
+	}
+	inline bool operator<(const uint64_t& a) const
+	{
+		return (_a < (a & 0xffffffffffULL));
+	}
+	inline bool operator>=(const uint64_t& a) const
+	{
+		return (_a >= (a & 0xffffffffffULL));
+	}
+	inline bool operator<=(const uint64_t& a) const
+	{
+		return (_a <= (a & 0xffffffffffULL));
+	}
 
-	inline bool operator==(const Address &a) const { return (_a == a._a); }
-	inline bool operator!=(const Address &a) const { return (_a != a._a); }
-	inline bool operator>(const Address &a) const { return (_a > a._a); }
-	inline bool operator<(const Address &a) const { return (_a < a._a); }
-	inline bool operator>=(const Address &a) const { return (_a >= a._a); }
-	inline bool operator<=(const Address &a) const { return (_a <= a._a); }
+	inline bool operator==(const Address& a) const
+	{
+		return (_a == a._a);
+	}
+	inline bool operator!=(const Address& a) const
+	{
+		return (_a != a._a);
+	}
+	inline bool operator>(const Address& a) const
+	{
+		return (_a > a._a);
+	}
+	inline bool operator<(const Address& a) const
+	{
+		return (_a < a._a);
+	}
+	inline bool operator>=(const Address& a) const
+	{
+		return (_a >= a._a);
+	}
+	inline bool operator<=(const Address& a) const
+	{
+		return (_a <= a._a);
+	}
 
-private:
+  private:
 	uint64_t _a;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 18 - 11
node/AtomicCounter.hpp

@@ -25,15 +25,17 @@ namespace ZeroTier {
 /**
  * Simple atomic counter supporting increment and decrement
  */
-class AtomicCounter
-{
-public:
-	AtomicCounter() { _v = 0; }
+class AtomicCounter {
+  public:
+	AtomicCounter()
+	{
+		_v = 0;
+	}
 
 	inline int load() const
 	{
 #ifdef __GNUC__
-		return __sync_or_and_fetch(const_cast<int *>(&_v),0);
+		return __sync_or_and_fetch(const_cast<int*>(&_v), 0);
 #else
 		return _v.load();
 #endif
@@ -42,7 +44,7 @@ public:
 	inline int operator++()
 	{
 #ifdef __GNUC__
-		return __sync_add_and_fetch(&_v,1);
+		return __sync_add_and_fetch(&_v, 1);
 #else
 		return ++_v;
 #endif
@@ -51,15 +53,20 @@ public:
 	inline int operator--()
 	{
 #ifdef __GNUC__
-		return __sync_sub_and_fetch(&_v,1);
+		return __sync_sub_and_fetch(&_v, 1);
 #else
 		return --_v;
 #endif
 	}
 
-private:
-	AtomicCounter(const AtomicCounter &) {}
-	const AtomicCounter &operator=(const AtomicCounter &) { return *this; }
+  private:
+	AtomicCounter(const AtomicCounter&)
+	{
+	}
+	const AtomicCounter& operator=(const AtomicCounter&)
+	{
+		return *this;
+	}
 
 #ifdef __GNUC__
 	int _v;
@@ -68,6 +75,6 @@ private:
 #endif
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 2 - 2
node/Bond.cpp

@@ -373,7 +373,7 @@ SharedPtr<Path> Bond::getAppropriatePath(int64_t now, int32_t flowId)
 	 */
 	if (_policy == ZT_BOND_POLICY_ACTIVE_BACKUP) {
 		if (_abPathIdx != ZT_MAX_PEER_NETWORK_PATHS && _paths[_abPathIdx].p) {
-			//fprintf(stderr, "trying to send via (_abPathIdx=%d) %s\n", _abPathIdx, pathToStr(_paths[_abPathIdx].p).c_str());
+			// fprintf(stderr, "trying to send via (_abPathIdx=%d) %s\n", _abPathIdx, pathToStr(_paths[_abPathIdx].p).c_str());
 			return _paths[_abPathIdx].p;
 		}
 	}
@@ -1584,7 +1584,7 @@ void Bond::processActiveBackupTasks(void* tPtr, int64_t now)
 						}
 					}
 				}
-				if (!foundPreferredPath && foundPathOnPrimaryLink && (nonPreferredPathIdx != ZT_MAX_PEER_NETWORK_PATHS)) {
+				if (! foundPreferredPath && foundPathOnPrimaryLink && (nonPreferredPathIdx != ZT_MAX_PEER_NETWORK_PATHS)) {
 					log("found non-preferred primary link (_abPathIdx=%d)", _abPathIdx);
 					_abPathIdx = nonPreferredPathIdx;
 				}

+ 2 - 2
node/Bond.hpp

@@ -1144,7 +1144,7 @@ class Bond {
 		__attribute__((format(printf, 2, 3)))
 #endif
 	{
-		//if (_peerId != 0x0 && _peerId != 0x0) { return; }
+		// if (_peerId != 0x0 && _peerId != 0x0) { return; }
 #ifdef ZT_TRACE
 		time_t rawtime;
 		struct tm* timeinfo;
@@ -1176,7 +1176,7 @@ class Bond {
 		__attribute__((format(printf, 2, 3)))
 #endif
 	{
-		//if (_peerId != 0x0 && _peerId != 0x0) { return; }
+		// if (_peerId != 0x0 && _peerId != 0x0) { return; }
 #ifdef ZT_DEBUG
 		time_t rawtime;
 		struct tm* timeinfo;

+ 137 - 104
node/Buffer.hpp

@@ -14,18 +14,17 @@
 #ifndef ZT_BUFFER_HPP
 #define ZT_BUFFER_HPP
 
-#include <string.h>
-#include <stdint.h>
+#include "Constants.hpp"
+#include "Utils.hpp"
 
+#include <algorithm>
 #include <stdexcept>
+#include <stdint.h>
+#include <string.h>
 #include <string>
-#include <algorithm>
 #include <utility>
 
-#include "Constants.hpp"
-#include "Utils.hpp"
-
-#if defined(__GNUC__) && (!defined(ZT_NO_TYPE_PUNNING))
+#if defined(__GNUC__) && (! defined(ZT_NO_TYPE_PUNNING))
 #define ZT_VAR_MAY_ALIAS __attribute__((__may_alias__))
 #else
 #define ZT_VAR_MAY_ALIAS
@@ -46,36 +45,57 @@ namespace ZeroTier {
  *
  * @tparam C Total capacity
  */
-template<unsigned int C>
-class Buffer
-{
+template <unsigned int C> class Buffer {
 	// I love me!
 	template <unsigned int C2> friend class Buffer;
 
-public:
+  public:
 	// STL container idioms
 	typedef unsigned char value_type;
-	typedef unsigned char * pointer;
-	typedef const char * const_pointer;
-	typedef char & reference;
-	typedef const char & const_reference;
-	typedef char * iterator;
-	typedef const char * const_iterator;
+	typedef unsigned char* pointer;
+	typedef const char* const_pointer;
+	typedef char& reference;
+	typedef const char& const_reference;
+	typedef char* iterator;
+	typedef const char* const_iterator;
 	typedef unsigned int size_type;
 	typedef int difference_type;
 	typedef std::reverse_iterator<iterator> reverse_iterator;
 	typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
-	inline iterator begin() { return _b; }
-	inline iterator end() { return (_b + _l); }
-	inline const_iterator begin() const { return _b; }
-	inline const_iterator end() const { return (_b + _l); }
-	inline reverse_iterator rbegin() { return reverse_iterator(begin()); }
-	inline reverse_iterator rend() { return reverse_iterator(end()); }
-	inline const_reverse_iterator rbegin() const { return const_reverse_iterator(begin()); }
-	inline const_reverse_iterator rend() const { return const_reverse_iterator(end()); }
+	inline iterator begin()
+	{
+		return _b;
+	}
+	inline iterator end()
+	{
+		return (_b + _l);
+	}
+	inline const_iterator begin() const
+	{
+		return _b;
+	}
+	inline const_iterator end() const
+	{
+		return (_b + _l);
+	}
+	inline reverse_iterator rbegin()
+	{
+		return reverse_iterator(begin());
+	}
+	inline reverse_iterator rend()
+	{
+		return reverse_iterator(end());
+	}
+	inline const_reverse_iterator rbegin() const
+	{
+		return const_reverse_iterator(begin());
+	}
+	inline const_reverse_iterator rend() const
+	{
+		return const_reverse_iterator(end());
+	}
 
-	Buffer() :
-		_l(0)
+	Buffer() : _l(0)
 	{
 	}
 
@@ -87,37 +107,36 @@ public:
 		_l = l;
 	}
 
-	template<unsigned int C2>
-	Buffer(const Buffer<C2> &b)
+	template <unsigned int C2> Buffer(const Buffer<C2>& b)
 	{
 		*this = b;
 	}
 
-	Buffer(const void *b,unsigned int l)
+	Buffer(const void* b, unsigned int l)
 	{
-		copyFrom(b,l);
+		copyFrom(b, l);
 	}
 
-	template<unsigned int C2>
-	inline Buffer &operator=(const Buffer<C2> &b)
+	template <unsigned int C2> inline Buffer& operator=(const Buffer<C2>& b)
 	{
 		if (unlikely(b._l > C)) {
 			throw ZT_EXCEPTION_OUT_OF_BOUNDS;
 		}
 		if (C2 == C) {
-			memcpy(this,&b,sizeof(Buffer<C>));
-		} else {
-			memcpy(_b,b._b,_l = b._l);
+			memcpy(this, &b, sizeof(Buffer<C>));
+		}
+		else {
+			memcpy(_b, b._b, _l = b._l);
 		}
 		return *this;
 	}
 
-	inline void copyFrom(const void *b,unsigned int l)
+	inline void copyFrom(const void* b, unsigned int l)
 	{
 		if (unlikely(l > C)) {
 			throw ZT_EXCEPTION_OUT_OF_BOUNDS;
 		}
-		memcpy(_b,b,l);
+		memcpy(_b, b, l);
 		_l = l;
 	}
 
@@ -129,12 +148,12 @@ public:
 		return (unsigned char)_b[i];
 	}
 
-	unsigned char &operator[](const unsigned int i)
+	unsigned char& operator[](const unsigned int i)
 	{
 		if (unlikely(i >= _l)) {
 			throw ZT_EXCEPTION_OUT_OF_BOUNDS;
 		}
-		return ((unsigned char *)_b)[i];
+		return ((unsigned char*)_b)[i];
 	}
 
 	/**
@@ -150,19 +169,19 @@ public:
 	 * @return Pointer to field data
 	 * @throws std::out_of_range Field extends beyond data size
 	 */
-	unsigned char *field(unsigned int i,unsigned int l)
+	unsigned char* field(unsigned int i, unsigned int l)
 	{
 		if (unlikely((i + l) > _l)) {
 			throw ZT_EXCEPTION_OUT_OF_BOUNDS;
 		}
-		return (unsigned char *)(_b + i);
+		return (unsigned char*)(_b + i);
 	}
-	const unsigned char *field(unsigned int i,unsigned int l) const
+	const unsigned char* field(unsigned int i, unsigned int l) const
 	{
 		if (unlikely((i + l) > _l)) {
 			throw ZT_EXCEPTION_OUT_OF_BOUNDS;
 		}
-		return (const unsigned char *)(_b + i);
+		return (const unsigned char*)(_b + i);
 	}
 
 	/**
@@ -172,19 +191,18 @@ public:
 	 * @param v Value
 	 * @tparam T Integer type (e.g. uint16_t, int64_t)
 	 */
-	template<typename T>
-	inline void setAt(unsigned int i,const T v)
+	template <typename T> inline void setAt(unsigned int i, const T v)
 	{
 		if (unlikely((i + sizeof(T)) > _l)) {
 			throw ZT_EXCEPTION_OUT_OF_BOUNDS;
 		}
 #ifdef ZT_NO_TYPE_PUNNING
-		uint8_t *p = reinterpret_cast<uint8_t *>(_b + i);
-		for(unsigned int x=1;x<=sizeof(T);++x) {
+		uint8_t* p = reinterpret_cast<uint8_t*>(_b + i);
+		for (unsigned int x = 1; x <= sizeof(T); ++x) {
 			*(p++) = (uint8_t)(v >> (8 * (sizeof(T) - x)));
 		}
 #else
-		T *const ZT_VAR_MAY_ALIAS p = reinterpret_cast<T *>(_b + i);
+		T* const ZT_VAR_MAY_ALIAS p = reinterpret_cast<T*>(_b + i);
 		*p = Utils::hton(v);
 #endif
 	}
@@ -196,22 +214,21 @@ public:
 	 * @tparam T Integer type (e.g. uint16_t, int64_t)
 	 * @return Integer value
 	 */
-	template<typename T>
-	inline T at(unsigned int i) const
+	template <typename T> inline T at(unsigned int i) const
 	{
 		if (unlikely((i + sizeof(T)) > _l)) {
 			throw ZT_EXCEPTION_OUT_OF_BOUNDS;
 		}
 #ifdef ZT_NO_TYPE_PUNNING
 		T v = 0;
-		const uint8_t *p = reinterpret_cast<const uint8_t *>(_b + i);
-		for(unsigned int x=0;x<sizeof(T);++x) {
+		const uint8_t* p = reinterpret_cast<const uint8_t*>(_b + i);
+		for (unsigned int x = 0; x < sizeof(T); ++x) {
 			v <<= 8;
-			v |= (T)*(p++);
+			v |= (T) * (p++);
 		}
 		return v;
 #else
-		const T *const ZT_VAR_MAY_ALIAS p = reinterpret_cast<const T *>(_b + i);
+		const T* const ZT_VAR_MAY_ALIAS p = reinterpret_cast<const T*>(_b + i);
 		return Utils::ntoh(*p);
 #endif
 	}
@@ -223,19 +240,18 @@ public:
 	 * @tparam T Integer type (e.g. uint16_t, int64_t)
 	 * @throws std::out_of_range Attempt to append beyond capacity
 	 */
-	template<typename T>
-	inline void append(const T v)
+	template <typename T> inline void append(const T v)
 	{
 		if (unlikely((_l + sizeof(T)) > C)) {
 			throw ZT_EXCEPTION_OUT_OF_BOUNDS;
 		}
 #ifdef ZT_NO_TYPE_PUNNING
-		uint8_t *p = reinterpret_cast<uint8_t *>(_b + _l);
-		for(unsigned int x=1;x<=sizeof(T);++x) {
+		uint8_t* p = reinterpret_cast<uint8_t*>(_b + _l);
+		for (unsigned int x = 1; x <= sizeof(T); ++x) {
 			*(p++) = (uint8_t)(v >> (8 * (sizeof(T) - x)));
 		}
 #else
-		T *const ZT_VAR_MAY_ALIAS p = reinterpret_cast<T *>(_b + _l);
+		T* const ZT_VAR_MAY_ALIAS p = reinterpret_cast<T*>(_b + _l);
 		*p = Utils::hton(v);
 #endif
 		_l += sizeof(T);
@@ -248,12 +264,12 @@ public:
 	 * @param n Number of times to append
 	 * @throws std::out_of_range Attempt to append beyond capacity
 	 */
-	inline void append(unsigned char c,unsigned int n)
+	inline void append(unsigned char c, unsigned int n)
 	{
 		if (unlikely((_l + n) > C)) {
 			throw ZT_EXCEPTION_OUT_OF_BOUNDS;
 		}
-		for(unsigned int i=0;i<n;++i) {
+		for (unsigned int i = 0; i < n; ++i) {
 			_b[_l++] = (char)c;
 		}
 	}
@@ -268,7 +284,7 @@ public:
 		if (unlikely((_l + n) > C)) {
 			throw ZT_EXCEPTION_OUT_OF_BOUNDS;
 		}
-		Utils::getSecureRandom(_b + _l,n);
+		Utils::getSecureRandom(_b + _l, n);
 		_l += n;
 	}
 
@@ -279,12 +295,12 @@ public:
 	 * @param l Length
 	 * @throws std::out_of_range Attempt to append beyond capacity
 	 */
-	inline void append(const void *b,unsigned int l)
+	inline void append(const void* b, unsigned int l)
 	{
 		if (unlikely((_l + l) > C)) {
 			throw ZT_EXCEPTION_OUT_OF_BOUNDS;
 		}
-		memcpy(_b + _l,b,l);
+		memcpy(_b + _l, b, l);
 		_l += l;
 	}
 
@@ -294,13 +310,13 @@ public:
 	 * @param s C string
 	 * @throws std::out_of_range Attempt to append beyond capacity
 	 */
-	inline void appendCString(const char *s)
+	inline void appendCString(const char* s)
 	{
-		for(;;) {
+		for (;;) {
 			if (unlikely(_l >= C)) {
 				throw ZT_EXCEPTION_OUT_OF_BOUNDS;
 			}
-			if (!(_b[_l++] = *(s++))) {
+			if (! (_b[_l++] = *(s++))) {
 				break;
 			}
 		}
@@ -313,10 +329,9 @@ public:
 	 * @tparam C2 Capacity of second buffer (typically inferred)
 	 * @throws std::out_of_range Attempt to append beyond capacity
 	 */
-	template<unsigned int C2>
-	inline void append(const Buffer<C2> &b)
+	template <unsigned int C2> inline void append(const Buffer<C2>& b)
 	{
-		append(b._b,b._l);
+		append(b._b, b._l);
 	}
 
 	/**
@@ -329,12 +344,12 @@ public:
 	 * @param l Length of field to append
 	 * @return Pointer to beginning of appended field of length 'l'
 	 */
-	inline char *appendField(unsigned int l)
+	inline char* appendField(unsigned int l)
 	{
 		if (unlikely((_l + l) > C)) {
 			throw ZT_EXCEPTION_OUT_OF_BOUNDS;
 		}
-		char *r = _b + _l;
+		char* r = _b + _l;
 		_l += l;
 		return r;
 	}
@@ -379,13 +394,13 @@ public:
 	 */
 	inline void behead(const unsigned int at)
 	{
-		if (!at) {
+		if (! at) {
 			return;
 		}
 		if (unlikely(at > _l)) {
 			throw ZT_EXCEPTION_OUT_OF_BOUNDS;
 		}
-		::memmove(_b,_b + at,_l -= at);
+		::memmove(_b, _b + at, _l -= at);
 	}
 
 	/**
@@ -395,92 +410,110 @@ public:
 	 * @param length Length of block to erase
 	 * @throws std::out_of_range Position plus length is beyond size of buffer
 	 */
-	inline void erase(const unsigned int at,const unsigned int length)
+	inline void erase(const unsigned int at, const unsigned int length)
 	{
 		const unsigned int endr = at + length;
 		if (unlikely(endr > _l)) {
 			throw ZT_EXCEPTION_OUT_OF_BOUNDS;
 		}
-		::memmove(_b + at,_b + endr,_l - endr);
+		::memmove(_b + at, _b + endr, _l - endr);
 		_l -= length;
 	}
 
 	/**
 	 * Set buffer data length to zero
 	 */
-	inline void clear() { _l = 0; }
+	inline void clear()
+	{
+		_l = 0;
+	}
 
 	/**
 	 * Zero buffer up to size()
 	 */
-	inline void zero() { memset(_b,0,_l); }
+	inline void zero()
+	{
+		memset(_b, 0, _l);
+	}
 
 	/**
 	 * Zero unused capacity area
 	 */
-	inline void zeroUnused() { memset(_b + _l,0,C - _l); }
+	inline void zeroUnused()
+	{
+		memset(_b + _l, 0, C - _l);
+	}
 
 	/**
 	 * Unconditionally and securely zero buffer's underlying memory
 	 */
-	inline void burn() { Utils::burn(_b,sizeof(_b)); }
+	inline void burn()
+	{
+		Utils::burn(_b, sizeof(_b));
+	}
 
 	/**
 	 * @return Constant pointer to data in buffer
 	 */
-	inline const void *data() const { return _b; }
+	inline const void* data() const
+	{
+		return _b;
+	}
 
 	/**
 	 * @return Non-constant pointer to data in buffer
 	 */
-	inline void *unsafeData() { return _b; }
+	inline void* unsafeData()
+	{
+		return _b;
+	}
 
 	/**
 	 * @return Size of data in buffer
 	 */
-	inline unsigned int size() const { return _l; }
+	inline unsigned int size() const
+	{
+		return _l;
+	}
 
 	/**
 	 * @return Capacity of buffer
 	 */
-	inline unsigned int capacity() const { return C; }
+	inline unsigned int capacity() const
+	{
+		return C;
+	}
 
-	template<unsigned int C2>
-	inline bool operator==(const Buffer<C2> &b) const
+	template <unsigned int C2> inline bool operator==(const Buffer<C2>& b) const
 	{
-		return ((_l == b._l)&&(!memcmp(_b,b._b,_l)));
+		return ((_l == b._l) && (! memcmp(_b, b._b, _l)));
 	}
-	template<unsigned int C2>
-	inline bool operator!=(const Buffer<C2> &b) const
+	template <unsigned int C2> inline bool operator!=(const Buffer<C2>& b) const
 	{
-		return ((_l != b._l)||(memcmp(_b,b._b,_l)));
+		return ((_l != b._l) || (memcmp(_b, b._b, _l)));
 	}
-	template<unsigned int C2>
-	inline bool operator<(const Buffer<C2> &b) const
+	template <unsigned int C2> inline bool operator<(const Buffer<C2>& b) const
 	{
-		return (memcmp(_b,b._b,std::min(_l,b._l)) < 0);
+		return (memcmp(_b, b._b, std::min(_l, b._l)) < 0);
 	}
-	template<unsigned int C2>
-	inline bool operator>(const Buffer<C2> &b) const
+	template <unsigned int C2> inline bool operator>(const Buffer<C2>& b) const
 	{
 		return (b < *this);
 	}
-	template<unsigned int C2>
-	inline bool operator<=(const Buffer<C2> &b) const
+	template <unsigned int C2> inline bool operator<=(const Buffer<C2>& b) const
 	{
-		return !(b < *this);
+		return ! (b < *this);
 	}
-	template<unsigned int C2>
-	inline bool operator>=(const Buffer<C2> &b) const
+	template <unsigned int C2> inline bool operator>=(const Buffer<C2>& b) const
 	{
-		return !(*this < b);
+		return ! (*this < b);
 	}
 
-private:
+  private:
 	char ZT_VAR_MAY_ALIAS _b[C];
 	unsigned int _l;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

File diff suppressed because it is too large
+ 620 - 691
node/C25519.cpp


+ 47 - 34
node/C25519.hpp

@@ -18,20 +18,28 @@
 
 namespace ZeroTier {
 
-#define ZT_C25519_PUBLIC_KEY_LEN 64
+#define ZT_C25519_PUBLIC_KEY_LEN  64
 #define ZT_C25519_PRIVATE_KEY_LEN 64
-#define ZT_C25519_SIGNATURE_LEN 96
+#define ZT_C25519_SIGNATURE_LEN	  96
 
 /**
  * A combined Curve25519 ECDH and Ed25519 signature engine
  */
-class C25519
-{
-public:
-	struct Public { uint8_t data[ZT_C25519_PUBLIC_KEY_LEN]; };
-	struct Private { uint8_t data[ZT_C25519_PRIVATE_KEY_LEN]; };
-	struct Signature { uint8_t data[ZT_C25519_SIGNATURE_LEN]; };
-	struct Pair { Public pub; Private priv; };
+class C25519 {
+  public:
+	struct Public {
+		uint8_t data[ZT_C25519_PUBLIC_KEY_LEN];
+	};
+	struct Private {
+		uint8_t data[ZT_C25519_PRIVATE_KEY_LEN];
+	};
+	struct Signature {
+		uint8_t data[ZT_C25519_SIGNATURE_LEN];
+	};
+	struct Pair {
+		Public pub;
+		Private priv;
+	};
 
 	/**
 	 * Generate a C25519 elliptic curve key pair
@@ -39,7 +47,7 @@ public:
 	static inline Pair generate()
 	{
 		Pair kp;
-		Utils::getSecureRandom(kp.priv.data,ZT_C25519_PRIVATE_KEY_LEN);
+		Utils::getSecureRandom(kp.priv.data, ZT_C25519_PRIVATE_KEY_LEN);
 		_calcPubDH(kp);
 		_calcPubED(kp);
 		return kp;
@@ -58,18 +66,17 @@ public:
 	 * @return Key pair where cond(kp) returns true
 	 * @tparam F Type of 'cond'
 	 */
-	template<typename F>
-	static inline Pair generateSatisfying(F cond)
+	template <typename F> static inline Pair generateSatisfying(F cond)
 	{
 		Pair kp;
-		void *const priv = (void *)kp.priv.data;
-		Utils::getSecureRandom(priv,ZT_C25519_PRIVATE_KEY_LEN);
-		_calcPubED(kp); // do Ed25519 key -- bytes 32-63 of pub and priv
+		void* const priv = (void*)kp.priv.data;
+		Utils::getSecureRandom(priv, ZT_C25519_PRIVATE_KEY_LEN);
+		_calcPubED(kp);	  // do Ed25519 key -- bytes 32-63 of pub and priv
 		do {
-			++(((uint64_t *)priv)[1]);
-			--(((uint64_t *)priv)[2]);
-			_calcPubDH(kp); // keep regenerating bytes 0-31 until satisfied
-		} while (!cond(kp));
+			++(((uint64_t*)priv)[1]);
+			--(((uint64_t*)priv)[2]);
+			_calcPubDH(kp);	  // keep regenerating bytes 0-31 until satisfied
+		} while (! cond(kp));
 		return kp;
 	}
 
@@ -84,8 +91,11 @@ public:
 	 * @param keybuf Buffer to fill
 	 * @param keylen Number of key bytes to generate
 	 */
-	static void agree(const Private &mine,const Public &their,void *keybuf,unsigned int keylen);
-	static inline void agree(const Pair &mine,const Public &their,void *keybuf,unsigned int keylen) { agree(mine.priv,their,keybuf,keylen); }
+	static void agree(const Private& mine, const Public& their, void* keybuf, unsigned int keylen);
+	static inline void agree(const Pair& mine, const Public& their, void* keybuf, unsigned int keylen)
+	{
+		agree(mine.priv, their, keybuf, keylen);
+	}
 
 	/**
 	 * Sign a message with a sender's key pair
@@ -106,8 +116,11 @@ public:
 	 * @param len Length of message in bytes
 	 * @param signature Buffer to fill with signature -- MUST be 96 bytes in length
 	 */
-	static void sign(const Private &myPrivate,const Public &myPublic,const void *msg,unsigned int len,void *signature);
-	static inline void sign(const Pair &mine,const void *msg,unsigned int len,void *signature) { sign(mine.priv,mine.pub,msg,len,signature); }
+	static void sign(const Private& myPrivate, const Public& myPublic, const void* msg, unsigned int len, void* signature);
+	static inline void sign(const Pair& mine, const void* msg, unsigned int len, void* signature)
+	{
+		sign(mine.priv, mine.pub, msg, len, signature);
+	}
 
 	/**
 	 * Sign a message with a sender's key pair
@@ -118,16 +131,16 @@ public:
 	 * @param len Length of message in bytes
 	 * @return Signature
 	 */
-	static inline Signature sign(const Private &myPrivate,const Public &myPublic,const void *msg,unsigned int len)
+	static inline Signature sign(const Private& myPrivate, const Public& myPublic, const void* msg, unsigned int len)
 	{
 		Signature sig;
-		sign(myPrivate,myPublic,msg,len,sig.data);
+		sign(myPrivate, myPublic, msg, len, sig.data);
 		return sig;
 	}
-	static inline Signature sign(const Pair &mine,const void *msg,unsigned int len)
+	static inline Signature sign(const Pair& mine, const void* msg, unsigned int len)
 	{
 		Signature sig;
-		sign(mine.priv,mine.pub,msg,len,sig.data);
+		sign(mine.priv, mine.pub, msg, len, sig.data);
 		return sig;
 	}
 
@@ -140,7 +153,7 @@ public:
 	 * @param signature 96-byte signature
 	 * @return True if signature is valid and the message is authentic and unmodified
 	 */
-	static bool verify(const Public &their,const void *msg,unsigned int len,const void *signature);
+	static bool verify(const Public& their, const void* msg, unsigned int len, const void* signature);
 
 	/**
 	 * Verify a message's signature
@@ -151,21 +164,21 @@ public:
 	 * @param signature 96-byte signature
 	 * @return True if signature is valid and the message is authentic and unmodified
 	 */
-	static inline bool verify(const Public &their,const void *msg,unsigned int len,const Signature &signature)
+	static inline bool verify(const Public& their, const void* msg, unsigned int len, const Signature& signature)
 	{
-		return verify(their,msg,len,signature.data);
+		return verify(their, msg, len, signature.data);
 	}
 
-private:
+  private:
 	// derive first 32 bytes of kp.pub from first 32 bytes of kp.priv
 	// this is the ECDH key
-	static void _calcPubDH(Pair &kp);
+	static void _calcPubDH(Pair& kp);
 
 	// derive 2nd 32 bytes of kp.pub from 2nd 32 bytes of kp.priv
 	// this is the Ed25519 sign/verify key
-	static void _calcPubED(Pair &kp);
+	static void _calcPubED(Pair& kp);
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 26 - 20
node/Capability.cpp

@@ -12,54 +12,60 @@
 /****/
 
 #include "Capability.hpp"
-#include "RuntimeEnvironment.hpp"
+
 #include "Identity.hpp"
-#include "Topology.hpp"
-#include "Switch.hpp"
 #include "Network.hpp"
 #include "Node.hpp"
+#include "RuntimeEnvironment.hpp"
+#include "Switch.hpp"
+#include "Topology.hpp"
 
 namespace ZeroTier {
 
-int Capability::verify(const RuntimeEnvironment *RR,void *tPtr) const
+int Capability::verify(const RuntimeEnvironment* RR, void* tPtr) const
 {
 	try {
 		// There must be at least one entry, and sanity check for bad chain max length
-		if ((_maxCustodyChainLength < 1)||(_maxCustodyChainLength > ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH)) {
+		if ((_maxCustodyChainLength < 1) || (_maxCustodyChainLength > ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH)) {
 			return -1;
 		}
 
 		// Validate all entries in chain of custody
 		Buffer<(sizeof(Capability) * 2)> tmp;
-		this->serialize(tmp,true);
-		for(unsigned int c=0;c<_maxCustodyChainLength;++c) {
+		this->serialize(tmp, true);
+		for (unsigned int c = 0; c < _maxCustodyChainLength; ++c) {
 			if (c == 0) {
-				if ((!_custody[c].to)||(!_custody[c].from)||(_custody[c].from != Network::controllerFor(_nwid))) {
-					return -1; // the first entry must be present and from the network's controller
+				if ((! _custody[c].to) || (! _custody[c].from) || (_custody[c].from != Network::controllerFor(_nwid))) {
+					return -1;	 // the first entry must be present and from the network's controller
 				}
-			} else {
-				if (!_custody[c].to) {
-					return 0; // all previous entries were valid, so we are valid
-				} else if ((!_custody[c].from)||(_custody[c].from != _custody[c-1].to)) {
-					return -1; // otherwise if we have another entry it must be from the previous holder in the chain
+			}
+			else {
+				if (! _custody[c].to) {
+					return 0;	// all previous entries were valid, so we are valid
+				}
+				else if ((! _custody[c].from) || (_custody[c].from != _custody[c - 1].to)) {
+					return -1;	 // otherwise if we have another entry it must be from the previous holder in the chain
 				}
 			}
 
-			const Identity id(RR->topology->getIdentity(tPtr,_custody[c].from));
+			const Identity id(RR->topology->getIdentity(tPtr, _custody[c].from));
 			if (id) {
-				if (!id.verify(tmp.data(),tmp.size(),_custody[c].signature)) {
+				if (! id.verify(tmp.data(), tmp.size(), _custody[c].signature)) {
 					return -1;
 				}
-			} else {
-				RR->sw->requestWhois(tPtr,RR->node->now(),_custody[c].from);
+			}
+			else {
+				RR->sw->requestWhois(tPtr, RR->node->now(), _custody[c].from);
 				return 1;
 			}
 		}
 
 		// We reached max custody chain length and everything was valid
 		return 0;
-	} catch ( ... ) {}
+	}
+	catch (...) {
+	}
 	return -1;
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier

+ 114 - 92
node/Capability.hpp

@@ -14,18 +14,18 @@
 #ifndef ZT_CAPABILITY_HPP
 #define ZT_CAPABILITY_HPP
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "Constants.hpp"
-#include "Credential.hpp"
+#include "../include/ZeroTierOne.h"
 #include "Address.hpp"
-#include "C25519.hpp"
-#include "Utils.hpp"
 #include "Buffer.hpp"
+#include "C25519.hpp"
+#include "Constants.hpp"
+#include "Credential.hpp"
 #include "Identity.hpp"
-#include "../include/ZeroTierOne.h"
+#include "Utils.hpp"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 
 namespace ZeroTier {
 
@@ -54,20 +54,17 @@ class RuntimeEnvironment;
  * handed off between nodes. Limited transferability of capabilities is
  * a feature of true capability based security.
  */
-class Capability : public Credential
-{
-public:
-	static inline Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_CAPABILITY; }
-
-	Capability() :
-		_nwid(0),
-		_ts(0),
-		_id(0),
-		_maxCustodyChainLength(0),
-		_ruleCount(0)
+class Capability : public Credential {
+  public:
+	static inline Credential::Type credentialType()
+	{
+		return Credential::CREDENTIAL_TYPE_CAPABILITY;
+	}
+
+	Capability() : _nwid(0), _ts(0), _id(0), _maxCustodyChainLength(0), _ruleCount(0)
 	{
-		memset(_rules,0,sizeof(_rules));
-		memset(_custody,0,sizeof(_custody));
+		memset(_rules, 0, sizeof(_rules));
+		memset(_custody, 0, sizeof(_custody));
 	}
 
 	/**
@@ -78,42 +75,57 @@ public:
 	 * @param rules Network flow rules for this capability
 	 * @param ruleCount Number of flow rules
 	 */
-	Capability(uint32_t id,uint64_t nwid,int64_t ts,unsigned int mccl,const ZT_VirtualNetworkRule *rules,unsigned int ruleCount) :
-		_nwid(nwid),
-		_ts(ts),
-		_id(id),
-		_maxCustodyChainLength((mccl > 0) ? ((mccl < ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH) ? mccl : (unsigned int)ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH) : 1),
-		_ruleCount((ruleCount < ZT_MAX_CAPABILITY_RULES) ? ruleCount : ZT_MAX_CAPABILITY_RULES)
+	Capability(uint32_t id, uint64_t nwid, int64_t ts, unsigned int mccl, const ZT_VirtualNetworkRule* rules, unsigned int ruleCount)
+		: _nwid(nwid)
+		, _ts(ts)
+		, _id(id)
+		, _maxCustodyChainLength((mccl > 0) ? ((mccl < ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH) ? mccl : (unsigned int)ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH) : 1)
+		, _ruleCount((ruleCount < ZT_MAX_CAPABILITY_RULES) ? ruleCount : ZT_MAX_CAPABILITY_RULES)
 	{
 		if (_ruleCount > 0) {
-			memcpy(_rules,rules,sizeof(ZT_VirtualNetworkRule) * _ruleCount);
+			memcpy(_rules, rules, sizeof(ZT_VirtualNetworkRule) * _ruleCount);
 		}
 	}
 
 	/**
 	 * @return Rules -- see ruleCount() for size of array
 	 */
-	inline const ZT_VirtualNetworkRule *rules() const { return _rules; }
+	inline const ZT_VirtualNetworkRule* rules() const
+	{
+		return _rules;
+	}
 
 	/**
 	 * @return Number of rules in rules()
 	 */
-	inline unsigned int ruleCount() const { return _ruleCount; }
+	inline unsigned int ruleCount() const
+	{
+		return _ruleCount;
+	}
 
 	/**
 	 * @return ID and evaluation order of this capability in network
 	 */
-	inline uint32_t id() const { return _id; }
+	inline uint32_t id() const
+	{
+		return _id;
+	}
 
 	/**
 	 * @return Network ID for which this capability was issued
 	 */
-	inline uint64_t networkId() const { return _nwid; }
+	inline uint64_t networkId() const
+	{
+		return _nwid;
+	}
 
 	/**
 	 * @return Timestamp
 	 */
-	inline int64_t timestamp() const { return _ts; }
+	inline int64_t timestamp() const
+	{
+		return _ts;
+	}
 
 	/**
 	 * @return Last 'to' address in chain of custody
@@ -121,10 +133,11 @@ public:
 	inline Address issuedTo() const
 	{
 		Address i2;
-		for(unsigned int i=0;i<ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH;++i) {
-			if (!_custody[i].to) {
+		for (unsigned int i = 0; i < ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH; ++i) {
+			if (! _custody[i].to) {
 				return i2;
-			} else {
+			}
+			else {
 				i2 = _custody[i].to;
 			}
 		}
@@ -144,20 +157,22 @@ public:
 	 * @param to Recipient of this signature
 	 * @return True if signature successful and chain of custody appended
 	 */
-	inline bool sign(const Identity &from,const Address &to)
+	inline bool sign(const Identity& from, const Address& to)
 	{
 		try {
-			for(unsigned int i=0;((i<_maxCustodyChainLength)&&(i<ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH));++i) {
-				if (!(_custody[i].to)) {
+			for (unsigned int i = 0; ((i < _maxCustodyChainLength) && (i < ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH)); ++i) {
+				if (! (_custody[i].to)) {
 					Buffer<(sizeof(Capability) * 2)> tmp;
-					this->serialize(tmp,true);
+					this->serialize(tmp, true);
 					_custody[i].to = to;
 					_custody[i].from = from.address();
-					_custody[i].signature = from.sign(tmp.data(),tmp.size());
+					_custody[i].signature = from.sign(tmp.data(), tmp.size());
 					return true;
 				}
 			}
-		} catch ( ... ) {}
+		}
+		catch (...) {
+		}
 		return false;
 	}
 
@@ -167,17 +182,16 @@ public:
 	 * @param RR Runtime environment to provide for peer lookup, etc.
 	 * @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or chain
 	 */
-	int verify(const RuntimeEnvironment *RR,void *tPtr) const;
+	int verify(const RuntimeEnvironment* RR, void* tPtr) const;
 
-	template<unsigned int C>
-	static inline void serializeRules(Buffer<C> &b,const ZT_VirtualNetworkRule *rules,unsigned int ruleCount)
+	template <unsigned int C> static inline void serializeRules(Buffer<C>& b, const ZT_VirtualNetworkRule* rules, unsigned int ruleCount)
 	{
-		for(unsigned int i=0;i<ruleCount;++i) {
+		for (unsigned int i = 0; i < ruleCount; ++i) {
 			// Each rule consists of its 8-bit type followed by the size of that type's
 			// field followed by field data. The inclusion of the size will allow non-supported
 			// rules to be ignored but still parsed.
 			b.append((uint8_t)rules[i].t);
-			switch((ZT_VirtualNetworkRuleType)(rules[i].t & 0x3f)) {
+			switch ((ZT_VirtualNetworkRuleType)(rules[i].t & 0x3f)) {
 				default:
 					b.append((uint8_t)0);
 					break;
@@ -187,7 +201,7 @@ public:
 					b.append((uint8_t)14);
 					b.append((uint64_t)rules[i].v.fwd.address);
 					b.append((uint32_t)rules[i].v.fwd.flags);
-					b.append((uint16_t)rules[i].v.fwd.length); // unused for redirect
+					b.append((uint16_t)rules[i].v.fwd.length);	 // unused for redirect
 					break;
 				case ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS:
 				case ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS:
@@ -209,18 +223,18 @@ public:
 				case ZT_NETWORK_RULE_MATCH_MAC_SOURCE:
 				case ZT_NETWORK_RULE_MATCH_MAC_DEST:
 					b.append((uint8_t)6);
-					b.append(rules[i].v.mac,6);
+					b.append(rules[i].v.mac, 6);
 					break;
 				case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE:
 				case ZT_NETWORK_RULE_MATCH_IPV4_DEST:
 					b.append((uint8_t)5);
-					b.append(&(rules[i].v.ipv4.ip),4);
+					b.append(&(rules[i].v.ipv4.ip), 4);
 					b.append((uint8_t)rules[i].v.ipv4.mask);
 					break;
 				case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE:
 				case ZT_NETWORK_RULE_MATCH_IPV6_DEST:
 					b.append((uint8_t)17);
-					b.append(rules[i].v.ipv6.ip,16);
+					b.append(rules[i].v.ipv6.ip, 16);
 					b.append((uint8_t)rules[i].v.ipv6.mask);
 					break;
 				case ZT_NETWORK_RULE_MATCH_IP_TOS:
@@ -276,7 +290,7 @@ public:
 				case ZT_NETWORK_RULE_MATCH_INTEGER_RANGE:
 					b.append((uint8_t)19);
 					b.append((uint64_t)rules[i].v.intRange.start);
-					b.append((uint64_t)(rules[i].v.intRange.start + (uint64_t)rules[i].v.intRange.end)); // more future-proof
+					b.append((uint64_t)(rules[i].v.intRange.start + (uint64_t)rules[i].v.intRange.end));   // more future-proof
 					b.append((uint16_t)rules[i].v.intRange.idx);
 					b.append((uint8_t)rules[i].v.intRange.format);
 					break;
@@ -284,13 +298,12 @@ public:
 		}
 	}
 
-	template<unsigned int C>
-	static inline void deserializeRules(const Buffer<C> &b,unsigned int &p,ZT_VirtualNetworkRule *rules,unsigned int &ruleCount,const unsigned int maxRuleCount)
+	template <unsigned int C> static inline void deserializeRules(const Buffer<C>& b, unsigned int& p, ZT_VirtualNetworkRule* rules, unsigned int& ruleCount, const unsigned int maxRuleCount)
 	{
-		while ((ruleCount < maxRuleCount)&&(p < b.size())) {
+		while ((ruleCount < maxRuleCount) && (p < b.size())) {
 			rules[ruleCount].t = (uint8_t)b[p++];
 			const unsigned int fieldLen = (unsigned int)b[p++];
-			switch((ZT_VirtualNetworkRuleType)(rules[ruleCount].t & 0x3f)) {
+			switch ((ZT_VirtualNetworkRuleType)(rules[ruleCount].t & 0x3f)) {
 				default:
 					break;
 				case ZT_NETWORK_RULE_ACTION_TEE:
@@ -302,7 +315,7 @@ public:
 					break;
 				case ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS:
 				case ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS:
-					rules[ruleCount].v.zt = Address(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH).toInt();
+					rules[ruleCount].v.zt = Address(b.field(p, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH).toInt();
 					break;
 				case ZT_NETWORK_RULE_MATCH_VLAN_ID:
 					rules[ruleCount].v.vlanId = b.template at<uint16_t>(p);
@@ -315,22 +328,22 @@ public:
 					break;
 				case ZT_NETWORK_RULE_MATCH_MAC_SOURCE:
 				case ZT_NETWORK_RULE_MATCH_MAC_DEST:
-					memcpy(rules[ruleCount].v.mac,b.field(p,6),6);
+					memcpy(rules[ruleCount].v.mac, b.field(p, 6), 6);
 					break;
 				case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE:
 				case ZT_NETWORK_RULE_MATCH_IPV4_DEST:
-					memcpy(&(rules[ruleCount].v.ipv4.ip),b.field(p,4),4);
+					memcpy(&(rules[ruleCount].v.ipv4.ip), b.field(p, 4), 4);
 					rules[ruleCount].v.ipv4.mask = (uint8_t)b[p + 4];
 					break;
 				case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE:
 				case ZT_NETWORK_RULE_MATCH_IPV6_DEST:
-					memcpy(rules[ruleCount].v.ipv6.ip,b.field(p,16),16);
+					memcpy(rules[ruleCount].v.ipv6.ip, b.field(p, 16), 16);
 					rules[ruleCount].v.ipv6.mask = (uint8_t)b[p + 16];
 					break;
 				case ZT_NETWORK_RULE_MATCH_IP_TOS:
 					rules[ruleCount].v.ipTos.mask = (uint8_t)b[p];
-					rules[ruleCount].v.ipTos.value[0] = (uint8_t)b[p+1];
-					rules[ruleCount].v.ipTos.value[1] = (uint8_t)b[p+2];
+					rules[ruleCount].v.ipTos.value[0] = (uint8_t)b[p + 1];
+					rules[ruleCount].v.ipTos.value[1] = (uint8_t)b[p + 2];
 					break;
 				case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL:
 					rules[ruleCount].v.ipProtocol = (uint8_t)b[p];
@@ -340,8 +353,8 @@ public:
 					break;
 				case ZT_NETWORK_RULE_MATCH_ICMP:
 					rules[ruleCount].v.icmp.type = (uint8_t)b[p];
-					rules[ruleCount].v.icmp.code = (uint8_t)b[p+1];
-					rules[ruleCount].v.icmp.flags = (uint8_t)b[p+2];
+					rules[ruleCount].v.icmp.code = (uint8_t)b[p + 1];
+					rules[ruleCount].v.icmp.flags = (uint8_t)b[p + 2];
 					break;
 				case ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE:
 				case ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE:
@@ -380,8 +393,7 @@ public:
 		}
 	}
 
-	template<unsigned int C>
-	inline void serialize(Buffer<C> &b,const bool forSign = false) const
+	template <unsigned int C> inline void serialize(Buffer<C>& b, const bool forSign = false) const
 	{
 		if (forSign) {
 			b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
@@ -393,19 +405,20 @@ public:
 		b.append(_id);
 
 		b.append((uint16_t)_ruleCount);
-		serializeRules(b,_rules,_ruleCount);
+		serializeRules(b, _rules, _ruleCount);
 		b.append((uint8_t)_maxCustodyChainLength);
 
-		if (!forSign) {
-			for(unsigned int i=0;;++i) {
-				if ((i < _maxCustodyChainLength)&&(i < ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH)&&(_custody[i].to)) {
+		if (! forSign) {
+			for (unsigned int i = 0;; ++i) {
+				if ((i < _maxCustodyChainLength) && (i < ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH) && (_custody[i].to)) {
 					_custody[i].to.appendTo(b);
 					_custody[i].from.appendTo(b);
-					b.append((uint8_t)1); // 1 == Ed25519 signature
-					b.append((uint16_t)ZT_C25519_SIGNATURE_LEN); // length of signature
-					b.append(_custody[i].signature.data,ZT_C25519_SIGNATURE_LEN);
-				} else {
-					b.append((unsigned char)0,ZT_ADDRESS_LENGTH); // zero 'to' terminates chain
+					b.append((uint8_t)1);						   // 1 == Ed25519 signature
+					b.append((uint16_t)ZT_C25519_SIGNATURE_LEN);   // length of signature
+					b.append(_custody[i].signature.data, ZT_C25519_SIGNATURE_LEN);
+				}
+				else {
+					b.append((unsigned char)0, ZT_ADDRESS_LENGTH);	 // zero 'to' terminates chain
 					break;
 				}
 			}
@@ -419,8 +432,7 @@ public:
 		}
 	}
 
-	template<unsigned int C>
-	inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
+	template <unsigned int C> inline unsigned int deserialize(const Buffer<C>& b, unsigned int startAt = 0)
 	{
 		*this = Capability();
 
@@ -438,33 +450,34 @@ public:
 		if (rc > ZT_MAX_CAPABILITY_RULES) {
 			throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
 		}
-		deserializeRules(b,p,_rules,_ruleCount,rc);
+		deserializeRules(b, p, _rules, _ruleCount, rc);
 
 		_maxCustodyChainLength = (unsigned int)b[p++];
-		if ((_maxCustodyChainLength < 1)||(_maxCustodyChainLength > ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH)) {
+		if ((_maxCustodyChainLength < 1) || (_maxCustodyChainLength > ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH)) {
 			throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
 		}
 
-		for(unsigned int i=0;;++i) {
-			const Address to(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
+		for (unsigned int i = 0;; ++i) {
+			const Address to(b.field(p, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
 			p += ZT_ADDRESS_LENGTH;
-			if (!to) {
+			if (! to) {
 				break;
 			}
-			if ((i >= _maxCustodyChainLength)||(i >= ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH)) {
+			if ((i >= _maxCustodyChainLength) || (i >= ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH)) {
 				throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
 			}
 			_custody[i].to = to;
-			_custody[i].from.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
+			_custody[i].from.setTo(b.field(p, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
 			p += ZT_ADDRESS_LENGTH;
 			if (b[p++] == 1) {
 				if (b.template at<uint16_t>(p) != ZT_C25519_SIGNATURE_LEN) {
 					throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
 				}
 				p += 2;
-				memcpy(_custody[i].signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN);
+				memcpy(_custody[i].signature.data, b.field(p, ZT_C25519_SIGNATURE_LEN), ZT_C25519_SIGNATURE_LEN);
 				p += ZT_C25519_SIGNATURE_LEN;
-			} else {
+			}
+			else {
 				p += 2 + b.template at<uint16_t>(p);
 			}
 		}
@@ -478,12 +491,21 @@ public:
 	}
 
 	// Provides natural sort order by ID
-	inline bool operator<(const Capability &c) const { return (_id < c._id); }
+	inline bool operator<(const Capability& c) const
+	{
+		return (_id < c._id);
+	}
 
-	inline bool operator==(const Capability &c) const { return (memcmp(this,&c,sizeof(Capability)) == 0); }
-	inline bool operator!=(const Capability &c) const { return (memcmp(this,&c,sizeof(Capability)) != 0); }
+	inline bool operator==(const Capability& c) const
+	{
+		return (memcmp(this, &c, sizeof(Capability)) == 0);
+	}
+	inline bool operator!=(const Capability& c) const
+	{
+		return (memcmp(this, &c, sizeof(Capability)) != 0);
+	}
 
-private:
+  private:
 	uint64_t _nwid;
 	int64_t _ts;
 	uint32_t _id;
@@ -500,6 +522,6 @@ private:
 	} _custody[ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH];
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 29 - 27
node/CertificateOfMembership.cpp

@@ -12,15 +12,16 @@
 /****/
 
 #include "CertificateOfMembership.hpp"
-#include "RuntimeEnvironment.hpp"
-#include "Topology.hpp"
-#include "Switch.hpp"
+
 #include "Network.hpp"
 #include "Node.hpp"
+#include "RuntimeEnvironment.hpp"
+#include "Switch.hpp"
+#include "Topology.hpp"
 
 namespace ZeroTier {
 
-CertificateOfMembership::CertificateOfMembership(uint64_t timestamp,uint64_t timestampMaxDelta,uint64_t nwid,const Identity &issuedTo)
+CertificateOfMembership::CertificateOfMembership(uint64_t timestamp, uint64_t timestampMaxDelta, uint64_t nwid, const Identity& issuedTo)
 {
 	_qualifiers[0].id = COM_RESERVED_ID_TIMESTAMP;
 	_qualifiers[0].value = timestamp;
@@ -36,34 +37,34 @@ CertificateOfMembership::CertificateOfMembership(uint64_t timestamp,uint64_t tim
 	// using the original COM format. Format may be revised in the future to make this cleaner.
 	uint64_t idHash[6];
 	issuedTo.publicKeyHash(idHash);
-	for(unsigned long i=0;i<4;++i) {
+	for (unsigned long i = 0; i < 4; ++i) {
 		_qualifiers[i + 3].id = (uint64_t)(i + 3);
 		_qualifiers[i + 3].value = Utils::ntoh(idHash[i]);
 		_qualifiers[i + 3].maxDelta = 0xffffffffffffffffULL;
 	}
 
 	_qualifierCount = 7;
-	memset(_signature.data,0,ZT_C25519_SIGNATURE_LEN);
+	memset(_signature.data, 0, ZT_C25519_SIGNATURE_LEN);
 }
 
-bool CertificateOfMembership::agreesWith(const CertificateOfMembership &other, const Identity &otherIdentity) const
+bool CertificateOfMembership::agreesWith(const CertificateOfMembership& other, const Identity& otherIdentity) const
 {
-	if ((_qualifierCount == 0)||(other._qualifierCount == 0)) {
+	if ((_qualifierCount == 0) || (other._qualifierCount == 0)) {
 		return false;
 	}
 
-	std::map< uint64_t, uint64_t > otherFields;
-	for(unsigned int i=0;i<other._qualifierCount;++i) {
+	std::map<uint64_t, uint64_t> otherFields;
+	for (unsigned int i = 0; i < other._qualifierCount; ++i) {
 		otherFields[other._qualifiers[i].id] = other._qualifiers[i].value;
 	}
 
 	bool fullIdentityVerification = false;
-	for(unsigned int i=0;i<_qualifierCount;++i) {
+	for (unsigned int i = 0; i < _qualifierCount; ++i) {
 		const uint64_t qid = _qualifiers[i].id;
-		if ((qid >= 3)&&(qid <= 6)) {
+		if ((qid >= 3) && (qid <= 6)) {
 			fullIdentityVerification = true;
 		}
-		std::map< uint64_t, uint64_t >::iterator otherQ(otherFields.find(qid));
+		std::map<uint64_t, uint64_t>::iterator otherQ(otherFields.find(qid));
 		if (otherQ == otherFields.end()) {
 			return false;
 		}
@@ -79,8 +80,8 @@ bool CertificateOfMembership::agreesWith(const CertificateOfMembership &other, c
 	if (fullIdentityVerification) {
 		uint64_t idHash[6];
 		otherIdentity.publicKeyHash(idHash);
-		for(unsigned long i=0;i<4;++i) {
-			std::map< uint64_t, uint64_t >::iterator otherQ(otherFields.find((uint64_t)(i + 3)));
+		for (unsigned long i = 0; i < 4; ++i) {
+			std::map<uint64_t, uint64_t>::iterator otherQ(otherFields.find((uint64_t)(i + 3)));
 			if (otherQ == otherFields.end()) {
 				return false;
 			}
@@ -93,46 +94,47 @@ bool CertificateOfMembership::agreesWith(const CertificateOfMembership &other, c
 	return true;
 }
 
-bool CertificateOfMembership::sign(const Identity &with)
+bool CertificateOfMembership::sign(const Identity& with)
 {
 	uint64_t buf[ZT_NETWORK_COM_MAX_QUALIFIERS * 3];
 	unsigned int ptr = 0;
-	for(unsigned int i=0;i<_qualifierCount;++i) {
+	for (unsigned int i = 0; i < _qualifierCount; ++i) {
 		buf[ptr++] = Utils::hton(_qualifiers[i].id);
 		buf[ptr++] = Utils::hton(_qualifiers[i].value);
 		buf[ptr++] = Utils::hton(_qualifiers[i].maxDelta);
 	}
 
 	try {
-		_signature = with.sign(buf,ptr * sizeof(uint64_t));
+		_signature = with.sign(buf, ptr * sizeof(uint64_t));
 		_signedBy = with.address();
 		return true;
-	} catch ( ... ) {
+	}
+	catch (...) {
 		_signedBy.zero();
 		return false;
 	}
 }
 
-int CertificateOfMembership::verify(const RuntimeEnvironment *RR,void *tPtr) const
+int CertificateOfMembership::verify(const RuntimeEnvironment* RR, void* tPtr) const
 {
-	if ((!_signedBy)||(_signedBy != Network::controllerFor(networkId()))||(_qualifierCount > ZT_NETWORK_COM_MAX_QUALIFIERS)) {
+	if ((! _signedBy) || (_signedBy != Network::controllerFor(networkId())) || (_qualifierCount > ZT_NETWORK_COM_MAX_QUALIFIERS)) {
 		return -1;
 	}
 
-	const Identity id(RR->topology->getIdentity(tPtr,_signedBy));
-	if (!id) {
-		RR->sw->requestWhois(tPtr,RR->node->now(),_signedBy);
+	const Identity id(RR->topology->getIdentity(tPtr, _signedBy));
+	if (! id) {
+		RR->sw->requestWhois(tPtr, RR->node->now(), _signedBy);
 		return 1;
 	}
 
 	uint64_t buf[ZT_NETWORK_COM_MAX_QUALIFIERS * 3];
 	unsigned int ptr = 0;
-	for(unsigned int i=0;i<_qualifierCount;++i) {
+	for (unsigned int i = 0; i < _qualifierCount; ++i) {
 		buf[ptr++] = Utils::hton(_qualifiers[i].id);
 		buf[ptr++] = Utils::hton(_qualifiers[i].value);
 		buf[ptr++] = Utils::hton(_qualifiers[i].maxDelta);
 	}
-	return (id.verify(buf,ptr * sizeof(uint64_t),_signature) ? 0 : -1);
+	return (id.verify(buf, ptr * sizeof(uint64_t), _signature) ? 0 : -1);
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier

+ 75 - 56
node/CertificateOfMembership.hpp

@@ -14,21 +14,20 @@
 #ifndef ZT_CERTIFICATEOFMEMBERSHIP_HPP
 #define ZT_CERTIFICATEOFMEMBERSHIP_HPP
 
-#include <stdint.h>
-#include <string.h>
-
-#include <string>
-#include <stdexcept>
-#include <algorithm>
-
-#include "Constants.hpp"
-#include "Credential.hpp"
-#include "Buffer.hpp"
 #include "Address.hpp"
+#include "Buffer.hpp"
 #include "C25519.hpp"
+#include "Constants.hpp"
+#include "Credential.hpp"
 #include "Identity.hpp"
 #include "Utils.hpp"
 
+#include <algorithm>
+#include <stdexcept>
+#include <stdint.h>
+#include <string.h>
+#include <string>
+
 /**
  * Maximum number of qualifiers allowed in a COM (absolute max: 65535)
  */
@@ -64,10 +63,12 @@ class RuntimeEnvironment;
  * This is a memcpy()'able structure and is safe (in a crash sense) to modify
  * without locks.
  */
-class CertificateOfMembership : public Credential
-{
-public:
-	static inline Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_COM; }
+class CertificateOfMembership : public Credential {
+  public:
+	static inline Credential::Type credentialType()
+	{
+		return Credential::CREDENTIAL_TYPE_COM;
+	}
 
 	/**
 	 * Reserved qualifier IDs
@@ -78,8 +79,7 @@ public:
 	 * Addition of new required fields requires that code in hasRequiredFields
 	 * be updated as well.
 	 */
-	enum ReservedId
-	{
+	enum ReservedId {
 		/**
 		 * Timestamp of certificate
 		 */
@@ -101,8 +101,9 @@ public:
 	/**
 	 * Create an empty certificate of membership
 	 */
-	CertificateOfMembership() :
-		_qualifierCount(0) {}
+	CertificateOfMembership() : _qualifierCount(0)
+	{
+	}
 
 	/**
 	 * Create from required fields common to all networks
@@ -112,7 +113,7 @@ public:
 	 * @param nwid Network ID
 	 * @param issuedTo Certificate recipient
 	 */
-	CertificateOfMembership(uint64_t timestamp,uint64_t timestampMaxDelta,uint64_t nwid,const Identity &issuedTo);
+	CertificateOfMembership(uint64_t timestamp, uint64_t timestampMaxDelta, uint64_t nwid, const Identity& issuedTo);
 
 	/**
 	 * Create from binary-serialized COM in buffer
@@ -120,28 +121,33 @@ public:
 	 * @param b Buffer to deserialize from
 	 * @param startAt Position to start in buffer
 	 */
-	template<unsigned int C>
-	CertificateOfMembership(const Buffer<C> &b,unsigned int startAt = 0)
+	template <unsigned int C> CertificateOfMembership(const Buffer<C>& b, unsigned int startAt = 0)
 	{
-		deserialize(b,startAt);
+		deserialize(b, startAt);
 	}
 
 	/**
 	 * @return True if there's something here
 	 */
-	inline operator bool() const { return (_qualifierCount != 0); }
+	inline operator bool() const
+	{
+		return (_qualifierCount != 0);
+	}
 
 	/**
 	 * @return Credential ID, always 0 for COMs
 	 */
-	inline uint32_t id() const { return 0; }
+	inline uint32_t id() const
+	{
+		return 0;
+	}
 
 	/**
 	 * @return Timestamp for this cert and maximum delta for timestamp
 	 */
 	inline int64_t timestamp() const
 	{
-		for(unsigned int i=0;i<_qualifierCount;++i) {
+		for (unsigned int i = 0; i < _qualifierCount; ++i) {
 			if (_qualifiers[i].id == COM_RESERVED_ID_TIMESTAMP) {
 				return _qualifiers[i].value;
 			}
@@ -154,7 +160,7 @@ public:
 	 */
 	inline Address issuedTo() const
 	{
-		for(unsigned int i=0;i<_qualifierCount;++i) {
+		for (unsigned int i = 0; i < _qualifierCount; ++i) {
 			if (_qualifiers[i].id == COM_RESERVED_ID_ISSUED_TO) {
 				return Address(_qualifiers[i].value);
 			}
@@ -167,7 +173,7 @@ public:
 	 */
 	inline uint64_t networkId() const
 	{
-		for(unsigned int i=0;i<_qualifierCount;++i) {
+		for (unsigned int i = 0; i < _qualifierCount; ++i) {
 			if (_qualifiers[i].id == COM_RESERVED_ID_NETWORK_ID) {
 				return _qualifiers[i].value;
 			}
@@ -189,7 +195,7 @@ public:
 	 * @param otherIdentity Identity of other node
 	 * @return True if certs agree and 'other' may be communicated with
 	 */
-	bool agreesWith(const CertificateOfMembership &other, const Identity &otherIdentity) const;
+	bool agreesWith(const CertificateOfMembership& other, const Identity& otherIdentity) const;
 
 	/**
 	 * Sign this certificate
@@ -197,7 +203,7 @@ public:
 	 * @param with Identity to sign with, must include private key
 	 * @return True if signature was successful
 	 */
-	bool sign(const Identity &with);
+	bool sign(const Identity& with);
 
 	/**
 	 * Verify this COM and its signature
@@ -206,36 +212,40 @@ public:
 	 * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
 	 * @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or credential
 	 */
-	int verify(const RuntimeEnvironment *RR,void *tPtr) const;
+	int verify(const RuntimeEnvironment* RR, void* tPtr) const;
 
 	/**
 	 * @return True if signed
 	 */
-	inline bool isSigned() const { return (_signedBy); }
+	inline bool isSigned() const
+	{
+		return (_signedBy);
+	}
 
 	/**
 	 * @return Address that signed this certificate or null address if none
 	 */
-	inline const Address &signedBy() const { return _signedBy; }
+	inline const Address& signedBy() const
+	{
+		return _signedBy;
+	}
 
-	template<unsigned int C>
-	inline void serialize(Buffer<C> &b) const
+	template <unsigned int C> inline void serialize(Buffer<C>& b) const
 	{
 		b.append((uint8_t)1);
 		b.append((uint16_t)_qualifierCount);
-		for(unsigned int i=0;i<_qualifierCount;++i) {
+		for (unsigned int i = 0; i < _qualifierCount; ++i) {
 			b.append(_qualifiers[i].id);
 			b.append(_qualifiers[i].value);
 			b.append(_qualifiers[i].maxDelta);
 		}
 		_signedBy.appendTo(b);
 		if (_signedBy) {
-			b.append(_signature.data,ZT_C25519_SIGNATURE_LEN);
+			b.append(_signature.data, ZT_C25519_SIGNATURE_LEN);
 		}
 	}
 
-	template<unsigned int C>
-	inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
+	template <unsigned int C> inline unsigned int deserialize(const Buffer<C>& b, unsigned int startAt = 0)
 	{
 		unsigned int p = startAt;
 
@@ -249,11 +259,12 @@ public:
 		unsigned int numq = b.template at<uint16_t>(p);
 		p += sizeof(uint16_t);
 		uint64_t lastId = 0;
-		for(unsigned int i=0;i<numq;++i) {
+		for (unsigned int i = 0; i < numq; ++i) {
 			const uint64_t qid = b.template at<uint64_t>(p);
 			if (qid < lastId) {
 				throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_BAD_ENCODING;
-			} else {
+			}
+			else {
 				lastId = qid;
 			}
 			if (_qualifierCount < ZT_NETWORK_COM_MAX_QUALIFIERS) {
@@ -262,23 +273,24 @@ public:
 				_qualifiers[_qualifierCount].maxDelta = b.template at<uint64_t>(p + 16);
 				p += 24;
 				++_qualifierCount;
-			} else {
+			}
+			else {
 				throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
 			}
 		}
 
-		_signedBy.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
+		_signedBy.setTo(b.field(p, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
 		p += ZT_ADDRESS_LENGTH;
 
 		if (_signedBy) {
-			memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN);
+			memcpy(_signature.data, b.field(p, ZT_C25519_SIGNATURE_LEN), ZT_C25519_SIGNATURE_LEN);
 			p += ZT_C25519_SIGNATURE_LEN;
 		}
 
 		return (p - startAt);
 	}
 
-	inline bool operator==(const CertificateOfMembership &c) const
+	inline bool operator==(const CertificateOfMembership& c) const
 	{
 		if (_signedBy != c._signedBy) {
 			return false;
@@ -286,25 +298,32 @@ public:
 		if (_qualifierCount != c._qualifierCount) {
 			return false;
 		}
-		for(unsigned int i=0;i<_qualifierCount;++i) {
-			const _Qualifier &a = _qualifiers[i];
-			const _Qualifier &b = c._qualifiers[i];
-			if ((a.id != b.id)||(a.value != b.value)||(a.maxDelta != b.maxDelta)) {
+		for (unsigned int i = 0; i < _qualifierCount; ++i) {
+			const _Qualifier& a = _qualifiers[i];
+			const _Qualifier& b = c._qualifiers[i];
+			if ((a.id != b.id) || (a.value != b.value) || (a.maxDelta != b.maxDelta)) {
 				return false;
 			}
 		}
-		return (memcmp(_signature.data,c._signature.data,ZT_C25519_SIGNATURE_LEN) == 0);
+		return (memcmp(_signature.data, c._signature.data, ZT_C25519_SIGNATURE_LEN) == 0);
 	}
-	inline bool operator!=(const CertificateOfMembership &c) const { return (!(*this == c)); }
-
-private:
-	struct _Qualifier
+	inline bool operator!=(const CertificateOfMembership& c) const
 	{
-		_Qualifier() : id(0),value(0),maxDelta(0) {}
+		return (! (*this == c));
+	}
+
+  private:
+	struct _Qualifier {
+		_Qualifier() : id(0), value(0), maxDelta(0)
+		{
+		}
 		uint64_t id;
 		uint64_t value;
 		uint64_t maxDelta;
-		inline bool operator<(const _Qualifier &q) const { return (id < q.id); } // sort order
+		inline bool operator<(const _Qualifier& q) const
+		{
+			return (id < q.id);
+		}	// sort order
 	};
 
 	Address _signedBy;
@@ -313,6 +332,6 @@ private:
 	C25519::Signature _signature;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 17 - 15
node/CertificateOfOwnership.cpp

@@ -12,41 +12,43 @@
 /****/
 
 #include "CertificateOfOwnership.hpp"
-#include "RuntimeEnvironment.hpp"
+
 #include "Identity.hpp"
-#include "Topology.hpp"
-#include "Switch.hpp"
 #include "Network.hpp"
 #include "Node.hpp"
+#include "RuntimeEnvironment.hpp"
+#include "Switch.hpp"
+#include "Topology.hpp"
 
 namespace ZeroTier {
 
-int CertificateOfOwnership::verify(const RuntimeEnvironment *RR,void *tPtr) const
+int CertificateOfOwnership::verify(const RuntimeEnvironment* RR, void* tPtr) const
 {
-	if ((!_signedBy)||(_signedBy != Network::controllerFor(_networkId))) {
+	if ((! _signedBy) || (_signedBy != Network::controllerFor(_networkId))) {
 		return -1;
 	}
-	const Identity id(RR->topology->getIdentity(tPtr,_signedBy));
-	if (!id) {
-		RR->sw->requestWhois(tPtr,RR->node->now(),_signedBy);
+	const Identity id(RR->topology->getIdentity(tPtr, _signedBy));
+	if (! id) {
+		RR->sw->requestWhois(tPtr, RR->node->now(), _signedBy);
 		return 1;
 	}
 	try {
 		Buffer<(sizeof(CertificateOfOwnership) + 64)> tmp;
-		this->serialize(tmp,true);
-		return (id.verify(tmp.data(),tmp.size(),_signature) ? 0 : -1);
-	} catch ( ... ) {
+		this->serialize(tmp, true);
+		return (id.verify(tmp.data(), tmp.size(), _signature) ? 0 : -1);
+	}
+	catch (...) {
 		return -1;
 	}
 }
 
-bool CertificateOfOwnership::_owns(const CertificateOfOwnership::Thing &t,const void *v,unsigned int l) const
+bool CertificateOfOwnership::_owns(const CertificateOfOwnership::Thing& t, const void* v, unsigned int l) const
 {
-	for(unsigned int i=0,j=_thingCount;i<j;++i) {
+	for (unsigned int i = 0, j = _thingCount; i < j; ++i) {
 		if (_thingTypes[i] == (uint8_t)t) {
 			unsigned int k = 0;
 			while (k < l) {
-				if (reinterpret_cast<const uint8_t *>(v)[k] != _thingValues[i][k]) {
+				if (reinterpret_cast<const uint8_t*>(v)[k] != _thingValues[i][k]) {
 					break;
 				}
 				++k;
@@ -59,4 +61,4 @@ bool CertificateOfOwnership::_owns(const CertificateOfOwnership::Thing &t,const
 	return false;
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier

+ 94 - 68
node/CertificateOfOwnership.hpp

@@ -14,20 +14,20 @@
 #ifndef ZT_CERTIFICATEOFOWNERSHIP_HPP
 #define ZT_CERTIFICATEOFOWNERSHIP_HPP
 
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
+#include "Address.hpp"
+#include "Buffer.hpp"
+#include "C25519.hpp"
 #include "Constants.hpp"
 #include "Credential.hpp"
-#include "C25519.hpp"
-#include "Address.hpp"
 #include "Identity.hpp"
-#include "Buffer.hpp"
 #include "InetAddress.hpp"
 #include "MAC.hpp"
 
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
 // Max things per CertificateOfOwnership
 #define ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS 16
 
@@ -41,84 +41,102 @@ class RuntimeEnvironment;
 /**
  * Certificate indicating ownership of a network identifier
  */
-class CertificateOfOwnership : public Credential
-{
-public:
-	static inline Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_COO; }
-
-	enum Thing
+class CertificateOfOwnership : public Credential {
+  public:
+	static inline Credential::Type credentialType()
 	{
-		THING_NULL = 0,
-		THING_MAC_ADDRESS = 1,
-		THING_IPV4_ADDRESS = 2,
-		THING_IPV6_ADDRESS = 3
-	};
+		return Credential::CREDENTIAL_TYPE_COO;
+	}
+
+	enum Thing { THING_NULL = 0, THING_MAC_ADDRESS = 1, THING_IPV4_ADDRESS = 2, THING_IPV6_ADDRESS = 3 };
 
 	CertificateOfOwnership()
 	{
-		memset(reinterpret_cast<void *>(this),0,sizeof(CertificateOfOwnership));
+		memset(reinterpret_cast<void*>(this), 0, sizeof(CertificateOfOwnership));
 	}
 
-	CertificateOfOwnership(const uint64_t nwid,const int64_t ts,const Address &issuedTo,const uint32_t id)
+	CertificateOfOwnership(const uint64_t nwid, const int64_t ts, const Address& issuedTo, const uint32_t id)
 	{
-		memset(reinterpret_cast<void *>(this),0,sizeof(CertificateOfOwnership));
+		memset(reinterpret_cast<void*>(this), 0, sizeof(CertificateOfOwnership));
 		_networkId = nwid;
 		_ts = ts;
 		_id = id;
 		_issuedTo = issuedTo;
 	}
 
-	inline uint64_t networkId() const { return _networkId; }
-	inline int64_t timestamp() const { return _ts; }
-	inline uint32_t id() const { return _id; }
-	inline unsigned int thingCount() const { return (unsigned int)_thingCount; }
+	inline uint64_t networkId() const
+	{
+		return _networkId;
+	}
+	inline int64_t timestamp() const
+	{
+		return _ts;
+	}
+	inline uint32_t id() const
+	{
+		return _id;
+	}
+	inline unsigned int thingCount() const
+	{
+		return (unsigned int)_thingCount;
+	}
 
-	inline Thing thingType(const unsigned int i) const { return (Thing)_thingTypes[i]; }
-	inline const uint8_t *thingValue(const unsigned int i) const { return _thingValues[i]; }
+	inline Thing thingType(const unsigned int i) const
+	{
+		return (Thing)_thingTypes[i];
+	}
+	inline const uint8_t* thingValue(const unsigned int i) const
+	{
+		return _thingValues[i];
+	}
 
-	inline const Address &issuedTo() const { return _issuedTo; }
+	inline const Address& issuedTo() const
+	{
+		return _issuedTo;
+	}
 
-	inline bool owns(const InetAddress &ip) const
+	inline bool owns(const InetAddress& ip) const
 	{
 		if (ip.ss_family == AF_INET) {
-			return this->_owns(THING_IPV4_ADDRESS,&(reinterpret_cast<const struct sockaddr_in *>(&ip)->sin_addr.s_addr),4);
+			return this->_owns(THING_IPV4_ADDRESS, &(reinterpret_cast<const struct sockaddr_in*>(&ip)->sin_addr.s_addr), 4);
 		}
 		if (ip.ss_family == AF_INET6) {
-			return this->_owns(THING_IPV6_ADDRESS,reinterpret_cast<const struct sockaddr_in6 *>(&ip)->sin6_addr.s6_addr,16);
+			return this->_owns(THING_IPV6_ADDRESS, reinterpret_cast<const struct sockaddr_in6*>(&ip)->sin6_addr.s6_addr, 16);
 		}
 		return false;
 	}
 
-	inline bool owns(const MAC &mac) const
+	inline bool owns(const MAC& mac) const
 	{
 		uint8_t tmp[6];
-		mac.copyTo(tmp,6);
-		return this->_owns(THING_MAC_ADDRESS,tmp,6);
+		mac.copyTo(tmp, 6);
+		return this->_owns(THING_MAC_ADDRESS, tmp, 6);
 	}
 
-	inline void addThing(const InetAddress &ip)
+	inline void addThing(const InetAddress& ip)
 	{
 		if (_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) {
 			return;
 		}
 		if (ip.ss_family == AF_INET) {
 			_thingTypes[_thingCount] = THING_IPV4_ADDRESS;
-			memcpy(_thingValues[_thingCount],&(reinterpret_cast<const struct sockaddr_in *>(&ip)->sin_addr.s_addr),4);
+			memcpy(_thingValues[_thingCount], &(reinterpret_cast<const struct sockaddr_in*>(&ip)->sin_addr.s_addr), 4);
 			++_thingCount;
-		} else if (ip.ss_family == AF_INET6) {
+		}
+		else if (ip.ss_family == AF_INET6) {
 			_thingTypes[_thingCount] = THING_IPV6_ADDRESS;
-			memcpy(_thingValues[_thingCount],reinterpret_cast<const struct sockaddr_in6 *>(&ip)->sin6_addr.s6_addr,16);
+			memcpy(_thingValues[_thingCount], reinterpret_cast<const struct sockaddr_in6*>(&ip)->sin6_addr.s6_addr, 16);
 			++_thingCount;
 		}
 	}
 
-	inline void addThing(const MAC &mac)
+	inline void addThing(const MAC& mac)
 	{
 		if (_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) {
 			return;
 		}
 		_thingTypes[_thingCount] = THING_MAC_ADDRESS;
-		mac.copyTo(_thingValues[_thingCount],6);
+		mac.copyTo(_thingValues[_thingCount], 6);
 		++_thingCount;
 	}
 
@@ -126,13 +144,13 @@ public:
 	 * @param signer Signing identity, must have private key
 	 * @return True if signature was successful
 	 */
-	inline bool sign(const Identity &signer)
+	inline bool sign(const Identity& signer)
 	{
 		if (signer.hasPrivate()) {
 			Buffer<sizeof(CertificateOfOwnership) + 64> tmp;
 			_signedBy = signer.address();
-			this->serialize(tmp,true);
-			_signature = signer.sign(tmp.data(),tmp.size());
+			this->serialize(tmp, true);
+			_signature = signer.sign(tmp.data(), tmp.size());
 			return true;
 		}
 		return false;
@@ -143,10 +161,9 @@ public:
 	 * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
 	 * @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature
 	 */
-	int verify(const RuntimeEnvironment *RR,void *tPtr) const;
+	int verify(const RuntimeEnvironment* RR, void* tPtr) const;
 
-	template<unsigned int C>
-	inline void serialize(Buffer<C> &b,const bool forSign = false) const
+	template <unsigned int C> inline void serialize(Buffer<C>& b, const bool forSign = false) const
 	{
 		if (forSign) {
 			b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
@@ -157,28 +174,27 @@ public:
 		b.append(_flags);
 		b.append(_id);
 		b.append((uint16_t)_thingCount);
-		for(unsigned int i=0,j=_thingCount;i<j;++i) {
+		for (unsigned int i = 0, j = _thingCount; i < j; ++i) {
 			b.append((uint8_t)_thingTypes[i]);
-			b.append(_thingValues[i],ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE);
+			b.append(_thingValues[i], ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE);
 		}
 
 		_issuedTo.appendTo(b);
 		_signedBy.appendTo(b);
-		if (!forSign) {
-			b.append((uint8_t)1); // 1 == Ed25519
-			b.append((uint16_t)ZT_C25519_SIGNATURE_LEN); // length of signature
-			b.append(_signature.data,ZT_C25519_SIGNATURE_LEN);
+		if (! forSign) {
+			b.append((uint8_t)1);						   // 1 == Ed25519
+			b.append((uint16_t)ZT_C25519_SIGNATURE_LEN);   // length of signature
+			b.append(_signature.data, ZT_C25519_SIGNATURE_LEN);
 		}
 
-		b.append((uint16_t)0); // length of additional fields, currently 0
+		b.append((uint16_t)0);	 // length of additional fields, currently 0
 
 		if (forSign) {
 			b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
 		}
 	}
 
-	template<unsigned int C>
-	inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
+	template <unsigned int C> inline unsigned int deserialize(const Buffer<C>& b, unsigned int startAt = 0)
 	{
 		unsigned int p = startAt;
 
@@ -194,26 +210,27 @@ public:
 		p += 4;
 		_thingCount = b.template at<uint16_t>(p);
 		p += 2;
-		for(unsigned int i=0,j=_thingCount;i<j;++i) {
+		for (unsigned int i = 0, j = _thingCount; i < j; ++i) {
 			if (i < ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) {
 				_thingTypes[i] = (uint8_t)b[p++];
-				memcpy(_thingValues[i],b.field(p,ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE),ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE);
+				memcpy(_thingValues[i], b.field(p, ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE), ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE);
 				p += ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE;
 			}
 		}
 
-		_issuedTo.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
+		_issuedTo.setTo(b.field(p, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
 		p += ZT_ADDRESS_LENGTH;
-		_signedBy.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
+		_signedBy.setTo(b.field(p, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
 		p += ZT_ADDRESS_LENGTH;
 		if (b[p++] == 1) {
 			if (b.template at<uint16_t>(p) != ZT_C25519_SIGNATURE_LEN) {
 				throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
 			}
 			p += 2;
-			memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN);
+			memcpy(_signature.data, b.field(p, ZT_C25519_SIGNATURE_LEN), ZT_C25519_SIGNATURE_LEN);
 			p += ZT_C25519_SIGNATURE_LEN;
-		} else {
+		}
+		else {
 			p += 2 + b.template at<uint16_t>(p);
 		}
 
@@ -226,13 +243,22 @@ public:
 	}
 
 	// Provides natural sort order by ID
-	inline bool operator<(const CertificateOfOwnership &coo) const { return (_id < coo._id); }
+	inline bool operator<(const CertificateOfOwnership& coo) const
+	{
+		return (_id < coo._id);
+	}
 
-	inline bool operator==(const CertificateOfOwnership &coo) const { return (memcmp(this,&coo,sizeof(CertificateOfOwnership)) == 0); }
-	inline bool operator!=(const CertificateOfOwnership &coo) const { return (memcmp(this,&coo,sizeof(CertificateOfOwnership)) != 0); }
+	inline bool operator==(const CertificateOfOwnership& coo) const
+	{
+		return (memcmp(this, &coo, sizeof(CertificateOfOwnership)) == 0);
+	}
+	inline bool operator!=(const CertificateOfOwnership& coo) const
+	{
+		return (memcmp(this, &coo, sizeof(CertificateOfOwnership)) != 0);
+	}
 
-private:
-	bool _owns(const Thing &t,const void *v,unsigned int l) const;
+  private:
+	bool _owns(const Thing& t, const void* v, unsigned int l) const;
 
 	uint64_t _networkId;
 	int64_t _ts;
@@ -246,6 +272,6 @@ private:
 	C25519::Signature _signature;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 49 - 49
node/Constants.hpp

@@ -61,8 +61,8 @@
 #ifdef ZT_SSO_SUPPORTED
 #define ZT_SSO_ENABLED 1
 #endif
-#define likely(x) __builtin_expect((x),1)
-#define unlikely(x) __builtin_expect((x),0)
+#define likely(x)	__builtin_expect((x), 1)
+#define unlikely(x) __builtin_expect((x), 0)
 #include <TargetConditionals.h>
 #ifndef __UNIX_LIKE__
 #define __UNIX_LIKE__
@@ -85,9 +85,9 @@
 #endif
 #include <machine/endian.h>
 #ifndef __BYTE_ORDER
-#define __BYTE_ORDER _BYTE_ORDER
+#define __BYTE_ORDER	_BYTE_ORDER
 #define __LITTLE_ENDIAN _LITTLE_ENDIAN
-#define __BIG_ENDIAN _BIG_ENDIAN
+#define __BIG_ENDIAN	_BIG_ENDIAN
 #endif
 #endif
 
@@ -106,25 +106,25 @@
 #pragma warning(disable : 4101)
 #undef __UNIX_LIKE__
 #undef __BSD__
-#include <winsock2.h>
 #include <windows.h>
+#include <winsock2.h>
 #endif
 
 #ifdef __NetBSD__
 #ifndef RTF_MULTICAST
-#define RTF_MULTICAST   0x20000000
+#define RTF_MULTICAST 0x20000000
 #endif
 #endif
 
 #if (defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) || defined(__AMD64__) || defined(_M_X64))
 #define ZT_ARCH_X64 1
-#include <xmmintrin.h>
 #include <emmintrin.h>
 #include <immintrin.h>
+#include <xmmintrin.h>
 #endif
 
 #if (defined(__ARM_NEON) || defined(__ARM_NEON__) || defined(ZT_ARCH_ARM_HAS_NEON))
-#if (defined(__APPLE__) && !defined(__LP64__)) || (defined(__ANDROID__) && defined(__arm__))
+#if (defined(__APPLE__) && ! defined(__LP64__)) || (defined(__ANDROID__) && defined(__arm__))
 #ifdef ZT_ARCH_ARM_HAS_NEON
 #undef ZT_ARCH_ARM_HAS_NEON
 #endif
@@ -145,7 +145,8 @@
 #endif
 
 // Define ZT_NO_TYPE_PUNNING to disable reckless casts on anything other than x86/x64.
-#if (!(defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_AMD64) || defined(_M_X64) || defined(i386) || defined(__i386) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(_M_IX86) || defined(__X86__) || defined(_X86_) || defined(__I86__) || defined(__INTEL__) || defined(__386)))
+#if (! (defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_AMD64) || defined(_M_X64) || defined(i386) || defined(__i386) || defined(__i386__) || defined(__i486__) || defined(__i586__)          \
+		|| defined(__i686__) || defined(_M_IX86) || defined(__X86__) || defined(_X86_) || defined(__I86__) || defined(__INTEL__) || defined(__386)))
 #ifndef ZT_NO_TYPE_PUNNING
 #define ZT_NO_TYPE_PUNNING 1
 #endif
@@ -157,23 +158,23 @@
 #endif
 
 // Assume little endian if not defined
-#if (defined(__APPLE__) || defined(__WINDOWS__)) && (!defined(__BYTE_ORDER))
+#if (defined(__APPLE__) || defined(__WINDOWS__)) && (! defined(__BYTE_ORDER))
 #undef __BYTE_ORDER
 #undef __LITTLE_ENDIAN
 #undef __BIG_ENDIAN
-#define __BIG_ENDIAN 4321
+#define __BIG_ENDIAN	4321
 #define __LITTLE_ENDIAN 1234
-#define __BYTE_ORDER 1234
+#define __BYTE_ORDER	1234
 #endif
 
 #ifdef __WINDOWS__
-#define ZT_PATH_SEPARATOR '\\'
+#define ZT_PATH_SEPARATOR	'\\'
 #define ZT_PATH_SEPARATOR_S "\\"
-#define ZT_EOL_S "\r\n"
+#define ZT_EOL_S			"\r\n"
 #else
-#define ZT_PATH_SEPARATOR '/'
+#define ZT_PATH_SEPARATOR	'/'
 #define ZT_PATH_SEPARATOR_S "/"
-#define ZT_EOL_S "\n"
+#define ZT_EOL_S			"\n"
 #endif
 
 #ifndef __BYTE_ORDER
@@ -182,10 +183,10 @@
 
 #if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__)
 #ifndef likely
-#define likely(x) __builtin_expect((x),1)
+#define likely(x) __builtin_expect((x), 1)
 #endif
 #ifndef unlikely
-#define unlikely(x) __builtin_expect((x),0)
+#define unlikely(x) __builtin_expect((x), 0)
 #endif
 #else
 #ifndef likely
@@ -197,43 +198,43 @@
 #endif
 
 #ifdef __WINDOWS__
-#define ZT_PACKED_STRUCT(D) __pragma(pack(push,1)) D __pragma(pack(pop))
+#define ZT_PACKED_STRUCT(D) __pragma(pack(push, 1)) D __pragma(pack(pop))
 #else
 #define ZT_PACKED_STRUCT(D) D __attribute__((packed))
 #endif
 
 #if defined(_WIN32)
-#define ZT_PLATFORM_NAME "windows" // Windows
+#define ZT_PLATFORM_NAME "windows"	 // Windows
 #elif defined(_WIN64)
-#define ZT_PLATFORM_NAME "windows" // Windows
+#define ZT_PLATFORM_NAME "windows"	 // Windows
 #elif defined(__CYGWIN__)
-#define ZT_PLATFORM_NAME "windows" // Windows (Cygwin POSIX under Microsoft Window)
+#define ZT_PLATFORM_NAME "windows"	 // Windows (Cygwin POSIX under Microsoft Window)
 #elif defined(__ANDROID__)
-#define ZT_PLATFORM_NAME "android" // Android (implies Linux, so it must come first)
+#define ZT_PLATFORM_NAME "android"	 // Android (implies Linux, so it must come first)
 #elif defined(__linux__)
-#define ZT_PLATFORM_NAME "linux" // Debian, Ubuntu, Gentoo, Fedora, openSUSE, RedHat, Centos and other
-#elif defined(__unix__) || !defined(__APPLE__) && defined(__MACH__)
+#define ZT_PLATFORM_NAME "linux"   // Debian, Ubuntu, Gentoo, Fedora, openSUSE, RedHat, Centos and other
+#elif defined(__unix__) || ! defined(__APPLE__) && defined(__MACH__)
 #include <sys/param.h>
 #if defined(BSD)
-#define ZT_PLATFORM_NAME "bsd" // FreeBSD, NetBSD, OpenBSD, DragonFly BSD
+#define ZT_PLATFORM_NAME "bsd"	 // FreeBSD, NetBSD, OpenBSD, DragonFly BSD
 #endif
 #elif defined(__hpux)
-#define ZT_PLATFORM_NAME "hp-ux" // HP-UX
+#define ZT_PLATFORM_NAME "hp-ux"   // HP-UX
 #elif defined(_AIX)
-#define ZT_PLATFORM_NAME "aix" // IBM AIX
-#elif defined(__APPLE__) && defined(__MACH__) // Apple OSX and iOS (Darwin)
+#define ZT_PLATFORM_NAME "aix"					// IBM AIX
+#elif defined(__APPLE__) && defined(__MACH__)	// Apple OSX and iOS (Darwin)
 #include <TargetConditionals.h>
 #if defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR == 1
-#define ZT_PLATFORM_NAME "ios_sim" // Apple iOS
+#define ZT_PLATFORM_NAME "ios_sim"	 // Apple iOS
 #elif defined(TARGET_OS_IPAD) && TARGET_OS_IPAD == 1
 #define ZT_PLATFORM_NAME "ios_ipad"
 #elif defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1
-#define ZT_PLATFORM_NAME "ios_iphone" // Apple iOS
+#define ZT_PLATFORM_NAME "ios_iphone"	// Apple iOS
 #elif defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1
-#define ZT_PLATFORM_NAME "macos" // Apple OSX
+#define ZT_PLATFORM_NAME "macos"   // Apple OSX
 #endif
 #elif defined(__sun) && defined(__SVR4)
-#define ZT_PLATFORM_NAME "solaris" // Oracle Solaris, Open Indiana
+#define ZT_PLATFORM_NAME "solaris"	 // Oracle Solaris, Open Indiana
 #else
 #define ZT_PLATFORM_NAME "unknown"
 #endif
@@ -255,7 +256,7 @@
 #define ZT_ARCH_NAME "mips"
 #elif defined(__riscv) || defined(__riscv_xlen)
 #define ZT_ARCH_NAME "riscv"
-#elif defined(__powerpc__) || defined(__powerpc64__) || defined(__ppc__) || defined(__ppc64__) || defined (_M_PPC)
+#elif defined(__powerpc__) || defined(__powerpc64__) || defined(__ppc__) || defined(__ppc64__) || defined(_M_PPC)
 #define ZT_ARCH_NAME "powerpc"
 #elif defined(__s390__) || defined(__s390x__) || defined(__zarch__)
 #define ZT_ARCH_NAME "s390"
@@ -580,23 +581,23 @@
 /**
  * Drainage constants for VERB_ECHO rate-limiters
  */
-#define ZT_ECHO_CUTOFF_LIMIT ((1000 / ZT_CORE_TIMER_TASK_GRANULARITY) * ZT_MAX_PEER_NETWORK_PATHS)
+#define ZT_ECHO_CUTOFF_LIMIT	 ((1000 / ZT_CORE_TIMER_TASK_GRANULARITY) * ZT_MAX_PEER_NETWORK_PATHS)
 #define ZT_ECHO_DRAINAGE_DIVISOR (1000 / ZT_ECHO_CUTOFF_LIMIT)
 
 /**
  * Drainage constants for VERB_QOS rate-limiters
  */
-#define ZT_QOS_CUTOFF_LIMIT ((1000 / ZT_CORE_TIMER_TASK_GRANULARITY) * ZT_MAX_PEER_NETWORK_PATHS)
+#define ZT_QOS_CUTOFF_LIMIT		((1000 / ZT_CORE_TIMER_TASK_GRANULARITY) * ZT_MAX_PEER_NETWORK_PATHS)
 #define ZT_QOS_DRAINAGE_DIVISOR (1000 / ZT_QOS_CUTOFF_LIMIT)
 
 /**
  * Drainage constants for VERB_ACK rate-limiters
  */
-#define ZT_ACK_CUTOFF_LIMIT 128
+#define ZT_ACK_CUTOFF_LIMIT		128
 #define ZT_ACK_DRAINAGE_DIVISOR (1000 / ZT_ACK_CUTOFF_LIMIT)
 
 #define ZT_BOND_DEFAULT_REFRACTORY_PERIOD 8000
-#define ZT_BOND_MAX_REFRACTORY_PERIOD 600000
+#define ZT_BOND_MAX_REFRACTORY_PERIOD	  600000
 
 /**
  * Maximum number of direct path pushes within cutoff time
@@ -632,7 +633,6 @@
  */
 #define ZT_PEER_GENERAL_RATE_LIMIT 1000
 
-
 /**
  * Minimum allowed amount of time between flow/path optimizations (anti-flapping)
  */
@@ -709,8 +709,8 @@
  * Artificially inflates the failover score for paths which meet
  * certain non-performance-related policy ranking criteria.
  */
-#define ZT_BOND_FAILOVER_HANDICAP_PREFERRED  500
-#define ZT_BOND_FAILOVER_HANDICAP_PRIMARY    1000
+#define ZT_BOND_FAILOVER_HANDICAP_PREFERRED	 500
+#define ZT_BOND_FAILOVER_HANDICAP_PRIMARY	 1000
 #define ZT_BOND_FAILOVER_HANDICAP_NEGOTIATED 5000
 
 /**
@@ -754,14 +754,14 @@
 #define ZT_THREAD_MIN_STACK_SIZE 1048576
 
 // Exceptions thrown in core ZT code
-#define ZT_EXCEPTION_OUT_OF_BOUNDS 100
-#define ZT_EXCEPTION_OUT_OF_MEMORY 101
-#define ZT_EXCEPTION_PRIVATE_KEY_REQUIRED 102
-#define ZT_EXCEPTION_INVALID_ARGUMENT 103
-#define ZT_EXCEPTION_INVALID_IDENTITY 104
-#define ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE 200
-#define ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW 201
+#define ZT_EXCEPTION_OUT_OF_BOUNDS										 100
+#define ZT_EXCEPTION_OUT_OF_MEMORY										 101
+#define ZT_EXCEPTION_PRIVATE_KEY_REQUIRED								 102
+#define ZT_EXCEPTION_INVALID_ARGUMENT									 103
+#define ZT_EXCEPTION_INVALID_IDENTITY									 104
+#define ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE				 200
+#define ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW					 201
 #define ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN 202
-#define ZT_EXCEPTION_INVALID_SERIALIZED_DATA_BAD_ENCODING 203
+#define ZT_EXCEPTION_INVALID_SERIALIZED_DATA_BAD_ENCODING				 203
 
 #endif

+ 10 - 13
node/Credential.hpp

@@ -14,39 +14,36 @@
 #ifndef ZT_CREDENTIAL_HPP
 #define ZT_CREDENTIAL_HPP
 
-#include <string>
+#include "Constants.hpp"
+
 #include <memory>
 #include <stdexcept>
-
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <stdint.h>
 #include <string.h>
-
-#include "Constants.hpp"
+#include <string>
 
 namespace ZeroTier {
 
 /**
  * Base class for credentials
  */
-class Credential
-{
-public:
+class Credential {
+  public:
 	/**
 	 * Do not change type code IDs -- these are used in Revocation objects and elsewhere
 	 */
-	enum Type
-	{
+	enum Type {
 		CREDENTIAL_TYPE_NULL = 0,
-		CREDENTIAL_TYPE_COM = 1,        // CertificateOfMembership
+		CREDENTIAL_TYPE_COM = 1,   // CertificateOfMembership
 		CREDENTIAL_TYPE_CAPABILITY = 2,
 		CREDENTIAL_TYPE_TAG = 3,
-		CREDENTIAL_TYPE_COO = 4,        // CertificateOfOwnership
+		CREDENTIAL_TYPE_COO = 4,   // CertificateOfOwnership
 		CREDENTIAL_TYPE_REVOCATION = 6
 	};
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 26 - 28
node/DNS.hpp

@@ -13,45 +13,43 @@
 
 #ifndef ZT_DNS_HPP
 #define ZT_DNS_HPP
+#include "../include/ZeroTierOne.h"
+#include "Buffer.hpp"
+#include "InetAddress.hpp"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "Buffer.hpp"
-#include "InetAddress.hpp"
-#include "../include/ZeroTierOne.h"
-
 namespace ZeroTier {
 
 /**
  * DNS data serialization methods
  */
 class DNS {
-public:
-    template<unsigned int C>
-    static inline void serializeDNS(Buffer<C> &b, const ZT_VirtualNetworkDNS *dns)
-    {
-        b.append(dns->domain, 128);
-        for(unsigned int j = 0; j < ZT_MAX_DNS_SERVERS; ++j) {
-            InetAddress tmp(dns->server_addr[j]);
-            tmp.serialize(b);
-        }
-    }
+  public:
+	template <unsigned int C> static inline void serializeDNS(Buffer<C>& b, const ZT_VirtualNetworkDNS* dns)
+	{
+		b.append(dns->domain, 128);
+		for (unsigned int j = 0; j < ZT_MAX_DNS_SERVERS; ++j) {
+			InetAddress tmp(dns->server_addr[j]);
+			tmp.serialize(b);
+		}
+	}
 
-    template<unsigned int C>
-    static inline void deserializeDNS(const Buffer<C> &b, unsigned int &p, ZT_VirtualNetworkDNS *dns)
-    {
-        char *d = (char*)b.data()+p;
-        memset(dns, 0, sizeof(ZT_VirtualNetworkDNS));
-        memcpy(dns->domain, d, 128);
-        dns->domain[127] = 0;
-        p += 128;
-        for (unsigned int j = 0; j < ZT_MAX_DNS_SERVERS; ++j) {
-            p += reinterpret_cast<InetAddress *>(&(dns->server_addr[j]))->deserialize(b, p);
-        }
-    }
+	template <unsigned int C> static inline void deserializeDNS(const Buffer<C>& b, unsigned int& p, ZT_VirtualNetworkDNS* dns)
+	{
+		char* d = (char*)b.data() + p;
+		memset(dns, 0, sizeof(ZT_VirtualNetworkDNS));
+		memcpy(dns->domain, d, 128);
+		dns->domain[127] = 0;
+		p += 128;
+		for (unsigned int j = 0; j < ZT_MAX_DNS_SERVERS; ++j) {
+			p += reinterpret_cast<InetAddress*>(&(dns->server_addr[j]))->deserialize(b, p);
+		}
+	}
 };
 
-}
+}	// namespace ZeroTier
 
-#endif // ZT_DNS_HPP
+#endif	 // ZT_DNS_HPP

+ 113 - 86
node/Dictionary.hpp

@@ -14,10 +14,10 @@
 #ifndef ZT_DICTIONARY_HPP
 #define ZT_DICTIONARY_HPP
 
+#include "Address.hpp"
+#include "Buffer.hpp"
 #include "Constants.hpp"
 #include "Utils.hpp"
-#include "Buffer.hpp"
-#include "Address.hpp"
 
 #include <stdint.h>
 
@@ -45,36 +45,48 @@ namespace ZeroTier {
  *
  * @tparam C Dictionary max capacity in bytes
  */
-template<unsigned int C>
-class Dictionary
-{
-public:
-	Dictionary() { memset(_d,0,sizeof(_d)); }
-	Dictionary(const char *s) { this->load(s); }
-	Dictionary(const char *s,unsigned int len)
+template <unsigned int C> class Dictionary {
+  public:
+	Dictionary()
+	{
+		memset(_d, 0, sizeof(_d));
+	}
+	Dictionary(const char* s)
+	{
+		this->load(s);
+	}
+	Dictionary(const char* s, unsigned int len)
 	{
-		for(unsigned int i=0;i<C;++i) {
-			if ((s)&&(i < len)) {
-				if (!(_d[i] = *s)) {
-					s = (const char *)0;
-				} else {
+		for (unsigned int i = 0; i < C; ++i) {
+			if ((s) && (i < len)) {
+				if (! (_d[i] = *s)) {
+					s = (const char*)0;
+				}
+				else {
 					++s;
 				}
-			} else {
+			}
+			else {
 				_d[i] = (char)0;
 			}
 		}
 		_d[C - 1] = (char)0;
 	}
-	Dictionary(const Dictionary &d) { memcpy(_d,d._d,C); }
+	Dictionary(const Dictionary& d)
+	{
+		memcpy(_d, d._d, C);
+	}
 
-	inline Dictionary &operator=(const Dictionary &d)
+	inline Dictionary& operator=(const Dictionary& d)
 	{
-		memcpy(_d,d._d,C);
+		memcpy(_d, d._d, C);
 		return *this;
 	}
 
-	inline operator bool() const { return (_d[0] != 0); }
+	inline operator bool() const
+	{
+		return (_d[0] != 0);
+	}
 
 	/**
 	 * Load a dictionary from a C-string
@@ -82,21 +94,23 @@ public:
 	 * @param s Dictionary in string form
 	 * @return False if 's' was longer than our capacity
 	 */
-	inline bool load(const char *s)
+	inline bool load(const char* s)
 	{
-		for(unsigned int i=0;i<C;++i) {
+		for (unsigned int i = 0; i < C; ++i) {
 			if (s) {
-				if (!(_d[i] = *s)) {
-					s = (const char *)0;
-				} else {
+				if (! (_d[i] = *s)) {
+					s = (const char*)0;
+				}
+				else {
 					++s;
 				}
-			} else {
+			}
+			else {
 				_d[i] = (char)0;
 			}
 		}
 		_d[C - 1] = (char)0;
-		return (!s);
+		return (! s);
 	}
 
 	/**
@@ -104,7 +118,7 @@ public:
 	 */
 	inline void clear()
 	{
-		memset(_d,0,sizeof(_d));
+		memset(_d, 0, sizeof(_d));
 	}
 
 	/**
@@ -112,12 +126,12 @@ public:
 	 */
 	inline unsigned int sizeBytes() const
 	{
-		for(unsigned int i=0;i<C;++i) {
-			if (!_d[i]) {
+		for (unsigned int i = 0; i < C; ++i) {
+			if (! _d[i]) {
 				return i;
 			}
 		}
-		return C-1;
+		return C - 1;
 	}
 
 	/**
@@ -142,21 +156,21 @@ public:
 	 * @param destlen Size of destination buffer
 	 * @return -1 if not found, or actual number of bytes stored in dest[] minus trailing 0
 	 */
-	inline int get(const char *key,char *dest,unsigned int destlen) const
+	inline int get(const char* key, char* dest, unsigned int destlen) const
 	{
-		const char *p = _d;
-		const char *const eof = p + C;
-		const char *k;
+		const char* p = _d;
+		const char* const eof = p + C;
+		const char* k;
 		bool esc;
 		int j;
 
-		if (!destlen) { // sanity check
+		if (! destlen) {   // sanity check
 			return -1;
 		}
 
 		while (*p) {
 			k = key;
-			while ((*k)&&(*p)) {
+			while ((*k) && (*p)) {
 				if (*p != *k) {
 					break;
 				}
@@ -167,14 +181,14 @@ public:
 				}
 			}
 
-			if ((!*k)&&(*p == '=')) {
+			if ((! *k) && (*p == '=')) {
 				j = 0;
 				esc = false;
 				++p;
-				while ((*p != 0)&&(*p != 13)&&(*p != 10)) {
+				while ((*p != 0) && (*p != 13) && (*p != 10)) {
 					if (esc) {
 						esc = false;
-						switch(*p) {
+						switch (*p) {
 							case 'r':
 								dest[j++] = 13;
 								break;
@@ -192,16 +206,18 @@ public:
 								break;
 						}
 						if (j == (int)destlen) {
-							dest[j-1] = (char)0;
-							return j-1;
+							dest[j - 1] = (char)0;
+							return j - 1;
 						}
-					} else if (*p == '\\') {
+					}
+					else if (*p == '\\') {
 						esc = true;
-					} else {
+					}
+					else {
 						dest[j++] = *p;
 						if (j == (int)destlen) {
-							dest[j-1] = (char)0;
-							return j-1;
+							dest[j - 1] = (char)0;
+							return j - 1;
 						}
 					}
 					if (++p == eof) {
@@ -211,8 +227,9 @@ public:
 				}
 				dest[j] = (char)0;
 				return j;
-			} else {
-				while ((*p)&&(*p != 13)&&(*p != 10)) {
+			}
+			else {
+				while ((*p) && (*p != 13) && (*p != 10)) {
 					if (++p == eof) {
 						dest[0] = (char)0;
 						return -1;
@@ -223,7 +240,8 @@ public:
 						dest[0] = (char)0;
 						return -1;
 					}
-				} else {
+				}
+				else {
 					break;
 				}
 			}
@@ -241,14 +259,14 @@ public:
 	 * @return True if key was found (if false, dest will be empty)
 	 * @tparam BC Buffer capacity (usually inferred)
 	 */
-	template<unsigned int BC>
-	inline bool get(const char *key,Buffer<BC> &dest) const
+	template <unsigned int BC> inline bool get(const char* key, Buffer<BC>& dest) const
 	{
-		const int r = this->get(key,const_cast<char *>(reinterpret_cast<const char *>(dest.data())),BC);
+		const int r = this->get(key, const_cast<char*>(reinterpret_cast<const char*>(dest.data())), BC);
 		if (r >= 0) {
 			dest.setSize((unsigned int)r);
 			return true;
-		} else {
+		}
+		else {
 			dest.clear();
 			return false;
 		}
@@ -261,11 +279,11 @@ public:
 	 * @param dfl Default value if not found in dictionary
 	 * @return Boolean value of key or 'dfl' if not found
 	 */
-	bool getB(const char *key,bool dfl = false) const
+	bool getB(const char* key, bool dfl = false) const
 	{
 		char tmp[4];
-		if (this->get(key,tmp,sizeof(tmp)) >= 0) {
-			return ((*tmp == '1')||(*tmp == 't')||(*tmp == 'T'));
+		if (this->get(key, tmp, sizeof(tmp)) >= 0) {
+			return ((*tmp == '1') || (*tmp == 't') || (*tmp == 'T'));
 		}
 		return dfl;
 	}
@@ -277,10 +295,10 @@ public:
 	 * @param dfl Default value or 0 if unspecified
 	 * @return Decoded hex UInt value or 'dfl' if not found
 	 */
-	inline uint64_t getUI(const char *key,uint64_t dfl = 0) const
+	inline uint64_t getUI(const char* key, uint64_t dfl = 0) const
 	{
 		char tmp[128];
-		if (this->get(key,tmp,sizeof(tmp)) >= 1) {
+		if (this->get(key, tmp, sizeof(tmp)) >= 1) {
 			return Utils::hexStrToU64(tmp);
 		}
 		return dfl;
@@ -293,10 +311,10 @@ public:
 	 * @param dfl Default value or 0 if unspecified
 	 * @return Decoded hex UInt value or 'dfl' if not found
 	 */
-	inline int64_t getI(const char *key,int64_t dfl = 0) const
+	inline int64_t getI(const char* key, int64_t dfl = 0) const
 	{
 		char tmp[128];
-		if (this->get(key,tmp,sizeof(tmp)) >= 1) {
+		if (this->get(key, tmp, sizeof(tmp)) >= 1) {
 			return Utils::hexStrTo64(tmp);
 		}
 		return dfl;
@@ -316,10 +334,10 @@ public:
 	 * @param vlen Length of value in bytes or -1 to treat value[] as a C-string and look for terminating 0
 	 * @return True if there was enough room to add this key=value pair
 	 */
-	inline bool add(const char *key,const char *value,int vlen = -1)
+	inline bool add(const char* key, const char* value, int vlen = -1)
 	{
-		for(unsigned int i=0;i<C;++i) {
-			if (!_d[i]) {
+		for (unsigned int i = 0; i < C; ++i) {
+			if (! _d[i]) {
 				unsigned int j = i;
 
 				if (j > 0) {
@@ -330,7 +348,7 @@ public:
 					}
 				}
 
-				const char *p = key;
+				const char* p = key;
 				while (*p) {
 					_d[j++] = *(p++);
 					if (j == C) {
@@ -347,8 +365,8 @@ public:
 
 				p = value;
 				int k = 0;
-				while ( ((vlen < 0)&&(*p)) || (k < vlen) ) {
-					switch(*p) {
+				while (((vlen < 0) && (*p)) || (k < vlen)) {
+					switch (*p) {
 						case 0:
 						case 13:
 						case 10:
@@ -359,7 +377,7 @@ public:
 								_d[i] = (char)0;
 								return false;
 							}
-							switch(*p) {
+							switch (*p) {
 								case 0:
 									_d[j++] = '0';
 									break;
@@ -404,41 +422,42 @@ public:
 	/**
 	 * Add a boolean as a '1' or a '0'
 	 */
-	inline bool add(const char *key,bool value)
+	inline bool add(const char* key, bool value)
 	{
-		return this->add(key,(value) ? "1" : "0",1);
+		return this->add(key, (value) ? "1" : "0", 1);
 	}
 
 	/**
 	 * Add a 64-bit integer (unsigned) as a hex value
 	 */
-	inline bool add(const char *key,uint64_t value)
+	inline bool add(const char* key, uint64_t value)
 	{
 		char tmp[32];
-		return this->add(key,Utils::hex(value,tmp),-1);
+		return this->add(key, Utils::hex(value, tmp), -1);
 	}
 
 	/**
 	 * Add a 64-bit integer (unsigned) as a hex value
 	 */
-	inline bool add(const char *key,int64_t value)
+	inline bool add(const char* key, int64_t value)
 	{
 		char tmp[32];
 		if (value >= 0) {
-			return this->add(key,Utils::hex((uint64_t)value,tmp),-1);
-		} else {
+			return this->add(key, Utils::hex((uint64_t)value, tmp), -1);
+		}
+		else {
 			tmp[0] = '-';
-			return this->add(key,Utils::hex((uint64_t)(value * -1),tmp+1),-1);
+			return this->add(key, Utils::hex((uint64_t)(value * -1), tmp + 1), -1);
 		}
 	}
 
 	/**
 	 * Add a 64-bit integer (unsigned) as a hex value
 	 */
-	inline bool add(const char *key,const Address &a)
+	inline bool add(const char* key, const Address& a)
 	{
 		char tmp[32];
-		return this->add(key,Utils::hex(a.toInt(),tmp),-1);
+		return this->add(key, Utils::hex(a.toInt(), tmp), -1);
 	}
 
 	/**
@@ -446,34 +465,42 @@ public:
 	 *
 	 * @tparam BC Buffer capacity (usually inferred)
 	 */
-	template<unsigned int BC>
-	inline bool add(const char *key,const Buffer<BC> &value)
+	template <unsigned int BC> inline bool add(const char* key, const Buffer<BC>& value)
 	{
-		return this->add(key,(const char *)value.data(),(int)value.size());
+		return this->add(key, (const char*)value.data(), (int)value.size());
 	}
 
 	/**
 	 * @param key Key to check
 	 * @return True if key is present
 	 */
-	inline bool contains(const char *key) const
+	inline bool contains(const char* key) const
 	{
 		char tmp[2];
-		return (this->get(key,tmp,2) >= 0);
+		return (this->get(key, tmp, 2) >= 0);
 	}
 
 	/**
 	 * @return Value of C template parameter
 	 */
-	inline unsigned int capacity() const { return C; }
+	inline unsigned int capacity() const
+	{
+		return C;
+	}
 
-	inline const char *data() const { return _d; }
-	inline char *unsafeData() { return _d; }
+	inline const char* data() const
+	{
+		return _d;
+	}
+	inline char* unsafeData()
+	{
+		return _d;
+	}
 
-private:
+  private:
 	char _d[C];
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 101 - 96
node/Hashtable.hpp

@@ -16,36 +16,43 @@
 
 #include "Constants.hpp"
 
+#include <algorithm>
+#include <stdexcept>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
-
-#include <stdexcept>
-#include <vector>
 #include <utility>
-#include <algorithm>
+#include <vector>
 
 namespace ZeroTier {
 
 /**
  * A minimal hash table implementation for the ZeroTier core
  */
-template<typename K,typename V>
-class Hashtable
-{
-private:
-	struct _Bucket
-	{
-		_Bucket(const K &k,const V &v) : k(k),v(v) {}
-		_Bucket(const K &k) : k(k),v() {}
-		_Bucket(const _Bucket &b) : k(b.k),v(b.v) {}
-		inline _Bucket &operator=(const _Bucket &b) { k = b.k; v = b.v; return *this; }
+template <typename K, typename V> class Hashtable {
+  private:
+	struct _Bucket {
+		_Bucket(const K& k, const V& v) : k(k), v(v)
+		{
+		}
+		_Bucket(const K& k) : k(k), v()
+		{
+		}
+		_Bucket(const _Bucket& b) : k(b.k), v(b.v)
+		{
+		}
+		inline _Bucket& operator=(const _Bucket& b)
+		{
+			k = b.k;
+			v = b.v;
+			return *this;
+		}
 		K k;
 		V v;
-		_Bucket *next; // must be set manually for each _Bucket
+		_Bucket* next;	 // must be set manually for each _Bucket
 	};
 
-public:
+  public:
 	/**
 	 * A simple forward iterator (different from STL)
 	 *
@@ -53,16 +60,12 @@ public:
 	 * may rehash and invalidate the iterator. Note the erasing the key will destroy
 	 * the targets of the pointers returned by next().
 	 */
-	class Iterator
-	{
-	public:
+	class Iterator {
+	  public:
 		/**
 		 * @param ht Hash table to iterate over
 		 */
-		Iterator(Hashtable &ht) :
-			_idx(0),
-			_ht(&ht),
-			_b(ht._t[0])
+		Iterator(Hashtable& ht) : _idx(0), _ht(&ht), _b(ht._t[0])
 		{
 		}
 
@@ -71,9 +74,9 @@ public:
 		 * @param vptr Pointer to set to point to next value
 		 * @return True if kptr and vptr are set, false if no more entries
 		 */
-		inline bool next(K *&kptr,V *&vptr)
+		inline bool next(K*& kptr, V*& vptr)
 		{
-			for(;;) {
+			for (;;) {
 				if (_b) {
 					kptr = &(_b->k);
 					vptr = &(_b->v);
@@ -88,44 +91,38 @@ public:
 			}
 		}
 
-	private:
+	  private:
 		unsigned long _idx;
-		Hashtable *_ht;
-		_Bucket *_b;
+		Hashtable* _ht;
+		_Bucket* _b;
 	};
-	//friend class Hashtable<K,V>::Iterator;
+	// friend class Hashtable<K,V>::Iterator;
 
 	/**
 	 * @param bc Initial capacity in buckets (default: 64, must be nonzero)
 	 */
-	Hashtable(unsigned long bc = 64) :
-		_t(reinterpret_cast<_Bucket **>(::malloc(sizeof(_Bucket *) * bc))),
-		_bc(bc),
-		_s(0)
+	Hashtable(unsigned long bc = 64) : _t(reinterpret_cast<_Bucket**>(::malloc(sizeof(_Bucket*) * bc))), _bc(bc), _s(0)
 	{
-		if (!_t) {
+		if (! _t) {
 			throw ZT_EXCEPTION_OUT_OF_MEMORY;
 		}
-		for(unsigned long i=0;i<bc;++i) {
-			_t[i] = (_Bucket *)0;
+		for (unsigned long i = 0; i < bc; ++i) {
+			_t[i] = (_Bucket*)0;
 		}
 	}
 
-	Hashtable(const Hashtable<K,V> &ht) :
-		_t(reinterpret_cast<_Bucket **>(::malloc(sizeof(_Bucket *) * ht._bc))),
-		_bc(ht._bc),
-		_s(ht._s)
+	Hashtable(const Hashtable<K, V>& ht) : _t(reinterpret_cast<_Bucket**>(::malloc(sizeof(_Bucket*) * ht._bc))), _bc(ht._bc), _s(ht._s)
 	{
-		if (!_t) {
+		if (! _t) {
 			throw ZT_EXCEPTION_OUT_OF_MEMORY;
 		}
-		for(unsigned long i=0;i<_bc;++i) {
-			_t[i] = (_Bucket *)0;
+		for (unsigned long i = 0; i < _bc; ++i) {
+			_t[i] = (_Bucket*)0;
 		}
-		for(unsigned long i=0;i<_bc;++i) {
-			const _Bucket *b = ht._t[i];
+		for (unsigned long i = 0; i < _bc; ++i) {
+			const _Bucket* b = ht._t[i];
 			while (b) {
-				_Bucket *nb = new _Bucket(*b);
+				_Bucket* nb = new _Bucket(*b);
 				nb->next = _t[i];
 				_t[i] = nb;
 				b = b->next;
@@ -139,14 +136,14 @@ public:
 		::free(_t);
 	}
 
-	inline Hashtable &operator=(const Hashtable<K,V> &ht)
+	inline Hashtable& operator=(const Hashtable<K, V>& ht)
 	{
 		this->clear();
 		if (ht._s) {
-			for(unsigned long i=0;i<ht._bc;++i) {
-				const _Bucket *b = ht._t[i];
+			for (unsigned long i = 0; i < ht._bc; ++i) {
+				const _Bucket* b = ht._t[i];
 				while (b) {
-					this->set(b->k,b->v);
+					this->set(b->k, b->v);
 					b = b->next;
 				}
 			}
@@ -160,14 +157,14 @@ public:
 	inline void clear()
 	{
 		if (_s) {
-			for(unsigned long i=0;i<_bc;++i) {
-				_Bucket *b = _t[i];
+			for (unsigned long i = 0; i < _bc; ++i) {
+				_Bucket* b = _t[i];
 				while (b) {
-					_Bucket *const nb = b->next;
+					_Bucket* const nb = b->next;
 					delete b;
 					b = nb;
 				}
-				_t[i] = (_Bucket *)0;
+				_t[i] = (_Bucket*)0;
 			}
 			_s = 0;
 		}
@@ -181,8 +178,8 @@ public:
 		typename std::vector<K> k;
 		if (_s) {
 			k.reserve(_s);
-			for(unsigned long i=0;i<_bc;++i) {
-				_Bucket *b = _t[i];
+			for (unsigned long i = 0; i < _bc; ++i) {
+				_Bucket* b = _t[i];
 				while (b) {
 					k.push_back(b->k);
 					b = b->next;
@@ -198,12 +195,11 @@ public:
 	 * @param v Vector, list, or other compliant container
 	 * @tparam Type of V (generally inferred)
 	 */
-	template<typename C>
-	inline void appendKeys(C &v) const
+	template <typename C> inline void appendKeys(C& v) const
 	{
 		if (_s) {
-			for(unsigned long i=0;i<_bc;++i) {
-				_Bucket *b = _t[i];
+			for (unsigned long i = 0; i < _bc; ++i) {
+				_Bucket* b = _t[i];
 				while (b) {
 					v.push_back(b->k);
 					b = b->next;
@@ -215,15 +211,15 @@ public:
 	/**
 	 * @return Vector of all entries (pairs of K,V)
 	 */
-	inline typename std::vector< std::pair<K,V> > entries() const
+	inline typename std::vector<std::pair<K, V> > entries() const
 	{
-		typename std::vector< std::pair<K,V> > k;
+		typename std::vector<std::pair<K, V> > k;
 		if (_s) {
 			k.reserve(_s);
-			for(unsigned long i=0;i<_bc;++i) {
-				_Bucket *b = _t[i];
+			for (unsigned long i = 0; i < _bc; ++i) {
+				_Bucket* b = _t[i];
 				while (b) {
-					k.push_back(std::pair<K,V>(b->k,b->v));
+					k.push_back(std::pair<K, V>(b->k, b->v));
 					b = b->next;
 				}
 			}
@@ -235,27 +231,30 @@ public:
 	 * @param k Key
 	 * @return Pointer to value or NULL if not found
 	 */
-	inline V *get(const K &k)
+	inline V* get(const K& k)
 	{
-		_Bucket *b = _t[_hc(k) % _bc];
+		_Bucket* b = _t[_hc(k) % _bc];
 		while (b) {
 			if (b->k == k) {
 				return &(b->v);
 			}
 			b = b->next;
 		}
-		return (V *)0;
+		return (V*)0;
+	}
+	inline const V* get(const K& k) const
+	{
+		return const_cast<Hashtable*>(this)->get(k);
 	}
-	inline const V *get(const K &k) const { return const_cast<Hashtable *>(this)->get(k); }
 
 	/**
 	 * @param k Key
 	 * @param v Value to fill with result
 	 * @return True if value was found and set (if false, v is not modified)
 	 */
-	inline bool get(const K &k,V &v) const
+	inline bool get(const K& k, V& v) const
 	{
-		_Bucket *b = _t[_hc(k) % _bc];
+		_Bucket* b = _t[_hc(k) % _bc];
 		while (b) {
 			if (b->k == k) {
 				v = b->v;
@@ -270,9 +269,9 @@ public:
 	 * @param k Key to check
 	 * @return True if key is present
 	 */
-	inline bool contains(const K &k) const
+	inline bool contains(const K& k) const
 	{
-		_Bucket *b = _t[_hc(k) % _bc];
+		_Bucket* b = _t[_hc(k) % _bc];
 		while (b) {
 			if (b->k == k) {
 				return true;
@@ -286,16 +285,17 @@ public:
 	 * @param k Key
 	 * @return True if value was present
 	 */
-	inline bool erase(const K &k)
+	inline bool erase(const K& k)
 	{
 		const unsigned long bidx = _hc(k) % _bc;
-		_Bucket *lastb = (_Bucket *)0;
-		_Bucket *b = _t[bidx];
+		_Bucket* lastb = (_Bucket*)0;
+		_Bucket* b = _t[bidx];
 		while (b) {
 			if (b->k == k) {
 				if (lastb) {
 					lastb->next = b->next;
-				} else {
+				}
+				else {
 					_t[bidx] = b->next;
 				}
 				delete b;
@@ -313,12 +313,12 @@ public:
 	 * @param v Value
 	 * @return Reference to value in table
 	 */
-	inline V &set(const K &k,const V &v)
+	inline V& set(const K& k, const V& v)
 	{
 		const unsigned long h = _hc(k);
 		unsigned long bidx = h % _bc;
 
-		_Bucket *b = _t[bidx];
+		_Bucket* b = _t[bidx];
 		while (b) {
 			if (b->k == k) {
 				b->v = v;
@@ -332,7 +332,7 @@ public:
 			bidx = h % _bc;
 		}
 
-		b = new _Bucket(k,v);
+		b = new _Bucket(k, v);
 		b->next = _t[bidx];
 		_t[bidx] = b;
 		++_s;
@@ -343,12 +343,12 @@ public:
 	 * @param k Key
 	 * @return Value, possibly newly created
 	 */
-	inline V &operator[](const K &k)
+	inline V& operator[](const K& k)
 	{
 		const unsigned long h = _hc(k);
 		unsigned long bidx = h % _bc;
 
-		_Bucket *b = _t[bidx];
+		_Bucket* b = _t[bidx];
 		while (b) {
 			if (b->k == k) {
 				return b->v;
@@ -371,22 +371,27 @@ public:
 	/**
 	 * @return Number of entries
 	 */
-	inline unsigned long size() const { return _s; }
+	inline unsigned long size() const
+	{
+		return _s;
+	}
 
 	/**
 	 * @return True if table is empty
 	 */
-	inline bool empty() const { return (_s == 0); }
+	inline bool empty() const
+	{
+		return (_s == 0);
+	}
 
-private:
-	template<typename O>
-	static inline unsigned long _hc(const O &obj)
+  private:
+	template <typename O> static inline unsigned long _hc(const O& obj)
 	{
 		return (unsigned long)obj.hashCode();
 	}
 	static inline unsigned long _hc(const uint64_t i)
 	{
-		return (unsigned long)(i ^ (i >> 32)); // good for network IDs and addresses
+		return (unsigned long)(i ^ (i >> 32));	 // good for network IDs and addresses
 	}
 	static inline unsigned long _hc(const uint32_t i)
 	{
@@ -404,15 +409,15 @@ private:
 	inline void _grow()
 	{
 		const unsigned long nc = _bc * 2;
-		_Bucket **nt = reinterpret_cast<_Bucket **>(::malloc(sizeof(_Bucket *) * nc));
+		_Bucket** nt = reinterpret_cast<_Bucket**>(::malloc(sizeof(_Bucket*) * nc));
 		if (nt) {
-			for(unsigned long i=0;i<nc;++i) {
-				nt[i] = (_Bucket *)0;
+			for (unsigned long i = 0; i < nc; ++i) {
+				nt[i] = (_Bucket*)0;
 			}
-			for(unsigned long i=0;i<_bc;++i) {
-				_Bucket *b = _t[i];
+			for (unsigned long i = 0; i < _bc; ++i) {
+				_Bucket* b = _t[i];
 				while (b) {
-					_Bucket *const nb = b->next;
+					_Bucket* const nb = b->next;
 					const unsigned long nidx = _hc(b->k) % nc;
 					b->next = nt[nidx];
 					nt[nidx] = b;
@@ -425,11 +430,11 @@ private:
 		}
 	}
 
-	_Bucket **_t;
+	_Bucket** _t;
 	unsigned long _bc;
 	unsigned long _s;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 68 - 70
node/Identity.cpp

@@ -11,94 +11,98 @@
  */
 /****/
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
+#include "Identity.hpp"
 
 #include "Constants.hpp"
-#include "Identity.hpp"
 #include "SHA512.hpp"
 #include "Salsa20.hpp"
 #include "Utils.hpp"
 
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
 // These can't be changed without a new identity type. They define the
 // parameters of the hashcash hashing/searching algorithm.
 
 #define ZT_IDENTITY_GEN_HASHCASH_FIRST_BYTE_LESS_THAN 17
-#define ZT_IDENTITY_GEN_MEMORY 2097152
+#define ZT_IDENTITY_GEN_MEMORY						  2097152
 
 namespace ZeroTier {
 
 // A memory-hard composition of SHA-512 and Salsa20 for hashcash hashing
-static inline void _computeMemoryHardHash(const void *publicKey,unsigned int publicKeyBytes,void *digest,void *genmem)
+static inline void _computeMemoryHardHash(const void* publicKey, unsigned int publicKeyBytes, void* digest, void* genmem)
 {
 	// Digest publicKey[] to obtain initial digest
-	SHA512(digest,publicKey,publicKeyBytes);
+	SHA512(digest, publicKey, publicKeyBytes);
 
 	// Initialize genmem[] using Salsa20 in a CBC-like configuration since
 	// ordinary Salsa20 is randomly seek-able. This is good for a cipher
 	// but is not what we want for sequential memory-hardness.
-	memset(genmem,0,ZT_IDENTITY_GEN_MEMORY);
-	Salsa20 s20(digest,(char *)digest + 32);
-	s20.crypt20((char *)genmem,(char *)genmem,64);
-	for(unsigned long i=64;i<ZT_IDENTITY_GEN_MEMORY;i+=64) {
+	memset(genmem, 0, ZT_IDENTITY_GEN_MEMORY);
+	Salsa20 s20(digest, (char*)digest + 32);
+	s20.crypt20((char*)genmem, (char*)genmem, 64);
+	for (unsigned long i = 64; i < ZT_IDENTITY_GEN_MEMORY; i += 64) {
 		unsigned long k = i - 64;
-		*((uint64_t *)((char *)genmem + i)) = *((uint64_t *)((char *)genmem + k));
-		*((uint64_t *)((char *)genmem + i + 8)) = *((uint64_t *)((char *)genmem + k + 8));
-		*((uint64_t *)((char *)genmem + i + 16)) = *((uint64_t *)((char *)genmem + k + 16));
-		*((uint64_t *)((char *)genmem + i + 24)) = *((uint64_t *)((char *)genmem + k + 24));
-		*((uint64_t *)((char *)genmem + i + 32)) = *((uint64_t *)((char *)genmem + k + 32));
-		*((uint64_t *)((char *)genmem + i + 40)) = *((uint64_t *)((char *)genmem + k + 40));
-		*((uint64_t *)((char *)genmem + i + 48)) = *((uint64_t *)((char *)genmem + k + 48));
-		*((uint64_t *)((char *)genmem + i + 56)) = *((uint64_t *)((char *)genmem + k + 56));
-		s20.crypt20((char *)genmem + i,(char *)genmem + i,64);
+		*((uint64_t*)((char*)genmem + i)) = *((uint64_t*)((char*)genmem + k));
+		*((uint64_t*)((char*)genmem + i + 8)) = *((uint64_t*)((char*)genmem + k + 8));
+		*((uint64_t*)((char*)genmem + i + 16)) = *((uint64_t*)((char*)genmem + k + 16));
+		*((uint64_t*)((char*)genmem + i + 24)) = *((uint64_t*)((char*)genmem + k + 24));
+		*((uint64_t*)((char*)genmem + i + 32)) = *((uint64_t*)((char*)genmem + k + 32));
+		*((uint64_t*)((char*)genmem + i + 40)) = *((uint64_t*)((char*)genmem + k + 40));
+		*((uint64_t*)((char*)genmem + i + 48)) = *((uint64_t*)((char*)genmem + k + 48));
+		*((uint64_t*)((char*)genmem + i + 56)) = *((uint64_t*)((char*)genmem + k + 56));
+		s20.crypt20((char*)genmem + i, (char*)genmem + i, 64);
 	}
 
 	// Render final digest using genmem as a lookup table
-	for(unsigned long i=0;i<(ZT_IDENTITY_GEN_MEMORY / sizeof(uint64_t));) {
-		unsigned long idx1 = (unsigned long)(Utils::ntoh(((uint64_t *)genmem)[i++]) % (64 / sizeof(uint64_t)));
-		unsigned long idx2 = (unsigned long)(Utils::ntoh(((uint64_t *)genmem)[i++]) % (ZT_IDENTITY_GEN_MEMORY / sizeof(uint64_t)));
-		uint64_t tmp = ((uint64_t *)genmem)[idx2];
-		((uint64_t *)genmem)[idx2] = ((uint64_t *)digest)[idx1];
-		((uint64_t *)digest)[idx1] = tmp;
-		s20.crypt20(digest,digest,64);
+	for (unsigned long i = 0; i < (ZT_IDENTITY_GEN_MEMORY / sizeof(uint64_t));) {
+		unsigned long idx1 = (unsigned long)(Utils::ntoh(((uint64_t*)genmem)[i++]) % (64 / sizeof(uint64_t)));
+		unsigned long idx2 = (unsigned long)(Utils::ntoh(((uint64_t*)genmem)[i++]) % (ZT_IDENTITY_GEN_MEMORY / sizeof(uint64_t)));
+		uint64_t tmp = ((uint64_t*)genmem)[idx2];
+		((uint64_t*)genmem)[idx2] = ((uint64_t*)digest)[idx1];
+		((uint64_t*)digest)[idx1] = tmp;
+		s20.crypt20(digest, digest, 64);
 	}
 }
 
 // Hashcash generation halting condition -- halt when first byte is less than
 // threshold value.
-struct _Identity_generate_cond
-{
-	_Identity_generate_cond() {}
-	_Identity_generate_cond(unsigned char *sb,char *gm) : digest(sb),genmem(gm) {}
-	inline bool operator()(const C25519::Pair &kp) const
+struct _Identity_generate_cond {
+	_Identity_generate_cond()
+	{
+	}
+	_Identity_generate_cond(unsigned char* sb, char* gm) : digest(sb), genmem(gm)
+	{
+	}
+	inline bool operator()(const C25519::Pair& kp) const
 	{
-		_computeMemoryHardHash(kp.pub.data,ZT_C25519_PUBLIC_KEY_LEN,digest,genmem);
+		_computeMemoryHardHash(kp.pub.data, ZT_C25519_PUBLIC_KEY_LEN, digest, genmem);
 		return (digest[0] < ZT_IDENTITY_GEN_HASHCASH_FIRST_BYTE_LESS_THAN);
 	}
-	unsigned char *digest;
-	char *genmem;
+	unsigned char* digest;
+	char* genmem;
 };
 
 void Identity::generate()
 {
 	unsigned char digest[64];
-	char *genmem = new char[ZT_IDENTITY_GEN_MEMORY];
+	char* genmem = new char[ZT_IDENTITY_GEN_MEMORY];
 
 	C25519::Pair kp;
 	do {
-		kp = C25519::generateSatisfying(_Identity_generate_cond(digest,genmem));
-		_address.setTo(digest + 59,ZT_ADDRESS_LENGTH); // last 5 bytes are address
+		kp = C25519::generateSatisfying(_Identity_generate_cond(digest, genmem));
+		_address.setTo(digest + 59, ZT_ADDRESS_LENGTH);	  // last 5 bytes are address
 	} while (_address.isReserved());
 
 	_publicKey = kp.pub;
-	if (!_privateKey) {
+	if (! _privateKey) {
 		_privateKey = new C25519::Private();
 	}
 	*_privateKey = kp.priv;
 
-	delete [] genmem;
+	delete[] genmem;
 }
 
 bool Identity::locallyValidate() const
@@ -108,60 +112,54 @@ bool Identity::locallyValidate() const
 	}
 
 	unsigned char digest[64];
-	char *genmem = new char[ZT_IDENTITY_GEN_MEMORY];
-	_computeMemoryHardHash(_publicKey.data,ZT_C25519_PUBLIC_KEY_LEN,digest,genmem);
-	delete [] genmem;
+	char* genmem = new char[ZT_IDENTITY_GEN_MEMORY];
+	_computeMemoryHardHash(_publicKey.data, ZT_C25519_PUBLIC_KEY_LEN, digest, genmem);
+	delete[] genmem;
 
 	unsigned char addrb[5];
-	_address.copyTo(addrb,5);
-
-	return (
-		(digest[0] < ZT_IDENTITY_GEN_HASHCASH_FIRST_BYTE_LESS_THAN)&&
-		(digest[59] == addrb[0])&&
-		(digest[60] == addrb[1])&&
-		(digest[61] == addrb[2])&&
-		(digest[62] == addrb[3])&&
-		(digest[63] == addrb[4]));
+	_address.copyTo(addrb, 5);
+
+	return ((digest[0] < ZT_IDENTITY_GEN_HASHCASH_FIRST_BYTE_LESS_THAN) && (digest[59] == addrb[0]) && (digest[60] == addrb[1]) && (digest[61] == addrb[2]) && (digest[62] == addrb[3]) && (digest[63] == addrb[4]));
 }
 
-char *Identity::toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const
+char* Identity::toString(bool includePrivate, char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const
 {
-	char *p = buf;
-	Utils::hex10(_address.toInt(),p);
+	char* p = buf;
+	Utils::hex10(_address.toInt(), p);
 	p += 10;
 	*(p++) = ':';
 	*(p++) = '0';
 	*(p++) = ':';
-	Utils::hex(_publicKey.data,ZT_C25519_PUBLIC_KEY_LEN,p);
+	Utils::hex(_publicKey.data, ZT_C25519_PUBLIC_KEY_LEN, p);
 	p += ZT_C25519_PUBLIC_KEY_LEN * 2;
-	if ((_privateKey)&&(includePrivate)) {
+	if ((_privateKey) && (includePrivate)) {
 		*(p++) = ':';
-		Utils::hex(_privateKey->data,ZT_C25519_PRIVATE_KEY_LEN,p);
+		Utils::hex(_privateKey->data, ZT_C25519_PRIVATE_KEY_LEN, p);
 		p += ZT_C25519_PRIVATE_KEY_LEN * 2;
 	}
 	*p = (char)0;
 	return buf;
 }
 
-bool Identity::fromString(const char *str)
+bool Identity::fromString(const char* str)
 {
-	if (!str) {
+	if (! str) {
 		_address.zero();
 		return false;
 	}
 	char tmp[ZT_IDENTITY_STRING_BUFFER_LENGTH];
-	if (!Utils::scopy(tmp,sizeof(tmp),str)) {
+	if (! Utils::scopy(tmp, sizeof(tmp), str)) {
 		_address.zero();
 		return false;
 	}
 
 	delete _privateKey;
-	_privateKey = (C25519::Private *)0;
+	_privateKey = (C25519::Private*)0;
 
 	int fno = 0;
-	char *saveptr = (char *)0;
-	for(char *f=Utils::stok(tmp,":",&saveptr);(f);f=Utils::stok((char *)0,":",&saveptr)) {
-		switch(fno++) {
+	char* saveptr = (char*)0;
+	for (char* f = Utils::stok(tmp, ":", &saveptr); (f); f = Utils::stok((char*)0, ":", &saveptr)) {
+		switch (fno++) {
 			case 0:
 				_address = Address(Utils::hexStrToU64(f));
 				if (_address.isReserved()) {
@@ -170,20 +168,20 @@ bool Identity::fromString(const char *str)
 				}
 				break;
 			case 1:
-				if ((f[0] != '0')||(f[1])) {
+				if ((f[0] != '0') || (f[1])) {
 					_address.zero();
 					return false;
 				}
 				break;
 			case 2:
-				if (Utils::unhex(f,_publicKey.data,ZT_C25519_PUBLIC_KEY_LEN) != ZT_C25519_PUBLIC_KEY_LEN) {
+				if (Utils::unhex(f, _publicKey.data, ZT_C25519_PUBLIC_KEY_LEN) != ZT_C25519_PUBLIC_KEY_LEN) {
 					_address.zero();
 					return false;
 				}
 				break;
 			case 3:
 				_privateKey = new C25519::Private();
-				if (Utils::unhex(f,_privateKey->data,ZT_C25519_PRIVATE_KEY_LEN) != ZT_C25519_PRIVATE_KEY_LEN) {
+				if (Utils::unhex(f, _privateKey->data, ZT_C25519_PRIVATE_KEY_LEN) != ZT_C25519_PRIVATE_KEY_LEN) {
 					_address.zero();
 					return false;
 				}
@@ -201,4 +199,4 @@ bool Identity::fromString(const char *str)
 	return true;
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier

+ 92 - 69
node/Identity.hpp

@@ -14,15 +14,15 @@
 #ifndef ZT_IDENTITY_HPP
 #define ZT_IDENTITY_HPP
 
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "Constants.hpp"
-#include "Utils.hpp"
 #include "Address.hpp"
-#include "C25519.hpp"
 #include "Buffer.hpp"
+#include "C25519.hpp"
+#include "Constants.hpp"
 #include "SHA512.hpp"
+#include "Utils.hpp"
+
+#include <stdio.h>
+#include <stdlib.h>
 
 #define ZT_IDENTITY_STRING_BUFFER_LENGTH 384
 
@@ -38,56 +38,49 @@ namespace ZeroTier {
  * search for a different public key that duplicates an existing address. (See
  * code for deriveAddress() for this algorithm.)
  */
-class Identity
-{
-public:
-	Identity() :
-		_privateKey((C25519::Private *)0)
+class Identity {
+  public:
+	Identity() : _privateKey((C25519::Private*)0)
 	{
 	}
 
-	Identity(const Identity &id) :
-		_address(id._address),
-		_publicKey(id._publicKey),
-		_privateKey((id._privateKey) ? new C25519::Private(*(id._privateKey)) : (C25519::Private *)0)
+	Identity(const Identity& id) : _address(id._address), _publicKey(id._publicKey), _privateKey((id._privateKey) ? new C25519::Private(*(id._privateKey)) : (C25519::Private*)0)
 	{
 	}
 
-	Identity(const char *str) :
-		_privateKey((C25519::Private *)0)
+	Identity(const char* str) : _privateKey((C25519::Private*)0)
 	{
-		if (!fromString(str)) {
+		if (! fromString(str)) {
 			throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE;
 		}
 	}
 
-	template<unsigned int C>
-	Identity(const Buffer<C> &b,unsigned int startAt = 0) :
-		_privateKey((C25519::Private *)0)
+	template <unsigned int C> Identity(const Buffer<C>& b, unsigned int startAt = 0) : _privateKey((C25519::Private*)0)
 	{
-		deserialize(b,startAt);
+		deserialize(b, startAt);
 	}
 
 	~Identity()
 	{
 		if (_privateKey) {
-			Utils::burn(_privateKey,sizeof(C25519::Private));
+			Utils::burn(_privateKey, sizeof(C25519::Private));
 			delete _privateKey;
 		}
 	}
 
-	inline Identity &operator=(const Identity &id)
+	inline Identity& operator=(const Identity& id)
 	{
 		_address = id._address;
 		_publicKey = id._publicKey;
 		if (id._privateKey) {
-			if (!_privateKey) {
+			if (! _privateKey) {
 				_privateKey = new C25519::Private();
 			}
 			*_privateKey = *(id._privateKey);
-		} else {
+		}
+		else {
 			delete _privateKey;
-			_privateKey = (C25519::Private *)0;
+			_privateKey = (C25519::Private*)0;
 		}
 		return *this;
 	}
@@ -109,14 +102,17 @@ public:
 	/**
 	 * @return True if this identity contains a private key
 	 */
-	inline bool hasPrivate() const { return (_privateKey != (C25519::Private *)0); }
+	inline bool hasPrivate() const
+	{
+		return (_privateKey != (C25519::Private*)0);
+	}
 
 	/**
 	 * Compute a SHA384 hash of this identity's address and public key(s).
-	 * 
+	 *
 	 * @param sha384buf Buffer with 48 bytes of space to receive hash
 	 */
-	inline void publicKeyHash(void *sha384buf) const
+	inline void publicKeyHash(void* sha384buf) const
 	{
 		uint8_t address[ZT_ADDRESS_LENGTH];
 		_address.copyTo(address, ZT_ADDRESS_LENGTH);
@@ -129,10 +125,10 @@ public:
 	 * @param sha Buffer to receive SHA512 (MUST be ZT_SHA512_DIGEST_LEN (64) bytes in length)
 	 * @return True on success, false if no private key
 	 */
-	inline bool sha512PrivateKey(void *sha) const
+	inline bool sha512PrivateKey(void* sha) const
 	{
 		if (_privateKey) {
-			SHA512(sha,_privateKey->data,ZT_C25519_PRIVATE_KEY_LEN);
+			SHA512(sha, _privateKey->data, ZT_C25519_PRIVATE_KEY_LEN);
 			return true;
 		}
 		return false;
@@ -144,10 +140,10 @@ public:
 	 * @param data Data to sign
 	 * @param len Length of data
 	 */
-	inline C25519::Signature sign(const void *data,unsigned int len) const
+	inline C25519::Signature sign(const void* data, unsigned int len) const
 	{
 		if (_privateKey) {
-			return C25519::sign(*_privateKey,_publicKey,data,len);
+			return C25519::sign(*_privateKey, _publicKey, data, len);
 		}
 		throw ZT_EXCEPTION_PRIVATE_KEY_REQUIRED;
 	}
@@ -161,12 +157,12 @@ public:
 	 * @param siglen Length of signature in bytes
 	 * @return True if signature validates and data integrity checks
 	 */
-	inline bool verify(const void *data,unsigned int len,const void *signature,unsigned int siglen) const
+	inline bool verify(const void* data, unsigned int len, const void* signature, unsigned int siglen) const
 	{
 		if (siglen != ZT_C25519_SIGNATURE_LEN) {
 			return false;
 		}
-		return C25519::verify(_publicKey,data,len,signature);
+		return C25519::verify(_publicKey, data, len, signature);
 	}
 
 	/**
@@ -177,9 +173,9 @@ public:
 	 * @param signature Signature
 	 * @return True if signature validates and data integrity checks
 	 */
-	inline bool verify(const void *data,unsigned int len,const C25519::Signature &signature) const
+	inline bool verify(const void* data, unsigned int len, const C25519::Signature& signature) const
 	{
-		return C25519::verify(_publicKey,data,len,signature);
+		return C25519::verify(_publicKey, data, len, signature);
 	}
 
 	/**
@@ -191,10 +187,10 @@ public:
 	 * @param key Result parameter to fill with key bytes
 	 * @return Was agreement successful?
 	 */
-	inline bool agree(const Identity &id,void *const key) const
+	inline bool agree(const Identity& id, void* const key) const
 	{
 		if (_privateKey) {
-			C25519::agree(*_privateKey,id._publicKey,key,ZT_SYMMETRIC_KEY_SIZE);
+			C25519::agree(*_privateKey, id._publicKey, key, ZT_SYMMETRIC_KEY_SIZE);
 			return true;
 		}
 		return false;
@@ -203,7 +199,10 @@ public:
 	/**
 	 * @return This identity's address
 	 */
-	inline const Address &address() const { return _address; }
+	inline const Address& address() const
+	{
+		return _address;
+	}
 
 	/**
 	 * Serialize this identity (binary)
@@ -212,16 +211,16 @@ public:
 	 * @param includePrivate If true, include private key component (if present) (default: false)
 	 * @throws std::out_of_range Buffer too small
 	 */
-	template<unsigned int C>
-	inline void serialize(Buffer<C> &b,bool includePrivate = false) const
+	template <unsigned int C> inline void serialize(Buffer<C>& b, bool includePrivate = false) const
 	{
 		_address.appendTo(b);
-		b.append((uint8_t)0); // C25519/Ed25519 identity type
-		b.append(_publicKey.data,ZT_C25519_PUBLIC_KEY_LEN);
-		if ((_privateKey)&&(includePrivate)) {
+		b.append((uint8_t)0);	// C25519/Ed25519 identity type
+		b.append(_publicKey.data, ZT_C25519_PUBLIC_KEY_LEN);
+		if ((_privateKey) && (includePrivate)) {
 			b.append((unsigned char)ZT_C25519_PRIVATE_KEY_LEN);
-			b.append(_privateKey->data,ZT_C25519_PRIVATE_KEY_LEN);
-		} else {
+			b.append(_privateKey->data, ZT_C25519_PRIVATE_KEY_LEN);
+		}
+		else {
 			b.append((unsigned char)0);
 		}
 	}
@@ -238,22 +237,21 @@ public:
 	 * @throws std::out_of_range Serialized data invalid
 	 * @throws std::invalid_argument Serialized data invalid
 	 */
-	template<unsigned int C>
-	inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
+	template <unsigned int C> inline unsigned int deserialize(const Buffer<C>& b, unsigned int startAt = 0)
 	{
 		delete _privateKey;
-		_privateKey = (C25519::Private *)0;
+		_privateKey = (C25519::Private*)0;
 
 		unsigned int p = startAt;
 
-		_address.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
+		_address.setTo(b.field(p, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
 		p += ZT_ADDRESS_LENGTH;
 
 		if (b[p++] != 0) {
 			throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE;
 		}
 
-		memcpy(_publicKey.data,b.field(p,ZT_C25519_PUBLIC_KEY_LEN),ZT_C25519_PUBLIC_KEY_LEN);
+		memcpy(_publicKey.data, b.field(p, ZT_C25519_PUBLIC_KEY_LEN), ZT_C25519_PUBLIC_KEY_LEN);
 		p += ZT_C25519_PUBLIC_KEY_LEN;
 
 		unsigned int privateKeyLength = (unsigned int)b[p++];
@@ -262,7 +260,7 @@ public:
 				throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
 			}
 			_privateKey = new C25519::Private();
-			memcpy(_privateKey->data,b.field(p,ZT_C25519_PRIVATE_KEY_LEN),ZT_C25519_PRIVATE_KEY_LEN);
+			memcpy(_privateKey->data, b.field(p, ZT_C25519_PRIVATE_KEY_LEN), ZT_C25519_PRIVATE_KEY_LEN);
 			p += ZT_C25519_PRIVATE_KEY_LEN;
 		}
 
@@ -276,7 +274,7 @@ public:
 	 * @param buf Buffer to store string
 	 * @return ASCII string representation of identity
 	 */
-	char *toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const;
+	char* toString(bool includePrivate, char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const;
 
 	/**
 	 * Deserialize a human-friendly string
@@ -287,12 +285,15 @@ public:
 	 * @param str String to deserialize
 	 * @return True if deserialization appears successful
 	 */
-	bool fromString(const char *str);
+	bool fromString(const char* str);
 
 	/**
 	 * @return C25519 public key
 	 */
-	inline const C25519::Public &publicKey() const { return _publicKey; }
+	inline const C25519::Public& publicKey() const
+	{
+		return _publicKey;
+	}
 
 	/**
 	 * @return C25519 key pair (only returns valid pair if private key is present in this Identity object)
@@ -303,8 +304,9 @@ public:
 		pair.pub = _publicKey;
 		if (_privateKey) {
 			pair.priv = *_privateKey;
-		} else {
-			memset(pair.priv.data,0,ZT_C25519_PRIVATE_KEY_LEN);
+		}
+		else {
+			memset(pair.priv.data, 0, ZT_C25519_PRIVATE_KEY_LEN);
 		}
 		return pair;
 	}
@@ -312,21 +314,42 @@ public:
 	/**
 	 * @return True if this identity contains something
 	 */
-	inline operator bool() const { return (_address); }
+	inline operator bool() const
+	{
+		return (_address);
+	}
 
-	inline bool operator==(const Identity &id) const { return ((_address == id._address)&&(memcmp(_publicKey.data,id._publicKey.data,ZT_C25519_PUBLIC_KEY_LEN) == 0)); }
-	inline bool operator<(const Identity &id) const { return ((_address < id._address)||((_address == id._address)&&(memcmp(_publicKey.data,id._publicKey.data,ZT_C25519_PUBLIC_KEY_LEN) < 0))); }
-	inline bool operator!=(const Identity &id) const { return !(*this == id); }
-	inline bool operator>(const Identity &id) const { return (id < *this); }
-	inline bool operator<=(const Identity &id) const { return !(id < *this); }
-	inline bool operator>=(const Identity &id) const { return !(*this < id); }
+	inline bool operator==(const Identity& id) const
+	{
+		return ((_address == id._address) && (memcmp(_publicKey.data, id._publicKey.data, ZT_C25519_PUBLIC_KEY_LEN) == 0));
+	}
+	inline bool operator<(const Identity& id) const
+	{
+		return ((_address < id._address) || ((_address == id._address) && (memcmp(_publicKey.data, id._publicKey.data, ZT_C25519_PUBLIC_KEY_LEN) < 0)));
+	}
+	inline bool operator!=(const Identity& id) const
+	{
+		return ! (*this == id);
+	}
+	inline bool operator>(const Identity& id) const
+	{
+		return (id < *this);
+	}
+	inline bool operator<=(const Identity& id) const
+	{
+		return ! (id < *this);
+	}
+	inline bool operator>=(const Identity& id) const
+	{
+		return ! (*this < id);
+	}
 
-private:
+  private:
 	Address _address;
 	C25519::Public _publicKey;
-	C25519::Private *_privateKey;
+	C25519::Private* _privateKey;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

File diff suppressed because it is too large
+ 275 - 258
node/IncomingPacket.cpp


+ 39 - 45
node/IncomingPacket.hpp

@@ -14,13 +14,13 @@
 #ifndef ZT_INCOMINGPACKET_HPP
 #define ZT_INCOMINGPACKET_HPP
 
-#include <stdexcept>
-
+#include "MulticastGroup.hpp"
 #include "Packet.hpp"
 #include "Path.hpp"
-#include "Utils.hpp"
-#include "MulticastGroup.hpp"
 #include "Peer.hpp"
+#include "Utils.hpp"
+
+#include <stdexcept>
 
 /*
  * The big picture:
@@ -46,14 +46,9 @@ class Network;
 /**
  * Subclass of packet that handles the decoding of it
  */
-class IncomingPacket : public Packet
-{
-public:
-	IncomingPacket() :
-		Packet(),
-		_receiveTime(0),
-		_path(),
-		_authenticated(false)
+class IncomingPacket : public Packet {
+  public:
+	IncomingPacket() : Packet(), _receiveTime(0), _path(), _authenticated(false)
 	{
 	}
 
@@ -66,11 +61,7 @@ public:
 	 * @param now Current time
 	 * @throws std::out_of_range Range error processing packet
 	 */
-	IncomingPacket(const void *data,unsigned int len,const SharedPtr<Path> &path,int64_t now) :
-		Packet(data,len),
-		_receiveTime(now),
-		_path(path),
-		_authenticated(false)
+	IncomingPacket(const void* data, unsigned int len, const SharedPtr<Path>& path, int64_t now) : Packet(data, len), _receiveTime(now), _path(path), _authenticated(false)
 	{
 	}
 
@@ -83,9 +74,9 @@ public:
 	 * @param now Current time
 	 * @throws std::out_of_range Range error processing packet
 	 */
-	inline void init(const void *data,unsigned int len,const SharedPtr<Path> &path,int64_t now)
+	inline void init(const void* data, unsigned int len, const SharedPtr<Path>& path, int64_t now)
 	{
-		copyFrom(data,len);
+		copyFrom(data, len);
 		_receiveTime = now;
 		_path = path;
 		_authenticated = false;
@@ -104,44 +95,47 @@ public:
 	 * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
 	 * @return True if decoding and processing is complete, false if caller should try again
 	 */
-	bool tryDecode(const RuntimeEnvironment *RR,void *tPtr,int32_t flowId);
+	bool tryDecode(const RuntimeEnvironment* RR, void* tPtr, int32_t flowId);
 
 	/**
 	 * @return Time of packet receipt / start of decode
 	 */
-	inline uint64_t receiveTime() const { return _receiveTime; }
+	inline uint64_t receiveTime() const
+	{
+		return _receiveTime;
+	}
 
-private:
+  private:
 	// These are called internally to handle packet contents once it has
 	// been authenticated, decrypted, decompressed, and classified.
-	bool _doERROR(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
-	bool _doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool alreadyAuthenticated);
-	bool _doACK(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
-	bool _doQOS_MEASUREMENT(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
-	bool _doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
-	bool _doWHOIS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
-	bool _doRENDEZVOUS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
-	bool _doFRAME(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer,int32_t flowId);
-	bool _doEXT_FRAME(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer,int32_t flowId);
-	bool _doECHO(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
-	bool _doMULTICAST_LIKE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
-	bool _doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
-	bool _doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
-	bool _doNETWORK_CONFIG(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
-	bool _doMULTICAST_GATHER(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
-	bool _doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
-	bool _doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
-	bool _doUSER_MESSAGE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
-	bool _doREMOTE_TRACE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
-	bool _doPATH_NEGOTIATION_REQUEST(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
-
-	void _sendErrorNeedCredentials(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer,const uint64_t nwid);
+	bool _doERROR(const RuntimeEnvironment* RR, void* tPtr, const SharedPtr<Peer>& peer);
+	bool _doHELLO(const RuntimeEnvironment* RR, void* tPtr, const bool alreadyAuthenticated);
+	bool _doACK(const RuntimeEnvironment* RR, void* tPtr, const SharedPtr<Peer>& peer);
+	bool _doQOS_MEASUREMENT(const RuntimeEnvironment* RR, void* tPtr, const SharedPtr<Peer>& peer);
+	bool _doOK(const RuntimeEnvironment* RR, void* tPtr, const SharedPtr<Peer>& peer);
+	bool _doWHOIS(const RuntimeEnvironment* RR, void* tPtr, const SharedPtr<Peer>& peer);
+	bool _doRENDEZVOUS(const RuntimeEnvironment* RR, void* tPtr, const SharedPtr<Peer>& peer);
+	bool _doFRAME(const RuntimeEnvironment* RR, void* tPtr, const SharedPtr<Peer>& peer, int32_t flowId);
+	bool _doEXT_FRAME(const RuntimeEnvironment* RR, void* tPtr, const SharedPtr<Peer>& peer, int32_t flowId);
+	bool _doECHO(const RuntimeEnvironment* RR, void* tPtr, const SharedPtr<Peer>& peer);
+	bool _doMULTICAST_LIKE(const RuntimeEnvironment* RR, void* tPtr, const SharedPtr<Peer>& peer);
+	bool _doNETWORK_CREDENTIALS(const RuntimeEnvironment* RR, void* tPtr, const SharedPtr<Peer>& peer);
+	bool _doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment* RR, void* tPtr, const SharedPtr<Peer>& peer);
+	bool _doNETWORK_CONFIG(const RuntimeEnvironment* RR, void* tPtr, const SharedPtr<Peer>& peer);
+	bool _doMULTICAST_GATHER(const RuntimeEnvironment* RR, void* tPtr, const SharedPtr<Peer>& peer);
+	bool _doMULTICAST_FRAME(const RuntimeEnvironment* RR, void* tPtr, const SharedPtr<Peer>& peer);
+	bool _doPUSH_DIRECT_PATHS(const RuntimeEnvironment* RR, void* tPtr, const SharedPtr<Peer>& peer);
+	bool _doUSER_MESSAGE(const RuntimeEnvironment* RR, void* tPtr, const SharedPtr<Peer>& peer);
+	bool _doREMOTE_TRACE(const RuntimeEnvironment* RR, void* tPtr, const SharedPtr<Peer>& peer);
+	bool _doPATH_NEGOTIATION_REQUEST(const RuntimeEnvironment* RR, void* tPtr, const SharedPtr<Peer>& peer);
+
+	void _sendErrorNeedCredentials(const RuntimeEnvironment* RR, void* tPtr, const SharedPtr<Peer>& peer, const uint64_t nwid);
 
 	uint64_t _receiveTime;
 	SharedPtr<Path> _path;
 	bool _authenticated;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 154 - 145
node/InetAddress.cpp

@@ -11,132 +11,132 @@
  */
 /****/
 
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-
-#include <string>
+#include "InetAddress.hpp"
 
 #include "Constants.hpp"
-#include "InetAddress.hpp"
 #include "Utils.hpp"
 
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <string>
+
 namespace ZeroTier {
 
-const InetAddress InetAddress::LO4((const void *)("\x7f\x00\x00\x01"),4,0);
-const InetAddress InetAddress::LO6((const void *)("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"),16,0);
+const InetAddress InetAddress::LO4((const void*)("\x7f\x00\x00\x01"), 4, 0);
+const InetAddress InetAddress::LO6((const void*)("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"), 16, 0);
 
 InetAddress::IpScope InetAddress::ipScope() const
 {
-	switch(ss_family) {
-
+	switch (ss_family) {
 		case AF_INET: {
-			const uint32_t ip = Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr);
-			switch(ip >> 24) {
+			const uint32_t ip = Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in*>(this)->sin_addr.s_addr);
+			switch (ip >> 24) {
 				case 0x00:
-					return IP_SCOPE_NONE;           // 0.0.0.0/8 (reserved, never used)
+					return IP_SCOPE_NONE;	// 0.0.0.0/8 (reserved, never used)
 				case 0x06:
-					return IP_SCOPE_PSEUDOPRIVATE;  // 6.0.0.0/8 (US Army)
+					return IP_SCOPE_PSEUDOPRIVATE;	 // 6.0.0.0/8 (US Army)
 				case 0x0a:
-					return IP_SCOPE_PRIVATE;        // 10.0.0.0/8
+					return IP_SCOPE_PRIVATE;   // 10.0.0.0/8
 				case 0x0b:
-					return IP_SCOPE_PSEUDOPRIVATE;  // 11.0.0.0/8 (US DoD)
+					return IP_SCOPE_PSEUDOPRIVATE;	 // 11.0.0.0/8 (US DoD)
 				case 0x15:
-					return IP_SCOPE_PSEUDOPRIVATE;  // 21.0.0.0/8 (US DDN-RVN)
+					return IP_SCOPE_PSEUDOPRIVATE;	 // 21.0.0.0/8 (US DDN-RVN)
 				case 0x16:
-					return IP_SCOPE_PSEUDOPRIVATE;  // 22.0.0.0/8 (US DISA)
+					return IP_SCOPE_PSEUDOPRIVATE;	 // 22.0.0.0/8 (US DISA)
 				case 0x19:
-					return IP_SCOPE_PSEUDOPRIVATE;  // 25.0.0.0/8 (UK Ministry of Defense)
+					return IP_SCOPE_PSEUDOPRIVATE;	 // 25.0.0.0/8 (UK Ministry of Defense)
 				case 0x1a:
-					return IP_SCOPE_PSEUDOPRIVATE;  // 26.0.0.0/8 (US DISA)
+					return IP_SCOPE_PSEUDOPRIVATE;	 // 26.0.0.0/8 (US DISA)
 				case 0x1c:
-					return IP_SCOPE_PSEUDOPRIVATE;  // 28.0.0.0/8 (US DSI-North)
+					return IP_SCOPE_PSEUDOPRIVATE;	 // 28.0.0.0/8 (US DSI-North)
 				case 0x1d:
-					return IP_SCOPE_PSEUDOPRIVATE;  // 29.0.0.0/8 (US DISA)
+					return IP_SCOPE_PSEUDOPRIVATE;	 // 29.0.0.0/8 (US DISA)
 				case 0x1e:
-					return IP_SCOPE_PSEUDOPRIVATE;  // 30.0.0.0/8 (US DISA)
+					return IP_SCOPE_PSEUDOPRIVATE;	 // 30.0.0.0/8 (US DISA)
 				case 0x33:
-					return IP_SCOPE_PSEUDOPRIVATE;  // 51.0.0.0/8 (UK Department of Social Security)
+					return IP_SCOPE_PSEUDOPRIVATE;	 // 51.0.0.0/8 (UK Department of Social Security)
 				case 0x37:
-					return IP_SCOPE_PSEUDOPRIVATE;  // 55.0.0.0/8 (US DoD)
+					return IP_SCOPE_PSEUDOPRIVATE;	 // 55.0.0.0/8 (US DoD)
 				case 0x38:
-					return IP_SCOPE_PSEUDOPRIVATE;  // 56.0.0.0/8 (US Postal Service)
+					return IP_SCOPE_PSEUDOPRIVATE;	 // 56.0.0.0/8 (US Postal Service)
 				case 0x64:
 					if ((ip & 0xffc00000) == 0x64400000) {
-						return IP_SCOPE_PRIVATE;    // 100.64.0.0/10
+						return IP_SCOPE_PRIVATE;   // 100.64.0.0/10
 					}
 					break;
 				case 0x7f:
-					return IP_SCOPE_LOOPBACK;       // 127.0.0.0/8
+					return IP_SCOPE_LOOPBACK;	// 127.0.0.0/8
 				case 0xa9:
 					if ((ip & 0xffff0000) == 0xa9fe0000) {
-					 	return IP_SCOPE_LINK_LOCAL; // 169.254.0.0/16
+						return IP_SCOPE_LINK_LOCAL;	  // 169.254.0.0/16
 					}
 					break;
 				case 0xac:
 					if ((ip & 0xfff00000) == 0xac100000) {
-						return IP_SCOPE_PRIVATE;    // 172.16.0.0/12
+						return IP_SCOPE_PRIVATE;   // 172.16.0.0/12
 					}
 					break;
 				case 0xc0:
 					if ((ip & 0xffff0000) == 0xc0a80000) {
-						return IP_SCOPE_PRIVATE;    // 192.168.0.0/16
+						return IP_SCOPE_PRIVATE;   // 192.168.0.0/16
 					}
 					if ((ip & 0xffffff00) == 0xc0000200) {
-						return IP_SCOPE_PRIVATE;    // 192.0.2.0/24
+						return IP_SCOPE_PRIVATE;   // 192.0.2.0/24
 					}
 					break;
 				case 0xc6:
 					if ((ip & 0xfffe0000) == 0xc6120000) {
-						return IP_SCOPE_PRIVATE;    // 198.18.0.0/15
+						return IP_SCOPE_PRIVATE;   // 198.18.0.0/15
 					}
 					if ((ip & 0xffffff00) == 0xc6336400) {
-						return IP_SCOPE_PRIVATE;    // 198.51.100.0/24
+						return IP_SCOPE_PRIVATE;   // 198.51.100.0/24
 					}
 					break;
 				case 0xcb:
 					if ((ip & 0xffffff00) == 0xcb007100) {
-						return IP_SCOPE_PRIVATE;    // 203.0.113.0/24
+						return IP_SCOPE_PRIVATE;   // 203.0.113.0/24
 					}
 					break;
 				case 0xff:
-					return IP_SCOPE_NONE;           // 255.0.0.0/8 (broadcast, or unused/unusable)
+					return IP_SCOPE_NONE;	// 255.0.0.0/8 (broadcast, or unused/unusable)
 			}
-			switch(ip >> 28) {
+			switch (ip >> 28) {
 				case 0xe:
-					return IP_SCOPE_MULTICAST;      // 224.0.0.0/4
+					return IP_SCOPE_MULTICAST;	 // 224.0.0.0/4
 				case 0xf:
-					return IP_SCOPE_PSEUDOPRIVATE;  // 240.0.0.0/4 ("reserved," usually unusable)
+					return IP_SCOPE_PSEUDOPRIVATE;	 // 240.0.0.0/4 ("reserved," usually unusable)
 			}
 			return IP_SCOPE_GLOBAL;
-		}	break;
+		} break;
 
 		case AF_INET6: {
-			const unsigned char *ip = reinterpret_cast<const unsigned char *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
+			const unsigned char* ip = reinterpret_cast<const unsigned char*>(reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_addr.s6_addr);
 			if ((ip[0] & 0xf0) == 0xf0) {
 				if (ip[0] == 0xff) {
-					return IP_SCOPE_MULTICAST;      // ff00::/8
+					return IP_SCOPE_MULTICAST;	 // ff00::/8
 				}
-				if ((ip[0] == 0xfe)&&((ip[1] & 0xc0) == 0x80)) {
+				if ((ip[0] == 0xfe) && ((ip[1] & 0xc0) == 0x80)) {
 					unsigned int k = 2;
-					while ((!ip[k])&&(k < 15)) {
+					while ((! ip[k]) && (k < 15)) {
 						++k;
 					}
-					if ((k == 15)&&(ip[15] == 0x01)) {
-						return IP_SCOPE_LOOPBACK;   // fe80::1/128
-					} else {
-						return IP_SCOPE_LINK_LOCAL; // fe80::/10
+					if ((k == 15) && (ip[15] == 0x01)) {
+						return IP_SCOPE_LOOPBACK;	// fe80::1/128
+					}
+					else {
+						return IP_SCOPE_LINK_LOCAL;	  // fe80::/10
 					}
 				}
 				if ((ip[0] & 0xfe) == 0xfc) {
-					return IP_SCOPE_PRIVATE;        // fc00::/7
+					return IP_SCOPE_PRIVATE;   // fc00::/7
 				}
 			}
 
 			// :::ffff:127.0.0.1
 			// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x7f, 0, 0, 1
 			unsigned int k = 0;
-			while ((!ip[k])&&(k < 9)) {
+			while ((! ip[k]) && (k < 9)) {
 				++k;
 			}
 			if (k == 9) {
@@ -146,92 +146,92 @@ InetAddress::IpScope InetAddress::ipScope() const
 			}
 
 			k = 0;
-			while ((!ip[k])&&(k < 15)) {
+			while ((! ip[k]) && (k < 15)) {
 				++k;
 			}
-			if (k == 15) { // all 0's except last byte
+			if (k == 15) {	 // all 0's except last byte
 				if (ip[15] == 0x01) {
-					return IP_SCOPE_LOOPBACK;       // ::1/128
+					return IP_SCOPE_LOOPBACK;	// ::1/128
 				}
 				if (ip[15] == 0x00) {
-					return IP_SCOPE_NONE;           // ::/128
+					return IP_SCOPE_NONE;	// ::/128
 				}
 			}
 			return IP_SCOPE_GLOBAL;
-		}	break;
-
+		} break;
 	}
 
 	return IP_SCOPE_NONE;
 }
 
-void InetAddress::set(const void *ipBytes,unsigned int ipLen,unsigned int port)
+void InetAddress::set(const void* ipBytes, unsigned int ipLen, unsigned int port)
 {
-	memset(this,0,sizeof(InetAddress));
+	memset(this, 0, sizeof(InetAddress));
 	if (ipLen == 4) {
 		uint32_t ipb[1];
-		memcpy(ipb,ipBytes,4);
+		memcpy(ipb, ipBytes, 4);
 		ss_family = AF_INET;
-		reinterpret_cast<struct sockaddr_in *>(this)->sin_addr.s_addr = ipb[0];
-		reinterpret_cast<struct sockaddr_in *>(this)->sin_port = Utils::hton((uint16_t)port);
-	} else if (ipLen == 16) {
+		reinterpret_cast<struct sockaddr_in*>(this)->sin_addr.s_addr = ipb[0];
+		reinterpret_cast<struct sockaddr_in*>(this)->sin_port = Utils::hton((uint16_t)port);
+	}
+	else if (ipLen == 16) {
 		ss_family = AF_INET6;
-		memcpy(reinterpret_cast<struct sockaddr_in6 *>(this)->sin6_addr.s6_addr,ipBytes,16);
-		reinterpret_cast<struct sockaddr_in6 *>(this)->sin6_port = Utils::hton((uint16_t)port);
+		memcpy(reinterpret_cast<struct sockaddr_in6*>(this)->sin6_addr.s6_addr, ipBytes, 16);
+		reinterpret_cast<struct sockaddr_in6*>(this)->sin6_port = Utils::hton((uint16_t)port);
 	}
 }
 
-char *InetAddress::toString(char buf[64]) const
+char* InetAddress::toString(char buf[64]) const
 {
-	char *p = toIpString(buf);
+	char* p = toIpString(buf);
 	if (*p) {
 		while (*p) {
 			++p;
 		}
 		*(p++) = '/';
-		Utils::decimal(port(),p);
+		Utils::decimal(port(), p);
 	}
 	return buf;
 }
 
-char *InetAddress::toIpString(char buf[64]) const
+char* InetAddress::toIpString(char buf[64]) const
 {
 	buf[0] = (char)0;
-	switch(ss_family) {
+	switch (ss_family) {
 		case AF_INET: {
 #ifdef _WIN32
-			inet_ntop(AF_INET, (void*)&reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr, buf, INET_ADDRSTRLEN);
+			inet_ntop(AF_INET, (void*)&reinterpret_cast<const struct sockaddr_in*>(this)->sin_addr.s_addr, buf, INET_ADDRSTRLEN);
 #else
-			inet_ntop(AF_INET, &reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr, buf, INET_ADDRSTRLEN);
+			inet_ntop(AF_INET, &reinterpret_cast<const struct sockaddr_in*>(this)->sin_addr.s_addr, buf, INET_ADDRSTRLEN);
 #endif
- 		}	break;
+		} break;
 
 		case AF_INET6: {
 #ifdef _WIN32
-			inet_ntop(AF_INET6, (void*)reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr, buf, INET6_ADDRSTRLEN);
+			inet_ntop(AF_INET6, (void*)reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_addr.s6_addr, buf, INET6_ADDRSTRLEN);
 #else
-			inet_ntop(AF_INET6, reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr, buf, INET6_ADDRSTRLEN);
+			inet_ntop(AF_INET6, reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_addr.s6_addr, buf, INET6_ADDRSTRLEN);
 #endif
-		}	break;
+		} break;
 	}
 	return buf;
 }
 
-bool InetAddress::fromString(const char *ipSlashPort)
+bool InetAddress::fromString(const char* ipSlashPort)
 {
 	char buf[64];
 
-	memset(this,0,sizeof(InetAddress));
+	memset(this, 0, sizeof(InetAddress));
 
-	if (!*ipSlashPort) {
+	if (! *ipSlashPort) {
 		return true;
 	}
-	if (!Utils::scopy(buf,sizeof(buf),ipSlashPort)) {
+	if (! Utils::scopy(buf, sizeof(buf), ipSlashPort)) {
 		return false;
 	}
 
-	char *portAt = buf;
-	while ((*portAt)&&(*portAt != '/')) {
+	char* portAt = buf;
+	while ((*portAt) && (*portAt != '/')) {
 		++portAt;
 	}
 	unsigned int port = 0;
@@ -240,19 +240,21 @@ bool InetAddress::fromString(const char *ipSlashPort)
 		port = Utils::strToUInt(portAt) & 0xffff;
 	}
 
-	if (strchr(buf,':')) {
-		struct sockaddr_in6 *const in6 = reinterpret_cast<struct sockaddr_in6 *>(this);
+	if (strchr(buf, ':')) {
+		struct sockaddr_in6* const in6 = reinterpret_cast<struct sockaddr_in6*>(this);
 		inet_pton(AF_INET6, buf, &in6->sin6_addr.s6_addr);
 		in6->sin6_family = AF_INET6;
 		in6->sin6_port = Utils::hton((uint16_t)port);
 		return true;
-	} else if (strchr(buf,'.')) {
-		struct sockaddr_in *const in = reinterpret_cast<struct sockaddr_in *>(this);
+	}
+	else if (strchr(buf, '.')) {
+		struct sockaddr_in* const in = reinterpret_cast<struct sockaddr_in*>(this);
 		inet_pton(AF_INET, buf, &in->sin_addr.s_addr);
 		in->sin_family = AF_INET;
 		in->sin_port = Utils::hton((uint16_t)port);
 		return true;
-	} else {
+	}
+	else {
 		return false;
 	}
 }
@@ -260,22 +262,23 @@ bool InetAddress::fromString(const char *ipSlashPort)
 InetAddress InetAddress::netmask() const
 {
 	InetAddress r(*this);
-	switch(r.ss_family) {
+	switch (r.ss_family) {
 		case AF_INET:
-			reinterpret_cast<struct sockaddr_in *>(&r)->sin_addr.s_addr = Utils::hton((uint32_t)(0xffffffff << (32 - netmaskBits())));
+			reinterpret_cast<struct sockaddr_in*>(&r)->sin_addr.s_addr = Utils::hton((uint32_t)(0xffffffff << (32 - netmaskBits())));
 			break;
 		case AF_INET6: {
 			uint64_t nm[2];
 			const unsigned int bits = netmaskBits();
-			if(bits) {
+			if (bits) {
 				nm[0] = Utils::hton((uint64_t)((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits))));
 				nm[1] = Utils::hton((uint64_t)((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits))));
-			} else {
+			}
+			else {
 				nm[0] = 0;
 				nm[1] = 0;
 			}
-			memcpy(reinterpret_cast<struct sockaddr_in6 *>(&r)->sin6_addr.s6_addr,nm,16);
-		}	break;
+			memcpy(reinterpret_cast<struct sockaddr_in6*>(&r)->sin6_addr.s6_addr, nm, 16);
+		} break;
 	}
 	return r;
 }
@@ -284,7 +287,7 @@ InetAddress InetAddress::broadcast() const
 {
 	if (ss_family == AF_INET) {
 		InetAddress r(*this);
-		reinterpret_cast<struct sockaddr_in *>(&r)->sin_addr.s_addr |= Utils::hton((uint32_t)(0xffffffff >> netmaskBits()));
+		reinterpret_cast<struct sockaddr_in*>(&r)->sin_addr.s_addr |= Utils::hton((uint32_t)(0xffffffff >> netmaskBits()));
 		return r;
 	}
 	return InetAddress();
@@ -293,34 +296,34 @@ InetAddress InetAddress::broadcast() const
 InetAddress InetAddress::network() const
 {
 	InetAddress r(*this);
-	switch(r.ss_family) {
+	switch (r.ss_family) {
 		case AF_INET:
-			reinterpret_cast<struct sockaddr_in *>(&r)->sin_addr.s_addr &= Utils::hton((uint32_t)(0xffffffff << (32 - netmaskBits())));
+			reinterpret_cast<struct sockaddr_in*>(&r)->sin_addr.s_addr &= Utils::hton((uint32_t)(0xffffffff << (32 - netmaskBits())));
 			break;
 		case AF_INET6: {
 			uint64_t nm[2];
 			const unsigned int bits = netmaskBits();
-			memcpy(nm,reinterpret_cast<struct sockaddr_in6 *>(&r)->sin6_addr.s6_addr,16);
+			memcpy(nm, reinterpret_cast<struct sockaddr_in6*>(&r)->sin6_addr.s6_addr, 16);
 			nm[0] &= Utils::hton((uint64_t)((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits))));
 			nm[1] &= Utils::hton((uint64_t)((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits))));
-			memcpy(reinterpret_cast<struct sockaddr_in6 *>(&r)->sin6_addr.s6_addr,nm,16);
-		}	break;
+			memcpy(reinterpret_cast<struct sockaddr_in6*>(&r)->sin6_addr.s6_addr, nm, 16);
+		} break;
 	}
 	return r;
 }
 
-bool InetAddress::isEqualPrefix(const InetAddress &addr) const
+bool InetAddress::isEqualPrefix(const InetAddress& addr) const
 {
 	if (addr.ss_family == ss_family) {
-		switch(ss_family) {
+		switch (ss_family) {
 			case AF_INET6: {
 				const InetAddress mask(netmask());
 				InetAddress addr_mask(addr.netmask());
-				const uint8_t *n = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(&addr_mask)->sin6_addr.s6_addr);
-				const uint8_t *m = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(&mask)->sin6_addr.s6_addr);
-				const uint8_t *a = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(&addr)->sin6_addr.s6_addr);
-				const uint8_t *b = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
-				for(unsigned int i=0;i<16;++i) {
+				const uint8_t* n = reinterpret_cast<const uint8_t*>(reinterpret_cast<const struct sockaddr_in6*>(&addr_mask)->sin6_addr.s6_addr);
+				const uint8_t* m = reinterpret_cast<const uint8_t*>(reinterpret_cast<const struct sockaddr_in6*>(&mask)->sin6_addr.s6_addr);
+				const uint8_t* a = reinterpret_cast<const uint8_t*>(reinterpret_cast<const struct sockaddr_in6*>(&addr)->sin6_addr.s6_addr);
+				const uint8_t* b = reinterpret_cast<const uint8_t*>(reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_addr.s6_addr);
+				for (unsigned int i = 0; i < 16; ++i) {
 					if ((a[i] & m[i]) != (b[i] & n[i])) {
 						return false;
 					}
@@ -332,23 +335,24 @@ bool InetAddress::isEqualPrefix(const InetAddress &addr) const
 	return false;
 }
 
-bool InetAddress::containsAddress(const InetAddress &addr) const
+bool InetAddress::containsAddress(const InetAddress& addr) const
 {
 	if (addr.ss_family == ss_family) {
-		switch(ss_family) {
+		switch (ss_family) {
 			case AF_INET: {
 				const unsigned int bits = netmaskBits();
 				if (bits == 0) {
 					return true;
 				}
-				return ( (Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(&addr)->sin_addr.s_addr) >> (32 - bits)) == (Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr) >> (32 - bits)) );
+				return (
+					(Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in*>(&addr)->sin_addr.s_addr) >> (32 - bits)) == (Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in*>(this)->sin_addr.s_addr) >> (32 - bits)));
 			}
 			case AF_INET6: {
 				const InetAddress mask(netmask());
-				const uint8_t *m = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(&mask)->sin6_addr.s6_addr);
-				const uint8_t *a = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(&addr)->sin6_addr.s6_addr);
-				const uint8_t *b = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
-				for(unsigned int i=0;i<16;++i) {
+				const uint8_t* m = reinterpret_cast<const uint8_t*>(reinterpret_cast<const struct sockaddr_in6*>(&mask)->sin6_addr.s6_addr);
+				const uint8_t* a = reinterpret_cast<const uint8_t*>(reinterpret_cast<const struct sockaddr_in6*>(&addr)->sin6_addr.s6_addr);
+				const uint8_t* b = reinterpret_cast<const uint8_t*>(reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_addr.s6_addr);
+				for (unsigned int i = 0; i < 16; ++i) {
 					if ((a[i] & m[i]) != b[i]) {
 						return false;
 					}
@@ -362,7 +366,7 @@ bool InetAddress::containsAddress(const InetAddress &addr) const
 
 bool InetAddress::isNetwork() const
 {
-	switch(ss_family) {
+	switch (ss_family) {
 		case AF_INET: {
 			unsigned int bits = netmaskBits();
 			if (bits <= 0) {
@@ -371,7 +375,7 @@ bool InetAddress::isNetwork() const
 			if (bits >= 32) {
 				return false;
 			}
-			uint32_t ip = Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr);
+			uint32_t ip = Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in*>(this)->sin_addr.s_addr);
 			return ((ip & (0xffffffff >> bits)) == 0);
 		}
 		case AF_INET6: {
@@ -382,7 +386,7 @@ bool InetAddress::isNetwork() const
 			if (bits >= 128) {
 				return false;
 			}
-			const unsigned char *ip = reinterpret_cast<const unsigned char *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
+			const unsigned char* ip = reinterpret_cast<const unsigned char*>(reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_addr.s6_addr);
 			unsigned int p = bits / 8;
 			if ((ip[p++] & (0xff >> (bits % 8))) != 0) {
 				return false;
@@ -398,55 +402,60 @@ bool InetAddress::isNetwork() const
 	return false;
 }
 
-bool InetAddress::operator==(const InetAddress &a) const
+bool InetAddress::operator==(const InetAddress& a) const
 {
 	if (ss_family == a.ss_family) {
-		switch(ss_family) {
+		switch (ss_family) {
 			case AF_INET:
 				return (
-					(reinterpret_cast<const struct sockaddr_in *>(this)->sin_port == reinterpret_cast<const struct sockaddr_in *>(&a)->sin_port)&&
-					(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr == reinterpret_cast<const struct sockaddr_in *>(&a)->sin_addr.s_addr));
+					(reinterpret_cast<const struct sockaddr_in*>(this)->sin_port == reinterpret_cast<const struct sockaddr_in*>(&a)->sin_port)
+					&& (reinterpret_cast<const struct sockaddr_in*>(this)->sin_addr.s_addr == reinterpret_cast<const struct sockaddr_in*>(&a)->sin_addr.s_addr));
 				break;
 			case AF_INET6:
 				return (
-					(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_port == reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_port)&&
-					(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_flowinfo == reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_flowinfo)&&
-					(memcmp(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr,reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_addr.s6_addr,16) == 0)&&
-					(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_scope_id == reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_scope_id));
+					(reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_port == reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_port)
+					&& (reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_flowinfo == reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_flowinfo)
+					&& (memcmp(reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_addr.s6_addr, reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_addr.s6_addr, 16) == 0)
+					&& (reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_scope_id == reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_scope_id));
 				break;
 			default:
-				return (memcmp(this,&a,sizeof(InetAddress)) == 0);
+				return (memcmp(this, &a, sizeof(InetAddress)) == 0);
 		}
 	}
 	return false;
 }
 
-bool InetAddress::operator<(const InetAddress &a) const
+bool InetAddress::operator<(const InetAddress& a) const
 {
 	if (ss_family < a.ss_family) {
 		return true;
-	} else if (ss_family == a.ss_family) {
-		switch(ss_family) {
+	}
+	else if (ss_family == a.ss_family) {
+		switch (ss_family) {
 			case AF_INET:
-				if (reinterpret_cast<const struct sockaddr_in *>(this)->sin_port < reinterpret_cast<const struct sockaddr_in *>(&a)->sin_port) {
+				if (reinterpret_cast<const struct sockaddr_in*>(this)->sin_port < reinterpret_cast<const struct sockaddr_in*>(&a)->sin_port) {
 					return true;
-				} else if (reinterpret_cast<const struct sockaddr_in *>(this)->sin_port == reinterpret_cast<const struct sockaddr_in *>(&a)->sin_port) {
-					if (reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr < reinterpret_cast<const struct sockaddr_in *>(&a)->sin_addr.s_addr) {
+				}
+				else if (reinterpret_cast<const struct sockaddr_in*>(this)->sin_port == reinterpret_cast<const struct sockaddr_in*>(&a)->sin_port) {
+					if (reinterpret_cast<const struct sockaddr_in*>(this)->sin_addr.s_addr < reinterpret_cast<const struct sockaddr_in*>(&a)->sin_addr.s_addr) {
 						return true;
 					}
 				}
 				break;
 			case AF_INET6:
-				if (reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_port < reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_port) {
+				if (reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_port < reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_port) {
 					return true;
-				} else if (reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_port == reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_port) {
-					if (reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_flowinfo < reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_flowinfo) {
+				}
+				else if (reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_port == reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_port) {
+					if (reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_flowinfo < reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_flowinfo) {
 						return true;
-					} else if (reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_flowinfo == reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_flowinfo) {
-						if (memcmp(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr,reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_addr.s6_addr,16) < 0) {
+					}
+					else if (reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_flowinfo == reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_flowinfo) {
+						if (memcmp(reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_addr.s6_addr, reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_addr.s6_addr, 16) < 0) {
 							return true;
-						} else if (memcmp(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr,reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_addr.s6_addr,16) == 0) {
-							if (reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_scope_id < reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_scope_id) {
+						}
+						else if (memcmp(reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_addr.s6_addr, reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_addr.s6_addr, 16) == 0) {
+							if (reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_scope_id < reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_scope_id) {
 								return true;
 							}
 						}
@@ -454,13 +463,13 @@ bool InetAddress::operator<(const InetAddress &a) const
 				}
 				break;
 			default:
-				return (memcmp(this,&a,sizeof(InetAddress)) < 0);
+				return (memcmp(this, &a, sizeof(InetAddress)) < 0);
 		}
 	}
 	return false;
 }
 
-InetAddress InetAddress::makeIpv6LinkLocal(const MAC &mac)
+InetAddress InetAddress::makeIpv6LinkLocal(const MAC& mac)
 {
 	struct sockaddr_in6 sin6;
 	sin6.sin6_family = AF_INET6;
@@ -484,10 +493,10 @@ InetAddress InetAddress::makeIpv6LinkLocal(const MAC &mac)
 	return InetAddress(sin6);
 }
 
-InetAddress InetAddress::makeIpv6rfc4193(uint64_t nwid,uint64_t zeroTierAddress)
+InetAddress InetAddress::makeIpv6rfc4193(uint64_t nwid, uint64_t zeroTierAddress)
 {
 	InetAddress r;
-	struct sockaddr_in6 *const sin6 = reinterpret_cast<struct sockaddr_in6 *>(&r);
+	struct sockaddr_in6* const sin6 = reinterpret_cast<struct sockaddr_in6*>(&r);
 	sin6->sin6_family = AF_INET6;
 	sin6->sin6_addr.s6_addr[0] = 0xfd;
 	sin6->sin6_addr.s6_addr[1] = (uint8_t)(nwid >> 56);
@@ -505,15 +514,15 @@ InetAddress InetAddress::makeIpv6rfc4193(uint64_t nwid,uint64_t zeroTierAddress)
 	sin6->sin6_addr.s6_addr[13] = (uint8_t)(zeroTierAddress >> 16);
 	sin6->sin6_addr.s6_addr[14] = (uint8_t)(zeroTierAddress >> 8);
 	sin6->sin6_addr.s6_addr[15] = (uint8_t)zeroTierAddress;
-	sin6->sin6_port = Utils::hton((uint16_t)88); // /88 includes 0xfd + network ID, discriminating by device ID below that
+	sin6->sin6_port = Utils::hton((uint16_t)88);   // /88 includes 0xfd + network ID, discriminating by device ID below that
 	return r;
 }
 
-InetAddress InetAddress::makeIpv66plane(uint64_t nwid,uint64_t zeroTierAddress)
+InetAddress InetAddress::makeIpv66plane(uint64_t nwid, uint64_t zeroTierAddress)
 {
 	nwid ^= (nwid >> 32);
 	InetAddress r;
-	struct sockaddr_in6 *const sin6 = reinterpret_cast<struct sockaddr_in6 *>(&r);
+	struct sockaddr_in6* const sin6 = reinterpret_cast<struct sockaddr_in6*>(&r);
 	sin6->sin6_family = AF_INET6;
 	sin6->sin6_addr.s6_addr[0] = 0xfc;
 	sin6->sin6_addr.s6_addr[1] = (uint8_t)(nwid >> 24);
@@ -530,4 +539,4 @@ InetAddress InetAddress::makeIpv66plane(uint64_t nwid,uint64_t zeroTierAddress)
 	return r;
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier

+ 239 - 166
node/InetAddress.hpp

@@ -14,15 +14,15 @@
 #ifndef ZT_INETADDRESS_HPP
 #define ZT_INETADDRESS_HPP
 
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-
-#include "Constants.hpp"
 #include "../include/ZeroTierOne.h"
-#include "Utils.hpp"
-#include "MAC.hpp"
 #include "Buffer.hpp"
+#include "Constants.hpp"
+#include "MAC.hpp"
+#include "Utils.hpp"
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
 
 namespace ZeroTier {
 
@@ -39,8 +39,7 @@ namespace ZeroTier {
  * sockaddr_storage and used interchangeably. DO NOT change this by e.g.
  * adding non-static fields, since much code depends on this identity.
  */
-struct InetAddress : public sockaddr_storage
-{
+struct InetAddress : public sockaddr_storage {
 	/**
 	 * Loopback IPv4 address (no port)
 	 */
@@ -58,134 +57,177 @@ struct InetAddress : public sockaddr_storage
 	 * MUST remain that way or Path must be changed to reflect. Also be sure
 	 * to change ZT_INETADDRESS_MAX_SCOPE if the max changes.
 	 */
-	enum IpScope
-	{
-		IP_SCOPE_NONE = 0,          // NULL or not an IP address
-		IP_SCOPE_MULTICAST = 1,     // 224.0.0.0 and other V4/V6 multicast IPs
-		IP_SCOPE_LOOPBACK = 2,      // 127.0.0.1, ::1, etc.
-		IP_SCOPE_PSEUDOPRIVATE = 3, // 28.x.x.x, etc. -- unofficially unrouted IPv4 blocks often "bogarted"
-		IP_SCOPE_GLOBAL = 4,        // globally routable IP address (all others)
-		IP_SCOPE_LINK_LOCAL = 5,    // 169.254.x.x, IPv6 LL
-		IP_SCOPE_SHARED = 6,        // currently unused, formerly used for carrier-grade NAT ranges
-		IP_SCOPE_PRIVATE = 7        // 10.x.x.x, 192.168.x.x, etc.
+	enum IpScope {
+		IP_SCOPE_NONE = 0,			  // NULL or not an IP address
+		IP_SCOPE_MULTICAST = 1,		  // 224.0.0.0 and other V4/V6 multicast IPs
+		IP_SCOPE_LOOPBACK = 2,		  // 127.0.0.1, ::1, etc.
+		IP_SCOPE_PSEUDOPRIVATE = 3,	  // 28.x.x.x, etc. -- unofficially unrouted IPv4 blocks often "bogarted"
+		IP_SCOPE_GLOBAL = 4,		  // globally routable IP address (all others)
+		IP_SCOPE_LINK_LOCAL = 5,	  // 169.254.x.x, IPv6 LL
+		IP_SCOPE_SHARED = 6,		  // currently unused, formerly used for carrier-grade NAT ranges
+		IP_SCOPE_PRIVATE = 7		  // 10.x.x.x, 192.168.x.x, etc.
 	};
 
 	// Can be used with the unordered maps and sets in c++11. We don't use C++11 in the core
 	// but this is safe to put here.
-	struct Hasher
-	{
-		inline std::size_t operator()(const InetAddress &a) const { return (std::size_t)a.hashCode(); }
+	struct Hasher {
+		inline std::size_t operator()(const InetAddress& a) const
+		{
+			return (std::size_t)a.hashCode();
+		}
 	};
 
-	InetAddress() { memset(this,0,sizeof(InetAddress)); }
-	InetAddress(const InetAddress &a) { memcpy(this,&a,sizeof(InetAddress)); }
-	InetAddress(const InetAddress *a) { memcpy(this,a,sizeof(InetAddress)); }
-	InetAddress(const struct sockaddr_storage &ss) { *this = ss; }
-	InetAddress(const struct sockaddr_storage *ss) { *this = ss; }
-	InetAddress(const struct sockaddr &sa) { *this = sa; }
-	InetAddress(const struct sockaddr *sa) { *this = sa; }
-	InetAddress(const struct sockaddr_in &sa) { *this = sa; }
-	InetAddress(const struct sockaddr_in *sa) { *this = sa; }
-	InetAddress(const struct sockaddr_in6 &sa) { *this = sa; }
-	InetAddress(const struct sockaddr_in6 *sa) { *this = sa; }
-	InetAddress(const void *ipBytes,unsigned int ipLen,unsigned int port) { this->set(ipBytes,ipLen,port); }
-	InetAddress(const uint32_t ipv4,unsigned int port) { this->set(&ipv4,4,port); }
-	InetAddress(const char *ipSlashPort) { this->fromString(ipSlashPort); }
-
-	inline InetAddress &operator=(const InetAddress &a)
+	InetAddress()
+	{
+		memset(this, 0, sizeof(InetAddress));
+	}
+	InetAddress(const InetAddress& a)
+	{
+		memcpy(this, &a, sizeof(InetAddress));
+	}
+	InetAddress(const InetAddress* a)
+	{
+		memcpy(this, a, sizeof(InetAddress));
+	}
+	InetAddress(const struct sockaddr_storage& ss)
+	{
+		*this = ss;
+	}
+	InetAddress(const struct sockaddr_storage* ss)
+	{
+		*this = ss;
+	}
+	InetAddress(const struct sockaddr& sa)
+	{
+		*this = sa;
+	}
+	InetAddress(const struct sockaddr* sa)
+	{
+		*this = sa;
+	}
+	InetAddress(const struct sockaddr_in& sa)
+	{
+		*this = sa;
+	}
+	InetAddress(const struct sockaddr_in* sa)
+	{
+		*this = sa;
+	}
+	InetAddress(const struct sockaddr_in6& sa)
+	{
+		*this = sa;
+	}
+	InetAddress(const struct sockaddr_in6* sa)
+	{
+		*this = sa;
+	}
+	InetAddress(const void* ipBytes, unsigned int ipLen, unsigned int port)
+	{
+		this->set(ipBytes, ipLen, port);
+	}
+	InetAddress(const uint32_t ipv4, unsigned int port)
+	{
+		this->set(&ipv4, 4, port);
+	}
+	InetAddress(const char* ipSlashPort)
+	{
+		this->fromString(ipSlashPort);
+	}
+
+	inline InetAddress& operator=(const InetAddress& a)
 	{
 		if (&a != this) {
-			memcpy(this,&a,sizeof(InetAddress));
+			memcpy(this, &a, sizeof(InetAddress));
 		}
 		return *this;
 	}
 
-	inline InetAddress &operator=(const InetAddress *a)
+	inline InetAddress& operator=(const InetAddress* a)
 	{
 		if (a != this) {
-			memcpy(this,a,sizeof(InetAddress));
+			memcpy(this, a, sizeof(InetAddress));
 		}
 		return *this;
 	}
 
-	inline InetAddress &operator=(const struct sockaddr_storage &ss)
+	inline InetAddress& operator=(const struct sockaddr_storage& ss)
 	{
-		if (reinterpret_cast<const InetAddress *>(&ss) != this) {
-			memcpy(this,&ss,sizeof(InetAddress));
+		if (reinterpret_cast<const InetAddress*>(&ss) != this) {
+			memcpy(this, &ss, sizeof(InetAddress));
 		}
 		return *this;
 	}
 
-	inline InetAddress &operator=(const struct sockaddr_storage *ss)
+	inline InetAddress& operator=(const struct sockaddr_storage* ss)
 	{
-		if (reinterpret_cast<const InetAddress *>(ss) != this) {
-			memcpy(this,ss,sizeof(InetAddress));
+		if (reinterpret_cast<const InetAddress*>(ss) != this) {
+			memcpy(this, ss, sizeof(InetAddress));
 		}
 		return *this;
 	}
 
-	inline InetAddress &operator=(const struct sockaddr_in &sa)
+	inline InetAddress& operator=(const struct sockaddr_in& sa)
 	{
-		if (reinterpret_cast<const InetAddress *>(&sa) != this) {
-			memset(this,0,sizeof(InetAddress));
-			memcpy(this,&sa,sizeof(struct sockaddr_in));
+		if (reinterpret_cast<const InetAddress*>(&sa) != this) {
+			memset(this, 0, sizeof(InetAddress));
+			memcpy(this, &sa, sizeof(struct sockaddr_in));
 		}
 		return *this;
 	}
 
-	inline InetAddress &operator=(const struct sockaddr_in *sa)
+	inline InetAddress& operator=(const struct sockaddr_in* sa)
 	{
-		if (reinterpret_cast<const InetAddress *>(sa) != this) {
-			memset(this,0,sizeof(InetAddress));
-			memcpy(this,sa,sizeof(struct sockaddr_in));
+		if (reinterpret_cast<const InetAddress*>(sa) != this) {
+			memset(this, 0, sizeof(InetAddress));
+			memcpy(this, sa, sizeof(struct sockaddr_in));
 		}
 		return *this;
 	}
 
-	inline InetAddress &operator=(const struct sockaddr_in6 &sa)
+	inline InetAddress& operator=(const struct sockaddr_in6& sa)
 	{
-		if (reinterpret_cast<const InetAddress *>(&sa) != this) {
-			memset(this,0,sizeof(InetAddress));
-			memcpy(this,&sa,sizeof(struct sockaddr_in6));
+		if (reinterpret_cast<const InetAddress*>(&sa) != this) {
+			memset(this, 0, sizeof(InetAddress));
+			memcpy(this, &sa, sizeof(struct sockaddr_in6));
 		}
 		return *this;
 	}
 
-	inline InetAddress &operator=(const struct sockaddr_in6 *sa)
+	inline InetAddress& operator=(const struct sockaddr_in6* sa)
 	{
-		if (reinterpret_cast<const InetAddress *>(sa) != this) {
-			memset(this,0,sizeof(InetAddress));
-			memcpy(this,sa,sizeof(struct sockaddr_in6));
+		if (reinterpret_cast<const InetAddress*>(sa) != this) {
+			memset(this, 0, sizeof(InetAddress));
+			memcpy(this, sa, sizeof(struct sockaddr_in6));
 		}
 		return *this;
 	}
 
-	inline InetAddress &operator=(const struct sockaddr &sa)
+	inline InetAddress& operator=(const struct sockaddr& sa)
 	{
-		if (reinterpret_cast<const InetAddress *>(&sa) != this) {
-			memset(this,0,sizeof(InetAddress));
-			switch(sa.sa_family) {
+		if (reinterpret_cast<const InetAddress*>(&sa) != this) {
+			memset(this, 0, sizeof(InetAddress));
+			switch (sa.sa_family) {
 				case AF_INET:
-					memcpy(this,&sa,sizeof(struct sockaddr_in));
+					memcpy(this, &sa, sizeof(struct sockaddr_in));
 					break;
 				case AF_INET6:
-					memcpy(this,&sa,sizeof(struct sockaddr_in6));
+					memcpy(this, &sa, sizeof(struct sockaddr_in6));
 					break;
 			}
 		}
 		return *this;
 	}
 
-	inline InetAddress &operator=(const struct sockaddr *sa)
+	inline InetAddress& operator=(const struct sockaddr* sa)
 	{
-		if (reinterpret_cast<const InetAddress *>(sa) != this) {
-			memset(this,0,sizeof(InetAddress));
-			switch(sa->sa_family) {
+		if (reinterpret_cast<const InetAddress*>(sa) != this) {
+			memset(this, 0, sizeof(InetAddress));
+			switch (sa->sa_family) {
 				case AF_INET:
-					memcpy(this,sa,sizeof(struct sockaddr_in));
+					memcpy(this, sa, sizeof(struct sockaddr_in));
 					break;
 				case AF_INET6:
-					memcpy(this,sa,sizeof(struct sockaddr_in6));
+					memcpy(this, sa, sizeof(struct sockaddr_in6));
 					break;
 			}
 		}
@@ -204,7 +246,7 @@ struct InetAddress : public sockaddr_storage
 	 * @param ipLen Length of IP address: 4 or 16
 	 * @param port Port number or 0 for none
 	 */
-	void set(const void *ipBytes,unsigned int ipLen,unsigned int port);
+	void set(const void* ipBytes, unsigned int ipLen, unsigned int port);
 
 	/**
 	 * Set the port component
@@ -213,12 +255,12 @@ struct InetAddress : public sockaddr_storage
 	 */
 	inline void setPort(unsigned int port)
 	{
-		switch(ss_family) {
+		switch (ss_family) {
 			case AF_INET:
-				reinterpret_cast<struct sockaddr_in *>(this)->sin_port = Utils::hton((uint16_t)port);
+				reinterpret_cast<struct sockaddr_in*>(this)->sin_port = Utils::hton((uint16_t)port);
 				break;
 			case AF_INET6:
-				reinterpret_cast<struct sockaddr_in6 *>(this)->sin6_port = Utils::hton((uint16_t)port);
+				reinterpret_cast<struct sockaddr_in6*>(this)->sin6_port = Utils::hton((uint16_t)port);
 				break;
 		}
 	}
@@ -228,17 +270,17 @@ struct InetAddress : public sockaddr_storage
 	 */
 	inline bool isDefaultRoute() const
 	{
-		switch(ss_family) {
+		switch (ss_family) {
 			case AF_INET:
-				return ( (reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr == 0) && (reinterpret_cast<const struct sockaddr_in *>(this)->sin_port == 0) );
+				return ((reinterpret_cast<const struct sockaddr_in*>(this)->sin_addr.s_addr == 0) && (reinterpret_cast<const struct sockaddr_in*>(this)->sin_port == 0));
 			case AF_INET6:
-				const uint8_t *ipb = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
-				for(int i=0;i<16;++i) {
+				const uint8_t* ipb = reinterpret_cast<const uint8_t*>(reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_addr.s6_addr);
+				for (int i = 0; i < 16; ++i) {
 					if (ipb[i]) {
 						return false;
 					}
 				}
-				return (reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_port == 0);
+				return (reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_port == 0);
 		}
 		return false;
 	}
@@ -246,29 +288,29 @@ struct InetAddress : public sockaddr_storage
 	/**
 	 * @return ASCII IP/port format representation
 	 */
-	char *toString(char buf[64]) const;
+	char* toString(char buf[64]) const;
 
 	/**
 	 * @return IP portion only, in ASCII string format
 	 */
-	char *toIpString(char buf[64]) const;
+	char* toIpString(char buf[64]) const;
 
 	/**
 	 * @param ipSlashPort IP/port (port is optional, will be 0 if not included)
 	 * @return True if address appeared to be valid
 	 */
-	bool fromString(const char *ipSlashPort);
+	bool fromString(const char* ipSlashPort);
 
 	/**
 	 * @return Port or 0 if no port component defined
 	 */
 	inline unsigned int port() const
 	{
-		switch(ss_family) {
+		switch (ss_family) {
 			case AF_INET:
-				return Utils::ntoh((uint16_t)(reinterpret_cast<const struct sockaddr_in *>(this)->sin_port));
+				return Utils::ntoh((uint16_t)(reinterpret_cast<const struct sockaddr_in*>(this)->sin_port));
 			case AF_INET6:
-				return Utils::ntoh((uint16_t)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_port));
+				return Utils::ntoh((uint16_t)(reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_port));
 			default:
 				return 0;
 		}
@@ -283,7 +325,10 @@ struct InetAddress : public sockaddr_storage
 	 *
 	 * @return Netmask bits
 	 */
-	inline unsigned int netmaskBits() const { return port(); }
+	inline unsigned int netmaskBits() const
+	{
+		return port();
+	}
 
 	/**
 	 * @return True if netmask bits is valid for the address type
@@ -291,7 +336,7 @@ struct InetAddress : public sockaddr_storage
 	inline bool netmaskBitsValid() const
 	{
 		const unsigned int n = port();
-		switch(ss_family) {
+		switch (ss_family) {
 			case AF_INET:
 				return (n <= 32);
 			case AF_INET6:
@@ -308,7 +353,10 @@ struct InetAddress : public sockaddr_storage
 	 *
 	 * @return Gateway metric
 	 */
-	inline unsigned int metric() const { return port(); }
+	inline unsigned int metric() const
+	{
+		return port();
+	}
 
 	/**
 	 * Construct a full netmask as an InetAddress
@@ -340,7 +388,7 @@ struct InetAddress : public sockaddr_storage
 	 * @param addr Address to check
 	 * @return True if this IPv6 prefix matches the prefix of a given IPv6 address
 	 */
-	bool isEqualPrefix(const InetAddress &addr) const;
+	bool isEqualPrefix(const InetAddress& addr) const;
 
 	/**
 	 * Test whether this IP/netmask contains this address
@@ -348,28 +396,34 @@ struct InetAddress : public sockaddr_storage
 	 * @param addr Address to check
 	 * @return True if this IP/netmask (route) contains this address
 	 */
-	bool containsAddress(const InetAddress &addr) const;
+	bool containsAddress(const InetAddress& addr) const;
 
 	/**
 	 * @return True if this is an IPv4 address
 	 */
-	inline bool isV4() const { return (ss_family == AF_INET); }
+	inline bool isV4() const
+	{
+		return (ss_family == AF_INET);
+	}
 
 	/**
 	 * @return True if this is an IPv6 address
 	 */
-	inline bool isV6() const { return (ss_family == AF_INET6); }
+	inline bool isV6() const
+	{
+		return (ss_family == AF_INET6);
+	}
 
 	/**
 	 * @return pointer to raw address bytes or NULL if not available
 	 */
-	inline const void *rawIpData() const
+	inline const void* rawIpData() const
 	{
-		switch(ss_family) {
+		switch (ss_family) {
 			case AF_INET:
-				return (const void *)&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr);
+				return (const void*)&(reinterpret_cast<const struct sockaddr_in*>(this)->sin_addr.s_addr);
 			case AF_INET6:
-				return (const void *)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
+				return (const void*)(reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_addr.s6_addr);
 			default:
 				return 0;
 		}
@@ -381,14 +435,14 @@ struct InetAddress : public sockaddr_storage
 	inline InetAddress ipOnly() const
 	{
 		InetAddress r;
-		switch(ss_family) {
+		switch (ss_family) {
 			case AF_INET:
 				r.ss_family = AF_INET;
-				reinterpret_cast<struct sockaddr_in *>(&r)->sin_addr.s_addr = reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr;
+				reinterpret_cast<struct sockaddr_in*>(&r)->sin_addr.s_addr = reinterpret_cast<const struct sockaddr_in*>(this)->sin_addr.s_addr;
 				break;
 			case AF_INET6:
 				r.ss_family = AF_INET6;
-				memcpy(reinterpret_cast<struct sockaddr_in6 *>(&r)->sin6_addr.s6_addr,reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr,16);
+				memcpy(reinterpret_cast<struct sockaddr_in6*>(&r)->sin6_addr.s6_addr, reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_addr.s6_addr, 16);
 				break;
 		}
 		return r;
@@ -400,16 +454,16 @@ struct InetAddress : public sockaddr_storage
 	 * @param a InetAddress to compare again
 	 * @return True if only IP portions are equal (false for non-IP or null addresses)
 	 */
-	inline bool ipsEqual(const InetAddress &a) const
+	inline bool ipsEqual(const InetAddress& a) const
 	{
 		if (ss_family == a.ss_family) {
 			if (ss_family == AF_INET) {
-				return (reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr == reinterpret_cast<const struct sockaddr_in *>(&a)->sin_addr.s_addr);
+				return (reinterpret_cast<const struct sockaddr_in*>(this)->sin_addr.s_addr == reinterpret_cast<const struct sockaddr_in*>(&a)->sin_addr.s_addr);
 			}
 			if (ss_family == AF_INET6) {
-				return (memcmp(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr,reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_addr.s6_addr,16) == 0);
+				return (memcmp(reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_addr.s6_addr, reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_addr.s6_addr, 16) == 0);
 			}
-			return (memcmp(this,&a,sizeof(InetAddress)) == 0);
+			return (memcmp(this, &a, sizeof(InetAddress)) == 0);
 		}
 		return false;
 	}
@@ -422,16 +476,16 @@ struct InetAddress : public sockaddr_storage
 	 * @param a InetAddress to compare again
 	 * @return True if only IP portions are equal (false for non-IP or null addresses)
 	 */
-	inline bool ipsEqual2(const InetAddress &a) const
+	inline bool ipsEqual2(const InetAddress& a) const
 	{
 		if (ss_family == a.ss_family) {
 			if (ss_family == AF_INET) {
-				return (reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr == reinterpret_cast<const struct sockaddr_in *>(&a)->sin_addr.s_addr);
+				return (reinterpret_cast<const struct sockaddr_in*>(this)->sin_addr.s_addr == reinterpret_cast<const struct sockaddr_in*>(&a)->sin_addr.s_addr);
 			}
 			if (ss_family == AF_INET6) {
-				return (memcmp(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr, reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_addr.s6_addr, 8) == 0);
+				return (memcmp(reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_addr.s6_addr, reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_addr.s6_addr, 8) == 0);
 			}
-			return (memcmp(this,&a,sizeof(InetAddress)) == 0);
+			return (memcmp(this, &a, sizeof(InetAddress)) == 0);
 		}
 		return false;
 	}
@@ -439,19 +493,21 @@ struct InetAddress : public sockaddr_storage
 	inline unsigned long hashCode() const
 	{
 		if (ss_family == AF_INET) {
-			return ((unsigned long)reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr + (unsigned long)reinterpret_cast<const struct sockaddr_in *>(this)->sin_port);
-		} else if (ss_family == AF_INET6) {
-			unsigned long tmp = reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_port;
-			const uint8_t *a = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
-			for(long i=0;i<16;++i) {
-				reinterpret_cast<uint8_t *>(&tmp)[i % sizeof(tmp)] ^= a[i];
+			return ((unsigned long)reinterpret_cast<const struct sockaddr_in*>(this)->sin_addr.s_addr + (unsigned long)reinterpret_cast<const struct sockaddr_in*>(this)->sin_port);
+		}
+		else if (ss_family == AF_INET6) {
+			unsigned long tmp = reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_port;
+			const uint8_t* a = reinterpret_cast<const uint8_t*>(reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_addr.s6_addr);
+			for (long i = 0; i < 16; ++i) {
+				reinterpret_cast<uint8_t*>(&tmp)[i % sizeof(tmp)] ^= a[i];
 			}
 			return tmp;
-		} else {
-			unsigned long tmp = reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_port;
-			const uint8_t *a = reinterpret_cast<const uint8_t *>(this);
-			for(long i=0;i<(long)sizeof(InetAddress);++i) {
-				reinterpret_cast<uint8_t *>(&tmp)[i % sizeof(tmp)] ^= a[i];
+		}
+		else {
+			unsigned long tmp = reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_port;
+			const uint8_t* a = reinterpret_cast<const uint8_t*>(this);
+			for (long i = 0; i < (long)sizeof(InetAddress); ++i) {
+				reinterpret_cast<uint8_t*>(&tmp)[i % sizeof(tmp)] ^= a[i];
 			}
 			return tmp;
 		}
@@ -460,7 +516,10 @@ struct InetAddress : public sockaddr_storage
 	/**
 	 * Set to null/zero
 	 */
-	inline void zero() { memset(this,0,sizeof(InetAddress)); }
+	inline void zero()
+	{
+		memset(this, 0, sizeof(InetAddress));
+	}
 
 	/**
 	 * Check whether this is a network/route rather than an IP assignment
@@ -474,18 +533,18 @@ struct InetAddress : public sockaddr_storage
 
 	/**
 	 * Find the total number of prefix bits that match between this IP and another
-	 * 
+	 *
 	 * @param b Second IP to compare with
 	 * @return Number of matching prefix bits or 0 if none match or IPs are of different families (e.g. v4 and v6)
 	 */
-	inline unsigned int matchingPrefixBits(const InetAddress &b) const
+	inline unsigned int matchingPrefixBits(const InetAddress& b) const
 	{
 		unsigned int c = 0;
 		if (ss_family == b.ss_family) {
-			switch(ss_family) {
+			switch (ss_family) {
 				case AF_INET: {
-					uint32_t ip0 = Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr);
-					uint32_t ip1 = Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(&b)->sin_addr.s_addr);
+					uint32_t ip0 = Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in*>(this)->sin_addr.s_addr);
+					uint32_t ip1 = Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in*>(&b)->sin_addr.s_addr);
 					while ((ip0 >> 31) == (ip1 >> 31)) {
 						ip0 <<= 1;
 						ip1 <<= 1;
@@ -493,14 +552,15 @@ struct InetAddress : public sockaddr_storage
 							break;
 						}
 					}
-				}	break;
+				} break;
 				case AF_INET6: {
-					const uint8_t *ip0 = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
-					const uint8_t *ip1 = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(&b)->sin6_addr.s6_addr);
-					for(unsigned int i=0;i<16;++i) {
+					const uint8_t* ip0 = reinterpret_cast<const uint8_t*>(reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_addr.s6_addr);
+					const uint8_t* ip1 = reinterpret_cast<const uint8_t*>(reinterpret_cast<const struct sockaddr_in6*>(&b)->sin6_addr.s6_addr);
+					for (unsigned int i = 0; i < 16; ++i) {
 						if (ip0[i] == ip1[i]) {
 							c += 8;
-						} else {
+						}
+						else {
 							uint8_t ip0b = ip0[i];
 							uint8_t ip1b = ip1[i];
 							uint8_t bit = 0x80;
@@ -514,7 +574,7 @@ struct InetAddress : public sockaddr_storage
 							break;
 						}
 					}
-				}	break;
+				} break;
 			}
 		}
 		return c;
@@ -526,13 +586,13 @@ struct InetAddress : public sockaddr_storage
 	inline unsigned long rateGateHash() const
 	{
 		unsigned long h = 0;
-		switch(ss_family) {
+		switch (ss_family) {
 			case AF_INET:
-				h = (Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr) & 0xffffff00) >> 8;
+				h = (Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in*>(this)->sin_addr.s_addr) & 0xffffff00) >> 8;
 				h ^= (h >> 14);
 				break;
 			case AF_INET6: {
-				const uint8_t *ip = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
+				const uint8_t* ip = reinterpret_cast<const uint8_t*>(reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_addr.s6_addr);
 				h = ((unsigned long)ip[0]);
 				h <<= 1;
 				h += ((unsigned long)ip[1]);
@@ -544,7 +604,7 @@ struct InetAddress : public sockaddr_storage
 				h += ((unsigned long)ip[4]);
 				h <<= 1;
 				h += ((unsigned long)ip[5]);
-			}	break;
+			} break;
 		}
 		return (h & 0x3fff);
 	}
@@ -552,23 +612,25 @@ struct InetAddress : public sockaddr_storage
 	/**
 	 * @return True if address family is non-zero
 	 */
-	inline operator bool() const { return (ss_family != 0); }
+	inline operator bool() const
+	{
+		return (ss_family != 0);
+	}
 
-	template<unsigned int C>
-	inline void serialize(Buffer<C> &b) const
+	template <unsigned int C> inline void serialize(Buffer<C>& b) const
 	{
 		// This is used in the protocol and must be the same as describe in places
 		// like VERB_HELLO in Packet.hpp.
-		switch(ss_family) {
+		switch (ss_family) {
 			case AF_INET:
 				b.append((uint8_t)0x04);
-				b.append(&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr),4);
-				b.append((uint16_t)port()); // just in case sin_port != uint16_t
+				b.append(&(reinterpret_cast<const struct sockaddr_in*>(this)->sin_addr.s_addr), 4);
+				b.append((uint16_t)port());	  // just in case sin_port != uint16_t
 				return;
 			case AF_INET6:
 				b.append((uint8_t)0x06);
-				b.append(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr,16);
-				b.append((uint16_t)port()); // just in case sin_port != uint16_t
+				b.append(reinterpret_cast<const struct sockaddr_in6*>(this)->sin6_addr.s6_addr, 16);
+				b.append((uint16_t)port());	  // just in case sin_port != uint16_t
 				return;
 			default:
 				b.append((uint8_t)0);
@@ -576,12 +638,11 @@ struct InetAddress : public sockaddr_storage
 		}
 	}
 
-	template<unsigned int C>
-	inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
+	template <unsigned int C> inline unsigned int deserialize(const Buffer<C>& b, unsigned int startAt = 0)
 	{
-		memset(this,0,sizeof(InetAddress));
+		memset(this, 0, sizeof(InetAddress));
 		unsigned int p = startAt;
-		switch(b[p++]) {
+		switch (b[p++]) {
 			case 0:
 				return 1;
 			case 0x01:
@@ -593,19 +654,19 @@ struct InetAddress : public sockaddr_storage
 			case 0x03:
 				// TODO: Other address types (but accept for forward compatibility)
 				// These could be extended/optional things like AF_UNIX, LTE Direct, shared memory, etc.
-				return (unsigned int)(b.template at<uint16_t>(p) + 3); // other addresses begin with 16-bit non-inclusive length
+				return (unsigned int)(b.template at<uint16_t>(p) + 3);	 // other addresses begin with 16-bit non-inclusive length
 			case 0x04:
 				ss_family = AF_INET;
-				memcpy(&(reinterpret_cast<struct sockaddr_in *>(this)->sin_addr.s_addr),b.field(p,4),4);
+				memcpy(&(reinterpret_cast<struct sockaddr_in*>(this)->sin_addr.s_addr), b.field(p, 4), 4);
 				p += 4;
-				reinterpret_cast<struct sockaddr_in *>(this)->sin_port = Utils::hton(b.template at<uint16_t>(p));
+				reinterpret_cast<struct sockaddr_in*>(this)->sin_port = Utils::hton(b.template at<uint16_t>(p));
 				p += 2;
 				break;
 			case 0x06:
 				ss_family = AF_INET6;
-				memcpy(reinterpret_cast<struct sockaddr_in6 *>(this)->sin6_addr.s6_addr,b.field(p,16),16);
+				memcpy(reinterpret_cast<struct sockaddr_in6*>(this)->sin6_addr.s6_addr, b.field(p, 16), 16);
 				p += 16;
-				reinterpret_cast<struct sockaddr_in *>(this)->sin_port = Utils::hton(b.template at<uint16_t>(p));
+				reinterpret_cast<struct sockaddr_in*>(this)->sin_port = Utils::hton(b.template at<uint16_t>(p));
 				p += 2;
 				break;
 			default:
@@ -614,18 +675,30 @@ struct InetAddress : public sockaddr_storage
 		return (p - startAt);
 	}
 
-	bool operator==(const InetAddress &a) const;
-	bool operator<(const InetAddress &a) const;
-	inline bool operator!=(const InetAddress &a) const { return !(*this == a); }
-	inline bool operator>(const InetAddress &a) const { return (a < *this); }
-	inline bool operator<=(const InetAddress &a) const { return !(a < *this); }
-	inline bool operator>=(const InetAddress &a) const { return !(*this < a); }
+	bool operator==(const InetAddress& a) const;
+	bool operator<(const InetAddress& a) const;
+	inline bool operator!=(const InetAddress& a) const
+	{
+		return ! (*this == a);
+	}
+	inline bool operator>(const InetAddress& a) const
+	{
+		return (a < *this);
+	}
+	inline bool operator<=(const InetAddress& a) const
+	{
+		return ! (a < *this);
+	}
+	inline bool operator>=(const InetAddress& a) const
+	{
+		return ! (*this < a);
+	}
 
 	/**
 	 * @param mac MAC address seed
 	 * @return IPv6 link-local address
 	 */
-	static InetAddress makeIpv6LinkLocal(const MAC &mac);
+	static InetAddress makeIpv6LinkLocal(const MAC& mac);
 
 	/**
 	 * Compute private IPv6 unicast address from network ID and ZeroTier address
@@ -668,14 +741,14 @@ struct InetAddress : public sockaddr_storage
 	 * @param zeroTierAddress 40-bit device address (in least significant 40 bits, highest 24 bits ignored)
 	 * @return IPv6 private unicast address with /88 netmask
 	 */
-	static InetAddress makeIpv6rfc4193(uint64_t nwid,uint64_t zeroTierAddress);
+	static InetAddress makeIpv6rfc4193(uint64_t nwid, uint64_t zeroTierAddress);
 
 	/**
 	 * Compute a private IPv6 "6plane" unicast address from network ID and ZeroTier address
 	 */
-	static InetAddress makeIpv66plane(uint64_t nwid,uint64_t zeroTierAddress);
+	static InetAddress makeIpv66plane(uint64_t nwid, uint64_t zeroTierAddress);
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 108 - 56
node/MAC.hpp

@@ -14,64 +14,81 @@
 #ifndef ZT_MAC_HPP
 #define ZT_MAC_HPP
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-
-#include "Constants.hpp"
-#include "Utils.hpp"
 #include "Address.hpp"
 #include "Buffer.hpp"
+#include "Constants.hpp"
+#include "Utils.hpp"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
 
 namespace ZeroTier {
 
 /**
  * 48-byte Ethernet MAC address
  */
-class MAC
-{
-public:
-	MAC() : _m(0ULL) {}
-	MAC(const MAC &m) : _m(m._m) {}
-
-	MAC(const unsigned char a,const unsigned char b,const unsigned char c,const unsigned char d,const unsigned char e,const unsigned char f) :
-		_m( ((((uint64_t)a) & 0xffULL) << 40) |
-		    ((((uint64_t)b) & 0xffULL) << 32) |
-		    ((((uint64_t)c) & 0xffULL) << 24) |
-		    ((((uint64_t)d) & 0xffULL) << 16) |
-		    ((((uint64_t)e) & 0xffULL) << 8) |
-		    (((uint64_t)f) & 0xffULL) ) {}
-	MAC(const void *bits,unsigned int len) { setTo(bits,len); }
-	MAC(const Address &ztaddr,uint64_t nwid) { fromAddress(ztaddr,nwid); }
-	MAC(const uint64_t m) : _m(m & 0xffffffffffffULL) {}
+class MAC {
+  public:
+	MAC() : _m(0ULL)
+	{
+	}
+	MAC(const MAC& m) : _m(m._m)
+	{
+	}
+
+	MAC(const unsigned char a, const unsigned char b, const unsigned char c, const unsigned char d, const unsigned char e, const unsigned char f)
+		: _m(((((uint64_t)a) & 0xffULL) << 40) | ((((uint64_t)b) & 0xffULL) << 32) | ((((uint64_t)c) & 0xffULL) << 24) | ((((uint64_t)d) & 0xffULL) << 16) | ((((uint64_t)e) & 0xffULL) << 8) | (((uint64_t)f) & 0xffULL))
+	{
+	}
+	MAC(const void* bits, unsigned int len)
+	{
+		setTo(bits, len);
+	}
+	MAC(const Address& ztaddr, uint64_t nwid)
+	{
+		fromAddress(ztaddr, nwid);
+	}
+	MAC(const uint64_t m) : _m(m & 0xffffffffffffULL)
+	{
+	}
 
 	/**
 	 * @return MAC in 64-bit integer
 	 */
-	inline uint64_t toInt() const { return _m; }
+	inline uint64_t toInt() const
+	{
+		return _m;
+	}
 
 	/**
 	 * Set MAC to zero
 	 */
-	inline void zero() { _m = 0ULL; }
+	inline void zero()
+	{
+		_m = 0ULL;
+	}
 
 	/**
 	 * @return True if MAC is non-zero
 	 */
-	inline operator bool() const { return (_m != 0ULL); }
+	inline operator bool() const
+	{
+		return (_m != 0ULL);
+	}
 
 	/**
 	 * @param bits Raw MAC in big-endian byte order
 	 * @param len Length, must be >= 6 or result is zero
 	 */
-	inline void setTo(const void *bits,unsigned int len)
+	inline void setTo(const void* bits, unsigned int len)
 	{
 		if (len < 6) {
 			_m = 0ULL;
 			return;
 		}
-		const unsigned char *b = (const unsigned char *)bits;
-		_m =  ((((uint64_t)*b) & 0xff) << 40);
+		const unsigned char* b = (const unsigned char*)bits;
+		_m = ((((uint64_t)*b) & 0xff) << 40);
 		++b;
 		_m |= ((((uint64_t)*b) & 0xff) << 32);
 		++b;
@@ -88,12 +105,12 @@ public:
 	 * @param buf Destination buffer for MAC in big-endian byte order
 	 * @param len Length of buffer, must be >= 6 or nothing is copied
 	 */
-	inline void copyTo(void *buf,unsigned int len) const
+	inline void copyTo(void* buf, unsigned int len) const
 	{
 		if (len < 6) {
 			return;
 		}
-		unsigned char *b = (unsigned char *)buf;
+		unsigned char* b = (unsigned char*)buf;
 		*(b++) = (unsigned char)((_m >> 40) & 0xff);
 		*(b++) = (unsigned char)((_m >> 32) & 0xff);
 		*(b++) = (unsigned char)((_m >> 24) & 0xff);
@@ -107,10 +124,9 @@ public:
 	 *
 	 * @param b Buffer to append to
 	 */
-	template<unsigned int C>
-	inline void appendTo(Buffer<C> &b) const
+	template <unsigned int C> inline void appendTo(Buffer<C>& b) const
 	{
-		unsigned char *p = (unsigned char *)b.appendField(6);
+		unsigned char* p = (unsigned char*)b.appendField(6);
 		*(p++) = (unsigned char)((_m >> 40) & 0xff);
 		*(p++) = (unsigned char)((_m >> 32) & 0xff);
 		*(p++) = (unsigned char)((_m >> 24) & 0xff);
@@ -122,17 +138,26 @@ public:
 	/**
 	 * @return True if this is broadcast (all 0xff)
 	 */
-	inline bool isBroadcast() const { return (_m == 0xffffffffffffULL); }
+	inline bool isBroadcast() const
+	{
+		return (_m == 0xffffffffffffULL);
+	}
 
 	/**
 	 * @return True if this is a multicast MAC
 	 */
-	inline bool isMulticast() const { return ((_m & 0x010000000000ULL) != 0ULL); }
+	inline bool isMulticast() const
+	{
+		return ((_m & 0x010000000000ULL) != 0ULL);
+	}
 
 	/**
 	 * @param True if this is a locally-administered MAC
 	 */
-	inline bool isLocallyAdministered() const { return ((_m & 0x020000000000ULL) != 0ULL); }
+	inline bool isLocallyAdministered() const
+	{
+		return ((_m & 0x020000000000ULL) != 0ULL);
+	}
 
 	/**
 	 * Set this MAC to a MAC derived from an address and a network ID
@@ -140,10 +165,10 @@ public:
 	 * @param ztaddr ZeroTier address
 	 * @param nwid 64-bit network ID
 	 */
-	inline void fromAddress(const Address &ztaddr,uint64_t nwid)
+	inline void fromAddress(const Address& ztaddr, uint64_t nwid)
 	{
 		uint64_t m = ((uint64_t)firstOctetForNetwork(nwid)) << 40;
-		m |= ztaddr.toInt(); // a is 40 bits
+		m |= ztaddr.toInt();   // a is 40 bits
 		m ^= ((nwid >> 8) & 0xff) << 32;
 		m ^= ((nwid >> 16) & 0xff) << 24;
 		m ^= ((nwid >> 24) & 0xff) << 16;
@@ -161,8 +186,8 @@ public:
 	 */
 	inline Address toAddress(uint64_t nwid) const
 	{
-		uint64_t a = _m & 0xffffffffffULL; // least significant 40 bits of MAC are formed from address
-		a ^= ((nwid >> 8) & 0xff) << 32; // ... XORed with bits 8-48 of the nwid in little-endian byte order, so unmask it
+		uint64_t a = _m & 0xffffffffffULL;	 // least significant 40 bits of MAC are formed from address
+		a ^= ((nwid >> 8) & 0xff) << 32;	 // ... XORed with bits 8-48 of the nwid in little-endian byte order, so unmask it
 		a ^= ((nwid >> 16) & 0xff) << 24;
 		a ^= ((nwid >> 24) & 0xff) << 16;
 		a ^= ((nwid >> 32) & 0xff) << 8;
@@ -176,24 +201,33 @@ public:
 	 */
 	static inline unsigned char firstOctetForNetwork(uint64_t nwid)
 	{
-		unsigned char a = ((unsigned char)(nwid & 0xfe) | 0x02); // locally administered, not multicast, from LSB of network ID
-		return ((a == 0x52) ? 0x32 : a); // blacklist 0x52 since it's used by KVM, libvirt, and other popular virtualization engines... seems de-facto standard on Linux
+		unsigned char a = ((unsigned char)(nwid & 0xfe) | 0x02);   // locally administered, not multicast, from LSB of network ID
+		return ((a == 0x52) ? 0x32 : a);						   // blacklist 0x52 since it's used by KVM, libvirt, and other popular virtualization engines... seems de-facto standard on Linux
 	}
 
 	/**
 	 * @param i Value from 0 to 5 (inclusive)
 	 * @return Byte at said position (address interpreted in big-endian order)
 	 */
-	inline unsigned char operator[](unsigned int i) const { return (unsigned char)((_m >> (40 - (i * 8))) & 0xff); }
+	inline unsigned char operator[](unsigned int i) const
+	{
+		return (unsigned char)((_m >> (40 - (i * 8))) & 0xff);
+	}
 
 	/**
 	 * @return 6, which is the number of bytes in a MAC, for container compliance
 	 */
-	inline unsigned int size() const { return 6; }
+	inline unsigned int size() const
+	{
+		return 6;
+	}
 
-	inline unsigned long hashCode() const { return (unsigned long)_m; }
+	inline unsigned long hashCode() const
+	{
+		return (unsigned long)_m;
+	}
 
-	inline char *toString(char buf[18]) const
+	inline char* toString(char buf[18]) const
 	{
 		buf[0] = Utils::HEXCHARS[(_m >> 44) & 0xf];
 		buf[1] = Utils::HEXCHARS[(_m >> 40) & 0xf];
@@ -216,28 +250,46 @@ public:
 		return buf;
 	}
 
-	inline MAC &operator=(const MAC &m)
+	inline MAC& operator=(const MAC& m)
 	{
 		_m = m._m;
 		return *this;
 	}
-	inline MAC &operator=(const uint64_t m)
+	inline MAC& operator=(const uint64_t m)
 	{
 		_m = m;
 		return *this;
 	}
 
-	inline bool operator==(const MAC &m) const { return (_m == m._m); }
-	inline bool operator!=(const MAC &m) const { return (_m != m._m); }
-	inline bool operator<(const MAC &m) const { return (_m < m._m); }
-	inline bool operator<=(const MAC &m) const { return (_m <= m._m); }
-	inline bool operator>(const MAC &m) const { return (_m > m._m); }
-	inline bool operator>=(const MAC &m) const { return (_m >= m._m); }
+	inline bool operator==(const MAC& m) const
+	{
+		return (_m == m._m);
+	}
+	inline bool operator!=(const MAC& m) const
+	{
+		return (_m != m._m);
+	}
+	inline bool operator<(const MAC& m) const
+	{
+		return (_m < m._m);
+	}
+	inline bool operator<=(const MAC& m) const
+	{
+		return (_m <= m._m);
+	}
+	inline bool operator>(const MAC& m) const
+	{
+		return (_m > m._m);
+	}
+	inline bool operator>=(const MAC& m) const
+	{
+		return (_m >= m._m);
+	}
 
-private:
+  private:
 	uint64_t _m;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 64 - 61
node/Membership.cpp

@@ -11,47 +11,41 @@
  */
 /****/
 
-#include <algorithm>
-
 #include "Membership.hpp"
-#include "RuntimeEnvironment.hpp"
+
+#include "Node.hpp"
+#include "Packet.hpp"
 #include "Peer.hpp"
-#include "Topology.hpp"
+#include "RuntimeEnvironment.hpp"
 #include "Switch.hpp"
-#include "Packet.hpp"
-#include "Node.hpp"
+#include "Topology.hpp"
 #include "Trace.hpp"
 
+#include <algorithm>
+
 namespace ZeroTier {
 
-Membership::Membership() :
-	_lastUpdatedMulticast(0),
-	_comRevocationThreshold(0),
-	_lastPushedCredentials(0),
-	_revocations(4),
-	_remoteTags(4),
-	_remoteCaps(4),
-	_remoteCoos(4)
+Membership::Membership() : _lastUpdatedMulticast(0), _comRevocationThreshold(0), _lastPushedCredentials(0), _revocations(4), _remoteTags(4), _remoteCaps(4), _remoteCoos(4)
 {
 }
 
-void Membership::pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const int64_t now,const Address &peerAddress,const NetworkConfig &nconf)
+void Membership::pushCredentials(const RuntimeEnvironment* RR, void* tPtr, const int64_t now, const Address& peerAddress, const NetworkConfig& nconf)
 {
-	const Capability *sendCaps[ZT_MAX_NETWORK_CAPABILITIES];
+	const Capability* sendCaps[ZT_MAX_NETWORK_CAPABILITIES];
 	unsigned int sendCapCount = 0;
-	for(unsigned int c=0;c<nconf.capabilityCount;++c) {
+	for (unsigned int c = 0; c < nconf.capabilityCount; ++c) {
 		sendCaps[sendCapCount++] = &(nconf.capabilities[c]);
 	}
 
-	const Tag *sendTags[ZT_MAX_NETWORK_TAGS];
+	const Tag* sendTags[ZT_MAX_NETWORK_TAGS];
 	unsigned int sendTagCount = 0;
-	for(unsigned int t=0;t<nconf.tagCount;++t) {
+	for (unsigned int t = 0; t < nconf.tagCount; ++t) {
 		sendTags[sendTagCount++] = &(nconf.tags[t]);
 	}
 
-	const CertificateOfOwnership *sendCoos[ZT_MAX_CERTIFICATES_OF_OWNERSHIP];
+	const CertificateOfOwnership* sendCoos[ZT_MAX_CERTIFICATES_OF_OWNERSHIP];
 	unsigned int sendCooCount = 0;
-	for(unsigned int c=0;c<nconf.certificateOfOwnershipCount;++c) {
+	for (unsigned int c = 0; c < nconf.certificateOfOwnershipCount; ++c) {
 		sendCoos[sendCooCount++] = &(nconf.certificatesOfOwnership[c]);
 	}
 
@@ -59,8 +53,8 @@ void Membership::pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const i
 	unsigned int tagPtr = 0;
 	unsigned int cooPtr = 0;
 	bool sendCom = (bool)(nconf.com);
-	while ((capPtr < sendCapCount)||(tagPtr < sendTagCount)||(cooPtr < sendCooCount)||(sendCom)) {
-		Packet outp(peerAddress,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS);
+	while ((capPtr < sendCapCount) || (tagPtr < sendTagCount) || (cooPtr < sendCooCount) || (sendCom)) {
+		Packet outp(peerAddress, RR->identity.address(), Packet::VERB_NETWORK_CREDENTIALS);
 
 		if (sendCom) {
 			sendCom = false;
@@ -71,20 +65,20 @@ void Membership::pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const i
 		const unsigned int capCountAt = outp.size();
 		outp.addSize(2);
 		unsigned int thisPacketCapCount = 0;
-		while ((capPtr < sendCapCount)&&((outp.size() + sizeof(Capability) + 16) < ZT_PROTO_MAX_PACKET_LENGTH)) {
+		while ((capPtr < sendCapCount) && ((outp.size() + sizeof(Capability) + 16) < ZT_PROTO_MAX_PACKET_LENGTH)) {
 			sendCaps[capPtr++]->serialize(outp);
 			++thisPacketCapCount;
 		}
-		outp.setAt(capCountAt,(uint16_t)thisPacketCapCount);
+		outp.setAt(capCountAt, (uint16_t)thisPacketCapCount);
 
 		const unsigned int tagCountAt = outp.size();
 		outp.addSize(2);
 		unsigned int thisPacketTagCount = 0;
-		while ((tagPtr < sendTagCount)&&((outp.size() + sizeof(Tag) + 16) < ZT_PROTO_MAX_PACKET_LENGTH)) {
+		while ((tagPtr < sendTagCount) && ((outp.size() + sizeof(Tag) + 16) < ZT_PROTO_MAX_PACKET_LENGTH)) {
 			sendTags[tagPtr++]->serialize(outp);
 			++thisPacketTagCount;
 		}
-		outp.setAt(tagCountAt,(uint16_t)thisPacketTagCount);
+		outp.setAt(tagCountAt, (uint16_t)thisPacketTagCount);
 
 		// No revocations, these propagate differently
 		outp.append((uint16_t)0);
@@ -92,43 +86,43 @@ void Membership::pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const i
 		const unsigned int cooCountAt = outp.size();
 		outp.addSize(2);
 		unsigned int thisPacketCooCount = 0;
-		while ((cooPtr < sendCooCount)&&((outp.size() + sizeof(CertificateOfOwnership) + 16) < ZT_PROTO_MAX_PACKET_LENGTH)) {
+		while ((cooPtr < sendCooCount) && ((outp.size() + sizeof(CertificateOfOwnership) + 16) < ZT_PROTO_MAX_PACKET_LENGTH)) {
 			sendCoos[cooPtr++]->serialize(outp);
 			++thisPacketCooCount;
 		}
-		outp.setAt(cooCountAt,(uint16_t)thisPacketCooCount);
+		outp.setAt(cooCountAt, (uint16_t)thisPacketCooCount);
 
 		outp.compress();
-		RR->sw->send(tPtr,outp,true);
+		RR->sw->send(tPtr, outp, true);
 		Metrics::pkt_network_credentials_out++;
 	}
 
 	_lastPushedCredentials = now;
 }
 
-Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const CertificateOfMembership &com)
+Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment* RR, void* tPtr, const NetworkConfig& nconf, const CertificateOfMembership& com)
 {
 	const int64_t newts = com.timestamp();
 	if (newts <= _comRevocationThreshold) {
-		RR->t->credentialRejected(tPtr,com,"revoked");
+		RR->t->credentialRejected(tPtr, com, "revoked");
 		return ADD_REJECTED;
 	}
 
 	const int64_t oldts = _com.timestamp();
 	if (newts < oldts) {
-		RR->t->credentialRejected(tPtr,com,"old");
+		RR->t->credentialRejected(tPtr, com, "old");
 		return ADD_REJECTED;
 	}
 	if (_com == com) {
 		return ADD_ACCEPTED_REDUNDANT;
 	}
 
-	switch(com.verify(RR,tPtr)) {
+	switch (com.verify(RR, tPtr)) {
 		default:
-			RR->t->credentialRejected(tPtr,com,"invalid");
+			RR->t->credentialRejected(tPtr, com, "invalid");
 			return ADD_REJECTED;
 		case 0:
-			//printf("%.16llx %.10llx replacing COM %lld with %lld\n", com.networkId(), com.issuedTo().toInt(), _com.timestamp(), com.timestamp()); fflush(stdout);
+			// printf("%.16llx %.10llx replacing COM %lld with %lld\n", com.networkId(), com.issuedTo().toInt(), _com.timestamp(), com.timestamp()); fflush(stdout);
 			_com = com;
 			return ADD_ACCEPTED_NEW;
 		case 1:
@@ -137,13 +131,13 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
 }
 
 // Template out addCredential() for many cred types to avoid copypasta
-template<typename C>
-static Membership::AddCredentialResult _addCredImpl(Hashtable<uint32_t,C> &remoteCreds,const Hashtable<uint64_t,int64_t> &revocations,const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const C &cred)
+template <typename C>
+static Membership::AddCredentialResult _addCredImpl(Hashtable<uint32_t, C>& remoteCreds, const Hashtable<uint64_t, int64_t>& revocations, const RuntimeEnvironment* RR, void* tPtr, const NetworkConfig& nconf, const C& cred)
 {
-	C *rc = remoteCreds.get(cred.id());
+	C* rc = remoteCreds.get(cred.id());
 	if (rc) {
 		if (rc->timestamp() > cred.timestamp()) {
-			RR->t->credentialRejected(tPtr,cred,"old");
+			RR->t->credentialRejected(tPtr, cred, "old");
 			return Membership::ADD_REJECTED;
 		}
 		if (*rc == cred) {
@@ -151,18 +145,18 @@ static Membership::AddCredentialResult _addCredImpl(Hashtable<uint32_t,C> &remot
 		}
 	}
 
-	const int64_t *const rt = revocations.get(Membership::credentialKey(C::credentialType(),cred.id()));
-	if ((rt)&&(*rt >= cred.timestamp())) {
-		RR->t->credentialRejected(tPtr,cred,"revoked");
+	const int64_t* const rt = revocations.get(Membership::credentialKey(C::credentialType(), cred.id()));
+	if ((rt) && (*rt >= cred.timestamp())) {
+		RR->t->credentialRejected(tPtr, cred, "revoked");
 		return Membership::ADD_REJECTED;
 	}
 
-	switch(cred.verify(RR,tPtr)) {
+	switch (cred.verify(RR, tPtr)) {
 		default:
-			RR->t->credentialRejected(tPtr,cred,"invalid");
+			RR->t->credentialRejected(tPtr, cred, "invalid");
 			return Membership::ADD_REJECTED;
 		case 0:
-			if (!rc) {
+			if (! rc) {
 				rc = &(remoteCreds[cred.id()]);
 			}
 			*rc = cred;
@@ -172,20 +166,29 @@ static Membership::AddCredentialResult _addCredImpl(Hashtable<uint32_t,C> &remot
 	}
 }
 
-Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const Tag &tag) { return _addCredImpl<Tag>(_remoteTags,_revocations,RR,tPtr,nconf,tag); }
-Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const Capability &cap) { return _addCredImpl<Capability>(_remoteCaps,_revocations,RR,tPtr,nconf,cap); }
-Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const CertificateOfOwnership &coo) { return _addCredImpl<CertificateOfOwnership>(_remoteCoos,_revocations,RR,tPtr,nconf,coo); }
+Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment* RR, void* tPtr, const NetworkConfig& nconf, const Tag& tag)
+{
+	return _addCredImpl<Tag>(_remoteTags, _revocations, RR, tPtr, nconf, tag);
+}
+Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment* RR, void* tPtr, const NetworkConfig& nconf, const Capability& cap)
+{
+	return _addCredImpl<Capability>(_remoteCaps, _revocations, RR, tPtr, nconf, cap);
+}
+Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment* RR, void* tPtr, const NetworkConfig& nconf, const CertificateOfOwnership& coo)
+{
+	return _addCredImpl<CertificateOfOwnership>(_remoteCoos, _revocations, RR, tPtr, nconf, coo);
+}
 
-Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const Revocation &rev)
+Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment* RR, void* tPtr, const NetworkConfig& nconf, const Revocation& rev)
 {
-	int64_t *rt;
-	switch(rev.verify(RR,tPtr)) {
+	int64_t* rt;
+	switch (rev.verify(RR, tPtr)) {
 		default:
-			RR->t->credentialRejected(tPtr,rev,"invalid");
+			RR->t->credentialRejected(tPtr, rev, "invalid");
 			return ADD_REJECTED;
 		case 0: {
 			const Credential::Type ct = rev.type();
-			switch(ct) {
+			switch (ct) {
 				case Credential::CREDENTIAL_TYPE_COM:
 					if (rev.threshold() > _comRevocationThreshold) {
 						_comRevocationThreshold = rev.threshold();
@@ -195,7 +198,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
 				case Credential::CREDENTIAL_TYPE_CAPABILITY:
 				case Credential::CREDENTIAL_TYPE_TAG:
 				case Credential::CREDENTIAL_TYPE_COO:
-					rt = &(_revocations[credentialKey(ct,rev.credentialId())]);
+					rt = &(_revocations[credentialKey(ct, rev.credentialId())]);
 					if (*rt < rev.threshold()) {
 						*rt = rev.threshold();
 						_comRevocationThreshold = rev.threshold();
@@ -203,7 +206,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
 					}
 					return ADD_ACCEPTED_REDUNDANT;
 				default:
-					RR->t->credentialRejected(tPtr,rev,"invalid");
+					RR->t->credentialRejected(tPtr, rev, "invalid");
 					return ADD_REJECTED;
 			}
 		}
@@ -212,11 +215,11 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
 	}
 }
 
-void Membership::clean(const int64_t now,const NetworkConfig &nconf)
+void Membership::clean(const int64_t now, const NetworkConfig& nconf)
 {
-	_cleanCredImpl<Tag>(nconf,_remoteTags);
-	_cleanCredImpl<Capability>(nconf,_remoteCaps);
-	_cleanCredImpl<CertificateOfOwnership>(nconf,_remoteCoos);
+	_cleanCredImpl<Tag>(nconf, _remoteTags);
+	_cleanCredImpl<Capability>(nconf, _remoteCaps);
+	_cleanCredImpl<CertificateOfOwnership>(nconf, _remoteCoos);
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier

+ 89 - 90
node/Membership.hpp

@@ -14,17 +14,17 @@
 #ifndef ZT_MEMBERSHIP_HPP
 #define ZT_MEMBERSHIP_HPP
 
-#include <stdint.h>
-
-#include "Constants.hpp"
 #include "../include/ZeroTierOne.h"
+#include "Capability.hpp"
+#include "CertificateOfMembership.hpp"
+#include "Constants.hpp"
 #include "Credential.hpp"
 #include "Hashtable.hpp"
-#include "CertificateOfMembership.hpp"
-#include "Capability.hpp"
-#include "Tag.hpp"
-#include "Revocation.hpp"
 #include "NetworkConfig.hpp"
+#include "Revocation.hpp"
+#include "Tag.hpp"
+
+#include <stdint.h>
 
 #define ZT_MEMBERSHIP_CRED_ID_UNUSED 0xffffffffffffffffULL
 
@@ -40,16 +40,9 @@ class Network;
  *
  * This class is not thread safe. It must be locked externally.
  */
-class Membership
-{
-public:
-	enum AddCredentialResult
-	{
-		ADD_REJECTED,
-		ADD_ACCEPTED_NEW,
-		ADD_ACCEPTED_REDUNDANT,
-		ADD_DEFERRED_FOR_WHOIS
-	};
+class Membership {
+  public:
+	enum AddCredentialResult { ADD_REJECTED, ADD_ACCEPTED_NEW, ADD_ACCEPTED_REDUNDANT, ADD_DEFERRED_FOR_WHOIS };
 
 	Membership();
 
@@ -62,11 +55,20 @@ public:
 	 * @param peerAddress Address of member peer (the one that this Membership describes)
 	 * @param nconf My network config
 	 */
-	void pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const int64_t now,const Address &peerAddress,const NetworkConfig &nconf);
+	void pushCredentials(const RuntimeEnvironment* RR, void* tPtr, const int64_t now, const Address& peerAddress, const NetworkConfig& nconf);
 
-	inline int64_t lastPushedCredentials() { return _lastPushedCredentials; }
-	inline int64_t comTimestamp() { return _com.timestamp(); }
-	inline int64_t comRevocationThreshold() { return _comRevocationThreshold; }
+	inline int64_t lastPushedCredentials()
+	{
+		return _lastPushedCredentials;
+	}
+	inline int64_t comTimestamp()
+	{
+		return _com.timestamp();
+	}
+	inline int64_t comRevocationThreshold()
+	{
+		return _comRevocationThreshold;
+	}
 
 	/**
 	 * Check whether we should push MULTICAST_LIKEs to this peer, and update last sent time if true
@@ -90,14 +92,14 @@ public:
 	 * @param otherNodeIdentity Identity of remote node
 	 * @return True if this peer is allowed on this network at all
 	 */
-	inline bool isAllowedOnNetwork(const NetworkConfig &thisNodeNetworkConfig, const Identity &otherNodeIdentity) const
+	inline bool isAllowedOnNetwork(const NetworkConfig& thisNodeNetworkConfig, const Identity& otherNodeIdentity) const
 	{
 		return thisNodeNetworkConfig.isPublic() || (((_com.timestamp() > _comRevocationThreshold) && (thisNodeNetworkConfig.com.agreesWith(_com, otherNodeIdentity))));
 	}
 
 	inline bool recentlyAssociated(const int64_t now) const
 	{
-		return ((_com)&&((now - _com.timestamp()) < ZT_PEER_ACTIVITY_TIMEOUT));
+		return ((_com) && ((now - _com.timestamp()) < ZT_PEER_ACTIVITY_TIMEOUT));
 	}
 
 	/**
@@ -108,18 +110,17 @@ public:
 	 * @param r Resource to check
 	 * @return True if this peer has a certificate of ownership for the given resource
 	 */
-	template<typename T>
-	inline bool hasCertificateOfOwnershipFor(const NetworkConfig &nconf,const T &r) const
+	template <typename T> inline bool hasCertificateOfOwnershipFor(const NetworkConfig& nconf, const T& r) const
 	{
-		uint32_t *k = (uint32_t *)0;
-		CertificateOfOwnership *v = (CertificateOfOwnership *)0;
-		Hashtable< uint32_t,CertificateOfOwnership >::Iterator i(*(const_cast< Hashtable< uint32_t,CertificateOfOwnership> *>(&_remoteCoos)));
-		while (i.next(k,v)) {
-			if (_isCredentialTimestampValid(nconf,*v)&&(v->owns(r))) {
+		uint32_t* k = (uint32_t*)0;
+		CertificateOfOwnership* v = (CertificateOfOwnership*)0;
+		Hashtable<uint32_t, CertificateOfOwnership>::Iterator i(*(const_cast<Hashtable<uint32_t, CertificateOfOwnership>*>(&_remoteCoos)));
+		while (i.next(k, v)) {
+			if (_isCredentialTimestampValid(nconf, *v) && (v->owns(r))) {
 				return true;
 			}
 		}
-		return _isV6NDPEmulated(nconf,r);
+		return _isV6NDPEmulated(nconf, r);
 	}
 
 	/**
@@ -129,36 +130,36 @@ public:
 	 * @param id Tag ID
 	 * @return Pointer to tag or NULL if not found
 	 */
-	inline const Tag *getTag(const NetworkConfig &nconf,const uint32_t id) const
+	inline const Tag* getTag(const NetworkConfig& nconf, const uint32_t id) const
 	{
-		const Tag *const t = _remoteTags.get(id);
-		return (((t)&&(_isCredentialTimestampValid(nconf,*t))) ? t : (Tag *)0);
+		const Tag* const t = _remoteTags.get(id);
+		return (((t) && (_isCredentialTimestampValid(nconf, *t))) ? t : (Tag*)0);
 	}
 
 	/**
 	 * Validate and add a credential if signature is okay and it's otherwise good
 	 */
-	AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const CertificateOfMembership &com);
+	AddCredentialResult addCredential(const RuntimeEnvironment* RR, void* tPtr, const NetworkConfig& nconf, const CertificateOfMembership& com);
 
 	/**
 	 * Validate and add a credential if signature is okay and it's otherwise good
 	 */
-	AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const Tag &tag);
+	AddCredentialResult addCredential(const RuntimeEnvironment* RR, void* tPtr, const NetworkConfig& nconf, const Tag& tag);
 
 	/**
 	 * Validate and add a credential if signature is okay and it's otherwise good
 	 */
-	AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const Capability &cap);
+	AddCredentialResult addCredential(const RuntimeEnvironment* RR, void* tPtr, const NetworkConfig& nconf, const Capability& cap);
 
 	/**
 	 * Validate and add a credential if signature is okay and it's otherwise good
 	 */
-	AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const CertificateOfOwnership &coo);
+	AddCredentialResult addCredential(const RuntimeEnvironment* RR, void* tPtr, const NetworkConfig& nconf, const CertificateOfOwnership& coo);
 
 	/**
 	 * Validate and add a credential if signature is okay and it's otherwise good
 	 */
-	AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const Revocation &rev);
+	AddCredentialResult addCredential(const RuntimeEnvironment* RR, void* tPtr, const NetworkConfig& nconf, const Revocation& rev);
 
 	/**
 	 * Clean internal databases of stale entries
@@ -166,24 +167,30 @@ public:
 	 * @param now Current time
 	 * @param nconf Current network configuration
 	 */
-	void clean(const int64_t now,const NetworkConfig &nconf);
+	void clean(const int64_t now, const NetworkConfig& nconf);
 
 	/**
 	 * Generates a key for the internal use in indexing credentials by type and credential ID
 	 */
-	static uint64_t credentialKey(const Credential::Type &t,const uint32_t i) { return (((uint64_t)t << 32) | (uint64_t)i); }
+	static uint64_t credentialKey(const Credential::Type& t, const uint32_t i)
+	{
+		return (((uint64_t)t << 32) | (uint64_t)i);
+	}
 
-private:
-	inline bool _isV6NDPEmulated(const NetworkConfig &nconf,const MAC &m) const { return false; }
-	inline bool _isV6NDPEmulated(const NetworkConfig &nconf,const InetAddress &ip) const
+  private:
+	inline bool _isV6NDPEmulated(const NetworkConfig& nconf, const MAC& m) const
 	{
-		if ((ip.isV6())&&(nconf.ndpEmulation())) {
-			const InetAddress sixpl(InetAddress::makeIpv66plane(nconf.networkId,nconf.issuedTo.toInt()));
-			for(unsigned int i=0;i<nconf.staticIpCount;++i) {
+		return false;
+	}
+	inline bool _isV6NDPEmulated(const NetworkConfig& nconf, const InetAddress& ip) const
+	{
+		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]) {
+					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;
 						}
@@ -195,12 +202,12 @@ private:
 				}
 			}
 
-			const InetAddress rfc4193(InetAddress::makeIpv6rfc4193(nconf.networkId,nconf.issuedTo.toInt()));
-			for(unsigned int i=0;i<nconf.staticIpCount;++i) {
+			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]) {
+					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;
 						}
@@ -215,25 +222,23 @@ private:
 		return false;
 	}
 
-	template<typename C>
-	inline bool _isCredentialTimestampValid(const NetworkConfig &nconf,const C &remoteCredential) const
+	template <typename C> inline bool _isCredentialTimestampValid(const NetworkConfig& nconf, const C& remoteCredential) const
 	{
 		const int64_t ts = remoteCredential.timestamp();
 		if (((ts >= nconf.timestamp) ? (ts - nconf.timestamp) : (nconf.timestamp - ts)) <= nconf.credentialTimeMaxDelta) {
-			const int64_t *threshold = _revocations.get(credentialKey(C::credentialType(),remoteCredential.id()));
-			return ((!threshold)||(ts > *threshold));
+			const int64_t* threshold = _revocations.get(credentialKey(C::credentialType(), remoteCredential.id()));
+			return ((! threshold) || (ts > *threshold));
 		}
 		return false;
 	}
 
-	template<typename C>
-	inline void _cleanCredImpl(const NetworkConfig &nconf,Hashtable<uint32_t,C> &remoteCreds)
+	template <typename C> inline void _cleanCredImpl(const NetworkConfig& nconf, Hashtable<uint32_t, C>& remoteCreds)
 	{
-		uint32_t *k = (uint32_t *)0;
-		C *v = (C *)0;
-		typename Hashtable<uint32_t,C>::Iterator i(remoteCreds);
-		while (i.next(k,v)) {
-			if (!_isCredentialTimestampValid(nconf,*v)) {
+		uint32_t* k = (uint32_t*)0;
+		C* v = (C*)0;
+		typename Hashtable<uint32_t, C>::Iterator i(remoteCreds);
+		while (i.next(k, v)) {
+			if (! _isCredentialTimestampValid(nconf, *v)) {
 				remoteCreds.erase(*k);
 			}
 		}
@@ -252,45 +257,39 @@ private:
 	CertificateOfMembership _com;
 
 	// Revocations by credentialKey()
-	Hashtable< uint64_t,int64_t > _revocations;
+	Hashtable<uint64_t, int64_t> _revocations;
 
 	// Remote credentials that we have received from this member (and that are valid)
-	Hashtable< uint32_t,Tag > _remoteTags;
-	Hashtable< uint32_t,Capability > _remoteCaps;
-	Hashtable< uint32_t,CertificateOfOwnership > _remoteCoos;
-
-public:
-	class CapabilityIterator
-	{
-	public:
-		CapabilityIterator(Membership &m,const NetworkConfig &nconf) :
-			_hti(m._remoteCaps),
-			_k((uint32_t *)0),
-			_c((Capability *)0),
-			_m(m),
-			_nconf(nconf)
+	Hashtable<uint32_t, Tag> _remoteTags;
+	Hashtable<uint32_t, Capability> _remoteCaps;
+	Hashtable<uint32_t, CertificateOfOwnership> _remoteCoos;
+
+  public:
+	class CapabilityIterator {
+	  public:
+		CapabilityIterator(Membership& m, const NetworkConfig& nconf) : _hti(m._remoteCaps), _k((uint32_t*)0), _c((Capability*)0), _m(m), _nconf(nconf)
 		{
 		}
 
-		inline Capability *next()
+		inline Capability* next()
 		{
-			while (_hti.next(_k,_c)) {
-				if (_m._isCredentialTimestampValid(_nconf,*_c)) {
+			while (_hti.next(_k, _c)) {
+				if (_m._isCredentialTimestampValid(_nconf, *_c)) {
 					return _c;
 				}
 			}
-			return (Capability *)0;
+			return (Capability*)0;
 		}
 
-	private:
-		Hashtable< uint32_t,Capability >::Iterator _hti;
-		uint32_t *_k;
-		Capability *_c;
-		Membership &_m;
-		const NetworkConfig &_nconf;
+	  private:
+		Hashtable<uint32_t, Capability>::Iterator _hti;
+		uint32_t* _k;
+		Capability* _c;
+		Membership& _m;
+		const NetworkConfig& _nconf;
 	};
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 137 - 245
node/Metrics.cpp

@@ -10,263 +10,155 @@
  * of this software will be governed by version 2.0 of the Apache License.
  */
 
-#include <prometheus/simpleapi.h>
 #include <prometheus/histogram.h>
+#include <prometheus/simpleapi.h>
 
 namespace prometheus {
-    namespace simpleapi {
-        std::shared_ptr<Registry> registry_ptr = std::make_shared<Registry>();
-        Registry&                 registry = *registry_ptr;
-        SaveToFile saver;
-    }
-}
+namespace simpleapi {
+std::shared_ptr<Registry> registry_ptr = std::make_shared<Registry>();
+Registry& registry = *registry_ptr;
+SaveToFile saver;
+}	// namespace simpleapi
+}	// namespace prometheus
 
 namespace ZeroTier {
-    namespace Metrics {
-        // Packet Type Counts
-        prometheus::simpleapi::counter_family_t packets
-        { "zt_packet", "ZeroTier packet type counts"};
-
-        // Incoming packets
-        prometheus::simpleapi::counter_metric_t pkt_nop_in
-        { packets.Add({{"packet_type", "nop"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_error_in
-        { packets.Add({{"packet_type", "error"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_ack_in
-        { packets.Add({{"packet_type", "ack"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_qos_in
-        { packets.Add({{"packet_type", "qos"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_hello_in
-        { packets.Add({{"packet_type", "hello"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_ok_in
-        { packets.Add({{"packet_type", "ok"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_whois_in
-        { packets.Add({{"packet_type", "whois"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_rendezvous_in
-        { packets.Add({{"packet_type", "rendezvous"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_frame_in
-        { packets.Add({{"packet_type", "frame"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_ext_frame_in
-        { packets.Add({{"packet_type", "ext_frame"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_echo_in
-        { packets.Add({{"packet_type", "echo"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_multicast_like_in
-        { packets.Add({{"packet_type", "multicast_like"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_network_credentials_in
-        { packets.Add({{"packet_type", "network_credentials"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_network_config_request_in
-        { packets.Add({{"packet_type", "network_config_request"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_network_config_in
-        { packets.Add({{"packet_type", "network_config"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_multicast_gather_in
-        { packets.Add({{"packet_type", "multicast_gather"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_multicast_frame_in
-        { packets.Add({{"packet_type", "multicast_frame"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_push_direct_paths_in
-        { packets.Add({{"packet_type", "push_direct_paths"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_user_message_in
-        { packets.Add({{"packet_type", "user_message"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_remote_trace_in
-        { packets.Add({{"packet_type", "remote_trace"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_path_negotiation_request_in
-        { packets.Add({{"packet_type", "path_negotiation_request"}, {"direction", "rx"}}) };
-
-        // Outgoing packets
-        prometheus::simpleapi::counter_metric_t pkt_nop_out
-        { packets.Add({{"packet_type", "nop"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_error_out
-        { packets.Add({{"packet_type", "error"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_ack_out
-        { packets.Add({{"packet_type", "ack"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_qos_out
-        { packets.Add({{"packet_type", "qos"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_hello_out
-        { packets.Add({{"packet_type", "hello"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_ok_out
-        { packets.Add({{"packet_type", "ok"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_whois_out
-        { packets.Add({{"packet_type", "whois"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_rendezvous_out
-        { packets.Add({{"packet_type", "rendezvous"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_frame_out
-        { packets.Add({{"packet_type", "frame"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_ext_frame_out
-        { packets.Add({{"packet_type", "ext_frame"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_echo_out
-        { packets.Add({{"packet_type", "echo"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_multicast_like_out
-        { packets.Add({{"packet_type", "multicast_like"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_network_credentials_out
-        { packets.Add({{"packet_type", "network_credentials"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_network_config_request_out
-        { packets.Add({{"packet_type", "network_config_request"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_network_config_out
-        { packets.Add({{"packet_type", "network_config"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_multicast_gather_out
-        { packets.Add({{"packet_type", "multicast_gather"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_multicast_frame_out
-        { packets.Add({{"packet_type", "multicast_frame"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_push_direct_paths_out
-        { packets.Add({{"packet_type", "push_direct_paths"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_user_message_out
-        { packets.Add({{"packet_type", "user_message"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_remote_trace_out
-        { packets.Add({{"packet_type", "remote_trace"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_path_negotiation_request_out
-        { packets.Add({{"packet_type", "path_negotiation_request"}, {"direction", "tx"}}) };
-
-
-        // Packet Error Counts
-        prometheus::simpleapi::counter_family_t packet_errors
-        { "zt_packet_error", "ZeroTier packet errors"};
-
-        // Incoming Error Counts
-        prometheus::simpleapi::counter_metric_t pkt_error_obj_not_found_in
-        { packet_errors.Add({{"error_type", "obj_not_found"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_error_unsupported_op_in
-        { packet_errors.Add({{"error_type", "unsupported_operation"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_error_identity_collision_in
-        { packet_errors.Add({{"error_type", "identity_collision"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_error_need_membership_cert_in
-        { packet_errors.Add({{"error_type", "need_membership_certificate"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_error_network_access_denied_in
-        { packet_errors.Add({{"error_type", "network_access_denied"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_error_unwanted_multicast_in
-        { packet_errors.Add({{"error_type", "unwanted_multicast"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_error_authentication_required_in
-        { packet_errors.Add({{"error_type", "authentication_required"}, {"direction", "rx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_error_internal_server_error_in
-        { packet_errors.Add({{"error_type", "internal_server_error"}, {"direction", "rx"}}) };
+namespace Metrics {
+// Packet Type Counts
+prometheus::simpleapi::counter_family_t packets { "zt_packet", "ZeroTier packet type counts" };
+
+// Incoming packets
+prometheus::simpleapi::counter_metric_t pkt_nop_in { packets.Add({ { "packet_type", "nop" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_error_in { packets.Add({ { "packet_type", "error" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_ack_in { packets.Add({ { "packet_type", "ack" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_qos_in { packets.Add({ { "packet_type", "qos" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_hello_in { packets.Add({ { "packet_type", "hello" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_ok_in { packets.Add({ { "packet_type", "ok" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_whois_in { packets.Add({ { "packet_type", "whois" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_rendezvous_in { packets.Add({ { "packet_type", "rendezvous" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_frame_in { packets.Add({ { "packet_type", "frame" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_ext_frame_in { packets.Add({ { "packet_type", "ext_frame" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_echo_in { packets.Add({ { "packet_type", "echo" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_multicast_like_in { packets.Add({ { "packet_type", "multicast_like" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_network_credentials_in { packets.Add({ { "packet_type", "network_credentials" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_network_config_request_in { packets.Add({ { "packet_type", "network_config_request" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_network_config_in { packets.Add({ { "packet_type", "network_config" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_multicast_gather_in { packets.Add({ { "packet_type", "multicast_gather" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_multicast_frame_in { packets.Add({ { "packet_type", "multicast_frame" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_push_direct_paths_in { packets.Add({ { "packet_type", "push_direct_paths" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_user_message_in { packets.Add({ { "packet_type", "user_message" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_remote_trace_in { packets.Add({ { "packet_type", "remote_trace" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_path_negotiation_request_in { packets.Add({ { "packet_type", "path_negotiation_request" }, { "direction", "rx" } }) };
+
+// Outgoing packets
+prometheus::simpleapi::counter_metric_t pkt_nop_out { packets.Add({ { "packet_type", "nop" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_error_out { packets.Add({ { "packet_type", "error" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_ack_out { packets.Add({ { "packet_type", "ack" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_qos_out { packets.Add({ { "packet_type", "qos" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_hello_out { packets.Add({ { "packet_type", "hello" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_ok_out { packets.Add({ { "packet_type", "ok" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_whois_out { packets.Add({ { "packet_type", "whois" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_rendezvous_out { packets.Add({ { "packet_type", "rendezvous" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_frame_out { packets.Add({ { "packet_type", "frame" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_ext_frame_out { packets.Add({ { "packet_type", "ext_frame" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_echo_out { packets.Add({ { "packet_type", "echo" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_multicast_like_out { packets.Add({ { "packet_type", "multicast_like" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_network_credentials_out { packets.Add({ { "packet_type", "network_credentials" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_network_config_request_out { packets.Add({ { "packet_type", "network_config_request" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_network_config_out { packets.Add({ { "packet_type", "network_config" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_multicast_gather_out { packets.Add({ { "packet_type", "multicast_gather" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_multicast_frame_out { packets.Add({ { "packet_type", "multicast_frame" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_push_direct_paths_out { packets.Add({ { "packet_type", "push_direct_paths" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_user_message_out { packets.Add({ { "packet_type", "user_message" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_remote_trace_out { packets.Add({ { "packet_type", "remote_trace" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_path_negotiation_request_out { packets.Add({ { "packet_type", "path_negotiation_request" }, { "direction", "tx" } }) };
+
+// Packet Error Counts
+prometheus::simpleapi::counter_family_t packet_errors { "zt_packet_error", "ZeroTier packet errors" };
+
+// Incoming Error Counts
+prometheus::simpleapi::counter_metric_t pkt_error_obj_not_found_in { packet_errors.Add({ { "error_type", "obj_not_found" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_error_unsupported_op_in { packet_errors.Add({ { "error_type", "unsupported_operation" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_error_identity_collision_in { packet_errors.Add({ { "error_type", "identity_collision" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_error_need_membership_cert_in { packet_errors.Add({ { "error_type", "need_membership_certificate" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_error_network_access_denied_in { packet_errors.Add({ { "error_type", "network_access_denied" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_error_unwanted_multicast_in { packet_errors.Add({ { "error_type", "unwanted_multicast" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_error_authentication_required_in { packet_errors.Add({ { "error_type", "authentication_required" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_error_internal_server_error_in { packet_errors.Add({ { "error_type", "internal_server_error" }, { "direction", "rx" } }) };
+
+// Outgoing Error Counts
+prometheus::simpleapi::counter_metric_t pkt_error_obj_not_found_out { packet_errors.Add({ { "error_type", "obj_not_found" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_error_unsupported_op_out { packet_errors.Add({ { "error_type", "unsupported_operation" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_error_identity_collision_out { packet_errors.Add({ { "error_type", "identity_collision" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_error_need_membership_cert_out { packet_errors.Add({ { "error_type", "need_membership_certificate" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_error_network_access_denied_out { packet_errors.Add({ { "error_type", "network_access_denied" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_error_unwanted_multicast_out { packet_errors.Add({ { "error_type", "unwanted_multicast" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_error_authentication_required_out { packet_errors.Add({ { "error_type", "authentication_required" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t pkt_error_internal_server_error_out { packet_errors.Add({ { "error_type", "internal_server_error" }, { "direction", "tx" } }) };
+
+// Data Sent/Received Metrics
+prometheus::simpleapi::counter_family_t data { "zt_data", "number of bytes ZeroTier has transmitted or received" };
+prometheus::simpleapi::counter_metric_t udp_recv { data.Add({ { "protocol", "udp" }, { "direction", "rx" } }) };
+prometheus::simpleapi::counter_metric_t udp_send { data.Add({ { "protocol", "udp" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t tcp_send { data.Add({ { "protocol", "tcp" }, { "direction", "tx" } }) };
+prometheus::simpleapi::counter_metric_t tcp_recv { data.Add({ { "protocol", "tcp" }, { "direction", "rx" } }) };
+
+// Network Metrics
+prometheus::simpleapi::gauge_metric_t network_num_joined { "zt_num_networks", "number of networks this instance is joined to" };
+prometheus::simpleapi::gauge_family_t network_num_multicast_groups { "zt_network_multicast_groups_subscribed", "number of multicast groups networks are subscribed to" };
+prometheus::simpleapi::counter_family_t network_packets { "zt_network_packets", "number of incoming/outgoing packets per network" };
 
-        // Outgoing Error Counts
-        prometheus::simpleapi::counter_metric_t pkt_error_obj_not_found_out
-        { packet_errors.Add({{"error_type", "obj_not_found"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_error_unsupported_op_out
-        { packet_errors.Add({{"error_type", "unsupported_operation"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_error_identity_collision_out
-        { packet_errors.Add({{"error_type", "identity_collision"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_error_need_membership_cert_out
-        { packet_errors.Add({{"error_type", "need_membership_certificate"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_error_network_access_denied_out
-        { packet_errors.Add({{"error_type", "network_access_denied"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_error_unwanted_multicast_out
-        { packet_errors.Add({{"error_type", "unwanted_multicast"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_error_authentication_required_out
-        { packet_errors.Add({{"error_type", "authentication_required"}, {"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t pkt_error_internal_server_error_out
-        { packet_errors.Add({{"error_type", "internal_server_error"}, {"direction", "tx"}}) };
-
-        // Data Sent/Received Metrics
-        prometheus::simpleapi::counter_family_t data
-        { "zt_data", "number of bytes ZeroTier has transmitted or received" };
-        prometheus::simpleapi::counter_metric_t udp_recv
-        { data.Add({{"protocol","udp"},{"direction","rx"}}) };
-        prometheus::simpleapi::counter_metric_t udp_send
-        { data.Add({{"protocol","udp"},{"direction","tx"}}) };
-        prometheus::simpleapi::counter_metric_t tcp_send
-        { data.Add({{"protocol","tcp"},{"direction", "tx"}}) };
-        prometheus::simpleapi::counter_metric_t tcp_recv
-        { data.Add({{"protocol","tcp"},{"direction", "rx"}}) };
-
-        // Network Metrics
-        prometheus::simpleapi::gauge_metric_t network_num_joined
-        { "zt_num_networks", "number of networks this instance is joined to" };
-        prometheus::simpleapi::gauge_family_t network_num_multicast_groups
-        { "zt_network_multicast_groups_subscribed", "number of multicast groups networks are subscribed to" };
-        prometheus::simpleapi::counter_family_t network_packets
-        { "zt_network_packets", "number of incoming/outgoing packets per network" };
-        
 #ifndef ZT_NO_PEER_METRICS
-        // PeerMetrics
-        prometheus::CustomFamily<prometheus::Histogram<uint64_t>> &peer_latency = 
-        prometheus::Builder<prometheus::Histogram<uint64_t>>()
-            .Name("zt_peer_latency")
-            .Help("peer latency (ms)")
-            .Register(prometheus::simpleapi::registry);
-    
-        prometheus::simpleapi::gauge_family_t peer_path_count
-        { "zt_peer_path_count", "number of paths to peer" };
-        prometheus::simpleapi::counter_family_t peer_packets
-        { "zt_peer_packets", "number of packets to/from a peer" };
-        prometheus::simpleapi::counter_family_t peer_packet_errors
-        { "zt_peer_packet_errors" , "number of incoming packet errors from a peer" };
-#endif
+// PeerMetrics
+prometheus::CustomFamily<prometheus::Histogram<uint64_t> >& peer_latency = prometheus::Builder<prometheus::Histogram<uint64_t> >().Name("zt_peer_latency").Help("peer latency (ms)").Register(prometheus::simpleapi::registry);
 
-        // General Controller Metrics
-        prometheus::simpleapi::gauge_metric_t   network_count
-        {"controller_network_count", "number of networks the controller is serving"};
-        prometheus::simpleapi::gauge_metric_t   member_count
-        {"controller_member_count", "number of network members the controller is serving"};
-        prometheus::simpleapi::counter_metric_t network_changes
-        {"controller_network_change_count", "number of times a network configuration is changed"};
-        prometheus::simpleapi::counter_metric_t member_changes
-        {"controller_member_change_count", "number of times a network member configuration is changed"};
-        prometheus::simpleapi::counter_metric_t member_auths
-        {"controller_member_auth_count", "number of network member auths"};
-        prometheus::simpleapi::counter_metric_t member_deauths
-        {"controller_member_deauth_count", "number of network member deauths"};
+prometheus::simpleapi::gauge_family_t peer_path_count { "zt_peer_path_count", "number of paths to peer" };
+prometheus::simpleapi::counter_family_t peer_packets { "zt_peer_packets", "number of packets to/from a peer" };
+prometheus::simpleapi::counter_family_t peer_packet_errors { "zt_peer_packet_errors", "number of incoming packet errors from a peer" };
+#endif
 
-        prometheus::simpleapi::gauge_metric_t network_config_request_queue_size
-        { "controller_network_config_request_queue", "number of entries in the request queue for network configurations" };
-        
-        prometheus::simpleapi::counter_metric_t sso_expiration_checks
-        { "controller_sso_expiration_checks", "number of sso expiration checks done" };
+// General Controller Metrics
+prometheus::simpleapi::gauge_metric_t network_count { "controller_network_count", "number of networks the controller is serving" };
+prometheus::simpleapi::gauge_metric_t member_count { "controller_member_count", "number of network members the controller is serving" };
+prometheus::simpleapi::counter_metric_t network_changes { "controller_network_change_count", "number of times a network configuration is changed" };
+prometheus::simpleapi::counter_metric_t member_changes { "controller_member_change_count", "number of times a network member configuration is changed" };
+prometheus::simpleapi::counter_metric_t member_auths { "controller_member_auth_count", "number of network member auths" };
+prometheus::simpleapi::counter_metric_t member_deauths { "controller_member_deauth_count", "number of network member deauths" };
 
-        prometheus::simpleapi::counter_metric_t sso_member_deauth
-        { "controller_sso_timeouts", "number of sso timeouts" };
+prometheus::simpleapi::gauge_metric_t network_config_request_queue_size { "controller_network_config_request_queue", "number of entries in the request queue for network configurations" };
 
-        prometheus::simpleapi::counter_metric_t network_config_request
-        { "controller_network_config_request", "count of config requests handled" };
-        prometheus::simpleapi::gauge_metric_t network_config_request_threads
-        { "controller_network_config_request_threads", "number of active network config handling threads" };
-        prometheus::simpleapi::counter_metric_t db_get_network
-        { "controller_db_get_network", "counter" };
-        prometheus::simpleapi::counter_metric_t db_get_network_and_member
-        { "controller_db_get_network_and_member", "counter" };
-        prometheus::simpleapi::counter_metric_t db_get_network_and_member_and_summary
-        { "controller_db_get_networK_and_member_summary", "counter" };
-        prometheus::simpleapi::counter_metric_t db_get_member_list
-        { "controller_db_get_member_list", "counter" };
-        prometheus::simpleapi::counter_metric_t db_get_network_list
-        { "controller_db_get_network_list", "counter" };
-        prometheus::simpleapi::counter_metric_t db_member_change
-        { "controller_db_member_change", "counter" };
-        prometheus::simpleapi::counter_metric_t db_network_change
-        { "controller_db_network_change", "counter" };
+prometheus::simpleapi::counter_metric_t sso_expiration_checks { "controller_sso_expiration_checks", "number of sso expiration checks done" };
 
-#ifdef ZT_CONTROLLER_USE_LIBPQ
-        // Central Controller Metrics
-        prometheus::simpleapi::counter_metric_t pgsql_mem_notification
-        { "controller_pgsql_member_notifications_received", "number of member change notifications received via pgsql NOTIFY" };
-        prometheus::simpleapi::counter_metric_t pgsql_net_notification
-        { "controller_pgsql_network_notifications_received", "number of network change notifications received via pgsql NOTIFY" };
-        prometheus::simpleapi::counter_metric_t pgsql_node_checkin
-        { "controller_pgsql_node_checkin_count", "number of node check-ins (pgsql)" };
-        prometheus::simpleapi::counter_metric_t pgsql_commit_ticks
-        { "controller_pgsql_commit_ticks", "number of commit ticks run (pgsql)" };
-        prometheus::simpleapi::counter_metric_t db_get_sso_info
-        { "controller_db_get_sso_info", "counter" };
+prometheus::simpleapi::counter_metric_t sso_member_deauth { "controller_sso_timeouts", "number of sso timeouts" };
 
-        prometheus::simpleapi::counter_metric_t redis_mem_notification
-        { "controller_redis_member_notifications_received", "number of member change notifications received via redis" };
-        prometheus::simpleapi::counter_metric_t redis_net_notification
-        { "controller_redis_network_notifications_received", "number of network change notifications received via redis" };
-        prometheus::simpleapi::counter_metric_t redis_node_checkin
-        { "controller_redis_node_checkin_count", "number of node check-ins (redis)" };
+prometheus::simpleapi::counter_metric_t network_config_request { "controller_network_config_request", "count of config requests handled" };
+prometheus::simpleapi::gauge_metric_t network_config_request_threads { "controller_network_config_request_threads", "number of active network config handling threads" };
+prometheus::simpleapi::counter_metric_t db_get_network { "controller_db_get_network", "counter" };
+prometheus::simpleapi::counter_metric_t db_get_network_and_member { "controller_db_get_network_and_member", "counter" };
+prometheus::simpleapi::counter_metric_t db_get_network_and_member_and_summary { "controller_db_get_networK_and_member_summary", "counter" };
+prometheus::simpleapi::counter_metric_t db_get_member_list { "controller_db_get_member_list", "counter" };
+prometheus::simpleapi::counter_metric_t db_get_network_list { "controller_db_get_network_list", "counter" };
+prometheus::simpleapi::counter_metric_t db_member_change { "controller_db_member_change", "counter" };
+prometheus::simpleapi::counter_metric_t db_network_change { "controller_db_network_change", "counter" };
 
-        // Central DB Pool Metrics
-        prometheus::simpleapi::counter_metric_t conn_counter
-        { "controller_pgsql_connections_created", "number of pgsql connections created"};
-        prometheus::simpleapi::counter_metric_t max_pool_size
-        { "controller_pgsql_max_conn_pool_size", "max connection pool size for postgres"};
-        prometheus::simpleapi::counter_metric_t min_pool_size
-        { "controller_pgsql_min_conn_pool_size", "minimum connection pool size for postgres" };
-        prometheus::simpleapi::gauge_metric_t   pool_avail
-        { "controller_pgsql_available_conns", "number of available postgres connections" };
-        prometheus::simpleapi::gauge_metric_t   pool_in_use
-        { "controller_pgsql_in_use_conns", "number of postgres database connections in use" };
-        prometheus::simpleapi::counter_metric_t pool_errors
-        { "controller_pgsql_connection_errors", "number of connection errors the connection pool has seen" };
+#ifdef ZT_CONTROLLER_USE_LIBPQ
+// Central Controller Metrics
+prometheus::simpleapi::counter_metric_t pgsql_mem_notification { "controller_pgsql_member_notifications_received", "number of member change notifications received via pgsql NOTIFY" };
+prometheus::simpleapi::counter_metric_t pgsql_net_notification { "controller_pgsql_network_notifications_received", "number of network change notifications received via pgsql NOTIFY" };
+prometheus::simpleapi::counter_metric_t pgsql_node_checkin { "controller_pgsql_node_checkin_count", "number of node check-ins (pgsql)" };
+prometheus::simpleapi::counter_metric_t pgsql_commit_ticks { "controller_pgsql_commit_ticks", "number of commit ticks run (pgsql)" };
+prometheus::simpleapi::counter_metric_t db_get_sso_info { "controller_db_get_sso_info", "counter" };
+
+prometheus::simpleapi::counter_metric_t redis_mem_notification { "controller_redis_member_notifications_received", "number of member change notifications received via redis" };
+prometheus::simpleapi::counter_metric_t redis_net_notification { "controller_redis_network_notifications_received", "number of network change notifications received via redis" };
+prometheus::simpleapi::counter_metric_t redis_node_checkin { "controller_redis_node_checkin_count", "number of node check-ins (redis)" };
+
+// Central DB Pool Metrics
+prometheus::simpleapi::counter_metric_t conn_counter { "controller_pgsql_connections_created", "number of pgsql connections created" };
+prometheus::simpleapi::counter_metric_t max_pool_size { "controller_pgsql_max_conn_pool_size", "max connection pool size for postgres" };
+prometheus::simpleapi::counter_metric_t min_pool_size { "controller_pgsql_min_conn_pool_size", "minimum connection pool size for postgres" };
+prometheus::simpleapi::gauge_metric_t pool_avail { "controller_pgsql_available_conns", "number of available postgres connections" };
+prometheus::simpleapi::gauge_metric_t pool_in_use { "controller_pgsql_in_use_conns", "number of postgres database connections in use" };
+prometheus::simpleapi::counter_metric_t pool_errors { "controller_pgsql_connection_errors", "number of connection errors the connection pool has seen" };
 #endif
-    }
-}
+}	// namespace Metrics
+}	// namespace ZeroTier

+ 135 - 138
node/Metrics.hpp

@@ -12,155 +12,152 @@
 #ifndef METRICS_H_
 #define METRICS_H_
 
-#include <prometheus/simpleapi.h>
 #include <prometheus/histogram.h>
+#include <prometheus/simpleapi.h>
 
 namespace prometheus {
-    namespace simpleapi {
-        extern std::shared_ptr<Registry> registry_ptr;
-    }
+namespace simpleapi {
+extern std::shared_ptr<Registry> registry_ptr;
 }
+}	// namespace prometheus
 
 namespace ZeroTier {
-    namespace Metrics {
-        // Packet Type Counts
-        extern prometheus::simpleapi::counter_family_t packets;
-
-        // incoming packets
-        extern prometheus::simpleapi::counter_metric_t pkt_nop_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_error_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_ack_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_qos_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_hello_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_ok_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_whois_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_rendezvous_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_frame_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_ext_frame_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_echo_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_multicast_like_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_network_credentials_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_network_config_request_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_network_config_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_multicast_gather_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_multicast_frame_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_push_direct_paths_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_user_message_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_remote_trace_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_path_negotiation_request_in;
-
-        // outgoing packets
-        extern prometheus::simpleapi::counter_metric_t pkt_nop_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_error_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_ack_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_qos_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_hello_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_ok_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_whois_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_rendezvous_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_frame_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_ext_frame_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_echo_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_multicast_like_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_network_credentials_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_network_config_request_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_network_config_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_multicast_gather_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_multicast_frame_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_push_direct_paths_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_user_message_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_remote_trace_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_path_negotiation_request_out;
-
-        // Packet Error Counts
-        extern prometheus::simpleapi::counter_family_t packet_errors;
-
-        // incoming errors
-        extern prometheus::simpleapi::counter_metric_t pkt_error_obj_not_found_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_error_unsupported_op_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_error_identity_collision_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_error_need_membership_cert_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_error_network_access_denied_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_error_unwanted_multicast_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_error_authentication_required_in;
-        extern prometheus::simpleapi::counter_metric_t pkt_error_internal_server_error_in;
-
-        // outgoing errors
-        extern prometheus::simpleapi::counter_metric_t pkt_error_obj_not_found_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_error_unsupported_op_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_error_identity_collision_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_error_need_membership_cert_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_error_network_access_denied_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_error_unwanted_multicast_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_error_authentication_required_out;
-        extern prometheus::simpleapi::counter_metric_t pkt_error_internal_server_error_out;
-
-        // Data Sent/Received Metrics
-        extern prometheus::simpleapi::counter_family_t data;
-        extern prometheus::simpleapi::counter_metric_t udp_send;
-        extern prometheus::simpleapi::counter_metric_t udp_recv;
-        extern prometheus::simpleapi::counter_metric_t tcp_send;
-        extern prometheus::simpleapi::counter_metric_t tcp_recv;
-
-        // Network Metrics
-        extern prometheus::simpleapi::gauge_metric_t   network_num_joined;
-        extern prometheus::simpleapi::gauge_family_t   network_num_multicast_groups;
-        extern prometheus::simpleapi::counter_family_t network_packets;
+namespace Metrics {
+// Packet Type Counts
+extern prometheus::simpleapi::counter_family_t packets;
+
+// incoming packets
+extern prometheus::simpleapi::counter_metric_t pkt_nop_in;
+extern prometheus::simpleapi::counter_metric_t pkt_error_in;
+extern prometheus::simpleapi::counter_metric_t pkt_ack_in;
+extern prometheus::simpleapi::counter_metric_t pkt_qos_in;
+extern prometheus::simpleapi::counter_metric_t pkt_hello_in;
+extern prometheus::simpleapi::counter_metric_t pkt_ok_in;
+extern prometheus::simpleapi::counter_metric_t pkt_whois_in;
+extern prometheus::simpleapi::counter_metric_t pkt_rendezvous_in;
+extern prometheus::simpleapi::counter_metric_t pkt_frame_in;
+extern prometheus::simpleapi::counter_metric_t pkt_ext_frame_in;
+extern prometheus::simpleapi::counter_metric_t pkt_echo_in;
+extern prometheus::simpleapi::counter_metric_t pkt_multicast_like_in;
+extern prometheus::simpleapi::counter_metric_t pkt_network_credentials_in;
+extern prometheus::simpleapi::counter_metric_t pkt_network_config_request_in;
+extern prometheus::simpleapi::counter_metric_t pkt_network_config_in;
+extern prometheus::simpleapi::counter_metric_t pkt_multicast_gather_in;
+extern prometheus::simpleapi::counter_metric_t pkt_multicast_frame_in;
+extern prometheus::simpleapi::counter_metric_t pkt_push_direct_paths_in;
+extern prometheus::simpleapi::counter_metric_t pkt_user_message_in;
+extern prometheus::simpleapi::counter_metric_t pkt_remote_trace_in;
+extern prometheus::simpleapi::counter_metric_t pkt_path_negotiation_request_in;
+
+// outgoing packets
+extern prometheus::simpleapi::counter_metric_t pkt_nop_out;
+extern prometheus::simpleapi::counter_metric_t pkt_error_out;
+extern prometheus::simpleapi::counter_metric_t pkt_ack_out;
+extern prometheus::simpleapi::counter_metric_t pkt_qos_out;
+extern prometheus::simpleapi::counter_metric_t pkt_hello_out;
+extern prometheus::simpleapi::counter_metric_t pkt_ok_out;
+extern prometheus::simpleapi::counter_metric_t pkt_whois_out;
+extern prometheus::simpleapi::counter_metric_t pkt_rendezvous_out;
+extern prometheus::simpleapi::counter_metric_t pkt_frame_out;
+extern prometheus::simpleapi::counter_metric_t pkt_ext_frame_out;
+extern prometheus::simpleapi::counter_metric_t pkt_echo_out;
+extern prometheus::simpleapi::counter_metric_t pkt_multicast_like_out;
+extern prometheus::simpleapi::counter_metric_t pkt_network_credentials_out;
+extern prometheus::simpleapi::counter_metric_t pkt_network_config_request_out;
+extern prometheus::simpleapi::counter_metric_t pkt_network_config_out;
+extern prometheus::simpleapi::counter_metric_t pkt_multicast_gather_out;
+extern prometheus::simpleapi::counter_metric_t pkt_multicast_frame_out;
+extern prometheus::simpleapi::counter_metric_t pkt_push_direct_paths_out;
+extern prometheus::simpleapi::counter_metric_t pkt_user_message_out;
+extern prometheus::simpleapi::counter_metric_t pkt_remote_trace_out;
+extern prometheus::simpleapi::counter_metric_t pkt_path_negotiation_request_out;
+
+// Packet Error Counts
+extern prometheus::simpleapi::counter_family_t packet_errors;
+
+// incoming errors
+extern prometheus::simpleapi::counter_metric_t pkt_error_obj_not_found_in;
+extern prometheus::simpleapi::counter_metric_t pkt_error_unsupported_op_in;
+extern prometheus::simpleapi::counter_metric_t pkt_error_identity_collision_in;
+extern prometheus::simpleapi::counter_metric_t pkt_error_need_membership_cert_in;
+extern prometheus::simpleapi::counter_metric_t pkt_error_network_access_denied_in;
+extern prometheus::simpleapi::counter_metric_t pkt_error_unwanted_multicast_in;
+extern prometheus::simpleapi::counter_metric_t pkt_error_authentication_required_in;
+extern prometheus::simpleapi::counter_metric_t pkt_error_internal_server_error_in;
+
+// outgoing errors
+extern prometheus::simpleapi::counter_metric_t pkt_error_obj_not_found_out;
+extern prometheus::simpleapi::counter_metric_t pkt_error_unsupported_op_out;
+extern prometheus::simpleapi::counter_metric_t pkt_error_identity_collision_out;
+extern prometheus::simpleapi::counter_metric_t pkt_error_need_membership_cert_out;
+extern prometheus::simpleapi::counter_metric_t pkt_error_network_access_denied_out;
+extern prometheus::simpleapi::counter_metric_t pkt_error_unwanted_multicast_out;
+extern prometheus::simpleapi::counter_metric_t pkt_error_authentication_required_out;
+extern prometheus::simpleapi::counter_metric_t pkt_error_internal_server_error_out;
+
+// Data Sent/Received Metrics
+extern prometheus::simpleapi::counter_family_t data;
+extern prometheus::simpleapi::counter_metric_t udp_send;
+extern prometheus::simpleapi::counter_metric_t udp_recv;
+extern prometheus::simpleapi::counter_metric_t tcp_send;
+extern prometheus::simpleapi::counter_metric_t tcp_recv;
+
+// Network Metrics
+extern prometheus::simpleapi::gauge_metric_t network_num_joined;
+extern prometheus::simpleapi::gauge_family_t network_num_multicast_groups;
+extern prometheus::simpleapi::counter_family_t network_packets;
 
 #ifndef ZT_NO_PEER_METRICS
-        // Peer Metrics
-        extern prometheus::CustomFamily<prometheus::Histogram<uint64_t>> &peer_latency;
-        extern prometheus::simpleapi::gauge_family_t   peer_path_count;
-        extern prometheus::simpleapi::counter_family_t peer_packets;
-        extern prometheus::simpleapi::counter_family_t peer_packet_errors;
+// Peer Metrics
+extern prometheus::CustomFamily<prometheus::Histogram<uint64_t> >& peer_latency;
+extern prometheus::simpleapi::gauge_family_t peer_path_count;
+extern prometheus::simpleapi::counter_family_t peer_packets;
+extern prometheus::simpleapi::counter_family_t peer_packet_errors;
 #endif
 
-        // General Controller Metrics
-        extern prometheus::simpleapi::gauge_metric_t   network_count;
-        extern prometheus::simpleapi::gauge_metric_t   member_count;
-        extern prometheus::simpleapi::counter_metric_t network_changes;
-        extern prometheus::simpleapi::counter_metric_t member_changes;
-        extern prometheus::simpleapi::counter_metric_t member_auths;
-        extern prometheus::simpleapi::counter_metric_t member_deauths;
-
-        extern prometheus::simpleapi::gauge_metric_t network_config_request_queue_size;
-        extern prometheus::simpleapi::counter_metric_t sso_expiration_checks;
-        extern prometheus::simpleapi::counter_metric_t sso_member_deauth;
-        extern prometheus::simpleapi::counter_metric_t network_config_request;
-        extern prometheus::simpleapi::gauge_metric_t network_config_request_threads;
-
-        extern prometheus::simpleapi::counter_metric_t db_get_network;
-        extern prometheus::simpleapi::counter_metric_t db_get_network_and_member;
-        extern prometheus::simpleapi::counter_metric_t db_get_network_and_member_and_summary;
-        extern prometheus::simpleapi::counter_metric_t db_get_member_list;
-        extern prometheus::simpleapi::counter_metric_t db_get_network_list;
-        extern prometheus::simpleapi::counter_metric_t db_member_change;
-        extern prometheus::simpleapi::counter_metric_t db_network_change;
-
+// General Controller Metrics
+extern prometheus::simpleapi::gauge_metric_t network_count;
+extern prometheus::simpleapi::gauge_metric_t member_count;
+extern prometheus::simpleapi::counter_metric_t network_changes;
+extern prometheus::simpleapi::counter_metric_t member_changes;
+extern prometheus::simpleapi::counter_metric_t member_auths;
+extern prometheus::simpleapi::counter_metric_t member_deauths;
+
+extern prometheus::simpleapi::gauge_metric_t network_config_request_queue_size;
+extern prometheus::simpleapi::counter_metric_t sso_expiration_checks;
+extern prometheus::simpleapi::counter_metric_t sso_member_deauth;
+extern prometheus::simpleapi::counter_metric_t network_config_request;
+extern prometheus::simpleapi::gauge_metric_t network_config_request_threads;
+
+extern prometheus::simpleapi::counter_metric_t db_get_network;
+extern prometheus::simpleapi::counter_metric_t db_get_network_and_member;
+extern prometheus::simpleapi::counter_metric_t db_get_network_and_member_and_summary;
+extern prometheus::simpleapi::counter_metric_t db_get_member_list;
+extern prometheus::simpleapi::counter_metric_t db_get_network_list;
+extern prometheus::simpleapi::counter_metric_t db_member_change;
+extern prometheus::simpleapi::counter_metric_t db_network_change;
 
 #ifdef ZT_CONTROLLER_USE_LIBPQ
-        // Central Controller Metrics
-        extern prometheus::simpleapi::counter_metric_t pgsql_mem_notification;
-        extern prometheus::simpleapi::counter_metric_t pgsql_net_notification;
-        extern prometheus::simpleapi::counter_metric_t pgsql_node_checkin;
-        extern prometheus::simpleapi::counter_metric_t pgsql_commit_ticks;
-        extern prometheus::simpleapi::counter_metric_t db_get_sso_info;
-        
-        extern prometheus::simpleapi::counter_metric_t redis_mem_notification;
-        extern prometheus::simpleapi::counter_metric_t redis_net_notification;
-        extern prometheus::simpleapi::counter_metric_t redis_node_checkin;
-
-        
-
-        // Central DB Pool Metrics
-        extern prometheus::simpleapi::counter_metric_t conn_counter;
-        extern prometheus::simpleapi::counter_metric_t max_pool_size;
-        extern prometheus::simpleapi::counter_metric_t min_pool_size;
-        extern prometheus::simpleapi::gauge_metric_t   pool_avail;
-        extern prometheus::simpleapi::gauge_metric_t   pool_in_use;
-        extern prometheus::simpleapi::counter_metric_t pool_errors;
+// Central Controller Metrics
+extern prometheus::simpleapi::counter_metric_t pgsql_mem_notification;
+extern prometheus::simpleapi::counter_metric_t pgsql_net_notification;
+extern prometheus::simpleapi::counter_metric_t pgsql_node_checkin;
+extern prometheus::simpleapi::counter_metric_t pgsql_commit_ticks;
+extern prometheus::simpleapi::counter_metric_t db_get_sso_info;
+
+extern prometheus::simpleapi::counter_metric_t redis_mem_notification;
+extern prometheus::simpleapi::counter_metric_t redis_net_notification;
+extern prometheus::simpleapi::counter_metric_t redis_node_checkin;
+
+// Central DB Pool Metrics
+extern prometheus::simpleapi::counter_metric_t conn_counter;
+extern prometheus::simpleapi::counter_metric_t max_pool_size;
+extern prometheus::simpleapi::counter_metric_t min_pool_size;
+extern prometheus::simpleapi::gauge_metric_t pool_avail;
+extern prometheus::simpleapi::gauge_metric_t pool_in_use;
+extern prometheus::simpleapi::counter_metric_t pool_errors;
 #endif
-    } // namespace Metrics
-}// namespace ZeroTier
+}	// namespace Metrics
+}	// namespace ZeroTier
 
-#endif // METRICS_H_
+#endif	 // METRICS_H_

+ 50 - 29
node/MulticastGroup.hpp

@@ -14,10 +14,10 @@
 #ifndef ZT_MULTICASTGROUP_HPP
 #define ZT_MULTICASTGROUP_HPP
 
-#include <stdint.h>
-
-#include "MAC.hpp"
 #include "InetAddress.hpp"
+#include "MAC.hpp"
+
+#include <stdint.h>
 
 namespace ZeroTier {
 
@@ -36,18 +36,13 @@ namespace ZeroTier {
  *
  * MulticastGroup behaves as an immutable value object.
  */
-class MulticastGroup
-{
-public:
-	MulticastGroup() :
-		_mac(),
-		_adi(0)
+class MulticastGroup {
+  public:
+	MulticastGroup() : _mac(), _adi(0)
 	{
 	}
 
-	MulticastGroup(const MAC &m,uint32_t a) :
-		_mac(m),
-		_adi(a)
+	MulticastGroup(const MAC& m, uint32_t a) : _mac(m), _adi(a)
 	{
 	}
 
@@ -57,21 +52,22 @@ public:
 	 * @param ip IP address (port field is ignored)
 	 * @return Multicast group for ARP/NDP
 	 */
-	static inline MulticastGroup deriveMulticastGroupForAddressResolution(const InetAddress &ip)
+	static inline MulticastGroup deriveMulticastGroupForAddressResolution(const InetAddress& ip)
 	{
 		if (ip.isV4()) {
 			// IPv4 wants broadcast MACs, so we shove the V4 address itself into
 			// the Multicast Group ADI field. Making V4 ARP work is basically why
 			// ADI was added, as well as handling other things that want mindless
 			// Ethernet broadcast to all.
-			return MulticastGroup(MAC(0xffffffffffffULL),Utils::ntoh(*((const uint32_t *)ip.rawIpData())));
-		} else if (ip.isV6()) {
+			return MulticastGroup(MAC(0xffffffffffffULL), Utils::ntoh(*((const uint32_t*)ip.rawIpData())));
+		}
+		else if (ip.isV6()) {
 			// IPv6 is better designed in this respect. We can compute the IPv6
 			// multicast address directly from the IP address, and it gives us
 			// 24 bits of uniqueness. Collisions aren't likely to be common enough
 			// to care about.
-			const unsigned char *a = (const unsigned char *)ip.rawIpData();
-			return MulticastGroup(MAC(0x33,0x33,0xff,a[13],a[14],a[15]),0);
+			const unsigned char* a = (const unsigned char*)ip.rawIpData();
+			return MulticastGroup(MAC(0x33, 0x33, 0xff, a[13], a[14], a[15]), 0);
 		}
 		return MulticastGroup();
 	}
@@ -79,35 +75,60 @@ public:
 	/**
 	 * @return Multicast address
 	 */
-	inline const MAC &mac() const { return _mac; }
+	inline const MAC& mac() const
+	{
+		return _mac;
+	}
 
 	/**
 	 * @return Additional distinguishing information
 	 */
-	inline uint32_t adi() const { return _adi; }
+	inline uint32_t adi() const
+	{
+		return _adi;
+	}
 
-	inline unsigned long hashCode() const { return (_mac.hashCode() ^ (unsigned long)_adi); }
+	inline unsigned long hashCode() const
+	{
+		return (_mac.hashCode() ^ (unsigned long)_adi);
+	}
 
-	inline bool operator==(const MulticastGroup &g) const { return ((_mac == g._mac)&&(_adi == g._adi)); }
-	inline bool operator!=(const MulticastGroup &g) const { return ((_mac != g._mac)||(_adi != g._adi)); }
-	inline bool operator<(const MulticastGroup &g) const
+	inline bool operator==(const MulticastGroup& g) const
+	{
+		return ((_mac == g._mac) && (_adi == g._adi));
+	}
+	inline bool operator!=(const MulticastGroup& g) const
+	{
+		return ((_mac != g._mac) || (_adi != g._adi));
+	}
+	inline bool operator<(const MulticastGroup& g) const
 	{
 		if (_mac < g._mac) {
 			return true;
-		} else if (_mac == g._mac) {
+		}
+		else if (_mac == g._mac) {
 			return (_adi < g._adi);
 		}
 		return false;
 	}
-	inline bool operator>(const MulticastGroup &g) const { return (g < *this); }
-	inline bool operator<=(const MulticastGroup &g) const { return !(g < *this); }
-	inline bool operator>=(const MulticastGroup &g) const { return !(*this < g); }
+	inline bool operator>(const MulticastGroup& g) const
+	{
+		return (g < *this);
+	}
+	inline bool operator<=(const MulticastGroup& g) const
+	{
+		return ! (g < *this);
+	}
+	inline bool operator>=(const MulticastGroup& g) const
+	{
+		return ! (*this < g);
+	}
 
-private:
+  private:
 	MAC _mac;
 	uint32_t _adi;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 116 - 127
node/Multicaster.cpp

@@ -11,25 +11,24 @@
  */
 /****/
 
-#include <algorithm>
-
-#include "Constants.hpp"
-#include "RuntimeEnvironment.hpp"
 #include "Multicaster.hpp"
-#include "Topology.hpp"
-#include "Switch.hpp"
-#include "Packet.hpp"
-#include "Peer.hpp"
+
 #include "C25519.hpp"
 #include "CertificateOfMembership.hpp"
-#include "Node.hpp"
+#include "Constants.hpp"
 #include "Network.hpp"
+#include "Node.hpp"
+#include "Packet.hpp"
+#include "Peer.hpp"
+#include "RuntimeEnvironment.hpp"
+#include "Switch.hpp"
+#include "Topology.hpp"
+
+#include <algorithm>
 
 namespace ZeroTier {
 
-Multicaster::Multicaster(const RuntimeEnvironment *renv) :
-	RR(renv),
-	_groups(32)
+Multicaster::Multicaster(const RuntimeEnvironment* renv) : RR(renv), _groups(32)
 {
 }
 
@@ -37,24 +36,24 @@ Multicaster::~Multicaster()
 {
 }
 
-void Multicaster::addMultiple(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup &mg,const void *addresses,unsigned int count,unsigned int totalKnown)
+void Multicaster::addMultiple(void* tPtr, int64_t now, uint64_t nwid, const MulticastGroup& mg, const void* addresses, unsigned int count, unsigned int totalKnown)
 {
-	const unsigned char *p = (const unsigned char *)addresses;
-	const unsigned char *e = p + (5 * count);
+	const unsigned char* p = (const unsigned char*)addresses;
+	const unsigned char* e = p + (5 * count);
 	Mutex::Lock _l(_groups_m);
-	MulticastGroupStatus &gs = _groups[Multicaster::Key(nwid,mg)];
+	MulticastGroupStatus& gs = _groups[Multicaster::Key(nwid, mg)];
 	while (p != e) {
-		_add(tPtr,now,nwid,mg,gs,Address(p,5));
+		_add(tPtr, now, nwid, mg, gs, Address(p, 5));
 		p += 5;
 	}
 }
 
-void Multicaster::remove(uint64_t nwid,const MulticastGroup &mg,const Address &member)
+void Multicaster::remove(uint64_t nwid, const MulticastGroup& mg, const Address& member)
 {
 	Mutex::Lock _l(_groups_m);
-	MulticastGroupStatus *s = _groups.get(Multicaster::Key(nwid,mg));
+	MulticastGroupStatus* s = _groups.get(Multicaster::Key(nwid, mg));
 	if (s) {
-		for(std::vector<MulticastGroupMember>::iterator m(s->members.begin());m!=s->members.end();++m) {
+		for (std::vector<MulticastGroupMember>::iterator m(s->members.begin()); m != s->members.end(); ++m) {
 			if (m->address == member) {
 				s->members.erase(m);
 				break;
@@ -63,26 +62,27 @@ void Multicaster::remove(uint64_t nwid,const MulticastGroup &mg,const Address &m
 	}
 }
 
-unsigned int Multicaster::gather(const Address &queryingPeer,uint64_t nwid,const MulticastGroup &mg,Buffer<ZT_PROTO_MAX_PACKET_LENGTH> &appendTo,unsigned int limit) const
+unsigned int Multicaster::gather(const Address& queryingPeer, uint64_t nwid, const MulticastGroup& mg, Buffer<ZT_PROTO_MAX_PACKET_LENGTH>& appendTo, unsigned int limit) const
 {
-	unsigned char *p;
-	unsigned int added = 0,i,k,rptr,totalKnown = 0;
-	uint64_t a,picked[(ZT_PROTO_MAX_PACKET_LENGTH / 5) + 2];
+	unsigned char* p;
+	unsigned int added = 0, i, k, rptr, totalKnown = 0;
+	uint64_t a, picked[(ZT_PROTO_MAX_PACKET_LENGTH / 5) + 2];
 
-	if (!limit) {
+	if (! limit) {
 		return 0;
-	} else if (limit > 0xffff) {
+	}
+	else if (limit > 0xffff) {
 		limit = 0xffff;
 	}
 
 	const unsigned int totalAt = appendTo.size();
-	appendTo.addSize(4); // sizeof(uint32_t)
+	appendTo.addSize(4);   // sizeof(uint32_t)
 	const unsigned int addedAt = appendTo.size();
-	appendTo.addSize(2); // sizeof(uint16_t)
+	appendTo.addSize(2);   // sizeof(uint16_t)
 
-	{ // Return myself if I am a member of this group
+	{	// Return myself if I am a member of this group
 		SharedPtr<Network> network(RR->node->network(nwid));
-		if ((network)&&(network->subscribedToMulticastGroup(mg,true))) {
+		if ((network) && (network->subscribedToMulticastGroup(mg, true))) {
 			RR->identity.address().appendTo(appendTo);
 			++totalKnown;
 			++added;
@@ -91,19 +91,19 @@ unsigned int Multicaster::gather(const Address &queryingPeer,uint64_t nwid,const
 
 	Mutex::Lock _l(_groups_m);
 
-	const MulticastGroupStatus *s = _groups.get(Multicaster::Key(nwid,mg));
-	if ((s)&&(!s->members.empty())) {
+	const MulticastGroupStatus* s = _groups.get(Multicaster::Key(nwid, mg));
+	if ((s) && (! s->members.empty())) {
 		totalKnown += (unsigned int)s->members.size();
 
 		// Members are returned in random order so that repeated gather queries
 		// will return different subsets of a large multicast group.
 		k = 0;
-		while ((added < limit)&&(k < s->members.size())&&((appendTo.size() + ZT_ADDRESS_LENGTH) <= ZT_PROTO_MAX_PACKET_LENGTH)) {
+		while ((added < limit) && (k < s->members.size()) && ((appendTo.size() + ZT_ADDRESS_LENGTH) <= ZT_PROTO_MAX_PACKET_LENGTH)) {
 			rptr = (unsigned int)RR->node->prng();
 
-restart_member_scan:
+		restart_member_scan:
 			a = s->members[rptr % (unsigned int)s->members.size()].address.toInt();
-			for(i=0;i<k;++i) {
+			for (i = 0; i < k; ++i) {
 				if (picked[i] == a) {
 					++rptr;
 					goto restart_member_scan;
@@ -111,8 +111,8 @@ restart_member_scan:
 			}
 			picked[k++] = a;
 
-			if (queryingPeer.toInt() != a) { // do not return the peer that is making the request as a result
-				p = (unsigned char *)appendTo.appendField(ZT_ADDRESS_LENGTH);
+			if (queryingPeer.toInt() != a) {   // do not return the peer that is making the request as a result
+				p = (unsigned char*)appendTo.appendField(ZT_ADDRESS_LENGTH);
 				*(p++) = (unsigned char)((a >> 32) & 0xff);
 				*(p++) = (unsigned char)((a >> 24) & 0xff);
 				*(p++) = (unsigned char)((a >> 16) & 0xff);
@@ -123,21 +123,21 @@ restart_member_scan:
 		}
 	}
 
-	appendTo.setAt(totalAt,(uint32_t)totalKnown);
-	appendTo.setAt(addedAt,(uint16_t)added);
+	appendTo.setAt(totalAt, (uint32_t)totalKnown);
+	appendTo.setAt(addedAt, (uint16_t)added);
 
 	return added;
 }
 
-std::vector<Address> Multicaster::getMembers(uint64_t nwid,const MulticastGroup &mg,unsigned int limit) const
+std::vector<Address> Multicaster::getMembers(uint64_t nwid, const MulticastGroup& mg, unsigned int limit) const
 {
 	std::vector<Address> ls;
 	Mutex::Lock _l(_groups_m);
-	const MulticastGroupStatus *s = _groups.get(Multicaster::Key(nwid,mg));
-	if (!s) {
+	const MulticastGroupStatus* s = _groups.get(Multicaster::Key(nwid, mg));
+	if (! s) {
 		return ls;
 	}
-	for(std::vector<MulticastGroupMember>::const_reverse_iterator m(s->members.rbegin());m!=s->members.rend();++m) {
+	for (std::vector<MulticastGroupMember>::const_reverse_iterator m(s->members.rbegin()); m != s->members.rend(); ++m) {
 		ls.push_back(m->address);
 		if (ls.size() >= limit) {
 			break;
@@ -146,19 +146,10 @@ std::vector<Address> Multicaster::getMembers(uint64_t nwid,const MulticastGroup
 	return ls;
 }
 
-void Multicaster::send(
-	void *tPtr,
-	int64_t now,
-	const SharedPtr<Network> &network,
-	const Address &origin,
-	const MulticastGroup &mg,
-	const MAC &src,
-	unsigned int etherType,
-	const void *data,
-	unsigned int len)
+void Multicaster::send(void* tPtr, int64_t now, const SharedPtr<Network>& network, const Address& origin, const MulticastGroup& mg, const MAC& src, unsigned int etherType, const void* data, unsigned int len)
 {
 	unsigned long idxbuf[4096];
-	unsigned long *indexes = idxbuf;
+	unsigned long* indexes = idxbuf;
 
 	// If we're in hub-and-spoke designated multicast replication mode, see if we
 	// have a multicast replicator active. If so, pick the best and send it
@@ -168,19 +159,19 @@ void Multicaster::send(
 	// the current protocol and could be fixed, but fixing it would add more
 	// complexity than the fix is probably worth. Bridges are generally high
 	// bandwidth nodes.
-	if (!network->config().isActiveBridge(RR->identity.address())) {
+	if (! network->config().isActiveBridge(RR->identity.address())) {
 		Address multicastReplicators[ZT_MAX_NETWORK_SPECIALISTS];
 		const unsigned int multicastReplicatorCount = network->config().multicastReplicators(multicastReplicators);
 		if (multicastReplicatorCount) {
-			if (std::find(multicastReplicators,multicastReplicators + multicastReplicatorCount,RR->identity.address()) == (multicastReplicators + multicastReplicatorCount)) {
+			if (std::find(multicastReplicators, multicastReplicators + multicastReplicatorCount, RR->identity.address()) == (multicastReplicators + multicastReplicatorCount)) {
 				SharedPtr<Peer> bestMulticastReplicator;
 				SharedPtr<Path> bestMulticastReplicatorPath;
 				unsigned int bestMulticastReplicatorLatency = 0xffff;
-				for(unsigned int i=0;i<multicastReplicatorCount;++i) {
+				for (unsigned int i = 0; i < multicastReplicatorCount; ++i) {
 					const SharedPtr<Peer> p(RR->topology->getPeerNoCache(multicastReplicators[i]));
-					if ((p)&&(p->isAlive(now))) {
-						const SharedPtr<Path> pp(p->getAppropriatePath(now,false));
-						if ((pp)&&(pp->latency() < bestMulticastReplicatorLatency)) {
+					if ((p) && (p->isAlive(now))) {
+						const SharedPtr<Path> pp(p->getAppropriatePath(now, false));
+						if ((pp) && (pp->latency() < bestMulticastReplicatorLatency)) {
 							bestMulticastReplicatorLatency = pp->latency();
 							bestMulticastReplicatorPath = pp;
 							bestMulticastReplicator = p;
@@ -188,20 +179,20 @@ void Multicaster::send(
 					}
 				}
 				if (bestMulticastReplicator) {
-					Packet outp(bestMulticastReplicator->address(),RR->identity.address(),Packet::VERB_MULTICAST_FRAME);
+					Packet outp(bestMulticastReplicator->address(), RR->identity.address(), Packet::VERB_MULTICAST_FRAME);
 					outp.append((uint64_t)network->id());
-					outp.append((uint8_t)0x0c); // includes source MAC | please replicate
-					((src) ? src : MAC(RR->identity.address(),network->id())).appendTo(outp);
+					outp.append((uint8_t)0x0c);	  // includes source MAC | please replicate
+					((src) ? src : MAC(RR->identity.address(), network->id())).appendTo(outp);
 					mg.mac().appendTo(outp);
 					outp.append((uint32_t)mg.adi());
 					outp.append((uint16_t)etherType);
-					outp.append(data,len);
-					if (!network->config().disableCompression()) {
+					outp.append(data, len);
+					if (! network->config().disableCompression()) {
 						outp.compress();
 					}
-					outp.armor(bestMulticastReplicator->key(),true,bestMulticastReplicator->aesKeysIfSupported());
+					outp.armor(bestMulticastReplicator->key(), true, bestMulticastReplicator->aesKeysIfSupported());
 					Metrics::pkt_multicast_frame_out++;
-					bestMulticastReplicatorPath->send(RR,tPtr,outp.data(),outp.size(),now);
+					bestMulticastReplicatorPath->send(RR, tPtr, outp.data(), outp.size(), now);
 					return;
 				}
 			}
@@ -210,19 +201,19 @@ void Multicaster::send(
 
 	try {
 		Mutex::Lock _l(_groups_m);
-		MulticastGroupStatus &gs = _groups[Multicaster::Key(network->id(),mg)];
+		MulticastGroupStatus& gs = _groups[Multicaster::Key(network->id(), mg)];
 
-		if (!gs.members.empty()) {
+		if (! gs.members.empty()) {
 			// Allocate a memory buffer if group is monstrous
 			if (gs.members.size() > (sizeof(idxbuf) / sizeof(unsigned long))) {
 				indexes = new unsigned long[gs.members.size()];
 			}
 
 			// Generate a random permutation of member indexes
-			for(unsigned long i=0;i<gs.members.size();++i) {
+			for (unsigned long i = 0; i < gs.members.size(); ++i) {
 				indexes[i] = i;
 			}
-			for(unsigned long i=(unsigned long)gs.members.size()-1;i>0;--i) {
+			for (unsigned long i = (unsigned long)gs.members.size() - 1; i > 0; --i) {
 				unsigned long j = (unsigned long)RR->node->prng() % (i + 1);
 				unsigned long tmp = indexes[j];
 				indexes[j] = indexes[i];
@@ -244,7 +235,7 @@ void Multicaster::send(
 				network->id(),
 				network->config().disableCompression(),
 				limit,
-				1, // we'll still gather a little from peers to keep multicast list fresh
+				1,	 // we'll still gather a little from peers to keep multicast list fresh
 				src,
 				mg,
 				etherType,
@@ -253,9 +244,9 @@ void Multicaster::send(
 
 			unsigned int count = 0;
 
-			for(unsigned int i=0;i<activeBridgeCount;++i) {
-				if ((activeBridges[i] != RR->identity.address())&&(activeBridges[i] != origin)) {
-					out.sendOnly(RR,tPtr,activeBridges[i]); // optimization: don't use dedup log if it's a one-pass send
+			for (unsigned int i = 0; i < activeBridgeCount; ++i) {
+				if ((activeBridges[i] != RR->identity.address()) && (activeBridges[i] != origin)) {
+					out.sendOnly(RR, tPtr, activeBridges[i]);	// optimization: don't use dedup log if it's a one-pass send
 					if (++count >= limit) {
 						break;
 					}
@@ -263,14 +254,15 @@ void Multicaster::send(
 			}
 
 			unsigned long idx = 0;
-			while ((count < limit)&&(idx < gs.members.size())) {
+			while ((count < limit) && (idx < gs.members.size())) {
 				const Address ma(gs.members[indexes[idx++]].address);
-				if ((std::find(activeBridges,activeBridges + activeBridgeCount,ma) == (activeBridges + activeBridgeCount))&&(ma != origin)) {
-					out.sendOnly(RR,tPtr,ma); // optimization: don't use dedup log if it's a one-pass send
+				if ((std::find(activeBridges, activeBridges + activeBridgeCount, ma) == (activeBridges + activeBridgeCount)) && (ma != origin)) {
+					out.sendOnly(RR, tPtr, ma);	  // optimization: don't use dedup log if it's a one-pass send
 					++count;
 				}
 			}
-		} else {
+		}
+		else {
 			while (gs.txQueue.size() >= ZT_TX_QUEUE_SIZE) {
 				gs.txQueue.pop_front();
 			}
@@ -278,7 +270,7 @@ void Multicaster::send(
 			const unsigned int gatherLimit = (limit - (unsigned int)gs.members.size()) + 1;
 
 			int timerScale = RR->node->lowBandwidthModeEnabled() ? 3 : 1;
-			if ((gs.members.empty())||((now - gs.lastExplicitGather) >= (ZT_MULTICAST_EXPLICIT_GATHER_DELAY * timerScale))) {
+			if ((gs.members.empty()) || ((now - gs.lastExplicitGather) >= (ZT_MULTICAST_EXPLICIT_GATHER_DELAY * timerScale))) {
 				gs.lastExplicitGather = now;
 
 				Address explicitGatherPeers[16];
@@ -294,10 +286,10 @@ void Multicaster::send(
 				Address ac[ZT_MAX_NETWORK_SPECIALISTS];
 				const unsigned int accnt = network->config().alwaysContactAddresses(ac);
 				unsigned int shuffled[ZT_MAX_NETWORK_SPECIALISTS];
-				for(unsigned int i=0;i<accnt;++i) {
+				for (unsigned int i = 0; i < accnt; ++i) {
 					shuffled[i] = i;
 				}
-				for(unsigned int i=0,k=accnt>>1;i<k;++i) {
+				for (unsigned int i = 0, k = accnt >> 1; i < k; ++i) {
 					const uint64_t x = RR->node->prng();
 					const unsigned int x1 = shuffled[(unsigned int)x % accnt];
 					const unsigned int x2 = shuffled[(unsigned int)(x >> 32) % accnt];
@@ -305,7 +297,7 @@ void Multicaster::send(
 					shuffled[x1] = shuffled[x2];
 					shuffled[x2] = tmp;
 				}
-				for(unsigned int i=0;i<accnt;++i) {
+				for (unsigned int i = 0; i < accnt; ++i) {
 					explicitGatherPeers[numExplicitGatherPeers++] = ac[shuffled[i]];
 					if (numExplicitGatherPeers == 16) {
 						break;
@@ -313,7 +305,7 @@ void Multicaster::send(
 				}
 
 				std::vector<Address> anchors(network->config().anchors());
-				for(std::vector<Address>::const_iterator a(anchors.begin());a!=anchors.end();++a) {
+				for (std::vector<Address>::const_iterator a(anchors.begin()); a != anchors.end(); ++a) {
 					if (*a != RR->identity.address()) {
 						explicitGatherPeers[numExplicitGatherPeers++] = *a;
 						if (numExplicitGatherPeers == 16) {
@@ -322,9 +314,9 @@ void Multicaster::send(
 					}
 				}
 
-				for(unsigned int k=0;k<numExplicitGatherPeers;++k) {
-					const CertificateOfMembership *com = (network) ? ((network->config().com) ? &(network->config().com) : (const CertificateOfMembership *)0) : (const CertificateOfMembership *)0;
-					Packet outp(explicitGatherPeers[k],RR->identity.address(),Packet::VERB_MULTICAST_GATHER);
+				for (unsigned int k = 0; k < numExplicitGatherPeers; ++k) {
+					const CertificateOfMembership* com = (network) ? ((network->config().com) ? &(network->config().com) : (const CertificateOfMembership*)0) : (const CertificateOfMembership*)0;
+					Packet outp(explicitGatherPeers[k], RR->identity.address(), Packet::VERB_MULTICAST_GATHER);
 					outp.append(network->id());
 					outp.append((uint8_t)((com) ? 0x01 : 0x00));
 					mg.mac().appendTo(outp);
@@ -334,26 +326,15 @@ void Multicaster::send(
 						com->serialize(outp);
 					}
 					RR->node->expectReplyTo(outp.packetId());
-					RR->sw->send(tPtr,outp,true);
+					RR->sw->send(tPtr, outp, true);
 					Metrics::pkt_multicast_gather_out++;
 				}
 			}
 
 			gs.txQueue.push_back(OutboundMulticast());
-			OutboundMulticast &out = gs.txQueue.back();
+			OutboundMulticast& out = gs.txQueue.back();
 
-			out.init(
-				RR,
-				now,
-				network->id(),
-				network->config().disableCompression(),
-				limit,
-				gatherLimit,
-				src,
-				mg,
-				etherType,
-				data,
-				len);
+			out.init(RR, now, network->id(), network->config().disableCompression(), limit, gatherLimit, src, mg, etherType, data, len);
 
 			if (origin) {
 				out.logAsSent(origin);
@@ -361,9 +342,9 @@ void Multicaster::send(
 
 			unsigned int count = 0;
 
-			for(unsigned int i=0;i<activeBridgeCount;++i) {
+			for (unsigned int i = 0; i < activeBridgeCount; ++i) {
 				if (activeBridges[i] != RR->identity.address()) {
-					out.sendAndLog(RR,tPtr,activeBridges[i]);
+					out.sendAndLog(RR, tPtr, activeBridges[i]);
 					if (++count >= limit) {
 						break;
 					}
@@ -371,33 +352,36 @@ void Multicaster::send(
 			}
 
 			unsigned long idx = 0;
-			while ((count < limit)&&(idx < gs.members.size())) {
+			while ((count < limit) && (idx < gs.members.size())) {
 				Address ma(gs.members[indexes[idx++]].address);
-				if (std::find(activeBridges,activeBridges + activeBridgeCount,ma) == (activeBridges + activeBridgeCount)) {
-					out.sendAndLog(RR,tPtr,ma);
+				if (std::find(activeBridges, activeBridges + activeBridgeCount, ma) == (activeBridges + activeBridgeCount)) {
+					out.sendAndLog(RR, tPtr, ma);
 					++count;
 				}
 			}
 		}
-	} catch ( ... ) {} // this is a sanity check to catch any failures and make sure indexes[] still gets deleted
+	}
+	catch (...) {
+	}	// this is a sanity check to catch any failures and make sure indexes[] still gets deleted
 
 	// Free allocated memory buffer if any
 	if (indexes != idxbuf) {
-		delete [] indexes;
+		delete[] indexes;
 	}
 }
 
 void Multicaster::clean(int64_t now)
 {
 	Mutex::Lock _l(_groups_m);
-	Multicaster::Key *k = (Multicaster::Key *)0;
-	MulticastGroupStatus *s = (MulticastGroupStatus *)0;
-	Hashtable<Multicaster::Key,MulticastGroupStatus>::Iterator mm(_groups);
-	while (mm.next(k,s)) {
-		for(std::list<OutboundMulticast>::iterator tx(s->txQueue.begin());tx!=s->txQueue.end();) {
-			if ((tx->expired(now))||(tx->atLimit())) {
+	Multicaster::Key* k = (Multicaster::Key*)0;
+	MulticastGroupStatus* s = (MulticastGroupStatus*)0;
+	Hashtable<Multicaster::Key, MulticastGroupStatus>::Iterator mm(_groups);
+	while (mm.next(k, s)) {
+		for (std::list<OutboundMulticast>::iterator tx(s->txQueue.begin()); tx != s->txQueue.end();) {
+			if ((tx->expired(now)) || (tx->atLimit())) {
 				s->txQueue.erase(tx++);
-			} else {
+			}
+			else {
 				++tx;
 			}
 		}
@@ -418,15 +402,17 @@ void Multicaster::clean(int64_t now)
 
 		if (count) {
 			s->members.resize(count);
-		} else if (s->txQueue.empty()) {
+		}
+		else if (s->txQueue.empty()) {
 			_groups.erase(*k);
-		} else {
+		}
+		else {
 			s->members.clear();
 		}
 	}
 }
 
-void Multicaster::_add(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup &mg,MulticastGroupStatus &gs,const Address &member)
+void Multicaster::_add(void* tPtr, int64_t now, uint64_t nwid, const MulticastGroup& mg, MulticastGroupStatus& gs, const Address& member)
 {
 	// assumes _groups_m is locked
 
@@ -435,29 +421,32 @@ void Multicaster::_add(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup
 		return;
 	}
 
-	std::vector<MulticastGroupMember>::iterator m(std::lower_bound(gs.members.begin(),gs.members.end(),member));
+	std::vector<MulticastGroupMember>::iterator m(std::lower_bound(gs.members.begin(), gs.members.end(), member));
 	if (m != gs.members.end()) {
 		if (m->address == member) {
 			m->timestamp = now;
 			return;
 		}
-		gs.members.insert(m,MulticastGroupMember(member,now));
-	} else {
-		gs.members.push_back(MulticastGroupMember(member,now));
+		gs.members.insert(m, MulticastGroupMember(member, now));
+	}
+	else {
+		gs.members.push_back(MulticastGroupMember(member, now));
 	}
 
-	for(std::list<OutboundMulticast>::iterator tx(gs.txQueue.begin());tx!=gs.txQueue.end();) {
+	for (std::list<OutboundMulticast>::iterator tx(gs.txQueue.begin()); tx != gs.txQueue.end();) {
 		if (tx->atLimit()) {
 			gs.txQueue.erase(tx++);
-		} else {
-			tx->sendIfNew(RR,tPtr,member);
+		}
+		else {
+			tx->sendIfNew(RR, tPtr, member);
 			if (tx->atLimit()) {
 				gs.txQueue.erase(tx++);
-			} else {
+			}
+			else {
 				++tx;
 			}
 		}
 	}
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier

+ 82 - 59
node/Multicaster.hpp

@@ -14,22 +14,21 @@
 #ifndef ZT_MULTICASTER_HPP
 #define ZT_MULTICASTER_HPP
 
-#include <stdint.h>
-#include <string.h>
-
-#include <map>
-#include <vector>
-#include <list>
-
+#include "Address.hpp"
 #include "Constants.hpp"
 #include "Hashtable.hpp"
-#include "Address.hpp"
 #include "MAC.hpp"
 #include "MulticastGroup.hpp"
-#include "OutboundMulticast.hpp"
-#include "Utils.hpp"
 #include "Mutex.hpp"
+#include "OutboundMulticast.hpp"
 #include "SharedPtr.hpp"
+#include "Utils.hpp"
+
+#include <list>
+#include <map>
+#include <stdint.h>
+#include <string.h>
+#include <vector>
 
 namespace ZeroTier {
 
@@ -41,10 +40,9 @@ class Network;
 /**
  * Database of known multicast peers within a network
  */
-class Multicaster
-{
-public:
-	Multicaster(const RuntimeEnvironment *renv);
+class Multicaster {
+  public:
+	Multicaster(const RuntimeEnvironment* renv);
 	~Multicaster();
 
 	/**
@@ -55,10 +53,10 @@ public:
 	 * @param mg Multicast group
 	 * @param member New member address
 	 */
-	inline void add(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup &mg,const Address &member)
+	inline void add(void* tPtr, int64_t now, uint64_t nwid, const MulticastGroup& mg, const Address& member)
 	{
 		Mutex::Lock _l(_groups_m);
-		_add(tPtr,now,nwid,mg,_groups[Multicaster::Key(nwid,mg)],member);
+		_add(tPtr, now, nwid, mg, _groups[Multicaster::Key(nwid, mg)], member);
 	}
 
 	/**
@@ -74,7 +72,7 @@ public:
 	 * @param count Number of addresses
 	 * @param totalKnown Total number of known addresses as reported by peer
 	 */
-	void addMultiple(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup &mg,const void *addresses,unsigned int count,unsigned int totalKnown);
+	void addMultiple(void* tPtr, int64_t now, uint64_t nwid, const MulticastGroup& mg, const void* addresses, unsigned int count, unsigned int totalKnown);
 
 	/**
 	 * Remove a multicast group member (if present)
@@ -83,7 +81,7 @@ public:
 	 * @param mg Multicast group
 	 * @param member Member to unsubscribe
 	 */
-	void remove(uint64_t nwid,const MulticastGroup &mg,const Address &member);
+	void remove(uint64_t nwid, const MulticastGroup& mg, const Address& member);
 
 	/**
 	 * Append gather results to a packet by choosing registered multicast recipients at random
@@ -103,7 +101,7 @@ public:
 	 * @return Number of addresses appended
 	 * @throws std::out_of_range Buffer overflow writing to packet
 	 */
-	unsigned int gather(const Address &queryingPeer,uint64_t nwid,const MulticastGroup &mg,Buffer<ZT_PROTO_MAX_PACKET_LENGTH> &appendTo,unsigned int limit) const;
+	unsigned int gather(const Address& queryingPeer, uint64_t nwid, const MulticastGroup& mg, Buffer<ZT_PROTO_MAX_PACKET_LENGTH>& appendTo, unsigned int limit) const;
 
 	/**
 	 * Get subscribers to a multicast group
@@ -111,7 +109,7 @@ public:
 	 * @param nwid Network ID
 	 * @param mg Multicast group
 	 */
-	std::vector<Address> getMembers(uint64_t nwid,const MulticastGroup &mg,unsigned int limit) const;
+	std::vector<Address> getMembers(uint64_t nwid, const MulticastGroup& mg, unsigned int limit) const;
 
 	/**
 	 * Send a multicast
@@ -126,16 +124,7 @@ public:
 	 * @param data Packet data
 	 * @param len Length of packet data
 	 */
-	void send(
-		void *tPtr,
-		int64_t now,
-		const SharedPtr<Network> &network,
-		const Address &origin,
-		const MulticastGroup &mg,
-		const MAC &src,
-		unsigned int etherType,
-		const void *data,
-		unsigned int len);
+	void send(void* tPtr, int64_t now, const SharedPtr<Network>& network, const Address& origin, const MulticastGroup& mg, const MAC& src, unsigned int etherType, const void* data, unsigned int len);
 
 	/**
 	 * Clean database
@@ -145,53 +134,87 @@ public:
 	 */
 	void clean(int64_t now);
 
-private:
-	struct Key
-	{
-		Key() : nwid(0),mg() {}
-		Key(uint64_t n,const MulticastGroup &g) : nwid(n),mg(g) {}
+  private:
+	struct Key {
+		Key() : nwid(0), mg()
+		{
+		}
+		Key(uint64_t n, const MulticastGroup& g) : nwid(n), mg(g)
+		{
+		}
 
 		uint64_t nwid;
 		MulticastGroup mg;
 
-		inline bool operator==(const Key &k) const { return ((nwid == k.nwid)&&(mg == k.mg)); }
-		inline bool operator!=(const Key &k) const { return ((nwid != k.nwid)||(mg != k.mg)); }
-		inline unsigned long hashCode() const { return (mg.hashCode() ^ (unsigned long)(nwid ^ (nwid >> 32))); }
+		inline bool operator==(const Key& k) const
+		{
+			return ((nwid == k.nwid) && (mg == k.mg));
+		}
+		inline bool operator!=(const Key& k) const
+		{
+			return ((nwid != k.nwid) || (mg != k.mg));
+		}
+		inline unsigned long hashCode() const
+		{
+			return (mg.hashCode() ^ (unsigned long)(nwid ^ (nwid >> 32)));
+		}
 	};
 
-	struct MulticastGroupMember
-	{
-		MulticastGroupMember() {}
-		MulticastGroupMember(const Address &a,uint64_t ts) : address(a),timestamp(ts) {}
-
-		inline bool operator<(const MulticastGroupMember &a) const { return (address < a.address); }
-		inline bool operator==(const MulticastGroupMember &a) const { return (address == a.address); }
-		inline bool operator!=(const MulticastGroupMember &a) const { return (address != a.address); }
-		inline bool operator<(const Address &a) const { return (address < a); }
-		inline bool operator==(const Address &a) const { return (address == a); }
-		inline bool operator!=(const Address &a) const { return (address != a); }
+	struct MulticastGroupMember {
+		MulticastGroupMember()
+		{
+		}
+		MulticastGroupMember(const Address& a, uint64_t ts) : address(a), timestamp(ts)
+		{
+		}
+
+		inline bool operator<(const MulticastGroupMember& a) const
+		{
+			return (address < a.address);
+		}
+		inline bool operator==(const MulticastGroupMember& a) const
+		{
+			return (address == a.address);
+		}
+		inline bool operator!=(const MulticastGroupMember& a) const
+		{
+			return (address != a.address);
+		}
+		inline bool operator<(const Address& a) const
+		{
+			return (address < a);
+		}
+		inline bool operator==(const Address& a) const
+		{
+			return (address == a);
+		}
+		inline bool operator!=(const Address& a) const
+		{
+			return (address != a);
+		}
 
 		Address address;
-		int64_t timestamp; // time of last notification
+		int64_t timestamp;	 // time of last notification
 	};
 
-	struct MulticastGroupStatus
-	{
-		MulticastGroupStatus() : lastExplicitGather(0) {}
+	struct MulticastGroupStatus {
+		MulticastGroupStatus() : lastExplicitGather(0)
+		{
+		}
 
 		int64_t lastExplicitGather;
-		std::list<OutboundMulticast> txQueue; // pending outbound multicasts
-		std::vector<MulticastGroupMember> members; // members of this group
+		std::list<OutboundMulticast> txQueue;		 // pending outbound multicasts
+		std::vector<MulticastGroupMember> members;	 // members of this group
 	};
 
-	void _add(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup &mg,MulticastGroupStatus &gs,const Address &member);
+	void _add(void* tPtr, int64_t now, uint64_t nwid, const MulticastGroup& mg, MulticastGroupStatus& gs, const Address& member);
 
-	const RuntimeEnvironment *const RR;
+	const RuntimeEnvironment* const RR;
 
-	Hashtable<Multicaster::Key,MulticastGroupStatus> _groups;
+	Hashtable<Multicaster::Key, MulticastGroupStatus> _groups;
 	Mutex _groups_m;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 41 - 39
node/Mutex.hpp

@@ -18,19 +18,18 @@
 
 #ifdef __UNIX_LIKE__
 
+#include <pthread.h>
 #include <stdint.h>
 #include <stdlib.h>
-#include <pthread.h>
 
 namespace ZeroTier {
 
 // libpthread based mutex lock
-class Mutex
-{
-public:
+class Mutex {
+  public:
 	Mutex()
 	{
-		pthread_mutex_init(&_mh,(const pthread_mutexattr_t *)0);
+		pthread_mutex_init(&_mh, (const pthread_mutexattr_t*)0);
 	}
 
 	~Mutex()
@@ -40,25 +39,22 @@ public:
 
 	inline void lock() const
 	{
-		pthread_mutex_lock(&((const_cast <Mutex *> (this))->_mh));
+		pthread_mutex_lock(&((const_cast<Mutex*>(this))->_mh));
 	}
 
 	inline void unlock() const
 	{
-		pthread_mutex_unlock(&((const_cast <Mutex *> (this))->_mh));
+		pthread_mutex_unlock(&((const_cast<Mutex*>(this))->_mh));
 	}
 
-	class Lock
-	{
-	public:
-		Lock(Mutex &m) :
-			_m(&m)
+	class Lock {
+	  public:
+		Lock(Mutex& m) : _m(&m)
 		{
 			m.lock();
 		}
 
-		Lock(const Mutex &m) :
-			_m(const_cast<Mutex *>(&m))
+		Lock(const Mutex& m) : _m(const_cast<Mutex*>(&m))
 		{
 			_m->lock();
 		}
@@ -68,18 +64,23 @@ public:
 			_m->unlock();
 		}
 
-	private:
-		Mutex *const _m;
+	  private:
+		Mutex* const _m;
 	};
 
-private:
-	Mutex(const Mutex &) {}
-	const Mutex &operator=(const Mutex &) { return *this; }
+  private:
+	Mutex(const Mutex&)
+	{
+	}
+	const Mutex& operator=(const Mutex&)
+	{
+		return *this;
+	}
 
 	pthread_mutex_t _mh;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif
 
@@ -91,9 +92,8 @@ private:
 namespace ZeroTier {
 
 // Windows critical section based lock
-class Mutex
-{
-public:
+class Mutex {
+  public:
 	Mutex()
 	{
 		InitializeCriticalSection(&_cs);
@@ -116,25 +116,22 @@ public:
 
 	inline void lock() const
 	{
-		(const_cast <Mutex *> (this))->lock();
+		(const_cast<Mutex*>(this))->lock();
 	}
 
 	inline void unlock() const
 	{
-		(const_cast <Mutex *> (this))->unlock();
+		(const_cast<Mutex*>(this))->unlock();
 	}
 
-	class Lock
-	{
-	public:
-		Lock(Mutex &m) :
-			_m(&m)
+	class Lock {
+	  public:
+		Lock(Mutex& m) : _m(&m)
 		{
 			m.lock();
 		}
 
-		Lock(const Mutex &m) :
-			_m(const_cast<Mutex *>(&m))
+		Lock(const Mutex& m) : _m(const_cast<Mutex*>(&m))
 		{
 			_m->lock();
 		}
@@ -144,19 +141,24 @@ public:
 			_m->unlock();
 		}
 
-	private:
-		Mutex *const _m;
+	  private:
+		Mutex* const _m;
 	};
 
-private:
-	Mutex(const Mutex &) {}
-	const Mutex &operator=(const Mutex &) { return *this; }
+  private:
+	Mutex(const Mutex&)
+	{
+	}
+	const Mutex& operator=(const Mutex&)
+	{
+		return *this;
+	}
 
 	CRITICAL_SECTION _cs;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
-#endif // _WIN32
+#endif	 // _WIN32
 
 #endif

File diff suppressed because it is too large
+ 323 - 256
node/Network.cpp


+ 134 - 107
node/Network.hpp

@@ -14,33 +14,31 @@
 #ifndef ZT_NETWORK_HPP
 #define ZT_NETWORK_HPP
 
-#include <stdint.h>
-
 #include "../include/ZeroTierOne.h"
-
-#include <string>
-#include <map>
-#include <vector>
-#include <algorithm>
-#include <stdexcept>
-
-#include "Constants.hpp"
-#include "Hashtable.hpp"
 #include "Address.hpp"
-#include "Mutex.hpp"
-#include "SharedPtr.hpp"
 #include "AtomicCounter.hpp"
-#include "MulticastGroup.hpp"
-#include "MAC.hpp"
+#include "CertificateOfMembership.hpp"
+#include "Constants.hpp"
 #include "Dictionary.hpp"
-#include "Multicaster.hpp"
+#include "Hashtable.hpp"
+#include "MAC.hpp"
 #include "Membership.hpp"
-#include "NetworkConfig.hpp"
-#include "CertificateOfMembership.hpp"
 #include "Metrics.hpp"
+#include "MulticastGroup.hpp"
+#include "Multicaster.hpp"
+#include "Mutex.hpp"
+#include "NetworkConfig.hpp"
+#include "SharedPtr.hpp"
+
+#include <algorithm>
+#include <map>
+#include <stdexcept>
+#include <stdint.h>
+#include <string>
+#include <vector>
 
 #define ZT_NETWORK_MAX_INCOMING_UPDATES 3
-#define ZT_NETWORK_MAX_UPDATE_CHUNKS ((ZT_NETWORKCONFIG_DICT_CAPACITY / 1024) + 1)
+#define ZT_NETWORK_MAX_UPDATE_CHUNKS	((ZT_NETWORKCONFIG_DICT_CAPACITY / 1024) + 1)
 
 namespace ZeroTier {
 
@@ -50,11 +48,10 @@ class Peer;
 /**
  * A virtual LAN
  */
-class Network
-{
+class Network {
 	friend class SharedPtr<Network>;
 
-public:
+  public:
 	/**
 	 * Broadcast multicast group: ff:ff:ff:ff:ff:ff / 0
 	 */
@@ -63,7 +60,10 @@ public:
 	/**
 	 * Compute primary controller device ID from network ID
 	 */
-	static inline Address controllerFor(uint64_t nwid) { return Address(nwid >> 24); }
+	static inline Address controllerFor(uint64_t nwid)
+	{
+		return Address(nwid >> 24);
+	}
 
 	/**
 	 * Construct a new network
@@ -77,18 +77,43 @@ 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,void *uptr,const NetworkConfig *nconf);
+	Network(const RuntimeEnvironment* renv, void* tPtr, uint64_t nwid, void* uptr, const NetworkConfig* nconf);
 
 	~Network();
 
-	inline uint64_t id() const { return _id; }
-	inline Address controller() const { return Address(_id >> 24); }
-	inline bool multicastEnabled() const { return (_config.multicastLimit > 0); }
-	inline bool hasConfig() const { return (_config); }
-	inline uint64_t lastConfigUpdate() const { return _lastConfigUpdate; }
-	inline ZT_VirtualNetworkStatus status() const { Mutex::Lock _l(_lock); return _status(); }
-	inline const NetworkConfig &config() const { return _config; }
-	inline const MAC &mac() const { return _mac; }
+	inline uint64_t id() const
+	{
+		return _id;
+	}
+	inline Address controller() const
+	{
+		return Address(_id >> 24);
+	}
+	inline bool multicastEnabled() const
+	{
+		return (_config.multicastLimit > 0);
+	}
+	inline bool hasConfig() const
+	{
+		return (_config);
+	}
+	inline uint64_t lastConfigUpdate() const
+	{
+		return _lastConfigUpdate;
+	}
+	inline ZT_VirtualNetworkStatus status() const
+	{
+		Mutex::Lock _l(_lock);
+		return _status();
+	}
+	inline const NetworkConfig& config() const
+	{
+		return _config;
+	}
+	inline const MAC& mac() const
+	{
+		return _mac;
+	}
 
 	/**
 	 * Apply filters to an outgoing packet
@@ -111,17 +136,17 @@ public:
 	 * @return True if packet should be sent, false if dropped or redirected
 	 */
 	bool filterOutgoingPacket(
-		void *tPtr,
+		void* tPtr,
 		const bool noTee,
-		const Address &ztSource,
-		const Address &ztDest,
-		const MAC &macSource,
-		const MAC &macDest,
-		const uint8_t *frameData,
+		const Address& ztSource,
+		const Address& ztDest,
+		const MAC& macSource,
+		const MAC& macDest,
+		const uint8_t* frameData,
 		const unsigned int frameLen,
 		const unsigned int etherType,
 		const unsigned int vlanId,
-		uint8_t &qosBucket);
+		uint8_t& qosBucket);
 
 	/**
 	 * Apply filters to an incoming packet
@@ -143,12 +168,12 @@ public:
 	 * @return 0 == drop, 1 == accept, 2 == accept even if bridged
 	 */
 	int filterIncomingPacket(
-		void *tPtr,
-		const SharedPtr<Peer> &sourcePeer,
-		const Address &ztDest,
-		const MAC &macSource,
-		const MAC &macDest,
-		const uint8_t *frameData,
+		void* tPtr,
+		const SharedPtr<Peer>& sourcePeer,
+		const Address& ztDest,
+		const MAC& macSource,
+		const MAC& macDest,
+		const uint8_t* frameData,
 		const unsigned int frameLen,
 		const unsigned int etherType,
 		const unsigned int vlanId);
@@ -160,7 +185,7 @@ public:
 	 * @param includeBridgedGroups If true, also check groups we've learned via bridging
 	 * @return True if this network endpoint / peer is a member
 	 */
-	bool subscribedToMulticastGroup(const MulticastGroup &mg,bool includeBridgedGroups) const;
+	bool subscribedToMulticastGroup(const MulticastGroup& mg, bool includeBridgedGroups) const;
 
 	/**
 	 * Subscribe to a multicast group
@@ -168,14 +193,14 @@ 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
 	 *
 	 * @param mg Multicast group
 	 */
-	void multicastUnsubscribe(const MulticastGroup &mg);
+	void multicastUnsubscribe(const MulticastGroup& mg);
 
 	/**
 	 * Handle an inbound network config chunk
@@ -191,7 +216,7 @@ public:
 	 * @param ptr Index of chunk and related fields in packet
 	 * @return Update ID if update was fully assembled and accepted or 0 otherwise
 	 */
-	uint64_t handleConfigChunk(void *tPtr,const uint64_t packetId,const Address &source,const Buffer<ZT_PROTO_MAX_PACKET_LENGTH> &chunk,unsigned int ptr);
+	uint64_t handleConfigChunk(void* tPtr, const uint64_t packetId, const Address& source, const Buffer<ZT_PROTO_MAX_PACKET_LENGTH>& chunk, unsigned int ptr);
 
 	/**
 	 * Set network configuration
@@ -201,12 +226,12 @@ 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
 	 */
-	inline void setAccessDenied(void *tPtr)
+	inline void setAccessDenied(void* tPtr)
 	{
 		Mutex::Lock _l(_lock);
 		_netconfFailure = NETCONF_FAILURE_ACCESS_DENIED;
@@ -217,7 +242,7 @@ public:
 	/**
 	 * Set netconf failure to 'not found' -- called by IncomingPacket when controller reports this
 	 */
-	inline void setNotFound(void *tPtr)
+	inline void setNotFound(void* tPtr)
 	{
 		Mutex::Lock _l(_lock);
 		_netconfFailure = NETCONF_FAILURE_NOT_FOUND;
@@ -228,7 +253,7 @@ public:
 	/**
 	 * Set netconf failure to 'authentication required' possibly with an authorization URL
 	 */
-	inline void setAuthenticationRequired(void *tPtr, const char *url)
+	inline void setAuthenticationRequired(void* tPtr, const char* url)
 	{
 		Mutex::Lock _l(_lock);
 		_netconfFailure = NETCONF_FAILURE_AUTHENTICATION_REQUIRED;
@@ -242,14 +267,14 @@ public:
 	 * set netconf failure to 'authentication required' along with info needed
 	 * for sso full flow authentication.
 	 */
-	void setAuthenticationRequired(void *tPtr, const char* issuerURL, const char* centralEndpoint, const char* clientID, const char *ssoProvider, const char* nonce, const char* state);
+	void setAuthenticationRequired(void* tPtr, const char* issuerURL, const char* centralEndpoint, const char* clientID, const char* ssoProvider, const char* nonce, const char* state);
 
 	/**
 	 * Causes this network to request an updated configuration from its master node now
 	 *
 	 * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
 	 */
-	void requestConfiguration(void *tPtr);
+	void requestConfiguration(void* tPtr);
 
 	/**
 	 * Determine whether this peer is permitted to communicate on this network
@@ -257,7 +282,7 @@ 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);
+	bool gate(void* tPtr, const SharedPtr<Peer>& peer);
 
 	/**
 	 * Check whether a given peer has recently had an association with this network
@@ -270,7 +295,7 @@ public:
 	 * @param addr Peer address
 	 * @return True if peer has recently associated
 	 */
-	bool recentlyAssociatedWith(const Address &addr);
+	bool recentlyAssociatedWith(const Address& addr);
 
 	/**
 	 * Do periodic cleanup and housekeeping tasks
@@ -282,10 +307,10 @@ public:
 	 *
 	 * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
 	 */
-	inline void sendUpdatesToMembers(void *tPtr)
+	inline void sendUpdatesToMembers(void* tPtr)
 	{
 		Mutex::Lock _l(_lock);
-		_sendUpdatesToMembers(tPtr,(const MulticastGroup *)0);
+		_sendUpdatesToMembers(tPtr, (const MulticastGroup*)0);
 	}
 
 	/**
@@ -294,17 +319,20 @@ public:
 	 * @param mac MAC address
 	 * @return ZeroTier address of bridge to this MAC
 	 */
-	inline Address findBridgeTo(const MAC &mac) const
+	inline Address findBridgeTo(const MAC& mac) const
 	{
 		Mutex::Lock _l(_lock);
-		const Address *const br = _remoteBridgeRoutes.get(mac);
+		const Address* const br = _remoteBridgeRoutes.get(mac);
 		return ((br) ? *br : Address());
 	}
 
 	/**
 	 * @return True if QoS is in effect for this network
 	 */
-	inline bool qosEnabled() { return false; }
+	inline bool qosEnabled()
+	{
+		return false;
+	}
 
 	/**
 	 * Set a bridge route
@@ -312,7 +340,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
@@ -321,52 +349,52 @@ public:
 	 * @param mg Multicast group
 	 * @param now Current time
 	 */
-	void learnBridgedMulticastGroup(void *tPtr,const MulticastGroup &mg,int64_t now);
+	void learnBridgedMulticastGroup(void* tPtr, const MulticastGroup& mg, int64_t now);
 
 	/**
 	 * Validate a credential and learn it if it passes certificate and other checks
 	 */
-	Membership::AddCredentialResult addCredential(void *tPtr,const CertificateOfMembership &com);
+	Membership::AddCredentialResult addCredential(void* tPtr, const CertificateOfMembership& com);
 
 	/**
 	 * Validate a credential and learn it if it passes certificate and other checks
 	 */
-	inline Membership::AddCredentialResult addCredential(void *tPtr,const Capability &cap)
+	inline Membership::AddCredentialResult addCredential(void* tPtr, const Capability& cap)
 	{
 		if (cap.networkId() != _id) {
 			return Membership::ADD_REJECTED;
 		}
 		Mutex::Lock _l(_lock);
-		return _membership(cap.issuedTo()).addCredential(RR,tPtr,_config,cap);
+		return _membership(cap.issuedTo()).addCredential(RR, tPtr, _config, cap);
 	}
 
 	/**
 	 * Validate a credential and learn it if it passes certificate and other checks
 	 */
-	inline Membership::AddCredentialResult addCredential(void *tPtr,const Tag &tag)
+	inline Membership::AddCredentialResult addCredential(void* tPtr, const Tag& tag)
 	{
 		if (tag.networkId() != _id) {
 			return Membership::ADD_REJECTED;
 		}
 		Mutex::Lock _l(_lock);
-		return _membership(tag.issuedTo()).addCredential(RR,tPtr,_config,tag);
+		return _membership(tag.issuedTo()).addCredential(RR, tPtr, _config, tag);
 	}
 
 	/**
 	 * Validate a credential and learn it if it passes certificate and other checks
 	 */
-	Membership::AddCredentialResult addCredential(void *tPtr,const Address &sentFrom,const Revocation &rev);
+	Membership::AddCredentialResult addCredential(void* tPtr, const Address& sentFrom, const Revocation& rev);
 
 	/**
 	 * Validate a credential and learn it if it passes certificate and other checks
 	 */
-	inline Membership::AddCredentialResult addCredential(void *tPtr,const CertificateOfOwnership &coo)
+	inline Membership::AddCredentialResult addCredential(void* tPtr, const CertificateOfOwnership& coo)
 	{
 		if (coo.networkId() != _id) {
 			return Membership::ADD_REJECTED;
 		}
 		Mutex::Lock _l(_lock);
-		return _membership(coo.issuedTo()).addCredential(RR,tPtr,_config,coo);
+		return _membership(coo.issuedTo()).addCredential(RR, tPtr, _config, coo);
 	}
 
 	/**
@@ -376,13 +404,13 @@ public:
 	 * @param to Destination peer address
 	 * @param now Current time
 	 */
-	inline void peerRequestedCredentials(void *tPtr,const Address &to,const int64_t now)
+	inline void peerRequestedCredentials(void* tPtr, const Address& to, const int64_t now)
 	{
 		Mutex::Lock _l(_lock);
-		Membership &m = _membership(to);
+		Membership& m = _membership(to);
 		const int64_t lastPushed = m.lastPushedCredentials();
-		if ((lastPushed < _lastConfigUpdate)||((now - lastPushed) > ZT_PEER_CREDENTIALS_REQUEST_RATE_LIMIT)) {
-			m.pushCredentials(RR,tPtr,now,to,_config);
+		if ((lastPushed < _lastConfigUpdate) || ((now - lastPushed) > ZT_PEER_CREDENTIALS_REQUEST_RATE_LIMIT)) {
+			m.pushCredentials(RR, tPtr, now, to, _config);
 		}
 	}
 
@@ -393,13 +421,13 @@ public:
 	 * @param to Destination peer address
 	 * @param now Current time
 	 */
-	inline void pushCredentialsIfNeeded(void *tPtr,const Address &to,const int64_t now)
+	inline void pushCredentialsIfNeeded(void* tPtr, const Address& to, const int64_t now)
 	{
 		Mutex::Lock _l(_lock);
-		Membership &m = _membership(to);
+		Membership& m = _membership(to);
 		const int64_t lastPushed = m.lastPushedCredentials();
-		if ((lastPushed < _lastConfigUpdate)||((now - lastPushed) > ZT_PEER_ACTIVITY_TIMEOUT)) {
-			m.pushCredentials(RR,tPtr,now,to,_config);
+		if ((lastPushed < _lastConfigUpdate) || ((now - lastPushed) > ZT_PEER_ACTIVITY_TIMEOUT)) {
+			m.pushCredentials(RR, tPtr, now, to, _config);
 		}
 	}
 
@@ -416,7 +444,7 @@ public:
 	 *
 	 * @param ec Buffer to fill with externally-visible network configuration
 	 */
-	inline void externalConfig(ZT_VirtualNetworkConfig *ec) const
+	inline void externalConfig(ZT_VirtualNetworkConfig* ec) const
 	{
 		Mutex::Lock _l(_lock);
 		_externalConfig(ec);
@@ -425,36 +453,41 @@ public:
 	/**
 	 * @return Externally usable pointer-to-pointer exported via the core API
 	 */
-	inline void **userPtr() { return &_uPtr; }
+	inline void** userPtr()
+	{
+		return &_uPtr;
+	}
 
-private:
+  private:
 	ZT_VirtualNetworkStatus _status() const;
-	void _externalConfig(ZT_VirtualNetworkConfig *ec) const; // assumes _lock is locked
-	bool _gate(const SharedPtr<Peer> &peer);
-	void _sendUpdatesToMembers(void *tPtr,const MulticastGroup *const newMulticastGroup);
-	void _announceMulticastGroupsTo(void *tPtr,const Address &peer,const std::vector<MulticastGroup> &allMulticastGroups);
+	void _externalConfig(ZT_VirtualNetworkConfig* ec) const;   // assumes _lock is locked
+	bool _gate(const SharedPtr<Peer>& peer);
+	void _sendUpdatesToMembers(void* tPtr, const MulticastGroup* const newMulticastGroup);
+	void _announceMulticastGroupsTo(void* tPtr, const Address& peer, const std::vector<MulticastGroup>& allMulticastGroups);
 	std::vector<MulticastGroup> _allMulticastGroups() const;
-	Membership &_membership(const Address &a);
-	void _sendUpdateEvent(void *tPtr);
+	Membership& _membership(const Address& a);
+	void _sendUpdateEvent(void* tPtr);
 
-	const RuntimeEnvironment *const RR;
-	void *_uPtr;
+	const RuntimeEnvironment* const RR;
+	void* _uPtr;
 	const uint64_t _id;
 	std::string _nwidStr;
 	uint64_t _lastAnnouncedMulticastGroupsUpstream;
-	MAC _mac; // local MAC address
+	MAC _mac;	// local MAC address
 	bool _portInitialized;
 
-	std::vector< MulticastGroup > _myMulticastGroups; // multicast groups that we belong to (according to tap)
-	Hashtable< MulticastGroup,uint64_t > _multicastGroupsBehindMe; // multicast groups that seem to be behind us and when we last saw them (if we are a bridge)
-	Hashtable< MAC,Address > _remoteBridgeRoutes; // remote addresses where given MACs are reachable (for tracking devices behind remote bridges)
+	std::vector<MulticastGroup> _myMulticastGroups;					// multicast groups that we belong to (according to tap)
+	Hashtable<MulticastGroup, uint64_t> _multicastGroupsBehindMe;	// multicast groups that seem to be behind us and when we last saw them (if we are a bridge)
+	Hashtable<MAC, Address> _remoteBridgeRoutes;					// remote addresses where given MACs are reachable (for tracking devices behind remote bridges)
 
 	NetworkConfig _config;
 	int64_t _lastConfigUpdate;
 
-	struct _IncomingConfigChunk
-	{
-		_IncomingConfigChunk() { memset(this,0,sizeof(_IncomingConfigChunk)); }
+	struct _IncomingConfigChunk {
+		_IncomingConfigChunk()
+		{
+			memset(this, 0, sizeof(_IncomingConfigChunk));
+		}
 		uint64_t ts;
 		uint64_t updateId;
 		uint64_t haveChunkIds[ZT_NETWORK_MAX_UPDATE_CHUNKS];
@@ -466,17 +499,11 @@ private:
 
 	bool _destroyed;
 
-	enum {
-		NETCONF_FAILURE_NONE,
-		NETCONF_FAILURE_ACCESS_DENIED,
-		NETCONF_FAILURE_NOT_FOUND,
-		NETCONF_FAILURE_INIT_FAILED,
-		NETCONF_FAILURE_AUTHENTICATION_REQUIRED
-	} _netconfFailure;
-	int _portError; // return value from port config callback
+	enum { NETCONF_FAILURE_NONE, NETCONF_FAILURE_ACCESS_DENIED, NETCONF_FAILURE_NOT_FOUND, NETCONF_FAILURE_INIT_FAILED, NETCONF_FAILURE_AUTHENTICATION_REQUIRED } _netconfFailure;
+	int _portError;	  // return value from port config callback
 	std::string _authenticationURL;
 
-	Hashtable<Address,Membership> _memberships;
+	Hashtable<Address, Membership> _memberships;
 
 	Mutex _lock;
 

+ 161 - 145
node/NetworkConfig.cpp

@@ -11,88 +11,87 @@
  */
 /****/
 
-#include <stdint.h>
+#include "NetworkConfig.hpp"
 
 #include <algorithm>
-
-#include "NetworkConfig.hpp"
+#include <stdint.h>
 
 namespace ZeroTier {
 
-bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,bool includeLegacy) const
+bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>& d, bool includeLegacy) const
 {
-	Buffer<ZT_NETWORKCONFIG_DICT_CAPACITY> *tmp = new Buffer<ZT_NETWORKCONFIG_DICT_CAPACITY>();
-	char tmp2[128] = {0};
+	Buffer<ZT_NETWORKCONFIG_DICT_CAPACITY>* tmp = new Buffer<ZT_NETWORKCONFIG_DICT_CAPACITY>();
+	char tmp2[128] = { 0 };
 
 	try {
 		d.clear();
 
 		// Try to put the more human-readable fields first
 
-		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_VERSION,(uint64_t)ZT_NETWORKCONFIG_VERSION)) {
+		if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_VERSION, (uint64_t)ZT_NETWORKCONFIG_VERSION)) {
 			delete tmp;
 			return false;
 		}
-		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID,this->networkId)) {
+		if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID, this->networkId)) {
 			delete tmp;
 			return false;
 		}
-		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP,this->timestamp)) {
+		if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP, this->timestamp)) {
 			delete tmp;
 			return false;
 		}
-		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CREDENTIAL_TIME_MAX_DELTA,this->credentialTimeMaxDelta)) {
+		if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_CREDENTIAL_TIME_MAX_DELTA, this->credentialTimeMaxDelta)) {
 			delete tmp;
 			return false;
 		}
-		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_REVISION,this->revision)) {
+		if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_REVISION, this->revision)) {
 			delete tmp;
 			return false;
 		}
-		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO,this->issuedTo.toString(tmp2))) {
+		if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO, this->issuedTo.toString(tmp2))) {
 			delete tmp;
 			return false;
 		}
-		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_REMOTE_TRACE_TARGET,this->remoteTraceTarget.toString(tmp2))) {
+		if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_REMOTE_TRACE_TARGET, this->remoteTraceTarget.toString(tmp2))) {
 			delete tmp;
 			return false;
 		}
-		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_REMOTE_TRACE_LEVEL,(uint64_t)this->remoteTraceLevel)) {
+		if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_REMOTE_TRACE_LEVEL, (uint64_t)this->remoteTraceLevel)) {
 			delete tmp;
 			return false;
 		}
-		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_FLAGS,this->flags)) {
+		if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_FLAGS, this->flags)) {
 			delete tmp;
 			return false;
 		}
-		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT,(uint64_t)this->multicastLimit)) {
+		if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT, (uint64_t)this->multicastLimit)) {
 			delete tmp;
 			return false;
 		}
-		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_TYPE,(uint64_t)this->type)) {
+		if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_TYPE, (uint64_t)this->type)) {
 			delete tmp;
 			return false;
 		}
-		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_NAME,this->name)) {
+		if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_NAME, this->name)) {
 			delete tmp;
 			return false;
 		}
-		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_MTU,(uint64_t)this->mtu)) {
+		if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_MTU, (uint64_t)this->mtu)) {
 			delete tmp;
 			return false;
 		}
 
 #ifdef ZT_SUPPORT_OLD_STYLE_NETCONF
 		if (includeLegacy) {
-			if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST_OLD,this->enableBroadcast())) {
+			if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST_OLD, this->enableBroadcast())) {
 				return false;
 			}
-			if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_PRIVATE_OLD,this->isPrivate())) {
+			if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_PRIVATE_OLD, this->isPrivate())) {
 				return false;
 			}
 
 			std::string v4s;
-			for(unsigned int i=0;i<staticIpCount;++i) {
+			for (unsigned int i = 0; i < staticIpCount; ++i) {
 				if (this->staticIps[i].ss_family == AF_INET) {
 					if (v4s.length() > 0) {
 						v4s.push_back(',');
@@ -102,12 +101,12 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
 				}
 			}
 			if (v4s.length() > 0) {
-				if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC_OLD,v4s.c_str())) {
+				if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC_OLD, v4s.c_str())) {
 					return false;
 				}
 			}
 			std::string v6s;
-			for(unsigned int i=0;i<staticIpCount;++i) {
+			for (unsigned int i = 0; i < staticIpCount; ++i) {
 				if (this->staticIps[i].ss_family == AF_INET6) {
 					if (v6s.length() > 0) {
 						v6s.push_back(',');
@@ -117,7 +116,7 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
 				}
 			}
 			if (v6s.length() > 0) {
-				if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC_OLD,v6s.c_str())) {
+				if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC_OLD, v6s.c_str())) {
 					return false;
 				}
 			}
@@ -125,130 +124,131 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
 			std::string ets;
 			unsigned int et = 0;
 			ZT_VirtualNetworkRuleType lastrt = ZT_NETWORK_RULE_ACTION_ACCEPT;
-			for(unsigned int i=0;i<ruleCount;++i) {
+			for (unsigned int i = 0; i < ruleCount; ++i) {
 				ZT_VirtualNetworkRuleType rt = (ZT_VirtualNetworkRuleType)(rules[i].t & 0x7f);
 				if (rt == ZT_NETWORK_RULE_MATCH_ETHERTYPE) {
 					et = rules[i].v.etherType;
-				} else if (rt == ZT_NETWORK_RULE_ACTION_ACCEPT) {
-					if (((int)lastrt < 32)||(lastrt == ZT_NETWORK_RULE_MATCH_ETHERTYPE)) {
+				}
+				else if (rt == ZT_NETWORK_RULE_ACTION_ACCEPT) {
+					if (((int)lastrt < 32) || (lastrt == ZT_NETWORK_RULE_MATCH_ETHERTYPE)) {
 						if (ets.length() > 0) {
 							ets.push_back(',');
 						}
-						char tmp2[16] = {0};
-						ets.append(Utils::hex((uint16_t)et,tmp2));
+						char tmp2[16] = { 0 };
+						ets.append(Utils::hex((uint16_t)et, tmp2));
 					}
 					et = 0;
 				}
 				lastrt = rt;
 			}
 			if (ets.length() > 0) {
-				if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES_OLD,ets.c_str())) {
+				if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES_OLD, ets.c_str())) {
 					return false;
 				}
 			}
 
 			if (this->com) {
-				if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP_OLD,this->com.toString().c_str())) {
+				if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP_OLD, this->com.toString().c_str())) {
 					return false;
 				}
 			}
 
 			std::string ab;
-			for(unsigned int i=0;i<this->specialistCount;++i) {
+			for (unsigned int i = 0; i < this->specialistCount; ++i) {
 				if ((this->specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0) {
 					if (ab.length() > 0) {
 						ab.push_back(',');
 					}
-					char tmp2[16] = {0};
+					char tmp2[16] = { 0 };
 					ab.append(Address(this->specialists[i]).toString(tmp2));
 				}
 			}
 			if (ab.length() > 0) {
-				if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES_OLD,ab.c_str())) {
+				if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES_OLD, ab.c_str())) {
 					return false;
 				}
 			}
 		}
-#endif // ZT_SUPPORT_OLD_STYLE_NETCONF
+#endif	 // ZT_SUPPORT_OLD_STYLE_NETCONF
 
 		// Then add binary blobs
 
 		if (this->com) {
 			tmp->clear();
 			this->com.serialize(*tmp);
-			if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_COM,*tmp)) {
+			if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_COM, *tmp)) {
 				return false;
 			}
 		}
 
 		tmp->clear();
-		for(unsigned int i=0;i<this->capabilityCount;++i) {
+		for (unsigned int i = 0; i < this->capabilityCount; ++i) {
 			this->capabilities[i].serialize(*tmp);
 		}
 		if (tmp->size()) {
-			if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CAPABILITIES,*tmp)) {
+			if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_CAPABILITIES, *tmp)) {
 				return false;
 			}
 		}
 
 		tmp->clear();
-		for(unsigned int i=0;i<this->tagCount;++i) {
+		for (unsigned int i = 0; i < this->tagCount; ++i) {
 			this->tags[i].serialize(*tmp);
 		}
 		if (tmp->size()) {
-			if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_TAGS,*tmp)) {
+			if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_TAGS, *tmp)) {
 				return false;
 			}
 		}
 
 		tmp->clear();
-		for(unsigned int i=0;i<this->certificateOfOwnershipCount;++i) {
+		for (unsigned int i = 0; i < this->certificateOfOwnershipCount; ++i) {
 			this->certificatesOfOwnership[i].serialize(*tmp);
 		}
 		if (tmp->size()) {
-			if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATES_OF_OWNERSHIP,*tmp)) {
+			if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATES_OF_OWNERSHIP, *tmp)) {
 				return false;
 			}
 		}
 
 		tmp->clear();
-		for(unsigned int i=0;i<this->specialistCount;++i) {
+		for (unsigned int i = 0; i < this->specialistCount; ++i) {
 			tmp->append((uint64_t)this->specialists[i]);
 		}
 		if (tmp->size()) {
-			if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_SPECIALISTS,*tmp)) {
+			if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_SPECIALISTS, *tmp)) {
 				return false;
 			}
 		}
 
 		tmp->clear();
-		for(unsigned int i=0;i<this->routeCount;++i) {
-			reinterpret_cast<const InetAddress *>(&(this->routes[i].target))->serialize(*tmp);
-			reinterpret_cast<const InetAddress *>(&(this->routes[i].via))->serialize(*tmp);
+		for (unsigned int i = 0; i < this->routeCount; ++i) {
+			reinterpret_cast<const InetAddress*>(&(this->routes[i].target))->serialize(*tmp);
+			reinterpret_cast<const InetAddress*>(&(this->routes[i].via))->serialize(*tmp);
 			tmp->append((uint16_t)this->routes[i].flags);
 			tmp->append((uint16_t)this->routes[i].metric);
 		}
 		if (tmp->size()) {
-			if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ROUTES,*tmp)) {
+			if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_ROUTES, *tmp)) {
 				return false;
 			}
 		}
 
 		tmp->clear();
-		for(unsigned int i=0;i<this->staticIpCount;++i) {
+		for (unsigned int i = 0; i < this->staticIpCount; ++i) {
 			this->staticIps[i].serialize(*tmp);
 		}
 		if (tmp->size()) {
-			if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_STATIC_IPS,*tmp)) {
+			if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_STATIC_IPS, *tmp)) {
 				return false;
 			}
 		}
 
 		if (this->ruleCount) {
 			tmp->clear();
-			Capability::serializeRules(*tmp,rules,ruleCount);
+			Capability::serializeRules(*tmp, rules, ruleCount);
 			if (tmp->size()) {
-				if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_RULES,*tmp)) {
+				if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_RULES, *tmp)) {
 					return false;
 				}
 			}
@@ -257,59 +257,61 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
 		tmp->clear();
 		DNS::serializeDNS(*tmp, &dns);
 		if (tmp->size()) {
-			if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_DNS,*tmp)) {
+			if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_DNS, *tmp)) {
 				return false;
 			}
 		}
 
 		if (this->ssoVersion == 0) {
-			if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_SSO_VERSION, this->ssoVersion)) {
+			if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_SSO_VERSION, this->ssoVersion)) {
 				return false;
 			}
-			if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_SSO_ENABLED, this->ssoEnabled)) {
+			if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_SSO_ENABLED, this->ssoEnabled)) {
 				return false;
 			}
 
 			if (this->ssoEnabled) {
 				if (this->authenticationURL[0]) {
-					if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_AUTHENTICATION_URL, this->authenticationURL)) {
+					if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_AUTHENTICATION_URL, this->authenticationURL)) {
 						return false;
 					}
 				}
-				if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_AUTHENTICATION_EXPIRY_TIME, this->authenticationExpiryTime)) {
+				if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_AUTHENTICATION_EXPIRY_TIME, this->authenticationExpiryTime)) {
 					return false;
 				}
 			}
-		} else if(this->ssoVersion == 1) {
-			if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_SSO_VERSION, this->ssoVersion)) {
+		}
+		else if (this->ssoVersion == 1) {
+			if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_SSO_VERSION, this->ssoVersion)) {
 				return false;
 			}
-			if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_SSO_ENABLED, this->ssoEnabled)) {
+			if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_SSO_ENABLED, this->ssoEnabled)) {
 				return false;
 			}
-			//if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_AUTHENTICATION_URL, this->authenticationURL)) return false;
-			if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ISSUER_URL, this->issuerURL)) {
+			// if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_AUTHENTICATION_URL, this->authenticationURL)) return false;
+			if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_ISSUER_URL, this->issuerURL)) {
 				return false;
 			}
-			if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CENTRAL_ENDPOINT_URL, this->centralAuthURL)) {
+			if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_CENTRAL_ENDPOINT_URL, this->centralAuthURL)) {
 				return false;
 			}
-			if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_NONCE, this->ssoNonce)) {
+			if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_NONCE, this->ssoNonce)) {
 				return false;
 			}
-			if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_STATE, this->ssoState)) {
+			if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_STATE, this->ssoState)) {
 				return false;
 			}
-			if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CLIENT_ID, this->ssoClientID)) {
+			if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_CLIENT_ID, this->ssoClientID)) {
 				return false;
 			}
-			if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_SSO_PROVIDER, this->ssoProvider)) {
+			if (! d.add(ZT_NETWORKCONFIG_DICT_KEY_SSO_PROVIDER, this->ssoProvider)) {
 				return false;
 			}
 		}
 
 		delete tmp;
-	} catch ( ... ) {
+	}
+	catch (...) {
 		delete tmp;
 		throw;
 	}
@@ -317,83 +319,84 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
 	return true;
 }
 
-bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d)
+bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>& d)
 {
 	static const NetworkConfig NIL_NC;
-	Buffer<ZT_NETWORKCONFIG_DICT_CAPACITY> *tmp = new Buffer<ZT_NETWORKCONFIG_DICT_CAPACITY>();
+	Buffer<ZT_NETWORKCONFIG_DICT_CAPACITY>* tmp = new Buffer<ZT_NETWORKCONFIG_DICT_CAPACITY>();
 
 	try {
 		*this = NIL_NC;
 
 		// Fields that are always present, new or old
-		this->networkId = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID,0);
-		if (!this->networkId) {
+		this->networkId = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID, 0);
+		if (! this->networkId) {
 			delete tmp;
 			return false;
 		}
-		this->timestamp = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP,0);
-		this->credentialTimeMaxDelta = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_CREDENTIAL_TIME_MAX_DELTA,0);
-		this->revision = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_REVISION,0);
-		this->issuedTo = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO,0);
-		if (!this->issuedTo) {
+		this->timestamp = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP, 0);
+		this->credentialTimeMaxDelta = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_CREDENTIAL_TIME_MAX_DELTA, 0);
+		this->revision = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_REVISION, 0);
+		this->issuedTo = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO, 0);
+		if (! this->issuedTo) {
 			delete tmp;
 			return false;
 		}
 		this->remoteTraceTarget = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_REMOTE_TRACE_TARGET);
 		this->remoteTraceLevel = (Trace::Level)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_REMOTE_TRACE_LEVEL);
-		this->multicastLimit = (unsigned int)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT,0);
-		d.get(ZT_NETWORKCONFIG_DICT_KEY_NAME,this->name,sizeof(this->name));
+		this->multicastLimit = (unsigned int)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT, 0);
+		d.get(ZT_NETWORKCONFIG_DICT_KEY_NAME, this->name, sizeof(this->name));
 
-		this->mtu = (unsigned int)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_MTU,ZT_DEFAULT_MTU);
+		this->mtu = (unsigned int)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_MTU, ZT_DEFAULT_MTU);
 		if (this->mtu < 1280) {
-			this->mtu = 1280; // minimum MTU allowed by IPv6 standard and others
-		} else if (this->mtu > ZT_MAX_MTU) {
+			this->mtu = 1280;	// minimum MTU allowed by IPv6 standard and others
+		}
+		else if (this->mtu > ZT_MAX_MTU) {
 			this->mtu = ZT_MAX_MTU;
 		}
 
-		if (d.getUI(ZT_NETWORKCONFIG_DICT_KEY_VERSION,0) < 6) {
-	#ifdef ZT_SUPPORT_OLD_STYLE_NETCONF
-			char tmp2[1024] = {0};
+		if (d.getUI(ZT_NETWORKCONFIG_DICT_KEY_VERSION, 0) < 6) {
+#ifdef ZT_SUPPORT_OLD_STYLE_NETCONF
+			char tmp2[1024] = { 0 };
 
 			// Decode legacy fields if version is old
 			if (d.getB(ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST_OLD)) {
 				this->flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST;
 			}
-			this->flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION; // always enable for old-style netconf
-			this->type = (d.getB(ZT_NETWORKCONFIG_DICT_KEY_PRIVATE_OLD,true)) ? ZT_NETWORK_TYPE_PRIVATE : ZT_NETWORK_TYPE_PUBLIC;
+			this->flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION;	  // always enable for old-style netconf
+			this->type = (d.getB(ZT_NETWORKCONFIG_DICT_KEY_PRIVATE_OLD, true)) ? ZT_NETWORK_TYPE_PRIVATE : ZT_NETWORK_TYPE_PUBLIC;
 
-			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC_OLD,tmp2,sizeof(tmp2)) > 0) {
-				char *saveptr = (char *)0;
-				for(char *f=Utils::stok(tmp2,",",&saveptr);(f);f=Utils::stok((char *)0,",",&saveptr)) {
+			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC_OLD, tmp2, sizeof(tmp2)) > 0) {
+				char* saveptr = (char*)0;
+				for (char* f = Utils::stok(tmp2, ",", &saveptr); (f); f = Utils::stok((char*)0, ",", &saveptr)) {
 					if (this->staticIpCount >= ZT_MAX_ZT_ASSIGNED_ADDRESSES) {
 						break;
 					}
 					InetAddress ip(f);
-					if (!ip.isNetwork()) {
+					if (! ip.isNetwork()) {
 						this->staticIps[this->staticIpCount++] = ip;
 					}
 				}
 			}
-			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC_OLD,tmp2,sizeof(tmp2)) > 0) {
-				char *saveptr = (char *)0;
-				for(char *f=Utils::stok(tmp2,",",&saveptr);(f);f=Utils::stok((char *)0,",",&saveptr)) {
+			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC_OLD, tmp2, sizeof(tmp2)) > 0) {
+				char* saveptr = (char*)0;
+				for (char* f = Utils::stok(tmp2, ",", &saveptr); (f); f = Utils::stok((char*)0, ",", &saveptr)) {
 					if (this->staticIpCount >= ZT_MAX_ZT_ASSIGNED_ADDRESSES) {
 						break;
 					}
 					InetAddress ip(f);
-					if (!ip.isNetwork()) {
+					if (! ip.isNetwork()) {
 						this->staticIps[this->staticIpCount++] = ip;
 					}
 				}
 			}
 
-			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP_OLD,tmp2,sizeof(tmp2)) > 0) {
+			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP_OLD, tmp2, sizeof(tmp2)) > 0) {
 				this->com.fromString(tmp2);
 			}
 
-			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES_OLD,tmp2,sizeof(tmp2)) > 0) {
-				char *saveptr = (char *)0;
-				for(char *f=Utils::stok(tmp2,",",&saveptr);(f);f=Utils::stok((char *)0,",",&saveptr)) {
+			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES_OLD, tmp2, sizeof(tmp2)) > 0) {
+				char* saveptr = (char*)0;
+				for (char* f = Utils::stok(tmp2, ",", &saveptr); (f); f = Utils::stok((char*)0, ",", &saveptr)) {
 					unsigned int et = Utils::hexStrToUInt(f) & 0xffff;
 					if ((this->ruleCount + 2) > ZT_MAX_NETWORK_RULES) {
 						break;
@@ -405,67 +408,74 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
 					}
 					this->rules[this->ruleCount++].t = (uint8_t)ZT_NETWORK_RULE_ACTION_ACCEPT;
 				}
-			} else {
+			}
+			else {
 				this->rules[0].t = ZT_NETWORK_RULE_ACTION_ACCEPT;
 				this->ruleCount = 1;
 			}
 
-			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES_OLD,tmp2,sizeof(tmp2)) > 0) {
-				char *saveptr = (char *)0;
-				for(char *f=Utils::stok(tmp2,",",&saveptr);(f);f=Utils::stok((char *)0,",",&saveptr)) {
-					this->addSpecialist(Address(Utils::hexStrToU64(f)),ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE);
+			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES_OLD, tmp2, sizeof(tmp2)) > 0) {
+				char* saveptr = (char*)0;
+				for (char* f = Utils::stok(tmp2, ",", &saveptr); (f); f = Utils::stok((char*)0, ",", &saveptr)) {
+					this->addSpecialist(Address(Utils::hexStrToU64(f)), ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE);
 				}
 			}
-	#else
+#else
 			delete tmp;
 			return false;
-	#endif // ZT_SUPPORT_OLD_STYLE_NETCONF
-		} else {
+#endif	 // ZT_SUPPORT_OLD_STYLE_NETCONF
+		}
+		else {
 			// Otherwise we can use the new fields
-			this->flags = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_FLAGS,0);
-			this->type = (ZT_VirtualNetworkType)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_TYPE,(uint64_t)ZT_NETWORK_TYPE_PRIVATE);
+			this->flags = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_FLAGS, 0);
+			this->type = (ZT_VirtualNetworkType)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_TYPE, (uint64_t)ZT_NETWORK_TYPE_PRIVATE);
 
-			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_COM,*tmp)) {
-				this->com.deserialize(*tmp,0);
+			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_COM, *tmp)) {
+				this->com.deserialize(*tmp, 0);
 			}
 
-			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_CAPABILITIES,*tmp)) {
+			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_CAPABILITIES, *tmp)) {
 				try {
 					unsigned int p = 0;
 					while (p < tmp->size()) {
 						Capability cap;
-						p += cap.deserialize(*tmp,p);
+						p += cap.deserialize(*tmp, p);
 						this->capabilities[this->capabilityCount++] = cap;
 					}
-				} catch ( ... ) {}
-				std::sort(&(this->capabilities[0]),&(this->capabilities[this->capabilityCount]));
+				}
+				catch (...) {
+				}
+				std::sort(&(this->capabilities[0]), &(this->capabilities[this->capabilityCount]));
 			}
 
-			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_TAGS,*tmp)) {
+			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_TAGS, *tmp)) {
 				try {
 					unsigned int p = 0;
 					while (p < tmp->size()) {
 						Tag tag;
-						p += tag.deserialize(*tmp,p);
+						p += tag.deserialize(*tmp, p);
 						this->tags[this->tagCount++] = tag;
 					}
-				} catch ( ... ) {}
-				std::sort(&(this->tags[0]),&(this->tags[this->tagCount]));
+				}
+				catch (...) {
+				}
+				std::sort(&(this->tags[0]), &(this->tags[this->tagCount]));
 			}
 
-			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATES_OF_OWNERSHIP,*tmp)) {
+			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATES_OF_OWNERSHIP, *tmp)) {
 				unsigned int p = 0;
 				while (p < tmp->size()) {
 					if (certificateOfOwnershipCount < ZT_MAX_CERTIFICATES_OF_OWNERSHIP) {
-						p += certificatesOfOwnership[certificateOfOwnershipCount++].deserialize(*tmp,p);
-					} else {
+						p += certificatesOfOwnership[certificateOfOwnershipCount++].deserialize(*tmp, p);
+					}
+					else {
 						CertificateOfOwnership foo;
-						p += foo.deserialize(*tmp,p);
+						p += foo.deserialize(*tmp, p);
 					}
 				}
 			}
 
-			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_SPECIALISTS,*tmp)) {
+			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_SPECIALISTS, *tmp)) {
 				unsigned int p = 0;
 				while ((p + 8) <= tmp->size()) {
 					if (specialistCount < ZT_MAX_NETWORK_SPECIALISTS) {
@@ -475,11 +485,11 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
 				}
 			}
 
-			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_ROUTES,*tmp)) {
+			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_ROUTES, *tmp)) {
 				unsigned int p = 0;
-				while ((p < tmp->size())&&(routeCount < ZT_MAX_NETWORK_ROUTES)) {
-					p += reinterpret_cast<InetAddress *>(&(this->routes[this->routeCount].target))->deserialize(*tmp,p);
-					p += reinterpret_cast<InetAddress *>(&(this->routes[this->routeCount].via))->deserialize(*tmp,p);
+				while ((p < tmp->size()) && (routeCount < ZT_MAX_NETWORK_ROUTES)) {
+					p += reinterpret_cast<InetAddress*>(&(this->routes[this->routeCount].target))->deserialize(*tmp, p);
+					p += reinterpret_cast<InetAddress*>(&(this->routes[this->routeCount].via))->deserialize(*tmp, p);
 					this->routes[this->routeCount].flags = tmp->at<uint16_t>(p);
 					p += 2;
 					this->routes[this->routeCount].metric = tmp->at<uint16_t>(p);
@@ -488,17 +498,17 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
 				}
 			}
 
-			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_STATIC_IPS,*tmp)) {
+			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_STATIC_IPS, *tmp)) {
 				unsigned int p = 0;
-				while ((p < tmp->size())&&(staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES)) {
-					p += this->staticIps[this->staticIpCount++].deserialize(*tmp,p);
+				while ((p < tmp->size()) && (staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES)) {
+					p += this->staticIps[this->staticIpCount++].deserialize(*tmp, p);
 				}
 			}
 
-			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_RULES,*tmp)) {
+			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_RULES, *tmp)) {
 				this->ruleCount = 0;
 				unsigned int p = 0;
-				Capability::deserializeRules(*tmp,p,this->rules,this->ruleCount,ZT_MAX_NETWORK_RULES);
+				Capability::deserializeRules(*tmp, p, this->rules, this->ruleCount, ZT_MAX_NETWORK_RULES);
 			}
 
 			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_DNS, *tmp)) {
@@ -513,16 +523,19 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
 				// implicit flow
 				if (this->ssoEnabled) {
 					if (d.get(ZT_NETWORKCONFIG_DICT_KEY_AUTHENTICATION_URL, this->authenticationURL, (unsigned int)sizeof(this->authenticationURL)) > 0) {
-						this->authenticationURL[sizeof(this->authenticationURL) - 1] = 0; // ensure null terminated
-					} else {
+						this->authenticationURL[sizeof(this->authenticationURL) - 1] = 0;	// ensure null terminated
+					}
+					else {
 						this->authenticationURL[0] = 0;
 					}
 					this->authenticationExpiryTime = d.getI(ZT_NETWORKCONFIG_DICT_KEY_AUTHENTICATION_EXPIRY_TIME, 0);
-				} else {
+				}
+				else {
 					this->authenticationURL[0] = 0;
 					this->authenticationExpiryTime = 0;
 				}
-			} else if (this->ssoVersion == 1) {
+			}
+			else if (this->ssoVersion == 1) {
 				// full flow
 				if (this->ssoEnabled) {
 					if (d.get(ZT_NETWORKCONFIG_DICT_KEY_AUTHENTICATION_URL, this->authenticationURL, (unsigned int)sizeof(this->authenticationURL)) > 0) {
@@ -545,11 +558,13 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
 					}
 					if (d.get(ZT_NETWORKCONFIG_DICT_KEY_SSO_PROVIDER, this->ssoProvider, (unsigned int)(sizeof(this->ssoProvider))) > 0) {
 						this->ssoProvider[sizeof(this->ssoProvider) - 1] = 0;
-					} else {
+					}
+					else {
 						strncpy(this->ssoProvider, "default", sizeof(this->ssoProvider));
 						this->ssoProvider[sizeof(this->ssoProvider) - 1] = 0;
 					}
-				} else {
+				}
+				else {
 					this->authenticationURL[0] = 0;
 					this->authenticationExpiryTime = 0;
 					this->centralAuthURL[0] = 0;
@@ -562,16 +577,17 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
 			}
 		}
 
-		//printf("~~~\n%s\n~~~\n",d.data());
-		//dump();
-		//printf("~~~\n");
+		// printf("~~~\n%s\n~~~\n",d.data());
+		// dump();
+		// printf("~~~\n");
 
 		delete tmp;
 		return true;
-	} catch ( ... ) {
+	}
+	catch (...) {
 		delete tmp;
 		return false;
 	}
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier

+ 112 - 92
node/NetworkConfig.hpp

@@ -14,31 +14,29 @@
 #ifndef ZT_NETWORKCONFIG_HPP
 #define ZT_NETWORKCONFIG_HPP
 
-#include <stdint.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <vector>
-#include <stdexcept>
-#include <algorithm>
-
 #include "../include/ZeroTierOne.h"
-
-#include "Constants.hpp"
-#include "Buffer.hpp"
-#include "DNS.hpp"
-#include "InetAddress.hpp"
-#include "MulticastGroup.hpp"
 #include "Address.hpp"
+#include "Buffer.hpp"
+#include "Capability.hpp"
 #include "CertificateOfMembership.hpp"
 #include "CertificateOfOwnership.hpp"
-#include "Capability.hpp"
-#include "Tag.hpp"
+#include "Constants.hpp"
+#include "DNS.hpp"
 #include "Dictionary.hpp"
 #include "Hashtable.hpp"
 #include "Identity.hpp"
-#include "Utils.hpp"
+#include "InetAddress.hpp"
+#include "MulticastGroup.hpp"
+#include "Tag.hpp"
 #include "Trace.hpp"
+#include "Utils.hpp"
+
+#include <algorithm>
+#include <stdexcept>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <vector>
 
 /**
  * Default time delta for COMs, tags, and capabilities
@@ -93,7 +91,9 @@
 namespace ZeroTier {
 
 // Dictionary capacity needed for max size network config
-#define ZT_NETWORKCONFIG_DICT_CAPACITY (4096 + (sizeof(ZT_VirtualNetworkConfig)) + (sizeof(ZT_VirtualNetworkRule) * ZT_MAX_NETWORK_RULES) + (sizeof(Capability) * ZT_MAX_NETWORK_CAPABILITIES) + (sizeof(Tag) * ZT_MAX_NETWORK_TAGS) + (sizeof(CertificateOfOwnership) * ZT_MAX_CERTIFICATES_OF_OWNERSHIP))
+#define ZT_NETWORKCONFIG_DICT_CAPACITY                                                                                                                                                                                                         \
+	(4096 + (sizeof(ZT_VirtualNetworkConfig)) + (sizeof(ZT_VirtualNetworkRule) * ZT_MAX_NETWORK_RULES) + (sizeof(Capability) * ZT_MAX_NETWORK_CAPABILITIES) + (sizeof(Tag) * ZT_MAX_NETWORK_TAGS)                                              \
+	 + (sizeof(CertificateOfOwnership) * ZT_MAX_CERTIFICATES_OF_OWNERSHIP))
 
 // Dictionary capacity needed for max size network meta-data
 #define ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY 1024
@@ -248,46 +248,45 @@ namespace ZeroTier {
  * This is a memcpy()'able structure and is safe (in a crash sense) to modify
  * without locks.
  */
-class NetworkConfig
-{
-public:
-	NetworkConfig() :
-		networkId(0),
-		timestamp(0),
-		credentialTimeMaxDelta(0),
-		revision(0),
-		issuedTo(),
-		remoteTraceTarget(),
-		flags(0),
-		remoteTraceLevel(Trace::LEVEL_NORMAL),
-		mtu(0),
-		multicastLimit(0),
-		specialistCount(0),
-		routeCount(0),
-		staticIpCount(0),
-		ruleCount(0),
-		capabilityCount(0),
-		tagCount(0),
-		certificateOfOwnershipCount(0),
-		capabilities(),
-		tags(),
-		certificatesOfOwnership(),
-		type(ZT_NETWORK_TYPE_PRIVATE),
-		dnsCount(0),
-		ssoEnabled(false),
-		authenticationURL(),
-		authenticationExpiryTime(0),
-		issuerURL(),
-		centralAuthURL(),
-		ssoNonce(),
-		ssoState(),
-		ssoClientID()
+class NetworkConfig {
+  public:
+	NetworkConfig()
+		: networkId(0)
+		, timestamp(0)
+		, credentialTimeMaxDelta(0)
+		, revision(0)
+		, issuedTo()
+		, remoteTraceTarget()
+		, flags(0)
+		, remoteTraceLevel(Trace::LEVEL_NORMAL)
+		, mtu(0)
+		, multicastLimit(0)
+		, specialistCount(0)
+		, routeCount(0)
+		, staticIpCount(0)
+		, ruleCount(0)
+		, capabilityCount(0)
+		, tagCount(0)
+		, certificateOfOwnershipCount(0)
+		, capabilities()
+		, tags()
+		, certificatesOfOwnership()
+		, type(ZT_NETWORK_TYPE_PRIVATE)
+		, dnsCount(0)
+		, ssoEnabled(false)
+		, authenticationURL()
+		, authenticationExpiryTime(0)
+		, issuerURL()
+		, centralAuthURL()
+		, ssoNonce()
+		, ssoState()
+		, ssoClientID()
 	{
 		name[0] = 0;
-		memset(specialists, 0, sizeof(uint64_t)*ZT_MAX_NETWORK_SPECIALISTS);
-		memset(routes, 0, sizeof(ZT_VirtualNetworkRoute)*ZT_MAX_NETWORK_ROUTES);
-		memset(staticIps, 0, sizeof(InetAddress)*ZT_MAX_ZT_ASSIGNED_ADDRESSES);
-		memset(rules, 0, sizeof(ZT_VirtualNetworkRule)*ZT_MAX_NETWORK_RULES);
+		memset(specialists, 0, sizeof(uint64_t) * ZT_MAX_NETWORK_SPECIALISTS);
+		memset(routes, 0, sizeof(ZT_VirtualNetworkRoute) * ZT_MAX_NETWORK_ROUTES);
+		memset(staticIps, 0, sizeof(InetAddress) * ZT_MAX_ZT_ASSIGNED_ADDRESSES);
+		memset(rules, 0, sizeof(ZT_VirtualNetworkRule) * ZT_MAX_NETWORK_RULES);
 		memset(&dns, 0, sizeof(ZT_VirtualNetworkDNS));
 		memset(authenticationURL, 0, sizeof(authenticationURL));
 		memset(issuerURL, 0, sizeof(issuerURL));
@@ -305,7 +304,7 @@ public:
 	 * @param includeLegacy If true, include legacy fields for old node versions
 	 * @return True if dictionary was successfully created, false if e.g. overflow
 	 */
-	bool toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,bool includeLegacy) const;
+	bool toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>& d, bool includeLegacy) const;
 
 	/**
 	 * Read this network config from a dictionary
@@ -313,17 +312,23 @@ public:
 	 * @param d Dictionary (non-const since it might be modified during parse, should not be used after call)
 	 * @return True if dictionary was valid and network config successfully initialized
 	 */
-	bool fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d);
+	bool fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>& d);
 
 	/**
 	 * @return True if broadcast (ff:ff:ff:ff:ff:ff) address should work on this network
 	 */
-	inline bool enableBroadcast() const { return ((this->flags & ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST) != 0); }
+	inline bool enableBroadcast() const
+	{
+		return ((this->flags & ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST) != 0);
+	}
 
 	/**
 	 * @return True if IPv6 NDP emulation should be allowed for certain "magic" IPv6 address patterns
 	 */
-	inline bool ndpEmulation() const { return ((this->flags & ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION) != 0); }
+	inline bool ndpEmulation() const
+	{
+		return ((this->flags & ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION) != 0);
+	}
 
 	/**
 	 * @return True if frames should not be compressed
@@ -344,12 +349,18 @@ public:
 	/**
 	 * @return Network type is public (no access control)
 	 */
-	inline bool isPublic() const { return (this->type == ZT_NETWORK_TYPE_PUBLIC); }
+	inline bool isPublic() const
+	{
+		return (this->type == ZT_NETWORK_TYPE_PUBLIC);
+	}
 
 	/**
 	 * @return Network type is private (certificate access control)
 	 */
-	inline bool isPrivate() const { return (this->type == ZT_NETWORK_TYPE_PRIVATE); }
+	inline bool isPrivate() const
+	{
+		return (this->type == ZT_NETWORK_TYPE_PRIVATE);
+	}
 
 	/**
 	 * @return ZeroTier addresses of devices on this network designated as active bridges
@@ -357,7 +368,7 @@ public:
 	inline std::vector<Address> activeBridges() const
 	{
 		std::vector<Address> r;
-		for(unsigned int i=0;i<specialistCount;++i) {
+		for (unsigned int i = 0; i < specialistCount; ++i) {
 			if ((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0) {
 				r.push_back(Address(specialists[i]));
 			}
@@ -368,7 +379,7 @@ public:
 	inline unsigned int activeBridges(Address ab[ZT_MAX_NETWORK_SPECIALISTS]) const
 	{
 		unsigned int c = 0;
-		for(unsigned int i=0;i<specialistCount;++i) {
+		for (unsigned int i = 0; i < specialistCount; ++i) {
 			if ((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0) {
 				ab[c++] = specialists[i];
 			}
@@ -376,10 +387,10 @@ public:
 		return c;
 	}
 
-	inline bool isActiveBridge(const Address &a) const
+	inline bool isActiveBridge(const Address& a) const
 	{
-		for(unsigned int i=0;i<specialistCount;++i) {
-			if (((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0)&&(a == specialists[i])) {
+		for (unsigned int i = 0; i < specialistCount; ++i) {
+			if (((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0) && (a == specialists[i])) {
 				return true;
 			}
 		}
@@ -389,7 +400,7 @@ public:
 	inline std::vector<Address> anchors() const
 	{
 		std::vector<Address> r;
-		for(unsigned int i=0;i<specialistCount;++i) {
+		for (unsigned int i = 0; i < specialistCount; ++i) {
 			if ((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ANCHOR) != 0) {
 				r.push_back(Address(specialists[i]));
 			}
@@ -400,7 +411,7 @@ public:
 	inline std::vector<Address> multicastReplicators() const
 	{
 		std::vector<Address> r;
-		for(unsigned int i=0;i<specialistCount;++i) {
+		for (unsigned int i = 0; i < specialistCount; ++i) {
 			if ((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR) != 0) {
 				r.push_back(Address(specialists[i]));
 			}
@@ -411,7 +422,7 @@ public:
 	inline unsigned int multicastReplicators(Address mr[ZT_MAX_NETWORK_SPECIALISTS]) const
 	{
 		unsigned int c = 0;
-		for(unsigned int i=0;i<specialistCount;++i) {
+		for (unsigned int i = 0; i < specialistCount; ++i) {
 			if ((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR) != 0) {
 				mr[c++] = specialists[i];
 			}
@@ -419,10 +430,10 @@ public:
 		return c;
 	}
 
-	inline bool isMulticastReplicator(const Address &a) const
+	inline bool isMulticastReplicator(const Address& a) const
 	{
-		for(unsigned int i=0;i<specialistCount;++i) {
-			if (((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR) != 0)&&(a == specialists[i])) {
+		for (unsigned int i = 0; i < specialistCount; ++i) {
+			if (((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR) != 0) && (a == specialists[i])) {
 				return true;
 			}
 		}
@@ -432,7 +443,7 @@ public:
 	inline std::vector<Address> alwaysContactAddresses() const
 	{
 		std::vector<Address> r;
-		for(unsigned int i=0;i<specialistCount;++i) {
+		for (unsigned int i = 0; i < specialistCount; ++i) {
 			if ((specialists[i] & (ZT_NETWORKCONFIG_SPECIALIST_TYPE_ANCHOR | ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR)) != 0) {
 				r.push_back(Address(specialists[i]));
 			}
@@ -443,7 +454,7 @@ public:
 	inline unsigned int alwaysContactAddresses(Address ac[ZT_MAX_NETWORK_SPECIALISTS]) const
 	{
 		unsigned int c = 0;
-		for(unsigned int i=0;i<specialistCount;++i) {
+		for (unsigned int i = 0; i < specialistCount; ++i) {
 			if ((specialists[i] & (ZT_NETWORKCONFIG_SPECIALIST_TYPE_ANCHOR | ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR)) != 0) {
 				ac[c++] = specialists[i];
 			}
@@ -451,9 +462,9 @@ public:
 		return c;
 	}
 
-	inline void alwaysContactAddresses(Hashtable< Address,std::vector<InetAddress> > &a) const
+	inline void alwaysContactAddresses(Hashtable<Address, std::vector<InetAddress> >& a) const
 	{
-		for(unsigned int i=0;i<specialistCount;++i) {
+		for (unsigned int i = 0; i < specialistCount; ++i) {
 			if ((specialists[i] & (ZT_NETWORKCONFIG_SPECIALIST_TYPE_ANCHOR | ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR)) != 0) {
 				a[Address(specialists[i])];
 			}
@@ -464,19 +475,28 @@ public:
 	 * @param fromPeer Peer attempting to bridge other Ethernet peers onto network
 	 * @return True if this network allows bridging
 	 */
-	inline bool permitsBridging(const Address &fromPeer) const
+	inline bool permitsBridging(const Address& fromPeer) const
 	{
-		for(unsigned int i=0;i<specialistCount;++i) {
-			if ((fromPeer == specialists[i])&&((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0)) {
+		for (unsigned int i = 0; i < specialistCount; ++i) {
+			if ((fromPeer == specialists[i]) && ((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0)) {
 				return true;
 			}
 		}
 		return false;
 	}
 
-	inline operator bool() const { return (networkId != 0); }
-	inline bool operator==(const NetworkConfig &nc) const { return (memcmp(this,&nc,sizeof(NetworkConfig)) == 0); }
-	inline bool operator!=(const NetworkConfig &nc) const { return (!(*this == nc)); }
+	inline operator bool() const
+	{
+		return (networkId != 0);
+	}
+	inline bool operator==(const NetworkConfig& nc) const
+	{
+		return (memcmp(this, &nc, sizeof(NetworkConfig)) == 0);
+	}
+	inline bool operator!=(const NetworkConfig& nc) const
+	{
+		return (! (*this == nc));
+	}
 
 	/**
 	 * Add a specialist or mask flags if already present
@@ -488,10 +508,10 @@ public:
 	 * @param f Flags (OR of specialist role/type flags)
 	 * @return True if successfully masked or added
 	 */
-	inline bool addSpecialist(const Address &a,const uint64_t f)
+	inline bool addSpecialist(const Address& a, const uint64_t f)
 	{
 		const uint64_t aint = a.toInt();
-		for(unsigned int i=0;i<specialistCount;++i) {
+		for (unsigned int i = 0; i < specialistCount; ++i) {
 			if ((specialists[i] & 0xffffffffffULL) == aint) {
 				specialists[i] |= f;
 				return true;
@@ -504,24 +524,24 @@ public:
 		return false;
 	}
 
-	const Capability *capability(const uint32_t id) const
+	const Capability* capability(const uint32_t id) const
 	{
-		for(unsigned int i=0;i<capabilityCount;++i) {
+		for (unsigned int i = 0; i < capabilityCount; ++i) {
 			if (capabilities[i].id() == id) {
 				return &(capabilities[i]);
 			}
 		}
-		return (Capability *)0;
+		return (Capability*)0;
 	}
 
-	const Tag *tag(const uint32_t id) const
+	const Tag* tag(const uint32_t id) const
 	{
-		for(unsigned int i=0;i<tagCount;++i) {
+		for (unsigned int i = 0; i < tagCount; ++i) {
 			if (tags[i].id() == id) {
 				return &(tags[i]);
 			}
 		}
-		return (Tag *)0;
+		return (Tag*)0;
 	}
 
 	/**
@@ -729,6 +749,6 @@ public:
 	char ssoProvider[64];
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 21 - 31
node/NetworkController.hpp

@@ -14,13 +14,13 @@
 #ifndef ZT_NETWORKCONFIGMASTER_HPP
 #define ZT_NETWORKCONFIGMASTER_HPP
 
-#include <stdint.h>
-
+#include "Address.hpp"
 #include "Constants.hpp"
 #include "Dictionary.hpp"
 #include "NetworkConfig.hpp"
 #include "Revocation.hpp"
-#include "Address.hpp"
+
+#include <stdint.h>
 
 namespace ZeroTier {
 
@@ -30,24 +30,15 @@ struct InetAddress;
 /**
  * Interface for network controller implementations
  */
-class NetworkController
-{
-public:
-	enum ErrorCode
-	{
-		NC_ERROR_NONE = 0,
-		NC_ERROR_OBJECT_NOT_FOUND = 1,
-		NC_ERROR_ACCESS_DENIED = 2,
-		NC_ERROR_INTERNAL_SERVER_ERROR = 3,
-		NC_ERROR_AUTHENTICATION_REQUIRED = 4
-	};
+class NetworkController {
+  public:
+	enum ErrorCode { NC_ERROR_NONE = 0, NC_ERROR_OBJECT_NOT_FOUND = 1, NC_ERROR_ACCESS_DENIED = 2, NC_ERROR_INTERNAL_SERVER_ERROR = 3, NC_ERROR_AUTHENTICATION_REQUIRED = 4 };
 
 	/**
 	 * Interface for sender used to send pushes and replies
 	 */
-	class Sender
-	{
-	public:
+	class Sender {
+	  public:
 		/**
 		 * Send a configuration to a remote peer
 		 *
@@ -57,7 +48,7 @@ public:
 		 * @param nc Network configuration to send
 		 * @param sendLegacyFormatConfig If true, send an old-format network config
 		 */
-		virtual void ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &destination,const NetworkConfig &nc,bool sendLegacyFormatConfig) = 0;
+		virtual void ncSendConfig(uint64_t nwid, uint64_t requestPacketId, const Address& destination, const NetworkConfig& nc, bool sendLegacyFormatConfig) = 0;
 
 		/**
 		 * Send revocation to a node
@@ -65,14 +56,14 @@ public:
 		 * @param destination Destination node address
 		 * @param rev Revocation to send
 		 */
-		virtual void ncSendRevocation(const Address &destination,const Revocation &rev) = 0;
+		virtual void ncSendRevocation(const Address& destination, const Revocation& rev) = 0;
 
 		/**
 		 * Send a network configuration request error
 		 *
 		 * If errorData/errorDataSize are provided they must point to a valid serialized
 		 * Dictionary containing error data. They can be null/zero if not specified.
-		 * 
+		 *
 		 * @param nwid Network ID
 		 * @param requestPacketId Request packet ID or 0 if none
 		 * @param destination Destination peer Address
@@ -80,11 +71,15 @@ public:
 		 * @param errorData Data associated with error or NULL if none
 		 * @param errorDataSize Size of errorData in bytes
 		 */
-		virtual void ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &destination,NetworkController::ErrorCode errorCode, const void *errorData, unsigned int errorDataSize) = 0;
+		virtual void ncSendError(uint64_t nwid, uint64_t requestPacketId, const Address& destination, NetworkController::ErrorCode errorCode, const void* errorData, unsigned int errorDataSize) = 0;
 	};
 
-	NetworkController() {}
-	virtual ~NetworkController() {}
+	NetworkController()
+	{
+	}
+	virtual ~NetworkController()
+	{
+	}
 
 	/**
 	 * Called when this is added to a Node to initialize and supply info
@@ -92,7 +87,7 @@ public:
 	 * @param signingId Identity for signing of network configurations, certs, etc.
 	 * @param sender Sender implementation for sending replies or config pushes
 	 */
-	virtual void init(const Identity &signingId,Sender *sender) = 0;
+	virtual void init(const Identity& signingId, Sender* sender) = 0;
 
 	/**
 	 * Handle a network configuration request
@@ -104,14 +99,9 @@ public:
 	 * @param metaData Meta-data bundled with request (if any)
 	 * @return Returns NETCONF_QUERY_OK if result 'nc' is valid, or an error code on error
 	 */
-	virtual void request(
-		uint64_t nwid,
-		const InetAddress &fromAddr,
-		uint64_t requestPacketId,
-		const Identity &identity,
-		const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> &metaData) = 0;
+	virtual void request(uint64_t nwid, const InetAddress& fromAddr, uint64_t requestPacketId, const Identity& identity, const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY>& metaData) = 0;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

File diff suppressed because it is too large
+ 372 - 335
node/Node.cpp


+ 138 - 114
node/Node.hpp

@@ -14,29 +14,26 @@
 #ifndef ZT_NODE_HPP
 #define ZT_NODE_HPP
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <map>
-#include <vector>
-
-#include "Constants.hpp"
-
 #include "../include/ZeroTierOne.h"
-
-#include "RuntimeEnvironment.hpp"
+#include "Bond.hpp"
+#include "Constants.hpp"
+#include "Hashtable.hpp"
 #include "InetAddress.hpp"
-#include "Mutex.hpp"
 #include "MAC.hpp"
+#include "Mutex.hpp"
 #include "Network.hpp"
+#include "NetworkController.hpp"
 #include "Path.hpp"
+#include "RuntimeEnvironment.hpp"
 #include "Salsa20.hpp"
-#include "NetworkController.hpp"
-#include "Hashtable.hpp"
-#include "Bond.hpp"
 #include "SelfAwareness.hpp"
 
+#include <map>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <vector>
+
 // Bit mask for "expecting reply" hash
 #define ZT_EXPECTING_REPLIES_BUCKET_MASK1 255
 #define ZT_EXPECTING_REPLIES_BUCKET_MASK2 31
@@ -50,94 +47,76 @@ class World;
  *
  * The pointer returned by ZT_Node_new() is an instance of this class.
  */
-class Node : public NetworkController::Sender
-{
-public:
-	Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64_t now);
+class Node : public NetworkController::Sender {
+  public:
+	Node(void* uptr, void* tptr, const struct ZT_Node_Callbacks* callbacks, int64_t now);
 	virtual ~Node();
 
 	// Get rid of alignment warnings on 32-bit Windows and possibly improve performance
 #ifdef __WINDOWS__
-	void * operator new(size_t i) { return _mm_malloc(i,16); }
-	void operator delete(void* p) { _mm_free(p); }
+	void* operator new(size_t i)
+	{
+		return _mm_malloc(i, 16);
+	}
+	void operator delete(void* p)
+	{
+		_mm_free(p);
+	}
 #endif
 
 	// Public API Functions ----------------------------------------------------
 
-	ZT_ResultCode processWirePacket(
-		void *tptr,
-		int64_t now,
-		int64_t localSocket,
-		const struct sockaddr_storage *remoteAddress,
-		const void *packetData,
-		unsigned int packetLength,
-		volatile int64_t *nextBackgroundTaskDeadline);
+	ZT_ResultCode processWirePacket(void* tptr, int64_t now, int64_t localSocket, const struct sockaddr_storage* remoteAddress, const void* packetData, unsigned int packetLength, volatile int64_t* nextBackgroundTaskDeadline);
 	ZT_ResultCode processVirtualNetworkFrame(
-		void *tptr,
+		void* tptr,
 		int64_t now,
 		uint64_t nwid,
 		uint64_t sourceMac,
 		uint64_t destMac,
 		unsigned int etherType,
 		unsigned int vlanId,
-		const void *frameData,
+		const void* frameData,
 		unsigned int frameLength,
-		volatile int64_t *nextBackgroundTaskDeadline);
-	ZT_ResultCode processBackgroundTasks(void *tptr,int64_t now,volatile int64_t *nextBackgroundTaskDeadline);
-	ZT_ResultCode join(uint64_t nwid,void *uptr,void *tptr);
-	ZT_ResultCode leave(uint64_t nwid,void **uptr,void *tptr);
-	ZT_ResultCode multicastSubscribe(void *tptr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
-	ZT_ResultCode multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
-	ZT_ResultCode orbit(void *tptr,uint64_t moonWorldId,uint64_t moonSeed);
-	ZT_ResultCode deorbit(void *tptr,uint64_t moonWorldId);
+		volatile int64_t* nextBackgroundTaskDeadline);
+	ZT_ResultCode processBackgroundTasks(void* tptr, int64_t now, volatile int64_t* nextBackgroundTaskDeadline);
+	ZT_ResultCode join(uint64_t nwid, void* uptr, void* tptr);
+	ZT_ResultCode leave(uint64_t nwid, void** uptr, void* tptr);
+	ZT_ResultCode multicastSubscribe(void* tptr, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi);
+	ZT_ResultCode multicastUnsubscribe(uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi);
+	ZT_ResultCode orbit(void* tptr, uint64_t moonWorldId, uint64_t moonSeed);
+	ZT_ResultCode deorbit(void* tptr, uint64_t moonWorldId);
 	uint64_t address() const;
-	void status(ZT_NodeStatus *status) const;
-	ZT_PeerList *peers() const;
-	ZT_VirtualNetworkConfig *networkConfig(uint64_t nwid) const;
-	ZT_VirtualNetworkList *networks() const;
-	void freeQueryResult(void *qr);
-	int addLocalInterfaceAddress(const struct sockaddr_storage *addr);
+	void status(ZT_NodeStatus* status) const;
+	ZT_PeerList* peers() const;
+	ZT_VirtualNetworkConfig* networkConfig(uint64_t nwid) const;
+	ZT_VirtualNetworkList* networks() const;
+	void freeQueryResult(void* qr);
+	int addLocalInterfaceAddress(const struct sockaddr_storage* addr);
 	void clearLocalInterfaceAddresses();
-	int sendUserMessage(void *tptr,uint64_t dest,uint64_t typeId,const void *data,unsigned int len);
-	void setNetconfMaster(void *networkControllerInstance);
+	int sendUserMessage(void* tptr, uint64_t dest, uint64_t typeId, const void* data, unsigned int len);
+	void setNetconfMaster(void* networkControllerInstance);
 
 	// Internal functions ------------------------------------------------------
 
-	inline int64_t now() const { return _now; }
+	inline int64_t now() const
+	{
+		return _now;
+	}
 
-	inline bool putPacket(void *tPtr,const int64_t localSocket,const InetAddress &addr,const void *data,unsigned int len,unsigned int ttl = 0)
+	inline bool putPacket(void* tPtr, const int64_t localSocket, const InetAddress& addr, const void* data, unsigned int len, unsigned int ttl = 0)
 	{
-		return (_cb.wirePacketSendFunction(
-			reinterpret_cast<ZT_Node *>(this),
-			_uPtr,
-			tPtr,
-			localSocket,
-			reinterpret_cast<const struct sockaddr_storage *>(&addr),
-			data,
-			len,
-			ttl) == 0);
+		return (_cb.wirePacketSendFunction(reinterpret_cast<ZT_Node*>(this), _uPtr, tPtr, localSocket, reinterpret_cast<const struct sockaddr_storage*>(&addr), data, len, ttl) == 0);
 	}
 
-	inline void putFrame(void *tPtr,uint64_t nwid,void **nuptr,const MAC &source,const MAC &dest,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len)
+	inline void putFrame(void* tPtr, uint64_t nwid, void** nuptr, const MAC& source, const MAC& dest, unsigned int etherType, unsigned int vlanId, const void* data, unsigned int len)
 	{
-		_cb.virtualNetworkFrameFunction(
-			reinterpret_cast<ZT_Node *>(this),
-			_uPtr,
-			tPtr,
-			nwid,
-			nuptr,
-			source.toInt(),
-			dest.toInt(),
-			etherType,
-			vlanId,
-			data,
-			len);
+		_cb.virtualNetworkFrameFunction(reinterpret_cast<ZT_Node*>(this), _uPtr, tPtr, nwid, nuptr, source.toInt(), dest.toInt(), etherType, vlanId, data, len);
 	}
 
 	inline SharedPtr<Network> network(uint64_t nwid) const
 	{
 		Mutex::Lock _l(_networks_m);
-		const SharedPtr<Network> *n = _networks.get(nwid);
+		const SharedPtr<Network>* n = _networks.get(nwid);
 		if (n) {
 			return *n;
 		}
@@ -150,14 +129,14 @@ public:
 		return _networks.contains(nwid);
 	}
 
-	inline std::vector< SharedPtr<Network> > allNetworks() const
+	inline std::vector<SharedPtr<Network> > allNetworks() const
 	{
-		std::vector< SharedPtr<Network> > nw;
+		std::vector<SharedPtr<Network> > nw;
 		Mutex::Lock _l(_networks_m);
-		Hashtable< uint64_t,SharedPtr<Network> >::Iterator i(*const_cast< Hashtable< uint64_t,SharedPtr<Network> > * >(&_networks));
-		uint64_t *k = (uint64_t *)0;
-		SharedPtr<Network> *v = (SharedPtr<Network> *)0;
-		while (i.next(k,v)) {
+		Hashtable<uint64_t, SharedPtr<Network> >::Iterator i(*const_cast<Hashtable<uint64_t, SharedPtr<Network> >*>(&_networks));
+		uint64_t* k = (uint64_t*)0;
+		SharedPtr<Network>* v = (SharedPtr<Network>*)0;
+		while (i.next(k, v)) {
 			nw.push_back(*v);
 		}
 		return nw;
@@ -169,30 +148,60 @@ public:
 		return _directPaths;
 	}
 
-	inline void postEvent(void *tPtr,ZT_Event ev,const void *md = (const void *)0) { _cb.eventCallback(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,ev,md); }
+	inline void postEvent(void* tPtr, ZT_Event ev, const void* md = (const void*)0)
+	{
+		_cb.eventCallback(reinterpret_cast<ZT_Node*>(this), _uPtr, tPtr, ev, md);
+	}
 
-	inline int configureVirtualNetworkPort(void *tPtr,uint64_t nwid,void **nuptr,ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nc) { return _cb.virtualNetworkConfigFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,nwid,nuptr,op,nc); }
+	inline int configureVirtualNetworkPort(void* tPtr, uint64_t nwid, void** nuptr, ZT_VirtualNetworkConfigOperation op, const ZT_VirtualNetworkConfig* nc)
+	{
+		return _cb.virtualNetworkConfigFunction(reinterpret_cast<ZT_Node*>(this), _uPtr, tPtr, nwid, nuptr, op, nc);
+	}
 
-	inline bool online() const { return _online; }
+	inline bool online() const
+	{
+		return _online;
+	}
 
-	inline int stateObjectGet(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2],void *const data,const unsigned int maxlen) { return _cb.stateGetFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,type,id,data,maxlen); }
-	inline void stateObjectPut(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2],const void *const data,const unsigned int len) { _cb.statePutFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,type,id,data,(int)len); }
-	inline void stateObjectDelete(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2]) { _cb.statePutFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,type,id,(const void *)0,-1); }
+	inline int stateObjectGet(void* const tPtr, ZT_StateObjectType type, const uint64_t id[2], void* const data, const unsigned int maxlen)
+	{
+		return _cb.stateGetFunction(reinterpret_cast<ZT_Node*>(this), _uPtr, tPtr, type, id, data, maxlen);
+	}
+	inline void stateObjectPut(void* const tPtr, ZT_StateObjectType type, const uint64_t id[2], const void* const data, const unsigned int len)
+	{
+		_cb.statePutFunction(reinterpret_cast<ZT_Node*>(this), _uPtr, tPtr, type, id, data, (int)len);
+	}
+	inline void stateObjectDelete(void* const tPtr, ZT_StateObjectType type, const uint64_t id[2])
+	{
+		_cb.statePutFunction(reinterpret_cast<ZT_Node*>(this), _uPtr, tPtr, type, id, (const void*)0, -1);
+	}
 
-	bool shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,const int64_t localSocket,const InetAddress &remoteAddress);
-	inline bool externalPathLookup(void *tPtr,const Address &ztaddr,int family,InetAddress &addr) { return ( (_cb.pathLookupFunction) ? (_cb.pathLookupFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,ztaddr.toInt(),family,reinterpret_cast<struct sockaddr_storage *>(&addr)) != 0) : false ); }
+	bool shouldUsePathForZeroTierTraffic(void* tPtr, const Address& ztaddr, const int64_t localSocket, const InetAddress& remoteAddress);
+	inline bool externalPathLookup(void* tPtr, const Address& ztaddr, int family, InetAddress& addr)
+	{
+		return ((_cb.pathLookupFunction) ? (_cb.pathLookupFunction(reinterpret_cast<ZT_Node*>(this), _uPtr, tPtr, ztaddr.toInt(), family, reinterpret_cast<struct sockaddr_storage*>(&addr)) != 0) : false);
+	}
 
 	uint64_t prng();
-	ZT_ResultCode setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig);
+	ZT_ResultCode setPhysicalPathConfiguration(const struct sockaddr_storage* pathNetwork, const ZT_PhysicalPathConfiguration* pathConfig);
 
 	World planet() const;
 	std::vector<World> moons() const;
 
-	inline const Identity &identity() const { return _RR.identity; }
+	inline const Identity& identity() const
+	{
+		return _RR.identity;
+	}
 
-	inline const std::vector<InetAddress> SurfaceAddresses() const { return _RR.sa->whoami(); }
+	inline const std::vector<InetAddress> SurfaceAddresses() const
+	{
+		return _RR.sa->whoami();
+	}
 
-	inline Bond *bondController() const { return _RR.bc; }
+	inline Bond* bondController() const
+	{
+		return _RR.bc;
+	}
 
 	/**
 	 * Register that we are expecting a reply to a packet ID
@@ -224,7 +233,7 @@ public:
 	{
 		const uint32_t pid2 = (uint32_t)(packetId >> 32);
 		const unsigned long bucket = (unsigned long)(pid2 & ZT_EXPECTING_REPLIES_BUCKET_MASK1);
-		for(unsigned long i=0;i<=ZT_EXPECTING_REPLIES_BUCKET_MASK2;++i) {
+		for (unsigned long i = 0; i <= ZT_EXPECTING_REPLIES_BUCKET_MASK2; ++i) {
 			if (_expectingRepliesTo[bucket][i] == pid2) {
 				return true;
 			}
@@ -239,7 +248,7 @@ public:
 	 * @param from Source address of packet
 	 * @return True if within rate limits
 	 */
-	inline bool rateGateIdentityVerification(const int64_t now,const InetAddress &from)
+	inline bool rateGateIdentityVerification(const int64_t now, const InetAddress& from)
 	{
 		unsigned long iph = from.rateGateHash();
 		if ((now - _lastIdentityVerification[iph]) >= ZT_IDENTITY_VALIDATION_SOURCE_RATE_LIMIT) {
@@ -249,17 +258,23 @@ public:
 		return false;
 	}
 
-	virtual void ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &destination,const NetworkConfig &nc,bool sendLegacyFormatConfig);
-	virtual void ncSendRevocation(const Address &destination,const Revocation &rev);
-	virtual void ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &destination,NetworkController::ErrorCode errorCode, const void *errorData, unsigned int errorDataSize);
+	virtual void ncSendConfig(uint64_t nwid, uint64_t requestPacketId, const Address& destination, const NetworkConfig& nc, bool sendLegacyFormatConfig);
+	virtual void ncSendRevocation(const Address& destination, const Revocation& rev);
+	virtual void ncSendError(uint64_t nwid, uint64_t requestPacketId, const Address& destination, NetworkController::ErrorCode errorCode, const void* errorData, unsigned int errorDataSize);
 
-	inline const Address &remoteTraceTarget() const { return _remoteTraceTarget; }
-	inline Trace::Level remoteTraceLevel() const { return _remoteTraceLevel; }
+	inline const Address& remoteTraceTarget() const
+	{
+		return _remoteTraceTarget;
+	}
+	inline Trace::Level remoteTraceLevel() const
+	{
+		return _remoteTraceLevel;
+	}
 
-	inline bool localControllerHasAuthorized(const int64_t now,const uint64_t nwid,const Address &addr) const
+	inline bool localControllerHasAuthorized(const int64_t now, const uint64_t nwid, const Address& addr) const
 	{
 		_localControllerAuthorizations_m.lock();
-		const int64_t *const at = _localControllerAuthorizations.get(_LocalControllerAuth(nwid,addr));
+		const int64_t* const at = _localControllerAuthorizations.get(_LocalControllerAuth(nwid, addr));
 		_localControllerAuthorizations_m.unlock();
 		if (at) {
 			return ((now - *at) < (ZT_NETWORK_AUTOCONF_DELAY * 3));
@@ -267,7 +282,7 @@ public:
 		return false;
 	}
 
-	inline void statsLogVerb(const unsigned int v,const unsigned int bytes)
+	inline void statsLogVerb(const unsigned int v, const unsigned int bytes)
 	{
 		++_stats.inVerbCounts[v];
 		_stats.inVerbBytes[v] += (uint64_t)bytes;
@@ -285,11 +300,10 @@ public:
 
 	void initMultithreading(unsigned int concurrency, bool cpuPinningEnabled);
 
-
-public:
+  public:
 	RuntimeEnvironment _RR;
-	RuntimeEnvironment *RR;
-	void *_uPtr; // _uptr (lower case) is reserved in Visual Studio :P
+	RuntimeEnvironment* RR;
+	void* _uPtr;   // _uptr (lower case) is reserved in Visual Studio :P
 	ZT_Node_Callbacks _cb;
 
 	// For tracking packet IDs to filter out OK/ERROR replies to packets we did not send
@@ -304,18 +318,28 @@ public:
 
 	// Map that remembers if we have recently sent a network config to someone
 	// querying us as a controller.
-	struct _LocalControllerAuth
-	{
-		uint64_t nwid,address;
-		_LocalControllerAuth(const uint64_t nwid_,const Address &address_) : nwid(nwid_),address(address_.toInt()) {}
-		inline unsigned long hashCode() const { return (unsigned long)(nwid ^ address); }
-		inline bool operator==(const _LocalControllerAuth &a) const { return ((a.nwid == nwid)&&(a.address == address)); }
-		inline bool operator!=(const _LocalControllerAuth &a) const { return ((a.nwid != nwid)||(a.address != address)); }
+	struct _LocalControllerAuth {
+		uint64_t nwid, address;
+		_LocalControllerAuth(const uint64_t nwid_, const Address& address_) : nwid(nwid_), address(address_.toInt())
+		{
+		}
+		inline unsigned long hashCode() const
+		{
+			return (unsigned long)(nwid ^ address);
+		}
+		inline bool operator==(const _LocalControllerAuth& a) const
+		{
+			return ((a.nwid == nwid) && (a.address == address));
+		}
+		inline bool operator!=(const _LocalControllerAuth& a) const
+		{
+			return ((a.nwid != nwid) || (a.address != address));
+		}
 	};
-	Hashtable< _LocalControllerAuth,int64_t > _localControllerAuthorizations;
+	Hashtable<_LocalControllerAuth, int64_t> _localControllerAuthorizations;
 	Mutex _localControllerAuthorizations_m;
 
-	Hashtable< uint64_t,SharedPtr<Network> > _networks;
+	Hashtable<uint64_t, SharedPtr<Network> > _networks;
 	Mutex _networks_m;
 
 	std::vector<InetAddress> _directPaths;
@@ -336,6 +360,6 @@ public:
 	bool _lowBandwidthMode;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 20 - 18
node/OutboundMulticast.cpp

@@ -11,28 +11,29 @@
  */
 /****/
 
-#include "Constants.hpp"
-#include "RuntimeEnvironment.hpp"
 #include "OutboundMulticast.hpp"
-#include "Switch.hpp"
+
+#include "Constants.hpp"
 #include "Network.hpp"
 #include "Node.hpp"
 #include "Peer.hpp"
+#include "RuntimeEnvironment.hpp"
+#include "Switch.hpp"
 #include "Topology.hpp"
 
 namespace ZeroTier {
 
 void OutboundMulticast::init(
-	const RuntimeEnvironment *RR,
+	const RuntimeEnvironment* RR,
 	uint64_t timestamp,
 	uint64_t nwid,
 	bool disableCompression,
 	unsigned int limit,
 	unsigned int gatherLimit,
-	const MAC &src,
-	const MulticastGroup &dest,
+	const MAC& src,
+	const MulticastGroup& dest,
 	unsigned int etherType,
-	const void *payload,
+	const void* payload,
 	unsigned int len)
 {
 	uint8_t flags = 0;
@@ -42,8 +43,9 @@ void OutboundMulticast::init(
 	if (src) {
 		_macSrc = src;
 		flags |= 0x04;
-	} else {
-		_macSrc.fromAddress(RR->identity.address(),nwid);
+	}
+	else {
+		_macSrc.fromAddress(RR->identity.address(), nwid);
 	}
 	_macDest = dest.mac();
 	_limit = limit;
@@ -67,26 +69,26 @@ void OutboundMulticast::init(
 	dest.mac().appendTo(_packet);
 	_packet.append((uint32_t)dest.adi());
 	_packet.append((uint16_t)etherType);
-	_packet.append(payload,_frameLen);
-	if (!disableCompression) {
+	_packet.append(payload, _frameLen);
+	if (! disableCompression) {
 		_packet.compress();
 	}
 
-	memcpy(_frameData,payload,_frameLen);
+	memcpy(_frameData, payload, _frameLen);
 }
 
-void OutboundMulticast::sendOnly(const RuntimeEnvironment *RR,void *tPtr,const Address &toAddr)
+void OutboundMulticast::sendOnly(const RuntimeEnvironment* RR, void* tPtr, const Address& toAddr)
 {
 	const SharedPtr<Network> nw(RR->node->network(_nwid));
-	uint8_t QoSBucket = 255; // Dummy value
-	if ((nw)&&(nw->filterOutgoingPacket(tPtr,true,RR->identity.address(),toAddr,_macSrc,_macDest,_frameData,_frameLen,_etherType,0,QoSBucket))) {
-		nw->pushCredentialsIfNeeded(tPtr,toAddr,RR->node->now());
+	uint8_t QoSBucket = 255;   // Dummy value
+	if ((nw) && (nw->filterOutgoingPacket(tPtr, true, RR->identity.address(), toAddr, _macSrc, _macDest, _frameData, _frameLen, _etherType, 0, QoSBucket))) {
+		nw->pushCredentialsIfNeeded(tPtr, toAddr, RR->node->now());
 		_packet.newInitializationVector();
 		_packet.setDestination(toAddr);
 		RR->node->expectReplyTo(_packet.packetId());
 		_tmp = _packet;
-		RR->sw->send(tPtr,_tmp,true);
+		RR->sw->send(tPtr, _tmp, true);
 	}
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier

+ 38 - 28
node/OutboundMulticast.hpp

@@ -14,17 +14,16 @@
 #ifndef ZT_OUTBOUNDMULTICAST_HPP
 #define ZT_OUTBOUNDMULTICAST_HPP
 
-#include <stdint.h>
-
-#include <vector>
-#include <algorithm>
-
+#include "Address.hpp"
 #include "Constants.hpp"
 #include "MAC.hpp"
 #include "MulticastGroup.hpp"
-#include "Address.hpp"
 #include "Packet.hpp"
 
+#include <algorithm>
+#include <stdint.h>
+#include <vector>
+
 namespace ZeroTier {
 
 class CertificateOfMembership;
@@ -35,15 +34,16 @@ class RuntimeEnvironment;
  *
  * This object isn't guarded by a mutex; caller must synchronize access.
  */
-class OutboundMulticast
-{
-public:
+class OutboundMulticast {
+  public:
 	/**
 	 * Create an uninitialized outbound multicast
 	 *
 	 * It must be initialized with init().
 	 */
-	OutboundMulticast() {}
+	OutboundMulticast()
+	{
+	}
 
 	/**
 	 * Initialize outbound multicast
@@ -62,33 +62,42 @@ public:
 	 * @throws std::out_of_range Data too large to fit in a MULTICAST_FRAME
 	 */
 	void init(
-		const RuntimeEnvironment *RR,
+		const RuntimeEnvironment* RR,
 		uint64_t timestamp,
 		uint64_t nwid,
 		bool disableCompression,
 		unsigned int limit,
 		unsigned int gatherLimit,
-		const MAC &src,
-		const MulticastGroup &dest,
+		const MAC& src,
+		const MulticastGroup& dest,
 		unsigned int etherType,
-		const void *payload,
+		const void* payload,
 		unsigned int len);
 
 	/**
 	 * @return Multicast creation time
 	 */
-	inline uint64_t timestamp() const { return _timestamp; }
+	inline uint64_t timestamp() const
+	{
+		return _timestamp;
+	}
 
 	/**
 	 * @param now Current time
 	 * @return True if this multicast is expired (has exceeded transmit timeout)
 	 */
-	inline bool expired(int64_t now) const { return ((now - _timestamp) >= ZT_MULTICAST_TRANSMIT_TIMEOUT); }
+	inline bool expired(int64_t now) const
+	{
+		return ((now - _timestamp) >= ZT_MULTICAST_TRANSMIT_TIMEOUT);
+	}
 
 	/**
 	 * @return True if this outbound multicast has been sent to enough peers
 	 */
-	inline bool atLimit() const { return (_alreadySentTo.size() >= _limit); }
+	inline bool atLimit() const
+	{
+		return (_alreadySentTo.size() >= _limit);
+	}
 
 	/**
 	 * Just send without checking log
@@ -97,7 +106,7 @@ public:
 	 * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
 	 * @param toAddr Destination address
 	 */
-	void sendOnly(const RuntimeEnvironment *RR,void *tPtr,const Address &toAddr);
+	void sendOnly(const RuntimeEnvironment* RR, void* tPtr, const Address& toAddr);
 
 	/**
 	 * Just send and log but do not check sent log
@@ -106,10 +115,10 @@ public:
 	 * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
 	 * @param toAddr Destination address
 	 */
-	inline void sendAndLog(const RuntimeEnvironment *RR,void *tPtr,const Address &toAddr)
+	inline void sendAndLog(const RuntimeEnvironment* RR, void* tPtr, const Address& toAddr)
 	{
 		_alreadySentTo.push_back(toAddr);
-		sendOnly(RR,tPtr,toAddr);
+		sendOnly(RR, tPtr, toAddr);
 	}
 
 	/**
@@ -117,7 +126,7 @@ public:
 	 *
 	 * @param toAddr Address to log as sent
 	 */
-	inline void logAsSent(const Address &toAddr)
+	inline void logAsSent(const Address& toAddr)
 	{
 		_alreadySentTo.push_back(toAddr);
 	}
@@ -130,17 +139,18 @@ public:
 	 * @param toAddr Destination address
 	 * @return True if address is new and packet was sent to switch, false if duplicate
 	 */
-	inline bool sendIfNew(const RuntimeEnvironment *RR,void *tPtr,const Address &toAddr)
+	inline bool sendIfNew(const RuntimeEnvironment* RR, void* tPtr, const Address& toAddr)
 	{
-		if (std::find(_alreadySentTo.begin(),_alreadySentTo.end(),toAddr) == _alreadySentTo.end()) {
-			sendAndLog(RR,tPtr,toAddr);
+		if (std::find(_alreadySentTo.begin(), _alreadySentTo.end(), toAddr) == _alreadySentTo.end()) {
+			sendAndLog(RR, tPtr, toAddr);
 			return true;
-		} else {
+		}
+		else {
 			return false;
 		}
 	}
 
-private:
+  private:
 	uint64_t _timestamp;
 	uint64_t _nwid;
 	MAC _macSrc;
@@ -148,11 +158,11 @@ private:
 	unsigned int _limit;
 	unsigned int _frameLen;
 	unsigned int _etherType;
-	Packet _packet,_tmp;
+	Packet _packet, _tmp;
 	std::vector<Address> _alreadySentTo;
 	uint8_t _frameData[ZT_MAX_MTU];
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

File diff suppressed because it is too large
+ 349 - 276
node/Packet.cpp


+ 216 - 163
node/Packet.hpp

@@ -14,21 +14,19 @@
 #ifndef ZT_N_PACKET_HPP
 #define ZT_N_PACKET_HPP
 
-#include <stdint.h>
-#include <string.h>
-#include <stdio.h>
-
-#include <string>
-#include <iostream>
-
-#include "Constants.hpp"
-
+#include "AES.hpp"
 #include "Address.hpp"
+#include "Buffer.hpp"
+#include "Constants.hpp"
 #include "Poly1305.hpp"
 #include "Salsa20.hpp"
-#include "AES.hpp"
 #include "Utils.hpp"
-#include "Buffer.hpp"
+
+#include <iostream>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <string>
 
 /**
  * Protocol version -- incremented only for major changes
@@ -221,12 +219,12 @@
 #define ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT 0x02
 
 // Field indexes in packet header
-#define ZT_PACKET_IDX_IV 0
-#define ZT_PACKET_IDX_DEST 8
-#define ZT_PACKET_IDX_SOURCE 13
-#define ZT_PACKET_IDX_FLAGS 18
-#define ZT_PACKET_IDX_MAC 19
-#define ZT_PACKET_IDX_VERB 27
+#define ZT_PACKET_IDX_IV	  0
+#define ZT_PACKET_IDX_DEST	  8
+#define ZT_PACKET_IDX_SOURCE  13
+#define ZT_PACKET_IDX_FLAGS	  18
+#define ZT_PACKET_IDX_MAC	  19
+#define ZT_PACKET_IDX_VERB	  27
 #define ZT_PACKET_IDX_PAYLOAD 28
 
 /**
@@ -240,12 +238,12 @@
 #define ZT_PROTO_MIN_PACKET_LENGTH ZT_PACKET_IDX_PAYLOAD
 
 // Indexes of fields in fragment header
-#define ZT_PACKET_FRAGMENT_IDX_PACKET_ID 0
-#define ZT_PACKET_FRAGMENT_IDX_DEST 8
+#define ZT_PACKET_FRAGMENT_IDX_PACKET_ID		  0
+#define ZT_PACKET_FRAGMENT_IDX_DEST				  8
 #define ZT_PACKET_FRAGMENT_IDX_FRAGMENT_INDICATOR 13
-#define ZT_PACKET_FRAGMENT_IDX_FRAGMENT_NO 14
-#define ZT_PACKET_FRAGMENT_IDX_HOPS 15
-#define ZT_PACKET_FRAGMENT_IDX_PAYLOAD 16
+#define ZT_PACKET_FRAGMENT_IDX_FRAGMENT_NO		  14
+#define ZT_PACKET_FRAGMENT_IDX_HOPS				  15
+#define ZT_PACKET_FRAGMENT_IDX_PAYLOAD			  16
 
 /**
  * Magic number found at ZT_PACKET_FRAGMENT_IDX_FRAGMENT_INDICATOR
@@ -264,89 +262,89 @@
 // See their respective handler functions.
 
 #define ZT_PROTO_VERB_HELLO_IDX_PROTOCOL_VERSION (ZT_PACKET_IDX_PAYLOAD)
-#define ZT_PROTO_VERB_HELLO_IDX_MAJOR_VERSION (ZT_PROTO_VERB_HELLO_IDX_PROTOCOL_VERSION + 1)
-#define ZT_PROTO_VERB_HELLO_IDX_MINOR_VERSION (ZT_PROTO_VERB_HELLO_IDX_MAJOR_VERSION + 1)
-#define ZT_PROTO_VERB_HELLO_IDX_REVISION (ZT_PROTO_VERB_HELLO_IDX_MINOR_VERSION + 1)
-#define ZT_PROTO_VERB_HELLO_IDX_TIMESTAMP (ZT_PROTO_VERB_HELLO_IDX_REVISION + 2)
-#define ZT_PROTO_VERB_HELLO_IDX_IDENTITY (ZT_PROTO_VERB_HELLO_IDX_TIMESTAMP + 8)
+#define ZT_PROTO_VERB_HELLO_IDX_MAJOR_VERSION	 (ZT_PROTO_VERB_HELLO_IDX_PROTOCOL_VERSION + 1)
+#define ZT_PROTO_VERB_HELLO_IDX_MINOR_VERSION	 (ZT_PROTO_VERB_HELLO_IDX_MAJOR_VERSION + 1)
+#define ZT_PROTO_VERB_HELLO_IDX_REVISION		 (ZT_PROTO_VERB_HELLO_IDX_MINOR_VERSION + 1)
+#define ZT_PROTO_VERB_HELLO_IDX_TIMESTAMP		 (ZT_PROTO_VERB_HELLO_IDX_REVISION + 2)
+#define ZT_PROTO_VERB_HELLO_IDX_IDENTITY		 (ZT_PROTO_VERB_HELLO_IDX_TIMESTAMP + 8)
 
-#define ZT_PROTO_VERB_ERROR_IDX_IN_RE_VERB (ZT_PACKET_IDX_PAYLOAD)
+#define ZT_PROTO_VERB_ERROR_IDX_IN_RE_VERB		(ZT_PACKET_IDX_PAYLOAD)
 #define ZT_PROTO_VERB_ERROR_IDX_IN_RE_PACKET_ID (ZT_PROTO_VERB_ERROR_IDX_IN_RE_VERB + 1)
-#define ZT_PROTO_VERB_ERROR_IDX_ERROR_CODE (ZT_PROTO_VERB_ERROR_IDX_IN_RE_PACKET_ID + 8)
-#define ZT_PROTO_VERB_ERROR_IDX_PAYLOAD (ZT_PROTO_VERB_ERROR_IDX_ERROR_CODE + 1)
+#define ZT_PROTO_VERB_ERROR_IDX_ERROR_CODE		(ZT_PROTO_VERB_ERROR_IDX_IN_RE_PACKET_ID + 8)
+#define ZT_PROTO_VERB_ERROR_IDX_PAYLOAD			(ZT_PROTO_VERB_ERROR_IDX_ERROR_CODE + 1)
 
-#define ZT_PROTO_VERB_OK_IDX_IN_RE_VERB (ZT_PACKET_IDX_PAYLOAD)
+#define ZT_PROTO_VERB_OK_IDX_IN_RE_VERB		 (ZT_PACKET_IDX_PAYLOAD)
 #define ZT_PROTO_VERB_OK_IDX_IN_RE_PACKET_ID (ZT_PROTO_VERB_OK_IDX_IN_RE_VERB + 1)
-#define ZT_PROTO_VERB_OK_IDX_PAYLOAD (ZT_PROTO_VERB_OK_IDX_IN_RE_PACKET_ID + 8)
+#define ZT_PROTO_VERB_OK_IDX_PAYLOAD		 (ZT_PROTO_VERB_OK_IDX_IN_RE_PACKET_ID + 8)
 
 #define ZT_PROTO_VERB_WHOIS_IDX_ZTADDRESS (ZT_PACKET_IDX_PAYLOAD)
 
-#define ZT_PROTO_VERB_RENDEZVOUS_IDX_FLAGS (ZT_PACKET_IDX_PAYLOAD)
+#define ZT_PROTO_VERB_RENDEZVOUS_IDX_FLAGS	   (ZT_PACKET_IDX_PAYLOAD)
 #define ZT_PROTO_VERB_RENDEZVOUS_IDX_ZTADDRESS (ZT_PROTO_VERB_RENDEZVOUS_IDX_FLAGS + 1)
-#define ZT_PROTO_VERB_RENDEZVOUS_IDX_PORT (ZT_PROTO_VERB_RENDEZVOUS_IDX_ZTADDRESS + 5)
-#define ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRLEN (ZT_PROTO_VERB_RENDEZVOUS_IDX_PORT + 2)
-#define ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS (ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRLEN + 1)
+#define ZT_PROTO_VERB_RENDEZVOUS_IDX_PORT	   (ZT_PROTO_VERB_RENDEZVOUS_IDX_ZTADDRESS + 5)
+#define ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRLEN   (ZT_PROTO_VERB_RENDEZVOUS_IDX_PORT + 2)
+#define ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS   (ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRLEN + 1)
 
 #define ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID (ZT_PACKET_IDX_PAYLOAD)
-#define ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE (ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID + 8)
-#define ZT_PROTO_VERB_FRAME_IDX_PAYLOAD (ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE + 2)
+#define ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE  (ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID + 8)
+#define ZT_PROTO_VERB_FRAME_IDX_PAYLOAD	   (ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE + 2)
 
 #define ZT_PROTO_VERB_EXT_FRAME_IDX_NETWORK_ID (ZT_PACKET_IDX_PAYLOAD)
 #define ZT_PROTO_VERB_EXT_FRAME_LEN_NETWORK_ID 8
-#define ZT_PROTO_VERB_EXT_FRAME_IDX_FLAGS (ZT_PROTO_VERB_EXT_FRAME_IDX_NETWORK_ID + ZT_PROTO_VERB_EXT_FRAME_LEN_NETWORK_ID)
-#define ZT_PROTO_VERB_EXT_FRAME_LEN_FLAGS 1
-#define ZT_PROTO_VERB_EXT_FRAME_IDX_COM (ZT_PROTO_VERB_EXT_FRAME_IDX_FLAGS + ZT_PROTO_VERB_EXT_FRAME_LEN_FLAGS)
-#define ZT_PROTO_VERB_EXT_FRAME_IDX_TO (ZT_PROTO_VERB_EXT_FRAME_IDX_FLAGS + ZT_PROTO_VERB_EXT_FRAME_LEN_FLAGS)
-#define ZT_PROTO_VERB_EXT_FRAME_LEN_TO 6
-#define ZT_PROTO_VERB_EXT_FRAME_IDX_FROM (ZT_PROTO_VERB_EXT_FRAME_IDX_TO + ZT_PROTO_VERB_EXT_FRAME_LEN_TO)
-#define ZT_PROTO_VERB_EXT_FRAME_LEN_FROM 6
-#define ZT_PROTO_VERB_EXT_FRAME_IDX_ETHERTYPE (ZT_PROTO_VERB_EXT_FRAME_IDX_FROM + ZT_PROTO_VERB_EXT_FRAME_LEN_FROM)
-#define ZT_PROTO_VERB_EXT_FRAME_LEN_ETHERTYPE 2
-#define ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD (ZT_PROTO_VERB_EXT_FRAME_IDX_ETHERTYPE + ZT_PROTO_VERB_EXT_FRAME_LEN_ETHERTYPE)
+#define ZT_PROTO_VERB_EXT_FRAME_IDX_FLAGS	   (ZT_PROTO_VERB_EXT_FRAME_IDX_NETWORK_ID + ZT_PROTO_VERB_EXT_FRAME_LEN_NETWORK_ID)
+#define ZT_PROTO_VERB_EXT_FRAME_LEN_FLAGS	   1
+#define ZT_PROTO_VERB_EXT_FRAME_IDX_COM		   (ZT_PROTO_VERB_EXT_FRAME_IDX_FLAGS + ZT_PROTO_VERB_EXT_FRAME_LEN_FLAGS)
+#define ZT_PROTO_VERB_EXT_FRAME_IDX_TO		   (ZT_PROTO_VERB_EXT_FRAME_IDX_FLAGS + ZT_PROTO_VERB_EXT_FRAME_LEN_FLAGS)
+#define ZT_PROTO_VERB_EXT_FRAME_LEN_TO		   6
+#define ZT_PROTO_VERB_EXT_FRAME_IDX_FROM	   (ZT_PROTO_VERB_EXT_FRAME_IDX_TO + ZT_PROTO_VERB_EXT_FRAME_LEN_TO)
+#define ZT_PROTO_VERB_EXT_FRAME_LEN_FROM	   6
+#define ZT_PROTO_VERB_EXT_FRAME_IDX_ETHERTYPE  (ZT_PROTO_VERB_EXT_FRAME_IDX_FROM + ZT_PROTO_VERB_EXT_FRAME_LEN_FROM)
+#define ZT_PROTO_VERB_EXT_FRAME_LEN_ETHERTYPE  2
+#define ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD	   (ZT_PROTO_VERB_EXT_FRAME_IDX_ETHERTYPE + ZT_PROTO_VERB_EXT_FRAME_LEN_ETHERTYPE)
 
 #define ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID (ZT_PACKET_IDX_PAYLOAD)
-#define ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN (ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID + 8)
-#define ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT (ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN + 2)
+#define ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN	(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID + 8)
+#define ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT		(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN + 2)
 
-#define ZT_PROTO_VERB_MULTICAST_GATHER_IDX_NETWORK_ID (ZT_PACKET_IDX_PAYLOAD)
-#define ZT_PROTO_VERB_MULTICAST_GATHER_IDX_FLAGS (ZT_PROTO_VERB_MULTICAST_GATHER_IDX_NETWORK_ID + 8)
-#define ZT_PROTO_VERB_MULTICAST_GATHER_IDX_MAC (ZT_PROTO_VERB_MULTICAST_GATHER_IDX_FLAGS + 1)
-#define ZT_PROTO_VERB_MULTICAST_GATHER_IDX_ADI (ZT_PROTO_VERB_MULTICAST_GATHER_IDX_MAC + 6)
+#define ZT_PROTO_VERB_MULTICAST_GATHER_IDX_NETWORK_ID	(ZT_PACKET_IDX_PAYLOAD)
+#define ZT_PROTO_VERB_MULTICAST_GATHER_IDX_FLAGS		(ZT_PROTO_VERB_MULTICAST_GATHER_IDX_NETWORK_ID + 8)
+#define ZT_PROTO_VERB_MULTICAST_GATHER_IDX_MAC			(ZT_PROTO_VERB_MULTICAST_GATHER_IDX_FLAGS + 1)
+#define ZT_PROTO_VERB_MULTICAST_GATHER_IDX_ADI			(ZT_PROTO_VERB_MULTICAST_GATHER_IDX_MAC + 6)
 #define ZT_PROTO_VERB_MULTICAST_GATHER_IDX_GATHER_LIMIT (ZT_PROTO_VERB_MULTICAST_GATHER_IDX_ADI + 4)
-#define ZT_PROTO_VERB_MULTICAST_GATHER_IDX_COM (ZT_PROTO_VERB_MULTICAST_GATHER_IDX_GATHER_LIMIT + 4)
+#define ZT_PROTO_VERB_MULTICAST_GATHER_IDX_COM			(ZT_PROTO_VERB_MULTICAST_GATHER_IDX_GATHER_LIMIT + 4)
 
 // Note: COM, GATHER_LIMIT, and SOURCE_MAC are optional, and so are specified without size
-#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID (ZT_PACKET_IDX_PAYLOAD)
-#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID + 8)
-#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_COM (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS + 1)
+#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID   (ZT_PACKET_IDX_PAYLOAD)
+#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS		   (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID + 8)
+#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_COM		   (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS + 1)
 #define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_GATHER_LIMIT (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS + 1)
-#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS + 1)
-#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_MAC (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS + 1)
-#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_ADI (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_MAC + 6)
-#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_ADI + 4)
-#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE + 2)
+#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC   (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS + 1)
+#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_MAC	   (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS + 1)
+#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_ADI	   (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_MAC + 6)
+#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE	   (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_ADI + 4)
+#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME		   (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE + 2)
 
-#define ZT_PROTO_VERB_HELLO__OK__IDX_TIMESTAMP (ZT_PROTO_VERB_OK_IDX_PAYLOAD)
+#define ZT_PROTO_VERB_HELLO__OK__IDX_TIMESTAMP		  (ZT_PROTO_VERB_OK_IDX_PAYLOAD)
 #define ZT_PROTO_VERB_HELLO__OK__IDX_PROTOCOL_VERSION (ZT_PROTO_VERB_HELLO__OK__IDX_TIMESTAMP + 8)
-#define ZT_PROTO_VERB_HELLO__OK__IDX_MAJOR_VERSION (ZT_PROTO_VERB_HELLO__OK__IDX_PROTOCOL_VERSION + 1)
-#define ZT_PROTO_VERB_HELLO__OK__IDX_MINOR_VERSION (ZT_PROTO_VERB_HELLO__OK__IDX_MAJOR_VERSION + 1)
-#define ZT_PROTO_VERB_HELLO__OK__IDX_REVISION (ZT_PROTO_VERB_HELLO__OK__IDX_MINOR_VERSION + 1)
+#define ZT_PROTO_VERB_HELLO__OK__IDX_MAJOR_VERSION	  (ZT_PROTO_VERB_HELLO__OK__IDX_PROTOCOL_VERSION + 1)
+#define ZT_PROTO_VERB_HELLO__OK__IDX_MINOR_VERSION	  (ZT_PROTO_VERB_HELLO__OK__IDX_MAJOR_VERSION + 1)
+#define ZT_PROTO_VERB_HELLO__OK__IDX_REVISION		  (ZT_PROTO_VERB_HELLO__OK__IDX_MINOR_VERSION + 1)
 
 #define ZT_PROTO_VERB_WHOIS__OK__IDX_IDENTITY (ZT_PROTO_VERB_OK_IDX_PAYLOAD)
 
 #define ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_NETWORK_ID (ZT_PROTO_VERB_OK_IDX_PAYLOAD)
-#define ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT_LEN (ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_NETWORK_ID + 8)
-#define ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT (ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT_LEN + 2)
+#define ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT_LEN	 (ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_NETWORK_ID + 8)
+#define ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT		 (ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT_LEN + 2)
 
-#define ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_NETWORK_ID (ZT_PROTO_VERB_OK_IDX_PAYLOAD)
-#define ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_MAC (ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_NETWORK_ID + 8)
-#define ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_ADI (ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_MAC + 6)
+#define ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_NETWORK_ID	   (ZT_PROTO_VERB_OK_IDX_PAYLOAD)
+#define ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_MAC			   (ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_NETWORK_ID + 8)
+#define ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_ADI			   (ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_MAC + 6)
 #define ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS (ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_ADI + 4)
 
-#define ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_NETWORK_ID (ZT_PROTO_VERB_OK_IDX_PAYLOAD)
-#define ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_MAC (ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_NETWORK_ID + 8)
-#define ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_ADI (ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_MAC + 6)
-#define ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_FLAGS (ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_ADI + 4)
+#define ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_NETWORK_ID			  (ZT_PROTO_VERB_OK_IDX_PAYLOAD)
+#define ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_MAC					  (ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_NETWORK_ID + 8)
+#define ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_ADI					  (ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_MAC + 6)
+#define ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_FLAGS				  (ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_ADI + 4)
 #define ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS (ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_FLAGS + 1)
 
 // ---------------------------------------------------------------------------
@@ -388,9 +386,8 @@ namespace ZeroTier {
  * For unencrypted packets, MAC is computed on plaintext. Only HELLO is ever
  * sent in the clear, as it's the "here is my public key" message.
  */
-class Packet : public Buffer<ZT_PROTO_MAX_PACKET_LENGTH>
-{
-public:
+class Packet : public Buffer<ZT_PROTO_MAX_PACKET_LENGTH> {
+  public:
 	/**
 	 * A packet fragment
 	 *
@@ -417,22 +414,17 @@ public:
 	 * receipt to authenticate and decrypt; there is no per-fragment MAC. (But if
 	 * fragments are corrupt, the MAC will fail for the whole assembled packet.)
 	 */
-	class Fragment : public Buffer<ZT_PROTO_MAX_PACKET_LENGTH>
-	{
-	public:
-		Fragment() :
-			Buffer<ZT_PROTO_MAX_PACKET_LENGTH>()
+	class Fragment : public Buffer<ZT_PROTO_MAX_PACKET_LENGTH> {
+	  public:
+		Fragment() : Buffer<ZT_PROTO_MAX_PACKET_LENGTH>()
 		{
 		}
 
-		template<unsigned int C2>
-		Fragment(const Buffer<C2> &b) :
-			Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(b)
+		template <unsigned int C2> Fragment(const Buffer<C2>& b) : Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(b)
 		{
 		}
 
-		Fragment(const void *data,unsigned int len) :
-			Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(data,len)
+		Fragment(const void* data, unsigned int len) : Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(data, len)
 		{
 		}
 
@@ -445,9 +437,9 @@ public:
 		 * @param fragNo Which fragment (>= 1, since 0 is Packet with end chopped off)
 		 * @param fragTotal Total number of fragments (including 0)
 		 */
-		Fragment(const Packet &p,unsigned int fragStart,unsigned int fragLen,unsigned int fragNo,unsigned int fragTotal)
+		Fragment(const Packet& p, unsigned int fragStart, unsigned int fragLen, unsigned int fragNo, unsigned int fragTotal)
 		{
-			init(p,fragStart,fragLen,fragNo,fragTotal);
+			init(p, fragStart, fragLen, fragNo, fragTotal);
 		}
 
 		/**
@@ -459,7 +451,7 @@ public:
 		 * @param fragNo Which fragment (>= 1, since 0 is Packet with end chopped off)
 		 * @param fragTotal Total number of fragments (including 0)
 		 */
-		inline void init(const Packet &p,unsigned int fragStart,unsigned int fragLen,unsigned int fragNo,unsigned int fragTotal)
+		inline void init(const Packet& p, unsigned int fragStart, unsigned int fragLen, unsigned int fragNo, unsigned int fragTotal)
 		{
 			if ((fragStart + fragLen) > p.size()) {
 				throw ZT_EXCEPTION_OUT_OF_BOUNDS;
@@ -467,13 +459,13 @@ public:
 			setSize(fragLen + ZT_PROTO_MIN_FRAGMENT_LENGTH);
 
 			// NOTE: this copies both the IV/packet ID and the destination address.
-			memcpy(field(ZT_PACKET_FRAGMENT_IDX_PACKET_ID,13),p.field(ZT_PACKET_IDX_IV,13),13);
+			memcpy(field(ZT_PACKET_FRAGMENT_IDX_PACKET_ID, 13), p.field(ZT_PACKET_IDX_IV, 13), 13);
 
 			(*this)[ZT_PACKET_FRAGMENT_IDX_FRAGMENT_INDICATOR] = ZT_PACKET_FRAGMENT_INDICATOR;
 			(*this)[ZT_PACKET_FRAGMENT_IDX_FRAGMENT_NO] = (char)(((fragTotal & 0xf) << 4) | (fragNo & 0xf));
 			(*this)[ZT_PACKET_FRAGMENT_IDX_HOPS] = 0;
 
-			memcpy(field(ZT_PACKET_FRAGMENT_IDX_PAYLOAD,fragLen),p.field(fragStart,fragLen),fragLen);
+			memcpy(field(ZT_PACKET_FRAGMENT_IDX_PAYLOAD, fragLen), p.field(fragStart, fragLen), fragLen);
 		}
 
 		/**
@@ -481,32 +473,50 @@ public:
 		 *
 		 * @return Destination ZT address
 		 */
-		inline Address destination() const { return Address(field(ZT_PACKET_FRAGMENT_IDX_DEST,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); }
+		inline Address destination() const
+		{
+			return Address(field(ZT_PACKET_FRAGMENT_IDX_DEST, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
+		}
 
 		/**
 		 * @return True if fragment is of a valid length
 		 */
-		inline bool lengthValid() const { return (size() >= ZT_PACKET_FRAGMENT_IDX_PAYLOAD); }
+		inline bool lengthValid() const
+		{
+			return (size() >= ZT_PACKET_FRAGMENT_IDX_PAYLOAD);
+		}
 
 		/**
 		 * @return ID of packet this is a fragment of
 		 */
-		inline uint64_t packetId() const { return at<uint64_t>(ZT_PACKET_FRAGMENT_IDX_PACKET_ID); }
+		inline uint64_t packetId() const
+		{
+			return at<uint64_t>(ZT_PACKET_FRAGMENT_IDX_PACKET_ID);
+		}
 
 		/**
 		 * @return Total number of fragments in packet
 		 */
-		inline unsigned int totalFragments() const { return (((unsigned int)((*this)[ZT_PACKET_FRAGMENT_IDX_FRAGMENT_NO]) >> 4) & 0xf); }
+		inline unsigned int totalFragments() const
+		{
+			return (((unsigned int)((*this)[ZT_PACKET_FRAGMENT_IDX_FRAGMENT_NO]) >> 4) & 0xf);
+		}
 
 		/**
 		 * @return Fragment number of this fragment
 		 */
-		inline unsigned int fragmentNumber() const { return ((unsigned int)((*this)[ZT_PACKET_FRAGMENT_IDX_FRAGMENT_NO]) & 0xf); }
+		inline unsigned int fragmentNumber() const
+		{
+			return ((unsigned int)((*this)[ZT_PACKET_FRAGMENT_IDX_FRAGMENT_NO]) & 0xf);
+		}
 
 		/**
 		 * @return Fragment ZT hop count
 		 */
-		inline unsigned int hops() const { return (unsigned int)((*this)[ZT_PACKET_FRAGMENT_IDX_HOPS]); }
+		inline unsigned int hops() const
+		{
+			return (unsigned int)((*this)[ZT_PACKET_FRAGMENT_IDX_HOPS]);
+		}
 
 		/**
 		 * Increment this packet's hop count
@@ -519,14 +529,17 @@ public:
 		/**
 		 * @return Length of payload in bytes
 		 */
-		inline unsigned int payloadLength() const { return ((size() > ZT_PACKET_FRAGMENT_IDX_PAYLOAD) ? (size() - ZT_PACKET_FRAGMENT_IDX_PAYLOAD) : 0); }
+		inline unsigned int payloadLength() const
+		{
+			return ((size() > ZT_PACKET_FRAGMENT_IDX_PAYLOAD) ? (size() - ZT_PACKET_FRAGMENT_IDX_PAYLOAD) : 0);
+		}
 
 		/**
 		 * @return Raw packet payload
 		 */
-		inline const unsigned char *payload() const
+		inline const unsigned char* payload() const
 		{
-			return field(ZT_PACKET_FRAGMENT_IDX_PAYLOAD,size() - ZT_PACKET_FRAGMENT_IDX_PAYLOAD);
+			return field(ZT_PACKET_FRAGMENT_IDX_PAYLOAD, size() - ZT_PACKET_FRAGMENT_IDX_PAYLOAD);
 		}
 	};
 
@@ -793,12 +806,12 @@ public:
 		 *
 		 * ERROR response payload:
 		 *   <[8] 64-bit network ID>
-     *   <[2] 16-bit length of error-related data (optional)>
-     *   <[...] error-related data (optional)>
-     * 
-     * Error related data is a Dictionary containing things like a URL
-     * for authentication or a human-readable error message, and is
-     * optional and may be absent or empty.
+		 *   <[2] 16-bit length of error-related data (optional)>
+		 *   <[...] error-related data (optional)>
+		 *
+		 * Error related data is a Dictionary containing things like a URL
+		 * for authentication or a human-readable error message, and is
+		 * optional and may be absent or empty.
 		 */
 		VERB_NETWORK_CONFIG_REQUEST = 0x0b,
 
@@ -1056,8 +1069,7 @@ public:
 	/**
 	 * Error codes for VERB_ERROR
 	 */
-	enum ErrorCode
-	{
+	enum ErrorCode {
 		/* No error, not actually used in transit */
 		ERROR_NONE = 0x00,
 
@@ -1085,18 +1097,15 @@ public:
 		/* Multicasts to this group are not wanted */
 		ERROR_UNWANTED_MULTICAST = 0x08,
 
-    /* Network requires external or 2FA authentication (e.g. SSO). */
-    ERROR_NETWORK_AUTHENTICATION_REQUIRED = 0x09
+		/* Network requires external or 2FA authentication (e.g. SSO). */
+		ERROR_NETWORK_AUTHENTICATION_REQUIRED = 0x09
 	};
 
-	template<unsigned int C2>
-	Packet(const Buffer<C2> &b) :
-		Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(b)
+	template <unsigned int C2> Packet(const Buffer<C2>& b) : Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(b)
 	{
 	}
 
-	Packet(const void *data,unsigned int len) :
-		Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(data,len)
+	Packet(const void* data, unsigned int len) : Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(data, len)
 	{
 	}
 
@@ -1107,11 +1116,10 @@ public:
 	 * Use the header access methods (setDestination() and friends) to fill out
 	 * the header. Payload should be appended; initial size is header size.
 	 */
-	Packet() :
-		Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(ZT_PROTO_MIN_PACKET_LENGTH)
+	Packet() : Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(ZT_PROTO_MIN_PACKET_LENGTH)
 	{
-		Utils::getSecureRandom(field(ZT_PACKET_IDX_IV,8),8);
-		(*this)[ZT_PACKET_IDX_FLAGS] = 0; // zero flags, cipher ID, and hops
+		Utils::getSecureRandom(field(ZT_PACKET_IDX_IV, 8), 8);
+		(*this)[ZT_PACKET_IDX_FLAGS] = 0;	// zero flags, cipher ID, and hops
 	}
 
 	/**
@@ -1123,10 +1131,9 @@ public:
 	 * @param prototype Prototype packet
 	 * @param dest Destination ZeroTier address for new packet
 	 */
-	Packet(const Packet &prototype,const Address &dest) :
-		Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(prototype)
+	Packet(const Packet& prototype, const Address& dest) : Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(prototype)
 	{
-		Utils::getSecureRandom(field(ZT_PACKET_IDX_IV,8),8);
+		Utils::getSecureRandom(field(ZT_PACKET_IDX_IV, 8), 8);
 		setDestination(dest);
 	}
 
@@ -1137,13 +1144,12 @@ public:
 	 * @param source Source ZT address
 	 * @param v Verb
 	 */
-	Packet(const Address &dest,const Address &source,const Verb v) :
-		Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(ZT_PROTO_MIN_PACKET_LENGTH)
+	Packet(const Address& dest, const Address& source, const Verb v) : Buffer<ZT_PROTO_MAX_PACKET_LENGTH>(ZT_PROTO_MIN_PACKET_LENGTH)
 	{
-		Utils::getSecureRandom(field(ZT_PACKET_IDX_IV,8),8);
+		Utils::getSecureRandom(field(ZT_PACKET_IDX_IV, 8), 8);
 		setDestination(dest);
 		setSource(source);
-		(*this)[ZT_PACKET_IDX_FLAGS] = 0; // zero flags and hops
+		(*this)[ZT_PACKET_IDX_FLAGS] = 0;	// zero flags and hops
 		setVerb(v);
 	}
 
@@ -1154,13 +1160,13 @@ public:
 	 * @param source Source ZT address
 	 * @param v Verb
 	 */
-	inline void reset(const Address &dest,const Address &source,const Verb v)
+	inline void reset(const Address& dest, const Address& source, const Verb v)
 	{
 		setSize(ZT_PROTO_MIN_PACKET_LENGTH);
-		Utils::getSecureRandom(field(ZT_PACKET_IDX_IV,8),8);
+		Utils::getSecureRandom(field(ZT_PACKET_IDX_IV, 8), 8);
 		setDestination(dest);
 		setSource(source);
-		(*this)[ZT_PACKET_IDX_FLAGS] = 0; // zero flags, cipher ID, and hops
+		(*this)[ZT_PACKET_IDX_FLAGS] = 0;	// zero flags, cipher ID, and hops
 		setVerb(v);
 	}
 
@@ -1171,45 +1177,66 @@ public:
 	 * technically different but otherwise identical copies of the same
 	 * packet.
 	 */
-	inline void newInitializationVector() { Utils::getSecureRandom(field(ZT_PACKET_IDX_IV,8),8); }
+	inline void newInitializationVector()
+	{
+		Utils::getSecureRandom(field(ZT_PACKET_IDX_IV, 8), 8);
+	}
 
 	/**
 	 * Set this packet's destination
 	 *
 	 * @param dest ZeroTier address of destination
 	 */
-	inline void setDestination(const Address &dest) { dest.copyTo(field(ZT_PACKET_IDX_DEST,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); }
+	inline void setDestination(const Address& dest)
+	{
+		dest.copyTo(field(ZT_PACKET_IDX_DEST, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
+	}
 
 	/**
 	 * Set this packet's source
 	 *
 	 * @param source ZeroTier address of source
 	 */
-	inline void setSource(const Address &source) { source.copyTo(field(ZT_PACKET_IDX_SOURCE,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); }
+	inline void setSource(const Address& source)
+	{
+		source.copyTo(field(ZT_PACKET_IDX_SOURCE, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
+	}
 
 	/**
 	 * Get this packet's destination
 	 *
 	 * @return Destination ZT address
 	 */
-	inline Address destination() const { return Address(field(ZT_PACKET_IDX_DEST,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); }
+	inline Address destination() const
+	{
+		return Address(field(ZT_PACKET_IDX_DEST, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
+	}
 
 	/**
 	 * Get this packet's source
 	 *
 	 * @return Source ZT address
 	 */
-	inline Address source() const { return Address(field(ZT_PACKET_IDX_SOURCE,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); }
+	inline Address source() const
+	{
+		return Address(field(ZT_PACKET_IDX_SOURCE, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
+	}
 
 	/**
 	 * @return True if packet is of valid length
 	 */
-	inline bool lengthValid() const { return (size() >= ZT_PROTO_MIN_PACKET_LENGTH); }
+	inline bool lengthValid() const
+	{
+		return (size() >= ZT_PROTO_MIN_PACKET_LENGTH);
+	}
 
 	/**
 	 * @return True if packet is fragmented (expect fragments)
 	 */
-	inline bool fragmented() const { return (((unsigned char)(*this)[ZT_PACKET_IDX_FLAGS] & ZT_PROTO_FLAG_FRAGMENTED) != 0); }
+	inline bool fragmented() const
+	{
+		return (((unsigned char)(*this)[ZT_PACKET_IDX_FLAGS] & ZT_PROTO_FLAG_FRAGMENTED) != 0);
+	}
 
 	/**
 	 * Set this packet's fragmented flag
@@ -1220,7 +1247,8 @@ public:
 	{
 		if (f) {
 			(*this)[ZT_PACKET_IDX_FLAGS] |= (char)ZT_PROTO_FLAG_FRAGMENTED;
-		} else {
+		}
+		else {
 			(*this)[ZT_PACKET_IDX_FLAGS] &= (char)(~ZT_PROTO_FLAG_FRAGMENTED);
 		}
 	}
@@ -1228,19 +1256,25 @@ public:
 	/**
 	 * @return True if compressed (result only valid if unencrypted)
 	 */
-	inline bool compressed() const { return (((unsigned char)(*this)[ZT_PACKET_IDX_VERB] & ZT_PROTO_VERB_FLAG_COMPRESSED) != 0); }
+	inline bool compressed() const
+	{
+		return (((unsigned char)(*this)[ZT_PACKET_IDX_VERB] & ZT_PROTO_VERB_FLAG_COMPRESSED) != 0);
+	}
 
 	/**
 	 * @return ZeroTier forwarding hops (0 to 7)
 	 */
-	inline unsigned int hops() const { return ((unsigned int)(*this)[ZT_PACKET_IDX_FLAGS] & 0x07); }
+	inline unsigned int hops() const
+	{
+		return ((unsigned int)(*this)[ZT_PACKET_IDX_FLAGS] & 0x07);
+	}
 
 	/**
 	 * Increment this packet's hop count
 	 */
 	inline void incrementHops()
 	{
-		unsigned char &b = (*this)[ZT_PACKET_IDX_FLAGS];
+		unsigned char& b = (*this)[ZT_PACKET_IDX_FLAGS];
 		b = (b & 0xf8) | ((b + 1) & 0x07);
 	}
 
@@ -1265,12 +1299,13 @@ public:
 	 */
 	inline void setCipher(unsigned int c)
 	{
-		unsigned char &b = (*this)[ZT_PACKET_IDX_FLAGS];
-		b = (b & 0xc7) | (unsigned char)((c << 3) & 0x38); // bits: FFCCCHHH
+		unsigned char& b = (*this)[ZT_PACKET_IDX_FLAGS];
+		b = (b & 0xc7) | (unsigned char)((c << 3) & 0x38);	 // bits: FFCCCHHH
 		// Set DEPRECATED "encrypted" flag -- used by pre-1.0.3 peers
 		if (c == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012) {
 			b |= ZT_PROTO_FLAG_ENCRYPTED;
-		} else {
+		}
+		else {
 			b &= (~ZT_PROTO_FLAG_ENCRYPTED);
 		}
 	}
@@ -1280,7 +1315,10 @@ public:
 	 *
 	 * @return Trusted path ID (from MAC field)
 	 */
-	inline uint64_t trustedPathId() const { return at<uint64_t>(ZT_PACKET_IDX_MAC); }
+	inline uint64_t trustedPathId() const
+	{
+		return at<uint64_t>(ZT_PACKET_IDX_MAC);
+	}
 
 	/**
 	 * Set this packet's trusted path ID and set the cipher spec to trusted path
@@ -1290,7 +1328,7 @@ public:
 	inline void setTrusted(const uint64_t tpid)
 	{
 		setCipher(ZT_PROTO_CIPHER_SUITE__NO_CRYPTO_TRUSTED_PATH);
-		setAt(ZT_PACKET_IDX_MAC,tpid);
+		setAt(ZT_PACKET_IDX_MAC, tpid);
 	}
 
 	/**
@@ -1304,7 +1342,10 @@ public:
 	 *
 	 * @return Packet ID
 	 */
-	inline uint64_t packetId() const { return at<uint64_t>(ZT_PACKET_IDX_IV); }
+	inline uint64_t packetId() const
+	{
+		return at<uint64_t>(ZT_PACKET_IDX_IV);
+	}
 
 	/**
 	 * Set packet verb
@@ -1314,22 +1355,34 @@ public:
 	 *
 	 * @param v New packet verb
 	 */
-	inline void setVerb(Verb v) { (*this)[ZT_PACKET_IDX_VERB] = (char)v; }
+	inline void setVerb(Verb v)
+	{
+		(*this)[ZT_PACKET_IDX_VERB] = (char)v;
+	}
 
 	/**
 	 * @return Packet verb (not including flag bits)
 	 */
-	inline Verb verb() const { return (Verb)((*this)[ZT_PACKET_IDX_VERB] & 0x1f); }
+	inline Verb verb() const
+	{
+		return (Verb)((*this)[ZT_PACKET_IDX_VERB] & 0x1f);
+	}
 
 	/**
 	 * @return Length of packet payload
 	 */
-	inline unsigned int payloadLength() const { return ((size() < ZT_PROTO_MIN_PACKET_LENGTH) ? 0 : (size() - ZT_PROTO_MIN_PACKET_LENGTH)); }
+	inline unsigned int payloadLength() const
+	{
+		return ((size() < ZT_PROTO_MIN_PACKET_LENGTH) ? 0 : (size() - ZT_PROTO_MIN_PACKET_LENGTH));
+	}
 
 	/**
 	 * @return Raw packet payload
 	 */
-	inline const unsigned char *payload() const { return field(ZT_PACKET_IDX_PAYLOAD,size() - ZT_PACKET_IDX_PAYLOAD); }
+	inline const unsigned char* payload() const
+	{
+		return field(ZT_PACKET_IDX_PAYLOAD, size() - ZT_PACKET_IDX_PAYLOAD);
+	}
 
 	/**
 	 * Armor packet for transport
@@ -1338,7 +1391,7 @@ public:
 	 * @param encryptPayload If true, encrypt packet payload, else just MAC
 	 * @param aesKeys If non-NULL these are the two keys for AES-GMAC-SIV
 	 */
-	void armor(const void *key,bool encryptPayload,const AES aesKeys[2]);
+	void armor(const void* key, bool encryptPayload, const AES aesKeys[2]);
 
 	/**
 	 * Verify and (if encrypted) decrypt packet
@@ -1351,7 +1404,7 @@ public:
 	 * @param aesKeys If non-NULL these are the two keys for AES-GMAC-SIV
 	 * @return False if packet is invalid or failed MAC authenticity check
 	 */
-	bool dearmor(const void *key,const AES aesKeys[2]);
+	bool dearmor(const void* key, const AES aesKeys[2]);
 
 	/**
 	 * Encrypt/decrypt a separately armored portion of a packet
@@ -1366,7 +1419,7 @@ public:
 	 * @param start Start of encrypted portion
 	 * @param len Length of encrypted portion
 	 */
-	void cryptField(const void *key,unsigned int start,unsigned int len);
+	void cryptField(const void* key, unsigned int start, unsigned int len);
 
 	/**
 	 * Attempt to compress payload if not already (must be unencrypted)
@@ -1390,7 +1443,7 @@ public:
 	 */
 	bool uncompress();
 
-private:
+  private:
 	static const unsigned char ZERO_KEY[32];
 
 	/**
@@ -1404,13 +1457,13 @@ private:
 	 * @param in Input key (32 bytes)
 	 * @param out Output buffer (32 bytes)
 	 */
-	inline void _salsa20MangleKey(const unsigned char *in,unsigned char *out) const
+	inline void _salsa20MangleKey(const unsigned char* in, unsigned char* out) const
 	{
-		const unsigned char *d = (const unsigned char *)data();
+		const unsigned char* d = (const unsigned char*)data();
 
 		// IV and source/destination addresses. Using the addresses divides the
 		// key space into two halves-- A->B and B->A (since order will change).
-		for(unsigned int i=0;i<18;++i) { // 8 + (ZT_ADDRESS_LENGTH * 2) == 18
+		for (unsigned int i = 0; i < 18; ++i) {	  // 8 + (ZT_ADDRESS_LENGTH * 2) == 18
 			out[i] = in[i] ^ d[i];
 		}
 
@@ -1422,15 +1475,15 @@ private:
 		// Raw packet size in bytes -- thus each packet size defines a new
 		// key space.
 		out[19] = in[19] ^ (unsigned char)(size() & 0xff);
-		out[20] = in[20] ^ (unsigned char)((size() >> 8) & 0xff); // little endian
+		out[20] = in[20] ^ (unsigned char)((size() >> 8) & 0xff);	// little endian
 
 		// Rest of raw key is used unchanged
-		for(unsigned int i=21;i<32;++i) {
+		for (unsigned int i = 21; i < 32; ++i) {
 			out[i] = in[i];
 		}
 	}
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 4 - 4
node/PacketMultiplexer.cpp

@@ -13,9 +13,9 @@
 
 #include "PacketMultiplexer.hpp"
 
+#include "Constants.hpp"
 #include "Node.hpp"
 #include "RuntimeEnvironment.hpp"
-#include "Constants.hpp"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -30,12 +30,12 @@ PacketMultiplexer::PacketMultiplexer(const RuntimeEnvironment* renv)
 void PacketMultiplexer::putFrame(void* tPtr, uint64_t nwid, void** nuptr, const MAC& source, const MAC& dest, unsigned int etherType, unsigned int vlanId, const void* data, unsigned int len, unsigned int flowId)
 {
 #if defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__WINDOWS__)
-	RR->node->putFrame(tPtr,nwid,nuptr,source,dest,etherType,vlanId,(const void *)data,len);
+	RR->node->putFrame(tPtr, nwid, nuptr, source, dest, etherType, vlanId, (const void*)data, len);
 	return;
 #endif
 
-	if (!_enabled) {
-		RR->node->putFrame(tPtr,nwid,nuptr,source,dest,etherType,vlanId,(const void *)data,len);
+	if (! _enabled) {
+		RR->node->putFrame(tPtr, nwid, nuptr, source, dest, etherType, vlanId, (const void*)data, len);
 		return;
 	}
 

+ 5 - 4
node/Path.cpp

@@ -12,18 +12,19 @@
 /****/
 
 #include "Path.hpp"
-#include "RuntimeEnvironment.hpp"
+
 #include "Node.hpp"
+#include "RuntimeEnvironment.hpp"
 
 namespace ZeroTier {
 
-bool Path::send(const RuntimeEnvironment *RR,void *tPtr,const void *data,unsigned int len,int64_t now)
+bool Path::send(const RuntimeEnvironment* RR, void* tPtr, const void* data, unsigned int len, int64_t now)
 {
-	if (RR->node->putPacket(tPtr,_localSocket,_addr,data,len)) {
+	if (RR->node->putPacket(tPtr, _localSocket, _addr, data, len)) {
 		_lastOut = now;
 		return true;
 	}
 	return false;
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier

+ 200 - 114
node/Path.hpp

@@ -14,20 +14,19 @@
 #ifndef ZT_PATH_HPP
 #define ZT_PATH_HPP
 
-#include <stdint.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <stdexcept>
-#include <algorithm>
-
+#include "AtomicCounter.hpp"
 #include "Constants.hpp"
 #include "InetAddress.hpp"
-#include "SharedPtr.hpp"
-#include "AtomicCounter.hpp"
-#include "Utils.hpp"
 #include "Packet.hpp"
 #include "RingBuffer.hpp"
+#include "SharedPtr.hpp"
+#include "Utils.hpp"
+
+#include <algorithm>
+#include <stdexcept>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
 
 /**
  * Maximum return value of preferenceRank()
@@ -41,89 +40,102 @@ class RuntimeEnvironment;
 /**
  * A path across the physical network
  */
-class Path
-{
+class Path {
 	friend class SharedPtr<Path>;
 	friend class Bond;
 
-public:
+  public:
 	/**
 	 * Efficient unique key for paths in a Hashtable
 	 */
-	class HashKey
-	{
-	public:
-		HashKey() {}
+	class HashKey {
+	  public:
+		HashKey()
+		{
+		}
 
-		HashKey(const int64_t l,const InetAddress &r)
+		HashKey(const int64_t l, const InetAddress& r)
 		{
 			if (r.ss_family == AF_INET) {
-				_k[0] = (uint64_t)reinterpret_cast<const struct sockaddr_in *>(&r)->sin_addr.s_addr;
-				_k[1] = (uint64_t)reinterpret_cast<const struct sockaddr_in *>(&r)->sin_port;
+				_k[0] = (uint64_t)reinterpret_cast<const struct sockaddr_in*>(&r)->sin_addr.s_addr;
+				_k[1] = (uint64_t)reinterpret_cast<const struct sockaddr_in*>(&r)->sin_port;
 				_k[2] = (uint64_t)l;
-			} else if (r.ss_family == AF_INET6) {
-				memcpy(_k,reinterpret_cast<const struct sockaddr_in6 *>(&r)->sin6_addr.s6_addr,16);
-				_k[2] = ((uint64_t)reinterpret_cast<const struct sockaddr_in6 *>(&r)->sin6_port << 32) ^ (uint64_t)l;
-			} else {
-				memcpy(_k,&r,std::min(sizeof(_k),sizeof(InetAddress)));
+			}
+			else if (r.ss_family == AF_INET6) {
+				memcpy(_k, reinterpret_cast<const struct sockaddr_in6*>(&r)->sin6_addr.s6_addr, 16);
+				_k[2] = ((uint64_t)reinterpret_cast<const struct sockaddr_in6*>(&r)->sin6_port << 32) ^ (uint64_t)l;
+			}
+			else {
+				memcpy(_k, &r, std::min(sizeof(_k), sizeof(InetAddress)));
 				_k[2] += (uint64_t)l;
 			}
 		}
 
-		inline unsigned long hashCode() const { return (unsigned long)(_k[0] + _k[1] + _k[2]); }
+		inline unsigned long hashCode() const
+		{
+			return (unsigned long)(_k[0] + _k[1] + _k[2]);
+		}
 
-		inline bool operator==(const HashKey &k) const { return ( (_k[0] == k._k[0]) && (_k[1] == k._k[1]) && (_k[2] == k._k[2]) ); }
-		inline bool operator!=(const HashKey &k) const { return (!(*this == k)); }
+		inline bool operator==(const HashKey& k) const
+		{
+			return ((_k[0] == k._k[0]) && (_k[1] == k._k[1]) && (_k[2] == k._k[2]));
+		}
+		inline bool operator!=(const HashKey& k) const
+		{
+			return (! (*this == k));
+		}
 
-	private:
+	  private:
 		uint64_t _k[3];
 	};
 
-	Path() :
-		_lastOut(0),
-		_lastIn(0),
-		_lastTrustEstablishedPacketReceived(0),
-		_lastEchoRequestReceived(0),
-		_localPort(0),
-		_localSocket(-1),
-		_latencyMean(0.0),
-		_latencyVariance(0.0),
-		_packetLossRatio(0.0),
-		_packetErrorRatio(0.0),
-		_assignedFlowCount(0),
-		_valid(true),
-		_eligible(false),
-		_bonded(false),
-		_mtu(0),
-		_givenLinkSpeed(0),
-		_relativeQuality(0),
-		_latency(0xffff),
-		_addr(),
-		_ipScope(InetAddress::IP_SCOPE_NONE)
-		{}
-
-	Path(const int64_t localSocket,const InetAddress &addr) :
-		_lastOut(0),
-		_lastIn(0),
-		_lastTrustEstablishedPacketReceived(0),
-		_lastEchoRequestReceived(0),
-		_localPort(0),
-		_localSocket(localSocket),
-		_latencyMean(0.0),
-		_latencyVariance(0.0),
-		_packetLossRatio(0.0),
-		_packetErrorRatio(0.0),
-		_assignedFlowCount(0),
-		_valid(true),
-		_eligible(false),
-		_bonded(false),
-		_mtu(0),
-		_givenLinkSpeed(0),
-		_relativeQuality(0),
-		_latency(0xffff),
-		_addr(addr),
-		_ipScope(addr.ipScope())
-	{}
+	Path()
+		: _lastOut(0)
+		, _lastIn(0)
+		, _lastTrustEstablishedPacketReceived(0)
+		, _lastEchoRequestReceived(0)
+		, _localPort(0)
+		, _localSocket(-1)
+		, _latencyMean(0.0)
+		, _latencyVariance(0.0)
+		, _packetLossRatio(0.0)
+		, _packetErrorRatio(0.0)
+		, _assignedFlowCount(0)
+		, _valid(true)
+		, _eligible(false)
+		, _bonded(false)
+		, _mtu(0)
+		, _givenLinkSpeed(0)
+		, _relativeQuality(0)
+		, _latency(0xffff)
+		, _addr()
+		, _ipScope(InetAddress::IP_SCOPE_NONE)
+	{
+	}
+
+	Path(const int64_t localSocket, const InetAddress& addr)
+		: _lastOut(0)
+		, _lastIn(0)
+		, _lastTrustEstablishedPacketReceived(0)
+		, _lastEchoRequestReceived(0)
+		, _localPort(0)
+		, _localSocket(localSocket)
+		, _latencyMean(0.0)
+		, _latencyVariance(0.0)
+		, _packetLossRatio(0.0)
+		, _packetErrorRatio(0.0)
+		, _assignedFlowCount(0)
+		, _valid(true)
+		, _eligible(false)
+		, _bonded(false)
+		, _mtu(0)
+		, _givenLinkSpeed(0)
+		, _relativeQuality(0)
+		, _latency(0xffff)
+		, _addr(addr)
+		, _ipScope(addr.ipScope())
+	{
+	}
 
 	/**
 	 * Called when a packet is received from this remote path, regardless of content
@@ -138,7 +150,10 @@ public:
 	/**
 	 * Set time last trusted packet was received (done in Peer::received())
 	 */
-	inline void trustedPacketReceived(const uint64_t t) { _lastTrustEstablishedPacketReceived = t; }
+	inline void trustedPacketReceived(const uint64_t t)
+	{
+		_lastTrustEstablishedPacketReceived = t;
+	}
 
 	/**
 	 * Send a packet via this path (last out time is also updated)
@@ -150,14 +165,17 @@ public:
 	 * @param now Current time
 	 * @return True if transport reported success
 	 */
-	bool send(const RuntimeEnvironment *RR,void *tPtr,const void *data,unsigned int len,int64_t now);
+	bool send(const RuntimeEnvironment* RR, void* tPtr, const void* data, unsigned int len, int64_t now);
 
 	/**
 	 * Manually update last sent time
 	 *
 	 * @param t Time of send
 	 */
-	inline void sent(const int64_t t) { _lastOut = t; }
+	inline void sent(const int64_t t)
+	{
+		_lastOut = t;
+	}
 
 	/**
 	 * Update path latency with a new measurement
@@ -169,7 +187,8 @@ public:
 		unsigned int pl = _latency;
 		if (pl < 0xffff) {
 			_latency = (pl + l) / 2;
-		} else {
+		}
+		else {
 			_latency = l;
 		}
 	}
@@ -177,27 +196,42 @@ public:
 	/**
 	 * @return Local socket as specified by external code
 	 */
-	inline int64_t localSocket() const { return _localSocket; }
+	inline int64_t localSocket() const
+	{
+		return _localSocket;
+	}
 
 	/**
 	 * @return Local port corresponding to the localSocket
 	 */
-	inline int64_t localPort() const { return _localPort; }
+	inline int64_t localPort() const
+	{
+		return _localPort;
+	}
 
 	/**
 	 * @return Physical address
 	 */
-	inline const InetAddress &address() const { return _addr; }
+	inline const InetAddress& address() const
+	{
+		return _addr;
+	}
 
 	/**
 	 * @return IP scope -- faster shortcut for address().ipScope()
 	 */
-	inline InetAddress::IpScope ipScope() const { return _ipScope; }
+	inline InetAddress::IpScope ipScope() const
+	{
+		return _ipScope;
+	}
 
 	/**
 	 * @return True if path has received a trust established packet (e.g. common network membership) in the past ZT_TRUST_EXPIRATION ms
 	 */
-	inline bool trustEstablished(const int64_t now) const { return ((now - _lastTrustEstablishedPacketReceived) < ZT_TRUST_EXPIRATION); }
+	inline bool trustEstablished(const int64_t now) const
+	{
+		return ((now - _lastTrustEstablishedPacketReceived) < ZT_TRUST_EXPIRATION);
+	}
 
 	/**
 	 * @return Preference rank, higher == better
@@ -206,7 +240,7 @@ public:
 	{
 		// This causes us to rank paths in order of IP scope rank (see InetAddress.hpp) but
 		// within each IP scope class to prefer IPv6 over IPv4.
-		return ( ((unsigned int)_ipScope << 1) | (unsigned int)(_addr.ss_family == AF_INET6) );
+		return (((unsigned int)_ipScope << 1) | (unsigned int)(_addr.ss_family == AF_INET6));
 	}
 
 	/**
@@ -218,10 +252,10 @@ public:
 	 * @param a Address to check
 	 * @return True if address is good for ZeroTier path use
 	 */
-	static inline bool isAddressValidForPath(const InetAddress &a)
+	static inline bool isAddressValidForPath(const InetAddress& a)
 	{
-		if ((a.ss_family == AF_INET)||(a.ss_family == AF_INET6)) {
-			switch(a.ipScope()) {
+		if ((a.ss_family == AF_INET) || (a.ss_family == AF_INET6)) {
+			switch (a.ipScope()) {
 				/* Note: we don't do link-local at the moment. Unfortunately these
 				 * cause several issues. The first is that they usually require a
 				 * device qualifier, which we don't handle yet and can't portably
@@ -237,8 +271,8 @@ public:
 						// TEMPORARY HACK: for now, we are going to blacklist he.net IPv6
 						// tunnels due to very spotty performance and low MTU issues over
 						// these IPv6 tunnel links.
-						const uint8_t *ipd = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_addr.s6_addr);
-						if ((ipd[0] == 0x20)&&(ipd[1] == 0x01)&&(ipd[2] == 0x04)&&(ipd[3] == 0x70)) {
+						const uint8_t* ipd = reinterpret_cast<const uint8_t*>(reinterpret_cast<const struct sockaddr_in6*>(&a)->sin6_addr.s6_addr);
+						if ((ipd[0] == 0x20) && (ipd[1] == 0x01) && (ipd[2] == 0x04) && (ipd[3] == 0x70)) {
 							return false;
 						}
 					}
@@ -253,7 +287,10 @@ public:
 	/**
 	 * @return Latency or 0xffff if unknown
 	 */
-	inline unsigned int latency() const { return _latency; }
+	inline unsigned int latency() const
+	{
+		return _latency;
+	}
 
 	/**
 	 * @return Path quality -- lower is better
@@ -261,41 +298,57 @@ public:
 	inline long quality(const int64_t now) const
 	{
 		const int l = (long)_latency;
-		const int age = (long)std::min((now - _lastIn),(int64_t)(ZT_PATH_HEARTBEAT_PERIOD * 10)); // set an upper sanity limit to avoid overflow
+		const int age = (long)std::min((now - _lastIn), (int64_t)(ZT_PATH_HEARTBEAT_PERIOD * 10));	 // set an upper sanity limit to avoid overflow
 		return (((age < (ZT_PATH_HEARTBEAT_PERIOD + 5000)) ? l : (l + 0xffff + age)) * (long)((ZT_INETADDRESS_MAX_SCOPE - _ipScope) + 1));
 	}
 
 	/**
 	 * @return True if this path is alive (receiving heartbeats)
 	 */
-	inline bool alive(const int64_t now) const {
+	inline bool alive(const int64_t now) const
+	{
 		return (now - _lastIn) < (ZT_PATH_HEARTBEAT_PERIOD + 5000);
 	}
 
 	/**
 	 * @return True if this path needs a heartbeat
 	 */
-	inline bool needsHeartbeat(const int64_t now) const { return ((now - _lastOut) >= ZT_PATH_HEARTBEAT_PERIOD); }
+	inline bool needsHeartbeat(const int64_t now) const
+	{
+		return ((now - _lastOut) >= ZT_PATH_HEARTBEAT_PERIOD);
+	}
 
 	/**
 	 * @return Last time we sent something
 	 */
-	inline int64_t lastOut() const { return _lastOut; }
+	inline int64_t lastOut() const
+	{
+		return _lastOut;
+	}
 
 	/**
 	 * @return Last time we received anything
 	 */
-	inline int64_t lastIn() const { return _lastIn; }
+	inline int64_t lastIn() const
+	{
+		return _lastIn;
+	}
 
 	/**
 	 * @return the age of the path in terms of receiving packets
 	 */
-	inline int64_t age(int64_t now) { return (now - _lastIn); }
+	inline int64_t age(int64_t now)
+	{
+		return (now - _lastIn);
+	}
 
 	/**
 	 * @return Time last trust-established packet was received
 	 */
-	inline int64_t lastTrustEstablishedPacketReceived() const { return _lastTrustEstablishedPacketReceived; }
+	inline int64_t lastTrustEstablishedPacketReceived() const
+	{
+		return _lastTrustEstablishedPacketReceived;
+	}
 
 	/**
 	 * Rate limit gate for inbound ECHO requests
@@ -312,69 +365,102 @@ public:
 	/**
 	 * @return Mean latency as reported by the bonding layer
 	 */
-	inline float latencyMean() const { return _latencyMean; }
+	inline float latencyMean() const
+	{
+		return _latencyMean;
+	}
 
 	/**
 	 * @return Latency variance as reported by the bonding layer
 	 */
-	inline float latencyVariance() const { return _latencyVariance; }
+	inline float latencyVariance() const
+	{
+		return _latencyVariance;
+	}
 
 	/**
 	 * @return Packet Loss Ratio as reported by the bonding layer
 	 */
-	inline float packetLossRatio() const { return _packetLossRatio; }
+	inline float packetLossRatio() const
+	{
+		return _packetLossRatio;
+	}
 
 	/**
 	 * @return Packet Error Ratio as reported by the bonding layer
 	 */
-	inline float packetErrorRatio() const { return _packetErrorRatio; }
+	inline float packetErrorRatio() const
+	{
+		return _packetErrorRatio;
+	}
 
 	/**
 	 * @return Number of flows assigned to this path
 	 */
-	inline unsigned int assignedFlowCount() const { return _assignedFlowCount; }
+	inline unsigned int assignedFlowCount() const
+	{
+		return _assignedFlowCount;
+	}
 
 	/**
 	 * @return Whether this path is valid as reported by the bonding layer. The bonding layer
 	 * actually checks with Phy to see if the interface is still up
 	 */
-	inline bool valid() const { return _valid; }
+	inline bool valid() const
+	{
+		return _valid;
+	}
 
 	/**
 	 * @return Whether this path is eligible for use in a bond as reported by the bonding layer
 	 */
-	inline bool eligible() const { return _eligible; }
+	inline bool eligible() const
+	{
+		return _eligible;
+	}
 
 	/**
 	 * @return Whether this path is bonded as reported by the bonding layer
 	 */
-	inline bool bonded() const { return _bonded; }
+	inline bool bonded() const
+	{
+		return _bonded;
+	}
 
 	/**
 	 * @return Whether the user-specified MTU for this path (determined by MTU for parent link)
 	 */
-	inline uint16_t mtu() const { return _mtu; }
+	inline uint16_t mtu() const
+	{
+		return _mtu;
+	}
 
 	/**
 	 * @return Given link capacity as reported by the bonding layer
 	 */
-	inline uint32_t givenLinkSpeed() const { return _givenLinkSpeed; }
+	inline uint32_t givenLinkSpeed() const
+	{
+		return _givenLinkSpeed;
+	}
 
 	/**
 	 * @return Path's quality as reported by the bonding layer
 	 */
-	inline float relativeQuality() const { return _relativeQuality; }
+	inline float relativeQuality() const
+	{
+		return _relativeQuality;
+	}
 
 	/**
 	 * @return Physical interface name that this path lives on
 	 */
-	char *ifname() {
+	char* ifname()
+	{
 		return _ifname;
 	}
 
-private:
-
-	char _ifname[ZT_MAX_PHYSIFNAME] = { };
+  private:
+	char _ifname[ZT_MAX_PHYSIFNAME] = {};
 
 	volatile int64_t _lastOut;
 	volatile int64_t _lastIn;
@@ -399,10 +485,10 @@ private:
 
 	volatile unsigned int _latency;
 	InetAddress _addr;
-	InetAddress::IpScope _ipScope; // memoize this since it's a computed value checked often
+	InetAddress::IpScope _ipScope;	 // memoize this since it's a computed value checked often
 	AtomicCounter __refCount;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 157 - 141
node/Peer.cpp

@@ -11,24 +11,25 @@
  */
 /****/
 
+#include "Peer.hpp"
+
 #include "../version.h"
 #include "Constants.hpp"
-#include "Peer.hpp"
-#include "Switch.hpp"
+#include "InetAddress.hpp"
+#include "Metrics.hpp"
 #include "Network.hpp"
-#include "SelfAwareness.hpp"
 #include "Packet.hpp"
-#include "Trace.hpp"
-#include "InetAddress.hpp"
 #include "RingBuffer.hpp"
+#include "SelfAwareness.hpp"
+#include "Switch.hpp"
+#include "Trace.hpp"
 #include "Utils.hpp"
-#include "Metrics.hpp"
 
 namespace ZeroTier {
 
 static unsigned char s_freeRandomByteCounter = 0;
 
-Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Identity &peerIdentity)
+Peer::Peer(const RuntimeEnvironment* renv, const Identity& myIdentity, const Identity& peerIdentity)
 	: RR(renv)
 	, _lastReceive(0)
 	, _lastNontrivialReceive(0)
@@ -52,29 +53,29 @@ Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Ident
 	, _localMultipathSupported(false)
 	, _lastComputedAggregateMeanLatency(0)
 #ifndef ZT_NO_PEER_METRICS
-	, _peer_latency{Metrics::peer_latency.Add({{"node_id", OSUtils::nodeIDStr(peerIdentity.address().toInt())}}, std::vector<uint64_t>{1,3,6,10,30,60,100,300,600,1000})}
-	, _alive_path_count{Metrics::peer_path_count.Add({{"node_id", OSUtils::nodeIDStr(peerIdentity.address().toInt())},{"status","alive"}})}
-	, _dead_path_count{Metrics::peer_path_count.Add({{"node_id", OSUtils::nodeIDStr(peerIdentity.address().toInt())},{"status","dead"}})}
-	, _incoming_packet{Metrics::peer_packets.Add({{"direction", "rx"},{"node_id", OSUtils::nodeIDStr(peerIdentity.address().toInt())}})}
-	, _outgoing_packet{Metrics::peer_packets.Add({{"direction", "tx"},{"node_id", OSUtils::nodeIDStr(peerIdentity.address().toInt())}})}
-	, _packet_errors{Metrics::peer_packet_errors.Add({{"node_id", OSUtils::nodeIDStr(peerIdentity.address().toInt())}})}
+	, _peer_latency { Metrics::peer_latency.Add({ { "node_id", OSUtils::nodeIDStr(peerIdentity.address().toInt()) } }, std::vector<uint64_t> { 1, 3, 6, 10, 30, 60, 100, 300, 600, 1000 }) }
+	, _alive_path_count { Metrics::peer_path_count.Add({ { "node_id", OSUtils::nodeIDStr(peerIdentity.address().toInt()) }, { "status", "alive" } }) }
+	, _dead_path_count { Metrics::peer_path_count.Add({ { "node_id", OSUtils::nodeIDStr(peerIdentity.address().toInt()) }, { "status", "dead" } }) }
+	, _incoming_packet { Metrics::peer_packets.Add({ { "direction", "rx" }, { "node_id", OSUtils::nodeIDStr(peerIdentity.address().toInt()) } }) }
+	, _outgoing_packet { Metrics::peer_packets.Add({ { "direction", "tx" }, { "node_id", OSUtils::nodeIDStr(peerIdentity.address().toInt()) } }) }
+	, _packet_errors { Metrics::peer_packet_errors.Add({ { "node_id", OSUtils::nodeIDStr(peerIdentity.address().toInt()) } }) }
 #endif
 {
-	if (!myIdentity.agree(peerIdentity,_key)) {
+	if (! myIdentity.agree(peerIdentity, _key)) {
 		throw ZT_EXCEPTION_INVALID_ARGUMENT;
 	}
 
 	uint8_t ktmp[ZT_SYMMETRIC_KEY_SIZE];
-	KBKDFHMACSHA384(_key,ZT_KBKDF_LABEL_AES_GMAC_SIV_K0,0,0,ktmp);
+	KBKDFHMACSHA384(_key, ZT_KBKDF_LABEL_AES_GMAC_SIV_K0, 0, 0, ktmp);
 	_aesKeys[0].init(ktmp);
-	KBKDFHMACSHA384(_key,ZT_KBKDF_LABEL_AES_GMAC_SIV_K1,0,0,ktmp);
+	KBKDFHMACSHA384(_key, ZT_KBKDF_LABEL_AES_GMAC_SIV_K1, 0, 0, ktmp);
 	_aesKeys[1].init(ktmp);
-	Utils::burn(ktmp,ZT_SYMMETRIC_KEY_SIZE);
+	Utils::burn(ktmp, ZT_SYMMETRIC_KEY_SIZE);
 }
 
 void Peer::received(
-	void *tPtr,
-	const SharedPtr<Path> &path,
+	void* tPtr,
+	const SharedPtr<Path>& path,
 	const unsigned int hops,
 	const uint64_t packetId,
 	const unsigned int payloadLength,
@@ -114,7 +115,7 @@ void Peer::received(
 		bool havePath = false;
 		{
 			Mutex::Lock _l(_paths_m);
-			for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
+			for (unsigned int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
 				if (_paths[i].p) {
 					if (_paths[i].p == path) {
 						_paths[i].lr = now;
@@ -123,25 +124,26 @@ void Peer::received(
 					}
 					// If same address on same interface then don't learn unless existing path isn't alive (prevents learning loop)
 					if (_paths[i].p->address().ipsEqual(path->address()) && _paths[i].p->localSocket() == path->localSocket()) {
-						if (_paths[i].p->alive(now) && !_bond) {
+						if (_paths[i].p->alive(now) && ! _bond) {
 							havePath = true;
 							break;
 						}
 					}
-				} else {
+				}
+				else {
 					break;
 				}
 			}
 		}
 
-		if ( (!havePath) && RR->node->shouldUsePathForZeroTierTraffic(tPtr,_id.address(),path->localSocket(),path->address()) ) {
+		if ((! havePath) && RR->node->shouldUsePathForZeroTierTraffic(tPtr, _id.address(), path->localSocket(), path->address())) {
 			if (verb == Packet::VERB_OK) {
 				Mutex::Lock _l(_paths_m);
 				unsigned int oldestPathIdx = ZT_MAX_PEER_NETWORK_PATHS;
 				unsigned int oldestPathAge = 0;
 				unsigned int replacePath = ZT_MAX_PEER_NETWORK_PATHS;
 
-				for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
+				for (unsigned int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
 					if (_paths[i].p) {
 						// Keep track of oldest path as a last resort option
 						unsigned int currAge = _paths[i].p->age(now);
@@ -151,13 +153,14 @@ void Peer::received(
 						}
 						if (_paths[i].p->address().ipsEqual(path->address())) {
 							if (_paths[i].p->localSocket() == path->localSocket()) {
-								if (!_paths[i].p->alive(now)) {
+								if (! _paths[i].p->alive(now)) {
 									replacePath = i;
 									break;
 								}
 							}
 						}
-					} else {
+					}
+					else {
 						replacePath = i;
 						break;
 					}
@@ -171,30 +174,33 @@ void Peer::received(
 					_paths[replacePath].p = path;
 					_paths[replacePath].priority = 1;
 					Mutex::Lock _l(_bond_m);
-					if(_bond) {
+					if (_bond) {
 						_bond->nominatePathToBond(_paths[replacePath].p, now);
 					}
 				}
-			} else {
+			}
+			else {
 				Mutex::Lock ltl(_lastTriedPath_m);
 
 				bool triedTooRecently = false;
-				for(std::list< std::pair< Path *, int64_t > >::iterator i(_lastTriedPath.begin());i!=_lastTriedPath.end();) {
+				for (std::list<std::pair<Path*, int64_t> >::iterator i(_lastTriedPath.begin()); i != _lastTriedPath.end();) {
 					if ((now - i->second) > 1000) {
 						_lastTriedPath.erase(i++);
-					} else if (i->first == path.ptr()) {
+					}
+					else if (i->first == path.ptr()) {
 						++i;
 						triedTooRecently = true;
-					} else {
+					}
+					else {
 						++i;
 					}
 				}
 
-				if (!triedTooRecently) {
-					_lastTriedPath.push_back(std::pair< Path *, int64_t >(path.ptr(), now));
-					attemptToContactAt(tPtr,path->localSocket(),path->address(),now,true);
+				if (! triedTooRecently) {
+					_lastTriedPath.push_back(std::pair<Path*, int64_t>(path.ptr(), now));
+					attemptToContactAt(tPtr, path->localSocket(), path->address(), now, true);
 					path->sent(now);
-					RR->t->peerConfirmingUnknownPath(tPtr,networkId,*this,path,packetId,verb);
+					RR->t->peerConfirmingUnknownPath(tPtr, networkId, *this, path, packetId, verb);
 				}
 			}
 		}
@@ -212,30 +218,30 @@ void Peer::received(
 			std::vector<InetAddress> pathsToPush(RR->node->directPaths());
 			std::vector<InetAddress> ma = RR->sa->whoami();
 			pathsToPush.insert(pathsToPush.end(), ma.begin(), ma.end());
-			if (!pathsToPush.empty()) {
+			if (! pathsToPush.empty()) {
 				std::vector<InetAddress>::const_iterator p(pathsToPush.begin());
 				while (p != pathsToPush.end()) {
-					Packet *const outp = new Packet(_id.address(),RR->identity.address(),Packet::VERB_PUSH_DIRECT_PATHS);
-					outp->addSize(2); // leave room for count
+					Packet* const outp = new Packet(_id.address(), RR->identity.address(), Packet::VERB_PUSH_DIRECT_PATHS);
+					outp->addSize(2);	// leave room for count
 					unsigned int count = 0;
-					while ((p != pathsToPush.end())&&((outp->size() + 24) < 1200)) {
+					while ((p != pathsToPush.end()) && ((outp->size() + 24) < 1200)) {
 						uint8_t addressType = 4;
-						switch(p->ss_family) {
+						switch (p->ss_family) {
 							case AF_INET:
 								break;
 							case AF_INET6:
 								addressType = 6;
 								break;
-							default: // we currently only push IP addresses
+							default:   // we currently only push IP addresses
 								++p;
 								continue;
 						}
 
-						outp->append((uint8_t)0); // no flags
-						outp->append((uint16_t)0); // no extensions
+						outp->append((uint8_t)0);	 // no flags
+						outp->append((uint16_t)0);	 // no extensions
 						outp->append(addressType);
 						outp->append((uint8_t)((addressType == 4) ? 6 : 18));
-						outp->append(p->rawIpData(),((addressType == 4) ? 4 : 16));
+						outp->append(p->rawIpData(), ((addressType == 4) ? 4 : 16));
 						outp->append((uint16_t)p->port());
 
 						++count;
@@ -243,11 +249,11 @@ void Peer::received(
 					}
 					if (count) {
 						Metrics::pkt_push_direct_paths_out++;
-						outp->setAt(ZT_PACKET_IDX_PAYLOAD,(uint16_t)count);
+						outp->setAt(ZT_PACKET_IDX_PAYLOAD, (uint16_t)count);
 						outp->compress();
-						outp->armor(_key,true,aesKeysIfSupported());
+						outp->armor(_key, true, aesKeysIfSupported());
 						Metrics::pkt_push_direct_paths_out++;
-						path->send(RR,tPtr,outp->data(),outp->size(),now);
+						path->send(RR, tPtr, outp->data(), outp->size(), now);
 					}
 					delete outp;
 				}
@@ -260,7 +266,7 @@ SharedPtr<Path> Peer::getAppropriatePath(int64_t now, bool includeExpired, int32
 {
 	Mutex::Lock _l(_paths_m);
 	Mutex::Lock _lb(_bond_m);
-	if(_bond && _bond->isReady()) {
+	if (_bond && _bond->isReady()) {
 		return _bond->getAppropriatePath(now, flowId);
 	}
 	unsigned int bestPath = ZT_MAX_PEER_NETWORK_PATHS;
@@ -269,16 +275,17 @@ SharedPtr<Path> Peer::getAppropriatePath(int64_t now, bool includeExpired, int32
 	 * use the old path quality metric from protocol version 9.
 	 */
 	long bestPathQuality = 2147483647;
-	for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
+	for (unsigned int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
 		if (_paths[i].p) {
-			if ((includeExpired)||((now - _paths[i].lr) < ZT_PEER_PATH_EXPIRATION)) {
+			if ((includeExpired) || ((now - _paths[i].lr) < ZT_PEER_PATH_EXPIRATION)) {
 				const long q = _paths[i].p->quality(now) / _paths[i].priority;
 				if (q <= bestPathQuality) {
 					bestPathQuality = q;
 					bestPath = i;
 				}
 			}
-		} else {
+		}
+		else {
 			break;
 		}
 	}
@@ -288,17 +295,17 @@ SharedPtr<Path> Peer::getAppropriatePath(int64_t now, bool includeExpired, int32
 	return SharedPtr<Path>();
 }
 
-void Peer::introduce(void *const tPtr,const int64_t now,const SharedPtr<Peer> &other) const
+void Peer::introduce(void* const tPtr, const int64_t now, const SharedPtr<Peer>& other) const
 {
-	unsigned int myBestV4ByScope[ZT_INETADDRESS_MAX_SCOPE+1];
-	unsigned int myBestV6ByScope[ZT_INETADDRESS_MAX_SCOPE+1];
-	long myBestV4QualityByScope[ZT_INETADDRESS_MAX_SCOPE+1];
-	long myBestV6QualityByScope[ZT_INETADDRESS_MAX_SCOPE+1];
-	unsigned int theirBestV4ByScope[ZT_INETADDRESS_MAX_SCOPE+1];
-	unsigned int theirBestV6ByScope[ZT_INETADDRESS_MAX_SCOPE+1];
-	long theirBestV4QualityByScope[ZT_INETADDRESS_MAX_SCOPE+1];
-	long theirBestV6QualityByScope[ZT_INETADDRESS_MAX_SCOPE+1];
-	for(int i=0;i<=ZT_INETADDRESS_MAX_SCOPE;++i) {
+	unsigned int myBestV4ByScope[ZT_INETADDRESS_MAX_SCOPE + 1];
+	unsigned int myBestV6ByScope[ZT_INETADDRESS_MAX_SCOPE + 1];
+	long myBestV4QualityByScope[ZT_INETADDRESS_MAX_SCOPE + 1];
+	long myBestV6QualityByScope[ZT_INETADDRESS_MAX_SCOPE + 1];
+	unsigned int theirBestV4ByScope[ZT_INETADDRESS_MAX_SCOPE + 1];
+	unsigned int theirBestV6ByScope[ZT_INETADDRESS_MAX_SCOPE + 1];
+	long theirBestV4QualityByScope[ZT_INETADDRESS_MAX_SCOPE + 1];
+	long theirBestV6QualityByScope[ZT_INETADDRESS_MAX_SCOPE + 1];
+	for (int i = 0; i <= ZT_INETADDRESS_MAX_SCOPE; ++i) {
 		myBestV4ByScope[i] = ZT_MAX_PEER_NETWORK_PATHS;
 		myBestV6ByScope[i] = ZT_MAX_PEER_NETWORK_PATHS;
 		myBestV4QualityByScope[i] = 2147483647;
@@ -311,11 +318,11 @@ void Peer::introduce(void *const tPtr,const int64_t now,const SharedPtr<Peer> &o
 
 	Mutex::Lock _l1(_paths_m);
 
-	for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
+	for (unsigned int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
 		if (_paths[i].p) {
 			const long q = _paths[i].p->quality(now) / _paths[i].priority;
 			const unsigned int s = (unsigned int)_paths[i].p->ipScope();
-			switch(_paths[i].p->address().ss_family) {
+			switch (_paths[i].p->address().ss_family) {
 				case AF_INET:
 					if (q <= myBestV4QualityByScope[s]) {
 						myBestV4QualityByScope[s] = q;
@@ -329,18 +336,19 @@ void Peer::introduce(void *const tPtr,const int64_t now,const SharedPtr<Peer> &o
 					}
 					break;
 			}
-		} else {
+		}
+		else {
 			break;
 		}
 	}
 
 	Mutex::Lock _l2(other->_paths_m);
 
-	for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
+	for (unsigned int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
 		if (other->_paths[i].p) {
 			const long q = other->_paths[i].p->quality(now) / other->_paths[i].priority;
 			const unsigned int s = (unsigned int)other->_paths[i].p->ipScope();
-			switch(other->_paths[i].p->address().ss_family) {
+			switch (other->_paths[i].p->address().ss_family) {
 				case AF_INET:
 					if (q <= theirBestV4QualityByScope[s]) {
 						theirBestV4QualityByScope[s] = q;
@@ -354,7 +362,8 @@ void Peer::introduce(void *const tPtr,const int64_t now,const SharedPtr<Peer> &o
 					}
 					break;
 			}
-		} else {
+		}
+		else {
 			break;
 		}
 	}
@@ -362,13 +371,13 @@ void Peer::introduce(void *const tPtr,const int64_t now,const SharedPtr<Peer> &o
 	unsigned int mine = ZT_MAX_PEER_NETWORK_PATHS;
 	unsigned int theirs = ZT_MAX_PEER_NETWORK_PATHS;
 
-	for(int s=ZT_INETADDRESS_MAX_SCOPE;s>=0;--s) {
-		if ((myBestV6ByScope[s] != ZT_MAX_PEER_NETWORK_PATHS)&&(theirBestV6ByScope[s] != ZT_MAX_PEER_NETWORK_PATHS)) {
+	for (int s = ZT_INETADDRESS_MAX_SCOPE; s >= 0; --s) {
+		if ((myBestV6ByScope[s] != ZT_MAX_PEER_NETWORK_PATHS) && (theirBestV6ByScope[s] != ZT_MAX_PEER_NETWORK_PATHS)) {
 			mine = myBestV6ByScope[s];
 			theirs = theirBestV6ByScope[s];
 			break;
 		}
-		if ((myBestV4ByScope[s] != ZT_MAX_PEER_NETWORK_PATHS)&&(theirBestV4ByScope[s] != ZT_MAX_PEER_NETWORK_PATHS)) {
+		if ((myBestV4ByScope[s] != ZT_MAX_PEER_NETWORK_PATHS) && (theirBestV4ByScope[s] != ZT_MAX_PEER_NETWORK_PATHS)) {
 			mine = myBestV4ByScope[s];
 			theirs = theirBestV4ByScope[s];
 			break;
@@ -376,55 +385,58 @@ void Peer::introduce(void *const tPtr,const int64_t now,const SharedPtr<Peer> &o
 	}
 
 	if (mine != ZT_MAX_PEER_NETWORK_PATHS) {
-		unsigned int alt = (unsigned int)RR->node->prng() & 1; // randomize which hint we send first for black magickal NAT-t reasons
+		unsigned int alt = (unsigned int)RR->node->prng() & 1;	 // randomize which hint we send first for black magickal NAT-t reasons
 		const unsigned int completed = alt + 2;
 		while (alt != completed) {
 			if ((alt & 1) == 0) {
-				Packet outp(_id.address(),RR->identity.address(),Packet::VERB_RENDEZVOUS);
+				Packet outp(_id.address(), RR->identity.address(), Packet::VERB_RENDEZVOUS);
 				outp.append((uint8_t)0);
 				other->_id.address().appendTo(outp);
 				outp.append((uint16_t)other->_paths[theirs].p->address().port());
 				if (other->_paths[theirs].p->address().ss_family == AF_INET6) {
 					outp.append((uint8_t)16);
-					outp.append(other->_paths[theirs].p->address().rawIpData(),16);
-				} else {
+					outp.append(other->_paths[theirs].p->address().rawIpData(), 16);
+				}
+				else {
 					outp.append((uint8_t)4);
-					outp.append(other->_paths[theirs].p->address().rawIpData(),4);
+					outp.append(other->_paths[theirs].p->address().rawIpData(), 4);
 				}
-				outp.armor(_key,true,aesKeysIfSupported());
+				outp.armor(_key, true, aesKeysIfSupported());
 				Metrics::pkt_rendezvous_out++;
-				_paths[mine].p->send(RR,tPtr,outp.data(),outp.size(),now);
-			} else {
-				Packet outp(other->_id.address(),RR->identity.address(),Packet::VERB_RENDEZVOUS);
+				_paths[mine].p->send(RR, tPtr, outp.data(), outp.size(), now);
+			}
+			else {
+				Packet outp(other->_id.address(), RR->identity.address(), Packet::VERB_RENDEZVOUS);
 				outp.append((uint8_t)0);
 				_id.address().appendTo(outp);
 				outp.append((uint16_t)_paths[mine].p->address().port());
 				if (_paths[mine].p->address().ss_family == AF_INET6) {
 					outp.append((uint8_t)16);
-					outp.append(_paths[mine].p->address().rawIpData(),16);
-				} else {
+					outp.append(_paths[mine].p->address().rawIpData(), 16);
+				}
+				else {
 					outp.append((uint8_t)4);
-					outp.append(_paths[mine].p->address().rawIpData(),4);
+					outp.append(_paths[mine].p->address().rawIpData(), 4);
 				}
-				outp.armor(other->_key,true,other->aesKeysIfSupported());
+				outp.armor(other->_key, true, other->aesKeysIfSupported());
 				Metrics::pkt_rendezvous_out++;
-				other->_paths[theirs].p->send(RR,tPtr,outp.data(),outp.size(),now);
+				other->_paths[theirs].p->send(RR, tPtr, outp.data(), outp.size(), now);
 			}
 			++alt;
 		}
 	}
 }
 
-void Peer::sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,int64_t now)
+void Peer::sendHELLO(void* tPtr, const int64_t localSocket, const InetAddress& atAddress, int64_t now)
 {
-	Packet outp(_id.address(),RR->identity.address(),Packet::VERB_HELLO);
+	Packet outp(_id.address(), RR->identity.address(), Packet::VERB_HELLO);
 
 	outp.append((unsigned char)ZT_PROTO_VERSION);
 	outp.append((unsigned char)ZEROTIER_ONE_VERSION_MAJOR);
 	outp.append((unsigned char)ZEROTIER_ONE_VERSION_MINOR);
 	outp.append((uint16_t)ZEROTIER_ONE_VERSION_REVISION);
 	outp.append(now);
-	RR->identity.serialize(outp,false);
+	RR->identity.serialize(outp, false);
 	atAddress.serialize(outp);
 
 	outp.append((uint64_t)RR->topology->planetWorldId());
@@ -435,56 +447,58 @@ void Peer::sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atA
 	std::vector<World> moons(RR->topology->moons());
 	std::vector<uint64_t> moonsWanted(RR->topology->moonsWanted());
 	outp.append((uint16_t)(moons.size() + moonsWanted.size()));
-	for(std::vector<World>::const_iterator m(moons.begin());m!=moons.end();++m) {
+	for (std::vector<World>::const_iterator m(moons.begin()); m != moons.end(); ++m) {
 		outp.append((uint8_t)m->type());
 		outp.append((uint64_t)m->id());
 		outp.append((uint64_t)m->timestamp());
 	}
-	for(std::vector<uint64_t>::const_iterator m(moonsWanted.begin());m!=moonsWanted.end();++m) {
+	for (std::vector<uint64_t>::const_iterator m(moonsWanted.begin()); m != moonsWanted.end(); ++m) {
 		outp.append((uint8_t)World::TYPE_MOON);
 		outp.append(*m);
 		outp.append((uint64_t)0);
 	}
 
-	outp.cryptField(_key,startCryptedPortionAt,outp.size() - startCryptedPortionAt);
+	outp.cryptField(_key, startCryptedPortionAt, outp.size() - startCryptedPortionAt);
 
 	Metrics::pkt_hello_out++;
 
 	if (atAddress) {
-		outp.armor(_key,false,nullptr); // false == don't encrypt full payload, but add MAC
+		outp.armor(_key, false, nullptr);	// false == don't encrypt full payload, but add MAC
 		RR->node->expectReplyTo(outp.packetId());
-		RR->node->putPacket(tPtr,RR->node->lowBandwidthModeEnabled() ? localSocket : -1,atAddress,outp.data(),outp.size());
-	} else {
+		RR->node->putPacket(tPtr, RR->node->lowBandwidthModeEnabled() ? localSocket : -1, atAddress, outp.data(), outp.size());
+	}
+	else {
 		RR->node->expectReplyTo(outp.packetId());
-		RR->sw->send(tPtr,outp,false); // false == don't encrypt full payload, but add MAC
+		RR->sw->send(tPtr, outp, false);   // false == don't encrypt full payload, but add MAC
 	}
 }
 
-void Peer::attemptToContactAt(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,int64_t now,bool sendFullHello)
+void Peer::attemptToContactAt(void* tPtr, const int64_t localSocket, const InetAddress& atAddress, int64_t now, bool sendFullHello)
 {
-	if ( (!sendFullHello) && (_vProto >= 5) && (!((_vMajor == 1)&&(_vMinor == 1)&&(_vRevision == 0))) ) {
-		Packet outp(_id.address(),RR->identity.address(),Packet::VERB_ECHO);
-		outp.armor(_key,true,aesKeysIfSupported());
+	if ((! sendFullHello) && (_vProto >= 5) && (! ((_vMajor == 1) && (_vMinor == 1) && (_vRevision == 0)))) {
+		Packet outp(_id.address(), RR->identity.address(), Packet::VERB_ECHO);
+		outp.armor(_key, true, aesKeysIfSupported());
 		Metrics::pkt_echo_out++;
 		RR->node->expectReplyTo(outp.packetId());
-		RR->node->putPacket(tPtr,localSocket,atAddress,outp.data(),outp.size());
-	} else {
-		sendHELLO(tPtr,localSocket,atAddress,now);
+		RR->node->putPacket(tPtr, localSocket, atAddress, outp.data(), outp.size());
+	}
+	else {
+		sendHELLO(tPtr, localSocket, atAddress, now);
 	}
 }
 
-void Peer::tryMemorizedPath(void *tPtr,int64_t now)
+void Peer::tryMemorizedPath(void* tPtr, int64_t now)
 {
 	if ((now - _lastTriedMemorizedPath) >= ZT_TRY_MEMORIZED_PATH_INTERVAL) {
 		_lastTriedMemorizedPath = now;
 		InetAddress mp;
-		if (RR->node->externalPathLookup(tPtr,_id.address(),-1,mp)) {
-			attemptToContactAt(tPtr,-1,mp,now,true);
+		if (RR->node->externalPathLookup(tPtr, _id.address(), -1, mp)) {
+			attemptToContactAt(tPtr, -1, mp, now, true);
 		}
 	}
 }
 
-void Peer::performMultipathStateCheck(void *tPtr, int64_t now)
+void Peer::performMultipathStateCheck(void* tPtr, int64_t now)
 {
 	Mutex::Lock _l(_bond_m);
 	/**
@@ -493,9 +507,9 @@ void Peer::performMultipathStateCheck(void *tPtr, int64_t now)
 	 */
 	int numAlivePaths = 0;
 	bool atLeastOneNonExpired = false;
-	for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
+	for (unsigned int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
 		if (_paths[i].p) {
-			if(_paths[i].p->alive(now)) {
+			if (_paths[i].p->alive(now)) {
 				numAlivePaths++;
 			}
 			if ((now - _paths[i].lr) < ZT_PEER_PATH_EXPIRATION) {
@@ -504,21 +518,21 @@ void Peer::performMultipathStateCheck(void *tPtr, int64_t now)
 		}
 	}
 	if (_bond) {
-		if (numAlivePaths == 0 && !atLeastOneNonExpired) {
+		if (numAlivePaths == 0 && ! atLeastOneNonExpired) {
 			_bond = SharedPtr<Bond>();
 			RR->bc->destroyBond(_id.address().toInt());
 		}
 		return;
 	}
 	_localMultipathSupported = ((numAlivePaths >= 1) && (RR->bc->inUse()) && (ZT_PROTO_VERSION > 9));
-	if (_localMultipathSupported && !_bond) {
+	if (_localMultipathSupported && ! _bond) {
 		if (RR->bc) {
 			_bond = RR->bc->createBond(RR, this);
 			/**
 			 * Allow new bond to retroactively learn all paths known to this peer
 			 */
 			if (_bond) {
-				for (unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
+				for (unsigned int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
 					if (_paths[i].p) {
 						_bond->nominatePathToBond(_paths[i].p, now);
 					}
@@ -528,7 +542,7 @@ void Peer::performMultipathStateCheck(void *tPtr, int64_t now)
 	}
 }
 
-unsigned int Peer::doPingAndKeepalive(void *tPtr,int64_t now)
+unsigned int Peer::doPingAndKeepalive(void* tPtr, int64_t now)
 {
 	unsigned int sent = 0;
 	{
@@ -546,31 +560,33 @@ unsigned int Peer::doPingAndKeepalive(void *tPtr,int64_t now)
 		// redirects us its redirect target links override all other links and we
 		// let those old links expire.
 		long maxPriority = 0;
-		for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
+		for (unsigned int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
 			if (_paths[i].p) {
-				maxPriority = std::max(_paths[i].priority,maxPriority);
-			} else {
+				maxPriority = std::max(_paths[i].priority, maxPriority);
+			}
+			else {
 				break;
 			}
 		}
 
 		bool deletionOccurred = false;
-		for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
+		for (unsigned int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
 			if (_paths[i].p) {
 				// Clean expired and reduced priority paths
-				if ( ((now - _paths[i].lr) < ZT_PEER_PATH_EXPIRATION) && (_paths[i].priority == maxPriority) ) {
-					if ((sendFullHello)||(_paths[i].p->needsHeartbeat(now))) {
-						attemptToContactAt(tPtr,_paths[i].p->localSocket(),_paths[i].p->address(),now,sendFullHello);
+				if (((now - _paths[i].lr) < ZT_PEER_PATH_EXPIRATION) && (_paths[i].priority == maxPriority)) {
+					if ((sendFullHello) || (_paths[i].p->needsHeartbeat(now))) {
+						attemptToContactAt(tPtr, _paths[i].p->localSocket(), _paths[i].p->address(), now, sendFullHello);
 						_paths[i].p->sent(now);
 						sent |= (_paths[i].p->address().ss_family == AF_INET) ? 0x1 : 0x2;
 					}
-				} else {
+				}
+				else {
 					_paths[i] = _PeerPath();
 					deletionOccurred = true;
 				}
 			}
-			if (!_paths[i].p || deletionOccurred) {
-				for(unsigned int j=i;j<ZT_MAX_PEER_NETWORK_PATHS;++j) {
+			if (! _paths[i].p || deletionOccurred) {
+				for (unsigned int j = i; j < ZT_MAX_PEER_NETWORK_PATHS; ++j) {
 					if (_paths[j].p && i != j) {
 						_paths[i] = _paths[j];
 						_paths[j] = _PeerPath();
@@ -582,7 +598,7 @@ unsigned int Peer::doPingAndKeepalive(void *tPtr,int64_t now)
 		}
 #ifndef ZT_NO_PEER_METRICS
 		uint16_t alive_path_count_tmp = 0, dead_path_count_tmp = 0;
-		for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
+		for (unsigned int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
 			if (_paths[i].p) {
 				if (_paths[i].p->alive(now)) {
 					alive_path_count_tmp++;
@@ -602,25 +618,26 @@ unsigned int Peer::doPingAndKeepalive(void *tPtr,int64_t now)
 	return sent;
 }
 
-void Peer::clusterRedirect(void *tPtr,const SharedPtr<Path> &originatingPath,const InetAddress &remoteAddress,const int64_t now)
+void Peer::clusterRedirect(void* tPtr, const SharedPtr<Path>& originatingPath, const InetAddress& remoteAddress, const int64_t now)
 {
-	SharedPtr<Path> np(RR->topology->getPath(originatingPath->localSocket(),remoteAddress));
-	RR->t->peerRedirected(tPtr,0,*this,np);
+	SharedPtr<Path> np(RR->topology->getPath(originatingPath->localSocket(), remoteAddress));
+	RR->t->peerRedirected(tPtr, 0, *this, np);
 
-	attemptToContactAt(tPtr,originatingPath->localSocket(),remoteAddress,now,true);
+	attemptToContactAt(tPtr, originatingPath->localSocket(), remoteAddress, now, true);
 
 	{
 		Mutex::Lock _l(_paths_m);
 
 		// New priority is higher than the priority of the originating path (if known)
 		long newPriority = 1;
-		for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
+		for (unsigned int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
 			if (_paths[i].p) {
 				if (_paths[i].p == originatingPath) {
 					newPriority = _paths[i].priority;
 					break;
 				}
-			} else {
+			}
+			else {
 				break;
 			}
 		}
@@ -629,9 +646,9 @@ void Peer::clusterRedirect(void *tPtr,const SharedPtr<Path> &originatingPath,con
 		// Erase any paths with lower priority than this one or that are duplicate
 		// IPs and add this path.
 		unsigned int j = 0;
-		for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
+		for (unsigned int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
 			if (_paths[i].p) {
-				if ((_paths[i].priority >= newPriority)&&(!_paths[i].p->address().ipsEqual2(remoteAddress))) {
+				if ((_paths[i].priority >= newPriority) && (! _paths[i].p->address().ipsEqual2(remoteAddress))) {
 					if (i != j) {
 						_paths[j] = _paths[i];
 					}
@@ -654,24 +671,24 @@ void Peer::clusterRedirect(void *tPtr,const SharedPtr<Path> &originatingPath,con
 	}
 }
 
-void Peer::resetWithinScope(void *tPtr,InetAddress::IpScope scope,int inetAddressFamily,int64_t now)
+void Peer::resetWithinScope(void* tPtr, InetAddress::IpScope scope, int inetAddressFamily, int64_t now)
 {
 	Mutex::Lock _l(_paths_m);
-	for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
+	for (unsigned int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
 		if (_paths[i].p) {
-			if ((_paths[i].p->address().ss_family == inetAddressFamily)&&(_paths[i].p->ipScope() == scope)) {
-				attemptToContactAt(tPtr,_paths[i].p->localSocket(),_paths[i].p->address(),now,false);
+			if ((_paths[i].p->address().ss_family == inetAddressFamily) && (_paths[i].p->ipScope() == scope)) {
+				attemptToContactAt(tPtr, _paths[i].p->localSocket(), _paths[i].p->address(), now, false);
 				_paths[i].p->sent(now);
-				_paths[i].lr = 0; // path will not be used unless it speaks again
+				_paths[i].lr = 0;	// path will not be used unless it speaks again
 			}
-		} else {
+		}
+		else {
 			break;
 		}
 	}
 }
 
-void Peer::recordOutgoingPacket(const SharedPtr<Path> &path, const uint64_t packetId,
-	uint16_t payloadLength, const Packet::Verb verb, const int32_t flowId, int64_t now)
+void Peer::recordOutgoingPacket(const SharedPtr<Path>& path, const uint64_t packetId, uint16_t payloadLength, const Packet::Verb verb, const int32_t flowId, int64_t now)
 {
 #ifndef ZT_NO_PEER_METRICS
 	_outgoing_packet++;
@@ -691,12 +708,11 @@ void Peer::recordIncomingInvalidPacket(const SharedPtr<Path>& path)
 	}
 }
 
-void Peer::recordIncomingPacket(const SharedPtr<Path> &path, const uint64_t packetId,
-	uint16_t payloadLength, const Packet::Verb verb, const int32_t flowId, int64_t now)
+void Peer::recordIncomingPacket(const SharedPtr<Path>& path, const uint64_t packetId, uint16_t payloadLength, const Packet::Verb verb, const int32_t flowId, int64_t now)
 {
 	if (_localMultipathSupported && _bond) {
 		_bond->recordIncomingPacket(path, packetId, payloadLength, verb, flowId, now);
 	}
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier

+ 164 - 114
node/Peer.hpp

@@ -14,27 +14,26 @@
 #ifndef ZT_PEER_HPP
 #define ZT_PEER_HPP
 
-#include <vector>
-#include <list>
-
 #include "../include/ZeroTierOne.h"
-
-#include "Constants.hpp"
-#include "RuntimeEnvironment.hpp"
-#include "Node.hpp"
-#include "Path.hpp"
+#include "AES.hpp"
 #include "Address.hpp"
-#include "Utils.hpp"
+#include "AtomicCounter.hpp"
+#include "Bond.hpp"
+#include "Constants.hpp"
+#include "Hashtable.hpp"
 #include "Identity.hpp"
 #include "InetAddress.hpp"
+#include "Metrics.hpp"
+#include "Mutex.hpp"
+#include "Node.hpp"
 #include "Packet.hpp"
+#include "Path.hpp"
+#include "RuntimeEnvironment.hpp"
 #include "SharedPtr.hpp"
-#include "AtomicCounter.hpp"
-#include "Hashtable.hpp"
-#include "Mutex.hpp"
-#include "Bond.hpp"
-#include "AES.hpp"
-#include "Metrics.hpp"
+#include "Utils.hpp"
+
+#include <list>
+#include <vector>
 
 #define ZT_PEER_MAX_SERIALIZED_STATE_SIZE (sizeof(Peer) + 32 + (sizeof(Path) * 2))
 
@@ -43,19 +42,19 @@ namespace ZeroTier {
 /**
  * Peer on P2P Network (virtual layer 1)
  */
-class Peer
-{
+class Peer {
 	friend class SharedPtr<Peer>;
 	friend class SharedPtr<Bond>;
 	friend class Switch;
 	friend class Bond;
 
-private:
-	Peer() = delete; // disabled to prevent bugs -- should not be constructed uninitialized
+  private:
+	Peer() = delete;   // disabled to prevent bugs -- should not be constructed uninitialized
 
-public:
-	~Peer() {
-		Utils::burn(_key,sizeof(_key));
+  public:
+	~Peer()
+	{
+		Utils::burn(_key, sizeof(_key));
 	}
 
 	/**
@@ -66,17 +65,23 @@ public:
 	 * @param peerIdentity Identity of peer
 	 * @throws std::runtime_error Key agreement with peer's identity failed
 	 */
-	Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Identity &peerIdentity);
+	Peer(const RuntimeEnvironment* renv, const Identity& myIdentity, const Identity& peerIdentity);
 
 	/**
 	 * @return This peer's ZT address (short for identity().address())
 	 */
-	inline const Address &address() const { return _id.address(); }
+	inline const Address& address() const
+	{
+		return _id.address();
+	}
 
 	/**
 	 * @return This peer's identity
 	 */
-	inline const Identity &identity() const { return _id; }
+	inline const Identity& identity() const
+	{
+		return _id;
+	}
 
 	/**
 	 * Log receipt of an authenticated packet
@@ -95,8 +100,8 @@ public:
 	 * @param networkId Network ID if this pertains to a network, or 0 otherwise
 	 */
 	void received(
-		void *tPtr,
-		const SharedPtr<Path> &path,
+		void* tPtr,
+		const SharedPtr<Path>& path,
 		const unsigned int hops,
 		const uint64_t packetId,
 		const unsigned int payloadLength,
@@ -114,15 +119,16 @@ public:
 	 * @param addr Remote address
 	 * @return True if we have an active path to this destination
 	 */
-	inline bool hasActivePathTo(int64_t now,const InetAddress &addr) const
+	inline bool hasActivePathTo(int64_t now, const InetAddress& addr) const
 	{
 		Mutex::Lock _l(_paths_m);
-		for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
+		for (unsigned int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
 			if (_paths[i].p) {
-				if (((now - _paths[i].lr) < ZT_PEER_PATH_EXPIRATION)&&(_paths[i].p->address() == addr)) {
+				if (((now - _paths[i].lr) < ZT_PEER_PATH_EXPIRATION) && (_paths[i].p->address() == addr)) {
 					return true;
 				}
-			} else {
+			}
+			else {
 				break;
 			}
 		}
@@ -139,11 +145,11 @@ public:
 	 * @param force If true, send even if path is not alive
 	 * @return True if we actually sent something
 	 */
-	inline bool sendDirect(void *tPtr,const void *data,unsigned int len,int64_t now,bool force)
+	inline bool sendDirect(void* tPtr, const void* data, unsigned int len, int64_t now, bool force)
 	{
-		SharedPtr<Path> bp(getAppropriatePath(now,force));
+		SharedPtr<Path> bp(getAppropriatePath(now, force));
 		if (bp) {
-			return bp->send(RR,tPtr,data,len,now);
+			return bp->send(RR, tPtr, data, len, now);
 		}
 		return false;
 	}
@@ -159,8 +165,7 @@ public:
 	 * @param flowId Flow ID
 	 * @param now Current time
 	 */
-	void recordIncomingPacket(const SharedPtr<Path> &path, const uint64_t packetId,
-		uint16_t payloadLength, const Packet::Verb verb, const int32_t flowId, int64_t now);
+	void recordIncomingPacket(const SharedPtr<Path>& path, const uint64_t packetId, uint16_t payloadLength, const Packet::Verb verb, const int32_t flowId, int64_t now);
 
 	/**
 	 *
@@ -171,8 +176,7 @@ public:
 	 * @param flowId Flow ID
 	 * @param now Current time
 	 */
-	void recordOutgoingPacket(const SharedPtr<Path> &path, const uint64_t packetId,
-		uint16_t payloadLength, const Packet::Verb verb, const int32_t flowId, int64_t now);
+	void recordOutgoingPacket(const SharedPtr<Path>& path, const uint64_t packetId, uint16_t payloadLength, const Packet::Verb verb, const int32_t flowId, int64_t now);
 
 	/**
 	 * Record an invalid incoming packet. This packet failed
@@ -195,7 +199,7 @@ public:
 	/**
 	 * Send VERB_RENDEZVOUS to this and another peer via the best common IP scope and path
 	 */
-	void introduce(void *const tPtr,const int64_t now,const SharedPtr<Peer> &other) const;
+	void introduce(void* const tPtr, const int64_t now, const SharedPtr<Peer>& other) const;
 
 	/**
 	 * Send a HELLO to this peer at a specified physical address
@@ -207,7 +211,7 @@ public:
 	 * @param atAddress Destination address
 	 * @param now Current time
 	 */
-	void sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,int64_t now);
+	void sendHELLO(void* tPtr, const int64_t localSocket, const InetAddress& atAddress, int64_t now);
 
 	/**
 	 * Send ECHO (or HELLO for older peers) to this peer at the given address
@@ -220,7 +224,7 @@ public:
 	 * @param now Current time
 	 * @param sendFullHello If true, always send a full HELLO instead of just an ECHO
 	 */
-	void attemptToContactAt(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,int64_t now,bool sendFullHello);
+	void attemptToContactAt(void* tPtr, const int64_t localSocket, const InetAddress& atAddress, int64_t now, bool sendFullHello);
 
 	/**
 	 * Try a memorized or statically defined path if any are known
@@ -230,14 +234,14 @@ public:
 	 * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
 	 * @param now Current time
 	 */
-	void tryMemorizedPath(void *tPtr,int64_t now);
+	void tryMemorizedPath(void* tPtr, int64_t now);
 
 	/**
 	 * A check to be performed periodically which determines whether multipath communication is
 	 * possible with this peer. This check should be performed early in the life-cycle of the peer
 	 * as well as during the process of learning new paths.
 	 */
-	void performMultipathStateCheck(void *tPtr, int64_t now);
+	void performMultipathStateCheck(void* tPtr, int64_t now);
 
 	/**
 	 * Send pings or keepalives depending on configured timeouts
@@ -249,7 +253,7 @@ public:
 	 * @param inetAddressFamily Keep this address family alive, or -1 for any
 	 * @return 0 if nothing sent or bit mask: bit 0x1 if IPv4 sent, bit 0x2 if IPv6 sent (0x3 means both sent)
 	 */
-	unsigned int doPingAndKeepalive(void *tPtr,int64_t now);
+	unsigned int doPingAndKeepalive(void* tPtr, int64_t now);
 
 	/**
 	 * Process a cluster redirect sent by this peer
@@ -259,7 +263,7 @@ public:
 	 * @param remoteAddress Remote address
 	 * @param now Current time
 	 */
-	void clusterRedirect(void *tPtr,const SharedPtr<Path> &originatingPath,const InetAddress &remoteAddress,const int64_t now);
+	void clusterRedirect(void* tPtr, const SharedPtr<Path>& originatingPath, const InetAddress& remoteAddress, const int64_t now);
 
 	/**
 	 * Reset paths within a given IP scope and address family
@@ -274,18 +278,18 @@ public:
 	 * @param inetAddressFamily Family e.g. AF_INET
 	 * @param now Current time
 	 */
-	void resetWithinScope(void *tPtr,InetAddress::IpScope scope,int inetAddressFamily,int64_t now);
+	void resetWithinScope(void* tPtr, InetAddress::IpScope scope, int inetAddressFamily, int64_t now);
 
 	/**
 	 * @param now Current time
 	 * @return All known paths to this peer
 	 */
-	inline std::vector< SharedPtr<Path> > paths(const int64_t now) const
+	inline std::vector<SharedPtr<Path> > paths(const int64_t now) const
 	{
-		std::vector< SharedPtr<Path> > pp;
+		std::vector<SharedPtr<Path> > pp;
 		Mutex::Lock _l(_paths_m);
-		for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
-			if (!_paths[i].p) {
+		for (unsigned int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
+			if (! _paths[i].p) {
 				break;
 			}
 			pp.push_back(_paths[i].p);
@@ -296,19 +300,31 @@ public:
 	/**
 	 * @return Time of last receive of anything, whether direct or relayed
 	 */
-	inline int64_t lastReceive() const { return _lastReceive; }
+	inline int64_t lastReceive() const
+	{
+		return _lastReceive;
+	}
 
 	/**
 	 * @return True if we've heard from this peer in less than ZT_PEER_ACTIVITY_TIMEOUT
 	 */
-	inline bool isAlive(const int64_t now) const { return ((now - _lastReceive) < ZT_PEER_ACTIVITY_TIMEOUT); }
+	inline bool isAlive(const int64_t now) const
+	{
+		return ((now - _lastReceive) < ZT_PEER_ACTIVITY_TIMEOUT);
+	}
 
 	/**
 	 * @return True if this peer has sent us real network traffic recently
 	 */
-	inline int64_t isActive(int64_t now) const { return ((now - _lastNontrivialReceive) < ZT_PEER_ACTIVITY_TIMEOUT); }
+	inline int64_t isActive(int64_t now) const
+	{
+		return ((now - _lastNontrivialReceive) < ZT_PEER_ACTIVITY_TIMEOUT);
+	}
 
-	inline int64_t lastSentFullHello() { return _lastSentFullHello; }
+	inline int64_t lastSentFullHello()
+	{
+		return _lastSentFullHello;
+	}
 
 	/**
 	 * @return Latency in milliseconds of best/aggregate path or 0xffff if unknown / no paths
@@ -317,8 +333,9 @@ public:
 	{
 		if (_localMultipathSupported) {
 			return (int)_lastComputedAggregateMeanLatency;
-		} else {
-			SharedPtr<Path> bp(getAppropriatePath(now,false));
+		}
+		else {
+			SharedPtr<Path> bp(getAppropriatePath(now, false));
 			if (bp) {
 				return (unsigned int)bp->latency();
 			}
@@ -344,7 +361,7 @@ public:
 			return (~(unsigned int)0);
 		}
 		unsigned int l = latency(now);
-		if (!l) {
+		if (! l) {
 			l = 0xffff;
 		}
 		return (l * (((unsigned int)tsr / (ZT_PEER_PING_PERIOD + 1000)) + 1));
@@ -353,7 +370,10 @@ public:
 	/**
 	 * @return 256-bit secret symmetric encryption key
 	 */
-	inline const unsigned char *key() const { return _key; }
+	inline const unsigned char* key() const
+	{
+		return _key;
+	}
 
 	/**
 	 * Set the currently known remote version of this peer's client
@@ -363,7 +383,7 @@ public:
 	 * @param vmin Minor version
 	 * @param vrev Revision
 	 */
-	inline void setRemoteVersion(unsigned int vproto,unsigned int vmaj,unsigned int vmin,unsigned int vrev)
+	inline void setRemoteVersion(unsigned int vproto, unsigned int vmaj, unsigned int vmin, unsigned int vrev)
 	{
 		_vProto = (uint16_t)vproto;
 		_vMajor = (uint16_t)vmaj;
@@ -371,17 +391,35 @@ public:
 		_vRevision = (uint16_t)vrev;
 	}
 
-	inline unsigned int remoteVersionProtocol() const { return _vProto; }
-	inline unsigned int remoteVersionMajor() const { return _vMajor; }
-	inline unsigned int remoteVersionMinor() const { return _vMinor; }
-	inline unsigned int remoteVersionRevision() const { return _vRevision; }
+	inline unsigned int remoteVersionProtocol() const
+	{
+		return _vProto;
+	}
+	inline unsigned int remoteVersionMajor() const
+	{
+		return _vMajor;
+	}
+	inline unsigned int remoteVersionMinor() const
+	{
+		return _vMinor;
+	}
+	inline unsigned int remoteVersionRevision() const
+	{
+		return _vRevision;
+	}
 
-	inline bool remoteVersionKnown() const { return ((_vMajor > 0)||(_vMinor > 0)||(_vRevision > 0)); }
+	inline bool remoteVersionKnown() const
+	{
+		return ((_vMajor > 0) || (_vMinor > 0) || (_vRevision > 0));
+	}
 
 	/**
 	 * @return True if peer has received a trust established packet (e.g. common network membership) in the past ZT_TRUST_EXPIRATION ms
 	 */
-	inline bool trustEstablished(const int64_t now) const { return ((now - _lastTrustEstablishedPacketReceived) < ZT_TRUST_EXPIRATION); }
+	inline bool trustEstablished(const int64_t now) const
+	{
+		return ((now - _lastTrustEstablishedPacketReceived) < ZT_TRUST_EXPIRATION);
+	}
 
 	/**
 	 * Rate limit gate for VERB_PUSH_DIRECT_PATHS
@@ -390,7 +428,8 @@ public:
 	{
 		if ((now - _lastDirectPathPushReceive) <= ZT_PUSH_DIRECT_PATHS_CUTOFF_TIME) {
 			++_directPathPushCutoffCount;
-		} else {
+		}
+		else {
 			_directPathPushCutoffCount = 0;
 		}
 		_lastDirectPathPushReceive = now;
@@ -439,10 +478,10 @@ public:
 	inline bool rateGateQoS(int64_t now, SharedPtr<Path>& path)
 	{
 		Mutex::Lock _l(_bond_m);
-		if(_bond) {
+		if (_bond) {
 			return _bond->rateGateQoS(now, path);
 		}
-		return false; // Default behavior. If there is no bond, we drop these
+		return false;	// Default behavior. If there is no bond, we drop these
 	}
 
 	/**
@@ -451,7 +490,7 @@ public:
 	void receivedQoS(const SharedPtr<Path>& path, int64_t now, int count, uint64_t* rx_id, uint16_t* rx_ts)
 	{
 		Mutex::Lock _l(_bond_m);
-		if(_bond) {
+		if (_bond) {
 			_bond->receivedQoS(path, now, count, rx_id, rx_ts);
 		}
 	}
@@ -462,7 +501,7 @@ public:
 	void processIncomingPathNegotiationRequest(uint64_t now, SharedPtr<Path>& path, int16_t remoteUtility)
 	{
 		Mutex::Lock _l(_bond_m);
-		if(_bond) {
+		if (_bond) {
 			_bond->processIncomingPathNegotiationRequest(now, path, remoteUtility);
 		}
 	}
@@ -473,10 +512,10 @@ public:
 	inline bool rateGatePathNegotiation(int64_t now, SharedPtr<Path>& path)
 	{
 		Mutex::Lock _l(_bond_m);
-		if(_bond) {
+		if (_bond) {
 			return _bond->rateGatePathNegotiation(now, path);
 		}
-		return false; // Default behavior. If there is no bond, we drop these
+		return false;	// Default behavior. If there is no bond, we drop these
 	}
 
 	/**
@@ -485,7 +524,7 @@ public:
 	bool flowHashingSupported()
 	{
 		Mutex::Lock _l(_bond_m);
-		if(_bond) {
+		if (_bond) {
 			return _bond->flowHashingSupported();
 		}
 		return false;
@@ -496,8 +535,7 @@ public:
 	 *
 	 * This does not serialize everything, just non-ephemeral information.
 	 */
-	template<unsigned int C>
-	inline void serializeForCache(Buffer<C> &b) const
+	template <unsigned int C> inline void serializeForCache(Buffer<C>& b) const
 	{
 		b.append((uint8_t)2);
 
@@ -511,22 +549,22 @@ public:
 		{
 			Mutex::Lock _l(_paths_m);
 			unsigned int pc = 0;
-			for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
+			for (unsigned int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
 				if (_paths[i].p) {
 					++pc;
-				} else {
+				}
+				else {
 					break;
 				}
 			}
 			b.append((uint16_t)pc);
-			for(unsigned int i=0;i<pc;++i) {
+			for (unsigned int i = 0; i < pc; ++i) {
 				_paths[i].p->address().serialize(b);
 			}
 		}
 	}
 
-	template<unsigned int C>
-	inline static SharedPtr<Peer> deserializeFromCache(int64_t now,void *tPtr,Buffer<C> &b,const RuntimeEnvironment *renv)
+	template <unsigned int C> inline static SharedPtr<Peer> deserializeFromCache(int64_t now, void* tPtr, Buffer<C>& b, const RuntimeEnvironment* renv)
 	{
 		try {
 			unsigned int ptr = 0;
@@ -535,12 +573,12 @@ public:
 			}
 
 			Identity id;
-			ptr += id.deserialize(b,ptr);
-			if (!id) {
+			ptr += id.deserialize(b, ptr);
+			if (! id) {
 				return SharedPtr<Peer>();
 			}
 
-			SharedPtr<Peer> p(new Peer(renv,renv->identity,id));
+			SharedPtr<Peer> p(new Peer(renv, renv->identity, id));
 
 			p->_vProto = b.template at<uint16_t>(ptr);
 			ptr += 2;
@@ -556,20 +594,22 @@ public:
 			// Paths are fairly ephemeral in the real world in most cases.
 			const unsigned int tryPathCount = b.template at<uint16_t>(ptr);
 			ptr += 2;
-			for(unsigned int i=0;i<tryPathCount;++i) {
+			for (unsigned int i = 0; i < tryPathCount; ++i) {
 				InetAddress inaddr;
 				try {
-					ptr += inaddr.deserialize(b,ptr);
+					ptr += inaddr.deserialize(b, ptr);
 					if (inaddr) {
-						p->attemptToContactAt(tPtr,-1,inaddr,now,true);
+						p->attemptToContactAt(tPtr, -1, inaddr, now, true);
 					}
-				} catch ( ... ) {
+				}
+				catch (...) {
 					break;
 				}
 			}
 
 			return p;
-		} catch ( ... ) {
+		}
+		catch (...) {
 			return SharedPtr<Peer>();
 		}
 	}
@@ -577,12 +617,16 @@ public:
 	/**
 	 * @return The bonding policy used to reach this peer
 	 */
-	SharedPtr<Bond> bond() { return _bond; }
+	SharedPtr<Bond> bond()
+	{
+		return _bond;
+	}
 
 	/**
 	 * @return The bonding policy used to reach this peer
 	 */
-	inline int8_t bondingPolicy() {
+	inline int8_t bondingPolicy()
+	{
 		Mutex::Lock _l(_bond_m);
 		if (_bond) {
 			return _bond->policy();
@@ -593,7 +637,8 @@ public:
 	/**
 	 * @return the number of links in this bond which are considered alive
 	 */
-	inline uint8_t getNumAliveLinks() {
+	inline uint8_t getNumAliveLinks()
+	{
 		Mutex::Lock _l(_paths_m);
 		if (_bond) {
 			return _bond->getNumAliveLinks();
@@ -604,7 +649,8 @@ public:
 	/**
 	 * @return the number of links in this bond
 	 */
-	inline uint8_t getNumTotalLinks() {
+	inline uint8_t getNumTotalLinks()
+	{
 		Mutex::Lock _l(_paths_m);
 		if (_bond) {
 			return _bond->getNumTotalLinks();
@@ -612,31 +658,36 @@ public:
 		return 0;
 	}
 
-	//inline const AES *aesKeysIfSupported() const
+	// inline const AES *aesKeysIfSupported() const
 	//{ return (const AES *)0; }
 
-	inline const AES *aesKeysIfSupported() const
-	{ return (_vProto >= 12) ? _aesKeys : (const AES *)0; }
-
-	inline const AES *aesKeys() const
-	{ return _aesKeys; }
+	inline const AES* aesKeysIfSupported() const
+	{
+		return (_vProto >= 12) ? _aesKeys : (const AES*)0;
+	}
 
-private:
-	struct _PeerPath
+	inline const AES* aesKeys() const
 	{
-		_PeerPath() : lr(0),p(),priority(1) {}
-		int64_t lr; // time of last valid ZeroTier packet
+		return _aesKeys;
+	}
+
+  private:
+	struct _PeerPath {
+		_PeerPath() : lr(0), p(), priority(1)
+		{
+		}
+		int64_t lr;	  // time of last valid ZeroTier packet
 		SharedPtr<Path> p;
-		long priority; // >= 1, higher is better
+		long priority;	 // >= 1, higher is better
 	};
 
 	uint8_t _key[ZT_SYMMETRIC_KEY_SIZE];
 	AES _aesKeys[2];
 
-	const RuntimeEnvironment *RR;
+	const RuntimeEnvironment* RR;
 
-	int64_t _lastReceive; // direct or indirect
-	int64_t _lastNontrivialReceive; // frames, things like netconf, etc.
+	int64_t _lastReceive;			  // direct or indirect
+	int64_t _lastNontrivialReceive;	  // frames, things like netconf, etc.
 	int64_t _lastTriedMemorizedPath;
 	int64_t _lastDirectPathPushSent;
 	int64_t _lastDirectPathPushReceive;
@@ -654,7 +705,7 @@ private:
 	uint16_t _vMinor;
 	uint16_t _vRevision;
 
-	std::list< std::pair< Path *, int64_t > > _lastTriedPath;
+	std::list<std::pair<Path*, int64_t> > _lastTriedPath;
 	Mutex _lastTriedPath_m;
 
 	_PeerPath _paths[ZT_MAX_PEER_NETWORK_PATHS];
@@ -679,7 +730,7 @@ private:
 	SharedPtr<Bond> _bond;
 
 #ifndef ZT_NO_PEER_METRICS
-	prometheus::Histogram<uint64_t> &_peer_latency;
+	prometheus::Histogram<uint64_t>& _peer_latency;
 	prometheus::simpleapi::gauge_metric_t _alive_path_count;
 	prometheus::simpleapi::gauge_metric_t _dead_path_count;
 	prometheus::simpleapi::counter_metric_t _incoming_packet;
@@ -688,15 +739,14 @@ private:
 #endif
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 // Add a swap() for shared ptr's to peers to speed up peer sorts
 namespace std {
-	template<>
-	inline void swap(ZeroTier::SharedPtr<ZeroTier::Peer> &a,ZeroTier::SharedPtr<ZeroTier::Peer> &b)
-	{
-		a.swap(b);
-	}
+template <> inline void swap(ZeroTier::SharedPtr<ZeroTier::Peer>& a, ZeroTier::SharedPtr<ZeroTier::Peer>& b)
+{
+	a.swap(b);
 }
+}	// namespace std
 
 #endif

+ 504 - 428
node/Poly1305.cpp

@@ -4,16 +4,17 @@ D. J. Bernstein
 Public domain.
 */
 
-#include "Constants.hpp"
 #include "Poly1305.hpp"
 
-#include <stdio.h>
+#include "Constants.hpp"
+
 #include <stdint.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 #ifdef __WINDOWS__
-#pragma warning(disable: 4146)
+#pragma warning(disable : 4146)
 #endif
 
 namespace ZeroTier {
@@ -21,8 +22,8 @@ namespace ZeroTier {
 namespace {
 
 typedef struct poly1305_context {
-  size_t aligner;
-  unsigned char opaque[136];
+	size_t aligner;
+	unsigned char opaque[136];
 } poly1305_context;
 
 #if (defined(_MSC_VER) || defined(__GNUC__)) && (defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) || defined(__AMD64__) || defined(_M_X64))
@@ -31,32 +32,42 @@ typedef struct poly1305_context {
 // 128-bit implementation for MSC and GCC from Poly1305-donna
 
 #if defined(_MSC_VER)
-  #include <intrin.h>
-
-  typedef struct uint128_t {
-    unsigned long long lo;
-    unsigned long long hi;
-  } uint128_t;
-
-  #define MUL(out, x, y) out.lo = _umul128((x), (y), &out.hi)
-  #define ADD(out, in) { unsigned long long t = out.lo; out.lo += in.lo; out.hi += (out.lo < t) + in.hi; }
-  #define ADDLO(out, in) { unsigned long long t = out.lo; out.lo += in; out.hi += (out.lo < t); }
-  #define SHR(in, shift) (__shiftright128(in.lo, in.hi, (shift)))
-  #define LO(in) (in.lo)
+#include <intrin.h>
+
+typedef struct uint128_t {
+	unsigned long long lo;
+	unsigned long long hi;
+} uint128_t;
+
+#define MUL(out, x, y) out.lo = _umul128((x), (y), &out.hi)
+#define ADD(out, in)                                                                                                                                                                                                                           \
+	{                                                                                                                                                                                                                                          \
+		unsigned long long t = out.lo;                                                                                                                                                                                                         \
+		out.lo += in.lo;                                                                                                                                                                                                                       \
+		out.hi += (out.lo < t) + in.hi;                                                                                                                                                                                                        \
+	}
+#define ADDLO(out, in)                                                                                                                                                                                                                         \
+	{                                                                                                                                                                                                                                          \
+		unsigned long long t = out.lo;                                                                                                                                                                                                         \
+		out.lo += in;                                                                                                                                                                                                                          \
+		out.hi += (out.lo < t);                                                                                                                                                                                                                \
+	}
+#define SHR(in, shift) (__shiftright128(in.lo, in.hi, (shift)))
+#define LO(in)		   (in.lo)
 
 //  #define POLY1305_NOINLINE __declspec(noinline)
 #elif defined(__GNUC__)
-  #if defined(__SIZEOF_INT128__)
-    typedef unsigned __int128 uint128_t;
-  #else
-    typedef unsigned uint128_t __attribute__((mode(TI)));
-  #endif
-
-  #define MUL(out, x, y) out = ((uint128_t)x * y)
-  #define ADD(out, in) out += in
-  #define ADDLO(out, in) out += in
-  #define SHR(in, shift) (unsigned long long)(in >> (shift))
-  #define LO(in) (unsigned long long)(in)
+#if defined(__SIZEOF_INT128__)
+typedef unsigned __int128 uint128_t;
+#else
+typedef unsigned uint128_t __attribute__((mode(TI)));
+#endif
+
+#define MUL(out, x, y) out = ((uint128_t)x * y)
+#define ADD(out, in)   out += in
+#define ADDLO(out, in) out += in
+#define SHR(in, shift) (unsigned long long)(in >> (shift))
+#define LO(in)		   (unsigned long long)(in)
 
 //  #define POLY1305_NOINLINE __attribute__((noinline))
 #endif
@@ -65,192 +76,228 @@ typedef struct poly1305_context {
 
 /* 17 + sizeof(size_t) + 8*sizeof(unsigned long long) */
 typedef struct poly1305_state_internal_t {
-  unsigned long long r[3];
-  unsigned long long h[3];
-  unsigned long long pad[2];
-  size_t leftover;
-  unsigned char buffer[poly1305_block_size];
-  unsigned char final;
+	unsigned long long r[3];
+	unsigned long long h[3];
+	unsigned long long pad[2];
+	size_t leftover;
+	unsigned char buffer[poly1305_block_size];
+	unsigned char final;
 } poly1305_state_internal_t;
 
 #if defined(ZT_NO_TYPE_PUNNING) || (__BYTE_ORDER != __LITTLE_ENDIAN)
-static inline unsigned long long U8TO64(const unsigned char *p)
+static inline unsigned long long U8TO64(const unsigned char* p)
 {
-  return
-    (((unsigned long long)(p[0] & 0xff)      ) |
-     ((unsigned long long)(p[1] & 0xff) <<  8) |
-     ((unsigned long long)(p[2] & 0xff) << 16) |
-     ((unsigned long long)(p[3] & 0xff) << 24) |
-     ((unsigned long long)(p[4] & 0xff) << 32) |
-     ((unsigned long long)(p[5] & 0xff) << 40) |
-     ((unsigned long long)(p[6] & 0xff) << 48) |
-     ((unsigned long long)(p[7] & 0xff) << 56));
+	return (
+		((unsigned long long)(p[0] & 0xff)) | ((unsigned long long)(p[1] & 0xff) << 8) | ((unsigned long long)(p[2] & 0xff) << 16) | ((unsigned long long)(p[3] & 0xff) << 24) | ((unsigned long long)(p[4] & 0xff) << 32)
+		| ((unsigned long long)(p[5] & 0xff) << 40) | ((unsigned long long)(p[6] & 0xff) << 48) | ((unsigned long long)(p[7] & 0xff) << 56));
 }
 #else
-#define U8TO64(p) (*reinterpret_cast<const unsigned long long *>(p))
+#define U8TO64(p) (*reinterpret_cast<const unsigned long long*>(p))
 #endif
 
 #if defined(ZT_NO_TYPE_PUNNING) || (__BYTE_ORDER != __LITTLE_ENDIAN)
-static inline void U64TO8(unsigned char *p, unsigned long long v)
+static inline void U64TO8(unsigned char* p, unsigned long long v)
 {
-  p[0] = (v      ) & 0xff;
-  p[1] = (v >>  8) & 0xff;
-  p[2] = (v >> 16) & 0xff;
-  p[3] = (v >> 24) & 0xff;
-  p[4] = (v >> 32) & 0xff;
-  p[5] = (v >> 40) & 0xff;
-  p[6] = (v >> 48) & 0xff;
-  p[7] = (v >> 56) & 0xff;
+	p[0] = (v) & 0xff;
+	p[1] = (v >> 8) & 0xff;
+	p[2] = (v >> 16) & 0xff;
+	p[3] = (v >> 24) & 0xff;
+	p[4] = (v >> 32) & 0xff;
+	p[5] = (v >> 40) & 0xff;
+	p[6] = (v >> 48) & 0xff;
+	p[7] = (v >> 56) & 0xff;
 }
 #else
-#define U64TO8(p,v) ((*reinterpret_cast<unsigned long long *>(p)) = (v))
+#define U64TO8(p, v) ((*reinterpret_cast<unsigned long long*>(p)) = (v))
 #endif
 
-static inline void poly1305_init(poly1305_context *ctx, const unsigned char key[32]) {
-  poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx;
-  unsigned long long t0,t1;
+static inline void poly1305_init(poly1305_context* ctx, const unsigned char key[32])
+{
+	poly1305_state_internal_t* st = (poly1305_state_internal_t*)ctx;
+	unsigned long long t0, t1;
 
-  /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
-  t0 = U8TO64(&key[0]);
-  t1 = U8TO64(&key[8]);
+	/* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
+	t0 = U8TO64(&key[0]);
+	t1 = U8TO64(&key[8]);
 
-  st->r[0] = ( t0                    ) & 0xffc0fffffff;
-  st->r[1] = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff;
-  st->r[2] = ((t1 >> 24)             ) & 0x00ffffffc0f;
+	st->r[0] = (t0) & 0xffc0fffffff;
+	st->r[1] = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff;
+	st->r[2] = ((t1 >> 24)) & 0x00ffffffc0f;
 
-  /* h = 0 */
-  st->h[0] = 0;
-  st->h[1] = 0;
-  st->h[2] = 0;
+	/* h = 0 */
+	st->h[0] = 0;
+	st->h[1] = 0;
+	st->h[2] = 0;
 
-  /* save pad for later */
-  st->pad[0] = U8TO64(&key[16]);
-  st->pad[1] = U8TO64(&key[24]);
+	/* save pad for later */
+	st->pad[0] = U8TO64(&key[16]);
+	st->pad[1] = U8TO64(&key[24]);
 
-  st->leftover = 0;
-  st->final = 0;
+	st->leftover = 0;
+	st->final = 0;
 }
 
-static inline void poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, size_t bytes) {
-  const unsigned long long hibit = (st->final) ? 0 : ((unsigned long long)1 << 40); /* 1 << 128 */
-  unsigned long long r0,r1,r2;
-  unsigned long long s1,s2;
-  unsigned long long h0,h1,h2;
-  unsigned long long c;
-  uint128_t d0,d1,d2,d;
-
-  r0 = st->r[0];
-  r1 = st->r[1];
-  r2 = st->r[2];
-
-  h0 = st->h[0];
-  h1 = st->h[1];
-  h2 = st->h[2];
-
-  s1 = r1 * (5 << 2);
-  s2 = r2 * (5 << 2);
-
-  while (bytes >= poly1305_block_size) {
-    unsigned long long t0,t1;
-
-    /* h += m[i] */
-    t0 = U8TO64(&m[0]);
-    t1 = U8TO64(&m[8]);
-
-    h0 += (( t0                    ) & 0xfffffffffff);
-    h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff);
-    h2 += (((t1 >> 24)             ) & 0x3ffffffffff) | hibit;
-
-    /* h *= r */
-    MUL(d0, h0, r0); MUL(d, h1, s2); ADD(d0, d); MUL(d, h2, s1); ADD(d0, d);
-    MUL(d1, h0, r1); MUL(d, h1, r0); ADD(d1, d); MUL(d, h2, s2); ADD(d1, d);
-    MUL(d2, h0, r2); MUL(d, h1, r1); ADD(d2, d); MUL(d, h2, r0); ADD(d2, d);
-
-    /* (partial) h %= p */
-                  c = SHR(d0, 44); h0 = LO(d0) & 0xfffffffffff;
-    ADDLO(d1, c); c = SHR(d1, 44); h1 = LO(d1) & 0xfffffffffff;
-    ADDLO(d2, c); c = SHR(d2, 42); h2 = LO(d2) & 0x3ffffffffff;
-    h0  += c * 5; c = (h0 >> 44);  h0 =    h0  & 0xfffffffffff;
-    h1  += c;
-
-    m += poly1305_block_size;
-    bytes -= poly1305_block_size;
-  }
-
-  st->h[0] = h0;
-  st->h[1] = h1;
-  st->h[2] = h2;
+static inline void poly1305_blocks(poly1305_state_internal_t* st, const unsigned char* m, size_t bytes)
+{
+	const unsigned long long hibit = (st->final) ? 0 : ((unsigned long long)1 << 40); /* 1 << 128 */
+	unsigned long long r0, r1, r2;
+	unsigned long long s1, s2;
+	unsigned long long h0, h1, h2;
+	unsigned long long c;
+	uint128_t d0, d1, d2, d;
+
+	r0 = st->r[0];
+	r1 = st->r[1];
+	r2 = st->r[2];
+
+	h0 = st->h[0];
+	h1 = st->h[1];
+	h2 = st->h[2];
+
+	s1 = r1 * (5 << 2);
+	s2 = r2 * (5 << 2);
+
+	while (bytes >= poly1305_block_size) {
+		unsigned long long t0, t1;
+
+		/* h += m[i] */
+		t0 = U8TO64(&m[0]);
+		t1 = U8TO64(&m[8]);
+
+		h0 += ((t0) & 0xfffffffffff);
+		h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff);
+		h2 += (((t1 >> 24)) & 0x3ffffffffff) | hibit;
+
+		/* h *= r */
+		MUL(d0, h0, r0);
+		MUL(d, h1, s2);
+		ADD(d0, d);
+		MUL(d, h2, s1);
+		ADD(d0, d);
+		MUL(d1, h0, r1);
+		MUL(d, h1, r0);
+		ADD(d1, d);
+		MUL(d, h2, s2);
+		ADD(d1, d);
+		MUL(d2, h0, r2);
+		MUL(d, h1, r1);
+		ADD(d2, d);
+		MUL(d, h2, r0);
+		ADD(d2, d);
+
+		/* (partial) h %= p */
+		c = SHR(d0, 44);
+		h0 = LO(d0) & 0xfffffffffff;
+		ADDLO(d1, c);
+		c = SHR(d1, 44);
+		h1 = LO(d1) & 0xfffffffffff;
+		ADDLO(d2, c);
+		c = SHR(d2, 42);
+		h2 = LO(d2) & 0x3ffffffffff;
+		h0 += c * 5;
+		c = (h0 >> 44);
+		h0 = h0 & 0xfffffffffff;
+		h1 += c;
+
+		m += poly1305_block_size;
+		bytes -= poly1305_block_size;
+	}
+
+	st->h[0] = h0;
+	st->h[1] = h1;
+	st->h[2] = h2;
 }
 
-static inline void poly1305_finish(poly1305_context *ctx, unsigned char mac[16]) {
-  poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx;
-  unsigned long long h0,h1,h2,c;
-  unsigned long long g0,g1,g2;
-  unsigned long long t0,t1;
-
-  /* process the remaining block */
-  if (st->leftover) {
-    size_t i = st->leftover;
-    st->buffer[i] = 1;
-    for (i = i + 1; i < poly1305_block_size; i++) {
-      st->buffer[i] = 0;
-    }
-    st->final = 1;
-    poly1305_blocks(st, st->buffer, poly1305_block_size);
-  }
-
-  /* fully carry h */
-  h0 = st->h[0];
-  h1 = st->h[1];
-  h2 = st->h[2];
-
-               c = (h1 >> 44); h1 &= 0xfffffffffff;
-  h2 += c;     c = (h2 >> 42); h2 &= 0x3ffffffffff;
-  h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff;
-  h1 += c;     c = (h1 >> 44); h1 &= 0xfffffffffff;
-  h2 += c;     c = (h2 >> 42); h2 &= 0x3ffffffffff;
-  h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff;
-  h1 += c;
-
-  /* compute h + -p */
-  g0 = h0 + 5; c = (g0 >> 44); g0 &= 0xfffffffffff;
-  g1 = h1 + c; c = (g1 >> 44); g1 &= 0xfffffffffff;
-  g2 = h2 + c - ((unsigned long long)1 << 42);
-
-  /* select h if h < p, or h + -p if h >= p */
-  c = (g2 >> ((sizeof(unsigned long long) * 8) - 1)) - 1;
-  g0 &= c;
-  g1 &= c;
-  g2 &= c;
-  c = ~c;
-  h0 = (h0 & c) | g0;
-  h1 = (h1 & c) | g1;
-  h2 = (h2 & c) | g2;
-
-  /* h = (h + pad) */
-  t0 = st->pad[0];
-  t1 = st->pad[1];
-
-  h0 += (( t0                    ) & 0xfffffffffff)    ; c = (h0 >> 44); h0 &= 0xfffffffffff;
-  h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c; c = (h1 >> 44); h1 &= 0xfffffffffff;
-  h2 += (((t1 >> 24)             ) & 0x3ffffffffff) + c;                 h2 &= 0x3ffffffffff;
-
-  /* mac = h % (2^128) */
-  h0 = ((h0      ) | (h1 << 44));
-  h1 = ((h1 >> 20) | (h2 << 24));
-
-  U64TO8(&mac[0], h0);
-  U64TO8(&mac[8], h1);
-
-  /* zero out the state */
-  st->h[0] = 0;
-  st->h[1] = 0;
-  st->h[2] = 0;
-  st->r[0] = 0;
-  st->r[1] = 0;
-  st->r[2] = 0;
-  st->pad[0] = 0;
-  st->pad[1] = 0;
+static inline void poly1305_finish(poly1305_context* ctx, unsigned char mac[16])
+{
+	poly1305_state_internal_t* st = (poly1305_state_internal_t*)ctx;
+	unsigned long long h0, h1, h2, c;
+	unsigned long long g0, g1, g2;
+	unsigned long long t0, t1;
+
+	/* process the remaining block */
+	if (st->leftover) {
+		size_t i = st->leftover;
+		st->buffer[i] = 1;
+		for (i = i + 1; i < poly1305_block_size; i++) {
+			st->buffer[i] = 0;
+		}
+		st->final = 1;
+		poly1305_blocks(st, st->buffer, poly1305_block_size);
+	}
+
+	/* fully carry h */
+	h0 = st->h[0];
+	h1 = st->h[1];
+	h2 = st->h[2];
+
+	c = (h1 >> 44);
+	h1 &= 0xfffffffffff;
+	h2 += c;
+	c = (h2 >> 42);
+	h2 &= 0x3ffffffffff;
+	h0 += c * 5;
+	c = (h0 >> 44);
+	h0 &= 0xfffffffffff;
+	h1 += c;
+	c = (h1 >> 44);
+	h1 &= 0xfffffffffff;
+	h2 += c;
+	c = (h2 >> 42);
+	h2 &= 0x3ffffffffff;
+	h0 += c * 5;
+	c = (h0 >> 44);
+	h0 &= 0xfffffffffff;
+	h1 += c;
+
+	/* compute h + -p */
+	g0 = h0 + 5;
+	c = (g0 >> 44);
+	g0 &= 0xfffffffffff;
+	g1 = h1 + c;
+	c = (g1 >> 44);
+	g1 &= 0xfffffffffff;
+	g2 = h2 + c - ((unsigned long long)1 << 42);
+
+	/* select h if h < p, or h + -p if h >= p */
+	c = (g2 >> ((sizeof(unsigned long long) * 8) - 1)) - 1;
+	g0 &= c;
+	g1 &= c;
+	g2 &= c;
+	c = ~c;
+	h0 = (h0 & c) | g0;
+	h1 = (h1 & c) | g1;
+	h2 = (h2 & c) | g2;
+
+	/* h = (h + pad) */
+	t0 = st->pad[0];
+	t1 = st->pad[1];
+
+	h0 += ((t0) & 0xfffffffffff);
+	c = (h0 >> 44);
+	h0 &= 0xfffffffffff;
+	h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c;
+	c = (h1 >> 44);
+	h1 &= 0xfffffffffff;
+	h2 += (((t1 >> 24)) & 0x3ffffffffff) + c;
+	h2 &= 0x3ffffffffff;
+
+	/* mac = h % (2^128) */
+	h0 = ((h0) | (h1 << 44));
+	h1 = ((h1 >> 20) | (h2 << 24));
+
+	U64TO8(&mac[0], h0);
+	U64TO8(&mac[8], h1);
+
+	/* zero out the state */
+	st->h[0] = 0;
+	st->h[1] = 0;
+	st->h[2] = 0;
+	st->r[0] = 0;
+	st->r[1] = 0;
+	st->r[2] = 0;
+	st->pad[0] = 0;
+	st->pad[1] = 0;
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -264,262 +311,291 @@ static inline void poly1305_finish(poly1305_context *ctx, unsigned char mac[16])
 
 /* 17 + sizeof(size_t) + 14*sizeof(unsigned long) */
 typedef struct poly1305_state_internal_t {
-  unsigned long r[5];
-  unsigned long h[5];
-  unsigned long pad[4];
-  size_t leftover;
-  unsigned char buffer[poly1305_block_size];
-  unsigned char final;
+	unsigned long r[5];
+	unsigned long h[5];
+	unsigned long pad[4];
+	size_t leftover;
+	unsigned char buffer[poly1305_block_size];
+	unsigned char final;
 } poly1305_state_internal_t;
 
 /* interpret four 8 bit unsigned integers as a 32 bit unsigned integer in little endian */
-static unsigned long
-U8TO32(const unsigned char *p) {
-  return
-    (((unsigned long)(p[0] & 0xff)      ) |
-       ((unsigned long)(p[1] & 0xff) <<  8) |
-         ((unsigned long)(p[2] & 0xff) << 16) |
-         ((unsigned long)(p[3] & 0xff) << 24));
+static unsigned long U8TO32(const unsigned char* p)
+{
+	return (((unsigned long)(p[0] & 0xff)) | ((unsigned long)(p[1] & 0xff) << 8) | ((unsigned long)(p[2] & 0xff) << 16) | ((unsigned long)(p[3] & 0xff) << 24));
 }
 
 /* store a 32 bit unsigned integer as four 8 bit unsigned integers in little endian */
-static void
-U32TO8(unsigned char *p, unsigned long v) {
-  p[0] = (v      ) & 0xff;
-  p[1] = (v >>  8) & 0xff;
-  p[2] = (v >> 16) & 0xff;
-  p[3] = (v >> 24) & 0xff;
+static void U32TO8(unsigned char* p, unsigned long v)
+{
+	p[0] = (v) & 0xff;
+	p[1] = (v >> 8) & 0xff;
+	p[2] = (v >> 16) & 0xff;
+	p[3] = (v >> 24) & 0xff;
 }
 
-static inline void
-poly1305_init(poly1305_context *ctx, const unsigned char key[32]) {
-  poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx;
-
-  /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
-  st->r[0] = (U8TO32(&key[ 0])     ) & 0x3ffffff;
-  st->r[1] = (U8TO32(&key[ 3]) >> 2) & 0x3ffff03;
-  st->r[2] = (U8TO32(&key[ 6]) >> 4) & 0x3ffc0ff;
-  st->r[3] = (U8TO32(&key[ 9]) >> 6) & 0x3f03fff;
-  st->r[4] = (U8TO32(&key[12]) >> 8) & 0x00fffff;
-
-  /* h = 0 */
-  st->h[0] = 0;
-  st->h[1] = 0;
-  st->h[2] = 0;
-  st->h[3] = 0;
-  st->h[4] = 0;
-
-  /* save pad for later */
-  st->pad[0] = U8TO32(&key[16]);
-  st->pad[1] = U8TO32(&key[20]);
-  st->pad[2] = U8TO32(&key[24]);
-  st->pad[3] = U8TO32(&key[28]);
-
-  st->leftover = 0;
-  st->final = 0;
+static inline void poly1305_init(poly1305_context* ctx, const unsigned char key[32])
+{
+	poly1305_state_internal_t* st = (poly1305_state_internal_t*)ctx;
+
+	/* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
+	st->r[0] = (U8TO32(&key[0])) & 0x3ffffff;
+	st->r[1] = (U8TO32(&key[3]) >> 2) & 0x3ffff03;
+	st->r[2] = (U8TO32(&key[6]) >> 4) & 0x3ffc0ff;
+	st->r[3] = (U8TO32(&key[9]) >> 6) & 0x3f03fff;
+	st->r[4] = (U8TO32(&key[12]) >> 8) & 0x00fffff;
+
+	/* h = 0 */
+	st->h[0] = 0;
+	st->h[1] = 0;
+	st->h[2] = 0;
+	st->h[3] = 0;
+	st->h[4] = 0;
+
+	/* save pad for later */
+	st->pad[0] = U8TO32(&key[16]);
+	st->pad[1] = U8TO32(&key[20]);
+	st->pad[2] = U8TO32(&key[24]);
+	st->pad[3] = U8TO32(&key[28]);
+
+	st->leftover = 0;
+	st->final = 0;
 }
 
-static inline void
-poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, size_t bytes) {
-  const unsigned long hibit = (st->final) ? 0 : (1 << 24); /* 1 << 128 */
-  unsigned long r0,r1,r2,r3,r4;
-  unsigned long s1,s2,s3,s4;
-  unsigned long h0,h1,h2,h3,h4;
-  unsigned long long d0,d1,d2,d3,d4;
-  unsigned long c;
-
-  r0 = st->r[0];
-  r1 = st->r[1];
-  r2 = st->r[2];
-  r3 = st->r[3];
-  r4 = st->r[4];
-
-  s1 = r1 * 5;
-  s2 = r2 * 5;
-  s3 = r3 * 5;
-  s4 = r4 * 5;
-
-  h0 = st->h[0];
-  h1 = st->h[1];
-  h2 = st->h[2];
-  h3 = st->h[3];
-  h4 = st->h[4];
-
-  while (bytes >= poly1305_block_size) {
-    /* h += m[i] */
-    h0 += (U8TO32(m+ 0)     ) & 0x3ffffff;
-    h1 += (U8TO32(m+ 3) >> 2) & 0x3ffffff;
-    h2 += (U8TO32(m+ 6) >> 4) & 0x3ffffff;
-    h3 += (U8TO32(m+ 9) >> 6) & 0x3ffffff;
-    h4 += (U8TO32(m+12) >> 8) | hibit;
-
-    /* h *= r */
-    d0 = ((unsigned long long)h0 * r0) + ((unsigned long long)h1 * s4) + ((unsigned long long)h2 * s3) + ((unsigned long long)h3 * s2) + ((unsigned long long)h4 * s1);
-    d1 = ((unsigned long long)h0 * r1) + ((unsigned long long)h1 * r0) + ((unsigned long long)h2 * s4) + ((unsigned long long)h3 * s3) + ((unsigned long long)h4 * s2);
-    d2 = ((unsigned long long)h0 * r2) + ((unsigned long long)h1 * r1) + ((unsigned long long)h2 * r0) + ((unsigned long long)h3 * s4) + ((unsigned long long)h4 * s3);
-    d3 = ((unsigned long long)h0 * r3) + ((unsigned long long)h1 * r2) + ((unsigned long long)h2 * r1) + ((unsigned long long)h3 * r0) + ((unsigned long long)h4 * s4);
-    d4 = ((unsigned long long)h0 * r4) + ((unsigned long long)h1 * r3) + ((unsigned long long)h2 * r2) + ((unsigned long long)h3 * r1) + ((unsigned long long)h4 * r0);
-
-    /* (partial) h %= p */
-                  c = (unsigned long)(d0 >> 26); h0 = (unsigned long)d0 & 0x3ffffff;
-    d1 += c;      c = (unsigned long)(d1 >> 26); h1 = (unsigned long)d1 & 0x3ffffff;
-    d2 += c;      c = (unsigned long)(d2 >> 26); h2 = (unsigned long)d2 & 0x3ffffff;
-    d3 += c;      c = (unsigned long)(d3 >> 26); h3 = (unsigned long)d3 & 0x3ffffff;
-    d4 += c;      c = (unsigned long)(d4 >> 26); h4 = (unsigned long)d4 & 0x3ffffff;
-    h0 += c * 5;  c =                (h0 >> 26); h0 =                h0 & 0x3ffffff;
-    h1 += c;
-
-    m += poly1305_block_size;
-    bytes -= poly1305_block_size;
-  }
-
-  st->h[0] = h0;
-  st->h[1] = h1;
-  st->h[2] = h2;
-  st->h[3] = h3;
-  st->h[4] = h4;
+static inline void poly1305_blocks(poly1305_state_internal_t* st, const unsigned char* m, size_t bytes)
+{
+	const unsigned long hibit = (st->final) ? 0 : (1 << 24); /* 1 << 128 */
+	unsigned long r0, r1, r2, r3, r4;
+	unsigned long s1, s2, s3, s4;
+	unsigned long h0, h1, h2, h3, h4;
+	unsigned long long d0, d1, d2, d3, d4;
+	unsigned long c;
+
+	r0 = st->r[0];
+	r1 = st->r[1];
+	r2 = st->r[2];
+	r3 = st->r[3];
+	r4 = st->r[4];
+
+	s1 = r1 * 5;
+	s2 = r2 * 5;
+	s3 = r3 * 5;
+	s4 = r4 * 5;
+
+	h0 = st->h[0];
+	h1 = st->h[1];
+	h2 = st->h[2];
+	h3 = st->h[3];
+	h4 = st->h[4];
+
+	while (bytes >= poly1305_block_size) {
+		/* h += m[i] */
+		h0 += (U8TO32(m + 0)) & 0x3ffffff;
+		h1 += (U8TO32(m + 3) >> 2) & 0x3ffffff;
+		h2 += (U8TO32(m + 6) >> 4) & 0x3ffffff;
+		h3 += (U8TO32(m + 9) >> 6) & 0x3ffffff;
+		h4 += (U8TO32(m + 12) >> 8) | hibit;
+
+		/* h *= r */
+		d0 = ((unsigned long long)h0 * r0) + ((unsigned long long)h1 * s4) + ((unsigned long long)h2 * s3) + ((unsigned long long)h3 * s2) + ((unsigned long long)h4 * s1);
+		d1 = ((unsigned long long)h0 * r1) + ((unsigned long long)h1 * r0) + ((unsigned long long)h2 * s4) + ((unsigned long long)h3 * s3) + ((unsigned long long)h4 * s2);
+		d2 = ((unsigned long long)h0 * r2) + ((unsigned long long)h1 * r1) + ((unsigned long long)h2 * r0) + ((unsigned long long)h3 * s4) + ((unsigned long long)h4 * s3);
+		d3 = ((unsigned long long)h0 * r3) + ((unsigned long long)h1 * r2) + ((unsigned long long)h2 * r1) + ((unsigned long long)h3 * r0) + ((unsigned long long)h4 * s4);
+		d4 = ((unsigned long long)h0 * r4) + ((unsigned long long)h1 * r3) + ((unsigned long long)h2 * r2) + ((unsigned long long)h3 * r1) + ((unsigned long long)h4 * r0);
+
+		/* (partial) h %= p */
+		c = (unsigned long)(d0 >> 26);
+		h0 = (unsigned long)d0 & 0x3ffffff;
+		d1 += c;
+		c = (unsigned long)(d1 >> 26);
+		h1 = (unsigned long)d1 & 0x3ffffff;
+		d2 += c;
+		c = (unsigned long)(d2 >> 26);
+		h2 = (unsigned long)d2 & 0x3ffffff;
+		d3 += c;
+		c = (unsigned long)(d3 >> 26);
+		h3 = (unsigned long)d3 & 0x3ffffff;
+		d4 += c;
+		c = (unsigned long)(d4 >> 26);
+		h4 = (unsigned long)d4 & 0x3ffffff;
+		h0 += c * 5;
+		c = (h0 >> 26);
+		h0 = h0 & 0x3ffffff;
+		h1 += c;
+
+		m += poly1305_block_size;
+		bytes -= poly1305_block_size;
+	}
+
+	st->h[0] = h0;
+	st->h[1] = h1;
+	st->h[2] = h2;
+	st->h[3] = h3;
+	st->h[4] = h4;
 }
 
-static inline void
-poly1305_finish(poly1305_context *ctx, unsigned char mac[16]) {
-  poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx;
-  unsigned long h0,h1,h2,h3,h4,c;
-  unsigned long g0,g1,g2,g3,g4;
-  unsigned long long f;
-  unsigned long mask;
-
-  /* process the remaining block */
-  if (st->leftover) {
-    size_t i = st->leftover;
-    st->buffer[i++] = 1;
-    for (; i < poly1305_block_size; i++) {
-      st->buffer[i] = 0;
-    }
-    st->final = 1;
-    poly1305_blocks(st, st->buffer, poly1305_block_size);
-  }
-
-  /* fully carry h */
-  h0 = st->h[0];
-  h1 = st->h[1];
-  h2 = st->h[2];
-  h3 = st->h[3];
-  h4 = st->h[4];
-
-               c = h1 >> 26; h1 = h1 & 0x3ffffff;
-  h2 +=     c; c = h2 >> 26; h2 = h2 & 0x3ffffff;
-  h3 +=     c; c = h3 >> 26; h3 = h3 & 0x3ffffff;
-  h4 +=     c; c = h4 >> 26; h4 = h4 & 0x3ffffff;
-  h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff;
-  h1 +=     c;
-
-  /* compute h + -p */
-  g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff;
-  g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff;
-  g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff;
-  g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff;
-  g4 = h4 + c - (1 << 26);
-
-  /* select h if h < p, or h + -p if h >= p */
-  mask = (g4 >> ((sizeof(unsigned long) * 8) - 1)) - 1;
-  g0 &= mask;
-  g1 &= mask;
-  g2 &= mask;
-  g3 &= mask;
-  g4 &= mask;
-  mask = ~mask;
-  h0 = (h0 & mask) | g0;
-  h1 = (h1 & mask) | g1;
-  h2 = (h2 & mask) | g2;
-  h3 = (h3 & mask) | g3;
-  h4 = (h4 & mask) | g4;
-
-  /* h = h % (2^128) */
-  h0 = ((h0      ) | (h1 << 26)) & 0xffffffff;
-  h1 = ((h1 >>  6) | (h2 << 20)) & 0xffffffff;
-  h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
-  h3 = ((h3 >> 18) | (h4 <<  8)) & 0xffffffff;
-
-  /* mac = (h + pad) % (2^128) */
-  f = (unsigned long long)h0 + st->pad[0]            ; h0 = (unsigned long)f;
-  f = (unsigned long long)h1 + st->pad[1] + (f >> 32); h1 = (unsigned long)f;
-  f = (unsigned long long)h2 + st->pad[2] + (f >> 32); h2 = (unsigned long)f;
-  f = (unsigned long long)h3 + st->pad[3] + (f >> 32); h3 = (unsigned long)f;
-
-  U32TO8(mac +  0, h0);
-  U32TO8(mac +  4, h1);
-  U32TO8(mac +  8, h2);
-  U32TO8(mac + 12, h3);
-
-  /* zero out the state */
-  st->h[0] = 0;
-  st->h[1] = 0;
-  st->h[2] = 0;
-  st->h[3] = 0;
-  st->h[4] = 0;
-  st->r[0] = 0;
-  st->r[1] = 0;
-  st->r[2] = 0;
-  st->r[3] = 0;
-  st->r[4] = 0;
-  st->pad[0] = 0;
-  st->pad[1] = 0;
-  st->pad[2] = 0;
-  st->pad[3] = 0;
+static inline void poly1305_finish(poly1305_context* ctx, unsigned char mac[16])
+{
+	poly1305_state_internal_t* st = (poly1305_state_internal_t*)ctx;
+	unsigned long h0, h1, h2, h3, h4, c;
+	unsigned long g0, g1, g2, g3, g4;
+	unsigned long long f;
+	unsigned long mask;
+
+	/* process the remaining block */
+	if (st->leftover) {
+		size_t i = st->leftover;
+		st->buffer[i++] = 1;
+		for (; i < poly1305_block_size; i++) {
+			st->buffer[i] = 0;
+		}
+		st->final = 1;
+		poly1305_blocks(st, st->buffer, poly1305_block_size);
+	}
+
+	/* fully carry h */
+	h0 = st->h[0];
+	h1 = st->h[1];
+	h2 = st->h[2];
+	h3 = st->h[3];
+	h4 = st->h[4];
+
+	c = h1 >> 26;
+	h1 = h1 & 0x3ffffff;
+	h2 += c;
+	c = h2 >> 26;
+	h2 = h2 & 0x3ffffff;
+	h3 += c;
+	c = h3 >> 26;
+	h3 = h3 & 0x3ffffff;
+	h4 += c;
+	c = h4 >> 26;
+	h4 = h4 & 0x3ffffff;
+	h0 += c * 5;
+	c = h0 >> 26;
+	h0 = h0 & 0x3ffffff;
+	h1 += c;
+
+	/* compute h + -p */
+	g0 = h0 + 5;
+	c = g0 >> 26;
+	g0 &= 0x3ffffff;
+	g1 = h1 + c;
+	c = g1 >> 26;
+	g1 &= 0x3ffffff;
+	g2 = h2 + c;
+	c = g2 >> 26;
+	g2 &= 0x3ffffff;
+	g3 = h3 + c;
+	c = g3 >> 26;
+	g3 &= 0x3ffffff;
+	g4 = h4 + c - (1 << 26);
+
+	/* select h if h < p, or h + -p if h >= p */
+	mask = (g4 >> ((sizeof(unsigned long) * 8) - 1)) - 1;
+	g0 &= mask;
+	g1 &= mask;
+	g2 &= mask;
+	g3 &= mask;
+	g4 &= mask;
+	mask = ~mask;
+	h0 = (h0 & mask) | g0;
+	h1 = (h1 & mask) | g1;
+	h2 = (h2 & mask) | g2;
+	h3 = (h3 & mask) | g3;
+	h4 = (h4 & mask) | g4;
+
+	/* h = h % (2^128) */
+	h0 = ((h0) | (h1 << 26)) & 0xffffffff;
+	h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff;
+	h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
+	h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff;
+
+	/* mac = (h + pad) % (2^128) */
+	f = (unsigned long long)h0 + st->pad[0];
+	h0 = (unsigned long)f;
+	f = (unsigned long long)h1 + st->pad[1] + (f >> 32);
+	h1 = (unsigned long)f;
+	f = (unsigned long long)h2 + st->pad[2] + (f >> 32);
+	h2 = (unsigned long)f;
+	f = (unsigned long long)h3 + st->pad[3] + (f >> 32);
+	h3 = (unsigned long)f;
+
+	U32TO8(mac + 0, h0);
+	U32TO8(mac + 4, h1);
+	U32TO8(mac + 8, h2);
+	U32TO8(mac + 12, h3);
+
+	/* zero out the state */
+	st->h[0] = 0;
+	st->h[1] = 0;
+	st->h[2] = 0;
+	st->h[3] = 0;
+	st->h[4] = 0;
+	st->r[0] = 0;
+	st->r[1] = 0;
+	st->r[2] = 0;
+	st->r[3] = 0;
+	st->r[4] = 0;
+	st->pad[0] = 0;
+	st->pad[1] = 0;
+	st->pad[2] = 0;
+	st->pad[3] = 0;
 }
 
 //////////////////////////////////////////////////////////////////////////////
 
-#endif // MSC/GCC or not
-
-static inline void poly1305_update(poly1305_context *ctx, const unsigned char *m, size_t bytes) {
-  poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx;
-  size_t i;
-
-  /* handle leftover */
-  if (st->leftover) {
-    size_t want = (poly1305_block_size - st->leftover);
-    if (want > bytes) {
-      want = bytes;
-    }
-    for (i = 0; i < want; i++) {
-      st->buffer[st->leftover + i] = m[i];
-    }
-    bytes -= want;
-    m += want;
-    st->leftover += want;
-    if (st->leftover < poly1305_block_size) {
-      return;
-    }
-    poly1305_blocks(st, st->buffer, poly1305_block_size);
-    st->leftover = 0;
-  }
-
-  /* process full blocks */
-  if (bytes >= poly1305_block_size) {
-    size_t want = (bytes & ~(poly1305_block_size - 1));
-    poly1305_blocks(st, m, want);
-    m += want;
-    bytes -= want;
-  }
-
-  /* store leftover */
-  if (bytes) {
-    for (i = 0; i < bytes; i++) {
-      st->buffer[st->leftover + i] = m[i];
-    }
-    st->leftover += bytes;
-  }
+#endif	 // MSC/GCC or not
+
+static inline void poly1305_update(poly1305_context* ctx, const unsigned char* m, size_t bytes)
+{
+	poly1305_state_internal_t* st = (poly1305_state_internal_t*)ctx;
+	size_t i;
+
+	/* handle leftover */
+	if (st->leftover) {
+		size_t want = (poly1305_block_size - st->leftover);
+		if (want > bytes) {
+			want = bytes;
+		}
+		for (i = 0; i < want; i++) {
+			st->buffer[st->leftover + i] = m[i];
+		}
+		bytes -= want;
+		m += want;
+		st->leftover += want;
+		if (st->leftover < poly1305_block_size) {
+			return;
+		}
+		poly1305_blocks(st, st->buffer, poly1305_block_size);
+		st->leftover = 0;
+	}
+
+	/* process full blocks */
+	if (bytes >= poly1305_block_size) {
+		size_t want = (bytes & ~(poly1305_block_size - 1));
+		poly1305_blocks(st, m, want);
+		m += want;
+		bytes -= want;
+	}
+
+	/* store leftover */
+	if (bytes) {
+		for (i = 0; i < bytes; i++) {
+			st->buffer[st->leftover + i] = m[i];
+		}
+		st->leftover += bytes;
+	}
 }
 
-} // anonymous namespace
+}	// anonymous namespace
 
-void Poly1305::compute(void *auth,const void *data,unsigned int len,const void *key)
+void Poly1305::compute(void* auth, const void* data, unsigned int len, const void* key)
 {
-  poly1305_context ctx;
-  poly1305_init(&ctx,reinterpret_cast<const unsigned char *>(key));
-  poly1305_update(&ctx,reinterpret_cast<const unsigned char *>(data),(size_t)len);
-  poly1305_finish(&ctx,reinterpret_cast<unsigned char *>(auth));
+	poly1305_context ctx;
+	poly1305_init(&ctx, reinterpret_cast<const unsigned char*>(key));
+	poly1305_update(&ctx, reinterpret_cast<const unsigned char*>(data), (size_t)len);
+	poly1305_finish(&ctx, reinterpret_cast<unsigned char*>(auth));
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier

+ 4 - 5
node/Poly1305.hpp

@@ -30,9 +30,8 @@ namespace ZeroTier {
  * keystream as a one-time-use key. These 32 bytes are then discarded and
  * the packet is encrypted with the next N bytes.
  */
-class Poly1305
-{
-public:
+class Poly1305 {
+  public:
 	/**
 	 * Compute a one-time authentication code
 	 *
@@ -41,9 +40,9 @@ public:
 	 * @param len Length of data to authenticate in bytes
 	 * @param key 32-byte one-time use key to authenticate data (must not be reused)
 	 */
-	static void compute(void *auth,const void *data,unsigned int len,const void *key);
+	static void compute(void* auth, const void* data, unsigned int len, const void* key);
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 14 - 12
node/Revocation.cpp

@@ -12,32 +12,34 @@
 /****/
 
 #include "Revocation.hpp"
-#include "RuntimeEnvironment.hpp"
+
 #include "Identity.hpp"
-#include "Topology.hpp"
-#include "Switch.hpp"
 #include "Network.hpp"
 #include "Node.hpp"
+#include "RuntimeEnvironment.hpp"
+#include "Switch.hpp"
+#include "Topology.hpp"
 
 namespace ZeroTier {
 
-int Revocation::verify(const RuntimeEnvironment *RR,void *tPtr) const
+int Revocation::verify(const RuntimeEnvironment* RR, void* tPtr) const
 {
-	if ((!_signedBy)||(_signedBy != Network::controllerFor(_networkId))) {
+	if ((! _signedBy) || (_signedBy != Network::controllerFor(_networkId))) {
 		return -1;
 	}
-	const Identity id(RR->topology->getIdentity(tPtr,_signedBy));
-	if (!id) {
-		RR->sw->requestWhois(tPtr,RR->node->now(),_signedBy);
+	const Identity id(RR->topology->getIdentity(tPtr, _signedBy));
+	if (! id) {
+		RR->sw->requestWhois(tPtr, RR->node->now(), _signedBy);
 		return 1;
 	}
 	try {
 		Buffer<sizeof(Revocation) + 64> tmp;
-		this->serialize(tmp,true);
-		return (id.verify(tmp.data(),tmp.size(),_signature) ? 0 : -1);
-	} catch ( ... ) {
+		this->serialize(tmp, true);
+		return (id.verify(tmp.data(), tmp.size(), _signature) ? 0 : -1);
+	}
+	catch (...) {
 		return -1;
 	}
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier

+ 82 - 64
node/Revocation.hpp

@@ -14,19 +14,19 @@
 #ifndef ZT_REVOCATION_HPP
 #define ZT_REVOCATION_HPP
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-
-#include "Constants.hpp"
 #include "../include/ZeroTierOne.h"
-#include "Credential.hpp"
 #include "Address.hpp"
-#include "C25519.hpp"
-#include "Utils.hpp"
 #include "Buffer.hpp"
+#include "C25519.hpp"
+#include "Constants.hpp"
+#include "Credential.hpp"
 #include "Identity.hpp"
+#include "Utils.hpp"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 
 /**
  * Flag: fast propagation via rumor mill algorithm
@@ -40,22 +40,16 @@ class RuntimeEnvironment;
 /**
  * Revocation certificate to instantaneously revoke a COM, capability, or tag
  */
-class Revocation : public Credential
-{
-public:
-	static inline Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_REVOCATION; }
-
-	Revocation() :
-		_id(0),
-		_credentialId(0),
-		_networkId(0),
-		_threshold(0),
-		_flags(0),
-		_target(),
-		_signedBy(),
-		_type(Credential::CREDENTIAL_TYPE_NULL)
+class Revocation : public Credential {
+  public:
+	static inline Credential::Type credentialType()
 	{
-		memset(_signature.data,0,sizeof(_signature.data));
+		return Credential::CREDENTIAL_TYPE_REVOCATION;
+	}
+
+	Revocation() : _id(0), _credentialId(0), _networkId(0), _threshold(0), _flags(0), _target(), _signedBy(), _type(Credential::CREDENTIAL_TYPE_NULL)
+	{
+		memset(_signature.data, 0, sizeof(_signature.data));
 	}
 
 	/**
@@ -67,40 +61,64 @@ public:
 	 * @param tgt Target node whose credential(s) are being revoked
 	 * @param ct Credential type being revoked
 	 */
-	Revocation(const uint32_t i,const uint64_t nwid,const uint32_t cid,const int64_t thr,const uint64_t fl,const Address &tgt,const Credential::Type ct) :
-		_id(i),
-		_credentialId(cid),
-		_networkId(nwid),
-		_threshold(thr),
-		_flags(fl),
-		_target(tgt),
-		_signedBy(),
-		_type(ct)
+	Revocation(const uint32_t i, const uint64_t nwid, const uint32_t cid, const int64_t thr, const uint64_t fl, const Address& tgt, const Credential::Type ct)
+		: _id(i)
+		, _credentialId(cid)
+		, _networkId(nwid)
+		, _threshold(thr)
+		, _flags(fl)
+		, _target(tgt)
+		, _signedBy()
+		, _type(ct)
 	{
-		memset(_signature.data,0,sizeof(_signature.data));
+		memset(_signature.data, 0, sizeof(_signature.data));
 	}
 
-	inline uint32_t id() const { return _id; }
-	inline uint32_t credentialId() const { return _credentialId; }
-	inline uint64_t networkId() const { return _networkId; }
-	inline int64_t threshold() const { return _threshold; }
-	inline const Address &target() const { return _target; }
-	inline const Address &signer() const { return _signedBy; }
-	inline Credential::Type type() const { return _type; }
+	inline uint32_t id() const
+	{
+		return _id;
+	}
+	inline uint32_t credentialId() const
+	{
+		return _credentialId;
+	}
+	inline uint64_t networkId() const
+	{
+		return _networkId;
+	}
+	inline int64_t threshold() const
+	{
+		return _threshold;
+	}
+	inline const Address& target() const
+	{
+		return _target;
+	}
+	inline const Address& signer() const
+	{
+		return _signedBy;
+	}
+	inline Credential::Type type() const
+	{
+		return _type;
+	}
 
-	inline bool fastPropagate() const { return ((_flags & ZT_REVOCATION_FLAG_FAST_PROPAGATE) != 0); }
+	inline bool fastPropagate() const
+	{
+		return ((_flags & ZT_REVOCATION_FLAG_FAST_PROPAGATE) != 0);
+	}
 
 	/**
 	 * @param signer Signing identity, must have private key
 	 * @return True if signature was successful
 	 */
-	inline bool sign(const Identity &signer)
+	inline bool sign(const Identity& signer)
 	{
 		if (signer.hasPrivate()) {
 			Buffer<sizeof(Revocation) + 64> tmp;
 			_signedBy = signer.address();
-			this->serialize(tmp,true);
-			_signature = signer.sign(tmp.data(),tmp.size());
+			this->serialize(tmp, true);
+			_signature = signer.sign(tmp.data(), tmp.size());
 			return true;
 		}
 		return false;
@@ -113,19 +131,18 @@ public:
 	 * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
 	 * @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or chain
 	 */
-	int verify(const RuntimeEnvironment *RR,void *tPtr) const;
+	int verify(const RuntimeEnvironment* RR, void* tPtr) const;
 
-	template<unsigned int C>
-	inline void serialize(Buffer<C> &b,const bool forSign = false) const
+	template <unsigned int C> inline void serialize(Buffer<C>& b, const bool forSign = false) const
 	{
 		if (forSign) {
 			b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
 		}
 
-		b.append((uint32_t)0); // 4 unused bytes, currently set to 0
+		b.append((uint32_t)0);	 // 4 unused bytes, currently set to 0
 		b.append(_id);
 		b.append(_networkId);
-		b.append((uint32_t)0); // 4 unused bytes, currently set to 0
+		b.append((uint32_t)0);	 // 4 unused bytes, currently set to 0
 		b.append(_credentialId);
 		b.append(_threshold);
 		b.append(_flags);
@@ -133,10 +150,10 @@ public:
 		_signedBy.appendTo(b);
 		b.append((uint8_t)_type);
 
-		if (!forSign) {
-			b.append((uint8_t)1); // 1 == Ed25519 signature
+		if (! forSign) {
+			b.append((uint8_t)1);	// 1 == Ed25519 signature
 			b.append((uint16_t)ZT_C25519_SIGNATURE_LEN);
-			b.append(_signature.data,ZT_C25519_SIGNATURE_LEN);
+			b.append(_signature.data, ZT_C25519_SIGNATURE_LEN);
 		}
 
 		// This is the size of any additional fields, currently 0.
@@ -147,40 +164,41 @@ public:
 		}
 	}
 
-	template<unsigned int C>
-	inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
+	template <unsigned int C> inline unsigned int deserialize(const Buffer<C>& b, unsigned int startAt = 0)
 	{
 		*this = Revocation();
 
 		unsigned int p = startAt;
 
-		p += 4; // 4 bytes, currently unused
+		p += 4;	  // 4 bytes, currently unused
 		_id = b.template at<uint32_t>(p);
 		p += 4;
 		_networkId = b.template at<uint64_t>(p);
 		p += 8;
-		p += 4; // 4 bytes, currently unused
+		p += 4;	  // 4 bytes, currently unused
 		_credentialId = b.template at<uint32_t>(p);
 		p += 4;
 		_threshold = (int64_t)b.template at<uint64_t>(p);
 		p += 8;
 		_flags = b.template at<uint64_t>(p);
 		p += 8;
-		_target.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
+		_target.setTo(b.field(p, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
 		p += ZT_ADDRESS_LENGTH;
-		_signedBy.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
+		_signedBy.setTo(b.field(p, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
 		p += ZT_ADDRESS_LENGTH;
 		_type = (Credential::Type)b[p++];
 
 		if (b[p++] == 1) {
 			if (b.template at<uint16_t>(p) == ZT_C25519_SIGNATURE_LEN) {
 				p += 2;
-				memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN);
+				memcpy(_signature.data, b.field(p, ZT_C25519_SIGNATURE_LEN), ZT_C25519_SIGNATURE_LEN);
 				p += ZT_C25519_SIGNATURE_LEN;
-			} else {
+			}
+			else {
 				throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
 			}
-		} else {
+		}
+		else {
 			p += 2 + b.template at<uint16_t>(p);
 		}
 
@@ -192,7 +210,7 @@ public:
 		return (p - startAt);
 	}
 
-private:
+  private:
 	uint32_t _id;
 	uint32_t _credentialId;
 	uint64_t _networkId;
@@ -204,6 +222,6 @@ private:
 	C25519::Signature _signature;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 40 - 31
node/RingBuffer.hpp

@@ -14,12 +14,12 @@
 #ifndef ZT_RINGBUFFER_H
 #define ZT_RINGBUFFER_H
 
-#include <typeinfo>
-#include <cstdint>
-#include <stdlib.h>
-#include <memory.h>
 #include <algorithm>
+#include <cstdint>
 #include <math.h>
+#include <memory.h>
+#include <stdlib.h>
+#include <typeinfo>
 
 namespace ZeroTier {
 
@@ -34,28 +34,23 @@ namespace ZeroTier {
  * to reduce the complexity of code needed to interact with this type of buffer.
  */
 
-template <class T,size_t S>
-class RingBuffer
-{
-private:
+template <class T, size_t S> class RingBuffer {
+  private:
 	T buf[S];
 	size_t begin;
 	size_t end;
 	bool wrap;
 
-public:
-	RingBuffer() :
-		begin(0),
-		end(0),
-		wrap(false)
+  public:
+	RingBuffer() : begin(0), end(0), wrap(false)
 	{
-		memset(buf,0,sizeof(T)*S);
+		memset(buf, 0, sizeof(T) * S);
 	}
 
 	/**
 	 * @return A pointer to the underlying buffer
 	 */
-	inline T *get_buf()
+	inline T* get_buf()
 	{
 		return buf + begin;
 	}
@@ -87,7 +82,10 @@ public:
 	 * Fast erase, O(1).
 	 * Merely reset the buffer pointer, doesn't erase contents
 	 */
-	inline void reset() { consume(count()); }
+	inline void reset()
+	{
+		consume(count());
+	}
 
 	/**
 	 * adjust buffer index pointer as if we copied data out
@@ -116,7 +114,7 @@ public:
 	 * @param data Buffer that is to be written to the ring
 	 * @param n Number of elements to write to the buffer
 	 */
-	inline size_t write(const T * data, size_t n)
+	inline size_t write(const T* data, size_t n)
 	{
 		n = std::min(n, getFree());
 		if (n == 0) {
@@ -157,14 +155,17 @@ public:
 	/**
 	 * @return The most recently pushed element on the buffer
 	 */
-	inline T get_most_recent() { return *(buf + end); }
+	inline T get_most_recent()
+	{
+		return *(buf + end);
+	}
 
 	/**
 	 * @param dest Destination buffer
 	 * @param n Size (in terms of number of elements) of the destination buffer
 	 * @return Number of elements read from the buffer
 	 */
-	inline size_t read(T *dest,size_t n)
+	inline size_t read(T* dest, size_t n)
 	{
 		n = std::min(n, count());
 		if (n == 0) {
@@ -193,9 +194,11 @@ public:
 	{
 		if (end == begin) {
 			return wrap ? S : 0;
-		} else if (end > begin) {
+		}
+		else if (end > begin) {
 			return end - begin;
-		} else {
+		}
+		else {
 			return S + end - begin;
 		}
 	}
@@ -203,7 +206,10 @@ public:
 	/**
 	 * @return The number of slots that are unused in the buffer
 	 */
-	inline size_t getFree() { return S - count(); }
+	inline size_t getFree()
+	{
+		return S - count();
+	}
 
 	/**
 	 * @return The arithmetic mean of the contents of the buffer
@@ -213,7 +219,7 @@ public:
 		size_t iterator = begin;
 		float subtotal = 0;
 		size_t curr_cnt = count();
-		for (size_t i=0; i<curr_cnt; i++) {
+		for (size_t i = 0; i < curr_cnt; i++) {
 			iterator = (iterator + S - 1) % curr_cnt;
 			subtotal += (float)*(buf + iterator);
 		}
@@ -229,7 +235,7 @@ public:
 		size_t iterator = begin;
 		float subtotal = 0;
 		size_t curr_cnt = count();
-		for (size_t i=0; i<n; i++) {
+		for (size_t i = 0; i < n; i++) {
 			iterator = (iterator + S - 1) % curr_cnt;
 			subtotal += (float)*(buf + iterator);
 		}
@@ -244,7 +250,7 @@ public:
 		size_t iterator = begin;
 		float total = 0;
 		size_t curr_cnt = count();
-		for (size_t i=0; i<curr_cnt; i++) {
+		for (size_t i = 0; i < curr_cnt; i++) {
 			iterator = (iterator + S - 1) % curr_cnt;
 			total += (float)*(buf + iterator);
 		}
@@ -254,7 +260,10 @@ public:
 	/**
 	 * @return The sample standard deviation of element values
 	 */
-	inline float stddev() { return sqrt(variance()); }
+	inline float stddev()
+	{
+		return sqrt(variance());
+	}
 
 	/**
 	 * @return The variance of element values
@@ -265,10 +274,10 @@ public:
 		float cached_mean = mean();
 		size_t curr_cnt = count();
 		T sum_of_squared_deviations = 0;
-		for (size_t i=0; i<curr_cnt; i++) {
+		for (size_t i = 0; i < curr_cnt; i++) {
 			iterator = (iterator + S - 1) % curr_cnt;
 			float deviation = (buf[i] - cached_mean);
-			sum_of_squared_deviations += (T)(deviation*deviation);
+			sum_of_squared_deviations += (T)(deviation * deviation);
 		}
 		float variance = (float)sum_of_squared_deviations / (float)(S - 1);
 		return variance;
@@ -282,7 +291,7 @@ public:
 		size_t iterator = begin;
 		size_t zeros = 0;
 		size_t curr_cnt = count();
-		for (size_t i=0; i<curr_cnt; i++) {
+		for (size_t i = 0; i < curr_cnt; i++) {
 			iterator = (iterator + S - 1) % curr_cnt;
 			if (*(buf + iterator) == 0) {
 				zeros++;
@@ -300,7 +309,7 @@ public:
 		size_t iterator = begin;
 		size_t cnt = 0;
 		size_t curr_cnt = count();
-		for (size_t i=0; i<curr_cnt; i++) {
+		for (size_t i = 0; i < curr_cnt; i++) {
 			iterator = (iterator + S - 1) % curr_cnt;
 			if (*(buf + iterator) == value) {
 				cnt++;
@@ -329,6 +338,6 @@ public:
 	*/
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 18 - 26
node/RuntimeEnvironment.hpp

@@ -14,11 +14,11 @@
 #ifndef ZT_RUNTIMEENVIRONMENT_HPP
 #define ZT_RUNTIMEENVIRONMENT_HPP
 
-#include <string.h>
-
 #include "Constants.hpp"
-#include "Utils.hpp"
 #include "Identity.hpp"
+#include "Utils.hpp"
+
+#include <string.h>
 
 namespace ZeroTier {
 
@@ -36,17 +36,9 @@ class PacketMultiplexer;
 /**
  * Holds global state for an instance of ZeroTier::Node
  */
-class RuntimeEnvironment
-{
-public:
-	RuntimeEnvironment(Node *n) :
-		node(n)
-		,localNetworkController((NetworkController *)0)
-		,rtmem((void *)0)
-		,sw((Switch *)0)
-		,mc((Multicaster *)0)
-		,topology((Topology *)0)
-		,sa((SelfAwareness *)0)
+class RuntimeEnvironment {
+  public:
+	RuntimeEnvironment(Node* n) : node(n), localNetworkController((NetworkController*)0), rtmem((void*)0), sw((Switch*)0), mc((Multicaster*)0), topology((Topology*)0), sa((SelfAwareness*)0)
 	{
 		publicIdentityStr[0] = (char)0;
 		secretIdentityStr[0] = (char)0;
@@ -54,17 +46,17 @@ public:
 
 	~RuntimeEnvironment()
 	{
-		Utils::burn(secretIdentityStr,sizeof(secretIdentityStr));
+		Utils::burn(secretIdentityStr, sizeof(secretIdentityStr));
 	}
 
 	// Node instance that owns this RuntimeEnvironment
-	Node *const node;
+	Node* const node;
 
 	// This is set externally to an instance of this base class
-	NetworkController *localNetworkController;
+	NetworkController* localNetworkController;
 
 	// Memory actually occupied by Trace, Switch, etc.
-	void *rtmem;
+	void* rtmem;
 
 	/* Order matters a bit here. These are constructed in this order
 	 * and then deleted in the opposite order on Node exit. The order ensures
@@ -72,13 +64,13 @@ public:
 	 *
 	 * These are constant and never null after startup unless indicated. */
 
-	Trace *t;
-	Switch *sw;
-	Multicaster *mc;
-	Topology *topology;
-	SelfAwareness *sa;
-	Bond *bc;
-	PacketMultiplexer *pm;
+	Trace* t;
+	Switch* sw;
+	Multicaster* mc;
+	Topology* topology;
+	SelfAwareness* sa;
+	Bond* bc;
+	PacketMultiplexer* pm;
 
 	// This node's identity and string representations thereof
 	Identity identity;
@@ -86,6 +78,6 @@ public:
 	char secretIdentityStr[ZT_IDENTITY_STRING_BUFFER_LENGTH];
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 95 - 104
node/SHA512.cpp

@@ -1,10 +1,11 @@
 // This code is public domain, taken from a PD crypto source file on GitHub.
 
-#include <algorithm>
-
 #include "SHA512.hpp"
+
 #include "Utils.hpp"
 
+#include <algorithm>
+
 namespace ZeroTier {
 
 #ifndef ZT_HAVE_NATIVE_SHA512
@@ -12,48 +13,35 @@ namespace ZeroTier {
 namespace {
 
 struct sha512_state {
-	uint64_t length,state[8];
+	uint64_t length, state[8];
 	unsigned long curlen;
 	uint8_t buf[128];
 };
 
-static const uint64_t K[80] = {
-	0x428a2f98d728ae22ULL,0x7137449123ef65cdULL,0xb5c0fbcfec4d3b2fULL,0xe9b5dba58189dbbcULL,
-	0x3956c25bf348b538ULL,0x59f111f1b605d019ULL,0x923f82a4af194f9bULL,0xab1c5ed5da6d8118ULL,
-	0xd807aa98a3030242ULL,0x12835b0145706fbeULL,0x243185be4ee4b28cULL,0x550c7dc3d5ffb4e2ULL,
-	0x72be5d74f27b896fULL,0x80deb1fe3b1696b1ULL,0x9bdc06a725c71235ULL,0xc19bf174cf692694ULL,
-	0xe49b69c19ef14ad2ULL,0xefbe4786384f25e3ULL,0x0fc19dc68b8cd5b5ULL,0x240ca1cc77ac9c65ULL,
-	0x2de92c6f592b0275ULL,0x4a7484aa6ea6e483ULL,0x5cb0a9dcbd41fbd4ULL,0x76f988da831153b5ULL,
-	0x983e5152ee66dfabULL,0xa831c66d2db43210ULL,0xb00327c898fb213fULL,0xbf597fc7beef0ee4ULL,
-	0xc6e00bf33da88fc2ULL,0xd5a79147930aa725ULL,0x06ca6351e003826fULL,0x142929670a0e6e70ULL,
-	0x27b70a8546d22ffcULL,0x2e1b21385c26c926ULL,0x4d2c6dfc5ac42aedULL,0x53380d139d95b3dfULL,
-	0x650a73548baf63deULL,0x766a0abb3c77b2a8ULL,0x81c2c92e47edaee6ULL,0x92722c851482353bULL,
-	0xa2bfe8a14cf10364ULL,0xa81a664bbc423001ULL,0xc24b8b70d0f89791ULL,0xc76c51a30654be30ULL,
-	0xd192e819d6ef5218ULL,0xd69906245565a910ULL,0xf40e35855771202aULL,0x106aa07032bbd1b8ULL,
-	0x19a4c116b8d2d0c8ULL,0x1e376c085141ab53ULL,0x2748774cdf8eeb99ULL,0x34b0bcb5e19b48a8ULL,
-	0x391c0cb3c5c95a63ULL,0x4ed8aa4ae3418acbULL,0x5b9cca4f7763e373ULL,0x682e6ff3d6b2b8a3ULL,
-	0x748f82ee5defb2fcULL,0x78a5636f43172f60ULL,0x84c87814a1f0ab72ULL,0x8cc702081a6439ecULL,
-	0x90befffa23631e28ULL,0xa4506cebde82bde9ULL,0xbef9a3f7b2c67915ULL,0xc67178f2e372532bULL,
-	0xca273eceea26619cULL,0xd186b8c721c0c207ULL,0xeada7dd6cde0eb1eULL,0xf57d4f7fee6ed178ULL,
-	0x06f067aa72176fbaULL,0x0a637dc5a2c898a6ULL,0x113f9804bef90daeULL,0x1b710b35131c471bULL,
-	0x28db77f523047d84ULL,0x32caab7b40c72493ULL,0x3c9ebe0a15c9bebcULL,0x431d67c49c100d4cULL,
-	0x4cc5d4becb3e42b6ULL,0x597f299cfc657e2aULL,0x5fcb6fab3ad6faecULL,0x6c44198c4a475817ULL
-};
-
-#define STORE64H(x, y) Utils::storeBigEndian<uint64_t>(y,x)
-#define LOAD64H(x, y) x = Utils::loadBigEndian<uint64_t>(y)
-#define ROL64c(x,y) (((x)<<(y)) | ((x)>>(64-(y))))
-#define ROR64c(x,y) (((x)>>(y)) | ((x)<<(64-(y))))
-#define Ch(x,y,z)       (z ^ (x & (y ^ z)))
-#define Maj(x,y,z)      (((x | y) & z) | (x & y))
-#define S(x, n)         ROR64c(x, n)
-#define R(x, n)         ((x)>>(n))
-#define Sigma0(x)       (S(x, 28) ^ S(x, 34) ^ S(x, 39))
-#define Sigma1(x)       (S(x, 14) ^ S(x, 18) ^ S(x, 41))
-#define Gamma0(x)       (S(x, 1) ^ S(x, 8) ^ R(x, 7))
-#define Gamma1(x)       (S(x, 19) ^ S(x, 61) ^ R(x, 6))
-
-static ZT_INLINE void sha512_compress(sha512_state *const md,uint8_t *const buf)
+static const uint64_t K[80] = { 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
+								0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+								0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
+								0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+								0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
+								0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+								0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
+								0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+								0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL };
+
+#define STORE64H(x, y) Utils::storeBigEndian<uint64_t>(y, x)
+#define LOAD64H(x, y)  x = Utils::loadBigEndian<uint64_t>(y)
+#define ROL64c(x, y)   (((x) << (y)) | ((x) >> (64 - (y))))
+#define ROR64c(x, y)   (((x) >> (y)) | ((x) << (64 - (y))))
+#define Ch(x, y, z)	   (z ^ (x & (y ^ z)))
+#define Maj(x, y, z)   (((x | y) & z) | (x & y))
+#define S(x, n)		   ROR64c(x, n)
+#define R(x, n)		   ((x) >> (n))
+#define Sigma0(x)	   (S(x, 28) ^ S(x, 34) ^ S(x, 39))
+#define Sigma1(x)	   (S(x, 14) ^ S(x, 18) ^ S(x, 41))
+#define Gamma0(x)	   (S(x, 1) ^ S(x, 8) ^ R(x, 7))
+#define Gamma1(x)	   (S(x, 19) ^ S(x, 61) ^ R(x, 6))
+
+static ZT_INLINE void sha512_compress(sha512_state* const md, uint8_t* const buf)
 {
 	uint64_t S[8], W[80], t0, t1;
 	int i;
@@ -62,27 +50,27 @@ static ZT_INLINE void sha512_compress(sha512_state *const md,uint8_t *const buf)
 		S[i] = md->state[i];
 	}
 	for (i = 0; i < 16; i++) {
-		LOAD64H(W[i], buf + (8*i));
+		LOAD64H(W[i], buf + (8 * i));
 	}
 	for (i = 16; i < 80; i++) {
 		W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
 	}
 
-#define RND(a,b,c,d,e,f,g,h,i) \
-	t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
-	t1 = Sigma0(a) + Maj(a, b, c); \
-	d += t0; \
-	h  = t0 + t1;
+#define RND(a, b, c, d, e, f, g, h, i)                                                                                                                                                                                                         \
+	t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];                                                                                                                                                                                            \
+	t1 = Sigma0(a) + Maj(a, b, c);                                                                                                                                                                                                             \
+	d += t0;                                                                                                                                                                                                                                   \
+	h = t0 + t1;
 
 	for (i = 0; i < 80; i += 8) {
-		RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0);
-		RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1);
-		RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2);
-		RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3);
-		RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4);
-		RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5);
-		RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6);
-		RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);
+		RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i + 0);
+		RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], i + 1);
+		RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], i + 2);
+		RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], i + 3);
+		RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], i + 4);
+		RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], i + 5);
+		RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], i + 6);
+		RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], i + 7);
 	}
 
 	for (i = 0; i < 8; i++) {
@@ -90,7 +78,7 @@ static ZT_INLINE void sha512_compress(sha512_state *const md,uint8_t *const buf)
 	}
 }
 
-static ZT_INLINE void sha384_init(sha512_state *const md)
+static ZT_INLINE void sha384_init(sha512_state* const md)
 {
 	md->curlen = 0;
 	md->length = 0;
@@ -104,7 +92,7 @@ static ZT_INLINE void sha384_init(sha512_state *const md)
 	md->state[7] = 0x47b5481dbefa4fa4ULL;
 }
 
-static ZT_INLINE void sha512_init(sha512_state *const md)
+static ZT_INLINE void sha512_init(sha512_state* const md)
 {
 	md->curlen = 0;
 	md->length = 0;
@@ -118,30 +106,31 @@ static ZT_INLINE void sha512_init(sha512_state *const md)
 	md->state[7] = 0x5be0cd19137e2179ULL;
 }
 
-static void sha512_process(sha512_state *const md,const uint8_t *in,unsigned long inlen)
+static void sha512_process(sha512_state* const md, const uint8_t* in, unsigned long inlen)
 {
 	while (inlen > 0) {
 		if (md->curlen == 0 && inlen >= 128) {
-			sha512_compress(md,(uint8_t *)in);
-			md->length     += 128 * 8;
-			in             += 128;
-			inlen          -= 128;
-		} else {
-			unsigned long n = std::min(inlen,(128 - md->curlen));
-			Utils::copy(md->buf + md->curlen,in,n);
+			sha512_compress(md, (uint8_t*)in);
+			md->length += 128 * 8;
+			in += 128;
+			inlen -= 128;
+		}
+		else {
+			unsigned long n = std::min(inlen, (128 - md->curlen));
+			Utils::copy(md->buf + md->curlen, in, n);
 			md->curlen += n;
-			in             += n;
-			inlen          -= n;
+			in += n;
+			inlen -= n;
 			if (md->curlen == 128) {
-				sha512_compress(md,md->buf);
-				md->length += 8*128;
+				sha512_compress(md, md->buf);
+				md->length += 8 * 128;
 				md->curlen = 0;
 			}
 		}
 	}
 }
 
-static ZT_INLINE void sha512_done(sha512_state *const md,uint8_t *out)
+static ZT_INLINE void sha512_done(sha512_state* const md, uint8_t* out)
 {
 	int i;
 
@@ -160,58 +149,58 @@ static ZT_INLINE void sha512_done(sha512_state *const md,uint8_t *out)
 		md->buf[md->curlen++] = (uint8_t)0;
 	}
 
-	STORE64H(md->length, md->buf+120);
+	STORE64H(md->length, md->buf + 120);
 	sha512_compress(md, md->buf);
 
 	for (i = 0; i < 8; i++) {
-		STORE64H(md->state[i], out+(8*i));
+		STORE64H(md->state[i], out + (8 * i));
 	}
 }
 
-} // anonymous namespace
+}	// anonymous namespace
 
-void SHA512(void *digest,const void *data,unsigned int len)
+void SHA512(void* digest, const void* data, unsigned int len)
 {
 	sha512_state state;
 	sha512_init(&state);
-	sha512_process(&state,(uint8_t *)data,(unsigned long)len);
-	sha512_done(&state,(uint8_t *)digest);
+	sha512_process(&state, (uint8_t*)data, (unsigned long)len);
+	sha512_done(&state, (uint8_t*)digest);
 }
 
-void SHA384(void *digest,const void *data,unsigned int len)
+void SHA384(void* digest, const void* data, unsigned int len)
 {
 	uint8_t tmp[64];
 	sha512_state state;
 	sha384_init(&state);
-	sha512_process(&state,(uint8_t *)data,(unsigned long)len);
-	sha512_done(&state,tmp);
-	Utils::copy<48>(digest,tmp);
+	sha512_process(&state, (uint8_t*)data, (unsigned long)len);
+	sha512_done(&state, tmp);
+	Utils::copy<48>(digest, tmp);
 }
 
-void SHA384(void *digest,const void *data0,unsigned int len0,const void *data1,unsigned int len1)
+void SHA384(void* digest, const void* data0, unsigned int len0, const void* data1, unsigned int len1)
 {
 	uint8_t tmp[64];
 	sha512_state state;
 	sha384_init(&state);
-	sha512_process(&state,(uint8_t *)data0,(unsigned long)len0);
-	sha512_process(&state,(uint8_t *)data1,(unsigned long)len1);
-	sha512_done(&state,tmp);
-	Utils::copy<48>(digest,tmp);
+	sha512_process(&state, (uint8_t*)data0, (unsigned long)len0);
+	sha512_process(&state, (uint8_t*)data1, (unsigned long)len1);
+	sha512_done(&state, tmp);
+	Utils::copy<48>(digest, tmp);
 }
 
-#endif // !ZT_HAVE_NATIVE_SHA512
+#endif	 // !ZT_HAVE_NATIVE_SHA512
 
-void HMACSHA384(const uint8_t key[ZT_SYMMETRIC_KEY_SIZE],const void *msg,const unsigned int msglen,uint8_t mac[48])
+void HMACSHA384(const uint8_t key[ZT_SYMMETRIC_KEY_SIZE], const void* msg, const unsigned int msglen, uint8_t mac[48])
 {
-	uint64_t kInPadded[16]; // input padded key
-	uint64_t outer[22]; // output padded key | H(input padded key | msg)
+	uint64_t kInPadded[16];	  // input padded key
+	uint64_t outer[22];		  // output padded key | H(input padded key | msg)
 
-	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 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;
@@ -250,18 +239,18 @@ void HMACSHA384(const uint8_t key[ZT_SYMMETRIC_KEY_SIZE],const void *msg,const u
 	outer[15] = opad;
 
 	// H(output padded key | H(input padded key | msg))
-	SHA384(reinterpret_cast<uint8_t *>(outer) + 128,kInPadded,128,msg,msglen);
-	SHA384(mac,outer,176);
+	SHA384(reinterpret_cast<uint8_t*>(outer) + 128, kInPadded, 128, msg, msglen);
+	SHA384(mac, outer, 176);
 }
 
-void KBKDFHMACSHA384(const uint8_t key[ZT_SYMMETRIC_KEY_SIZE],const char label,const char context,const uint32_t iter,uint8_t out[ZT_SYMMETRIC_KEY_SIZE])
+void KBKDFHMACSHA384(const uint8_t key[ZT_SYMMETRIC_KEY_SIZE], const char label, const char context, const uint32_t iter, uint8_t out[ZT_SYMMETRIC_KEY_SIZE])
 {
 	uint8_t kbkdfMsg[13];
 
-	Utils::storeBigEndian<uint32_t>(kbkdfMsg,(uint32_t)iter);
+	Utils::storeBigEndian<uint32_t>(kbkdfMsg, (uint32_t)iter);
 
 	kbkdfMsg[4] = (uint8_t)'Z';
-	kbkdfMsg[5] = (uint8_t)'T'; // preface our labels with something ZT-specific
+	kbkdfMsg[5] = (uint8_t)'T';	  // preface our labels with something ZT-specific
 	kbkdfMsg[6] = (uint8_t)label;
 	kbkdfMsg[7] = 0;
 
@@ -273,13 +262,15 @@ void KBKDFHMACSHA384(const uint8_t key[ZT_SYMMETRIC_KEY_SIZE],const char label,c
 	kbkdfMsg[11] = 0x01;
 	kbkdfMsg[12] = 0x80;
 
-	static_assert(ZT_SYMMETRIC_KEY_SIZE == ZT_SHA384_DIGEST_SIZE,"sizeof(out) != ZT_SHA384_DIGEST_SIZE");
-	HMACSHA384(key,&kbkdfMsg,sizeof(kbkdfMsg),out);
+	static_assert(ZT_SYMMETRIC_KEY_SIZE == ZT_SHA384_DIGEST_SIZE, "sizeof(out) != ZT_SHA384_DIGEST_SIZE");
+	HMACSHA384(key, &kbkdfMsg, sizeof(kbkdfMsg), out);
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 // Internally re-export to included C code, which includes some fast crypto code ported in on some platforms.
 // This eliminates the need to link against a third party SHA512() from this code
-extern "C" void ZT_sha512internal(void *digest,const void *data,unsigned int len)
-{ ZeroTier::SHA512(digest,data,len); }
+extern "C" void ZT_sha512internal(void* digest, const void* data, unsigned int len)
+{
+	ZeroTier::SHA512(digest, data, len);
+}

+ 18 - 18
node/SHA512.hpp

@@ -22,8 +22,8 @@
 
 #define ZT_SHA512_DIGEST_SIZE 64
 #define ZT_SHA384_DIGEST_SIZE 48
-#define ZT_SHA512_BLOCK_SIZE 128
-#define ZT_SHA384_BLOCK_SIZE 128
+#define ZT_SHA512_BLOCK_SIZE  128
+#define ZT_SHA384_BLOCK_SIZE  128
 
 #define ZT_HMACSHA384_LEN 48
 
@@ -32,34 +32,34 @@ namespace ZeroTier {
 // SHA384 and SHA512 are actually in the standard libraries on MacOS and iOS
 #ifdef __APPLE__
 #define ZT_HAVE_NATIVE_SHA512 1
-static ZT_INLINE void SHA512(void *digest,const void *data,unsigned int len)
+static ZT_INLINE void SHA512(void* digest, const void* data, unsigned int len)
 {
 	CC_SHA512_CTX ctx;
 	CC_SHA512_Init(&ctx);
-	CC_SHA512_Update(&ctx,data,len);
-	CC_SHA512_Final(reinterpret_cast<unsigned char *>(digest),&ctx);
+	CC_SHA512_Update(&ctx, data, len);
+	CC_SHA512_Final(reinterpret_cast<unsigned char*>(digest), &ctx);
 }
-static ZT_INLINE void SHA384(void *digest,const void *data,unsigned int len)
+static ZT_INLINE void SHA384(void* digest, const void* data, unsigned int len)
 {
 	CC_SHA512_CTX ctx;
 	CC_SHA384_Init(&ctx);
-	CC_SHA384_Update(&ctx,data,len);
-	CC_SHA384_Final(reinterpret_cast<unsigned char *>(digest),&ctx);
+	CC_SHA384_Update(&ctx, data, len);
+	CC_SHA384_Final(reinterpret_cast<unsigned char*>(digest), &ctx);
 }
-static ZT_INLINE void SHA384(void *digest,const void *data0,unsigned int len0,const void *data1,unsigned int len1)
+static ZT_INLINE void SHA384(void* digest, const void* data0, unsigned int len0, const void* data1, unsigned int len1)
 {
 	CC_SHA512_CTX ctx;
 	CC_SHA384_Init(&ctx);
-	CC_SHA384_Update(&ctx,data0,len0);
-	CC_SHA384_Update(&ctx,data1,len1);
-	CC_SHA384_Final(reinterpret_cast<unsigned char *>(digest),&ctx);
+	CC_SHA384_Update(&ctx, data0, len0);
+	CC_SHA384_Update(&ctx, data1, len1);
+	CC_SHA384_Final(reinterpret_cast<unsigned char*>(digest), &ctx);
 }
 #endif
 
 #ifndef ZT_HAVE_NATIVE_SHA512
-void SHA512(void *digest,const void *data,unsigned int len);
-void SHA384(void *digest,const void *data,unsigned int len);
-void SHA384(void *digest,const void *data0,unsigned int len0,const void *data1,unsigned int len1);
+void SHA512(void* digest, const void* data, unsigned int len);
+void SHA384(void* digest, const void* data, unsigned int len);
+void SHA384(void* digest, const void* data0, unsigned int len0, const void* data1, unsigned int len1);
 #endif
 
 /**
@@ -70,7 +70,7 @@ void SHA384(void *digest,const void *data0,unsigned int len0,const void *data1,u
  * @param msglen Length of message
  * @param mac Buffer to fill with result
  */
-void HMACSHA384(const uint8_t key[ZT_SYMMETRIC_KEY_SIZE],const void *msg,unsigned int msglen,uint8_t mac[48]);
+void HMACSHA384(const uint8_t key[ZT_SYMMETRIC_KEY_SIZE], const void* msg, unsigned int msglen, uint8_t mac[48]);
 
 /**
  * Compute KBKDF (key-based key derivation function) using HMAC-SHA-384 as a PRF
@@ -81,8 +81,8 @@ void HMACSHA384(const uint8_t key[ZT_SYMMETRIC_KEY_SIZE],const void *msg,unsigne
  * @param iter Key iteration for generation of multiple keys for the same label/context
  * @param out Output to receive derived key
  */
-void KBKDFHMACSHA384(const uint8_t key[ZT_SYMMETRIC_KEY_SIZE],char label,char context,uint32_t iter,uint8_t out[ZT_SYMMETRIC_KEY_SIZE]);
+void KBKDFHMACSHA384(const uint8_t key[ZT_SYMMETRIC_KEY_SIZE], char label, char context, uint32_t iter, uint8_t out[ZT_SYMMETRIC_KEY_SIZE]);
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

File diff suppressed because it is too large
+ 671 - 659
node/Salsa20.cpp


+ 59 - 55
node/Salsa20.hpp

@@ -7,32 +7,36 @@
 #ifndef ZT_SALSA20_HPP
 #define ZT_SALSA20_HPP
 
-#include <stdio.h>
+#include "Constants.hpp"
+#include "Utils.hpp"
+
 #include <stdint.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "Constants.hpp"
-#include "Utils.hpp"
-
-#if (!defined(ZT_SALSA20_SSE)) && (defined(__SSE2__) || (defined(__WINDOWS__) && !defined(__MINGW32__) && !defined(_M_ARM64)))
+#if (! defined(ZT_SALSA20_SSE)) && (defined(__SSE2__) || (defined(__WINDOWS__) && ! defined(__MINGW32__) && ! defined(_M_ARM64)))
 #define ZT_SALSA20_SSE 1
 #endif
 
 #ifdef ZT_SALSA20_SSE
 #include <emmintrin.h>
-#endif // ZT_SALSA20_SSE
+#endif	 // ZT_SALSA20_SSE
 
 namespace ZeroTier {
 
 /**
  * Salsa20 stream cipher
  */
-class Salsa20
-{
-public:
-	Salsa20() {}
-	~Salsa20() { Utils::burn(&_state,sizeof(_state)); }
+class Salsa20 {
+  public:
+	Salsa20()
+	{
+	}
+	~Salsa20()
+	{
+		Utils::burn(&_state, sizeof(_state));
+	}
 
 	/**
 	 * XOR d with s
@@ -45,48 +49,48 @@ public:
 	 * @param s Source bytes to XOR with destination
 	 * @param len Length of s and d
 	 */
-	static inline void memxor(uint8_t *d,const uint8_t *s,unsigned int len)
+	static inline void memxor(uint8_t* d, const uint8_t* s, unsigned int len)
 	{
 #ifdef ZT_SALSA20_SSE
 		while (len >= 128) {
-			__m128i s0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(s));
-			__m128i s1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(s + 16));
-			__m128i s2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(s + 32));
-			__m128i s3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(s + 48));
-			__m128i s4 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(s + 64));
-			__m128i s5 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(s + 80));
-			__m128i s6 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(s + 96));
-			__m128i s7 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(s + 112));
-			__m128i d0 = _mm_loadu_si128(reinterpret_cast<__m128i *>(d));
-			__m128i d1 = _mm_loadu_si128(reinterpret_cast<__m128i *>(d + 16));
-			__m128i d2 = _mm_loadu_si128(reinterpret_cast<__m128i *>(d + 32));
-			__m128i d3 = _mm_loadu_si128(reinterpret_cast<__m128i *>(d + 48));
-			__m128i d4 = _mm_loadu_si128(reinterpret_cast<__m128i *>(d + 64));
-			__m128i d5 = _mm_loadu_si128(reinterpret_cast<__m128i *>(d + 80));
-			__m128i d6 = _mm_loadu_si128(reinterpret_cast<__m128i *>(d + 96));
-			__m128i d7 = _mm_loadu_si128(reinterpret_cast<__m128i *>(d + 112));
-			d0 = _mm_xor_si128(d0,s0);
-			d1 = _mm_xor_si128(d1,s1);
-			d2 = _mm_xor_si128(d2,s2);
-			d3 = _mm_xor_si128(d3,s3);
-			d4 = _mm_xor_si128(d4,s4);
-			d5 = _mm_xor_si128(d5,s5);
-			d6 = _mm_xor_si128(d6,s6);
-			d7 = _mm_xor_si128(d7,s7);
-			_mm_storeu_si128(reinterpret_cast<__m128i *>(d),d0);
-			_mm_storeu_si128(reinterpret_cast<__m128i *>(d + 16),d1);
-			_mm_storeu_si128(reinterpret_cast<__m128i *>(d + 32),d2);
-			_mm_storeu_si128(reinterpret_cast<__m128i *>(d + 48),d3);
-			_mm_storeu_si128(reinterpret_cast<__m128i *>(d + 64),d4);
-			_mm_storeu_si128(reinterpret_cast<__m128i *>(d + 80),d5);
-			_mm_storeu_si128(reinterpret_cast<__m128i *>(d + 96),d6);
-			_mm_storeu_si128(reinterpret_cast<__m128i *>(d + 112),d7);
+			__m128i s0 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(s));
+			__m128i s1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(s + 16));
+			__m128i s2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(s + 32));
+			__m128i s3 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(s + 48));
+			__m128i s4 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(s + 64));
+			__m128i s5 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(s + 80));
+			__m128i s6 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(s + 96));
+			__m128i s7 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(s + 112));
+			__m128i d0 = _mm_loadu_si128(reinterpret_cast<__m128i*>(d));
+			__m128i d1 = _mm_loadu_si128(reinterpret_cast<__m128i*>(d + 16));
+			__m128i d2 = _mm_loadu_si128(reinterpret_cast<__m128i*>(d + 32));
+			__m128i d3 = _mm_loadu_si128(reinterpret_cast<__m128i*>(d + 48));
+			__m128i d4 = _mm_loadu_si128(reinterpret_cast<__m128i*>(d + 64));
+			__m128i d5 = _mm_loadu_si128(reinterpret_cast<__m128i*>(d + 80));
+			__m128i d6 = _mm_loadu_si128(reinterpret_cast<__m128i*>(d + 96));
+			__m128i d7 = _mm_loadu_si128(reinterpret_cast<__m128i*>(d + 112));
+			d0 = _mm_xor_si128(d0, s0);
+			d1 = _mm_xor_si128(d1, s1);
+			d2 = _mm_xor_si128(d2, s2);
+			d3 = _mm_xor_si128(d3, s3);
+			d4 = _mm_xor_si128(d4, s4);
+			d5 = _mm_xor_si128(d5, s5);
+			d6 = _mm_xor_si128(d6, s6);
+			d7 = _mm_xor_si128(d7, s7);
+			_mm_storeu_si128(reinterpret_cast<__m128i*>(d), d0);
+			_mm_storeu_si128(reinterpret_cast<__m128i*>(d + 16), d1);
+			_mm_storeu_si128(reinterpret_cast<__m128i*>(d + 32), d2);
+			_mm_storeu_si128(reinterpret_cast<__m128i*>(d + 48), d3);
+			_mm_storeu_si128(reinterpret_cast<__m128i*>(d + 64), d4);
+			_mm_storeu_si128(reinterpret_cast<__m128i*>(d + 80), d5);
+			_mm_storeu_si128(reinterpret_cast<__m128i*>(d + 96), d6);
+			_mm_storeu_si128(reinterpret_cast<__m128i*>(d + 112), d7);
 			s += 128;
 			d += 128;
 			len -= 128;
 		}
 		while (len >= 16) {
-			_mm_storeu_si128(reinterpret_cast<__m128i *>(d),_mm_xor_si128(_mm_loadu_si128(reinterpret_cast<__m128i *>(d)),_mm_loadu_si128(reinterpret_cast<const __m128i *>(s))));
+			_mm_storeu_si128(reinterpret_cast<__m128i*>(d), _mm_xor_si128(_mm_loadu_si128(reinterpret_cast<__m128i*>(d)), _mm_loadu_si128(reinterpret_cast<const __m128i*>(s))));
 			s += 16;
 			d += 16;
 			len -= 16;
@@ -94,10 +98,10 @@ public:
 #else
 #ifndef ZT_NO_TYPE_PUNNING
 		while (len >= 16) {
-			(*reinterpret_cast<uint64_t *>(d)) ^= (*reinterpret_cast<const uint64_t *>(s));
+			(*reinterpret_cast<uint64_t*>(d)) ^= (*reinterpret_cast<const uint64_t*>(s));
 			s += 8;
 			d += 8;
-			(*reinterpret_cast<uint64_t *>(d)) ^= (*reinterpret_cast<const uint64_t *>(s));
+			(*reinterpret_cast<uint64_t*>(d)) ^= (*reinterpret_cast<const uint64_t*>(s));
 			s += 8;
 			d += 8;
 			len -= 16;
@@ -114,9 +118,9 @@ public:
 	 * @param key 256-bit (32 byte) key
 	 * @param iv 64-bit initialization vector
 	 */
-	Salsa20(const void *key,const void *iv)
+	Salsa20(const void* key, const void* iv)
 	{
-		init(key,iv);
+		init(key, iv);
 	}
 
 	/**
@@ -125,7 +129,7 @@ public:
 	 * @param key Key bits
 	 * @param iv 64-bit initialization vector
 	 */
-	void init(const void *key,const void *iv);
+	void init(const void* key, const void* iv);
 
 	/**
 	 * Encrypt/decrypt data using Salsa20/12
@@ -134,7 +138,7 @@ public:
 	 * @param out Output buffer
 	 * @param bytes Length of data
 	 */
-	void crypt12(const void *in,void *out,unsigned int bytes);
+	void crypt12(const void* in, void* out, unsigned int bytes);
 
 	/**
 	 * Encrypt/decrypt data using Salsa20/20
@@ -143,17 +147,17 @@ public:
 	 * @param out Output buffer
 	 * @param bytes Length of data
 	 */
-	void crypt20(const void *in,void *out,unsigned int bytes);
+	void crypt20(const void* in, void* out, unsigned int bytes);
 
-private:
+  private:
 	union {
 #ifdef ZT_SALSA20_SSE
 		__m128i v[4];
-#endif // ZT_SALSA20_SSE
+#endif	 // ZT_SALSA20_SSE
 		uint32_t i[16];
 	} _state;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 44 - 45
node/SelfAwareness.cpp

@@ -11,66 +11,64 @@
  */
 /****/
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <set>
-#include <vector>
+#include "SelfAwareness.hpp"
 
 #include "Constants.hpp"
-#include "SelfAwareness.hpp"
-#include "RuntimeEnvironment.hpp"
 #include "Node.hpp"
-#include "Topology.hpp"
 #include "Packet.hpp"
 #include "Peer.hpp"
+#include "RuntimeEnvironment.hpp"
 #include "Switch.hpp"
+#include "Topology.hpp"
 #include "Trace.hpp"
 
+#include <set>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <vector>
+
 // Entry timeout -- make it fairly long since this is just to prevent stale buildup
 #define ZT_SELFAWARENESS_ENTRY_TIMEOUT 600000
 
 namespace ZeroTier {
 
-class _ResetWithinScope
-{
-public:
-	_ResetWithinScope(void *tPtr,int64_t now,int inetAddressFamily,InetAddress::IpScope scope) :
-		_now(now),
-		_tPtr(tPtr),
-		_family(inetAddressFamily),
-		_scope(scope) {}
+class _ResetWithinScope {
+  public:
+	_ResetWithinScope(void* tPtr, int64_t now, int inetAddressFamily, InetAddress::IpScope scope) : _now(now), _tPtr(tPtr), _family(inetAddressFamily), _scope(scope)
+	{
+	}
 
-	inline void operator()(Topology &t,const SharedPtr<Peer> &p) { p->resetWithinScope(_tPtr,_scope,_family,_now); }
+	inline void operator()(Topology& t, const SharedPtr<Peer>& p)
+	{
+		p->resetWithinScope(_tPtr, _scope, _family, _now);
+	}
 
-private:
+  private:
 	uint64_t _now;
-	void *_tPtr;
+	void* _tPtr;
 	int _family;
 	InetAddress::IpScope _scope;
 };
 
-SelfAwareness::SelfAwareness(const RuntimeEnvironment *renv) :
-	RR(renv),
-	_phy(128)
+SelfAwareness::SelfAwareness(const RuntimeEnvironment* renv) : RR(renv), _phy(128)
 {
 }
 
-void SelfAwareness::iam(void *tPtr,const Address &reporter,const int64_t receivedOnLocalSocket,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,int64_t now)
+void SelfAwareness::iam(void* tPtr, const Address& reporter, const int64_t receivedOnLocalSocket, const InetAddress& reporterPhysicalAddress, const InetAddress& myPhysicalAddress, bool trusted, int64_t now)
 {
 	const InetAddress::IpScope scope = myPhysicalAddress.ipScope();
 
-	if ((scope != reporterPhysicalAddress.ipScope())||(scope == InetAddress::IP_SCOPE_NONE)||(scope == InetAddress::IP_SCOPE_LOOPBACK)||(scope == InetAddress::IP_SCOPE_MULTICAST)) {
+	if ((scope != reporterPhysicalAddress.ipScope()) || (scope == InetAddress::IP_SCOPE_NONE) || (scope == InetAddress::IP_SCOPE_LOOPBACK) || (scope == InetAddress::IP_SCOPE_MULTICAST)) {
 		return;
 	}
 
 	Mutex::Lock _l(_phy_m);
-	PhySurfaceEntry &entry = _phy[PhySurfaceKey(reporter,receivedOnLocalSocket,reporterPhysicalAddress,scope)];
+	PhySurfaceEntry& entry = _phy[PhySurfaceKey(reporter, receivedOnLocalSocket, reporterPhysicalAddress, scope)];
 
-	if ( (trusted) && ((now - entry.ts) < ZT_SELFAWARENESS_ENTRY_TIMEOUT) && (!entry.mySurface.ipsEqual(myPhysicalAddress)) ) {
+	if ((trusted) && ((now - entry.ts) < ZT_SELFAWARENESS_ENTRY_TIMEOUT) && (! entry.mySurface.ipsEqual(myPhysicalAddress))) {
 		// Changes to external surface reported by trusted peers causes path reset in this scope
-		RR->t->resettingPathsInScope(tPtr,reporter,reporterPhysicalAddress,myPhysicalAddress,scope);
+		RR->t->resettingPathsInScope(tPtr, reporter, reporterPhysicalAddress, myPhysicalAddress, scope);
 
 		entry.mySurface = myPhysicalAddress;
 		entry.ts = now;
@@ -80,20 +78,21 @@ void SelfAwareness::iam(void *tPtr,const Address &reporter,const int64_t receive
 		// due to multiple reports of endpoint change.
 		// Don't use 'entry' after this since hash table gets modified.
 		{
-			Hashtable< PhySurfaceKey,PhySurfaceEntry >::Iterator i(_phy);
-			PhySurfaceKey *k = (PhySurfaceKey *)0;
-			PhySurfaceEntry *e = (PhySurfaceEntry *)0;
-			while (i.next(k,e)) {
-				if ((k->reporterPhysicalAddress != reporterPhysicalAddress)&&(k->scope == scope)) {
+			Hashtable<PhySurfaceKey, PhySurfaceEntry>::Iterator i(_phy);
+			PhySurfaceKey* k = (PhySurfaceKey*)0;
+			PhySurfaceEntry* e = (PhySurfaceEntry*)0;
+			while (i.next(k, e)) {
+				if ((k->reporterPhysicalAddress != reporterPhysicalAddress) && (k->scope == scope)) {
 					_phy.erase(*k);
 				}
 			}
 		}
 
 		// Reset all paths within this scope and address family
-		_ResetWithinScope rset(tPtr,now,myPhysicalAddress.ss_family,(InetAddress::IpScope)scope);
-		RR->topology->eachPeer<_ResetWithinScope &>(rset);
-	} else {
+		_ResetWithinScope rset(tPtr, now, myPhysicalAddress.ss_family, (InetAddress::IpScope)scope);
+		RR->topology->eachPeer<_ResetWithinScope&>(rset);
+	}
+	else {
 		// Otherwise just update DB to use to determine external surface info
 		entry.mySurface = myPhysicalAddress;
 		entry.ts = now;
@@ -105,10 +104,10 @@ std::vector<InetAddress> SelfAwareness::whoami()
 {
 	std::vector<InetAddress> surfaceAddresses;
 	Mutex::Lock _l(_phy_m);
-	Hashtable< PhySurfaceKey,PhySurfaceEntry >::Iterator i(_phy);
-	PhySurfaceKey *k = (PhySurfaceKey *)0;
-	PhySurfaceEntry *e = (PhySurfaceEntry *)0;
-	while (i.next(k,e)) {
+	Hashtable<PhySurfaceKey, PhySurfaceEntry>::Iterator i(_phy);
+	PhySurfaceKey* k = (PhySurfaceKey*)0;
+	PhySurfaceEntry* e = (PhySurfaceEntry*)0;
+	while (i.next(k, e)) {
 		if (std::find(surfaceAddresses.begin(), surfaceAddresses.end(), e->mySurface) == surfaceAddresses.end()) {
 			surfaceAddresses.push_back(e->mySurface);
 		}
@@ -119,14 +118,14 @@ std::vector<InetAddress> SelfAwareness::whoami()
 void SelfAwareness::clean(int64_t now)
 {
 	Mutex::Lock _l(_phy_m);
-	Hashtable< PhySurfaceKey,PhySurfaceEntry >::Iterator i(_phy);
-	PhySurfaceKey *k = (PhySurfaceKey *)0;
-	PhySurfaceEntry *e = (PhySurfaceEntry *)0;
-	while (i.next(k,e)) {
+	Hashtable<PhySurfaceKey, PhySurfaceEntry>::Iterator i(_phy);
+	PhySurfaceKey* k = (PhySurfaceKey*)0;
+	PhySurfaceEntry* e = (PhySurfaceEntry*)0;
+	while (i.next(k, e)) {
 		if ((now - e->ts) >= ZT_SELFAWARENESS_ENTRY_TIMEOUT) {
 			_phy.erase(*k);
 		}
 	}
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier

+ 33 - 22
node/SelfAwareness.hpp

@@ -14,10 +14,10 @@
 #ifndef ZT_SELFAWARENESS_HPP
 #define ZT_SELFAWARENESS_HPP
 
+#include "Address.hpp"
 #include "Constants.hpp"
-#include "InetAddress.hpp"
 #include "Hashtable.hpp"
-#include "Address.hpp"
+#include "InetAddress.hpp"
 #include "Mutex.hpp"
 
 namespace ZeroTier {
@@ -27,10 +27,9 @@ class RuntimeEnvironment;
 /**
  * Tracks changes to this peer's real world addresses
  */
-class SelfAwareness
-{
-public:
-	SelfAwareness(const RuntimeEnvironment *renv);
+class SelfAwareness {
+  public:
+	SelfAwareness(const RuntimeEnvironment* renv);
 
 	/**
 	 * Called when a trusted remote peer informs us of our external network address
@@ -42,7 +41,7 @@ public:
 	 * @param trusted True if this peer is trusted as an authority to inform us of external address changes
 	 * @param now Current time
 	 */
-	void iam(void *tPtr,const Address &reporter,const int64_t receivedOnLocalSocket,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,int64_t now);
+	void iam(void* tPtr, const Address& reporter, const int64_t receivedOnLocalSocket, const InetAddress& reporterPhysicalAddress, const InetAddress& myPhysicalAddress, bool trusted, int64_t now);
 
 	/**
 	 * Return all known external surface addresses reported by peers
@@ -58,36 +57,48 @@ public:
 	 */
 	void clean(int64_t now);
 
-private:
-	struct PhySurfaceKey
-	{
+  private:
+	struct PhySurfaceKey {
 		Address reporter;
 		int64_t receivedOnLocalSocket;
 		InetAddress reporterPhysicalAddress;
 		InetAddress::IpScope scope;
 
-		PhySurfaceKey() : reporter(),scope(InetAddress::IP_SCOPE_NONE) {}
-		PhySurfaceKey(const Address &r,const int64_t rol,const InetAddress &ra,InetAddress::IpScope s) : reporter(r),receivedOnLocalSocket(rol),reporterPhysicalAddress(ra),scope(s) {}
-
-		inline unsigned long hashCode() const { return ((unsigned long)reporter.toInt() + (unsigned long)scope); }
-		inline bool operator==(const PhySurfaceKey &k) const { return ((reporter == k.reporter)&&(receivedOnLocalSocket == k.receivedOnLocalSocket)&&(reporterPhysicalAddress == k.reporterPhysicalAddress)&&(scope == k.scope)); }
+		PhySurfaceKey() : reporter(), scope(InetAddress::IP_SCOPE_NONE)
+		{
+		}
+		PhySurfaceKey(const Address& r, const int64_t rol, const InetAddress& ra, InetAddress::IpScope s) : reporter(r), receivedOnLocalSocket(rol), reporterPhysicalAddress(ra), scope(s)
+		{
+		}
+
+		inline unsigned long hashCode() const
+		{
+			return ((unsigned long)reporter.toInt() + (unsigned long)scope);
+		}
+		inline bool operator==(const PhySurfaceKey& k) const
+		{
+			return ((reporter == k.reporter) && (receivedOnLocalSocket == k.receivedOnLocalSocket) && (reporterPhysicalAddress == k.reporterPhysicalAddress) && (scope == k.scope));
+		}
 	};
-	struct PhySurfaceEntry
-	{
+	struct PhySurfaceEntry {
 		InetAddress mySurface;
 		uint64_t ts;
 		bool trusted;
 
-		PhySurfaceEntry() : mySurface(),ts(0),trusted(false) {}
-		PhySurfaceEntry(const InetAddress &a,const uint64_t t) : mySurface(a),ts(t),trusted(false) {}
+		PhySurfaceEntry() : mySurface(), ts(0), trusted(false)
+		{
+		}
+		PhySurfaceEntry(const InetAddress& a, const uint64_t t) : mySurface(a), ts(t), trusted(false)
+		{
+		}
 	};
 
-	const RuntimeEnvironment *RR;
+	const RuntimeEnvironment* RR;
 
-	Hashtable< PhySurfaceKey,PhySurfaceEntry > _phy;
+	Hashtable<PhySurfaceKey, PhySurfaceEntry> _phy;
 	Mutex _phy_m;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 63 - 28
node/SharedPtr.hpp

@@ -14,8 +14,8 @@
 #ifndef ZT_SHAREDPTR_HPP
 #define ZT_SHAREDPTR_HPP
 
-#include "Mutex.hpp"
 #include "AtomicCounter.hpp"
+#include "Mutex.hpp"
 
 namespace ZeroTier {
 
@@ -26,13 +26,18 @@ namespace ZeroTier {
  * counted must list this as a 'friend' and must have a private instance of
  * AtomicCounter called __refCount.
  */
-template<typename T>
-class SharedPtr
-{
-public:
-	SharedPtr() : _ptr((T *)0) {}
-	SharedPtr(T *obj) : _ptr(obj) { ++obj->__refCount; }
-	SharedPtr(const SharedPtr &sp) : _ptr(sp._getAndInc()) {}
+template <typename T> class SharedPtr {
+  public:
+	SharedPtr() : _ptr((T*)0)
+	{
+	}
+	SharedPtr(T* obj) : _ptr(obj)
+	{
+		++obj->__refCount;
+	}
+	SharedPtr(const SharedPtr& sp) : _ptr(sp._getAndInc())
+	{
+	}
 
 	~SharedPtr()
 	{
@@ -43,10 +48,10 @@ public:
 		}
 	}
 
-	inline SharedPtr &operator=(const SharedPtr &sp)
+	inline SharedPtr& operator=(const SharedPtr& sp)
 	{
 		if (_ptr != sp._ptr) {
-			T *p = sp._getAndInc();
+			T* p = sp._getAndInc();
 			if (_ptr) {
 				if (--_ptr->__refCount <= 0) {
 					delete _ptr;
@@ -65,7 +70,7 @@ public:
 	 *
 	 * @param ptr Naked pointer to assign
 	 */
-	inline void set(T *ptr)
+	inline void set(T* ptr)
 	{
 		zero();
 		++ptr->__refCount;
@@ -77,21 +82,33 @@ public:
 	 *
 	 * @param with Pointer to swap with
 	 */
-	inline void swap(SharedPtr &with)
+	inline void swap(SharedPtr& with)
 	{
-		T *tmp = _ptr;
+		T* tmp = _ptr;
 		_ptr = with._ptr;
 		with._ptr = tmp;
 	}
 
-	inline operator bool() const { return (_ptr != (T *)0); }
-	inline T &operator*() const { return *_ptr; }
-	inline T *operator->() const { return _ptr; }
+	inline operator bool() const
+	{
+		return (_ptr != (T*)0);
+	}
+	inline T& operator*() const
+	{
+		return *_ptr;
+	}
+	inline T* operator->() const
+	{
+		return _ptr;
+	}
 
 	/**
 	 * @return Raw pointer to held object
 	 */
-	inline T *ptr() const { return _ptr; }
+	inline T* ptr() const
+	{
+		return _ptr;
+	}
 
 	/**
 	 * Set this pointer to NULL
@@ -102,7 +119,7 @@ public:
 			if (--_ptr->__refCount <= 0) {
 				delete _ptr;
 			}
-			_ptr = (T *)0;
+			_ptr = (T*)0;
 		}
 	}
 
@@ -117,24 +134,42 @@ public:
 		return 0;
 	}
 
-	inline bool operator==(const SharedPtr &sp) const { return (_ptr == sp._ptr); }
-	inline bool operator!=(const SharedPtr &sp) const { return (_ptr != sp._ptr); }
-	inline bool operator>(const SharedPtr &sp) const { return (_ptr > sp._ptr); }
-	inline bool operator<(const SharedPtr &sp) const { return (_ptr < sp._ptr); }
-	inline bool operator>=(const SharedPtr &sp) const { return (_ptr >= sp._ptr); }
-	inline bool operator<=(const SharedPtr &sp) const { return (_ptr <= sp._ptr); }
+	inline bool operator==(const SharedPtr& sp) const
+	{
+		return (_ptr == sp._ptr);
+	}
+	inline bool operator!=(const SharedPtr& sp) const
+	{
+		return (_ptr != sp._ptr);
+	}
+	inline bool operator>(const SharedPtr& sp) const
+	{
+		return (_ptr > sp._ptr);
+	}
+	inline bool operator<(const SharedPtr& sp) const
+	{
+		return (_ptr < sp._ptr);
+	}
+	inline bool operator>=(const SharedPtr& sp) const
+	{
+		return (_ptr >= sp._ptr);
+	}
+	inline bool operator<=(const SharedPtr& sp) const
+	{
+		return (_ptr <= sp._ptr);
+	}
 
-private:
-	inline T *_getAndInc() const
+  private:
+	inline T* _getAndInc() const
 	{
 		if (_ptr) {
 			++_ptr->__refCount;
 		}
 		return _ptr;
 	}
-	T *_ptr;
+	T* _ptr;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

File diff suppressed because it is too large
+ 263 - 260
node/Switch.cpp


+ 90 - 89
node/Switch.hpp

@@ -14,32 +14,32 @@
 #ifndef ZT_N_SWITCH_HPP
 #define ZT_N_SWITCH_HPP
 
-#include <map>
-#include <set>
-#include <vector>
-#include <list>
-
 #include "Constants.hpp"
-#include "Mutex.hpp"
-#include "MAC.hpp"
-#include "Packet.hpp"
-#include "Utils.hpp"
+#include "Hashtable.hpp"
+#include "IncomingPacket.hpp"
 #include "InetAddress.hpp"
-#include "Topology.hpp"
+#include "MAC.hpp"
+#include "Mutex.hpp"
 #include "Network.hpp"
+#include "Packet.hpp"
 #include "SharedPtr.hpp"
-#include "IncomingPacket.hpp"
-#include "Hashtable.hpp"
+#include "Topology.hpp"
+#include "Utils.hpp"
+
+#include <list>
+#include <map>
+#include <set>
+#include <vector>
 
 /* Ethernet frame types that might be relevant to us */
-#define ZT_ETHERTYPE_IPV4 0x0800
-#define ZT_ETHERTYPE_ARP 0x0806
-#define ZT_ETHERTYPE_RARP 0x8035
+#define ZT_ETHERTYPE_IPV4  0x0800
+#define ZT_ETHERTYPE_ARP   0x0806
+#define ZT_ETHERTYPE_RARP  0x8035
 #define ZT_ETHERTYPE_ATALK 0x809b
-#define ZT_ETHERTYPE_AARP 0x80f3
+#define ZT_ETHERTYPE_AARP  0x80f3
 #define ZT_ETHERTYPE_IPX_A 0x8137
 #define ZT_ETHERTYPE_IPX_B 0x8138
-#define ZT_ETHERTYPE_IPV6 0x86dd
+#define ZT_ETHERTYPE_IPV6  0x86dd
 
 namespace ZeroTier {
 
@@ -54,20 +54,19 @@ class Peer;
  * packets from tap devices, and this sends them where they need to go and
  * wraps/unwraps accordingly. It also handles queues and timeouts and such.
  */
-class Switch
-{
+class Switch {
 	struct ManagedQueue;
 	struct TXQueueEntry;
 
 	friend class SharedPtr<Peer>;
 
 	typedef struct {
-		TXQueueEntry *p;
+		TXQueueEntry* p;
 		bool ok_to_drop;
 	} dqr;
 
-public:
-	Switch(const RuntimeEnvironment *renv);
+  public:
+	Switch(const RuntimeEnvironment* renv);
 
 	/**
 	 * Called when a packet is received from the real network
@@ -78,7 +77,7 @@ public:
 	 * @param data Packet data
 	 * @param len Packet length
 	 */
-	void onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddress &fromAddr,const void *data,unsigned int len);
+	void onRemotePacket(void* tPtr, const int64_t localSocket, const InetAddress& fromAddr, const void* data, unsigned int len);
 
 	/**
 	 * Returns whether our bonding or balancing policy is aware of flows.
@@ -97,7 +96,7 @@ public:
 	 * @param data Ethernet payload
 	 * @param len Frame length
 	 */
-	void onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len);
+	void onLocalEthernet(void* tPtr, const SharedPtr<Network>& network, const MAC& from, const MAC& to, unsigned int etherType, unsigned int vlanId, const void* data, unsigned int len);
 
 	/**
 	 * Determines the next drop schedule for packets in the TX queue
@@ -114,7 +113,7 @@ public:
 	 * @param q The TX queue that is being dequeued from
 	 * @param now Current time
 	 */
-	dqr dodequeue(ManagedQueue *q, uint64_t now);
+	dqr dodequeue(ManagedQueue* q, uint64_t now);
 
 	/**
 	 * Presents a packet to the AQM scheduler.
@@ -125,14 +124,14 @@ public:
 	 * @param encrypt Encrypt packet payload? (always true except for HELLO)
 	 * @param qosBucket Which bucket the rule-system determined this packet should fall into
 	 */
-	void aqm_enqueue(void *tPtr, const SharedPtr<Network> &network, Packet &packet,bool encrypt,int qosBucket,int32_t flowId = ZT_QOS_NO_FLOW);
+	void aqm_enqueue(void* tPtr, const SharedPtr<Network>& network, Packet& packet, bool encrypt, int qosBucket, int32_t flowId = ZT_QOS_NO_FLOW);
 
 	/**
 	 * Performs a single AQM cycle and dequeues and transmits all eligible packets on all networks
 	 *
 	 * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
 	 */
-	void aqm_dequeue(void *tPtr);
+	void aqm_dequeue(void* tPtr);
 
 	/**
 	 * Calls the dequeue mechanism and adjust queue state variables
@@ -141,7 +140,7 @@ public:
 	 * @param isNew Whether or not this queue is in the NEW list
 	 * @param now Current time
 	 */
-	Switch::TXQueueEntry * CoDelDequeue(ManagedQueue *q, bool isNew, uint64_t now);
+	Switch::TXQueueEntry* CoDelDequeue(ManagedQueue* q, bool isNew, uint64_t now);
 
 	/**
 	 * Removes QoS Queues and flow state variables for a specific network. These queues are created
@@ -171,7 +170,7 @@ public:
 	 * @param packet Packet to send (buffer may be modified)
 	 * @param encrypt Encrypt packet payload? (always true except for HELLO)
 	 */
-	void send(void *tPtr,Packet &packet,bool encrypt,int32_t flowId = ZT_QOS_NO_FLOW);
+	void send(void* tPtr, Packet& packet, bool encrypt, int32_t flowId = ZT_QOS_NO_FLOW);
 
 	/**
 	 * Request WHOIS on a given address
@@ -180,7 +179,7 @@ public:
 	 * @param now Current time
 	 * @param addr Address to look up
 	 */
-	void requestWhois(void *tPtr,const int64_t now,const Address &addr);
+	void requestWhois(void* tPtr, const int64_t now, const Address& addr);
 
 	/**
 	 * Run any processes that are waiting for this peer's identity
@@ -190,7 +189,7 @@ public:
 	 * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
 	 * @param peer New peer
 	 */
-	void doAnythingWaitingForPeer(void *tPtr,const SharedPtr<Peer> &peer);
+	void doAnythingWaitingForPeer(void* tPtr, const SharedPtr<Peer>& peer);
 
 	/**
 	 * Perform retries and other periodic timer tasks
@@ -202,33 +201,34 @@ public:
 	 * @param now Current time
 	 * @return Number of milliseconds until doTimerTasks() should be run again
 	 */
-	unsigned long doTimerTasks(void *tPtr,int64_t now);
+	unsigned long doTimerTasks(void* tPtr, int64_t now);
 
-private:
-	bool _shouldUnite(const int64_t now,const Address &source,const Address &destination);
-	bool _trySend(void *tPtr,Packet &packet,bool encrypt,int32_t flowId = ZT_QOS_NO_FLOW); // packet is modified if return is true
-	void _sendViaSpecificPath(void *tPtr,SharedPtr<Peer> peer,SharedPtr<Path> viaPath,uint16_t userSpecifiedMtu, int64_t now,Packet &packet,bool encrypt,int32_t flowId);
-	void _recordOutgoingPacketMetrics(const Packet &p);
+  private:
+	bool _shouldUnite(const int64_t now, const Address& source, const Address& destination);
+	bool _trySend(void* tPtr, Packet& packet, bool encrypt, int32_t flowId = ZT_QOS_NO_FLOW);	// packet is modified if return is true
+	void _sendViaSpecificPath(void* tPtr, SharedPtr<Peer> peer, SharedPtr<Path> viaPath, uint16_t userSpecifiedMtu, int64_t now, Packet& packet, bool encrypt, int32_t flowId);
+	void _recordOutgoingPacketMetrics(const Packet& p);
 
-	const RuntimeEnvironment *const RR;
+	const RuntimeEnvironment* const RR;
 	int64_t _lastBeaconResponse;
 	volatile int64_t _lastCheckedQueues;
 
 	// Time we last sent a WHOIS request for each address
-	Hashtable< Address,int64_t > _lastSentWhoisRequest;
+	Hashtable<Address, int64_t> _lastSentWhoisRequest;
 	Mutex _lastSentWhoisRequest_m;
 
 	// Packets waiting for WHOIS replies or other decode info or missing fragments
-	struct RXQueueEntry
-	{
-		RXQueueEntry() : timestamp(0) {}
-		volatile int64_t timestamp; // 0 if entry is not in use
+	struct RXQueueEntry {
+		RXQueueEntry() : timestamp(0)
+		{
+		}
+		volatile int64_t timestamp;	  // 0 if entry is not in use
 		volatile uint64_t packetId;
-		IncomingPacket frag0; // head of packet
-		Packet::Fragment frags[ZT_MAX_PACKET_FRAGMENTS - 1]; // later fragments (if any)
-		unsigned int totalFragments; // 0 if only frag0 received, waiting for frags
-		uint32_t haveFragments; // bit mask, LSB to MSB
-		volatile bool complete; // if true, packet is complete
+		IncomingPacket frag0;								   // head of packet
+		Packet::Fragment frags[ZT_MAX_PACKET_FRAGMENTS - 1];   // later fragments (if any)
+		unsigned int totalFragments;						   // 0 if only frag0 received, waiting for frags
+		uint32_t haveFragments;								   // bit mask, LSB to MSB
+		volatile bool complete;								   // if true, packet is complete
 		volatile int32_t flowId;
 		Mutex lock;
 	};
@@ -236,12 +236,12 @@ private:
 	AtomicCounter _rxQueuePtr;
 
 	// Returns matching or next available RX queue entry
-	inline RXQueueEntry *_findRXQueueEntry(uint64_t packetId)
+	inline RXQueueEntry* _findRXQueueEntry(uint64_t packetId)
 	{
 		const unsigned int current = static_cast<unsigned int>(_rxQueuePtr.load());
-		for(unsigned int k=1;k<=ZT_RX_QUEUE_SIZE;++k) {
-			RXQueueEntry *rq = &(_rxQueue[(current - k) % ZT_RX_QUEUE_SIZE]);
-			if ((rq->packetId == packetId)&&(rq->timestamp)) {
+		for (unsigned int k = 1; k <= ZT_RX_QUEUE_SIZE; ++k) {
+			RXQueueEntry* rq = &(_rxQueue[(current - k) % ZT_RX_QUEUE_SIZE]);
+			if ((rq->packetId == packetId) && (rq->timestamp)) {
 				return rq;
 			}
 		}
@@ -250,62 +250,64 @@ private:
 	}
 
 	// Returns current entry in rx queue ring buffer and increments ring pointer
-	inline RXQueueEntry *_nextRXQueueEntry()
+	inline RXQueueEntry* _nextRXQueueEntry()
 	{
 		return &(_rxQueue[static_cast<unsigned int>((++_rxQueuePtr) - 1) % ZT_RX_QUEUE_SIZE]);
 	}
 
 	// ZeroTier-layer TX queue entry
-	struct TXQueueEntry
-	{
-		TXQueueEntry() {}
-		TXQueueEntry(Address d,uint64_t ct,const Packet &p,bool enc,int32_t fid) :
-			dest(d),
-			creationTime(ct),
-			packet(p),
-			encrypt(enc),
-			flowId(fid) {}
+	struct TXQueueEntry {
+		TXQueueEntry()
+		{
+		}
+		TXQueueEntry(Address d, uint64_t ct, const Packet& p, bool enc, int32_t fid) : dest(d), creationTime(ct), packet(p), encrypt(enc), flowId(fid)
+		{
+		}
 
 		Address dest;
 		uint64_t creationTime;
-		Packet packet; // unencrypted/unMAC'd packet -- this is done at send time
+		Packet packet;	 // unencrypted/unMAC'd packet -- this is done at send time
 		bool encrypt;
 		int32_t flowId;
 	};
-	std::list< TXQueueEntry > _txQueue;
+	std::list<TXQueueEntry> _txQueue;
 	Mutex _txQueue_m;
 	Mutex _aqm_m;
 
 	// Tracks sending of VERB_RENDEZVOUS to relaying peers
-	struct _LastUniteKey
-	{
-		_LastUniteKey() : x(0),y(0) {}
-		_LastUniteKey(const Address &a1,const Address &a2)
+	struct _LastUniteKey {
+		_LastUniteKey() : x(0), y(0)
+		{
+		}
+		_LastUniteKey(const Address& a1, const Address& a2)
 		{
 			if (a1 > a2) {
 				x = a2.toInt();
 				y = a1.toInt();
-			} else {
+			}
+			else {
 				x = a1.toInt();
 				y = a2.toInt();
 			}
 		}
-		inline unsigned long hashCode() const { return ((unsigned long)x ^ (unsigned long)y); }
-		inline bool operator==(const _LastUniteKey &k) const { return ((x == k.x)&&(y == k.y)); }
-		uint64_t x,y;
+		inline unsigned long hashCode() const
+		{
+			return ((unsigned long)x ^ (unsigned long)y);
+		}
+		inline bool operator==(const _LastUniteKey& k) const
+		{
+			return ((x == k.x) && (y == k.y));
+		}
+		uint64_t x, y;
 	};
-	Hashtable< _LastUniteKey,uint64_t > _lastUniteAttempt; // key is always sorted in ascending order, for set-like behavior
+	Hashtable<_LastUniteKey, uint64_t> _lastUniteAttempt;	// key is always sorted in ascending order, for set-like behavior
 	Mutex _lastUniteAttempt_m;
 
 	// Queue with additional flow state variables
-	struct ManagedQueue
-	{
-		ManagedQueue(int id) :
-			id(id),
-			byteCredit(ZT_AQM_QUANTUM),
-			byteLength(0),
-			dropping(false)
-		{}
+	struct ManagedQueue {
+		ManagedQueue(int id) : id(id), byteCredit(ZT_AQM_QUANTUM), byteLength(0), dropping(false)
+		{
+		}
 		int id;
 		int byteCredit;
 		int byteLength;
@@ -314,19 +316,18 @@ private:
 		uint64_t drop_next;
 		bool dropping;
 		uint64_t drop_next_time;
-		std::list< TXQueueEntry *> q;
+		std::list<TXQueueEntry*> q;
 	};
 	// To implement fq_codel we need to maintain a queue of queues
-	struct NetworkQoSControlBlock
-	{
+	struct NetworkQoSControlBlock {
 		int _currEnqueuedPackets;
-		std::vector<ManagedQueue *> newQueues;
-		std::vector<ManagedQueue *> oldQueues;
-		std::vector<ManagedQueue *> inactiveQueues;
+		std::vector<ManagedQueue*> newQueues;
+		std::vector<ManagedQueue*> oldQueues;
+		std::vector<ManagedQueue*> inactiveQueues;
 	};
-	std::map<uint64_t,NetworkQoSControlBlock*> _netQueueControlBlock;
+	std::map<uint64_t, NetworkQoSControlBlock*> _netQueueControlBlock;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 14 - 12
node/Tag.cpp

@@ -12,32 +12,34 @@
 /****/
 
 #include "Tag.hpp"
-#include "RuntimeEnvironment.hpp"
+
 #include "Identity.hpp"
-#include "Topology.hpp"
-#include "Switch.hpp"
 #include "Network.hpp"
 #include "Node.hpp"
+#include "RuntimeEnvironment.hpp"
+#include "Switch.hpp"
+#include "Topology.hpp"
 
 namespace ZeroTier {
 
-int Tag::verify(const RuntimeEnvironment *RR,void *tPtr) const
+int Tag::verify(const RuntimeEnvironment* RR, void* tPtr) const
 {
-	if ((!_signedBy)||(_signedBy != Network::controllerFor(_networkId))) {
+	if ((! _signedBy) || (_signedBy != Network::controllerFor(_networkId))) {
 		return -1;
 	}
-	const Identity id(RR->topology->getIdentity(tPtr,_signedBy));
-	if (!id) {
-		RR->sw->requestWhois(tPtr,RR->node->now(),_signedBy);
+	const Identity id(RR->topology->getIdentity(tPtr, _signedBy));
+	if (! id) {
+		RR->sw->requestWhois(tPtr, RR->node->now(), _signedBy);
 		return 1;
 	}
 	try {
 		Buffer<(sizeof(Tag) * 2)> tmp;
-		this->serialize(tmp,true);
-		return (id.verify(tmp.data(),tmp.size(),_signature) ? 0 : -1);
-	} catch ( ... ) {
+		this->serialize(tmp, true);
+		return (id.verify(tmp.data(), tmp.size(), _signature) ? 0 : -1);
+	}
+	catch (...) {
 		return -1;
 	}
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier

+ 109 - 65
node/Tag.hpp

@@ -14,18 +14,18 @@
 #ifndef ZT_TAG_HPP
 #define ZT_TAG_HPP
 
+#include "Address.hpp"
+#include "Buffer.hpp"
+#include "C25519.hpp"
+#include "Constants.hpp"
+#include "Credential.hpp"
+#include "Identity.hpp"
+
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "Constants.hpp"
-#include "Credential.hpp"
-#include "C25519.hpp"
-#include "Address.hpp"
-#include "Identity.hpp"
-#include "Buffer.hpp"
-
 namespace ZeroTier {
 
 class RuntimeEnvironment;
@@ -47,18 +47,16 @@ class RuntimeEnvironment;
  * Unlike capabilities tags are signed only by the issuer and are never
  * transferable.
  */
-class Tag : public Credential
-{
-public:
-	static inline Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_TAG; }
-
-	Tag() :
-		_id(0),
-		_value(0),
-		_networkId(0),
-		_ts(0)
+class Tag : public Credential {
+  public:
+	static inline Credential::Type credentialType()
+	{
+		return Credential::CREDENTIAL_TYPE_TAG;
+	}
+
+	Tag() : _id(0), _value(0), _networkId(0), _ts(0)
 	{
-		memset(_signature.data,0,sizeof(_signature.data));
+		memset(_signature.data, 0, sizeof(_signature.data));
 	}
 
 	/**
@@ -68,23 +66,35 @@ public:
 	 * @param id Tag ID
 	 * @param value Tag value
 	 */
-	Tag(const uint64_t nwid,const int64_t ts,const Address &issuedTo,const uint32_t id,const uint32_t value) :
-		_id(id),
-		_value(value),
-		_networkId(nwid),
-		_ts(ts),
-		_issuedTo(issuedTo),
-		_signedBy()
+	Tag(const uint64_t nwid, const int64_t ts, const Address& issuedTo, const uint32_t id, const uint32_t value) : _id(id), _value(value), _networkId(nwid), _ts(ts), _issuedTo(issuedTo), _signedBy()
 	{
-		memset(_signature.data,0,sizeof(_signature.data));
+		memset(_signature.data, 0, sizeof(_signature.data));
 	}
 
-	inline uint32_t id() const { return _id; }
-	inline const uint32_t &value() const { return _value; }
-	inline uint64_t networkId() const { return _networkId; }
-	inline int64_t timestamp() const { return _ts; }
-	inline const Address &issuedTo() const { return _issuedTo; }
-	inline const Address &signedBy() const { return _signedBy; }
+	inline uint32_t id() const
+	{
+		return _id;
+	}
+	inline const uint32_t& value() const
+	{
+		return _value;
+	}
+	inline uint64_t networkId() const
+	{
+		return _networkId;
+	}
+	inline int64_t timestamp() const
+	{
+		return _ts;
+	}
+	inline const Address& issuedTo() const
+	{
+		return _issuedTo;
+	}
+	inline const Address& signedBy() const
+	{
+		return _signedBy;
+	}
 
 	/**
 	 * Sign this tag
@@ -92,13 +102,13 @@ public:
 	 * @param signer Signing identity, must have private key
 	 * @return True if signature was successful
 	 */
-	inline bool sign(const Identity &signer)
+	inline bool sign(const Identity& signer)
 	{
 		if (signer.hasPrivate()) {
 			Buffer<sizeof(Tag) + 64> tmp;
 			_signedBy = signer.address();
-			this->serialize(tmp,true);
-			_signature = signer.sign(tmp.data(),tmp.size());
+			this->serialize(tmp, true);
+			_signature = signer.sign(tmp.data(), tmp.size());
 			return true;
 		}
 		return false;
@@ -111,10 +121,9 @@ public:
 	 * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
 	 * @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature or tag
 	 */
-	int verify(const RuntimeEnvironment *RR,void *tPtr) const;
+	int verify(const RuntimeEnvironment* RR, void* tPtr) const;
 
-	template<unsigned int C>
-	inline void serialize(Buffer<C> &b,const bool forSign = false) const
+	template <unsigned int C> inline void serialize(Buffer<C>& b, const bool forSign = false) const
 	{
 		if (forSign) {
 			b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
@@ -127,21 +136,20 @@ public:
 
 		_issuedTo.appendTo(b);
 		_signedBy.appendTo(b);
-		if (!forSign) {
-			b.append((uint8_t)1); // 1 == Ed25519
-			b.append((uint16_t)ZT_C25519_SIGNATURE_LEN); // length of signature
-			b.append(_signature.data,ZT_C25519_SIGNATURE_LEN);
+		if (! forSign) {
+			b.append((uint8_t)1);						   // 1 == Ed25519
+			b.append((uint16_t)ZT_C25519_SIGNATURE_LEN);   // length of signature
+			b.append(_signature.data, ZT_C25519_SIGNATURE_LEN);
 		}
 
-		b.append((uint16_t)0); // length of additional fields, currently 0
+		b.append((uint16_t)0);	 // length of additional fields, currently 0
 
 		if (forSign) {
 			b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
 		}
 	}
 
-	template<unsigned int C>
-	inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
+	template <unsigned int C> inline unsigned int deserialize(const Buffer<C>& b, unsigned int startAt = 0)
 	{
 		unsigned int p = startAt;
 
@@ -157,18 +165,19 @@ public:
 		_value = b.template at<uint32_t>(p);
 		p += 4;
 
-		_issuedTo.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
+		_issuedTo.setTo(b.field(p, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
 		p += ZT_ADDRESS_LENGTH;
-		_signedBy.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
+		_signedBy.setTo(b.field(p, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
 		p += ZT_ADDRESS_LENGTH;
 		if (b[p++] == 1) {
 			if (b.template at<uint16_t>(p) != ZT_C25519_SIGNATURE_LEN) {
 				throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
 			}
 			p += 2;
-			memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN);
+			memcpy(_signature.data, b.field(p, ZT_C25519_SIGNATURE_LEN), ZT_C25519_SIGNATURE_LEN);
 			p += ZT_C25519_SIGNATURE_LEN;
-		} else {
+		}
+		else {
 			p += 2 + b.template at<uint16_t>(p);
 		}
 
@@ -181,26 +190,61 @@ public:
 	}
 
 	// Provides natural sort order by ID
-	inline bool operator<(const Tag &t) const { return (_id < t._id); }
+	inline bool operator<(const Tag& t) const
+	{
+		return (_id < t._id);
+	}
 
-	inline bool operator==(const Tag &t) const { return (memcmp(this,&t,sizeof(Tag)) == 0); }
-	inline bool operator!=(const Tag &t) const { return (memcmp(this,&t,sizeof(Tag)) != 0); }
+	inline bool operator==(const Tag& t) const
+	{
+		return (memcmp(this, &t, sizeof(Tag)) == 0);
+	}
+	inline bool operator!=(const Tag& t) const
+	{
+		return (memcmp(this, &t, sizeof(Tag)) != 0);
+	}
 
 	// For searching sorted arrays or lists of Tags by ID
-	struct IdComparePredicate
-	{
-		inline bool operator()(const Tag &a,const Tag &b) const { return (a.id() < b.id()); }
-		inline bool operator()(const uint32_t a,const Tag &b) const { return (a < b.id()); }
-		inline bool operator()(const Tag &a,const uint32_t b) const { return (a.id() < b); }
-		inline bool operator()(const Tag *a,const Tag *b) const { return (a->id() < b->id()); }
-		inline bool operator()(const Tag *a,const Tag &b) const { return (a->id() < b.id()); }
-		inline bool operator()(const Tag &a,const Tag *b) const { return (a.id() < b->id()); }
-		inline bool operator()(const uint32_t a,const Tag *b) const { return (a < b->id()); }
-		inline bool operator()(const Tag *a,const uint32_t b) const { return (a->id() < b); }
-		inline bool operator()(const uint32_t a,const uint32_t b) const { return (a < b); }
+	struct IdComparePredicate {
+		inline bool operator()(const Tag& a, const Tag& b) const
+		{
+			return (a.id() < b.id());
+		}
+		inline bool operator()(const uint32_t a, const Tag& b) const
+		{
+			return (a < b.id());
+		}
+		inline bool operator()(const Tag& a, const uint32_t b) const
+		{
+			return (a.id() < b);
+		}
+		inline bool operator()(const Tag* a, const Tag* b) const
+		{
+			return (a->id() < b->id());
+		}
+		inline bool operator()(const Tag* a, const Tag& b) const
+		{
+			return (a->id() < b.id());
+		}
+		inline bool operator()(const Tag& a, const Tag* b) const
+		{
+			return (a.id() < b->id());
+		}
+		inline bool operator()(const uint32_t a, const Tag* b) const
+		{
+			return (a < b->id());
+		}
+		inline bool operator()(const Tag* a, const uint32_t b) const
+		{
+			return (a->id() < b);
+		}
+		inline bool operator()(const uint32_t a, const uint32_t b) const
+		{
+			return (a < b);
+		}
 	};
 
-private:
+  private:
 	uint32_t _id;
 	uint32_t _value;
 	uint64_t _networkId;
@@ -210,6 +254,6 @@ private:
 	C25519::Signature _signature;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

File diff suppressed because it is too large
+ 5 - 4
node/Topology.cpp


+ 98 - 95
node/Topology.hpp

@@ -14,26 +14,24 @@
 #ifndef ZT_TOPOLOGY_HPP
 #define ZT_TOPOLOGY_HPP
 
-#include <stdio.h>
-#include <string.h>
-
-#include <vector>
-#include <stdexcept>
-#include <algorithm>
-#include <utility>
-
-#include "Constants.hpp"
 #include "../include/ZeroTierOne.h"
-
 #include "Address.hpp"
+#include "Constants.hpp"
+#include "Hashtable.hpp"
 #include "Identity.hpp"
-#include "Peer.hpp"
-#include "Path.hpp"
-#include "Mutex.hpp"
 #include "InetAddress.hpp"
-#include "Hashtable.hpp"
+#include "Mutex.hpp"
+#include "Path.hpp"
+#include "Peer.hpp"
 #include "World.hpp"
 
+#include <algorithm>
+#include <stdexcept>
+#include <stdio.h>
+#include <string.h>
+#include <utility>
+#include <vector>
+
 namespace ZeroTier {
 
 class RuntimeEnvironment;
@@ -41,10 +39,9 @@ class RuntimeEnvironment;
 /**
  * Database of network topology
  */
-class Topology
-{
-public:
-	Topology(const RuntimeEnvironment *renv,void *tPtr);
+class Topology {
+  public:
+	Topology(const RuntimeEnvironment* renv, void* tPtr);
 	~Topology();
 
 	/**
@@ -57,7 +54,7 @@ public:
 	 * @param peer Peer to add
 	 * @return New or existing peer (should replace 'peer')
 	 */
-	SharedPtr<Peer> addPeer(void *tPtr,const SharedPtr<Peer> &peer);
+	SharedPtr<Peer> addPeer(void* tPtr, const SharedPtr<Peer>& peer);
 
 	/**
 	 * Get a peer from its address
@@ -66,14 +63,14 @@ public:
 	 * @param zta ZeroTier address of peer
 	 * @return Peer or NULL if not found
 	 */
-	SharedPtr<Peer> getPeer(void *tPtr,const Address &zta);
+	SharedPtr<Peer> getPeer(void* tPtr, const Address& zta);
 
 	/**
 	 * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
 	 * @param zta ZeroTier address of peer
 	 * @return Identity or NULL identity if not found
 	 */
-	Identity getIdentity(void *tPtr,const Address &zta);
+	Identity getIdentity(void* tPtr, const Address& zta);
 
 	/**
 	 * Get a peer only if it is presently in memory (no disk cache)
@@ -85,10 +82,10 @@ public:
 	 *
 	 * @param zta ZeroTier address
 	 */
-	inline SharedPtr<Peer> getPeerNoCache(const Address &zta)
+	inline SharedPtr<Peer> getPeerNoCache(const Address& zta)
 	{
 		Mutex::Lock _l(_peers_m);
-		const SharedPtr<Peer> *const ap = _peers.get(zta);
+		const SharedPtr<Peer>* const ap = _peers.get(zta);
 		if (ap) {
 			return *ap;
 		}
@@ -102,12 +99,12 @@ public:
 	 * @param r Remote address
 	 * @return Pointer to canonicalized Path object
 	 */
-	inline SharedPtr<Path> getPath(const int64_t l,const InetAddress &r)
+	inline SharedPtr<Path> getPath(const int64_t l, const InetAddress& r)
 	{
 		Mutex::Lock _l(_paths_m);
-		SharedPtr<Path> &p = _paths[Path::HashKey(l,r)];
-		if (!p) {
-			p.set(new Path(l,r));
+		SharedPtr<Path>& p = _paths[Path::HashKey(l, r)];
+		if (! p) {
+			p.set(new Path(l, r));
 		}
 		return p;
 	}
@@ -123,19 +120,19 @@ public:
 	 * @param id Identity to check
 	 * @return True if this is a root server or a network preferred relay from one of our networks
 	 */
-	bool isUpstream(const Identity &id) const;
+	bool isUpstream(const Identity& id) const;
 
 	/**
 	 * @param addr Address to check
 	 * @return True if we should accept a world update from this address
 	 */
-	bool shouldAcceptWorldUpdateFrom(const Address &addr) const;
+	bool shouldAcceptWorldUpdateFrom(const Address& addr) const;
 
 	/**
 	 * @param ztaddr ZeroTier address
 	 * @return Peer role for this device
 	 */
-	ZT_PeerRole role(const Address &ztaddr) const;
+	ZT_PeerRole role(const Address& ztaddr) const;
 
 	/**
 	 * Check for prohibited endpoints
@@ -151,39 +148,39 @@ public:
 	 * @param ipaddr IP address
 	 * @return True if this ZT/IP pair should not be allowed to be used
 	 */
-	bool isProhibitedEndpoint(const Address &ztaddr,const InetAddress &ipaddr) const;
+	bool isProhibitedEndpoint(const Address& ztaddr, const InetAddress& ipaddr) const;
 
 	/**
 	 * Gets upstreams to contact and their stable endpoints (if known)
 	 *
 	 * @param eps Hash table to fill with addresses and their stable endpoints
 	 */
-	inline void getUpstreamsToContact(Hashtable< Address,std::vector<InetAddress> > &eps) const
+	inline void getUpstreamsToContact(Hashtable<Address, std::vector<InetAddress> >& eps) const
 	{
 		Mutex::Lock _l(_upstreams_m);
-		for(std::vector<World::Root>::const_iterator i(_planet.roots().begin());i!=_planet.roots().end();++i) {
+		for (std::vector<World::Root>::const_iterator i(_planet.roots().begin()); i != _planet.roots().end(); ++i) {
 			if (i->identity != RR->identity) {
-				std::vector<InetAddress> &ips = eps[i->identity.address()];
-				for(std::vector<InetAddress>::const_iterator j(i->stableEndpoints.begin());j!=i->stableEndpoints.end();++j) {
-					if (std::find(ips.begin(),ips.end(),*j) == ips.end()) {
+				std::vector<InetAddress>& ips = eps[i->identity.address()];
+				for (std::vector<InetAddress>::const_iterator j(i->stableEndpoints.begin()); j != i->stableEndpoints.end(); ++j) {
+					if (std::find(ips.begin(), ips.end(), *j) == ips.end()) {
 						ips.push_back(*j);
 					}
 				}
 			}
 		}
-		for(std::vector<World>::const_iterator m(_moons.begin());m!=_moons.end();++m) {
-			for(std::vector<World::Root>::const_iterator i(m->roots().begin());i!=m->roots().end();++i) {
+		for (std::vector<World>::const_iterator m(_moons.begin()); m != _moons.end(); ++m) {
+			for (std::vector<World::Root>::const_iterator i(m->roots().begin()); i != m->roots().end(); ++i) {
 				if (i->identity != RR->identity) {
-					std::vector<InetAddress> &ips = eps[i->identity.address()];
-					for(std::vector<InetAddress>::const_iterator j(i->stableEndpoints.begin());j!=i->stableEndpoints.end();++j) {
-						if (std::find(ips.begin(),ips.end(),*j) == ips.end()) {
+					std::vector<InetAddress>& ips = eps[i->identity.address()];
+					for (std::vector<InetAddress>::const_iterator j(i->stableEndpoints.begin()); j != i->stableEndpoints.end(); ++j) {
+						if (std::find(ips.begin(), ips.end(), *j) == ips.end()) {
 							ips.push_back(*j);
 						}
 					}
 				}
 			}
 		}
-		for(std::vector< std::pair<uint64_t,Address> >::const_iterator m(_moonSeeds.begin());m!=_moonSeeds.end();++m) {
+		for (std::vector<std::pair<uint64_t, Address> >::const_iterator m(_moonSeeds.begin()); m != _moonSeeds.end(); ++m) {
 			eps[m->second];
 		}
 	}
@@ -213,8 +210,8 @@ public:
 	{
 		Mutex::Lock _l(_upstreams_m);
 		std::vector<uint64_t> mw;
-		for(std::vector< std::pair<uint64_t,Address> >::const_iterator s(_moonSeeds.begin());s!=_moonSeeds.end();++s) {
-			if (std::find(mw.begin(),mw.end(),s->first) == mw.end()) {
+		for (std::vector<std::pair<uint64_t, Address> >::const_iterator s(_moonSeeds.begin()); s != _moonSeeds.end(); ++s) {
+			if (std::find(mw.begin(), mw.end(), s->first) == mw.end()) {
 				mw.push_back(s->first);
 			}
 		}
@@ -235,7 +232,7 @@ public:
 	 */
 	inline uint64_t planetWorldId() const
 	{
-		return _planet.id(); // safe to read without lock, and used from within eachPeer() so don't lock
+		return _planet.id();   // safe to read without lock, and used from within eachPeer() so don't lock
 	}
 
 	/**
@@ -243,7 +240,7 @@ public:
 	 */
 	inline uint64_t planetWorldTimestamp() const
 	{
-		return _planet.timestamp(); // safe to read without lock, and used from within eachPeer() so don't lock
+		return _planet.timestamp();	  // safe to read without lock, and used from within eachPeer() so don't lock
 	}
 
 	/**
@@ -254,7 +251,7 @@ public:
 	 * @param alwaysAcceptNew If true, always accept new moons even if we're not waiting for one
 	 * @return True if it was valid and newer than current (or totally new for moons)
 	 */
-	bool addWorld(void *tPtr,const World &newWorld,bool alwaysAcceptNew);
+	bool addWorld(void* tPtr, const World& newWorld, bool alwaysAcceptNew);
 
 	/**
 	 * Add a moon
@@ -265,7 +262,7 @@ public:
 	 * @param id Moon ID
 	 * @param seed If non-NULL, an address of any member of the moon to contact
 	 */
-	void addMoon(void *tPtr,const uint64_t id,const Address &seed);
+	void addMoon(void* tPtr, const uint64_t id, const Address& seed);
 
 	/**
 	 * Remove a moon
@@ -273,12 +270,12 @@ public:
 	 * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
 	 * @param id Moon's world ID
 	 */
-	void removeMoon(void *tPtr,const uint64_t id);
+	void removeMoon(void* tPtr, const uint64_t id);
 
 	/**
 	 * Clean and flush database
 	 */
-	void doPeriodicTasks(void *tPtr,int64_t now);
+	void doPeriodicTasks(void* tPtr, int64_t now);
 
 	/**
 	 * @param now Current time
@@ -288,11 +285,11 @@ public:
 	{
 		unsigned long cnt = 0;
 		Mutex::Lock _l(_peers_m);
-		Hashtable< Address,SharedPtr<Peer> >::Iterator i(const_cast<Topology *>(this)->_peers);
-		Address *a = (Address *)0;
-		SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
-		while (i.next(a,p)) {
-			const SharedPtr<Path> pp((*p)->getAppropriatePath(now,false));
+		Hashtable<Address, SharedPtr<Peer> >::Iterator i(const_cast<Topology*>(this)->_peers);
+		Address* a = (Address*)0;
+		SharedPtr<Peer>* p = (SharedPtr<Peer>*)0;
+		while (i.next(a, p)) {
+			const SharedPtr<Path> pp((*p)->getAppropriatePath(now, false));
 			if (pp) {
 				++cnt;
 			}
@@ -306,22 +303,21 @@ public:
 	 * @param f Function to apply
 	 * @tparam F Function or function object type
 	 */
-	template<typename F>
-	inline void eachPeer(F f)
+	template <typename F> inline void eachPeer(F f)
 	{
 		Mutex::Lock _l(_peers_m);
-		Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers);
-		Address *a = (Address *)0;
-		SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
-		while (i.next(a,p)) {
-			f(*this,*((const SharedPtr<Peer> *)p));
+		Hashtable<Address, SharedPtr<Peer> >::Iterator i(_peers);
+		Address* a = (Address*)0;
+		SharedPtr<Peer>* p = (SharedPtr<Peer>*)0;
+		while (i.next(a, p)) {
+			f(*this, *((const SharedPtr<Peer>*)p));
 		}
 	}
 
 	/**
 	 * @return All currently active peers by address (unsorted)
 	 */
-	inline std::vector< std::pair< Address,SharedPtr<Peer> > > allPeers() const
+	inline std::vector<std::pair<Address, SharedPtr<Peer> > > allPeers() const
 	{
 		Mutex::Lock _l(_peers_m);
 		return _peers.entries();
@@ -330,7 +326,10 @@ public:
 	/**
 	 * @return True if I am a root server in a planet or moon
 	 */
-	inline bool amUpstream() const { return _amUpstream; }
+	inline bool amUpstream() const
+	{
+		return _amUpstream;
+	}
 
 	/**
 	 * Get info about a path
@@ -341,9 +340,9 @@ public:
 	 * @param mtu Variable set to MTU
 	 * @param trustedPathId Variable set to trusted path ID
 	 */
-	inline void getOutboundPathInfo(const InetAddress &physicalAddress,unsigned int &mtu,uint64_t &trustedPathId)
+	inline void getOutboundPathInfo(const InetAddress& physicalAddress, unsigned int& mtu, uint64_t& trustedPathId)
 	{
-		for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) {
+		for (unsigned int i = 0, j = _numConfiguredPhysicalPaths; i < j; ++i) {
 			if (_physicalPathConfig[i].first.containsAddress(physicalAddress)) {
 				trustedPathId = _physicalPathConfig[i].second.trustedPathId;
 				mtu = _physicalPathConfig[i].second.mtu;
@@ -358,9 +357,9 @@ public:
 	 * @param physicalAddress Physical endpoint address
 	 * @return MTU
 	 */
-	inline unsigned int getOutboundPathMtu(const InetAddress &physicalAddress)
+	inline unsigned int getOutboundPathMtu(const InetAddress& physicalAddress)
 	{
-		for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) {
+		for (unsigned int i = 0, j = _numConfiguredPhysicalPaths; i < j; ++i) {
 			if (_physicalPathConfig[i].first.containsAddress(physicalAddress)) {
 				return _physicalPathConfig[i].second.mtu;
 			}
@@ -374,9 +373,9 @@ public:
 	 * @param physicalAddress Physical address to which we are sending the packet
 	 * @return Trusted path ID or 0 if none (0 is not a valid trusted path ID)
 	 */
-	inline uint64_t getOutboundPathTrust(const InetAddress &physicalAddress)
+	inline uint64_t getOutboundPathTrust(const InetAddress& physicalAddress)
 	{
-		for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) {
+		for (unsigned int i = 0, j = _numConfiguredPhysicalPaths; i < j; ++i) {
 			if (_physicalPathConfig[i].first.containsAddress(physicalAddress)) {
 				return _physicalPathConfig[i].second.trustedPathId;
 			}
@@ -390,10 +389,10 @@ public:
 	 * @param physicalAddress Originating physical address
 	 * @param trustedPathId Trusted path ID from packet (from MAC field)
 	 */
-	inline bool shouldInboundPathBeTrusted(const InetAddress &physicalAddress,const uint64_t trustedPathId)
+	inline bool shouldInboundPathBeTrusted(const InetAddress& physicalAddress, const uint64_t trustedPathId)
 	{
-		for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) {
-			if ((_physicalPathConfig[i].second.trustedPathId == trustedPathId)&&(_physicalPathConfig[i].first.containsAddress(physicalAddress))) {
+		for (unsigned int i = 0, j = _numConfiguredPhysicalPaths; i < j; ++i) {
+			if ((_physicalPathConfig[i].second.trustedPathId == trustedPathId) && (_physicalPathConfig[i].first.containsAddress(physicalAddress))) {
 				return true;
 			}
 		}
@@ -403,13 +402,14 @@ public:
 	/**
 	 * Set or clear physical path configuration (called via Node::setPhysicalPathConfiguration)
 	 */
-	inline void setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig)
+	inline void setPhysicalPathConfiguration(const struct sockaddr_storage* pathNetwork, const ZT_PhysicalPathConfiguration* pathConfig)
 	{
-		if (!pathNetwork) {
+		if (! pathNetwork) {
 			_numConfiguredPhysicalPaths = 0;
-		} else {
-			std::map<InetAddress,ZT_PhysicalPathConfiguration> cpaths;
-			for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) {
+		}
+		else {
+			std::map<InetAddress, ZT_PhysicalPathConfiguration> cpaths;
+			for (unsigned int i = 0, j = _numConfiguredPhysicalPaths; i < j; ++i) {
 				cpaths[_physicalPathConfig[i].first] = _physicalPathConfig[i].second;
 			}
 
@@ -418,19 +418,22 @@ public:
 
 				if (pc.mtu <= 0) {
 					pc.mtu = ZT_DEFAULT_PHYSMTU;
-				} else if (pc.mtu < ZT_MIN_PHYSMTU) {
+				}
+				else if (pc.mtu < ZT_MIN_PHYSMTU) {
 					pc.mtu = ZT_MIN_PHYSMTU;
-				} else if (pc.mtu > ZT_MAX_PHYSMTU) {
+				}
+				else if (pc.mtu > ZT_MAX_PHYSMTU) {
 					pc.mtu = ZT_MAX_PHYSMTU;
 				}
 
-				cpaths[*(reinterpret_cast<const InetAddress *>(pathNetwork))] = pc;
-			} else {
-				cpaths.erase(*(reinterpret_cast<const InetAddress *>(pathNetwork)));
+				cpaths[*(reinterpret_cast<const InetAddress*>(pathNetwork))] = pc;
+			}
+			else {
+				cpaths.erase(*(reinterpret_cast<const InetAddress*>(pathNetwork)));
 			}
 
 			unsigned int cnt = 0;
-			for(std::map<InetAddress,ZT_PhysicalPathConfiguration>::const_iterator i(cpaths.begin());((i!=cpaths.end())&&(cnt<ZT_MAX_CONFIGURABLE_PATHS));++i) {
+			for (std::map<InetAddress, ZT_PhysicalPathConfiguration>::const_iterator i(cpaths.begin()); ((i != cpaths.end()) && (cnt < ZT_MAX_CONFIGURABLE_PATHS)); ++i) {
 				_physicalPathConfig[cnt].first = i->first;
 				_physicalPathConfig[cnt].second = i->second;
 				++cnt;
@@ -439,30 +442,30 @@ public:
 		}
 	}
 
-private:
-	Identity _getIdentity(void *tPtr,const Address &zta);
-	void _memoizeUpstreams(void *tPtr);
-	void _savePeer(void *tPtr,const SharedPtr<Peer> &peer);
+  private:
+	Identity _getIdentity(void* tPtr, const Address& zta);
+	void _memoizeUpstreams(void* tPtr);
+	void _savePeer(void* tPtr, const SharedPtr<Peer>& peer);
 
-	const RuntimeEnvironment *const RR;
+	const RuntimeEnvironment* const RR;
 
-	std::pair<InetAddress,ZT_PhysicalPathConfiguration> _physicalPathConfig[ZT_MAX_CONFIGURABLE_PATHS];
+	std::pair<InetAddress, ZT_PhysicalPathConfiguration> _physicalPathConfig[ZT_MAX_CONFIGURABLE_PATHS];
 	volatile unsigned int _numConfiguredPhysicalPaths;
 
-	Hashtable< Address,SharedPtr<Peer> > _peers;
+	Hashtable<Address, SharedPtr<Peer> > _peers;
 	Mutex _peers_m;
 
-	Hashtable< Path::HashKey,SharedPtr<Path> > _paths;
+	Hashtable<Path::HashKey, SharedPtr<Path> > _paths;
 	Mutex _paths_m;
 
 	World _planet;
 	std::vector<World> _moons;
-	std::vector< std::pair<uint64_t,Address> > _moonSeeds;
+	std::vector<std::pair<uint64_t, Address> > _moonSeeds;
 	std::vector<Address> _upstreamAddresses;
 	bool _amUpstream;
-	Mutex _upstreams_m; // locks worlds, upstream info, moon info, etc.
+	Mutex _upstreams_m;	  // locks worlds, upstream info, moon info, etc.
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 323 - 283
node/Trace.cpp

@@ -11,374 +11,411 @@
  */
 /****/
 
-//#define ZT_TRACE
-
-#include <stdio.h>
-#include <stdarg.h>
+// #define ZT_TRACE
 
 #include "Trace.hpp"
-#include "RuntimeEnvironment.hpp"
-#include "Switch.hpp"
-#include "Node.hpp"
-#include "Utils.hpp"
-#include "Dictionary.hpp"
+
+#include "../include/ZeroTierDebug.h"
+#include "Capability.hpp"
 #include "CertificateOfMembership.hpp"
 #include "CertificateOfOwnership.hpp"
-#include "Tag.hpp"
-#include "Capability.hpp"
+#include "Dictionary.hpp"
+#include "Node.hpp"
 #include "Revocation.hpp"
-#include "../include/ZeroTierDebug.h"
+#include "RuntimeEnvironment.hpp"
+#include "Switch.hpp"
+#include "Tag.hpp"
+#include "Utils.hpp"
+
+#include <stdarg.h>
+#include <stdio.h>
 
 namespace ZeroTier {
 
 #ifdef ZT_TRACE
-static void ZT_LOCAL_TRACE(void *const tPtr,const RuntimeEnvironment *const RR,const char *const fmt,...)
+static void ZT_LOCAL_TRACE(void* const tPtr, const RuntimeEnvironment* const RR, const char* const fmt, ...)
 {
 	char traceMsgBuf[1024];
 	va_list ap;
-	va_start(ap,fmt);
-	vsnprintf(traceMsgBuf,sizeof(traceMsgBuf),fmt,ap);
+	va_start(ap, fmt);
+	vsnprintf(traceMsgBuf, sizeof(traceMsgBuf), fmt, ap);
 	va_end(ap);
 	traceMsgBuf[sizeof(traceMsgBuf) - 1] = (char)0;
-	RR->node->postEvent(tPtr,ZT_EVENT_TRACE,traceMsgBuf);
+	RR->node->postEvent(tPtr, ZT_EVENT_TRACE, traceMsgBuf);
 }
 #else
 #define ZT_LOCAL_TRACE(...)
 #endif
 
-void Trace::resettingPathsInScope(void *const tPtr,const Address &reporter,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,const InetAddress::IpScope scope)
+void Trace::resettingPathsInScope(void* const tPtr, const Address& reporter, const InetAddress& reporterPhysicalAddress, const InetAddress& myPhysicalAddress, const InetAddress::IpScope scope)
 {
 	char tmp[128];
 
-	ZT_LOCAL_TRACE(tPtr,RR,"RESET and revalidate paths in scope %d; new phy address %s reported by trusted peer %.10llx",(int)scope,myPhysicalAddress.toIpString(tmp),reporter.toInt());
+	ZT_LOCAL_TRACE(tPtr, RR, "RESET and revalidate paths in scope %d; new phy address %s reported by trusted peer %.10llx", (int)scope, myPhysicalAddress.toIpString(tmp), reporter.toInt());
 
 	Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
-	d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__RESETTING_PATHS_IN_SCOPE_S);
-	d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR,reporter);
-	d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,reporterPhysicalAddress.toString(tmp));
-	d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_PHYADDR,myPhysicalAddress.toString(tmp));
-	d.add(ZT_REMOTE_TRACE_FIELD__IP_SCOPE,(uint64_t)scope);
+	d.add(ZT_REMOTE_TRACE_FIELD__EVENT, ZT_REMOTE_TRACE_EVENT__RESETTING_PATHS_IN_SCOPE_S);
+	d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR, reporter);
+	d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR, reporterPhysicalAddress.toString(tmp));
+	d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_PHYADDR, myPhysicalAddress.toString(tmp));
+	d.add(ZT_REMOTE_TRACE_FIELD__IP_SCOPE, (uint64_t)scope);
 
 	if (_globalTarget) {
-		_send(tPtr,d,_globalTarget);
+		_send(tPtr, d, _globalTarget);
 	}
-	_spamToAllNetworks(tPtr,d,Trace::LEVEL_NORMAL);
+	_spamToAllNetworks(tPtr, d, Trace::LEVEL_NORMAL);
 }
 
-void Trace::peerConfirmingUnknownPath(void *const tPtr,const uint64_t networkId,Peer &peer,const SharedPtr<Path> &path,const uint64_t packetId,const Packet::Verb verb)
+void Trace::peerConfirmingUnknownPath(void* const tPtr, const uint64_t networkId, Peer& peer, const SharedPtr<Path>& path, const uint64_t packetId, const Packet::Verb verb)
 {
 	char tmp[128];
-	if (!path) {
-		return; // sanity check
+	if (! path) {
+		return;	  // sanity check
 	}
 
-	ZT_LOCAL_TRACE(tPtr,RR,"trying unknown path %s to %.10llx (packet %.16llx verb %d local socket %lld network %.16llx)",path->address().toString(tmp),peer.address().toInt(),packetId,verb,path->localSocket(),networkId);
+	ZT_LOCAL_TRACE(tPtr, RR, "trying unknown path %s to %.10llx (packet %.16llx verb %d local socket %lld network %.16llx)", path->address().toString(tmp), peer.address().toInt(), packetId, verb, path->localSocket(), networkId);
 
-	std::pair<Address,Trace::Level> byn;
+	std::pair<Address, Trace::Level> byn;
 	if (networkId) {
 		Mutex::Lock l(_byNet_m);
-		_byNet.get(networkId,byn);
+		_byNet.get(networkId, byn);
 	}
 
-	if ((_globalTarget)||(byn.first)) {
+	if ((_globalTarget) || (byn.first)) {
 		Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
-		d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__PEER_CONFIRMING_UNKNOWN_PATH_S);
-		d.add(ZT_REMOTE_TRACE_FIELD__PACKET_ID,packetId);
-		d.add(ZT_REMOTE_TRACE_FIELD__PACKET_VERB,(uint64_t)verb);
+		d.add(ZT_REMOTE_TRACE_FIELD__EVENT, ZT_REMOTE_TRACE_EVENT__PEER_CONFIRMING_UNKNOWN_PATH_S);
+		d.add(ZT_REMOTE_TRACE_FIELD__PACKET_ID, packetId);
+		d.add(ZT_REMOTE_TRACE_FIELD__PACKET_VERB, (uint64_t)verb);
 		if (networkId) {
-			d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,networkId);
+			d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID, networkId);
 		}
-		d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR,peer.address());
+		d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR, peer.address());
 		if (path) {
-			d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,path->address().toString(tmp));
-			d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,path->localSocket());
+			d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR, path->address().toString(tmp));
+			d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET, path->localSocket());
 		}
 
 		if (_globalTarget) {
-			_send(tPtr,d,_globalTarget);
+			_send(tPtr, d, _globalTarget);
 		}
 		if (byn.first) {
-			_send(tPtr,d,byn.first);
+			_send(tPtr, d, byn.first);
 		}
 	}
 }
 
-void Trace::bondStateMessage(void *const tPtr,char *msg)
+void Trace::bondStateMessage(void* const tPtr, char* msg)
 {
-	ZT_LOCAL_TRACE(tPtr,RR,"%s",msg);
+	ZT_LOCAL_TRACE(tPtr, RR, "%s", msg);
 }
 
-void Trace::peerLearnedNewPath(void *const tPtr,const uint64_t networkId,Peer &peer,const SharedPtr<Path> &newPath,const uint64_t packetId)
+void Trace::peerLearnedNewPath(void* const tPtr, const uint64_t networkId, Peer& peer, const SharedPtr<Path>& newPath, const uint64_t packetId)
 {
 	char tmp[128];
-	if (!newPath) {
-		return; // sanity check
+	if (! newPath) {
+		return;	  // sanity check
 	}
 
-	ZT_LOCAL_TRACE(tPtr,RR,"learned new path %s to %.10llx (packet %.16llx local socket %lld network %.16llx)",newPath->address().toString(tmp),peer.address().toInt(),packetId,newPath->localSocket(),networkId);
+	ZT_LOCAL_TRACE(tPtr, RR, "learned new path %s to %.10llx (packet %.16llx local socket %lld network %.16llx)", newPath->address().toString(tmp), peer.address().toInt(), packetId, newPath->localSocket(), networkId);
 
-	std::pair<Address,Trace::Level> byn;
+	std::pair<Address, Trace::Level> byn;
 	if (networkId) {
 		Mutex::Lock l(_byNet_m);
-		_byNet.get(networkId,byn);
+		_byNet.get(networkId, byn);
 	}
 
-	if ((_globalTarget)||(byn.first)) {
+	if ((_globalTarget) || (byn.first)) {
 		Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
-		d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__PEER_LEARNED_NEW_PATH_S);
-		d.add(ZT_REMOTE_TRACE_FIELD__PACKET_ID,packetId);
+		d.add(ZT_REMOTE_TRACE_FIELD__EVENT, ZT_REMOTE_TRACE_EVENT__PEER_LEARNED_NEW_PATH_S);
+		d.add(ZT_REMOTE_TRACE_FIELD__PACKET_ID, packetId);
 		if (networkId) {
 			d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID, networkId);
 		}
-		d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR,peer.address());
-		d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,newPath->address().toString(tmp));
-		d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,newPath->localSocket());
+		d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR, peer.address());
+		d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR, newPath->address().toString(tmp));
+		d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET, newPath->localSocket());
 
 		if (_globalTarget) {
-			_send(tPtr,d,_globalTarget);
+			_send(tPtr, d, _globalTarget);
 		}
 		if (byn.first) {
-			_send(tPtr,d,byn.first);
+			_send(tPtr, d, byn.first);
 		}
 	}
 }
 
-void Trace::peerRedirected(void *const tPtr,const uint64_t networkId,Peer &peer,const SharedPtr<Path> &newPath)
+void Trace::peerRedirected(void* const tPtr, const uint64_t networkId, Peer& peer, const SharedPtr<Path>& newPath)
 {
 	char tmp[128];
-	if (!newPath) {
-		return; // sanity check
+	if (! newPath) {
+		return;	  // sanity check
 	}
 
-	ZT_LOCAL_TRACE(tPtr,RR,"explicit redirect from %.10llx to path %s",peer.address().toInt(),newPath->address().toString(tmp));
+	ZT_LOCAL_TRACE(tPtr, RR, "explicit redirect from %.10llx to path %s", peer.address().toInt(), newPath->address().toString(tmp));
 
-	std::pair<Address,Trace::Level> byn;
+	std::pair<Address, Trace::Level> byn;
 	if (networkId) {
 		Mutex::Lock l(_byNet_m);
-		_byNet.get(networkId,byn);
+		_byNet.get(networkId, byn);
 	}
 
-	if ((_globalTarget)||(byn.first)) {
+	if ((_globalTarget) || (byn.first)) {
 		Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
-		d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__PEER_REDIRECTED_S);
+		d.add(ZT_REMOTE_TRACE_FIELD__EVENT, ZT_REMOTE_TRACE_EVENT__PEER_REDIRECTED_S);
 		if (networkId) {
-			d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,networkId);
+			d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID, networkId);
 		}
-		d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR,peer.address());
-		d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,newPath->address().toString(tmp));
-		d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,newPath->localSocket());
+		d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR, peer.address());
+		d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR, newPath->address().toString(tmp));
+		d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET, newPath->localSocket());
 
 		if (_globalTarget) {
-			_send(tPtr,d,_globalTarget);
+			_send(tPtr, d, _globalTarget);
 		}
 		if (byn.first) {
-			_send(tPtr,d,byn.first);
+			_send(tPtr, d, byn.first);
 		}
 	}
 }
 
-void Trace::outgoingNetworkFrameDropped(void *const tPtr,const SharedPtr<Network> &network,const MAC &sourceMac,const MAC &destMac,const unsigned int etherType,const unsigned int vlanId,const unsigned int frameLen,const char *reason)
+void Trace::outgoingNetworkFrameDropped(void* const tPtr, const SharedPtr<Network>& network, const MAC& sourceMac, const MAC& destMac, const unsigned int etherType, const unsigned int vlanId, const unsigned int frameLen, const char* reason)
 {
 #ifdef ZT_TRACE
-	char tmp[128],tmp2[128];
+	char tmp[128], tmp2[128];
 #endif
-	if (!network) {
-		return; // sanity check
+	if (! network) {
+		return;	  // sanity check
 	}
 
-	ZT_LOCAL_TRACE(tPtr,RR,"%.16llx DROP frame %s -> %s etherType %.4x size %u (%s)",network->id(),sourceMac.toString(tmp),destMac.toString(tmp2),etherType,frameLen,(reason) ? reason : "unknown reason");
+	ZT_LOCAL_TRACE(tPtr, RR, "%.16llx DROP frame %s -> %s etherType %.4x size %u (%s)", network->id(), sourceMac.toString(tmp), destMac.toString(tmp2), etherType, frameLen, (reason) ? reason : "unknown reason");
 
-	std::pair<Address,Trace::Level> byn;
-	{ Mutex::Lock l(_byNet_m); _byNet.get(network->id(),byn); }
+	std::pair<Address, Trace::Level> byn;
+	{
+		Mutex::Lock l(_byNet_m);
+		_byNet.get(network->id(), byn);
+	}
 
-	if ( ((_globalTarget)&&((int)_globalLevel >= (int)Trace::LEVEL_VERBOSE)) || ((byn.first)&&((int)byn.second >= (int)Trace::LEVEL_VERBOSE)) ) {
+	if (((_globalTarget) && ((int)_globalLevel >= (int)Trace::LEVEL_VERBOSE)) || ((byn.first) && ((int)byn.second >= (int)Trace::LEVEL_VERBOSE))) {
 		Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
-		d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__OUTGOING_NETWORK_FRAME_DROPPED_S);
-		d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,network->id());
-		d.add(ZT_REMOTE_TRACE_FIELD__SOURCE_MAC,sourceMac.toInt());
-		d.add(ZT_REMOTE_TRACE_FIELD__DEST_MAC,destMac.toInt());
-		d.add(ZT_REMOTE_TRACE_FIELD__ETHERTYPE,(uint64_t)etherType);
-		d.add(ZT_REMOTE_TRACE_FIELD__VLAN_ID,(uint64_t)vlanId);
-		d.add(ZT_REMOTE_TRACE_FIELD__FRAME_LENGTH,(uint64_t)frameLen);
+		d.add(ZT_REMOTE_TRACE_FIELD__EVENT, ZT_REMOTE_TRACE_EVENT__OUTGOING_NETWORK_FRAME_DROPPED_S);
+		d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID, network->id());
+		d.add(ZT_REMOTE_TRACE_FIELD__SOURCE_MAC, sourceMac.toInt());
+		d.add(ZT_REMOTE_TRACE_FIELD__DEST_MAC, destMac.toInt());
+		d.add(ZT_REMOTE_TRACE_FIELD__ETHERTYPE, (uint64_t)etherType);
+		d.add(ZT_REMOTE_TRACE_FIELD__VLAN_ID, (uint64_t)vlanId);
+		d.add(ZT_REMOTE_TRACE_FIELD__FRAME_LENGTH, (uint64_t)frameLen);
 		if (reason) {
-			d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason);
+			d.add(ZT_REMOTE_TRACE_FIELD__REASON, reason);
 		}
 
-		if ((_globalTarget)&&((int)_globalLevel >= (int)Trace::LEVEL_VERBOSE)) {
-			_send(tPtr,d,_globalTarget);
+		if ((_globalTarget) && ((int)_globalLevel >= (int)Trace::LEVEL_VERBOSE)) {
+			_send(tPtr, d, _globalTarget);
 		}
-		if ((byn.first)&&((int)byn.second >= (int)Trace::LEVEL_VERBOSE)) {
-			_send(tPtr,d,byn.first);
+		if ((byn.first) && ((int)byn.second >= (int)Trace::LEVEL_VERBOSE)) {
+			_send(tPtr, d, byn.first);
 		}
 	}
 }
 
-void Trace::incomingNetworkAccessDenied(void *const tPtr,const SharedPtr<Network> &network,const SharedPtr<Path> &path,const uint64_t packetId,const unsigned int packetLength,const Address &source,const Packet::Verb verb,bool credentialsRequested)
+void Trace::incomingNetworkAccessDenied(
+	void* const tPtr,
+	const SharedPtr<Network>& network,
+	const SharedPtr<Path>& path,
+	const uint64_t packetId,
+	const unsigned int packetLength,
+	const Address& source,
+	const Packet::Verb verb,
+	bool credentialsRequested)
 {
 	char tmp[128];
-	if (!network) {
-		return; // sanity check
+	if (! network) {
+		return;	  // sanity check
+	}
+
+	ZT_LOCAL_TRACE(
+		tPtr,
+		RR,
+		"%.16llx DENIED packet from %.10llx(%s) verb %d size %u%s",
+		network->id(),
+		source.toInt(),
+		(path) ? (path->address().toString(tmp)) : "???",
+		(int)verb,
+		packetLength,
+		credentialsRequested ? " (credentials requested)" : " (credentials not requested)");
+
+	std::pair<Address, Trace::Level> byn;
+	{
+		Mutex::Lock l(_byNet_m);
+		_byNet.get(network->id(), byn);
 	}
 
-	ZT_LOCAL_TRACE(tPtr,RR,"%.16llx DENIED packet from %.10llx(%s) verb %d size %u%s",network->id(),source.toInt(),(path) ? (path->address().toString(tmp)) : "???",(int)verb,packetLength,credentialsRequested ? " (credentials requested)" : " (credentials not requested)");
-
-	std::pair<Address,Trace::Level> byn;
-	{ Mutex::Lock l(_byNet_m); _byNet.get(network->id(),byn); }
-
-	if ( ((_globalTarget)&&((int)_globalLevel >= (int)Trace::LEVEL_VERBOSE)) || ((byn.first)&&((int)byn.second >= (int)Trace::LEVEL_VERBOSE)) ) {
+	if (((_globalTarget) && ((int)_globalLevel >= (int)Trace::LEVEL_VERBOSE)) || ((byn.first) && ((int)byn.second >= (int)Trace::LEVEL_VERBOSE))) {
 		Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
-		d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_ACCESS_DENIED_S);
-		d.add(ZT_REMOTE_TRACE_FIELD__PACKET_ID,packetId);
-		d.add(ZT_REMOTE_TRACE_FIELD__PACKET_VERB,(uint64_t)verb);
-		d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR,source);
+		d.add(ZT_REMOTE_TRACE_FIELD__EVENT, ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_ACCESS_DENIED_S);
+		d.add(ZT_REMOTE_TRACE_FIELD__PACKET_ID, packetId);
+		d.add(ZT_REMOTE_TRACE_FIELD__PACKET_VERB, (uint64_t)verb);
+		d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR, source);
 		if (path) {
-			d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,path->address().toString(tmp));
-			d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,path->localSocket());
+			d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR, path->address().toString(tmp));
+			d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET, path->localSocket());
 		}
-		d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,network->id());
+		d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID, network->id());
 
-		if ((_globalTarget)&&((int)_globalLevel >= (int)Trace::LEVEL_VERBOSE)) {
-			_send(tPtr,d,_globalTarget);
+		if ((_globalTarget) && ((int)_globalLevel >= (int)Trace::LEVEL_VERBOSE)) {
+			_send(tPtr, d, _globalTarget);
 		}
-		if ((byn.first)&&((int)byn.second >= (int)Trace::LEVEL_VERBOSE)) {
-			_send(tPtr,d,byn.first);
+		if ((byn.first) && ((int)byn.second >= (int)Trace::LEVEL_VERBOSE)) {
+			_send(tPtr, d, byn.first);
 		}
 	}
 }
 
-void Trace::incomingNetworkFrameDropped(void *const tPtr,const SharedPtr<Network> &network,const SharedPtr<Path> &path,const uint64_t packetId,const unsigned int packetLength,const Address &source,const Packet::Verb verb,const MAC &sourceMac,const MAC &destMac,const char *reason)
+void Trace::incomingNetworkFrameDropped(
+	void* const tPtr,
+	const SharedPtr<Network>& network,
+	const SharedPtr<Path>& path,
+	const uint64_t packetId,
+	const unsigned int packetLength,
+	const Address& source,
+	const Packet::Verb verb,
+	const MAC& sourceMac,
+	const MAC& destMac,
+	const char* reason)
 {
 	char tmp[128];
-	if (!network) {
-		return; // sanity check
+	if (! network) {
+		return;	  // sanity check
 	}
 
-	ZT_LOCAL_TRACE(tPtr,RR,"%.16llx DROPPED frame from %.10llx(%s) verb %d size %u",network->id(),source.toInt(),(path) ? (path->address().toString(tmp)) : "???",(int)verb,packetLength);
+	ZT_LOCAL_TRACE(tPtr, RR, "%.16llx DROPPED frame from %.10llx(%s) verb %d size %u", network->id(), source.toInt(), (path) ? (path->address().toString(tmp)) : "???", (int)verb, packetLength);
 
-	std::pair<Address,Trace::Level> byn;
-	{ Mutex::Lock l(_byNet_m); _byNet.get(network->id(),byn); }
+	std::pair<Address, Trace::Level> byn;
+	{
+		Mutex::Lock l(_byNet_m);
+		_byNet.get(network->id(), byn);
+	}
 
-	if ( ((_globalTarget)&&((int)_globalLevel >= (int)Trace::LEVEL_VERBOSE)) || ((byn.first)&&((int)byn.second >= (int)Trace::LEVEL_VERBOSE)) ) {
+	if (((_globalTarget) && ((int)_globalLevel >= (int)Trace::LEVEL_VERBOSE)) || ((byn.first) && ((int)byn.second >= (int)Trace::LEVEL_VERBOSE))) {
 		Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
-		d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_FRAME_DROPPED_S);
-		d.add(ZT_REMOTE_TRACE_FIELD__PACKET_ID,packetId);
-		d.add(ZT_REMOTE_TRACE_FIELD__PACKET_VERB,(uint64_t)verb);
-		d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR,source);
+		d.add(ZT_REMOTE_TRACE_FIELD__EVENT, ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_FRAME_DROPPED_S);
+		d.add(ZT_REMOTE_TRACE_FIELD__PACKET_ID, packetId);
+		d.add(ZT_REMOTE_TRACE_FIELD__PACKET_VERB, (uint64_t)verb);
+		d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR, source);
 		if (path) {
-			d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,path->address().toString(tmp));
-			d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,path->localSocket());
+			d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR, path->address().toString(tmp));
+			d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET, path->localSocket());
 		}
-		d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,network->id());
-		d.add(ZT_REMOTE_TRACE_FIELD__SOURCE_MAC,sourceMac.toInt());
-		d.add(ZT_REMOTE_TRACE_FIELD__DEST_MAC,destMac.toInt());
+		d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID, network->id());
+		d.add(ZT_REMOTE_TRACE_FIELD__SOURCE_MAC, sourceMac.toInt());
+		d.add(ZT_REMOTE_TRACE_FIELD__DEST_MAC, destMac.toInt());
 		if (reason) {
-			d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason);
+			d.add(ZT_REMOTE_TRACE_FIELD__REASON, reason);
 		}
 
-		if ((_globalTarget)&&((int)_globalLevel >= (int)Trace::LEVEL_VERBOSE)) {
-			_send(tPtr,d,_globalTarget);
+		if ((_globalTarget) && ((int)_globalLevel >= (int)Trace::LEVEL_VERBOSE)) {
+			_send(tPtr, d, _globalTarget);
 		}
-		if ((byn.first)&&((int)byn.second >= (int)Trace::LEVEL_VERBOSE)) {
-			_send(tPtr,d,byn.first);
+		if ((byn.first) && ((int)byn.second >= (int)Trace::LEVEL_VERBOSE)) {
+			_send(tPtr, d, byn.first);
 		}
 	}
 }
 
-void Trace::incomingPacketMessageAuthenticationFailure(void *const tPtr,const SharedPtr<Path> &path,const uint64_t packetId,const Address &source,const unsigned int hops,const char *reason)
+void Trace::incomingPacketMessageAuthenticationFailure(void* const tPtr, const SharedPtr<Path>& path, const uint64_t packetId, const Address& source, const unsigned int hops, const char* reason)
 {
 	char tmp[128];
 
-	ZT_LOCAL_TRACE(tPtr,RR,"MAC failed for packet %.16llx from %.10llx(%s)",packetId,source.toInt(),(path) ? path->address().toString(tmp) : "???");
+	ZT_LOCAL_TRACE(tPtr, RR, "MAC failed for packet %.16llx from %.10llx(%s)", packetId, source.toInt(), (path) ? path->address().toString(tmp) : "???");
 
-	if ((_globalTarget)&&((int)_globalLevel >= Trace::LEVEL_DEBUG)) {
+	if ((_globalTarget) && ((int)_globalLevel >= Trace::LEVEL_DEBUG)) {
 		Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
-		d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__PACKET_MAC_FAILURE_S);
-		d.add(ZT_REMOTE_TRACE_FIELD__PACKET_ID,packetId);
-		d.add(ZT_REMOTE_TRACE_FIELD__PACKET_HOPS,(uint64_t)hops);
-		d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR,source);
+		d.add(ZT_REMOTE_TRACE_FIELD__EVENT, ZT_REMOTE_TRACE_EVENT__PACKET_MAC_FAILURE_S);
+		d.add(ZT_REMOTE_TRACE_FIELD__PACKET_ID, packetId);
+		d.add(ZT_REMOTE_TRACE_FIELD__PACKET_HOPS, (uint64_t)hops);
+		d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR, source);
 		if (path) {
-			d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,path->address().toString(tmp));
-			d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,path->localSocket());
+			d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR, path->address().toString(tmp));
+			d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET, path->localSocket());
 		}
 		if (reason) {
-			d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason);
+			d.add(ZT_REMOTE_TRACE_FIELD__REASON, reason);
 		}
 
-		_send(tPtr,d,_globalTarget);
+		_send(tPtr, d, _globalTarget);
 	}
 }
 
-void Trace::incomingPacketInvalid(void *const tPtr,const SharedPtr<Path> &path,const uint64_t packetId,const Address &source,const unsigned int hops,const Packet::Verb verb,const char *reason)
+void Trace::incomingPacketInvalid(void* const tPtr, const SharedPtr<Path>& path, const uint64_t packetId, const Address& source, const unsigned int hops, const Packet::Verb verb, const char* reason)
 {
 	char tmp[128];
 
-	ZT_LOCAL_TRACE(tPtr,RR,"INVALID packet %.16llx from %.10llx(%s) (%s)",packetId,source.toInt(),(path) ? path->address().toString(tmp) : "???",(reason) ? reason : "unknown reason");
+	ZT_LOCAL_TRACE(tPtr, RR, "INVALID packet %.16llx from %.10llx(%s) (%s)", packetId, source.toInt(), (path) ? path->address().toString(tmp) : "???", (reason) ? reason : "unknown reason");
 
-	if ((_globalTarget)&&((int)_globalLevel >= Trace::LEVEL_DEBUG)) {
+	if ((_globalTarget) && ((int)_globalLevel >= Trace::LEVEL_DEBUG)) {
 		Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
-		d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__PACKET_INVALID_S);
-		d.add(ZT_REMOTE_TRACE_FIELD__PACKET_ID,packetId);
-		d.add(ZT_REMOTE_TRACE_FIELD__PACKET_VERB,(uint64_t)verb);
-		d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR,source);
+		d.add(ZT_REMOTE_TRACE_FIELD__EVENT, ZT_REMOTE_TRACE_EVENT__PACKET_INVALID_S);
+		d.add(ZT_REMOTE_TRACE_FIELD__PACKET_ID, packetId);
+		d.add(ZT_REMOTE_TRACE_FIELD__PACKET_VERB, (uint64_t)verb);
+		d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR, source);
 		if (path) {
-			d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,path->address().toString(tmp));
-			d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,path->localSocket());
+			d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR, path->address().toString(tmp));
+			d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET, path->localSocket());
 		}
-		d.add(ZT_REMOTE_TRACE_FIELD__PACKET_HOPS,(uint64_t)hops);
+		d.add(ZT_REMOTE_TRACE_FIELD__PACKET_HOPS, (uint64_t)hops);
 		if (reason) {
-			d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason);
+			d.add(ZT_REMOTE_TRACE_FIELD__REASON, reason);
 		}
 
-		_send(tPtr,d,_globalTarget);
+		_send(tPtr, d, _globalTarget);
 	}
 }
 
-void Trace::incomingPacketDroppedHELLO(void *const tPtr,const SharedPtr<Path> &path,const uint64_t packetId,const Address &source,const char *reason)
+void Trace::incomingPacketDroppedHELLO(void* const tPtr, const SharedPtr<Path>& path, const uint64_t packetId, const Address& source, const char* reason)
 {
 	char tmp[128];
 
-	ZT_LOCAL_TRACE(tPtr,RR,"DROPPED HELLO from %.10llx(%s) (%s)",source.toInt(),(path) ? path->address().toString(tmp) : "???",(reason) ? reason : "???");
+	ZT_LOCAL_TRACE(tPtr, RR, "DROPPED HELLO from %.10llx(%s) (%s)", source.toInt(), (path) ? path->address().toString(tmp) : "???", (reason) ? reason : "???");
 
-	if ((_globalTarget)&&((int)_globalLevel >= Trace::LEVEL_DEBUG)) {
+	if ((_globalTarget) && ((int)_globalLevel >= Trace::LEVEL_DEBUG)) {
 		Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
-		d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__PACKET_INVALID_S);
-		d.add(ZT_REMOTE_TRACE_FIELD__PACKET_ID,packetId);
-		d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR,source);
+		d.add(ZT_REMOTE_TRACE_FIELD__EVENT, ZT_REMOTE_TRACE_EVENT__PACKET_INVALID_S);
+		d.add(ZT_REMOTE_TRACE_FIELD__PACKET_ID, packetId);
+		d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR, source);
 		if (path) {
-			d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,path->address().toString(tmp));
-			d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,path->localSocket());
+			d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR, path->address().toString(tmp));
+			d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET, path->localSocket());
 		}
 		if (reason) {
-			d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason);
+			d.add(ZT_REMOTE_TRACE_FIELD__REASON, reason);
 		}
 
-		_send(tPtr,d,_globalTarget);
+		_send(tPtr, d, _globalTarget);
 	}
 }
 
-void Trace::networkConfigRequestSent(void *const tPtr,const Network &network,const Address &controller)
+void Trace::networkConfigRequestSent(void* const tPtr, const Network& network, const Address& controller)
 {
-	ZT_LOCAL_TRACE(tPtr,RR,"requesting configuration for network %.16llx",network.id());
-	if ((_globalTarget)&&((int)_globalLevel >= Trace::LEVEL_DEBUG)) {
+	ZT_LOCAL_TRACE(tPtr, RR, "requesting configuration for network %.16llx", network.id());
+	if ((_globalTarget) && ((int)_globalLevel >= Trace::LEVEL_DEBUG)) {
 		Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
-		d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__NETWORK_CONFIG_REQUEST_SENT_S);
-		d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,network.id());
-		d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_CONTROLLER_ID,controller);
-		_send(tPtr,d,_globalTarget);
+		d.add(ZT_REMOTE_TRACE_FIELD__EVENT, ZT_REMOTE_TRACE_EVENT__NETWORK_CONFIG_REQUEST_SENT_S);
+		d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID, network.id());
+		d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_CONTROLLER_ID, controller);
+		_send(tPtr, d, _globalTarget);
 	}
 }
 
 void Trace::networkFilter(
-	void *const tPtr,
-	const Network &network,
-	const RuleResultLog &primaryRuleSetLog,
-	const RuleResultLog *const matchingCapabilityRuleSetLog,
-	const Capability *const matchingCapability,
-	const Address &ztSource,
-	const Address &ztDest,
-	const MAC &macSource,
-	const MAC &macDest,
-	const uint8_t *const frameData,
+	void* const tPtr,
+	const Network& network,
+	const RuleResultLog& primaryRuleSetLog,
+	const RuleResultLog* const matchingCapabilityRuleSetLog,
+	const Capability* const matchingCapability,
+	const Address& ztSource,
+	const Address& ztDest,
+	const MAC& macSource,
+	const MAC& macDest,
+	const uint8_t* const frameData,
 	const unsigned int frameLen,
 	const unsigned int etherType,
 	const unsigned int vlanId,
@@ -386,184 +423,187 @@ void Trace::networkFilter(
 	const bool inbound,
 	const int accept)
 {
-	std::pair<Address,Trace::Level> byn;
-	{ Mutex::Lock l(_byNet_m); _byNet.get(network.id(),byn); }
+	std::pair<Address, Trace::Level> byn;
+	{
+		Mutex::Lock l(_byNet_m);
+		_byNet.get(network.id(), byn);
+	}
 
-	if ( ((_globalTarget)&&((int)_globalLevel >= (int)Trace::LEVEL_RULES)) || ((byn.first)&&((int)byn.second >= (int)Trace::LEVEL_RULES)) ) {
+	if (((_globalTarget) && ((int)_globalLevel >= (int)Trace::LEVEL_RULES)) || ((byn.first) && ((int)byn.second >= (int)Trace::LEVEL_RULES))) {
 		Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
-		d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__NETWORK_FILTER_TRACE_S);
-		d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,network.id());
-		d.add(ZT_REMOTE_TRACE_FIELD__SOURCE_ZTADDR,ztSource);
-		d.add(ZT_REMOTE_TRACE_FIELD__DEST_ZTADDR,ztDest);
-		d.add(ZT_REMOTE_TRACE_FIELD__SOURCE_MAC,macSource.toInt());
-		d.add(ZT_REMOTE_TRACE_FIELD__DEST_MAC,macDest.toInt());
-		d.add(ZT_REMOTE_TRACE_FIELD__ETHERTYPE,(uint64_t)etherType);
-		d.add(ZT_REMOTE_TRACE_FIELD__VLAN_ID,(uint64_t)vlanId);
-		d.add(ZT_REMOTE_TRACE_FIELD__FILTER_FLAG_NOTEE,noTee ? "1" : "0");
-		d.add(ZT_REMOTE_TRACE_FIELD__FILTER_FLAG_INBOUND,inbound ? "1" : "0");
-		d.add(ZT_REMOTE_TRACE_FIELD__FILTER_RESULT,(int64_t)accept);
-		d.add(ZT_REMOTE_TRACE_FIELD__FILTER_BASE_RULE_LOG,(const char *)primaryRuleSetLog.data(),(int)primaryRuleSetLog.sizeBytes());
+		d.add(ZT_REMOTE_TRACE_FIELD__EVENT, ZT_REMOTE_TRACE_EVENT__NETWORK_FILTER_TRACE_S);
+		d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID, network.id());
+		d.add(ZT_REMOTE_TRACE_FIELD__SOURCE_ZTADDR, ztSource);
+		d.add(ZT_REMOTE_TRACE_FIELD__DEST_ZTADDR, ztDest);
+		d.add(ZT_REMOTE_TRACE_FIELD__SOURCE_MAC, macSource.toInt());
+		d.add(ZT_REMOTE_TRACE_FIELD__DEST_MAC, macDest.toInt());
+		d.add(ZT_REMOTE_TRACE_FIELD__ETHERTYPE, (uint64_t)etherType);
+		d.add(ZT_REMOTE_TRACE_FIELD__VLAN_ID, (uint64_t)vlanId);
+		d.add(ZT_REMOTE_TRACE_FIELD__FILTER_FLAG_NOTEE, noTee ? "1" : "0");
+		d.add(ZT_REMOTE_TRACE_FIELD__FILTER_FLAG_INBOUND, inbound ? "1" : "0");
+		d.add(ZT_REMOTE_TRACE_FIELD__FILTER_RESULT, (int64_t)accept);
+		d.add(ZT_REMOTE_TRACE_FIELD__FILTER_BASE_RULE_LOG, (const char*)primaryRuleSetLog.data(), (int)primaryRuleSetLog.sizeBytes());
 		if (matchingCapabilityRuleSetLog) {
-			d.add(ZT_REMOTE_TRACE_FIELD__FILTER_CAP_RULE_LOG,(const char *)matchingCapabilityRuleSetLog->data(),(int)matchingCapabilityRuleSetLog->sizeBytes());
+			d.add(ZT_REMOTE_TRACE_FIELD__FILTER_CAP_RULE_LOG, (const char*)matchingCapabilityRuleSetLog->data(), (int)matchingCapabilityRuleSetLog->sizeBytes());
 		}
 		if (matchingCapability) {
-			d.add(ZT_REMOTE_TRACE_FIELD__FILTER_CAP_ID,(uint64_t)matchingCapability->id());
+			d.add(ZT_REMOTE_TRACE_FIELD__FILTER_CAP_ID, (uint64_t)matchingCapability->id());
 		}
-		d.add(ZT_REMOTE_TRACE_FIELD__FRAME_LENGTH,(uint64_t)frameLen);
+		d.add(ZT_REMOTE_TRACE_FIELD__FRAME_LENGTH, (uint64_t)frameLen);
 		if (frameLen > 0) {
-			d.add(ZT_REMOTE_TRACE_FIELD__FRAME_DATA,(const char *)frameData,(frameLen > 256) ? (int)256 : (int)frameLen);
+			d.add(ZT_REMOTE_TRACE_FIELD__FRAME_DATA, (const char*)frameData, (frameLen > 256) ? (int)256 : (int)frameLen);
 		}
 
-		if ((_globalTarget)&&((int)_globalLevel >= (int)Trace::LEVEL_RULES)) {
-			_send(tPtr,d,_globalTarget);
+		if ((_globalTarget) && ((int)_globalLevel >= (int)Trace::LEVEL_RULES)) {
+			_send(tPtr, d, _globalTarget);
 		}
-		if ((byn.first)&&((int)byn.second >= (int)Trace::LEVEL_RULES)) {
-			_send(tPtr,d,byn.first);
+		if ((byn.first) && ((int)byn.second >= (int)Trace::LEVEL_RULES)) {
+			_send(tPtr, d, byn.first);
 		}
 	}
 }
 
-void Trace::credentialRejected(void *const tPtr,const CertificateOfMembership &c,const char *reason)
+void Trace::credentialRejected(void* const tPtr, const CertificateOfMembership& c, const char* reason)
 {
-	std::pair<Address,Trace::Level> byn;
+	std::pair<Address, Trace::Level> byn;
 	if (c.networkId()) {
 		Mutex::Lock l(_byNet_m);
-		_byNet.get(c.networkId(),byn);
+		_byNet.get(c.networkId(), byn);
 	}
 
-	if ((_globalTarget)||(byn.first)) {
+	if ((_globalTarget) || (byn.first)) {
 		Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
-		d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED_S);
-		d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,c.networkId());
-		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType());
-		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id());
-		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp());
-		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo());
+		d.add(ZT_REMOTE_TRACE_FIELD__EVENT, ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED_S);
+		d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID, c.networkId());
+		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE, (uint64_t)c.credentialType());
+		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID, (uint64_t)c.id());
+		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP, c.timestamp());
+		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO, c.issuedTo());
 		if (reason) {
-			d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason);
+			d.add(ZT_REMOTE_TRACE_FIELD__REASON, reason);
 		}
 
 		if (_globalTarget) {
-			_send(tPtr,d,_globalTarget);
+			_send(tPtr, d, _globalTarget);
 		}
 		if (byn.first) {
-			_send(tPtr,d,byn.first);
+			_send(tPtr, d, byn.first);
 		}
 	}
 }
 
-void Trace::credentialRejected(void *const tPtr,const CertificateOfOwnership &c,const char *reason)
+void Trace::credentialRejected(void* const tPtr, const CertificateOfOwnership& c, const char* reason)
 {
-	std::pair<Address,Trace::Level> byn;
+	std::pair<Address, Trace::Level> byn;
 	if (c.networkId()) {
 		Mutex::Lock l(_byNet_m);
-		_byNet.get(c.networkId(),byn);
+		_byNet.get(c.networkId(), byn);
 	}
 
-	if ((_globalTarget)||(byn.first)) {
+	if ((_globalTarget) || (byn.first)) {
 		Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
-		d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED_S);
-		d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,c.networkId());
-		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType());
-		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id());
-		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp());
-		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo());
+		d.add(ZT_REMOTE_TRACE_FIELD__EVENT, ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED_S);
+		d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID, c.networkId());
+		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE, (uint64_t)c.credentialType());
+		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID, (uint64_t)c.id());
+		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP, c.timestamp());
+		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO, c.issuedTo());
 		if (reason) {
-			d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason);
+			d.add(ZT_REMOTE_TRACE_FIELD__REASON, reason);
 		}
 
 		if (_globalTarget) {
-			_send(tPtr,d,_globalTarget);
+			_send(tPtr, d, _globalTarget);
 		}
 		if (byn.first) {
-			_send(tPtr,d,byn.first);
+			_send(tPtr, d, byn.first);
 		}
 	}
 }
 
-void Trace::credentialRejected(void *const tPtr,const Capability &c,const char *reason)
+void Trace::credentialRejected(void* const tPtr, const Capability& c, const char* reason)
 {
-	std::pair<Address,Trace::Level> byn;
+	std::pair<Address, Trace::Level> byn;
 	if (c.networkId()) {
 		Mutex::Lock l(_byNet_m);
-		_byNet.get(c.networkId(),byn);
+		_byNet.get(c.networkId(), byn);
 	}
 
-	if ((_globalTarget)||(byn.first)) {
+	if ((_globalTarget) || (byn.first)) {
 		Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
-		d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED_S);
-		d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,c.networkId());
-		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType());
-		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id());
-		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp());
-		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo());
+		d.add(ZT_REMOTE_TRACE_FIELD__EVENT, ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED_S);
+		d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID, c.networkId());
+		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE, (uint64_t)c.credentialType());
+		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID, (uint64_t)c.id());
+		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP, c.timestamp());
+		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO, c.issuedTo());
 		if (reason) {
-			d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason);
+			d.add(ZT_REMOTE_TRACE_FIELD__REASON, reason);
 		}
 
 		if (_globalTarget) {
-			_send(tPtr,d,_globalTarget);
+			_send(tPtr, d, _globalTarget);
 		}
 		if (byn.first) {
-			_send(tPtr,d,byn.first);
+			_send(tPtr, d, byn.first);
 		}
 	}
 }
 
-void Trace::credentialRejected(void *const tPtr,const Tag &c,const char *reason)
+void Trace::credentialRejected(void* const tPtr, const Tag& c, const char* reason)
 {
-	std::pair<Address,Trace::Level> byn;
+	std::pair<Address, Trace::Level> byn;
 	if (c.networkId()) {
 		Mutex::Lock l(_byNet_m);
-		_byNet.get(c.networkId(),byn);
+		_byNet.get(c.networkId(), byn);
 	}
 
-	if ((_globalTarget)||(byn.first)) {
+	if ((_globalTarget) || (byn.first)) {
 		Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
-		d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED_S);
-		d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,c.networkId());
-		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType());
-		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id());
-		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp());
-		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo());
-		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_INFO,(uint64_t)c.value());
+		d.add(ZT_REMOTE_TRACE_FIELD__EVENT, ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED_S);
+		d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID, c.networkId());
+		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE, (uint64_t)c.credentialType());
+		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID, (uint64_t)c.id());
+		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP, c.timestamp());
+		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO, c.issuedTo());
+		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_INFO, (uint64_t)c.value());
 		if (reason) {
-			d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason);
+			d.add(ZT_REMOTE_TRACE_FIELD__REASON, reason);
 		}
 
 		if (_globalTarget) {
-			_send(tPtr,d,_globalTarget);
+			_send(tPtr, d, _globalTarget);
 		}
 		if (byn.first) {
-			_send(tPtr,d,byn.first);
+			_send(tPtr, d, byn.first);
 		}
 	}
 }
 
-void Trace::credentialRejected(void *const tPtr,const Revocation &c,const char *reason)
+void Trace::credentialRejected(void* const tPtr, const Revocation& c, const char* reason)
 {
-	std::pair<Address,Trace::Level> byn;
+	std::pair<Address, Trace::Level> byn;
 	if (c.networkId()) {
 		Mutex::Lock l(_byNet_m);
-		_byNet.get(c.networkId(),byn);
+		_byNet.get(c.networkId(), byn);
 	}
 
-	if ((_globalTarget)||(byn.first)) {
+	if ((_globalTarget) || (byn.first)) {
 		Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
-		d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED_S);
-		d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,c.networkId());
-		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType());
-		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id());
-		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_REVOCATION_TARGET,c.target());
+		d.add(ZT_REMOTE_TRACE_FIELD__EVENT, ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED_S);
+		d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID, c.networkId());
+		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE, (uint64_t)c.credentialType());
+		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID, (uint64_t)c.id());
+		d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_REVOCATION_TARGET, c.target());
 		if (reason) {
 			d.add(ZT_REMOTE_TRACE_FIELD__REASON, reason);
 		}
 
 		if (_globalTarget) {
-			_send(tPtr,d,_globalTarget);
+			_send(tPtr, d, _globalTarget);
 		}
 		if (byn.first) {
-			_send(tPtr,d,byn.first);
+			_send(tPtr, d, byn.first);
 		}
 	}
 }
@@ -572,14 +612,14 @@ void Trace::updateMemoizedSettings()
 {
 	_globalTarget = RR->node->remoteTraceTarget();
 	_globalLevel = RR->node->remoteTraceLevel();
-	const std::vector< SharedPtr<Network> > nws(RR->node->allNetworks());
+	const std::vector<SharedPtr<Network> > nws(RR->node->allNetworks());
 	{
 		Mutex::Lock l(_byNet_m);
 		_byNet.clear();
-		for(std::vector< SharedPtr<Network> >::const_iterator n(nws.begin());n!=nws.end();++n) {
+		for (std::vector<SharedPtr<Network> >::const_iterator n(nws.begin()); n != nws.end(); ++n) {
 			const Address dest((*n)->config().remoteTraceTarget);
 			if (dest) {
-				std::pair<Address,Trace::Level> &m = _byNet[(*n)->id()];
+				std::pair<Address, Trace::Level>& m = _byNet[(*n)->id()];
 				m.first = dest;
 				m.second = (*n)->config().remoteTraceLevel;
 			}
@@ -587,25 +627,25 @@ void Trace::updateMemoizedSettings()
 	}
 }
 
-void Trace::_send(void *const tPtr,const Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> &d,const Address &dest)
+void Trace::_send(void* const tPtr, const Dictionary<ZT_MAX_REMOTE_TRACE_SIZE>& d, const Address& dest)
 {
-	Packet outp(dest,RR->identity.address(),Packet::VERB_REMOTE_TRACE);
+	Packet outp(dest, RR->identity.address(), Packet::VERB_REMOTE_TRACE);
 	outp.appendCString(d.data());
 	outp.compress();
-	RR->sw->send(tPtr,outp,true);
+	RR->sw->send(tPtr, outp, true);
 }
 
-void Trace::_spamToAllNetworks(void *const tPtr,const Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> &d,const Level level)
+void Trace::_spamToAllNetworks(void* const tPtr, const Dictionary<ZT_MAX_REMOTE_TRACE_SIZE>& d, const Level level)
 {
 	Mutex::Lock l(_byNet_m);
-	Hashtable< uint64_t,std::pair< Address,Trace::Level > >::Iterator i(_byNet);
-	uint64_t *k = (uint64_t *)0;
-	std::pair<Address,Trace::Level> *v = (std::pair<Address,Trace::Level> *)0;
-	while (i.next(k,v)) {
-		if ((v)&&(v->first)&&((int)v->second >= (int)level)) {
-			_send(tPtr,d,v->first);
+	Hashtable<uint64_t, std::pair<Address, Trace::Level> >::Iterator i(_byNet);
+	uint64_t* k = (uint64_t*)0;
+	std::pair<Address, Trace::Level>* v = (std::pair<Address, Trace::Level>*)0;
+	while (i.next(k, v)) {
+		if ((v) && (v->first) && ((int)v->second >= (int)level)) {
+			_send(tPtr, d, v->first);
 		}
 	}
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier

+ 88 - 74
node/Trace.hpp

@@ -14,21 +14,20 @@
 #ifndef ZT_TRACE_HPP
 #define ZT_TRACE_HPP
 
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <stdlib.h>
-
 #include "../include/ZeroTierOne.h"
-
 #include "Constants.hpp"
-#include "SharedPtr.hpp"
-#include "Packet.hpp"
 #include "Credential.hpp"
-#include "InetAddress.hpp"
 #include "Dictionary.hpp"
-#include "Mutex.hpp"
 #include "Hashtable.hpp"
+#include "InetAddress.hpp"
+#include "Mutex.hpp"
+#include "Packet.hpp"
+#include "SharedPtr.hpp"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 
 namespace ZeroTier {
 
@@ -49,20 +48,12 @@ class Capability;
 /**
  * Remote tracing and trace logging handler
  */
-class Trace
-{
-public:
+class Trace {
+  public:
 	/**
 	 * Trace verbosity level
 	 */
-	enum Level
-	{
-		LEVEL_NORMAL = 0,
-		LEVEL_VERBOSE = 10,
-		LEVEL_RULES = 15,
-		LEVEL_DEBUG = 20,
-		LEVEL_INSANE = 30
-	};
+	enum Level { LEVEL_NORMAL = 0, LEVEL_VERBOSE = 10, LEVEL_RULES = 15, LEVEL_DEBUG = 20, LEVEL_INSANE = 30 };
 
 	/**
 	 * Filter rule evaluation result log
@@ -73,67 +64,90 @@ public:
 	 * As with four-bit rules an 00 value here means this was not
 	 * evaluated or was not relevant.
 	 */
-	class RuleResultLog
-	{
-	public:
-		RuleResultLog() {}
+	class RuleResultLog {
+	  public:
+		RuleResultLog()
+		{
+		}
 
-		inline void log(const unsigned int rn,const uint8_t thisRuleMatches,const uint8_t thisSetMatches)
+		inline void log(const unsigned int rn, const uint8_t thisRuleMatches, const uint8_t thisSetMatches)
 		{
-			_l[rn >> 1] |= ( ((thisRuleMatches + 1) << 2) | (thisSetMatches + 1) ) << ((rn & 1) << 2);
+			_l[rn >> 1] |= (((thisRuleMatches + 1) << 2) | (thisSetMatches + 1)) << ((rn & 1) << 2);
 		}
-		inline void logSkipped(const unsigned int rn,const uint8_t thisSetMatches)
+		inline void logSkipped(const unsigned int rn, const uint8_t thisSetMatches)
 		{
 			_l[rn >> 1] |= (thisSetMatches + 1) << ((rn & 1) << 2);
 		}
 
 		inline void clear()
 		{
-			memset(_l,0,sizeof(_l));
+			memset(_l, 0, sizeof(_l));
 		}
 
-		inline const uint8_t *data() const { return _l; }
-		inline unsigned int sizeBytes() const { return (ZT_MAX_NETWORK_RULES / 2); }
+		inline const uint8_t* data() const
+		{
+			return _l;
+		}
+		inline unsigned int sizeBytes() const
+		{
+			return (ZT_MAX_NETWORK_RULES / 2);
+		}
 
-	private:
+	  private:
 		uint8_t _l[ZT_MAX_NETWORK_RULES / 2];
 	};
 
-	Trace(const RuntimeEnvironment *renv) :
-		RR(renv),
-		_byNet(8)
+	Trace(const RuntimeEnvironment* renv) : RR(renv), _byNet(8)
 	{
 	}
 
-	void resettingPathsInScope(void *const tPtr,const Address &reporter,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,const InetAddress::IpScope scope);
-
-	void peerConfirmingUnknownPath(void *const tPtr,const uint64_t networkId,Peer &peer,const SharedPtr<Path> &path,const uint64_t packetId,const Packet::Verb verb);
-
-	void bondStateMessage(void *const tPtr,char *msg);
-
-	void peerLearnedNewPath(void *const tPtr,const uint64_t networkId,Peer &peer,const SharedPtr<Path> &newPath,const uint64_t packetId);
-	void peerRedirected(void *const tPtr,const uint64_t networkId,Peer &peer,const SharedPtr<Path> &newPath);
-
-	void incomingPacketMessageAuthenticationFailure(void *const tPtr,const SharedPtr<Path> &path,const uint64_t packetId,const Address &source,const unsigned int hops,const char *reason);
-	void incomingPacketInvalid(void *const tPtr,const SharedPtr<Path> &path,const uint64_t packetId,const Address &source,const unsigned int hops,const Packet::Verb verb,const char *reason);
-	void incomingPacketDroppedHELLO(void *const tPtr,const SharedPtr<Path> &path,const uint64_t packetId,const Address &source,const char *reason);
-
-	void outgoingNetworkFrameDropped(void *const tPtr,const SharedPtr<Network> &network,const MAC &sourceMac,const MAC &destMac,const unsigned int etherType,const unsigned int vlanId,const unsigned int frameLen,const char *reason);
-	void incomingNetworkAccessDenied(void *const tPtr,const SharedPtr<Network> &network,const SharedPtr<Path> &path,const uint64_t packetId,const unsigned int packetLength,const Address &source,const Packet::Verb verb,bool credentialsRequested);
-	void incomingNetworkFrameDropped(void *const tPtr,const SharedPtr<Network> &network,const SharedPtr<Path> &path,const uint64_t packetId,const unsigned int packetLength,const Address &source,const Packet::Verb verb,const MAC &sourceMac,const MAC &destMac,const char *reason);
-
-	void networkConfigRequestSent(void *const tPtr,const Network &network,const Address &controller);
+	void resettingPathsInScope(void* const tPtr, const Address& reporter, const InetAddress& reporterPhysicalAddress, const InetAddress& myPhysicalAddress, const InetAddress::IpScope scope);
+
+	void peerConfirmingUnknownPath(void* const tPtr, const uint64_t networkId, Peer& peer, const SharedPtr<Path>& path, const uint64_t packetId, const Packet::Verb verb);
+
+	void bondStateMessage(void* const tPtr, char* msg);
+
+	void peerLearnedNewPath(void* const tPtr, const uint64_t networkId, Peer& peer, const SharedPtr<Path>& newPath, const uint64_t packetId);
+	void peerRedirected(void* const tPtr, const uint64_t networkId, Peer& peer, const SharedPtr<Path>& newPath);
+
+	void incomingPacketMessageAuthenticationFailure(void* const tPtr, const SharedPtr<Path>& path, const uint64_t packetId, const Address& source, const unsigned int hops, const char* reason);
+	void incomingPacketInvalid(void* const tPtr, const SharedPtr<Path>& path, const uint64_t packetId, const Address& source, const unsigned int hops, const Packet::Verb verb, const char* reason);
+	void incomingPacketDroppedHELLO(void* const tPtr, const SharedPtr<Path>& path, const uint64_t packetId, const Address& source, const char* reason);
+
+	void outgoingNetworkFrameDropped(void* const tPtr, const SharedPtr<Network>& network, const MAC& sourceMac, const MAC& destMac, const unsigned int etherType, const unsigned int vlanId, const unsigned int frameLen, const char* reason);
+	void incomingNetworkAccessDenied(
+		void* const tPtr,
+		const SharedPtr<Network>& network,
+		const SharedPtr<Path>& path,
+		const uint64_t packetId,
+		const unsigned int packetLength,
+		const Address& source,
+		const Packet::Verb verb,
+		bool credentialsRequested);
+	void incomingNetworkFrameDropped(
+		void* const tPtr,
+		const SharedPtr<Network>& network,
+		const SharedPtr<Path>& path,
+		const uint64_t packetId,
+		const unsigned int packetLength,
+		const Address& source,
+		const Packet::Verb verb,
+		const MAC& sourceMac,
+		const MAC& destMac,
+		const char* reason);
+
+	void networkConfigRequestSent(void* const tPtr, const Network& network, const Address& controller);
 	void networkFilter(
-		void *const tPtr,
-		const Network &network,
-		const RuleResultLog &primaryRuleSetLog,
-		const RuleResultLog *const matchingCapabilityRuleSetLog,
-		const Capability *const matchingCapability,
-		const Address &ztSource,
-		const Address &ztDest,
-		const MAC &macSource,
-		const MAC &macDest,
-		const uint8_t *const frameData,
+		void* const tPtr,
+		const Network& network,
+		const RuleResultLog& primaryRuleSetLog,
+		const RuleResultLog* const matchingCapabilityRuleSetLog,
+		const Capability* const matchingCapability,
+		const Address& ztSource,
+		const Address& ztDest,
+		const MAC& macSource,
+		const MAC& macDest,
+		const uint8_t* const frameData,
 		const unsigned int frameLen,
 		const unsigned int etherType,
 		const unsigned int vlanId,
@@ -141,26 +155,26 @@ public:
 		const bool inbound,
 		const int accept);
 
-	void credentialRejected(void *const tPtr,const CertificateOfMembership &c,const char *reason);
-	void credentialRejected(void *const tPtr,const CertificateOfOwnership &c,const char *reason);
-	void credentialRejected(void *const tPtr,const Capability &c,const char *reason);
-	void credentialRejected(void *const tPtr,const Tag &c,const char *reason);
-	void credentialRejected(void *const tPtr,const Revocation &c,const char *reason);
+	void credentialRejected(void* const tPtr, const CertificateOfMembership& c, const char* reason);
+	void credentialRejected(void* const tPtr, const CertificateOfOwnership& c, const char* reason);
+	void credentialRejected(void* const tPtr, const Capability& c, const char* reason);
+	void credentialRejected(void* const tPtr, const Tag& c, const char* reason);
+	void credentialRejected(void* const tPtr, const Revocation& c, const char* reason);
 
 	void updateMemoizedSettings();
 
-private:
-	const RuntimeEnvironment *const RR;
+  private:
+	const RuntimeEnvironment* const RR;
 
-	void _send(void *const tPtr,const Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> &d,const Address &dest);
-	void _spamToAllNetworks(void *const tPtr,const Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> &d,const Level level);
+	void _send(void* const tPtr, const Dictionary<ZT_MAX_REMOTE_TRACE_SIZE>& d, const Address& dest);
+	void _spamToAllNetworks(void* const tPtr, const Dictionary<ZT_MAX_REMOTE_TRACE_SIZE>& d, const Level level);
 
 	Address _globalTarget;
 	Trace::Level _globalLevel;
-	Hashtable< uint64_t,std::pair< Address,Trace::Level > > _byNet;
+	Hashtable<uint64_t, std::pair<Address, Trace::Level> > _byNet;
 	Mutex _byNet_m;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 69 - 72
node/Utils.cpp

@@ -11,23 +11,23 @@
  */
 /****/
 
+#include "Constants.hpp"
+
+#include <stdarg.h>
 #include <stdio.h>
-#include <string.h>
 #include <stdlib.h>
-#include <stdarg.h>
-#include <time.h>
+#include <string.h>
 #include <sys/stat.h>
-
-#include "Constants.hpp"
+#include <time.h>
 
 #ifdef __UNIX_LIKE__
-#include <unistd.h>
+#include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/types.h>
 #include <sys/uio.h>
-#include <dirent.h>
+#include <unistd.h>
 #ifdef ZT_ARCH_ARM_HAS_NEON
 #ifdef __LINUX__
 #include <sys/auxv.h>
@@ -36,13 +36,13 @@
 #endif
 
 #ifdef __WINDOWS__
-#include <wincrypt.h>
 #include <intrin.h>
+#include <wincrypt.h>
 #endif
 
-#include "Utils.hpp"
 #include "Mutex.hpp"
 #include "Salsa20.hpp"
+#include "Utils.hpp"
 
 #ifdef __APPLE__
 #include <TargetConditionals.h>
@@ -55,8 +55,8 @@
 #ifdef ZT_ARCH_ARM_HAS_NEON
 
 #ifdef __LINUX__
-#include <sys/auxv.h>
 #include <asm/hwcap.h>
+#include <sys/auxv.h>
 #endif
 
 #if defined(__FreeBSD__)
@@ -87,36 +87,37 @@ static inline long getauxval(int caps)
 #define HWCAP_SHA2 0
 #endif
 
-#endif // ZT_ARCH_ARM_HAS_NEON
+#endif	 // ZT_ARCH_ARM_HAS_NEON
 
 namespace ZeroTier {
 
-const uint64_t Utils::ZERO256[4] = {0ULL,0ULL,0ULL,0ULL};
+const uint64_t Utils::ZERO256[4] = { 0ULL, 0ULL, 0ULL, 0ULL };
 
-const char Utils::HEXCHARS[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
+const char Utils::HEXCHARS[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
 
 #ifdef ZT_ARCH_ARM_HAS_NEON
 Utils::ARMCapabilities::ARMCapabilities() noexcept
 {
 #ifdef __APPLE__
 
-    this->aes = true;
-    this->crc32 = true;
-    this->pmull = true;
-    this->sha1 = true;
-    this->sha2 = true;
+	this->aes = true;
+	this->crc32 = true;
+	this->pmull = true;
+	this->sha1 = true;
+	this->sha2 = true;
 
 #else
 
 #ifdef HWCAP2_AES
-	if (sizeof(void *) == 4) {
+	if (sizeof(void*) == 4) {
 		const long hwcaps2 = getauxval(AT_HWCAP2);
 		this->aes = (hwcaps2 & HWCAP2_AES) != 0;
 		this->crc32 = (hwcaps2 & HWCAP2_CRC32) != 0;
 		this->pmull = (hwcaps2 & HWCAP2_PMULL) != 0;
 		this->sha1 = (hwcaps2 & HWCAP2_SHA1) != 0;
 		this->sha2 = (hwcaps2 & HWCAP2_SHA2) != 0;
-	} else {
+	}
+	else {
 #endif
 		const long hwcaps = getauxval(AT_HWCAP);
 		this->aes = (hwcaps & HWCAP_AES) != 0;
@@ -128,7 +129,7 @@ Utils::ARMCapabilities::ARMCapabilities() noexcept
 	}
 #endif
 
-#endif // __APPLE__
+#endif	 // __APPLE__
 }
 
 const Utils::ARMCapabilities Utils::ARMCAP;
@@ -142,17 +143,13 @@ Utils::CPUIDRegisters::CPUIDRegisters() noexcept
 
 #ifdef __WINDOWS__
 	int regs[4];
-	__cpuid(regs,1);
+	__cpuid(regs, 1);
 	eax = (uint32_t)regs[0];
 	ebx = (uint32_t)regs[1];
 	ecx = (uint32_t)regs[2];
 	edx = (uint32_t)regs[3];
 #else
-	__asm__ __volatile__ (
-	"cpuid"
-	: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
-	: "a"(1), "c"(0)
-	);
+	__asm__ __volatile__("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(1), "c"(0));
 #endif
 
 	rdrand = ((ecx & (1U << 30U)) != 0);
@@ -160,17 +157,13 @@ Utils::CPUIDRegisters::CPUIDRegisters() noexcept
 	avx = ((ecx & (1U << 25U)) != 0);
 
 #ifdef __WINDOWS__
-	__cpuid(regs,7);
+	__cpuid(regs, 7);
 	eax = (uint32_t)regs[0];
 	ebx = (uint32_t)regs[1];
 	ecx = (uint32_t)regs[2];
 	edx = (uint32_t)regs[3];
 #else
-	__asm__ __volatile__ (
-	"cpuid"
-	: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
-	: "a"(7), "c"(0)
-	);
+	__asm__ __volatile__("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(7), "c"(0));
 #endif
 
 	vaes = aes && avx && ((ecx & (1U << 9U)) != 0);
@@ -185,40 +178,43 @@ const Utils::CPUIDRegisters Utils::CPUID;
 #endif
 
 // Crazy hack to force memory to be securely zeroed in spite of the best efforts of optimizing compilers.
-static void _Utils_doBurn(volatile uint8_t *ptr,unsigned int len)
+static void _Utils_doBurn(volatile uint8_t* ptr, unsigned int len)
 {
-	volatile uint8_t *const end = ptr + len;
+	volatile uint8_t* const end = ptr + len;
 	while (ptr != end) {
 		*(ptr++) = (uint8_t)0;
 	}
 }
-static void (*volatile _Utils_doBurn_ptr)(volatile uint8_t *,unsigned int) = _Utils_doBurn;
-void Utils::burn(void *ptr,unsigned int len) { (_Utils_doBurn_ptr)((volatile uint8_t *)ptr,len); }
+static void (*volatile _Utils_doBurn_ptr)(volatile uint8_t*, unsigned int) = _Utils_doBurn;
+void Utils::burn(void* ptr, unsigned int len)
+{
+	(_Utils_doBurn_ptr)((volatile uint8_t*)ptr, len);
+}
 
-static unsigned long _Utils_itoa(unsigned long n,char *s)
+static unsigned long _Utils_itoa(unsigned long n, char* s)
 {
 	if (n == 0) {
 		return 0;
 	}
-	unsigned long pos = _Utils_itoa(n / 10,s);
-	if (pos >= 22) { // sanity check, should be impossible
+	unsigned long pos = _Utils_itoa(n / 10, s);
+	if (pos >= 22) {   // sanity check, should be impossible
 		pos = 22;
 	}
 	s[pos] = '0' + (char)(n % 10);
 	return pos + 1;
 }
-char *Utils::decimal(unsigned long n,char s[24])
+char* Utils::decimal(unsigned long n, char s[24])
 {
 	if (n == 0) {
 		s[0] = '0';
 		s[1] = (char)0;
 		return s;
 	}
-	s[_Utils_itoa(n,s)] = (char)0;
+	s[_Utils_itoa(n, s)] = (char)0;
 	return s;
 }
 
-void Utils::getSecureRandom(void *buf,unsigned int bytes)
+void Utils::getSecureRandom(void* buf, unsigned int bytes)
 {
 	static Mutex globalLock;
 	static Salsa20 s20;
@@ -235,75 +231,76 @@ void Utils::getSecureRandom(void *buf,unsigned int bytes)
 	 * a bit of extra entropy and further randomizing the result, and comes
 	 * at almost no cost and with no real downside if the random source is
 	 * good. */
-	if (!s20Initialized) {
+	if (! s20Initialized) {
 		s20Initialized = true;
 		uint64_t s20Key[4];
-		s20Key[0] = (uint64_t)time(0); // system clock
-		s20Key[1] = (uint64_t)buf; // address of buf
-		s20Key[2] = (uint64_t)s20Key; // address of s20Key[]
-		s20Key[3] = (uint64_t)&s20; // address of s20
-		s20.init(s20Key,s20Key);
+		s20Key[0] = (uint64_t)time(0);	 // system clock
+		s20Key[1] = (uint64_t)buf;		 // address of buf
+		s20Key[2] = (uint64_t)s20Key;	 // address of s20Key[]
+		s20Key[3] = (uint64_t)&s20;		 // address of s20
+		s20.init(s20Key, s20Key);
 	}
 
 #ifdef __WINDOWS__
 
 	static HCRYPTPROV cryptProvider = NULL;
 
-	for(unsigned int i=0;i<bytes;++i) {
+	for (unsigned int i = 0; i < bytes; ++i) {
 		if (randomPtr >= sizeof(randomBuf)) {
 			if (cryptProvider == NULL) {
-				if (!CryptAcquireContextA(&cryptProvider,NULL,NULL,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT|CRYPT_SILENT)) {
-					fprintf(stderr,"FATAL ERROR: Utils::getSecureRandom() unable to obtain WinCrypt context!\r\n");
+				if (! CryptAcquireContextA(&cryptProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
+					fprintf(stderr, "FATAL ERROR: Utils::getSecureRandom() unable to obtain WinCrypt context!\r\n");
 					exit(1);
 				}
 			}
-			if (!CryptGenRandom(cryptProvider,(DWORD)sizeof(randomBuf),(BYTE *)randomBuf)) {
-				fprintf(stderr,"FATAL ERROR: Utils::getSecureRandom() CryptGenRandom failed!\r\n");
+			if (! CryptGenRandom(cryptProvider, (DWORD)sizeof(randomBuf), (BYTE*)randomBuf)) {
+				fprintf(stderr, "FATAL ERROR: Utils::getSecureRandom() CryptGenRandom failed!\r\n");
 				exit(1);
 			}
 			randomPtr = 0;
-			s20.crypt12(randomBuf,randomBuf,sizeof(randomBuf));
-			s20.init(randomBuf,randomBuf);
+			s20.crypt12(randomBuf, randomBuf, sizeof(randomBuf));
+			s20.init(randomBuf, randomBuf);
 		}
-		((uint8_t *)buf)[i] = randomBuf[randomPtr++];
+		((uint8_t*)buf)[i] = randomBuf[randomPtr++];
 	}
 
-#else // not __WINDOWS__
+#else	// not __WINDOWS__
 
 	static int devURandomFd = -1;
 
 	if (devURandomFd < 0) {
-		devURandomFd = ::open("/dev/urandom",O_RDONLY);
+		devURandomFd = ::open("/dev/urandom", O_RDONLY);
 		if (devURandomFd < 0) {
-			fprintf(stderr,"FATAL ERROR: Utils::getSecureRandom() unable to open /dev/urandom\n");
+			fprintf(stderr, "FATAL ERROR: Utils::getSecureRandom() unable to open /dev/urandom\n");
 			exit(1);
 			return;
 		}
 	}
 
-	for(unsigned int i=0;i<bytes;++i) {
+	for (unsigned int i = 0; i < bytes; ++i) {
 		if (randomPtr >= sizeof(randomBuf)) {
-			for(;;) {
-				if ((int)::read(devURandomFd,randomBuf,sizeof(randomBuf)) != (int)sizeof(randomBuf)) {
+			for (;;) {
+				if ((int)::read(devURandomFd, randomBuf, sizeof(randomBuf)) != (int)sizeof(randomBuf)) {
 					::close(devURandomFd);
-					devURandomFd = ::open("/dev/urandom",O_RDONLY);
+					devURandomFd = ::open("/dev/urandom", O_RDONLY);
 					if (devURandomFd < 0) {
-						fprintf(stderr,"FATAL ERROR: Utils::getSecureRandom() unable to open /dev/urandom\n");
+						fprintf(stderr, "FATAL ERROR: Utils::getSecureRandom() unable to open /dev/urandom\n");
 						exit(1);
 						return;
 					}
-				} else {
+				}
+				else {
 					break;
 				}
 			}
 			randomPtr = 0;
-			s20.crypt12(randomBuf,randomBuf,sizeof(randomBuf));
-			s20.init(randomBuf,randomBuf);
+			s20.crypt12(randomBuf, randomBuf, sizeof(randomBuf));
+			s20.init(randomBuf, randomBuf);
 		}
-		((uint8_t *)buf)[i] = randomBuf[randomPtr++];
+		((uint8_t*)buf)[i] = randomBuf[randomPtr++];
 	}
 
-#endif // __WINDOWS__ or not
+#endif	 // __WINDOWS__ or not
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier

+ 291 - 286
node/Utils.hpp

@@ -14,17 +14,16 @@
 #ifndef ZT_UTILS_HPP
 #define ZT_UTILS_HPP
 
+#include <algorithm>
+#include <map>
+#include <stdexcept>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <stdint.h>
 #include <string.h>
-#include <time.h>
-
 #include <string>
-#include <stdexcept>
+#include <time.h>
 #include <vector>
-#include <map>
-#include <algorithm>
 
 #if defined(__FreeBSD__)
 #include <sys/endian.h>
@@ -34,15 +33,9 @@
 
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 #define ZT_CONST_TO_BE_UINT16(x) ((uint16_t)((uint16_t)((uint16_t)(x) << 8U) | (uint16_t)((uint16_t)(x) >> 8U)))
-#define ZT_CONST_TO_BE_UINT64(x) ( \
-  (((uint64_t)(x) & 0x00000000000000ffULL) << 56U) | \
-  (((uint64_t)(x) & 0x000000000000ff00ULL) << 40U) | \
-  (((uint64_t)(x) & 0x0000000000ff0000ULL) << 24U) | \
-  (((uint64_t)(x) & 0x00000000ff000000ULL) <<  8U) | \
-  (((uint64_t)(x) & 0x000000ff00000000ULL) >>  8U) | \
-  (((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24U) | \
-  (((uint64_t)(x) & 0x00ff000000000000ULL) >> 40U) | \
-  (((uint64_t)(x) & 0xff00000000000000ULL) >> 56U))
+#define ZT_CONST_TO_BE_UINT64(x)                                                                                                                                                                                                               \
+	((((uint64_t)(x) & 0x00000000000000ffULL) << 56U) | (((uint64_t)(x) & 0x000000000000ff00ULL) << 40U) | (((uint64_t)(x) & 0x0000000000ff0000ULL) << 24U) | (((uint64_t)(x) & 0x00000000ff000000ULL) << 8U)                                  \
+	 | (((uint64_t)(x) & 0x000000ff00000000ULL) >> 8U) | (((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24U) | (((uint64_t)(x) & 0x00ff000000000000ULL) >> 40U) | (((uint64_t)(x) & 0xff00000000000000ULL) >> 56U))
 #else
 #define ZT_CONST_TO_BE_UINT16(x) ((uint16_t)(x))
 #define ZT_CONST_TO_BE_UINT64(x) ((uint64_t)(x))
@@ -58,14 +51,12 @@ namespace ZeroTier {
 /**
  * Miscellaneous utility functions and global constants
  */
-class Utils
-{
-public:
+class Utils {
+  public:
 	static const uint64_t ZERO256[4];
 
 #ifdef ZT_ARCH_ARM_HAS_NEON
-	struct ARMCapabilities
-	{
+	struct ARMCapabilities {
 		ARMCapabilities() noexcept;
 
 		bool aes;
@@ -78,15 +69,14 @@ public:
 #endif
 
 #ifdef ZT_ARCH_X64
-	struct CPUIDRegisters
-	{
+	struct CPUIDRegisters {
 		CPUIDRegisters() noexcept;
 
 		bool rdrand;
 		bool aes;
 		bool avx;
-		bool vaes; // implies AVX
-		bool vpclmulqdq; // implies AVX
+		bool vaes;		   // implies AVX
+		bool vpclmulqdq;   // implies AVX
 		bool avx2;
 		bool avx512f;
 		bool sha;
@@ -97,7 +87,7 @@ public:
 
 	/**
 	 * Compute the log2 (most significant bit set) of a 32-bit integer
-	 * 
+	 *
 	 * @param v Integer to compute
 	 * @return log2 or 0 if v is 0
 	 */
@@ -126,11 +116,11 @@ public:
 	 * @param len Length of strings
 	 * @return True if strings are equal
 	 */
-	static inline bool secureEq(const void *a,const void *b,unsigned int len)
+	static inline bool secureEq(const void* a, const void* b, unsigned int len)
 	{
 		uint8_t diff = 0;
-		for(unsigned int i=0;i<len;++i) {
-			diff |= ( (reinterpret_cast<const uint8_t *>(a))[i] ^ (reinterpret_cast<const uint8_t *>(b))[i] );
+		for (unsigned int i = 0; i < len; ++i) {
+			diff |= ((reinterpret_cast<const uint8_t*>(a))[i] ^ (reinterpret_cast<const uint8_t*>(b))[i]);
 		}
 		return (diff == 0);
 	}
@@ -138,16 +128,16 @@ public:
 	/**
 	 * Securely zero memory, avoiding compiler optimizations and such
 	 */
-	static void burn(void *ptr,unsigned int len);
+	static void burn(void* ptr, unsigned int len);
 
 	/**
 	 * @param n Number to convert
 	 * @param s Buffer, at least 24 bytes in size
 	 * @return String containing 'n' in base 10 form
 	 */
-	static char *decimal(unsigned long n,char s[24]);
+	static char* decimal(unsigned long n, char s[24]);
 
-	static inline char *hex(uint64_t i,char s[17])
+	static inline char* hex(uint64_t i, char s[17])
 	{
 		s[0] = HEXCHARS[(i >> 60) & 0xf];
 		s[1] = HEXCHARS[(i >> 56) & 0xf];
@@ -169,7 +159,7 @@ public:
 		return s;
 	}
 
-	static inline char *hex10(uint64_t i,char s[11])
+	static inline char* hex10(uint64_t i, char s[11])
 	{
 		s[0] = HEXCHARS[(i >> 36) & 0xf];
 		s[1] = HEXCHARS[(i >> 32) & 0xf];
@@ -185,7 +175,7 @@ public:
 		return s;
 	}
 
-	static inline char *hex(uint32_t i,char s[9])
+	static inline char* hex(uint32_t i, char s[9])
 	{
 		s[0] = HEXCHARS[(i >> 28) & 0xf];
 		s[1] = HEXCHARS[(i >> 24) & 0xf];
@@ -199,7 +189,7 @@ public:
 		return s;
 	}
 
-	static inline char *hex(uint16_t i,char s[5])
+	static inline char* hex(uint16_t i, char s[5])
 	{
 		s[0] = HEXCHARS[(i >> 12) & 0xf];
 		s[1] = HEXCHARS[(i >> 8) & 0xf];
@@ -209,7 +199,7 @@ public:
 		return s;
 	}
 
-	static inline char *hex(uint8_t i,char s[3])
+	static inline char* hex(uint8_t i, char s[3])
 	{
 		s[0] = HEXCHARS[(i >> 4) & 0xf];
 		s[1] = HEXCHARS[i & 0xf];
@@ -217,11 +207,11 @@ public:
 		return s;
 	}
 
-	static inline char *hex(const void *d,unsigned int l,char *s)
+	static inline char* hex(const void* d, unsigned int l, char* s)
 	{
-		char *const save = s;
-		for(unsigned int i=0;i<l;++i) {
-			const unsigned int b = reinterpret_cast<const uint8_t *>(d)[i];
+		char* const save = s;
+		for (unsigned int i = 0; i < l; ++i) {
+			const unsigned int b = reinterpret_cast<const uint8_t*>(d)[i];
 			*(s++) = HEXCHARS[b >> 4];
 			*(s++) = HEXCHARS[b & 0xf];
 		}
@@ -229,83 +219,91 @@ public:
 		return save;
 	}
 
-	static inline unsigned int unhex(const char *h,void *buf,unsigned int buflen)
+	static inline unsigned int unhex(const char* h, void* buf, unsigned int buflen)
 	{
 		unsigned int l = 0;
 		while (l < buflen) {
-			uint8_t hc = *(reinterpret_cast<const uint8_t *>(h++));
-			if (!hc) {
+			uint8_t hc = *(reinterpret_cast<const uint8_t*>(h++));
+			if (! hc) {
 				break;
 			}
 
 			uint8_t c = 0;
-			if ((hc >= 48)&&(hc <= 57)) { // 0..9
+			if ((hc >= 48) && (hc <= 57)) {	  // 0..9
 				c = hc - 48;
-			} else if ((hc >= 97)&&(hc <= 102)) { // a..f
+			}
+			else if ((hc >= 97) && (hc <= 102)) {	// a..f
 				c = hc - 87;
-			} else if ((hc >= 65)&&(hc <= 70)) { // A..F
+			}
+			else if ((hc >= 65) && (hc <= 70)) {   // A..F
 				c = hc - 55;
 			}
 
-			hc = *(reinterpret_cast<const uint8_t *>(h++));
-			if (!hc) {
+			hc = *(reinterpret_cast<const uint8_t*>(h++));
+			if (! hc) {
 				break;
 			}
 
 			c <<= 4;
-			if ((hc >= 48)&&(hc <= 57)) {
+			if ((hc >= 48) && (hc <= 57)) {
 				c |= hc - 48;
-			} else if ((hc >= 97)&&(hc <= 102)) {
+			}
+			else if ((hc >= 97) && (hc <= 102)) {
 				c |= hc - 87;
-			} else if ((hc >= 65)&&(hc <= 70)) {
+			}
+			else if ((hc >= 65) && (hc <= 70)) {
 				c |= hc - 55;
 			}
 
-			reinterpret_cast<uint8_t *>(buf)[l++] = c;
+			reinterpret_cast<uint8_t*>(buf)[l++] = c;
 		}
 		return l;
 	}
 
-	static inline unsigned int unhex(const char *h,unsigned int hlen,void *buf,unsigned int buflen)
+	static inline unsigned int unhex(const char* h, unsigned int hlen, void* buf, unsigned int buflen)
 	{
 		unsigned int l = 0;
-		const char *hend = h + hlen;
+		const char* hend = h + hlen;
 		while (l < buflen) {
 			if (h == hend) {
 				break;
 			}
-			uint8_t hc = *(reinterpret_cast<const uint8_t *>(h++));
-			if (!hc) {
+			uint8_t hc = *(reinterpret_cast<const uint8_t*>(h++));
+			if (! hc) {
 				break;
 			}
 
 			uint8_t c = 0;
-			if ((hc >= 48)&&(hc <= 57)) {
+			if ((hc >= 48) && (hc <= 57)) {
 				c = hc - 48;
-			} else if ((hc >= 97)&&(hc <= 102)) {
+			}
+			else if ((hc >= 97) && (hc <= 102)) {
 				c = hc - 87;
-			} else if ((hc >= 65)&&(hc <= 70)) {
+			}
+			else if ((hc >= 65) && (hc <= 70)) {
 				c = hc - 55;
 			}
 
 			if (h == hend) {
 				break;
 			}
-			hc = *(reinterpret_cast<const uint8_t *>(h++));
-			if (!hc) {
+			hc = *(reinterpret_cast<const uint8_t*>(h++));
+			if (! hc) {
 				break;
 			}
 
 			c <<= 4;
-			if ((hc >= 48)&&(hc <= 57)) {
+			if ((hc >= 48) && (hc <= 57)) {
 				c |= hc - 48;
-			} else if ((hc >= 97)&&(hc <= 102)) {
+			}
+			else if ((hc >= 97) && (hc <= 102)) {
 				c |= hc - 87;
-			} else if ((hc >= 65)&&(hc <= 70)) {
+			}
+			else if ((hc >= 65) && (hc <= 70)) {
 				c |= hc - 55;
 			}
 
-			reinterpret_cast<uint8_t *>(buf)[l++] = c;
+			reinterpret_cast<uint8_t*>(buf)[l++] = c;
 		}
 		return l;
 	}
@@ -327,7 +325,7 @@ public:
 	 * @param buf Buffer to fill
 	 * @param bytes Number of random bytes to generate
 	 */
-	static void getSecureRandom(void *buf,unsigned int bytes);
+	static void getSecureRandom(void* buf, unsigned int bytes);
 
 	/**
 	 * Tokenize a string (alias for strtok_r or strtok_s depending on platform)
@@ -336,54 +334,81 @@ public:
 	 * @param delim Delimiters
 	 * @param saveptr Pointer to a char * for temporary reentrant storage
 	 */
-	static inline char *stok(char *str,const char *delim,char **saveptr)
+	static inline char* stok(char* str, const char* delim, char** saveptr)
 	{
 #ifdef __WINDOWS__
-		return strtok_s(str,delim,saveptr);
+		return strtok_s(str, delim, saveptr);
 #else
-		return strtok_r(str,delim,saveptr);
+		return strtok_r(str, delim, saveptr);
 #endif
 	}
 
-	static inline unsigned int strToUInt(const char *s) { return (unsigned int)strtoul(s,(char **)0,10); }
-	static inline int strToInt(const char *s) { return (int)strtol(s,(char **)0,10); }
-	static inline unsigned long strToULong(const char *s) { return strtoul(s,(char **)0,10); }
-	static inline long strToLong(const char *s) { return strtol(s,(char **)0,10); }
-	static inline double strToDouble(const char *s) { return strtod(s,NULL); }
-	static inline unsigned long long strToU64(const char *s)
+	static inline unsigned int strToUInt(const char* s)
+	{
+		return (unsigned int)strtoul(s, (char**)0, 10);
+	}
+	static inline int strToInt(const char* s)
+	{
+		return (int)strtol(s, (char**)0, 10);
+	}
+	static inline unsigned long strToULong(const char* s)
+	{
+		return strtoul(s, (char**)0, 10);
+	}
+	static inline long strToLong(const char* s)
+	{
+		return strtol(s, (char**)0, 10);
+	}
+	static inline double strToDouble(const char* s)
+	{
+		return strtod(s, NULL);
+	}
+	static inline unsigned long long strToU64(const char* s)
 	{
 #ifdef __WINDOWS__
-		return (unsigned long long)_strtoui64(s,(char **)0,10);
+		return (unsigned long long)_strtoui64(s, (char**)0, 10);
 #else
-		return strtoull(s,(char **)0,10);
+		return strtoull(s, (char**)0, 10);
 #endif
 	}
-	static inline long long strTo64(const char *s)
+	static inline long long strTo64(const char* s)
 	{
 #ifdef __WINDOWS__
-		return (long long)_strtoi64(s,(char **)0,10);
+		return (long long)_strtoi64(s, (char**)0, 10);
 #else
-		return strtoll(s,(char **)0,10);
+		return strtoll(s, (char**)0, 10);
 #endif
 	}
-	static inline unsigned int hexStrToUInt(const char *s) { return (unsigned int)strtoul(s,(char **)0,16); }
-	static inline int hexStrToInt(const char *s) { return (int)strtol(s,(char **)0,16); }
-	static inline unsigned long hexStrToULong(const char *s) { return strtoul(s,(char **)0,16); }
-	static inline long hexStrToLong(const char *s) { return strtol(s,(char **)0,16); }
-	static inline unsigned long long hexStrToU64(const char *s)
+	static inline unsigned int hexStrToUInt(const char* s)
+	{
+		return (unsigned int)strtoul(s, (char**)0, 16);
+	}
+	static inline int hexStrToInt(const char* s)
+	{
+		return (int)strtol(s, (char**)0, 16);
+	}
+	static inline unsigned long hexStrToULong(const char* s)
+	{
+		return strtoul(s, (char**)0, 16);
+	}
+	static inline long hexStrToLong(const char* s)
+	{
+		return strtol(s, (char**)0, 16);
+	}
+	static inline unsigned long long hexStrToU64(const char* s)
 	{
 #ifdef __WINDOWS__
-		return (unsigned long long)_strtoui64(s,(char **)0,16);
+		return (unsigned long long)_strtoui64(s, (char**)0, 16);
 #else
-		return strtoull(s,(char **)0,16);
+		return strtoull(s, (char**)0, 16);
 #endif
 	}
-	static inline long long hexStrTo64(const char *s)
+	static inline long long hexStrTo64(const char* s)
 	{
 #ifdef __WINDOWS__
-		return (long long)_strtoi64(s,(char **)0,16);
+		return (long long)_strtoi64(s, (char**)0, 16);
 #else
-		return strtoll(s,(char **)0,16);
+		return strtoll(s, (char**)0, 16);
 #endif
 	}
 
@@ -398,16 +423,16 @@ public:
 	 * @param src Source string (if NULL, dest will receive a zero-length string and true is returned)
 	 * @return True on success, false on overflow (buffer will still be 0-terminated)
 	 */
-	static inline bool scopy(char *dest,unsigned int len,const char *src)
+	static inline bool scopy(char* dest, unsigned int len, const char* src)
 	{
-		if (!len) {
-			return false; // sanity check
+		if (! len) {
+			return false;	// sanity check
 		}
-		if (!src) {
+		if (! src) {
 			*dest = (char)0;
 			return true;
 		}
-		char *end = dest + len;
+		char* end = dest + len;
 		while ((*dest++ = *src++)) {
 			if (dest == end) {
 				*(--dest) = (char)0;
@@ -438,10 +463,10 @@ public:
 	 */
 	static inline uint64_t countBits(uint64_t v)
 	{
-		v = v - ((v >> 1) & (uint64_t)~(uint64_t)0/3);
-		v = (v & (uint64_t)~(uint64_t)0/15*3) + ((v >> 2) & (uint64_t)~(uint64_t)0/15*3);
-		v = (v + (v >> 4)) & (uint64_t)~(uint64_t)0/255*15;
-		return (uint64_t)(v * ((uint64_t)~(uint64_t)0/255)) >> 56;
+		v = v - ((v >> 1) & (uint64_t)~(uint64_t)0 / 3);
+		v = (v & (uint64_t)~(uint64_t)0 / 15 * 3) + ((v >> 2) & (uint64_t)~(uint64_t)0 / 15 * 3);
+		v = (v + (v >> 4)) & (uint64_t)~(uint64_t)0 / 255 * 15;
+		return (uint64_t)(v * ((uint64_t)~(uint64_t)0 / 255)) >> 56;
 	}
 
 	/**
@@ -451,10 +476,10 @@ public:
 	 * @param len Length of memory
 	 * @return True if memory is all zero
 	 */
-	static inline bool isZero(const void *p,unsigned int len)
+	static inline bool isZero(const void* p, unsigned int len)
 	{
-		for(unsigned int i=0;i<len;++i) {
-			if (((const unsigned char *)p)[i]) {
+		for (unsigned int i = 0; i < len; ++i) {
+			if (((const unsigned char*)p)[i]) {
 				return false;
 			}
 		}
@@ -469,24 +494,17 @@ public:
 	 */
 	static ZT_INLINE uint64_t swapBytes(const uint64_t n) noexcept
 	{
-	#ifdef __GNUC__
+#ifdef __GNUC__
 		return __builtin_bswap64(n);
-	#else
-	#ifdef _MSC_VER
+#else
+#ifdef _MSC_VER
 		return (uint64_t)_byteswap_uint64((unsigned __int64)n);
-	#else
+#else
 		return (
-			((n & 0x00000000000000ffULL) << 56) |
-			((n & 0x000000000000ff00ULL) << 40) |
-			((n & 0x0000000000ff0000ULL) << 24) |
-			((n & 0x00000000ff000000ULL) <<  8) |
-			((n & 0x000000ff00000000ULL) >>  8) |
-			((n & 0x0000ff0000000000ULL) >> 24) |
-			((n & 0x00ff000000000000ULL) >> 40) |
-			((n & 0xff00000000000000ULL) >> 56)
-		);
-	#endif
-	#endif
+			((n & 0x00000000000000ffULL) << 56) | ((n & 0x000000000000ff00ULL) << 40) | ((n & 0x0000000000ff0000ULL) << 24) | ((n & 0x00000000ff000000ULL) << 8) | ((n & 0x000000ff00000000ULL) >> 8) | ((n & 0x0000ff0000000000ULL) >> 24)
+			| ((n & 0x00ff000000000000ULL) >> 40) | ((n & 0xff00000000000000ULL) >> 56));
+#endif
+#endif
 	}
 
 	/**
@@ -497,15 +515,15 @@ public:
 	 */
 	static ZT_INLINE uint32_t swapBytes(const uint32_t n) noexcept
 	{
-	#if defined(__GNUC__)
+#if defined(__GNUC__)
 		return __builtin_bswap32(n);
-	#else
-	#ifdef _MSC_VER
+#else
+#ifdef _MSC_VER
 		return (uint32_t)_byteswap_ulong((unsigned long)n);
-	#else
+#else
 		return htonl(n);
-	#endif
-	#endif
+#endif
+#endif
 	}
 
 	/**
@@ -516,122 +534,119 @@ public:
 	 */
 	static ZT_INLINE uint16_t swapBytes(const uint16_t n) noexcept
 	{
-	#if defined(__GNUC__)
+#if defined(__GNUC__)
 		return __builtin_bswap16(n);
-	#else
-	#ifdef _MSC_VER
+#else
+#ifdef _MSC_VER
 		return (uint16_t)_byteswap_ushort((unsigned short)n);
-	#else
+#else
 		return htons(n);
-	#endif
-	#endif
+#endif
+#endif
 	}
 
 	// These are helper adapters to load and swap integer types special cased by size
 	// to work with all typedef'd variants, signed/unsigned, etc.
-	template< typename I, unsigned int S >
-	class _swap_bytes_bysize;
+	template <typename I, unsigned int S> class _swap_bytes_bysize;
 
-	template< typename I >
-	class _swap_bytes_bysize< I, 1 >
-	{
-	public:
+	template <typename I> class _swap_bytes_bysize<I, 1> {
+	  public:
 		static ZT_INLINE I s(const I n) noexcept
-		{ return n; }
+		{
+			return n;
+		}
 	};
 
-	template< typename I >
-	class _swap_bytes_bysize< I, 2 >
-	{
-	public:
+	template <typename I> class _swap_bytes_bysize<I, 2> {
+	  public:
 		static ZT_INLINE I s(const I n) noexcept
-		{ return (I)swapBytes((uint16_t)n); }
+		{
+			return (I)swapBytes((uint16_t)n);
+		}
 	};
 
-	template< typename I >
-	class _swap_bytes_bysize< I, 4 >
-	{
-	public:
+	template <typename I> class _swap_bytes_bysize<I, 4> {
+	  public:
 		static ZT_INLINE I s(const I n) noexcept
-		{ return (I)swapBytes((uint32_t)n); }
+		{
+			return (I)swapBytes((uint32_t)n);
+		}
 	};
 
-	template< typename I >
-	class _swap_bytes_bysize< I, 8 >
-	{
-	public:
+	template <typename I> class _swap_bytes_bysize<I, 8> {
+	  public:
 		static ZT_INLINE I s(const I n) noexcept
-		{ return (I)swapBytes((uint64_t)n); }
+		{
+			return (I)swapBytes((uint64_t)n);
+		}
 	};
 
-	template< typename I, unsigned int S >
-	class _load_be_bysize;
+	template <typename I, unsigned int S> class _load_be_bysize;
 
-	template< typename I >
-	class _load_be_bysize< I, 1 >
-	{
-	public:
-		static ZT_INLINE I l(const uint8_t *const p) noexcept
-		{ return p[0]; }
+	template <typename I> class _load_be_bysize<I, 1> {
+	  public:
+		static ZT_INLINE I l(const uint8_t* const p) noexcept
+		{
+			return p[0];
+		}
 	};
 
-	template< typename I >
-	class _load_be_bysize< I, 2 >
-	{
-	public:
-		static ZT_INLINE I l(const uint8_t *const p) noexcept
-		{ return (I)(((unsigned int)p[0] << 8U) | (unsigned int)p[1]); }
+	template <typename I> class _load_be_bysize<I, 2> {
+	  public:
+		static ZT_INLINE I l(const uint8_t* const p) noexcept
+		{
+			return (I)(((unsigned int)p[0] << 8U) | (unsigned int)p[1]);
+		}
 	};
 
-	template< typename I >
-	class _load_be_bysize< I, 4 >
-	{
-	public:
-		static ZT_INLINE I l(const uint8_t *const p) noexcept
-		{ return (I)(((uint32_t)p[0] << 24U) | ((uint32_t)p[1] << 16U) | ((uint32_t)p[2] << 8U) | (uint32_t)p[3]); }
+	template <typename I> class _load_be_bysize<I, 4> {
+	  public:
+		static ZT_INLINE I l(const uint8_t* const p) noexcept
+		{
+			return (I)(((uint32_t)p[0] << 24U) | ((uint32_t)p[1] << 16U) | ((uint32_t)p[2] << 8U) | (uint32_t)p[3]);
+		}
 	};
 
-	template< typename I >
-	class _load_be_bysize< I, 8 >
-	{
-	public:
-		static ZT_INLINE I l(const uint8_t *const p) noexcept
-		{ return (I)(((uint64_t)p[0] << 56U) | ((uint64_t)p[1] << 48U) | ((uint64_t)p[2] << 40U) | ((uint64_t)p[3] << 32U) | ((uint64_t)p[4] << 24U) | ((uint64_t)p[5] << 16U) | ((uint64_t)p[6] << 8U) | (uint64_t)p[7]); }
+	template <typename I> class _load_be_bysize<I, 8> {
+	  public:
+		static ZT_INLINE I l(const uint8_t* const p) noexcept
+		{
+			return (I)(((uint64_t)p[0] << 56U) | ((uint64_t)p[1] << 48U) | ((uint64_t)p[2] << 40U) | ((uint64_t)p[3] << 32U) | ((uint64_t)p[4] << 24U) | ((uint64_t)p[5] << 16U) | ((uint64_t)p[6] << 8U) | (uint64_t)p[7]);
+		}
 	};
 
-	template< typename I, unsigned int S >
-	class _load_le_bysize;
+	template <typename I, unsigned int S> class _load_le_bysize;
 
-	template< typename I >
-	class _load_le_bysize< I, 1 >
-	{
-	public:
-		static ZT_INLINE I l(const uint8_t *const p) noexcept
-		{ return p[0]; }
+	template <typename I> class _load_le_bysize<I, 1> {
+	  public:
+		static ZT_INLINE I l(const uint8_t* const p) noexcept
+		{
+			return p[0];
+		}
 	};
 
-	template< typename I >
-	class _load_le_bysize< I, 2 >
-	{
-	public:
-		static ZT_INLINE I l(const uint8_t *const p) noexcept
-		{ return (I)((unsigned int)p[0] | ((unsigned int)p[1] << 8U)); }
+	template <typename I> class _load_le_bysize<I, 2> {
+	  public:
+		static ZT_INLINE I l(const uint8_t* const p) noexcept
+		{
+			return (I)((unsigned int)p[0] | ((unsigned int)p[1] << 8U));
+		}
 	};
 
-	template< typename I >
-	class _load_le_bysize< I, 4 >
-	{
-	public:
-		static ZT_INLINE I l(const uint8_t *const p) noexcept
-		{ return (I)((uint32_t)p[0] | ((uint32_t)p[1] << 8U) | ((uint32_t)p[2] << 16U) | ((uint32_t)p[3] << 24U)); }
+	template <typename I> class _load_le_bysize<I, 4> {
+	  public:
+		static ZT_INLINE I l(const uint8_t* const p) noexcept
+		{
+			return (I)((uint32_t)p[0] | ((uint32_t)p[1] << 8U) | ((uint32_t)p[2] << 16U) | ((uint32_t)p[3] << 24U));
+		}
 	};
 
-	template< typename I >
-	class _load_le_bysize< I, 8 >
-	{
-	public:
-		static ZT_INLINE I l(const uint8_t *const p) noexcept
-		{ return (I)((uint64_t)p[0] | ((uint64_t)p[1] << 8U) | ((uint64_t)p[2] << 16U) | ((uint64_t)p[3] << 24U) | ((uint64_t)p[4] << 32U) | ((uint64_t)p[5] << 40U) | ((uint64_t)p[6] << 48U) | ((uint64_t)p[7]) << 56U); }
+	template <typename I> class _load_le_bysize<I, 8> {
+	  public:
+		static ZT_INLINE I l(const uint8_t* const p) noexcept
+		{
+			return (I)((uint64_t)p[0] | ((uint64_t)p[1] << 8U) | ((uint64_t)p[2] << 16U) | ((uint64_t)p[3] << 24U) | ((uint64_t)p[4] << 32U) | ((uint64_t)p[5] << 40U) | ((uint64_t)p[6] << 48U) | ((uint64_t)p[7]) << 56U);
+		}
 	};
 
 	/**
@@ -641,14 +656,13 @@ public:
 	 * @param n Value to convert
 	 * @return Value in big-endian order
 	 */
-	template< typename I >
-	static ZT_INLINE I hton(const I n) noexcept
+	template <typename I> static ZT_INLINE I hton(const I n) noexcept
 	{
-	#if __BYTE_ORDER == __LITTLE_ENDIAN
-		return _swap_bytes_bysize< I, sizeof(I) >::s(n);
-	#else
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+		return _swap_bytes_bysize<I, sizeof(I)>::s(n);
+#else
 		return n;
-	#endif
+#endif
 	}
 
 	/**
@@ -658,14 +672,13 @@ public:
 	 * @param n Value to convert
 	 * @return Value in host byte order
 	 */
-	template< typename I >
-	static ZT_INLINE I ntoh(const I n) noexcept
+	template <typename I> static ZT_INLINE I ntoh(const I n) noexcept
 	{
-	#if __BYTE_ORDER == __LITTLE_ENDIAN
-		return _swap_bytes_bysize< I, sizeof(I) >::s(n);
-	#else
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+		return _swap_bytes_bysize<I, sizeof(I)>::s(n);
+#else
 		return n;
-	#endif
+#endif
 	}
 
 	/**
@@ -675,18 +688,17 @@ public:
 	 * @param p Byte stream, must be at least sizeof(I) in size
 	 * @return Loaded raw integer
 	 */
-	template< typename I >
-	static ZT_INLINE I loadMachineEndian(const void *const p) noexcept
+	template <typename I> static ZT_INLINE I loadMachineEndian(const void* const p) noexcept
 	{
-	#ifdef ZT_NO_UNALIGNED_ACCESS
+#ifdef ZT_NO_UNALIGNED_ACCESS
 		I tmp;
-		for(int i=0;i<(int)sizeof(I);++i) {
-			reinterpret_cast<uint8_t *>(&tmp)[i] = reinterpret_cast<const uint8_t *>(p)[i];
+		for (int i = 0; i < (int)sizeof(I); ++i) {
+			reinterpret_cast<uint8_t*>(&tmp)[i] = reinterpret_cast<const uint8_t*>(p)[i];
 		}
 		return tmp;
-	#else
-		return *reinterpret_cast<const I *>(p);
-	#endif
+#else
+		return *reinterpret_cast<const I*>(p);
+#endif
 	}
 
 	/**
@@ -696,16 +708,15 @@ public:
 	 * @param p Byte array (must be at least sizeof(I))
 	 * @param i Integer to store
 	 */
-	template< typename I >
-	static ZT_INLINE void storeMachineEndian(void *const p, const I i) noexcept
+	template <typename I> 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) {
-			reinterpret_cast<uint8_t *>(p)[k] = reinterpret_cast<const uint8_t *>(&i)[k];
+#ifdef ZT_NO_UNALIGNED_ACCESS
+		for (unsigned int k = 0; k < sizeof(I); ++k) {
+			reinterpret_cast<uint8_t*>(p)[k] = reinterpret_cast<const uint8_t*>(&i)[k];
 		}
-	#else
-		*reinterpret_cast<I *>(p) = i;
-	#endif
+#else
+		*reinterpret_cast<I*>(p) = i;
+#endif
 	}
 
 	/**
@@ -715,14 +726,13 @@ public:
 	 * @param p Byte stream, must be at least sizeof(I) in size
 	 * @return Decoded integer
 	 */
-	template< typename I >
-	static ZT_INLINE I loadBigEndian(const void *const p) noexcept
+	template <typename I> static ZT_INLINE I loadBigEndian(const void* const p) noexcept
 	{
-	#ifdef ZT_NO_UNALIGNED_ACCESS
-		return _load_be_bysize<I,sizeof(I)>::l(reinterpret_cast<const uint8_t *>(p));
-	#else
-		return ntoh(*reinterpret_cast<const I *>(p));
-	#endif
+#ifdef ZT_NO_UNALIGNED_ACCESS
+		return _load_be_bysize<I, sizeof(I)>::l(reinterpret_cast<const uint8_t*>(p));
+#else
+		return ntoh(*reinterpret_cast<const I*>(p));
+#endif
 	}
 
 	/**
@@ -732,14 +742,13 @@ public:
 	 * @param p Byte stream to write (must be at least sizeof(I))
 	 * #param i Integer to write
 	 */
-	template< typename I >
-	static ZT_INLINE void storeBigEndian(void *const p, I i) noexcept
+	template <typename I> static ZT_INLINE void storeBigEndian(void* const p, I i) noexcept
 	{
-	#ifdef ZT_NO_UNALIGNED_ACCESS
-		storeMachineEndian(p,hton(i));
-	#else
-		*reinterpret_cast<I *>(p) = hton(i);
-	#endif
+#ifdef ZT_NO_UNALIGNED_ACCESS
+		storeMachineEndian(p, hton(i));
+#else
+		*reinterpret_cast<I*>(p) = hton(i);
+#endif
 	}
 
 	/**
@@ -749,14 +758,13 @@ public:
 	 * @param p Byte stream, must be at least sizeof(I) in size
 	 * @return Decoded integer
 	 */
-	template< typename I >
-	static ZT_INLINE I loadLittleEndian(const void *const p) noexcept
+	template <typename I> static ZT_INLINE I loadLittleEndian(const void* const p) noexcept
 	{
-	#if __BYTE_ORDER == __BIG_ENDIAN || defined(ZT_NO_UNALIGNED_ACCESS)
-		return _load_le_bysize<I,sizeof(I)>::l(reinterpret_cast<const uint8_t *>(p));
-	#else
-		return *reinterpret_cast<const I *>(p);
-	#endif
+#if __BYTE_ORDER == __BIG_ENDIAN || defined(ZT_NO_UNALIGNED_ACCESS)
+		return _load_le_bysize<I, sizeof(I)>::l(reinterpret_cast<const uint8_t*>(p));
+#else
+		return *reinterpret_cast<const I*>(p);
+#endif
 	}
 
 	/**
@@ -766,18 +774,17 @@ public:
 	 * @param p Byte stream to write (must be at least sizeof(I))
 	 * #param i Integer to write
 	 */
-	template< typename I >
-	static ZT_INLINE void storeLittleEndian(void *const p, const I i) noexcept
+	template <typename I> static ZT_INLINE void storeLittleEndian(void* const p, const I i) noexcept
 	{
-	#if __BYTE_ORDER == __BIG_ENDIAN
-		storeMachineEndian(p,_swap_bytes_bysize<I,sizeof(I)>::s(i));
-	#else
-	#ifdef ZT_NO_UNALIGNED_ACCESS
-		storeMachineEndian(p,i);
-	#else
-		*reinterpret_cast<I *>(p) = i;
-	#endif
-	#endif
+#if __BYTE_ORDER == __BIG_ENDIAN
+		storeMachineEndian(p, _swap_bytes_bysize<I, sizeof(I)>::s(i));
+#else
+#ifdef ZT_NO_UNALIGNED_ACCESS
+		storeMachineEndian(p, i);
+#else
+		*reinterpret_cast<I*>(p) = i;
+#endif
+#endif
 	}
 
 	/**
@@ -787,15 +794,14 @@ public:
 	 * @param dest Destination memory
 	 * @param src Source memory
 	 */
-	template< unsigned long L >
-	static ZT_INLINE void copy(void *dest, const void *src) noexcept
+	template <unsigned long L> static ZT_INLINE void copy(void* dest, const void* src) noexcept
 	{
-	#if defined(ZT_ARCH_X64) && defined(__GNUC__)
+#if defined(ZT_ARCH_X64) && defined(__GNUC__)
 		uintptr_t l = L;
-		__asm__ __volatile__ ("cld ; rep movsb" : "+c"(l), "+S"(src), "+D"(dest) :: "memory");
-	#else
+		__asm__ __volatile__("cld ; rep movsb" : "+c"(l), "+S"(src), "+D"(dest)::"memory");
+#else
 		memcpy(dest, src, L);
-	#endif
+#endif
 	}
 
 	/**
@@ -805,13 +811,13 @@ public:
 	 * @param src Source memory
 	 * @param len Bytes to copy
 	 */
-	static ZT_INLINE void copy(void *dest, const void *src, unsigned long len) noexcept
+	static ZT_INLINE void copy(void* dest, const void* src, unsigned long len) noexcept
 	{
-	#if defined(ZT_ARCH_X64) && defined(__GNUC__)
-		__asm__ __volatile__ ("cld ; rep movsb" : "+c"(len), "+S"(src), "+D"(dest) :: "memory");
-	#else
+#if defined(ZT_ARCH_X64) && defined(__GNUC__)
+		__asm__ __volatile__("cld ; rep movsb" : "+c"(len), "+S"(src), "+D"(dest)::"memory");
+#else
 		memcpy(dest, src, len);
-	#endif
+#endif
 	}
 
 	/**
@@ -820,15 +826,14 @@ public:
 	 * @tparam L Size in bytes
 	 * @param dest Memory to zero
 	 */
-	template< unsigned long L >
-	static ZT_INLINE void zero(void *dest) noexcept
+	template <unsigned long L> static ZT_INLINE void zero(void* dest) noexcept
 	{
-	#if defined(ZT_ARCH_X64) && defined(__GNUC__)
+#if defined(ZT_ARCH_X64) && defined(__GNUC__)
 		uintptr_t l = L;
-		__asm__ __volatile__ ("cld ; rep stosb" :"+c" (l), "+D" (dest) : "a" (0) : "memory");
-	#else
+		__asm__ __volatile__("cld ; rep stosb" : "+c"(l), "+D"(dest) : "a"(0) : "memory");
+#else
 		memset(dest, 0, L);
-	#endif
+#endif
 	}
 
 	/**
@@ -837,13 +842,13 @@ public:
 	 * @param dest Memory to zero
 	 * @param len Size in bytes
 	 */
-	static ZT_INLINE void zero(void *dest, unsigned long len) noexcept
+	static ZT_INLINE void zero(void* dest, unsigned long len) noexcept
 	{
-	#if defined(ZT_ARCH_X64) && defined(__GNUC__)
-		__asm__ __volatile__ ("cld ; rep stosb" :"+c" (len), "+D" (dest) : "a" (0) : "memory");
-	#else
+#if defined(ZT_ARCH_X64) && defined(__GNUC__)
+		__asm__ __volatile__("cld ; rep stosb" : "+c"(len), "+D"(dest) : "a"(0) : "memory");
+#else
 		memset(dest, 0, len);
-	#endif
+#endif
 	}
 
 	/**
@@ -855,7 +860,7 @@ public:
 	 * Remove `-` and `:` from a MAC address (in-place).
 	 *
 	 * @param mac The MAC address
-	*/
+	 */
 	static inline void cleanMac(std::string& mac)
 	{
 		auto start = mac.begin();
@@ -865,6 +870,6 @@ public:
 	}
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 92 - 60
node/World.hpp

@@ -14,14 +14,14 @@
 #ifndef ZT_WORLD_HPP
 #define ZT_WORLD_HPP
 
-#include <vector>
-#include <string>
-
-#include "Constants.hpp"
-#include "InetAddress.hpp"
-#include "Identity.hpp"
 #include "Buffer.hpp"
 #include "C25519.hpp"
+#include "Constants.hpp"
+#include "Identity.hpp"
+#include "InetAddress.hpp"
+
+#include <string>
+#include <vector>
 
 /**
  * Maximum number of roots (sanity limit, okay to increase)
@@ -76,69 +76,92 @@ namespace ZeroTier {
  * world ID for Mars and nearby space is defined but not yet used, and a test
  * world ID is provided for testing purposes.
  */
-class World
-{
-public:
+class World {
+  public:
 	/**
 	 * World type -- do not change IDs
 	 */
-	enum Type
-	{
+	enum Type {
 		TYPE_NULL = 0,
-		TYPE_PLANET = 1, // Planets, of which there is currently one (Earth)
-		TYPE_MOON = 127  // Moons, which are user-created and many
+		TYPE_PLANET = 1,   // Planets, of which there is currently one (Earth)
+		TYPE_MOON = 127	   // Moons, which are user-created and many
 	};
 
 	/**
 	 * Upstream server definition in world/moon
 	 */
-	struct Root
-	{
+	struct Root {
 		Identity identity;
 		std::vector<InetAddress> stableEndpoints;
 
-		inline bool operator==(const Root &r) const { return ((identity == r.identity)&&(stableEndpoints == r.stableEndpoints)); }
-		inline bool operator!=(const Root &r) const { return (!(*this == r)); }
-		inline bool operator<(const Root &r) const { return (identity < r.identity); } // for sorting
+		inline bool operator==(const Root& r) const
+		{
+			return ((identity == r.identity) && (stableEndpoints == r.stableEndpoints));
+		}
+		inline bool operator!=(const Root& r) const
+		{
+			return (! (*this == r));
+		}
+		inline bool operator<(const Root& r) const
+		{
+			return (identity < r.identity);
+		}	// for sorting
 	};
 
 	/**
 	 * Construct an empty / null World
 	 */
-	World() :
-		_id(0),
-		_ts(0),
-		_type(TYPE_NULL) {}
+	World() : _id(0), _ts(0), _type(TYPE_NULL)
+	{
+	}
 
 	/**
 	 * @return Root servers for this world and their stable endpoints
 	 */
-	inline const std::vector<World::Root> &roots() const { return _roots; }
+	inline const std::vector<World::Root>& roots() const
+	{
+		return _roots;
+	}
 
 	/**
 	 * @return World type: planet or moon
 	 */
-	inline Type type() const { return _type; }
+	inline Type type() const
+	{
+		return _type;
+	}
 
 	/**
 	 * @return World unique identifier
 	 */
-	inline uint64_t id() const { return _id; }
+	inline uint64_t id() const
+	{
+		return _id;
+	}
 
 	/**
 	 * @return World definition timestamp
 	 */
-	inline uint64_t timestamp() const { return _ts; }
+	inline uint64_t timestamp() const
+	{
+		return _ts;
+	}
 
 	/**
 	 * @return C25519 signature
 	 */
-	inline const C25519::Signature &signature() const { return _signature; }
+	inline const C25519::Signature& signature() const
+	{
+		return _signature;
+	}
 
 	/**
 	 * @return Public key that must sign next update
 	 */
-	inline const C25519::Public &updatesMustBeSignedBy() const { return _updatesMustBeSignedBy; }
+	inline const C25519::Public& updatesMustBeSignedBy() const
+	{
+		return _updatesMustBeSignedBy;
+	}
 
 	/**
 	 * Check whether a world update should replace this one
@@ -146,15 +169,15 @@ public:
 	 * @param update Candidate update
 	 * @return True if update is newer than current, matches its ID and type, and is properly signed (or if current is NULL)
 	 */
-	inline bool shouldBeReplacedBy(const World &update)
+	inline bool shouldBeReplacedBy(const World& update)
 	{
-		if ((_id == 0)||(_type == TYPE_NULL)) {
+		if ((_id == 0) || (_type == TYPE_NULL)) {
 			return true;
 		}
-		if ((_id == update._id)&&(_ts < update._ts)&&(_type == update._type)) {
+		if ((_id == update._id) && (_ts < update._ts) && (_type == update._type)) {
 			Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> tmp;
-			update.serialize(tmp,true);
-			return C25519::verify(_updatesMustBeSignedBy,tmp.data(),tmp.size(),update._signature);
+			update.serialize(tmp, true);
+			return C25519::verify(_updatesMustBeSignedBy, tmp.data(), tmp.size(), update._signature);
 		}
 		return false;
 	}
@@ -162,10 +185,12 @@ public:
 	/**
 	 * @return True if this World is non-empty
 	 */
-	inline operator bool() const { return (_type != TYPE_NULL); }
+	inline operator bool() const
+	{
+		return (_type != TYPE_NULL);
+	}
 
-	template<unsigned int C>
-	inline void serialize(Buffer<C> &b,bool forSign = false) const
+	template <unsigned int C> inline void serialize(Buffer<C>& b, bool forSign = false) const
 	{
 		if (forSign) {
 			b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
@@ -174,20 +199,20 @@ public:
 		b.append((uint8_t)_type);
 		b.append((uint64_t)_id);
 		b.append((uint64_t)_ts);
-		b.append(_updatesMustBeSignedBy.data,ZT_C25519_PUBLIC_KEY_LEN);
-		if (!forSign) {
-			b.append(_signature.data,ZT_C25519_SIGNATURE_LEN);
+		b.append(_updatesMustBeSignedBy.data, ZT_C25519_PUBLIC_KEY_LEN);
+		if (! forSign) {
+			b.append(_signature.data, ZT_C25519_SIGNATURE_LEN);
 		}
 		b.append((uint8_t)_roots.size());
-		for(std::vector<Root>::const_iterator r(_roots.begin());r!=_roots.end();++r) {
+		for (std::vector<Root>::const_iterator r(_roots.begin()); r != _roots.end(); ++r) {
 			r->identity.serialize(b);
 			b.append((uint8_t)r->stableEndpoints.size());
-			for(std::vector<InetAddress>::const_iterator ep(r->stableEndpoints.begin());ep!=r->stableEndpoints.end();++ep) {
+			for (std::vector<InetAddress>::const_iterator ep(r->stableEndpoints.begin()); ep != r->stableEndpoints.end(); ++ep) {
 				ep->serialize(b);
 			}
 		}
 		if (_type == TYPE_MOON) {
-			b.append((uint16_t)0); // no attached dictionary (for future use)
+			b.append((uint16_t)0);	 // no attached dictionary (for future use)
 		}
 
 		if (forSign) {
@@ -195,15 +220,14 @@ public:
 		}
 	}
 
-	template<unsigned int C>
-	inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
+	template <unsigned int C> inline unsigned int deserialize(const Buffer<C>& b, unsigned int startAt = 0)
 	{
 		unsigned int p = startAt;
 
 		_roots.clear();
 
-		switch((Type)b[p++]) {
-			case TYPE_NULL: // shouldn't ever really happen in serialized data but it's not invalid
+		switch ((Type)b[p++]) {
+			case TYPE_NULL:	  // shouldn't ever really happen in serialized data but it's not invalid
 				_type = TYPE_NULL;
 				break;
 			case TYPE_PLANET:
@@ -220,25 +244,25 @@ public:
 		p += 8;
 		_ts = b.template at<uint64_t>(p);
 		p += 8;
-		memcpy(_updatesMustBeSignedBy.data,b.field(p,ZT_C25519_PUBLIC_KEY_LEN),ZT_C25519_PUBLIC_KEY_LEN);
+		memcpy(_updatesMustBeSignedBy.data, b.field(p, ZT_C25519_PUBLIC_KEY_LEN), ZT_C25519_PUBLIC_KEY_LEN);
 		p += ZT_C25519_PUBLIC_KEY_LEN;
-		memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN);
+		memcpy(_signature.data, b.field(p, ZT_C25519_SIGNATURE_LEN), ZT_C25519_SIGNATURE_LEN);
 		p += ZT_C25519_SIGNATURE_LEN;
 		const unsigned int numRoots = (unsigned int)b[p++];
 		if (numRoots > ZT_WORLD_MAX_ROOTS) {
 			throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
 		}
-		for(unsigned int k=0;k<numRoots;++k) {
+		for (unsigned int k = 0; k < numRoots; ++k) {
 			_roots.push_back(Root());
-			Root &r = _roots.back();
-			p += r.identity.deserialize(b,p);
+			Root& r = _roots.back();
+			p += r.identity.deserialize(b, p);
 			unsigned int numStableEndpoints = b[p++];
 			if (numStableEndpoints > ZT_WORLD_MAX_STABLE_ENDPOINTS_PER_ROOT) {
 				throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
 			}
-			for(unsigned int kk=0;kk<numStableEndpoints;++kk) {
+			for (unsigned int kk = 0; kk < numStableEndpoints; ++kk) {
 				r.stableEndpoints.push_back(InetAddress());
-				p += r.stableEndpoints.back().deserialize(b,p);
+				p += r.stableEndpoints.back().deserialize(b, p);
 			}
 		}
 		if (_type == TYPE_MOON) {
@@ -248,8 +272,16 @@ public:
 		return (p - startAt);
 	}
 
-	inline bool operator==(const World &w) const { return ((_id == w._id)&&(_ts == w._ts)&&(memcmp(_updatesMustBeSignedBy.data,w._updatesMustBeSignedBy.data,ZT_C25519_PUBLIC_KEY_LEN) == 0)&&(memcmp(_signature.data,w._signature.data,ZT_C25519_SIGNATURE_LEN) == 0)&&(_roots == w._roots)&&(_type == w._type)); }
-	inline bool operator!=(const World &w) const { return (!(*this == w)); }
+	inline bool operator==(const World& w) const
+	{
+		return (
+			(_id == w._id) && (_ts == w._ts) && (memcmp(_updatesMustBeSignedBy.data, w._updatesMustBeSignedBy.data, ZT_C25519_PUBLIC_KEY_LEN) == 0) && (memcmp(_signature.data, w._signature.data, ZT_C25519_SIGNATURE_LEN) == 0)
+			&& (_roots == w._roots) && (_type == w._type));
+	}
+	inline bool operator!=(const World& w) const
+	{
+		return (! (*this == w));
+	}
 
 	/**
 	 * Create a World object signed with a key pair
@@ -262,7 +294,7 @@ public:
 	 * @param signWith Key to sign this World with (can have the same public as the next-update signing key, but doesn't have to)
 	 * @return Signed World object
 	 */
-	static inline World make(World::Type t,uint64_t id,uint64_t ts,const C25519::Public &sk,const std::vector<World::Root> &roots,const C25519::Pair &signWith)
+	static inline World make(World::Type t, uint64_t id, uint64_t ts, const C25519::Public& sk, const std::vector<World::Root>& roots, const C25519::Pair& signWith)
 	{
 		World w;
 		w._id = id;
@@ -272,13 +304,13 @@ public:
 		w._roots = roots;
 
 		Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> tmp;
-		w.serialize(tmp,true);
-		w._signature = C25519::sign(signWith,tmp.data(),tmp.size());
+		w.serialize(tmp, true);
+		w._signature = C25519::sign(signWith, tmp.data(), tmp.size());
 
 		return w;
 	}
 
-protected:
+  protected:
 	uint64_t _id;
 	uint64_t _ts;
 	Type _type;
@@ -287,6 +319,6 @@ protected:
 	std::vector<Root> _roots;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 51 - 46
osdep/Arp.cpp

@@ -11,29 +11,28 @@
  */
 /****/
 
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
 #include "Arp.hpp"
+
 #include "OSUtils.hpp"
 
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
 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(256),
-	_lastCleaned(OSUtils::now())
+Arp::Arp() : _cache(256), _lastCleaned(OSUtils::now())
 {
 }
 
-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
-	e.lastResponseReceived = 0; // local IP
+	_ArpEntry& e = _cache[ip];
+	e.lastQuerySent = 0;		  // local IP
+	e.lastResponseReceived = 0;	  // local IP
 	e.mac = mac;
 	e.local = true;
 }
@@ -43,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;
@@ -52,25 +51,26 @@ 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,6);
-				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);
+			_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, 6);
+				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,6);
+				responseDest.setTo(reinterpret_cast<const uint8_t*>(arp) + 8, 6);
 			}
-		} 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)) {
+			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,6);
+				queryEntry->mac.setTo(reinterpret_cast<const uint8_t*>(arp) + 8, 6);
 				ip = responseIp;
 			}
 		}
@@ -78,11 +78,11 @@ uint32_t Arp::processIncomingArp(const void *arp,unsigned int len,void *response
 
 	if ((now - _lastCleaned) >= ZT_ARP_EXPIRE) {
 		_lastCleaned = now;
-		Hashtable< uint32_t,_ArpEntry >::Iterator i(_cache);
-		uint32_t *k = (uint32_t *)0;
-		_ArpEntry *v = (_ArpEntry *)0;
-		while (i.next(k,v)) {
-			if ((!v->local)&&((now - v->lastResponseReceived) >= ZT_ARP_EXPIRE))
+		Hashtable<uint32_t, _ArpEntry>::Iterator i(_cache);
+		uint32_t* k = (uint32_t*)0;
+		_ArpEntry* v = (_ArpEntry*)0;
+		while (i.next(k, v)) {
+			if ((! v->local) && ((now - v->lastResponseReceived) >= ZT_ARP_EXPIRE))
 				_cache.erase(*k);
 		}
 	}
@@ -90,27 +90,32 @@ 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];
+	_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,6); 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)
+		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, 6);
+		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
-		else queryDest = (uint64_t)0xffffffffffffULL; // broadcast query
-	} else {
+			queryDest = e.mac;	 // confirmation query, send directly to address holder
+		else
+			queryDest = (uint64_t)0xffffffffffffULL;   // broadcast query
+	}
+	else {
 		queryLen = 0;
 		queryDest.zero();
 	}
@@ -118,4 +123,4 @@ MAC Arp::query(const MAC &localMac,uint32_t localIp,uint32_t targetIp,void *quer
 	return e.mac;
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier

+ 21 - 22
osdep/Arp.hpp

@@ -14,14 +14,13 @@
 #ifndef ZT_ARP_HPP
 #define ZT_ARP_HPP
 
-#include <stdint.h>
-
-#include <utility>
-
 #include "../node/Constants.hpp"
 #include "../node/Hashtable.hpp"
 #include "../node/MAC.hpp"
 
+#include <stdint.h>
+#include <utility>
+
 /**
  * Maximum possible ARP length
  *
@@ -67,9 +66,8 @@ namespace ZeroTier {
  * This class is not thread-safe and must be guarded if used in multi-threaded
  * code.
  */
-class Arp
-{
-public:
+class Arp {
+  public:
 	Arp();
 
 	/**
@@ -78,7 +76,7 @@ public:
 	 * @param mac Our local MAC address
 	 * @param ip IP in big-endian byte order (sin_addr.s_addr)
 	 */
-	void addLocal(uint32_t ip,const MAC &mac);
+	void addLocal(uint32_t ip, const MAC& mac);
 
 	/**
 	 * Delete a local IP entry or a cached ARP entry
@@ -103,7 +101,7 @@ public:
 	 * @param responseDest Destination of response, or set to null if no response
 	 * @return IP address learned or 0 if no new IPs in cache
 	 */
-	uint32_t processIncomingArp(const void *arp,unsigned int len,void *response,unsigned int &responseLen,MAC &responseDest);
+	uint32_t processIncomingArp(const void* arp, unsigned int len, void* response, unsigned int& responseLen, MAC& responseDest);
 
 	/**
 	 * Get the MAC corresponding to an IP, generating a query if needed
@@ -115,29 +113,30 @@ public:
 	 * MAC returned is non-null.
 	 *
 	 * @param localMac Local MAC address of host interface
-     * @param localIp Local IP address of host interface
+	 * @param localIp Local IP address of host interface
 	 * @param targetIp IP to look up
 	 * @param query Buffer for generated query -- MUST be a minimum of ZT_ARP_BUF_LENGTH in size
 	 * @param queryLen Length of generated query, or set to 0 if no query generated
 	 * @param queryDest Destination of query, or set to null if no query generated
 	 * @return MAC or 0 if no cached entry for this IP
 	 */
-	MAC query(const MAC &localMac,uint32_t localIp,uint32_t targetIp,void *query,unsigned int &queryLen,MAC &queryDest);
-
-private:
-	struct _ArpEntry
-	{
-		_ArpEntry() : lastQuerySent(0),lastResponseReceived(0),mac(),local(false) {}
-		uint64_t lastQuerySent; // Time last query was sent or 0 for local IP
-		uint64_t lastResponseReceived; // Time of last ARP response or 0 for local IP
-		MAC mac; // MAC address of device responsible for IP or null if not known yet
-		bool local; // True if this is a local ARP entry
+	MAC query(const MAC& localMac, uint32_t localIp, uint32_t targetIp, void* query, unsigned int& queryLen, MAC& queryDest);
+
+  private:
+	struct _ArpEntry {
+		_ArpEntry() : lastQuerySent(0), lastResponseReceived(0), mac(), local(false)
+		{
+		}
+		uint64_t lastQuerySent;			 // Time last query was sent or 0 for local IP
+		uint64_t lastResponseReceived;	 // Time of last ARP response or 0 for local IP
+		MAC mac;						 // MAC address of device responsible for IP or null if not known yet
+		bool local;						 // True if this is a local ARP entry
 	};
 
-	Hashtable< uint32_t,_ArpEntry > _cache;
+	Hashtable<uint32_t, _ArpEntry> _cache;
 	uint64_t _lastCleaned;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 175 - 167
osdep/BSDEthernetTap.cpp

@@ -11,81 +11,78 @@
  */
 /****/
 
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
+#include "BSDEthernetTap.hpp"
 
-#include <unistd.h>
-#include <signal.h>
+#include "../node/Constants.hpp"
+#include "../node/Mutex.hpp"
+#include "../node/Utils.hpp"
+#include "OSUtils.hpp"
 
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/wait.h>
-#include <sys/select.h>
-#include <sys/cdefs.h>
-#include <sys/uio.h>
-#include <sys/param.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
+#include <algorithm>
 #include <arpa/inet.h>
-#include <net/if.h>
+#include <errno.h>
+#include <fcntl.h>
 #include <ifaddrs.h>
+#include <map>
+#include <net/if.h>
 #include <net/if_arp.h>
 #include <net/if_dl.h>
 #include <net/if_media.h>
 #include <net/route.h>
+#include <netinet/in.h>
 #include <pthread_np.h>
-
 #include <sched.h>
-#include <string>
-#include <map>
 #include <set>
-#include <algorithm>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <string>
+#include <sys/cdefs.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/wait.h>
+#include <unistd.h>
 #include <utility>
 
-#include "../node/Constants.hpp"
-#include "../node/Utils.hpp"
-#include "../node/Mutex.hpp"
-#include "OSUtils.hpp"
-#include "BSDEthernetTap.hpp"
-
 #define ZT_BASE32_CHARS "0123456789abcdefghijklmnopqrstuv"
 #define ZT_TAP_BUF_SIZE (1024 * 16)
 
 // ff:ff:ff:ff:ff:ff with no ADI
-static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff),0);
+static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff), 0);
 
 namespace ZeroTier {
 
 BSDEthernetTap::BSDEthernetTap(
-	const char *homePath,
+	const char* homePath,
 	unsigned int concurrency,
 	bool pinning,
-	const MAC &mac,
+	const MAC& mac,
 	unsigned int mtu,
 	unsigned int metric,
 	uint64_t nwid,
-	const char *friendlyName,
-	void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
-	void *arg) :
-	_handler(handler),
-	_concurrency(concurrency),
-	_pinning(pinning),
-	_arg(arg),
-	_nwid(nwid),
-	_mtu(mtu),
-	_metric(metric),
-	_fd(0),
-	_enabled(true),
-	_lastIfAddrsUpdate(0)
+	const char* friendlyName,
+	void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int),
+	void* arg)
+	: _handler(handler)
+	, _concurrency(concurrency)
+	, _pinning(pinning)
+	, _arg(arg)
+	, _nwid(nwid)
+	, _mtu(mtu)
+	, _metric(metric)
+	, _fd(0)
+	, _enabled(true)
+	, _lastIfAddrsUpdate(0)
 {
 	static Mutex globalTapCreateLock;
-	char devpath[64],ethaddr[64],mtustr[32],metstr[32],tmpdevname[32];
+	char devpath[64], ethaddr[64], mtustr[32], metstr[32], tmpdevname[32];
 
 	Mutex::Lock _gl(globalTapCreateLock);
 
@@ -108,43 +105,51 @@ BSDEthernetTap::BSDEthernetTap(
 	_dev.push_back(ZT_BASE32_CHARS[(unsigned long)(nwid & 0x1f)]);
 
 	std::vector<std::string> devFiles(OSUtils::listDirectory("/dev"));
-	for(int i=9993;i<(9993+128);++i) {
-		OSUtils::ztsnprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i);
-		OSUtils::ztsnprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname);
-		if (std::find(devFiles.begin(),devFiles.end(),std::string(tmpdevname)) == devFiles.end()) {
+	for (int i = 9993; i < (9993 + 128); ++i) {
+		OSUtils::ztsnprintf(tmpdevname, sizeof(tmpdevname), "tap%d", i);
+		OSUtils::ztsnprintf(devpath, sizeof(devpath), "/dev/%s", tmpdevname);
+		if (std::find(devFiles.begin(), devFiles.end(), std::string(tmpdevname)) == devFiles.end()) {
 			long cpid = (long)vfork();
 			if (cpid == 0) {
 #ifdef ZT_TRACE
 				fprintf(stderr, "DEBUG: ifconfig %s create" ZT_EOL_S, tmpdevname);
 #endif
-				::execl("/sbin/ifconfig","/sbin/ifconfig",tmpdevname,"create",(const char *)0);
+				::execl("/sbin/ifconfig", "/sbin/ifconfig", tmpdevname, "create", (const char*)0);
 				::_exit(-1);
-			} else if (cpid > 0) {
+			}
+			else if (cpid > 0) {
 				int exitcode = -1;
-				::waitpid(cpid,&exitcode,0);
-			} else throw std::runtime_error("fork() failed");
+				::waitpid(cpid, &exitcode, 0);
+			}
+			else
+				throw std::runtime_error("fork() failed");
 
 			struct stat stattmp;
-			if (!stat(devpath,&stattmp)) {
+			if (! stat(devpath, &stattmp)) {
 				cpid = (long)vfork();
 				if (cpid == 0) {
 #ifdef ZT_TRACE
 					fprintf(stderr, "DEBUG: ifconfig %s name %s" ZT_EOL_S, tmpdevname, _dev.c_str());
 #endif
-					::execl("/sbin/ifconfig","/sbin/ifconfig",tmpdevname,"name",_dev.c_str(),(const char *)0);
+					::execl("/sbin/ifconfig", "/sbin/ifconfig", tmpdevname, "name", _dev.c_str(), (const char*)0);
 					::_exit(-1);
-				} else if (cpid > 0) {
+				}
+				else if (cpid > 0) {
 					int exitcode = -1;
-					::waitpid(cpid,&exitcode,0);
+					::waitpid(cpid, &exitcode, 0);
 					if (exitcode)
 						throw std::runtime_error("ifconfig rename operation failed");
-				} else throw std::runtime_error("fork() failed");
+				}
+				else
+					throw std::runtime_error("fork() failed");
 
-				_fd = ::open(devpath,O_RDWR);
+				_fd = ::open(devpath, O_RDWR);
 				if (_fd > 0)
 					break;
-				else throw std::runtime_error("unable to open created tap device");
-			} else {
+				else
+					throw std::runtime_error("unable to open created tap device");
+			}
+			else {
 				throw std::runtime_error("cannot find /dev node for newly created tap device");
 			}
 		}
@@ -152,10 +157,10 @@ BSDEthernetTap::BSDEthernetTap(
 #else
 	/* Other BSDs like OpenBSD only have a limited number of tap devices that cannot be renamed */
 
-	for(int i=0;i<64;++i) {
-		OSUtils::ztsnprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i);
-		OSUtils::ztsnprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname);
-		_fd = ::open(devpath,O_RDWR);
+	for (int i = 0; i < 64; ++i) {
+		OSUtils::ztsnprintf(tmpdevname, sizeof(tmpdevname), "tap%d", i);
+		OSUtils::ztsnprintf(devpath, sizeof(devpath), "/dev/%s", tmpdevname);
+		_fd = ::open(devpath, O_RDWR);
 		if (_fd > 0) {
 			_dev = tmpdevname;
 			break;
@@ -166,25 +171,26 @@ BSDEthernetTap::BSDEthernetTap(
 	if (_fd <= 0)
 		throw std::runtime_error("unable to open TAP device or no more devices available");
 
-	if (fcntl(_fd,F_SETFL,fcntl(_fd,F_GETFL) & ~O_NONBLOCK) == -1) {
+	if (fcntl(_fd, F_SETFL, fcntl(_fd, F_GETFL) & ~O_NONBLOCK) == -1) {
 		::close(_fd);
 		throw std::runtime_error("unable to set flags on file descriptor for TAP device");
 	}
 
 	// Configure MAC address and MTU, bring interface up
-	OSUtils::ztsnprintf(ethaddr,sizeof(ethaddr),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)mac[0],(int)mac[1],(int)mac[2],(int)mac[3],(int)mac[4],(int)mac[5]);
-	OSUtils::ztsnprintf(mtustr,sizeof(mtustr),"%u",_mtu);
-	OSUtils::ztsnprintf(metstr,sizeof(metstr),"%u",_metric);
+	OSUtils::ztsnprintf(ethaddr, sizeof(ethaddr), "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", (int)mac[0], (int)mac[1], (int)mac[2], (int)mac[3], (int)mac[4], (int)mac[5]);
+	OSUtils::ztsnprintf(mtustr, sizeof(mtustr), "%u", _mtu);
+	OSUtils::ztsnprintf(metstr, sizeof(metstr), "%u", _metric);
 	long cpid = (long)vfork();
 	if (cpid == 0) {
 #ifdef ZT_TRACE
 		fprintf(stderr, "DEBUG: ifconfig %s lladdr %s mtu %s metric %s up" ZT_EOL_S, _dev.c_str(), ethaddr, mtustr, metstr);
 #endif
-		::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"lladdr",ethaddr,"mtu",mtustr,"metric",metstr,"up",(const char *)0);
+		::execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), "lladdr", ethaddr, "mtu", mtustr, "metric", metstr, "up", (const char*)0);
 		::_exit(-1);
-	} else if (cpid > 0) {
+	}
+	else if (cpid > 0) {
 		int exitcode = -1;
-		::waitpid(cpid,&exitcode,0);
+		::waitpid(cpid, &exitcode, 0);
 		if (exitcode) {
 			::close(_fd);
 			throw std::runtime_error("ifconfig failure setting link-layer address and activating tap interface");
@@ -192,7 +198,7 @@ BSDEthernetTap::BSDEthernetTap(
 	}
 
 	// Set close-on-exec so that devices cannot persist if we fork/exec for update
-	fcntl(_fd,F_SETFD,fcntl(_fd,F_GETFD) | FD_CLOEXEC);
+	fcntl(_fd, F_SETFD, fcntl(_fd, F_GETFD) | FD_CLOEXEC);
 
 	::pipe(_shutdownSignalPipe);
 
@@ -201,23 +207,24 @@ BSDEthernetTap::BSDEthernetTap(
 
 BSDEthernetTap::~BSDEthernetTap()
 {
-	::write(_shutdownSignalPipe[1],"\0",1); // causes thread to exit
+	::write(_shutdownSignalPipe[1], "\0", 1);	// causes thread to exit
 	::close(_fd);
 	::close(_shutdownSignalPipe[0]);
 	::close(_shutdownSignalPipe[1]);
 	long cpid = (long)vfork();
 	if (cpid == 0) {
 #ifdef ZT_TRACE
-			fprintf(stderr, "DEBUG: ifconfig %s destroy" ZT_EOL_S, _dev.c_str());
+		fprintf(stderr, "DEBUG: ifconfig %s destroy" ZT_EOL_S, _dev.c_str());
 #endif
-		::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"destroy",(const char *)0);
+		::execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), "destroy", (const char*)0);
 		::_exit(-1);
-	} else if (cpid > 0) {
+	}
+	else if (cpid > 0) {
 		int exitcode = -1;
-		::waitpid(cpid,&exitcode,0);
+		::waitpid(cpid, &exitcode, 0);
 	}
 	Thread::join(_thread);
-	for (std::thread &t : _rxThreads) {
+	for (std::thread& t : _rxThreads) {
 		t.join();
 	}
 }
@@ -232,7 +239,7 @@ bool BSDEthernetTap::enabled() const
 	return _enabled;
 }
 
-static bool ___removeIp(const std::string &_dev,const InetAddress &ip)
+static bool ___removeIp(const std::string& _dev, const InetAddress& ip)
 {
 	long cpid = (long)vfork();
 	if (cpid == 0) {
@@ -240,29 +247,30 @@ static bool ___removeIp(const std::string &_dev,const InetAddress &ip)
 #ifdef ZT_TRACE
 		fprintf(stderr, "DEBUG: ifconfig %s inet %s -alias" ZT_EOL_S, _dev.c_str(), ip.toIpString(ipbuf));
 #endif
-		execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"inet",ip.toIpString(ipbuf),"-alias",(const char *)0);
+		execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), "inet", ip.toIpString(ipbuf), "-alias", (const char*)0);
 		_exit(-1);
-	} else if (cpid > 0) {
+	}
+	else if (cpid > 0) {
 		int exitcode = -1;
-		waitpid(cpid,&exitcode,0);
+		waitpid(cpid, &exitcode, 0);
 		return (exitcode == 0);
 	}
-	return false; // never reached, make compiler shut up about return value
+	return false;	// never reached, make compiler shut up about return value
 }
 
-bool BSDEthernetTap::addIp(const InetAddress &ip)
+bool BSDEthernetTap::addIp(const InetAddress& ip)
 {
-	if (!ip)
+	if (! ip)
 		return false;
 
 	std::vector<InetAddress> allIps(ips());
-	if (std::find(allIps.begin(),allIps.end(),ip) != allIps.end())
-		return true; // IP/netmask already assigned
+	if (std::find(allIps.begin(), allIps.end(), ip) != allIps.end())
+		return true;   // IP/netmask already assigned
 
 	// Remove and reconfigure if address is the same but netmask is different
-	for(std::vector<InetAddress>::iterator i(allIps.begin());i!=allIps.end();++i) {
-		if ((i->ipsEqual(ip))&&(i->netmaskBits() != ip.netmaskBits())) {
-			if (___removeIp(_dev,*i))
+	for (std::vector<InetAddress>::iterator i(allIps.begin()); i != allIps.end(); ++i) {
+		if ((i->ipsEqual(ip)) && (i->netmaskBits() != ip.netmaskBits())) {
+			if (___removeIp(_dev, *i))
 				break;
 		}
 	}
@@ -273,23 +281,24 @@ bool BSDEthernetTap::addIp(const InetAddress &ip)
 #ifdef ZT_TRACE
 		fprintf(stderr, "DEBUG: ifconfig %s %s %s alias" ZT_EOL_S, _dev.c_str(), ip.isV4() ? "inet" : "inet6", ip.toString(tmp));
 #endif
-		::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),ip.isV4() ? "inet" : "inet6",ip.toString(tmp),"alias",(const char *)0);
+		::execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), ip.isV4() ? "inet" : "inet6", ip.toString(tmp), "alias", (const char*)0);
 		::_exit(-1);
-	} else if (cpid > 0) {
+	}
+	else if (cpid > 0) {
 		int exitcode = -1;
-		::waitpid(cpid,&exitcode,0);
+		::waitpid(cpid, &exitcode, 0);
 		return (exitcode == 0);
 	}
 	return false;
 }
 
-bool BSDEthernetTap::removeIp(const InetAddress &ip)
+bool BSDEthernetTap::removeIp(const InetAddress& ip)
 {
-	if (!ip)
+	if (! ip)
 		return false;
 	std::vector<InetAddress> allIps(ips());
-	if (std::find(allIps.begin(),allIps.end(),ip) != allIps.end()) {
-		if (___removeIp(_dev,ip))
+	if (std::find(allIps.begin(), allIps.end(), ip) != allIps.end()) {
+		if (___removeIp(_dev, ip))
 			return true;
 	}
 	return false;
@@ -304,28 +313,28 @@ std::vector<InetAddress> BSDEthernetTap::ips() const
 	}
 	_lastIfAddrsUpdate = now;
 
-	struct ifaddrs *ifa = (struct ifaddrs *)0;
+	struct ifaddrs* ifa = (struct ifaddrs*)0;
 	if (getifaddrs(&ifa))
 		return std::vector<InetAddress>();
 
 	std::vector<InetAddress> r;
 
-	struct ifaddrs *p = ifa;
+	struct ifaddrs* p = ifa;
 	while (p) {
-		if ((!strcmp(p->ifa_name,_dev.c_str()))&&(p->ifa_addr)&&(p->ifa_netmask)&&(p->ifa_addr->sa_family == p->ifa_netmask->sa_family)) {
-			switch(p->ifa_addr->sa_family) {
+		if ((! strcmp(p->ifa_name, _dev.c_str())) && (p->ifa_addr) && (p->ifa_netmask) && (p->ifa_addr->sa_family == p->ifa_netmask->sa_family)) {
+			switch (p->ifa_addr->sa_family) {
 				case AF_INET: {
-					struct sockaddr_in *sin = (struct sockaddr_in *)p->ifa_addr;
-					struct sockaddr_in *nm = (struct sockaddr_in *)p->ifa_netmask;
-					r.push_back(InetAddress(&(sin->sin_addr.s_addr),4,Utils::countBits((uint32_t)nm->sin_addr.s_addr)));
-				}	break;
+					struct sockaddr_in* sin = (struct sockaddr_in*)p->ifa_addr;
+					struct sockaddr_in* nm = (struct sockaddr_in*)p->ifa_netmask;
+					r.push_back(InetAddress(&(sin->sin_addr.s_addr), 4, Utils::countBits((uint32_t)nm->sin_addr.s_addr)));
+				} break;
 				case AF_INET6: {
-					struct sockaddr_in6 *sin = (struct sockaddr_in6 *)p->ifa_addr;
-					struct sockaddr_in6 *nm = (struct sockaddr_in6 *)p->ifa_netmask;
+					struct sockaddr_in6* sin = (struct sockaddr_in6*)p->ifa_addr;
+					struct sockaddr_in6* nm = (struct sockaddr_in6*)p->ifa_netmask;
 					uint32_t b[4];
-					memcpy(b,nm->sin6_addr.s6_addr,sizeof(b));
-					r.push_back(InetAddress(sin->sin6_addr.s6_addr,16,Utils::countBits(b[0]) + Utils::countBits(b[1]) + Utils::countBits(b[2]) + Utils::countBits(b[3])));
-				}	break;
+					memcpy(b, nm->sin6_addr.s6_addr, sizeof(b));
+					r.push_back(InetAddress(sin->sin6_addr.s6_addr, 16, Utils::countBits(b[0]) + Utils::countBits(b[1]) + Utils::countBits(b[2]) + Utils::countBits(b[3])));
+				} break;
 			}
 		}
 		p = p->ifa_next;
@@ -334,24 +343,24 @@ std::vector<InetAddress> BSDEthernetTap::ips() const
 	if (ifa)
 		freeifaddrs(ifa);
 
-	std::sort(r.begin(),r.end());
-	std::unique(r.begin(),r.end());
+	std::sort(r.begin(), r.end());
+	std::unique(r.begin(), r.end());
 
 	_ifaddrs = r;
 
 	return r;
 }
 
-void BSDEthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len)
+void BSDEthernetTap::put(const MAC& from, const MAC& to, unsigned int etherType, const void* data, unsigned int len)
 {
 	char putBuf[ZT_MAX_MTU + 64];
-	if ((_fd > 0)&&(len <= _mtu)&&(_enabled)) {
-		to.copyTo(putBuf,6);
-		from.copyTo(putBuf + 6,6);
-		*((uint16_t *)(putBuf + 12)) = htons((uint16_t)etherType);
-		memcpy(putBuf + 14,data,len);
+	if ((_fd > 0) && (len <= _mtu) && (_enabled)) {
+		to.copyTo(putBuf, 6);
+		from.copyTo(putBuf + 6, 6);
+		*((uint16_t*)(putBuf + 12)) = htons((uint16_t)etherType);
+		memcpy(putBuf + 14, data, len);
 		len += 14;
-		::write(_fd,putBuf,len);
+		::write(_fd, putBuf, len);
 	}
 }
 
@@ -360,44 +369,44 @@ std::string BSDEthernetTap::deviceName() const
 	return _dev;
 }
 
-void BSDEthernetTap::setFriendlyName(const char *friendlyName)
+void BSDEthernetTap::setFriendlyName(const char* friendlyName)
 {
 }
 
-void BSDEthernetTap::scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed)
+void BSDEthernetTap::scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed)
 {
 	std::vector<MulticastGroup> newGroups;
 
 #ifndef __OpenBSD__
-	struct ifmaddrs *ifmap = (struct ifmaddrs *)0;
-	if (!getifmaddrs(&ifmap)) {
-		struct ifmaddrs *p = ifmap;
+	struct ifmaddrs* ifmap = (struct ifmaddrs*)0;
+	if (! getifmaddrs(&ifmap)) {
+		struct ifmaddrs* p = ifmap;
 		while (p) {
 			if (p->ifma_addr->sa_family == AF_LINK) {
-				struct sockaddr_dl *in = (struct sockaddr_dl *)p->ifma_name;
-				struct sockaddr_dl *la = (struct sockaddr_dl *)p->ifma_addr;
-				if ((la->sdl_alen == 6)&&(in->sdl_nlen <= _dev.length())&&(!memcmp(_dev.data(),in->sdl_data,in->sdl_nlen)))
-					newGroups.push_back(MulticastGroup(MAC(la->sdl_data + la->sdl_nlen,6),0));
+				struct sockaddr_dl* in = (struct sockaddr_dl*)p->ifma_name;
+				struct sockaddr_dl* la = (struct sockaddr_dl*)p->ifma_addr;
+				if ((la->sdl_alen == 6) && (in->sdl_nlen <= _dev.length()) && (! memcmp(_dev.data(), in->sdl_data, in->sdl_nlen)))
+					newGroups.push_back(MulticastGroup(MAC(la->sdl_data + la->sdl_nlen, 6), 0));
 			}
 			p = p->ifma_next;
 		}
 		freeifmaddrs(ifmap);
 	}
-#endif // __OpenBSD__
+#endif	 // __OpenBSD__
 
 	std::vector<InetAddress> allIps(ips());
-	for(std::vector<InetAddress>::iterator ip(allIps.begin());ip!=allIps.end();++ip)
+	for (std::vector<InetAddress>::iterator ip(allIps.begin()); ip != allIps.end(); ++ip)
 		newGroups.push_back(MulticastGroup::deriveMulticastGroupForAddressResolution(*ip));
 
-	std::sort(newGroups.begin(),newGroups.end());
-	std::unique(newGroups.begin(),newGroups.end());
+	std::sort(newGroups.begin(), newGroups.end());
+	std::unique(newGroups.begin(), newGroups.end());
 
-	for(std::vector<MulticastGroup>::iterator m(newGroups.begin());m!=newGroups.end();++m) {
-		if (!std::binary_search(_multicastGroups.begin(),_multicastGroups.end(),*m))
+	for (std::vector<MulticastGroup>::iterator m(newGroups.begin()); m != newGroups.end(); ++m) {
+		if (! std::binary_search(_multicastGroups.begin(), _multicastGroups.end(), *m))
 			added.push_back(*m);
 	}
-	for(std::vector<MulticastGroup>::iterator m(_multicastGroups.begin());m!=_multicastGroups.end();++m) {
-		if (!std::binary_search(newGroups.begin(),newGroups.end(),*m))
+	for (std::vector<MulticastGroup>::iterator m(_multicastGroups.begin()); m != _multicastGroups.end(); ++m) {
+		if (! std::binary_search(newGroups.begin(), newGroups.end(), *m))
 			removed.push_back(*m);
 	}
 
@@ -411,21 +420,21 @@ void BSDEthernetTap::setMtu(unsigned int mtu)
 		long cpid = (long)vfork();
 		if (cpid == 0) {
 			char tmp[64];
-			OSUtils::ztsnprintf(tmp,sizeof(tmp),"%u",mtu);
+			OSUtils::ztsnprintf(tmp, sizeof(tmp), "%u", mtu);
 #ifdef ZT_TRACE
 			fprintf(stderr, "DEBUG: ifconfig %s mtu %s" ZT_EOL_S, _dev.c_str(), tmp);
 #endif
-			execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"mtu",tmp,(const char *)0);
+			execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), "mtu", tmp, (const char*)0);
 			_exit(-1);
-		} else if (cpid > 0) {
+		}
+		else if (cpid > 0) {
 			int exitcode = -1;
-			waitpid(cpid,&exitcode,0);
+			waitpid(cpid, &exitcode, 0);
 		}
 	}
 }
 
-void BSDEthernetTap::threadMain()
-	throw()
+void BSDEthernetTap::threadMain() throw()
 {
 	// Wait for a moment after startup -- wait for Network to finish
 	// constructing itself.
@@ -436,7 +445,6 @@ void BSDEthernetTap::threadMain()
 
 	for (unsigned int i = 0; i < _concurrency; ++i) {
 		_rxThreads.push_back(std::thread([this, i, pinning] {
-
 			if (pinning) {
 				int pinCore = i % _concurrency;
 				fprintf(stderr, "Pinning thread %d to core %d\n", i, pinCore);
@@ -444,15 +452,14 @@ void BSDEthernetTap::threadMain()
 				cpu_set_t cpuset;
 				CPU_ZERO(&cpuset);
 				CPU_SET(pinCore, &cpuset);
-				//int rc = sched_setaffinity(self, sizeof(cpu_set_t), &cpuset);
+				// int rc = sched_setaffinity(self, sizeof(cpu_set_t), &cpuset);
 				int rc = pthread_setaffinity_np(self, sizeof(cpu_set_t), &cpuset);
-				if (rc != 0)
-				{
+				if (rc != 0) {
 					fprintf(stderr, "Failed to pin thread %d to core %d: %s\n", i, pinCore, strerror(errno));
 					exit(1);
 				}
 			}
-#endif // __OpenBSD__
+#endif	 // __OpenBSD__
 
 			uint8_t b[ZT_TAP_BUF_SIZE];
 			MAC to, from;
@@ -461,37 +468,38 @@ void BSDEthernetTap::threadMain()
 
 			FD_ZERO(&readfds);
 			FD_ZERO(&nullfds);
-			nfds = (int)std::max(_shutdownSignalPipe[0],_fd) + 1;
+			nfds = (int)std::max(_shutdownSignalPipe[0], _fd) + 1;
 
 			r = 0;
 
-			for(;;) {
-				FD_SET(_shutdownSignalPipe[0],&readfds);
-				FD_SET(_fd,&readfds);
-				select(nfds,&readfds,&nullfds,&nullfds,(struct timeval *)0);
+			for (;;) {
+				FD_SET(_shutdownSignalPipe[0], &readfds);
+				FD_SET(_fd, &readfds);
+				select(nfds, &readfds, &nullfds, &nullfds, (struct timeval*)0);
 
-				if (FD_ISSET(_shutdownSignalPipe[0],&readfds)) // writes to shutdown pipe terminate thread
+				if (FD_ISSET(_shutdownSignalPipe[0], &readfds))	  // writes to shutdown pipe terminate thread
 					break;
 
-				if (FD_ISSET(_fd,&readfds)) {
-					n = (int)::read(_fd,b + r,sizeof(b) - r);
+				if (FD_ISSET(_fd, &readfds)) {
+					n = (int)::read(_fd, b + r, sizeof(b) - r);
 					if (n < 0) {
-						if ((errno != EINTR)&&(errno != ETIMEDOUT))
+						if ((errno != EINTR) && (errno != ETIMEDOUT))
 							break;
-					} else {
+					}
+					else {
 						// Some tap drivers like to send the ethernet frame and the
 						// payload in two chunks, so handle that by accumulating
 						// data until we have at least a frame.
 						r += n;
 						if (r > 14) {
-							if (r > ((int)_mtu + 14)) // sanity check for weird TAP behavior on some platforms
+							if (r > ((int)_mtu + 14))	// sanity check for weird TAP behavior on some platforms
 								r = _mtu + 14;
 
 							if (_enabled) {
-								to.setTo(b,6);
-								from.setTo(b + 6,6);
-								unsigned int etherType = ntohs(((const uint16_t *)b)[6]);
-								_handler(_arg,(void *)0,_nwid,from,to,etherType,0,(const void *)(b + 14),r - 14);
+								to.setTo(b, 6);
+								from.setTo(b + 6, 6);
+								unsigned int etherType = ntohs(((const uint16_t*)b)[6]);
+								_handler(_arg, (void*)0, _nwid, from, to, etherType, 0, (const void*)(b + 14), r - 14);
 							}
 
 							r = 0;
@@ -502,7 +510,7 @@ void BSDEthernetTap::threadMain()
 #ifndef __OpenBSD__
 		}));
 	}
-#endif // __OpenBSD__
+#endif	 // __OpenBSD__
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier

+ 28 - 29
osdep/BSDEthernetTap.hpp

@@ -14,57 +14,56 @@
 #ifndef ZT_BSDETHERNETTAP_HPP
 #define ZT_BSDETHERNETTAP_HPP
 
+#include "../node/Constants.hpp"
+#include "../node/MAC.hpp"
+#include "../node/MulticastGroup.hpp"
+#include "EthernetTap.hpp"
+#include "Thread.hpp"
+
+#include <stdexcept>
 #include <stdio.h>
 #include <stdlib.h>
-
 #include <string>
-#include <vector>
-#include <stdexcept>
 #include <thread>
-
-#include "../node/Constants.hpp"
-#include "../node/MulticastGroup.hpp"
-#include "../node/MAC.hpp"
-#include "Thread.hpp"
-#include "EthernetTap.hpp"
+#include <vector>
 
 namespace ZeroTier {
 
-class BSDEthernetTap : public EthernetTap
-{
-public:
+class BSDEthernetTap : public EthernetTap {
+  public:
 	BSDEthernetTap(
-		const char *homePath,
+		const char* homePath,
 		unsigned int concurrency,
 		bool pinning,
-		const MAC &mac,
+		const MAC& mac,
 		unsigned int mtu,
 		unsigned int metric,
 		uint64_t nwid,
-		const char *friendlyName,
-		void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
-		void *arg);
+		const char* friendlyName,
+		void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int),
+		void* arg);
 
 	virtual ~BSDEthernetTap();
 
 	virtual void setEnabled(bool en);
 	virtual bool enabled() const;
-	virtual bool addIp(const InetAddress &ip);
-	virtual bool removeIp(const InetAddress &ip);
+	virtual bool addIp(const InetAddress& ip);
+	virtual bool removeIp(const InetAddress& ip);
 	virtual std::vector<InetAddress> ips() const;
-	virtual void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len);
+	virtual void put(const MAC& from, const MAC& to, unsigned int etherType, const void* data, unsigned int len);
 	virtual std::string deviceName() const;
-	virtual void setFriendlyName(const char *friendlyName);
-	virtual void scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed);
+	virtual void setFriendlyName(const char* friendlyName);
+	virtual void scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed);
 	virtual void setMtu(unsigned int mtu);
-	virtual void setDns(const char *domain, const std::vector<InetAddress> &servers) {}
+	virtual void setDns(const char* domain, const std::vector<InetAddress>& servers)
+	{
+	}
 
-	void threadMain()
-		throw();
+	void threadMain() throw();
 
-private:
-	void (*_handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int);
-	void *_arg;
+  private:
+	void (*_handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int);
+	void* _arg;
 	unsigned int _concurrency;
 	bool _pinning;
 	uint64_t _nwid;
@@ -81,6 +80,6 @@ private:
 	std::vector<std::thread> _rxThreads;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 32 - 31
osdep/Binder.hpp

@@ -22,11 +22,11 @@
 #include <string.h>
 
 #ifdef __WINDOWS__
-#include <shlobj.h>
-#include <winsock2.h>
-#include <windows.h>
 #include <iphlpapi.h>
 #include <netioapi.h>
+#include <shlobj.h>
+#include <windows.h>
+#include <winsock2.h>
 #else
 #include <ifaddrs.h>
 #include <sys/socket.h>
@@ -34,13 +34,13 @@
 #include <sys/wait.h>
 #include <unistd.h>
 #ifdef __LINUX__
+#include <linux/if_addr.h>
 #include <net/if.h>
 #include <sys/ioctl.h>
-#include <linux/if_addr.h>
 #endif
 #endif
 
-#if (defined(__unix__) || defined(__APPLE__)) && !defined(__LINUX__) && !defined(ZT_SDK)
+#if (defined(__unix__) || defined(__APPLE__)) && ! defined(__LINUX__) && ! defined(ZT_SDK)
 #include <net/if.h>
 #if TARGET_OS_OSX
 #include <netinet6/in6_var.h>
@@ -51,9 +51,9 @@
 #include "../node/InetAddress.hpp"
 #include "../node/Mutex.hpp"
 #include "../node/Utils.hpp"
+#include "../osdep/ExtOsdep.hpp"
 #include "OSUtils.hpp"
 #include "Phy.hpp"
-#include "../osdep/ExtOsdep.hpp"
 
 #include <algorithm>
 #include <atomic>
@@ -132,30 +132,31 @@ class Binder {
 	template <typename PHY_HANDLER_TYPE, typename INTERFACE_CHECKER> void refresh(Phy<PHY_HANDLER_TYPE>& phy, unsigned int* ports, unsigned int portCount, const std::vector<InetAddress> explicitBind, INTERFACE_CHECKER& ifChecker)
 	{
 		std::map<InetAddress, std::string> localIfAddrs;
-		PhySocket *udps;
+		PhySocket* udps;
 		Mutex::Lock _l(_lock);
 		bool interfacesEnumerated = true;
 
 		if (explicitBind.empty()) {
 #ifdef ZT_EXTOSDEP
-                        std::map<InetAddress,std::string> addrs;
-                        interfacesEnumerated = ExtOsdep::getBindAddrs(addrs);
-                        for (auto &a : addrs) {
-                                auto ip = a.first;
-                                switch(ip.ipScope()) {
-                                        default: break;
-                                        case InetAddress::IP_SCOPE_PSEUDOPRIVATE:
-                                        case InetAddress::IP_SCOPE_GLOBAL:
-                                        case InetAddress::IP_SCOPE_SHARED:
-                                        case InetAddress::IP_SCOPE_PRIVATE:
-                                                for(int x=0;x<(int)portCount;++x) {
-                                                        ip.setPort(ports[x]);
-                                                        localIfAddrs.insert(std::pair<InetAddress,std::string>(ip,a.second));
-                                                }
-                                                break;
-                                }
-                        }
-#else // ZT_EXTOSDEP
+			std::map<InetAddress, std::string> addrs;
+			interfacesEnumerated = ExtOsdep::getBindAddrs(addrs);
+			for (auto& a : addrs) {
+				auto ip = a.first;
+				switch (ip.ipScope()) {
+					default:
+						break;
+					case InetAddress::IP_SCOPE_PSEUDOPRIVATE:
+					case InetAddress::IP_SCOPE_GLOBAL:
+					case InetAddress::IP_SCOPE_SHARED:
+					case InetAddress::IP_SCOPE_PRIVATE:
+						for (int x = 0; x < (int)portCount; ++x) {
+							ip.setPort(ports[x]);
+							localIfAddrs.insert(std::pair<InetAddress, std::string>(ip, a.second));
+						}
+						break;
+				}
+			}
+#else	// ZT_EXTOSDEP
 #ifdef __WINDOWS__
 
 			char aabuf[32768];
@@ -252,7 +253,7 @@ class Binder {
 						}
 					}
 
-					if ( (flags & IFA_F_TEMPORARY) != 0) {
+					if ((flags & IFA_F_TEMPORARY) != 0) {
 						continue;
 					}
 					if (devname) {
@@ -338,11 +339,11 @@ class Binder {
 			//
 			(void)gotViaProc;
 
-#if ! defined(__ANDROID__)	  // getifaddrs() freeifaddrs() not available on Android
+#if ! defined(__ANDROID__)	 // getifaddrs() freeifaddrs() not available on Android
 			if (! gotViaProc) {
 				struct ifaddrs* ifatbl = (struct ifaddrs*)0;
 				struct ifaddrs* ifa;
-#if (defined(__unix__) || defined(__APPLE__)) && !defined(__LINUX__) && !defined(ZT_SDK)
+#if (defined(__unix__) || defined(__APPLE__)) && ! defined(__LINUX__) && ! defined(ZT_SDK)
 				// set up an IPv6 socket so we can check the state of interfaces via SIOCGIFAFLAG_IN6
 				int infoSock = socket(AF_INET6, SOCK_DGRAM, 0);
 #endif
@@ -351,7 +352,7 @@ class Binder {
 					while (ifa) {
 						if ((ifa->ifa_name) && (ifa->ifa_addr)) {
 							InetAddress ip = *(ifa->ifa_addr);
-#if (defined(__unix__) || defined(__APPLE__)) && !defined(__LINUX__) && !defined(ZT_SDK) && TARGET_OS_OSX
+#if (defined(__unix__) || defined(__APPLE__)) && ! defined(__LINUX__) && ! defined(ZT_SDK) && TARGET_OS_OSX
 							// Check if the address is an IPv6 Temporary Address, macOS/BSD version
 							if (ifa->ifa_addr->sa_family == AF_INET6) {
 								struct sockaddr_in6* sa6 = (struct sockaddr_in6*)ifa->ifa_addr;
@@ -399,7 +400,7 @@ class Binder {
 				else {
 					interfacesEnumerated = false;
 				}
-#if (defined(__unix__) || defined(__APPLE__)) && !defined(__LINUX__) && !defined(ZT_SDK)
+#if (defined(__unix__) || defined(__APPLE__)) && ! defined(__LINUX__) && ! defined(ZT_SDK)
 				close(infoSock);
 #endif
 			}
@@ -407,7 +408,7 @@ class Binder {
 
 #endif
 
-#endif // ZT_EXTOSDEP
+#endif	 // ZT_EXTOSDEP
 		}
 		else {
 			for (std::vector<InetAddress>::const_iterator i(explicitBind.begin()); i != explicitBind.end(); ++i) {

+ 27 - 31
osdep/BlockingQueue.hpp

@@ -14,11 +14,11 @@
 #ifndef ZT_BLOCKINGQUEUE_HPP
 #define ZT_BLOCKINGQUEUE_HPP
 
-#include <queue>
-#include <mutex>
-#include <condition_variable>
-#include <chrono>
 #include <atomic>
+#include <chrono>
+#include <condition_variable>
+#include <mutex>
+#include <queue>
 #include <vector>
 
 namespace ZeroTier {
@@ -28,11 +28,11 @@ namespace ZeroTier {
  *
  * Do not use in node/ since we have not gone C++11 there yet.
  */
-template <class T>
-class BlockingQueue
-{
-public:
-	BlockingQueue(void) : r(true) {}
+template <class T> class BlockingQueue {
+  public:
+	BlockingQueue(void) : r(true)
+	{
+	}
 
 	inline void post(T t)
 	{
@@ -41,16 +41,16 @@ public:
 		c.notify_one();
 	}
 
-	inline void postLimit(T t,const unsigned long limit)
+	inline void postLimit(T t, const unsigned long limit)
 	{
 		std::unique_lock<std::mutex> lock(m);
-		for(;;) {
+		for (;;) {
 			if (q.size() < limit) {
 				q.push(t);
 				c.notify_one();
 				break;
 			}
-			if (!r)
+			if (! r)
 				break;
 			gc.wait(lock);
 		}
@@ -64,14 +64,14 @@ public:
 		gc.notify_all();
 	}
 
-	inline bool get(T &value)
+	inline bool get(T& value)
 	{
 		std::unique_lock<std::mutex> lock(m);
-		if (!r)
+		if (! r)
 			return false;
 		while (q.empty()) {
 			c.wait(lock);
-			if (!r) {
+			if (! r) {
 				gc.notify_all();
 				return false;
 			}
@@ -85,30 +85,25 @@ public:
 	inline std::vector<T> drain()
 	{
 		std::vector<T> v;
-		while (!q.empty()) {
+		while (! q.empty()) {
 			v.push_back(q.front());
 			q.pop();
 		}
 		return v;
 	}
 
-	enum TimedWaitResult
-	{
-		OK,
-		TIMED_OUT,
-		STOP
-	};
+	enum TimedWaitResult { OK, TIMED_OUT, STOP };
 
-	inline TimedWaitResult get(T &value,const unsigned long ms)
+	inline TimedWaitResult get(T& value, const unsigned long ms)
 	{
-		const std::chrono::milliseconds ms2{ms};
+		const std::chrono::milliseconds ms2 { ms };
 		std::unique_lock<std::mutex> lock(m);
-		if (!r)
+		if (! r)
 			return STOP;
 		while (q.empty()) {
-			if (c.wait_for(lock,ms2) == std::cv_status::timeout)
+			if (c.wait_for(lock, ms2) == std::cv_status::timeout)
 				return ((r) ? TIMED_OUT : STOP);
-			else if (!r)
+			else if (! r)
 				return STOP;
 		}
 		value = q.front();
@@ -116,17 +111,18 @@ public:
 		return OK;
 	}
 
-	inline size_t size() const {
+	inline size_t size() const
+	{
 		return q.size();
 	}
 
-private:
+  private:
 	std::queue<T> q;
 	mutable std::mutex m;
-	mutable std::condition_variable c,gc;
+	mutable std::condition_variable c, gc;
 	std::atomic_bool r;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 50 - 54
osdep/EthernetTap.cpp

@@ -12,6 +12,7 @@
 /****/
 
 #include "EthernetTap.hpp"
+
 #include "OSUtils.hpp"
 
 #include <stdlib.h>
@@ -20,87 +21,88 @@
 #ifdef ZT_SDK
 
 #include "../controller/EmbeddedNetworkController.hpp"
-#include "../node/Node.hpp"
 #include "../include/VirtualTap.hpp"
+#include "../node/Node.hpp"
 
 #else
 
 #ifdef __APPLE__
-#include <sys/sysctl.h>
 #include "MacEthernetTap.hpp"
 #include "MacKextEthernetTap.hpp"
-#endif // __APPLE__
+
+#include <sys/sysctl.h>
+#endif	 // __APPLE__
 
 #ifdef __LINUX__
 #include "ExtOsdep.hpp"
 #include "LinuxEthernetTap.hpp"
-#endif // __LINUX__
+#endif	 // __LINUX__
 
 #ifdef __WINDOWS__
 #include "WindowsEthernetTap.hpp"
-#endif // __WINDOWS__
+#endif	 // __WINDOWS__
 
 #ifdef __FreeBSD__
 #include "BSDEthernetTap.hpp"
-#endif // __FreeBSD__
+#endif	 // __FreeBSD__
 
 #ifdef __NetBSD__
 #include "NetBSDEthernetTap.hpp"
-#endif // __NetBSD__
+#endif	 // __NetBSD__
 
 #ifdef __OpenBSD__
 #include "BSDEthernetTap.hpp"
-#endif // __OpenBSD__
+#endif	 // __OpenBSD__
 
 #endif
 
 namespace ZeroTier {
 
 std::shared_ptr<EthernetTap> EthernetTap::newInstance(
-	const char *tapDeviceType, // OS-specific, NULL for default
+	const char* tapDeviceType,	 // OS-specific, NULL for default
 	unsigned int concurrency,
 	bool pinning,
-	const char *homePath,
-	const MAC &mac,
+	const char* homePath,
+	const MAC& mac,
 	unsigned int mtu,
 	unsigned int metric,
 	uint64_t nwid,
-	const char *friendlyName,
-	void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
-	void *arg)
+	const char* friendlyName,
+	void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int),
+	void* arg)
 {
-
 #ifdef ZT_SDK
 
-	return std::shared_ptr<EthernetTap>(new VirtualTap(homePath,mac,mtu,metric,nwid,friendlyName,handler,arg));
+	return std::shared_ptr<EthernetTap>(new VirtualTap(homePath, mac, mtu, metric, nwid, friendlyName, handler, arg));
 
-#else // not ZT_SDK
+#else	// not ZT_SDK
 
 #ifdef __APPLE__
 	char osrelease[256];
 	size_t size = sizeof(osrelease);
-	if (sysctlbyname("kern.osrelease",osrelease,&size,nullptr,0) == 0) {
-		char *dotAt = strchr(osrelease,'.');
+	if (sysctlbyname("kern.osrelease", osrelease, &size, nullptr, 0) == 0) {
+		char* dotAt = strchr(osrelease, '.');
 		if (dotAt) {
 			*dotAt = (char)0;
 			// The "feth" virtual Ethernet device type appeared in Darwin 17.x.x. Older versions
 			// (Sierra and earlier) must use the a kernel extension.
-			if (strtol(osrelease,(char **)0,10) < 17) {
-				return std::shared_ptr<EthernetTap>(new MacKextEthernetTap(homePath,mac,mtu,metric,nwid,friendlyName,handler,arg));
-			} else {
-				return std::shared_ptr<EthernetTap>(new MacEthernetTap(homePath,mac,mtu,metric,nwid,friendlyName,handler,arg));
+			if (strtol(osrelease, (char**)0, 10) < 17) {
+				return std::shared_ptr<EthernetTap>(new MacKextEthernetTap(homePath, mac, mtu, metric, nwid, friendlyName, handler, arg));
+			}
+			else {
+				return std::shared_ptr<EthernetTap>(new MacEthernetTap(homePath, mac, mtu, metric, nwid, friendlyName, handler, arg));
 			}
 		}
 	}
-#endif // __APPLE__
+#endif	 // __APPLE__
 
 #ifdef __LINUX__
 #ifdef ZT_EXTOSDEP
-	return std::shared_ptr<EthernetTap>(new ExtOsdepTap(homePath,mac,mtu,metric,nwid,friendlyName,handler,arg));
+	return std::shared_ptr<EthernetTap>(new ExtOsdepTap(homePath, mac, mtu, metric, nwid, friendlyName, handler, arg));
 #else
-	return std::shared_ptr<EthernetTap>(new LinuxEthernetTap(homePath,concurrency,pinning,mac,mtu,metric,nwid,friendlyName,handler,arg));
-#endif // ZT_EXTOSDEP
-#endif // __LINUX__
+	return std::shared_ptr<EthernetTap>(new LinuxEthernetTap(homePath, concurrency, pinning, mac, mtu, metric, nwid, friendlyName, handler, arg));
+#endif	 // ZT_EXTOSDEP
+#endif	 // __LINUX__
 
 #ifdef __WINDOWS__
 	HRESULT hres = CoInitializeEx(0, COINIT_MULTITHREADED);
@@ -113,18 +115,8 @@ std::shared_ptr<EthernetTap> EthernetTap::newInstance(
 
 	{
 		Mutex::Lock l(_comInit_m);
-		if (!_comInit) {
-			hres = CoInitializeSecurity(
-				NULL,
-				-1,
-				NULL,
-				NULL,
-				RPC_C_AUTHN_LEVEL_PKT,
-				RPC_C_IMP_LEVEL_IMPERSONATE,
-				NULL,
-				EOAC_NONE,
-				NULL
-			);
+		if (! _comInit) {
+			hres = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
 			if (FAILED(hres)) {
 				CoUninitialize();
 				fprintf(stderr, "WinEthernetTap: Failed to initialize security");
@@ -133,33 +125,37 @@ std::shared_ptr<EthernetTap> EthernetTap::newInstance(
 			_comInit = true;
 		}
 	}
-	return std::shared_ptr<EthernetTap>(new WindowsEthernetTap(homePath,mac,mtu,metric,nwid,friendlyName,handler,arg));
-#endif // __WINDOWS__
+	return std::shared_ptr<EthernetTap>(new WindowsEthernetTap(homePath, mac, mtu, metric, nwid, friendlyName, handler, arg));
+#endif	 // __WINDOWS__
 
 #ifdef __FreeBSD__
-	return std::shared_ptr<EthernetTap>(new BSDEthernetTap(homePath,concurrency,pinning,mac,mtu,metric,nwid,friendlyName,handler,arg));
-#endif // __FreeBSD__
+	return std::shared_ptr<EthernetTap>(new BSDEthernetTap(homePath, concurrency, pinning, mac, mtu, metric, nwid, friendlyName, handler, arg));
+#endif	 // __FreeBSD__
 
 #ifdef __NetBSD__
-	return std::shared_ptr<EthernetTap>(new NetBSDEthernetTap(homePath,mac,mtu,metric,nwid,friendlyName,handler,arg));
-#endif // __NetBSD__
+	return std::shared_ptr<EthernetTap>(new NetBSDEthernetTap(homePath, mac, mtu, metric, nwid, friendlyName, handler, arg));
+#endif	 // __NetBSD__
 
 #ifdef __OpenBSD__
-	return std::shared_ptr<EthernetTap>(new BSDEthernetTap(homePath,concurrency,pinning,mac,mtu,metric,nwid,friendlyName,handler,arg));
-#endif // __OpenBSD__
+	return std::shared_ptr<EthernetTap>(new BSDEthernetTap(homePath, concurrency, pinning, mac, mtu, metric, nwid, friendlyName, handler, arg));
+#endif	 // __OpenBSD__
 
-#endif // ZT_SDK?
+#endif	 // ZT_SDK?
 
 	return std::shared_ptr<EthernetTap>();
 }
 
-EthernetTap::EthernetTap() {}
-EthernetTap::~EthernetTap() {}
+EthernetTap::EthernetTap()
+{
+}
+EthernetTap::~EthernetTap()
+{
+}
 
 bool EthernetTap::addIps(std::vector<InetAddress> ips)
 {
-	for(std::vector<InetAddress>::const_iterator i(ips.begin());i!=ips.end();++i) {
-		if (!addIp(*i))
+	for (std::vector<InetAddress>::const_iterator i(ips.begin()); i != ips.end(); ++i) {
+		if (! addIp(*i))
 			return false;
 	}
 	return true;
@@ -171,4 +167,4 @@ std::string EthernetTap::friendlyName() const
 	return std::string();
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier

+ 18 - 19
osdep/EthernetTap.hpp

@@ -15,52 +15,51 @@
 #define ZT_ETHERNETTAP_HPP
 
 #include "../node/Constants.hpp"
-#include "../node/MAC.hpp"
 #include "../node/InetAddress.hpp"
+#include "../node/MAC.hpp"
 #include "../node/MulticastGroup.hpp"
 
-#include <string>
 #include <memory>
+#include <string>
 #include <vector>
 
 #define GETIFADDRS_CACHE_TIME 1000
 
 namespace ZeroTier {
 
-class EthernetTap
-{
-public:
+class EthernetTap {
+  public:
 	static std::shared_ptr<EthernetTap> newInstance(
-		const char *tapDeviceType, // OS-specific, NULL for default
+		const char* tapDeviceType,	 // OS-specific, NULL for default
 		unsigned int concurrency,
 		bool pinning,
-		const char *homePath,
-		const MAC &mac,
+		const char* homePath,
+		const MAC& mac,
 		unsigned int mtu,
 		unsigned int metric,
 		uint64_t nwid,
-		const char *friendlyName,
-		void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
-		void *arg);
+		const char* friendlyName,
+		void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int),
+		void* arg);
 
 	EthernetTap();
 	virtual ~EthernetTap();
 
 	virtual void setEnabled(bool en) = 0;
 	virtual bool enabled() const = 0;
-	virtual bool addIp(const InetAddress &ip) = 0;
-	virtual bool addIps(std::vector<InetAddress> ips); // uses addIp() unless overridden
-	virtual bool removeIp(const InetAddress &ip) = 0;
+	virtual bool addIp(const InetAddress& ip) = 0;
+	virtual bool addIps(std::vector<InetAddress> ips);	 // uses addIp() unless overridden
+	virtual bool removeIp(const InetAddress& ip) = 0;
 	virtual std::vector<InetAddress> ips() const = 0;
-	virtual void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len) = 0;
+	virtual void put(const MAC& from, const MAC& to, unsigned int etherType, const void* data, unsigned int len) = 0;
 	virtual std::string deviceName() const = 0;
-	virtual void setFriendlyName(const char *friendlyName) = 0;
+	virtual void setFriendlyName(const char* friendlyName) = 0;
 	virtual std::string friendlyName() const;
-	virtual void scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed) = 0;
+	virtual void scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed) = 0;
 	virtual void setMtu(unsigned int mtu) = 0;
-	virtual void setDns(const char *domain, const std::vector<InetAddress> &servers) = 0;
+	virtual void setDns(const char* domain, const std::vector<InetAddress>& servers) = 0;
 };
 
-} // namespace ZeroTier
+}	// namespace ZeroTier
 
 #endif

+ 104 - 102
osdep/Http.cpp

@@ -11,15 +11,16 @@
  */
 /****/
 
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-
 #include "Http.hpp"
-#include "Phy.hpp"
-#include "OSUtils.hpp"
+
 #include "../node/Constants.hpp"
 #include "../node/Utils.hpp"
+#include "OSUtils.hpp"
+#include "Phy.hpp"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
 
 #ifdef ZT_USE_SYSTEM_HTTP_PARSER
 #include <http_parser.h>
@@ -31,90 +32,87 @@ namespace ZeroTier {
 
 namespace {
 
-static int ShttpOnMessageBegin(http_parser *parser);
-static int ShttpOnUrl(http_parser *parser,const char *ptr,size_t length);
+static int ShttpOnMessageBegin(http_parser* parser);
+static int ShttpOnUrl(http_parser* parser, const char* ptr, size_t length);
 #if (HTTP_PARSER_VERSION_MAJOR >= 2) && (HTTP_PARSER_VERSION_MINOR >= 2)
-static int ShttpOnStatus(http_parser *parser,const char *ptr,size_t length);
+static int ShttpOnStatus(http_parser* parser, const char* ptr, size_t length);
 #else
-static int ShttpOnStatus(http_parser *parser);
+static int ShttpOnStatus(http_parser* parser);
 #endif
-static int ShttpOnHeaderField(http_parser *parser,const char *ptr,size_t length);
-static int ShttpOnValue(http_parser *parser,const char *ptr,size_t length);
-static int ShttpOnHeadersComplete(http_parser *parser);
-static int ShttpOnBody(http_parser *parser,const char *ptr,size_t length);
-static int ShttpOnMessageComplete(http_parser *parser);
+static int ShttpOnHeaderField(http_parser* parser, const char* ptr, size_t length);
+static int ShttpOnValue(http_parser* parser, const char* ptr, size_t length);
+static int ShttpOnHeadersComplete(http_parser* parser);
+static int ShttpOnBody(http_parser* parser, const char* ptr, size_t length);
+static int ShttpOnMessageComplete(http_parser* parser);
 
 #if (HTTP_PARSER_VERSION_MAJOR >= 2) && (HTTP_PARSER_VERSION_MINOR >= 1)
-static const struct http_parser_settings HTTP_PARSER_SETTINGS = {
-	ShttpOnMessageBegin,
-	ShttpOnUrl,
-	ShttpOnStatus,
-	ShttpOnHeaderField,
-	ShttpOnValue,
-	ShttpOnHeadersComplete,
-	ShttpOnBody,
-	ShttpOnMessageComplete
-};
+static const struct http_parser_settings HTTP_PARSER_SETTINGS = { ShttpOnMessageBegin, ShttpOnUrl, ShttpOnStatus, ShttpOnHeaderField, ShttpOnValue, ShttpOnHeadersComplete, ShttpOnBody, ShttpOnMessageComplete };
 #else
-static const struct http_parser_settings HTTP_PARSER_SETTINGS = {
-	ShttpOnMessageBegin,
-	ShttpOnUrl,
-	ShttpOnHeaderField,
-	ShttpOnValue,
-	ShttpOnHeadersComplete,
-	ShttpOnBody,
-	ShttpOnMessageComplete
-};
+static const struct http_parser_settings HTTP_PARSER_SETTINGS = { ShttpOnMessageBegin, ShttpOnUrl, ShttpOnHeaderField, ShttpOnValue, ShttpOnHeadersComplete, ShttpOnBody, ShttpOnMessageComplete };
 #endif
 
-struct HttpPhyHandler
-{
+struct HttpPhyHandler {
 	// not used
-	inline void phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *localAddr,const struct sockaddr *from,void *data,unsigned long len) {}
-	inline void phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,const struct sockaddr *from) {}
+	inline void phyOnDatagram(PhySocket* sock, void** uptr, const struct sockaddr* localAddr, const struct sockaddr* from, void* data, unsigned long len)
+	{
+	}
+	inline void phyOnTcpAccept(PhySocket* sockL, PhySocket* sockN, void** uptrL, void** uptrN, const struct sockaddr* from)
+	{
+	}
 
-	inline void phyOnTcpConnect(PhySocket *sock,void **uptr,bool success)
+	inline void phyOnTcpConnect(PhySocket* sock, void** uptr, bool success)
 	{
 		if (success) {
-			phy->setNotifyWritable(sock,true);
-		} else {
+			phy->setNotifyWritable(sock, true);
+		}
+		else {
 			*responseBody = "connection failed";
 			error = true;
 			done = true;
 		}
 	}
 
-	inline void phyOnTcpClose(PhySocket *sock,void **uptr)
+	inline void phyOnTcpClose(PhySocket* sock, void** uptr)
 	{
 		done = true;
 	}
 
-	inline void phyOnTcpData(PhySocket *sock,void **uptr,void *data,unsigned long len)
+	inline void phyOnTcpData(PhySocket* sock, void** uptr, void* data, unsigned long len)
 	{
 		lastActivity = OSUtils::now();
-		http_parser_execute(&parser,&HTTP_PARSER_SETTINGS,(const char *)data,len);
-		if ((parser.upgrade)||(parser.http_errno != HPE_OK))
+		http_parser_execute(&parser, &HTTP_PARSER_SETTINGS, (const char*)data, len);
+		if ((parser.upgrade) || (parser.http_errno != HPE_OK))
 			phy->close(sock);
 	}
 
-	inline void phyOnTcpWritable(PhySocket *sock,void **uptr)
+	inline void phyOnTcpWritable(PhySocket* sock, void** uptr)
 	{
 		if (writePtr < (unsigned long)writeBuf.length()) {
-			long n = phy->streamSend(sock,writeBuf.data() + writePtr,(unsigned long)writeBuf.length() - writePtr,true);
+			long n = phy->streamSend(sock, writeBuf.data() + writePtr, (unsigned long)writeBuf.length() - writePtr, true);
 			if (n > 0)
 				writePtr += n;
 		}
 		if (writePtr >= (unsigned long)writeBuf.length())
-			phy->setNotifyWritable(sock,false);
+			phy->setNotifyWritable(sock, false);
 	}
 
-	inline void phyOnFileDescriptorActivity(PhySocket *sock,void **uptr,bool readable,bool writable) {}
+	inline void phyOnFileDescriptorActivity(PhySocket* sock, void** uptr, bool readable, bool writable)
+	{
+	}
 #ifdef __UNIX_LIKE__
-	inline void phyOnUnixAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN) {}
-	inline void phyOnUnixClose(PhySocket *sock,void **uptr) {}
-	inline void phyOnUnixData(PhySocket *sock,void **uptr,void *data,unsigned long len) {}
-	inline void phyOnUnixWritable(PhySocket *sock,void **uptr) {}
-#endif // __UNIX_LIKE__
+	inline void phyOnUnixAccept(PhySocket* sockL, PhySocket* sockN, void** uptrL, void** uptrN)
+	{
+	}
+	inline void phyOnUnixClose(PhySocket* sock, void** uptr)
+	{
+	}
+	inline void phyOnUnixData(PhySocket* sock, void** uptr, void* data, unsigned long len)
+	{
+	}
+	inline void phyOnUnixWritable(PhySocket* sock, void** uptr)
+	{
+	}
+#endif	 // __UNIX_LIKE__
 
 	http_parser parser;
 	std::string currentHeaderField;
@@ -125,27 +123,27 @@ struct HttpPhyHandler
 	std::string writeBuf;
 
 	unsigned long maxResponseSize;
-	std::map<std::string,std::string> *responseHeaders;
-	std::string *responseBody;
+	std::map<std::string, std::string>* responseHeaders;
+	std::string* responseBody;
 	bool error;
 	bool done;
 
-	Phy<HttpPhyHandler *> *phy;
-	PhySocket *sock;
+	Phy<HttpPhyHandler*>* phy;
+	PhySocket* sock;
 };
 
-static int ShttpOnMessageBegin(http_parser *parser)
+static int ShttpOnMessageBegin(http_parser* parser)
 {
 	return 0;
 }
-static int ShttpOnUrl(http_parser *parser,const char *ptr,size_t length)
+static int ShttpOnUrl(http_parser* parser, const char* ptr, size_t length)
 {
 	return 0;
 }
 #if (HTTP_PARSER_VERSION_MAJOR >= 2) && (HTTP_PARSER_VERSION_MINOR >= 2)
-static int ShttpOnStatus(http_parser *parser,const char *ptr,size_t length)
+static int ShttpOnStatus(http_parser* parser, const char* ptr, size_t length)
 #else
-static int ShttpOnStatus(http_parser *parser)
+static int ShttpOnStatus(http_parser* parser)
 #endif
 {
 	/*
@@ -156,66 +154,66 @@ static int ShttpOnStatus(http_parser *parser)
 	*/
 	return 0;
 }
-static int ShttpOnHeaderField(http_parser *parser,const char *ptr,size_t length)
+static int ShttpOnHeaderField(http_parser* parser, const char* ptr, size_t length)
 {
-	HttpPhyHandler *hh = reinterpret_cast<HttpPhyHandler *>(parser->data);
+	HttpPhyHandler* hh = reinterpret_cast<HttpPhyHandler*>(parser->data);
 	hh->messageSize += (unsigned long)length;
 	if (hh->messageSize > hh->maxResponseSize)
 		return -1;
-	if ((hh->currentHeaderField.length())&&(hh->currentHeaderValue.length())) {
+	if ((hh->currentHeaderField.length()) && (hh->currentHeaderValue.length())) {
 		(*hh->responseHeaders)[hh->currentHeaderField] = hh->currentHeaderValue;
 		hh->currentHeaderField = "";
 		hh->currentHeaderValue = "";
 	}
-	for(size_t i=0;i<length;++i)
+	for (size_t i = 0; i < length; ++i)
 		hh->currentHeaderField.push_back(OSUtils::toLower(ptr[i]));
 	return 0;
 }
-static int ShttpOnValue(http_parser *parser,const char *ptr,size_t length)
+static int ShttpOnValue(http_parser* parser, const char* ptr, size_t length)
 {
-	HttpPhyHandler *hh = reinterpret_cast<HttpPhyHandler *>(parser->data);
+	HttpPhyHandler* hh = reinterpret_cast<HttpPhyHandler*>(parser->data);
 	hh->messageSize += (unsigned long)length;
 	if (hh->messageSize > hh->maxResponseSize)
 		return -1;
-	hh->currentHeaderValue.append(ptr,length);
+	hh->currentHeaderValue.append(ptr, length);
 	return 0;
 }
-static int ShttpOnHeadersComplete(http_parser *parser)
+static int ShttpOnHeadersComplete(http_parser* parser)
 {
-	HttpPhyHandler *hh = reinterpret_cast<HttpPhyHandler *>(parser->data);
-	if ((hh->currentHeaderField.length())&&(hh->currentHeaderValue.length()))
+	HttpPhyHandler* hh = reinterpret_cast<HttpPhyHandler*>(parser->data);
+	if ((hh->currentHeaderField.length()) && (hh->currentHeaderValue.length()))
 		(*hh->responseHeaders)[hh->currentHeaderField] = hh->currentHeaderValue;
 	return 0;
 }
-static int ShttpOnBody(http_parser *parser,const char *ptr,size_t length)
+static int ShttpOnBody(http_parser* parser, const char* ptr, size_t length)
 {
-	HttpPhyHandler *hh = reinterpret_cast<HttpPhyHandler *>(parser->data);
+	HttpPhyHandler* hh = reinterpret_cast<HttpPhyHandler*>(parser->data);
 	hh->messageSize += (unsigned long)length;
 	if (hh->messageSize > hh->maxResponseSize)
 		return -1;
-	hh->responseBody->append(ptr,length);
+	hh->responseBody->append(ptr, length);
 	return 0;
 }
-static int ShttpOnMessageComplete(http_parser *parser)
+static int ShttpOnMessageComplete(http_parser* parser)
 {
-	HttpPhyHandler *hh = reinterpret_cast<HttpPhyHandler *>(parser->data);
+	HttpPhyHandler* hh = reinterpret_cast<HttpPhyHandler*>(parser->data);
 	hh->phy->close(hh->sock);
 	return 0;
 }
 
-} // anonymous namespace
+}	// anonymous namespace
 
 unsigned int Http::_do(
-	const char *method,
+	const char* method,
 	unsigned long maxResponseSize,
 	unsigned long timeout,
-	const struct sockaddr *remoteAddress,
-	const char *path,
-	const std::map<std::string,std::string> &requestHeaders,
-	const void *requestBody,
+	const struct sockaddr* remoteAddress,
+	const char* path,
+	const std::map<std::string, std::string>& requestHeaders,
+	const void* requestBody,
 	unsigned long requestBodyLength,
-	std::map<std::string,std::string> &responseHeaders,
-	std::string &responseBody)
+	std::map<std::string, std::string>& responseHeaders,
+	std::string& responseBody)
 {
 	try {
 		responseHeaders.clear();
@@ -223,31 +221,33 @@ unsigned int Http::_do(
 
 		HttpPhyHandler handler;
 
-		http_parser_init(&(handler.parser),HTTP_RESPONSE);
-		handler.parser.data = (void *)&handler;
+		http_parser_init(&(handler.parser), HTTP_RESPONSE);
+		handler.parser.data = (void*)&handler;
 		handler.messageSize = 0;
 		handler.writePtr = 0;
 		handler.lastActivity = OSUtils::now();
 
 		try {
 			char tmp[1024];
-			OSUtils::ztsnprintf(tmp,sizeof(tmp),"%s %s HTTP/1.1\r\n",method,path);
+			OSUtils::ztsnprintf(tmp, sizeof(tmp), "%s %s HTTP/1.1\r\n", method, path);
 			handler.writeBuf.append(tmp);
-			for(std::map<std::string,std::string>::const_iterator h(requestHeaders.begin());h!=requestHeaders.end();++h) {
-				OSUtils::ztsnprintf(tmp,sizeof(tmp),"%s: %s\r\n",h->first.c_str(),h->second.c_str());
+			for (std::map<std::string, std::string>::const_iterator h(requestHeaders.begin()); h != requestHeaders.end(); ++h) {
+				OSUtils::ztsnprintf(tmp, sizeof(tmp), "%s: %s\r\n", h->first.c_str(), h->second.c_str());
 				handler.writeBuf.append(tmp);
 			}
 			handler.writeBuf.append("\r\n");
-			if ((requestBody)&&(requestBodyLength))
-				handler.writeBuf.append((const char *)requestBody,requestBodyLength);
-		} catch ( ... ) {
+			if ((requestBody) && (requestBodyLength))
+				handler.writeBuf.append((const char*)requestBody, requestBodyLength);
+		}
+		catch (...) {
 			responseBody = "request too large";
 			return 0;
 		}
 
 		if (maxResponseSize) {
 			handler.maxResponseSize = maxResponseSize;
-		} else {
+		}
+		else {
 			handler.maxResponseSize = 2147483647;
 		}
 		handler.responseHeaders = &responseHeaders;
@@ -255,19 +255,19 @@ unsigned int Http::_do(
 		handler.error = false;
 		handler.done = false;
 
-		Phy<HttpPhyHandler *> phy(&handler,true,true);
+		Phy<HttpPhyHandler*> phy(&handler, true, true);
 
 		bool instantConnect = false;
 		handler.phy = &phy;
-		handler.sock = phy.tcpConnect((const struct sockaddr *)remoteAddress,instantConnect,(void *)0,true);
-		if (!handler.sock) {
+		handler.sock = phy.tcpConnect((const struct sockaddr*)remoteAddress, instantConnect, (void*)0, true);
+		if (! handler.sock) {
 			responseBody = "connection failed (2)";
 			return 0;
 		}
 
-		while (!handler.done) {
+		while (! handler.done) {
 			phy.poll(timeout / 2);
-			if ((timeout)&&((unsigned long)(OSUtils::now() - handler.lastActivity) > timeout)) {
+			if ((timeout) && ((unsigned long)(OSUtils::now() - handler.lastActivity) > timeout)) {
 				phy.close(handler.sock);
 				responseBody = "timed out";
 				return 0;
@@ -275,13 +275,15 @@ unsigned int Http::_do(
 		}
 
 		return ((handler.error) ? 0 : ((handler.parser.http_errno != HPE_OK) ? 0 : handler.parser.status_code));
-	} catch (std::exception &exc) {
+	}
+	catch (std::exception& exc) {
 		responseBody = exc.what();
 		return 0;
-	} catch ( ... ) {
+	}
+	catch (...) {
 		responseBody = "unknown exception";
 		return 0;
 	}
 }
 
-} // namespace ZeroTier
+}	// namespace ZeroTier

Some files were not shown because too many files changed in this diff