Browse Source

Moar build fixes, clock perf improvement.

Adam Ierymenko 5 years ago
parent
commit
490b9c4d79

+ 3 - 1
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:

+ 4 - 0
go/cmd/zerotier-fuzz/zerotier-fuzz.go

@@ -0,0 +1,4 @@
+package main
+
+func main() {
+}

+ 0 - 1
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

+ 0 - 29
go/cmd/zerotier/cli/selftest.go

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

+ 0 - 3
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":

+ 1 - 1
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{}) {

+ 6 - 2
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))]

+ 2 - 2
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);

+ 2 - 0
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
 {

+ 0 - 26
node/LZ4.hpp

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

+ 32 - 23
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<Address> rootsNotOnline;
 	ZT_INLINE void operator()(const SharedPtr<Peer> &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> &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;

+ 10 - 0
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;

+ 27 - 4
osdep/OSUtils.hpp

@@ -32,6 +32,12 @@
 #include <unistd.h>
 #endif
 
+#ifdef __APPLE__
+#include <mach/mach.h>
+#include <mach/clock.h>
+#include <mach/mach_time.h>
+#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
 	};