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,10 +12,7 @@
/****/ /****/
#include "Buf.hpp" #include "Buf.hpp"
#include "Spinlock.hpp"
#ifdef __WINDOWS__
#define sched_yield() Sleep(0)
#endif
namespace ZeroTier { namespace ZeroTier {
@ -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
@ -112,10 +132,14 @@ public:
* *
* @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 { return ZT_CAPABILITY_MARSHAL_SIZE_MAX; }
int marshal(uint8_t data[ZT_CAPABILITY_MARSHAL_SIZE_MAX], bool forSign = false) const 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; int unmarshal(const uint8_t *data, int len) noexcept;
/** /**
@ -141,14 +165,18 @@ public:
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 {
@ -50,7 +52,8 @@ public:
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

@ -43,7 +43,7 @@
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];
@ -52,7 +52,7 @@ static ZT_INLINE Credential::VerifyResult p_credVerify(const RuntimeEnvironment
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;
@ -66,19 +66,26 @@ static ZT_INLINE Credential::VerifyResult p_credVerify(const RuntimeEnvironment
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

@ -136,7 +136,7 @@ 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
*/ */
@ -148,7 +148,7 @@ public:
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

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

@ -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) {
@ -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)
@ -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
@ -145,17 +145,19 @@ 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
@ -163,7 +165,7 @@ private:
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));

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() {}

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,25 +68,46 @@ 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
@ -127,17 +150,25 @@ 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 { return ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX; }
int marshal(uint8_t data[ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX], bool forSign = false) const 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; 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

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
@ -80,7 +87,8 @@ public:
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());
} }