This commit is contained in:
Adam Ierymenko 2020-01-07 13:24:15 -08:00
parent 19899de5a6
commit 627533cf48
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
20 changed files with 346 additions and 630 deletions

5
.gitignore vendored
View file

@ -1,5 +1,8 @@
build/
/build
/cmake-build-debug
/cmake-build-release
/version.h
/.idea
.DS_Store
.Trashes
*.swp

7
.idea/ZeroTierOne.iml generated
View file

@ -1,9 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<module classpath="CMake" type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

1
.idea/misc.xml generated
View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>

View file

@ -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
$<$<CONFIG:Debug>:-g>
$<$<CONFIG:DEBUG>:-O0>
$<$<CONFIG:RELEASE>:-Ofast>
$<$<CONFIG:RELEASE>:-fPIE>
$<$<CONFIG:RELEASE>:-flto>
$<$<CONFIG:RELWITHDEBINFO>:-Ofast>
$<$<CONFIG:RELWITHDEBINFO>:-fPIE>
$<$<CONFIG:RELWITHDEBINFO>:-g>
)
add_link_options(
-mmacosx-version-min=10.9
$<$<CONFIG:RELEASE>:-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
$<$<CONFIG:Debug>:-g>
$<$<CONFIG:DEBUG>:-O0>
$<$<CONFIG:RELEASE>:-O3>
$<$<CONFIG:RELEASE>:-fPIE>
$<$<CONFIG:RELWITHDEBINFO>:-O3>
$<$<CONFIG:RELWITHDEBINFO>:-fPIE>
$<$<CONFIG:RELWITHDEBINFO>:-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)

View file

@ -17,7 +17,6 @@ set(core_headers
Credential.hpp
Dictionary.hpp
ECC384.hpp
EphemeralKey.hpp
Hashtable.hpp
Identity.hpp
InetAddress.hpp

View file

@ -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

View file

@ -44,24 +44,24 @@ public:
ETHERNET = 5 // 48-bit LAN-local Ethernet address
};
inline Endpoint() { memset(reinterpret_cast<void *>(this),0,sizeof(Endpoint)); }
ZT_ALWAYS_INLINE Endpoint() { memset(reinterpret_cast<void *>(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<const InetAddress *>(&_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<const InetAddress *>(&_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;

View file

@ -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<unsigned int C>
inline void serialize(Buffer<C> &b) const
{
b.append(_type);
if (_type == C25519ECC384)
b.append(_pub,ZT_EPHEMERAL_KEY_TYPE_1_PUBLIC_SIZE);
}
template<unsigned int C>
inline unsigned int deserialize(const Buffer<C> &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

View file

@ -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<typename O>
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()
{

View file

@ -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> &path,int64_t now) :
ZT_ALWAYS_INLINE IncomingPacket(const void *data,unsigned int len,const SharedPtr<Path> &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> &path,int64_t now)
ZT_ALWAYS_INLINE void init(const void *data,unsigned int len,const SharedPtr<Path> &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;

View file

@ -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<const InetAddress *>(&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<const InetAddress *>(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<const InetAddress *>(&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<const InetAddress *>(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<const InetAddress *>(&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<const InetAddress *>(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<const InetAddress *>(&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<const InetAddress *>(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<const struct sockaddr_in *>(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<const struct sockaddr_in *>(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<const struct sockaddr_in *>(this)->sin_addr.s_addr + (unsigned long)reinterpret_cast<const struct sockaddr_in *>(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

View file

@ -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))

View file

@ -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];

View file

@ -29,7 +29,7 @@ namespace ZeroTier {
class Meter
{
public:
inline Meter()
ZT_ALWAYS_INLINE Meter()
{
for(int i=0;i<ZT_METER_HISTORY_LENGTH;++i)
_history[i] = 0.0;
@ -38,7 +38,7 @@ public:
}
template<typename 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);

View file

@ -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;

View file

@ -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<const uint8_t *>(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<const uint8_t *>(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;f<rq->totalFragments;++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> &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<Peer> toPeer(RR->topology->get(toZT));
@ -400,7 +410,7 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &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

View file

@ -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;

View file

@ -161,7 +161,7 @@ public:
* @tparam F Function or function object type
*/
template<typename F>
inline void eachPeer(F f)
ZT_ALWAYS_INLINE void eachPeer(F f)
{
Mutex::Lock l(_peers_l);
Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers);
@ -191,7 +191,7 @@ public:
/**
* @param allPeers vector to fill with all current peers
*/
inline void getAllPeers(std::vector< SharedPtr<Peer> > &allPeers) const
ZT_ALWAYS_INLINE void getAllPeers(std::vector< SharedPtr<Peer> > &allPeers) const
{
Mutex::Lock l(_peers_l);
allPeers.clear();

View file

@ -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<len;++i)
@ -148,35 +115,32 @@ unsigned short crc16(const void *buf,unsigned int len)
return crc;
}
unsigned int unhex(const char *h,void *buf,unsigned int buflen)
char *hex10(uint64_t i,char s[11])
{
unsigned int l = 0;
while (l < buflen) {
uint8_t hc = *(reinterpret_cast<const uint8_t *>(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<const uint8_t *>(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<uint8_t *>(buf)[l++] = c;
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];
*(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)

View file

@ -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<l;++i) {
const unsigned int b = reinterpret_cast<const uint8_t *>(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)
{