From 490b9c4d797fef95de4c78e79f7b88bdadad1334 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 23 Mar 2020 16:12:45 -0700 Subject: [PATCH] Moar build fixes, clock perf improvement. --- doc/SECURITY.md | 4 +- go/cmd/zerotier-fuzz/zerotier-fuzz.go | 4 ++ go/cmd/zerotier/cli/help.go | 1 - go/cmd/zerotier/cli/selftest.go | 29 -------------- go/cmd/zerotier/zerotier.go | 3 -- go/pkg/zerotier/identity.go | 2 +- go/pkg/zerotier/localconfig.go | 8 +++- node/AES.cpp | 4 +- node/Address.hpp | 2 + node/LZ4.hpp | 26 ------------- node/Node.cpp | 55 ++++++++++++++++----------- osdep/OSUtils.cpp | 10 +++++ osdep/OSUtils.hpp | 31 +++++++++++++-- 13 files changed, 87 insertions(+), 92 deletions(-) create mode 100644 go/cmd/zerotier-fuzz/zerotier-fuzz.go delete mode 100644 go/cmd/zerotier/cli/selftest.go delete mode 100644 node/LZ4.hpp diff --git a/doc/SECURITY.md b/doc/SECURITY.md index b97b3e6c5..b81d0830f 100644 --- a/doc/SECURITY.md +++ b/doc/SECURITY.md @@ -27,7 +27,7 @@ A ZeroTier identity is comprised of one or more cryptographic public keys and a #### Identity Types and Corresponding Algorithms * **Type 0** (v1.x and v2.x): one Curve25519 key for elliptic curve Diffie-Hellman and one Ed25519 key for Ed25519 signatures, with the address and fingerprint computed from a hash of both. -* **Type 1** (v2.x only): Curve25519, Ed25519, and NIST P-384 public keys, with the latter being used for signatures (the Ed25519 key is still there but is presently unused) and with *both* keys being used for elliptic curve Diffie-Hellman key agreement. In key agreement the resulting raw secret keys are hashed together using SHA-384 to combine them and yield a single session key. +* **Type 1** (v2.x only): Curve25519, Ed25519, and NIST P-384 public keys, with the latter being used for signatures (the Ed25519 key is still there but is presently unused) and with *both* Curve25519 and NIST P-384 being used for elliptic curve Diffie-Hellman key agreement. In key agreement the resulting raw secret keys are hashed together using SHA-384 to combine them and yield a single session key. Session keys resulting from identity key exchange and agreement are *long-lived keys* that remain static for the lifetime of a particular pair of identities. A different mechanism is used for ephemeral key negotiation. @@ -52,6 +52,8 @@ bzg7fc3sn46fzyxcxw2ev4c4m2u5fyisb3o4wz5hfmvexbzwk6et3fsglkdcn6nnjobxi3bq7hgxqox3 These are too large to type but not to copy/paste, store in databases, or use in scripts and APIs. +Once a device has joined a network, network controllers will remember and check its full identity or identity fingerprint (depending on implementation) rather than just the device's ZeroTier address. + ## VL1 Wire Protocol ZeroTier's wire protocol is packet based with packets having the following format: diff --git a/go/cmd/zerotier-fuzz/zerotier-fuzz.go b/go/cmd/zerotier-fuzz/zerotier-fuzz.go new file mode 100644 index 000000000..da29a2cad --- /dev/null +++ b/go/cmd/zerotier-fuzz/zerotier-fuzz.go @@ -0,0 +1,4 @@ +package main + +func main() { +} diff --git a/go/cmd/zerotier/cli/help.go b/go/cmd/zerotier/cli/help.go index f3a3bb2cd..924deb543 100644 --- a/go/cmd/zerotier/cli/help.go +++ b/go/cmd/zerotier/cli/help.go @@ -37,7 +37,6 @@ Global Options: Commands: help Show this help version Print version - selftest Run internal tests service Start as service status Show ZeroTier status and config peers Show VL1 peers and link information diff --git a/go/cmd/zerotier/cli/selftest.go b/go/cmd/zerotier/cli/selftest.go deleted file mode 100644 index 0f0a0d529..000000000 --- a/go/cmd/zerotier/cli/selftest.go +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c)2013-2020 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: 2024-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. - */ -/****/ - -package cli - -import ( - "fmt" - "os" - - "zerotier/pkg/zerotier" -) - -func SelfTest() { - if !zerotier.SelfTest() { - fmt.Println("FAILED: at least one ZeroTier self-test reported failure.") - os.Exit(1) - } - os.Exit(0) -} diff --git a/go/cmd/zerotier/zerotier.go b/go/cmd/zerotier/zerotier.go index 293bbffd2..f9bddc176 100644 --- a/go/cmd/zerotier/zerotier.go +++ b/go/cmd/zerotier/zerotier.go @@ -123,9 +123,6 @@ func main() { case "version": fmt.Printf("%d.%d.%d\n", zerotier.CoreVersionMajor, zerotier.CoreVersionMinor, zerotier.CoreVersionRevision) os.Exit(0) - case "selftest": - cli.SelfTest() - os.Exit(0) case "service": cli.Service(basePath, authToken, cmdArgs) case "status": diff --git a/go/pkg/zerotier/identity.go b/go/pkg/zerotier/identity.go index 65ee53bc5..1d7dd35de 100644 --- a/go/pkg/zerotier/identity.go +++ b/go/pkg/zerotier/identity.go @@ -46,7 +46,7 @@ type Identity struct { idtype int publicKey []byte privateKey []byte - cid unsafe.Pointer + cid unsafe.Pointer // ZT_Identity } func identityFinalizer(obj interface{}) { diff --git a/go/pkg/zerotier/localconfig.go b/go/pkg/zerotier/localconfig.go index 17bd1d0e2..7f5165324 100644 --- a/go/pkg/zerotier/localconfig.go +++ b/go/pkg/zerotier/localconfig.go @@ -45,10 +45,10 @@ type ExternalAddress struct { // LocalConfigSettings contains node settings type LocalConfigSettings struct { - // PrimaryPort is the main UDP port and must be set (defaults to 9993) + // PrimaryPort is the main UDP port and must be set. PrimaryPort int `json:"primaryPort"` - // SecondaryPort is the secondary UDP port, set to 0 to disbale (picked at random by default) + // SecondaryPort is the secondary UDP port, set to 0 to disable (picked at random by default) SecondaryPort int `json:"secondaryPort"` // PortSearch causes ZeroTier to try other ports automatically if it can't bind to configured ports @@ -100,6 +100,10 @@ func (lc *LocalConfig) Read(p string, saveDefaultsIfNotExist bool, isTotallyNewN if isTotallyNewNode { lc.Settings.PrimaryPort = 793 } else { + // For legacy reasons we keep nodes that already existed prior to 2.0 (upgraded nodes) + // at 9993 by default if there is no existing primary port configured. This is for + // principle of least surprise since some admins may have special firewall rules for + // this port. lc.Settings.PrimaryPort = 9993 } lc.Settings.SecondaryPort = unassignedPrivilegedPorts[randomUInt()%uint(len(unassignedPrivilegedPorts))] diff --git a/node/AES.cpp b/node/AES.cpp index 641ef06ea..9fa6a9456 100644 --- a/node/AES.cpp +++ b/node/AES.cpp @@ -899,7 +899,7 @@ void AES::CTR::finish() noexcept // Software AES and AES key expansion --------------------------------------------------------------------------------- #ifdef ZT_NO_UNALIGNED_ACCESS -static inline uint32_t readuint32_t(const void *in) +static ZT_INLINE uint32_t readuint32_t(const void *in) { uint32_t v = ((const uint8_t *)in)[0]; v <<= 8; @@ -910,7 +910,7 @@ static inline uint32_t readuint32_t(const void *in) v |= ((const uint8_t *)in)[3]; return v; } -static inline void writeuint32_t(void *out,const uint32_t v) +static ZT_INLINE void writeuint32_t(void *out,const uint32_t v) { ((uint8_t *)out)[0] = (uint8_t)(v >> 24); ((uint8_t *)out)[1] = (uint8_t)(v >> 16); diff --git a/node/Address.hpp b/node/Address.hpp index 61a2527f6..66fa9fc17 100644 --- a/node/Address.hpp +++ b/node/Address.hpp @@ -24,6 +24,8 @@ namespace ZeroTier { /** * A ZeroTier address + * + * This is merely a 40-bit short address packed into a uint64_t and wrapped with methods. */ class Address : public TriviallyCopyable { diff --git a/node/LZ4.hpp b/node/LZ4.hpp deleted file mode 100644 index 227dce627..000000000 --- a/node/LZ4.hpp +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c)2013-2020 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: 2024-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_LZ4_HPP -#define ZT_LZ4_HPP - -#include "Constants.hpp" - -namespace ZeroTier { - -int LZ4_compress_fast(const char *source,char *dest,int inputSize,int maxOutputSize,int acceleration = 1) noexcept; -int LZ4_decompress_safe(const char *source,char *dest,int compressedSize,int maxDecompressedSize) noexcept; - -} // namespace ZeroTier - -#endif diff --git a/node/Node.cpp b/node/Node.cpp index 6e3544319..649861570 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -36,6 +36,13 @@ namespace ZeroTier { namespace { +/** + * All core objects of a ZeroTier node. + * + * This is just a box that allows us to allocate all core objects + * and data structures at once for a bit of memory saves and improved + * cache adjacency. + */ struct _NodeObjects { ZT_INLINE _NodeObjects(RuntimeEnvironment *const RR,void *const tPtr) : @@ -190,11 +197,17 @@ ZT_ResultCode Node::processVirtualNetworkFrame( } } -struct _processBackgroundTasks_ping_eachPeer +struct _processBackgroundTasks_eachPeer { - int64_t now; - Node *parent; - void *tPtr; + ZT_INLINE _processBackgroundTasks_eachPeer(const int64_t now_,Node *const parent_,void *const tPtr_) : + now(now_), + parent(parent_), + tPtr(tPtr_), + online(false), + rootsNotOnline() {} + const int64_t now; + Node *const parent; + void *const tPtr; bool online; std::vector
rootsNotOnline; ZT_INLINE void operator()(const SharedPtr &peer,const bool isRoot) @@ -209,22 +222,25 @@ struct _processBackgroundTasks_ping_eachPeer } } }; - -static uint8_t keepAlivePayload = 0; // junk payload for keepalive packets -struct _processBackgroundTasks_path_keepalive +struct _processBackgroundTasks_eachPath { - int64_t now; - RuntimeEnvironment *RR; - void *tPtr; + ZT_INLINE _processBackgroundTasks_eachPath(const int64_t now_,const RuntimeEnvironment *const RR_,void *const tPtr_) : + now(now_), + RR(RR_), + tPtr(tPtr_), + keepAlivePayload((uint8_t)now_) {} + const int64_t now; + const RuntimeEnvironment *const RR; + void *const tPtr; + uint8_t keepAlivePayload; ZT_INLINE void operator()(const SharedPtr &path) { if ((now - path->lastOut()) >= ZT_PATH_KEEPALIVE_PERIOD) { ++keepAlivePayload; - path->send(RR,tPtr,&keepAlivePayload,1,now); + path->send(RR,tPtr,&keepAlivePayload,sizeof(keepAlivePayload),now); } } }; - ZT_ResultCode Node::processBackgroundTasks(void *tPtr, int64_t now, volatile int64_t *nextBackgroundTaskDeadline) { _now = now; @@ -233,12 +249,8 @@ ZT_ResultCode Node::processBackgroundTasks(void *tPtr, int64_t now, volatile int if ((now - _lastPing) >= ZT_PEER_PING_PERIOD) { _lastPing = now; try { - _processBackgroundTasks_ping_eachPeer pf; - pf.now = now; - pf.parent = this; - pf.tPtr = tPtr; - pf.online = false; - RR->topology->eachPeerWithRoot<_processBackgroundTasks_ping_eachPeer &>(pf); + _processBackgroundTasks_eachPeer pf(now,this,tPtr); + RR->topology->eachPeerWithRoot<_processBackgroundTasks_eachPeer &>(pf); if (pf.online != _online) { _online = pf.online; @@ -300,11 +312,8 @@ ZT_ResultCode Node::processBackgroundTasks(void *tPtr, int64_t now, volatile int if ((now - _lastPathKeepaliveCheck) >= ZT_PATH_KEEPALIVE_PERIOD) { _lastPathKeepaliveCheck = now; - _processBackgroundTasks_path_keepalive pf; - pf.now = now; - pf.RR = RR; - pf.tPtr = tPtr; - RR->topology->eachPath<_processBackgroundTasks_path_keepalive &>(pf); + _processBackgroundTasks_eachPath pf(now,RR,tPtr); + RR->topology->eachPath<_processBackgroundTasks_eachPath &>(pf); } int64_t earliestAlarmAt = 0x7fffffffffffffffLL; diff --git a/osdep/OSUtils.cpp b/osdep/OSUtils.cpp index 1390bc68a..3e733b2c9 100644 --- a/osdep/OSUtils.cpp +++ b/osdep/OSUtils.cpp @@ -30,6 +30,16 @@ namespace ZeroTier { +#ifdef __APPLE__ +static clock_serv_t _machGetRealtimeClock() noexcept +{ + clock_serv_t c; + host_get_clock_service(mach_host_self(),CALENDAR_CLOCK,&c); + return c; +} +static clock_serv_t s_machRealtimeClock = _machGetRealtimeClock(); +#endif + unsigned int OSUtils::ztsnprintf(char *buf,unsigned int len,const char *fmt,...) { va_list ap; diff --git a/osdep/OSUtils.hpp b/osdep/OSUtils.hpp index 48ea69520..4d4aa6970 100644 --- a/osdep/OSUtils.hpp +++ b/osdep/OSUtils.hpp @@ -32,6 +32,12 @@ #include #endif +#ifdef __APPLE__ +#include +#include +#include +#endif + #ifndef OMIT_JSON_SUPPORT #include "../ext/json/json.hpp" #endif @@ -43,6 +49,11 @@ namespace ZeroTier { */ class OSUtils { +private: +#ifdef __APPLE__ + static clock_serv_t s_machRealtimeClock; +#endif + public: /** * Variant of snprintf that is portable and throws an exception @@ -161,14 +172,26 @@ public: tmp.LowPart = ft.dwLowDateTime; tmp.HighPart = ft.dwHighDateTime; return (int64_t)( ((tmp.QuadPart - 116444736000000000LL) / 10000L) + st.wMilliseconds ); +#else +#ifdef __LINUX__ + timespec ts; +#ifdef CLOCK_REALTIME_COARSE + clock_gettime(CLOCK_REALTIME_COARSE,&ts); +#else + clock_gettime(CLOCK_REALTIME,&ts); +#endif + return ( (1000LL * (int64_t)ts.tv_sec) + ((int64_t)(ts.tv_nsec / 1000000)) ); +#else +#ifdef __APPLE__ + mach_timespec_t mts; + clock_get_time(s_machRealtimeClock,&mts); + return ( (1000LL * (int64_t)mts.tv_sec) + ((int64_t)(mts.tv_nsec / 1000000)) ); #else timeval tv; -// #ifdef __LINUX__ -// syscall(SYS_gettimeofday,&tv,0); /* fix for musl libc broken gettimeofday bug */ -// #else gettimeofday(&tv,(struct timezone *)0); -// #endif return ( (1000LL * (int64_t)tv.tv_sec) + (int64_t)(tv.tv_usec / 1000) ); +#endif +#endif #endif };