Big core refactor to create a CallContext to carry several annoying state variables through the call chain. Also remove some warnings.

This commit is contained in:
Adam Ierymenko 2021-04-06 17:33:00 -04:00
parent 0f4d18c4ed
commit 89e9eb755e
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
65 changed files with 1572 additions and 1494 deletions

View file

@ -82,6 +82,7 @@ if(NOT PACKAGE_STATIC)
-Wno-deprecated -Wno-deprecated
-Wno-unused-function -Wno-unused-function
-Wno-format -Wno-format
-Wno-attributes
$<$<CONFIG:DEBUG>:-g> $<$<CONFIG:DEBUG>:-g>
$<$<CONFIG:DEBUG>:-O0> $<$<CONFIG:DEBUG>:-O0>
$<$<CONFIG:RELEASE>:-O3> $<$<CONFIG:RELEASE>:-O3>
@ -125,6 +126,7 @@ if(NOT PACKAGE_STATIC)
-Wall -Wall
-Wno-deprecated -Wno-deprecated
-Wno-unused-function -Wno-unused-function
-Wno-attributes
-mmacosx-version-min=${MACOS_VERSION_MIN} -mmacosx-version-min=${MACOS_VERSION_MIN}
$<$<CONFIG:DEBUG>:-g> $<$<CONFIG:DEBUG>:-g>
$<$<CONFIG:DEBUG>:-O0> $<$<CONFIG:DEBUG>:-O0>
@ -157,6 +159,7 @@ if(NOT PACKAGE_STATIC)
-Wno-deprecated -Wno-deprecated
-Wno-unused-function -Wno-unused-function
-Wno-format -Wno-format
-Wno-attributes
$<$<CONFIG:DEBUG>:-g> $<$<CONFIG:DEBUG>:-g>
$<$<CONFIG:DEBUG>:-O0> $<$<CONFIG:DEBUG>:-O0>
$<$<CONFIG:RELEASE>:-O3> $<$<CONFIG:RELEASE>:-O3>

View file

@ -12,15 +12,12 @@
/****/ /****/
#include "Buf.hpp" #include "Buf.hpp"
#include "Spinlock.hpp"
#ifdef __WINDOWS__
#define sched_yield() Sleep(0)
#endif
namespace ZeroTier { namespace ZeroTier {
static std::atomic<uintptr_t> s_pool(0); static std::atomic< uintptr_t > s_pool(0);
static std::atomic<long> s_allocated(0); static std::atomic< long > s_allocated(0);
// uintptr_max can never be a valid pointer, so use it to indicate that s_pool is locked (very short duration spinlock) // uintptr_max can never be a valid pointer, so use it to indicate that s_pool is locked (very short duration spinlock)
#define ZT_ATOMIC_PTR_LOCKED (~((uintptr_t)0)) #define ZT_ATOMIC_PTR_LOCKED (~((uintptr_t)0))
@ -29,45 +26,44 @@ void *Buf::operator new(std::size_t sz)
{ {
uintptr_t bb; uintptr_t bb;
for (;;) { for (;;) {
bb = s_pool.exchange(ZT_ATOMIC_PTR_LOCKED); bb = s_pool.exchange(ZT_ATOMIC_PTR_LOCKED, std::memory_order_acquire);
if (bb != ZT_ATOMIC_PTR_LOCKED) if (likely(bb != ZT_ATOMIC_PTR_LOCKED))
break; break;
sched_yield(); Spinlock::pause();
} }
Buf *b; Buf *b;
if (bb) { if (bb) {
s_pool.store(((Buf *) bb)->__nextInPool); s_pool.store(((Buf *)bb)->__nextInPool.load(std::memory_order_relaxed), std::memory_order_release);
b = (Buf *) bb; b = (Buf *)bb;
} else { } else {
s_pool.store(0); s_pool.store(0, std::memory_order_release);
b = (Buf *) malloc(sz); b = (Buf *)malloc(sz);
if (!b) if (!b)
throw Utils::BadAllocException; throw Utils::BadAllocException;
++s_allocated; s_allocated.fetch_add(1, std::memory_order_relaxed);
} }
b->__refCount.store(0); b->__refCount.store(0, std::memory_order_relaxed);
return (void *) b; return (void *)b;
} }
void Buf::operator delete(void *ptr) void Buf::operator delete(void *ptr)
{ {
if (ptr) { if (ptr) {
if (s_allocated.load() > ZT_BUF_MAX_POOL_SIZE) { if (s_allocated.load(std::memory_order_relaxed) > ZT_BUF_MAX_POOL_SIZE) {
--s_allocated;
free(ptr); free(ptr);
} else { } else {
uintptr_t bb; uintptr_t bb;
for (;;) { for (;;) {
bb = s_pool.exchange(ZT_ATOMIC_PTR_LOCKED); bb = s_pool.exchange(ZT_ATOMIC_PTR_LOCKED, std::memory_order_acquire);
if (bb != ZT_ATOMIC_PTR_LOCKED) if (likely(bb != ZT_ATOMIC_PTR_LOCKED))
break; break;
sched_yield(); Spinlock::pause();
} }
((Buf *) ptr)->__nextInPool.store(bb); ((Buf *)ptr)->__nextInPool.store(bb, std::memory_order_relaxed);
s_pool.store((uintptr_t) ptr); s_pool.store((uintptr_t)ptr, std::memory_order_release);
} }
} }
} }
@ -76,24 +72,23 @@ void Buf::freePool() noexcept
{ {
uintptr_t bb; uintptr_t bb;
for (;;) { for (;;) {
bb = s_pool.exchange(ZT_ATOMIC_PTR_LOCKED); bb = s_pool.exchange(ZT_ATOMIC_PTR_LOCKED, std::memory_order_acquire);
if (bb != ZT_ATOMIC_PTR_LOCKED) if (likely(bb != ZT_ATOMIC_PTR_LOCKED))
break; break;
sched_yield(); Spinlock::pause();
} }
s_pool.store(0);
s_pool.store(0, std::memory_order_release);
while (bb != 0) { while (bb != 0) {
const uintptr_t next = ((Buf *) bb)->__nextInPool; const uintptr_t next = ((Buf *)bb)->__nextInPool.load(std::memory_order_relaxed);
--s_allocated; s_allocated.fetch_sub(1, std::memory_order_relaxed);
free((void *) bb); free((void *)bb);
bb = next; bb = next;
} }
} }
long Buf::poolAllocated() noexcept long Buf::poolAllocated() noexcept
{ { return s_allocated.load(std::memory_order_relaxed); }
return s_allocated.load();
}
} // namespace ZeroTier } // namespace ZeroTier

View file

@ -286,7 +286,7 @@ public:
/** /**
* Set all memory to zero * Set all memory to zero
*/ */
ZT_INLINE void clear() noexcept ZT_MAYBE_UNUSED ZT_INLINE void clear() noexcept
{ {
Utils::zero< ZT_BUF_MEM_SIZE >(unsafeData); Utils::zero< ZT_BUF_MEM_SIZE >(unsafeData);
} }
@ -297,7 +297,7 @@ public:
* @param ii Index value-result parameter (incremented by 1) * @param ii Index value-result parameter (incremented by 1)
* @return Byte (undefined on overflow) * @return Byte (undefined on overflow)
*/ */
ZT_INLINE uint8_t rI8(int &ii) const noexcept ZT_MAYBE_UNUSED ZT_INLINE uint8_t rI8(int &ii) const noexcept
{ {
const int s = ii++; const int s = ii++;
return unsafeData[(unsigned int)s & ZT_BUF_MEM_MASK]; return unsafeData[(unsigned int)s & ZT_BUF_MEM_MASK];
@ -309,7 +309,7 @@ public:
* @param ii Index value-result parameter (incremented by 2) * @param ii Index value-result parameter (incremented by 2)
* @return Integer (undefined on overflow) * @return Integer (undefined on overflow)
*/ */
ZT_INLINE uint16_t rI16(int &ii) const noexcept ZT_MAYBE_UNUSED ZT_INLINE uint16_t rI16(int &ii) const noexcept
{ {
const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK; const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK;
ii += 2; ii += 2;
@ -328,7 +328,7 @@ public:
* @param ii Index value-result parameter (incremented by 4) * @param ii Index value-result parameter (incremented by 4)
* @return Integer (undefined on overflow) * @return Integer (undefined on overflow)
*/ */
ZT_INLINE uint32_t rI32(int &ii) const noexcept ZT_MAYBE_UNUSED ZT_INLINE uint32_t rI32(int &ii) const noexcept
{ {
const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK; const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK;
ii += 4; ii += 4;
@ -349,7 +349,7 @@ public:
* @param ii Index value-result parameter (incremented by 8) * @param ii Index value-result parameter (incremented by 8)
* @return Integer (undefined on overflow) * @return Integer (undefined on overflow)
*/ */
ZT_INLINE uint64_t rI64(int &ii) const noexcept ZT_MAYBE_UNUSED ZT_INLINE uint64_t rI64(int &ii) const noexcept
{ {
const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK; const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK;
ii += 8; ii += 8;
@ -384,7 +384,7 @@ public:
* @return Bytes read or a negative value on unmarshal error (passed from object) or overflow * @return Bytes read or a negative value on unmarshal error (passed from object) or overflow
*/ */
template< typename T > template< typename T >
ZT_INLINE int rO(int &ii, T &obj) const noexcept ZT_MAYBE_UNUSED ZT_INLINE int rO(int &ii, T &obj) const noexcept
{ {
if (likely(ii < ZT_BUF_MEM_SIZE)) { if (likely(ii < ZT_BUF_MEM_SIZE)) {
int ms = obj.unmarshal(unsafeData + ii, ZT_BUF_MEM_SIZE - ii); int ms = obj.unmarshal(unsafeData + ii, ZT_BUF_MEM_SIZE - ii);
@ -406,7 +406,7 @@ public:
* @param bufSize Capacity of buffer in bytes * @param bufSize Capacity of buffer in bytes
* @return Pointer to buf or NULL on overflow or error * @return Pointer to buf or NULL on overflow or error
*/ */
ZT_INLINE char *rS(int &ii, char *const buf, const unsigned int bufSize) const noexcept ZT_MAYBE_UNUSED ZT_INLINE char *rS(int &ii, char *const buf, const unsigned int bufSize) const noexcept
{ {
const char *const s = (const char *)(unsafeData + ii); const char *const s = (const char *)(unsafeData + ii);
const int sii = ii; const int sii = ii;
@ -435,7 +435,7 @@ public:
* @param ii Index value-result parameter (incremented by length of string) * @param ii Index value-result parameter (incremented by length of string)
* @return Pointer to null-terminated C-style string or NULL on overflow or error * @return Pointer to null-terminated C-style string or NULL on overflow or error
*/ */
ZT_INLINE const char *rSnc(int &ii) const noexcept ZT_MAYBE_UNUSED ZT_INLINE const char *rSnc(int &ii) const noexcept
{ {
const char *const s = (const char *)(unsafeData + ii); const char *const s = (const char *)(unsafeData + ii);
while (ii < ZT_BUF_MEM_SIZE) { while (ii < ZT_BUF_MEM_SIZE) {
@ -456,7 +456,7 @@ public:
* @param len Length of buffer * @param len Length of buffer
* @return Pointer to data or NULL on overflow or error * @return Pointer to data or NULL on overflow or error
*/ */
ZT_INLINE uint8_t *rB(int &ii, void *const bytes, const unsigned int len) const noexcept ZT_MAYBE_UNUSED ZT_INLINE uint8_t *rB(int &ii, void *const bytes, const unsigned int len) const noexcept
{ {
if (likely(((ii += (int)len) <= ZT_BUF_MEM_SIZE))) { if (likely(((ii += (int)len) <= ZT_BUF_MEM_SIZE))) {
Utils::copy(bytes, unsafeData + ii, len); Utils::copy(bytes, unsafeData + ii, len);
@ -478,7 +478,7 @@ public:
* @param len Length of data field to obtain a pointer to * @param len Length of data field to obtain a pointer to
* @return Pointer to field or NULL on overflow * @return Pointer to field or NULL on overflow
*/ */
ZT_INLINE const uint8_t *rBnc(int &ii, unsigned int len) const noexcept ZT_MAYBE_UNUSED ZT_INLINE const uint8_t *rBnc(int &ii, unsigned int len) const noexcept
{ {
const uint8_t *const b = unsafeData + ii; const uint8_t *const b = unsafeData + ii;
return ((ii += (int)len) <= ZT_BUF_MEM_SIZE) ? b : nullptr; return ((ii += (int)len) <= ZT_BUF_MEM_SIZE) ? b : nullptr;
@ -491,7 +491,7 @@ public:
* @return Value * @return Value
*/ */
template< unsigned int I > template< unsigned int I >
ZT_INLINE uint8_t lI8() const noexcept ZT_MAYBE_UNUSED ZT_INLINE uint8_t lI8() const noexcept
{ {
static_assert(I < ZT_BUF_MEM_SIZE, "overflow"); static_assert(I < ZT_BUF_MEM_SIZE, "overflow");
return unsafeData[I]; return unsafeData[I];
@ -504,7 +504,7 @@ public:
* @return Value * @return Value
*/ */
template< unsigned int I > template< unsigned int I >
ZT_INLINE uint8_t lI16() const noexcept ZT_MAYBE_UNUSED ZT_INLINE uint8_t lI16() const noexcept
{ {
static_assert((I + 1) < ZT_BUF_MEM_SIZE, "overflow"); static_assert((I + 1) < ZT_BUF_MEM_SIZE, "overflow");
#ifdef ZT_NO_UNALIGNED_ACCESS #ifdef ZT_NO_UNALIGNED_ACCESS
@ -523,7 +523,7 @@ public:
* @return Value * @return Value
*/ */
template< unsigned int I > template< unsigned int I >
ZT_INLINE uint8_t lI32() const noexcept ZT_MAYBE_UNUSED ZT_INLINE uint8_t lI32() const noexcept
{ {
static_assert((I + 3) < ZT_BUF_MEM_SIZE, "overflow"); static_assert((I + 3) < ZT_BUF_MEM_SIZE, "overflow");
#ifdef ZT_NO_UNALIGNED_ACCESS #ifdef ZT_NO_UNALIGNED_ACCESS
@ -544,7 +544,7 @@ public:
* @return Value * @return Value
*/ */
template< unsigned int I > template< unsigned int I >
ZT_INLINE uint8_t lI64() const noexcept ZT_MAYBE_UNUSED ZT_INLINE uint8_t lI64() const noexcept
{ {
static_assert((I + 7) < ZT_BUF_MEM_SIZE, "overflow"); static_assert((I + 7) < ZT_BUF_MEM_SIZE, "overflow");
#ifdef ZT_NO_UNALIGNED_ACCESS #ifdef ZT_NO_UNALIGNED_ACCESS
@ -569,7 +569,7 @@ public:
* will not necessarily result in a 'true' return from readOverflow(). It does * will not necessarily result in a 'true' return from readOverflow(). It does
* however subject 'ii' to soft bounds masking like the gI??() methods. * however subject 'ii' to soft bounds masking like the gI??() methods.
*/ */
ZT_INLINE uint8_t lI8(const int ii) const noexcept ZT_MAYBE_UNUSED ZT_INLINE uint8_t lI8(const int ii) const noexcept
{ {
return unsafeData[(unsigned int)ii & ZT_BUF_MEM_MASK]; return unsafeData[(unsigned int)ii & ZT_BUF_MEM_MASK];
} }
@ -581,7 +581,7 @@ public:
* will not necessarily result in a 'true' return from readOverflow(). It does * will not necessarily result in a 'true' return from readOverflow(). It does
* however subject 'ii' to soft bounds masking like the gI??() methods. * however subject 'ii' to soft bounds masking like the gI??() methods.
*/ */
ZT_INLINE uint16_t lI16(const int ii) const noexcept ZT_MAYBE_UNUSED ZT_INLINE uint16_t lI16(const int ii) const noexcept
{ {
const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK; const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK;
#ifdef ZT_NO_UNALIGNED_ACCESS #ifdef ZT_NO_UNALIGNED_ACCESS
@ -600,7 +600,7 @@ public:
* will not necessarily result in a 'true' return from readOverflow(). It does * will not necessarily result in a 'true' return from readOverflow(). It does
* however subject 'ii' to soft bounds masking like the gI??() methods. * however subject 'ii' to soft bounds masking like the gI??() methods.
*/ */
ZT_INLINE uint32_t lI32(const int ii) const noexcept ZT_MAYBE_UNUSED ZT_INLINE uint32_t lI32(const int ii) const noexcept
{ {
const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK; const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK;
#ifdef ZT_NO_UNALIGNED_ACCESS #ifdef ZT_NO_UNALIGNED_ACCESS
@ -621,7 +621,7 @@ public:
* will not necessarily result in a 'true' return from readOverflow(). It does * will not necessarily result in a 'true' return from readOverflow(). It does
* however subject 'ii' to soft bounds masking like the gI??() methods. * however subject 'ii' to soft bounds masking like the gI??() methods.
*/ */
ZT_INLINE uint8_t lI64(const int ii) const noexcept ZT_MAYBE_UNUSED ZT_INLINE uint8_t lI64(const int ii) const noexcept
{ {
const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK; const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK;
#ifdef ZT_NO_UNALIGNED_ACCESS #ifdef ZT_NO_UNALIGNED_ACCESS
@ -645,7 +645,7 @@ public:
* @param ii Index value-result parameter (incremented by 1) * @param ii Index value-result parameter (incremented by 1)
* @param n Byte * @param n Byte
*/ */
ZT_INLINE void wI8(int &ii, const uint8_t n) noexcept ZT_MAYBE_UNUSED ZT_INLINE void wI8(int &ii, const uint8_t n) noexcept
{ {
const int s = ii++; const int s = ii++;
unsafeData[(unsigned int)s & ZT_BUF_MEM_MASK] = n; unsafeData[(unsigned int)s & ZT_BUF_MEM_MASK] = n;
@ -657,7 +657,7 @@ public:
* @param ii Index value-result parameter (incremented by 2) * @param ii Index value-result parameter (incremented by 2)
* @param n Integer * @param n Integer
*/ */
ZT_INLINE void wI16(int &ii, const uint16_t n) noexcept ZT_MAYBE_UNUSED ZT_INLINE void wI16(int &ii, const uint16_t n) noexcept
{ {
const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK; const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK;
ii += 2; ii += 2;
@ -675,7 +675,7 @@ public:
* @param ii Index value-result parameter (incremented by 4) * @param ii Index value-result parameter (incremented by 4)
* @param n Integer * @param n Integer
*/ */
ZT_INLINE void wI32(int &ii, const uint32_t n) noexcept ZT_MAYBE_UNUSED ZT_INLINE void wI32(int &ii, const uint32_t n) noexcept
{ {
const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK; const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK;
ii += 4; ii += 4;
@ -695,7 +695,7 @@ public:
* @param ii Index value-result parameter (incremented by 8) * @param ii Index value-result parameter (incremented by 8)
* @param n Integer * @param n Integer
*/ */
ZT_INLINE void wI64(int &ii, const uint64_t n) noexcept ZT_MAYBE_UNUSED ZT_INLINE void wI64(int &ii, const uint64_t n) noexcept
{ {
const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK; const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK;
ii += 8; ii += 8;
@ -721,7 +721,7 @@ public:
* @param t Object to write * @param t Object to write
*/ */
template< typename T > template< typename T >
ZT_INLINE void wO(int &ii, T &t) noexcept ZT_MAYBE_UNUSED ZT_INLINE void wO(int &ii, T &t) noexcept
{ {
const int s = ii; const int s = ii;
if (likely((s + T::marshalSizeMax()) <= ZT_BUF_MEM_SIZE)) { if (likely((s + T::marshalSizeMax()) <= ZT_BUF_MEM_SIZE)) {
@ -739,7 +739,7 @@ public:
* @param ii Index value-result parameter (incremented by length of string) * @param ii Index value-result parameter (incremented by length of string)
* @param s String to write (writes an empty string if this is NULL) * @param s String to write (writes an empty string if this is NULL)
*/ */
ZT_INLINE void wS(int &ii, const char *s) noexcept ZT_MAYBE_UNUSED ZT_INLINE void wS(int &ii, const char *s) noexcept
{ {
if (s) { if (s) {
char c; char c;
@ -759,7 +759,7 @@ public:
* @param bytes Bytes to write * @param bytes Bytes to write
* @param len Size of data in bytes * @param len Size of data in bytes
*/ */
ZT_INLINE void wB(int &ii, const void *const bytes, const unsigned int len) noexcept ZT_MAYBE_UNUSED ZT_INLINE void wB(int &ii, const void *const bytes, const unsigned int len) noexcept
{ {
const int s = ii; const int s = ii;
if (likely((ii += (int)len) <= ZT_BUF_MEM_SIZE)) if (likely((ii += (int)len) <= ZT_BUF_MEM_SIZE))
@ -772,7 +772,7 @@ public:
* @param ii Index value-result parameter (incremented by len) * @param ii Index value-result parameter (incremented by len)
* @param len Number of zero bytes to write * @param len Number of zero bytes to write
*/ */
ZT_INLINE void wZ(int &ii, const unsigned int len) noexcept ZT_MAYBE_UNUSED ZT_INLINE void wZ(int &ii, const unsigned int len) noexcept
{ {
const int s = ii; const int s = ii;
if (likely((ii += (int)len) <= ZT_BUF_MEM_SIZE)) if (likely((ii += (int)len) <= ZT_BUF_MEM_SIZE))
@ -785,7 +785,7 @@ public:
* @param ii Index value-result parameter (incremented by len) * @param ii Index value-result parameter (incremented by len)
* @param len Number of random bytes to write * @param len Number of random bytes to write
*/ */
ZT_INLINE void wR(int &ii, const unsigned int len) noexcept ZT_MAYBE_UNUSED ZT_INLINE void wR(int &ii, const unsigned int len) noexcept
{ {
const int s = ii; const int s = ii;
if (likely((ii += (int)len) <= ZT_BUF_MEM_SIZE)) if (likely((ii += (int)len) <= ZT_BUF_MEM_SIZE))
@ -795,7 +795,7 @@ public:
/** /**
* Store a byte without advancing the index * Store a byte without advancing the index
*/ */
ZT_INLINE void sI8(const int ii, const uint8_t n) noexcept ZT_MAYBE_UNUSED ZT_INLINE void sI8(const int ii, const uint8_t n) noexcept
{ {
unsafeData[(unsigned int)ii & ZT_BUF_MEM_MASK] = n; unsafeData[(unsigned int)ii & ZT_BUF_MEM_MASK] = n;
} }
@ -803,7 +803,7 @@ public:
/** /**
* Store an integer without advancing the index * Store an integer without advancing the index
*/ */
ZT_INLINE void sI16(const int ii, const uint16_t n) noexcept ZT_MAYBE_UNUSED ZT_INLINE void sI16(const int ii, const uint16_t n) noexcept
{ {
const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK; const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK;
#ifdef ZT_NO_UNALIGNED_ACCESS #ifdef ZT_NO_UNALIGNED_ACCESS
@ -817,7 +817,7 @@ public:
/** /**
* Store an integer without advancing the index * Store an integer without advancing the index
*/ */
ZT_INLINE void sI32(const int ii, const uint32_t n) noexcept ZT_MAYBE_UNUSED ZT_INLINE void sI32(const int ii, const uint32_t n) noexcept
{ {
const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK; const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK;
#ifdef ZT_NO_UNALIGNED_ACCESS #ifdef ZT_NO_UNALIGNED_ACCESS
@ -833,7 +833,7 @@ public:
/** /**
* Store an integer without advancing the index * Store an integer without advancing the index
*/ */
ZT_INLINE void sI64(const int ii, const uint64_t n) noexcept ZT_MAYBE_UNUSED ZT_INLINE void sI64(const int ii, const uint64_t n) noexcept
{ {
const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK; const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK;
#ifdef ZT_NO_UNALIGNED_ACCESS #ifdef ZT_NO_UNALIGNED_ACCESS
@ -853,7 +853,7 @@ public:
/** /**
* @return Capacity of this buffer (usable size of data.bytes) * @return Capacity of this buffer (usable size of data.bytes)
*/ */
static constexpr unsigned int capacity() noexcept ZT_MAYBE_UNUSED static constexpr unsigned int capacity() noexcept
{ return ZT_BUF_MEM_SIZE; } { return ZT_BUF_MEM_SIZE; }
private: private:

View file

@ -19,6 +19,7 @@
#include "InetAddress.hpp" #include "InetAddress.hpp"
#include "VL1.hpp" #include "VL1.hpp"
#include "VL2.hpp" #include "VL2.hpp"
#include "CallContext.hpp"
extern "C" { extern "C" {
@ -30,7 +31,7 @@ extern "C" {
#define ZT_PTRTOBUF(p) ((ZeroTier::Buf *)( ((uintptr_t)(p)) - ((uintptr_t)&(((ZeroTier::Buf *)0)->unsafeData[0])) )) #define ZT_PTRTOBUF(p) ((ZeroTier::Buf *)( ((uintptr_t)(p)) - ((uintptr_t)&(((ZeroTier::Buf *)0)->unsafeData[0])) ))
#define ZT_BUFTOPTR(b) ((void *)(&((b)->unsafeData[0]))) #define ZT_BUFTOPTR(b) ((void *)(&((b)->unsafeData[0])))
void *ZT_getBuffer() ZT_MAYBE_UNUSED void *ZT_getBuffer()
{ {
// When external code requests a Buf, grab one from the pool (or freshly allocated) // When external code requests a Buf, grab one from the pool (or freshly allocated)
// and return it with its reference count left at zero. It's the responsibility of // and return it with its reference count left at zero. It's the responsibility of
@ -44,7 +45,7 @@ void *ZT_getBuffer()
} }
} }
void ZT_freeBuffer(void *b) ZT_MAYBE_UNUSED void ZT_freeBuffer(void *b)
{ {
if (b) if (b)
delete ZT_PTRTOBUF(b); delete ZT_PTRTOBUF(b);
@ -55,13 +56,13 @@ struct p_queryResultBase
void (*freeFunction)(const void *); void (*freeFunction)(const void *);
}; };
void ZT_freeQueryResult(const void *qr) ZT_MAYBE_UNUSED void ZT_freeQueryResult(const void *qr)
{ {
if ((qr) && (reinterpret_cast<const p_queryResultBase *>(qr)->freeFunction)) if ((qr) && (reinterpret_cast<const p_queryResultBase *>(qr)->freeFunction))
reinterpret_cast<const p_queryResultBase *>(qr)->freeFunction(qr); reinterpret_cast<const p_queryResultBase *>(qr)->freeFunction(qr);
} }
void ZT_version(int *major, int *minor, int *revision, int *build) ZT_MAYBE_UNUSED void ZT_version(int *major, int *minor, int *revision, int *build)
{ {
if (major) if (major)
*major = ZEROTIER_VERSION_MAJOR; *major = ZEROTIER_VERSION_MAJOR;
@ -75,11 +76,18 @@ void ZT_version(int *major, int *minor, int *revision, int *build)
/********************************************************************************************************************/ /********************************************************************************************************************/
enum ZT_ResultCode ZT_Node_new(ZT_Node **node, void *uptr, void *tptr, const struct ZT_Node_Callbacks *callbacks, int64_t now) ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_new(
ZT_Node **node,
int64_t clock,
int64_t ticks,
void *tptr,
void *uptr,
const struct ZT_Node_Callbacks *callbacks)
{ {
*node = nullptr; *node = nullptr;
try { try {
*node = reinterpret_cast<ZT_Node *>(new ZeroTier::Node(uptr, tptr, callbacks, now)); ZeroTier::CallContext cc(clock, ticks, tptr);
*node = reinterpret_cast<ZT_Node *>(new ZeroTier::Node(uptr, callbacks, cc));
return ZT_RESULT_OK; return ZT_RESULT_OK;
} catch (std::bad_alloc &exc) { } catch (std::bad_alloc &exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
@ -90,18 +98,24 @@ enum ZT_ResultCode ZT_Node_new(ZT_Node **node, void *uptr, void *tptr, const str
} }
} }
void ZT_Node_delete(ZT_Node *node, void *tPtr) ZT_MAYBE_UNUSED void ZT_Node_delete(
ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr)
{ {
try { try {
reinterpret_cast<ZeroTier::Node *>(node)->shutdown(tPtr); ZeroTier::CallContext cc(clock, ticks, tptr);
reinterpret_cast<ZeroTier::Node *>(node)->shutdown(cc);
delete (reinterpret_cast<ZeroTier::Node *>(node)); delete (reinterpret_cast<ZeroTier::Node *>(node));
} catch (...) {} } catch (...) {}
} }
enum ZT_ResultCode ZT_Node_processWirePacket( ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_processWirePacket(
ZT_Node *node, ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr, void *tptr,
int64_t now,
int64_t localSocket, int64_t localSocket,
const ZT_InetAddress *remoteAddress, const ZT_InetAddress *remoteAddress,
const void *packetData, const void *packetData,
@ -110,8 +124,9 @@ enum ZT_ResultCode ZT_Node_processWirePacket(
volatile int64_t *nextBackgroundTaskDeadline) volatile int64_t *nextBackgroundTaskDeadline)
{ {
try { try {
ZeroTier::CallContext cc(clock, ticks, tptr);
ZeroTier::SharedPtr< ZeroTier::Buf > buf((isZtBuffer) ? ZT_PTRTOBUF(packetData) : new ZeroTier::Buf(packetData, packetLength & ZT_BUF_MEM_MASK)); ZeroTier::SharedPtr< ZeroTier::Buf > buf((isZtBuffer) ? ZT_PTRTOBUF(packetData) : new ZeroTier::Buf(packetData, packetLength & ZT_BUF_MEM_MASK));
reinterpret_cast<ZeroTier::Node *>(node)->RR->vl1->onRemotePacket(tptr, localSocket, *ZeroTier::asInetAddress(remoteAddress), buf, packetLength); reinterpret_cast<ZeroTier::Node *>(node)->RR->vl1->onRemotePacket(cc, localSocket, *ZeroTier::asInetAddress(remoteAddress), buf, packetLength);
} catch (std::bad_alloc &exc) { } catch (std::bad_alloc &exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
} catch (...) { } catch (...) {
@ -121,10 +136,11 @@ enum ZT_ResultCode ZT_Node_processWirePacket(
return ZT_RESULT_OK; return ZT_RESULT_OK;
} }
enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame( ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
ZT_Node *node, ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr, void *tptr,
int64_t now,
uint64_t nwid, uint64_t nwid,
uint64_t sourceMac, uint64_t sourceMac,
uint64_t destMac, uint64_t destMac,
@ -136,10 +152,11 @@ enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
volatile int64_t *nextBackgroundTaskDeadline) volatile int64_t *nextBackgroundTaskDeadline)
{ {
try { try {
ZeroTier::CallContext cc(clock, ticks, tptr);
ZeroTier::SharedPtr< ZeroTier::Network > network(reinterpret_cast<ZeroTier::Node *>(node)->RR->networks->get(nwid)); ZeroTier::SharedPtr< ZeroTier::Network > network(reinterpret_cast<ZeroTier::Node *>(node)->RR->networks->get(nwid));
if (likely(network)) { if (likely(network)) {
ZeroTier::SharedPtr< ZeroTier::Buf > buf((isZtBuffer) ? ZT_PTRTOBUF(frameData) : new ZeroTier::Buf(frameData, frameLength & ZT_BUF_MEM_MASK)); ZeroTier::SharedPtr< ZeroTier::Buf > buf((isZtBuffer) ? ZT_PTRTOBUF(frameData) : new ZeroTier::Buf(frameData, frameLength & ZT_BUF_MEM_MASK));
reinterpret_cast<ZeroTier::Node *>(node)->RR->vl2->onLocalEthernet(tptr, network, ZeroTier::MAC(sourceMac), ZeroTier::MAC(destMac), etherType, vlanId, buf, frameLength); reinterpret_cast<ZeroTier::Node *>(node)->RR->vl2->onLocalEthernet(cc, network, ZeroTier::MAC(sourceMac), ZeroTier::MAC(destMac), etherType, vlanId, buf, frameLength);
return ZT_RESULT_OK; return ZT_RESULT_OK;
} else { } else {
return ZT_RESULT_ERROR_NETWORK_NOT_FOUND; return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
@ -151,10 +168,16 @@ enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
} }
} }
enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node, void *tptr, int64_t now, volatile int64_t *nextBackgroundTaskDeadline) ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_processBackgroundTasks(
ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr,
volatile int64_t *nextBackgroundTaskDeadline)
{ {
try { try {
return reinterpret_cast<ZeroTier::Node *>(node)->processBackgroundTasks(tptr, now, nextBackgroundTaskDeadline); ZeroTier::CallContext cc(clock, ticks, tptr);
return reinterpret_cast<ZeroTier::Node *>(node)->processBackgroundTasks(cc, nextBackgroundTaskDeadline);
} catch (std::bad_alloc &exc) { } catch (std::bad_alloc &exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
} catch (...) { } catch (...) {
@ -162,10 +185,18 @@ enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node, void *tptr, int
} }
} }
enum ZT_ResultCode ZT_Node_join(ZT_Node *node, uint64_t nwid, const ZT_Fingerprint *controllerFingerprint, void *uptr, void *tptr) ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_join(
ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr,
void *uptr,
uint64_t nwid,
const ZT_Fingerprint *controllerFingerprint)
{ {
try { try {
return reinterpret_cast<ZeroTier::Node *>(node)->join(nwid, controllerFingerprint, uptr, tptr); ZeroTier::CallContext cc(clock, ticks, tptr);
return reinterpret_cast<ZeroTier::Node *>(node)->join(nwid, controllerFingerprint, uptr, cc);
} catch (std::bad_alloc &exc) { } catch (std::bad_alloc &exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
} catch (...) { } catch (...) {
@ -173,10 +204,17 @@ enum ZT_ResultCode ZT_Node_join(ZT_Node *node, uint64_t nwid, const ZT_Fingerpri
} }
} }
enum ZT_ResultCode ZT_Node_leave(ZT_Node *node, uint64_t nwid, void **uptr, void *tptr) ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_leave(
ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr,
void **uptr,
uint64_t nwid)
{ {
try { try {
return reinterpret_cast<ZeroTier::Node *>(node)->leave(nwid, uptr, tptr); ZeroTier::CallContext cc(clock, ticks, tptr);
return reinterpret_cast<ZeroTier::Node *>(node)->leave(nwid, uptr, cc);
} catch (std::bad_alloc &exc) { } catch (std::bad_alloc &exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
} catch (...) { } catch (...) {
@ -184,10 +222,18 @@ enum ZT_ResultCode ZT_Node_leave(ZT_Node *node, uint64_t nwid, void **uptr, void
} }
} }
enum ZT_ResultCode ZT_Node_multicastSubscribe(ZT_Node *node, void *tptr, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi) ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_multicastSubscribe(
ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr,
uint64_t nwid,
uint64_t multicastGroup,
unsigned long multicastAdi)
{ {
try { try {
return reinterpret_cast<ZeroTier::Node *>(node)->multicastSubscribe(tptr, nwid, multicastGroup, multicastAdi); ZeroTier::CallContext cc(clock, ticks, tptr);
return reinterpret_cast<ZeroTier::Node *>(node)->multicastSubscribe(cc, nwid, multicastGroup, multicastAdi);
} catch (std::bad_alloc &exc) { } catch (std::bad_alloc &exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
} catch (...) { } catch (...) {
@ -195,10 +241,18 @@ enum ZT_ResultCode ZT_Node_multicastSubscribe(ZT_Node *node, void *tptr, uint64_
} }
} }
enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi) ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_multicastUnsubscribe(
ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr,
uint64_t nwid,
uint64_t multicastGroup,
unsigned long multicastAdi)
{ {
try { try {
return reinterpret_cast<ZeroTier::Node *>(node)->multicastUnsubscribe(nwid, multicastGroup, multicastAdi); ZeroTier::CallContext cc(clock, ticks, tptr);
return reinterpret_cast<ZeroTier::Node *>(node)->multicastUnsubscribe(cc, nwid, multicastGroup, multicastAdi);
} catch (std::bad_alloc &exc) { } catch (std::bad_alloc &exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
} catch (...) { } catch (...) {
@ -206,29 +260,44 @@ enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node, uint64_t nwid, ui
} }
} }
uint64_t ZT_Node_address(ZT_Node *node) ZT_MAYBE_UNUSED uint64_t ZT_Node_address(ZT_Node *node)
{ return reinterpret_cast<ZeroTier::Node *>(node)->RR->identity.address().toInt(); } { return reinterpret_cast<ZeroTier::Node *>(node)->RR->identity.address().toInt(); }
const ZT_Identity *ZT_Node_identity(ZT_Node *node) ZT_MAYBE_UNUSED const ZT_Identity *ZT_Node_identity(ZT_Node *node)
{ return (const ZT_Identity *)(&(reinterpret_cast<ZeroTier::Node *>(node)->identity())); } { return (const ZT_Identity *)(&(reinterpret_cast<ZeroTier::Node *>(node)->identity())); }
void ZT_Node_status(ZT_Node *node, ZT_NodeStatus *status) ZT_MAYBE_UNUSED void ZT_Node_status(
ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr,
ZT_NodeStatus *status)
{ {
try { try {
reinterpret_cast<ZeroTier::Node *>(node)->status(status); reinterpret_cast<ZeroTier::Node *>(node)->status(status);
} catch (...) {} } catch (...) {}
} }
ZT_PeerList *ZT_Node_peers(ZT_Node *node) ZT_MAYBE_UNUSED ZT_PeerList *ZT_Node_peers(
ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr)
{ {
try { try {
return reinterpret_cast<ZeroTier::Node *>(node)->peers(); ZeroTier::CallContext cc(clock, ticks, tptr);
return reinterpret_cast<ZeroTier::Node *>(node)->peers(cc);
} catch (...) { } catch (...) {
return (ZT_PeerList *)0; return (ZT_PeerList *)0;
} }
} }
ZT_VirtualNetworkConfig *ZT_Node_networkConfig(ZT_Node *node, uint64_t nwid) ZT_MAYBE_UNUSED ZT_VirtualNetworkConfig *ZT_Node_networkConfig(
ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr,
uint64_t nwid)
{ {
try { try {
return reinterpret_cast<ZeroTier::Node *>(node)->networkConfig(nwid); return reinterpret_cast<ZeroTier::Node *>(node)->networkConfig(nwid);
@ -237,7 +306,7 @@ ZT_VirtualNetworkConfig *ZT_Node_networkConfig(ZT_Node *node, uint64_t nwid)
} }
} }
ZT_VirtualNetworkList *ZT_Node_networks(ZT_Node *node) ZT_MAYBE_UNUSED ZT_VirtualNetworkList *ZT_Node_networks(ZT_Node *node)
{ {
try { try {
return reinterpret_cast<ZeroTier::Node *>(node)->networks(); return reinterpret_cast<ZeroTier::Node *>(node)->networks();
@ -246,49 +315,67 @@ ZT_VirtualNetworkList *ZT_Node_networks(ZT_Node *node)
} }
} }
int ZT_Node_tryPeer( ZT_MAYBE_UNUSED void ZT_Node_setNetworkUserPtr(
ZT_Node *node, ZT_Node *node,
void *tptr, uint64_t nwid,
const ZT_Fingerprint *fp, void *ptr)
const ZT_Endpoint *endpoint,
int retries)
{ {
try { try {
return reinterpret_cast<ZeroTier::Node *>(node)->tryPeer(tptr, fp, endpoint, retries); reinterpret_cast<ZeroTier::Node *>(node)->setNetworkUserPtr(nwid, ptr);
} catch (...) { } catch (...) {}
return 0;
}
} }
enum ZT_CertificateError ZT_Node_addCertificate( ZT_MAYBE_UNUSED void ZT_Node_setInterfaceAddresses(
ZT_Node *node, ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr,
const ZT_InterfaceAddress *addrs,
unsigned int addrCount)
{
try {
reinterpret_cast<ZeroTier::Node *>(node)->setInterfaceAddresses(addrs, addrCount);
} catch (...) {}
}
ZT_MAYBE_UNUSED enum ZT_CertificateError ZT_Node_addCertificate(
ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr, void *tptr,
int64_t now,
unsigned int localTrust, unsigned int localTrust,
const ZT_Certificate *cert, const ZT_Certificate *cert,
const void *certData, const void *certData,
unsigned int certSize) unsigned int certSize)
{ {
try { try {
return reinterpret_cast<ZeroTier::Node *>(node)->addCertificate(tptr, now, localTrust, cert, certData, certSize); ZeroTier::CallContext cc(clock, ticks, tptr);
return reinterpret_cast<ZeroTier::Node *>(node)->addCertificate(cc, localTrust, cert, certData, certSize);
} catch (...) { } catch (...) {
return ZT_CERTIFICATE_ERROR_INVALID_FORMAT; return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
} }
} }
ZT_SDK_API enum ZT_ResultCode ZT_Node_deleteCertificate( ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_deleteCertificate(
ZT_Node *node, ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr, void *tptr,
const void *serialNo) const void *serialNo)
{ {
try { try {
return reinterpret_cast<ZeroTier::Node *>(node)->deleteCertificate(tptr, serialNo); ZeroTier::CallContext cc(clock, ticks, tptr);
return reinterpret_cast<ZeroTier::Node *>(node)->deleteCertificate(cc, serialNo);
} catch (...) { } catch (...) {
return ZT_RESULT_ERROR_INTERNAL; return ZT_RESULT_ERROR_INTERNAL;
} }
} }
ZT_SDK_API ZT_CertificateList *ZT_Node_listCertificates(ZT_Node *node) ZT_MAYBE_UNUSED ZT_CertificateList *ZT_Node_listCertificates(
ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr)
{ {
try { try {
return reinterpret_cast<ZeroTier::Node *>(node)->listCertificates(); return reinterpret_cast<ZeroTier::Node *>(node)->listCertificates();
@ -297,42 +384,27 @@ ZT_SDK_API ZT_CertificateList *ZT_Node_listCertificates(ZT_Node *node)
} }
} }
void ZT_Node_setNetworkUserPtr(ZT_Node *node, uint64_t nwid, void *ptr) ZT_MAYBE_UNUSED int ZT_Node_sendUserMessage(
{
try {
reinterpret_cast<ZeroTier::Node *>(node)->setNetworkUserPtr(nwid, ptr);
} catch (...) {}
}
void ZT_Node_setInterfaceAddresses(ZT_Node *node, const ZT_InterfaceAddress *addrs, unsigned int addrCount)
{
try {
reinterpret_cast<ZeroTier::Node *>(node)->setInterfaceAddresses(addrs, addrCount);
} catch (...) {}
}
enum ZT_ResultCode ZT_Node_addPeer(
ZT_Node *node, ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr, void *tptr,
const ZT_Identity *id) uint64_t dest,
uint64_t typeId,
const void *data,
unsigned int len)
{ {
try { try {
return reinterpret_cast<ZeroTier::Node *>(node)->addPeer(tptr, id); ZeroTier::CallContext cc(clock, ticks, tptr);
} catch (...) { return reinterpret_cast<ZeroTier::Node *>(node)->sendUserMessage(cc, dest, typeId, data, len);
return ZT_RESULT_ERROR_INTERNAL;
}
}
int ZT_Node_sendUserMessage(ZT_Node *node, void *tptr, uint64_t dest, uint64_t typeId, const void *data, unsigned int len)
{
try {
return reinterpret_cast<ZeroTier::Node *>(node)->sendUserMessage(tptr, dest, typeId, data, len);
} catch (...) { } catch (...) {
return 0; return 0;
} }
} }
void ZT_Node_setController(ZT_Node *node, void *networkControllerInstance) ZT_MAYBE_UNUSED void ZT_Node_setController(
ZT_Node *node,
void *networkControllerInstance)
{ {
try { try {
reinterpret_cast<ZeroTier::Node *>(node)->setController(networkControllerInstance); reinterpret_cast<ZeroTier::Node *>(node)->setController(networkControllerInstance);
@ -341,20 +413,20 @@ void ZT_Node_setController(ZT_Node *node, void *networkControllerInstance)
/********************************************************************************************************************/ /********************************************************************************************************************/
ZT_Locator *ZT_Locator_create( ZT_MAYBE_UNUSED ZT_Locator *ZT_Locator_create(
int64_t ts, int64_t rev,
const ZT_Endpoint *endpoints, const ZT_Endpoint *endpoints,
const ZT_EndpointAttributes *endpointAttributes, // TODO: not used yet const ZT_EndpointAttributes *endpointAttributes,
unsigned int endpointCount, unsigned int endpointCount,
const ZT_Identity *signer) const ZT_Identity *signer)
{ {
try { try {
if ((ts <= 0) || (!endpoints) || (endpointCount == 0) || (!signer)) if ((!endpoints) || (endpointCount == 0) || (!signer))
return nullptr; return nullptr;
ZeroTier::Locator *loc = new ZeroTier::Locator(); ZeroTier::Locator *loc = new ZeroTier::Locator();
for (unsigned int i = 0;i < endpointCount;++i) for (unsigned int i = 0;i < endpointCount;++i)
loc->add(reinterpret_cast< const ZeroTier::Endpoint * >(endpoints)[i], ZeroTier::Locator::EndpointAttributes::DEFAULT); loc->add(reinterpret_cast< const ZeroTier::Endpoint * >(endpoints)[i], ZeroTier::Locator::EndpointAttributes::DEFAULT);
if (!loc->sign(ts, *reinterpret_cast< const ZeroTier::Identity * >(signer))) { if (!loc->sign(rev, *reinterpret_cast< const ZeroTier::Identity * >(signer))) {
delete loc; delete loc;
return nullptr; return nullptr;
} }
@ -364,7 +436,7 @@ ZT_Locator *ZT_Locator_create(
} }
} }
ZT_Locator *ZT_Locator_fromString(const char *str) ZT_MAYBE_UNUSED ZT_Locator *ZT_Locator_fromString(const char *str)
{ {
try { try {
if (!str) if (!str)
@ -380,7 +452,7 @@ ZT_Locator *ZT_Locator_fromString(const char *str)
} }
} }
ZT_Locator *ZT_Locator_unmarshal( ZT_MAYBE_UNUSED ZT_Locator *ZT_Locator_unmarshal(
const void *data, const void *data,
unsigned int len) unsigned int len)
{ {
@ -398,14 +470,14 @@ ZT_Locator *ZT_Locator_unmarshal(
} }
} }
int ZT_Locator_marshal(const ZT_Locator *loc, void *buf, unsigned int bufSize) ZT_MAYBE_UNUSED int ZT_Locator_marshal(const ZT_Locator *loc, void *buf, unsigned int bufSize)
{ {
if ((!loc) || (bufSize < ZT_LOCATOR_MARSHAL_SIZE_MAX)) if ((!loc) || (bufSize < ZT_LOCATOR_MARSHAL_SIZE_MAX))
return -1; return -1;
return reinterpret_cast<const ZeroTier::Locator *>(loc)->marshal(reinterpret_cast<uint8_t *>(buf), false); return reinterpret_cast<const ZeroTier::Locator *>(loc)->marshal(reinterpret_cast<uint8_t *>(buf), false);
} }
char *ZT_Locator_toString( ZT_MAYBE_UNUSED char *ZT_Locator_toString(
const ZT_Locator *loc, const ZT_Locator *loc,
char *buf, char *buf,
int capacity) int capacity)
@ -415,26 +487,24 @@ char *ZT_Locator_toString(
return reinterpret_cast<const ZeroTier::Locator *>(loc)->toString(buf); return reinterpret_cast<const ZeroTier::Locator *>(loc)->toString(buf);
} }
const ZT_Fingerprint *ZT_Locator_fingerprint(const ZT_Locator *loc) ZT_MAYBE_UNUSED const ZT_Fingerprint *ZT_Locator_fingerprint(const ZT_Locator *loc)
{ {
if (!loc) if (!loc)
return nullptr; return nullptr;
return (ZT_Fingerprint *) (&(reinterpret_cast<const ZeroTier::Locator *>(loc)->signer())); return (ZT_Fingerprint *) (&(reinterpret_cast<const ZeroTier::Locator *>(loc)->signer()));
} }
int64_t ZT_Locator_timestamp(const ZT_Locator *loc) ZT_MAYBE_UNUSED int64_t ZT_Locator_revision(const ZT_Locator *loc)
{ {
if (!loc) if (!loc)
return 0; return 0;
return reinterpret_cast<const ZeroTier::Locator *>(loc)->timestamp(); return reinterpret_cast<const ZeroTier::Locator *>(loc)->revision();
} }
unsigned int ZT_Locator_endpointCount(const ZT_Locator *loc) ZT_MAYBE_UNUSED unsigned int ZT_Locator_endpointCount(const ZT_Locator *loc)
{ { return (loc) ? (unsigned int) (reinterpret_cast<const ZeroTier::Locator *>(loc)->endpoints().size()) : 0; }
return (loc) ? (unsigned int) (reinterpret_cast<const ZeroTier::Locator *>(loc)->endpoints().size()) : 0;
}
const ZT_Endpoint *ZT_Locator_endpoint(const ZT_Locator *loc, const unsigned int ep) ZT_MAYBE_UNUSED const ZT_Endpoint *ZT_Locator_endpoint(const ZT_Locator *loc, const unsigned int ep)
{ {
if (!loc) if (!loc)
return nullptr; return nullptr;
@ -443,14 +513,14 @@ const ZT_Endpoint *ZT_Locator_endpoint(const ZT_Locator *loc, const unsigned int
return reinterpret_cast<const ZT_Endpoint *>(&(reinterpret_cast<const ZeroTier::Locator *>(loc)->endpoints()[ep])); return reinterpret_cast<const ZT_Endpoint *>(&(reinterpret_cast<const ZeroTier::Locator *>(loc)->endpoints()[ep]));
} }
int ZT_Locator_verify(const ZT_Locator *loc, const ZT_Identity *signer) ZT_MAYBE_UNUSED int ZT_Locator_verify(const ZT_Locator *loc, const ZT_Identity *signer)
{ {
if ((!loc) || (!signer)) if ((!loc) || (!signer))
return 0; return 0;
return reinterpret_cast<const ZeroTier::Locator *>(loc)->verify(*reinterpret_cast<const ZeroTier::Identity *>(signer)) ? 1 : 0; return reinterpret_cast<const ZeroTier::Locator *>(loc)->verify(*reinterpret_cast<const ZeroTier::Identity *>(signer)) ? 1 : 0;
} }
void ZT_Locator_delete(const ZT_Locator *loc) ZT_MAYBE_UNUSED void ZT_Locator_delete(const ZT_Locator *loc)
{ {
if (loc) if (loc)
delete reinterpret_cast<const ZeroTier::Locator *>(loc); delete reinterpret_cast<const ZeroTier::Locator *>(loc);
@ -458,7 +528,7 @@ void ZT_Locator_delete(const ZT_Locator *loc)
/********************************************************************************************************************/ /********************************************************************************************************************/
ZT_Identity *ZT_Identity_new(enum ZT_IdentityType type) ZT_MAYBE_UNUSED ZT_Identity *ZT_Identity_new(enum ZT_IdentityType type)
{ {
if ((type != ZT_IDENTITY_TYPE_C25519) && (type != ZT_IDENTITY_TYPE_P384)) if ((type != ZT_IDENTITY_TYPE_C25519) && (type != ZT_IDENTITY_TYPE_P384))
return nullptr; return nullptr;
@ -471,7 +541,7 @@ ZT_Identity *ZT_Identity_new(enum ZT_IdentityType type)
} }
} }
ZT_Identity *ZT_Identity_clone(const ZT_Identity *id) ZT_MAYBE_UNUSED ZT_Identity *ZT_Identity_clone(const ZT_Identity *id)
{ {
if (id) { if (id) {
try { try {
@ -483,7 +553,7 @@ ZT_Identity *ZT_Identity_clone(const ZT_Identity *id)
return nullptr; return nullptr;
} }
ZT_Identity *ZT_Identity_fromString(const char *idStr) ZT_MAYBE_UNUSED ZT_Identity *ZT_Identity_fromString(const char *idStr)
{ {
if (!idStr) if (!idStr)
return nullptr; return nullptr;
@ -499,14 +569,14 @@ ZT_Identity *ZT_Identity_fromString(const char *idStr)
} }
} }
int ZT_Identity_validate(const ZT_Identity *id) ZT_MAYBE_UNUSED int ZT_Identity_validate(const ZT_Identity *id)
{ {
if (!id) if (!id)
return 0; return 0;
return reinterpret_cast<const ZeroTier::Identity *>(id)->locallyValidate() ? 1 : 0; return reinterpret_cast<const ZeroTier::Identity *>(id)->locallyValidate() ? 1 : 0;
} }
unsigned int ZT_Identity_sign(const ZT_Identity *id, const void *data, unsigned int len, void *signature, unsigned int signatureBufferLength) ZT_MAYBE_UNUSED unsigned int ZT_Identity_sign(const ZT_Identity *id, const void *data, unsigned int len, void *signature, unsigned int signatureBufferLength)
{ {
if (!id) if (!id)
return 0; return 0;
@ -515,21 +585,21 @@ unsigned int ZT_Identity_sign(const ZT_Identity *id, const void *data, unsigned
return reinterpret_cast<const ZeroTier::Identity *>(id)->sign(data, len, signature, signatureBufferLength); return reinterpret_cast<const ZeroTier::Identity *>(id)->sign(data, len, signature, signatureBufferLength);
} }
int ZT_Identity_verify(const ZT_Identity *id, const void *data, unsigned int len, const void *signature, unsigned int sigLen) ZT_MAYBE_UNUSED int ZT_Identity_verify(const ZT_Identity *id, const void *data, unsigned int len, const void *signature, unsigned int sigLen)
{ {
if ((!id) || (!signature) || (!sigLen)) if ((!id) || (!signature) || (!sigLen))
return 0; return 0;
return reinterpret_cast<const ZeroTier::Identity *>(id)->verify(data, len, signature, sigLen) ? 1 : 0; return reinterpret_cast<const ZeroTier::Identity *>(id)->verify(data, len, signature, sigLen) ? 1 : 0;
} }
enum ZT_IdentityType ZT_Identity_type(const ZT_Identity *id) ZT_MAYBE_UNUSED enum ZT_IdentityType ZT_Identity_type(const ZT_Identity *id)
{ {
if (!id) if (!id)
return (ZT_IdentityType)0; return (ZT_IdentityType)0;
return (enum ZT_IdentityType)reinterpret_cast<const ZeroTier::Identity *>(id)->type(); return (enum ZT_IdentityType)reinterpret_cast<const ZeroTier::Identity *>(id)->type();
} }
char *ZT_Identity_toString(const ZT_Identity *id, char *buf, int capacity, int includePrivate) ZT_MAYBE_UNUSED char *ZT_Identity_toString(const ZT_Identity *id, char *buf, int capacity, int includePrivate)
{ {
if ((!id) || (!buf) || (capacity < ZT_IDENTITY_STRING_BUFFER_LENGTH)) if ((!id) || (!buf) || (capacity < ZT_IDENTITY_STRING_BUFFER_LENGTH))
return nullptr; return nullptr;
@ -537,28 +607,28 @@ char *ZT_Identity_toString(const ZT_Identity *id, char *buf, int capacity, int i
return buf; return buf;
} }
int ZT_Identity_hasPrivate(const ZT_Identity *id) ZT_MAYBE_UNUSED int ZT_Identity_hasPrivate(const ZT_Identity *id)
{ {
if (!id) if (!id)
return 0; return 0;
return reinterpret_cast<const ZeroTier::Identity *>(id)->hasPrivate() ? 1 : 0; return reinterpret_cast<const ZeroTier::Identity *>(id)->hasPrivate() ? 1 : 0;
} }
uint64_t ZT_Identity_address(const ZT_Identity *id) ZT_MAYBE_UNUSED uint64_t ZT_Identity_address(const ZT_Identity *id)
{ {
if (!id) if (!id)
return 0; return 0;
return reinterpret_cast<const ZeroTier::Identity *>(id)->address(); return reinterpret_cast<const ZeroTier::Identity *>(id)->address();
} }
const ZT_Fingerprint *ZT_Identity_fingerprint(const ZT_Identity *id) ZT_MAYBE_UNUSED const ZT_Fingerprint *ZT_Identity_fingerprint(const ZT_Identity *id)
{ {
if (!id) if (!id)
return nullptr; return nullptr;
return &(reinterpret_cast<const ZeroTier::Identity *>(id)->fingerprint()); return &(reinterpret_cast<const ZeroTier::Identity *>(id)->fingerprint());
} }
int ZT_Identity_compare(const ZT_Identity *a, const ZT_Identity *b) ZT_MAYBE_UNUSED int ZT_Identity_compare(const ZT_Identity *a, const ZT_Identity *b)
{ {
if (a) { if (a) {
if (b) { if (b) {
@ -579,7 +649,7 @@ int ZT_Identity_compare(const ZT_Identity *a, const ZT_Identity *b)
} }
} }
void ZT_Identity_delete(const ZT_Identity *id) ZT_MAYBE_UNUSED void ZT_Identity_delete(const ZT_Identity *id)
{ {
if (id) if (id)
delete reinterpret_cast<const ZeroTier::Identity *>(id); delete reinterpret_cast<const ZeroTier::Identity *>(id);
@ -587,7 +657,7 @@ void ZT_Identity_delete(const ZT_Identity *id)
/********************************************************************************************************************/ /********************************************************************************************************************/
int ZT_Certificate_newSubjectUniqueId( ZT_MAYBE_UNUSED int ZT_Certificate_newSubjectUniqueId(
enum ZT_CertificateUniqueIdType type, enum ZT_CertificateUniqueIdType type,
void *uniqueId, void *uniqueId,
int *uniqueIdSize, int *uniqueIdSize,
@ -610,7 +680,7 @@ int ZT_Certificate_newSubjectUniqueId(
} }
} }
int ZT_Certificate_newCSR( ZT_MAYBE_UNUSED int ZT_Certificate_newCSR(
const ZT_Certificate_Subject *subject, const ZT_Certificate_Subject *subject,
const void *uniqueId, const void *uniqueId,
int uniqueIdSize, int uniqueIdSize,
@ -633,7 +703,7 @@ int ZT_Certificate_newCSR(
} }
} }
int ZT_Certificate_sign( ZT_MAYBE_UNUSED int ZT_Certificate_sign(
const ZT_Certificate *cert, const ZT_Certificate *cert,
const ZT_Identity *signer, const ZT_Identity *signer,
void *signedCert, void *signedCert,
@ -658,7 +728,7 @@ int ZT_Certificate_sign(
} }
} }
enum ZT_CertificateError ZT_Certificate_decode( ZT_MAYBE_UNUSED enum ZT_CertificateError ZT_Certificate_decode(
const ZT_Certificate **decodedCert, const ZT_Certificate **decodedCert,
const void *cert, const void *cert,
int certSize, int certSize,
@ -687,7 +757,7 @@ enum ZT_CertificateError ZT_Certificate_decode(
} }
} }
int ZT_Certificate_encode( ZT_MAYBE_UNUSED int ZT_Certificate_encode(
const ZT_Certificate *cert, const ZT_Certificate *cert,
void *encoded, void *encoded,
int *encodedSize) int *encodedSize)
@ -707,7 +777,7 @@ int ZT_Certificate_encode(
} }
} }
enum ZT_CertificateError ZT_Certificate_verify( ZT_MAYBE_UNUSED enum ZT_CertificateError ZT_Certificate_verify(
const ZT_Certificate *cert, const ZT_Certificate *cert,
int64_t clock) int64_t clock)
{ {
@ -720,7 +790,7 @@ enum ZT_CertificateError ZT_Certificate_verify(
} }
} }
const ZT_Certificate *ZT_Certificate_clone(const ZT_Certificate *cert) ZT_MAYBE_UNUSED const ZT_Certificate *ZT_Certificate_clone(const ZT_Certificate *cert)
{ {
try { try {
if (!cert) if (!cert)
@ -731,7 +801,7 @@ const ZT_Certificate *ZT_Certificate_clone(const ZT_Certificate *cert)
} }
} }
void ZT_Certificate_delete(const ZT_Certificate *cert) ZT_MAYBE_UNUSED void ZT_Certificate_delete(const ZT_Certificate *cert)
{ {
try { try {
if (cert) if (cert)
@ -741,7 +811,7 @@ void ZT_Certificate_delete(const ZT_Certificate *cert)
/********************************************************************************************************************/ /********************************************************************************************************************/
char *ZT_Endpoint_toString( ZT_MAYBE_UNUSED char *ZT_Endpoint_toString(
const ZT_Endpoint *ep, const ZT_Endpoint *ep,
char *buf, char *buf,
int capacity) int capacity)
@ -751,7 +821,7 @@ char *ZT_Endpoint_toString(
return reinterpret_cast<const ZeroTier::Endpoint *>(ep)->toString(buf); return reinterpret_cast<const ZeroTier::Endpoint *>(ep)->toString(buf);
} }
int ZT_Endpoint_fromString( ZT_MAYBE_UNUSED int ZT_Endpoint_fromString(
ZT_Endpoint *ep, ZT_Endpoint *ep,
const char *str) const char *str)
{ {
@ -760,7 +830,7 @@ int ZT_Endpoint_fromString(
return reinterpret_cast<ZeroTier::Endpoint *>(ep)->fromString(str) ? ZT_RESULT_OK : ZT_RESULT_ERROR_BAD_PARAMETER; return reinterpret_cast<ZeroTier::Endpoint *>(ep)->fromString(str) ? ZT_RESULT_OK : ZT_RESULT_ERROR_BAD_PARAMETER;
} }
int ZT_Endpoint_fromBytes( ZT_MAYBE_UNUSED int ZT_Endpoint_fromBytes(
ZT_Endpoint *ep, ZT_Endpoint *ep,
const void *bytes, const void *bytes,
unsigned int len) unsigned int len)
@ -772,14 +842,14 @@ int ZT_Endpoint_fromBytes(
/********************************************************************************************************************/ /********************************************************************************************************************/
char *ZT_Fingerprint_toString(const ZT_Fingerprint *fp, char *buf, int capacity) ZT_MAYBE_UNUSED char *ZT_Fingerprint_toString(const ZT_Fingerprint *fp, char *buf, int capacity)
{ {
if (capacity < ZT_FINGERPRINT_STRING_SIZE_MAX) if (capacity < ZT_FINGERPRINT_STRING_SIZE_MAX)
return nullptr; return nullptr;
return reinterpret_cast<const ZeroTier::Fingerprint *>(fp)->toString(buf); return reinterpret_cast<const ZeroTier::Fingerprint *>(fp)->toString(buf);
} }
int ZT_Fingerprint_fromString(ZT_Fingerprint *fp, const char *s) ZT_MAYBE_UNUSED int ZT_Fingerprint_fromString(ZT_Fingerprint *fp, const char *s)
{ {
if ((!fp)||(!s)) if ((!fp)||(!s))
return 0; return 0;
@ -793,13 +863,13 @@ int ZT_Fingerprint_fromString(ZT_Fingerprint *fp, const char *s)
/********************************************************************************************************************/ /********************************************************************************************************************/
void ZT_InetAddress_clear(ZT_InetAddress *ia) ZT_MAYBE_UNUSED void ZT_InetAddress_clear(ZT_InetAddress *ia)
{ {
if (likely(ia != nullptr)) if (likely(ia != nullptr))
ZeroTier::Utils::zero<sizeof(ZT_InetAddress)>(ia); ZeroTier::Utils::zero<sizeof(ZT_InetAddress)>(ia);
} }
char *ZT_InetAddress_toString(const ZT_InetAddress *ia, char *buf, unsigned int cap) ZT_MAYBE_UNUSED char *ZT_InetAddress_toString(const ZT_InetAddress *ia, char *buf, unsigned int cap)
{ {
if (likely((cap > 0)&&(buf != nullptr))) { if (likely((cap > 0)&&(buf != nullptr))) {
if (likely((ia != nullptr)&&(cap >= ZT_INETADDRESS_STRING_SIZE_MAX))) { if (likely((ia != nullptr)&&(cap >= ZT_INETADDRESS_STRING_SIZE_MAX))) {
@ -811,7 +881,7 @@ char *ZT_InetAddress_toString(const ZT_InetAddress *ia, char *buf, unsigned int
return buf; return buf;
} }
int ZT_InetAddress_fromString(ZT_InetAddress *ia, const char *str) ZT_MAYBE_UNUSED int ZT_InetAddress_fromString(ZT_InetAddress *ia, const char *str)
{ {
if (likely((ia != nullptr)&&(str != nullptr))) { if (likely((ia != nullptr)&&(str != nullptr))) {
return (int)reinterpret_cast<ZeroTier::InetAddress *>(ia)->fromString(str); return (int)reinterpret_cast<ZeroTier::InetAddress *>(ia)->fromString(str);
@ -819,53 +889,53 @@ int ZT_InetAddress_fromString(ZT_InetAddress *ia, const char *str)
return 0; return 0;
} }
void ZT_InetAddress_set(ZT_InetAddress *ia, const void *saddr) ZT_MAYBE_UNUSED void ZT_InetAddress_set(ZT_InetAddress *ia, const void *saddr)
{ {
if (likely(ia != nullptr)) if (likely(ia != nullptr))
(*reinterpret_cast<ZeroTier::InetAddress *>(ia)) = reinterpret_cast<const struct sockaddr *>(saddr); (*reinterpret_cast<ZeroTier::InetAddress *>(ia)) = reinterpret_cast<const struct sockaddr *>(saddr);
} }
void ZT_InetAddress_setIpBytes(ZT_InetAddress *ia, const void *ipBytes, unsigned int ipLen, unsigned int port) ZT_MAYBE_UNUSED void ZT_InetAddress_setIpBytes(ZT_InetAddress *ia, const void *ipBytes, unsigned int ipLen, unsigned int port)
{ {
if (likely(ia != nullptr)) if (likely(ia != nullptr))
reinterpret_cast<ZeroTier::InetAddress *>(ia)->set(ipBytes, ipLen, port); reinterpret_cast<ZeroTier::InetAddress *>(ia)->set(ipBytes, ipLen, port);
} }
void ZT_InetAddress_setPort(ZT_InetAddress *ia, unsigned int port) ZT_MAYBE_UNUSED void ZT_InetAddress_setPort(ZT_InetAddress *ia, unsigned int port)
{ {
if (likely(ia != nullptr)) if (likely(ia != nullptr))
reinterpret_cast<ZeroTier::InetAddress *>(ia)->setPort(port); reinterpret_cast<ZeroTier::InetAddress *>(ia)->setPort(port);
} }
unsigned int ZT_InetAddress_port(const ZT_InetAddress *ia) ZT_MAYBE_UNUSED unsigned int ZT_InetAddress_port(const ZT_InetAddress *ia)
{ {
if (likely(ia != nullptr)) if (likely(ia != nullptr))
return reinterpret_cast<const ZeroTier::InetAddress *>(ia)->port(); return reinterpret_cast<const ZeroTier::InetAddress *>(ia)->port();
return 0; return 0;
} }
int ZT_InetAddress_isNil(const ZT_InetAddress *ia) ZT_MAYBE_UNUSED int ZT_InetAddress_isNil(const ZT_InetAddress *ia)
{ {
if (!ia) if (!ia)
return 0; return 0;
return (int)((bool)(*reinterpret_cast<const ZeroTier::InetAddress *>(ia))); return (int)((bool)(*reinterpret_cast<const ZeroTier::InetAddress *>(ia)));
} }
int ZT_InetAddress_isV4(const ZT_InetAddress *ia) ZT_MAYBE_UNUSED int ZT_InetAddress_isV4(const ZT_InetAddress *ia)
{ {
if (!ia) if (!ia)
return 0; return 0;
return (int)(reinterpret_cast<const ZeroTier::InetAddress *>(ia))->isV4(); return (int)(reinterpret_cast<const ZeroTier::InetAddress *>(ia))->isV4();
} }
int ZT_InetAddress_isV6(const ZT_InetAddress *ia) ZT_MAYBE_UNUSED int ZT_InetAddress_isV6(const ZT_InetAddress *ia)
{ {
if (!ia) if (!ia)
return 0; return 0;
return (int)(reinterpret_cast<const ZeroTier::InetAddress *>(ia))->isV6(); return (int)(reinterpret_cast<const ZeroTier::InetAddress *>(ia))->isV6();
} }
unsigned int ZT_InetAddress_ipBytes(const ZT_InetAddress *ia, void *buf) ZT_MAYBE_UNUSED unsigned int ZT_InetAddress_ipBytes(const ZT_InetAddress *ia, void *buf)
{ {
if (ia) { if (ia) {
switch(reinterpret_cast<const ZeroTier::InetAddress *>(ia)->as.sa.sa_family) { switch(reinterpret_cast<const ZeroTier::InetAddress *>(ia)->as.sa.sa_family) {
@ -880,14 +950,14 @@ unsigned int ZT_InetAddress_ipBytes(const ZT_InetAddress *ia, void *buf)
return 0; return 0;
} }
enum ZT_InetAddress_IpScope ZT_InetAddress_ipScope(const ZT_InetAddress *ia) ZT_MAYBE_UNUSED enum ZT_InetAddress_IpScope ZT_InetAddress_ipScope(const ZT_InetAddress *ia)
{ {
if (likely(ia != nullptr)) if (likely(ia != nullptr))
return reinterpret_cast<const ZeroTier::InetAddress *>(ia)->ipScope(); return reinterpret_cast<const ZeroTier::InetAddress *>(ia)->ipScope();
return ZT_IP_SCOPE_NONE; return ZT_IP_SCOPE_NONE;
} }
int ZT_InetAddress_compare(const ZT_InetAddress *a, const ZT_InetAddress *b) ZT_MAYBE_UNUSED int ZT_InetAddress_compare(const ZT_InetAddress *a, const ZT_InetAddress *b)
{ {
if (a) { if (a) {
if (b) { if (b) {
@ -910,7 +980,7 @@ int ZT_InetAddress_compare(const ZT_InetAddress *a, const ZT_InetAddress *b)
/********************************************************************************************************************/ /********************************************************************************************************************/
int ZT_Dictionary_parse(const void *const dict, const unsigned int len, void *const arg, void (*f)(void *, const char *, unsigned int, const void *, unsigned int)) ZT_MAYBE_UNUSED int ZT_Dictionary_parse(const void *const dict, const unsigned int len, void *const arg, void (*f)(void *, const char *, unsigned int, const void *, unsigned int))
{ {
ZeroTier::Dictionary d; ZeroTier::Dictionary d;
if (d.decode(dict, len)) { if (d.decode(dict, len)) {
@ -924,7 +994,7 @@ int ZT_Dictionary_parse(const void *const dict, const unsigned int len, void *co
/********************************************************************************************************************/ /********************************************************************************************************************/
uint64_t ZT_random() ZT_MAYBE_UNUSED uint64_t ZT_random()
{ return ZeroTier::Utils::random(); } { return ZeroTier::Utils::random(); }
} // extern "C" } // extern "C"

View file

@ -11,6 +11,7 @@ set(core_headers
Address.hpp Address.hpp
Buf.hpp Buf.hpp
C25519.hpp C25519.hpp
CallContext.hpp
CapabilityCredential.hpp CapabilityCredential.hpp
Certificate.hpp Certificate.hpp
Defaults.hpp Defaults.hpp

63
core/CallContext.hpp Normal file
View file

@ -0,0 +1,63 @@
/*
* Copyright (c)2013-2021 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: 2026-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_CALLCONTEXT_HPP
#define ZT_CALLCONTEXT_HPP
#include "Constants.hpp"
namespace ZeroTier {
/**
* A per-API-call equivalent to the runtime
*
* This captures several things that are passed into API calls and follow
* the call chain. Some such as tPtr may be supplied to callbacks.
*/
class CallContext
{
public:
ZT_INLINE CallContext(const int64_t c, const int64_t t, void *const p) :
clock(c),
ticks(t),
tPtr(p)
{}
/**
* Real world time in milliseconds since Unix epoch or -1 if unknown.
*
* This is used for things like checking certificate expiration. If it's
* not known then the value may be inferred from peers/roots or some
* features may be disabled.
*/
const int64_t clock;
/**
* Monotonic process or system clock in milliseconds since an arbitrary point.
*
* This is never -1 or undefined and is used for most timings.
*/
const int64_t ticks;
/**
* An arbitrary pointer users pass into calls that follows the call chain
*
* By passing this back to callbacks state can be kept by the caller using
* a mechanism that is faster (on most platforms) than thread-local storage.
*/
void *const tPtr;
};
} // namespace ZeroTier
#endif

View file

@ -38,7 +38,7 @@ int CapabilityCredential::marshal(uint8_t data[ZT_CAPABILITY_MARSHAL_SIZE_MAX],
Utils::storeBigEndian<uint64_t>(data + p, m_nwid); Utils::storeBigEndian<uint64_t>(data + p, m_nwid);
p += 8; p += 8;
Utils::storeBigEndian<uint64_t>(data + p, (uint64_t) m_ts); Utils::storeBigEndian<uint64_t>(data + p, (uint64_t) m_timestamp);
p += 8; p += 8;
Utils::storeBigEndian<uint32_t>(data + p, m_id); Utils::storeBigEndian<uint32_t>(data + p, m_id);
p += 4; p += 4;
@ -84,7 +84,7 @@ int CapabilityCredential::unmarshal(const uint8_t *data, int len) noexcept
return -1; return -1;
m_nwid = Utils::loadBigEndian<uint64_t>(data); m_nwid = Utils::loadBigEndian<uint64_t>(data);
m_ts = (int64_t) Utils::loadBigEndian<uint64_t>(data + 8); m_timestamp = (int64_t) Utils::loadBigEndian<uint64_t>(data + 8);
m_id = Utils::loadBigEndian<uint32_t>(data + 16); m_id = Utils::loadBigEndian<uint32_t>(data + 16);
const unsigned int rc = Utils::loadBigEndian<uint16_t>(data + 20); const unsigned int rc = Utils::loadBigEndian<uint16_t>(data + 20);

View file

@ -51,21 +51,23 @@ class CapabilityCredential : public Credential
friend class Credential; friend class Credential;
public: public:
static constexpr ZT_CredentialType credentialType() noexcept { return ZT_CREDENTIAL_TYPE_CAPABILITY; } static constexpr ZT_CredentialType credentialType() noexcept
{ return ZT_CREDENTIAL_TYPE_CAPABILITY; }
ZT_INLINE CapabilityCredential() noexcept { memoryZero(this); } ZT_INLINE CapabilityCredential() noexcept
{ memoryZero(this); }
/** /**
* @param id Capability ID * @param id Capability ID
* @param nwid Network ID * @param nwid Network ID
* @param ts Timestamp (at controller) * @param timestamp Timestamp (at controller)
* @param mccl Maximum custody chain length (1 to create non-transferable capability) * @param mccl Maximum custody chain length (1 to create non-transferable capability)
* @param rules Network flow rules for this capability * @param rules Network flow rules for this capability
* @param ruleCount Number of flow rules * @param ruleCount Number of flow rules
*/ */
ZT_INLINE CapabilityCredential(const uint32_t id, const uint64_t nwid, const int64_t ts, const ZT_VirtualNetworkRule *const rules, const unsigned int ruleCount) noexcept : // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init) ZT_INLINE CapabilityCredential(const uint32_t id, const uint64_t nwid, const int64_t timestamp, const ZT_VirtualNetworkRule *const rules, const unsigned int ruleCount) noexcept: // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
m_nwid(nwid), m_nwid(nwid),
m_ts(ts), m_timestamp(timestamp),
m_id(id), m_id(id),
m_ruleCount((ruleCount < ZT_MAX_CAPABILITY_RULES) ? ruleCount : ZT_MAX_CAPABILITY_RULES), m_ruleCount((ruleCount < ZT_MAX_CAPABILITY_RULES) ? ruleCount : ZT_MAX_CAPABILITY_RULES),
m_signatureLength(0) m_signatureLength(0)
@ -77,20 +79,38 @@ public:
/** /**
* @return Rules -- see ruleCount() for size of array * @return Rules -- see ruleCount() for size of array
*/ */
ZT_INLINE const ZT_VirtualNetworkRule *rules() const noexcept { return m_rules; } ZT_INLINE const ZT_VirtualNetworkRule *rules() const noexcept
{ return m_rules; }
/** /**
* @return Number of rules in rules() * @return Number of rules in rules()
*/ */
ZT_INLINE unsigned int ruleCount() const noexcept { return m_ruleCount; } ZT_INLINE unsigned int ruleCount() const noexcept
{ return m_ruleCount; }
ZT_INLINE uint32_t id() const noexcept { return m_id; } ZT_INLINE uint32_t id() const noexcept
ZT_INLINE uint64_t networkId() const noexcept { return m_nwid; } { return m_id; }
ZT_INLINE int64_t timestamp() const noexcept { return m_ts; }
ZT_INLINE const Address &issuedTo() const noexcept { return m_issuedTo; } ZT_INLINE uint64_t networkId() const noexcept
ZT_INLINE const Address &signer() const noexcept { return m_signedBy; } { return m_nwid; }
ZT_INLINE const uint8_t *signature() const noexcept { return m_signature; }
ZT_INLINE unsigned int signatureLength() const noexcept { return m_signatureLength; } ZT_INLINE int64_t timestamp() const noexcept
{ return m_timestamp; }
ZT_INLINE int64_t revision() const noexcept
{ return m_timestamp; }
ZT_INLINE const Address &issuedTo() const noexcept
{ return m_issuedTo; }
ZT_INLINE const Address &signer() const noexcept
{ return m_signedBy; }
ZT_INLINE const uint8_t *signature() const noexcept
{ return m_signature; }
ZT_INLINE unsigned int signatureLength() const noexcept
{ return m_signatureLength; }
/** /**
* Sign this capability and add signature to its chain of custody * Sign this capability and add signature to its chain of custody
@ -105,18 +125,22 @@ public:
* @param to Recipient of this signature * @param to Recipient of this signature
* @return True if signature successful and chain of custody appended * @return True if signature successful and chain of custody appended
*/ */
bool sign(const Identity &from,const Address &to) noexcept; bool sign(const Identity &from, const Address &to) noexcept;
/** /**
* Verify this capability's chain of custody and signatures * Verify this capability's chain of custody and signatures
* *
* @param RR Runtime environment to provide for peer lookup, etc. * @param RR Runtime environment to provide for peer lookup, etc.
*/ */
ZT_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const noexcept { return s_verify(RR, tPtr, *this); } ZT_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR, CallContext &cc) const noexcept
{ return s_verify(RR, cc, *this); }
static constexpr int marshalSizeMax() noexcept { return ZT_CAPABILITY_MARSHAL_SIZE_MAX; } static constexpr int marshalSizeMax() noexcept
int marshal(uint8_t data[ZT_CAPABILITY_MARSHAL_SIZE_MAX],bool forSign = false) const noexcept; { return ZT_CAPABILITY_MARSHAL_SIZE_MAX; }
int unmarshal(const uint8_t *data,int len) noexcept;
int marshal(uint8_t data[ZT_CAPABILITY_MARSHAL_SIZE_MAX], bool forSign = false) const noexcept;
int unmarshal(const uint8_t *data, int len) noexcept;
/** /**
* Marshal a set of virtual network rules * Marshal a set of virtual network rules
@ -126,7 +150,7 @@ public:
* @param ruleCount Number of rules * @param ruleCount Number of rules
* @return Number of bytes written or -1 on error * @return Number of bytes written or -1 on error
*/ */
static int marshalVirtualNetworkRules(uint8_t *data,const ZT_VirtualNetworkRule *rules,unsigned int ruleCount) noexcept; static int marshalVirtualNetworkRules(uint8_t *data, const ZT_VirtualNetworkRule *rules, unsigned int ruleCount) noexcept;
/** /**
* Unmarshal a set of virtual network rules * Unmarshal a set of virtual network rules
@ -138,17 +162,21 @@ public:
* @param maxRuleCount Capacity of rules buffer * @param maxRuleCount Capacity of rules buffer
* @return Number of bytes unmarshaled or -1 on error * @return Number of bytes unmarshaled or -1 on error
*/ */
static int unmarshalVirtualNetworkRules(const uint8_t *data,int len,ZT_VirtualNetworkRule *rules,unsigned int &ruleCount,unsigned int maxRuleCount) noexcept; static int unmarshalVirtualNetworkRules(const uint8_t *data, int len, ZT_VirtualNetworkRule *rules, unsigned int &ruleCount, unsigned int maxRuleCount) noexcept;
// Provides natural sort order by ID // Provides natural sort order by ID
ZT_INLINE bool operator<(const CapabilityCredential &c) const noexcept { return (m_id < c.m_id); } ZT_INLINE bool operator<(const CapabilityCredential &c) const noexcept
{ return (m_id < c.m_id); }
ZT_INLINE bool operator==(const CapabilityCredential &c) const noexcept { return (memcmp(this, &c, sizeof(CapabilityCredential)) == 0); } ZT_INLINE bool operator==(const CapabilityCredential &c) const noexcept
ZT_INLINE bool operator!=(const CapabilityCredential &c) const noexcept { return (memcmp(this, &c, sizeof(CapabilityCredential)) != 0); } { return (memcmp(this, &c, sizeof(CapabilityCredential)) == 0); }
ZT_INLINE bool operator!=(const CapabilityCredential &c) const noexcept
{ return (memcmp(this, &c, sizeof(CapabilityCredential)) != 0); }
private: private:
uint64_t m_nwid; uint64_t m_nwid;
int64_t m_ts; int64_t m_timestamp;
uint32_t m_id; uint32_t m_id;
unsigned int m_ruleCount; unsigned int m_ruleCount;
ZT_VirtualNetworkRule m_rules[ZT_MAX_CAPABILITY_RULES]; ZT_VirtualNetworkRule m_rules[ZT_MAX_CAPABILITY_RULES];

View file

@ -167,7 +167,7 @@ void Certificate::addSubjectCertificate(const uint8_t serialNo[ZT_SHA384_DIGEST_
// Enlarge array of uint8_t pointers, set new pointer to local copy of serial, and set // Enlarge array of uint8_t pointers, set new pointer to local copy of serial, and set
// certificates to point to potentially reallocated array. // certificates to point to potentially reallocated array.
m_subjectCertificates.push_back(m_serials.front().bytes()); m_subjectCertificates.push_back(reinterpret_cast<const uint8_t *>(m_serials.front().data));
this->subject.certificates = m_subjectCertificates.data(); this->subject.certificates = m_subjectCertificates.data();
this->subject.certificateCount = (unsigned int)m_subjectCertificates.size(); this->subject.certificateCount = (unsigned int)m_subjectCertificates.size();
} }
@ -187,6 +187,7 @@ void Certificate::addSubjectUpdateUrl(const char *url)
this->subject.updateURLCount = (unsigned int)m_updateUrls.size(); this->subject.updateURLCount = (unsigned int)m_updateUrls.size();
} }
/*
void Certificate::setExtendedAttributes(const Dictionary &x) void Certificate::setExtendedAttributes(const Dictionary &x)
{ {
m_extendedAttributes.clear(); m_extendedAttributes.clear();
@ -194,6 +195,7 @@ void Certificate::setExtendedAttributes(const Dictionary &x)
this->extendedAttributes = m_extendedAttributes.data(); this->extendedAttributes = m_extendedAttributes.data();
this->extendedAttributesSize = (unsigned int)m_extendedAttributes.size(); this->extendedAttributesSize = (unsigned int)m_extendedAttributes.size();
} }
*/
bool Certificate::setSubjectUniqueId(const uint8_t uniqueId[ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE], const uint8_t uniqueIdPrivate[ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE]) bool Certificate::setSubjectUniqueId(const uint8_t uniqueId[ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE], const uint8_t uniqueIdPrivate[ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE])
{ {

View file

@ -110,7 +110,7 @@ public:
* *
* @param x Extended attributes (set by issuer) * @param x Extended attributes (set by issuer)
*/ */
void setExtendedAttributes(const Dictionary &x); //void setExtendedAttributes(const Dictionary &x);
/** /**
* Set the unique ID of this certificate's subject * Set the unique ID of this certificate's subject

View file

@ -102,9 +102,9 @@
#define ZT_NETWORK_HOUSEKEEPING_PERIOD 30000 #define ZT_NETWORK_HOUSEKEEPING_PERIOD 30000
/** /**
* How often to rank roots * Period between calls to update() in TrustStore
*/ */
#define ZT_ROOT_RANK_PERIOD 5000 #define ZT_TRUSTSTORE_UPDATE_PERIOD 300000
/** /**
* Delay between WHOIS retries in ms * Delay between WHOIS retries in ms

View file

@ -27,9 +27,11 @@
#include <algorithm> #include <algorithm>
#ifdef __CPP11__ #ifdef __CPP11__
#include <atomic> #include <atomic>
#include <unordered_map> #include <unordered_map>
#include <forward_list> #include <forward_list>
#endif #endif
namespace ZeroTier { namespace ZeroTier {
@ -43,14 +45,15 @@ public:
{} {}
template< typename I > template< typename I >
ZT_INLINE Vector(I begin,I end) : ZT_INLINE Vector(I begin, I end) :
std::vector< V >(begin, end) std::vector< V >(begin, end)
{} {}
}; };
template< typename V > template< typename V >
class List : public std::list< V > class List : public std::list< V >
{}; {
};
#ifdef __CPP11__ #ifdef __CPP11__
@ -78,11 +81,13 @@ struct intl_MapHasher
template< typename K, typename V > template< typename K, typename V >
class Map : public std::unordered_map< K, V, intl_MapHasher > class Map : public std::unordered_map< K, V, intl_MapHasher >
{}; {
};
template< typename K, typename V > template< typename K, typename V >
class MultiMap : public std::unordered_multimap< K, V, intl_MapHasher, std::equal_to< K > > class MultiMap : public std::unordered_multimap< K, V, intl_MapHasher, std::equal_to< K > >
{}; {
};
#else #else
@ -98,13 +103,15 @@ class MultiMap : public std::multimap< K, V >
template< typename K, typename V > template< typename K, typename V >
class SortedMap : public std::map< K, V > class SortedMap : public std::map< K, V >
{}; {
};
#ifdef __CPP11__ #ifdef __CPP11__
template< typename V > template< typename V >
class ForwardList : public std::forward_list< V > class ForwardList : public std::forward_list< V >
{}; {
};
#else #else
@ -116,7 +123,8 @@ class ForwardList : public std::list< V >
template< typename V > template< typename V >
class Set : public std::set< V, std::less< V > > class Set : public std::set< V, std::less< V > >
{}; {
};
typedef std::string String; typedef std::string String;
@ -130,11 +138,17 @@ struct H384
ZT_INLINE H384() noexcept ZT_INLINE H384() noexcept
{ Utils::zero< sizeof(data) >(data); } { Utils::zero< sizeof(data) >(data); }
ZT_INLINE H384(const H384 &b) noexcept
{ Utils::copy< 48 >(data, b.data); }
explicit ZT_INLINE H384(const void *const d) noexcept explicit ZT_INLINE H384(const void *const d) noexcept
{ Utils::copy< 48 >(data, d); } { Utils::copy< 48 >(data, d); }
ZT_INLINE const uint8_t *bytes() const noexcept ZT_INLINE H384 &operator=(const H384 &b) noexcept
{ return reinterpret_cast<const uint8_t *>(data); } {
Utils::copy< 48 >(data, b.data);
return *this;
}
ZT_INLINE unsigned long hashCode() const noexcept ZT_INLINE unsigned long hashCode() const noexcept
{ return (unsigned long)data[0]; } { return (unsigned long)data[0]; }
@ -151,12 +165,12 @@ struct H384
ZT_INLINE bool operator<(const H384 &b) const noexcept ZT_INLINE bool operator<(const H384 &b) const noexcept
{ return std::lexicographical_compare(data, data + 6, b.data, b.data + 6); } { return std::lexicographical_compare(data, data + 6, b.data, b.data + 6); }
ZT_INLINE bool operator>(const H384 &b) const noexcept
{ return (b < *this); }
ZT_INLINE bool operator<=(const H384 &b) const noexcept ZT_INLINE bool operator<=(const H384 &b) const noexcept
{ return !(b < *this); } { return !(b < *this); }
ZT_INLINE bool operator>(const H384 &b) const noexcept
{ return (b < *this); }
ZT_INLINE bool operator>=(const H384 &b) const noexcept ZT_INLINE bool operator>=(const H384 &b) const noexcept
{ return !(*this < b); } { return !(*this < b); }
}; };
@ -164,7 +178,7 @@ struct H384
static_assert(sizeof(H384) == 48, "H384 contains unnecessary padding"); static_assert(sizeof(H384) == 48, "H384 contains unnecessary padding");
/** /**
* A byte array * A fixed size byte array
* *
* @tparam S Size in bytes * @tparam S Size in bytes
*/ */
@ -172,6 +186,53 @@ template< unsigned long S >
struct Blob struct Blob
{ {
uint8_t data[S]; uint8_t data[S];
ZT_INLINE Blob() noexcept
{ Utils::zero< S >(data); }
ZT_INLINE Blob(const Blob &b) noexcept
{ Utils::copy< S >(data, b.data); }
explicit ZT_INLINE Blob(const void *const d) noexcept
{ Utils::copy< S >(data, d); }
explicit ZT_INLINE Blob(const void *const d, const unsigned int l) noexcept
{
Utils::copy(data, d, l);
if (l < S) {
Utils::zero(data + l, S - l);
}
}
ZT_INLINE Blob &operator=(const Blob &b) noexcept
{
Utils::copy< S >(data, b.data);
return *this;
}
ZT_INLINE unsigned long hashCode() const noexcept
{ return Utils::fnv1a32(data, (unsigned int)S); }
ZT_INLINE operator bool() const noexcept
{ return Utils::allZero(data, (unsigned int)S); }
ZT_INLINE bool operator==(const Blob &b) const noexcept
{ return (memcmp(data, b.data, S) == 0); }
ZT_INLINE bool operator!=(const Blob &b) const noexcept
{ return (memcmp(data, b.data, S) != 0); }
ZT_INLINE bool operator<(const Blob &b) const noexcept
{ return (memcmp(data, b.data, S) < 0); }
ZT_INLINE bool operator<=(const Blob &b) const noexcept
{ return (memcmp(data, b.data, S) <= 0); }
ZT_INLINE bool operator>(const Blob &b) const noexcept
{ return (memcmp(data, b.data, S) > 0); }
ZT_INLINE bool operator>=(const Blob &b) const noexcept
{ return (memcmp(data, b.data, S) >= 0); }
}; };
} // ZeroTier } // ZeroTier

View file

@ -42,43 +42,50 @@
namespace ZeroTier { namespace ZeroTier {
template<typename CRED> template< typename CRED >
static ZT_INLINE Credential::VerifyResult p_credVerify(const RuntimeEnvironment *RR,void *tPtr,CRED credential) static ZT_INLINE Credential::VerifyResult p_credVerify(const RuntimeEnvironment *RR, CallContext &cc, CRED credential)
{ {
uint8_t tmp[ZT_BUF_MEM_SIZE + 16]; uint8_t tmp[ZT_BUF_MEM_SIZE + 16];
const Address signedBy(credential.signer()); const Address signedBy(credential.signer());
const uint64_t networkId = credential.networkId(); const uint64_t networkId = credential.networkId();
if ((!signedBy)||(signedBy != Network::controllerFor(networkId))) if ((!signedBy) || (signedBy != Network::controllerFor(networkId)))
return Credential::VERIFY_BAD_SIGNATURE; return Credential::VERIFY_BAD_SIGNATURE;
const SharedPtr<Peer> peer(RR->topology->peer(tPtr,signedBy)); const SharedPtr< Peer > peer(RR->topology->peer(cc, signedBy));
if (!peer) if (!peer)
return Credential::VERIFY_NEED_IDENTITY; return Credential::VERIFY_NEED_IDENTITY;
try { try {
int l = credential.marshal(tmp,true); int l = credential.marshal(tmp, true);
if (l <= 0) if (l <= 0)
return Credential::VERIFY_BAD_SIGNATURE; return Credential::VERIFY_BAD_SIGNATURE;
return (peer->identity().verify(tmp,(unsigned int)l,credential.signature(),credential.signatureLength()) ? Credential::VERIFY_OK : Credential::VERIFY_BAD_SIGNATURE); return (peer->identity().verify(tmp, (unsigned int)l, credential.signature(), credential.signatureLength()) ? Credential::VERIFY_OK : Credential::VERIFY_BAD_SIGNATURE);
} catch ( ... ) {} } catch (...) {}
return Credential::VERIFY_BAD_SIGNATURE; return Credential::VERIFY_BAD_SIGNATURE;
} }
Credential::VerifyResult Credential::s_verify(const RuntimeEnvironment *RR, void *tPtr, const RevocationCredential &credential) { return p_credVerify(RR, tPtr, credential); } Credential::VerifyResult Credential::s_verify(const RuntimeEnvironment *RR, CallContext &cc, const RevocationCredential &credential)
Credential::VerifyResult Credential::s_verify(const RuntimeEnvironment *RR, void *tPtr, const TagCredential &credential) { return p_credVerify(RR, tPtr, credential); } { return p_credVerify(RR, cc, credential); }
Credential::VerifyResult Credential::s_verify(const RuntimeEnvironment *RR, void *tPtr, const CapabilityCredential &credential) { return p_credVerify(RR, tPtr, credential); }
Credential::VerifyResult Credential::s_verify(const RuntimeEnvironment *RR, void *tPtr, const OwnershipCredential &credential) { return p_credVerify(RR, tPtr, credential); }
Credential::VerifyResult Credential::s_verify(const RuntimeEnvironment *RR, void *tPtr, const MembershipCredential &credential) Credential::VerifyResult Credential::s_verify(const RuntimeEnvironment *RR, CallContext &cc, const TagCredential &credential)
{ return p_credVerify(RR, cc, credential); }
Credential::VerifyResult Credential::s_verify(const RuntimeEnvironment *RR, CallContext &cc, const CapabilityCredential &credential)
{ return p_credVerify(RR, cc, credential); }
Credential::VerifyResult Credential::s_verify(const RuntimeEnvironment *RR, CallContext &cc, const OwnershipCredential &credential)
{ return p_credVerify(RR, cc, credential); }
Credential::VerifyResult Credential::s_verify(const RuntimeEnvironment *RR, CallContext &cc, const MembershipCredential &credential)
{ {
// Sanity check network ID. // Sanity check network ID.
if ((!credential.m_signedBy) || (credential.m_signedBy != Network::controllerFor(credential.m_networkId))) if ((!credential.m_signedBy) || (credential.m_signedBy != Network::controllerFor(credential.m_networkId)))
return Credential::VERIFY_BAD_SIGNATURE; return Credential::VERIFY_BAD_SIGNATURE;
// If we don't know the peer, get its identity. This shouldn't happen here but should be handled. // If we don't know the peer, get its identity. This shouldn't happen here but should be handled.
const SharedPtr<Peer> peer(RR->topology->peer(tPtr,credential.m_signedBy)); const SharedPtr< Peer > peer(RR->topology->peer(cc, credential.m_signedBy));
if (!peer) if (!peer)
return Credential::VERIFY_NEED_IDENTITY; return Credential::VERIFY_NEED_IDENTITY;

View file

@ -16,6 +16,7 @@
#include "Constants.hpp" #include "Constants.hpp"
#include "TriviallyCopyable.hpp" #include "TriviallyCopyable.hpp"
#include "CallContext.hpp"
#include <string> #include <string>
#include <memory> #include <memory>
@ -52,11 +53,11 @@ public:
}; };
protected: protected:
static VerifyResult s_verify(const RuntimeEnvironment *RR, void *tPtr, const MembershipCredential &credential); static VerifyResult s_verify(const RuntimeEnvironment *RR, CallContext &cc, const MembershipCredential &credential);
static VerifyResult s_verify(const RuntimeEnvironment *RR, void *tPtr, const RevocationCredential &credential); static VerifyResult s_verify(const RuntimeEnvironment *RR, CallContext &cc, const RevocationCredential &credential);
static VerifyResult s_verify(const RuntimeEnvironment *RR, void *tPtr, const TagCredential &credential); static VerifyResult s_verify(const RuntimeEnvironment *RR, CallContext &cc, const TagCredential &credential);
static VerifyResult s_verify(const RuntimeEnvironment *RR, void *tPtr, const OwnershipCredential &credential); static VerifyResult s_verify(const RuntimeEnvironment *RR, CallContext &cc, const OwnershipCredential &credential);
static VerifyResult s_verify(const RuntimeEnvironment *RR, void *tPtr, const CapabilityCredential &credential); static VerifyResult s_verify(const RuntimeEnvironment *RR, CallContext &cc, const CapabilityCredential &credential);
}; };
} // namespace ZeroTier } // namespace ZeroTier

View file

@ -50,7 +50,7 @@ template<
unsigned int MFP = ZT_MAX_INCOMING_FRAGMENTS_PER_PATH, unsigned int MFP = ZT_MAX_INCOMING_FRAGMENTS_PER_PATH,
unsigned int GCS = (ZT_MAX_PACKET_FRAGMENTS * 2), unsigned int GCS = (ZT_MAX_PACKET_FRAGMENTS * 2),
unsigned int GCT = (ZT_MAX_PACKET_FRAGMENTS * 4), unsigned int GCT = (ZT_MAX_PACKET_FRAGMENTS * 4),
typename P = SharedPtr <Path> > typename P = SharedPtr< Path > >
class Defragmenter class Defragmenter
{ {
public: public:
@ -136,19 +136,19 @@ public:
* @param fragmentDataSize Length of data in fragment's data.bytes (fragment's data.fields type is ignored) * @param fragmentDataSize Length of data in fragment's data.bytes (fragment's data.fields type is ignored)
* @param fragmentNo Number of fragment (0..totalFragmentsExpected, non-inclusive) * @param fragmentNo Number of fragment (0..totalFragmentsExpected, non-inclusive)
* @param totalFragmentsExpected Total number of expected fragments in this message or 0 to use cached value * @param totalFragmentsExpected Total number of expected fragments in this message or 0 to use cached value
* @param now Current time * @param ts Current time
* @param via If non-NULL this is the path on which this message fragment was received * @param via If non-NULL this is the path on which this message fragment was received
* @return Result code * @return Result code
*/ */
ZT_INLINE ResultCode assemble( ZT_INLINE ResultCode assemble(
const uint64_t messageId, const uint64_t messageId,
FCV <Buf::Slice, MF> &message, FCV< Buf::Slice, MF > &message,
SharedPtr <Buf> &fragment, SharedPtr< Buf > &fragment,
const unsigned int fragmentDataIndex, const unsigned int fragmentDataIndex,
const unsigned int fragmentDataSize, const unsigned int fragmentDataSize,
const unsigned int fragmentNo, const unsigned int fragmentNo,
const unsigned int totalFragmentsExpected, const unsigned int totalFragmentsExpected,
const int64_t now, const int64_t ts,
const P &via) const P &via)
{ {
// Sanity checks for malformed fragments or invalid input parameters. // Sanity checks for malformed fragments or invalid input parameters.
@ -210,7 +210,7 @@ public:
return ERR_DUPLICATE_FRAGMENT; return ERR_DUPLICATE_FRAGMENT;
// Update last-activity timestamp for this entry, delaying GC. // Update last-activity timestamp for this entry, delaying GC.
e->lastUsed = now; e->lastUsed = ts;
// Learn total fragments expected if a value is given. Otherwise the cached // Learn total fragments expected if a value is given. Otherwise the cached
// value gets used. This is to support the implementation of fragmentation // value gets used. This is to support the implementation of fragmentation
@ -344,11 +344,11 @@ private:
unsigned int totalFragmentsExpected; unsigned int totalFragmentsExpected;
unsigned int fragmentsReceived; unsigned int fragmentsReceived;
P via; P via;
FCV <Buf::Slice, MF> message; FCV< Buf::Slice, MF > message;
Mutex lock; Mutex lock;
}; };
Map <uint64_t, Defragmenter< MF, MFP, GCS, GCT, P >::p_E> m_messages; Map< uint64_t, Defragmenter< MF, MFP, GCS, GCT, P >::p_E > m_messages;
RWMutex m_messages_l; RWMutex m_messages_l;
}; };

View file

@ -15,24 +15,24 @@
namespace ZeroTier { namespace ZeroTier {
Vector< uint8_t > &Dictionary::operator[](const char *const k) ZT_MAYBE_UNUSED Vector< uint8_t > &Dictionary::operator[](const char *const k)
{ return m_entries[k]; } { return m_entries[k]; }
const Vector< uint8_t > &Dictionary::operator[](const char *const k) const ZT_MAYBE_UNUSED const Vector< uint8_t > &Dictionary::operator[](const char *const k) const
{ {
static const Vector< uint8_t > s_emptyEntry; static const Vector< uint8_t > s_emptyEntry;
const SortedMap< String, Vector< uint8_t > >::const_iterator e(m_entries.find(k)); const SortedMap< String, Vector< uint8_t > >::const_iterator e(m_entries.find(k));
return (e == m_entries.end()) ? s_emptyEntry : e->second; return (e == m_entries.end()) ? s_emptyEntry : e->second;
} }
void Dictionary::add(const char *k, const Address &v) ZT_MAYBE_UNUSED void Dictionary::add(const char *k, const Address &v)
{ {
char tmp[ZT_ADDRESS_STRING_SIZE_MAX]; char tmp[ZT_ADDRESS_STRING_SIZE_MAX];
v.toString(tmp); v.toString(tmp);
add(k, tmp); add(k, tmp);
} }
void Dictionary::add(const char *k, const char *v) ZT_MAYBE_UNUSED void Dictionary::add(const char *k, const char *v)
{ {
Vector< uint8_t > &e = (*this)[k]; Vector< uint8_t > &e = (*this)[k];
e.clear(); e.clear();
@ -42,7 +42,7 @@ void Dictionary::add(const char *k, const char *v)
} }
} }
void Dictionary::add(const char *k, const void *data, unsigned int len) ZT_MAYBE_UNUSED void Dictionary::add(const char *k, const void *data, unsigned int len)
{ {
Vector< uint8_t > &e = (*this)[k]; Vector< uint8_t > &e = (*this)[k];
if (likely(len != 0)) { if (likely(len != 0)) {
@ -52,7 +52,7 @@ void Dictionary::add(const char *k, const void *data, unsigned int len)
} }
} }
uint64_t Dictionary::getUI(const char *k, uint64_t dfl) const ZT_MAYBE_UNUSED uint64_t Dictionary::getUI(const char *k, uint64_t dfl) const
{ {
char tmp[32]; char tmp[32];
getS(k, tmp, sizeof(tmp)); getS(k, tmp, sizeof(tmp));
@ -61,7 +61,7 @@ uint64_t Dictionary::getUI(const char *k, uint64_t dfl) const
return dfl; return dfl;
} }
char *Dictionary::getS(const char *k, char *v, const unsigned int cap) const ZT_MAYBE_UNUSED char *Dictionary::getS(const char *k, char *v, const unsigned int cap) const
{ {
if (cap == 0) // sanity check if (cap == 0) // sanity check
return v; return v;
@ -84,10 +84,10 @@ char *Dictionary::getS(const char *k, char *v, const unsigned int cap) const
return v; return v;
} }
void Dictionary::clear() ZT_MAYBE_UNUSED void Dictionary::clear()
{ m_entries.clear(); } { m_entries.clear(); }
void Dictionary::encode(Vector< uint8_t > &out) const ZT_MAYBE_UNUSED void Dictionary::encode(Vector< uint8_t > &out) const
{ {
out.clear(); out.clear();
for (SortedMap< String, Vector< uint8_t > >::const_iterator ti(m_entries.begin()); ti != m_entries.end(); ++ti) { for (SortedMap< String, Vector< uint8_t > >::const_iterator ti(m_entries.begin()); ti != m_entries.end(); ++ti) {
@ -98,7 +98,7 @@ void Dictionary::encode(Vector< uint8_t > &out) const
} }
} }
bool Dictionary::decode(const void *data, unsigned int len) ZT_MAYBE_UNUSED bool Dictionary::decode(const void *data, unsigned int len)
{ {
clear(); clear();
String k; String k;
@ -151,7 +151,7 @@ bool Dictionary::decode(const void *data, unsigned int len)
return true; return true;
} }
char *Dictionary::arraySubscript(char *buf, unsigned int bufSize, const char *name, const unsigned long sub) noexcept ZT_MAYBE_UNUSED char *Dictionary::arraySubscript(char *buf, unsigned int bufSize, const char *name, const unsigned long sub) noexcept
{ {
if (bufSize < 17) { // sanity check if (bufSize < 17) { // sanity check
buf[0] = 0; buf[0] = 0;

View file

@ -81,7 +81,7 @@ public:
* @param k Key to look up * @param k Key to look up
* @return Reference to value * @return Reference to value
*/ */
Vector< uint8_t > &operator[](const char *k); ZT_MAYBE_UNUSED Vector< uint8_t > &operator[](const char *k);
/** /**
* Get a const reference to a value * Get a const reference to a value
@ -89,18 +89,18 @@ public:
* @param k Key to look up * @param k Key to look up
* @return Reference to value or to empty vector if not found * @return Reference to value or to empty vector if not found
*/ */
const Vector< uint8_t > &operator[](const char *k) const; ZT_MAYBE_UNUSED const Vector< uint8_t > &operator[](const char *k) const;
/** /**
* @return Start of key->value pairs * @return Start of key->value pairs
*/ */
ZT_INLINE const_iterator begin() const noexcept ZT_MAYBE_UNUSED ZT_INLINE const_iterator begin() const noexcept
{ return m_entries.begin(); } { return m_entries.begin(); }
/** /**
* @return End of key->value pairs * @return End of key->value pairs
*/ */
ZT_INLINE const_iterator end() const noexcept ZT_MAYBE_UNUSED ZT_INLINE const_iterator end() const noexcept
{ return m_entries.end(); } { return m_entries.end(); }
/** /**
@ -109,7 +109,7 @@ public:
* @param k Key to set * @param k Key to set
* @param v Integer to set, will be cast to uint64_t and stored as hex * @param v Integer to set, will be cast to uint64_t and stored as hex
*/ */
ZT_INLINE void add(const char *const k, const uint64_t v) ZT_MAYBE_UNUSED ZT_INLINE void add(const char *const k, const uint64_t v)
{ {
char buf[24]; char buf[24];
add(k, Utils::hex((uint64_t)(v), buf)); add(k, Utils::hex((uint64_t)(v), buf));
@ -121,7 +121,7 @@ public:
* @param k Key to set * @param k Key to set
* @param v Integer to set, will be cast to uint64_t and stored as hex * @param v Integer to set, will be cast to uint64_t and stored as hex
*/ */
ZT_INLINE void add(const char *const k, const int64_t v) ZT_MAYBE_UNUSED ZT_INLINE void add(const char *const k, const int64_t v)
{ {
char buf[24]; char buf[24];
add(k, Utils::hex((uint64_t)(v), buf)); add(k, Utils::hex((uint64_t)(v), buf));
@ -130,17 +130,17 @@ public:
/** /**
* Add an address in 10-digit hex string format * Add an address in 10-digit hex string format
*/ */
void add(const char *k, const Address &v); ZT_MAYBE_UNUSED void add(const char *k, const Address &v);
/** /**
* Add a C string as a value * Add a C string as a value
*/ */
void add(const char *k, const char *v); ZT_MAYBE_UNUSED void add(const char *k, const char *v);
/** /**
* Add a binary blob as a value * Add a binary blob as a value
*/ */
void add(const char *k, const void *data, unsigned int len); ZT_MAYBE_UNUSED void add(const char *k, const void *data, unsigned int len);
/** /**
* Get an integer * Get an integer
@ -149,7 +149,7 @@ public:
* @param dfl Default value (default: 0) * @param dfl Default value (default: 0)
* @return Value of key or default if not found * @return Value of key or default if not found
*/ */
uint64_t getUI(const char *k, uint64_t dfl = 0) const; ZT_MAYBE_UNUSED uint64_t getUI(const char *k, uint64_t dfl = 0) const;
/** /**
* Get a C string * Get a C string
@ -161,7 +161,7 @@ public:
* @param v Buffer to hold string * @param v Buffer to hold string
* @param cap Maximum size of string (including terminating null) * @param cap Maximum size of string (including terminating null)
*/ */
char *getS(const char *k, char *v, unsigned int cap) const; ZT_MAYBE_UNUSED char *getS(const char *k, char *v, unsigned int cap) const;
/** /**
* Get an object supporting the marshal/unmarshal interface pattern * Get an object supporting the marshal/unmarshal interface pattern
@ -172,7 +172,7 @@ public:
* @return True if unmarshal was successful * @return True if unmarshal was successful
*/ */
template< typename T > template< typename T >
ZT_INLINE bool getO(const char *k, T &obj) const ZT_MAYBE_UNUSED ZT_INLINE bool getO(const char *k, T &obj) const
{ {
const Vector< uint8_t > &d = (*this)[k]; const Vector< uint8_t > &d = (*this)[k];
if (d.empty()) if (d.empty())
@ -189,7 +189,7 @@ public:
* @return True if successful * @return True if successful
*/ */
template< typename T > template< typename T >
ZT_INLINE bool addO(const char *k, T &obj) ZT_MAYBE_UNUSED ZT_INLINE bool addO(const char *k, T &obj)
{ {
Vector< uint8_t > &d = (*this)[k]; Vector< uint8_t > &d = (*this)[k];
d.resize(T::marshalSizeMax()); d.resize(T::marshalSizeMax());
@ -205,18 +205,18 @@ public:
/** /**
* Erase all entries in dictionary * Erase all entries in dictionary
*/ */
void clear(); ZT_MAYBE_UNUSED void clear();
/** /**
* @return Number of entries * @return Number of entries
*/ */
ZT_INLINE unsigned int size() const noexcept ZT_MAYBE_UNUSED ZT_INLINE unsigned int size() const noexcept
{ return (unsigned int)m_entries.size(); } { return (unsigned int)m_entries.size(); }
/** /**
* @return True if dictionary is not empty * @return True if dictionary is not empty
*/ */
ZT_INLINE bool empty() const noexcept ZT_MAYBE_UNUSED ZT_INLINE bool empty() const noexcept
{ return m_entries.empty(); } { return m_entries.empty(); }
/** /**
@ -224,7 +224,7 @@ public:
* *
* @param out String encoded dictionary * @param out String encoded dictionary
*/ */
void encode(Vector< uint8_t > &out) const; ZT_MAYBE_UNUSED void encode(Vector< uint8_t > &out) const;
/** /**
* Decode a string encoded dictionary * Decode a string encoded dictionary
@ -236,7 +236,7 @@ public:
* @param len Length of data * @param len Length of data
* @return True if dictionary was formatted correctly and valid, false on error * @return True if dictionary was formatted correctly and valid, false on error
*/ */
bool decode(const void *data, unsigned int len); ZT_MAYBE_UNUSED bool decode(const void *data, unsigned int len);
/** /**
* Append a key=value pair to a buffer (vector or FCV) * Append a key=value pair to a buffer (vector or FCV)
@ -246,7 +246,7 @@ public:
* @param v Value * @param v Value
*/ */
template< typename V > template< typename V >
ZT_INLINE static void append(V &out, const char *const k, const bool v) ZT_MAYBE_UNUSED ZT_INLINE static void append(V &out, const char *const k, const bool v)
{ {
s_appendKey(out, k); s_appendKey(out, k);
out.push_back((uint8_t)(v ? '1' : '0')); out.push_back((uint8_t)(v ? '1' : '0'));
@ -261,7 +261,7 @@ public:
* @param v Value * @param v Value
*/ */
template< typename V > template< typename V >
ZT_INLINE static void append(V &out, const char *const k, const Address v) ZT_MAYBE_UNUSED ZT_INLINE static void append(V &out, const char *const k, const Address v)
{ {
s_appendKey(out, k); s_appendKey(out, k);
const uint64_t a = v.toInt(); const uint64_t a = v.toInt();
@ -287,7 +287,7 @@ public:
* @param v Value * @param v Value
*/ */
template< typename V > template< typename V >
ZT_INLINE static void append(V &out, const char *const k, const uint64_t v) ZT_MAYBE_UNUSED ZT_INLINE static void append(V &out, const char *const k, const uint64_t v)
{ {
s_appendKey(out, k); s_appendKey(out, k);
char buf[17]; char buf[17];
@ -299,31 +299,31 @@ public:
} }
template< typename V > template< typename V >
ZT_INLINE static void append(V &out, const char *const k, const int64_t v) ZT_MAYBE_UNUSED ZT_INLINE static void append(V &out, const char *const k, const int64_t v)
{ append(out, k, (uint64_t)v); } { append(out, k, (uint64_t)v); }
template< typename V > template< typename V >
ZT_INLINE static void append(V &out, const char *const k, const uint32_t v) ZT_MAYBE_UNUSED ZT_INLINE static void append(V &out, const char *const k, const uint32_t v)
{ append(out, k, (uint64_t)v); } { append(out, k, (uint64_t)v); }
template< typename V > template< typename V >
ZT_INLINE static void append(V &out, const char *const k, const int32_t v) ZT_MAYBE_UNUSED ZT_INLINE static void append(V &out, const char *const k, const int32_t v)
{ append(out, k, (uint64_t)v); } { append(out, k, (uint64_t)v); }
template< typename V > template< typename V >
ZT_INLINE static void append(V &out, const char *const k, const uint16_t v) ZT_MAYBE_UNUSED ZT_INLINE static void append(V &out, const char *const k, const uint16_t v)
{ append(out, k, (uint64_t)v); } { append(out, k, (uint64_t)v); }
template< typename V > template< typename V >
ZT_INLINE static void append(V &out, const char *const k, const int16_t v) ZT_MAYBE_UNUSED ZT_INLINE static void append(V &out, const char *const k, const int16_t v)
{ append(out, k, (uint64_t)v); } { append(out, k, (uint64_t)v); }
template< typename V > template< typename V >
ZT_INLINE static void append(V &out, const char *const k, const uint8_t v) ZT_MAYBE_UNUSED ZT_INLINE static void append(V &out, const char *const k, const uint8_t v)
{ append(out, k, (uint64_t)v); } { append(out, k, (uint64_t)v); }
template< typename V > template< typename V >
ZT_INLINE static void append(V &out, const char *const k, const int8_t v) ZT_MAYBE_UNUSED ZT_INLINE static void append(V &out, const char *const k, const int8_t v)
{ append(out, k, (uint64_t)v); } { append(out, k, (uint64_t)v); }
/** /**
@ -334,7 +334,7 @@ public:
* @param v Value * @param v Value
*/ */
template< typename V > template< typename V >
ZT_INLINE static void append(V &out, const char *const k, const char *v) ZT_MAYBE_UNUSED ZT_INLINE static void append(V &out, const char *const k, const char *v)
{ {
if ((v) && (*v)) { if ((v) && (*v)) {
s_appendKey(out, k); s_appendKey(out, k);
@ -353,7 +353,7 @@ public:
* @param vlen Value length in bytes * @param vlen Value length in bytes
*/ */
template< typename V > template< typename V >
ZT_INLINE static void append(V &out, const char *const k, const void *const v, const unsigned int vlen) ZT_MAYBE_UNUSED ZT_INLINE static void append(V &out, const char *const k, const void *const v, const unsigned int vlen)
{ {
s_appendKey(out, k); s_appendKey(out, k);
for (unsigned int i = 0; i < vlen; ++i) for (unsigned int i = 0; i < vlen; ++i)
@ -369,7 +369,7 @@ public:
* @param pid Packet ID * @param pid Packet ID
*/ */
template< typename V > template< typename V >
static ZT_INLINE void appendPacketId(V &out, const char *const k, const uint64_t pid) ZT_MAYBE_UNUSED static ZT_INLINE void appendPacketId(V &out, const char *const k, const uint64_t pid)
{ append(out, k, &pid, 8); } { append(out, k, &pid, 8); }
/** /**
@ -381,7 +381,7 @@ public:
* @return Bytes appended or negative on error (return value of marshal()) * @return Bytes appended or negative on error (return value of marshal())
*/ */
template< typename V, typename T > template< typename V, typename T >
static ZT_INLINE int appendObject(V &out, const char *const k, const T &v) ZT_MAYBE_UNUSED static ZT_INLINE int appendObject(V &out, const char *const k, const T &v)
{ {
uint8_t tmp[2048]; // large enough for any current object uint8_t tmp[2048]; // large enough for any current object
if (T::marshalSizeMax() > sizeof(tmp)) if (T::marshalSizeMax() > sizeof(tmp))
@ -400,7 +400,7 @@ public:
* @param sub Subscript index * @param sub Subscript index
* @return Pointer to 'buf' * @return Pointer to 'buf'
*/ */
static char *arraySubscript(char *buf, unsigned int bufSize, const char *name, const unsigned long sub) noexcept; ZT_MAYBE_UNUSED static char *arraySubscript(char *buf, unsigned int bufSize, const char *name, const unsigned long sub) noexcept;
private: private:
template< typename V > template< typename V >

View file

@ -68,7 +68,7 @@ public:
private: private:
// Each bucket contains a timestamp in units of the max expect duration. // Each bucket contains a timestamp in units of the max expect duration.
std::atomic<uint32_t> m_packetIdSent[ZT_EXPECT_BUCKETS]; std::atomic< uint32_t > m_packetIdSent[ZT_EXPECT_BUCKETS];
}; };
} // namespace ZeroTier } // namespace ZeroTier

View file

@ -81,7 +81,7 @@ public:
/** /**
* Clear this vector, destroying all content objects * Clear this vector, destroying all content objects
*/ */
ZT_INLINE void clear() ZT_MAYBE_UNUSED ZT_INLINE void clear()
{ {
const unsigned int s = _s; const unsigned int s = _s;
_s = 0; _s = 0;
@ -94,51 +94,51 @@ public:
* *
* @param v Target vector * @param v Target vector
*/ */
ZT_INLINE void unsafeMoveTo(FCV &v) noexcept ZT_MAYBE_UNUSED ZT_INLINE void unsafeMoveTo(FCV &v) noexcept
{ {
Utils::copy(v._m, _m, (v._s = _s) * sizeof(T)); Utils::copy(v._m, _m, (v._s = _s) * sizeof(T));
_s = 0; _s = 0;
} }
ZT_INLINE iterator begin() noexcept ZT_MAYBE_UNUSED ZT_INLINE iterator begin() noexcept
{ return reinterpret_cast<T *>(_m); } { return reinterpret_cast<T *>(_m); }
ZT_INLINE iterator end() noexcept ZT_MAYBE_UNUSED ZT_INLINE iterator end() noexcept
{ return reinterpret_cast<T *>(_m) + _s; } { return reinterpret_cast<T *>(_m) + _s; }
ZT_INLINE const_iterator begin() const noexcept ZT_MAYBE_UNUSED ZT_INLINE const_iterator begin() const noexcept
{ return reinterpret_cast<const T *>(_m); } { return reinterpret_cast<const T *>(_m); }
ZT_INLINE const_iterator end() const noexcept ZT_MAYBE_UNUSED ZT_INLINE const_iterator end() const noexcept
{ return reinterpret_cast<const T *>(_m) + _s; } { return reinterpret_cast<const T *>(_m) + _s; }
ZT_INLINE T &operator[](const unsigned int i) ZT_MAYBE_UNUSED ZT_INLINE T &operator[](const unsigned int i)
{ {
if (likely(i < _s)) if (likely(i < _s))
return reinterpret_cast<T *>(_m)[i]; return reinterpret_cast<T *>(_m)[i];
throw Utils::OutOfRangeException; throw Utils::OutOfRangeException;
} }
ZT_INLINE const T &operator[](const unsigned int i) const ZT_MAYBE_UNUSED ZT_INLINE const T &operator[](const unsigned int i) const
{ {
if (likely(i < _s)) if (likely(i < _s))
return reinterpret_cast<const T *>(_m)[i]; return reinterpret_cast<const T *>(_m)[i];
throw Utils::OutOfRangeException; throw Utils::OutOfRangeException;
} }
static constexpr unsigned int capacity() noexcept ZT_MAYBE_UNUSED static constexpr unsigned int capacity() noexcept
{ return C; } { return C; }
ZT_INLINE unsigned int size() const noexcept ZT_MAYBE_UNUSED ZT_INLINE unsigned int size() const noexcept
{ return _s; } { return _s; }
ZT_INLINE bool empty() const noexcept ZT_MAYBE_UNUSED ZT_INLINE bool empty() const noexcept
{ return (_s == 0); } { return (_s == 0); }
ZT_INLINE T *data() noexcept ZT_MAYBE_UNUSED ZT_INLINE T *data() noexcept
{ return reinterpret_cast<T *>(_m); } { return reinterpret_cast<T *>(_m); }
ZT_INLINE const T *data() const noexcept ZT_MAYBE_UNUSED ZT_INLINE const T *data() const noexcept
{ return reinterpret_cast<const T *>(_m); } { return reinterpret_cast<const T *>(_m); }
/** /**
@ -148,7 +148,7 @@ public:
* *
* @param v Value to push * @param v Value to push
*/ */
ZT_INLINE void push_back(const T &v) ZT_MAYBE_UNUSED ZT_INLINE void push_back(const T &v)
{ {
if (likely(_s < C)) if (likely(_s < C))
new(reinterpret_cast<T *>(_m) + _s++) T(v); new(reinterpret_cast<T *>(_m) + _s++) T(v);
@ -160,7 +160,7 @@ public:
* *
* @return Reference to new item * @return Reference to new item
*/ */
ZT_INLINE T &push() ZT_MAYBE_UNUSED ZT_INLINE T &push()
{ {
if (likely(_s < C)) { if (likely(_s < C)) {
return *(new(reinterpret_cast<T *>(_m) + _s++) T()); return *(new(reinterpret_cast<T *>(_m) + _s++) T());
@ -174,7 +174,7 @@ public:
* *
* @return Reference to new item * @return Reference to new item
*/ */
ZT_INLINE T &push(const T &v) ZT_MAYBE_UNUSED ZT_INLINE T &push(const T &v)
{ {
if (likely(_s < C)) { if (likely(_s < C)) {
return *(new(reinterpret_cast<T *>(_m) + _s++) T(v)); return *(new(reinterpret_cast<T *>(_m) + _s++) T(v));
@ -188,7 +188,7 @@ public:
/** /**
* Remove the last element if this vector is not empty * Remove the last element if this vector is not empty
*/ */
ZT_INLINE void pop_back() ZT_MAYBE_UNUSED ZT_INLINE void pop_back()
{ {
if (likely(_s != 0)) if (likely(_s != 0))
(reinterpret_cast<T *>(_m) + --_s)->~T(); (reinterpret_cast<T *>(_m) + --_s)->~T();
@ -199,7 +199,7 @@ public:
* *
* @param ns New size (clipped to C if larger than capacity) * @param ns New size (clipped to C if larger than capacity)
*/ */
ZT_INLINE void resize(unsigned int ns) ZT_MAYBE_UNUSED ZT_INLINE void resize(unsigned int ns)
{ {
if (unlikely(ns > C)) if (unlikely(ns > C))
throw Utils::OutOfRangeException; throw Utils::OutOfRangeException;
@ -216,7 +216,7 @@ public:
* *
* @param ns New size * @param ns New size
*/ */
ZT_INLINE void unsafeSetSize(unsigned int ns) ZT_MAYBE_UNUSED ZT_INLINE void unsafeSetSize(unsigned int ns)
{ _s = ns; } { _s = ns; }
/** /**
@ -228,7 +228,7 @@ public:
* @param i Index to obtain as a reference, resizing if needed * @param i Index to obtain as a reference, resizing if needed
* @return Reference to value at this index * @return Reference to value at this index
*/ */
ZT_INLINE T &at(unsigned int i) ZT_MAYBE_UNUSED ZT_INLINE T &at(unsigned int i)
{ {
if (i >= _s) { if (i >= _s) {
if (unlikely(i >= C)) if (unlikely(i >= C))
@ -250,7 +250,7 @@ public:
* @param end Ending iterator (must be greater than start) * @param end Ending iterator (must be greater than start)
*/ */
template< typename X > template< typename X >
ZT_INLINE void assign(X start, const X &end) ZT_MAYBE_UNUSED ZT_INLINE void assign(X start, const X &end)
{ {
const int l = std::min((int)std::distance(start, end), (int)C); const int l = std::min((int)std::distance(start, end), (int)C);
if (l > 0) { if (l > 0) {
@ -262,7 +262,7 @@ public:
} }
} }
ZT_INLINE bool operator==(const FCV &v) const noexcept ZT_MAYBE_UNUSED ZT_INLINE bool operator==(const FCV &v) const noexcept
{ {
if (_s == v._s) { if (_s == v._s) {
for (unsigned int i = 0; i < _s; ++i) { for (unsigned int i = 0; i < _s; ++i) {
@ -274,20 +274,20 @@ public:
return false; return false;
} }
ZT_INLINE bool operator!=(const FCV &v) const noexcept ZT_MAYBE_UNUSED ZT_INLINE bool operator!=(const FCV &v) const noexcept
{ return (!(*this == v)); } { return *this != v; }
ZT_INLINE bool operator<(const FCV &v) const noexcept ZT_MAYBE_UNUSED ZT_INLINE bool operator<(const FCV &v) const noexcept
{ return std::lexicographical_compare(begin(), end(), v.begin(), v.end()); } { return std::lexicographical_compare(begin(), end(), v.begin(), v.end()); }
ZT_INLINE bool operator>(const FCV &v) const noexcept ZT_MAYBE_UNUSED ZT_INLINE bool operator>(const FCV &v) const noexcept
{ return (v < *this); } { return (v < *this); }
ZT_INLINE bool operator<=(const FCV &v) const noexcept ZT_MAYBE_UNUSED ZT_INLINE bool operator<=(const FCV &v) const noexcept
{ return !(v < *this); } { return v >= *this; }
ZT_INLINE bool operator>=(const FCV &v) const noexcept ZT_MAYBE_UNUSED ZT_INLINE bool operator>=(const FCV &v) const noexcept
{ return !(*this < v); } { return *this >= v; }
private: private:
#ifdef _MSC_VER #ifdef _MSC_VER

View file

@ -92,24 +92,6 @@ public:
return true; return true;
} }
/**
* Check for equality with best possible specificity.
*
* If both fingerprints have a hash, that is compared. Otherwise just the
* addresses are compared.
*
* @param fp Fingerprint to test
*/
ZT_INLINE bool bestSpecificityEquals(const ZT_Fingerprint &fp) const noexcept
{
if (address == fp.address) {
if (Utils::allZero(fp.hash, ZT_FINGERPRINT_HASH_SIZE) || Utils::allZero(hash, ZT_FINGERPRINT_HASH_SIZE))
return true;
return (memcmp(hash, fp.hash, ZT_FINGERPRINT_HASH_SIZE) == 0);
}
return false;
}
ZT_INLINE void zero() noexcept ZT_INLINE void zero() noexcept
{ memoryZero(this); } { memoryZero(this); }

View file

@ -15,12 +15,10 @@
#include "Identity.hpp" #include "Identity.hpp"
#include "SHA512.hpp" #include "SHA512.hpp"
#include "Salsa20.hpp" #include "Salsa20.hpp"
#include "Poly1305.hpp"
#include "Utils.hpp" #include "Utils.hpp"
#include "Endpoint.hpp" #include "Endpoint.hpp"
#include "MIMC52.hpp" #include "MIMC52.hpp"
#include <algorithm>
#include <memory> #include <memory>
#include <utility> #include <utility>
@ -31,7 +29,7 @@ namespace {
// This is the memory-intensive hash function used to compute v0 identities from v0 public keys. // This is the memory-intensive hash function used to compute v0 identities from v0 public keys.
#define ZT_V0_IDENTITY_GEN_MEMORY 2097152 #define ZT_V0_IDENTITY_GEN_MEMORY 2097152
void identityV0ProofOfWorkFrankenhash(const void *const publicKey, unsigned int publicKeyBytes, void *const digest, void *const genmem) noexcept void identityV0ProofOfWorkFrankenhash(const void *const restrict publicKey, unsigned int publicKeyBytes, void *const restrict digest, void *const restrict genmem) noexcept
{ {
// Digest publicKey[] to obtain initial digest // Digest publicKey[] to obtain initial digest
SHA512(digest, publicKey, publicKeyBytes); SHA512(digest, publicKey, publicKeyBytes);
@ -68,7 +66,7 @@ void identityV0ProofOfWorkFrankenhash(const void *const publicKey, unsigned int
struct identityV0ProofOfWorkCriteria struct identityV0ProofOfWorkCriteria
{ {
ZT_INLINE identityV0ProofOfWorkCriteria(unsigned char *sb, char *gm) noexcept: digest(sb), genmem(gm) ZT_INLINE identityV0ProofOfWorkCriteria(unsigned char *restrict sb, char *restrict gm) noexcept: digest(sb), genmem(gm)
{} {}
ZT_INLINE bool operator()(const uint8_t pub[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE]) const noexcept ZT_INLINE bool operator()(const uint8_t pub[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE]) const noexcept

View file

@ -27,7 +27,7 @@ const InetAddress InetAddress::LO4((const void *) ("\x7f\x00\x00\x01"), 4, 0);
const InetAddress InetAddress::LO6((const void *) ("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"), 16, 0); const InetAddress InetAddress::LO6((const void *) ("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"), 16, 0);
const InetAddress InetAddress::NIL; const InetAddress InetAddress::NIL;
InetAddress::IpScope InetAddress::ipScope() const noexcept ZT_MAYBE_UNUSED InetAddress::IpScope InetAddress::ipScope() const noexcept
{ {
switch (as.ss.ss_family) { switch (as.ss.ss_family) {
@ -40,17 +40,17 @@ InetAddress::IpScope InetAddress::ipScope() const noexcept
return ZT_IP_SCOPE_PSEUDOPRIVATE; // 6.0.0.0/8 (US Army) return ZT_IP_SCOPE_PSEUDOPRIVATE; // 6.0.0.0/8 (US Army)
case 0x0a: case 0x0a:
return ZT_IP_SCOPE_PRIVATE; // 10.0.0.0/8 return ZT_IP_SCOPE_PRIVATE; // 10.0.0.0/8
case 0x0b: //return IP_SCOPE_PSEUDOPRIVATE; // 11.0.0.0/8 (US DoD) case 0x0b: //return IP_SCOPE_PSEUDOPRIVATE; // 11.0.0.0/8 (US DoD)
case 0x15: //return IP_SCOPE_PSEUDOPRIVATE; // 21.0.0.0/8 (US DDN-RVN) case 0x15: //return IP_SCOPE_PSEUDOPRIVATE; // 21.0.0.0/8 (US DDN-RVN)
case 0x16: //return IP_SCOPE_PSEUDOPRIVATE; // 22.0.0.0/8 (US DISA) case 0x16: //return IP_SCOPE_PSEUDOPRIVATE; // 22.0.0.0/8 (US DISA)
case 0x19: //return IP_SCOPE_PSEUDOPRIVATE; // 25.0.0.0/8 (UK Ministry of Defense) case 0x19: //return IP_SCOPE_PSEUDOPRIVATE; // 25.0.0.0/8 (UK Ministry of Defense)
case 0x1a: //return IP_SCOPE_PSEUDOPRIVATE; // 26.0.0.0/8 (US DISA) case 0x1a: //return IP_SCOPE_PSEUDOPRIVATE; // 26.0.0.0/8 (US DISA)
case 0x1c: //return IP_SCOPE_PSEUDOPRIVATE; // 28.0.0.0/8 (US DSI-North) case 0x1c: //return IP_SCOPE_PSEUDOPRIVATE; // 28.0.0.0/8 (US DSI-North)
case 0x1d: //return IP_SCOPE_PSEUDOPRIVATE; // 29.0.0.0/8 (US DISA) case 0x1d: //return IP_SCOPE_PSEUDOPRIVATE; // 29.0.0.0/8 (US DISA)
case 0x1e: //return IP_SCOPE_PSEUDOPRIVATE; // 30.0.0.0/8 (US DISA) case 0x1e: //return IP_SCOPE_PSEUDOPRIVATE; // 30.0.0.0/8 (US DISA)
case 0x33: //return IP_SCOPE_PSEUDOPRIVATE; // 51.0.0.0/8 (UK Department of Social Security) case 0x33: //return IP_SCOPE_PSEUDOPRIVATE; // 51.0.0.0/8 (UK Department of Social Security)
case 0x37: //return IP_SCOPE_PSEUDOPRIVATE; // 55.0.0.0/8 (US DoD) case 0x37: //return IP_SCOPE_PSEUDOPRIVATE; // 55.0.0.0/8 (US DoD)
case 0x38: // 56.0.0.0/8 (US Postal Service) case 0x38: // 56.0.0.0/8 (US Postal Service)
return ZT_IP_SCOPE_PSEUDOPRIVATE; return ZT_IP_SCOPE_PSEUDOPRIVATE;
case 0x64: case 0x64:
if ((ip & 0xffc00000) == 0x64400000) return ZT_IP_SCOPE_PRIVATE; // 100.64.0.0/10 if ((ip & 0xffc00000) == 0x64400000) return ZT_IP_SCOPE_PRIVATE; // 100.64.0.0/10
@ -112,7 +112,7 @@ InetAddress::IpScope InetAddress::ipScope() const noexcept
return ZT_IP_SCOPE_NONE; return ZT_IP_SCOPE_NONE;
} }
void InetAddress::set(const void *ipBytes, unsigned int ipLen, unsigned int port) noexcept ZT_MAYBE_UNUSED void InetAddress::set(const void *ipBytes, unsigned int ipLen, unsigned int port) noexcept
{ {
memoryZero(this); memoryZero(this);
if (ipLen == 4) { if (ipLen == 4) {
@ -126,7 +126,7 @@ void InetAddress::set(const void *ipBytes, unsigned int ipLen, unsigned int port
} }
} }
bool InetAddress::isDefaultRoute() const noexcept ZT_MAYBE_UNUSED bool InetAddress::isDefaultRoute() const noexcept
{ {
switch (as.ss.ss_family) { switch (as.ss.ss_family) {
case AF_INET: case AF_INET:
@ -145,7 +145,7 @@ bool InetAddress::isDefaultRoute() const noexcept
} }
} }
char *InetAddress::toString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept ZT_MAYBE_UNUSED char *InetAddress::toString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept
{ {
char *p = toIpString(buf); char *p = toIpString(buf);
if (*p) { if (*p) {
@ -156,7 +156,7 @@ char *InetAddress::toString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noex
return buf; return buf;
} }
char *InetAddress::toIpString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept ZT_MAYBE_UNUSED char *InetAddress::toIpString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept
{ {
buf[0] = (char) 0; buf[0] = (char) 0;
switch (as.ss.ss_family) { switch (as.ss.ss_family) {
@ -170,7 +170,7 @@ char *InetAddress::toIpString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const no
return buf; return buf;
} }
bool InetAddress::fromString(const char *ipSlashPort) noexcept ZT_MAYBE_UNUSED bool InetAddress::fromString(const char *ipSlashPort) noexcept
{ {
char buf[64]; char buf[64];
@ -205,7 +205,7 @@ bool InetAddress::fromString(const char *ipSlashPort) noexcept
return false; return false;
} }
InetAddress InetAddress::netmask() const noexcept ZT_MAYBE_UNUSED InetAddress InetAddress::netmask() const noexcept
{ {
InetAddress r(*this); InetAddress r(*this);
switch (r.as.ss.ss_family) { switch (r.as.ss.ss_family) {
@ -229,7 +229,7 @@ InetAddress InetAddress::netmask() const noexcept
return r; return r;
} }
InetAddress InetAddress::broadcast() const noexcept ZT_MAYBE_UNUSED InetAddress InetAddress::broadcast() const noexcept
{ {
if (as.ss.ss_family == AF_INET) { if (as.ss.ss_family == AF_INET) {
InetAddress r(*this); InetAddress r(*this);
@ -239,7 +239,7 @@ InetAddress InetAddress::broadcast() const noexcept
return InetAddress(); return InetAddress();
} }
InetAddress InetAddress::network() const noexcept ZT_MAYBE_UNUSED InetAddress InetAddress::network() const noexcept
{ {
InetAddress r(*this); InetAddress r(*this);
switch (r.as.ss.ss_family) { switch (r.as.ss.ss_family) {
@ -259,7 +259,7 @@ InetAddress InetAddress::network() const noexcept
return r; return r;
} }
bool InetAddress::isEqualPrefix(const InetAddress &addr) const noexcept ZT_MAYBE_UNUSED bool InetAddress::isEqualPrefix(const InetAddress &addr) const noexcept
{ {
if (addr.as.ss.ss_family == as.ss.ss_family) { if (addr.as.ss.ss_family == as.ss.ss_family) {
switch (as.ss.ss_family) { switch (as.ss.ss_family) {
@ -281,7 +281,7 @@ bool InetAddress::isEqualPrefix(const InetAddress &addr) const noexcept
return false; return false;
} }
bool InetAddress::containsAddress(const InetAddress &addr) const noexcept ZT_MAYBE_UNUSED bool InetAddress::containsAddress(const InetAddress &addr) const noexcept
{ {
if (addr.as.ss.ss_family == as.ss.ss_family) { if (addr.as.ss.ss_family == as.ss.ss_family) {
switch (as.ss.ss_family) { switch (as.ss.ss_family) {
@ -310,7 +310,7 @@ bool InetAddress::containsAddress(const InetAddress &addr) const noexcept
return false; return false;
} }
bool InetAddress::isNetwork() const noexcept ZT_MAYBE_UNUSED bool InetAddress::isNetwork() const noexcept
{ {
switch (as.ss.ss_family) { switch (as.ss.ss_family) {
case AF_INET: { case AF_INET: {
@ -342,7 +342,7 @@ bool InetAddress::isNetwork() const noexcept
return false; return false;
} }
int InetAddress::marshal(uint8_t data[ZT_INETADDRESS_MARSHAL_SIZE_MAX]) const noexcept ZT_MAYBE_UNUSED int InetAddress::marshal(uint8_t data[ZT_INETADDRESS_MARSHAL_SIZE_MAX]) const noexcept
{ {
unsigned int port; unsigned int port;
switch (as.ss.ss_family) { switch (as.ss.ss_family) {
@ -369,7 +369,7 @@ int InetAddress::marshal(uint8_t data[ZT_INETADDRESS_MARSHAL_SIZE_MAX]) const no
} }
} }
int InetAddress::unmarshal(const uint8_t *restrict data, const int len) noexcept ZT_MAYBE_UNUSED int InetAddress::unmarshal(const uint8_t *restrict data, const int len) noexcept
{ {
memoryZero(this); memoryZero(this);
if (unlikely(len <= 0)) if (unlikely(len <= 0))
@ -396,7 +396,7 @@ int InetAddress::unmarshal(const uint8_t *restrict data, const int len) noexcept
} }
} }
InetAddress InetAddress::makeIpv6LinkLocal(const MAC &mac) noexcept ZT_MAYBE_UNUSED InetAddress InetAddress::makeIpv6LinkLocal(const MAC &mac) noexcept
{ {
InetAddress r; InetAddress r;
r.as.sa_in6.sin6_family = AF_INET6; r.as.sa_in6.sin6_family = AF_INET6;
@ -420,7 +420,7 @@ InetAddress InetAddress::makeIpv6LinkLocal(const MAC &mac) noexcept
return r; return r;
} }
InetAddress InetAddress::makeIpv6rfc4193(uint64_t nwid, uint64_t zeroTierAddress) noexcept ZT_MAYBE_UNUSED InetAddress InetAddress::makeIpv6rfc4193(uint64_t nwid, uint64_t zeroTierAddress) noexcept
{ {
InetAddress r; InetAddress r;
r.as.sa_in6.sin6_family = AF_INET6; r.as.sa_in6.sin6_family = AF_INET6;
@ -444,7 +444,7 @@ InetAddress InetAddress::makeIpv6rfc4193(uint64_t nwid, uint64_t zeroTierAddress
return r; return r;
} }
InetAddress InetAddress::makeIpv66plane(uint64_t nwid, uint64_t zeroTierAddress) noexcept ZT_MAYBE_UNUSED InetAddress InetAddress::makeIpv66plane(uint64_t nwid, uint64_t zeroTierAddress) noexcept
{ {
nwid ^= (nwid >> 32U); nwid ^= (nwid >> 32U);
InetAddress r; InetAddress r;
@ -465,8 +465,8 @@ InetAddress InetAddress::makeIpv66plane(uint64_t nwid, uint64_t zeroTierAddress)
} }
extern "C" { extern "C" {
extern const int ZT_AF_INET = (int)AF_INET; ZT_MAYBE_UNUSED extern const int ZT_AF_INET = (int)AF_INET;
extern const int ZT_AF_INET6 = (int)AF_INET6; ZT_MAYBE_UNUSED extern const int ZT_AF_INET6 = (int)AF_INET6;
} }
} // namespace ZeroTier } // namespace ZeroTier

View file

@ -60,13 +60,6 @@ public:
*/ */
typedef ZT_InetAddress_IpScope IpScope; typedef ZT_InetAddress_IpScope IpScope;
// Hasher for unordered sets and maps in C++11
struct Hasher
{
ZT_INLINE std::size_t operator()(const InetAddress &a) const noexcept
{ return (std::size_t)a.hashCode(); }
};
ZT_INLINE InetAddress() noexcept ZT_INLINE InetAddress() noexcept
{ memoryZero(this); } { memoryZero(this); }
@ -169,19 +162,13 @@ public:
return *this; return *this;
} }
ZT_INLINE void clear() noexcept ZT_MAYBE_UNUSED ZT_INLINE void clear() noexcept
{ memoryZero(this); } { memoryZero(this); }
/**
* @return Address family (ss_family in sockaddr_storage)
*/
ZT_INLINE uint8_t family() const noexcept
{ return as.ss.ss_family; }
/** /**
* @return IP scope classification (e.g. loopback, link-local, private, global) * @return IP scope classification (e.g. loopback, link-local, private, global)
*/ */
IpScope ipScope() const noexcept; ZT_MAYBE_UNUSED IpScope ipScope() const noexcept;
/** /**
* Set from a raw IP and port number * Set from a raw IP and port number
@ -190,14 +177,14 @@ public:
* @param ipLen Length of IP address: 4 or 16 * @param ipLen Length of IP address: 4 or 16
* @param port Port number or 0 for none * @param port Port number or 0 for none
*/ */
void set(const void *ipBytes, unsigned int ipLen, unsigned int port) noexcept; ZT_MAYBE_UNUSED void set(const void *ipBytes, unsigned int ipLen, unsigned int port) noexcept;
/** /**
* Set the port component * Set the port component
* *
* @param port Port, 0 to 65535 * @param port Port, 0 to 65535
*/ */
ZT_INLINE void setPort(unsigned int port) noexcept ZT_MAYBE_UNUSED ZT_INLINE void setPort(unsigned int port) noexcept
{ {
switch (as.ss.ss_family) { switch (as.ss.ss_family) {
case AF_INET: case AF_INET:
@ -212,14 +199,14 @@ public:
/** /**
* @return True if this network/netmask route describes a default route (e.g. 0.0.0.0/0) * @return True if this network/netmask route describes a default route (e.g. 0.0.0.0/0)
*/ */
bool isDefaultRoute() const noexcept; ZT_MAYBE_UNUSED bool isDefaultRoute() const noexcept;
/** /**
* @return ASCII IP/port format representation * @return ASCII IP/port format representation
*/ */
char *toString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept; ZT_MAYBE_UNUSED char *toString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept;
ZT_INLINE String toString() const ZT_MAYBE_UNUSED ZT_INLINE String toString() const
{ {
char buf[ZT_INETADDRESS_STRING_SIZE_MAX]; char buf[ZT_INETADDRESS_STRING_SIZE_MAX];
toString(buf); toString(buf);
@ -229,9 +216,9 @@ public:
/** /**
* @return IP portion only, in ASCII string format * @return IP portion only, in ASCII string format
*/ */
char *toIpString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept; ZT_MAYBE_UNUSED char *toIpString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept;
ZT_INLINE String toIpString() const ZT_MAYBE_UNUSED ZT_INLINE String toIpString() const
{ {
char buf[ZT_INETADDRESS_STRING_SIZE_MAX]; char buf[ZT_INETADDRESS_STRING_SIZE_MAX];
toIpString(buf); toIpString(buf);
@ -242,12 +229,12 @@ public:
* @param ipSlashPort IP/port (port is optional, will be 0 if not included) * @param ipSlashPort IP/port (port is optional, will be 0 if not included)
* @return True if address appeared to be valid * @return True if address appeared to be valid
*/ */
bool fromString(const char *ipSlashPort) noexcept; ZT_MAYBE_UNUSED bool fromString(const char *ipSlashPort) noexcept;
/** /**
* @return Port or 0 if no port component defined * @return Port or 0 if no port component defined
*/ */
ZT_INLINE unsigned int port() const noexcept ZT_MAYBE_UNUSED ZT_INLINE unsigned int port() const noexcept
{ {
switch (as.ss.ss_family) { switch (as.ss.ss_family) {
case AF_INET: case AF_INET:
@ -268,13 +255,13 @@ public:
* *
* @return Netmask bits * @return Netmask bits
*/ */
ZT_INLINE unsigned int netmaskBits() const noexcept ZT_MAYBE_UNUSED ZT_INLINE unsigned int netmaskBits() const noexcept
{ return port(); } { return port(); }
/** /**
* @return True if netmask bits is valid for the address type * @return True if netmask bits is valid for the address type
*/ */
ZT_INLINE bool netmaskBitsValid() const noexcept ZT_MAYBE_UNUSED ZT_INLINE bool netmaskBitsValid() const noexcept
{ {
const unsigned int n = port(); const unsigned int n = port();
switch (as.ss.ss_family) { switch (as.ss.ss_family) {
@ -294,7 +281,7 @@ public:
* *
* @return Gateway metric * @return Gateway metric
*/ */
ZT_INLINE unsigned int metric() const noexcept ZT_MAYBE_UNUSED ZT_INLINE unsigned int metric() const noexcept
{ return port(); } { return port(); }
/** /**
@ -302,7 +289,7 @@ public:
* *
* @return Netmask such as 255.255.255.0 if this address is /24 (port field will be unchanged) * @return Netmask such as 255.255.255.0 if this address is /24 (port field will be unchanged)
*/ */
InetAddress netmask() const noexcept; ZT_MAYBE_UNUSED InetAddress netmask() const noexcept;
/** /**
* Constructs a broadcast address from a network/netmask address * Constructs a broadcast address from a network/netmask address
@ -312,14 +299,14 @@ public:
* *
* @return Broadcast address (only IP portion is meaningful) * @return Broadcast address (only IP portion is meaningful)
*/ */
InetAddress broadcast() const noexcept; ZT_MAYBE_UNUSED InetAddress broadcast() const noexcept;
/** /**
* Return the network -- a.k.a. the IP ANDed with the netmask * Return the network -- a.k.a. the IP ANDed with the netmask
* *
* @return Network e.g. 10.0.1.0/24 from 10.0.1.200/24 * @return Network e.g. 10.0.1.0/24 from 10.0.1.200/24
*/ */
InetAddress network() const noexcept; ZT_MAYBE_UNUSED InetAddress network() const noexcept;
/** /**
* Test whether this IPv6 prefix matches the prefix of a given IPv6 address * Test whether this IPv6 prefix matches the prefix of a given IPv6 address
@ -327,7 +314,7 @@ public:
* @param addr Address to check * @param addr Address to check
* @return True if this IPv6 prefix matches the prefix of a given IPv6 address * @return True if this IPv6 prefix matches the prefix of a given IPv6 address
*/ */
bool isEqualPrefix(const InetAddress &addr) const noexcept; ZT_MAYBE_UNUSED bool isEqualPrefix(const InetAddress &addr) const noexcept;
/** /**
* Test whether this IP/netmask contains this address * Test whether this IP/netmask contains this address
@ -335,24 +322,24 @@ public:
* @param addr Address to check * @param addr Address to check
* @return True if this IP/netmask (route) contains this address * @return True if this IP/netmask (route) contains this address
*/ */
bool containsAddress(const InetAddress &addr) const noexcept; ZT_MAYBE_UNUSED bool containsAddress(const InetAddress &addr) const noexcept;
/** /**
* @return True if this is an IPv4 address * @return True if this is an IPv4 address
*/ */
ZT_INLINE bool isV4() const noexcept ZT_MAYBE_UNUSED ZT_INLINE bool isV4() const noexcept
{ return (as.ss.ss_family == AF_INET); } { return (as.ss.ss_family == AF_INET); }
/** /**
* @return True if this is an IPv6 address * @return True if this is an IPv6 address
*/ */
ZT_INLINE bool isV6() const noexcept ZT_MAYBE_UNUSED ZT_INLINE bool isV6() const noexcept
{ return (as.ss.ss_family == AF_INET6); } { return (as.ss.ss_family == AF_INET6); }
/** /**
* @return pointer to raw address bytes or NULL if not available * @return pointer to raw address bytes or NULL if not available
*/ */
ZT_INLINE const void *rawIpData() const noexcept ZT_MAYBE_UNUSED ZT_INLINE const void *rawIpData() const noexcept
{ {
switch (as.ss.ss_family) { switch (as.ss.ss_family) {
case AF_INET: case AF_INET:
@ -367,7 +354,7 @@ public:
/** /**
* @return InetAddress containing only the IP portion of this address and a zero port, or NULL if not IPv4 or IPv6 * @return InetAddress containing only the IP portion of this address and a zero port, or NULL if not IPv4 or IPv6
*/ */
ZT_INLINE InetAddress ipOnly() const noexcept ZT_MAYBE_UNUSED ZT_INLINE InetAddress ipOnly() const noexcept
{ {
InetAddress r; InetAddress r;
switch (as.ss.ss_family) { switch (as.ss.ss_family) {
@ -389,7 +376,7 @@ public:
* @param a InetAddress to compare again * @param a InetAddress to compare again
* @return True if only IP portions are equal (false for non-IP or null addresses) * @return True if only IP portions are equal (false for non-IP or null addresses)
*/ */
ZT_INLINE bool ipsEqual(const InetAddress &a) const noexcept ZT_MAYBE_UNUSED ZT_INLINE bool ipsEqual(const InetAddress &a) const noexcept
{ {
const uint8_t f = as.ss.ss_family; const uint8_t f = as.ss.ss_family;
if (f == a.as.ss.ss_family) { if (f == a.as.ss.ss_family) {
@ -410,7 +397,7 @@ public:
* @param a InetAddress to compare again * @param a InetAddress to compare again
* @return True if only IP portions are equal (false for non-IP or null addresses) * @return True if only IP portions are equal (false for non-IP or null addresses)
*/ */
ZT_INLINE bool ipsEqual2(const InetAddress &a) const noexcept ZT_MAYBE_UNUSED ZT_INLINE bool ipsEqual2(const InetAddress &a) const noexcept
{ {
const uint8_t f = as.ss.ss_family; const uint8_t f = as.ss.ss_family;
if (f == a.as.ss.ss_family) { if (f == a.as.ss.ss_family) {
@ -423,7 +410,7 @@ public:
return false; return false;
} }
ZT_INLINE unsigned long hashCode() const noexcept ZT_MAYBE_UNUSED ZT_INLINE unsigned long hashCode() const noexcept
{ {
if (as.ss.ss_family == AF_INET) { if (as.ss.ss_family == AF_INET) {
return (unsigned long)Utils::hash32(((uint32_t)as.sa_in.sin_addr.s_addr + (uint32_t)as.sa_in.sin_port) ^ (uint32_t)Utils::s_mapNonce); return (unsigned long)Utils::hash32(((uint32_t)as.sa_in.sin_addr.s_addr + (uint32_t)as.sa_in.sin_port) ^ (uint32_t)Utils::s_mapNonce);
@ -445,20 +432,20 @@ public:
* *
* @return True if everything after netmask bits is zero * @return True if everything after netmask bits is zero
*/ */
bool isNetwork() const noexcept; ZT_MAYBE_UNUSED bool isNetwork() const noexcept;
/** /**
* @return True if address family is non-zero * @return True if address family is non-zero
*/ */
explicit ZT_INLINE operator bool() const noexcept ZT_MAYBE_UNUSED explicit ZT_INLINE operator bool() const noexcept
{ return (as.ss.ss_family != 0); } { return (as.ss.ss_family != 0); }
static constexpr int marshalSizeMax() noexcept ZT_MAYBE_UNUSED static constexpr int marshalSizeMax() noexcept
{ return ZT_INETADDRESS_MARSHAL_SIZE_MAX; } { return ZT_INETADDRESS_MARSHAL_SIZE_MAX; }
int marshal(uint8_t data[ZT_INETADDRESS_MARSHAL_SIZE_MAX]) const noexcept; ZT_MAYBE_UNUSED int marshal(uint8_t data[ZT_INETADDRESS_MARSHAL_SIZE_MAX]) const noexcept;
int unmarshal(const uint8_t *restrict data, int len) noexcept; ZT_MAYBE_UNUSED int unmarshal(const uint8_t *restrict data, int len) noexcept;
ZT_INLINE bool operator==(const InetAddress &a) const noexcept ZT_INLINE bool operator==(const InetAddress &a) const noexcept
{ {
@ -512,7 +499,7 @@ public:
* @param mac MAC address seed * @param mac MAC address seed
* @return IPv6 link-local address * @return IPv6 link-local address
*/ */
static InetAddress makeIpv6LinkLocal(const MAC &mac) noexcept; ZT_MAYBE_UNUSED static InetAddress makeIpv6LinkLocal(const MAC &mac) noexcept;
/** /**
* Compute private IPv6 unicast address from network ID and ZeroTier address * Compute private IPv6 unicast address from network ID and ZeroTier address
@ -574,64 +561,64 @@ public:
} as; } as;
}; };
static ZT_INLINE InetAddress *asInetAddress(sockaddr_in *const p) noexcept ZT_MAYBE_UNUSED static ZT_INLINE InetAddress *asInetAddress(sockaddr_in *const p) noexcept
{ return reinterpret_cast<InetAddress *>(p); } { return reinterpret_cast<InetAddress *>(p); }
static ZT_INLINE InetAddress *asInetAddress(sockaddr_in6 *const p) noexcept ZT_MAYBE_UNUSED static ZT_INLINE InetAddress *asInetAddress(sockaddr_in6 *const p) noexcept
{ return reinterpret_cast<InetAddress *>(p); } { return reinterpret_cast<InetAddress *>(p); }
static ZT_INLINE InetAddress *asInetAddress(sockaddr *const p) noexcept ZT_MAYBE_UNUSED static ZT_INLINE InetAddress *asInetAddress(sockaddr *const p) noexcept
{ return reinterpret_cast<InetAddress *>(p); } { return reinterpret_cast<InetAddress *>(p); }
static ZT_INLINE InetAddress *asInetAddress(sockaddr_storage *const p) noexcept ZT_MAYBE_UNUSED static ZT_INLINE InetAddress *asInetAddress(sockaddr_storage *const p) noexcept
{ return reinterpret_cast<InetAddress *>(p); } { return reinterpret_cast<InetAddress *>(p); }
static ZT_INLINE InetAddress *asInetAddress(ZT_InetAddress *const p) noexcept ZT_MAYBE_UNUSED static ZT_INLINE InetAddress *asInetAddress(ZT_InetAddress *const p) noexcept
{ return reinterpret_cast<InetAddress *>(p); } { return reinterpret_cast<InetAddress *>(p); }
static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_in *const p) noexcept ZT_MAYBE_UNUSED static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_in *const p) noexcept
{ return reinterpret_cast<const InetAddress *>(p); } { return reinterpret_cast<const InetAddress *>(p); }
static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_in6 *const p) noexcept ZT_MAYBE_UNUSED static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_in6 *const p) noexcept
{ return reinterpret_cast<const InetAddress *>(p); } { return reinterpret_cast<const InetAddress *>(p); }
static ZT_INLINE const InetAddress *asInetAddress(const sockaddr *const p) noexcept ZT_MAYBE_UNUSED static ZT_INLINE const InetAddress *asInetAddress(const sockaddr *const p) noexcept
{ return reinterpret_cast<const InetAddress *>(p); } { return reinterpret_cast<const InetAddress *>(p); }
static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_storage *const p) noexcept ZT_MAYBE_UNUSED static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_storage *const p) noexcept
{ return reinterpret_cast<const InetAddress *>(p); } { return reinterpret_cast<const InetAddress *>(p); }
static ZT_INLINE const InetAddress *asInetAddress(const ZT_InetAddress *const p) noexcept ZT_MAYBE_UNUSED static ZT_INLINE const InetAddress *asInetAddress(const ZT_InetAddress *const p) noexcept
{ return reinterpret_cast<const InetAddress *>(p); } { return reinterpret_cast<const InetAddress *>(p); }
static ZT_INLINE InetAddress &asInetAddress(sockaddr_in &p) noexcept ZT_MAYBE_UNUSED static ZT_INLINE InetAddress &asInetAddress(sockaddr_in &p) noexcept
{ return *reinterpret_cast<InetAddress *>(&p); } { return *reinterpret_cast<InetAddress *>(&p); }
static ZT_INLINE InetAddress &asInetAddress(sockaddr_in6 &p) noexcept ZT_MAYBE_UNUSED static ZT_INLINE InetAddress &asInetAddress(sockaddr_in6 &p) noexcept
{ return *reinterpret_cast<InetAddress *>(&p); } { return *reinterpret_cast<InetAddress *>(&p); }
static ZT_INLINE InetAddress &asInetAddress(sockaddr &p) noexcept ZT_MAYBE_UNUSED static ZT_INLINE InetAddress &asInetAddress(sockaddr &p) noexcept
{ return *reinterpret_cast<InetAddress *>(&p); } { return *reinterpret_cast<InetAddress *>(&p); }
static ZT_INLINE InetAddress &asInetAddress(sockaddr_storage &p) noexcept ZT_MAYBE_UNUSED static ZT_INLINE InetAddress &asInetAddress(sockaddr_storage &p) noexcept
{ return *reinterpret_cast<InetAddress *>(&p); } { return *reinterpret_cast<InetAddress *>(&p); }
static ZT_INLINE InetAddress &asInetAddress(ZT_InetAddress &p) noexcept ZT_MAYBE_UNUSED static ZT_INLINE InetAddress &asInetAddress(ZT_InetAddress &p) noexcept
{ return *reinterpret_cast<InetAddress *>(&p); } { return *reinterpret_cast<InetAddress *>(&p); }
static ZT_INLINE const InetAddress &asInetAddress(const sockaddr_in &p) noexcept ZT_MAYBE_UNUSED static ZT_INLINE const InetAddress &asInetAddress(const sockaddr_in &p) noexcept
{ return *reinterpret_cast<const InetAddress *>(&p); } { return *reinterpret_cast<const InetAddress *>(&p); }
static ZT_INLINE const InetAddress &asInetAddress(const sockaddr_in6 &p) noexcept ZT_MAYBE_UNUSED static ZT_INLINE const InetAddress &asInetAddress(const sockaddr_in6 &p) noexcept
{ return *reinterpret_cast<const InetAddress *>(&p); } { return *reinterpret_cast<const InetAddress *>(&p); }
static ZT_INLINE const InetAddress &asInetAddress(const sockaddr &p) noexcept ZT_MAYBE_UNUSED static ZT_INLINE const InetAddress &asInetAddress(const sockaddr &p) noexcept
{ return *reinterpret_cast<const InetAddress *>(&p); } { return *reinterpret_cast<const InetAddress *>(&p); }
static ZT_INLINE const InetAddress &asInetAddress(const sockaddr_storage &p) noexcept ZT_MAYBE_UNUSED static ZT_INLINE const InetAddress &asInetAddress(const sockaddr_storage &p) noexcept
{ return *reinterpret_cast<const InetAddress *>(&p); } { return *reinterpret_cast<const InetAddress *>(&p); }
static ZT_INLINE const InetAddress &asInetAddress(const ZT_InetAddress &p) noexcept ZT_MAYBE_UNUSED static ZT_INLINE const InetAddress &asInetAddress(const ZT_InetAddress &p) noexcept
{ return *reinterpret_cast<const InetAddress *>(&p); } { return *reinterpret_cast<const InetAddress *>(&p); }
} // namespace ZeroTier } // namespace ZeroTier

View file

@ -24,7 +24,7 @@ Locator::Locator(const char *const str) noexcept :
__refCount(0) __refCount(0)
{ {
if (!fromString(str)) { if (!fromString(str)) {
m_ts = 0; m_revision = 0;
m_signer.zero(); m_signer.zero();
m_endpoints.clear(); m_endpoints.clear();
m_signature.clear(); m_signature.clear();
@ -46,9 +46,9 @@ bool Locator::add(const Endpoint &ep, const SharedPtr< const EndpointAttributes
return false; return false;
} }
bool Locator::sign(const int64_t ts, const Identity &id) noexcept bool Locator::sign(const int64_t rev, const Identity &id) noexcept
{ {
m_ts = ts; m_revision = rev;
m_signer = id.fingerprint(); m_signer = id.fingerprint();
m_sortEndpoints(); m_sortEndpoints();
@ -67,7 +67,7 @@ bool Locator::sign(const int64_t ts, const Identity &id) noexcept
bool Locator::verify(const Identity &id) const noexcept bool Locator::verify(const Identity &id) const noexcept
{ {
try { try {
if ((m_ts > 0) && (m_signer == id.fingerprint())) { if ((m_revision > 0) && (m_signer == id.fingerprint())) {
uint8_t signdata[ZT_LOCATOR_MARSHAL_SIZE_MAX]; uint8_t signdata[ZT_LOCATOR_MARSHAL_SIZE_MAX];
const unsigned int signlen = marshal(signdata, true); const unsigned int signlen = marshal(signdata, true);
return id.verify(signdata, signlen, m_signature.data(), m_signature.size()); return id.verify(signdata, signlen, m_signature.data(), m_signature.size());
@ -101,7 +101,7 @@ bool Locator::fromString(const char *s) noexcept
int Locator::marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX], const bool excludeSignature) const noexcept int Locator::marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX], const bool excludeSignature) const noexcept
{ {
Utils::storeBigEndian<uint64_t>(data, (uint64_t) m_ts); Utils::storeBigEndian<uint64_t>(data, (uint64_t) m_revision);
int p = 8; int p = 8;
int l = m_signer.marshal(data + p); int l = m_signer.marshal(data + p);
@ -143,7 +143,7 @@ int Locator::unmarshal(const uint8_t *data, const int len) noexcept
{ {
if (unlikely(len < 8)) if (unlikely(len < 8))
return -1; return -1;
m_ts = (int64_t)Utils::loadBigEndian<uint64_t>(data); m_revision = (int64_t)Utils::loadBigEndian<uint64_t>(data);
int p = 8; int p = 8;
int l = m_signer.unmarshal(data + p, len - p); int l = m_signer.unmarshal(data + p, len - p);

View file

@ -106,13 +106,13 @@ public:
}; };
ZT_INLINE Locator() noexcept: ZT_INLINE Locator() noexcept:
m_ts(0) m_revision(0)
{} {}
explicit Locator(const char *const str) noexcept; explicit Locator(const char *const str) noexcept;
ZT_INLINE Locator(const Locator &loc) noexcept: ZT_INLINE Locator(const Locator &loc) noexcept:
m_ts(loc.m_ts), m_revision(loc.m_revision),
m_signer(loc.m_signer), m_signer(loc.m_signer),
m_endpoints(loc.m_endpoints), m_endpoints(loc.m_endpoints),
m_signature(loc.m_signature), m_signature(loc.m_signature),
@ -122,8 +122,8 @@ public:
/** /**
* @return Timestamp (a.k.a. revision number) set by Location signer * @return Timestamp (a.k.a. revision number) set by Location signer
*/ */
ZT_INLINE int64_t timestamp() const noexcept ZT_INLINE int64_t revision() const noexcept
{ return m_ts; } { return m_revision; }
/** /**
* @return Fingerprint of identity that signed this locator * @return Fingerprint of identity that signed this locator
@ -164,7 +164,7 @@ public:
* @param id Identity that includes private key * @param id Identity that includes private key
* @return True if signature successful * @return True if signature successful
*/ */
bool sign(int64_t ts, const Identity &id) noexcept; bool sign(int64_t rev, const Identity &id) noexcept;
/** /**
* Verify this Locator's validity and signature * Verify this Locator's validity and signature
@ -197,7 +197,7 @@ public:
bool fromString(const char *s) noexcept; bool fromString(const char *s) noexcept;
explicit ZT_INLINE operator bool() const noexcept explicit ZT_INLINE operator bool() const noexcept
{ return m_ts > 0; } { return m_revision > 0; }
static constexpr int marshalSizeMax() noexcept static constexpr int marshalSizeMax() noexcept
{ return ZT_LOCATOR_MARSHAL_SIZE_MAX; } { return ZT_LOCATOR_MARSHAL_SIZE_MAX; }
@ -207,7 +207,7 @@ public:
ZT_INLINE bool operator==(const Locator &l) const noexcept ZT_INLINE bool operator==(const Locator &l) const noexcept
{ {
const unsigned long es = (unsigned long)m_endpoints.size(); const unsigned long es = (unsigned long)m_endpoints.size();
if ((m_ts == l.m_ts) && (m_signer == l.m_signer) && (es == (unsigned long)l.m_endpoints.size()) && (m_signature == l.m_signature)) { if ((m_revision == l.m_revision) && (m_signer == l.m_signer) && (es == (unsigned long)l.m_endpoints.size()) && (m_signature == l.m_signature)) {
for(unsigned long i=0;i<es;++i) { for(unsigned long i=0;i<es;++i) {
if (m_endpoints[i].first != l.m_endpoints[i].first) if (m_endpoints[i].first != l.m_endpoints[i].first)
return false; return false;
@ -229,7 +229,7 @@ public:
private: private:
void m_sortEndpoints() noexcept; void m_sortEndpoints() noexcept;
int64_t m_ts; int64_t m_revision;
Fingerprint m_signer; Fingerprint m_signer;
Vector< std::pair< Endpoint, SharedPtr< const EndpointAttributes > > > m_endpoints; Vector< std::pair< Endpoint, SharedPtr< const EndpointAttributes > > > m_endpoints;
FCV< uint8_t, ZT_SIGNATURE_BUFFER_SIZE > m_signature; FCV< uint8_t, ZT_SIGNATURE_BUFFER_SIZE > m_signature;

View file

@ -28,7 +28,7 @@ Member::Member() :
{ {
} }
void Member::pushCredentials(const RuntimeEnvironment *RR, void *tPtr, const int64_t now, const SharedPtr< Peer > &to, const NetworkConfig &nconf) void Member::pushCredentials(const RuntimeEnvironment *RR, CallContext &cc, const SharedPtr< Peer > &to, const NetworkConfig &nconf)
{ {
if (!nconf.com) // sanity check if (!nconf.com) // sanity check
return; return;
@ -112,7 +112,7 @@ void Member::pushCredentials(const RuntimeEnvironment *RR, void *tPtr, const int
} }
#endif #endif
m_lastPushedCredentials = now; m_lastPushedCredentials = cc.ticks;
} }
void Member::clean(const NetworkConfig &nconf) void Member::clean(const NetworkConfig &nconf)
@ -122,31 +122,31 @@ void Member::clean(const NetworkConfig &nconf)
m_cleanCredImpl< OwnershipCredential >(nconf, m_remoteCoos); m_cleanCredImpl< OwnershipCredential >(nconf, m_remoteCoos);
} }
Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, void *tPtr, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const MembershipCredential &com) Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const MembershipCredential &com)
{ {
const int64_t newts = com.timestamp(); const int64_t newts = com.timestamp();
if (newts <= m_comRevocationThreshold) { if (newts <= m_comRevocationThreshold) {
RR->t->credentialRejected(tPtr, 0xd9992121, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED); RR->t->credentialRejected(cc, 0xd9992121, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED);
return ADD_REJECTED; return ADD_REJECTED;
} }
const int64_t oldts = m_com.timestamp(); const int64_t oldts = m_com.timestamp();
if (newts < oldts) { if (newts < oldts) {
RR->t->credentialRejected(tPtr, 0xd9928192, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST); RR->t->credentialRejected(cc, 0xd9928192, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST);
return ADD_REJECTED; return ADD_REJECTED;
} }
if ((newts == oldts) && (m_com == com)) if ((newts == oldts) && (m_com == com))
return ADD_ACCEPTED_REDUNDANT; return ADD_ACCEPTED_REDUNDANT;
switch (com.verify(RR, tPtr)) { switch (com.verify(RR, cc)) {
default: default:
RR->t->credentialRejected(tPtr, 0x0f198241, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID); RR->t->credentialRejected(cc, 0x0f198241, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
return Member::ADD_REJECTED; return Member::ADD_REJECTED;
case Credential::VERIFY_OK: case Credential::VERIFY_OK:
m_com = com; m_com = com;
return ADD_ACCEPTED_NEW; return ADD_ACCEPTED_NEW;
case Credential::VERIFY_BAD_SIGNATURE: case Credential::VERIFY_BAD_SIGNATURE:
RR->t->credentialRejected(tPtr, 0xbaf0aaaa, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_SIGNATURE_VERIFICATION_FAILED); RR->t->credentialRejected(cc, 0xbaf0aaaa, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_SIGNATURE_VERIFICATION_FAILED);
return ADD_REJECTED; return ADD_REJECTED;
case Credential::VERIFY_NEED_IDENTITY: case Credential::VERIFY_NEED_IDENTITY:
return ADD_DEFERRED_FOR_WHOIS; return ADD_DEFERRED_FOR_WHOIS;
@ -159,15 +159,15 @@ static ZT_INLINE Member::AddCredentialResult _addCredImpl(
Map< uint32_t, C > &remoteCreds, Map< uint32_t, C > &remoteCreds,
const Map< uint64_t, int64_t > &revocations, const Map< uint64_t, int64_t > &revocations,
const RuntimeEnvironment *const RR, const RuntimeEnvironment *const RR,
void *const tPtr, CallContext &cc,
const Identity &sourcePeerIdentity, const Identity &sourcePeerIdentity,
const NetworkConfig &nconf, const NetworkConfig &nconf,
const C &cred) const C &cred)
{ {
typename Map< uint32_t, C >::const_iterator rc(remoteCreds.find(cred.id())); typename Map< uint32_t, C >::const_iterator rc(remoteCreds.find(cred.id()));
if (rc != remoteCreds.end()) { if (rc != remoteCreds.end()) {
if (rc->second.timestamp() > cred.timestamp()) { if (rc->second.revision() > cred.revision()) {
RR->t->credentialRejected(tPtr, 0x40000001, nconf.networkId, sourcePeerIdentity, cred.id(), cred.timestamp(), C::credentialType(), ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST); RR->t->credentialRejected(cc, 0x40000001, nconf.networkId, sourcePeerIdentity, cred.id(), cred.revision(), C::credentialType(), ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST);
return Member::ADD_REJECTED; return Member::ADD_REJECTED;
} }
if (rc->second == cred) if (rc->second == cred)
@ -175,14 +175,14 @@ static ZT_INLINE Member::AddCredentialResult _addCredImpl(
} }
typename Map< uint64_t, int64_t >::const_iterator rt(revocations.find(Member::credentialKey(C::credentialType(), cred.id()))); typename Map< uint64_t, int64_t >::const_iterator rt(revocations.find(Member::credentialKey(C::credentialType(), cred.id())));
if ((rt != revocations.end()) && (rt->second >= cred.timestamp())) { if ((rt != revocations.end()) && (rt->second >= cred.revision())) {
RR->t->credentialRejected(tPtr, 0x24248124, nconf.networkId, sourcePeerIdentity, cred.id(), cred.timestamp(), C::credentialType(), ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED); RR->t->credentialRejected(cc, 0x24248124, nconf.networkId, sourcePeerIdentity, cred.id(), cred.revision(), C::credentialType(), ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED);
return Member::ADD_REJECTED; return Member::ADD_REJECTED;
} }
switch (cred.verify(RR, tPtr)) { switch (cred.verify(RR, cc)) {
default: default:
RR->t->credentialRejected(tPtr, 0x01feba012, nconf.networkId, sourcePeerIdentity, cred.id(), cred.timestamp(), C::credentialType(), ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID); RR->t->credentialRejected(cc, 0x01feba012, nconf.networkId, sourcePeerIdentity, cred.id(), cred.revision(), C::credentialType(), ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
return Member::ADD_REJECTED; return Member::ADD_REJECTED;
case 0: case 0:
if (rc == remoteCreds.end()) if (rc == remoteCreds.end())
@ -193,21 +193,21 @@ static ZT_INLINE Member::AddCredentialResult _addCredImpl(
} }
} }
Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, void *tPtr, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const TagCredential &tag) Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const TagCredential &tag)
{ return _addCredImpl< TagCredential >(m_remoteTags, m_revocations, RR, tPtr, sourcePeerIdentity, nconf, tag); } { return _addCredImpl< TagCredential >(m_remoteTags, m_revocations, RR, cc, sourcePeerIdentity, nconf, tag); }
Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, void *tPtr, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const CapabilityCredential &cap) Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const CapabilityCredential &cap)
{ return _addCredImpl< CapabilityCredential >(m_remoteCaps, m_revocations, RR, tPtr, sourcePeerIdentity, nconf, cap); } { return _addCredImpl< CapabilityCredential >(m_remoteCaps, m_revocations, RR, cc, sourcePeerIdentity, nconf, cap); }
Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, void *tPtr, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const OwnershipCredential &coo) Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const OwnershipCredential &coo)
{ return _addCredImpl< OwnershipCredential >(m_remoteCoos, m_revocations, RR, tPtr, sourcePeerIdentity, nconf, coo); } { return _addCredImpl< OwnershipCredential >(m_remoteCoos, m_revocations, RR, cc, sourcePeerIdentity, nconf, coo); }
Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, void *tPtr, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const RevocationCredential &rev) Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const RevocationCredential &rev)
{ {
int64_t *rt; int64_t *rt;
switch (rev.verify(RR, tPtr)) { switch (rev.verify(RR, cc)) {
default: default:
RR->t->credentialRejected(tPtr, 0x938fffff, nconf.networkId, sourcePeerIdentity, rev.id(), 0, ZT_CREDENTIAL_TYPE_REVOCATION, ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID); RR->t->credentialRejected(cc, 0x938fffff, nconf.networkId, sourcePeerIdentity, rev.id(), 0, ZT_CREDENTIAL_TYPE_REVOCATION, ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
return ADD_REJECTED; return ADD_REJECTED;
case 0: { case 0: {
const ZT_CredentialType ct = rev.typeBeingRevoked(); const ZT_CredentialType ct = rev.typeBeingRevoked();
@ -229,7 +229,7 @@ Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR,
} }
return ADD_ACCEPTED_REDUNDANT; return ADD_ACCEPTED_REDUNDANT;
default: default:
RR->t->credentialRejected(tPtr, 0x0bbbb1a4, nconf.networkId, sourcePeerIdentity, rev.id(), 0, ZT_CREDENTIAL_TYPE_REVOCATION, ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID); RR->t->credentialRejected(cc, 0x0bbbb1a4, nconf.networkId, sourcePeerIdentity, rev.id(), 0, ZT_CREDENTIAL_TYPE_REVOCATION, ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
return ADD_REJECTED; return ADD_REJECTED;
} }
} }

View file

@ -26,6 +26,7 @@
namespace ZeroTier { namespace ZeroTier {
class RuntimeEnvironment; class RuntimeEnvironment;
class Network; class Network;
/** /**
@ -51,18 +52,16 @@ public:
/** /**
* Send COM and other credentials to this peer * Send COM and other credentials to this peer
* *
* @param RR Runtime environment
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param now Current time
* @param to Peer identity * @param to Peer identity
* @param nconf My network config * @param nconf My network config
*/ */
void pushCredentials(const RuntimeEnvironment *RR,void *tPtr,int64_t now,const SharedPtr<Peer> &to,const NetworkConfig &nconf); void pushCredentials(const RuntimeEnvironment *RR, CallContext &cc, const SharedPtr< Peer > &to, const NetworkConfig &nconf);
/** /**
* @return Time we last pushed credentials to this member * @return Time we last pushed credentials to this member
*/ */
ZT_INLINE int64_t lastPushedCredentials() const noexcept { return m_lastPushedCredentials; } ZT_INLINE int64_t lastPushedCredentials() const noexcept
{ return m_lastPushedCredentials; }
/** /**
* Get a remote member's tag (if we have it) * Get a remote member's tag (if we have it)
@ -74,7 +73,7 @@ public:
ZT_INLINE const TagCredential *getTag(const NetworkConfig &nconf, const uint32_t id) const noexcept ZT_INLINE const TagCredential *getTag(const NetworkConfig &nconf, const uint32_t id) const noexcept
{ {
Map< uint32_t, TagCredential >::const_iterator t(m_remoteTags.find(id)); Map< uint32_t, TagCredential >::const_iterator t(m_remoteTags.find(id));
return (((t != m_remoteTags.end())&&(m_isCredentialTimestampValid(nconf, t->second))) ? &(t->second) : (TagCredential *)0); return (((t != m_remoteTags.end()) && (m_isCredentialTimestampValid(nconf, t->second))) ? &(t->second) : (TagCredential *)0);
} }
/** /**
@ -87,7 +86,8 @@ public:
/** /**
* Generates a key for internal use in indexing credentials by type and credential ID * Generates a key for internal use in indexing credentials by type and credential ID
*/ */
static ZT_INLINE uint64_t credentialKey(const ZT_CredentialType &t,const uint32_t i) noexcept { return (((uint64_t)t << 32U) | (uint64_t)i); } static ZT_INLINE uint64_t credentialKey(const ZT_CredentialType &t, const uint32_t i) noexcept
{ return (((uint64_t)t << 32U) | (uint64_t)i); }
/** /**
* Check whether the peer represented by this Membership owns a given address * Check whether the peer represented by this Membership owns a given address
@ -97,12 +97,12 @@ public:
* @param r Resource to check * @param r Resource to check
* @return True if this peer has a certificate of ownership for the given resource * @return True if this peer has a certificate of ownership for the given resource
*/ */
template<typename T> template< typename T >
ZT_INLINE bool peerOwnsAddress(const NetworkConfig &nconf, const T &r) const noexcept ZT_INLINE bool peerOwnsAddress(const NetworkConfig &nconf, const T &r) const noexcept
{ {
if (m_isUnspoofableAddress(nconf, r)) if (m_isUnspoofableAddress(nconf, r))
return true; return true;
for(Map< uint32_t,OwnershipCredential >::const_iterator i(m_remoteCoos.begin()); i != m_remoteCoos.end(); ++i) { for (Map< uint32_t, OwnershipCredential >::const_iterator i(m_remoteCoos.begin()); i != m_remoteCoos.end(); ++i) {
if (m_isCredentialTimestampValid(nconf, i->second) && (i->second.owns(r))) if (m_isCredentialTimestampValid(nconf, i->second) && (i->second.owns(r)))
return true; return true;
} }
@ -145,36 +145,38 @@ public:
return false; return false;
} }
AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const MembershipCredential &com); AddCredentialResult addCredential(const RuntimeEnvironment *RR, CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const MembershipCredential &com);
AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const TagCredential &tag); AddCredentialResult addCredential(const RuntimeEnvironment *RR, CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const TagCredential &tag);
AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const CapabilityCredential &cap); AddCredentialResult addCredential(const RuntimeEnvironment *RR, CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const CapabilityCredential &cap);
AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const OwnershipCredential &coo); AddCredentialResult addCredential(const RuntimeEnvironment *RR, CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const OwnershipCredential &coo);
AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const RevocationCredential &rev); AddCredentialResult addCredential(const RuntimeEnvironment *RR, CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const RevocationCredential &rev);
private: private:
// This returns true if a resource is an IPv6 NDP-emulated address. These embed the ZT // This returns true if a resource is an IPv6 NDP-emulated address. These embed the ZT
// address of the peer and therefore cannot be spoofed, causing peerOwnsAddress() to // address of the peer and therefore cannot be spoofed, causing peerOwnsAddress() to
// always return true for them. A certificate is not required for these. // always return true for them. A certificate is not required for these.
ZT_INLINE bool m_isUnspoofableAddress(const NetworkConfig &nconf, const MAC &m) const noexcept { return false; } ZT_INLINE bool m_isUnspoofableAddress(const NetworkConfig &nconf, const MAC &m) const noexcept
{ return false; }
bool m_isUnspoofableAddress(const NetworkConfig &nconf, const InetAddress &ip) const noexcept; bool m_isUnspoofableAddress(const NetworkConfig &nconf, const InetAddress &ip) const noexcept;
// This compares the remote credential's timestamp to the timestamp in our network config // This compares the remote credential's timestamp to the timestamp in our network config
// plus or minus the permitted maximum timestamp delta. // plus or minus the permitted maximum timestamp delta.
template<typename C> template< typename C >
ZT_INLINE bool m_isCredentialTimestampValid(const NetworkConfig &nconf, const C &remoteCredential) const noexcept ZT_INLINE bool m_isCredentialTimestampValid(const NetworkConfig &nconf, const C &remoteCredential) const noexcept
{ {
const int64_t ts = remoteCredential.timestamp(); const int64_t ts = remoteCredential.revision();
if (((ts >= nconf.timestamp) ? (ts - nconf.timestamp) : (nconf.timestamp - ts)) <= nconf.credentialTimeMaxDelta) { if (((ts >= nconf.timestamp) ? (ts - nconf.timestamp) : (nconf.timestamp - ts)) <= nconf.credentialTimeMaxDelta) {
Map< uint64_t, int64_t >::const_iterator threshold(m_revocations.find(credentialKey(C::credentialType(), remoteCredential.id()))); Map< uint64_t, int64_t >::const_iterator threshold(m_revocations.find(credentialKey(C::credentialType(), remoteCredential.id())));
return ((threshold == m_revocations.end())||(ts > threshold->second)); return ((threshold == m_revocations.end()) || (ts > threshold->second));
} }
return false; return false;
} }
template<typename C> template< typename C >
ZT_INLINE void m_cleanCredImpl(const NetworkConfig &nconf, Map<uint32_t,C> &remoteCreds) ZT_INLINE void m_cleanCredImpl(const NetworkConfig &nconf, Map< uint32_t, C > &remoteCreds)
{ {
for(typename Map<uint32_t,C>::iterator i(remoteCreds.begin());i!=remoteCreds.end();) { for (typename Map< uint32_t, C >::iterator i(remoteCreds.begin()); i != remoteCreds.end();) {
if (!m_isCredentialTimestampValid(nconf, i->second)) if (!m_isCredentialTimestampValid(nconf, i->second))
remoteCreds.erase(i++); remoteCreds.erase(i++);
else ++i; else ++i;
@ -188,24 +190,24 @@ private:
int64_t m_lastPushedCredentials; int64_t m_lastPushedCredentials;
// COM timestamps at which we last agreed-- used to memo-ize agreement and avoid having to recompute constantly. // COM timestamps at which we last agreed-- used to memo-ize agreement and avoid having to recompute constantly.
int64_t m_comAgreementLocalTimestamp,m_comAgreementRemoteTimestamp; int64_t m_comAgreementLocalTimestamp, m_comAgreementRemoteTimestamp;
// Remote member's latest network COM // Remote member's latest network COM
MembershipCredential m_com; MembershipCredential m_com;
// Revocations by credentialKey() // Revocations by credentialKey()
Map<uint64_t,int64_t> m_revocations; Map< uint64_t, int64_t > m_revocations;
// Remote credentials that we have received from this member (and that are valid) // Remote credentials that we have received from this member (and that are valid)
Map<uint32_t,TagCredential> m_remoteTags; Map< uint32_t, TagCredential > m_remoteTags;
Map<uint32_t,CapabilityCredential> m_remoteCaps; Map< uint32_t, CapabilityCredential > m_remoteCaps;
Map<uint32_t,OwnershipCredential> m_remoteCoos; Map< uint32_t, OwnershipCredential > m_remoteCoos;
public: public:
class CapabilityIterator class CapabilityIterator
{ {
public: public:
ZT_INLINE CapabilityIterator(Member &m, const NetworkConfig &nconf) noexcept : ZT_INLINE CapabilityIterator(Member &m, const NetworkConfig &nconf) noexcept:
m_hti(m.m_remoteCaps.begin()), m_hti(m.m_remoteCaps.begin()),
m_parent(m), m_parent(m),
m_nconf(nconf) m_nconf(nconf)
@ -215,7 +217,7 @@ public:
ZT_INLINE CapabilityCredential *next() noexcept ZT_INLINE CapabilityCredential *next() noexcept
{ {
while (m_hti != m_parent.m_remoteCaps.end()) { while (m_hti != m_parent.m_remoteCaps.end()) {
Map< uint32_t,CapabilityCredential >::iterator i(m_hti++); Map< uint32_t, CapabilityCredential >::iterator i(m_hti++);
if (m_parent.m_isCredentialTimestampValid(m_nconf, i->second)) if (m_parent.m_isCredentialTimestampValid(m_nconf, i->second))
return &(i->second); return &(i->second);
} }
@ -223,7 +225,7 @@ public:
} }
private: private:
Map< uint32_t,CapabilityCredential >::iterator m_hti; Map< uint32_t, CapabilityCredential >::iterator m_hti;
Member &m_parent; Member &m_parent;
const NetworkConfig &m_nconf; const NetworkConfig &m_nconf;
}; };

View file

@ -133,6 +133,9 @@ public:
*/ */
ZT_INLINE int64_t timestamp() const noexcept { return m_timestamp; } ZT_INLINE int64_t timestamp() const noexcept { return m_timestamp; }
ZT_INLINE int64_t revision() const noexcept
{ return m_timestamp; }
/** /**
* @return Maximum allowed difference between timestamps * @return Maximum allowed difference between timestamps
*/ */
@ -177,7 +180,7 @@ public:
* @param RR Runtime environment for looking up peers * @param RR Runtime environment for looking up peers
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
*/ */
ZT_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return s_verify(RR, tPtr, *this); } ZT_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR, CallContext &cc) const { return s_verify(RR, cc, *this); }
// NOTE: right now we use v1 serialization format which works with both ZeroTier 1.x and 2.x. V2 format // NOTE: right now we use v1 serialization format which works with both ZeroTier 1.x and 2.x. V2 format
// will be switched on once 1.x is pretty much dead and out of support. // will be switched on once 1.x is pretty much dead and out of support.

View file

@ -43,28 +43,25 @@ public:
* *
* @param now Start time * @param now Start time
*/ */
ZT_INLINE Meter() noexcept : ZT_INLINE Meter() noexcept
m_counts(),
m_totalExclCounts(0),
m_bucket(0)
{} {}
/** /**
* Add a measurement * Add a measurement
* *
* @param now Current time * @param ts Timestamp for measurement
* @param count Count of items (usually bytes) * @param count Count of items (usually bytes)
*/ */
ZT_INLINE void log(const int64_t now, uint64_t count) noexcept ZT_INLINE void log(const int64_t ts, const uint64_t count) noexcept
{ {
// We log by choosing a log bucket based on the current time in units modulo // We log by choosing a log bucket based on the current time in units modulo
// the log size and then if it's a new bucket setting it or otherwise adding // the log size and then if it's a new bucket setting it or otherwise adding
// to it. // to it.
const unsigned long bucket = ((unsigned long)(now / TUNIT)) % LSIZE; const unsigned long bucket = ((unsigned long)(ts / TUNIT)) % LSIZE;
if (m_bucket.exchange(bucket) != bucket) { if (m_bucket.exchange(bucket, std::memory_order_relaxed) != bucket) {
m_totalExclCounts.fetch_add(m_counts[bucket].exchange(count)); m_totalExclCounts.fetch_add(m_counts[bucket].exchange(count, std::memory_order_relaxed), std::memory_order_relaxed);
} else { } else {
m_counts[bucket].fetch_add(count); m_counts[bucket].fetch_add(count, std::memory_order_relaxed);
} }
} }
@ -79,9 +76,9 @@ public:
{ {
total = 0; total = 0;
for (unsigned long i = 0;i < LSIZE;++i) for (unsigned long i = 0;i < LSIZE;++i)
total += m_counts[i].load(); total += m_counts[i].load(std::memory_order_relaxed);
rate = (double) total / (double) LSIZE; rate = (double) total / (double) LSIZE;
total += m_totalExclCounts.load(); total += m_totalExclCounts.load(std::memory_order_relaxed);
} }
private: private:

View file

@ -538,7 +538,7 @@ _doZtFilterResult _doZtFilter(
const ZeroTier::MulticastGroup Network::BROADCAST(ZeroTier::MAC(0xffffffffffffULL), 0); const ZeroTier::MulticastGroup Network::BROADCAST(ZeroTier::MAC(0xffffffffffffULL), 0);
Network::Network(const RuntimeEnvironment *renv, void *tPtr, uint64_t nwid, const Fingerprint &controllerFingerprint, void *uptr, const NetworkConfig *nconf) : Network::Network(const RuntimeEnvironment *renv, CallContext &cc, uint64_t nwid, const Fingerprint &controllerFingerprint, void *uptr, const NetworkConfig *nconf) :
RR(renv), RR(renv),
m_uPtr(uptr), m_uPtr(uptr),
m_id(nwid), m_id(nwid),
@ -552,7 +552,7 @@ Network::Network(const RuntimeEnvironment *renv, void *tPtr, uint64_t nwid, cons
m_controllerFingerprint = controllerFingerprint; m_controllerFingerprint = controllerFingerprint;
if (nconf) { if (nconf) {
this->setConfiguration(tPtr, *nconf, false); this->setConfiguration(cc, *nconf, false);
m_lastConfigUpdate = 0; // still want to re-request since it's likely outdated m_lastConfigUpdate = 0; // still want to re-request since it's likely outdated
} else { } else {
uint64_t tmp[2]; uint64_t tmp[2];
@ -562,14 +562,14 @@ Network::Network(const RuntimeEnvironment *renv, void *tPtr, uint64_t nwid, cons
bool got = false; bool got = false;
try { try {
Dictionary dict; Dictionary dict;
Vector< uint8_t > nconfData(RR->store->get(tPtr, ZT_STATE_OBJECT_NETWORK_CONFIG, tmp, 1)); Vector< uint8_t > nconfData(RR->store->get(cc, ZT_STATE_OBJECT_NETWORK_CONFIG, tmp, 1));
if (nconfData.size() > 2) { if (nconfData.size() > 2) {
nconfData.push_back(0); nconfData.push_back(0);
if (dict.decode(nconfData.data(), (unsigned int)nconfData.size())) { if (dict.decode(nconfData.data(), (unsigned int)nconfData.size())) {
try { try {
ScopedPtr< NetworkConfig > nconf2(new NetworkConfig()); ScopedPtr< NetworkConfig > nconf2(new NetworkConfig());
if (nconf2->fromDictionary(dict)) { if (nconf2->fromDictionary(dict)) {
this->setConfiguration(tPtr, *nconf2, false); this->setConfiguration(cc, *nconf2, false);
m_lastConfigUpdate = 0; // still want to re-request an update since it's likely outdated m_lastConfigUpdate = 0; // still want to re-request an update since it's likely outdated
got = true; got = true;
} }
@ -579,13 +579,13 @@ Network::Network(const RuntimeEnvironment *renv, void *tPtr, uint64_t nwid, cons
} catch (...) {} } catch (...) {}
if (!got) if (!got)
RR->store->put(tPtr, ZT_STATE_OBJECT_NETWORK_CONFIG, tmp, 1, "\n", 1); RR->store->put(cc, ZT_STATE_OBJECT_NETWORK_CONFIG, tmp, 1, "\n", 1);
} }
if (!m_portInitialized) { if (!m_portInitialized) {
ZT_VirtualNetworkConfig ctmp; ZT_VirtualNetworkConfig ctmp;
m_externalConfig(&ctmp); m_externalConfig(&ctmp);
RR->node->configureVirtualNetworkPort(tPtr, m_id, &m_uPtr, ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP, &ctmp); RR->cb.virtualNetworkConfigFunction(reinterpret_cast<ZT_Node *>(RR->node), RR->uPtr, cc.tPtr, m_id, &m_uPtr, ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP, &ctmp);
m_portInitialized = true; m_portInitialized = true;
} }
} }
@ -604,12 +604,12 @@ Network::~Network()
// This is done in Node::leave() so we can pass tPtr properly // This is done in Node::leave() so we can pass tPtr properly
//RR->node->configureVirtualNetworkPort((void *)0,_id,&_uPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY,&ctmp); //RR->node->configureVirtualNetworkPort((void *)0,_id,&_uPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY,&ctmp);
} else { } else {
RR->node->configureVirtualNetworkPort(nullptr, m_id, &m_uPtr, ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN, &ctmp); RR->cb.virtualNetworkConfigFunction(reinterpret_cast<ZT_Node *>(RR->node), RR->uPtr, nullptr, m_id, &m_uPtr, ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN, &ctmp);
} }
} }
bool Network::filterOutgoingPacket( bool Network::filterOutgoingPacket(
void *tPtr, CallContext &cc,
const bool noTee, const bool noTee,
const Address &ztSource, const Address &ztSource,
const Address &ztDest, const Address &ztDest,
@ -625,7 +625,7 @@ bool Network::filterOutgoingPacket(
Address ztFinalDest(ztDest); Address ztFinalDest(ztDest);
int localCapabilityIndex = -1; int localCapabilityIndex = -1;
int accept = 0; int accept = 0;
Address cc; Address ccNodeAddress;
unsigned int ccLength = 0; unsigned int ccLength = 0;
bool ccWatch = false; bool ccWatch = false;
@ -640,7 +640,7 @@ bool Network::filterOutgoingPacket(
membership = nullptr; membership = nullptr;
} }
switch (_doZtFilter(RR, rrl, m_config, membership, false, ztSource, ztFinalDest, macSource, macDest, frameData, frameLen, etherType, vlanId, m_config.rules, m_config.ruleCount, cc, ccLength, ccWatch, qosBucket)) { switch (_doZtFilter(RR, rrl, m_config, membership, false, ztSource, ztFinalDest, macSource, macDest, frameData, frameLen, etherType, vlanId, m_config.rules, m_config.ruleCount, ccNodeAddress, ccLength, ccWatch, qosBucket)) {
case DOZTFILTER_NO_MATCH: { case DOZTFILTER_NO_MATCH: {
for (unsigned int c = 0; c < m_config.capabilityCount; ++c) { for (unsigned int c = 0; c < m_config.capabilityCount; ++c) {
@ -683,7 +683,7 @@ bool Network::filterOutgoingPacket(
break; break;
case DOZTFILTER_DROP: case DOZTFILTER_DROP:
RR->t->networkFilter(tPtr, 0xadea5a2a, m_id, rrl.l, nullptr, 0, 0, ztSource, ztDest, macSource, macDest, (uint16_t)frameLen, frameData, (uint16_t)etherType, (uint16_t)vlanId, noTee, false, 0); RR->t->networkFilter(cc, 0xadea5a2a, m_id, rrl.l, nullptr, 0, 0, ztSource, ztDest, macSource, macDest, (uint16_t)frameLen, frameData, (uint16_t)etherType, (uint16_t)vlanId, noTee, false, 0);
return false; return false;
case DOZTFILTER_REDIRECT: // interpreted as ACCEPT but ztFinalDest will have been changed in _doZtFilter() case DOZTFILTER_REDIRECT: // interpreted as ACCEPT but ztFinalDest will have been changed in _doZtFilter()
@ -697,7 +697,7 @@ bool Network::filterOutgoingPacket(
} }
if (accept != 0) { if (accept != 0) {
if ((!noTee) && (cc)) { if ((!noTee) && (ccNodeAddress)) {
// TODO // TODO
/* /*
Packet outp(cc,RR->identity.address(),Packet::VERB_EXT_FRAME); Packet outp(cc,RR->identity.address(),Packet::VERB_EXT_FRAME);
@ -733,16 +733,16 @@ bool Network::filterOutgoingPacket(
if (localCapabilityIndex >= 0) { if (localCapabilityIndex >= 0) {
const CapabilityCredential &cap = m_config.capabilities[localCapabilityIndex]; const CapabilityCredential &cap = m_config.capabilities[localCapabilityIndex];
RR->t->networkFilter(tPtr, 0x56ff1a93, m_id, rrl.l, crrl.l, cap.id(), cap.timestamp(), ztSource, ztDest, macSource, macDest, (uint16_t)frameLen, frameData, (uint16_t)etherType, (uint16_t)vlanId, noTee, false, accept); RR->t->networkFilter(cc, 0x56ff1a93, m_id, rrl.l, crrl.l, cap.id(), cap.timestamp(), ztSource, ztDest, macSource, macDest, (uint16_t)frameLen, frameData, (uint16_t)etherType, (uint16_t)vlanId, noTee, false, accept);
} else { } else {
RR->t->networkFilter(tPtr, 0x112fbbab, m_id, rrl.l, nullptr, 0, 0, ztSource, ztDest, macSource, macDest, (uint16_t)frameLen, frameData, (uint16_t)etherType, (uint16_t)vlanId, noTee, false, accept); RR->t->networkFilter(cc, 0x112fbbab, m_id, rrl.l, nullptr, 0, 0, ztSource, ztDest, macSource, macDest, (uint16_t)frameLen, frameData, (uint16_t)etherType, (uint16_t)vlanId, noTee, false, accept);
} }
return (accept != 0); return (accept != 0);
} }
int Network::filterIncomingPacket( int Network::filterIncomingPacket(
void *tPtr, CallContext &cc,
const SharedPtr< Peer > &sourcePeer, const SharedPtr< Peer > &sourcePeer,
const Address &ztDest, const Address &ztDest,
const MAC &macSource, const MAC &macSource,
@ -755,7 +755,7 @@ int Network::filterIncomingPacket(
Address ztFinalDest(ztDest); Address ztFinalDest(ztDest);
Trace::RuleResultLog rrl, crrl; Trace::RuleResultLog rrl, crrl;
int accept = 0; int accept = 0;
Address cc; Address ccNodeAddress;
unsigned int ccLength = 0; unsigned int ccLength = 0;
bool ccWatch = false; bool ccWatch = false;
const CapabilityCredential *c = nullptr; const CapabilityCredential *c = nullptr;
@ -767,7 +767,7 @@ int Network::filterIncomingPacket(
Member &membership = m_memberships[sourcePeer->address()]; Member &membership = m_memberships[sourcePeer->address()];
switch (_doZtFilter(RR, rrl, m_config, &membership, true, sourcePeer->address(), ztFinalDest, macSource, macDest, frameData, frameLen, etherType, vlanId, m_config.rules, m_config.ruleCount, cc, ccLength, ccWatch, qosBucket)) { switch (_doZtFilter(RR, rrl, m_config, &membership, true, sourcePeer->address(), ztFinalDest, macSource, macDest, frameData, frameLen, etherType, vlanId, m_config.rules, m_config.ruleCount, ccNodeAddress, ccLength, ccWatch, qosBucket)) {
case DOZTFILTER_NO_MATCH: { case DOZTFILTER_NO_MATCH: {
Member::CapabilityIterator mci(membership, m_config); Member::CapabilityIterator mci(membership, m_config);
@ -825,7 +825,7 @@ int Network::filterIncomingPacket(
} }
if (accept) { if (accept) {
if (cc) { if (ccNodeAddress) {
// TODO // TODO
/* /*
Packet outp(cc,RR->identity.address(),Packet::VERB_EXT_FRAME); Packet outp(cc,RR->identity.address(),Packet::VERB_EXT_FRAME);
@ -865,13 +865,13 @@ int Network::filterIncomingPacket(
return accept; return accept;
} }
void Network::multicastSubscribe(void *tPtr, const MulticastGroup &mg) void Network::multicastSubscribe(CallContext &cc, const MulticastGroup &mg)
{ {
Mutex::Lock l(m_myMulticastGroups_l); Mutex::Lock l(m_myMulticastGroups_l);
if (!std::binary_search(m_myMulticastGroups.begin(), m_myMulticastGroups.end(), mg)) { if (!std::binary_search(m_myMulticastGroups.begin(), m_myMulticastGroups.end(), mg)) {
m_myMulticastGroups.insert(std::upper_bound(m_myMulticastGroups.begin(), m_myMulticastGroups.end(), mg), mg); m_myMulticastGroups.insert(std::upper_bound(m_myMulticastGroups.begin(), m_myMulticastGroups.end(), mg), mg);
Mutex::Lock l2(m_memberships_l); Mutex::Lock l2(m_memberships_l);
m_announceMulticastGroups(tPtr, true); m_announceMulticastGroups(cc.tPtr, true);
} }
} }
@ -883,7 +883,7 @@ void Network::multicastUnsubscribe(const MulticastGroup &mg)
m_myMulticastGroups.erase(i); m_myMulticastGroups.erase(i);
} }
uint64_t Network::handleConfigChunk(void *tPtr, uint64_t packetId, const SharedPtr< Peer > &source, const Buf &chunk, int ptr, int size) uint64_t Network::handleConfigChunk(CallContext &cc, uint64_t packetId, const SharedPtr< Peer > &source, const Buf &chunk, int ptr, int size)
{ {
// If the controller's full fingerprint is known or was explicitly specified on join(), // If the controller's full fingerprint is known or was explicitly specified on join(),
// require that the controller's identity match. Otherwise learn it. // require that the controller's identity match. Otherwise learn it.
@ -1027,7 +1027,7 @@ uint64_t Network::handleConfigChunk(void *tPtr, uint64_t packetId, const SharedP
#endif #endif
} }
int Network::setConfiguration(void *tPtr, const NetworkConfig &nconf, bool saveToDisk) int Network::setConfiguration(CallContext &cc, const NetworkConfig &nconf, bool saveToDisk)
{ {
if (m_destroyed) if (m_destroyed)
return 0; return 0;
@ -1048,7 +1048,7 @@ int Network::setConfiguration(void *tPtr, const NetworkConfig &nconf, bool saveT
Mutex::Lock l1(m_config_l); Mutex::Lock l1(m_config_l);
m_config = nconf; m_config = nconf;
m_lastConfigUpdate = RR->node->now(); m_lastConfigUpdate = cc.ticks;
_netconfFailure = NETCONF_FAILURE_NONE; _netconfFailure = NETCONF_FAILURE_NONE;
oldPortInitialized = m_portInitialized; oldPortInitialized = m_portInitialized;
@ -1057,7 +1057,7 @@ int Network::setConfiguration(void *tPtr, const NetworkConfig &nconf, bool saveT
m_externalConfig(&ctmp); m_externalConfig(&ctmp);
} }
RR->node->configureVirtualNetworkPort(tPtr, m_id, &m_uPtr, (oldPortInitialized) ? ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE : ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP, &ctmp); RR->cb.virtualNetworkConfigFunction(reinterpret_cast<ZT_Node *>(RR->node), RR->uPtr, cc.tPtr, nconf.networkId, &m_uPtr, (oldPortInitialized) ? ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE : ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP, &ctmp);
if (saveToDisk) { if (saveToDisk) {
try { try {
@ -1068,7 +1068,7 @@ int Network::setConfiguration(void *tPtr, const NetworkConfig &nconf, bool saveT
tmp[1] = 0; tmp[1] = 0;
Vector< uint8_t > d2; Vector< uint8_t > d2;
d.encode(d2); d.encode(d2);
RR->store->put(tPtr, ZT_STATE_OBJECT_NETWORK_CONFIG, tmp, 1, d2.data(), (unsigned int)d2.size()); RR->store->put(cc, ZT_STATE_OBJECT_NETWORK_CONFIG, tmp, 1, d2.data(), (unsigned int)d2.size());
} }
} catch (...) {} } catch (...) {}
} }
@ -1095,13 +1095,13 @@ bool Network::gate(void *tPtr, const SharedPtr< Peer > &peer) noexcept
return false; return false;
} }
void Network::doPeriodicTasks(void *tPtr, const int64_t now) void Network::doPeriodicTasks(CallContext &cc)
{ {
if (m_destroyed) if (m_destroyed)
return; return;
if ((now - m_lastConfigUpdate) >= ZT_NETWORK_AUTOCONF_DELAY) if ((cc.ticks - m_lastConfigUpdate) >= ZT_NETWORK_AUTOCONF_DELAY)
m_requestConfiguration(tPtr); m_requestConfiguration(cc);
{ {
Mutex::Lock l1(m_memberships_l); Mutex::Lock l1(m_memberships_l);
@ -1157,31 +1157,31 @@ void Network::learnBridgeRoute(const MAC &mac, const Address &addr)
} }
} }
Member::AddCredentialResult Network::addCredential(void *tPtr, const Identity &sourcePeerIdentity, const MembershipCredential &com) Member::AddCredentialResult Network::addCredential(CallContext &cc, const Identity &sourcePeerIdentity, const MembershipCredential &com)
{ {
if (com.networkId() != m_id) if (com.networkId() != m_id)
return Member::ADD_REJECTED; return Member::ADD_REJECTED;
Mutex::Lock _l(m_memberships_l); Mutex::Lock _l(m_memberships_l);
return m_memberships[com.issuedTo().address].addCredential(RR, tPtr, sourcePeerIdentity, m_config, com); return m_memberships[com.issuedTo().address].addCredential(RR, cc, sourcePeerIdentity, m_config, com);
} }
Member::AddCredentialResult Network::addCredential(void *tPtr, const Identity &sourcePeerIdentity, const CapabilityCredential &cap) Member::AddCredentialResult Network::addCredential(CallContext &cc, const Identity &sourcePeerIdentity, const CapabilityCredential &cap)
{ {
if (cap.networkId() != m_id) if (cap.networkId() != m_id)
return Member::ADD_REJECTED; return Member::ADD_REJECTED;
Mutex::Lock _l(m_memberships_l); Mutex::Lock _l(m_memberships_l);
return m_memberships[cap.issuedTo()].addCredential(RR, tPtr, sourcePeerIdentity, m_config, cap); return m_memberships[cap.issuedTo()].addCredential(RR, cc, sourcePeerIdentity, m_config, cap);
} }
Member::AddCredentialResult Network::addCredential(void *tPtr, const Identity &sourcePeerIdentity, const TagCredential &tag) Member::AddCredentialResult Network::addCredential(CallContext &cc, const Identity &sourcePeerIdentity, const TagCredential &tag)
{ {
if (tag.networkId() != m_id) if (tag.networkId() != m_id)
return Member::ADD_REJECTED; return Member::ADD_REJECTED;
Mutex::Lock _l(m_memberships_l); Mutex::Lock _l(m_memberships_l);
return m_memberships[tag.issuedTo()].addCredential(RR, tPtr, sourcePeerIdentity, m_config, tag); return m_memberships[tag.issuedTo()].addCredential(RR, cc, sourcePeerIdentity, m_config, tag);
} }
Member::AddCredentialResult Network::addCredential(void *tPtr, const Identity &sourcePeerIdentity, const RevocationCredential &rev) Member::AddCredentialResult Network::addCredential(CallContext &cc, const Identity &sourcePeerIdentity, const RevocationCredential &rev)
{ {
if (rev.networkId() != m_id) if (rev.networkId() != m_id)
return Member::ADD_REJECTED; return Member::ADD_REJECTED;
@ -1189,7 +1189,7 @@ Member::AddCredentialResult Network::addCredential(void *tPtr, const Identity &s
Mutex::Lock l1(m_memberships_l); Mutex::Lock l1(m_memberships_l);
Member &m = m_memberships[rev.target()]; Member &m = m_memberships[rev.target()];
const Member::AddCredentialResult result = m.addCredential(RR, tPtr, sourcePeerIdentity, m_config, rev); const Member::AddCredentialResult result = m.addCredential(RR, cc, sourcePeerIdentity, m_config, rev);
if ((result == Member::ADD_ACCEPTED_NEW) && (rev.fastPropagate())) { if ((result == Member::ADD_ACCEPTED_NEW) && (rev.fastPropagate())) {
// TODO // TODO
@ -1215,22 +1215,21 @@ Member::AddCredentialResult Network::addCredential(void *tPtr, const Identity &s
return result; return result;
} }
Member::AddCredentialResult Network::addCredential(void *tPtr, const Identity &sourcePeerIdentity, const OwnershipCredential &coo) Member::AddCredentialResult Network::addCredential(CallContext &cc, const Identity &sourcePeerIdentity, const OwnershipCredential &coo)
{ {
if (coo.networkId() != m_id) if (coo.networkId() != m_id)
return Member::ADD_REJECTED; return Member::ADD_REJECTED;
Mutex::Lock _l(m_memberships_l); Mutex::Lock _l(m_memberships_l);
return m_memberships[coo.issuedTo()].addCredential(RR, tPtr, sourcePeerIdentity, m_config, coo); return m_memberships[coo.issuedTo()].addCredential(RR, cc, sourcePeerIdentity, m_config, coo);
} }
void Network::pushCredentials(void *tPtr, const SharedPtr< Peer > &to, const int64_t now) void Network::pushCredentials(CallContext &cc, const SharedPtr< Peer > &to)
{ {
const int64_t tout = std::min(m_config.credentialTimeMaxDelta, m_config.com.timestampMaxDelta()); const int64_t tout = std::min(m_config.credentialTimeMaxDelta, m_config.com.timestampMaxDelta());
Mutex::Lock _l(m_memberships_l); Mutex::Lock _l(m_memberships_l);
Member &m = m_memberships[to->address()]; Member &m = m_memberships[to->address()];
if (((now - m.lastPushedCredentials()) + 5000) >= tout) { if (((cc.ticks - m.lastPushedCredentials()) + 5000) >= tout)
m.pushCredentials(RR, tPtr, now, to, m_config); m.pushCredentials(RR, cc, to, m_config);
}
} }
void Network::destroy() void Network::destroy()
@ -1248,7 +1247,7 @@ void Network::externalConfig(ZT_VirtualNetworkConfig *ec) const
m_externalConfig(ec); m_externalConfig(ec);
} }
void Network::m_requestConfiguration(void *tPtr) void Network::m_requestConfiguration(CallContext &cc)
{ {
if (m_destroyed) if (m_destroyed)
return; return;
@ -1261,7 +1260,7 @@ void Network::m_requestConfiguration(void *tPtr)
ScopedPtr< NetworkConfig > nconf(new NetworkConfig()); ScopedPtr< NetworkConfig > nconf(new NetworkConfig());
nconf->networkId = m_id; nconf->networkId = m_id;
nconf->timestamp = RR->node->now(); nconf->timestamp = (cc.clock < 0) ? cc.ticks : cc.clock;
nconf->credentialTimeMaxDelta = ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MAX_MAX_DELTA; nconf->credentialTimeMaxDelta = ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MAX_MAX_DELTA;
nconf->revision = 1; nconf->revision = 1;
nconf->issuedTo = RR->identity.address(); nconf->issuedTo = RR->identity.address();
@ -1319,7 +1318,7 @@ void Network::m_requestConfiguration(void *tPtr)
Utils::hex((uint16_t)endPortRange, nconf->name + 11); Utils::hex((uint16_t)endPortRange, nconf->name + 11);
nconf->name[15] = (char)0; nconf->name[15] = (char)0;
this->setConfiguration(tPtr, *nconf, false); this->setConfiguration(cc, *nconf, false);
} else { } else {
this->setNotFound(); this->setNotFound();
} }
@ -1340,7 +1339,7 @@ void Network::m_requestConfiguration(void *tPtr)
ScopedPtr< NetworkConfig > nconf(new NetworkConfig()); ScopedPtr< NetworkConfig > nconf(new NetworkConfig());
nconf->networkId = m_id; nconf->networkId = m_id;
nconf->timestamp = RR->node->now(); nconf->timestamp = (cc.clock < 0) ? cc.ticks : cc.clock;
nconf->credentialTimeMaxDelta = ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MAX_MAX_DELTA; nconf->credentialTimeMaxDelta = ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MAX_MAX_DELTA;
nconf->revision = 1; nconf->revision = 1;
nconf->issuedTo = RR->identity.address(); nconf->issuedTo = RR->identity.address();
@ -1377,7 +1376,7 @@ void Network::m_requestConfiguration(void *tPtr)
nconf->name[nn++] = '0'; nconf->name[nn++] = '0';
nconf->name[nn] = (char)0; nconf->name[nn] = (char)0;
this->setConfiguration(tPtr, *nconf, false); this->setConfiguration(cc, *nconf, false);
} }
return; return;
} }
@ -1397,7 +1396,7 @@ void Network::m_requestConfiguration(void *tPtr)
rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_FLAGS, (uint64_t)0); rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_FLAGS, (uint64_t)0);
rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_RULES_ENGINE_REV, (uint64_t)ZT_RULES_ENGINE_REVISION); rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_RULES_ENGINE_REV, (uint64_t)ZT_RULES_ENGINE_REVISION);
RR->t->networkConfigRequestSent(tPtr, 0x335bb1a2, m_id); RR->t->networkConfigRequestSent(cc, 0x335bb1a2, m_id);
if (ctrl == RR->identity.address()) { if (ctrl == RR->identity.address()) {
if (RR->localNetworkController) { if (RR->localNetworkController) {

View file

@ -26,6 +26,7 @@
#include "NetworkConfig.hpp" #include "NetworkConfig.hpp"
#include "MembershipCredential.hpp" #include "MembershipCredential.hpp"
#include "Containers.hpp" #include "Containers.hpp"
#include "CallContext.hpp"
#define ZT_NETWORK_MAX_INCOMING_UPDATES 3 #define ZT_NETWORK_MAX_INCOMING_UPDATES 3
@ -60,14 +61,18 @@ public:
* Note that init() should be called immediately after the network is * Note that init() should be called immediately after the network is
* constructed to actually configure the port. * constructed to actually configure the port.
* *
* @param renv Runtime environment
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param nwid Network ID * @param nwid Network ID
* @param controllerFingerprint Initial controller fingerprint if non-NULL * @param controllerFingerprint Initial controller fingerprint if non-NULL
* @param uptr Arbitrary pointer used by externally-facing API (for user use) * @param uptr Arbitrary pointer used by externally-facing API (for user use)
* @param nconf Network config, if known * @param nconf Network config, if known
*/ */
Network(const RuntimeEnvironment *renv, void *tPtr, uint64_t nwid, const Fingerprint &controllerFingerprint, void *uptr, const NetworkConfig *nconf); Network(
const RuntimeEnvironment *renv,
CallContext &cc,
uint64_t nwid,
const Fingerprint &controllerFingerprint,
void *uptr,
const NetworkConfig *nconf);
~Network(); ~Network();
@ -103,7 +108,6 @@ public:
* such as TEE may be taken, and credentials may be pushed, so this is not * such as TEE may be taken, and credentials may be pushed, so this is not
* side-effect-free. It's basically step one in sending something over VL2. * side-effect-free. It's basically step one in sending something over VL2.
* *
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param noTee If true, do not TEE anything anywhere (for two-pass filtering as done with multicast and bridging) * @param noTee If true, do not TEE anything anywhere (for two-pass filtering as done with multicast and bridging)
* @param ztSource Source ZeroTier address * @param ztSource Source ZeroTier address
* @param ztDest Destination ZeroTier address * @param ztDest Destination ZeroTier address
@ -116,7 +120,7 @@ public:
* @return True if packet should be sent, false if dropped or redirected * @return True if packet should be sent, false if dropped or redirected
*/ */
bool filterOutgoingPacket( bool filterOutgoingPacket(
void *tPtr, CallContext &cc,
bool noTee, bool noTee,
const Address &ztSource, const Address &ztSource,
const Address &ztDest, const Address &ztDest,
@ -136,7 +140,6 @@ public:
* a match certain actions may be taken such as sending a copy of the packet * a match certain actions may be taken such as sending a copy of the packet
* to a TEE or REDIRECT target. * to a TEE or REDIRECT target.
* *
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param sourcePeer Source Peer * @param sourcePeer Source Peer
* @param ztDest Destination ZeroTier address * @param ztDest Destination ZeroTier address
* @param macSource Ethernet layer source address * @param macSource Ethernet layer source address
@ -148,7 +151,7 @@ public:
* @return 0 == drop, 1 == accept, 2 == accept even if bridged * @return 0 == drop, 1 == accept, 2 == accept even if bridged
*/ */
int filterIncomingPacket( int filterIncomingPacket(
void *tPtr, CallContext &cc,
const SharedPtr< Peer > &sourcePeer, const SharedPtr< Peer > &sourcePeer,
const Address &ztDest, const Address &ztDest,
const MAC &macSource, const MAC &macSource,
@ -158,30 +161,12 @@ public:
unsigned int etherType, unsigned int etherType,
unsigned int vlanId); unsigned int vlanId);
/**
* Check whether we are subscribed to a multicast group
*
* @param mg Multicast group
* @param includeBridgedGroups If true, also check groups we've learned via bridging
* @return True if this network endpoint / peer is a member
*/
ZT_INLINE bool subscribedToMulticastGroup(const MulticastGroup &mg, const bool includeBridgedGroups) const
{
Mutex::Lock l(m_myMulticastGroups_l);
if (std::binary_search(m_myMulticastGroups.begin(), m_myMulticastGroups.end(), mg))
return true;
else if (includeBridgedGroups)
return (m_multicastGroupsBehindMe.find(mg) != m_multicastGroupsBehindMe.end());
return false;
}
/** /**
* Subscribe to a multicast group * Subscribe to a multicast group
* *
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param mg New multicast group * @param mg New multicast group
*/ */
void multicastSubscribe(void *tPtr, const MulticastGroup &mg); void multicastSubscribe(CallContext &cc, const MulticastGroup &mg);
/** /**
* Unsubscribe from a multicast group * Unsubscribe from a multicast group
@ -198,7 +183,6 @@ public:
* bit of packet parsing code that also verifies chunks and replicates * bit of packet parsing code that also verifies chunks and replicates
* them (via rumor mill flooding) if their fast propagate flag is set. * them (via rumor mill flooding) if their fast propagate flag is set.
* *
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param packetId Packet ID or 0 if none (e.g. via cluster path) * @param packetId Packet ID or 0 if none (e.g. via cluster path)
* @param source Peer that actually sent this chunk (probably controller) * @param source Peer that actually sent this chunk (probably controller)
* @param chunk Buffer containing chunk * @param chunk Buffer containing chunk
@ -206,7 +190,13 @@ public:
* @param size Size of data in chunk buffer (total, not relative to ptr) * @param size Size of data in chunk buffer (total, not relative to ptr)
* @return Update ID if update was fully assembled and accepted or 0 otherwise * @return Update ID if update was fully assembled and accepted or 0 otherwise
*/ */
uint64_t handleConfigChunk(void *tPtr, uint64_t packetId, const SharedPtr< Peer > &source, const Buf &chunk, int ptr, int size); uint64_t handleConfigChunk(
CallContext &cc,
uint64_t packetId,
const SharedPtr< Peer > &source,
const Buf &chunk,
int ptr,
int size);
/** /**
* Set network configuration * Set network configuration
@ -215,12 +205,14 @@ public:
* and fully assembled, but it can also be called on Node startup when * and fully assembled, but it can also be called on Node startup when
* cached configurations are re-read from the data store. * cached configurations are re-read from the data store.
* *
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param nconf Network configuration * @param nconf Network configuration
* @param saveToDisk Save to disk? Used during loading, should usually be true otherwise. * @param saveToDisk Save to disk? Used during loading, should usually be true otherwise.
* @return 0 == bad, 1 == accepted but duplicate/unchanged, 2 == accepted and new * @return 0 == bad, 1 == accepted but duplicate/unchanged, 2 == accepted and new
*/ */
int setConfiguration(void *tPtr, const NetworkConfig &nconf, bool saveToDisk); int setConfiguration(
CallContext &cc,
const NetworkConfig &nconf,
bool saveToDisk);
/** /**
* Set netconf failure to 'access denied' -- called in IncomingPacket when controller reports this * Set netconf failure to 'access denied' -- called in IncomingPacket when controller reports this
@ -245,7 +237,7 @@ public:
/** /**
* Do periodic cleanup and housekeeping tasks * Do periodic cleanup and housekeeping tasks
*/ */
void doPeriodicTasks(void *tPtr, int64_t now); void doPeriodicTasks(CallContext &cc);
/** /**
* Find the node on this network that has this MAC behind it (if any) * Find the node on this network that has this MAC behind it (if any)
@ -275,7 +267,7 @@ public:
* @param mg Multicast group * @param mg Multicast group
* @param now Current time * @param now Current time
*/ */
ZT_INLINE void learnBridgedMulticastGroup(void *tPtr, const MulticastGroup &mg, int64_t now) ZT_INLINE void learnBridgedMulticastGroup(const MulticastGroup &mg, int64_t now)
{ {
Mutex::Lock l(m_myMulticastGroups_l); Mutex::Lock l(m_myMulticastGroups_l);
m_multicastGroupsBehindMe[mg] = now; m_multicastGroupsBehindMe[mg] = now;
@ -284,36 +276,34 @@ public:
/** /**
* Validate a credential and learn it if it passes certificate and other checks * Validate a credential and learn it if it passes certificate and other checks
*/ */
Member::AddCredentialResult addCredential(void *tPtr, const Identity &sourcePeerIdentity, const MembershipCredential &com); Member::AddCredentialResult addCredential(CallContext &cc, const Identity &sourcePeerIdentity, const MembershipCredential &com);
/** /**
* Validate a credential and learn it if it passes certificate and other checks * Validate a credential and learn it if it passes certificate and other checks
*/ */
Member::AddCredentialResult addCredential(void *tPtr, const Identity &sourcePeerIdentity, const CapabilityCredential &cap); Member::AddCredentialResult addCredential(CallContext &cc, const Identity &sourcePeerIdentity, const CapabilityCredential &cap);
/** /**
* Validate a credential and learn it if it passes certificate and other checks * Validate a credential and learn it if it passes certificate and other checks
*/ */
Member::AddCredentialResult addCredential(void *tPtr, const Identity &sourcePeerIdentity, const TagCredential &tag); Member::AddCredentialResult addCredential(CallContext &cc, const Identity &sourcePeerIdentity, const TagCredential &tag);
/** /**
* Validate a credential and learn it if it passes certificate and other checks * Validate a credential and learn it if it passes certificate and other checks
*/ */
Member::AddCredentialResult addCredential(void *tPtr, const Identity &sourcePeerIdentity, const RevocationCredential &rev); Member::AddCredentialResult addCredential(CallContext &cc, const Identity &sourcePeerIdentity, const RevocationCredential &rev);
/** /**
* Validate a credential and learn it if it passes certificate and other checks * Validate a credential and learn it if it passes certificate and other checks
*/ */
Member::AddCredentialResult addCredential(void *tPtr, const Identity &sourcePeerIdentity, const OwnershipCredential &coo); Member::AddCredentialResult addCredential(CallContext &cc, const Identity &sourcePeerIdentity, const OwnershipCredential &coo);
/** /**
* Push credentials to a peer if timeouts indicate that we should do so * Push credentials to a peer if timeouts indicate that we should do so
* *
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param to Destination peer * @param to Destination peer
* @param now Current time
*/ */
void pushCredentials(void *tPtr, const SharedPtr< Peer > &to, int64_t now); void pushCredentials(CallContext &cc, const SharedPtr< Peer > &to);
/** /**
* Destroy this network * Destroy this network
@ -352,7 +342,7 @@ public:
{ return &m_uPtr; } { return &m_uPtr; }
private: private:
void m_requestConfiguration(void *tPtr); void m_requestConfiguration(CallContext &cc);
ZT_VirtualNetworkStatus m_status() const; ZT_VirtualNetworkStatus m_status() const;

View file

@ -54,7 +54,7 @@ public:
* @param nc Network configuration to send * @param nc Network configuration to send
* @param sendLegacyFormatConfig If true, send an old-format network config * @param sendLegacyFormatConfig If true, send an old-format network config
*/ */
virtual void ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &destination,const NetworkConfig &nc,bool sendLegacyFormatConfig) = 0; virtual void ncSendConfig(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid, uint64_t requestPacketId, const Address &destination, const NetworkConfig &nc, bool sendLegacyFormatConfig) = 0;
/** /**
* Send revocation to a node * Send revocation to a node
@ -62,7 +62,7 @@ public:
* @param destination Destination node address * @param destination Destination node address
* @param rev Revocation to send * @param rev Revocation to send
*/ */
virtual void ncSendRevocation(const Address &destination,const RevocationCredential &rev) = 0; virtual void ncSendRevocation(void *tPtr, int64_t clock, int64_t ticks, const Address &destination, const RevocationCredential &rev) = 0;
/** /**
* Send a network configuration request error * Send a network configuration request error
@ -72,7 +72,7 @@ public:
* @param destination Destination peer Address * @param destination Destination peer Address
* @param errorCode Error code * @param errorCode Error code
*/ */
virtual void ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &destination,NetworkController::ErrorCode errorCode) = 0; virtual void ncSendError(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid, uint64_t requestPacketId, const Address &destination, NetworkController::ErrorCode errorCode) = 0;
}; };
NetworkController() {} NetworkController() {}
@ -84,7 +84,7 @@ public:
* @param signingId Identity for signing of network configurations, certs, etc. * @param signingId Identity for signing of network configurations, certs, etc.
* @param sender Sender implementation for sending replies or config pushes * @param sender Sender implementation for sending replies or config pushes
*/ */
virtual void init(const Identity &signingId,Sender *sender) = 0; virtual void init(const Identity &signingId, Sender *sender) = 0;
/** /**
* Handle a network configuration request * Handle a network configuration request

View file

@ -35,13 +35,13 @@ namespace {
struct _NodeObjects struct _NodeObjects
{ {
ZT_INLINE _NodeObjects(RuntimeEnvironment *const RR, Node *const n, void *const tPtr, const int64_t now) : ZT_INLINE _NodeObjects(RuntimeEnvironment *const RR, CallContext &cc) :
networks(), networks(),
t(RR), t(RR),
expect(), expect(),
vl2(RR), vl2(RR),
vl1(RR), vl1(RR),
topology(RR, tPtr, now), topology(RR, cc),
sa(RR), sa(RR),
ts() ts()
{ {
@ -69,9 +69,8 @@ struct _NodeObjects
Node::Node( Node::Node(
void *uPtr, void *uPtr,
void *tPtr,
const struct ZT_Node_Callbacks *callbacks, const struct ZT_Node_Callbacks *callbacks,
int64_t now) : CallContext &cc) :
m_RR(this), m_RR(this),
RR(&m_RR), RR(&m_RR),
m_store(&m_RR), m_store(&m_RR),
@ -79,8 +78,7 @@ Node::Node(
m_lastPeerPulse(0), m_lastPeerPulse(0),
m_lastHousekeepingRun(0), m_lastHousekeepingRun(0),
m_lastNetworkHousekeepingRun(0), m_lastNetworkHousekeepingRun(0),
m_lastRootRank(0), m_lastTrustStoreUpdate(0),
m_now(now),
m_online(false) m_online(false)
{ {
ZT_SPEW("Node starting up!"); ZT_SPEW("Node starting up!");
@ -89,7 +87,7 @@ Node::Node(
m_RR.uPtr = uPtr; m_RR.uPtr = uPtr;
m_RR.store = &m_store; m_RR.store = &m_store;
Vector< uint8_t > data(m_store.get(tPtr, ZT_STATE_OBJECT_IDENTITY_SECRET, Utils::ZERO256, 0)); Vector< uint8_t > data(m_store.get(cc, ZT_STATE_OBJECT_IDENTITY_SECRET, Utils::ZERO256, 0));
bool haveIdentity = false; bool haveIdentity = false;
if (!data.empty()) { if (!data.empty()) {
data.push_back(0); // zero-terminate string data.push_back(0); // zero-terminate string
@ -105,13 +103,13 @@ Node::Node(
m_RR.identity.generate(Identity::C25519); m_RR.identity.generate(Identity::C25519);
m_RR.identity.toString(false, m_RR.publicIdentityStr); m_RR.identity.toString(false, m_RR.publicIdentityStr);
m_RR.identity.toString(true, m_RR.secretIdentityStr); m_RR.identity.toString(true, m_RR.secretIdentityStr);
m_store.put(tPtr, ZT_STATE_OBJECT_IDENTITY_SECRET, Utils::ZERO256, 0, m_RR.secretIdentityStr, (unsigned int)strlen(m_RR.secretIdentityStr)); m_store.put(cc, ZT_STATE_OBJECT_IDENTITY_SECRET, Utils::ZERO256, 0, m_RR.secretIdentityStr, (unsigned int)strlen(m_RR.secretIdentityStr));
m_store.put(tPtr, ZT_STATE_OBJECT_IDENTITY_PUBLIC, Utils::ZERO256, 0, m_RR.publicIdentityStr, (unsigned int)strlen(m_RR.publicIdentityStr)); m_store.put(cc, ZT_STATE_OBJECT_IDENTITY_PUBLIC, Utils::ZERO256, 0, m_RR.publicIdentityStr, (unsigned int)strlen(m_RR.publicIdentityStr));
ZT_SPEW("no pre-existing identity found, created %s", RR->identity.toString().c_str()); ZT_SPEW("no pre-existing identity found, created %s", RR->identity.toString().c_str());
} else { } else {
data = m_store.get(tPtr, ZT_STATE_OBJECT_IDENTITY_PUBLIC, Utils::ZERO256, 0); data = m_store.get(cc, ZT_STATE_OBJECT_IDENTITY_PUBLIC, Utils::ZERO256, 0);
if ((data.empty()) || (memcmp(data.data(), m_RR.publicIdentityStr, strlen(m_RR.publicIdentityStr)) != 0)) if ((data.empty()) || (memcmp(data.data(), m_RR.publicIdentityStr, strlen(m_RR.publicIdentityStr)) != 0))
m_store.put(tPtr, ZT_STATE_OBJECT_IDENTITY_PUBLIC, Utils::ZERO256, 0, m_RR.publicIdentityStr, (unsigned int)strlen(m_RR.publicIdentityStr)); m_store.put(cc, ZT_STATE_OBJECT_IDENTITY_PUBLIC, Utils::ZERO256, 0, m_RR.publicIdentityStr, (unsigned int)strlen(m_RR.publicIdentityStr));
} }
uint8_t localSecretCipherKey[ZT_FINGERPRINT_HASH_SIZE]; uint8_t localSecretCipherKey[ZT_FINGERPRINT_HASH_SIZE];
@ -133,10 +131,10 @@ Node::Node(
} }
} }
m_objects = new _NodeObjects(&m_RR, this, tPtr, now); m_objects = new _NodeObjects(&m_RR, cc);
ZT_SPEW("node initialized!"); ZT_SPEW("node initialized!");
postEvent(tPtr, ZT_EVENT_UP); postEvent(cc.tPtr, ZT_EVENT_UP);
} }
Node::~Node() Node::~Node()
@ -157,28 +155,59 @@ Node::~Node()
Buf::freePool(); Buf::freePool();
} }
void Node::shutdown(void *tPtr) void Node::shutdown(CallContext &cc)
{ {
m_allNetworks_l.lock(); m_allNetworks_l.lock();
RR->networks->clear(); RR->networks->clear();
m_allNetworks.clear(); m_allNetworks.clear();
m_allNetworks_l.unlock(); m_allNetworks_l.unlock();
postEvent(tPtr, ZT_EVENT_DOWN);
postEvent(cc.tPtr, ZT_EVENT_DOWN);
if (RR->topology) if (RR->topology)
RR->topology->saveAll(tPtr); RR->topology->saveAll(cc);
} }
ZT_ResultCode Node::processBackgroundTasks( ZT_ResultCode Node::processBackgroundTasks(
void *tPtr, CallContext &cc,
int64_t now,
volatile int64_t *nextBackgroundTaskDeadline) volatile int64_t *nextBackgroundTaskDeadline)
{ {
m_now = now;
Mutex::Lock bl(m_backgroundTasksLock); Mutex::Lock bl(m_backgroundTasksLock);
try { try {
if ((now - m_lastPeerPulse) >= ZT_PEER_PULSE_INTERVAL) { // Updating the trust store means checking certificates and certificate chains
m_lastPeerPulse = now; // against the current time, etc., and also resynchronizing roots as specified by
// certificates. This also happens on demand when the trust store is changed.
if ((cc.ticks - m_lastTrustStoreUpdate) >= ZT_TRUSTSTORE_UPDATE_PERIOD) {
m_lastTrustStoreUpdate = cc.ticks;
if (RR->ts->update(cc.ticks, nullptr))
RR->topology->trustStoreChanged(cc);
}
// Networks perform housekeeping here such as refreshing configs.
if ((cc.ticks - m_lastNetworkHousekeepingRun) >= ZT_NETWORK_HOUSEKEEPING_PERIOD) {
m_lastNetworkHousekeepingRun = cc.ticks;
ZT_SPEW("running networking housekeeping...");
Mutex::Lock l(m_allNetworks_l);
for (Vector< SharedPtr< Network > >::const_iterator n(m_allNetworks.begin()); n != m_allNetworks.end(); ++n)
(*n)->doPeriodicTasks(cc);
}
// Perform general housekeeping for other objects in the system.
if ((cc.ticks - m_lastHousekeepingRun) >= ZT_HOUSEKEEPING_PERIOD) {
m_lastHousekeepingRun = cc.ticks;
ZT_SPEW("running housekeeping...");
RR->topology->doPeriodicTasks(cc);
RR->sa->clean(cc);
}
// Peers have a "pulse" method that does things like keepalive and path housekeeping.
// This happens last because keepalives are only necessary if nothing has been sent
// in a while, and some of the above actions may cause peers to send things which may
// reduce the need for keepalives. Root ranking also happens here.
if ((cc.ticks - m_lastPeerPulse) >= ZT_PEER_PULSE_INTERVAL) {
m_lastPeerPulse = cc.ticks;
ZT_SPEW("running pulse() on each peer..."); ZT_SPEW("running pulse() on each peer...");
try { try {
Vector< SharedPtr< Peer > > allPeers, rootPeers; Vector< SharedPtr< Peer > > allPeers, rootPeers;
@ -187,41 +216,21 @@ ZT_ResultCode Node::processBackgroundTasks(
bool online = false; bool online = false;
for (Vector< SharedPtr< Peer > >::iterator p(allPeers.begin()); p != allPeers.end(); ++p) { for (Vector< SharedPtr< Peer > >::iterator p(allPeers.begin()); p != allPeers.end(); ++p) {
const bool isRoot = std::find(rootPeers.begin(), rootPeers.end(), *p) != rootPeers.end(); const bool isRoot = std::find(rootPeers.begin(), rootPeers.end(), *p) != rootPeers.end();
(*p)->pulse(tPtr, now, isRoot); (*p)->pulse(cc, isRoot);
online |= ((isRoot || rootPeers.empty()) && (*p)->directlyConnected(now)); online |= ((isRoot || rootPeers.empty()) && (*p)->directlyConnected(cc));
} }
if (m_online.exchange(online) != online) if (m_online.exchange(online) != online)
postEvent(tPtr, online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE); postEvent(cc.tPtr, online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE);
ZT_SPEW("ranking roots...");
RR->topology->rankRoots(cc);
} catch (...) { } catch (...) {
return ZT_RESULT_FATAL_ERROR_INTERNAL; return ZT_RESULT_FATAL_ERROR_INTERNAL;
} }
} }
if ((now - m_lastNetworkHousekeepingRun) >= ZT_NETWORK_HOUSEKEEPING_PERIOD) { *nextBackgroundTaskDeadline = cc.ticks + ZT_TIMER_TASK_INTERVAL;
m_lastHousekeepingRun = now;
ZT_SPEW("running networking housekeeping...");
Mutex::Lock l(m_allNetworks_l);
for (Vector< SharedPtr< Network > >::const_iterator i(m_allNetworks.begin()); i != m_allNetworks.end(); ++i) {
(*i)->doPeriodicTasks(tPtr, now);
}
}
if ((now - m_lastHousekeepingRun) >= ZT_HOUSEKEEPING_PERIOD) {
m_lastHousekeepingRun = now;
ZT_SPEW("running housekeeping...");
RR->topology->doPeriodicTasks(tPtr, now);
RR->sa->clean(now);
}
if ((now - m_lastRootRank) >= ZT_ROOT_RANK_PERIOD) {
m_lastRootRank = now;
ZT_SPEW("ranking roots...");
RR->topology->rankRoots(now);
}
*nextBackgroundTaskDeadline = now + ZT_TIMER_TASK_INTERVAL;
} catch (...) { } catch (...) {
return ZT_RESULT_FATAL_ERROR_INTERNAL; return ZT_RESULT_FATAL_ERROR_INTERNAL;
} }
@ -233,7 +242,7 @@ ZT_ResultCode Node::join(
uint64_t nwid, uint64_t nwid,
const ZT_Fingerprint *controllerFingerprint, const ZT_Fingerprint *controllerFingerprint,
void *uptr, void *uptr,
void *tptr) CallContext &cc)
{ {
Mutex::Lock l(m_allNetworks_l); Mutex::Lock l(m_allNetworks_l);
@ -249,7 +258,7 @@ ZT_ResultCode Node::join(
if ((*n)->id() == nwid) if ((*n)->id() == nwid)
return ZT_RESULT_OK; return ZT_RESULT_OK;
} }
SharedPtr< Network > network(new Network(RR, tptr, nwid, fp, uptr, nullptr)); SharedPtr< Network > network(new Network(RR, cc, nwid, fp, uptr, nullptr));
m_allNetworks.push_back(network); m_allNetworks.push_back(network);
RR->networks->set(nwid, network); RR->networks->set(nwid, network);
@ -259,7 +268,7 @@ ZT_ResultCode Node::join(
ZT_ResultCode Node::leave( ZT_ResultCode Node::leave(
uint64_t nwid, uint64_t nwid,
void **uptr, void **uptr,
void *tptr) CallContext &cc)
{ {
Mutex::Lock l(m_allNetworks_l); Mutex::Lock l(m_allNetworks_l);
@ -279,21 +288,22 @@ ZT_ResultCode Node::leave(
uint64_t tmp[2]; uint64_t tmp[2];
tmp[0] = nwid; tmp[0] = nwid;
tmp[1] = 0; tmp[1] = 0;
m_store.erase(tptr, ZT_STATE_OBJECT_NETWORK_CONFIG, tmp, 1); m_store.erase(cc, ZT_STATE_OBJECT_NETWORK_CONFIG, tmp, 1);
if (network) { if (network) {
if (uptr) if (uptr)
*uptr = *network->userPtr(); *uptr = *network->userPtr();
network->externalConfig(&ctmp); network->externalConfig(&ctmp);
RR->node->configureVirtualNetworkPort(tptr, nwid, uptr, ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY, &ctmp); RR->cb.virtualNetworkConfigFunction(reinterpret_cast<ZT_Node *>(this), RR->uPtr, cc.tPtr, nwid, network->userPtr(), ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY, &ctmp);
network->destroy(); network->destroy();
return ZT_RESULT_OK; return ZT_RESULT_OK;
} else {
return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
} }
return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
} }
ZT_ResultCode Node::multicastSubscribe( ZT_ResultCode Node::multicastSubscribe(
void *tPtr, CallContext &cc,
uint64_t nwid, uint64_t nwid,
uint64_t multicastGroup, uint64_t multicastGroup,
unsigned long multicastAdi) unsigned long multicastAdi)
@ -301,7 +311,7 @@ ZT_ResultCode Node::multicastSubscribe(
ZT_SPEW("multicast subscribe to %s:%lu", MAC(multicastGroup).toString().c_str(), multicastAdi); ZT_SPEW("multicast subscribe to %s:%lu", MAC(multicastGroup).toString().c_str(), multicastAdi);
const SharedPtr< Network > nw(RR->networks->get(nwid)); const SharedPtr< Network > nw(RR->networks->get(nwid));
if (nw) { if (nw) {
nw->multicastSubscribe(tPtr, MulticastGroup(MAC(multicastGroup), (uint32_t)(multicastAdi & 0xffffffff))); nw->multicastSubscribe(cc, MulticastGroup(MAC(multicastGroup), (uint32_t)(multicastAdi & 0xffffffff)));
return ZT_RESULT_OK; return ZT_RESULT_OK;
} else { } else {
return ZT_RESULT_ERROR_NETWORK_NOT_FOUND; return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
@ -309,6 +319,7 @@ ZT_ResultCode Node::multicastSubscribe(
} }
ZT_ResultCode Node::multicastUnsubscribe( ZT_ResultCode Node::multicastUnsubscribe(
CallContext &cc,
uint64_t nwid, uint64_t nwid,
uint64_t multicastGroup, uint64_t multicastGroup,
unsigned long multicastAdi) unsigned long multicastAdi)
@ -353,7 +364,7 @@ struct p_sortPeerPtrsByAddress
{ return (a->address() < b->address()); } { return (a->address() < b->address()); }
}; };
ZT_PeerList *Node::peers() const ZT_PeerList *Node::peers(CallContext &cc) const
{ {
p_ZT_PeerListPrivate *pl = nullptr; p_ZT_PeerListPrivate *pl = nullptr;
try { try {
@ -364,7 +375,6 @@ ZT_PeerList *Node::peers() const
RR->topology->allPeers(peers, rootPeers); RR->topology->allPeers(peers, rootPeers);
std::sort(peers.begin(), peers.end(), p_sortPeerPtrsByAddress()); std::sort(peers.begin(), peers.end(), p_sortPeerPtrsByAddress());
std::sort(rootPeers.begin(), rootPeers.end()); std::sort(rootPeers.begin(), rootPeers.end());
int64_t now = m_now;
for (Vector< SharedPtr< Peer > >::iterator pi(peers.begin()); pi != peers.end(); ++pi) { for (Vector< SharedPtr< Peer > >::iterator pi(peers.begin()); pi != peers.end(); ++pi) {
pl->p_peers.push_back(ZT_Peer()); pl->p_peers.push_back(ZT_Peer());
@ -405,7 +415,7 @@ ZT_PeerList *Node::peers() const
Utils::copy< sizeof(struct sockaddr_storage) >(&(apip.endpoint.value.ss), &(ztp->address().as.ss)); Utils::copy< sizeof(struct sockaddr_storage) >(&(apip.endpoint.value.ss), &(ztp->address().as.ss));
apip.lastSend = ztp->lastOut(); apip.lastSend = ztp->lastOut();
apip.lastReceive = ztp->lastIn(); apip.lastReceive = ztp->lastIn();
apip.alive = ztp->alive(now) ? 1 : 0; apip.alive = ztp->alive(cc) ? 1 : 0;
apip.preferred = (i == 0) ? 1 : 0; apip.preferred = (i == 0) ? 1 : 0;
} }
p.paths = apiPaths.data(); p.paths = apiPaths.data();
@ -499,40 +509,8 @@ void Node::setInterfaceAddresses(
} }
} }
ZT_ResultCode Node::addPeer(
void *tptr,
const ZT_Identity *identity)
{
if (!identity)
return ZT_RESULT_ERROR_BAD_PARAMETER;
SharedPtr< Peer > peer(RR->topology->peer(tptr, reinterpret_cast<const Identity *>(identity)->address()));
if (!peer) {
peer.set(new Peer(RR));
peer->init(*reinterpret_cast<const Identity *>(identity));
peer = RR->topology->add(tptr, peer);
}
return (peer->identity() == *reinterpret_cast<const Identity *>(identity)) ? ZT_RESULT_OK : ZT_RESULT_ERROR_COLLIDING_OBJECT;
}
int Node::tryPeer(
void *tptr,
const ZT_Fingerprint *fp,
const ZT_Endpoint *endpoint,
int retries)
{
if ((!fp) || (!endpoint))
return 0;
const SharedPtr< Peer > peer(RR->topology->peer(tptr, fp->address, true));
if ((peer) && (peer->identity().fingerprint().bestSpecificityEquals(*fp))) {
peer->contact(tptr, m_now, Endpoint(*endpoint), std::min(retries, 1));
return 1;
}
return 0;
}
ZT_CertificateError Node::addCertificate( ZT_CertificateError Node::addCertificate(
void *tptr, CallContext &cc,
int64_t now,
unsigned int localTrust, unsigned int localTrust,
const ZT_Certificate *cert, const ZT_Certificate *cert,
const void *certData, const void *certData,
@ -548,13 +526,13 @@ ZT_CertificateError Node::addCertificate(
return ZT_CERTIFICATE_ERROR_INVALID_FORMAT; return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
} }
RR->ts->add(c, localTrust); RR->ts->add(c, localTrust);
RR->ts->update(now, nullptr); RR->ts->update(cc.clock, nullptr);
SharedPtr< TrustStore::Entry > ent(RR->ts->get(c.getSerialNo())); SharedPtr< TrustStore::Entry > ent(RR->ts->get(c.getSerialNo()));
return (ent) ? ent->error() : ZT_CERTIFICATE_ERROR_INVALID_FORMAT; // should never be null, but if so it means invalid return (ent) ? ent->error() : ZT_CERTIFICATE_ERROR_INVALID_FORMAT; // should never be null, but if so it means invalid
} }
ZT_ResultCode Node::deleteCertificate( ZT_ResultCode Node::deleteCertificate(
void *tptr, CallContext &cc,
const void *serialNo) const void *serialNo)
{ {
if (!serialNo) if (!serialNo)
@ -605,11 +583,11 @@ ZT_CertificateList *Node::listCertificates()
} }
int Node::sendUserMessage( int Node::sendUserMessage(
void *tptr, CallContext &cc,
uint64_t dest, uint64_t dest,
uint64_t typeId, uint64_t /*typeId*/,
const void *data, const void */*data*/,
unsigned int len) unsigned int /*len*/)
{ {
try { try {
if (RR->identity.address().toInt() != dest) { if (RR->identity.address().toInt() != dest) {
@ -679,13 +657,14 @@ bool Node::externalPathLookup(void *tPtr, const Identity &id, int family, InetAd
// Implementation of NetworkController::Sender ------------------------------------------------------------------------ // Implementation of NetworkController::Sender ------------------------------------------------------------------------
void Node::ncSendConfig(uint64_t nwid, uint64_t requestPacketId, const Address &destination, const NetworkConfig &nc, bool sendLegacyFormatConfig) void Node::ncSendConfig(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid, uint64_t requestPacketId, const Address &destination, const NetworkConfig &nc, bool sendLegacyFormatConfig)
{ {
if (destination == RR->identity.address()) { if (destination == RR->identity.address()) {
SharedPtr< Network > n(RR->networks->get(nwid)); SharedPtr< Network > n(RR->networks->get(nwid));
if (!n) if (!n)
return; return;
n->setConfiguration((void *)0, nc, true); CallContext cc(clock, ticks, tPtr);
n->setConfiguration(cc, nc, true);
} else { } else {
Dictionary dconf; Dictionary dconf;
if (nc.toDictionary(dconf)) { if (nc.toDictionary(dconf)) {
@ -731,13 +710,14 @@ void Node::ncSendConfig(uint64_t nwid, uint64_t requestPacketId, const Address &
} }
} }
void Node::ncSendRevocation(const Address &destination, const RevocationCredential &rev) void Node::ncSendRevocation(void *tPtr, int64_t clock, int64_t ticks, const Address &destination, const RevocationCredential &rev)
{ {
if (destination == RR->identity.address()) { if (destination == RR->identity.address()) {
SharedPtr< Network > n(RR->networks->get(rev.networkId())); SharedPtr< Network > n(RR->networks->get(rev.networkId()));
if (!n) if (!n)
return; return;
n->addCredential(nullptr, RR->identity, rev); CallContext cc(clock, ticks, tPtr);
n->addCredential(cc, RR->identity, rev);
} else { } else {
// TODO // TODO
/* /*
@ -753,7 +733,7 @@ void Node::ncSendRevocation(const Address &destination, const RevocationCredenti
} }
} }
void Node::ncSendError(uint64_t nwid, uint64_t requestPacketId, const Address &destination, NetworkController::ErrorCode errorCode) void Node::ncSendError(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid, uint64_t requestPacketId, const Address &destination, NetworkController::ErrorCode errorCode)
{ {
if (destination == RR->identity.address()) { if (destination == RR->identity.address()) {
SharedPtr< Network > n(RR->networks->get(nwid)); SharedPtr< Network > n(RR->networks->get(nwid));

View file

@ -26,6 +26,7 @@
#include "Buf.hpp" #include "Buf.hpp"
#include "Containers.hpp" #include "Containers.hpp"
#include "Store.hpp" #include "Store.hpp"
#include "CallContext.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -43,37 +44,35 @@ public:
void operator delete(void* p) { _mm_free(p); } void operator delete(void* p) { _mm_free(p); }
#endif #endif
Node(void *uPtr, void *tPtr, const struct ZT_Node_Callbacks *callbacks, int64_t now); Node(void *uPtr, const struct ZT_Node_Callbacks *callbacks, CallContext &cc);
virtual ~Node(); virtual ~Node();
void shutdown(void *tPtr); void shutdown(CallContext &cc);
// Public API Functions ---------------------------------------------------------------------------------------------
ZT_ResultCode processBackgroundTasks( ZT_ResultCode processBackgroundTasks(
void *tPtr, CallContext &cc,
int64_t now,
volatile int64_t *nextBackgroundTaskDeadline); volatile int64_t *nextBackgroundTaskDeadline);
ZT_ResultCode join( ZT_ResultCode join(
uint64_t nwid, uint64_t nwid,
const ZT_Fingerprint *controllerFingerprint, const ZT_Fingerprint *controllerFingerprint,
void *uptr, void *uptr,
void *tptr); CallContext &cc);
ZT_ResultCode leave( ZT_ResultCode leave(
uint64_t nwid, uint64_t nwid,
void **uptr, void **uptr,
void *tptr); CallContext &cc);
ZT_ResultCode multicastSubscribe( ZT_ResultCode multicastSubscribe(
void *tPtr, CallContext &cc,
uint64_t nwid, uint64_t nwid,
uint64_t multicastGroup, uint64_t multicastGroup,
unsigned long multicastAdi); unsigned long multicastAdi);
ZT_ResultCode multicastUnsubscribe( ZT_ResultCode multicastUnsubscribe(
CallContext &cc,
uint64_t nwid, uint64_t nwid,
uint64_t multicastGroup, uint64_t multicastGroup,
unsigned long multicastAdi); unsigned long multicastAdi);
@ -81,7 +80,8 @@ public:
void status( void status(
ZT_NodeStatus *status) const; ZT_NodeStatus *status) const;
ZT_PeerList *peers() const; ZT_PeerList *peers(
CallContext &cc) const;
ZT_VirtualNetworkConfig *networkConfig( ZT_VirtualNetworkConfig *networkConfig(
uint64_t nwid) const; uint64_t nwid) const;
@ -96,32 +96,21 @@ public:
const ZT_InterfaceAddress *addrs, const ZT_InterfaceAddress *addrs,
unsigned int addrCount); unsigned int addrCount);
ZT_ResultCode addPeer(
void *tptr,
const ZT_Identity *identity);
int tryPeer(
void *tptr,
const ZT_Fingerprint *fp,
const ZT_Endpoint *endpoint,
int retries);
ZT_CertificateError addCertificate( ZT_CertificateError addCertificate(
void *tptr, CallContext &cc,
int64_t now,
unsigned int localTrust, unsigned int localTrust,
const ZT_Certificate *cert, const ZT_Certificate *cert,
const void *certData, const void *certData,
unsigned int certSize); unsigned int certSize);
ZT_ResultCode deleteCertificate( ZT_ResultCode deleteCertificate(
void *tptr, CallContext &cc,
const void *serialNo); const void *serialNo);
ZT_CertificateList *listCertificates(); ZT_CertificateList *listCertificates();
int sendUserMessage( int sendUserMessage(
void *tptr, CallContext &cc,
uint64_t dest, uint64_t dest,
uint64_t typeId, uint64_t typeId,
const void *data, const void *data,
@ -130,23 +119,6 @@ public:
void setController( void setController(
void *networkControllerInstance); void *networkControllerInstance);
// Internal functions -----------------------------------------------------------------------------------------------
/**
* @return Most recent time value supplied to core via API
*/
ZT_INLINE int64_t now() const noexcept
{ return m_now; }
/**
* @return Known local interface addresses for this node
*/
ZT_INLINE Vector< ZT_InterfaceAddress > localInterfaceAddresses() const
{
Mutex::Lock _l(m_localInterfaceAddresses_m);
return m_localInterfaceAddresses;
}
/** /**
* Post an event via external callback * Post an event via external callback
* *
@ -158,18 +130,6 @@ public:
ZT_INLINE void postEvent(void *tPtr, ZT_Event ev, const void *md = nullptr, const unsigned int mdSize = 0) noexcept ZT_INLINE void postEvent(void *tPtr, ZT_Event ev, const void *md = nullptr, const unsigned int mdSize = 0) noexcept
{ RR->cb.eventCallback(reinterpret_cast<ZT_Node *>(this), RR->uPtr, tPtr, ev, md, mdSize); } { RR->cb.eventCallback(reinterpret_cast<ZT_Node *>(this), RR->uPtr, tPtr, ev, md, mdSize); }
/**
* Post network port configuration via external callback
*
* @param tPtr Thread pointer
* @param nwid Network ID
* @param nuptr Network-associated user pointer
* @param op Config operation or event type
* @param nc Network config info
*/
ZT_INLINE void configureVirtualNetworkPort(void *tPtr, uint64_t nwid, void **nuptr, ZT_VirtualNetworkConfigOperation op, const ZT_VirtualNetworkConfig *nc) noexcept
{ RR->cb.virtualNetworkConfigFunction(reinterpret_cast<ZT_Node *>(this), RR->uPtr, tPtr, nwid, nuptr, op, nc); }
/** /**
* Check whether a path should be used for ZeroTier traffic * Check whether a path should be used for ZeroTier traffic
* *
@ -201,9 +161,9 @@ public:
{ return m_RR.identity; } { return m_RR.identity; }
// Implementation of NetworkController::Sender interface // Implementation of NetworkController::Sender interface
virtual void ncSendConfig(uint64_t nwid, uint64_t requestPacketId, const Address &destination, const NetworkConfig &nc, bool sendLegacyFormatConfig); virtual void ncSendConfig(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid, uint64_t requestPacketId, const Address &destination, const NetworkConfig &nc, bool sendLegacyFormatConfig);
virtual void ncSendRevocation(const Address &destination, const RevocationCredential &rev); virtual void ncSendRevocation(void *tPtr, int64_t clock, int64_t ticks, const Address &destination, const RevocationCredential &rev);
virtual void ncSendError(uint64_t nwid, uint64_t requestPacketId, const Address &destination, NetworkController::ErrorCode errorCode); virtual void ncSendError(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid, uint64_t requestPacketId, const Address &destination, NetworkController::ErrorCode errorCode);
private: private:
RuntimeEnvironment m_RR; RuntimeEnvironment m_RR;
@ -234,10 +194,7 @@ private:
int64_t m_lastPeerPulse; int64_t m_lastPeerPulse;
int64_t m_lastHousekeepingRun; int64_t m_lastHousekeepingRun;
int64_t m_lastNetworkHousekeepingRun; int64_t m_lastNetworkHousekeepingRun;
int64_t m_lastRootRank; int64_t m_lastTrustStoreUpdate;
// This is the most recent value for time passed in via any of the core API methods.
std::atomic< int64_t > m_now;
// True if at least one root appears reachable. // True if at least one root appears reachable.
std::atomic< bool > m_online; std::atomic< bool > m_online;

View file

@ -161,11 +161,22 @@
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
#if __cplusplus > 199711L #if __cplusplus >= 199711L
#include <atomic> #include <atomic>
#ifndef __CPP11__ #ifndef __CPP11__
#define __CPP11__ 1 #define __CPP11__ 1
#endif #endif
#if __cplusplus >= 201703L
#define ZT_MAYBE_UNUSED [[maybe_unused]]
#ifndef __CPP17__
#define __CPP17__ 1
#endif
#else
#define ZT_MAYBE_UNUSED
#endif
#endif #endif
#if defined(ZT_ARCH_X64) || defined(__aarch64__) #if defined(ZT_ARCH_X64) || defined(__aarch64__)

View file

@ -19,11 +19,11 @@ void OwnershipCredential::addThing(const InetAddress &ip)
{ {
if (m_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) if (m_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS)
return; return;
if (ip.family() == AF_INET) { if (ip.as.sa.sa_family == AF_INET) {
m_thingTypes[m_thingCount] = THING_IPV4_ADDRESS; m_thingTypes[m_thingCount] = THING_IPV4_ADDRESS;
Utils::copy<4>(m_thingValues[m_thingCount], &(reinterpret_cast<const struct sockaddr_in *>(&ip)->sin_addr.s_addr)); Utils::copy<4>(m_thingValues[m_thingCount], &(reinterpret_cast<const struct sockaddr_in *>(&ip)->sin_addr.s_addr));
++m_thingCount; ++m_thingCount;
} else if (ip.family() == AF_INET6) { } else if (ip.as.sa.sa_family == AF_INET6) {
m_thingTypes[m_thingCount] = THING_IPV6_ADDRESS; m_thingTypes[m_thingCount] = THING_IPV6_ADDRESS;
Utils::copy<16>(m_thingValues[m_thingCount], reinterpret_cast<const struct sockaddr_in6 *>(&ip)->sin6_addr.s6_addr); Utils::copy<16>(m_thingValues[m_thingCount], reinterpret_cast<const struct sockaddr_in6 *>(&ip)->sin6_addr.s6_addr);
++m_thingCount; ++m_thingCount;

View file

@ -45,7 +45,8 @@ class OwnershipCredential : public Credential
friend class Credential; friend class Credential;
public: public:
static constexpr ZT_CredentialType credentialType() noexcept { return ZT_CREDENTIAL_TYPE_COO; } static constexpr ZT_CredentialType credentialType() noexcept
{ return ZT_CREDENTIAL_TYPE_COO; }
enum Thing enum Thing
{ {
@ -55,7 +56,8 @@ public:
THING_IPV6_ADDRESS = 3 THING_IPV6_ADDRESS = 3
}; };
ZT_INLINE OwnershipCredential() noexcept { memoryZero(this); } ZT_INLINE OwnershipCredential() noexcept
{ memoryZero(this); }
ZT_INLINE OwnershipCredential(const uint64_t nwid, const int64_t ts, const Address &issuedTo, const uint32_t id) noexcept ZT_INLINE OwnershipCredential(const uint64_t nwid, const int64_t ts, const Address &issuedTo, const uint32_t id) noexcept
{ {
@ -66,32 +68,53 @@ public:
m_issuedTo = issuedTo; m_issuedTo = issuedTo;
} }
ZT_INLINE uint64_t networkId() const noexcept { return m_networkId; } ZT_INLINE uint64_t networkId() const noexcept
ZT_INLINE int64_t timestamp() const noexcept { return m_ts; } { return m_networkId; }
ZT_INLINE uint32_t id() const noexcept { return m_id; }
ZT_INLINE const Address &issuedTo() const noexcept { return m_issuedTo; }
ZT_INLINE const Address &signer() const noexcept { return m_signedBy; }
ZT_INLINE const uint8_t *signature() const noexcept { return m_signature; }
ZT_INLINE unsigned int signatureLength() const noexcept { return m_signatureLength; }
ZT_INLINE unsigned int thingCount() const noexcept { return (unsigned int)m_thingCount; } ZT_INLINE int64_t timestamp() const noexcept
ZT_INLINE Thing thingType(const unsigned int i) const noexcept { return (Thing)m_thingTypes[i]; } { return m_ts; }
ZT_INLINE const uint8_t *thingValue(const unsigned int i) const noexcept { return m_thingValues[i]; }
ZT_INLINE int64_t revision() const noexcept
{ return m_ts; }
ZT_INLINE uint32_t id() const noexcept
{ return m_id; }
ZT_INLINE const Address &issuedTo() const noexcept
{ return m_issuedTo; }
ZT_INLINE const Address &signer() const noexcept
{ return m_signedBy; }
ZT_INLINE const uint8_t *signature() const noexcept
{ return m_signature; }
ZT_INLINE unsigned int signatureLength() const noexcept
{ return m_signatureLength; }
ZT_INLINE unsigned int thingCount() const noexcept
{ return (unsigned int)m_thingCount; }
ZT_INLINE Thing thingType(const unsigned int i) const noexcept
{ return (Thing)m_thingTypes[i]; }
ZT_INLINE const uint8_t *thingValue(const unsigned int i) const noexcept
{ return m_thingValues[i]; }
ZT_INLINE bool owns(const InetAddress &ip) const noexcept ZT_INLINE bool owns(const InetAddress &ip) const noexcept
{ {
if (ip.family() == AF_INET) if (ip.as.sa.sa_family == AF_INET)
return this->_owns(THING_IPV4_ADDRESS,&(reinterpret_cast<const struct sockaddr_in *>(&ip)->sin_addr.s_addr),4); return this->_owns(THING_IPV4_ADDRESS, &(reinterpret_cast<const struct sockaddr_in *>(&ip)->sin_addr.s_addr), 4);
if (ip.family() == AF_INET6) else if (ip.as.sa.sa_family == AF_INET6)
return this->_owns(THING_IPV6_ADDRESS,reinterpret_cast<const struct sockaddr_in6 *>(&ip)->sin6_addr.s6_addr,16); return this->_owns(THING_IPV6_ADDRESS, reinterpret_cast<const struct sockaddr_in6 *>(&ip)->sin6_addr.s6_addr, 16);
return false; else return false;
} }
ZT_INLINE bool owns(const MAC &mac) const noexcept ZT_INLINE bool owns(const MAC &mac) const noexcept
{ {
uint8_t tmp[6]; uint8_t tmp[6];
mac.copyTo(tmp); mac.copyTo(tmp);
return this->_owns(THING_MAC_ADDRESS,tmp,6); return this->_owns(THING_MAC_ADDRESS, tmp, 6);
} }
/** /**
@ -127,22 +150,30 @@ public:
* @param tPtr That pointer we pass around * @param tPtr That pointer we pass around
* @return Credential verification result: OK, bad signature, or identity needed * @return Credential verification result: OK, bad signature, or identity needed
*/ */
ZT_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return s_verify(RR, tPtr, *this); } ZT_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR, CallContext &cc) const
{ return s_verify(RR, cc, *this); }
static constexpr int marshalSizeMax() noexcept { return ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX; } static constexpr int marshalSizeMax() noexcept
int marshal(uint8_t data[ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX],bool forSign = false) const noexcept; { return ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX; }
int unmarshal(const uint8_t *data,int len) noexcept;
int marshal(uint8_t data[ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX], bool forSign = false) const noexcept;
int unmarshal(const uint8_t *data, int len) noexcept;
// Provides natural sort order by ID // Provides natural sort order by ID
ZT_INLINE bool operator<(const OwnershipCredential &coo) const noexcept { return (m_id < coo.m_id); } ZT_INLINE bool operator<(const OwnershipCredential &coo) const noexcept
{ return (m_id < coo.m_id); }
ZT_INLINE bool operator==(const OwnershipCredential &coo) const noexcept { return (memcmp(this, &coo, sizeof(OwnershipCredential)) == 0); } ZT_INLINE bool operator==(const OwnershipCredential &coo) const noexcept
ZT_INLINE bool operator!=(const OwnershipCredential &coo) const noexcept { return (memcmp(this, &coo, sizeof(OwnershipCredential)) != 0); } { return (memcmp(this, &coo, sizeof(OwnershipCredential)) == 0); }
ZT_INLINE bool operator!=(const OwnershipCredential &coo) const noexcept
{ return (memcmp(this, &coo, sizeof(OwnershipCredential)) != 0); }
private: private:
ZT_INLINE bool _owns(const Thing &t,const void *v,unsigned int l) const noexcept ZT_INLINE bool _owns(const Thing &t, const void *v, unsigned int l) const noexcept
{ {
for(unsigned int i=0,j=m_thingCount;i < j;++i) { for (unsigned int i = 0, j = m_thingCount; i < j; ++i) {
if (m_thingTypes[i] == (uint8_t)t) { if (m_thingTypes[i] == (uint8_t)t) {
unsigned int k = 0; unsigned int k = 0;
while (k < l) { while (k < l) {

View file

@ -17,11 +17,11 @@
namespace ZeroTier { namespace ZeroTier {
bool Path::send(const RuntimeEnvironment *const RR, void *const tPtr, const void *const data, const unsigned int len, const int64_t now) noexcept bool Path::send(const RuntimeEnvironment *const RR, CallContext &cc, const void *const data, const unsigned int len) noexcept
{ {
if (likely(RR->cb.wirePacketSendFunction(reinterpret_cast<ZT_Node *>(RR->node), RR->uPtr, tPtr, m_localSocket, reinterpret_cast<const ZT_InetAddress *>(&m_addr), data, len, 0) == 0)) { if (likely(RR->cb.wirePacketSendFunction(reinterpret_cast<ZT_Node *>(RR->node), RR->uPtr, cc.tPtr, m_localSocket, reinterpret_cast<const ZT_InetAddress *>(&m_addr), data, len, 0) == 0)) {
m_lastOut = now; m_lastOut = cc.ticks;
m_outMeter.log(now, len); m_outMeter.log(cc.ticks, len);
return true; return true;
} }
return false; return false;

View file

@ -21,6 +21,7 @@
#include "Mutex.hpp" #include "Mutex.hpp"
#include "Meter.hpp" #include "Meter.hpp"
#include "Containers.hpp" #include "Containers.hpp"
#include "CallContext.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -140,14 +141,11 @@ public:
/** /**
* Send a packet via this path (last out time is also updated) * Send a packet via this path (last out time is also updated)
* *
* @param RR Runtime environment
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param data Packet data * @param data Packet data
* @param len Packet length * @param len Packet length
* @param now Current time
* @return True if transport reported success * @return True if transport reported success
*/ */
bool send(const RuntimeEnvironment *RR, void *tPtr, const void *data, unsigned int len, int64_t now) noexcept; bool send(const RuntimeEnvironment *RR, CallContext &cc, const void *data, unsigned int len) noexcept;
/** /**
* Explicitly update last sent time * Explicitly update last sent time
@ -155,10 +153,10 @@ public:
* @param now Time of send * @param now Time of send
* @param bytes Bytes sent * @param bytes Bytes sent
*/ */
ZT_INLINE void sent(const int64_t now, const unsigned int bytes) noexcept ZT_INLINE void sent(const CallContext &cc, const unsigned int bytes) noexcept
{ {
m_lastOut.store(now); m_lastOut.store(cc.ticks, std::memory_order_relaxed);
m_outMeter.log(now, bytes); m_outMeter.log(cc.ticks, bytes);
} }
/** /**
@ -167,10 +165,10 @@ public:
* @param now Time of receive * @param now Time of receive
* @param bytes Bytes received * @param bytes Bytes received
*/ */
ZT_INLINE void received(const int64_t now, const unsigned int bytes) noexcept ZT_INLINE void received(const CallContext &cc, const unsigned int bytes) noexcept
{ {
m_lastIn.store(now); m_lastIn.store(cc.ticks, std::memory_order_relaxed);
m_inMeter.log(now, bytes); m_inMeter.log(cc.ticks, bytes);
} }
/** /**
@ -199,8 +197,8 @@ public:
* *
* @param now Current time * @param now Current time
*/ */
ZT_INLINE bool alive(const int64_t now) const noexcept ZT_INLINE bool alive(const CallContext &cc) const noexcept
{ return ((now - m_lastIn.load()) < ZT_PATH_ALIVE_TIMEOUT); } { return ((cc.ticks - m_lastIn.load()) < ZT_PATH_ALIVE_TIMEOUT); }
/** /**
* @return Physical address * @return Physical address

View file

@ -45,7 +45,7 @@ Peer::Peer(const RuntimeEnvironment *renv) :
Peer::~Peer() Peer::~Peer()
{ Utils::burn(m_helloMacKey, sizeof(m_helloMacKey)); } { Utils::burn(m_helloMacKey, sizeof(m_helloMacKey)); }
bool Peer::init(const Identity &peerIdentity) bool Peer::init(CallContext &cc, const Identity &peerIdentity)
{ {
RWMutex::Lock l(m_lock); RWMutex::Lock l(m_lock);
@ -56,7 +56,7 @@ bool Peer::init(const Identity &peerIdentity)
uint8_t k[ZT_SYMMETRIC_KEY_SIZE]; uint8_t k[ZT_SYMMETRIC_KEY_SIZE];
if (!RR->identity.agree(peerIdentity, k)) if (!RR->identity.agree(peerIdentity, k))
return false; return false;
m_identityKey.set(new SymmetricKey(RR->node->now(), k)); m_identityKey.set(new SymmetricKey(cc.ticks, k));
Utils::burn(k, sizeof(k)); Utils::burn(k, sizeof(k));
m_deriveSecondaryIdentityKeys(); m_deriveSecondaryIdentityKeys();
@ -65,7 +65,7 @@ bool Peer::init(const Identity &peerIdentity)
} }
void Peer::received( void Peer::received(
void *tPtr, CallContext &cc,
const SharedPtr< Path > &path, const SharedPtr< Path > &path,
const unsigned int hops, const unsigned int hops,
const uint64_t packetId, const uint64_t packetId,
@ -73,10 +73,8 @@ void Peer::received(
const Protocol::Verb verb, const Protocol::Verb verb,
const Protocol::Verb inReVerb) const Protocol::Verb inReVerb)
{ {
const int64_t now = RR->node->now(); m_lastReceive = cc.ticks;
m_inMeter.log(cc.ticks, payloadLength);
m_lastReceive = now;
m_inMeter.log(now, payloadLength);
if (hops == 0) { if (hops == 0) {
RWMutex::RMaybeWLock l(m_lock); RWMutex::RMaybeWLock l(m_lock);
@ -89,7 +87,7 @@ void Peer::received(
} }
// If we made it here, we don't already know this path. // If we made it here, we don't already know this path.
if (RR->node->shouldUsePathForZeroTierTraffic(tPtr, m_id, path->localSocket(), path->address())) { if (RR->node->shouldUsePathForZeroTierTraffic(cc.tPtr, m_id, path->localSocket(), path->address())) {
// SECURITY: note that if we've made it here we expected this OK, see Expect.hpp. // SECURITY: note that if we've made it here we expected this OK, see Expect.hpp.
// There is replay protection in effect for OK responses. // There is replay protection in effect for OK responses.
if (verb == Protocol::VERB_OK) { if (verb == Protocol::VERB_OK) {
@ -101,7 +99,7 @@ void Peer::received(
if (m_alivePathCount == ZT_MAX_PEER_NETWORK_PATHS) { if (m_alivePathCount == ZT_MAX_PEER_NETWORK_PATHS) {
int64_t lastReceiveTimeMax = 0; int64_t lastReceiveTimeMax = 0;
for (unsigned int i = 0; i < m_alivePathCount; ++i) { for (unsigned int i = 0; i < m_alivePathCount; ++i) {
if ((m_paths[i]->address().family() == path->address().family()) && if ((m_paths[i]->address().as.sa.sa_family == path->address().as.sa.sa_family) &&
(m_paths[i]->localSocket() == path->localSocket()) && // TODO: should be localInterface when multipath is integrated (m_paths[i]->localSocket() == path->localSocket()) && // TODO: should be localInterface when multipath is integrated
(m_paths[i]->address().ipsEqual2(path->address()))) { (m_paths[i]->address().ipsEqual2(path->address()))) {
// Replace older path if everything is the same except the port number, since NAT/firewall reboots // Replace older path if everything is the same except the port number, since NAT/firewall reboots
@ -123,7 +121,7 @@ void Peer::received(
m_paths[newPathIdx] = path; m_paths[newPathIdx] = path;
// Re-prioritize paths to include the new one. // Re-prioritize paths to include the new one.
m_prioritizePaths(now); m_prioritizePaths(cc);
// Add or update entry in the endpoint cache. If this endpoint // Add or update entry in the endpoint cache. If this endpoint
// is already present, its timesSeen count is incremented. Otherwise // is already present, its timesSeen count is incremented. Otherwise
@ -133,35 +131,35 @@ void Peer::received(
for (unsigned int i = 0;; ++i) { for (unsigned int i = 0;; ++i) {
if (i == (ZT_PEER_ENDPOINT_CACHE_SIZE - 1)) { if (i == (ZT_PEER_ENDPOINT_CACHE_SIZE - 1)) {
m_endpointCache[i].target = thisEndpoint; m_endpointCache[i].target = thisEndpoint;
m_endpointCache[i].lastSeen = now; m_endpointCache[i].lastSeen = cc.ticks;
break; break;
} else if (m_endpointCache[i].target == thisEndpoint) { } else if (m_endpointCache[i].target == thisEndpoint) {
m_endpointCache[i].lastSeen = now; m_endpointCache[i].lastSeen = cc.ticks;
break; break;
} }
} }
RR->t->learnedNewPath(tPtr, 0x582fabdd, packetId, m_id, path->address(), old); RR->t->learnedNewPath(cc, 0x582fabdd, packetId, m_id, path->address(), old);
} else { } else {
path->sent(now, hello(tPtr, path->localSocket(), path->address(), now)); path->sent(cc, hello(cc, path->localSocket(), path->address()));
RR->t->tryingNewPath(tPtr, 0xb7747ddd, m_id, path->address(), path->address(), packetId, (uint8_t)verb, m_id); RR->t->tryingNewPath(cc, 0xb7747ddd, m_id, path->address(), path->address(), packetId, (uint8_t)verb, m_id);
} }
} }
} }
} }
void Peer::send(void *tPtr, int64_t now, const void *data, unsigned int len) noexcept void Peer::send(CallContext &cc, const void *data, unsigned int len) noexcept
{ {
SharedPtr< Path > via(this->path(now)); SharedPtr< Path > via(this->path(cc));
if (via) { if (via) {
via->send(RR, tPtr, data, len, now); via->send(RR, cc, data, len);
} else { } else {
const SharedPtr< Peer > root(RR->topology->root()); const SharedPtr< Peer > root(RR->topology->root());
if ((root) && (root.ptr() != this)) { if ((root) && (root.ptr() != this)) {
via = root->path(now); via = root->path(cc);
if (via) { if (via) {
via->send(RR, tPtr, data, len, now); via->send(RR, cc, data, len);
root->relayed(now, len); root->relayed(cc, len);
} else { } else {
return; return;
} }
@ -169,10 +167,10 @@ void Peer::send(void *tPtr, int64_t now, const void *data, unsigned int len) noe
return; return;
} }
} }
sent(now, len); sent(cc, len);
} }
unsigned int Peer::hello(void *tPtr, int64_t localSocket, const InetAddress &atAddress, const int64_t now) unsigned int Peer::hello(CallContext &cc, int64_t localSocket, const InetAddress &atAddress)
{ {
Buf outp; Buf outp;
@ -183,7 +181,7 @@ unsigned int Peer::hello(void *tPtr, int64_t localSocket, const InetAddress &atA
outp.wI8(ii, ZEROTIER_VERSION_MAJOR); outp.wI8(ii, ZEROTIER_VERSION_MAJOR);
outp.wI8(ii, ZEROTIER_VERSION_MINOR); outp.wI8(ii, ZEROTIER_VERSION_MINOR);
outp.wI16(ii, ZEROTIER_VERSION_REVISION); outp.wI16(ii, ZEROTIER_VERSION_REVISION);
outp.wI64(ii, (uint64_t)now); outp.wI64(ii, (uint64_t)cc.clock);
outp.wO(ii, RR->identity); outp.wO(ii, RR->identity);
outp.wO(ii, atAddress); outp.wO(ii, atAddress);
@ -226,10 +224,10 @@ unsigned int Peer::hello(void *tPtr, int64_t localSocket, const InetAddress &atA
p1305.finish(polyMac); p1305.finish(polyMac);
Utils::storeMachineEndian< uint64_t >(outp.unsafeData + ZT_PROTO_PACKET_MAC_INDEX, polyMac[0]); Utils::storeMachineEndian< uint64_t >(outp.unsafeData + ZT_PROTO_PACKET_MAC_INDEX, polyMac[0]);
return (likely(RR->cb.wirePacketSendFunction(reinterpret_cast<ZT_Node *>(RR->node), RR->uPtr, tPtr, localSocket, reinterpret_cast<const ZT_InetAddress *>(&atAddress), outp.unsafeData, ii, 0) == 0)) ? ii : 0; return (likely(RR->cb.wirePacketSendFunction(reinterpret_cast<ZT_Node *>(RR->node), RR->uPtr, cc.tPtr, localSocket, reinterpret_cast<const ZT_InetAddress *>(&atAddress), outp.unsafeData, ii, 0) == 0)) ? ii : 0;
} }
void Peer::pulse(void *const tPtr, const int64_t now, const bool isRoot) void Peer::pulse(CallContext &cc, const bool isRoot)
{ {
RWMutex::Lock l(m_lock); RWMutex::Lock l(m_lock);
@ -237,15 +235,15 @@ void Peer::pulse(void *const tPtr, const int64_t now, const bool isRoot)
// to be sent. The latter happens every ZT_PEER_HELLO_INTERVAL or if a new // to be sent. The latter happens every ZT_PEER_HELLO_INTERVAL or if a new
// ephemeral key pair is generated. // ephemeral key pair is generated.
bool needHello = false; bool needHello = false;
if ((m_vProto >= 11) && (((now - m_ephemeralPairTimestamp) >= (ZT_SYMMETRIC_KEY_TTL / 2)) || ((m_ephemeralKeys[0]) && (m_ephemeralKeys[0]->odometer() >= (ZT_SYMMETRIC_KEY_TTL_MESSAGES / 2))))) { if ((m_vProto >= 11) && (((cc.ticks - m_ephemeralPairTimestamp) >= (ZT_SYMMETRIC_KEY_TTL / 2)) || ((m_ephemeralKeys[0]) && (m_ephemeralKeys[0]->odometer() >= (ZT_SYMMETRIC_KEY_TTL_MESSAGES / 2))))) {
m_ephemeralPair.generate(); m_ephemeralPair.generate();
needHello = true; needHello = true;
} else if ((now - m_lastSentHello) >= ZT_PEER_HELLO_INTERVAL) { } else if ((cc.ticks - m_lastSentHello) >= ZT_PEER_HELLO_INTERVAL) {
needHello = true; needHello = true;
} }
// Prioritize paths and more importantly for here forget dead ones. // Prioritize paths and more importantly for here forget dead ones.
m_prioritizePaths(now); m_prioritizePaths(cc);
if (m_tryQueue.empty()) { if (m_tryQueue.empty()) {
if (m_alivePathCount == 0) { if (m_alivePathCount == 0) {
@ -256,12 +254,12 @@ void Peer::pulse(void *const tPtr, const int64_t now, const bool isRoot)
if (m_locator) { if (m_locator) {
for (Vector< std::pair<Endpoint, SharedPtr< const Locator::EndpointAttributes > > >::const_iterator ep(m_locator->endpoints().begin()); ep != m_locator->endpoints().end(); ++ep) { for (Vector< std::pair<Endpoint, SharedPtr< const Locator::EndpointAttributes > > >::const_iterator ep(m_locator->endpoints().begin()); ep != m_locator->endpoints().end(); ++ep) {
if (ep->first.type == ZT_ENDPOINT_TYPE_IP_UDP) { if (ep->first.type == ZT_ENDPOINT_TYPE_IP_UDP) {
if (RR->node->shouldUsePathForZeroTierTraffic(tPtr, m_id, -1, ep->first.ip())) { if (RR->node->shouldUsePathForZeroTierTraffic(cc.tPtr, m_id, -1, ep->first.ip())) {
int64_t &lt = m_lastTried[ep->first]; int64_t &lt = m_lastTried[ep->first];
if ((now - lt) > ZT_PATH_MIN_TRY_INTERVAL) { if ((cc.ticks - lt) > ZT_PATH_MIN_TRY_INTERVAL) {
lt = now; lt = cc.ticks;
RR->t->tryingNewPath(tPtr, 0x84b22322, m_id, ep->first.ip(), InetAddress::NIL, 0, 0, Identity::NIL); RR->t->tryingNewPath(cc, 0x84b22322, m_id, ep->first.ip(), InetAddress::NIL, 0, 0, Identity::NIL);
sent(now, m_sendProbe(tPtr, -1, ep->first.ip(), nullptr, 0, now)); sent(cc, m_sendProbe(cc, -1, ep->first.ip(), nullptr, 0));
} }
} }
} }
@ -270,25 +268,25 @@ void Peer::pulse(void *const tPtr, const int64_t now, const bool isRoot)
for (unsigned int i = 0; i < ZT_PEER_ENDPOINT_CACHE_SIZE; ++i) { for (unsigned int i = 0; i < ZT_PEER_ENDPOINT_CACHE_SIZE; ++i) {
if ((m_endpointCache[i].lastSeen > 0) && (m_endpointCache[i].target.type == ZT_ENDPOINT_TYPE_IP_UDP)) { if ((m_endpointCache[i].lastSeen > 0) && (m_endpointCache[i].target.type == ZT_ENDPOINT_TYPE_IP_UDP)) {
if (RR->node->shouldUsePathForZeroTierTraffic(tPtr, m_id, -1, m_endpointCache[i].target.ip())) { if (RR->node->shouldUsePathForZeroTierTraffic(cc.tPtr, m_id, -1, m_endpointCache[i].target.ip())) {
int64_t &lt = m_lastTried[m_endpointCache[i].target]; int64_t &lt = m_lastTried[m_endpointCache[i].target];
if ((now - lt) > ZT_PATH_MIN_TRY_INTERVAL) { if ((cc.ticks - lt) > ZT_PATH_MIN_TRY_INTERVAL) {
lt = now; lt = cc.ticks;
RR->t->tryingNewPath(tPtr, 0x84b22343, m_id, m_endpointCache[i].target.ip(), InetAddress::NIL, 0, 0, Identity::NIL); RR->t->tryingNewPath(cc, 0x84b22343, m_id, m_endpointCache[i].target.ip(), InetAddress::NIL, 0, 0, Identity::NIL);
sent(now, m_sendProbe(tPtr, -1, m_endpointCache[i].target.ip(), nullptr, 0, now)); sent(cc, m_sendProbe(cc, -1, m_endpointCache[i].target.ip(), nullptr, 0));
} }
} }
} }
} }
InetAddress addr; InetAddress addr;
if (RR->node->externalPathLookup(tPtr, m_id, -1, addr)) { if (RR->node->externalPathLookup(cc.tPtr, m_id, -1, addr)) {
if ((addr) && RR->node->shouldUsePathForZeroTierTraffic(tPtr, m_id, -1, addr)) { if ((addr) && RR->node->shouldUsePathForZeroTierTraffic(cc.tPtr, m_id, -1, addr)) {
int64_t &lt = m_lastTried[Endpoint(addr)]; int64_t &lt = m_lastTried[Endpoint(addr)];
if ((now - lt) > ZT_PATH_MIN_TRY_INTERVAL) { if ((cc.ticks - lt) > ZT_PATH_MIN_TRY_INTERVAL) {
lt = now; lt = cc.ticks;
RR->t->tryingNewPath(tPtr, 0x84a10000, m_id, addr, InetAddress::NIL, 0, 0, Identity::NIL); RR->t->tryingNewPath(cc, 0x84a10000, m_id, addr, InetAddress::NIL, 0, 0, Identity::NIL);
sent(now, m_sendProbe(tPtr, -1, addr, nullptr, 0, now)); sent(cc, m_sendProbe(cc, -1, addr, nullptr, 0));
} }
} }
} }
@ -318,7 +316,7 @@ void Peer::pulse(void *const tPtr, const int64_t now, const bool isRoot)
// If iteration is less than zero, try to contact the original address. // If iteration is less than zero, try to contact the original address.
// It may be set to a larger negative value to try multiple times such // It may be set to a larger negative value to try multiple times such
// as e.g. -3 to try 3 times. // as e.g. -3 to try 3 times.
sent(now, m_sendProbe(tPtr, -1, qi.target.ip(), nullptr, 0, now)); sent(cc, m_sendProbe(cc, -1, qi.target.ip(), nullptr, 0));
++qi.iteration; ++qi.iteration;
goto requeue_item; goto requeue_item;
@ -340,7 +338,7 @@ void Peer::pulse(void *const tPtr, const int64_t now, const bool isRoot)
ports[pn++] = p; ports[pn++] = p;
} }
if (pn > 0) if (pn > 0)
sent(now, m_sendProbe(tPtr, -1, qi.target.ip(), ports, pn, now)); sent(cc, m_sendProbe(cc, -1, qi.target.ip(), ports, pn));
if (qi.iteration < 1023) if (qi.iteration < 1023)
goto requeue_item; goto requeue_item;
@ -354,7 +352,7 @@ void Peer::pulse(void *const tPtr, const int64_t now, const bool isRoot)
if (p > 65535) if (p > 65535)
p -= 64512; // wrap back to 1024 p -= 64512; // wrap back to 1024
tmp.setPort(p); tmp.setPort(p);
sent(now, m_sendProbe(tPtr, -1, tmp, nullptr, 0, now)); sent(cc, m_sendProbe(cc, -1, tmp, nullptr, 0));
if (qi.iteration < ZT_NAT_T_PORT_SCAN_MAX) if (qi.iteration < ZT_NAT_T_PORT_SCAN_MAX)
goto requeue_item; goto requeue_item;
@ -385,13 +383,13 @@ void Peer::pulse(void *const tPtr, const int64_t now, const bool isRoot)
for (unsigned int i = 0; i < m_alivePathCount; ++i) { for (unsigned int i = 0; i < m_alivePathCount; ++i) {
if (needHello) { if (needHello) {
needHello = false; needHello = false;
const unsigned int bytes = hello(tPtr, m_paths[i]->localSocket(), m_paths[i]->address(), now); const unsigned int bytes = hello(cc, m_paths[i]->localSocket(), m_paths[i]->address());
m_paths[i]->sent(now, bytes); m_paths[i]->sent(cc, bytes);
sent(now, bytes); sent(cc, bytes);
m_lastSentHello = now; m_lastSentHello = cc.ticks;
} else if ((now - m_paths[i]->lastOut()) >= ZT_PATH_KEEPALIVE_PERIOD) { } else if ((cc.ticks - m_paths[i]->lastOut()) >= ZT_PATH_KEEPALIVE_PERIOD) {
m_paths[i]->send(RR, tPtr, reinterpret_cast<uint8_t *>(&randomJunk) + (i & 7U), 1, now); m_paths[i]->send(RR, cc, reinterpret_cast<uint8_t *>(&randomJunk) + (i & 7U), 1);
sent(now, 1); sent(cc, 1);
} }
} }
@ -399,34 +397,35 @@ void Peer::pulse(void *const tPtr, const int64_t now, const bool isRoot)
if (needHello) { if (needHello) {
const SharedPtr< Peer > root(RR->topology->root()); const SharedPtr< Peer > root(RR->topology->root());
if (root) { if (root) {
const SharedPtr< Path > via(root->path(now)); const SharedPtr< Path > via(root->path(cc));
if (via) { if (via) {
const unsigned int bytes = hello(tPtr, via->localSocket(), via->address(), now); const unsigned int bytes = hello(cc, via->localSocket(), via->address());
via->sent(now, bytes); via->sent(cc, bytes);
root->relayed(now, bytes); root->relayed(cc, bytes);
sent(now, bytes); sent(cc, bytes);
m_lastSentHello = now; m_lastSentHello = cc.ticks;
} }
} }
} }
// Clean m_lastTried // Clean m_lastTried
for (Map< Endpoint, int64_t >::iterator i(m_lastTried.begin()); i != m_lastTried.end();) { for (Map< Endpoint, int64_t >::iterator i(m_lastTried.begin()); i != m_lastTried.end();) {
if ((now - i->second) > (ZT_PATH_MIN_TRY_INTERVAL * 4)) if ((cc.ticks - i->second) > (ZT_PATH_MIN_TRY_INTERVAL * 4))
m_lastTried.erase(i++); m_lastTried.erase(i++);
else ++i; else ++i;
} }
} }
void Peer::contact(void *tPtr, const int64_t now, const Endpoint &ep, int tries) void Peer::contact(CallContext &cc, const Endpoint &ep, int tries)
{ {
static uint8_t foo = 0; static uint8_t foo = 0;
RWMutex::Lock l(m_lock); RWMutex::Lock l(m_lock);
// See if there's already a path to this endpoint and if so ignore it. // See if there's already a path to this endpoint and if so ignore it.
if (ep.isInetAddr()) { if (ep.isInetAddr()) {
if ((now - m_lastPrioritizedPaths) > ZT_PEER_PRIORITIZE_PATHS_INTERVAL) if ((cc.ticks - m_lastPrioritizedPaths) > ZT_PEER_PRIORITIZE_PATHS_INTERVAL) {
m_prioritizePaths(now); m_prioritizePaths(cc);
}
for (unsigned int i = 0; i < m_alivePathCount; ++i) { for (unsigned int i = 0; i < m_alivePathCount; ++i) {
if (m_paths[i]->address().ipsEqual(ep.ip())) if (m_paths[i]->address().ipsEqual(ep.ip()))
return; return;
@ -435,15 +434,15 @@ void Peer::contact(void *tPtr, const int64_t now, const Endpoint &ep, int tries)
// Check underlying path attempt rate limit. // Check underlying path attempt rate limit.
int64_t &lt = m_lastTried[ep]; int64_t &lt = m_lastTried[ep];
if ((now - lt) < ZT_PATH_MIN_TRY_INTERVAL) if ((cc.ticks - lt) < ZT_PATH_MIN_TRY_INTERVAL)
return; return;
lt = now; lt = cc.ticks;
// For IPv4 addresses we send a tiny packet with a low TTL, which helps to // For IPv4 addresses we send a tiny packet with a low TTL, which helps to
// traverse some NAT types. It has no effect otherwise. // traverse some NAT types. It has no effect otherwise.
if (ep.isInetAddr() && ep.ip().isV4()) { if (ep.isInetAddr() && ep.ip().isV4()) {
++foo; ++foo;
RR->cb.wirePacketSendFunction(reinterpret_cast<ZT_Node *>(RR->node), RR->uPtr, tPtr, -1, reinterpret_cast<const ZT_InetAddress *>(&ep.ip()), &foo, 1, 2); RR->cb.wirePacketSendFunction(reinterpret_cast<ZT_Node *>(RR->node), RR->uPtr, cc.tPtr, -1, reinterpret_cast<const ZT_InetAddress *>(&ep.ip()), &foo, 1, 2);
} }
// Make sure address is not already in the try queue. If so just update it. // Make sure address is not already in the try queue. If so just update it.
@ -458,15 +457,15 @@ void Peer::contact(void *tPtr, const int64_t now, const Endpoint &ep, int tries)
m_tryQueue.push_back(p_TryQueueItem(ep, -tries)); m_tryQueue.push_back(p_TryQueueItem(ep, -tries));
} }
void Peer::resetWithinScope(void *tPtr, InetAddress::IpScope scope, int inetAddressFamily, int64_t now) void Peer::resetWithinScope(CallContext &cc, InetAddress::IpScope scope, int inetAddressFamily)
{ {
RWMutex::Lock l(m_lock); RWMutex::Lock l(m_lock);
unsigned int pc = 0; unsigned int pc = 0;
for (unsigned int i = 0; i < m_alivePathCount; ++i) { for (unsigned int i = 0; i < m_alivePathCount; ++i) {
if ((m_paths[i]) && ((m_paths[i]->address().family() == inetAddressFamily) && (m_paths[i]->address().ipScope() == scope))) { if ((m_paths[i]) && (((int)m_paths[i]->address().as.sa.sa_family == inetAddressFamily) && (m_paths[i]->address().ipScope() == scope))) {
const unsigned int bytes = m_sendProbe(tPtr, m_paths[i]->localSocket(), m_paths[i]->address(), nullptr, 0, now); const unsigned int bytes = m_sendProbe(cc, m_paths[i]->localSocket(), m_paths[i]->address(), nullptr, 0);
m_paths[i]->sent(now, bytes); m_paths[i]->sent(cc, bytes);
sent(now, bytes); sent(cc, bytes);
} else if (pc != i) { } else if (pc != i) {
m_paths[pc++] = m_paths[i]; m_paths[pc++] = m_paths[i];
} }
@ -476,11 +475,11 @@ void Peer::resetWithinScope(void *tPtr, InetAddress::IpScope scope, int inetAddr
m_paths[pc++].zero(); m_paths[pc++].zero();
} }
bool Peer::directlyConnected(int64_t now) bool Peer::directlyConnected(CallContext &cc)
{ {
if ((now - m_lastPrioritizedPaths) > ZT_PEER_PRIORITIZE_PATHS_INTERVAL) { if ((cc.ticks - m_lastPrioritizedPaths) > ZT_PEER_PRIORITIZE_PATHS_INTERVAL) {
RWMutex::Lock l(m_lock); RWMutex::Lock l(m_lock);
m_prioritizePaths(now); m_prioritizePaths(cc);
return m_alivePathCount > 0; return m_alivePathCount > 0;
} else { } else {
RWMutex::RLock l(m_lock); RWMutex::RLock l(m_lock);
@ -496,19 +495,19 @@ void Peer::getAllPaths(Vector< SharedPtr< Path > > &paths)
paths.assign(m_paths, m_paths + m_alivePathCount); paths.assign(m_paths, m_paths + m_alivePathCount);
} }
void Peer::save(void *tPtr) const void Peer::save(CallContext &cc) const
{ {
uint8_t buf[8 + ZT_PEER_MARSHAL_SIZE_MAX]; uint8_t buf[8 + ZT_PEER_MARSHAL_SIZE_MAX];
// Prefix each saved peer with the current timestamp. // Prefix each saved peer with the current timestamp.
Utils::storeBigEndian< uint64_t >(buf, (uint64_t)RR->node->now()); Utils::storeBigEndian< uint64_t >(buf, (uint64_t)cc.clock);
const int len = marshal(buf + 8); const int len = marshal(buf + 8);
if (len > 0) { if (len > 0) {
uint64_t id[2]; uint64_t id[2];
id[0] = m_id.address().toInt(); id[0] = m_id.address().toInt();
id[1] = 0; id[1] = 0;
RR->store->put(tPtr, ZT_STATE_OBJECT_PEER, id, 1, buf, (unsigned int)len + 8); RR->store->put(cc, ZT_STATE_OBJECT_PEER, id, 1, buf, (unsigned int)len + 8);
} }
} }
@ -579,7 +578,7 @@ int Peer::marshal(uint8_t data[ZT_PEER_MARSHAL_SIZE_MAX]) const noexcept
return p; return p;
} }
int Peer::unmarshal(const uint8_t *restrict data, const int len) noexcept int Peer::unmarshal(const int64_t ticks, const uint8_t *restrict data, const int len) noexcept
{ {
RWMutex::Lock l(m_lock); RWMutex::Lock l(m_lock);
@ -596,7 +595,7 @@ int Peer::unmarshal(const uint8_t *restrict data, const int len) noexcept
RR->localSecretCipher.decrypt(data + 1 + ZT_ADDRESS_LENGTH, k); RR->localSecretCipher.decrypt(data + 1 + ZT_ADDRESS_LENGTH, k);
RR->localSecretCipher.decrypt(data + 1 + ZT_ADDRESS_LENGTH + 16, k + 16); RR->localSecretCipher.decrypt(data + 1 + ZT_ADDRESS_LENGTH + 16, k + 16);
RR->localSecretCipher.decrypt(data + 1 + ZT_ADDRESS_LENGTH + 32, k + 32); RR->localSecretCipher.decrypt(data + 1 + ZT_ADDRESS_LENGTH + 32, k + 32);
m_identityKey.set(new SymmetricKey(RR->node->now(), k)); m_identityKey.set(new SymmetricKey(ticks, k));
Utils::burn(k, sizeof(k)); Utils::burn(k, sizeof(k));
} }
@ -611,7 +610,7 @@ int Peer::unmarshal(const uint8_t *restrict data, const int len) noexcept
uint8_t k[ZT_SYMMETRIC_KEY_SIZE]; uint8_t k[ZT_SYMMETRIC_KEY_SIZE];
if (!RR->identity.agree(m_id, k)) if (!RR->identity.agree(m_id, k))
return -1; return -1;
m_identityKey.set(new SymmetricKey(RR->node->now(), k)); m_identityKey.set(new SymmetricKey(ticks, k));
Utils::burn(k, sizeof(k)); Utils::burn(k, sizeof(k));
} }
@ -673,10 +672,10 @@ struct _PathPriorityComparisonOperator
} }
}; };
void Peer::m_prioritizePaths(int64_t now) void Peer::m_prioritizePaths(CallContext &cc)
{ {
// assumes _lock is locked for writing // assumes _lock is locked for writing
m_lastPrioritizedPaths = now; m_lastPrioritizedPaths = cc.ticks;
if (m_alivePathCount > 0) { if (m_alivePathCount > 0) {
// Sort paths in descending order of priority. // Sort paths in descending order of priority.
@ -684,7 +683,7 @@ void Peer::m_prioritizePaths(int64_t now)
// Let go of paths that have expired. // Let go of paths that have expired.
for (unsigned int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) { for (unsigned int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
if ((!m_paths[i]) || (!m_paths[i]->alive(now))) { if ((!m_paths[i]) || (!m_paths[i]->alive(cc))) {
m_alivePathCount = i; m_alivePathCount = i;
for (; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) for (; i < ZT_MAX_PEER_NETWORK_PATHS; ++i)
m_paths[i].zero(); m_paths[i].zero();
@ -694,7 +693,7 @@ void Peer::m_prioritizePaths(int64_t now)
} }
} }
unsigned int Peer::m_sendProbe(void *tPtr, int64_t localSocket, const InetAddress &atAddress, const uint16_t *ports, const unsigned int numPorts, int64_t now) unsigned int Peer::m_sendProbe(CallContext &cc, int64_t localSocket, const InetAddress &atAddress, const uint16_t *ports, const unsigned int numPorts)
{ {
// Assumes m_lock is locked // Assumes m_lock is locked
const SharedPtr< SymmetricKey > k(m_key()); const SharedPtr< SymmetricKey > k(m_key());
@ -709,17 +708,17 @@ unsigned int Peer::m_sendProbe(void *tPtr, int64_t localSocket, const InetAddres
Protocol::armor(p, ZT_PROTO_MIN_PACKET_LENGTH, k, cipher()); Protocol::armor(p, ZT_PROTO_MIN_PACKET_LENGTH, k, cipher());
RR->expect->sending(packetId, now); RR->expect->sending(packetId, cc.ticks);
if (numPorts > 0) { if (numPorts > 0) {
InetAddress tmp(atAddress); InetAddress tmp(atAddress);
for (unsigned int i = 0; i < numPorts; ++i) { for (unsigned int i = 0; i < numPorts; ++i) {
tmp.setPort(ports[i]); tmp.setPort(ports[i]);
RR->cb.wirePacketSendFunction(reinterpret_cast<ZT_Node *>(RR->node), RR->uPtr, tPtr, -1, reinterpret_cast<const ZT_InetAddress *>(&tmp), p, ZT_PROTO_MIN_PACKET_LENGTH, 0); RR->cb.wirePacketSendFunction(reinterpret_cast<ZT_Node *>(RR->node), RR->uPtr, cc.tPtr, -1, reinterpret_cast<const ZT_InetAddress *>(&tmp), p, ZT_PROTO_MIN_PACKET_LENGTH, 0);
} }
return ZT_PROTO_MIN_PACKET_LENGTH * numPorts; return ZT_PROTO_MIN_PACKET_LENGTH * numPorts;
} else { } else {
RR->cb.wirePacketSendFunction(reinterpret_cast<ZT_Node *>(RR->node), RR->uPtr, tPtr, -1, reinterpret_cast<const ZT_InetAddress *>(&atAddress), p, ZT_PROTO_MIN_PACKET_LENGTH, 0); RR->cb.wirePacketSendFunction(reinterpret_cast<ZT_Node *>(RR->node), RR->uPtr, cc.tPtr, -1, reinterpret_cast<const ZT_InetAddress *>(&atAddress), p, ZT_PROTO_MIN_PACKET_LENGTH, 0);
return ZT_PROTO_MIN_PACKET_LENGTH; return ZT_PROTO_MIN_PACKET_LENGTH;
} }
} }

View file

@ -77,7 +77,7 @@ public:
* @param peerIdentity The peer's identity * @param peerIdentity The peer's identity
* @return True if initialization was succcesful * @return True if initialization was succcesful
*/ */
bool init(const Identity &peerIdentity); bool init(CallContext &cc, const Identity &peerIdentity);
/** /**
* @return This peer's ZT address (short for identity().address()) * @return This peer's ZT address (short for identity().address())
@ -113,7 +113,7 @@ public:
ZT_INLINE SharedPtr< const Locator > setLocator(const SharedPtr< const Locator > &loc, bool verify) noexcept ZT_INLINE SharedPtr< const Locator > setLocator(const SharedPtr< const Locator > &loc, bool verify) noexcept
{ {
RWMutex::Lock l(m_lock); RWMutex::Lock l(m_lock);
if ((loc) && ((!m_locator) || (m_locator->timestamp() < loc->timestamp()))) { if ((loc) && ((!m_locator) || (m_locator->revision() < loc->revision()))) {
if ((!verify) || loc->verify(m_id)) if ((!verify) || loc->verify(m_id))
m_locator = loc; m_locator = loc;
} }
@ -126,7 +126,6 @@ public:
* This is called by the decode pipe when a packet is proven to be authentic * This is called by the decode pipe when a packet is proven to be authentic
* and appears to be valid. * and appears to be valid.
* *
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param path Path over which packet was received * @param path Path over which packet was received
* @param hops ZeroTier (not IP) hops * @param hops ZeroTier (not IP) hops
* @param packetId Packet ID * @param packetId Packet ID
@ -134,7 +133,7 @@ public:
* @param inReVerb In-reply verb for OK or ERROR verbs * @param inReVerb In-reply verb for OK or ERROR verbs
*/ */
void received( void received(
void *tPtr, CallContext &cc,
const SharedPtr< Path > &path, const SharedPtr< Path > &path,
unsigned int hops, unsigned int hops,
uint64_t packetId, uint64_t packetId,
@ -145,38 +144,36 @@ public:
/** /**
* Log sent data * Log sent data
* *
* @param now Current time
* @param bytes Number of bytes written * @param bytes Number of bytes written
*/ */
ZT_INLINE void sent(const int64_t now, const unsigned int bytes) noexcept ZT_INLINE void sent(CallContext &cc, const unsigned int bytes) noexcept
{ {
m_lastSend = now; m_lastSend = cc.ticks;
m_outMeter.log(now, bytes); m_outMeter.log(cc.ticks, bytes);
} }
/** /**
* Called when traffic destined for a different peer is sent to this one * Called when traffic destined for a different peer is sent to this one
* *
* @param now Current time
* @param bytes Number of bytes relayed * @param bytes Number of bytes relayed
*/ */
ZT_INLINE void relayed(const int64_t now, const unsigned int bytes) noexcept ZT_INLINE void relayed(CallContext &cc, const unsigned int bytes) noexcept
{ m_relayedMeter.log(now, bytes); } { m_relayedMeter.log(cc.ticks, bytes); }
/** /**
* Get the current best direct path or NULL if none * Get the current best direct path or NULL if none
* *
* @return Current best path or NULL if there is no direct path * @return Current best path or NULL if there is no direct path
*/ */
ZT_INLINE SharedPtr< Path > path(const int64_t now) noexcept ZT_INLINE SharedPtr< Path > path(CallContext &cc) noexcept
{ {
if (likely((now - m_lastPrioritizedPaths) < ZT_PEER_PRIORITIZE_PATHS_INTERVAL)) { if (likely((cc.ticks - m_lastPrioritizedPaths) < ZT_PEER_PRIORITIZE_PATHS_INTERVAL)) {
RWMutex::RLock l(m_lock); RWMutex::RLock l(m_lock);
if (m_alivePathCount > 0) if (m_alivePathCount > 0)
return m_paths[0]; return m_paths[0];
} else { } else {
RWMutex::Lock l(m_lock); RWMutex::Lock l(m_lock);
m_prioritizePaths(now); m_prioritizePaths(cc);
if (m_alivePathCount > 0) if (m_alivePathCount > 0)
return m_paths[0]; return m_paths[0];
} }
@ -186,16 +183,14 @@ public:
/** /**
* Send data to this peer over a specific path only * Send data to this peer over a specific path only
* *
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param now Current time
* @param data Data to send * @param data Data to send
* @param len Length in bytes * @param len Length in bytes
* @param via Path over which to send data (may or may not be an already-learned path for this peer) * @param via Path over which to send data (may or may not be an already-learned path for this peer)
*/ */
ZT_INLINE void send(void *tPtr, int64_t now, const void *data, unsigned int len, const SharedPtr< Path > &via) noexcept ZT_INLINE void send(CallContext &cc, const void *data, unsigned int len, const SharedPtr< Path > &via) noexcept
{ {
via->send(RR, tPtr, data, len, now); via->send(RR, cc, data, len);
sent(now, len); sent(cc, len);
} }
/** /**
@ -204,42 +199,34 @@ public:
* If there is a working direct path it will be used. Otherwise the data will be * If there is a working direct path it will be used. Otherwise the data will be
* sent via a root server. * sent via a root server.
* *
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param now Current time
* @param data Data to send * @param data Data to send
* @param len Length in bytes * @param len Length in bytes
*/ */
void send(void *tPtr, int64_t now, const void *data, unsigned int len) noexcept; void send(CallContext &cc, const void *data, unsigned int len) noexcept;
/** /**
* Send a HELLO to this peer at a specified physical address. * Send a HELLO to this peer at a specified physical address.
* *
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param localSocket Local source socket * @param localSocket Local source socket
* @param atAddress Destination address * @param atAddress Destination address
* @param now Current time
* @return Number of bytes sent * @return Number of bytes sent
*/ */
unsigned int hello(void *tPtr, int64_t localSocket, const InetAddress &atAddress, int64_t now); unsigned int hello(CallContext &cc, int64_t localSocket, const InetAddress &atAddress);
/** /**
* Ping this peer if needed and/or perform other periodic tasks. * Ping this peer if needed and/or perform other periodic tasks.
* *
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param now Current time
* @param isRoot True if this peer is a root * @param isRoot True if this peer is a root
*/ */
void pulse(void *tPtr, int64_t now, bool isRoot); void pulse(CallContext &cc, bool isRoot);
/** /**
* Attempt to contact this peer at a given endpoint. * Attempt to contact this peer at a given endpoint.
* *
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param now Current time
* @param ep Endpoint to attempt to contact * @param ep Endpoint to attempt to contact
* @param tries Number of times to try (default: 1) * @param tries Number of times to try (default: 1)
*/ */
void contact(void *tPtr, int64_t now, const Endpoint &ep, int tries = 1); void contact(CallContext &cc, const Endpoint &ep, int tries = 1);
/** /**
* Reset paths within a given IP scope and address family * Reset paths within a given IP scope and address family
@ -249,12 +236,10 @@ public:
* to our external IP or another system change that might invalidate * to our external IP or another system change that might invalidate
* many or all current paths. * many or all current paths.
* *
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param scope IP scope * @param scope IP scope
* @param inetAddressFamily Family e.g. AF_INET * @param inetAddressFamily Family e.g. AF_INET
* @param now Current time
*/ */
void resetWithinScope(void *tPtr, InetAddress::IpScope scope, int inetAddressFamily, int64_t now); void resetWithinScope(CallContext &cc, InetAddress::IpScope scope, int inetAddressFamily);
/** /**
* @return Time of last receive of anything, whether direct or relayed * @return Time of last receive of anything, whether direct or relayed
@ -372,7 +357,7 @@ public:
/** /**
* @return True if there is at least one alive direct path * @return True if there is at least one alive direct path
*/ */
bool directlyConnected(int64_t now); bool directlyConnected(CallContext &cc);
/** /**
* Get all paths * Get all paths
@ -384,7 +369,7 @@ public:
/** /**
* Save the latest version of this peer to the data store * Save the latest version of this peer to the data store
*/ */
void save(void *tPtr) const; void save(CallContext &cc) const;
// NOTE: peer marshal/unmarshal only saves/restores the identity, locator, most // NOTE: peer marshal/unmarshal only saves/restores the identity, locator, most
// recent bootstrap address, and version information. // recent bootstrap address, and version information.
@ -393,15 +378,15 @@ public:
int marshal(uint8_t data[ZT_PEER_MARSHAL_SIZE_MAX]) const noexcept; int marshal(uint8_t data[ZT_PEER_MARSHAL_SIZE_MAX]) const noexcept;
int unmarshal(const uint8_t *restrict data, int len) noexcept; int unmarshal(int64_t ticks, const uint8_t *restrict data, int len) noexcept;
/** /**
* Rate limit gate for inbound WHOIS requests * Rate limit gate for inbound WHOIS requests
*/ */
ZT_INLINE bool rateGateInboundWhoisRequest(const int64_t now) noexcept ZT_INLINE bool rateGateInboundWhoisRequest(CallContext &cc) noexcept
{ {
if ((now - m_lastWhoisRequestReceived) >= ZT_PEER_WHOIS_RATE_LIMIT) { if ((cc.ticks - m_lastWhoisRequestReceived) >= ZT_PEER_WHOIS_RATE_LIMIT) {
m_lastWhoisRequestReceived = now; m_lastWhoisRequestReceived = cc.ticks;
return true; return true;
} }
return false; return false;
@ -410,10 +395,10 @@ public:
/** /**
* Rate limit gate for inbound ECHO requests * Rate limit gate for inbound ECHO requests
*/ */
ZT_INLINE bool rateGateEchoRequest(const int64_t now) noexcept ZT_INLINE bool rateGateEchoRequest(CallContext &cc) noexcept
{ {
if ((now - m_lastEchoRequestReceived) >= ZT_PEER_GENERAL_RATE_LIMIT) { if ((cc.ticks - m_lastEchoRequestReceived) >= ZT_PEER_GENERAL_RATE_LIMIT) {
m_lastEchoRequestReceived = now; m_lastEchoRequestReceived = cc.ticks;
return true; return true;
} }
return false; return false;
@ -422,10 +407,10 @@ public:
/** /**
* Rate limit gate for inbound probes * Rate limit gate for inbound probes
*/ */
ZT_INLINE bool rateGateProbeRequest(const int64_t now) noexcept ZT_INLINE bool rateGateProbeRequest(CallContext &cc) noexcept
{ {
if ((now - m_lastProbeReceived) > ZT_PEER_PROBE_RESPONSE_RATE_LIMIT) { if ((cc.ticks - m_lastProbeReceived) > ZT_PEER_PROBE_RESPONSE_RATE_LIMIT) {
m_lastProbeReceived = now; m_lastProbeReceived = cc.ticks;
return true; return true;
} }
return false; return false;
@ -447,10 +432,8 @@ public:
} }
private: private:
void m_prioritizePaths(int64_t now); void m_prioritizePaths(CallContext &cc);
unsigned int m_sendProbe(CallContext &cc, int64_t localSocket, const InetAddress &atAddress, const uint16_t *ports, unsigned int numPorts);
unsigned int m_sendProbe(void *tPtr, int64_t localSocket, const InetAddress &atAddress, const uint16_t *ports, unsigned int numPorts, int64_t now);
void m_deriveSecondaryIdentityKeys() noexcept; void m_deriveSecondaryIdentityKeys() noexcept;
ZT_INLINE SharedPtr< SymmetricKey > m_key() noexcept ZT_INLINE SharedPtr< SymmetricKey > m_key() noexcept

View file

@ -110,8 +110,8 @@ public:
* @param RR Runtime environment to provide for peer lookup, etc. * @param RR Runtime environment to provide for peer lookup, etc.
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
*/ */
ZT_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR, void *tPtr) const noexcept ZT_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR, CallContext &cc) const noexcept
{ return s_verify(RR, tPtr, *this); } { return s_verify(RR, cc, *this); }
static constexpr int marshalSizeMax() noexcept static constexpr int marshalSizeMax() noexcept
{ return ZT_REVOCATION_MARSHAL_SIZE_MAX; } { return ZT_REVOCATION_MARSHAL_SIZE_MAX; }

View file

@ -39,19 +39,26 @@ class Salsa20 : public TriviallyCopyable
{ {
public: public:
#ifdef ZT_SALSA20_SSE #ifdef ZT_SALSA20_SSE
static constexpr bool accelerated() noexcept { return true; }
static constexpr bool accelerated() noexcept
{ return true; }
#else #else
static constexpr bool accelerated() noexcept { return false; } static constexpr bool accelerated() noexcept { return false; }
#endif #endif
ZT_INLINE Salsa20() noexcept {} ZT_INLINE Salsa20() noexcept
ZT_INLINE ~Salsa20() noexcept { Utils::burn(&_state,sizeof(_state)); } {}
ZT_INLINE ~Salsa20() noexcept
{ Utils::burn(&_state, sizeof(_state)); }
/** /**
* @param key 256-bit (32 byte) key * @param key 256-bit (32 byte) key
* @param iv 64-bit initialization vector * @param iv 64-bit initialization vector
*/ */
ZT_INLINE Salsa20(const void *key,const void *iv) noexcept { init(key,iv); } ZT_INLINE Salsa20(const void *key, const void *iv) noexcept
{ init(key, iv); }
/** /**
* Initialize cipher * Initialize cipher
@ -59,7 +66,7 @@ public:
* @param key Key bits * @param key Key bits
* @param iv 64-bit initialization vector * @param iv 64-bit initialization vector
*/ */
void init(const void *key,const void *iv) noexcept; void init(const void *key, const void *iv) noexcept;
/** /**
* Encrypt/decrypt data using Salsa20/12 * Encrypt/decrypt data using Salsa20/12
@ -68,7 +75,7 @@ public:
* @param out Output buffer * @param out Output buffer
* @param bytes Length of data * @param bytes Length of data
*/ */
void crypt12(const void *in,void *out,unsigned int bytes) noexcept; void crypt12(const void *in, void *out, unsigned int bytes) noexcept;
/** /**
* Encrypt/decrypt data using Salsa20/20 * Encrypt/decrypt data using Salsa20/20
@ -77,10 +84,11 @@ public:
* @param out Output buffer * @param out Output buffer
* @param bytes Length of data * @param bytes Length of data
*/ */
void crypt20(const void *in,void *out,unsigned int bytes) noexcept; void crypt20(const void *in, void *out, unsigned int bytes) noexcept;
private: private:
union { union
{
#ifdef ZT_SALSA20_SSE #ifdef ZT_SALSA20_SSE
__m128i v[4]; __m128i v[4];
#endif // ZT_SALSA20_SSE #endif // ZT_SALSA20_SSE

View file

@ -84,6 +84,6 @@ namespace std {
template< typename T > template< typename T >
ZT_INLINE void swap(ZeroTier::ScopedPtr< T > &a, ZeroTier::ScopedPtr< T > &b) noexcept ZT_INLINE void swap(ZeroTier::ScopedPtr< T > &a, ZeroTier::ScopedPtr< T > &b) noexcept
{ a.swap(b); } { a.swap(b); }
} } // namespace std
#endif #endif

View file

@ -24,32 +24,12 @@
namespace ZeroTier { namespace ZeroTier {
class _ResetWithinScope
{
public:
ZT_INLINE _ResetWithinScope(void *tPtr, int64_t now, int inetAddressFamily, InetAddress::IpScope scope) :
_now(now),
_tPtr(tPtr),
_family(inetAddressFamily),
_scope(scope)
{}
ZT_INLINE void operator()(const SharedPtr< Peer > &p)
{ p->resetWithinScope(_tPtr, _scope, _family, _now); }
private:
int64_t _now;
void *_tPtr;
int _family;
InetAddress::IpScope _scope;
};
SelfAwareness::SelfAwareness(const RuntimeEnvironment *renv) : SelfAwareness::SelfAwareness(const RuntimeEnvironment *renv) :
RR(renv) RR(renv)
{ {
} }
void SelfAwareness::iam(void *tPtr, const Identity &reporter, const int64_t receivedOnLocalSocket, const InetAddress &reporterPhysicalAddress, const InetAddress &myPhysicalAddress, bool trusted, int64_t now) void SelfAwareness::iam(CallContext &cc, const Identity &reporter, const int64_t receivedOnLocalSocket, const InetAddress &reporterPhysicalAddress, const InetAddress &myPhysicalAddress, bool trusted)
{ {
const InetAddress::IpScope scope = myPhysicalAddress.ipScope(); const InetAddress::IpScope scope = myPhysicalAddress.ipScope();
@ -59,10 +39,10 @@ void SelfAwareness::iam(void *tPtr, const Identity &reporter, const int64_t rece
Mutex::Lock l(m_phy_l); Mutex::Lock l(m_phy_l);
p_PhySurfaceEntry &entry = m_phy[p_PhySurfaceKey(reporter.address(), receivedOnLocalSocket, reporterPhysicalAddress, scope)]; p_PhySurfaceEntry &entry = m_phy[p_PhySurfaceKey(reporter.address(), receivedOnLocalSocket, reporterPhysicalAddress, scope)];
if ((trusted) && ((now - entry.ts) < ZT_SELFAWARENESS_ENTRY_TIMEOUT) && (!entry.mySurface.ipsEqual(myPhysicalAddress))) { if ((trusted) && ((cc.ticks - entry.timestampTicks) < ZT_SELFAWARENESS_ENTRY_TIMEOUT) && (!entry.mySurface.ipsEqual(myPhysicalAddress))) {
// Changes to external surface reported by trusted peers causes path reset in this scope // Changes to external surface reported by trusted peers causes path reset in this scope
entry.mySurface = myPhysicalAddress; entry.mySurface = myPhysicalAddress;
entry.ts = now; entry.timestampTicks = cc.ticks;
entry.trusted = trusted; entry.trusted = trusted;
// Erase all entries in this scope that were not reported from this remote address to prevent 'thrashing' // Erase all entries in this scope that were not reported from this remote address to prevent 'thrashing'
@ -78,28 +58,28 @@ void SelfAwareness::iam(void *tPtr, const Identity &reporter, const int64_t rece
Vector< SharedPtr< Peer > > peers, rootPeers; Vector< SharedPtr< Peer > > peers, rootPeers;
RR->topology->allPeers(peers, rootPeers); RR->topology->allPeers(peers, rootPeers);
for(Vector< SharedPtr< Peer > >::const_iterator p(peers.begin());p!=peers.end();++p) for(Vector< SharedPtr< Peer > >::const_iterator p(peers.begin());p!=peers.end();++p)
(*p)->resetWithinScope(tPtr, (InetAddress::IpScope)scope, myPhysicalAddress.family(), now); (*p)->resetWithinScope(cc, (InetAddress::IpScope)scope, myPhysicalAddress.as.sa.sa_family);
RR->t->resettingPathsInScope(tPtr, 0x9afff100, reporter, reporterPhysicalAddress, entry.mySurface, myPhysicalAddress, scope); RR->t->resettingPathsInScope(cc, 0x9afff100, reporter, reporterPhysicalAddress, entry.mySurface, myPhysicalAddress, scope);
} else { } else {
// Otherwise just update DB to use to determine external surface info // Otherwise just update DB to use to determine external surface info
entry.mySurface = myPhysicalAddress; entry.mySurface = myPhysicalAddress;
entry.ts = now; entry.timestampTicks = cc.ticks;
entry.trusted = trusted; entry.trusted = trusted;
} }
} }
void SelfAwareness::clean(int64_t now) void SelfAwareness::clean(CallContext &cc)
{ {
Mutex::Lock l(m_phy_l); Mutex::Lock l(m_phy_l);
for (Map< p_PhySurfaceKey, p_PhySurfaceEntry >::iterator i(m_phy.begin()); i != m_phy.end();) { for (Map< p_PhySurfaceKey, p_PhySurfaceEntry >::iterator i(m_phy.begin()); i != m_phy.end();) {
if ((now - i->second.ts) >= ZT_SELFAWARENESS_ENTRY_TIMEOUT) if ((cc.ticks - i->second.timestampTicks) >= ZT_SELFAWARENESS_ENTRY_TIMEOUT)
m_phy.erase(i++); m_phy.erase(i++);
else ++i; else ++i;
} }
} }
MultiMap< unsigned int, InetAddress > SelfAwareness::externalAddresses(const int64_t now) const MultiMap< unsigned int, InetAddress > SelfAwareness::externalAddresses(CallContext &cc) const
{ {
MultiMap< unsigned int, InetAddress > r; MultiMap< unsigned int, InetAddress > r;
@ -108,7 +88,7 @@ MultiMap< unsigned int, InetAddress > SelfAwareness::externalAddresses(const int
{ {
Mutex::Lock l(m_phy_l); Mutex::Lock l(m_phy_l);
for (Map< p_PhySurfaceKey, p_PhySurfaceEntry >::const_iterator i(m_phy.begin()); i != m_phy.end(); ++i) { for (Map< p_PhySurfaceKey, p_PhySurfaceEntry >::const_iterator i(m_phy.begin()); i != m_phy.end(); ++i) {
if ((now - i->second.ts) < ZT_SELFAWARENESS_ENTRY_TIMEOUT) if ((cc.ticks - i->second.timestampTicks) < ZT_SELFAWARENESS_ENTRY_TIMEOUT)
++counts[i->second.mySurface]; ++counts[i->second.mySurface];
} }
} }

View file

@ -19,6 +19,7 @@
#include "Containers.hpp" #include "Containers.hpp"
#include "Address.hpp" #include "Address.hpp"
#include "Mutex.hpp" #include "Mutex.hpp"
#include "CallContext.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -44,24 +45,20 @@ public:
* @param reporterPhysicalAddress Physical address that reporting peer seems to have * @param reporterPhysicalAddress Physical address that reporting peer seems to have
* @param myPhysicalAddress Physical address that peer says we have * @param myPhysicalAddress Physical address that peer says we have
* @param trusted True if this peer is trusted as an authority to inform us of external address changes * @param trusted True if this peer is trusted as an authority to inform us of external address changes
* @param now Current time
*/ */
void iam(void *tPtr, const Identity &reporter, int64_t receivedOnLocalSocket, const InetAddress &reporterPhysicalAddress, const InetAddress &myPhysicalAddress, bool trusted, int64_t now); void iam(CallContext &cc, const Identity &reporter, int64_t receivedOnLocalSocket, const InetAddress &reporterPhysicalAddress, const InetAddress &myPhysicalAddress, bool trusted);
/** /**
* Clean up database periodically * Clean up database periodically
*
* @param now Current time
*/ */
void clean(int64_t now); void clean(CallContext &cc);
/** /**
* Get external address consensus, which is the statistical "mode" of external addresses. * Get external address consensus, which is the statistical "mode" of external addresses.
* *
* @param now Current time
* @return Map of count to IP/port representing how many endpoints reported each address * @return Map of count to IP/port representing how many endpoints reported each address
*/ */
MultiMap< unsigned int, InetAddress > externalAddresses(int64_t now) const; MultiMap< unsigned int, InetAddress > externalAddresses(CallContext &cc) const;
private: private:
struct p_PhySurfaceKey struct p_PhySurfaceKey
@ -108,13 +105,13 @@ private:
struct p_PhySurfaceEntry struct p_PhySurfaceEntry
{ {
InetAddress mySurface; InetAddress mySurface;
int64_t ts; int64_t timestampTicks;
bool trusted; bool trusted;
ZT_INLINE p_PhySurfaceEntry() noexcept: mySurface(), ts(0), trusted(false) ZT_INLINE p_PhySurfaceEntry() noexcept: mySurface(), timestampTicks(0), trusted(false)
{} {}
ZT_INLINE p_PhySurfaceEntry(const InetAddress &a, const int64_t t) noexcept: mySurface(a), ts(t), trusted(false) ZT_INLINE p_PhySurfaceEntry(const InetAddress &a, const int64_t t) noexcept: mySurface(a), timestampTicks(t), trusted(false)
{} {}
}; };

View file

@ -33,7 +33,7 @@ public:
{} {}
explicit ZT_INLINE SharedPtr(T *obj) noexcept: m_ptr(obj) explicit ZT_INLINE SharedPtr(T *obj) noexcept: m_ptr(obj)
{ if (likely(obj != nullptr)) const_cast<std::atomic< int > *>(&(obj->__refCount))->fetch_add(1, std::memory_order_relaxed); } { if (likely(obj != nullptr)) const_cast<std::atomic< int > *>(&(obj->__refCount))->fetch_add(1, std::memory_order_acquire); }
ZT_INLINE SharedPtr(const SharedPtr &sp) noexcept: m_ptr(sp._getAndInc()) ZT_INLINE SharedPtr(const SharedPtr &sp) noexcept: m_ptr(sp._getAndInc())
{} {}
@ -54,7 +54,7 @@ public:
ZT_INLINE void set(T *ptr) noexcept ZT_INLINE void set(T *ptr) noexcept
{ {
_release(); _release();
const_cast<std::atomic< int > *>(&((m_ptr = ptr)->__refCount))->fetch_add(1, std::memory_order_relaxed); const_cast<std::atomic< int > *>(&((m_ptr = ptr)->__refCount))->fetch_add(1, std::memory_order_acquire);
} }
/** /**
@ -122,7 +122,7 @@ public:
{ {
if (likely(m_ptr != nullptr)) { if (likely(m_ptr != nullptr)) {
int one = 1; int one = 1;
if (const_cast<std::atomic< int > *>(&(m_ptr->__refCount))->compare_exchange_strong(one, (int)0)) { if (const_cast<std::atomic< int > *>(&(m_ptr->__refCount))->compare_exchange_strong(one, (int)0, std::memory_order_acq_rel)) {
delete m_ptr; delete m_ptr;
m_ptr = nullptr; m_ptr = nullptr;
return true; return true;
@ -145,14 +145,6 @@ public:
return 0; return 0;
} }
/**
* Cast this SharedPtr<> to one that holds a const instance of the type
*
* @return "this" casted in place to hold "const T"
*/
ZT_INLINE const SharedPtr<const T> &constify() const noexcept
{ return reinterpret_cast< const SharedPtr<const T> >(*this); }
ZT_INLINE unsigned long hashCode() const noexcept ZT_INLINE unsigned long hashCode() const noexcept
{ return (unsigned long)Utils::hash64((uint64_t)((uintptr_t)m_ptr)); } { return (unsigned long)Utils::hash64((uint64_t)((uintptr_t)m_ptr)); }
@ -178,13 +170,13 @@ private:
ZT_INLINE T *_getAndInc() const noexcept ZT_INLINE T *_getAndInc() const noexcept
{ {
if (likely(m_ptr != nullptr)) if (likely(m_ptr != nullptr))
const_cast<std::atomic< int > *>(&(m_ptr->__refCount))->fetch_add(1, std::memory_order_relaxed); const_cast<std::atomic< int > *>(&(m_ptr->__refCount))->fetch_add(1, std::memory_order_acquire);
return m_ptr; return m_ptr;
} }
ZT_INLINE void _release() const noexcept ZT_INLINE void _release() const noexcept
{ {
if (unlikely((m_ptr != nullptr)&&(const_cast<std::atomic< int > *>(&(m_ptr->__refCount))->fetch_sub(1, std::memory_order_relaxed) <= 1))) if (unlikely((m_ptr != nullptr)&&(const_cast<std::atomic< int > *>(&(m_ptr->__refCount))->fetch_sub(1, std::memory_order_release) <= 1)))
delete m_ptr; delete m_ptr;
} }
@ -197,9 +189,13 @@ private:
namespace std { namespace std {
template< typename T > template< typename T >
ZT_INLINE void swap(ZeroTier::SharedPtr< T > &a, ZeroTier::SharedPtr< T > &b) noexcept ZT_MAYBE_UNUSED ZT_INLINE void swap(ZeroTier::SharedPtr< T > &a, ZeroTier::SharedPtr< T > &b) noexcept
{ a.swap(b); } { a.swap(b); }
template< typename T >
ZT_MAYBE_UNUSED ZT_INLINE void move(ZeroTier::SharedPtr< T > &a, ZeroTier::SharedPtr< T > &b) noexcept
{ a.move(b); }
} // namespace std } // namespace std
#endif #endif

View file

@ -17,6 +17,7 @@
#include "Constants.hpp" #include "Constants.hpp"
#include "Containers.hpp" #include "Containers.hpp"
#include "RuntimeEnvironment.hpp" #include "RuntimeEnvironment.hpp"
#include "CallContext.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -32,18 +33,17 @@ public:
/** /**
* Get a state object * Get a state object
* *
* @param tPtr Thread pointer to pass through
* @param type Object type * @param type Object type
* @param id Object ID * @param id Object ID
* @param idSize Size of object ID in qwords * @param idSize Size of object ID in qwords
* @return Data or empty vector if not found * @return Data or empty vector if not found
*/ */
ZT_INLINE Vector< uint8_t > get(void *tPtr, ZT_StateObjectType type, const uint64_t *id, unsigned int idSize) const ZT_INLINE Vector< uint8_t > get(CallContext &cc, ZT_StateObjectType type, const uint64_t *id, unsigned int idSize) const
{ {
Vector< uint8_t > dv; Vector< uint8_t > dv;
void *data = nullptr; void *data = nullptr;
void (*freeFunc)(void *) = nullptr; void (*freeFunc)(void *) = nullptr;
const int r = RR->cb.stateGetFunction(reinterpret_cast<ZT_Node *>(RR->node), RR->uPtr, tPtr, type, id, idSize, &data, &freeFunc); const int r = RR->cb.stateGetFunction(reinterpret_cast<ZT_Node *>(RR->node), RR->uPtr, cc.tPtr, type, id, idSize, &data, &freeFunc);
if (r > 0) if (r > 0)
dv.assign(reinterpret_cast<const uint8_t *>(data), reinterpret_cast<const uint8_t *>(data) + r); dv.assign(reinterpret_cast<const uint8_t *>(data), reinterpret_cast<const uint8_t *>(data) + r);
if ((data) && (freeFunc)) if ((data) && (freeFunc))
@ -54,26 +54,24 @@ public:
/** /**
* Store a state object * Store a state object
* *
* @param tPtr Thread pointer to pass through
* @param type Object type * @param type Object type
* @param id Object ID * @param id Object ID
* @param idSize Size of object ID in qwords * @param idSize Size of object ID in qwords
* @param data Data to store * @param data Data to store
* @param len Length of data * @param len Length of data
*/ */
ZT_INLINE void put(void *const tPtr, ZT_StateObjectType type, const uint64_t *const id, const unsigned int idSize, const void *const data, const unsigned int len) noexcept ZT_INLINE void put(CallContext &cc, ZT_StateObjectType type, const uint64_t *const id, const unsigned int idSize, const void *const data, const unsigned int len) noexcept
{ RR->cb.statePutFunction(reinterpret_cast<ZT_Node *>(this), RR->uPtr, tPtr, type, id, idSize, data, (int)len); } { RR->cb.statePutFunction(reinterpret_cast<ZT_Node *>(this), RR->uPtr, cc.tPtr, type, id, idSize, data, (int)len); }
/** /**
* Erase a state object from the object store * Erase a state object from the object store
* *
* @param tPtr Thread pointer to pass through
* @param type Object type * @param type Object type
* @param id Object ID * @param id Object ID
* @param idSize Size of object ID in qwords * @param idSize Size of object ID in qwords
*/ */
ZT_INLINE void erase(void *const tPtr, ZT_StateObjectType type, const uint64_t *const id, const unsigned int idSize) noexcept ZT_INLINE void erase(CallContext &cc, ZT_StateObjectType type, const uint64_t *const id, const unsigned int idSize) noexcept
{ RR->cb.statePutFunction(reinterpret_cast<ZT_Node *>(this), RR->uPtr, tPtr, type, id, idSize, nullptr, -1); } { RR->cb.statePutFunction(reinterpret_cast<ZT_Node *>(this), RR->uPtr, cc.tPtr, type, id, idSize, nullptr, -1); }
private: private:
const RuntimeEnvironment *RR; const RuntimeEnvironment *RR;

View file

@ -84,6 +84,9 @@ public:
ZT_INLINE int64_t timestamp() const noexcept ZT_INLINE int64_t timestamp() const noexcept
{ return m_ts; } { return m_ts; }
ZT_INLINE int64_t revision() const noexcept
{ return m_ts; }
ZT_INLINE const Address &issuedTo() const noexcept ZT_INLINE const Address &issuedTo() const noexcept
{ return m_issuedTo; } { return m_issuedTo; }
@ -110,8 +113,8 @@ public:
* @param RR Runtime environment to allow identity lookup for signedBy * @param RR Runtime environment to allow identity lookup for signedBy
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
*/ */
ZT_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR, void *tPtr) const noexcept ZT_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR, CallContext &cc) const noexcept
{ return s_verify(RR, tPtr, *this); } { return s_verify(RR, cc, *this); }
static constexpr int marshalSizeMax() noexcept static constexpr int marshalSizeMax() noexcept
{ return ZT_TAG_MARSHAL_SIZE_MAX; } { return ZT_TAG_MARSHAL_SIZE_MAX; }

View file

@ -13,20 +13,22 @@
#include "Topology.hpp" #include "Topology.hpp"
#include "Defaults.hpp" #include "Defaults.hpp"
#include "TrustStore.hpp"
#include "Locator.hpp"
namespace ZeroTier { namespace ZeroTier {
Topology::Topology(const RuntimeEnvironment *renv, void *tPtr, const int64_t now) : Topology::Topology(const RuntimeEnvironment *renv, CallContext &cc) :
RR(renv) RR(renv)
{} {}
SharedPtr< Peer > Topology::add(void *tPtr, const SharedPtr< Peer > &peer) SharedPtr< Peer > Topology::add(CallContext &cc, const SharedPtr< Peer > &peer)
{ {
RWMutex::Lock _l(m_peers_l); RWMutex::Lock _l(m_peers_l);
SharedPtr< Peer > &hp = m_peers[peer->address()]; SharedPtr< Peer > &hp = m_peers[peer->address()];
if (hp) if (hp)
return hp; return hp;
m_loadCached(tPtr, peer->address(), hp); m_loadCached(cc, peer->address(), hp);
if (hp) if (hp)
return hp; return hp;
hp = peer; hp = peer;
@ -48,13 +50,13 @@ void Topology::allPeers(Vector< SharedPtr< Peer > > &allPeers, Vector< SharedPtr
} }
} }
void Topology::doPeriodicTasks(void *tPtr, const int64_t now) void Topology::doPeriodicTasks(CallContext &cc)
{ {
// Get a list of root peer pointer addresses for filtering during peer cleanup. // Get a list of root peer pointer addresses for filtering during peer cleanup.
Vector< uintptr_t > rootLookup; Vector< uintptr_t > rootLookup;
{ {
Mutex::Lock l(m_roots_l); Mutex::Lock l(m_roots_l);
m_rankRoots(now); m_rankRoots();
rootLookup.reserve(m_roots.size()); rootLookup.reserve(m_roots.size());
for (Vector< SharedPtr< Peer > >::const_iterator r(m_roots.begin()); r != m_roots.end(); ++r) for (Vector< SharedPtr< Peer > >::const_iterator r(m_roots.begin()); r != m_roots.end(); ++r)
rootLookup.push_back((uintptr_t)r->ptr()); rootLookup.push_back((uintptr_t)r->ptr());
@ -69,7 +71,7 @@ void Topology::doPeriodicTasks(void *tPtr, const int64_t now)
RWMutex::RLock l1(m_peers_l); RWMutex::RLock l1(m_peers_l);
for (Map< Address, SharedPtr< Peer > >::iterator i(m_peers.begin()); i != m_peers.end(); ++i) { for (Map< Address, SharedPtr< Peer > >::iterator i(m_peers.begin()); i != m_peers.end(); ++i) {
// TODO: also delete if the peer has not exchanged meaningful communication in a while, such as a network frame or non-trivial control packet. // TODO: also delete if the peer has not exchanged meaningful communication in a while, such as a network frame or non-trivial control packet.
if (((now - i->second->lastReceive()) > ZT_PEER_ALIVE_TIMEOUT) && (std::find(rootLookup.begin(), rootLookup.end(), (uintptr_t)(i->second.ptr())) == rootLookup.end())) if (((cc.ticks - i->second->lastReceive()) > ZT_PEER_ALIVE_TIMEOUT) && (std::find(rootLookup.begin(), rootLookup.end(), (uintptr_t)(i->second.ptr())) == rootLookup.end()))
toDelete.push_back(i->first); toDelete.push_back(i->first);
} }
} }
@ -86,7 +88,7 @@ void Topology::doPeriodicTasks(void *tPtr, const int64_t now)
} }
} }
if (toSave) if (toSave)
toSave->save(tPtr); toSave->save(cc);
} }
} }
} }
@ -117,11 +119,37 @@ void Topology::doPeriodicTasks(void *tPtr, const int64_t now)
} }
} }
void Topology::saveAll(void *tPtr) void Topology::trustStoreChanged(CallContext &cc)
{
Map< Identity, SharedPtr< const Locator > > roots(RR->ts->roots());
Vector< SharedPtr< Peer > > newRootList;
newRootList.reserve(roots.size());
for (Map< Identity, SharedPtr< const Locator > >::const_iterator r(roots.begin()); r != roots.end(); ++r) {
SharedPtr< Peer > root(this->peer(cc, r->first.address(), true));
if (!root) {
root.set(new Peer(RR));
root->init(cc, r->first);
root = this->add(cc, root);
}
newRootList.push_back(root);
if (r->second)
root->setLocator(r->second, true);
}
{
Mutex::Lock l(m_roots_l);
m_roots.swap(newRootList);
m_rankRoots();
}
}
void Topology::saveAll(CallContext &cc)
{ {
RWMutex::RLock l(m_peers_l); RWMutex::RLock l(m_peers_l);
for (Map< Address, SharedPtr< Peer > >::iterator i(m_peers.begin()); i != m_peers.end(); ++i) for (Map< Address, SharedPtr< Peer > >::iterator i(m_peers.begin()); i != m_peers.end(); ++i)
i->second->save(tPtr); i->second->save(cc);
} }
struct p_RootRankingComparisonOperator struct p_RootRankingComparisonOperator
@ -147,7 +175,7 @@ struct p_RootRankingComparisonOperator
} }
}; };
void Topology::m_rankRoots(const int64_t now) void Topology::m_rankRoots()
{ {
// assumes m_roots is locked // assumes m_roots is locked
if (unlikely(m_roots.empty())) { if (unlikely(m_roots.empty())) {
@ -162,7 +190,7 @@ void Topology::m_rankRoots(const int64_t now)
} }
} }
void Topology::m_loadCached(void *tPtr, const Address &zta, SharedPtr< Peer > &peer) void Topology::m_loadCached(CallContext &cc, const Address &zta, SharedPtr< Peer > &peer)
{ {
// does not require any locks to be held // does not require any locks to be held
@ -170,19 +198,19 @@ void Topology::m_loadCached(void *tPtr, const Address &zta, SharedPtr< Peer > &p
uint64_t id[2]; uint64_t id[2];
id[0] = zta.toInt(); id[0] = zta.toInt();
id[1] = 0; id[1] = 0;
Vector< uint8_t > data(RR->store->get(tPtr, ZT_STATE_OBJECT_PEER, id, 1)); Vector< uint8_t > data(RR->store->get(cc, ZT_STATE_OBJECT_PEER, id, 1));
if (data.size() > 8) { if (data.size() > 8) {
const uint8_t *d = data.data(); const uint8_t *d = data.data();
int dl = (int)data.size(); int dl = (int)data.size();
const int64_t ts = (int64_t)Utils::loadBigEndian< uint64_t >(d); const int64_t ts = (int64_t)Utils::loadBigEndian< uint64_t >(d);
Peer *const p = new Peer(RR); Peer *const p = new Peer(RR);
int n = p->unmarshal(d + 8, dl - 8); int n = p->unmarshal(cc.ticks, d + 8, dl - 8);
if (n < 0) { if (n < 0) {
delete p; delete p;
return; return;
} }
if ((RR->node->now() - ts) < ZT_PEER_GLOBAL_TIMEOUT) { if ((cc.ticks - ts) < ZT_PEER_GLOBAL_TIMEOUT) {
// TODO: handle many peers, same address (?) // TODO: handle many peers, same address (?)
peer.set(p); peer.set(p);
return; return;
@ -193,10 +221,10 @@ void Topology::m_loadCached(void *tPtr, const Address &zta, SharedPtr< Peer > &p
} }
} }
SharedPtr< Peer > Topology::m_peerFromCached(void *tPtr, const Address &zta) SharedPtr< Peer > Topology::m_peerFromCached(CallContext &cc, const Address &zta)
{ {
SharedPtr< Peer > p; SharedPtr< Peer > p;
m_loadCached(tPtr, zta, p); m_loadCached(cc, zta, p);
if (p) { if (p) {
RWMutex::Lock l(m_peers_l); RWMutex::Lock l(m_peers_l);
SharedPtr< Peer > &hp = m_peers[zta]; SharedPtr< Peer > &hp = m_peers[zta];

View file

@ -28,6 +28,7 @@
#include "Certificate.hpp" #include "Certificate.hpp"
#include "Containers.hpp" #include "Containers.hpp"
#include "Spinlock.hpp" #include "Spinlock.hpp"
#include "CallContext.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -39,7 +40,7 @@ class RuntimeEnvironment;
class Topology class Topology
{ {
public: public:
Topology(const RuntimeEnvironment *renv, void *tPtr, int64_t now); Topology(const RuntimeEnvironment *renv, CallContext &cc);
/** /**
* Add peer to database * Add peer to database
@ -47,21 +48,19 @@ public:
* This will not replace existing peers. In that case the existing peer * This will not replace existing peers. In that case the existing peer
* record is returned. * record is returned.
* *
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param peer Peer to add * @param peer Peer to add
* @return New or existing peer (should replace 'peer') * @return New or existing peer (should replace 'peer')
*/ */
SharedPtr< Peer > add(void *tPtr, const SharedPtr< Peer > &peer); SharedPtr< Peer > add(CallContext &cc, const SharedPtr< Peer > &peer);
/** /**
* Get a peer from its address * Get a peer from its address
* *
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param zta ZeroTier address of peer * @param zta ZeroTier address of peer
* @param loadFromCached If false do not load from cache if not in memory (default: true) * @param loadFromCached If false do not load from cache if not in memory (default: true)
* @return Peer or NULL if not found * @return Peer or NULL if not found
*/ */
ZT_INLINE SharedPtr< Peer > peer(void *tPtr, const Address &zta, const bool loadFromCached = true) ZT_INLINE SharedPtr< Peer > peer(CallContext &cc, const Address &zta, const bool loadFromCached = true)
{ {
{ {
RWMutex::RLock l(m_peers_l); RWMutex::RLock l(m_peers_l);
@ -70,7 +69,7 @@ public:
return ap->second; return ap->second;
} }
if (loadFromCached) if (loadFromCached)
return m_peerFromCached(tPtr, zta); return m_peerFromCached(cc, zta);
return SharedPtr< Peer >(); return SharedPtr< Peer >();
} }
@ -125,34 +124,34 @@ public:
/** /**
* Do periodic tasks such as database cleanup, cert cleanup, root ranking, etc. * Do periodic tasks such as database cleanup, cert cleanup, root ranking, etc.
*
* @param tPtr Thread pointer
* @param now Current time
*/ */
void doPeriodicTasks(void *tPtr, int64_t now); void doPeriodicTasks(CallContext &cc);
/** /**
* Rank root servers in descending order of quality * Rank root servers in descending order of quality
* *
* @param now Current time * @param now Current time
*/ */
ZT_INLINE void rankRoots(int64_t now) ZT_INLINE void rankRoots(CallContext &cc)
{ {
Mutex::Lock l(m_roots_l); Mutex::Lock l(m_roots_l);
m_rankRoots(now); m_rankRoots();
} }
/** /**
* Save all currently known peers to data store * Perform internal updates based on changes in the trust store
*
* @param tPtr Thread pointer
*/ */
void saveAll(void *tPtr); void trustStoreChanged(CallContext &cc);
/**
* Save all currently known peers to data store
*/
void saveAll(CallContext &cc);
private: private:
void m_rankRoots(int64_t now); void m_rankRoots();
void m_loadCached(void *tPtr, const Address &zta, SharedPtr< Peer > &peer); void m_loadCached(CallContext &cc, const Address &zta, SharedPtr< Peer > &peer);
SharedPtr< Peer > m_peerFromCached(void *tPtr, const Address &zta); SharedPtr< Peer > m_peerFromCached(CallContext &cc, const Address &zta);
SharedPtr< Path > m_newPath(int64_t l, const InetAddress &r, const Path::Key &k); SharedPtr< Path > m_newPath(int64_t l, const InetAddress &r, const Path::Key &k);
const RuntimeEnvironment *const RR; const RuntimeEnvironment *const RR;

View file

@ -29,7 +29,7 @@ Trace::Trace(const RuntimeEnvironment *renv) :
} }
void Trace::unexpectedError( void Trace::unexpectedError(
void *tPtr, CallContext &cc,
uint32_t codeLocation, uint32_t codeLocation,
const char *message, const char *message,
...) ...)
@ -39,17 +39,17 @@ void Trace::unexpectedError(
Dictionary::append(buf, ZT_TRACE_FIELD_CODE_LOCATION, codeLocation); Dictionary::append(buf, ZT_TRACE_FIELD_CODE_LOCATION, codeLocation);
Dictionary::append(buf, ZT_TRACE_FIELD_MESSAGE, message); Dictionary::append(buf, ZT_TRACE_FIELD_MESSAGE, message);
buf.push_back(0); buf.push_back(0);
RR->node->postEvent(tPtr, ZT_EVENT_TRACE, buf.data()); RR->node->postEvent(cc.tPtr, ZT_EVENT_TRACE, buf.data());
} }
void Trace::_resettingPathsInScope( void Trace::m_resettingPathsInScope(
void *const tPtr, void *tPtr,
const uint32_t codeLocation, uint32_t codeLocation,
const Identity &reporter, const Identity &reporter,
const InetAddress &from, const InetAddress &from,
const InetAddress &oldExternal, const InetAddress &oldExternal,
const InetAddress &newExternal, const InetAddress &newExternal,
const InetAddress::IpScope scope) ZT_InetAddress_IpScope scope)
{ {
FCV< uint8_t, 4096 > buf; FCV< uint8_t, 4096 > buf;
Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL1_RESETTING_PATHS_IN_SCOPE); Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL1_RESETTING_PATHS_IN_SCOPE);
@ -67,14 +67,14 @@ void Trace::_resettingPathsInScope(
RR->node->postEvent(tPtr, ZT_EVENT_TRACE, buf.data()); RR->node->postEvent(tPtr, ZT_EVENT_TRACE, buf.data());
} }
void Trace::_tryingNewPath( void Trace::m_tryingNewPath(
void *const tPtr, void *tPtr,
const uint32_t codeLocation, uint32_t codeLocation,
const Identity &trying, const Identity &trying,
const InetAddress &physicalAddress, const InetAddress &physicalAddress,
const InetAddress &triggerAddress, const InetAddress &triggerAddress,
const uint64_t triggeringPacketId, uint64_t triggeringPacketId,
const uint8_t triggeringPacketVerb, uint8_t triggeringPacketVerb,
const Identity &triggeringPeer) const Identity &triggeringPeer)
{ {
if ((trying)&&(physicalAddress)) { if ((trying)&&(physicalAddress)) {
@ -94,10 +94,10 @@ void Trace::_tryingNewPath(
} }
} }
void Trace::_learnedNewPath( void Trace::m_learnedNewPath(
void *const tPtr, void *tPtr,
const uint32_t codeLocation, uint32_t codeLocation,
const uint64_t packetId, uint64_t packetId,
const Identity &peerIdentity, const Identity &peerIdentity,
const InetAddress &physicalAddress, const InetAddress &physicalAddress,
const InetAddress &replaced) const InetAddress &replaced)
@ -117,16 +117,16 @@ void Trace::_learnedNewPath(
} }
} }
void Trace::_incomingPacketDropped( void Trace::m_incomingPacketDropped(
void *const tPtr, void *tPtr,
const uint32_t codeLocation, uint32_t codeLocation,
const uint64_t packetId, uint64_t packetId,
const uint64_t networkId, uint64_t networkId,
const Identity &peerIdentity, const Identity &peerIdentity,
const InetAddress &physicalAddress, const InetAddress &physicalAddress,
const uint8_t hops, uint8_t hops,
const uint8_t verb, uint8_t verb,
const ZT_TracePacketDropReason reason) ZT_TracePacketDropReason reason)
{ {
FCV< uint8_t, 4096 > buf; FCV< uint8_t, 4096 > buf;
Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL1_INCOMING_PACKET_DROPPED); Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL1_INCOMING_PACKET_DROPPED);
@ -144,16 +144,16 @@ void Trace::_incomingPacketDropped(
RR->node->postEvent(tPtr, ZT_EVENT_TRACE, buf.data()); RR->node->postEvent(tPtr, ZT_EVENT_TRACE, buf.data());
} }
void Trace::_outgoingNetworkFrameDropped( void Trace::m_outgoingNetworkFrameDropped(
void *const tPtr, void *tPtr,
const uint32_t codeLocation, uint32_t codeLocation,
const uint64_t networkId, uint64_t networkId,
const MAC &sourceMac, const MAC &sourceMac,
const MAC &destMac, const MAC &destMac,
const uint16_t etherType, uint16_t etherType,
const uint16_t frameLength, uint16_t frameLength,
const uint8_t *frameData, const uint8_t *frameData,
const ZT_TraceFrameDropReason reason) ZT_TraceFrameDropReason reason)
{ {
FCV< uint8_t, 4096 > buf; FCV< uint8_t, 4096 > buf;
Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL1_INCOMING_PACKET_DROPPED); Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL1_INCOMING_PACKET_DROPPED);
@ -170,21 +170,21 @@ void Trace::_outgoingNetworkFrameDropped(
RR->node->postEvent(tPtr, ZT_EVENT_TRACE, buf.data()); RR->node->postEvent(tPtr, ZT_EVENT_TRACE, buf.data());
} }
void Trace::_incomingNetworkFrameDropped( void Trace::m_incomingNetworkFrameDropped(
void *const tPtr, void *tPtr,
const uint32_t codeLocation, uint32_t codeLocation,
const uint64_t networkId, uint64_t networkId,
const MAC &sourceMac, const MAC &sourceMac,
const MAC &destMac, const MAC &destMac,
const uint16_t etherType, const uint16_t etherType,
const Identity &peerIdentity, const Identity &peerIdentity,
const InetAddress &physicalAddress, const InetAddress &physicalAddress,
const uint8_t hops, uint8_t hops,
const uint16_t frameLength, uint16_t frameLength,
const uint8_t *frameData, const uint8_t *frameData,
const uint8_t verb, uint8_t verb,
const bool credentialRequestSent, bool credentialRequestSent,
const ZT_TraceFrameDropReason reason) ZT_TraceFrameDropReason reason)
{ {
FCV< uint8_t, 4096 > buf; FCV< uint8_t, 4096 > buf;
Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL2_INCOMING_FRAME_DROPPED); Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL2_INCOMING_FRAME_DROPPED);
@ -207,10 +207,10 @@ void Trace::_incomingNetworkFrameDropped(
RR->node->postEvent(tPtr, ZT_EVENT_TRACE, buf.data()); RR->node->postEvent(tPtr, ZT_EVENT_TRACE, buf.data());
} }
void Trace::_networkConfigRequestSent( void Trace::m_networkConfigRequestSent(
void *const tPtr, void *tPtr,
const uint32_t codeLocation, uint32_t codeLocation,
const uint64_t networkId) uint64_t networkId)
{ {
FCV< uint8_t, 4096 > buf; FCV< uint8_t, 4096 > buf;
Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL2_NETWORK_CONFIG_REQUESTED); Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL2_NETWORK_CONFIG_REQUESTED);
@ -220,25 +220,25 @@ void Trace::_networkConfigRequestSent(
RR->node->postEvent(tPtr, ZT_EVENT_TRACE, buf.data()); RR->node->postEvent(tPtr, ZT_EVENT_TRACE, buf.data());
} }
void Trace::_networkFilter( void Trace::m_networkFilter(
void *const tPtr, void *tPtr,
const uint32_t codeLocation, uint32_t codeLocation,
const uint64_t networkId, uint64_t networkId,
const uint8_t primaryRuleSetLog[512], const uint8_t *primaryRuleSetLog,
const uint8_t matchingCapabilityRuleSetLog[512], const uint8_t *matchingCapabilityRuleSetLog,
const uint32_t matchingCapabilityId, uint32_t matchingCapabilityId,
const int64_t matchingCapabilityTimestamp, int64_t matchingCapabilityTimestamp,
const Address &source, const Address &source,
const Address &dest, const Address &dest,
const MAC &sourceMac, const MAC &sourceMac,
const MAC &destMac, const MAC &destMac,
const uint16_t frameLength, uint16_t frameLength,
const uint8_t *frameData, const uint8_t *frameData,
const uint16_t etherType, uint16_t etherType,
const uint16_t vlanId, uint16_t vlanId,
const bool noTee, bool noTee,
const bool inbound, bool inbound,
const int accept) int accept)
{ {
FCV< uint8_t, 4096 > buf; FCV< uint8_t, 4096 > buf;
Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL2_NETWORK_FILTER); Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL2_NETWORK_FILTER);
@ -266,15 +266,15 @@ void Trace::_networkFilter(
RR->node->postEvent(tPtr, ZT_EVENT_TRACE, buf.data()); RR->node->postEvent(tPtr, ZT_EVENT_TRACE, buf.data());
} }
void Trace::_credentialRejected( void Trace::m_credentialRejected(
void *const tPtr, void *tPtr,
const uint32_t codeLocation, uint32_t codeLocation,
const uint64_t networkId, uint64_t networkId,
const Identity &identity, const Identity &identity,
const uint32_t credentialId, uint32_t credentialId,
const int64_t credentialTimestamp, int64_t credentialTimestamp,
const uint8_t credentialType, uint8_t credentialType,
const ZT_TraceCredentialRejectionReason reason) ZT_TraceCredentialRejectionReason reason)
{ {
FCV< uint8_t, 4096 > buf; FCV< uint8_t, 4096 > buf;
Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL2_NETWORK_CREDENTIAL_REJECTED); Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL2_NETWORK_CREDENTIAL_REJECTED);

View file

@ -22,6 +22,7 @@
#include "MAC.hpp" #include "MAC.hpp"
#include "Containers.hpp" #include "Containers.hpp"
#include "Utils.hpp" #include "Utils.hpp"
#include "CallContext.hpp"
#define ZT_TRACE_F_VL1 0x01U #define ZT_TRACE_F_VL1 0x01U
#define ZT_TRACE_F_VL2 0x02U #define ZT_TRACE_F_VL2 0x02U
@ -31,25 +32,15 @@
namespace ZeroTier { namespace ZeroTier {
class RuntimeEnvironment; class RuntimeEnvironment;
class Identity; class Identity;
class Peer; class Peer;
class Path; class Path;
class Network; class Network;
class MembershipCredential; class MembershipCredential;
class OwnershipCredential; class OwnershipCredential;
class RevocationCredential; class RevocationCredential;
class TagCredential; class TagCredential;
class CapabilityCredential; class CapabilityCredential;
struct NetworkConfig; struct NetworkConfig;
/** /**
@ -73,31 +64,25 @@ public:
uint8_t l[ZT_MAX_NETWORK_RULES / 2]; // ZT_MAX_NETWORK_RULES 4-bit fields uint8_t l[ZT_MAX_NETWORK_RULES / 2]; // ZT_MAX_NETWORK_RULES 4-bit fields
ZT_INLINE void log(const unsigned int rn, const uint8_t thisRuleMatches, const uint8_t thisSetMatches) noexcept ZT_INLINE void log(const unsigned int rn, const uint8_t thisRuleMatches, const uint8_t thisSetMatches) noexcept
{ { l[rn >> 1U] |= (((thisRuleMatches + 1U) << 2U) | (thisSetMatches + 1U)) << ((rn & 1U) << 2U); }
l[rn >> 1U] |= (((thisRuleMatches + 1U) << 2U) | (thisSetMatches + 1U)) << ((rn & 1U) << 2U);
}
ZT_INLINE void logSkipped(const unsigned int rn, const uint8_t thisSetMatches) noexcept ZT_INLINE void logSkipped(const unsigned int rn, const uint8_t thisSetMatches) noexcept
{ { l[rn >> 1U] |= (thisSetMatches + 1U) << ((rn & 1U) << 2U); }
l[rn >> 1U] |= (thisSetMatches + 1U) << ((rn & 1U) << 2U);
}
ZT_INLINE void clear() noexcept ZT_INLINE void clear() noexcept
{ { memoryZero(this); }
memoryZero(this);
}
}; };
explicit Trace(const RuntimeEnvironment *renv); explicit Trace(const RuntimeEnvironment *renv);
void unexpectedError( void unexpectedError(
void *tPtr, CallContext &cc,
uint32_t codeLocation, uint32_t codeLocation,
const char *message, const char *message,
...); ...);
ZT_INLINE void resettingPathsInScope( ZT_INLINE void resettingPathsInScope(
void *const tPtr, CallContext &cc,
const uint32_t codeLocation, const uint32_t codeLocation,
const Identity &reporter, const Identity &reporter,
const InetAddress &from, const InetAddress &from,
@ -105,12 +90,12 @@ public:
const InetAddress &newExternal, const InetAddress &newExternal,
const InetAddress::IpScope scope) const InetAddress::IpScope scope)
{ {
if ((m_traceFlags & ZT_TRACE_F_VL1) != 0) if (unlikely((m_traceFlags & ZT_TRACE_F_VL1) != 0))
_resettingPathsInScope(tPtr, codeLocation, reporter, from, oldExternal, newExternal, scope); m_resettingPathsInScope(cc.tPtr, codeLocation, reporter, from, oldExternal, newExternal, scope);
} }
ZT_INLINE void tryingNewPath( ZT_INLINE void tryingNewPath(
void *const tPtr, CallContext &cc,
const uint32_t codeLocation, const uint32_t codeLocation,
const Identity &trying, const Identity &trying,
const InetAddress &physicalAddress, const InetAddress &physicalAddress,
@ -119,24 +104,24 @@ public:
uint8_t triggeringPacketVerb, uint8_t triggeringPacketVerb,
const Identity &triggeringPeer) const Identity &triggeringPeer)
{ {
if ((m_traceFlags & ZT_TRACE_F_VL1) != 0) if (unlikely((m_traceFlags & ZT_TRACE_F_VL1) != 0))
_tryingNewPath(tPtr, codeLocation, trying, physicalAddress, triggerAddress, triggeringPacketId, triggeringPacketVerb, triggeringPeer); m_tryingNewPath(cc.tPtr, codeLocation, trying, physicalAddress, triggerAddress, triggeringPacketId, triggeringPacketVerb, triggeringPeer);
} }
ZT_INLINE void learnedNewPath( ZT_INLINE void learnedNewPath(
void *const tPtr, CallContext &cc,
const uint32_t codeLocation, const uint32_t codeLocation,
uint64_t packetId, uint64_t packetId,
const Identity &peerIdentity, const Identity &peerIdentity,
const InetAddress &physicalAddress, const InetAddress &physicalAddress,
const InetAddress &replaced) const InetAddress &replaced)
{ {
if ((m_traceFlags & ZT_TRACE_F_VL1) != 0) if (unlikely((m_traceFlags & ZT_TRACE_F_VL1) != 0))
_learnedNewPath(tPtr, codeLocation, packetId, peerIdentity, physicalAddress, replaced); m_learnedNewPath(cc.tPtr, codeLocation, packetId, peerIdentity, physicalAddress, replaced);
} }
ZT_INLINE void incomingPacketDropped( ZT_INLINE void incomingPacketDropped(
void *const tPtr, CallContext &cc,
const uint32_t codeLocation, const uint32_t codeLocation,
uint64_t packetId, uint64_t packetId,
uint64_t networkId, uint64_t networkId,
@ -146,12 +131,12 @@ public:
uint8_t verb, uint8_t verb,
const ZT_TracePacketDropReason reason) const ZT_TracePacketDropReason reason)
{ {
if ((m_traceFlags & ZT_TRACE_F_VL1) != 0) if (unlikely((m_traceFlags & ZT_TRACE_F_VL1) != 0))
_incomingPacketDropped(tPtr, codeLocation, packetId, networkId, peerIdentity, physicalAddress, hops, verb, reason); m_incomingPacketDropped(cc.tPtr, codeLocation, packetId, networkId, peerIdentity, physicalAddress, hops, verb, reason);
} }
ZT_INLINE void outgoingNetworkFrameDropped( ZT_INLINE void outgoingNetworkFrameDropped(
void *const tPtr, CallContext &cc,
const uint32_t codeLocation, const uint32_t codeLocation,
uint64_t networkId, uint64_t networkId,
const MAC &sourceMac, const MAC &sourceMac,
@ -161,12 +146,12 @@ public:
const uint8_t *frameData, const uint8_t *frameData,
ZT_TraceFrameDropReason reason) ZT_TraceFrameDropReason reason)
{ {
if ((m_traceFlags & ZT_TRACE_F_VL2) != 0) if (unlikely((m_traceFlags & ZT_TRACE_F_VL2) != 0))
_outgoingNetworkFrameDropped(tPtr, codeLocation, networkId, sourceMac, destMac, etherType, frameLength, frameData, reason); m_outgoingNetworkFrameDropped(cc.tPtr, codeLocation, networkId, sourceMac, destMac, etherType, frameLength, frameData, reason);
} }
ZT_INLINE void incomingNetworkFrameDropped( ZT_INLINE void incomingNetworkFrameDropped(
void *const tPtr, CallContext &cc,
const uint32_t codeLocation, const uint32_t codeLocation,
uint64_t networkId, uint64_t networkId,
const MAC &sourceMac, const MAC &sourceMac,
@ -181,21 +166,21 @@ public:
bool credentialRequestSent, bool credentialRequestSent,
ZT_TraceFrameDropReason reason) ZT_TraceFrameDropReason reason)
{ {
if ((m_traceFlags & ZT_TRACE_F_VL2) != 0) if (unlikely((m_traceFlags & ZT_TRACE_F_VL2) != 0))
_incomingNetworkFrameDropped(tPtr, codeLocation, networkId, sourceMac, destMac, etherType, peerIdentity, physicalAddress, hops, frameLength, frameData, verb, credentialRequestSent, reason); m_incomingNetworkFrameDropped(cc.tPtr, codeLocation, networkId, sourceMac, destMac, etherType, peerIdentity, physicalAddress, hops, frameLength, frameData, verb, credentialRequestSent, reason);
} }
ZT_INLINE void networkConfigRequestSent( ZT_INLINE void networkConfigRequestSent(
void *const tPtr, CallContext &cc,
const uint32_t codeLocation, const uint32_t codeLocation,
uint64_t networkId) uint64_t networkId)
{ {
if ((m_traceFlags & ZT_TRACE_F_VL2) != 0) if (unlikely((m_traceFlags & ZT_TRACE_F_VL2) != 0))
_networkConfigRequestSent(tPtr, codeLocation, networkId); m_networkConfigRequestSent(cc.tPtr, codeLocation, networkId);
} }
ZT_INLINE void networkFilter( ZT_INLINE void networkFilter(
void *const tPtr, CallContext &cc,
const uint32_t codeLocation, const uint32_t codeLocation,
uint64_t networkId, uint64_t networkId,
const uint8_t primaryRuleSetLog[512], const uint8_t primaryRuleSetLog[512],
@ -214,9 +199,9 @@ public:
bool inbound, bool inbound,
int accept) int accept)
{ {
if ((m_traceFlags & ZT_TRACE_F_VL2_FILTER) != 0) { if (unlikely((m_traceFlags & ZT_TRACE_F_VL2_FILTER) != 0)) {
_networkFilter( m_networkFilter(
tPtr, cc.tPtr,
codeLocation, codeLocation,
networkId, networkId,
primaryRuleSetLog, primaryRuleSetLog,
@ -238,7 +223,7 @@ public:
} }
ZT_INLINE void credentialRejected( ZT_INLINE void credentialRejected(
void *const tPtr, CallContext &cc,
const uint32_t codeLocation, const uint32_t codeLocation,
uint64_t networkId, uint64_t networkId,
const Identity &identity, const Identity &identity,
@ -247,12 +232,12 @@ public:
uint8_t credentialType, uint8_t credentialType,
ZT_TraceCredentialRejectionReason reason) ZT_TraceCredentialRejectionReason reason)
{ {
if ((m_traceFlags & ZT_TRACE_F_VL2) != 0) if (unlikely((m_traceFlags & ZT_TRACE_F_VL2) != 0))
_credentialRejected(tPtr, codeLocation, networkId, identity, credentialId, credentialTimestamp, credentialType, reason); m_credentialRejected(cc.tPtr, codeLocation, networkId, identity, credentialId, credentialTimestamp, credentialType, reason);
} }
private: private:
void _resettingPathsInScope( void m_resettingPathsInScope(
void *tPtr, void *tPtr,
uint32_t codeLocation, uint32_t codeLocation,
const Identity &reporter, const Identity &reporter,
@ -261,7 +246,7 @@ private:
const InetAddress &newExternal, const InetAddress &newExternal,
InetAddress::IpScope scope); InetAddress::IpScope scope);
void _tryingNewPath( void m_tryingNewPath(
void *tPtr, void *tPtr,
uint32_t codeLocation, uint32_t codeLocation,
const Identity &trying, const Identity &trying,
@ -271,7 +256,7 @@ private:
uint8_t triggeringPacketVerb, uint8_t triggeringPacketVerb,
const Identity &triggeringPeer); const Identity &triggeringPeer);
void _learnedNewPath( void m_learnedNewPath(
void *tPtr, void *tPtr,
uint32_t codeLocation, uint32_t codeLocation,
uint64_t packetId, uint64_t packetId,
@ -279,7 +264,7 @@ private:
const InetAddress &physicalAddress, const InetAddress &physicalAddress,
const InetAddress &replaced); const InetAddress &replaced);
void _incomingPacketDropped( void m_incomingPacketDropped(
void *tPtr, void *tPtr,
uint32_t codeLocation, uint32_t codeLocation,
uint64_t packetId, uint64_t packetId,
@ -290,7 +275,7 @@ private:
uint8_t verb, uint8_t verb,
ZT_TracePacketDropReason reason); ZT_TracePacketDropReason reason);
void _outgoingNetworkFrameDropped( void m_outgoingNetworkFrameDropped(
void *tPtr, void *tPtr,
uint32_t codeLocation, uint32_t codeLocation,
uint64_t networkId, uint64_t networkId,
@ -301,7 +286,7 @@ private:
const uint8_t *frameData, const uint8_t *frameData,
ZT_TraceFrameDropReason reason); ZT_TraceFrameDropReason reason);
void _incomingNetworkFrameDropped( void m_incomingNetworkFrameDropped(
void *tPtr, void *tPtr,
uint32_t codeLocation, uint32_t codeLocation,
uint64_t networkId, uint64_t networkId,
@ -317,17 +302,17 @@ private:
bool credentialRequestSent, bool credentialRequestSent,
ZT_TraceFrameDropReason reason); ZT_TraceFrameDropReason reason);
void _networkConfigRequestSent( void m_networkConfigRequestSent(
void *tPtr, void *tPtr,
uint32_t codeLocation, uint32_t codeLocation,
uint64_t networkId); uint64_t networkId);
void _networkFilter( void m_networkFilter(
void *tPtr, void *tPtr,
uint32_t codeLocation, uint32_t codeLocation,
uint64_t networkId, uint64_t networkId,
const uint8_t primaryRuleSetLog[512], const uint8_t *primaryRuleSetLog,
const uint8_t matchingCapabilityRuleSetLog[512], const uint8_t *matchingCapabilityRuleSetLog,
uint32_t matchingCapabilityId, uint32_t matchingCapabilityId,
int64_t matchingCapabilityTimestamp, int64_t matchingCapabilityTimestamp,
const Address &source, const Address &source,
@ -342,7 +327,7 @@ private:
bool inbound, bool inbound,
int accept); int accept);
void _credentialRejected( void m_credentialRejected(
void *tPtr, void *tPtr,
uint32_t codeLocation, uint32_t codeLocation,
uint64_t networkId, uint64_t networkId,

View file

@ -41,7 +41,7 @@ Map< Identity, SharedPtr< const Locator > > TrustStore::roots()
if (likely((id != nullptr) && (*id))) { // sanity check if (likely((id != nullptr) && (*id))) { // sanity check
SharedPtr< const Locator > &existingLoc = r[*id]; SharedPtr< const Locator > &existingLoc = r[*id];
const Locator *const loc = reinterpret_cast<const Locator *>((*c)->certificate().subject.identities[j].locator); const Locator *const loc = reinterpret_cast<const Locator *>((*c)->certificate().subject.identities[j].locator);
if ((loc != nullptr) && ((!existingLoc) || (existingLoc->timestamp() < loc->timestamp()))) if ((loc != nullptr) && ((!existingLoc) || (existingLoc->revision() < loc->revision())))
existingLoc.set(new Locator(*loc)); existingLoc.set(new Locator(*loc));
} }
} }
@ -63,17 +63,6 @@ Vector< SharedPtr< TrustStore::Entry > > TrustStore::all(const bool includeRejec
return r; return r;
} }
Vector< SharedPtr< TrustStore::Entry > > TrustStore::rejects() const
{
RWMutex::RLock l(m_lock);
Vector< SharedPtr< Entry > > r;
for (Map< H384, SharedPtr< Entry > >::const_iterator c(m_bySerial.begin()); c != m_bySerial.end(); ++c) {
if (c->second->error() != ZT_CERTIFICATE_ERROR_NONE)
r.push_back(c->second);
}
return r;
}
void TrustStore::add(const Certificate &cert, const unsigned int localTrust) void TrustStore::add(const Certificate &cert, const unsigned int localTrust)
{ {
RWMutex::Lock l(m_lock); RWMutex::Lock l(m_lock);
@ -105,7 +94,7 @@ static bool p_validatePath(const Map< H384, Vector< SharedPtr< TrustStore::Entry
return false; return false;
} }
void TrustStore::update(const int64_t clock, Vector< SharedPtr< Entry > > *const purge) bool TrustStore::update(const int64_t clock, Vector< SharedPtr< Entry > > *const purge)
{ {
RWMutex::Lock l(m_lock); RWMutex::Lock l(m_lock);
@ -113,15 +102,21 @@ void TrustStore::update(const int64_t clock, Vector< SharedPtr< Entry > > *const
// signature check here since that's done when they're taken out of the add queue. // signature check here since that's done when they're taken out of the add queue.
bool errorStateModified = false; bool errorStateModified = false;
for (Map< H384, SharedPtr< Entry > >::const_iterator c(m_bySerial.begin()); c != m_bySerial.end(); ++c) { for (Map< H384, SharedPtr< Entry > >::const_iterator c(m_bySerial.begin()); c != m_bySerial.end(); ++c) {
const ZT_CertificateError err = c->second->m_certificate.verify(clock, false); const ZT_CertificateError err = c->second->error();
errorStateModified |= (c->second->m_error.exchange((int)err, std::memory_order_relaxed) != (int)err); if ((err != ZT_CERTIFICATE_ERROR_HAVE_NEWER_CERT) && (err != ZT_CERTIFICATE_ERROR_INVALID_CHAIN)) {
const ZT_CertificateError newErr = c->second->m_certificate.verify(clock, false);
if (newErr != err) {
c->second->m_error.store((int)newErr, std::memory_order_relaxed);
errorStateModified = true;
}
}
} }
// If no certificate error statuses changed and there are no new certificates to // If no certificate error statuses changed and there are no new certificates to
// add, there is nothing to do and we don't need to do more expensive path validation // add, there is nothing to do and we don't need to do more expensive path validation
// and structure rebuilding. // and structure rebuilding.
if ((!errorStateModified) && (m_addQueue.empty()) && (m_deleteQueue.empty())) if ((!errorStateModified) && (m_addQueue.empty()) && (m_deleteQueue.empty()))
return; return false;
// Add new certificates to m_bySerial, which is the master certificate set. They still // Add new certificates to m_bySerial, which is the master certificate set. They still
// have yet to have their full certificate chains validated. Full signature checking is // have yet to have their full certificate chains validated. Full signature checking is
@ -164,8 +159,8 @@ void TrustStore::update(const int64_t clock, Vector< SharedPtr< Entry > > *const
for (Map< H384, SharedPtr< Entry > >::const_iterator c(m_bySerial.begin()); c != m_bySerial.end();) { for (Map< H384, SharedPtr< Entry > >::const_iterator c(m_bySerial.begin()); c != m_bySerial.end();) {
if (c->second->error() == ZT_CERTIFICATE_ERROR_NONE) { if (c->second->error() == ZT_CERTIFICATE_ERROR_NONE) {
const unsigned int uniqueIdSize = c->second->m_certificate.subject.uniqueIdSize; const unsigned int uniqueIdSize = c->second->m_certificate.subject.uniqueIdSize;
if ((uniqueIdSize > 0) && (uniqueIdSize <= 1024)) { // 1024 is a sanity check value, actual unique IDs are <100 bytes if ((uniqueIdSize > 0) && (uniqueIdSize <= ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE)) {
SharedPtr< Entry > &current = m_bySubjectUniqueId[Vector< uint8_t >(c->second->m_certificate.subject.uniqueId, c->second->m_certificate.subject.uniqueId + uniqueIdSize)]; SharedPtr< Entry > &current = m_bySubjectUniqueId[Blob< ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE >(c->second->m_certificate.subject.uniqueId, uniqueIdSize)];
if (current) { if (current) {
exitLoop = false; exitLoop = false;
if (c->second->m_certificate.subject.timestamp > current->m_certificate.subject.timestamp) { if (c->second->m_certificate.subject.timestamp > current->m_certificate.subject.timestamp) {
@ -222,6 +217,8 @@ void TrustStore::update(const int64_t clock, Vector< SharedPtr< Entry > > *const
} }
} }
} }
return true;
} }
Vector< uint8_t > TrustStore::save() const Vector< uint8_t > TrustStore::save() const

View file

@ -124,13 +124,6 @@ public:
*/ */
Vector< SharedPtr< Entry > > all(bool includeRejectedCertificates) const; Vector< SharedPtr< Entry > > all(bool includeRejectedCertificates) const;
/**
* Get a copy of the current rejected certificate set.
*
* @return Rejected certificates
*/
Vector< SharedPtr< Entry > > rejects() const;
/** /**
* Add a certificate * Add a certificate
* *
@ -161,8 +154,9 @@ public:
* *
* @param clock Current time in milliseconds since epoch, or -1 to not check times on this pass * @param clock Current time in milliseconds since epoch, or -1 to not check times on this pass
* @param purge If non-NULL, purge rejected certificates and return them in this vector (vector should be empty) * @param purge If non-NULL, purge rejected certificates and return them in this vector (vector should be empty)
* @return True if there were changes
*/ */
void update(int64_t clock, Vector< SharedPtr< Entry > > *purge); bool update(int64_t clock, Vector< SharedPtr< Entry > > *purge);
/** /**
* Create a compressed binary version of certificates and their local trust * Create a compressed binary version of certificates and their local trust
@ -184,7 +178,7 @@ public:
private: private:
Map< H384, SharedPtr< Entry > > m_bySerial; // all certificates Map< H384, SharedPtr< Entry > > m_bySerial; // all certificates
Map< Vector< uint8_t >, SharedPtr< Entry > > m_bySubjectUniqueId; // non-rejected certificates only Map< Blob< ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE >, SharedPtr< Entry > > m_bySubjectUniqueId; // non-rejected certificates only
Map< Fingerprint, Vector< SharedPtr< Entry > > > m_bySubjectIdentity; // non-rejected certificates only Map< Fingerprint, Vector< SharedPtr< Entry > > > m_bySubjectIdentity; // non-rejected certificates only
ForwardList< SharedPtr< Entry > > m_addQueue; ForwardList< SharedPtr< Entry > > m_addQueue;
ForwardList< H384 > m_deleteQueue; ForwardList< H384 > m_deleteQueue;

View file

@ -529,7 +529,7 @@ bool scopy(char *const dest, const unsigned int len, const char *const src) noex
} }
} }
uint32_t fnv1a32(const void *const data, const unsigned int len) noexcept uint32_t fnv1a32(const void *const restrict data, const unsigned int len) noexcept
{ {
uint32_t h = 0x811c9dc5; uint32_t h = 0x811c9dc5;
const uint32_t p = 0x01000193; const uint32_t p = 0x01000193;

View file

@ -546,7 +546,7 @@ static ZT_INLINE I ntoh(const I n) noexcept
* @return Loaded raw integer * @return Loaded raw integer
*/ */
template< typename I > template< typename I >
static ZT_INLINE I loadMachineEndian(const void *const p) noexcept static ZT_INLINE I loadMachineEndian(const void *const restrict p) noexcept
{ {
#ifdef ZT_NO_UNALIGNED_ACCESS #ifdef ZT_NO_UNALIGNED_ACCESS
I tmp; I tmp;
@ -566,7 +566,7 @@ static ZT_INLINE I loadMachineEndian(const void *const p) noexcept
* @param i Integer to store * @param i Integer to store
*/ */
template< typename I > template< typename I >
static ZT_INLINE void storeMachineEndian(void *const p, const I i) noexcept static ZT_INLINE void storeMachineEndian(void *const restrict p, const I i) noexcept
{ {
#ifdef ZT_NO_UNALIGNED_ACCESS #ifdef ZT_NO_UNALIGNED_ACCESS
for(unsigned int k=0;k<sizeof(I);++k) for(unsigned int k=0;k<sizeof(I);++k)
@ -584,7 +584,7 @@ static ZT_INLINE void storeMachineEndian(void *const p, const I i) noexcept
* @return Decoded integer * @return Decoded integer
*/ */
template< typename I > template< typename I >
static ZT_INLINE I loadBigEndian(const void *const p) noexcept static ZT_INLINE I loadBigEndian(const void *const restrict p) noexcept
{ {
#ifdef ZT_NO_UNALIGNED_ACCESS #ifdef ZT_NO_UNALIGNED_ACCESS
return _load_be_bysize<I,sizeof(I)>::l(reinterpret_cast<const uint8_t *>(p)); return _load_be_bysize<I,sizeof(I)>::l(reinterpret_cast<const uint8_t *>(p));
@ -601,7 +601,7 @@ static ZT_INLINE I loadBigEndian(const void *const p) noexcept
* #param i Integer to write * #param i Integer to write
*/ */
template< typename I > template< typename I >
static ZT_INLINE void storeBigEndian(void *const p, I i) noexcept static ZT_INLINE void storeBigEndian(void *const restrict p, I i) noexcept
{ {
#ifdef ZT_NO_UNALIGNED_ACCESS #ifdef ZT_NO_UNALIGNED_ACCESS
storeMachineEndian(p,hton(i)); storeMachineEndian(p,hton(i));
@ -618,7 +618,7 @@ static ZT_INLINE void storeBigEndian(void *const p, I i) noexcept
* @return Decoded integer * @return Decoded integer
*/ */
template< typename I > template< typename I >
static ZT_INLINE I loadLittleEndian(const void *const p) noexcept static ZT_INLINE I loadLittleEndian(const void *const restrict p) noexcept
{ {
#if __BYTE_ORDER == __BIG_ENDIAN || defined(ZT_NO_UNALIGNED_ACCESS) #if __BYTE_ORDER == __BIG_ENDIAN || defined(ZT_NO_UNALIGNED_ACCESS)
return _load_le_bysize<I,sizeof(I)>::l(reinterpret_cast<const uint8_t *>(p)); return _load_le_bysize<I,sizeof(I)>::l(reinterpret_cast<const uint8_t *>(p));
@ -635,7 +635,7 @@ static ZT_INLINE I loadLittleEndian(const void *const p) noexcept
* #param i Integer to write * #param i Integer to write
*/ */
template< typename I > template< typename I >
static ZT_INLINE void storeLittleEndian(void *const p, const I i) noexcept static ZT_INLINE void storeLittleEndian(void *const restrict p, const I i) noexcept
{ {
#if __BYTE_ORDER == __BIG_ENDIAN #if __BYTE_ORDER == __BIG_ENDIAN
storeMachineEndian(p,_swap_bytes_bysize<I,sizeof(I)>::s(i)); storeMachineEndian(p,_swap_bytes_bysize<I,sizeof(I)>::s(i));
@ -723,7 +723,7 @@ static ZT_INLINE void zero(void *dest, unsigned long len) noexcept
* @param len Length of data * @param len Length of data
* @return FNV1a checksum * @return FNV1a checksum
*/ */
uint32_t fnv1a32(const void *data, unsigned int len) noexcept; uint32_t fnv1a32(const void *restrict data, unsigned int len) noexcept;
/** /**
* Mix bits in a 64-bit integer (non-cryptographic, for hash tables) * Mix bits in a 64-bit integer (non-cryptographic, for hash tables)

View file

@ -99,13 +99,12 @@ VL1::VL1(const RuntimeEnvironment *renv) :
RR(renv) RR(renv)
{} {}
void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const InetAddress &fromAddr, SharedPtr< Buf > &data, const unsigned int len) noexcept void VL1::onRemotePacket(CallContext &cc, const int64_t localSocket, const InetAddress &fromAddr, SharedPtr< Buf > &data, const unsigned int len) noexcept
{ {
const SharedPtr< Path > path(RR->topology->path(localSocket, fromAddr)); const SharedPtr< Path > path(RR->topology->path(localSocket, fromAddr));
const int64_t now = RR->node->now();
ZT_SPEW("%u bytes from %s (local socket %lld)", len, fromAddr.toString().c_str(), localSocket); ZT_SPEW("%u bytes from %s (local socket %lld)", len, fromAddr.toString().c_str(), localSocket);
path->received(now, len); path->received(cc, len);
// NOTE: likely/unlikely are used here to highlight the most common code path // NOTE: likely/unlikely are used here to highlight the most common code path
// for valid data packets. This may allow the compiler to generate very slightly // for valid data packets. This may allow the compiler to generate very slightly
@ -121,7 +120,7 @@ void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const Inet
static_assert((ZT_PROTO_PACKET_DESTINATION_INDEX + ZT_ADDRESS_LENGTH) < ZT_PROTO_MIN_FRAGMENT_LENGTH, "overflow"); static_assert((ZT_PROTO_PACKET_DESTINATION_INDEX + ZT_ADDRESS_LENGTH) < ZT_PROTO_MIN_FRAGMENT_LENGTH, "overflow");
const Address destination(data->unsafeData + ZT_PROTO_PACKET_DESTINATION_INDEX); const Address destination(data->unsafeData + ZT_PROTO_PACKET_DESTINATION_INDEX);
if (destination != RR->identity.address()) { if (destination != RR->identity.address()) {
m_relay(tPtr, path, destination, data, len); m_relay(cc, path, destination, data, len);
return; return;
} }
@ -145,7 +144,7 @@ void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const Inet
len - ZT_PROTO_PACKET_FRAGMENT_PAYLOAD_START_AT, len - ZT_PROTO_PACKET_FRAGMENT_PAYLOAD_START_AT,
fragmentNo, fragmentNo,
totalFragments, totalFragments,
now, cc.ticks,
path)) { path)) {
case Defragmenter< ZT_MAX_PACKET_FRAGMENTS >::COMPLETE: case Defragmenter< ZT_MAX_PACKET_FRAGMENTS >::COMPLETE:
break; break;
@ -171,7 +170,7 @@ void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const Inet
len, len,
0, // always the zero'eth fragment 0, // always the zero'eth fragment
0, // this is specified in fragments, not in the head 0, // this is specified in fragments, not in the head
now, cc.ticks,
path)) { path)) {
case Defragmenter< ZT_MAX_PACKET_FRAGMENTS >::COMPLETE: case Defragmenter< ZT_MAX_PACKET_FRAGMENTS >::COMPLETE:
break; break;
@ -214,9 +213,9 @@ void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const Inet
ZT_SPEW("discarding packet %.16llx from %s(%s): assembled packet size: %d", packetId, source.toString().c_str(), fromAddr.toString().c_str(), pktSize); ZT_SPEW("discarding packet %.16llx from %s(%s): assembled packet size: %d", packetId, source.toString().c_str(), fromAddr.toString().c_str(), pktSize);
return; return;
} }
const SharedPtr< Peer > peer(m_HELLO(tPtr, path, *pkt, pktSize)); const SharedPtr< Peer > peer(m_HELLO(cc, path, *pkt, pktSize));
if (likely(peer)) if (likely(peer))
peer->received(tPtr, path, hops, packetId, pktSize - ZT_PROTO_PACKET_PAYLOAD_START, Protocol::VERB_HELLO, Protocol::VERB_NOP); peer->received(cc, path, hops, packetId, pktSize - ZT_PROTO_PACKET_PAYLOAD_START, Protocol::VERB_HELLO, Protocol::VERB_NOP);
return; return;
} }
@ -225,7 +224,7 @@ void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const Inet
// secrecy status. // secrecy status.
unsigned int auth = 0; unsigned int auth = 0;
SharedPtr< Peer > peer(RR->topology->peer(tPtr, source)); SharedPtr< Peer > peer(RR->topology->peer(cc, source));
if (likely(peer)) { if (likely(peer)) {
switch (cipher) { switch (cipher) {
@ -245,7 +244,7 @@ void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const Inet
static_assert((ZT_PROTO_PACKET_MAC_INDEX + 8) < ZT_PROTO_MIN_PACKET_LENGTH, "overflow"); static_assert((ZT_PROTO_PACKET_MAC_INDEX + 8) < ZT_PROTO_MIN_PACKET_LENGTH, "overflow");
if (unlikely(Utils::loadMachineEndian< uint64_t >(hdr + ZT_PROTO_PACKET_MAC_INDEX) != mac[0])) { if (unlikely(Utils::loadMachineEndian< uint64_t >(hdr + ZT_PROTO_PACKET_MAC_INDEX) != mac[0])) {
ZT_SPEW("discarding packet %.16llx from %s(%s): packet MAC failed (none/poly1305)", packetId, source.toString().c_str(), fromAddr.toString().c_str()); ZT_SPEW("discarding packet %.16llx from %s(%s): packet MAC failed (none/poly1305)", packetId, source.toString().c_str(), fromAddr.toString().c_str());
RR->t->incomingPacketDropped(tPtr, 0xcc89c812, packetId, 0, peer->identity(), path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); RR->t->incomingPacketDropped(cc, 0xcc89c812, packetId, 0, peer->identity(), path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
return; return;
} }
@ -269,7 +268,7 @@ void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const Inet
static_assert((ZT_PROTO_PACKET_MAC_INDEX + 8) < ZT_PROTO_MIN_PACKET_LENGTH, "overflow"); static_assert((ZT_PROTO_PACKET_MAC_INDEX + 8) < ZT_PROTO_MIN_PACKET_LENGTH, "overflow");
if (unlikely(Utils::loadMachineEndian< uint64_t >(hdr + ZT_PROTO_PACKET_MAC_INDEX) != mac[0])) { if (unlikely(Utils::loadMachineEndian< uint64_t >(hdr + ZT_PROTO_PACKET_MAC_INDEX) != mac[0])) {
ZT_SPEW("discarding packet %.16llx from %s(%s): packet MAC failed (salsa/poly1305)", packetId, source.toString().c_str(), fromAddr.toString().c_str()); ZT_SPEW("discarding packet %.16llx from %s(%s): packet MAC failed (salsa/poly1305)", packetId, source.toString().c_str(), fromAddr.toString().c_str());
RR->t->incomingPacketDropped(tPtr, 0xcc89c812, packetId, 0, peer->identity(), path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); RR->t->incomingPacketDropped(cc, 0xcc89c812, packetId, 0, peer->identity(), path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
return; return;
} }
@ -288,7 +287,7 @@ void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const Inet
break; break;
default: default:
RR->t->incomingPacketDropped(tPtr, 0x5b001099, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); RR->t->incomingPacketDropped(cc, 0x5b001099, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT);
return; return;
} }
} }
@ -327,7 +326,7 @@ void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const Inet
ZT_SPEW("decompressed packet: %d -> %d", pktSize, ZT_PROTO_PACKET_PAYLOAD_START + uncompressedLen); ZT_SPEW("decompressed packet: %d -> %d", pktSize, ZT_PROTO_PACKET_PAYLOAD_START + uncompressedLen);
pktSize = ZT_PROTO_PACKET_PAYLOAD_START + uncompressedLen; pktSize = ZT_PROTO_PACKET_PAYLOAD_START + uncompressedLen;
} else { } else {
RR->t->incomingPacketDropped(tPtr, 0xee9e4392, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, verb, ZT_TRACE_PACKET_DROP_REASON_INVALID_COMPRESSED_DATA); RR->t->incomingPacketDropped(cc, 0xee9e4392, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, verb, ZT_TRACE_PACKET_DROP_REASON_INVALID_COMPRESSED_DATA);
return; return;
} }
} }
@ -345,66 +344,66 @@ void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const Inet
case Protocol::VERB_NOP: case Protocol::VERB_NOP:
break; break;
case Protocol::VERB_HELLO: case Protocol::VERB_HELLO:
ok = (bool)(m_HELLO(tPtr, path, *pkt, pktSize)); ok = (bool)(m_HELLO(cc, path, *pkt, pktSize));
break; break;
case Protocol::VERB_ERROR: case Protocol::VERB_ERROR:
ok = m_ERROR(tPtr, packetId, auth, path, peer, *pkt, pktSize, inReVerb); ok = m_ERROR(cc, packetId, auth, path, peer, *pkt, pktSize, inReVerb);
break; break;
case Protocol::VERB_OK: case Protocol::VERB_OK:
ok = m_OK(tPtr, packetId, auth, path, peer, *pkt, pktSize, inReVerb); ok = m_OK(cc, packetId, auth, path, peer, *pkt, pktSize, inReVerb);
break; break;
case Protocol::VERB_WHOIS: case Protocol::VERB_WHOIS:
ok = m_WHOIS(tPtr, packetId, auth, path, peer, *pkt, pktSize); ok = m_WHOIS(cc, packetId, auth, path, peer, *pkt, pktSize);
break; break;
case Protocol::VERB_RENDEZVOUS: case Protocol::VERB_RENDEZVOUS:
ok = m_RENDEZVOUS(tPtr, packetId, auth, path, peer, *pkt, pktSize); ok = m_RENDEZVOUS(cc, packetId, auth, path, peer, *pkt, pktSize);
break; break;
case Protocol::VERB_FRAME: case Protocol::VERB_FRAME:
ok = RR->vl2->m_FRAME(tPtr, packetId, auth, path, peer, *pkt, pktSize); ok = RR->vl2->m_FRAME(cc, packetId, auth, path, peer, *pkt, pktSize);
break; break;
case Protocol::VERB_EXT_FRAME: case Protocol::VERB_EXT_FRAME:
ok = RR->vl2->m_EXT_FRAME(tPtr, packetId, auth, path, peer, *pkt, pktSize); ok = RR->vl2->m_EXT_FRAME(cc, packetId, auth, path, peer, *pkt, pktSize);
break; break;
case Protocol::VERB_ECHO: case Protocol::VERB_ECHO:
ok = m_ECHO(tPtr, packetId, auth, path, peer, *pkt, pktSize); ok = m_ECHO(cc, packetId, auth, path, peer, *pkt, pktSize);
break; break;
case Protocol::VERB_MULTICAST_LIKE: case Protocol::VERB_MULTICAST_LIKE:
ok = RR->vl2->m_MULTICAST_LIKE(tPtr, packetId, auth, path, peer, *pkt, pktSize); ok = RR->vl2->m_MULTICAST_LIKE(cc, packetId, auth, path, peer, *pkt, pktSize);
break; break;
case Protocol::VERB_NETWORK_CREDENTIALS: case Protocol::VERB_NETWORK_CREDENTIALS:
ok = RR->vl2->m_NETWORK_CREDENTIALS(tPtr, packetId, auth, path, peer, *pkt, pktSize); ok = RR->vl2->m_NETWORK_CREDENTIALS(cc, packetId, auth, path, peer, *pkt, pktSize);
break; break;
case Protocol::VERB_NETWORK_CONFIG_REQUEST: case Protocol::VERB_NETWORK_CONFIG_REQUEST:
ok = RR->vl2->m_NETWORK_CONFIG_REQUEST(tPtr, packetId, auth, path, peer, *pkt, pktSize); ok = RR->vl2->m_NETWORK_CONFIG_REQUEST(cc, packetId, auth, path, peer, *pkt, pktSize);
break; break;
case Protocol::VERB_NETWORK_CONFIG: case Protocol::VERB_NETWORK_CONFIG:
ok = RR->vl2->m_NETWORK_CONFIG(tPtr, packetId, auth, path, peer, *pkt, pktSize); ok = RR->vl2->m_NETWORK_CONFIG(cc, packetId, auth, path, peer, *pkt, pktSize);
break; break;
case Protocol::VERB_MULTICAST_GATHER: case Protocol::VERB_MULTICAST_GATHER:
ok = RR->vl2->m_MULTICAST_GATHER(tPtr, packetId, auth, path, peer, *pkt, pktSize); ok = RR->vl2->m_MULTICAST_GATHER(cc, packetId, auth, path, peer, *pkt, pktSize);
break; break;
case Protocol::VERB_MULTICAST_FRAME_deprecated: case Protocol::VERB_MULTICAST_FRAME_deprecated:
ok = RR->vl2->m_MULTICAST_FRAME_deprecated(tPtr, packetId, auth, path, peer, *pkt, pktSize); ok = RR->vl2->m_MULTICAST_FRAME_deprecated(cc, packetId, auth, path, peer, *pkt, pktSize);
break; break;
case Protocol::VERB_PUSH_DIRECT_PATHS: case Protocol::VERB_PUSH_DIRECT_PATHS:
ok = m_PUSH_DIRECT_PATHS(tPtr, packetId, auth, path, peer, *pkt, pktSize); ok = m_PUSH_DIRECT_PATHS(cc, packetId, auth, path, peer, *pkt, pktSize);
break; break;
case Protocol::VERB_USER_MESSAGE: case Protocol::VERB_USER_MESSAGE:
ok = m_USER_MESSAGE(tPtr, packetId, auth, path, peer, *pkt, pktSize); ok = m_USER_MESSAGE(cc, packetId, auth, path, peer, *pkt, pktSize);
break; break;
case Protocol::VERB_MULTICAST: case Protocol::VERB_MULTICAST:
ok = RR->vl2->m_MULTICAST(tPtr, packetId, auth, path, peer, *pkt, pktSize); ok = RR->vl2->m_MULTICAST(cc, packetId, auth, path, peer, *pkt, pktSize);
break; break;
case Protocol::VERB_ENCAP: case Protocol::VERB_ENCAP:
ok = m_ENCAP(tPtr, packetId, auth, path, peer, *pkt, pktSize); ok = m_ENCAP(cc, packetId, auth, path, peer, *pkt, pktSize);
break; break;
default: default:
RR->t->incomingPacketDropped(tPtr, 0xeeeeeff0, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, verb, ZT_TRACE_PACKET_DROP_REASON_UNRECOGNIZED_VERB); RR->t->incomingPacketDropped(cc, 0xeeeeeff0, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, verb, ZT_TRACE_PACKET_DROP_REASON_UNRECOGNIZED_VERB);
break; break;
} }
if (likely(ok)) if (likely(ok))
peer->received(tPtr, path, hops, packetId, pktSize - ZT_PROTO_PACKET_PAYLOAD_START, verb, inReVerb); peer->received(cc, path, hops, packetId, pktSize - ZT_PROTO_PACKET_PAYLOAD_START, verb, inReVerb);
} else { } else {
// If decryption and authentication were not successful, try to look up identities. // If decryption and authentication were not successful, try to look up identities.
// This is rate limited by virtue of the retry rate limit timer. // This is rate limited by virtue of the retry rate limit timer.
@ -419,27 +418,27 @@ void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const Inet
const unsigned int wpidx = wq.waitingPacketCount++ % ZT_VL1_MAX_WHOIS_WAITING_PACKETS; const unsigned int wpidx = wq.waitingPacketCount++ % ZT_VL1_MAX_WHOIS_WAITING_PACKETS;
wq.waitingPacketSize[wpidx] = (unsigned int)pktSize; wq.waitingPacketSize[wpidx] = (unsigned int)pktSize;
wq.waitingPacket[wpidx] = pkt; wq.waitingPacket[wpidx] = pkt;
sendPending = (now - wq.lastRetry) >= ZT_WHOIS_RETRY_DELAY; sendPending = (cc.ticks - wq.lastRetry) >= ZT_WHOIS_RETRY_DELAY;
} }
if (sendPending) if (sendPending)
m_sendPendingWhois(tPtr, now); m_sendPendingWhois(cc);
} }
} }
} catch (...) { } catch (...) {
RR->t->unexpectedError(tPtr, 0xea1b6dea, "unexpected exception in onRemotePacket() parsing packet from %s", path->address().toString().c_str()); RR->t->unexpectedError(cc, 0xea1b6dea, "unexpected exception in onRemotePacket() parsing packet from %s", path->address().toString().c_str());
} }
} }
void VL1::m_relay(void *tPtr, const SharedPtr< Path > &path, Address destination, SharedPtr< Buf > &pkt, int pktSize) void VL1::m_relay(CallContext &cc, const SharedPtr< Path > &path, Address destination, SharedPtr< Buf > &pkt, int pktSize)
{ {
} }
void VL1::m_sendPendingWhois(void *tPtr, int64_t now) void VL1::m_sendPendingWhois(CallContext &cc)
{ {
const SharedPtr< Peer > root(RR->topology->root()); const SharedPtr< Peer > root(RR->topology->root());
if (unlikely(!root)) if (unlikely(!root))
return; return;
const SharedPtr< Path > rootPath(root->path(now)); const SharedPtr< Path > rootPath(root->path(cc));
if (unlikely(!rootPath)) if (unlikely(!rootPath))
return; return;
@ -447,8 +446,8 @@ void VL1::m_sendPendingWhois(void *tPtr, int64_t now)
{ {
Mutex::Lock wl(m_whoisQueue_l); Mutex::Lock wl(m_whoisQueue_l);
for (Map< Address, p_WhoisQueueItem >::iterator wi(m_whoisQueue.begin()); wi != m_whoisQueue.end(); ++wi) { for (Map< Address, p_WhoisQueueItem >::iterator wi(m_whoisQueue.begin()); wi != m_whoisQueue.end(); ++wi) {
if ((now - wi->second.lastRetry) >= ZT_WHOIS_RETRY_DELAY) { if ((cc.ticks - wi->second.lastRetry) >= ZT_WHOIS_RETRY_DELAY) {
wi->second.lastRetry = now; wi->second.lastRetry = cc.ticks;
++wi->second.retries; ++wi->second.retries;
toSend.push_back(wi->first); toSend.push_back(wi->first);
} }
@ -468,13 +467,13 @@ void VL1::m_sendPendingWhois(void *tPtr, int64_t now)
p += ZT_ADDRESS_LENGTH; p += ZT_ADDRESS_LENGTH;
} }
Protocol::armor(outp, p, key, root->cipher()); Protocol::armor(outp, p, key, root->cipher());
RR->expect->sending(packetId, now); RR->expect->sending(packetId, cc.ticks);
root->send(tPtr, now, outp, p, rootPath); root->send(cc, outp, p, rootPath);
} }
} }
} }
SharedPtr< Peer > VL1::m_HELLO(void *tPtr, const SharedPtr< Path > &path, Buf &pkt, int packetSize) SharedPtr< Peer > VL1::m_HELLO(CallContext &cc, const SharedPtr< Path > &path, Buf &pkt, int packetSize)
{ {
const uint64_t packetId = Utils::loadMachineEndian< uint64_t >(pkt.unsafeData + ZT_PROTO_PACKET_ID_INDEX); const uint64_t packetId = Utils::loadMachineEndian< uint64_t >(pkt.unsafeData + ZT_PROTO_PACKET_ID_INDEX);
const uint64_t mac = Utils::loadMachineEndian< uint64_t >(pkt.unsafeData + ZT_PROTO_PACKET_MAC_INDEX); const uint64_t mac = Utils::loadMachineEndian< uint64_t >(pkt.unsafeData + ZT_PROTO_PACKET_MAC_INDEX);
@ -482,7 +481,7 @@ SharedPtr< Peer > VL1::m_HELLO(void *tPtr, const SharedPtr< Path > &path, Buf &p
const uint8_t protoVersion = pkt.lI8< ZT_PROTO_PACKET_PAYLOAD_START >(); const uint8_t protoVersion = pkt.lI8< ZT_PROTO_PACKET_PAYLOAD_START >();
if (unlikely(protoVersion < ZT_PROTO_VERSION_MIN)) { if (unlikely(protoVersion < ZT_PROTO_VERSION_MIN)) {
RR->t->incomingPacketDropped(tPtr, 0x907a9891, packetId, 0, Identity::NIL, path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_PEER_TOO_OLD); RR->t->incomingPacketDropped(cc, 0x907a9891, packetId, 0, Identity::NIL, path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_PEER_TOO_OLD);
return SharedPtr< Peer >(); return SharedPtr< Peer >();
} }
const unsigned int versionMajor = pkt.lI8< ZT_PROTO_PACKET_PAYLOAD_START + 1 >(); const unsigned int versionMajor = pkt.lI8< ZT_PROTO_PACKET_PAYLOAD_START + 1 >();
@ -495,19 +494,19 @@ SharedPtr< Peer > VL1::m_HELLO(void *tPtr, const SharedPtr< Path > &path, Buf &p
// Get identity and verify that it matches the sending address in the packet. // Get identity and verify that it matches the sending address in the packet.
Identity id; Identity id;
if (unlikely(pkt.rO(ii, id) < 0)) { if (unlikely(pkt.rO(ii, id) < 0)) {
RR->t->incomingPacketDropped(tPtr, 0x707a9810, packetId, 0, Identity::NIL, path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); RR->t->incomingPacketDropped(cc, 0x707a9810, packetId, 0, Identity::NIL, path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT);
return SharedPtr< Peer >(); return SharedPtr< Peer >();
} }
if (unlikely(id.address() != Address(pkt.unsafeData + ZT_PROTO_PACKET_SOURCE_INDEX))) { if (unlikely(id.address() != Address(pkt.unsafeData + ZT_PROTO_PACKET_SOURCE_INDEX))) {
RR->t->incomingPacketDropped(tPtr, 0x707a9010, packetId, 0, Identity::NIL, path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); RR->t->incomingPacketDropped(cc, 0x707a9010, packetId, 0, Identity::NIL, path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
return SharedPtr< Peer >(); return SharedPtr< Peer >();
} }
// Get the peer that matches this identity, or learn a new one if we don't know it. // Get the peer that matches this identity, or learn a new one if we don't know it.
SharedPtr< Peer > peer(RR->topology->peer(tPtr, id.address(), true)); SharedPtr< Peer > peer(RR->topology->peer(cc, id.address(), true));
if (peer) { if (peer) {
if (unlikely(peer->identity() != id)) { if (unlikely(peer->identity() != id)) {
RR->t->incomingPacketDropped(tPtr, 0x707a9891, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); RR->t->incomingPacketDropped(cc, 0x707a9891, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
return SharedPtr< Peer >(); return SharedPtr< Peer >();
} }
if (unlikely(peer->deduplicateIncomingPacket(packetId))) { if (unlikely(peer->deduplicateIncomingPacket(packetId))) {
@ -516,15 +515,15 @@ SharedPtr< Peer > VL1::m_HELLO(void *tPtr, const SharedPtr< Path > &path, Buf &p
} }
} else { } else {
if (unlikely(!id.locallyValidate())) { if (unlikely(!id.locallyValidate())) {
RR->t->incomingPacketDropped(tPtr, 0x707a9892, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); RR->t->incomingPacketDropped(cc, 0x707a9892, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT);
return SharedPtr< Peer >(); return SharedPtr< Peer >();
} }
peer.set(new Peer(RR)); peer.set(new Peer(RR));
if (unlikely(!peer->init(id))) { if (unlikely(!peer->init(cc, id))) {
RR->t->incomingPacketDropped(tPtr, 0x707a9893, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_UNSPECIFIED); RR->t->incomingPacketDropped(cc, 0x707a9893, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_UNSPECIFIED);
return SharedPtr< Peer >(); return SharedPtr< Peer >();
} }
peer = RR->topology->add(tPtr, peer); peer = RR->topology->add(cc, peer);
} }
// ------------------------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------------------------
@ -537,7 +536,7 @@ SharedPtr< Peer > VL1::m_HELLO(void *tPtr, const SharedPtr< Path > &path, Buf &p
// field is ignored, and eventually it'll be undefined. // field is ignored, and eventually it'll be undefined.
uint8_t hmac[ZT_HMACSHA384_LEN]; uint8_t hmac[ZT_HMACSHA384_LEN];
if (unlikely(packetSize < ZT_HMACSHA384_LEN)) { if (unlikely(packetSize < ZT_HMACSHA384_LEN)) {
RR->t->incomingPacketDropped(tPtr, 0xab9c9891, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); RR->t->incomingPacketDropped(cc, 0xab9c9891, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
return SharedPtr< Peer >(); return SharedPtr< Peer >();
} }
packetSize -= ZT_HMACSHA384_LEN; packetSize -= ZT_HMACSHA384_LEN;
@ -545,7 +544,7 @@ SharedPtr< Peer > VL1::m_HELLO(void *tPtr, const SharedPtr< Path > &path, Buf &p
Utils::storeMachineEndian< uint64_t >(pkt.unsafeData + ZT_PROTO_PACKET_MAC_INDEX, 0); // set MAC field to 0 Utils::storeMachineEndian< uint64_t >(pkt.unsafeData + ZT_PROTO_PACKET_MAC_INDEX, 0); // set MAC field to 0
HMACSHA384(peer->identityHelloHmacKey(), pkt.unsafeData, packetSize, hmac); HMACSHA384(peer->identityHelloHmacKey(), pkt.unsafeData, packetSize, hmac);
if (unlikely(!Utils::secureEq(hmac, pkt.unsafeData + packetSize, ZT_HMACSHA384_LEN))) { if (unlikely(!Utils::secureEq(hmac, pkt.unsafeData + packetSize, ZT_HMACSHA384_LEN))) {
RR->t->incomingPacketDropped(tPtr, 0x707a9891, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); RR->t->incomingPacketDropped(cc, 0x707a9891, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
return SharedPtr< Peer >(); return SharedPtr< Peer >();
} }
} else { } else {
@ -560,11 +559,11 @@ SharedPtr< Peer > VL1::m_HELLO(void *tPtr, const SharedPtr< Path > &path, Buf &p
uint64_t polyMac[2]; uint64_t polyMac[2];
poly1305.finish(polyMac); poly1305.finish(polyMac);
if (unlikely(mac != polyMac[0])) { if (unlikely(mac != polyMac[0])) {
RR->t->incomingPacketDropped(tPtr, 0x11bfff82, packetId, 0, id, path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); RR->t->incomingPacketDropped(cc, 0x11bfff82, packetId, 0, id, path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
return SharedPtr< Peer >(); return SharedPtr< Peer >();
} }
} else { } else {
RR->t->incomingPacketDropped(tPtr, 0x11bfff81, packetId, 0, id, path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); RR->t->incomingPacketDropped(cc, 0x11bfff81, packetId, 0, id, path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
return SharedPtr< Peer >(); return SharedPtr< Peer >();
} }
} }
@ -575,7 +574,7 @@ SharedPtr< Peer > VL1::m_HELLO(void *tPtr, const SharedPtr< Path > &path, Buf &p
InetAddress sentTo; InetAddress sentTo;
if (unlikely(pkt.rO(ii, sentTo) < 0)) { if (unlikely(pkt.rO(ii, sentTo) < 0)) {
RR->t->incomingPacketDropped(tPtr, 0x707a9811, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); RR->t->incomingPacketDropped(cc, 0x707a9811, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT);
return SharedPtr< Peer >(); return SharedPtr< Peer >();
} }
@ -595,12 +594,12 @@ SharedPtr< Peer > VL1::m_HELLO(void *tPtr, const SharedPtr< Path > &path, Buf &p
ii += 2; // skip reserved field ii += 2; // skip reserved field
const unsigned int dictSize = pkt.rI16(ii); const unsigned int dictSize = pkt.rI16(ii);
if (unlikely((ii + dictSize) > packetSize)) { if (unlikely((ii + dictSize) > packetSize)) {
RR->t->incomingPacketDropped(tPtr, 0x707a9815, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); RR->t->incomingPacketDropped(cc, 0x707a9815, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT);
return peer; return peer;
} }
Dictionary md; Dictionary md;
if (!md.decode(pkt.unsafeData + ii, dictSize)) { if (!md.decode(pkt.unsafeData + ii, dictSize)) {
RR->t->incomingPacketDropped(tPtr, 0x707a9816, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); RR->t->incomingPacketDropped(cc, 0x707a9816, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT);
return peer; return peer;
} }
@ -635,11 +634,11 @@ SharedPtr< Peer > VL1::m_HELLO(void *tPtr, const SharedPtr< Path > &path, Buf &p
} }
peer->setRemoteVersion(protoVersion, versionMajor, versionMinor, versionRev); peer->setRemoteVersion(protoVersion, versionMajor, versionMinor, versionRev);
peer->send(tPtr, RR->node->now(), pkt.unsafeData, ii, path); peer->send(cc, pkt.unsafeData, ii, path);
return peer; return peer;
} }
bool VL1::m_ERROR(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb) bool VL1::m_ERROR(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb)
{ {
#if 0 #if 0
if (packetSize < (int)sizeof(Protocol::ERROR::Header)) { if (packetSize < (int)sizeof(Protocol::ERROR::Header)) {
@ -686,20 +685,19 @@ bool VL1::m_ERROR(void *tPtr, const uint64_t packetId, const unsigned int auth,
#endif #endif
} }
bool VL1::m_OK(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb) bool VL1::m_OK(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb)
{ {
int ii = ZT_PROTO_PACKET_PAYLOAD_START + 13; int ii = ZT_PROTO_PACKET_PAYLOAD_START + 13;
inReVerb = (Protocol::Verb)pkt.rI8(ii); inReVerb = (Protocol::Verb)pkt.rI8(ii);
const uint64_t inRePacketId = pkt.rI64(ii); const uint64_t inRePacketId = pkt.rI64(ii);
if (unlikely(Buf::readOverflow(ii, packetSize))) { if (unlikely(Buf::readOverflow(ii, packetSize))) {
RR->t->incomingPacketDropped(tPtr, 0x4c1f1ff7, packetId, 0, identityFromPeerPtr(peer), path->address(), 0, Protocol::VERB_OK, ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET); RR->t->incomingPacketDropped(cc, 0x4c1f1ff7, packetId, 0, identityFromPeerPtr(peer), path->address(), 0, Protocol::VERB_OK, ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET);
return false; return false;
} }
const int64_t now = RR->node->now(); if (unlikely(!RR->expect->expecting(inRePacketId, cc.ticks))) {
if (unlikely(!RR->expect->expecting(inRePacketId, now))) { RR->t->incomingPacketDropped(cc, 0x4c1f1ff8, packetId, 0, identityFromPeerPtr(peer), path->address(), 0, Protocol::VERB_OK, ZT_TRACE_PACKET_DROP_REASON_REPLY_NOT_EXPECTED);
RR->t->incomingPacketDropped(tPtr, 0x4c1f1ff8, packetId, 0, identityFromPeerPtr(peer), path->address(), 0, Protocol::VERB_OK, ZT_TRACE_PACKET_DROP_REASON_REPLY_NOT_EXPECTED);
return false; return false;
} }
@ -724,7 +722,7 @@ bool VL1::m_OK(void *tPtr, const uint64_t packetId, const unsigned int auth, con
return true; return true;
} }
bool VL1::m_WHOIS(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize) bool VL1::m_WHOIS(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
{ {
#if 0 #if 0
if (packetSize < (int)sizeof(Protocol::OK::Header)) { if (packetSize < (int)sizeof(Protocol::OK::Header)) {
@ -778,7 +776,7 @@ bool VL1::m_WHOIS(void *tPtr, const uint64_t packetId, const unsigned int auth,
#endif #endif
} }
bool VL1::m_RENDEZVOUS(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize) bool VL1::m_RENDEZVOUS(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
{ {
#if 0 #if 0
if (RR->topology->isRoot(peer->identity())) { if (RR->topology->isRoot(peer->identity())) {
@ -826,7 +824,7 @@ bool VL1::m_RENDEZVOUS(void *tPtr, const uint64_t packetId, const unsigned int a
#endif #endif
} }
bool VL1::m_ECHO(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize) bool VL1::m_ECHO(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
{ {
#if 0 #if 0
const uint64_t packetId = Protocol::packetId(pkt,packetSize); const uint64_t packetId = Protocol::packetId(pkt,packetSize);
@ -864,7 +862,7 @@ bool VL1::m_ECHO(void *tPtr, const uint64_t packetId, const unsigned int auth, c
#endif #endif
} }
bool VL1::m_PUSH_DIRECT_PATHS(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize) bool VL1::m_PUSH_DIRECT_PATHS(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
{ {
#if 0 #if 0
if (packetSize < (int)sizeof(Protocol::PUSH_DIRECT_PATHS)) { if (packetSize < (int)sizeof(Protocol::PUSH_DIRECT_PATHS)) {
@ -955,13 +953,13 @@ bool VL1::m_PUSH_DIRECT_PATHS(void *tPtr, const uint64_t packetId, const unsigne
#endif #endif
} }
bool VL1::m_USER_MESSAGE(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize) bool VL1::m_USER_MESSAGE(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
{ {
// TODO // TODO
return true; return true;
} }
bool VL1::m_ENCAP(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize) bool VL1::m_ENCAP(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
{ {
// TODO: not implemented yet // TODO: not implemented yet
return true; return true;

View file

@ -22,6 +22,7 @@
#include "Mutex.hpp" #include "Mutex.hpp"
#include "FCV.hpp" #include "FCV.hpp"
#include "Containers.hpp" #include "Containers.hpp"
#include "CallContext.hpp"
#define ZT_VL1_MAX_WHOIS_WAITING_PACKETS 32 #define ZT_VL1_MAX_WHOIS_WAITING_PACKETS 32
@ -56,38 +57,37 @@ public:
* contents should not be used after this call. Make a copy if the * contents should not be used after this call. Make a copy if the
* data might still be needed. * data might still be needed.
* *
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param localSocket Local I/O socket as supplied by external code * @param localSocket Local I/O socket as supplied by external code
* @param fromAddr Internet IP address of origin * @param fromAddr Internet IP address of origin
* @param data Packet data * @param data Packet data
* @param len Packet length * @param len Packet length
*/ */
void onRemotePacket(void *tPtr, int64_t localSocket, const InetAddress &fromAddr, SharedPtr< Buf > &data, unsigned int len) noexcept; void onRemotePacket(CallContext &cc, int64_t localSocket, const InetAddress &fromAddr, SharedPtr< Buf > &data, unsigned int len) noexcept;
private: private:
const RuntimeEnvironment *RR; const RuntimeEnvironment *RR;
void m_relay(void *tPtr, const SharedPtr< Path > &path, Address destination, SharedPtr< Buf > &pkt, int pktSize); void m_relay(CallContext &cc, const SharedPtr< Path > &path, Address destination, SharedPtr< Buf > &pkt, int pktSize);
void m_sendPendingWhois(void *tPtr, int64_t now); void m_sendPendingWhois(CallContext &cc);
SharedPtr< Peer > m_HELLO(void *tPtr, const SharedPtr< Path > &path, Buf &pkt, int packetSize); SharedPtr< Peer > m_HELLO(CallContext &cc, const SharedPtr< Path > &path, Buf &pkt, int packetSize);
bool m_ERROR(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb); bool m_ERROR(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb);
bool m_OK(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb); bool m_OK(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb);
bool m_WHOIS(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize); bool m_WHOIS(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
bool m_RENDEZVOUS(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize); bool m_RENDEZVOUS(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
bool m_ECHO(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize); bool m_ECHO(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
bool m_PUSH_DIRECT_PATHS(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize); bool m_PUSH_DIRECT_PATHS(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
bool m_USER_MESSAGE(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize); bool m_USER_MESSAGE(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
bool m_ENCAP(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize); bool m_ENCAP(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
// Defragmentation engine for handling inbound packets with more than one fragment. // Defragmentation engine for handling inbound packets with more than one fragment.
Defragmenter< ZT_MAX_PACKET_FRAGMENTS > m_inputPacketAssembler; Defragmenter< ZT_MAX_PACKET_FRAGMENTS > m_inputPacketAssembler;

View file

@ -26,43 +26,43 @@ VL2::VL2(const RuntimeEnvironment *renv)
{ {
} }
void VL2::onLocalEthernet(void *const tPtr, const SharedPtr< Network > &network, const MAC &from, const MAC &to, const unsigned int etherType, unsigned int vlanId, SharedPtr< Buf > &data, unsigned int len) void VL2::onLocalEthernet(CallContext &cc, const SharedPtr< Network > &network, const MAC &from, const MAC &to, const unsigned int etherType, unsigned int vlanId, SharedPtr< Buf > &data, unsigned int len)
{ {
} }
bool VL2::m_FRAME(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) bool VL2::m_FRAME(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
{ {
} }
bool VL2::m_EXT_FRAME(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) bool VL2::m_EXT_FRAME(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
{ {
} }
bool VL2::m_MULTICAST_LIKE(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) bool VL2::m_MULTICAST_LIKE(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
{ {
} }
bool VL2::m_NETWORK_CREDENTIALS(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) bool VL2::m_NETWORK_CREDENTIALS(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
{ {
} }
bool VL2::m_NETWORK_CONFIG_REQUEST(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) bool VL2::m_NETWORK_CONFIG_REQUEST(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
{ {
} }
bool VL2::m_NETWORK_CONFIG(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) bool VL2::m_NETWORK_CONFIG(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
{ {
} }
bool VL2::m_MULTICAST_GATHER(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) bool VL2::m_MULTICAST_GATHER(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
{ {
} }
bool VL2::m_MULTICAST_FRAME_deprecated(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) bool VL2::m_MULTICAST_FRAME_deprecated(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
{ {
} }
bool VL2::m_MULTICAST(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) bool VL2::m_MULTICAST(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
{ {
} }

View file

@ -21,6 +21,7 @@
#include "Mutex.hpp" #include "Mutex.hpp"
#include "FCV.hpp" #include "FCV.hpp"
#include "Containers.hpp" #include "Containers.hpp"
#include "CallContext.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -46,7 +47,6 @@ public:
/** /**
* Called when a packet comes from a local Ethernet tap * Called when a packet comes from a local Ethernet tap
* *
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param network Which network's TAP did this packet come from? * @param network Which network's TAP did this packet come from?
* @param from Originating MAC address * @param from Originating MAC address
* @param to Destination MAC address * @param to Destination MAC address
@ -55,26 +55,26 @@ public:
* @param data Ethernet payload * @param data Ethernet payload
* @param len Frame length * @param len Frame length
*/ */
void onLocalEthernet(void *tPtr, const SharedPtr< Network > &network, const MAC &from, const MAC &to, unsigned int etherType, unsigned int vlanId, SharedPtr< Buf > &data, unsigned int len); void onLocalEthernet(CallContext &cc, const SharedPtr< Network > &network, const MAC &from, const MAC &to, unsigned int etherType, unsigned int vlanId, SharedPtr< Buf > &data, unsigned int len);
protected: protected:
bool m_FRAME(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); bool m_FRAME(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
bool m_EXT_FRAME(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); bool m_EXT_FRAME(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
bool m_MULTICAST_LIKE(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); bool m_MULTICAST_LIKE(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
bool m_NETWORK_CREDENTIALS(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); bool m_NETWORK_CREDENTIALS(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
bool m_NETWORK_CONFIG_REQUEST(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); bool m_NETWORK_CONFIG_REQUEST(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
bool m_NETWORK_CONFIG(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); bool m_NETWORK_CONFIG(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
bool m_MULTICAST_GATHER(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); bool m_MULTICAST_GATHER(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
bool m_MULTICAST_FRAME_deprecated(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); bool m_MULTICAST_FRAME_deprecated(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
bool m_MULTICAST(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); bool m_MULTICAST(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
private: private:
}; };

View file

@ -1750,18 +1750,10 @@ enum ZT_StateObjectType
* List of certificates, their local trust, and locally added roots * List of certificates, their local trust, and locally added roots
* *
* Object ID: (none) * Object ID: (none)
* Canonical path: <HOME>/trust * Canonical path: <HOME>/truststore
* Persistence: required if root settings should persist * Persistence: required if root settings should persist
*/ */
ZT_STATE_OBJECT_TRUST_STORE = 7, ZT_STATE_OBJECT_TRUST_STORE = 7
/**
* Certificate
*
* Object ID: [6]serial (384-bit serial packed into 6 uint64_t's)
* Canonical path: <HOME>/certs.d/<serial> (96-digit hex serial)
*/
ZT_STATE_OBJECT_CERT = 8
}; };
/** /**
@ -2028,7 +2020,7 @@ struct ZT_Node_Callbacks
* *
* @return Pointer to I/O buffer * @return Pointer to I/O buffer
*/ */
ZT_SDK_API void *ZT_getBuffer(); ZT_SDK_API [[maybe_unused]] void *ZT_getBuffer();
/** /**
* Free an unused buffer obtained via getBuffer * Free an unused buffer obtained via getBuffer
@ -2059,37 +2051,32 @@ ZT_SDK_API void ZT_freeQueryResult(const void *qr);
* *
* @param node Result: pointer is set to new node instance on success * @param node Result: pointer is set to new node instance on success
* @param uptr User pointer to pass to functions/callbacks * @param uptr User pointer to pass to functions/callbacks
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
* @param callbacks Callback function configuration * @param callbacks Callback function configuration
* @param now Current clock in milliseconds
* @return OK (0) or error code if a fatal error condition has occurred * @return OK (0) or error code if a fatal error condition has occurred
*/ */
ZT_SDK_API enum ZT_ResultCode ZT_Node_new( ZT_SDK_API enum ZT_ResultCode ZT_Node_new(
ZT_Node **node, ZT_Node **node,
void *uptr, int64_t clock,
int64_t ticks,
void *tptr, void *tptr,
const struct ZT_Node_Callbacks *callbacks, void *uptr,
int64_t now); const struct ZT_Node_Callbacks *callbacks);
/** /**
* Delete a node and free all resources it consumes * Delete a node and free all resources it consumes
* *
* If you are using multiple threads, all other threads must be shut down * If you are using multiple threads, all other threads must be shut down
* first. This can crash if processXXX() methods are in progress. * first. This can crash if processXXX() methods are in progress.
*
* @param node Node to delete
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
*/ */
ZT_SDK_API void ZT_Node_delete( ZT_SDK_API void ZT_Node_delete(
ZT_Node *node, ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr); void *tptr);
/** /**
* Process a packet received from the physical wire * Process a packet received from the physical wire
* *
* @param node Node instance
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
* @param now Current clock in milliseconds
* @param localSocket Local socket (you can use 0 if only one local socket is bound and ignore this) * @param localSocket Local socket (you can use 0 if only one local socket is bound and ignore this)
* @param remoteAddress Origin of packet * @param remoteAddress Origin of packet
* @param packetData Packet data * @param packetData Packet data
@ -2100,8 +2087,9 @@ ZT_SDK_API void ZT_Node_delete(
*/ */
ZT_SDK_API enum ZT_ResultCode ZT_Node_processWirePacket( ZT_SDK_API enum ZT_ResultCode ZT_Node_processWirePacket(
ZT_Node *node, ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr, void *tptr,
int64_t now,
int64_t localSocket, int64_t localSocket,
const ZT_InetAddress *remoteAddress, const ZT_InetAddress *remoteAddress,
const void *packetData, const void *packetData,
@ -2112,9 +2100,6 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_processWirePacket(
/** /**
* Process a frame from a virtual network port (tap) * Process a frame from a virtual network port (tap)
* *
* @param node Node instance
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
* @param now Current clock in milliseconds
* @param nwid ZeroTier 64-bit virtual network ID * @param nwid ZeroTier 64-bit virtual network ID
* @param sourceMac Source MAC address (least significant 48 bits) * @param sourceMac Source MAC address (least significant 48 bits)
* @param destMac Destination MAC address (least significant 48 bits) * @param destMac Destination MAC address (least significant 48 bits)
@ -2128,8 +2113,9 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_processWirePacket(
*/ */
ZT_SDK_API enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame( ZT_SDK_API enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
ZT_Node *node, ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr, void *tptr,
int64_t now,
uint64_t nwid, uint64_t nwid,
uint64_t sourceMac, uint64_t sourceMac,
uint64_t destMac, uint64_t destMac,
@ -2143,16 +2129,15 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
/** /**
* Perform periodic background operations * Perform periodic background operations
* *
* @param node Node instance
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
* @param now Current clock in milliseconds * @param now Current clock in milliseconds
* @param nextBackgroundTaskDeadline Value/result: set to deadline for next call to processBackgroundTasks() * @param nextBackgroundTaskDeadline Value/result: set to deadline for next call to processBackgroundTasks()
* @return OK (0) or error code if a fatal error condition has occurred * @return OK (0) or error code if a fatal error condition has occurred
*/ */
ZT_SDK_API enum ZT_ResultCode ZT_Node_processBackgroundTasks( ZT_SDK_API enum ZT_ResultCode ZT_Node_processBackgroundTasks(
ZT_Node *node, ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr, void *tptr,
int64_t now,
volatile int64_t *nextBackgroundTaskDeadline); volatile int64_t *nextBackgroundTaskDeadline);
/** /**
@ -2164,19 +2149,18 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_processBackgroundTasks(
* If we are already a member of the network, nothing is done and OK is * If we are already a member of the network, nothing is done and OK is
* returned. * returned.
* *
* @param node Node instance
* @param nwid 64-bit ZeroTier network ID * @param nwid 64-bit ZeroTier network ID
* @param fingerprintHash If non-NULL this is the full fingerprint of the controller * @param fingerprintHash If non-NULL this is the full fingerprint of the controller
* @param uptr An arbitrary pointer to associate with this network (default: NULL)
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
* @return OK (0) or error code if a fatal error condition has occurred * @return OK (0) or error code if a fatal error condition has occurred
*/ */
ZT_SDK_API enum ZT_ResultCode ZT_Node_join( ZT_SDK_API enum ZT_ResultCode ZT_Node_join(
ZT_Node *node, ZT_Node *node,
uint64_t nwid, int64_t clock,
const ZT_Fingerprint *controllerFingerprint, int64_t ticks,
void *tptr,
void *uptr, void *uptr,
void *tptr); uint64_t nwid,
const ZT_Fingerprint *controllerFingerprint);
/** /**
* Leave a network * Leave a network
@ -2188,17 +2172,15 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_join(
* The uptr parameter is optional and is NULL by default. If it is not NULL, * The uptr parameter is optional and is NULL by default. If it is not NULL,
* the pointer it points to is set to this network's uptr on success. * the pointer it points to is set to this network's uptr on success.
* *
* @param node Node instance
* @param nwid 64-bit network ID
* @param uptr Target pointer is set to uptr (if not NULL)
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
* @return OK (0) or error code if a fatal error condition has occurred * @return OK (0) or error code if a fatal error condition has occurred
*/ */
ZT_SDK_API enum ZT_ResultCode ZT_Node_leave( ZT_SDK_API enum ZT_ResultCode ZT_Node_leave(
ZT_Node *node, ZT_Node *node,
uint64_t nwid, int64_t clock,
int64_t ticks,
void *tptr,
void **uptr, void **uptr,
void *tptr); uint64_t nwid);
/** /**
* Subscribe to an Ethernet multicast group * Subscribe to an Ethernet multicast group
@ -2219,8 +2201,6 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_leave(
* *
* This does not generate an update call to networkConfigCallback(). * This does not generate an update call to networkConfigCallback().
* *
* @param node Node instance
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
* @param nwid 64-bit network ID * @param nwid 64-bit network ID
* @param multicastGroup Ethernet multicast or broadcast MAC (least significant 48 bits) * @param multicastGroup Ethernet multicast or broadcast MAC (least significant 48 bits)
* @param multicastAdi Multicast ADI (least significant 32 bits only, use 0 if not needed) * @param multicastAdi Multicast ADI (least significant 32 bits only, use 0 if not needed)
@ -2228,6 +2208,8 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_leave(
*/ */
ZT_SDK_API enum ZT_ResultCode ZT_Node_multicastSubscribe( ZT_SDK_API enum ZT_ResultCode ZT_Node_multicastSubscribe(
ZT_Node *node, ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr, void *tptr,
uint64_t nwid, uint64_t nwid,
uint64_t multicastGroup, uint64_t multicastGroup,
@ -2241,7 +2223,6 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_multicastSubscribe(
* *
* This does not generate an update call to networkConfigCallback(). * This does not generate an update call to networkConfigCallback().
* *
* @param node Node instance
* @param nwid 64-bit network ID * @param nwid 64-bit network ID
* @param multicastGroup Ethernet multicast or broadcast MAC (least significant 48 bits) * @param multicastGroup Ethernet multicast or broadcast MAC (least significant 48 bits)
* @param multicastAdi Multicast ADI (least significant 32 bits only, use 0 if not needed) * @param multicastAdi Multicast ADI (least significant 32 bits only, use 0 if not needed)
@ -2249,6 +2230,9 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_multicastSubscribe(
*/ */
ZT_SDK_API enum ZT_ResultCode ZT_Node_multicastUnsubscribe( ZT_SDK_API enum ZT_ResultCode ZT_Node_multicastUnsubscribe(
ZT_Node *node, ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr,
uint64_t nwid, uint64_t nwid,
uint64_t multicastGroup, uint64_t multicastGroup,
unsigned long multicastAdi); unsigned long multicastAdi);
@ -2256,10 +2240,10 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_multicastUnsubscribe(
/** /**
* Get this node's 40-bit ZeroTier address * Get this node's 40-bit ZeroTier address
* *
* @param node Node instance
* @return ZeroTier address (least significant 40 bits of 64-bit int) * @return ZeroTier address (least significant 40 bits of 64-bit int)
*/ */
ZT_SDK_API uint64_t ZT_Node_address(ZT_Node *node); ZT_SDK_API uint64_t ZT_Node_address(
ZT_Node *node);
/** /**
* Get this node's identity * Get this node's identity
@ -2267,19 +2251,21 @@ ZT_SDK_API uint64_t ZT_Node_address(ZT_Node *node);
* The identity pointer returned by this function need not and should not be * The identity pointer returned by this function need not and should not be
* freed with ZT_Identity_delete(). It's valid until the node is deleted. * freed with ZT_Identity_delete(). It's valid until the node is deleted.
* *
* @param node Node instance
* @return Identity * @return Identity
*/ */
ZT_SDK_API const ZT_Identity *ZT_Node_identity(ZT_Node *node); ZT_SDK_API const ZT_Identity *ZT_Node_identity(
ZT_Node *node);
/** /**
* Get the status of this node * Get the status of this node
* *
* @param node Node instance
* @param status Buffer to fill with current node status * @param status Buffer to fill with current node status
*/ */
ZT_SDK_API void ZT_Node_status( ZT_SDK_API void ZT_Node_status(
ZT_Node *node, ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr,
ZT_NodeStatus *status); ZT_NodeStatus *status);
/** /**
@ -2288,10 +2274,13 @@ ZT_SDK_API void ZT_Node_status(
* The pointer returned here must be freed with freeQueryResult() * The pointer returned here must be freed with freeQueryResult()
* when you are done with it. * when you are done with it.
* *
* @param node Node instance
* @return List of known peers or NULL on failure * @return List of known peers or NULL on failure
*/ */
ZT_SDK_API ZT_PeerList *ZT_Node_peers(ZT_Node *node); ZT_SDK_API ZT_PeerList *ZT_Node_peers(
ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr);
/** /**
* Get the status of a virtual network * Get the status of a virtual network
@ -2299,12 +2288,14 @@ ZT_SDK_API ZT_PeerList *ZT_Node_peers(ZT_Node *node);
* The pointer returned here must be freed with freeQueryResult() * The pointer returned here must be freed with freeQueryResult()
* when you are done with it. * when you are done with it.
* *
* @param node Node instance
* @param nwid 64-bit network ID * @param nwid 64-bit network ID
* @return Network configuration or NULL if we are not a member of this network * @return Network configuration or NULL if we are not a member of this network
*/ */
ZT_SDK_API ZT_VirtualNetworkConfig *ZT_Node_networkConfig( ZT_SDK_API ZT_VirtualNetworkConfig *ZT_Node_networkConfig(
ZT_Node *node, ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr,
uint64_t nwid); uint64_t nwid);
/** /**
@ -2313,7 +2304,8 @@ ZT_SDK_API ZT_VirtualNetworkConfig *ZT_Node_networkConfig(
* @param node Node instance * @param node Node instance
* @return List of networks or NULL on failure * @return List of networks or NULL on failure
*/ */
ZT_SDK_API ZT_VirtualNetworkList *ZT_Node_networks(ZT_Node *node); ZT_SDK_API ZT_VirtualNetworkList *ZT_Node_networks(
ZT_Node *node);
/** /**
* Set the network-associated user-defined pointer for a given network * Set the network-associated user-defined pointer for a given network
@ -2338,61 +2330,18 @@ ZT_SDK_API void ZT_Node_setNetworkUserPtr(
*/ */
ZT_SDK_API void ZT_Node_setInterfaceAddresses( ZT_SDK_API void ZT_Node_setInterfaceAddresses(
ZT_Node *node, ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr,
const ZT_InterfaceAddress *addrs, const ZT_InterfaceAddress *addrs,
unsigned int addrCount); unsigned int addrCount);
/**
* Add a peer directly by supplying its identity
*
* This does not authorize the peer on a network (only the network's
* controller can do that) or otherwise give it special privileges. It
* also doesn't guarantee it will be contacted. It just adds it to the
* internal peer data set if it is not already present.
*
* @param node Node instance
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
* @param id Identity of peer to add
* @return OK (0) or error code
*/
ZT_SDK_API enum ZT_ResultCode ZT_Node_addPeer(
ZT_Node *node,
void *tptr,
const ZT_Identity *id);
/**
* Attempt to contact a peer at an explicit endpoint address.
*
* If the fingerprint structure's hash is all zeroes, the peer is
* looked up only by address.
*
* This can only fail if the peer was not found.
*
* Note that this can immediately (before this returns) result in
* calls to the send packet functions supplied to the core.
*
* @param node Node instance
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
* @param fp Fingerprint (or only address)
* @param endpoint Endpoint
* @param retries If greater than zero, try this many times
* @return Boolean: non-zero on success, zero if peer was not found
*/
ZT_SDK_API int ZT_Node_tryPeer(
ZT_Node *node,
void *tptr,
const ZT_Fingerprint *fp,
const ZT_Endpoint *endpoint,
int retries);
/** /**
* Add a certificate to this node's certificate store * Add a certificate to this node's certificate store
* *
* This supports adding of certificates as expanded ZT_Certificate structures * This supports adding of certificates as expanded ZT_Certificate structures
* or as raw data. If 'cert' is NULL then certData/certSize must be set. * or as raw data. If 'cert' is NULL then certData/certSize must be set.
* *
* @param node Node instance
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
* @param now Current time
* @param localTrust Local trust flags (ORed together) * @param localTrust Local trust flags (ORed together)
* @param cert Certificate object, or set to NULL if certData and certSize are to be used * @param cert Certificate object, or set to NULL if certData and certSize are to be used
* @param certData Certificate binary data if 'cert' is NULL, NULL otherwise * @param certData Certificate binary data if 'cert' is NULL, NULL otherwise
@ -2401,8 +2350,9 @@ ZT_SDK_API int ZT_Node_tryPeer(
*/ */
ZT_SDK_API enum ZT_CertificateError ZT_Node_addCertificate( ZT_SDK_API enum ZT_CertificateError ZT_Node_addCertificate(
ZT_Node *node, ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr, void *tptr,
int64_t now,
unsigned int localTrust, unsigned int localTrust,
const ZT_Certificate *cert, const ZT_Certificate *cert,
const void *certData, const void *certData,
@ -2421,6 +2371,8 @@ ZT_SDK_API enum ZT_CertificateError ZT_Node_addCertificate(
*/ */
ZT_SDK_API enum ZT_ResultCode ZT_Node_deleteCertificate( ZT_SDK_API enum ZT_ResultCode ZT_Node_deleteCertificate(
ZT_Node *node, ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr, void *tptr,
const void *serialNo); const void *serialNo);
@ -2430,7 +2382,11 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_deleteCertificate(
* @param node Node instance * @param node Node instance
* @return List of certificates or NULL on error * @return List of certificates or NULL on error
*/ */
ZT_SDK_API ZT_CertificateList *ZT_Node_listCertificates(ZT_Node *node); ZT_SDK_API ZT_CertificateList *ZT_Node_listCertificates(
ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr);
/** /**
* Send a VERB_USER_MESSAGE to another ZeroTier node * Send a VERB_USER_MESSAGE to another ZeroTier node
@ -2448,6 +2404,8 @@ ZT_SDK_API ZT_CertificateList *ZT_Node_listCertificates(ZT_Node *node);
*/ */
ZT_SDK_API int ZT_Node_sendUserMessage( ZT_SDK_API int ZT_Node_sendUserMessage(
ZT_Node *node, ZT_Node *node,
int64_t clock,
int64_t ticks,
void *tptr, void *tptr,
uint64_t dest, uint64_t dest,
uint64_t typeId, uint64_t typeId,
@ -2665,7 +2623,7 @@ ZT_SDK_API int ZT_Endpoint_fromBytes(
* Note that attributes must be either NULL to use defaults for all or there * Note that attributes must be either NULL to use defaults for all or there
* must be an attributes object for each endpoint. * must be an attributes object for each endpoint.
* *
* @param ts Locator timestamp * @param rev Locator timestamp
* @param endpoints List of endpoints to store in locator * @param endpoints List of endpoints to store in locator
* @param endpointAttributes Array of ZT_EndpointAttributes objects or NULL to use defaults * @param endpointAttributes Array of ZT_EndpointAttributes objects or NULL to use defaults
* @param endpointCount Number of endpoints (maximum: 8) * @param endpointCount Number of endpoints (maximum: 8)
@ -2673,7 +2631,7 @@ ZT_SDK_API int ZT_Endpoint_fromBytes(
* @return Locator or NULL on error (too many endpoints or identity does not have private key) * @return Locator or NULL on error (too many endpoints or identity does not have private key)
*/ */
ZT_SDK_API ZT_Locator *ZT_Locator_create( ZT_SDK_API ZT_Locator *ZT_Locator_create(
int64_t ts, int64_t rev,
const ZT_Endpoint *endpoints, const ZT_Endpoint *endpoints,
const ZT_EndpointAttributes *endpointAttributes, const ZT_EndpointAttributes *endpointAttributes,
unsigned int endpointCount, unsigned int endpointCount,
@ -2735,12 +2693,12 @@ ZT_SDK_API char *ZT_Locator_toString(
ZT_SDK_API const ZT_Fingerprint *ZT_Locator_fingerprint(const ZT_Locator *loc); ZT_SDK_API const ZT_Fingerprint *ZT_Locator_fingerprint(const ZT_Locator *loc);
/** /**
* Get a locator's timestamp * Get a locator's revision
* *
* @param loc Locator to query * @param loc Locator to query
* @return Locator timestamp in milliseconds since epoch * @return Locator revision
*/ */
ZT_SDK_API int64_t ZT_Locator_timestamp(const ZT_Locator *loc); ZT_SDK_API int64_t ZT_Locator_revision(const ZT_Locator *loc);
/** /**
* Get the number of endpoints in this locator * Get the number of endpoints in this locator

View file

@ -27,13 +27,13 @@ pub struct Locator {
impl Locator { impl Locator {
/// Create and sign a new locator. /// Create and sign a new locator.
/// The signer must include its secret key. /// The signer must include its secret key.
pub fn new(signer: &Identity, timestamp: i64, endpoints: &Vec<Endpoint>) -> Result<Locator, ResultCode> { pub fn new(signer: &Identity, revision: i64, endpoints: &Vec<Endpoint>) -> Result<Locator, ResultCode> {
let mut capi_endpoints: Vec<ztcore::ZT_Endpoint> = Vec::new(); let mut capi_endpoints: Vec<ztcore::ZT_Endpoint> = Vec::new();
capi_endpoints.reserve(endpoints.len()); capi_endpoints.reserve(endpoints.len());
for ep in endpoints.iter() { for ep in endpoints.iter() {
capi_endpoints.push(ep.capi); capi_endpoints.push(ep.capi);
} }
let loc = unsafe { ztcore::ZT_Locator_create(timestamp, capi_endpoints.as_ptr(), null(), capi_endpoints.len() as c_uint, signer.capi) }; let loc = unsafe { ztcore::ZT_Locator_create(revision, capi_endpoints.as_ptr(), null(), capi_endpoints.len() as c_uint, signer.capi) };
if loc.is_null() { if loc.is_null() {
Err(ResultCode::ErrorBadParameter) Err(ResultCode::ErrorBadParameter)
} else { } else {
@ -65,9 +65,9 @@ impl Locator {
} }
#[inline(always)] #[inline(always)]
pub fn timestamp(&self) -> i64 { pub fn revision(&self) -> i64 {
unsafe { unsafe {
ztcore::ZT_Locator_timestamp(self.capi) as i64 ztcore::ZT_Locator_revision(self.capi) as i64
} }
} }

View file

@ -48,7 +48,14 @@ pub enum StateObjectType {
Peer = ztcore::ZT_StateObjectType_ZT_STATE_OBJECT_PEER as isize, Peer = ztcore::ZT_StateObjectType_ZT_STATE_OBJECT_PEER as isize,
NetworkConfig = ztcore::ZT_StateObjectType_ZT_STATE_OBJECT_NETWORK_CONFIG as isize, NetworkConfig = ztcore::ZT_StateObjectType_ZT_STATE_OBJECT_NETWORK_CONFIG as isize,
TrustStore = ztcore::ZT_StateObjectType_ZT_STATE_OBJECT_TRUST_STORE as isize, TrustStore = ztcore::ZT_StateObjectType_ZT_STATE_OBJECT_TRUST_STORE as isize,
Certificate = ztcore::ZT_StateObjectType_ZT_STATE_OBJECT_CERT as isize, }
impl StateObjectType {
/// True if this state object should be protected.
#[inline(always)]
pub fn is_secret(&self) -> bool {
*self == StateObjectType::IdentitySecret || *self == StateObjectType::TrustStore
}
} }
/// The status of a ZeroTier node. /// The status of a ZeroTier node.

View file

@ -35,7 +35,6 @@ pub(crate) struct Store {
peers_path: Box<Path>, peers_path: Box<Path>,
controller_path: Box<Path>, controller_path: Box<Path>,
networks_path: Box<Path>, networks_path: Box<Path>,
certs_path: Box<Path>,
auth_token_path: Mutex<Box<Path>>, auth_token_path: Mutex<Box<Path>>,
auth_token: Mutex<String>, auth_token: Mutex<String>,
} }
@ -69,7 +68,6 @@ impl Store {
peers_path: bp.join("peers.d").into_boxed_path(), peers_path: bp.join("peers.d").into_boxed_path(),
controller_path: bp.join("controller.d").into_boxed_path(), controller_path: bp.join("controller.d").into_boxed_path(),
networks_path: bp.join("networks.d").into_boxed_path(), networks_path: bp.join("networks.d").into_boxed_path(),
certs_path: bp.join("certs.d").into_boxed_path(),
auth_token_path: Mutex::new(auth_token_path_override.map_or_else(|| { auth_token_path: Mutex::new(auth_token_path_override.map_or_else(|| {
bp.join(AUTHTOKEN_SECRET).into_boxed_path() bp.join(AUTHTOKEN_SECRET).into_boxed_path()
}, |auth_token_path_override| { }, |auth_token_path_override| {
@ -85,32 +83,16 @@ impl Store {
let _ = std::fs::create_dir_all(&s.peers_path); let _ = std::fs::create_dir_all(&s.peers_path);
let _ = std::fs::create_dir_all(&s.controller_path); let _ = std::fs::create_dir_all(&s.controller_path);
let _ = std::fs::create_dir_all(&s.networks_path); let _ = std::fs::create_dir_all(&s.networks_path);
let _ = std::fs::create_dir_all(&s.certs_path);
Ok(s) Ok(s)
} }
fn make_obj_path_internal(&self, obj_type: &StateObjectType, obj_id: &[u64]) -> Option<PathBuf> { fn make_obj_path_internal(&self, obj_type: &StateObjectType, obj_id: &[u64]) -> Option<PathBuf> {
match obj_type { match obj_type {
StateObjectType::IdentityPublic => { StateObjectType::IdentityPublic => Some(self.base_path.join("identity.public")),
Some(self.base_path.join("identity.public")) StateObjectType::IdentitySecret => Some(self.base_path.join("identity.secret")),
}, StateObjectType::TrustStore => Some(self.base_path.join("truststore")),
StateObjectType::IdentitySecret => { StateObjectType::Locator => Some(self.base_path.join("locator")),
Some(self.base_path.join("identity.secret"))
},
StateObjectType::Certificate => {
if obj_id.len() < 6 {
None
} else {
Some(self.certs_path.join(format!("{:0>16x}{:0>16x}{:0>16x}{:0>16x}{:0>16x}{:0>16x}.cert", obj_id[0], obj_id[1], obj_id[2], obj_id[3], obj_id[4], obj_id[5])))
}
},
StateObjectType::TrustStore => {
Some(self.base_path.join("trust"))
},
StateObjectType::Locator => {
Some(self.base_path.join("locator"))
},
StateObjectType::NetworkConfig => { StateObjectType::NetworkConfig => {
if obj_id.len() < 1 { if obj_id.len() < 1 {
None None
@ -306,7 +288,7 @@ impl Store {
let obj_path = obj_path.unwrap(); let obj_path = obj_path.unwrap();
std::fs::OpenOptions::new().write(true).truncate(true).create(true).open(&obj_path)?.write_all(obj_data)?; std::fs::OpenOptions::new().write(true).truncate(true).create(true).open(&obj_path)?.write_all(obj_data)?;
if obj_type.eq(&StateObjectType::IdentitySecret) || obj_type.eq(&StateObjectType::TrustStore) { if obj_type.is_secret() {
lock_down_file(obj_path.to_str().unwrap()); lock_down_file(obj_path.to_str().unwrap());
} }