diff --git a/.gitignore b/.gitignore index a15627933..2ad8627f1 100755 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ -build/ +/build +/cmake-build-debug +/cmake-build-release /version.h +/.idea .DS_Store .Trashes *.swp diff --git a/.idea/ZeroTierOne.iml b/.idea/ZeroTierOne.iml index 5e764c4f0..44599ced0 100644 --- a/.idea/ZeroTierOne.iml +++ b/.idea/ZeroTierOne.iml @@ -1,9 +1,4 @@ - + - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 28a804d89..8822db8f1 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,5 +1,6 @@ + diff --git a/CMakeLists.txt b/CMakeLists.txt index 7487351ec..408772d22 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,208 +1,144 @@ -cmake_minimum_required (VERSION 3.8) +cmake_minimum_required(VERSION 3.15) +project(ZeroTierOne) -if(${CMAKE_VERSION} VERSION_LESS 3.15) - cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) -else() - cmake_policy(VERSION 3.15) -endif() +set(CMAKE_CXX_STANDARD 14) -if(WIN32) - # If building on Windows, set minimum target to Windows 7 - set(CMAKE_SYSTEM_VERSION "7" CACHE STRING INTERNAL FORCE) -endif(WIN32) +include_directories(controller) +include_directories(ext) +include_directories(ext/json) +include_directories(include) +include_directories(node) +include_directories(osdep) +include_directories(root) -set(ZEROTIER_ONE_VERSION_MAJOR 2 CACHE INTERNAL "") -set(ZEROTIER_ONE_VERSION_MINOR 0 CACHE INTERNAL "") -set(ZEROTIER_ONE_VERSION_REVISION 0 CACHE INTERNAL "") -set(ZEROTIER_ONE_VERSION_BUILD 0 CACHE INTERNAL "") - -set(default_build_type "Release") -if(EXISTS "${CMAKE_SOURCE_DIR}/.git") - set(default_build_type "Debug") -endif() - -if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - message(STATUS "Setting build type to '${default_build_type}' as none was specified.") - set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE - STRING "Choose the type of build." FORCE) - # Set the possible values of build type for cmake-gui - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Release" "MinSizeRel" "RelWithDebInfo") -endif() - -option(BUILD_CENTRAL_CONTROLLER "Build ZeroTier Central Controller" OFF) -option(ZT_TRACE "Trace Messages" OFF) -option(ZT_DEBUG_TRACE "Debug Trace Messages" OFF) - -if (BUILD_CENTRAL_CONTROLLER) - find_package(PostgreSQL REQUIRED) - set(ENABLE_SSL_SUPPORT OFF) - set(BUILD_SHARED_LIBS OFF) - set(BUILD_EXAMPLES OFF) - set(BUILD_TOOLS OFF) - set(BUILD_TESTS OFF) - set(BUILD_API_DOCS OFF) - add_subdirectory("ext/librabbitmq") -endif(BUILD_CENTRAL_CONTROLLER) - -set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OS X Deployment Version") - -if(CMAKE_BUILD_TYPE STREQUAL "Debug") - add_definitions(-DZT_TRACE) -endif(CMAKE_BUILD_TYPE STREQUAL "Debug") - -project(zerotier - DESCRIPTION "ZeroTier Network Hypervisor" - LANGUAGES CXX C) - -if(WIN32) - add_definitions(-DNOMINMAX) -else(WIN32) - if(APPLE) - - message("Setting macOS Compiler Flags ${CMAKE_BUILD_TYPE}") - add_compile_options( - -Wall - -Wno-deprecated - -mmacosx-version-min=10.9 - $<$:-g> - $<$:-O0> - $<$:-Ofast> - $<$:-fPIE> - $<$:-flto> - $<$:-Ofast> - $<$:-fPIE> - $<$:-g> - ) - add_link_options( - -mmacosx-version-min=10.9 - $<$:-flto> - ) - - elseif ( - CMAKE_SYSTEM_NAME MATCHES "Linux" OR - CMAKE_SYSTEM_NAME MATCHES "FreeBSD" OR - CMAKE_SYSTEM_NAME MATCHES "OpenBSD" OR - CMAKE_SYSTEM_NAME MATCHES "NetBSD" - ) - - message("Setting Linux/BSD Compiler Flags (${CMAKE_BUILD_TYPE})") - add_compile_options( - -Wall - -Wno-deprecated - $<$:-g> - $<$:-O0> - $<$:-O3> - $<$:-fPIE> - $<$:-O3> - $<$:-fPIE> - $<$:-g> - ) - - endif(APPLE) -endif(WIN32) - -if ( - CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64" OR - CMAKE_SYSTEM_PROCESSOR MATCHES "amd64" OR - CMAKE_SYSTEM_PROCESSOR MATCHES "i386" OR - CMAKE_SYSTEM_PROCESSOR MATCHES "i486" OR - CMAKE_SYSTEM_PROCESSOR MATCHES "i586" OR - CMAKE_SYSTEM_PROCESSOR MATCHES "i686" -) - message("Adding SSE and AES-NI flags for processor ${CMAKE_SYSTEM_PROCESSOR}") - add_compile_options( - -maes - -mmmx - -mrdrnd - -mpclmul - -msse - -msse2 - -msse3 - -msse4.1 - ) -endif() - -if(ZT_TRACE) - add_definitions(-DZT_TRACE) -endif() -if(ZT_DEBUG_TRACE) - add_definitions(-DZT_DEBUG_TRACE) -endif() - -add_subdirectory(node) -add_subdirectory(controller) -add_subdirectory(osdep) -add_subdirectory(root) -add_subdirectory(go/native) - -#if(WIN32) -# add_subdirectory("windows/WinUI") -# add_subdirectory("windows/copyutil") -# add_definitions(-DNOMINMAX) -#endif(WIN32) - -set( - zt_osdep - zt_core - zt_controller - zt_go_native -) - -configure_file( - ${CMAKE_SOURCE_DIR}/version.h.in - ${CMAKE_BINARY_DIR}/version.h -) - -#set(src -# one.cpp -# "ext/http-parser/http_parser.c" -#) -#set(headers -# "ext/http-parser/http_parser.h" -#) - -if(WIN32) - set(libs ${libs} wsock32 ws2_32 rpcrt4 iphlpapi) -else(WIN32) - set(libs ${libs} pthread) -endif(WIN32) - -#if(WIN32) -# set(libs ${libs} wsock32 ws2_32 rpcrt4 iphlpapi) -# set(src -# ${src} -# "windows/ZeroTierOne/ServiceBase.cpp" -# "windows/ZeroTierOne/ServiceInstaller.cpp" -# "windows/ZeroTierOne/ZeroTierOneService.cpp" -# "windows/ZeroTierOne/ZeroTierOne.rc" -# ) -# set(headers -# ${headers} -# "windows/ZeroTierOne/ServiceBase.h" -# "windows/ZeroTierOne/ServiceInstaller.h" -# "windows/ZeroTierOne/ZeroTierOneService.h" -# ) -#else(WIN32) -# set(libs ${libs} pthread resolv) -#endif(WIN32) - -#if(BUILD_CENTRAL_CONTROLLER) -# set(libs ${libs} rabbitmq-static ${PostgreSQL_LIBRARIES}) -#endif(BUILD_CENTRAL_CONTROLLER) - -#add_executable(${PROJECT_NAME} ${src} ${headers}) -#target_link_libraries(${PROJECT_NAME} ${libs}) -#target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_BINARY_DIR}) - -add_custom_command( - OUTPUT zerotier - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/go - COMMAND go build -trimpath -ldflags -s -o ../build/zerotier cmd/zerotier/zerotier.go - DEPENDS zt_osdep zt_core zt_go_native -) -add_custom_target(build_zerotier ALL DEPENDS zerotier) - -add_executable(zerotier-selftest selftest.cpp) -target_link_libraries(zerotier-selftest ${libs} zt_core zt_osdep) -target_compile_features(zerotier-selftest PUBLIC cxx_std_11) +add_executable(ZeroTierOne + controller/CMakeLists.txt + controller/DB.cpp + controller/DB.hpp + controller/DBMirrorSet.cpp + controller/DBMirrorSet.hpp + controller/EmbeddedNetworkController.cpp + controller/EmbeddedNetworkController.hpp + controller/FileDB.cpp + controller/FileDB.hpp + controller/LFDB.cpp + controller/LFDB.hpp + controller/PostgreSQL.cpp + controller/PostgreSQL.hpp + controller/RabbitMQ.cpp + controller/RabbitMQ.hpp + ext/json/json.hpp + include/ZeroTierCore.h + include/ZeroTierDebug.h + node/Address.hpp + node/AES-aesni.c + node/AES.cpp + node/AES.hpp + node/AtomicCounter.hpp + node/Buffer.hpp + node/C25519.cpp + node/C25519.hpp + node/Capability.hpp + node/CertificateOfMembership.hpp + node/CertificateOfOwnership.hpp + node/CMakeLists.txt + node/Constants.hpp + node/Credential.cpp + node/Credential.hpp + node/Dictionary.hpp + node/ECC384.cpp + node/ECC384.hpp + node/Endpoint.hpp + node/Hashtable.hpp + node/Identity.cpp + node/Identity.hpp + node/IncomingPacket.cpp + node/IncomingPacket.hpp + node/InetAddress.cpp + node/InetAddress.hpp + node/Locator.hpp + node/MAC.hpp + node/Membership.cpp + node/Membership.hpp + node/Meter.hpp + node/MulticastGroup.hpp + node/Mutex.hpp + node/Network.cpp + node/Network.hpp + node/NetworkConfig.cpp + node/NetworkConfig.hpp + node/NetworkController.hpp + node/Node.cpp + node/Node.hpp + node/OS.hpp + node/Packet.cpp + node/Packet.hpp + node/Path.cpp + node/Path.hpp + node/Peer.cpp + node/Peer.hpp + node/Poly1305.cpp + node/Poly1305.hpp + node/README.md + node/Revocation.hpp + node/RingBuffer.hpp + node/RuntimeEnvironment.hpp + node/Salsa20.cpp + node/Salsa20.hpp + node/ScopedPtr.hpp + node/SelfAwareness.cpp + node/SelfAwareness.hpp + node/SHA512.cpp + node/SHA512.hpp + node/SharedPtr.hpp + node/Str.hpp + node/Switch.cpp + node/Switch.hpp + node/Tag.hpp + node/Topology.hpp + node/Trace.cpp + node/Trace.hpp + node/Utils.cpp + node/Utils.hpp + osdep/Arp.cpp + osdep/Arp.hpp + osdep/BlockingQueue.hpp + osdep/BSDEthernetTap.cpp + osdep/BSDEthernetTap.hpp + osdep/CMakeLists.txt + osdep/EthernetTap.cpp + osdep/EthernetTap.hpp + osdep/freebsd_getifmaddrs.c + osdep/freebsd_getifmaddrs.h + osdep/LinuxEthernetTap.cpp + osdep/LinuxEthernetTap.hpp + osdep/LinuxNetLink.cpp + osdep/LinuxNetLink.hpp + osdep/MacEthernetTap.cpp + osdep/MacEthernetTap.hpp + osdep/MacEthernetTapAgent.c + osdep/MacEthernetTapAgent.h + osdep/MacKextEthernetTap.cpp + osdep/MacKextEthernetTap.hpp + osdep/ManagedRoute.cpp + osdep/ManagedRoute.hpp + osdep/NeighborDiscovery.cpp + osdep/NeighborDiscovery.hpp + osdep/NetBSDEthernetTap.cpp + osdep/NetBSDEthernetTap.hpp + osdep/OSUtils.cpp + osdep/OSUtils.hpp + osdep/README.md + osdep/Thread.hpp + osdep/WindowsEthernetTap.cpp + osdep/WindowsEthernetTap.hpp + root/CMakeLists.txt + root/geoip-html.h + root/root.cpp + AUTHORS.md + CMakeLists.txt + LICENSE.txt + OFFICIAL-RELEASE-STEPS.md + README.md + RELEASE-NOTES.md + selftest.cpp) diff --git a/node/CMakeLists.txt b/node/CMakeLists.txt index 99a3ae8d0..2dc365a79 100644 --- a/node/CMakeLists.txt +++ b/node/CMakeLists.txt @@ -17,7 +17,6 @@ set(core_headers Credential.hpp Dictionary.hpp ECC384.hpp - EphemeralKey.hpp Hashtable.hpp Identity.hpp InetAddress.hpp diff --git a/node/Constants.hpp b/node/Constants.hpp index 04748c066..08df5abd8 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -31,11 +31,6 @@ */ #define ZT_ADDRESS_LENGTH 5 -/** - * Length of a hexadecimal ZeroTier address - */ -#define ZT_ADDRESS_LENGTH_HEX 10 - /** * Addresses beginning with this byte are reserved for the joy of in-band signaling */ @@ -131,30 +126,6 @@ */ #define ZT_MULTICAST_ANNOUNCE_PERIOD 60000 -/** - * Period for multicast GATHER on multicast groups - */ -#define ZT_MULTICAST_GATHER_PERIOD ZT_MULTICAST_ANNOUNCE_PERIOD - -/** - * Period for multicast GATHER if there are no known recipients - */ -#define ZT_MULTICAST_GATHER_PERIOD_WHEN_NO_RECIPIENTS 2500 - -/** - * Timeout for outgoing multicasts - * - * This is how long we wait for explicit or implicit gather results. - */ -#define ZT_MULTICAST_TRANSMIT_TIMEOUT 5000 - -/** - * How frequently to check for changes to the system's network interfaces. When - * the service decides to use this constant it's because we want to react more - * quickly to new interfaces that pop up or go down. - */ -#define ZT_MULTIPATH_BINDER_REFRESH_PERIOD 5000 - /** * Packets are only used for QoS/ACK statistical sampling if their packet ID is divisible by * this integer. This is to provide a mechanism for both peers to agree on which packets need @@ -319,11 +290,6 @@ */ #define ZT_QOS_DEFAULT_BUCKET 0 -/** - * Do not accept HELLOs over a given path more often than this - */ -#define ZT_PATH_HELLO_RATE_LIMIT 1000 - /** * Delay between full-fledge pings of directly connected peers * @@ -348,21 +314,6 @@ #define ZT_PEER_ACTIVITY_TIMEOUT 30000 #endif -/** - * Rescan for best/fastest root every N milliseconds - */ -#define ZT_FIND_BEST_ROOT_PERIOD 2000 - -/** - * General rate limit timeout for multiple packet types (HELLO, etc.) - */ -#define ZT_PEER_GENERAL_INBOUND_RATE_LIMIT 500 - -/** - * General limit for max RTT for requests over the network - */ -#define ZT_GENERAL_RTT_LIMIT 5000 - /** * Delay between requests for updated network autoconf information * @@ -477,7 +428,7 @@ */ #define ZT_THREAD_MIN_STACK_SIZE 1048576 -// Internal cryptographic algorithm IDs +// Internal cryptographic algorithm IDs (these match relevant identity types) #define ZT_CRYPTO_ALG_C25519 0 #define ZT_CRYPTO_ALG_P384 1 @@ -491,4 +442,9 @@ #define ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN 202 #define ZT_EXCEPTION_INVALID_SERIALIZED_DATA_BAD_ENCODING 203 +/* Ethernet frame types that might be relevant to us */ +#define ZT_ETHERTYPE_IPV4 0x0800 +#define ZT_ETHERTYPE_ARP 0x0806 +#define ZT_ETHERTYPE_IPV6 0x86dd + #endif diff --git a/node/Endpoint.hpp b/node/Endpoint.hpp index bb167e2f6..baf1e9697 100644 --- a/node/Endpoint.hpp +++ b/node/Endpoint.hpp @@ -44,24 +44,24 @@ public: ETHERNET = 5 // 48-bit LAN-local Ethernet address }; - inline Endpoint() { memset(reinterpret_cast(this),0,sizeof(Endpoint)); } + ZT_ALWAYS_INLINE Endpoint() { memset(reinterpret_cast(this),0,sizeof(Endpoint)); } - inline Endpoint(const InetAddress &sa) : _t(INETADDR) { _v.sa = sa; } - inline Endpoint(const Address &zt,const uint8_t identityHash[ZT_IDENTITY_HASH_SIZE]) : _t(ZEROTIER) { _v.zt.a = zt.toInt(); memcpy(_v.zt.idh,identityHash,ZT_IDENTITY_HASH_SIZE); } - inline Endpoint(const char *name,const int port) : _t(DNSNAME) { Utils::scopy(_v.dns.name,sizeof(_v.dns.name),name); _v.dns.port = port; } - inline Endpoint(const char *url) : _t(URL) { Utils::scopy(_v.url,sizeof(_v.url),url); } + ZT_ALWAYS_INLINE Endpoint(const InetAddress &sa) : _t(INETADDR) { _v.sa = sa; } + ZT_ALWAYS_INLINE Endpoint(const Address &zt,const uint8_t identityHash[ZT_IDENTITY_HASH_SIZE]) : _t(ZEROTIER) { _v.zt.a = zt.toInt(); memcpy(_v.zt.idh,identityHash,ZT_IDENTITY_HASH_SIZE); } + ZT_ALWAYS_INLINE Endpoint(const char *name,const int port) : _t(DNSNAME) { Utils::scopy(_v.dns.name,sizeof(_v.dns.name),name); _v.dns.port = port; } + ZT_ALWAYS_INLINE Endpoint(const char *url) : _t(URL) { Utils::scopy(_v.url,sizeof(_v.url),url); } - inline const InetAddress *sockaddr() const { return (_t == INETADDR) ? reinterpret_cast(&_v.sa) : nullptr; } - inline const char *dnsName() const { return (_t == DNSNAME) ? _v.dns.name : nullptr; } - inline const int dnsPort() const { return (_t == DNSNAME) ? _v.dns.port : -1; } - inline Address ztAddress() const { return (_t == ZEROTIER) ? Address(_v.zt.a) : Address(); } - inline const uint8_t *ztIdentityHash() const { return (_t == ZEROTIER) ? _v.zt.idh : nullptr; } - inline const char *url() const { return (_t == URL) ? _v.url : nullptr; } - inline MAC ethernet() const { return (_t == ETHERNET) ? MAC(_v.eth) : MAC(); } + ZT_ALWAYS_INLINE const InetAddress *sockaddr() const { return (_t == INETADDR) ? reinterpret_cast(&_v.sa) : nullptr; } + ZT_ALWAYS_INLINE const char *dnsName() const { return (_t == DNSNAME) ? _v.dns.name : nullptr; } + ZT_ALWAYS_INLINE const int dnsPort() const { return (_t == DNSNAME) ? _v.dns.port : -1; } + ZT_ALWAYS_INLINE Address ztAddress() const { return (_t == ZEROTIER) ? Address(_v.zt.a) : Address(); } + ZT_ALWAYS_INLINE const uint8_t *ztIdentityHash() const { return (_t == ZEROTIER) ? _v.zt.idh : nullptr; } + ZT_ALWAYS_INLINE const char *url() const { return (_t == URL) ? _v.url : nullptr; } + ZT_ALWAYS_INLINE MAC ethernet() const { return (_t == ETHERNET) ? MAC(_v.eth) : MAC(); } - inline Type type() const { return _t; } + ZT_ALWAYS_INLINE Type type() const { return _t; } - static inline int marshalSizeMax() { return ZT_ENDPOINT_MARSHAL_SIZE_MAX; } + static ZT_ALWAYS_INLINE int marshalSizeMax() { return ZT_ENDPOINT_MARSHAL_SIZE_MAX; } inline int marshal(uint8_t data[ZT_ENDPOINT_MARSHAL_SIZE_MAX]) const { int p; diff --git a/node/EphemeralKey.hpp b/node/EphemeralKey.hpp deleted file mode 100644 index 613b9a142..000000000 --- a/node/EphemeralKey.hpp +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2023-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. - */ -/****/ - -#ifndef ZT_EPHEMERALKEY_HPP -#define ZT_EPHEMERALKEY_HPP - -#include "Constants.hpp" -#include "C25519.hpp" -#include "ECC384.hpp" -#include "SHA512.hpp" -#include "Buffer.hpp" -#include "Utils.hpp" - -namespace ZeroTier { - -#define ZT_EPHEMERAL_KEY_TYPE_1_PUBLIC_SIZE (ZT_C25519_PUBLIC_KEY_LEN + ZT_ECC384_PUBLIC_KEY_SIZE) -#define ZT_EPHEMERAL_KEY_TYPE_1_PRIVATE_SIZE (ZT_C25519_PRIVATE_KEY_LEN + ZT_ECC384_PRIVATE_KEY_SIZE) - -/** - * An ephemeral key exchanged to implement forward secrecy - * - * This key includes both C25519 and ECC384 keys and key agreement executes - * ECDH for both and hashes the results together. This should be able to be - * FIPS compliant (if the C25519 portion is just considered a nonce) while - * simultaneously being more secure than either curve alone. - * - * Serialization includes only the public portion since ephemeral private - * keys are never shared or stored anywhere. - */ -class EphemeralKey -{ -public: - enum Type - { - NONE = 0, - C25519ECC384 = 1 - }; - - inline EphemeralKey() : _priv(nullptr),_type(NONE) {} - - inline ~EphemeralKey() - { - if (_priv) { - Utils::burn(_priv,ZT_EPHEMERAL_KEY_TYPE_1_PRIVATE_SIZE); - delete [] _priv; - } - } - - inline Type type() const { return (Type)_type; } - inline bool hasPrivate() const { return (_priv != nullptr); } - - inline void generate() - { - if (!_priv) - _priv = new uint8_t[ZT_EPHEMERAL_KEY_TYPE_1_PRIVATE_SIZE]; - C25519::generate(_pub,_priv); - ECC384GenerateKey(_pub + ZT_C25519_PUBLIC_KEY_LEN,_priv + ZT_C25519_PRIVATE_KEY_LEN); - _type = C25519ECC384; - } - - inline bool agree(const EphemeralKey &theirs,uint8_t key[ZT_PEER_SECRET_KEY_LENGTH]) const - { - if ((_priv)&&(_type == 1)) { - uint8_t rawkey[128],h[48]; - C25519::agree(_priv,theirs._pub,rawkey); - ECC384ECDH(theirs._pub + ZT_C25519_PUBLIC_KEY_LEN,_priv + ZT_C25519_PRIVATE_KEY_LEN,rawkey + ZT_C25519_SHARED_KEY_LEN); - SHA384(h,rawkey,ZT_C25519_SHARED_KEY_LEN + ZT_ECC384_SHARED_SECRET_SIZE); - memcpy(key,h,ZT_PEER_SECRET_KEY_LENGTH); - return true; - } - return false; - } - - template - inline void serialize(Buffer &b) const - { - b.append(_type); - if (_type == C25519ECC384) - b.append(_pub,ZT_EPHEMERAL_KEY_TYPE_1_PUBLIC_SIZE); - } - - template - inline unsigned int deserialize(const Buffer &b,unsigned int startAt = 0) - { - unsigned int p = startAt; - delete [] _priv; - _priv = nullptr; - switch(b[p++]) { - case C25519ECC384: - memcpy(_pub,b.field(p,ZT_EPHEMERAL_KEY_TYPE_1_PUBLIC_SIZE),ZT_EPHEMERAL_KEY_TYPE_1_PUBLIC_SIZE); - p += ZT_EPHEMERAL_KEY_TYPE_1_PUBLIC_SIZE; - break; - default: - _type = NONE; - break; - } - return (p - startAt); - } - -private: - uint8_t *_priv; - uint8_t _pub[ZT_EPHEMERAL_KEY_TYPE_1_PUBLIC_SIZE]; - uint8_t _type; -}; - -} // namespace ZeroTier - -#endif diff --git a/node/Hashtable.hpp b/node/Hashtable.hpp index 60344ae09..73e6f5ace 100644 --- a/node/Hashtable.hpp +++ b/node/Hashtable.hpp @@ -33,10 +33,10 @@ class Hashtable private: struct _Bucket { - inline _Bucket(const K &k,const V &v) : k(k),v(v) {} - inline _Bucket(const K &k) : k(k),v() {} - inline _Bucket(const _Bucket &b) : k(b.k),v(b.v) {} - inline _Bucket &operator=(const _Bucket &b) { k = b.k; v = b.v; return *this; } + ZT_ALWAYS_INLINE _Bucket(const K &k,const V &v) : k(k),v(v) {} + ZT_ALWAYS_INLINE _Bucket(const K &k) : k(k),v() {} + ZT_ALWAYS_INLINE _Bucket(const _Bucket &b) : k(b.k),v(b.v) {} + ZT_ALWAYS_INLINE _Bucket &operator=(const _Bucket &b) { k = b.k; v = b.v; return *this; } _Bucket *next; // must be set manually for each _Bucket const K k; V v; @@ -56,7 +56,7 @@ public: /** * @param ht Hash table to iterate over */ - inline Iterator(Hashtable &ht) : + ZT_ALWAYS_INLINE Iterator(Hashtable &ht) : _idx(0), _ht(&ht), _b(ht._t[0]) @@ -68,7 +68,7 @@ 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) + ZT_ALWAYS_INLINE bool next(K *&kptr,V *&vptr) { for(;;) { if (_b) { @@ -358,23 +358,23 @@ public: /** * @return Number of entries */ - inline unsigned long size() const { return _s; } + ZT_ALWAYS_INLINE unsigned long size() const { return _s; } /** * @return True if table is empty */ - inline bool empty() const { return (_s == 0); } + ZT_ALWAYS_INLINE bool empty() const { return (_s == 0); } private: template - static inline unsigned long _hc(const O &obj) { return (unsigned long)obj.hashCode(); } + static ZT_ALWAYS_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)); } - static inline unsigned long _hc(const uint32_t i) { return ((unsigned long)i * (unsigned long)0x9e3779b1); } - static inline unsigned long _hc(const uint16_t i) { return ((unsigned long)i * (unsigned long)0x9e3779b1); } - static inline unsigned long _hc(const int i) { return ((unsigned long)i * (unsigned long)0x9e3379b1); } - static inline unsigned long _hc(void *p) { return ((unsigned long)((uintptr_t)p) * (unsigned long)0x9e3779b1); } - static inline unsigned long _hc(const void *p) { return ((unsigned long)((uintptr_t)p) * (unsigned long)0x9e3779b1); } + static ZT_ALWAYS_INLINE unsigned long _hc(const uint64_t i) { return (unsigned long)(i ^ (i >> 32)); } + static ZT_ALWAYS_INLINE unsigned long _hc(const uint32_t i) { return ((unsigned long)i * (unsigned long)0x9e3779b1); } + static ZT_ALWAYS_INLINE unsigned long _hc(const uint16_t i) { return ((unsigned long)i * (unsigned long)0x9e3779b1); } + static ZT_ALWAYS_INLINE unsigned long _hc(const int i) { return ((unsigned long)i * (unsigned long)0x9e3379b1); } + static ZT_ALWAYS_INLINE unsigned long _hc(void *p) { return ((unsigned long)((uintptr_t)p) * (unsigned long)0x9e3779b1); } + static ZT_ALWAYS_INLINE unsigned long _hc(const void *p) { return ((unsigned long)((uintptr_t)p) * (unsigned long)0x9e3779b1); } inline void _grow() { diff --git a/node/IncomingPacket.hpp b/node/IncomingPacket.hpp index 6451847c6..1e7219380 100644 --- a/node/IncomingPacket.hpp +++ b/node/IncomingPacket.hpp @@ -46,7 +46,7 @@ class Network; class IncomingPacket : public Packet { public: - inline IncomingPacket() : Packet(),_receiveTime(0),_path() {} + ZT_ALWAYS_INLINE IncomingPacket() : Packet(),_receiveTime(0),_path() {} /** * Create a new packet-in-decode @@ -57,7 +57,7 @@ public: * @param now Current time * @throws std::out_of_range Range error processing packet */ - inline IncomingPacket(const void *data,unsigned int len,const SharedPtr &path,int64_t now) : + ZT_ALWAYS_INLINE IncomingPacket(const void *data,unsigned int len,const SharedPtr &path,int64_t now) : Packet(data,len), _receiveTime(now), _path(path) @@ -73,7 +73,7 @@ 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,int64_t now) + ZT_ALWAYS_INLINE void init(const void *data,unsigned int len,const SharedPtr &path,int64_t now) { copyFrom(data,len); _receiveTime = now; @@ -98,7 +98,7 @@ public: /** * @return Time of packet receipt / start of decode */ - inline uint64_t receiveTime() const { return _receiveTime; } + ZT_ALWAYS_INLINE uint64_t receiveTime() const { return _receiveTime; } private: uint64_t _receiveTime; diff --git a/node/InetAddress.hpp b/node/InetAddress.hpp index f6dc56f17..707109a34 100644 --- a/node/InetAddress.hpp +++ b/node/InetAddress.hpp @@ -75,59 +75,55 @@ struct InetAddress : public sockaddr_storage 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(); } - }; + // Hasher for unordered sets and maps in C++11 + struct Hasher { ZT_ALWAYS_INLINE std::size_t operator()(const InetAddress &a) const { return (std::size_t)a.hashCode(); } }; - inline InetAddress() { memset(this,0,sizeof(InetAddress)); } - inline InetAddress(const InetAddress &a) { memcpy(this,&a,sizeof(InetAddress)); } - inline InetAddress(const InetAddress *a) { memcpy(this,a,sizeof(InetAddress)); } - inline InetAddress(const struct sockaddr_storage &ss) { *this = ss; } - inline InetAddress(const struct sockaddr_storage *ss) { *this = ss; } - inline InetAddress(const struct sockaddr &sa) { *this = sa; } - inline InetAddress(const struct sockaddr *sa) { *this = sa; } - inline InetAddress(const struct sockaddr_in &sa) { *this = sa; } - inline InetAddress(const struct sockaddr_in *sa) { *this = sa; } - inline InetAddress(const struct sockaddr_in6 &sa) { *this = sa; } - inline InetAddress(const struct sockaddr_in6 *sa) { *this = sa; } - inline InetAddress(const void *ipBytes,unsigned int ipLen,unsigned int port) { this->set(ipBytes,ipLen,port); } - inline InetAddress(const uint32_t ipv4,unsigned int port) { this->set(&ipv4,4,port); } - inline InetAddress(const char *ipSlashPort) { this->fromString(ipSlashPort); } + ZT_ALWAYS_INLINE InetAddress() { memset(this,0,sizeof(InetAddress)); } + ZT_ALWAYS_INLINE InetAddress(const InetAddress &a) { memcpy(this,&a,sizeof(InetAddress)); } + ZT_ALWAYS_INLINE InetAddress(const InetAddress *a) { memcpy(this,a,sizeof(InetAddress)); } + ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_storage &ss) { *this = ss; } + ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_storage *ss) { *this = ss; } + ZT_ALWAYS_INLINE InetAddress(const struct sockaddr &sa) { *this = sa; } + ZT_ALWAYS_INLINE InetAddress(const struct sockaddr *sa) { *this = sa; } + ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_in &sa) { *this = sa; } + ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_in *sa) { *this = sa; } + ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_in6 &sa) { *this = sa; } + ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_in6 *sa) { *this = sa; } + ZT_ALWAYS_INLINE InetAddress(const void *ipBytes,unsigned int ipLen,unsigned int port) { this->set(ipBytes,ipLen,port); } + ZT_ALWAYS_INLINE InetAddress(const uint32_t ipv4,unsigned int port) { this->set(&ipv4,4,port); } + ZT_ALWAYS_INLINE InetAddress(const char *ipSlashPort) { this->fromString(ipSlashPort); } - inline void clear() { memset(this,0,sizeof(InetAddress)); } + ZT_ALWAYS_INLINE void clear() { memset(this,0,sizeof(InetAddress)); } - inline InetAddress &operator=(const InetAddress &a) + ZT_ALWAYS_INLINE InetAddress &operator=(const InetAddress &a) { if (&a != this) memcpy(this,&a,sizeof(InetAddress)); return *this; } - inline InetAddress &operator=(const InetAddress *a) + ZT_ALWAYS_INLINE InetAddress &operator=(const InetAddress *a) { if (a != this) memcpy(this,a,sizeof(InetAddress)); return *this; } - inline InetAddress &operator=(const struct sockaddr_storage &ss) + ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr_storage &ss) { if (reinterpret_cast(&ss) != this) memcpy(this,&ss,sizeof(InetAddress)); return *this; } - inline InetAddress &operator=(const struct sockaddr_storage *ss) + ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr_storage *ss) { if (reinterpret_cast(ss) != this) memcpy(this,ss,sizeof(InetAddress)); return *this; } - inline InetAddress &operator=(const struct sockaddr_in &sa) + ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr_in &sa) { if (reinterpret_cast(&sa) != this) { memset(this,0,sizeof(InetAddress)); @@ -136,7 +132,7 @@ struct InetAddress : public sockaddr_storage return *this; } - inline InetAddress &operator=(const struct sockaddr_in *sa) + ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr_in *sa) { if (reinterpret_cast(sa) != this) { memset(this,0,sizeof(InetAddress)); @@ -145,7 +141,7 @@ struct InetAddress : public sockaddr_storage return *this; } - inline InetAddress &operator=(const struct sockaddr_in6 &sa) + ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr_in6 &sa) { if (reinterpret_cast(&sa) != this) { memset(this,0,sizeof(InetAddress)); @@ -154,7 +150,7 @@ struct InetAddress : public sockaddr_storage return *this; } - inline InetAddress &operator=(const struct sockaddr_in6 *sa) + ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr_in6 *sa) { if (reinterpret_cast(sa) != this) { memset(this,0,sizeof(InetAddress)); @@ -163,7 +159,7 @@ struct InetAddress : public sockaddr_storage return *this; } - inline InetAddress &operator=(const struct sockaddr &sa) + ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr &sa) { if (reinterpret_cast(&sa) != this) { memset(this,0,sizeof(InetAddress)); @@ -179,7 +175,7 @@ struct InetAddress : public sockaddr_storage return *this; } - inline InetAddress &operator=(const struct sockaddr *sa) + ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr *sa) { if (reinterpret_cast(sa) != this) { memset(this,0,sizeof(InetAddress)); @@ -214,7 +210,7 @@ struct InetAddress : public sockaddr_storage * * @param port Port, 0 to 65535 */ - inline void setPort(unsigned int port) + ZT_ALWAYS_INLINE void setPort(unsigned int port) { switch(ss_family) { case AF_INET: @@ -229,7 +225,7 @@ struct InetAddress : public sockaddr_storage /** * @return True if this network/netmask route describes a default route (e.g. 0.0.0.0/0) */ - inline bool isDefaultRoute() const + ZT_ALWAYS_INLINE bool isDefaultRoute() const { switch(ss_family) { case AF_INET: @@ -264,7 +260,7 @@ struct InetAddress : public sockaddr_storage /** * @return Port or 0 if no port component defined */ - inline unsigned int port() const + ZT_ALWAYS_INLINE unsigned int port() const { switch(ss_family) { case AF_INET: return Utils::ntoh((uint16_t)(reinterpret_cast(this)->sin_port)); @@ -282,12 +278,12 @@ struct InetAddress : public sockaddr_storage * * @return Netmask bits */ - inline unsigned int netmaskBits() const { return port(); } + ZT_ALWAYS_INLINE unsigned int netmaskBits() const { return port(); } /** * @return True if netmask bits is valid for the address type */ - inline bool netmaskBitsValid() const + ZT_ALWAYS_INLINE bool netmaskBitsValid() const { const unsigned int n = port(); switch(ss_family) { @@ -305,7 +301,7 @@ struct InetAddress : public sockaddr_storage * * @return Gateway metric */ - inline unsigned int metric() const { return port(); } + ZT_ALWAYS_INLINE unsigned int metric() const { return port(); } /** * Construct a full netmask as an InetAddress @@ -350,17 +346,17 @@ struct InetAddress : public sockaddr_storage /** * @return True if this is an IPv4 address */ - inline bool isV4() const { return (ss_family == AF_INET); } + ZT_ALWAYS_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); } + ZT_ALWAYS_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 + ZT_ALWAYS_INLINE const void *rawIpData() const { switch(ss_family) { case AF_INET: return (const void *)&(reinterpret_cast(this)->sin_addr.s_addr); @@ -372,7 +368,7 @@ struct InetAddress : public sockaddr_storage /** * @return InetAddress containing only the IP portion of this address and a zero port, or NULL if not IPv4 or IPv6 */ - inline InetAddress ipOnly() const + ZT_ALWAYS_INLINE InetAddress ipOnly() const { InetAddress r; switch(ss_family) { @@ -394,7 +390,7 @@ 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 + ZT_ALWAYS_INLINE bool ipsEqual(const InetAddress &a) const { if (ss_family == a.ss_family) { if (ss_family == AF_INET) @@ -414,7 +410,7 @@ 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 + ZT_ALWAYS_INLINE bool ipsEqual2(const InetAddress &a) const { if (ss_family == a.ss_family) { if (ss_family == AF_INET) @@ -426,7 +422,7 @@ struct InetAddress : public sockaddr_storage return false; } - inline unsigned long hashCode() const + ZT_ALWAYS_INLINE unsigned long hashCode() const { if (ss_family == AF_INET) { return ((unsigned long)reinterpret_cast(this)->sin_addr.s_addr + (unsigned long)reinterpret_cast(this)->sin_port); @@ -448,7 +444,7 @@ struct InetAddress : public sockaddr_storage /** * Set to null/zero */ - inline void zero() { memset(this,0,sizeof(InetAddress)); } + ZT_ALWAYS_INLINE void zero() { memset(this,0,sizeof(InetAddress)); } /** * Check whether this is a network/route rather than an IP assignment @@ -463,7 +459,7 @@ struct InetAddress : public sockaddr_storage /** * @return 14-bit (0-16383) hash of this IP's first 24 or 48 bits (for V4 or V6) for rate limiting code, or 0 if non-IP */ - inline unsigned long rateGateHash() const + ZT_ALWAYS_INLINE unsigned long rateGateHash() const { unsigned long h = 0; switch(ss_family) { @@ -487,10 +483,10 @@ struct InetAddress : public sockaddr_storage /** * @return True if address family is non-zero */ - inline operator bool() const { return (ss_family != 0); } + ZT_ALWAYS_INLINE operator bool() const { return (ss_family != 0); } // Marshal interface /////////////////////////////////////////////////////// - static inline int marshalSizeMax() { return 19; } + static ZT_ALWAYS_INLINE int marshalSizeMax() { return 19; } inline int marshal(uint8_t restrict data[19]) const { switch(ss_family) { @@ -608,10 +604,10 @@ struct InetAddress : public sockaddr_storage 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); } + ZT_ALWAYS_INLINE bool operator!=(const InetAddress &a) const { return !(*this == a); } + ZT_ALWAYS_INLINE bool operator>(const InetAddress &a) const { return (a < *this); } + ZT_ALWAYS_INLINE bool operator<=(const InetAddress &a) const { return !(a < *this); } + ZT_ALWAYS_INLINE bool operator>=(const InetAddress &a) const { return !(*this < a); } /** * @param mac MAC address seed diff --git a/node/Locator.hpp b/node/Locator.hpp index fef06b55c..63c8061c8 100644 --- a/node/Locator.hpp +++ b/node/Locator.hpp @@ -35,12 +35,12 @@ namespace ZeroTier { class Locator { public: - inline Locator() : _ts(0),_endpointCount(0),_signatureLength(0) {} + ZT_ALWAYS_INLINE Locator() : _ts(0),_endpointCount(0),_signatureLength(0) {} /** * @return Timestamp (a.k.a. revision number) set by Location signer */ - inline int64_t timestamp() const { return _ts; } + ZT_ALWAYS_INLINE int64_t timestamp() const { return _ts; } /** * Create and sign a Locator @@ -85,10 +85,10 @@ public: return id.verify(signData,signLen,_signature,_signatureLength); } - inline operator bool() const { return (_ts != 0); } + ZT_ALWAYS_INLINE operator bool() const { return (_ts != 0); } // Marshal interface /////////////////////////////////////////////////////// - static inline int marshalSizeMax() { return ZT_LOCATOR_MARSHAL_SIZE_MAX; } + static ZT_ALWAYS_INLINE int marshalSizeMax() { return ZT_LOCATOR_MARSHAL_SIZE_MAX; } inline int marshal(uint8_t restrict data[ZT_LOCATOR_MARSHAL_SIZE_MAX],const bool excludeSignature = false) const { if ((_endpointCount > ZT_LOCATOR_MAX_ENDPOINTS)||(_signatureLength > ZT_SIGNATURE_BUFFER_SIZE)) diff --git a/node/MAC.hpp b/node/MAC.hpp index d200a7cad..c60186aa9 100644 --- a/node/MAC.hpp +++ b/node/MAC.hpp @@ -187,7 +187,7 @@ public: ZT_ALWAYS_INLINE unsigned long hashCode() const { return (unsigned long)_m; } - ZT_ALWAYS_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]; diff --git a/node/Meter.hpp b/node/Meter.hpp index 9a12ccdef..301fc97f9 100644 --- a/node/Meter.hpp +++ b/node/Meter.hpp @@ -29,7 +29,7 @@ namespace ZeroTier { class Meter { public: - inline Meter() + ZT_ALWAYS_INLINE Meter() { for(int i=0;i - inline void log(const int64_t now,I count) + ZT_ALWAYS_INLINE void log(const int64_t now,I count) { const int64_t since = now - _ts; if (since >= ZT_METER_HISTORY_TICK_DURATION) { @@ -50,7 +50,7 @@ public: } } - inline double perSecond(const int64_t now) const + ZT_ALWAYS_INLINE double perSecond(const int64_t now) const { double r = 0.0,n = 0.0; const int64_t since = (now - _ts); diff --git a/node/MulticastGroup.hpp b/node/MulticastGroup.hpp index 2ce1667ea..e3deebdb6 100644 --- a/node/MulticastGroup.hpp +++ b/node/MulticastGroup.hpp @@ -41,8 +41,8 @@ namespace ZeroTier { class MulticastGroup { public: - inline MulticastGroup() : _mac(),_adi(0) {} - inline MulticastGroup(const MAC &m,uint32_t a) : _mac(m),_adi(a) {} + ZT_ALWAYS_INLINE MulticastGroup() : _mac(),_adi(0) {} + ZT_ALWAYS_INLINE MulticastGroup(const MAC &m,uint32_t a) : _mac(m),_adi(a) {} /** * Derive the multicast group used for address resolution (ARP/NDP) for an IP @@ -50,7 +50,7 @@ public: * @param ip IP address (port field is ignored) * @return Multicast group for ARP/NDP */ - static inline MulticastGroup deriveMulticastGroupForAddressResolution(const InetAddress &ip) + static ZT_ALWAYS_INLINE MulticastGroup deriveMulticastGroupForAddressResolution(const InetAddress &ip) { if (ip.isV4()) { // IPv4 wants broadcast MACs, so we shove the V4 address itself into @@ -72,37 +72,16 @@ public: /** * @return Ethernet MAC portion of multicast group */ - inline const MAC &mac() const { return _mac; } + ZT_ALWAYS_INLINE const MAC &mac() const { return _mac; } /** * @return Additional distinguishing information, which is normally zero except for IPv4 ARP where it's the IPv4 address */ - inline uint32_t adi() const { return _adi; } + ZT_ALWAYS_INLINE uint32_t adi() const { return _adi; } - /** - * @return 32-bit non-cryptographic hash ID of this multicast group - */ - inline uint32_t id() const - { - uint64_t m = _mac.toInt(); - uint32_t x1 = _adi; - uint32_t x2 = (uint32_t)(m >> 32); - uint32_t x3 = (uint32_t)m; - x1 = ((x1 >> 16) ^ x1) * 0x45d9f3b; - x2 = ((x2 >> 16) ^ x2) * 0x45d9f3b; - x3 = ((x3 >> 16) ^ x3) * 0x45d9f3b; - x1 = ((x1 >> 16) ^ x1) * 0x45d9f3b; - x2 = ((x2 >> 16) ^ x2) * 0x45d9f3b; - x3 = ((x3 >> 16) ^ x3) * 0x45d9f3b; - x1 = (x1 >> 16) ^ x1; - x2 = (x2 >> 16) ^ x2; - x3 = (x3 >> 16) ^ x3; - return (x1 ^ x2 ^ x3); - } - - 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 + ZT_ALWAYS_INLINE bool operator==(const MulticastGroup &g) const { return ((_mac == g._mac)&&(_adi == g._adi)); } + ZT_ALWAYS_INLINE bool operator!=(const MulticastGroup &g) const { return ((_mac != g._mac)||(_adi != g._adi)); } + ZT_ALWAYS_INLINE bool operator<(const MulticastGroup &g) const { if (_mac < g._mac) return true; @@ -110,11 +89,11 @@ public: 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); } + ZT_ALWAYS_INLINE bool operator>(const MulticastGroup &g) const { return (g < *this); } + ZT_ALWAYS_INLINE bool operator<=(const MulticastGroup &g) const { return !(g < *this); } + ZT_ALWAYS_INLINE bool operator>=(const MulticastGroup &g) const { return !(*this < g); } - inline unsigned long hashCode() const { return (_mac.hashCode() ^ (unsigned long)_adi); } + ZT_ALWAYS_INLINE unsigned long hashCode() const { return (_mac.hashCode() ^ (unsigned long)_adi); } private: MAC _mac; diff --git a/node/Switch.cpp b/node/Switch.cpp index 1b76bf082..39893df27 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -125,6 +125,8 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre return; if (destination != RR->identity.address()) { + // This packet is not for this node, so possibly relay it ---------- + Packet packet(data,len); if (packet.hops() < ZT_RELAY_MAX_HOPS) { packet.incrementHops(); @@ -146,8 +148,9 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre } } } + } else if ((reinterpret_cast(data)[ZT_PACKET_IDX_FLAGS] & ZT_PROTO_FLAG_FRAGMENTED) != 0) { - // Packet is the head of a fragmented packet series + // Packet is the head of a fragmented packet series ---------------- const uint64_t packetId = ( (((uint64_t)reinterpret_cast(data)[0]) << 56) | @@ -172,10 +175,10 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre rq->haveFragments = 1; rq->complete = false; } else if (!(rq->haveFragments & 1)) { - // If we have other fragments but no head, see if we are complete with the head + // Check if packet is complete ----------------------------------- if ((rq->totalFragments > 1)&&(Utils::countBits(rq->haveFragments |= 1) == rq->totalFragments)) { - // We have all fragments -- assemble and process full Packet + // We have all fragments -- assemble and process full Packet --- rq->frag0.init(data,len,path,now); for(unsigned int f=1;ftotalFragments;++f) @@ -186,13 +189,17 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre } else { rq->complete = true; // set complete flag but leave entry since it probably needs WHOIS or something } + } else { - // Still waiting on more fragments, but keep the head + // Still waiting on more fragments, but keep the head ---------- + rq->frag0.init(data,len,path,now); + } } // else this is a duplicate head, ignore } else { - // Packet is unfragmented, so just process it + + // Packet is unfragmented, so just process it ---------------------- IncomingPacket packet(data,len,path,now); if (!packet.tryDecode(RR,tPtr)) { RXQueueEntry *const rq = _nextRXQueueEntry(); @@ -204,6 +211,7 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre rq->haveFragments = 1; rq->complete = true; } + } // -------------------------------------------------------------------- @@ -364,10 +372,12 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr &network,const len); */ } else if (to == network->mac()) { - // Destination is this node, so just reinject it + // Destination is this node, so just reinject it ------------------------- + RR->node->putFrame(tPtr,network->id(),network->userPtr(),from,to,etherType,vlanId,data,len); + } else if (to[0] == MAC::firstOctetForNetwork(network->id())) { - // Destination is another ZeroTier peer on the same network + // Destination is another ZeroTier peer on the same network -------------- Address toZT(to.toAddress(network->id())); // since in-network MACs are derived from addresses and network IDs, we can reverse this SharedPtr toPeer(RR->topology->get(toZT)); @@ -400,7 +410,7 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr &network,const aqm_enqueue(tPtr,network,outp,true,qosBucket); } } else { - // Destination is bridged behind a remote peer + // Destination is bridged behind a remote peer --------------------------- // We filter with a NULL destination ZeroTier address first. Filtrations // for each ZT destination are also done below. This is the same rationale diff --git a/node/Switch.hpp b/node/Switch.hpp index 7d7278635..6b36960fa 100644 --- a/node/Switch.hpp +++ b/node/Switch.hpp @@ -31,16 +31,6 @@ #include "IncomingPacket.hpp" #include "Hashtable.hpp" -/* 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_ATALK 0x809b -#define ZT_ETHERTYPE_AARP 0x80f3 -#define ZT_ETHERTYPE_IPX_A 0x8137 -#define ZT_ETHERTYPE_IPX_B 0x8138 -#define ZT_ETHERTYPE_IPV6 0x86dd - namespace ZeroTier { class RuntimeEnvironment; diff --git a/node/Topology.hpp b/node/Topology.hpp index c65901ef4..0e44f3ccb 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -161,7 +161,7 @@ public: * @tparam F Function or function object type */ template - inline void eachPeer(F f) + ZT_ALWAYS_INLINE void eachPeer(F f) { Mutex::Lock l(_peers_l); Hashtable< Address,SharedPtr >::Iterator i(_peers); @@ -191,7 +191,7 @@ public: /** * @param allPeers vector to fill with all current peers */ - inline void getAllPeers(std::vector< SharedPtr > &allPeers) const + ZT_ALWAYS_INLINE void getAllPeers(std::vector< SharedPtr > &allPeers) const { Mutex::Lock l(_peers_l); allPeers.clear(); diff --git a/node/Utils.cpp b/node/Utils.cpp index fa29968a5..d2da7d779 100644 --- a/node/Utils.cpp +++ b/node/Utils.cpp @@ -107,40 +107,7 @@ char *decimal(unsigned long n,char s[24]) unsigned short crc16(const void *buf,unsigned int len) { - static const uint16_t crc16tab[256]= { - 0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7, - 0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef, - 0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6, - 0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de, - 0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485, - 0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d, - 0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4, - 0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc, - 0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823, - 0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b, - 0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12, - 0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a, - 0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41, - 0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49, - 0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70, - 0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78, - 0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f, - 0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067, - 0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e, - 0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256, - 0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d, - 0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405, - 0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c, - 0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634, - 0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab, - 0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3, - 0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a, - 0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92, - 0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9, - 0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1, - 0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8, - 0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0 - }; + static const uint16_t crc16tab[256]= { 0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6,0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d,0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4,0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823,0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b,0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12,0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41,0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49,0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f,0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067,0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d,0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405,0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634,0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab,0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92,0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9,0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0 }; uint16_t crc = 0; const uint8_t *p = (const uint8_t *)buf; for(unsigned int i=0;i(h++)); - if (!hc) break; + s[0] = HEXCHARS[(i >> 36) & 0xf]; + s[1] = HEXCHARS[(i >> 32) & 0xf]; + s[2] = HEXCHARS[(i >> 28) & 0xf]; + s[3] = HEXCHARS[(i >> 24) & 0xf]; + s[4] = HEXCHARS[(i >> 20) & 0xf]; + s[5] = HEXCHARS[(i >> 16) & 0xf]; + s[6] = HEXCHARS[(i >> 12) & 0xf]; + s[7] = HEXCHARS[(i >> 8) & 0xf]; + s[8] = HEXCHARS[(i >> 4) & 0xf]; + s[9] = HEXCHARS[i & 0xf]; + s[10] = (char)0; + return s; +} - uint8_t c = 0; - if ((hc >= 48)&&(hc <= 57)) // 0..9 - c = hc - 48; - else if ((hc >= 97)&&(hc <= 102)) // a..f - c = hc - 87; - else if ((hc >= 65)&&(hc <= 70)) // A..F - c = hc - 55; - - hc = *(reinterpret_cast(h++)); - if (!hc) break; - - c <<= 4; - if ((hc >= 48)&&(hc <= 57)) - c |= hc - 48; - else if ((hc >= 97)&&(hc <= 102)) - c |= hc - 87; - else if ((hc >= 65)&&(hc <= 70)) - c |= hc - 55; - - reinterpret_cast(buf)[l++] = c; +char *hex(const void *d,unsigned int l,char *s) +{ + char *const save = s; + for(unsigned int i=0;i(d)[i]; + *(s++) = HEXCHARS[b >> 4]; + *(s++) = HEXCHARS[b & 0xf]; } - return l; + *s = (char)0; + return save; } unsigned int unhex(const char *h,unsigned int hlen,void *buf,unsigned int buflen) diff --git a/node/Utils.hpp b/node/Utils.hpp index 130c32348..89f30e905 100644 --- a/node/Utils.hpp +++ b/node/Utils.hpp @@ -89,21 +89,7 @@ static inline char *hex(I x,char *s) * @param s Buffer of size [11] to receive 10 hex characters * @return Pointer to buffer */ -static inline char *hex10(uint64_t i,char s[11]) -{ - s[0] = HEXCHARS[(i >> 36) & 0xf]; - s[1] = HEXCHARS[(i >> 32) & 0xf]; - s[2] = HEXCHARS[(i >> 28) & 0xf]; - s[3] = HEXCHARS[(i >> 24) & 0xf]; - s[4] = HEXCHARS[(i >> 20) & 0xf]; - s[5] = HEXCHARS[(i >> 16) & 0xf]; - s[6] = HEXCHARS[(i >> 12) & 0xf]; - s[7] = HEXCHARS[(i >> 8) & 0xf]; - s[8] = HEXCHARS[(i >> 4) & 0xf]; - s[9] = HEXCHARS[i & 0xf]; - s[10] = (char)0; - return s; -} +char *hex10(uint64_t i,char s[11]); /** * Convert a byte array into hex @@ -113,19 +99,17 @@ static inline char *hex10(uint64_t i,char s[11]) * @param s String buffer, must be at least (l*2)+1 in size or overflow will occur * @return Pointer to filled string buffer */ -static inline char *hex(const void *d,unsigned int l,char *s) -{ - char *const save = s; - for(unsigned int i=0;i(d)[i]; - *(s++) = HEXCHARS[b >> 4]; - *(s++) = HEXCHARS[b & 0xf]; - } - *s = (char)0; - return save; -} +char *hex(const void *d,unsigned int l,char *s); -unsigned int unhex(const char *h,void *buf,unsigned int buflen); +/** + * Decode a hex string + * + * @param h Hex C-string (non hex chars are ignored) + * @param hlen Maximum length of string (will stop at terminating zero) + * @param buf Output buffer + * @param buflen Length of output buffer + * @return Number of written bytes + */ unsigned int unhex(const char *h,unsigned int hlen,void *buf,unsigned int buflen); /** @@ -165,6 +149,19 @@ int b32d(const char *encoded, uint8_t *result, int bufSize); */ uint64_t random(); +/** + * Perform a safe C string copy, ALWAYS null-terminating the result + * + * This will never ever EVER result in dest[] not being null-terminated + * regardless of any input parameter (other than len==0 which is invalid). + * + * @param dest Destination buffer (must not be NULL) + * @param len Length of dest[] (if zero, false is returned and nothing happens) + * @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) + */ +bool scopy(char *dest,unsigned int len,const char *src); + static ZT_ALWAYS_INLINE float normalize(float value, int64_t bigMin, int64_t bigMax, int32_t targetMin, int32_t targetMax) { int64_t bigSpan = bigMax - bigMin; @@ -230,19 +227,6 @@ static ZT_ALWAYS_INLINE long long hexStrTo64(const char *s) #endif } -/** - * Perform a safe C string copy, ALWAYS null-terminating the result - * - * This will never ever EVER result in dest[] not being null-terminated - * regardless of any input parameter (other than len==0 which is invalid). - * - * @param dest Destination buffer (must not be NULL) - * @param len Length of dest[] (if zero, false is returned and nothing happens) - * @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) - */ -bool scopy(char *dest,unsigned int len,const char *src); - /** * Calculate a non-cryptographic hash of a byte string * @@ -281,11 +265,21 @@ static ZT_ALWAYS_INLINE unsigned int countBits(T v) } #endif -// Byte swappers for big/little endian conversion #if __BYTE_ORDER == __LITTLE_ENDIAN static ZT_ALWAYS_INLINE uint8_t hton(uint8_t n) { return n; } static ZT_ALWAYS_INLINE int8_t hton(int8_t n) { return n; } -static ZT_ALWAYS_INLINE uint16_t hton(uint16_t n) { return htons(n); } +static ZT_ALWAYS_INLINE uint16_t hton(uint16_t n) +{ +#if defined(__GNUC__) +#if defined(__FreeBSD__) + return htons(n); +#elif (!defined(__OpenBSD__)) + return __builtin_bswap16(n); +#endif +#else + return htons(n); +#endif +} static ZT_ALWAYS_INLINE int16_t hton(int16_t n) { return (int16_t)Utils::hton((uint16_t)n); } static ZT_ALWAYS_INLINE uint32_t hton(uint32_t n) { @@ -330,7 +324,18 @@ static ZT_ALWAYS_INLINE T hton(T n) { return n; } #if __BYTE_ORDER == __LITTLE_ENDIAN static ZT_ALWAYS_INLINE uint8_t ntoh(uint8_t n) { return n; } static ZT_ALWAYS_INLINE int8_t ntoh(int8_t n) { return n; } -static ZT_ALWAYS_INLINE uint16_t ntoh(uint16_t n) { return ntohs(n); } +static ZT_ALWAYS_INLINE uint16_t ntoh(uint16_t n) +{ +#if defined(__GNUC__) +#if defined(__FreeBSD__) + return htons(n); +#elif (!defined(__OpenBSD__)) + return __builtin_bswap16(n); +#endif +#else + return htons(n); +#endif +} static ZT_ALWAYS_INLINE int16_t ntoh(int16_t n) { return (int16_t)Utils::ntoh((uint16_t)n); } static ZT_ALWAYS_INLINE uint32_t ntoh(uint32_t n) {